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