Commit 3b5c78a35cf7511c15e09a9b0ffab290a42d9bcf

Authored by Adam Jackson
Committed by Keith Packard
1 parent f45b55575c

drm/i915/dp: Dither down to 6bpc if it makes the mode fit

Some active adaptors (VGA usually) only have two lanes at 2.7GHz.
That's a maximum pixel clock of 144MHz at 8bpc, but 192MHz at 6bpc.

Fixes Asus UX31 panel being black at startup due to no valid modes since
dc22ee6fc18ce0f15424e753e8473c306ece95c1.

v2: Rebased to current code, resulting in the fix applying to EDP panels as
    well.  Also changed from spatio-temporal to just spatial dithering on
    pre-ironlake, to be conssitent (and less visual flicker)

Signed-off-by: Adam Jackson <ajax@redhat.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
Tested-by: Eric Anholt <eric@anholt.net>
Tested-by: Dirk Hohndel <hohndel@infradead.org>
Signed-off-by: Keith Packard <keithp@keithp.com>

Showing 3 changed files with 39 additions and 8 deletions Side-by-side Diff

drivers/gpu/drm/i915/intel_display.c
... ... @@ -4670,6 +4670,7 @@
4670 4670 /**
4671 4671 * intel_choose_pipe_bpp_dither - figure out what color depth the pipe should send
4672 4672 * @crtc: CRTC structure
  4673 + * @mode: requested mode
4673 4674 *
4674 4675 * A pipe may be connected to one or more outputs. Based on the depth of the
4675 4676 * attached framebuffer, choose a good color depth to use on the pipe.
4676 4677  
... ... @@ -4681,13 +4682,15 @@
4681 4682 * HDMI supports only 8bpc or 12bpc, so clamp to 8bpc with dither for 10bpc
4682 4683 * Displays may support a restricted set as well, check EDID and clamp as
4683 4684 * appropriate.
  4685 + * DP may want to dither down to 6bpc to fit larger modes
4684 4686 *
4685 4687 * RETURNS:
4686 4688 * Dithering requirement (i.e. false if display bpc and pipe bpc match,
4687 4689 * true if they don't match).
4688 4690 */
4689 4691 static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
4690   - unsigned int *pipe_bpp)
  4692 + unsigned int *pipe_bpp,
  4693 + struct drm_display_mode *mode)
4691 4694 {
4692 4695 struct drm_device *dev = crtc->dev;
4693 4696 struct drm_i915_private *dev_priv = dev->dev_private;
... ... @@ -4758,6 +4761,11 @@
4758 4761 }
4759 4762 }
4760 4763  
  4764 + if (mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) {
  4765 + DRM_DEBUG_KMS("Dithering DP to 6bpc\n");
  4766 + display_bpc = 6;
  4767 + }
  4768 +
4761 4769 /*
4762 4770 * We could just drive the pipe at the highest bpc all the time and
4763 4771 * enable dithering as needed, but that costs bandwidth. So choose
... ... @@ -5019,6 +5027,16 @@
5019 5027 pipeconf &= ~PIPECONF_DOUBLE_WIDE;
5020 5028 }
5021 5029  
  5030 + /* default to 8bpc */
  5031 + pipeconf &= ~(PIPECONF_BPP_MASK | PIPECONF_DITHER_EN);
  5032 + if (is_dp) {
  5033 + if (mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) {
  5034 + pipeconf |= PIPECONF_BPP_6 |
  5035 + PIPECONF_DITHER_EN |
  5036 + PIPECONF_DITHER_TYPE_SP;
  5037 + }
  5038 + }
  5039 +
5022 5040 dpll |= DPLL_VCO_ENABLE;
5023 5041  
5024 5042 DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
... ... @@ -5480,7 +5498,7 @@
5480 5498 /* determine panel color depth */
5481 5499 temp = I915_READ(PIPECONF(pipe));
5482 5500 temp &= ~PIPE_BPC_MASK;
5483   - dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp);
  5501 + dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp, mode);
5484 5502 switch (pipe_bpp) {
5485 5503 case 18:
5486 5504 temp |= PIPE_6BPC;
drivers/gpu/drm/i915/intel_dp.c
... ... @@ -208,13 +208,15 @@
208 208 */
209 209  
210 210 static int
211   -intel_dp_link_required(struct intel_dp *intel_dp, int pixel_clock)
  211 +intel_dp_link_required(struct intel_dp *intel_dp, int pixel_clock, int check_bpp)
212 212 {
213 213 struct drm_crtc *crtc = intel_dp->base.base.crtc;
214 214 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
215 215 int bpp = 24;
216 216  
217   - if (intel_crtc)
  217 + if (check_bpp)
  218 + bpp = check_bpp;
  219 + else if (intel_crtc)
218 220 bpp = intel_crtc->bpp;
219 221  
220 222 return (pixel_clock * bpp + 9) / 10;
... ... @@ -233,6 +235,7 @@
233 235 struct intel_dp *intel_dp = intel_attached_dp(connector);
234 236 int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp));
235 237 int max_lanes = intel_dp_max_lane_count(intel_dp);
  238 + int max_rate, mode_rate;
236 239  
237 240 if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) {
238 241 if (mode->hdisplay > intel_dp->panel_fixed_mode->hdisplay)
239 242  
... ... @@ -242,10 +245,18 @@
242 245 return MODE_PANEL;
243 246 }
244 247  
245   - if (intel_dp_link_required(intel_dp, mode->clock)
246   - > intel_dp_max_data_rate(max_link_clock, max_lanes))
247   - return MODE_CLOCK_HIGH;
  248 + mode_rate = intel_dp_link_required(intel_dp, mode->clock, 0);
  249 + max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes);
248 250  
  251 + if (mode_rate > max_rate) {
  252 + mode_rate = intel_dp_link_required(intel_dp,
  253 + mode->clock, 18);
  254 + if (mode_rate > max_rate)
  255 + return MODE_CLOCK_HIGH;
  256 + else
  257 + mode->private_flags |= INTEL_MODE_DP_FORCE_6BPC;
  258 + }
  259 +
249 260 if (mode->clock < 10000)
250 261 return MODE_CLOCK_LOW;
251 262  
... ... @@ -672,6 +683,7 @@
672 683 int lane_count, clock;
673 684 int max_lane_count = intel_dp_max_lane_count(intel_dp);
674 685 int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 0;
  686 + int bpp = mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 0;
675 687 static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
676 688  
677 689 if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) {
... ... @@ -689,7 +701,7 @@
689 701 for (clock = 0; clock <= max_clock; clock++) {
690 702 int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count);
691 703  
692   - if (intel_dp_link_required(intel_dp, mode->clock)
  704 + if (intel_dp_link_required(intel_dp, mode->clock, bpp)
693 705 <= link_avail) {
694 706 intel_dp->link_bw = bws[clock];
695 707 intel_dp->lane_count = lane_count;
drivers/gpu/drm/i915/intel_drv.h
... ... @@ -110,6 +110,7 @@
110 110 /* drm_display_mode->private_flags */
111 111 #define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0)
112 112 #define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT)
  113 +#define INTEL_MODE_DP_FORCE_6BPC (0x10)
113 114  
114 115 static inline void
115 116 intel_mode_set_pixel_multiplier(struct drm_display_mode *mode,