File Index
Files and directories
Sign in
FILE

intel_color.c

File preview with syntax highlighting.

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