Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 218009
b: refs/heads/master
c: e9e331a
h: refs/heads/master
i:
  218007: 27509dc
v: v3
  • Loading branch information
Chris Wilson committed Sep 13, 2010
1 parent 2ba0ab4 commit bf77aa5
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 64 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 6edc3242e35f03990e362e7c115e722717f0f7a7
refs/heads/master: e9e331a8abeece1565d383510ed985945132ffe3
31 changes: 0 additions & 31 deletions trunk/drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -2636,33 +2636,6 @@ static int i830_get_display_clock_speed(struct drm_device *dev)
return 133000;
}

/**
* Return the pipe currently connected to the panel fitter,
* or -1 if the panel fitter is not present or not in use
*/
int intel_panel_fitter_pipe (struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u32 pfit_control;

/* i830 doesn't have a panel fitter */
if (IS_I830(dev))
return -1;

pfit_control = I915_READ(PFIT_CONTROL);

/* See if the panel fitter is in use */
if ((pfit_control & PFIT_ENABLE) == 0)
return -1;

/* 965 can place panel fitter on either pipe */
if (IS_I965G(dev))
return (pfit_control >> 29) & 0x3;

/* older chips can only use pipe 1 */
return 1;
}

struct fdi_m_n {
u32 tu;
u32 gmch_m;
Expand Down Expand Up @@ -3921,10 +3894,6 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
pipeconf |= PIPECONF_ENABLE;
dpll |= DPLL_VCO_ENABLE;

/* Disable the panel fitter if it was on our pipe */
if (!HAS_PCH_SPLIT(dev) && intel_panel_fitter_pipe(dev) == pipe)
I915_WRITE(PFIT_CONTROL, 0);

DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
drm_mode_debug_printmodeline(mode);

Expand Down
1 change: 0 additions & 1 deletion trunk/drivers/gpu/drm/i915/intel_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,6 @@ extern u32 intel_panel_get_max_backlight(struct drm_device *dev);
extern u32 intel_panel_get_backlight(struct drm_device *dev);
extern void intel_panel_set_backlight(struct drm_device *dev, u32 level);

extern int intel_panel_fitter_pipe (struct drm_device *dev);
extern void intel_crtc_load_lut(struct drm_crtc *crtc);
extern void intel_encoder_prepare (struct drm_encoder *encoder);
extern void intel_encoder_commit (struct drm_encoder *encoder);
Expand Down
103 changes: 75 additions & 28 deletions trunk/drivers/gpu/drm/i915/intel_lvds.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,38 +46,28 @@ struct intel_lvds {
int fitting_mode;
u32 pfit_control;
u32 pfit_pgm_ratios;
bool pfit_dirty;
};

static struct intel_lvds *enc_to_intel_lvds(struct drm_encoder *encoder)
{
return container_of(encoder, struct intel_lvds, base.base);
}

static void intel_lvds_lock_panel(struct drm_device *dev, bool lock)
{
struct drm_i915_private *dev_priv = dev->dev_private;

if (lock)
I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & 0x3);
else
I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
}

/**
* Sets the power state for the panel.
*/
static void intel_lvds_set_power(struct drm_device *dev, bool on)
static void intel_lvds_set_power(struct intel_lvds *intel_lvds, bool on)
{
struct drm_device *dev = intel_lvds->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
u32 ctl_reg, status_reg, lvds_reg;
u32 ctl_reg, lvds_reg;

if (HAS_PCH_SPLIT(dev)) {
ctl_reg = PCH_PP_CONTROL;
status_reg = PCH_PP_STATUS;
lvds_reg = PCH_LVDS;
} else {
ctl_reg = PP_CONTROL;
status_reg = PP_STATUS;
lvds_reg = LVDS;
}

Expand All @@ -86,21 +76,31 @@ static void intel_lvds_set_power(struct drm_device *dev, bool on)
I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON);
intel_panel_set_backlight(dev, dev_priv->backlight_level);
} else {
dev_priv->backlight_level = intel_panel_get_backlight(dev);

intel_panel_set_backlight(dev, 0);
I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON);

if (intel_lvds->pfit_control) {
if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000))
DRM_ERROR("timed out waiting for panel to power off\n");
I915_WRITE(PFIT_CONTROL, 0);
intel_lvds->pfit_control = 0;
}

I915_WRITE(lvds_reg, I915_READ(lvds_reg) & ~LVDS_PORT_EN);
}
POSTING_READ(lvds_reg);
}

static void intel_lvds_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_device *dev = encoder->dev;
struct intel_lvds *intel_lvds = enc_to_intel_lvds(encoder);

if (mode == DRM_MODE_DPMS_ON)
intel_lvds_set_power(dev, true);
intel_lvds_set_power(intel_lvds, true);
else
intel_lvds_set_power(dev, false);
intel_lvds_set_power(intel_lvds, false);

/* XXX: We never power down the LVDS pairs. */
}
Expand Down Expand Up @@ -331,8 +331,12 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
}

out:
intel_lvds->pfit_control = pfit_control;
intel_lvds->pfit_pgm_ratios = pfit_pgm_ratios;
if (pfit_control != intel_lvds->pfit_control ||
pfit_pgm_ratios != intel_lvds->pfit_pgm_ratios) {
intel_lvds->pfit_control = pfit_control;
intel_lvds->pfit_pgm_ratios = pfit_pgm_ratios;
intel_lvds->pfit_dirty = true;
}
dev_priv->lvds_border_bits = border;

