1 // SPDX-License-Identifier: MIT 2 // 3 // Copyright 2024 Advanced Micro Devices, Inc. 4 5 6 #include "dml2_internal_shared_types.h" 7 #include "dml21_translation_helper.h" 8 #include "dml2_internal_types.h" 9 #include "dml21_utils.h" 10 #include "dml2_dc_resource_mgmt.h" 11 12 #include "dml2_core_dcn4_calcs.h" 13 14 15 int dml21_helper_find_dml_pipe_idx_by_stream_id(struct dml2_context *ctx, unsigned int stream_id) 16 { 17 int i; 18 for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) { 19 if (ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id_valid[i] && ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id[i] == stream_id) 20 return i; 21 } 22 23 return -1; 24 } 25 26 int dml21_find_dml_pipe_idx_by_plane_id(struct dml2_context *ctx, unsigned int plane_id) 27 { 28 int i; 29 for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) { 30 if (ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_id_valid[i] && ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_id[i] == plane_id) 31 return i; 32 } 33 34 return -1; 35 } 36 37 bool dml21_get_plane_id(const struct dc_state *state, const struct dc_plane_state *plane, unsigned int *plane_id) 38 { 39 int i, j; 40 41 if (!plane_id) 42 return false; 43 44 for (i = 0; i < state->stream_count; i++) { 45 for (j = 0; j < state->stream_status[i].plane_count; j++) { 46 if (state->stream_status[i].plane_states[j] == plane) { 47 *plane_id = (i << 16) | j; 48 return true; 49 } 50 } 51 } 52 53 return false; 54 } 55 56 unsigned int dml21_get_dc_plane_idx_from_plane_id(unsigned int plane_id) 57 { 58 return 0xffff & plane_id; 59 } 60 61 void find_valid_pipe_idx_for_stream_index(const struct dml2_context *dml_ctx, unsigned int *dml_pipe_idx, unsigned int stream_index) 62 { 63 unsigned int i = 0; 64 65 for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) { 66 if (dml_ctx->v21.mode_programming.programming->plane_programming[i].plane_descriptor->stream_index == stream_index) { 67 *dml_pipe_idx = i; 68 return; 69 } 70 } 71 } 72 73 void find_pipe_regs_idx(const struct dml2_context *dml_ctx, 74 struct pipe_ctx *pipe, unsigned int *pipe_regs_idx) 75 { 76 struct pipe_ctx *opp_head = dml_ctx->config.callbacks.get_opp_head(pipe); 77 78 *pipe_regs_idx = dml_ctx->config.callbacks.get_odm_slice_index(opp_head); 79 80 if (pipe->plane_state) 81 *pipe_regs_idx += dml_ctx->config.callbacks.get_mpc_slice_index(pipe); 82 } 83 84 /* places pipe references into pipes arrays and returns number of pipes */ 85 int dml21_find_dc_pipes_for_plane(const struct dc *in_dc, 86 struct dc_state *context, 87 struct dml2_context *dml_ctx, 88 struct pipe_ctx *dc_main_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__], 89 struct pipe_ctx *dc_phantom_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__], 90 int dml_plane_idx) 91 { 92 unsigned int dml_stream_index; 93 unsigned int main_stream_id; 94 unsigned int dc_plane_index; 95 struct dc_stream_state *dc_main_stream; 96 struct dc_stream_status *dc_main_stream_status; 97 struct dc_plane_state *dc_main_plane; 98 struct dc_stream_state *dc_phantom_stream; 99 struct dc_stream_status *dc_phantom_stream_status; 100 struct dc_plane_state *dc_phantom_plane; 101 int num_pipes = 0; 102 103 memset(dc_main_pipes, 0, sizeof(struct pipe_ctx *) * __DML2_WRAPPER_MAX_STREAMS_PLANES__); 104 memset(dc_phantom_pipes, 0, sizeof(struct pipe_ctx *) * __DML2_WRAPPER_MAX_STREAMS_PLANES__); 105 106 dml_stream_index = dml_ctx->v21.mode_programming.programming->plane_programming[dml_plane_idx].plane_descriptor->stream_index; 107 main_stream_id = dml_ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id[dml_stream_index]; 108 109 dc_main_stream = dml_ctx->config.callbacks.get_stream_from_id(context, main_stream_id); 110 dc_main_stream_status = dml_ctx->config.callbacks.get_stream_status(context, dc_main_stream); 111 if (!dc_main_stream_status) 112 return num_pipes; 113 114 /* find main plane based on id */ 115 dc_plane_index = dml21_get_dc_plane_idx_from_plane_id(dml_ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_id[dml_plane_idx]); 116 dc_main_plane = dc_main_stream_status->plane_states[dc_plane_index]; 117 118 if (dc_main_plane) { 119 num_pipes = dml_ctx->config.callbacks.get_dpp_pipes_for_plane(dc_main_plane, &context->res_ctx, dc_main_pipes); 120 } else { 121 /* stream was configured with dummy plane, so get pipes from opp head */ 122 struct pipe_ctx *otg_master_pipe = dml_ctx->config.callbacks.get_otg_master_for_stream(&context->res_ctx, dc_main_stream); 123 if (otg_master_pipe != NULL) 124 num_pipes = dml_ctx->config.callbacks.get_opp_heads_for_otg_master(otg_master_pipe, &context->res_ctx, dc_main_pipes); 125 } 126 127 /* if phantom exists, find associated pipes */ 128 dc_phantom_stream = dml_ctx->config.svp_pstate.callbacks.get_paired_subvp_stream(context, dc_main_stream); 129 if (dc_phantom_stream && num_pipes > 0) { 130 dc_phantom_stream_status = dml_ctx->config.callbacks.get_stream_status(context, dc_phantom_stream); 131 132 if (dc_phantom_stream_status) { 133 /* phantom plane will have same index as main */ 134 dc_phantom_plane = dc_phantom_stream_status->plane_states[dc_plane_index]; 135 136 if (dc_phantom_plane) { 137 /* only care about phantom pipes if they contain the phantom plane */ 138 dml_ctx->config.callbacks.get_dpp_pipes_for_plane(dc_phantom_plane, &context->res_ctx, dc_phantom_pipes); 139 } 140 } 141 } 142 143 return num_pipes; 144 } 145 146 147 void dml21_update_pipe_ctx_dchub_regs(struct dml2_display_rq_regs *rq_regs, 148 struct dml2_display_dlg_regs *disp_dlg_regs, 149 struct dml2_display_ttu_regs *disp_ttu_regs, 150 struct pipe_ctx *out) 151 { 152 memset(&out->rq_regs, 0, sizeof(out->rq_regs)); 153 out->rq_regs.rq_regs_l.chunk_size = rq_regs->rq_regs_l.chunk_size; 154 out->rq_regs.rq_regs_l.min_chunk_size = rq_regs->rq_regs_l.min_chunk_size; 155 //out->rq_regs.rq_regs_l.meta_chunk_size = rq_regs->rq_regs_l.meta_chunk_size; 156 //out->rq_regs.rq_regs_l.min_meta_chunk_size = rq_regs->rq_regs_l.min_meta_chunk_size; 157 out->rq_regs.rq_regs_l.dpte_group_size = rq_regs->rq_regs_l.dpte_group_size; 158 out->rq_regs.rq_regs_l.mpte_group_size = rq_regs->rq_regs_l.mpte_group_size; 159 out->rq_regs.rq_regs_l.swath_height = rq_regs->rq_regs_l.swath_height; 160 out->rq_regs.rq_regs_l.pte_row_height_linear = rq_regs->rq_regs_l.pte_row_height_linear; 161 162 out->rq_regs.rq_regs_c.chunk_size = rq_regs->rq_regs_c.chunk_size; 163 out->rq_regs.rq_regs_c.min_chunk_size = rq_regs->rq_regs_c.min_chunk_size; 164 //out->rq_regs.rq_regs_c.meta_chunk_size = rq_regs->rq_regs_c.meta_chunk_size; 165 //out->rq_regs.rq_regs_c.min_meta_chunk_size = rq_regs->rq_regs_c.min_meta_chunk_size; 166 out->rq_regs.rq_regs_c.dpte_group_size = rq_regs->rq_regs_c.dpte_group_size; 167 out->rq_regs.rq_regs_c.mpte_group_size = rq_regs->rq_regs_c.mpte_group_size; 168 out->rq_regs.rq_regs_c.swath_height = rq_regs->rq_regs_c.swath_height; 169 out->rq_regs.rq_regs_c.pte_row_height_linear = rq_regs->rq_regs_c.pte_row_height_linear; 170 171 out->rq_regs.drq_expansion_mode = rq_regs->drq_expansion_mode; 172 out->rq_regs.prq_expansion_mode = rq_regs->prq_expansion_mode; 173 //out->rq_regs.mrq_expansion_mode = rq_regs->mrq_expansion_mode; 174 out->rq_regs.crq_expansion_mode = rq_regs->crq_expansion_mode; 175 out->rq_regs.plane1_base_address = rq_regs->plane1_base_address; 176 out->unbounded_req = rq_regs->unbounded_request_enabled; 177 178 memset(&out->dlg_regs, 0, sizeof(out->dlg_regs)); 179 out->dlg_regs.refcyc_h_blank_end = disp_dlg_regs->refcyc_h_blank_end; 180 out->dlg_regs.dlg_vblank_end = disp_dlg_regs->dlg_vblank_end; 181 out->dlg_regs.min_dst_y_next_start = disp_dlg_regs->min_dst_y_next_start; 182 out->dlg_regs.refcyc_per_htotal = disp_dlg_regs->refcyc_per_htotal; 183 out->dlg_regs.refcyc_x_after_scaler = disp_dlg_regs->refcyc_x_after_scaler; 184 out->dlg_regs.dst_y_after_scaler = disp_dlg_regs->dst_y_after_scaler; 185 out->dlg_regs.dst_y_prefetch = disp_dlg_regs->dst_y_prefetch; 186 out->dlg_regs.dst_y_per_vm_vblank = disp_dlg_regs->dst_y_per_vm_vblank; 187 out->dlg_regs.dst_y_per_row_vblank = disp_dlg_regs->dst_y_per_row_vblank; 188 out->dlg_regs.dst_y_per_vm_flip = disp_dlg_regs->dst_y_per_vm_flip; 189 out->dlg_regs.dst_y_per_row_flip = disp_dlg_regs->dst_y_per_row_flip; 190 out->dlg_regs.ref_freq_to_pix_freq = disp_dlg_regs->ref_freq_to_pix_freq; 191 out->dlg_regs.vratio_prefetch = disp_dlg_regs->vratio_prefetch; 192 out->dlg_regs.vratio_prefetch_c = disp_dlg_regs->vratio_prefetch_c; 193 out->dlg_regs.refcyc_per_tdlut_group = disp_dlg_regs->refcyc_per_tdlut_group; 194 out->dlg_regs.refcyc_per_pte_group_vblank_l = disp_dlg_regs->refcyc_per_pte_group_vblank_l; 195 out->dlg_regs.refcyc_per_pte_group_vblank_c = disp_dlg_regs->refcyc_per_pte_group_vblank_c; 196 //out->dlg_regs.refcyc_per_meta_chunk_vblank_l = disp_dlg_regs->refcyc_per_meta_chunk_vblank_l; 197 //out->dlg_regs.refcyc_per_meta_chunk_vblank_c = disp_dlg_regs->refcyc_per_meta_chunk_vblank_c; 198 out->dlg_regs.refcyc_per_pte_group_flip_l = disp_dlg_regs->refcyc_per_pte_group_flip_l; 199 out->dlg_regs.refcyc_per_pte_group_flip_c = disp_dlg_regs->refcyc_per_pte_group_flip_c; 200 //out->dlg_regs.refcyc_per_meta_chunk_flip_l = disp_dlg_regs->refcyc_per_meta_chunk_flip_l; 201 //out->dlg_regs.refcyc_per_meta_chunk_flip_c = disp_dlg_regs->refcyc_per_meta_chunk_flip_c; 202 out->dlg_regs.dst_y_per_pte_row_nom_l = disp_dlg_regs->dst_y_per_pte_row_nom_l; 203 out->dlg_regs.dst_y_per_pte_row_nom_c = disp_dlg_regs->dst_y_per_pte_row_nom_c; 204 out->dlg_regs.refcyc_per_pte_group_nom_l = disp_dlg_regs->refcyc_per_pte_group_nom_l; 205 out->dlg_regs.refcyc_per_pte_group_nom_c = disp_dlg_regs->refcyc_per_pte_group_nom_c; 206 //out->dlg_regs.dst_y_per_meta_row_nom_l = disp_dlg_regs->dst_y_per_meta_row_nom_l; 207 //out->dlg_regs.dst_y_per_meta_row_nom_c = disp_dlg_regs->dst_y_per_meta_row_nom_c; 208 //out->dlg_regs.refcyc_per_meta_chunk_nom_l = disp_dlg_regs->refcyc_per_meta_chunk_nom_l; 209 //out->dlg_regs.refcyc_per_meta_chunk_nom_c = disp_dlg_regs->refcyc_per_meta_chunk_nom_c; 210 out->dlg_regs.refcyc_per_line_delivery_pre_l = disp_dlg_regs->refcyc_per_line_delivery_pre_l; 211 out->dlg_regs.refcyc_per_line_delivery_pre_c = disp_dlg_regs->refcyc_per_line_delivery_pre_c; 212 out->dlg_regs.refcyc_per_line_delivery_l = disp_dlg_regs->refcyc_per_line_delivery_l; 213 out->dlg_regs.refcyc_per_line_delivery_c = disp_dlg_regs->refcyc_per_line_delivery_c; 214 out->dlg_regs.refcyc_per_vm_group_vblank = disp_dlg_regs->refcyc_per_vm_group_vblank; 215 out->dlg_regs.refcyc_per_vm_group_flip = disp_dlg_regs->refcyc_per_vm_group_flip; 216 out->dlg_regs.refcyc_per_vm_req_vblank = disp_dlg_regs->refcyc_per_vm_req_vblank; 217 out->dlg_regs.refcyc_per_vm_req_flip = disp_dlg_regs->refcyc_per_vm_req_flip; 218 out->dlg_regs.dst_y_offset_cur0 = disp_dlg_regs->dst_y_offset_cur0; 219 out->dlg_regs.chunk_hdl_adjust_cur0 = disp_dlg_regs->chunk_hdl_adjust_cur0; 220 //out->dlg_regs.dst_y_offset_cur1 = disp_dlg_regs->dst_y_offset_cur1; 221 //out->dlg_regs.chunk_hdl_adjust_cur1 = disp_dlg_regs->chunk_hdl_adjust_cur1; 222 out->dlg_regs.vready_after_vcount0 = disp_dlg_regs->vready_after_vcount0; 223 out->dlg_regs.dst_y_delta_drq_limit = disp_dlg_regs->dst_y_delta_drq_limit; 224 out->dlg_regs.refcyc_per_vm_dmdata = disp_dlg_regs->refcyc_per_vm_dmdata; 225 out->dlg_regs.dmdata_dl_delta = disp_dlg_regs->dmdata_dl_delta; 226 227 memset(&out->ttu_regs, 0, sizeof(out->ttu_regs)); 228 out->ttu_regs.qos_level_low_wm = disp_ttu_regs->qos_level_low_wm; 229 out->ttu_regs.qos_level_high_wm = disp_ttu_regs->qos_level_high_wm; 230 out->ttu_regs.min_ttu_vblank = disp_ttu_regs->min_ttu_vblank; 231 out->ttu_regs.qos_level_flip = disp_ttu_regs->qos_level_flip; 232 out->ttu_regs.refcyc_per_req_delivery_l = disp_ttu_regs->refcyc_per_req_delivery_l; 233 out->ttu_regs.refcyc_per_req_delivery_c = disp_ttu_regs->refcyc_per_req_delivery_c; 234 out->ttu_regs.refcyc_per_req_delivery_cur0 = disp_ttu_regs->refcyc_per_req_delivery_cur0; 235 //out->ttu_regs.refcyc_per_req_delivery_cur1 = disp_ttu_regs->refcyc_per_req_delivery_cur1; 236 out->ttu_regs.refcyc_per_req_delivery_pre_l = disp_ttu_regs->refcyc_per_req_delivery_pre_l; 237 out->ttu_regs.refcyc_per_req_delivery_pre_c = disp_ttu_regs->refcyc_per_req_delivery_pre_c; 238 out->ttu_regs.refcyc_per_req_delivery_pre_cur0 = disp_ttu_regs->refcyc_per_req_delivery_pre_cur0; 239 //out->ttu_regs.refcyc_per_req_delivery_pre_cur1 = disp_ttu_regs->refcyc_per_req_delivery_pre_cur1; 240 out->ttu_regs.qos_level_fixed_l = disp_ttu_regs->qos_level_fixed_l; 241 out->ttu_regs.qos_level_fixed_c = disp_ttu_regs->qos_level_fixed_c; 242 out->ttu_regs.qos_level_fixed_cur0 = disp_ttu_regs->qos_level_fixed_cur0; 243 //out->ttu_regs.qos_level_fixed_cur1 = disp_ttu_regs->qos_level_fixed_cur1; 244 out->ttu_regs.qos_ramp_disable_l = disp_ttu_regs->qos_ramp_disable_l; 245 out->ttu_regs.qos_ramp_disable_c = disp_ttu_regs->qos_ramp_disable_c; 246 out->ttu_regs.qos_ramp_disable_cur0 = disp_ttu_regs->qos_ramp_disable_cur0; 247 //out->ttu_regs.qos_ramp_disable_cur1 = disp_ttu_regs->qos_ramp_disable_cur1; 248 } 249 250 void dml21_populate_mall_allocation_size(struct dc_state *context, 251 struct dml2_context *in_ctx, 252 struct dml2_per_plane_programming *pln_prog, 253 struct pipe_ctx *dc_pipe) 254 { 255 256 /* Reuse MALL Allocation Sizes logic from dcn32_fpu.c */ 257 /* Count from active, top pipes per plane only. Only add mall_ss_size_bytes for each unique plane. */ 258 if (dc_pipe->stream && dc_pipe->plane_state && 259 (dc_pipe->top_pipe == NULL || 260 dc_pipe->plane_state != dc_pipe->top_pipe->plane_state) && 261 dc_pipe->prev_odm_pipe == NULL) { 262 /* SS: all active surfaces stored in MALL */ 263 if (in_ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(context, dc_pipe) != SUBVP_PHANTOM) { 264 dc_pipe->surface_size_in_mall_bytes = pln_prog->surface_size_mall_bytes; 265 context->bw_ctx.bw.dcn.mall_ss_size_bytes += dc_pipe->surface_size_in_mall_bytes; 266 } else { 267 /* SUBVP: phantom surfaces only stored in MALL */ 268 dc_pipe->surface_size_in_mall_bytes = pln_prog->svp_size_mall_bytes; 269 context->bw_ctx.bw.dcn.mall_subvp_size_bytes += dc_pipe->surface_size_in_mall_bytes; 270 } 271 } 272 } 273 274 bool check_dp2p0_output_encoder(const struct pipe_ctx *pipe_ctx) 275 { 276 /* If this assert is hit then we have a link encoder dynamic management issue */ 277 ASSERT(pipe_ctx->stream_res.hpo_dp_stream_enc ? pipe_ctx->link_res.hpo_dp_link_enc != NULL : true); 278 return (pipe_ctx->stream_res.hpo_dp_stream_enc && 279 pipe_ctx->link_res.hpo_dp_link_enc && 280 dc_is_dp_signal(pipe_ctx->stream->signal)); 281 } 282 283 void dml21_program_dc_pipe(struct dml2_context *dml_ctx, struct dc_state *context, struct pipe_ctx *pipe_ctx, struct dml2_per_plane_programming *pln_prog, 284 struct dml2_per_stream_programming *stream_prog) 285 { 286 unsigned int pipe_reg_index = 0; 287 288 dml21_populate_pipe_ctx_dlg_params(dml_ctx, context, pipe_ctx, stream_prog); 289 find_pipe_regs_idx(dml_ctx, pipe_ctx, &pipe_reg_index); 290 291 if (dml_ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) { 292 memcpy(&pipe_ctx->hubp_regs, pln_prog->phantom_plane.pipe_regs[pipe_reg_index], sizeof(struct dml2_dchub_per_pipe_register_set)); 293 pipe_ctx->unbounded_req = false; 294 295 /* legacy only, should be removed later */ 296 dml21_update_pipe_ctx_dchub_regs(&pln_prog->phantom_plane.pipe_regs[pipe_reg_index]->rq_regs, 297 &pln_prog->phantom_plane.pipe_regs[pipe_reg_index]->dlg_regs, 298 &pln_prog->phantom_plane.pipe_regs[pipe_reg_index]->ttu_regs, pipe_ctx); 299 300 pipe_ctx->det_buffer_size_kb = 0; 301 } else { 302 memcpy(&pipe_ctx->hubp_regs, pln_prog->pipe_regs[pipe_reg_index], sizeof(struct dml2_dchub_per_pipe_register_set)); 303 pipe_ctx->unbounded_req = pln_prog->pipe_regs[pipe_reg_index]->rq_regs.unbounded_request_enabled; 304 305 /* legacy only, should be removed later */ 306 dml21_update_pipe_ctx_dchub_regs(&pln_prog->pipe_regs[pipe_reg_index]->rq_regs, 307 &pln_prog->pipe_regs[pipe_reg_index]->dlg_regs, 308 &pln_prog->pipe_regs[pipe_reg_index]->ttu_regs, pipe_ctx); 309 310 pipe_ctx->det_buffer_size_kb = pln_prog->pipe_regs[pipe_reg_index]->det_size * 64; 311 } 312 313 pipe_ctx->plane_res.bw.dppclk_khz = pln_prog->min_clocks.dcn4.dppclk_khz; 314 if (context->bw_ctx.bw.dcn.clk.dppclk_khz < pipe_ctx->plane_res.bw.dppclk_khz) 315 context->bw_ctx.bw.dcn.clk.dppclk_khz = pipe_ctx->plane_res.bw.dppclk_khz; 316 317 dml21_populate_mall_allocation_size(context, dml_ctx, pln_prog, pipe_ctx); 318 memcpy(&context->bw_ctx.bw.dcn.mcache_allocations[pipe_ctx->pipe_idx], &pln_prog->mcache_allocation, sizeof(struct dml2_mcache_surface_allocation)); 319 320 dml21_set_dc_p_state_type(pipe_ctx, stream_prog); 321 } 322 323 static struct dc_stream_state *dml21_add_phantom_stream(struct dml2_context *dml_ctx, 324 const struct dc *dc, 325 struct dc_state *context, 326 struct dc_stream_state *main_stream, 327 struct dml2_per_stream_programming *stream_programming) 328 { 329 struct dc_stream_state *phantom_stream; 330 struct dml2_stream_parameters *phantom_stream_descriptor = &stream_programming->phantom_stream.descriptor; 331 332 phantom_stream = dml_ctx->config.svp_pstate.callbacks.create_phantom_stream(dc, context, main_stream); 333 if (!phantom_stream) 334 return NULL; 335 336 /* copy details of phantom stream from main */ 337 memcpy(&phantom_stream->timing, &main_stream->timing, sizeof(phantom_stream->timing)); 338 memcpy(&phantom_stream->src, &main_stream->src, sizeof(phantom_stream->src)); 339 memcpy(&phantom_stream->dst, &main_stream->dst, sizeof(phantom_stream->dst)); 340 341 /* modify timing for phantom */ 342 phantom_stream->timing.v_front_porch = phantom_stream_descriptor->timing.v_front_porch; 343 phantom_stream->timing.v_addressable = phantom_stream_descriptor->timing.v_active; 344 phantom_stream->timing.v_total = phantom_stream_descriptor->timing.v_total; 345 phantom_stream->timing.flags.DSC = 0; // phantom always has DSC disabled 346 347 phantom_stream->dst.y = 0; 348 phantom_stream->dst.height = stream_programming->phantom_stream.descriptor.timing.v_active; 349 350 phantom_stream->src.y = 0; 351 phantom_stream->src.height = (double)phantom_stream_descriptor->timing.v_active * (double)main_stream->src.height / (double)main_stream->dst.height; 352 353 phantom_stream->use_dynamic_meta = false; 354 355 dml_ctx->config.svp_pstate.callbacks.add_phantom_stream(dc, context, phantom_stream, main_stream); 356 357 return phantom_stream; 358 } 359 360 static struct dc_plane_state *dml21_add_phantom_plane(struct dml2_context *dml_ctx, 361 const struct dc *dc, 362 struct dc_state *context, 363 struct dc_stream_state *phantom_stream, 364 struct dc_plane_state *main_plane, 365 struct dml2_per_plane_programming *plane_programming) 366 { 367 struct dc_plane_state *phantom_plane; 368 369 phantom_plane = dml_ctx->config.svp_pstate.callbacks.create_phantom_plane(dc, context, main_plane); 370 if (!phantom_plane) 371 return NULL; 372 373 phantom_plane->format = main_plane->format; 374 phantom_plane->rotation = main_plane->rotation; 375 phantom_plane->visible = main_plane->visible; 376 377 memcpy(&phantom_plane->address, &main_plane->address, sizeof(phantom_plane->address)); 378 memcpy(&phantom_plane->scaling_quality, &main_plane->scaling_quality, 379 sizeof(phantom_plane->scaling_quality)); 380 memcpy(&phantom_plane->src_rect, &main_plane->src_rect, sizeof(phantom_plane->src_rect)); 381 memcpy(&phantom_plane->dst_rect, &main_plane->dst_rect, sizeof(phantom_plane->dst_rect)); 382 memcpy(&phantom_plane->clip_rect, &main_plane->clip_rect, sizeof(phantom_plane->clip_rect)); 383 memcpy(&phantom_plane->plane_size, &main_plane->plane_size, 384 sizeof(phantom_plane->plane_size)); 385 memcpy(&phantom_plane->tiling_info, &main_plane->tiling_info, 386 sizeof(phantom_plane->tiling_info)); 387 memcpy(&phantom_plane->dcc, &main_plane->dcc, sizeof(phantom_plane->dcc)); 388 389 phantom_plane->format = main_plane->format; 390 phantom_plane->rotation = main_plane->rotation; 391 phantom_plane->visible = main_plane->visible; 392 393 /* Shadow pipe has small viewport. */ 394 phantom_plane->clip_rect.y = 0; 395 phantom_plane->clip_rect.height = phantom_stream->src.height; 396 397 dml_ctx->config.svp_pstate.callbacks.add_phantom_plane(dc, phantom_stream, phantom_plane, context); 398 399 return phantom_plane; 400 } 401 402 void dml21_handle_phantom_streams_planes(const struct dc *dc, struct dc_state *context, struct dml2_context *dml_ctx) 403 { 404 unsigned int dml_stream_index, dml_plane_index, dc_plane_index; 405 struct dc_stream_state *main_stream; 406 struct dc_stream_status *main_stream_status; 407 struct dc_stream_state *phantom_stream; 408 struct dc_plane_state *main_plane; 409 bool phantoms_added = false; 410 411 /* create phantom streams and planes and add to context */ 412 for (dml_stream_index = 0; dml_stream_index < dml_ctx->v21.mode_programming.programming->display_config.num_streams; dml_stream_index++) { 413 /* iterate through DML streams looking for phantoms */ 414 if (dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_index].phantom_stream.enabled) { 415 /* find associated dc stream */ 416 main_stream = dml_ctx->config.callbacks.get_stream_from_id(context, 417 dml_ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id[dml_stream_index]); 418 419 main_stream_status = dml_ctx->config.callbacks.get_stream_status(context, main_stream); 420 421 if (!main_stream_status || main_stream_status->plane_count == 0) 422 continue; 423 424 /* create phantom stream for subvp enabled stream */ 425 phantom_stream = dml21_add_phantom_stream(dml_ctx, 426 dc, 427 context, 428 main_stream, 429 &dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_index]); 430 431 if (!phantom_stream) 432 continue; 433 434 /* iterate through DML planes associated with this stream */ 435 for (dml_plane_index = 0; dml_plane_index < dml_ctx->v21.mode_programming.programming->display_config.num_planes; dml_plane_index++) { 436 if (dml_ctx->v21.mode_programming.programming->plane_programming[dml_plane_index].plane_descriptor->stream_index == dml_stream_index) { 437 /* find associated dc plane */ 438 dc_plane_index = dml21_get_dc_plane_idx_from_plane_id(dml_ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_id[dml_plane_index]); 439 main_plane = main_stream_status->plane_states[dc_plane_index]; 440 441 /* create phantom planes for subvp enabled plane */ 442 dml21_add_phantom_plane(dml_ctx, 443 dc, 444 context, 445 phantom_stream, 446 main_plane, 447 &dml_ctx->v21.mode_programming.programming->plane_programming[dml_plane_index]); 448 449 phantoms_added = true; 450 } 451 } 452 } 453 } 454 455 if (phantoms_added) 456 dml2_map_dc_pipes(dml_ctx, context, NULL, &dml_ctx->v21.dml_to_dc_pipe_mapping, dc->current_state); 457 } 458 459 void dml21_build_fams2_programming(const struct dc *dc, 460 struct dc_state *context, 461 struct dml2_context *dml_ctx) 462 { 463 int i, j, k; 464 465 /* reset fams2 data */ 466 context->bw_ctx.bw.dcn.fams2_stream_count = 0; 467 memset(&context->bw_ctx.bw.dcn.fams2_stream_params, 0, sizeof(struct dmub_fams2_stream_static_state) * DML2_MAX_PLANES); 468 469 if (!dml_ctx->v21.mode_programming.programming->fams2_required) 470 return; 471 472 for (i = 0; i < context->stream_count; i++) { 473 int dml_stream_idx; 474 struct dc_stream_state *phantom_stream; 475 struct dc_stream_status *phantom_status; 476 477 struct dmub_fams2_stream_static_state *static_state = &context->bw_ctx.bw.dcn.fams2_stream_params[context->bw_ctx.bw.dcn.fams2_stream_count]; 478 479 struct dc_stream_state *stream = context->streams[i]; 480 481 if (context->stream_status[i].plane_count == 0 || 482 dml_ctx->config.svp_pstate.callbacks.get_stream_subvp_type(context, stream) == SUBVP_PHANTOM) { 483 /* can ignore blanked or phantom streams */ 484 continue; 485 } 486 487 dml_stream_idx = dml21_helper_find_dml_pipe_idx_by_stream_id(dml_ctx, stream->stream_id); 488 if (dml_stream_idx < 0) { 489 ASSERT(dml_stream_idx >= 0); 490 continue; 491 } 492 493 /* copy static state from PMO */ 494 memcpy(static_state, 495 &dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_params, 496 sizeof(struct dmub_fams2_stream_static_state)); 497 498 /* get information from context */ 499 static_state->num_planes = context->stream_status[i].plane_count; 500 static_state->otg_inst = context->stream_status[i].primary_otg_inst; 501 502 /* populate pipe masks for planes */ 503 for (j = 0; j < context->stream_status[i].plane_count; j++) { 504 for (k = 0; k < dc->res_pool->pipe_count; k++) { 505 if (context->res_ctx.pipe_ctx[k].stream && 506 context->res_ctx.pipe_ctx[k].stream->stream_id == stream->stream_id && 507 context->res_ctx.pipe_ctx[k].plane_state == context->stream_status[i].plane_states[j]) { 508 static_state->pipe_mask |= (1 << k); 509 static_state->plane_pipe_masks[j] |= (1 << k); 510 } 511 } 512 } 513 514 /* get per method programming */ 515 switch (static_state->type) { 516 case FAMS2_STREAM_TYPE_VBLANK: 517 case FAMS2_STREAM_TYPE_VACTIVE: 518 case FAMS2_STREAM_TYPE_DRR: 519 break; 520 case FAMS2_STREAM_TYPE_SUBVP: 521 phantom_stream = dml_ctx->config.svp_pstate.callbacks.get_paired_subvp_stream(context, stream); 522 if (!phantom_stream) 523 break; 524 525 phantom_status = dml_ctx->config.callbacks.get_stream_status(context, phantom_stream); 526 527 /* phantom status should always be present */ 528 ASSERT(phantom_status); 529 static_state->sub_state.subvp.phantom_otg_inst = phantom_status->primary_otg_inst; 530 531 /* populate pipe masks for phantom planes */ 532 for (j = 0; j < phantom_status->plane_count; j++) { 533 for (k = 0; k < dc->res_pool->pipe_count; k++) { 534 if (context->res_ctx.pipe_ctx[k].stream && 535 context->res_ctx.pipe_ctx[k].stream->stream_id == phantom_stream->stream_id && 536 context->res_ctx.pipe_ctx[k].plane_state == phantom_status->plane_states[j]) { 537 static_state->sub_state.subvp.phantom_pipe_mask |= (1 << k); 538 static_state->sub_state.subvp.phantom_plane_pipe_masks[j] |= (1 << k); 539 } 540 } 541 } 542 break; 543 default: 544 ASSERT(false); 545 break; 546 } 547 548 context->bw_ctx.bw.dcn.fams2_stream_count++; 549 } 550 551 context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = context->bw_ctx.bw.dcn.fams2_stream_count > 0; 552 } 553 554 bool dml21_is_plane1_enabled(enum dml2_source_format_class source_format) 555 { 556 return source_format >= dml2_420_8 && source_format <= dml2_rgbe_alpha; 557 } 558