All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jesse Barnes <jbarnes@virtuousgeek.org>
To: Yetunde Adebisi <yetundex.adebisi@intel.com>,
	intel-gfx@lists.freedesktop.org
Cc: Jani Nikula <jani.nikula@intel.com>, Deepak M <m.deepak@intel.com>
Subject: Re: [PATCH 1/1] drm/i915: Add Backlight Control using DPCD for eDP connectors
Date: Wed, 28 Oct 2015 13:17:20 -0700	[thread overview]
Message-ID: <56312D50.2020808@virtuousgeek.org> (raw)
In-Reply-To: <1443623767-11389-2-git-send-email-yetundex.adebisi@intel.com>

On 09/30/2015 07:36 AM, Yetunde Adebisi wrote:
> This patch adds support for eDP backlight control using DPCD registers to
> backlight hooks in intel_panel.
> 
> It checks for backlight control over AUX channel capability and sets up
> function pointers to get and set the backlight brightness level if
> supported.
> 
> Cc: Bob Paauwe <bob.j.paauwe@intel.com>
> Cc: Jani Nikula <jani.nikula@intel.com>
> Cc: Deepak M <m.deepak@intel.com>
> Signed-off-by: Yetunde Adebisi <yetundex.adebisi@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c    | 185 +++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h   |   3 +
>  drivers/gpu/drm/i915/intel_panel.c |   5 +-
>  include/drm/drm_dp_helper.h        |   6 ++
>  4 files changed, 198 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index fa1a524..fc4b896 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -6259,3 +6259,188 @@ void intel_dp_mst_resume(struct drm_device *dev)
>  		}
>  	}
>  }
> +
> +static uint8_t read_aux_backlight_mode_set_reg(struct intel_dp *intel_dp)
> +{
> +	uint8_t dpcd_buf = 0;
> +
> +	if (intel_dp_dpcd_read_wake(&intel_dp->aux,
> +			DP_EDP_BACKLIGHT_MODE_SET_REGISTER,
> +			&dpcd_buf, sizeof(dpcd_buf)) < 0)
> +		DRM_DEBUG_KMS("Failed to read DPCD register 0x%x\n",
> +				DP_EDP_BACKLIGHT_MODE_SET_REGISTER);
> +
> +	return dpcd_buf;
> +}
> +
> +static bool get_aux_backlight_enable(struct drm_dp_aux *aux)
> +{
> +	uint8_t read_val = 0;
> +
> +	if (intel_dp_dpcd_read_wake(aux, DP_EDP_DISPLAY_CONTROL_REGISTER,
> +			&read_val, sizeof(read_val)) < 0) {
> +		DRM_DEBUG_KMS("Failed to read DPCD register 0x%x\n",
> +				DP_EDP_DISPLAY_CONTROL_REGISTER);
> +		}
> +	return read_val & DP_EDP_BACKLIGHT_ENABLE;
> +}
> +
> +static void set_aux_backlight_enable(struct intel_dp *intel_dp, bool enable)
> +{
> +	uint8_t reg_val = 0;
> +
> +	if (intel_dp_dpcd_read_wake(&intel_dp->aux,
> +				DP_EDP_DISPLAY_CONTROL_REGISTER,
> +				&reg_val, sizeof(reg_val)) < 0) {
> +		DRM_DEBUG_KMS("Failed to read DPCD register 0x%x\n",
> +				DP_EDP_DISPLAY_CONTROL_REGISTER);
> +		return;
> +	}
> +	if (enable)
> +		reg_val |= DP_EDP_BACKLIGHT_ENABLE;
> +	else
> +		reg_val &= ~(DP_EDP_BACKLIGHT_ENABLE);
> +
> +	if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_EDP_DISPLAY_CONTROL_REGISTER,
> +			reg_val) < 0) {
> +		DRM_DEBUG_KMS("Failed to %s aux backlight\n",
> +				enable ? "enable" : "disable");
> +	}
> +}
> +
> +/**
> + * Read the current backlight value from DPCD register(s) based
> + * on if 8-bit(MSB) or 16-bit(MSB and LSB) values are supported
> + */
> +static uint32_t intel_dp_aux_get_backlight(struct intel_connector *connector)
> +{
> +	struct intel_dp *intel_dp = intel_attached_dp(&connector->base);
> +	uint16_t read_val = 0;
> +
> +	if (intel_dp_dpcd_read_wake(&intel_dp->aux,
> +			DP_EDP_BACKLIGHT_BRIGHTNESS_MSB,
> +			&read_val, sizeof(read_val)) < 0) {
> +		DRM_DEBUG_KMS("Failed to read DPCD register 0x%x\n",
> +				DP_EDP_BACKLIGHT_BRIGHTNESS_MSB);
> +		return 0;
> +	}
> +	if (intel_dp->aux_blc_use_lsb) {
> +		uint8_t val_lsb = 0;
> +
> +		if (intel_dp_dpcd_read_wake(&intel_dp->aux,
> +				DP_EDP_BACKLIGHT_BRIGHTNESS_LSB,
> +				&val_lsb, sizeof(val_lsb)) < 0) {
> +			DRM_DEBUG_KMS("Failed to read DPCD register 0x%x\n",
> +					DP_EDP_BACKLIGHT_BRIGHTNESS_LSB);
> +			return 0;
> +		}
> +		read_val = (read_val << 8 | val_lsb);
> +	}
> +
> +	return read_val;
> +}
> +
> +/**
> + * Sends the current backlight level over the aux channel, checking if its using
> + * 8-bit or 16 bit value (MSB and LSB)
> + */
> +static void
> +intel_dp_aux_set_backlight(struct intel_connector *connector, u32 level)
> +{
> +	struct intel_dp *intel_dp = intel_attached_dp(&connector->base);
> +	uint8_t vals[2] = { 0x0 };
> +
> +	vals[0] = level;
> +	DRM_DEBUG_KMS("Level 0x%x\n", level);
> +
> +	/* Write the MSB and/or LSB */
> +	 if (intel_dp->aux_blc_use_lsb) {
> +		vals[0] = (level & 0xFF00) >> 8;
> +		vals[1] = (level & 0xFF);
> +		if (drm_dp_dpcd_writeb(&intel_dp->aux,
> +				DP_EDP_BACKLIGHT_BRIGHTNESS_LSB, vals[1]) < 0) {
> +			DRM_DEBUG_KMS("Failed to write aux backlight level\n");
> +			return;
> +		}
> +	 }
> +	if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_EDP_BACKLIGHT_BRIGHTNESS_MSB,
> +			vals[0]) < 0) {
> +		DRM_DEBUG_KMS("Failed to write aux backlight level\n");
> +		return;
> +	}
> +}
> +
> +static void intel_dp_aux_enable_backlight(struct intel_connector *connector)
> +{
> +	set_aux_backlight_enable(intel_attached_dp(&connector->base), true);
> +}
> +
> +static void intel_dp_aux_disable_backlight(struct intel_connector *connector)
> +{
> +	set_aux_backlight_enable(intel_attached_dp(&connector->base), false);
> +}
> +
> +static int intel_dp_aux_setup_backlight(struct intel_connector *connector,
> +			       enum pipe pipe)
> +{
> +	struct intel_dp *intel_dp = intel_attached_dp(&connector->base);
> +	struct intel_panel *panel = &connector->panel;
> +
> +	if (!intel_dp_aux_display_control_capable(connector)) {
> +		DRM_DEBUG_KMS("Backlight control over AUX not supported\n");
> +		return -ENODEV;
> +	}
> +
> +	if (intel_dp->aux_blc_use_lsb)
> +		panel->backlight.max = 0xFFFF;
> +	else
> +		panel->backlight.max = 0xFF;
> +
> +	panel->backlight.min = 0;
> +
> +	panel->backlight.level = intel_dp_aux_get_backlight(connector);
> +	panel->backlight.enabled = get_aux_backlight_enable(&intel_dp->aux);
> +
> +	return 0;
> +}
> +
> +void intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector)
> +{
> +	struct intel_panel *panel = &intel_connector->panel;
> +
> +	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;
> +}
> +
> +bool intel_dp_aux_display_control_capable(struct intel_connector *connector)
> +{
> +	struct intel_dp *intel_dp = intel_attached_dp(&connector->base);
> +	uint8_t dpcd_edp[2] = { 0x0 };
> +
> +	/* Check the  eDP Display control capabilities registers to determine if
> +	 * the panel can support backlight control over the aux channel*/
> +	if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_EDP_GENERAL_CAP_1,
> +			dpcd_edp, sizeof(dpcd_edp)) < 0) {
> +		DRM_DEBUG_KMS("Failed to read DPCD Display Control registers\n");
> +		return false;
> +	}
> +	DRM_DEBUG_KMS("EDP DPCD : %*ph\n", (int) sizeof(dpcd_edp), dpcd_edp);
> +
> +	if (dpcd_edp[0] & DP_EDP_TCON_BACKLIGHT_ADJUSTMENT_CAPABLE &&
> +			(dpcd_edp[0] & DP_EDP_BACKLIGHT_AUX_ENABLE_CAPABLE) &&
> +			(dpcd_edp[1] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAPABLE) &&
> +			((read_aux_backlight_mode_set_reg(intel_dp) &
> +					DP_EDP_BACKLIGHT_BRIGHTNESS_CTL_MODE_DPCD_MASK))) {
> +
> +		DRM_DEBUG_KMS("AUX Backlight Control Supported!\n");
> +
> +		if (dpcd_edp[1] & DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT)
> +			intel_dp->aux_blc_use_lsb = true;
> +
> +		return true;
> +	}
> +	return false;
> +}
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 35a65ca..dacbc37 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -747,6 +747,7 @@ struct intel_dp {
>  	unsigned long last_power_cycle;
>  	unsigned long last_power_on;
>  	unsigned long last_backlight_off;
> +	bool aux_blc_use_lsb;
>  
>  	struct notifier_block edp_notifier;
>  
> @@ -1221,6 +1222,8 @@ void intel_edp_drrs_invalidate(struct drm_device *dev,
>  		unsigned frontbuffer_bits);
>  void intel_edp_drrs_flush(struct drm_device *dev, unsigned frontbuffer_bits);
>  void hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config);
> +bool intel_dp_aux_display_control_capable(struct intel_connector *connector);
> +void intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector);
>  
>  /* intel_dp_mst.c */
>  int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id);
> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> index 9adb62b..04eff34 100644
> --- a/drivers/gpu/drm/i915/intel_panel.c
> +++ b/drivers/gpu/drm/i915/intel_panel.c
> @@ -1685,7 +1685,10 @@ intel_panel_init_backlight_funcs(struct intel_panel *panel)
>  	struct drm_device *dev = intel_connector->base.dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  
> -	if (IS_BROXTON(dev)) {
> +	if (intel_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP &&
> +		intel_dp_aux_display_control_capable(intel_connector)) {
> +			intel_dp_aux_init_backlight_funcs(intel_connector);
> +	} else if (IS_BROXTON(dev)) {
>  		panel->backlight.setup = bxt_setup_backlight;
>  		panel->backlight.enable = bxt_enable_backlight;
>  		panel->backlight.disable = bxt_disable_backlight;
> diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> index 9ec4716..7367e1a 100644
> --- a/include/drm/drm_dp_helper.h
> +++ b/include/drm/drm_dp_helper.h
> @@ -455,16 +455,22 @@
>  # define DP_EDP_14			    0x03
>  
>  #define DP_EDP_GENERAL_CAP_1		    0x701
> +#define DP_EDP_TCON_BACKLIGHT_ADJUSTMENT_CAPABLE      (1 << 0)
> +#define DP_EDP_BACKLIGHT_AUX_ENABLE_CAPABLE           (1 << 2)
>  
>  #define DP_EDP_BACKLIGHT_ADJUSTMENT_CAP     0x702
> +#define DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAPABLE   (1 << 1)
> +#define DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT        (1 << 2)
>  
>  #define DP_EDP_GENERAL_CAP_2		    0x703
>  
>  #define DP_EDP_GENERAL_CAP_3		    0x704    /* eDP 1.4 */
>  
>  #define DP_EDP_DISPLAY_CONTROL_REGISTER     0x720
> +#define DP_EDP_BACKLIGHT_ENABLE                       (1 << 0)
>  
>  #define DP_EDP_BACKLIGHT_MODE_SET_REGISTER  0x721
> +#define DP_EDP_BACKLIGHT_BRIGHTNESS_CTL_MODE_DPCD_MASK 0x2
>  
>  #define DP_EDP_BACKLIGHT_BRIGHTNESS_MSB     0x722
>  #define DP_EDP_BACKLIGHT_BRIGHTNESS_LSB     0x723

I don't have the spec for this but assume you've tested it.  The code looks ok, my only worry is that some eDP panels might return a DPCD backlight capability but then just ignore the writes.  But I guess we'll find that out soon enough if we land this.

So:
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

  parent reply	other threads:[~2015-10-28 20:44 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-30 14:36 [PATCH 0/1] drm/i915: DPCD Backlight Control Yetunde Adebisi
2015-09-30 14:36 ` [PATCH 1/1] drm/i915: Add Backlight Control using DPCD for eDP connectors Yetunde Adebisi
2015-10-27 15:56   ` Adebisi, YetundeX
2015-10-28 20:17   ` Jesse Barnes [this message]
2015-10-29  9:35   ` Jani Nikula

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=56312D50.2020808@virtuousgeek.org \
    --to=jbarnes@virtuousgeek.org \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=jani.nikula@intel.com \
    --cc=m.deepak@intel.com \
    --cc=yetundex.adebisi@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.