]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/gpu/drm/i915/intel_color.c
drm/i915/glk: Fix degamma lut programming
[linux.git] / drivers / gpu / drm / i915 / intel_color.c
1 /*
2  * Copyright © 2016 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  */
24
25 #include "intel_drv.h"
26
27 #define CTM_COEFF_SIGN  (1ULL << 63)
28
29 #define CTM_COEFF_1_0   (1ULL << 32)
30 #define CTM_COEFF_2_0   (CTM_COEFF_1_0 << 1)
31 #define CTM_COEFF_4_0   (CTM_COEFF_2_0 << 1)
32 #define CTM_COEFF_8_0   (CTM_COEFF_4_0 << 1)
33 #define CTM_COEFF_0_5   (CTM_COEFF_1_0 >> 1)
34 #define CTM_COEFF_0_25  (CTM_COEFF_0_5 >> 1)
35 #define CTM_COEFF_0_125 (CTM_COEFF_0_25 >> 1)
36
37 #define CTM_COEFF_LIMITED_RANGE ((235ULL - 16ULL) * CTM_COEFF_1_0 / 255)
38
39 #define CTM_COEFF_NEGATIVE(coeff)       (((coeff) & CTM_COEFF_SIGN) != 0)
40 #define CTM_COEFF_ABS(coeff)            ((coeff) & (CTM_COEFF_SIGN - 1))
41
42 #define LEGACY_LUT_LENGTH               256
43
44 /* Post offset values for RGB->YCBCR conversion */
45 #define POSTOFF_RGB_TO_YUV_HI 0x800
46 #define POSTOFF_RGB_TO_YUV_ME 0x100
47 #define POSTOFF_RGB_TO_YUV_LO 0x800
48
49 /*
50  * These values are direct register values specified in the Bspec,
51  * for RGB->YUV conversion matrix (colorspace BT709)
52  */
53 #define CSC_RGB_TO_YUV_RU_GU 0x2ba809d8
54 #define CSC_RGB_TO_YUV_BU 0x37e80000
55 #define CSC_RGB_TO_YUV_RY_GY 0x1e089cc0
56 #define CSC_RGB_TO_YUV_BY 0xb5280000
57 #define CSC_RGB_TO_YUV_RV_GV 0xbce89ad8
58 #define CSC_RGB_TO_YUV_BV 0x1e080000
59
60 /*
61  * Extract the CSC coefficient from a CTM coefficient (in U32.32 fixed point
62  * format). This macro takes the coefficient we want transformed and the
63  * number of fractional bits.
64  *
65  * We only have a 9 bits precision window which slides depending on the value
66  * of the CTM coefficient and we write the value from bit 3. We also round the
67  * value.
68  */
69 #define ILK_CSC_COEFF_FP(coeff, fbits)  \
70         (clamp_val(((coeff) >> (32 - (fbits) - 3)) + 4, 0, 0xfff) & 0xff8)
71
72 #define ILK_CSC_COEFF_LIMITED_RANGE     \
73         ILK_CSC_COEFF_FP(CTM_COEFF_LIMITED_RANGE, 9)
74 #define ILK_CSC_COEFF_1_0               \
75         ((7 << 12) | ILK_CSC_COEFF_FP(CTM_COEFF_1_0, 8))
76
77 static bool lut_is_legacy(const struct drm_property_blob *lut)
78 {
79         return drm_color_lut_size(lut) == LEGACY_LUT_LENGTH;
80 }
81
82 static bool crtc_state_is_legacy_gamma(const struct intel_crtc_state *crtc_state)
83 {
84         return !crtc_state->base.degamma_lut &&
85                 !crtc_state->base.ctm &&
86                 crtc_state->base.gamma_lut &&
87                 lut_is_legacy(crtc_state->base.gamma_lut);
88 }
89
90 /*
91  * When using limited range, multiply the matrix given by userspace by
92  * the matrix that we would use for the limited range.
93  */
94 static u64 *ctm_mult_by_limited(u64 *result, const u64 *input)
95 {
96         int i;
97
98         for (i = 0; i < 9; i++) {
99                 u64 user_coeff = input[i];
100                 u32 limited_coeff = CTM_COEFF_LIMITED_RANGE;
101                 u32 abs_coeff = clamp_val(CTM_COEFF_ABS(user_coeff), 0,
102                                           CTM_COEFF_4_0 - 1) >> 2;
103
104                 /*
105                  * By scaling every co-efficient with limited range (16-235)
106                  * vs full range (0-255) the final o/p will be scaled down to
107                  * fit in the limited range supported by the panel.
108                  */
109                 result[i] = mul_u32_u32(limited_coeff, abs_coeff) >> 30;
110                 result[i] |= user_coeff & CTM_COEFF_SIGN;
111         }
112
113         return result;
114 }
115
116 static void ilk_load_ycbcr_conversion_matrix(struct intel_crtc *crtc)
117 {
118         struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
119         enum pipe pipe = crtc->pipe;
120
121         I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), 0);
122         I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0);
123         I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), 0);
124
125         I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), CSC_RGB_TO_YUV_RU_GU);
126         I915_WRITE(PIPE_CSC_COEFF_BU(pipe), CSC_RGB_TO_YUV_BU);
127
128         I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), CSC_RGB_TO_YUV_RY_GY);
129         I915_WRITE(PIPE_CSC_COEFF_BY(pipe), CSC_RGB_TO_YUV_BY);
130
131         I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), CSC_RGB_TO_YUV_RV_GV);
132         I915_WRITE(PIPE_CSC_COEFF_BV(pipe), CSC_RGB_TO_YUV_BV);
133
134         I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), POSTOFF_RGB_TO_YUV_HI);
135         I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), POSTOFF_RGB_TO_YUV_ME);
136         I915_WRITE(PIPE_CSC_POSTOFF_LO(pipe), POSTOFF_RGB_TO_YUV_LO);
137         I915_WRITE(PIPE_CSC_MODE(pipe), 0);
138 }
139
140 static void ilk_load_csc_matrix(const struct intel_crtc_state *crtc_state)
141 {
142         struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
143         struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
144         bool limited_color_range = false;
145         enum pipe pipe = crtc->pipe;
146         u16 coeffs[9] = {};
147         int i;
148
149         /*
150          * FIXME if there's a gamma LUT after the CSC, we should
151          * do the range compression using the gamma LUT instead.
152          */
153         if (INTEL_GEN(dev_priv) >= 8 || IS_HASWELL(dev_priv))
154                 limited_color_range = crtc_state->limited_color_range;
155
156         if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ||
157             crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444) {
158                 ilk_load_ycbcr_conversion_matrix(crtc);
159                 return;
160         } else if (crtc_state->base.ctm) {
161                 struct drm_color_ctm *ctm = crtc_state->base.ctm->data;
162                 const u64 *input;
163                 u64 temp[9];
164
165                 if (limited_color_range)
166                         input = ctm_mult_by_limited(temp, ctm->matrix);
167                 else
168                         input = ctm->matrix;
169
170                 /*
171                  * Convert fixed point S31.32 input to format supported by the
172                  * hardware.
173                  */
174                 for (i = 0; i < ARRAY_SIZE(coeffs); i++) {
175                         u64 abs_coeff = ((1ULL << 63) - 1) & input[i];
176
177                         /*
178                          * Clamp input value to min/max supported by
179                          * hardware.
180                          */
181                         abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_4_0 - 1);
182
183                         /* sign bit */
184                         if (CTM_COEFF_NEGATIVE(input[i]))
185                                 coeffs[i] |= 1 << 15;
186
187                         if (abs_coeff < CTM_COEFF_0_125)
188                                 coeffs[i] |= (3 << 12) |
189                                         ILK_CSC_COEFF_FP(abs_coeff, 12);
190                         else if (abs_coeff < CTM_COEFF_0_25)
191                                 coeffs[i] |= (2 << 12) |
192                                         ILK_CSC_COEFF_FP(abs_coeff, 11);
193                         else if (abs_coeff < CTM_COEFF_0_5)
194                                 coeffs[i] |= (1 << 12) |
195                                         ILK_CSC_COEFF_FP(abs_coeff, 10);
196                         else if (abs_coeff < CTM_COEFF_1_0)
197                                 coeffs[i] |= ILK_CSC_COEFF_FP(abs_coeff, 9);
198                         else if (abs_coeff < CTM_COEFF_2_0)
199                                 coeffs[i] |= (7 << 12) |
200                                         ILK_CSC_COEFF_FP(abs_coeff, 8);
201                         else
202                                 coeffs[i] |= (6 << 12) |
203                                         ILK_CSC_COEFF_FP(abs_coeff, 7);
204                 }
205         } else {
206                 /*
207                  * Load an identity matrix if no coefficients are provided.
208                  *
209                  * TODO: Check what kind of values actually come out of the
210                  * pipe with these coeff/postoff values and adjust to get the
211                  * best accuracy. Perhaps we even need to take the bpc value
212                  * into consideration.
213                  */
214                 for (i = 0; i < 3; i++) {
215                         if (limited_color_range)
216                                 coeffs[i * 3 + i] =
217                                         ILK_CSC_COEFF_LIMITED_RANGE;
218                         else
219                                 coeffs[i * 3 + i] = ILK_CSC_COEFF_1_0;
220                 }
221         }
222
223         I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), coeffs[0] << 16 | coeffs[1]);
224         I915_WRITE(PIPE_CSC_COEFF_BY(pipe), coeffs[2] << 16);
225
226         I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), coeffs[3] << 16 | coeffs[4]);
227         I915_WRITE(PIPE_CSC_COEFF_BU(pipe), coeffs[5] << 16);
228
229         I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), coeffs[6] << 16 | coeffs[7]);
230         I915_WRITE(PIPE_CSC_COEFF_BV(pipe), coeffs[8] << 16);
231
232         I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), 0);
233         I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0);
234         I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), 0);
235
236         if (INTEL_GEN(dev_priv) > 6) {
237                 u16 postoff = 0;
238
239                 if (limited_color_range)
240                         postoff = (16 * (1 << 12) / 255) & 0x1fff;
241
242                 I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff);
243                 I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), postoff);
244                 I915_WRITE(PIPE_CSC_POSTOFF_LO(pipe), postoff);
245
246                 I915_WRITE(PIPE_CSC_MODE(pipe), 0);
247         } else {
248                 u32 mode = CSC_MODE_YUV_TO_RGB;
249
250                 if (limited_color_range)
251                         mode |= CSC_BLACK_SCREEN_OFFSET;
252
253                 I915_WRITE(PIPE_CSC_MODE(pipe), mode);
254         }
255 }
256
257 /*
258  * Set up the pipe CSC unit on CherryView.
259  */
260 static void cherryview_load_csc_matrix(const struct intel_crtc_state *crtc_state)
261 {
262         struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
263         struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
264         enum pipe pipe = crtc->pipe;
265         u32 mode;
266
267         if (crtc_state->base.ctm) {
268                 const struct drm_color_ctm *ctm = crtc_state->base.ctm->data;
269                 u16 coeffs[9] = {};
270                 int i;
271
272                 for (i = 0; i < ARRAY_SIZE(coeffs); i++) {
273                         u64 abs_coeff =
274                                 ((1ULL << 63) - 1) & ctm->matrix[i];
275
276                         /* Round coefficient. */
277                         abs_coeff += 1 << (32 - 13);
278                         /* Clamp to hardware limits. */
279                         abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_8_0 - 1);
280
281                         /* Write coefficients in S3.12 format. */
282                         if (ctm->matrix[i] & (1ULL << 63))
283                                 coeffs[i] = 1 << 15;
284                         coeffs[i] |= ((abs_coeff >> 32) & 7) << 12;
285                         coeffs[i] |= (abs_coeff >> 20) & 0xfff;
286                 }
287
288                 I915_WRITE(CGM_PIPE_CSC_COEFF01(pipe),
289                            coeffs[1] << 16 | coeffs[0]);
290                 I915_WRITE(CGM_PIPE_CSC_COEFF23(pipe),
291                            coeffs[3] << 16 | coeffs[2]);
292                 I915_WRITE(CGM_PIPE_CSC_COEFF45(pipe),
293                            coeffs[5] << 16 | coeffs[4]);
294                 I915_WRITE(CGM_PIPE_CSC_COEFF67(pipe),
295                            coeffs[7] << 16 | coeffs[6]);
296                 I915_WRITE(CGM_PIPE_CSC_COEFF8(pipe), coeffs[8]);
297         }
298
299         mode = (crtc_state->base.ctm ? CGM_PIPE_MODE_CSC : 0);
300         if (!crtc_state_is_legacy_gamma(crtc_state)) {
301                 mode |= (crtc_state->base.degamma_lut ? CGM_PIPE_MODE_DEGAMMA : 0) |
302                         (crtc_state->base.gamma_lut ? CGM_PIPE_MODE_GAMMA : 0);
303         }
304         I915_WRITE(CGM_PIPE_MODE(pipe), mode);
305 }
306
307 /* Loads the legacy palette/gamma unit for the CRTC. */
308 static void i9xx_load_luts_internal(const struct intel_crtc_state *crtc_state,
309                                     const struct drm_property_blob *blob)
310 {
311         struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
312         struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
313         enum pipe pipe = crtc->pipe;
314         int i;
315
316         if (HAS_GMCH(dev_priv)) {
317                 if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI))
318                         assert_dsi_pll_enabled(dev_priv);
319                 else
320                         assert_pll_enabled(dev_priv, pipe);
321         }
322
323         if (blob) {
324                 const struct drm_color_lut *lut = blob->data;
325
326                 for (i = 0; i < 256; i++) {
327                         u32 word =
328                                 (drm_color_lut_extract(lut[i].red, 8) << 16) |
329                                 (drm_color_lut_extract(lut[i].green, 8) << 8) |
330                                 drm_color_lut_extract(lut[i].blue, 8);
331
332                         if (HAS_GMCH(dev_priv))
333                                 I915_WRITE(PALETTE(pipe, i), word);
334                         else
335                                 I915_WRITE(LGC_PALETTE(pipe, i), word);
336                 }
337         } else {
338                 for (i = 0; i < 256; i++) {
339                         u32 word = (i << 16) | (i << 8) | i;
340
341                         if (HAS_GMCH(dev_priv))
342                                 I915_WRITE(PALETTE(pipe, i), word);
343                         else
344                                 I915_WRITE(LGC_PALETTE(pipe, i), word);
345                 }
346         }
347 }
348
349 static void i9xx_load_luts(const struct intel_crtc_state *crtc_state)
350 {
351         i9xx_load_luts_internal(crtc_state, crtc_state->base.gamma_lut);
352 }
353
354 static void i9xx_color_commit(const struct intel_crtc_state *crtc_state)
355 {
356         struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
357         struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
358         enum pipe pipe = crtc->pipe;
359         u32 val;
360
361         val = I915_READ(PIPECONF(pipe));
362         val &= ~PIPECONF_GAMMA_MODE_MASK_I9XX;
363         val |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);
364         I915_WRITE(PIPECONF(pipe), val);
365 }
366
367 static void ilk_color_commit(const struct intel_crtc_state *crtc_state)
368 {
369         struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
370         struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
371         enum pipe pipe = crtc->pipe;
372         u32 val;
373
374         val = I915_READ(PIPECONF(pipe));
375         val &= ~PIPECONF_GAMMA_MODE_MASK_ILK;
376         val |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);
377         I915_WRITE(PIPECONF(pipe), val);
378 }
379
380 static void hsw_color_commit(const struct intel_crtc_state *crtc_state)
381 {
382         struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
383         struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
384
385         I915_WRITE(GAMMA_MODE(crtc->pipe), crtc_state->gamma_mode);
386
387         ilk_load_csc_matrix(crtc_state);
388 }
389
390 static void skl_color_commit(const struct intel_crtc_state *crtc_state)
391 {
392         struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
393         struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
394         enum pipe pipe = crtc->pipe;
395         u32 val = 0;
396
397         /*
398          * We don't (yet) allow userspace to control the pipe background color,
399          * so force it to black, but apply pipe gamma and CSC appropriately
400          * so that its handling will match how we program our planes.
401          */
402         if (crtc_state->gamma_enable)
403                 val |= SKL_BOTTOM_COLOR_GAMMA_ENABLE;
404         if (crtc_state->csc_enable)
405                 val |= SKL_BOTTOM_COLOR_CSC_ENABLE;
406         I915_WRITE(SKL_BOTTOM_COLOR(pipe), val);
407
408         I915_WRITE(GAMMA_MODE(crtc->pipe), crtc_state->gamma_mode);
409
410         ilk_load_csc_matrix(crtc_state);
411 }
412
413 static void bdw_load_degamma_lut(const struct intel_crtc_state *crtc_state)
414 {
415         struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
416         struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
417         const struct drm_property_blob *degamma_lut = crtc_state->base.degamma_lut;
418         u32 i, lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
419         enum pipe pipe = crtc->pipe;
420
421         I915_WRITE(PREC_PAL_INDEX(pipe),
422                    PAL_PREC_SPLIT_MODE | PAL_PREC_AUTO_INCREMENT);
423
424         if (degamma_lut) {
425                 const struct drm_color_lut *lut = degamma_lut->data;
426
427                 for (i = 0; i < lut_size; i++) {
428                         u32 word =
429                         drm_color_lut_extract(lut[i].red, 10) << 20 |
430                         drm_color_lut_extract(lut[i].green, 10) << 10 |
431                         drm_color_lut_extract(lut[i].blue, 10);
432
433                         I915_WRITE(PREC_PAL_DATA(pipe), word);
434                 }
435         } else {
436                 for (i = 0; i < lut_size; i++) {
437                         u32 v = (i * ((1 << 10) - 1)) / (lut_size - 1);
438
439                         I915_WRITE(PREC_PAL_DATA(pipe),
440                                    (v << 20) | (v << 10) | v);
441                 }
442         }
443 }
444
445 static void bdw_load_gamma_lut(const struct intel_crtc_state *crtc_state, u32 offset)
446 {
447         struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
448         struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
449         const struct drm_property_blob *gamma_lut = crtc_state->base.gamma_lut;
450         u32 i, lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
451         enum pipe pipe = crtc->pipe;
452
453         WARN_ON(offset & ~PAL_PREC_INDEX_VALUE_MASK);
454
455         I915_WRITE(PREC_PAL_INDEX(pipe),
456                    (offset ? PAL_PREC_SPLIT_MODE : 0) |
457                    PAL_PREC_AUTO_INCREMENT |
458                    offset);
459
460         if (gamma_lut) {
461                 const struct drm_color_lut *lut = gamma_lut->data;
462
463                 for (i = 0; i < lut_size; i++) {
464                         u32 word =
465                         (drm_color_lut_extract(lut[i].red, 10) << 20) |
466                         (drm_color_lut_extract(lut[i].green, 10) << 10) |
467                         drm_color_lut_extract(lut[i].blue, 10);
468
469                         I915_WRITE(PREC_PAL_DATA(pipe), word);
470                 }
471
472                 /* Program the max register to clamp values > 1.0. */
473                 i = lut_size - 1;
474                 I915_WRITE(PREC_PAL_GC_MAX(pipe, 0),
475                            drm_color_lut_extract(lut[i].red, 16));
476                 I915_WRITE(PREC_PAL_GC_MAX(pipe, 1),
477                            drm_color_lut_extract(lut[i].green, 16));
478                 I915_WRITE(PREC_PAL_GC_MAX(pipe, 2),
479                            drm_color_lut_extract(lut[i].blue, 16));
480         } else {
481                 for (i = 0; i < lut_size; i++) {
482                         u32 v = (i * ((1 << 10) - 1)) / (lut_size - 1);
483
484                         I915_WRITE(PREC_PAL_DATA(pipe),
485                                    (v << 20) | (v << 10) | v);
486                 }
487
488                 I915_WRITE(PREC_PAL_GC_MAX(pipe, 0), (1 << 16) - 1);
489                 I915_WRITE(PREC_PAL_GC_MAX(pipe, 1), (1 << 16) - 1);
490                 I915_WRITE(PREC_PAL_GC_MAX(pipe, 2), (1 << 16) - 1);
491         }
492
493         /*
494          * Reset the index, otherwise it prevents the legacy palette to be
495          * written properly.
496          */
497         I915_WRITE(PREC_PAL_INDEX(pipe), 0);
498 }
499
500 /* Loads the palette/gamma unit for the CRTC on Broadwell+. */
501 static void broadwell_load_luts(const struct intel_crtc_state *crtc_state)
502 {
503         struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
504         struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
505
506         if (crtc_state_is_legacy_gamma(crtc_state)) {
507                 i9xx_load_luts(crtc_state);
508         } else {
509                 bdw_load_degamma_lut(crtc_state);
510                 bdw_load_gamma_lut(crtc_state,
511                                    INTEL_INFO(dev_priv)->color.degamma_lut_size);
512         }
513 }
514
515 static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state)
516 {
517         struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
518         struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
519         enum pipe pipe = crtc->pipe;
520         const u32 lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
521         u32 i;
522
523         /*
524          * When setting the auto-increment bit, the hardware seems to
525          * ignore the index bits, so we need to reset it to index 0
526          * separately.
527          */
528         I915_WRITE(PRE_CSC_GAMC_INDEX(pipe), 0);
529         I915_WRITE(PRE_CSC_GAMC_INDEX(pipe), PRE_CSC_GAMC_AUTO_INCREMENT);
530
531         if (crtc_state->base.degamma_lut) {
532                 struct drm_color_lut *lut = crtc_state->base.degamma_lut->data;
533
534                 for (i = 0; i < lut_size; i++) {
535                         /*
536                          * First 33 entries represent range from 0 to 1.0
537                          * 34th and 35th entry will represent extended range
538                          * inputs 3.0 and 7.0 respectively, currently clamped
539                          * at 1.0. Since the precision is 16bit, the user
540                          * value can be directly filled to register.
541                          * The pipe degamma table in GLK+ onwards doesn't
542                          * support different values per channel, so this just
543                          * programs green value which will be equal to Red and
544                          * Blue into the lut registers.
545                          * ToDo: Extend to max 7.0. Enable 32 bit input value
546                          * as compared to just 16 to achieve this.
547                          */
548                         I915_WRITE(PRE_CSC_GAMC_DATA(pipe), lut[i].green);
549                 }
550         } else {
551                 /* load a linear table. */
552                 for (i = 0; i < lut_size; i++) {
553                         u32 v = (i * (1 << 16)) / (lut_size - 1);
554
555                         I915_WRITE(PRE_CSC_GAMC_DATA(pipe), v);
556                 }
557         }
558
559         /* Clamp values > 1.0. */
560         while (i++ < 35)
561                 I915_WRITE(PRE_CSC_GAMC_DATA(pipe), (1 << 16));
562 }
563
564 static void glk_load_luts(const struct intel_crtc_state *crtc_state)
565 {
566         glk_load_degamma_lut(crtc_state);
567
568         if (crtc_state_is_legacy_gamma(crtc_state))
569                 i9xx_load_luts(crtc_state);
570         else
571                 bdw_load_gamma_lut(crtc_state, 0);
572 }
573
574 static void cherryview_load_luts(const struct intel_crtc_state *crtc_state)
575 {
576         struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
577         struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
578         const struct drm_property_blob *gamma_lut = crtc_state->base.gamma_lut;
579         const struct drm_property_blob *degamma_lut = crtc_state->base.degamma_lut;
580         enum pipe pipe = crtc->pipe;
581
582         cherryview_load_csc_matrix(crtc_state);
583
584         if (crtc_state_is_legacy_gamma(crtc_state)) {
585                 i9xx_load_luts_internal(crtc_state, gamma_lut);
586                 return;
587         }
588
589         if (degamma_lut) {
590                 const struct drm_color_lut *lut = degamma_lut->data;
591                 int i, lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
592
593                 for (i = 0; i < lut_size; i++) {
594                         u32 word0, word1;
595
596                         /* Write LUT in U0.14 format. */
597                         word0 =
598                         (drm_color_lut_extract(lut[i].green, 14) << 16) |
599                         drm_color_lut_extract(lut[i].blue, 14);
600                         word1 = drm_color_lut_extract(lut[i].red, 14);
601
602                         I915_WRITE(CGM_PIPE_DEGAMMA(pipe, i, 0), word0);
603                         I915_WRITE(CGM_PIPE_DEGAMMA(pipe, i, 1), word1);
604                 }
605         }
606
607         if (gamma_lut) {
608                 const struct drm_color_lut *lut = gamma_lut->data;
609                 int i, lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
610
611                 for (i = 0; i < lut_size; i++) {
612                         u32 word0, word1;
613
614                         /* Write LUT in U0.10 format. */
615                         word0 =
616                         (drm_color_lut_extract(lut[i].green, 10) << 16) |
617                         drm_color_lut_extract(lut[i].blue, 10);
618                         word1 = drm_color_lut_extract(lut[i].red, 10);
619
620                         I915_WRITE(CGM_PIPE_GAMMA(pipe, i, 0), word0);
621                         I915_WRITE(CGM_PIPE_GAMMA(pipe, i, 1), word1);
622                 }
623         }
624
625         /*
626          * Also program a linear LUT in the legacy block (behind the
627          * CGM block).
628          */
629         i9xx_load_luts_internal(crtc_state, NULL);
630 }
631
632 void intel_color_load_luts(const struct intel_crtc_state *crtc_state)
633 {
634         struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
635
636         dev_priv->display.load_luts(crtc_state);
637 }
638
639 void intel_color_commit(const struct intel_crtc_state *crtc_state)
640 {
641         struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
642
643         dev_priv->display.color_commit(crtc_state);
644 }
645
646 static bool need_plane_update(struct intel_plane *plane,
647                               const struct intel_crtc_state *crtc_state)
648 {
649         struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
650
651         /*
652          * On pre-SKL the pipe gamma enable and pipe csc enable for
653          * the pipe bottom color are configured via the primary plane.
654          * We have to reconfigure that even if the plane is inactive.
655          */
656         return crtc_state->active_planes & BIT(plane->id) ||
657                 (INTEL_GEN(dev_priv) < 9 &&
658                  plane->id == PLANE_PRIMARY);
659 }
660
661 static int
662 intel_color_add_affected_planes(struct intel_crtc_state *new_crtc_state)
663 {
664         struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
665         struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
666         struct intel_atomic_state *state =
667                 to_intel_atomic_state(new_crtc_state->base.state);
668         const struct intel_crtc_state *old_crtc_state =
669                 intel_atomic_get_old_crtc_state(state, crtc);
670         struct intel_plane *plane;
671
672         if (!new_crtc_state->base.active ||
673             drm_atomic_crtc_needs_modeset(&new_crtc_state->base))
674                 return 0;
675
676         if (new_crtc_state->gamma_enable == old_crtc_state->gamma_enable &&
677             new_crtc_state->csc_enable == old_crtc_state->csc_enable)
678                 return 0;
679
680         for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) {
681                 struct intel_plane_state *plane_state;
682
683                 if (!need_plane_update(plane, new_crtc_state))
684                         continue;
685
686                 plane_state = intel_atomic_get_plane_state(state, plane);
687                 if (IS_ERR(plane_state))
688                         return PTR_ERR(plane_state);
689
690                 new_crtc_state->update_planes |= BIT(plane->id);
691         }
692
693         return 0;
694 }
695
696 static int check_lut_size(const struct drm_property_blob *lut, int expected)
697 {
698         int len;
699
700         if (!lut)
701                 return 0;
702
703         len = drm_color_lut_size(lut);
704         if (len != expected) {
705                 DRM_DEBUG_KMS("Invalid LUT size; got %d, expected %d\n",
706                               len, expected);
707                 return -EINVAL;
708         }
709
710         return 0;
711 }
712
713 int intel_color_check(struct intel_crtc_state *crtc_state)
714 {
715         struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
716         const struct drm_property_blob *gamma_lut = crtc_state->base.gamma_lut;
717         const struct drm_property_blob *degamma_lut = crtc_state->base.degamma_lut;
718         bool limited_color_range = false;
719         int gamma_length, degamma_length;
720         u32 gamma_tests, degamma_tests;
721         int ret;
722
723         degamma_length = INTEL_INFO(dev_priv)->color.degamma_lut_size;
724         gamma_length = INTEL_INFO(dev_priv)->color.gamma_lut_size;
725         degamma_tests = INTEL_INFO(dev_priv)->color.degamma_lut_tests;
726         gamma_tests = INTEL_INFO(dev_priv)->color.gamma_lut_tests;
727
728         /* C8 needs the legacy LUT all to itself */
729         if (crtc_state->c8_planes &&
730             !crtc_state_is_legacy_gamma(crtc_state))
731                 return -EINVAL;
732
733         crtc_state->gamma_enable = (gamma_lut || degamma_lut) &&
734                 !crtc_state->c8_planes;
735
736         if (INTEL_GEN(dev_priv) >= 9 ||
737             IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
738                 limited_color_range = crtc_state->limited_color_range;
739
740         crtc_state->csc_enable =
741                 crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB ||
742                 crtc_state->base.ctm || limited_color_range;
743
744         ret = intel_color_add_affected_planes(crtc_state);
745         if (ret)
746                 return ret;
747
748         /* Always allow legacy gamma LUT with no further checking. */
749         if (!crtc_state->gamma_enable ||
750             crtc_state_is_legacy_gamma(crtc_state)) {
751                 crtc_state->gamma_mode = GAMMA_MODE_MODE_8BIT;
752                 return 0;
753         }
754
755         if (check_lut_size(degamma_lut, degamma_length) ||
756             check_lut_size(gamma_lut, gamma_length))
757                 return -EINVAL;
758
759         if (drm_color_lut_check(degamma_lut, degamma_tests) ||
760             drm_color_lut_check(gamma_lut, gamma_tests))
761                 return -EINVAL;
762
763         if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
764                 crtc_state->gamma_mode = GAMMA_MODE_MODE_10BIT;
765         else if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
766                 crtc_state->gamma_mode = GAMMA_MODE_MODE_SPLIT;
767         else
768                 crtc_state->gamma_mode = GAMMA_MODE_MODE_8BIT;
769
770         return 0;
771 }
772
773 void intel_color_init(struct intel_crtc *crtc)
774 {
775         struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
776
777         drm_mode_crtc_set_gamma_size(&crtc->base, 256);
778
779         if (HAS_GMCH(dev_priv)) {
780                 if (IS_CHERRYVIEW(dev_priv))
781                         dev_priv->display.load_luts = cherryview_load_luts;
782                 else
783                         dev_priv->display.load_luts = i9xx_load_luts;
784
785                 dev_priv->display.color_commit = i9xx_color_commit;
786         } else {
787                 if (IS_CANNONLAKE(dev_priv) || IS_GEMINILAKE(dev_priv))
788                         dev_priv->display.load_luts = glk_load_luts;
789                 else if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
790                         dev_priv->display.load_luts = broadwell_load_luts;
791                 else
792                         dev_priv->display.load_luts = i9xx_load_luts;
793
794                 if (INTEL_GEN(dev_priv) >= 9)
795                         dev_priv->display.color_commit = skl_color_commit;
796                 else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
797                         dev_priv->display.color_commit = hsw_color_commit;
798                 else
799                         dev_priv->display.color_commit = ilk_color_commit;
800         }
801
802         /* Enable color management support when we have degamma & gamma LUTs. */
803         if (INTEL_INFO(dev_priv)->color.degamma_lut_size != 0 &&
804             INTEL_INFO(dev_priv)->color.gamma_lut_size != 0)
805                 drm_crtc_enable_color_mgmt(&crtc->base,
806                                            INTEL_INFO(dev_priv)->color.degamma_lut_size,
807                                            true,
808                                            INTEL_INFO(dev_priv)->color.gamma_lut_size);
809 }