Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 260183
b: refs/heads/master
c: 5a35420
h: refs/heads/master
i:
  260181: df6c535
  260179: 9167310
  260175: dae7fa9
v: v3
  • Loading branch information
Jesse Barnes authored and Keith Packard committed Jul 7, 2011
1 parent 56ca28c commit 1bde7cf
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 43 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: 9325c9f088c42e3e07475d4f733ee6539ebf9c0b
refs/heads/master: 5a3542041bf85a65633ed203c3782492116ebb94
194 changes: 152 additions & 42 deletions trunk/drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -4309,6 +4309,133 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
return dev_priv->lvds_use_ssc && i915_panel_use_ssc;
}

/**
* intel_choose_pipe_bpp_dither - figure out what color depth the pipe should send
* @crtc: CRTC structure
*
* A pipe may be connected to one or more outputs. Based on the depth of the
* attached framebuffer, choose a good color depth to use on the pipe.
*
* If possible, match the pipe depth to the fb depth. In some cases, this
* isn't ideal, because the connected output supports a lesser or restricted
* set of depths. Resolve that here:
* LVDS typically supports only 6bpc, so clamp down in that case
* HDMI supports only 8bpc or 12bpc, so clamp to 8bpc with dither for 10bpc
* Displays may support a restricted set as well, check EDID and clamp as
* appropriate.
*
* RETURNS:
* Dithering requirement (i.e. false if display bpc and pipe bpc match,
* true if they don't match).
*/
static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
unsigned int *pipe_bpp)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_encoder *encoder;
struct drm_connector *connector;
unsigned int display_bpc = UINT_MAX, bpc;

/* Walk the encoders & connectors on this crtc, get min bpc */
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);

if (encoder->crtc != crtc)
continue;

if (intel_encoder->type == INTEL_OUTPUT_LVDS) {
unsigned int lvds_bpc;

if ((I915_READ(PCH_LVDS) & LVDS_A3_POWER_MASK) ==
LVDS_A3_POWER_UP)
lvds_bpc = 8;
else
lvds_bpc = 6;

if (lvds_bpc < display_bpc) {
DRM_DEBUG_DRIVER("clamping display bpc (was %d) to LVDS (%d)\n", display_bpc, lvds_bpc);
display_bpc = lvds_bpc;
}
continue;
}

if (intel_encoder->type == INTEL_OUTPUT_EDP) {
/* Use VBT settings if we have an eDP panel */
unsigned int edp_bpc = dev_priv->edp.bpp / 3;

if (edp_bpc < display_bpc) {
DRM_DEBUG_DRIVER("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);
display_bpc = edp_bpc;
}
continue;
}

/* Not one of the known troublemakers, check the EDID */
list_for_each_entry(connector, &dev->mode_config.connector_list,
head) {
if (connector->encoder != encoder)
continue;

if (connector->display_info.bpc < display_bpc) {
DRM_DEBUG_DRIVER("clamping display bpc (was %d) to EDID reported max of %d\n", display_bpc, connector->display_info.bpc);
display_bpc = connector->display_info.bpc;
}
}

/*
* HDMI is either 12 or 8, so if the display lets 10bpc sneak
* through, clamp it down. (Note: >12bpc will be caught below.)
*/
if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
if (display_bpc > 8 && display_bpc < 12) {
DRM_DEBUG_DRIVER("forcing bpc to 12 for HDMI\n");
display_bpc = 12;
} else {
DRM_DEBUG_DRIVER("forcing bpc to 8 for HDMI\n");
display_bpc = 8;
}
}
}

/*
* We could just drive the pipe at the highest bpc all the time and
* enable dithering as needed, but that costs bandwidth. So choose
* the minimum value that expresses the full color range of the fb but
* also stays within the max display bpc discovered above.
*/

switch (crtc->fb->depth) {
case 8:
bpc = 8; /* since we go through a colormap */
break;
case 15:
case 16:
bpc = 6; /* min is 18bpp */
break;
case 24:
bpc = min((unsigned int)8, display_bpc);
break;
case 30:
bpc = min((unsigned int)10, display_bpc);
break;
case 48:
bpc = min((unsigned int)12, display_bpc);
break;
default:
DRM_DEBUG("unsupported depth, assuming 24 bits\n");
bpc = min((unsigned int)8, display_bpc);
break;
}

DRM_DEBUG_DRIVER("setting pipe bpc to %d (max display bpc %d)\n",
bpc, display_bpc);

