[Intel-gfx] [PATCH v2 2/3] drm/i915: initialize backlight max from VBT

Clint Taylor clinton.a.taylor at intel.com
Fri Sep 4 15:42:13 PDT 2015


On 09/04/2015 06:55 AM, Jani Nikula wrote:
> Normally we determine the backlight PWM modulation frequency (which we
> also use as backlight max value) from the backlight registers at module
> load time, expecting the registers have been initialized by the BIOS. If
> this is not the case, we fail.
>
> The VBT contains the backlight modulation frequency in Hz. Add platform
> specific functions to convert the frequency in Hz to backlight PWM
> modulation frequency, and use them to initialize the backlight when the
> registers are not initialized by the BIOS.
>
> v2: Fix SPT and VLV. Thanks to Clint for the VLV code.
>
> Cc: Clint Taylor <clinton.a.taylor at intel.com>
> Signed-off-by: Jani Nikula <jani.nikula at intel.com>
> ---
>   drivers/gpu/drm/i915/i915_drv.h    |   2 +
>   drivers/gpu/drm/i915/i915_reg.h    |   3 +
>   drivers/gpu/drm/i915/intel_panel.c | 187 +++++++++++++++++++++++++++++++++++--
>   3 files changed, 185 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 12870073d58f..503dff5d747d 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -671,6 +671,8 @@ struct drm_i915_display_funcs {
>   			      uint32_t level);
>   	void (*disable_backlight)(struct intel_connector *connector);
>   	void (*enable_backlight)(struct intel_connector *connector);
> +	uint32_t (*backlight_hz_to_pwm)(struct intel_connector *connector,
> +					uint32_t hz);
>   };
>
>   enum forcewake_domain_id {
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 84ed9ab41b0f..812b7b211fa8 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -4648,6 +4648,7 @@ enum skl_disp_power_wells {
>
>   #define CBR1_VLV			(VLV_DISPLAY_BASE + 0x70400)
>   #define  CBR_PND_DEADLINE_DISABLE	(1<<31)
> +#define  CBR_PWM_CLOCK_MUX_SELECT	(1<<30)
>
>   /* FIFO watermark sizes etc */
>   #define G4X_FIFO_LINE_SIZE	64
> @@ -6325,9 +6326,11 @@ enum skl_disp_power_wells {
>   #define  FDI_PHASE_SYNC_OVR(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_OVR - ((pipe) * 2)))
>   #define  FDI_PHASE_SYNC_EN(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_EN - ((pipe) * 2)))
>   #define  FDI_BC_BIFURCATION_SELECT	(1 << 12)
> +#define  SPT_PWM_GRANULARITY		(1<<0)
>   #define SOUTH_CHICKEN2		0xc2004
>   #define  FDI_MPHY_IOSFSB_RESET_STATUS	(1<<13)
>   #define  FDI_MPHY_IOSFSB_RESET_CTL	(1<<12)
> +#define  LPT_PWM_GRANULARITY		(1<<5)
>   #define  DPLS_EDP_PPS_FIX_DIS		(1<<0)
>
>   #define _FDI_RXA_CHICKEN         0xc200c
> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> index 681686e5d550..d3a312c409eb 100644
> --- a/drivers/gpu/drm/i915/intel_panel.c
> +++ b/drivers/gpu/drm/i915/intel_panel.c
> @@ -1224,10 +1224,149 @@ static void intel_backlight_device_unregister(struct intel_connector *connector)
>   #endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */
>
>   /*
> - * Note: The setup hooks can't assume pipe is set!
> + * SPT: This value represents the period of the PWM stream in clock periods
> + * multiplied by 16 (default increment) or 128 (alternate increment selected in
> + * SCHICKEN_1 bit 0). PWM clock is 24 MHz.
> + */
> +static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
> +{
> +	struct drm_device *dev = connector->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	u32 mul, clock;
> +
> +	if (I915_READ(SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY)
> +		mul = 128;
> +	else
> +		mul = 16;
> +
> +	clock = MHz(24);
> +
> +	return clock / (pwm_freq_hz * mul);
> +}
> +
> +/*
> + * LPT: This value represents the period of the PWM stream in clock periods
> + * multiplied by 128 (default increment) or 16 (alternate increment, selected in
> + * LPT SOUTH_CHICKEN2 register bit 5).
> + */
> +static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
> +{
> +	struct drm_device *dev = connector->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	u32 mul, clock;
> +
> +	if (I915_READ(SOUTH_CHICKEN2) & LPT_PWM_GRANULARITY)
> +		mul = 16;
> +	else
> +		mul = 128;
> +
> +	if (dev_priv->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE)
> +		clock = MHz(135); /* LPT:H */
> +	else
> +		clock = MHz(24); /* LPT:LP */
> +
> +	return clock / (pwm_freq_hz * mul);
> +}
> +
> +/*
> + * ILK/SNB/IVB: This value represents the period of the PWM stream in PCH
> + * display raw clocks multiplied by 128.
> + */
> +static u32 pch_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
> +{
> +	struct drm_device *dev = connector->base.dev;
> +	int clock = MHz(intel_pch_rawclk(dev));
> +
> +	return clock / (pwm_freq_hz * 128);
> +}
> +
> +/*
> + * Gen2: This field determines the number of time base events (display core
> + * clock frequency/32) in total for a complete cycle of modulated backlight
> + * control.
>    *
> - * XXX: Query mode clock or hardware clock and program PWM modulation frequency
> - * appropriately when it's 0. Use VBT and/or sane defaults.
> + * Gen3: A time base event equals the display core clock ([DevPNV] HRAW clock)
> + * divided by 32.
> + */
> +static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
> +{
> +	struct drm_device *dev = connector->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	int clock;
> +
> +	if (IS_PINEVIEW(dev))
> +		clock = intel_hrawclk(dev);
> +	else
> +		clock = 1000 * dev_priv->display.get_display_clock_speed(dev);
> +
> +	return clock / (pwm_freq_hz * 32);
> +}
> +
> +/*
> + * Gen4: This value represents the period of the PWM stream in display core
> + * clocks multiplied by 128.
> + */
> +static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
> +{
> +	struct drm_device *dev = connector->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	int clock = 1000 * dev_priv->display.get_display_clock_speed(dev);
> +
> +	return clock / (pwm_freq_hz * 128);
> +}
> +
> +/*
> + * VLV: This value represents the period of the PWM stream in display core
> + * clocks ([DevCTG] 200MHz HRAW clocks) multiplied by 128 or 25MHz S0IX clocks
> + * multiplied by 16. CHV uses a 19.2MHz S0IX clock.
> + */
> +static u32 vlv_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
> +{
> +	struct drm_device *dev = connector->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	int clock;
> +
> +	if ((I915_READ(CBR1_VLV) & CBR_PWM_CLOCK_MUX_SELECT) == 0) {
> +		if (IS_CHERRYVIEW(dev))
> +			return KHz(19200) / (pwm_freq_hz * 16);
> +		else
> +			return MHz(25) / (pwm_freq_hz * 16);
> +	} else {
> +		clock = intel_hrawclk(dev);
> +		return MHz(clock) / (pwm_freq_hz * 128);
> +	}
> +}
> +
> +static u32 get_backlight_max_vbt(struct intel_connector *connector)
> +{
> +	struct drm_device *dev = connector->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	u16 pwm_freq_hz = dev_priv->vbt.backlight.pwm_freq_hz;
> +	u32 pwm;
> +
> +	if (!pwm_freq_hz) {
> +		DRM_DEBUG_KMS("backlight frequency not specified in VBT\n");
> +		return 0;
> +	}
> +
> +	if (!dev_priv->display.backlight_hz_to_pwm) {
> +		DRM_DEBUG_KMS("backlight frequency setting from VBT currently not supported on this platform\n");
> +		return 0;
> +	}
> +
> +	pwm = dev_priv->display.backlight_hz_to_pwm(connector, pwm_freq_hz);
> +	if (!pwm) {
> +		DRM_DEBUG_KMS("backlight frequency conversion failed\n");
> +		return 0;
> +	}
> +
> +	DRM_DEBUG_KMS("backlight frequency %u Hz from VBT\n", pwm_freq_hz);
> +
> +	return pwm;
> +}
> +
> +/*
> + * Note: The setup hooks can't assume pipe is set!
>    */
>   static u32 get_backlight_min_vbt(struct intel_connector *connector)
>   {
> @@ -1267,6 +1406,10 @@ static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unus
>
>   	pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
>   	panel->backlight.max = pch_ctl2 >> 16;
> +
> +	if (!panel->backlight.max)
> +		panel->backlight.max = get_backlight_max_vbt(connector);
> +
>   	if (!panel->backlight.max)
>   		return -ENODEV;
>
> @@ -1293,6 +1436,10 @@ static int pch_setup_backlight(struct intel_connector *connector, enum pipe unus
>
>   	pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
>   	panel->backlight.max = pch_ctl2 >> 16;
> +
> +	if (!panel->backlight.max)
> +		panel->backlight.max = get_backlight_max_vbt(connector);
> +
>   	if (!panel->backlight.max)
>   		return -ENODEV;
>
> @@ -1324,12 +1471,18 @@ static int i9xx_setup_backlight(struct intel_connector *connector, enum pipe unu
>   		panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV;
>
>   	panel->backlight.max = ctl >> 17;
> -	if (panel->backlight.combination_mode)
> -		panel->backlight.max *= 0xff;
> +
> +	if (!panel->backlight.max) {
> +		panel->backlight.max = get_backlight_max_vbt(connector);
> +		panel->backlight.max >>= 1;
> +	}
>
>   	if (!panel->backlight.max)
>   		return -ENODEV;
>
> +	if (panel->backlight.combination_mode)
> +		panel->backlight.max *= 0xff;
> +
>   	panel->backlight.min = get_backlight_min_vbt(connector);
>
>   	val = i9xx_get_backlight(connector);
> @@ -1353,12 +1506,16 @@ static int i965_setup_backlight(struct intel_connector *connector, enum pipe unu
>
>   	ctl = I915_READ(BLC_PWM_CTL);
>   	panel->backlight.max = ctl >> 16;
> -	if (panel->backlight.combination_mode)
> -		panel->backlight.max *= 0xff;
> +
> +	if (!panel->backlight.max)
> +		panel->backlight.max = get_backlight_max_vbt(connector);
>
>   	if (!panel->backlight.max)
>   		return -ENODEV;
>
> +	if (panel->backlight.combination_mode)
> +		panel->backlight.max *= 0xff;
> +
>   	panel->backlight.min = get_backlight_min_vbt(connector);
>
>   	val = i9xx_get_backlight(connector);
> @@ -1398,6 +1555,10 @@ static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe
>
>   	ctl = I915_READ(VLV_BLC_PWM_CTL(pipe));
>   	panel->backlight.max = ctl >> 16;
> +
> +	if (!panel->backlight.max)
> +		panel->backlight.max = get_backlight_max_vbt(connector);
> +
>   	if (!panel->backlight.max)
>   		return -ENODEV;
>
> @@ -1424,6 +1585,10 @@ bxt_setup_backlight(struct intel_connector *connector, enum pipe unused)
>   	panel->backlight.active_low_pwm = pwm_ctl & BXT_BLC_PWM_POLARITY;
>
>   	panel->backlight.max = I915_READ(BXT_BLC_PWM_FREQ1);
> +
> +	if (!panel->backlight.max)
> +		panel->backlight.max = get_backlight_max_vbt(connector);
> +
>   	if (!panel->backlight.max)
>   		return -ENODEV;
>
> @@ -1537,12 +1702,17 @@ void intel_panel_init_backlight_funcs(struct drm_device *dev)
>   		dev_priv->display.disable_backlight = lpt_disable_backlight;
>   		dev_priv->display.set_backlight = lpt_set_backlight;
>   		dev_priv->display.get_backlight = lpt_get_backlight;
> +		if (HAS_PCH_LPT(dev))
> +			dev_priv->display.backlight_hz_to_pwm = lpt_hz_to_pwm;
> +		else
> +			dev_priv->display.backlight_hz_to_pwm = spt_hz_to_pwm;
>   	} else if (HAS_PCH_SPLIT(dev)) {
>   		dev_priv->display.setup_backlight = pch_setup_backlight;
>   		dev_priv->display.enable_backlight = pch_enable_backlight;
>   		dev_priv->display.disable_backlight = pch_disable_backlight;
>   		dev_priv->display.set_backlight = pch_set_backlight;
>   		dev_priv->display.get_backlight = pch_get_backlight;
> +		dev_priv->display.backlight_hz_to_pwm = pch_hz_to_pwm;
>   	} else if (IS_VALLEYVIEW(dev)) {
>   		if (dev_priv->vbt.has_mipi) {
>   			dev_priv->display.setup_backlight = pwm_setup_backlight;
> @@ -1556,6 +1726,7 @@ void intel_panel_init_backlight_funcs(struct drm_device *dev)
>   			dev_priv->display.disable_backlight = vlv_disable_backlight;
>   			dev_priv->display.set_backlight = vlv_set_backlight;
>   			dev_priv->display.get_backlight = vlv_get_backlight;
> +			dev_priv->display.backlight_hz_to_pwm = vlv_hz_to_pwm;
>   		}
>   	} else if (IS_GEN4(dev)) {
>   		dev_priv->display.setup_backlight = i965_setup_backlight;
> @@ -1563,12 +1734,14 @@ void intel_panel_init_backlight_funcs(struct drm_device *dev)
>   		dev_priv->display.disable_backlight = i965_disable_backlight;
>   		dev_priv->display.set_backlight = i9xx_set_backlight;
>   		dev_priv->display.get_backlight = i9xx_get_backlight;
> +		dev_priv->display.backlight_hz_to_pwm = i965_hz_to_pwm;
>   	} else {
>   		dev_priv->display.setup_backlight = i9xx_setup_backlight;
>   		dev_priv->display.enable_backlight = i9xx_enable_backlight;
>   		dev_priv->display.disable_backlight = i9xx_disable_backlight;
>   		dev_priv->display.set_backlight = i9xx_set_backlight;
>   		dev_priv->display.get_backlight = i9xx_get_backlight;
> +		dev_priv->display.backlight_hz_to_pwm = i9xx_hz_to_pwm;
>   	}
>   }
>
>

Reviewed-by: Clint Taylor <Clinton.A.Taylor at intel.com>



More information about the Intel-gfx mailing list