All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/7] ALSA: HD-audio display power fixes
@ 2018-12-09  9:33 Takashi Iwai
  2018-12-09  9:33 ` [PATCH 1/7] ALSA: hda/intel: Refactoring PM code Takashi Iwai
                   ` (6 more replies)
  0 siblings, 7 replies; 16+ messages in thread
From: Takashi Iwai @ 2018-12-09  9:33 UTC (permalink / raw)
  To: alsa-devel; +Cc: Liam Girdwood, Mark Brown, Jie Yang, Pierre-Louis Bossart

Hi,

this patch is about fixing possible HD-audio display power unbalance.
Basically the "fix" is done by refactoring the whole relevant code.
It starts from the Intel HD-audio runtime PM refactoring, followed
by the display PM API change, and lots of code cleanups.

Since it changes the display power API function, it hits both legacy
and ASoC drivers.

The patches are kept in topic/hda-pm-refactor branch of my sound git
tree.  This will be an immutable branch once when merged to for-next,
so that it can be merged to ASoC tree if any conflicting change needs
to be applied.


Takashi

===

Takashi Iwai (7):
  ALSA: hda/intel: Refactoring PM code
  ALSA: hda: Refactor display power management
  ALSA: hda/intel: Drop superfluous AZX_DCAPS_I915_POWERWELL checks
  ALSA: hda/intel: Properly free the display power at error path
  ALSA: hda: Make snd_hdac_display_power() void function
  ASoC: hdac_hdmi: Add missing display power-off at driver removal
  ALSA: hda/hdmi: Always set display_power_control for Intel HSW+ codecs

 include/sound/hda_codec.h      |   1 +
 include/sound/hda_component.h  |   9 +-
 include/sound/hdaudio.h        |   7 +-
 sound/hda/hdac_component.c     |  39 ++++---
 sound/hda/hdac_device.c        |  17 ---
 sound/pci/hda/hda_codec.c      |  16 ++-
 sound/pci/hda/hda_controller.c |  11 --
 sound/pci/hda/hda_intel.c      | 192 +++++++++++++--------------------
 sound/pci/hda/patch_hdmi.c     |   8 +-
 sound/soc/codecs/hdac_hdmi.c   |  22 ++--
 sound/soc/intel/skylake/skl.c  |  40 ++-----
 11 files changed, 134 insertions(+), 228 deletions(-)

-- 
2.19.2

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 1/7] ALSA: hda/intel: Refactoring PM code
  2018-12-09  9:33 [PATCH 0/7] ALSA: HD-audio display power fixes Takashi Iwai
@ 2018-12-09  9:33 ` Takashi Iwai
  2018-12-09  9:33 ` [PATCH 2/7] ALSA: hda: Refactor display power management Takashi Iwai
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 16+ messages in thread
From: Takashi Iwai @ 2018-12-09  9:33 UTC (permalink / raw)
  To: alsa-devel; +Cc: Liam Girdwood, Mark Brown, Jie Yang, Pierre-Louis Bossart

Make unified suspend / resume helpers and call them from both the
runtime- and the system-PM callbacks for simplifying code.

There are slight changes of call orders, but there shouldn't be any
functional difference after refactoring.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_intel.c | 160 ++++++++++++++++----------------------
 1 file changed, 69 insertions(+), 91 deletions(-)

diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 76f03abd15ab..cc06a323c817 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -930,35 +930,82 @@ static int param_set_xint(const char *val, const struct kernel_param *kp)
 	mutex_unlock(&card_list_lock);
 	return 0;
 }
-#else
-#define azx_add_card_list(chip) /* NOP */
-#define azx_del_card_list(chip) /* NOP */
-#endif /* CONFIG_PM */
 
-#ifdef CONFIG_PM_SLEEP
 /*
  * power management
  */
-static int azx_suspend(struct device *dev)
+static bool azx_is_pm_ready(struct snd_card *card)
 {
-	struct snd_card *card = dev_get_drvdata(dev);
 	struct azx *chip;
 	struct hda_intel *hda;
-	struct hdac_bus *bus;
 
 	if (!card)
-		return 0;
-
+		return false;
 	chip = card->private_data;
 	hda = container_of(chip, struct hda_intel, chip);
 	if (chip->disabled || hda->init_failed || !chip->running)
+		return false;
+	return true;
+}
+
+static void __azx_runtime_suspend(struct azx *chip)
+{
+	struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
+
+	azx_stop_chip(chip);
+	azx_enter_link_reset(chip);
+	azx_clear_irq_pending(chip);
+	if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) &&
+	    hda->need_i915_power)
+		snd_hdac_display_power(azx_bus(chip), false);
+}
+
+static void __azx_runtime_resume(struct azx *chip)
+{
+	struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
+	struct hdac_bus *bus = azx_bus(chip);
+	struct hda_codec *codec;
+	int status;
+
+	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
+		snd_hdac_display_power(bus, true);
+		if (hda->need_i915_power)
+			snd_hdac_i915_set_bclk(bus);
+	}
+
+	/* Read STATESTS before controller reset */
+	status = azx_readw(chip, STATESTS);
+
+	azx_init_pci(chip);
+	hda_intel_init_chip(chip, true);
+
+	if (status) {
+		list_for_each_codec(codec, &chip->bus)
+			if (status & (1 << codec->addr))
+				schedule_delayed_work(&codec->jackpoll_work,
+						      codec->jackpoll_interval);
+	}
+
+	/* power down again for link-controlled chips */
+	if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) &&
+	    !hda->need_i915_power)
+		snd_hdac_display_power(bus, false);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int azx_suspend(struct device *dev)
+{
+	struct snd_card *card = dev_get_drvdata(dev);
+	struct azx *chip;
+	struct hdac_bus *bus;
+
+	if (!azx_is_pm_ready(card))
 		return 0;
 
+	chip = card->private_data;
 	bus = azx_bus(chip);
 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
-	azx_clear_irq_pending(chip);
-	azx_stop_chip(chip);
-	azx_enter_link_reset(chip);
+	__azx_runtime_suspend(chip);
 	if (bus->irq >= 0) {
 		free_irq(bus->irq, chip);
 		bus->irq = -1;
@@ -966,9 +1013,6 @@ static int azx_suspend(struct device *dev)
 
 	if (chip->msi)
 		pci_disable_msi(chip->pci);
-	if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
-		&& hda->need_i915_power)
-		snd_hdac_display_power(bus, false);
 
 	trace_azx_suspend(chip);
 	return 0;
@@ -976,41 +1020,19 @@ static int azx_suspend(struct device *dev)
 
 static int azx_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct azx *chip;
-	struct hda_intel *hda;
-	struct hdac_bus *bus;
 
-	if (!card)
+	if (!azx_is_pm_ready(card))
 		return 0;
 
 	chip = card->private_data;
-	hda = container_of(chip, struct hda_intel, chip);
-	bus = azx_bus(chip);
-	if (chip->disabled || hda->init_failed || !chip->running)
-		return 0;
-
-	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
-		snd_hdac_display_power(bus, true);
-		if (hda->need_i915_power)
-			snd_hdac_i915_set_bclk(bus);
-	}
-
 	if (chip->msi)
-		if (pci_enable_msi(pci) < 0)
+		if (pci_enable_msi(chip->pci) < 0)
 			chip->msi = 0;
 	if (azx_acquire_irq(chip, 1) < 0)
 		return -EIO;
-	azx_init_pci(chip);
-
-	hda_intel_init_chip(chip, true);
-
-	/* power down again for link-controlled chips */
-	if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) &&
-	    !hda->need_i915_power)
-		snd_hdac_display_power(bus, false);
-
+	__azx_runtime_resume(chip);
 	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
 
 	trace_azx_resume(chip);
@@ -1045,21 +1067,14 @@ static int azx_thaw_noirq(struct device *dev)
 }
 #endif /* CONFIG_PM_SLEEP */
 
-#ifdef CONFIG_PM
 static int azx_runtime_suspend(struct device *dev)
 {
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct azx *chip;
-	struct hda_intel *hda;
 
-	if (!card)
+	if (!azx_is_pm_ready(card))
 		return 0;
-
 	chip = card->private_data;
-	hda = container_of(chip, struct hda_intel, chip);
-	if (chip->disabled || hda->init_failed)
-		return 0;
-
 	if (!azx_has_pm_runtime(chip))
 		return 0;
 
@@ -1067,13 +1082,7 @@ static int azx_runtime_suspend(struct device *dev)
 	azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) |
 		  STATESTS_INT_MASK);
 
-	azx_stop_chip(chip);
-	azx_enter_link_reset(chip);
-	azx_clear_irq_pending(chip);
-	if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
-		&& hda->need_i915_power)
-		snd_hdac_display_power(azx_bus(chip), false);
-
+	__azx_runtime_suspend(chip);
 	trace_azx_runtime_suspend(chip);
 	return 0;
 }
@@ -1082,51 +1091,18 @@ static int azx_runtime_resume(struct device *dev)
 {
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct azx *chip;
-	struct hda_intel *hda;
-	struct hdac_bus *bus;
-	struct hda_codec *codec;
-	int status;
 
-	if (!card)
+	if (!azx_is_pm_ready(card))
 		return 0;
-
 	chip = card->private_data;
-	hda = container_of(chip, struct hda_intel, chip);
-	bus = azx_bus(chip);
-	if (chip->disabled || hda->init_failed)
-		return 0;
-
 	if (!azx_has_pm_runtime(chip))
 		return 0;
-
-	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
-		snd_hdac_display_power(bus, true);
-		if (hda->need_i915_power)
-			snd_hdac_i915_set_bclk(bus);
-	}
-
-	/* Read STATESTS before controller reset */
-	status = azx_readw(chip, STATESTS);
-
-	azx_init_pci(chip);
-	hda_intel_init_chip(chip, true);
-
-	if (status) {
-		list_for_each_codec(codec, &chip->bus)
-			if (status & (1 << codec->addr))
-				schedule_delayed_work(&codec->jackpoll_work,
-						      codec->jackpoll_interval);
-	}
+	__azx_runtime_resume(chip);
 
 	/* disable controller Wake Up event*/
 	azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) &
 			~STATESTS_INT_MASK);
 
-	/* power down again for link-controlled chips */
-	if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) &&
-	    !hda->need_i915_power)
-		snd_hdac_display_power(bus, false);
-
 	trace_azx_runtime_resume(chip);
 	return 0;
 }
@@ -1167,6 +1143,8 @@ static const struct dev_pm_ops azx_pm = {
 
 #define AZX_PM_OPS	&azx_pm
 #else
+#define azx_add_card_list(chip) /* NOP */
+#define azx_del_card_list(chip) /* NOP */
 #define AZX_PM_OPS	NULL
 #endif /* CONFIG_PM */
 
-- 
2.19.2

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 2/7] ALSA: hda: Refactor display power management
  2018-12-09  9:33 [PATCH 0/7] ALSA: HD-audio display power fixes Takashi Iwai
  2018-12-09  9:33 ` [PATCH 1/7] ALSA: hda/intel: Refactoring PM code Takashi Iwai
@ 2018-12-09  9:33 ` Takashi Iwai
  2018-12-10 20:52   ` Pierre-Louis Bossart
  2018-12-09  9:33 ` [PATCH 3/7] ALSA: hda/intel: Drop superfluous AZX_DCAPS_I915_POWERWELL checks Takashi Iwai
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 16+ messages in thread
From: Takashi Iwai @ 2018-12-09  9:33 UTC (permalink / raw)
  To: alsa-devel; +Cc: Liam Girdwood, Mark Brown, Jie Yang, Pierre-Louis Bossart

The current HD-audio code manages the DRM audio power via too complex
redirections, and this seems even still unbalanced in a corner case as
Intel DRM CI has been intermittently reporting.  This patch is a big
surgery for addressing the complexity and the possible unbalance.

Basically the patch changes the display PM in the following ways:

- Both HD-audio controller and codec drivers call a single helper,
  snd_hdac_display_power().  (Formerly, the display power control from
  a codec was done indirectly via link_power bus ops.)

- snd_hdac_display_power() receives the codec address index.  For
  turning on/off from the controller, pass HDA_CODEC_IDX_CONTROLLER.

- snd_hdac_display_power() doesn't manage refcounts any longer, but
  keeps the power status in bitmap.  If any of controller or codecs is
  turned on, the function updates the DRM power state via get_power()
  or put_power().

Also this refactor allows us more cleanup:

- The link_power bus ops is dropped, so there is no longer indirect
  management, as mentioned in the above.

- hdac_device link_power_control flag is moved to hda_codec
  display_power_control flag, as it's only for HDA legacy.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=106525
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 include/sound/hda_codec.h      |  1 +
 include/sound/hda_component.h  |  8 ++++++--
 include/sound/hdaudio.h        |  7 ++-----
 sound/hda/hdac_component.c     | 35 +++++++++++++++++++++-------------
 sound/hda/hdac_device.c        | 17 -----------------
 sound/pci/hda/hda_codec.c      | 16 ++++++++++++----
 sound/pci/hda/hda_controller.c | 11 -----------
 sound/pci/hda/hda_intel.c      | 24 ++++++++---------------
 sound/pci/hda/patch_hdmi.c     |  4 ++--
 sound/soc/codecs/hdac_hdmi.c   |  7 +++----
 sound/soc/intel/skylake/skl.c  | 10 +++++-----
 11 files changed, 61 insertions(+), 79 deletions(-)

diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h
index 0d98bb9068b1..7fa48b100936 100644
--- a/include/sound/hda_codec.h
+++ b/include/sound/hda_codec.h
@@ -236,6 +236,7 @@ struct hda_codec {
 	/* misc flags */
 	unsigned int in_freeing:1; /* being released */
 	unsigned int registered:1; /* codec was registered */
+	unsigned int display_power_control:1; /* needs display power */
 	unsigned int spdif_status_reset :1; /* needs to toggle SPDIF for each
 					     * status change
 					     * (e.g. Realtek codecs)
diff --git a/include/sound/hda_component.h b/include/sound/hda_component.h
index 78626cde7081..b78add315b1f 100644
--- a/include/sound/hda_component.h
+++ b/include/sound/hda_component.h
@@ -6,9 +6,12 @@
 
 #include <drm/drm_audio_component.h>
 
+#define HDA_CODEC_IDX_CONTROLLER	16	/* virtual idx for controller */
+
 #ifdef CONFIG_SND_HDA_COMPONENT
 int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable);
-int snd_hdac_display_power(struct hdac_bus *bus, bool enable);
+int snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx,
+			   bool enable);
 int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid,
 			     int dev_id, int rate);
 int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id,
@@ -25,7 +28,8 @@ static inline int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable)
 {
 	return 0;
 }
-static inline int snd_hdac_display_power(struct hdac_bus *bus, bool enable)
+static inline int snd_hdac_display_power(struct hdac_bus *bus,
+					 unsigned int idx, bool enable)
 {
 	return 0;
 }
diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h
index cd1773d0e08f..940e2b282133 100644
--- a/include/sound/hdaudio.h
+++ b/include/sound/hdaudio.h
@@ -79,7 +79,6 @@ struct hdac_device {
 
 	/* misc flags */
 	atomic_t in_pm;		/* suspend/resume being performed */
-	bool  link_power_control:1;
 
 	/* sysfs */
 	struct hdac_widget_tree *widgets;
@@ -237,8 +236,6 @@ struct hdac_bus_ops {
 	/* get a response from the last command */
 	int (*get_response)(struct hdac_bus *bus, unsigned int addr,
 			    unsigned int *res);
-	/* control the link power  */
-	int (*link_power)(struct hdac_bus *bus, bool enable);
 };
 
 /*
@@ -363,7 +360,8 @@ struct hdac_bus {
 
 	/* DRM component interface */
 	struct drm_audio_component *audio_component;
-	int drm_power_refcount;
+	long display_power_status;
+	bool display_power_active;
 
 	/* parameters required for enhanced capabilities */
 	int num_streams;
@@ -404,7 +402,6 @@ int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val);
 int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr,
 			      unsigned int *res);
 int snd_hdac_bus_parse_capabilities(struct hdac_bus *bus);
-int snd_hdac_link_power(struct hdac_device *codec, bool enable);
 
 bool snd_hdac_bus_init_chip(struct hdac_bus *bus, bool full_reset);
 void snd_hdac_bus_stop_chip(struct hdac_bus *bus);
diff --git a/sound/hda/hdac_component.c b/sound/hda/hdac_component.c
index 6e46a9c73aed..dd766414436b 100644
--- a/sound/hda/hdac_component.c
+++ b/sound/hda/hdac_component.c
@@ -54,38 +54,45 @@ EXPORT_SYMBOL_GPL(snd_hdac_set_codec_wakeup);
 /**
  * snd_hdac_display_power - Power up / down the power refcount
  * @bus: HDA core bus
+ * @idx: HDA codec address, pass HDA_CODEC_IDX_CONTROLLER for controller
  * @enable: power up or down
  *
- * This function is supposed to be used only by a HD-audio controller
- * driver that needs the interaction with graphics driver.
+ * This function is used by either HD-audio controller or codec driver that
+ * needs the interaction with graphics driver.
  *
- * This function manages a refcount and calls the get_power() and
+ * This function updates the power status, and calls the get_power() and
  * put_power() ops accordingly, toggling the codec wakeup, too.
  *
  * Returns zero for success or a negative error code.
  */
