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