dce60_hw_sequencer.c (13046B)
1/* 2 * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> 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 "dc.h" 28#include "core_types.h" 29#include "dce60_hw_sequencer.h" 30 31#include "dce/dce_hwseq.h" 32#include "dce110/dce110_hw_sequencer.h" 33#include "dce100/dce100_hw_sequencer.h" 34 35/* include DCE6 register header files */ 36#include "dce/dce_6_0_d.h" 37#include "dce/dce_6_0_sh_mask.h" 38 39#define DC_LOGGER_INIT() 40 41/******************************************************************************* 42 * Private definitions 43 ******************************************************************************/ 44 45/***************************PIPE_CONTROL***********************************/ 46 47/* 48 * Check if FBC can be enabled 49 */ 50static bool dce60_should_enable_fbc(struct dc *dc, 51 struct dc_state *context, 52 uint32_t *pipe_idx) 53{ 54 uint32_t i; 55 struct pipe_ctx *pipe_ctx = NULL; 56 struct resource_context *res_ctx = &context->res_ctx; 57 unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; 58 59 60 ASSERT(dc->fbc_compressor); 61 62 /* FBC memory should be allocated */ 63 if (!dc->ctx->fbc_gpu_addr) 64 return false; 65 66 /* Only supports single display */ 67 if (context->stream_count != 1) 68 return false; 69 70 for (i = 0; i < dc->res_pool->pipe_count; i++) { 71 if (res_ctx->pipe_ctx[i].stream) { 72 73 pipe_ctx = &res_ctx->pipe_ctx[i]; 74 75 if (!pipe_ctx) 76 continue; 77 78 /* fbc not applicable on underlay pipe */ 79 if (pipe_ctx->pipe_idx != underlay_idx) { 80 *pipe_idx = i; 81 break; 82 } 83 } 84 } 85 86 if (i == dc->res_pool->pipe_count) 87 return false; 88 89 if (!pipe_ctx->stream->link) 90 return false; 91 92 /* Only supports eDP */ 93 if (pipe_ctx->stream->link->connector_signal != SIGNAL_TYPE_EDP) 94 return false; 95 96 /* PSR should not be enabled */ 97 if (pipe_ctx->stream->link->psr_settings.psr_feature_enabled) 98 return false; 99 100 /* Nothing to compress */ 101 if (!pipe_ctx->plane_state) 102 return false; 103 104 /* Only for non-linear tiling */ 105 if (pipe_ctx->plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL) 106 return false; 107 108 return true; 109} 110 111/* 112 * Enable FBC 113 */ 114static void dce60_enable_fbc( 115 struct dc *dc, 116 struct dc_state *context) 117{ 118 uint32_t pipe_idx = 0; 119 120 if (dce60_should_enable_fbc(dc, context, &pipe_idx)) { 121 /* Program GRPH COMPRESSED ADDRESS and PITCH */ 122 struct compr_addr_and_pitch_params params = {0, 0, 0}; 123 struct compressor *compr = dc->fbc_compressor; 124 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; 125 126 params.source_view_width = pipe_ctx->stream->timing.h_addressable; 127 params.source_view_height = pipe_ctx->stream->timing.v_addressable; 128 params.inst = pipe_ctx->stream_res.tg->inst; 129 compr->compr_surface_address.quad_part = dc->ctx->fbc_gpu_addr; 130 131 compr->funcs->surface_address_and_pitch(compr, ¶ms); 132 compr->funcs->set_fbc_invalidation_triggers(compr, 1); 133 134 compr->funcs->enable_fbc(compr, ¶ms); 135 } 136} 137 138 139/******************************************************************************* 140 * Front End programming 141 ******************************************************************************/ 142 143static void dce60_set_default_colors(struct pipe_ctx *pipe_ctx) 144{ 145 struct default_adjustment default_adjust = { 0 }; 146 147 default_adjust.force_hw_default = false; 148 default_adjust.in_color_space = pipe_ctx->plane_state->color_space; 149 default_adjust.out_color_space = pipe_ctx->stream->output_color_space; 150 default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW; 151 default_adjust.surface_pixel_format = pipe_ctx->plane_res.scl_data.format; 152 153 /* display color depth */ 154 default_adjust.color_depth = 155 pipe_ctx->stream->timing.display_color_depth; 156 157 /* Lb color depth */ 158 default_adjust.lb_color_depth = pipe_ctx->plane_res.scl_data.lb_params.depth; 159 160 pipe_ctx->plane_res.xfm->funcs->opp_set_csc_default( 161 pipe_ctx->plane_res.xfm, &default_adjust); 162} 163 164/******************************************************************************* 165 * In order to turn on surface we will program 166 * CRTC 167 * 168 * DCE6 has no bottom_pipe and no Blender HW 169 * We need to set 'blank_target' to false in order to turn on the display 170 * 171 * |-----------|------------|---------| 172 * |curr pipe | set_blank | | 173 * |Surface |blank_target| CRCT | 174 * |visibility | argument | | 175 * |-----------|------------|---------| 176 * | off | true | blank | 177 * | on | false | unblank | 178 * |-----------|------------|---------| 179 * 180 ******************************************************************************/ 181static void dce60_program_surface_visibility(const struct dc *dc, 182 struct pipe_ctx *pipe_ctx) 183{ 184 bool blank_target = false; 185 186 /* DCE6 has no bottom_pipe and no Blender HW */ 187 188 if (!pipe_ctx->plane_state->visible) 189 blank_target = true; 190 191 /* DCE6 skip dce_set_blender_mode() but then proceed to 'unblank' CRTC */ 192 pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, blank_target); 193 194} 195 196 197static void dce60_get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx, 198 struct tg_color *color) 199{ 200 uint32_t color_value = MAX_TG_COLOR_VALUE * (4 - pipe_ctx->stream_res.tg->inst) / 4; 201 202 switch (pipe_ctx->plane_res.scl_data.format) { 203 case PIXEL_FORMAT_ARGB8888: 204 /* set boarder color to red */ 205 color->color_r_cr = color_value; 206 break; 207 208 case PIXEL_FORMAT_ARGB2101010: 209 /* set boarder color to blue */ 210 color->color_b_cb = color_value; 211 break; 212 case PIXEL_FORMAT_420BPP8: 213 /* set boarder color to green */ 214 color->color_g_y = color_value; 215 break; 216 case PIXEL_FORMAT_420BPP10: 217 /* set boarder color to yellow */ 218 color->color_g_y = color_value; 219 color->color_r_cr = color_value; 220 break; 221 case PIXEL_FORMAT_FP16: 222 /* set boarder color to white */ 223 color->color_r_cr = color_value; 224 color->color_b_cb = color_value; 225 color->color_g_y = color_value; 226 break; 227 default: 228 break; 229 } 230} 231 232static void dce60_program_scaler(const struct dc *dc, 233 const struct pipe_ctx *pipe_ctx) 234{ 235 struct tg_color color = {0}; 236 237 /* DCE6 skips DCN TOFPGA check for transform_set_pixel_storage_depth == NULL */ 238 239 if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE) 240 dce60_get_surface_visual_confirm_color(pipe_ctx, &color); 241 else 242 color_space_to_black_color(dc, 243 pipe_ctx->stream->output_color_space, 244 &color); 245 246 pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth( 247 pipe_ctx->plane_res.xfm, 248 pipe_ctx->plane_res.scl_data.lb_params.depth, 249 &pipe_ctx->stream->bit_depth_params); 250 251 if (pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color) { 252 /* 253 * The way 420 is packed, 2 channels carry Y component, 1 channel 254 * alternate between Cb and Cr, so both channels need the pixel 255 * value for Y 256 */ 257 if (pipe_ctx->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) 258 color.color_r_cr = color.color_g_y; 259 260 pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color( 261 pipe_ctx->stream_res.tg, 262 &color); 263 } 264 265 pipe_ctx->plane_res.xfm->funcs->transform_set_scaler(pipe_ctx->plane_res.xfm, 266 &pipe_ctx->plane_res.scl_data); 267} 268 269static void 270dce60_program_front_end_for_pipe( 271 struct dc *dc, struct pipe_ctx *pipe_ctx) 272{ 273 struct mem_input *mi = pipe_ctx->plane_res.mi; 274 struct dc_plane_state *plane_state = pipe_ctx->plane_state; 275 struct xfm_grph_csc_adjustment adjust; 276 struct out_csc_color_matrix tbl_entry; 277 unsigned int i; 278 struct dce_hwseq *hws = dc->hwseq; 279 280 DC_LOGGER_INIT(); 281 memset(&tbl_entry, 0, sizeof(tbl_entry)); 282 283 memset(&adjust, 0, sizeof(adjust)); 284 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; 285 286 dce_enable_fe_clock(dc->hwseq, mi->inst, true); 287 288 dce60_set_default_colors(pipe_ctx); 289 if (pipe_ctx->stream->csc_color_matrix.enable_adjustment 290 == true) { 291 tbl_entry.color_space = 292 pipe_ctx->stream->output_color_space; 293 294 for (i = 0; i < 12; i++) 295 tbl_entry.regval[i] = 296 pipe_ctx->stream->csc_color_matrix.matrix[i]; 297 298 pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment 299 (pipe_ctx->plane_res.xfm, &tbl_entry); 300 } 301 302 if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { 303 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; 304 305 for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++) 306 adjust.temperature_matrix[i] = 307 pipe_ctx->stream->gamut_remap_matrix.matrix[i]; 308 } 309 310 pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust); 311 312 pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; 313 314 dce60_program_scaler(dc, pipe_ctx); 315 316 mi->funcs->mem_input_program_surface_config( 317 mi, 318 plane_state->format, 319 &plane_state->tiling_info, 320 &plane_state->plane_size, 321 plane_state->rotation, 322 NULL, 323 false); 324 if (mi->funcs->set_blank) 325 mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible); 326 327 if (dc->config.gpu_vm_support) 328 mi->funcs->mem_input_program_pte_vm( 329 pipe_ctx->plane_res.mi, 330 plane_state->format, 331 &plane_state->tiling_info, 332 plane_state->rotation); 333 334 /* Moved programming gamma from dc to hwss */ 335 if (pipe_ctx->plane_state->update_flags.bits.full_update || 336 pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change || 337 pipe_ctx->plane_state->update_flags.bits.gamma_change) 338 hws->funcs.set_input_transfer_func(dc, pipe_ctx, pipe_ctx->plane_state); 339 340 if (pipe_ctx->plane_state->update_flags.bits.full_update) 341 hws->funcs.set_output_transfer_func(dc, pipe_ctx, pipe_ctx->stream); 342 343 DC_LOG_SURFACE( 344 "Pipe:%d %p: addr hi:0x%x, " 345 "addr low:0x%x, " 346 "src: %d, %d, %d," 347 " %d; dst: %d, %d, %d, %d;" 348 "clip: %d, %d, %d, %d\n", 349 pipe_ctx->pipe_idx, 350 (void *) pipe_ctx->plane_state, 351 pipe_ctx->plane_state->address.grph.addr.high_part, 352 pipe_ctx->plane_state->address.grph.addr.low_part, 353 pipe_ctx->plane_state->src_rect.x, 354 pipe_ctx->plane_state->src_rect.y, 355 pipe_ctx->plane_state->src_rect.width, 356 pipe_ctx->plane_state->src_rect.height, 357 pipe_ctx->plane_state->dst_rect.x, 358 pipe_ctx->plane_state->dst_rect.y, 359 pipe_ctx->plane_state->dst_rect.width, 360 pipe_ctx->plane_state->dst_rect.height, 361 pipe_ctx->plane_state->clip_rect.x, 362 pipe_ctx->plane_state->clip_rect.y, 363 pipe_ctx->plane_state->clip_rect.width, 364 pipe_ctx->plane_state->clip_rect.height); 365 366 DC_LOG_SURFACE( 367 "Pipe %d: width, height, x, y\n" 368 "viewport:%d, %d, %d, %d\n" 369 "recout: %d, %d, %d, %d\n", 370 pipe_ctx->pipe_idx, 371 pipe_ctx->plane_res.scl_data.viewport.width, 372 pipe_ctx->plane_res.scl_data.viewport.height, 373 pipe_ctx->plane_res.scl_data.viewport.x, 374 pipe_ctx->plane_res.scl_data.viewport.y, 375 pipe_ctx->plane_res.scl_data.recout.width, 376 pipe_ctx->plane_res.scl_data.recout.height, 377 pipe_ctx->plane_res.scl_data.recout.x, 378 pipe_ctx->plane_res.scl_data.recout.y); 379} 380 381static void dce60_apply_ctx_for_surface( 382 struct dc *dc, 383 const struct dc_stream_state *stream, 384 int num_planes, 385 struct dc_state *context) 386{ 387 int i; 388 389 if (num_planes == 0) 390 return; 391 392 if (dc->fbc_compressor) 393 dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); 394 395 for (i = 0; i < dc->res_pool->pipe_count; i++) { 396 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 397 398 if (pipe_ctx->stream != stream) 399 continue; 400 401 /* Need to allocate mem before program front end for Fiji */ 402 pipe_ctx->plane_res.mi->funcs->allocate_mem_input( 403 pipe_ctx->plane_res.mi, 404 pipe_ctx->stream->timing.h_total, 405 pipe_ctx->stream->timing.v_total, 406 pipe_ctx->stream->timing.pix_clk_100hz / 10, 407 context->stream_count); 408 409 dce60_program_front_end_for_pipe(dc, pipe_ctx); 410 411 dc->hwss.update_plane_addr(dc, pipe_ctx); 412 413 dce60_program_surface_visibility(dc, pipe_ctx); 414 415 } 416 417 if (dc->fbc_compressor) 418 dce60_enable_fbc(dc, context); 419} 420 421void dce60_hw_sequencer_construct(struct dc *dc) 422{ 423 dce110_hw_sequencer_construct(dc); 424 425 dc->hwseq->funcs.enable_display_power_gating = dce100_enable_display_power_gating; 426 dc->hwss.apply_ctx_for_surface = dce60_apply_ctx_for_surface; 427 dc->hwss.cursor_lock = dce60_pipe_control_lock; 428 dc->hwss.pipe_control_lock = dce60_pipe_control_lock; 429 dc->hwss.prepare_bandwidth = dce100_prepare_bandwidth; 430 dc->hwss.optimize_bandwidth = dce100_optimize_bandwidth; 431} 432