diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 72f78f320c25..1c45664e0e5a 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -597,6 +597,7 @@ int snd_hdac_stream_get_spbmaxfifo(struct hdac_bus *bus, struct hdac_stream *azx_dev); void snd_hdac_stream_drsm_enable(struct hdac_bus *bus, bool enable, int index); +int snd_hdac_stream_wait_drsm(struct hdac_stream *azx_dev); int snd_hdac_stream_set_dpibr(struct hdac_bus *bus, struct hdac_stream *azx_dev, u32 value); int snd_hdac_stream_set_lpib(struct hdac_stream *azx_dev, u32 value); diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c index cf478c3662f9..9810248165a4 100644 --- a/sound/hda/hdac_stream.c +++ b/sound/hda/hdac_stream.c @@ -820,6 +820,28 @@ void snd_hdac_stream_drsm_enable(struct hdac_bus *bus, } EXPORT_SYMBOL_GPL(snd_hdac_stream_drsm_enable); +/* + * snd_hdac_stream_wait_drsm - wait for HW to clear RSM for a stream + * @azx_dev: HD-audio core stream to await RSM for + * + * Returns 0 on success and -ETIMEDOUT upon a timeout. + */ +int snd_hdac_stream_wait_drsm(struct hdac_stream *azx_dev) +{ + struct hdac_bus *bus = azx_dev->bus; + u32 mask, reg; + int ret; + + mask = 1 << azx_dev->index; + + ret = read_poll_timeout(snd_hdac_reg_readl, reg, !(reg & mask), 250, 2000, false, bus, + bus->drsmcap + AZX_REG_DRSM_CTL); + if (ret) + dev_dbg(bus->dev, "polling RSM 0x%08x failed: %d\n", mask, ret); + return ret; +} +EXPORT_SYMBOL_GPL(snd_hdac_stream_wait_drsm); + /** * snd_hdac_stream_set_dpibr - sets the dpibr value of a stream * @bus: HD-audio core bus