aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2011-06-24 15:19:22 -0400
committerKeith Packard <keithp@keithp.com>2011-07-07 16:20:34 -0400
commit5a3542041bf85a65633ed203c3782492116ebb94 (patch)
tree809fc9808011b5d2f20bf870d5472f093ee9c03b /drivers/gpu/drm
parent9325c9f088c42e3e07475d4f733ee6539ebf9c0b (diff)
drm/i915: split out Ironlake pipe bpp picking code
Figuring out which pipe bpp to use is a bit painful. It depends on both the encoder and display configuration attached to a pipe. For instance, to drive a 24bpp framebuffer out to an 18bpp panel, we need to use 6bpc on the pipe but also enable dithering. But driving that same framebuffer to a DisplayPort output on another pipe means using 8bpc and no dithering. So split out and enhance the code to handle the various cases, returning an appropriate pipe bpp as well as whether dithering should be enabled. Save the resulting pipe bpp in the intel_crtc struct for use by encoders in calculating bandwidth requirements (defaults to 24bpp on pre-ILK). Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c194
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h1
2 files changed, 153 insertions, 42 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index ce3666d53f57..7c5d28fd5f36 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4309,6 +4309,133 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
4309 return dev_priv->lvds_use_ssc && i915_panel_use_ssc; 4309 return dev_priv->lvds_use_ssc && i915_panel_use_ssc;
4310} 4310}
4311 4311
4312/**
4313 * intel_choose_pipe_bpp_dither - figure out what color depth the pipe should send
4314 * @crtc: CRTC structure
4315 *
4316 * A pipe may be connected to one or more outputs. Based on the depth of the
4317 * attached framebuffer, choose a good color depth to use on the pipe.
4318 *
4319 * If possible, match the pipe depth to the fb depth. In some cases, this
4320 * isn't ideal, because the connected output supports a lesser or restricted
4321 * set of depths. Resolve that here:
4322 * LVDS typically supports only 6bpc, so clamp down in that case
4323 * HDMI supports only 8bpc or 12bpc, so clamp to 8bpc with dither for 10bpc
4324 * Displays may support a restricted set as well, check EDID and clamp as
4325 * appropriate.
4326 *
4327 * RETURNS:
4328 * Dithering requirement (i.e. false if display bpc and pipe bpc match,
4329 * true if they don't match).
4330 */
4331static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
4332 unsigned int *pipe_bpp)
4333{
4334 struct drm_device *dev = crtc->dev;
4335 struct drm_i915_private *dev_priv = dev->dev_private;
4336 struct drm_encoder *encoder;
4337 struct drm_connector *connector;
4338 unsigned int display_bpc = UINT_MAX, bpc;
4339
4340 /* Walk the encoders & connectors on this crtc, get min bpc */
4341 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
4342 struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
4343
4344 if (encoder->crtc != crtc)
4345 continue;
4346
4347 if (intel_encoder->type == INTEL_OUTPUT_LVDS) {
4348 unsigned int lvds_bpc;
4349
4350 if ((I915_READ(PCH_LVDS) & LVDS_A3_POWER_MASK) ==
4351 LVDS_A3_POWER_UP)
4352 lvds_bpc = 8;
4353 else
4354 lvds_bpc = 6;
4355
4356 if (lvds_bpc < display_bpc) {
4357 DRM_DEBUG_DRIVER("clamping display bpc (was %d) to LVDS (%d)\n", display_bpc, lvds_bpc);
4358 display_bpc = lvds_bpc;
4359 }
4360 continue;
4361 }
4362
4363 if (intel_encoder->type == INTEL_OUTPUT_EDP) {
4364 /* Use VBT settings if we have an eDP panel */
4365 unsigned int edp_bpc = dev_priv->edp.bpp / 3;
4366
4367 if (edp_bpc < display_bpc) {
4368 DRM_DEBUG_DRIVER("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);
4369 display_bpc = edp_bpc;
4370 }
4371 continue;
4372 }
4373
4374 /* Not one of the known troublemakers, check the EDID */
4375 list_for_each_entry(connector, &dev->mode_config.connector_list,
4376 head) {
4377 if (connector->encoder != encoder)
4378 continue;
4379
4380 if (connector->display_info.bpc < display_bpc) {
4381 DRM_DEBUG_DRIVER("clamping display bpc (was %d) to EDID reported max of %d\n", display_bpc, connector->display_info.bpc);
4382 display_bpc = connector->display_info.bpc;
4383 }
4384 }
4385
4386 /*
4387 * HDMI is either 12 or 8, so if the display lets 10bpc sneak
4388 * through, clamp it down. (Note: >12bpc will be caught below.)
4389 */
4390 if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
4391 if (display_bpc > 8 && display_bpc < 12) {
4392 DRM_DEBUG_DRIVER("forcing bpc to 12 for HDMI\n");
4393 display_bpc = 12;
4394 } else {
4395 DRM_DEBUG_DRIVER("forcing bpc to 8 for HDMI\n");
4396 display_bpc = 8;
4397 }
4398 }
4399 }
4400
4401 /*
4402 * We could just drive the pipe at the highest bpc all the time and
4403 * enable dithering as needed, but that costs bandwidth. So choose
4404 * the minimum value that expresses the full color range of the fb but
4405 * also stays within the max display bpc discovered above.
4406 */
4407
4408 switch (crtc->fb->depth) {
4409 case 8:
4410 bpc = 8; /* since we go through a colormap */
4411 break;
4412 case 15:
4413 case 16:
4414 bpc = 6; /* min is 18bpp */
4415 break;
4416 case 24:
4417 bpc = min((unsigned int)8, display_bpc);
4418 break;
4419 case 30:
4420 bpc = min((unsigned int)10, display_bpc);
4421 break;
4422 case 48:
4423 bpc = min((unsigned int)12, display_bpc);
4424 break;
4425 default:
4426 DRM_DEBUG("unsupported depth, assuming 24 bits\n");
4427 bpc = min((unsigned int)8, display_bpc);
4428 break;
4429 }
4430
4431 DRM_DEBUG_DRIVER("setting pipe bpc to %d (max display bpc %d)\n",
4432 bpc, display_bpc);
4433
4434 *pipe_bpp = bpc * 3;
4435
4436 return display_bpc != bpc;
4437}
4438
4312static int i9xx_crtc_mode_set(struct drm_crtc *crtc, 4439static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
4313 struct drm_display_mode *mode, 4440 struct drm_display_mode *mode,
4314 struct drm_display_mode *adjusted_mode, 4441 struct drm_display_mode *adjusted_mode,
@@ -4721,7 +4848,9 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
4721 struct fdi_m_n m_n = {0}; 4848 struct fdi_m_n m_n = {0};
4722 u32 temp; 4849 u32 temp;
4723 u32 lvds_sync = 0; 4850 u32 lvds_sync = 0;
4724 int target_clock, pixel_multiplier, lane, link_bw, bpp, factor; 4851 int target_clock, pixel_multiplier, lane, link_bw, factor;
4852 unsigned int pipe_bpp;
4853 bool dither;
4725 4854
4726 list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { 4855 list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
4727 if (encoder->base.crtc != crtc) 4856 if (encoder->base.crtc != crtc)
@@ -4848,56 +4977,37 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
4848 /* determine panel color depth */ 4977 /* determine panel color depth */
4849 temp = I915_READ(PIPECONF(pipe)); 4978 temp = I915_READ(PIPECONF(pipe));
4850 temp &= ~PIPE_BPC_MASK; 4979 temp &= ~PIPE_BPC_MASK;
4851 if (is_lvds) { 4980 dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp);
4852 /* the BPC will be 6 if it is 18-bit LVDS panel */ 4981 switch (pipe_bpp) {
4853 if ((I915_READ(PCH_LVDS) & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP) 4982 case 18:
4854 temp |= PIPE_8BPC; 4983 temp |= PIPE_6BPC;
4855 else
4856 temp |= PIPE_6BPC;
4857 } else if (has_edp_encoder) {
4858 switch (dev_priv->edp.bpp/3) {
4859 case 8:
4860 temp |= PIPE_8BPC;
4861 break;
4862 case 10:
4863 temp |= PIPE_10BPC;
4864 break;
4865 case 6:
4866 temp |= PIPE_6BPC;
4867 break;
4868 case 12:
4869 temp |= PIPE_12BPC;
4870 break;
4871 }
4872 } else
4873 temp |= PIPE_8BPC;
4874 I915_WRITE(PIPECONF(pipe), temp);
4875
4876 switch (temp & PIPE_BPC_MASK) {
4877 case PIPE_8BPC:
4878 bpp = 24;
4879 break; 4984 break;
4880 case PIPE_10BPC: 4985 case 24:
4881 bpp = 30; 4986 temp |= PIPE_8BPC;
4882 break; 4987 break;
4883 case PIPE_6BPC: 4988 case 30:
4884 bpp = 18; 4989 temp |= PIPE_10BPC;
4885 break; 4990 break;
4886 case PIPE_12BPC: 4991 case 36:
4887 bpp = 36; 4992 temp |= PIPE_12BPC;
4888 break; 4993 break;
4889 default: 4994 default:
4890 DRM_ERROR("unknown pipe bpc value\n"); 4995 WARN(1, "intel_choose_pipe_bpp returned invalid value\n");
4891 bpp = 24; 4996 temp |= PIPE_8BPC;
4997 pipe_bpp = 24;
4998 break;
4892 } 4999 }
4893 5000
5001 intel_crtc->bpp = pipe_bpp;
5002 I915_WRITE(PIPECONF(pipe), temp);
5003
4894 if (!lane) { 5004 if (!lane) {
4895 /* 5005 /*
4896 * Account for spread spectrum to avoid 5006 * Account for spread spectrum to avoid
4897 * oversubscribing the link. Max center spread 5007 * oversubscribing the link. Max center spread
4898 * is 2.5%; use 5% for safety's sake. 5008 * is 2.5%; use 5% for safety's sake.
4899 */ 5009 */
4900 u32 bps = target_clock * bpp * 21 / 20; 5010 u32 bps = target_clock * intel_crtc->bpp * 21 / 20;
4901 lane = bps / (link_bw * 8) + 1; 5011 lane = bps / (link_bw * 8) + 1;
4902 } 5012 }
4903 5013
@@ -4905,7 +5015,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
4905 5015
4906 if (pixel_multiplier > 1) 5016 if (pixel_multiplier > 1)
4907 link_bw *= pixel_multiplier; 5017 link_bw *= pixel_multiplier;
4908 ironlake_compute_m_n(bpp, lane, target_clock, link_bw, &m_n); 5018 ironlake_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw,
5019 &m_n);
4909 5020
4910 /* Ironlake: try to setup display ref clock before DPLL 5021 /* Ironlake: try to setup display ref clock before DPLL
4911 * enabling. This is only under driver's control after 5022 * enabling. This is only under driver's control after
@@ -5108,14 +5219,12 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
5108 I915_WRITE(PCH_LVDS, temp); 5219 I915_WRITE(PCH_LVDS, temp);
5109 } 5220 }
5110 5221
5111 /* set the dithering flag and clear for anything other than a panel. */
5112 pipeconf &= ~PIPECONF_DITHER_EN; 5222 pipeconf &= ~PIPECONF_DITHER_EN;
5113 pipeconf &= ~PIPECONF_DITHER_TYPE_MASK; 5223 pipeconf &= ~PIPECONF_DITHER_TYPE_MASK;
5114 if (dev_priv->lvds_dither && (is_lvds || has_edp_encoder)) { 5224 if ((is_lvds && dev_priv->lvds_dither) || dither) {
5115 pipeconf |= PIPECONF_DITHER_EN; 5225 pipeconf |= PIPECONF_DITHER_EN;
5116 pipeconf |= PIPECONF_DITHER_TYPE_ST1; 5226 pipeconf |= PIPECONF_DITHER_TYPE_ST1;
5117 } 5227 }
5118
5119 if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) { 5228 if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
5120 intel_dp_set_m_n(crtc, mode, adjusted_mode); 5229 intel_dp_set_m_n(crtc, mode, adjusted_mode);
5121 } else { 5230 } else {
@@ -6638,6 +6747,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
6638 6747
6639 intel_crtc_reset(&intel_crtc->base); 6748 intel_crtc_reset(&intel_crtc->base);
6640 intel_crtc->active = true; /* force the pipe off on setup_init_config */ 6749 intel_crtc->active = true; /* force the pipe off on setup_init_config */
6750 intel_crtc->bpp = 24; /* default for pre-Ironlake */
6641 6751
6642 if (HAS_PCH_SPLIT(dev)) { 6752 if (HAS_PCH_SPLIT(dev)) {
6643 intel_helper_funcs.prepare = ironlake_crtc_prepare; 6753 intel_helper_funcs.prepare = ironlake_crtc_prepare;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 8ac3bd8b6faa..7ec48d864577 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -170,6 +170,7 @@ struct intel_crtc {
170 int16_t cursor_x, cursor_y; 170 int16_t cursor_x, cursor_y;
171 int16_t cursor_width, cursor_height; 171 int16_t cursor_width, cursor_height;
172 bool cursor_visible; 172 bool cursor_visible;
173 unsigned int bpp;
173}; 174};
174 175
175#define to_intel_crtc(x) container_of(x, struct intel_crtc, base) 176#define to_intel_crtc(x) container_of(x, struct intel_crtc, base)