diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 8c24851b930c..8d7be66d96bc 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3627,17 +3627,29 @@ enum skl_disp_power_wells { #define UTIL_PIN_CTL 0x48400 #define UTIL_PIN_ENABLE (1 << 31) +#define UTIL_PIN_PIPE(x) ((x) << 29) +#define UTIL_PIN_PIPE_MASK (3 << 29) +#define UTIL_PIN_MODE_PWM (1 << 24) +#define UTIL_PIN_MODE_MASK (0xf << 24) +#define UTIL_PIN_POLARITY (1 << 22) + /* BXT backlight register definition. */ -#define BXT_BLC_PWM_CTL1 0xC8250 +#define _BXT_BLC_PWM_CTL1 0xC8250 #define BXT_BLC_PWM_ENABLE (1 << 31) #define BXT_BLC_PWM_POLARITY (1 << 29) -#define BXT_BLC_PWM_FREQ1 0xC8254 -#define BXT_BLC_PWM_DUTY1 0xC8258 +#define _BXT_BLC_PWM_FREQ1 0xC8254 +#define _BXT_BLC_PWM_DUTY1 0xC8258 -#define BXT_BLC_PWM_CTL2 0xC8350 -#define BXT_BLC_PWM_FREQ2 0xC8354 -#define BXT_BLC_PWM_DUTY2 0xC8358 +#define _BXT_BLC_PWM_CTL2 0xC8350 +#define _BXT_BLC_PWM_FREQ2 0xC8354 +#define _BXT_BLC_PWM_DUTY2 0xC8358 +#define BXT_BLC_PWM_CTL(controller) _PIPE(controller, \ + _BXT_BLC_PWM_CTL1, _BXT_BLC_PWM_CTL2) +#define BXT_BLC_PWM_FREQ(controller) _PIPE(controller, \ + _BXT_BLC_PWM_FREQ1, _BXT_BLC_PWM_FREQ2) +#define BXT_BLC_PWM_DUTY(controller) _PIPE(controller, \ + _BXT_BLC_PWM_DUTY1, _BXT_BLC_PWM_DUTY2) #define PCH_GTC_CTL 0xe7000 #define PCH_GTC_ENABLE (1 << 31) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index dfd2d10d3d3c..563c4f1e3685 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -179,6 +179,8 @@ struct intel_panel { bool active_low_pwm; /* PWM chip */ + bool util_pin_active_low; /* bxt+ */ + u8 controller; /* bxt+ only */ struct pwm_device *pwm; struct backlight_device *device; diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 4d28c7b904e7..f30c996e882c 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -536,9 +536,10 @@ static u32 vlv_get_backlight(struct intel_connector *connector) static u32 bxt_get_backlight(struct intel_connector *connector) { struct drm_device *dev = connector->base.dev; + struct intel_panel *panel = &connector->panel; struct drm_i915_private *dev_priv = dev->dev_private; - return I915_READ(BXT_BLC_PWM_DUTY1); + return I915_READ(BXT_BLC_PWM_DUTY(panel->backlight.controller)); } static u32 pwm_get_backlight(struct intel_connector *connector) @@ -634,8 +635,9 @@ static void bxt_set_backlight(struct intel_connector *connector, u32 level) { struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_panel *panel = &connector->panel; - I915_WRITE(BXT_BLC_PWM_DUTY1, level); + I915_WRITE(BXT_BLC_PWM_DUTY(panel->backlight.controller), level); } static void pwm_set_backlight(struct intel_connector *connector, u32 level) @@ -786,12 +788,20 @@ static void bxt_disable_backlight(struct intel_connector *connector) { struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - u32 tmp; + struct intel_panel *panel = &connector->panel; + u32 tmp, val; intel_panel_actually_set_backlight(connector, 0); - tmp = I915_READ(BXT_BLC_PWM_CTL1); - I915_WRITE(BXT_BLC_PWM_CTL1, tmp & ~BXT_BLC_PWM_ENABLE); + tmp = I915_READ(BXT_BLC_PWM_CTL(panel->backlight.controller)); + I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller), + tmp & ~BXT_BLC_PWM_ENABLE); + + if (panel->backlight.controller == 1) { + val = I915_READ(UTIL_PIN_CTL); + val &= ~UTIL_PIN_ENABLE; + I915_WRITE(UTIL_PIN_CTL, val); + } } static void pwm_disable_backlight(struct intel_connector *connector) @@ -1023,16 +1033,38 @@ static void bxt_enable_backlight(struct intel_connector *connector) struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_panel *panel = &connector->panel; - u32 pwm_ctl; + enum pipe pipe = intel_get_pipe_from_connector(connector); + u32 pwm_ctl, val; - pwm_ctl = I915_READ(BXT_BLC_PWM_CTL1); + /* To use 2nd set of backlight registers, utility pin has to be + * enabled with PWM mode. + * The field should only be changed when the utility pin is disabled + */ + if (panel->backlight.controller == 1) { + val = I915_READ(UTIL_PIN_CTL); + if (val & UTIL_PIN_ENABLE) { + DRM_DEBUG_KMS("util pin already enabled\n"); + val &= ~UTIL_PIN_ENABLE; + I915_WRITE(UTIL_PIN_CTL, val); + } + + val = 0; + if (panel->backlight.util_pin_active_low) + val |= UTIL_PIN_POLARITY; + I915_WRITE(UTIL_PIN_CTL, val | UTIL_PIN_PIPE(pipe) | + UTIL_PIN_MODE_PWM | UTIL_PIN_ENABLE); + } + + pwm_ctl = I915_READ(BXT_BLC_PWM_CTL(panel->backlight.controller)); if (pwm_ctl & BXT_BLC_PWM_ENABLE) { DRM_DEBUG_KMS("backlight already enabled\n"); pwm_ctl &= ~BXT_BLC_PWM_ENABLE; - I915_WRITE(BXT_BLC_PWM_CTL1, pwm_ctl); + I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller), + pwm_ctl); } - I915_WRITE(BXT_BLC_PWM_FREQ1, panel->backlight.max); + I915_WRITE(BXT_BLC_PWM_FREQ(panel->backlight.controller), + panel->backlight.max); intel_panel_actually_set_backlight(connector, panel->backlight.level); @@ -1040,9 +1072,10 @@ static void bxt_enable_backlight(struct intel_connector *connector) if (panel->backlight.active_low_pwm) pwm_ctl |= BXT_BLC_PWM_POLARITY; - I915_WRITE(BXT_BLC_PWM_CTL1, pwm_ctl); - POSTING_READ(BXT_BLC_PWM_CTL1); - I915_WRITE(BXT_BLC_PWM_CTL1, pwm_ctl | BXT_BLC_PWM_ENABLE); + I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl); + POSTING_READ(BXT_BLC_PWM_CTL(panel->backlight.controller)); + I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller), + pwm_ctl | BXT_BLC_PWM_ENABLE); } static void pwm_enable_backlight(struct intel_connector *connector) @@ -1562,10 +1595,28 @@ bxt_setup_backlight(struct intel_connector *connector, enum pipe unused) struct intel_panel *panel = &connector->panel; u32 pwm_ctl, val; - pwm_ctl = I915_READ(BXT_BLC_PWM_CTL1); - panel->backlight.active_low_pwm = pwm_ctl & BXT_BLC_PWM_POLARITY; + /* + * For BXT hard coding the Backlight controller to 0. + * TODO : Read the controller value from VBT and generalize + */ + panel->backlight.controller = 0; - panel->backlight.max = I915_READ(BXT_BLC_PWM_FREQ1); + pwm_ctl = I915_READ(BXT_BLC_PWM_CTL(panel->backlight.controller)); + + /* Keeping the check if controller 1 is to be programmed. + * This will come into affect once the VBT parsing + * is fixed for controller selection, and controller 1 is used + * for a prticular display configuration. + */ + if (panel->backlight.controller == 1) { + val = I915_READ(UTIL_PIN_CTL); + panel->backlight.util_pin_active_low = + val & UTIL_PIN_POLARITY; + } + + panel->backlight.active_low_pwm = pwm_ctl & BXT_BLC_PWM_POLARITY; + panel->backlight.max = + I915_READ(BXT_BLC_PWM_FREQ(panel->backlight.controller)); if (!panel->backlight.max) panel->backlight.max = get_backlight_max_vbt(connector);