-int snd_hdac_display_power(struct hdac_bus *bus, bool enable)
+int snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx, bool enable)
 {
 	struct drm_audio_component *acomp = bus->audio_component;
 
-	if (!acomp || !acomp->ops)
-		return -ENODEV;
-
 	dev_dbg(bus->dev, "display power %s\n",
 		enable ? "enable" : "disable");
+	if (enable)
+		set_bit(idx, &bus->display_power_status);
+	else
+		clear_bit(idx, &bus->display_power_status);
 
-	if (enable) {
-		if (!bus->drm_power_refcount++) {
+	if (!acomp || !acomp->ops)
+		return 0;
+
+	if (bus->display_power_status) {
+		if (!bus->display_power_active) {
 			if (acomp->ops->get_power)
 				acomp->ops->get_power(acomp->dev);
 			snd_hdac_set_codec_wakeup(bus, true);
 			snd_hdac_set_codec_wakeup(bus, false);
+			bus->display_power_active = true;
 		}
 	} else {
-		WARN_ON(!bus->drm_power_refcount);
-		if (!--bus->drm_power_refcount)
+		if (bus->display_power_active) {
 			if (acomp->ops->put_power)
 				acomp->ops->put_power(acomp->dev);
+			bus->display_power_active = false;
+		}
 	}
 
 	return 0;
@@ -321,10 +328,12 @@ int snd_hdac_acomp_exit(struct hdac_bus *bus)
 	if (!acomp)
 		return 0;
 
-	WARN_ON(bus->drm_power_refcount);
-	if (bus->drm_power_refcount > 0 && acomp->ops)
+	if (WARN_ON(bus->display_power_active) && acomp->ops)
 		acomp->ops->put_power(acomp->dev);
 
+	bus->display_power_active = false;
+	bus->display_power_status = 0;
+
 	component_master_del(dev, &hdac_component_master_ops);
 
 	bus->audio_component = NULL;
diff --git a/sound/hda/hdac_device.c b/sound/hda/hdac_device.c
index dbf02a3a8d2f..95b073ee4b32 100644
--- a/sound/hda/hdac_device.c
+++ b/sound/hda/hdac_device.c
@@ -622,23 +622,6 @@ int snd_hdac_power_down_pm(struct hdac_device *codec)
 EXPORT_SYMBOL_GPL(snd_hdac_power_down_pm);
 #endif
 
-/**
- * snd_hdac_link_power - Enable/disable the link power for a codec
- * @codec: the codec object
- * @bool: enable or disable the link power
- */
-int snd_hdac_link_power(struct hdac_device *codec, bool enable)
-{
-	if  (!codec->link_power_control)
-		return 0;
-
-	if  (codec->bus->ops->link_power)
-		return codec->bus->ops->link_power(codec->bus, enable);
-	else
-		return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(snd_hdac_link_power);
-
 /* codec vendor labels */
 struct hda_vendor_id {
 	unsigned int id;
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 0957813939e5..9f8d59e7e89f 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -36,6 +36,7 @@
 #include "hda_beep.h"
 #include "hda_jack.h"
 #include <sound/hda_hwdep.h>
+#include <sound/hda_component.h>
 
 #define codec_in_pm(codec)		snd_hdac_is_in_pm(&codec->core)
 #define hda_codec_is_power_on(codec)	snd_hdac_is_power_on(&codec->core)
@@ -799,6 +800,13 @@ void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec)
 static unsigned int hda_set_power_state(struct hda_codec *codec,
 				unsigned int power_state);
 
+/* enable/disable display power per codec */
+static void codec_display_power(struct hda_codec *codec, bool enable)
+{
+	if (codec->display_power_control)
+		snd_hdac_display_power(&codec->bus->core, codec->addr, enable);
+}
+
 /* also called from hda_bind.c */
 void snd_hda_codec_register(struct hda_codec *codec)
 {
@@ -806,7 +814,7 @@ void snd_hda_codec_register(struct hda_codec *codec)
 		return;
 	if (device_is_registered(hda_codec_dev(codec))) {
 		snd_hda_register_beep_device(codec);
-		snd_hdac_link_power(&codec->core, true);
+		codec_display_power(codec, true);
 		pm_runtime_enable(hda_codec_dev(codec));
 		/* it was powered up in snd_hda_codec_new(), now all done */
 		snd_hda_power_down(codec);
@@ -834,7 +842,7 @@ static int snd_hda_codec_dev_free(struct snd_device *device)
 
 	codec->in_freeing = 1;
 	snd_hdac_device_unregister(&codec->core);
-	snd_hdac_link_power(&codec->core, false);
+	codec_display_power(codec, false);
 	put_device(hda_codec_dev(codec));
 	return 0;
 }
@@ -2926,7 +2934,7 @@ static int hda_codec_runtime_suspend(struct device *dev)
 	    (codec_has_clkstop(codec) && codec_has_epss(codec) &&
 	     (state & AC_PWRST_CLK_STOP_OK)))
 		snd_hdac_codec_link_down(&codec->core);
-	snd_hdac_link_power(&codec->core, false);
+	codec_display_power(codec, false);
 	return 0;
 }
 
@@ -2934,7 +2942,7 @@ static int hda_codec_runtime_resume(struct device *dev)
 {
 	struct hda_codec *codec = dev_to_hda_codec(dev);
 
-	snd_hdac_link_power(&codec->core, true);
+	codec_display_power(codec, true);
 	snd_hdac_codec_link_up(&codec->core);
 	hda_call_codec_resume(codec);
 	pm_runtime_mark_last_busy(dev);
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c
index fe2506672a72..532e081f8b8a 100644
--- a/sound/pci/hda/hda_controller.c
+++ b/sound/pci/hda/hda_controller.c
@@ -989,20 +989,9 @@ static int azx_get_response(struct hdac_bus *bus, unsigned int addr,
 		return azx_rirb_get_response(bus, addr, res);
 }
 
-static int azx_link_power(struct hdac_bus *bus, bool enable)
-{
-	struct azx *chip = bus_to_azx(bus);
-
-	if (chip->ops->link_power)
-		return chip->ops->link_power(chip, enable);
-	else
-		return -EINVAL;
-}
-
 static const struct hdac_bus_ops bus_core_ops = {
 	.command = azx_send_cmd,
 	.get_response = azx_get_response,
-	.link_power = azx_link_power,
 };
 
 #ifdef CONFIG_SND_HDA_DSP_LOADER
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index cc06a323c817..151c6ca85ec6 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -667,13 +667,8 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev)
 	return 0;
 }
 
-/* Enable/disable i915 display power for the link */
-static int azx_intel_link_power(struct azx *chip, bool enable)
-{
-	struct hdac_bus *bus = azx_bus(chip);
-
-	return snd_hdac_display_power(bus, enable);
-}
+#define display_power(chip, enable) \
+	snd_hdac_display_power(azx_bus(chip), HDA_CODEC_IDX_CONTROLLER, enable)
 
 /*
  * Check whether the current DMA position is acceptable for updating
@@ -950,14 +945,12 @@ static bool azx_is_pm_ready(struct snd_card *card)
 
 static void __azx_runtime_suspend(struct azx *chip)
 {
-	struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
-
 	azx_stop_chip(chip);
 	azx_enter_link_reset(chip);
 	azx_clear_irq_pending(chip);
 	if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) &&
 	    hda->need_i915_power)
-		snd_hdac_display_power(azx_bus(chip), false);
+		display_power(chip, false);
 }
 
 static void __azx_runtime_resume(struct azx *chip)
@@ -968,7 +961,7 @@ static void __azx_runtime_resume(struct azx *chip)
 	int status;
 
 	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
-		snd_hdac_display_power(bus, true);
+		display_power(chip, true);
 		if (hda->need_i915_power)
 			snd_hdac_i915_set_bclk(bus);
 	}
@@ -989,7 +982,7 @@ static void __azx_runtime_resume(struct azx *chip)
 	/* power down again for link-controlled chips */
 	if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) &&
 	    !hda->need_i915_power)
-		snd_hdac_display_power(bus, false);
+		display_power(chip, false);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -1355,7 +1348,7 @@ static int azx_free(struct azx *chip)
 
 	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
 		if (hda->need_i915_power)
-			snd_hdac_display_power(bus, false);
+			display_power(chip, false);
 	}
 	if (chip->driver_caps & AZX_DCAPS_I915_COMPONENT)
 		snd_hdac_i915_exit(bus);
@@ -2056,7 +2049,6 @@ static const struct hda_controller_ops pci_hda_ops = {
 	.disable_msi_reset_irq = disable_msi_reset_irq,
 	.pcm_mmap_prepare = pcm_mmap_prepare,
 	.position_check = azx_position_check,
-	.link_power = azx_intel_link_power,
 };
 
 static int azx_probe(struct pci_dev *pci,
@@ -2239,7 +2231,7 @@ static int azx_probe_continue(struct azx *chip)
 		if (CONTROLLER_IN_GPU(pci))
 			hda->need_i915_power = 1;
 
-		err = snd_hdac_display_power(bus, true);
+		err = display_power(chip, true);
 		if (err < 0) {
 			dev_err(chip->card->dev,
 				"Cannot turn on display power on i915\n");
@@ -2295,7 +2287,7 @@ static int azx_probe_continue(struct azx *chip)
 out_free:
 	if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
 		&& !hda->need_i915_power)
-		snd_hdac_display_power(bus, false);
+		display_power(chip, false);
 
 i915_power_fail:
 	if (err < 0)
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 67099cbb6be2..30fe4dbdb0ae 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -2620,7 +2620,7 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid)
 	 * can cover the codec power request, and so need not set this flag.
 	 */
 	if (!is_haswell(codec) && !is_broadwell(codec))
