50,22 → 50,23 |
struct intel_crtc_config *pipe_config, |
int fitting_mode) |
{ |
struct drm_display_mode *adjusted_mode; |
struct drm_display_mode *mode, *adjusted_mode; |
int x, y, width, height; |
|
mode = &pipe_config->requested_mode; |
adjusted_mode = &pipe_config->adjusted_mode; |
|
x = y = width = height = 0; |
|
/* Native modes don't need fitting */ |
if (adjusted_mode->hdisplay == pipe_config->pipe_src_w && |
adjusted_mode->vdisplay == pipe_config->pipe_src_h) |
if (adjusted_mode->hdisplay == mode->hdisplay && |
adjusted_mode->vdisplay == mode->vdisplay) |
goto done; |
|
switch (fitting_mode) { |
case DRM_MODE_SCALE_CENTER: |
width = pipe_config->pipe_src_w; |
height = pipe_config->pipe_src_h; |
width = mode->hdisplay; |
height = mode->vdisplay; |
x = (adjusted_mode->hdisplay - width + 1)/2; |
y = (adjusted_mode->vdisplay - height + 1)/2; |
break; |
73,12 → 74,10 |
case DRM_MODE_SCALE_ASPECT: |
/* Scale but preserve the aspect ratio */ |
{ |
u32 scaled_width = adjusted_mode->hdisplay |
* pipe_config->pipe_src_h; |
u32 scaled_height = pipe_config->pipe_src_w |
* adjusted_mode->vdisplay; |
u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay; |
u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay; |
if (scaled_width > scaled_height) { /* pillar */ |
width = scaled_height / pipe_config->pipe_src_h; |
width = scaled_height / mode->vdisplay; |
if (width & 1) |
width++; |
x = (adjusted_mode->hdisplay - width + 1) / 2; |
85,7 → 84,7 |
y = 0; |
height = adjusted_mode->vdisplay; |
} else if (scaled_width < scaled_height) { /* letter */ |
height = scaled_width / pipe_config->pipe_src_w; |
height = scaled_width / mode->hdisplay; |
if (height & 1) |
height++; |
y = (adjusted_mode->vdisplay - height + 1) / 2; |
172,37 → 171,54 |
return (FACTOR * ratio + FACTOR/2) / FACTOR; |
} |
|
static void i965_scale_aspect(struct intel_crtc_config *pipe_config, |
u32 *pfit_control) |
void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc, |
struct intel_crtc_config *pipe_config, |
int fitting_mode) |
{ |
struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; |
struct drm_device *dev = intel_crtc->base.dev; |
u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; |
struct drm_display_mode *mode, *adjusted_mode; |
|
mode = &pipe_config->requested_mode; |
adjusted_mode = &pipe_config->adjusted_mode; |
|
/* Native modes don't need fitting */ |
if (adjusted_mode->hdisplay == mode->hdisplay && |
adjusted_mode->vdisplay == mode->vdisplay) |
goto out; |
|
switch (fitting_mode) { |
case DRM_MODE_SCALE_CENTER: |
/* |
* For centered modes, we have to calculate border widths & |
* heights and modify the values programmed into the CRTC. |
*/ |
centre_horizontally(adjusted_mode, mode->hdisplay); |
centre_vertically(adjusted_mode, mode->vdisplay); |
border = LVDS_BORDER_ENABLE; |
break; |
case DRM_MODE_SCALE_ASPECT: |
/* Scale but preserve the aspect ratio */ |
if (INTEL_INFO(dev)->gen >= 4) { |
u32 scaled_width = adjusted_mode->hdisplay * |
pipe_config->pipe_src_h; |
u32 scaled_height = pipe_config->pipe_src_w * |
mode->vdisplay; |
u32 scaled_height = mode->hdisplay * |
adjusted_mode->vdisplay; |
|
/* 965+ is easy, it does everything in hw */ |
if (scaled_width > scaled_height) |
*pfit_control |= PFIT_ENABLE | |
pfit_control |= PFIT_ENABLE | |
PFIT_SCALING_PILLAR; |
else if (scaled_width < scaled_height) |
*pfit_control |= PFIT_ENABLE | |
pfit_control |= PFIT_ENABLE | |
PFIT_SCALING_LETTER; |
else if (adjusted_mode->hdisplay != pipe_config->pipe_src_w) |
*pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO; |
} |
|
static void i9xx_scale_aspect(struct intel_crtc_config *pipe_config, |
u32 *pfit_control, u32 *pfit_pgm_ratios, |
u32 *border) |
{ |
struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; |
else if (adjusted_mode->hdisplay != mode->hdisplay) |
pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO; |
} else { |
u32 scaled_width = adjusted_mode->hdisplay * |
pipe_config->pipe_src_h; |
u32 scaled_height = pipe_config->pipe_src_w * |
mode->vdisplay; |
u32 scaled_height = mode->hdisplay * |
adjusted_mode->vdisplay; |
u32 bits; |
|
/* |
* For earlier chips we have to calculate the scaling |
* ratio by hand and program it into the |
211,16 → 227,14 |
if (scaled_width > scaled_height) { /* pillar */ |
centre_horizontally(adjusted_mode, |
scaled_height / |
pipe_config->pipe_src_h); |
mode->vdisplay); |
|
*border = LVDS_BORDER_ENABLE; |
if (pipe_config->pipe_src_h != adjusted_mode->vdisplay) { |
bits = panel_fitter_scaling(pipe_config->pipe_src_h, |
adjusted_mode->vdisplay); |
|
*pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | |
border = LVDS_BORDER_ENABLE; |
if (mode->vdisplay != adjusted_mode->vdisplay) { |
u32 bits = panel_fitter_scaling(mode->vdisplay, adjusted_mode->vdisplay); |
pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | |
bits << PFIT_VERT_SCALE_SHIFT); |
*pfit_control |= (PFIT_ENABLE | |
pfit_control |= (PFIT_ENABLE | |
VERT_INTERP_BILINEAR | |
HORIZ_INTERP_BILINEAR); |
} |
227,68 → 241,33 |
} else if (scaled_width < scaled_height) { /* letter */ |
centre_vertically(adjusted_mode, |
scaled_width / |
pipe_config->pipe_src_w); |
mode->hdisplay); |
|
*border = LVDS_BORDER_ENABLE; |
if (pipe_config->pipe_src_w != adjusted_mode->hdisplay) { |
bits = panel_fitter_scaling(pipe_config->pipe_src_w, |
adjusted_mode->hdisplay); |
|
*pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | |
border = LVDS_BORDER_ENABLE; |
if (mode->hdisplay != adjusted_mode->hdisplay) { |
u32 bits = panel_fitter_scaling(mode->hdisplay, adjusted_mode->hdisplay); |
pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | |
bits << PFIT_VERT_SCALE_SHIFT); |
*pfit_control |= (PFIT_ENABLE | |
pfit_control |= (PFIT_ENABLE | |
VERT_INTERP_BILINEAR | |
HORIZ_INTERP_BILINEAR); |
} |
} else { |
/* Aspects match, Let hw scale both directions */ |
*pfit_control |= (PFIT_ENABLE | |
pfit_control |= (PFIT_ENABLE | |
VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | |
VERT_INTERP_BILINEAR | |
HORIZ_INTERP_BILINEAR); |
} |
} |
|
void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc, |
struct intel_crtc_config *pipe_config, |
int fitting_mode) |
{ |
struct drm_device *dev = intel_crtc->base.dev; |
u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; |
struct drm_display_mode *adjusted_mode; |
|
adjusted_mode = &pipe_config->adjusted_mode; |
|
/* Native modes don't need fitting */ |
if (adjusted_mode->hdisplay == pipe_config->pipe_src_w && |
adjusted_mode->vdisplay == pipe_config->pipe_src_h) |
goto out; |
|
switch (fitting_mode) { |
case DRM_MODE_SCALE_CENTER: |
/* |
* For centered modes, we have to calculate border widths & |
* heights and modify the values programmed into the CRTC. |
*/ |
centre_horizontally(adjusted_mode, pipe_config->pipe_src_w); |
centre_vertically(adjusted_mode, pipe_config->pipe_src_h); |
border = LVDS_BORDER_ENABLE; |
break; |
case DRM_MODE_SCALE_ASPECT: |
/* Scale but preserve the aspect ratio */ |
if (INTEL_INFO(dev)->gen >= 4) |
i965_scale_aspect(pipe_config, &pfit_control); |
else |
i9xx_scale_aspect(pipe_config, &pfit_control, |
&pfit_pgm_ratios, &border); |
break; |
case DRM_MODE_SCALE_FULLSCREEN: |
/* |
* Full scaling, even if it changes the aspect ratio. |
* Fortunately this is all done for us in hw. |
*/ |
if (pipe_config->pipe_src_h != adjusted_mode->vdisplay || |
pipe_config->pipe_src_w != adjusted_mode->hdisplay) { |
if (mode->vdisplay != adjusted_mode->vdisplay || |
mode->hdisplay != adjusted_mode->hdisplay) { |
pfit_control |= PFIT_ENABLE; |
if (INTEL_INFO(dev)->gen >= 4) |
pfit_control |= PFIT_SCALING_AUTO; |
325,6 → 304,81 |
pipe_config->gmch_pfit.lvds_border_bits = border; |
} |
|
static int is_backlight_combination_mode(struct drm_device *dev) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
|
if (INTEL_INFO(dev)->gen >= 4) |
return I915_READ(BLC_PWM_CTL2) & BLM_COMBINATION_MODE; |
|
if (IS_GEN2(dev)) |
return I915_READ(BLC_PWM_CTL) & BLM_LEGACY_MODE; |
|
return 0; |
} |
|
/* XXX: query mode clock or hardware clock and program max PWM appropriately |
* when it's 0. |
*/ |
static u32 i915_read_blc_pwm_ctl(struct drm_device *dev) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
u32 val; |
|
// WARN_ON_SMP(!spin_is_locked(&dev_priv->backlight.lock)); |
|
/* Restore the CTL value if it lost, e.g. GPU reset */ |
|
if (HAS_PCH_SPLIT(dev_priv->dev)) { |
val = I915_READ(BLC_PWM_PCH_CTL2); |
if (dev_priv->regfile.saveBLC_PWM_CTL2 == 0) { |
dev_priv->regfile.saveBLC_PWM_CTL2 = val; |
} else if (val == 0) { |
val = dev_priv->regfile.saveBLC_PWM_CTL2; |
I915_WRITE(BLC_PWM_PCH_CTL2, val); |
} |
} else { |
val = I915_READ(BLC_PWM_CTL); |
if (dev_priv->regfile.saveBLC_PWM_CTL == 0) { |
dev_priv->regfile.saveBLC_PWM_CTL = val; |
if (INTEL_INFO(dev)->gen >= 4) |
dev_priv->regfile.saveBLC_PWM_CTL2 = |
I915_READ(BLC_PWM_CTL2); |
} else if (val == 0) { |
val = dev_priv->regfile.saveBLC_PWM_CTL; |
I915_WRITE(BLC_PWM_CTL, val); |
if (INTEL_INFO(dev)->gen >= 4) |
I915_WRITE(BLC_PWM_CTL2, |
dev_priv->regfile.saveBLC_PWM_CTL2); |
} |
} |
|
return val; |
} |
|
static u32 intel_panel_get_max_backlight(struct drm_device *dev) |
{ |
u32 max; |
|
max = i915_read_blc_pwm_ctl(dev); |
|
if (HAS_PCH_SPLIT(dev)) { |
max >>= 16; |
} else { |
if (INTEL_INFO(dev)->gen < 4) |
max >>= 17; |
else |
max >>= 16; |
|
if (is_backlight_combination_mode(dev)) |
max *= 0xff; |
} |
|
DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max); |
|
return max; |
} |
|
static int i915_panel_invert_brightness; |
MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness " |
"(-1 force normal, 0 machine defaults, 1 force inversion), please " |
332,256 → 386,110 |
"to dri-devel@lists.freedesktop.org, if your machine needs it. " |
"It will then be included in an upcoming module version."); |
module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600); |
static u32 intel_panel_compute_brightness(struct intel_connector *connector, |
u32 val) |
static u32 intel_panel_compute_brightness(struct drm_device *dev, u32 val) |
{ |
struct drm_device *dev = connector->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_panel *panel = &connector->panel; |
|
WARN_ON(panel->backlight.max == 0); |
|
if (i915_panel_invert_brightness < 0) |
return val; |
|
if (i915_panel_invert_brightness > 0 || |
dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) { |
return panel->backlight.max - val; |
u32 max = intel_panel_get_max_backlight(dev); |
if (max) |
return max - val; |
} |
|
return val; |
} |
|
static u32 bdw_get_backlight(struct intel_connector *connector) |
static u32 intel_panel_get_backlight(struct drm_device *dev) |
{ |
struct drm_device *dev = connector->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
u32 val; |
unsigned long flags; |
|
return I915_READ(BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK; |
} |
spin_lock_irqsave(&dev_priv->backlight.lock, flags); |
|
static u32 pch_get_backlight(struct intel_connector *connector) |
{ |
struct drm_device *dev = connector->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
|
return I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; |
} |
|
static u32 i9xx_get_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 val; |
|
if (HAS_PCH_SPLIT(dev)) { |
val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; |
} else { |
val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; |
if (INTEL_INFO(dev)->gen < 4) |
val >>= 1; |
|
if (panel->backlight.combination_mode) { |
if (is_backlight_combination_mode(dev)) { |
u8 lbpc; |
|
pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc); |
val *= lbpc; |
} |
|
return val; |
} |
|
static u32 _vlv_get_backlight(struct drm_device *dev, enum pipe pipe) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
val = intel_panel_compute_brightness(dev, val); |
|
return I915_READ(VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK; |
} |
spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); |
|
static u32 vlv_get_backlight(struct intel_connector *connector) |
{ |
struct drm_device *dev = connector->base.dev; |
enum pipe pipe = intel_get_pipe_from_connector(connector); |
|
return _vlv_get_backlight(dev, pipe); |
} |
|
static u32 intel_panel_get_backlight(struct intel_connector *connector) |
{ |
struct drm_device *dev = connector->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
u32 val; |
unsigned long flags; |
|
spin_lock_irqsave(&dev_priv->backlight_lock, flags); |
|
val = dev_priv->display.get_backlight(connector); |
val = intel_panel_compute_brightness(connector, val); |
|
spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); |
|
DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val); |
return val; |
} |
|
static void bdw_set_backlight(struct intel_connector *connector, u32 level) |
static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level) |
{ |
struct drm_device *dev = connector->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
u32 val = I915_READ(BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK; |
I915_WRITE(BLC_PWM_PCH_CTL2, val | level); |
u32 val = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; |
I915_WRITE(BLC_PWM_CPU_CTL, val | level); |
} |
|
static void pch_set_backlight(struct intel_connector *connector, u32 level) |
static void intel_panel_actually_set_backlight(struct drm_device *dev, u32 level) |
{ |
struct drm_device *dev = connector->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
u32 tmp; |
|
tmp = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; |
I915_WRITE(BLC_PWM_CPU_CTL, tmp | level); |
} |
DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); |
level = intel_panel_compute_brightness(dev, level); |
|
static void i9xx_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; |
u32 tmp, mask; |
if (HAS_PCH_SPLIT(dev)) |
return intel_pch_panel_set_backlight(dev, level); |
|
WARN_ON(panel->backlight.max == 0); |
|
if (panel->backlight.combination_mode) { |
if (is_backlight_combination_mode(dev)) { |
u32 max = intel_panel_get_max_backlight(dev); |
u8 lbpc; |
|
lbpc = level * 0xfe / panel->backlight.max + 1; |
/* we're screwed, but keep behaviour backwards compatible */ |
if (!max) |
max = 1; |
|
lbpc = level * 0xfe / max + 1; |
level /= lbpc; |
pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc); |
} |
|
if (IS_GEN4(dev)) { |
mask = BACKLIGHT_DUTY_CYCLE_MASK; |
} else { |
tmp = I915_READ(BLC_PWM_CTL); |
if (INTEL_INFO(dev)->gen < 4) |
level <<= 1; |
mask = BACKLIGHT_DUTY_CYCLE_MASK_PNV; |
} |
|
tmp = I915_READ(BLC_PWM_CTL) & ~mask; |
tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK; |
I915_WRITE(BLC_PWM_CTL, tmp | level); |
} |
|
static void vlv_set_backlight(struct intel_connector *connector, u32 level) |
{ |
struct drm_device *dev = connector->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
enum pipe pipe = intel_get_pipe_from_connector(connector); |
u32 tmp; |
|
tmp = I915_READ(VLV_BLC_PWM_CTL(pipe)) & ~BACKLIGHT_DUTY_CYCLE_MASK; |
I915_WRITE(VLV_BLC_PWM_CTL(pipe), tmp | level); |
} |
|
static void |
intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level) |
{ |
struct drm_device *dev = connector->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
|
DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); |
|
level = intel_panel_compute_brightness(connector, level); |
dev_priv->display.set_backlight(connector, level); |
} |
|
/* set backlight brightness to level in range [0..max] */ |
void intel_panel_set_backlight(struct intel_connector *connector, u32 level, |
u32 max) |
void intel_panel_set_backlight(struct drm_device *dev, u32 level, u32 max) |
{ |
struct drm_device *dev = connector->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_panel *panel = &connector->panel; |
enum pipe pipe = intel_get_pipe_from_connector(connector); |
u32 freq; |
unsigned long flags; |
|
if (!panel->backlight.present || pipe == INVALID_PIPE) |
return; |
dev_priv->backlight.level = level; |
// if (dev_priv->backlight.device) |
// dev_priv->backlight.device->props.brightness = level; |
|
spin_lock_irqsave(&dev_priv->backlight_lock, flags); |
|
WARN_ON(panel->backlight.max == 0); |
|
/* scale to hardware max, but be careful to not overflow */ |
freq = panel->backlight.max; |
if (freq < max) |
level = level * freq / max; |
else |
level = freq / max * level; |
|
panel->backlight.level = level; |
// if (panel->backlight.device) |
// panel->backlight.device->props.brightness = level; |
|
if (panel->backlight.enabled) |
intel_panel_actually_set_backlight(connector, level); |
|
spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); |
// if (dev_priv->backlight.enabled) |
// intel_panel_actually_set_backlight(dev, level); |
} |
|
static void pch_disable_backlight(struct intel_connector *connector) |
void intel_panel_disable_backlight(struct drm_device *dev) |
{ |
struct drm_device *dev = connector->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
u32 tmp; |
|
intel_panel_actually_set_backlight(connector, 0); |
|
tmp = I915_READ(BLC_PWM_CPU_CTL2); |
I915_WRITE(BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE); |
|
tmp = I915_READ(BLC_PWM_PCH_CTL1); |
I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE); |
} |
|
static void i9xx_disable_backlight(struct intel_connector *connector) |
{ |
intel_panel_actually_set_backlight(connector, 0); |
} |
|
static void i965_disable_backlight(struct intel_connector *connector) |
{ |
struct drm_device *dev = connector->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
u32 tmp; |
|
intel_panel_actually_set_backlight(connector, 0); |
|
tmp = I915_READ(BLC_PWM_CTL2); |
I915_WRITE(BLC_PWM_CTL2, tmp & ~BLM_PWM_ENABLE); |
} |
|
static void vlv_disable_backlight(struct intel_connector *connector) |
{ |
struct drm_device *dev = connector->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
enum pipe pipe = intel_get_pipe_from_connector(connector); |
u32 tmp; |
|
intel_panel_actually_set_backlight(connector, 0); |
|
tmp = I915_READ(VLV_BLC_PWM_CTL2(pipe)); |
I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp & ~BLM_PWM_ENABLE); |
} |
|
void intel_panel_disable_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; |
enum pipe pipe = intel_get_pipe_from_connector(connector); |
unsigned long flags; |
|
if (!panel->backlight.present || pipe == INVALID_PIPE) |
return; |
|
/* |
* Do not disable backlight on the vgaswitcheroo path. When switching |
* away from i915, the other client may depend on i915 to handle the |
593,217 → 501,102 |
return; |
} |
|
spin_lock_irqsave(&dev_priv->backlight_lock, flags); |
spin_lock_irqsave(&dev_priv->backlight.lock, flags); |
|
panel->backlight.enabled = false; |
dev_priv->display.disable_backlight(connector); |
dev_priv->backlight.enabled = false; |
intel_panel_actually_set_backlight(dev, 0); |
|
spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); |
} |
if (INTEL_INFO(dev)->gen >= 4) { |
uint32_t reg, tmp; |
|
static void bdw_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 pch_ctl1, pch_ctl2; |
reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2; |
|
pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); |
if (pch_ctl1 & BLM_PCH_PWM_ENABLE) { |
DRM_DEBUG_KMS("pch backlight already enabled\n"); |
pch_ctl1 &= ~BLM_PCH_PWM_ENABLE; |
I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); |
I915_WRITE(reg, I915_READ(reg) & ~BLM_PWM_ENABLE); |
|
if (HAS_PCH_SPLIT(dev)) { |
tmp = I915_READ(BLC_PWM_PCH_CTL1); |
tmp &= ~BLM_PCH_PWM_ENABLE; |
I915_WRITE(BLC_PWM_PCH_CTL1, tmp); |
} |
} |
|
pch_ctl2 = panel->backlight.max << 16; |
I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2); |
|
pch_ctl1 = 0; |
if (panel->backlight.active_low_pwm) |
pch_ctl1 |= BLM_PCH_POLARITY; |
|
/* BDW always uses the pch pwm controls. */ |
pch_ctl1 |= BLM_PCH_OVERRIDE_ENABLE; |
|
I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); |
POSTING_READ(BLC_PWM_PCH_CTL1); |
I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE); |
|
/* This won't stick until the above enable. */ |
intel_panel_actually_set_backlight(connector, panel->backlight.level); |
spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); |
} |
|
static void pch_enable_backlight(struct intel_connector *connector) |
void intel_panel_enable_backlight(struct drm_device *dev, |
enum pipe pipe) |
{ |
struct drm_device *dev = connector->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_panel *panel = &connector->panel; |
enum pipe pipe = intel_get_pipe_from_connector(connector); |
enum transcoder cpu_transcoder = |
intel_pipe_to_cpu_transcoder(dev_priv, pipe); |
u32 cpu_ctl2, pch_ctl1, pch_ctl2; |
unsigned long flags; |
|
cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2); |
if (cpu_ctl2 & BLM_PWM_ENABLE) { |
WARN(1, "cpu backlight already enabled\n"); |
cpu_ctl2 &= ~BLM_PWM_ENABLE; |
I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2); |
} |
spin_lock_irqsave(&dev_priv->backlight.lock, flags); |
|
pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); |
if (pch_ctl1 & BLM_PCH_PWM_ENABLE) { |
DRM_DEBUG_KMS("pch backlight already enabled\n"); |
pch_ctl1 &= ~BLM_PCH_PWM_ENABLE; |
I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); |
if (dev_priv->backlight.level == 0) { |
dev_priv->backlight.level = intel_panel_get_max_backlight(dev); |
// if (dev_priv->backlight.device) |
// dev_priv->backlight.device->props.brightness = |
// dev_priv->backlight.level; |
} |
|
if (cpu_transcoder == TRANSCODER_EDP) |
cpu_ctl2 = BLM_TRANSCODER_EDP; |
else |
cpu_ctl2 = BLM_PIPE(cpu_transcoder); |
I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2); |
POSTING_READ(BLC_PWM_CPU_CTL2); |
I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2 | BLM_PWM_ENABLE); |
if (INTEL_INFO(dev)->gen >= 4) { |
uint32_t reg, tmp; |
|
/* This won't stick until the above enable. */ |
intel_panel_actually_set_backlight(connector, panel->backlight.level); |
reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2; |
|
pch_ctl2 = panel->backlight.max << 16; |
I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2); |
|
pch_ctl1 = 0; |
if (panel->backlight.active_low_pwm) |
pch_ctl1 |= BLM_PCH_POLARITY; |
tmp = I915_READ(reg); |
|
I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); |
POSTING_READ(BLC_PWM_PCH_CTL1); |
I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE); |
} |
/* Note that this can also get called through dpms changes. And |
* we don't track the backlight dpms state, hence check whether |
* we have to do anything first. */ |
if (tmp & BLM_PWM_ENABLE) |
goto set_level; |
|
static void i9xx_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 ctl, freq; |
if (INTEL_INFO(dev)->num_pipes == 3) |
tmp &= ~BLM_PIPE_SELECT_IVB; |
else |
tmp &= ~BLM_PIPE_SELECT; |
|
ctl = I915_READ(BLC_PWM_CTL); |
if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) { |
WARN(1, "backlight already enabled\n"); |
I915_WRITE(BLC_PWM_CTL, 0); |
} |
if (cpu_transcoder == TRANSCODER_EDP) |
tmp |= BLM_TRANSCODER_EDP; |
else |
tmp |= BLM_PIPE(cpu_transcoder); |
tmp &= ~BLM_PWM_ENABLE; |
|
freq = panel->backlight.max; |
if (panel->backlight.combination_mode) |
freq /= 0xff; |
I915_WRITE(reg, tmp); |
POSTING_READ(reg); |
I915_WRITE(reg, tmp | BLM_PWM_ENABLE); |
|
ctl = freq << 17; |
if (IS_GEN2(dev) && panel->backlight.combination_mode) |
ctl |= BLM_LEGACY_MODE; |
if (IS_PINEVIEW(dev) && panel->backlight.active_low_pwm) |
ctl |= BLM_POLARITY_PNV; |
|
I915_WRITE(BLC_PWM_CTL, ctl); |
POSTING_READ(BLC_PWM_CTL); |
|
/* XXX: combine this into above write? */ |
intel_panel_actually_set_backlight(connector, panel->backlight.level); |
if (HAS_PCH_SPLIT(dev) && |
!(dev_priv->quirks & QUIRK_NO_PCH_PWM_ENABLE)) { |
tmp = I915_READ(BLC_PWM_PCH_CTL1); |
tmp |= BLM_PCH_PWM_ENABLE; |
tmp &= ~BLM_PCH_OVERRIDE_ENABLE; |
I915_WRITE(BLC_PWM_PCH_CTL1, tmp); |
} |
|
static void i965_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; |
enum pipe pipe = intel_get_pipe_from_connector(connector); |
u32 ctl, ctl2, freq; |
|
ctl2 = I915_READ(BLC_PWM_CTL2); |
if (ctl2 & BLM_PWM_ENABLE) { |
WARN(1, "backlight already enabled\n"); |
ctl2 &= ~BLM_PWM_ENABLE; |
I915_WRITE(BLC_PWM_CTL2, ctl2); |
} |
|
freq = panel->backlight.max; |
if (panel->backlight.combination_mode) |
freq /= 0xff; |
set_level: |
/* Call below after setting BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1. |
* BLC_PWM_CPU_CTL may be cleared to zero automatically when these |
* registers are set. |
*/ |
dev_priv->backlight.enabled = true; |
intel_panel_actually_set_backlight(dev, dev_priv->backlight.level); |
|
ctl = freq << 16; |
I915_WRITE(BLC_PWM_CTL, ctl); |
|
/* XXX: combine this into above write? */ |
intel_panel_actually_set_backlight(connector, panel->backlight.level); |
|
ctl2 = BLM_PIPE(pipe); |
if (panel->backlight.combination_mode) |
ctl2 |= BLM_COMBINATION_MODE; |
if (panel->backlight.active_low_pwm) |
ctl2 |= BLM_POLARITY_I965; |
I915_WRITE(BLC_PWM_CTL2, ctl2); |
POSTING_READ(BLC_PWM_CTL2); |
I915_WRITE(BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE); |
spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); |
} |
|
static void vlv_enable_backlight(struct intel_connector *connector) |
static void intel_panel_init_backlight(struct drm_device *dev) |
{ |
struct drm_device *dev = connector->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_panel *panel = &connector->panel; |
enum pipe pipe = intel_get_pipe_from_connector(connector); |
u32 ctl, ctl2; |
|
ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe)); |
if (ctl2 & BLM_PWM_ENABLE) { |
WARN(1, "backlight already enabled\n"); |
ctl2 &= ~BLM_PWM_ENABLE; |
I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2); |
dev_priv->backlight.level = intel_panel_get_backlight(dev); |
dev_priv->backlight.enabled = dev_priv->backlight.level != 0; |
} |
|
ctl = panel->backlight.max << 16; |
I915_WRITE(VLV_BLC_PWM_CTL(pipe), ctl); |
|
/* XXX: combine this into above write? */ |
intel_panel_actually_set_backlight(connector, panel->backlight.level); |
|
ctl2 = 0; |
if (panel->backlight.active_low_pwm) |
ctl2 |= BLM_POLARITY_I965; |
I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2); |
POSTING_READ(VLV_BLC_PWM_CTL2(pipe)); |
I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2 | BLM_PWM_ENABLE); |
} |
|
void intel_panel_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; |
enum pipe pipe = intel_get_pipe_from_connector(connector); |
unsigned long flags; |
|
if (!panel->backlight.present || pipe == INVALID_PIPE) |
return; |
|
DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe)); |
|
spin_lock_irqsave(&dev_priv->backlight_lock, flags); |
|
WARN_ON(panel->backlight.max == 0); |
|
if (panel->backlight.level == 0) { |
panel->backlight.level = panel->backlight.max; |
// if (panel->backlight.device) |
// panel->backlight.device->props.brightness = |
// panel->backlight.level; |
} |
|
dev_priv->display.enable_backlight(connector); |
panel->backlight.enabled = true; |
|
spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); |
} |
|
enum drm_connector_status |
intel_panel_detect(struct drm_device *dev) |
{ |
826,378 → 619,85 |
} |
} |
|
#if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) |
static int intel_backlight_device_update_status(struct backlight_device *bd) |
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE |
static int intel_panel_update_status(struct backlight_device *bd) |
{ |
struct intel_connector *connector = bl_get_data(bd); |
struct drm_device *dev = connector->base.dev; |
|
mutex_lock(&dev->mode_config.mutex); |
DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n", |
bd->props.brightness, bd->props.max_brightness); |
intel_panel_set_backlight(connector, bd->props.brightness, |
struct drm_device *dev = bl_get_data(bd); |
intel_panel_set_backlight(dev, bd->props.brightness, |
bd->props.max_brightness); |
mutex_unlock(&dev->mode_config.mutex); |
return 0; |
} |
|
static int intel_backlight_device_get_brightness(struct backlight_device *bd) |
static int intel_panel_get_brightness(struct backlight_device *bd) |
{ |
struct intel_connector *connector = bl_get_data(bd); |
struct drm_device *dev = connector->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
int ret; |
|
intel_runtime_pm_get(dev_priv); |
mutex_lock(&dev->mode_config.mutex); |
ret = intel_panel_get_backlight(connector); |
mutex_unlock(&dev->mode_config.mutex); |
intel_runtime_pm_put(dev_priv); |
|
return ret; |
struct drm_device *dev = bl_get_data(bd); |
return intel_panel_get_backlight(dev); |
} |
|
static const struct backlight_ops intel_backlight_device_ops = { |
.update_status = intel_backlight_device_update_status, |
.get_brightness = intel_backlight_device_get_brightness, |
static const struct backlight_ops intel_panel_bl_ops = { |
.update_status = intel_panel_update_status, |
.get_brightness = intel_panel_get_brightness, |
}; |
|
static int intel_backlight_device_register(struct intel_connector *connector) |
int intel_panel_setup_backlight(struct drm_connector *connector) |
{ |
struct intel_panel *panel = &connector->panel; |
struct drm_device *dev = connector->dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct backlight_properties props; |
unsigned long flags; |
|
if (WARN_ON(panel->backlight.device)) |
intel_panel_init_backlight(dev); |
|
if (WARN_ON(dev_priv->backlight.device)) |
return -ENODEV; |
|
BUG_ON(panel->backlight.max == 0); |
|
memset(&props, 0, sizeof(props)); |
props.type = BACKLIGHT_RAW; |
props.brightness = panel->backlight.level; |
props.max_brightness = panel->backlight.max; |
props.brightness = dev_priv->backlight.level; |
|
/* |
* Note: using the same name independent of the connector prevents |
* registration of multiple backlight devices in the driver. |
*/ |
panel->backlight.device = |
backlight_device_register("intel_backlight", |
connector->base.kdev, |
connector, |
&intel_backlight_device_ops, &props); |
spin_lock_irqsave(&dev_priv->backlight.lock, flags); |
props.max_brightness = intel_panel_get_max_backlight(dev); |
spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); |
|
if (IS_ERR(panel->backlight.device)) { |
DRM_ERROR("Failed to register backlight: %ld\n", |
PTR_ERR(panel->backlight.device)); |
panel->backlight.device = NULL; |
if (props.max_brightness == 0) { |
DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n"); |
return -ENODEV; |
} |
return 0; |
} |
dev_priv->backlight.device = |
backlight_device_register("intel_backlight", |
&connector->kdev, dev, |
&intel_panel_bl_ops, &props); |
|
static void intel_backlight_device_unregister(struct intel_connector *connector) |
{ |
struct intel_panel *panel = &connector->panel; |
|
if (panel->backlight.device) { |
backlight_device_unregister(panel->backlight.device); |
panel->backlight.device = NULL; |
} |
} |
#else /* CONFIG_BACKLIGHT_CLASS_DEVICE */ |
static int intel_backlight_device_register(struct intel_connector *connector) |
{ |
return 0; |
} |
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! |
* |
* XXX: Query mode clock or hardware clock and program PWM modulation frequency |
* appropriately when it's 0. Use VBT and/or sane defaults. |
*/ |
static int bdw_setup_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 pch_ctl1, pch_ctl2, val; |
|
pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); |
panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY; |
|
pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2); |
panel->backlight.max = pch_ctl2 >> 16; |
if (!panel->backlight.max) |
if (IS_ERR(dev_priv->backlight.device)) { |
DRM_ERROR("Failed to register backlight: %ld\n", |
PTR_ERR(dev_priv->backlight.device)); |
dev_priv->backlight.device = NULL; |
return -ENODEV; |
|
val = bdw_get_backlight(connector); |
panel->backlight.level = intel_panel_compute_brightness(connector, val); |
|
panel->backlight.enabled = (pch_ctl1 & BLM_PCH_PWM_ENABLE) && |
panel->backlight.level != 0; |
|
return 0; |
} |
|
static int pch_setup_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 cpu_ctl2, pch_ctl1, pch_ctl2, val; |
|
pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); |
panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY; |
|
pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2); |
panel->backlight.max = pch_ctl2 >> 16; |
if (!panel->backlight.max) |
return -ENODEV; |
|
val = pch_get_backlight(connector); |
panel->backlight.level = intel_panel_compute_brightness(connector, val); |
|
cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2); |
panel->backlight.enabled = (cpu_ctl2 & BLM_PWM_ENABLE) && |
(pch_ctl1 & BLM_PCH_PWM_ENABLE) && panel->backlight.level != 0; |
|
return 0; |
} |
|
static int i9xx_setup_backlight(struct intel_connector *connector) |
void intel_panel_destroy_backlight(struct drm_device *dev) |
{ |
struct drm_device *dev = connector->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_panel *panel = &connector->panel; |
u32 ctl, val; |
|
ctl = I915_READ(BLC_PWM_CTL); |
|
if (IS_GEN2(dev)) |
panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE; |
|
if (IS_PINEVIEW(dev)) |
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) |
return -ENODEV; |
|
val = i9xx_get_backlight(connector); |
panel->backlight.level = intel_panel_compute_brightness(connector, val); |
|
panel->backlight.enabled = panel->backlight.level != 0; |
|
return 0; |
if (dev_priv->backlight.device) { |
backlight_device_unregister(dev_priv->backlight.device); |
dev_priv->backlight.device = NULL; |
} |
|
static int i965_setup_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 ctl, ctl2, val; |
|
ctl2 = I915_READ(BLC_PWM_CTL2); |
panel->backlight.combination_mode = ctl2 & BLM_COMBINATION_MODE; |
panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965; |
|
ctl = I915_READ(BLC_PWM_CTL); |
panel->backlight.max = ctl >> 16; |
if (panel->backlight.combination_mode) |
panel->backlight.max *= 0xff; |
|
if (!panel->backlight.max) |
return -ENODEV; |
|
val = i9xx_get_backlight(connector); |
panel->backlight.level = intel_panel_compute_brightness(connector, val); |
|
panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) && |
panel->backlight.level != 0; |
|
return 0; |
} |
|
static int vlv_setup_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; |
enum pipe pipe; |
u32 ctl, ctl2, val; |
|
for_each_pipe(pipe) { |
u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe)); |
|
/* Skip if the modulation freq is already set */ |
if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK) |
continue; |
|
cur_val &= BACKLIGHT_DUTY_CYCLE_MASK; |
I915_WRITE(VLV_BLC_PWM_CTL(pipe), (0xf42 << 16) | |
cur_val); |
} |
|
ctl2 = I915_READ(VLV_BLC_PWM_CTL2(PIPE_A)); |
panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965; |
|
ctl = I915_READ(VLV_BLC_PWM_CTL(PIPE_A)); |
panel->backlight.max = ctl >> 16; |
if (!panel->backlight.max) |
return -ENODEV; |
|
val = _vlv_get_backlight(dev, PIPE_A); |
panel->backlight.level = intel_panel_compute_brightness(connector, val); |
|
panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) && |
panel->backlight.level != 0; |
|
return 0; |
} |
|
#else |
int intel_panel_setup_backlight(struct drm_connector *connector) |
{ |
struct drm_device *dev = connector->dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_connector *intel_connector = to_intel_connector(connector); |
struct intel_panel *panel = &intel_connector->panel; |
unsigned long flags; |
int ret; |
|
/* set level and max in panel struct */ |
spin_lock_irqsave(&dev_priv->backlight_lock, flags); |
ret = dev_priv->display.setup_backlight(intel_connector); |
spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); |
|
if (ret) { |
DRM_DEBUG_KMS("failed to setup backlight for connector %s\n", |
drm_get_connector_name(connector)); |
return ret; |
} |
|
intel_backlight_device_register(intel_connector); |
|
panel->backlight.present = true; |
|
DRM_DEBUG_KMS("backlight initialized, %s, brightness %u/%u, " |
"sysfs interface %sregistered\n", |
panel->backlight.enabled ? "enabled" : "disabled", |
panel->backlight.level, panel->backlight.max, |
panel->backlight.device ? "" : "not "); |
|
intel_panel_init_backlight(connector->dev); |
return 0; |
} |
|
void intel_panel_destroy_backlight(struct drm_connector *connector) |
void intel_panel_destroy_backlight(struct drm_device *dev) |
{ |
struct intel_connector *intel_connector = to_intel_connector(connector); |
struct intel_panel *panel = &intel_connector->panel; |
|
panel->backlight.present = false; |
intel_backlight_device_unregister(intel_connector); |
return; |
} |
#endif |
|
/** |
* intel_find_panel_downclock - find the reduced downclock for LVDS in EDID |
* @dev: drm device |
* @fixed_mode : panel native mode |
* @connector: LVDS/eDP connector |
* |
* Return downclock_avail |
* Find the reduced downclock for LVDS/eDP in EDID. |
*/ |
struct drm_display_mode * |
intel_find_panel_downclock(struct drm_device *dev, |
struct drm_display_mode *fixed_mode, |
struct drm_connector *connector) |
{ |
struct drm_display_mode *scan, *tmp_mode; |
int temp_downclock; |
|
temp_downclock = fixed_mode->clock; |
tmp_mode = NULL; |
|
list_for_each_entry(scan, &connector->probed_modes, head) { |
/* |
* If one mode has the same resolution with the fixed_panel |
* mode while they have the different refresh rate, it means |
* that the reduced downclock is found. In such |
* case we can set the different FPx0/1 to dynamically select |
* between low and high frequency. |
*/ |
if (scan->hdisplay == fixed_mode->hdisplay && |
scan->hsync_start == fixed_mode->hsync_start && |
scan->hsync_end == fixed_mode->hsync_end && |
scan->htotal == fixed_mode->htotal && |
scan->vdisplay == fixed_mode->vdisplay && |
scan->vsync_start == fixed_mode->vsync_start && |
scan->vsync_end == fixed_mode->vsync_end && |
scan->vtotal == fixed_mode->vtotal) { |
if (scan->clock < temp_downclock) { |
/* |
* The downclock is already found. But we |
* expect to find the lower downclock. |
*/ |
temp_downclock = scan->clock; |
tmp_mode = scan; |
} |
} |
} |
|
if (temp_downclock < fixed_mode->clock) |
return drm_mode_duplicate(dev, tmp_mode); |
else |
return NULL; |
} |
|
/* Set up chip specific backlight functions */ |
void intel_panel_init_backlight_funcs(struct drm_device *dev) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
|
if (IS_BROADWELL(dev)) { |
dev_priv->display.setup_backlight = bdw_setup_backlight; |
dev_priv->display.enable_backlight = bdw_enable_backlight; |
dev_priv->display.disable_backlight = pch_disable_backlight; |
dev_priv->display.set_backlight = bdw_set_backlight; |
dev_priv->display.get_backlight = bdw_get_backlight; |
} 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; |
} else if (IS_VALLEYVIEW(dev)) { |
dev_priv->display.setup_backlight = vlv_setup_backlight; |
dev_priv->display.enable_backlight = vlv_enable_backlight; |
dev_priv->display.disable_backlight = vlv_disable_backlight; |
dev_priv->display.set_backlight = vlv_set_backlight; |
dev_priv->display.get_backlight = vlv_get_backlight; |
} else if (IS_GEN4(dev)) { |
dev_priv->display.setup_backlight = i965_setup_backlight; |
dev_priv->display.enable_backlight = i965_enable_backlight; |
dev_priv->display.disable_backlight = i965_disable_backlight; |
dev_priv->display.set_backlight = i9xx_set_backlight; |
dev_priv->display.get_backlight = i9xx_get_backlight; |
} 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; |
} |
} |
|
int intel_panel_init(struct intel_panel *panel, |
struct drm_display_mode *fixed_mode) |
{ |
1213,8 → 713,4 |
|
if (panel->fixed_mode) |
drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode); |
|
if (panel->downclock_mode) |
drm_mode_destroy(intel_connector->base.dev, |
panel->downclock_mode); |
} |