forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
kernel/drivers/gpu/drm/amd/display/dc/core/dc.c
....@@ -22,6 +22,9 @@
2222 * Authors: AMD
2323 */
2424
25
+#include <linux/slab.h>
26
+#include <linux/mm.h>
27
+
2528 #include "dm_services.h"
2629
2730 #include "dc.h"
....@@ -33,6 +36,7 @@
3336
3437 #include "resource.h"
3538
39
+#include "clk_mgr.h"
3640 #include "clock_source.h"
3741 #include "dc_bios_types.h"
3842
....@@ -54,9 +58,74 @@
5458 #include "hubp.h"
5559
5660 #include "dc_link_dp.h"
61
+#include "dc_dmub_srv.h"
62
+
63
+#include "dsc.h"
64
+
65
+#include "vm_helper.h"
66
+
67
+#include "dce/dce_i2c.h"
68
+
69
+#include "dmub/dmub_srv.h"
70
+
71
+#include "dce/dmub_hw_lock_mgr.h"
72
+
73
+#define CTX \
74
+ dc->ctx
75
+
5776 #define DC_LOGGER \
5877 dc->ctx->logger
5978
79
+static const char DC_BUILD_ID[] = "production-build";
80
+
81
+/**
82
+ * DOC: Overview
83
+ *
84
+ * DC is the OS-agnostic component of the amdgpu DC driver.
85
+ *
86
+ * DC maintains and validates a set of structs representing the state of the
87
+ * driver and writes that state to AMD hardware
88
+ *
89
+ * Main DC HW structs:
90
+ *
91
+ * struct dc - The central struct. One per driver. Created on driver load,
92
+ * destroyed on driver unload.
93
+ *
94
+ * struct dc_context - One per driver.
95
+ * Used as a backpointer by most other structs in dc.
96
+ *
97
+ * struct dc_link - One per connector (the physical DP, HDMI, miniDP, or eDP
98
+ * plugpoints). Created on driver load, destroyed on driver unload.
99
+ *
100
+ * struct dc_sink - One per display. Created on boot or hotplug.
101
+ * Destroyed on shutdown or hotunplug. A dc_link can have a local sink
102
+ * (the display directly attached). It may also have one or more remote
103
+ * sinks (in the Multi-Stream Transport case)
104
+ *
105
+ * struct resource_pool - One per driver. Represents the hw blocks not in the
106
+ * main pipeline. Not directly accessible by dm.
107
+ *
108
+ * Main dc state structs:
109
+ *
110
+ * These structs can be created and destroyed as needed. There is a full set of
111
+ * these structs in dc->current_state representing the currently programmed state.
112
+ *
113
+ * struct dc_state - The global DC state to track global state information,
114
+ * such as bandwidth values.
115
+ *
116
+ * struct dc_stream_state - Represents the hw configuration for the pipeline from
117
+ * a framebuffer to a display. Maps one-to-one with dc_sink.
118
+ *
119
+ * struct dc_plane_state - Represents a framebuffer. Each stream has at least one,
120
+ * and may have more in the Multi-Plane Overlay case.
121
+ *
122
+ * struct resource_context - Represents the programmable state of everything in
123
+ * the resource_pool. Not directly accessible by dm.
124
+ *
125
+ * struct pipe_ctx - A member of struct resource_context. Represents the
126
+ * internal hardware pipeline components. Each dc_plane_state has either
127
+ * one or two (in the pipe-split case).
128
+ */
60129
61130 /*******************************************************************************
62131 * Private functions
....@@ -98,10 +167,6 @@
98167 return false;
99168 }
100169
101
- if (connectors_num == 0 && num_virtual_links == 0) {
102
- dm_error("DC: Number of connectors is zero!\n");
103
- }
104
-
105170 dm_output_to_console(
106171 "DC: %s: connectors_num: physical:%d, virtual:%d\n",
107172 __func__,
....@@ -120,9 +185,27 @@
120185 link = link_create(&link_init_params);
121186
122187 if (link) {
123
- dc->links[dc->link_count] = link;
124
- link->dc = dc;
125
- ++dc->link_count;
188
+ bool should_destory_link = false;
189
+
190
+ if (link->connector_signal == SIGNAL_TYPE_EDP) {
191
+ if (dc->config.edp_not_connected) {
192
+ if (!IS_DIAG_DC(dc->ctx->dce_environment))
193
+ should_destory_link = true;
194
+ } else {
195
+ enum dc_connection_type type;
196
+ dc_link_detect_sink(link, &type);
197
+ if (type == dc_connection_none)
198
+ should_destory_link = true;
199
+ }
200
+ }
201
+
202
+ if (dc->config.force_enum_edp || !should_destory_link) {
203
+ dc->links[dc->link_count] = link;
204
+ link->dc = dc;
205
+ ++dc->link_count;
206
+ } else {
207
+ link_destroy(&link);
208
+ }
126209 }
127210 }
128211
....@@ -171,6 +254,17 @@
171254 return false;
172255 }
173256
257
+static struct dc_perf_trace *dc_perf_trace_create(void)
258
+{
259
+ return kzalloc(sizeof(struct dc_perf_trace), GFP_KERNEL);
260
+}
261
+
262
+static void dc_perf_trace_destroy(struct dc_perf_trace **perf_trace)
263
+{
264
+ kfree(*perf_trace);
265
+ *perf_trace = NULL;
266
+}
267
+
174268 /**
175269 *****************************************************************************
176270 * Function: dc_stream_adjust_vmin_vmax
....@@ -188,23 +282,24 @@
188282 *****************************************************************************
189283 */
190284 bool dc_stream_adjust_vmin_vmax(struct dc *dc,
191
- struct dc_stream_state **streams, int num_streams,
192
- int vmin, int vmax)
285
+ struct dc_stream_state *stream,
286
+ struct dc_crtc_timing_adjust *adjust)
193287 {
194
- /* TODO: Support multiple streams */
195
- struct dc_stream_state *stream = streams[0];
196288 int i = 0;
197289 bool ret = false;
290
+
291
+ stream->adjust = *adjust;
198292
199293 for (i = 0; i < MAX_PIPES; i++) {
200294 struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
201295
202
- if (pipe->stream == stream && pipe->stream_res.stream_enc) {
203
- dc->hwss.set_drr(&pipe, 1, vmin, vmax);
204
-
205
- /* build and update the info frame */
206
- resource_build_info_frame(pipe);
207
- dc->hwss.update_info_frame(pipe);
296
+ if (pipe->stream == stream && pipe->stream_res.tg) {
297
+ dc->hwss.set_drr(&pipe,
298
+ 1,
299
+ adjust->v_total_min,
300
+ adjust->v_total_max,
301
+ adjust->v_total_mid,
302
+ adjust->v_total_mid_frame_num);
208303
209304 ret = true;
210305 }
....@@ -217,7 +312,7 @@
217312 unsigned int *v_pos, unsigned int *nom_v_pos)
218313 {
219314 /* TODO: Support multiple streams */
220
- struct dc_stream_state *stream = streams[0];
315
+ const struct dc_stream_state *stream = streams[0];
221316 int i = 0;
222317 bool ret = false;
223318 struct crtc_position position;
....@@ -238,7 +333,7 @@
238333 }
239334
240335 /**
241
- * dc_stream_configure_crc: Configure CRC capture for the given stream.
336
+ * dc_stream_configure_crc() - Configure CRC capture for the given stream.
242337 * @dc: DC Object
243338 * @stream: The stream to configure CRC on.
244339 * @enable: Enable CRC if true, disable otherwise.
....@@ -258,7 +353,7 @@
258353
259354 for (i = 0; i < MAX_PIPES; i++) {
260355 pipe = &dc->current_state->res_ctx.pipe_ctx[i];
261
- if (pipe->stream == stream)
356
+ if (pipe->stream == stream && !pipe->top_pipe && !pipe->prev_odm_pipe)
262357 break;
263358 }
264359 /* Stream not found */
....@@ -275,6 +370,9 @@
275370 param.windowb_x_end = pipe->stream->timing.h_addressable;
276371 param.windowb_y_end = pipe->stream->timing.v_addressable;
277372
373
+ param.dsc_mode = pipe->stream->timing.flags.DSC ? 1:0;
374
+ param.odm_mode = pipe->next_odm_pipe ? 1:0;
375
+
278376 /* Default to the union of both windows */
279377 param.selection = UNION_WINDOW_A_B;
280378 param.continuous_mode = continuous;
....@@ -290,7 +388,7 @@
290388 }
291389
292390 /**
293
- * dc_stream_get_crc: Get CRC values for the given stream.
391
+ * dc_stream_get_crc() - Get CRC values for the given stream.
294392 * @dc: DC object
295393 * @stream: The DC stream state of the stream to get CRCs from.
296394 * @r_cr, g_y, b_cb: CRC values for the three channels are stored here.
....@@ -322,11 +420,32 @@
322420 return false;
323421 }
324422
423
+void dc_stream_set_dyn_expansion(struct dc *dc, struct dc_stream_state *stream,
424
+ enum dc_dynamic_expansion option)
425
+{
426
+ /* OPP FMT dyn expansion updates*/
427
+ int i = 0;
428
+ struct pipe_ctx *pipe_ctx;
429
+
430
+ for (i = 0; i < MAX_PIPES; i++) {
431
+ if (dc->current_state->res_ctx.pipe_ctx[i].stream
432
+ == stream) {
433
+ pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
434
+ pipe_ctx->stream_res.opp->dyn_expansion = option;
435
+ pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion(
436
+ pipe_ctx->stream_res.opp,
437
+ COLOR_SPACE_YCBCR601,
438
+ stream->timing.display_color_depth,
439
+ stream->signal);
440
+ }
441
+ }
442
+}
443
+
325444 void dc_stream_set_dither_option(struct dc_stream_state *stream,
326445 enum dc_dither_option option)
327446 {
328447 struct bit_depth_reduction_params params;
329
- struct dc_link *link = stream->status.link;
448
+ struct dc_link *link = stream->link;
330449 struct pipe_ctx *pipes = NULL;
331450 int i;
332451
....@@ -361,10 +480,50 @@
361480 opp_program_bit_depth_reduction(pipes->stream_res.opp, &params);
362481 }
363482
364
-void dc_stream_set_static_screen_events(struct dc *dc,
483
+bool dc_stream_set_gamut_remap(struct dc *dc, const struct dc_stream_state *stream)
484
+{
485
+ int i = 0;
486
+ bool ret = false;
487
+ struct pipe_ctx *pipes;
488
+
489
+ for (i = 0; i < MAX_PIPES; i++) {
490
+ if (dc->current_state->res_ctx.pipe_ctx[i].stream == stream) {
491
+ pipes = &dc->current_state->res_ctx.pipe_ctx[i];
492
+ dc->hwss.program_gamut_remap(pipes);
493
+ ret = true;
494
+ }
495
+ }
496
+
497
+ return ret;
498
+}
499
+
500
+bool dc_stream_program_csc_matrix(struct dc *dc, struct dc_stream_state *stream)
501
+{
502
+ int i = 0;
503
+ bool ret = false;
504
+ struct pipe_ctx *pipes;
505
+
506
+ for (i = 0; i < MAX_PIPES; i++) {
507
+ if (dc->current_state->res_ctx.pipe_ctx[i].stream
508
+ == stream) {
509
+
510
+ pipes = &dc->current_state->res_ctx.pipe_ctx[i];
511
+ dc->hwss.program_output_csc(dc,
512
+ pipes,
513
+ stream->output_color_space,
514
+ stream->csc_color_matrix.matrix,
515
+ pipes->stream_res.opp->inst);
516
+ ret = true;
517
+ }
518
+ }
519
+
520
+ return ret;
521
+}
522
+
523
+void dc_stream_set_static_screen_params(struct dc *dc,
365524 struct dc_stream_state **streams,
366525 int num_streams,
367
- const struct dc_static_screen_events *events)
526
+ const struct dc_static_screen_params *params)
368527 {
369528 int i = 0;
370529 int j = 0;
....@@ -383,84 +542,10 @@
383542 }
384543 }
385544
386
- dc->hwss.set_static_screen_control(pipes_affected, num_pipes_affected, events);
545
+ dc->hwss.set_static_screen_control(pipes_affected, num_pipes_affected, params);
387546 }
388547
389
-void dc_link_set_drive_settings(struct dc *dc,
390
- struct link_training_settings *lt_settings,
391
- const struct dc_link *link)
392
-{
393
-
394
- int i;
395
-
396
- for (i = 0; i < dc->link_count; i++) {
397
- if (dc->links[i] == link)
398
- break;
399
- }
400
-
401
- if (i >= dc->link_count)
402
- ASSERT_CRITICAL(false);
403
-
404
- dc_link_dp_set_drive_settings(dc->links[i], lt_settings);
405
-}
406
-
407
-void dc_link_perform_link_training(struct dc *dc,
408
- struct dc_link_settings *link_setting,
409
- bool skip_video_pattern)
410
-{
411
- int i;
412
-
413
- for (i = 0; i < dc->link_count; i++)
414
- dc_link_dp_perform_link_training(
415
- dc->links[i],
416
- link_setting,
417
- skip_video_pattern);
418
-}
419
-
420
-void dc_link_set_preferred_link_settings(struct dc *dc,
421
- struct dc_link_settings *link_setting,
422
- struct dc_link *link)
423
-{
424
- struct dc_link_settings store_settings = *link_setting;
425
- struct dc_stream_state *link_stream =
426
- link->dc->current_state->res_ctx.pipe_ctx[0].stream;
427
-
428
- link->preferred_link_setting = store_settings;
429
- if (link_stream)
430
- decide_link_settings(link_stream, &store_settings);
431
-
432
- if ((store_settings.lane_count != LANE_COUNT_UNKNOWN) &&
433
- (store_settings.link_rate != LINK_RATE_UNKNOWN))
434
- dp_retrain_link_dp_test(link, &store_settings, false);
435
-}
436
-
437
-void dc_link_enable_hpd(const struct dc_link *link)
438
-{
439
- dc_link_dp_enable_hpd(link);
440
-}
441
-
442
-void dc_link_disable_hpd(const struct dc_link *link)
443
-{
444
- dc_link_dp_disable_hpd(link);
445
-}
446
-
447
-
448
-void dc_link_set_test_pattern(struct dc_link *link,
449
- enum dp_test_pattern test_pattern,
450
- const struct link_training_settings *p_link_settings,
451
- const unsigned char *p_custom_pattern,
452
- unsigned int cust_pattern_size)
453
-{
454
- if (link != NULL)
455
- dc_link_dp_set_test_pattern(
456
- link,
457
- test_pattern,
458
- p_link_settings,
459
- p_custom_pattern,
460
- cust_pattern_size);
461
-}
462
-
463
-static void destruct(struct dc *dc)
548
+static void dc_destruct(struct dc *dc)
464549 {
465550 if (dc->current_state) {
466551 dc_release_state(dc->current_state);
....@@ -469,16 +554,20 @@
469554
470555 destroy_links(dc);
471556
557
+ if (dc->clk_mgr) {
558
+ dc_destroy_clk_mgr(dc->clk_mgr);
559
+ dc->clk_mgr = NULL;
560
+ }
561
+
472562 dc_destroy_resource_pool(dc);
473563
474564 if (dc->ctx->gpio_service)
475565 dal_gpio_service_destroy(&dc->ctx->gpio_service);
476566
477
- if (dc->ctx->i2caux)
478
- dal_i2caux_destroy(&dc->ctx->i2caux);
479
-
480567 if (dc->ctx->created_bios)
481568 dal_bios_parser_destroy(&dc->ctx->dc_bios);
569
+
570
+ dc_perf_trace_destroy(&dc->ctx->perf_trace);
482571
483572 kfree(dc->ctx);
484573 dc->ctx = NULL;
....@@ -489,7 +578,7 @@
489578 kfree(dc->bw_dceip);
490579 dc->bw_dceip = NULL;
491580
492
-#ifdef CONFIG_DRM_AMD_DC_DCN1_0
581
+#ifdef CONFIG_DRM_AMD_DC_DCN
493582 kfree(dc->dcn_soc);
494583 dc->dcn_soc = NULL;
495584
....@@ -497,20 +586,66 @@
497586 dc->dcn_ip = NULL;
498587
499588 #endif
589
+ kfree(dc->vm_helper);
590
+ dc->vm_helper = NULL;
591
+
500592 }
501593
502
-static bool construct(struct dc *dc,
594
+static bool dc_construct_ctx(struct dc *dc,
595
+ const struct dc_init_data *init_params)
596
+{
597
+ struct dc_context *dc_ctx;
598
+ enum dce_version dc_version = DCE_VERSION_UNKNOWN;
599
+
600
+ dc_ctx = kzalloc(sizeof(*dc_ctx), GFP_KERNEL);
601
+ if (!dc_ctx)
602
+ return false;
603
+
604
+ dc_ctx->cgs_device = init_params->cgs_device;
605
+ dc_ctx->driver_context = init_params->driver;
606
+ dc_ctx->dc = dc;
607
+ dc_ctx->asic_id = init_params->asic_id;
608
+ dc_ctx->dc_sink_id_count = 0;
609
+ dc_ctx->dc_stream_id_count = 0;
610
+ dc_ctx->dce_environment = init_params->dce_environment;
611
+
612
+ /* Create logger */
613
+
614
+ dc_version = resource_parse_asic_id(init_params->asic_id);
615
+ dc_ctx->dce_version = dc_version;
616
+
617
+ dc_ctx->perf_trace = dc_perf_trace_create();
618
+ if (!dc_ctx->perf_trace) {
619
+ ASSERT_CRITICAL(false);
620
+ return false;
621
+ }
622
+
623
+ dc->ctx = dc_ctx;
624
+
625
+ return true;
626
+}
627
+
628
+static bool dc_construct(struct dc *dc,
503629 const struct dc_init_data *init_params)
504630 {
505631 struct dc_context *dc_ctx;
506632 struct bw_calcs_dceip *dc_dceip;
507633 struct bw_calcs_vbios *dc_vbios;
508
-#ifdef CONFIG_DRM_AMD_DC_DCN1_0
634
+#ifdef CONFIG_DRM_AMD_DC_DCN
509635 struct dcn_soc_bounding_box *dcn_soc;
510636 struct dcn_ip_params *dcn_ip;
511637 #endif
512638
513
- enum dce_version dc_version = DCE_VERSION_UNKNOWN;
639
+ dc->config = init_params->flags;
640
+
641
+ // Allocate memory for the vm_helper
642
+ dc->vm_helper = kzalloc(sizeof(struct vm_helper), GFP_KERNEL);
643
+ if (!dc->vm_helper) {
644
+ dm_error("%s: failed to create dc->vm_helper\n", __func__);
645
+ goto fail;
646
+ }
647
+
648
+ memcpy(&dc->bb_overrides, &init_params->bb_overrides, sizeof(dc->bb_overrides));
514649
515650 dc_dceip = kzalloc(sizeof(*dc_dceip), GFP_KERNEL);
516651 if (!dc_dceip) {
....@@ -527,7 +662,7 @@
527662 }
528663
529664 dc->bw_vbios = dc_vbios;
530
-#ifdef CONFIG_DRM_AMD_DC_DCN1_0
665
+#ifdef CONFIG_DRM_AMD_DC_DCN
531666 dcn_soc = kzalloc(sizeof(*dcn_soc), GFP_KERNEL);
532667 if (!dcn_soc) {
533668 dm_error("%s: failed to create dcn_soc\n", __func__);
....@@ -543,34 +678,15 @@
543678 }
544679
545680 dc->dcn_ip = dcn_ip;
681
+ dc->soc_bounding_box = init_params->soc_bounding_box;
546682 #endif
547683
548
- dc_ctx = kzalloc(sizeof(*dc_ctx), GFP_KERNEL);
549
- if (!dc_ctx) {
684
+ if (!dc_construct_ctx(dc, init_params)) {
550685 dm_error("%s: failed to create ctx\n", __func__);
551686 goto fail;
552687 }
553688
554
- dc_ctx->cgs_device = init_params->cgs_device;
555
- dc_ctx->driver_context = init_params->driver;
556
- dc_ctx->dc = dc;
557
- dc_ctx->asic_id = init_params->asic_id;
558
- dc_ctx->dc_sink_id_count = 0;
559
- dc->ctx = dc_ctx;
560
-
561
- dc->current_state = dc_create_state();
562
-
563
- if (!dc->current_state) {
564
- dm_error("%s: failed to create validate ctx\n", __func__);
565
- goto fail;
566
- }
567
-
568
- /* Create logger */
569
-
570
- dc_ctx->dce_environment = init_params->dce_environment;
571
-
572
- dc_version = resource_parse_asic_id(init_params->asic_id);
573
- dc_ctx->dce_version = dc_version;
689
+ dc_ctx = dc->ctx;
574690
575691 /* Resource should construct all asic specific resources.
576692 * This should be the only place where we need to parse the asic id
....@@ -585,7 +701,7 @@
585701 bp_init_data.bios = init_params->asic_id.atombios_base_address;
586702
587703 dc_ctx->dc_bios = dal_bios_parser_create(
588
- &bp_init_data, dc_version);
704
+ &bp_init_data, dc_ctx->dce_version);
589705
590706 if (!dc_ctx->dc_bios) {
591707 ASSERT_CRITICAL(false);
....@@ -593,19 +709,13 @@
593709 }
594710
595711 dc_ctx->created_bios = true;
596
- }
597
-
598
- /* Create I2C AUX */
599
- dc_ctx->i2caux = dal_i2caux_create(dc_ctx);
600
-
601
- if (!dc_ctx->i2caux) {
602
- ASSERT_CRITICAL(false);
603
- goto fail;
604712 }
713
+
714
+ dc->vendor_signature = init_params->vendor_signature;
605715
606716 /* Create GPIO service */
607717 dc_ctx->gpio_service = dal_gpio_service_create(
608
- dc_version,
718
+ dc_ctx->dce_version,
609719 dc_ctx->dce_environment,
610720 dc_ctx);
611721
....@@ -614,13 +724,33 @@
614724 goto fail;
615725 }
616726
617
- dc->res_pool = dc_create_resource_pool(
618
- dc,
619
- init_params->num_virtual_links,
620
- dc_version,
621
- init_params->asic_id);
727
+ dc->res_pool = dc_create_resource_pool(dc, init_params, dc_ctx->dce_version);
622728 if (!dc->res_pool)
623729 goto fail;
730
+
731
+ dc->clk_mgr = dc_clk_mgr_create(dc->ctx, dc->res_pool->pp_smu, dc->res_pool->dccg);
732
+ if (!dc->clk_mgr)
733
+ goto fail;
734
+#ifdef CONFIG_DRM_AMD_DC_DCN3_0
735
+ dc->clk_mgr->force_smu_not_present = init_params->force_smu_not_present;
736
+#endif
737
+
738
+ dc->debug.force_ignore_link_settings = init_params->force_ignore_link_settings;
739
+
740
+ if (dc->res_pool->funcs->update_bw_bounding_box)
741
+ dc->res_pool->funcs->update_bw_bounding_box(dc, dc->clk_mgr->bw_params);
742
+
743
+ /* Creation of current_state must occur after dc->dml
744
+ * is initialized in dc_create_resource_pool because
745
+ * on creation it copies the contents of dc->dml
746
+ */
747
+
748
+ dc->current_state = dc_create_state(dc);
749
+
750
+ if (!dc->current_state) {
751
+ dm_error("%s: failed to create validate ctx\n", __func__);
752
+ goto fail;
753
+ }
624754
625755 dc_resource_state_construct(dc, dc->current_state);
626756
....@@ -630,15 +760,48 @@
630760 return true;
631761
632762 fail:
633
-
634
- destruct(dc);
635763 return false;
764
+}
765
+
766
+static bool disable_all_writeback_pipes_for_stream(
767
+ const struct dc *dc,
768
+ struct dc_stream_state *stream,
769
+ struct dc_state *context)
770
+{
771
+ int i;
772
+
773
+ for (i = 0; i < stream->num_wb_info; i++)
774
+ stream->writeback_info[i].wb_enabled = false;
775
+
776
+ return true;
777
+}
778
+
779
+void apply_ctx_interdependent_lock(struct dc *dc, struct dc_state *context, struct dc_stream_state *stream, bool lock)
780
+{
781
+ int i = 0;
782
+
783
+ /* Checks if interdependent update function pointer is NULL or not, takes care of DCE110 case */
784
+ if (dc->hwss.interdependent_update_lock)
785
+ dc->hwss.interdependent_update_lock(dc, context, lock);
786
+ else {
787
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
788
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
789
+ struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
790
+
791
+ // Copied conditions that were previously in dce110_apply_ctx_for_surface
792
+ if (stream == pipe_ctx->stream) {
793
+ if (!pipe_ctx->top_pipe &&
794
+ (pipe_ctx->plane_state || old_pipe_ctx->plane_state))
795
+ dc->hwss.pipe_control_lock(dc, pipe_ctx, lock);
796
+ }
797
+ }
798
+ }
636799 }
637800
638801 static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
639802 {
640803 int i, j;
641
- struct dc_state *dangling_context = dc_create_state();
804
+ struct dc_state *dangling_context = dc_create_state(dc);
642805 struct dc_state *current_ctx;
643806
644807 if (dangling_context == NULL)
....@@ -659,13 +822,106 @@
659822 }
660823 if (should_disable && old_stream) {
661824 dc_rem_all_planes_for_stream(dc, old_stream, dangling_context);
662
- dc->hwss.apply_ctx_for_surface(dc, old_stream, 0, dangling_context);
825
+ disable_all_writeback_pipes_for_stream(dc, old_stream, dangling_context);
826
+
827
+ if (dc->hwss.apply_ctx_for_surface) {
828
+ apply_ctx_interdependent_lock(dc, dc->current_state, old_stream, true);
829
+ dc->hwss.apply_ctx_for_surface(dc, old_stream, 0, dangling_context);
830
+ apply_ctx_interdependent_lock(dc, dc->current_state, old_stream, false);
831
+ dc->hwss.post_unlock_program_front_end(dc, dangling_context);
832
+ }
833
+ if (dc->hwss.program_front_end_for_ctx) {
834
+ dc->hwss.interdependent_update_lock(dc, dc->current_state, true);
835
+ dc->hwss.program_front_end_for_ctx(dc, dangling_context);
836
+ dc->hwss.interdependent_update_lock(dc, dc->current_state, false);
837
+ dc->hwss.post_unlock_program_front_end(dc, dangling_context);
838
+ }
663839 }
664840 }
665841
666842 current_ctx = dc->current_state;
667843 dc->current_state = dangling_context;
668844 dc_release_state(current_ctx);
845
+}
846
+
847
+static void disable_vbios_mode_if_required(
848
+ struct dc *dc,
849
+ struct dc_state *context)
850
+{
851
+ unsigned int i, j;
852
+
853
+ /* check if timing_changed, disable stream*/
854
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
855
+ struct dc_stream_state *stream = NULL;
856
+ struct dc_link *link = NULL;
857
+ struct pipe_ctx *pipe = NULL;
858
+
859
+ pipe = &context->res_ctx.pipe_ctx[i];
860
+ stream = pipe->stream;
861
+ if (stream == NULL)
862
+ continue;
863
+
864
+ if (stream->link->local_sink &&
865
+ stream->link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
866
+ link = stream->link;
867
+ }
868
+
869
+ if (link != NULL) {
870
+ unsigned int enc_inst, tg_inst = 0;
871
+ unsigned int pix_clk_100hz;
872
+
873
+ enc_inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);
874
+ if (enc_inst != ENGINE_ID_UNKNOWN) {
875
+ for (j = 0; j < dc->res_pool->stream_enc_count; j++) {
876
+ if (dc->res_pool->stream_enc[j]->id == enc_inst) {
877
+ tg_inst = dc->res_pool->stream_enc[j]->funcs->dig_source_otg(
878
+ dc->res_pool->stream_enc[j]);
879
+ break;
880
+ }
881
+ }
882
+
883
+ dc->res_pool->dp_clock_source->funcs->get_pixel_clk_frequency_100hz(
884
+ dc->res_pool->dp_clock_source,
885
+ tg_inst, &pix_clk_100hz);
886
+
887
+ if (link->link_status.link_active) {
888
+ uint32_t requested_pix_clk_100hz =
889
+ pipe->stream_res.pix_clk_params.requested_pix_clk_100hz;
890
+
891
+ if (pix_clk_100hz != requested_pix_clk_100hz) {
892
+ core_link_disable_stream(pipe);
893
+ pipe->stream->dpms_off = false;
894
+ }
895
+ }
896
+ }
897
+ }
898
+ }
899
+}
900
+
901
+static void wait_for_no_pipes_pending(struct dc *dc, struct dc_state *context)
902
+{
903
+ int i;
904
+ PERF_TRACE();
905
+ for (i = 0; i < MAX_PIPES; i++) {
906
+ int count = 0;
907
+ struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
908
+
909
+ if (!pipe->plane_state)
910
+ continue;
911
+
912
+ /* Timeout 100 ms */
913
+ while (count < 100000) {
914
+ /* Must set to false to start with, due to OR in update function */
915
+ pipe->plane_state->status.is_flip_pending = false;
916
+ dc->hwss.update_pending_status(pipe);
917
+ if (!pipe->plane_state->status.is_flip_pending)
918
+ break;
919
+ udelay(1);
920
+ count++;
921
+ }
922
+ ASSERT(!pipe->plane_state->status.is_flip_pending);
923
+ }
924
+ PERF_TRACE();
669925 }
670926
671927 /*******************************************************************************
....@@ -680,36 +936,43 @@
680936 if (NULL == dc)
681937 goto alloc_fail;
682938
683
- if (false == construct(dc, init_params))
684
- goto construct_fail;
939
+ if (init_params->dce_environment == DCE_ENV_VIRTUAL_HW) {
940
+ if (false == dc_construct_ctx(dc, init_params)) {
941
+ dc_destruct(dc);
942
+ goto construct_fail;
943
+ }
944
+ } else {
945
+ if (false == dc_construct(dc, init_params)) {
946
+ dc_destruct(dc);
947
+ goto construct_fail;
948
+ }
685949
686
- /*TODO: separate HW and SW initialization*/
687
- dc->hwss.init_hw(dc);
950
+ full_pipe_count = dc->res_pool->pipe_count;
951
+ if (dc->res_pool->underlay_pipe_index != NO_UNDERLAY_PIPE)
952
+ full_pipe_count--;
953
+ dc->caps.max_streams = min(
954
+ full_pipe_count,
955
+ dc->res_pool->stream_enc_count);
688956
689
- full_pipe_count = dc->res_pool->pipe_count;
690
- if (dc->res_pool->underlay_pipe_index != NO_UNDERLAY_PIPE)
691
- full_pipe_count--;
692
- dc->caps.max_streams = min(
693
- full_pipe_count,
694
- dc->res_pool->stream_enc_count);
957
+ dc->optimize_seamless_boot_streams = 0;
958
+ dc->caps.max_links = dc->link_count;
959
+ dc->caps.max_audios = dc->res_pool->audio_count;
960
+ dc->caps.linear_pitch_alignment = 64;
695961
696
- dc->caps.max_links = dc->link_count;
697
- dc->caps.max_audios = dc->res_pool->audio_count;
698
- dc->caps.linear_pitch_alignment = 64;
962
+ dc->caps.max_dp_protocol_version = DP_VERSION_1_4;
963
+
964
+ if (dc->res_pool->dmcu != NULL)
965
+ dc->versions.dmcu_version = dc->res_pool->dmcu->dmcu_version;
966
+ }
699967
700968 /* Populate versioning information */
701969 dc->versions.dc_ver = DC_VER;
702970
703
- if (dc->res_pool->dmcu != NULL)
704
- dc->versions.dmcu_version = dc->res_pool->dmcu->dmcu_version;
705
-
706
- dc->config = init_params->flags;
971
+ dc->build_id = DC_BUILD_ID;
707972
708973 DC_LOG_DC("Display Core initialized\n");
709974
710975
711
- /* TODO: missing feature to be enabled */
712
- dc->debug.disable_dfs_bypass = true;
713976
714977 return dc;
715978
....@@ -720,9 +983,30 @@
720983 return NULL;
721984 }
722985
986
+void dc_hardware_init(struct dc *dc)
987
+{
988
+ if (dc->ctx->dce_environment != DCE_ENV_VIRTUAL_HW)
989
+ dc->hwss.init_hw(dc);
990
+}
991
+
992
+void dc_init_callbacks(struct dc *dc,
993
+ const struct dc_callback_init *init_params)
994
+{
995
+#ifdef CONFIG_DRM_AMD_DC_HDCP
996
+ dc->ctx->cp_psp = init_params->cp_psp;
997
+#endif
998
+}
999
+
1000
+void dc_deinit_callbacks(struct dc *dc)
1001
+{
1002
+#ifdef CONFIG_DRM_AMD_DC_HDCP
1003
+ memset(&dc->ctx->cp_psp, 0, sizeof(dc->ctx->cp_psp));
1004
+#endif
1005
+}
1006
+
7231007 void dc_destroy(struct dc **dc)
7241008 {
725
- destruct(*dc);
1009
+ dc_destruct(*dc);
7261010 kfree(*dc);
7271011 *dc = NULL;
7281012 }
....@@ -755,8 +1039,9 @@
7551039 struct dc *dc,
7561040 struct dc_state *ctx)
7571041 {
758
- int i, j;
1042
+ int i, j, k;
7591043 int group_index = 0;
1044
+ int num_group = 0;
7601045 int pipe_count = dc->res_pool->pipe_count;
7611046 struct pipe_ctx *unsynced_pipes[MAX_PIPES] = { NULL };
7621047
....@@ -795,22 +1080,46 @@
7951080
7961081 /* set first unblanked pipe as master */
7971082 for (j = 0; j < group_size; j++) {
798
- struct pipe_ctx *temp;
1083
+ bool is_blanked;
7991084
800
- if (pipe_set[j]->stream_res.tg->funcs->is_blanked && !pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg)) {
1085
+ if (pipe_set[j]->stream_res.opp->funcs->dpg_is_blanked)
1086
+ is_blanked =
1087
+ pipe_set[j]->stream_res.opp->funcs->dpg_is_blanked(pipe_set[j]->stream_res.opp);
1088
+ else
1089
+ is_blanked =
1090
+ pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg);
1091
+ if (!is_blanked) {
8011092 if (j == 0)
8021093 break;
8031094
804
- temp = pipe_set[0];
805
- pipe_set[0] = pipe_set[j];
806
- pipe_set[j] = temp;
1095
+ swap(pipe_set[0], pipe_set[j]);
8071096 break;
8081097 }
8091098 }
8101099
1100
+
1101
+ for (k = 0; k < group_size; k++) {
1102
+ struct dc_stream_status *status = dc_stream_get_status_from_state(ctx, pipe_set[k]->stream);
1103
+
1104
+ status->timing_sync_info.group_id = num_group;
1105
+ status->timing_sync_info.group_size = group_size;
1106
+ if (k == 0)
1107
+ status->timing_sync_info.master = true;
1108
+ else
1109
+ status->timing_sync_info.master = false;
1110
+
1111
+ }
8111112 /* remove any other unblanked pipes as they have already been synced */
8121113 for (j = j + 1; j < group_size; j++) {
813
- if (pipe_set[j]->stream_res.tg->funcs->is_blanked && !pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg)) {
1114
+ bool is_blanked;
1115
+
1116
+ if (pipe_set[j]->stream_res.opp->funcs->dpg_is_blanked)
1117
+ is_blanked =
1118
+ pipe_set[j]->stream_res.opp->funcs->dpg_is_blanked(pipe_set[j]->stream_res.opp);
1119
+ else
1120
+ is_blanked =
1121
+ pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg);
1122
+ if (!is_blanked) {
8141123 group_size--;
8151124 pipe_set[j] = pipe_set[group_size];
8161125 j--;
....@@ -822,6 +1131,7 @@
8221131 dc, group_index, group_size, pipe_set);
8231132 group_index++;
8241133 }
1134
+ num_group++;
8251135 }
8261136 }
8271137
....@@ -840,6 +1150,123 @@
8401150 }
8411151
8421152 return false;
1153
+}
1154
+
1155
+bool dc_validate_seamless_boot_timing(const struct dc *dc,
1156
+ const struct dc_sink *sink,
1157
+ struct dc_crtc_timing *crtc_timing)
1158
+{
1159
+ struct timing_generator *tg;
1160
+ struct stream_encoder *se = NULL;
1161
+
1162
+ struct dc_crtc_timing hw_crtc_timing = {0};
1163
+
1164
+ struct dc_link *link = sink->link;
1165
+ unsigned int i, enc_inst, tg_inst = 0;
1166
+
1167
+ // Seamless port only support single DP and EDP so far
1168
+ if (sink->sink_signal != SIGNAL_TYPE_DISPLAY_PORT &&
1169
+ sink->sink_signal != SIGNAL_TYPE_EDP)
1170
+ return false;
1171
+
1172
+ /* Check for enabled DIG to identify enabled display */
1173
+ if (!link->link_enc->funcs->is_dig_enabled(link->link_enc))
1174
+ return false;
1175
+
1176
+ enc_inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);
1177
+
1178
+ if (enc_inst == ENGINE_ID_UNKNOWN)
1179
+ return false;
1180
+
1181
+ for (i = 0; i < dc->res_pool->stream_enc_count; i++) {
1182
+ if (dc->res_pool->stream_enc[i]->id == enc_inst) {
1183
+
1184
+ se = dc->res_pool->stream_enc[i];
1185
+
1186
+ tg_inst = dc->res_pool->stream_enc[i]->funcs->dig_source_otg(
1187
+ dc->res_pool->stream_enc[i]);
1188
+ break;
1189
+ }
1190
+ }
1191
+
1192
+ // tg_inst not found
1193
+ if (i == dc->res_pool->stream_enc_count)
1194
+ return false;
1195
+
1196
+ if (tg_inst >= dc->res_pool->timing_generator_count)
1197
+ return false;
1198
+
1199
+ tg = dc->res_pool->timing_generators[tg_inst];
1200
+
1201
+ if (!tg->funcs->get_hw_timing)
1202
+ return false;
1203
+
1204
+ if (!tg->funcs->get_hw_timing(tg, &hw_crtc_timing))
1205
+ return false;
1206
+
1207
+ if (crtc_timing->h_total != hw_crtc_timing.h_total)
1208
+ return false;
1209
+
1210
+ if (crtc_timing->h_border_left != hw_crtc_timing.h_border_left)
1211
+ return false;
1212
+
1213
+ if (crtc_timing->h_addressable != hw_crtc_timing.h_addressable)
1214
+ return false;
1215
+
1216
+ if (crtc_timing->h_border_right != hw_crtc_timing.h_border_right)
1217
+ return false;
1218
+
1219
+ if (crtc_timing->h_front_porch != hw_crtc_timing.h_front_porch)
1220
+ return false;
1221
+
1222
+ if (crtc_timing->h_sync_width != hw_crtc_timing.h_sync_width)
1223
+ return false;
1224
+
1225
+ if (crtc_timing->v_total != hw_crtc_timing.v_total)
1226
+ return false;
1227
+
1228
+ if (crtc_timing->v_border_top != hw_crtc_timing.v_border_top)
1229
+ return false;
1230
+
1231
+ if (crtc_timing->v_addressable != hw_crtc_timing.v_addressable)
1232
+ return false;
1233
+
1234
+ if (crtc_timing->v_border_bottom != hw_crtc_timing.v_border_bottom)
1235
+ return false;
1236
+
1237
+ if (crtc_timing->v_front_porch != hw_crtc_timing.v_front_porch)
1238
+ return false;
1239
+
1240
+ if (crtc_timing->v_sync_width != hw_crtc_timing.v_sync_width)
1241
+ return false;
1242
+
1243
+ if (dc_is_dp_signal(link->connector_signal)) {
1244
+ unsigned int pix_clk_100hz;
1245
+
1246
+ dc->res_pool->dp_clock_source->funcs->get_pixel_clk_frequency_100hz(
1247
+ dc->res_pool->dp_clock_source,
1248
+ tg_inst, &pix_clk_100hz);
1249
+
1250
+ if (crtc_timing->pix_clk_100hz != pix_clk_100hz)
1251
+ return false;
1252
+
1253
+ if (!se->funcs->dp_get_pixel_format)
1254
+ return false;
1255
+
1256
+ if (!se->funcs->dp_get_pixel_format(
1257
+ se,
1258
+ &hw_crtc_timing.pixel_encoding,
1259
+ &hw_crtc_timing.display_color_depth))
1260
+ return false;
1261
+
1262
+ if (hw_crtc_timing.display_color_depth != crtc_timing->display_color_depth)
1263
+ return false;
1264
+
1265
+ if (hw_crtc_timing.pixel_encoding != crtc_timing->pixel_encoding)
1266
+ return false;
1267
+ }
1268
+
1269
+ return true;
8431270 }
8441271
8451272 bool dc_enable_stereo(
....@@ -867,6 +1294,27 @@
8671294 return ret;
8681295 }
8691296
1297
+void dc_trigger_sync(struct dc *dc, struct dc_state *context)
1298
+{
1299
+ if (context->stream_count > 1 && !dc->debug.disable_timing_sync) {
1300
+ enable_timing_multisync(dc, context);
1301
+ program_timing_sync(dc, context);
1302
+ }
1303
+}
1304
+
1305
+static uint8_t get_stream_mask(struct dc *dc, struct dc_state *context)
1306
+{
1307
+ int i;
1308
+ unsigned int stream_mask = 0;
1309
+
1310
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
1311
+ if (context->res_ctx.pipe_ctx[i].stream)
1312
+ stream_mask |= 1 << i;
1313
+ }
1314
+
1315
+ return stream_mask;
1316
+}
1317
+
8701318 /*
8711319 * Applies given context to HW and copy it into current context.
8721320 * It's up to the user to release the src context afterwards.
....@@ -879,32 +1327,45 @@
8791327 int i, k, l;
8801328 struct dc_stream_state *dc_streams[MAX_STREAMS] = {0};
8811329
882
- disable_dangling_plane(dc, context);
1330
+#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
1331
+ dc_allow_idle_optimizations(dc, false);
1332
+#endif
8831333
8841334 for (i = 0; i < context->stream_count; i++)
8851335 dc_streams[i] = context->streams[i];
8861336
887
- if (!dcb->funcs->is_accelerated_mode(dcb))
1337
+ if (!dcb->funcs->is_accelerated_mode(dcb)) {
1338
+ disable_vbios_mode_if_required(dc, context);
8881339 dc->hwss.enable_accelerated_mode(dc, context);
1340
+ }
8891341
890
- dc->hwss.set_bandwidth(dc, context, false);
1342
+ for (i = 0; i < context->stream_count; i++)
1343
+ if (context->streams[i]->apply_seamless_boot_optimization)
1344
+ dc->optimize_seamless_boot_streams++;
8911345
1346
+ if (context->stream_count > dc->optimize_seamless_boot_streams ||
1347
+ context->stream_count == 0)
1348
+ dc->hwss.prepare_bandwidth(dc, context);
1349
+
1350
+ disable_dangling_plane(dc, context);
8921351 /* re-program planes for existing stream, in case we need to
8931352 * free up plane resource for later use
8941353 */
895
- for (i = 0; i < context->stream_count; i++) {
896
- if (context->streams[i]->mode_changed)
897
- continue;
898
-
899
- dc->hwss.apply_ctx_for_surface(
900
- dc, context->streams[i],
901
- context->stream_status[i].plane_count,
902
- context); /* use new pipe config in new context */
1354
+ if (dc->hwss.apply_ctx_for_surface) {
1355
+ for (i = 0; i < context->stream_count; i++) {
1356
+ if (context->streams[i]->mode_changed)
1357
+ continue;
1358
+ apply_ctx_interdependent_lock(dc, context, context->streams[i], true);
1359
+ dc->hwss.apply_ctx_for_surface(
1360
+ dc, context->streams[i],
1361
+ context->stream_status[i].plane_count,
1362
+ context); /* use new pipe config in new context */
1363
+ apply_ctx_interdependent_lock(dc, context, context->streams[i], false);
1364
+ dc->hwss.post_unlock_program_front_end(dc, context);
1365
+ }
9031366 }
9041367
9051368 /* Program hardware */
906
- dc->hwss.ready_shared_resources(dc, context);
907
-
9081369 for (i = 0; i < dc->res_pool->pipe_count; i++) {
9091370 pipe = &context->res_ctx.pipe_ctx[i];
9101371 dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe);
....@@ -915,22 +1376,30 @@
9151376 if (result != DC_OK)
9161377 return result;
9171378
918
- if (context->stream_count > 1) {
919
- enable_timing_multisync(dc, context);
920
- program_timing_sync(dc, context);
921
- }
1379
+ dc_trigger_sync(dc, context);
9221380
9231381 /* Program all planes within new context*/
1382
+ if (dc->hwss.program_front_end_for_ctx) {
1383
+ dc->hwss.interdependent_update_lock(dc, context, true);
1384
+ dc->hwss.program_front_end_for_ctx(dc, context);
1385
+ dc->hwss.interdependent_update_lock(dc, context, false);
1386
+ dc->hwss.post_unlock_program_front_end(dc, context);
1387
+ }
9241388 for (i = 0; i < context->stream_count; i++) {
925
- const struct dc_sink *sink = context->streams[i]->sink;
1389
+ const struct dc_link *link = context->streams[i]->link;
9261390
9271391 if (!context->streams[i]->mode_changed)
9281392 continue;
9291393
930
- dc->hwss.apply_ctx_for_surface(
931
- dc, context->streams[i],
932
- context->stream_status[i].plane_count,
933
- context);
1394
+ if (dc->hwss.apply_ctx_for_surface) {
1395
+ apply_ctx_interdependent_lock(dc, context, context->streams[i], true);
1396
+ dc->hwss.apply_ctx_for_surface(
1397
+ dc, context->streams[i],
1398
+ context->stream_status[i].plane_count,
1399
+ context);
1400
+ apply_ctx_interdependent_lock(dc, context, context->streams[i], false);
1401
+ dc->hwss.post_unlock_program_front_end(dc, context);
1402
+ }
9341403
9351404 /*
9361405 * enable stereo
....@@ -947,18 +1416,28 @@
9471416 }
9481417 }
9491418
950
- CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}",
1419
+ CONN_MSG_MODE(link, "{%dx%d, %dx%d@%dKhz}",
9511420 context->streams[i]->timing.h_addressable,
9521421 context->streams[i]->timing.v_addressable,
9531422 context->streams[i]->timing.h_total,
9541423 context->streams[i]->timing.v_total,
955
- context->streams[i]->timing.pix_clk_khz);
1424
+ context->streams[i]->timing.pix_clk_100hz / 10);
9561425 }
9571426
9581427 dc_enable_stereo(dc, context, dc_streams, context->stream_count);
9591428
960
- /* pplib is notified if disp_num changed */
961
- dc->hwss.set_bandwidth(dc, context, true);
1429
+ if (context->stream_count > dc->optimize_seamless_boot_streams ||
1430
+ context->stream_count == 0) {
1431
+ /* Must wait for no flips to be pending before doing optimize bw */
1432
+ wait_for_no_pipes_pending(dc, context);
1433
+ /* pplib is notified if disp_num changed */
1434
+ dc->hwss.optimize_bandwidth(dc, context);
1435
+ }
1436
+
1437
+ context->stream_mask = get_stream_mask(dc, context);
1438
+
1439
+ if (context->stream_mask != dc->current_state->stream_mask)
1440
+ dc_dmub_srv_notify_stream_mask(dc->ctx->dmub_srv, context->stream_mask);
9621441
9631442 for (i = 0; i < context->stream_count; i++)
9641443 context->streams[i]->mode_changed = false;
....@@ -968,8 +1447,6 @@
9681447 dc->current_state = context;
9691448
9701449 dc_retain_state(dc->current_state);
971
-
972
- dc->hwss.optimize_shared_resources(dc);
9731450
9741451 return result;
9751452 }
....@@ -996,6 +1473,43 @@
9961473 return (result == DC_OK);
9971474 }
9981475
1476
+#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
1477
+bool dc_acquire_release_mpc_3dlut(
1478
+ struct dc *dc, bool acquire,
1479
+ struct dc_stream_state *stream,
1480
+ struct dc_3dlut **lut,
1481
+ struct dc_transfer_func **shaper)
1482
+{
1483
+ int pipe_idx;
1484
+ bool ret = false;
1485
+ bool found_pipe_idx = false;
1486
+ const struct resource_pool *pool = dc->res_pool;
1487
+ struct resource_context *res_ctx = &dc->current_state->res_ctx;
1488
+ int mpcc_id = 0;
1489
+
1490
+ if (pool && res_ctx) {
1491
+ if (acquire) {
1492
+ /*find pipe idx for the given stream*/
1493
+ for (pipe_idx = 0; pipe_idx < pool->pipe_count; pipe_idx++) {
1494
+ if (res_ctx->pipe_ctx[pipe_idx].stream == stream) {
1495
+ found_pipe_idx = true;
1496
+ mpcc_id = res_ctx->pipe_ctx[pipe_idx].plane_res.hubp->inst;
1497
+ break;
1498
+ }
1499
+ }
1500
+ } else
1501
+ found_pipe_idx = true;/*for release pipe_idx is not required*/
1502
+
1503
+ if (found_pipe_idx) {
1504
+ if (acquire && pool->funcs->acquire_post_bldn_3dlut)
1505
+ ret = pool->funcs->acquire_post_bldn_3dlut(res_ctx, pool, mpcc_id, lut, shaper);
1506
+ else if (acquire == false && pool->funcs->release_post_bldn_3dlut)
1507
+ ret = pool->funcs->release_post_bldn_3dlut(res_ctx, pool, lut, shaper);
1508
+ }
1509
+ }
1510
+ return ret;
1511
+}
1512
+#endif
9991513 static bool is_flip_pending_in_pipes(struct dc *dc, struct dc_state *context)
10001514 {
10011515 int i;
....@@ -1021,6 +1535,9 @@
10211535 int i;
10221536 struct dc_state *context = dc->current_state;
10231537
1538
+ if ((!dc->optimized_required) || dc->optimize_seamless_boot_streams > 0)
1539
+ return true;
1540
+
10241541 post_surface_trace(dc);
10251542
10261543 if (is_flip_pending_in_pipes(dc, context))
....@@ -1033,22 +1550,76 @@
10331550 dc->hwss.disable_plane(dc, &context->res_ctx.pipe_ctx[i]);
10341551 }
10351552
1036
- dc->optimized_required = false;
1553
+ dc->hwss.optimize_bandwidth(dc, context);
10371554
1038
- dc->hwss.set_bandwidth(dc, context, true);
1555
+ dc->optimized_required = false;
1556
+ dc->wm_optimized_required = false;
1557
+
10391558 return true;
10401559 }
10411560
1042
-struct dc_state *dc_create_state(void)
1561
+static void init_state(struct dc *dc, struct dc_state *context)
10431562 {
1044
- struct dc_state *context = kzalloc(sizeof(struct dc_state),
1045
- GFP_KERNEL);
1563
+ /* Each context must have their own instance of VBA and in order to
1564
+ * initialize and obtain IP and SOC the base DML instance from DC is
1565
+ * initially copied into every context
1566
+ */
1567
+#ifdef CONFIG_DRM_AMD_DC_DCN
1568
+ memcpy(&context->bw_ctx.dml, &dc->dml, sizeof(struct display_mode_lib));
1569
+#endif
1570
+}
1571
+
1572
+struct dc_state *dc_create_state(struct dc *dc)
1573
+{
1574
+ struct dc_state *context = kvzalloc(sizeof(struct dc_state),
1575
+ GFP_KERNEL);
10461576
10471577 if (!context)
10481578 return NULL;
10491579
1580
+ init_state(dc, context);
1581
+
10501582 kref_init(&context->refcount);
1583
+
10511584 return context;
1585
+}
1586
+
1587
+struct dc_state *dc_copy_state(struct dc_state *src_ctx)
1588
+{
1589
+ int i, j;
1590
+ struct dc_state *new_ctx = kvmalloc(sizeof(struct dc_state), GFP_KERNEL);
1591
+
1592
+ if (!new_ctx)
1593
+ return NULL;
1594
+ memcpy(new_ctx, src_ctx, sizeof(struct dc_state));
1595
+
1596
+ for (i = 0; i < MAX_PIPES; i++) {
1597
+ struct pipe_ctx *cur_pipe = &new_ctx->res_ctx.pipe_ctx[i];
1598
+
1599
+ if (cur_pipe->top_pipe)
1600
+ cur_pipe->top_pipe = &new_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx];
1601
+
1602
+ if (cur_pipe->bottom_pipe)
1603
+ cur_pipe->bottom_pipe = &new_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
1604
+
1605
+ if (cur_pipe->prev_odm_pipe)
1606
+ cur_pipe->prev_odm_pipe = &new_ctx->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx];
1607
+
1608
+ if (cur_pipe->next_odm_pipe)
1609
+ cur_pipe->next_odm_pipe = &new_ctx->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx];
1610
+
1611
+ }
1612
+
1613
+ for (i = 0; i < new_ctx->stream_count; i++) {
1614
+ dc_stream_retain(new_ctx->streams[i]);
1615
+ for (j = 0; j < new_ctx->stream_status[i].plane_count; j++)
1616
+ dc_plane_state_retain(
1617
+ new_ctx->stream_status[i].plane_states[j]);
1618
+ }
1619
+
1620
+ kref_init(&new_ctx->refcount);
1621
+
1622
+ return new_ctx;
10521623 }
10531624
10541625 void dc_retain_state(struct dc_state *context)
....@@ -1060,12 +1631,61 @@
10601631 {
10611632 struct dc_state *context = container_of(kref, struct dc_state, refcount);
10621633 dc_resource_state_destruct(context);
1063
- kfree(context);
1634
+ kvfree(context);
10641635 }
10651636
10661637 void dc_release_state(struct dc_state *context)
10671638 {
10681639 kref_put(&context->refcount, dc_state_free);
1640
+}
1641
+
1642
+bool dc_set_generic_gpio_for_stereo(bool enable,
1643
+ struct gpio_service *gpio_service)
1644
+{
1645
+ enum gpio_result gpio_result = GPIO_RESULT_NON_SPECIFIC_ERROR;
1646
+ struct gpio_pin_info pin_info;
1647
+ struct gpio *generic;
1648
+ struct gpio_generic_mux_config *config = kzalloc(sizeof(struct gpio_generic_mux_config),
1649
+ GFP_KERNEL);
1650
+
1651
+ if (!config)
1652
+ return false;
1653
+ pin_info = dal_gpio_get_generic_pin_info(gpio_service, GPIO_ID_GENERIC, 0);
1654
+
1655
+ if (pin_info.mask == 0xFFFFFFFF || pin_info.offset == 0xFFFFFFFF) {
1656
+ kfree(config);
1657
+ return false;
1658
+ } else {
1659
+ generic = dal_gpio_service_create_generic_mux(
1660
+ gpio_service,
1661
+ pin_info.offset,
1662
+ pin_info.mask);
1663
+ }
1664
+
1665
+ if (!generic) {
1666
+ kfree(config);
1667
+ return false;
1668
+ }
1669
+
1670
+ gpio_result = dal_gpio_open(generic, GPIO_MODE_OUTPUT);
1671
+
1672
+ config->enable_output_from_mux = enable;
1673
+ config->mux_select = GPIO_SIGNAL_SOURCE_PASS_THROUGH_STEREO_SYNC;
1674
+
1675
+ if (gpio_result == GPIO_RESULT_OK)
1676
+ gpio_result = dal_mux_setup_config(generic, config);
1677
+
1678
+ if (gpio_result == GPIO_RESULT_OK) {
1679
+ dal_gpio_close(generic);
1680
+ dal_gpio_destroy_generic_mux(&generic);
1681
+ kfree(config);
1682
+ return true;
1683
+ } else {
1684
+ dal_gpio_close(generic);
1685
+ dal_gpio_destroy_generic_mux(&generic);
1686
+ kfree(config);
1687
+ return false;
1688
+ }
10691689 }
10701690
10711691 static bool is_surface_in_context(
....@@ -1085,91 +1705,91 @@
10851705 return false;
10861706 }
10871707
1088
-static unsigned int pixel_format_to_bpp(enum surface_pixel_format format)
1089
-{
1090
- switch (format) {
1091
- case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
1092
- case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
1093
- return 12;
1094
- case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
1095
- case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
1096
- case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
1097
- case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
1098
- return 16;
1099
- case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
1100
- case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
1101
- case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
1102
- case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
1103
- return 32;
1104
- case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
1105
- case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
1106
- case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
1107
- return 64;
1108
- default:
1109
- ASSERT_CRITICAL(false);
1110
- return -1;
1111
- }
1112
-}
1113
-
11141708 static enum surface_update_type get_plane_info_update_type(const struct dc_surface_update *u)
11151709 {
11161710 union surface_update_flags *update_flags = &u->surface->update_flags;
1711
+ enum surface_update_type update_type = UPDATE_TYPE_FAST;
11171712
11181713 if (!u->plane_info)
11191714 return UPDATE_TYPE_FAST;
11201715
1121
- if (u->plane_info->color_space != u->surface->color_space)
1716
+ if (u->plane_info->color_space != u->surface->color_space) {
11221717 update_flags->bits.color_space_change = 1;
1718
+ elevate_update_type(&update_type, UPDATE_TYPE_MED);
1719
+ }
11231720
1124
- if (u->plane_info->horizontal_mirror != u->surface->horizontal_mirror)
1721
+ if (u->plane_info->horizontal_mirror != u->surface->horizontal_mirror) {
11251722 update_flags->bits.horizontal_mirror_change = 1;
1723
+ elevate_update_type(&update_type, UPDATE_TYPE_MED);
1724
+ }
11261725
1127
- if (u->plane_info->rotation != u->surface->rotation)
1726
+ if (u->plane_info->rotation != u->surface->rotation) {
11281727 update_flags->bits.rotation_change = 1;
1728
+ elevate_update_type(&update_type, UPDATE_TYPE_FULL);
1729
+ }
11291730
1130
- if (u->plane_info->format != u->surface->format)
1731
+ if (u->plane_info->format != u->surface->format) {
11311732 update_flags->bits.pixel_format_change = 1;
1733
+ elevate_update_type(&update_type, UPDATE_TYPE_FULL);
1734
+ }
11321735
1133
- if (u->plane_info->stereo_format != u->surface->stereo_format)
1736
+ if (u->plane_info->stereo_format != u->surface->stereo_format) {
11341737 update_flags->bits.stereo_format_change = 1;
1738
+ elevate_update_type(&update_type, UPDATE_TYPE_FULL);
1739
+ }
11351740
1136
- if (u->plane_info->per_pixel_alpha != u->surface->per_pixel_alpha)
1741
+ if (u->plane_info->per_pixel_alpha != u->surface->per_pixel_alpha) {
11371742 update_flags->bits.per_pixel_alpha_change = 1;
1743
+ elevate_update_type(&update_type, UPDATE_TYPE_MED);
1744
+ }
1745
+
1746
+ if (u->plane_info->global_alpha_value != u->surface->global_alpha_value) {
1747
+ update_flags->bits.global_alpha_change = 1;
1748
+ elevate_update_type(&update_type, UPDATE_TYPE_MED);
1749
+ }
11381750
11391751 if (u->plane_info->dcc.enable != u->surface->dcc.enable
1140
- || u->plane_info->dcc.grph.independent_64b_blks != u->surface->dcc.grph.independent_64b_blks
1141
- || u->plane_info->dcc.grph.meta_pitch != u->surface->dcc.grph.meta_pitch)
1752
+ || u->plane_info->dcc.independent_64b_blks != u->surface->dcc.independent_64b_blks
1753
+ || u->plane_info->dcc.meta_pitch != u->surface->dcc.meta_pitch) {
11421754 update_flags->bits.dcc_change = 1;
1755
+ elevate_update_type(&update_type, UPDATE_TYPE_MED);
1756
+ }
11431757
1144
- if (pixel_format_to_bpp(u->plane_info->format) !=
1145
- pixel_format_to_bpp(u->surface->format))
1758
+ if (resource_pixel_format_to_bpp(u->plane_info->format) !=
1759
+ resource_pixel_format_to_bpp(u->surface->format)) {
11461760 /* different bytes per element will require full bandwidth
11471761 * and DML calculation
11481762 */
11491763 update_flags->bits.bpp_change = 1;
1764
+ elevate_update_type(&update_type, UPDATE_TYPE_FULL);
1765
+ }
1766
+
1767
+ if (u->plane_info->plane_size.surface_pitch != u->surface->plane_size.surface_pitch
1768
+ || u->plane_info->plane_size.chroma_pitch != u->surface->plane_size.chroma_pitch) {
1769
+ update_flags->bits.plane_size_change = 1;
1770
+ elevate_update_type(&update_type, UPDATE_TYPE_MED);
1771
+ }
1772
+
11501773
11511774 if (memcmp(&u->plane_info->tiling_info, &u->surface->tiling_info,
11521775 sizeof(union dc_tiling_info)) != 0) {
11531776 update_flags->bits.swizzle_change = 1;
1777
+ elevate_update_type(&update_type, UPDATE_TYPE_MED);
1778
+
11541779 /* todo: below are HW dependent, we should add a hook to
11551780 * DCE/N resource and validated there.
11561781 */
1157
- if (u->plane_info->tiling_info.gfx9.swizzle != DC_SW_LINEAR)
1782
+ if (u->plane_info->tiling_info.gfx9.swizzle != DC_SW_LINEAR) {
11581783 /* swizzled mode requires RQ to be setup properly,
11591784 * thus need to run DML to calculate RQ settings
11601785 */
11611786 update_flags->bits.bandwidth_change = 1;
1787
+ elevate_update_type(&update_type, UPDATE_TYPE_FULL);
1788
+ }
11621789 }
11631790
1164
- if (update_flags->bits.rotation_change
1165
- || update_flags->bits.stereo_format_change
1166
- || update_flags->bits.pixel_format_change
1167
- || update_flags->bits.bpp_change
1168
- || update_flags->bits.bandwidth_change
1169
- || update_flags->bits.output_tf_change)
1170
- return UPDATE_TYPE_FULL;
1171
-
1172
- return UPDATE_TYPE_MED;
1791
+ /* This should be UPDATE_TYPE_FAST if nothing has changed. */
1792
+ return update_type;
11731793 }
11741794
11751795 static enum surface_update_type get_scaling_info_update_type(
....@@ -1183,7 +1803,10 @@
11831803 if (u->scaling_info->clip_rect.width != u->surface->clip_rect.width
11841804 || u->scaling_info->clip_rect.height != u->surface->clip_rect.height
11851805 || u->scaling_info->dst_rect.width != u->surface->dst_rect.width
1186
- || u->scaling_info->dst_rect.height != u->surface->dst_rect.height) {
1806
+ || u->scaling_info->dst_rect.height != u->surface->dst_rect.height
1807
+ || u->scaling_info->scaling_quality.integer_scaling !=
1808
+ u->surface->scaling_quality.integer_scaling
1809
+ ) {
11871810 update_flags->bits.scaling_change = 1;
11881811
11891812 if ((u->scaling_info->dst_rect.width < u->surface->dst_rect.width
....@@ -1199,7 +1822,7 @@
11991822
12001823 update_flags->bits.scaling_change = 1;
12011824 if (u->scaling_info->src_rect.width > u->surface->src_rect.width
1202
- && u->scaling_info->src_rect.height > u->surface->src_rect.height)
1825
+ || u->scaling_info->src_rect.height > u->surface->src_rect.height)
12031826 /* Making src rect bigger requires a bandwidth change */
12041827 update_flags->bits.clock_change = 1;
12051828 }
....@@ -1213,11 +1836,11 @@
12131836 update_flags->bits.position_change = 1;
12141837
12151838 if (update_flags->bits.clock_change
1216
- || update_flags->bits.bandwidth_change)
1839
+ || update_flags->bits.bandwidth_change
1840
+ || update_flags->bits.scaling_change)
12171841 return UPDATE_TYPE_FULL;
12181842
1219
- if (update_flags->bits.scaling_change
1220
- || update_flags->bits.position_change)
1843
+ if (update_flags->bits.position_change)
12211844 return UPDATE_TYPE_MED;
12221845
12231846 return UPDATE_TYPE_FAST;
....@@ -1231,23 +1854,24 @@
12311854 enum surface_update_type overall_type = UPDATE_TYPE_FAST;
12321855 union surface_update_flags *update_flags = &u->surface->update_flags;
12331856
1857
+ if (u->flip_addr)
1858
+ update_flags->bits.addr_update = 1;
1859
+
1860
+ if (!is_surface_in_context(context, u->surface) || u->surface->force_full_update) {
1861
+ update_flags->raw = 0xFFFFFFFF;
1862
+ return UPDATE_TYPE_FULL;
1863
+ }
1864
+
12341865 update_flags->raw = 0; // Reset all flags
1235
-
1236
- if (!is_surface_in_context(context, u->surface)) {
1237
- update_flags->bits.new_plane = 1;
1238
- return UPDATE_TYPE_FULL;
1239
- }
1240
-
1241
- if (u->surface->force_full_update) {
1242
- update_flags->bits.full_update = 1;
1243
- return UPDATE_TYPE_FULL;
1244
- }
12451866
12461867 type = get_plane_info_update_type(u);
12471868 elevate_update_type(&overall_type, type);
12481869
12491870 type = get_scaling_info_update_type(u);
12501871 elevate_update_type(&overall_type, type);
1872
+
1873
+ if (u->flip_addr)
1874
+ update_flags->bits.addr_update = 1;
12511875
12521876 if (u->in_transfer_func)
12531877 update_flags->bits.in_transfer_func_change = 1;
....@@ -1257,6 +1881,9 @@
12571881
12581882 if (u->coeff_reduction_factor)
12591883 update_flags->bits.coeff_reduction_change = 1;
1884
+
1885
+ if (u->gamut_remap_matrix)
1886
+ update_flags->bits.gamut_remap_change = 1;
12601887
12611888 if (u->gamma) {
12621889 enum surface_pixel_format format = SURFACE_PIXEL_FORMAT_GRPH_BEGIN;
....@@ -1270,6 +1897,12 @@
12701897 update_flags->bits.gamma_change = 1;
12711898 }
12721899
1900
+ if (u->hdr_mult.value)
1901
+ if (u->hdr_mult.value != u->surface->hdr_mult.value) {
1902
+ update_flags->bits.hdr_mult = 1;
1903
+ elevate_update_type(&overall_type, UPDATE_TYPE_MED);
1904
+ }
1905
+
12731906 if (update_flags->bits.in_transfer_func_change) {
12741907 type = UPDATE_TYPE_MED;
12751908 elevate_update_type(&overall_type, type);
....@@ -1277,7 +1910,8 @@
12771910
12781911 if (update_flags->bits.input_csc_change
12791912 || update_flags->bits.coeff_reduction_change
1280
- || update_flags->bits.gamma_change) {
1913
+ || update_flags->bits.gamma_change
1914
+ || update_flags->bits.gamut_remap_change) {
12811915 type = UPDATE_TYPE_FULL;
12821916 elevate_update_type(&overall_type, type);
12831917 }
....@@ -1295,18 +1929,51 @@
12951929 int i;
12961930 enum surface_update_type overall_type = UPDATE_TYPE_FAST;
12971931
1298
- if (stream_status == NULL || stream_status->plane_count != surface_count)
1299
- return UPDATE_TYPE_FULL;
1932
+#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
1933
+ if (dc->idle_optimizations_allowed)
1934
+ overall_type = UPDATE_TYPE_FULL;
13001935
1301
- if (stream_update)
1302
- return UPDATE_TYPE_FULL;
1936
+#endif
1937
+ if (stream_status == NULL || stream_status->plane_count != surface_count)
1938
+ overall_type = UPDATE_TYPE_FULL;
1939
+
1940
+ /* some stream updates require passive update */
1941
+ if (stream_update) {
1942
+ union stream_update_flags *su_flags = &stream_update->stream->update_flags;
1943
+
1944
+ if ((stream_update->src.height != 0 && stream_update->src.width != 0) ||
1945
+ (stream_update->dst.height != 0 && stream_update->dst.width != 0) ||
1946
+ stream_update->integer_scaling_update)
1947
+ su_flags->bits.scaling = 1;
1948
+
1949
+ if (stream_update->out_transfer_func)
1950
+ su_flags->bits.out_tf = 1;
1951
+
1952
+ if (stream_update->abm_level)
1953
+ su_flags->bits.abm_level = 1;
1954
+
1955
+ if (stream_update->dpms_off)
1956
+ su_flags->bits.dpms_off = 1;
1957
+
1958
+ if (stream_update->gamut_remap)
1959
+ su_flags->bits.gamut_remap = 1;
1960
+
1961
+ if (stream_update->wb_update)
1962
+ su_flags->bits.wb_update = 1;
1963
+
1964
+ if (stream_update->dsc_config)
1965
+ su_flags->bits.dsc_changed = 1;
1966
+
1967
+ if (su_flags->raw != 0)
1968
+ overall_type = UPDATE_TYPE_FULL;
1969
+
1970
+ if (stream_update->output_csc_transform || stream_update->output_color_space)
1971
+ su_flags->bits.out_csc = 1;
1972
+ }
13031973
13041974 for (i = 0 ; i < surface_count; i++) {
13051975 enum surface_update_type type =
13061976 det_surface_update(dc, &updates[i]);
1307
-
1308
- if (type == UPDATE_TYPE_FULL)
1309
- return type;
13101977
13111978 elevate_update_type(&overall_type, type);
13121979 }
....@@ -1314,6 +1981,11 @@
13141981 return overall_type;
13151982 }
13161983
1984
+/**
1985
+ * dc_check_update_surfaces_for_stream() - Determine update type (fast, med, or full)
1986
+ *
1987
+ * See :c:type:`enum surface_update_type <surface_update_type>` for explanation of update types
1988
+ */
13171989 enum surface_update_type dc_check_update_surfaces_for_stream(
13181990 struct dc *dc,
13191991 struct dc_surface_update *updates,
....@@ -1324,13 +1996,34 @@
13241996 int i;
13251997 enum surface_update_type type;
13261998
1999
+ if (stream_update)
2000
+ stream_update->stream->update_flags.raw = 0;
13272001 for (i = 0; i < surface_count; i++)
13282002 updates[i].surface->update_flags.raw = 0;
13292003
13302004 type = check_update_surfaces_for_stream(dc, updates, surface_count, stream_update, stream_status);
1331
- if (type == UPDATE_TYPE_FULL)
2005
+ if (type == UPDATE_TYPE_FULL) {
2006
+ if (stream_update) {
2007
+ uint32_t dsc_changed = stream_update->stream->update_flags.bits.dsc_changed;
2008
+ stream_update->stream->update_flags.raw = 0xFFFFFFFF;
2009
+ stream_update->stream->update_flags.bits.dsc_changed = dsc_changed;
2010
+ }
13322011 for (i = 0; i < surface_count; i++)
13332012 updates[i].surface->update_flags.raw = 0xFFFFFFFF;
2013
+ }
2014
+
2015
+ if (type == UPDATE_TYPE_FAST) {
2016
+ // If there's an available clock comparator, we use that.
2017
+ if (dc->clk_mgr->funcs->are_clock_states_equal) {
2018
+ if (!dc->clk_mgr->funcs->are_clock_states_equal(&dc->clk_mgr->clks, &dc->current_state->bw_ctx.bw.dcn.clk))
2019
+ dc->optimized_required = true;
2020
+ // Else we fallback to mem compare.
2021
+ } else if (memcmp(&dc->current_state->bw_ctx.bw.dcn.clk, &dc->clk_mgr->clks, offsetof(struct dc_clocks, prev_p_state_change_support)) != 0) {
2022
+ dc->optimized_required = true;
2023
+ }
2024
+
2025
+ dc->optimized_required |= dc->wm_optimized_required;
2026
+ }
13342027
13352028 return type;
13362029 }
....@@ -1352,6 +2045,328 @@
13522045
13532046 static const enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL;
13542047
2048
+static void copy_surface_update_to_plane(
2049
+ struct dc_plane_state *surface,
2050
+ struct dc_surface_update *srf_update)
2051
+{
2052
+ if (srf_update->flip_addr) {
2053
+ surface->address = srf_update->flip_addr->address;
2054
+ surface->flip_immediate =
2055
+ srf_update->flip_addr->flip_immediate;
2056
+ surface->time.time_elapsed_in_us[surface->time.index] =
2057
+ srf_update->flip_addr->flip_timestamp_in_us -
2058
+ surface->time.prev_update_time_in_us;
2059
+ surface->time.prev_update_time_in_us =
2060
+ srf_update->flip_addr->flip_timestamp_in_us;
2061
+ surface->time.index++;
2062
+ if (surface->time.index >= DC_PLANE_UPDATE_TIMES_MAX)
2063
+ surface->time.index = 0;
2064
+
2065
+ surface->triplebuffer_flips = srf_update->flip_addr->triplebuffer_flips;
2066
+ }
2067
+
2068
+ if (srf_update->scaling_info) {
2069
+ surface->scaling_quality =
2070
+ srf_update->scaling_info->scaling_quality;
2071
+ surface->dst_rect =
2072
+ srf_update->scaling_info->dst_rect;
2073
+ surface->src_rect =
2074
+ srf_update->scaling_info->src_rect;
2075
+ surface->clip_rect =
2076
+ srf_update->scaling_info->clip_rect;
2077
+ }
2078
+
2079
+ if (srf_update->plane_info) {
2080
+ surface->color_space =
2081
+ srf_update->plane_info->color_space;
2082
+ surface->format =
2083
+ srf_update->plane_info->format;
2084
+ surface->plane_size =
2085
+ srf_update->plane_info->plane_size;
2086
+ surface->rotation =
2087
+ srf_update->plane_info->rotation;
2088
+ surface->horizontal_mirror =
2089
+ srf_update->plane_info->horizontal_mirror;
2090
+ surface->stereo_format =
2091
+ srf_update->plane_info->stereo_format;
2092
+ surface->tiling_info =
2093
+ srf_update->plane_info->tiling_info;
2094
+ surface->visible =
2095
+ srf_update->plane_info->visible;
2096
+ surface->per_pixel_alpha =
2097
+ srf_update->plane_info->per_pixel_alpha;
2098
+ surface->global_alpha =
2099
+ srf_update->plane_info->global_alpha;
2100
+ surface->global_alpha_value =
2101
+ srf_update->plane_info->global_alpha_value;
2102
+ surface->dcc =
2103
+ srf_update->plane_info->dcc;
2104
+ surface->layer_index =
2105
+ srf_update->plane_info->layer_index;
2106
+ }
2107
+
2108
+ if (srf_update->gamma &&
2109
+ (surface->gamma_correction !=
2110
+ srf_update->gamma)) {
2111
+ memcpy(&surface->gamma_correction->entries,
2112
+ &srf_update->gamma->entries,
2113
+ sizeof(struct dc_gamma_entries));
2114
+ surface->gamma_correction->is_identity =
2115
+ srf_update->gamma->is_identity;
2116
+ surface->gamma_correction->num_entries =
2117
+ srf_update->gamma->num_entries;
2118
+ surface->gamma_correction->type =
2119
+ srf_update->gamma->type;
2120
+ }
2121
+
2122
+ if (srf_update->in_transfer_func &&
2123
+ (surface->in_transfer_func !=
2124
+ srf_update->in_transfer_func)) {
2125
+ surface->in_transfer_func->sdr_ref_white_level =
2126
+ srf_update->in_transfer_func->sdr_ref_white_level;
2127
+ surface->in_transfer_func->tf =
2128
+ srf_update->in_transfer_func->tf;
2129
+ surface->in_transfer_func->type =
2130
+ srf_update->in_transfer_func->type;
2131
+ memcpy(&surface->in_transfer_func->tf_pts,
2132
+ &srf_update->in_transfer_func->tf_pts,
2133
+ sizeof(struct dc_transfer_func_distributed_points));
2134
+ }
2135
+
2136
+ if (srf_update->func_shaper &&
2137
+ (surface->in_shaper_func !=
2138
+ srf_update->func_shaper))
2139
+ memcpy(surface->in_shaper_func, srf_update->func_shaper,
2140
+ sizeof(*surface->in_shaper_func));
2141
+
2142
+ if (srf_update->lut3d_func &&
2143
+ (surface->lut3d_func !=
2144
+ srf_update->lut3d_func))
2145
+ memcpy(surface->lut3d_func, srf_update->lut3d_func,
2146
+ sizeof(*surface->lut3d_func));
2147
+
2148
+ if (srf_update->hdr_mult.value)
2149
+ surface->hdr_mult =
2150
+ srf_update->hdr_mult;
2151
+
2152
+ if (srf_update->blend_tf &&
2153
+ (surface->blend_tf !=
2154
+ srf_update->blend_tf))
2155
+ memcpy(surface->blend_tf, srf_update->blend_tf,
2156
+ sizeof(*surface->blend_tf));
2157
+
2158
+ if (srf_update->input_csc_color_matrix)
2159
+ surface->input_csc_color_matrix =
2160
+ *srf_update->input_csc_color_matrix;
2161
+
2162
+ if (srf_update->coeff_reduction_factor)
2163
+ surface->coeff_reduction_factor =
2164
+ *srf_update->coeff_reduction_factor;
2165
+
2166
+ if (srf_update->gamut_remap_matrix)
2167
+ surface->gamut_remap_matrix =
2168
+ *srf_update->gamut_remap_matrix;
2169
+}
2170
+
2171
+static void copy_stream_update_to_stream(struct dc *dc,
2172
+ struct dc_state *context,
2173
+ struct dc_stream_state *stream,
2174
+ struct dc_stream_update *update)
2175
+{
2176
+ struct dc_context *dc_ctx = dc->ctx;
2177
+
2178
+ if (update == NULL || stream == NULL)
2179
+ return;
2180
+
2181
+ if (update->src.height && update->src.width)
2182
+ stream->src = update->src;
2183
+
2184
+ if (update->dst.height && update->dst.width)
2185
+ stream->dst = update->dst;
2186
+
2187
+ if (update->out_transfer_func &&
2188
+ stream->out_transfer_func != update->out_transfer_func) {
2189
+ stream->out_transfer_func->sdr_ref_white_level =
2190
+ update->out_transfer_func->sdr_ref_white_level;
2191
+ stream->out_transfer_func->tf = update->out_transfer_func->tf;
2192
+ stream->out_transfer_func->type =
2193
+ update->out_transfer_func->type;
2194
+ memcpy(&stream->out_transfer_func->tf_pts,
2195
+ &update->out_transfer_func->tf_pts,
2196
+ sizeof(struct dc_transfer_func_distributed_points));
2197
+ }
2198
+
2199
+ if (update->hdr_static_metadata)
2200
+ stream->hdr_static_metadata = *update->hdr_static_metadata;
2201
+
2202
+ if (update->abm_level)
2203
+ stream->abm_level = *update->abm_level;
2204
+
2205
+ if (update->periodic_interrupt)
2206
+ stream->periodic_interrupt = *update->periodic_interrupt;
2207
+
2208
+ if (update->gamut_remap)
2209
+ stream->gamut_remap_matrix = *update->gamut_remap;
2210
+
2211
+ /* Note: this being updated after mode set is currently not a use case
2212
+ * however if it arises OCSC would need to be reprogrammed at the
2213
+ * minimum
2214
+ */
2215
+ if (update->output_color_space)
2216
+ stream->output_color_space = *update->output_color_space;
2217
+
2218
+ if (update->output_csc_transform)
2219
+ stream->csc_color_matrix = *update->output_csc_transform;
2220
+
2221
+ if (update->vrr_infopacket)
2222
+ stream->vrr_infopacket = *update->vrr_infopacket;
2223
+
2224
+ if (update->dpms_off)
2225
+ stream->dpms_off = *update->dpms_off;
2226
+
2227
+ if (update->vsc_infopacket)
2228
+ stream->vsc_infopacket = *update->vsc_infopacket;
2229
+
2230
+ if (update->vsp_infopacket)
2231
+ stream->vsp_infopacket = *update->vsp_infopacket;
2232
+
2233
+ if (update->dither_option)
2234
+ stream->dither_option = *update->dither_option;
2235
+ /* update current stream with writeback info */
2236
+ if (update->wb_update) {
2237
+ int i;
2238
+
2239
+ stream->num_wb_info = update->wb_update->num_wb_info;
2240
+ ASSERT(stream->num_wb_info <= MAX_DWB_PIPES);
2241
+ for (i = 0; i < stream->num_wb_info; i++)
2242
+ stream->writeback_info[i] =
2243
+ update->wb_update->writeback_info[i];
2244
+ }
2245
+ if (update->dsc_config) {
2246
+ struct dc_dsc_config old_dsc_cfg = stream->timing.dsc_cfg;
2247
+ uint32_t old_dsc_enabled = stream->timing.flags.DSC;
2248
+ uint32_t enable_dsc = (update->dsc_config->num_slices_h != 0 &&
2249
+ update->dsc_config->num_slices_v != 0);
2250
+
2251
+ /* Use temporarry context for validating new DSC config */
2252
+ struct dc_state *dsc_validate_context = dc_create_state(dc);
2253
+
2254
+ if (dsc_validate_context) {
2255
+ dc_resource_state_copy_construct(dc->current_state, dsc_validate_context);
2256
+
2257
+ stream->timing.dsc_cfg = *update->dsc_config;
2258
+ stream->timing.flags.DSC = enable_dsc;
2259
+ if (!dc->res_pool->funcs->validate_bandwidth(dc, dsc_validate_context, true)) {
2260
+ stream->timing.dsc_cfg = old_dsc_cfg;
2261
+ stream->timing.flags.DSC = old_dsc_enabled;
2262
+ update->dsc_config = NULL;
2263
+ }
2264
+
2265
+ dc_release_state(dsc_validate_context);
2266
+ } else {
2267
+ DC_ERROR("Failed to allocate new validate context for DSC change\n");
2268
+ update->dsc_config = NULL;
2269
+ }
2270
+ }
2271
+}
2272
+
2273
+static void commit_planes_do_stream_update(struct dc *dc,
2274
+ struct dc_stream_state *stream,
2275
+ struct dc_stream_update *stream_update,
2276
+ enum surface_update_type update_type,
2277
+ struct dc_state *context)
2278
+{
2279
+ int j;
2280
+ bool should_program_abm;
2281
+
2282
+ // Stream updates
2283
+ for (j = 0; j < dc->res_pool->pipe_count; j++) {
2284
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
2285
+
2286
+ if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe && pipe_ctx->stream == stream) {
2287
+
2288
+ if (stream_update->periodic_interrupt && dc->hwss.setup_periodic_interrupt)
2289
+ dc->hwss.setup_periodic_interrupt(dc, pipe_ctx);
2290
+
2291
+ if ((stream_update->hdr_static_metadata && !stream->use_dynamic_meta) ||
2292
+ stream_update->vrr_infopacket ||
2293
+ stream_update->vsc_infopacket ||
2294
+ stream_update->vsp_infopacket) {
2295
+ resource_build_info_frame(pipe_ctx);
2296
+ dc->hwss.update_info_frame(pipe_ctx);
2297
+ }
2298
+
2299
+ if (stream_update->hdr_static_metadata &&
2300
+ stream->use_dynamic_meta &&
2301
+ dc->hwss.set_dmdata_attributes &&
2302
+ pipe_ctx->stream->dmdata_address.quad_part != 0)
2303
+ dc->hwss.set_dmdata_attributes(pipe_ctx);
2304
+
2305
+ if (stream_update->gamut_remap)
2306
+ dc_stream_set_gamut_remap(dc, stream);
2307
+
2308
+ if (stream_update->output_csc_transform)
2309
+ dc_stream_program_csc_matrix(dc, stream);
2310
+
2311
+ if (stream_update->dither_option) {
2312
+ struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe;
2313
+ resource_build_bit_depth_reduction_params(pipe_ctx->stream,
2314
+ &pipe_ctx->stream->bit_depth_params);
2315
+ pipe_ctx->stream_res.opp->funcs->opp_program_fmt(pipe_ctx->stream_res.opp,
2316
+ &stream->bit_depth_params,
2317
+ &stream->clamping);
2318
+ while (odm_pipe) {
2319
+ odm_pipe->stream_res.opp->funcs->opp_program_fmt(odm_pipe->stream_res.opp,
2320
+ &stream->bit_depth_params,
2321
+ &stream->clamping);
2322
+ odm_pipe = odm_pipe->next_odm_pipe;
2323
+ }
2324
+ }
2325
+
2326
+ /* Full fe update*/
2327
+ if (update_type == UPDATE_TYPE_FAST)
2328
+ continue;
2329
+
2330
+ if (stream_update->dsc_config)
2331
+ dp_update_dsc_config(pipe_ctx);
2332
+
2333
+ if (stream_update->dpms_off) {
2334
+ if (*stream_update->dpms_off) {
2335
+ core_link_disable_stream(pipe_ctx);
2336
+ /* for dpms, keep acquired resources*/
2337
+ if (pipe_ctx->stream_res.audio && !dc->debug.az_endpoint_mute_only)
2338
+ pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
2339
+
2340
+ dc->optimized_required = true;
2341
+
2342
+ } else {
2343
+ if (dc->optimize_seamless_boot_streams == 0)
2344
+ dc->hwss.prepare_bandwidth(dc, dc->current_state);
2345
+
2346
+ core_link_enable_stream(dc->current_state, pipe_ctx);
2347
+ }
2348
+ }
2349
+
2350
+ if (stream_update->abm_level && pipe_ctx->stream_res.abm) {
2351
+ should_program_abm = true;
2352
+
2353
+ // if otg funcs defined check if blanked before programming
2354
+ if (pipe_ctx->stream_res.tg->funcs->is_blanked)
2355
+ if (pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg))
2356
+ should_program_abm = false;
2357
+
2358
+ if (should_program_abm) {
2359
+ if (*stream_update->abm_level == ABM_LEVEL_IMMEDIATE_DISABLE) {
2360
+ dc->hwss.set_abm_immediate_disable(pipe_ctx);
2361
+ } else {
2362
+ pipe_ctx->stream_res.abm->funcs->set_abm_level(
2363
+ pipe_ctx->stream_res.abm, stream->abm_level);
2364
+ }
2365
+ }
2366
+ }
2367
+ }
2368
+ }
2369
+}
13552370
13562371 static void commit_planes_for_stream(struct dc *dc,
13572372 struct dc_surface_update *srf_updates,
....@@ -1361,72 +2376,205 @@
13612376 enum surface_update_type update_type,
13622377 struct dc_state *context)
13632378 {
2379
+ bool mpcc_disconnected = false;
13642380 int i, j;
13652381 struct pipe_ctx *top_pipe_to_program = NULL;
13662382
2383
+ if (dc->optimize_seamless_boot_streams > 0 && surface_count > 0) {
2384
+ /* Optimize seamless boot flag keeps clocks and watermarks high until
2385
+ * first flip. After first flip, optimization is required to lower
2386
+ * bandwidth. Important to note that it is expected UEFI will
2387
+ * only light up a single display on POST, therefore we only expect
2388
+ * one stream with seamless boot flag set.
2389
+ */
2390
+ if (stream->apply_seamless_boot_optimization) {
2391
+ stream->apply_seamless_boot_optimization = false;
2392
+ dc->optimize_seamless_boot_streams--;
2393
+
2394
+ if (dc->optimize_seamless_boot_streams == 0)
2395
+ dc->optimized_required = true;
2396
+ }
2397
+ }
2398
+
13672399 if (update_type == UPDATE_TYPE_FULL) {
1368
- dc->hwss.set_bandwidth(dc, context, false);
2400
+#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
2401
+ dc_allow_idle_optimizations(dc, false);
2402
+
2403
+#endif
2404
+ if (dc->optimize_seamless_boot_streams == 0)
2405
+ dc->hwss.prepare_bandwidth(dc, context);
2406
+
13692407 context_clock_trace(dc, context);
13702408 }
13712409
1372
- if (surface_count == 0) {
1373
- /*
1374
- * In case of turning off screen, no need to program front end a second time.
1375
- * just return after program front end.
1376
- */
1377
- dc->hwss.apply_ctx_for_surface(dc, stream, surface_count, context);
1378
- return;
2410
+ if (update_type != UPDATE_TYPE_FAST && dc->hwss.interdependent_update_lock &&
2411
+ dc->hwss.disconnect_pipes && dc->hwss.wait_for_pending_cleared){
2412
+ dc->hwss.interdependent_update_lock(dc, context, true);
2413
+ mpcc_disconnected = dc->hwss.disconnect_pipes(dc, context);
2414
+ dc->hwss.interdependent_update_lock(dc, context, false);
2415
+ if (mpcc_disconnected)
2416
+ dc->hwss.wait_for_pending_cleared(dc, context);
13792417 }
13802418
1381
- /* Full fe update*/
13822419 for (j = 0; j < dc->res_pool->pipe_count; j++) {
13832420 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
13842421
13852422 if (!pipe_ctx->top_pipe &&
2423
+ !pipe_ctx->prev_odm_pipe &&
2424
+ pipe_ctx->stream &&
2425
+ pipe_ctx->stream == stream) {
2426
+ top_pipe_to_program = pipe_ctx;
2427
+ }
2428
+ }
2429
+
2430
+ if ((update_type != UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed)
2431
+ if (top_pipe_to_program &&
2432
+ top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) {
2433
+ if (should_use_dmub_lock(stream->link)) {
2434
+ union dmub_hw_lock_flags hw_locks = { 0 };
2435
+ struct dmub_hw_lock_inst_flags inst_flags = { 0 };
2436
+
2437
+ hw_locks.bits.lock_dig = 1;
2438
+ inst_flags.dig_inst = top_pipe_to_program->stream_res.tg->inst;
2439
+
2440
+ dmub_hw_lock_mgr_cmd(dc->ctx->dmub_srv,
2441
+ true,
2442
+ &hw_locks,
2443
+ &inst_flags);
2444
+ } else
2445
+ top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable(
2446
+ top_pipe_to_program->stream_res.tg);
2447
+ }
2448
+
2449
+ if ((update_type != UPDATE_TYPE_FAST) && dc->hwss.interdependent_update_lock)
2450
+ dc->hwss.interdependent_update_lock(dc, context, true);
2451
+ else
2452
+ /* Lock the top pipe while updating plane addrs, since freesync requires
2453
+ * plane addr update event triggers to be synchronized.
2454
+ * top_pipe_to_program is expected to never be NULL
2455
+ */
2456
+ dc->hwss.pipe_control_lock(dc, top_pipe_to_program, true);
2457
+
2458
+
2459
+ // Stream updates
2460
+ if (stream_update)
2461
+ commit_planes_do_stream_update(dc, stream, stream_update, update_type, context);
2462
+
2463
+ if (surface_count == 0) {
2464
+ /*
2465
+ * In case of turning off screen, no need to program front end a second time.
2466
+ * just return after program blank.
2467
+ */
2468
+ if (dc->hwss.apply_ctx_for_surface)
2469
+ dc->hwss.apply_ctx_for_surface(dc, stream, 0, context);
2470
+ if (dc->hwss.program_front_end_for_ctx)
2471
+ dc->hwss.program_front_end_for_ctx(dc, context);
2472
+
2473
+ if ((update_type != UPDATE_TYPE_FAST) && dc->hwss.interdependent_update_lock)
2474
+ dc->hwss.interdependent_update_lock(dc, context, false);
2475
+ else
2476
+ dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false);
2477
+
2478
+ dc->hwss.post_unlock_program_front_end(dc, context);
2479
+ return;
2480
+ }
2481
+
2482
+ if (!IS_DIAG_DC(dc->ctx->dce_environment)) {
2483
+ for (i = 0; i < surface_count; i++) {
2484
+ struct dc_plane_state *plane_state = srf_updates[i].surface;
2485
+ /*set logical flag for lock/unlock use*/
2486
+ for (j = 0; j < dc->res_pool->pipe_count; j++) {
2487
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
2488
+ if (!pipe_ctx->plane_state)
2489
+ continue;
2490
+ if (pipe_ctx->plane_state != plane_state)
2491
+ continue;
2492
+ plane_state->triplebuffer_flips = false;
2493
+ if (update_type == UPDATE_TYPE_FAST &&
2494
+ dc->hwss.program_triplebuffer != NULL &&
2495
+ !plane_state->flip_immediate && dc->debug.enable_tri_buf) {
2496
+ /*triple buffer for VUpdate only*/
2497
+ plane_state->triplebuffer_flips = true;
2498
+ }
2499
+ }
2500
+ if (update_type == UPDATE_TYPE_FULL) {
2501
+ /* force vsync flip when reconfiguring pipes to prevent underflow */
2502
+ plane_state->flip_immediate = false;
2503
+ }
2504
+ }
2505
+ }
2506
+
2507
+ // Update Type FULL, Surface updates
2508
+ for (j = 0; j < dc->res_pool->pipe_count; j++) {
2509
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
2510
+
2511
+ if (!pipe_ctx->top_pipe &&
2512
+ !pipe_ctx->prev_odm_pipe &&
13862513 pipe_ctx->stream &&
13872514 pipe_ctx->stream == stream) {
13882515 struct dc_stream_status *stream_status = NULL;
13892516
1390
- top_pipe_to_program = pipe_ctx;
1391
-
1392
- if (update_type == UPDATE_TYPE_FAST || !pipe_ctx->plane_state)
2517
+ if (!pipe_ctx->plane_state)
13932518 continue;
13942519
1395
- stream_status =
1396
- stream_get_status(context, pipe_ctx->stream);
2520
+ /* Full fe update*/
2521
+ if (update_type == UPDATE_TYPE_FAST)
2522
+ continue;
13972523
1398
- dc->hwss.apply_ctx_for_surface(
1399
- dc, pipe_ctx->stream, stream_status->plane_count, context);
2524
+ ASSERT(!pipe_ctx->plane_state->triplebuffer_flips);
14002525
1401
- if (stream_update && stream_update->abm_level && pipe_ctx->stream_res.abm) {
1402
- if (pipe_ctx->stream_res.tg->funcs->is_blanked) {
1403
- // if otg funcs defined check if blanked before programming
1404
- if (!pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg))
1405
- pipe_ctx->stream_res.abm->funcs->set_abm_level(
1406
- pipe_ctx->stream_res.abm, stream->abm_level);
1407
- } else
1408
- pipe_ctx->stream_res.abm->funcs->set_abm_level(
1409
- pipe_ctx->stream_res.abm, stream->abm_level);
2526
+ if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) {
2527
+ /*turn off triple buffer for full update*/
2528
+ dc->hwss.program_triplebuffer(
2529
+ dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips);
14102530 }
2531
+ stream_status =
2532
+ stream_get_status(context, pipe_ctx->stream);
14112533
1412
- if (stream_update && stream_update->periodic_fn_vsync_delta &&
1413
- pipe_ctx->stream_res.tg->funcs->program_vline_interrupt)
1414
- pipe_ctx->stream_res.tg->funcs->program_vline_interrupt(
1415
- pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing,
1416
- pipe_ctx->stream->periodic_fn_vsync_delta);
2534
+ if (dc->hwss.apply_ctx_for_surface)
2535
+ dc->hwss.apply_ctx_for_surface(
2536
+ dc, pipe_ctx->stream, stream_status->plane_count, context);
14172537 }
14182538 }
2539
+ if (dc->hwss.program_front_end_for_ctx && update_type != UPDATE_TYPE_FAST) {
2540
+ dc->hwss.program_front_end_for_ctx(dc, context);
2541
+#ifdef CONFIG_DRM_AMD_DC_DCN
2542
+ if (dc->debug.validate_dml_output) {
2543
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
2544
+ struct pipe_ctx cur_pipe = context->res_ctx.pipe_ctx[i];
2545
+ if (cur_pipe.stream == NULL)
2546
+ continue;
14192547
1420
- if (update_type == UPDATE_TYPE_FULL)
1421
- context_timing_trace(dc, &context->res_ctx);
2548
+ cur_pipe.plane_res.hubp->funcs->validate_dml_output(
2549
+ cur_pipe.plane_res.hubp, dc->ctx,
2550
+ &context->res_ctx.pipe_ctx[i].rq_regs,
2551
+ &context->res_ctx.pipe_ctx[i].dlg_regs,
2552
+ &context->res_ctx.pipe_ctx[i].ttu_regs);
2553
+ }
2554
+ }
2555
+#endif
2556
+ }
14222557
1423
- /* Lock the top pipe while updating plane addrs, since freesync requires
1424
- * plane addr update event triggers to be synchronized.
1425
- * top_pipe_to_program is expected to never be NULL
1426
- */
2558
+ // Update Type FAST, Surface updates
14272559 if (update_type == UPDATE_TYPE_FAST) {
1428
- dc->hwss.pipe_control_lock(dc, top_pipe_to_program, true);
2560
+ if (dc->hwss.set_flip_control_gsl)
2561
+ for (i = 0; i < surface_count; i++) {
2562
+ struct dc_plane_state *plane_state = srf_updates[i].surface;
14292563
2564
+ for (j = 0; j < dc->res_pool->pipe_count; j++) {
2565
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
2566
+
2567
+ if (pipe_ctx->stream != stream)
2568
+ continue;
2569
+
2570
+ if (pipe_ctx->plane_state != plane_state)
2571
+ continue;
2572
+
2573
+ // GSL has to be used for flip immediate
2574
+ dc->hwss.set_flip_control_gsl(pipe_ctx,
2575
+ plane_state->flip_immediate);
2576
+ }
2577
+ }
14302578 /* Perform requested Updates */
14312579 for (i = 0; i < surface_count; i++) {
14322580 struct dc_plane_state *plane_state = srf_updates[i].surface;
....@@ -1439,28 +2587,67 @@
14392587
14402588 if (pipe_ctx->plane_state != plane_state)
14412589 continue;
1442
-
2590
+ /*program triple buffer after lock based on flip type*/
2591
+ if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) {
2592
+ /*only enable triplebuffer for fast_update*/
2593
+ dc->hwss.program_triplebuffer(
2594
+ dc, pipe_ctx, plane_state->triplebuffer_flips);
2595
+ }
14432596 if (srf_updates[i].flip_addr)
14442597 dc->hwss.update_plane_addr(dc, pipe_ctx);
14452598 }
14462599 }
1447
-
1448
- dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false);
14492600 }
14502601
1451
- if (stream && stream_update && update_type > UPDATE_TYPE_FAST)
1452
- for (j = 0; j < dc->res_pool->pipe_count; j++) {
1453
- struct pipe_ctx *pipe_ctx =
1454
- &context->res_ctx.pipe_ctx[j];
2602
+ if ((update_type != UPDATE_TYPE_FAST) && dc->hwss.interdependent_update_lock)
2603
+ dc->hwss.interdependent_update_lock(dc, context, false);
2604
+ else
2605
+ dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false);
14552606
1456
- if (pipe_ctx->stream != stream)
1457
- continue;
2607
+ if ((update_type != UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed)
2608
+ if (top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) {
2609
+ top_pipe_to_program->stream_res.tg->funcs->wait_for_state(
2610
+ top_pipe_to_program->stream_res.tg,
2611
+ CRTC_STATE_VACTIVE);
2612
+ top_pipe_to_program->stream_res.tg->funcs->wait_for_state(
2613
+ top_pipe_to_program->stream_res.tg,
2614
+ CRTC_STATE_VBLANK);
2615
+ top_pipe_to_program->stream_res.tg->funcs->wait_for_state(
2616
+ top_pipe_to_program->stream_res.tg,
2617
+ CRTC_STATE_VACTIVE);
14582618
1459
- if (stream_update->hdr_static_metadata) {
1460
- resource_build_info_frame(pipe_ctx);
1461
- dc->hwss.update_info_frame(pipe_ctx);
1462
- }
2619
+ if (stream && should_use_dmub_lock(stream->link)) {
2620
+ union dmub_hw_lock_flags hw_locks = { 0 };
2621
+ struct dmub_hw_lock_inst_flags inst_flags = { 0 };
2622
+
2623
+ hw_locks.bits.lock_dig = 1;
2624
+ inst_flags.dig_inst = top_pipe_to_program->stream_res.tg->inst;
2625
+
2626
+ dmub_hw_lock_mgr_cmd(dc->ctx->dmub_srv,
2627
+ false,
2628
+ &hw_locks,
2629
+ &inst_flags);
2630
+ } else
2631
+ top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_disable(
2632
+ top_pipe_to_program->stream_res.tg);
14632633 }
2634
+
2635
+ if (update_type != UPDATE_TYPE_FAST)
2636
+ dc->hwss.post_unlock_program_front_end(dc, context);
2637
+
2638
+ // Fire manual trigger only when bottom plane is flipped
2639
+ for (j = 0; j < dc->res_pool->pipe_count; j++) {
2640
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
2641
+
2642
+ if (pipe_ctx->bottom_pipe ||
2643
+ !pipe_ctx->stream ||
2644
+ pipe_ctx->stream != stream ||
2645
+ !pipe_ctx->plane_state->update_flags.bits.addr_update)
2646
+ continue;
2647
+
2648
+ if (pipe_ctx->stream_res.tg->funcs->program_manual_trigger)
2649
+ pipe_ctx->stream_res.tg->funcs->program_manual_trigger(pipe_ctx->stream_res.tg);
2650
+ }
14642651 }
14652652
14662653 void dc_commit_updates_for_stream(struct dc *dc,
....@@ -1468,7 +2655,6 @@
14682655 int surface_count,
14692656 struct dc_stream_state *stream,
14702657 struct dc_stream_update *stream_update,
1471
- struct dc_plane_state **plane_states,
14722658 struct dc_state *state)
14732659 {
14742660 const struct dc_stream_status *stream_status;
....@@ -1490,7 +2676,7 @@
14902676 if (update_type >= UPDATE_TYPE_FULL) {
14912677
14922678 /* initialize scratch memory for building context */
1493
- context = dc_create_state();
2679
+ context = dc_create_state(dc);
14942680 if (context == NULL) {
14952681 DC_ERROR("Failed to allocate new validate context!\n");
14962682 return;
....@@ -1511,24 +2697,28 @@
15112697 for (i = 0; i < surface_count; i++) {
15122698 struct dc_plane_state *surface = srf_updates[i].surface;
15132699
1514
- /* TODO: On flip we don't build the state, so it still has the
1515
- * old address. Which is why we are updating the address here
1516
- */
1517
- if (srf_updates[i].flip_addr) {
1518
- surface->address = srf_updates[i].flip_addr->address;
1519
- surface->flip_immediate = srf_updates[i].flip_addr->flip_immediate;
1520
-
1521
- }
2700
+ copy_surface_update_to_plane(surface, &srf_updates[i]);
15222701
15232702 if (update_type >= UPDATE_TYPE_MED) {
15242703 for (j = 0; j < dc->res_pool->pipe_count; j++) {
1525
- struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
2704
+ struct pipe_ctx *pipe_ctx =
2705
+ &context->res_ctx.pipe_ctx[j];
15262706
15272707 if (pipe_ctx->plane_state != surface)
15282708 continue;
15292709
15302710 resource_build_scaling_params(pipe_ctx);
15312711 }
2712
+ }
2713
+ }
2714
+
2715
+ copy_stream_update_to_stream(dc, context, stream, stream_update);
2716
+
2717
+ if (update_type >= UPDATE_TYPE_FULL) {
2718
+ if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false)) {
2719
+ DC_ERROR("Mode validation failed for stream update!\n");
2720
+ dc_release_state(context);
2721
+ return;
15322722 }
15332723 }
15342724
....@@ -1575,6 +2765,19 @@
15752765 return NULL;
15762766 }
15772767
2768
+struct dc_stream_state *dc_stream_find_from_link(const struct dc_link *link)
2769
+{
2770
+ uint8_t i;
2771
+ struct dc_context *ctx = link->ctx;
2772
+
2773
+ for (i = 0; i < ctx->dc->current_state->stream_count; i++) {
2774
+ if (ctx->dc->current_state->streams[i]->link == link)
2775
+ return ctx->dc->current_state->streams[i];
2776
+ }
2777
+
2778
+ return NULL;
2779
+}
2780
+
15782781 enum dc_irq_source dc_interrupt_to_irq_source(
15792782 struct dc *dc,
15802783 uint32_t src_id,
....@@ -1583,6 +2786,9 @@
15832786 return dal_irq_service_to_irq_source(dc->res_pool->irqs, src_id, ext_id);
15842787 }
15852788
2789
+/**
2790
+ * dc_interrupt_set() - Enable/disable an AMD hw interrupt source
2791
+ */
15862792 bool dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable)
15872793 {
15882794
....@@ -1597,55 +2803,81 @@
15972803 dal_irq_service_ack(dc->res_pool->irqs, src);
15982804 }
15992805
2806
+void dc_power_down_on_boot(struct dc *dc)
2807
+{
2808
+ if (dc->ctx->dce_environment != DCE_ENV_VIRTUAL_HW &&
2809
+ dc->hwss.power_down_on_boot)
2810
+ dc->hwss.power_down_on_boot(dc);
2811
+}
2812
+
16002813 void dc_set_power_state(
16012814 struct dc *dc,
16022815 enum dc_acpi_cm_power_state power_state)
16032816 {
16042817 struct kref refcount;
2818
+ struct display_mode_lib *dml;
16052819
16062820 switch (power_state) {
16072821 case DC_ACPI_CM_POWER_STATE_D0:
16082822 dc_resource_state_construct(dc, dc->current_state);
16092823
2824
+ if (dc->ctx->dmub_srv)
2825
+ dc_dmub_srv_wait_phy_init(dc->ctx->dmub_srv);
2826
+
16102827 dc->hwss.init_hw(dc);
16112828
1612
-#ifdef CONFIG_DRM_AMD_DC_DCN2_0
16132829 if (dc->hwss.init_sys_ctx != NULL &&
16142830 dc->vm_pa_config.valid) {
16152831 dc->hwss.init_sys_ctx(dc->hwseq, dc, &dc->vm_pa_config);
16162832 }
1617
-#endif
16182833
16192834 break;
16202835 default:
1621
-
1622
- dc->hwss.power_down(dc);
1623
-
2836
+ ASSERT(dc->current_state->stream_count == 0);
16242837 /* Zero out the current context so that on resume we start with
16252838 * clean state, and dc hw programming optimizations will not
16262839 * cause any trouble.
16272840 */
2841
+ dml = kzalloc(sizeof(struct display_mode_lib),
2842
+ GFP_KERNEL);
2843
+
2844
+ ASSERT(dml);
2845
+ if (!dml)
2846
+ return;
16282847
16292848 /* Preserve refcount */
16302849 refcount = dc->current_state->refcount;
2850
+ /* Preserve display mode lib */
2851
+ memcpy(dml, &dc->current_state->bw_ctx.dml, sizeof(struct display_mode_lib));
2852
+
16312853 dc_resource_state_destruct(dc->current_state);
16322854 memset(dc->current_state, 0,
16332855 sizeof(*dc->current_state));
16342856
16352857 dc->current_state->refcount = refcount;
2858
+ dc->current_state->bw_ctx.dml = *dml;
2859
+
2860
+ kfree(dml);
16362861
16372862 break;
16382863 }
1639
-
16402864 }
16412865
16422866 void dc_resume(struct dc *dc)
16432867 {
1644
-
16452868 uint32_t i;
16462869
16472870 for (i = 0; i < dc->link_count; i++)
16482871 core_link_resume(dc->links[i]);
2872
+}
2873
+
2874
+bool dc_is_dmcu_initialized(struct dc *dc)
2875
+{
2876
+ struct dmcu *dmcu = dc->res_pool->dmcu;
2877
+
2878
+ if (dmcu)
2879
+ return dmcu->funcs->is_dmcu_initialized(dmcu);
2880
+ return false;
16492881 }
16502882
16512883 bool dc_submit_i2c(
....@@ -1656,9 +2888,19 @@
16562888
16572889 struct dc_link *link = dc->links[link_index];
16582890 struct ddc_service *ddc = link->ddc;
2891
+ return dce_i2c_submit_command(
2892
+ dc->res_pool,
2893
+ ddc->ddc_pin,
2894
+ cmd);
2895
+}
16592896
1660
- return dal_i2caux_submit_i2c_command(
1661
- ddc->ctx->i2caux,
2897
+bool dc_submit_i2c_oem(
2898
+ struct dc *dc,
2899
+ struct i2c_command *cmd)
2900
+{
2901
+ struct ddc_service *ddc = dc->res_pool->oem_device;
2902
+ return dce_i2c_submit_command(
2903
+ dc->res_pool,
16622904 ddc->ddc_pin,
16632905 cmd);
16642906 }
....@@ -1678,6 +2920,11 @@
16782920 return true;
16792921 }
16802922
2923
+/**
2924
+ * dc_link_add_remote_sink() - Create a sink and attach it to an existing link
2925
+ *
2926
+ * EDID length is in bytes
2927
+ */
16812928 struct dc_sink *dc_link_add_remote_sink(
16822929 struct dc_link *link,
16832930 const uint8_t *edid,
....@@ -1736,6 +2983,12 @@
17362983 return NULL;
17372984 }
17382985
2986
+/**
2987
+ * dc_link_remove_remote_sink() - Remove a remote sink from a dc_link
2988
+ *
2989
+ * Note that this just removes the struct dc_sink - it doesn't
2990
+ * program hardware or alter other members of dc_link
2991
+ */
17392992 void dc_link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink)
17402993 {
17412994 int i;
....@@ -1761,3 +3014,105 @@
17613014 }
17623015 }
17633016 }
3017
+
3018
+void get_clock_requirements_for_state(struct dc_state *state, struct AsicStateEx *info)
3019
+{
3020
+ info->displayClock = (unsigned int)state->bw_ctx.bw.dcn.clk.dispclk_khz;
3021
+ info->engineClock = (unsigned int)state->bw_ctx.bw.dcn.clk.dcfclk_khz;
3022
+ info->memoryClock = (unsigned int)state->bw_ctx.bw.dcn.clk.dramclk_khz;
3023
+ info->maxSupportedDppClock = (unsigned int)state->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz;
3024
+ info->dppClock = (unsigned int)state->bw_ctx.bw.dcn.clk.dppclk_khz;
3025
+ info->socClock = (unsigned int)state->bw_ctx.bw.dcn.clk.socclk_khz;
3026
+ info->dcfClockDeepSleep = (unsigned int)state->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz;
3027
+ info->fClock = (unsigned int)state->bw_ctx.bw.dcn.clk.fclk_khz;
3028
+ info->phyClock = (unsigned int)state->bw_ctx.bw.dcn.clk.phyclk_khz;
3029
+}
3030
+enum dc_status dc_set_clock(struct dc *dc, enum dc_clock_type clock_type, uint32_t clk_khz, uint32_t stepping)
3031
+{
3032
+ if (dc->hwss.set_clock)
3033
+ return dc->hwss.set_clock(dc, clock_type, clk_khz, stepping);
3034
+ return DC_ERROR_UNEXPECTED;
3035
+}
3036
+void dc_get_clock(struct dc *dc, enum dc_clock_type clock_type, struct dc_clock_config *clock_cfg)
3037
+{
3038
+ if (dc->hwss.get_clock)
3039
+ dc->hwss.get_clock(dc, clock_type, clock_cfg);
3040
+}
3041
+
3042
+/* enable/disable eDP PSR without specify stream for eDP */
3043
+bool dc_set_psr_allow_active(struct dc *dc, bool enable)
3044
+{
3045
+ int i;
3046
+
3047
+ for (i = 0; i < dc->current_state->stream_count ; i++) {
3048
+ struct dc_link *link;
3049
+ struct dc_stream_state *stream = dc->current_state->streams[i];
3050
+
3051
+ link = stream->link;
3052
+ if (!link)
3053
+ continue;
3054
+
3055
+ if (link->psr_settings.psr_feature_enabled) {
3056
+ if (enable && !link->psr_settings.psr_allow_active)
3057
+ return dc_link_set_psr_allow_active(link, true, false);
3058
+ else if (!enable && link->psr_settings.psr_allow_active)
3059
+ return dc_link_set_psr_allow_active(link, false, true);
3060
+ }
3061
+ }
3062
+
3063
+ return true;
3064
+}
3065
+
3066
+#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
3067
+
3068
+void dc_allow_idle_optimizations(struct dc *dc, bool allow)
3069
+{
3070
+ if (dc->debug.disable_idle_power_optimizations)
3071
+ return;
3072
+
3073
+ if (allow == dc->idle_optimizations_allowed)
3074
+ return;
3075
+
3076
+ if (dc->hwss.apply_idle_power_optimizations && dc->hwss.apply_idle_power_optimizations(dc, allow))
3077
+ dc->idle_optimizations_allowed = allow;
3078
+}
3079
+
3080
+/*
3081
+ * blank all streams, and set min and max memory clock to
3082
+ * lowest and highest DPM level, respectively
3083
+ */
3084
+void dc_unlock_memory_clock_frequency(struct dc *dc)
3085
+{
3086
+ unsigned int i;
3087
+
3088
+ for (i = 0; i < MAX_PIPES; i++)
3089
+ if (dc->current_state->res_ctx.pipe_ctx[i].plane_state)
3090
+ core_link_disable_stream(&dc->current_state->res_ctx.pipe_ctx[i]);
3091
+
3092
+ dc->clk_mgr->funcs->set_hard_min_memclk(dc->clk_mgr, false);
3093
+ dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr);
3094
+}
3095
+
3096
+/*
3097
+ * set min memory clock to the min required for current mode,
3098
+ * max to maxDPM, and unblank streams
3099
+ */
3100
+void dc_lock_memory_clock_frequency(struct dc *dc)
3101
+{
3102
+ unsigned int i;
3103
+
3104
+ dc->clk_mgr->funcs->get_memclk_states_from_smu(dc->clk_mgr);
3105
+ dc->clk_mgr->funcs->set_hard_min_memclk(dc->clk_mgr, true);
3106
+ dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr);
3107
+
3108
+ for (i = 0; i < MAX_PIPES; i++)
3109
+ if (dc->current_state->res_ctx.pipe_ctx[i].plane_state)
3110
+ core_link_enable_stream(dc->current_state, &dc->current_state->res_ctx.pipe_ctx[i]);
3111
+}
3112
+
3113
+bool dc_is_plane_eligible_for_idle_optimizaitons(struct dc *dc,
3114
+ struct dc_plane_state *plane)
3115
+{
3116
+ return false;
3117
+}
3118
+#endif