gma500: Fix backlight crash

Initial changes to get backlight behaviour we want and to fix backlight crashes
on suspend/resume paths.

[Note: on some boxes this will now produce a warning about the backlight, this
 isn't a regression it's an unfixed but non harmful case I still need to nail]

Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
Alan Cox 2011-11-29 22:26:58 +00:00 committed by Dave Airlie
parent 2357f7e61f
commit 1f0d0b5183
2 changed files with 33 additions and 27 deletions

View File

@ -302,7 +302,7 @@ int psb_runtime_suspend(struct device *dev)
int psb_runtime_resume(struct device *dev) int psb_runtime_resume(struct device *dev)
{ {
return 0; return gma_power_resume(dev);;
} }
int psb_runtime_idle(struct device *dev) int psb_runtime_idle(struct device *dev)

View File

@ -68,20 +68,23 @@ struct psb_intel_lvds_priv {
static u32 psb_intel_lvds_get_max_backlight(struct drm_device *dev) static u32 psb_intel_lvds_get_max_backlight(struct drm_device *dev)
{ {
struct drm_psb_private *dev_priv = dev->dev_private; struct drm_psb_private *dev_priv = dev->dev_private;
u32 retVal; u32 ret;
if (gma_power_begin(dev, false)) { if (gma_power_begin(dev, false)) {
retVal = ((REG_READ(BLC_PWM_CTL) & ret = REG_READ(BLC_PWM_CTL);
BACKLIGHT_MODULATION_FREQ_MASK) >>
BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
gma_power_end(dev); gma_power_end(dev);
} else } else /* Powered off, use the saved value */
retVal = ((dev_priv->saveBLC_PWM_CTL & ret = dev_priv->saveBLC_PWM_CTL;
BACKLIGHT_MODULATION_FREQ_MASK) >>
BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
return retVal; /* Top 15bits hold the frequency mask */
ret = (ret & BACKLIGHT_MODULATION_FREQ_MASK) >>
BACKLIGHT_MODULATION_FREQ_SHIFT;
ret *= 2; /* Return a 16bit range as needed for setting */
if (ret == 0)
dev_err(dev->dev, "BL bug: Reg %08x save %08X\n",
REG_READ(BLC_PWM_CTL), dev_priv->saveBLC_PWM_CTL);
return ret;
} }
/* /*
@ -142,7 +145,7 @@ static int psb_lvds_pwm_set_brightness(struct drm_device *dev, int level)
max_pwm_blc = psb_intel_lvds_get_max_backlight(dev); max_pwm_blc = psb_intel_lvds_get_max_backlight(dev);
/*BLC_PWM_CTL Should be initiated while backlight device init*/ /*BLC_PWM_CTL Should be initiated while backlight device init*/
BUG_ON((max_pwm_blc & PSB_BLC_MAX_PWM_REG_FREQ) == 0); BUG_ON(max_pwm_blc == 0);
blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL; blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL;
@ -154,6 +157,10 @@ static int psb_lvds_pwm_set_brightness(struct drm_device *dev, int level)
(max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) | (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) |
(blc_pwm_duty_cycle)); (blc_pwm_duty_cycle));
dev_info(dev->dev, "Backlight lvds set brightness %08x\n",
(max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) |
(blc_pwm_duty_cycle));
return 0; return 0;
} }
@ -162,14 +169,12 @@ static int psb_lvds_pwm_set_brightness(struct drm_device *dev, int level)
*/ */
void psb_intel_lvds_set_brightness(struct drm_device *dev, int level) void psb_intel_lvds_set_brightness(struct drm_device *dev, int level)
{ {
/*u32 blc_pwm_ctl;*/ struct drm_psb_private *dev_priv = dev->dev_private;
struct drm_psb_private *dev_priv =
(struct drm_psb_private *)dev->dev_private;
dev_dbg(dev->dev, "backlight level is %d\n", level); dev_dbg(dev->dev, "backlight level is %d\n", level);
if (!dev_priv->lvds_bl) { if (!dev_priv->lvds_bl) {
dev_err(dev->dev, "NO LVDS Backlight Info\n"); dev_err(dev->dev, "NO LVDS backlight info\n");
return; return;
} }
@ -190,11 +195,13 @@ static void psb_intel_lvds_set_backlight(struct drm_device *dev, int level)
u32 blc_pwm_ctl; u32 blc_pwm_ctl;
if (gma_power_begin(dev, false)) { if (gma_power_begin(dev, false)) {
blc_pwm_ctl = blc_pwm_ctl = REG_READ(BLC_PWM_CTL);
REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK;
REG_WRITE(BLC_PWM_CTL, REG_WRITE(BLC_PWM_CTL,
(blc_pwm_ctl | (blc_pwm_ctl |
(level << BACKLIGHT_DUTY_CYCLE_SHIFT))); (level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl |
(level << BACKLIGHT_DUTY_CYCLE_SHIFT));
gma_power_end(dev); gma_power_end(dev);
} else { } else {
blc_pwm_ctl = dev_priv->saveBLC_PWM_CTL & blc_pwm_ctl = dev_priv->saveBLC_PWM_CTL &
@ -212,9 +219,11 @@ static void psb_intel_lvds_set_power(struct drm_device *dev,
{ {
u32 pp_status; u32 pp_status;
if (!gma_power_begin(dev, true)) if (!gma_power_begin(dev, true)) {
dev_err(dev->dev, "set power, chip off!\n");
return; return;
}
if (on) { if (on) {
REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) |
POWER_TARGET_ON); POWER_TARGET_ON);
@ -296,9 +305,6 @@ static void psb_intel_lvds_restore(struct drm_connector *connector)
{ {
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
u32 pp_status; u32 pp_status;
/*struct drm_psb_private *dev_priv =
(struct drm_psb_private *)dev->dev_private;*/
struct psb_intel_output *psb_intel_output = struct psb_intel_output *psb_intel_output =
to_psb_intel_output(connector); to_psb_intel_output(connector);
struct psb_intel_lvds_priv *lvds_priv = struct psb_intel_lvds_priv *lvds_priv =
@ -621,7 +627,8 @@ int psb_intel_lvds_set_property(struct drm_connector *connector,
goto set_prop_error; goto set_prop_error;
else { else {
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
struct drm_psb_private *devp = encoder->dev->dev_private; struct drm_psb_private *devp =
encoder->dev->dev_private;
struct backlight_device *bd = devp->backlight_device; struct backlight_device *bd = devp->backlight_device;
if (bd) { if (bd) {
bd->props.brightness = value; bd->props.brightness = value;
@ -694,8 +701,7 @@ void psb_intel_lvds_init(struct drm_device *dev,
struct drm_encoder *encoder; struct drm_encoder *encoder;
struct drm_display_mode *scan; /* *modes, *bios_mode; */ struct drm_display_mode *scan; /* *modes, *bios_mode; */
struct drm_crtc *crtc; struct drm_crtc *crtc;
struct drm_psb_private *dev_priv = struct drm_psb_private *dev_priv = dev->dev_private;
(struct drm_psb_private *)dev->dev_private;
u32 lvds; u32 lvds;
int pipe; int pipe;
@ -711,8 +717,8 @@ void psb_intel_lvds_init(struct drm_device *dev,
} }
psb_intel_output->dev_priv = lvds_priv; psb_intel_output->dev_priv = lvds_priv;
psb_intel_output->mode_dev = mode_dev; psb_intel_output->mode_dev = mode_dev;
connector = &psb_intel_output->base; connector = &psb_intel_output->base;
encoder = &psb_intel_output->enc; encoder = &psb_intel_output->enc;
drm_connector_init(dev, &psb_intel_output->base, drm_connector_init(dev, &psb_intel_output->base,