[alsa-devel] [PATCH 4/4] ALSA: x86: Enable keep-link feature
Pierre-Louis Bossart
pierre-louis.bossart at linux.intel.com
Mon Feb 13 18:05:37 CET 2017
On 2/13/17 8:39 AM, Takashi Iwai wrote:
> This patch enables the "keep-link" feature experimentally. It's a
> feature where the device keeps the link and sending the silent output
> even after the PCM device is closed. Then the receiver will be
> resumed quickly once when a PCM is opened and a stream is sent again.
>
> The stream link is turned off when the device goes to the auto
> suspend, and it's set to two seconds after the PCM close. This
> timeout value can be changed dynamically in a standard way via sysfs
> like other drivers. For example, to make it 10 seconds, run like:
>
> echo 10000 > /sys/bus/platform/devices/hdmi-lpe-audio/power/autosuspend_delay_ms
Keeping the link active has really a limited impact on power since the
source provides power to the sink and will also drive the display. For
people who rely on HDMI for system sounds/beeps/notifications it'd make
more sense to make that value something like 15-30mn (i.e. aligned with
display screen saver timeout), otherwise for every sound the receiver
will have to spend 1-2 seconds figuring out if the data is PCM or
compressed.
PulseAudio has a 5s timeout on idle, 2s seems really low to me.
>
> This new keep-link feature itself is controlled via a new module
> option, keep_link. You can turn it on/off, again, via sysfs like:
>
> echo 0 > /sys/module/snd_hdmi_lpe_audio/parameters/keep_link
>
> As default, the feature is turned on.
>
> Signed-off-by: Takashi Iwai <tiwai at suse.de>
> ---
> sound/x86/intel_hdmi_audio.c | 38 ++++++++++++++++++++++++++++++++++++++
> 1 file changed, 38 insertions(+)
>
> diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c
> index 95b07a260d54..506cff306b5c 100644
> --- a/sound/x86/intel_hdmi_audio.c
> +++ b/sound/x86/intel_hdmi_audio.c
> @@ -52,6 +52,10 @@ module_param_named(id, hdmi_card_id, charp, 0444);
> MODULE_PARM_DESC(id,
> "ID string for INTEL Intel HDMI Audio controller.");
>
> +static bool keep_link = true;
> +module_param(keep_link, bool, 0644);
> +MODULE_PARM_DESC(keep_link, "Keep link on after the stream is closed.");
> +
> /*
> * ELD SA bits in the CEA Speaker Allocation data block
> */
> @@ -217,8 +221,12 @@ static void had_write_register(struct snd_intelhad *ctx, u32 reg, u32 val)
> static void had_enable_audio(struct snd_intelhad *intelhaddata,
> bool enable)
> {
> + if (intelhaddata->aud_config.regx.aud_en == enable)
> + return;
> +
> /* update the cached value */
> intelhaddata->aud_config.regx.aud_en = enable;
> + intelhaddata->aud_config.regx.underrun = keep_link;
> had_write_register(intelhaddata, AUD_CONFIG,
> intelhaddata->aud_config.regval);
> }
> @@ -901,6 +909,21 @@ static void had_init_ringbuf(struct snd_pcm_substream *substream,
> intelhaddata->bd_head = 0; /* reset at head again before starting */
> }
>
> +/* Set up the silent output after PCM close */
> +static void had_keep_silent(struct snd_intelhad *intelhaddata)
> +{
> + int i;
> +
> + if (!(keep_link && intelhaddata->connected &&
> + intelhaddata->aud_config.regval))
> + return;
> +
> + for (i = 0; i < HAD_NUM_OF_RING_BUFS; i++)
> + had_invalidate_bd(intelhaddata, i);
> + intelhaddata->need_reset = true; /* reset at next */
> + had_enable_audio(intelhaddata, true);
> +}
> +
> /* process a bd, advance to the next */
> static void had_advance_ringbuf(struct snd_pcm_substream *substream,
> struct snd_intelhad *intelhaddata)
> @@ -1007,6 +1030,9 @@ static void had_do_reset(struct snd_intelhad *intelhaddata)
> if (!intelhaddata->need_reset)
> return;
>
> + /* disable the silent output */
> + had_enable_audio(intelhaddata, false);
> +
> /* Reset buffer pointers */
> had_reset_audio(intelhaddata);
> wait_clear_underrun_bit(intelhaddata);
> @@ -1101,6 +1127,8 @@ static int had_pcm_close(struct snd_pcm_substream *substream)
> }
> spin_unlock_irq(&intelhaddata->had_spinlock);
>
> + had_keep_silent(intelhaddata);
> +
> pm_runtime_mark_last_busy(intelhaddata->dev);
> pm_runtime_put_autosuspend(intelhaddata->dev);
> return 0;
> @@ -1626,6 +1654,9 @@ static int hdmi_lpe_audio_runtime_suspend(struct device *dev)
> had_substream_put(ctx);
> }
>
> + /* disable the silent output */
> + had_enable_audio(ctx, false);
> +
> return 0;
> }
>
> @@ -1642,6 +1673,9 @@ static int __maybe_unused hdmi_lpe_audio_suspend(struct device *dev)
>
> static int hdmi_lpe_audio_runtime_resume(struct device *dev)
> {
> + struct snd_intelhad *ctx = dev_get_drvdata(dev);
> +
> + had_keep_silent(ctx);
> pm_runtime_mark_last_busy(dev);
> return 0;
> }
> @@ -1799,6 +1833,10 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
> pdata->notify_pending = false;
> spin_unlock_irq(&pdata->lpe_audio_slock);
>
> + /* set a relatively long autosuspend delay (2 seconds) for making
> + * keep_link feature working reasonably
> + */
> + pm_runtime_set_autosuspend_delay(&pdev->dev, 2000);
> pm_runtime_use_autosuspend(&pdev->dev);
> pm_runtime_mark_last_busy(&pdev->dev);
>
>
More information about the Alsa-devel
mailing list