-		codec->core.link_power_control = 1;
+		codec->display_power_control = 1;
 
 	codec->patch_ops.set_power_state = haswell_set_power_state;
 	codec->depop_delay = 0;
@@ -2656,7 +2656,7 @@ static int patch_i915_byt_hdmi(struct hda_codec *codec)
 	/* For Valleyview/Cherryview, only the display codec is in the display
 	 * power well and can use link_power ops to request/release the power.
 	 */
-	codec->core.link_power_control = 1;
+	codec->display_power_control = 1;
 
 	codec->depop_delay = 0;
 	codec->auto_runtime_pm = 1;
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
index e63d6e33df48..c3d551d2af7f 100644
--- a/sound/soc/codecs/hdac_hdmi.c
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -2031,14 +2031,13 @@ static int hdac_hdmi_dev_probe(struct hdac_device *hdev)
 	 * Turned off in the runtime_suspend during the first explicit
 	 * pm_runtime_suspend call.
 	 */
-	ret = snd_hdac_display_power(hdev->bus, true);
+	ret = snd_hdac_display_power(hdev->bus, hdev->addr, true);
 	if (ret < 0) {
 		dev_err(&hdev->dev,
 			"Cannot turn on display power on i915 err: %d\n",
 			ret);
 		return ret;
 	}
-
 	ret = hdac_hdmi_parse_and_map_nid(hdev, &hdmi_dais, &num_dais);
 	if (ret < 0) {
 		dev_err(&hdev->dev,
@@ -2196,7 +2195,7 @@ static int hdac_hdmi_runtime_suspend(struct device *dev)
 
 	snd_hdac_ext_bus_link_put(bus, hlink);
 
-	err = snd_hdac_display_power(bus, false);
+	err = snd_hdac_display_power(bus, hdev->addr, false);
 	if (err < 0)
 		dev_err(dev, "Cannot turn off display power on i915\n");
 
@@ -2224,7 +2223,7 @@ static int hdac_hdmi_runtime_resume(struct device *dev)
 
 	snd_hdac_ext_bus_link_get(bus, hlink);
 
-	err = snd_hdac_display_power(bus, true);
+	err = snd_hdac_display_power(bus, hdev->addr, true);
 	if (err < 0) {
 		dev_err(dev, "Cannot turn on display power on i915\n");
 		return err;
diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c
index 7487f388e65d..64f8433ae921 100644
--- a/sound/soc/intel/skylake/skl.c
+++ b/sound/soc/intel/skylake/skl.c
@@ -334,7 +334,7 @@ static int skl_suspend(struct device *dev)
 	}
 
 	if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
-		ret = snd_hdac_display_power(bus, false);
+		ret = snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
 		if (ret < 0)
 			dev_err(bus->dev,
 				"Cannot turn OFF display power on i915\n");
@@ -353,7 +353,7 @@ static int skl_resume(struct device *dev)
 
 	/* Turned OFF in HDMI codec driver after codec reconfiguration */
 	if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
-		ret = snd_hdac_display_power(bus, true);
+		ret = snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true);
 		if (ret < 0) {
 			dev_err(bus->dev,
 				"Cannot turn on display power on i915\n");
@@ -783,7 +783,7 @@ static int skl_i915_init(struct hdac_bus *bus)
 	if (err < 0)
 		return err;
 
-	err = snd_hdac_display_power(bus, true);
+	err = snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true);
 	if (err < 0)
 		dev_err(bus->dev, "Cannot turn on display power on i915\n");
 
@@ -838,7 +838,7 @@ static void skl_probe_work(struct work_struct *work)
 		snd_hdac_ext_bus_link_put(bus, hlink);
 
 	if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
-		err = snd_hdac_display_power(bus, false);
+		err = snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
 		if (err < 0) {
 			dev_err(bus->dev, "Cannot turn off display power on i915\n");
 			skl_machine_device_unregister(skl);
@@ -855,7 +855,7 @@ static void skl_probe_work(struct work_struct *work)
 
 out_err:
 	if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
-		err = snd_hdac_display_power(bus, false);
+		err = snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
 }
 
 /*
-- 
2.19.2

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 3/7] ALSA: hda/intel: Drop superfluous AZX_DCAPS_I915_POWERWELL checks
  2018-12-09  9:33 [PATCH 0/7] ALSA: HD-audio display power fixes Takashi Iwai
  2018-12-09  9:33 ` [PATCH 1/7] ALSA: hda/intel: Refactoring PM code Takashi Iwai
  2018-12-09  9:33 ` [PATCH 2/7] ALSA: hda: Refactor display power management Takashi Iwai
@ 2018-12-09  9:33 ` Takashi Iwai
  2018-12-10 20:56   ` Pierre-Louis Bossart
  2018-12-09  9:33 ` [PATCH 4/7] ALSA: hda/intel: Properly free the display power at error path Takashi Iwai
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 16+ messages in thread
From: Takashi Iwai @ 2018-12-09  9:33 UTC (permalink / raw)
  To: alsa-devel; +Cc: Liam Girdwood, Mark Brown, Jie Yang, Pierre-Louis Bossart

Since snd_hdac_display_power() can be called even for a HDA controller
without DRM binding, lots of superfluous AZX_DCAPS_I915_POWERWELL
checks in hda_intel.c can be dropped.  This simplifies the code a
lot.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_intel.c | 43 +++++++++++++++------------------------
 1 file changed, 16 insertions(+), 27 deletions(-)

diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 151c6ca85ec6..cacee33a74a8 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -948,9 +948,7 @@ static void __azx_runtime_suspend(struct azx *chip)
 	azx_stop_chip(chip);
 	azx_enter_link_reset(chip);
 	azx_clear_irq_pending(chip);
-	if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) &&
-	    hda->need_i915_power)
-		display_power(chip, false);
+	display_power(chip, false);
 }
 
 static void __azx_runtime_resume(struct azx *chip)
@@ -960,11 +958,9 @@ static void __azx_runtime_resume(struct azx *chip)
 	struct hda_codec *codec;
 	int status;
 
-	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
-		display_power(chip, true);
-		if (hda->need_i915_power)
-			snd_hdac_i915_set_bclk(bus);
-	}
+	display_power(chip, true);
+	if (hda->need_i915_power)
+		snd_hdac_i915_set_bclk(bus);
 
 	/* Read STATESTS before controller reset */
 	status = azx_readw(chip, STATESTS);
@@ -980,8 +976,7 @@ static void __azx_runtime_resume(struct azx *chip)
 	}
 
 	/* power down again for link-controlled chips */
-	if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) &&
-	    !hda->need_i915_power)
+	if (!hda->need_i915_power)
 		display_power(chip, false);
 }
 
@@ -1345,11 +1340,8 @@ static int azx_free(struct azx *chip)
 #ifdef CONFIG_SND_HDA_PATCH_LOADER
 	release_firmware(chip->fw);
 #endif
+	display_power(chip, false);
 
-	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
-		if (hda->need_i915_power)
-			display_power(chip, false);
-	}
 	if (chip->driver_caps & AZX_DCAPS_I915_COMPONENT)
 		snd_hdac_i915_exit(bus);
 	kfree(hda);
@@ -2219,6 +2211,10 @@ static int azx_probe_continue(struct azx *chip)
 					~(AZX_DCAPS_I915_COMPONENT | AZX_DCAPS_I915_POWERWELL);
 			}
 		}
+
+		/* HSW/BDW controllers need this power */
+		if (CONTROLLER_IN_GPU(pci))
+			hda->need_i915_power = 1;
 	}
 
 	/* Request display power well for the HDA controller or codec. For
@@ -2226,17 +2222,11 @@ static int azx_probe_continue(struct azx *chip)
 	 * this power. For other platforms, like Baytrail/Braswell, only the
 	 * display codec needs the power and it can be released after probe.
 	 */
-	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
-		/* HSW/BDW controllers need this power */
-		if (CONTROLLER_IN_GPU(pci))
-			hda->need_i915_power = 1;
-
-		err = display_power(chip, true);
-		if (err < 0) {
-			dev_err(chip->card->dev,
-				"Cannot turn on display power on i915\n");
-			goto i915_power_fail;
-		}
+	err = display_power(chip, true);
+	if (err < 0) {
+		dev_err(chip->card->dev,
+			"Cannot turn on display power on i915\n");
+		goto i915_power_fail;
 	}
 
 	err = azx_first_init(chip);
