Skip to content

Commit 86d3efc

Browse files
vsyrjaladanvet
authored andcommitted
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>
1 parent ac4199e commit 86d3efc

File tree

3 files changed

+124
-2
lines changed

3 files changed

+124
-2
lines changed

drivers/gpu/drm/i915/i915_reg.h

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2949,6 +2949,7 @@
29492949
#define CURSOR_ENABLE 0x80000000
29502950
#define CURSOR_GAMMA_ENABLE 0x40000000
29512951
#define CURSOR_STRIDE_MASK 0x30000000
2952+
#define CURSOR_PIPE_CSC_ENABLE (1<<24)
29522953
#define CURSOR_FORMAT_SHIFT 24
29532954
#define CURSOR_FORMAT_MASK (0x07 << CURSOR_FORMAT_SHIFT)
29542955
#define CURSOR_FORMAT_2C (0x00 << CURSOR_FORMAT_SHIFT)
@@ -3010,6 +3011,7 @@
30103011
#define DISPPLANE_RGBA888 (0xf<<26)
30113012
#define DISPPLANE_STEREO_ENABLE (1<<25)
30123013
#define DISPPLANE_STEREO_DISABLE 0
3014+
#define DISPPLANE_PIPE_CSC_ENABLE (1<<24)
30133015
#define DISPPLANE_SEL_PIPE_SHIFT 24
30143016
#define DISPPLANE_SEL_PIPE_MASK (3<<DISPPLANE_SEL_PIPE_SHIFT)
30153017
#define DISPPLANE_SEL_PIPE_A 0
@@ -3098,6 +3100,7 @@
30983100
#define DVS_FORMAT_RGBX101010 (1<<25)
30993101
#define DVS_FORMAT_RGBX888 (2<<25)
31003102
#define DVS_FORMAT_RGBX161616 (3<<25)
3103+
#define DVS_PIPE_CSC_ENABLE (1<<24)
31013104
#define DVS_SOURCE_KEY (1<<22)
31023105
#define DVS_RGB_ORDER_XBGR (1<<20)
31033106
#define DVS_YUV_BYTE_ORDER_MASK (3<<16)
@@ -3165,7 +3168,7 @@
31653168
#define SPRITE_FORMAT_RGBX161616 (3<<25)
31663169
#define SPRITE_FORMAT_YUV444 (4<<25)
31673170
#define SPRITE_FORMAT_XR_BGR101010 (5<<25) /* Extended range */
3168-
#define SPRITE_CSC_ENABLE (1<<24)
3171+
#define SPRITE_PIPE_CSC_ENABLE (1<<24)
31693172
#define SPRITE_SOURCE_KEY (1<<22)
31703173
#define SPRITE_RGB_ORDER_RGBX (1<<20) /* only for 888 and 161616 */
31713174
#define SPRITE_YUV_TO_RGB_CSC_DISABLE (1<<19)
@@ -4645,4 +4648,51 @@
46454648
#define WM_DBG_DISALLOW_MAXFIFO (1<<1)
46464649
#define WM_DBG_DISALLOW_SPRITE (1<<2)
46474650

