xref: /linux/drivers/gpu/drm/amd/display/dc/dpp/dcn50/dcn50_dpp.c (revision 67f8bc848ee31831336bd478e57d2f993551902e)
1 // SPDX-License-Identifier: MIT
2 //
3 // Copyright (c) 2026 Advanced Micro Devices, Inc. All rights reserved.
4 
5 #include "dm_services.h"
6 #include "core_types.h"
7 #include "reg_helper.h"
8 #include "dcn401/dcn401_dpp.h"
9 #include "dcn50_dpp.h"
10 #include "basics/conversion.h"
11 #include "dcn30/dcn30_cm_common.h"
12 #include "dcn32/dcn32_dpp.h"
13 #include "dcn35/dcn35_dpp.h"
14 
15 #define REG(reg)\
16 	dpp->tf_regs->reg
17 
18 #define CTX \
19 	dpp->base.ctx
20 
21 #undef FN
22 #define FN(reg_name, field_name) \
23 	dpp->tf_shift->field_name, dpp->tf_mask->field_name
24 
25 void dpp50_set_pregam_state(
26 	struct dpp *dpp_base,
27 	enum dc_transfer_func_predefined tr,
28 	enum dc_scaling_linearity scaling)
29 {
30 	struct dcn50_dpp *dpp = TO_DCN50_DPP(dpp_base);
31 	enum pregam_mode pre_degam_en = PREGAM_DEGAM;
32 	enum degam_lut degamma_lut_selection = 0;
33 
34 	if (scaling == DC_SCALING_LINEARITY_SOURCE) {
35 		//If scaling in non-linear, apply regamma
36 		REG_SET_2(PRE_GAM, 0,
37 			PRE_GAM_MODE, PREGAM_REGAM,
38 			PRE_REGAM_SELECT, REGAM_20);
39 	} else {
40 		//If scaling in linear, apply degamma based on TF
41 		switch (tr) {
42 		case TRANSFER_FUNCTION_SRGB:
43 			degamma_lut_selection = DEGAM_SRGB;
44 			break;
45 		case TRANSFER_FUNCTION_GAMMA22:
46 			degamma_lut_selection = DEGAM_GAMMA_22;
47 			break;
48 		case TRANSFER_FUNCTION_GAMMA24:
49 			degamma_lut_selection = DEGAM_GAMMA_24;
50 			break;
51 		case TRANSFER_FUNCTION_GAMMA26:
52 			degamma_lut_selection = DEGAM_GAMMA_26;
53 			break;
54 		case TRANSFER_FUNCTION_BT709:
55 			degamma_lut_selection = DEGAM_BT2020;
56 			break;
57 		case TRANSFER_FUNCTION_PQ:
58 			degamma_lut_selection = DEGAM_BT2100PQ;
59 			break;
60 		case TRANSFER_FUNCTION_HLG:
61 			degamma_lut_selection = DEGAM_BT2100HLG;
62 			break;
63 		case TRANSFER_FUNCTION_LINEAR:
64 		case TRANSFER_FUNCTION_UNITY:
65 		case TRANSFER_FUNCTION_HLG12:
66 		default:
67 			pre_degam_en = PREGAM_BYPASS;
68 			break;
69 		}
70 
71 		REG_SET_2(PRE_GAM, 0,
72 			PRE_GAM_MODE, pre_degam_en,
73 			PRE_DEGAM_SELECT, degamma_lut_selection);
74 	}
75 }
76 
77 void dpp50_dpp_setup(
78 	struct dpp *dpp_base,
79 	enum surface_pixel_format format,
80 	enum expansion_mode mode,
81 	struct dc_csc_transform input_csc_color_matrix,
82 	enum dc_color_space input_color_space,
83 	struct cnv_alpha_2bit_lut *alpha_2bit_lut)
84 {
85 	struct dcn50_dpp *dpp = TO_DCN50_DPP(dpp_base);
86 	uint32_t pixel_format = 0;
87 	uint32_t alpha_en = 1;
88 	enum dc_color_space color_space = COLOR_SPACE_SRGB;
89 	enum dcn10_input_csc_select select = INPUT_CSC_SELECT_BYPASS;
90 	uint32_t is_2bit = 0;
91 	uint32_t alpha_plane_enable = 0;
92 	uint32_t dealpha_en = 0, dealpha_ablnd_en = 0;
93 	uint32_t realpha_en = 0, realpha_ablnd_en = 0;
94 	struct out_csc_color_matrix tbl_entry;
95 	int i;
96 
97 	REG_SET_2(FORMAT_CONTROL, 0,
98 		CNVC_BYPASS, 0,
99 		FORMAT_EXPANSION_MODE, mode);
100 
101 	REG_UPDATE(FORMAT_CONTROL, FORMAT_CNV16, 0);
102 	REG_UPDATE(FORMAT_CONTROL, CNVC_BYPASS_MSB_ALIGN, 0);
103 	REG_UPDATE(FORMAT_CONTROL, CLAMP_POSITIVE, 0);
104 	REG_UPDATE(FORMAT_CONTROL, CLAMP_POSITIVE_C, 0);
105 
106 	REG_UPDATE(FORMAT_CONTROL, FORMAT_CROSSBAR_R, 0);
107 	REG_UPDATE(FORMAT_CONTROL, FORMAT_CROSSBAR_G, 1);
108 	REG_UPDATE(FORMAT_CONTROL, FORMAT_CROSSBAR_B, 2);
109 
110 	switch (format) {
111 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
112 		pixel_format = 1;
113 		break;
114 	case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
115 		pixel_format = 3;
116 		alpha_en = 0;
117 		break;
118 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
119 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
120 		pixel_format = 8;
121 		break;
122 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
123 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
124 		pixel_format = 10;
125 		is_2bit = 1;
126 		break;
127 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
128 	case SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P208:
129 		pixel_format = 64;
130 		color_space = COLOR_SPACE_YCBCR709;
131 		select = INPUT_CSC_SELECT_ICSC;
132 		break;
133 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
134 	case SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P208:
135 		pixel_format = 65;
136 		color_space = COLOR_SPACE_YCBCR709;
137 		select = INPUT_CSC_SELECT_ICSC;
138 		break;
139 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
140 	case SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P210:
141 		pixel_format = 66;
142 		color_space = COLOR_SPACE_YCBCR709;
143 		select = INPUT_CSC_SELECT_ICSC;
144 		break;
145 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
146 	case SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P210:
147 		pixel_format = 67;
148 		color_space = COLOR_SPACE_YCBCR709;
149 		select = INPUT_CSC_SELECT_ICSC;
150 		break;
151 	case SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P212:
152 		pixel_format = 68;
153 		color_space = COLOR_SPACE_YCBCR709;
154 		select = INPUT_CSC_SELECT_ICSC;
155 		break;
156 	case SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P212:
157 		pixel_format = 69;
158 		color_space = COLOR_SPACE_YCBCR709;
159 		select = INPUT_CSC_SELECT_ICSC;
160 		break;
161 	/* Packed 422 formats*/
162 	case SURFACE_PIXEL_FORMAT_VIDEO_422_YCrYCb:
163 		pixel_format = 72;
164 		color_space = COLOR_SPACE_YCBCR709;
165 		select = INPUT_CSC_SELECT_ICSC;
166 		// color space and select subjected to change
167 		break;
168 	case SURFACE_PIXEL_FORMAT_VIDEO_422_YCbYCr:
169 		pixel_format = 73;
170 		color_space = COLOR_SPACE_YCBCR709;
171 		select = INPUT_CSC_SELECT_ICSC;
172 		// color space and select subjected to change
173 		break;
174 	case SURFACE_PIXEL_FORMAT_VIDEO_422_CrYCbY:
175 		pixel_format = 74;
176 		color_space = COLOR_SPACE_YCBCR709;
177 		select = INPUT_CSC_SELECT_ICSC;
178 		// color space and select subjected to change
179 		break;
180 	case SURFACE_PIXEL_FORMAT_VIDEO_422_CbYCrY:
181 		pixel_format = 75;
182 		color_space = COLOR_SPACE_YCBCR709;
183 		select = INPUT_CSC_SELECT_ICSC;
184 		// color space and select subjected to change
185 		break;
186 	case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_YCrYCb:
187 		pixel_format = 76;
188 		color_space = COLOR_SPACE_YCBCR709;
189 		select = INPUT_CSC_SELECT_ICSC;
190 		// color space and select subjected to change
191 		break;
192 	case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_YCbYCr:
193 		pixel_format = 77;
194 		color_space = COLOR_SPACE_YCBCR709;
195 		select = INPUT_CSC_SELECT_ICSC;
196 		// color space and select subjected to change
197 		break;
198 	case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_CrYCbY:
199 		pixel_format = 78;
200 		color_space = COLOR_SPACE_YCBCR709;
201 		select = INPUT_CSC_SELECT_ICSC;
202 		// color space and select subjected to change
203 		break;
204 	case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_CbYCrY:
205 		pixel_format = 79;
206 		color_space = COLOR_SPACE_YCBCR709;
207 		select = INPUT_CSC_SELECT_ICSC;
208 		// color space and select subjected to change
209 		break;
210 	case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_YCrYCb:
211 		pixel_format = 80;
212 		color_space = COLOR_SPACE_YCBCR709;
213 		select = INPUT_CSC_SELECT_ICSC;
214 		// color space and select subjected to change
215 		break;
216 	case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_YCbYCr:
217 		pixel_format = 81;
218 		color_space = COLOR_SPACE_YCBCR709;
219 		select = INPUT_CSC_SELECT_ICSC;
220 		// color space and select subjected to change
221 		break;
222 	case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_CrYCbY:
223 		pixel_format = 82;
224 		color_space = COLOR_SPACE_YCBCR709;
225 		select = INPUT_CSC_SELECT_ICSC;
226 		// color space and select subjected to change
227 		break;
228 	case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_CbYCrY:
229 		pixel_format = 83;
230 		color_space = COLOR_SPACE_YCBCR709;
231 		select = INPUT_CSC_SELECT_ICSC;
232 		// color space and select subjected to change
233 		break;
234 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
235 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616:
236 		pixel_format = 26; /* ARGB16161616_UNORM */
237 		break;
238 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
239 		pixel_format = 24;
240 		break;
241 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
242 		pixel_format = 25;
243 		break;
244 	case SURFACE_PIXEL_FORMAT_VIDEO_AYCrCb8888:
245 		pixel_format = 12;
246 		color_space = COLOR_SPACE_YCBCR709;
247 		select = INPUT_CSC_SELECT_ICSC;
248 		break;
249 	case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FIX:
250 		pixel_format = 112;
251 		alpha_en = 0;
252 		break;
253 	case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FIX:
254 		pixel_format = 113;
255 		alpha_en = 0;
256 		break;
257 	case SURFACE_PIXEL_FORMAT_VIDEO_ACrYCb2101010:
258 		pixel_format = 114;
259 		color_space = COLOR_SPACE_YCBCR709;
260 		select = INPUT_CSC_SELECT_ICSC;
261 		is_2bit = 1;
262 		break;
263 	case SURFACE_PIXEL_FORMAT_VIDEO_CrYCbA1010102:
264 		pixel_format = 115;
265 		color_space = COLOR_SPACE_YCBCR709;
266 		select = INPUT_CSC_SELECT_ICSC;
267 		is_2bit = 1;
268 		break;
269 	case SURFACE_PIXEL_FORMAT_GRPH_RGBE:
270 		pixel_format = 116;
271 		alpha_plane_enable = 0;
272 		break;
273 	case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA:
274 		pixel_format = 116;
275 		alpha_plane_enable = 1;
276 		break;
277 	case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FLOAT:
278 		pixel_format = 118;
279 		alpha_en = 0;
280 		break;
281 	case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FLOAT:
282 		pixel_format = 119;
283 		alpha_en = 0;
284 		break;
285 	default:
286 		break;
287 	}
288 
289 	/* Set default color space based on format if none is given. */
290 	color_space = input_color_space ? input_color_space : color_space;
291 
292 	if (is_2bit == 1 && alpha_2bit_lut != NULL) {
293 		REG_UPDATE(ALPHA_2BIT_LUT, ALPHA_2BIT_LUT0, alpha_2bit_lut->lut0);
294 		REG_UPDATE(ALPHA_2BIT_LUT, ALPHA_2BIT_LUT1, alpha_2bit_lut->lut1);
295 		REG_UPDATE(ALPHA_2BIT_LUT, ALPHA_2BIT_LUT2, alpha_2bit_lut->lut2);
296 		REG_UPDATE(ALPHA_2BIT_LUT, ALPHA_2BIT_LUT3, alpha_2bit_lut->lut3);
297 	}
298 
299 	REG_SET_2(CNVC_SURFACE_PIXEL_FORMAT, 0,
300 		CNVC_SURFACE_PIXEL_FORMAT, pixel_format,
301 		CNVC_ALPHA_PLANE_ENABLE, alpha_plane_enable);
302 	REG_UPDATE(FORMAT_CONTROL, FORMAT_CONTROL__ALPHA_EN, alpha_en);
303 
304 	REG_SET_2(PRE_DEALPHA, 0,
305 		PRE_DEALPHA_EN, dealpha_en,
306 		PRE_DEALPHA_ABLND_EN, dealpha_ablnd_en);
307 	REG_SET_2(PRE_REALPHA, 0,
308 		PRE_REALPHA_EN, realpha_en,
309 		PRE_REALPHA_ABLND_EN, realpha_ablnd_en);
310 
311 	/* If input adjustment exists, program the ICSC with those values. */
312 	if (input_csc_color_matrix.enable_adjustment == true) {
313 		for (i = 0; i < 12; i++)
314 			tbl_entry.regval[i] = input_csc_color_matrix.matrix[i];
315 
316 		tbl_entry.color_space = input_color_space;
317 
318 		if (dpp3_should_bypass_post_csc_for_colorspace(color_space))
319 			select = INPUT_CSC_SELECT_BYPASS;
320 		else
321 			select = INPUT_CSC_SELECT_ICSC;
322 
323 		dpp3_program_post_csc(dpp_base, color_space, select,
324 			&tbl_entry);
325 	} else {
326 		dpp3_program_post_csc(dpp_base, color_space, select, NULL);
327 	}
328 }
329 
330 static struct dpp_funcs dcn50_dpp_funcs = {
331 	.dpp_program_gamcor_lut		= dpp3_program_gamcor_lut,
332 	.dpp_read_state				= dpp401_read_state,
333 	.dpp_reset					= dpp_reset,
334 	.dpp_set_scaler				= dpp401_dscl_set_scaler_manual_scale,
335 	.dpp_get_optimal_number_of_taps	= dpp3_get_optimal_number_of_taps,
336 	.dpp_set_gamut_remap		= NULL,
337 	.dpp_set_csc_adjustment		= NULL,
338 	.dpp_set_csc_default		= NULL,
339 	.dpp_program_regamma_pwl	= NULL,
340 	.dpp_set_pre_degam			= NULL,
341 	.dpp_program_input_lut		= NULL,
342 	.dpp_full_bypass			= NULL,
343 	.dpp_setup					= dpp50_dpp_setup,
344 	.dpp_program_degamma_pwl	= NULL,
345 	.dpp_program_cm_dealpha		= dpp3_program_cm_dealpha,
346 	.dpp_program_cm_bias		= dpp3_program_cm_bias,
347 
348 	.dpp_program_blnd_lut		= NULL, // BLNDGAM is removed completely in DCN3.2 DPP
349 	.dpp_program_shaper_lut		= NULL, // CM SHAPER block is removed in DCN3.2 DPP,
350 									//(it is in MPCC, programmable before or after BLND)
351 	.dpp_program_3dlut			= NULL, // CM 3DLUT block is removed in DCN3.2 DPP,
352 									//(it is in MPCC, programmable before or after BLND)
353 
354 	.dpp_program_bias_and_scale	= dpp35_program_bias_and_scale_fcnv,
355 	.dpp_cnv_set_alpha_keyer	= dpp2_cnv_set_alpha_keyer,
356 	.set_cursor_attributes		= dpp401_set_cursor_attributes,
357 	.set_cursor_position		= dpp401_set_cursor_position,
358 	.set_optional_cursor_attributes	= dpp401_set_optional_cursor_attributes,
359 	.dpp_dppclk_control			= dpp1_dppclk_control,
360 	.dpp_set_hdr_multiplier		= dpp3_set_hdr_multiplier,
361 	.dpp_read_reg_state			= dpp30_read_reg_state,
362 	.set_cursor_matrix			= dpp401_set_cursor_matrix,
363 	.dpp_set_pregam_state		= dpp50_set_pregam_state,
364 };
365 
366 static struct dpp_caps dcn50_dpp_cap = {
367 	.dscl_data_proc_format = DSCL_DATA_PRCESSING_FLOAT_FORMAT,
368 	.max_lb_partitions = 63,
369 	.dscl_calc_lb_num_partitions = dscl401_calc_lb_num_partitions,
370 };
371 
372 bool dpp50_construct(
373 	struct dcn50_dpp *dpp,
374 	struct dc_context *ctx,
375 	uint32_t inst,
376 	const struct dcn50_dpp_registers *tf_regs,
377 	const struct dcn50_dpp_shift *tf_shift,
378 	const struct dcn50_dpp_mask *tf_mask)
379 {
380 	dpp->base.ctx = ctx;
381 
382 	dpp->base.inst = inst;
383 	dpp->base.funcs = &dcn50_dpp_funcs;
384 	dpp->base.caps = &dcn50_dpp_cap;
385 
386 	dpp->tf_regs = tf_regs;
387 	dpp->tf_shift = tf_shift;
388 	dpp->tf_mask = tf_mask;
389 
390 	return true;
391 }
392