@@ -2285,8 +2275,7 @@ static int azx_probe_continue(struct azx *chip)
 		pm_runtime_put_autosuspend(&pci->dev);
 
 out_free:
-	if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
-		&& !hda->need_i915_power)
+	if (!hda->need_i915_power)
 		display_power(chip, false);
 
 i915_power_fail:
-- 
2.19.2

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 4/7] ALSA: hda/intel: Properly free the display power at error path
  2018-12-09  9:33 [PATCH 0/7] ALSA: HD-audio display power fixes Takashi Iwai
                   ` (2 preceding siblings ...)
  2018-12-09  9:33 ` [PATCH 3/7] ALSA: hda/intel: Drop superfluous AZX_DCAPS_I915_POWERWELL checks Takashi Iwai
@ 2018-12-09  9:33 ` Takashi Iwai
  2018-12-09  9:33 ` [PATCH 5/7] ALSA: hda: Make snd_hdac_display_power() void function Takashi Iwai
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 16+ messages in thread
From: Takashi Iwai @ 2018-12-09  9:33 UTC (permalink / raw)
  To: alsa-devel; +Cc: Liam Girdwood, Mark Brown, Jie Yang, Pierre-Louis Bossart

When an error occurs in azx_probe_continue(), we should release the
display power.  However, the current code ignores it and releases the
display power only for HSW/BDW cases.  Fix it.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_intel.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index cacee33a74a8..48b29f02f72d 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -2275,7 +2275,7 @@ static int azx_probe_continue(struct azx *chip)
 		pm_runtime_put_autosuspend(&pci->dev);
 
 out_free:
-	if (!hda->need_i915_power)
+	if (err < 0 || !hda->need_i915_power)
 		display_power(chip, false);
 
 i915_power_fail:
-- 
2.19.2

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 5/7] ALSA: hda: Make snd_hdac_display_power() void function
  2018-12-09  9:33 [PATCH 0/7] ALSA: HD-audio display power fixes Takashi Iwai
                   ` (3 preceding siblings ...)
  2018-12-09  9:33 ` [PATCH 4/7] ALSA: hda/intel: Properly free the display power at error path Takashi Iwai
@ 2018-12-09  9:33 ` Takashi Iwai
  2018-12-09  9:33 ` [PATCH 6/7] ASoC: hdac_hdmi: Add missing display power-off at driver removal Takashi Iwai
  2018-12-09  9:33 ` [PATCH 7/7] ALSA: hda/hdmi: Always set display_power_control for Intel HSW+ codecs Takashi Iwai
  6 siblings, 0 replies; 16+ messages in thread
From: Takashi Iwai @ 2018-12-09  9:33 UTC (permalink / raw)
  To: alsa-devel; +Cc: Liam Girdwood, Mark Brown, Jie Yang, Pierre-Louis Bossart

After the recent refactoring, snd_hdac_display_power() doesn't return
any error, hence it can be defined to return void.
This makes many error checks redundant and allows us to reduce them
gracefully.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 include/sound/hda_component.h |  9 ++++----
 sound/hda/hdac_component.c    |  8 ++-----
 sound/pci/hda/hda_intel.c     |  9 +-------
 sound/soc/codecs/hdac_hdmi.c  | 21 +++++-------------
 sound/soc/intel/skylake/skl.c | 40 ++++++++++-------------------------
 5 files changed, 23 insertions(+), 64 deletions(-)

diff --git a/include/sound/hda_component.h b/include/sound/hda_component.h
index b78add315b1f..1916f4928bf3 100644
--- a/include/sound/hda_component.h
+++ b/include/sound/hda_component.h
@@ -10,8 +10,8 @@
 
 #ifdef CONFIG_SND_HDA_COMPONENT
 int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable);
-int snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx,
-			   bool enable);
+void snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx,
+			    bool enable);
 int snd_hdac_sync_audio_rate(struct hdac_device *codec, hda_nid_t nid,
 			     int dev_id, int rate);
 int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id,
@@ -28,10 +28,9 @@ static inline int snd_hdac_set_codec_wakeup(struct hdac_bus *bus, bool enable)
 {
 	return 0;
 }
-static inline int snd_hdac_display_power(struct hdac_bus *bus,
-					 unsigned int idx, bool enable)
+static inline void snd_hdac_display_power(struct hdac_bus *bus,
+					  unsigned int idx, bool enable)
 {
-	return 0;
 }
 static inline int snd_hdac_sync_audio_rate(struct hdac_device *codec,
 					   hda_nid_t nid, int dev_id, int rate)
diff --git a/sound/hda/hdac_component.c b/sound/hda/hdac_component.c
index dd766414436b..a6d37b9d6413 100644
--- a/sound/hda/hdac_component.c
+++ b/sound/hda/hdac_component.c
@@ -62,10 +62,8 @@ EXPORT_SYMBOL_GPL(snd_hdac_set_codec_wakeup);
  *
  * This function updates the power status, and calls the get_power() and
  * put_power() ops accordingly, toggling the codec wakeup, too.
- *
- * Returns zero for success or a negative error code.
  */
-int snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx, bool enable)
+void snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx, bool enable)
 {
 	struct drm_audio_component *acomp = bus->audio_component;
 
@@ -77,7 +75,7 @@ int snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx, bool enable)
 		clear_bit(idx, &bus->display_power_status);
 
 	if (!acomp || !acomp->ops)
-		return 0;
+		return;
 
 	if (bus->display_power_status) {
 		if (!bus->display_power_active) {
@@ -94,8 +92,6 @@ int snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx, bool enable)
 			bus->display_power_active = false;
 		}
 	}
-
-	return 0;
 }
 EXPORT_SYMBOL_GPL(snd_hdac_display_power);
 
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 48b29f02f72d..e89b8933b464 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -2222,12 +2222,7 @@ static int azx_probe_continue(struct azx *chip)
 	 * this power. For other platforms, like Baytrail/Braswell, only the
 	 * display codec needs the power and it can be released after probe.
 	 */
-	err = display_power(chip, true);
-	if (err < 0) {
-		dev_err(chip->card->dev,
-			"Cannot turn on display power on i915\n");
-		goto i915_power_fail;
-	}
+	display_power(chip, true);
 
 	err = azx_first_init(chip);
 	if (err < 0)
@@ -2277,8 +2272,6 @@ static int azx_probe_continue(struct azx *chip)
 out_free:
 	if (err < 0 || !hda->need_i915_power)
 		display_power(chip, false);
-
-i915_power_fail:
 	if (err < 0)
 		hda->init_failed = 1;
 	complete_all(&hda->probe_wait);
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
index c3d551d2af7f..adce94a3b289 100644
--- a/sound/soc/codecs/hdac_hdmi.c
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -2031,13 +2031,8 @@ static int hdac_hdmi_dev_probe(struct hdac_device *hdev)
 	 * Turned off in the runtime_suspend during the first explicit
 	 * pm_runtime_suspend call.
 	 */
-	ret = snd_hdac_display_power(hdev->bus, hdev->addr, true);
-	if (ret < 0) {
-		dev_err(&hdev->dev,
-			"Cannot turn on display power on i915 err: %d\n",
-			ret);
-		return ret;
-	}
+	snd_hdac_display_power(hdev->bus, hdev->addr, true);
+
 	ret = hdac_hdmi_parse_and_map_nid(hdev, &hdmi_dais, &num_dais);
 	if (ret < 0) {
 		dev_err(&hdev->dev,
@@ -2195,11 +2190,9 @@ static int hdac_hdmi_runtime_suspend(struct device *dev)
 
 	snd_hdac_ext_bus_link_put(bus, hlink);
 
-	err = snd_hdac_display_power(bus, hdev->addr, false);
-	if (err < 0)
-		dev_err(dev, "Cannot turn off display power on i915\n");
+	snd_hdac_display_power(bus, hdev->addr, false);
 
-	return err;
+	return 0;
 }
 
 static int hdac_hdmi_runtime_resume(struct device *dev)
@@ -2223,11 +2216,7 @@ static int hdac_hdmi_runtime_resume(struct device *dev)
 
 	snd_hdac_ext_bus_link_get(bus, hlink);
 
-	err = snd_hdac_display_power(bus, hdev->addr, true);
-	if (err < 0) {
-		dev_err(dev, "Cannot turn on display power on i915\n");
-		return err;
-	}
+	snd_hdac_display_power(bus, hdev->addr, true);
 
 	hdac_hdmi_skl_enable_all_pins(hdev);
 	hdac_hdmi_skl_enable_dp12(hdev);
diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c
index 64f8433ae921..5c224a0e1c7a 100644
--- a/sound/soc/intel/skylake/skl.c
+++ b/sound/soc/intel/skylake/skl.c
@@ -311,7 +311,7 @@ static int skl_suspend(struct device *dev)
 	struct pci_dev *pci = to_pci_dev(dev);
 	struct hdac_bus *bus = pci_get_drvdata(pci);
 	struct skl *skl  = bus_to_skl(bus);
-	int ret = 0;
+	int ret;
 
 	/*
 	 * Do not suspend if streams which are marked ignore suspend are
@@ -333,14 +333,10 @@ static int skl_suspend(struct device *dev)
 		skl->skl_sst->fw_loaded = false;
 	}
 
-	if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
-		ret = snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
-		if (ret < 0)
-			dev_err(bus->dev,
-				"Cannot turn OFF display power on i915\n");
-	}
+	if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
+		snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
 
-	return ret;
+	return 0;
 }
 
 static int skl_resume(struct device *dev)
@@ -352,14 +348,8 @@ static int skl_resume(struct device *dev)
 	int ret;
 
 	/* Turned OFF in HDMI codec driver after codec reconfiguration */
-	if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
-		ret = snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true);
-		if (ret < 0) {
-			dev_err(bus->dev,
-				"Cannot turn on display power on i915\n");
-			return ret;
-		}
-	}
+	if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
+		snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true);
 
 	/*
 	 * resume only when we are not in suspend active, otherwise need to
@@ -783,11 +773,9 @@ static int skl_i915_init(struct hdac_bus *bus)
 	if (err < 0)
 		return err;
 
-	err = snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true);
-	if (err < 0)
-		dev_err(bus->dev, "Cannot turn on display power on i915\n");
+	snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true);
 
-	return err;
+	return 0;
 }
 
 static void skl_probe_work(struct work_struct *work)
@@ -837,14 +825,8 @@ static void skl_probe_work(struct work_struct *work)
 	list_for_each_entry(hlink, &bus->hlink_list, list)
 		snd_hdac_ext_bus_link_put(bus, hlink);
 
-	if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
-		err = snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
-		if (err < 0) {
-			dev_err(bus->dev, "Cannot turn off display power on i915\n");
-			skl_machine_device_unregister(skl);
-			return;
-		}
-	}
+	if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
+		snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
 
 	/* configure PM */
 	pm_runtime_put_noidle(bus->dev);
@@ -855,7 +837,7 @@ static void skl_probe_work(struct work_struct *work)
 
 out_err:
 	if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
-		err = snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
+		snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
 }
 
 /*
-- 
2.19.2

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 6/7] ASoC: hdac_hdmi: Add missing display power-off at driver removal
  2018-12-09  9:33 [PATCH 0/7] ALSA: HD-audio display power fixes Takashi Iwai
                   ` (4 preceding siblings ...)
  2018-12-09  9:33 ` [PATCH 5/7] ALSA: hda: Make snd_hdac_display_power() void function Takashi Iwai
@ 2018-12-09  9:33 ` Takashi Iwai
  2018-12-10 14:33   ` Mark Brown
  2018-12-09  9:33 ` [PATCH 7/7] ALSA: hda/hdmi: Always set display_power_control for Intel HSW+ codecs Takashi Iwai
  6 siblings, 1 reply; 16+ messages in thread