/*
Expand All @@ -352,24 +356,56 @@ static void intel_lvds_prepare(struct drm_encoder *encoder)

dev_priv->backlight_level = intel_panel_get_backlight(dev);

if (intel_lvds->pfit_control == I915_READ(PFIT_CONTROL))
intel_lvds_lock_panel(dev, false);
else
intel_lvds_set_power(dev, false);
/* We try to do the minimum that is necessary in order to unlock
* the registers for mode setting.
*
* On Ironlake, this is quite simple as we just set the unlock key
* and ignore all subtleties. (This may cause some issues...)
*
* Prior to Ironlake, we must disable the pipe if we want to adjust
* the panel fitter. However at all other times we can just reset
* the registers regardless.
*/

if (HAS_PCH_SPLIT(dev)) {
I915_WRITE(PCH_PP_CONTROL,
I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS);
} else if (intel_lvds->pfit_dirty) {
I915_WRITE(PP_CONTROL,
I915_READ(PP_CONTROL) & ~POWER_TARGET_ON);
I915_WRITE(LVDS, I915_READ(LVDS) & ~LVDS_PORT_EN);
} else {
I915_WRITE(PP_CONTROL,
I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
}
}

static void intel_lvds_commit( struct drm_encoder *encoder)
static void intel_lvds_commit(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_lvds *intel_lvds = enc_to_intel_lvds(encoder);

if (dev_priv->backlight_level == 0)
dev_priv->backlight_level = intel_panel_get_max_backlight(dev);

if ((I915_READ(PP_CONTROL) & PANEL_UNLOCK_REGS) == PANEL_UNLOCK_REGS)
intel_lvds_lock_panel(dev, true);
else
intel_lvds_set_power(dev, true);
/* Undo any unlocking done in prepare to prevent accidental
* adjustment of the registers.
*/
if (HAS_PCH_SPLIT(dev)) {
u32 val = I915_READ(PCH_PP_CONTROL);
if ((val & PANEL_UNLOCK_REGS) == PANEL_UNLOCK_REGS)
I915_WRITE(PCH_PP_CONTROL, val & 0x3);
} else {
u32 val = I915_READ(PP_CONTROL);
if ((val & PANEL_UNLOCK_REGS) == PANEL_UNLOCK_REGS)
I915_WRITE(PP_CONTROL, val & 0x3);
}

/* Always do a full power on as we do not know what state
* we were left in.
*/
intel_lvds_set_power(intel_lvds, true);
}

static void intel_lvds_mode_set(struct drm_encoder *encoder,
Expand All @@ -389,13 +425,20 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
if (HAS_PCH_SPLIT(dev))
return;

if (!intel_lvds->pfit_dirty)
return;

/*
* Enable automatic panel scaling so that non-native modes fill the
* screen. Should be enabled before the pipe is enabled, according to
* register description and PRM.
*/
if (wait_for((I915_READ(PP_STATUS) & PP_ON) == 0, 1000))
DRM_ERROR("timed out waiting for panel to power off\n");

I915_WRITE(PFIT_PGM_RATIOS, intel_lvds->pfit_pgm_ratios);
I915_WRITE(PFIT_CONTROL, intel_lvds->pfit_control);
intel_lvds->pfit_dirty = false;
}

/**
Expand Down Expand Up @@ -824,6 +867,10 @@ void intel_lvds_init(struct drm_device *dev)
return;
}

if (!HAS_PCH_SPLIT(dev)) {
intel_lvds->pfit_control = I915_READ(PFIT_CONTROL);
}

intel_encoder = &intel_lvds->base;
encoder = &intel_encoder->base;
connector = &intel_connector->base;
Expand Down
33 changes: 30 additions & 3 deletions trunk/drivers/gpu/drm/i915/intel_overlay.c
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,33 @@ static int check_overlay_src(struct drm_device *dev,
return 0;
}

/**
* Return the pipe currently connected to the panel fitter,
* or -1 if the panel fitter is not present or not in use
*/
static int intel_panel_fitter_pipe(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u32 pfit_control;

/* i830 doesn't have a panel fitter */
if (IS_I830(dev))
return -1;

pfit_control = I915_READ(PFIT_CONTROL);

/* See if the panel fitter is in use */
if ((pfit_control & PFIT_ENABLE) == 0)
return -1;

/* 965 can place panel fitter on either pipe */
if (IS_I965G(dev))
return (pfit_control >> 29) & 0x3;

/* older chips can only use pipe 1 */
return 1;
}

int intel_overlay_put_image(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
Expand Down Expand Up @@ -1124,9 +1151,9 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
overlay->crtc = crtc;
crtc->overlay = overlay;

if (intel_panel_fitter_pipe(dev) == crtc->pipe
/* and line to wide, i.e. one-line-mode */
&& mode->hdisplay > 1024) {
/* line too wide, i.e. one-line-mode */
if (mode->hdisplay > 1024 &&
intel_panel_fitter_pipe(dev) == crtc->pipe) {
overlay->pfit_active = 1;
update_pfit_vscale_ratio(overlay);
} else
Expand Down

0 comments on commit bf77aa5

Please sign in to comment.