diff options
| -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, |
