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, 0x1004, 0x0868, 0x15B2,
94 0x01E6, 0x201, 0xFB88, 0xF478, 0x1000, 0x1004} },
95 { COLOR_SPACE_YCBCR709_BLACK_TYPE,
96 { 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000,
97 0x0000, 0x0200, 0x0000, 0x0000, 0x0000, 0x1000} },
98 };
99
is_rgb_type(enum dc_color_space color_space)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
is_rgb_limited_type(enum dc_color_space color_space)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
is_ycbcr601_type(enum dc_color_space color_space)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
is_ycbcr601_limited_type(enum dc_color_space color_space)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
is_ycbcr709_type(enum dc_color_space color_space)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
is_ycbcr2020_type(enum dc_color_space color_space)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
is_ycbcr709_limited_type(enum dc_color_space color_space)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 }
get_color_space_type(enum dc_color_space color_space)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
find_color_matrix(enum dc_color_space color_space,uint32_t * array_size)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
color_space_to_black_color(const struct dc * dc,enum dc_color_space colorspace,struct tg_color * black_color)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
hwss_wait_for_blank_complete(struct timing_generator * tg)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
get_mpctree_visual_confirm_color(struct pipe_ctx * pipe_ctx,struct tg_color * color)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
get_surface_visual_confirm_color(const struct pipe_ctx * pipe_ctx,struct tg_color * color)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
get_hdr_visual_confirm_color(struct pipe_ctx * pipe_ctx,struct tg_color * color)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
get_subvp_visual_confirm_color(struct dc * dc,struct pipe_ctx * pipe_ctx,struct tg_color * color)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
get_surface_tile_visual_confirm_color(struct pipe_ctx * pipe_ctx,struct tg_color * color)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