From: Takashi Iwai @ 2018-12-09  9:33 UTC (permalink / raw)
  To: alsa-devel; +Cc: Liam Girdwood, Mark Brown, Jie Yang, Pierre-Louis Bossart

The display power is in unbalance at removing the driver since it
misses the snd_hdac_display_power(OFF) call.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/soc/codecs/hdac_hdmi.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
index adce94a3b289..6549adcf857f 100644
--- a/sound/soc/codecs/hdac_hdmi.c
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -2059,6 +2059,8 @@ static int hdac_hdmi_dev_remove(struct hdac_device *hdev)
 	struct hdac_hdmi_port *port, *port_next;
 	int i;
 
+	snd_hdac_display_power(hdev->bus, hdev->addr, false);
+
 	list_for_each_entry_safe(pcm, pcm_next, &hdmi->pcm_list, head) {
 		pcm->cvt = NULL;
 		if (list_empty(&pcm->port_list))
-- 
2.19.2

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 7/7] ALSA: hda/hdmi: Always set display_power_control for Intel HSW+ codecs
  2018-12-09  9:33 [PATCH 0/7] ALSA: HD-audio display power fixes Takashi Iwai
                   ` (5 preceding siblings ...)
  2018-12-09  9:33 ` [PATCH 6/7] ASoC: hdac_hdmi: Add missing display power-off at driver removal Takashi Iwai
@ 2018-12-09  9:33 ` Takashi Iwai
  6 siblings, 0 replies; 16+ messages in thread
From: Takashi Iwai @ 2018-12-09  9:33 UTC (permalink / raw)
  To: alsa-devel; +Cc: Liam Girdwood, Mark Brown, Jie Yang, Pierre-Louis Bossart

We've excluded the display_power_control flag for Intel HSW and BDW
codecs as the HD-audio controllers of the corresponding platforms take
care of the display power as well.  But the recent refactoring
separates the controller and the codec power accounting, so it's fine
to call the display PM even for HSW/BDW codecs.  This is less
confusing since we can avoid this well-hidden condition.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_hdmi.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 30fe4dbdb0ae..15290e4706e0 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -2616,11 +2616,7 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid)
 	intel_haswell_enable_all_pins(codec, true);
 	intel_haswell_fixup_enable_dp12(codec);
 
-	/* For Haswell/Broadwell, the controller is also in the power well and
-	 * can cover the codec power request, and so need not set this flag.
-	 */
-	if (!is_haswell(codec) && !is_broadwell(codec))
-		codec->display_power_control = 1;
+	codec->display_power_control = 1;
 
 	codec->patch_ops.set_power_state = haswell_set_power_state;
 	codec->depop_delay = 0;
-- 
2.19.2

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH 6/7] ASoC: hdac_hdmi: Add missing display power-off at driver removal
  2018-12-09  9:33 ` [PATCH 6/7] ASoC: hdac_hdmi: Add missing display power-off at driver removal Takashi Iwai
@ 2018-12-10 14:33   ` Mark Brown
  0 siblings, 0 replies; 16+ messages in thread
From: Mark Brown @ 2018-12-10 14:33 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: Liam Girdwood, alsa-devel, Jie Yang, Pierre-Louis Bossart


[-- Attachment #1.1: Type: text/plain, Size: 220 bytes --]

On Sun, Dec 09, 2018 at 10:33:17AM +0100, Takashi Iwai wrote:
> The display power is in unbalance at removing the driver since it
> misses the snd_hdac_display_power(OFF) call.

Acked-by: Mark Brown <broonie@kernel.org>

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/7] ALSA: hda: Refactor display power management
  2018-12-09  9:33 ` [PATCH 2/7] ALSA: hda: Refactor display power management Takashi Iwai
@ 2018-12-10 20:52   ` Pierre-Louis Bossart
  2018-12-11  6:54     ` Takashi Iwai
  0 siblings, 1 reply; 16+ messages in thread
From: Pierre-Louis Bossart @ 2018-12-10 20:52 UTC (permalink / raw)
  To: Takashi Iwai, alsa-devel; +Cc: Liam Girdwood, Mark Brown, Jie Yang


On 12/9/18 3:33 AM, Takashi Iwai wrote:
> The current HD-audio code manages the DRM audio power via too complex
> redirections, and this seems even still unbalanced in a corner case as
> Intel DRM CI has been intermittently reporting.  This patch is a big
> surgery for addressing the complexity and the possible unbalance.
>
> Basically the patch changes the display PM in the following ways:
>
> - Both HD-audio controller and codec drivers call a single helper,
>    snd_hdac_display_power().  (Formerly, the display power control from
>    a codec was done indirectly via link_power bus ops.)
>
> - snd_hdac_display_power() receives the codec address index.  For
>    turning on/off from the controller, pass HDA_CODEC_IDX_CONTROLLER.

The need for this virtual index==16 isn't fully clear to me, especially 
if you use the bitfields instead of reference counts.

Isn't there a risk of the controller setting the bit16 to zero, but you 
still have bit4 on (assuming the idx is 4). If you use this virtual 
index, it should override the actual physical bits when set/cleared.

Or is this meant to actually implement a preemption mechanism, where the 
display power remains on for as long as the controller wishes, 
regardless of what the patch_hdmi and hdac_hdmi code requests?

