1 /*
2  * Copyright 2015 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 "core_types.h"
28 #include "timing_generator.h"
29 #include "hw_sequencer.h"
30 
31 #define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
32 
33 /* used as index in array of black_color_format */
34 enum black_color_format {
35 	BLACK_COLOR_FORMAT_RGB_FULLRANGE = 0,
36 	BLACK_COLOR_FORMAT_RGB_LIMITED,
37 	BLACK_COLOR_FORMAT_YUV_TV,
38 	BLACK_COLOR_FORMAT_YUV_CV,
39 	BLACK_COLOR_FORMAT_YUV_SUPER_AA,
40 	BLACK_COLOR_FORMAT_DEBUG,
41 };
42 
43 enum dc_color_space_type {
44 	COLOR_SPACE_RGB_TYPE,
45 	COLOR_SPACE_RGB_LIMITED_TYPE,
46 	COLOR_SPACE_YCBCR601_TYPE,
47 	COLOR_SPACE_YCBCR709_TYPE,
48 	COLOR_SPACE_YCBCR2020_TYPE,
49 	COLOR_SPACE_YCBCR601_LIMITED_TYPE,
50 	COLOR_SPACE_YCBCR709_LIMITED_TYPE,
51 	COLOR_SPACE_YCBCR709_BLACK_TYPE,
52 };
53 
54 static const struct tg_color black_color_format[] = {
55 	/* BlackColorFormat_RGB_FullRange */
56 	{0, 0, 0},
57 	/* BlackColorFormat_RGB_Limited */
58 	{0x40, 0x40, 0x40},
59 	/* BlackColorFormat_YUV_TV */
60 	{0x200, 0x40, 0x200},
61 	/* BlackColorFormat_YUV_CV */
62 	{0x1f4, 0x40, 0x1f4},
63 	/* BlackColorFormat_YUV_SuperAA */
64 	{0x1a2, 0x20, 0x1a2},
65 	/* visual confirm debug */
66 	{0xff, 0xff, 0},
67 };
68 
69 struct out_csc_color_matrix_type {
70 	enum dc_color_space_type color_space_type;
71 	uint16_t regval[12];
72 };
73 
74 static const struct out_csc_color_matrix_type output_csc_matrix[] = {
75 	{ COLOR_SPACE_RGB_TYPE,
76 		{ 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
77 	{ COLOR_SPACE_RGB_LIMITED_TYPE,
78 		{ 0x1B67, 0, 0, 0x201, 0, 0x1B67, 0, 0x201, 0, 0, 0x1B67, 0x201} },
79 	{ COLOR_SPACE_YCBCR601_TYPE,
80 		{ 0xE04, 0xF444, 0xFDB9, 0x1004, 0x831, 0x1016, 0x320, 0x201, 0xFB45,
81 				0xF6B7, 0xE04, 0x1004} },
82 	{ COLOR_SPACE_YCBCR709_TYPE,
83 		{ 0xE04, 0xF345, 0xFEB7, 0x1004, 0x5D3, 0x1399, 0x1FA,
84 				0x201, 0xFCCA, 0xF533, 0xE04, 0x1004} },
85 	/* TODO: correct values below */
86 	{ COLOR_SPACE_YCBCR601_LIMITED_TYPE,
87 		{ 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991,
88 				0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} },
89 	{ COLOR_SPACE_YCBCR709_LIMITED_TYPE,
90 		{ 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3,
91 				0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} },
92 	{ COLOR_SPACE_YCBCR2020_TYPE,
93 		{ 0x1000, 0xF149, 0xFEB7, 0x0000, 0x0868, 0x15B2,
94 				0x01E6, 0x0000, 0xFB88, 0xF478, 0x1000, 0x0000} },
95 	{ COLOR_SPACE_YCBCR709_BLACK_TYPE,
96 		{ 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000,
97 				0x0000, 0x0200, 0x0000, 0x0000, 0x0000, 0x1000} },
98 };
99 
100 static bool is_rgb_type(
101 		enum dc_color_space color_space)
102 {
103 	bool ret = false;
104 
105 	if (color_space == COLOR_SPACE_SRGB			||
106 		color_space == COLOR_SPACE_XR_RGB		||
107 		color_space == COLOR_SPACE_MSREF_SCRGB		||
108 		color_space == COLOR_SPACE_2020_RGB_FULLRANGE	||
109 		color_space == COLOR_SPACE_ADOBERGB		||
110 		color_space == COLOR_SPACE_DCIP3	||
111 		color_space == COLOR_SPACE_DOLBYVISION)
112 		ret = true;
113 	return ret;
114 }
115 
116 static bool is_rgb_limited_type(
117 		enum dc_color_space color_space)
118 {
119 	bool ret = false;
120 
121 	if (color_space == COLOR_SPACE_SRGB_LIMITED		||
122 		color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE)
123 		ret = true;
124 	return ret;
125 }
126 
127 static bool is_ycbcr601_type(
128 		enum dc_color_space color_space)
129 {
130 	bool ret = false;
131 
132 	if (color_space == COLOR_SPACE_YCBCR601	||
133 		color_space == COLOR_SPACE_XV_YCC_601)
134 		ret = true;
135 	return ret;
136 }
137 
138 static bool is_ycbcr601_limited_type(
139 		enum dc_color_space color_space)
140 {
141 	bool ret = false;
142 
143 	if (color_space == COLOR_SPACE_YCBCR601_LIMITED)
144 		ret = true;
145 	return ret;
146 }
147 
148 static bool is_ycbcr709_type(
149 		enum dc_color_space color_space)
150 {
151 	bool ret = false;
152 
153 	if (color_space == COLOR_SPACE_YCBCR709	||
154 		color_space == COLOR_SPACE_XV_YCC_709)
155 		ret = true;
156 	return ret;
157 }
158 
159 static bool is_ycbcr2020_type(
160 	enum dc_color_space color_space)
161 {
162 	bool ret = false;
163 
164 	if (color_space == COLOR_SPACE_2020_YCBCR)
165 		ret = true;
166 	return ret;
167 }
168 
169 static bool is_ycbcr709_limited_type(
170 		enum dc_color_space color_space)
171 {
172 	bool ret = false;
173 
174 	if (color_space == COLOR_SPACE_YCBCR709_LIMITED)
175 		ret = true;
176 	return ret;
177 }
178 static enum dc_color_space_type get_color_space_type(enum dc_color_space color_space)
179 {
180 	enum dc_color_space_type type = COLOR_SPACE_RGB_TYPE;
181 
182 	if (is_rgb_type(color_space))
183 		type = COLOR_SPACE_RGB_TYPE;
184 	else if (is_rgb_limited_type(color_space))
185 		type = COLOR_SPACE_RGB_LIMITED_TYPE;
186 	else if (is_ycbcr601_type(color_space))
187 		type = COLOR_SPACE_YCBCR601_TYPE;
188 	else if (is_ycbcr709_type(color_space))
189 		type = COLOR_SPACE_YCBCR709_TYPE;
190 	else if (is_ycbcr601_limited_type(color_space))
191 		type = COLOR_SPACE_YCBCR601_LIMITED_TYPE;
192 	else if (is_ycbcr709_limited_type(color_space))
193 		type = COLOR_SPACE_YCBCR709_LIMITED_TYPE;
194 	else if (is_ycbcr2020_type(color_space))
195 		type = COLOR_SPACE_YCBCR2020_TYPE;
196 	else if (color_space == COLOR_SPACE_YCBCR709)
197 		type = COLOR_SPACE_YCBCR709_BLACK_TYPE;
198 	else if (color_space == COLOR_SPACE_YCBCR709_BLACK)
199 		type = COLOR_SPACE_YCBCR709_BLACK_TYPE;
200 	return type;
201 }
202 
203 const uint16_t *find_color_matrix(enum dc_color_space color_space,
204 							uint32_t *array_size)
205 {
206 	int i;
207 	enum dc_color_space_type type;
208 	const uint16_t *val = NULL;
209 	int arr_size = NUM_ELEMENTS(output_csc_matrix);
210 
211 	type = get_color_space_type(color_space);
212 	for (i = 0; i < arr_size; i++)
213 		if (output_csc_matrix[i].color_space_type == type) {
214 			val = output_csc_matrix[i].regval;
215 			*array_size = 12;
216 			break;
217 		}
218 
219 	return val;
220 }
221 
222 
223 void color_space_to_black_color(
224 	const struct dc *dc,
225 	enum dc_color_space colorspace,
226 	struct tg_color *black_color)
227 {
228 	switch (colorspace) {
229 	case COLOR_SPACE_YCBCR601:
230 	case COLOR_SPACE_YCBCR709:
231 	case COLOR_SPACE_YCBCR709_BLACK:
232 	case COLOR_SPACE_YCBCR601_LIMITED:
233 	case COLOR_SPACE_YCBCR709_LIMITED:
234 	case COLOR_SPACE_2020_YCBCR:
235 		*black_color = black_color_format[BLACK_COLOR_FORMAT_YUV_CV];
236 		break;
237 
238 	case COLOR_SPACE_SRGB_LIMITED:
239 		*black_color =
240 			black_color_format[BLACK_COLOR_FORMAT_RGB_LIMITED];
241 		break;
242 
243 	/**
244 	 * Remove default and add case for all color space
245 	 * so when we forget to add new color space
246 	 * compiler will give a warning
247 	 */
248 	case COLOR_SPACE_UNKNOWN:
249 	case COLOR_SPACE_SRGB:
250 	case COLOR_SPACE_XR_RGB:
251 	case COLOR_SPACE_MSREF_SCRGB:
252 	case COLOR_SPACE_XV_YCC_709:
253 	case COLOR_SPACE_XV_YCC_601:
254 	case COLOR_SPACE_2020_RGB_FULLRANGE:
255 	case COLOR_SPACE_2020_RGB_LIMITEDRANGE:
256 	case COLOR_SPACE_ADOBERGB:
257 	case COLOR_SPACE_DCIP3:
258 	case COLOR_SPACE_DISPLAYNATIVE:
259 	case COLOR_SPACE_DOLBYVISION:
260 	case COLOR_SPACE_APPCTRL:
261 	case COLOR_SPACE_CUSTOMPOINTS:
262 		/* fefault is sRGB black (full range). */
263 		*black_color =
264 			black_color_format[BLACK_COLOR_FORMAT_RGB_FULLRANGE];
265 		/* default is sRGB black 0. */
266 		break;
267 	}
268 }
269 
270 bool hwss_wait_for_blank_complete(
271 		struct timing_generator *tg)
272 {
273 	int counter;
274 
275 	/* Not applicable if the pipe is not primary, save 300ms of boot time */
276 	if (!tg->funcs->is_blanked)
277 		return true;
278 	for (counter = 0; counter < 100; counter++) {
279 		if (tg->funcs->is_blanked(tg))
280 			break;
281 
282 		msleep(1);
283 	}
284 
285 	if (counter == 100) {
286 		dm_error("DC: failed to blank crtc!\n");
287 		return false;
288 	}
289 
290 	return true;
291 }
292 
293 void get_mpctree_visual_confirm_color(
294 		struct pipe_ctx *pipe_ctx,
295 		struct tg_color *color)
296 {
297 	const struct tg_color pipe_colors[6] = {
298 			{MAX_TG_COLOR_VALUE, 0, 0}, /* red */
299 			{MAX_TG_COLOR_VALUE, MAX_TG_COLOR_VALUE / 4, 0}, /* orange */
300 			{MAX_TG_COLOR_VALUE, MAX_TG_COLOR_VALUE, 0}, /* yellow */
301 			{0, MAX_TG_COLOR_VALUE, 0}, /* green */
302 			{0, 0, MAX_TG_COLOR_VALUE}, /* blue */
303 			{MAX_TG_COLOR_VALUE / 2, 0, MAX_TG_COLOR_VALUE / 2}, /* purple */
304 	};
305 
306 	struct pipe_ctx *top_pipe = pipe_ctx;
307 
308 	while (top_pipe->top_pipe)
309 		top_pipe = top_pipe->top_pipe;
310 
311 	*color = pipe_colors[top_pipe->pipe_idx];
312 }
313 
314 void get_surface_visual_confirm_color(
315 		const struct pipe_ctx *pipe_ctx,
316 		struct tg_color *color)
317 {
318 	uint32_t color_value = MAX_TG_COLOR_VALUE;
319 
320 	switch (pipe_ctx->plane_res.scl_data.format) {
321 	case PIXEL_FORMAT_ARGB8888:
322 		/* set border color to red */
323 		color->color_r_cr = color_value;
324 		if (pipe_ctx->plane_state->layer_index > 0) {
325 			/* set border color to pink */
326 			color->color_b_cb = color_value;
327 			color->color_g_y = color_value * 0.5;
328 		}
329 		break;
330 
331 	case PIXEL_FORMAT_ARGB2101010:
332 		/* set border color to blue */
333 		color->color_b_cb = color_value;
334 		if (pipe_ctx->plane_state->layer_index > 0) {
335 			/* set border color to cyan */
336 			color->color_g_y = color_value;
337 		}
338 		break;
339 	case PIXEL_FORMAT_420BPP8:
340 		/* set border color to green */
341 		color->color_g_y = color_value;
342 		break;
343 	case PIXEL_FORMAT_420BPP10:
344 		/* set border color to yellow */
345 		color->color_g_y = color_value;
346 		color->color_r_cr = color_value;
347 		break;
348 	case PIXEL_FORMAT_FP16:
349 		/* set border color to white */
350 		color->color_r_cr = color_value;
351 		color->color_b_cb = color_value;
352 		color->color_g_y = color_value;
353 		if (pipe_ctx->plane_state->layer_index > 0) {
354 			/* set border color to orange */
355 			color->color_g_y = 0.22 * color_value;
356 			color->color_b_cb = 0;
357 		}
358 		break;
359 	default:
360 		break;
361 	}
362 }
363 
364 void get_hdr_visual_confirm_color(
365 		struct pipe_ctx *pipe_ctx,
366 		struct tg_color *color)
367 {
368 	uint32_t color_value = MAX_TG_COLOR_VALUE;
369 
370 	/* Determine the overscan color based on the top-most (desktop) plane's context */
371 	struct pipe_ctx *top_pipe_ctx  = pipe_ctx;
372 
373 	while (top_pipe_ctx->top_pipe != NULL)
374 		top_pipe_ctx = top_pipe_ctx->top_pipe;
375 
376 	switch (top_pipe_ctx->plane_res.scl_data.format) {
377 	case PIXEL_FORMAT_ARGB2101010:
378 		if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_PQ) {
379 			/* HDR10, ARGB2101010 - set border color to red */
380 			color->color_r_cr = color_value;
381 		} else if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) {
382 			/* FreeSync 2 ARGB2101010 - set border color to pink */
383 			color->color_r_cr = color_value;
384 			color->color_b_cb = color_value;
385 		}
386 		break;
387 	case PIXEL_FORMAT_FP16:
388 		if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_PQ) {
389 			/* HDR10, FP16 - set border color to blue */
390 			color->color_b_cb = color_value;
391 		} else if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) {
392 			/* FreeSync 2 HDR - set border color to green */
393 			color->color_g_y = color_value;
394 		}
395 		break;
396 	default:
397 		/* SDR - set border color to Gray */
398 		color->color_r_cr = color_value/2;
399 		color->color_b_cb = color_value/2;
400 		color->color_g_y = color_value/2;
401 		break;
402 	}
403 }
404 
405 void get_subvp_visual_confirm_color(
406 		struct dc *dc,
407 		struct pipe_ctx *pipe_ctx,
408 		struct tg_color *color)
409 {
410 	uint32_t color_value = MAX_TG_COLOR_VALUE;
411 	bool enable_subvp = false;
412 	int i;
413 
414 	if (!dc->ctx || !dc->ctx->dmub_srv || !pipe_ctx)
415 		return;
416 
417 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
418 		struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
419 
420 		if (pipe->stream && pipe->stream->mall_stream_config.paired_stream &&
421 		    pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
422 			/* SubVP enable - red */
423 			color->color_r_cr = color_value;
424 			enable_subvp = true;
425 
426 			if (pipe_ctx->stream == pipe->stream)
427 				return;
428 			break;
429 		}
430 	}
431 
432 	if (enable_subvp && pipe_ctx->stream->mall_stream_config.type == SUBVP_NONE) {
433 		color->color_r_cr = 0;
434 		if (pipe_ctx->stream->ignore_msa_timing_param == 1)
435 			/* SubVP enable and DRR on - green */
436 			color->color_g_y = color_value;
437 		else
438 			/* SubVP enable and No DRR - blue */
439 			color->color_b_cb = color_value;
440 	}
441 }
442 
443 void get_surface_tile_visual_confirm_color(
444 		struct pipe_ctx *pipe_ctx,
445 		struct tg_color *color)
446 {
447 	uint32_t color_value = MAX_TG_COLOR_VALUE;
448 	/* Determine the overscan color based on the bottom-most plane's context */
449 	struct pipe_ctx *bottom_pipe_ctx  = pipe_ctx;
450 
451 	while (bottom_pipe_ctx->bottom_pipe != NULL)
452 		bottom_pipe_ctx = bottom_pipe_ctx->bottom_pipe;
453 
454 	switch (bottom_pipe_ctx->plane_state->tiling_info.gfx9.swizzle) {
455 	case DC_SW_LINEAR:
456 		/* LINEAR Surface - set border color to red */
457 		color->color_r_cr = color_value;
458 		break;
459 	default:
460 		break;
461 	}
462 }
463