brintos

brintos / linux-shallow public Read only

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