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 "i915_reg.h"
26#include "intel_color.h"
27#include "intel_color_regs.h"
28#include "intel_de.h"
29#include "intel_display_types.h"
30#include "intel_dsb.h"
31
32struct intel_color_funcs {
33 int (*color_check)(struct intel_crtc_state *crtc_state);
34 /*
35 * Program non-arming double buffered color management registers
36 * before vblank evasion. The registers should then latch after
37 * the arming register is written (by color_commit_arm()) during
38 * the next vblank start, alongside any other double buffered
39 * registers involved with the same commit. This hook is optional.
40 */
41 void (*color_commit_noarm)(const struct intel_crtc_state *crtc_state);
42 /*
43 * Program arming double buffered color management registers
44 * during vblank evasion. The registers (and whatever other registers
45 * they arm that were written by color_commit_noarm) should then latch
46 * during the next vblank start, alongside any other double buffered
47 * registers involved with the same commit.
48 */
49 void (*color_commit_arm)(const struct intel_crtc_state *crtc_state);
50 /*
51 * Perform any extra tasks needed after all the
52 * double buffered registers have been latched.
53 */
54 void (*color_post_update)(const struct intel_crtc_state *crtc_state);
55 /*
56 * Load LUTs (and other single buffered color management
57 * registers). Will (hopefully) be called during the vblank
58 * following the latching of any double buffered registers
59 * involved with the same commit.
60 */
61 void (*load_luts)(const struct intel_crtc_state *crtc_state);
62 /*
63 * Read out the LUTs from the hardware into the software state.
64 * Used by eg. the hardware state checker.
65 */
66 void (*read_luts)(struct intel_crtc_state *crtc_state);
67 /*
68 * Compare the LUTs
69 */
70 bool (*lut_equal)(const struct intel_crtc_state *crtc_state,
71 const struct drm_property_blob *blob1,
72 const struct drm_property_blob *blob2,
73 bool is_pre_csc_lut);
74 /*
75 * Read out the CSCs (if any) from the hardware into the
76 * software state. Used by eg. the hardware state checker.
77 */
78 void (*read_csc)(struct intel_crtc_state *crtc_state);
79 /*
80 * Read config other than LUTs and CSCs, before them. Optional.
81 */
82 void (*get_config)(struct intel_crtc_state *crtc_state);
83};
84
85#define CTM_COEFF_SIGN (1ULL << 63)
86
87#define CTM_COEFF_1_0 (1ULL << 32)
88#define CTM_COEFF_2_0 (CTM_COEFF_1_0 << 1)
89#define CTM_COEFF_4_0 (CTM_COEFF_2_0 << 1)
90#define CTM_COEFF_8_0 (CTM_COEFF_4_0 << 1)
91#define CTM_COEFF_0_5 (CTM_COEFF_1_0 >> 1)
92#define CTM_COEFF_0_25 (CTM_COEFF_0_5 >> 1)
93#define CTM_COEFF_0_125 (CTM_COEFF_0_25 >> 1)
94
95#define CTM_COEFF_LIMITED_RANGE ((235ULL - 16ULL) * CTM_COEFF_1_0 / 255)
96
97#define CTM_COEFF_NEGATIVE(coeff) (((coeff) & CTM_COEFF_SIGN) != 0)
98#define CTM_COEFF_ABS(coeff) ((coeff) & (CTM_COEFF_SIGN - 1))
99
100#define LEGACY_LUT_LENGTH 256
101
102/*
103 * ILK+ csc matrix:
104 *
105 * |R/Cr| | c0 c1 c2 | ( |R/Cr| |preoff0| ) |postoff0|
106 * |G/Y | = | c3 c4 c5 | x ( |G/Y | + |preoff1| ) + |postoff1|
107 * |B/Cb| | c6 c7 c8 | ( |B/Cb| |preoff2| ) |postoff2|
108 *
109 * ILK/SNB don't have explicit post offsets, and instead
110 * CSC_MODE_YUV_TO_RGB and CSC_BLACK_SCREEN_OFFSET are used:
111 * CSC_MODE_YUV_TO_RGB=0 + CSC_BLACK_SCREEN_OFFSET=0 -> 1/2, 0, 1/2
112 * CSC_MODE_YUV_TO_RGB=0 + CSC_BLACK_SCREEN_OFFSET=1 -> 1/2, 1/16, 1/2
113 * CSC_MODE_YUV_TO_RGB=1 + CSC_BLACK_SCREEN_OFFSET=0 -> 0, 0, 0
114 * CSC_MODE_YUV_TO_RGB=1 + CSC_BLACK_SCREEN_OFFSET=1 -> 1/16, 1/16, 1/16
115 */
116
117/*
118 * Extract the CSC coefficient from a CTM coefficient (in U32.32 fixed point
119 * format). This macro takes the coefficient we want transformed and the
120 * number of fractional bits.
121 *
122 * We only have a 9 bits precision window which slides depending on the value
123 * of the CTM coefficient and we write the value from bit 3. We also round the
124 * value.
125 */
126#define ILK_CSC_COEFF_FP(coeff, fbits) \
127 (clamp_val(((coeff) >> (32 - (fbits) - 3)) + 4, 0, 0xfff) & 0xff8)
128
129#define ILK_CSC_COEFF_1_0 0x7800
130#define ILK_CSC_COEFF_LIMITED_RANGE ((235 - 16) << (12 - 8)) /* exponent 0 */
131#define ILK_CSC_POSTOFF_LIMITED_RANGE (16 << (12 - 8))
132
133static const struct intel_csc_matrix ilk_csc_matrix_identity = {
134 .preoff = {},
135 .coeff = {
136 ILK_CSC_COEFF_1_0, 0, 0,
137 0, ILK_CSC_COEFF_1_0, 0,
138 0, 0, ILK_CSC_COEFF_1_0,
139 },
140 .postoff = {},
141};
142
143/* Full range RGB -> limited range RGB matrix */
144static const struct intel_csc_matrix ilk_csc_matrix_limited_range = {
145 .preoff = {},
146 .coeff = {
147 ILK_CSC_COEFF_LIMITED_RANGE, 0, 0,
148 0, ILK_CSC_COEFF_LIMITED_RANGE, 0,
149 0, 0, ILK_CSC_COEFF_LIMITED_RANGE,
150 },
151 .postoff = {
152 ILK_CSC_POSTOFF_LIMITED_RANGE,
153 ILK_CSC_POSTOFF_LIMITED_RANGE,
154 ILK_CSC_POSTOFF_LIMITED_RANGE,
155 },
156};
157
158/* BT.709 full range RGB -> limited range YCbCr matrix */
159static const struct intel_csc_matrix ilk_csc_matrix_rgb_to_ycbcr = {
160 .preoff = {},
161 .coeff = {
162 0x1e08, 0x9cc0, 0xb528,
163 0x2ba8, 0x09d8, 0x37e8,
164 0xbce8, 0x9ad8, 0x1e08,
165 },
166 .postoff = {
167 0x0800, 0x0100, 0x0800,
168 },
169};
170
171static void intel_csc_clear(struct intel_csc_matrix *csc)
172{
173 memset(csc, 0, sizeof(*csc));
174}
175
176static bool lut_is_legacy(const struct drm_property_blob *lut)
177{
178 return lut && drm_color_lut_size(blob: lut) == LEGACY_LUT_LENGTH;
179}
180
181/*
182 * When using limited range, multiply the matrix given by userspace by
183 * the matrix that we would use for the limited range.
184 */
185static u64 *ctm_mult_by_limited(u64 *result, const u64 *input)
186{
187 int i;
188
189 for (i = 0; i < 9; i++) {
190 u64 user_coeff = input[i];
191 u32 limited_coeff = CTM_COEFF_LIMITED_RANGE;
192 u32 abs_coeff = clamp_val(CTM_COEFF_ABS(user_coeff), 0,
193 CTM_COEFF_4_0 - 1) >> 2;
194
195 /*
196 * By scaling every co-efficient with limited range (16-235)
197 * vs full range (0-255) the final o/p will be scaled down to
198 * fit in the limited range supported by the panel.
199 */
200 result[i] = mul_u32_u32(a: limited_coeff, b: abs_coeff) >> 30;
201 result[i] |= user_coeff & CTM_COEFF_SIGN;
202 }
203
204 return result;
205}
206
207static void ilk_update_pipe_csc(struct intel_crtc *crtc,
208 const struct intel_csc_matrix *csc)
209{
210 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
211 enum pipe pipe = crtc->pipe;
212
213 intel_de_write_fw(i915, PIPE_CSC_PREOFF_HI(pipe), val: csc->preoff[0]);
214 intel_de_write_fw(i915, PIPE_CSC_PREOFF_ME(pipe), val: csc->preoff[1]);
215 intel_de_write_fw(i915, PIPE_CSC_PREOFF_LO(pipe), val: csc->preoff[2]);
216
217 intel_de_write_fw(i915, PIPE_CSC_COEFF_RY_GY(pipe),
218 val: csc->coeff[0] << 16 | csc->coeff[1]);
219 intel_de_write_fw(i915, PIPE_CSC_COEFF_BY(pipe),
220 val: csc->coeff[2] << 16);
221
222 intel_de_write_fw(i915, PIPE_CSC_COEFF_RU_GU(pipe),
223 val: csc->coeff[3] << 16 | csc->coeff[4]);
224 intel_de_write_fw(i915, PIPE_CSC_COEFF_BU(pipe),
225 val: csc->coeff[5] << 16);
226
227 intel_de_write_fw(i915, PIPE_CSC_COEFF_RV_GV(pipe),
228 val: csc->coeff[6] << 16 | csc->coeff[7]);
229 intel_de_write_fw(i915, PIPE_CSC_COEFF_BV(pipe),
230 val: csc->coeff[8] << 16);
231
232 if (DISPLAY_VER(i915) < 7)
233 return;
234
235 intel_de_write_fw(i915, PIPE_CSC_POSTOFF_HI(pipe), val: csc->postoff[0]);
236 intel_de_write_fw(i915, PIPE_CSC_POSTOFF_ME(pipe), val: csc->postoff[1]);
237 intel_de_write_fw(i915, PIPE_CSC_POSTOFF_LO(pipe), val: csc->postoff[2]);
238}
239
240static void ilk_read_pipe_csc(struct intel_crtc *crtc,
241 struct intel_csc_matrix *csc)
242{
243 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
244 enum pipe pipe = crtc->pipe;
245 u32 tmp;
246
247 csc->preoff[0] = intel_de_read_fw(i915, PIPE_CSC_PREOFF_HI(pipe));
248 csc->preoff[1] = intel_de_read_fw(i915, PIPE_CSC_PREOFF_ME(pipe));
249 csc->preoff[2] = intel_de_read_fw(i915, PIPE_CSC_PREOFF_LO(pipe));
250
251 tmp = intel_de_read_fw(i915, PIPE_CSC_COEFF_RY_GY(pipe));
252 csc->coeff[0] = tmp >> 16;
253 csc->coeff[1] = tmp & 0xffff;
254 tmp = intel_de_read_fw(i915, PIPE_CSC_COEFF_BY(pipe));
255 csc->coeff[2] = tmp >> 16;
256
257 tmp = intel_de_read_fw(i915, PIPE_CSC_COEFF_RU_GU(pipe));
258 csc->coeff[3] = tmp >> 16;
259 csc->coeff[4] = tmp & 0xffff;
260 tmp = intel_de_read_fw(i915, PIPE_CSC_COEFF_BU(pipe));
261 csc->coeff[5] = tmp >> 16;
262
263 tmp = intel_de_read_fw(i915, PIPE_CSC_COEFF_RV_GV(pipe));
264 csc->coeff[6] = tmp >> 16;
265 csc->coeff[7] = tmp & 0xffff;
266 tmp = intel_de_read_fw(i915, PIPE_CSC_COEFF_BV(pipe));
267 csc->coeff[8] = tmp >> 16;
268
269 if (DISPLAY_VER(i915) < 7)
270 return;
271
272 csc->postoff[0] = intel_de_read_fw(i915, PIPE_CSC_POSTOFF_HI(pipe));
273 csc->postoff[1] = intel_de_read_fw(i915, PIPE_CSC_POSTOFF_ME(pipe));
274 csc->postoff[2] = intel_de_read_fw(i915, PIPE_CSC_POSTOFF_LO(pipe));
275}
276
277static void ilk_read_csc(struct intel_crtc_state *crtc_state)
278{
279 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
280
281 if (crtc_state->csc_enable)
282 ilk_read_pipe_csc(crtc, csc: &crtc_state->csc);
283}
284
285static void skl_read_csc(struct intel_crtc_state *crtc_state)
286{
287 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
288
289 /*
290 * Display WA #1184: skl,glk
291 * Wa_1406463849: icl
292 *
293 * Danger! On SKL-ICL *reads* from the CSC coeff/offset registers
294 * will disarm an already armed CSC double buffer update.
295 * So this must not be called while armed. Fortunately the state checker
296 * readout happens only after the update has been already been latched.
297 *
298 * On earlier and later platforms only writes to said registers will
299 * disarm the update. This is considered normal behavior and also
300 * happens with various other hardware units.
301 */
302 if (crtc_state->csc_enable)
303 ilk_read_pipe_csc(crtc, csc: &crtc_state->csc);
304}
305
306static void icl_update_output_csc(struct intel_crtc *crtc,
307 const struct intel_csc_matrix *csc)
308{
309 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
310 enum pipe pipe = crtc->pipe;
311
312 intel_de_write_fw(i915, PIPE_CSC_OUTPUT_PREOFF_HI(pipe), val: csc->preoff[0]);
313 intel_de_write_fw(i915, PIPE_CSC_OUTPUT_PREOFF_ME(pipe), val: csc->preoff[1]);
314 intel_de_write_fw(i915, PIPE_CSC_OUTPUT_PREOFF_LO(pipe), val: csc->preoff[2]);
315
316 intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_RY_GY(pipe),
317 val: csc->coeff[0] << 16 | csc->coeff[1]);
318 intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_BY(pipe),
319 val: csc->coeff[2] << 16);
320
321 intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_RU_GU(pipe),
322 val: csc->coeff[3] << 16 | csc->coeff[4]);
323 intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_BU(pipe),
324 val: csc->coeff[5] << 16);
325
326 intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_RV_GV(pipe),
327 val: csc->coeff[6] << 16 | csc->coeff[7]);
328 intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_BV(pipe),
329 val: csc->coeff[8] << 16);
330
331 intel_de_write_fw(i915, PIPE_CSC_OUTPUT_POSTOFF_HI(pipe), val: csc->postoff[0]);
332 intel_de_write_fw(i915, PIPE_CSC_OUTPUT_POSTOFF_ME(pipe), val: csc->postoff[1]);
333 intel_de_write_fw(i915, PIPE_CSC_OUTPUT_POSTOFF_LO(pipe), val: csc->postoff[2]);
334}
335
336static void icl_read_output_csc(struct intel_crtc *crtc,
337 struct intel_csc_matrix *csc)
338{
339 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
340 enum pipe pipe = crtc->pipe;
341 u32 tmp;
342
343 csc->preoff[0] = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_PREOFF_HI(pipe));
344 csc->preoff[1] = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_PREOFF_ME(pipe));
345 csc->preoff[2] = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_PREOFF_LO(pipe));
346
347 tmp = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_COEFF_RY_GY(pipe));
348 csc->coeff[0] = tmp >> 16;
349 csc->coeff[1] = tmp & 0xffff;
350 tmp = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_COEFF_BY(pipe));
351 csc->coeff[2] = tmp >> 16;
352
353 tmp = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_COEFF_RU_GU(pipe));
354 csc->coeff[3] = tmp >> 16;
355 csc->coeff[4] = tmp & 0xffff;
356 tmp = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_COEFF_BU(pipe));
357 csc->coeff[5] = tmp >> 16;
358
359 tmp = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_COEFF_RV_GV(pipe));
360 csc->coeff[6] = tmp >> 16;
361 csc->coeff[7] = tmp & 0xffff;
362 tmp = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_COEFF_BV(pipe));
363 csc->coeff[8] = tmp >> 16;
364
365 csc->postoff[0] = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_POSTOFF_HI(pipe));
366 csc->postoff[1] = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_POSTOFF_ME(pipe));
367 csc->postoff[2] = intel_de_read_fw(i915, PIPE_CSC_OUTPUT_POSTOFF_LO(pipe));
368}
369
370static void icl_read_csc(struct intel_crtc_state *crtc_state)
371{
372 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
373
374 /*
375 * Wa_1406463849: icl
376 *
377 * See skl_read_csc()
378 */
379 if (crtc_state->csc_mode & ICL_CSC_ENABLE)
380 ilk_read_pipe_csc(crtc, csc: &crtc_state->csc);
381
382 if (crtc_state->csc_mode & ICL_OUTPUT_CSC_ENABLE)
383 icl_read_output_csc(crtc, csc: &crtc_state->output_csc);
384}
385
386static bool ilk_limited_range(const struct intel_crtc_state *crtc_state)
387{
388 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
389
390 /* icl+ have dedicated output CSC */
391 if (DISPLAY_VER(i915) >= 11)
392 return false;
393
394 /* pre-hsw have TRANSCONF_COLOR_RANGE_SELECT */
395 if (DISPLAY_VER(i915) < 7 || IS_IVYBRIDGE(i915))
396 return false;
397
398 return crtc_state->limited_color_range;
399}
400
401static bool ilk_lut_limited_range(const struct intel_crtc_state *crtc_state)
402{
403 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
404
405 if (!ilk_limited_range(crtc_state))
406 return false;
407
408 if (crtc_state->c8_planes)
409 return false;
410
411 if (DISPLAY_VER(i915) == 10)
412 return crtc_state->hw.gamma_lut;
413 else
414 return crtc_state->hw.gamma_lut &&
415 (crtc_state->hw.degamma_lut || crtc_state->hw.ctm);
416}
417
418static bool ilk_csc_limited_range(const struct intel_crtc_state *crtc_state)
419{
420 if (!ilk_limited_range(crtc_state))
421 return false;
422
423 return !ilk_lut_limited_range(crtc_state);
424}
425
426static void ilk_csc_copy(struct drm_i915_private *i915,
427 struct intel_csc_matrix *dst,
428 const struct intel_csc_matrix *src)
429{
430 *dst = *src;
431
432 if (DISPLAY_VER(i915) < 7)
433 memset(dst->postoff, 0, sizeof(dst->postoff));
434}
435
436static void ilk_csc_convert_ctm(const struct intel_crtc_state *crtc_state,
437 struct intel_csc_matrix *csc,
438 bool limited_color_range)
439{
440 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
441 const struct drm_color_ctm *ctm = crtc_state->hw.ctm->data;
442 const u64 *input;
443 u64 temp[9];
444 int i;
445
446 /* for preoff/postoff */
447 if (limited_color_range)
448 ilk_csc_copy(i915, dst: csc, src: &ilk_csc_matrix_limited_range);
449 else
450 ilk_csc_copy(i915, dst: csc, src: &ilk_csc_matrix_identity);
451
452 if (limited_color_range)
453 input = ctm_mult_by_limited(result: temp, input: ctm->matrix);
454 else
455 input = ctm->matrix;
456
457 /*
458 * Convert fixed point S31.32 input to format supported by the
459 * hardware.
460 */
461 for (i = 0; i < 9; i++) {
462 u64 abs_coeff = ((1ULL << 63) - 1) & input[i];
463
464 /*
465 * Clamp input value to min/max supported by
466 * hardware.
467 */
468 abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_4_0 - 1);
469
470 csc->coeff[i] = 0;
471
472 /* sign bit */
473 if (CTM_COEFF_NEGATIVE(input[i]))
474 csc->coeff[i] |= 1 << 15;
475
476 if (abs_coeff < CTM_COEFF_0_125)
477 csc->coeff[i] |= (3 << 12) |
478 ILK_CSC_COEFF_FP(abs_coeff, 12);
479 else if (abs_coeff < CTM_COEFF_0_25)
480 csc->coeff[i] |= (2 << 12) |
481 ILK_CSC_COEFF_FP(abs_coeff, 11);
482 else if (abs_coeff < CTM_COEFF_0_5)
483 csc->coeff[i] |= (1 << 12) |
484 ILK_CSC_COEFF_FP(abs_coeff, 10);
485 else if (abs_coeff < CTM_COEFF_1_0)
486 csc->coeff[i] |= ILK_CSC_COEFF_FP(abs_coeff, 9);
487 else if (abs_coeff < CTM_COEFF_2_0)
488 csc->coeff[i] |= (7 << 12) |
489 ILK_CSC_COEFF_FP(abs_coeff, 8);
490 else
491 csc->coeff[i] |= (6 << 12) |
492 ILK_CSC_COEFF_FP(abs_coeff, 7);
493 }
494}
495
496static void ilk_assign_csc(struct intel_crtc_state *crtc_state)
497{
498 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
499 bool limited_color_range = ilk_csc_limited_range(crtc_state);
500
501 if (crtc_state->hw.ctm) {
502 drm_WARN_ON(&i915->drm, !crtc_state->csc_enable);
503
504 ilk_csc_convert_ctm(crtc_state, csc: &crtc_state->csc, limited_color_range);
505 } else if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB) {
506 drm_WARN_ON(&i915->drm, !crtc_state->csc_enable);
507
508 ilk_csc_copy(i915, dst: &crtc_state->csc, src: &ilk_csc_matrix_rgb_to_ycbcr);
509 } else if (limited_color_range) {
510 drm_WARN_ON(&i915->drm, !crtc_state->csc_enable);
511
512 ilk_csc_copy(i915, dst: &crtc_state->csc, src: &ilk_csc_matrix_limited_range);
513 } else if (crtc_state->csc_enable) {
514 /*
515 * On GLK both pipe CSC and degamma LUT are controlled
516 * by csc_enable. Hence for the cases where the degama
517 * LUT is needed but CSC is not we need to load an
518 * identity matrix.
519 */
520 drm_WARN_ON(&i915->drm, !IS_GEMINILAKE(i915));
521
522 ilk_csc_copy(i915, dst: &crtc_state->csc, src: &ilk_csc_matrix_identity);
523 } else {
524 intel_csc_clear(csc: &crtc_state->csc);
525 }
526}
527
528static void ilk_load_csc_matrix(const struct intel_crtc_state *crtc_state)
529{
530 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
531
532 if (crtc_state->csc_enable)
533 ilk_update_pipe_csc(crtc, csc: &crtc_state->csc);
534}
535
536static void icl_assign_csc(struct intel_crtc_state *crtc_state)
537{
538 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
539
540 if (crtc_state->hw.ctm) {
541 drm_WARN_ON(&i915->drm, (crtc_state->csc_mode & ICL_CSC_ENABLE) == 0);
542
543 ilk_csc_convert_ctm(crtc_state, csc: &crtc_state->csc, limited_color_range: false);
544 } else {
545 drm_WARN_ON(&i915->drm, (crtc_state->csc_mode & ICL_CSC_ENABLE) != 0);
546
547 intel_csc_clear(csc: &crtc_state->csc);
548 }
549
550 if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB) {
551 drm_WARN_ON(&i915->drm, (crtc_state->csc_mode & ICL_OUTPUT_CSC_ENABLE) == 0);
552
553 ilk_csc_copy(i915, dst: &crtc_state->output_csc, src: &ilk_csc_matrix_rgb_to_ycbcr);
554 } else if (crtc_state->limited_color_range) {
555 drm_WARN_ON(&i915->drm, (crtc_state->csc_mode & ICL_OUTPUT_CSC_ENABLE) == 0);
556
557 ilk_csc_copy(i915, dst: &crtc_state->output_csc, src: &ilk_csc_matrix_limited_range);
558 } else {
559 drm_WARN_ON(&i915->drm, (crtc_state->csc_mode & ICL_OUTPUT_CSC_ENABLE) != 0);
560
561 intel_csc_clear(csc: &crtc_state->output_csc);
562 }
563}
564
565static void icl_load_csc_matrix(const struct intel_crtc_state *crtc_state)
566{
567 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
568
569 if (crtc_state->csc_mode & ICL_CSC_ENABLE)
570 ilk_update_pipe_csc(crtc, csc: &crtc_state->csc);
571
572 if (crtc_state->csc_mode & ICL_OUTPUT_CSC_ENABLE)
573 icl_update_output_csc(crtc, csc: &crtc_state->output_csc);
574}
575
576static u16 ctm_to_twos_complement(u64 coeff, int int_bits, int frac_bits)
577{
578 s64 c = CTM_COEFF_ABS(coeff);
579
580 /* leave an extra bit for rounding */
581 c >>= 32 - frac_bits - 1;
582
583 /* round and drop the extra bit */
584 c = (c + 1) >> 1;
585
586 if (CTM_COEFF_NEGATIVE(coeff))
587 c = -c;
588
589 c = clamp(c, -(s64)BIT(int_bits + frac_bits - 1),
590 (s64)(BIT(int_bits + frac_bits - 1) - 1));
591
592 return c & (BIT(int_bits + frac_bits) - 1);
593}
594
595/*
596 * VLV/CHV Wide Gamut Color Correction (WGC) CSC
597 * |r| | c0 c1 c2 | |r|
598 * |g| = | c3 c4 c5 | x |g|
599 * |b| | c6 c7 c8 | |b|
600 *
601 * Coefficients are two's complement s2.10.
602 */
603static void vlv_wgc_csc_convert_ctm(const struct intel_crtc_state *crtc_state,
604 struct intel_csc_matrix *csc)
605{
606 const struct drm_color_ctm *ctm = crtc_state->hw.ctm->data;
607 int i;
608
609 for (i = 0; i < 9; i++)
610 csc->coeff[i] = ctm_to_twos_complement(coeff: ctm->matrix[i], int_bits: 2, frac_bits: 10);
611}
612
613static void vlv_load_wgc_csc(struct intel_crtc *crtc,
614 const struct intel_csc_matrix *csc)
615{
616 struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev);
617 enum pipe pipe = crtc->pipe;
618
619 intel_de_write_fw(i915: dev_priv, PIPE_WGC_C01_C00(pipe),
620 val: csc->coeff[1] << 16 | csc->coeff[0]);
621 intel_de_write_fw(i915: dev_priv, PIPE_WGC_C02(pipe),
622 val: csc->coeff[2]);
623
624 intel_de_write_fw(i915: dev_priv, PIPE_WGC_C11_C10(pipe),
625 val: csc->coeff[4] << 16 | csc->coeff[3]);
626 intel_de_write_fw(i915: dev_priv, PIPE_WGC_C12(pipe),
627 val: csc->coeff[5]);
628
629 intel_de_write_fw(i915: dev_priv, PIPE_WGC_C21_C20(pipe),
630 val: csc->coeff[7] << 16 | csc->coeff[6]);
631 intel_de_write_fw(i915: dev_priv, PIPE_WGC_C22(pipe),
632 val: csc->coeff[8]);
633}
634
635static void vlv_read_wgc_csc(struct intel_crtc *crtc,
636 struct intel_csc_matrix *csc)
637{
638 struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev);
639 enum pipe pipe = crtc->pipe;
640 u32 tmp;
641
642 tmp = intel_de_read_fw(i915: dev_priv, PIPE_WGC_C01_C00(pipe));
643 csc->coeff[0] = tmp & 0xffff;
644 csc->coeff[1] = tmp >> 16;
645
646 tmp = intel_de_read_fw(i915: dev_priv, PIPE_WGC_C02(pipe));
647 csc->coeff[2] = tmp & 0xffff;
648
649 tmp = intel_de_read_fw(i915: dev_priv, PIPE_WGC_C11_C10(pipe));
650 csc->coeff[3] = tmp & 0xffff;
651 csc->coeff[4] = tmp >> 16;
652
653 tmp = intel_de_read_fw(i915: dev_priv, PIPE_WGC_C12(pipe));
654 csc->coeff[5] = tmp & 0xffff;
655
656 tmp = intel_de_read_fw(i915: dev_priv, PIPE_WGC_C21_C20(pipe));
657 csc->coeff[6] = tmp & 0xffff;
658 csc->coeff[7] = tmp >> 16;
659
660 tmp = intel_de_read_fw(i915: dev_priv, PIPE_WGC_C22(pipe));
661 csc->coeff[8] = tmp & 0xffff;
662}
663
664static void vlv_read_csc(struct intel_crtc_state *crtc_state)
665{
666 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
667
668 if (crtc_state->wgc_enable)
669 vlv_read_wgc_csc(crtc, csc: &crtc_state->csc);
670}
671
672static void vlv_assign_csc(struct intel_crtc_state *crtc_state)
673{
674 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
675
676 if (crtc_state->hw.ctm) {
677 drm_WARN_ON(&i915->drm, !crtc_state->wgc_enable);
678
679 vlv_wgc_csc_convert_ctm(crtc_state, csc: &crtc_state->csc);
680 } else {
681 drm_WARN_ON(&i915->drm, crtc_state->wgc_enable);
682
683 intel_csc_clear(csc: &crtc_state->csc);
684 }
685}
686
687/*
688 * CHV Color Gamut Mapping (CGM) CSC
689 * |r| | c0 c1 c2 | |r|
690 * |g| = | c3 c4 c5 | x |g|
691 * |b| | c6 c7 c8 | |b|
692 *
693 * Coefficients are two's complement s4.12.
694 */
695static void chv_cgm_csc_convert_ctm(const struct intel_crtc_state *crtc_state,
696 struct intel_csc_matrix *csc)
697{
698 const struct drm_color_ctm *ctm = crtc_state->hw.ctm->data;
699 int i;
700
701 for (i = 0; i < 9; i++)
702 csc->coeff[i] = ctm_to_twos_complement(coeff: ctm->matrix[i], int_bits: 4, frac_bits: 12);
703}
704
705#define CHV_CGM_CSC_COEFF_1_0 (1 << 12)
706
707static const struct intel_csc_matrix chv_cgm_csc_matrix_identity = {
708 .coeff = {
709 CHV_CGM_CSC_COEFF_1_0, 0, 0,
710 0, CHV_CGM_CSC_COEFF_1_0, 0,
711 0, 0, CHV_CGM_CSC_COEFF_1_0,
712 },
713};
714
715static void chv_load_cgm_csc(struct intel_crtc *crtc,
716 const struct intel_csc_matrix *csc)
717{
718 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
719 enum pipe pipe = crtc->pipe;
720
721 intel_de_write_fw(i915, CGM_PIPE_CSC_COEFF01(pipe),
722 val: csc->coeff[1] << 16 | csc->coeff[0]);
723 intel_de_write_fw(i915, CGM_PIPE_CSC_COEFF23(pipe),
724 val: csc->coeff[3] << 16 | csc->coeff[2]);
725 intel_de_write_fw(i915, CGM_PIPE_CSC_COEFF45(pipe),
726 val: csc->coeff[5] << 16 | csc->coeff[4]);
727 intel_de_write_fw(i915, CGM_PIPE_CSC_COEFF67(pipe),
728 val: csc->coeff[7] << 16 | csc->coeff[6]);
729 intel_de_write_fw(i915, CGM_PIPE_CSC_COEFF8(pipe),
730 val: csc->coeff[8]);
731}
732
733static void chv_read_cgm_csc(struct intel_crtc *crtc,
734 struct intel_csc_matrix *csc)
735{
736 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
737 enum pipe pipe = crtc->pipe;
738 u32 tmp;
739
740 tmp = intel_de_read_fw(i915, CGM_PIPE_CSC_COEFF01(pipe));
741 csc->coeff[0] = tmp & 0xffff;
742 csc->coeff[1] = tmp >> 16;
743
744 tmp = intel_de_read_fw(i915, CGM_PIPE_CSC_COEFF23(pipe));
745 csc->coeff[2] = tmp & 0xffff;
746 csc->coeff[3] = tmp >> 16;
747
748 tmp = intel_de_read_fw(i915, CGM_PIPE_CSC_COEFF45(pipe));
749 csc->coeff[4] = tmp & 0xffff;
750 csc->coeff[5] = tmp >> 16;
751
752 tmp = intel_de_read_fw(i915, CGM_PIPE_CSC_COEFF67(pipe));
753 csc->coeff[6] = tmp & 0xffff;
754 csc->coeff[7] = tmp >> 16;
755
756 tmp = intel_de_read_fw(i915, CGM_PIPE_CSC_COEFF8(pipe));
757 csc->coeff[8] = tmp & 0xffff;
758}
759
760static void chv_read_csc(struct intel_crtc_state *crtc_state)
761{
762 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
763
764 if (crtc_state->cgm_mode & CGM_PIPE_MODE_CSC)
765 chv_read_cgm_csc(crtc, csc: &crtc_state->csc);
766}
767
768static void chv_assign_csc(struct intel_crtc_state *crtc_state)
769{
770 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
771
772 drm_WARN_ON(&i915->drm, crtc_state->wgc_enable);
773
774 if (crtc_state->hw.ctm) {
775 drm_WARN_ON(&i915->drm, (crtc_state->cgm_mode & CGM_PIPE_MODE_CSC) == 0);
776
777 chv_cgm_csc_convert_ctm(crtc_state, csc: &crtc_state->csc);
778 } else {
779 drm_WARN_ON(&i915->drm, (crtc_state->cgm_mode & CGM_PIPE_MODE_CSC) == 0);
780
781 crtc_state->csc = chv_cgm_csc_matrix_identity;
782 }
783}
784
785/* convert hw value with given bit_precision to lut property val */
786static u32 intel_color_lut_pack(u32 val, int bit_precision)
787{
788 if (bit_precision > 16)
789 return DIV_ROUND_CLOSEST_ULL(mul_u32_u32(val, (1 << 16) - 1),
790 (1 << bit_precision) - 1);
791 else
792 return DIV_ROUND_CLOSEST(val * ((1 << 16) - 1),
793 (1 << bit_precision) - 1);
794}
795
796static u32 i9xx_lut_8(const struct drm_color_lut *color)
797{
798 return REG_FIELD_PREP(PALETTE_RED_MASK, drm_color_lut_extract(color->red, 8)) |
799 REG_FIELD_PREP(PALETTE_GREEN_MASK, drm_color_lut_extract(color->green, 8)) |
800 REG_FIELD_PREP(PALETTE_BLUE_MASK, drm_color_lut_extract(color->blue, 8));
801}
802
803static void i9xx_lut_8_pack(struct drm_color_lut *entry, u32 val)
804{
805 entry->red = intel_color_lut_pack(REG_FIELD_GET(PALETTE_RED_MASK, val), bit_precision: 8);
806 entry->green = intel_color_lut_pack(REG_FIELD_GET(PALETTE_GREEN_MASK, val), bit_precision: 8);
807 entry->blue = intel_color_lut_pack(REG_FIELD_GET(PALETTE_BLUE_MASK, val), bit_precision: 8);
808}
809
810/* i8xx/i9xx+ 10bit slope format "even DW" (low 8 bits) */
811static u32 _i9xx_lut_10_ldw(u16 a)
812{
813 return drm_color_lut_extract(user_input: a, bit_precision: 10) & 0xff;
814}
815
816static u32 i9xx_lut_10_ldw(const struct drm_color_lut *color)
817{
818 return REG_FIELD_PREP(PALETTE_RED_MASK, _i9xx_lut_10_ldw(color[0].red)) |
819 REG_FIELD_PREP(PALETTE_GREEN_MASK, _i9xx_lut_10_ldw(color[0].green)) |
820 REG_FIELD_PREP(PALETTE_BLUE_MASK, _i9xx_lut_10_ldw(color[0].blue));
821}
822
823/* i8xx/i9xx+ 10bit slope format "odd DW" (high 2 bits + slope) */
824static u32 _i9xx_lut_10_udw(u16 a, u16 b)
825{
826 unsigned int mantissa, exponent;
827
828 a = drm_color_lut_extract(user_input: a, bit_precision: 10);
829 b = drm_color_lut_extract(user_input: b, bit_precision: 10);
830
831 /* b = a + 8 * m * 2 ^ -e */
832 mantissa = clamp(b - a, 0, 0x7f);
833 exponent = 3;
834 while (mantissa > 0xf) {
835 mantissa >>= 1;
836 exponent--;
837 }
838
839 return (exponent << 6) |
840 (mantissa << 2) |
841 (a >> 8);
842}
843
844static u32 i9xx_lut_10_udw(const struct drm_color_lut *color)
845{
846 return REG_FIELD_PREP(PALETTE_RED_MASK, _i9xx_lut_10_udw(color[0].red, color[1].red)) |
847 REG_FIELD_PREP(PALETTE_GREEN_MASK, _i9xx_lut_10_udw(color[0].green, color[1].green)) |
848 REG_FIELD_PREP(PALETTE_BLUE_MASK, _i9xx_lut_10_udw(color[0].blue, color[1].blue));
849}
850
851static void i9xx_lut_10_pack(struct drm_color_lut *color,
852 u32 ldw, u32 udw)
853{
854 u16 red = REG_FIELD_GET(PALETTE_10BIT_RED_LDW_MASK, ldw) |
855 REG_FIELD_GET(PALETTE_10BIT_RED_UDW_MASK, udw) << 8;
856 u16 green = REG_FIELD_GET(PALETTE_10BIT_GREEN_LDW_MASK, ldw) |
857 REG_FIELD_GET(PALETTE_10BIT_GREEN_UDW_MASK, udw) << 8;
858 u16 blue = REG_FIELD_GET(PALETTE_10BIT_BLUE_LDW_MASK, ldw) |
859 REG_FIELD_GET(PALETTE_10BIT_BLUE_UDW_MASK, udw) << 8;
860
861 color->red = intel_color_lut_pack(val: red, bit_precision: 10);
862 color->green = intel_color_lut_pack(val: green, bit_precision: 10);
863 color->blue = intel_color_lut_pack(val: blue, bit_precision: 10);
864}
865
866static void i9xx_lut_10_pack_slope(struct drm_color_lut *color,
867 u32 ldw, u32 udw)
868{
869 int r_exp = REG_FIELD_GET(PALETTE_10BIT_RED_EXP_MASK, udw);
870 int r_mant = REG_FIELD_GET(PALETTE_10BIT_RED_MANT_MASK, udw);
871 int g_exp = REG_FIELD_GET(PALETTE_10BIT_GREEN_EXP_MASK, udw);
872 int g_mant = REG_FIELD_GET(PALETTE_10BIT_GREEN_MANT_MASK, udw);
873 int b_exp = REG_FIELD_GET(PALETTE_10BIT_BLUE_EXP_MASK, udw);
874 int b_mant = REG_FIELD_GET(PALETTE_10BIT_BLUE_MANT_MASK, udw);
875
876 i9xx_lut_10_pack(color, ldw, udw);
877
878 color->red += r_mant << (3 - r_exp);
879 color->green += g_mant << (3 - g_exp);
880 color->blue += b_mant << (3 - b_exp);
881}
882
883/* i965+ "10.6" bit interpolated format "even DW" (low 8 bits) */
884static u32 i965_lut_10p6_ldw(const struct drm_color_lut *color)
885{
886 return REG_FIELD_PREP(PALETTE_RED_MASK, color->red & 0xff) |
887 REG_FIELD_PREP(PALETTE_GREEN_MASK, color->green & 0xff) |
888 REG_FIELD_PREP(PALETTE_BLUE_MASK, color->blue & 0xff);
889}
890
891/* i965+ "10.6" interpolated format "odd DW" (high 8 bits) */
892static u32 i965_lut_10p6_udw(const struct drm_color_lut *color)
893{
894 return REG_FIELD_PREP(PALETTE_RED_MASK, color->red >> 8) |
895 REG_FIELD_PREP(PALETTE_GREEN_MASK, color->green >> 8) |
896 REG_FIELD_PREP(PALETTE_BLUE_MASK, color->blue >> 8);
897}
898
899static void i965_lut_10p6_pack(struct drm_color_lut *entry, u32 ldw, u32 udw)
900{
901 entry->red = REG_FIELD_GET(PALETTE_RED_MASK, udw) << 8 |
902 REG_FIELD_GET(PALETTE_RED_MASK, ldw);
903 entry->green = REG_FIELD_GET(PALETTE_GREEN_MASK, udw) << 8 |
904 REG_FIELD_GET(PALETTE_GREEN_MASK, ldw);
905 entry->blue = REG_FIELD_GET(PALETTE_BLUE_MASK, udw) << 8 |
906 REG_FIELD_GET(PALETTE_BLUE_MASK, ldw);
907}
908
909static u16 i965_lut_11p6_max_pack(u32 val)
910{
911 /* PIPEGCMAX is 11.6, clamp to 10.6 */
912 return min(val, 0xffffu);
913}
914
915static u32 ilk_lut_10(const struct drm_color_lut *color)
916{
917 return REG_FIELD_PREP(PREC_PALETTE_10_RED_MASK, drm_color_lut_extract(color->red, 10)) |
918 REG_FIELD_PREP(PREC_PALETTE_10_GREEN_MASK, drm_color_lut_extract(color->green, 10)) |
919 REG_FIELD_PREP(PREC_PALETTE_10_BLUE_MASK, drm_color_lut_extract(color->blue, 10));
920}
921
922static void ilk_lut_10_pack(struct drm_color_lut *entry, u32 val)
923{
924 entry->red = intel_color_lut_pack(REG_FIELD_GET(PREC_PALETTE_10_RED_MASK, val), bit_precision: 10);
925 entry->green = intel_color_lut_pack(REG_FIELD_GET(PREC_PALETTE_10_GREEN_MASK, val), bit_precision: 10);
926 entry->blue = intel_color_lut_pack(REG_FIELD_GET(PREC_PALETTE_10_BLUE_MASK, val), bit_precision: 10);
927}
928
929/* ilk+ "12.4" interpolated format (low 6 bits) */
930static u32 ilk_lut_12p4_ldw(const struct drm_color_lut *color)
931{
932 return REG_FIELD_PREP(PREC_PALETTE_12P4_RED_LDW_MASK, color->red & 0x3f) |
933 REG_FIELD_PREP(PREC_PALETTE_12P4_GREEN_LDW_MASK, color->green & 0x3f) |
934 REG_FIELD_PREP(PREC_PALETTE_12P4_BLUE_LDW_MASK, color->blue & 0x3f);
935}
936
937/* ilk+ "12.4" interpolated format (high 10 bits) */
938static u32 ilk_lut_12p4_udw(const struct drm_color_lut *color)
939{
940 return REG_FIELD_PREP(PREC_PALETTE_12P4_RED_UDW_MASK, color->red >> 6) |
941 REG_FIELD_PREP(PREC_PALETTE_12P4_GREEN_UDW_MASK, color->green >> 6) |
942 REG_FIELD_PREP(PREC_PALETTE_12P4_BLUE_UDW_MASK, color->blue >> 6);
943}
944
945static void ilk_lut_12p4_pack(struct drm_color_lut *entry, u32 ldw, u32 udw)
946{
947 entry->red = REG_FIELD_GET(PREC_PALETTE_12P4_RED_UDW_MASK, udw) << 6 |
948 REG_FIELD_GET(PREC_PALETTE_12P4_RED_LDW_MASK, ldw);
949 entry->green = REG_FIELD_GET(PREC_PALETTE_12P4_GREEN_UDW_MASK, udw) << 6 |
950 REG_FIELD_GET(PREC_PALETTE_12P4_GREEN_LDW_MASK, ldw);
951 entry->blue = REG_FIELD_GET(PREC_PALETTE_12P4_BLUE_UDW_MASK, udw) << 6 |
952 REG_FIELD_GET(PREC_PALETTE_12P4_BLUE_LDW_MASK, ldw);
953}
954
955static void icl_color_commit_noarm(const struct intel_crtc_state *crtc_state)
956{
957 /*
958 * Despite Wa_1406463849, ICL no longer suffers from the SKL
959 * DC5/PSR CSC black screen issue (see skl_color_commit_noarm()).
960 * Possibly due to the extra sticky CSC arming
961 * (see icl_color_post_update()).
962 *
963 * On TGL+ all CSC arming issues have been properly fixed.
964 */
965 icl_load_csc_matrix(crtc_state);
966}
967
968static void skl_color_commit_noarm(const struct intel_crtc_state *crtc_state)
969{
970 /*
971 * Possibly related to display WA #1184, SKL CSC loses the latched
972 * CSC coeff/offset register values if the CSC registers are disarmed
973 * between DC5 exit and PSR exit. This will cause the plane(s) to
974 * output all black (until CSC_MODE is rearmed and properly latched).
975 * Once PSR exit (and proper register latching) has occurred the
976 * danger is over. Thus when PSR is enabled the CSC coeff/offset
977 * register programming will be peformed from skl_color_commit_arm()
978 * which is called after PSR exit.
979 */
980 if (!crtc_state->has_psr)
981 ilk_load_csc_matrix(crtc_state);
982}
983
984static void ilk_color_commit_noarm(const struct intel_crtc_state *crtc_state)
985{
986 ilk_load_csc_matrix(crtc_state);
987}
988
989static void i9xx_color_commit_arm(const struct intel_crtc_state *crtc_state)
990{
991 /* update TRANSCONF GAMMA_MODE */
992 i9xx_set_pipeconf(crtc_state);
993}
994
995static void ilk_color_commit_arm(const struct intel_crtc_state *crtc_state)
996{
997 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
998 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
999
1000 /* update TRANSCONF GAMMA_MODE */
1001 ilk_set_pipeconf(crtc_state);
1002
1003 intel_de_write_fw(i915, PIPE_CSC_MODE(crtc->pipe),
1004 val: crtc_state->csc_mode);
1005}
1006
1007static void hsw_color_commit_arm(const struct intel_crtc_state *crtc_state)
1008{
1009 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1010 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
1011
1012 intel_de_write(i915, GAMMA_MODE(crtc->pipe),
1013 val: crtc_state->gamma_mode);
1014
1015 intel_de_write_fw(i915, PIPE_CSC_MODE(crtc->pipe),
1016 val: crtc_state->csc_mode);
1017}
1018
1019static u32 hsw_read_gamma_mode(struct intel_crtc *crtc)
1020{
1021 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
1022
1023 return intel_de_read(i915, GAMMA_MODE(crtc->pipe));
1024}
1025
1026static u32 ilk_read_csc_mode(struct intel_crtc *crtc)
1027{
1028 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
1029
1030 return intel_de_read(i915, PIPE_CSC_MODE(crtc->pipe));
1031}
1032
1033static void i9xx_get_config(struct intel_crtc_state *crtc_state)
1034{
1035 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1036 struct intel_plane *plane = to_intel_plane(crtc->base.primary);
1037 struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev);
1038 enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
1039 u32 tmp;
1040
1041 tmp = intel_de_read(i915: dev_priv, DSPCNTR(i9xx_plane));
1042
1043 if (tmp & DISP_PIPE_GAMMA_ENABLE)
1044 crtc_state->gamma_enable = true;
1045
1046 if (!HAS_GMCH(dev_priv) && tmp & DISP_PIPE_CSC_ENABLE)
1047 crtc_state->csc_enable = true;
1048}
1049
1050static void hsw_get_config(struct intel_crtc_state *crtc_state)
1051{
1052 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1053
1054 crtc_state->gamma_mode = hsw_read_gamma_mode(crtc);
1055 crtc_state->csc_mode = ilk_read_csc_mode(crtc);
1056
1057 i9xx_get_config(crtc_state);
1058}
1059
1060static void skl_get_config(struct intel_crtc_state *crtc_state)
1061{
1062 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1063 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
1064 u32 tmp;
1065
1066 crtc_state->gamma_mode = hsw_read_gamma_mode(crtc);
1067 crtc_state->csc_mode = ilk_read_csc_mode(crtc);
1068
1069 tmp = intel_de_read(i915, SKL_BOTTOM_COLOR(crtc->pipe));
1070
1071 if (tmp & SKL_BOTTOM_COLOR_GAMMA_ENABLE)
1072 crtc_state->gamma_enable = true;
1073
1074 if (tmp & SKL_BOTTOM_COLOR_CSC_ENABLE)
1075 crtc_state->csc_enable = true;
1076}
1077
1078static void skl_color_commit_arm(const struct intel_crtc_state *crtc_state)
1079{
1080 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1081 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
1082 enum pipe pipe = crtc->pipe;
1083 u32 val = 0;
1084
1085 if (crtc_state->has_psr)
1086 ilk_load_csc_matrix(crtc_state);
1087
1088 /*
1089 * We don't (yet) allow userspace to control the pipe background color,
1090 * so force it to black, but apply pipe gamma and CSC appropriately
1091 * so that its handling will match how we program our planes.
1092 */
1093 if (crtc_state->gamma_enable)
1094 val |= SKL_BOTTOM_COLOR_GAMMA_ENABLE;
1095 if (crtc_state->csc_enable)
1096 val |= SKL_BOTTOM_COLOR_CSC_ENABLE;
1097 intel_de_write(i915, SKL_BOTTOM_COLOR(pipe), val);
1098
1099 intel_de_write(i915, GAMMA_MODE(crtc->pipe),
1100 val: crtc_state->gamma_mode);
1101
1102 intel_de_write_fw(i915, PIPE_CSC_MODE(crtc->pipe),
1103 val: crtc_state->csc_mode);
1104}
1105
1106static void icl_color_commit_arm(const struct intel_crtc_state *crtc_state)
1107{
1108 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1109 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
1110 enum pipe pipe = crtc->pipe;
1111
1112 /*
1113 * We don't (yet) allow userspace to control the pipe background color,
1114 * so force it to black.
1115 */
1116 intel_de_write(i915, SKL_BOTTOM_COLOR(pipe), val: 0);
1117
1118 intel_de_write(i915, GAMMA_MODE(crtc->pipe),
1119 val: crtc_state->gamma_mode);
1120
1121 intel_de_write_fw(i915, PIPE_CSC_MODE(crtc->pipe),
1122 val: crtc_state->csc_mode);
1123}
1124
1125static void icl_color_post_update(const struct intel_crtc_state *crtc_state)
1126{
1127 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1128 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
1129
1130 /*
1131 * Despite Wa_1406463849, ICL CSC is no longer disarmed by
1132 * coeff/offset register *writes*. Instead, once CSC_MODE
1133 * is armed it stays armed, even after it has been latched.
1134 * Afterwards the coeff/offset registers become effectively
1135 * self-arming. That self-arming must be disabled before the
1136 * next icl_color_commit_noarm() tries to write the next set
1137 * of coeff/offset registers. Fortunately register *reads*
1138 * do still disarm the CSC. Naturally this must not be done
1139 * until the previously written CSC registers have actually
1140 * been latched.
1141 *
1142 * TGL+ no longer need this workaround.
1143 */
1144 intel_de_read_fw(i915, PIPE_CSC_PREOFF_HI(crtc->pipe));
1145}
1146
1147static struct drm_property_blob *
1148create_linear_lut(struct drm_i915_private *i915, int lut_size)
1149{
1150 struct drm_property_blob *blob;
1151 struct drm_color_lut *lut;
1152 int i;
1153
1154 blob = drm_property_create_blob(dev: &i915->drm,
1155 length: sizeof(lut[0]) * lut_size,
1156 NULL);
1157 if (IS_ERR(ptr: blob))
1158 return blob;
1159
1160 lut = blob->data;
1161
1162 for (i = 0; i < lut_size; i++) {
1163 u16 val = 0xffff * i / (lut_size - 1);
1164
1165 lut[i].red = val;
1166 lut[i].green = val;
1167 lut[i].blue = val;
1168 }
1169
1170 return blob;
1171}
1172
1173static u16 lut_limited_range(unsigned int value)
1174{
1175 unsigned int min = 16 << 8;
1176 unsigned int max = 235 << 8;
1177
1178 return value * (max - min) / 0xffff + min;
1179}
1180
1181static struct drm_property_blob *
1182create_resized_lut(struct drm_i915_private *i915,
1183 const struct drm_property_blob *blob_in, int lut_out_size,
1184 bool limited_color_range)
1185{
1186 int i, lut_in_size = drm_color_lut_size(blob: blob_in);
1187 struct drm_property_blob *blob_out;
1188 const struct drm_color_lut *lut_in;
1189 struct drm_color_lut *lut_out;
1190
1191 blob_out = drm_property_create_blob(dev: &i915->drm,
1192 length: sizeof(lut_out[0]) * lut_out_size,
1193 NULL);
1194 if (IS_ERR(ptr: blob_out))
1195 return blob_out;
1196
1197 lut_in = blob_in->data;
1198 lut_out = blob_out->data;
1199
1200 for (i = 0; i < lut_out_size; i++) {
1201 const struct drm_color_lut *entry =
1202 &lut_in[i * (lut_in_size - 1) / (lut_out_size - 1)];
1203
1204 if (limited_color_range) {
1205 lut_out[i].red = lut_limited_range(value: entry->red);
1206 lut_out[i].green = lut_limited_range(value: entry->green);
1207 lut_out[i].blue = lut_limited_range(value: entry->blue);
1208 } else {
1209 lut_out[i] = *entry;
1210 }
1211 }
1212
1213 return blob_out;
1214}
1215
1216static void i9xx_load_lut_8(struct intel_crtc *crtc,
1217 const struct drm_property_blob *blob)
1218{
1219 struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev);
1220 const struct drm_color_lut *lut;
1221 enum pipe pipe = crtc->pipe;
1222 int i;
1223
1224 if (!blob)
1225 return;
1226
1227 lut = blob->data;
1228
1229 for (i = 0; i < 256; i++)
1230 intel_de_write_fw(i915: dev_priv, PALETTE(pipe, i),
1231 val: i9xx_lut_8(color: &lut[i]));
1232}
1233
1234static void i9xx_load_lut_10(struct intel_crtc *crtc,
1235 const struct drm_property_blob *blob)
1236{
1237 struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev);
1238 const struct drm_color_lut *lut = blob->data;
1239 int i, lut_size = drm_color_lut_size(blob);
1240 enum pipe pipe = crtc->pipe;
1241
1242 for (i = 0; i < lut_size - 1; i++) {
1243 intel_de_write_fw(i915: dev_priv, PALETTE(pipe, 2 * i + 0),
1244 val: i9xx_lut_10_ldw(color: &lut[i]));
1245 intel_de_write_fw(i915: dev_priv, PALETTE(pipe, 2 * i + 1),
1246 val: i9xx_lut_10_udw(color: &lut[i]));
1247 }
1248}
1249
1250static void i9xx_load_luts(const struct intel_crtc_state *crtc_state)
1251{
1252 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1253 const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut;
1254
1255 switch (crtc_state->gamma_mode) {
1256 case GAMMA_MODE_MODE_8BIT:
1257 i9xx_load_lut_8(crtc, blob: post_csc_lut);
1258 break;
1259 case GAMMA_MODE_MODE_10BIT:
1260 i9xx_load_lut_10(crtc, blob: post_csc_lut);
1261 break;
1262 default:
1263 MISSING_CASE(crtc_state->gamma_mode);
1264 break;
1265 }
1266}
1267
1268static void i965_load_lut_10p6(struct intel_crtc *crtc,
1269 const struct drm_property_blob *blob)
1270{
1271 struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev);
1272 const struct drm_color_lut *lut = blob->data;
1273 int i, lut_size = drm_color_lut_size(blob);
1274 enum pipe pipe = crtc->pipe;
1275
1276 for (i = 0; i < lut_size - 1; i++) {
1277 intel_de_write_fw(i915: dev_priv, PALETTE(pipe, 2 * i + 0),
1278 val: i965_lut_10p6_ldw(color: &lut[i]));
1279 intel_de_write_fw(i915: dev_priv, PALETTE(pipe, 2 * i + 1),
1280 val: i965_lut_10p6_udw(color: &lut[i]));
1281 }
1282
1283 intel_de_write_fw(i915: dev_priv, PIPEGCMAX(pipe, 0), val: lut[i].red);
1284 intel_de_write_fw(i915: dev_priv, PIPEGCMAX(pipe, 1), val: lut[i].green);
1285 intel_de_write_fw(i915: dev_priv, PIPEGCMAX(pipe, 2), val: lut[i].blue);
1286}
1287
1288static void i965_load_luts(const struct intel_crtc_state *crtc_state)
1289{
1290 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1291 const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut;
1292
1293 switch (crtc_state->gamma_mode) {
1294 case GAMMA_MODE_MODE_8BIT:
1295 i9xx_load_lut_8(crtc, blob: post_csc_lut);
1296 break;
1297 case GAMMA_MODE_MODE_10BIT:
1298 i965_load_lut_10p6(crtc, blob: post_csc_lut);
1299 break;
1300 default:
1301 MISSING_CASE(crtc_state->gamma_mode);
1302 break;
1303 }
1304}
1305
1306static void ilk_lut_write(const struct intel_crtc_state *crtc_state,
1307 i915_reg_t reg, u32 val)
1308{
1309 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
1310
1311 if (crtc_state->dsb)
1312 intel_dsb_reg_write(dsb: crtc_state->dsb, reg, val);
1313 else
1314 intel_de_write_fw(i915, reg, val);
1315}
1316
1317static void ilk_load_lut_8(const struct intel_crtc_state *crtc_state,
1318 const struct drm_property_blob *blob)
1319{
1320 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1321 const struct drm_color_lut *lut;
1322 enum pipe pipe = crtc->pipe;
1323 int i;
1324
1325 if (!blob)
1326 return;
1327
1328 lut = blob->data;
1329
1330 /*
1331 * DSB fails to correctly load the legacy LUT
1332 * unless we either write each entry twice,
1333 * or use non-posted writes
1334 */
1335 if (crtc_state->dsb)
1336 intel_dsb_nonpost_start(dsb: crtc_state->dsb);
1337
1338 for (i = 0; i < 256; i++)
1339 ilk_lut_write(crtc_state, LGC_PALETTE(pipe, i),
1340 val: i9xx_lut_8(color: &lut[i]));
1341
1342 if (crtc_state->dsb)
1343 intel_dsb_nonpost_end(dsb: crtc_state->dsb);
1344}
1345
1346static void ilk_load_lut_10(const struct intel_crtc_state *crtc_state,
1347 const struct drm_property_blob *blob)
1348{
1349 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1350 const struct drm_color_lut *lut = blob->data;
1351 int i, lut_size = drm_color_lut_size(blob);
1352 enum pipe pipe = crtc->pipe;
1353
1354 for (i = 0; i < lut_size; i++)
1355 ilk_lut_write(crtc_state, PREC_PALETTE(pipe, i),
1356 val: ilk_lut_10(color: &lut[i]));
1357}
1358
1359static void ilk_load_luts(const struct intel_crtc_state *crtc_state)
1360{
1361 const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut;
1362 const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut;
1363 const struct drm_property_blob *blob = post_csc_lut ?: pre_csc_lut;
1364
1365 switch (crtc_state->gamma_mode) {
1366 case GAMMA_MODE_MODE_8BIT:
1367 ilk_load_lut_8(crtc_state, blob);
1368 break;
1369 case GAMMA_MODE_MODE_10BIT:
1370 ilk_load_lut_10(crtc_state, blob);
1371 break;
1372 default:
1373 MISSING_CASE(crtc_state->gamma_mode);
1374 break;
1375 }
1376}
1377
1378static int ivb_lut_10_size(u32 prec_index)
1379{
1380 if (prec_index & PAL_PREC_SPLIT_MODE)
1381 return 512;
1382 else
1383 return 1024;
1384}
1385
1386/*
1387 * IVB/HSW Bspec / PAL_PREC_INDEX:
1388 * "Restriction : Index auto increment mode is not
1389 * supported and must not be enabled."
1390 */
1391static void ivb_load_lut_10(const struct intel_crtc_state *crtc_state,
1392 const struct drm_property_blob *blob,
1393 u32 prec_index)
1394{
1395 const struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1396 const struct drm_color_lut *lut = blob->data;
1397 int i, lut_size = drm_color_lut_size(blob);
1398 enum pipe pipe = crtc->pipe;
1399
1400 for (i = 0; i < lut_size; i++) {
1401 ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe),
1402 val: prec_index + i);
1403 ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe),
1404 val: ilk_lut_10(color: &lut[i]));
1405 }
1406
1407 /*
1408 * Reset the index, otherwise it prevents the legacy palette to be
1409 * written properly.
1410 */
1411 ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe),
1412 PAL_PREC_INDEX_VALUE(0));
1413}
1414
1415/* On BDW+ the index auto increment mode actually works */
1416static void bdw_load_lut_10(const struct intel_crtc_state *crtc_state,
1417 const struct drm_property_blob *blob,
1418 u32 prec_index)
1419{
1420 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1421 const struct drm_color_lut *lut = blob->data;
1422 int i, lut_size = drm_color_lut_size(blob);
1423 enum pipe pipe = crtc->pipe;
1424
1425 ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe),
1426 val: prec_index);
1427 ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe),
1428 PAL_PREC_AUTO_INCREMENT |
1429 prec_index);
1430
1431 for (i = 0; i < lut_size; i++)
1432 ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe),
1433 val: ilk_lut_10(color: &lut[i]));
1434
1435 /*
1436 * Reset the index, otherwise it prevents the legacy palette to be
1437 * written properly.
1438 */
1439 ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe),
1440 PAL_PREC_INDEX_VALUE(0));
1441}
1442
1443static void ivb_load_lut_ext_max(const struct intel_crtc_state *crtc_state)
1444{
1445 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1446 enum pipe pipe = crtc->pipe;
1447
1448 /* Program the max register to clamp values > 1.0. */
1449 ilk_lut_write(crtc_state, PREC_PAL_EXT_GC_MAX(pipe, 0), val: 1 << 16);
1450 ilk_lut_write(crtc_state, PREC_PAL_EXT_GC_MAX(pipe, 1), val: 1 << 16);
1451 ilk_lut_write(crtc_state, PREC_PAL_EXT_GC_MAX(pipe, 2), val: 1 << 16);
1452}
1453
1454static void glk_load_lut_ext2_max(const struct intel_crtc_state *crtc_state)
1455{
1456 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1457 enum pipe pipe = crtc->pipe;
1458
1459 /* Program the max register to clamp values > 1.0. */
1460 ilk_lut_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 0), val: 1 << 16);
1461 ilk_lut_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 1), val: 1 << 16);
1462 ilk_lut_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 2), val: 1 << 16);
1463}
1464
1465static void ivb_load_luts(const struct intel_crtc_state *crtc_state)
1466{
1467 const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut;
1468 const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut;
1469 const struct drm_property_blob *blob = post_csc_lut ?: pre_csc_lut;
1470
1471 switch (crtc_state->gamma_mode) {
1472 case GAMMA_MODE_MODE_8BIT:
1473 ilk_load_lut_8(crtc_state, blob);
1474 break;
1475 case GAMMA_MODE_MODE_SPLIT:
1476 ivb_load_lut_10(crtc_state, blob: pre_csc_lut, PAL_PREC_SPLIT_MODE |
1477 PAL_PREC_INDEX_VALUE(0));
1478 ivb_load_lut_ext_max(crtc_state);
1479 ivb_load_lut_10(crtc_state, blob: post_csc_lut, PAL_PREC_SPLIT_MODE |
1480 PAL_PREC_INDEX_VALUE(512));
1481 break;
1482 case GAMMA_MODE_MODE_10BIT:
1483 ivb_load_lut_10(crtc_state, blob,
1484 PAL_PREC_INDEX_VALUE(0));
1485 ivb_load_lut_ext_max(crtc_state);
1486 break;
1487 default:
1488 MISSING_CASE(crtc_state->gamma_mode);
1489 break;
1490 }
1491}
1492
1493static void bdw_load_luts(const struct intel_crtc_state *crtc_state)
1494{
1495 const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut;
1496 const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut;
1497 const struct drm_property_blob *blob = post_csc_lut ?: pre_csc_lut;
1498
1499 switch (crtc_state->gamma_mode) {
1500 case GAMMA_MODE_MODE_8BIT:
1501 ilk_load_lut_8(crtc_state, blob);
1502 break;
1503 case GAMMA_MODE_MODE_SPLIT:
1504 bdw_load_lut_10(crtc_state, blob: pre_csc_lut, PAL_PREC_SPLIT_MODE |
1505 PAL_PREC_INDEX_VALUE(0));
1506 ivb_load_lut_ext_max(crtc_state);
1507 bdw_load_lut_10(crtc_state, blob: post_csc_lut, PAL_PREC_SPLIT_MODE |
1508 PAL_PREC_INDEX_VALUE(512));
1509 break;
1510 case GAMMA_MODE_MODE_10BIT:
1511 bdw_load_lut_10(crtc_state, blob,
1512 PAL_PREC_INDEX_VALUE(0));
1513 ivb_load_lut_ext_max(crtc_state);
1514 break;
1515 default:
1516 MISSING_CASE(crtc_state->gamma_mode);
1517 break;
1518 }
1519}
1520
1521static int glk_degamma_lut_size(struct drm_i915_private *i915)
1522{
1523 if (DISPLAY_VER(i915) >= 13)
1524 return 131;
1525 else
1526 return 35;
1527}
1528
1529static u32 glk_degamma_lut(const struct drm_color_lut *color)
1530{
1531 return color->green;
1532}
1533
1534static void glk_degamma_lut_pack(struct drm_color_lut *entry, u32 val)
1535{
1536 /* PRE_CSC_GAMC_DATA is 3.16, clamp to 0.16 */
1537 entry->red = entry->green = entry->blue = min(val, 0xffffu);
1538}
1539
1540static u32 mtl_degamma_lut(const struct drm_color_lut *color)
1541{
1542 return drm_color_lut_extract(user_input: color->green, bit_precision: 24);
1543}
1544
1545static void mtl_degamma_lut_pack(struct drm_color_lut *entry, u32 val)
1546{
1547 /* PRE_CSC_GAMC_DATA is 3.24, clamp to 0.16 */
1548 entry->red = entry->green = entry->blue =
1549 intel_color_lut_pack(min(val, 0xffffffu), bit_precision: 24);
1550}
1551
1552static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state,
1553 const struct drm_property_blob *blob)
1554{
1555 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1556 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
1557 const struct drm_color_lut *lut = blob->data;
1558 int i, lut_size = drm_color_lut_size(blob);
1559 enum pipe pipe = crtc->pipe;
1560
1561 /*
1562 * When setting the auto-increment bit, the hardware seems to
1563 * ignore the index bits, so we need to reset it to index 0
1564 * separately.
1565 */
1566 ilk_lut_write(crtc_state, PRE_CSC_GAMC_INDEX(pipe),
1567 PRE_CSC_GAMC_INDEX_VALUE(0));
1568 ilk_lut_write(crtc_state, PRE_CSC_GAMC_INDEX(pipe),
1569 PRE_CSC_GAMC_AUTO_INCREMENT |
1570 PRE_CSC_GAMC_INDEX_VALUE(0));
1571
1572 for (i = 0; i < lut_size; i++) {
1573 /*
1574 * First lut_size entries represent range from 0 to 1.0
1575 * 3 additional lut entries will represent extended range
1576 * inputs 3.0 and 7.0 respectively, currently clamped
1577 * at 1.0. Since the precision is 16bit, the user
1578 * value can be directly filled to register.
1579 * The pipe degamma table in GLK+ onwards doesn't
1580 * support different values per channel, so this just
1581 * programs green value which will be equal to Red and
1582 * Blue into the lut registers.
1583 * ToDo: Extend to max 7.0. Enable 32 bit input value
1584 * as compared to just 16 to achieve this.
1585 */
1586 ilk_lut_write(crtc_state, PRE_CSC_GAMC_DATA(pipe),
1587 DISPLAY_VER(i915) >= 14 ?
1588 mtl_degamma_lut(color: &lut[i]) : glk_degamma_lut(color: &lut[i]));
1589 }
1590
1591 /* Clamp values > 1.0. */
1592 while (i++ < glk_degamma_lut_size(i915))
1593 ilk_lut_write(crtc_state, PRE_CSC_GAMC_DATA(pipe),
1594 DISPLAY_VER(i915) >= 14 ?
1595 1 << 24 : 1 << 16);
1596
1597 ilk_lut_write(crtc_state, PRE_CSC_GAMC_INDEX(pipe), val: 0);
1598}
1599
1600static void glk_load_luts(const struct intel_crtc_state *crtc_state)
1601{
1602 const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut;
1603 const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut;
1604
1605 if (pre_csc_lut)
1606 glk_load_degamma_lut(crtc_state, blob: pre_csc_lut);
1607
1608 switch (crtc_state->gamma_mode) {
1609 case GAMMA_MODE_MODE_8BIT:
1610 ilk_load_lut_8(crtc_state, blob: post_csc_lut);
1611 break;
1612 case GAMMA_MODE_MODE_10BIT:
1613 bdw_load_lut_10(crtc_state, blob: post_csc_lut, PAL_PREC_INDEX_VALUE(0));
1614 ivb_load_lut_ext_max(crtc_state);
1615 glk_load_lut_ext2_max(crtc_state);
1616 break;
1617 default:
1618 MISSING_CASE(crtc_state->gamma_mode);
1619 break;
1620 }
1621}
1622
1623static void
1624ivb_load_lut_max(const struct intel_crtc_state *crtc_state,
1625 const struct drm_color_lut *color)
1626{
1627 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1628 enum pipe pipe = crtc->pipe;
1629
1630 /* FIXME LUT entries are 16 bit only, so we can prog 0xFFFF max */
1631 ilk_lut_write(crtc_state, PREC_PAL_GC_MAX(pipe, 0), val: color->red);
1632 ilk_lut_write(crtc_state, PREC_PAL_GC_MAX(pipe, 1), val: color->green);
1633 ilk_lut_write(crtc_state, PREC_PAL_GC_MAX(pipe, 2), val: color->blue);
1634}
1635
1636static void
1637icl_program_gamma_superfine_segment(const struct intel_crtc_state *crtc_state)
1638{
1639 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1640 const struct drm_property_blob *blob = crtc_state->post_csc_lut;
1641 const struct drm_color_lut *lut = blob->data;
1642 enum pipe pipe = crtc->pipe;
1643 int i;
1644
1645 /*
1646 * Program Super Fine segment (let's call it seg1)...
1647 *
1648 * Super Fine segment's step is 1/(8 * 128 * 256) and it has
1649 * 9 entries, corresponding to values 0, 1/(8 * 128 * 256),
1650 * 2/(8 * 128 * 256) ... 8/(8 * 128 * 256).
1651 */
1652 ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_INDEX(pipe),
1653 PAL_PREC_MULTI_SEG_INDEX_VALUE(0));
1654 ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_INDEX(pipe),
1655 PAL_PREC_AUTO_INCREMENT |
1656 PAL_PREC_MULTI_SEG_INDEX_VALUE(0));
1657
1658 for (i = 0; i < 9; i++) {
1659 const struct drm_color_lut *entry = &lut[i];
1660
1661 ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe),
1662 val: ilk_lut_12p4_ldw(color: entry));
1663 ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe),
1664 val: ilk_lut_12p4_udw(color: entry));
1665 }
1666
1667 ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_INDEX(pipe),
1668 PAL_PREC_MULTI_SEG_INDEX_VALUE(0));
1669}
1670
1671static void
1672icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state)
1673{
1674 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1675 const struct drm_property_blob *blob = crtc_state->post_csc_lut;
1676 const struct drm_color_lut *lut = blob->data;
1677 const struct drm_color_lut *entry;
1678 enum pipe pipe = crtc->pipe;
1679 int i;
1680
1681 /*
1682 * Program Fine segment (let's call it seg2)...
1683 *
1684 * Fine segment's step is 1/(128 * 256) i.e. 1/(128 * 256), 2/(128 * 256)
1685 * ... 256/(128 * 256). So in order to program fine segment of LUT we
1686 * need to pick every 8th entry in the LUT, and program 256 indexes.
1687 *
1688 * PAL_PREC_INDEX[0] and PAL_PREC_INDEX[1] map to seg2[1],
1689 * seg2[0] being unused by the hardware.
1690 */
1691 ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe),
1692 PAL_PREC_INDEX_VALUE(0));
1693 ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe),
1694 PAL_PREC_AUTO_INCREMENT |
1695 PAL_PREC_INDEX_VALUE(0));
1696
1697 for (i = 1; i < 257; i++) {
1698 entry = &lut[i * 8];
1699
1700 ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe),
1701 val: ilk_lut_12p4_ldw(color: entry));
1702 ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe),
1703 val: ilk_lut_12p4_udw(color: entry));
1704 }
1705
1706 /*
1707 * Program Coarse segment (let's call it seg3)...
1708 *
1709 * Coarse segment starts from index 0 and it's step is 1/256 ie 0,
1710 * 1/256, 2/256 ... 256/256. As per the description of each entry in LUT
1711 * above, we need to pick every (8 * 128)th entry in LUT, and
1712 * program 256 of those.
1713 *
1714 * Spec is not very clear about if entries seg3[0] and seg3[1] are
1715 * being used or not, but we still need to program these to advance
1716 * the index.
1717 */
1718 for (i = 0; i < 256; i++) {
1719 entry = &lut[i * 8 * 128];
1720
1721 ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe),
1722 val: ilk_lut_12p4_ldw(color: entry));
1723 ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe),
1724 val: ilk_lut_12p4_udw(color: entry));
1725 }
1726
1727 ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe),
1728 PAL_PREC_INDEX_VALUE(0));
1729
1730 /* The last entry in the LUT is to be programmed in GCMAX */
1731 entry = &lut[256 * 8 * 128];
1732 ivb_load_lut_max(crtc_state, color: entry);
1733}
1734
1735static void icl_load_luts(const struct intel_crtc_state *crtc_state)
1736{
1737 const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut;
1738 const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut;
1739
1740 if (pre_csc_lut)
1741 glk_load_degamma_lut(crtc_state, blob: pre_csc_lut);
1742
1743 switch (crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) {
1744 case GAMMA_MODE_MODE_8BIT:
1745 ilk_load_lut_8(crtc_state, blob: post_csc_lut);
1746 break;
1747 case GAMMA_MODE_MODE_12BIT_MULTI_SEG:
1748 icl_program_gamma_superfine_segment(crtc_state);
1749 icl_program_gamma_multi_segment(crtc_state);
1750 ivb_load_lut_ext_max(crtc_state);
1751 glk_load_lut_ext2_max(crtc_state);
1752 break;
1753 case GAMMA_MODE_MODE_10BIT:
1754 bdw_load_lut_10(crtc_state, blob: post_csc_lut, PAL_PREC_INDEX_VALUE(0));
1755 ivb_load_lut_ext_max(crtc_state);
1756 glk_load_lut_ext2_max(crtc_state);
1757 break;
1758 default:
1759 MISSING_CASE(crtc_state->gamma_mode);
1760 break;
1761 }
1762}
1763
1764static void vlv_load_luts(const struct intel_crtc_state *crtc_state)
1765{
1766 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1767
1768 if (crtc_state->wgc_enable)
1769 vlv_load_wgc_csc(crtc, csc: &crtc_state->csc);
1770
1771 i965_load_luts(crtc_state);
1772}
1773
1774static u32 chv_cgm_degamma_ldw(const struct drm_color_lut *color)
1775{
1776 return REG_FIELD_PREP(CGM_PIPE_DEGAMMA_GREEN_LDW_MASK, drm_color_lut_extract(color->green, 14)) |
1777 REG_FIELD_PREP(CGM_PIPE_DEGAMMA_BLUE_LDW_MASK, drm_color_lut_extract(color->blue, 14));
1778}
1779
1780static u32 chv_cgm_degamma_udw(const struct drm_color_lut *color)
1781{
1782 return REG_FIELD_PREP(CGM_PIPE_DEGAMMA_RED_UDW_MASK, drm_color_lut_extract(color->red, 14));
1783}
1784
1785static void chv_cgm_degamma_pack(struct drm_color_lut *entry, u32 ldw, u32 udw)
1786{
1787 entry->green = intel_color_lut_pack(REG_FIELD_GET(CGM_PIPE_DEGAMMA_GREEN_LDW_MASK, ldw), bit_precision: 14);
1788 entry->blue = intel_color_lut_pack(REG_FIELD_GET(CGM_PIPE_DEGAMMA_BLUE_LDW_MASK, ldw), bit_precision: 14);
1789 entry->red = intel_color_lut_pack(REG_FIELD_GET(CGM_PIPE_DEGAMMA_RED_UDW_MASK, udw), bit_precision: 14);
1790}
1791
1792static void chv_load_cgm_degamma(struct intel_crtc *crtc,
1793 const struct drm_property_blob *blob)
1794{
1795 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
1796 const struct drm_color_lut *lut = blob->data;
1797 int i, lut_size = drm_color_lut_size(blob);
1798 enum pipe pipe = crtc->pipe;
1799
1800 for (i = 0; i < lut_size; i++) {
1801 intel_de_write_fw(i915, CGM_PIPE_DEGAMMA(pipe, i, 0),
1802 val: chv_cgm_degamma_ldw(color: &lut[i]));
1803 intel_de_write_fw(i915, CGM_PIPE_DEGAMMA(pipe, i, 1),
1804 val: chv_cgm_degamma_udw(color: &lut[i]));
1805 }
1806}
1807
1808static u32 chv_cgm_gamma_ldw(const struct drm_color_lut *color)
1809{
1810 return REG_FIELD_PREP(CGM_PIPE_GAMMA_GREEN_LDW_MASK, drm_color_lut_extract(color->green, 10)) |
1811 REG_FIELD_PREP(CGM_PIPE_GAMMA_BLUE_LDW_MASK, drm_color_lut_extract(color->blue, 10));
1812}
1813
1814static u32 chv_cgm_gamma_udw(const struct drm_color_lut *color)
1815{
1816 return REG_FIELD_PREP(CGM_PIPE_GAMMA_RED_UDW_MASK, drm_color_lut_extract(color->red, 10));
1817}
1818
1819static void chv_cgm_gamma_pack(struct drm_color_lut *entry, u32 ldw, u32 udw)
1820{
1821 entry->green = intel_color_lut_pack(REG_FIELD_GET(CGM_PIPE_GAMMA_GREEN_LDW_MASK, ldw), bit_precision: 10);
1822 entry->blue = intel_color_lut_pack(REG_FIELD_GET(CGM_PIPE_GAMMA_BLUE_LDW_MASK, ldw), bit_precision: 10);
1823 entry->red = intel_color_lut_pack(REG_FIELD_GET(CGM_PIPE_GAMMA_RED_UDW_MASK, udw), bit_precision: 10);
1824}
1825
1826static void chv_load_cgm_gamma(struct intel_crtc *crtc,
1827 const struct drm_property_blob *blob)
1828{
1829 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
1830 const struct drm_color_lut *lut = blob->data;
1831 int i, lut_size = drm_color_lut_size(blob);
1832 enum pipe pipe = crtc->pipe;
1833
1834 for (i = 0; i < lut_size; i++) {
1835 intel_de_write_fw(i915, CGM_PIPE_GAMMA(pipe, i, 0),
1836 val: chv_cgm_gamma_ldw(color: &lut[i]));
1837 intel_de_write_fw(i915, CGM_PIPE_GAMMA(pipe, i, 1),
1838 val: chv_cgm_gamma_udw(color: &lut[i]));
1839 }
1840}
1841
1842static void chv_load_luts(const struct intel_crtc_state *crtc_state)
1843{
1844 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1845 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
1846 const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut;
1847 const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut;
1848
1849 if (crtc_state->cgm_mode & CGM_PIPE_MODE_CSC)
1850 chv_load_cgm_csc(crtc, csc: &crtc_state->csc);
1851
1852 if (crtc_state->cgm_mode & CGM_PIPE_MODE_DEGAMMA)
1853 chv_load_cgm_degamma(crtc, blob: pre_csc_lut);
1854
1855 if (crtc_state->cgm_mode & CGM_PIPE_MODE_GAMMA)
1856 chv_load_cgm_gamma(crtc, blob: post_csc_lut);
1857 else
1858 i965_load_luts(crtc_state);
1859
1860 intel_de_write_fw(i915, CGM_PIPE_MODE(crtc->pipe),
1861 val: crtc_state->cgm_mode);
1862}
1863
1864void intel_color_load_luts(const struct intel_crtc_state *crtc_state)
1865{
1866 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
1867
1868 if (crtc_state->dsb)
1869 return;
1870
1871 i915->display.funcs.color->load_luts(crtc_state);
1872}
1873
1874void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state)
1875{
1876 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
1877
1878 if (i915->display.funcs.color->color_commit_noarm)
1879 i915->display.funcs.color->color_commit_noarm(crtc_state);
1880}
1881
1882void intel_color_commit_arm(const struct intel_crtc_state *crtc_state)
1883{
1884 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
1885
1886 i915->display.funcs.color->color_commit_arm(crtc_state);
1887
1888 if (crtc_state->dsb)
1889 intel_dsb_commit(dsb: crtc_state->dsb, wait_for_vblank: true);
1890}
1891
1892void intel_color_post_update(const struct intel_crtc_state *crtc_state)
1893{
1894 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
1895
1896 if (i915->display.funcs.color->color_post_update)
1897 i915->display.funcs.color->color_post_update(crtc_state);
1898}
1899
1900void intel_color_prepare_commit(struct intel_crtc_state *crtc_state)
1901{
1902 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1903 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
1904
1905 if (!crtc_state->hw.active ||
1906 intel_crtc_needs_modeset(crtc_state))
1907 return;
1908
1909 if (!crtc_state->pre_csc_lut && !crtc_state->post_csc_lut)
1910 return;
1911
1912 crtc_state->dsb = intel_dsb_prepare(crtc_state, max_cmds: 1024);
1913 if (!crtc_state->dsb)
1914 return;
1915
1916 i915->display.funcs.color->load_luts(crtc_state);
1917
1918 intel_dsb_finish(dsb: crtc_state->dsb);
1919}
1920
1921void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state)
1922{
1923 if (!crtc_state->dsb)
1924 return;
1925
1926 intel_dsb_cleanup(dsb: crtc_state->dsb);
1927 crtc_state->dsb = NULL;
1928}
1929
1930void intel_color_wait_commit(const struct intel_crtc_state *crtc_state)
1931{
1932 if (crtc_state->dsb)
1933 intel_dsb_wait(dsb: crtc_state->dsb);
1934}
1935
1936bool intel_color_uses_dsb(const struct intel_crtc_state *crtc_state)
1937{
1938 return crtc_state->dsb;
1939}
1940
1941static bool intel_can_preload_luts(const struct intel_crtc_state *new_crtc_state)
1942{
1943 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
1944 struct intel_atomic_state *state =
1945 to_intel_atomic_state(new_crtc_state->uapi.state);
1946 const struct intel_crtc_state *old_crtc_state =
1947 intel_atomic_get_old_crtc_state(state, crtc);
1948
1949 return !old_crtc_state->post_csc_lut &&
1950 !old_crtc_state->pre_csc_lut;
1951}
1952
1953static bool vlv_can_preload_luts(const struct intel_crtc_state *new_crtc_state)
1954{
1955 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
1956 struct intel_atomic_state *state =
1957 to_intel_atomic_state(new_crtc_state->uapi.state);
1958 const struct intel_crtc_state *old_crtc_state =
1959 intel_atomic_get_old_crtc_state(state, crtc);
1960
1961 return !old_crtc_state->wgc_enable &&
1962 !old_crtc_state->post_csc_lut;
1963}
1964
1965static bool chv_can_preload_luts(const struct intel_crtc_state *new_crtc_state)
1966{
1967 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
1968 struct intel_atomic_state *state =
1969 to_intel_atomic_state(new_crtc_state->uapi.state);
1970 const struct intel_crtc_state *old_crtc_state =
1971 intel_atomic_get_old_crtc_state(state, crtc);
1972
1973 /*
1974 * CGM_PIPE_MODE is itself single buffered. We'd have to
1975 * somehow split it out from chv_load_luts() if we wanted
1976 * the ability to preload the CGM LUTs/CSC without tearing.
1977 */
1978 if (old_crtc_state->cgm_mode || new_crtc_state->cgm_mode)
1979 return false;
1980
1981 return vlv_can_preload_luts(new_crtc_state);
1982}
1983
1984int intel_color_check(struct intel_crtc_state *crtc_state)
1985{
1986 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
1987
1988 return i915->display.funcs.color->color_check(crtc_state);
1989}
1990
1991void intel_color_get_config(struct intel_crtc_state *crtc_state)
1992{
1993 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
1994
1995 if (i915->display.funcs.color->get_config)
1996 i915->display.funcs.color->get_config(crtc_state);
1997
1998 i915->display.funcs.color->read_luts(crtc_state);
1999
2000 if (i915->display.funcs.color->read_csc)
2001 i915->display.funcs.color->read_csc(crtc_state);
2002}
2003
2004bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state,
2005 const struct drm_property_blob *blob1,
2006 const struct drm_property_blob *blob2,
2007 bool is_pre_csc_lut)
2008{
2009 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
2010
2011 /*
2012 * FIXME c8_planes readout missing thus
2013 * .read_luts() doesn't read out post_csc_lut.
2014 */
2015 if (!is_pre_csc_lut && crtc_state->c8_planes)
2016 return true;
2017
2018 return i915->display.funcs.color->lut_equal(crtc_state, blob1, blob2,
2019 is_pre_csc_lut);
2020}
2021
2022static bool need_plane_update(struct intel_plane *plane,
2023 const struct intel_crtc_state *crtc_state)
2024{
2025 struct drm_i915_private *i915 = to_i915(dev: plane->base.dev);
2026
2027 /*
2028 * On pre-SKL the pipe gamma enable and pipe csc enable for
2029 * the pipe bottom color are configured via the primary plane.
2030 * We have to reconfigure that even if the plane is inactive.
2031 */
2032 return crtc_state->active_planes & BIT(plane->id) ||
2033 (DISPLAY_VER(i915) < 9 &&
2034 plane->id == PLANE_PRIMARY);
2035}
2036
2037static int
2038intel_color_add_affected_planes(struct intel_crtc_state *new_crtc_state)
2039{
2040 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
2041 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
2042 struct intel_atomic_state *state =
2043 to_intel_atomic_state(new_crtc_state->uapi.state);
2044 const struct intel_crtc_state *old_crtc_state =
2045 intel_atomic_get_old_crtc_state(state, crtc);
2046 struct intel_plane *plane;
2047
2048 if (!new_crtc_state->hw.active ||
2049 intel_crtc_needs_modeset(crtc_state: new_crtc_state))
2050 return 0;
2051
2052 if (new_crtc_state->gamma_enable == old_crtc_state->gamma_enable &&
2053 new_crtc_state->csc_enable == old_crtc_state->csc_enable)
2054 return 0;
2055
2056 for_each_intel_plane_on_crtc(&i915->drm, crtc, plane) {
2057 struct intel_plane_state *plane_state;
2058
2059 if (!need_plane_update(plane, crtc_state: new_crtc_state))
2060 continue;
2061
2062 plane_state = intel_atomic_get_plane_state(state, plane);
2063 if (IS_ERR(ptr: plane_state))
2064 return PTR_ERR(ptr: plane_state);
2065
2066 new_crtc_state->update_planes |= BIT(plane->id);
2067 new_crtc_state->async_flip_planes = 0;
2068 new_crtc_state->do_async_flip = false;
2069
2070 /* plane control register changes blocked by CxSR */
2071 if (HAS_GMCH(i915))
2072 new_crtc_state->disable_cxsr = true;
2073 }
2074
2075 return 0;
2076}
2077
2078static u32 intel_gamma_lut_tests(const struct intel_crtc_state *crtc_state)
2079{
2080 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
2081 const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
2082
2083 if (lut_is_legacy(lut: gamma_lut))
2084 return 0;
2085
2086 return DISPLAY_INFO(i915)->color.gamma_lut_tests;
2087}
2088
2089static u32 intel_degamma_lut_tests(const struct intel_crtc_state *crtc_state)
2090{
2091 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
2092
2093 return DISPLAY_INFO(i915)->color.degamma_lut_tests;
2094}
2095
2096static int intel_gamma_lut_size(const struct intel_crtc_state *crtc_state)
2097{
2098 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
2099 const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
2100
2101 if (lut_is_legacy(lut: gamma_lut))
2102 return LEGACY_LUT_LENGTH;
2103
2104 return DISPLAY_INFO(i915)->color.gamma_lut_size;
2105}
2106
2107static u32 intel_degamma_lut_size(const struct intel_crtc_state *crtc_state)
2108{
2109 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
2110
2111 return DISPLAY_INFO(i915)->color.degamma_lut_size;
2112}
2113
2114static int check_lut_size(struct drm_i915_private *i915,
2115 const struct drm_property_blob *lut, int expected)
2116{
2117 int len;
2118
2119 if (!lut)
2120 return 0;
2121
2122 len = drm_color_lut_size(blob: lut);
2123 if (len != expected) {
2124 drm_dbg_kms(&i915->drm, "Invalid LUT size; got %d, expected %d\n",
2125 len, expected);
2126 return -EINVAL;
2127 }
2128
2129 return 0;
2130}
2131
2132static int _check_luts(const struct intel_crtc_state *crtc_state,
2133 u32 degamma_tests, u32 gamma_tests)
2134{
2135 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
2136 const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
2137 const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut;
2138 int gamma_length, degamma_length;
2139
2140 /* C8 relies on its palette being stored in the legacy LUT */
2141 if (crtc_state->c8_planes && !lut_is_legacy(lut: crtc_state->hw.gamma_lut)) {
2142 drm_dbg_kms(&i915->drm,
2143 "C8 pixelformat requires the legacy LUT\n");
2144 return -EINVAL;
2145 }
2146
2147 degamma_length = intel_degamma_lut_size(crtc_state);
2148 gamma_length = intel_gamma_lut_size(crtc_state);
2149
2150 if (check_lut_size(i915, lut: degamma_lut, expected: degamma_length) ||
2151 check_lut_size(i915, lut: gamma_lut, expected: gamma_length))
2152 return -EINVAL;
2153
2154 if (drm_color_lut_check(lut: degamma_lut, tests: degamma_tests) ||
2155 drm_color_lut_check(lut: gamma_lut, tests: gamma_tests))
2156 return -EINVAL;
2157
2158 return 0;
2159}
2160
2161static int check_luts(const struct intel_crtc_state *crtc_state)
2162{
2163 return _check_luts(crtc_state,
2164 degamma_tests: intel_degamma_lut_tests(crtc_state),
2165 gamma_tests: intel_gamma_lut_tests(crtc_state));
2166}
2167
2168static u32 i9xx_gamma_mode(struct intel_crtc_state *crtc_state)
2169{
2170 if (!crtc_state->gamma_enable ||
2171 lut_is_legacy(lut: crtc_state->hw.gamma_lut))
2172 return GAMMA_MODE_MODE_8BIT;
2173 else
2174 return GAMMA_MODE_MODE_10BIT;
2175}
2176
2177static int i9xx_lut_10_diff(u16 a, u16 b)
2178{
2179 return drm_color_lut_extract(user_input: a, bit_precision: 10) -
2180 drm_color_lut_extract(user_input: b, bit_precision: 10);
2181}
2182
2183static int i9xx_check_lut_10(struct drm_i915_private *dev_priv,
2184 const struct drm_property_blob *blob)
2185{
2186 const struct drm_color_lut *lut = blob->data;
2187 int lut_size = drm_color_lut_size(blob);
2188 const struct drm_color_lut *a = &lut[lut_size - 2];
2189 const struct drm_color_lut *b = &lut[lut_size - 1];
2190
2191 if (i9xx_lut_10_diff(a: b->red, b: a->red) > 0x7f ||
2192 i9xx_lut_10_diff(a: b->green, b: a->green) > 0x7f ||
2193 i9xx_lut_10_diff(a: b->blue, b: a->blue) > 0x7f) {
2194 drm_dbg_kms(&dev_priv->drm, "Last gamma LUT entry exceeds max slope\n");
2195 return -EINVAL;
2196 }
2197
2198 return 0;
2199}
2200
2201void intel_color_assert_luts(const struct intel_crtc_state *crtc_state)
2202{
2203 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
2204
2205 /* make sure {pre,post}_csc_lut were correctly assigned */
2206 if (DISPLAY_VER(i915) >= 11 || HAS_GMCH(i915)) {
2207 drm_WARN_ON(&i915->drm,
2208 crtc_state->pre_csc_lut != crtc_state->hw.degamma_lut);
2209 drm_WARN_ON(&i915->drm,
2210 crtc_state->post_csc_lut != crtc_state->hw.gamma_lut);
2211 } else if (DISPLAY_VER(i915) == 10) {
2212 drm_WARN_ON(&i915->drm,
2213 crtc_state->post_csc_lut == crtc_state->hw.gamma_lut &&
2214 crtc_state->pre_csc_lut != crtc_state->hw.degamma_lut &&
2215 crtc_state->pre_csc_lut != i915->display.color.glk_linear_degamma_lut);
2216 drm_WARN_ON(&i915->drm,
2217 !ilk_lut_limited_range(crtc_state) &&
2218 crtc_state->post_csc_lut != NULL &&
2219 crtc_state->post_csc_lut != crtc_state->hw.gamma_lut);
2220 } else if (crtc_state->gamma_mode != GAMMA_MODE_MODE_SPLIT) {
2221 drm_WARN_ON(&i915->drm,
2222 crtc_state->pre_csc_lut != crtc_state->hw.degamma_lut &&
2223 crtc_state->pre_csc_lut != crtc_state->hw.gamma_lut);
2224 drm_WARN_ON(&i915->drm,
2225 !ilk_lut_limited_range(crtc_state) &&
2226 crtc_state->post_csc_lut != crtc_state->hw.degamma_lut &&
2227 crtc_state->post_csc_lut != crtc_state->hw.gamma_lut);
2228 }
2229}
2230
2231static void intel_assign_luts(struct intel_crtc_state *crtc_state)
2232{
2233 drm_property_replace_blob(blob: &crtc_state->pre_csc_lut,
2234 new_blob: crtc_state->hw.degamma_lut);
2235 drm_property_replace_blob(blob: &crtc_state->post_csc_lut,
2236 new_blob: crtc_state->hw.gamma_lut);
2237}
2238
2239static int i9xx_color_check(struct intel_crtc_state *crtc_state)
2240{
2241 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
2242 int ret;
2243
2244 ret = check_luts(crtc_state);
2245 if (ret)
2246 return ret;
2247
2248 crtc_state->gamma_enable =
2249 crtc_state->hw.gamma_lut &&
2250 !crtc_state->c8_planes;
2251
2252 crtc_state->gamma_mode = i9xx_gamma_mode(crtc_state);
2253
2254 if (DISPLAY_VER(i915) < 4 &&
2255 crtc_state->gamma_mode == GAMMA_MODE_MODE_10BIT) {
2256 ret = i9xx_check_lut_10(dev_priv: i915, blob: crtc_state->hw.gamma_lut);
2257 if (ret)
2258 return ret;
2259 }
2260
2261 ret = intel_color_add_affected_planes(new_crtc_state: crtc_state);
2262 if (ret)
2263 return ret;
2264
2265 intel_assign_luts(crtc_state);
2266
2267 crtc_state->preload_luts = intel_can_preload_luts(new_crtc_state: crtc_state);
2268
2269 return 0;
2270}
2271
2272/*
2273 * VLV color pipeline:
2274 * u0.10 -> WGC csc -> u0.10 -> pipe gamma -> u0.10
2275 */
2276static int vlv_color_check(struct intel_crtc_state *crtc_state)
2277{
2278 int ret;
2279
2280 ret = check_luts(crtc_state);
2281 if (ret)
2282 return ret;
2283
2284 crtc_state->gamma_enable =
2285 crtc_state->hw.gamma_lut &&
2286 !crtc_state->c8_planes;
2287
2288 crtc_state->gamma_mode = i9xx_gamma_mode(crtc_state);
2289
2290 crtc_state->wgc_enable = crtc_state->hw.ctm;
2291
2292 ret = intel_color_add_affected_planes(new_crtc_state: crtc_state);
2293 if (ret)
2294 return ret;
2295
2296 intel_assign_luts(crtc_state);
2297
2298 vlv_assign_csc(crtc_state);
2299
2300 crtc_state->preload_luts = vlv_can_preload_luts(new_crtc_state: crtc_state);
2301
2302 return 0;
2303}
2304
2305static u32 chv_cgm_mode(const struct intel_crtc_state *crtc_state)
2306{
2307 u32 cgm_mode = 0;
2308
2309 if (crtc_state->hw.degamma_lut)
2310 cgm_mode |= CGM_PIPE_MODE_DEGAMMA;
2311 if (crtc_state->hw.ctm)
2312 cgm_mode |= CGM_PIPE_MODE_CSC;
2313 if (crtc_state->hw.gamma_lut &&
2314 !lut_is_legacy(lut: crtc_state->hw.gamma_lut))
2315 cgm_mode |= CGM_PIPE_MODE_GAMMA;
2316
2317 /*
2318 * Toggling the CGM CSC on/off outside of the tiny window
2319 * between start of vblank and frame start causes underruns.
2320 * Always enable the CGM CSC as a workaround.
2321 */
2322 cgm_mode |= CGM_PIPE_MODE_CSC;
2323
2324 return cgm_mode;
2325}
2326
2327/*
2328 * CHV color pipeline:
2329 * u0.10 -> CGM degamma -> u0.14 -> CGM csc -> u0.14 -> CGM gamma ->
2330 * u0.10 -> WGC csc -> u0.10 -> pipe gamma -> u0.10
2331 *
2332 * We always bypass the WGC csc and use the CGM csc
2333 * instead since it has degamma and better precision.
2334 */
2335static int chv_color_check(struct intel_crtc_state *crtc_state)
2336{
2337 int ret;
2338
2339 ret = check_luts(crtc_state);
2340 if (ret)
2341 return ret;
2342
2343 /*
2344 * Pipe gamma will be used only for the legacy LUT.
2345 * Otherwise we bypass it and use the CGM gamma instead.
2346 */
2347 crtc_state->gamma_enable =
2348 lut_is_legacy(lut: crtc_state->hw.gamma_lut) &&
2349 !crtc_state->c8_planes;
2350
2351 crtc_state->gamma_mode = GAMMA_MODE_MODE_8BIT;
2352
2353 crtc_state->cgm_mode = chv_cgm_mode(crtc_state);
2354
2355 /*
2356 * We always bypass the WGC CSC and use the CGM CSC
2357 * instead since it has degamma and better precision.
2358 */
2359 crtc_state->wgc_enable = false;
2360
2361 ret = intel_color_add_affected_planes(new_crtc_state: crtc_state);
2362 if (ret)
2363 return ret;
2364
2365 intel_assign_luts(crtc_state);
2366
2367 chv_assign_csc(crtc_state);
2368
2369 crtc_state->preload_luts = chv_can_preload_luts(new_crtc_state: crtc_state);
2370
2371 return 0;
2372}
2373
2374static bool ilk_gamma_enable(const struct intel_crtc_state *crtc_state)
2375{
2376 return (crtc_state->hw.gamma_lut ||
2377 crtc_state->hw.degamma_lut) &&
2378 !crtc_state->c8_planes;
2379}
2380
2381static bool ilk_csc_enable(const struct intel_crtc_state *crtc_state)
2382{
2383 return crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB ||
2384 ilk_csc_limited_range(crtc_state) ||
2385 crtc_state->hw.ctm;
2386}
2387
2388static u32 ilk_gamma_mode(const struct intel_crtc_state *crtc_state)
2389{
2390 if (!crtc_state->gamma_enable ||
2391 lut_is_legacy(lut: crtc_state->hw.gamma_lut))
2392 return GAMMA_MODE_MODE_8BIT;
2393 else
2394 return GAMMA_MODE_MODE_10BIT;
2395}
2396
2397static u32 ilk_csc_mode(const struct intel_crtc_state *crtc_state)
2398{
2399 /*
2400 * CSC comes after the LUT in RGB->YCbCr mode.
2401 * RGB->YCbCr needs the limited range offsets added to
2402 * the output. RGB limited range output is handled by
2403 * the hw automagically elsewhere.
2404 */
2405 if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB)
2406 return CSC_BLACK_SCREEN_OFFSET;
2407
2408 if (crtc_state->hw.degamma_lut)
2409 return CSC_MODE_YUV_TO_RGB;
2410
2411 return CSC_MODE_YUV_TO_RGB |
2412 CSC_POSITION_BEFORE_GAMMA;
2413}
2414
2415static int ilk_assign_luts(struct intel_crtc_state *crtc_state)
2416{
2417 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
2418
2419 if (ilk_lut_limited_range(crtc_state)) {
2420 struct drm_property_blob *gamma_lut;
2421
2422 gamma_lut = create_resized_lut(i915, blob_in: crtc_state->hw.gamma_lut,
2423 lut_out_size: drm_color_lut_size(blob: crtc_state->hw.gamma_lut),
2424 limited_color_range: true);
2425 if (IS_ERR(ptr: gamma_lut))
2426 return PTR_ERR(ptr: gamma_lut);
2427
2428 drm_property_replace_blob(blob: &crtc_state->post_csc_lut, new_blob: gamma_lut);
2429
2430 drm_property_blob_put(blob: gamma_lut);
2431
2432 drm_property_replace_blob(blob: &crtc_state->pre_csc_lut, new_blob: crtc_state->hw.degamma_lut);
2433
2434 return 0;
2435 }
2436
2437 if (crtc_state->hw.degamma_lut ||
2438 crtc_state->csc_mode & CSC_POSITION_BEFORE_GAMMA) {
2439 drm_property_replace_blob(blob: &crtc_state->pre_csc_lut,
2440 new_blob: crtc_state->hw.degamma_lut);
2441 drm_property_replace_blob(blob: &crtc_state->post_csc_lut,
2442 new_blob: crtc_state->hw.gamma_lut);
2443 } else {
2444 drm_property_replace_blob(blob: &crtc_state->pre_csc_lut,
2445 new_blob: crtc_state->hw.gamma_lut);
2446 drm_property_replace_blob(blob: &crtc_state->post_csc_lut,
2447 NULL);
2448 }
2449
2450 return 0;
2451}
2452
2453static int ilk_color_check(struct intel_crtc_state *crtc_state)
2454{
2455 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
2456 int ret;
2457
2458 ret = check_luts(crtc_state);
2459 if (ret)
2460 return ret;
2461
2462 if (crtc_state->hw.degamma_lut && crtc_state->hw.gamma_lut) {
2463 drm_dbg_kms(&i915->drm,
2464 "Degamma and gamma together are not possible\n");
2465 return -EINVAL;
2466 }
2467
2468 if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB &&
2469 crtc_state->hw.ctm) {
2470 drm_dbg_kms(&i915->drm,
2471 "YCbCr and CTM together are not possible\n");
2472 return -EINVAL;
2473 }
2474
2475 crtc_state->gamma_enable = ilk_gamma_enable(crtc_state);
2476
2477 crtc_state->csc_enable = ilk_csc_enable(crtc_state);
2478
2479 crtc_state->gamma_mode = ilk_gamma_mode(crtc_state);
2480
2481 crtc_state->csc_mode = ilk_csc_mode(crtc_state);
2482
2483 ret = intel_color_add_affected_planes(new_crtc_state: crtc_state);
2484 if (ret)
2485 return ret;
2486
2487 ret = ilk_assign_luts(crtc_state);
2488 if (ret)
2489 return ret;
2490
2491 ilk_assign_csc(crtc_state);
2492
2493 crtc_state->preload_luts = intel_can_preload_luts(new_crtc_state: crtc_state);
2494
2495 return 0;
2496}
2497
2498static u32 ivb_gamma_mode(const struct intel_crtc_state *crtc_state)
2499{
2500 if (crtc_state->hw.degamma_lut && crtc_state->hw.gamma_lut)
2501 return GAMMA_MODE_MODE_SPLIT;
2502
2503 return ilk_gamma_mode(crtc_state);
2504}
2505
2506static u32 ivb_csc_mode(const struct intel_crtc_state *crtc_state)
2507{
2508 bool limited_color_range = ilk_csc_limited_range(crtc_state);
2509
2510 /*
2511 * CSC comes after the LUT in degamma, RGB->YCbCr,
2512 * and RGB full->limited range mode.
2513 */
2514 if (crtc_state->hw.degamma_lut ||
2515 crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB ||
2516 limited_color_range)
2517 return 0;
2518
2519 return CSC_POSITION_BEFORE_GAMMA;
2520}
2521
2522static int ivb_assign_luts(struct intel_crtc_state *crtc_state)
2523{
2524 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
2525 struct drm_property_blob *degamma_lut, *gamma_lut;
2526
2527 if (crtc_state->gamma_mode != GAMMA_MODE_MODE_SPLIT)
2528 return ilk_assign_luts(crtc_state);
2529
2530 drm_WARN_ON(&i915->drm, drm_color_lut_size(crtc_state->hw.degamma_lut) != 1024);
2531 drm_WARN_ON(&i915->drm, drm_color_lut_size(crtc_state->hw.gamma_lut) != 1024);
2532
2533 degamma_lut = create_resized_lut(i915, blob_in: crtc_state->hw.degamma_lut, lut_out_size: 512,
2534 limited_color_range: false);
2535 if (IS_ERR(ptr: degamma_lut))
2536 return PTR_ERR(ptr: degamma_lut);
2537
2538 gamma_lut = create_resized_lut(i915, blob_in: crtc_state->hw.gamma_lut, lut_out_size: 512,
2539 limited_color_range: ilk_lut_limited_range(crtc_state));
2540 if (IS_ERR(ptr: gamma_lut)) {
2541 drm_property_blob_put(blob: degamma_lut);
2542 return PTR_ERR(ptr: gamma_lut);
2543 }
2544
2545 drm_property_replace_blob(blob: &crtc_state->pre_csc_lut, new_blob: degamma_lut);
2546 drm_property_replace_blob(blob: &crtc_state->post_csc_lut, new_blob: gamma_lut);
2547
2548 drm_property_blob_put(blob: degamma_lut);
2549 drm_property_blob_put(blob: gamma_lut);
2550
2551 return 0;
2552}
2553
2554static int ivb_color_check(struct intel_crtc_state *crtc_state)
2555{
2556 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
2557 int ret;
2558
2559 ret = check_luts(crtc_state);
2560 if (ret)
2561 return ret;
2562
2563 if (crtc_state->c8_planes && crtc_state->hw.degamma_lut) {
2564 drm_dbg_kms(&i915->drm,
2565 "C8 pixelformat and degamma together are not possible\n");
2566 return -EINVAL;
2567 }
2568
2569 if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB &&
2570 crtc_state->hw.ctm) {
2571 drm_dbg_kms(&i915->drm,
2572 "YCbCr and CTM together are not possible\n");
2573 return -EINVAL;
2574 }
2575
2576 if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB &&
2577 crtc_state->hw.degamma_lut && crtc_state->hw.gamma_lut) {
2578 drm_dbg_kms(&i915->drm,
2579 "YCbCr and degamma+gamma together are not possible\n");
2580 return -EINVAL;
2581 }
2582
2583 crtc_state->gamma_enable = ilk_gamma_enable(crtc_state);
2584
2585 crtc_state->csc_enable = ilk_csc_enable(crtc_state);
2586
2587 crtc_state->gamma_mode = ivb_gamma_mode(crtc_state);
2588
2589 crtc_state->csc_mode = ivb_csc_mode(crtc_state);
2590
2591 ret = intel_color_add_affected_planes(new_crtc_state: crtc_state);
2592 if (ret)
2593 return ret;
2594
2595 ret = ivb_assign_luts(crtc_state);
2596 if (ret)
2597 return ret;
2598
2599 ilk_assign_csc(crtc_state);
2600
2601 crtc_state->preload_luts = intel_can_preload_luts(new_crtc_state: crtc_state);
2602
2603 return 0;
2604}
2605
2606static u32 glk_gamma_mode(const struct intel_crtc_state *crtc_state)
2607{
2608 if (!crtc_state->gamma_enable ||
2609 lut_is_legacy(lut: crtc_state->hw.gamma_lut))
2610 return GAMMA_MODE_MODE_8BIT;
2611 else
2612 return GAMMA_MODE_MODE_10BIT;
2613}
2614
2615static bool glk_use_pre_csc_lut_for_gamma(const struct intel_crtc_state *crtc_state)
2616{
2617 return crtc_state->hw.gamma_lut &&
2618 !crtc_state->c8_planes &&
2619 crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB;
2620}
2621
2622static int glk_assign_luts(struct intel_crtc_state *crtc_state)
2623{
2624 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
2625
2626 if (glk_use_pre_csc_lut_for_gamma(crtc_state)) {
2627 struct drm_property_blob *gamma_lut;
2628
2629 gamma_lut = create_resized_lut(i915, blob_in: crtc_state->hw.gamma_lut,
2630 DISPLAY_INFO(i915)->color.degamma_lut_size,
2631 limited_color_range: false);
2632 if (IS_ERR(ptr: gamma_lut))
2633 return PTR_ERR(ptr: gamma_lut);
2634
2635 drm_property_replace_blob(blob: &crtc_state->pre_csc_lut, new_blob: gamma_lut);
2636 drm_property_replace_blob(blob: &crtc_state->post_csc_lut, NULL);
2637
2638 drm_property_blob_put(blob: gamma_lut);
2639
2640 return 0;
2641 }
2642
2643 if (ilk_lut_limited_range(crtc_state)) {
2644 struct drm_property_blob *gamma_lut;
2645
2646 gamma_lut = create_resized_lut(i915, blob_in: crtc_state->hw.gamma_lut,
2647 lut_out_size: drm_color_lut_size(blob: crtc_state->hw.gamma_lut),
2648 limited_color_range: true);
2649 if (IS_ERR(ptr: gamma_lut))
2650 return PTR_ERR(ptr: gamma_lut);
2651
2652 drm_property_replace_blob(blob: &crtc_state->post_csc_lut, new_blob: gamma_lut);
2653
2654 drm_property_blob_put(blob: gamma_lut);
2655 } else {
2656 drm_property_replace_blob(blob: &crtc_state->post_csc_lut, new_blob: crtc_state->hw.gamma_lut);
2657 }
2658
2659 drm_property_replace_blob(blob: &crtc_state->pre_csc_lut, new_blob: crtc_state->hw.degamma_lut);
2660
2661 /*
2662 * On GLK+ both pipe CSC and degamma LUT are controlled
2663 * by csc_enable. Hence for the cases where the CSC is
2664 * needed but degamma LUT is not we need to load a
2665 * linear degamma LUT.
2666 */
2667 if (crtc_state->csc_enable && !crtc_state->pre_csc_lut)
2668 drm_property_replace_blob(blob: &crtc_state->pre_csc_lut,
2669 new_blob: i915->display.color.glk_linear_degamma_lut);
2670
2671 return 0;
2672}
2673
2674static int glk_check_luts(const struct intel_crtc_state *crtc_state)
2675{
2676 u32 degamma_tests = intel_degamma_lut_tests(crtc_state);
2677 u32 gamma_tests = intel_gamma_lut_tests(crtc_state);
2678
2679 if (glk_use_pre_csc_lut_for_gamma(crtc_state))
2680 gamma_tests |= degamma_tests;
2681
2682 return _check_luts(crtc_state, degamma_tests, gamma_tests);
2683}
2684
2685static int glk_color_check(struct intel_crtc_state *crtc_state)
2686{
2687 struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev);
2688 int ret;
2689
2690 ret = glk_check_luts(crtc_state);
2691 if (ret)
2692 return ret;
2693
2694 if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB &&
2695 crtc_state->hw.ctm) {
2696 drm_dbg_kms(&i915->drm,
2697 "YCbCr and CTM together are not possible\n");
2698 return -EINVAL;
2699 }
2700
2701 if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB &&
2702 crtc_state->hw.degamma_lut && crtc_state->hw.gamma_lut) {
2703 drm_dbg_kms(&i915->drm,
2704 "YCbCr and degamma+gamma together are not possible\n");
2705 return -EINVAL;
2706 }
2707
2708 crtc_state->gamma_enable =
2709 !glk_use_pre_csc_lut_for_gamma(crtc_state) &&
2710 crtc_state->hw.gamma_lut &&
2711 !crtc_state->c8_planes;
2712
2713 /* On GLK+ degamma LUT is controlled by csc_enable */
2714 crtc_state->csc_enable =
2715 glk_use_pre_csc_lut_for_gamma(crtc_state) ||
2716 crtc_state->hw.degamma_lut ||
2717 crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB ||
2718 crtc_state->hw.ctm || ilk_csc_limited_range(crtc_state);
2719
2720 crtc_state->gamma_mode = glk_gamma_mode(crtc_state);
2721
2722 crtc_state->csc_mode = 0;
2723
2724 ret = intel_color_add_affected_planes(new_crtc_state: crtc_state);
2725 if (ret)
2726 return ret;
2727
2728 ret = glk_assign_luts(crtc_state);
2729 if (ret)
2730 return ret;
2731
2732 ilk_assign_csc(crtc_state);
2733
2734 crtc_state->preload_luts = intel_can_preload_luts(new_crtc_state: crtc_state);
2735
2736 return 0;
2737}
2738
2739static u32 icl_gamma_mode(const struct intel_crtc_state *crtc_state)
2740{
2741 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
2742 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
2743 u32 gamma_mode = 0;
2744
2745 if (crtc_state->hw.degamma_lut)
2746 gamma_mode |= PRE_CSC_GAMMA_ENABLE;
2747
2748 if (crtc_state->hw.gamma_lut &&
2749 !crtc_state->c8_planes)
2750 gamma_mode |= POST_CSC_GAMMA_ENABLE;
2751
2752 if (!crtc_state->hw.gamma_lut ||
2753 lut_is_legacy(lut: crtc_state->hw.gamma_lut))
2754 gamma_mode |= GAMMA_MODE_MODE_8BIT;
2755 /*
2756 * Enable 10bit gamma for D13
2757 * ToDo: Extend to Logarithmic Gamma once the new UAPI
2758 * is accepted and implemented by a userspace consumer
2759 */
2760 else if (DISPLAY_VER(i915) >= 13)
2761 gamma_mode |= GAMMA_MODE_MODE_10BIT;
2762 else
2763 gamma_mode |= GAMMA_MODE_MODE_12BIT_MULTI_SEG;
2764
2765 return gamma_mode;
2766}
2767
2768static u32 icl_csc_mode(const struct intel_crtc_state *crtc_state)
2769{
2770 u32 csc_mode = 0;
2771
2772 if (crtc_state->hw.ctm)
2773 csc_mode |= ICL_CSC_ENABLE;
2774
2775 if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB ||
2776 crtc_state->limited_color_range)
2777 csc_mode |= ICL_OUTPUT_CSC_ENABLE;
2778
2779 return csc_mode;
2780}
2781
2782static int icl_color_check(struct intel_crtc_state *crtc_state)
2783{
2784 int ret;
2785
2786 ret = check_luts(crtc_state);
2787 if (ret)
2788 return ret;
2789
2790 crtc_state->gamma_mode = icl_gamma_mode(crtc_state);
2791
2792 crtc_state->csc_mode = icl_csc_mode(crtc_state);
2793
2794 intel_assign_luts(crtc_state);
2795
2796 icl_assign_csc(crtc_state);
2797
2798 crtc_state->preload_luts = intel_can_preload_luts(new_crtc_state: crtc_state);
2799
2800 return 0;
2801}
2802
2803static int i9xx_post_csc_lut_precision(const struct intel_crtc_state *crtc_state)
2804{
2805 if (!crtc_state->gamma_enable && !crtc_state->c8_planes)
2806 return 0;
2807
2808 switch (crtc_state->gamma_mode) {
2809 case GAMMA_MODE_MODE_8BIT:
2810 return 8;
2811 case GAMMA_MODE_MODE_10BIT:
2812 return 10;
2813 default:
2814 MISSING_CASE(crtc_state->gamma_mode);
2815 return 0;
2816 }
2817}
2818
2819static int i9xx_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state)
2820{
2821 return 0;
2822}
2823
2824static int i965_post_csc_lut_precision(const struct intel_crtc_state *crtc_state)
2825{
2826 if (!crtc_state->gamma_enable && !crtc_state->c8_planes)
2827 return 0;
2828
2829 switch (crtc_state->gamma_mode) {
2830 case GAMMA_MODE_MODE_8BIT:
2831 return 8;
2832 case GAMMA_MODE_MODE_10BIT:
2833 return 16;
2834 default:
2835 MISSING_CASE(crtc_state->gamma_mode);
2836 return 0;
2837 }
2838}
2839
2840static int ilk_gamma_mode_precision(u32 gamma_mode)
2841{
2842 switch (gamma_mode) {
2843 case GAMMA_MODE_MODE_8BIT:
2844 return 8;
2845 case GAMMA_MODE_MODE_10BIT:
2846 return 10;
2847 default:
2848 MISSING_CASE(gamma_mode);
2849 return 0;
2850 }
2851}
2852
2853static bool ilk_has_post_csc_lut(const struct intel_crtc_state *crtc_state)
2854{
2855 if (crtc_state->c8_planes)
2856 return true;
2857
2858 return crtc_state->gamma_enable &&
2859 (crtc_state->csc_mode & CSC_POSITION_BEFORE_GAMMA) != 0;
2860}
2861
2862static bool ilk_has_pre_csc_lut(const struct intel_crtc_state *crtc_state)
2863{
2864 return crtc_state->gamma_enable &&
2865 (crtc_state->csc_mode & CSC_POSITION_BEFORE_GAMMA) == 0;
2866}
2867
2868static int ilk_post_csc_lut_precision(const struct intel_crtc_state *crtc_state)
2869{
2870 if (!ilk_has_post_csc_lut(crtc_state))
2871 return 0;
2872
2873 return ilk_gamma_mode_precision(gamma_mode: crtc_state->gamma_mode);
2874}
2875
2876static int ilk_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state)
2877{
2878 if (!ilk_has_pre_csc_lut(crtc_state))
2879 return 0;
2880
2881 return ilk_gamma_mode_precision(gamma_mode: crtc_state->gamma_mode);
2882}
2883
2884static int ivb_post_csc_lut_precision(const struct intel_crtc_state *crtc_state)
2885{
2886 if (crtc_state->gamma_enable &&
2887 crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)
2888 return 10;
2889
2890 return ilk_post_csc_lut_precision(crtc_state);
2891}
2892
2893static int ivb_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state)
2894{
2895 if (crtc_state->gamma_enable &&
2896 crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)
2897 return 10;
2898
2899 return ilk_pre_csc_lut_precision(crtc_state);
2900}
2901
2902static int chv_post_csc_lut_precision(const struct intel_crtc_state *crtc_state)
2903{
2904 if (crtc_state->cgm_mode & CGM_PIPE_MODE_GAMMA)
2905 return 10;
2906
2907 return i965_post_csc_lut_precision(crtc_state);
2908}
2909
2910static int chv_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state)
2911{
2912 if (crtc_state->cgm_mode & CGM_PIPE_MODE_DEGAMMA)
2913 return 14;
2914
2915 return 0;
2916}
2917
2918static int glk_post_csc_lut_precision(const struct intel_crtc_state *crtc_state)
2919{
2920 if (!crtc_state->gamma_enable && !crtc_state->c8_planes)
2921 return 0;
2922
2923 return ilk_gamma_mode_precision(gamma_mode: crtc_state->gamma_mode);
2924}
2925
2926static int glk_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state)
2927{
2928 if (!crtc_state->csc_enable)
2929 return 0;
2930
2931 return 16;
2932}
2933
2934static bool icl_has_post_csc_lut(const struct intel_crtc_state *crtc_state)
2935{
2936 if (crtc_state->c8_planes)
2937 return true;
2938
2939 return crtc_state->gamma_mode & POST_CSC_GAMMA_ENABLE;
2940}
2941
2942static bool icl_has_pre_csc_lut(const struct intel_crtc_state *crtc_state)
2943{
2944 return crtc_state->gamma_mode & PRE_CSC_GAMMA_ENABLE;
2945}
2946
2947static int icl_post_csc_lut_precision(const struct intel_crtc_state *crtc_state)
2948{
2949 if (!icl_has_post_csc_lut(crtc_state))
2950 return 0;
2951
2952 switch (crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) {
2953 case GAMMA_MODE_MODE_8BIT:
2954 return 8;
2955 case GAMMA_MODE_MODE_10BIT:
2956 return 10;
2957 case GAMMA_MODE_MODE_12BIT_MULTI_SEG:
2958 return 16;
2959 default:
2960 MISSING_CASE(crtc_state->gamma_mode);
2961 return 0;
2962 }
2963}
2964
2965static int icl_pre_csc_lut_precision(const struct intel_crtc_state *crtc_state)
2966{
2967 if (!icl_has_pre_csc_lut(crtc_state))
2968 return 0;
2969
2970 return 16;
2971}
2972
2973static bool err_check(const struct drm_color_lut *lut1,
2974 const struct drm_color_lut *lut2, u32 err)
2975{
2976 return ((abs((long)lut2->red - lut1->red)) <= err) &&
2977 ((abs((long)lut2->blue - lut1->blue)) <= err) &&
2978 ((abs((long)lut2->green - lut1->green)) <= err);
2979}
2980
2981static bool intel_lut_entries_equal(const struct drm_color_lut *lut1,
2982 const struct drm_color_lut *lut2,
2983 int lut_size, u32 err)
2984{
2985 int i;
2986
2987 for (i = 0; i < lut_size; i++) {
2988 if (!err_check(lut1: &lut1[i], lut2: &lut2[i], err))
2989 return false;
2990 }
2991
2992 return true;
2993}
2994
2995static bool intel_lut_equal(const struct drm_property_blob *blob1,
2996 const struct drm_property_blob *blob2,
2997 int check_size, int precision)
2998{
2999 const struct drm_color_lut *lut1, *lut2;
3000 int lut_size1, lut_size2;
3001 u32 err;
3002
3003 if (!blob1 != !blob2)
3004 return false;
3005
3006 if (!blob1 != !precision)
3007 return false;
3008
3009 if (!blob1)
3010 return true;
3011
3012 lut_size1 = drm_color_lut_size(blob: blob1);
3013 lut_size2 = drm_color_lut_size(blob: blob2);
3014
3015 if (lut_size1 != lut_size2)
3016 return false;
3017
3018 if (check_size > lut_size1)
3019 return false;
3020
3021 lut1 = blob1->data;
3022 lut2 = blob2->data;
3023
3024 err = 0xffff >> precision;
3025
3026 if (!check_size)
3027 check_size = lut_size1;
3028
3029 return intel_lut_entries_equal(lut1, lut2, lut_size: check_size, err);
3030}
3031
3032static bool i9xx_lut_equal(const struct intel_crtc_state *crtc_state,
3033 const struct drm_property_blob *blob1,
3034 const struct drm_property_blob *blob2,
3035 bool is_pre_csc_lut)
3036{
3037 int check_size = 0;
3038
3039 if (is_pre_csc_lut)
3040 return intel_lut_equal(blob1, blob2, check_size: 0,
3041 precision: i9xx_pre_csc_lut_precision(crtc_state));
3042
3043 /* 10bit mode last entry is implicit, just skip it */
3044 if (crtc_state->gamma_mode == GAMMA_MODE_MODE_10BIT)
3045 check_size = 128;
3046
3047 return intel_lut_equal(blob1, blob2, check_size,
3048 precision: i9xx_post_csc_lut_precision(crtc_state));
3049}
3050
3051static bool i965_lut_equal(const struct intel_crtc_state *crtc_state,
3052 const struct drm_property_blob *blob1,
3053 const struct drm_property_blob *blob2,
3054 bool is_pre_csc_lut)
3055{
3056 if (is_pre_csc_lut)
3057 return intel_lut_equal(blob1, blob2, check_size: 0,
3058 precision: i9xx_pre_csc_lut_precision(crtc_state));
3059 else
3060 return intel_lut_equal(blob1, blob2, check_size: 0,
3061 precision: i965_post_csc_lut_precision(crtc_state));
3062}
3063
3064static bool chv_lut_equal(const struct intel_crtc_state *crtc_state,
3065 const struct drm_property_blob *blob1,
3066 const struct drm_property_blob *blob2,
3067 bool is_pre_csc_lut)
3068{
3069 if (is_pre_csc_lut)
3070 return intel_lut_equal(blob1, blob2, check_size: 0,
3071 precision: chv_pre_csc_lut_precision(crtc_state));
3072 else
3073 return intel_lut_equal(blob1, blob2, check_size: 0,
3074 precision: chv_post_csc_lut_precision(crtc_state));
3075}
3076
3077static bool ilk_lut_equal(const struct intel_crtc_state *crtc_state,
3078 const struct drm_property_blob *blob1,
3079 const struct drm_property_blob *blob2,
3080 bool is_pre_csc_lut)
3081{
3082 if (is_pre_csc_lut)
3083 return intel_lut_equal(blob1, blob2, check_size: 0,
3084 precision: ilk_pre_csc_lut_precision(crtc_state));
3085 else
3086 return intel_lut_equal(blob1, blob2, check_size: 0,
3087 precision: ilk_post_csc_lut_precision(crtc_state));
3088}
3089
3090static bool ivb_lut_equal(const struct intel_crtc_state *crtc_state,
3091 const struct drm_property_blob *blob1,
3092 const struct drm_property_blob *blob2,
3093 bool is_pre_csc_lut)
3094{
3095 if (is_pre_csc_lut)
3096 return intel_lut_equal(blob1, blob2, check_size: 0,
3097 precision: ivb_pre_csc_lut_precision(crtc_state));
3098 else
3099 return intel_lut_equal(blob1, blob2, check_size: 0,
3100 precision: ivb_post_csc_lut_precision(crtc_state));
3101}
3102
3103static bool glk_lut_equal(const struct intel_crtc_state *crtc_state,
3104 const struct drm_property_blob *blob1,
3105 const struct drm_property_blob *blob2,
3106 bool is_pre_csc_lut)
3107{
3108 if (is_pre_csc_lut)
3109 return intel_lut_equal(blob1, blob2, check_size: 0,
3110 precision: glk_pre_csc_lut_precision(crtc_state));
3111 else
3112 return intel_lut_equal(blob1, blob2, check_size: 0,
3113 precision: glk_post_csc_lut_precision(crtc_state));
3114}
3115
3116static bool icl_lut_equal(const struct intel_crtc_state *crtc_state,
3117 const struct drm_property_blob *blob1,
3118 const struct drm_property_blob *blob2,
3119 bool is_pre_csc_lut)
3120{
3121 int check_size = 0;
3122
3123 if (is_pre_csc_lut)
3124 return intel_lut_equal(blob1, blob2, check_size: 0,
3125 precision: icl_pre_csc_lut_precision(crtc_state));
3126
3127 /* hw readout broken except for the super fine segment :( */
3128 if ((crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) ==
3129 GAMMA_MODE_MODE_12BIT_MULTI_SEG)
3130 check_size = 9;
3131
3132 return intel_lut_equal(blob1, blob2, check_size,
3133 precision: icl_post_csc_lut_precision(crtc_state));
3134}
3135
3136static struct drm_property_blob *i9xx_read_lut_8(struct intel_crtc *crtc)
3137{
3138 struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev);
3139 enum pipe pipe = crtc->pipe;
3140 struct drm_property_blob *blob;
3141 struct drm_color_lut *lut;
3142 int i;
3143
3144 blob = drm_property_create_blob(dev: &dev_priv->drm,
3145 length: sizeof(lut[0]) * LEGACY_LUT_LENGTH,
3146 NULL);
3147 if (IS_ERR(ptr: blob))
3148 return NULL;
3149
3150 lut = blob->data;
3151
3152 for (i = 0; i < LEGACY_LUT_LENGTH; i++) {
3153 u32 val = intel_de_read_fw(i915: dev_priv, PALETTE(pipe, i));
3154
3155 i9xx_lut_8_pack(entry: &lut[i], val);
3156 }
3157
3158 return blob;
3159}
3160
3161static struct drm_property_blob *i9xx_read_lut_10(struct intel_crtc *crtc)
3162{
3163 struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev);
3164 u32 lut_size = DISPLAY_INFO(dev_priv)->color.gamma_lut_size;
3165 enum pipe pipe = crtc->pipe;
3166 struct drm_property_blob *blob;
3167 struct drm_color_lut *lut;
3168 u32 ldw, udw;
3169 int i;
3170
3171 blob = drm_property_create_blob(dev: &dev_priv->drm,
3172 length: lut_size * sizeof(lut[0]), NULL);
3173 if (IS_ERR(ptr: blob))
3174 return NULL;
3175
3176 lut = blob->data;
3177
3178 for (i = 0; i < lut_size - 1; i++) {
3179 ldw = intel_de_read_fw(i915: dev_priv, PALETTE(pipe, 2 * i + 0));
3180 udw = intel_de_read_fw(i915: dev_priv, PALETTE(pipe, 2 * i + 1));
3181
3182 i9xx_lut_10_pack(color: &lut[i], ldw, udw);
3183 }
3184
3185 i9xx_lut_10_pack_slope(color: &lut[i], ldw, udw);
3186
3187 return blob;
3188}
3189
3190static void i9xx_read_luts(struct intel_crtc_state *crtc_state)
3191{
3192 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
3193
3194 if (!crtc_state->gamma_enable && !crtc_state->c8_planes)
3195 return;
3196
3197 switch (crtc_state->gamma_mode) {
3198 case GAMMA_MODE_MODE_8BIT:
3199 crtc_state->post_csc_lut = i9xx_read_lut_8(crtc);
3200 break;
3201 case GAMMA_MODE_MODE_10BIT:
3202 crtc_state->post_csc_lut = i9xx_read_lut_10(crtc);
3203 break;
3204 default:
3205 MISSING_CASE(crtc_state->gamma_mode);
3206 break;
3207 }
3208}
3209
3210static struct drm_property_blob *i965_read_lut_10p6(struct intel_crtc *crtc)
3211{
3212 struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev);
3213 int i, lut_size = DISPLAY_INFO(dev_priv)->color.gamma_lut_size;
3214 enum pipe pipe = crtc->pipe;
3215 struct drm_property_blob *blob;
3216 struct drm_color_lut *lut;
3217
3218 blob = drm_property_create_blob(dev: &dev_priv->drm,
3219 length: sizeof(lut[0]) * lut_size,
3220 NULL);
3221 if (IS_ERR(ptr: blob))
3222 return NULL;
3223
3224 lut = blob->data;
3225
3226 for (i = 0; i < lut_size - 1; i++) {
3227 u32 ldw = intel_de_read_fw(i915: dev_priv, PALETTE(pipe, 2 * i + 0));
3228 u32 udw = intel_de_read_fw(i915: dev_priv, PALETTE(pipe, 2 * i + 1));
3229
3230 i965_lut_10p6_pack(entry: &lut[i], ldw, udw);
3231 }
3232
3233 lut[i].red = i965_lut_11p6_max_pack(val: intel_de_read_fw(i915: dev_priv, PIPEGCMAX(pipe, 0)));
3234 lut[i].green = i965_lut_11p6_max_pack(val: intel_de_read_fw(i915: dev_priv, PIPEGCMAX(pipe, 1)));
3235 lut[i].blue = i965_lut_11p6_max_pack(val: intel_de_read_fw(i915: dev_priv, PIPEGCMAX(pipe, 2)));
3236
3237 return blob;
3238}
3239
3240static void i965_read_luts(struct intel_crtc_state *crtc_state)
3241{
3242 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
3243
3244 if (!crtc_state->gamma_enable && !crtc_state->c8_planes)
3245 return;
3246
3247 switch (crtc_state->gamma_mode) {
3248 case GAMMA_MODE_MODE_8BIT:
3249 crtc_state->post_csc_lut = i9xx_read_lut_8(crtc);
3250 break;
3251 case GAMMA_MODE_MODE_10BIT:
3252 crtc_state->post_csc_lut = i965_read_lut_10p6(crtc);
3253 break;
3254 default:
3255 MISSING_CASE(crtc_state->gamma_mode);
3256 break;
3257 }
3258}
3259
3260static struct drm_property_blob *chv_read_cgm_degamma(struct intel_crtc *crtc)
3261{
3262 struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev);
3263 int i, lut_size = DISPLAY_INFO(dev_priv)->color.degamma_lut_size;
3264 enum pipe pipe = crtc->pipe;
3265 struct drm_property_blob *blob;
3266 struct drm_color_lut *lut;
3267
3268 blob = drm_property_create_blob(dev: &dev_priv->drm,
3269 length: sizeof(lut[0]) * lut_size,
3270 NULL);
3271 if (IS_ERR(ptr: blob))
3272 return NULL;
3273
3274 lut = blob->data;
3275
3276 for (i = 0; i < lut_size; i++) {
3277 u32 ldw = intel_de_read_fw(i915: dev_priv, CGM_PIPE_DEGAMMA(pipe, i, 0));
3278 u32 udw = intel_de_read_fw(i915: dev_priv, CGM_PIPE_DEGAMMA(pipe, i, 1));
3279
3280 chv_cgm_degamma_pack(entry: &lut[i], ldw, udw);
3281 }
3282
3283 return blob;
3284}
3285
3286static struct drm_property_blob *chv_read_cgm_gamma(struct intel_crtc *crtc)
3287{
3288 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
3289 int i, lut_size = DISPLAY_INFO(i915)->color.gamma_lut_size;
3290 enum pipe pipe = crtc->pipe;
3291 struct drm_property_blob *blob;
3292 struct drm_color_lut *lut;
3293
3294 blob = drm_property_create_blob(dev: &i915->drm,
3295 length: sizeof(lut[0]) * lut_size,
3296 NULL);
3297 if (IS_ERR(ptr: blob))
3298 return NULL;
3299
3300 lut = blob->data;
3301
3302 for (i = 0; i < lut_size; i++) {
3303 u32 ldw = intel_de_read_fw(i915, CGM_PIPE_GAMMA(pipe, i, 0));
3304 u32 udw = intel_de_read_fw(i915, CGM_PIPE_GAMMA(pipe, i, 1));
3305
3306 chv_cgm_gamma_pack(entry: &lut[i], ldw, udw);
3307 }
3308
3309 return blob;
3310}
3311
3312static void chv_get_config(struct intel_crtc_state *crtc_state)
3313{
3314 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
3315 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
3316
3317 crtc_state->cgm_mode = intel_de_read(i915, CGM_PIPE_MODE(crtc->pipe));
3318
3319 i9xx_get_config(crtc_state);
3320}
3321
3322static void chv_read_luts(struct intel_crtc_state *crtc_state)
3323{
3324 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
3325
3326 if (crtc_state->cgm_mode & CGM_PIPE_MODE_DEGAMMA)
3327 crtc_state->pre_csc_lut = chv_read_cgm_degamma(crtc);
3328
3329 if (crtc_state->cgm_mode & CGM_PIPE_MODE_GAMMA)
3330 crtc_state->post_csc_lut = chv_read_cgm_gamma(crtc);
3331 else
3332 i965_read_luts(crtc_state);
3333}
3334
3335static struct drm_property_blob *ilk_read_lut_8(struct intel_crtc *crtc)
3336{
3337 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
3338 enum pipe pipe = crtc->pipe;
3339 struct drm_property_blob *blob;
3340 struct drm_color_lut *lut;
3341 int i;
3342
3343 blob = drm_property_create_blob(dev: &i915->drm,
3344 length: sizeof(lut[0]) * LEGACY_LUT_LENGTH,
3345 NULL);
3346 if (IS_ERR(ptr: blob))
3347 return NULL;
3348
3349 lut = blob->data;
3350
3351 for (i = 0; i < LEGACY_LUT_LENGTH; i++) {
3352 u32 val = intel_de_read_fw(i915, LGC_PALETTE(pipe, i));
3353
3354 i9xx_lut_8_pack(entry: &lut[i], val);
3355 }
3356
3357 return blob;
3358}
3359
3360static struct drm_property_blob *ilk_read_lut_10(struct intel_crtc *crtc)
3361{
3362 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
3363 int i, lut_size = DISPLAY_INFO(i915)->color.gamma_lut_size;
3364 enum pipe pipe = crtc->pipe;
3365 struct drm_property_blob *blob;
3366 struct drm_color_lut *lut;
3367
3368 blob = drm_property_create_blob(dev: &i915->drm,
3369 length: sizeof(lut[0]) * lut_size,
3370 NULL);
3371 if (IS_ERR(ptr: blob))
3372 return NULL;
3373
3374 lut = blob->data;
3375
3376 for (i = 0; i < lut_size; i++) {
3377 u32 val = intel_de_read_fw(i915, PREC_PALETTE(pipe, i));
3378
3379 ilk_lut_10_pack(entry: &lut[i], val);
3380 }
3381
3382 return blob;
3383}
3384
3385static void ilk_get_config(struct intel_crtc_state *crtc_state)
3386{
3387 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
3388
3389 crtc_state->csc_mode = ilk_read_csc_mode(crtc);
3390
3391 i9xx_get_config(crtc_state);
3392}
3393
3394static void ilk_read_luts(struct intel_crtc_state *crtc_state)
3395{
3396 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
3397 struct drm_property_blob **blob =
3398 ilk_has_post_csc_lut(crtc_state) ?
3399 &crtc_state->post_csc_lut : &crtc_state->pre_csc_lut;
3400
3401 if (!crtc_state->gamma_enable && !crtc_state->c8_planes)
3402 return;
3403
3404 switch (crtc_state->gamma_mode) {
3405 case GAMMA_MODE_MODE_8BIT:
3406 *blob = ilk_read_lut_8(crtc);
3407 break;
3408 case GAMMA_MODE_MODE_10BIT:
3409 *blob = ilk_read_lut_10(crtc);
3410 break;
3411 default:
3412 MISSING_CASE(crtc_state->gamma_mode);
3413 break;
3414 }
3415}
3416
3417/*
3418 * IVB/HSW Bspec / PAL_PREC_INDEX:
3419 * "Restriction : Index auto increment mode is not
3420 * supported and must not be enabled."
3421 */
3422static struct drm_property_blob *ivb_read_lut_10(struct intel_crtc *crtc,
3423 u32 prec_index)
3424{
3425 struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev);
3426 int i, lut_size = ivb_lut_10_size(prec_index);
3427 enum pipe pipe = crtc->pipe;
3428 struct drm_property_blob *blob;
3429 struct drm_color_lut *lut;
3430
3431 blob = drm_property_create_blob(dev: &dev_priv->drm,
3432 length: sizeof(lut[0]) * lut_size,
3433 NULL);
3434 if (IS_ERR(ptr: blob))
3435 return NULL;
3436
3437 lut = blob->data;
3438
3439 for (i = 0; i < lut_size; i++) {
3440 u32 val;
3441
3442 intel_de_write_fw(i915: dev_priv, PREC_PAL_INDEX(pipe),
3443 val: prec_index + i);
3444 val = intel_de_read_fw(i915: dev_priv, PREC_PAL_DATA(pipe));
3445
3446 ilk_lut_10_pack(entry: &lut[i], val);
3447 }
3448
3449 intel_de_write_fw(i915: dev_priv, PREC_PAL_INDEX(pipe),
3450 PAL_PREC_INDEX_VALUE(0));
3451
3452 return blob;
3453}
3454
3455static void ivb_read_luts(struct intel_crtc_state *crtc_state)
3456{
3457 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
3458 struct drm_property_blob **blob =
3459 ilk_has_post_csc_lut(crtc_state) ?
3460 &crtc_state->post_csc_lut : &crtc_state->pre_csc_lut;
3461
3462 if (!crtc_state->gamma_enable && !crtc_state->c8_planes)
3463 return;
3464
3465 switch (crtc_state->gamma_mode) {
3466 case GAMMA_MODE_MODE_8BIT:
3467 *blob = ilk_read_lut_8(crtc);
3468 break;
3469 case GAMMA_MODE_MODE_SPLIT:
3470 crtc_state->pre_csc_lut =
3471 ivb_read_lut_10(crtc, PAL_PREC_SPLIT_MODE |
3472 PAL_PREC_INDEX_VALUE(0));
3473 crtc_state->post_csc_lut =
3474 ivb_read_lut_10(crtc, PAL_PREC_SPLIT_MODE |
3475 PAL_PREC_INDEX_VALUE(512));
3476 break;
3477 case GAMMA_MODE_MODE_10BIT:
3478 *blob = ivb_read_lut_10(crtc, PAL_PREC_INDEX_VALUE(0));
3479 break;
3480 default:
3481 MISSING_CASE(crtc_state->gamma_mode);
3482 break;
3483 }
3484}
3485
3486/* On BDW+ the index auto increment mode actually works */
3487static struct drm_property_blob *bdw_read_lut_10(struct intel_crtc *crtc,
3488 u32 prec_index)
3489{
3490 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
3491 int i, lut_size = ivb_lut_10_size(prec_index);
3492 enum pipe pipe = crtc->pipe;
3493 struct drm_property_blob *blob;
3494 struct drm_color_lut *lut;
3495
3496 blob = drm_property_create_blob(dev: &i915->drm,
3497 length: sizeof(lut[0]) * lut_size,
3498 NULL);
3499 if (IS_ERR(ptr: blob))
3500 return NULL;
3501
3502 lut = blob->data;
3503
3504 intel_de_write_fw(i915, PREC_PAL_INDEX(pipe),
3505 val: prec_index);
3506 intel_de_write_fw(i915, PREC_PAL_INDEX(pipe),
3507 PAL_PREC_AUTO_INCREMENT |
3508 prec_index);
3509
3510 for (i = 0; i < lut_size; i++) {
3511 u32 val = intel_de_read_fw(i915, PREC_PAL_DATA(pipe));
3512
3513 ilk_lut_10_pack(entry: &lut[i], val);
3514 }
3515
3516 intel_de_write_fw(i915, PREC_PAL_INDEX(pipe),
3517 PAL_PREC_INDEX_VALUE(0));
3518
3519 return blob;
3520}
3521
3522static void bdw_read_luts(struct intel_crtc_state *crtc_state)
3523{
3524 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
3525 struct drm_property_blob **blob =
3526 ilk_has_post_csc_lut(crtc_state) ?
3527 &crtc_state->post_csc_lut : &crtc_state->pre_csc_lut;
3528
3529 if (!crtc_state->gamma_enable && !crtc_state->c8_planes)
3530 return;
3531
3532 switch (crtc_state->gamma_mode) {
3533 case GAMMA_MODE_MODE_8BIT:
3534 *blob = ilk_read_lut_8(crtc);
3535 break;
3536 case GAMMA_MODE_MODE_SPLIT:
3537 crtc_state->pre_csc_lut =
3538 bdw_read_lut_10(crtc, PAL_PREC_SPLIT_MODE |
3539 PAL_PREC_INDEX_VALUE(0));
3540 crtc_state->post_csc_lut =
3541 bdw_read_lut_10(crtc, PAL_PREC_SPLIT_MODE |
3542 PAL_PREC_INDEX_VALUE(512));
3543 break;
3544 case GAMMA_MODE_MODE_10BIT:
3545 *blob = bdw_read_lut_10(crtc, PAL_PREC_INDEX_VALUE(0));
3546 break;
3547 default:
3548 MISSING_CASE(crtc_state->gamma_mode);
3549 break;
3550 }
3551}
3552
3553static struct drm_property_blob *glk_read_degamma_lut(struct intel_crtc *crtc)
3554{
3555 struct drm_i915_private *dev_priv = to_i915(dev: crtc->base.dev);
3556 int i, lut_size = DISPLAY_INFO(dev_priv)->color.degamma_lut_size;
3557 enum pipe pipe = crtc->pipe;
3558 struct drm_property_blob *blob;
3559 struct drm_color_lut *lut;
3560
3561 blob = drm_property_create_blob(dev: &dev_priv->drm,
3562 length: sizeof(lut[0]) * lut_size,
3563 NULL);
3564 if (IS_ERR(ptr: blob))
3565 return NULL;
3566
3567 lut = blob->data;
3568
3569 /*
3570 * When setting the auto-increment bit, the hardware seems to
3571 * ignore the index bits, so we need to reset it to index 0
3572 * separately.
3573 */
3574 intel_de_write_fw(i915: dev_priv, PRE_CSC_GAMC_INDEX(pipe),
3575 PRE_CSC_GAMC_INDEX_VALUE(0));
3576 intel_de_write_fw(i915: dev_priv, PRE_CSC_GAMC_INDEX(pipe),
3577 PRE_CSC_GAMC_AUTO_INCREMENT |
3578 PRE_CSC_GAMC_INDEX_VALUE(0));
3579
3580 for (i = 0; i < lut_size; i++) {
3581 u32 val = intel_de_read_fw(i915: dev_priv, PRE_CSC_GAMC_DATA(pipe));
3582
3583 if (DISPLAY_VER(dev_priv) >= 14)
3584 mtl_degamma_lut_pack(entry: &lut[i], val);
3585 else
3586 glk_degamma_lut_pack(entry: &lut[i], val);
3587 }
3588
3589 intel_de_write_fw(i915: dev_priv, PRE_CSC_GAMC_INDEX(pipe),
3590 PRE_CSC_GAMC_INDEX_VALUE(0));
3591
3592 return blob;
3593}
3594
3595static void glk_read_luts(struct intel_crtc_state *crtc_state)
3596{
3597 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
3598
3599 if (crtc_state->csc_enable)
3600 crtc_state->pre_csc_lut = glk_read_degamma_lut(crtc);
3601
3602 if (!crtc_state->gamma_enable && !crtc_state->c8_planes)
3603 return;
3604
3605 switch (crtc_state->gamma_mode) {
3606 case GAMMA_MODE_MODE_8BIT:
3607 crtc_state->post_csc_lut = ilk_read_lut_8(crtc);
3608 break;
3609 case GAMMA_MODE_MODE_10BIT:
3610 crtc_state->post_csc_lut = bdw_read_lut_10(crtc, PAL_PREC_INDEX_VALUE(0));
3611 break;
3612 default:
3613 MISSING_CASE(crtc_state->gamma_mode);
3614 break;
3615 }
3616}
3617
3618static struct drm_property_blob *
3619icl_read_lut_multi_segment(struct intel_crtc *crtc)
3620{
3621 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
3622 int i, lut_size = DISPLAY_INFO(i915)->color.gamma_lut_size;
3623 enum pipe pipe = crtc->pipe;
3624 struct drm_property_blob *blob;
3625 struct drm_color_lut *lut;
3626
3627 blob = drm_property_create_blob(dev: &i915->drm,
3628 length: sizeof(lut[0]) * lut_size,
3629 NULL);
3630 if (IS_ERR(ptr: blob))
3631 return NULL;
3632
3633 lut = blob->data;
3634
3635 intel_de_write_fw(i915, PREC_PAL_MULTI_SEG_INDEX(pipe),
3636 PAL_PREC_MULTI_SEG_INDEX_VALUE(0));
3637 intel_de_write_fw(i915, PREC_PAL_MULTI_SEG_INDEX(pipe),
3638 PAL_PREC_MULTI_SEG_AUTO_INCREMENT |
3639 PAL_PREC_MULTI_SEG_INDEX_VALUE(0));
3640
3641 for (i = 0; i < 9; i++) {
3642 u32 ldw = intel_de_read_fw(i915, PREC_PAL_MULTI_SEG_DATA(pipe));
3643 u32 udw = intel_de_read_fw(i915, PREC_PAL_MULTI_SEG_DATA(pipe));
3644
3645 ilk_lut_12p4_pack(entry: &lut[i], ldw, udw);
3646 }
3647
3648 intel_de_write_fw(i915, PREC_PAL_MULTI_SEG_INDEX(pipe),
3649 PAL_PREC_MULTI_SEG_INDEX_VALUE(0));
3650
3651 /*
3652 * FIXME readouts from PAL_PREC_DATA register aren't giving
3653 * correct values in the case of fine and coarse segments.
3654 * Restricting readouts only for super fine segment as of now.
3655 */
3656
3657 return blob;
3658}
3659
3660static void icl_read_luts(struct intel_crtc_state *crtc_state)
3661{
3662 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
3663
3664 if (icl_has_pre_csc_lut(crtc_state))
3665 crtc_state->pre_csc_lut = glk_read_degamma_lut(crtc);
3666
3667 if (!icl_has_post_csc_lut(crtc_state))
3668 return;
3669
3670 switch (crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) {
3671 case GAMMA_MODE_MODE_8BIT:
3672 crtc_state->post_csc_lut = ilk_read_lut_8(crtc);
3673 break;
3674 case GAMMA_MODE_MODE_10BIT:
3675 crtc_state->post_csc_lut = bdw_read_lut_10(crtc, PAL_PREC_INDEX_VALUE(0));
3676 break;
3677 case GAMMA_MODE_MODE_12BIT_MULTI_SEG:
3678 crtc_state->post_csc_lut = icl_read_lut_multi_segment(crtc);
3679 break;
3680 default:
3681 MISSING_CASE(crtc_state->gamma_mode);
3682 break;
3683 }
3684}
3685
3686static const struct intel_color_funcs chv_color_funcs = {
3687 .color_check = chv_color_check,
3688 .color_commit_arm = i9xx_color_commit_arm,
3689 .load_luts = chv_load_luts,
3690 .read_luts = chv_read_luts,
3691 .lut_equal = chv_lut_equal,
3692 .read_csc = chv_read_csc,
3693 .get_config = chv_get_config,
3694};
3695
3696static const struct intel_color_funcs vlv_color_funcs = {
3697 .color_check = vlv_color_check,
3698 .color_commit_arm = i9xx_color_commit_arm,
3699 .load_luts = vlv_load_luts,
3700 .read_luts = i965_read_luts,
3701 .lut_equal = i965_lut_equal,
3702 .read_csc = vlv_read_csc,
3703 .get_config = i9xx_get_config,
3704};
3705
3706static const struct intel_color_funcs i965_color_funcs = {
3707 .color_check = i9xx_color_check,
3708 .color_commit_arm = i9xx_color_commit_arm,
3709 .load_luts = i965_load_luts,
3710 .read_luts = i965_read_luts,
3711 .lut_equal = i965_lut_equal,
3712 .get_config = i9xx_get_config,
3713};
3714
3715static const struct intel_color_funcs i9xx_color_funcs = {
3716 .color_check = i9xx_color_check,
3717 .color_commit_arm = i9xx_color_commit_arm,
3718 .load_luts = i9xx_load_luts,
3719 .read_luts = i9xx_read_luts,
3720 .lut_equal = i9xx_lut_equal,
3721 .get_config = i9xx_get_config,
3722};
3723
3724static const struct intel_color_funcs tgl_color_funcs = {
3725 .color_check = icl_color_check,
3726 .color_commit_noarm = icl_color_commit_noarm,
3727 .color_commit_arm = icl_color_commit_arm,
3728 .load_luts = icl_load_luts,
3729 .read_luts = icl_read_luts,
3730 .lut_equal = icl_lut_equal,
3731 .read_csc = icl_read_csc,
3732 .get_config = skl_get_config,
3733};
3734
3735static const struct intel_color_funcs icl_color_funcs = {
3736 .color_check = icl_color_check,
3737 .color_commit_noarm = icl_color_commit_noarm,
3738 .color_commit_arm = icl_color_commit_arm,
3739 .color_post_update = icl_color_post_update,
3740 .load_luts = icl_load_luts,
3741 .read_luts = icl_read_luts,
3742 .lut_equal = icl_lut_equal,
3743 .read_csc = icl_read_csc,
3744 .get_config = skl_get_config,
3745};
3746
3747static const struct intel_color_funcs glk_color_funcs = {
3748 .color_check = glk_color_check,
3749 .color_commit_noarm = skl_color_commit_noarm,
3750 .color_commit_arm = skl_color_commit_arm,
3751 .load_luts = glk_load_luts,
3752 .read_luts = glk_read_luts,
3753 .lut_equal = glk_lut_equal,
3754 .read_csc = skl_read_csc,
3755 .get_config = skl_get_config,
3756};
3757
3758static const struct intel_color_funcs skl_color_funcs = {
3759 .color_check = ivb_color_check,
3760 .color_commit_noarm = skl_color_commit_noarm,
3761 .color_commit_arm = skl_color_commit_arm,
3762 .load_luts = bdw_load_luts,
3763 .read_luts = bdw_read_luts,
3764 .lut_equal = ivb_lut_equal,
3765 .read_csc = skl_read_csc,
3766 .get_config = skl_get_config,
3767};
3768
3769static const struct intel_color_funcs bdw_color_funcs = {
3770 .color_check = ivb_color_check,
3771 .color_commit_noarm = ilk_color_commit_noarm,
3772 .color_commit_arm = hsw_color_commit_arm,
3773 .load_luts = bdw_load_luts,
3774 .read_luts = bdw_read_luts,
3775 .lut_equal = ivb_lut_equal,
3776 .read_csc = ilk_read_csc,
3777 .get_config = hsw_get_config,
3778};
3779
3780static const struct intel_color_funcs hsw_color_funcs = {
3781 .color_check = ivb_color_check,
3782 .color_commit_noarm = ilk_color_commit_noarm,
3783 .color_commit_arm = hsw_color_commit_arm,
3784 .load_luts = ivb_load_luts,
3785 .read_luts = ivb_read_luts,
3786 .lut_equal = ivb_lut_equal,
3787 .read_csc = ilk_read_csc,
3788 .get_config = hsw_get_config,
3789};
3790
3791static const struct intel_color_funcs ivb_color_funcs = {
3792 .color_check = ivb_color_check,
3793 .color_commit_noarm = ilk_color_commit_noarm,
3794 .color_commit_arm = ilk_color_commit_arm,
3795 .load_luts = ivb_load_luts,
3796 .read_luts = ivb_read_luts,
3797 .lut_equal = ivb_lut_equal,
3798 .read_csc = ilk_read_csc,
3799 .get_config = ilk_get_config,
3800};
3801
3802static const struct intel_color_funcs ilk_color_funcs = {
3803 .color_check = ilk_color_check,
3804 .color_commit_noarm = ilk_color_commit_noarm,
3805 .color_commit_arm = ilk_color_commit_arm,
3806 .load_luts = ilk_load_luts,
3807 .read_luts = ilk_read_luts,
3808 .lut_equal = ilk_lut_equal,
3809 .read_csc = ilk_read_csc,
3810 .get_config = ilk_get_config,
3811};
3812
3813void intel_color_crtc_init(struct intel_crtc *crtc)
3814{
3815 struct drm_i915_private *i915 = to_i915(dev: crtc->base.dev);
3816 int degamma_lut_size, gamma_lut_size;
3817 bool has_ctm;
3818
3819 drm_mode_crtc_set_gamma_size(crtc: &crtc->base, gamma_size: 256);
3820
3821 gamma_lut_size = DISPLAY_INFO(i915)->color.gamma_lut_size;
3822 degamma_lut_size = DISPLAY_INFO(i915)->color.degamma_lut_size;
3823 has_ctm = DISPLAY_VER(i915) >= 5;
3824
3825 /*
3826 * "DPALETTE_A: NOTE: The 8-bit (non-10-bit) mode is the
3827 * only mode supported by Alviso and Grantsdale."
3828 *
3829 * Actually looks like this affects all of gen3.
3830 * Confirmed on alv,cst,pnv. Mobile gen2 parts (alm,mgm)
3831 * are confirmed not to suffer from this restriction.
3832 */
3833 if (DISPLAY_VER(i915) == 3 && crtc->pipe == PIPE_A)
3834 gamma_lut_size = 256;
3835
3836 drm_crtc_enable_color_mgmt(crtc: &crtc->base, degamma_lut_size,
3837 has_ctm, gamma_lut_size);
3838}
3839
3840int intel_color_init(struct drm_i915_private *i915)
3841{
3842 struct drm_property_blob *blob;
3843
3844 if (DISPLAY_VER(i915) != 10)
3845 return 0;
3846
3847 blob = create_linear_lut(i915,
3848 DISPLAY_INFO(i915)->color.degamma_lut_size);
3849 if (IS_ERR(ptr: blob))
3850 return PTR_ERR(ptr: blob);
3851
3852 i915->display.color.glk_linear_degamma_lut = blob;
3853
3854 return 0;
3855}
3856
3857void intel_color_init_hooks(struct drm_i915_private *i915)
3858{
3859 if (HAS_GMCH(i915)) {
3860 if (IS_CHERRYVIEW(i915))
3861 i915->display.funcs.color = &chv_color_funcs;
3862 else if (IS_VALLEYVIEW(i915))
3863 i915->display.funcs.color = &vlv_color_funcs;
3864 else if (DISPLAY_VER(i915) >= 4)
3865 i915->display.funcs.color = &i965_color_funcs;
3866 else
3867 i915->display.funcs.color = &i9xx_color_funcs;
3868 } else {
3869 if (DISPLAY_VER(i915) >= 12)
3870 i915->display.funcs.color = &tgl_color_funcs;
3871 else if (DISPLAY_VER(i915) == 11)
3872 i915->display.funcs.color = &icl_color_funcs;
3873 else if (DISPLAY_VER(i915) == 10)
3874 i915->display.funcs.color = &glk_color_funcs;
3875 else if (DISPLAY_VER(i915) == 9)
3876 i915->display.funcs.color = &skl_color_funcs;
3877 else if (DISPLAY_VER(i915) == 8)
3878 i915->display.funcs.color = &bdw_color_funcs;
3879 else if (IS_HASWELL(i915))
3880 i915->display.funcs.color = &hsw_color_funcs;
3881 else if (DISPLAY_VER(i915) == 7)
3882 i915->display.funcs.color = &ivb_color_funcs;
3883 else
3884 i915->display.funcs.color = &ilk_color_funcs;
3885 }
3886}
3887

source code of linux/drivers/gpu/drm/i915/display/intel_color.c