[v2,5/5] drm/i915/opregion: update cadl based on actually active outputs

Submitted by Jani Nikula on June 13, 2016, 9:30 a.m.

Details

Message ID a53350490cca15ad1a64f604fed19bd347922011.1465810007.git.jani.nikula@intel.com
State New
Headers show
Series "drm/i915/opregion: proper handling of DIDL and CADL" ( rev: 2 ) in Intel GFX

Not browsing as part of any series.

Commit Message

Jani Nikula June 13, 2016, 9:30 a.m.
Previously we've just shoved the first eight devices in DIDL to CADL
(list of active outputs). Some of the active outputs may have been left
outside of CADL. The problem is, some BIOS implementations prevent
laptop brightness hotkey propagation if the flat panel is not active.

Now that we have connector to acpi device id mapping covered, we can
update CADL based on which outputs are actually active.

Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Reviewed-and-tested-by: Peter Wu <peter@lekensteyn.nl>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h       |  2 +
 drivers/gpu/drm/i915/intel_display.c  |  2 +
 drivers/gpu/drm/i915/intel_opregion.c | 70 ++++++++++++++++++-----------------
 3 files changed, 41 insertions(+), 33 deletions(-)

Patch hide | download patch | download mbox

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 53d9e3fab489..148c47ae38f3 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3646,6 +3646,7 @@  extern int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,
 extern int intel_opregion_notify_adapter(struct drm_i915_private *dev_priv,
 					 pci_power_t state);
 extern int intel_opregion_get_panel_type(struct drm_i915_private *dev_priv);
+extern void intel_opregion_update_cadl(struct drm_i915_private *dev_priv);
 #else
 static inline int intel_opregion_setup(struct drm_i915_private *dev) { return 0; }
 static inline void intel_opregion_init(struct drm_i915_private *dev) { }
@@ -3667,6 +3668,7 @@  static inline int intel_opregion_get_panel_type(struct drm_i915_private *dev)
 {
 	return -ENODEV;
 }
