2 * Copyright © 2016 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
25 #include "intel_drv.h"
27 #define CTM_COEFF_SIGN (1ULL << 63)
29 #define CTM_COEFF_1_0 (1ULL << 32)
30 #define CTM_COEFF_2_0 (CTM_COEFF_1_0 << 1)
31 #define CTM_COEFF_4_0 (CTM_COEFF_2_0 << 1)
32 #define CTM_COEFF_8_0 (CTM_COEFF_4_0 << 1)
33 #define CTM_COEFF_0_5 (CTM_COEFF_1_0 >> 1)
34 #define CTM_COEFF_0_25 (CTM_COEFF_0_5 >> 1)
35 #define CTM_COEFF_0_125 (CTM_COEFF_0_25 >> 1)
37 #define CTM_COEFF_LIMITED_RANGE ((235ULL - 16ULL) * CTM_COEFF_1_0 / 255)
39 #define CTM_COEFF_NEGATIVE(coeff) (((coeff) & CTM_COEFF_SIGN) != 0)
40 #define CTM_COEFF_ABS(coeff) ((coeff) & (CTM_COEFF_SIGN - 1))
42 #define LEGACY_LUT_LENGTH 256
44 /* Post offset values for RGB->YCBCR conversion */
45 #define POSTOFF_RGB_TO_YUV_HI 0x800
46 #define POSTOFF_RGB_TO_YUV_ME 0x100
47 #define POSTOFF_RGB_TO_YUV_LO 0x800
50 * These values are direct register values specified in the Bspec,
51 * for RGB->YUV conversion matrix (colorspace BT709)
53 #define CSC_RGB_TO_YUV_RU_GU 0x2ba809d8
54 #define CSC_RGB_TO_YUV_BU 0x37e80000
55 #define CSC_RGB_TO_YUV_RY_GY 0x1e089cc0
56 #define CSC_RGB_TO_YUV_BY 0xb5280000
57 #define CSC_RGB_TO_YUV_RV_GV 0xbce89ad8
58 #define CSC_RGB_TO_YUV_BV 0x1e080000
61 * Extract the CSC coefficient from a CTM coefficient (in U32.32 fixed point
62 * format). This macro takes the coefficient we want transformed and the
63 * number of fractional bits.
65 * We only have a 9 bits precision window which slides depending on the value
66 * of the CTM coefficient and we write the value from bit 3. We also round the
69 #define ILK_CSC_COEFF_FP(coeff, fbits) \
70 (clamp_val(((coeff) >> (32 - (fbits) - 3)) + 4, 0, 0xfff) & 0xff8)
72 #define ILK_CSC_COEFF_LIMITED_RANGE \
73 ILK_CSC_COEFF_FP(CTM_COEFF_LIMITED_RANGE, 9)
74 #define ILK_CSC_COEFF_1_0 \
75 ((7 << 12) | ILK_CSC_COEFF_FP(CTM_COEFF_1_0, 8))
77 static bool lut_is_legacy(const struct drm_property_blob *lut)
79 return drm_color_lut_size(lut) == LEGACY_LUT_LENGTH;
82 static bool crtc_state_is_legacy_gamma(const struct intel_crtc_state *crtc_state)
84 return !crtc_state->base.degamma_lut &&
85 !crtc_state->base.ctm &&
86 crtc_state->base.gamma_lut &&
87 lut_is_legacy(crtc_state->base.gamma_lut);
91 * When using limited range, multiply the matrix given by userspace by
92 * the matrix that we would use for the limited range.
94 static u64 *ctm_mult_by_limited(u64 *result, const u64 *input)
98 for (i = 0; i < 9; i++) {
99 u64 user_coeff = input[i];
100 u32 limited_coeff = CTM_COEFF_LIMITED_RANGE;
101 u32 abs_coeff = clamp_val(CTM_COEFF_ABS(user_coeff), 0,
102 CTM_COEFF_4_0 - 1) >> 2;
105 * By scaling every co-efficient with limited range (16-235)
106 * vs full range (0-255) the final o/p will be scaled down to
107 * fit in the limited range supported by the panel.
109 result[i] = mul_u32_u32(limited_coeff, abs_coeff) >> 30;
110 result[i] |= user_coeff & CTM_COEFF_SIGN;
116 static void ilk_load_ycbcr_conversion_matrix(struct intel_crtc *crtc)
118 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
119 enum pipe pipe = crtc->pipe;
121 I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), 0);
122 I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0);
123 I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), 0);
125 I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), CSC_RGB_TO_YUV_RU_GU);
126 I915_WRITE(PIPE_CSC_COEFF_BU(pipe), CSC_RGB_TO_YUV_BU);
128 I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), CSC_RGB_TO_YUV_RY_GY);
129 I915_WRITE(PIPE_CSC_COEFF_BY(pipe), CSC_RGB_TO_YUV_BY);
131 I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), CSC_RGB_TO_YUV_RV_GV);
132 I915_WRITE(PIPE_CSC_COEFF_BV(pipe), CSC_RGB_TO_YUV_BV);
134 I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), POSTOFF_RGB_TO_YUV_HI);
135 I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), POSTOFF_RGB_TO_YUV_ME);
136 I915_WRITE(PIPE_CSC_POSTOFF_LO(pipe), POSTOFF_RGB_TO_YUV_LO);
137 I915_WRITE(PIPE_CSC_MODE(pipe), 0);
140 static void ilk_load_csc_matrix(const struct intel_crtc_state *crtc_state)
142 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
143 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
144 bool limited_color_range = false;
145 enum pipe pipe = crtc->pipe;
150 * FIXME if there's a gamma LUT after the CSC, we should
151 * do the range compression using the gamma LUT instead.
153 if (INTEL_GEN(dev_priv) >= 8 || IS_HASWELL(dev_priv))
154 limited_color_range = crtc_state->limited_color_range;
156 if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ||
157 crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444) {
158 ilk_load_ycbcr_conversion_matrix(crtc);
160 } else if (crtc_state->base.ctm) {
161 struct drm_color_ctm *ctm = crtc_state->base.ctm->data;
165 if (limited_color_range)
166 input = ctm_mult_by_limited(temp, ctm->matrix);
171 * Convert fixed point S31.32 input to format supported by the
174 for (i = 0; i < ARRAY_SIZE(coeffs); i++) {
175 u64 abs_coeff = ((1ULL << 63) - 1) & input[i];
178 * Clamp input value to min/max supported by
181 abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_4_0 - 1);
184 if (CTM_COEFF_NEGATIVE(input[i]))
185 coeffs[i] |= 1 << 15;
187 if (abs_coeff < CTM_COEFF_0_125)
188 coeffs[i] |= (3 << 12) |
189 ILK_CSC_COEFF_FP(abs_coeff, 12);
190 else if (abs_coeff < CTM_COEFF_0_25)
191 coeffs[i] |= (2 << 12) |
192 ILK_CSC_COEFF_FP(abs_coeff, 11);
193 else if (abs_coeff < CTM_COEFF_0_5)
194 coeffs[i] |= (1 << 12) |
195 ILK_CSC_COEFF_FP(abs_coeff, 10);
196 else if (abs_coeff < CTM_COEFF_1_0)
197 coeffs[i] |= ILK_CSC_COEFF_FP(abs_coeff, 9);
198 else if (abs_coeff < CTM_COEFF_2_0)
199 coeffs[i] |= (7 << 12) |
200 ILK_CSC_COEFF_FP(abs_coeff, 8);
202 coeffs[i] |= (6 << 12) |
203 ILK_CSC_COEFF_FP(abs_coeff, 7);
207 * Load an identity matrix if no coefficients are provided.
209 * TODO: Check what kind of values actually come out of the
210 * pipe with these coeff/postoff values and adjust to get the
211 * best accuracy. Perhaps we even need to take the bpc value
212 * into consideration.
214 for (i = 0; i < 3; i++) {
215 if (limited_color_range)
217 ILK_CSC_COEFF_LIMITED_RANGE;
219 coeffs[i * 3 + i] = ILK_CSC_COEFF_1_0;
223 I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), coeffs[0] << 16 | coeffs[1]);
224 I915_WRITE(PIPE_CSC_COEFF_BY(pipe), coeffs[2] << 16);
226 I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), coeffs[3] << 16 | coeffs[4]);
227 I915_WRITE(PIPE_CSC_COEFF_BU(pipe), coeffs[5] << 16);
229 I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), coeffs[6] << 16 | coeffs[7]);
230 I915_WRITE(PIPE_CSC_COEFF_BV(pipe), coeffs[8] << 16);
232 I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), 0);
233 I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0);
234 I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), 0);
236 if (INTEL_GEN(dev_priv) > 6) {
239 if (limited_color_range)
240 postoff = (16 * (1 << 12) / 255) & 0x1fff;
242 I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff);
243 I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), postoff);
244 I915_WRITE(PIPE_CSC_POSTOFF_LO(pipe), postoff);
246 I915_WRITE(PIPE_CSC_MODE(pipe), 0);
248 u32 mode = CSC_MODE_YUV_TO_RGB;
250 if (limited_color_range)
251 mode |= CSC_BLACK_SCREEN_OFFSET;
253 I915_WRITE(PIPE_CSC_MODE(pipe), mode);
258 * Set up the pipe CSC unit on CherryView.
260 static void cherryview_load_csc_matrix(const struct intel_crtc_state *crtc_state)
262 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
263 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
264 enum pipe pipe = crtc->pipe;
267 if (crtc_state->base.ctm) {
268 const struct drm_color_ctm *ctm = crtc_state->base.ctm->data;
272 for (i = 0; i < ARRAY_SIZE(coeffs); i++) {
274 ((1ULL << 63) - 1) & ctm->matrix[i];
276 /* Round coefficient. */
277 abs_coeff += 1 << (32 - 13);
278 /* Clamp to hardware limits. */
279 abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_8_0 - 1);
281 /* Write coefficients in S3.12 format. */
282 if (ctm->matrix[i] & (1ULL << 63))
284 coeffs[i] |= ((abs_coeff >> 32) & 7) << 12;
285 coeffs[i] |= (abs_coeff >> 20) & 0xfff;
288 I915_WRITE(CGM_PIPE_CSC_COEFF01(pipe),
289 coeffs[1] << 16 | coeffs[0]);
290 I915_WRITE(CGM_PIPE_CSC_COEFF23(pipe),
291 coeffs[3] << 16 | coeffs[2]);
292 I915_WRITE(CGM_PIPE_CSC_COEFF45(pipe),
293 coeffs[5] << 16 | coeffs[4]);
294 I915_WRITE(CGM_PIPE_CSC_COEFF67(pipe),
295 coeffs[7] << 16 | coeffs[6]);
296 I915_WRITE(CGM_PIPE_CSC_COEFF8(pipe), coeffs[8]);
299 mode = (crtc_state->base.ctm ? CGM_PIPE_MODE_CSC : 0);
300 if (!crtc_state_is_legacy_gamma(crtc_state)) {
301 mode |= (crtc_state->base.degamma_lut ? CGM_PIPE_MODE_DEGAMMA : 0) |
302 (crtc_state->base.gamma_lut ? CGM_PIPE_MODE_GAMMA : 0);
304 I915_WRITE(CGM_PIPE_MODE(pipe), mode);
307 /* Loads the legacy palette/gamma unit for the CRTC. */
308 static void i9xx_load_luts_internal(const struct intel_crtc_state *crtc_state,
309 const struct drm_property_blob *blob)
311 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
312 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
313 enum pipe pipe = crtc->pipe;
316 if (HAS_GMCH(dev_priv)) {
317 if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI))
318 assert_dsi_pll_enabled(dev_priv);
320 assert_pll_enabled(dev_priv, pipe);
324 const struct drm_color_lut *lut = blob->data;
326 for (i = 0; i < 256; i++) {
328 (drm_color_lut_extract(lut[i].red, 8) << 16) |
329 (drm_color_lut_extract(lut[i].green, 8) << 8) |
330 drm_color_lut_extract(lut[i].blue, 8);
332 if (HAS_GMCH(dev_priv))
333 I915_WRITE(PALETTE(pipe, i), word);
335 I915_WRITE(LGC_PALETTE(pipe, i), word);
338 for (i = 0; i < 256; i++) {
339 u32 word = (i << 16) | (i << 8) | i;
341 if (HAS_GMCH(dev_priv))
342 I915_WRITE(PALETTE(pipe, i), word);
344 I915_WRITE(LGC_PALETTE(pipe, i), word);
349 static void i9xx_load_luts(const struct intel_crtc_state *crtc_state)
351 i9xx_load_luts_internal(crtc_state, crtc_state->base.gamma_lut);
354 static void i9xx_color_commit(const struct intel_crtc_state *crtc_state)
356 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
357 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
358 enum pipe pipe = crtc->pipe;
361 val = I915_READ(PIPECONF(pipe));
362 val &= ~PIPECONF_GAMMA_MODE_MASK_I9XX;
363 val |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);
364 I915_WRITE(PIPECONF(pipe), val);
367 static void ilk_color_commit(const struct intel_crtc_state *crtc_state)
369 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
370 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
371 enum pipe pipe = crtc->pipe;
374 val = I915_READ(PIPECONF(pipe));
375 val &= ~PIPECONF_GAMMA_MODE_MASK_ILK;
376 val |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);
377 I915_WRITE(PIPECONF(pipe), val);
380 static void hsw_color_commit(const struct intel_crtc_state *crtc_state)
382 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
383 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
385 I915_WRITE(GAMMA_MODE(crtc->pipe), crtc_state->gamma_mode);
387 ilk_load_csc_matrix(crtc_state);
390 static void skl_color_commit(const struct intel_crtc_state *crtc_state)
392 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
393 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
394 enum pipe pipe = crtc->pipe;
398 * We don't (yet) allow userspace to control the pipe background color,
399 * so force it to black, but apply pipe gamma and CSC appropriately
400 * so that its handling will match how we program our planes.
402 if (crtc_state->gamma_enable)
403 val |= SKL_BOTTOM_COLOR_GAMMA_ENABLE;
404 if (crtc_state->csc_enable)
405 val |= SKL_BOTTOM_COLOR_CSC_ENABLE;
406 I915_WRITE(SKL_BOTTOM_COLOR(pipe), val);
408 I915_WRITE(GAMMA_MODE(crtc->pipe), crtc_state->gamma_mode);
410 ilk_load_csc_matrix(crtc_state);
413 static void bdw_load_degamma_lut(const struct intel_crtc_state *crtc_state)
415 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
416 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
417 const struct drm_property_blob *degamma_lut = crtc_state->base.degamma_lut;
418 u32 i, lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
419 enum pipe pipe = crtc->pipe;
421 I915_WRITE(PREC_PAL_INDEX(pipe),
422 PAL_PREC_SPLIT_MODE | PAL_PREC_AUTO_INCREMENT);
425 const struct drm_color_lut *lut = degamma_lut->data;
427 for (i = 0; i < lut_size; i++) {
429 drm_color_lut_extract(lut[i].red, 10) << 20 |
430 drm_color_lut_extract(lut[i].green, 10) << 10 |
431 drm_color_lut_extract(lut[i].blue, 10);
433 I915_WRITE(PREC_PAL_DATA(pipe), word);
436 for (i = 0; i < lut_size; i++) {
437 u32 v = (i * ((1 << 10) - 1)) / (lut_size - 1);
439 I915_WRITE(PREC_PAL_DATA(pipe),
440 (v << 20) | (v << 10) | v);
445 static void bdw_load_gamma_lut(const struct intel_crtc_state *crtc_state, u32 offset)
447 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
448 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
449 const struct drm_property_blob *gamma_lut = crtc_state->base.gamma_lut;
450 u32 i, lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
451 enum pipe pipe = crtc->pipe;
453 WARN_ON(offset & ~PAL_PREC_INDEX_VALUE_MASK);
455 I915_WRITE(PREC_PAL_INDEX(pipe),
456 (offset ? PAL_PREC_SPLIT_MODE : 0) |
457 PAL_PREC_AUTO_INCREMENT |
461 const struct drm_color_lut *lut = gamma_lut->data;
463 for (i = 0; i < lut_size; i++) {
465 (drm_color_lut_extract(lut[i].red, 10) << 20) |
466 (drm_color_lut_extract(lut[i].green, 10) << 10) |
467 drm_color_lut_extract(lut[i].blue, 10);
469 I915_WRITE(PREC_PAL_DATA(pipe), word);
472 /* Program the max register to clamp values > 1.0. */
474 I915_WRITE(PREC_PAL_GC_MAX(pipe, 0),
475 drm_color_lut_extract(lut[i].red, 16));
476 I915_WRITE(PREC_PAL_GC_MAX(pipe, 1),
477 drm_color_lut_extract(lut[i].green, 16));
478 I915_WRITE(PREC_PAL_GC_MAX(pipe, 2),
479 drm_color_lut_extract(lut[i].blue, 16));
481 for (i = 0; i < lut_size; i++) {
482 u32 v = (i * ((1 << 10) - 1)) / (lut_size - 1);
484 I915_WRITE(PREC_PAL_DATA(pipe),
485 (v << 20) | (v << 10) | v);
488 I915_WRITE(PREC_PAL_GC_MAX(pipe, 0), (1 << 16) - 1);
489 I915_WRITE(PREC_PAL_GC_MAX(pipe, 1), (1 << 16) - 1);
490 I915_WRITE(PREC_PAL_GC_MAX(pipe, 2), (1 << 16) - 1);
494 * Reset the index, otherwise it prevents the legacy palette to be
497 I915_WRITE(PREC_PAL_INDEX(pipe), 0);
500 /* Loads the palette/gamma unit for the CRTC on Broadwell+. */
501 static void broadwell_load_luts(const struct intel_crtc_state *crtc_state)
503 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
504 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
506 if (crtc_state_is_legacy_gamma(crtc_state)) {
507 i9xx_load_luts(crtc_state);
509 bdw_load_degamma_lut(crtc_state);
510 bdw_load_gamma_lut(crtc_state,
511 INTEL_INFO(dev_priv)->color.degamma_lut_size);
515 static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state)
517 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
518 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
519 enum pipe pipe = crtc->pipe;
520 const u32 lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
524 * When setting the auto-increment bit, the hardware seems to
525 * ignore the index bits, so we need to reset it to index 0
528 I915_WRITE(PRE_CSC_GAMC_INDEX(pipe), 0);
529 I915_WRITE(PRE_CSC_GAMC_INDEX(pipe), PRE_CSC_GAMC_AUTO_INCREMENT);
531 if (crtc_state->base.degamma_lut) {
532 struct drm_color_lut *lut = crtc_state->base.degamma_lut->data;
534 for (i = 0; i < lut_size; i++) {
536 * First 33 entries represent range from 0 to 1.0
537 * 34th and 35th entry will represent extended range
538 * inputs 3.0 and 7.0 respectively, currently clamped
539 * at 1.0. Since the precision is 16bit, the user
540 * value can be directly filled to register.
541 * The pipe degamma table in GLK+ onwards doesn't
542 * support different values per channel, so this just
543 * programs green value which will be equal to Red and
544 * Blue into the lut registers.
545 * ToDo: Extend to max 7.0. Enable 32 bit input value
546 * as compared to just 16 to achieve this.
548 I915_WRITE(PRE_CSC_GAMC_DATA(pipe), lut[i].green);
551 /* load a linear table. */
552 for (i = 0; i < lut_size; i++) {
553 u32 v = (i * (1 << 16)) / (lut_size - 1);
555 I915_WRITE(PRE_CSC_GAMC_DATA(pipe), v);
559 /* Clamp values > 1.0. */
561 I915_WRITE(PRE_CSC_GAMC_DATA(pipe), (1 << 16));
564 static void glk_load_luts(const struct intel_crtc_state *crtc_state)
566 glk_load_degamma_lut(crtc_state);
568 if (crtc_state_is_legacy_gamma(crtc_state))
569 i9xx_load_luts(crtc_state);
571 bdw_load_gamma_lut(crtc_state, 0);
574 static void cherryview_load_luts(const struct intel_crtc_state *crtc_state)
576 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
577 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
578 const struct drm_property_blob *gamma_lut = crtc_state->base.gamma_lut;
579 const struct drm_property_blob *degamma_lut = crtc_state->base.degamma_lut;
580 enum pipe pipe = crtc->pipe;
582 cherryview_load_csc_matrix(crtc_state);
584 if (crtc_state_is_legacy_gamma(crtc_state)) {
585 i9xx_load_luts_internal(crtc_state, gamma_lut);
590 const struct drm_color_lut *lut = degamma_lut->data;
591 int i, lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
593 for (i = 0; i < lut_size; i++) {
596 /* Write LUT in U0.14 format. */
598 (drm_color_lut_extract(lut[i].green, 14) << 16) |
599 drm_color_lut_extract(lut[i].blue, 14);
600 word1 = drm_color_lut_extract(lut[i].red, 14);
602 I915_WRITE(CGM_PIPE_DEGAMMA(pipe, i, 0), word0);
603 I915_WRITE(CGM_PIPE_DEGAMMA(pipe, i, 1), word1);
608 const struct drm_color_lut *lut = gamma_lut->data;
609 int i, lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
611 for (i = 0; i < lut_size; i++) {
614 /* Write LUT in U0.10 format. */
616 (drm_color_lut_extract(lut[i].green, 10) << 16) |
617 drm_color_lut_extract(lut[i].blue, 10);
618 word1 = drm_color_lut_extract(lut[i].red, 10);
620 I915_WRITE(CGM_PIPE_GAMMA(pipe, i, 0), word0);
621 I915_WRITE(CGM_PIPE_GAMMA(pipe, i, 1), word1);
626 * Also program a linear LUT in the legacy block (behind the
629 i9xx_load_luts_internal(crtc_state, NULL);
632 void intel_color_load_luts(const struct intel_crtc_state *crtc_state)
634 struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
636 dev_priv->display.load_luts(crtc_state);
639 void intel_color_commit(const struct intel_crtc_state *crtc_state)
641 struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
643 dev_priv->display.color_commit(crtc_state);
646 static bool need_plane_update(struct intel_plane *plane,
647 const struct intel_crtc_state *crtc_state)
649 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
652 * On pre-SKL the pipe gamma enable and pipe csc enable for
653 * the pipe bottom color are configured via the primary plane.
654 * We have to reconfigure that even if the plane is inactive.
656 return crtc_state->active_planes & BIT(plane->id) ||
657 (INTEL_GEN(dev_priv) < 9 &&
658 plane->id == PLANE_PRIMARY);
662 intel_color_add_affected_planes(struct intel_crtc_state *new_crtc_state)
664 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
665 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
666 struct intel_atomic_state *state =
667 to_intel_atomic_state(new_crtc_state->base.state);
668 const struct intel_crtc_state *old_crtc_state =
669 intel_atomic_get_old_crtc_state(state, crtc);
670 struct intel_plane *plane;
672 if (!new_crtc_state->base.active ||
673 drm_atomic_crtc_needs_modeset(&new_crtc_state->base))
676 if (new_crtc_state->gamma_enable == old_crtc_state->gamma_enable &&
677 new_crtc_state->csc_enable == old_crtc_state->csc_enable)
680 for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) {
681 struct intel_plane_state *plane_state;
683 if (!need_plane_update(plane, new_crtc_state))
686 plane_state = intel_atomic_get_plane_state(state, plane);
687 if (IS_ERR(plane_state))
688 return PTR_ERR(plane_state);
690 new_crtc_state->update_planes |= BIT(plane->id);
696 static int check_lut_size(const struct drm_property_blob *lut, int expected)
703 len = drm_color_lut_size(lut);
704 if (len != expected) {
705 DRM_DEBUG_KMS("Invalid LUT size; got %d, expected %d\n",
713 int intel_color_check(struct intel_crtc_state *crtc_state)
715 struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
716 const struct drm_property_blob *gamma_lut = crtc_state->base.gamma_lut;
717 const struct drm_property_blob *degamma_lut = crtc_state->base.degamma_lut;
718 bool limited_color_range = false;
719 int gamma_length, degamma_length;
720 u32 gamma_tests, degamma_tests;
723 degamma_length = INTEL_INFO(dev_priv)->color.degamma_lut_size;
724 gamma_length = INTEL_INFO(dev_priv)->color.gamma_lut_size;
725 degamma_tests = INTEL_INFO(dev_priv)->color.degamma_lut_tests;
726 gamma_tests = INTEL_INFO(dev_priv)->color.gamma_lut_tests;
728 /* C8 needs the legacy LUT all to itself */
729 if (crtc_state->c8_planes &&
730 !crtc_state_is_legacy_gamma(crtc_state))
733 crtc_state->gamma_enable = (gamma_lut || degamma_lut) &&
734 !crtc_state->c8_planes;
736 if (INTEL_GEN(dev_priv) >= 9 ||
737 IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
738 limited_color_range = crtc_state->limited_color_range;
740 crtc_state->csc_enable =
741 crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB ||
742 crtc_state->base.ctm || limited_color_range;
744 ret = intel_color_add_affected_planes(crtc_state);
748 /* Always allow legacy gamma LUT with no further checking. */
749 if (!crtc_state->gamma_enable ||
750 crtc_state_is_legacy_gamma(crtc_state)) {
751 crtc_state->gamma_mode = GAMMA_MODE_MODE_8BIT;
755 if (check_lut_size(degamma_lut, degamma_length) ||
756 check_lut_size(gamma_lut, gamma_length))
759 if (drm_color_lut_check(degamma_lut, degamma_tests) ||
760 drm_color_lut_check(gamma_lut, gamma_tests))
763 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
764 crtc_state->gamma_mode = GAMMA_MODE_MODE_10BIT;
765 else if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
766 crtc_state->gamma_mode = GAMMA_MODE_MODE_SPLIT;
768 crtc_state->gamma_mode = GAMMA_MODE_MODE_8BIT;
773 void intel_color_init(struct intel_crtc *crtc)
775 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
777 drm_mode_crtc_set_gamma_size(&crtc->base, 256);
779 if (HAS_GMCH(dev_priv)) {
780 if (IS_CHERRYVIEW(dev_priv))
781 dev_priv->display.load_luts = cherryview_load_luts;
783 dev_priv->display.load_luts = i9xx_load_luts;
785 dev_priv->display.color_commit = i9xx_color_commit;
787 if (IS_CANNONLAKE(dev_priv) || IS_GEMINILAKE(dev_priv))
788 dev_priv->display.load_luts = glk_load_luts;
789 else if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
790 dev_priv->display.load_luts = broadwell_load_luts;
792 dev_priv->display.load_luts = i9xx_load_luts;
794 if (INTEL_GEN(dev_priv) >= 9)
795 dev_priv->display.color_commit = skl_color_commit;
796 else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
797 dev_priv->display.color_commit = hsw_color_commit;
799 dev_priv->display.color_commit = ilk_color_commit;
802 /* Enable color management support when we have degamma & gamma LUTs. */
803 if (INTEL_INFO(dev_priv)->color.degamma_lut_size != 0 &&
804 INTEL_INFO(dev_priv)->color.gamma_lut_size != 0)
805 drm_crtc_enable_color_mgmt(&crtc->base,
806 INTEL_INFO(dev_priv)->color.degamma_lut_size,
808 INTEL_INFO(dev_priv)->color.gamma_lut_size);