1 /*
2 * Copyright 2015 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: AMD
23 */
24
25 #include "dm_services.h"
26
27 #include "amdgpu.h"
28
29 #include "dc.h"
30
31 #include "core_status.h"
32 #include "core_types.h"
33 #include "hw_sequencer.h"
34 #include "dce/dce_hwseq.h"
35 #include "hw/dccg.h"
36
37 #include "resource.h"
38 #include "dc_state.h"
39 #include "dc_state_priv.h"
40 #include "dc_plane.h"
41 #include "dc_plane_priv.h"
42 #include "dc_stream_priv.h"
43
44 #include "gpio_service_interface.h"
45 #include "clk_mgr.h"
46 #include "clock_source.h"
47 #include "dc_bios_types.h"
48
49 #include "bios_parser_interface.h"
50 #include "bios/bios_parser_helper.h"
51 #include "include/irq_service_interface.h"
52 #include "transform.h"
53 #include "dmcu.h"
54 #include "dpp.h"
55 #include "timing_generator.h"
56 #include "abm.h"
57 #include "dio/virtual/virtual_link_encoder.h"
58 #include "hubp.h"
59
60 #include "link_hwss.h"
61 #include "link_encoder.h"
62 #include "link_enc_cfg.h"
63
64 #include "link_service.h"
65 #include "link/protocols/link_dp_capability.h"
66 #include "dm_helpers.h"
67 #include "mem_input.h"
68
69 #include "dc_dmub_srv.h"
70
71 #include "dsc.h"
72
73 #include "vm_helper.h"
74
75 #include "dce/dce_i2c.h"
76
77 #include "dmub/dmub_srv.h"
78
79 #include "dce/dmub_psr.h"
80
81 #include "dce/dmub_hw_lock_mgr.h"
82
83 #include "dc_trace.h"
84
85 #include "hw_sequencer_private.h"
86
87 #if defined(CONFIG_DRM_AMD_DC_FP)
88 #include "dml2_0/dml2_internal_types.h"
89 #include "soc_and_ip_translator.h"
90 #endif
91
92 #include "dce/dmub_outbox.h"
93
94 #define CTX \
95 dc->ctx
96
97 #define DC_LOGGER \
98 dc->ctx->logger
99
100 static const char DC_BUILD_ID[] = "production-build";
101
102 /**
103 * DOC: Overview
104 *
105 * DC is the OS-agnostic component of the amdgpu DC driver.
106 *
107 * DC maintains and validates a set of structs representing the state of the
108 * driver and writes that state to AMD hardware
109 *
110 * Main DC HW structs:
111 *
112 * struct dc - The central struct. One per driver. Created on driver load,
113 * destroyed on driver unload.
114 *
115 * struct dc_context - One per driver.
116 * Used as a backpointer by most other structs in dc.
117 *
118 * struct dc_link - One per connector (the physical DP, HDMI, miniDP, or eDP
119 * plugpoints). Created on driver load, destroyed on driver unload.
120 *
121 * struct dc_sink - One per display. Created on boot or hotplug.
122 * Destroyed on shutdown or hotunplug. A dc_link can have a local sink
123 * (the display directly attached). It may also have one or more remote
124 * sinks (in the Multi-Stream Transport case)
125 *
126 * struct resource_pool - One per driver. Represents the hw blocks not in the
127 * main pipeline. Not directly accessible by dm.
128 *
129 * Main dc state structs:
130 *
131 * These structs can be created and destroyed as needed. There is a full set of
132 * these structs in dc->current_state representing the currently programmed state.
133 *
134 * struct dc_state - The global DC state to track global state information,
135 * such as bandwidth values.
136 *
137 * struct dc_stream_state - Represents the hw configuration for the pipeline from
138 * a framebuffer to a display. Maps one-to-one with dc_sink.
139 *
140 * struct dc_plane_state - Represents a framebuffer. Each stream has at least one,
141 * and may have more in the Multi-Plane Overlay case.
142 *
143 * struct resource_context - Represents the programmable state of everything in
144 * the resource_pool. Not directly accessible by dm.
145 *
146 * struct pipe_ctx - A member of struct resource_context. Represents the
147 * internal hardware pipeline components. Each dc_plane_state has either
148 * one or two (in the pipe-split case).
149 */
150
151 /* Private functions */
152
elevate_update_type(struct dc_update_descriptor * descriptor,enum dc_update_type new_type,enum dc_lock_descriptor new_locks)153 static inline void elevate_update_type(
154 struct dc_update_descriptor *descriptor,
155 enum dc_update_type new_type,
156 enum dc_lock_descriptor new_locks
157 )
158 {
159 if (new_type > descriptor->update_type)
160 descriptor->update_type = new_type;
161
162 descriptor->lock_descriptor |= new_locks;
163 }
164
destroy_links(struct dc * dc)165 static void destroy_links(struct dc *dc)
166 {
167 uint32_t i;
168
169 for (i = 0; i < dc->link_count; i++) {
170 if (NULL != dc->links[i])
171 dc->link_srv->destroy_link(&dc->links[i]);
172 }
173 }
174
get_num_of_internal_disp(struct dc_link ** links,uint32_t num_links)175 static uint32_t get_num_of_internal_disp(struct dc_link **links, uint32_t num_links)
176 {
177 uint32_t i;
178 uint32_t count = 0;
179
180 for (i = 0; i < num_links; i++) {
181 if (links[i]->connector_signal == SIGNAL_TYPE_EDP ||
182 links[i]->is_internal_display)
183 count++;
184 }
185
186 return count;
187 }
188
get_seamless_boot_stream_count(struct dc_state * ctx)189 static int get_seamless_boot_stream_count(struct dc_state *ctx)
190 {
191 uint8_t i;
192 uint8_t seamless_boot_stream_count = 0;
193
194 for (i = 0; i < ctx->stream_count; i++)
195 if (ctx->streams[i]->apply_seamless_boot_optimization)
196 seamless_boot_stream_count++;
197
198 return seamless_boot_stream_count;
199 }
200
create_links(struct dc * dc,uint32_t num_virtual_links)201 static bool create_links(
202 struct dc *dc,
203 uint32_t num_virtual_links)
204 {
205 uint32_t i;
206 int connectors_num;
207 struct dc_bios *bios = dc->ctx->dc_bios;
208
209 dc->link_count = 0;
210
211 connectors_num = bios->funcs->get_connectors_number(bios);
212
213 DC_LOG_DC("BIOS object table - number of connectors: %d", connectors_num);
214
215 if (connectors_num > ENUM_ID_COUNT) {
216 dm_error(
217 "DC: Number of connectors %d exceeds maximum of %d!\n",
218 connectors_num,
219 ENUM_ID_COUNT);
220 return false;
221 }
222
223 dm_output_to_console(
224 "DC: %s: connectors_num: physical:%d, virtual:%d\n",
225 __func__,
226 connectors_num,
227 num_virtual_links);
228
229 /* When getting the number of connectors, the VBIOS reports the number of valid indices,
230 * but it doesn't say which indices are valid, and not every index has an actual connector.
231 * So, if we don't find a connector on an index, that is not an error.
232 *
233 * - There is no guarantee that the first N indices will be valid
234 * - VBIOS may report a higher amount of valid indices than there are actual connectors
235 * - Some VBIOS have valid configurations for more connectors than there actually are
236 * on the card. This may be because the manufacturer used the same VBIOS for different
237 * variants of the same card.
238 */
239 for (i = 0; dc->link_count < connectors_num && i < MAX_LINKS; i++) {
240 struct graphics_object_id connector_id = bios->funcs->get_connector_id(bios, (uint8_t)i);
241 struct link_init_data link_init_params = {0};
242 struct dc_link *link;
243
244 if (connector_id.id == CONNECTOR_ID_UNKNOWN)
245 continue;
246
247 DC_LOG_DC("BIOS object table - printing link object info for connector number: %d, link_index: %d", i, dc->link_count);
248
249 link_init_params.ctx = dc->ctx;
250 /* next BIOS object table connector */
251 link_init_params.connector_index = (uint8_t)i;
252 link_init_params.link_index = dc->link_count;
253 link_init_params.dc = dc;
254 link = dc->link_srv->create_link(&link_init_params);
255
256 if (link) {
257 dc->links[dc->link_count] = link;
258 link->dc = dc;
259 ++dc->link_count;
260 }
261 }
262
263 DC_LOG_DC("BIOS object table - end");
264
265 /* Create a link for each usb4 dpia port */
266 dc->lowest_dpia_link_index = MAX_LINKS;
267 for (i = 0; i < dc->res_pool->usb4_dpia_count; i++) {
268 struct link_init_data link_init_params = {0};
269 struct dc_link *link;
270
271 link_init_params.ctx = dc->ctx;
272 link_init_params.connector_index = (uint8_t)i;
273 link_init_params.link_index = dc->link_count;
274 link_init_params.dc = dc;
275 link_init_params.is_dpia_link = true;
276
277 link = dc->link_srv->create_link(&link_init_params);
278 if (link) {
279 if (dc->lowest_dpia_link_index > dc->link_count)
280 dc->lowest_dpia_link_index = dc->link_count;
281
282 dc->links[dc->link_count] = link;
283 link->dc = dc;
284 ++dc->link_count;
285 }
286 }
287
288 for (i = 0; i < num_virtual_links; i++) {
289 struct dc_link *link = kzalloc_obj(*link);
290 struct encoder_init_data enc_init = {0};
291
292 if (link == NULL) {
293 BREAK_TO_DEBUGGER();
294 goto failed_alloc;
295 }
296
297 link->link_index = dc->link_count;
298 dc->links[dc->link_count] = link;
299 dc->link_count++;
300
301 link->ctx = dc->ctx;
302 link->dc = dc;
303 link->connector_signal = SIGNAL_TYPE_VIRTUAL;
304 link->link_id.type = OBJECT_TYPE_CONNECTOR;
305 link->link_id.id = CONNECTOR_ID_VIRTUAL;
306 link->link_id.enum_id = ENUM_ID_1;
307 link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED;
308 link->replay_settings.config.replay_version = DC_REPLAY_VERSION_UNSUPPORTED;
309 link->link_enc = kzalloc_obj(*link->link_enc);
310
311 if (!link->link_enc) {
312 BREAK_TO_DEBUGGER();
313 goto failed_alloc;
314 }
315
316 link->link_status.dpcd_caps = &link->dpcd_caps;
317
318 enc_init.ctx = dc->ctx;
319 enc_init.channel = CHANNEL_ID_UNKNOWN;
320 enc_init.hpd_source = HPD_SOURCEID_UNKNOWN;
321 enc_init.transmitter = TRANSMITTER_UNKNOWN;
322 enc_init.connector = link->link_id;
323 enc_init.encoder.type = OBJECT_TYPE_ENCODER;
324 enc_init.encoder.id = ENCODER_ID_INTERNAL_VIRTUAL;
325 enc_init.encoder.enum_id = ENUM_ID_1;
326 virtual_link_encoder_construct(link->link_enc, &enc_init);
327 }
328
329 dc->caps.num_of_internal_disp = get_num_of_internal_disp(dc->links, dc->link_count);
330
331 return true;
332
333 failed_alloc:
334 return false;
335 }
336
337 /* Create additional DIG link encoder objects if fewer than the platform
338 * supports were created during link construction. This can happen if the
339 * number of physical connectors is less than the number of DIGs.
340 */
create_link_encoders(struct dc * dc)341 static bool create_link_encoders(struct dc *dc)
342 {
343 bool res = true;
344 unsigned int num_usb4_dpia = dc->res_pool->res_cap->num_usb4_dpia;
345 unsigned int num_dig_link_enc = dc->res_pool->res_cap->num_dig_link_enc;
346 unsigned int i;
347
348 /* A platform without USB4 DPIA endpoints has a fixed mapping between DIG
349 * link encoders and physical display endpoints and does not require
350 * additional link encoder objects.
351 */
352 if (num_usb4_dpia == 0)
353 return res;
354
355 /* Create as many link encoder objects as the platform supports. DPIA
356 * endpoints can be programmably mapped to any DIG.
357 */
358 if (num_dig_link_enc > dc->res_pool->dig_link_enc_count) {
359 for (i = 0; i < num_dig_link_enc; i++) {
360 struct link_encoder *link_enc = dc->res_pool->link_encoders[i];
361
362 if (!link_enc && dc->res_pool->funcs->link_enc_create_minimal) {
363 link_enc = dc->res_pool->funcs->link_enc_create_minimal(dc->ctx,
364 (enum engine_id)(ENGINE_ID_DIGA + i));
365 if (link_enc) {
366 dc->res_pool->link_encoders[i] = link_enc;
367 dc->res_pool->dig_link_enc_count++;
368 } else {
369 res = false;
370 }
371 }
372 }
373 }
374
375 return res;
376 }
377
378 /* Destroy any additional DIG link encoder objects created by
379 * create_link_encoders().
380 * NB: Must only be called after destroy_links().
381 */
destroy_link_encoders(struct dc * dc)382 static void destroy_link_encoders(struct dc *dc)
383 {
384 unsigned int num_usb4_dpia;
385 unsigned int num_dig_link_enc;
386 unsigned int i;
387
388 if (!dc->res_pool)
389 return;
390
391 num_usb4_dpia = dc->res_pool->res_cap->num_usb4_dpia;
392 num_dig_link_enc = dc->res_pool->res_cap->num_dig_link_enc;
393
394 /* A platform without USB4 DPIA endpoints has a fixed mapping between DIG
395 * link encoders and physical display endpoints and does not require
396 * additional link encoder objects.
397 */
398 if (num_usb4_dpia == 0)
399 return;
400
401 for (i = 0; i < num_dig_link_enc; i++) {
402 struct link_encoder *link_enc = dc->res_pool->link_encoders[i];
403
404 if (link_enc) {
405 link_enc->funcs->destroy(&link_enc);
406 dc->res_pool->link_encoders[i] = NULL;
407 dc->res_pool->dig_link_enc_count--;
408 }
409 }
410 }
411
dc_perf_trace_create(void)412 static struct dc_perf_trace *dc_perf_trace_create(void)
413 {
414 return kzalloc_obj(struct dc_perf_trace);
415 }
416
dc_perf_trace_destroy(struct dc_perf_trace ** perf_trace)417 static void dc_perf_trace_destroy(struct dc_perf_trace **perf_trace)
418 {
419 kfree(*perf_trace);
420 *perf_trace = NULL;
421 }
422
set_long_vtotal(struct dc * dc,struct dc_stream_state * stream,struct dc_crtc_timing_adjust * adjust)423 static bool set_long_vtotal(struct dc *dc, struct dc_stream_state *stream, struct dc_crtc_timing_adjust *adjust)
424 {
425 if (!dc || !stream || !adjust)
426 return false;
427
428 if (!dc->current_state)
429 return false;
430
431 int i;
432
433 for (i = 0; i < MAX_PIPES; i++) {
434 struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
435
436 if (pipe->stream == stream && pipe->stream_res.tg) {
437 if (dc->hwss.set_long_vtotal)
438 dc->hwss.set_long_vtotal(&pipe, 1, adjust->v_total_min, adjust->v_total_max);
439
440 return true;
441 }
442 }
443
444 return false;
445 }
446
447 /**
448 * dc_stream_get_last_used_drr_vtotal - Looks up the pipe context of
449 * dc_stream_state and gets the last VTOTAL used by DRR (Dynamic Refresh Rate)
450 *
451 * @dc: [in] dc reference
452 * @stream: [in] Initial dc stream state
453 * @refresh_rate: [in] new refresh_rate
454 *
455 * Return: %true if the pipe context is found and there is an associated
456 * timing_generator for the DC;
457 * %false if the pipe context is not found or there is no
458 * timing_generator for the DC.
459 */
dc_stream_get_last_used_drr_vtotal(struct dc * dc,struct dc_stream_state * stream,uint32_t * refresh_rate)460 bool dc_stream_get_last_used_drr_vtotal(struct dc *dc,
461 struct dc_stream_state *stream,
462 uint32_t *refresh_rate)
463 {
464 bool status = false;
465
466 int i = 0;
467
468 dc_exit_ips_for_hw_access(dc);
469
470 for (i = 0; i < MAX_PIPES; i++) {
471 struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
472
473 if (pipe->stream == stream && pipe->stream_res.tg) {
474 /* Only execute if a function pointer has been defined for
475 * the DC version in question
476 */
477 if (pipe->stream_res.tg->funcs->get_last_used_drr_vtotal) {
478 pipe->stream_res.tg->funcs->get_last_used_drr_vtotal(pipe->stream_res.tg, refresh_rate);
479
480 status = true;
481
482 break;
483 }
484 }
485 }
486
487 return status;
488 }
489
490 #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
491 static inline void
dc_stream_forward_dmub_crc_window(struct dc_dmub_srv * dmub_srv,struct rect * rect,struct otg_phy_mux * mux_mapping,bool is_stop)492 dc_stream_forward_dmub_crc_window(struct dc_dmub_srv *dmub_srv,
493 struct rect *rect, struct otg_phy_mux *mux_mapping, bool is_stop)
494 {
495 union dmub_rb_cmd cmd = {0};
496
497 cmd.secure_display.roi_info.phy_id = mux_mapping->phy_output_num;
498 cmd.secure_display.roi_info.otg_id = mux_mapping->otg_output_num;
499
500 if (is_stop) {
501 cmd.secure_display.header.type = DMUB_CMD__SECURE_DISPLAY;
502 cmd.secure_display.header.sub_type = DMUB_CMD__SECURE_DISPLAY_CRC_STOP_UPDATE;
503 } else {
504 cmd.secure_display.header.type = DMUB_CMD__SECURE_DISPLAY;
505 cmd.secure_display.header.sub_type = DMUB_CMD__SECURE_DISPLAY_CRC_WIN_NOTIFY;
506 cmd.secure_display.roi_info.x_start = rect->x;
507 cmd.secure_display.roi_info.y_start = rect->y;
508 cmd.secure_display.roi_info.x_end = rect->x + rect->width;
509 cmd.secure_display.roi_info.y_end = rect->y + rect->height;
510 }
511
512 dc_wake_and_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
513 }
514
515 static inline void
dc_stream_forward_dmcu_crc_window(struct dmcu * dmcu,struct rect * rect,struct otg_phy_mux * mux_mapping,bool is_stop)516 dc_stream_forward_dmcu_crc_window(struct dmcu *dmcu,
517 struct rect *rect, struct otg_phy_mux *mux_mapping, bool is_stop)
518 {
519 if (is_stop)
520 dmcu->funcs->stop_crc_win_update(dmcu, mux_mapping);
521 else
522 dmcu->funcs->forward_crc_window(dmcu, rect, mux_mapping);
523 }
524
525 bool
dc_stream_forward_crc_window(struct dc_stream_state * stream,struct rect * rect,uint8_t phy_id,bool is_stop)526 dc_stream_forward_crc_window(struct dc_stream_state *stream,
527 struct rect *rect, uint8_t phy_id, bool is_stop)
528 {
529 struct dmcu *dmcu;
530 struct dc_dmub_srv *dmub_srv;
531 struct otg_phy_mux mux_mapping;
532 struct pipe_ctx *pipe;
533 int i;
534 struct dc *dc = stream->ctx->dc;
535
536 for (i = 0; i < MAX_PIPES; i++) {
537 pipe = &dc->current_state->res_ctx.pipe_ctx[i];
538 if (pipe->stream == stream && !pipe->top_pipe && !pipe->prev_odm_pipe)
539 break;
540 }
541
542 /* Stream not found */
543 if (i == MAX_PIPES)
544 return false;
545
546 mux_mapping.phy_output_num = phy_id;
547 mux_mapping.otg_output_num = pipe->stream_res.tg->inst;
548
549 dmcu = dc->res_pool->dmcu;
550 dmub_srv = dc->ctx->dmub_srv;
551
552 /* forward to dmub */
553 if (dmub_srv)
554 dc_stream_forward_dmub_crc_window(dmub_srv, rect, &mux_mapping, is_stop);
555 /* forward to dmcu */
556 else if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu))
557 dc_stream_forward_dmcu_crc_window(dmcu, rect, &mux_mapping, is_stop);
558 else
559 return false;
560
561 return true;
562 }
563
564 static void
dc_stream_forward_dmub_multiple_crc_window(struct dc_dmub_srv * dmub_srv,struct crc_window * window,struct otg_phy_mux * mux_mapping,bool stop)565 dc_stream_forward_dmub_multiple_crc_window(struct dc_dmub_srv *dmub_srv,
566 struct crc_window *window, struct otg_phy_mux *mux_mapping, bool stop)
567 {
568 int i;
569 union dmub_rb_cmd cmd = {0};
570
571 cmd.secure_display.mul_roi_ctl.phy_id = mux_mapping->phy_output_num;
572 cmd.secure_display.mul_roi_ctl.otg_id = mux_mapping->otg_output_num;
573
574 cmd.secure_display.header.type = DMUB_CMD__SECURE_DISPLAY;
575
576 if (stop) {
577 cmd.secure_display.header.sub_type = DMUB_CMD__SECURE_DISPLAY_MULTIPLE_CRC_STOP_UPDATE;
578 } else {
579 cmd.secure_display.header.sub_type = DMUB_CMD__SECURE_DISPLAY_MULTIPLE_CRC_WIN_NOTIFY;
580 for (i = 0; i < MAX_CRC_WINDOW_NUM; i++) {
581 cmd.secure_display.mul_roi_ctl.roi_ctl[i].x_start = window[i].rect.x;
582 cmd.secure_display.mul_roi_ctl.roi_ctl[i].y_start = window[i].rect.y;
583 cmd.secure_display.mul_roi_ctl.roi_ctl[i].x_end = window[i].rect.x + window[i].rect.width;
584 cmd.secure_display.mul_roi_ctl.roi_ctl[i].y_end = window[i].rect.y + window[i].rect.height;
585 cmd.secure_display.mul_roi_ctl.roi_ctl[i].enable = window[i].enable;
586 }
587 }
588
589 dc_wake_and_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
590 }
591
592 bool
dc_stream_forward_multiple_crc_window(struct dc_stream_state * stream,struct crc_window * window,uint8_t phy_id,bool stop)593 dc_stream_forward_multiple_crc_window(struct dc_stream_state *stream,
594 struct crc_window *window, uint8_t phy_id, bool stop)
595 {
596 struct dc_dmub_srv *dmub_srv;
597 struct otg_phy_mux mux_mapping;
598 struct pipe_ctx *pipe;
599 int i;
600 struct dc *dc = stream->ctx->dc;
601
602 for (i = 0; i < MAX_PIPES; i++) {
603 pipe = &dc->current_state->res_ctx.pipe_ctx[i];
604 if (pipe->stream == stream && !pipe->top_pipe && !pipe->prev_odm_pipe)
605 break;
606 }
607
608 /* Stream not found */
609 if (i == MAX_PIPES)
610 return false;
611
612 mux_mapping.phy_output_num = phy_id;
613 mux_mapping.otg_output_num = pipe->stream_res.tg->inst;
614
615 dmub_srv = dc->ctx->dmub_srv;
616
617 /* forward to dmub only. no dmcu support*/
618 if (dmub_srv)
619 dc_stream_forward_dmub_multiple_crc_window(dmub_srv, window, &mux_mapping, stop);
620 else
621 return false;
622
623 return true;
624 }
625 #endif /* CONFIG_DRM_AMD_SECURE_DISPLAY */
626
627 /**
628 * dc_stream_configure_crc() - Configure CRC capture for the given stream.
629 * @dc: DC Object
630 * @stream: The stream to configure CRC on.
631 * @crc_window: CRC window (x/y start/end) information
632 * @enable: Enable CRC if true, disable otherwise.
633 * @continuous: Capture CRC on every frame if true. Otherwise, only capture
634 * once.
635 * @idx: Capture CRC on which CRC engine instance
636 * @reset: Reset CRC engine before the configuration
637 * @crc_poly_mode: CRC polynomial mode
638 *
639 * By default, the entire frame is used to calculate the CRC.
640 *
641 * Return: %false if the stream is not found or CRC capture is not supported;
642 * %true if the stream has been configured.
643 */
dc_stream_configure_crc(struct dc * dc,struct dc_stream_state * stream,struct crc_params * crc_window,bool enable,bool continuous,uint8_t idx,bool reset,enum crc_poly_mode crc_poly_mode)644 bool dc_stream_configure_crc(struct dc *dc, struct dc_stream_state *stream,
645 struct crc_params *crc_window, bool enable, bool continuous,
646 uint8_t idx, bool reset, enum crc_poly_mode crc_poly_mode)
647 {
648 struct pipe_ctx *pipe;
649 struct crc_params param;
650 struct timing_generator *tg;
651
652 pipe = resource_get_otg_master_for_stream(
653 &dc->current_state->res_ctx, stream);
654
655 /* Stream not found */
656 if (pipe == NULL)
657 return false;
658
659 dc_exit_ips_for_hw_access(dc);
660
661 /* By default, capture the full frame */
662 param.windowa_x_start = 0;
663 param.windowa_y_start = 0;
664 param.windowa_x_end = (uint16_t)pipe->stream->timing.h_addressable;
665 param.windowa_y_end = (uint16_t)pipe->stream->timing.v_addressable;
666 param.windowb_x_start = 0;
667 param.windowb_y_start = 0;
668 param.windowb_x_end = (uint16_t)pipe->stream->timing.h_addressable;
669 param.windowb_y_end = (uint16_t)pipe->stream->timing.v_addressable;
670 param.crc_poly_mode = crc_poly_mode;
671
672 if (crc_window) {
673 param.windowa_x_start = crc_window->windowa_x_start;
674 param.windowa_y_start = crc_window->windowa_y_start;
675 param.windowa_x_end = crc_window->windowa_x_end;
676 param.windowa_y_end = crc_window->windowa_y_end;
677 param.windowb_x_start = crc_window->windowb_x_start;
678 param.windowb_y_start = crc_window->windowb_y_start;
679 param.windowb_x_end = crc_window->windowb_x_end;
680 param.windowb_y_end = crc_window->windowb_y_end;
681 }
682
683 param.dsc_mode = pipe->stream->timing.flags.DSC ? 1:0;
684 param.odm_mode = pipe->next_odm_pipe ? 1:0;
685
686 /* Default to the union of both windows */
687 param.selection = UNION_WINDOW_A_B;
688 param.continuous_mode = continuous;
689 param.enable = enable;
690
691 param.crc_eng_inst = idx;
692 param.reset = reset;
693
694 tg = pipe->stream_res.tg;
695
696 /* Only call if supported */
697 if (tg->funcs->configure_crc)
698 return tg->funcs->configure_crc(tg, ¶m);
699 DC_LOG_WARNING("CRC capture not supported.");
700 return false;
701 }
702
703 /**
704 * dc_stream_get_crc() - Get CRC values for the given stream.
705 *
706 * @dc: DC object.
707 * @stream: The DC stream state of the stream to get CRCs from.
708 * @idx: index of crc engine to get CRC from
709 * @r_cr: CRC value for the red component.
710 * @g_y: CRC value for the green component.
711 * @b_cb: CRC value for the blue component.
712 *
713 * dc_stream_configure_crc needs to be called beforehand to enable CRCs.
714 *
715 * Return:
716 * %false if stream is not found, or if CRCs are not enabled.
717 */
dc_stream_get_crc(struct dc * dc,struct dc_stream_state * stream,uint8_t idx,uint32_t * r_cr,uint32_t * g_y,uint32_t * b_cb)718 bool dc_stream_get_crc(struct dc *dc, struct dc_stream_state *stream, uint8_t idx,
719 uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb)
720 {
721 int i;
722 struct pipe_ctx *pipe = NULL;
723 struct timing_generator *tg;
724
725 dc_exit_ips_for_hw_access(dc);
726
727 for (i = 0; i < MAX_PIPES; i++) {
728 pipe = &dc->current_state->res_ctx.pipe_ctx[i];
729 if (pipe->stream == stream)
730 break;
731 }
732 /* Stream not found */
733 if (i == MAX_PIPES)
734 return false;
735
736 tg = pipe->stream_res.tg;
737
738 if (tg->funcs->get_crc)
739 return tg->funcs->get_crc(tg, idx, r_cr, g_y, b_cb);
740 DC_LOG_WARNING("CRC capture not supported.");
741 return false;
742 }
743
dc_stream_set_dyn_expansion(struct dc * dc,struct dc_stream_state * stream,enum dc_dynamic_expansion option)744 void dc_stream_set_dyn_expansion(struct dc *dc, struct dc_stream_state *stream,
745 enum dc_dynamic_expansion option)
746 {
747 /* OPP FMT dyn expansion updates*/
748 int i;
749 struct pipe_ctx *pipe_ctx;
750
751 dc_exit_ips_for_hw_access(dc);
752
753 for (i = 0; i < MAX_PIPES; i++) {
754 if (dc->current_state->res_ctx.pipe_ctx[i].stream
755 == stream) {
756 pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
757 pipe_ctx->stream_res.opp->dyn_expansion = option;
758 pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion(
759 pipe_ctx->stream_res.opp,
760 COLOR_SPACE_YCBCR601,
761 stream->timing.display_color_depth,
762 stream->signal);
763 }
764 }
765 }
766
dc_stream_set_dither_option(struct dc_stream_state * stream,enum dc_dither_option option)767 void dc_stream_set_dither_option(struct dc_stream_state *stream,
768 enum dc_dither_option option)
769 {
770 struct bit_depth_reduction_params params;
771 struct dc_link *link = stream->link;
772 struct resource_context *res_ctx = &link->dc->current_state->res_ctx;
773 struct pipe_ctx *otg_master;
774 struct pipe_ctx *opp_heads[MAX_PIPES];
775 int opp_cnt;
776 int i;
777
778 otg_master = resource_get_otg_master_for_stream(res_ctx, stream);
779 if (!otg_master)
780 return;
781 if (option > DITHER_OPTION_MAX)
782 return;
783
784 opp_cnt = resource_get_opp_heads_for_otg_master(otg_master, res_ctx, opp_heads);
785
786 if (opp_cnt == 0)
787 return;
788
789 dc_exit_ips_for_hw_access(stream->ctx->dc);
790
791 stream->dither_option = option;
792
793 memset(¶ms, 0, sizeof(params));
794 resource_build_bit_depth_reduction_params(stream, ¶ms);
795 stream->bit_depth_params = params;
796
797 /*
798 * Program bit-depth reduction (dither) on every OPP head of the
799 * stream. Under ODM combine there is more than one OPP head and they
800 * must all be kept in sync, otherwise (e.g. when CRC capture requests
801 * dither off) a secondary ODM segment can keep dither enabled and
802 * produce a different CRC than the primary segment.
803 */
804 for (i = 0; i < opp_cnt; i++) {
805 struct pipe_ctx *opp_head = opp_heads[i];
806
807 if (opp_head->plane_res.xfm &&
808 opp_head->plane_res.xfm->funcs->transform_set_pixel_storage_depth) {
809 opp_head->plane_res.xfm->funcs->transform_set_pixel_storage_depth(
810 opp_head->plane_res.xfm,
811 opp_head->plane_res.scl_data.lb_params.depth,
812 &stream->bit_depth_params);
813 }
814
815 if (opp_head->stream_res.opp &&
816 opp_head->stream_res.opp->funcs->opp_program_bit_depth_reduction) {
817 opp_head->stream_res.opp->funcs->opp_program_bit_depth_reduction(
818 opp_head->stream_res.opp, ¶ms);
819 }
820 }
821 }
822
dc_stream_set_gamut_remap(struct dc * dc,const struct dc_stream_state * stream)823 bool dc_stream_set_gamut_remap(struct dc *dc, const struct dc_stream_state *stream)
824 {
825 int i;
826 bool ret = false;
827 struct pipe_ctx *pipes;
828
829 dc_exit_ips_for_hw_access(dc);
830
831 for (i = 0; i < MAX_PIPES; i++) {
832 if (dc->current_state->res_ctx.pipe_ctx[i].stream == stream) {
833 pipes = &dc->current_state->res_ctx.pipe_ctx[i];
834 dc->hwss.program_gamut_remap(&(struct program_gamut_remap_params) {
835 .xfm = pipes->plane_res.xfm,
836 .dpp = pipes->plane_res.dpp,
837 .mpc = dc->res_pool->mpc,
838 .mpcc_id = pipes->plane_res.mpcc_inst,
839 .stream = pipes->stream,
840 .plane = pipes->plane_state,
841 .is_top_pipe = pipes->top_pipe == NULL,
842 });
843 ret = true;
844 }
845 }
846
847 return ret;
848 }
849
dc_stream_program_csc_matrix(struct dc * dc,struct dc_stream_state * stream)850 bool dc_stream_program_csc_matrix(struct dc *dc, struct dc_stream_state *stream)
851 {
852 int i;
853 bool ret = false;
854 struct pipe_ctx *pipes;
855
856 dc_exit_ips_for_hw_access(dc);
857
858 for (i = 0; i < MAX_PIPES; i++) {
859 if (dc->current_state->res_ctx.pipe_ctx[i].stream
860 == stream) {
861
862 pipes = &dc->current_state->res_ctx.pipe_ctx[i];
863 dc->hwss.program_output_csc(dc,
864 pipes,
865 stream->output_color_space,
866 stream->csc_color_matrix.matrix,
867 pipes->stream_res.opp->inst);
868 ret = true;
869 }
870 }
871
872 return ret;
873 }
874
dc_stream_set_static_screen_params(struct dc * dc,struct dc_stream_state ** streams,int num_streams,const struct dc_static_screen_params * params)875 void dc_stream_set_static_screen_params(struct dc *dc,
876 struct dc_stream_state **streams,
877 int num_streams,
878 const struct dc_static_screen_params *params)
879 {
880 int i, j;
881 struct pipe_ctx *pipes_affected[MAX_PIPES];
882 int num_pipes_affected = 0;
883
884 dc_exit_ips_for_hw_access(dc);
885
886 for (i = 0; i < num_streams; i++) {
887 struct dc_stream_state *stream = streams[i];
888
889 for (j = 0; j < MAX_PIPES; j++) {
890 if (dc->current_state->res_ctx.pipe_ctx[j].stream
891 == stream) {
892 pipes_affected[num_pipes_affected++] =
893 &dc->current_state->res_ctx.pipe_ctx[j];
894 }
895 }
896 }
897
898 dc->hwss.set_static_screen_control(pipes_affected, num_pipes_affected, params);
899 }
900
dc_destruct_update_scratch_pool(struct dc * dc)901 static void dc_destruct_update_scratch_pool(struct dc *dc)
902 {
903 unsigned int i;
904
905 for (i = 0; i < ARRAY_SIZE(dc->update_scratch_pool); i++) {
906 kfree(dc->update_scratch_pool[i]);
907 dc->update_scratch_pool[i] = NULL;
908 dc->update_scratch_in_use[i] = false;
909 }
910 }
911
dc_construct_update_scratch_pool(struct dc * dc)912 static bool dc_construct_update_scratch_pool(struct dc *dc)
913 {
914 unsigned int i;
915
916 for (i = 0; i < ARRAY_SIZE(dc->update_scratch_pool); i++) {
917 dc->update_scratch_pool[i] = kzalloc(
918 sizeof(struct dc_update_scratch_space), GFP_KERNEL);
919 if (!dc->update_scratch_pool[i])
920 return false;
921 dc->update_scratch_in_use[i] = false;
922 }
923
924 return true;
925 }
926
dc_destruct(struct dc * dc)927 static void dc_destruct(struct dc *dc)
928 {
929 // reset link encoder assignment table on destruct
930 if (dc->res_pool && dc->res_pool->funcs->link_encs_assign &&
931 !dc->config.unify_link_enc_assignment)
932 link_enc_cfg_init(dc, dc->current_state);
933
934 dc_destruct_update_scratch_pool(dc);
935
936 if (dc->current_state) {
937 dc_state_release(dc->current_state);
938 dc->current_state = NULL;
939 }
940
941 destroy_links(dc);
942
943 destroy_link_encoders(dc);
944
945 if (dc->clk_mgr) {
946 dc_destroy_clk_mgr(dc->clk_mgr);
947 dc->clk_mgr = NULL;
948 }
949
950 dc_destroy_resource_pool(dc);
951 #ifdef CONFIG_DRM_AMD_DC_FP
952 dc_destroy_soc_and_ip_translator(&dc->soc_and_ip_translator);
953 #endif
954 if (dc->link_srv)
955 link_destroy_link_service(&dc->link_srv);
956
957 if (dc->ctx) {
958 if (dc->ctx->gpio_service)
959 dal_gpio_service_destroy(&dc->ctx->gpio_service);
960
961 if (dc->ctx->created_bios)
962 dal_bios_parser_destroy(&dc->ctx->dc_bios);
963 kfree(dc->ctx->logger);
964 dc_perf_trace_destroy(&dc->ctx->perf_trace);
965
966 kfree(dc->ctx);
967 dc->ctx = NULL;
968 }
969
970 kfree(dc->bw_vbios);
971 dc->bw_vbios = NULL;
972
973 kfree(dc->bw_dceip);
974 dc->bw_dceip = NULL;
975
976 kfree(dc->dcn_soc);
977 dc->dcn_soc = NULL;
978
979 kfree(dc->dcn_ip);
980 dc->dcn_ip = NULL;
981
982 kfree(dc->vm_helper);
983 dc->vm_helper = NULL;
984
985 }
986
dc_construct_ctx(struct dc * dc,const struct dc_init_data * init_params)987 static bool dc_construct_ctx(struct dc *dc,
988 const struct dc_init_data *init_params)
989 {
990 struct dc_context *dc_ctx;
991
992 dc_ctx = kzalloc_obj(*dc_ctx);
993 if (!dc_ctx)
994 return false;
995
996 dc_stream_init_rmcm_3dlut(dc);
997
998 dc_ctx->cgs_device = init_params->cgs_device;
999 dc_ctx->driver_context = init_params->driver;
1000 dc_ctx->dc = dc;
1001 dc_ctx->asic_id = init_params->asic_id;
1002 dc_ctx->dc_sink_id_count = 0;
1003 dc_ctx->dc_stream_id_count = 0;
1004 dc_ctx->dce_environment = init_params->dce_environment;
1005 dc_ctx->dcn_reg_offsets = init_params->dcn_reg_offsets;
1006 dc_ctx->nbio_reg_offsets = init_params->nbio_reg_offsets;
1007 dc_ctx->clk_reg_offsets = init_params->clk_reg_offsets;
1008
1009 /* Create logger */
1010 dc_ctx->logger = kmalloc_obj(*dc_ctx->logger);
1011
1012 if (!dc_ctx->logger) {
1013 kfree(dc_ctx);
1014 return false;
1015 }
1016
1017 dc_ctx->logger->dev = adev_to_drm(init_params->driver);
1018 dc->dml.logger = dc_ctx->logger;
1019
1020 dc_ctx->dce_version = resource_parse_asic_id(init_params->asic_id);
1021
1022 dc_ctx->perf_trace = dc_perf_trace_create();
1023 if (!dc_ctx->perf_trace) {
1024 kfree(dc_ctx);
1025 ASSERT_CRITICAL(false);
1026 return false;
1027 }
1028
1029 dc->ctx = dc_ctx;
1030
1031 dc->link_srv = link_create_link_service();
1032 if (!dc->link_srv)
1033 return false;
1034
1035 return true;
1036 }
1037
dc_construct(struct dc * dc,const struct dc_init_data * init_params)1038 static bool dc_construct(struct dc *dc,
1039 const struct dc_init_data *init_params)
1040 {
1041 struct dc_context *dc_ctx;
1042 struct bw_calcs_dceip *dc_dceip;
1043 struct bw_calcs_vbios *dc_vbios;
1044 struct dcn_soc_bounding_box *dcn_soc;
1045 struct dcn_ip_params *dcn_ip;
1046
1047 dc->config = init_params->flags;
1048
1049 // Allocate memory for the vm_helper
1050 dc->vm_helper = kzalloc_obj(struct vm_helper);
1051 if (!dc->vm_helper) {
1052 dm_error("%s: failed to create dc->vm_helper\n", __func__);
1053 goto fail;
1054 }
1055
1056 memcpy(&dc->bb_overrides, &init_params->bb_overrides, sizeof(dc->bb_overrides));
1057
1058 dc_dceip = kzalloc_obj(*dc_dceip);
1059 if (!dc_dceip) {
1060 dm_error("%s: failed to create dceip\n", __func__);
1061 goto fail;
1062 }
1063
1064 dc->bw_dceip = dc_dceip;
1065
1066 dc_vbios = kzalloc_obj(*dc_vbios);
1067 if (!dc_vbios) {
1068 dm_error("%s: failed to create vbios\n", __func__);
1069 goto fail;
1070 }
1071
1072 dc->bw_vbios = dc_vbios;
1073 dcn_soc = kzalloc_obj(*dcn_soc);
1074 if (!dcn_soc) {
1075 dm_error("%s: failed to create dcn_soc\n", __func__);
1076 goto fail;
1077 }
1078
1079 dc->dcn_soc = dcn_soc;
1080
1081 dcn_ip = kzalloc_obj(*dcn_ip);
1082 if (!dcn_ip) {
1083 dm_error("%s: failed to create dcn_ip\n", __func__);
1084 goto fail;
1085 }
1086
1087 dc->dcn_ip = dcn_ip;
1088
1089 if (init_params->bb_from_dmub)
1090 dc->dml2_options.bb_from_dmub = init_params->bb_from_dmub;
1091 else
1092 dc->dml2_options.bb_from_dmub = NULL;
1093
1094 if (!dc_construct_ctx(dc, init_params)) {
1095 dm_error("%s: failed to create ctx\n", __func__);
1096 goto fail;
1097 }
1098
1099 dc_ctx = dc->ctx;
1100
1101 /* Resource should construct all asic specific resources.
1102 * This should be the only place where we need to parse the asic id
1103 */
1104 if (init_params->vbios_override)
1105 dc_ctx->dc_bios = init_params->vbios_override;
1106 else {
1107 /* Create BIOS parser */
1108 struct bp_init_data bp_init_data;
1109
1110 bp_init_data.ctx = dc_ctx;
1111 bp_init_data.bios = init_params->asic_id.atombios_base_address;
1112
1113 dc_ctx->dc_bios = dal_bios_parser_create(
1114 &bp_init_data, dc_ctx->dce_version);
1115
1116 if (!dc_ctx->dc_bios) {
1117 ASSERT_CRITICAL(false);
1118 goto fail;
1119 }
1120
1121 dc_ctx->created_bios = true;
1122 }
1123
1124 dc->vendor_signature = init_params->vendor_signature;
1125
1126 /* Create GPIO service */
1127 dc_ctx->gpio_service = dal_gpio_service_create(
1128 dc_ctx->dce_version,
1129 dc_ctx->dce_environment,
1130 dc_ctx);
1131
1132 if (!dc_ctx->gpio_service) {
1133 ASSERT_CRITICAL(false);
1134 goto fail;
1135 }
1136
1137 dc->res_pool = dc_create_resource_pool(dc, init_params, dc_ctx->dce_version);
1138 if (!dc->res_pool)
1139 goto fail;
1140
1141 /* set i2c speed if not done by the respective dcnxxx__resource.c */
1142 if (dc->caps.i2c_speed_in_khz_hdcp == 0)
1143 dc->caps.i2c_speed_in_khz_hdcp = dc->caps.i2c_speed_in_khz;
1144 if (dc->check_config.max_optimizable_video_width == 0)
1145 dc->check_config.max_optimizable_video_width = 5120;
1146 dc->clk_mgr = dc_clk_mgr_create(dc->ctx, dc->res_pool->pp_smu, dc->res_pool->dccg);
1147 if (!dc->clk_mgr)
1148 goto fail;
1149 #ifdef CONFIG_DRM_AMD_DC_FP
1150 dc->clk_mgr->force_smu_not_present = init_params->force_smu_not_present;
1151
1152 if (dc->res_pool->funcs->update_bw_bounding_box)
1153 dc->res_pool->funcs->update_bw_bounding_box(dc, dc->clk_mgr->bw_params);
1154 dc->soc_and_ip_translator = dc_create_soc_and_ip_translator(dc_ctx->dce_version);
1155 if (!dc->soc_and_ip_translator)
1156 goto fail;
1157 #endif
1158
1159 if (!create_links(dc, init_params->num_virtual_links))
1160 goto fail;
1161
1162 /* Create additional DIG link encoder objects if fewer than the platform
1163 * supports were created during link construction.
1164 */
1165 if (!create_link_encoders(dc))
1166 goto fail;
1167
1168 /* Creation of current_state must occur after dc->dml
1169 * is initialized in dc_create_resource_pool because
1170 * on creation it copies the contents of dc->dml
1171 */
1172 dc->current_state = dc_state_create(dc, NULL);
1173
1174 if (!dc->current_state) {
1175 dm_error("%s: failed to create validate ctx\n", __func__);
1176 goto fail;
1177 }
1178
1179 if (!dc_construct_update_scratch_pool(dc)) {
1180 dm_error("%s: failed to create update scratch pool\n", __func__);
1181 goto fail;
1182 }
1183
1184 return true;
1185
1186 fail:
1187 return false;
1188 }
1189
disable_all_writeback_pipes_for_stream(const struct dc * dc,struct dc_stream_state * stream,struct dc_state * context)1190 static void disable_all_writeback_pipes_for_stream(
1191 const struct dc *dc,
1192 struct dc_stream_state *stream,
1193 struct dc_state *context)
1194 {
1195 (void)dc;
1196 (void)context;
1197 unsigned int i;
1198
1199 for (i = 0; i < stream->num_wb_info; i++)
1200 stream->writeback_info[i].wb_enabled = false;
1201 }
1202
apply_ctx_interdependent_lock(struct dc * dc,struct dc_state * context,struct dc_stream_state * stream,bool lock)1203 static void apply_ctx_interdependent_lock(struct dc *dc,
1204 struct dc_state *context,
1205 struct dc_stream_state *stream,
1206 bool lock)
1207 {
1208 (void)dc;
1209 (void)context;
1210 unsigned int i;
1211
1212 /* Checks if interdependent update function pointer is NULL or not, takes care of DCE110 case */
1213 if (dc->hwss.interdependent_update_lock)
1214 dc->hwss.interdependent_update_lock(dc, context, lock);
1215 else {
1216 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1217 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1218 struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
1219
1220 // Copied conditions that were previously in dce110_apply_ctx_for_surface
1221 if (stream == pipe_ctx->stream) {
1222 if (resource_is_pipe_type(pipe_ctx, OPP_HEAD) &&
1223 (pipe_ctx->plane_state || old_pipe_ctx->plane_state))
1224 dc->hwss.pipe_control_lock(dc, pipe_ctx, lock);
1225 }
1226 }
1227 }
1228 }
1229
dc_update_visual_confirm_color(struct dc * dc,struct dc_state * context,struct pipe_ctx * pipe_ctx)1230 static void dc_update_visual_confirm_color(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx)
1231 {
1232 if (dc->debug.visual_confirm & VISUAL_CONFIRM_EXPLICIT) {
1233 memcpy(&pipe_ctx->visual_confirm_color, &pipe_ctx->plane_state->visual_confirm_color,
1234 sizeof(pipe_ctx->visual_confirm_color));
1235 return;
1236 }
1237
1238 if (dc->ctx->dce_version >= DCN_VERSION_1_0) {
1239 memset(&pipe_ctx->visual_confirm_color, 0, sizeof(struct tg_color));
1240
1241 if (dc->debug.visual_confirm == VISUAL_CONFIRM_HDR)
1242 get_hdr_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color));
1243 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE)
1244 get_surface_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color));
1245 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SWIZZLE)
1246 get_surface_tile_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color));
1247 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_HW_CURSOR)
1248 get_cursor_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color));
1249 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_DCC)
1250 get_dcc_visual_confirm_color(dc, pipe_ctx, &(pipe_ctx->visual_confirm_color));
1251 else {
1252 if (dc->ctx->dce_version < DCN_VERSION_2_0)
1253 color_space_to_black_color(
1254 dc, pipe_ctx->stream->output_color_space, &(pipe_ctx->visual_confirm_color));
1255 }
1256 if (dc->ctx->dce_version >= DCN_VERSION_2_0) {
1257 if (dc->debug.visual_confirm == VISUAL_CONFIRM_MPCTREE)
1258 get_mpctree_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color));
1259 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SUBVP)
1260 get_subvp_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color));
1261 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_MCLK_SWITCH)
1262 get_mclk_switch_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color));
1263 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_FAMS2)
1264 get_fams2_visual_confirm_color(dc, context, pipe_ctx, &(pipe_ctx->visual_confirm_color));
1265 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_VABC)
1266 get_vabc_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color));
1267 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_BOOSTED_REFRESH_RATE)
1268 get_refresh_rate_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color));
1269 }
1270 }
1271 }
1272
dc_get_visual_confirm_for_stream(struct dc * dc,struct dc_stream_state * stream_state,struct tg_color * color)1273 void dc_get_visual_confirm_for_stream(
1274 struct dc *dc,
1275 struct dc_stream_state *stream_state,
1276 struct tg_color *color)
1277 {
1278 struct dc_stream_status *stream_status = dc_stream_get_status(stream_state);
1279 struct pipe_ctx *pipe_ctx;
1280 int i;
1281 struct dc_plane_state *plane_state = NULL;
1282
1283 if (!stream_status)
1284 return;
1285
1286 switch (dc->debug.visual_confirm) {
1287 case VISUAL_CONFIRM_DISABLE:
1288 return;
1289 case VISUAL_CONFIRM_PSR:
1290 case VISUAL_CONFIRM_FAMS:
1291 pipe_ctx = dc_stream_get_pipe_ctx(stream_state);
1292 if (!pipe_ctx)
1293 return;
1294 dc_dmub_srv_get_visual_confirm_color_cmd(dc, pipe_ctx);
1295 memcpy(color, &dc->ctx->dmub_srv->dmub->visual_confirm_color, sizeof(struct tg_color));
1296 return;
1297
1298 default:
1299 /* find plane with highest layer_index */
1300 for (i = 0; i < stream_status->plane_count; i++) {
1301 if (stream_status->plane_states[i]->visible)
1302 plane_state = stream_status->plane_states[i];
1303 }
1304 if (!plane_state)
1305 return;
1306 /* find pipe that contains plane with highest layer index */
1307 for (i = 0; i < MAX_PIPES; i++) {
1308 struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
1309
1310 if (pipe->plane_state == plane_state) {
1311 memcpy(color, &pipe->visual_confirm_color, sizeof(struct tg_color));
1312 return;
1313 }
1314 }
1315 }
1316 }
1317
1318 /**
1319 * dc_stream_adjust_vmin_vmax - look up pipe context & update parts of DRR
1320 * @dc: dc reference
1321 * @stream: Initial dc stream state
1322 * @adjust: Updated parameters for vertical_total_min and vertical_total_max
1323 *
1324 * Looks up the pipe context of dc_stream_state and updates the
1325 * vertical_total_min and vertical_total_max of the DRR, Dynamic Refresh
1326 * Rate, which is a power-saving feature that targets reducing panel
1327 * refresh rate while the screen is static
1328 *
1329 * Return: %true if the pipe context is found and adjusted;
1330 * %false if the pipe context is not found.
1331 */
dc_stream_adjust_vmin_vmax(struct dc * dc,struct dc_stream_state * stream,struct dc_crtc_timing_adjust * adjust)1332 bool dc_stream_adjust_vmin_vmax(struct dc *dc,
1333 struct dc_stream_state *stream,
1334 struct dc_crtc_timing_adjust *adjust)
1335 {
1336 int i;
1337
1338 /*
1339 * Don't adjust DRR while there's bandwidth optimizations pending to
1340 * avoid conflicting with firmware updates.
1341 */
1342 if (dc->ctx->dce_version > DCE_VERSION_MAX) {
1343 if (dc->optimized_required &&
1344 (stream->adjust.v_total_max != adjust->v_total_max ||
1345 stream->adjust.v_total_min != adjust->v_total_min)) {
1346 stream->adjust.timing_adjust_pending = true;
1347 return false;
1348 }
1349 }
1350
1351 dc_exit_ips_for_hw_access(dc);
1352
1353 stream->adjust.v_total_max = adjust->v_total_max;
1354 stream->adjust.v_total_mid = adjust->v_total_mid;
1355 stream->adjust.v_total_mid_frame_num = adjust->v_total_mid_frame_num;
1356 stream->adjust.v_total_min = adjust->v_total_min;
1357 stream->adjust.allow_otg_v_count_halt = adjust->allow_otg_v_count_halt;
1358
1359 if (dc->caps.max_v_total != 0 &&
1360 (adjust->v_total_max > dc->caps.max_v_total || adjust->v_total_min > dc->caps.max_v_total)) {
1361 stream->adjust.timing_adjust_pending = false;
1362 if (adjust->allow_otg_v_count_halt)
1363 return set_long_vtotal(dc, stream, adjust);
1364 else
1365 return false;
1366 }
1367
1368 for (i = 0; i < MAX_PIPES; i++) {
1369 struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
1370
1371 if (pipe->stream == stream && pipe->stream_res.tg) {
1372 dc->hwss.set_drr(&pipe,
1373 1,
1374 *adjust);
1375 stream->adjust.timing_adjust_pending = false;
1376
1377 if (dc->debug.visual_confirm == VISUAL_CONFIRM_BOOSTED_REFRESH_RATE) {
1378 if (pipe->stream && pipe->plane_state) {
1379 dc_update_visual_confirm_color(dc, dc->current_state, pipe);
1380 dc->hwss.update_visual_confirm_color(dc, pipe, pipe->plane_res.hubp->mpcc_id);
1381
1382 }
1383 }
1384
1385 if (dc->hwss.notify_cursor_offload_drr_update)
1386 dc->hwss.notify_cursor_offload_drr_update(dc, dc->current_state, stream);
1387
1388 return true;
1389 }
1390 }
1391
1392 return false;
1393 }
1394
disable_dangling_plane(struct dc * dc,struct dc_state * context)1395 static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
1396 {
1397 unsigned int i, j;
1398 struct dc_state *dangling_context = dc_state_create_current_copy(dc);
1399 struct dc_state *current_ctx;
1400 struct pipe_ctx *pipe;
1401 struct timing_generator *tg;
1402
1403 if (dangling_context == NULL)
1404 return;
1405
1406 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1407 struct dc_stream_state *old_stream =
1408 dc->current_state->res_ctx.pipe_ctx[i].stream;
1409 bool should_disable = true;
1410 bool pipe_split_change = false;
1411
1412 if ((context->res_ctx.pipe_ctx[i].top_pipe) &&
1413 (dc->current_state->res_ctx.pipe_ctx[i].top_pipe))
1414 pipe_split_change = context->res_ctx.pipe_ctx[i].top_pipe->pipe_idx !=
1415 dc->current_state->res_ctx.pipe_ctx[i].top_pipe->pipe_idx;
1416 else
1417 pipe_split_change = context->res_ctx.pipe_ctx[i].top_pipe !=
1418 dc->current_state->res_ctx.pipe_ctx[i].top_pipe;
1419
1420 for (j = 0; j < context->stream_count; j++) {
1421 if (old_stream == context->streams[j]) {
1422 should_disable = false;
1423 break;
1424 }
1425 }
1426 if (!should_disable && pipe_split_change &&
1427 dc->current_state->stream_count != context->stream_count)
1428 should_disable = true;
1429
1430 if (old_stream && !dc->current_state->res_ctx.pipe_ctx[i].top_pipe &&
1431 !dc->current_state->res_ctx.pipe_ctx[i].prev_odm_pipe) {
1432 struct pipe_ctx *old_pipe, *new_pipe;
1433
1434 old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
1435 new_pipe = &context->res_ctx.pipe_ctx[i];
1436
1437 if (old_pipe->plane_state && !new_pipe->plane_state)
1438 should_disable = true;
1439 }
1440
1441 if (should_disable && old_stream) {
1442 bool is_phantom = dc_state_get_stream_subvp_type(dc->current_state, old_stream) == SUBVP_PHANTOM;
1443 pipe = &dc->current_state->res_ctx.pipe_ctx[i];
1444 tg = pipe->stream_res.tg;
1445 /* When disabling plane for a phantom pipe, we must turn on the
1446 * phantom OTG so the disable programming gets the double buffer
1447 * update. Otherwise the pipe will be left in a partially disabled
1448 * state that can result in underflow or hang when enabling it
1449 * again for different use.
1450 */
1451 if (is_phantom) {
1452 if (tg->funcs->enable_crtc) {
1453 if (dc->hwseq->funcs.blank_pixel_data)
1454 dc->hwseq->funcs.blank_pixel_data(dc, pipe, true);
1455 tg->funcs->enable_crtc(tg);
1456 }
1457 }
1458
1459 if (is_phantom)
1460 dc_state_rem_all_phantom_planes_for_stream(dc, old_stream, dangling_context, true);
1461 else
1462 dc_state_rem_all_planes_for_stream(dc, old_stream, dangling_context);
1463 disable_all_writeback_pipes_for_stream(dc, old_stream, dangling_context);
1464
1465 if (pipe->stream && pipe->plane_state) {
1466 if (!dc->debug.using_dml2)
1467 set_p_state_switch_method(dc, context, pipe);
1468 dc_update_visual_confirm_color(dc, context, pipe);
1469 }
1470
1471 if (dc->hwss.apply_ctx_for_surface) {
1472 apply_ctx_interdependent_lock(dc, dc->current_state, old_stream, true);
1473 dc->hwss.apply_ctx_for_surface(dc, old_stream, 0, dangling_context);
1474 apply_ctx_interdependent_lock(dc, dc->current_state, old_stream, false);
1475 dc->hwss.post_unlock_program_front_end(dc, dangling_context);
1476 }
1477
1478 if (dc->res_pool->funcs->prepare_mcache_programming)
1479 dc->res_pool->funcs->prepare_mcache_programming(dc, dangling_context);
1480 if (dc->hwss.program_front_end_for_ctx) {
1481 dc->hwss.interdependent_update_lock(dc, dc->current_state, true);
1482 dc->hwss.program_front_end_for_ctx(dc, dangling_context);
1483 dc->hwss.interdependent_update_lock(dc, dc->current_state, false);
1484 dc->hwss.post_unlock_program_front_end(dc, dangling_context);
1485 }
1486 /* We need to put the phantom OTG back into it's default (disabled) state or we
1487 * can get corruption when transition from one SubVP config to a different one.
1488 * The OTG is set to disable on falling edge of VUPDATE so the plane disable
1489 * will still get it's double buffer update.
1490 */
1491 if (is_phantom) {
1492 if (tg->funcs->disable_phantom_crtc)
1493 tg->funcs->disable_phantom_crtc(tg);
1494 }
1495 }
1496 }
1497
1498 current_ctx = dc->current_state;
1499 dc->current_state = dangling_context;
1500 dc_state_release(current_ctx);
1501 }
1502
disable_vbios_mode_if_required(struct dc * dc,struct dc_state * context)1503 static void disable_vbios_mode_if_required(
1504 struct dc *dc,
1505 struct dc_state *context)
1506 {
1507 unsigned int i, j;
1508
1509 /* check if timing_changed, disable stream*/
1510 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1511 struct dc_stream_state *stream = NULL;
1512 struct dc_link *link = NULL;
1513 struct pipe_ctx *pipe = NULL;
1514
1515 pipe = &context->res_ctx.pipe_ctx[i];
1516 stream = pipe->stream;
1517 if (stream == NULL)
1518 continue;
1519
1520 if (stream->apply_seamless_boot_optimization)
1521 continue;
1522
1523 // only looking for first odm pipe
1524 if (pipe->prev_odm_pipe)
1525 continue;
1526
1527 if (stream->link->local_sink &&
1528 stream->link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
1529 link = stream->link;
1530 }
1531
1532 if (link != NULL && link->link_enc->funcs->is_dig_enabled(link->link_enc)) {
1533 unsigned int enc_inst, tg_inst = 0;
1534 unsigned int pix_clk_100hz = 0;
1535
1536 enc_inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);
1537 if (enc_inst != ENGINE_ID_UNKNOWN) {
1538 for (j = 0; j < dc->res_pool->stream_enc_count; j++) {
1539 if (dc->res_pool->stream_enc[j]->id == enc_inst) {
1540 tg_inst = dc->res_pool->stream_enc[j]->funcs->dig_source_otg(
1541 dc->res_pool->stream_enc[j]);
1542 break;
1543 }
1544 }
1545
1546 dc->res_pool->dp_clock_source->funcs->get_dp_dto_frequency_100hz(
1547 dc->res_pool->dp_clock_source,
1548 tg_inst, &pix_clk_100hz);
1549
1550 if (link->link_status.link_active) {
1551 uint32_t requested_pix_clk_100hz =
1552 pipe->stream_res.pix_clk_params.requested_pix_clk_100hz;
1553
1554 if (pix_clk_100hz != requested_pix_clk_100hz) {
1555 dc->link_srv->set_dpms_off(pipe);
1556 pipe->stream->dpms_off = false;
1557 }
1558 }
1559 }
1560 }
1561 }
1562 }
1563
1564 /* Public functions */
1565
dc_create(const struct dc_init_data * init_params)1566 struct dc *dc_create(const struct dc_init_data *init_params)
1567 {
1568 struct dc *dc = kvzalloc_obj(*dc);
1569 unsigned int full_pipe_count;
1570
1571 if (!dc)
1572 return NULL;
1573
1574 if (init_params->dce_environment == DCE_ENV_VIRTUAL_HW) {
1575 dc->caps.linear_pitch_alignment = 64;
1576 if (!dc_construct_ctx(dc, init_params))
1577 goto destruct_dc;
1578 } else {
1579 if (!dc_construct(dc, init_params))
1580 goto destruct_dc;
1581
1582 full_pipe_count = dc->res_pool->pipe_count;
1583 if (dc->res_pool->underlay_pipe_index != NO_UNDERLAY_PIPE)
1584 full_pipe_count--;
1585 dc->caps.max_streams = min(
1586 full_pipe_count,
1587 dc->res_pool->stream_enc_count);
1588
1589 dc->caps.max_links = dc->link_count;
1590 dc->caps.max_audios = dc->res_pool->audio_count;
1591 dc->caps.linear_pitch_alignment = 64;
1592
1593 dc->caps.max_dp_protocol_version = DP_VERSION_1_4;
1594
1595 dc->caps.max_otg_num = dc->res_pool->res_cap->num_timing_generator;
1596
1597 if (dc->res_pool->dmcu != NULL)
1598 dc->versions.dmcu_version = dc->res_pool->dmcu->dmcu_version;
1599 }
1600
1601 dc->dcn_reg_offsets = init_params->dcn_reg_offsets;
1602 dc->nbio_reg_offsets = init_params->nbio_reg_offsets;
1603 dc->clk_reg_offsets = init_params->clk_reg_offsets;
1604
1605 /* Populate versioning information */
1606 dc->versions.dc_ver = DC_VER;
1607
1608 dc->build_id = DC_BUILD_ID;
1609
1610 DC_LOG_DC("Display Core initialized\n");
1611
1612 return dc;
1613
1614 destruct_dc:
1615 dc_destruct(dc);
1616 kvfree(dc);
1617 return NULL;
1618 }
1619
detect_edp_presence(struct dc * dc)1620 static void detect_edp_presence(struct dc *dc)
1621 {
1622 struct dc_link *edp_links[MAX_NUM_EDP];
1623 struct dc_link *edp_link = NULL;
1624 enum dc_connection_type type;
1625 unsigned int i, edp_num;
1626
1627 dc_get_edp_links(dc, edp_links, &edp_num);
1628 if (!edp_num)
1629 return;
1630
1631 for (i = 0; i < edp_num; i++) {
1632 edp_link = edp_links[i];
1633 if (dc->config.edp_not_connected) {
1634 edp_link->edp_sink_present = false;
1635 } else {
1636 dc_link_detect_connection_type(edp_link, &type);
1637 edp_link->edp_sink_present = (type != dc_connection_none);
1638 }
1639 }
1640 }
1641
dc_hardware_init(struct dc * dc)1642 void dc_hardware_init(struct dc *dc)
1643 {
1644
1645 detect_edp_presence(dc);
1646 if (dc->ctx->dce_environment != DCE_ENV_VIRTUAL_HW)
1647 dc->hwss.init_hw(dc);
1648 dc_dmub_srv_notify_fw_dc_power_state(dc->ctx->dmub_srv, DC_ACPI_CM_POWER_STATE_D0);
1649 }
1650
dc_init_callbacks(struct dc * dc,const struct dc_callback_init * init_params)1651 void dc_init_callbacks(struct dc *dc,
1652 const struct dc_callback_init *init_params)
1653 {
1654 dc->ctx->cp_psp = init_params->cp_psp;
1655 }
1656
dc_deinit_callbacks(struct dc * dc)1657 void dc_deinit_callbacks(struct dc *dc)
1658 {
1659 memset(&dc->ctx->cp_psp, 0, sizeof(dc->ctx->cp_psp));
1660 }
1661
dc_destroy(struct dc ** dc)1662 void dc_destroy(struct dc **dc)
1663 {
1664 dc_destruct(*dc);
1665 kvfree(*dc);
1666 *dc = NULL;
1667 }
1668
enable_timing_multisync(struct dc * dc,struct dc_state * ctx)1669 static void enable_timing_multisync(
1670 struct dc *dc,
1671 struct dc_state *ctx)
1672 {
1673 int i, multisync_count = 0;
1674 int pipe_count = dc->res_pool->pipe_count;
1675 struct pipe_ctx *multisync_pipes[MAX_PIPES] = { NULL };
1676
1677 for (i = 0; i < pipe_count; i++) {
1678 if (!ctx->res_ctx.pipe_ctx[i].stream ||
1679 !ctx->res_ctx.pipe_ctx[i].stream->triggered_crtc_reset.enabled)
1680 continue;
1681 if (ctx->res_ctx.pipe_ctx[i].stream == ctx->res_ctx.pipe_ctx[i].stream->triggered_crtc_reset.event_source)
1682 continue;
1683 multisync_pipes[multisync_count] = &ctx->res_ctx.pipe_ctx[i];
1684 multisync_count++;
1685 }
1686
1687 if (multisync_count > 0) {
1688 dc->hwss.enable_per_frame_crtc_position_reset(
1689 dc, multisync_count, multisync_pipes);
1690 }
1691 }
1692
program_timing_sync(struct dc * dc,struct dc_state * ctx)1693 static void program_timing_sync(
1694 struct dc *dc,
1695 struct dc_state *ctx)
1696 {
1697 int i, j, k;
1698 int group_index = 0;
1699 int num_group = 0;
1700 int pipe_count = dc->res_pool->pipe_count;
1701 struct pipe_ctx *unsynced_pipes[MAX_PIPES] = { NULL };
1702
1703 for (i = 0; i < pipe_count; i++) {
1704 if (!ctx->res_ctx.pipe_ctx[i].stream
1705 || ctx->res_ctx.pipe_ctx[i].top_pipe
1706 || ctx->res_ctx.pipe_ctx[i].prev_odm_pipe)
1707 continue;
1708
1709 unsynced_pipes[i] = &ctx->res_ctx.pipe_ctx[i];
1710 }
1711
1712 for (i = 0; i < pipe_count; i++) {
1713 int group_size = 1;
1714 enum timing_synchronization_type sync_type = NOT_SYNCHRONIZABLE;
1715 struct pipe_ctx *pipe_set[MAX_PIPES];
1716
1717 if (!unsynced_pipes[i])
1718 continue;
1719
1720 pipe_set[0] = unsynced_pipes[i];
1721 unsynced_pipes[i] = NULL;
1722
1723 /* Add tg to the set, search rest of the tg's for ones with
1724 * same timing, add all tgs with same timing to the group
1725 */
1726 for (j = i + 1; j < pipe_count; j++) {
1727 if (!unsynced_pipes[j])
1728 continue;
1729 if (sync_type != TIMING_SYNCHRONIZABLE &&
1730 dc->hwss.enable_vblanks_synchronization &&
1731 unsynced_pipes[j]->stream_res.tg->funcs->align_vblanks &&
1732 resource_are_vblanks_synchronizable(
1733 unsynced_pipes[j]->stream,
1734 pipe_set[0]->stream)) {
1735 sync_type = VBLANK_SYNCHRONIZABLE;
1736 pipe_set[group_size] = unsynced_pipes[j];
1737 unsynced_pipes[j] = NULL;
1738 group_size++;
1739 } else
1740 if (sync_type != VBLANK_SYNCHRONIZABLE &&
1741 resource_are_streams_timing_synchronizable(
1742 unsynced_pipes[j]->stream,
1743 pipe_set[0]->stream)) {
1744 sync_type = TIMING_SYNCHRONIZABLE;
1745 pipe_set[group_size] = unsynced_pipes[j];
1746 unsynced_pipes[j] = NULL;
1747 group_size++;
1748 }
1749 }
1750
1751 /* set first unblanked pipe as master */
1752 for (j = 0; j < group_size; j++) {
1753 bool is_blanked;
1754
1755 if (pipe_set[j]->stream_res.opp->funcs->dpg_is_blanked)
1756 is_blanked =
1757 pipe_set[j]->stream_res.opp->funcs->dpg_is_blanked(pipe_set[j]->stream_res.opp);
1758 else
1759 is_blanked =
1760 pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg);
1761 if (!is_blanked) {
1762 if (j == 0)
1763 break;
1764
1765 swap(pipe_set[0], pipe_set[j]);
1766 break;
1767 }
1768 }
1769
1770 for (k = 0; k < group_size; k++) {
1771 struct dc_stream_status *status = dc_state_get_stream_status(ctx, pipe_set[k]->stream);
1772
1773 if (!status)
1774 continue;
1775
1776 status->timing_sync_info.group_id = num_group;
1777 status->timing_sync_info.group_size = group_size;
1778 if (k == 0)
1779 status->timing_sync_info.master = true;
1780 else
1781 status->timing_sync_info.master = false;
1782
1783 }
1784
1785 /* remove any other unblanked pipes as they have already been synced */
1786 if (dc->config.use_pipe_ctx_sync_logic) {
1787 /* check pipe's syncd to decide which pipe to be removed */
1788 for (j = 1; j < group_size; j++) {
1789 if (pipe_set[j]->pipe_idx_syncd == pipe_set[0]->pipe_idx_syncd) {
1790 group_size--;
1791 pipe_set[j] = pipe_set[group_size];
1792 j--;
1793 } else
1794 /* link slave pipe's syncd with master pipe */
1795 pipe_set[j]->pipe_idx_syncd = pipe_set[0]->pipe_idx_syncd;
1796 }
1797 } else {
1798 /* remove any other pipes by checking valid plane */
1799 for (j = j + 1; j < group_size; j++) {
1800 bool is_blanked;
1801
1802 if (pipe_set[j]->stream_res.opp->funcs->dpg_is_blanked)
1803 is_blanked =
1804 pipe_set[j]->stream_res.opp->funcs->dpg_is_blanked(pipe_set[j]->stream_res.opp);
1805 else
1806 is_blanked =
1807 pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg);
1808 if (!is_blanked) {
1809 group_size--;
1810 pipe_set[j] = pipe_set[group_size];
1811 j--;
1812 }
1813 }
1814 }
1815
1816 if (group_size > 1) {
1817 if (sync_type == TIMING_SYNCHRONIZABLE) {
1818 dc->hwss.enable_timing_synchronization(
1819 dc, ctx, group_index, group_size, pipe_set);
1820 } else
1821 if (sync_type == VBLANK_SYNCHRONIZABLE) {
1822 dc->hwss.enable_vblanks_synchronization(
1823 dc, group_index, group_size, pipe_set);
1824 }
1825 group_index++;
1826 }
1827 num_group++;
1828 }
1829 }
1830
streams_changed(struct dc * dc,struct dc_stream_state * streams[],uint8_t stream_count)1831 static bool streams_changed(struct dc *dc,
1832 struct dc_stream_state *streams[],
1833 uint8_t stream_count)
1834 {
1835 uint8_t i;
1836
1837 if (stream_count != dc->current_state->stream_count)
1838 return true;
1839
1840 for (i = 0; i < dc->current_state->stream_count; i++) {
1841 if (dc->current_state->streams[i] != streams[i])
1842 return true;
1843 if (!streams[i]->link->link_state_valid)
1844 return true;
1845 }
1846
1847 return false;
1848 }
1849
dc_validate_boot_timing(const struct dc * dc,const struct dc_sink * sink,struct dc_crtc_timing * crtc_timing)1850 bool dc_validate_boot_timing(const struct dc *dc,
1851 const struct dc_sink *sink,
1852 struct dc_crtc_timing *crtc_timing)
1853 {
1854 struct timing_generator *tg;
1855 struct stream_encoder *se = NULL;
1856
1857 struct dc_crtc_timing hw_crtc_timing = {0};
1858
1859 struct dc_link *link = sink->link;
1860 unsigned int i, enc_inst;
1861 unsigned int tg_inst = 0;
1862
1863 /* Support seamless boot on EDP displays only */
1864 if (sink->sink_signal != SIGNAL_TYPE_EDP) {
1865 return false;
1866 }
1867
1868 if (dc->debug.force_odm_combine) {
1869 DC_LOG_DEBUG("boot timing validation failed due to force_odm_combine\n");
1870 return false;
1871 }
1872
1873 /* Check for enabled DIG to identify enabled display */
1874 if (!link->link_enc->funcs->is_dig_enabled(link->link_enc)) {
1875 DC_LOG_DEBUG("boot timing validation failed due to disabled DIG\n");
1876 return false;
1877 }
1878
1879 enc_inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);
1880
1881 if (enc_inst == ENGINE_ID_UNKNOWN) {
1882 DC_LOG_DEBUG("boot timing validation failed due to unknown DIG engine ID\n");
1883 return false;
1884 }
1885
1886 for (i = 0; i < dc->res_pool->stream_enc_count; i++) {
1887 if (dc->res_pool->stream_enc[i]->id == enc_inst) {
1888
1889 se = dc->res_pool->stream_enc[i];
1890
1891 tg_inst = dc->res_pool->stream_enc[i]->funcs->dig_source_otg(
1892 dc->res_pool->stream_enc[i]);
1893 break;
1894 }
1895 }
1896
1897 // tg_inst not found
1898 if (i == dc->res_pool->stream_enc_count) {
1899 DC_LOG_DEBUG("boot timing validation failed due to timing generator instance not found\n");
1900 return false;
1901 }
1902
1903 if (tg_inst >= dc->res_pool->timing_generator_count) {
1904 DC_LOG_DEBUG("boot timing validation failed due to invalid timing generator count\n");
1905 return false;
1906 }
1907
1908 if (tg_inst != link->link_enc->preferred_engine) {
1909 DC_LOG_DEBUG("boot timing validation failed due to non-preferred timing generator\n");
1910 return false;
1911 }
1912
1913 tg = dc->res_pool->timing_generators[tg_inst];
1914
1915 if (!tg->funcs->get_hw_timing) {
1916 DC_LOG_DEBUG("boot timing validation failed due to missing get_hw_timing callback\n");
1917 return false;
1918 }
1919
1920 if (!tg->funcs->get_hw_timing(tg, &hw_crtc_timing)) {
1921 DC_LOG_DEBUG("boot timing validation failed due to failed get_hw_timing return\n");
1922 return false;
1923 }
1924
1925 if (crtc_timing->h_total != hw_crtc_timing.h_total) {
1926 DC_LOG_DEBUG("boot timing validation failed due to h_total mismatch\n");
1927 return false;
1928 }
1929
1930 if (crtc_timing->h_border_left != hw_crtc_timing.h_border_left) {
1931 DC_LOG_DEBUG("boot timing validation failed due to h_border_left mismatch\n");
1932 return false;
1933 }
1934
1935 if (crtc_timing->h_addressable != hw_crtc_timing.h_addressable) {
1936 DC_LOG_DEBUG("boot timing validation failed due to h_addressable mismatch\n");
1937 return false;
1938 }
1939
1940 if (crtc_timing->h_border_right != hw_crtc_timing.h_border_right) {
1941 DC_LOG_DEBUG("boot timing validation failed due to h_border_right mismatch\n");
1942 return false;
1943 }
1944
1945 if (crtc_timing->h_front_porch != hw_crtc_timing.h_front_porch) {
1946 DC_LOG_DEBUG("boot timing validation failed due to h_front_porch mismatch\n");
1947 return false;
1948 }
1949
1950 if (crtc_timing->h_sync_width != hw_crtc_timing.h_sync_width) {
1951 DC_LOG_DEBUG("boot timing validation failed due to h_sync_width mismatch\n");
1952 return false;
1953 }
1954
1955 if (crtc_timing->v_total != hw_crtc_timing.v_total) {
1956 DC_LOG_DEBUG("boot timing validation failed due to v_total mismatch\n");
1957 return false;
1958 }
1959
1960 if (crtc_timing->v_border_top != hw_crtc_timing.v_border_top) {
1961 DC_LOG_DEBUG("boot timing validation failed due to v_border_top mismatch\n");
1962 return false;
1963 }
1964
1965 if (crtc_timing->v_addressable != hw_crtc_timing.v_addressable) {
1966 DC_LOG_DEBUG("boot timing validation failed due to v_addressable mismatch\n");
1967 return false;
1968 }
1969
1970 if (crtc_timing->v_border_bottom != hw_crtc_timing.v_border_bottom) {
1971 DC_LOG_DEBUG("boot timing validation failed due to v_border_bottom mismatch\n");
1972 return false;
1973 }
1974
1975 if (crtc_timing->v_front_porch != hw_crtc_timing.v_front_porch) {
1976 DC_LOG_DEBUG("boot timing validation failed due to v_front_porch mismatch\n");
1977 return false;
1978 }
1979
1980 if (crtc_timing->v_sync_width != hw_crtc_timing.v_sync_width) {
1981 DC_LOG_DEBUG("boot timing validation failed due to v_sync_width mismatch\n");
1982 return false;
1983 }
1984
1985 if (crtc_timing->flags.DSC) {
1986 struct display_stream_compressor *dsc = NULL;
1987 struct dcn_dsc_state dsc_state = {0};
1988
1989 if (dc->ctx->dce_version < DCN_VERSION_4_2) {
1990 /*vbios enabled eDP dsc for one of DCN315 only but it has known issue,
1991 since there is no production bios update, block it there*/
1992 DC_LOG_DEBUG("boot timing validation failed due to unsupported DSC on this ASIC\n");
1993 return false;
1994 }
1995
1996 /* Find DSC associated with this timing generator */
1997 if (tg_inst < (unsigned int)dc->res_pool->res_cap->num_dsc) {
1998 dsc = dc->res_pool->dscs[tg_inst];
1999 }
2000
2001 if (!dsc || !dsc->funcs->dsc_read_state) {
2002 DC_LOG_DEBUG("boot timing validation failed due to no DSC resource or read function\n");
2003 return false;
2004 }
2005
2006 /* Read current DSC hardware state */
2007 dsc->funcs->dsc_read_state(dsc, &dsc_state);
2008
2009 /* Check if DSC is actually enabled in hardware */
2010 if (dsc_state.dsc_clock_en == 0) {
2011 DC_LOG_DEBUG("boot timing validation failed due to DSC not enabled in hardware\n");
2012 return false;
2013 }
2014
2015 uint32_t num_slices_h = 0;
2016 uint32_t num_slices_v = 0;
2017
2018 if (dsc_state.dsc_slice_width > 0) {
2019 num_slices_h = (crtc_timing->h_addressable + dsc_state.dsc_slice_width - 1) / dsc_state.dsc_slice_width;
2020 }
2021
2022 if (dsc_state.dsc_slice_height > 0) {
2023 num_slices_v = (crtc_timing->v_addressable + dsc_state.dsc_slice_height - 1) / dsc_state.dsc_slice_height;
2024 }
2025
2026 if (crtc_timing->dsc_cfg.num_slices_h != num_slices_h) {
2027 DC_LOG_DEBUG("boot timing validation failed due to num_slices_h mismatch\n");
2028 return false;
2029 }
2030
2031 if (crtc_timing->dsc_cfg.num_slices_v != num_slices_v) {
2032 DC_LOG_DEBUG("boot timing validation failed due to num_slices_v mismatch\n");
2033 return false;
2034 }
2035
2036 if (crtc_timing->dsc_cfg.bits_per_pixel != dsc_state.dsc_bits_per_pixel) {
2037 DC_LOG_DEBUG("boot timing validation failed due to bits_per_pixel mismatch\n");
2038 return false;
2039 }
2040
2041 if (crtc_timing->dsc_cfg.block_pred_enable != dsc_state.dsc_block_pred_enable) {
2042 DC_LOG_DEBUG("boot timing validation failed due to block_pred_enable mismatch\n");
2043 return false;
2044 }
2045
2046 if (crtc_timing->dsc_cfg.linebuf_depth != dsc_state.dsc_line_buf_depth) {
2047 DC_LOG_DEBUG("boot timing validation failed due to linebuf_depth mismatch\n");
2048 return false;
2049 }
2050
2051 if (crtc_timing->dsc_cfg.version_minor != dsc_state.dsc_version_minor) {
2052 DC_LOG_DEBUG("boot timing validation failed due to version_minor mismatch\n");
2053 return false;
2054 }
2055
2056 if (crtc_timing->dsc_cfg.ycbcr422_simple != dsc_state.dsc_simple_422) {
2057 DC_LOG_DEBUG("boot timing validation failed due to pixel encoding mismatch\n");
2058 return false;
2059 }
2060
2061 // Skip checks for is_frl, is_dp, and rc_buffer_size which are not programmed by vbios
2062 // or not necessary for seamless boot validation.
2063 }
2064
2065 if (dc_is_dp_signal(link->connector_signal)) {
2066 unsigned int pix_clk_100hz = 0;
2067 uint32_t numOdmPipes = 1;
2068 uint32_t id_src[4] = {0};
2069
2070 dc->res_pool->dp_clock_source->funcs->get_dp_dto_frequency_100hz(
2071 dc->res_pool->dp_clock_source,
2072 tg_inst, &pix_clk_100hz);
2073
2074 if (tg->funcs->get_optc_source)
2075 tg->funcs->get_optc_source(tg,
2076 &numOdmPipes, &id_src[0], &id_src[1]);
2077
2078 if (numOdmPipes == 2) {
2079 pix_clk_100hz *= 2;
2080 } else if (numOdmPipes == 4) {
2081 pix_clk_100hz *= 4;
2082 } else if (se && se->funcs->get_pixels_per_cycle) {
2083 uint32_t pixels_per_cycle = se->funcs->get_pixels_per_cycle(se);
2084
2085 if (pixels_per_cycle != 1 && !dc->debug.enable_dp_dig_pixel_rate_div_policy) {
2086 DC_LOG_DEBUG("boot timing validation failed due to pixels_per_cycle\n");
2087 return false;
2088 }
2089
2090 pix_clk_100hz *= pixels_per_cycle;
2091 }
2092
2093 // Note: In rare cases, HW pixclk may differ from crtc's pixclk
2094 // slightly due to rounding issues in 10 kHz units.
2095 if (crtc_timing->pix_clk_100hz != pix_clk_100hz) {
2096 DC_LOG_DEBUG("boot timing validation failed due to pix_clk_100hz mismatch\n");
2097 return false;
2098 }
2099
2100 if (!se || !se->funcs->dp_get_pixel_format) {
2101 DC_LOG_DEBUG("boot timing validation failed due to missing dp_get_pixel_format\n");
2102 return false;
2103 }
2104
2105 if (!se->funcs->dp_get_pixel_format(
2106 se,
2107 &hw_crtc_timing.pixel_encoding,
2108 &hw_crtc_timing.display_color_depth)) {
2109 DC_LOG_DEBUG("boot timing validation failed due to dp_get_pixel_format failure\n");
2110 return false;
2111 }
2112
2113 if (hw_crtc_timing.display_color_depth != crtc_timing->display_color_depth) {
2114 DC_LOG_DEBUG("boot timing validation failed due to display_color_depth mismatch\n");
2115 return false;
2116 }
2117
2118 if (hw_crtc_timing.pixel_encoding != crtc_timing->pixel_encoding) {
2119 DC_LOG_DEBUG("boot timing validation failed due to pixel_encoding mismatch\n");
2120 return false;
2121 }
2122 }
2123
2124
2125 if (link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED) {
2126 DC_LOG_DEBUG("boot timing validation failed due to VSC SDP colorimetry\n");
2127 return false;
2128 }
2129
2130 if (link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED) {
2131 DC_LOG_DEBUG("boot timing validation failed due to DP 128b/132b\n");
2132 return false;
2133 }
2134
2135 if (dc->link_srv->edp_is_ilr_optimization_required(link, crtc_timing)) {
2136 DC_LOG_EVENT_LINK_TRAINING("Seamless boot disabled to optimize eDP link rate\n");
2137 return false;
2138 }
2139
2140 return true;
2141 }
2142
should_update_pipe_for_stream(struct dc_state * context,struct pipe_ctx * pipe_ctx,struct dc_stream_state * stream)2143 static inline bool should_update_pipe_for_stream(
2144 struct dc_state *context,
2145 struct pipe_ctx *pipe_ctx,
2146 struct dc_stream_state *stream)
2147 {
2148 return (pipe_ctx->stream && pipe_ctx->stream == stream);
2149 }
2150
should_update_pipe_for_plane(struct dc_state * context,struct pipe_ctx * pipe_ctx,struct dc_plane_state * plane_state)2151 static inline bool should_update_pipe_for_plane(
2152 struct dc_state *context,
2153 struct pipe_ctx *pipe_ctx,
2154 struct dc_plane_state *plane_state)
2155 {
2156 return (pipe_ctx->plane_state == plane_state);
2157 }
2158
dc_enable_stereo(struct dc * dc,struct dc_state * context,struct dc_stream_state * streams[],uint8_t stream_count)2159 void dc_enable_stereo(
2160 struct dc *dc,
2161 struct dc_state *context,
2162 struct dc_stream_state *streams[],
2163 uint8_t stream_count)
2164 {
2165 int i, j;
2166 struct pipe_ctx *pipe;
2167
2168 dc_exit_ips_for_hw_access(dc);
2169
2170 for (i = 0; i < MAX_PIPES; i++) {
2171 if (context != NULL) {
2172 pipe = &context->res_ctx.pipe_ctx[i];
2173 } else {
2174 context = dc->current_state;
2175 pipe = &dc->current_state->res_ctx.pipe_ctx[i];
2176 }
2177
2178 for (j = 0; pipe && j < stream_count; j++) {
2179 if (should_update_pipe_for_stream(context, pipe, streams[j]) &&
2180 dc->hwss.setup_stereo)
2181 dc->hwss.setup_stereo(pipe, dc);
2182 }
2183 }
2184 }
2185
dc_trigger_sync(struct dc * dc,struct dc_state * context)2186 void dc_trigger_sync(struct dc *dc, struct dc_state *context)
2187 {
2188 if (context->stream_count > 1 && !dc->debug.disable_timing_sync) {
2189 dc_exit_ips_for_hw_access(dc);
2190
2191 enable_timing_multisync(dc, context);
2192 program_timing_sync(dc, context);
2193 }
2194 }
2195
get_stream_mask(struct dc * dc,struct dc_state * context)2196 static uint8_t get_stream_mask(struct dc *dc, struct dc_state *context)
2197 {
2198 unsigned int i;
2199 unsigned int stream_mask = 0;
2200
2201 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2202 if (context->res_ctx.pipe_ctx[i].stream)
2203 stream_mask |= 1 << i;
2204 }
2205
2206 return (uint8_t)stream_mask;
2207 }
2208
dc_z10_restore(const struct dc * dc)2209 void dc_z10_restore(const struct dc *dc)
2210 {
2211 if (dc->hwss.z10_restore)
2212 dc->hwss.z10_restore(dc);
2213 }
2214
dc_z10_save_init(struct dc * dc)2215 void dc_z10_save_init(struct dc *dc)
2216 {
2217 if (dc->hwss.z10_save_init)
2218 dc->hwss.z10_save_init(dc);
2219 }
2220
2221 /* Set a pipe unlock order based on the change in DET allocation and stores it in dc scratch memory
2222 * Prevents over allocation of DET during unlock process
2223 * e.g. 2 pipe config with different streams with a max of 20 DET segments
2224 * Before: After:
2225 * - Pipe0: 10 DET segments - Pipe0: 12 DET segments
2226 * - Pipe1: 10 DET segments - Pipe1: 8 DET segments
2227 * If Pipe0 gets updated first, 22 DET segments will be allocated
2228 */
determine_pipe_unlock_order(struct dc * dc,struct dc_state * context)2229 static void determine_pipe_unlock_order(struct dc *dc, struct dc_state *context)
2230 {
2231 unsigned int i = 0;
2232 struct pipe_ctx *pipe = NULL;
2233 struct timing_generator *tg = NULL;
2234
2235 if (!dc->config.set_pipe_unlock_order)
2236 return;
2237
2238 memset(dc->scratch.pipes_to_unlock_first, 0, sizeof(dc->scratch.pipes_to_unlock_first));
2239 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2240 pipe = &context->res_ctx.pipe_ctx[i];
2241 tg = pipe->stream_res.tg;
2242
2243 if (!resource_is_pipe_type(pipe, OTG_MASTER) ||
2244 !tg->funcs->is_tg_enabled(tg) ||
2245 dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM) {
2246 continue;
2247 }
2248
2249 if (resource_calculate_det_for_stream(context, pipe) <
2250 resource_calculate_det_for_stream(dc->current_state, &dc->current_state->res_ctx.pipe_ctx[i])) {
2251 dc->scratch.pipes_to_unlock_first[i] = true;
2252 }
2253 }
2254 }
2255
2256 /**
2257 * dc_commit_state_no_check - Apply context to the hardware
2258 *
2259 * @dc: DC object with the current status to be updated
2260 * @context: New state that will become the current status at the end of this function
2261 *
2262 * Applies given context to the hardware and copy it into current context.
2263 * It's up to the user to release the src context afterwards.
2264 *
2265 * Return: an enum dc_status result code for the operation
2266 */
dc_commit_state_no_check(struct dc * dc,struct dc_state * context)2267 static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *context)
2268 {
2269 struct dc_bios *dcb = dc->ctx->dc_bios;
2270 enum dc_status result = DC_ERROR_UNEXPECTED;
2271 struct pipe_ctx *pipe;
2272 unsigned int i, k, l;
2273 struct dc_stream_state *dc_streams[MAX_STREAMS] = {0};
2274 struct dc_state *old_state;
2275 bool subvp_prev_use = false;
2276
2277 dc_z10_restore(dc);
2278 dc_allow_idle_optimizations(dc, false);
2279
2280 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2281 struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
2282
2283 /* Check old context for SubVP */
2284 subvp_prev_use |= (dc_state_get_pipe_subvp_type(dc->current_state, old_pipe) == SUBVP_PHANTOM);
2285 if (subvp_prev_use)
2286 break;
2287 }
2288
2289 for (i = 0; i < context->stream_count; i++)
2290 dc_streams[i] = context->streams[i];
2291
2292 if (!dcb->funcs->is_accelerated_mode(dcb)) {
2293 disable_vbios_mode_if_required(dc, context);
2294 dc->hwss.enable_accelerated_mode(dc, context);
2295 } else if (get_seamless_boot_stream_count(dc->current_state) > 0) {
2296 /* If the previous Stream still retains the apply seamless boot flag,
2297 * it means the OS has not actually performed a flip yet.
2298 * At this point, if we receive dc_commit_streams again, we should
2299 * once more check whether the actual HW timing matches what the OS
2300 * has provided
2301 */
2302 disable_vbios_mode_if_required(dc, context);
2303 }
2304
2305 if (dc->hwseq->funcs.wait_for_pipe_update_if_needed) {
2306 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2307 pipe = &context->res_ctx.pipe_ctx[i];
2308 //Only delay otg master for a given config
2309 if (resource_is_pipe_type(pipe, OTG_MASTER)) {
2310 //dc_commit_state_no_check is always a full update
2311 dc->hwseq->funcs.wait_for_pipe_update_if_needed(dc, pipe, false);
2312 break;
2313 }
2314 }
2315 }
2316
2317 if (context->stream_count > get_seamless_boot_stream_count(context) ||
2318 context->stream_count == 0)
2319 dc->hwss.prepare_bandwidth(dc, context);
2320
2321 /* When SubVP is active, all HW programming must be done while
2322 * SubVP lock is acquired
2323 */
2324 if (dc->hwss.subvp_pipe_control_lock)
2325 dc->hwss.subvp_pipe_control_lock(dc, context, true, true, NULL, subvp_prev_use);
2326 if (dc->hwss.dmub_hw_control_lock)
2327 dc->hwss.dmub_hw_control_lock(dc, context, true);
2328
2329 if (dc->hwss.update_dsc_pg)
2330 dc->hwss.update_dsc_pg(dc, context, false);
2331
2332 disable_dangling_plane(dc, context);
2333 /* re-program planes for existing stream, in case we need to
2334 * free up plane resource for later use
2335 */
2336 if (dc->hwss.apply_ctx_for_surface) {
2337 for (i = 0; i < context->stream_count; i++) {
2338 if (context->streams[i]->mode_changed)
2339 continue;
2340 apply_ctx_interdependent_lock(dc, context, context->streams[i], true);
2341 dc->hwss.apply_ctx_for_surface(
2342 dc, context->streams[i],
2343 context->stream_status[i].plane_count,
2344 context); /* use new pipe config in new context */
2345 apply_ctx_interdependent_lock(dc, context, context->streams[i], false);
2346 dc->hwss.post_unlock_program_front_end(dc, context);
2347 }
2348 }
2349
2350 /* Program hardware */
2351 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2352 pipe = &context->res_ctx.pipe_ctx[i];
2353 dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe);
2354 }
2355
2356 for (i = 0; i < dc->current_state->stream_count; i++)
2357 dc_dmub_srv_control_cursor_offload(dc, dc->current_state, dc->current_state->streams[i], false);
2358
2359 result = dc->hwss.apply_ctx_to_hw(dc, context);
2360
2361 for (i = 0; i < context->stream_count; i++)
2362 dc_dmub_srv_control_cursor_offload(dc, context, context->streams[i], true);
2363
2364 if (result != DC_OK) {
2365 /* Application of dc_state to hardware stopped. */
2366 dc->current_state->res_ctx.link_enc_cfg_ctx.mode = LINK_ENC_CFG_STEADY;
2367 return result;
2368 }
2369
2370 dc_trigger_sync(dc, context);
2371
2372 /* Full update should unconditionally be triggered when dc_commit_state_no_check is called */
2373 for (i = 0; i < context->stream_count; i++) {
2374 uint32_t prev_dsc_changed = context->streams[i]->update_flags.bits.dsc_changed;
2375
2376 stream_update_flags_set_full(&context->streams[i]->update_flags);
2377 context->streams[i]->update_flags.bits.dsc_changed = prev_dsc_changed;
2378 }
2379
2380 determine_pipe_unlock_order(dc, context);
2381 /* Program all planes within new context*/
2382 if (dc->res_pool->funcs->prepare_mcache_programming)
2383 dc->res_pool->funcs->prepare_mcache_programming(dc, context);
2384 if (dc->hwss.program_front_end_for_ctx) {
2385 dc->hwss.interdependent_update_lock(dc, context, true);
2386 dc->hwss.program_front_end_for_ctx(dc, context);
2387
2388 if (dc->hwseq->funcs.set_wait_for_update_needed_for_pipe) {
2389 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2390 pipe = &context->res_ctx.pipe_ctx[i];
2391 dc->hwseq->funcs.set_wait_for_update_needed_for_pipe(dc, pipe);
2392 }
2393 }
2394
2395 dc->hwss.interdependent_update_lock(dc, context, false);
2396 dc->hwss.post_unlock_program_front_end(dc, context);
2397 }
2398
2399 if (dc->hwss.commit_subvp_config)
2400 dc->hwss.commit_subvp_config(dc, context);
2401 if (dc->hwss.subvp_pipe_control_lock)
2402 dc->hwss.subvp_pipe_control_lock(dc, context, false, true, NULL, subvp_prev_use);
2403 if (dc->hwss.dmub_hw_control_lock)
2404 dc->hwss.dmub_hw_control_lock(dc, context, false);
2405
2406 for (i = 0; i < context->stream_count; i++) {
2407 const struct dc_link *link = context->streams[i]->link;
2408
2409 if (!context->streams[i]->mode_changed)
2410 continue;
2411
2412 if (dc->hwss.apply_ctx_for_surface) {
2413 apply_ctx_interdependent_lock(dc, context, context->streams[i], true);
2414 dc->hwss.apply_ctx_for_surface(
2415 dc, context->streams[i],
2416 context->stream_status[i].plane_count,
2417 context);
2418 apply_ctx_interdependent_lock(dc, context, context->streams[i], false);
2419 dc->hwss.post_unlock_program_front_end(dc, context);
2420 }
2421
2422 /*
2423 * enable stereo
2424 * TODO rework dc_enable_stereo call to work with validation sets?
2425 */
2426 for (k = 0; k < MAX_PIPES; k++) {
2427 pipe = &context->res_ctx.pipe_ctx[k];
2428
2429 for (l = 0 ; pipe && l < context->stream_count; l++) {
2430 if (context->streams[l] &&
2431 context->streams[l] == pipe->stream &&
2432 dc->hwss.setup_stereo)
2433 dc->hwss.setup_stereo(pipe, dc);
2434 }
2435 }
2436
2437 CONN_MSG_MODE(link, "{%dx%d, %dx%d@%dKhz}",
2438 context->streams[i]->timing.h_addressable,
2439 context->streams[i]->timing.v_addressable,
2440 context->streams[i]->timing.h_total,
2441 context->streams[i]->timing.v_total,
2442 context->streams[i]->timing.pix_clk_100hz / 10);
2443 }
2444
2445 dc_enable_stereo(dc, context, dc_streams, context->stream_count);
2446
2447 if (get_seamless_boot_stream_count(context) == 0 ||
2448 context->stream_count == 0) {
2449 /* Must wait for no flips to be pending before doing optimize bw */
2450 hwss_wait_for_no_pipes_pending(dc, context);
2451 /*
2452 * optimized dispclk depends on ODM setup. Need to wait for ODM
2453 * update pending complete before optimizing bandwidth.
2454 */
2455 hwss_wait_for_odm_update_pending_complete(dc, context);
2456 /* pplib is notified if disp_num changed */
2457 dc->hwss.optimize_bandwidth(dc, context);
2458 /* Need to do otg sync again as otg could be out of sync due to otg
2459 * workaround applied during clock update
2460 */
2461 dc_trigger_sync(dc, context);
2462 }
2463
2464 if (dc->hwss.update_dsc_pg)
2465 dc->hwss.update_dsc_pg(dc, context, true);
2466
2467 if (dc->ctx->dce_version >= DCE_VERSION_MAX)
2468 TRACE_DCN_CLOCK_STATE(&context->bw_ctx.bw.dcn.clk);
2469 else
2470 TRACE_DCE_CLOCK_STATE(&context->bw_ctx.bw.dce);
2471
2472 context->stream_mask = get_stream_mask(dc, context);
2473
2474 if (context->stream_mask != dc->current_state->stream_mask)
2475 dc_dmub_srv_notify_stream_mask(dc->ctx->dmub_srv, context->stream_mask);
2476
2477 for (i = 0; i < context->stream_count; i++)
2478 context->streams[i]->mode_changed = false;
2479
2480 /* Clear update flags that were set earlier to avoid redundant programming */
2481 for (i = 0; i < context->stream_count; i++) {
2482 stream_update_flags_clear(&context->streams[i]->update_flags);
2483 }
2484
2485 old_state = dc->current_state;
2486 dc->current_state = context;
2487
2488 dc_state_release(old_state);
2489
2490 dc_state_retain(dc->current_state);
2491
2492 return result;
2493 }
2494
2495 static bool commit_minimal_transition_state(struct dc *dc,
2496 struct dc_state *transition_base_context);
2497
2498 /**
2499 * dc_commit_streams - Commit current stream state
2500 *
2501 * @dc: DC object with the commit state to be configured in the hardware
2502 * @params: Parameters for the commit, including the streams to be committed
2503 *
2504 * Function responsible for commit streams change to the hardware.
2505 *
2506 * Return:
2507 * Return DC_OK if everything work as expected, otherwise, return a dc_status
2508 * code.
2509 */
dc_commit_streams(struct dc * dc,struct dc_commit_streams_params * params)2510 enum dc_status dc_commit_streams(struct dc *dc, struct dc_commit_streams_params *params)
2511 {
2512 unsigned int i, j;
2513 struct dc_state *context;
2514 enum dc_status res = DC_OK;
2515 struct dc_validation_set set = {0};
2516 struct pipe_ctx *pipe;
2517 bool handle_exit_odm2to1 = false;
2518
2519 if (!params)
2520 return DC_ERROR_UNEXPECTED;
2521
2522 if (dc->ctx->dce_environment == DCE_ENV_VIRTUAL_HW)
2523 return res;
2524
2525 if (!streams_changed(dc, params->streams, params->stream_count) &&
2526 dc->current_state->power_source == params->power_source)
2527 return res;
2528
2529 dc_exit_ips_for_hw_access(dc);
2530
2531 DC_LOG_DC("%s: %d streams\n", __func__, params->stream_count);
2532
2533 for (i = 0; i < params->stream_count; i++) {
2534 struct dc_stream_state *stream = params->streams[i];
2535 struct dc_stream_status *status = dc_stream_get_status(stream);
2536 struct dc_sink *sink = stream->sink;
2537
2538 /* revalidate streams */
2539 if (!dc_is_virtual_signal(sink->sink_signal)) {
2540 res = dc_validate_stream(dc, stream);
2541 if (res != DC_OK)
2542 return res;
2543 }
2544
2545
2546 dc_stream_log(dc, stream);
2547
2548 set.streams[i].stream = stream;
2549
2550 if (status) {
2551 set.streams[i].plane_count = (uint8_t)status->plane_count;
2552 for (j = 0; j < (unsigned int)status->plane_count; j++)
2553 set.streams[i].plane_states[j] = status->plane_states[j];
2554 }
2555 }
2556 set.stream_count = (uint8_t)params->stream_count;
2557
2558 /* ODM Combine 2:1 power optimization is only applied for single stream
2559 * scenario, it uses extra pipes than needed to reduce power consumption
2560 * We need to switch off this feature to make room for new streams.
2561 */
2562 if (params->stream_count > dc->current_state->stream_count &&
2563 dc->current_state->stream_count == 1) {
2564 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2565 pipe = &dc->current_state->res_ctx.pipe_ctx[i];
2566 if (pipe->next_odm_pipe)
2567 handle_exit_odm2to1 = true;
2568 }
2569 }
2570
2571 if (handle_exit_odm2to1)
2572 res = commit_minimal_transition_state(dc, dc->current_state);
2573
2574 context = dc_state_create_current_copy(dc);
2575 if (!context)
2576 goto context_alloc_fail;
2577
2578 context->power_source = params->power_source;
2579
2580 res = dc_validate_with_context(dc, &set, context, DC_VALIDATE_MODE_AND_PROGRAMMING);
2581
2582 /*
2583 * Only update link encoder to stream assignment after bandwidth validation passed.
2584 */
2585 if (res == DC_OK && dc->res_pool->funcs->link_encs_assign && !dc->config.unify_link_enc_assignment)
2586 dc->res_pool->funcs->link_encs_assign(
2587 dc, context, context->streams, context->stream_count);
2588
2589 if (res != DC_OK) {
2590 BREAK_TO_DEBUGGER();
2591 goto fail;
2592 }
2593
2594 /*
2595 * If not already seamless, make transition seamless by inserting intermediate minimal transition
2596 */
2597 if (dc->hwss.is_pipe_topology_transition_seamless &&
2598 !dc->hwss.is_pipe_topology_transition_seamless(dc, dc->current_state, context)) {
2599 res = commit_minimal_transition_state(dc, context);
2600 if (res != DC_OK) {
2601 BREAK_TO_DEBUGGER();
2602 goto fail;
2603 }
2604 }
2605
2606 res = dc_commit_state_no_check(dc, context);
2607
2608 for (i = 0; i < params->stream_count; i++) {
2609 for (j = 0; j < context->stream_count; j++) {
2610 if (params->streams[i]->stream_id == context->streams[j]->stream_id)
2611 params->streams[i]->out.otg_offset = (uint8_t)context->stream_status[j].primary_otg_inst;
2612
2613 if (dc_is_embedded_signal(params->streams[i]->signal)) {
2614 struct dc_stream_status *status = dc_state_get_stream_status(context, params->streams[i]);
2615
2616 if (!status)
2617 continue;
2618
2619 if (dc->hwss.is_abm_supported)
2620 status->is_abm_supported = dc->hwss.is_abm_supported(dc, context, params->streams[i]);
2621 else
2622 status->is_abm_supported = true;
2623 }
2624 }
2625 }
2626
2627 fail:
2628 dc_state_release(context);
2629
2630 context_alloc_fail:
2631
2632 DC_LOG_DC("%s Finished.\n", __func__);
2633
2634 return res;
2635 }
2636
dc_acquire_release_mpc_3dlut(struct dc * dc,bool acquire,struct dc_stream_state * stream,struct dc_3dlut ** lut,struct dc_transfer_func ** shaper)2637 bool dc_acquire_release_mpc_3dlut(
2638 struct dc *dc, bool acquire,
2639 struct dc_stream_state *stream,
2640 struct dc_3dlut **lut,
2641 struct dc_transfer_func **shaper)
2642 {
2643 unsigned int pipe_idx;
2644 bool ret = false;
2645 bool found_pipe_idx = false;
2646 const struct resource_pool *pool = dc->res_pool;
2647 struct resource_context *res_ctx = &dc->current_state->res_ctx;
2648 int mpcc_id = 0;
2649
2650 if (pool && res_ctx) {
2651 if (acquire) {
2652 /*find pipe idx for the given stream*/
2653 for (pipe_idx = 0; pipe_idx < pool->pipe_count; pipe_idx++) {
2654 if (res_ctx->pipe_ctx[pipe_idx].stream == stream) {
2655 found_pipe_idx = true;
2656 mpcc_id = res_ctx->pipe_ctx[pipe_idx].plane_res.hubp->inst;
2657 break;
2658 }
2659 }
2660 } else
2661 found_pipe_idx = true;/*for release pipe_idx is not required*/
2662
2663 if (found_pipe_idx) {
2664 if (acquire && pool->funcs->acquire_post_bldn_3dlut)
2665 ret = pool->funcs->acquire_post_bldn_3dlut(res_ctx, pool, mpcc_id, lut, shaper);
2666 else if (!acquire && pool->funcs->release_post_bldn_3dlut)
2667 ret = pool->funcs->release_post_bldn_3dlut(res_ctx, pool, lut, shaper);
2668 }
2669 }
2670 return ret;
2671 }
2672
is_flip_pending_in_pipes(struct dc * dc,struct dc_state * context)2673 static bool is_flip_pending_in_pipes(struct dc *dc, struct dc_state *context)
2674 {
2675 int i;
2676 struct pipe_ctx *pipe;
2677
2678 for (i = 0; i < MAX_PIPES; i++) {
2679 pipe = &context->res_ctx.pipe_ctx[i];
2680
2681 // Don't check flip pending on phantom pipes
2682 if (!pipe->plane_state || (dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM))
2683 continue;
2684
2685 /* Must set to false to start with, due to OR in update function */
2686 pipe->plane_state->status.is_flip_pending = false;
2687 dc->hwss.update_pending_status(pipe);
2688 if (pipe->plane_state->status.is_flip_pending)
2689 return true;
2690 }
2691 return false;
2692 }
2693
2694 /* Perform updates here which need to be deferred until next vupdate
2695 *
2696 * i.e. blnd lut, 3dlut, and shaper lut bypass regs are double buffered
2697 * but forcing lut memory to shutdown state is immediate. This causes
2698 * single frame corruption as lut gets disabled mid-frame unless shutdown
2699 * is deferred until after entering bypass.
2700 */
process_deferred_updates(struct dc * dc)2701 static void process_deferred_updates(struct dc *dc)
2702 {
2703 int i = 0;
2704
2705 if (dc->debug.enable_mem_low_power.bits.cm) {
2706 ASSERT(dc->dcn_ip->max_num_dpp);
2707 for (i = 0; i < dc->dcn_ip->max_num_dpp; i++)
2708 if (dc->res_pool->dpps[i]->funcs->dpp_deferred_update)
2709 dc->res_pool->dpps[i]->funcs->dpp_deferred_update(dc->res_pool->dpps[i]);
2710 }
2711 }
2712
dc_post_update_surfaces_to_stream(struct dc * dc)2713 void dc_post_update_surfaces_to_stream(struct dc *dc)
2714 {
2715 unsigned int i;
2716 struct dc_state *context = dc->current_state;
2717
2718 if ((!dc->optimized_required) || get_seamless_boot_stream_count(context) > 0)
2719 return;
2720
2721 post_surface_trace(dc);
2722
2723 /*
2724 * Only relevant for DCN behavior where we can guarantee the optimization
2725 * is safe to apply - retain the legacy behavior for DCE.
2726 */
2727
2728 if (dc->ctx->dce_version < DCE_VERSION_MAX)
2729 TRACE_DCE_CLOCK_STATE(&context->bw_ctx.bw.dce);
2730 else {
2731 TRACE_DCN_CLOCK_STATE(&context->bw_ctx.bw.dcn.clk);
2732
2733 if (is_flip_pending_in_pipes(dc, context))
2734 return;
2735
2736 for (i = 0; i < dc->res_pool->pipe_count; i++)
2737 if (context->res_ctx.pipe_ctx[i].stream == NULL ||
2738 context->res_ctx.pipe_ctx[i].plane_state == NULL) {
2739 context->res_ctx.pipe_ctx[i].pipe_idx = (uint8_t)i;
2740 dc->hwss.disable_plane(dc, context, &context->res_ctx.pipe_ctx[i]);
2741 }
2742
2743 process_deferred_updates(dc);
2744
2745 dc->hwss.optimize_bandwidth(dc, context);
2746
2747 if (dc->hwss.update_dsc_pg)
2748 dc->hwss.update_dsc_pg(dc, context, true);
2749 }
2750
2751 dc->optimized_required = false;
2752 }
2753
dc_get_default_tiling_info(const struct dc * dc,struct dc_tiling_info * tiling_info)2754 void dc_get_default_tiling_info(const struct dc *dc, struct dc_tiling_info *tiling_info)
2755 {
2756 if (!dc || !tiling_info)
2757 return;
2758 if (dc->res_pool && dc->res_pool->funcs && dc->res_pool->funcs->get_default_tiling_info) {
2759 dc->res_pool->funcs->get_default_tiling_info(tiling_info);
2760 return;
2761 }
2762 }
2763
dc_set_generic_gpio_for_stereo(bool enable,struct gpio_service * gpio_service)2764 bool dc_set_generic_gpio_for_stereo(bool enable,
2765 struct gpio_service *gpio_service)
2766 {
2767 enum gpio_result gpio_result = GPIO_RESULT_NON_SPECIFIC_ERROR;
2768 struct gpio_pin_info pin_info;
2769 struct gpio *generic;
2770 struct gpio_generic_mux_config *config = kzalloc_obj(struct gpio_generic_mux_config);
2771
2772 if (!config)
2773 return false;
2774 pin_info = dal_gpio_get_generic_pin_info(gpio_service, GPIO_ID_GENERIC, 0);
2775
2776 if (pin_info.mask == 0xFFFFFFFF || pin_info.offset == 0xFFFFFFFF) {
2777 kfree(config);
2778 return false;
2779 } else {
2780 generic = dal_gpio_service_create_generic_mux(
2781 gpio_service,
2782 pin_info.offset,
2783 pin_info.mask);
2784 }
2785
2786 if (!generic) {
2787 kfree(config);
2788 return false;
2789 }
2790
2791 gpio_result = dal_gpio_open(generic, GPIO_MODE_OUTPUT);
2792
2793 config->enable_output_from_mux = enable;
2794 config->mux_select = GPIO_SIGNAL_SOURCE_PASS_THROUGH_STEREO_SYNC;
2795
2796 if (gpio_result == GPIO_RESULT_OK)
2797 gpio_result = dal_mux_setup_config(generic, config);
2798
2799 if (gpio_result == GPIO_RESULT_OK) {
2800 dal_gpio_close(generic);
2801 dal_gpio_destroy_generic_mux(&generic);
2802 kfree(config);
2803 return true;
2804 } else {
2805 dal_gpio_close(generic);
2806 dal_gpio_destroy_generic_mux(&generic);
2807 kfree(config);
2808 return false;
2809 }
2810 }
2811
is_surface_in_context(const struct dc_state * context,const struct dc_plane_state * plane_state)2812 static bool is_surface_in_context(
2813 const struct dc_state *context,
2814 const struct dc_plane_state *plane_state)
2815 {
2816 int j;
2817
2818 for (j = 0; j < MAX_PIPES; j++) {
2819 const struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
2820
2821 if (plane_state == pipe_ctx->plane_state) {
2822 return true;
2823 }
2824 }
2825
2826 return false;
2827 }
2828
get_plane_info_update_type(const struct dc_surface_update * u)2829 static struct dc_update_descriptor get_plane_info_update_type(const struct dc_surface_update *u)
2830 {
2831 struct pipe_update_bits *update_bits = &u->surface->update_bits;
2832 struct dc_update_descriptor update_type = { UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_NONE };
2833
2834 if (!u->plane_info)
2835 return update_type;
2836
2837 // `plane_info` present means at least `STREAM` lock is required
2838 elevate_update_type(&update_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
2839
2840 if (u->plane_info->color_space != u->surface->color_space) {
2841 update_bits->color_space_change = 1;
2842 elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM);
2843 }
2844
2845 if (u->plane_info->horizontal_mirror != u->surface->horizontal_mirror) {
2846 update_bits->horizontal_mirror_change = 1;
2847 elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM);
2848 }
2849
2850 if (u->plane_info->rotation != u->surface->rotation) {
2851 update_bits->rotation_change = 1;
2852 elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
2853 }
2854
2855 if (u->plane_info->format != u->surface->format) {
2856 update_bits->pixel_format_change = 1;
2857 elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
2858 }
2859
2860 if (u->plane_info->stereo_format != u->surface->stereo_format) {
2861 update_bits->stereo_format_change = 1;
2862 elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
2863 }
2864
2865 if (u->plane_info->per_pixel_alpha != u->surface->per_pixel_alpha) {
2866 update_bits->per_pixel_alpha_change = 1;
2867 elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM);
2868 }
2869
2870 if (u->plane_info->global_alpha_value != u->surface->global_alpha_value) {
2871 update_bits->global_alpha_change = 1;
2872 elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM);
2873 }
2874
2875 if (u->plane_info->dcc.enable != u->surface->dcc.enable
2876 || u->plane_info->dcc.dcc_ind_blk != u->surface->dcc.dcc_ind_blk
2877 || u->plane_info->dcc.meta_pitch != u->surface->dcc.meta_pitch) {
2878 /* During DCC on/off, stutter period is calculated before
2879 * DCC has fully transitioned. This results in incorrect
2880 * stutter period calculation. Triggering a full update will
2881 * recalculate stutter period.
2882 */
2883 update_bits->dcc_change = 1;
2884 elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
2885 }
2886
2887 if (resource_pixel_format_to_bpp(u->plane_info->format) !=
2888 resource_pixel_format_to_bpp(u->surface->format)) {
2889 /* different bytes per element will require full bandwidth
2890 * and DML calculation
2891 */
2892 update_bits->bpp_change = 1;
2893 elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
2894 }
2895
2896 if (u->plane_info->plane_size.surface_pitch != u->surface->plane_size.surface_pitch
2897 || u->plane_info->plane_size.chroma_pitch != u->surface->plane_size.chroma_pitch) {
2898 update_bits->plane_size_change = 1;
2899 elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM);
2900 }
2901
2902 const struct dc_tiling_info *tiling = &u->plane_info->tiling_info;
2903
2904 if (memcmp(tiling, &u->surface->tiling_info, sizeof(*tiling)) != 0) {
2905 update_bits->swizzle_change = 1;
2906
2907 if (tiling->flags.avoid_full_update_on_tiling_change) {
2908 elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM);
2909 } else {
2910 update_bits->bandwidth_change = 1;
2911 elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
2912 }
2913 }
2914
2915 /* This should be UPDATE_TYPE_FAST if nothing has changed. */
2916 return update_type;
2917 }
2918
get_scaling_info_update_type(const struct dc_check_config * check_config,const struct dc_surface_update * u)2919 static struct dc_update_descriptor get_scaling_info_update_type(
2920 const struct dc_check_config *check_config,
2921 const struct dc_surface_update *u)
2922 {
2923 struct pipe_update_bits *update_bits = &u->surface->update_bits;
2924 struct dc_update_descriptor update_type = { UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_NONE };
2925
2926 if (!u->scaling_info)
2927 return update_type;
2928
2929 // `scaling_info` present means at least `STREAM` lock is required
2930 elevate_update_type(&update_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
2931
2932 if (u->scaling_info->src_rect.width != u->surface->src_rect.width
2933 || u->scaling_info->src_rect.height != u->surface->src_rect.height
2934 || u->scaling_info->dst_rect.width != u->surface->dst_rect.width
2935 || u->scaling_info->dst_rect.height != u->surface->dst_rect.height
2936 || u->scaling_info->clip_rect.width != u->surface->clip_rect.width
2937 || u->scaling_info->clip_rect.height != u->surface->clip_rect.height
2938 || u->scaling_info->scaling_quality.integer_scaling !=
2939 u->surface->scaling_quality.integer_scaling) {
2940 update_bits->scaling_change = 1;
2941 elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
2942
2943 if (u->scaling_info->src_rect.width > u->surface->src_rect.width
2944 || u->scaling_info->src_rect.height > u->surface->src_rect.height)
2945 /* Making src rect bigger requires a bandwidth change */
2946 update_bits->clock_change = 1;
2947
2948 if ((u->scaling_info->dst_rect.width < u->surface->dst_rect.width
2949 || u->scaling_info->dst_rect.height < u->surface->dst_rect.height)
2950 && (u->scaling_info->dst_rect.width < u->surface->src_rect.width
2951 || u->scaling_info->dst_rect.height < u->surface->src_rect.height))
2952 /* Making dst rect smaller requires a bandwidth change */
2953 update_bits->bandwidth_change = 1;
2954
2955 if (u->scaling_info->src_rect.width > (int)check_config->max_optimizable_video_width &&
2956 (u->scaling_info->clip_rect.width > u->surface->clip_rect.width ||
2957 u->scaling_info->clip_rect.height > u->surface->clip_rect.height))
2958 /* Changing clip size of a large surface may result in MPC slice count change */
2959 update_bits->bandwidth_change = 1;
2960 }
2961
2962 if (u->scaling_info->src_rect.x != u->surface->src_rect.x
2963 || u->scaling_info->src_rect.y != u->surface->src_rect.y
2964 || u->scaling_info->clip_rect.x != u->surface->clip_rect.x
2965 || u->scaling_info->clip_rect.y != u->surface->clip_rect.y
2966 || u->scaling_info->dst_rect.x != u->surface->dst_rect.x
2967 || u->scaling_info->dst_rect.y != u->surface->dst_rect.y) {
2968 elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM);
2969 update_bits->position_change = 1;
2970 }
2971
2972 return update_type;
2973 }
2974
det_surface_update(const struct dc_check_config * check_config,struct dc_surface_update * u)2975 static struct dc_update_descriptor det_surface_update(
2976 const struct dc_check_config *check_config,
2977 struct dc_surface_update *u)
2978 {
2979 struct dc_update_descriptor overall_type = { UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_NONE };
2980 struct pipe_update_bits *update_bits = &u->surface->update_bits;
2981
2982 if (u->surface->force_full_update) {
2983 dc_pipe_update_bits_set_full(update_bits);
2984 elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
2985 return overall_type;
2986 }
2987
2988 dc_pipe_update_bits_clear(update_bits);
2989
2990 struct dc_update_descriptor inner_type = get_plane_info_update_type(u);
2991 elevate_update_type(&overall_type, inner_type.update_type, inner_type.lock_descriptor);
2992
2993 inner_type = get_scaling_info_update_type(check_config, u);
2994 elevate_update_type(&overall_type, inner_type.update_type, inner_type.lock_descriptor);
2995
2996 if (u->flip_addr) {
2997 update_bits->addr_update = 1;
2998 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
2999
3000 if (u->flip_addr->address.tmz_surface != u->surface->address.tmz_surface) {
3001 update_bits->tmz_changed = 1;
3002 elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
3003 }
3004 }
3005 if (u->in_transfer_func) {
3006 update_bits->in_transfer_func_change = 1;
3007 elevate_update_type(&overall_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM);
3008 }
3009
3010 if (u->input_csc_color_matrix) {
3011 update_bits->input_csc_change = 1;
3012 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
3013 }
3014
3015 if (u->cursor_csc_color_matrix) {
3016 update_bits->cursor_csc_color_matrix_change = 1;
3017 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
3018 }
3019
3020 if (u->coeff_reduction_factor) {
3021 update_bits->coeff_reduction_change = 1;
3022 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
3023 }
3024
3025 if (u->gamut_remap_matrix) {
3026 update_bits->gamut_remap_change = 1;
3027 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
3028 }
3029
3030 if ((u->cm && (u->cm->flags.bits.blend_enable ||
3031 u->cm->flags.bits.blend_enable != u->surface->cm.flags.bits.blend_enable)) ||
3032 (u->gamma && dce_use_lut(u->plane_info ? u->plane_info->format : u->surface->format))) {
3033 update_bits->gamma_change = 1;
3034 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
3035 }
3036
3037 if (u->cm && (u->cm->flags.bits.lut3d_enable || u->surface->cm.flags.bits.lut3d_enable)) {
3038 update_bits->lut_3d = 1;
3039 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
3040 }
3041
3042 if (u->cm && u->cm->flags.bits.lut3d_dma_enable != u->surface->cm.flags.bits.lut3d_dma_enable &&
3043 u->cm->flags.bits.lut3d_enable && u->surface->cm.flags.bits.lut3d_enable) {
3044 /* Toggling 3DLUT loading between DMA and Host is illegal */
3045 BREAK_TO_DEBUGGER();
3046 }
3047
3048 if (u->cm && u->cm->flags.bits.lut3d_enable && !u->cm->flags.bits.lut3d_dma_enable) {
3049 /* Host loading 3DLUT requires full update but only stream lock */
3050 elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_STREAM);
3051 }
3052
3053 if (u->hdr_mult.value)
3054 if (u->hdr_mult.value != u->surface->hdr_mult.value) {
3055 // TODO: Should be fast?
3056 update_bits->hdr_mult = 1;
3057 elevate_update_type(&overall_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM);
3058 }
3059
3060 if (u->sdr_white_level_nits)
3061 if (u->sdr_white_level_nits != u->surface->sdr_white_level_nits) {
3062 // TODO: Should be fast?
3063 update_bits->sdr_white_level_nits = 1;
3064 elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
3065 }
3066
3067 if (u->cm_hist_control) {
3068 update_bits->cm_hist_change = 1;
3069 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
3070 }
3071
3072 if (u->cm) {
3073 const union dc_plane_cm_flags blend_only_flags = {
3074 .bits = {
3075 .blend_enable = 1,
3076 }
3077 };
3078
3079 if ((u->cm->flags.all != blend_only_flags.all && u->cm->flags.all != 0) ||
3080 (u->surface->cm.flags.all != blend_only_flags.all && u->surface->cm.flags.all != 0)) {
3081 elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
3082 }
3083 }
3084
3085 if (check_config->enable_legacy_fast_update &&
3086 (update_bits->gamma_change ||
3087 update_bits->gamut_remap_change ||
3088 update_bits->input_csc_change ||
3089 update_bits->cm_hist_change ||
3090 update_bits->coeff_reduction_change ||
3091 update_bits->cursor_csc_color_matrix_change)) {
3092 elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
3093 }
3094 return overall_type;
3095 }
3096
3097 /* May need to flip the desktop plane in cases where MPO plane receives a flip but desktop plane doesn't
3098 * while both planes are flip_immediate
3099 */
force_immediate_gsl_plane_flip(struct dc * dc,struct dc_surface_update * updates,int surface_count)3100 static void force_immediate_gsl_plane_flip(struct dc *dc, struct dc_surface_update *updates, int surface_count)
3101 {
3102 (void)dc;
3103 bool has_flip_immediate_plane = false;
3104 int i;
3105
3106 for (i = 0; i < surface_count; i++) {
3107 if (updates[i].surface->flip_immediate) {
3108 has_flip_immediate_plane = true;
3109 break;
3110 }
3111 }
3112
3113 if (has_flip_immediate_plane && surface_count > 1) {
3114 for (i = 0; i < surface_count; i++) {
3115 if (updates[i].surface->flip_immediate)
3116 updates[i].surface->update_bits.addr_update = 1;
3117 }
3118 }
3119 }
3120
check_update_surfaces_for_stream(const struct dc_check_config * check_config,struct dc_surface_update * updates,int surface_count,struct dc_stream_update * stream_update)3121 static struct dc_update_descriptor check_update_surfaces_for_stream(
3122 const struct dc_check_config *check_config,
3123 struct dc_surface_update *updates,
3124 int surface_count,
3125 struct dc_stream_update *stream_update)
3126 {
3127 struct dc_update_descriptor overall_type = { UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_NONE };
3128
3129 /* When countdown finishes, promote this flip to full to trigger deferred final transition */
3130 if (check_config->deferred_transition_state && !check_config->transition_countdown_to_steady_state) {
3131 elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
3132 }
3133
3134 if (stream_update && stream_update->pending_test_pattern) {
3135 elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
3136 }
3137
3138 if (stream_update && stream_update->hw_cursor_req) {
3139 elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
3140 }
3141
3142 /* some stream updates require passive update */
3143 if (stream_update) {
3144 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
3145
3146 union stream_update_flags *su_flags = &stream_update->stream->update_flags;
3147
3148 if ((stream_update->src.height != 0 && stream_update->src.width != 0) ||
3149 (stream_update->dst.height != 0 && stream_update->dst.width != 0) ||
3150 stream_update->integer_scaling_update)
3151 su_flags->bits.scaling = 1;
3152
3153 if (check_config->enable_legacy_fast_update && stream_update->out_transfer_func)
3154 su_flags->bits.out_tf = 1;
3155
3156 if (stream_update->abm_level)
3157 su_flags->bits.abm_level = 1;
3158
3159 if (stream_update->dpms_off) {
3160 su_flags->bits.dpms_off = 1;
3161 elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL | LOCK_DESCRIPTOR_LINK);
3162 }
3163
3164 if (check_config->enable_legacy_fast_update && stream_update->gamut_remap)
3165 su_flags->bits.gamut_remap = 1;
3166
3167 if (stream_update->wb_update)
3168 su_flags->bits.wb_update = 1;
3169
3170 if (stream_update->dsc_config)
3171 su_flags->bits.dsc_changed = 1;
3172
3173 if (stream_update->mst_bw_update)
3174 su_flags->bits.mst_bw = 1;
3175
3176 if (stream_update->stream->freesync_on_desktop &&
3177 (stream_update->vrr_infopacket || stream_update->allow_freesync ||
3178 stream_update->vrr_active_variable || stream_update->vrr_active_fixed))
3179 su_flags->bits.fams_changed = 1;
3180
3181 if (stream_update->scaler_sharpener_update)
3182 su_flags->bits.scaler_sharpener = 1;
3183
3184 if (stream_update->sharpening_required)
3185 su_flags->bits.sharpening_required = 1;
3186
3187 if (stream_update->output_color_space)
3188 su_flags->bits.out_csc = 1;
3189
3190 // TODO: Make each elevation explicit, as to not override fast stream in crct_timing_adjust
3191 if (su_flags->raw)
3192 elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
3193
3194 // Non-global cases
3195
3196 if (stream_update->gamut_remap) {
3197 su_flags->bits.gamut_remap = 1;
3198 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
3199 }
3200
3201 if ((stream_update->hdr_static_metadata && !stream_update->stream->use_dynamic_meta) ||
3202 stream_update->vrr_infopacket ||
3203 stream_update->vsc_infopacket ||
3204 stream_update->vsp_infopacket ||
3205 stream_update->hfvsif_infopacket ||
3206 stream_update->adaptive_sync_infopacket ||
3207 stream_update->vtem_infopacket ||
3208 stream_update->avi_infopacket) {
3209 su_flags->bits.info_frame = 1;
3210 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
3211 }
3212
3213 if (stream_update->hdr_static_metadata && stream_update->stream->use_dynamic_meta) {
3214 su_flags->bits.dmdata = 1;
3215 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
3216 }
3217
3218 if (stream_update->output_csc_transform) {
3219 su_flags->bits.out_csc = 1;
3220 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
3221 }
3222
3223 if (!check_config->enable_legacy_fast_update && stream_update->out_transfer_func) {
3224 su_flags->bits.out_tf = 1;
3225 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
3226 }
3227
3228 if (stream_update->periodic_interrupt) {
3229 su_flags->bits.periodic_interrupt = 1;
3230 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
3231 }
3232
3233 if (stream_update->dither_option) {
3234 su_flags->bits.dither = 1;
3235 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
3236 }
3237
3238 if (stream_update->cursor_attributes) {
3239 su_flags->bits.cursor_attr = 1;
3240 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
3241 }
3242
3243 if (stream_update->cursor_position) {
3244 su_flags->bits.cursor_pos = 1;
3245 elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
3246 }
3247 }
3248
3249 for (int i = 0 ; i < surface_count; i++) {
3250 struct dc_update_descriptor inner_type =
3251 det_surface_update(check_config, &updates[i]);
3252
3253 elevate_update_type(&overall_type, inner_type.update_type, inner_type.lock_descriptor);
3254 }
3255
3256 return overall_type;
3257 }
3258
3259 /**
3260 * dc_check_state_update - Classify a dc_state_update by locking / re-entrancy requirements.
3261 * @check_config: ASIC capabilities and display configuration context
3262 * @updates: root update object describing the full desired commit
3263 *
3264 * Determines whether the update requires a fast, medium, or full lock
3265 * by inspecting the stream, stream_update, and surface_updates carried on
3266 * the root object. A probe update elevates the result to at least MED with
3267 * the PROBE lock, so a probe-carrying commit takes the probe mutex.
3268 *
3269 * Return: dc_update_descriptor with update_type and lock_descriptor.
3270 */
dc_check_state_update(const struct dc_check_config * check_config,const struct dc_state_update * updates)3271 struct dc_update_descriptor dc_check_state_update(
3272 const struct dc_check_config *check_config,
3273 const struct dc_state_update *updates)
3274 {
3275 struct dc_update_descriptor desc = {0};
3276
3277 if (updates->stream_update)
3278 stream_update_flags_clear(&updates->stream_update->stream->update_flags);
3279 for (int i = 0; i < updates->surface_count; i++)
3280 dc_pipe_update_bits_clear(&updates->surface_updates[i].surface->update_bits);
3281
3282 desc = check_update_surfaces_for_stream(check_config, updates->surface_updates,
3283 updates->surface_count, updates->stream_update);
3284
3285 if (updates->probe_updates && updates->probe_updates->probe_count > 0)
3286 elevate_update_type(&desc, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_PROBE);
3287
3288 return desc;
3289 }
3290
3291 /**
3292 * dc_check_update_surfaces_for_stream - Shim for dc_check_state_update.
3293 * @check_config: ASIC capabilities and display configuration context
3294 * @updates: array of surface update descriptors
3295 * @surface_count: number of entries in @updates
3296 * @stream_update: optional stream update
3297 *
3298 * Packs the individual arguments into a dc_state_update and forwards to
3299 * dc_check_state_update(). Preserved for out-of-tree and incremental callers.
3300 *
3301 * Return: dc_update_descriptor with update_type and lock_descriptor.
3302 */
dc_check_update_surfaces_for_stream(const struct dc_check_config * check_config,struct dc_surface_update * updates,int surface_count,struct dc_stream_update * stream_update)3303 struct dc_update_descriptor dc_check_update_surfaces_for_stream(
3304 const struct dc_check_config *check_config,
3305 struct dc_surface_update *updates,
3306 int surface_count,
3307 struct dc_stream_update *stream_update)
3308 {
3309 struct dc_state_update root = {
3310 .stream = stream_update ? stream_update->stream : NULL,
3311 .stream_update = stream_update,
3312 .surface_updates = updates,
3313 .surface_count = surface_count,
3314 .probe_updates = NULL
3315 };
3316
3317 return dc_check_state_update(check_config, &root);
3318 }
3319
stream_get_status(struct dc_state * ctx,struct dc_stream_state * stream)3320 static struct dc_stream_status *stream_get_status(
3321 struct dc_state *ctx,
3322 struct dc_stream_state *stream)
3323 {
3324 uint8_t i;
3325
3326 for (i = 0; i < ctx->stream_count; i++) {
3327 if (stream == ctx->streams[i]) {
3328 return &ctx->stream_status[i];
3329 }
3330 }
3331
3332 return NULL;
3333 }
3334
3335 static const enum dc_update_type update_surface_trace_level = UPDATE_TYPE_FULL;
3336
copy_surface_update_to_plane(struct dc_plane_state * surface,struct dc_surface_update * srf_update)3337 static void copy_surface_update_to_plane(
3338 struct dc_plane_state *surface,
3339 struct dc_surface_update *srf_update)
3340 {
3341 if (srf_update->flip_addr) {
3342 surface->address = srf_update->flip_addr->address;
3343 surface->flip_immediate =
3344 srf_update->flip_addr->flip_immediate;
3345 surface->time.time_elapsed_in_us[surface->time.index] =
3346 (unsigned int)(srf_update->flip_addr->flip_timestamp_in_us -
3347 surface->time.prev_update_time_in_us);
3348 surface->time.prev_update_time_in_us =
3349 (unsigned int)srf_update->flip_addr->flip_timestamp_in_us;
3350 surface->time.index++;
3351 if (surface->time.index >= DC_PLANE_UPDATE_TIMES_MAX)
3352 surface->time.index = 0;
3353
3354 surface->triplebuffer_flips = srf_update->flip_addr->triplebuffer_flips;
3355 }
3356
3357 if (srf_update->scaling_info) {
3358 surface->scaling_quality =
3359 srf_update->scaling_info->scaling_quality;
3360 surface->dst_rect =
3361 srf_update->scaling_info->dst_rect;
3362 surface->src_rect =
3363 srf_update->scaling_info->src_rect;
3364 surface->clip_rect =
3365 srf_update->scaling_info->clip_rect;
3366 }
3367
3368 if (srf_update->plane_info) {
3369 surface->color_space =
3370 srf_update->plane_info->color_space;
3371 surface->format =
3372 srf_update->plane_info->format;
3373 surface->plane_size =
3374 srf_update->plane_info->plane_size;
3375 surface->rotation =
3376 srf_update->plane_info->rotation;
3377 surface->horizontal_mirror =
3378 srf_update->plane_info->horizontal_mirror;
3379 surface->stereo_format =
3380 srf_update->plane_info->stereo_format;
3381 surface->tiling_info =
3382 srf_update->plane_info->tiling_info;
3383 surface->visible =
3384 srf_update->plane_info->visible;
3385 surface->per_pixel_alpha =
3386 srf_update->plane_info->per_pixel_alpha;
3387 surface->global_alpha =
3388 srf_update->plane_info->global_alpha;
3389 surface->global_alpha_value =
3390 srf_update->plane_info->global_alpha_value;
3391 surface->dcc =
3392 srf_update->plane_info->dcc;
3393 surface->layer_index =
3394 srf_update->plane_info->layer_index;
3395 surface->scaling_linearity =
3396 srf_update->plane_info->scaling_linearity;
3397 surface->cositing =
3398 srf_update->plane_info->cositing;
3399 }
3400
3401 if (srf_update->gamma) {
3402 memcpy(&surface->gamma_correction.entries,
3403 &srf_update->gamma->entries,
3404 sizeof(struct dc_gamma_entries));
3405 surface->gamma_correction.is_identity =
3406 srf_update->gamma->is_identity;
3407 surface->gamma_correction.num_entries =
3408 srf_update->gamma->num_entries;
3409 surface->gamma_correction.type =
3410 srf_update->gamma->type;
3411 }
3412 if (srf_update->cm_hist_control) {
3413 memcpy(&surface->cm_hist_control,
3414 srf_update->cm_hist_control,
3415 sizeof(surface->cm_hist_control));
3416 }
3417
3418 if (srf_update->in_transfer_func) {
3419 surface->in_transfer_func.sdr_ref_white_level =
3420 srf_update->in_transfer_func->sdr_ref_white_level;
3421 surface->in_transfer_func.tf =
3422 srf_update->in_transfer_func->tf;
3423 surface->in_transfer_func.type =
3424 srf_update->in_transfer_func->type;
3425 memcpy(&surface->in_transfer_func.tf_pts,
3426 &srf_update->in_transfer_func->tf_pts,
3427 sizeof(struct dc_transfer_func_distributed_points));
3428 }
3429
3430 /* Shaper, 3DLUT, 1DLUT */
3431 if (srf_update->cm) {
3432 struct kref refcount = surface->cm.refcount;
3433
3434 memcpy(&surface->cm, srf_update->cm, sizeof(surface->cm));
3435 surface->cm.refcount = refcount;
3436
3437 }
3438
3439 if (srf_update->hdr_mult.value)
3440 surface->hdr_mult =
3441 srf_update->hdr_mult;
3442
3443 if (srf_update->sdr_white_level_nits)
3444 surface->sdr_white_level_nits =
3445 srf_update->sdr_white_level_nits;
3446
3447 if (srf_update->input_csc_color_matrix)
3448 surface->input_csc_color_matrix =
3449 *srf_update->input_csc_color_matrix;
3450
3451 if (srf_update->coeff_reduction_factor)
3452 surface->coeff_reduction_factor =
3453 *srf_update->coeff_reduction_factor;
3454
3455 if (srf_update->gamut_remap_matrix)
3456 surface->gamut_remap_matrix =
3457 *srf_update->gamut_remap_matrix;
3458
3459 if (srf_update->cursor_csc_color_matrix)
3460 surface->cursor_csc_color_matrix =
3461 *srf_update->cursor_csc_color_matrix;
3462
3463 if (srf_update->bias_and_scale.bias_and_scale_valid)
3464 surface->bias_and_scale =
3465 srf_update->bias_and_scale;
3466 }
3467
copy_stream_update_to_stream(struct dc * dc,struct dc_state * context,struct dc_stream_state * stream,struct dc_stream_update * update)3468 static void copy_stream_update_to_stream(struct dc *dc,
3469 struct dc_state *context,
3470 struct dc_stream_state *stream,
3471 struct dc_stream_update *update)
3472 {
3473 (void)context;
3474 struct dc_context *dc_ctx = dc->ctx;
3475
3476 if (update == NULL || stream == NULL)
3477 return;
3478
3479 if (update->src.height && update->src.width)
3480 stream->src = update->src;
3481
3482 if (update->dst.height && update->dst.width)
3483 stream->dst = update->dst;
3484
3485 if (update->out_transfer_func) {
3486 stream->out_transfer_func.sdr_ref_white_level =
3487 update->out_transfer_func->sdr_ref_white_level;
3488 stream->out_transfer_func.tf = update->out_transfer_func->tf;
3489 stream->out_transfer_func.type =
3490 update->out_transfer_func->type;
3491 memcpy(&stream->out_transfer_func.tf_pts,
3492 &update->out_transfer_func->tf_pts,
3493 sizeof(struct dc_transfer_func_distributed_points));
3494 }
3495
3496 if (update->hdr_static_metadata)
3497 stream->hdr_static_metadata = *update->hdr_static_metadata;
3498
3499 if (update->abm_level)
3500 stream->abm_level = *update->abm_level;
3501
3502 if (update->periodic_interrupt)
3503 stream->periodic_interrupt = *update->periodic_interrupt;
3504
3505 if (update->gamut_remap)
3506 stream->gamut_remap_matrix = *update->gamut_remap;
3507
3508 /* Note: this being updated after mode set is currently not a use case
3509 * however if it arises OCSC would need to be reprogrammed at the
3510 * minimum
3511 */
3512 if (update->output_color_space)
3513 stream->output_color_space = *update->output_color_space;
3514
3515 if (update->output_csc_transform)
3516 stream->csc_color_matrix = *update->output_csc_transform;
3517
3518 if (update->vrr_infopacket)
3519 stream->vrr_infopacket = *update->vrr_infopacket;
3520
3521 if (update->hw_cursor_req)
3522 stream->hw_cursor_req = *update->hw_cursor_req;
3523
3524 if (update->allow_freesync)
3525 stream->allow_freesync = *update->allow_freesync;
3526
3527 if (update->vrr_active_variable)
3528 stream->vrr_active_variable = *update->vrr_active_variable;
3529
3530 if (update->vrr_active_fixed)
3531 stream->vrr_active_fixed = *update->vrr_active_fixed;
3532
3533 if (update->crtc_timing_adjust) {
3534 if (stream->adjust.v_total_min != update->crtc_timing_adjust->v_total_min ||
3535 stream->adjust.v_total_max != update->crtc_timing_adjust->v_total_max ||
3536 stream->adjust.timing_adjust_pending)
3537 update->crtc_timing_adjust->timing_adjust_pending = true;
3538 stream->adjust = *update->crtc_timing_adjust;
3539 update->crtc_timing_adjust->timing_adjust_pending = false;
3540 }
3541
3542 if (update->dpms_off)
3543 stream->dpms_off = *update->dpms_off;
3544
3545 if (update->hfvsif_infopacket)
3546 stream->hfvsif_infopacket = *update->hfvsif_infopacket;
3547
3548 if (update->vtem_infopacket)
3549 stream->vtem_infopacket = *update->vtem_infopacket;
3550
3551 if (update->vsc_infopacket)
3552 stream->vsc_infopacket = *update->vsc_infopacket;
3553
3554 if (update->vsp_infopacket)
3555 stream->vsp_infopacket = *update->vsp_infopacket;
3556
3557 if (update->adaptive_sync_infopacket)
3558 stream->adaptive_sync_infopacket = *update->adaptive_sync_infopacket;
3559
3560 if (update->avi_infopacket)
3561 stream->avi_infopacket = *update->avi_infopacket;
3562
3563 if (update->dither_option)
3564 stream->dither_option = *update->dither_option;
3565
3566 if (update->pending_test_pattern)
3567 stream->test_pattern = *update->pending_test_pattern;
3568 /* update current stream with writeback info */
3569 if (update->wb_update) {
3570 unsigned int i;
3571
3572 stream->num_wb_info = update->wb_update->num_wb_info;
3573 ASSERT(stream->num_wb_info <= MAX_DWB_PIPES);
3574 for (i = 0; i < stream->num_wb_info; i++)
3575 stream->writeback_info[i] =
3576 update->wb_update->writeback_info[i];
3577 }
3578 if (update->dsc_config) {
3579 struct dc_dsc_config old_dsc_cfg = stream->timing.dsc_cfg;
3580 uint32_t old_dsc_enabled = stream->timing.flags.DSC;
3581 uint32_t enable_dsc = (update->dsc_config->num_slices_h != 0 &&
3582 update->dsc_config->num_slices_v != 0);
3583
3584 /* Use temporarry context for validating new DSC config */
3585 struct dc_state *dsc_validate_context = dc_state_create_copy(dc->current_state);
3586
3587 if (dsc_validate_context) {
3588 stream->timing.dsc_cfg = *update->dsc_config;
3589 stream->timing.flags.DSC = enable_dsc;
3590 if (dc->res_pool->funcs->validate_bandwidth(dc, dsc_validate_context,
3591 DC_VALIDATE_MODE_ONLY) != DC_OK) {
3592 stream->timing.dsc_cfg = old_dsc_cfg;
3593 stream->timing.flags.DSC = old_dsc_enabled;
3594 update->dsc_config = NULL;
3595 }
3596
3597 dc_state_release(dsc_validate_context);
3598 } else {
3599 DC_ERROR("Failed to allocate new validate context for DSC change\n");
3600 update->dsc_config = NULL;
3601 }
3602 }
3603 if (update->scaler_sharpener_update)
3604 stream->scaler_sharpener_update = *update->scaler_sharpener_update;
3605 if (update->sharpening_required)
3606 stream->sharpening_required = *update->sharpening_required;
3607
3608 if (update->blending_linearity)
3609 stream->blending_linearity = *update->blending_linearity;
3610
3611 if (update->drr_trigger_mode) {
3612 stream->drr_trigger_mode = *update->drr_trigger_mode;
3613 }
3614 }
3615
backup_planes_and_stream_state(struct dc_scratch_space * scratch,struct dc_stream_state * stream)3616 static void backup_planes_and_stream_state(
3617 struct dc_scratch_space *scratch,
3618 struct dc_stream_state *stream)
3619 {
3620 int i;
3621 struct dc_stream_status *status = dc_stream_get_status(stream);
3622
3623 if (!status)
3624 return;
3625
3626 for (i = 0; i < status->plane_count; i++) {
3627 dc_plane_copy_config(&scratch->plane_states[i], status->plane_states[i]);
3628 }
3629 scratch->stream_state = *stream;
3630 }
3631
restore_planes_and_stream_state(struct dc_scratch_space * scratch,struct dc_stream_state * stream)3632 static void restore_planes_and_stream_state(
3633 struct dc_scratch_space *scratch,
3634 struct dc_stream_state *stream)
3635 {
3636 int i;
3637 struct dc_stream_status *status = dc_stream_get_status(stream);
3638
3639 if (!status)
3640 return;
3641
3642 for (i = 0; i < status->plane_count; i++) {
3643 dc_plane_copy_config(status->plane_states[i], &scratch->plane_states[i]);
3644 }
3645
3646 // refcount is persistent
3647 struct kref temp_refcount = stream->refcount;
3648 *stream = scratch->stream_state;
3649 stream->refcount = temp_refcount;
3650 }
3651
3652 /**
3653 * update_seamless_boot_flags() - Helper function for updating seamless boot flags
3654 *
3655 * @dc: Current DC state
3656 * @context: New DC state to be programmed
3657 * @surface_count: Number of surfaces that have an updated
3658 * @stream: Corresponding stream to be updated in the current flip
3659 *
3660 * Updating seamless boot flags do not need to be part of the commit sequence. This
3661 * helper function will update the seamless boot flags on each flip (if required)
3662 * outside of the HW commit sequence (fast or slow).
3663 *
3664 * Return: void
3665 */
update_seamless_boot_flags(struct dc * dc,struct dc_state * context,int surface_count,struct dc_stream_state * stream)3666 static void update_seamless_boot_flags(struct dc *dc,
3667 struct dc_state *context,
3668 int surface_count,
3669 struct dc_stream_state *stream)
3670 {
3671 if (get_seamless_boot_stream_count(context) > 0 && (surface_count > 0 || stream->dpms_off)) {
3672 /* Optimize seamless boot flag keeps clocks and watermarks high until
3673 * first flip. After first flip, optimization is required to lower
3674 * bandwidth. Important to note that it is expected UEFI will
3675 * only light up a single display on POST, therefore we only expect
3676 * one stream with seamless boot flag set.
3677 */
3678 if (stream->apply_seamless_boot_optimization) {
3679 stream->apply_seamless_boot_optimization = false;
3680
3681 if (get_seamless_boot_stream_count(context) == 0)
3682 dc->optimized_required = true;
3683 }
3684 }
3685 }
3686
3687 static bool full_update_required_weak(
3688 const struct dc *dc,
3689 const struct dc_surface_update *srf_updates,
3690 int surface_count,
3691 const struct dc_stream_update *stream_update,
3692 const struct dc_stream_state *stream);
3693
backup_and_set_minimal_pipe_split_policy(struct dc * dc,struct dc_state * context,struct pipe_split_policy_backup * policy)3694 static void backup_and_set_minimal_pipe_split_policy(struct dc *dc,
3695 struct dc_state *context,
3696 struct pipe_split_policy_backup *policy)
3697 {
3698 int i;
3699
3700 if (!dc->config.is_vmin_only_asic) {
3701 policy->mpc_policy = dc->debug.pipe_split_policy;
3702 dc->debug.pipe_split_policy = MPC_SPLIT_AVOID;
3703 }
3704 policy->dynamic_odm_policy = dc->debug.enable_single_display_2to1_odm_policy;
3705 dc->debug.enable_single_display_2to1_odm_policy = false;
3706 policy->subvp_policy = dc->debug.force_disable_subvp;
3707 dc->debug.force_disable_subvp = true;
3708 for (i = 0; i < context->stream_count; i++) {
3709 policy->force_odm[i] = context->streams[i]->debug.force_odm_combine_segments;
3710 if (context->streams[i]->debug.allow_transition_for_forced_odm)
3711 context->streams[i]->debug.force_odm_combine_segments = 0;
3712 }
3713 }
3714
restore_minimal_pipe_split_policy(struct dc * dc,struct dc_state * context,struct pipe_split_policy_backup * policy)3715 static void restore_minimal_pipe_split_policy(struct dc *dc,
3716 struct dc_state *context,
3717 struct pipe_split_policy_backup *policy)
3718 {
3719 uint8_t i;
3720
3721 if (!dc->config.is_vmin_only_asic)
3722 dc->debug.pipe_split_policy = policy->mpc_policy;
3723 dc->debug.enable_single_display_2to1_odm_policy =
3724 policy->dynamic_odm_policy;
3725 dc->debug.force_disable_subvp = policy->subvp_policy;
3726 for (i = 0; i < context->stream_count; i++)
3727 context->streams[i]->debug.force_odm_combine_segments = policy->force_odm[i];
3728 }
3729
3730 /**
3731 * update_planes_and_stream_state() - The function takes planes and stream
3732 * updates as inputs and determines the appropriate update type. If update type
3733 * is FULL, the function allocates a new context, populates and validates it.
3734 * Otherwise, it updates current dc context. The function will return both
3735 * new_context and new_update_type back to the caller. The function also backs
3736 * up both current and new contexts into corresponding dc state scratch memory.
3737 * TODO: The function does too many things, and even conditionally allocates dc
3738 * context memory implicitly. We should consider to break it down.
3739 *
3740 * @dc: Current DC state
3741 * @srf_updates: an array of surface updates
3742 * @surface_count: surface update count
3743 * @stream: Corresponding stream to be updated
3744 * @stream_update: stream update
3745 * @update_descriptor: describes what plane and stream changes to apply
3746 * @new_update_type: [out] determined update type by the function
3747 * @new_context: [out] new context allocated and validated if update type is
3748 * FULL, reference to current context if update type is less than FULL.
3749 *
3750 * Return: true if a valid update is populated into new_context, false
3751 * otherwise.
3752 */
update_planes_and_stream_state(struct dc * dc,struct dc_surface_update * srf_updates,int surface_count,struct dc_stream_state * stream,struct dc_stream_update * stream_update,enum dc_update_type * new_update_type,struct dc_state ** new_context)3753 static bool update_planes_and_stream_state(struct dc *dc,
3754 struct dc_surface_update *srf_updates, int surface_count,
3755 struct dc_stream_state *stream,
3756 struct dc_stream_update *stream_update,
3757 enum dc_update_type *new_update_type,
3758 struct dc_state **new_context)
3759 {
3760 struct dc_state *context;
3761 int i;
3762 unsigned int j;
3763 enum dc_update_type update_type;
3764 const struct dc_stream_status *stream_status;
3765 struct dc_context *dc_ctx = dc->ctx;
3766
3767 stream_status = dc_stream_get_status(stream);
3768
3769 if (!stream_status) {
3770 if (surface_count) /* Only an error condition if surf_count non-zero*/
3771 ASSERT(false);
3772
3773 return false; /* Cannot commit surface to stream that is not committed */
3774 }
3775
3776 context = dc->current_state;
3777 update_type = dc_check_update_surfaces_for_stream(
3778 &dc->check_config, srf_updates, surface_count, stream_update).update_type;
3779 if (full_update_required_weak(dc, srf_updates, surface_count, stream_update, stream))
3780 update_type = UPDATE_TYPE_FULL;
3781
3782 /* It is possible to receive a flip for one plane while there are multiple flip_immediate planes in the same stream.
3783 * E.g. Desktop and MPO plane are flip_immediate but only the MPO plane received a flip
3784 * Force the other flip_immediate planes to flip so GSL doesn't wait for a flip that won't come.
3785 */
3786 force_immediate_gsl_plane_flip(dc, srf_updates, surface_count);
3787 if (update_type == UPDATE_TYPE_FULL)
3788 backup_planes_and_stream_state(&dc->scratch.current_state, stream);
3789
3790 /* update current stream with the new updates */
3791 copy_stream_update_to_stream(dc, context, stream, stream_update);
3792
3793 /* do not perform surface update if surface has invalid dimensions
3794 * (all zero) and no scaling_info is provided
3795 */
3796 if (surface_count > 0) {
3797 for (i = 0; i < surface_count; i++) {
3798 if ((srf_updates[i].surface->src_rect.width == 0 ||
3799 srf_updates[i].surface->src_rect.height == 0 ||
3800 srf_updates[i].surface->dst_rect.width == 0 ||
3801 srf_updates[i].surface->dst_rect.height == 0) &&
3802 (!srf_updates[i].scaling_info ||
3803 srf_updates[i].scaling_info->src_rect.width == 0 ||
3804 srf_updates[i].scaling_info->src_rect.height == 0 ||
3805 srf_updates[i].scaling_info->dst_rect.width == 0 ||
3806 srf_updates[i].scaling_info->dst_rect.height == 0)) {
3807 DC_ERROR("Invalid src/dst rects in surface update!\n");
3808 return false;
3809 }
3810 }
3811 }
3812
3813 if (update_type == UPDATE_TYPE_FULL) {
3814 if (stream_update) {
3815 uint32_t dsc_changed = stream_update->stream->update_flags.bits.dsc_changed;
3816 stream_update_flags_set_full(&stream_update->stream->update_flags);
3817 stream_update->stream->update_flags.bits.dsc_changed = dsc_changed;
3818 }
3819 for (i = 0; i < surface_count; i++)
3820 dc_pipe_update_bits_set_full(&srf_updates[i].surface->update_bits);
3821 }
3822
3823 if (update_type >= update_surface_trace_level)
3824 update_surface_trace(dc, srf_updates, surface_count);
3825
3826 for (i = 0; i < surface_count; i++)
3827 copy_surface_update_to_plane(srf_updates[i].surface, &srf_updates[i]);
3828
3829 if (update_type >= UPDATE_TYPE_FULL) {
3830 struct dc_plane_state *new_planes[MAX_SURFACES] = {0};
3831
3832 for (i = 0; i < surface_count; i++)
3833 new_planes[i] = srf_updates[i].surface;
3834
3835 /* initialize scratch memory for building context */
3836 context = dc_state_create_copy(dc->current_state);
3837 if (context == NULL) {
3838 DC_ERROR("Failed to allocate new validate context!\n");
3839 return false;
3840 }
3841
3842 /* For each full update, remove all existing phantom pipes first.
3843 * Ensures that we have enough pipes for newly added MPO planes
3844 */
3845 dc_state_remove_phantom_streams_and_planes(dc, context);
3846 dc_state_release_phantom_streams_and_planes(dc, context);
3847
3848 /*remove old surfaces from context */
3849 if (!dc_state_rem_all_planes_for_stream(dc, stream, context)) {
3850
3851 BREAK_TO_DEBUGGER();
3852 goto fail;
3853 }
3854
3855 /* add surface to context */
3856 if (!dc_state_add_all_planes_for_stream(dc, stream, new_planes, surface_count, context)) {
3857
3858 BREAK_TO_DEBUGGER();
3859 goto fail;
3860 }
3861 }
3862
3863 /* save update parameters into surface */
3864 for (i = 0; i < surface_count; i++) {
3865 struct dc_plane_state *surface = srf_updates[i].surface;
3866
3867 if (update_type != UPDATE_TYPE_MED)
3868 continue;
3869 if (surface->update_bits.position_change) {
3870 for (j = 0; j < dc->res_pool->pipe_count; j++) {
3871 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
3872
3873 if (pipe_ctx->plane_state != surface)
3874 continue;
3875
3876 resource_build_scaling_params(pipe_ctx);
3877 }
3878 }
3879 }
3880
3881 if (update_type == UPDATE_TYPE_FULL) {
3882 struct pipe_split_policy_backup policy;
3883 bool minimize = false;
3884
3885 if (dc->check_config.deferred_transition_state) {
3886 if (dc->check_config.transition_countdown_to_steady_state) {
3887 /* During countdown, all new contexts created as minimal transition states */
3888 minimize = true;
3889 } else {
3890 dc->check_config.deferred_transition_state = false;
3891 }
3892 }
3893
3894 if (minimize)
3895 backup_and_set_minimal_pipe_split_policy(dc, context, &policy);
3896
3897 if (dc->res_pool->funcs->validate_bandwidth(dc, context, DC_VALIDATE_MODE_AND_PROGRAMMING) != DC_OK) {
3898 if (minimize)
3899 restore_minimal_pipe_split_policy(dc, context, &policy);
3900 BREAK_TO_DEBUGGER();
3901 goto fail;
3902 }
3903
3904 if (minimize)
3905 restore_minimal_pipe_split_policy(dc, context, &policy);
3906 }
3907 update_seamless_boot_flags(dc, context, surface_count, stream);
3908
3909 *new_context = context;
3910 *new_update_type = update_type;
3911 if (update_type == UPDATE_TYPE_FULL)
3912 backup_planes_and_stream_state(&dc->scratch.new_state, stream);
3913
3914 return true;
3915
3916 fail:
3917 dc_state_release(context);
3918
3919 return false;
3920
3921 }
3922
program_cursor_attributes_sequence(struct dc * dc,struct dc_stream_state * stream,struct dc_state * context,struct block_sequence_state * seq_state)3923 static void program_cursor_attributes_sequence(
3924 struct dc *dc,
3925 struct dc_stream_state *stream,
3926 struct dc_state *context,
3927 struct block_sequence_state *seq_state)
3928 {
3929 int k;
3930 struct pipe_ctx *pipe_to_program = NULL;
3931 bool enable_cursor_offload = dc_dmub_srv_is_cursor_offload_enabled(dc);
3932
3933 for (k = 0; k < (int)dc->res_pool->pipe_count; k++) {
3934 struct pipe_ctx *tmp_pipe = &context->res_ctx.pipe_ctx[k];
3935
3936 if (tmp_pipe->stream != stream)
3937 continue;
3938
3939 if (!pipe_to_program) {
3940 pipe_to_program = tmp_pipe;
3941
3942 if (enable_cursor_offload && dc->hwss.begin_cursor_offload_update) {
3943 hwss_add_begin_cursor_offload_update(seq_state, dc, tmp_pipe);
3944 } else {
3945 hwss_add_cursor_lock(seq_state, dc, pipe_to_program, true);
3946 if (pipe_to_program->next_odm_pipe)
3947 hwss_add_cursor_lock(seq_state, dc, pipe_to_program->next_odm_pipe, true);
3948 }
3949 }
3950
3951 hwss_add_set_cursor_attribute(seq_state, dc, tmp_pipe);
3952 if (dc->ctx->dmub_srv)
3953 hwss_add_send_update_cursor_info_to_dmu(seq_state, tmp_pipe, k);
3954 if (dc->hwss.set_cursor_sdr_white_level)
3955 hwss_add_set_cursor_sdr_white_level(seq_state, dc, tmp_pipe);
3956 if (enable_cursor_offload && dc->hwss.update_cursor_offload_pipe)
3957 hwss_add_update_cursor_offload_pipe(seq_state, dc, tmp_pipe);
3958 }
3959
3960 if (pipe_to_program) {
3961 if (enable_cursor_offload && dc->hwss.commit_cursor_offload_update) {
3962 hwss_add_commit_cursor_offload_update(seq_state, dc, pipe_to_program);
3963 } else {
3964 hwss_add_cursor_lock(seq_state, dc, pipe_to_program, false);
3965 if (pipe_to_program->next_odm_pipe)
3966 hwss_add_cursor_lock(seq_state, dc, pipe_to_program->next_odm_pipe, false);
3967 }
3968 }
3969 }
3970
program_cursor_position_sequence(struct dc * dc,struct dc_stream_state * stream,struct dc_state * context,struct block_sequence_state * seq_state)3971 static void program_cursor_position_sequence(
3972 struct dc *dc,
3973 struct dc_stream_state *stream,
3974 struct dc_state *context,
3975 struct block_sequence_state *seq_state)
3976 {
3977 int k;
3978 struct pipe_ctx *pipe_to_program = NULL;
3979 bool enable_cursor_offload = dc_dmub_srv_is_cursor_offload_enabled(dc);
3980
3981 for (k = 0; k < (int)dc->res_pool->pipe_count; k++) {
3982 struct pipe_ctx *tmp_pipe = &context->res_ctx.pipe_ctx[k];
3983
3984 if (tmp_pipe->stream != stream ||
3985 (!tmp_pipe->plane_res.mi && !tmp_pipe->plane_res.hubp) ||
3986 !tmp_pipe->plane_state ||
3987 (!tmp_pipe->plane_res.xfm && !tmp_pipe->plane_res.dpp) ||
3988 (!tmp_pipe->plane_res.ipp && !tmp_pipe->plane_res.dpp))
3989 continue;
3990
3991 if (!pipe_to_program) {
3992 pipe_to_program = tmp_pipe;
3993
3994 if (enable_cursor_offload && dc->hwss.begin_cursor_offload_update)
3995 hwss_add_begin_cursor_offload_update(seq_state, dc, tmp_pipe);
3996 else
3997 hwss_add_cursor_lock(seq_state, dc, pipe_to_program, true);
3998 }
3999
4000 hwss_add_set_cursor_position(seq_state, dc, tmp_pipe);
4001 if (enable_cursor_offload && dc->hwss.update_cursor_offload_pipe)
4002 hwss_add_update_cursor_offload_pipe(seq_state, dc, tmp_pipe);
4003
4004 if (dc->ctx->dmub_srv)
4005 hwss_add_send_update_cursor_info_to_dmu(seq_state, tmp_pipe, k);
4006 }
4007
4008 if (pipe_to_program) {
4009 if (enable_cursor_offload && dc->hwss.commit_cursor_offload_update)
4010 hwss_add_commit_cursor_offload_update(seq_state, dc, pipe_to_program);
4011 else
4012 hwss_add_cursor_lock(seq_state, dc, pipe_to_program, false);
4013 }
4014 }
4015
add_update_info_frame_sequence(struct block_sequence_state * seq_state,struct pipe_ctx * pipe_ctx)4016 static void add_update_info_frame_sequence(
4017 struct block_sequence_state *seq_state,
4018 struct pipe_ctx *pipe_ctx)
4019 {
4020 bool is_hdmi_tmds;
4021 bool is_dp;
4022 bool is_hdmi_frl;
4023
4024 if (!pipe_ctx || !pipe_ctx->stream)
4025 return;
4026
4027 if (pipe_ctx->stream_res.stream_enc == NULL &&
4028 pipe_ctx->stream_res.hpo_frl_stream_enc == NULL)
4029 return;
4030
4031 is_hdmi_tmds = dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal);
4032 is_dp = dc_is_dp_signal(pipe_ctx->stream->signal);
4033
4034 is_hdmi_frl = dc_is_hdmi_frl_signal(pipe_ctx->stream->signal);
4035 if (!is_hdmi_tmds && !is_dp && !is_hdmi_frl)
4036 return;
4037
4038 if (is_hdmi_tmds) {
4039 hwss_add_stream_enc_update_hdmi_info_packets(seq_state, pipe_ctx);
4040 return;
4041 }
4042
4043 if (is_hdmi_frl) {
4044 hwss_add_hpo_frl_stream_enc_update_hdmi_info_packets(seq_state, pipe_ctx);
4045 return;
4046 }
4047
4048 if (is_dp) {
4049 if (dp_is_128b_132b_signal(pipe_ctx)) {
4050 hwss_add_hpo_dp_stream_enc_update_dp_info_packets_sdp_line_num(seq_state, pipe_ctx);
4051 hwss_add_hpo_dp_stream_enc_update_dp_info_packets(seq_state, pipe_ctx);
4052 } else {
4053 hwss_add_stream_enc_update_dp_info_packets_sdp_line_num(seq_state, pipe_ctx);
4054 hwss_add_stream_enc_update_dp_info_packets(seq_state, pipe_ctx);
4055 }
4056 }
4057 }
4058
add_link_update_dsc_config_sequence(struct block_sequence_state * seq_state,struct pipe_ctx * pipe_ctx,struct dsc_config * dsc_cfg,struct dsc_optc_config * dsc_optc_cfg)4059 static void add_link_update_dsc_config_sequence(
4060 struct block_sequence_state *seq_state,
4061 struct pipe_ctx *pipe_ctx,
4062 struct dsc_config *dsc_cfg,
4063 struct dsc_optc_config *dsc_optc_cfg)
4064 {
4065 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
4066 struct dc_stream_state *stream = pipe_ctx->stream;
4067 struct dc *dc = stream->ctx->dc;
4068 struct dccg *dccg = dc->res_pool->dccg;
4069 struct pipe_ctx *top_pipe = pipe_ctx;
4070 struct pipe_ctx *odm_pipe = NULL;
4071 int opp_cnt = 1;
4072 bool should_use_dto_dscclk = false;
4073 struct dsc_config dsc_pps_cfg;
4074 uint8_t *dsc_packed_pps = stream->dsc_packed_pps;
4075 int last_dsc_set_config_step = 0;
4076
4077 if (!stream->timing.flags.DSC || !dsc)
4078 return;
4079
4080 while (top_pipe->prev_odm_pipe)
4081 top_pipe = top_pipe->prev_odm_pipe;
4082
4083 for (odm_pipe = top_pipe->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
4084 opp_cnt++;
4085
4086 memset(dsc_cfg, 0, sizeof(*dsc_cfg));
4087 memset(dsc_optc_cfg, 0, sizeof(*dsc_optc_cfg));
4088
4089 dsc_cfg->pic_width = (stream->timing.h_addressable +
4090 top_pipe->dsc_padding_params.dsc_hactive_padding +
4091 stream->timing.h_border_left +
4092 stream->timing.h_border_right) / opp_cnt;
4093 dsc_cfg->pic_height = stream->timing.v_addressable +
4094 stream->timing.v_border_top +
4095 stream->timing.v_border_bottom;
4096 dsc_cfg->pixel_encoding = stream->timing.pixel_encoding;
4097 dsc_cfg->color_depth = stream->timing.display_color_depth;
4098 dsc_cfg->is_odm = top_pipe->next_odm_pipe ? true : false;
4099 dsc_cfg->dc_dsc_cfg = stream->timing.dsc_cfg;
4100 ASSERT(dsc_cfg->dc_dsc_cfg.num_slices_h % opp_cnt == 0);
4101 dsc_cfg->dc_dsc_cfg.num_slices_h /= opp_cnt;
4102 dsc_cfg->dsc_padding = 0;
4103
4104 if (dccg && dccg->funcs->set_dto_dscclk &&
4105 stream->timing.pix_clk_100hz > 480000)
4106 should_use_dto_dscclk = true;
4107
4108 if (should_use_dto_dscclk)
4109 hwss_add_dccg_set_dto_dscclk(seq_state, dccg, dsc->inst,
4110 dsc_cfg->dc_dsc_cfg.num_slices_h);
4111
4112 last_dsc_set_config_step = *seq_state->num_steps;
4113 hwss_add_dsc_set_config(seq_state, dsc, dsc_cfg, dsc_optc_cfg);
4114 hwss_add_dsc_enable_with_opp(seq_state, top_pipe);
4115
4116 for (odm_pipe = top_pipe->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
4117 struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;
4118
4119 if (should_use_dto_dscclk)
4120 hwss_add_dccg_set_dto_dscclk(seq_state, dccg, odm_dsc->inst,
4121 dsc_cfg->dc_dsc_cfg.num_slices_h);
4122
4123 last_dsc_set_config_step = *seq_state->num_steps;
4124 hwss_add_dsc_set_config(seq_state, odm_dsc, dsc_cfg, dsc_optc_cfg);
4125 hwss_add_dsc_enable_with_opp(seq_state, odm_pipe);
4126 }
4127
4128 if (dc_is_dp_signal(stream->signal) && !dp_is_128b_132b_signal(pipe_ctx))
4129 hwss_add_stream_enc_dp_set_dsc_config(seq_state,
4130 pipe_ctx->stream_res.stream_enc,
4131 &seq_state->steps[last_dsc_set_config_step].params.dsc_set_config_simple_params.dsc_optc_cfg);
4132
4133 hwss_add_tg_set_dsc_config(seq_state, top_pipe->stream_res.tg,
4134 &seq_state->steps[last_dsc_set_config_step].params.dsc_set_config_simple_params.dsc_optc_cfg, true);
4135
4136 memset(&dsc_pps_cfg, 0, sizeof(dsc_pps_cfg));
4137 dsc_pps_cfg.pic_width = stream->timing.h_addressable +
4138 stream->timing.h_border_left + stream->timing.h_border_right;
4139 dsc_pps_cfg.pic_height = stream->timing.v_addressable +
4140 stream->timing.v_border_top + stream->timing.v_border_bottom;
4141 dsc_pps_cfg.pixel_encoding = stream->timing.pixel_encoding;
4142 dsc_pps_cfg.color_depth = stream->timing.display_color_depth;
4143 dsc_pps_cfg.is_odm = top_pipe->next_odm_pipe ? true : false;
4144 dsc_pps_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
4145 dsc_pps_cfg.dsc_padding = top_pipe->dsc_padding_params.dsc_hactive_padding;
4146
4147 if (dsc->funcs->dsc_get_packed_pps) {
4148 dsc->funcs->dsc_get_packed_pps(dsc, &dsc_pps_cfg, dsc_packed_pps);
4149
4150 if (dc_is_dp_signal(stream->signal)) {
4151 if (dp_is_128b_132b_signal(pipe_ctx))
4152 hwss_add_hpo_dp_stream_enc_dp_set_dsc_pps_info_packet(seq_state,
4153 pipe_ctx->stream_res.hpo_dp_stream_enc,
4154 true, dsc_packed_pps, false);
4155 else
4156 hwss_add_stream_enc_dp_set_dsc_pps_info_packet(seq_state,
4157 pipe_ctx->stream_res.stream_enc,
4158 true, dsc_packed_pps, false);
4159 }
4160 else if (dc_is_hdmi_frl_signal(stream->signal)) {
4161 hwss_add_hpo_frl_stream_enc_set_dsc_config(seq_state,
4162 pipe_ctx->stream_res.hpo_frl_stream_enc,
4163 &stream->timing,
4164 dsc_packed_pps);
4165 }
4166 }
4167 }
4168
commit_planes_do_stream_update_sequence(struct dc * dc,struct dc_stream_state * stream,struct dc_stream_update * stream_update,enum dc_update_type update_type,struct dc_state * context,struct block_sequence block_sequence[MAX_HWSS_BLOCK_SEQUENCE_SIZE],unsigned int * num_steps)4169 static void commit_planes_do_stream_update_sequence(struct dc *dc,
4170 struct dc_stream_state *stream,
4171 struct dc_stream_update *stream_update,
4172 enum dc_update_type update_type,
4173 struct dc_state *context,
4174 struct block_sequence block_sequence[MAX_HWSS_BLOCK_SEQUENCE_SIZE],
4175 unsigned int *num_steps)
4176 {
4177 int j;
4178 struct block_sequence_state seq_state = { .steps = block_sequence, .num_steps = num_steps };
4179 unsigned int dsc_cfg_index = 0;
4180 *num_steps = 0; // Initialize to 0
4181
4182 // Stream updates
4183 for (j = 0; j < (int)dc->res_pool->pipe_count; j++) {
4184 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
4185
4186 if (resource_is_pipe_type(pipe_ctx, OTG_MASTER) && pipe_ctx->stream == stream) {
4187
4188 if (stream_update->periodic_interrupt && dc->hwss.setup_periodic_interrupt)
4189 hwss_add_setup_periodic_interrupt(&seq_state, dc, pipe_ctx);
4190
4191 if ((stream_update->hdr_static_metadata && !stream->use_dynamic_meta) ||
4192 stream_update->vrr_infopacket ||
4193 stream_update->vsc_infopacket ||
4194 stream_update->vsp_infopacket ||
4195 stream_update->hfvsif_infopacket ||
4196 stream_update->adaptive_sync_infopacket ||
4197 stream_update->vtem_infopacket ||
4198 stream_update->avi_infopacket) {
4199 resource_build_info_frame(pipe_ctx);
4200 add_update_info_frame_sequence(&seq_state, pipe_ctx);
4201
4202 if (dc_is_dp_signal(pipe_ctx->stream->signal))
4203 hwss_add_dp_trace_source_sequence(&seq_state,
4204 pipe_ctx->stream->link,
4205 DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME);
4206 }
4207
4208 if (stream_update->hdr_static_metadata &&
4209 stream->use_dynamic_meta &&
4210 dc->hwss.set_dmdata_attributes &&
4211 pipe_ctx->stream->dmdata_address.quad_part != 0)
4212 hwss_add_set_dmdata_attributes(&seq_state, pipe_ctx);
4213
4214 if (stream_update->gamut_remap)
4215 hwss_add_dpp_program_gamut_remap(&seq_state, pipe_ctx);
4216
4217 if (stream_update->output_csc_transform)
4218 hwss_add_program_output_csc(&seq_state, dc, pipe_ctx,
4219 stream->output_color_space,
4220 stream->csc_color_matrix.matrix,
4221 pipe_ctx->stream_res.opp->inst);
4222
4223 if (stream_update->dither_option) {
4224 struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe;
4225 resource_build_bit_depth_reduction_params(pipe_ctx->stream,
4226 &pipe_ctx->stream->bit_depth_params);
4227 hwss_add_opp_program_fmt(&seq_state, pipe_ctx->stream_res.opp,
4228 &stream->bit_depth_params,
4229 &stream->clamping);
4230 while (odm_pipe) {
4231 hwss_add_opp_program_fmt(&seq_state, odm_pipe->stream_res.opp,
4232 &stream->bit_depth_params,
4233 &stream->clamping);
4234 odm_pipe = odm_pipe->next_odm_pipe;
4235 }
4236 }
4237
4238 if (stream_update->cursor_attributes)
4239 program_cursor_attributes_sequence(dc, stream, context, &seq_state);
4240
4241 if (stream_update->cursor_position)
4242 program_cursor_position_sequence(dc, stream, context, &seq_state);
4243
4244 /* Full fe update*/
4245 if (update_type == UPDATE_TYPE_FAST)
4246 continue;
4247
4248 if (stream_update->dsc_config)
4249 if (dsc_cfg_index < MAX_PIPES) {
4250 struct dsc_config dsc_cfg;
4251 struct dsc_optc_config dsc_optc_cfg;
4252
4253 add_link_update_dsc_config_sequence(&seq_state,
4254 pipe_ctx,
4255 &dsc_cfg,
4256 &dsc_optc_cfg);
4257 }
4258
4259 if (stream_update->mst_bw_update) {
4260 if (stream_update->mst_bw_update->is_increase)
4261 hwss_add_link_increase_mst_payload(&seq_state,
4262 pipe_ctx,
4263 stream_update->mst_bw_update->mst_stream_bw);
4264 else
4265 hwss_add_link_reduce_mst_payload(&seq_state,
4266 pipe_ctx,
4267 stream_update->mst_bw_update->mst_stream_bw);
4268 }
4269
4270 if (stream_update->pending_test_pattern) {
4271 /*
4272 * test pattern params depends on ODM topology
4273 * changes that we could be applying to front
4274 * end. Since at the current stage front end
4275 * changes are not yet applied. We can only
4276 * apply test pattern in hw based on current
4277 * state and populate the final test pattern
4278 * params in new state. If current and new test
4279 * pattern params are different as result of
4280 * different ODM topology being used, it will be
4281 * detected and handle during front end
4282 * programming update.
4283 */
4284 hwss_add_dp_set_test_pattern(&seq_state,
4285 stream->link,
4286 stream->test_pattern.type,
4287 stream->test_pattern.color_space,
4288 stream->test_pattern.p_link_settings,
4289 stream->test_pattern.p_custom_pattern,
4290 stream->test_pattern.cust_pattern_size);
4291 resource_build_test_pattern_params(&context->res_ctx, pipe_ctx);
4292 }
4293
4294 if (stream_update->dpms_off) {
4295 // DPMS should not use partially updated pipe context
4296 struct pipe_ctx *dpms_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[j];
4297
4298 if (*stream_update->dpms_off) {
4299 hwss_add_link_set_dpms_off(&seq_state, dpms_pipe_ctx);
4300 /* for dpms, keep acquired resources*/
4301 if (dpms_pipe_ctx->stream_res.audio && !dc->debug.az_endpoint_mute_only)
4302 hwss_add_disable_audio_stream(&seq_state, dpms_pipe_ctx);
4303
4304 hwss_add_dc_set_optimized_required(&seq_state, dc, true);
4305
4306 } else {
4307 if (get_seamless_boot_stream_count(context) == 0 && dc->hwss.prepare_bandwidth_sequence)
4308 dc->hwss.prepare_bandwidth_sequence(dc, dc->current_state, &seq_state);
4309 hwss_add_link_set_dpms_on(&seq_state, dc->current_state, dpms_pipe_ctx);
4310 }
4311 } else if (pipe_ctx->stream->link->wa_flags.blank_stream_on_ocs_change && stream_update->output_color_space
4312 && !stream->dpms_off && dc_is_dp_signal(pipe_ctx->stream->signal)) {
4313 /*
4314 * Workaround for firmware issue in some receivers where they don't pick up
4315 * correct output color space unless DP link is disabled/re-enabled
4316 */
4317 hwss_add_link_set_dpms_on(&seq_state, dc->current_state, pipe_ctx);
4318 }
4319
4320 if (stream_update->abm_level && pipe_ctx->stream_res.abm) {
4321 bool should_program_abm = true;
4322
4323 // if otg funcs defined check if blanked before programming
4324 if (pipe_ctx->stream_res.tg->funcs->is_blanked)
4325 if (pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg))
4326 should_program_abm = false;
4327
4328 if (should_program_abm) {
4329 if (*stream_update->abm_level == ABM_LEVEL_IMMEDIATE_DISABLE) {
4330 hwss_add_abm_set_immediate_disable(&seq_state, dc, pipe_ctx);
4331 } else {
4332 hwss_add_abm_set_level(&seq_state, pipe_ctx->stream_res.abm, stream->abm_level);
4333 }
4334 }
4335 }
4336 }
4337 }
4338 }
4339
commit_planes_do_stream_update(struct dc * dc,struct dc_stream_state * stream,struct dc_stream_update * stream_update,enum dc_update_type update_type,struct dc_state * context)4340 static void commit_planes_do_stream_update(struct dc *dc,
4341 struct dc_stream_state *stream,
4342 struct dc_stream_update *stream_update,
4343 enum dc_update_type update_type,
4344 struct dc_state *context)
4345 {
4346 unsigned int j;
4347
4348 // Check if block sequence programming is enabled
4349 if (dc->debug.enable_block_sequence_programming) {
4350 unsigned int num_steps = 0;
4351
4352 // Build the block sequence using context's pre-allocated array
4353 commit_planes_do_stream_update_sequence(dc, stream, stream_update,
4354 update_type, context, context->block_sequence, &num_steps);
4355
4356 // Execute the block sequence
4357 if (num_steps > 0)
4358 hwss_execute_sequence(dc, context->block_sequence, num_steps);
4359
4360 return;
4361 }
4362
4363 // Legacy path (existing implementation)
4364 // Stream updates
4365 for (j = 0; j < dc->res_pool->pipe_count; j++) {
4366 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
4367
4368 if (resource_is_pipe_type(pipe_ctx, OTG_MASTER) && pipe_ctx->stream == stream) {
4369
4370 if (stream_update->periodic_interrupt && dc->hwss.setup_periodic_interrupt)
4371 dc->hwss.setup_periodic_interrupt(dc, pipe_ctx);
4372
4373 if ((stream_update->hdr_static_metadata && !stream->use_dynamic_meta) ||
4374 stream_update->vrr_infopacket ||
4375 stream_update->vsc_infopacket ||
4376 stream_update->vsp_infopacket ||
4377 stream_update->hfvsif_infopacket ||
4378 stream_update->adaptive_sync_infopacket ||
4379 stream_update->vtem_infopacket ||
4380 stream_update->avi_infopacket) {
4381 resource_build_info_frame(pipe_ctx);
4382 dc->hwss.update_info_frame(pipe_ctx);
4383
4384 if (dc_is_dp_signal(pipe_ctx->stream->signal))
4385 dc->link_srv->dp_trace_source_sequence(
4386 pipe_ctx->stream->link,
4387 DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME);
4388 }
4389
4390 if (stream_update->hdr_static_metadata &&
4391 stream->use_dynamic_meta &&
4392 dc->hwss.set_dmdata_attributes &&
4393 pipe_ctx->stream->dmdata_address.quad_part != 0)
4394 dc->hwss.set_dmdata_attributes(pipe_ctx);
4395
4396 if (stream_update->gamut_remap)
4397 dc_stream_set_gamut_remap(dc, stream);
4398
4399 if (stream_update->output_csc_transform)
4400 dc_stream_program_csc_matrix(dc, stream);
4401
4402 if (stream_update->dither_option) {
4403 struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe;
4404 resource_build_bit_depth_reduction_params(pipe_ctx->stream,
4405 &pipe_ctx->stream->bit_depth_params);
4406 pipe_ctx->stream_res.opp->funcs->opp_program_fmt(pipe_ctx->stream_res.opp,
4407 &stream->bit_depth_params,
4408 &stream->clamping);
4409 while (odm_pipe) {
4410 odm_pipe->stream_res.opp->funcs->opp_program_fmt(odm_pipe->stream_res.opp,
4411 &stream->bit_depth_params,
4412 &stream->clamping);
4413 odm_pipe = odm_pipe->next_odm_pipe;
4414 }
4415 }
4416
4417 if (stream_update->cursor_attributes)
4418 program_cursor_attributes(dc, stream);
4419
4420 if (stream_update->cursor_position)
4421 program_cursor_position(dc, stream);
4422
4423 /* Full fe update*/
4424 if (update_type == UPDATE_TYPE_FAST)
4425 continue;
4426
4427 if (stream_update->dsc_config)
4428 dc->link_srv->update_dsc_config(pipe_ctx);
4429
4430 if (stream_update->mst_bw_update) {
4431 if (stream_update->mst_bw_update->is_increase)
4432 dc->link_srv->increase_mst_payload(pipe_ctx,
4433 stream_update->mst_bw_update->mst_stream_bw);
4434 else
4435 dc->link_srv->reduce_mst_payload(pipe_ctx,
4436 stream_update->mst_bw_update->mst_stream_bw);
4437 }
4438
4439 if (stream_update->pending_test_pattern) {
4440 /*
4441 * test pattern params depends on ODM topology
4442 * changes that we could be applying to front
4443 * end. Since at the current stage front end
4444 * changes are not yet applied. We can only
4445 * apply test pattern in hw based on current
4446 * state and populate the final test pattern
4447 * params in new state. If current and new test
4448 * pattern params are different as result of
4449 * different ODM topology being used, it will be
4450 * detected and handle during front end
4451 * programming update.
4452 */
4453 dc->link_srv->dp_set_test_pattern(stream->link,
4454 stream->test_pattern.type,
4455 stream->test_pattern.color_space,
4456 stream->test_pattern.p_link_settings,
4457 stream->test_pattern.p_custom_pattern,
4458 stream->test_pattern.cust_pattern_size);
4459 resource_build_test_pattern_params(&context->res_ctx, pipe_ctx);
4460 }
4461
4462 // DPMS should not use partially updated pipe context
4463 struct pipe_ctx *dpms_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[j];
4464
4465 if (stream_update->dpms_off) {
4466 if (*stream_update->dpms_off) {
4467 dc->link_srv->set_dpms_off(dpms_pipe_ctx);
4468 /* for dpms, keep acquired resources*/
4469 if (dpms_pipe_ctx->stream_res.audio && !dc->debug.az_endpoint_mute_only) {
4470 struct audio *audio = dpms_pipe_ctx->stream_res.audio;
4471
4472 audio->funcs->az_disable(audio);
4473 }
4474
4475 dc->optimized_required = true;
4476
4477 } else {
4478 if (get_seamless_boot_stream_count(context) == 0)
4479 dc->hwss.prepare_bandwidth(dc, dc->current_state);
4480 dc->link_srv->set_dpms_on(dc->current_state, dpms_pipe_ctx);
4481 }
4482 } else if (dpms_pipe_ctx->stream->link->wa_flags.blank_stream_on_ocs_change &&
4483 stream_update->output_color_space &&
4484 !stream->dpms_off && dc_is_dp_signal(dpms_pipe_ctx->stream->signal)) {
4485 /*
4486 * Workaround for firmware issue in some receivers where they don't pick up
4487 * correct output color space unless DP link is disabled/re-enabled
4488 */
4489 dc->link_srv->set_dpms_on(dc->current_state, dpms_pipe_ctx);
4490 }
4491
4492 if (stream_update->abm_level && pipe_ctx->stream_res.abm) {
4493 bool should_program_abm = true;
4494
4495 // if otg funcs defined check if blanked before programming
4496 if (pipe_ctx->stream_res.tg->funcs->is_blanked)
4497 if (pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg))
4498 should_program_abm = false;
4499
4500 if (should_program_abm) {
4501 if (*stream_update->abm_level == ABM_LEVEL_IMMEDIATE_DISABLE) {
4502 dc->hwss.set_abm_immediate_disable(pipe_ctx);
4503 } else {
4504 pipe_ctx->stream_res.abm->funcs->set_abm_level(
4505 pipe_ctx->stream_res.abm, stream->abm_level);
4506 }
4507 }
4508 }
4509 }
4510 }
4511 }
4512
dc_dmub_should_send_dirty_rect_cmd(struct dc * dc,struct dc_stream_state * stream)4513 static bool dc_dmub_should_send_dirty_rect_cmd(struct dc *dc, struct dc_stream_state *stream)
4514 {
4515 (void)dc;
4516 if ((stream->link->psr_settings.psr_version == DC_PSR_VERSION_SU_1
4517 || stream->link->psr_settings.psr_version == DC_PSR_VERSION_1)
4518 && stream->ctx->dce_version >= DCN_VERSION_3_1)
4519 return true;
4520
4521 if (stream->link->replay_settings.config.replay_supported)
4522 return true;
4523
4524 if (stream->ctx->dce_version >= DCN_VERSION_3_5 && stream->abm_level)
4525 return true;
4526
4527 return false;
4528 }
4529
dc_dmub_update_dirty_rect(struct dc * dc,int surface_count,struct dc_stream_state * stream,const struct dc_surface_update * srf_updates,struct dc_state * context)4530 void dc_dmub_update_dirty_rect(struct dc *dc,
4531 int surface_count,
4532 struct dc_stream_state *stream,
4533 const struct dc_surface_update *srf_updates,
4534 struct dc_state *context)
4535 {
4536 union dmub_rb_cmd cmd;
4537 struct dmub_cmd_update_dirty_rect_data *update_dirty_rect;
4538 int i;
4539 unsigned int j;
4540 unsigned int panel_inst = 0;
4541
4542 if (!dc_dmub_should_send_dirty_rect_cmd(dc, stream))
4543 return;
4544
4545 if (!dc->config.frame_update_cmd_version2 && !dc_get_edp_link_panel_inst(dc, stream->link, &panel_inst))
4546 return;
4547
4548 memset(&cmd, 0x0, sizeof(cmd));
4549 cmd.update_dirty_rect.header.type = DMUB_CMD__UPDATE_DIRTY_RECT;
4550 cmd.update_dirty_rect.header.sub_type = 0;
4551 cmd.update_dirty_rect.header.payload_bytes =
4552 sizeof(cmd.update_dirty_rect) -
4553 sizeof(cmd.update_dirty_rect.header);
4554 update_dirty_rect = &cmd.update_dirty_rect.update_dirty_rect_data;
4555 for (i = 0; i < surface_count; i++) {
4556 struct dc_plane_state *plane_state = srf_updates[i].surface;
4557 const struct dc_flip_addrs *flip_addr = srf_updates[i].flip_addr;
4558
4559 if (!srf_updates[i].surface || !flip_addr)
4560 continue;
4561 /* Do not send in immediate flip mode */
4562 if (srf_updates[i].surface->flip_immediate)
4563 continue;
4564
4565 if (dc->config.frame_update_cmd_version2)
4566 update_dirty_rect->cmd_version = DMUB_CMD_CURSOR_UPDATE_VERSION_2;
4567 else
4568 update_dirty_rect->cmd_version = DMUB_CMD_CURSOR_UPDATE_VERSION_1;
4569
4570 update_dirty_rect->dirty_rect_count = (uint8_t)flip_addr->dirty_rect_count;
4571 memcpy(update_dirty_rect->src_dirty_rects, flip_addr->dirty_rects,
4572 sizeof(flip_addr->dirty_rects));
4573 for (j = 0; j < dc->res_pool->pipe_count; j++) {
4574 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
4575
4576 if (pipe_ctx->stream != stream)
4577 continue;
4578 if (pipe_ctx->plane_state != plane_state)
4579 continue;
4580
4581 update_dirty_rect->panel_inst = (uint8_t)panel_inst;
4582 update_dirty_rect->pipe_idx = (uint8_t)j;
4583 update_dirty_rect->otg_inst = (uint8_t)pipe_ctx->stream_res.tg->inst;
4584 dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
4585 }
4586 }
4587 }
4588
build_dmub_update_dirty_rect(struct dc * dc,int surface_count,struct dc_stream_state * stream,struct dc_surface_update * srf_updates,struct dc_state * context,struct dc_dmub_cmd dc_dmub_cmd[],unsigned int * dmub_cmd_count)4589 static void build_dmub_update_dirty_rect(
4590 struct dc *dc,
4591 int surface_count,
4592 struct dc_stream_state *stream,
4593 struct dc_surface_update *srf_updates,
4594 struct dc_state *context,
4595 struct dc_dmub_cmd dc_dmub_cmd[],
4596 unsigned int *dmub_cmd_count)
4597 {
4598 union dmub_rb_cmd cmd;
4599 struct dmub_cmd_update_dirty_rect_data *update_dirty_rect;
4600 int i;
4601 unsigned int j;
4602 unsigned int panel_inst = 0;
4603
4604 if (!dc_dmub_should_send_dirty_rect_cmd(dc, stream))
4605 return;
4606
4607 if (!dc->config.frame_update_cmd_version2 && !dc_get_edp_link_panel_inst(dc, stream->link, &panel_inst))
4608 return;
4609
4610 memset(&cmd, 0x0, sizeof(cmd));
4611 cmd.update_dirty_rect.header.type = DMUB_CMD__UPDATE_DIRTY_RECT;
4612 cmd.update_dirty_rect.header.sub_type = 0;
4613 cmd.update_dirty_rect.header.payload_bytes =
4614 sizeof(cmd.update_dirty_rect) -
4615 sizeof(cmd.update_dirty_rect.header);
4616 update_dirty_rect = &cmd.update_dirty_rect.update_dirty_rect_data;
4617 for (i = 0; i < surface_count; i++) {
4618 struct dc_plane_state *plane_state = srf_updates[i].surface;
4619 const struct dc_flip_addrs *flip_addr = srf_updates[i].flip_addr;
4620
4621 if (!srf_updates[i].surface || !flip_addr)
4622 continue;
4623 /* Do not send in immediate flip mode */
4624 if (srf_updates[i].surface->flip_immediate)
4625 continue;
4626
4627 if (dc->config.frame_update_cmd_version2)
4628 update_dirty_rect->cmd_version = DMUB_CMD_CURSOR_UPDATE_VERSION_2;
4629 else
4630 update_dirty_rect->cmd_version = DMUB_CMD_CURSOR_UPDATE_VERSION_1;
4631
4632 update_dirty_rect->dirty_rect_count = (uint8_t)flip_addr->dirty_rect_count;
4633 memcpy(update_dirty_rect->src_dirty_rects, flip_addr->dirty_rects,
4634 sizeof(flip_addr->dirty_rects));
4635 for (j = 0; j < dc->res_pool->pipe_count; j++) {
4636 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
4637
4638 if (pipe_ctx->stream != stream)
4639 continue;
4640 if (pipe_ctx->plane_state != plane_state)
4641 continue;
4642 update_dirty_rect->panel_inst = (uint8_t)panel_inst;
4643 update_dirty_rect->pipe_idx = (uint8_t)j;
4644 update_dirty_rect->otg_inst = (uint8_t)pipe_ctx->stream_res.tg->inst;
4645 dc_dmub_cmd[*dmub_cmd_count].dmub_cmd = cmd;
4646 dc_dmub_cmd[*dmub_cmd_count].wait_type = DM_DMUB_WAIT_TYPE_NO_WAIT;
4647 (*dmub_cmd_count)++;
4648 }
4649 }
4650 }
4651
4652 /**
4653 * dc_check_address_only_update - Check if addr_update is the sole flag set
4654 *
4655 * @update_bits: The pipe update bits to check
4656 *
4657 * Determines whether an update contains only an address change with no other
4658 * pending updates.
4659 *
4660 * Return: %true if addr_update is the sole bit set, %false otherwise.
4661 */
dc_check_address_only_update(struct pipe_update_bits update_bits)4662 bool dc_check_address_only_update(struct pipe_update_bits update_bits)
4663 {
4664 struct pipe_update_bits check = update_bits; /* 1. Copy all flags from input */
4665
4666 check.addr_update = 0; /* 2. Zero the addr_update bit in the copy */
4667 return update_bits.addr_update && /* 3. Check addr_update was set in original */
4668 !dc_pipe_update_bits_is_any_set(&check); /* 4. Check no other bits remain in the copy */
4669 }
4670
4671 /**
4672 * build_dmub_cmd_list() - Build an array of DMCUB commands to be sent to DMCUB
4673 *
4674 * @dc: Current DC state
4675 * @srf_updates: Array of surface updates
4676 * @surface_count: Number of surfaces that have an updated
4677 * @stream: Corresponding stream to be updated in the current flip
4678 * @context: New DC state to be programmed
4679 *
4680 * @dc_dmub_cmd: Array of DMCUB commands to be sent to DMCUB
4681 * @dmub_cmd_count: Count indicating the number of DMCUB commands in dc_dmub_cmd array
4682 *
4683 * This function builds an array of DMCUB commands to be sent to DMCUB. This function is required
4684 * to build an array of commands and have them sent while the OTG lock is acquired.
4685 *
4686 * Return: void
4687 */
build_dmub_cmd_list(struct dc * dc,struct dc_surface_update * srf_updates,int surface_count,struct dc_stream_state * stream,struct dc_state * context,struct dc_dmub_cmd dc_dmub_cmd[],unsigned int * dmub_cmd_count)4688 static void build_dmub_cmd_list(struct dc *dc,
4689 struct dc_surface_update *srf_updates,
4690 int surface_count,
4691 struct dc_stream_state *stream,
4692 struct dc_state *context,
4693 struct dc_dmub_cmd dc_dmub_cmd[],
4694 unsigned int *dmub_cmd_count)
4695 {
4696 // Initialize cmd count to 0
4697 *dmub_cmd_count = 0;
4698 build_dmub_update_dirty_rect(dc, surface_count, stream, srf_updates, context, dc_dmub_cmd, dmub_cmd_count);
4699 }
4700
commit_plane_for_stream_offload_fams2_flip(struct dc * dc,struct dc_surface_update * srf_updates,int surface_count,struct dc_stream_state * stream,struct dc_state * context)4701 static void commit_plane_for_stream_offload_fams2_flip(struct dc *dc,
4702 struct dc_surface_update *srf_updates,
4703 int surface_count,
4704 struct dc_stream_state *stream,
4705 struct dc_state *context)
4706 {
4707 int i;
4708 unsigned int j;
4709
4710 /* update dirty rect for PSR */
4711 dc_dmub_update_dirty_rect(dc, surface_count, stream,
4712 srf_updates, context);
4713
4714 /* Perform requested Updates */
4715 for (i = 0; i < surface_count; i++) {
4716 struct dc_plane_state *plane_state = srf_updates[i].surface;
4717
4718 for (j = 0; j < dc->res_pool->pipe_count; j++) {
4719 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
4720
4721 if (!should_update_pipe_for_stream(context, pipe_ctx, stream))
4722 continue;
4723
4724 if (!should_update_pipe_for_plane(context, pipe_ctx, plane_state))
4725 continue;
4726
4727 /* update pipe context for plane */
4728 if (pipe_ctx->plane_state->update_bits.addr_update)
4729 dc->hwss.update_plane_addr(dc, pipe_ctx);
4730 }
4731 }
4732
4733 /* Send commands to DMCUB */
4734 dc_dmub_srv_fams2_passthrough_flip(dc,
4735 context,
4736 stream,
4737 srf_updates,
4738 surface_count);
4739 }
4740
commit_planes_for_stream_fast(struct dc * dc,struct dc_surface_update * srf_updates,int surface_count,struct dc_stream_state * stream,struct dc_stream_update * stream_update,enum dc_update_type update_type,struct dc_state * context)4741 static void commit_planes_for_stream_fast(struct dc *dc,
4742 struct dc_surface_update *srf_updates,
4743 int surface_count,
4744 struct dc_stream_state *stream,
4745 struct dc_stream_update *stream_update,
4746 enum dc_update_type update_type,
4747 struct dc_state *context)
4748 {
4749 int i;
4750 unsigned int j;
4751 struct pipe_ctx *top_pipe_to_program = NULL;
4752 struct dc_stream_status *stream_status = NULL;
4753 bool should_offload_fams2_flip = false;
4754 bool should_lock_all_pipes = (update_type != UPDATE_TYPE_FAST);
4755
4756 if (should_lock_all_pipes)
4757 determine_pipe_unlock_order(dc, context);
4758
4759 if (dc->debug.fams2_config.bits.enable &&
4760 dc->debug.fams2_config.bits.enable_offload_flip &&
4761 dc_state_is_fams2_in_use(dc, context)) {
4762 /* if not offloading to HWFQ, offload to FAMS2 if needed */
4763 should_offload_fams2_flip = true;
4764 for (i = 0; i < surface_count; i++) {
4765 if (srf_updates[i].surface &&
4766 dc_pipe_update_bits_is_any_set(&srf_updates[i].surface->update_bits) &&
4767 !dc_check_address_only_update(srf_updates[i].surface->update_bits)) {
4768 /* more than address update, need to acquire FAMS2 lock */
4769 should_offload_fams2_flip = false;
4770 break;
4771 }
4772 }
4773 if (stream_update) {
4774 /* more than address update, need to acquire FAMS2 lock */
4775 should_offload_fams2_flip = false;
4776 }
4777 }
4778
4779 dc_exit_ips_for_hw_access(dc);
4780
4781 dc_z10_restore(dc);
4782
4783 top_pipe_to_program = resource_get_otg_master_for_stream(
4784 &context->res_ctx,
4785 stream);
4786
4787 if (!top_pipe_to_program)
4788 return;
4789
4790 for (i = 0; i < (int)dc->res_pool->pipe_count; i++) {
4791 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
4792
4793 if (pipe->stream && pipe->plane_state) {
4794 if (!dc->debug.using_dml2)
4795 set_p_state_switch_method(dc, context, pipe);
4796
4797 if (dc->debug.visual_confirm)
4798 dc_update_visual_confirm_color(dc, context, pipe);
4799 }
4800 }
4801
4802 for (i = 0; i < surface_count; i++) {
4803 struct dc_plane_state *plane_state = srf_updates[i].surface;
4804 /*set logical flag for lock/unlock use*/
4805 for (j = 0; j < dc->res_pool->pipe_count; j++) {
4806 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
4807
4808 if (!pipe_ctx->plane_state)
4809 continue;
4810 if (!should_update_pipe_for_plane(context, pipe_ctx, plane_state))
4811 continue;
4812
4813 pipe_ctx->plane_state->triplebuffer_flips = false;
4814 if (update_type == UPDATE_TYPE_FAST &&
4815 dc->hwss.program_triplebuffer != NULL &&
4816 !pipe_ctx->plane_state->flip_immediate && dc->debug.enable_tri_buf) {
4817 /*triple buffer for VUpdate only*/
4818 pipe_ctx->plane_state->triplebuffer_flips = true;
4819 }
4820 }
4821 }
4822
4823 stream_status = dc_state_get_stream_status(context, stream);
4824
4825 if (should_offload_fams2_flip) {
4826 commit_plane_for_stream_offload_fams2_flip(dc,
4827 srf_updates,
4828 surface_count,
4829 stream,
4830 context);
4831 } else if (stream_status) {
4832 build_dmub_cmd_list(dc,
4833 srf_updates,
4834 surface_count,
4835 stream,
4836 context,
4837 context->dc_dmub_cmd,
4838 &(context->dmub_cmd_count));
4839 hwss_build_fast_sequence(dc,
4840 context->dc_dmub_cmd,
4841 context->dmub_cmd_count,
4842 context->block_sequence,
4843 &(context->block_sequence_steps),
4844 top_pipe_to_program,
4845 stream_status,
4846 context);
4847 hwss_execute_sequence(dc,
4848 context->block_sequence,
4849 context->block_sequence_steps);
4850 }
4851
4852 /* Clear update flags so next flip doesn't have redundant programming
4853 * (if there's no stream update, the update flags are not cleared).
4854 * Surface updates are cleared unconditionally at the beginning of each flip,
4855 * so no need to clear here.
4856 */
4857 if (top_pipe_to_program->stream)
4858 stream_update_flags_clear(&top_pipe_to_program->stream->update_flags);
4859 }
4860
commit_planes_for_stream(struct dc * dc,const struct dc_surface_update * srf_updates,int surface_count,struct dc_stream_state * stream,struct dc_stream_update * stream_update,enum dc_update_type update_type,struct dc_state * context)4861 static void commit_planes_for_stream(struct dc *dc,
4862 const struct dc_surface_update *srf_updates,
4863 int surface_count,
4864 struct dc_stream_state *stream,
4865 struct dc_stream_update *stream_update,
4866 enum dc_update_type update_type,
4867 struct dc_state *context)
4868 {
4869 int i;
4870 unsigned int j, pipe_idx;
4871 struct pipe_ctx *top_pipe_to_program = NULL;
4872 bool should_lock_all_pipes = (update_type != UPDATE_TYPE_FAST);
4873 bool subvp_prev_use = false;
4874 bool subvp_curr_use = false;
4875 uint8_t current_stream_mask = 0;
4876
4877 if (should_lock_all_pipes)
4878 determine_pipe_unlock_order(dc, context);
4879 // Once we apply the new subvp context to hardware it won't be in the
4880 // dc->current_state anymore, so we have to cache it before we apply
4881 // the new SubVP context
4882 subvp_prev_use = false;
4883 dc_exit_ips_for_hw_access(dc);
4884
4885 dc_z10_restore(dc);
4886 if (update_type == UPDATE_TYPE_FULL && dc->optimized_required)
4887 hwss_process_outstanding_hw_updates(dc, dc->current_state);
4888
4889 if (update_type != UPDATE_TYPE_FAST && dc->res_pool->funcs->prepare_mcache_programming)
4890 dc->res_pool->funcs->prepare_mcache_programming(dc, context);
4891
4892 for (pipe_idx = 0; pipe_idx < dc->res_pool->pipe_count; pipe_idx++) {
4893 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[pipe_idx];
4894
4895 if (pipe->stream && pipe->plane_state) {
4896 if (!dc->debug.using_dml2)
4897 set_p_state_switch_method(dc, context, pipe);
4898
4899 if (dc->debug.visual_confirm)
4900 dc_update_visual_confirm_color(dc, context, pipe);
4901 }
4902 }
4903
4904 if (update_type == UPDATE_TYPE_FULL) {
4905 dc_allow_idle_optimizations(dc, false);
4906
4907 if (get_seamless_boot_stream_count(context) == 0)
4908 dc->hwss.prepare_bandwidth(dc, context);
4909
4910 if (dc->hwss.update_dsc_pg)
4911 dc->hwss.update_dsc_pg(dc, context, false);
4912
4913 context_clock_trace(dc, context);
4914 }
4915
4916 if (update_type == UPDATE_TYPE_FULL)
4917 hwss_wait_for_outstanding_hw_updates(dc, dc->current_state);
4918
4919 top_pipe_to_program = resource_get_otg_master_for_stream(
4920 &context->res_ctx,
4921 stream);
4922 ASSERT(top_pipe_to_program != NULL);
4923
4924 for (pipe_idx = 0; pipe_idx < dc->res_pool->pipe_count; pipe_idx++) {
4925 struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[pipe_idx];
4926
4927 // Check old context for SubVP
4928 subvp_prev_use |= (dc_state_get_pipe_subvp_type(dc->current_state, old_pipe) == SUBVP_PHANTOM);
4929 if (subvp_prev_use)
4930 break;
4931 }
4932
4933 for (pipe_idx = 0; pipe_idx < dc->res_pool->pipe_count; pipe_idx++) {
4934 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[pipe_idx];
4935
4936 if (dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM) {
4937 subvp_curr_use = true;
4938 break;
4939 }
4940 }
4941
4942 if (stream->test_pattern.type != DP_TEST_PATTERN_VIDEO_MODE) {
4943 struct pipe_ctx *mpcc_pipe;
4944 struct pipe_ctx *odm_pipe;
4945
4946 for (mpcc_pipe = top_pipe_to_program; mpcc_pipe; mpcc_pipe = mpcc_pipe->bottom_pipe)
4947 for (odm_pipe = mpcc_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
4948 odm_pipe->ttu_regs.min_ttu_vblank = MAX_TTU;
4949 }
4950
4951 if ((update_type != UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed)
4952 if (top_pipe_to_program &&
4953 top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) {
4954 if (should_use_dmub_inbox1_lock(dc, stream->link)) {
4955 union dmub_hw_lock_flags hw_locks = { 0 };
4956 struct dmub_hw_lock_inst_flags inst_flags = { 0 };
4957
4958 hw_locks.bits.lock_dig = 1;
4959 inst_flags.dig_inst = (uint8_t)top_pipe_to_program->stream_res.tg->inst;
4960
4961 dmub_hw_lock_mgr_cmd(dc->ctx->dmub_srv,
4962 true,
4963 &hw_locks,
4964 &inst_flags);
4965 } else
4966 top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable(
4967 top_pipe_to_program->stream_res.tg);
4968 }
4969
4970 if (dc->hwss.wait_for_dcc_meta_propagation) {
4971 dc->hwss.wait_for_dcc_meta_propagation(dc, top_pipe_to_program);
4972 }
4973
4974 if (dc->hwseq->funcs.wait_for_pipe_update_if_needed)
4975 dc->hwseq->funcs.wait_for_pipe_update_if_needed(dc, top_pipe_to_program, update_type < UPDATE_TYPE_FULL);
4976
4977 if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) {
4978 if (dc->hwss.subvp_pipe_control_lock)
4979 dc->hwss.subvp_pipe_control_lock(dc, context, true, should_lock_all_pipes, NULL, subvp_prev_use);
4980
4981 if (dc->hwss.dmub_hw_control_lock)
4982 dc->hwss.dmub_hw_control_lock(dc, context, true);
4983
4984 dc->hwss.interdependent_update_lock(dc, context, true);
4985 } else {
4986 if (dc->hwss.subvp_pipe_control_lock)
4987 dc->hwss.subvp_pipe_control_lock(dc, context, true, should_lock_all_pipes, top_pipe_to_program, subvp_prev_use);
4988
4989 if (dc->hwss.dmub_hw_control_lock)
4990 dc->hwss.dmub_hw_control_lock(dc, context, true);
4991
4992 /* Lock the top pipe while updating plane addrs, since freesync requires
4993 * plane addr update event triggers to be synchronized.
4994 * top_pipe_to_program is expected to never be NULL
4995 */
4996 dc->hwss.pipe_control_lock(dc, top_pipe_to_program, true);
4997 }
4998
4999 dc_dmub_update_dirty_rect(dc, surface_count, stream, srf_updates, context);
5000
5001 // Stream updates
5002 if (stream_update)
5003 commit_planes_do_stream_update(dc, stream, stream_update, update_type, context);
5004
5005 if (surface_count == 0) {
5006 /*
5007 * In case of turning off screen, no need to program front end a second time.
5008 * just return after program blank.
5009 */
5010 if (dc->hwss.apply_ctx_for_surface)
5011 dc->hwss.apply_ctx_for_surface(dc, stream, 0, context);
5012 if (dc->hwss.program_front_end_for_ctx)
5013 dc->hwss.program_front_end_for_ctx(dc, context);
5014
5015 if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) {
5016 dc->hwss.interdependent_update_lock(dc, context, false);
5017 } else {
5018 dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false);
5019 }
5020 dc->hwss.post_unlock_program_front_end(dc, context);
5021
5022 if (update_type != UPDATE_TYPE_FAST)
5023 if (dc->hwss.commit_subvp_config)
5024 dc->hwss.commit_subvp_config(dc, context);
5025
5026 /* Since phantom pipe programming is moved to post_unlock_program_front_end,
5027 * move the SubVP lock to after the phantom pipes have been setup
5028 */
5029 if (dc->hwss.subvp_pipe_control_lock)
5030 dc->hwss.subvp_pipe_control_lock(dc, context, false, should_lock_all_pipes,
5031 NULL, subvp_prev_use);
5032
5033 if (dc->hwss.dmub_hw_control_lock)
5034 dc->hwss.dmub_hw_control_lock(dc, context, false);
5035 return;
5036 }
5037
5038 if (update_type != UPDATE_TYPE_FAST) {
5039 for (j = 0; j < dc->res_pool->pipe_count; j++) {
5040 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
5041
5042 if ((dc->debug.visual_confirm == VISUAL_CONFIRM_SUBVP ||
5043 dc->debug.visual_confirm == VISUAL_CONFIRM_MCLK_SWITCH) &&
5044 pipe_ctx->stream && pipe_ctx->plane_state) {
5045 /* Only update visual confirm for SUBVP and Mclk switching here.
5046 * The bar appears on all pipes, so we need to update the bar on all displays,
5047 * so the information doesn't get stale.
5048 */
5049 dc->hwss.update_visual_confirm_color(dc, pipe_ctx,
5050 pipe_ctx->plane_res.hubp->inst);
5051 }
5052 }
5053 }
5054
5055 for (i = 0; i < surface_count; i++) {
5056 struct dc_plane_state *plane_state = srf_updates[i].surface;
5057
5058 /*set logical flag for lock/unlock use*/
5059 for (j = 0; j < dc->res_pool->pipe_count; j++) {
5060 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
5061 if (!pipe_ctx->plane_state)
5062 continue;
5063 if (!should_update_pipe_for_plane(context, pipe_ctx, plane_state))
5064 continue;
5065 pipe_ctx->plane_state->triplebuffer_flips = false;
5066 if (update_type == UPDATE_TYPE_FAST &&
5067 dc->hwss.program_triplebuffer != NULL &&
5068 !pipe_ctx->plane_state->flip_immediate && dc->debug.enable_tri_buf) {
5069 /*triple buffer for VUpdate only*/
5070 pipe_ctx->plane_state->triplebuffer_flips = true;
5071 }
5072 }
5073 if (update_type == UPDATE_TYPE_FULL) {
5074 /* force vsync flip when reconfiguring pipes to prevent underflow */
5075 plane_state->flip_immediate = false;
5076 plane_state->triplebuffer_flips = false;
5077 }
5078 }
5079
5080 // Update Type FULL, Surface updates
5081 for (j = 0; j < dc->res_pool->pipe_count; j++) {
5082 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
5083
5084 if (!pipe_ctx->top_pipe &&
5085 !pipe_ctx->prev_odm_pipe &&
5086 should_update_pipe_for_stream(context, pipe_ctx, stream)) {
5087 struct dc_stream_status *pipe_stream_status = NULL;
5088
5089 if (!pipe_ctx->plane_state)
5090 continue;
5091
5092 /* Full fe update*/
5093 if (update_type == UPDATE_TYPE_FAST)
5094 continue;
5095
5096 pipe_stream_status =
5097 stream_get_status(context, pipe_ctx->stream);
5098
5099 if (dc->hwss.apply_ctx_for_surface && pipe_stream_status)
5100 dc->hwss.apply_ctx_for_surface(
5101 dc, pipe_ctx->stream, pipe_stream_status->plane_count, context);
5102 }
5103 }
5104
5105 for (j = 0; j < dc->res_pool->pipe_count; j++) {
5106 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
5107
5108 if (!pipe_ctx->plane_state)
5109 continue;
5110
5111 /* Full fe update*/
5112 if (update_type == UPDATE_TYPE_FAST)
5113 continue;
5114
5115 ASSERT(!pipe_ctx->plane_state->triplebuffer_flips);
5116 if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) {
5117 /*turn off triple buffer for full update*/
5118 dc->hwss.program_triplebuffer(
5119 dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips);
5120 }
5121 }
5122
5123 if (dc->hwss.program_front_end_for_ctx && update_type != UPDATE_TYPE_FAST) {
5124 dc->hwss.program_front_end_for_ctx(dc, context);
5125
5126 //Pipe busy until some frame and line #
5127 if (dc->hwseq->funcs.set_wait_for_update_needed_for_pipe && update_type == UPDATE_TYPE_FULL) {
5128 for (j = 0; j < dc->res_pool->pipe_count; j++) {
5129 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
5130
5131 dc->hwseq->funcs.set_wait_for_update_needed_for_pipe(dc, pipe_ctx);
5132 }
5133 }
5134
5135 if (dc->debug.validate_dml_output) {
5136 for (pipe_idx = 0; pipe_idx < dc->res_pool->pipe_count; pipe_idx++) {
5137 struct pipe_ctx *cur_pipe = &context->res_ctx.pipe_ctx[pipe_idx];
5138 if (cur_pipe->stream == NULL)
5139 continue;
5140
5141 cur_pipe->plane_res.hubp->funcs->validate_dml_output(
5142 cur_pipe->plane_res.hubp, dc->ctx,
5143 &context->res_ctx.pipe_ctx[pipe_idx].rq_regs,
5144 &context->res_ctx.pipe_ctx[pipe_idx].dlg_regs,
5145 &context->res_ctx.pipe_ctx[pipe_idx].ttu_regs);
5146 }
5147 }
5148 }
5149
5150 // Update Type FAST, Surface updates
5151 if (update_type == UPDATE_TYPE_FAST) {
5152 if (dc->hwss.set_flip_control_gsl)
5153 for (i = 0; i < surface_count; i++) {
5154 struct dc_plane_state *plane_state = srf_updates[i].surface;
5155
5156 for (j = 0; j < dc->res_pool->pipe_count; j++) {
5157 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
5158
5159 if (!should_update_pipe_for_stream(context, pipe_ctx, stream))
5160 continue;
5161
5162 if (!should_update_pipe_for_plane(context, pipe_ctx, plane_state))
5163 continue;
5164
5165 // GSL has to be used for flip immediate
5166 dc->hwss.set_flip_control_gsl(pipe_ctx,
5167 pipe_ctx->plane_state->flip_immediate);
5168 }
5169 }
5170
5171 /* Perform requested Updates */
5172 for (i = 0; i < surface_count; i++) {
5173 struct dc_plane_state *plane_state = srf_updates[i].surface;
5174
5175 for (j = 0; j < dc->res_pool->pipe_count; j++) {
5176 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
5177
5178 if (!should_update_pipe_for_stream(context, pipe_ctx, stream))
5179 continue;
5180
5181 if (!should_update_pipe_for_plane(context, pipe_ctx, plane_state))
5182 continue;
5183
5184 if (srf_updates[i].cm &&
5185 srf_updates[i].cm->flags.bits.lut3d_enable &&
5186 srf_updates[i].cm->flags.bits.lut3d_dma_enable &&
5187 dc->hwss.trigger_3dlut_dma_load)
5188 dc->hwss.trigger_3dlut_dma_load(pipe_ctx);
5189
5190 /*program triple buffer after lock based on flip type*/
5191 if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) {
5192 /*only enable triplebuffer for fast_update*/
5193 dc->hwss.program_triplebuffer(
5194 dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips);
5195 }
5196 if (pipe_ctx->plane_state->update_bits.addr_update)
5197 dc->hwss.update_plane_addr(dc, pipe_ctx);
5198 }
5199 }
5200 }
5201
5202 if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) {
5203 dc->hwss.interdependent_update_lock(dc, context, false);
5204 } else {
5205 dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false);
5206 }
5207
5208 if ((update_type != UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed)
5209 if (top_pipe_to_program &&
5210 top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) {
5211 top_pipe_to_program->stream_res.tg->funcs->wait_for_state(
5212 top_pipe_to_program->stream_res.tg,
5213 CRTC_STATE_VACTIVE);
5214 top_pipe_to_program->stream_res.tg->funcs->wait_for_state(
5215 top_pipe_to_program->stream_res.tg,
5216 CRTC_STATE_VBLANK);
5217 top_pipe_to_program->stream_res.tg->funcs->wait_for_state(
5218 top_pipe_to_program->stream_res.tg,
5219 CRTC_STATE_VACTIVE);
5220
5221 if (should_use_dmub_inbox1_lock(dc, stream->link)) {
5222 union dmub_hw_lock_flags hw_locks = { 0 };
5223 struct dmub_hw_lock_inst_flags inst_flags = { 0 };
5224
5225 hw_locks.bits.lock_dig = 1;
5226 inst_flags.dig_inst = (uint8_t)top_pipe_to_program->stream_res.tg->inst;
5227
5228 dmub_hw_lock_mgr_cmd(dc->ctx->dmub_srv,
5229 false,
5230 &hw_locks,
5231 &inst_flags);
5232 } else
5233 top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_disable(
5234 top_pipe_to_program->stream_res.tg);
5235 }
5236
5237 if (subvp_curr_use) {
5238 /* If enabling subvp or transitioning from subvp->subvp, enable the
5239 * phantom streams before we program front end for the phantom pipes.
5240 */
5241 if (update_type != UPDATE_TYPE_FAST) {
5242 if (dc->hwss.enable_phantom_streams)
5243 dc->hwss.enable_phantom_streams(dc, context);
5244 }
5245 }
5246
5247 if (update_type != UPDATE_TYPE_FAST)
5248 dc->hwss.post_unlock_program_front_end(dc, context);
5249
5250 if (subvp_prev_use && !subvp_curr_use) {
5251 /* If disabling subvp, disable phantom streams after front end
5252 * programming has completed (we turn on phantom OTG in order
5253 * to complete the plane disable for phantom pipes).
5254 */
5255
5256 if (dc->hwss.disable_phantom_streams)
5257 dc->hwss.disable_phantom_streams(dc, context);
5258 }
5259
5260 if (update_type != UPDATE_TYPE_FAST)
5261 if (dc->hwss.commit_subvp_config)
5262 dc->hwss.commit_subvp_config(dc, context);
5263 /* Since phantom pipe programming is moved to post_unlock_program_front_end,
5264 * move the SubVP lock to after the phantom pipes have been setup
5265 */
5266 if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) {
5267 if (dc->hwss.subvp_pipe_control_lock)
5268 dc->hwss.subvp_pipe_control_lock(dc, context, false, should_lock_all_pipes, NULL, subvp_prev_use);
5269 if (dc->hwss.dmub_hw_control_lock)
5270 dc->hwss.dmub_hw_control_lock(dc, context, false);
5271 } else {
5272 if (dc->hwss.subvp_pipe_control_lock)
5273 dc->hwss.subvp_pipe_control_lock(dc, context, false, should_lock_all_pipes, top_pipe_to_program, subvp_prev_use);
5274 if (dc->hwss.dmub_hw_control_lock)
5275 dc->hwss.dmub_hw_control_lock(dc, context, false);
5276 }
5277
5278 // Fire manual trigger only when bottom plane is flipped
5279 for (j = 0; j < dc->res_pool->pipe_count; j++) {
5280 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
5281
5282 if (!pipe_ctx->plane_state)
5283 continue;
5284
5285 if (pipe_ctx->bottom_pipe || pipe_ctx->next_odm_pipe ||
5286 !pipe_ctx->stream || !should_update_pipe_for_stream(context, pipe_ctx, stream) ||
5287 !pipe_ctx->plane_state->update_bits.addr_update ||
5288 pipe_ctx->plane_state->skip_manual_trigger)
5289 continue;
5290
5291 if (dc->hwss.program_cursor_offload_now)
5292 dc->hwss.program_cursor_offload_now(dc, pipe_ctx);
5293 if (pipe_ctx->stream_res.tg->funcs->program_manual_trigger)
5294 pipe_ctx->stream_res.tg->funcs->program_manual_trigger(pipe_ctx->stream_res.tg);
5295 }
5296
5297 current_stream_mask = get_stream_mask(dc, context);
5298 if (current_stream_mask != context->stream_mask) {
5299 context->stream_mask = current_stream_mask;
5300 dc_dmub_srv_notify_stream_mask(dc->ctx->dmub_srv, current_stream_mask);
5301 }
5302 }
5303
5304 /**
5305 * could_mpcc_tree_change_for_active_pipes - Check if an OPP associated with MPCC might change
5306 *
5307 * @dc: Used to get the current state status
5308 * @stream: Target stream, which we want to remove the attached planes
5309 * @srf_updates: Array of surface updates
5310 * @surface_count: Number of surface update
5311 * @is_plane_addition: [in] Fill out with true if it is a plane addition case
5312 *
5313 * DCN32x and newer support a feature named Dynamic ODM which can conflict with
5314 * the MPO if used simultaneously in some specific configurations (e.g.,
5315 * 4k@144). This function checks if the incoming context requires applying a
5316 * transition state with unnecessary pipe splitting and ODM disabled to
5317 * circumvent our hardware limitations to prevent this edge case. If the OPP
5318 * associated with an MPCC might change due to plane additions, this function
5319 * returns true.
5320 *
5321 * Return:
5322 * Return true if OPP and MPCC might change, otherwise, return false.
5323 */
could_mpcc_tree_change_for_active_pipes(struct dc * dc,struct dc_stream_state * stream,struct dc_surface_update * srf_updates,int surface_count,bool * is_plane_addition)5324 static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc,
5325 struct dc_stream_state *stream,
5326 struct dc_surface_update *srf_updates,
5327 int surface_count,
5328 bool *is_plane_addition)
5329 {
5330 (void)srf_updates;
5331
5332 struct dc_stream_status *cur_stream_status = stream_get_status(dc->current_state, stream);
5333 bool force_minimal_pipe_splitting = false;
5334 bool subvp_active = false;
5335 uint32_t i;
5336
5337 *is_plane_addition = false;
5338
5339 if (cur_stream_status &&
5340 dc->current_state->stream_count > 0 &&
5341 dc->debug.pipe_split_policy != MPC_SPLIT_AVOID) {
5342 /* determine if minimal transition is required due to MPC*/
5343 if (surface_count > 0) {
5344 if (cur_stream_status->plane_count > surface_count) {
5345 force_minimal_pipe_splitting = true;
5346 } else if (cur_stream_status->plane_count < surface_count) {
5347 force_minimal_pipe_splitting = true;
5348 *is_plane_addition = true;
5349 }
5350 }
5351 }
5352
5353 if (cur_stream_status &&
5354 dc->current_state->stream_count == 1 &&
5355 dc->debug.enable_single_display_2to1_odm_policy) {
5356 /* determine if minimal transition is required due to dynamic ODM*/
5357 if (surface_count > 0) {
5358 if (cur_stream_status->plane_count > 2 && cur_stream_status->plane_count > surface_count) {
5359 force_minimal_pipe_splitting = true;
5360 } else if (surface_count > 2 && cur_stream_status->plane_count < surface_count) {
5361 force_minimal_pipe_splitting = true;
5362 *is_plane_addition = true;
5363 }
5364 }
5365 }
5366
5367 for (i = 0; i < dc->res_pool->pipe_count; i++) {
5368 struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
5369
5370 if (dc_state_get_pipe_subvp_type(dc->current_state, pipe) != SUBVP_NONE) {
5371 subvp_active = true;
5372 break;
5373 }
5374 }
5375
5376 /* For SubVP when adding or removing planes we need to add a minimal transition
5377 * (even when disabling all planes). Whenever disabling a phantom pipe, we
5378 * must use the minimal transition path to disable the pipe correctly.
5379 *
5380 * We want to use the minimal transition whenever subvp is active, not only if
5381 * a plane is being added / removed from a subvp stream (MPO plane can be added
5382 * to a DRR pipe of SubVP + DRR config, in which case we still want to run through
5383 * a min transition to disable subvp.
5384 */
5385 if (cur_stream_status && subvp_active) {
5386 /* determine if minimal transition is required due to SubVP*/
5387 if (cur_stream_status->plane_count > surface_count) {
5388 force_minimal_pipe_splitting = true;
5389 } else if (cur_stream_status->plane_count < surface_count) {
5390 force_minimal_pipe_splitting = true;
5391 *is_plane_addition = true;
5392 }
5393 }
5394
5395 return force_minimal_pipe_splitting;
5396 }
5397
5398
release_minimal_transition_state(struct dc * dc,struct dc_state * minimal_transition_context,struct dc_state * base_context,struct pipe_split_policy_backup * policy)5399 static void release_minimal_transition_state(struct dc *dc,
5400 struct dc_state *minimal_transition_context,
5401 struct dc_state *base_context,
5402 struct pipe_split_policy_backup *policy)
5403 {
5404 restore_minimal_pipe_split_policy(dc, base_context, policy);
5405 dc_state_release(minimal_transition_context);
5406 }
5407
force_vsync_flip_in_minimal_transition_context(struct dc_state * context)5408 static void force_vsync_flip_in_minimal_transition_context(struct dc_state *context)
5409 {
5410 uint8_t i;
5411 int j;
5412 struct dc_stream_status *stream_status;
5413
5414 for (i = 0; i < context->stream_count; i++) {
5415 stream_status = &context->stream_status[i];
5416
5417 for (j = 0; j < stream_status->plane_count; j++)
5418 stream_status->plane_states[j]->flip_immediate = false;
5419 }
5420 }
5421
create_minimal_transition_state(struct dc * dc,struct dc_state * base_context,struct pipe_split_policy_backup * policy)5422 static struct dc_state *create_minimal_transition_state(struct dc *dc,
5423 struct dc_state *base_context, struct pipe_split_policy_backup *policy)
5424 {
5425 struct dc_state *minimal_transition_context = NULL;
5426
5427 minimal_transition_context = dc_state_create_copy(base_context);
5428 if (!minimal_transition_context)
5429 return NULL;
5430
5431 backup_and_set_minimal_pipe_split_policy(dc, base_context, policy);
5432 /* commit minimal state */
5433 if (dc->res_pool->funcs->validate_bandwidth(dc, minimal_transition_context,
5434 DC_VALIDATE_MODE_AND_PROGRAMMING) == DC_OK) {
5435 /* prevent underflow and corruption when reconfiguring pipes */
5436 force_vsync_flip_in_minimal_transition_context(minimal_transition_context);
5437 } else {
5438 /*
5439 * This should never happen, minimal transition state should
5440 * always be validated first before adding pipe split features.
5441 */
5442 release_minimal_transition_state(dc, minimal_transition_context, base_context, policy);
5443 BREAK_TO_DEBUGGER();
5444 minimal_transition_context = NULL;
5445 }
5446 return minimal_transition_context;
5447 }
5448
is_pipe_topology_transition_seamless_with_intermediate_step(struct dc * dc,struct dc_state * initial_state,struct dc_state * intermediate_state,struct dc_state * final_state)5449 static bool is_pipe_topology_transition_seamless_with_intermediate_step(
5450 struct dc *dc,
5451 struct dc_state *initial_state,
5452 struct dc_state *intermediate_state,
5453 struct dc_state *final_state)
5454 {
5455 return dc->hwss.is_pipe_topology_transition_seamless(dc, initial_state,
5456 intermediate_state) &&
5457 dc->hwss.is_pipe_topology_transition_seamless(dc,
5458 intermediate_state, final_state);
5459 }
5460
swap_and_release_current_context(struct dc * dc,struct dc_state * new_context,struct dc_stream_state * stream)5461 static void swap_and_release_current_context(struct dc *dc,
5462 struct dc_state *new_context, struct dc_stream_state *stream)
5463 {
5464
5465 unsigned int i;
5466 struct dc_state *old = dc->current_state;
5467 struct pipe_ctx *pipe_ctx;
5468
5469 /* Since memory free requires elevated IRQ, an interrupt
5470 * request is generated by mem free. If this happens
5471 * between freeing and reassigning the context, our vsync
5472 * interrupt will call into dc and cause a memory
5473 * corruption. Hence, we first reassign the context,
5474 * then free the old context.
5475 */
5476 dc->current_state = new_context;
5477 dc_state_release(old);
5478
5479 // clear any forced full updates
5480 for (i = 0; i < dc->res_pool->pipe_count; i++) {
5481 pipe_ctx = &new_context->res_ctx.pipe_ctx[i];
5482
5483 if (pipe_ctx->plane_state && pipe_ctx->stream == stream)
5484 pipe_ctx->plane_state->force_full_update = false;
5485 }
5486 }
5487
initialize_empty_surface_updates(struct dc_stream_state * stream,struct dc_surface_update * srf_updates)5488 static int initialize_empty_surface_updates(
5489 struct dc_stream_state *stream,
5490 struct dc_surface_update *srf_updates)
5491 {
5492 struct dc_stream_status *status = dc_stream_get_status(stream);
5493 int i;
5494
5495 if (!status)
5496 return 0;
5497
5498 for (i = 0; i < status->plane_count; i++)
5499 srf_updates[i].surface = status->plane_states[i];
5500
5501 return status->plane_count;
5502 }
5503
commit_minimal_transition_based_on_new_context(struct dc * dc,struct dc_state * new_context,struct dc_stream_state * stream,struct dc_stream_update * stream_update,struct dc_surface_update * srf_updates,int surface_count)5504 static bool commit_minimal_transition_based_on_new_context(struct dc *dc,
5505 struct dc_state *new_context,
5506 struct dc_stream_state *stream,
5507 struct dc_stream_update *stream_update,
5508 struct dc_surface_update *srf_updates,
5509 int surface_count)
5510 {
5511 bool success = false;
5512 struct pipe_split_policy_backup policy;
5513 struct dc_state *intermediate_context =
5514 create_minimal_transition_state(dc, new_context,
5515 &policy);
5516
5517 if (intermediate_context) {
5518 if (is_pipe_topology_transition_seamless_with_intermediate_step(
5519 dc,
5520 dc->current_state,
5521 intermediate_context,
5522 new_context)) {
5523 DC_LOG_DC("commit minimal transition state: base = new state\n");
5524 commit_planes_for_stream(dc, srf_updates,
5525 surface_count, stream, stream_update,
5526 UPDATE_TYPE_FULL, intermediate_context);
5527 swap_and_release_current_context(
5528 dc, intermediate_context, stream);
5529 dc_state_retain(dc->current_state);
5530 success = true;
5531 }
5532 release_minimal_transition_state(
5533 dc, intermediate_context, new_context, &policy);
5534 }
5535 return success;
5536 }
5537
commit_minimal_transition_based_on_current_context(struct dc * dc,struct dc_state * new_context,struct dc_stream_state * stream)5538 static bool commit_minimal_transition_based_on_current_context(struct dc *dc,
5539 struct dc_state *new_context, struct dc_stream_state *stream)
5540 {
5541 bool success = false;
5542 struct pipe_split_policy_backup policy;
5543 struct dc_state *intermediate_context;
5544 struct dc_state *old_current_state = dc->current_state;
5545 struct dc_surface_update srf_updates[MAX_SURFACES] = {0};
5546 int surface_count;
5547
5548 /*
5549 * Both current and new contexts share the same stream and plane state
5550 * pointers. When new context is validated, stream and planes get
5551 * populated with new updates such as new plane addresses. This makes
5552 * the current context no longer valid because stream and planes are
5553 * modified from the original. We backup current stream and plane states
5554 * into scratch space whenever we are populating new context. So we can
5555 * restore the original values back by calling the restore function now.
5556 * This restores back the original stream and plane states associated
5557 * with the current state.
5558 */
5559 restore_planes_and_stream_state(&dc->scratch.current_state, stream);
5560 dc_state_retain(old_current_state);
5561 intermediate_context = create_minimal_transition_state(dc,
5562 old_current_state, &policy);
5563
5564 if (intermediate_context) {
5565 if (is_pipe_topology_transition_seamless_with_intermediate_step(
5566 dc,
5567 dc->current_state,
5568 intermediate_context,
5569 new_context)) {
5570 DC_LOG_DC("commit minimal transition state: base = current state\n");
5571 surface_count = initialize_empty_surface_updates(
5572 stream, srf_updates);
5573 commit_planes_for_stream(dc, srf_updates,
5574 surface_count, stream, NULL,
5575 UPDATE_TYPE_FULL, intermediate_context);
5576 swap_and_release_current_context(
5577 dc, intermediate_context, stream);
5578 dc_state_retain(dc->current_state);
5579 success = true;
5580 }
5581 release_minimal_transition_state(dc, intermediate_context,
5582 old_current_state, &policy);
5583 }
5584 dc_state_release(old_current_state);
5585 /*
5586 * Restore stream and plane states back to the values associated with
5587 * new context.
5588 */
5589 restore_planes_and_stream_state(&dc->scratch.new_state, stream);
5590 return success;
5591 }
5592
5593 /**
5594 * commit_minimal_transition_state_in_dc_update - Commit a minimal state based
5595 * on current or new context
5596 *
5597 * @dc: DC structure, used to get the current state
5598 * @new_context: New context
5599 * @stream: Stream getting the update for the flip
5600 * @srf_updates: Surface updates
5601 * @surface_count: Number of surfaces
5602 *
5603 * The function takes in current state and new state and determine a minimal
5604 * transition state as the intermediate step which could make the transition
5605 * between current and new states seamless. If found, it will commit the minimal
5606 * transition state and update current state to this minimal transition state
5607 * and return true, if not, it will return false.
5608 *
5609 * Return:
5610 * Return True if the minimal transition succeeded, false otherwise
5611 */
commit_minimal_transition_state_in_dc_update(struct dc * dc,struct dc_state * new_context,struct dc_stream_state * stream,struct dc_surface_update * srf_updates,int surface_count)5612 static bool commit_minimal_transition_state_in_dc_update(struct dc *dc,
5613 struct dc_state *new_context,
5614 struct dc_stream_state *stream,
5615 struct dc_surface_update *srf_updates,
5616 int surface_count)
5617 {
5618 bool success = commit_minimal_transition_based_on_new_context(
5619 dc, new_context, stream, NULL,
5620 srf_updates, surface_count);
5621 if (!success)
5622 success = commit_minimal_transition_based_on_current_context(dc,
5623 new_context, stream);
5624 if (!success)
5625 DC_LOG_ERROR("Fail to commit a seamless minimal transition state between current and new states.\nThis pipe topology update is non-seamless!\n");
5626 return success;
5627 }
5628
5629 /**
5630 * commit_minimal_transition_state - Create a transition pipe split state
5631 *
5632 * @dc: Used to get the current state status
5633 * @transition_base_context: New transition state
5634 *
5635 * In some specific configurations, such as pipe split on multi-display with
5636 * MPO and/or Dynamic ODM, removing a plane may cause unsupported pipe
5637 * programming when moving to new planes. To mitigate those types of problems,
5638 * this function adds a transition state that minimizes pipe usage before
5639 * programming the new configuration. When adding a new plane, the current
5640 * state requires the least pipes, so it is applied without splitting. When
5641 * removing a plane, the new state requires the least pipes, so it is applied
5642 * without splitting.
5643 *
5644 * Return:
5645 * Return false if something is wrong in the transition state.
5646 */
commit_minimal_transition_state(struct dc * dc,struct dc_state * transition_base_context)5647 static bool commit_minimal_transition_state(struct dc *dc,
5648 struct dc_state *transition_base_context)
5649 {
5650 struct dc_state *transition_context;
5651 struct pipe_split_policy_backup policy;
5652 enum dc_status ret = DC_ERROR_UNEXPECTED;
5653 unsigned int i, j;
5654 unsigned int pipe_in_use = 0;
5655 bool subvp_in_use = false;
5656 bool odm_in_use = false;
5657
5658 /* check current pipes in use*/
5659 for (i = 0; i < dc->res_pool->pipe_count; i++) {
5660 struct pipe_ctx *pipe = &transition_base_context->res_ctx.pipe_ctx[i];
5661
5662 if (pipe->plane_state)
5663 pipe_in_use++;
5664 }
5665
5666 /* If SubVP is enabled and we are adding or removing planes from any main subvp
5667 * pipe, we must use the minimal transition.
5668 */
5669 for (i = 0; i < dc->res_pool->pipe_count; i++) {
5670 struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
5671
5672 if (pipe->stream && dc_state_get_pipe_subvp_type(dc->current_state, pipe) == SUBVP_PHANTOM) {
5673 subvp_in_use = true;
5674 break;
5675 }
5676 }
5677
5678 /* If ODM is enabled and we are adding or removing planes from any ODM
5679 * pipe, we must use the minimal transition.
5680 */
5681 for (i = 0; i < dc->res_pool->pipe_count; i++) {
5682 struct pipe_ctx *pipe = &transition_base_context->res_ctx.pipe_ctx[i];
5683
5684 if (resource_is_pipe_type(pipe, OTG_MASTER)) {
5685 odm_in_use = resource_get_odm_slice_count(pipe) > 1;
5686 break;
5687 }
5688 }
5689
5690 /* When the OS add a new surface if we have been used all of pipes with odm combine
5691 * and mpc split feature, it need use commit_minimal_transition_state to transition safely.
5692 * After OS exit MPO, it will back to use odm and mpc split with all of pipes, we need
5693 * call it again. Otherwise return true to skip.
5694 *
5695 * Reduce the scenarios to use dc_commit_state_no_check in the stage of flip. Especially
5696 * enter/exit MPO when DCN still have enough resources.
5697 */
5698 if (pipe_in_use != dc->res_pool->pipe_count && !subvp_in_use && !odm_in_use)
5699 return true;
5700
5701 DC_LOG_DC("%s base = %s state, reason = %s\n", __func__,
5702 dc->current_state == transition_base_context ? "current" : "new",
5703 subvp_in_use ? "Subvp In Use" :
5704 odm_in_use ? "ODM in Use" :
5705 dc->debug.pipe_split_policy != MPC_SPLIT_AVOID ? "MPC in Use" :
5706 "Unknown");
5707
5708 dc_state_retain(transition_base_context);
5709 transition_context = create_minimal_transition_state(dc,
5710 transition_base_context, &policy);
5711 if (transition_context) {
5712 ret = dc_commit_state_no_check(dc, transition_context);
5713 release_minimal_transition_state(dc, transition_context, transition_base_context, &policy);
5714 }
5715 dc_state_release(transition_base_context);
5716
5717 if (ret != DC_OK) {
5718 /* this should never happen */
5719 BREAK_TO_DEBUGGER();
5720 return false;
5721 }
5722
5723 /* force full surface update */
5724 for (i = 0; i < dc->current_state->stream_count; i++) {
5725 for (j = 0; j < (unsigned int)dc->current_state->stream_status[i].plane_count; j++) {
5726 dc_pipe_update_bits_set_full(&dc->current_state->stream_status[i].plane_states[j]->update_bits);
5727 }
5728 }
5729
5730 return true;
5731 }
5732
populate_fast_updates(struct dc_fast_update * fast_update,struct dc_surface_update * srf_updates,int surface_count,struct dc_stream_update * stream_update)5733 void populate_fast_updates(struct dc_fast_update *fast_update,
5734 struct dc_surface_update *srf_updates,
5735 int surface_count,
5736 struct dc_stream_update *stream_update)
5737 {
5738 int i = 0;
5739
5740 if (stream_update) {
5741 fast_update[0].out_transfer_func = stream_update->out_transfer_func;
5742 fast_update[0].output_csc_transform = stream_update->output_csc_transform;
5743 fast_update[0].cursor_attributes = stream_update->cursor_attributes;
5744 fast_update[0].cursor_position = stream_update->cursor_position;
5745 fast_update[0].periodic_interrupt = stream_update->periodic_interrupt;
5746 fast_update[0].dither_option = stream_update->dither_option;
5747 fast_update[0].gamut_remap = stream_update->gamut_remap;
5748 fast_update[0].vrr_infopacket = stream_update->vrr_infopacket;
5749 fast_update[0].vsc_infopacket = stream_update->vsc_infopacket;
5750 fast_update[0].vsp_infopacket = stream_update->vsp_infopacket;
5751 fast_update[0].hfvsif_infopacket = stream_update->hfvsif_infopacket;
5752 fast_update[0].vtem_infopacket = stream_update->vtem_infopacket;
5753 fast_update[0].adaptive_sync_infopacket = stream_update->adaptive_sync_infopacket;
5754 fast_update[0].avi_infopacket = stream_update->avi_infopacket;
5755 fast_update[0].hdr_static_metadata = stream_update->hdr_static_metadata;
5756 } else {
5757 fast_update[0].out_transfer_func = NULL;
5758 fast_update[0].output_csc_transform = NULL;
5759 fast_update[0].cursor_attributes = NULL;
5760 fast_update[0].cursor_position = NULL;
5761 fast_update[0].periodic_interrupt = NULL;
5762 fast_update[0].dither_option = NULL;
5763 fast_update[0].gamut_remap = NULL;
5764 fast_update[0].vrr_infopacket = NULL;
5765 fast_update[0].vsc_infopacket = NULL;
5766 fast_update[0].vsp_infopacket = NULL;
5767 fast_update[0].hfvsif_infopacket = NULL;
5768 fast_update[0].vtem_infopacket = NULL;
5769 fast_update[0].adaptive_sync_infopacket = NULL;
5770 fast_update[0].avi_infopacket = NULL;
5771 fast_update[0].hdr_static_metadata = NULL;
5772 }
5773
5774 for (i = 0; i < surface_count; i++) {
5775 fast_update[i].flip_addr = srf_updates[i].flip_addr;
5776 fast_update[i].gamma = srf_updates[i].gamma;
5777 fast_update[i].gamut_remap_matrix = srf_updates[i].gamut_remap_matrix;
5778 fast_update[i].input_csc_color_matrix = srf_updates[i].input_csc_color_matrix;
5779 fast_update[i].coeff_reduction_factor = srf_updates[i].coeff_reduction_factor;
5780 fast_update[i].cursor_csc_color_matrix = srf_updates[i].cursor_csc_color_matrix;
5781 fast_update[i].cm_hist_control = srf_updates[i].cm_hist_control;
5782 }
5783 }
5784
fast_updates_exist(const struct dc_fast_update * fast_update,int surface_count)5785 static bool fast_updates_exist(const struct dc_fast_update *fast_update, int surface_count)
5786 {
5787 int i;
5788
5789 if (fast_update[0].out_transfer_func ||
5790 fast_update[0].output_csc_transform ||
5791 fast_update[0].cursor_attributes ||
5792 fast_update[0].cursor_position ||
5793 fast_update[0].periodic_interrupt ||
5794 fast_update[0].dither_option ||
5795 fast_update[0].gamut_remap ||
5796 fast_update[0].vrr_infopacket ||
5797 fast_update[0].vsc_infopacket ||
5798 fast_update[0].vsp_infopacket ||
5799 fast_update[0].hfvsif_infopacket ||
5800 fast_update[0].vtem_infopacket ||
5801 fast_update[0].adaptive_sync_infopacket ||
5802 fast_update[0].avi_infopacket ||
5803 fast_update[0].hdr_static_metadata)
5804 return true;
5805
5806 for (i = 0; i < surface_count; i++) {
5807 if (fast_update[i].flip_addr ||
5808 fast_update[i].gamma ||
5809 fast_update[i].gamut_remap_matrix ||
5810 fast_update[i].input_csc_color_matrix ||
5811 fast_update[i].cursor_csc_color_matrix ||
5812 fast_update[i].cm_hist_control ||
5813 fast_update[i].coeff_reduction_factor)
5814 return true;
5815 }
5816
5817 return false;
5818 }
5819
fast_nonaddr_updates_exist(struct dc_fast_update * fast_update,int surface_count)5820 bool fast_nonaddr_updates_exist(struct dc_fast_update *fast_update, int surface_count)
5821 {
5822 int i;
5823
5824 if (fast_update[0].out_transfer_func ||
5825 fast_update[0].output_csc_transform ||
5826 fast_update[0].gamut_remap ||
5827 fast_update[0].cursor_attributes ||
5828 fast_update[0].cursor_position ||
5829 fast_update[0].periodic_interrupt ||
5830 fast_update[0].dither_option ||
5831 fast_update[0].vrr_infopacket ||
5832 fast_update[0].vsc_infopacket ||
5833 fast_update[0].vsp_infopacket ||
5834 fast_update[0].hfvsif_infopacket ||
5835 fast_update[0].vtem_infopacket ||
5836 fast_update[0].adaptive_sync_infopacket ||
5837 fast_update[0].avi_infopacket ||
5838 fast_update[0].hdr_static_metadata)
5839 return true;
5840
5841 for (i = 0; i < surface_count; i++) {
5842 if (fast_update[i].input_csc_color_matrix ||
5843 fast_update[i].gamma ||
5844 fast_update[i].gamut_remap_matrix ||
5845 fast_update[i].coeff_reduction_factor ||
5846 fast_update[i].cm_hist_control ||
5847 fast_update[i].cursor_csc_color_matrix)
5848 return true;
5849 }
5850
5851 return false;
5852 }
5853
full_update_required_weak(const struct dc * dc,const struct dc_surface_update * srf_updates,int surface_count,const struct dc_stream_update * stream_update,const struct dc_stream_state * stream)5854 static bool full_update_required_weak(
5855 const struct dc *dc,
5856 const struct dc_surface_update *srf_updates,
5857 int surface_count,
5858 const struct dc_stream_update *stream_update,
5859 const struct dc_stream_state *stream)
5860 {
5861 (void)stream_update;
5862 const struct dc_state *context = dc->current_state;
5863 if (srf_updates)
5864 for (int i = 0; i < surface_count; i++)
5865 if (!is_surface_in_context(context, srf_updates[i].surface))
5866 return true;
5867
5868 if (stream) {
5869 const struct dc_stream_status *stream_status = dc_stream_get_status_const(stream);
5870 if (stream_status == NULL || stream_status->plane_count != surface_count)
5871 return true;
5872 }
5873 if (dc->idle_optimizations_allowed)
5874 return true;
5875
5876 if (dc_can_clear_cursor_limit(dc))
5877 return true;
5878
5879 return false;
5880 }
5881
full_update_required(const struct dc * dc,const struct dc_surface_update * srf_updates,int surface_count,const struct dc_stream_update * stream_update,const struct dc_stream_state * stream)5882 static bool full_update_required(
5883 const struct dc *dc,
5884 const struct dc_surface_update *srf_updates,
5885 int surface_count,
5886 const struct dc_stream_update *stream_update,
5887 const struct dc_stream_state *stream)
5888 {
5889 if (full_update_required_weak(dc, srf_updates, surface_count, stream_update, stream))
5890 return true;
5891
5892 for (int i = 0; i < surface_count; i++) {
5893 if (srf_updates &&
5894 (srf_updates[i].plane_info ||
5895 srf_updates[i].scaling_info ||
5896 (srf_updates[i].hdr_mult.value &&
5897 srf_updates[i].hdr_mult.value != srf_updates->surface->hdr_mult.value) ||
5898 (srf_updates[i].sdr_white_level_nits &&
5899 srf_updates[i].sdr_white_level_nits != srf_updates->surface->sdr_white_level_nits) ||
5900 srf_updates[i].in_transfer_func ||
5901 srf_updates[i].surface->force_full_update ||
5902 (srf_updates[i].flip_addr &&
5903 srf_updates[i].flip_addr->address.tmz_surface != srf_updates[i].surface->address.tmz_surface)))
5904 return true;
5905 }
5906
5907 if (stream_update &&
5908 (((stream_update->src.height != 0 && stream_update->src.width != 0) ||
5909 (stream_update->dst.height != 0 && stream_update->dst.width != 0) ||
5910 stream_update->integer_scaling_update) ||
5911 stream_update->abm_level ||
5912 stream_update->dpms_off ||
5913 stream_update->allow_freesync ||
5914 stream_update->vrr_active_variable ||
5915 stream_update->vrr_active_fixed ||
5916 stream_update->output_color_space ||
5917 stream_update->wb_update ||
5918 stream_update->dsc_config ||
5919 stream_update->mst_bw_update ||
5920 stream_update->func_shaper ||
5921 stream_update->lut3d_func ||
5922 stream_update->pending_test_pattern ||
5923 stream_update->crtc_timing_adjust ||
5924 stream_update->scaler_sharpener_update ||
5925 stream_update->hw_cursor_req))
5926 return true;
5927
5928 return false;
5929 }
5930
fast_update_only(const struct dc * dc,const struct dc_fast_update * fast_update,const struct dc_surface_update * srf_updates,int surface_count,const struct dc_stream_update * stream_update,const struct dc_stream_state * stream)5931 static bool fast_update_only(
5932 const struct dc *dc,
5933 const struct dc_fast_update *fast_update,
5934 const struct dc_surface_update *srf_updates,
5935 int surface_count,
5936 const struct dc_stream_update *stream_update,
5937 const struct dc_stream_state *stream)
5938 {
5939 return fast_updates_exist(fast_update, surface_count)
5940 && !full_update_required(dc, srf_updates, surface_count, stream_update, stream);
5941 }
5942
update_planes_and_stream_v2(struct dc * dc,struct dc_surface_update * srf_updates,int surface_count,struct dc_stream_state * stream,struct dc_stream_update * stream_update)5943 static bool update_planes_and_stream_v2(struct dc *dc,
5944 struct dc_surface_update *srf_updates, int surface_count,
5945 struct dc_stream_state *stream,
5946 struct dc_stream_update *stream_update)
5947 {
5948 struct dc_state *context;
5949 enum dc_update_type update_type;
5950 struct dc_fast_update fast_update[MAX_SURFACES] = {0};
5951
5952 /* In cases where MPO and split or ODM are used transitions can
5953 * cause underflow. Apply stream configuration with minimal pipe
5954 * split first to avoid unsupported transitions for active pipes.
5955 */
5956 bool force_minimal_pipe_splitting = 0;
5957 bool is_plane_addition = 0;
5958 bool is_fast_update_only;
5959
5960 populate_fast_updates(fast_update, srf_updates, surface_count, stream_update);
5961 is_fast_update_only = fast_update_only(dc, fast_update, srf_updates,
5962 surface_count, stream_update, stream);
5963 force_minimal_pipe_splitting = could_mpcc_tree_change_for_active_pipes(
5964 dc,
5965 stream,
5966 srf_updates,
5967 surface_count,
5968 &is_plane_addition);
5969
5970 /* on plane addition, minimal state is the current one */
5971 if (force_minimal_pipe_splitting && is_plane_addition &&
5972 !commit_minimal_transition_state(dc, dc->current_state))
5973 return false;
5974
5975 if (!update_planes_and_stream_state(
5976 dc,
5977 srf_updates,
5978 surface_count,
5979 stream,
5980 stream_update,
5981 &update_type,
5982 &context))
5983 return false;
5984
5985 /* on plane removal, minimal state is the new one */
5986 if (force_minimal_pipe_splitting && !is_plane_addition) {
5987 if (!commit_minimal_transition_state(dc, context)) {
5988 dc_state_release(context);
5989 return false;
5990 }
5991 update_type = UPDATE_TYPE_FULL;
5992 }
5993
5994 if (dc->hwss.is_pipe_topology_transition_seamless &&
5995 !dc->hwss.is_pipe_topology_transition_seamless(
5996 dc, dc->current_state, context))
5997 commit_minimal_transition_state_in_dc_update(dc, context, stream,
5998 srf_updates, surface_count);
5999
6000 if (is_fast_update_only && !dc->check_config.enable_legacy_fast_update) {
6001 commit_planes_for_stream_fast(dc,
6002 srf_updates,
6003 surface_count,
6004 stream,
6005 stream_update,
6006 update_type,
6007 context);
6008 } else {
6009 if (!stream_update &&
6010 dc->hwss.is_pipe_topology_transition_seamless &&
6011 !dc->hwss.is_pipe_topology_transition_seamless(
6012 dc, dc->current_state, context)) {
6013 DC_LOG_ERROR("performing non-seamless pipe topology transition with surface only update!\n");
6014 BREAK_TO_DEBUGGER();
6015 }
6016 commit_planes_for_stream(
6017 dc,
6018 srf_updates,
6019 surface_count,
6020 stream,
6021 stream_update,
6022 update_type,
6023 context);
6024 }
6025 if (dc->current_state != context)
6026 swap_and_release_current_context(dc, context, stream);
6027 return true;
6028 }
6029
commit_planes_and_stream_update_on_current_context(struct dc * dc,struct dc_surface_update * srf_updates,int surface_count,struct dc_stream_state * stream,struct dc_stream_update * stream_update,enum dc_update_type update_type)6030 static void commit_planes_and_stream_update_on_current_context(struct dc *dc,
6031 struct dc_surface_update *srf_updates, int surface_count,
6032 struct dc_stream_state *stream,
6033 struct dc_stream_update *stream_update,
6034 enum dc_update_type update_type)
6035 {
6036 struct dc_fast_update fast_update[MAX_SURFACES] = {0};
6037
6038 ASSERT(update_type < UPDATE_TYPE_FULL);
6039 populate_fast_updates(fast_update, srf_updates, surface_count,
6040 stream_update);
6041 if (fast_update_only(dc, fast_update, srf_updates, surface_count,
6042 stream_update, stream) &&
6043 !dc->check_config.enable_legacy_fast_update)
6044 commit_planes_for_stream_fast(dc,
6045 srf_updates,
6046 surface_count,
6047 stream,
6048 stream_update,
6049 update_type,
6050 dc->current_state);
6051 else
6052 commit_planes_for_stream(
6053 dc,
6054 srf_updates,
6055 surface_count,
6056 stream,
6057 stream_update,
6058 update_type,
6059 dc->current_state);
6060 }
6061
commit_planes_and_stream_update_with_new_context(struct dc * dc,struct dc_surface_update * srf_updates,int surface_count,struct dc_stream_state * stream,struct dc_stream_update * stream_update,enum dc_update_type update_type,struct dc_state * new_context)6062 static void commit_planes_and_stream_update_with_new_context(struct dc *dc,
6063 struct dc_surface_update *srf_updates, int surface_count,
6064 struct dc_stream_state *stream,
6065 struct dc_stream_update *stream_update,
6066 enum dc_update_type update_type,
6067 struct dc_state *new_context)
6068 {
6069 bool skip_new_context = false;
6070 ASSERT(update_type >= UPDATE_TYPE_FULL);
6071 /*
6072 * It is required by the feature design that all pipe topologies
6073 * using extra free pipes for power saving purposes such as
6074 * dynamic ODM or SubVp shall only be enabled when it can be
6075 * transitioned seamlessly to AND from its minimal transition
6076 * state. A minimal transition state is defined as the same dc
6077 * state but with all power saving features disabled. So it uses
6078 * the minimum pipe topology. When we can't seamlessly
6079 * transition from state A to state B, we will insert the
6080 * minimal transition state A' or B' in between so seamless
6081 * transition between A and B can be made possible.
6082 *
6083 * To optimize for the time it takes to execute flips,
6084 * the transition from the minimal state to the final state is
6085 * deferred until a steady state (no more transitions) is reached.
6086 */
6087 if (!dc->hwss.is_pipe_topology_transition_seamless(dc, dc->current_state, new_context)) {
6088 if (!dc->debug.disable_deferred_minimal_transitions) {
6089 dc->check_config.deferred_transition_state = true;
6090 dc->check_config.transition_countdown_to_steady_state =
6091 dc->debug.num_fast_flips_to_steady_state_override ?
6092 dc->debug.num_fast_flips_to_steady_state_override :
6093 NUM_FAST_FLIPS_TO_STEADY_STATE;
6094
6095 if (commit_minimal_transition_based_on_new_context(dc, new_context, stream, stream_update,
6096 srf_updates, surface_count)) {
6097 skip_new_context = true;
6098 dc_state_release(new_context);
6099 new_context = dc->current_state;
6100 } else {
6101 /*
6102 * In this case a new mpo plane is being enabled on pipes that were
6103 * previously in use, and the surface update to the existing plane
6104 * includes an alpha box where the new plane will be, so the update
6105 * from minimal to final cannot be deferred as the alpha box would
6106 * be visible to the user
6107 */
6108 commit_minimal_transition_based_on_current_context(dc, new_context, stream);
6109 }
6110 } else {
6111 commit_minimal_transition_state_in_dc_update(dc, new_context, stream,
6112 srf_updates, surface_count);
6113 }
6114 } else if (dc->check_config.deferred_transition_state) {
6115 /* reset countdown as steady state not reached */
6116 dc->check_config.transition_countdown_to_steady_state =
6117 dc->debug.num_fast_flips_to_steady_state_override ?
6118 dc->debug.num_fast_flips_to_steady_state_override :
6119 NUM_FAST_FLIPS_TO_STEADY_STATE;
6120 }
6121
6122 if (!skip_new_context) {
6123 commit_planes_for_stream(dc, srf_updates, surface_count, stream, stream_update, update_type, new_context);
6124 swap_and_release_current_context(dc, new_context, stream);
6125 }
6126 }
6127
update_planes_and_stream_v3(struct dc * dc,struct dc_surface_update * srf_updates,int surface_count,struct dc_stream_state * stream,struct dc_stream_update * stream_update)6128 static bool update_planes_and_stream_v3(struct dc *dc,
6129 struct dc_surface_update *srf_updates, int surface_count,
6130 struct dc_stream_state *stream,
6131 struct dc_stream_update *stream_update)
6132 {
6133 struct dc_state *new_context;
6134 enum dc_update_type update_type;
6135
6136 /*
6137 * When this function returns true and new_context is not equal to
6138 * current state, the function allocates and validates a new dc state
6139 * and assigns it to new_context. The function expects that the caller
6140 * is responsible to free this memory when new_context is no longer
6141 * used. We swap current with new context and free current instead. So
6142 * new_context's memory will live until the next full update after it is
6143 * replaced by a newer context. Refer to the use of
6144 * swap_and_free_current_context below.
6145 */
6146 if (!update_planes_and_stream_state(dc, srf_updates, surface_count,
6147 stream, stream_update, &update_type,
6148 &new_context))
6149 return false;
6150
6151 if (new_context == dc->current_state) {
6152 commit_planes_and_stream_update_on_current_context(dc,
6153 srf_updates, surface_count, stream,
6154 stream_update, update_type);
6155
6156 if (dc->check_config.transition_countdown_to_steady_state)
6157 dc->check_config.transition_countdown_to_steady_state--;
6158 } else {
6159 commit_planes_and_stream_update_with_new_context(dc,
6160 srf_updates, surface_count, stream,
6161 stream_update, update_type, new_context);
6162 }
6163
6164 return true;
6165 }
6166
clear_update_bits(struct dc_surface_update * srf_updates,int surface_count,struct dc_stream_state * stream)6167 static void clear_update_bits(struct dc_surface_update *srf_updates,
6168 int surface_count, struct dc_stream_state *stream)
6169 {
6170 int i;
6171
6172 if (stream)
6173 stream_update_flags_clear(&stream->update_flags);
6174
6175 for (i = 0; i < surface_count; i++)
6176 if (srf_updates[i].surface)
6177 dc_pipe_update_bits_clear(&srf_updates[i].surface->update_bits);
6178 }
6179
dc_update_scratch_acquire(struct dc * dc)6180 static struct dc_update_scratch_space *dc_update_scratch_acquire(struct dc *dc)
6181 {
6182 unsigned int i;
6183
6184 for (i = 0; i < ARRAY_SIZE(dc->update_scratch_pool); i++) {
6185 if (dc->update_scratch_in_use[i])
6186 continue;
6187
6188 dc->update_scratch_in_use[i] = true;
6189 return dc->update_scratch_pool[i];
6190 }
6191
6192 /* TODO: add recoverable scratch acquisition failure handling. */
6193 ASSERT(false);
6194 return NULL;
6195 }
6196
dc_update_scratch_release(struct dc * dc,struct dc_update_scratch_space * scratch)6197 static void dc_update_scratch_release(struct dc *dc,
6198 struct dc_update_scratch_space *scratch)
6199 {
6200 unsigned int i;
6201
6202 for (i = 0; i < ARRAY_SIZE(dc->update_scratch_pool); i++) {
6203 if (dc->update_scratch_pool[i] == scratch) {
6204 dc->update_scratch_in_use[i] = false;
6205 return;
6206 }
6207 }
6208 }
6209
6210 /**
6211 * dc_update_state - Commit an absolute dc_state_update.
6212 * @dc: DC structure
6213 * @updates: root update object carrying stream, plane, and probe updates
6214 * Return: true on success, false on failure.
6215 */
dc_update_state(struct dc * dc,const struct dc_state_update * updates)6216 bool dc_update_state(struct dc *dc, const struct dc_state_update *updates)
6217 {
6218 struct dc_update_scratch_space *scratch;
6219 bool more = true;
6220
6221 if (!dc || !updates)
6222 return false;
6223
6224 scratch = dc_update_state_init(dc, updates);
6225 if (!scratch)
6226 return false;
6227
6228 while (more) {
6229 if (!dc_update_state_prepare(scratch))
6230 return false;
6231
6232 dc_update_state_execute(scratch);
6233 more = dc_update_state_cleanup(scratch);
6234 }
6235
6236 return true;
6237 }
6238
6239 /**
6240 * dc_update_planes_and_stream - Shim for dc_update_state.
6241 * @dc: DC structure
6242 * @srf_updates: array of surface update descriptors
6243 * @surface_count: number of entries in @srf_updates
6244 * @stream: target stream
6245 * @stream_update: optional stream update
6246 *
6247 * Packs the individual arguments into a dc_state_update and forwards to
6248 * dc_update_state(). Preserved for out-of-tree and incremental callers.
6249 *
6250 * Return: true on success; false on failure.
6251 */
dc_update_planes_and_stream(struct dc * dc,struct dc_surface_update * srf_updates,int surface_count,struct dc_stream_state * stream,struct dc_stream_update * stream_update)6252 bool dc_update_planes_and_stream(struct dc *dc,
6253 struct dc_surface_update *srf_updates, int surface_count,
6254 struct dc_stream_state *stream,
6255 struct dc_stream_update *stream_update)
6256 {
6257 struct dc_state_update updates = {
6258 .stream = stream,
6259 .stream_update = stream_update,
6260 .surface_updates = srf_updates,
6261 .surface_count = surface_count,
6262 };
6263
6264 return dc_update_state(dc, &updates);
6265 }
6266
dc_commit_updates_for_stream(struct dc * dc,struct dc_surface_update * srf_updates,int surface_count,struct dc_stream_state * stream,struct dc_stream_update * stream_update,struct dc_state * state)6267 void dc_commit_updates_for_stream(struct dc *dc,
6268 struct dc_surface_update *srf_updates,
6269 int surface_count,
6270 struct dc_stream_state *stream,
6271 struct dc_stream_update *stream_update,
6272 struct dc_state *state)
6273 {
6274 (void)state;
6275 bool ret = false;
6276
6277 dc_exit_ips_for_hw_access(dc);
6278 /* TODO: Since change commit sequence can have a huge impact,
6279 * we decided to only enable it for DCN3x. However, as soon as
6280 * we get more confident about this change we'll need to enable
6281 * the new sequence for all ASICs.
6282 */
6283 if (dc->ctx->dce_version >= DCN_VERSION_4_01) {
6284 ret = update_planes_and_stream_v3(dc, srf_updates, surface_count,
6285 stream, stream_update);
6286 } else {
6287 ret = update_planes_and_stream_v2(dc, srf_updates, surface_count,
6288 stream, stream_update);
6289 }
6290
6291 if (ret && dc->ctx->dce_version >= DCN_VERSION_3_2)
6292 clear_update_bits(srf_updates, surface_count, stream);
6293 }
6294
dc_get_current_stream_count(struct dc * dc)6295 uint8_t dc_get_current_stream_count(struct dc *dc)
6296 {
6297 return dc->current_state->stream_count;
6298 }
6299
dc_get_stream_at_index(struct dc * dc,uint8_t i)6300 struct dc_stream_state *dc_get_stream_at_index(struct dc *dc, uint8_t i)
6301 {
6302 if (i < dc->current_state->stream_count)
6303 return dc->current_state->streams[i];
6304 return NULL;
6305 }
6306
dc_interrupt_to_irq_source(struct dc * dc,uint32_t src_id,uint32_t ext_id)6307 enum dc_irq_source dc_interrupt_to_irq_source(
6308 struct dc *dc,
6309 uint32_t src_id,
6310 uint32_t ext_id)
6311 {
6312 return dal_irq_service_to_irq_source(dc->res_pool->irqs, src_id, ext_id);
6313 }
6314
6315 /*
6316 * dc_interrupt_set() - Enable/disable an AMD hw interrupt source
6317 */
dc_interrupt_set(struct dc * dc,enum dc_irq_source src,bool enable)6318 bool dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable)
6319 {
6320
6321 if (dc == NULL)
6322 return false;
6323
6324 return dal_irq_service_set(dc->res_pool->irqs, src, enable);
6325 }
6326
dc_interrupt_ack(struct dc * dc,enum dc_irq_source src)6327 void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src)
6328 {
6329 dal_irq_service_ack(dc->res_pool->irqs, src);
6330 }
6331
6332 /* Preserve this tg if a physical link is still lighting a present display */
should_preserve_tg(struct dc * dc,struct timing_generator * tg)6333 static bool should_preserve_tg(struct dc *dc, struct timing_generator *tg)
6334 {
6335 unsigned int i, j;
6336
6337 /* Check if a physical link is lighting this tg */
6338 for (i = 0; i < dc->link_count; i++) {
6339 struct dc_link *link = dc->links[i];
6340 int fe;
6341
6342 if (!link || link->ep_type != DISPLAY_ENDPOINT_PHY ||
6343 !link->link_enc ||
6344 !link->link_enc->funcs->is_dig_enabled ||
6345 !link->link_enc->funcs->is_dig_enabled(link->link_enc) ||
6346 !link->link_enc->funcs->get_dig_frontend)
6347 continue;
6348
6349 /* Get the DIG front-end this link's encoder drives; skip if none */
6350 fe = link->link_enc->funcs->get_dig_frontend(link->link_enc);
6351 if (fe == ENGINE_ID_UNKNOWN)
6352 continue;
6353
6354 /* Find the stream encoder bound to this link's front-end */
6355 for (j = 0; j < dc->res_pool->stream_enc_count; j++) {
6356 struct stream_encoder *se = dc->res_pool->stream_enc[j];
6357
6358 /* Skip unless this stream encoder feeds our front-end and drives this tg */
6359 if (se->id != fe || !se->funcs->dig_source_otg ||
6360 (int)se->funcs->dig_source_otg(se) != tg->inst)
6361 continue;
6362
6363 /* This link drives the OTG: keep a seamless-boot eDP, or
6364 * any external link whose sink is still connected.
6365 */
6366 if (link->connector_signal == SIGNAL_TYPE_EDP)
6367 return true;
6368 if (link->link_enc->funcs->get_hpd_state &&
6369 dc->link_srv->get_hpd_state(link))
6370 return true;
6371 }
6372 }
6373
6374 return false;
6375 }
6376
6377 /*
6378 * GOP/vBIOS may leave an OPTC enabled for a display present at power-on but no
6379 * longer driven (e.g. external DP unplugged at boot). Such a dangling pipe keeps
6380 * DCN out of idle and blocks s0i3. If nothing needs to survive (no committed
6381 * stream or seamless-boot eDP) and no sink is still connected, power down all hw
6382 * blocks.
6383 */
dc_disable_dangling_timing_generators(struct dc * dc)6384 void dc_disable_dangling_timing_generators(struct dc *dc)
6385 {
6386 struct dce_hwseq *hws = dc->hwseq;
6387 bool any_dangling = false;
6388 bool any_preserved = false;
6389 bool any_connected = false;
6390 unsigned int i;
6391
6392 /* No real hw to touch on a virtual/emulated environment */
6393 if (dc->ctx->dce_environment == DCE_ENV_VIRTUAL_HW)
6394 return;
6395
6396 /* Wake hw out of IPS before reading/touching tg state */
6397 dc_exit_ips_for_hw_access(dc);
6398
6399 /* Classify every enabled tg as either to-preserve or dangling */
6400 for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
6401 struct timing_generator *tg = dc->res_pool->timing_generators[i];
6402
6403 if (!tg || !tg->funcs->is_tg_enabled ||
6404 !tg->funcs->is_tg_enabled(tg))
6405 continue;
6406
6407 if (should_preserve_tg(dc, tg))
6408 any_preserved = true;
6409 else
6410 any_dangling = true;
6411 }
6412
6413 /* A physically connected sink (HPD asserted) will be re-lit by a
6414 * subsequent atomic commit. For that case we don't call the global
6415 * power_down().
6416 */
6417 for (i = 0; i < dc->link_count; i++) {
6418 struct dc_link *link = dc->links[i];
6419
6420 if (link && link->ep_type == DISPLAY_ENDPOINT_PHY &&
6421 link->link_enc && link->link_enc->funcs &&
6422 link->link_enc->funcs->get_hpd_state &&
6423 dc->link_srv->get_hpd_state(link)) {
6424 any_connected = true;
6425 break;
6426 }
6427 }
6428
6429 if (!any_dangling)
6430 return;
6431
6432 if (!any_preserved && !any_connected && hws && hws->funcs.power_down) {
6433 /* Truly headless / all sinks unplugged: nothing to preserve */
6434 DC_LOG_DC("%s: powering down dangling hw blocks to allow idle\n",
6435 __func__);
6436 hws->funcs.power_down(dc);
6437 return;
6438 }
6439 }
6440
6441 /*
6442 * dc_get_flip_pending_on_otg() - Check if a GRPH_FLIP is still pending on OTG
6443 *
6444 * @dc: display core context @otg_inst: OTG instance to query
6445 *
6446 * Reads the HUBP flip-pending status for the pipe(s) bound to @otg_inst,
6447 * returning true if any of them has not yet latched its programmed surface
6448 * address.
6449 *
6450 * Unlike dc_plane_get_status(), this does not take or mutate a dc_plane_state,
6451 * so it is safe to call from interrupt context without racing a concurrent
6452 * commit that may be updating plane state.
6453 *
6454 * Return: true if a flip is still pending on the OTG, false otherwise.
6455 */
dc_get_flip_pending_on_otg(struct dc * dc,int otg_inst)6456 bool dc_get_flip_pending_on_otg(struct dc *dc, int otg_inst)
6457 {
6458 bool flip_pending = false;
6459 unsigned int i;
6460
6461 if (!dc || !dc->current_state)
6462 return false;
6463
6464 dc_exit_ips_for_hw_access(dc);
6465
6466 for (i = 0; i < dc->res_pool->pipe_count; i++) {
6467 struct pipe_ctx *pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
6468 struct hubp *hubp = pipe_ctx->plane_res.hubp;
6469
6470 if (!pipe_ctx->plane_state || !pipe_ctx->stream_res.tg)
6471 continue;
6472
6473 if (pipe_ctx->stream_res.tg->inst != otg_inst)
6474 continue;
6475
6476 if (hubp && hubp->funcs->hubp_is_flip_pending &&
6477 hubp->funcs->hubp_is_flip_pending(hubp)) {
6478 flip_pending = true;
6479 break;
6480 }
6481 }
6482
6483 return flip_pending;
6484 }
6485
dc_power_down_on_boot(struct dc * dc)6486 void dc_power_down_on_boot(struct dc *dc)
6487 {
6488 if (dc->ctx->dce_environment != DCE_ENV_VIRTUAL_HW &&
6489 dc->hwss.power_down_on_boot) {
6490 if (dc->current_state->stream_count > 0)
6491 return;
6492
6493 if (dc->caps.ips_support)
6494 dc_exit_ips_for_hw_access(dc);
6495 dc->hwss.power_down_on_boot(dc);
6496
6497 if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->notify_cstate_disable)
6498 dc->clk_mgr->funcs->notify_cstate_disable(dc->clk_mgr, false);
6499 }
6500 }
6501
dc_set_power_state(struct dc * dc,enum dc_acpi_cm_power_state power_state)6502 void dc_set_power_state(struct dc *dc, enum dc_acpi_cm_power_state power_state)
6503 {
6504 if (!dc->current_state)
6505 return;
6506
6507 dc_exit_ips_for_hw_access(dc);
6508
6509 switch (power_state) {
6510 case DC_ACPI_CM_POWER_STATE_D0:
6511 dc_state_construct(dc, dc->current_state);
6512
6513 dc_z10_restore(dc);
6514
6515 dc_dmub_srv_notify_fw_dc_power_state(dc->ctx->dmub_srv, power_state);
6516
6517 dc->hwss.init_hw(dc);
6518
6519 if (dc->hwss.init_sys_ctx != NULL &&
6520 dc->vm_pa_config.valid) {
6521 dc->hwss.init_sys_ctx(dc->hwseq, dc, &dc->vm_pa_config);
6522 }
6523 break;
6524 case DC_ACPI_CM_POWER_STATE_D3:
6525 if (dc->caps.ips_support)
6526 dc_dmub_srv_notify_fw_dc_power_state(dc->ctx->dmub_srv, DC_ACPI_CM_POWER_STATE_D3);
6527
6528 if (dc->caps.ips_v2_support) {
6529 if (dc->clk_mgr->funcs->set_low_power_state)
6530 dc->clk_mgr->funcs->set_low_power_state(dc->clk_mgr);
6531 }
6532 break;
6533 default:
6534 ASSERT(dc->current_state->stream_count == 0);
6535 dc_dmub_srv_notify_fw_dc_power_state(dc->ctx->dmub_srv, power_state);
6536
6537 dc_state_destruct(dc->current_state);
6538
6539 break;
6540 }
6541 }
6542
dc_resume(struct dc * dc)6543 void dc_resume(struct dc *dc)
6544 {
6545 uint32_t i;
6546
6547 for (i = 0; i < dc->link_count; i++)
6548 dc->link_srv->resume(dc->links[i]);
6549 }
6550
dc_is_dmcu_initialized(struct dc * dc)6551 bool dc_is_dmcu_initialized(struct dc *dc)
6552 {
6553 struct dmcu *dmcu = dc->res_pool->dmcu;
6554
6555 if (dmcu)
6556 return dmcu->funcs->is_dmcu_initialized(dmcu);
6557 return false;
6558 }
6559
dc_set_clock(struct dc * dc,enum dc_clock_type clock_type,uint32_t clk_khz,uint32_t stepping)6560 enum dc_status dc_set_clock(struct dc *dc, enum dc_clock_type clock_type, uint32_t clk_khz, uint32_t stepping)
6561 {
6562 if (dc->hwss.set_clock)
6563 return dc->hwss.set_clock(dc, clock_type, clk_khz, stepping);
6564 return DC_ERROR_UNEXPECTED;
6565 }
dc_get_clock(struct dc * dc,enum dc_clock_type clock_type,struct dc_clock_config * clock_cfg)6566 void dc_get_clock(struct dc *dc, enum dc_clock_type clock_type, struct dc_clock_config *clock_cfg)
6567 {
6568 if (dc->hwss.get_clock)
6569 dc->hwss.get_clock(dc, clock_type, clock_cfg);
6570 }
6571
6572 /* enable/disable eDP PSR without specify stream for eDP */
dc_set_psr_allow_active(struct dc * dc,bool enable)6573 bool dc_set_psr_allow_active(struct dc *dc, bool enable)
6574 {
6575 int i;
6576 bool allow_active;
6577
6578 for (i = 0; i < dc->current_state->stream_count ; i++) {
6579 struct dc_link *link;
6580 struct dc_stream_state *stream = dc->current_state->streams[i];
6581
6582 link = stream->link;
6583 if (!link)
6584 continue;
6585
6586 if (link->psr_settings.psr_feature_enabled) {
6587 if (enable && !link->psr_settings.psr_allow_active) {
6588 allow_active = true;
6589 if (!dc_link_set_psr_allow_active(link, &allow_active, false, false, NULL))
6590 return false;
6591 } else if (!enable && link->psr_settings.psr_allow_active) {
6592 allow_active = false;
6593 if (!dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL))
6594 return false;
6595 }
6596 }
6597 }
6598
6599 return true;
6600 }
6601
6602 /* enable/disable eDP Replay without specify stream for eDP */
dc_set_replay_allow_active(struct dc * dc,bool active)6603 bool dc_set_replay_allow_active(struct dc *dc, bool active)
6604 {
6605 int i;
6606 bool allow_active;
6607
6608 for (i = 0; i < dc->current_state->stream_count; i++) {
6609 struct dc_link *link;
6610 struct dc_stream_state *stream = dc->current_state->streams[i];
6611
6612 link = stream->link;
6613 if (!link)
6614 continue;
6615
6616 if (link->replay_settings.replay_feature_enabled) {
6617 if (active && !link->replay_settings.replay_allow_active) {
6618 allow_active = true;
6619 if (!dc_link_set_replay_allow_active(link, &allow_active,
6620 false, false, NULL))
6621 return false;
6622 } else if (!active && link->replay_settings.replay_allow_active) {
6623 allow_active = false;
6624 if (!dc_link_set_replay_allow_active(link, &allow_active,
6625 true, false, NULL))
6626 return false;
6627 }
6628 }
6629 }
6630
6631 return true;
6632 }
6633
6634 /* set IPS disable state */
dc_set_ips_disable(struct dc * dc,unsigned int disable_ips)6635 bool dc_set_ips_disable(struct dc *dc, unsigned int disable_ips)
6636 {
6637 dc_exit_ips_for_hw_access(dc);
6638
6639 dc->config.disable_ips = disable_ips;
6640
6641 return true;
6642 }
6643
dc_allow_idle_optimizations_internal(struct dc * dc,bool allow,char const * caller_name)6644 void dc_allow_idle_optimizations_internal(struct dc *dc, bool allow, char const *caller_name)
6645 {
6646 int idle_fclk_khz = 0, idle_dramclk_khz = 0;
6647 unsigned int i = 0;
6648 enum mall_stream_type subvp_pipe_type[MAX_PIPES] = {0};
6649 struct pipe_ctx *pipe = NULL;
6650 struct dc_state *context = dc->current_state;
6651
6652 if (dc->debug.disable_idle_power_optimizations) {
6653 DC_LOG_DEBUG("%s: disabled\n", __func__);
6654 return;
6655 }
6656
6657 if (allow != dc->idle_optimizations_allowed)
6658 DC_LOG_IPS("%s: allow_idle old=%d new=%d (caller=%s)\n", __func__,
6659 dc->idle_optimizations_allowed, allow, caller_name);
6660
6661 if (dc->caps.ips_support && (dc->config.disable_ips == DMUB_IPS_DISABLE_ALL))
6662 return;
6663
6664 if (dc->clk_mgr != NULL && dc->clk_mgr->funcs->is_smu_present)
6665 if (!dc->clk_mgr->funcs->is_smu_present(dc->clk_mgr))
6666 return;
6667
6668 if (allow == dc->idle_optimizations_allowed)
6669 return;
6670
6671 if (dc->hwss.apply_idle_power_optimizations && dc->clk_mgr != NULL &&
6672 dc->hwss.apply_idle_power_optimizations(dc, allow)) {
6673 dc->idle_optimizations_allowed = allow;
6674 DC_LOG_DEBUG("%s: %s\n", __func__, allow ? "enabled" : "disabled");
6675 }
6676
6677 // log idle clocks and sub vp pipe types at idle optimization time
6678 if (dc->clk_mgr != NULL && dc->clk_mgr->funcs->get_hard_min_fclk)
6679 idle_fclk_khz = dc->clk_mgr->funcs->get_hard_min_fclk(dc->clk_mgr);
6680
6681 if (dc->clk_mgr != NULL && dc->clk_mgr->funcs->get_hard_min_memclk)
6682 idle_dramclk_khz = dc->clk_mgr->funcs->get_hard_min_memclk(dc->clk_mgr);
6683
6684 if (dc->res_pool && context) {
6685 for (i = 0; i < dc->res_pool->pipe_count; i++) {
6686 pipe = &context->res_ctx.pipe_ctx[i];
6687 subvp_pipe_type[i] = dc_state_get_pipe_subvp_type(context, pipe);
6688 }
6689 }
6690 if (!dc->caps.is_apu)
6691 DC_LOG_DC("%s: allow_idle=%d\n HardMinUClk_Khz=%d HardMinDramclk_Khz=%d\n Pipe_0=%d Pipe_1=%d Pipe_2=%d Pipe_3=%d Pipe_4=%d Pipe_5=%d (caller=%s)\n",
6692 __func__, allow, idle_fclk_khz, idle_dramclk_khz, subvp_pipe_type[0], subvp_pipe_type[1], subvp_pipe_type[2],
6693 subvp_pipe_type[3], subvp_pipe_type[4], subvp_pipe_type[5], caller_name);
6694
6695 }
6696
dc_exit_ips_for_hw_access_internal(struct dc * dc,const char * caller_name)6697 void dc_exit_ips_for_hw_access_internal(struct dc *dc, const char *caller_name)
6698 {
6699 if (dc->caps.ips_support)
6700 dc_allow_idle_optimizations_internal(dc, false, caller_name);
6701 }
6702
dc_dmub_is_ips_idle_state(struct dc * dc)6703 bool dc_dmub_is_ips_idle_state(struct dc *dc)
6704 {
6705 if (dc->debug.disable_idle_power_optimizations)
6706 return false;
6707
6708 if (!dc->caps.ips_support || (dc->config.disable_ips == DMUB_IPS_DISABLE_ALL))
6709 return false;
6710
6711 if (!dc->ctx->dmub_srv)
6712 return false;
6713
6714 return dc->ctx->dmub_srv->idle_allowed;
6715 }
6716
6717 /* set min and max memory clock to lowest and highest DPM level, respectively */
dc_unlock_memory_clock_frequency(struct dc * dc)6718 void dc_unlock_memory_clock_frequency(struct dc *dc)
6719 {
6720 if (dc->clk_mgr->funcs->set_hard_min_memclk)
6721 dc->clk_mgr->funcs->set_hard_min_memclk(dc->clk_mgr, false);
6722
6723 if (dc->clk_mgr->funcs->set_hard_max_memclk)
6724 dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr);
6725 }
6726
6727 /* set min memory clock to the min required for current mode, max to maxDPM */
dc_lock_memory_clock_frequency(struct dc * dc)6728 void dc_lock_memory_clock_frequency(struct dc *dc)
6729 {
6730 if (dc->clk_mgr->funcs->get_memclk_states_from_smu)
6731 dc->clk_mgr->funcs->get_memclk_states_from_smu(dc->clk_mgr);
6732
6733 if (dc->clk_mgr->funcs->set_hard_min_memclk)
6734 dc->clk_mgr->funcs->set_hard_min_memclk(dc->clk_mgr, true);
6735
6736 if (dc->clk_mgr->funcs->set_hard_max_memclk)
6737 dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr);
6738 }
6739
blank_and_force_memclk(struct dc * dc,bool apply,unsigned int memclk_mhz)6740 static void blank_and_force_memclk(struct dc *dc, bool apply, unsigned int memclk_mhz)
6741 {
6742 (void)apply;
6743 struct dc_state *context = dc->current_state;
6744 struct hubp *hubp;
6745 struct pipe_ctx *pipe;
6746 unsigned int i;
6747
6748 for (i = 0; i < dc->res_pool->pipe_count; i++) {
6749 pipe = &context->res_ctx.pipe_ctx[i];
6750
6751 if (pipe->stream != NULL) {
6752 dc->hwss.disable_pixel_data(dc, pipe, true);
6753
6754 // wait for double buffer
6755 pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, CRTC_STATE_VACTIVE);
6756 pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, CRTC_STATE_VBLANK);
6757 pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg, CRTC_STATE_VACTIVE);
6758
6759 hubp = pipe->plane_res.hubp;
6760 hubp->funcs->set_blank_regs(hubp, true);
6761 }
6762 }
6763 if (dc->clk_mgr->funcs->set_max_memclk)
6764 dc->clk_mgr->funcs->set_max_memclk(dc->clk_mgr, memclk_mhz);
6765 if (dc->clk_mgr->funcs->set_min_memclk)
6766 dc->clk_mgr->funcs->set_min_memclk(dc->clk_mgr, memclk_mhz);
6767
6768 for (i = 0; i < dc->res_pool->pipe_count; i++) {
6769 pipe = &context->res_ctx.pipe_ctx[i];
6770
6771 if (pipe->stream != NULL) {
6772 dc->hwss.disable_pixel_data(dc, pipe, false);
6773
6774 hubp = pipe->plane_res.hubp;
6775 hubp->funcs->set_blank_regs(hubp, false);
6776 }
6777 }
6778 }
6779
6780
6781 /**
6782 * dc_enable_dcmode_clk_limit() - lower clocks in dc (battery) mode
6783 * @dc: pointer to dc of the dm calling this
6784 * @enable: True = transition to DC mode, false = transition back to AC mode
6785 *
6786 * Some SoCs define additional clock limits when in DC mode, DM should
6787 * invoke this function when the platform undergoes a power source transition
6788 * so DC can apply/unapply the limit. This interface may be disruptive to
6789 * the onscreen content.
6790 *
6791 * Context: Triggered by OS through DM interface, or manually by escape calls.
6792 * Need to hold a dclock when doing so.
6793 *
6794 * Return: none (void function)
6795 *
6796 */
dc_enable_dcmode_clk_limit(struct dc * dc,bool enable)6797 void dc_enable_dcmode_clk_limit(struct dc *dc, bool enable)
6798 {
6799 unsigned int softMax = 0, maxDPM = 0, funcMin = 0, i;
6800 bool p_state_change_support;
6801
6802 if (!dc->config.dc_mode_clk_limit_support)
6803 return;
6804
6805 softMax = dc->clk_mgr->bw_params->dc_mode_softmax_memclk;
6806 for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries; i++) {
6807 if (dc->clk_mgr->bw_params->clk_table.entries[i].memclk_mhz > maxDPM)
6808 maxDPM = dc->clk_mgr->bw_params->clk_table.entries[i].memclk_mhz;
6809 }
6810 funcMin = (dc->clk_mgr->clks.dramclk_khz + 999) / 1000;
6811 p_state_change_support = dc->clk_mgr->clks.p_state_change_support;
6812
6813 if (enable && !dc->clk_mgr->dc_mode_softmax_enabled) {
6814 if (p_state_change_support) {
6815 if (funcMin <= softMax && dc->clk_mgr->funcs->set_max_memclk)
6816 dc->clk_mgr->funcs->set_max_memclk(dc->clk_mgr, softMax);
6817 // else: No-Op
6818 } else {
6819 if (funcMin <= softMax)
6820 blank_and_force_memclk(dc, true, softMax);
6821 // else: No-Op
6822 }
6823 } else if (!enable && dc->clk_mgr->dc_mode_softmax_enabled) {
6824 if (p_state_change_support) {
6825 if (funcMin <= softMax && dc->clk_mgr->funcs->set_max_memclk)
6826 dc->clk_mgr->funcs->set_max_memclk(dc->clk_mgr, maxDPM);
6827 // else: No-Op
6828 } else {
6829 if (funcMin <= softMax)
6830 blank_and_force_memclk(dc, true, maxDPM);
6831 // else: No-Op
6832 }
6833 }
6834 dc->clk_mgr->dc_mode_softmax_enabled = enable;
6835 }
dc_is_plane_eligible_for_idle_optimizations(struct dc * dc,unsigned int pitch,unsigned int height,enum surface_pixel_format format,struct dc_cursor_attributes * cursor_attr)6836 bool dc_is_plane_eligible_for_idle_optimizations(struct dc *dc,
6837 unsigned int pitch,
6838 unsigned int height,
6839 enum surface_pixel_format format,
6840 struct dc_cursor_attributes *cursor_attr)
6841 {
6842 if (dc->hwss.does_plane_fit_in_mall && dc->hwss.does_plane_fit_in_mall(dc, pitch, height, format, cursor_attr))
6843 return true;
6844 return false;
6845 }
6846
6847 /* cleanup on driver unload */
dc_hardware_release(struct dc * dc)6848 void dc_hardware_release(struct dc *dc)
6849 {
6850 dc_mclk_switch_using_fw_based_vblank_stretch_shut_down(dc);
6851
6852 if (dc->hwss.hardware_release)
6853 dc->hwss.hardware_release(dc);
6854 }
6855
dc_mclk_switch_using_fw_based_vblank_stretch_shut_down(struct dc * dc)6856 void dc_mclk_switch_using_fw_based_vblank_stretch_shut_down(struct dc *dc)
6857 {
6858 if (dc->current_state)
6859 dc->current_state->bw_ctx.bw.dcn.clk.fw_based_mclk_switching_shut_down = true;
6860 }
6861
6862 /**
6863 * dc_is_dmub_outbox_supported - Check if DMUB firmware support outbox notification
6864 *
6865 * @dc: [in] dc structure
6866 *
6867 * Checks whether DMUB FW supports outbox notifications, if supported DM
6868 * should register outbox interrupt prior to actually enabling interrupts
6869 * via dc_enable_dmub_outbox
6870 *
6871 * Return:
6872 * True if DMUB FW supports outbox notifications, False otherwise
6873 */
dc_is_dmub_outbox_supported(struct dc * dc)6874 bool dc_is_dmub_outbox_supported(struct dc *dc)
6875 {
6876 if (!dc->caps.dmcub_support)
6877 return false;
6878
6879 switch (dc->ctx->asic_id.chip_family) {
6880
6881 case FAMILY_YELLOW_CARP:
6882 /* DCN31 B0 USB4 DPIA needs dmub notifications for interrupts */
6883 if (dc->ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0 &&
6884 !dc->debug.dpia_debug.bits.disable_dpia)
6885 return true;
6886 break;
6887
6888 case AMDGPU_FAMILY_GC_11_0_1:
6889 case AMDGPU_FAMILY_GC_11_5_0:
6890 case AMDGPU_FAMILY_GC_11_5_4:
6891 if (!dc->debug.dpia_debug.bits.disable_dpia)
6892 return true;
6893 break;
6894
6895 default:
6896 break;
6897 }
6898
6899 /* dmub aux needs dmub notifications to be enabled */
6900 return dc->debug.enable_dmub_aux_for_legacy_ddc;
6901
6902 }
6903
6904 /**
6905 * dc_enable_dmub_notifications - Check if dmub fw supports outbox
6906 *
6907 * @dc: [in] dc structure
6908 *
6909 * Calls dc_is_dmub_outbox_supported to check if dmub fw supports outbox
6910 * notifications. All DMs shall switch to dc_is_dmub_outbox_supported. This
6911 * API shall be removed after switching.
6912 *
6913 * Return:
6914 * True if DMUB FW supports outbox notifications, False otherwise
6915 */
dc_enable_dmub_notifications(struct dc * dc)6916 bool dc_enable_dmub_notifications(struct dc *dc)
6917 {
6918 return dc_is_dmub_outbox_supported(dc);
6919 }
6920
6921 /**
6922 * dc_enable_dmub_outbox - Enables DMUB unsolicited notification
6923 *
6924 * @dc: [in] dc structure
6925 *
6926 * Enables DMUB unsolicited notifications to x86 via outbox.
6927 */
dc_enable_dmub_outbox(struct dc * dc)6928 void dc_enable_dmub_outbox(struct dc *dc)
6929 {
6930 struct dc_context *dc_ctx = dc->ctx;
6931
6932 dmub_enable_outbox_notification(dc_ctx->dmub_srv);
6933 DC_LOG_DC("%s: dmub outbox notifications enabled\n", __func__);
6934 }
6935
6936 /**
6937 * dc_process_dmub_aux_transfer_async - Submits aux command to dmub via inbox message
6938 * Sets port index appropriately for legacy DDC
6939 * @dc: dc structure
6940 * @link_index: link index
6941 * @payload: aux payload
6942 *
6943 * Returns: True if successful, False if failure
6944 */
dc_process_dmub_aux_transfer_async(struct dc * dc,uint32_t link_index,struct aux_payload * payload)6945 bool dc_process_dmub_aux_transfer_async(struct dc *dc,
6946 uint32_t link_index,
6947 struct aux_payload *payload)
6948 {
6949 uint8_t action;
6950 union dmub_rb_cmd cmd = {0};
6951
6952 if (link_index >= dc->link_count || !dc->links[link_index])
6953 return false;
6954
6955 if (payload->length > sizeof(cmd.dp_aux_access.aux_control.dpaux.data))
6956 return false;
6957
6958 cmd.dp_aux_access.header.type = DMUB_CMD__DP_AUX_ACCESS;
6959 cmd.dp_aux_access.header.payload_bytes = 0;
6960 /* For dpia, ddc_pin is set to NULL */
6961 if (!dc->links[link_index]->ddc->ddc_pin)
6962 cmd.dp_aux_access.aux_control.type = AUX_CHANNEL_DPIA;
6963 else
6964 cmd.dp_aux_access.aux_control.type = AUX_CHANNEL_LEGACY_DDC;
6965
6966 cmd.dp_aux_access.aux_control.instance = (uint8_t)dc->links[link_index]->ddc_hw_inst;
6967 cmd.dp_aux_access.aux_control.sw_crc_enabled = 0;
6968 cmd.dp_aux_access.aux_control.timeout = 0;
6969 cmd.dp_aux_access.aux_control.dpaux.address = payload->address;
6970 cmd.dp_aux_access.aux_control.dpaux.is_i2c_over_aux = payload->i2c_over_aux;
6971 cmd.dp_aux_access.aux_control.dpaux.length = (uint8_t)payload->length;
6972
6973 /* set aux action */
6974 if (payload->i2c_over_aux) {
6975 if (payload->write) {
6976 if (payload->mot)
6977 action = DP_AUX_REQ_ACTION_I2C_WRITE_MOT;
6978 else
6979 action = DP_AUX_REQ_ACTION_I2C_WRITE;
6980 } else {
6981 if (payload->mot)
6982 action = DP_AUX_REQ_ACTION_I2C_READ_MOT;
6983 else
6984 action = DP_AUX_REQ_ACTION_I2C_READ;
6985 }
6986 } else {
6987 if (payload->write)
6988 action = DP_AUX_REQ_ACTION_DPCD_WRITE;
6989 else
6990 action = DP_AUX_REQ_ACTION_DPCD_READ;
6991 }
6992
6993 cmd.dp_aux_access.aux_control.dpaux.action = action;
6994
6995 if (payload->length && payload->write) {
6996 memcpy(cmd.dp_aux_access.aux_control.dpaux.data,
6997 payload->data,
6998 payload->length
6999 );
7000 }
7001
7002 dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
7003
7004 return true;
7005 }
7006
dc_smart_power_oled_enable(const struct dc_link * link,bool enable,uint16_t peak_nits,uint8_t debug_control,uint16_t fixed_CLL,uint32_t triggerline)7007 bool dc_smart_power_oled_enable(const struct dc_link *link, bool enable, uint16_t peak_nits,
7008 uint8_t debug_control, uint16_t fixed_CLL, uint32_t triggerline)
7009 {
7010 bool status = false;
7011 struct dc *dc = link->ctx->dc;
7012 union dmub_rb_cmd cmd;
7013 uint8_t otg_inst = 0;
7014 unsigned int panel_inst = 0;
7015 struct pipe_ctx *pipe_ctx = NULL;
7016 struct resource_context *res_ctx = &link->ctx->dc->current_state->res_ctx;
7017 int i = 0;
7018
7019 // get panel_inst
7020 if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
7021 return status;
7022
7023 // get otg_inst
7024 for (i = 0; i < MAX_PIPES; i++) {
7025 if (res_ctx &&
7026 res_ctx->pipe_ctx[i].stream &&
7027 res_ctx->pipe_ctx[i].stream->link &&
7028 res_ctx->pipe_ctx[i].stream->link == link &&
7029 res_ctx->pipe_ctx[i].stream->link->connector_signal == SIGNAL_TYPE_EDP) {
7030 pipe_ctx = &res_ctx->pipe_ctx[i];
7031 //TODO: refactor for multi edp support
7032 break;
7033 }
7034 }
7035
7036 if (pipe_ctx)
7037 otg_inst = (uint8_t)pipe_ctx->stream_res.tg->inst;
7038
7039 // before enable smart power OLED, we need to call set pipe for DMUB to set ABM config
7040 if (enable) {
7041 if (dc->hwss.set_pipe && pipe_ctx)
7042 dc->hwss.set_pipe(pipe_ctx);
7043 }
7044
7045 // fill in cmd
7046 memset(&cmd, 0, sizeof(cmd));
7047
7048 cmd.smart_power_oled_enable.header.type = DMUB_CMD__SMART_POWER_OLED;
7049 cmd.smart_power_oled_enable.header.sub_type = DMUB_CMD__SMART_POWER_OLED_ENABLE;
7050 cmd.smart_power_oled_enable.header.payload_bytes =
7051 sizeof(struct dmub_rb_cmd_smart_power_oled_enable_data) - sizeof(struct dmub_cmd_header);
7052 cmd.smart_power_oled_enable.header.ret_status = 1;
7053 cmd.smart_power_oled_enable.data.enable = enable;
7054 cmd.smart_power_oled_enable.data.panel_inst = (uint8_t)panel_inst;
7055 cmd.smart_power_oled_enable.data.peak_nits = peak_nits;
7056 cmd.smart_power_oled_enable.data.otg_inst = otg_inst;
7057 cmd.smart_power_oled_enable.data.digfe_inst = (uint8_t)link->link_enc->preferred_engine;
7058 cmd.smart_power_oled_enable.data.digbe_inst = (uint8_t)link->link_enc->transmitter;
7059
7060 cmd.smart_power_oled_enable.data.debugcontrol = debug_control;
7061 cmd.smart_power_oled_enable.data.triggerline = triggerline;
7062 cmd.smart_power_oled_enable.data.fixed_max_cll = fixed_CLL;
7063
7064 // send cmd
7065 status = dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
7066
7067 // Update firmware_controlled_hdr_info_packet state on successful command execution
7068 if (status && pipe_ctx)
7069 pipe_ctx->stream->firmware_controlled_hdr_info_packet = enable;
7070
7071 return status;
7072 }
7073
dc_smart_power_oled_get_max_cll(const struct dc_link * link,unsigned int * pCurrent_MaxCLL)7074 bool dc_smart_power_oled_get_max_cll(const struct dc_link *link, unsigned int *pCurrent_MaxCLL)
7075 {
7076 struct dc *dc = link->ctx->dc;
7077 union dmub_rb_cmd cmd;
7078 bool status = false;
7079 unsigned int panel_inst = 0;
7080
7081 // get panel_inst
7082 if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
7083 return status;
7084
7085 // fill in cmd
7086 memset(&cmd, 0, sizeof(cmd));
7087
7088 cmd.smart_power_oled_getmaxcll.header.type = DMUB_CMD__SMART_POWER_OLED;
7089 cmd.smart_power_oled_getmaxcll.header.sub_type = DMUB_CMD__SMART_POWER_OLED_GETMAXCLL;
7090 cmd.smart_power_oled_getmaxcll.header.payload_bytes = sizeof(cmd.smart_power_oled_getmaxcll.data);
7091 cmd.smart_power_oled_getmaxcll.header.ret_status = 1;
7092
7093 cmd.smart_power_oled_getmaxcll.data.input.panel_inst = (uint8_t)panel_inst;
7094
7095 // send cmd and wait for reply
7096 status = dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY);
7097
7098 if (status)
7099 *pCurrent_MaxCLL = cmd.smart_power_oled_getmaxcll.data.output.current_max_cll;
7100 else
7101 *pCurrent_MaxCLL = 0;
7102
7103 return status;
7104 }
7105
get_link_index_from_dpia_port_index(const struct dc * dc,uint8_t dpia_port_index)7106 uint8_t get_link_index_from_dpia_port_index(const struct dc *dc,
7107 uint8_t dpia_port_index)
7108 {
7109 uint8_t index, link_index = 0xFF;
7110
7111 for (index = 0; index < dc->link_count; index++) {
7112 /* ddc_hw_inst has dpia port index for dpia links
7113 * and ddc instance for legacy links
7114 */
7115 if (!dc->links[index]->ddc->ddc_pin) {
7116 if (dc->links[index]->ddc_hw_inst == dpia_port_index) {
7117 link_index = index;
7118 break;
7119 }
7120 }
7121 }
7122 ASSERT(link_index != 0xFF);
7123 return link_index;
7124 }
7125
7126 /**
7127 * dc_process_dmub_set_config_async - Submits set_config command
7128 *
7129 * @dc: [in] dc structure
7130 * @link_index: [in] link_index: link index
7131 * @payload: [in] aux payload
7132 * @notify: [out] set_config immediate reply
7133 *
7134 * Submits set_config command to dmub via inbox message.
7135 *
7136 * Return:
7137 * True if successful, False if failure
7138 */
dc_process_dmub_set_config_async(struct dc * dc,uint32_t link_index,struct set_config_cmd_payload * payload,struct dmub_notification * notify)7139 bool dc_process_dmub_set_config_async(struct dc *dc,
7140 uint32_t link_index,
7141 struct set_config_cmd_payload *payload,
7142 struct dmub_notification *notify)
7143 {
7144 union dmub_rb_cmd cmd = {0};
7145 bool is_cmd_complete = true;
7146
7147 /* prepare SET_CONFIG command */
7148 cmd.set_config_access.header.type = DMUB_CMD__DPIA;
7149 cmd.set_config_access.header.sub_type = DMUB_CMD__DPIA_SET_CONFIG_ACCESS;
7150
7151 cmd.set_config_access.set_config_control.instance = (uint8_t)dc->links[link_index]->ddc_hw_inst;
7152 cmd.set_config_access.set_config_control.cmd_pkt.msg_type = payload->msg_type;
7153 cmd.set_config_access.set_config_control.cmd_pkt.msg_data = payload->msg_data;
7154
7155 if (!dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) {
7156 /* command is not processed by dmub */
7157 notify->sc_status = SET_CONFIG_UNKNOWN_ERROR;
7158 return is_cmd_complete;
7159 }
7160
7161 /* command processed by dmub, if ret_status is 1, it is completed instantly */
7162 if (cmd.set_config_access.header.ret_status == 1)
7163 notify->sc_status = cmd.set_config_access.set_config_control.immed_status;
7164 else
7165 /* cmd pending, will receive notification via outbox */
7166 is_cmd_complete = false;
7167
7168 return is_cmd_complete;
7169 }
7170
7171 /**
7172 * dc_process_dmub_set_mst_slots - Submits MST solt allocation
7173 *
7174 * @dc: [in] dc structure
7175 * @link_index: [in] link index
7176 * @mst_alloc_slots: [in] mst slots to be allotted
7177 * @mst_slots_in_use: [out] mst slots in use returned in failure case
7178 *
7179 * Submits mst slot allocation command to dmub via inbox message
7180 *
7181 * Return:
7182 * DC_OK if successful, DC_ERROR if failure
7183 */
dc_process_dmub_set_mst_slots(const struct dc * dc,uint32_t link_index,uint8_t mst_alloc_slots,uint8_t * mst_slots_in_use)7184 enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc,
7185 uint32_t link_index,
7186 uint8_t mst_alloc_slots,
7187 uint8_t *mst_slots_in_use)
7188 {
7189 union dmub_rb_cmd cmd = {0};
7190
7191 /* prepare MST_ALLOC_SLOTS command */
7192 cmd.set_mst_alloc_slots.header.type = DMUB_CMD__DPIA;
7193 cmd.set_mst_alloc_slots.header.sub_type = DMUB_CMD__DPIA_MST_ALLOC_SLOTS;
7194
7195 cmd.set_mst_alloc_slots.mst_slots_control.instance = (uint8_t)dc->links[link_index]->ddc_hw_inst;
7196 cmd.set_mst_alloc_slots.mst_slots_control.mst_alloc_slots = mst_alloc_slots;
7197
7198 if (!dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY))
7199 /* command is not processed by dmub */
7200 return DC_ERROR_UNEXPECTED;
7201
7202 /* command processed by dmub, if ret_status is 1 */
7203 if (cmd.set_config_access.header.ret_status != 1)
7204 /* command processing error */
7205 return DC_ERROR_UNEXPECTED;
7206
7207 /* command processed and we have a status of 2, mst not enabled in dpia */
7208 if (cmd.set_mst_alloc_slots.mst_slots_control.immed_status == 2)
7209 return DC_FAIL_UNSUPPORTED_1;
7210
7211 /* previously configured mst alloc and used slots did not match */
7212 if (cmd.set_mst_alloc_slots.mst_slots_control.immed_status == 3) {
7213 *mst_slots_in_use = cmd.set_mst_alloc_slots.mst_slots_control.mst_slots_in_use;
7214 return DC_NOT_SUPPORTED;
7215 }
7216
7217 return DC_OK;
7218 }
7219
7220 /**
7221 * dc_process_dmub_dpia_set_tps_notification - Submits tps notification
7222 *
7223 * @dc: [in] dc structure
7224 * @link_index: [in] link index
7225 * @tps: [in] request tps
7226 *
7227 * Submits set_tps_notification command to dmub via inbox message
7228 */
dc_process_dmub_dpia_set_tps_notification(const struct dc * dc,uint32_t link_index,uint8_t tps)7229 void dc_process_dmub_dpia_set_tps_notification(const struct dc *dc, uint32_t link_index, uint8_t tps)
7230 {
7231 union dmub_rb_cmd cmd = {0};
7232
7233 cmd.set_tps_notification.header.type = DMUB_CMD__DPIA;
7234 cmd.set_tps_notification.header.sub_type = DMUB_CMD__DPIA_SET_TPS_NOTIFICATION;
7235 cmd.set_tps_notification.tps_notification.instance = (uint8_t)dc->links[link_index]->ddc_hw_inst;
7236 cmd.set_tps_notification.tps_notification.tps = tps;
7237
7238 dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
7239 }
7240
7241 /**
7242 * dc_process_dmub_dpia_hpd_int_enable - Submits DPIA DPD interruption
7243 *
7244 * @dc: [in] dc structure
7245 * @hpd_int_enable: [in] 1 for hpd int enable, 0 to disable
7246 *
7247 * Submits dpia hpd int enable command to dmub via inbox message
7248 */
dc_process_dmub_dpia_hpd_int_enable(const struct dc * dc,uint32_t hpd_int_enable)7249 void dc_process_dmub_dpia_hpd_int_enable(const struct dc *dc,
7250 uint32_t hpd_int_enable)
7251 {
7252 union dmub_rb_cmd cmd = {0};
7253
7254 cmd.dpia_hpd_int_enable.header.type = DMUB_CMD__DPIA_HPD_INT_ENABLE;
7255 cmd.dpia_hpd_int_enable.enable = hpd_int_enable;
7256
7257 dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
7258
7259 DC_LOG_DEBUG("%s: hpd_int_enable(%d)\n", __func__, hpd_int_enable);
7260 }
7261
7262 /**
7263 * dc_print_dmub_diagnostic_data - Print DMUB diagnostic data for debugging
7264 *
7265 * @dc: [in] dc structure
7266 *
7267 *
7268 */
dc_print_dmub_diagnostic_data(const struct dc * dc)7269 void dc_print_dmub_diagnostic_data(const struct dc *dc)
7270 {
7271 dc_dmub_srv_log_diagnostic_data(dc->ctx->dmub_srv);
7272 }
7273
7274 /**
7275 * dc_disable_accelerated_mode - disable accelerated mode
7276 * @dc: dc structure
7277 */
dc_disable_accelerated_mode(struct dc * dc)7278 void dc_disable_accelerated_mode(struct dc *dc)
7279 {
7280 bios_set_scratch_acc_mode_change(dc->ctx->dc_bios, 0);
7281 }
7282
7283
7284 /**
7285 * dc_notify_vsync_int_state - notifies vsync enable/disable state
7286 * @dc: dc structure
7287 * @stream: stream where vsync int state changed
7288 * @enable: whether vsync is enabled or disabled
7289 *
7290 * Called when vsync is enabled/disabled Will notify DMUB to start/stop ABM
7291 * interrupts after steady state is reached.
7292 */
dc_notify_vsync_int_state(struct dc * dc,struct dc_stream_state * stream,bool enable)7293 void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bool enable)
7294 {
7295 unsigned int i, edp_num;
7296 struct pipe_ctx *pipe = NULL;
7297 struct dc_link *link = stream->sink->link;
7298 struct dc_link *edp_links[MAX_NUM_EDP];
7299
7300
7301 if (link->psr_settings.psr_feature_enabled)
7302 return;
7303
7304 if (link->replay_settings.replay_feature_enabled)
7305 return;
7306
7307 /*find primary pipe associated with stream*/
7308 for (i = 0; i < MAX_PIPES; i++) {
7309 pipe = &dc->current_state->res_ctx.pipe_ctx[i];
7310
7311 if (pipe->stream == stream && pipe->stream_res.tg)
7312 break;
7313 }
7314
7315 if (i == MAX_PIPES) {
7316 ASSERT(0);
7317 return;
7318 }
7319
7320 dc_get_edp_links(dc, edp_links, &edp_num);
7321
7322 /* Determine panel inst */
7323 for (i = 0; i < edp_num; i++) {
7324 if (edp_links[i] == link)
7325 break;
7326 }
7327
7328 if (i == edp_num) {
7329 return;
7330 }
7331
7332 if (pipe->stream_res.abm && pipe->stream_res.abm->funcs->set_abm_pause)
7333 pipe->stream_res.abm->funcs->set_abm_pause(pipe->stream_res.abm, !enable, i, pipe->stream_res.tg->inst);
7334 }
7335
7336 /*****************************************************************************
7337 * dc_abm_save_restore() - Interface to DC for save+pause and restore+un-pause
7338 * ABM
7339 * @dc: dc structure
7340 * @stream: stream where vsync int state changed
7341 * @pData: abm hw states
7342 *
7343 ****************************************************************************/
dc_abm_save_restore(struct dc * dc,struct dc_stream_state * stream,struct abm_save_restore * pData)7344 bool dc_abm_save_restore(
7345 struct dc *dc,
7346 struct dc_stream_state *stream,
7347 struct abm_save_restore *pData)
7348 {
7349 unsigned int i, edp_num;
7350 struct pipe_ctx *pipe = NULL;
7351 struct dc_link *link = stream->sink->link;
7352 struct dc_link *edp_links[MAX_NUM_EDP];
7353
7354 if (link->replay_settings.replay_feature_enabled)
7355 return false;
7356
7357 /*find primary pipe associated with stream*/
7358 for (i = 0; i < MAX_PIPES; i++) {
7359 pipe = &dc->current_state->res_ctx.pipe_ctx[i];
7360
7361 if (pipe->stream == stream && pipe->stream_res.tg)
7362 break;
7363 }
7364
7365 if (i == MAX_PIPES) {
7366 ASSERT(0);
7367 return false;
7368 }
7369
7370 dc_get_edp_links(dc, edp_links, &edp_num);
7371
7372 /* Determine panel inst */
7373 for (i = 0; i < edp_num; i++)
7374 if (edp_links[i] == link)
7375 break;
7376
7377 if (i == edp_num)
7378 return false;
7379
7380 if (pipe->stream_res.abm &&
7381 pipe->stream_res.abm->funcs->save_restore)
7382 return pipe->stream_res.abm->funcs->save_restore(
7383 pipe->stream_res.abm,
7384 i,
7385 pData);
7386 return false;
7387 }
7388
dc_query_current_properties(struct dc * dc,struct dc_current_properties * properties)7389 void dc_query_current_properties(struct dc *dc, struct dc_current_properties *properties)
7390 {
7391 unsigned int i;
7392 unsigned int max_cursor_size = dc->caps.max_cursor_size;
7393 unsigned int stream_cursor_size;
7394
7395 if (dc->debug.allow_sw_cursor_fallback && dc->res_pool->funcs->get_max_hw_cursor_size) {
7396 for (i = 0; i < dc->current_state->stream_count; i++) {
7397 stream_cursor_size = dc->res_pool->funcs->get_max_hw_cursor_size(dc,
7398 dc->current_state,
7399 dc->current_state->streams[i]);
7400
7401 if (stream_cursor_size < max_cursor_size) {
7402 max_cursor_size = stream_cursor_size;
7403 }
7404 }
7405 }
7406
7407 properties->cursor_size_limit = max_cursor_size;
7408 }
7409
7410 /**
7411 * dc_set_edp_power() - DM controls eDP power to be ON/OFF
7412 *
7413 * Called when DM wants to power on/off eDP.
7414 * Only work on links with flag skip_implict_edp_power_control is set.
7415 *
7416 * @dc: Current DC state
7417 * @edp_link: a link with eDP connector signal type
7418 * @powerOn: power on/off eDP
7419 *
7420 * Return: void
7421 */
dc_set_edp_power(const struct dc * dc,struct dc_link * edp_link,bool powerOn)7422 void dc_set_edp_power(const struct dc *dc, struct dc_link *edp_link,
7423 bool powerOn)
7424 {
7425 (void)dc;
7426 if (edp_link->connector_signal != SIGNAL_TYPE_EDP)
7427 return;
7428
7429 if (edp_link->skip_implict_edp_power_control == false)
7430 return;
7431
7432 edp_link->dc->link_srv->edp_set_panel_power(edp_link, powerOn);
7433 }
7434
7435 /**
7436 * dc_get_power_profile_for_dc_state() - extracts power profile from dc state
7437 *
7438 * Called when DM wants to make power policy decisions based on dc_state
7439 *
7440 * @context: Pointer to the dc_state from which the power profile is extracted.
7441 *
7442 * Return: The power profile structure containing the power level information.
7443 */
dc_get_power_profile_for_dc_state(const struct dc_state * context)7444 struct dc_power_profile dc_get_power_profile_for_dc_state(const struct dc_state *context)
7445 {
7446 struct dc_power_profile profile = { 0 };
7447
7448 profile.power_level = !context->bw_ctx.bw.dcn.clk.p_state_change_support;
7449 if (!context->clk_mgr || !context->clk_mgr->ctx || !context->clk_mgr->ctx->dc)
7450 return profile;
7451 struct dc *dc = context->clk_mgr->ctx->dc;
7452
7453 if (dc->res_pool->funcs->get_power_profile)
7454 profile.power_level = dc->res_pool->funcs->get_power_profile(context);
7455 return profile;
7456 }
7457
7458 /**
7459 * dc_get_det_buffer_size_from_state() - extracts detile buffer size from dc state
7460 *
7461 * This function is called to log the detile buffer size from the dc_state.
7462 *
7463 * @context: a pointer to the dc_state from which the detile buffer size is extracted.
7464 *
7465 * Return: the size of the detile buffer, or 0 if not available.
7466 */
dc_get_det_buffer_size_from_state(const struct dc_state * context)7467 unsigned int dc_get_det_buffer_size_from_state(const struct dc_state *context)
7468 {
7469 struct dc *dc = context->clk_mgr->ctx->dc;
7470
7471 if (dc->res_pool->funcs->get_det_buffer_size)
7472 return dc->res_pool->funcs->get_det_buffer_size(context);
7473 else
7474 return 0;
7475 }
7476
7477 /**
7478 * dc_get_host_router_index: Get index of host router from a dpia link
7479 *
7480 * This function return a host router index of the target link. If the target link is dpia link.
7481 *
7482 * @link: Pointer to the target link (input)
7483 * @host_router_index: Pointer to store the host router index of the target link (output).
7484 *
7485 * Return: true if the host router index is found and valid.
7486 *
7487 */
dc_get_host_router_index(const struct dc_link * link,unsigned int * host_router_index)7488 bool dc_get_host_router_index(const struct dc_link *link, unsigned int *host_router_index)
7489 {
7490 struct dc *dc;
7491
7492 if (!link || !host_router_index || link->ep_type != DISPLAY_ENDPOINT_USB4_DPIA)
7493 return false;
7494
7495 dc = link->ctx->dc;
7496
7497 if (link->link_index < dc->lowest_dpia_link_index)
7498 return false;
7499
7500 *host_router_index = (link->link_index - dc->lowest_dpia_link_index) / dc->caps.num_of_dpias_per_host_router;
7501 if (*host_router_index < dc->caps.num_of_host_routers)
7502 return true;
7503 else
7504 return false;
7505 }
7506
dc_is_cursor_limit_pending(struct dc * dc)7507 bool dc_is_cursor_limit_pending(struct dc *dc)
7508 {
7509 uint32_t i;
7510
7511 for (i = 0; i < dc->current_state->stream_count; i++) {
7512 if (dc_stream_is_cursor_limit_pending(dc, dc->current_state->streams[i]))
7513 return true;
7514 }
7515
7516 return false;
7517 }
7518
dc_can_clear_cursor_limit(const struct dc * dc)7519 bool dc_can_clear_cursor_limit(const struct dc *dc)
7520 {
7521 uint32_t i;
7522
7523 for (i = 0; i < dc->current_state->stream_count; i++) {
7524 if (dc_state_can_clear_stream_cursor_subvp_limit(dc->current_state->streams[i], dc->current_state))
7525 return true;
7526 }
7527
7528 return false;
7529 }
7530
dc_get_underflow_debug_data_for_otg(struct dc * dc,unsigned int primary_otg_inst,struct dc_underflow_debug_data * out_data)7531 void dc_get_underflow_debug_data_for_otg(struct dc *dc, unsigned int primary_otg_inst,
7532 struct dc_underflow_debug_data *out_data)
7533 {
7534 struct timing_generator *tg = NULL;
7535
7536 for (int i = 0; i < MAX_PIPES; i++) {
7537 if (dc->res_pool->timing_generators[i] &&
7538 dc->res_pool->timing_generators[i]->inst == primary_otg_inst) {
7539 tg = dc->res_pool->timing_generators[i];
7540 break;
7541 }
7542 }
7543
7544 dc_exit_ips_for_hw_access(dc);
7545 if (dc->hwss.get_underflow_debug_data)
7546 dc->hwss.get_underflow_debug_data(dc, tg, out_data);
7547 }
7548
dc_get_power_feature_status(struct dc * dc,unsigned int primary_otg_inst,struct power_features * out_data)7549 void dc_get_power_feature_status(struct dc *dc, unsigned int primary_otg_inst,
7550 struct power_features *out_data)
7551 {
7552 (void)primary_otg_inst;
7553 out_data->uclk_p_state = dc->current_state->clk_mgr->clks.p_state_change_support;
7554 out_data->fams = dc->current_state->bw_ctx.bw.dcn.clk.fw_based_mclk_switching;
7555 }
7556
dc_capture_register_software_state(struct dc * dc,struct dc_register_software_state * state)7557 bool dc_capture_register_software_state(struct dc *dc, struct dc_register_software_state *state)
7558 {
7559 struct dc_state *context;
7560 struct resource_context *res_ctx;
7561 unsigned int i;
7562 const unsigned int max_pipes = MAX_PIPES;
7563
7564 if (!dc || !dc->current_state || !state) {
7565 if (state)
7566 state->state_valid = false;
7567 return false;
7568 }
7569
7570 /* Initialize the state structure */
7571 memset(state, 0, sizeof(struct dc_register_software_state));
7572
7573 context = dc->current_state;
7574 res_ctx = &context->res_ctx;
7575
7576 /* Count active pipes and streams */
7577 state->active_pipe_count = 0;
7578 state->active_stream_count = context->stream_count;
7579
7580 for (i = 0; i < dc->res_pool->pipe_count; i++) {
7581 if (res_ctx->pipe_ctx[i].stream)
7582 state->active_pipe_count++;
7583 }
7584
7585 /* Capture HUBP programming state for each pipe */
7586 for (i = 0; i < max_pipes && i < dc->res_pool->pipe_count; i++) {
7587 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
7588
7589 state->hubp[i].valid_stream = false;
7590 if (!pipe_ctx->stream)
7591 continue;
7592
7593 state->hubp[i].valid_stream = true;
7594
7595 /* HUBP register programming variables */
7596 if (pipe_ctx->stream_res.tg)
7597 state->hubp[i].vtg_sel = pipe_ctx->stream_res.tg->inst;
7598
7599 state->hubp[i].hubp_clock_enable = (pipe_ctx->plane_res.hubp != NULL) ? 1 : 0;
7600
7601 state->hubp[i].valid_plane_state = false;
7602 if (pipe_ctx->plane_state) {
7603 state->hubp[i].valid_plane_state = true;
7604 state->hubp[i].surface_pixel_format = pipe_ctx->plane_state->format;
7605 state->hubp[i].rotation_angle = pipe_ctx->plane_state->rotation;
7606 state->hubp[i].h_mirror_en = pipe_ctx->plane_state->horizontal_mirror ? 1 : 0;
7607
7608 /* Surface size */
7609 if (pipe_ctx->plane_state->plane_size.surface_size.width > 0) {
7610 state->hubp[i].surface_size_width = pipe_ctx->plane_state->plane_size.surface_size.width;
7611 state->hubp[i].surface_size_height = pipe_ctx->plane_state->plane_size.surface_size.height;
7612 }
7613
7614 /* Viewport dimensions from scaler data */
7615 if (pipe_ctx->plane_state->src_rect.width > 0) {
7616 state->hubp[i].pri_viewport_width = pipe_ctx->plane_state->src_rect.width;
7617 state->hubp[i].pri_viewport_height = pipe_ctx->plane_state->src_rect.height;
7618 state->hubp[i].pri_viewport_x_start = pipe_ctx->plane_state->src_rect.x;
7619 state->hubp[i].pri_viewport_y_start = pipe_ctx->plane_state->src_rect.y;
7620 }
7621
7622 /* DCC settings */
7623 state->hubp[i].surface_dcc_en = (pipe_ctx->plane_state->dcc.enable) ? 1 : 0;
7624 state->hubp[i].surface_dcc_ind_64b_blk = pipe_ctx->plane_state->dcc.independent_64b_blks;
7625 state->hubp[i].surface_dcc_ind_128b_blk = pipe_ctx->plane_state->dcc.dcc_ind_blk;
7626
7627 /* Surface pitch */
7628 state->hubp[i].surface_pitch = pipe_ctx->plane_state->plane_size.surface_pitch;
7629 state->hubp[i].meta_pitch = pipe_ctx->plane_state->dcc.meta_pitch;
7630 state->hubp[i].chroma_pitch = pipe_ctx->plane_state->plane_size.chroma_pitch;
7631 state->hubp[i].meta_pitch_c = pipe_ctx->plane_state->dcc.meta_pitch_c;
7632
7633 /* Surface addresses - primary */
7634 state->hubp[i].primary_surface_address_low = pipe_ctx->plane_state->address.grph.addr.low_part;
7635 state->hubp[i].primary_surface_address_high = pipe_ctx->plane_state->address.grph.addr.high_part;
7636 state->hubp[i].primary_meta_surface_address_low = pipe_ctx->plane_state->address.grph.meta_addr.low_part;
7637 state->hubp[i].primary_meta_surface_address_high = pipe_ctx->plane_state->address.grph.meta_addr.high_part;
7638
7639 /* TMZ settings */
7640 state->hubp[i].primary_surface_tmz = pipe_ctx->plane_state->address.tmz_surface;
7641 state->hubp[i].primary_meta_surface_tmz = pipe_ctx->plane_state->address.tmz_surface;
7642
7643 /* Tiling configuration */
7644 state->hubp[i].min_dc_gfx_version9 = false;
7645 if (pipe_ctx->plane_state->tiling_info.gfxversion >= DcGfxVersion9) {
7646 state->hubp[i].min_dc_gfx_version9 = true;
7647 state->hubp[i].sw_mode = pipe_ctx->plane_state->tiling_info.gfx9.swizzle;
7648 state->hubp[i].num_pipes = pipe_ctx->plane_state->tiling_info.gfx9.num_pipes;
7649 state->hubp[i].num_banks = pipe_ctx->plane_state->tiling_info.gfx9.num_banks;
7650 state->hubp[i].pipe_interleave = pipe_ctx->plane_state->tiling_info.gfx9.pipe_interleave;
7651 state->hubp[i].num_shader_engines = pipe_ctx->plane_state->tiling_info.gfx9.num_shader_engines;
7652 state->hubp[i].num_rb_per_se = pipe_ctx->plane_state->tiling_info.gfx9.num_rb_per_se;
7653 state->hubp[i].num_pkrs = pipe_ctx->plane_state->tiling_info.gfx9.num_pkrs;
7654 }
7655 }
7656
7657 /* DML Request Size Configuration */
7658 if (pipe_ctx->rq_regs.rq_regs_l.chunk_size > 0) {
7659 state->hubp[i].rq_chunk_size = pipe_ctx->rq_regs.rq_regs_l.chunk_size;
7660 state->hubp[i].rq_min_chunk_size = pipe_ctx->rq_regs.rq_regs_l.min_chunk_size;
7661 state->hubp[i].rq_meta_chunk_size = pipe_ctx->rq_regs.rq_regs_l.meta_chunk_size;
7662 state->hubp[i].rq_min_meta_chunk_size = pipe_ctx->rq_regs.rq_regs_l.min_meta_chunk_size;
7663 state->hubp[i].rq_dpte_group_size = pipe_ctx->rq_regs.rq_regs_l.dpte_group_size;
7664 state->hubp[i].rq_mpte_group_size = pipe_ctx->rq_regs.rq_regs_l.mpte_group_size;
7665 state->hubp[i].rq_swath_height_l = pipe_ctx->rq_regs.rq_regs_l.swath_height;
7666 state->hubp[i].rq_pte_row_height_l = pipe_ctx->rq_regs.rq_regs_l.pte_row_height_linear;
7667 }
7668
7669 /* Chroma request size configuration */
7670 if (pipe_ctx->rq_regs.rq_regs_c.chunk_size > 0) {
7671 state->hubp[i].rq_chunk_size_c = pipe_ctx->rq_regs.rq_regs_c.chunk_size;
7672 state->hubp[i].rq_min_chunk_size_c = pipe_ctx->rq_regs.rq_regs_c.min_chunk_size;
7673 state->hubp[i].rq_meta_chunk_size_c = pipe_ctx->rq_regs.rq_regs_c.meta_chunk_size;
7674 state->hubp[i].rq_min_meta_chunk_size_c = pipe_ctx->rq_regs.rq_regs_c.min_meta_chunk_size;
7675 state->hubp[i].rq_dpte_group_size_c = pipe_ctx->rq_regs.rq_regs_c.dpte_group_size;
7676 state->hubp[i].rq_mpte_group_size_c = pipe_ctx->rq_regs.rq_regs_c.mpte_group_size;
7677 state->hubp[i].rq_swath_height_c = pipe_ctx->rq_regs.rq_regs_c.swath_height;
7678 state->hubp[i].rq_pte_row_height_c = pipe_ctx->rq_regs.rq_regs_c.pte_row_height_linear;
7679 }
7680
7681 /* DML expansion modes */
7682 state->hubp[i].drq_expansion_mode = pipe_ctx->rq_regs.drq_expansion_mode;
7683 state->hubp[i].prq_expansion_mode = pipe_ctx->rq_regs.prq_expansion_mode;
7684 state->hubp[i].mrq_expansion_mode = pipe_ctx->rq_regs.mrq_expansion_mode;
7685 state->hubp[i].crq_expansion_mode = pipe_ctx->rq_regs.crq_expansion_mode;
7686
7687 /* DML DLG parameters - nominal */
7688 state->hubp[i].dst_y_per_vm_vblank = pipe_ctx->dlg_regs.dst_y_per_vm_vblank;
7689 state->hubp[i].dst_y_per_row_vblank = pipe_ctx->dlg_regs.dst_y_per_row_vblank;
7690 state->hubp[i].dst_y_per_vm_flip = pipe_ctx->dlg_regs.dst_y_per_vm_flip;
7691 state->hubp[i].dst_y_per_row_flip = pipe_ctx->dlg_regs.dst_y_per_row_flip;
7692
7693 /* DML prefetch settings */
7694 state->hubp[i].dst_y_prefetch = pipe_ctx->dlg_regs.dst_y_prefetch;
7695 state->hubp[i].vratio_prefetch = pipe_ctx->dlg_regs.vratio_prefetch;
7696 state->hubp[i].vratio_prefetch_c = pipe_ctx->dlg_regs.vratio_prefetch_c;
7697
7698 /* TTU parameters */
7699 state->hubp[i].qos_level_low_wm = pipe_ctx->ttu_regs.qos_level_low_wm;
7700 state->hubp[i].qos_level_high_wm = pipe_ctx->ttu_regs.qos_level_high_wm;
7701 state->hubp[i].qos_level_flip = pipe_ctx->ttu_regs.qos_level_flip;
7702 state->hubp[i].min_ttu_vblank = pipe_ctx->ttu_regs.min_ttu_vblank;
7703 }
7704
7705 /* Capture HUBBUB programming state */
7706 if (dc->res_pool->hubbub) {
7707 /* Individual DET buffer sizes - software state variables that program DET registers */
7708 for (i = 0; i < 4u && i < dc->res_pool->pipe_count; i++) {
7709 uint32_t det_size = res_ctx->pipe_ctx[i].det_buffer_size_kb;
7710 switch (i) {
7711 case 0:
7712 state->hubbub.det0_size = det_size;
7713 break;
7714 case 1:
7715 state->hubbub.det1_size = det_size;
7716 break;
7717 case 2:
7718 state->hubbub.det2_size = det_size;
7719 break;
7720 case 3:
7721 state->hubbub.det3_size = det_size;
7722 break;
7723 }
7724 }
7725
7726 /* Compression buffer configuration - software state that programs COMPBUF_SIZE register */
7727 // TODO: Handle logic for legacy DCN pre-DCN401
7728 state->hubbub.compbuf_size = context->bw_ctx.bw.dcn.arb_regs.compbuf_size;
7729 }
7730
7731 /* Capture DPP programming state for each pipe */
7732 for (i = 0; i < max_pipes && i < dc->res_pool->pipe_count; i++) {
7733 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
7734
7735 if (!pipe_ctx->stream)
7736 continue;
7737
7738 state->dpp[i].dpp_clock_enable = (pipe_ctx->plane_res.dpp != NULL) ? 1 : 0;
7739
7740 if (pipe_ctx->plane_state && pipe_ctx->plane_res.scl_data.recout.width > 0) {
7741 /* Access dscl_prog_data directly - this contains the actual software state used for register programming */
7742 struct dscl_prog_data *dscl_data = &pipe_ctx->plane_res.scl_data.dscl_prog_data;
7743
7744 /* Recout (Rectangle of Interest) configuration - software state that programs RECOUT registers */
7745 state->dpp[i].recout_start_x = dscl_data->recout.x;
7746 state->dpp[i].recout_start_y = dscl_data->recout.y;
7747 state->dpp[i].recout_width = dscl_data->recout.width;
7748 state->dpp[i].recout_height = dscl_data->recout.height;
7749
7750 /* MPC (Multiple Pipe/Plane Combiner) size - software state that programs MPC_SIZE registers */
7751 state->dpp[i].mpc_width = dscl_data->mpc_size.width;
7752 state->dpp[i].mpc_height = dscl_data->mpc_size.height;
7753
7754 /* DSCL mode - software state that programs SCL_MODE registers */
7755 state->dpp[i].dscl_mode = dscl_data->dscl_mode;
7756
7757 /* Scaler ratios - software state that programs scale ratio registers (use actual programmed ratios) */
7758 state->dpp[i].horz_ratio_int = dscl_data->ratios.h_scale_ratio >> 19; // Extract integer part from programmed ratio
7759 state->dpp[i].vert_ratio_int = dscl_data->ratios.v_scale_ratio >> 19; // Extract integer part from programmed ratio
7760
7761 /* Basic scaler taps - software state that programs tap control registers (use actual programmed taps) */
7762 state->dpp[i].h_taps = dscl_data->taps.h_taps + 1; // dscl_prog_data.taps stores (taps - 1), so add 1 back
7763 state->dpp[i].v_taps = dscl_data->taps.v_taps + 1; // dscl_prog_data.taps stores (taps - 1), so add 1 back
7764 }
7765 }
7766
7767 /* Capture essential clock state for underflow analysis */
7768 if (dc->clk_mgr && dc->clk_mgr->clks.dispclk_khz > 0) {
7769 /* Core display clocks affecting bandwidth and timing */
7770 state->dccg.dispclk_khz = dc->clk_mgr->clks.dispclk_khz;
7771
7772 /* Per-pipe clock configuration - only capture what's essential */
7773 for (i = 0; i < max_pipes && i < dc->res_pool->pipe_count; i++) {
7774 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
7775 if (pipe_ctx->stream) {
7776 /* Essential clocks that directly affect underflow risk */
7777 state->dccg.dppclk_khz[i] = dc->clk_mgr->clks.dppclk_khz;
7778 state->dccg.pixclk_khz[i] = pipe_ctx->stream->timing.pix_clk_100hz / 10;
7779 state->dccg.dppclk_enable[i] = 1;
7780
7781 /* DP stream clock only for DP signals */
7782 if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
7783 pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
7784 state->dccg.dpstreamclk_enable[i] = 1;
7785 } else {
7786 state->dccg.dpstreamclk_enable[i] = 0;
7787 }
7788 } else {
7789 /* Inactive pipe - no clocks */
7790 state->dccg.dppclk_khz[i] = 0;
7791 state->dccg.pixclk_khz[i] = 0;
7792 state->dccg.dppclk_enable[i] = 0;
7793 if (i < 4) {
7794 state->dccg.dpstreamclk_enable[i] = 0;
7795 }
7796 }
7797 }
7798
7799 /* DSC clock state - only when actually using DSC */
7800 for (i = 0; i < max_pipes; i++) {
7801 struct pipe_ctx *pipe_ctx = (i < dc->res_pool->pipe_count) ? &res_ctx->pipe_ctx[i] : NULL;
7802 if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->timing.dsc_cfg.num_slices_h > 0) {
7803 state->dccg.dscclk_khz[i] = 400000; /* Typical DSC clock frequency */
7804 } else {
7805 state->dccg.dscclk_khz[i] = 0;
7806 }
7807 }
7808
7809 /* SYMCLK32 LE Control - only the essential HPO state for underflow analysis */
7810 for (i = 0; i < 2; i++) {
7811 state->dccg.symclk32_le_enable[i] = 0; /* Default: disabled */
7812 }
7813
7814 /* Check for active HPO usage that affects symclk32_le */
7815 for (unsigned int pipe_idx = 0; pipe_idx < MAX_PIPES && pipe_idx < dc->res_pool->pipe_count; pipe_idx++) {
7816 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[pipe_idx];
7817 if (!pipe_ctx->stream)
7818 continue;
7819
7820 /* HPO FRL (HDMI FRL) streams use symclk32_le */
7821 if (pipe_ctx->stream_res.hpo_frl_stream_enc && pipe_ctx->link_res.hpo_frl_link_enc) {
7822 int hpo_le_inst = pipe_ctx->link_res.hpo_frl_link_enc->inst;
7823 if (hpo_le_inst >= 0 && hpo_le_inst < 2) {
7824 state->dccg.symclk32_le_enable[hpo_le_inst] = 1;
7825 }
7826 }
7827 }
7828 }
7829
7830 /* Capture essential DSC configuration for underflow analysis */
7831 for (i = 0; i < max_pipes && i < dc->res_pool->pipe_count; i++) {
7832 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
7833
7834 if (pipe_ctx->stream && pipe_ctx->stream->timing.dsc_cfg.num_slices_h > 0) {
7835 /* DSC is enabled - capture essential configuration */
7836 state->dsc[i].dsc_clock_enable = 1;
7837
7838 /* DSC configuration affecting bandwidth and timing */
7839 struct dc_dsc_config *dsc_cfg = &pipe_ctx->stream->timing.dsc_cfg;
7840 state->dsc[i].dsc_num_slices_h = dsc_cfg->num_slices_h;
7841 state->dsc[i].dsc_num_slices_v = dsc_cfg->num_slices_v;
7842 state->dsc[i].dsc_bits_per_pixel = dsc_cfg->bits_per_pixel;
7843
7844 /* OPP pipe source for DSC forwarding */
7845 if (pipe_ctx->stream_res.opp) {
7846 state->dsc[i].dscrm_dsc_forward_enable = 1;
7847 state->dsc[i].dscrm_dsc_opp_pipe_source = pipe_ctx->stream_res.opp->inst;
7848 } else {
7849 state->dsc[i].dscrm_dsc_forward_enable = 0;
7850 state->dsc[i].dscrm_dsc_opp_pipe_source = 0;
7851 }
7852 } else {
7853 /* DSC not enabled - clear all fields */
7854 memset(&state->dsc[i], 0, sizeof(state->dsc[i]));
7855 }
7856 }
7857
7858 /* Capture MPC programming state - comprehensive register field coverage */
7859 for (i = 0; i < max_pipes && i < dc->res_pool->pipe_count; i++) {
7860 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
7861
7862 if (pipe_ctx->plane_state && pipe_ctx->stream) {
7863 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
7864
7865 /* MPCC blending tree and mode control - capture actual blend configuration */
7866 state->mpc.mpcc_mode[i] = (plane_state->cm.blend_func.type != TF_TYPE_BYPASS) ? 1 : 0;
7867 state->mpc.mpcc_alpha_blend_mode[i] = plane_state->per_pixel_alpha ? 1 : 0;
7868 state->mpc.mpcc_alpha_multiplied_mode[i] = plane_state->pre_multiplied_alpha ? 1 : 0;
7869 state->mpc.mpcc_blnd_active_overlap_only[i] = 0; /* Default - no overlap restriction */
7870 state->mpc.mpcc_global_alpha[i] = plane_state->global_alpha_value;
7871 state->mpc.mpcc_global_gain[i] = plane_state->global_alpha ? 255 : 0;
7872 state->mpc.mpcc_bg_bpc[i] = 8; /* Standard 8-bit background */
7873 state->mpc.mpcc_bot_gain_mode[i] = 0; /* Standard gain mode */
7874
7875 /* MPCC blending tree connections - capture tree topology */
7876 if (pipe_ctx->bottom_pipe) {
7877 state->mpc.mpcc_bot_sel[i] = pipe_ctx->bottom_pipe->pipe_idx;
7878 } else {
7879 state->mpc.mpcc_bot_sel[i] = 0xF; /* No bottom connection */
7880 }
7881 state->mpc.mpcc_top_sel[i] = pipe_ctx->pipe_idx; /* This pipe's DPP ID */
7882
7883 /* MPCC output gamma control - capture gamma programming */
7884 if (plane_state->gamma_correction.type != GAMMA_CS_TFM_1D && plane_state->gamma_correction.num_entries > 0) {
7885 state->mpc.mpcc_ogam_mode[i] = 1; /* Gamma enabled */
7886 state->mpc.mpcc_ogam_select[i] = 0; /* Bank A selection */
7887 state->mpc.mpcc_ogam_pwl_disable[i] = 0; /* PWL enabled */
7888 } else {
7889 state->mpc.mpcc_ogam_mode[i] = 0; /* Bypass mode */
7890 state->mpc.mpcc_ogam_select[i] = 0;
7891 state->mpc.mpcc_ogam_pwl_disable[i] = 1; /* PWL disabled */
7892 }
7893
7894 /* MPCC pipe assignment and operational status */
7895 if (pipe_ctx->stream_res.opp) {
7896 state->mpc.mpcc_opp_id[i] = pipe_ctx->stream_res.opp->inst;
7897 } else {
7898 state->mpc.mpcc_opp_id[i] = 0xF; /* No OPP assignment */
7899 }
7900
7901 /* MPCC status indicators - active pipe state */
7902 state->mpc.mpcc_idle[i] = 0; /* Active pipe - not idle */
7903 state->mpc.mpcc_busy[i] = 1; /* Active pipe - busy processing */
7904
7905 } else {
7906 /* Pipe not active - set disabled/idle state for all fields */
7907 state->mpc.mpcc_mode[i] = 0;
7908 state->mpc.mpcc_alpha_blend_mode[i] = 0;
7909 state->mpc.mpcc_alpha_multiplied_mode[i] = 0;
7910 state->mpc.mpcc_blnd_active_overlap_only[i] = 0;
7911 state->mpc.mpcc_global_alpha[i] = 0;
7912 state->mpc.mpcc_global_gain[i] = 0;
7913 state->mpc.mpcc_bg_bpc[i] = 0;
7914 state->mpc.mpcc_bot_gain_mode[i] = 0;
7915 state->mpc.mpcc_bot_sel[i] = 0xF; /* No bottom connection */
7916 state->mpc.mpcc_top_sel[i] = 0xF; /* No top connection */
7917 state->mpc.mpcc_ogam_mode[i] = 0; /* Bypass */
7918 state->mpc.mpcc_ogam_select[i] = 0;
7919 state->mpc.mpcc_ogam_pwl_disable[i] = 1; /* PWL disabled */
7920 state->mpc.mpcc_opp_id[i] = 0xF; /* No OPP assignment */
7921 state->mpc.mpcc_idle[i] = 1; /* Idle */
7922 state->mpc.mpcc_busy[i] = 0; /* Not busy */
7923 }
7924 }
7925
7926 /* Capture OPP programming state for each pipe - comprehensive register field coverage */
7927 for (i = 0; i < max_pipes && i < dc->res_pool->pipe_count; i++) {
7928 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
7929
7930 if (!pipe_ctx->stream)
7931 continue;
7932
7933 if (pipe_ctx->stream_res.opp) {
7934 struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
7935
7936 /* OPP Pipe Control */
7937 state->opp[i].opp_pipe_clock_enable = 1; /* Active pipe has clock enabled */
7938
7939 /* Display Pattern Generator (DPG) Control - 19 fields */
7940 if (pipe_ctx->stream->test_pattern.type != DP_TEST_PATTERN_VIDEO_MODE) {
7941 state->opp[i].dpg_enable = 1;
7942 } else {
7943 /* Video mode - DPG disabled */
7944 state->opp[i].dpg_enable = 0;
7945 }
7946
7947 /* Format Control (FMT) - 18 fields */
7948 state->opp[i].fmt_pixel_encoding = timing->pixel_encoding;
7949
7950 /* Chroma subsampling mode based on pixel encoding */
7951 if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) {
7952 state->opp[i].fmt_subsampling_mode = 1; /* 4:2:0 subsampling */
7953 } else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
7954 state->opp[i].fmt_subsampling_mode = 2; /* 4:2:2 subsampling */
7955 } else {
7956 state->opp[i].fmt_subsampling_mode = 0; /* No subsampling (4:4:4) */
7957 }
7958
7959 state->opp[i].fmt_cbcr_bit_reduction_bypass = (timing->pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0;
7960 state->opp[i].fmt_stereosync_override = (timing->timing_3d_format != TIMING_3D_FORMAT_NONE) ? 1 : 0;
7961
7962 /* Dithering control based on bit depth */
7963 if (timing->display_color_depth < COLOR_DEPTH_121212) {
7964 state->opp[i].fmt_spatial_dither_frame_counter_max = 15; /* Typical frame counter max */
7965 state->opp[i].fmt_spatial_dither_frame_counter_bit_swap = 0; /* No bit swapping */
7966 state->opp[i].fmt_spatial_dither_enable = 1;
7967 state->opp[i].fmt_spatial_dither_mode = 0; /* Spatial dithering mode */
7968 state->opp[i].fmt_spatial_dither_depth = timing->display_color_depth;
7969 state->opp[i].fmt_temporal_dither_enable = 0; /* Spatial dithering preferred */
7970 } else {
7971 state->opp[i].fmt_spatial_dither_frame_counter_max = 0;
7972 state->opp[i].fmt_spatial_dither_frame_counter_bit_swap = 0;
7973 state->opp[i].fmt_spatial_dither_enable = 0;
7974 state->opp[i].fmt_spatial_dither_mode = 0;
7975 state->opp[i].fmt_spatial_dither_depth = 0;
7976 state->opp[i].fmt_temporal_dither_enable = 0;
7977 }
7978
7979 /* Truncation control for bit depth reduction */
7980 if (timing->display_color_depth < COLOR_DEPTH_121212) {
7981 state->opp[i].fmt_truncate_enable = 1;
7982 state->opp[i].fmt_truncate_depth = timing->display_color_depth;
7983 state->opp[i].fmt_truncate_mode = 0; /* Round mode */
7984 } else {
7985 state->opp[i].fmt_truncate_enable = 0;
7986 state->opp[i].fmt_truncate_depth = 0;
7987 state->opp[i].fmt_truncate_mode = 0;
7988 }
7989
7990 /* Data clamping control */
7991 state->opp[i].fmt_clamp_data_enable = 1; /* Clamping typically enabled */
7992 state->opp[i].fmt_clamp_color_format = timing->pixel_encoding;
7993
7994 /* Dynamic expansion for limited range content */
7995 if (timing->pixel_encoding != PIXEL_ENCODING_RGB) {
7996 state->opp[i].fmt_dynamic_exp_enable = 1; /* YCbCr typically needs expansion */
7997 state->opp[i].fmt_dynamic_exp_mode = 0; /* Standard expansion */
7998 } else {
7999 state->opp[i].fmt_dynamic_exp_enable = 0; /* RGB typically full range */
8000 state->opp[i].fmt_dynamic_exp_mode = 0;
8001 }
8002
8003 /* Legacy field for compatibility */
8004 state->opp[i].fmt_bit_depth_control = timing->display_color_depth;
8005
8006 /* Output Buffer (OPPBUF) Control - 6 fields */
8007 state->opp[i].oppbuf_active_width = timing->h_addressable;
8008 state->opp[i].oppbuf_pixel_repetition = 0; /* No pixel repetition by default */
8009
8010 /* Multi-Stream Output (MSO) / ODM segmentation */
8011 if (pipe_ctx->next_odm_pipe) {
8012 state->opp[i].oppbuf_display_segmentation = 1; /* Segmented display */
8013 state->opp[i].oppbuf_overlap_pixel_num = 0; /* ODM overlap pixels */
8014 } else {
8015 state->opp[i].oppbuf_display_segmentation = 0; /* Single segment */
8016 state->opp[i].oppbuf_overlap_pixel_num = 0;
8017 }
8018
8019 /* 3D/Stereo control */
8020 if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE) {
8021 state->opp[i].oppbuf_3d_vact_space1_size = 30; /* Typical stereo blanking */
8022 state->opp[i].oppbuf_3d_vact_space2_size = 30;
8023 } else {
8024 state->opp[i].oppbuf_3d_vact_space1_size = 0;
8025 state->opp[i].oppbuf_3d_vact_space2_size = 0;
8026 }
8027
8028 /* DSC Forward Config - 3 fields */
8029 if (timing->dsc_cfg.num_slices_h > 0) {
8030 state->opp[i].dscrm_dsc_forward_enable = 1;
8031 state->opp[i].dscrm_dsc_opp_pipe_source = pipe_ctx->stream_res.opp->inst;
8032 state->opp[i].dscrm_dsc_forward_enable_status = 1; /* Status follows enable */
8033 } else {
8034 state->opp[i].dscrm_dsc_forward_enable = 0;
8035 state->opp[i].dscrm_dsc_opp_pipe_source = 0;
8036 state->opp[i].dscrm_dsc_forward_enable_status = 0;
8037 }
8038 } else {
8039 /* No OPP resource - set all fields to disabled state */
8040 memset(&state->opp[i], 0, sizeof(state->opp[i]));
8041 }
8042 }
8043
8044 /* Capture OPTC programming state for each pipe - comprehensive register field coverage */
8045 for (i = 0; i < max_pipes && i < dc->res_pool->pipe_count; i++) {
8046 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
8047
8048 if (!pipe_ctx->stream)
8049 continue;
8050
8051 if (pipe_ctx->stream_res.tg) {
8052 struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
8053
8054 state->optc[i].otg_master_inst = pipe_ctx->stream_res.tg->inst;
8055
8056 /* OTG_CONTROL register - 5 fields */
8057 state->optc[i].otg_master_enable = 1; /* Active stream */
8058 state->optc[i].otg_disable_point_cntl = 0; /* Normal operation */
8059 state->optc[i].otg_start_point_cntl = 0; /* Normal start */
8060 state->optc[i].otg_field_number_cntl = (timing->flags.INTERLACE) ? 1 : 0;
8061 state->optc[i].otg_out_mux = 0; /* Direct output */
8062
8063 /* OTG Horizontal Timing - 7 fields */
8064 state->optc[i].otg_h_total = timing->h_total;
8065 state->optc[i].otg_h_blank_start = timing->h_addressable;
8066 state->optc[i].otg_h_blank_end = timing->h_total - timing->h_front_porch;
8067 state->optc[i].otg_h_sync_start = timing->h_addressable + timing->h_front_porch;
8068 state->optc[i].otg_h_sync_end = timing->h_addressable + timing->h_front_porch + timing->h_sync_width;
8069 state->optc[i].otg_h_sync_polarity = timing->flags.HSYNC_POSITIVE_POLARITY ? 0 : 1;
8070 state->optc[i].otg_h_timing_div_mode = (pipe_ctx->next_odm_pipe) ? 1 : 0; /* ODM divide mode */
8071
8072 /* OTG Vertical Timing - 7 fields */
8073 state->optc[i].otg_v_total = timing->v_total;
8074 state->optc[i].otg_v_blank_start = timing->v_addressable;
8075 state->optc[i].otg_v_blank_end = timing->v_total - timing->v_front_porch;
8076 state->optc[i].otg_v_sync_start = timing->v_addressable + timing->v_front_porch;
8077 state->optc[i].otg_v_sync_end = timing->v_addressable + timing->v_front_porch + timing->v_sync_width;
8078 state->optc[i].otg_v_sync_polarity = timing->flags.VSYNC_POSITIVE_POLARITY ? 0 : 1;
8079 state->optc[i].otg_v_sync_mode = 0; /* Normal sync mode */
8080
8081 /* Initialize remaining core fields with appropriate defaults */
8082 // TODO: Update logic for accurate vtotal min/max
8083 state->optc[i].otg_v_total_max = timing->v_total + 100; /* Typical DRR range */
8084 state->optc[i].otg_v_total_min = timing->v_total - 50;
8085 state->optc[i].otg_v_total_mid = timing->v_total;
8086
8087 /* ODM configuration */
8088 // TODO: Update logic to have complete ODM mappings (e.g. 3:1 and 4:1) stored in single pipe
8089 if (pipe_ctx->next_odm_pipe) {
8090 state->optc[i].optc_seg0_src_sel = pipe_ctx->stream_res.opp ? pipe_ctx->stream_res.opp->inst : 0;
8091 state->optc[i].optc_seg1_src_sel = pipe_ctx->next_odm_pipe->stream_res.opp ? pipe_ctx->next_odm_pipe->stream_res.opp->inst : 0;
8092 state->optc[i].optc_num_of_input_segment = 1; /* 2 segments - 1 */
8093 } else {
8094 state->optc[i].optc_seg0_src_sel = pipe_ctx->stream_res.opp ? pipe_ctx->stream_res.opp->inst : 0;
8095 state->optc[i].optc_seg1_src_sel = 0;
8096 state->optc[i].optc_num_of_input_segment = 0; /* Single segment */
8097 }
8098
8099 /* DSC configuration */
8100 if (timing->dsc_cfg.num_slices_h > 0) {
8101 state->optc[i].optc_dsc_mode = 1; /* DSC enabled */
8102 state->optc[i].optc_dsc_bytes_per_pixel = timing->dsc_cfg.bits_per_pixel / 16; /* Convert to bytes */
8103 state->optc[i].optc_dsc_slice_width = timing->h_addressable / timing->dsc_cfg.num_slices_h;
8104 } else {
8105 state->optc[i].optc_dsc_mode = 0;
8106 state->optc[i].optc_dsc_bytes_per_pixel = 0;
8107 state->optc[i].optc_dsc_slice_width = 0;
8108 }
8109
8110 /* Essential control fields */
8111 state->optc[i].otg_stereo_enable = (timing->timing_3d_format != TIMING_3D_FORMAT_NONE) ? 1 : 0;
8112 state->optc[i].otg_interlace_enable = timing->flags.INTERLACE ? 1 : 0;
8113 state->optc[i].otg_clock_enable = 1; /* OTG clock enabled */
8114 state->optc[i].vtg0_enable = 1; /* VTG enabled for timing generation */
8115
8116 /* Initialize other key fields to defaults */
8117 state->optc[i].optc_input_pix_clk_en = 1;
8118 state->optc[i].optc_segment_width = (pipe_ctx->next_odm_pipe) ? (timing->h_addressable / 2) : timing->h_addressable;
8119 state->optc[i].otg_vready_offset = 1;
8120 state->optc[i].otg_vstartup_start = timing->v_addressable + 10;
8121 state->optc[i].otg_vupdate_offset = 0;
8122 state->optc[i].otg_vupdate_width = 5;
8123 } else {
8124 /* No timing generator resource - initialize all fields to 0 */
8125 memset(&state->optc[i], 0, sizeof(state->optc[i]));
8126 }
8127 }
8128
8129 state->state_valid = true;
8130 return true;
8131 }
8132
dc_log_preos_dmcub_info(const struct dc * dc)8133 void dc_log_preos_dmcub_info(const struct dc *dc)
8134 {
8135 dc_dmub_srv_log_preos_dmcub_info(dc->ctx->dmub_srv);
8136 }
8137
dc_get_qos_info(struct dc * dc,struct dc_qos_info * info)8138 bool dc_get_qos_info(struct dc *dc, struct dc_qos_info *info)
8139 {
8140 const struct dc_clocks *clk = &dc->current_state->bw_ctx.bw.dcn.clk;
8141 struct dc_requested_memory_qos requested = {};
8142
8143 memset(info, 0, sizeof(*info));
8144
8145 info->dcn_bandwidth_ub_in_mbps = (uint32_t)(clk->fclk_khz / 1000 * 64);
8146
8147 if (dc->clk_mgr && dc->clk_mgr->funcs->get_requested_memory_qos) {
8148 dc->clk_mgr->funcs->get_requested_memory_qos(dc->clk_mgr, &requested);
8149 info->qos_bandwidth_lb_in_mbps = requested.bandwidth_lb_in_mbps;
8150 info->calculated_avg_bw_in_mbps = requested.calculated_avg_bw_in_mbps;
8151 info->qos_max_latency_ub_in_ns = requested.max_latency_ub_in_ns;
8152 info->qos_avg_latency_ub_in_ns = requested.avg_latency_ub_in_ns;
8153 info->qos_max_bw_budget_in_mbps = requested.max_bw_budget_in_mbps;
8154 }
8155
8156 return true;
8157 }
8158
dc_override_memory_bandwidth_request(struct dc * dc,unsigned int bw_mbps)8159 unsigned int dc_override_memory_bandwidth_request(
8160 struct dc *dc,
8161 unsigned int bw_mbps)
8162 {
8163 if (!dc->clk_mgr || !dc->clk_mgr->funcs)
8164 return 0;
8165
8166 return dc->clk_mgr->funcs->override_memory_bandwidth_request(
8167 dc->clk_mgr, bw_mbps * 1000) / 1000;
8168 }
8169
update_planes_and_stream_prepare_v2(struct dc_update_scratch_space * scratch)8170 static bool update_planes_and_stream_prepare_v2(
8171 struct dc_update_scratch_space *scratch
8172 )
8173 {
8174 // v2 is too tangled to break into stages, so just execute everything under lock
8175 dc_exit_ips_for_hw_access(scratch->dc);
8176 return update_planes_and_stream_v2(
8177 scratch->dc,
8178 scratch->surface_updates,
8179 scratch->surface_count,
8180 scratch->stream,
8181 scratch->stream_update
8182 );
8183 }
8184
update_planes_and_stream_execute_v2(const struct dc_update_scratch_space * scratch)8185 static void update_planes_and_stream_execute_v2(
8186 const struct dc_update_scratch_space *scratch
8187 )
8188 {
8189 // Nothing to do, see `update_planes_and_stream_prepare_v2`
8190 (void) scratch;
8191 }
8192
update_planes_and_stream_cleanup_v2(const struct dc_update_scratch_space * scratch)8193 static bool update_planes_and_stream_cleanup_v2(
8194 const struct dc_update_scratch_space *scratch
8195 )
8196 {
8197 if (scratch->do_clear_update_bits)
8198 clear_update_bits(scratch->surface_updates, scratch->surface_count, scratch->stream);
8199
8200 return false;
8201 }
8202
8203 static void update_planes_and_stream_cleanup_v3_release_minimal(
8204 struct dc_update_scratch_space *scratch,
8205 bool backup
8206 );
8207
update_planes_and_stream_prepare_v3_intermediate_seamless(struct dc_update_scratch_space * scratch)8208 static bool update_planes_and_stream_prepare_v3_intermediate_seamless(
8209 struct dc_update_scratch_space *scratch
8210 )
8211 {
8212 return is_pipe_topology_transition_seamless_with_intermediate_step(
8213 scratch->dc,
8214 scratch->dc->current_state,
8215 scratch->intermediate_context,
8216 scratch->new_context
8217 );
8218 }
8219
transition_countdown_init(struct dc * dc)8220 static void transition_countdown_init(struct dc *dc)
8221 {
8222 dc->check_config.transition_countdown_to_steady_state =
8223 dc->debug.num_fast_flips_to_steady_state_override ?
8224 dc->debug.num_fast_flips_to_steady_state_override :
8225 NUM_FAST_FLIPS_TO_STEADY_STATE;
8226 }
8227
update_planes_and_stream_prepare_v3(struct dc_update_scratch_space * scratch)8228 static bool update_planes_and_stream_prepare_v3(
8229 struct dc_update_scratch_space *scratch
8230 )
8231 {
8232 if (scratch->flow == UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS) {
8233 return true;
8234 }
8235 ASSERT(scratch->flow == UPDATE_V3_FLOW_INVALID);
8236 dc_exit_ips_for_hw_access(scratch->dc);
8237
8238 /* HWSS path determination needs to be done prior to updating the surface and stream states. */
8239 struct dc_fast_update fast_update[MAX_SURFACES] = { 0 };
8240
8241 populate_fast_updates(fast_update,
8242 scratch->surface_updates,
8243 scratch->surface_count,
8244 scratch->stream_update);
8245
8246 const bool is_hwss_fast_path_only =
8247 fast_update_only(scratch->dc,
8248 fast_update,
8249 scratch->surface_updates,
8250 scratch->surface_count,
8251 scratch->stream_update,
8252 scratch->stream) &&
8253 !scratch->dc->check_config.enable_legacy_fast_update;
8254
8255 if (!update_planes_and_stream_state(
8256 scratch->dc,
8257 scratch->surface_updates,
8258 scratch->surface_count,
8259 scratch->stream,
8260 scratch->stream_update,
8261 &scratch->update_type,
8262 &scratch->new_context
8263 )) {
8264 return false;
8265 }
8266
8267 if (scratch->new_context == scratch->dc->current_state) {
8268 ASSERT(scratch->update_type < UPDATE_TYPE_FULL);
8269
8270 scratch->flow = is_hwss_fast_path_only
8271 ? UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FAST
8272 : UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FULL;
8273 return true;
8274 }
8275
8276 ASSERT(scratch->update_type >= UPDATE_TYPE_FULL);
8277
8278 const bool seamless = scratch->dc->hwss.is_pipe_topology_transition_seamless(
8279 scratch->dc,
8280 scratch->dc->current_state,
8281 scratch->new_context
8282 );
8283 if (seamless) {
8284 scratch->flow = UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS;
8285 if (scratch->dc->check_config.deferred_transition_state)
8286 /* reset countdown as steady state not reached */
8287 transition_countdown_init(scratch->dc);
8288 return true;
8289 }
8290
8291 if (!scratch->dc->debug.disable_deferred_minimal_transitions) {
8292 scratch->dc->check_config.deferred_transition_state = true;
8293 transition_countdown_init(scratch->dc);
8294 }
8295
8296 scratch->intermediate_context = create_minimal_transition_state(
8297 scratch->dc,
8298 scratch->new_context,
8299 &scratch->intermediate_policy
8300 );
8301 if (scratch->intermediate_context) {
8302 if (update_planes_and_stream_prepare_v3_intermediate_seamless(scratch)) {
8303 scratch->flow = UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_NEW;
8304 return true;
8305 }
8306
8307 update_planes_and_stream_cleanup_v3_release_minimal(scratch, false);
8308 }
8309
8310 scratch->backup_context = scratch->dc->current_state;
8311 restore_planes_and_stream_state(&scratch->dc->scratch.current_state, scratch->stream);
8312 dc_state_retain(scratch->backup_context);
8313 scratch->intermediate_context = create_minimal_transition_state(
8314 scratch->dc,
8315 scratch->backup_context,
8316 &scratch->intermediate_policy
8317 );
8318 if (scratch->intermediate_context) {
8319 if (update_planes_and_stream_prepare_v3_intermediate_seamless(scratch)) {
8320 scratch->flow = UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_CURRENT;
8321 scratch->intermediate_count = initialize_empty_surface_updates(
8322 scratch->stream, scratch->intermediate_updates
8323 );
8324 return true;
8325 }
8326
8327 update_planes_and_stream_cleanup_v3_release_minimal(scratch, true);
8328 }
8329
8330 scratch->flow = UPDATE_V3_FLOW_INVALID;
8331 dc_state_release(scratch->backup_context);
8332 restore_planes_and_stream_state(&scratch->dc->scratch.new_state, scratch->stream);
8333 return false;
8334 }
8335
8336 /**
8337 * should_commit_intermediate_context - Does this flow commit a transient
8338 * minimal-transition intermediate context
8339 * @flow: the commit flow selected for this iteration
8340 *
8341 * Return: true if this iteration commits the intermediate context.
8342 */
should_commit_intermediate_context(enum update_v3_flow flow)8343 static bool should_commit_intermediate_context(enum update_v3_flow flow)
8344 {
8345 return flow == UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_NEW
8346 || flow == UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_CURRENT;
8347 }
8348
update_planes_and_stream_execute_v3_commit(const struct dc_update_scratch_space * scratch,bool intermediate_update,bool intermediate_context,bool use_stream_update)8349 static void update_planes_and_stream_execute_v3_commit(
8350 const struct dc_update_scratch_space *scratch,
8351 bool intermediate_update,
8352 bool intermediate_context,
8353 bool use_stream_update
8354 )
8355 {
8356 commit_planes_for_stream(
8357 scratch->dc,
8358 intermediate_update ? scratch->intermediate_updates : scratch->surface_updates,
8359 intermediate_update ? scratch->intermediate_count : scratch->surface_count,
8360 scratch->stream,
8361 use_stream_update ? scratch->stream_update : NULL,
8362 intermediate_context ? UPDATE_TYPE_FULL : scratch->update_type,
8363 // `dc->current_state` only used in `NO_NEW_CONTEXT`, where it is equal to `new_context`
8364 intermediate_context ? scratch->intermediate_context : scratch->new_context
8365 );
8366 }
8367
update_planes_and_stream_execute_v3(const struct dc_update_scratch_space * scratch)8368 static void update_planes_and_stream_execute_v3(
8369 const struct dc_update_scratch_space *scratch
8370 )
8371 {
8372 bool intermediate_context = should_commit_intermediate_context(scratch->flow);
8373
8374 switch (scratch->flow) {
8375 case UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FAST:
8376 commit_planes_for_stream_fast(
8377 scratch->dc,
8378 scratch->surface_updates,
8379 scratch->surface_count,
8380 scratch->stream,
8381 scratch->stream_update,
8382 scratch->update_type,
8383 scratch->new_context
8384 );
8385 break;
8386
8387 case UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FULL:
8388 case UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS:
8389 update_planes_and_stream_execute_v3_commit(scratch, false, intermediate_context, true);
8390 break;
8391
8392 case UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_NEW:
8393 update_planes_and_stream_execute_v3_commit(scratch, false, intermediate_context,
8394 scratch->dc->check_config.deferred_transition_state);
8395 break;
8396
8397 case UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_CURRENT:
8398 update_planes_and_stream_execute_v3_commit(scratch, true, intermediate_context, false);
8399 break;
8400
8401 case UPDATE_V3_FLOW_INVALID:
8402 default:
8403 ASSERT(false);
8404 }
8405 }
8406
update_planes_and_stream_cleanup_v3_release_minimal(struct dc_update_scratch_space * scratch,bool backup)8407 static void update_planes_and_stream_cleanup_v3_release_minimal(
8408 struct dc_update_scratch_space *scratch,
8409 bool backup
8410 )
8411 {
8412 release_minimal_transition_state(
8413 scratch->dc,
8414 scratch->intermediate_context,
8415 backup ? scratch->backup_context : scratch->new_context,
8416 &scratch->intermediate_policy
8417 );
8418 }
8419
update_planes_and_stream_cleanup_v3_intermediate(struct dc_update_scratch_space * scratch,bool backup)8420 static void update_planes_and_stream_cleanup_v3_intermediate(
8421 struct dc_update_scratch_space *scratch,
8422 bool backup
8423 )
8424 {
8425 swap_and_release_current_context(scratch->dc, scratch->intermediate_context, scratch->stream);
8426 dc_state_retain(scratch->dc->current_state);
8427 update_planes_and_stream_cleanup_v3_release_minimal(scratch, backup);
8428 }
8429
update_planes_and_stream_cleanup_v3(struct dc_update_scratch_space * scratch)8430 static bool update_planes_and_stream_cleanup_v3(
8431 struct dc_update_scratch_space *scratch
8432 )
8433 {
8434 switch (scratch->flow) {
8435 case UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FAST:
8436 case UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FULL:
8437 if (scratch->dc->check_config.transition_countdown_to_steady_state)
8438 scratch->dc->check_config.transition_countdown_to_steady_state--;
8439 break;
8440
8441 case UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS:
8442 swap_and_release_current_context(scratch->dc, scratch->new_context, scratch->stream);
8443 break;
8444
8445 case UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_NEW:
8446 update_planes_and_stream_cleanup_v3_intermediate(scratch, false);
8447 if (scratch->dc->check_config.deferred_transition_state) {
8448 dc_state_release(scratch->new_context);
8449 } else {
8450 scratch->flow = UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS;
8451 return true;
8452 }
8453 break;
8454
8455 case UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_CURRENT:
8456 update_planes_and_stream_cleanup_v3_intermediate(scratch, true);
8457 dc_state_release(scratch->backup_context);
8458 restore_planes_and_stream_state(&scratch->dc->scratch.new_state, scratch->stream);
8459 scratch->flow = UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS;
8460 return true;
8461
8462 case UPDATE_V3_FLOW_INVALID:
8463 default:
8464 ASSERT(false);
8465 }
8466
8467 if (scratch->do_clear_update_bits)
8468 clear_update_bits(scratch->surface_updates, scratch->surface_count, scratch->stream);
8469
8470 return false;
8471 }
8472
dc_update_state_init(struct dc * dc,const struct dc_state_update * updates)8473 struct dc_update_scratch_space *dc_update_state_init(
8474 struct dc *dc,
8475 const struct dc_state_update *updates
8476 )
8477 {
8478 const enum dce_version version = dc->ctx->dce_version;
8479 struct dc_update_scratch_space *scratch = dc_update_scratch_acquire(dc);
8480 const bool has_stream_or_plane = updates->stream || updates->stream_update || updates->surface_updates;
8481 const bool has_probe = updates->probe_updates;
8482 const bool surface_without_stream = updates->surface_updates && !updates->stream;
8483 const bool stream_update_without_stream = updates->stream_update && !updates->stream;
8484 const bool bad_surface_count = updates->surface_count > 0 && !updates->surface_updates;
8485
8486 if (!scratch)
8487 return NULL;
8488
8489 if (!has_stream_or_plane && !has_probe) {
8490 dc_update_scratch_release(dc, scratch);
8491 return NULL;
8492 }
8493
8494 if (surface_without_stream || stream_update_without_stream || bad_surface_count) {
8495 dc_update_scratch_release(dc, scratch);
8496 return NULL;
8497 }
8498
8499 *scratch = (struct dc_update_scratch_space){
8500 .dc = dc,
8501 .surface_updates = updates->surface_updates,
8502 .surface_count = updates->surface_count,
8503 .stream = updates->stream,
8504 .stream_update = updates->stream_update,
8505 .probe_updates = updates->probe_updates,
8506 .update_v3 = version >= DCN_VERSION_4_01
8507 || version == DCN_VERSION_3_2
8508 || version == DCN_VERSION_3_21,
8509 .do_clear_update_bits = version >= DCN_VERSION_1_0,
8510 .new_context = NULL,
8511 .flow = UPDATE_V3_FLOW_INVALID,
8512 };
8513
8514 return scratch;
8515 }
8516
8517 /**
8518 * dc_update_probes_prepare - Commit the desired probe set into new_context.
8519 * @scratch: commit scratch carrying the probe updates
8520 *
8521 * Return: true on success or when there is nothing to do; false when the
8522 * desired set is unachievable.
8523 */
dc_update_probes_prepare(struct dc_update_scratch_space * scratch)8524 static bool dc_update_probes_prepare(struct dc_update_scratch_space *scratch)
8525 {
8526 struct dc *dc = scratch->dc;
8527 const struct dc_probe_updates *probe_updates = scratch->probe_updates;
8528 uint8_t i;
8529
8530 if (!probe_updates)
8531 return true;
8532
8533 if (resource_validate_probe_set(dc, probe_updates->probes,
8534 (uint8_t)probe_updates->probe_count) != DC_OK)
8535 return false;
8536
8537 if (!scratch->new_context)
8538 scratch->new_context = dc->current_state;
8539
8540 for (i = 0; i < probe_updates->probe_count && i < MAX_PROBES; i++)
8541 scratch->new_context->probes[i] = probe_updates->probes[i];
8542 scratch->new_context->probe_count = probe_updates->probe_count;
8543
8544 return true;
8545 }
8546
8547 /**
8548 * dc_update_probes_execute - Program the committed probes.
8549 * @scratch: commit scratch carrying the probe updates
8550 *
8551 */
dc_update_probes_execute(const struct dc_update_scratch_space * scratch)8552 static void dc_update_probes_execute(const struct dc_update_scratch_space *scratch)
8553 {
8554 struct dc *dc = scratch->dc;
8555
8556 if (should_commit_intermediate_context(scratch->flow))
8557 return;
8558
8559 if (dc->hwss.program_perfmon)
8560 dc->hwss.program_perfmon(dc, scratch->new_context);
8561 }
8562
dc_update_state_prepare(struct dc_update_scratch_space * scratch)8563 bool dc_update_state_prepare(struct dc_update_scratch_space *scratch)
8564 {
8565 if (scratch->stream) {
8566 bool ok = scratch->update_v3
8567 ? update_planes_and_stream_prepare_v3(scratch)
8568 : update_planes_and_stream_prepare_v2(scratch);
8569
8570 if (!ok)
8571 goto release_scratch;
8572 }
8573
8574 if (!dc_update_probes_prepare(scratch))
8575 goto release_scratch;
8576
8577 return true;
8578
8579 release_scratch:
8580 /* execute and cleanup never run on this path, so release here. */
8581 dc_update_scratch_release(scratch->dc, scratch);
8582 return false;
8583 }
8584
dc_update_state_execute(const struct dc_update_scratch_space * scratch)8585 void dc_update_state_execute(
8586 const struct dc_update_scratch_space *scratch
8587 )
8588 {
8589 if (scratch->stream)
8590 scratch->update_v3
8591 ? update_planes_and_stream_execute_v3(scratch)
8592 : update_planes_and_stream_execute_v2(scratch);
8593
8594 if (scratch->probe_updates)
8595 dc_update_probes_execute(scratch);
8596 }
8597
dc_update_state_cleanup(struct dc_update_scratch_space * scratch)8598 bool dc_update_state_cleanup(
8599 struct dc_update_scratch_space *scratch
8600 )
8601 {
8602 bool more = false;
8603
8604 if (scratch->stream)
8605 more = scratch->update_v3
8606 ? update_planes_and_stream_cleanup_v3(scratch)
8607 : update_planes_and_stream_cleanup_v2(scratch);
8608
8609 if (!more)
8610 dc_update_scratch_release(scratch->dc, scratch);
8611
8612 return more;
8613 }
8614
8615