4651+
/* pipe CSC */
4652+
#define _PIPE_A_CSC_COEFF_RY_GY 0x49010
4653+
#define _PIPE_A_CSC_COEFF_BY 0x49014
4654+
#define _PIPE_A_CSC_COEFF_RU_GU 0x49018
4655+
#define _PIPE_A_CSC_COEFF_BU 0x4901c
4656+
#define _PIPE_A_CSC_COEFF_RV_GV 0x49020
4657+
#define _PIPE_A_CSC_COEFF_BV 0x49024
4658+
#define _PIPE_A_CSC_MODE 0x49028
4659+
#define _PIPE_A_CSC_PREOFF_HI 0x49030
4660+
#define _PIPE_A_CSC_PREOFF_ME 0x49034
4661+
#define _PIPE_A_CSC_PREOFF_LO 0x49038
4662+
#define _PIPE_A_CSC_POSTOFF_HI 0x49040
4663+
#define _PIPE_A_CSC_POSTOFF_ME 0x49044
4664+
#define _PIPE_A_CSC_POSTOFF_LO 0x49048
4665+
4666+
#define _PIPE_B_CSC_COEFF_RY_GY 0x49110
4667+
#define _PIPE_B_CSC_COEFF_BY 0x49114
4668+
#define _PIPE_B_CSC_COEFF_RU_GU 0x49118
4669+
#define _PIPE_B_CSC_COEFF_BU 0x4911c
4670+
#define _PIPE_B_CSC_COEFF_RV_GV 0x49120
4671+
#define _PIPE_B_CSC_COEFF_BV 0x49124
4672+
#define _PIPE_B_CSC_MODE 0x49128
4673+
#define _PIPE_B_CSC_PREOFF_HI 0x49130
4674+
#define _PIPE_B_CSC_PREOFF_ME 0x49134
4675+
#define _PIPE_B_CSC_PREOFF_LO 0x49138
4676+
#define _PIPE_B_CSC_POSTOFF_HI 0x49140
4677+
#define _PIPE_B_CSC_POSTOFF_ME 0x49144
4678+
#define _PIPE_B_CSC_POSTOFF_LO 0x49148
4679+
4680+
#define CSC_BLACK_SCREEN_OFFSET (1 << 2)
4681+
#define CSC_POSITION_BEFORE_GAMMA (1 << 1)
4682+
#define CSC_MODE_YUV_TO_RGB (1 << 0)
4683+
4684+
#define PIPE_CSC_COEFF_RY_GY(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_RY_GY, _PIPE_B_CSC_COEFF_RY_GY)
4685+
#define PIPE_CSC_COEFF_BY(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_BY, _PIPE_B_CSC_COEFF_BY)
4686+
#define PIPE_CSC_COEFF_RU_GU(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_RU_GU, _PIPE_B_CSC_COEFF_RU_GU)
4687+
#define PIPE_CSC_COEFF_BU(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_BU, _PIPE_B_CSC_COEFF_BU)
4688+
#define PIPE_CSC_COEFF_RV_GV(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_RV_GV, _PIPE_B_CSC_COEFF_RV_GV)
4689+
#define PIPE_CSC_COEFF_BV(pipe) _PIPE(pipe, _PIPE_A_CSC_COEFF_BV, _PIPE_B_CSC_COEFF_BV)
4690+
#define PIPE_CSC_MODE(pipe) _PIPE(pipe, _PIPE_A_CSC_MODE, _PIPE_B_CSC_MODE)
4691+
#define PIPE_CSC_PREOFF_HI(pipe) _PIPE(pipe, _PIPE_A_CSC_PREOFF_HI, _PIPE_B_CSC_PREOFF_HI)
4692+
#define PIPE_CSC_PREOFF_ME(pipe) _PIPE(pipe, _PIPE_A_CSC_PREOFF_ME, _PIPE_B_CSC_PREOFF_ME)
4693+
#define PIPE_CSC_PREOFF_LO(pipe) _PIPE(pipe, _PIPE_A_CSC_PREOFF_LO, _PIPE_B_CSC_PREOFF_LO)
4694+
#define PIPE_CSC_POSTOFF_HI(pipe) _PIPE(pipe, _PIPE_A_CSC_POSTOFF_HI, _PIPE_B_CSC_POSTOFF_HI)
4695+
#define PIPE_CSC_POSTOFF_ME(pipe) _PIPE(pipe, _PIPE_A_CSC_POSTOFF_ME, _PIPE_B_CSC_POSTOFF_ME)
4696+
#define PIPE_CSC_POSTOFF_LO(pipe) _PIPE(pipe, _PIPE_A_CSC_POSTOFF_LO, _PIPE_B_CSC_POSTOFF_LO)
4697+
46484698
#endif /* _I915_REG_H_ */

drivers/gpu/drm/i915/intel_display.c

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5126,6 +5126,71 @@ static void ironlake_set_pipeconf(struct drm_crtc *crtc,
51265126
POSTING_READ(PIPECONF(pipe));
51275127
}
51285128

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+
*/
5136+
static 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+
51295194
static void haswell_set_pipeconf(struct drm_crtc *crtc,
51305195
struct drm_display_mode *adjusted_mode,
51315196
bool dither)
@@ -5714,8 +5779,10 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
57145779

57155780
haswell_set_pipeconf(crtc, adjusted_mode, dither);
57165781

5782+
intel_set_pipe_csc(crtc, adjusted_mode);
5783+
57175784
/* 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);
57195786
POSTING_READ(DSPCNTR(plane));
57205787

57215788
ret = intel_pipe_set_base(crtc, x, y, fb);
@@ -6120,6 +6187,8 @@ static void ivb_update_cursor(struct drm_crtc *crtc, u32 base)
61206187
cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
61216188
cntl |= CURSOR_MODE_DISABLE;
61226189
}
6190+
if (IS_HASWELL(dev))
6191+
cntl |= CURSOR_PIPE_CSC_ENABLE;
61236192
I915_WRITE(CURCNTR_IVB(pipe), cntl);
61246193

61256194
intel_crtc->cursor_visible = visible;

drivers/gpu/drm/i915/intel_sprite.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
9090
sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
9191
sprctl |= SPRITE_ENABLE;
9292

93+
if (IS_HASWELL(dev))
94+
sprctl |= SPRITE_PIPE_CSC_ENABLE;
95+
9396
/* Sizes are 0 based */
9497
src_w--;
9598
src_h--;

0 commit comments

Comments
 (0)