drm/i915: Add heuristic to determine better way to adjust brightness
authorPuthikorn Voravootivat <puthik@chromium.org>
Thu, 22 Jun 2017 19:03:38 +0000 (12:03 -0700)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Fri, 23 Jun 2017 10:24:49 +0000 (12:24 +0200)
Add heuristic to decide that AUX or PWM pin should use for
backlight brightness adjustment and modify i915 param description
to have auto, force disable, and force enable.

The heuristic to determine that using AUX pin is better than using
PWM pin is that the panel support any of the feature list here.
- Regional backlight brightness adjustment
- Backlight PWM frequency set
- More than 8 bits resolution of brightness level
- Backlight enablement via AUX and not by BL_ENABLE pin

Signed-off-by: Puthikorn Voravootivat <puthik@chromium.org>
Reviewed-by: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/20170622190339.142671-3-puthik@chromium.org
drivers/gpu/drm/i915/i915_params.c
drivers/gpu/drm/i915/i915_params.h
drivers/gpu/drm/i915/intel_dp_aux_backlight.c

index 14e2c2e57f96a53f2fdddd8ecf897c3d28a4ddce..5b5ab15d191f819bfaa2134305655a6a320a050c 100644 (file)
@@ -63,7 +63,7 @@ struct i915_params i915 __read_mostly = {
        .huc_firmware_path = NULL,
        .enable_dp_mst = true,
        .inject_load_failure = 0,
-       .enable_dpcd_backlight = false,
+       .enable_dpcd_backlight = -1,
        .enable_gvt = false,
 };
 
@@ -246,9 +246,10 @@ MODULE_PARM_DESC(enable_dp_mst,
 module_param_named_unsafe(inject_load_failure, i915.inject_load_failure, uint, 0400);
 MODULE_PARM_DESC(inject_load_failure,
        "Force an error after a number of failure check points (0:disabled (default), N:force failure at the Nth failure check point)");
-module_param_named(enable_dpcd_backlight, i915.enable_dpcd_backlight, bool, 0600);
+module_param_named_unsafe(enable_dpcd_backlight, i915.enable_dpcd_backlight, int, 0600);
 MODULE_PARM_DESC(enable_dpcd_backlight,
-       "Enable support for DPCD backlight control (default:false)");
+       "Enable support for DPCD backlight control "
+       "(-1:auto (default), 0:force disable, 1:force enabled if supported");
 
 module_param_named(enable_gvt, i915.enable_gvt, bool, 0400);
 MODULE_PARM_DESC(enable_gvt,
index febbfdbd30bdb179ec310af6e5c7c1a54944d4db..0d6cf9138dc4ba3553ca156a10c8d5a522c18507 100644 (file)
@@ -53,6 +53,7 @@
        func(int, edp_vswing); \
        func(int, reset); \
        func(unsigned int, inject_load_failure); \
+       func(int, enable_dpcd_backlight); \
        /* leave bools at the end to not create holes */ \
        func(bool, alpha_support); \
        func(bool, enable_cmd_parser); \
@@ -66,7 +67,6 @@
        func(bool, verbose_state_checks); \
        func(bool, nuclear_pageflip); \
        func(bool, enable_dp_mst); \
-       func(bool, enable_dpcd_backlight); \
        func(bool, enable_gvt)
 
 #define MEMBER(T, member) T member
index d2830ba3162e1a66cc976d639995bb8b09954bae..fea161727c6effefbd639fa10bdefa729a19571a 100644 (file)
@@ -251,15 +251,66 @@ intel_dp_aux_display_control_capable(struct intel_connector *connector)
        /* Check the eDP Display control capabilities registers to determine if
         * the panel can support backlight control over the aux channel
         */
-       if (intel_dp->edp_dpcd[1] & DP_EDP_TCON_BACKLIGHT_ADJUSTMENT_CAP &&
-           (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP) &&
-           !(intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_PWM_PIN_CAP)) {
+       if ((intel_dp->edp_dpcd[1] & DP_EDP_TCON_BACKLIGHT_ADJUSTMENT_CAP) &&
+           (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP)) {
                DRM_DEBUG_KMS("AUX Backlight Control Supported!\n");
                return true;
        }
        return false;
 }
 
+/*
+ * Heuristic function whether we should use AUX for backlight adjustment or not.
+ *
+ * We should use AUX for backlight brightness adjustment if panel doesn't this
+ * via PWM pin or using AUX is better than using PWM pin.
+ *
+ * The heuristic to determine that using AUX pin is better than using PWM pin is
+ * that the panel support any of the feature list here.
+ * - Regional backlight brightness adjustment
+ * - Backlight PWM frequency set
+ * - More than 8 bits resolution of brightness level
+ * - Backlight enablement via AUX and not by BL_ENABLE pin
+ *
+ * If all above are not true, assume that using PWM pin is better.
+ */
+static bool
+intel_dp_aux_display_control_heuristic(struct intel_connector *connector)
+{
+       struct intel_dp *intel_dp = enc_to_intel_dp(&connector->encoder->base);
+       uint8_t reg_val;
+
+       /* Panel doesn't support adjusting backlight brightness via PWN pin */
+       if (!(intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_PWM_PIN_CAP))
+               return true;
+
+       /* Panel supports regional backlight brightness adjustment */
+       if (drm_dp_dpcd_readb(&intel_dp->aux, DP_EDP_GENERAL_CAP_3,
+                             &reg_val) != 1) {
+               DRM_DEBUG_KMS("Failed to read DPCD register 0x%x\n",
+                              DP_EDP_GENERAL_CAP_3);
+               return false;
+       }
+       if (reg_val > 0)
+               return true;
+
+       /* Panel supports backlight PWM frequency set */
+       if (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_FREQ_AUX_SET_CAP)
+               return true;
+
+       /* Panel supports more than 8 bits resolution of brightness level */
+       if (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT)
+               return true;
+
+       /* Panel supports enabling backlight via AUX but not by BL_ENABLE pin */
+       if ((intel_dp->edp_dpcd[1] & DP_EDP_BACKLIGHT_AUX_ENABLE_CAP) &&
+           !(intel_dp->edp_dpcd[1] & DP_EDP_BACKLIGHT_PIN_ENABLE_CAP))
+               return true;
+
+       return false;
+
+}
+
 int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector)
 {
        struct intel_panel *panel = &intel_connector->panel;
@@ -270,6 +321,10 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector)
        if (!intel_dp_aux_display_control_capable(intel_connector))
                return -ENODEV;
 
+       if (i915.enable_dpcd_backlight == -1 &&
+           !intel_dp_aux_display_control_heuristic(intel_connector))
+               return -ENODEV;
+
        panel->backlight.setup = intel_dp_aux_setup_backlight;
        panel->backlight.enable = intel_dp_aux_enable_backlight;
        panel->backlight.disable = intel_dp_aux_disable_backlight;