1/*	$NetBSD: intel_color.c,v 1.2 2021/12/18 23:45:29 riastradh Exp $	*/
2
3/*
4 * Copyright �� 2016 Intel Corporation
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27#include <sys/cdefs.h>
28__KERNEL_RCSID(0, "$NetBSD: intel_color.c,v 1.2 2021/12/18 23:45:29 riastradh Exp $");
29
30#include "intel_color.h"
31#include "intel_display_types.h"
32
33#define CTM_COEFF_SIGN	(1ULL << 63)
34
35#define CTM_COEFF_1_0	(1ULL << 32)
36#define CTM_COEFF_2_0	(CTM_COEFF_1_0 << 1)
37#define CTM_COEFF_4_0	(CTM_COEFF_2_0 << 1)
38#define CTM_COEFF_8_0	(CTM_COEFF_4_0 << 1)
39#define CTM_COEFF_0_5	(CTM_COEFF_1_0 >> 1)
40#define CTM_COEFF_0_25	(CTM_COEFF_0_5 >> 1)
41#define CTM_COEFF_0_125	(CTM_COEFF_0_25 >> 1)
42
43#define CTM_COEFF_LIMITED_RANGE ((235ULL - 16ULL) * CTM_COEFF_1_0 / 255)
44
45#define CTM_COEFF_NEGATIVE(coeff)	(((coeff) & CTM_COEFF_SIGN) != 0)
46#define CTM_COEFF_ABS(coeff)		((coeff) & (CTM_COEFF_SIGN - 1))
47
48#define LEGACY_LUT_LENGTH		256
49
50/*
51 * ILK+ csc matrix:
52 *
53 * |R/Cr|   | c0 c1 c2 |   ( |R/Cr|   |preoff0| )   |postoff0|
54 * |G/Y | = | c3 c4 c5 | x ( |G/Y | + |preoff1| ) + |postoff1|
55 * |B/Cb|   | c6 c7 c8 |   ( |B/Cb|   |preoff2| )   |postoff2|
56 *
57 * ILK/SNB don't have explicit post offsets, and instead
58 * CSC_MODE_YUV_TO_RGB and CSC_BLACK_SCREEN_OFFSET are used:
59 *  CSC_MODE_YUV_TO_RGB=0 + CSC_BLACK_SCREEN_OFFSET=0 -> 1/2, 0, 1/2
60 *  CSC_MODE_YUV_TO_RGB=0 + CSC_BLACK_SCREEN_OFFSET=1 -> 1/2, 1/16, 1/2
61 *  CSC_MODE_YUV_TO_RGB=1 + CSC_BLACK_SCREEN_OFFSET=0 -> 0, 0, 0
62 *  CSC_MODE_YUV_TO_RGB=1 + CSC_BLACK_SCREEN_OFFSET=1 -> 1/16, 1/16, 1/16
63 */
64
65/*
66 * Extract the CSC coefficient from a CTM coefficient (in U32.32 fixed point
67 * format). This macro takes the coefficient we want transformed and the
68 * number of fractional bits.
69 *
70 * We only have a 9 bits precision window which slides depending on the value
71 * of the CTM coefficient and we write the value from bit 3. We also round the
72 * value.
73 */
74#define ILK_CSC_COEFF_FP(coeff, fbits)	\
75	(clamp_val(((coeff) >> (32 - (fbits) - 3)) + 4, 0, 0xfff) & 0xff8)
76
77#define ILK_CSC_COEFF_LIMITED_RANGE 0x0dc0
78#define ILK_CSC_COEFF_1_0 0x7800
79
80#define ILK_CSC_POSTOFF_LIMITED_RANGE (16 * (1 << 12) / 255)
81
82/* Nop pre/post offsets */
83static const u16 ilk_csc_off_zero[3] = {};
84
85/* Identity matrix */
86static const u16 ilk_csc_coeff_identity[9] = {
87	ILK_CSC_COEFF_1_0, 0, 0,
88	0, ILK_CSC_COEFF_1_0, 0,
89	0, 0, ILK_CSC_COEFF_1_0,
90};
91
92/* Limited range RGB post offsets */
93static const u16 ilk_csc_postoff_limited_range[3] = {
94	ILK_CSC_POSTOFF_LIMITED_RANGE,
95	ILK_CSC_POSTOFF_LIMITED_RANGE,
96	ILK_CSC_POSTOFF_LIMITED_RANGE,
97};
98
99/* Full range RGB -> limited range RGB matrix */
100static const u16 ilk_csc_coeff_limited_range[9] = {
101	ILK_CSC_COEFF_LIMITED_RANGE, 0, 0,
102	0, ILK_CSC_COEFF_LIMITED_RANGE, 0,
103	0, 0, ILK_CSC_COEFF_LIMITED_RANGE,
104};
105
106/* BT.709 full range RGB -> limited range YCbCr matrix */
107static const u16 ilk_csc_coeff_rgb_to_ycbcr[9] = {
108	0x1e08, 0x9cc0, 0xb528,
109	0x2ba8, 0x09d8, 0x37e8,
110	0xbce8, 0x9ad8, 0x1e08,
111};
112
113/* Limited range YCbCr post offsets */
114static const u16 ilk_csc_postoff_rgb_to_ycbcr[3] = {
115	0x0800, 0x0100, 0x0800,
116};
117
118static bool lut_is_legacy(const struct drm_property_blob *lut)
119{
120	return drm_color_lut_size(lut) == LEGACY_LUT_LENGTH;
121}
122
123static bool crtc_state_is_legacy_gamma(const struct intel_crtc_state *crtc_state)
124{
125	return !crtc_state->hw.degamma_lut &&
126		!crtc_state->hw.ctm &&
127		crtc_state->hw.gamma_lut &&
128		lut_is_legacy(crtc_state->hw.gamma_lut);
129}
130
131/*
132 * When using limited range, multiply the matrix given by userspace by
133 * the matrix that we would use for the limited range.
134 */
135static u64 *ctm_mult_by_limited(u64 *result, const u64 *input)
136{
137	int i;
138
139	for (i = 0; i < 9; i++) {
140		u64 user_coeff = input[i];
141		u32 limited_coeff = CTM_COEFF_LIMITED_RANGE;
142		u32 abs_coeff = clamp_val(CTM_COEFF_ABS(user_coeff), 0,
143					  CTM_COEFF_4_0 - 1) >> 2;
144
145		/*
146		 * By scaling every co-efficient with limited range (16-235)
147		 * vs full range (0-255) the final o/p will be scaled down to
148		 * fit in the limited range supported by the panel.
149		 */
150		result[i] = mul_u32_u32(limited_coeff, abs_coeff) >> 30;
151		result[i] |= user_coeff & CTM_COEFF_SIGN;
152	}
153
154	return result;
155}
156
157static void ilk_update_pipe_csc(struct intel_crtc *crtc,
158				const u16 preoff[3],
159				const u16 coeff[9],
160				const u16 postoff[3])
161{
162	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
163	enum pipe pipe = crtc->pipe;
164
165	I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), preoff[0]);
166	I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), preoff[1]);
167	I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), preoff[2]);
168
169	I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), coeff[0] << 16 | coeff[1]);
170	I915_WRITE(PIPE_CSC_COEFF_BY(pipe), coeff[2] << 16);
171
172	I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), coeff[3] << 16 | coeff[4]);
173	I915_WRITE(PIPE_CSC_COEFF_BU(pipe), coeff[5] << 16);
174
175	I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), coeff[6] << 16 | coeff[7]);
176	I915_WRITE(PIPE_CSC_COEFF_BV(pipe), coeff[8] << 16);
177
178	if (INTEL_GEN(dev_priv) >= 7) {
179		I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff[0]);
180		I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), postoff[1]);
181		I915_WRITE(PIPE_CSC_POSTOFF_LO(pipe), postoff[2]);
182	}
183}
184
185static void icl_update_output_csc(struct intel_crtc *crtc,
186				  const u16 preoff[3],
187				  const u16 coeff[9],
188				  const u16 postoff[3])
189{
190	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
191	enum pipe pipe = crtc->pipe;
192
193	I915_WRITE(PIPE_CSC_OUTPUT_PREOFF_HI(pipe), preoff[0]);
194	I915_WRITE(PIPE_CSC_OUTPUT_PREOFF_ME(pipe), preoff[1]);
195	I915_WRITE(PIPE_CSC_OUTPUT_PREOFF_LO(pipe), preoff[2]);
196
197	I915_WRITE(PIPE_CSC_OUTPUT_COEFF_RY_GY(pipe), coeff[0] << 16 | coeff[1]);
198	I915_WRITE(PIPE_CSC_OUTPUT_COEFF_BY(pipe), coeff[2] << 16);
199
200	I915_WRITE(PIPE_CSC_OUTPUT_COEFF_RU_GU(pipe), coeff[3] << 16 | coeff[4]);
201	I915_WRITE(PIPE_CSC_OUTPUT_COEFF_BU(pipe), coeff[5] << 16);
202
203	I915_WRITE(PIPE_CSC_OUTPUT_COEFF_RV_GV(pipe), coeff[6] << 16 | coeff[7]);
204	I915_WRITE(PIPE_CSC_OUTPUT_COEFF_BV(pipe), coeff[8] << 16);
205
206	I915_WRITE(PIPE_CSC_OUTPUT_POSTOFF_HI(pipe), postoff[0]);
207	I915_WRITE(PIPE_CSC_OUTPUT_POSTOFF_ME(pipe), postoff[1]);
208	I915_WRITE(PIPE_CSC_OUTPUT_POSTOFF_LO(pipe), postoff[2]);
209}
210
211static bool ilk_csc_limited_range(const struct intel_crtc_state *crtc_state)
212{
213	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
214
215	/*
216	 * FIXME if there's a gamma LUT after the CSC, we should
217	 * do the range compression using the gamma LUT instead.
218	 */
219	return crtc_state->limited_color_range &&
220		(IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv) ||
221		 IS_GEN_RANGE(dev_priv, 9, 10));
222}
223
224static void ilk_csc_convert_ctm(const struct intel_crtc_state *crtc_state,
225				u16 coeffs[9])
226{
227	const struct drm_color_ctm *ctm = crtc_state->hw.ctm->data;
228	const u64 *input;
229	u64 temp[9];
230	int i;
231
232	if (ilk_csc_limited_range(crtc_state))
233		input = ctm_mult_by_limited(temp, ctm->matrix);
234	else
235		input = ctm->matrix;
236
237	/*
238	 * Convert fixed point S31.32 input to format supported by the
239	 * hardware.
240	 */
241	for (i = 0; i < 9; i++) {
242		u64 abs_coeff = ((1ULL << 63) - 1) & input[i];
243
244		/*
245		 * Clamp input value to min/max supported by
246		 * hardware.
247		 */
248		abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_4_0 - 1);
249
250		coeffs[i] = 0;
251
252		/* sign bit */
253		if (CTM_COEFF_NEGATIVE(input[i]))
254			coeffs[i] |= 1 << 15;
255
256		if (abs_coeff < CTM_COEFF_0_125)
257			coeffs[i] |= (3 << 12) |
258				ILK_CSC_COEFF_FP(abs_coeff, 12);
259		else if (abs_coeff < CTM_COEFF_0_25)
260			coeffs[i] |= (2 << 12) |
261				ILK_CSC_COEFF_FP(abs_coeff, 11);
262		else if (abs_coeff < CTM_COEFF_0_5)
263			coeffs[i] |= (1 << 12) |
264				ILK_CSC_COEFF_FP(abs_coeff, 10);
265		else if (abs_coeff < CTM_COEFF_1_0)
266			coeffs[i] |= ILK_CSC_COEFF_FP(abs_coeff, 9);
267		else if (abs_coeff < CTM_COEFF_2_0)
268			coeffs[i] |= (7 << 12) |
269				ILK_CSC_COEFF_FP(abs_coeff, 8);
270		else
271			coeffs[i] |= (6 << 12) |
272				ILK_CSC_COEFF_FP(abs_coeff, 7);
273	}
274}
275
276static void ilk_load_csc_matrix(const struct intel_crtc_state *crtc_state)
277{
278	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
279	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
280	bool limited_color_range = ilk_csc_limited_range(crtc_state);
281
282	if (crtc_state->hw.ctm) {
283		u16 coeff[9];
284
285		ilk_csc_convert_ctm(crtc_state, coeff);
286		ilk_update_pipe_csc(crtc, ilk_csc_off_zero, coeff,
287				    limited_color_range ?
288				    ilk_csc_postoff_limited_range :
289				    ilk_csc_off_zero);
290	} else if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB) {
291		ilk_update_pipe_csc(crtc, ilk_csc_off_zero,
292				    ilk_csc_coeff_rgb_to_ycbcr,
293				    ilk_csc_postoff_rgb_to_ycbcr);
294	} else if (limited_color_range) {
295		ilk_update_pipe_csc(crtc, ilk_csc_off_zero,
296				    ilk_csc_coeff_limited_range,
297				    ilk_csc_postoff_limited_range);
298	} else if (crtc_state->csc_enable) {
299		/*
300		 * On GLK+ both pipe CSC and degamma LUT are controlled
301		 * by csc_enable. Hence for the cases where the degama
302		 * LUT is needed but CSC is not we need to load an
303		 * identity matrix.
304		 */
305		WARN_ON(!IS_CANNONLAKE(dev_priv) && !IS_GEMINILAKE(dev_priv));
306
307		ilk_update_pipe_csc(crtc, ilk_csc_off_zero,
308				    ilk_csc_coeff_identity,
309				    ilk_csc_off_zero);
310	}
311
312	I915_WRITE(PIPE_CSC_MODE(crtc->pipe), crtc_state->csc_mode);
313}
314
315static void icl_load_csc_matrix(const struct intel_crtc_state *crtc_state)
316{
317	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
318	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
319
320	if (crtc_state->hw.ctm) {
321		u16 coeff[9];
322
323		ilk_csc_convert_ctm(crtc_state, coeff);
324		ilk_update_pipe_csc(crtc, ilk_csc_off_zero,
325				    coeff, ilk_csc_off_zero);
326	}
327
328	if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB) {
329		icl_update_output_csc(crtc, ilk_csc_off_zero,
330				      ilk_csc_coeff_rgb_to_ycbcr,
331				      ilk_csc_postoff_rgb_to_ycbcr);
332	} else if (crtc_state->limited_color_range) {
333		icl_update_output_csc(crtc, ilk_csc_off_zero,
334				      ilk_csc_coeff_limited_range,
335				      ilk_csc_postoff_limited_range);
336	}
337
338	I915_WRITE(PIPE_CSC_MODE(crtc->pipe), crtc_state->csc_mode);
339}
340
341/*
342 * Set up the pipe CSC unit on CherryView.
343 */
344static void cherryview_load_csc_matrix(const struct intel_crtc_state *crtc_state)
345{
346	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
347	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
348	enum pipe pipe = crtc->pipe;
349
350	if (crtc_state->hw.ctm) {
351		const struct drm_color_ctm *ctm = crtc_state->hw.ctm->data;
352		u16 coeffs[9] = {};
353		int i;
354
355		for (i = 0; i < ARRAY_SIZE(coeffs); i++) {
356			u64 abs_coeff =
357				((1ULL << 63) - 1) & ctm->matrix[i];
358
359			/* Round coefficient. */
360			abs_coeff += 1 << (32 - 13);
361			/* Clamp to hardware limits. */
362			abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_8_0 - 1);
363
364			/* Write coefficients in S3.12 format. */
365			if (ctm->matrix[i] & (1ULL << 63))
366				coeffs[i] = 1 << 15;
367			coeffs[i] |= ((abs_coeff >> 32) & 7) << 12;
368			coeffs[i] |= (abs_coeff >> 20) & 0xfff;
369		}
370
371		I915_WRITE(CGM_PIPE_CSC_COEFF01(pipe),
372			   coeffs[1] << 16 | coeffs[0]);
373		I915_WRITE(CGM_PIPE_CSC_COEFF23(pipe),
374			   coeffs[3] << 16 | coeffs[2]);
375		I915_WRITE(CGM_PIPE_CSC_COEFF45(pipe),
376			   coeffs[5] << 16 | coeffs[4]);
377		I915_WRITE(CGM_PIPE_CSC_COEFF67(pipe),
378			   coeffs[7] << 16 | coeffs[6]);
379		I915_WRITE(CGM_PIPE_CSC_COEFF8(pipe), coeffs[8]);
380	}
381
382	I915_WRITE(CGM_PIPE_MODE(pipe), crtc_state->cgm_mode);
383}
384
385/* i965+ "10.6" bit interpolated format "even DW" (low 8 bits) */
386static u32 i965_lut_10p6_ldw(const struct drm_color_lut *color)
387{
388	return (color->red & 0xff) << 16 |
389		(color->green & 0xff) << 8 |
390		(color->blue & 0xff);
391}
392
393/* i965+ "10.6" interpolated format "odd DW" (high 8 bits) */
394static u32 i965_lut_10p6_udw(const struct drm_color_lut *color)
395{
396	return (color->red >> 8) << 16 |
397		(color->green >> 8) << 8 |
398		(color->blue >> 8);
399}
400
401static u32 ilk_lut_10(const struct drm_color_lut *color)
402{
403	return drm_color_lut_extract(color->red, 10) << 20 |
404		drm_color_lut_extract(color->green, 10) << 10 |
405		drm_color_lut_extract(color->blue, 10);
406}
407
408/* Loads the legacy palette/gamma unit for the CRTC. */
409static void i9xx_load_luts_internal(const struct intel_crtc_state *crtc_state,
410				    const struct drm_property_blob *blob)
411{
412	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
413	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
414	enum pipe pipe = crtc->pipe;
415	int i;
416
417	if (HAS_GMCH(dev_priv)) {
418		if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI))
419			assert_dsi_pll_enabled(dev_priv);
420		else
421			assert_pll_enabled(dev_priv, pipe);
422	}
423
424	if (blob) {
425		const struct drm_color_lut *lut = blob->data;
426
427		for (i = 0; i < 256; i++) {
428			u32 word =
429				(drm_color_lut_extract(lut[i].red, 8) << 16) |
430				(drm_color_lut_extract(lut[i].green, 8) << 8) |
431				drm_color_lut_extract(lut[i].blue, 8);
432
433			if (HAS_GMCH(dev_priv))
434				I915_WRITE(PALETTE(pipe, i), word);
435			else
436				I915_WRITE(LGC_PALETTE(pipe, i), word);
437		}
438	}
439}
440
441static void i9xx_load_luts(const struct intel_crtc_state *crtc_state)
442{
443	i9xx_load_luts_internal(crtc_state, crtc_state->hw.gamma_lut);
444}
445
446static void i9xx_color_commit(const struct intel_crtc_state *crtc_state)
447{
448	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
449	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
450	enum pipe pipe = crtc->pipe;
451	u32 val;
452
453	val = I915_READ(PIPECONF(pipe));
454	val &= ~PIPECONF_GAMMA_MODE_MASK_I9XX;
455	val |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);
456	I915_WRITE(PIPECONF(pipe), val);
457}
458
459static void ilk_color_commit(const struct intel_crtc_state *crtc_state)
460{
461	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
462	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
463	enum pipe pipe = crtc->pipe;
464	u32 val;
465
466	val = I915_READ(PIPECONF(pipe));
467	val &= ~PIPECONF_GAMMA_MODE_MASK_ILK;
468	val |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);
469	I915_WRITE(PIPECONF(pipe), val);
470
471	ilk_load_csc_matrix(crtc_state);
472}
473
474static void hsw_color_commit(const struct intel_crtc_state *crtc_state)
475{
476	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
477	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
478
479	I915_WRITE(GAMMA_MODE(crtc->pipe), crtc_state->gamma_mode);
480
481	ilk_load_csc_matrix(crtc_state);
482}
483
484static void skl_color_commit(const struct intel_crtc_state *crtc_state)
485{
486	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
487	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
488	enum pipe pipe = crtc->pipe;
489	u32 val = 0;
490
491	/*
492	 * We don't (yet) allow userspace to control the pipe background color,
493	 * so force it to black, but apply pipe gamma and CSC appropriately
494	 * so that its handling will match how we program our planes.
495	 */
496	if (crtc_state->gamma_enable)
497		val |= SKL_BOTTOM_COLOR_GAMMA_ENABLE;
498	if (crtc_state->csc_enable)
499		val |= SKL_BOTTOM_COLOR_CSC_ENABLE;
500	I915_WRITE(SKL_BOTTOM_COLOR(pipe), val);
501
502	I915_WRITE(GAMMA_MODE(crtc->pipe), crtc_state->gamma_mode);
503
504	if (INTEL_GEN(dev_priv) >= 11)
505		icl_load_csc_matrix(crtc_state);
506	else
507		ilk_load_csc_matrix(crtc_state);
508}
509
510static void i965_load_lut_10p6(struct intel_crtc *crtc,
511			       const struct drm_property_blob *blob)
512{
513	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
514	const struct drm_color_lut *lut = blob->data;
515	int i, lut_size = drm_color_lut_size(blob);
516	enum pipe pipe = crtc->pipe;
517
518	for (i = 0; i < lut_size - 1; i++) {
519		I915_WRITE(PALETTE(pipe, 2 * i + 0),
520			   i965_lut_10p6_ldw(&lut[i]));
521		I915_WRITE(PALETTE(pipe, 2 * i + 1),
522			   i965_lut_10p6_udw(&lut[i]));
523	}
524
525	I915_WRITE(PIPEGCMAX(pipe, 0), lut[i].red);
526	I915_WRITE(PIPEGCMAX(pipe, 1), lut[i].green);
527	I915_WRITE(PIPEGCMAX(pipe, 2), lut[i].blue);
528}
529
530static void i965_load_luts(const struct intel_crtc_state *crtc_state)
531{
532	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
533	const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
534
535	if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT)
536		i9xx_load_luts(crtc_state);
537	else
538		i965_load_lut_10p6(crtc, gamma_lut);
539}
540
541static void ilk_load_lut_10(struct intel_crtc *crtc,
542			    const struct drm_property_blob *blob)
543{
544	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
545	const struct drm_color_lut *lut = blob->data;
546	int i, lut_size = drm_color_lut_size(blob);
547	enum pipe pipe = crtc->pipe;
548
549	for (i = 0; i < lut_size; i++)
550		I915_WRITE(PREC_PALETTE(pipe, i), ilk_lut_10(&lut[i]));
551}
552
553static void ilk_load_luts(const struct intel_crtc_state *crtc_state)
554{
555	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
556	const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
557
558	if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT)
559		i9xx_load_luts(crtc_state);
560	else
561		ilk_load_lut_10(crtc, gamma_lut);
562}
563
564static int ivb_lut_10_size(u32 prec_index)
565{
566	if (prec_index & PAL_PREC_SPLIT_MODE)
567		return 512;
568	else
569		return 1024;
570}
571
572/*
573 * IVB/HSW Bspec / PAL_PREC_INDEX:
574 * "Restriction : Index auto increment mode is not
575 *  supported and must not be enabled."
576 */
577static void ivb_load_lut_10(struct intel_crtc *crtc,
578			    const struct drm_property_blob *blob,
579			    u32 prec_index)
580{
581	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
582	int hw_lut_size = ivb_lut_10_size(prec_index);
583	const struct drm_color_lut *lut = blob->data;
584	int i, lut_size = drm_color_lut_size(blob);
585	enum pipe pipe = crtc->pipe;
586
587	for (i = 0; i < hw_lut_size; i++) {
588		/* We discard half the user entries in split gamma mode */
589		const struct drm_color_lut *entry =
590			&lut[i * (lut_size - 1) / (hw_lut_size - 1)];
591
592		I915_WRITE(PREC_PAL_INDEX(pipe), prec_index++);
593		I915_WRITE(PREC_PAL_DATA(pipe), ilk_lut_10(entry));
594	}
595
596	/*
597	 * Reset the index, otherwise it prevents the legacy palette to be
598	 * written properly.
599	 */
600	I915_WRITE(PREC_PAL_INDEX(pipe), 0);
601}
602
603/* On BDW+ the index auto increment mode actually works */
604static void bdw_load_lut_10(struct intel_crtc *crtc,
605			    const struct drm_property_blob *blob,
606			    u32 prec_index)
607{
608	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
609	int hw_lut_size = ivb_lut_10_size(prec_index);
610	const struct drm_color_lut *lut = blob->data;
611	int i, lut_size = drm_color_lut_size(blob);
612	enum pipe pipe = crtc->pipe;
613
614	I915_WRITE(PREC_PAL_INDEX(pipe), prec_index |
615		   PAL_PREC_AUTO_INCREMENT);
616
617	for (i = 0; i < hw_lut_size; i++) {
618		/* We discard half the user entries in split gamma mode */
619		const struct drm_color_lut *entry =
620			&lut[i * (lut_size - 1) / (hw_lut_size - 1)];
621
622		I915_WRITE(PREC_PAL_DATA(pipe), ilk_lut_10(entry));
623	}
624
625	/*
626	 * Reset the index, otherwise it prevents the legacy palette to be
627	 * written properly.
628	 */
629	I915_WRITE(PREC_PAL_INDEX(pipe), 0);
630}
631
632static void ivb_load_lut_ext_max(struct intel_crtc *crtc)
633{
634	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
635	struct intel_dsb *dsb = intel_dsb_get(crtc);
636	enum pipe pipe = crtc->pipe;
637
638	/* Program the max register to clamp values > 1.0. */
639	intel_dsb_reg_write(dsb, PREC_PAL_EXT_GC_MAX(pipe, 0), 1 << 16);
640	intel_dsb_reg_write(dsb, PREC_PAL_EXT_GC_MAX(pipe, 1), 1 << 16);
641	intel_dsb_reg_write(dsb, PREC_PAL_EXT_GC_MAX(pipe, 2), 1 << 16);
642
643	/*
644	 * Program the gc max 2 register to clamp values > 1.0.
645	 * ToDo: Extend the ABI to be able to program values
646	 * from 3.0 to 7.0
647	 */
648	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
649		intel_dsb_reg_write(dsb, PREC_PAL_EXT2_GC_MAX(pipe, 0),
650				    1 << 16);
651		intel_dsb_reg_write(dsb, PREC_PAL_EXT2_GC_MAX(pipe, 1),
652				    1 << 16);
653		intel_dsb_reg_write(dsb, PREC_PAL_EXT2_GC_MAX(pipe, 2),
654				    1 << 16);
655	}
656
657	intel_dsb_put(dsb);
658}
659
660static void ivb_load_luts(const struct intel_crtc_state *crtc_state)
661{
662	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
663	const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
664	const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut;
665
666	if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) {
667		i9xx_load_luts(crtc_state);
668	} else if (crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT) {
669		ivb_load_lut_10(crtc, degamma_lut, PAL_PREC_SPLIT_MODE |
670				PAL_PREC_INDEX_VALUE(0));
671		ivb_load_lut_ext_max(crtc);
672		ivb_load_lut_10(crtc, gamma_lut, PAL_PREC_SPLIT_MODE |
673				PAL_PREC_INDEX_VALUE(512));
674	} else {
675		const struct drm_property_blob *blob = gamma_lut ?: degamma_lut;
676
677		ivb_load_lut_10(crtc, blob,
678				PAL_PREC_INDEX_VALUE(0));
679		ivb_load_lut_ext_max(crtc);
680	}
681}
682
683static void bdw_load_luts(const struct intel_crtc_state *crtc_state)
684{
685	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
686	const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
687	const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut;
688
689	if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) {
690		i9xx_load_luts(crtc_state);
691	} else if (crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT) {
692		bdw_load_lut_10(crtc, degamma_lut, PAL_PREC_SPLIT_MODE |
693				PAL_PREC_INDEX_VALUE(0));
694		ivb_load_lut_ext_max(crtc);
695		bdw_load_lut_10(crtc, gamma_lut, PAL_PREC_SPLIT_MODE |
696				PAL_PREC_INDEX_VALUE(512));
697	} else {
698		const struct drm_property_blob *blob = gamma_lut ?: degamma_lut;
699
700		bdw_load_lut_10(crtc, blob,
701				PAL_PREC_INDEX_VALUE(0));
702		ivb_load_lut_ext_max(crtc);
703	}
704}
705
706static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state)
707{
708	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
709	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
710	enum pipe pipe = crtc->pipe;
711	const u32 lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
712	const struct drm_color_lut *lut = crtc_state->hw.degamma_lut->data;
713	u32 i;
714
715	/*
716	 * When setting the auto-increment bit, the hardware seems to
717	 * ignore the index bits, so we need to reset it to index 0
718	 * separately.
719	 */
720	I915_WRITE(PRE_CSC_GAMC_INDEX(pipe), 0);
721	I915_WRITE(PRE_CSC_GAMC_INDEX(pipe), PRE_CSC_GAMC_AUTO_INCREMENT);
722
723	for (i = 0; i < lut_size; i++) {
724		/*
725		 * First 33 entries represent range from 0 to 1.0
726		 * 34th and 35th entry will represent extended range
727		 * inputs 3.0 and 7.0 respectively, currently clamped
728		 * at 1.0. Since the precision is 16bit, the user
729		 * value can be directly filled to register.
730		 * The pipe degamma table in GLK+ onwards doesn't
731		 * support different values per channel, so this just
732		 * programs green value which will be equal to Red and
733		 * Blue into the lut registers.
734		 * ToDo: Extend to max 7.0. Enable 32 bit input value
735		 * as compared to just 16 to achieve this.
736		 */
737		I915_WRITE(PRE_CSC_GAMC_DATA(pipe), lut[i].green);
738	}
739
740	/* Clamp values > 1.0. */
741	while (i++ < 35)
742		I915_WRITE(PRE_CSC_GAMC_DATA(pipe), 1 << 16);
743}
744
745static void glk_load_degamma_lut_linear(const struct intel_crtc_state *crtc_state)
746{
747	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
748	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
749	enum pipe pipe = crtc->pipe;
750	const u32 lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
751	u32 i;
752
753	/*
754	 * When setting the auto-increment bit, the hardware seems to
755	 * ignore the index bits, so we need to reset it to index 0
756	 * separately.
757	 */
758	I915_WRITE(PRE_CSC_GAMC_INDEX(pipe), 0);
759	I915_WRITE(PRE_CSC_GAMC_INDEX(pipe), PRE_CSC_GAMC_AUTO_INCREMENT);
760
761	for (i = 0; i < lut_size; i++) {
762		u32 v = (i << 16) / (lut_size - 1);
763
764		I915_WRITE(PRE_CSC_GAMC_DATA(pipe), v);
765	}
766
767	/* Clamp values > 1.0. */
768	while (i++ < 35)
769		I915_WRITE(PRE_CSC_GAMC_DATA(pipe), 1 << 16);
770}
771
772static void glk_load_luts(const struct intel_crtc_state *crtc_state)
773{
774	const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
775	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
776
777	/*
778	 * On GLK+ both pipe CSC and degamma LUT are controlled
779	 * by csc_enable. Hence for the cases where the CSC is
780	 * needed but degamma LUT is not we need to load a
781	 * linear degamma LUT. In fact we'll just always load
782	 * the degama LUT so that we don't have to reload
783	 * it every time the pipe CSC is being enabled.
784	 */
785	if (crtc_state->hw.degamma_lut)
786		glk_load_degamma_lut(crtc_state);
787	else
788		glk_load_degamma_lut_linear(crtc_state);
789
790	if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) {
791		i9xx_load_luts(crtc_state);
792	} else {
793		bdw_load_lut_10(crtc, gamma_lut, PAL_PREC_INDEX_VALUE(0));
794		ivb_load_lut_ext_max(crtc);
795	}
796}
797
798/* ilk+ "12.4" interpolated format (high 10 bits) */
799static u32 ilk_lut_12p4_udw(const struct drm_color_lut *color)
800{
801	return (color->red >> 6) << 20 | (color->green >> 6) << 10 |
802		(color->blue >> 6);
803}
804
805/* ilk+ "12.4" interpolated format (low 6 bits) */
806static u32 ilk_lut_12p4_ldw(const struct drm_color_lut *color)
807{
808	return (color->red & 0x3f) << 24 | (color->green & 0x3f) << 14 |
809		(color->blue & 0x3f) << 4;
810}
811
812static void
813icl_load_gcmax(const struct intel_crtc_state *crtc_state,
814	       const struct drm_color_lut *color)
815{
816	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
817	struct intel_dsb *dsb = intel_dsb_get(crtc);
818	enum pipe pipe = crtc->pipe;
819
820	/* Fixme: LUT entries are 16 bit only, so we can prog 0xFFFF max */
821	intel_dsb_reg_write(dsb, PREC_PAL_GC_MAX(pipe, 0), color->red);
822	intel_dsb_reg_write(dsb, PREC_PAL_GC_MAX(pipe, 1), color->green);
823	intel_dsb_reg_write(dsb, PREC_PAL_GC_MAX(pipe, 2), color->blue);
824	intel_dsb_put(dsb);
825}
826
827static void
828icl_program_gamma_superfine_segment(const struct intel_crtc_state *crtc_state)
829{
830	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
831	const struct drm_property_blob *blob = crtc_state->hw.gamma_lut;
832	const struct drm_color_lut *lut = blob->data;
833	struct intel_dsb *dsb = intel_dsb_get(crtc);
834	enum pipe pipe = crtc->pipe;
835	u32 i;
836
837	/*
838	 * Program Super Fine segment (let's call it seg1)...
839	 *
840	 * Super Fine segment's step is 1/(8 * 128 * 256) and it has
841	 * 9 entries, corresponding to values 0, 1/(8 * 128 * 256),
842	 * 2/(8 * 128 * 256) ... 8/(8 * 128 * 256).
843	 */
844	intel_dsb_reg_write(dsb, PREC_PAL_MULTI_SEG_INDEX(pipe),
845			    PAL_PREC_AUTO_INCREMENT);
846
847	for (i = 0; i < 9; i++) {
848		const struct drm_color_lut *entry = &lut[i];
849
850		intel_dsb_indexed_reg_write(dsb, PREC_PAL_MULTI_SEG_DATA(pipe),
851					    ilk_lut_12p4_ldw(entry));
852		intel_dsb_indexed_reg_write(dsb, PREC_PAL_MULTI_SEG_DATA(pipe),
853					    ilk_lut_12p4_udw(entry));
854	}
855
856	intel_dsb_put(dsb);
857}
858
859static void
860icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state)
861{
862	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
863	const struct drm_property_blob *blob = crtc_state->hw.gamma_lut;
864	const struct drm_color_lut *lut = blob->data;
865	const struct drm_color_lut *entry;
866	struct intel_dsb *dsb = intel_dsb_get(crtc);
867	enum pipe pipe = crtc->pipe;
868	u32 i;
869
870	/*
871	 * Program Fine segment (let's call it seg2)...
872	 *
873	 * Fine segment's step is 1/(128 * 256) i.e. 1/(128 * 256), 2/(128 * 256)
874	 * ... 256/(128 * 256). So in order to program fine segment of LUT we
875	 * need to pick every 8th entry in the LUT, and program 256 indexes.
876	 *
877	 * PAL_PREC_INDEX[0] and PAL_PREC_INDEX[1] map to seg2[1],
878	 * seg2[0] being unused by the hardware.
879	 */
880	intel_dsb_reg_write(dsb, PREC_PAL_INDEX(pipe), PAL_PREC_AUTO_INCREMENT);
881	for (i = 1; i < 257; i++) {
882		entry = &lut[i * 8];
883		intel_dsb_indexed_reg_write(dsb, PREC_PAL_DATA(pipe),
884					    ilk_lut_12p4_ldw(entry));
885		intel_dsb_indexed_reg_write(dsb, PREC_PAL_DATA(pipe),
886					    ilk_lut_12p4_udw(entry));
887	}
888
889	/*
890	 * Program Coarse segment (let's call it seg3)...
891	 *
892	 * Coarse segment starts from index 0 and it's step is 1/256 ie 0,
893	 * 1/256, 2/256 ... 256/256. As per the description of each entry in LUT
894	 * above, we need to pick every (8 * 128)th entry in LUT, and
895	 * program 256 of those.
896	 *
897	 * Spec is not very clear about if entries seg3[0] and seg3[1] are
898	 * being used or not, but we still need to program these to advance
899	 * the index.
900	 */
901	for (i = 0; i < 256; i++) {
902		entry = &lut[i * 8 * 128];
903		intel_dsb_indexed_reg_write(dsb, PREC_PAL_DATA(pipe),
904					    ilk_lut_12p4_ldw(entry));
905		intel_dsb_indexed_reg_write(dsb, PREC_PAL_DATA(pipe),
906					    ilk_lut_12p4_udw(entry));
907	}
908
909	/* The last entry in the LUT is to be programmed in GCMAX */
910	entry = &lut[256 * 8 * 128];
911	icl_load_gcmax(crtc_state, entry);
912	ivb_load_lut_ext_max(crtc);
913	intel_dsb_put(dsb);
914}
915
916static void icl_load_luts(const struct intel_crtc_state *crtc_state)
917{
918	const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
919	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
920	struct intel_dsb *dsb = intel_dsb_get(crtc);
921
922	if (crtc_state->hw.degamma_lut)
923		glk_load_degamma_lut(crtc_state);
924
925	switch (crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) {
926	case GAMMA_MODE_MODE_8BIT:
927		i9xx_load_luts(crtc_state);
928		break;
929	case GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED:
930		icl_program_gamma_superfine_segment(crtc_state);
931		icl_program_gamma_multi_segment(crtc_state);
932		break;
933	default:
934		bdw_load_lut_10(crtc, gamma_lut, PAL_PREC_INDEX_VALUE(0));
935		ivb_load_lut_ext_max(crtc);
936	}
937
938	intel_dsb_commit(dsb);
939	intel_dsb_put(dsb);
940}
941
942static u32 chv_cgm_degamma_ldw(const struct drm_color_lut *color)
943{
944	return drm_color_lut_extract(color->green, 14) << 16 |
945		drm_color_lut_extract(color->blue, 14);
946}
947
948static u32 chv_cgm_degamma_udw(const struct drm_color_lut *color)
949{
950	return drm_color_lut_extract(color->red, 14);
951}
952
953static void chv_load_cgm_degamma(struct intel_crtc *crtc,
954				 const struct drm_property_blob *blob)
955{
956	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
957	const struct drm_color_lut *lut = blob->data;
958	int i, lut_size = drm_color_lut_size(blob);
959	enum pipe pipe = crtc->pipe;
960
961	for (i = 0; i < lut_size; i++) {
962		I915_WRITE(CGM_PIPE_DEGAMMA(pipe, i, 0),
963			   chv_cgm_degamma_ldw(&lut[i]));
964		I915_WRITE(CGM_PIPE_DEGAMMA(pipe, i, 1),
965			   chv_cgm_degamma_udw(&lut[i]));
966	}
967}
968
969static u32 chv_cgm_gamma_ldw(const struct drm_color_lut *color)
970{
971	return drm_color_lut_extract(color->green, 10) << 16 |
972		drm_color_lut_extract(color->blue, 10);
973}
974
975static u32 chv_cgm_gamma_udw(const struct drm_color_lut *color)
976{
977	return drm_color_lut_extract(color->red, 10);
978}
979
980static void chv_load_cgm_gamma(struct intel_crtc *crtc,
981			       const struct drm_property_blob *blob)
982{
983	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
984	const struct drm_color_lut *lut = blob->data;
985	int i, lut_size = drm_color_lut_size(blob);
986	enum pipe pipe = crtc->pipe;
987
988	for (i = 0; i < lut_size; i++) {
989		I915_WRITE(CGM_PIPE_GAMMA(pipe, i, 0),
990			   chv_cgm_gamma_ldw(&lut[i]));
991		I915_WRITE(CGM_PIPE_GAMMA(pipe, i, 1),
992			   chv_cgm_gamma_udw(&lut[i]));
993	}
994}
995
996static void chv_load_luts(const struct intel_crtc_state *crtc_state)
997{
998	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
999	const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
1000	const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut;
1001
1002	cherryview_load_csc_matrix(crtc_state);
1003
1004	if (crtc_state_is_legacy_gamma(crtc_state)) {
1005		i9xx_load_luts(crtc_state);
1006		return;
1007	}
1008
1009	if (degamma_lut)
1010		chv_load_cgm_degamma(crtc, degamma_lut);
1011
1012	if (gamma_lut)
1013		chv_load_cgm_gamma(crtc, gamma_lut);
1014}
1015
1016void intel_color_load_luts(const struct intel_crtc_state *crtc_state)
1017{
1018	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
1019
1020	dev_priv->display.load_luts(crtc_state);
1021}
1022
1023void intel_color_commit(const struct intel_crtc_state *crtc_state)
1024{
1025	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
1026
1027	dev_priv->display.color_commit(crtc_state);
1028}
1029
1030static bool intel_can_preload_luts(const struct intel_crtc_state *new_crtc_state)
1031{
1032	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
1033	struct intel_atomic_state *state =
1034		to_intel_atomic_state(new_crtc_state->uapi.state);
1035	const struct intel_crtc_state *old_crtc_state =
1036		intel_atomic_get_old_crtc_state(state, crtc);
1037
1038	return !old_crtc_state->hw.gamma_lut &&
1039		!old_crtc_state->hw.degamma_lut;
1040}
1041
1042static bool chv_can_preload_luts(const struct intel_crtc_state *new_crtc_state)
1043{
1044	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
1045	struct intel_atomic_state *state =
1046		to_intel_atomic_state(new_crtc_state->uapi.state);
1047	const struct intel_crtc_state *old_crtc_state =
1048		intel_atomic_get_old_crtc_state(state, crtc);
1049
1050	/*
1051	 * CGM_PIPE_MODE is itself single buffered. We'd have to
1052	 * somehow split it out from chv_load_luts() if we wanted
1053	 * the ability to preload the CGM LUTs/CSC without tearing.
1054	 */
1055	if (old_crtc_state->cgm_mode || new_crtc_state->cgm_mode)
1056		return false;
1057
1058	return !old_crtc_state->hw.gamma_lut;
1059}
1060
1061static bool glk_can_preload_luts(const struct intel_crtc_state *new_crtc_state)
1062{
1063	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
1064	struct intel_atomic_state *state =
1065		to_intel_atomic_state(new_crtc_state->uapi.state);
1066	const struct intel_crtc_state *old_crtc_state =
1067		intel_atomic_get_old_crtc_state(state, crtc);
1068
1069	/*
1070	 * The hardware degamma is active whenever the pipe
1071	 * CSC is active. Thus even if the old state has no
1072	 * software degamma we need to avoid clobbering the
1073	 * linear hardware degamma mid scanout.
1074	 */
1075	return !old_crtc_state->csc_enable &&
1076		!old_crtc_state->hw.gamma_lut;
1077}
1078
1079int intel_color_check(struct intel_crtc_state *crtc_state)
1080{
1081	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
1082
1083	return dev_priv->display.color_check(crtc_state);
1084}
1085
1086void intel_color_get_config(struct intel_crtc_state *crtc_state)
1087{
1088	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
1089
1090	if (dev_priv->display.read_luts)
1091		dev_priv->display.read_luts(crtc_state);
1092}
1093
1094static bool need_plane_update(struct intel_plane *plane,
1095			      const struct intel_crtc_state *crtc_state)
1096{
1097	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1098
1099	/*
1100	 * On pre-SKL the pipe gamma enable and pipe csc enable for
1101	 * the pipe bottom color are configured via the primary plane.
1102	 * We have to reconfigure that even if the plane is inactive.
1103	 */
1104	return crtc_state->active_planes & BIT(plane->id) ||
1105		(INTEL_GEN(dev_priv) < 9 &&
1106		 plane->id == PLANE_PRIMARY);
1107}
1108
1109static int
1110intel_color_add_affected_planes(struct intel_crtc_state *new_crtc_state)
1111{
1112	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
1113	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1114	struct intel_atomic_state *state =
1115		to_intel_atomic_state(new_crtc_state->uapi.state);
1116	const struct intel_crtc_state *old_crtc_state =
1117		intel_atomic_get_old_crtc_state(state, crtc);
1118	struct intel_plane *plane;
1119
1120	if (!new_crtc_state->hw.active ||
1121	    drm_atomic_crtc_needs_modeset(&new_crtc_state->uapi))
1122		return 0;
1123
1124	if (new_crtc_state->gamma_enable == old_crtc_state->gamma_enable &&
1125	    new_crtc_state->csc_enable == old_crtc_state->csc_enable)
1126		return 0;
1127
1128	for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) {
1129		struct intel_plane_state *plane_state;
1130
1131		if (!need_plane_update(plane, new_crtc_state))
1132			continue;
1133
1134		plane_state = intel_atomic_get_plane_state(state, plane);
1135		if (IS_ERR(plane_state))
1136			return PTR_ERR(plane_state);
1137
1138		new_crtc_state->update_planes |= BIT(plane->id);
1139	}
1140
1141	return 0;
1142}
1143
1144static int check_lut_size(const struct drm_property_blob *lut, int expected)
1145{
1146	int len;
1147
1148	if (!lut)
1149		return 0;
1150
1151	len = drm_color_lut_size(lut);
1152	if (len != expected) {
1153		DRM_DEBUG_KMS("Invalid LUT size; got %d, expected %d\n",
1154			      len, expected);
1155		return -EINVAL;
1156	}
1157
1158	return 0;
1159}
1160
1161static int check_luts(const struct intel_crtc_state *crtc_state)
1162{
1163	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
1164	const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
1165	const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut;
1166	int gamma_length, degamma_length;
1167	u32 gamma_tests, degamma_tests;
1168
1169	/* Always allow legacy gamma LUT with no further checking. */
1170	if (crtc_state_is_legacy_gamma(crtc_state))
1171		return 0;
1172
1173	/* C8 relies on its palette being stored in the legacy LUT */
1174	if (crtc_state->c8_planes) {
1175		DRM_DEBUG_KMS("C8 pixelformat requires the legacy LUT\n");
1176		return -EINVAL;
1177	}
1178
1179	degamma_length = INTEL_INFO(dev_priv)->color.degamma_lut_size;
1180	gamma_length = INTEL_INFO(dev_priv)->color.gamma_lut_size;
1181	degamma_tests = INTEL_INFO(dev_priv)->color.degamma_lut_tests;
1182	gamma_tests = INTEL_INFO(dev_priv)->color.gamma_lut_tests;
1183
1184	if (check_lut_size(degamma_lut, degamma_length) ||
1185	    check_lut_size(gamma_lut, gamma_length))
1186		return -EINVAL;
1187
1188	if (drm_color_lut_check(degamma_lut, degamma_tests) ||
1189	    drm_color_lut_check(gamma_lut, gamma_tests))
1190		return -EINVAL;
1191
1192	return 0;
1193}
1194
1195static u32 i9xx_gamma_mode(struct intel_crtc_state *crtc_state)
1196{
1197	if (!crtc_state->gamma_enable ||
1198	    crtc_state_is_legacy_gamma(crtc_state))
1199		return GAMMA_MODE_MODE_8BIT;
1200	else
1201		return GAMMA_MODE_MODE_10BIT; /* i965+ only */
1202}
1203
1204static int i9xx_color_check(struct intel_crtc_state *crtc_state)
1205{
1206	int ret;
1207
1208	ret = check_luts(crtc_state);
1209	if (ret)
1210		return ret;
1211
1212	crtc_state->gamma_enable =
1213		crtc_state->hw.gamma_lut &&
1214		!crtc_state->c8_planes;
1215
1216	crtc_state->gamma_mode = i9xx_gamma_mode(crtc_state);
1217
1218	ret = intel_color_add_affected_planes(crtc_state);
1219	if (ret)
1220		return ret;
1221
1222	crtc_state->preload_luts = intel_can_preload_luts(crtc_state);
1223
1224	return 0;
1225}
1226
1227static u32 chv_cgm_mode(const struct intel_crtc_state *crtc_state)
1228{
1229	u32 cgm_mode = 0;
1230
1231	if (crtc_state_is_legacy_gamma(crtc_state))
1232		return 0;
1233
1234	if (crtc_state->hw.degamma_lut)
1235		cgm_mode |= CGM_PIPE_MODE_DEGAMMA;
1236	if (crtc_state->hw.ctm)
1237		cgm_mode |= CGM_PIPE_MODE_CSC;
1238	if (crtc_state->hw.gamma_lut)
1239		cgm_mode |= CGM_PIPE_MODE_GAMMA;
1240
1241	return cgm_mode;
1242}
1243
1244/*
1245 * CHV color pipeline:
1246 * u0.10 -> CGM degamma -> u0.14 -> CGM csc -> u0.14 -> CGM gamma ->
1247 * u0.10 -> WGC csc -> u0.10 -> pipe gamma -> u0.10
1248 *
1249 * We always bypass the WGC csc and use the CGM csc
1250 * instead since it has degamma and better precision.
1251 */
1252static int chv_color_check(struct intel_crtc_state *crtc_state)
1253{
1254	int ret;
1255
1256	ret = check_luts(crtc_state);
1257	if (ret)
1258		return ret;
1259
1260	/*
1261	 * Pipe gamma will be used only for the legacy LUT.
1262	 * Otherwise we bypass it and use the CGM gamma instead.
1263	 */
1264	crtc_state->gamma_enable =
1265		crtc_state_is_legacy_gamma(crtc_state) &&
1266		!crtc_state->c8_planes;
1267
1268	crtc_state->gamma_mode = GAMMA_MODE_MODE_8BIT;
1269
1270	crtc_state->cgm_mode = chv_cgm_mode(crtc_state);
1271
1272	ret = intel_color_add_affected_planes(crtc_state);
1273	if (ret)
1274		return ret;
1275
1276	crtc_state->preload_luts = chv_can_preload_luts(crtc_state);
1277
1278	return 0;
1279}
1280
1281static u32 ilk_gamma_mode(const struct intel_crtc_state *crtc_state)
1282{
1283	if (!crtc_state->gamma_enable ||
1284	    crtc_state_is_legacy_gamma(crtc_state))
1285		return GAMMA_MODE_MODE_8BIT;
1286	else
1287		return GAMMA_MODE_MODE_10BIT;
1288}
1289
1290static u32 ilk_csc_mode(const struct intel_crtc_state *crtc_state)
1291{
1292	/*
1293	 * CSC comes after the LUT in RGB->YCbCr mode.
1294	 * RGB->YCbCr needs the limited range offsets added to
1295	 * the output. RGB limited range output is handled by
1296	 * the hw automagically elsewhere.
1297	 */
1298	if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB)
1299		return CSC_BLACK_SCREEN_OFFSET;
1300
1301	return CSC_MODE_YUV_TO_RGB |
1302		CSC_POSITION_BEFORE_GAMMA;
1303}
1304
1305static int ilk_color_check(struct intel_crtc_state *crtc_state)
1306{
1307	int ret;
1308
1309	ret = check_luts(crtc_state);
1310	if (ret)
1311		return ret;
1312
1313	crtc_state->gamma_enable =
1314		crtc_state->hw.gamma_lut &&
1315		!crtc_state->c8_planes;
1316
1317	/*
1318	 * We don't expose the ctm on ilk/snb currently, also RGB
1319	 * limited range output is handled by the hw automagically.
1320	 */
1321	crtc_state->csc_enable =
1322		crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB;
1323
1324	crtc_state->gamma_mode = ilk_gamma_mode(crtc_state);
1325
1326	crtc_state->csc_mode = ilk_csc_mode(crtc_state);
1327
1328	ret = intel_color_add_affected_planes(crtc_state);
1329	if (ret)
1330		return ret;
1331
1332	crtc_state->preload_luts = intel_can_preload_luts(crtc_state);
1333
1334	return 0;
1335}
1336
1337static u32 ivb_gamma_mode(const struct intel_crtc_state *crtc_state)
1338{
1339	if (!crtc_state->gamma_enable ||
1340	    crtc_state_is_legacy_gamma(crtc_state))
1341		return GAMMA_MODE_MODE_8BIT;
1342	else if (crtc_state->hw.gamma_lut &&
1343		 crtc_state->hw.degamma_lut)
1344		return GAMMA_MODE_MODE_SPLIT;
1345	else
1346		return GAMMA_MODE_MODE_10BIT;
1347}
1348
1349static u32 ivb_csc_mode(const struct intel_crtc_state *crtc_state)
1350{
1351	bool limited_color_range = ilk_csc_limited_range(crtc_state);
1352
1353	/*
1354	 * CSC comes after the LUT in degamma, RGB->YCbCr,
1355	 * and RGB full->limited range mode.
1356	 */
1357	if (crtc_state->hw.degamma_lut ||
1358	    crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB ||
1359	    limited_color_range)
1360		return 0;
1361
1362	return CSC_POSITION_BEFORE_GAMMA;
1363}
1364
1365static int ivb_color_check(struct intel_crtc_state *crtc_state)
1366{
1367	bool limited_color_range = ilk_csc_limited_range(crtc_state);
1368	int ret;
1369
1370	ret = check_luts(crtc_state);
1371	if (ret)
1372		return ret;
1373
1374	crtc_state->gamma_enable =
1375		(crtc_state->hw.gamma_lut ||
1376		 crtc_state->hw.degamma_lut) &&
1377		!crtc_state->c8_planes;
1378
1379	crtc_state->csc_enable =
1380		crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB ||
1381		crtc_state->hw.ctm || limited_color_range;
1382
1383	crtc_state->gamma_mode = ivb_gamma_mode(crtc_state);
1384
1385	crtc_state->csc_mode = ivb_csc_mode(crtc_state);
1386
1387	ret = intel_color_add_affected_planes(crtc_state);
1388	if (ret)
1389		return ret;
1390
1391	crtc_state->preload_luts = intel_can_preload_luts(crtc_state);
1392
1393	return 0;
1394}
1395
1396static u32 glk_gamma_mode(const struct intel_crtc_state *crtc_state)
1397{
1398	if (!crtc_state->gamma_enable ||
1399	    crtc_state_is_legacy_gamma(crtc_state))
1400		return GAMMA_MODE_MODE_8BIT;
1401	else
1402		return GAMMA_MODE_MODE_10BIT;
1403}
1404
1405static int glk_color_check(struct intel_crtc_state *crtc_state)
1406{
1407	int ret;
1408
1409	ret = check_luts(crtc_state);
1410	if (ret)
1411		return ret;
1412
1413	crtc_state->gamma_enable =
1414		crtc_state->hw.gamma_lut &&
1415		!crtc_state->c8_planes;
1416
1417	/* On GLK+ degamma LUT is controlled by csc_enable */
1418	crtc_state->csc_enable =
1419		crtc_state->hw.degamma_lut ||
1420		crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB ||
1421		crtc_state->hw.ctm || crtc_state->limited_color_range;
1422
1423	crtc_state->gamma_mode = glk_gamma_mode(crtc_state);
1424
1425	crtc_state->csc_mode = 0;
1426
1427	ret = intel_color_add_affected_planes(crtc_state);
1428	if (ret)
1429		return ret;
1430
1431	crtc_state->preload_luts = glk_can_preload_luts(crtc_state);
1432
1433	return 0;
1434}
1435
1436static u32 icl_gamma_mode(const struct intel_crtc_state *crtc_state)
1437{
1438	u32 gamma_mode = 0;
1439
1440	if (crtc_state->hw.degamma_lut)
1441		gamma_mode |= PRE_CSC_GAMMA_ENABLE;
1442
1443	if (crtc_state->hw.gamma_lut &&
1444	    !crtc_state->c8_planes)
1445		gamma_mode |= POST_CSC_GAMMA_ENABLE;
1446
1447	if (!crtc_state->hw.gamma_lut ||
1448	    crtc_state_is_legacy_gamma(crtc_state))
1449		gamma_mode |= GAMMA_MODE_MODE_8BIT;
1450	else
1451		gamma_mode |= GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED;
1452
1453	return gamma_mode;
1454}
1455
1456static u32 icl_csc_mode(const struct intel_crtc_state *crtc_state)
1457{
1458	u32 csc_mode = 0;
1459
1460	if (crtc_state->hw.ctm)
1461		csc_mode |= ICL_CSC_ENABLE;
1462
1463	if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB ||
1464	    crtc_state->limited_color_range)
1465		csc_mode |= ICL_OUTPUT_CSC_ENABLE;
1466
1467	return csc_mode;
1468}
1469
1470static int icl_color_check(struct intel_crtc_state *crtc_state)
1471{
1472	int ret;
1473
1474	ret = check_luts(crtc_state);
1475	if (ret)
1476		return ret;
1477
1478	crtc_state->gamma_mode = icl_gamma_mode(crtc_state);
1479
1480	crtc_state->csc_mode = icl_csc_mode(crtc_state);
1481
1482	crtc_state->preload_luts = intel_can_preload_luts(crtc_state);
1483
1484	return 0;
1485}
1486
1487static int i9xx_gamma_precision(const struct intel_crtc_state *crtc_state)
1488{
1489	if (!crtc_state->gamma_enable)
1490		return 0;
1491
1492	switch (crtc_state->gamma_mode) {
1493	case GAMMA_MODE_MODE_8BIT:
1494		return 8;
1495	case GAMMA_MODE_MODE_10BIT:
1496		return 16;
1497	default:
1498		MISSING_CASE(crtc_state->gamma_mode);
1499		return 0;
1500	}
1501}
1502
1503static int ilk_gamma_precision(const struct intel_crtc_state *crtc_state)
1504{
1505	if (!crtc_state->gamma_enable)
1506		return 0;
1507
1508	if ((crtc_state->csc_mode & CSC_POSITION_BEFORE_GAMMA) == 0)
1509		return 0;
1510
1511	switch (crtc_state->gamma_mode) {
1512	case GAMMA_MODE_MODE_8BIT:
1513		return 8;
1514	case GAMMA_MODE_MODE_10BIT:
1515		return 10;
1516	default:
1517		MISSING_CASE(crtc_state->gamma_mode);
1518		return 0;
1519	}
1520}
1521
1522static int chv_gamma_precision(const struct intel_crtc_state *crtc_state)
1523{
1524	if (crtc_state->cgm_mode & CGM_PIPE_MODE_GAMMA)
1525		return 10;
1526	else
1527		return i9xx_gamma_precision(crtc_state);
1528}
1529
1530static int glk_gamma_precision(const struct intel_crtc_state *crtc_state)
1531{
1532	if (!crtc_state->gamma_enable)
1533		return 0;
1534
1535	switch (crtc_state->gamma_mode) {
1536	case GAMMA_MODE_MODE_8BIT:
1537		return 8;
1538	case GAMMA_MODE_MODE_10BIT:
1539		return 10;
1540	default:
1541		MISSING_CASE(crtc_state->gamma_mode);
1542		return 0;
1543	}
1544}
1545
1546int intel_color_get_gamma_bit_precision(const struct intel_crtc_state *crtc_state)
1547{
1548	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1549	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1550
1551	if (HAS_GMCH(dev_priv)) {
1552		if (IS_CHERRYVIEW(dev_priv))
1553			return chv_gamma_precision(crtc_state);
1554		else
1555			return i9xx_gamma_precision(crtc_state);
1556	} else {
1557		if (IS_CANNONLAKE(dev_priv) || IS_GEMINILAKE(dev_priv))
1558			return glk_gamma_precision(crtc_state);
1559		else if (IS_IRONLAKE(dev_priv))
1560			return ilk_gamma_precision(crtc_state);
1561	}
1562
1563	return 0;
1564}
1565
1566static bool err_check(struct drm_color_lut *lut1,
1567		      struct drm_color_lut *lut2, u32 err)
1568{
1569	return ((abs((long)lut2->red - lut1->red)) <= err) &&
1570		((abs((long)lut2->blue - lut1->blue)) <= err) &&
1571		((abs((long)lut2->green - lut1->green)) <= err);
1572}
1573
1574static bool intel_color_lut_entry_equal(struct drm_color_lut *lut1,
1575					struct drm_color_lut *lut2,
1576					int lut_size, u32 err)
1577{
1578	int i;
1579
1580	for (i = 0; i < lut_size; i++) {
1581		if (!err_check(&lut1[i], &lut2[i], err))
1582			return false;
1583	}
1584
1585	return true;
1586}
1587
1588bool intel_color_lut_equal(struct drm_property_blob *blob1,
1589			   struct drm_property_blob *blob2,
1590			   u32 gamma_mode, u32 bit_precision)
1591{
1592	struct drm_color_lut *lut1, *lut2;
1593	int lut_size1, lut_size2;
1594	u32 err;
1595
1596	if (!blob1 != !blob2)
1597		return false;
1598
1599	if (!blob1)
1600		return true;
1601
1602	lut_size1 = drm_color_lut_size(blob1);
1603	lut_size2 = drm_color_lut_size(blob2);
1604
1605	/* check sw and hw lut size */
1606	switch (gamma_mode) {
1607	case GAMMA_MODE_MODE_8BIT:
1608	case GAMMA_MODE_MODE_10BIT:
1609		if (lut_size1 != lut_size2)
1610			return false;
1611		break;
1612	default:
1613		MISSING_CASE(gamma_mode);
1614			return false;
1615	}
1616
1617	lut1 = blob1->data;
1618	lut2 = blob2->data;
1619
1620	err = 0xffff >> bit_precision;
1621
1622	/* check sw and hw lut entry to be equal */
1623	switch (gamma_mode) {
1624	case GAMMA_MODE_MODE_8BIT:
1625	case GAMMA_MODE_MODE_10BIT:
1626		if (!intel_color_lut_entry_equal(lut1, lut2,
1627						 lut_size2, err))
1628			return false;
1629		break;
1630	default:
1631		MISSING_CASE(gamma_mode);
1632			return false;
1633	}
1634
1635	return true;
1636}
1637
1638/* convert hw value with given bit_precision to lut property val */
1639static u32 intel_color_lut_pack(u32 val, u32 bit_precision)
1640{
1641	u32 max = 0xffff >> (16 - bit_precision);
1642
1643	val = clamp_val(val, 0, max);
1644
1645	if (bit_precision < 16)
1646		val <<= 16 - bit_precision;
1647
1648	return val;
1649}
1650
1651static struct drm_property_blob *
1652i9xx_read_lut_8(const struct intel_crtc_state *crtc_state)
1653{
1654	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1655	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1656	enum pipe pipe = crtc->pipe;
1657	struct drm_property_blob *blob;
1658	struct drm_color_lut *blob_data;
1659	u32 i, val;
1660
1661	blob = drm_property_create_blob(&dev_priv->drm,
1662					sizeof(struct drm_color_lut) * LEGACY_LUT_LENGTH,
1663					NULL);
1664	if (IS_ERR(blob))
1665		return NULL;
1666
1667	blob_data = blob->data;
1668
1669	for (i = 0; i < LEGACY_LUT_LENGTH; i++) {
1670		if (HAS_GMCH(dev_priv))
1671			val = I915_READ(PALETTE(pipe, i));
1672		else
1673			val = I915_READ(LGC_PALETTE(pipe, i));
1674
1675		blob_data[i].red = intel_color_lut_pack(REG_FIELD_GET(
1676							LGC_PALETTE_RED_MASK, val), 8);
1677		blob_data[i].green = intel_color_lut_pack(REG_FIELD_GET(
1678							  LGC_PALETTE_GREEN_MASK, val), 8);
1679		blob_data[i].blue = intel_color_lut_pack(REG_FIELD_GET(
1680							 LGC_PALETTE_BLUE_MASK, val), 8);
1681	}
1682
1683	return blob;
1684}
1685
1686static void i9xx_read_luts(struct intel_crtc_state *crtc_state)
1687{
1688	if (!crtc_state->gamma_enable)
1689		return;
1690
1691	crtc_state->hw.gamma_lut = i9xx_read_lut_8(crtc_state);
1692}
1693
1694static struct drm_property_blob *
1695i965_read_lut_10p6(const struct intel_crtc_state *crtc_state)
1696{
1697	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1698	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1699	u32 lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
1700	enum pipe pipe = crtc->pipe;
1701	struct drm_property_blob *blob;
1702	struct drm_color_lut *blob_data;
1703	u32 i, val1, val2;
1704
1705	blob = drm_property_create_blob(&dev_priv->drm,
1706					sizeof(struct drm_color_lut) * lut_size,
1707					NULL);
1708	if (IS_ERR(blob))
1709		return NULL;
1710
1711	blob_data = blob->data;
1712
1713	for (i = 0; i < lut_size - 1; i++) {
1714		val1 = I915_READ(PALETTE(pipe, 2 * i + 0));
1715		val2 = I915_READ(PALETTE(pipe, 2 * i + 1));
1716
1717		blob_data[i].red = REG_FIELD_GET(PALETTE_RED_MASK, val2) << 8 |
1718						 REG_FIELD_GET(PALETTE_RED_MASK, val1);
1719		blob_data[i].green = REG_FIELD_GET(PALETTE_GREEN_MASK, val2) << 8 |
1720						   REG_FIELD_GET(PALETTE_GREEN_MASK, val1);
1721		blob_data[i].blue = REG_FIELD_GET(PALETTE_BLUE_MASK, val2) << 8 |
1722						  REG_FIELD_GET(PALETTE_BLUE_MASK, val1);
1723	}
1724
1725	blob_data[i].red = REG_FIELD_GET(PIPEGCMAX_RGB_MASK,
1726					 I915_READ(PIPEGCMAX(pipe, 0)));
1727	blob_data[i].green = REG_FIELD_GET(PIPEGCMAX_RGB_MASK,
1728					   I915_READ(PIPEGCMAX(pipe, 1)));
1729	blob_data[i].blue = REG_FIELD_GET(PIPEGCMAX_RGB_MASK,
1730					  I915_READ(PIPEGCMAX(pipe, 2)));
1731
1732	return blob;
1733}
1734
1735static void i965_read_luts(struct intel_crtc_state *crtc_state)
1736{
1737	if (!crtc_state->gamma_enable)
1738		return;
1739
1740	if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT)
1741		crtc_state->hw.gamma_lut = i9xx_read_lut_8(crtc_state);
1742	else
1743		crtc_state->hw.gamma_lut = i965_read_lut_10p6(crtc_state);
1744}
1745
1746static struct drm_property_blob *
1747chv_read_cgm_lut(const struct intel_crtc_state *crtc_state)
1748{
1749	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1750	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1751	u32 lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
1752	enum pipe pipe = crtc->pipe;
1753	struct drm_property_blob *blob;
1754	struct drm_color_lut *blob_data;
1755	u32 i, val;
1756
1757	blob = drm_property_create_blob(&dev_priv->drm,
1758					sizeof(struct drm_color_lut) * lut_size,
1759					NULL);
1760	if (IS_ERR(blob))
1761		return NULL;
1762
1763	blob_data = blob->data;
1764
1765	for (i = 0; i < lut_size; i++) {
1766		val = I915_READ(CGM_PIPE_GAMMA(pipe, i, 0));
1767		blob_data[i].green = intel_color_lut_pack(REG_FIELD_GET(
1768							  CGM_PIPE_GAMMA_GREEN_MASK, val), 10);
1769		blob_data[i].blue = intel_color_lut_pack(REG_FIELD_GET(
1770							 CGM_PIPE_GAMMA_BLUE_MASK, val), 10);
1771
1772		val = I915_READ(CGM_PIPE_GAMMA(pipe, i, 1));
1773		blob_data[i].red = intel_color_lut_pack(REG_FIELD_GET(
1774							CGM_PIPE_GAMMA_RED_MASK, val), 10);
1775	}
1776
1777	return blob;
1778}
1779
1780static void chv_read_luts(struct intel_crtc_state *crtc_state)
1781{
1782	if (crtc_state->cgm_mode & CGM_PIPE_MODE_GAMMA)
1783		crtc_state->hw.gamma_lut = chv_read_cgm_lut(crtc_state);
1784	else
1785		i965_read_luts(crtc_state);
1786}
1787
1788static struct drm_property_blob *
1789ilk_read_lut_10(const struct intel_crtc_state *crtc_state)
1790{
1791	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1792	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1793	u32 lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
1794	enum pipe pipe = crtc->pipe;
1795	struct drm_property_blob *blob;
1796	struct drm_color_lut *blob_data;
1797	u32 i, val;
1798
1799	blob = drm_property_create_blob(&dev_priv->drm,
1800					sizeof(struct drm_color_lut) * lut_size,
1801					NULL);
1802	if (IS_ERR(blob))
1803		return NULL;
1804
1805	blob_data = blob->data;
1806
1807	for (i = 0; i < lut_size; i++) {
1808		val = I915_READ(PREC_PALETTE(pipe, i));
1809
1810		blob_data[i].red = intel_color_lut_pack(REG_FIELD_GET(
1811							PREC_PALETTE_RED_MASK, val), 10);
1812		blob_data[i].green = intel_color_lut_pack(REG_FIELD_GET(
1813							  PREC_PALETTE_GREEN_MASK, val), 10);
1814		blob_data[i].blue = intel_color_lut_pack(REG_FIELD_GET(
1815							 PREC_PALETTE_BLUE_MASK, val), 10);
1816	}
1817
1818	return blob;
1819}
1820
1821static void ilk_read_luts(struct intel_crtc_state *crtc_state)
1822{
1823	if (!crtc_state->gamma_enable)
1824		return;
1825
1826	if ((crtc_state->csc_mode & CSC_POSITION_BEFORE_GAMMA) == 0)
1827		return;
1828
1829	if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT)
1830		crtc_state->hw.gamma_lut = i9xx_read_lut_8(crtc_state);
1831	else
1832		crtc_state->hw.gamma_lut = ilk_read_lut_10(crtc_state);
1833}
1834
1835static struct drm_property_blob *
1836glk_read_lut_10(const struct intel_crtc_state *crtc_state, u32 prec_index)
1837{
1838	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1839	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1840	int hw_lut_size = ivb_lut_10_size(prec_index);
1841	enum pipe pipe = crtc->pipe;
1842	struct drm_property_blob *blob;
1843	struct drm_color_lut *blob_data;
1844	u32 i, val;
1845
1846	blob = drm_property_create_blob(&dev_priv->drm,
1847					sizeof(struct drm_color_lut) * hw_lut_size,
1848					NULL);
1849	if (IS_ERR(blob))
1850		return NULL;
1851
1852	blob_data = blob->data;
1853
1854	I915_WRITE(PREC_PAL_INDEX(pipe), prec_index |
1855		   PAL_PREC_AUTO_INCREMENT);
1856
1857	for (i = 0; i < hw_lut_size; i++) {
1858		val = I915_READ(PREC_PAL_DATA(pipe));
1859
1860		blob_data[i].red = intel_color_lut_pack(REG_FIELD_GET(
1861							PREC_PAL_DATA_RED_MASK, val), 10);
1862		blob_data[i].green = intel_color_lut_pack(REG_FIELD_GET(
1863							PREC_PAL_DATA_GREEN_MASK, val), 10);
1864		blob_data[i].blue = intel_color_lut_pack(REG_FIELD_GET(
1865							PREC_PAL_DATA_BLUE_MASK, val), 10);
1866	}
1867
1868	I915_WRITE(PREC_PAL_INDEX(pipe), 0);
1869
1870	return blob;
1871}
1872
1873static void glk_read_luts(struct intel_crtc_state *crtc_state)
1874{
1875	if (!crtc_state->gamma_enable)
1876		return;
1877
1878	if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT)
1879		crtc_state->hw.gamma_lut = i9xx_read_lut_8(crtc_state);
1880	else
1881		crtc_state->hw.gamma_lut = glk_read_lut_10(crtc_state, PAL_PREC_INDEX_VALUE(0));
1882}
1883
1884void intel_color_init(struct intel_crtc *crtc)
1885{
1886	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1887	bool has_ctm = INTEL_INFO(dev_priv)->color.degamma_lut_size != 0;
1888
1889	drm_mode_crtc_set_gamma_size(&crtc->base, 256);
1890
1891	if (HAS_GMCH(dev_priv)) {
1892		if (IS_CHERRYVIEW(dev_priv)) {
1893			dev_priv->display.color_check = chv_color_check;
1894			dev_priv->display.color_commit = i9xx_color_commit;
1895			dev_priv->display.load_luts = chv_load_luts;
1896			dev_priv->display.read_luts = chv_read_luts;
1897		} else if (INTEL_GEN(dev_priv) >= 4) {
1898			dev_priv->display.color_check = i9xx_color_check;
1899			dev_priv->display.color_commit = i9xx_color_commit;
1900			dev_priv->display.load_luts = i965_load_luts;
1901			dev_priv->display.read_luts = i965_read_luts;
1902		} else {
1903			dev_priv->display.color_check = i9xx_color_check;
1904			dev_priv->display.color_commit = i9xx_color_commit;
1905			dev_priv->display.load_luts = i9xx_load_luts;
1906			dev_priv->display.read_luts = i9xx_read_luts;
1907		}
1908	} else {
1909		if (INTEL_GEN(dev_priv) >= 11)
1910			dev_priv->display.color_check = icl_color_check;
1911		else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
1912			dev_priv->display.color_check = glk_color_check;
1913		else if (INTEL_GEN(dev_priv) >= 7)
1914			dev_priv->display.color_check = ivb_color_check;
1915		else
1916			dev_priv->display.color_check = ilk_color_check;
1917
1918		if (INTEL_GEN(dev_priv) >= 9)
1919			dev_priv->display.color_commit = skl_color_commit;
1920		else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
1921			dev_priv->display.color_commit = hsw_color_commit;
1922		else
1923			dev_priv->display.color_commit = ilk_color_commit;
1924
1925		if (INTEL_GEN(dev_priv) >= 11) {
1926			dev_priv->display.load_luts = icl_load_luts;
1927		} else if (IS_CANNONLAKE(dev_priv) || IS_GEMINILAKE(dev_priv)) {
1928			dev_priv->display.load_luts = glk_load_luts;
1929			dev_priv->display.read_luts = glk_read_luts;
1930		} else if (INTEL_GEN(dev_priv) >= 8) {
1931			dev_priv->display.load_luts = bdw_load_luts;
1932		} else if (INTEL_GEN(dev_priv) >= 7) {
1933			dev_priv->display.load_luts = ivb_load_luts;
1934		} else {
1935			dev_priv->display.load_luts = ilk_load_luts;
1936			dev_priv->display.read_luts = ilk_read_luts;
1937		}
1938	}
1939
1940	drm_crtc_enable_color_mgmt(&crtc->base,
1941				   INTEL_INFO(dev_priv)->color.degamma_lut_size,
1942				   has_ctm,
1943				   INTEL_INFO(dev_priv)->color.gamma_lut_size);
1944}
1945