File Index
Files and directories
Sign in
FILE

dce_transform.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c C
   1/*
   2 * Copyright 2012-16 Advanced Micro Devices, Inc.
   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 shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 * Authors: AMD
  23 *
  24 */
  25
  26#include "dce_transform.h"
  27#include "reg_helper.h"
  28#include "opp.h"
  29#include "basics/conversion.h"
  30#include "dc.h"
  31
  32#define REG(reg) \
  33	(xfm_dce->regs->reg)
  34
  35#undef FN
  36#define FN(reg_name, field_name) \
  37	xfm_dce->xfm_shift->field_name, xfm_dce->xfm_mask->field_name
  38
  39#define CTX \
  40	xfm_dce->base.ctx
  41#define DC_LOGGER \
  42	xfm_dce->base.ctx->logger
  43
  44#define IDENTITY_RATIO(ratio) (dc_fixpt_u2d19(ratio) == (1 << 19))
  45#define GAMUT_MATRIX_SIZE 12
  46#define SCL_PHASES 16
  47
  48enum dcp_out_trunc_round_mode {
  49	DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE,
  50	DCP_OUT_TRUNC_ROUND_MODE_ROUND
  51};
  52
  53enum dcp_out_trunc_round_depth {
  54	DCP_OUT_TRUNC_ROUND_DEPTH_14BIT,
  55	DCP_OUT_TRUNC_ROUND_DEPTH_13BIT,
  56	DCP_OUT_TRUNC_ROUND_DEPTH_12BIT,
  57	DCP_OUT_TRUNC_ROUND_DEPTH_11BIT,
  58	DCP_OUT_TRUNC_ROUND_DEPTH_10BIT,
  59	DCP_OUT_TRUNC_ROUND_DEPTH_9BIT,
  60	DCP_OUT_TRUNC_ROUND_DEPTH_8BIT
  61};
  62
  63/*  defines the various methods of bit reduction available for use */
  64enum dcp_bit_depth_reduction_mode {
  65	DCP_BIT_DEPTH_REDUCTION_MODE_DITHER,
  66	DCP_BIT_DEPTH_REDUCTION_MODE_ROUND,
  67	DCP_BIT_DEPTH_REDUCTION_MODE_TRUNCATE,
  68	DCP_BIT_DEPTH_REDUCTION_MODE_DISABLED,
  69	DCP_BIT_DEPTH_REDUCTION_MODE_INVALID
  70};
  71
  72enum dcp_spatial_dither_mode {
  73	DCP_SPATIAL_DITHER_MODE_AAAA,
  74	DCP_SPATIAL_DITHER_MODE_A_AA_A,
  75	DCP_SPATIAL_DITHER_MODE_AABBAABB,
  76	DCP_SPATIAL_DITHER_MODE_AABBCCAABBCC,
  77	DCP_SPATIAL_DITHER_MODE_INVALID
  78};
  79
  80enum dcp_spatial_dither_depth {
  81	DCP_SPATIAL_DITHER_DEPTH_30BPP,
  82	DCP_SPATIAL_DITHER_DEPTH_24BPP
  83};
  84
  85enum csc_color_mode {
  86	/* 00 - BITS2:0 Bypass */
  87	CSC_COLOR_MODE_GRAPHICS_BYPASS,
  88	/* 01 - hard coded coefficient TV RGB */
  89	CSC_COLOR_MODE_GRAPHICS_PREDEFINED,
  90	/* 04 - programmable OUTPUT CSC coefficient */
  91	CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC,
  92};
  93
  94enum grph_color_adjust_option {
  95	GRPH_COLOR_MATRIX_HW_DEFAULT = 1,
  96	GRPH_COLOR_MATRIX_SW
  97};
  98
  99static const struct out_csc_color_matrix global_color_matrix[] = {
 100{ COLOR_SPACE_SRGB,
 101	{ 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
 102{ COLOR_SPACE_SRGB_LIMITED,
 103	{ 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} },
 104{ COLOR_SPACE_YCBCR601,
 105	{ 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47,
 106		0xF6B9, 0xE00, 0x1000} },
 107{ COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA,
 108	0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} },
 109/* TODO: correct values below */
 110{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991,
 111	0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} },
 112{ COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3,
 113	0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }
 114};
 115
 116static bool setup_scaling_configuration(
 117	struct dce_transform *xfm_dce,
 118	const struct scaler_data *data)
 119{
 120	REG_SET(SCL_BYPASS_CONTROL, 0, SCL_BYPASS_MODE, 0);
 121
 122	if (data->taps.h_taps + data->taps.v_taps <= 2) {
 123		/* Set bypass */
 124		if (xfm_dce->xfm_mask->SCL_PSCL_EN != 0)
 125			REG_UPDATE_2(SCL_MODE, SCL_MODE, 0, SCL_PSCL_EN, 0);
 126		else
 127			REG_UPDATE(SCL_MODE, SCL_MODE, 0);
 128		return false;
 129	}
 130
 131	REG_SET_2(SCL_TAP_CONTROL, 0,
 132			SCL_H_NUM_OF_TAPS, data->taps.h_taps - 1,
 133			SCL_V_NUM_OF_TAPS, data->taps.v_taps - 1);
 134
 135	if (data->format <= PIXEL_FORMAT_GRPH_END)
 136		REG_UPDATE(SCL_MODE, SCL_MODE, 1);
 137	else
 138		REG_UPDATE(SCL_MODE, SCL_MODE, 2);
 139
 140	if (xfm_dce->xfm_mask->SCL_PSCL_EN != 0)
 141		REG_UPDATE(SCL_MODE, SCL_PSCL_EN, 1);
 142
 143	/* 1 - Replace out of bound pixels with edge */
 144	REG_SET(SCL_CONTROL, 0, SCL_BOUNDARY_MODE, 1);
 145
 146	return true;
 147}
 148
 149#if defined(CONFIG_DRM_AMD_DC_SI)
 150static bool dce60_setup_scaling_configuration(
 151	struct dce_transform *xfm_dce,
 152	const struct scaler_data *data)
 153{
 154	REG_SET(SCL_BYPASS_CONTROL, 0, SCL_BYPASS_MODE, 0);
 155
 156	if (data->taps.h_taps + data->taps.v_taps <= 2) {
 157		/* Disable scaler functionality */
 158		REG_WRITE(SCL_SCALER_ENABLE, 0);
 159
 160		/* Clear registers that can cause glitches even when the scaler is off */
 161		REG_WRITE(SCL_TAP_CONTROL, 0);
 162		REG_WRITE(SCL_AUTOMATIC_MODE_CONTROL, 0);
 163		REG_WRITE(SCL_F_SHARP_CONTROL, 0);
 164		return false;
 165	}
 166
 167	REG_SET_2(SCL_TAP_CONTROL, 0,
 168			SCL_H_NUM_OF_TAPS, data->taps.h_taps - 1,
 169			SCL_V_NUM_OF_TAPS, data->taps.v_taps - 1);
 170
 171	REG_WRITE(SCL_SCALER_ENABLE, 1);
 172
 173	/* DCE6 has no SCL_BOUNDARY_MODE bit, skip replace out of bound pixels */
 174
 175	return true;
 176}
 177#endif
 178
 179static void program_overscan(
 180		struct dce_transform *xfm_dce,
 181		const struct scaler_data *data)
 182{
 183	int overscan_right = data->h_active
 184			- data->recout.x - data->recout.width;
 185	int overscan_bottom = data->v_active
 186			- data->recout.y - data->recout.height;
 187
 188	if (xfm_dce->base.ctx->dc->debug.visual_confirm != VISUAL_CONFIRM_DISABLE) {
 189		overscan_bottom += 2;
 190		overscan_right += 2;
 191	}
 192
 193	if (overscan_right < 0) {
 194		BREAK_TO_DEBUGGER();
 195		overscan_right = 0;
 196	}
 197	if (overscan_bottom < 0) {
 198		BREAK_TO_DEBUGGER();
 199		overscan_bottom = 0;
 200	}
 201
 202	REG_SET_2(EXT_OVERSCAN_LEFT_RIGHT, 0,
 203			EXT_OVERSCAN_LEFT, data->recout.x,
 204			EXT_OVERSCAN_RIGHT, overscan_right);
 205	REG_SET_2(EXT_OVERSCAN_TOP_BOTTOM, 0,
 206			EXT_OVERSCAN_TOP, data->recout.y,
 207			EXT_OVERSCAN_BOTTOM, overscan_bottom);
 208}
 209
 210static void program_multi_taps_filter(
 211	struct dce_transform *xfm_dce,
 212	int taps,
 213	const uint16_t *coeffs,
 214	enum ram_filter_type filter_type)
 215{
 216	int phase, pair;
 217	int array_idx = 0;
 218	int taps_pairs = (taps + 1) / 2;
 219	int phases_to_program = SCL_PHASES / 2 + 1;
 220
 221	uint32_t power_ctl = 0;
 222
 223	if (!coeffs)
 224		return;
 225
 226	/*We need to disable power gating on coeff memory to do programming*/
 227	if (REG(DCFE_MEM_PWR_CTRL)) {
 228		power_ctl = REG_READ(DCFE_MEM_PWR_CTRL);
 229		REG_SET(DCFE_MEM_PWR_CTRL, power_ctl, SCL_COEFF_MEM_PWR_DIS, 1);
 230
 231		REG_WAIT(DCFE_MEM_PWR_STATUS, SCL_COEFF_MEM_PWR_STATE, 0, 1, 10);
 232	}
 233	for (phase = 0; phase < phases_to_program; phase++) {
 234		/*we always program N/2 + 1 phases, total phases N, but N/2-1 are just mirror
 235		phase 0 is unique and phase N/2 is unique if N is even*/
 236		for (pair = 0; pair < taps_pairs; pair++) {
 237			uint16_t odd_coeff = 0;
 238			uint16_t even_coeff = coeffs[array_idx];
 239
 240			REG_SET_3(SCL_COEF_RAM_SELECT, 0,
 241					SCL_C_RAM_FILTER_TYPE, filter_type,
 242					SCL_C_RAM_PHASE, phase,
 243					SCL_C_RAM_TAP_PAIR_IDX, pair);
 244
 245			if (taps % 2 && pair == taps_pairs - 1)
 246				array_idx++;
 247			else {
 248				odd_coeff = coeffs[array_idx + 1];
 249				array_idx += 2;
 250			}
 251
 252			REG_SET_4(SCL_COEF_RAM_TAP_DATA, 0,
 253					SCL_C_RAM_EVEN_TAP_COEF_EN, 1,
 254					SCL_C_RAM_EVEN_TAP_COEF, even_coeff,
 255					SCL_C_RAM_ODD_TAP_COEF_EN, 1,
 256					SCL_C_RAM_ODD_TAP_COEF, odd_coeff);
 257		}
 258	}
 259
 260	/*We need to restore power gating on coeff memory to initial state*/
 261	if (REG(DCFE_MEM_PWR_CTRL))
 262		REG_WRITE(DCFE_MEM_PWR_CTRL, power_ctl);
 263}
 264
 265static void program_viewport(
 266	struct dce_transform *xfm_dce,
 267	const struct rect *view_port)
 268{
 269	REG_SET_2(VIEWPORT_START, 0,
 270			VIEWPORT_X_START, view_port->x,
 271			VIEWPORT_Y_START, view_port->y);
 272
 273	REG_SET_2(VIEWPORT_SIZE, 0,
 274			VIEWPORT_HEIGHT, view_port->height,
 275			VIEWPORT_WIDTH, view_port->width);
 276
 277	/* TODO: add stereo support */
 278}
 279
 280static void calculate_inits(
 281	struct dce_transform *xfm_dce,
 282	const struct scaler_data *data,
 283	struct scl_ratios_inits *inits)
 284{
 285	struct fixed31_32 h_init;
 286	struct fixed31_32 v_init;
 287
 288	inits->h_int_scale_ratio =
 289		dc_fixpt_u2d19(data->ratios.horz) << 5;
 290	inits->v_int_scale_ratio =
 291		dc_fixpt_u2d19(data->ratios.vert) << 5;
 292
 293	h_init =
 294		dc_fixpt_div_int(
 295			dc_fixpt_add(
 296				data->ratios.horz,
 297				dc_fixpt_from_int(data->taps.h_taps + 1)),
 298				2);
 299	inits->h_init.integer = dc_fixpt_floor(h_init);
 300	inits->h_init.fraction = dc_fixpt_u0d19(h_init) << 5;
 301
 302	v_init =
 303		dc_fixpt_div_int(
 304			dc_fixpt_add(
 305				data->ratios.vert,
 306				dc_fixpt_from_int(data->taps.v_taps + 1)),
 307				2);
 308	inits->v_init.integer = dc_fixpt_floor(v_init);
 309	inits->v_init.fraction = dc_fixpt_u0d19(v_init) << 5;
 310}
 311
 312#if defined(CONFIG_DRM_AMD_DC_SI)
 313static void dce60_calculate_inits(
 314	struct dce_transform *xfm_dce,
 315	const struct scaler_data *data,
 316	struct sclh_ratios_inits *inits)
 317{
 318	struct fixed31_32 v_init;
 319
 320	inits->h_int_scale_ratio =
 321		dc_fixpt_u2d19(data->ratios.horz) << 5;
 322	inits->v_int_scale_ratio =
 323		dc_fixpt_u2d19(data->ratios.vert) << 5;
 324
 325	/* DCE6 h_init_luma setting inspired by DCE110 */
 326	inits->h_init_luma.integer = 1;
 327
 328	/* DCE6 h_init_chroma setting inspired by DCE110 */
 329	inits->h_init_chroma.integer = 1;
 330
 331	v_init =
 332		dc_fixpt_div_int(
 333			dc_fixpt_add(
 334				data->ratios.vert,
 335				dc_fixpt_from_int(data->taps.v_taps + 1)),
 336				2);
 337	inits->v_init.integer = dc_fixpt_floor(v_init);
 338	inits->v_init.fraction = dc_fixpt_u0d19(v_init) << 5;
 339}
 340#endif
 341
 342static void program_scl_ratios_inits(
 343	struct dce_transform *xfm_dce,
 344	struct scl_ratios_inits *inits)
 345{
 346
 347	REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0,
 348			SCL_H_SCALE_RATIO, inits->h_int_scale_ratio);
 349
 350	REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0,
 351			SCL_V_SCALE_RATIO, inits->v_int_scale_ratio);
 352
 353	REG_SET_2(SCL_HORZ_FILTER_INIT, 0,
 354			SCL_H_INIT_INT, inits->h_init.integer,
 355			SCL_H_INIT_FRAC, inits->h_init.fraction);
 356
 357	REG_SET_2(SCL_VERT_FILTER_INIT, 0,
 358			SCL_V_INIT_INT, inits->v_init.integer,
 359			SCL_V_INIT_FRAC, inits->v_init.fraction);
 360
 361	REG_WRITE(SCL_AUTOMATIC_MODE_CONTROL, 0);
 362}
 363
 364#if defined(CONFIG_DRM_AMD_DC_SI)
 365static void dce60_program_scl_ratios_inits(
 366	struct dce_transform *xfm_dce,
 367	struct sclh_ratios_inits *inits)
 368{
 369
 370	REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0,
 371			SCL_H_SCALE_RATIO, inits->h_int_scale_ratio);
 372
 373	REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0,
 374			SCL_V_SCALE_RATIO, inits->v_int_scale_ratio);
 375
 376	/* DCE6 has SCL_HORZ_FILTER_INIT_RGB_LUMA register */
 377	REG_SET_2(SCL_HORZ_FILTER_INIT_RGB_LUMA, 0,
 378			SCL_H_INIT_INT_RGB_Y, inits->h_init_luma.integer,
 379			SCL_H_INIT_FRAC_RGB_Y, inits->h_init_luma.fraction);
 380
 381	/* DCE6 has SCL_HORZ_FILTER_INIT_CHROMA register */
 382	REG_SET_2(SCL_HORZ_FILTER_INIT_CHROMA, 0,
 383			SCL_H_INIT_INT_CBCR, inits->h_init_chroma.integer,
 384			SCL_H_INIT_FRAC_CBCR, inits->h_init_chroma.fraction);
 385
 386	REG_SET_2(SCL_VERT_FILTER_INIT, 0,
 387			SCL_V_INIT_INT, inits->v_init.integer,
 388			SCL_V_INIT_FRAC, inits->v_init.fraction);
 389
 390	REG_WRITE(SCL_AUTOMATIC_MODE_CONTROL, 0);
 391}
 392#endif
 393
 394static const uint16_t *get_filter_coeffs_16p(int taps, struct fixed31_32 ratio)
 395{
 396	if (taps == 4)
 397		return get_filter_4tap_16p(ratio);
 398	else if (taps == 3)
 399		return get_filter_3tap_16p(ratio);
 400	else if (taps == 2)
 401		return get_filter_2tap_16p();
 402	else if (taps == 1)
 403		return NULL;
 404	else {
 405		/* should never happen, bug */
 406		BREAK_TO_DEBUGGER();
 407		return NULL;
 408	}
 409}
 410
 411static void dce_transform_set_scaler(
 412	struct transform *xfm,
 413	const struct scaler_data *data)
 414{
 415	struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
 416	bool is_scaling_required;
 417	bool filter_updated = false;
 418	const uint16_t *coeffs_v, *coeffs_h;
 419
 420	/*Use all three pieces of memory always*/
 421	REG_SET_2(LB_MEMORY_CTRL, 0,
 422			LB_MEMORY_CONFIG, 0,
 423			LB_MEMORY_SIZE, xfm_dce->lb_memory_size);
 424
 425	/* Clear SCL_F_SHARP_CONTROL value to 0 */
 426	REG_WRITE(SCL_F_SHARP_CONTROL, 0);
 427
 428	/* 1. Program overscan */
 429	program_overscan(xfm_dce, data);
 430
 431	/* 2. Program taps and configuration */
 432	is_scaling_required = setup_scaling_configuration(xfm_dce, data);
 433
 434	if (is_scaling_required) {
 435		/* 3. Calculate and program ratio, filter initialization */
 436		struct scl_ratios_inits inits = { 0 };
 437
 438		calculate_inits(xfm_dce, data, &inits);
 439
 440		program_scl_ratios_inits(xfm_dce, &inits);
 441
 442		coeffs_v = get_filter_coeffs_16p(data->taps.v_taps, data->ratios.vert);
 443		coeffs_h = get_filter_coeffs_16p(data->taps.h_taps, data->ratios.horz);
 444
 445		if (coeffs_v != xfm_dce->filter_v || coeffs_h != xfm_dce->filter_h) {
 446			/* 4. Program vertical filters */
 447			if (xfm_dce->filter_v == NULL)
 448				REG_SET(SCL_VERT_FILTER_CONTROL, 0,
 449						SCL_V_2TAP_HARDCODE_COEF_EN, 0);
 450			program_multi_taps_filter(
 451					xfm_dce,
 452					data->taps.v_taps,
 453					coeffs_v,
 454					FILTER_TYPE_RGB_Y_VERTICAL);
 455			program_multi_taps_filter(
 456					xfm_dce,
 457					data->taps.v_taps,
 458					coeffs_v,
 459					FILTER_TYPE_ALPHA_VERTICAL);
 460
 461			/* 5. Program horizontal filters */
 462			if (xfm_dce->filter_h == NULL)
 463				REG_SET(SCL_HORZ_FILTER_CONTROL, 0,
 464						SCL_H_2TAP_HARDCODE_COEF_EN, 0);
 465			program_multi_taps_filter(
 466					xfm_dce,
 467					data->taps.h_taps,
 468					coeffs_h,
 469					FILTER_TYPE_RGB_Y_HORIZONTAL);
 470			program_multi_taps_filter(
 471					xfm_dce,
 472					data->taps.h_taps,
 473					coeffs_h,
 474					FILTER_TYPE_ALPHA_HORIZONTAL);
 475
 476			xfm_dce->filter_v = coeffs_v;
 477			xfm_dce->filter_h = coeffs_h;
 478			filter_updated = true;
 479		}
 480	}
 481
 482	/* 6. Program the viewport */
 483	program_viewport(xfm_dce, &data->viewport);
 484
 485	/* 7. Set bit to flip to new coefficient memory */
 486	if (filter_updated)
 487		REG_UPDATE(SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE, 1);
 488
 489	REG_UPDATE(LB_DATA_FORMAT, ALPHA_EN, data->lb_params.alpha_en);
 490}
 491
 492#if defined(CONFIG_DRM_AMD_DC_SI)
 493static void dce60_transform_set_scaler(
 494	struct transform *xfm,
 495	const struct scaler_data *data)
 496{
 497	struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
 498	bool is_scaling_required;
 499	const uint16_t *coeffs_v, *coeffs_h;
 500
 501	/*Use whole line buffer memory always*/
 502	REG_SET(DC_LB_MEMORY_SPLIT, 0,
 503		DC_LB_MEMORY_CONFIG, 0);
 504
 505	REG_SET(DC_LB_MEM_SIZE, 0,
 506		DC_LB_MEM_SIZE, xfm_dce->lb_memory_size);
 507
 508	REG_WRITE(SCL_UPDATE, 0x00010000);
 509
 510	/* Clear SCL_F_SHARP_CONTROL value to 0 */
 511	REG_WRITE(SCL_F_SHARP_CONTROL, 0);
 512
 513	/* 1. Program overscan */
 514	program_overscan(xfm_dce, data);
 515
 516	/* 2. Program taps and configuration */
 517	is_scaling_required = dce60_setup_scaling_configuration(xfm_dce, data);
 518
 519	if (is_scaling_required) {
 520		/* 3. Calculate and program ratio, DCE6 filter initialization */
 521		struct sclh_ratios_inits inits = { 0 };
 522
 523		/* DCE6 has specific calculate_inits() function */
 524		dce60_calculate_inits(xfm_dce, data, &inits);
 525
 526		/* DCE6 has specific program_scl_ratios_inits() function */
 527		dce60_program_scl_ratios_inits(xfm_dce, &inits);
 528
 529		coeffs_v = get_filter_coeffs_16p(data->taps.v_taps, data->ratios.vert);
 530		coeffs_h = get_filter_coeffs_16p(data->taps.h_taps, data->ratios.horz);
 531
 532		if (coeffs_v != xfm_dce->filter_v || coeffs_h != xfm_dce->filter_h) {
 533			/* 4. Program vertical filters */
 534			if (xfm_dce->filter_v == NULL)
 535				REG_WRITE(SCL_VERT_FILTER_CONTROL, 0);
 536			program_multi_taps_filter(
 537					xfm_dce,
 538					data->taps.v_taps,
 539					coeffs_v,
 540					FILTER_TYPE_RGB_Y_VERTICAL);
 541			program_multi_taps_filter(
 542					xfm_dce,
 543					data->taps.v_taps,
 544					coeffs_v,
 545					FILTER_TYPE_ALPHA_VERTICAL);
 546
 547			/* 5. Program horizontal filters */
 548			if (xfm_dce->filter_h == NULL)
 549				REG_WRITE(SCL_HORZ_FILTER_CONTROL, 0);
 550			program_multi_taps_filter(
 551					xfm_dce,
 552					data->taps.h_taps,
 553					coeffs_h,
 554					FILTER_TYPE_RGB_Y_HORIZONTAL);
 555			program_multi_taps_filter(
 556					xfm_dce,
 557					data->taps.h_taps,
 558					coeffs_h,
 559					FILTER_TYPE_ALPHA_HORIZONTAL);
 560
 561			xfm_dce->filter_v = coeffs_v;
 562			xfm_dce->filter_h = coeffs_h;
 563		}
 564	}
 565
 566	/* 6. Program the viewport */
 567	program_viewport(xfm_dce, &data->viewport);
 568
 569	/* DCE6 has no SCL_COEF_UPDATE_COMPLETE bit to flip to new coefficient memory */
 570
 571	/* DCE6 DATA_FORMAT register does not support ALPHA_EN */
 572
 573	REG_WRITE(SCL_UPDATE, 0);
 574}
 575#endif
 576
 577/*****************************************************************************
 578 * set_clamp
 579 *
 580 * @param depth : bit depth to set the clamp to (should match denorm)
 581 *
 582 * @brief
 583 *     Programs clamp according to panel bit depth.
 584 *
 585 *******************************************************************************/
 586static void set_clamp(
 587	struct dce_transform *xfm_dce,
 588	enum dc_color_depth depth)
 589{
 590	int clamp_max = 0;
 591
 592	/* At the clamp block the data will be MSB aligned, so we set the max
 593	 * clamp accordingly.
 594	 * For example, the max value for 6 bits MSB aligned (14 bit bus) would
 595	 * be "11 1111 0000 0000" in binary, so 0x3F00.
 596	 */
 597	switch (depth) {
 598	case COLOR_DEPTH_666:
 599		/* 6bit MSB aligned on 14 bit bus '11 1111 0000 0000' */
 600		clamp_max = 0x3F00;
 601		break;
 602	case COLOR_DEPTH_888:
 603		/* 8bit MSB aligned on 14 bit bus '11 1111 1100 0000' */
 604		clamp_max = 0x3FC0;
 605		break;
 606	case COLOR_DEPTH_101010:
 607		/* 10bit MSB aligned on 14 bit bus '11 1111 1111 0000' */
 608		clamp_max = 0x3FF0;
 609		break;
 610	case COLOR_DEPTH_121212:
 611		/* 12bit MSB aligned on 14 bit bus '11 1111 1111 1100' */
 612		clamp_max = 0x3FFC;
 613		break;
 614	default:
 615		clamp_max = 0x3FC0;
 616		BREAK_TO_DEBUGGER(); /* Invalid clamp bit depth */
 617	}
 618	REG_SET_2(OUT_CLAMP_CONTROL_B_CB, 0,
 619			OUT_CLAMP_MIN_B_CB, 0,
 620			OUT_CLAMP_MAX_B_CB, clamp_max);
 621
 622	REG_SET_2(OUT_CLAMP_CONTROL_G_Y, 0,
 623			OUT_CLAMP_MIN_G_Y, 0,
 624			OUT_CLAMP_MAX_G_Y, clamp_max);
 625
 626	REG_SET_2(OUT_CLAMP_CONTROL_R_CR, 0,
 627			OUT_CLAMP_MIN_R_CR, 0,
 628			OUT_CLAMP_MAX_R_CR, clamp_max);
 629}
 630
 631/*******************************************************************************
 632 * set_round
 633 *
 634 * @brief
 635 *     Programs Round/Truncate
 636 *
 637 * @param [in] mode  :round or truncate
 638 * @param [in] depth :bit depth to round/truncate to
 639 OUT_ROUND_TRUNC_MODE 3:0 0xA Output data round or truncate mode
 640 POSSIBLE VALUES:
 641      00 - truncate to u0.12
 642      01 - truncate to u0.11
 643      02 - truncate to u0.10
 644      03 - truncate to u0.9
 645      04 - truncate to u0.8
 646      05 - reserved
 647      06 - truncate to u0.14
 648      07 - truncate to u0.13		set_reg_field_value(
 649			value,
 650			clamp_max,
 651			OUT_CLAMP_CONTROL_R_CR,
 652			OUT_CLAMP_MAX_R_CR);
 653      08 - round to u0.12
 654      09 - round to u0.11
 655      10 - round to u0.10
 656      11 - round to u0.9
 657      12 - round to u0.8
 658      13 - reserved
 659      14 - round to u0.14
 660      15 - round to u0.13
 661
 662 ******************************************************************************/
 663static void set_round(
 664	struct dce_transform *xfm_dce,
 665	enum dcp_out_trunc_round_mode mode,
 666	enum dcp_out_trunc_round_depth depth)
 667{
 668	int depth_bits = 0;
 669	int mode_bit = 0;
 670
 671	/*  set up bit depth */
 672	switch (depth) {
 673	case DCP_OUT_TRUNC_ROUND_DEPTH_14BIT:
 674		depth_bits = 6;
 675		break;
 676	case DCP_OUT_TRUNC_ROUND_DEPTH_13BIT:
 677		depth_bits = 7;
 678		break;
 679	case DCP_OUT_TRUNC_ROUND_DEPTH_12BIT:
 680		depth_bits = 0;
 681		break;
 682	case DCP_OUT_TRUNC_ROUND_DEPTH_11BIT:
 683		depth_bits = 1;
 684		break;
 685	case DCP_OUT_TRUNC_ROUND_DEPTH_10BIT:
 686		depth_bits = 2;
 687		break;
 688	case DCP_OUT_TRUNC_ROUND_DEPTH_9BIT:
 689		depth_bits = 3;
 690		break;
 691	case DCP_OUT_TRUNC_ROUND_DEPTH_8BIT:
 692		depth_bits = 4;
 693		break;
 694	default:
 695		depth_bits = 4;
 696		BREAK_TO_DEBUGGER(); /* Invalid dcp_out_trunc_round_depth */
 697	}
 698
 699	/*  set up round or truncate */
 700	switch (mode) {
 701	case DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE:
 702		mode_bit = 0;
 703		break;
 704	case DCP_OUT_TRUNC_ROUND_MODE_ROUND:
 705		mode_bit = 1;
 706		break;
 707	default:
 708		BREAK_TO_DEBUGGER(); /* Invalid dcp_out_trunc_round_mode */
 709	}
 710
 711	depth_bits |= mode_bit << 3;
 712
 713	REG_SET(OUT_ROUND_CONTROL, 0, OUT_ROUND_TRUNC_MODE, depth_bits);
 714}
 715
 716/*****************************************************************************
 717 * set_dither
 718 *
 719 * @brief
 720 *     Programs Dither
 721 *
 722 * @param [in] dither_enable        : enable dither
 723 * @param [in] dither_mode           : dither mode to set
 724 * @param [in] dither_depth          : bit depth to dither to
 725 * @param [in] frame_random_enable    : enable frame random
 726 * @param [in] rgb_random_enable      : enable rgb random
 727 * @param [in] highpass_random_enable : enable highpass random
 728 *
 729 ******************************************************************************/
 730
 731static void set_dither(
 732	struct dce_transform *xfm_dce,
 733	bool dither_enable,
 734	enum dcp_spatial_dither_mode dither_mode,
 735	enum dcp_spatial_dither_depth dither_depth,
 736	bool frame_random_enable,
 737	bool rgb_random_enable,
 738	bool highpass_random_enable)
 739{
 740	int dither_depth_bits = 0;
 741	int dither_mode_bits = 0;
 742
 743	switch (dither_mode) {
 744	case DCP_SPATIAL_DITHER_MODE_AAAA:
 745		dither_mode_bits = 0;
 746		break;
 747	case DCP_SPATIAL_DITHER_MODE_A_AA_A:
 748		dither_mode_bits = 1;
 749		break;
 750	case DCP_SPATIAL_DITHER_MODE_AABBAABB:
 751		dither_mode_bits = 2;
 752		break;
 753	case DCP_SPATIAL_DITHER_MODE_AABBCCAABBCC:
 754		dither_mode_bits = 3;
 755		break;
 756	default:
 757		/* Invalid dcp_spatial_dither_mode */
 758		BREAK_TO_DEBUGGER();
 759	}
 760
 761	switch (dither_depth) {
 762	case DCP_SPATIAL_DITHER_DEPTH_30BPP:
 763		dither_depth_bits = 0;
 764		break;
 765	case DCP_SPATIAL_DITHER_DEPTH_24BPP:
 766		dither_depth_bits = 1;
 767		break;
 768	default:
 769		/* Invalid dcp_spatial_dither_depth */
 770		BREAK_TO_DEBUGGER();
 771	}
 772
 773	/*  write the register */
 774	REG_SET_6(DCP_SPATIAL_DITHER_CNTL, 0,
 775			DCP_SPATIAL_DITHER_EN, dither_enable,
 776			DCP_SPATIAL_DITHER_MODE, dither_mode_bits,
 777			DCP_SPATIAL_DITHER_DEPTH, dither_depth_bits,
 778			DCP_FRAME_RANDOM_ENABLE, frame_random_enable,
 779			DCP_RGB_RANDOM_ENABLE, rgb_random_enable,
 780			DCP_HIGHPASS_RANDOM_ENABLE, highpass_random_enable);
 781}
 782
 783/*****************************************************************************
 784 * dce_transform_bit_depth_reduction_program
 785 *
 786 * @brief
 787 *     Programs the DCP bit depth reduction registers (Clamp, Round/Truncate,
 788 *      Dither) for dce
 789 *
 790 * @param depth : bit depth to set the clamp to (should match denorm)
 791 *
 792 ******************************************************************************/
 793static void program_bit_depth_reduction(
 794	struct dce_transform *xfm_dce,
 795	enum dc_color_depth depth,
 796	const struct bit_depth_reduction_params *bit_depth_params)
 797{
 798	enum dcp_out_trunc_round_depth trunc_round_depth;
 799	enum dcp_out_trunc_round_mode trunc_mode;
 800	bool spatial_dither_enable;
 801
 802	ASSERT(depth <= COLOR_DEPTH_121212); /* Invalid clamp bit depth */
 803
 804	spatial_dither_enable = bit_depth_params->flags.SPATIAL_DITHER_ENABLED;
 805	/* Default to 12 bit truncation without rounding */
 806	trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_12BIT;
 807	trunc_mode = DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE;
 808
 809	if (bit_depth_params->flags.TRUNCATE_ENABLED) {
 810		/* Don't enable dithering if truncation is enabled */
 811		spatial_dither_enable = false;
 812		trunc_mode = bit_depth_params->flags.TRUNCATE_MODE ?
 813			     DCP_OUT_TRUNC_ROUND_MODE_ROUND :
 814			     DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE;
 815
 816		if (bit_depth_params->flags.TRUNCATE_DEPTH == 0 ||
 817		    bit_depth_params->flags.TRUNCATE_DEPTH == 1)
 818			trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_8BIT;
 819		else if (bit_depth_params->flags.TRUNCATE_DEPTH == 2)
 820			trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_10BIT;
 821		else {
 822			/*
 823			 * Invalid truncate/round depth. Setting here to 12bit
 824			 * to prevent use-before-initialize errors.
 825			 */
 826			trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_12BIT;
 827			BREAK_TO_DEBUGGER();
 828		}
 829	}
 830
 831	set_clamp(xfm_dce, depth);
 832	set_round(xfm_dce, trunc_mode, trunc_round_depth);
 833	set_dither(xfm_dce,
 834		   spatial_dither_enable,
 835		   DCP_SPATIAL_DITHER_MODE_A_AA_A,
 836		   DCP_SPATIAL_DITHER_DEPTH_30BPP,
 837		   bit_depth_params->flags.FRAME_RANDOM,
 838		   bit_depth_params->flags.RGB_RANDOM,
 839		   bit_depth_params->flags.HIGHPASS_RANDOM);
 840}
 841
 842#if defined(CONFIG_DRM_AMD_DC_SI)
 843/*****************************************************************************
 844 * dce60_transform_bit_depth_reduction program
 845 *
 846 * @brief
 847 *     Programs the DCP bit depth reduction registers (Clamp, Round/Truncate,
 848 *      Dither) for dce
 849 *
 850 * @param depth : bit depth to set the clamp to (should match denorm)
 851 *
 852 ******************************************************************************/
 853static void dce60_program_bit_depth_reduction(
 854	struct dce_transform *xfm_dce,
 855	enum dc_color_depth depth,
 856	const struct bit_depth_reduction_params *bit_depth_params)
 857{
 858	enum dcp_out_trunc_round_depth trunc_round_depth;
 859	enum dcp_out_trunc_round_mode trunc_mode;
 860	bool spatial_dither_enable;
 861
 862	ASSERT(depth <= COLOR_DEPTH_121212); /* Invalid clamp bit depth */
 863
 864	spatial_dither_enable = bit_depth_params->flags.SPATIAL_DITHER_ENABLED;
 865	/* Default to 12 bit truncation without rounding */
 866	trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_12BIT;
 867	trunc_mode = DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE;
 868
 869	if (bit_depth_params->flags.TRUNCATE_ENABLED) {
 870		/* Don't enable dithering if truncation is enabled */
 871		spatial_dither_enable = false;
 872		trunc_mode = bit_depth_params->flags.TRUNCATE_MODE ?
 873			     DCP_OUT_TRUNC_ROUND_MODE_ROUND :
 874			     DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE;
 875
 876		if (bit_depth_params->flags.TRUNCATE_DEPTH == 0 ||
 877		    bit_depth_params->flags.TRUNCATE_DEPTH == 1)
 878			trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_8BIT;
 879		else if (bit_depth_params->flags.TRUNCATE_DEPTH == 2)
 880			trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_10BIT;
 881		else {
 882			/*
 883			 * Invalid truncate/round depth. Setting here to 12bit
 884			 * to prevent use-before-initialize errors.
 885			 */
 886			trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_12BIT;
 887			BREAK_TO_DEBUGGER();
 888		}
 889	}
 890
 891	/* DCE6 has no OUT_CLAMP_CONTROL_* registers - set_clamp() is skipped */
 892	set_round(xfm_dce, trunc_mode, trunc_round_depth);
 893	set_dither(xfm_dce,
 894		   spatial_dither_enable,
 895		   DCP_SPATIAL_DITHER_MODE_A_AA_A,
 896		   DCP_SPATIAL_DITHER_DEPTH_30BPP,
 897		   bit_depth_params->flags.FRAME_RANDOM,
 898		   bit_depth_params->flags.RGB_RANDOM,
 899		   bit_depth_params->flags.HIGHPASS_RANDOM);
 900}
 901#endif
 902
 903static int dce_transform_get_max_num_of_supported_lines(
 904	struct dce_transform *xfm_dce,
 905	enum lb_pixel_depth depth,
 906	int pixel_width)
 907{
 908	int pixels_per_entries = 0;
 909	int max_pixels_supports = 0;
 910
 911	ASSERT(pixel_width);
 912
 913	/* Find number of pixels that can fit into a single LB entry and
 914	 * take floor of the value since we cannot store a single pixel
 915	 * across multiple entries. */
 916	switch (depth) {
 917	case LB_PIXEL_DEPTH_18BPP:
 918		pixels_per_entries = xfm_dce->lb_bits_per_entry / 18;
 919		break;
 920
 921	case LB_PIXEL_DEPTH_24BPP:
 922		pixels_per_entries = xfm_dce->lb_bits_per_entry / 24;
 923		break;
 924
 925	case LB_PIXEL_DEPTH_30BPP:
 926		pixels_per_entries = xfm_dce->lb_bits_per_entry / 30;
 927		break;
 928
 929	case LB_PIXEL_DEPTH_36BPP:
 930		pixels_per_entries = xfm_dce->lb_bits_per_entry / 36;
 931		break;
 932
 933	default:
 934		DC_LOG_WARNING("%s: Invalid LB pixel depth",
 935			__func__);
 936		BREAK_TO_DEBUGGER();
 937		break;
 938	}
 939
 940	ASSERT(pixels_per_entries);
 941
 942	max_pixels_supports =
 943			pixels_per_entries *
 944			xfm_dce->lb_memory_size;
 945
 946	return (max_pixels_supports / pixel_width);
 947}
 948
 949static void set_denormalization(
 950	struct dce_transform *xfm_dce,
 951	enum dc_color_depth depth)
 952{
 953	int denorm_mode = 0;
 954
 955	switch (depth) {
 956	case COLOR_DEPTH_666:
 957		/* 63/64 for 6 bit output color depth */
 958		denorm_mode = 1;
 959		break;
 960	case COLOR_DEPTH_888:
 961		/* Unity for 8 bit output color depth
 962		 * because prescale is disabled by default */
 963		denorm_mode = 0;
 964		break;
 965	case COLOR_DEPTH_101010:
 966		/* 1023/1024 for 10 bit output color depth */
 967		denorm_mode = 3;
 968		break;
 969	case COLOR_DEPTH_121212:
 970		/* 4095/4096 for 12 bit output color depth */
 971		denorm_mode = 5;
 972		break;
 973	case COLOR_DEPTH_141414:
 974	case COLOR_DEPTH_161616:
 975	default:
 976		/* not valid used case! */
 977		break;
 978	}
 979
 980	REG_SET(DENORM_CONTROL, 0, DENORM_MODE, denorm_mode);
 981}
 982
 983static void dce_transform_set_pixel_storage_depth(
 984	struct transform *xfm,
 985	enum lb_pixel_depth depth,
 986	const struct bit_depth_reduction_params *bit_depth_params)
 987{
 988	struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
 989	int pixel_depth, expan_mode;
 990	enum dc_color_depth color_depth;
 991
 992	switch (depth) {
 993	case LB_PIXEL_DEPTH_18BPP:
 994		color_depth = COLOR_DEPTH_666;
 995		pixel_depth = 2;
 996		expan_mode  = 1;
 997		break;
 998	case LB_PIXEL_DEPTH_24BPP:
 999		color_depth = COLOR_DEPTH_888;
1000		pixel_depth = 1;
1001		expan_mode  = 1;
1002		break;
1003	case LB_PIXEL_DEPTH_30BPP:
1004		color_depth = COLOR_DEPTH_101010;
1005		pixel_depth = 0;
1006		expan_mode  = 1;
1007		break;
1008	case LB_PIXEL_DEPTH_36BPP:
1009		color_depth = COLOR_DEPTH_121212;
1010		pixel_depth = 3;
1011		expan_mode  = 0;
1012		break;
1013	default:
1014		color_depth = COLOR_DEPTH_101010;
1015		pixel_depth = 0;
1016		expan_mode  = 1;
1017		DC_LOG_DC("The pixel depth %d is not valid, set COLOR_DEPTH_101010 instead.", depth);
1018		break;
1019	}
1020
1021	set_denormalization(xfm_dce, color_depth);
1022	program_bit_depth_reduction(xfm_dce, color_depth, bit_depth_params);
1023
1024	REG_UPDATE_2(LB_DATA_FORMAT,
1025			PIXEL_DEPTH, pixel_depth,
1026			PIXEL_EXPAN_MODE, expan_mode);
1027
1028	if (!(xfm_dce->lb_pixel_depth_supported & depth)) {
1029		/*we should use unsupported capabilities
1030		 *  unless it is required by w/a*/
1031		DC_LOG_DC("%s: Capability not supported", __func__);
1032	}
1033}
1034
1035#if defined(CONFIG_DRM_AMD_DC_SI)
1036static void dce60_transform_set_pixel_storage_depth(
1037	struct transform *xfm,
1038	enum lb_pixel_depth depth,
1039	const struct bit_depth_reduction_params *bit_depth_params)
1040{
1041	struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1042	enum dc_color_depth color_depth;
1043
1044	switch (depth) {
1045	case LB_PIXEL_DEPTH_18BPP:
1046		color_depth = COLOR_DEPTH_666;
1047		break;
1048	case LB_PIXEL_DEPTH_24BPP:
1049		color_depth = COLOR_DEPTH_888;
1050		break;
1051	case LB_PIXEL_DEPTH_30BPP:
1052		color_depth = COLOR_DEPTH_101010;
1053		break;
1054	case LB_PIXEL_DEPTH_36BPP:
1055		color_depth = COLOR_DEPTH_121212;
1056		break;
1057	default:
1058		color_depth = COLOR_DEPTH_101010;
1059		BREAK_TO_DEBUGGER();
1060		break;
1061	}
1062
1063	set_denormalization(xfm_dce, color_depth);
1064	dce60_program_bit_depth_reduction(xfm_dce, color_depth, bit_depth_params);
1065
1066	/* DATA_FORMAT in DCE6 does not have PIXEL_DEPTH and PIXEL_EXPAN_MODE masks */
1067
1068	if (!(xfm_dce->lb_pixel_depth_supported & depth)) {
1069		/*we should use unsupported capabilities
1070		 *  unless it is required by w/a*/
1071		DC_LOG_WARNING("%s: Capability not supported",
1072			__func__);
1073	}
1074}
1075#endif
1076
1077static void program_gamut_remap(
1078	struct dce_transform *xfm_dce,
1079	const uint16_t *reg_val)
1080{
1081	if (reg_val) {
1082		REG_SET_2(GAMUT_REMAP_C11_C12, 0,
1083				GAMUT_REMAP_C11, reg_val[0],
1084				GAMUT_REMAP_C12, reg_val[1]);
1085		REG_SET_2(GAMUT_REMAP_C13_C14, 0,
1086				GAMUT_REMAP_C13, reg_val[2],
1087				GAMUT_REMAP_C14, reg_val[3]);
1088		REG_SET_2(GAMUT_REMAP_C21_C22, 0,
1089				GAMUT_REMAP_C21, reg_val[4],
1090				GAMUT_REMAP_C22, reg_val[5]);
1091		REG_SET_2(GAMUT_REMAP_C23_C24, 0,
1092				GAMUT_REMAP_C23, reg_val[6],
1093				GAMUT_REMAP_C24, reg_val[7]);
1094		REG_SET_2(GAMUT_REMAP_C31_C32, 0,
1095				GAMUT_REMAP_C31, reg_val[8],
1096				GAMUT_REMAP_C32, reg_val[9]);
1097		REG_SET_2(GAMUT_REMAP_C33_C34, 0,
1098				GAMUT_REMAP_C33, reg_val[10],
1099				GAMUT_REMAP_C34, reg_val[11]);
1100
1101		REG_SET(GAMUT_REMAP_CONTROL, 0, GRPH_GAMUT_REMAP_MODE, 1);
1102	} else
1103		REG_SET(GAMUT_REMAP_CONTROL, 0, GRPH_GAMUT_REMAP_MODE, 0);
1104
1105}
1106
1107/*
1108 *****************************************************************************
1109 *  Function: dal_transform_wide_gamut_set_gamut_remap
1110 *
1111 *  @param [in] const struct xfm_grph_csc_adjustment *adjust
1112 *
1113 *  @return
1114 *     void
1115 *
1116 *  @note calculate and apply color temperature adjustment to in Rgb color space
1117 *
1118 *  @see
1119 *
1120 *****************************************************************************
1121 */
1122static void dce_transform_set_gamut_remap(
1123	struct transform *xfm,
1124	const struct xfm_grph_csc_adjustment *adjust)
1125{
1126	struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1127	int i = 0;
1128
1129	if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW)
1130		/* Bypass if type is bypass or hw */
1131		program_gamut_remap(xfm_dce, NULL);
1132	else {
1133		struct fixed31_32 arr_matrix[GAMUT_MATRIX_SIZE];
1134		uint16_t arr_reg_val[GAMUT_MATRIX_SIZE];
1135
1136		for (i = 0; i < GAMUT_MATRIX_SIZE; i++)
1137			arr_matrix[i] = adjust->temperature_matrix[i];
1138
1139		convert_float_matrix(
1140			arr_reg_val, arr_matrix, GAMUT_MATRIX_SIZE);
1141
1142		program_gamut_remap(xfm_dce, arr_reg_val);
1143	}
1144}
1145
1146static uint32_t decide_taps(struct fixed31_32 ratio, uint32_t in_taps, bool chroma)
1147{
1148	uint32_t taps;
1149
1150	if (IDENTITY_RATIO(ratio)) {
1151		return 1;
1152	} else if (in_taps != 0) {
1153		taps = in_taps;
1154	} else {
1155		taps = 4;
1156	}
1157
1158	if (chroma) {
1159		taps /= 2;
1160		if (taps < 2)
1161			taps = 2;
1162	}
1163
1164	return taps;
1165}
1166
1167
1168bool dce_transform_get_optimal_number_of_taps(
1169	struct transform *xfm,
1170	struct scaler_data *scl_data,
1171	const struct scaling_taps *in_taps)
1172{
1173	struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1174	int pixel_width = scl_data->viewport.width;
1175	int max_num_of_lines;
1176
1177	if (xfm_dce->prescaler_on &&
1178			(scl_data->viewport.width > scl_data->recout.width))
1179		pixel_width = scl_data->recout.width;
1180
1181	max_num_of_lines = dce_transform_get_max_num_of_supported_lines(
1182		xfm_dce,
1183		scl_data->lb_params.depth,
1184		pixel_width);
1185
1186	/* Fail if in_taps are impossible */
1187	if (in_taps->v_taps >= max_num_of_lines)
1188		return false;
1189
1190	/*
1191	 * Set taps according to this policy (in this order)
1192	 * - Use 1 for no scaling
1193	 * - Use input taps
1194	 * - Use 4 and reduce as required by line buffer size
1195	 * - Decide chroma taps if chroma is scaled
1196	 *
1197	 * Ignore input chroma taps. Decide based on non-chroma
1198	 */
1199	scl_data->taps.h_taps = decide_taps(scl_data->ratios.horz, in_taps->h_taps, false);
1200	scl_data->taps.v_taps = decide_taps(scl_data->ratios.vert, in_taps->v_taps, false);
1201	scl_data->taps.h_taps_c = decide_taps(scl_data->ratios.horz_c, in_taps->h_taps, true);
1202	scl_data->taps.v_taps_c = decide_taps(scl_data->ratios.vert_c, in_taps->v_taps, true);
1203
1204	if (!IDENTITY_RATIO(scl_data->ratios.vert)) {
1205		/* reduce v_taps if needed but ensure we have at least two */
1206		if (in_taps->v_taps == 0
1207				&& max_num_of_lines <= scl_data->taps.v_taps
1208				&& scl_data->taps.v_taps > 1) {
1209			scl_data->taps.v_taps = max_num_of_lines - 1;
1210		}
1211
1212		if (scl_data->taps.v_taps <= 1)
1213			return false;
1214	}
1215
1216	if (!IDENTITY_RATIO(scl_data->ratios.vert_c)) {
1217		/* reduce chroma v_taps if needed but ensure we have at least two */
1218		if (max_num_of_lines <= scl_data->taps.v_taps_c && scl_data->taps.v_taps_c > 1) {
1219			scl_data->taps.v_taps_c = max_num_of_lines - 1;
1220		}
1221
1222		if (scl_data->taps.v_taps_c <= 1)
1223			return false;
1224	}
1225
1226	/* we've got valid taps */
1227	return true;
1228}
1229
1230static void dce_transform_reset(struct transform *xfm)
1231{
1232	struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1233
1234	xfm_dce->filter_h = NULL;
1235	xfm_dce->filter_v = NULL;
1236}
1237
1238static void program_color_matrix(
1239	struct dce_transform *xfm_dce,
1240	const struct out_csc_color_matrix *tbl_entry,
1241	enum grph_color_adjust_option options)
1242{
1243	{
1244		REG_SET_2(OUTPUT_CSC_C11_C12, 0,
1245			OUTPUT_CSC_C11, tbl_entry->regval[0],
1246			OUTPUT_CSC_C12, tbl_entry->regval[1]);
1247	}
1248	{
1249		REG_SET_2(OUTPUT_CSC_C13_C14, 0,
1250			OUTPUT_CSC_C11, tbl_entry->regval[2],
1251			OUTPUT_CSC_C12, tbl_entry->regval[3]);
1252	}
1253	{
1254		REG_SET_2(OUTPUT_CSC_C21_C22, 0,
1255			OUTPUT_CSC_C11, tbl_entry->regval[4],
1256			OUTPUT_CSC_C12, tbl_entry->regval[5]);
1257	}
1258	{
1259		REG_SET_2(OUTPUT_CSC_C23_C24, 0,
1260			OUTPUT_CSC_C11, tbl_entry->regval[6],
1261			OUTPUT_CSC_C12, tbl_entry->regval[7]);
1262	}
1263	{
1264		REG_SET_2(OUTPUT_CSC_C31_C32, 0,
1265			OUTPUT_CSC_C11, tbl_entry->regval[8],
1266			OUTPUT_CSC_C12, tbl_entry->regval[9]);
1267	}
1268	{
1269		REG_SET_2(OUTPUT_CSC_C33_C34, 0,
1270			OUTPUT_CSC_C11, tbl_entry->regval[10],
1271			OUTPUT_CSC_C12, tbl_entry->regval[11]);
1272	}
1273}
1274
1275static bool configure_graphics_mode(
1276	struct dce_transform *xfm_dce,
1277	enum csc_color_mode config,
1278	enum graphics_csc_adjust_type csc_adjust_type,
1279	enum dc_color_space color_space)
1280{
1281	REG_SET(OUTPUT_CSC_CONTROL, 0,
1282		OUTPUT_CSC_GRPH_MODE, 0);
1283
1284	if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) {
1285		if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) {
1286			REG_SET(OUTPUT_CSC_CONTROL, 0,
1287				OUTPUT_CSC_GRPH_MODE, 4);
1288		} else {
1289
1290			switch (color_space) {
1291			case COLOR_SPACE_SRGB:
1292				/* by pass */
1293				REG_SET(OUTPUT_CSC_CONTROL, 0,
1294					OUTPUT_CSC_GRPH_MODE, 0);
1295				break;
1296			case COLOR_SPACE_SRGB_LIMITED:
1297				/* TV RGB */
1298				REG_SET(OUTPUT_CSC_CONTROL, 0,
1299					OUTPUT_CSC_GRPH_MODE, 1);
1300				break;
1301			case COLOR_SPACE_YCBCR601:
1302			case COLOR_SPACE_YCBCR601_LIMITED:
1303				/* YCbCr601 */
1304				REG_SET(OUTPUT_CSC_CONTROL, 0,
1305					OUTPUT_CSC_GRPH_MODE, 2);
1306				break;
1307			case COLOR_SPACE_YCBCR709:
1308			case COLOR_SPACE_YCBCR709_LIMITED:
1309				/* YCbCr709 */
1310				REG_SET(OUTPUT_CSC_CONTROL, 0,
1311					OUTPUT_CSC_GRPH_MODE, 3);
1312				break;
1313			default:
1314				return false;
1315			}
1316		}
1317	} else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) {
1318		switch (color_space) {
1319		case COLOR_SPACE_SRGB:
1320			/* by pass */
1321			REG_SET(OUTPUT_CSC_CONTROL, 0,
1322				OUTPUT_CSC_GRPH_MODE, 0);
1323			break;
1324		case COLOR_SPACE_SRGB_LIMITED:
1325			/* TV RGB */
1326			REG_SET(OUTPUT_CSC_CONTROL, 0,
1327				OUTPUT_CSC_GRPH_MODE, 1);
1328			break;
1329		case COLOR_SPACE_YCBCR601:
1330		case COLOR_SPACE_YCBCR601_LIMITED:
1331			/* YCbCr601 */
1332			REG_SET(OUTPUT_CSC_CONTROL, 0,
1333				OUTPUT_CSC_GRPH_MODE, 2);
1334			break;
1335		case COLOR_SPACE_YCBCR709:
1336		case COLOR_SPACE_YCBCR709_LIMITED:
1337			 /* YCbCr709 */
1338			REG_SET(OUTPUT_CSC_CONTROL, 0,
1339				OUTPUT_CSC_GRPH_MODE, 3);
1340			break;
1341		default:
1342			return false;
1343		}
1344
1345	} else
1346		/* by pass */
1347		REG_SET(OUTPUT_CSC_CONTROL, 0,
1348			OUTPUT_CSC_GRPH_MODE, 0);
1349
1350	return true;
1351}
1352
1353void dce110_opp_set_csc_adjustment(
1354	struct transform *xfm,
1355	const struct out_csc_color_matrix *tbl_entry)
1356{
1357	struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1358	enum csc_color_mode config =
1359			CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC;
1360
1361	program_color_matrix(
1362			xfm_dce, tbl_entry, GRPH_COLOR_MATRIX_SW);
1363
1364	/*  We did everything ,now program DxOUTPUT_CSC_CONTROL */
1365	configure_graphics_mode(xfm_dce, config, GRAPHICS_CSC_ADJUST_TYPE_SW,
1366			tbl_entry->color_space);
1367}
1368
1369void dce110_opp_set_csc_default(
1370	struct transform *xfm,
1371	const struct default_adjustment *default_adjust)
1372{
1373	struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1374	enum csc_color_mode config =
1375			CSC_COLOR_MODE_GRAPHICS_PREDEFINED;
1376
1377	if (default_adjust->force_hw_default == false) {
1378		const struct out_csc_color_matrix *elm;
1379		/* currently parameter not in use */
1380		enum grph_color_adjust_option option =
1381			GRPH_COLOR_MATRIX_HW_DEFAULT;
1382		uint32_t i;
1383		/*
1384		 * HW default false we program locally defined matrix
1385		 * HW default true  we use predefined hw matrix and we
1386		 * do not need to program matrix
1387		 * OEM wants the HW default via runtime parameter.
1388		 */
1389		option = GRPH_COLOR_MATRIX_SW;
1390
1391		for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) {
1392			elm = &global_color_matrix[i];
1393			if (elm->color_space != default_adjust->out_color_space)
1394				continue;
1395			/* program the matrix with default values from this
1396			 * file */
1397			program_color_matrix(xfm_dce, elm, option);
1398			config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC;
1399			break;
1400		}
1401	}
1402
1403	/* configure the what we programmed :
1404	 * 1. Default values from this file
1405	 * 2. Use hardware default from ROM_A and we do not need to program
1406	 * matrix */
1407
1408	configure_graphics_mode(xfm_dce, config,
1409		default_adjust->csc_adjust_type,
1410		default_adjust->out_color_space);
1411}
1412
1413static void program_pwl(struct dce_transform *xfm_dce,
1414			const struct pwl_params *params)
1415{
1416	uint32_t retval;
1417	uint8_t max_tries = 10;
1418	uint8_t counter = 0;
1419	uint32_t i = 0;
1420	const struct pwl_result_data *rgb = params->rgb_resulted;
1421
1422	/* Power on LUT memory */
1423	if (REG(DCFE_MEM_PWR_CTRL))
1424		REG_UPDATE(DCFE_MEM_PWR_CTRL,
1425			   DCP_REGAMMA_MEM_PWR_DIS, 1);
1426	else
1427		REG_UPDATE(DCFE_MEM_LIGHT_SLEEP_CNTL,
1428			   REGAMMA_LUT_LIGHT_SLEEP_DIS, 1);
1429
1430	while (counter < max_tries) {
1431		if (REG(DCFE_MEM_PWR_STATUS)) {
1432			REG_GET(DCFE_MEM_PWR_STATUS,
1433				DCP_REGAMMA_MEM_PWR_STATE,
1434				&retval);
1435
1436			if (retval == 0)
1437				break;
1438			++counter;
1439		} else {
1440			REG_GET(DCFE_MEM_LIGHT_SLEEP_CNTL,
1441				REGAMMA_LUT_MEM_PWR_STATE,
1442				&retval);
1443
1444			if (retval == 0)
1445				break;
1446			++counter;
1447		}
1448	}
1449
1450	if (counter == max_tries) {
1451		DC_LOG_WARNING("%s: regamma lut was not powered on "
1452				"in a timely manner,"
1453				" programming still proceeds\n",
1454				__func__);
1455	}
1456
1457	REG_UPDATE(REGAMMA_LUT_WRITE_EN_MASK,
1458		   REGAMMA_LUT_WRITE_EN_MASK, 7);
1459
1460	REG_WRITE(REGAMMA_LUT_INDEX, 0);
1461
1462	/* Program REGAMMA_LUT_DATA */
1463	while (i != params->hw_points_num) {
1464
1465		REG_WRITE(REGAMMA_LUT_DATA, rgb->red_reg);
1466		REG_WRITE(REGAMMA_LUT_DATA, rgb->green_reg);
1467		REG_WRITE(REGAMMA_LUT_DATA, rgb->blue_reg);
1468		REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_red_reg);
1469		REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_green_reg);
1470		REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_blue_reg);
1471
1472		++rgb;
1473		++i;
1474	}
1475
1476	/*  we are done with DCP LUT memory; re-enable low power mode */
1477	if (REG(DCFE_MEM_PWR_CTRL))
1478		REG_UPDATE(DCFE_MEM_PWR_CTRL,
1479			   DCP_REGAMMA_MEM_PWR_DIS, 0);
1480	else
1481		REG_UPDATE(DCFE_MEM_LIGHT_SLEEP_CNTL,
1482			   REGAMMA_LUT_LIGHT_SLEEP_DIS, 0);
1483}
1484
1485static void regamma_config_regions_and_segments(struct dce_transform *xfm_dce,
1486						const struct pwl_params *params)
1487{
1488	const struct gamma_curve *curve;
1489
1490	REG_SET_2(REGAMMA_CNTLA_START_CNTL, 0,
1491		  REGAMMA_CNTLA_EXP_REGION_START, params->arr_points[0].custom_float_x,
1492		  REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, 0);
1493
1494	REG_SET(REGAMMA_CNTLA_SLOPE_CNTL, 0,
1495		REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, params->arr_points[0].custom_float_slope);
1496
1497	REG_SET(REGAMMA_CNTLA_END_CNTL1, 0,
1498		REGAMMA_CNTLA_EXP_REGION_END, params->arr_points[1].custom_float_x);
1499
1500	REG_SET_2(REGAMMA_CNTLA_END_CNTL2, 0,
1501		  REGAMMA_CNTLA_EXP_REGION_END_BASE, params->arr_points[1].custom_float_y,
1502		  REGAMMA_CNTLA_EXP_REGION_END_SLOPE, params->arr_points[1].custom_float_slope);
1503
1504	curve = params->arr_curve_points;
1505
1506	REG_SET_4(REGAMMA_CNTLA_REGION_0_1, 0,
1507		  REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
1508		  REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
1509		  REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
1510		  REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
1511	curve += 2;
1512
1513	REG_SET_4(REGAMMA_CNTLA_REGION_2_3, 0,
1514		  REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
1515		  REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
1516		  REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
1517		  REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
1518	curve += 2;
1519
1520	REG_SET_4(REGAMMA_CNTLA_REGION_4_5, 0,
1521		  REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
1522		  REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
1523		  REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
1524		  REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
1525	curve += 2;
1526
1527	REG_SET_4(REGAMMA_CNTLA_REGION_6_7, 0,
1528		  REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
1529		  REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
1530		  REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
1531		  REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
1532	curve += 2;
1533
1534	REG_SET_4(REGAMMA_CNTLA_REGION_8_9, 0,
1535		  REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
1536		  REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
1537		  REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
1538		  REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
1539	curve += 2;
1540
1541	REG_SET_4(REGAMMA_CNTLA_REGION_10_11, 0,
1542		  REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
1543		  REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
1544		  REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
1545		  REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
1546	curve += 2;
1547
1548	REG_SET_4(REGAMMA_CNTLA_REGION_12_13, 0,
1549		  REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
1550		  REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
1551		  REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
1552		  REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
1553	curve += 2;
1554
1555	REG_SET_4(REGAMMA_CNTLA_REGION_14_15, 0,
1556		  REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
1557		  REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
1558		  REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
1559		  REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
1560}
1561
1562
1563
1564void dce110_opp_program_regamma_pwl(struct transform *xfm,
1565				    const struct pwl_params *params)
1566{
1567	struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1568
1569	/* Setup regions */
1570	regamma_config_regions_and_segments(xfm_dce, params);
1571
1572	/* Program PWL */
1573	program_pwl(xfm_dce, params);
1574}
1575
1576void dce110_opp_power_on_regamma_lut(struct transform *xfm,
1577				     bool power_on)
1578{
1579	struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1580
1581	if (REG(DCFE_MEM_PWR_CTRL))
1582		REG_UPDATE_2(DCFE_MEM_PWR_CTRL,
1583			     DCP_REGAMMA_MEM_PWR_DIS, power_on,
1584			     DCP_LUT_MEM_PWR_DIS, power_on);
1585	else
1586		REG_UPDATE_2(DCFE_MEM_LIGHT_SLEEP_CNTL,
1587			    REGAMMA_LUT_LIGHT_SLEEP_DIS, power_on,
1588			    DCP_LUT_LIGHT_SLEEP_DIS, power_on);
1589
1590}
1591
1592void dce110_opp_set_regamma_mode(struct transform *xfm,
1593				 enum opp_regamma mode)
1594{
1595	struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1596
1597	REG_SET(REGAMMA_CONTROL, 0,
1598		GRPH_REGAMMA_MODE, mode);
1599}
1600
1601static const struct transform_funcs dce_transform_funcs = {
1602	.transform_reset = dce_transform_reset,
1603	.transform_set_scaler = dce_transform_set_scaler,
1604	.transform_set_gamut_remap = dce_transform_set_gamut_remap,
1605	.opp_set_csc_adjustment = dce110_opp_set_csc_adjustment,
1606	.opp_set_csc_default = dce110_opp_set_csc_default,
1607	.opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut,
1608	.opp_program_regamma_pwl = dce110_opp_program_regamma_pwl,
1609	.opp_set_regamma_mode = dce110_opp_set_regamma_mode,
1610	.transform_set_pixel_storage_depth = dce_transform_set_pixel_storage_depth,
1611	.transform_get_optimal_number_of_taps = dce_transform_get_optimal_number_of_taps
1612};
1613
1614#if defined(CONFIG_DRM_AMD_DC_SI)
1615static const struct transform_funcs dce60_transform_funcs = {
1616	.transform_reset = dce_transform_reset,
1617	.transform_set_scaler = dce60_transform_set_scaler,
1618	.transform_set_gamut_remap = dce_transform_set_gamut_remap,
1619	.opp_set_csc_adjustment = dce110_opp_set_csc_adjustment,
1620	.opp_set_csc_default = dce110_opp_set_csc_default,
1621	.opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut,
1622	.opp_program_regamma_pwl = dce110_opp_program_regamma_pwl,
1623	.opp_set_regamma_mode = dce110_opp_set_regamma_mode,
1624	.transform_set_pixel_storage_depth = dce60_transform_set_pixel_storage_depth,
1625	.transform_get_optimal_number_of_taps = dce_transform_get_optimal_number_of_taps
1626};
1627#endif
1628
1629/*****************************************/
1630/* Constructor, Destructor               */
1631/*****************************************/
1632
1633void dce_transform_construct(
1634	struct dce_transform *xfm_dce,
1635	struct dc_context *ctx,
1636	uint32_t inst,
1637	const struct dce_transform_registers *regs,
1638	const struct dce_transform_shift *xfm_shift,
1639	const struct dce_transform_mask *xfm_mask)
1640{
1641	xfm_dce->base.ctx = ctx;
1642
1643	xfm_dce->base.inst = inst;
1644	xfm_dce->base.funcs = &dce_transform_funcs;
1645
1646	xfm_dce->regs = regs;
1647	xfm_dce->xfm_shift = xfm_shift;
1648	xfm_dce->xfm_mask = xfm_mask;
1649
1650	xfm_dce->prescaler_on = true;
1651	xfm_dce->lb_pixel_depth_supported =
1652			LB_PIXEL_DEPTH_18BPP |
1653			LB_PIXEL_DEPTH_24BPP |
1654			LB_PIXEL_DEPTH_30BPP |
1655			LB_PIXEL_DEPTH_36BPP;
1656
1657	xfm_dce->lb_bits_per_entry = LB_BITS_PER_ENTRY;
1658	xfm_dce->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x6B0*/
1659}
1660
1661#if defined(CONFIG_DRM_AMD_DC_SI)
1662void dce60_transform_construct(
1663	struct dce_transform *xfm_dce,
1664	struct dc_context *ctx,
1665	uint32_t inst,
1666	const struct dce_transform_registers *regs,
1667	const struct dce_transform_shift *xfm_shift,
1668	const struct dce_transform_mask *xfm_mask)
1669{
1670	xfm_dce->base.ctx = ctx;
1671
1672	xfm_dce->base.inst = inst;
1673	xfm_dce->base.funcs = &dce60_transform_funcs;
1674
1675	xfm_dce->regs = regs;
1676	xfm_dce->xfm_shift = xfm_shift;
1677	xfm_dce->xfm_mask = xfm_mask;
1678
1679	xfm_dce->prescaler_on = true;
1680	xfm_dce->lb_pixel_depth_supported =
1681			LB_PIXEL_DEPTH_18BPP |
1682			LB_PIXEL_DEPTH_24BPP |
1683			LB_PIXEL_DEPTH_30BPP |
1684			LB_PIXEL_DEPTH_36BPP;
1685
1686	xfm_dce->lb_bits_per_entry = LB_BITS_PER_ENTRY;
1687	xfm_dce->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x6B0*/
1688}
1689#endif
~/ Read-only file preview.