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