drm/i915: initialize backlight pwm from vbt if needed
Subsystems (2)
cover drm/i915: initialize backlight pwm from vbt if needed
This is a rebase of [1] and originally [2]. I haven't tried this in a year and I have no idea if it works on SKL, and it's not implemented for BXT. However there's renewed interest, so here's the rebase.
BR,
Jani.
[1] http://mid.gmane.org/[email protected]
[2] http://mid.gmane.org/[email protected]
Jani Nikula (2):
drm/i915: move intel_hrawclk() to intel_display.c drm/i915: initialize backlight max from VBT
drivers/gpu/drm/i915/i915_drv.h | 2 + drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_display.c | 33 ++++++++ drivers/gpu/drm/i915/intel_dp.c | 34 -------- drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_panel.c | 160 +++++++++++++++++++++++++++++++++-- 6 files changed, 190 insertions(+), 41 deletions(-)
Signature · 6 lines
2.1.4 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
PATCH 1/2 drm/i915: move intel_hrawclk() to intel_display.c
Make it available outside of intel_dp.c.
--- drivers/gpu/drm/i915/intel_display.c | 33 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_dp.c | 34 ---------------------------------- drivers/gpu/drm/i915/intel_drv.h | 1 + 3 files changed, 34 insertions(+), 34 deletions(-)
drivers/gpu/drm/i915/intel_display.c +33 -0
@@ -135,6 +135,39 @@ intel_pch_rawclk(struct drm_device *dev)return I915_READ (PCH_RAWCLK_FREQ ) &RAWCLK_FREQ_MASK ; } +/* hrawclock is 1/4 the FSB frequency */ +int intel_hrawclk (struct drm_device *dev) +{ +struct drm_i915_private *dev_priv = dev->dev_private; +uint32_t clkcfg; + +/* There is no CLKCFG reg in Valleyview. VLV hrawclk is 200 MHz */ +if (IS_VALLEYVIEW (dev)) +return 200 ; + + clkcfg =I915_READ (CLKCFG ); +switch (clkcfg &CLKCFG_FSB_MASK ) { +case CLKCFG_FSB_400 : +return 100 ; +case CLKCFG_FSB_533 : +return 133 ; +case CLKCFG_FSB_667 : +return 166 ; +case CLKCFG_FSB_800 : +return 200 ; +case CLKCFG_FSB_1067 : +return 266 ; +case CLKCFG_FSB_1333 : +return 333 ; +/* these two are just a guess; one of them might be right */ +case CLKCFG_FSB_1600 : +case CLKCFG_FSB_1600_ALT : +return 400 ; +default : +return 133 ; + } +} +static inline u32 /* units of 100MHz */ intel_fdi_link_freq (struct drm_device *dev) {
drivers/gpu/drm/i915/intel_dp.c +0 -34
@@ -253,40 +253,6 @@ static void intel_dp_unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes) dst[i] = src >> ((3 -i) *8 ); } -/* hrawclock is 1/4 the FSB frequency */ -static int -intel_hrawclk (struct drm_device *dev) -{ -struct drm_i915_private *dev_priv = dev->dev_private; -uint32_t clkcfg; - -/* There is no CLKCFG reg in Valleyview. VLV hrawclk is 200 MHz */ -if (IS_VALLEYVIEW (dev)) -return 200 ; - - clkcfg =I915_READ (CLKCFG ); -switch (clkcfg &CLKCFG_FSB_MASK ) { -case CLKCFG_FSB_400 : -return 100 ; -case CLKCFG_FSB_533 : -return 133 ; -case CLKCFG_FSB_667 : -return 166 ; -case CLKCFG_FSB_800 : -return 200 ; -case CLKCFG_FSB_1067 : -return 266 ; -case CLKCFG_FSB_1333 : -return 333 ; -/* these two are just a guess; one of them might be right */ -case CLKCFG_FSB_1600 : -case CLKCFG_FSB_1600_ALT : -return 400 ; -default : -return 133 ; - } -} -static void intel_dp_init_panel_power_sequencer (struct drm_device *dev,struct intel_dp *intel_dp);
drivers/gpu/drm/i915/intel_drv.h +1 -0
@@ -993,6 +993,7 @@ void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);extern const struct drm_plane_funcs intel_plane_funcs;bool intel_has_pending_fb_unpin (struct drm_device *dev);int intel_pch_rawclk (struct drm_device *dev); +int intel_hrawclk (struct drm_device *dev);void intel_mark_busy (struct drm_device *dev);void intel_mark_idle (struct drm_device *dev);void intel_crtc_restore_mode (struct drm_crtc *crtc);
Signature · 6 lines
2.1.4 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
PATCH 2/2 drm/i915: initialize backlight max from VBT
In reply to Jani NikulaNormally 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.
--- drivers/gpu/drm/i915/i915_drv.h | 2 + drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_panel.c | 160 +++++++++++++++++++++++++++++++++++-- 3 files changed, 156 insertions(+), 7 deletions(-)
drivers/gpu/drm/i915/i915_drv.h +2 -0
@@ -665,6 +665,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 {
drivers/gpu/drm/i915/i915_reg.h +1 -0
@@ -6316,6 +6316,7 @@ enum skl_disp_power_wells {#define SOUTH_CHICKEN2 0xc2004#define FDI_MPHY_IOSFSB_RESET_STATUS (1<<13)#define FDI_MPHY_IOSFSB_RESET_CTL (1<<12) +#define PWM_GRANULARITY (1<<5)/* LPT */ #define DPLS_EDP_PPS_FIX_DIS (1<<0)#define _FDI_RXA_CHICKEN 0xc200c
drivers/gpu/drm/i915/intel_panel.c +153 -7
241 lines not on this page · raw message
Signature · 6 lines
2.1.4 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 2/2] drm/i915: initialize backlight max from VBT
Quoted 35 lines · Jani Nikula
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.
Signed-off-by Jani Nikula <[email protected]>--- drivers/gpu/drm/i915/i915_drv.h | 2 + drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_panel.c | 160 +++++++++++++++++++++++++++++++++++-- 3 files changed, 156 insertions(+), 7 deletions(-)drivers/gpu/drm/i915/i915_drv.h +2
-0@@ -665,6 +665,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 {drivers/gpu/drm/i915/i915_reg.h +0
-0
drivers/gpu/drm/i915/i915_reg.h enum skl_disp_power_wells { · line 6319
Quoted 4 lines
drivers/gpu/drm/i915/i915_reg.h +1
-0@@ -6316,6 +6316,7 @@ enum skl_disp_power_wells {#define SOUTH_CHICKEN2 0xc2004#define FDI_MPHY_IOSFSB_RESET_STATUS (1<<13)#define FDI_MPHY_IOSFSB_RESET_CTL (1<<12) +#define PWM_GRANULARITY (1<<5)/* LPT */
Shouldn't we be using the BLC_PWM_CTL version of the PWM_GRANULARITY bit on HSW and later?
Quoted 20 lines
drivers/gpu/drm/i915/i915_reg.h +0
-0#define DPLS_EDP_PPS_FIX_DIS (1<<0)#define _FDI_RXA_CHICKEN 0xc200cdrivers/gpu/drm/i915/intel_panel.c +5
-3@@ -1212,10 +1212,125 @@ 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! +* HSW/BDW: 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). * -* XXX: Query mode clock or hardware clock and program PWM modulation frequency -* appropriately when it's 0. Use VBT and/or sane defaults. +* XXX: This only works when driving the PCH PWM. When driving the CPU PWM on +* the utility pin, the granularity needs to be determined by BLC_PWM_CTL bit
drivers/gpu/drm/i915/intel_panel.c static void intel_backlight_device_unregister(struct intel_connector *connector) · line 1230
Quoted 10 lines
drivers/gpu/drm/i915/intel_panel.c +10
-0+* 27. +*/ +static u32 hsw_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 ) &PWM_GRANULARITY ) + mul =16 ;
According to the HSW, BDW, and SKL BSPECs the increment is 8 and 128 based on the PWM Granularity bit. The BDW and SKL ChromeOS reference designs uses the dedicated PWM pin and not the utility pin. So BLC_PWM_CTRL bit 27 should be used for PWM_GRANULARITY. We probably need logic to switch between PCH and CPU PWMs.
Quoted 51 lines
drivers/gpu/drm/i915/intel_panel.c +51
-0+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. +* +* 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) +{
drivers/gpu/drm/i915/intel_panel.c static void intel_backlight_device_unregister(struct intel_connector *connector) · line 1291
Quoted 10 lines
drivers/gpu/drm/i915/intel_panel.c +10
-0+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] 100MHz HRAW clocks) multiplied by 128 or 25MHz S0IX clocks
VLV and CHV use a 200 Mhz HRAW clock. Since patch 1 in the series moved intel_hrawclk() into intel_display.c lets use the returned value instead of the hardcoded value.
drivers/gpu/drm/i915/intel_panel.c static void intel_backlight_device_unregister(struct intel_connector *connector) · line 1294
Quoted 3 lines
drivers/gpu/drm/i915/intel_panel.c +3
-0+* multiplied by 16. +* +* XXX: Where is this selected???
This is currently selected in Bit 30 of CBR1_VLV. Of course intel_pm.c writes this register as 0x0 during init so it doesn't surprise me that this test would also be 0x0.
drivers/gpu/drm/i915/intel_panel.c static void intel_backlight_device_unregister(struct intel_connector *connector) · line 1299
Quoted 5 lines
drivers/gpu/drm/i915/intel_panel.c +5
-0+*/ +static u32 vlv_hz_to_pwm (struct intel_connector *connector,u32 pwm_freq_hz) +{ +if (1 ) +return MHz (25 ) / (pwm_freq_hz *16 );
CHV actually uses a 19.2 MHz S0IX clock and since the MHz() macro doesn't accept floats we need to use KHz() macro.
drivers/gpu/drm/i915/intel_panel.c static void intel_backlight_device_unregister(struct intel_connector *connector) · line 1302
Quoted 3 lines
drivers/gpu/drm/i915/intel_panel.c +3
-0+else +return MHz (100 ) / (pwm_freq_hz *128 ); +}
Here is the new function for the 3 previous issues
/*
* 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);
}
}Quoted 97 lines
drivers/gpu/drm/i915/intel_panel.c +53
-4+ +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) {@@ -1255,6 +1370,10 @@ static int bdw_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 ;@@ -1281,6 +1400,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 ;@@ -1312,12 +1435,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);@@ -1341,12 +1470,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);
drivers/gpu/drm/i915/intel_panel.c static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe · line 1522
Quoted 4 lines
drivers/gpu/drm/i915/intel_panel.c +1
-0@@ -1386,6 +1519,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 ; +
the for_each_pipe() above this code hardcodes the upper 16 bits of VLV_BLC_PWM_CTL to 0xF42 (307.4 Hz) so this code never executes. removing the for_each_pipe block above these adds resolves this issue.
Quoted 18 lines
drivers/gpu/drm/i915/intel_panel.c +7
-0+if (!panel->backlight.max) + panel->backlight.max =get_backlight_max_vbt (connector); +if (!panel->backlight.max)return -ENODEV ;@@ -1412,6 +1549,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 ;
drivers/gpu/drm/i915/intel_panel.c void intel_panel_init_backlight_funcs(struct drm_device *dev) · line 1669
Quoted 4 lines
drivers/gpu/drm/i915/intel_panel.c +1
-0@@ -1525,12 +1666,14 @@ void intel_panel_init_backlight_funcs(struct drm_device *dev) dev_priv->display.disable_backlight = pch_disable_backlight; dev_priv->display.set_backlight = bdw_set_backlight; dev_priv->display.get_backlight = bdw_get_backlight; + dev_priv->display.backlight_hz_to_pwm = hsw_hz_to_pwm;
We need to create a new function for SKL, and BXT that doesn't use the utility pin. and yes I understand that this patch was submitted 20 months ago. I'm investigating changes for BDW and SKL support.
Quoted 24 lines
drivers/gpu/drm/i915/intel_panel.c +3
-0}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;@@ -1544,6 +1687,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;@@ -1551,12 +1695,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;
drivers/gpu/drm/i915/intel_panel.c void intel_panel_init_backlight_funcs(struct drm_device *dev) · line 1708
Quoted 10 lines
drivers/gpu/drm/i915/intel_panel.c +1
-0}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; } }
_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 1/2] drm/i915: move intel_hrawclk() to intel_display.c
In reply to Jani NikulaQuoted 104 lines · Jani Nikula
Make it available outside of
intel_dp.c.Signed-off-by Jani Nikula <[email protected]>--- drivers/gpu/drm/i915/intel_display.c | 33 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_dp.c | 34 ---------------------------------- drivers/gpu/drm/i915/intel_drv.h | 1 + 3 files changed, 34 insertions(+), 34 deletions(-)drivers/gpu/drm/i915/intel_display.c +33
-0@@ -135,6 +135,39 @@ intel_pch_rawclk(struct drm_device *dev)return I915_READ (PCH_RAWCLK_FREQ ) &RAWCLK_FREQ_MASK ; } +/* hrawclock is 1/4 the FSB frequency */ +int intel_hrawclk (struct drm_device *dev) +{ +struct drm_i915_private *dev_priv = dev->dev_private; +uint32_t clkcfg; + +/* There is no CLKCFG reg in Valleyview. VLV hrawclk is 200 MHz */ +if (IS_VALLEYVIEW (dev)) +return 200 ; + + clkcfg =I915_READ (CLKCFG ); +switch (clkcfg &CLKCFG_FSB_MASK ) { +case CLKCFG_FSB_400 : +return 100 ; +case CLKCFG_FSB_533 : +return 133 ; +case CLKCFG_FSB_667 : +return 166 ; +case CLKCFG_FSB_800 : +return 200 ; +case CLKCFG_FSB_1067 : +return 266 ; +case CLKCFG_FSB_1333 : +return 333 ; +/* these two are just a guess; one of them might be right */ +case CLKCFG_FSB_1600 : +case CLKCFG_FSB_1600_ALT : +return 400 ; +default : +return 133 ; + } +} +static inline u32 /* units of 100MHz */ intel_fdi_link_freq (struct drm_device *dev) {drivers/gpu/drm/i915/intel_dp.c +0
-34@@ -253,40 +253,6 @@ static void intel_dp_unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes) dst[i] = src >> ((3 -i) *8 ); } -/* hrawclock is 1/4 the FSB frequency */ -static int -intel_hrawclk (struct drm_device *dev) -{ -struct drm_i915_private *dev_priv = dev->dev_private; -uint32_t clkcfg; - -/* There is no CLKCFG reg in Valleyview. VLV hrawclk is 200 MHz */ -if (IS_VALLEYVIEW (dev)) -return 200 ; - - clkcfg =I915_READ (CLKCFG ); -switch (clkcfg &CLKCFG_FSB_MASK ) { -case CLKCFG_FSB_400 : -return 100 ; -case CLKCFG_FSB_533 : -return 133 ; -case CLKCFG_FSB_667 : -return 166 ; -case CLKCFG_FSB_800 : -return 200 ; -case CLKCFG_FSB_1067 : -return 266 ; -case CLKCFG_FSB_1333 : -return 333 ; -/* these two are just a guess; one of them might be right */ -case CLKCFG_FSB_1600 : -case CLKCFG_FSB_1600_ALT : -return 400 ; -default : -return 133 ; - } -} -static void intel_dp_init_panel_power_sequencer (struct drm_device *dev,struct intel_dp *intel_dp);drivers/gpu/drm/i915/intel_drv.h +0
-0
drivers/gpu/drm/i915/intel_drv.h void i915_audio_component_cleanup(struct drm_i915_private *dev_priv); · line 999
Quoted 7 lines
drivers/gpu/drm/i915/intel_drv.h +1
-0@@ -993,6 +993,7 @@ void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);extern const struct drm_plane_funcs intel_plane_funcs;bool intel_has_pending_fb_unpin (struct drm_device *dev);int intel_pch_rawclk (struct drm_device *dev); +int intel_hrawclk (struct drm_device *dev);void intel_mark_busy (struct drm_device *dev);void intel_mark_idle (struct drm_device *dev);void intel_crtc_restore_mode (struct drm_crtc *crtc);
Simple move of the function with no change in functionality.
_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Quoted 3 lines · Jani Nikula
This is a rebase of [1] and originally [2]. I haven't tried this in a year and I have no idea if it works on SKL, and it's not implemented for BXT. However there's renewed interest, so here's the rebase.
Renewed interest as an ODM has been reporting that BSW is producing an incorrect PWM frequency. This is due to a CHV documentation issue that states the S0IX clock is 25MHz when it's actually only 19.2MHz.
Quoted 11 lines
BR,
Jani.[1] http://mid.gmane.org/[email protected]
[2] http://mid.gmane.org/[email protected]Jani Nikula (2):
drm/i915: moveintel_hrawclk()tointel_display.cdrm/i915: initialize backlight max from VBT
Quoted 8 lines
drivers/gpu/drm/i915/i915_drv.h | 2 + drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_display.c | 33 ++++++++ drivers/gpu/drm/i915/intel_dp.c | 34 -------- drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_panel.c | 160 +++++++++++++++++++++++++++++++++-- 6 files changed, 190 insertions(+), 41 deletions(-)
_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 2/2] drm/i915: initialize backlight max from VBT
In reply to Jani NikulaTask id: 7258 -------------------------------------Summary-------------------------------------
Platform Delta drm-intel-nightly Series Applied
ILK 302/302 302/302 SNB 315/315 315/315 IVB 336/336 336/336 BYT 283/283 283/283 HSW 378/378 378/378
-------------------------------------Detailed-------------------------------------
Platform Test drm-intel-nightly Series Applied
Note: You need to pay more attention to line start with '*'
_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Daniel Vetter
AppliedRe: [PATCH 1/2] drm/i915: move intel_hrawclk() to intel_display.c
In reply to Clint TaylorQuoted 115 lines · Clint Taylor
Quoted 104 lines · Jani Nikula
Make it available outside of
intel_dp.c.Signed-off-by Jani Nikula <[email protected]>--- drivers/gpu/drm/i915/intel_display.c | 33 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_dp.c | 34 ---------------------------------- drivers/gpu/drm/i915/intel_drv.h | 1 + 3 files changed, 34 insertions(+), 34 deletions(-)drivers/gpu/drm/i915/intel_display.c +33
-0@@ -135,6 +135,39 @@ intel_pch_rawclk(struct drm_device *dev)return I915_READ (PCH_RAWCLK_FREQ ) &RAWCLK_FREQ_MASK ; } +/* hrawclock is 1/4 the FSB frequency */ +int intel_hrawclk (struct drm_device *dev) +{ +struct drm_i915_private *dev_priv = dev->dev_private; +uint32_t clkcfg; + +/* There is no CLKCFG reg in Valleyview. VLV hrawclk is 200 MHz */ +if (IS_VALLEYVIEW (dev)) +return 200 ; + + clkcfg =I915_READ (CLKCFG ); +switch (clkcfg &CLKCFG_FSB_MASK ) { +case CLKCFG_FSB_400 : +return 100 ; +case CLKCFG_FSB_533 : +return 133 ; +case CLKCFG_FSB_667 : +return 166 ; +case CLKCFG_FSB_800 : +return 200 ; +case CLKCFG_FSB_1067 : +return 266 ; +case CLKCFG_FSB_1333 : +return 333 ; +/* these two are just a guess; one of them might be right */ +case CLKCFG_FSB_1600 : +case CLKCFG_FSB_1600_ALT : +return 400 ; +default : +return 133 ; + } +} +static inline u32 /* units of 100MHz */ intel_fdi_link_freq (struct drm_device *dev) {drivers/gpu/drm/i915/intel_dp.c +0
-34@@ -253,40 +253,6 @@ static void intel_dp_unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes) dst[i] = src >> ((3 -i) *8 ); } -/* hrawclock is 1/4 the FSB frequency */ -static int -intel_hrawclk (struct drm_device *dev) -{ -struct drm_i915_private *dev_priv = dev->dev_private; -uint32_t clkcfg; - -/* There is no CLKCFG reg in Valleyview. VLV hrawclk is 200 MHz */ -if (IS_VALLEYVIEW (dev)) -return 200 ; - - clkcfg =I915_READ (CLKCFG ); -switch (clkcfg &CLKCFG_FSB_MASK ) { -case CLKCFG_FSB_400 : -return 100 ; -case CLKCFG_FSB_533 : -return 133 ; -case CLKCFG_FSB_667 : -return 166 ; -case CLKCFG_FSB_800 : -return 200 ; -case CLKCFG_FSB_1067 : -return 266 ; -case CLKCFG_FSB_1333 : -return 333 ; -/* these two are just a guess; one of them might be right */ -case CLKCFG_FSB_1600 : -case CLKCFG_FSB_1600_ALT : -return 400 ; -default : -return 133 ; - } -} -static void intel_dp_init_panel_power_sequencer (struct drm_device *dev,struct intel_dp *intel_dp);drivers/gpu/drm/i915/intel_drv.h +0
-0drivers/gpu/drm/i915/intel_drv.h void i915_audio_component_cleanup(struct drm_i915_private *dev_priv); · line 999
Quoted 7 lines
drivers/gpu/drm/i915/intel_drv.h +1
-0@@ -993,6 +993,7 @@ void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);extern const struct drm_plane_funcs intel_plane_funcs;bool intel_has_pending_fb_unpin (struct drm_device *dev);int intel_pch_rawclk (struct drm_device *dev); +int intel_hrawclk (struct drm_device *dev);void intel_mark_busy (struct drm_device *dev);void intel_mark_idle (struct drm_device *dev);void intel_crtc_restore_mode (struct drm_crtc *crtc);Simple move of the function with no change in functionality.
Quoted 2 lines
Reviewed-by Clint Taylor <[email protected]>Tested-by Clint Taylor <[email protected]>
Queued for -next, thanks for the patch.
-Daniel
Signature · 7 lines
Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 2/2] drm/i915: initialize backlight max from VBT
In reply to Clint TaylorQuoted 30 lines · Clint Taylor
Quoted 29 lines · Jani Nikula
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.
Signed-off-by Jani Nikula <[email protected]>--- drivers/gpu/drm/i915/i915_drv.h | 2 + drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_panel.c | 160 +++++++++++++++++++++++++++++++++++-- 3 files changed, 156 insertions(+), 7 deletions(-)drivers/gpu/drm/i915/i915_drv.h +2
-0@@ -665,6 +665,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); };
Quoted 13 lines
drivers/gpu/drm/i915/i915_reg.h enum skl_disp_power_wells { · line 6319
Quoted 10 lines
drivers/gpu/drm/i915/i915_drv.h +0
-0enum forcewake_domain_id {drivers/gpu/drm/i915/i915_reg.h +1
-0@@ -6316,6 +6316,7 @@ enum skl_disp_power_wells {#define SOUTH_CHICKEN2 0xc2004#define FDI_MPHY_IOSFSB_RESET_STATUS (1<<13)#define FDI_MPHY_IOSFSB_RESET_CTL (1<<12) +#define PWM_GRANULARITY (1<<5)/* LPT */ Shouldn't we be using the
BLC_PWM_CTLversion of thePWM_GRANULARITYbit on HSW and later?
Only when driving the backlight on the utility pin.
Quoted 29 lines
Quoted 29 lines
drivers/gpu/drm/i915/i915_reg.h +0
-0#define DPLS_EDP_PPS_FIX_DIS (1<<0)#define _FDI_RXA_CHICKEN 0xc200cdrivers/gpu/drm/i915/intel_panel.c +13
-3@@ -1212,10 +1212,125 @@ 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! +* HSW/BDW: 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). * -* XXX: Query mode clock or hardware clock and program PWM modulation frequency -* appropriately when it's 0. Use VBT and/or sane defaults. +* XXX: This only works when driving the PCH PWM. When driving the CPU PWM on +* the utility pin, the granularity needs to be determined by BLC_PWM_CTL bit +* 27. +*/ +static u32 hsw_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; +
Quoted 8 lines
drivers/gpu/drm/i915/intel_panel.c static void intel_backlight_device_unregister(struct intel_connector *connector) · line 1230
Quoted 2 lines
drivers/gpu/drm/i915/intel_panel.c +2
-0+if (I915_READ (SOUTH_CHICKEN2 ) &PWM_GRANULARITY ) + mul =16 ;According to the HSW, BDW, and SKL BSPECs the increment is 8 and 128 based on the PWM Granularity bit. The BDW and SKL ChromeOS reference designs uses the dedicated PWM pin and not the utility pin. So
BLC_PWM_CTRLbit 27 should be used forPWM_GRANULARITY. We probably need logic to switch between PCH and CPU PWMs.
No, it's the other way around. BLC_PWM_CTL bit 27 is used for granularity control when driving the utility pin. Yes, in theory we would need logic to switch between PCH/CPU PWMs, but in practise we do not support CPU PWM anywhere, and the last time I checked (probably like a year or two ago, admittedly) there were no designs using the CPU PWM. I've kind of decided to look at it when we get the first bug where backlight doesn't work because the design uses the utility pin.
Quoted 84 lines
Quoted 52 lines
drivers/gpu/drm/i915/intel_panel.c +51
-0+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. +* +* 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) +{drivers/gpu/drm/i915/intel_panel.c static void intel_backlight_device_unregister(struct intel_connector *connector) · line 1291
Quoted 10 lines
drivers/gpu/drm/i915/intel_panel.c +10
-0+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] 100MHz HRAW clocks) multiplied by 128 or 25MHz S0IX clocks VLV and CHV use a 200 Mhz HRAW clock. Since patch 1 in the series moved
intel_hrawclk()intointel_display.clets use the returned value instead of the hardcoded value.drivers/gpu/drm/i915/intel_panel.c static void intel_backlight_device_unregister(struct intel_connector *connector) · line 1294
Quoted 3 lines
drivers/gpu/drm/i915/intel_panel.c +3
-0+* multiplied by 16. +* +* XXX: Where is this selected??? This is currently selected in Bit 30 of
CBR1_VLV. Of courseintel_pm.cwrites this register as0x0during init so it doesn't surprise me that this test would also be0x0.drivers/gpu/drm/i915/intel_panel.c static void intel_backlight_device_unregister(struct intel_connector *connector) · line 1299
Quoted 5 lines
drivers/gpu/drm/i915/intel_panel.c +5
-0+*/ +static u32 vlv_hz_to_pwm (struct intel_connector *connector,u32 pwm_freq_hz) +{ +if (1 ) +return MHz (25 ) / (pwm_freq_hz *16 );CHV actually uses a 19.2 MHz S0IX clock and since the
MHz()macro doesn't accept floats we need to useKHz()macro.
Quoted 5 lines
drivers/gpu/drm/i915/intel_panel.c static void intel_backlight_device_unregister(struct intel_connector *connector) · line 1302
Quoted 3 lines
drivers/gpu/drm/i915/intel_panel.c +3
-0+else +return MHz (100 ) / (pwm_freq_hz *128 ); +}Here is the new function for the 3 previous issues
Thanks, this is the kind of review I like. :)
Quoted 125 lines
/*
* 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 u32vlv_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); } }Quoted 98 lines
drivers/gpu/drm/i915/intel_panel.c +53
-4+ +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) {@@ -1255,6 +1370,10 @@ static int bdw_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 ;@@ -1281,6 +1400,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 ;@@ -1312,12 +1435,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);@@ -1341,12 +1470,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);@@ -1386,6 +1519,10 @@ static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe
Quoted 7 lines
drivers/gpu/drm/i915/intel_panel.c static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe · line 1522
Quoted 3 lines
drivers/gpu/drm/i915/intel_panel.c +1
-0ctl =I915_READ (VLV_BLC_PWM_CTL (pipe)); panel->backlight.max = ctl >>16 ; +the
for_each_pipe()above this code hardcodes the upper 16 bits ofVLV_BLC_PWM_CTLto0xF42(307.4 Hz) so this code never executes. removing thefor_each_pipeblock above these adds resolves this issue.
Ack, I was thinking of making this a separate patch.
Quoted 18 lines
Quoted 18 lines
drivers/gpu/drm/i915/intel_panel.c +7
-0+if (!panel->backlight.max) + panel->backlight.max =get_backlight_max_vbt (connector); +if (!panel->backlight.max)return -ENODEV ;@@ -1412,6 +1549,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 ;
Quoted 9 lines
drivers/gpu/drm/i915/intel_panel.c void intel_panel_init_backlight_funcs(struct drm_device *dev) · line 1669
Quoted 5 lines
drivers/gpu/drm/i915/intel_panel.c +1
-0@@ -1525,12 +1666,14 @@ void intel_panel_init_backlight_funcs(struct drm_device *dev) dev_priv->display.disable_backlight = pch_disable_backlight; dev_priv->display.set_backlight = bdw_set_backlight; dev_priv->display.get_backlight = bdw_get_backlight; + dev_priv->display.backlight_hz_to_pwm = hsw_hz_to_pwm;We need to create a new function for SKL, and BXT that doesn't use the utility pin. and yes I understand that this patch was submitted 20 months ago. I'm investigating changes for BDW and SKL support.
Okay, so I've gone through the backlight register specs a few times too many, so I didn't do it this time. However, from memory, hsw, bdw and skl PCH backlight works just the same. We could use the current bdw/skl code for hsw just as well, we've just ended up letting the hardware send the messages from the CPU registers to PCH; this is possible on LPT PCH but no longer on SPT PCH. (See bdw_enable_backlight; LPT PCH *allows* setting or not setting BLM_PCH_OVERRIDE_ENABLE, after that it's the default.)
Again, we do not support CPU backlight anywhere on PCH split platforms, it's just the passing of messages from CPU registers to PCH. We also don't support backlight on the utility pin (there's patches to add this to bxt, but that's different anyway).
---
I think I know too much about backlight. And by too much I mean that I know enough to know I don't know nowhere near enough, and that thought really scares me. I don't want to know more about backlight. I'd rather regress to the blissful ignorance and the naïve misconception that backlight should be easy.
BR,
Jani.
Quoted 36 lines
Quoted 35 lines
drivers/gpu/drm/i915/intel_panel.c +4
-0}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;@@ -1544,6 +1687,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;@@ -1551,12 +1695,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; } }
Signature · 5 lines
Jani Nikula, Intel Open Source Technology Center _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 2/2] drm/i915: initialize backlight max from VBT
Quoted 85 lines · Jani Nikula
Quoted 30 lines · Clint Taylor
Quoted 29 lines · Jani Nikula
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.
Signed-off-by Jani Nikula <[email protected]>--- drivers/gpu/drm/i915/i915_drv.h | 2 + drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_panel.c | 160 +++++++++++++++++++++++++++++++++++-- 3 files changed, 156 insertions(+), 7 deletions(-)drivers/gpu/drm/i915/i915_drv.h +2
-0@@ -665,6 +665,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); };Quoted 13 lines
drivers/gpu/drm/i915/i915_reg.h enum skl_disp_power_wells { · line 6319
Quoted 10 lines
drivers/gpu/drm/i915/i915_drv.h +0
-0enum forcewake_domain_id {drivers/gpu/drm/i915/i915_reg.h +1
-0@@ -6316,6 +6316,7 @@ enum skl_disp_power_wells {#define SOUTH_CHICKEN2 0xc2004#define FDI_MPHY_IOSFSB_RESET_STATUS (1<<13)#define FDI_MPHY_IOSFSB_RESET_CTL (1<<12) +#define PWM_GRANULARITY (1<<5)/* LPT */ Shouldn't we be using the
BLC_PWM_CTLversion of thePWM_GRANULARITYbit on HSW and later?Only when driving the backlight on the utility pin.
Quoted 29 lines
Quoted 29 lines
drivers/gpu/drm/i915/i915_reg.h +0
-0#define DPLS_EDP_PPS_FIX_DIS (1<<0)#define _FDI_RXA_CHICKEN 0xc200cdrivers/gpu/drm/i915/intel_panel.c +13
-3@@ -1212,10 +1212,125 @@ 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! +* HSW/BDW: 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). * -* XXX: Query mode clock or hardware clock and program PWM modulation frequency -* appropriately when it's 0. Use VBT and/or sane defaults. +* XXX: This only works when driving the PCH PWM. When driving the CPU PWM on +* the utility pin, the granularity needs to be determined by BLC_PWM_CTL bit +* 27. +*/ +static u32 hsw_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; +Quoted 8 lines
drivers/gpu/drm/i915/intel_panel.c static void intel_backlight_device_unregister(struct intel_connector *connector) · line 1230
Quoted 2 lines
drivers/gpu/drm/i915/intel_panel.c +2
-0+if (I915_READ (SOUTH_CHICKEN2 ) &PWM_GRANULARITY ) + mul =16 ;According to the HSW, BDW, and SKL BSPECs the increment is 8 and 128 based on the PWM Granularity bit. The BDW and SKL ChromeOS reference designs uses the dedicated PWM pin and not the utility pin. So
BLC_PWM_CTRLbit 27 should be used forPWM_GRANULARITY. We probably need logic to switch between PCH and CPU PWMs.
Quoted 7 lines
No, it's the other way around.
BLC_PWM_CTLbit 27 is used for granularity control when driving the utility pin. Yes, in theory we would need logic to switch between PCH/CPU PWMs, but in practise we do not support CPU PWM anywhere, and the last time I checked (probably like a year or two ago, admittedly) there were no designs using the CPU PWM. I've kind of decided to look at it when we get the first bug where backlight doesn't work because the design uses the utility pin.
Addition, for SKL/SPT we need to look at SOUTH_CHICKEN_1 bit 0.
BR,
Jani.
Quoted 320 lines
Quoted 85 lines
Quoted 53 lines
drivers/gpu/drm/i915/intel_panel.c +51
-0+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. +* +* 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) +{drivers/gpu/drm/i915/intel_panel.c static void intel_backlight_device_unregister(struct intel_connector *connector) · line 1291
Quoted 10 lines
drivers/gpu/drm/i915/intel_panel.c +10
-0+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] 100MHz HRAW clocks) multiplied by 128 or 25MHz S0IX clocks VLV and CHV use a 200 Mhz HRAW clock. Since patch 1 in the series moved
intel_hrawclk()intointel_display.clets use the returned value instead of the hardcoded value.drivers/gpu/drm/i915/intel_panel.c static void intel_backlight_device_unregister(struct intel_connector *connector) · line 1294
Quoted 3 lines
drivers/gpu/drm/i915/intel_panel.c +3
-0+* multiplied by 16. +* +* XXX: Where is this selected??? This is currently selected in Bit 30 of
CBR1_VLV. Of courseintel_pm.cwrites this register as0x0during init so it doesn't surprise me that this test would also be0x0.drivers/gpu/drm/i915/intel_panel.c static void intel_backlight_device_unregister(struct intel_connector *connector) · line 1299
Quoted 5 lines
drivers/gpu/drm/i915/intel_panel.c +5
-0+*/ +static u32 vlv_hz_to_pwm (struct intel_connector *connector,u32 pwm_freq_hz) +{ +if (1 ) +return MHz (25 ) / (pwm_freq_hz *16 );CHV actually uses a 19.2 MHz S0IX clock and since the
MHz()macro doesn't accept floats we need to useKHz()macro.Quoted 5 lines
drivers/gpu/drm/i915/intel_panel.c static void intel_backlight_device_unregister(struct intel_connector *connector) · line 1302
Quoted 3 lines
drivers/gpu/drm/i915/intel_panel.c +3
-0+else +return MHz (100 ) / (pwm_freq_hz *128 ); +}Here is the new function for the 3 previous issues
Thanks, this is the kind of review I like. :)
Quoted 125 lines
/*
* 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 u32vlv_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); } }Quoted 98 lines
drivers/gpu/drm/i915/intel_panel.c +53
-4+ +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) {@@ -1255,6 +1370,10 @@ static int bdw_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 ;@@ -1281,6 +1400,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 ;@@ -1312,12 +1435,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);@@ -1341,12 +1470,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);@@ -1386,6 +1519,10 @@ static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipeQuoted 7 lines
drivers/gpu/drm/i915/intel_panel.c static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe · line 1522
Quoted 3 lines
drivers/gpu/drm/i915/intel_panel.c +1
-0ctl =I915_READ (VLV_BLC_PWM_CTL (pipe)); panel->backlight.max = ctl >>16 ; +the
for_each_pipe()above this code hardcodes the upper 16 bits ofVLV_BLC_PWM_CTLto0xF42(307.4 Hz) so this code never executes. removing thefor_each_pipeblock above these adds resolves this issue.Ack, I was thinking of making this a separate patch.
Quoted 18 lines
Quoted 18 lines
drivers/gpu/drm/i915/intel_panel.c +7
-0+if (!panel->backlight.max) + panel->backlight.max =get_backlight_max_vbt (connector); +if (!panel->backlight.max)return -ENODEV ;@@ -1412,6 +1549,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 ;Quoted 9 lines
drivers/gpu/drm/i915/intel_panel.c void intel_panel_init_backlight_funcs(struct drm_device *dev) · line 1669
Quoted 5 lines
drivers/gpu/drm/i915/intel_panel.c +1
-0@@ -1525,12 +1666,14 @@ void intel_panel_init_backlight_funcs(struct drm_device *dev) dev_priv->display.disable_backlight = pch_disable_backlight; dev_priv->display.set_backlight = bdw_set_backlight; dev_priv->display.get_backlight = bdw_get_backlight; + dev_priv->display.backlight_hz_to_pwm = hsw_hz_to_pwm;We need to create a new function for SKL, and BXT that doesn't use the utility pin. and yes I understand that this patch was submitted 20 months ago. I'm investigating changes for BDW and SKL support.
Okay, so I've gone through the backlight register specs a few times too many, so I didn't do it this time. However, from memory, hsw, bdw and skl PCH backlight works just the same. We could use the current bdw/skl code for hsw just as well, we've just ended up letting the hardware send the messages from the CPU registers to PCH; this is possible on LPT PCH but no longer on SPT PCH. (See
bdw_enable_backlight; LPT PCH *allows* setting or not settingBLM_PCH_OVERRIDE_ENABLE, after that it's the default.)Again, we do not support CPU backlight anywhere on PCH split platforms, it's just the passing of messages from CPU registers to PCH. We also don't support backlight on the utility pin (there's patches to add this to bxt, but that's different anyway).
---
I think I know too much about backlight. And by too much I mean that I know enough to know I don't know nowhere near enough, and that thought really scares me. I don't want to know more about backlight. I'd rather regress to the blissful ignorance and the naïve misconception that backlight should be easy.
BR,
Jani.Quoted 36 lines
Quoted 35 lines
drivers/gpu/drm/i915/intel_panel.c +4
-0}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;@@ -1544,6 +1687,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;@@ -1551,12 +1695,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; } }Signature · 1 line
Jani Nikula, Intel Open Source Technology Center
Signature · 5 lines
Jani Nikula, Intel Open Source Technology Center _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx