diff options
author | Adam Jackson <ajax@redhat.com> | 2011-12-13 18:41:00 -0500 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2011-12-16 11:49:59 -0500 |
commit | 3b5c78a35cf7511c15e09a9b0ffab290a42d9bcf (patch) | |
tree | 1ac33469f850f6c84df493974cf6034991dcd0c1 | |
parent | f45b55575cedb7efa782e43f1ea74338456d0381 (diff) |
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>
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 24 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 1 |
3 files changed, 39 insertions, 8 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 91b5f8707a62..d809b038ca88 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -4670,6 +4670,7 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) | |||
4670 | /** | 4670 | /** |
4671 | * intel_choose_pipe_bpp_dither - figure out what color depth the pipe should send | 4671 | * intel_choose_pipe_bpp_dither - figure out what color depth the pipe should send |
4672 | * @crtc: CRTC structure | 4672 | * @crtc: CRTC structure |
4673 | * @mode: requested mode | ||
4673 | * | 4674 | * |
4674 | * A pipe may be connected to one or more outputs. Based on the depth of the | 4675 | * A pipe may be connected to one or more outputs. Based on the depth of the |
4675 | * attached framebuffer, choose a good color depth to use on the pipe. | 4676 | * attached framebuffer, choose a good color depth to use on the pipe. |
@@ -4681,13 +4682,15 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) | |||
4681 | * HDMI supports only 8bpc or 12bpc, so clamp to 8bpc with dither for 10bpc | 4682 | * HDMI supports only 8bpc or 12bpc, so clamp to 8bpc with dither for 10bpc |
4682 | * Displays may support a restricted set as well, check EDID and clamp as | 4683 | * Displays may support a restricted set as well, check EDID and clamp as |
4683 | * appropriate. | 4684 | * appropriate. |
4685 | * DP may want to dither down to 6bpc to fit larger modes | ||
4684 | * | 4686 | * |
4685 | * RETURNS: | 4687 | * RETURNS: |
4686 | * Dithering requirement (i.e. false if display bpc and pipe bpc match, | 4688 | * Dithering requirement (i.e. false if display bpc and pipe bpc match, |
4687 | * true if they don't match). | 4689 | * true if they don't match). |
4688 | */ | 4690 | */ |
4689 | static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, | 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 | struct drm_device *dev = crtc->dev; | 4695 | struct drm_device *dev = crtc->dev; |
4693 | struct drm_i915_private *dev_priv = dev->dev_private; | 4696 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -4758,6 +4761,11 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, | |||
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 | * We could just drive the pipe at the highest bpc all the time and | 4770 | * We could just drive the pipe at the highest bpc all the time and |
4763 | * enable dithering as needed, but that costs bandwidth. So choose | 4771 | * enable dithering as needed, but that costs bandwidth. So choose |
@@ -5019,6 +5027,16 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, | |||
5019 | pipeconf &= ~PIPECONF_DOUBLE_WIDE; | 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 | dpll |= DPLL_VCO_ENABLE; | 5040 | dpll |= DPLL_VCO_ENABLE; |
5023 | 5041 | ||
5024 | DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); | 5042 | DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); |
@@ -5480,7 +5498,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, | |||
5480 | /* determine panel color depth */ | 5498 | /* determine panel color depth */ |
5481 | temp = I915_READ(PIPECONF(pipe)); | 5499 | temp = I915_READ(PIPECONF(pipe)); |
5482 | temp &= ~PIPE_BPC_MASK; | 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 | switch (pipe_bpp) { | 5502 | switch (pipe_bpp) { |
5485 | case 18: | 5503 | case 18: |
5486 | temp |= PIPE_6BPC; | 5504 | temp |= PIPE_6BPC; |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 294f55788f0b..92b041b66e49 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -208,13 +208,15 @@ intel_dp_link_clock(uint8_t link_bw) | |||
208 | */ | 208 | */ |
209 | 209 | ||
210 | static int | 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 | struct drm_crtc *crtc = intel_dp->base.base.crtc; | 213 | struct drm_crtc *crtc = intel_dp->base.base.crtc; |
214 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 214 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
215 | int bpp = 24; | 215 | int bpp = 24; |
216 | 216 | ||
217 | if (intel_crtc) | 217 | if (check_bpp) |
218 | bpp = check_bpp; | ||
219 | else if (intel_crtc) | ||
218 | bpp = intel_crtc->bpp; | 220 | bpp = intel_crtc->bpp; |
219 | 221 | ||
220 | return (pixel_clock * bpp + 9) / 10; | 222 | return (pixel_clock * bpp + 9) / 10; |
@@ -233,6 +235,7 @@ intel_dp_mode_valid(struct drm_connector *connector, | |||
233 | struct intel_dp *intel_dp = intel_attached_dp(connector); | 235 | struct intel_dp *intel_dp = intel_attached_dp(connector); |
234 | int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp)); | 236 | int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp)); |
235 | int max_lanes = intel_dp_max_lane_count(intel_dp); | 237 | int max_lanes = intel_dp_max_lane_count(intel_dp); |
238 | int max_rate, mode_rate; | ||
236 | 239 | ||
237 | if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) { | 240 | if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) { |
238 | if (mode->hdisplay > intel_dp->panel_fixed_mode->hdisplay) | 241 | if (mode->hdisplay > intel_dp->panel_fixed_mode->hdisplay) |
@@ -242,9 +245,17 @@ intel_dp_mode_valid(struct drm_connector *connector, | |||
242 | return MODE_PANEL; | 245 | return MODE_PANEL; |
243 | } | 246 | } |
244 | 247 | ||
245 | if (intel_dp_link_required(intel_dp, mode->clock) | 248 | mode_rate = intel_dp_link_required(intel_dp, mode->clock, 0); |
246 | > intel_dp_max_data_rate(max_link_clock, max_lanes)) | 249 | max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes); |
247 | return MODE_CLOCK_HIGH; | 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 | } | ||
248 | 259 | ||
249 | if (mode->clock < 10000) | 260 | if (mode->clock < 10000) |
250 | return MODE_CLOCK_LOW; | 261 | return MODE_CLOCK_LOW; |
@@ -672,6 +683,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
672 | int lane_count, clock; | 683 | int lane_count, clock; |
673 | int max_lane_count = intel_dp_max_lane_count(intel_dp); | 684 | int max_lane_count = intel_dp_max_lane_count(intel_dp); |
674 | int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 0; | 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 | static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 }; | 687 | static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 }; |
676 | 688 | ||
677 | if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) { | 689 | if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) { |
@@ -689,7 +701,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
689 | for (clock = 0; clock <= max_clock; clock++) { | 701 | for (clock = 0; clock <= max_clock; clock++) { |
690 | int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); | 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 | <= link_avail) { | 705 | <= link_avail) { |
694 | intel_dp->link_bw = bws[clock]; | 706 | intel_dp->link_bw = bws[clock]; |
695 | intel_dp->lane_count = lane_count; | 707 | intel_dp->lane_count = lane_count; |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index bd9a604b73da..a1b4343814e8 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -110,6 +110,7 @@ | |||
110 | /* drm_display_mode->private_flags */ | 110 | /* drm_display_mode->private_flags */ |
111 | #define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0) | 111 | #define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0) |
112 | #define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT) | 112 | #define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT) |
113 | #define INTEL_MODE_DP_FORCE_6BPC (0x10) | ||
113 | 114 | ||
114 | static inline void | 115 | static inline void |
115 | intel_mode_set_pixel_multiplier(struct drm_display_mode *mode, | 116 | intel_mode_set_pixel_multiplier(struct drm_display_mode *mode, |