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
46void 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
292void 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
311bool 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
328void 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
345static 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
358void 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