]> git.ipfire.org Git - thirdparty/kernel/stable.git/blob - drivers/gpu/drm/i915/intel_color.c
drm/i915: Extract bdw_color_check()
[thirdparty/kernel/stable.git] / drivers / gpu / drm / i915 / intel_color.c
1 /*
2 * Copyright © 2016 Intel Corporation
3 *
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:
10 *
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
13 * Software.
14 *
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.
22 *
23 */
24
25 #include "intel_drv.h"
26
27 #define CTM_COEFF_SIGN (1ULL << 63)
28
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)
36
37 #define CTM_COEFF_LIMITED_RANGE ((235ULL - 16ULL) * CTM_COEFF_1_0 / 255)
38
39 #define CTM_COEFF_NEGATIVE(coeff) (((coeff) & CTM_COEFF_SIGN) != 0)
40 #define CTM_COEFF_ABS(coeff) ((coeff) & (CTM_COEFF_SIGN - 1))
41
42 #define LEGACY_LUT_LENGTH 256
43 /*
44 * Extract the CSC coefficient from a CTM coefficient (in U32.32 fixed point
45 * format). This macro takes the coefficient we want transformed and the
46 * number of fractional bits.
47 *
48 * We only have a 9 bits precision window which slides depending on the value
49 * of the CTM coefficient and we write the value from bit 3. We also round the
50 * value.
51 */
52 #define ILK_CSC_COEFF_FP(coeff, fbits) \
53 (clamp_val(((coeff) >> (32 - (fbits) - 3)) + 4, 0, 0xfff) & 0xff8)
54
55 #define ILK_CSC_COEFF_LIMITED_RANGE 0x0dc0
56 #define ILK_CSC_COEFF_1_0 0x7800
57
58 #define ILK_CSC_POSTOFF_LIMITED_RANGE (16 * (1 << 12) / 255)
59
60 static const u16 ilk_csc_off_zero[3] = {};
61
62 static const u16 ilk_csc_coeff_identity[9] = {
63 ILK_CSC_COEFF_1_0, 0, 0,
64 0, ILK_CSC_COEFF_1_0, 0,
65 0, 0, ILK_CSC_COEFF_1_0,
66 };
67
68 static const u16 ilk_csc_postoff_limited_range[3] = {
69 ILK_CSC_POSTOFF_LIMITED_RANGE,
70 ILK_CSC_POSTOFF_LIMITED_RANGE,
71 ILK_CSC_POSTOFF_LIMITED_RANGE,
72 };
73
74 static const u16 ilk_csc_coeff_limited_range[9] = {
75 ILK_CSC_COEFF_LIMITED_RANGE, 0, 0,
76 0, ILK_CSC_COEFF_LIMITED_RANGE, 0,
77 0, 0, ILK_CSC_COEFF_LIMITED_RANGE,
78 };
79
80 /*
81 * These values are direct register values specified in the Bspec,
82 * for RGB->YUV conversion matrix (colorspace BT709)
83 */
84 static const u16 ilk_csc_coeff_rgb_to_ycbcr[9] = {
85 0x1e08, 0x9cc0, 0xb528,
86 0x2ba8, 0x09d8, 0x37e8,
87 0xbce8, 0x9ad8, 0x1e08,
88 };
89
90 /* Post offset values for RGB->YCBCR conversion */
91 static const u16 ilk_csc_postoff_rgb_to_ycbcr[3] = {
92 0x0800, 0x0100, 0x0800,
93 };
94
95 static bool lut_is_legacy(const struct drm_property_blob *lut)
96 {
97 return drm_color_lut_size(lut) == LEGACY_LUT_LENGTH;
98 }
99
100 static bool crtc_state_is_legacy_gamma(const struct intel_crtc_state *crtc_state)
101 {
102 return !crtc_state->base.degamma_lut &&
103 !crtc_state->base.ctm &&
104 crtc_state->base.gamma_lut &&
105 lut_is_legacy(crtc_state->base.gamma_lut);
106 }
107
108 /*
109 * When using limited range, multiply the matrix given by userspace by
110 * the matrix that we would use for the limited range.
111 */
112 static u64 *ctm_mult_by_limited(u64 *result, const u64 *input)
113 {
114 int i;
115
116 for (i = 0; i < 9; i++) {
117 u64 user_coeff = input[i];
118 u32 limited_coeff = CTM_COEFF_LIMITED_RANGE;
119 u32 abs_coeff = clamp_val(CTM_COEFF_ABS(user_coeff), 0,
120 CTM_COEFF_4_0 - 1) >> 2;
121
122 /*
123 * By scaling every co-efficient with limited range (16-235)
124 * vs full range (0-255) the final o/p will be scaled down to
125 * fit in the limited range supported by the panel.
126 */
127 result[i] = mul_u32_u32(limited_coeff, abs_coeff) >> 30;
128 result[i] |= user_coeff & CTM_COEFF_SIGN;
129 }
130
131 return result;
132 }
133
134 static void ilk_update_pipe_csc(struct intel_crtc *crtc,
135 const u16 preoff[3],
136 const u16 coeff[9],
137 const u16 postoff[3])
138 {
139 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
140 enum pipe pipe = crtc->pipe;
141
142 I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), preoff[0]);
143 I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), preoff[1]);
144 I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), preoff[2]);
145
146 I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), coeff[0] << 16 | coeff[1]);
147 I915_WRITE(PIPE_CSC_COEFF_BY(pipe), coeff[2] << 16);
148
149 I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), coeff[3] << 16 | coeff[4]);
150 I915_WRITE(PIPE_CSC_COEFF_BU(pipe), coeff[5] << 16);
151
152 I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), coeff[6] << 16 | coeff[7]);
153 I915_WRITE(PIPE_CSC_COEFF_BV(pipe), coeff[8] << 16);
154
155 if (INTEL_GEN(dev_priv) >= 7) {
156 I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff[0]);
157 I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), postoff[1]);
158 I915_WRITE(PIPE_CSC_POSTOFF_LO(pipe), postoff[2]);
159 }
160 }
161
162 static void icl_update_output_csc(struct intel_crtc *crtc,
163 const u16 preoff[3],
164 const u16 coeff[9],
165 const u16 postoff[3])
166 {
167 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
168 enum pipe pipe = crtc->pipe;
169
170 I915_WRITE(PIPE_CSC_OUTPUT_PREOFF_HI(pipe), preoff[0]);
171 I915_WRITE(PIPE_CSC_OUTPUT_PREOFF_ME(pipe), preoff[1]);
172 I915_WRITE(PIPE_CSC_OUTPUT_PREOFF_LO(pipe), preoff[2]);
173
174 I915_WRITE(PIPE_CSC_OUTPUT_COEFF_RY_GY(pipe), coeff[0] << 16 | coeff[1]);
175 I915_WRITE(PIPE_CSC_OUTPUT_COEFF_BY(pipe), coeff[2]);
176
177 I915_WRITE(PIPE_CSC_OUTPUT_COEFF_RU_GU(pipe), coeff[3] << 16 | coeff[4]);
178 I915_WRITE(PIPE_CSC_OUTPUT_COEFF_BU(pipe), coeff[5]);
179
180 I915_WRITE(PIPE_CSC_OUTPUT_COEFF_RV_GV(pipe), coeff[6] << 16 | coeff[7]);
181 I915_WRITE(PIPE_CSC_OUTPUT_COEFF_BV(pipe), coeff[8]);
182
183 I915_WRITE(PIPE_CSC_OUTPUT_POSTOFF_HI(pipe), postoff[0]);
184 I915_WRITE(PIPE_CSC_OUTPUT_POSTOFF_ME(pipe), postoff[1]);
185 I915_WRITE(PIPE_CSC_OUTPUT_POSTOFF_LO(pipe), postoff[2]);
186 }
187
188 static bool ilk_csc_limited_range(const struct intel_crtc_state *crtc_state)
189 {
190 struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
191
192 /*
193 * FIXME if there's a gamma LUT after the CSC, we should
194 * do the range compression using the gamma LUT instead.
195 */
196 return crtc_state->limited_color_range &&
197 (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv) ||
198 IS_GEN_RANGE(dev_priv, 9, 10));
199 }
200
201 static void ilk_csc_convert_ctm(const struct intel_crtc_state *crtc_state,
202 u16 coeffs[9])
203 {
204 const struct drm_color_ctm *ctm = crtc_state->base.ctm->data;
205 const u64 *input;
206 u64 temp[9];
207 int i;
208
209 if (ilk_csc_limited_range(crtc_state))
210 input = ctm_mult_by_limited(temp, ctm->matrix);
211 else
212 input = ctm->matrix;
213
214 /*
215 * Convert fixed point S31.32 input to format supported by the
216 * hardware.
217 */
218 for (i = 0; i < 9; i++) {
219 u64 abs_coeff = ((1ULL << 63) - 1) & input[i];
220
221 /*
222 * Clamp input value to min/max supported by
223 * hardware.
224 */
225 abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_4_0 - 1);
226
227 coeffs[i] = 0;
228
229 /* sign bit */
230 if (CTM_COEFF_NEGATIVE(input[i]))
231 coeffs[i] |= 1 << 15;
232
233 if (abs_coeff < CTM_COEFF_0_125)
234 coeffs[i] |= (3 << 12) |
235 ILK_CSC_COEFF_FP(abs_coeff, 12);
236 else if (abs_coeff < CTM_COEFF_0_25)
237 coeffs[i] |= (2 << 12) |
238 ILK_CSC_COEFF_FP(abs_coeff, 11);
239 else if (abs_coeff < CTM_COEFF_0_5)
240 coeffs[i] |= (1 << 12) |
241 ILK_CSC_COEFF_FP(abs_coeff, 10);
242 else if (abs_coeff < CTM_COEFF_1_0)
243 coeffs[i] |= ILK_CSC_COEFF_FP(abs_coeff, 9);
244 else if (abs_coeff < CTM_COEFF_2_0)
245 coeffs[i] |= (7 << 12) |
246 ILK_CSC_COEFF_FP(abs_coeff, 8);
247 else
248 coeffs[i] |= (6 << 12) |
249 ILK_CSC_COEFF_FP(abs_coeff, 7);
250 }
251 }
252
253 static void ilk_load_csc_matrix(const struct intel_crtc_state *crtc_state)
254 {
255 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
256 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
257 bool limited_color_range = ilk_csc_limited_range(crtc_state);
258
259 if (crtc_state->base.ctm) {
260 u16 coeff[9];
261
262 ilk_csc_convert_ctm(crtc_state, coeff);
263 ilk_update_pipe_csc(crtc, ilk_csc_off_zero, coeff,
264 limited_color_range ?
265 ilk_csc_postoff_limited_range :
266 ilk_csc_off_zero);
267 } else if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB) {
268 ilk_update_pipe_csc(crtc, ilk_csc_off_zero,
269 ilk_csc_coeff_rgb_to_ycbcr,
270 ilk_csc_postoff_rgb_to_ycbcr);
271 } else if (limited_color_range) {
272 ilk_update_pipe_csc(crtc, ilk_csc_off_zero,
273 ilk_csc_coeff_limited_range,
274 ilk_csc_postoff_limited_range);
275 } else if (crtc_state->csc_enable) {
276 ilk_update_pipe_csc(crtc, ilk_csc_off_zero,
277 ilk_csc_coeff_identity,
278 ilk_csc_off_zero);
279 }
280
281 I915_WRITE(PIPE_CSC_MODE(crtc->pipe), crtc_state->csc_mode);
282 }
283
284 static void icl_load_csc_matrix(const struct intel_crtc_state *crtc_state)
285 {
286 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
287 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
288
289 if (crtc_state->base.ctm) {
290 u16 coeff[9];
291
292 ilk_csc_convert_ctm(crtc_state, coeff);
293 ilk_update_pipe_csc(crtc, ilk_csc_off_zero,
294 coeff, ilk_csc_off_zero);
295 }
296
297 if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB) {
298 icl_update_output_csc(crtc, ilk_csc_off_zero,
299 ilk_csc_coeff_rgb_to_ycbcr,
300 ilk_csc_postoff_rgb_to_ycbcr);
301 } else if (crtc_state->limited_color_range) {
302 icl_update_output_csc(crtc, ilk_csc_off_zero,
303 ilk_csc_coeff_limited_range,
304 ilk_csc_postoff_limited_range);
305 }
306
307 I915_WRITE(PIPE_CSC_MODE(crtc->pipe), crtc_state->csc_mode);
308 }
309
310 /*
311 * Set up the pipe CSC unit on CherryView.
312 */
313 static void cherryview_load_csc_matrix(const struct intel_crtc_state *crtc_state)
314 {
315 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
316 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
317 enum pipe pipe = crtc->pipe;
318
319 if (crtc_state->base.ctm) {
320 const struct drm_color_ctm *ctm = crtc_state->base.ctm->data;
321 u16 coeffs[9] = {};
322 int i;
323
324 for (i = 0; i < ARRAY_SIZE(coeffs); i++) {
325 u64 abs_coeff =
326 ((1ULL << 63) - 1) & ctm->matrix[i];
327
328 /* Round coefficient. */
329 abs_coeff += 1 << (32 - 13);
330 /* Clamp to hardware limits. */
331 abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_8_0 - 1);
332
333 /* Write coefficients in S3.12 format. */
334 if (ctm->matrix[i] & (1ULL << 63))
335 coeffs[i] = 1 << 15;
336 coeffs[i] |= ((abs_coeff >> 32) & 7) << 12;
337 coeffs[i] |= (abs_coeff >> 20) & 0xfff;
338 }
339
340 I915_WRITE(CGM_PIPE_CSC_COEFF01(pipe),
341 coeffs[1] << 16 | coeffs[0]);
342 I915_WRITE(CGM_PIPE_CSC_COEFF23(pipe),
343 coeffs[3] << 16 | coeffs[2]);
344 I915_WRITE(CGM_PIPE_CSC_COEFF45(pipe),
345 coeffs[5] << 16 | coeffs[4]);
346 I915_WRITE(CGM_PIPE_CSC_COEFF67(pipe),
347 coeffs[7] << 16 | coeffs[6]);
348 I915_WRITE(CGM_PIPE_CSC_COEFF8(pipe), coeffs[8]);
349 }
350
351 I915_WRITE(CGM_PIPE_MODE(pipe), crtc_state->cgm_mode);
352 }
353
354 /* Loads the legacy palette/gamma unit for the CRTC. */
355 static void i9xx_load_luts_internal(const struct intel_crtc_state *crtc_state,
356 const struct drm_property_blob *blob)
357 {
358 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
359 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
360 enum pipe pipe = crtc->pipe;
361 int i;
362
363 if (HAS_GMCH(dev_priv)) {
364 if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI))
365 assert_dsi_pll_enabled(dev_priv);
366 else
367 assert_pll_enabled(dev_priv, pipe);
368 }
369
370 if (blob) {
371 const struct drm_color_lut *lut = blob->data;
372
373 for (i = 0; i < 256; i++) {
374 u32 word =
375 (drm_color_lut_extract(lut[i].red, 8) << 16) |
376 (drm_color_lut_extract(lut[i].green, 8) << 8) |
377 drm_color_lut_extract(lut[i].blue, 8);
378
379 if (HAS_GMCH(dev_priv))
380 I915_WRITE(PALETTE(pipe, i), word);
381 else
382 I915_WRITE(LGC_PALETTE(pipe, i), word);
383 }
384 } else {
385 for (i = 0; i < 256; i++) {
386 u32 word = (i << 16) | (i << 8) | i;
387
388 if (HAS_GMCH(dev_priv))
389 I915_WRITE(PALETTE(pipe, i), word);
390 else
391 I915_WRITE(LGC_PALETTE(pipe, i), word);
392 }
393 }
394 }
395
396 static void i9xx_load_luts(const struct intel_crtc_state *crtc_state)
397 {
398 i9xx_load_luts_internal(crtc_state, crtc_state->base.gamma_lut);
399 }
400
401 static void i9xx_color_commit(const struct intel_crtc_state *crtc_state)
402 {
403 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
404 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
405 enum pipe pipe = crtc->pipe;
406 u32 val;
407
408 val = I915_READ(PIPECONF(pipe));
409 val &= ~PIPECONF_GAMMA_MODE_MASK_I9XX;
410 val |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);
411 I915_WRITE(PIPECONF(pipe), val);
412 }
413
414 static void ilk_color_commit(const struct intel_crtc_state *crtc_state)
415 {
416 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
417 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
418 enum pipe pipe = crtc->pipe;
419 u32 val;
420
421 val = I915_READ(PIPECONF(pipe));
422 val &= ~PIPECONF_GAMMA_MODE_MASK_ILK;
423 val |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);
424 I915_WRITE(PIPECONF(pipe), val);
425 }
426
427 static void hsw_color_commit(const struct intel_crtc_state *crtc_state)
428 {
429 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
430 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
431
432 I915_WRITE(GAMMA_MODE(crtc->pipe), crtc_state->gamma_mode);
433
434 ilk_load_csc_matrix(crtc_state);
435 }
436
437 static void skl_color_commit(const struct intel_crtc_state *crtc_state)
438 {
439 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
440 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
441 enum pipe pipe = crtc->pipe;
442 u32 val = 0;
443
444 /*
445 * We don't (yet) allow userspace to control the pipe background color,
446 * so force it to black, but apply pipe gamma and CSC appropriately
447 * so that its handling will match how we program our planes.
448 */
449 if (crtc_state->gamma_enable)
450 val |= SKL_BOTTOM_COLOR_GAMMA_ENABLE;
451 if (crtc_state->csc_enable)
452 val |= SKL_BOTTOM_COLOR_CSC_ENABLE;
453 I915_WRITE(SKL_BOTTOM_COLOR(pipe), val);
454
455 I915_WRITE(GAMMA_MODE(crtc->pipe), crtc_state->gamma_mode);
456
457 if (INTEL_GEN(dev_priv) >= 11)
458 icl_load_csc_matrix(crtc_state);
459 else
460 ilk_load_csc_matrix(crtc_state);
461 }
462
463 static void bdw_load_degamma_lut(const struct intel_crtc_state *crtc_state)
464 {
465 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
466 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
467 const struct drm_property_blob *degamma_lut = crtc_state->base.degamma_lut;
468 u32 i, lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
469 enum pipe pipe = crtc->pipe;
470
471 I915_WRITE(PREC_PAL_INDEX(pipe),
472 PAL_PREC_SPLIT_MODE | PAL_PREC_AUTO_INCREMENT);
473
474 if (degamma_lut) {
475 const struct drm_color_lut *lut = degamma_lut->data;
476
477 for (i = 0; i < lut_size; i++) {
478 u32 word =
479 drm_color_lut_extract(lut[i].red, 10) << 20 |
480 drm_color_lut_extract(lut[i].green, 10) << 10 |
481 drm_color_lut_extract(lut[i].blue, 10);
482
483 I915_WRITE(PREC_PAL_DATA(pipe), word);
484 }
485 } else {
486 for (i = 0; i < lut_size; i++) {
487 u32 v = (i * ((1 << 10) - 1)) / (lut_size - 1);
488
489 I915_WRITE(PREC_PAL_DATA(pipe),
490 (v << 20) | (v << 10) | v);
491 }
492 }
493 }
494
495 static void bdw_load_gamma_lut(const struct intel_crtc_state *crtc_state, u32 offset)
496 {
497 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
498 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
499 const struct drm_property_blob *gamma_lut = crtc_state->base.gamma_lut;
500 u32 i, lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
501 enum pipe pipe = crtc->pipe;
502
503 WARN_ON(offset & ~PAL_PREC_INDEX_VALUE_MASK);
504
505 I915_WRITE(PREC_PAL_INDEX(pipe),
506 (offset ? PAL_PREC_SPLIT_MODE : 0) |
507 PAL_PREC_AUTO_INCREMENT |
508 offset);
509
510 if (gamma_lut) {
511 const struct drm_color_lut *lut = gamma_lut->data;
512
513 for (i = 0; i < lut_size; i++) {
514 u32 word =
515 (drm_color_lut_extract(lut[i].red, 10) << 20) |
516 (drm_color_lut_extract(lut[i].green, 10) << 10) |
517 drm_color_lut_extract(lut[i].blue, 10);
518
519 I915_WRITE(PREC_PAL_DATA(pipe), word);
520 }
521
522 /* Program the max register to clamp values > 1.0. */
523 i = lut_size - 1;
524 I915_WRITE(PREC_PAL_GC_MAX(pipe, 0),
525 drm_color_lut_extract(lut[i].red, 16));
526 I915_WRITE(PREC_PAL_GC_MAX(pipe, 1),
527 drm_color_lut_extract(lut[i].green, 16));
528 I915_WRITE(PREC_PAL_GC_MAX(pipe, 2),
529 drm_color_lut_extract(lut[i].blue, 16));
530 } else {
531 for (i = 0; i < lut_size; i++) {
532 u32 v = (i * ((1 << 10) - 1)) / (lut_size - 1);
533
534 I915_WRITE(PREC_PAL_DATA(pipe),
535 (v << 20) | (v << 10) | v);
536 }
537
538 I915_WRITE(PREC_PAL_GC_MAX(pipe, 0), (1 << 16) - 1);
539 I915_WRITE(PREC_PAL_GC_MAX(pipe, 1), (1 << 16) - 1);
540 I915_WRITE(PREC_PAL_GC_MAX(pipe, 2), (1 << 16) - 1);
541 }
542
543 /*
544 * Reset the index, otherwise it prevents the legacy palette to be
545 * written properly.
546 */
547 I915_WRITE(PREC_PAL_INDEX(pipe), 0);
548 }
549
550 /* Loads the palette/gamma unit for the CRTC on Broadwell+. */
551 static void broadwell_load_luts(const struct intel_crtc_state *crtc_state)
552 {
553 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
554 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
555
556 if (crtc_state_is_legacy_gamma(crtc_state)) {
557 i9xx_load_luts(crtc_state);
558 } else {
559 bdw_load_degamma_lut(crtc_state);
560 bdw_load_gamma_lut(crtc_state,
561 INTEL_INFO(dev_priv)->color.degamma_lut_size);
562 }
563 }
564
565 static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state)
566 {
567 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
568 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
569 enum pipe pipe = crtc->pipe;
570 const u32 lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
571 u32 i;
572
573 /*
574 * When setting the auto-increment bit, the hardware seems to
575 * ignore the index bits, so we need to reset it to index 0
576 * separately.
577 */
578 I915_WRITE(PRE_CSC_GAMC_INDEX(pipe), 0);
579 I915_WRITE(PRE_CSC_GAMC_INDEX(pipe), PRE_CSC_GAMC_AUTO_INCREMENT);
580
581 if (crtc_state->base.degamma_lut) {
582 struct drm_color_lut *lut = crtc_state->base.degamma_lut->data;
583
584 for (i = 0; i < lut_size; i++) {
585 /*
586 * First 33 entries represent range from 0 to 1.0
587 * 34th and 35th entry will represent extended range
588 * inputs 3.0 and 7.0 respectively, currently clamped
589 * at 1.0. Since the precision is 16bit, the user
590 * value can be directly filled to register.
591 * The pipe degamma table in GLK+ onwards doesn't
592 * support different values per channel, so this just
593 * programs green value which will be equal to Red and
594 * Blue into the lut registers.
595 * ToDo: Extend to max 7.0. Enable 32 bit input value
596 * as compared to just 16 to achieve this.
597 */
598 I915_WRITE(PRE_CSC_GAMC_DATA(pipe), lut[i].green);
599 }
600 } else {
601 /* load a linear table. */
602 for (i = 0; i < lut_size; i++) {
603 u32 v = (i * (1 << 16)) / (lut_size - 1);
604
605 I915_WRITE(PRE_CSC_GAMC_DATA(pipe), v);
606 }
607 }
608
609 /* Clamp values > 1.0. */
610 while (i++ < 35)
611 I915_WRITE(PRE_CSC_GAMC_DATA(pipe), (1 << 16));
612 }
613
614 static void glk_load_luts(const struct intel_crtc_state *crtc_state)
615 {
616 glk_load_degamma_lut(crtc_state);
617
618 if (crtc_state_is_legacy_gamma(crtc_state))
619 i9xx_load_luts(crtc_state);
620 else
621 bdw_load_gamma_lut(crtc_state, 0);
622 }
623
624 static void icl_load_luts(const struct intel_crtc_state *crtc_state)
625 {
626 glk_load_degamma_lut(crtc_state);
627
628 if (crtc_state_is_legacy_gamma(crtc_state))
629 i9xx_load_luts(crtc_state);
630 else
631 /* ToDo: Add support for multi segment gamma LUT */
632 bdw_load_gamma_lut(crtc_state, 0);
633 }
634
635 static void cherryview_load_luts(const struct intel_crtc_state *crtc_state)
636 {
637 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
638 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
639 const struct drm_property_blob *gamma_lut = crtc_state->base.gamma_lut;
640 const struct drm_property_blob *degamma_lut = crtc_state->base.degamma_lut;
641 enum pipe pipe = crtc->pipe;
642
643 cherryview_load_csc_matrix(crtc_state);
644
645 if (crtc_state_is_legacy_gamma(crtc_state)) {
646 i9xx_load_luts_internal(crtc_state, gamma_lut);
647 return;
648 }
649
650 if (degamma_lut) {
651 const struct drm_color_lut *lut = degamma_lut->data;
652 int i, lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
653
654 for (i = 0; i < lut_size; i++) {
655 u32 word0, word1;
656
657 /* Write LUT in U0.14 format. */
658 word0 =
659 (drm_color_lut_extract(lut[i].green, 14) << 16) |
660 drm_color_lut_extract(lut[i].blue, 14);
661 word1 = drm_color_lut_extract(lut[i].red, 14);
662
663 I915_WRITE(CGM_PIPE_DEGAMMA(pipe, i, 0), word0);
664 I915_WRITE(CGM_PIPE_DEGAMMA(pipe, i, 1), word1);
665 }
666 }
667
668 if (gamma_lut) {
669 const struct drm_color_lut *lut = gamma_lut->data;
670 int i, lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
671
672 for (i = 0; i < lut_size; i++) {
673 u32 word0, word1;
674
675 /* Write LUT in U0.10 format. */
676 word0 =
677 (drm_color_lut_extract(lut[i].green, 10) << 16) |
678 drm_color_lut_extract(lut[i].blue, 10);
679 word1 = drm_color_lut_extract(lut[i].red, 10);
680
681 I915_WRITE(CGM_PIPE_GAMMA(pipe, i, 0), word0);
682 I915_WRITE(CGM_PIPE_GAMMA(pipe, i, 1), word1);
683 }
684 }
685
686 /*
687 * Also program a linear LUT in the legacy block (behind the
688 * CGM block).
689 */
690 i9xx_load_luts_internal(crtc_state, NULL);
691 }
692
693 void intel_color_load_luts(const struct intel_crtc_state *crtc_state)
694 {
695 struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
696
697 dev_priv->display.load_luts(crtc_state);
698 }
699
700 void intel_color_commit(const struct intel_crtc_state *crtc_state)
701 {
702 struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
703
704 dev_priv->display.color_commit(crtc_state);
705 }
706
707 int intel_color_check(struct intel_crtc_state *crtc_state)
708 {
709 struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
710
711 return dev_priv->display.color_check(crtc_state);
712 }
713
714 static bool need_plane_update(struct intel_plane *plane,
715 const struct intel_crtc_state *crtc_state)
716 {
717 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
718
719 /*
720 * On pre-SKL the pipe gamma enable and pipe csc enable for
721 * the pipe bottom color are configured via the primary plane.
722 * We have to reconfigure that even if the plane is inactive.
723 */
724 return crtc_state->active_planes & BIT(plane->id) ||
725 (INTEL_GEN(dev_priv) < 9 &&
726 plane->id == PLANE_PRIMARY);
727 }
728
729 static int
730 intel_color_add_affected_planes(struct intel_crtc_state *new_crtc_state)
731 {
732 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
733 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
734 struct intel_atomic_state *state =
735 to_intel_atomic_state(new_crtc_state->base.state);
736 const struct intel_crtc_state *old_crtc_state =
737 intel_atomic_get_old_crtc_state(state, crtc);
738 struct intel_plane *plane;
739
740 if (!new_crtc_state->base.active ||
741 drm_atomic_crtc_needs_modeset(&new_crtc_state->base))
742 return 0;
743
744 if (new_crtc_state->gamma_enable == old_crtc_state->gamma_enable &&
745 new_crtc_state->csc_enable == old_crtc_state->csc_enable)
746 return 0;
747
748 for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) {
749 struct intel_plane_state *plane_state;
750
751 if (!need_plane_update(plane, new_crtc_state))
752 continue;
753
754 plane_state = intel_atomic_get_plane_state(state, plane);
755 if (IS_ERR(plane_state))
756 return PTR_ERR(plane_state);
757
758 new_crtc_state->update_planes |= BIT(plane->id);
759 }
760
761 return 0;
762 }
763
764 static int check_lut_size(const struct drm_property_blob *lut, int expected)
765 {
766 int len;
767
768 if (!lut)
769 return 0;
770
771 len = drm_color_lut_size(lut);
772 if (len != expected) {
773 DRM_DEBUG_KMS("Invalid LUT size; got %d, expected %d\n",
774 len, expected);
775 return -EINVAL;
776 }
777
778 return 0;
779 }
780
781 static int check_luts(const struct intel_crtc_state *crtc_state)
782 {
783 struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
784 const struct drm_property_blob *gamma_lut = crtc_state->base.gamma_lut;
785 const struct drm_property_blob *degamma_lut = crtc_state->base.degamma_lut;
786 int gamma_length, degamma_length;
787 u32 gamma_tests, degamma_tests;
788
789 /* Always allow legacy gamma LUT with no further checking. */
790 if (crtc_state_is_legacy_gamma(crtc_state))
791 return 0;
792
793 /* C8 relies on its palette being stored in the legacy LUT */
794 if (crtc_state->c8_planes)
795 return -EINVAL;
796
797 degamma_length = INTEL_INFO(dev_priv)->color.degamma_lut_size;
798 gamma_length = INTEL_INFO(dev_priv)->color.gamma_lut_size;
799 degamma_tests = INTEL_INFO(dev_priv)->color.degamma_lut_tests;
800 gamma_tests = INTEL_INFO(dev_priv)->color.gamma_lut_tests;
801
802 if (check_lut_size(degamma_lut, degamma_length) ||
803 check_lut_size(gamma_lut, gamma_length))
804 return -EINVAL;
805
806 if (drm_color_lut_check(degamma_lut, degamma_tests) ||
807 drm_color_lut_check(gamma_lut, gamma_tests))
808 return -EINVAL;
809
810 return 0;
811 }
812
813 static int i9xx_color_check(struct intel_crtc_state *crtc_state)
814 {
815 int ret;
816
817 ret = check_luts(crtc_state);
818 if (ret)
819 return ret;
820
821 crtc_state->gamma_enable =
822 crtc_state->base.gamma_lut &&
823 !crtc_state->c8_planes;
824
825 crtc_state->gamma_mode = GAMMA_MODE_MODE_8BIT;
826
827 ret = intel_color_add_affected_planes(crtc_state);
828 if (ret)
829 return ret;
830
831 return 0;
832 }
833
834 static u32 chv_cgm_mode(const struct intel_crtc_state *crtc_state)
835 {
836 u32 cgm_mode = 0;
837
838 if (crtc_state_is_legacy_gamma(crtc_state))
839 return 0;
840
841 if (crtc_state->base.degamma_lut)
842 cgm_mode |= CGM_PIPE_MODE_DEGAMMA;
843 if (crtc_state->base.ctm)
844 cgm_mode |= CGM_PIPE_MODE_CSC;
845 if (crtc_state->base.gamma_lut)
846 cgm_mode |= CGM_PIPE_MODE_GAMMA;
847
848 return cgm_mode;
849 }
850
851 /*
852 * CHV color pipeline:
853 * u0.10 -> CGM degamma -> u0.14 -> CGM csc -> u0.14 -> CGM gamma ->
854 * u0.10 -> WGC csc -> u0.10 -> pipe gamma -> u0.10
855 *
856 * We always bypass the WGC csc and use the CGM csc
857 * instead since it has degamma and better precision.
858 */
859 static int chv_color_check(struct intel_crtc_state *crtc_state)
860 {
861 int ret;
862
863 ret = check_luts(crtc_state);
864 if (ret)
865 return ret;
866
867 /*
868 * Pipe gamma will be used only for the legacy LUT.
869 * Otherwise we bypass it and use the CGM gamma instead.
870 */
871 crtc_state->gamma_enable =
872 crtc_state_is_legacy_gamma(crtc_state) &&
873 !crtc_state->c8_planes;
874
875 crtc_state->gamma_mode = GAMMA_MODE_MODE_8BIT;
876
877 crtc_state->cgm_mode = chv_cgm_mode(crtc_state);
878
879 ret = intel_color_add_affected_planes(crtc_state);
880 if (ret)
881 return ret;
882
883 return 0;
884 }
885
886 static u32 bdw_gamma_mode(const struct intel_crtc_state *crtc_state)
887 {
888 if (!crtc_state->gamma_enable ||
889 crtc_state_is_legacy_gamma(crtc_state))
890 return GAMMA_MODE_MODE_8BIT;
891 else
892 return GAMMA_MODE_MODE_SPLIT;
893 }
894
895 static int bdw_color_check(struct intel_crtc_state *crtc_state)
896 {
897 int ret;
898
899 ret = check_luts(crtc_state);
900 if (ret)
901 return ret;
902
903 crtc_state->gamma_enable =
904 (crtc_state->base.gamma_lut ||
905 crtc_state->base.degamma_lut) &&
906 !crtc_state->c8_planes;
907
908 crtc_state->csc_enable =
909 crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB ||
910 crtc_state->base.ctm || crtc_state->limited_color_range;
911
912 crtc_state->gamma_mode = bdw_gamma_mode(crtc_state);
913
914 crtc_state->csc_mode = 0;
915
916 ret = intel_color_add_affected_planes(crtc_state);
917 if (ret)
918 return ret;
919
920 return 0;
921 }
922
923 static u32 glk_gamma_mode(const struct intel_crtc_state *crtc_state)
924 {
925 if (!crtc_state->gamma_enable ||
926 crtc_state_is_legacy_gamma(crtc_state))
927 return GAMMA_MODE_MODE_8BIT;
928 else
929 return GAMMA_MODE_MODE_10BIT;
930 }
931
932 static int glk_color_check(struct intel_crtc_state *crtc_state)
933 {
934 int ret;
935
936 ret = check_luts(crtc_state);
937 if (ret)
938 return ret;
939
940 crtc_state->gamma_enable =
941 crtc_state->base.gamma_lut &&
942 !crtc_state->c8_planes;
943
944 /* On GLK+ degamma LUT is controlled by csc_enable */
945 crtc_state->csc_enable =
946 crtc_state->base.degamma_lut ||
947 crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB ||
948 crtc_state->base.ctm || crtc_state->limited_color_range;
949
950 crtc_state->gamma_mode = glk_gamma_mode(crtc_state);
951
952 crtc_state->csc_mode = 0;
953
954 ret = intel_color_add_affected_planes(crtc_state);
955 if (ret)
956 return ret;
957
958 return 0;
959 }
960
961 static u32 icl_gamma_mode(const struct intel_crtc_state *crtc_state)
962 {
963 u32 gamma_mode = 0;
964
965 if (crtc_state->base.degamma_lut)
966 gamma_mode |= PRE_CSC_GAMMA_ENABLE;
967
968 if (crtc_state->base.gamma_lut &&
969 !crtc_state->c8_planes)
970 gamma_mode |= POST_CSC_GAMMA_ENABLE;
971
972 if (!crtc_state->base.gamma_lut ||
973 crtc_state_is_legacy_gamma(crtc_state))
974 gamma_mode |= GAMMA_MODE_MODE_8BIT;
975 else
976 gamma_mode |= GAMMA_MODE_MODE_10BIT;
977
978 return gamma_mode;
979 }
980
981 static u32 icl_csc_mode(const struct intel_crtc_state *crtc_state)
982 {
983 u32 csc_mode = 0;
984
985 if (crtc_state->base.ctm)
986 csc_mode |= ICL_CSC_ENABLE;
987
988 if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB ||
989 crtc_state->limited_color_range)
990 csc_mode |= ICL_OUTPUT_CSC_ENABLE;
991
992 return csc_mode;
993 }
994
995 static int icl_color_check(struct intel_crtc_state *crtc_state)
996 {
997 int ret;
998
999 ret = check_luts(crtc_state);
1000 if (ret)
1001 return ret;
1002
1003 crtc_state->gamma_mode = icl_gamma_mode(crtc_state);
1004
1005 crtc_state->csc_mode = icl_csc_mode(crtc_state);
1006
1007 return 0;
1008 }
1009
1010 static int _intel_color_check(struct intel_crtc_state *crtc_state)
1011 {
1012 struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
1013 const struct drm_property_blob *gamma_lut = crtc_state->base.gamma_lut;
1014 const struct drm_property_blob *degamma_lut = crtc_state->base.degamma_lut;
1015 bool limited_color_range = false;
1016 int ret;
1017
1018 ret = check_luts(crtc_state);
1019 if (ret)
1020 return ret;
1021
1022 crtc_state->gamma_enable = (gamma_lut || degamma_lut) &&
1023 !crtc_state->c8_planes;
1024
1025 if (INTEL_GEN(dev_priv) >= 9 ||
1026 IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
1027 limited_color_range = crtc_state->limited_color_range;
1028
1029 crtc_state->csc_enable =
1030 crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB ||
1031 crtc_state->base.ctm || limited_color_range;
1032
1033 ret = intel_color_add_affected_planes(crtc_state);
1034 if (ret)
1035 return ret;
1036
1037 crtc_state->csc_mode = 0;
1038
1039 if (!crtc_state->gamma_enable ||
1040 crtc_state_is_legacy_gamma(crtc_state))
1041 crtc_state->gamma_mode = GAMMA_MODE_MODE_8BIT;
1042 else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
1043 crtc_state->gamma_mode = GAMMA_MODE_MODE_10BIT;
1044 else if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
1045 crtc_state->gamma_mode = GAMMA_MODE_MODE_SPLIT;
1046 else
1047 crtc_state->gamma_mode = GAMMA_MODE_MODE_8BIT;
1048
1049 return 0;
1050 }
1051
1052 void intel_color_init(struct intel_crtc *crtc)
1053 {
1054 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1055
1056 drm_mode_crtc_set_gamma_size(&crtc->base, 256);
1057
1058 if (HAS_GMCH(dev_priv)) {
1059 if (IS_CHERRYVIEW(dev_priv)) {
1060 dev_priv->display.color_check = chv_color_check;
1061 dev_priv->display.color_commit = i9xx_color_commit;
1062 dev_priv->display.load_luts = cherryview_load_luts;
1063 } else {
1064 dev_priv->display.color_check = i9xx_color_check;
1065 dev_priv->display.color_commit = i9xx_color_commit;
1066 dev_priv->display.load_luts = i9xx_load_luts;
1067 }
1068 } else {
1069 if (INTEL_GEN(dev_priv) >= 11)
1070 dev_priv->display.color_check = icl_color_check;
1071 else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
1072 dev_priv->display.color_check = glk_color_check;
1073 else if (INTEL_GEN(dev_priv) >= 8)
1074 dev_priv->display.color_check = bdw_color_check;
1075 else
1076 dev_priv->display.color_check = _intel_color_check;
1077
1078 if (INTEL_GEN(dev_priv) >= 9)
1079 dev_priv->display.color_commit = skl_color_commit;
1080 else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
1081 dev_priv->display.color_commit = hsw_color_commit;
1082 else
1083 dev_priv->display.color_commit = ilk_color_commit;
1084
1085 if (INTEL_GEN(dev_priv) >= 11)
1086 dev_priv->display.load_luts = icl_load_luts;
1087 else if (IS_CANNONLAKE(dev_priv) || IS_GEMINILAKE(dev_priv))
1088 dev_priv->display.load_luts = glk_load_luts;
1089 else if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
1090 dev_priv->display.load_luts = broadwell_load_luts;
1091 else
1092 dev_priv->display.load_luts = i9xx_load_luts;
1093 }
1094
1095 /* Enable color management support when we have degamma & gamma LUTs. */
1096 if (INTEL_INFO(dev_priv)->color.degamma_lut_size != 0 &&
1097 INTEL_INFO(dev_priv)->color.gamma_lut_size != 0)
1098 drm_crtc_enable_color_mgmt(&crtc->base,
1099 INTEL_INFO(dev_priv)->color.degamma_lut_size,
1100 true,
1101 INTEL_INFO(dev_priv)->color.gamma_lut_size);
1102 }