Also don't we already have the HDMI codec address already after the 
probe, so couldn't we provide the address directly?

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 3/7] ALSA: hda/intel: Drop superfluous AZX_DCAPS_I915_POWERWELL checks
  2018-12-09  9:33 ` [PATCH 3/7] ALSA: hda/intel: Drop superfluous AZX_DCAPS_I915_POWERWELL checks Takashi Iwai
@ 2018-12-10 20:56   ` Pierre-Louis Bossart
  2018-12-11  7:00     ` Takashi Iwai
  0 siblings, 1 reply; 16+ messages in thread
From: Pierre-Louis Bossart @ 2018-12-10 20:56 UTC (permalink / raw)
  To: Takashi Iwai, alsa-devel; +Cc: Liam Girdwood, Mark Brown, Jie Yang


On 12/9/18 3:33 AM, Takashi Iwai wrote:
> Since snd_hdac_display_power() can be called even for a HDA controller
> without DRM binding, lots of superfluous AZX_DCAPS_I915_POWERWELL
> checks in hda_intel.c can be dropped.  This simplifies the code a
> lot.
>
> Signed-off-by: Takashi Iwai <tiwai@suse.de>
> ---
>   sound/pci/hda/hda_intel.c | 43 +++++++++++++++------------------------
>   1 file changed, 16 insertions(+), 27 deletions(-)
>
> diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
> index 151c6ca85ec6..cacee33a74a8 100644
> --- a/sound/pci/hda/hda_intel.c
> +++ b/sound/pci/hda/hda_intel.c
> @@ -948,9 +948,7 @@ static void __azx_runtime_suspend(struct azx *chip)
>   	azx_stop_chip(chip);
>   	azx_enter_link_reset(chip);
>   	azx_clear_irq_pending(chip);
> -	if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) &&
> -	    hda->need_i915_power)
> -		display_power(chip, false);
> +	display_power(chip, false);
>   }
>   
>   static void __azx_runtime_resume(struct azx *chip)
> @@ -960,11 +958,9 @@ static void __azx_runtime_resume(struct azx *chip)
>   	struct hda_codec *codec;
>   	int status;
>   
> -	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
> -		display_power(chip, true);
> -		if (hda->need_i915_power)
> -			snd_hdac_i915_set_bclk(bus);
> -	}
> +	display_power(chip, true);
> +	if (hda->need_i915_power)
> +		snd_hdac_i915_set_bclk(bus);

Question: I still see this 'old style' init in hda_intel.c even with all 
the patches applied.

     /* initialize chip */
     azx_init_pci(chip);

     if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
         snd_hdac_i915_set_bclk(bus);

is this intentional or a miss?


_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/7] ALSA: hda: Refactor display power management
  2018-12-10 20:52   ` Pierre-Louis Bossart
@ 2018-12-11  6:54     ` Takashi Iwai
  2018-12-11 13:58       ` Pierre-Louis Bossart
  0 siblings, 1 reply; 16+ messages in thread
From: Takashi Iwai @ 2018-12-11  6:54 UTC (permalink / raw)
  To: Pierre-Louis Bossart; +Cc: Liam Girdwood, alsa-devel, Mark Brown, Jie Yang

On Mon, 10 Dec 2018 21:52:05 +0100,
Pierre-Louis Bossart wrote:
> 
> 
> On 12/9/18 3:33 AM, Takashi Iwai wrote:
> > The current HD-audio code manages the DRM audio power via too complex
> > redirections, and this seems even still unbalanced in a corner case as
> > Intel DRM CI has been intermittently reporting.  This patch is a big
> > surgery for addressing the complexity and the possible unbalance.
> >
> > Basically the patch changes the display PM in the following ways:
> >
> > - Both HD-audio controller and codec drivers call a single helper,
> >    snd_hdac_display_power().  (Formerly, the display power control from
> >    a codec was done indirectly via link_power bus ops.)
> >
> > - snd_hdac_display_power() receives the codec address index.  For
> >    turning on/off from the controller, pass HDA_CODEC_IDX_CONTROLLER.
> 
> The need for this virtual index==16 isn't fully clear to me,
> especially if you use the bitfields instead of reference counts.
> 
> Isn't there a risk of the controller setting the bit16 to zero, but
> you still have bit4 on (assuming the idx is 4). If you use this
> virtual index, it should override the actual physical bits when
> set/cleared.

This is the index for a controller, i.e. we'd need bits for the max
number of codecs + 1.

Actually we do support only up to 8 codecs (HDA_MAX_CODECS), so it
should be 8, instead of 16, too.  I'll update to be HDA_MAX_CODECS.

> Or is this meant to actually implement a preemption mechanism, where
> the display power remains on for as long as the controller wishes,
> regardless of what the patch_hdmi and hdac_hdmi code requests?

Right.  That's the mechanism at the initial phase, we need the display
power on while probing the codec, i.e. before identifying the codec
ID.

> Also don't we already have the HDMI codec address already after the
> probe, so couldn't we provide the address directly?

The resume seemed requiring the controller to take the display power
at first, so the same mechanism is used.


thanks,

Takashi

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 3/7] ALSA: hda/intel: Drop superfluous AZX_DCAPS_I915_POWERWELL checks
  2018-12-10 20:56   ` Pierre-Louis Bossart
@ 2018-12-11  7:00     ` Takashi Iwai
  0 siblings, 0 replies; 16+ messages in thread
From: Takashi Iwai @ 2018-12-11  7:00 UTC (permalink / raw)
  To: Pierre-Louis Bossart; +Cc: Liam Girdwood, alsa-devel, Mark Brown, Jie Yang

On Mon, 10 Dec 2018 21:56:15 +0100,
Pierre-Louis Bossart wrote:
> 
> 
> On 12/9/18 3:33 AM, Takashi Iwai wrote:
> > Since snd_hdac_display_power() can be called even for a HDA controller
> > without DRM binding, lots of superfluous AZX_DCAPS_I915_POWERWELL
> > checks in hda_intel.c can be dropped.  This simplifies the code a
> > lot.
> >
> > Signed-off-by: Takashi Iwai <tiwai@suse.de>
> > ---
> >   sound/pci/hda/hda_intel.c | 43 +++++++++++++++------------------------
> >   1 file changed, 16 insertions(+), 27 deletions(-)
> >
> > diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
> > index 151c6ca85ec6..cacee33a74a8 100644
> > --- a/sound/pci/hda/hda_intel.c
> > +++ b/sound/pci/hda/hda_intel.c
> > @@ -948,9 +948,7 @@ static void __azx_runtime_suspend(struct azx *chip)
> >   	azx_stop_chip(chip);
> >   	azx_enter_link_reset(chip);
> >   	azx_clear_irq_pending(chip);
> > -	if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) &&
> > -	    hda->need_i915_power)
> > -		display_power(chip, false);
> > +	display_power(chip, false);
> >   }
> >     static void __azx_runtime_resume(struct azx *chip)
> > @@ -960,11 +958,9 @@ static void __azx_runtime_resume(struct azx *chip)
> >   	struct hda_codec *codec;
> >   	int status;
> >   -	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
> > -		display_power(chip, true);
> > -		if (hda->need_i915_power)
> > -			snd_hdac_i915_set_bclk(bus);
> > -	}
> > +	display_power(chip, true);
> > +	if (hda->need_i915_power)
> > +		snd_hdac_i915_set_bclk(bus);
> 
> Question: I still see this 'old style' init in hda_intel.c even with
> all the patches applied.
> 
>     /* initialize chip */
>     azx_init_pci(chip);
> 
>     if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
>         snd_hdac_i915_set_bclk(bus);
> 
> is this intentional or a miss?

It's intentional.  The purpose of the patch isn't to eliminate the
whole DCAPS_I915_POWERWELL checks, but remove the checks that are
relevant with snd_hdac_display_power() calls.  In the changes, some
calls are reduced with only hda->need_i915 check, which is safe since
need_i915 mandates AZX_DCAPS_I915_POWERWELL.

Though, actually, snd_hdac_i915_set_bclk() can be called safely for
the case without GPU binding, too.  So it's fine to get rid of the
AZX_DCAPS check there, too.


thanks,

