From patchwork Fri Oct 11 15:28:21 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Aaron Ma X-Patchwork-Id: 1175280 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46qX0m5fZTz9sPw; Sat, 12 Oct 2019 02:28:39 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1iIwqG-0002qJ-SM; Fri, 11 Oct 2019 15:28:32 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1iIwqE-0002pq-9K for kernel-team@lists.ubuntu.com; Fri, 11 Oct 2019 15:28:30 +0000 Received: from [114.245.47.25] (helo=localhost.localdomain) by youngberry.canonical.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1iIwqD-0004iz-Hn for kernel-team@lists.ubuntu.com; Fri, 11 Oct 2019 15:28:30 +0000 From: Aaron Ma To: kernel-team@lists.ubuntu.com Subject: [PATCH 1/2] UBUNTU: SAUCE: i915: intel_dp_aux_backlight: Fix max backlight calculations Date: Fri, 11 Oct 2019 23:28:21 +0800 Message-Id: <20191011152822.26495-2-aaron.ma@canonical.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191011152822.26495-1-aaron.ma@canonical.com> References: <20191011152822.26495-1-aaron.ma@canonical.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Furquan Shaikh BugLink: https://bugs.launchpad.net/bugs/1844798 Max backlight value for the panel was being calculated using byte count i.e. 0xffff if 2 bytes are supported for backlight brightness and 0xff if 1 byte is supported. However, EDP_PWMGEN_BIT_COUNT determines the number of active control bits used for the brightness setting. Thus, even if the panel uses 2 byte setting, it might not use all the control bits. Thus, max backlight should be set based on the value of EDP_PWMGEN_BIT_COUNT instead of assuming 65535 or 255. Additionally, EDP_PWMGEN_BIT_COUNT was being updated based on the VBT frequency which results in a different max backlight value. Thus, setting of EDP_PWMGEN_BIT_COUNT is moved to setup phase instead of enable so that max backlight can be calculated correctly. Only the frequency divider is set during the enable phase using the value of EDP_PWMGEN_BIT_COUNT. v2: In case of DPCD failure and pn being uninitialized, return max_backlight as 0. Signed-off-by: Furquan Shaikh Reviewed-by: Stéphane Marchesin Link: https://patchwork.kernel.org/patch/11039395 Signed-off-by: Aaron Ma --- drivers/gpu/drm/i915/intel_dp_aux_backlight.c | 135 ++++++++++++------ 1 file changed, 90 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/intel_dp_aux_backlight.c index 2bb2ceb9d463..cbf61ac2910d 100644 --- a/drivers/gpu/drm/i915/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/intel_dp_aux_backlight.c @@ -110,61 +110,34 @@ static bool intel_dp_aux_set_pwm_freq(struct intel_connector *connector) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_dp *intel_dp = enc_to_intel_dp(&connector->encoder->base); - int freq, fxp, fxp_min, fxp_max, fxp_actual, f = 1; - u8 pn, pn_min, pn_max; + int freq, fxp, f, fxp_actual, fxp_min, fxp_max; + u8 pn; - /* Find desired value of (F x P) - * Note that, if F x P is out of supported range, the maximum value or - * minimum value will applied automatically. So no need to check that. - */ freq = dev_priv->vbt.backlight.pwm_freq_hz; - DRM_DEBUG_KMS("VBT defined backlight frequency %u Hz\n", freq); if (!freq) { DRM_DEBUG_KMS("Use panel default backlight frequency\n"); return false; } - fxp = DIV_ROUND_CLOSEST(KHz(DP_EDP_BACKLIGHT_FREQ_BASE_KHZ), freq); - - /* Use highest possible value of Pn for more granularity of brightness - * adjustment while satifying the conditions below. - * - Pn is in the range of Pn_min and Pn_max - * - F is in the range of 1 and 255 - * - FxP is within 25% of desired value. - * Note: 25% is arbitrary value and may need some tweak. - */ - if (drm_dp_dpcd_readb(&intel_dp->aux, - DP_EDP_PWMGEN_BIT_COUNT_CAP_MIN, &pn_min) != 1) { - DRM_DEBUG_KMS("Failed to read pwmgen bit count cap min\n"); + if (drm_dp_dpcd_readb(&intel_dp->aux, DP_EDP_PWMGEN_BIT_COUNT, + &pn) < 0) { + DRM_DEBUG_KMS("Failed to read aux pwmgen bit count\n"); return false; } - if (drm_dp_dpcd_readb(&intel_dp->aux, - DP_EDP_PWMGEN_BIT_COUNT_CAP_MAX, &pn_max) != 1) { - DRM_DEBUG_KMS("Failed to read pwmgen bit count cap max\n"); - return false; - } - pn_min &= DP_EDP_PWMGEN_BIT_COUNT_MASK; - pn_max &= DP_EDP_PWMGEN_BIT_COUNT_MASK; + fxp = DIV_ROUND_CLOSEST(KHz(DP_EDP_BACKLIGHT_FREQ_BASE_KHZ), freq); + f = clamp(DIV_ROUND_CLOSEST(fxp, 1 << pn), 1, 255); + fxp_actual = f << pn; + + /* Ensure frequency is within 25% of desired value */ fxp_min = DIV_ROUND_CLOSEST(fxp * 3, 4); fxp_max = DIV_ROUND_CLOSEST(fxp * 5, 4); - if (fxp_min < (1 << pn_min) || (255 << pn_max) < fxp_max) { - DRM_DEBUG_KMS("VBT defined backlight frequency out of range\n"); - return false; - } - - for (pn = pn_max; pn >= pn_min; pn--) { - f = clamp(DIV_ROUND_CLOSEST(fxp, 1 << pn), 1, 255); - fxp_actual = f << pn; - if (fxp_min <= fxp_actual && fxp_actual <= fxp_max) - break; - } - if (drm_dp_dpcd_writeb(&intel_dp->aux, - DP_EDP_PWMGEN_BIT_COUNT, pn) < 0) { - DRM_DEBUG_KMS("Failed to write aux pwmgen bit count\n"); + if (fxp_min > fxp_actual || fxp_actual > fxp_max) { + DRM_DEBUG_KMS("Actual frequency out of range\n"); return false; } + if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_EDP_BACKLIGHT_FREQ_SET, (u8) f) < 0) { DRM_DEBUG_KMS("Failed to write aux backlight freq\n"); @@ -224,16 +197,88 @@ static void intel_dp_aux_disable_backlight(const struct drm_connector_state *old set_aux_backlight_enable(enc_to_intel_dp(old_conn_state->best_encoder), false); } +static u32 intel_dp_aux_calc_max_backlight(struct intel_connector *connector) +{ + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct intel_dp *intel_dp = enc_to_intel_dp(&connector->encoder->base); + u32 max_backlight = 0; + int freq, fxp, fxp_min, fxp_max, fxp_actual, f = 1; + u8 pn, pn_min, pn_max; + + if (drm_dp_dpcd_readb(&intel_dp->aux, DP_EDP_PWMGEN_BIT_COUNT, + &pn) != 1) + return max_backlight; + + pn &= DP_EDP_PWMGEN_BIT_COUNT_MASK; + max_backlight = (1 << pn) - 1; + + /* Find desired value of (F x P) + * Note that, if F x P is out of supported range, the maximum value or + * minimum value will applied automatically. So no need to check that. + */ + freq = dev_priv->vbt.backlight.pwm_freq_hz; + DRM_DEBUG_KMS("VBT defined backlight frequency %u Hz\n", freq); + if (!freq) { + DRM_DEBUG_KMS("Use panel default backlight frequency\n"); + return max_backlight; + } + + fxp = DIV_ROUND_CLOSEST(KHz(DP_EDP_BACKLIGHT_FREQ_BASE_KHZ), freq); + + /* Use highest possible value of Pn for more granularity of brightness + * adjustment while satifying the conditions below. + * - Pn is in the range of Pn_min and Pn_max + * - F is in the range of 1 and 255 + * - FxP is within 25% of desired value. + * Note: 25% is arbitrary value and may need some tweak. + */ + if (drm_dp_dpcd_readb(&intel_dp->aux, + DP_EDP_PWMGEN_BIT_COUNT_CAP_MIN, &pn_min) != 1) { + DRM_DEBUG_KMS("Failed to read pwmgen bit count cap min\n"); + return max_backlight; + } + if (drm_dp_dpcd_readb(&intel_dp->aux, + DP_EDP_PWMGEN_BIT_COUNT_CAP_MAX, &pn_max) != 1) { + DRM_DEBUG_KMS("Failed to read pwmgen bit count cap max\n"); + return max_backlight; + } + pn_min &= DP_EDP_PWMGEN_BIT_COUNT_MASK; + pn_max &= DP_EDP_PWMGEN_BIT_COUNT_MASK; + + fxp_min = DIV_ROUND_CLOSEST(fxp * 3, 4); + fxp_max = DIV_ROUND_CLOSEST(fxp * 5, 4); + if (fxp_min < (1 << pn_min) || (255 << pn_max) < fxp_max) { + DRM_DEBUG_KMS("VBT defined backlight frequency out of range\n"); + return max_backlight; + } + + for (pn = pn_max; pn >= pn_min; pn--) { + f = clamp(DIV_ROUND_CLOSEST(fxp, 1 << pn), 1, 255); + fxp_actual = f << pn; + if (fxp_min <= fxp_actual && fxp_actual <= fxp_max) + break; + } + + if (drm_dp_dpcd_writeb(&intel_dp->aux, + DP_EDP_PWMGEN_BIT_COUNT, pn) < 0) { + DRM_DEBUG_KMS("Failed to write aux pwmgen bit count\n"); + return max_backlight; + } + + max_backlight = (1 << pn) - 1; + + return max_backlight; +} + static int intel_dp_aux_setup_backlight(struct intel_connector *connector, enum pipe pipe) { - struct intel_dp *intel_dp = enc_to_intel_dp(&connector->encoder->base); struct intel_panel *panel = &connector->panel; - if (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT) - panel->backlight.max = 0xFFFF; - else - panel->backlight.max = 0xFF; + panel->backlight.max = intel_dp_aux_calc_max_backlight(connector); + + if (!panel->backlight.max) + return -ENODEV; panel->backlight.min = 0; panel->backlight.level = intel_dp_aux_get_backlight(connector); From patchwork Fri Oct 11 15:28:22 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Ma X-Patchwork-Id: 1175281 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46qX0m2tJJz9sP6; Sat, 12 Oct 2019 02:28:40 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1iIwqK-0002r3-20; Fri, 11 Oct 2019 15:28:36 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1iIwqF-0002qD-Pl for kernel-team@lists.ubuntu.com; Fri, 11 Oct 2019 15:28:31 +0000 Received: from [114.245.47.25] (helo=localhost.localdomain) by youngberry.canonical.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1iIwqF-0004iz-1m for kernel-team@lists.ubuntu.com; Fri, 11 Oct 2019 15:28:31 +0000 From: Aaron Ma To: kernel-team@lists.ubuntu.com Subject: [PATCH 2/2] UBUNTU: SAUCE: drm/i915: customize DPCD brightness control for specific panel Date: Fri, 11 Oct 2019 23:28:22 +0800 Message-Id: <20191011152822.26495-3-aaron.ma@canonical.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191011152822.26495-1-aaron.ma@canonical.com> References: <20191011152822.26495-1-aaron.ma@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Lee Shawn C BugLink: https://bugs.launchpad.net/bugs/1844798 This panel (manufacturer is SDC, product ID is 0x4141) used manufacturer defined DPCD register to control brightness that not defined in eDP spec so far. This change follow panel vendor's instruction to support brightness adjustment. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97883 V2: To check sink OUI instead of EDID quirk. According to TCON's capability to decide to enable this method for brightness control. Cc: Jani Nikula Cc: Adam Jackson Cc: Maarten Lankhorst Cc: Gustavo Padovan Cc: Cooper Chiou Signed-off-by: Lee Shawn C Link: https://patchwork.kernel.org/patch/11180697/ Signed-off-by: Aaron Ma --- drivers/gpu/drm/drm_dp_helper.c | 18 ++- drivers/gpu/drm/i915/intel_dp.c | 7 + drivers/gpu/drm/i915/intel_dp_aux_backlight.c | 138 +++++++++++++++++- include/drm/drm_dp_helper.h | 20 +++ 4 files changed, 176 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 038bd1e3889a..64a95d147abf 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -1225,6 +1225,8 @@ struct dpcd_quirk { static const struct dpcd_quirk dpcd_quirk_list[] = { /* Analogix 7737 needs reduced M and N at HBR2 link rates */ { OUI(0x00, 0x22, 0xb9), true, BIT(DP_DPCD_QUIRK_LIMITED_M_N) }, + /* Samsung eDP panel */ + { OUI(0xba, 0x41, 0x59), false, BIT(DP_DPCD_QUIRK_CUSTOMIZE_BRIGHTNESS_CONTROL) }, }; #undef OUI @@ -1238,7 +1240,7 @@ static const struct dpcd_quirk dpcd_quirk_list[] = { * to device identification string and hardware/firmware revisions later. */ static u32 -drm_dp_get_quirks(const struct drm_dp_dpcd_ident *ident, bool is_branch) +drm_dp_get_quirks(const struct drm_dp_dpcd_ident *ident, bool is_branch, u8 *tcon_cap) { const struct dpcd_quirk *quirk; u32 quirks = 0; @@ -1253,6 +1255,11 @@ drm_dp_get_quirks(const struct drm_dp_dpcd_ident *ident, bool is_branch) if (memcmp(quirk->oui, ident->oui, sizeof(ident->oui)) != 0) continue; + if (quirk->quirks == DP_DPCD_QUIRK_CUSTOMIZE_BRIGHTNESS_CONTROL && + (!(tcon_cap[1] & DP_BRIGHTNESS_CONTROL_NITS) || + !(tcon_cap[2] & DP_BRIGHTNESS_CONTROL_BY_AUX))) + continue; + quirks |= quirk->quirks; } @@ -1276,12 +1283,19 @@ int drm_dp_read_desc(struct drm_dp_aux *aux, struct drm_dp_desc *desc, struct drm_dp_dpcd_ident *ident = &desc->ident; unsigned int offset = is_branch ? DP_BRANCH_OUI : DP_SINK_OUI; int ret, dev_id_len; + u8 tcon_cap[4] = {0}; ret = drm_dp_dpcd_read(aux, offset, ident, sizeof(*ident)); if (ret < 0) return ret; - desc->quirks = drm_dp_get_quirks(ident, is_branch); + if (offset == DP_SINK_OUI) { + ret = drm_dp_dpcd_read(aux, DP_EDP_TCON_CAPABILITY_BYTE0, tcon_cap, sizeof(tcon_cap)); + if (ret < 0) + return ret; + } + + desc->quirks = drm_dp_get_quirks(ident, is_branch, tcon_cap); dev_id_len = strnlen(ident->device_id, sizeof(ident->device_id)); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 6753b73ebc4e..0cdf4a65e91f 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -5934,6 +5934,13 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, goto out_vdd_off; } + if (drm_dp_has_quirk(&intel_dp->desc, + DP_DPCD_QUIRK_CUSTOMIZE_BRIGHTNESS_CONTROL)) { + i915_modparams.enable_dpcd_backlight = true; + i915_modparams.fastboot = false; + DRM_DEBUG_KMS("Using specific DPCD to control brightness\n"); + } + mutex_lock(&dev->mode_config.mutex); edid = drm_get_edid(connector, &intel_dp->aux.ddc); if (edid) { diff --git a/drivers/gpu/drm/i915/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/intel_dp_aux_backlight.c index cbf61ac2910d..bde2720f2f8a 100644 --- a/drivers/gpu/drm/i915/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/intel_dp_aux_backlight.c @@ -24,6 +24,111 @@ #include "intel_drv.h" +#define EDP_CUSTOMIZE_MAX_BRIGHTNESS_LEVEL (512) + +static uint32_t intel_dp_aux_get_customize_backlight(struct intel_connector *connector) +{ + struct intel_dp *intel_dp = enc_to_intel_dp(&connector->encoder->base); + uint8_t read_val[2] = { 0x0 }; + + if (drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_BRIGHTNESS_NITS, + &read_val, sizeof(read_val)) < 0) { + DRM_DEBUG_KMS("Failed to read DPCD register %x\n", + DP_EDP_BRIGHTNESS_NITS); + return 0; + } + + return (read_val[1] << 8 | read_val[0]); +} + +static void +intel_dp_aux_set_customize_backlight(const struct drm_connector_state *conn_state, u32 level) +{ + struct intel_connector *connector = to_intel_connector(conn_state->connector); + struct intel_dp *intel_dp = enc_to_intel_dp(&connector->encoder->base); + struct intel_panel *panel = &connector->panel; + uint8_t new_vals[4]; + + if (level > panel->backlight.max) + level = panel->backlight.max; + + new_vals[0] = level & 0xFF; + new_vals[1] = (level & 0xFF00) >> 8; + new_vals[2] = 0; + new_vals[3] = 0; + + if (drm_dp_dpcd_write(&intel_dp->aux, DP_EDP_BRIGHTNESS_NITS, new_vals, 4) < 0) + DRM_DEBUG_KMS("Failed to write aux backlight level\n"); +} + +static void intel_dp_aux_enable_customize_backlight(const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state) +{ + struct intel_connector *connector = to_intel_connector(conn_state->connector); + struct intel_dp *intel_dp = enc_to_intel_dp(&connector->encoder->base); + uint8_t read_val[4], i; + uint8_t write_val[8] = {0x00, 0x00, 0xF0, 0x01, 0x90, 0x01, 0x00, 0x00}; + + if (drm_dp_dpcd_write(&intel_dp->aux, DP_EDP_PANEL_LUMINANCE_OVERRIDE, write_val, sizeof(write_val)) < 0) + DRM_DEBUG_KMS("Failed to write panel luminance.\n"); + + if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_EDP_BRIGHTNESS_OPTIMIZATION, 0x01) < 0) + DRM_DEBUG_KMS("Failed to write %x\n", + DP_EDP_BRIGHTNESS_OPTIMIZATION); + /* write source OUI */ + write_val[0] = 0x00; + write_val[1] = 0xaa; + write_val[2] = 0x01; + if (drm_dp_dpcd_write(&intel_dp->aux, DP_SOURCE_OUI, write_val, 3) < 0) + DRM_DEBUG_KMS("Failed to write OUI\n"); + + if (drm_dp_dpcd_readb(&intel_dp->aux, DP_EDP_GETSET_CTRL_PARAMS, read_val) != 1) + DRM_DEBUG_KMS("Failed to read %x\n", + DP_EDP_GETSET_CTRL_PARAMS); + + if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_EDP_GETSET_CTRL_PARAMS, 0) != 1) + DRM_DEBUG_KMS("Failed to write %x\n", + DP_EDP_GETSET_CTRL_PARAMS); + + if (drm_dp_dpcd_readb(&intel_dp->aux, DP_EDP_GETSET_CTRL_PARAMS, read_val) != 1) + DRM_DEBUG_KMS("Failed to read %x\n", + DP_EDP_GETSET_CTRL_PARAMS); + + if (drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_CONTENT_LUMINANCE, &read_val, sizeof(read_val)) < 0) + DRM_DEBUG_KMS("Failed to read %x\n", + DP_EDP_CONTENT_LUMINANCE); + + memset(read_val, 0x0, 4); + if (drm_dp_dpcd_write(&intel_dp->aux, DP_EDP_CONTENT_LUMINANCE, read_val, sizeof(read_val)) < 0) + DRM_DEBUG_KMS("Failed to write %x\n", + DP_EDP_CONTENT_LUMINANCE); + + if (drm_dp_dpcd_readb(&intel_dp->aux, DP_EDP_GETSET_CTRL_PARAMS, read_val) != 1) + DRM_DEBUG_KMS("Failed to read %x\n", + DP_EDP_GETSET_CTRL_PARAMS); + + if (drm_dp_dpcd_read(&intel_dp->aux, DP_SOURCE_OUI, read_val, 4) < 0) + DRM_DEBUG_KMS("Failed to read OUI\n"); + + DRM_DEBUG_KMS("got OUI %3ph\n", read_val); + + for (i = 0; i < 6; i++) { + intel_dp_aux_set_customize_backlight(conn_state, connector->panel.backlight.level); + + msleep(60); + if (intel_dp_aux_get_customize_backlight(connector)) + return; + } + + DRM_DEBUG_KMS("Restore brightness may have problem.\n"); +} + +static void intel_dp_aux_disable_customize_backlight(const struct drm_connector_state *old_conn_state) +{ + // do nothing + return; +} + static void set_aux_backlight_enable(struct intel_dp *intel_dp, bool enable) { uint8_t reg_val = 0; @@ -197,6 +302,19 @@ static void intel_dp_aux_disable_backlight(const struct drm_connector_state *old set_aux_backlight_enable(enc_to_intel_dp(old_conn_state->best_encoder), false); } +static int intel_dp_aux_setup_customize_backlight(struct intel_connector *connector, + enum pipe pipe) +{ + struct intel_panel *panel = &connector->panel; + + panel->backlight.max = EDP_CUSTOMIZE_MAX_BRIGHTNESS_LEVEL; + panel->backlight.min = 0; + panel->backlight.level = panel->backlight.get(connector); + panel->backlight.enabled = panel->backlight.level != 0; + + return 0; +} + static u32 intel_dp_aux_calc_max_backlight(struct intel_connector *connector) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); @@ -308,6 +426,7 @@ intel_dp_aux_display_control_capable(struct intel_connector *connector) int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector) { struct intel_panel *panel = &intel_connector->panel; + struct intel_dp *intel_dp = enc_to_intel_dp(&intel_connector->encoder->base); if (!i915_modparams.enable_dpcd_backlight) return -ENODEV; @@ -315,11 +434,20 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector) if (!intel_dp_aux_display_control_capable(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; - panel->backlight.set = intel_dp_aux_set_backlight; - panel->backlight.get = intel_dp_aux_get_backlight; + if (drm_dp_has_quirk(&intel_dp->desc, + DP_DPCD_QUIRK_CUSTOMIZE_BRIGHTNESS_CONTROL)) { + panel->backlight.setup = intel_dp_aux_setup_customize_backlight; + panel->backlight.enable = intel_dp_aux_enable_customize_backlight; + panel->backlight.disable = intel_dp_aux_disable_customize_backlight; + panel->backlight.set = intel_dp_aux_set_customize_backlight; + panel->backlight.get = intel_dp_aux_get_customize_backlight; + } else { + panel->backlight.setup = intel_dp_aux_setup_backlight; + panel->backlight.enable = intel_dp_aux_enable_backlight; + panel->backlight.disable = intel_dp_aux_disable_backlight; + panel->backlight.set = intel_dp_aux_set_backlight; + panel->backlight.get = intel_dp_aux_get_backlight; + } return 0; } diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 836252de56a2..6f08017e695b 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -625,6 +625,20 @@ /* up to ID_SLOT_63 at 0x2ff */ #define DP_SOURCE_OUI 0x300 +#define DP_EDP_TCON_CAPABILITY_BYTE0 0x340 + +#define DP_EDP_TCON_CAPABILITY_BYTE1 0x341 +#define DP_BRIGHTNESS_CONTROL_NITS 0x10 + +#define DP_EDP_TCON_CAPABILITY_BYTE2 0x342 +#define DP_BRIGHTNESS_CONTROL_BY_AUX 0x01 + +#define DP_EDP_GETSET_CTRL_PARAMS 0x344 +#define DP_EDP_CONTENT_LUMINANCE 0x346 +#define DP_EDP_PANEL_LUMINANCE_OVERRIDE 0x34A +#define DP_EDP_BRIGHTNESS_NITS 0x354 +#define DP_EDP_BRIGHTNESS_OPTIMIZATION 0x358 + #define DP_SINK_OUI 0x400 #define DP_BRANCH_OUI 0x500 #define DP_BRANCH_ID 0x503 @@ -1161,6 +1175,12 @@ enum drm_dp_quirk { * to 16 bits. */ DP_DPCD_QUIRK_LIMITED_M_N, + /** + * @DP_DPCD_QUIRK_NON_STANDARD_BRIGHTNESS_CONTROL: + * + * The device used specific DPCD register to control brightness. + */ + DP_DPCD_QUIRK_CUSTOMIZE_BRIGHTNESS_CONTROL, }; /**