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