1 // SPDX-License-Identifier: MIT
2 //
3 // Copyright 2024 Advanced Micro Devices, Inc.
4
5
6 #include "dml21_wrapper.h"
7 #include "dml2_core_dcn4_calcs.h"
8 #include "dml2_internal_shared_types.h"
9 #include "dml2_internal_types.h"
10 #include "dml21_utils.h"
11 #include "dml21_translation_helper.h"
12 #include "bounding_boxes/dcn4_soc_bb.h"
13 #include "bounding_boxes/dcn3_soc_bb.h"
14
dml21_init_socbb_params(struct dml2_initialize_instance_in_out * dml_init,const struct dml2_configuration_options * config,const struct dc * in_dc)15 static void dml21_init_socbb_params(struct dml2_initialize_instance_in_out *dml_init,
16 const struct dml2_configuration_options *config,
17 const struct dc *in_dc)
18 {
19 const struct dml2_soc_bb *soc_bb;
20 const struct dml2_soc_qos_parameters *qos_params;
21
22 switch (in_dc->ctx->dce_version) {
23 case DCN_VERSION_3_2: // TODO : Temporary for N-1 validation. Remove this after N-1 validation phase is complete.
24 soc_bb = &dml2_socbb_dcn31;
25 qos_params = &dml_dcn31_soc_qos_params;
26 break;
27 case DCN_VERSION_4_01:
28 default:
29 if (config->bb_from_dmub)
30 soc_bb = config->bb_from_dmub;
31 else
32 soc_bb = &dml2_socbb_dcn401;
33
34 qos_params = &dml_dcn4_variant_a_soc_qos_params;
35 }
36
37 /* patch soc bb */
38 memcpy(&dml_init->soc_bb, soc_bb, sizeof(struct dml2_soc_bb));
39
40 /* patch qos params */
41 memcpy(&dml_init->soc_bb.qos_parameters, qos_params, sizeof(struct dml2_soc_qos_parameters));
42 }
43
dml21_external_socbb_params(struct dml2_initialize_instance_in_out * dml_init,const struct dml2_configuration_options * config)44 static void dml21_external_socbb_params(struct dml2_initialize_instance_in_out *dml_init,
45 const struct dml2_configuration_options *config)
46 {
47 memcpy(&dml_init->soc_bb, &config->external_socbb_ip_params->soc_bb, sizeof(struct dml2_soc_bb));
48 }
49
dml21_external_ip_params(struct dml2_initialize_instance_in_out * dml_init,const struct dml2_configuration_options * config)50 static void dml21_external_ip_params(struct dml2_initialize_instance_in_out *dml_init,
51 const struct dml2_configuration_options *config)
52 {
53 memcpy(&dml_init->ip_caps, &config->external_socbb_ip_params->ip_params, sizeof(struct dml2_ip_capabilities));
54 }
55
dml21_init_ip_params(struct dml2_initialize_instance_in_out * dml_init,const struct dml2_configuration_options * config,const struct dc * in_dc)56 static void dml21_init_ip_params(struct dml2_initialize_instance_in_out *dml_init,
57 const struct dml2_configuration_options *config,
58 const struct dc *in_dc)
59 {
60 const struct dml2_ip_capabilities *ip_caps;
61
62 switch (in_dc->ctx->dce_version) {
63 case DCN_VERSION_3_2: // TODO : Temporary for N-1 validation. Remove this after N-1 validation phase is complete.
64 ip_caps = &dml2_dcn31_max_ip_caps;
65 break;
66 case DCN_VERSION_4_01:
67 default:
68 ip_caps = &dml2_dcn401_max_ip_caps;
69 }
70
71 memcpy(&dml_init->ip_caps, ip_caps, sizeof(struct dml2_ip_capabilities));
72 }
73
dml21_initialize_soc_bb_params(struct dml2_initialize_instance_in_out * dml_init,const struct dml2_configuration_options * config,const struct dc * in_dc)74 void dml21_initialize_soc_bb_params(struct dml2_initialize_instance_in_out *dml_init,
75 const struct dml2_configuration_options *config,
76 const struct dc *in_dc)
77 {
78 if (config->use_native_soc_bb_construction)
79 dml21_init_socbb_params(dml_init, config, in_dc);
80 else
81 dml21_external_socbb_params(dml_init, config);
82 }
83
dml21_initialize_ip_params(struct dml2_initialize_instance_in_out * dml_init,const struct dml2_configuration_options * config,const struct dc * in_dc)84 void dml21_initialize_ip_params(struct dml2_initialize_instance_in_out *dml_init,
85 const struct dml2_configuration_options *config,
86 const struct dc *in_dc)
87 {
88 if (config->use_native_soc_bb_construction)
89 dml21_init_ip_params(dml_init, config, in_dc);
90 else
91 dml21_external_ip_params(dml_init, config);
92 }
93
dml21_apply_soc_bb_overrides(struct dml2_initialize_instance_in_out * dml_init,const struct dml2_configuration_options * config,const struct dc * in_dc)94 void dml21_apply_soc_bb_overrides(struct dml2_initialize_instance_in_out *dml_init,
95 const struct dml2_configuration_options *config, const struct dc *in_dc)
96 {
97 int i;
98
99 const struct clk_bw_params *dc_bw_params = in_dc->clk_mgr->bw_params;
100 const struct clk_limit_table *dc_clk_table = &dc_bw_params->clk_table;
101 struct dml2_soc_bb *dml_soc_bb = &dml_init->soc_bb;
102 struct dml2_soc_state_table *dml_clk_table = &dml_soc_bb->clk_table;
103
104 /* override clocks if smu is present */
105 if (in_dc->clk_mgr->funcs->is_smu_present && in_dc->clk_mgr->funcs->is_smu_present(in_dc->clk_mgr)) {
106 /* dcfclk */
107 if (dc_clk_table->num_entries_per_clk.num_dcfclk_levels) {
108 dml_clk_table->dcfclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dcfclk_levels;
109 for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) {
110 if (i < dml_clk_table->dcfclk.num_clk_values) {
111 if (config->use_clock_dc_limits && dc_bw_params->dc_mode_limit.dcfclk_mhz &&
112 dc_clk_table->entries[i].dcfclk_mhz > dc_bw_params->dc_mode_limit.dcfclk_mhz) {
113 if (i == 0 || dc_clk_table->entries[i-1].dcfclk_mhz < dc_bw_params->dc_mode_limit.dcfclk_mhz) {
114 dml_clk_table->dcfclk.clk_values_khz[i] = dc_bw_params->dc_mode_limit.dcfclk_mhz * 1000;
115 dml_clk_table->dcfclk.num_clk_values = i + 1;
116 } else {
117 dml_clk_table->dcfclk.clk_values_khz[i] = 0;
118 dml_clk_table->dcfclk.num_clk_values = i;
119 }
120 } else {
121 dml_clk_table->dcfclk.clk_values_khz[i] = dc_clk_table->entries[i].dcfclk_mhz * 1000;
122 }
123 } else {
124 dml_clk_table->dcfclk.clk_values_khz[i] = 0;
125 }
126 }
127 }
128
129 /* fclk */
130 if (dc_clk_table->num_entries_per_clk.num_fclk_levels) {
131 dml_clk_table->fclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_fclk_levels;
132 for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) {
133 if (i < dml_clk_table->fclk.num_clk_values) {
134 if (config->use_clock_dc_limits && dc_bw_params->dc_mode_limit.fclk_mhz &&
135 dc_clk_table->entries[i].fclk_mhz > dc_bw_params->dc_mode_limit.fclk_mhz) {
136 if (i == 0 || dc_clk_table->entries[i-1].fclk_mhz < dc_bw_params->dc_mode_limit.fclk_mhz) {
137 dml_clk_table->fclk.clk_values_khz[i] = dc_bw_params->dc_mode_limit.fclk_mhz * 1000;
138 dml_clk_table->fclk.num_clk_values = i + 1;
139 } else {
140 dml_clk_table->fclk.clk_values_khz[i] = 0;
141 dml_clk_table->fclk.num_clk_values = i;
142 }
143 } else {
144 dml_clk_table->fclk.clk_values_khz[i] = dc_clk_table->entries[i].fclk_mhz * 1000;
145 }
146 } else {
147 dml_clk_table->fclk.clk_values_khz[i] = 0;
148 }
149 }
150 }
151
152 /* uclk */
153 if (dc_clk_table->num_entries_per_clk.num_memclk_levels) {
154 dml_clk_table->uclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_memclk_levels;
155 for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) {
156 if (i < dml_clk_table->uclk.num_clk_values) {
157 if (config->use_clock_dc_limits && dc_bw_params->dc_mode_limit.memclk_mhz &&
158 dc_clk_table->entries[i].memclk_mhz > dc_bw_params->dc_mode_limit.memclk_mhz) {
159 if (i == 0 || dc_clk_table->entries[i-1].memclk_mhz < dc_bw_params->dc_mode_limit.memclk_mhz) {
160 dml_clk_table->uclk.clk_values_khz[i] = dc_bw_params->dc_mode_limit.memclk_mhz * 1000;
161 dml_clk_table->uclk.num_clk_values = i + 1;
162 } else {
163 dml_clk_table->uclk.clk_values_khz[i] = 0;
164 dml_clk_table->uclk.num_clk_values = i;
165 }
166 } else {
167 dml_clk_table->uclk.clk_values_khz[i] = dc_clk_table->entries[i].memclk_mhz * 1000;
168 }
169 } else {
170 dml_clk_table->uclk.clk_values_khz[i] = 0;
171 }
172 }
173 }
174
175 /* dispclk */
176 if (dc_clk_table->num_entries_per_clk.num_dispclk_levels) {
177 dml_clk_table->dispclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dispclk_levels;
178 for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) {
179 if (i < dml_clk_table->dispclk.num_clk_values) {
180 if (config->use_clock_dc_limits && dc_bw_params->dc_mode_limit.dispclk_mhz &&
181 dc_clk_table->entries[i].dispclk_mhz > dc_bw_params->dc_mode_limit.dispclk_mhz) {
182 if (i == 0 || dc_clk_table->entries[i-1].dispclk_mhz < dc_bw_params->dc_mode_limit.dispclk_mhz) {
183 dml_clk_table->dispclk.clk_values_khz[i] = dc_bw_params->dc_mode_limit.dispclk_mhz * 1000;
184 dml_clk_table->dispclk.num_clk_values = i + 1;
185 } else {
186 dml_clk_table->dispclk.clk_values_khz[i] = 0;
187 dml_clk_table->dispclk.num_clk_values = i;
188 }
189 } else {
190 dml_clk_table->dispclk.clk_values_khz[i] = dc_clk_table->entries[i].dispclk_mhz * 1000;
191 }
192 } else {
193 dml_clk_table->dispclk.clk_values_khz[i] = 0;
194 }
195 }
196 }
197
198 /* dppclk */
199 if (dc_clk_table->num_entries_per_clk.num_dppclk_levels) {
200 dml_clk_table->dppclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dppclk_levels;
201 for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) {
202 if (i < dml_clk_table->dppclk.num_clk_values) {
203 if (config->use_clock_dc_limits && dc_bw_params->dc_mode_limit.dppclk_mhz &&
204 dc_clk_table->entries[i].dppclk_mhz > dc_bw_params->dc_mode_limit.dppclk_mhz) {
205 if (i == 0 || dc_clk_table->entries[i-1].dppclk_mhz < dc_bw_params->dc_mode_limit.dppclk_mhz) {
206 dml_clk_table->dppclk.clk_values_khz[i] = dc_bw_params->dc_mode_limit.dppclk_mhz * 1000;
207 dml_clk_table->dppclk.num_clk_values = i + 1;
208 } else {
209 dml_clk_table->dppclk.clk_values_khz[i] = 0;
210 dml_clk_table->dppclk.num_clk_values = i;
211 }
212 } else {
213 dml_clk_table->dppclk.clk_values_khz[i] = dc_clk_table->entries[i].dppclk_mhz * 1000;
214 }
215 } else {
216 dml_clk_table->dppclk.clk_values_khz[i] = 0;
217 }
218 }
219 }
220
221 /* dtbclk */
222 if (dc_clk_table->num_entries_per_clk.num_dtbclk_levels) {
223 dml_clk_table->dtbclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dtbclk_levels;
224 for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) {
225 if (i < dml_clk_table->dtbclk.num_clk_values) {
226 if (config->use_clock_dc_limits && dc_bw_params->dc_mode_limit.dtbclk_mhz &&
227 dc_clk_table->entries[i].dtbclk_mhz > dc_bw_params->dc_mode_limit.dtbclk_mhz) {
228 if (i == 0 || dc_clk_table->entries[i-1].dtbclk_mhz < dc_bw_params->dc_mode_limit.dtbclk_mhz) {
229 dml_clk_table->dtbclk.clk_values_khz[i] = dc_bw_params->dc_mode_limit.dtbclk_mhz * 1000;
230 dml_clk_table->dtbclk.num_clk_values = i + 1;
231 } else {
232 dml_clk_table->dtbclk.clk_values_khz[i] = 0;
233 dml_clk_table->dtbclk.num_clk_values = i;
234 }
235 } else {
236 dml_clk_table->dtbclk.clk_values_khz[i] = dc_clk_table->entries[i].dtbclk_mhz * 1000;
237 }
238 } else {
239 dml_clk_table->dtbclk.clk_values_khz[i] = 0;
240 }
241 }
242 }
243
244 /* socclk */
245 if (dc_clk_table->num_entries_per_clk.num_socclk_levels) {
246 dml_clk_table->socclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_socclk_levels;
247 for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) {
248 if (i < dml_clk_table->socclk.num_clk_values) {
249 if (config->use_clock_dc_limits && dc_bw_params->dc_mode_limit.socclk_mhz &&
250 dc_clk_table->entries[i].socclk_mhz > dc_bw_params->dc_mode_limit.socclk_mhz) {
251 if (i == 0 || dc_clk_table->entries[i-1].socclk_mhz < dc_bw_params->dc_mode_limit.socclk_mhz) {
252 dml_clk_table->socclk.clk_values_khz[i] = dc_bw_params->dc_mode_limit.socclk_mhz * 1000;
253 dml_clk_table->socclk.num_clk_values = i + 1;
254 } else {
255 dml_clk_table->socclk.clk_values_khz[i] = 0;
256 dml_clk_table->socclk.num_clk_values = i;
257 }
258 } else {
259 dml_clk_table->socclk.clk_values_khz[i] = dc_clk_table->entries[i].socclk_mhz * 1000;
260 }
261 } else {
262 dml_clk_table->socclk.clk_values_khz[i] = 0;
263 }
264 }
265 }
266
267 /* do not override phyclks for now */
268 /* phyclk */
269 // dml_clk_table->phyclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_phyclk_levels;
270 // for (i = 0; i < DML_MAX_CLK_TABLE_SIZE; i++) {
271 // dml_clk_table->phyclk.clk_values_khz[i] = dc_clk_table->entries[i].phyclk_mhz * 1000;
272 // }
273
274 /* phyclk_d18 */
275 // dml_clk_table->phyclk_d18.num_clk_values = dc_clk_table->num_entries_per_clk.num_phyclk_d18_levels;
276 // for (i = 0; i < DML_MAX_CLK_TABLE_SIZE; i++) {
277 // dml_clk_table->phyclk_d18.clk_values_khz[i] = dc_clk_table->entries[i].phyclk_d18_mhz * 1000;
278 // }
279
280 /* phyclk_d32 */
281 // dml_clk_table->phyclk_d32.num_clk_values = dc_clk_table->num_entries_per_clk.num_phyclk_d32_levels;
282 // for (i = 0; i < DML_MAX_CLK_TABLE_SIZE; i++) {
283 // dml_clk_table->phyclk_d32.clk_values_khz[i] = dc_clk_table->entries[i].phyclk_d32_mhz * 1000;
284 // }
285 }
286
287 dml_soc_bb->dchub_refclk_mhz = in_dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000;
288 dml_soc_bb->dprefclk_mhz = in_dc->clk_mgr->dprefclk_khz / 1000;
289 dml_soc_bb->xtalclk_mhz = in_dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency / 1000;
290 dml_soc_bb->dispclk_dppclk_vco_speed_mhz = in_dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
291
292 /* override bounding box paramters from VBIOS */
293 if (in_dc->ctx->dc_bios->bb_info.dram_clock_change_latency_100ns > 0)
294 dml_soc_bb->power_management_parameters.dram_clk_change_blackout_us =
295 (in_dc->ctx->dc_bios->bb_info.dram_clock_change_latency_100ns + 9) / 10;
296
297 if (in_dc->ctx->dc_bios->bb_info.dram_sr_enter_exit_latency_100ns > 0)
298 dml_soc_bb->power_management_parameters.stutter_enter_plus_exit_latency_us =
299 (in_dc->ctx->dc_bios->bb_info.dram_sr_enter_exit_latency_100ns + 9) / 10;
300
301 if (in_dc->ctx->dc_bios->bb_info.dram_sr_exit_latency_100ns > 0)
302 dml_soc_bb->power_management_parameters.stutter_exit_latency_us =
303 (in_dc->ctx->dc_bios->bb_info.dram_sr_exit_latency_100ns + 9) / 10;
304
305 if (in_dc->ctx->dc_bios->vram_info.num_chans) {
306 dml_clk_table->dram_config.channel_count = in_dc->ctx->dc_bios->vram_info.num_chans;
307 dml_soc_bb->mall_allocated_for_dcn_mbytes = in_dc->caps.mall_size_total / 1048576;
308 }
309
310 if (in_dc->ctx->dc_bios->vram_info.dram_channel_width_bytes) {
311 dml_clk_table->dram_config.channel_width_bytes = in_dc->ctx->dc_bios->vram_info.dram_channel_width_bytes;
312 }
313
314 /* override bounding box paramters from DC config */
315 if (in_dc->bb_overrides.sr_exit_time_ns) {
316 dml_soc_bb->power_management_parameters.stutter_exit_latency_us =
317 in_dc->bb_overrides.sr_exit_time_ns / 1000.0;
318 }
319
320 if (in_dc->bb_overrides.sr_enter_plus_exit_time_ns) {
321 dml_soc_bb->power_management_parameters.stutter_enter_plus_exit_latency_us =
322 in_dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0;
323 }
324
325 if (in_dc->bb_overrides.dram_clock_change_latency_ns) {
326 dml_soc_bb->power_management_parameters.dram_clk_change_blackout_us =
327 in_dc->bb_overrides.dram_clock_change_latency_ns / 1000.0;
328 }
329
330 if (in_dc->bb_overrides.fclk_clock_change_latency_ns) {
331 dml_soc_bb->power_management_parameters.fclk_change_blackout_us =
332 in_dc->bb_overrides.fclk_clock_change_latency_ns / 1000.0;
333 }
334
335 //TODO
336 // if (in_dc->bb_overrides.dummy_clock_change_latency_ns) {
337 // dml_soc_bb->power_management_parameters.dram_clk_change_blackout_us =
338 // in_dc->bb_overrides.dram_clock_change_latency_ns / 1000.0;
339 // }
340 }
341
calc_max_hardware_v_total(const struct dc_stream_state * stream)342 static unsigned int calc_max_hardware_v_total(const struct dc_stream_state *stream)
343 {
344 unsigned int max_hw_v_total = stream->ctx->dc->caps.max_v_total;
345
346 if (stream->ctx->dc->caps.vtotal_limited_by_fp2) {
347 max_hw_v_total -= stream->timing.v_front_porch + 1;
348 }
349
350 return max_hw_v_total;
351 }
352
populate_dml21_timing_config_from_stream_state(struct dml2_timing_cfg * timing,struct dc_stream_state * stream,struct dml2_context * dml_ctx)353 static void populate_dml21_timing_config_from_stream_state(struct dml2_timing_cfg *timing,
354 struct dc_stream_state *stream,
355 struct dml2_context *dml_ctx)
356 {
357 unsigned int hblank_start, vblank_start, min_hardware_refresh_in_uhz;
358
359 timing->h_active = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
360 timing->v_active = stream->timing.v_addressable + stream->timing.v_border_bottom + stream->timing.v_border_top;
361 timing->h_front_porch = stream->timing.h_front_porch;
362 timing->v_front_porch = stream->timing.v_front_porch;
363 timing->pixel_clock_khz = stream->timing.pix_clk_100hz / 10;
364 if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
365 timing->pixel_clock_khz *= 2;
366 timing->h_total = stream->timing.h_total;
367 timing->v_total = stream->timing.v_total;
368 timing->h_sync_width = stream->timing.h_sync_width;
369 timing->interlaced = stream->timing.flags.INTERLACE;
370
371 hblank_start = stream->timing.h_total - stream->timing.h_front_porch;
372
373 timing->h_blank_end = hblank_start - stream->timing.h_addressable
374 - stream->timing.h_border_left - stream->timing.h_border_right;
375
376 if (hblank_start < stream->timing.h_addressable)
377 timing->h_blank_end = 0;
378
379 vblank_start = stream->timing.v_total - stream->timing.v_front_porch;
380
381 timing->v_blank_end = vblank_start - stream->timing.v_addressable
382 - stream->timing.v_border_top - stream->timing.v_border_bottom;
383
384 timing->drr_config.enabled = stream->ignore_msa_timing_param;
385 timing->drr_config.drr_active_variable = stream->vrr_active_variable;
386 timing->drr_config.drr_active_fixed = stream->vrr_active_fixed;
387 timing->drr_config.disallowed = !stream->allow_freesync;
388
389 /* limit min refresh rate to DC cap */
390 min_hardware_refresh_in_uhz = stream->timing.min_refresh_in_uhz;
391 if (stream->ctx->dc->caps.max_v_total != 0) {
392 min_hardware_refresh_in_uhz = div64_u64((stream->timing.pix_clk_100hz * 100000000ULL),
393 (stream->timing.h_total * (long long)calc_max_hardware_v_total(stream)));
394 }
395
396 if (stream->timing.min_refresh_in_uhz > min_hardware_refresh_in_uhz) {
397 timing->drr_config.min_refresh_uhz = stream->timing.min_refresh_in_uhz;
398 } else {
399 timing->drr_config.min_refresh_uhz = min_hardware_refresh_in_uhz;
400 }
401
402 if (dml_ctx->config.callbacks.get_max_flickerless_instant_vtotal_increase &&
403 stream->ctx->dc->config.enable_fpo_flicker_detection == 1)
404 timing->drr_config.max_instant_vtotal_delta = dml_ctx->config.callbacks.get_max_flickerless_instant_vtotal_increase(stream, false);
405 else
406 timing->drr_config.max_instant_vtotal_delta = 0;
407
408 if (stream->timing.flags.DSC) {
409 timing->dsc.enable = dml2_dsc_enable;
410 timing->dsc.overrides.num_slices = stream->timing.dsc_cfg.num_slices_h;
411 timing->dsc.dsc_compressed_bpp_x16 = stream->timing.dsc_cfg.bits_per_pixel;
412 } else
413 timing->dsc.enable = dml2_dsc_disable;
414
415 switch (stream->timing.display_color_depth) {
416 case COLOR_DEPTH_666:
417 timing->bpc = 6;
418 break;
419 case COLOR_DEPTH_888:
420 timing->bpc = 8;
421 break;
422 case COLOR_DEPTH_101010:
423 timing->bpc = 10;
424 break;
425 case COLOR_DEPTH_121212:
426 timing->bpc = 12;
427 break;
428 case COLOR_DEPTH_141414:
429 timing->bpc = 14;
430 break;
431 case COLOR_DEPTH_161616:
432 timing->bpc = 16;
433 break;
434 case COLOR_DEPTH_999:
435 timing->bpc = 9;
436 break;
437 case COLOR_DEPTH_111111:
438 timing->bpc = 11;
439 break;
440 default:
441 timing->bpc = 8;
442 break;
443 }
444
445 timing->vblank_nom = timing->v_total - timing->v_active;
446 }
447
populate_dml21_output_config_from_stream_state(struct dml2_link_output_cfg * output,struct dc_stream_state * stream,const struct pipe_ctx * pipe)448 static void populate_dml21_output_config_from_stream_state(struct dml2_link_output_cfg *output,
449 struct dc_stream_state *stream, const struct pipe_ctx *pipe)
450 {
451 output->output_dp_lane_count = 4;
452
453 switch (stream->signal) {
454 case SIGNAL_TYPE_DISPLAY_PORT_MST:
455 case SIGNAL_TYPE_DISPLAY_PORT:
456 output->output_encoder = dml2_dp;
457 if (check_dp2p0_output_encoder(pipe))
458 output->output_encoder = dml2_dp2p0;
459 break;
460 case SIGNAL_TYPE_EDP:
461 output->output_encoder = dml2_edp;
462 break;
463 case SIGNAL_TYPE_HDMI_TYPE_A:
464 case SIGNAL_TYPE_DVI_SINGLE_LINK:
465 case SIGNAL_TYPE_DVI_DUAL_LINK:
466 output->output_encoder = dml2_hdmi;
467 break;
468 default:
469 output->output_encoder = dml2_dp;
470 }
471
472 switch (stream->timing.pixel_encoding) {
473 case PIXEL_ENCODING_RGB:
474 case PIXEL_ENCODING_YCBCR444:
475 output->output_format = dml2_444;
476 break;
477 case PIXEL_ENCODING_YCBCR420:
478 output->output_format = dml2_420;
479 break;
480 case PIXEL_ENCODING_YCBCR422:
481 if (stream->timing.flags.DSC && !stream->timing.dsc_cfg.ycbcr422_simple)
482 output->output_format = dml2_n422;
483 else
484 output->output_format = dml2_s422;
485 break;
486 default:
487 output->output_format = dml2_444;
488 break;
489 }
490
491 switch (stream->signal) {
492 case SIGNAL_TYPE_NONE:
493 case SIGNAL_TYPE_DVI_SINGLE_LINK:
494 case SIGNAL_TYPE_DVI_DUAL_LINK:
495 case SIGNAL_TYPE_HDMI_TYPE_A:
496 case SIGNAL_TYPE_LVDS:
497 case SIGNAL_TYPE_RGB:
498 case SIGNAL_TYPE_DISPLAY_PORT:
499 case SIGNAL_TYPE_DISPLAY_PORT_MST:
500 case SIGNAL_TYPE_EDP:
501 case SIGNAL_TYPE_VIRTUAL:
502 default:
503 output->output_dp_link_rate = dml2_dp_rate_na;
504 break;
505 }
506
507 output->audio_sample_layout = stream->audio_info.modes->sample_size;
508 output->audio_sample_rate = stream->audio_info.modes->max_bit_rate;
509 output->output_disabled = true;
510
511 //TODO : New to DML2.1. How do we populate this ?
512 // output->validate_output
513 }
514
populate_dml21_stream_overrides_from_stream_state(struct dml2_stream_parameters * stream_desc,struct dc_stream_state * stream)515 static void populate_dml21_stream_overrides_from_stream_state(
516 struct dml2_stream_parameters *stream_desc,
517 struct dc_stream_state *stream)
518 {
519 switch (stream->debug.force_odm_combine_segments) {
520 case 0:
521 stream_desc->overrides.odm_mode = dml2_odm_mode_auto;
522 break;
523 case 1:
524 stream_desc->overrides.odm_mode = dml2_odm_mode_bypass;
525 break;
526 case 2:
527 stream_desc->overrides.odm_mode = dml2_odm_mode_combine_2to1;
528 break;
529 case 3:
530 stream_desc->overrides.odm_mode = dml2_odm_mode_combine_3to1;
531 break;
532 case 4:
533 stream_desc->overrides.odm_mode = dml2_odm_mode_combine_4to1;
534 break;
535 default:
536 stream_desc->overrides.odm_mode = dml2_odm_mode_auto;
537 break;
538 }
539 if (!stream->ctx->dc->debug.enable_single_display_2to1_odm_policy ||
540 stream->debug.force_odm_combine_segments > 0)
541 stream_desc->overrides.disable_dynamic_odm = true;
542 stream_desc->overrides.disable_subvp = stream->ctx->dc->debug.force_disable_subvp || stream->hw_cursor_req;
543 }
544
gfx_addr3_to_dml2_swizzle_mode(enum swizzle_mode_addr3_values addr3_mode)545 static enum dml2_swizzle_mode gfx_addr3_to_dml2_swizzle_mode(enum swizzle_mode_addr3_values addr3_mode)
546 {
547 enum dml2_swizzle_mode dml2_mode = dml2_sw_linear;
548
549 switch (addr3_mode) {
550 case DC_ADDR3_SW_LINEAR:
551 dml2_mode = dml2_sw_linear;
552 break;
553 case DC_ADDR3_SW_256B_2D:
554 dml2_mode = dml2_sw_256b_2d;
555 break;
556 case DC_ADDR3_SW_4KB_2D:
557 dml2_mode = dml2_sw_4kb_2d;
558 break;
559 case DC_ADDR3_SW_64KB_2D:
560 dml2_mode = dml2_sw_64kb_2d;
561 break;
562 case DC_ADDR3_SW_256KB_2D:
563 dml2_mode = dml2_sw_256kb_2d;
564 break;
565 default:
566 /* invalid swizzle mode for DML2.1 */
567 ASSERT(false);
568 dml2_mode = dml2_sw_linear;
569 }
570
571 return dml2_mode;
572 }
573
gfx9_to_dml2_swizzle_mode(enum swizzle_mode_values gfx9_mode)574 static enum dml2_swizzle_mode gfx9_to_dml2_swizzle_mode(enum swizzle_mode_values gfx9_mode)
575 {
576 enum dml2_swizzle_mode dml2_mode = dml2_sw_64kb_2d;
577
578 switch (gfx9_mode) {
579 case DC_SW_LINEAR:
580 dml2_mode = dml2_sw_linear;
581 break;
582 case DC_SW_256_D:
583 case DC_SW_256_R:
584 dml2_mode = dml2_sw_256b_2d;
585 break;
586 case DC_SW_4KB_D:
587 case DC_SW_4KB_R:
588 case DC_SW_4KB_R_X:
589 dml2_mode = dml2_sw_4kb_2d;
590 break;
591 case DC_SW_64KB_D:
592 case DC_SW_64KB_D_X:
593 case DC_SW_64KB_R:
594 case DC_SW_64KB_R_X:
595 dml2_mode = dml2_sw_64kb_2d;
596 break;
597 case DC_SW_256B_S:
598 case DC_SW_4KB_S:
599 case DC_SW_64KB_S:
600 case DC_SW_VAR_S:
601 case DC_SW_VAR_D:
602 case DC_SW_VAR_R:
603 case DC_SW_64KB_S_T:
604 case DC_SW_64KB_D_T:
605 case DC_SW_4KB_S_X:
606 case DC_SW_4KB_D_X:
607 case DC_SW_64KB_S_X:
608 case DC_SW_VAR_S_X:
609 case DC_SW_VAR_D_X:
610 case DC_SW_VAR_R_X:
611 default:
612 /*
613 * invalid swizzle mode for DML2.1. This could happen because
614 * DML21 is not intended to be used by N-1 in production. To
615 * properly filter out unsupported swizzle modes, we will need
616 * to fix capability reporting when DML2.1 is used for N-1 in
617 * dc. So DML will only receive DML21 supported swizzle modes.
618 * This implementation is not added and has a low value because
619 * the supported swizzle modes should already cover most of our
620 * N-1 test cases.
621 */
622 return dml2_sw_64kb_2d;
623 }
624
625 return dml2_mode;
626 }
627
populate_dml21_dummy_surface_cfg(struct dml2_surface_cfg * surface,const struct dc_stream_state * stream)628 static void populate_dml21_dummy_surface_cfg(struct dml2_surface_cfg *surface, const struct dc_stream_state *stream)
629 {
630 surface->plane0.width = stream->timing.h_addressable;
631 surface->plane0.height = stream->timing.v_addressable;
632 surface->plane1.width = stream->timing.h_addressable;
633 surface->plane1.height = stream->timing.v_addressable;
634 surface->plane0.pitch = ((surface->plane0.width + 127) / 128) * 128;
635 surface->plane1.pitch = 0;
636 surface->dcc.enable = false;
637 surface->dcc.informative.dcc_rate_plane0 = 1.0;
638 surface->dcc.informative.dcc_rate_plane1 = 1.0;
639 surface->dcc.informative.fraction_of_zero_size_request_plane0 = 0;
640 surface->dcc.informative.fraction_of_zero_size_request_plane1 = 0;
641 surface->tiling = dml2_sw_64kb_2d;
642 }
643
populate_dml21_dummy_plane_cfg(struct dml2_plane_parameters * plane,const struct dc_stream_state * stream)644 static void populate_dml21_dummy_plane_cfg(struct dml2_plane_parameters *plane, const struct dc_stream_state *stream)
645 {
646 unsigned int width, height;
647
648 if (stream->timing.h_addressable > 3840)
649 width = 3840;
650 else
651 width = stream->timing.h_addressable; // 4K max
652
653 if (stream->timing.v_addressable > 2160)
654 height = 2160;
655 else
656 height = stream->timing.v_addressable; // 4K max
657
658 plane->cursor.cursor_bpp = 32;
659
660 plane->cursor.cursor_width = 256;
661 plane->cursor.num_cursors = 1;
662
663 plane->composition.viewport.plane0.width = width;
664 plane->composition.viewport.plane0.height = height;
665 plane->composition.viewport.plane1.width = 0;
666 plane->composition.viewport.plane1.height = 0;
667
668 plane->composition.viewport.stationary = false;
669 plane->composition.viewport.plane0.x_start = 0;
670 plane->composition.viewport.plane0.y_start = 0;
671 plane->composition.viewport.plane1.x_start = 0;
672 plane->composition.viewport.plane1.y_start = 0;
673
674 plane->composition.scaler_info.enabled = false;
675 plane->composition.rotation_angle = dml2_rotation_0;
676 plane->composition.scaler_info.plane0.h_ratio = 1.0;
677 plane->composition.scaler_info.plane0.v_ratio = 1.0;
678 plane->composition.scaler_info.plane1.h_ratio = 0;
679 plane->composition.scaler_info.plane1.v_ratio = 0;
680 plane->composition.scaler_info.plane0.h_taps = 1;
681 plane->composition.scaler_info.plane0.v_taps = 1;
682 plane->composition.scaler_info.plane1.h_taps = 0;
683 plane->composition.scaler_info.plane1.v_taps = 0;
684 plane->composition.scaler_info.rect_out_width = width;
685 plane->pixel_format = dml2_444_32;
686
687 plane->dynamic_meta_data.enable = false;
688 plane->overrides.gpuvm_min_page_size_kbytes = 256;
689 }
690
populate_dml21_surface_config_from_plane_state(const struct dc * in_dc,struct dml2_surface_cfg * surface,const struct dc_plane_state * plane_state)691 static void populate_dml21_surface_config_from_plane_state(
692 const struct dc *in_dc,
693 struct dml2_surface_cfg *surface,
694 const struct dc_plane_state *plane_state)
695 {
696 surface->plane0.pitch = plane_state->plane_size.surface_pitch;
697 surface->plane1.pitch = plane_state->plane_size.chroma_pitch;
698 surface->plane0.height = plane_state->plane_size.surface_size.height;
699 surface->plane0.width = plane_state->plane_size.surface_size.width;
700 surface->plane1.height = plane_state->plane_size.chroma_size.height;
701 surface->plane1.width = plane_state->plane_size.chroma_size.width;
702 surface->dcc.enable = plane_state->dcc.enable;
703 surface->dcc.informative.dcc_rate_plane0 = 1.0;
704 surface->dcc.informative.dcc_rate_plane1 = 1.0;
705 surface->dcc.informative.fraction_of_zero_size_request_plane0 = plane_state->dcc.independent_64b_blks;
706 surface->dcc.informative.fraction_of_zero_size_request_plane1 = plane_state->dcc.independent_64b_blks_c;
707 surface->dcc.plane0.pitch = plane_state->dcc.meta_pitch;
708 surface->dcc.plane1.pitch = plane_state->dcc.meta_pitch_c;
709 if (in_dc->ctx->dce_version < DCN_VERSION_4_01) {
710 /* needed for N-1 testing */
711 surface->tiling = gfx9_to_dml2_swizzle_mode(plane_state->tiling_info.gfx9.swizzle);
712 } else {
713 surface->tiling = gfx_addr3_to_dml2_swizzle_mode(plane_state->tiling_info.gfx_addr3.swizzle);
714 }
715 }
716
get_scaler_data_for_plane(struct dml2_context * dml_ctx,const struct dc_plane_state * in,const struct dc_state * context)717 static const struct scaler_data *get_scaler_data_for_plane(
718 struct dml2_context *dml_ctx,
719 const struct dc_plane_state *in,
720 const struct dc_state *context)
721 {
722 int i;
723 struct pipe_ctx *temp_pipe = &dml_ctx->v21.scratch.temp_pipe;
724
725 memset(temp_pipe, 0, sizeof(struct pipe_ctx));
726
727 for (i = 0; i < MAX_PIPES; i++) {
728 const struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
729
730 if (pipe->plane_state == in && !pipe->prev_odm_pipe) {
731 temp_pipe->stream = pipe->stream;
732 temp_pipe->plane_state = pipe->plane_state;
733 temp_pipe->plane_res.scl_data.taps = pipe->plane_res.scl_data.taps;
734 temp_pipe->stream_res = pipe->stream_res;
735 dml_ctx->config.callbacks.build_scaling_params(temp_pipe);
736 break;
737 }
738 }
739
740 ASSERT(i < MAX_PIPES);
741 return &temp_pipe->plane_res.scl_data;
742 }
743
populate_dml21_plane_config_from_plane_state(struct dml2_context * dml_ctx,struct dml2_plane_parameters * plane,const struct dc_plane_state * plane_state,const struct dc_state * context,unsigned int stream_index)744 static void populate_dml21_plane_config_from_plane_state(struct dml2_context *dml_ctx,
745 struct dml2_plane_parameters *plane, const struct dc_plane_state *plane_state,
746 const struct dc_state *context, unsigned int stream_index)
747 {
748 const struct scaler_data *scaler_data = get_scaler_data_for_plane(dml_ctx, plane_state, context);
749 struct dc_stream_state *stream = context->streams[stream_index];
750
751 plane->cursor.cursor_bpp = 32;
752 plane->cursor.cursor_width = 256;
753 plane->cursor.num_cursors = 1;
754
755 switch (plane_state->format) {
756 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
757 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
758 plane->pixel_format = dml2_420_8;
759 break;
760 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
761 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
762 plane->pixel_format = dml2_420_10;
763 break;
764 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
765 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616:
766 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
767 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
768 plane->pixel_format = dml2_444_64;
769 break;
770 case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
771 case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
772 plane->pixel_format = dml2_444_16;
773 break;
774 case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
775 plane->pixel_format = dml2_444_8;
776 break;
777 case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA:
778 plane->pixel_format = dml2_rgbe_alpha;
779 break;
780 default:
781 plane->pixel_format = dml2_444_32;
782 break;
783 }
784
785 plane->composition.viewport.plane0.height = scaler_data->viewport.height;
786 plane->composition.viewport.plane0.width = scaler_data->viewport.width;
787 plane->composition.viewport.plane1.height = scaler_data->viewport_c.height;
788 plane->composition.viewport.plane1.width = scaler_data->viewport_c.width;
789 plane->composition.viewport.plane0.x_start = scaler_data->viewport.x;
790 plane->composition.viewport.plane0.y_start = scaler_data->viewport.y;
791 plane->composition.viewport.plane1.x_start = scaler_data->viewport_c.x;
792 plane->composition.viewport.plane1.y_start = scaler_data->viewport_c.y;
793 plane->composition.viewport.stationary = false;
794 plane->composition.scaler_info.enabled = scaler_data->ratios.horz.value != dc_fixpt_one.value ||
795 scaler_data->ratios.horz_c.value != dc_fixpt_one.value ||
796 scaler_data->ratios.vert.value != dc_fixpt_one.value ||
797 scaler_data->ratios.vert_c.value != dc_fixpt_one.value;
798
799 if (!scaler_data->taps.h_taps) {
800 /* Above logic determines scaling should be enabled even when there are no taps for
801 * certain cases. Hence do corrective active and disable scaling.
802 */
803 plane->composition.scaler_info.enabled = false;
804 } else if ((plane_state->ctx->dc->config.use_spl == true) &&
805 (plane->composition.scaler_info.enabled == false)) {
806 /* To enable sharpener for 1:1, scaler must be enabled. If use_spl is set, then
807 * allow case where ratio is 1 but taps > 1
808 */
809 if ((scaler_data->taps.h_taps > 1) || (scaler_data->taps.v_taps > 1) ||
810 (scaler_data->taps.h_taps_c > 1) || (scaler_data->taps.v_taps_c > 1))
811 plane->composition.scaler_info.enabled = true;
812 }
813
814 /* always_scale is only used for debug purposes not used in production but has to be
815 * maintained for certain complainces. */
816 if (plane_state->ctx->dc->debug.always_scale == true) {
817 plane->composition.scaler_info.enabled = true;
818 }
819
820 if (plane->composition.scaler_info.enabled == false) {
821 plane->composition.scaler_info.plane0.h_ratio = 1.0;
822 plane->composition.scaler_info.plane0.v_ratio = 1.0;
823 plane->composition.scaler_info.plane1.h_ratio = 1.0;
824 plane->composition.scaler_info.plane1.v_ratio = 1.0;
825 } else {
826 plane->composition.scaler_info.plane0.h_ratio = (double)scaler_data->ratios.horz.value / (1ULL << 32);
827 plane->composition.scaler_info.plane0.v_ratio = (double)scaler_data->ratios.vert.value / (1ULL << 32);
828 plane->composition.scaler_info.plane1.h_ratio = (double)scaler_data->ratios.horz_c.value / (1ULL << 32);
829 plane->composition.scaler_info.plane1.v_ratio = (double)scaler_data->ratios.vert_c.value / (1ULL << 32);
830 }
831
832 if (!scaler_data->taps.h_taps) {
833 plane->composition.scaler_info.plane0.h_taps = 1;
834 plane->composition.scaler_info.plane1.h_taps = 1;
835 } else {
836 plane->composition.scaler_info.plane0.h_taps = scaler_data->taps.h_taps;
837 plane->composition.scaler_info.plane1.h_taps = scaler_data->taps.h_taps_c;
838 }
839 if (!scaler_data->taps.v_taps) {
840 plane->composition.scaler_info.plane0.v_taps = 1;
841 plane->composition.scaler_info.plane1.v_taps = 1;
842 } else {
843 plane->composition.scaler_info.plane0.v_taps = scaler_data->taps.v_taps;
844 plane->composition.scaler_info.plane1.v_taps = scaler_data->taps.v_taps_c;
845 }
846
847 plane->composition.viewport.stationary = false;
848
849 if (plane_state->mcm_luts.lut3d_data.lut3d_src == DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM) {
850 plane->tdlut.setup_for_tdlut = true;
851
852 switch (plane_state->mcm_luts.lut3d_data.gpu_mem_params.layout) {
853 case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_RGB:
854 case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_BGR:
855 plane->tdlut.tdlut_addressing_mode = dml2_tdlut_sw_linear;
856 break;
857 case DC_CM2_GPU_MEM_LAYOUT_1D_PACKED_LINEAR:
858 plane->tdlut.tdlut_addressing_mode = dml2_tdlut_simple_linear;
859 break;
860 }
861
862 switch (plane_state->mcm_luts.lut3d_data.gpu_mem_params.size) {
863 case DC_CM2_GPU_MEM_SIZE_171717:
864 plane->tdlut.tdlut_width_mode = dml2_tdlut_width_17_cube;
865 break;
866 case DC_CM2_GPU_MEM_SIZE_TRANSFORMED:
867 //plane->tdlut.tdlut_width_mode = dml2_tdlut_width_flatten; // dml2_tdlut_width_flatten undefined
868 break;
869 }
870 }
871 plane->tdlut.setup_for_tdlut |= dml_ctx->config.force_tdlut_enable;
872
873 plane->dynamic_meta_data.enable = false;
874 plane->dynamic_meta_data.lines_before_active_required = 0;
875 plane->dynamic_meta_data.transmitted_bytes = 0;
876
877 plane->composition.scaler_info.rect_out_width = plane_state->dst_rect.width;
878 plane->composition.rotation_angle = (enum dml2_rotation_angle) plane_state->rotation;
879 plane->stream_index = stream_index;
880
881 plane->overrides.gpuvm_min_page_size_kbytes = 256;
882
883 plane->immediate_flip = plane_state->flip_immediate;
884
885 plane->composition.rect_out_height_spans_vactive =
886 plane_state->dst_rect.height >= stream->src.height &&
887 stream->dst.height >= stream->timing.v_addressable;
888 }
889
890 //TODO : Could be possibly moved to a common helper layer.
dml21_wrapper_get_plane_id(const struct dc_state * context,unsigned int stream_id,const struct dc_plane_state * plane,unsigned int * plane_id)891 static bool dml21_wrapper_get_plane_id(const struct dc_state *context, unsigned int stream_id, const struct dc_plane_state *plane, unsigned int *plane_id)
892 {
893 int i, j;
894
895 if (!plane_id)
896 return false;
897
898 for (i = 0; i < context->stream_count; i++) {
899 if (context->streams[i]->stream_id == stream_id) {
900 for (j = 0; j < context->stream_status[i].plane_count; j++) {
901 if (context->stream_status[i].plane_states[j] == plane) {
902 *plane_id = (i << 16) | j;
903 return true;
904 }
905 }
906 }
907 }
908
909 return false;
910 }
911
map_stream_to_dml21_display_cfg(const struct dml2_context * dml_ctx,const struct dc_stream_state * stream)912 static unsigned int map_stream_to_dml21_display_cfg(const struct dml2_context *dml_ctx, const struct dc_stream_state *stream)
913 {
914 int i = 0;
915 int location = -1;
916
917 for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) {
918 if (dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_stream_id_valid[i] && dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_stream_id[i] == stream->stream_id) {
919 location = i;
920 break;
921 }
922 }
923
924 return location;
925 }
926
map_plane_to_dml21_display_cfg(const struct dml2_context * dml_ctx,unsigned int stream_id,const struct dc_plane_state * plane,const struct dc_state * context)927 static unsigned int map_plane_to_dml21_display_cfg(const struct dml2_context *dml_ctx, unsigned int stream_id,
928 const struct dc_plane_state *plane, const struct dc_state *context)
929 {
930 unsigned int plane_id;
931 int i = 0;
932 int location = -1;
933
934 if (!dml21_wrapper_get_plane_id(context, stream_id, plane, &plane_id)) {
935 ASSERT(false);
936 return -1;
937 }
938
939 for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) {
940 if (dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id_valid[i] && dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id[i] == plane_id) {
941 location = i;
942 break;
943 }
944 }
945
946 return location;
947 }
948
dml21_force_pstate_method_to_uclk_state_change_strategy(enum dml2_force_pstate_methods force_pstate_method)949 static enum dml2_uclk_pstate_change_strategy dml21_force_pstate_method_to_uclk_state_change_strategy(enum dml2_force_pstate_methods force_pstate_method)
950 {
951 enum dml2_uclk_pstate_change_strategy val = dml2_uclk_pstate_change_strategy_auto;
952
953 switch (force_pstate_method) {
954 case dml2_force_pstate_method_vactive:
955 val = dml2_uclk_pstate_change_strategy_force_vactive;
956 break;
957 case dml2_force_pstate_method_vblank:
958 val = dml2_uclk_pstate_change_strategy_force_vblank;
959 break;
960 case dml2_force_pstate_method_drr:
961 val = dml2_uclk_pstate_change_strategy_force_drr;
962 break;
963 case dml2_force_pstate_method_subvp:
964 val = dml2_uclk_pstate_change_strategy_force_mall_svp;
965 break;
966 case dml2_force_pstate_method_auto:
967 default:
968 val = dml2_uclk_pstate_change_strategy_auto;
969 }
970
971 return val;
972 }
973
dml21_map_dc_state_into_dml_display_cfg(const struct dc * in_dc,struct dc_state * context,struct dml2_context * dml_ctx)974 bool dml21_map_dc_state_into_dml_display_cfg(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx)
975 {
976 int stream_index, plane_index;
977 int disp_cfg_stream_location, disp_cfg_plane_location;
978 struct dml2_display_cfg *dml_dispcfg = &dml_ctx->v21.display_config;
979 unsigned int plane_count = 0;
980
981 memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping));
982
983 dml_dispcfg->gpuvm_enable = dml_ctx->config.gpuvm_enable;
984 dml_dispcfg->gpuvm_max_page_table_levels = 4;
985 dml_dispcfg->hostvm_enable = false;
986 dml_dispcfg->minimize_det_reallocation = true;
987 dml_dispcfg->overrides.enable_subvp_implicit_pmo = true;
988
989 if (in_dc->debug.disable_unbounded_requesting) {
990 dml_dispcfg->overrides.hw.force_unbounded_requesting.enable = true;
991 dml_dispcfg->overrides.hw.force_unbounded_requesting.value = false;
992 }
993
994 for (stream_index = 0; stream_index < context->stream_count; stream_index++) {
995 disp_cfg_stream_location = map_stream_to_dml21_display_cfg(dml_ctx, context->streams[stream_index]);
996
997 if (disp_cfg_stream_location < 0)
998 disp_cfg_stream_location = dml_dispcfg->num_streams++;
999
1000 ASSERT(disp_cfg_stream_location >= 0 && disp_cfg_stream_location < __DML2_WRAPPER_MAX_STREAMS_PLANES__);
1001 populate_dml21_timing_config_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].timing, context->streams[stream_index], dml_ctx);
1002 populate_dml21_output_config_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].output, context->streams[stream_index], &context->res_ctx.pipe_ctx[stream_index]);
1003 populate_dml21_stream_overrides_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location], context->streams[stream_index]);
1004
1005 dml_dispcfg->stream_descriptors[disp_cfg_stream_location].overrides.hw.twait_budgeting.fclk_pstate = dml2_twait_budgeting_setting_if_needed;
1006 dml_dispcfg->stream_descriptors[disp_cfg_stream_location].overrides.hw.twait_budgeting.uclk_pstate = dml2_twait_budgeting_setting_if_needed;
1007 dml_dispcfg->stream_descriptors[disp_cfg_stream_location].overrides.hw.twait_budgeting.stutter_enter_exit = dml2_twait_budgeting_setting_if_needed;
1008
1009 dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_stream_id[disp_cfg_stream_location] = context->streams[stream_index]->stream_id;
1010 dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_stream_id_valid[disp_cfg_stream_location] = true;
1011
1012 if (context->stream_status[stream_index].plane_count == 0) {
1013 disp_cfg_plane_location = dml_dispcfg->num_planes++;
1014 populate_dml21_dummy_surface_cfg(&dml_dispcfg->plane_descriptors[disp_cfg_plane_location].surface, context->streams[stream_index]);
1015 populate_dml21_dummy_plane_cfg(&dml_dispcfg->plane_descriptors[disp_cfg_plane_location], context->streams[stream_index]);
1016 dml_dispcfg->plane_descriptors[disp_cfg_plane_location].stream_index = disp_cfg_stream_location;
1017 } else {
1018 for (plane_index = 0; plane_index < context->stream_status[stream_index].plane_count; plane_index++) {
1019 disp_cfg_plane_location = map_plane_to_dml21_display_cfg(dml_ctx, context->streams[stream_index]->stream_id, context->stream_status[stream_index].plane_states[plane_index], context);
1020
1021 if (disp_cfg_plane_location < 0)
1022 disp_cfg_plane_location = dml_dispcfg->num_planes++;
1023
1024 ASSERT(disp_cfg_plane_location >= 0 && disp_cfg_plane_location < __DML2_WRAPPER_MAX_STREAMS_PLANES__);
1025
1026 populate_dml21_surface_config_from_plane_state(in_dc, &dml_dispcfg->plane_descriptors[disp_cfg_plane_location].surface, context->stream_status[stream_index].plane_states[plane_index]);
1027 populate_dml21_plane_config_from_plane_state(dml_ctx, &dml_dispcfg->plane_descriptors[disp_cfg_plane_location], context->stream_status[stream_index].plane_states[plane_index], context, stream_index);
1028 dml_dispcfg->plane_descriptors[disp_cfg_plane_location].stream_index = disp_cfg_stream_location;
1029
1030 if (dml21_wrapper_get_plane_id(context, context->streams[stream_index]->stream_id, context->stream_status[stream_index].plane_states[plane_index], &dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id[disp_cfg_plane_location]))
1031 dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id_valid[disp_cfg_plane_location] = true;
1032
1033 /* apply forced pstate policy */
1034 if (dml_ctx->config.pmo.force_pstate_method_enable) {
1035 dml_dispcfg->plane_descriptors[disp_cfg_plane_location].overrides.uclk_pstate_change_strategy =
1036 dml21_force_pstate_method_to_uclk_state_change_strategy(dml_ctx->config.pmo.force_pstate_method_values[stream_index]);
1037 }
1038
1039 plane_count++;
1040 }
1041 }
1042 }
1043
1044 if (plane_count == 0) {
1045 dml_dispcfg->overrides.all_streams_blanked = true;
1046 }
1047
1048 return true;
1049 }
1050
dml21_copy_clocks_to_dc_state(struct dml2_context * in_ctx,struct dc_state * context)1051 void dml21_copy_clocks_to_dc_state(struct dml2_context *in_ctx, struct dc_state *context)
1052 {
1053 /* TODO these should be the max of active, svp prefetch and idle should be tracked seperately */
1054 context->bw_ctx.bw.dcn.clk.dispclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.dispclk_khz;
1055 context->bw_ctx.bw.dcn.clk.dcfclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.active.dcfclk_khz;
1056 context->bw_ctx.bw.dcn.clk.dramclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.active.uclk_khz;
1057 context->bw_ctx.bw.dcn.clk.fclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.active.fclk_khz;
1058 context->bw_ctx.bw.dcn.clk.idle_dramclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.idle.uclk_khz;
1059 context->bw_ctx.bw.dcn.clk.idle_fclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.idle.fclk_khz;
1060 context->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.deepsleep_dcfclk_khz;
1061 context->bw_ctx.bw.dcn.clk.fclk_p_state_change_support = in_ctx->v21.mode_programming.programming->fclk_pstate_supported;
1062 context->bw_ctx.bw.dcn.clk.p_state_change_support = in_ctx->v21.mode_programming.programming->uclk_pstate_supported;
1063 context->bw_ctx.bw.dcn.clk.dtbclk_en = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.dtbrefclk_khz > 0;
1064 context->bw_ctx.bw.dcn.clk.ref_dtbclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.dtbrefclk_khz;
1065 }
1066
dml21_extract_legacy_watermark_set(const struct dc * in_dc,struct dcn_watermarks * watermark,enum dml2_dchub_watermark_reg_set_index reg_set_idx,struct dml2_context * in_ctx)1067 void dml21_extract_legacy_watermark_set(const struct dc *in_dc, struct dcn_watermarks *watermark, enum dml2_dchub_watermark_reg_set_index reg_set_idx, struct dml2_context *in_ctx)
1068 {
1069 struct dml2_core_internal_display_mode_lib *mode_lib = &in_ctx->v21.dml_init.dml2_instance->core_instance.clean_me_up.mode_lib;
1070 double refclk_freq_in_mhz = (in_ctx->v21.display_config.overrides.hw.dlg_ref_clk_mhz > 0) ? (double)in_ctx->v21.display_config.overrides.hw.dlg_ref_clk_mhz : mode_lib->soc.dchub_refclk_mhz;
1071
1072 if (reg_set_idx >= DML2_DCHUB_WATERMARK_SET_NUM) {
1073 /* invalid register set index */
1074 return;
1075 }
1076
1077 /* convert to legacy format (time in ns) */
1078 watermark->urgent_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].urgent / refclk_freq_in_mhz) * 1000.0;
1079 watermark->pte_meta_urgent_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].urgent / refclk_freq_in_mhz) * 1000.0;
1080 watermark->cstate_pstate.cstate_enter_plus_exit_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].sr_enter / refclk_freq_in_mhz) * 1000.0;
1081 watermark->cstate_pstate.cstate_exit_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].sr_exit / refclk_freq_in_mhz) * 1000.0;
1082 watermark->cstate_pstate.pstate_change_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].uclk_pstate / refclk_freq_in_mhz) * 1000.0;
1083 watermark->urgent_latency_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].urgent / refclk_freq_in_mhz) * 1000.0;
1084 watermark->cstate_pstate.fclk_pstate_change_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].fclk_pstate / refclk_freq_in_mhz) * 1000.0;
1085 watermark->frac_urg_bw_flip = in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].frac_urg_bw_flip;
1086 watermark->frac_urg_bw_nom = in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].frac_urg_bw_nom;
1087 }
1088
wm_set_index_to_dc_wm_set(union dcn_watermark_set * watermarks,const enum dml2_dchub_watermark_reg_set_index wm_index)1089 static struct dml2_dchub_watermark_regs *wm_set_index_to_dc_wm_set(union dcn_watermark_set *watermarks, const enum dml2_dchub_watermark_reg_set_index wm_index)
1090 {
1091 struct dml2_dchub_watermark_regs *wm_regs = NULL;
1092
1093 switch (wm_index) {
1094 case DML2_DCHUB_WATERMARK_SET_A:
1095 wm_regs = &watermarks->dcn4x.a;
1096 break;
1097 case DML2_DCHUB_WATERMARK_SET_B:
1098 wm_regs = &watermarks->dcn4x.b;
1099 break;
1100 case DML2_DCHUB_WATERMARK_SET_C:
1101 wm_regs = &watermarks->dcn4x.c;
1102 break;
1103 case DML2_DCHUB_WATERMARK_SET_D:
1104 wm_regs = &watermarks->dcn4x.d;
1105 break;
1106 case DML2_DCHUB_WATERMARK_SET_NUM:
1107 default:
1108 /* invalid wm set index */
1109 wm_regs = NULL;
1110 }
1111
1112 return wm_regs;
1113 }
1114
dml21_extract_watermark_sets(const struct dc * in_dc,union dcn_watermark_set * watermarks,struct dml2_context * in_ctx)1115 void dml21_extract_watermark_sets(const struct dc *in_dc, union dcn_watermark_set *watermarks, struct dml2_context *in_ctx)
1116 {
1117 const struct dml2_display_cfg_programming *programming = in_ctx->v21.mode_programming.programming;
1118
1119 unsigned int wm_index;
1120
1121 /* copy watermark sets from DML */
1122 for (wm_index = 0; wm_index < programming->global_regs.num_watermark_sets; wm_index++) {
1123 struct dml2_dchub_watermark_regs *wm_regs = wm_set_index_to_dc_wm_set(watermarks, wm_index);
1124
1125 if (wm_regs)
1126 memcpy(wm_regs,
1127 &programming->global_regs.wm_regs[wm_index],
1128 sizeof(struct dml2_dchub_watermark_regs));
1129 }
1130 }
1131
1132
dml21_populate_pipe_ctx_dlg_params(struct dml2_context * dml_ctx,struct dc_state * context,struct pipe_ctx * pipe_ctx,struct dml2_per_stream_programming * stream_programming)1133 void dml21_populate_pipe_ctx_dlg_params(struct dml2_context *dml_ctx, struct dc_state *context, struct pipe_ctx *pipe_ctx, struct dml2_per_stream_programming *stream_programming)
1134 {
1135 unsigned int hactive, vactive, hblank_start, vblank_start, hblank_end, vblank_end;
1136 struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
1137 union dml2_global_sync_programming *global_sync = &stream_programming->global_sync;
1138
1139 hactive = timing->h_addressable + timing->h_border_left + timing->h_border_right;
1140 vactive = timing->v_addressable + timing->v_border_bottom + timing->v_border_top;
1141 hblank_start = pipe_ctx->stream->timing.h_total - pipe_ctx->stream->timing.h_front_porch;
1142 vblank_start = pipe_ctx->stream->timing.v_total - pipe_ctx->stream->timing.v_front_porch;
1143
1144 hblank_end = hblank_start - timing->h_addressable - timing->h_border_left - timing->h_border_right;
1145 vblank_end = vblank_start - timing->v_addressable - timing->v_border_top - timing->v_border_bottom;
1146
1147 if (dml_ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) {
1148 /* phantom has its own global sync */
1149 global_sync = &stream_programming->phantom_stream.global_sync;
1150 }
1151
1152 pipe_ctx->pipe_dlg_param.vstartup_start = global_sync->dcn4x.vstartup_lines;
1153 pipe_ctx->pipe_dlg_param.vupdate_offset = global_sync->dcn4x.vupdate_offset_pixels;
1154 pipe_ctx->pipe_dlg_param.vupdate_width = global_sync->dcn4x.vupdate_vupdate_width_pixels;
1155 pipe_ctx->pipe_dlg_param.vready_offset = global_sync->dcn4x.vready_offset_pixels;
1156 pipe_ctx->pipe_dlg_param.pstate_keepout = global_sync->dcn4x.pstate_keepout_start_lines;
1157
1158 pipe_ctx->pipe_dlg_param.otg_inst = pipe_ctx->stream_res.tg->inst;
1159
1160 pipe_ctx->pipe_dlg_param.hactive = hactive;
1161 pipe_ctx->pipe_dlg_param.vactive = vactive;
1162 pipe_ctx->pipe_dlg_param.htotal = pipe_ctx->stream->timing.h_total;
1163 pipe_ctx->pipe_dlg_param.vtotal = pipe_ctx->stream->timing.v_total;
1164 pipe_ctx->pipe_dlg_param.hblank_end = hblank_end;
1165 pipe_ctx->pipe_dlg_param.vblank_end = vblank_end;
1166 pipe_ctx->pipe_dlg_param.hblank_start = hblank_start;
1167 pipe_ctx->pipe_dlg_param.vblank_start = vblank_start;
1168 pipe_ctx->pipe_dlg_param.vfront_porch = pipe_ctx->stream->timing.v_front_porch;
1169 pipe_ctx->pipe_dlg_param.pixel_rate_mhz = pipe_ctx->stream->timing.pix_clk_100hz / 10000.00;
1170 pipe_ctx->pipe_dlg_param.refresh_rate = ((timing->pix_clk_100hz * 100) / timing->h_total) / timing->v_total;
1171 pipe_ctx->pipe_dlg_param.vtotal_max = pipe_ctx->stream->adjust.v_total_max;
1172 pipe_ctx->pipe_dlg_param.vtotal_min = pipe_ctx->stream->adjust.v_total_min;
1173 pipe_ctx->pipe_dlg_param.recout_height = pipe_ctx->plane_res.scl_data.recout.height;
1174 pipe_ctx->pipe_dlg_param.recout_width = pipe_ctx->plane_res.scl_data.recout.width;
1175 pipe_ctx->pipe_dlg_param.full_recout_height = pipe_ctx->plane_res.scl_data.recout.height;
1176 pipe_ctx->pipe_dlg_param.full_recout_width = pipe_ctx->plane_res.scl_data.recout.width;
1177 }
1178
dml21_map_hw_resources(struct dml2_context * dml_ctx)1179 void dml21_map_hw_resources(struct dml2_context *dml_ctx)
1180 {
1181 unsigned int i = 0;
1182
1183 for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) {
1184 dml_ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id[i] = dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_stream_id[i];
1185 dml_ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id_valid[i] = true;
1186 dml_ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_id[i] = dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id[i];
1187 dml_ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_id_valid[i] = true;
1188 }
1189
1190 }
1191
dml21_get_pipe_mcache_config(struct dc_state * context,struct pipe_ctx * pipe_ctx,struct dml2_per_plane_programming * pln_prog,struct dml2_pipe_configuration_descriptor * mcache_pipe_config)1192 void dml21_get_pipe_mcache_config(
1193 struct dc_state *context,
1194 struct pipe_ctx *pipe_ctx,
1195 struct dml2_per_plane_programming *pln_prog,
1196 struct dml2_pipe_configuration_descriptor *mcache_pipe_config)
1197 {
1198 mcache_pipe_config->plane0.viewport_x_start = pipe_ctx->plane_res.scl_data.viewport.x;
1199 mcache_pipe_config->plane0.viewport_width = pipe_ctx->plane_res.scl_data.viewport.width;
1200
1201 mcache_pipe_config->plane1.viewport_x_start = pipe_ctx->plane_res.scl_data.viewport_c.x;
1202 mcache_pipe_config->plane1.viewport_width = pipe_ctx->plane_res.scl_data.viewport_c.width;
1203
1204 mcache_pipe_config->plane1_enabled =
1205 dml21_is_plane1_enabled(pln_prog->plane_descriptor->pixel_format);
1206 }
1207
dml21_set_dc_p_state_type(struct pipe_ctx * pipe_ctx,struct dml2_per_stream_programming * stream_programming,bool sub_vp_enabled)1208 void dml21_set_dc_p_state_type(
1209 struct pipe_ctx *pipe_ctx,
1210 struct dml2_per_stream_programming *stream_programming,
1211 bool sub_vp_enabled)
1212 {
1213 switch (stream_programming->uclk_pstate_method) {
1214 case dml2_uclk_pstate_support_method_vactive:
1215 case dml2_uclk_pstate_support_method_fw_vactive_drr:
1216 pipe_ctx->p_state_type = P_STATE_V_ACTIVE;
1217 break;
1218 case dml2_uclk_pstate_support_method_vblank:
1219 case dml2_uclk_pstate_support_method_fw_vblank_drr:
1220 if (sub_vp_enabled)
1221 pipe_ctx->p_state_type = P_STATE_V_BLANK_SUB_VP;
1222 else
1223 pipe_ctx->p_state_type = P_STATE_V_BLANK;
1224 break;
1225 case dml2_uclk_pstate_support_method_fw_subvp_phantom:
1226 case dml2_uclk_pstate_support_method_fw_subvp_phantom_drr:
1227 pipe_ctx->p_state_type = P_STATE_SUB_VP;
1228 break;
1229 case dml2_uclk_pstate_support_method_fw_drr:
1230 if (sub_vp_enabled)
1231 pipe_ctx->p_state_type = P_STATE_DRR_SUB_VP;
1232 else
1233 pipe_ctx->p_state_type = P_STATE_FPO;
1234 break;
1235 default:
1236 pipe_ctx->p_state_type = P_STATE_UNKNOWN;
1237 break;
1238 }
1239 }
1240
1241