xref: /netbsd-src/sys/external/bsd/drm2/dist/drm/amd/display/dc/dcn20/amdgpu_dcn20_opp.c (revision 41ec02673d281bbb3d38e6c78504ce6e30c228c1)
1 /*	$NetBSD: amdgpu_dcn20_opp.c,v 1.2 2021/12/18 23:45:03 riastradh Exp $	*/
2 
3 /*
4  * Copyright 2012-15 Advanced Micro Devices, Inc.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22  * OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * Authors: AMD
25  *
26  */
27 
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: amdgpu_dcn20_opp.c,v 1.2 2021/12/18 23:45:03 riastradh Exp $");
30 
31 #include "dm_services.h"
32 #include "dcn20_opp.h"
33 #include "reg_helper.h"
34 
35 #define REG(reg) \
36 	(oppn20->regs->reg)
37 
38 #undef FN
39 #define FN(reg_name, field_name) \
40 	oppn20->opp_shift->field_name, oppn20->opp_mask->field_name
41 
42 #define CTX \
43 	oppn20->base.ctx
44 
45 
opp2_set_disp_pattern_generator(struct output_pixel_processor * opp,enum controller_dp_test_pattern test_pattern,enum controller_dp_color_space color_space,enum dc_color_depth color_depth,const struct tg_color * solid_color,int width,int height)46 void opp2_set_disp_pattern_generator(
47 		struct output_pixel_processor *opp,
48 		enum controller_dp_test_pattern test_pattern,
49 		enum controller_dp_color_space color_space,
50 		enum dc_color_depth color_depth,
51 		const struct tg_color *solid_color,
52 		int width,
53 		int height)
54 {
55 	struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp);
56 	enum test_pattern_color_format bit_depth;
57 	enum test_pattern_dyn_range dyn_range;
58 	enum test_pattern_mode mode;
59 
60 	/* color ramp generator mixes 16-bits color */
61 	uint32_t src_bpc = 16;
62 	/* requested bpc */
63 	uint32_t dst_bpc;
64 	uint32_t index;
65 	/* RGB values of the color bars.
66 	 * Produce two RGB colors: RGB0 - white (all Fs)
67 	 * and RGB1 - black (all 0s)
68 	 * (three RGB components for two colors)
69 	 */
70 	uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000,
71 						0x0000, 0x0000};
72 	/* dest color (converted to the specified color format) */
73 	uint16_t dst_color[6];
74 	uint32_t inc_base;
75 
76 	/* translate to bit depth */
77 	switch (color_depth) {
78 	case COLOR_DEPTH_666:
79 		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6;
80 	break;
81 	case COLOR_DEPTH_888:
82 		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
83 	break;
84 	case COLOR_DEPTH_101010:
85 		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10;
86 	break;
87 	case COLOR_DEPTH_121212:
88 		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12;
89 	break;
90 	default:
91 		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
92 	break;
93 	}
94 
95 	/* set DPG dimentions */
96 	REG_SET_2(DPG_DIMENSIONS, 0,
97 		DPG_ACTIVE_WIDTH, width,
98 		DPG_ACTIVE_HEIGHT, height);
99 
100 	switch (test_pattern) {
101 	case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES:
102 	case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA:
103 	{
104 		dyn_range = (test_pattern ==
105 				CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ?
106 				TEST_PATTERN_DYN_RANGE_CEA :
107 				TEST_PATTERN_DYN_RANGE_VESA);
108 
109 		switch (color_space) {
110 		case CONTROLLER_DP_COLOR_SPACE_YCBCR601:
111 			mode = TEST_PATTERN_MODE_COLORSQUARES_YCBCR601;
112 		break;
113 		case CONTROLLER_DP_COLOR_SPACE_YCBCR709:
114 			mode = TEST_PATTERN_MODE_COLORSQUARES_YCBCR709;
115 		break;
116 		case CONTROLLER_DP_COLOR_SPACE_RGB:
117 		default:
118 			mode = TEST_PATTERN_MODE_COLORSQUARES_RGB;
119 		break;
120 		}
121 
122 		REG_UPDATE_6(DPG_CONTROL,
123 			DPG_EN, 1,
124 			DPG_MODE, mode,
125 			DPG_DYNAMIC_RANGE, dyn_range,
126 			DPG_BIT_DEPTH, bit_depth,
127 			DPG_VRES, 6,
128 			DPG_HRES, 6);
129 	}
130 	break;
131 
132 	case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS:
133 	case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS:
134 	{
135 		mode = (test_pattern ==
136 			CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ?
137 			TEST_PATTERN_MODE_VERTICALBARS :
138 			TEST_PATTERN_MODE_HORIZONTALBARS);
139 
140 		switch (bit_depth) {
141 		case TEST_PATTERN_COLOR_FORMAT_BPC_6:
142 			dst_bpc = 6;
143 		break;
144 		case TEST_PATTERN_COLOR_FORMAT_BPC_8:
145 			dst_bpc = 8;
146 		break;
147 		case TEST_PATTERN_COLOR_FORMAT_BPC_10:
148 			dst_bpc = 10;
149 		break;
150 		default:
151 			dst_bpc = 8;
152 		break;
153 		}
154 
155 		/* adjust color to the required colorFormat */
156 		for (index = 0; index < 6; index++) {
157 			/* dst = 2^dstBpc * src / 2^srcBpc = src >>
158 			 * (srcBpc - dstBpc);
159 			 */
160 			dst_color[index] =
161 				src_color[index] >> (src_bpc - dst_bpc);
162 		/* DPG_COLOUR registers are 16-bit MSB aligned value with bits 3:0 hardwired to ZERO.
163 		 * XXXXXXXXXX000000 for 10 bit,
164 		 * XXXXXXXX00000000 for 8 bit,
165 		 * XXXXXX0000000000 for 6 bits
166 		 */
167 			dst_color[index] <<= (16 - dst_bpc);
168 		}
169 
170 		REG_SET_2(DPG_COLOUR_R_CR, 0,
171 				DPG_COLOUR1_R_CR, dst_color[0],
172 				DPG_COLOUR0_R_CR, dst_color[3]);
173 		REG_SET_2(DPG_COLOUR_G_Y, 0,
174 				DPG_COLOUR1_G_Y, dst_color[1],
175 				DPG_COLOUR0_G_Y, dst_color[4]);
176 		REG_SET_2(DPG_COLOUR_B_CB, 0,
177 				DPG_COLOUR1_B_CB, dst_color[2],
178 				DPG_COLOUR0_B_CB, dst_color[5]);
179 
180 		/* enable test pattern */
181 		REG_UPDATE_6(DPG_CONTROL,
182 			DPG_EN, 1,
183 			DPG_MODE, mode,
184 			DPG_DYNAMIC_RANGE, 0,
185 			DPG_BIT_DEPTH, bit_depth,
186 			DPG_VRES, 0,
187 			DPG_HRES, 0);
188 	}
189 	break;
190 
191 	case CONTROLLER_DP_TEST_PATTERN_COLORRAMP:
192 	{
193 		mode = (bit_depth ==
194 			TEST_PATTERN_COLOR_FORMAT_BPC_10 ?
195 			TEST_PATTERN_MODE_DUALRAMP_RGB :
196 			TEST_PATTERN_MODE_SINGLERAMP_RGB);
197 
198 		switch (bit_depth) {
199 		case TEST_PATTERN_COLOR_FORMAT_BPC_6:
200 			dst_bpc = 6;
201 		break;
202 		case TEST_PATTERN_COLOR_FORMAT_BPC_8:
203 			dst_bpc = 8;
204 		break;
205 		case TEST_PATTERN_COLOR_FORMAT_BPC_10:
206 			dst_bpc = 10;
207 		break;
208 		default:
209 			dst_bpc = 8;
210 		break;
211 		}
212 
213 		/* increment for the first ramp for one color gradation
214 		 * 1 gradation for 6-bit color is 2^10
215 		 * gradations in 16-bit color
216 		 */
217 		inc_base = (src_bpc - dst_bpc);
218 
219 		switch (bit_depth) {
220 		case TEST_PATTERN_COLOR_FORMAT_BPC_6:
221 		{
222 			REG_SET_3(DPG_RAMP_CONTROL, 0,
223 				DPG_RAMP0_OFFSET, 0,
224 				DPG_INC0, inc_base,
225 				DPG_INC1, 0);
226 			REG_UPDATE_2(DPG_CONTROL,
227 				DPG_VRES, 6,
228 				DPG_HRES, 6);
229 		}
230 		break;
231 		case TEST_PATTERN_COLOR_FORMAT_BPC_8:
232 		{
233 			REG_SET_3(DPG_RAMP_CONTROL, 0,
234 				DPG_RAMP0_OFFSET, 0,
235 				DPG_INC0, inc_base,
236 				DPG_INC1, 0);
237 			REG_UPDATE_2(DPG_CONTROL,
238 				DPG_VRES, 6,
239 				DPG_HRES, 8);
240 		}
241 		break;
242 		case TEST_PATTERN_COLOR_FORMAT_BPC_10:
243 		{
244 			REG_SET_3(DPG_RAMP_CONTROL, 0,
245 				DPG_RAMP0_OFFSET, 384 << 6,
246 				DPG_INC0, inc_base,
247 				DPG_INC1, inc_base + 2);
248 			REG_UPDATE_2(DPG_CONTROL,
249 				DPG_VRES, 5,
250 				DPG_HRES, 8);
251 		}
252 		break;
253 		default:
254 		break;
255 		}
256 
257 		/* enable test pattern */
258 		REG_UPDATE_4(DPG_CONTROL,
259 			DPG_EN, 1,
260 			DPG_MODE, mode,
261 			DPG_DYNAMIC_RANGE, 0,
262 			DPG_BIT_DEPTH, bit_depth);
263 	}
264 	break;
265 	case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE:
266 	{
267 		REG_WRITE(DPG_CONTROL, 0);
268 		REG_WRITE(DPG_COLOUR_R_CR, 0);
269 		REG_WRITE(DPG_COLOUR_G_Y, 0);
270 		REG_WRITE(DPG_COLOUR_B_CB, 0);
271 		REG_WRITE(DPG_RAMP_CONTROL, 0);
272 	}
273 	break;
274 	case CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR:
275 	{
276 		opp2_dpg_set_blank_color(opp, solid_color);
277 		REG_UPDATE_2(DPG_CONTROL,
278 				DPG_EN, 1,
279 				DPG_MODE, TEST_PATTERN_MODE_HORIZONTALBARS);
280 
281 		REG_SET_2(DPG_DIMENSIONS, 0,
282 				DPG_ACTIVE_WIDTH, width,
283 				DPG_ACTIVE_HEIGHT, height);
284 	}
285 	break;
286 	default:
287 		break;
288 
289 	}
290 }
291 
opp2_dpg_set_blank_color(struct output_pixel_processor * opp,const struct tg_color * color)292 void opp2_dpg_set_blank_color(
293 		struct output_pixel_processor *opp,
294 		const struct tg_color *color)
295 {
296 	struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp);
297 
298 	/* 16-bit MSB aligned value. Bits 3:0 of this field are hardwired to ZERO */
299 	ASSERT(color);
300 	REG_SET_2(DPG_COLOUR_B_CB, 0,
301 			DPG_COLOUR1_B_CB, color->color_b_cb << 6,
302 			DPG_COLOUR0_B_CB, color->color_b_cb << 6);
303 	REG_SET_2(DPG_COLOUR_G_Y, 0,
304 			DPG_COLOUR1_G_Y, color->color_g_y << 6,
305 			DPG_COLOUR0_G_Y, color->color_g_y << 6);
306 	REG_SET_2(DPG_COLOUR_R_CR, 0,
307 			DPG_COLOUR1_R_CR, color->color_r_cr << 6,
308 			DPG_COLOUR0_R_CR, color->color_r_cr << 6);
309 }
310 
opp2_dpg_is_blanked(struct output_pixel_processor * opp)311 bool opp2_dpg_is_blanked(struct output_pixel_processor *opp)
312 {
313 	struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp);
314 	uint32_t dpg_en, dpg_mode;
315 	uint32_t double_buffer_pending;
316 
317 	REG_GET_2(DPG_CONTROL,
318 			DPG_EN, &dpg_en,
319 			DPG_MODE, &dpg_mode);
320 
321 	REG_GET(DPG_STATUS,
322 			DPG_DOUBLE_BUFFER_PENDING, &double_buffer_pending);
323 
324 	return (dpg_en == 1) &&
325 		(double_buffer_pending == 0);
326 }
327 
opp2_program_left_edge_extra_pixel(struct output_pixel_processor * opp,bool count)328 void opp2_program_left_edge_extra_pixel (
329 		struct output_pixel_processor *opp,
330 		bool count)
331 {
332 	struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp);
333 
334 	/* Specifies the number of extra left edge pixels that are supplied to
335 	 * the 422 horizontal chroma sub-sample filter.
336 	 * Note that when left edge pixel is not "0", fmt pixel encoding can be in either 420 or 422 mode
337 	 * */
338 	REG_UPDATE(FMT_422_CONTROL, FMT_LEFT_EDGE_EXTRA_PIXEL_COUNT, count);
339 }
340 
341 /*****************************************/
342 /* Constructor, Destructor               */
343 /*****************************************/
344 
345 static struct opp_funcs dcn20_opp_funcs = {
346 		.opp_set_dyn_expansion = opp1_set_dyn_expansion,
347 		.opp_program_fmt = opp1_program_fmt,
348 		.opp_program_bit_depth_reduction = opp1_program_bit_depth_reduction,
349 		.opp_program_stereo = opp1_program_stereo,
350 		.opp_pipe_clock_control = opp1_pipe_clock_control,
351 		.opp_set_disp_pattern_generator = opp2_set_disp_pattern_generator,
352 		.dpg_is_blanked = opp2_dpg_is_blanked,
353 		.opp_dpg_set_blank_color = opp2_dpg_set_blank_color,
354 		.opp_destroy = opp1_destroy,
355 		.opp_program_left_edge_extra_pixel = opp2_program_left_edge_extra_pixel,
356 };
357 
dcn20_opp_construct(struct dcn20_opp * oppn20,struct dc_context * ctx,uint32_t inst,const struct dcn20_opp_registers * regs,const struct dcn20_opp_shift * opp_shift,const struct dcn20_opp_mask * opp_mask)358 void dcn20_opp_construct(struct dcn20_opp *oppn20,
359 	struct dc_context *ctx,
360 	uint32_t inst,
361 	const struct dcn20_opp_registers *regs,
362 	const struct dcn20_opp_shift *opp_shift,
363 	const struct dcn20_opp_mask *opp_mask)
364 {
365 	oppn20->base.ctx = ctx;
366 	oppn20->base.inst = inst;
367 	oppn20->base.funcs = &dcn20_opp_funcs;
368 
369 	oppn20->regs = regs;
370 	oppn20->opp_shift = opp_shift;
371 	oppn20->opp_mask = opp_mask;
372 }
373 
374