*pipe_bpp = bpc * 3;

return display_bpc != bpc;
}

static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode,
Expand Down Expand Up @@ -4721,7 +4848,9 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
struct fdi_m_n m_n = {0};
u32 temp;
u32 lvds_sync = 0;
int target_clock, pixel_multiplier, lane, link_bw, bpp, factor;
int target_clock, pixel_multiplier, lane, link_bw, factor;
unsigned int pipe_bpp;
bool dither;

list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
if (encoder->base.crtc != crtc)
Expand Down Expand Up @@ -4848,64 +4977,46 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
/* determine panel color depth */
temp = I915_READ(PIPECONF(pipe));
temp &= ~PIPE_BPC_MASK;
if (is_lvds) {
/* the BPC will be 6 if it is 18-bit LVDS panel */
if ((I915_READ(PCH_LVDS) & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP)
temp |= PIPE_8BPC;
else
temp |= PIPE_6BPC;
} else if (has_edp_encoder) {
switch (dev_priv->edp.bpp/3) {
case 8:
temp |= PIPE_8BPC;
break;
case 10:
temp |= PIPE_10BPC;
break;
case 6:
temp |= PIPE_6BPC;
break;
case 12:
temp |= PIPE_12BPC;
break;
}
} else
temp |= PIPE_8BPC;
I915_WRITE(PIPECONF(pipe), temp);

switch (temp & PIPE_BPC_MASK) {
case PIPE_8BPC:
bpp = 24;
dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp);
switch (pipe_bpp) {
case 18:
temp |= PIPE_6BPC;
break;
case PIPE_10BPC:
bpp = 30;
case 24:
temp |= PIPE_8BPC;
break;
case PIPE_6BPC:
bpp = 18;
case 30:
temp |= PIPE_10BPC;
break;
case PIPE_12BPC:
bpp = 36;
case 36:
temp |= PIPE_12BPC;
break;
default:
DRM_ERROR("unknown pipe bpc value\n");
bpp = 24;
WARN(1, "intel_choose_pipe_bpp returned invalid value\n");
temp |= PIPE_8BPC;
pipe_bpp = 24;
break;
}

intel_crtc->bpp = pipe_bpp;
I915_WRITE(PIPECONF(pipe), temp);

if (!lane) {
/*
* Account for spread spectrum to avoid
* oversubscribing the link. Max center spread
* is 2.5%; use 5% for safety's sake.
*/
u32 bps = target_clock * bpp * 21 / 20;
u32 bps = target_clock * intel_crtc->bpp * 21 / 20;
lane = bps / (link_bw * 8) + 1;
}

intel_crtc->fdi_lanes = lane;

if (pixel_multiplier > 1)
link_bw *= pixel_multiplier;
ironlake_compute_m_n(bpp, lane, target_clock, link_bw, &m_n);
ironlake_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw,
&m_n);

/* Ironlake: try to setup display ref clock before DPLL
* enabling. This is only under driver's control after
Expand Down Expand Up @@ -5108,14 +5219,12 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
I915_WRITE(PCH_LVDS, temp);
}

/* set the dithering flag and clear for anything other than a panel. */
pipeconf &= ~PIPECONF_DITHER_EN;
pipeconf &= ~PIPECONF_DITHER_TYPE_MASK;
if (dev_priv->lvds_dither && (is_lvds || has_edp_encoder)) {
if ((is_lvds && dev_priv->lvds_dither) || dither) {
pipeconf |= PIPECONF_DITHER_EN;
pipeconf |= PIPECONF_DITHER_TYPE_ST1;
}

if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
intel_dp_set_m_n(crtc, mode, adjusted_mode);
} else {
Expand Down Expand Up @@ -6638,6 +6747,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)

intel_crtc_reset(&intel_crtc->base);
intel_crtc->active = true; /* force the pipe off on setup_init_config */
intel_crtc->bpp = 24; /* default for pre-Ironlake */

if (HAS_PCH_SPLIT(dev)) {
intel_helper_funcs.prepare = ironlake_crtc_prepare;
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/gpu/drm/i915/intel_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ struct intel_crtc {
int16_t cursor_x, cursor_y;
int16_t cursor_width, cursor_height;
bool cursor_visible;
unsigned int bpp;
};

#define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
Expand Down

0 comments on commit 1bde7cf

Please sign in to comment.