Takashi
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/7] ALSA: hda: Refactor display power management
  2018-12-11  6:54     ` Takashi Iwai
@ 2018-12-11 13:58       ` Pierre-Louis Bossart
  2018-12-11 14:04         ` Takashi Iwai
  0 siblings, 1 reply; 16+ messages in thread
From: Pierre-Louis Bossart @ 2018-12-11 13:58 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: Liam Girdwood, alsa-devel, Mark Brown, Jie Yang


On 12/11/18 12:54 AM, Takashi Iwai wrote:
> On Mon, 10 Dec 2018 21:52:05 +0100,
> Pierre-Louis Bossart wrote:
>>
>> On 12/9/18 3:33 AM, Takashi Iwai wrote:
>>> The current HD-audio code manages the DRM audio power via too complex
>>> redirections, and this seems even still unbalanced in a corner case as
>>> Intel DRM CI has been intermittently reporting.  This patch is a big
>>> surgery for addressing the complexity and the possible unbalance.
>>>
>>> Basically the patch changes the display PM in the following ways:
>>>
>>> - Both HD-audio controller and codec drivers call a single helper,
>>>     snd_hdac_display_power().  (Formerly, the display power control from
>>>     a codec was done indirectly via link_power bus ops.)
>>>
>>> - snd_hdac_display_power() receives the codec address index.  For
>>>     turning on/off from the controller, pass HDA_CODEC_IDX_CONTROLLER.
>> The need for this virtual index==16 isn't fully clear to me,
>> especially if you use the bitfields instead of reference counts.
>>
>> Isn't there a risk of the controller setting the bit16 to zero, but
>> you still have bit4 on (assuming the idx is 4). If you use this
>> virtual index, it should override the actual physical bits when
>> set/cleared.
> This is the index for a controller, i.e. we'd need bits for the max
> number of codecs + 1.
>
> Actually we do support only up to 8 codecs (HDA_MAX_CODECS), so it
> should be 8, instead of 16, too.  I'll update to be HDA_MAX_CODECS.
>
>> Or is this meant to actually implement a preemption mechanism, where
>> the display power remains on for as long as the controller wishes,
>> regardless of what the patch_hdmi and hdac_hdmi code requests?
> Right.  That's the mechanism at the initial phase, we need the display
> power on while probing the codec, i.e. before identifying the codec
> ID.
>
>> Also don't we already have the HDMI codec address already after the
>> probe, so couldn't we provide the address directly?
> The resume seemed requiring the controller to take the display power
> at first, so the same mechanism is used.

ok, makes sense, thanks for the explanations.

So I guess for the SOF patches, the only change would be to add the 
second argument HDA_CODEC_IDX_CONTROLLER to snd_hdac_display_power() 
calls, the rest looks unchanged or hidden inside the hdac library or 
hdac_hdmi parts.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/7] ALSA: hda: Refactor display power management
  2018-12-11 13:58       ` Pierre-Louis Bossart
@ 2018-12-11 14:04         ` Takashi Iwai
  2018-12-11 14:34           ` Pierre-Louis Bossart
  0 siblings, 1 reply; 16+ messages in thread
From: Takashi Iwai @ 2018-12-11 14:04 UTC (permalink / raw)
  To: Pierre-Louis Bossart; +Cc: Liam Girdwood, alsa-devel, Mark Brown, Jie Yang

On Tue, 11 Dec 2018 14:58:37 +0100,
Pierre-Louis Bossart wrote:
> 
> 
> On 12/11/18 12:54 AM, Takashi Iwai wrote:
> > On Mon, 10 Dec 2018 21:52:05 +0100,
> > Pierre-Louis Bossart wrote:
> >>
> >> On 12/9/18 3:33 AM, Takashi Iwai wrote:
> >>> The current HD-audio code manages the DRM audio power via too complex
> >>> redirections, and this seems even still unbalanced in a corner case as
> >>> Intel DRM CI has been intermittently reporting.  This patch is a big
> >>> surgery for addressing the complexity and the possible unbalance.
> >>>
> >>> Basically the patch changes the display PM in the following ways:
> >>>
> >>> - Both HD-audio controller and codec drivers call a single helper,
> >>>     snd_hdac_display_power().  (Formerly, the display power control from
> >>>     a codec was done indirectly via link_power bus ops.)
> >>>
> >>> - snd_hdac_display_power() receives the codec address index.  For
> >>>     turning on/off from the controller, pass HDA_CODEC_IDX_CONTROLLER.
> >> The need for this virtual index==16 isn't fully clear to me,
> >> especially if you use the bitfields instead of reference counts.
> >>
> >> Isn't there a risk of the controller setting the bit16 to zero, but
> >> you still have bit4 on (assuming the idx is 4). If you use this
> >> virtual index, it should override the actual physical bits when
> >> set/cleared.
> > This is the index for a controller, i.e. we'd need bits for the max
> > number of codecs + 1.
> >
> > Actually we do support only up to 8 codecs (HDA_MAX_CODECS), so it
> > should be 8, instead of 16, too.  I'll update to be HDA_MAX_CODECS.
> >
> >> Or is this meant to actually implement a preemption mechanism, where
> >> the display power remains on for as long as the controller wishes,
> >> regardless of what the patch_hdmi and hdac_hdmi code requests?
> > Right.  That's the mechanism at the initial phase, we need the display
> > power on while probing the codec, i.e. before identifying the codec
> > ID.
> >
> >> Also don't we already have the HDMI codec address already after the
> >> probe, so couldn't we provide the address directly?
> > The resume seemed requiring the controller to take the display power
> > at first, so the same mechanism is used.
> 
> ok, makes sense, thanks for the explanations.
> 
> So I guess for the SOF patches, the only change would be to add the
> second argument HDA_CODEC_IDX_CONTROLLER to snd_hdac_display_power()
> calls, the rest looks unchanged or hidden inside the hdac library or
> hdac_hdmi parts.

Yes, other than that, this change makes things easier.

Since we don't manage with refcount, the only important point is to
turn off/on properly at suspend/resume (also off at remove), no matter
how many times it gets called.


thanks,

Takashi

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/7] ALSA: hda: Refactor display power management
  2018-12-11 14:04         ` Takashi Iwai
@ 2018-12-11 14:34           ` Pierre-Louis Bossart
  0 siblings, 0 replies; 16+ messages in thread
From: Pierre-Louis Bossart @ 2018-12-11 14:34 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: Liam Girdwood, alsa-devel, Mark Brown, Jie Yang


>>>>>      a codec was done indirectly via link_power bus ops.)
>>>>>
>>>>> - snd_hdac_display_power() receives the codec address index.  For
>>>>>      turning on/off from the controller, pass HDA_CODEC_IDX_CONTROLLER.
>>>> The need for this virtual index==16 isn't fully clear to me,
>>>> especially if you use the bitfields instead of reference counts.
>>>>
>>>> Isn't there a risk of the controller setting the bit16 to zero, but
>>>> you still have bit4 on (assuming the idx is 4). If you use this
>>>> virtual index, it should override the actual physical bits when
>>>> set/cleared.
>>> This is the index for a controller, i.e. we'd need bits for the max
>>> number of codecs + 1.
>>>
>>> Actually we do support only up to 8 codecs (HDA_MAX_CODECS), so it
>>> should be 8, instead of 16, too.  I'll update to be HDA_MAX_CODECS.
>>>
>>>> Or is this meant to actually implement a preemption mechanism, where
>>>> the display power remains on for as long as the controller wishes,
>>>> regardless of what the patch_hdmi and hdac_hdmi code requests?
>>> Right.  That's the mechanism at the initial phase, we need the display
>>> power on while probing the codec, i.e. before identifying the codec
>>> ID.
>>>
>>>> Also don't we already have the HDMI codec address already after the
>>>> probe, so couldn't we provide the address directly?
>>> The resume seemed requiring the controller to take the display power
>>> at first, so the same mechanism is used.
>> ok, makes sense, thanks for the explanations.
>>
>> So I guess for the SOF patches, the only change would be to add the
>> second argument HDA_CODEC_IDX_CONTROLLER to snd_hdac_display_power()
>> calls, the rest looks unchanged or hidden inside the hdac library or
>> hdac_hdmi parts.
> Yes, other than that, this change makes things easier.
>
> Since we don't manage with refcount, the only important point is to
> turn off/on properly at suspend/resume (also off at remove), no matter
> how many times it gets called.
Ah yes, we are missing this on remove since we assumed the refcount 
would already be zero. I guess we'll have to revalidate this part 
anyways once your patches are merged (already have an SOF issue filed to 
track this change).

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2018-12-11 14:34 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-12-09  9:33 [PATCH 0/7] ALSA: HD-audio display power fixes Takashi Iwai
2018-12-09  9:33 ` [PATCH 1/7] ALSA: hda/intel: Refactoring PM code Takashi Iwai
2018-12-09  9:33 ` [PATCH 2/7] ALSA: hda: Refactor display power management Takashi Iwai
2018-12-10 20:52   ` Pierre-Louis Bossart
2018-12-11  6:54     ` Takashi Iwai
2018-12-11 13:58       ` Pierre-Louis Bossart
2018-12-11 14:04         ` Takashi Iwai
2018-12-11 14:34           ` Pierre-Louis Bossart
2018-12-09  9:33 ` [PATCH 3/7] ALSA: hda/intel: Drop superfluous AZX_DCAPS_I915_POWERWELL checks Takashi Iwai
2018-12-10 20:56   ` Pierre-Louis Bossart
2018-12-11  7:00     ` Takashi Iwai
2018-12-09  9:33 ` [PATCH 4/7] ALSA: hda/intel: Properly free the display power at error path Takashi Iwai
2018-12-09  9:33 ` [PATCH 5/7] ALSA: hda: Make snd_hdac_display_power() void function Takashi Iwai
2018-12-09  9:33 ` [PATCH 6/7] ASoC: hdac_hdmi: Add missing display power-off at driver removal Takashi Iwai
2018-12-10 14:33   ` Mark Brown
2018-12-09  9:33 ` [PATCH 7/7] ALSA: hda/hdmi: Always set display_power_control for Intel HSW+ codecs Takashi Iwai

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.