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 "core_types.h"
27 #include "dm_services.h"
28 #include "dcn20_opp.h"
29 #include "reg_helper.h"
30 
31 #define REG(reg) \
32 	(oppn20->regs->reg)
33 
34 #undef FN
35 #define FN(reg_name, field_name) \
36 	oppn20->opp_shift->field_name, oppn20->opp_mask->field_name
37 
38 #define CTX \
39 	oppn20->base.ctx
40 
41 
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,int offset)42 void opp2_set_disp_pattern_generator(
43 		struct output_pixel_processor *opp,
44 		enum controller_dp_test_pattern test_pattern,
45 		enum controller_dp_color_space color_space,
46 		enum dc_color_depth color_depth,
47 		const struct tg_color *solid_color,
48 		int width,
49 		int height,
50 		int offset)
51 {
52 	struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp);
53 	enum test_pattern_color_format bit_depth;
54 	enum test_pattern_dyn_range dyn_range;
55 	enum test_pattern_mode mode;
56 
57 	/* color ramp generator mixes 16-bits color */
58 	uint32_t src_bpc = 16;
59 	/* requested bpc */
60 	uint32_t dst_bpc;
61 	uint32_t index;
62 	/* RGB values of the color bars.
63 	 * Produce two RGB colors: RGB0 - white (all Fs)
64 	 * and RGB1 - black (all 0s)
65 	 * (three RGB components for two colors)
66 	 */
67 	uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000,
68 						0x0000, 0x0000};
69 	/* dest color (converted to the specified color format) */
70 	uint16_t dst_color[6];
71 	uint32_t inc_base;
72 
73 	/* translate to bit depth */
74 	switch (color_depth) {
75 	case COLOR_DEPTH_666:
76 		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6;
77 	break;
78 	case COLOR_DEPTH_888:
79 		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
80 	break;
81 	case COLOR_DEPTH_101010:
82 		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10;
83 	break;
84 	case COLOR_DEPTH_121212:
85 		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12;
86 	break;
87 	default:
88 		bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
89 	break;
90 	}
91 
92 	/* set DPG dimentions */
93 	REG_SET_2(DPG_DIMENSIONS, 0,
94 		DPG_ACTIVE_WIDTH, width,
95 		DPG_ACTIVE_HEIGHT, height);
96 
97 	/* set DPG offset */
98 	REG_SET_2(DPG_OFFSET_SEGMENT, 0,
99 		DPG_X_OFFSET, offset,
100 		DPG_SEGMENT_WIDTH, 0);
101 
102 	switch (test_pattern) {
103 	case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES:
104 	case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA:
105 	{
106 		dyn_range = (test_pattern ==
107 				CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ?
108 				TEST_PATTERN_DYN_RANGE_CEA :
109 				TEST_PATTERN_DYN_RANGE_VESA);
110 
111 		switch (color_space) {
112 		case CONTROLLER_DP_COLOR_SPACE_YCBCR601:
113 			mode = TEST_PATTERN_MODE_COLORSQUARES_YCBCR601;
114 		break;
115 		case CONTROLLER_DP_COLOR_SPACE_YCBCR709:
116 			mode = TEST_PATTERN_MODE_COLORSQUARES_YCBCR709;
117 		break;
118 		case CONTROLLER_DP_COLOR_SPACE_RGB:
119 		default:
120 			mode = TEST_PATTERN_MODE_COLORSQUARES_RGB;
121 		break;
122 		}
123 
124 		REG_UPDATE_6(DPG_CONTROL,
125 			DPG_EN, 1,
126 			DPG_MODE, mode,
127 			DPG_DYNAMIC_RANGE, dyn_range,
128 			DPG_BIT_DEPTH, bit_depth,
129 			DPG_VRES, 6,
130 			DPG_HRES, 6);
131 	}
132 	break;
133 
134 	case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS:
135 	case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS:
136 	{
137 		mode = (test_pattern ==
138 			CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ?
139 			TEST_PATTERN_MODE_VERTICALBARS :
140 			TEST_PATTERN_MODE_HORIZONTALBARS);
141 
142 		switch (bit_depth) {
143 		case TEST_PATTERN_COLOR_FORMAT_BPC_6:
144 			dst_bpc = 6;
145 		break;
146 		case TEST_PATTERN_COLOR_FORMAT_BPC_8:
147 			dst_bpc = 8;
148 		break;
149 		case TEST_PATTERN_COLOR_FORMAT_BPC_10:
150 			dst_bpc = 10;
151 		break;
152 		default:
153 			dst_bpc = 8;
154 		break;
155 		}
156 
157 		/* adjust color to the required colorFormat */
158 		for (index = 0; index < 6; index++) {
159 			/* dst = 2^dstBpc * src / 2^srcBpc = src >>
160 			 * (srcBpc - dstBpc);
161 			 */
162 			dst_color[index] =
163 				src_color[index] >> (src_bpc - dst_bpc);
164 		/* DPG_COLOUR registers are 16-bit MSB aligned value with bits 3:0 hardwired to ZERO.
165 		 * XXXXXXXXXX000000 for 10 bit,
166 		 * XXXXXXXX00000000 for 8 bit,
167 		 * XXXXXX0000000000 for 6 bits
168 		 */
169 			dst_color[index] <<= (16 - dst_bpc);
170 		}
171 
172 		REG_SET_2(DPG_COLOUR_R_CR, 0,
173 				DPG_COLOUR1_R_CR, dst_color[0],
174 				DPG_COLOUR0_R_CR, dst_color[3]);
175 		REG_SET_2(DPG_COLOUR_G_Y, 0,
176 				DPG_COLOUR1_G_Y, dst_color[1],
177 				DPG_COLOUR0_G_Y, dst_color[4]);
178 		REG_SET_2(DPG_COLOUR_B_CB, 0,
179 				DPG_COLOUR1_B_CB, dst_color[2],
180 				DPG_COLOUR0_B_CB, dst_color[5]);
181 
182 		/* enable test pattern */
183 		REG_UPDATE_6(DPG_CONTROL,
184 			DPG_EN, 1,
185 			DPG_MODE, mode,
186 			DPG_DYNAMIC_RANGE, 0,
187 			DPG_BIT_DEPTH, bit_depth,
188 			DPG_VRES, 0,
189 			DPG_HRES, 0);
190 	}
191 	break;
192 
193 	case CONTROLLER_DP_TEST_PATTERN_COLORRAMP:
194 	{
195 		mode = (bit_depth ==
196 			TEST_PATTERN_COLOR_FORMAT_BPC_10 ?
197 			TEST_PATTERN_MODE_DUALRAMP_RGB :
198 			TEST_PATTERN_MODE_SINGLERAMP_RGB);
199 
200 		switch (bit_depth) {
201 		case TEST_PATTERN_COLOR_FORMAT_BPC_6:
202 			dst_bpc = 6;
203 		break;
204 		case TEST_PATTERN_COLOR_FORMAT_BPC_8:
205 			dst_bpc = 8;
206 		break;
207 		case TEST_PATTERN_COLOR_FORMAT_BPC_10:
208 			dst_bpc = 10;
209 		break;
210 		default:
211 			dst_bpc = 8;
212 		break;
213 		}
214 
215 		/* increment for the first ramp for one color gradation
216 		 * 1 gradation for 6-bit color is 2^10
217 		 * gradations in 16-bit color
218 		 */
219 		inc_base = (src_bpc - dst_bpc);
220 
221 		switch (bit_depth) {
222 		case TEST_PATTERN_COLOR_FORMAT_BPC_6:
223 		{
224 			REG_SET_3(DPG_RAMP_CONTROL, 0,
225 				DPG_RAMP0_OFFSET, 0,
226 				DPG_INC0, inc_base,
227 				DPG_INC1, 0);
228 			REG_UPDATE_2(DPG_CONTROL,
229 				DPG_VRES, 6,
230 				DPG_HRES, 6);
231 		}
232 		break;
233 		case TEST_PATTERN_COLOR_FORMAT_BPC_8:
234 		{
235 			REG_SET_3(DPG_RAMP_CONTROL, 0,
236 				DPG_RAMP0_OFFSET, 0,
237 				DPG_INC0, inc_base,
238 				DPG_INC1, 0);
239 			REG_UPDATE_2(DPG_CONTROL,
240 				DPG_VRES, 6,
241 				DPG_HRES, 8);
242 		}
243 		break;
244 		case TEST_PATTERN_COLOR_FORMAT_BPC_10:
245 		{
246 			REG_SET_3(DPG_RAMP_CONTROL, 0,
247 				DPG_RAMP0_OFFSET, 384 << 6,
248 				DPG_INC0, inc_base,
249 				DPG_INC1, inc_base + 2);
250 			REG_UPDATE_2(DPG_CONTROL,
251 				DPG_VRES, 5,
252 				DPG_HRES, 8);
253 		}
254 		break;
255 		default:
256 		break;
257 		}
258 
259 		/* enable test pattern */
260 		REG_UPDATE_4(DPG_CONTROL,
261 			DPG_EN, 1,
262 			DPG_MODE, mode,
263 			DPG_DYNAMIC_RANGE, 0,
264 			DPG_BIT_DEPTH, bit_depth);
265 	}
266 	break;
267 	case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE:
268 	{
269 		REG_WRITE(DPG_CONTROL, 0);
270 		REG_WRITE(DPG_COLOUR_R_CR, 0);
271 		REG_WRITE(DPG_COLOUR_G_Y, 0);
272 		REG_WRITE(DPG_COLOUR_B_CB, 0);
273 		REG_WRITE(DPG_RAMP_CONTROL, 0);
274 	}
275 	break;
276 	case CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR:
277 	{
278 		opp2_dpg_set_blank_color(opp, solid_color);
279 		REG_UPDATE_2(DPG_CONTROL,
280 				DPG_EN, 1,
281 				DPG_MODE, TEST_PATTERN_MODE_HORIZONTALBARS);
282 
283 		REG_SET_2(DPG_DIMENSIONS, 0,
284 				DPG_ACTIVE_WIDTH, width,
285 				DPG_ACTIVE_HEIGHT, height);
286 	}
287 	break;
288 	default:
289 		break;
290 
291 	}
292 }
293 
opp2_program_dpg_dimensions(struct output_pixel_processor * opp,int width,int height)294 void opp2_program_dpg_dimensions(
295 		struct output_pixel_processor *opp,
296 		int width, int height)
297 {
298 	struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp);
299 
300 	REG_SET_2(DPG_DIMENSIONS, 0,
301 		DPG_ACTIVE_WIDTH, width,
302 		DPG_ACTIVE_HEIGHT, height);
303 }
304 
opp2_dpg_set_blank_color(struct output_pixel_processor * opp,const struct tg_color * color)305 void opp2_dpg_set_blank_color(
306 		struct output_pixel_processor *opp,
307 		const struct tg_color *color)
308 {
309 	struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp);
310 
311 	/* 16-bit MSB aligned value. Bits 3:0 of this field are hardwired to ZERO */
312 	ASSERT(color);
313 	REG_SET_2(DPG_COLOUR_B_CB, 0,
314 			DPG_COLOUR1_B_CB, color->color_b_cb << 6,
315 			DPG_COLOUR0_B_CB, color->color_b_cb << 6);
316 	REG_SET_2(DPG_COLOUR_G_Y, 0,
317 			DPG_COLOUR1_G_Y, color->color_g_y << 6,
318 			DPG_COLOUR0_G_Y, color->color_g_y << 6);
319 	REG_SET_2(DPG_COLOUR_R_CR, 0,
320 			DPG_COLOUR1_R_CR, color->color_r_cr << 6,
321 			DPG_COLOUR0_R_CR, color->color_r_cr << 6);
322 }
323 
opp2_dpg_is_blanked(struct output_pixel_processor * opp)324 bool opp2_dpg_is_blanked(struct output_pixel_processor *opp)
325 {
326 	struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp);
327 	uint32_t dpg_en, dpg_mode;
328 	uint32_t double_buffer_pending;
329 
330 	REG_GET_2(DPG_CONTROL,
331 			DPG_EN, &dpg_en,
332 			DPG_MODE, &dpg_mode);
333 
334 	REG_GET(DPG_STATUS,
335 			DPG_DOUBLE_BUFFER_PENDING, &double_buffer_pending);
336 
337 	return (dpg_en == 1) &&
338 		(double_buffer_pending == 0);
339 }
340 
opp2_dpg_is_pending(struct output_pixel_processor * opp)341 bool opp2_dpg_is_pending(struct output_pixel_processor *opp)
342 {
343 	struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp);
344 	uint32_t double_buffer_pending;
345 	uint32_t dpg_en;
346 
347 	REG_GET(DPG_CONTROL, DPG_EN, &dpg_en);
348 
349 	REG_GET(DPG_STATUS, DPG_DOUBLE_BUFFER_PENDING, &double_buffer_pending);
350 
351 	return (dpg_en == 1 && double_buffer_pending == 1);
352 }
353 
opp2_program_left_edge_extra_pixel(struct output_pixel_processor * opp,enum dc_pixel_encoding pixel_encoding,bool is_primary)354 void opp2_program_left_edge_extra_pixel(
355 		struct output_pixel_processor *opp,
356 		enum dc_pixel_encoding pixel_encoding,
357 		bool is_primary)
358 {
359 	struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp);
360 	uint32_t count = opp2_get_left_edge_extra_pixel_count(opp, pixel_encoding, is_primary);
361 
362 	/*
363 	 * Specifies the number of extra left edge pixels that are supplied to
364 	 * the 422 horizontal chroma sub-sample filter.
365 	 */
366 	REG_UPDATE(FMT_422_CONTROL, FMT_LEFT_EDGE_EXTRA_PIXEL_COUNT, count);
367 }
368 
opp2_get_left_edge_extra_pixel_count(struct output_pixel_processor * opp,enum dc_pixel_encoding pixel_encoding,bool is_primary)369 uint32_t opp2_get_left_edge_extra_pixel_count(struct output_pixel_processor *opp,
370 		enum dc_pixel_encoding pixel_encoding, bool is_primary)
371 {
372 	if ((pixel_encoding == PIXEL_ENCODING_YCBCR422 || pixel_encoding == PIXEL_ENCODING_YCBCR420) &&
373 			!opp->ctx->dc->debug.force_chroma_subsampling_1tap &&
374 			!is_primary)
375 		return 1;
376 	else
377 		return 0;
378 }
379 
380 /*****************************************/
381 /* Constructor, Destructor               */
382 /*****************************************/
383 
384 static struct opp_funcs dcn20_opp_funcs = {
385 		.opp_set_dyn_expansion = opp1_set_dyn_expansion,
386 		.opp_program_fmt = opp1_program_fmt,
387 		.opp_program_bit_depth_reduction = opp1_program_bit_depth_reduction,
388 		.opp_program_stereo = opp1_program_stereo,
389 		.opp_pipe_clock_control = opp1_pipe_clock_control,
390 		.opp_set_disp_pattern_generator = opp2_set_disp_pattern_generator,
391 		.opp_program_dpg_dimensions = opp2_program_dpg_dimensions,
392 		.dpg_is_blanked = opp2_dpg_is_blanked,
393 		.dpg_is_pending = opp2_dpg_is_pending,
394 		.opp_dpg_set_blank_color = opp2_dpg_set_blank_color,
395 		.opp_destroy = opp1_destroy,
396 		.opp_program_left_edge_extra_pixel = opp2_program_left_edge_extra_pixel,
397 		.opp_get_left_edge_extra_pixel_count = opp2_get_left_edge_extra_pixel_count,
398 };
399 
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)400 void dcn20_opp_construct(struct dcn20_opp *oppn20,
401 	struct dc_context *ctx,
402 	uint32_t inst,
403 	const struct dcn20_opp_registers *regs,
404 	const struct dcn20_opp_shift *opp_shift,
405 	const struct dcn20_opp_mask *opp_mask)
406 {
407 	oppn20->base.ctx = ctx;
408 	oppn20->base.inst = inst;
409 	oppn20->base.funcs = &dcn20_opp_funcs;
410 
411 	oppn20->regs = regs;
412 	oppn20->opp_shift = opp_shift;
413 	oppn20->opp_mask = opp_mask;
414 }
415 
416