aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2013-02-20 18:00:16 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-04-29 15:51:17 -0400
commite29c22c0c4fefeb48a0157811930f7e9df0bb3f3 (patch)
tree9343736c96d36826c1827c60a19b76a934d2989c
parent325b9d048810f7689ec644595061c0b700e64bce (diff)
drm/i915: implement fdi auto-dithering
So on a bunch of setups we only have 2 fdi lanes available, e.g. hsw VGA or 3 pipes on ivb. And seemingly a lot of modes don't quite fit into this, among them the default 1080p mode. The solution is to dither down the pipe a bit so that everything fits, which this patch implements. But ports compute their state under the assumption that the bpp they pick will be the one selected, e.g. the display port bw computations won't work otherwise. Now we could adjust our code to again up-dither to the computed DP link parameters, but that's pointless. So instead when the pipe needs to adjust parameters we need to retry the pipe_config computation at the encoder stage. Furthermore we need to inform encoders that they should not increase bandwidth requirements if possible. This is required for the hdmi code, which prefers the pipe to up-dither to either of the two possible hdmi bpc values. LVDS has a similar requirement, although that's probably only theoretical in nature: It's unlikely that we'll ever see an 8bpc high-res lvds panel (which is required to hit the 2 fdi lane limit). eDP is the only thing which could increase the pipe_bpp setting again, even when in the retry-loop. This could hit the WARN. Two reasons for not bothering: - On many eDP panels we'll get a black screen if the bpp settings don't match vbt. So failing the modeset is the right thing to do. But since that also means it's the only way to light up the panel, it should work. So we shouldn't be able to hit this WARN. - There are still opens around the eDP panel handling, and maybe we need additional tricks. Before that happens it's imo no use trying to be too clever. Worst case we just need to kill that WARN or maybe fail the compute config stage if the eDP connector can't get the bpp setting it wants. And since this can only happen with an fdi link in between and so for pch eDP panels it's rather unlikely to blow up, if ever. v2: Rebased on top of a bikeshed from Paulo. v3: Improve commit message around eDP handling with the stuff things with Imre. Reviewed-by: Imre Deak <imre.deak@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/intel_display.c56
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h7
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c14
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c2
4 files changed, 62 insertions, 17 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 1ef44b2a6952..f40a28589eea 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4040,13 +4040,16 @@ static bool ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
4040 } 4040 }
4041} 4041}
4042 4042
4043static bool ironlake_fdi_compute_config(struct intel_crtc *intel_crtc, 4043#define RETRY 1
4044 struct intel_crtc_config *pipe_config) 4044static int ironlake_fdi_compute_config(struct intel_crtc *intel_crtc,
4045 struct intel_crtc_config *pipe_config)
4045{ 4046{
4046 struct drm_device *dev = intel_crtc->base.dev; 4047 struct drm_device *dev = intel_crtc->base.dev;
4047 struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; 4048 struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
4048 int target_clock, lane, link_bw; 4049 int target_clock, lane, link_bw;
4050 bool setup_ok, needs_recompute = false;
4049 4051
4052retry:
4050 /* FDI is a binary signal running at ~2.7GHz, encoding 4053 /* FDI is a binary signal running at ~2.7GHz, encoding
4051 * each output octet as 10 bits. The actual frequency 4054 * each output octet as 10 bits. The actual frequency
4052 * is stored as a divider into a 100MHz clock, and the 4055 * is stored as a divider into a 100MHz clock, and the
@@ -4071,12 +4074,26 @@ static bool ironlake_fdi_compute_config(struct intel_crtc *intel_crtc,
4071 intel_link_compute_m_n(pipe_config->pipe_bpp, lane, target_clock, 4074 intel_link_compute_m_n(pipe_config->pipe_bpp, lane, target_clock,
4072 link_bw, &pipe_config->fdi_m_n); 4075 link_bw, &pipe_config->fdi_m_n);
4073 4076
4074 return ironlake_check_fdi_lanes(intel_crtc->base.dev, 4077 setup_ok = ironlake_check_fdi_lanes(intel_crtc->base.dev,
4075 intel_crtc->pipe, pipe_config); 4078 intel_crtc->pipe, pipe_config);
4079 if (!setup_ok && pipe_config->pipe_bpp > 6*3) {
4080 pipe_config->pipe_bpp -= 2*3;
4081 DRM_DEBUG_KMS("fdi link bw constraint, reducing pipe bpp to %i\n",
4082 pipe_config->pipe_bpp);
4083 needs_recompute = true;
4084 pipe_config->bw_constrained = true;
4085
4086 goto retry;
4087 }
4088
4089 if (needs_recompute)
4090 return RETRY;
4091
4092 return setup_ok ? 0 : -EINVAL;
4076} 4093}
4077 4094
4078static bool intel_crtc_compute_config(struct drm_crtc *crtc, 4095static int intel_crtc_compute_config(struct drm_crtc *crtc,
4079 struct intel_crtc_config *pipe_config) 4096 struct intel_crtc_config *pipe_config)
4080{ 4097{
4081 struct drm_device *dev = crtc->dev; 4098 struct drm_device *dev = crtc->dev;
4082 struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; 4099 struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
@@ -4085,7 +4102,7 @@ static bool intel_crtc_compute_config(struct drm_crtc *crtc,
4085 /* FDI link clock is fixed at 2.7G */ 4102 /* FDI link clock is fixed at 2.7G */
4086 if (pipe_config->requested_mode.clock * 3 4103 if (pipe_config->requested_mode.clock * 3
4087 > IRONLAKE_FDI_FREQ * 4) 4104 > IRONLAKE_FDI_FREQ * 4)
4088 return false; 4105 return -EINVAL;
4089 } 4106 }
4090 4107
4091 /* All interlaced capable intel hw wants timings in frames. Note though 4108 /* All interlaced capable intel hw wants timings in frames. Note though
@@ -4099,7 +4116,7 @@ static bool intel_crtc_compute_config(struct drm_crtc *crtc,
4099 */ 4116 */
4100 if ((INTEL_INFO(dev)->gen > 4 || IS_G4X(dev)) && 4117 if ((INTEL_INFO(dev)->gen > 4 || IS_G4X(dev)) &&
4101 adjusted_mode->hsync_start == adjusted_mode->hdisplay) 4118 adjusted_mode->hsync_start == adjusted_mode->hdisplay)
4102 return false; 4119 return -EINVAL;
4103 4120
4104 if ((IS_G4X(dev) || IS_VALLEYVIEW(dev)) && pipe_config->pipe_bpp > 10*3) { 4121 if ((IS_G4X(dev) || IS_VALLEYVIEW(dev)) && pipe_config->pipe_bpp > 10*3) {
4105 pipe_config->pipe_bpp = 10*3; /* 12bpc is gen5+ */ 4122 pipe_config->pipe_bpp = 10*3; /* 12bpc is gen5+ */
@@ -4112,7 +4129,7 @@ static bool intel_crtc_compute_config(struct drm_crtc *crtc,
4112 if (pipe_config->has_pch_encoder) 4129 if (pipe_config->has_pch_encoder)
4113 return ironlake_fdi_compute_config(to_intel_crtc(crtc), pipe_config); 4130 return ironlake_fdi_compute_config(to_intel_crtc(crtc), pipe_config);
4114 4131
4115 return true; 4132 return 0;
4116} 4133}
4117 4134
4118static int valleyview_get_display_clock_speed(struct drm_device *dev) 4135static int valleyview_get_display_clock_speed(struct drm_device *dev)
@@ -7692,7 +7709,8 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
7692 struct drm_encoder_helper_funcs *encoder_funcs; 7709 struct drm_encoder_helper_funcs *encoder_funcs;
7693 struct intel_encoder *encoder; 7710 struct intel_encoder *encoder;
7694 struct intel_crtc_config *pipe_config; 7711 struct intel_crtc_config *pipe_config;
7695 int plane_bpp; 7712 int plane_bpp, ret = -EINVAL;
7713 bool retry = true;
7696 7714
7697 pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL); 7715 pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL);
7698 if (!pipe_config) 7716 if (!pipe_config)
@@ -7705,6 +7723,7 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
7705 if (plane_bpp < 0) 7723 if (plane_bpp < 0)
7706 goto fail; 7724 goto fail;
7707 7725
7726encoder_retry:
7708 /* Pass our mode to the connectors and the CRTC to give them a chance to 7727 /* Pass our mode to the connectors and the CRTC to give them a chance to
7709 * adjust it according to limitations or connector properties, and also 7728 * adjust it according to limitations or connector properties, and also
7710 * a chance to reject the mode entirely. 7729 * a chance to reject the mode entirely.
@@ -7733,10 +7752,23 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
7733 } 7752 }
7734 } 7753 }
7735 7754
7736 if (!(intel_crtc_compute_config(crtc, pipe_config))) { 7755 ret = intel_crtc_compute_config(crtc, pipe_config);
7756 if (ret < 0) {
7737 DRM_DEBUG_KMS("CRTC fixup failed\n"); 7757 DRM_DEBUG_KMS("CRTC fixup failed\n");
7738 goto fail; 7758 goto fail;
7739 } 7759 }
7760
7761 if (ret == RETRY) {
7762 if (WARN(!retry, "loop in pipe configuration computation\n")) {
7763 ret = -EINVAL;
7764 goto fail;
7765 }
7766
7767 DRM_DEBUG_KMS("CRTC bw constrained, retrying\n");
7768 retry = false;
7769 goto encoder_retry;
7770 }
7771
7740 DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); 7772 DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
7741 7773
7742 pipe_config->dither = pipe_config->pipe_bpp != plane_bpp; 7774 pipe_config->dither = pipe_config->pipe_bpp != plane_bpp;
@@ -7746,7 +7778,7 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
7746 return pipe_config; 7778 return pipe_config;
7747fail: 7779fail:
7748 kfree(pipe_config); 7780 kfree(pipe_config);
7749 return ERR_PTR(-EINVAL); 7781 return ERR_PTR(ret);
7750} 7782}
7751 7783
7752/* Computes which crtcs are affected and sets the relevant bits in the mask. For 7784/* Computes which crtcs are affected and sets the relevant bits in the mask. For
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 48f309eaf7aa..766afcf39ee9 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -223,6 +223,13 @@ struct intel_crtc_config {
223 /* Controls for the clock computation, to override various stages. */ 223 /* Controls for the clock computation, to override various stages. */
224 bool clock_set; 224 bool clock_set;
225 225
226 /*
227 * crtc bandwidth limit, don't increase pipe bpp or clock if not really
228 * required. This is set in the 2nd loop of calling encoder's
229 * ->compute_config if the first pick doesn't work out.
230 */
231 bool bw_constrained;
232
226 /* Settings for the intel dpll used on pretty much everything but 233 /* Settings for the intel dpll used on pretty much everything but
227 * haswell. */ 234 * haswell. */
228 struct dpll dpll; 235 struct dpll dpll;
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 21302db7f76d..93de5ff77912 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -784,6 +784,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
784 struct drm_device *dev = encoder->base.dev; 784 struct drm_device *dev = encoder->base.dev;
785 struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; 785 struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
786 int clock_12bpc = pipe_config->requested_mode.clock * 3 / 2; 786 int clock_12bpc = pipe_config->requested_mode.clock * 3 / 2;
787 int desired_bpp;
787 788
788 if (intel_hdmi->color_range_auto) { 789 if (intel_hdmi->color_range_auto) {
789 /* See CEA-861-E - 5.1 Default Encoding Parameters */ 790 /* See CEA-861-E - 5.1 Default Encoding Parameters */
@@ -808,16 +809,21 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
808 */ 809 */
809 if (pipe_config->pipe_bpp > 8*3 && clock_12bpc <= 225000 810 if (pipe_config->pipe_bpp > 8*3 && clock_12bpc <= 225000
810 && HAS_PCH_SPLIT(dev)) { 811 && HAS_PCH_SPLIT(dev)) {
811 DRM_DEBUG_KMS("forcing bpc to 12 for HDMI\n"); 812 DRM_DEBUG_KMS("picking bpc to 12 for HDMI output\n");
812 pipe_config->pipe_bpp = 12*3; 813 desired_bpp = 12*3;
813 814
814 /* Need to adjust the port link by 1.5x for 12bpc. */ 815 /* Need to adjust the port link by 1.5x for 12bpc. */
815 adjusted_mode->clock = clock_12bpc; 816 adjusted_mode->clock = clock_12bpc;
816 pipe_config->pixel_target_clock = 817 pipe_config->pixel_target_clock =
817 pipe_config->requested_mode.clock; 818 pipe_config->requested_mode.clock;
818 } else { 819 } else {
819 DRM_DEBUG_KMS("forcing bpc to 8 for HDMI\n"); 820 DRM_DEBUG_KMS("picking bpc to 8 for HDMI output\n");
820 pipe_config->pipe_bpp = 8*3; 821 desired_bpp = 8*3;
822 }
823
824 if (!pipe_config->bw_constrained) {
825 DRM_DEBUG_KMS("forcing pipe bpc to %i for HDMI\n", desired_bpp);
826 pipe_config->pipe_bpp = desired_bpp;
821 } 827 }
822 828
823 if (adjusted_mode->clock > 225000) { 829 if (adjusted_mode->clock > 225000) {
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 3e29499b2e9a..8d65baf043ea 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -248,7 +248,7 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
248 else 248 else
249 lvds_bpp = 6*3; 249 lvds_bpp = 6*3;
250 250
251 if (lvds_bpp != pipe_config->pipe_bpp) { 251 if (lvds_bpp != pipe_config->pipe_bpp && !pipe_config->bw_constrained) {
252 DRM_DEBUG_KMS("forcing display bpp (was %d) to LVDS (%d)\n", 252 DRM_DEBUG_KMS("forcing display bpp (was %d) to LVDS (%d)\n",
253 pipe_config->pipe_bpp, lvds_bpp); 253 pipe_config->pipe_bpp, lvds_bpp);
254 pipe_config->pipe_bpp = lvds_bpp; 254 pipe_config->pipe_bpp = lvds_bpp;