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