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