From f6b95b0da11f8e599f3a10a97c6f2ea80bfe2802 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 6 Feb 2020 13:22:02 +0200 Subject: [PATCH 1/3] [SQUASH ME] ASoC: SOF: Intel: hda: release display power for D0ix Display driver will emit a warning if system enters S3 with wakerefs to some power domain active. Make sure SOF releases display power when it enters D0ix, and wakes it back up upon resume. Now that we have more invocations of the display power helper functions, put the the ifdefs and the check for codec_mask, into hda_codec_i915_display_power() directly to reduce clutter. Should be squashed with "ASoC: SOF: Intel: hda: fix ordering bug in resume flow" Signed-off-by: Kai Vehmanen --- sound/soc/sof/intel/hda-codec.c | 12 ++++++++---- sound/soc/sof/intel/hda-dsp.c | 15 +++++++-------- sound/soc/sof/intel/hda.c | 2 +- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index 9106ab8dac6f62..ff45075ef72038 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -174,8 +174,10 @@ void hda_codec_i915_display_power(struct snd_sof_dev *sdev, bool enable) { struct hdac_bus *bus = sof_to_bus(sdev); - dev_dbg(bus->dev, "Turning i915 HDAC power %d\n", enable); - snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, enable); + if (HDA_IDISP_CODEC(bus->codec_mask)) { + dev_dbg(bus->dev, "Turning i915 HDAC power %d\n", enable); + snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, enable); + } } EXPORT_SYMBOL_NS(hda_codec_i915_display_power, SND_SOC_SOF_HDA_AUDIO_CODEC_I915); @@ -189,7 +191,8 @@ int hda_codec_i915_init(struct snd_sof_dev *sdev) if (ret < 0) return ret; - hda_codec_i915_display_power(sdev, true); + /* codec_mask not yet known, power up for probe */ + snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true); return 0; } @@ -200,7 +203,8 @@ int hda_codec_i915_exit(struct snd_sof_dev *sdev) struct hdac_bus *bus = sof_to_bus(sdev); int ret; - hda_codec_i915_display_power(sdev, false); + /* power down unconditionally */ + snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false); ret = snd_hdac_i915_exit(bus); diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index dfccbcbf769e7e..46d7b55a158383 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -595,11 +595,8 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend) return ret; } -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) /* display codec can powered off after link reset */ - if (HDA_IDISP_CODEC(bus->codec_mask)) - hda_codec_i915_display_power(sdev, false); -#endif + hda_codec_i915_display_power(sdev, false); return 0; } @@ -612,11 +609,8 @@ static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume) #endif int ret; -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) /* display codec must be powered before link reset */ - if (HDA_IDISP_CODEC(bus->codec_mask)) - hda_codec_i915_display_power(sdev, true); -#endif + hda_codec_i915_display_power(sdev, true); /* * clear TCSEL to clear playback on some HD Audio @@ -675,6 +669,8 @@ int hda_dsp_resume(struct snd_sof_dev *sdev) return ret; } + hda_codec_i915_display_power(sdev, true); + /* restore L1SEN bit */ if (hda->l1_support_changed) snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, @@ -763,6 +759,9 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state) return ret; } + /* we can't keep a wakeref to display driver at suspend */ + hda_codec_i915_display_power(sdev, false); + /* enable L1SEN to make sure the system can enter S0Ix */ hda->l1_support_changed = snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index f225152c21d78d..be8d775ee6d2d4 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -645,7 +645,7 @@ static int hda_init_caps(struct snd_sof_dev *sdev) hda_codec_probe_bus(sdev, hda_codec_use_common_hdmi); if (!HDA_IDISP_CODEC(bus->codec_mask)) - hda_codec_i915_display_power(sdev, false); + hda_codec_i915_exit(sdev); /* * we are done probing so decrement link counts From 58a3a52d6fdf3d3c355bd4b8719ee4886b757f99 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 6 Feb 2020 15:41:23 +0200 Subject: [PATCH 2/3] ALSA: hda: do not override probe codec_mask at in link_get() snd_hdac_ext_bus_link_get() does not work correctly in case there are multiple codecs on the bus. It unconditionally resets the bus->codec_mask value. This overwrites the initial value discovered at probe time when all codecs on the link were powered up. Signed-off-by: Kai Vehmanen --- sound/hda/ext/hdac_ext_controller.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sound/hda/ext/hdac_ext_controller.c b/sound/hda/ext/hdac_ext_controller.c index a684f0520b4b98..4d060d5b1db6dc 100644 --- a/sound/hda/ext/hdac_ext_controller.c +++ b/sound/hda/ext/hdac_ext_controller.c @@ -254,6 +254,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_down_all); int snd_hdac_ext_bus_link_get(struct hdac_bus *bus, struct hdac_ext_link *link) { + unsigned long codec_mask; int ret = 0; mutex_lock(&bus->lock); @@ -280,9 +281,11 @@ int snd_hdac_ext_bus_link_get(struct hdac_bus *bus, * HDA spec section 4.3 - Codec Discovery */ udelay(521); - bus->codec_mask = snd_hdac_chip_readw(bus, STATESTS); - dev_dbg(bus->dev, "codec_mask = 0x%lx\n", bus->codec_mask); - snd_hdac_chip_writew(bus, STATESTS, bus->codec_mask); + codec_mask = snd_hdac_chip_readw(bus, STATESTS); + dev_dbg(bus->dev, "codec_mask = 0x%lx\n", codec_mask); + snd_hdac_chip_writew(bus, STATESTS, codec_mask); + if (!bus->codec_mask) + bus->codec_mask = codec_mask; } mutex_unlock(&bus->lock); From d31cd9252811563ac1e6735f7bbe55c2379da10f Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 6 Feb 2020 15:41:23 +0200 Subject: [PATCH 3/3] [SQUASH ME] ASoC: SOF: Intel: hda: align with upstream Incremental changes to following patches sent usptream: ALSA: hda: do not override bus codec_mask in link_get() ASoC: SOF: Intel: hda: fix ordering bug in resume flow ASoC: SOF: Intel: hda: move i915 init earlier Signed-off-by: Kai Vehmanen --- sound/soc/sof/intel/hda.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index be8d775ee6d2d4..cdb418edd66451 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -519,14 +519,12 @@ static int hda_init(struct snd_sof_dev *sdev) /* HDA base */ sdev->bar[HDA_DSP_HDA_BAR] = bus->remap_addr; -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) /* init i915 and HDMI codecs */ ret = hda_codec_i915_init(sdev); if (ret < 0) { dev_err(sdev->dev, "error: init i915 and HDMI codec failed\n"); return ret; } -#endif /* get controller capabilities */ ret = hda_dsp_ctrl_get_caps(sdev); @@ -884,6 +882,7 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) iounmap(sdev->bar[HDA_DSP_BAR]); hdac_bus_unmap: iounmap(bus->remap_addr); + hda_codec_i915_exit(sdev); err: return ret; }