aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_display.c
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2013-01-18 12:11:38 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-02-19 18:21:49 -0500
commit86d3efce2c37d3fb98f75f56f21e6ab75c745bb6 (patch)
tree3af18f73d13ca0a380dd4c9b71f58f447a4d14da /drivers/gpu/drm/i915/intel_display.c
parentac4199e0f047546aa40172785e26c82b54bbe811 (diff)
drm/i915: Implement pipe CSC based limited range RGB output
HSW no longer has the PIPECONF bit for limited range RGB output. Instead the pipe CSC unit must be used to perform that task. The CSC pre offset are set to 0, since the incoming data is full [0:255] range RGB, the coefficients are programmed to compress the data into [0:219] range, and then we use either the CSC_MODE black screen offset bit, or the CSC post offsets to shift the data to the correct [16:235] range. Also have to change the confiuration of all planes so that the data is sent through the pipe CSC unit. For simplicity send the plane data through the pipe CSC unit always, and in case full range output is requested, the pipe CSC unit is set up with an identity transform to pass the plane data through unchanged. I've been told by some hardware people that the use of the pipe CSC unit shouldn't result in any measurable increase in power consumption numbers. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c71
1 files changed, 70 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index ba1d9131a5d6..6eb3882ba9bf 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5126,6 +5126,71 @@ static void ironlake_set_pipeconf(struct drm_crtc *crtc,
5126 POSTING_READ(PIPECONF(pipe)); 5126 POSTING_READ(PIPECONF(pipe));
5127} 5127}
5128 5128
5129/*
5130 * Set up the pipe CSC unit.
5131 *
5132 * Currently only full range RGB to limited range RGB conversion
5133 * is supported, but eventually this should handle various
5134 * RGB<->YCbCr scenarios as well.
5135 */
5136static void intel_set_pipe_csc(struct drm_crtc *crtc,
5137 const struct drm_display_mode *adjusted_mode)
5138{
5139 struct drm_device *dev = crtc->dev;
5140 struct drm_i915_private *dev_priv = dev->dev_private;
5141 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
5142 int pipe = intel_crtc->pipe;
5143 uint16_t coeff = 0x7800; /* 1.0 */
5144
5145 /*
5146 * TODO: Check what kind of values actually come out of the pipe
5147 * with these coeff/postoff values and adjust to get the best
5148 * accuracy. Perhaps we even need to take the bpc value into
5149 * consideration.
5150 */
5151
5152 if (adjusted_mode->private_flags & INTEL_MODE_LIMITED_COLOR_RANGE)
5153 coeff = ((235 - 16) * (1 << 12) / 255) & 0xff8; /* 0.xxx... */
5154
5155 /*
5156 * GY/GU and RY/RU should be the other way around according
5157 * to BSpec, but reality doesn't agree. Just set them up in
5158 * a way that results in the correct picture.
5159 */
5160 I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), coeff << 16);
5161 I915_WRITE(PIPE_CSC_COEFF_BY(pipe), 0);
5162
5163 I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), coeff);
5164 I915_WRITE(PIPE_CSC_COEFF_BU(pipe), 0);
5165
5166 I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), 0);
5167 I915_WRITE(PIPE_CSC_COEFF_BV(pipe), coeff << 16);
5168
5169 I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), 0);
5170 I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0);
5171 I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), 0);
5172
5173 if (INTEL_INFO(dev)->gen > 6) {
5174 uint16_t postoff = 0;
5175
5176 if (adjusted_mode->private_flags & INTEL_MODE_LIMITED_COLOR_RANGE)
5177 postoff = (16 * (1 << 13) / 255) & 0x1fff;
5178
5179 I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff);
5180 I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), postoff);
5181 I915_WRITE(PIPE_CSC_POSTOFF_LO(pipe), postoff);
5182
5183 I915_WRITE(PIPE_CSC_MODE(pipe), 0);
5184 } else {
5185 uint32_t mode = CSC_MODE_YUV_TO_RGB;
5186
5187 if (adjusted_mode->private_flags & INTEL_MODE_LIMITED_COLOR_RANGE)
5188 mode |= CSC_BLACK_SCREEN_OFFSET;
5189
5190 I915_WRITE(PIPE_CSC_MODE(pipe), mode);
5191 }
5192}
5193
5129static void haswell_set_pipeconf(struct drm_crtc *crtc, 5194static void haswell_set_pipeconf(struct drm_crtc *crtc,
5130 struct drm_display_mode *adjusted_mode, 5195 struct drm_display_mode *adjusted_mode,
5131 bool dither) 5196 bool dither)
@@ -5714,8 +5779,10 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
5714 5779
5715 haswell_set_pipeconf(crtc, adjusted_mode, dither); 5780 haswell_set_pipeconf(crtc, adjusted_mode, dither);
5716 5781
5782 intel_set_pipe_csc(crtc, adjusted_mode);
5783
5717 /* Set up the display plane register */ 5784 /* Set up the display plane register */
5718 I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE); 5785 I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE | DISPPLANE_PIPE_CSC_ENABLE);
5719 POSTING_READ(DSPCNTR(plane)); 5786 POSTING_READ(DSPCNTR(plane));
5720 5787
5721 ret = intel_pipe_set_base(crtc, x, y, fb); 5788 ret = intel_pipe_set_base(crtc, x, y, fb);
@@ -6120,6 +6187,8 @@ static void ivb_update_cursor(struct drm_crtc *crtc, u32 base)
6120 cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE); 6187 cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
6121 cntl |= CURSOR_MODE_DISABLE; 6188 cntl |= CURSOR_MODE_DISABLE;
6122 } 6189 }
6190 if (IS_HASWELL(dev))
6191 cntl |= CURSOR_PIPE_CSC_ENABLE;
6123 I915_WRITE(CURCNTR_IVB(pipe), cntl); 6192 I915_WRITE(CURCNTR_IVB(pipe), cntl);
6124 6193
6125 intel_crtc->cursor_visible = visible; 6194 intel_crtc->cursor_visible = visible;