+static inline void intel_opregion_update_cadl(struct drm_i915_private *dev_priv) { return; }
 #endif
 
 /* intel_acpi.c */
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 801e4c17dd8d..7d6d6746a22a 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13833,6 +13833,8 @@  static int intel_atomic_commit(struct drm_device *dev,
 
 	drm_atomic_state_free(state);
 
+	intel_opregion_update_cadl(dev);
+
 	/* As one of the primary mmio accessors, KMS has a high likelihood
 	 * of triggering bugs in unclaimed access. After we finish
 	 * modesetting, see if an error has been flagged, and if so
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
index 632f0178c2b0..8b3f7e6ae4bb 100644
--- a/drivers/gpu/drm/i915/intel_opregion.c
+++ b/drivers/gpu/drm/i915/intel_opregion.c
@@ -642,24 +642,6 @@  static struct notifier_block intel_opregion_notifier = {
  * (version 3)
  */
 
-static u32 get_did(struct intel_opregion *opregion, int i)
-{
-	u32 did;
-
-	if (i < ARRAY_SIZE(opregion->acpi->didl)) {
-		did = opregion->acpi->didl[i];
-	} else {
-		i -= ARRAY_SIZE(opregion->acpi->didl);
-
-		if (WARN_ON(i >= ARRAY_SIZE(opregion->acpi->did2)))
-			return 0;
-
-		did = opregion->acpi->did2[i];
-	}
-
-	return did;
-}
-
 static void set_did(struct intel_opregion *opregion, int i, u32 val)
 {
 	if (i < ARRAY_SIZE(opregion->acpi->didl)) {
@@ -674,6 +656,14 @@  static void set_did(struct intel_opregion *opregion, int i, u32 val)
 	}
 }
 
+static void set_cad(struct intel_opregion *opregion, int i, u32 val)
+{
+	if (WARN_ON(i >= ARRAY_SIZE(opregion->acpi->cadl)))
+		return;
+
+	opregion->acpi->cadl[i] = val;
+}
+
 static u32 acpi_display_type(struct intel_connector *connector)
 {
 	u32 display_type;
@@ -759,22 +749,36 @@  static void intel_didl_outputs(struct drm_i915_private *dev_priv)
 		set_did(opregion, i, 0);
 }
 
-static void intel_setup_cadls(struct drm_i915_private *dev_priv)
+/* Update CADL to reflect active outputs. */
+void intel_opregion_update_cadl(struct drm_i915_private *dev_priv)
 {
 	struct intel_opregion *opregion = &dev_priv->opregion;
-	int i = 0;
-	u32 disp_id;
-
-	/* Initialize the CADL field by duplicating the DIDL values.
-	 * Technically, this is not always correct as display outputs may exist,
-	 * but not active. This initialization is necessary for some Clevo
-	 * laptops that check this field before processing the brightness and
-	 * display switching hotkeys. Just like DIDL, CADL is NULL-terminated if
-	 * there are less than eight devices. */
-	do {
-		disp_id = get_did(opregion, i);
-		opregion->acpi->cadl[i] = disp_id;
-	} while (++i < 8 && disp_id != 0);
+	struct intel_crtc *crtc;
+	int i = 0, max_active = ARRAY_SIZE(opregion->acpi->cadl);
+
+	for_each_intel_crtc(dev_priv->dev, crtc) {
+		struct intel_encoder *encoder;
+
+		if (!crtc->active)
+			continue;
+
+		for_each_encoder_on_crtc(dev_priv->dev, &crtc->base, encoder) {
+			struct intel_connector *connector;
+
+			for_each_connector_on_encoder(dev_priv->dev, &encoder->base, connector) {
+				if (i >= max_active) {
+					DRM_DEBUG_KMS("too many outputs active\n");
+					return;
+				}
+
+				set_cad(opregion, i++, connector->acpi_device_id);
+			}
+		}
+	}
+
+	/* If fewer than max active outputs, the list must be null terminated */
+	if (i < max_active)
+		set_cad(opregion, i, 0);
 }
 
 void intel_opregion_register(struct drm_i915_private *dev_priv)
@@ -786,7 +790,7 @@  void intel_opregion_register(struct drm_i915_private *dev_priv)
 
 	if (opregion->acpi) {
 		intel_didl_outputs(dev_priv);
-		intel_setup_cadls(dev_priv);
+		intel_opregion_update_cadl(dev_priv);
 
 		/* Notify BIOS we are ready to handle ACPI video ext notifs.
 		 * Right now, all the events are handled by the ACPI video module.

Comments

Hi,

[auto build test ERROR on drm-intel/for-linux-next]
[also build test ERROR on next-20160609]
[cannot apply to v4.7-rc3]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Jani-Nikula/drm-i915-opregion-proper-handling-of-DIDL-and-CADL/20160613-173347
base:   git://anongit.freedesktop.org/drm-intel for-linux-next
config: x86_64-allmodconfig (attached as .config)
compiler: gcc-6 (Debian 6.1.1-1) 6.1.1 20160430
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

   drivers/gpu/drm/i915/intel_display.c: In function 'intel_atomic_commit':
>> drivers/gpu/drm/i915/intel_display.c:13836:29: error: passing argument 1 of 'intel_opregion_update_cadl' from incompatible pointer type [-Werror=incompatible-pointer-types]
     intel_opregion_update_cadl(dev);
                                ^~~
   In file included from drivers/gpu/drm/i915/intel_drv.h:32:0,
                    from drivers/gpu/drm/i915/intel_display.c:36:
   drivers/gpu/drm/i915/i915_drv.h:3666:13: note: expected 'struct drm_i915_private *' but argument is of type 'struct drm_device *'
    extern void intel_opregion_update_cadl(struct drm_i915_private *dev_priv);
                ^~~~~~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +/intel_opregion_update_cadl +13836 drivers/gpu/drm/i915/intel_display.c

 13830		mutex_lock(&dev->struct_mutex);
 13831		drm_atomic_helper_cleanup_planes(dev, state);
 13832		mutex_unlock(&dev->struct_mutex);
 13833	
 13834		drm_atomic_state_free(state);
 13835	
 13836		intel_opregion_update_cadl(dev);
 13837	
 13838		/* As one of the primary mmio accessors, KMS has a high likelihood
 13839		 * of triggering bugs in unclaimed access. After we finish

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
Hi,

[auto build test WARNING on drm-intel/for-linux-next]
[also build test WARNING on next-20160609]
[cannot apply to v4.7-rc3]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Jani-Nikula/drm-i915-opregion-proper-handling-of-DIDL-and-CADL/20160613-173347
base:   git://anongit.freedesktop.org/drm-intel for-linux-next
config: x86_64-rhel (attached as .config)
compiler: gcc-4.9 (Debian 4.9.3-14) 4.9.3
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All warnings (new ones prefixed by >>):

   drivers/gpu/drm/i915/intel_display.c: In function 'intel_atomic_commit':
>> drivers/gpu/drm/i915/intel_display.c:13836:29: warning: passing argument 1 of 'intel_opregion_update_cadl' from incompatible pointer type
     intel_opregion_update_cadl(dev);
                                ^
   In file included from drivers/gpu/drm/i915/intel_drv.h:32:0,
                    from drivers/gpu/drm/i915/intel_display.c:36:
   drivers/gpu/drm/i915/i915_drv.h:3666:13: note: expected 'struct drm_i915_private *' but argument is of type 'struct drm_device *'
    extern void intel_opregion_update_cadl(struct drm_i915_private *dev_priv);
                ^

vim +/intel_opregion_update_cadl +13836 drivers/gpu/drm/i915/intel_display.c

 13820	
 13821			if (put_domains[i])
 13822				modeset_put_power_domains(dev_priv, put_domains[i]);
 13823	
 13824			intel_modeset_verify_crtc(crtc, old_crtc_state, crtc->state);
 13825		}
 13826	
 13827		if (intel_state->modeset)
 13828			intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET);
 13829	
 13830		mutex_lock(&dev->struct_mutex);
 13831		drm_atomic_helper_cleanup_planes(dev, state);
 13832		mutex_unlock(&dev->struct_mutex);
 13833	
 13834		drm_atomic_state_free(state);
 13835	
 13836		intel_opregion_update_cadl(dev);
 13837	
 13838		/* As one of the primary mmio accessors, KMS has a high likelihood
 13839		 * of triggering bugs in unclaimed access. After we finish
 13840		 * modesetting, see if an error has been flagged, and if so
 13841		 * enable debugging for the next modeset - and hope we catch
 13842		 * the culprit.
 13843		 *
 13844		 * XXX note that we assume display power is on at this point.

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation