xref: /linux/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c (revision 0fc8f6200d2313278fbf4539bbab74677c685531)
1 // SPDX-License-Identifier: MIT
2 //
3 // Copyright 2026 Advanced Micro Devices, Inc.
4 
5 #include "dm_services.h"
6 #include "core_types.h"
7 #include "reg_helper.h"
8 #include "dcn42_dpp.h"
9 #include "dcn35/dcn35_dpp.h"
10 
11 #define REG(reg)\
12 	dpp->tf_regs->reg
13 
14 #define CTX \
15 	dpp->base.ctx
16 
17 #undef FN
18 #define FN(reg_name, field_name) \
19 	dpp->tf_shift->field_name, dpp->tf_mask->field_name
20 
21 static const uint32_t *get_hist_rgb_luma_coefs(enum dc_color_space color_space)
22 {
23 	// Coefs in s.6.12.
24 	// Y = 0.2126R + 0.7152G + 0.0722B
25 	static const uint32_t luma_transform_bt_709[] = {0x1cb36, 0x1e6e2, 0x1b27b};
26 	// Y = 0.2627R + 0.678G + 0.0593B
27 	static const uint32_t luma_transform_bt_2020[] = {0x1d0d0, 0x1e5b2, 0x1ae5c};
28 
29 	switch (color_space) {
30 	case COLOR_SPACE_2020_RGB_FULLRANGE:
31 	case COLOR_SPACE_2020_RGB_LIMITEDRANGE:
32 		return luma_transform_bt_2020;
33 	default:
34 		return luma_transform_bt_709;
35 	}
36 }
37 
38 static void dpp42_dpp_cm_hist_control(
39 	struct dpp *dpp_base,
40 	struct cm_hist_control cntl,
41 	enum dc_color_space color_space)
42 {
43 	struct dcn42_dpp *dpp = TO_DCN42_DPP(dpp_base);
44 
45 	REG_UPDATE_10(
46 		CM_HIST_CNTL,
47 		CM_HIST_SEL, cntl.tap_point,
48 		CM_HIST_CH_EN, cntl.channels_enabled,
49 		CM_HIST_SRC1_SEL, cntl.src_1_select,
50 		CM_HIST_SRC2_SEL, cntl.src_2_select,
51 		CM_HIST_SRC3_SEL, cntl.src_3_select,
52 		CM_HIST_CH1_XBAR, cntl.ch1_src,
53 		CM_HIST_CH2_XBAR, cntl.ch2_src,
54 		CM_HIST_CH3_XBAR, cntl.ch3_src,
55 		CM_HIST_FORMAT, cntl.format,
56 		CM_HIST_READ_CHANNEL_MASK, cntl.read_channel_mask);
57 
58 	if (cntl.src_2_select == CM_HIST_SRC2_MODE_RGB_TO_Y) {
59 		const uint32_t *luma_transform = get_hist_rgb_luma_coefs(color_space);
60 
61 		REG_UPDATE(CM_HIST_COEFA_SRC2, CM_HIST_COEFA_SRC2, luma_transform[0]);
62 		REG_UPDATE(CM_HIST_COEFB_SRC2, CM_HIST_COEFB_SRC2, luma_transform[1]);
63 		REG_UPDATE(CM_HIST_COEFC_SRC2, CM_HIST_COEFC_SRC2, luma_transform[2]);
64 	} else {
65 		REG_UPDATE(CM_HIST_COEFA_SRC2, CM_HIST_COEFA_SRC2, 0);
66 		REG_UPDATE(CM_HIST_COEFB_SRC2, CM_HIST_COEFB_SRC2, 0x1f000); // 1 in s.6.12
67 		REG_UPDATE(CM_HIST_COEFC_SRC2, CM_HIST_COEFC_SRC2, 0);
68 	}
69 }
70 
71 static bool dpp42_dpp_cm_hist_read(struct dpp *dpp_base, struct cm_hist *hist_out)
72 {
73 	struct dcn42_dpp *dpp = TO_DCN42_DPP(dpp_base);
74 	uint32_t channel_mask = 0;
75 	uint32_t rdy_status = 0, rdy_status_a = 0, rdy_status_b = 0;
76 	bool ch1, ch2, ch3;
77 
78 	if (hist_out == NULL)
79 		return false;
80 
81 
82 	REG_GET(CM_HIST_CNTL, CM_HIST_READ_CHANNEL_MASK, &channel_mask);
83 	ch1 = (channel_mask & 1) > 0;
84 	ch2 = (channel_mask & 2) > 0;
85 	ch3 = (channel_mask & 4) > 0;
86 
87 	REG_GET(CM_HIST_STATUS, CM_HIST_BUFA_RDY_STATUS, &rdy_status_a);
88 	REG_GET(CM_HIST_STATUS, CM_HIST_BUFB_RDY_STATUS, &rdy_status_b);
89 
90 	rdy_status = rdy_status_a || rdy_status_b;
91 
92 	if (rdy_status) {
93 		REG_UPDATE(CM_HIST_LOCK, CM_HIST_LOCK, 1);
94 		REG_UPDATE(CM_HIST_INDEX, CM_HIST_INDEX, 0);
95 		for (int i = 0; i < 256; i++) {
96 			uint32_t temp;
97 
98 			if (ch1) {
99 				REG_GET(CM_HIST_DATA, CM_HIST_DATA, &temp);
100 				hist_out->ch1[i] += temp;
101 			}
102 			if (ch2) {
103 				REG_GET(CM_HIST_DATA, CM_HIST_DATA, &temp);
104 				hist_out->ch2[i] += temp;
105 			}
106 			if (ch3) {
107 				REG_GET(CM_HIST_DATA, CM_HIST_DATA, &temp);
108 				hist_out->ch3[i] += temp;
109 			}
110 		}
111 		REG_UPDATE(CM_HIST_LOCK, CM_HIST_LOCK, 0);
112 		return true;
113 	} else {
114 		return false;
115 	}
116 }
117 
118 static void dpp42_dpp_setup(
119 	struct dpp *dpp_base,
120 	enum surface_pixel_format format,
121 	enum expansion_mode mode,
122 	struct dc_csc_transform input_csc_color_matrix,
123 	enum dc_color_space input_color_space,
124 	struct cnv_alpha_2bit_lut *alpha_2bit_lut)
125 {
126 	struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base);
127 	uint32_t pixel_format = 0;
128 	uint32_t alpha_en = 1;
129 	enum dc_color_space color_space = COLOR_SPACE_SRGB;
130 	enum dcn10_input_csc_select select = INPUT_CSC_SELECT_BYPASS;
131 	uint32_t is_2bit = 0;
132 	uint32_t alpha_plane_enable = 0;
133 	uint32_t dealpha_en = 0, dealpha_ablnd_en = 0;
134 	uint32_t realpha_en = 0, realpha_ablnd_en = 0;
135 	struct out_csc_color_matrix tbl_entry;
136 	int i;
137 
138 	REG_SET_2(FORMAT_CONTROL, 0,
139 		CNVC_BYPASS, 0,
140 		FORMAT_EXPANSION_MODE, mode);
141 
142 	REG_UPDATE(FORMAT_CONTROL, FORMAT_CNV16, 0);
143 	REG_UPDATE(FORMAT_CONTROL, CNVC_BYPASS_MSB_ALIGN, 0);
144 	REG_UPDATE(FORMAT_CONTROL, CLAMP_POSITIVE, 0);
145 	REG_UPDATE(FORMAT_CONTROL, CLAMP_POSITIVE_C, 0);
146 
147 	REG_UPDATE(FORMAT_CONTROL, FORMAT_CROSSBAR_R, 0);
148 	REG_UPDATE(FORMAT_CONTROL, FORMAT_CROSSBAR_G, 1);
149 	REG_UPDATE(FORMAT_CONTROL, FORMAT_CROSSBAR_B, 2);
150 
151 	switch (format) {
152 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
153 		pixel_format = 1;
154 		break;
155 	case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
156 		pixel_format = 3;
157 		alpha_en = 0;
158 		break;
159 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
160 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
161 		pixel_format = 8;
162 		break;
163 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
164 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
165 		pixel_format = 10;
166 		is_2bit = 1;
167 		break;
168 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
169 		pixel_format = 65;
170 		color_space = COLOR_SPACE_YCBCR709;
171 		select = INPUT_CSC_SELECT_ICSC;
172 		break;
173 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
174 		pixel_format = 64;
175 		color_space = COLOR_SPACE_YCBCR709;
176 		select = INPUT_CSC_SELECT_ICSC;
177 		break;
178 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
179 		pixel_format = 67;
180 		color_space = COLOR_SPACE_YCBCR709;
181 		select = INPUT_CSC_SELECT_ICSC;
182 		break;
183 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
184 		pixel_format = 66;
185 		color_space = COLOR_SPACE_YCBCR709;
186 		select = INPUT_CSC_SELECT_ICSC;
187 		break;
188 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
189 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616:
190 		pixel_format = 26; /* ARGB16161616_UNORM */
191 		break;
192 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
193 		pixel_format = 24;
194 		break;
195 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
196 		pixel_format = 25;
197 		break;
198 	case SURFACE_PIXEL_FORMAT_VIDEO_AYCrCb8888:
199 		pixel_format = 12;
200 		color_space = COLOR_SPACE_YCBCR709;
201 		select = INPUT_CSC_SELECT_ICSC;
202 		break;
203 	case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FIX:
204 		pixel_format = 112;
205 		alpha_en = 0;
206 		break;
207 	case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FIX:
208 		pixel_format = 113;
209 		alpha_en = 0;
210 		break;
211 	case SURFACE_PIXEL_FORMAT_VIDEO_ACrYCb2101010:
212 		pixel_format = 114;
213 		color_space = COLOR_SPACE_YCBCR709;
214 		select = INPUT_CSC_SELECT_ICSC;
215 		is_2bit = 1;
216 		break;
217 	case SURFACE_PIXEL_FORMAT_VIDEO_CrYCbA1010102:
218 		pixel_format = 115;
219 		color_space = COLOR_SPACE_YCBCR709;
220 		select = INPUT_CSC_SELECT_ICSC;
221 		is_2bit = 1;
222 		break;
223 	case SURFACE_PIXEL_FORMAT_GRPH_RGBE:
224 		pixel_format = 116;
225 		alpha_plane_enable = 0;
226 		break;
227 	case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA:
228 		pixel_format = 116;
229 		alpha_plane_enable = 1;
230 		break;
231 	case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FLOAT:
232 		pixel_format = 118;
233 		alpha_en = 0;
234 		break;
235 	case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FLOAT:
236 		pixel_format = 119;
237 		alpha_en = 0;
238 		break;
239 	default:
240 		break;
241 	}
242 
243 	/* Set default color space based on format if none is given. */
244 	color_space = input_color_space ? input_color_space : color_space;
245 
246 	if (is_2bit == 1 && alpha_2bit_lut != NULL) {
247 		REG_UPDATE(ALPHA_2BIT_LUT01, ALPHA_2BIT_LUT0, alpha_2bit_lut->lut0);
248 		REG_UPDATE(ALPHA_2BIT_LUT01, ALPHA_2BIT_LUT1, alpha_2bit_lut->lut1);
249 		REG_UPDATE(ALPHA_2BIT_LUT23, ALPHA_2BIT_LUT2, alpha_2bit_lut->lut2);
250 		REG_UPDATE(ALPHA_2BIT_LUT23, ALPHA_2BIT_LUT3, alpha_2bit_lut->lut3);
251 	}
252 
253 	REG_SET_2(CNVC_SURFACE_PIXEL_FORMAT, 0,
254 		CNVC_SURFACE_PIXEL_FORMAT, pixel_format,
255 		CNVC_ALPHA_PLANE_ENABLE, alpha_plane_enable);
256 	REG_UPDATE(FORMAT_CONTROL, FORMAT_CONTROL__ALPHA_EN, alpha_en);
257 
258 	REG_SET_2(PRE_DEALPHA, 0,
259 		PRE_DEALPHA_EN, dealpha_en,
260 		PRE_DEALPHA_ABLND_EN, dealpha_ablnd_en);
261 	REG_SET_2(PRE_REALPHA, 0,
262 		PRE_REALPHA_EN, realpha_en,
263 		PRE_REALPHA_ABLND_EN, realpha_ablnd_en);
264 
265 	/* If input adjustment exists, program the ICSC with those values. */
266 	if (input_csc_color_matrix.enable_adjustment == true) {
267 		for (i = 0; i < 12; i++)
268 			tbl_entry.regval[i] = input_csc_color_matrix.matrix[i];
269 
270 		tbl_entry.color_space = input_color_space;
271 
272 		if (color_space >= COLOR_SPACE_YCBCR601)
273 			select = INPUT_CSC_SELECT_ICSC;
274 		else
275 			select = INPUT_CSC_SELECT_BYPASS;
276 
277 		dpp3_program_post_csc(dpp_base, color_space, select,
278 			&tbl_entry);
279 	} else {
280 		dpp3_program_post_csc(dpp_base, color_space, select, NULL);
281 	}
282 }
283 
284 static struct dpp_funcs dcn42_dpp_funcs = {
285 	.dpp_program_gamcor_lut		= dpp3_program_gamcor_lut,
286 	.dpp_read_state				= dpp401_read_state,
287 	.dpp_reset					= dpp_reset,
288 	.dpp_set_scaler				= dpp401_dscl_set_scaler_manual_scale,
289 	.dpp_get_optimal_number_of_taps	= dpp3_get_optimal_number_of_taps,
290 	.dpp_set_pre_degam			= dpp3_set_pre_degam,
291 	.dpp_setup					= dpp42_dpp_setup,
292 	.dpp_program_cm_dealpha		= dpp3_program_cm_dealpha,
293 	.dpp_program_cm_bias		= dpp3_program_cm_bias,
294 	.dpp_program_bias_and_scale	= dpp35_program_bias_and_scale_fcnv,
295 	.dpp_cnv_set_alpha_keyer	= dpp2_cnv_set_alpha_keyer,
296 	.set_cursor_attributes		= dpp401_set_cursor_attributes,
297 	.set_cursor_position		= dpp401_set_cursor_position,
298 	.set_optional_cursor_attributes	= dpp401_set_optional_cursor_attributes,
299 	.dpp_dppclk_control			= dpp35_dppclk_control,
300 	.dpp_set_hdr_multiplier		= dpp3_set_hdr_multiplier,
301 	.set_cursor_matrix			= dpp401_set_cursor_matrix,
302 	.dpp_cm_hist_control        = dpp42_dpp_cm_hist_control,
303 	.dpp_cm_hist_read           = dpp42_dpp_cm_hist_read,
304 	.dpp_read_reg_state			= dpp30_read_reg_state,
305 };
306 
307 
308 static struct dpp_caps dcn42_dpp_cap = {
309 	.dscl_data_proc_format = DSCL_DATA_PRCESSING_FLOAT_FORMAT,
310 	.max_lb_partitions = 63,
311 	.dscl_calc_lb_num_partitions = dscl401_calc_lb_num_partitions,
312 };
313 
314 bool dpp42_construct(
315 	struct dcn42_dpp *dpp,
316 	struct dc_context *ctx,
317 	uint32_t inst,
318 	const struct dcn42_dpp_registers *tf_regs,
319 	const struct dcn42_dpp_shift *tf_shift,
320 	const struct dcn42_dpp_mask *tf_mask)
321 {
322 	dpp->base.ctx = ctx;
323 
324 	dpp->base.inst = inst;
325 	dpp->base.funcs = &dcn42_dpp_funcs;
326 	dpp->base.caps = &dcn42_dpp_cap;
327 
328 	dpp->tf_regs = tf_regs;
329 	dpp->tf_shift = tf_shift;
330 	dpp->tf_mask = tf_mask;
331 
332 	return true;
333 }
334