aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-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;