forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-04 1543e317f1da31b75942316931e8f491a8920811
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,67 @@
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
+ kfree(dc_ctx);
620
+ ASSERT_CRITICAL(false);
621
+ return false;
622
+ }
623
+
624
+ dc->ctx = dc_ctx;
625
+
626
+ return true;
627
+}
628
+
629
+static bool dc_construct(struct dc *dc,
503630 const struct dc_init_data *init_params)
504631 {
505632 struct dc_context *dc_ctx;
506633 struct bw_calcs_dceip *dc_dceip;
507634 struct bw_calcs_vbios *dc_vbios;
508
-#ifdef CONFIG_DRM_AMD_DC_DCN1_0
635
+#ifdef CONFIG_DRM_AMD_DC_DCN
509636 struct dcn_soc_bounding_box *dcn_soc;
510637 struct dcn_ip_params *dcn_ip;
511638 #endif
512639
513
- enum dce_version dc_version = DCE_VERSION_UNKNOWN;
640
+ dc->config = init_params->flags;
641
+
642
+ // Allocate memory for the vm_helper
643
+ dc->vm_helper = kzalloc(sizeof(struct vm_helper), GFP_KERNEL);
644
+ if (!dc->vm_helper) {
645
+ dm_error("%s: failed to create dc->vm_helper\n", __func__);
646
+ goto fail;
647
+ }
648
+
649
+ memcpy(&dc->bb_overrides, &init_params->bb_overrides, sizeof(dc->bb_overrides));
514650
515651 dc_dceip = kzalloc(sizeof(*dc_dceip), GFP_KERNEL);
516652 if (!dc_dceip) {
....@@ -527,7 +663,7 @@
527663 }
528664
529665 dc->bw_vbios = dc_vbios;
530
-#ifdef CONFIG_DRM_AMD_DC_DCN1_0
666
+#ifdef CONFIG_DRM_AMD_DC_DCN
531667 dcn_soc = kzalloc(sizeof(*dcn_soc), GFP_KERNEL);
532668 if (!dcn_soc) {
533669 dm_error("%s: failed to create dcn_soc\n", __func__);
....@@ -543,34 +679,15 @@
543679 }
544680
545681 dc->dcn_ip = dcn_ip;
682
+ dc->soc_bounding_box = init_params->soc_bounding_box;
546683 #endif
547684
548
- dc_ctx = kzalloc(sizeof(*dc_ctx), GFP_KERNEL);
549
- if (!dc_ctx) {
685
+ if (!dc_construct_ctx(dc, init_params)) {
550686 dm_error("%s: failed to create ctx\n", __func__);
551687 goto fail;
552688 }
553689
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;
690
+ dc_ctx = dc->ctx;
574691
575692 /* Resource should construct all asic specific resources.
576693 * This should be the only place where we need to parse the asic id
....@@ -585,7 +702,7 @@
585702 bp_init_data.bios = init_params->asic_id.atombios_base_address;
586703
587704 dc_ctx->dc_bios = dal_bios_parser_create(
588
- &bp_init_data, dc_version);
705
+ &bp_init_data, dc_ctx->dce_version);
589706
590707 if (!dc_ctx->dc_bios) {
591708 ASSERT_CRITICAL(false);
....@@ -593,19 +710,13 @@
593710 }
594711
595712 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;
604713 }
714
+
715
+ dc->vendor_signature = init_params->vendor_signature;
605716
606717 /* Create GPIO service */
607718 dc_ctx->gpio_service = dal_gpio_service_create(
608
- dc_version,
719
+ dc_ctx->dce_version,
609720 dc_ctx->dce_environment,
610721 dc_ctx);
611722
....@@ -614,13 +725,33 @@
614725 goto fail;
615726 }
616727
617
- dc->res_pool = dc_create_resource_pool(
618
- dc,
619
- init_params->num_virtual_links,
620
- dc_version,
621
- init_params->asic_id);
728
+ dc->res_pool = dc_create_resource_pool(dc, init_params, dc_ctx->dce_version);
622729 if (!dc->res_pool)
623730 goto fail;
731
+
732
+ dc->clk_mgr = dc_clk_mgr_create(dc->ctx, dc->res_pool->pp_smu, dc->res_pool->dccg);
733
+ if (!dc->clk_mgr)
734
+ goto fail;
735
+#ifdef CONFIG_DRM_AMD_DC_DCN3_0
736
+ dc->clk_mgr->force_smu_not_present = init_params->force_smu_not_present;
737
+#endif
738
+
739
+ dc->debug.force_ignore_link_settings = init_params->force_ignore_link_settings;
740
+
741
+ if (dc->res_pool->funcs->update_bw_bounding_box)
742
+ dc->res_pool->funcs->update_bw_bounding_box(dc, dc->clk_mgr->bw_params);
743
+
744
+ /* Creation of current_state must occur after dc->dml
745
+ * is initialized in dc_create_resource_pool because
746
+ * on creation it copies the contents of dc->dml
747
+ */
748
+
749
+ dc->current_state = dc_create_state(dc);
750
+
751
+ if (!dc->current_state) {
752
+ dm_error("%s: failed to create validate ctx\n", __func__);
753
+ goto fail;
754
+ }
624755
625756 dc_resource_state_construct(dc, dc->current_state);
626757
....@@ -630,15 +761,48 @@
630761 return true;
631762
632763 fail:
633
-
634
- destruct(dc);
635764 return false;
765
+}
766
+
767
+static bool disable_all_writeback_pipes_for_stream(
768
+ const struct dc *dc,
769
+ struct dc_stream_state *stream,
770
+ struct dc_state *context)
771
+{
772
+ int i;
773
+
774
+ for (i = 0; i < stream->num_wb_info; i++)
775
+ stream->writeback_info[i].wb_enabled = false;
776
+
777
+ return true;
778
+}
779
+
780
+void apply_ctx_interdependent_lock(struct dc *dc, struct dc_state *context, struct dc_stream_state *stream, bool lock)
781
+{
782
+ int i = 0;
783
+
784
+ /* Checks if interdependent update function pointer is NULL or not, takes care of DCE110 case */
785
+ if (dc->hwss.interdependent_update_lock)
786
+ dc->hwss.interdependent_update_lock(dc, context, lock);
787
+ else {
788
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
789
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
790
+ struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
791
+
792
+ // Copied conditions that were previously in dce110_apply_ctx_for_surface
793
+ if (stream == pipe_ctx->stream) {
794
+ if (!pipe_ctx->top_pipe &&
795
+ (pipe_ctx->plane_state || old_pipe_ctx->plane_state))
796
+ dc->hwss.pipe_control_lock(dc, pipe_ctx, lock);
797
+ }
798
+ }
799
+ }
636800 }
637801
638802 static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
639803 {
640804 int i, j;
641
- struct dc_state *dangling_context = dc_create_state();
805
+ struct dc_state *dangling_context = dc_create_state(dc);
642806 struct dc_state *current_ctx;
643807
644808 if (dangling_context == NULL)
....@@ -659,13 +823,106 @@
659823 }
660824 if (should_disable && old_stream) {
661825 dc_rem_all_planes_for_stream(dc, old_stream, dangling_context);
662
- dc->hwss.apply_ctx_for_surface(dc, old_stream, 0, dangling_context);
826
+ disable_all_writeback_pipes_for_stream(dc, old_stream, dangling_context);
827
+
828
+ if (dc->hwss.apply_ctx_for_surface) {
829
+ apply_ctx_interdependent_lock(dc, dc->current_state, old_stream, true);
830
+ dc->hwss.apply_ctx_for_surface(dc, old_stream, 0, dangling_context);
831
+ apply_ctx_interdependent_lock(dc, dc->current_state, old_stream, false);
832
+ dc->hwss.post_unlock_program_front_end(dc, dangling_context);
833
+ }
834
+ if (dc->hwss.program_front_end_for_ctx) {
835
+ dc->hwss.interdependent_update_lock(dc, dc->current_state, true);
836
+ dc->hwss.program_front_end_for_ctx(dc, dangling_context);
837
+ dc->hwss.interdependent_update_lock(dc, dc->current_state, false);
838
+ dc->hwss.post_unlock_program_front_end(dc, dangling_context);
839
+ }
663840 }
664841 }
665842
666843 current_ctx = dc->current_state;
667844 dc->current_state = dangling_context;
668845 dc_release_state(current_ctx);
846
+}
847
+
848
+static void disable_vbios_mode_if_required(
849
+ struct dc *dc,
850
+ struct dc_state *context)
851
+{
852
+ unsigned int i, j;
853
+
854
+ /* check if timing_changed, disable stream*/
855
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
856
+ struct dc_stream_state *stream = NULL;
857
+ struct dc_link *link = NULL;
858
+ struct pipe_ctx *pipe = NULL;
859
+
860
+ pipe = &context->res_ctx.pipe_ctx[i];
861
+ stream = pipe->stream;
862
+ if (stream == NULL)
863
+ continue;
864
+
865
+ if (stream->link->local_sink &&
866
+ stream->link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
867
+ link = stream->link;
868
+ }
869
+
870
+ if (link != NULL) {
871
+ unsigned int enc_inst, tg_inst = 0;
872
+ unsigned int pix_clk_100hz;
873
+
874
+ enc_inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);
875
+ if (enc_inst != ENGINE_ID_UNKNOWN) {
876
+ for (j = 0; j < dc->res_pool->stream_enc_count; j++) {
877
+ if (dc->res_pool->stream_enc[j]->id == enc_inst) {
878
+ tg_inst = dc->res_pool->stream_enc[j]->funcs->dig_source_otg(
879
+ dc->res_pool->stream_enc[j]);
880
+ break;
881
+ }
882
+ }
883
+
884
+ dc->res_pool->dp_clock_source->funcs->get_pixel_clk_frequency_100hz(
885
+ dc->res_pool->dp_clock_source,
886
+ tg_inst, &pix_clk_100hz);
887
+
888
+ if (link->link_status.link_active) {
889
+ uint32_t requested_pix_clk_100hz =
890
+ pipe->stream_res.pix_clk_params.requested_pix_clk_100hz;
891
+
892
+ if (pix_clk_100hz != requested_pix_clk_100hz) {
893
+ core_link_disable_stream(pipe);
894
+ pipe->stream->dpms_off = false;
895
+ }
896
+ }
897
+ }
898
+ }
899
+ }
900
+}
901
+
902
+static void wait_for_no_pipes_pending(struct dc *dc, struct dc_state *context)
903
+{
904
+ int i;
905
+ PERF_TRACE();
906
+ for (i = 0; i < MAX_PIPES; i++) {
907
+ int count = 0;
908
+ struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
909
+
910
+ if (!pipe->plane_state)
911
+ continue;
912
+
913
+ /* Timeout 100 ms */
914
+ while (count < 100000) {
915
+ /* Must set to false to start with, due to OR in update function */
916
+ pipe->plane_state->status.is_flip_pending = false;
917
+ dc->hwss.update_pending_status(pipe);
918
+ if (!pipe->plane_state->status.is_flip_pending)
919
+ break;
920
+ udelay(1);
921
+ count++;
922
+ }
923
+ ASSERT(!pipe->plane_state->status.is_flip_pending);
924
+ }
925
+ PERF_TRACE();
669926 }
670927
671928 /*******************************************************************************
....@@ -680,36 +937,43 @@
680937 if (NULL == dc)
681938 goto alloc_fail;
682939
683
- if (false == construct(dc, init_params))
684
- goto construct_fail;
940
+ if (init_params->dce_environment == DCE_ENV_VIRTUAL_HW) {
941
+ if (false == dc_construct_ctx(dc, init_params)) {
942
+ dc_destruct(dc);
943
+ goto construct_fail;
944
+ }
945
+ } else {
946
+ if (false == dc_construct(dc, init_params)) {
947
+ dc_destruct(dc);
948
+ goto construct_fail;
949
+ }
685950
686
- /*TODO: separate HW and SW initialization*/
687
- dc->hwss.init_hw(dc);
951
+ full_pipe_count = dc->res_pool->pipe_count;
952
+ if (dc->res_pool->underlay_pipe_index != NO_UNDERLAY_PIPE)
953
+ full_pipe_count--;
954
+ dc->caps.max_streams = min(
955
+ full_pipe_count,
956
+ dc->res_pool->stream_enc_count);
688957
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);
958
+ dc->optimize_seamless_boot_streams = 0;
959
+ dc->caps.max_links = dc->link_count;
960
+ dc->caps.max_audios = dc->res_pool->audio_count;
961
+ dc->caps.linear_pitch_alignment = 64;
695962
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;
963
+ dc->caps.max_dp_protocol_version = DP_VERSION_1_4;
964
+
965
+ if (dc->res_pool->dmcu != NULL)
966
+ dc->versions.dmcu_version = dc->res_pool->dmcu->dmcu_version;
967
+ }
699968
700969 /* Populate versioning information */
701970 dc->versions.dc_ver = DC_VER;
702971
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;
972
+ dc->build_id = DC_BUILD_ID;
707973
708974 DC_LOG_DC("Display Core initialized\n");
709975
710976
711
- /* TODO: missing feature to be enabled */
712
- dc->debug.disable_dfs_bypass = true;
713977
714978 return dc;
715979
....@@ -720,9 +984,30 @@
720984 return NULL;
721985 }
722986
987
+void dc_hardware_init(struct dc *dc)
988
+{
989
+ if (dc->ctx->dce_environment != DCE_ENV_VIRTUAL_HW)
990
+ dc->hwss.init_hw(dc);
991
+}
992
+
993
+void dc_init_callbacks(struct dc *dc,
994
+ const struct dc_callback_init *init_params)
995
+{
996
+#ifdef CONFIG_DRM_AMD_DC_HDCP
997
+ dc->ctx->cp_psp = init_params->cp_psp;
998
+#endif
999
+}
1000
+
1001
+void dc_deinit_callbacks(struct dc *dc)
1002
+{
1003
+#ifdef CONFIG_DRM_AMD_DC_HDCP
1004
+ memset(&dc->ctx->cp_psp, 0, sizeof(dc->ctx->cp_psp));
1005
+#endif
1006
+}
1007
+
7231008 void dc_destroy(struct dc **dc)
7241009 {
725
- destruct(*dc);
1010
+ dc_destruct(*dc);
7261011 kfree(*dc);
7271012 *dc = NULL;
7281013 }
....@@ -755,8 +1040,9 @@
7551040 struct dc *dc,
7561041 struct dc_state *ctx)
7571042 {
758
- int i, j;
1043
+ int i, j, k;
7591044 int group_index = 0;
1045
+ int num_group = 0;
7601046 int pipe_count = dc->res_pool->pipe_count;
7611047 struct pipe_ctx *unsynced_pipes[MAX_PIPES] = { NULL };
7621048
....@@ -795,22 +1081,46 @@
7951081
7961082 /* set first unblanked pipe as master */
7971083 for (j = 0; j < group_size; j++) {
798
- struct pipe_ctx *temp;
1084
+ bool is_blanked;
7991085
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)) {
1086
+ if (pipe_set[j]->stream_res.opp->funcs->dpg_is_blanked)
1087
+ is_blanked =
1088
+ pipe_set[j]->stream_res.opp->funcs->dpg_is_blanked(pipe_set[j]->stream_res.opp);
1089
+ else
1090
+ is_blanked =
1091
+ pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg);
1092
+ if (!is_blanked) {
8011093 if (j == 0)
8021094 break;
8031095
804
- temp = pipe_set[0];
805
- pipe_set[0] = pipe_set[j];
806
- pipe_set[j] = temp;
1096
+ swap(pipe_set[0], pipe_set[j]);
8071097 break;
8081098 }
8091099 }
8101100
1101
+
1102
+ for (k = 0; k < group_size; k++) {
1103
+ struct dc_stream_status *status = dc_stream_get_status_from_state(ctx, pipe_set[k]->stream);
1104
+
1105
+ status->timing_sync_info.group_id = num_group;
1106
+ status->timing_sync_info.group_size = group_size;
1107
+ if (k == 0)
1108
+ status->timing_sync_info.master = true;
1109
+ else
1110
+ status->timing_sync_info.master = false;
1111
+
1112
+ }
8111113 /* remove any other unblanked pipes as they have already been synced */
8121114 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)) {
1115
+ bool is_blanked;
1116
+
1117
+ if (pipe_set[j]->stream_res.opp->funcs->dpg_is_blanked)
1118
+ is_blanked =
1119
+ pipe_set[j]->stream_res.opp->funcs->dpg_is_blanked(pipe_set[j]->stream_res.opp);
1120
+ else
1121
+ is_blanked =
1122
+ pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg);
1123
+ if (!is_blanked) {
8141124 group_size--;
8151125 pipe_set[j] = pipe_set[group_size];
8161126 j--;
....@@ -822,6 +1132,7 @@
8221132 dc, group_index, group_size, pipe_set);
8231133 group_index++;
8241134 }
1135
+ num_group++;
8251136 }
8261137 }
8271138
....@@ -840,6 +1151,123 @@
8401151 }
8411152
8421153 return false;
1154
+}
1155
+
1156
+bool dc_validate_seamless_boot_timing(const struct dc *dc,
1157
+ const struct dc_sink *sink,
1158
+ struct dc_crtc_timing *crtc_timing)
1159
+{
1160
+ struct timing_generator *tg;
1161
+ struct stream_encoder *se = NULL;
1162
+
1163
+ struct dc_crtc_timing hw_crtc_timing = {0};
1164
+
1165
+ struct dc_link *link = sink->link;
1166
+ unsigned int i, enc_inst, tg_inst = 0;
1167
+
1168
+ // Seamless port only support single DP and EDP so far
1169
+ if (sink->sink_signal != SIGNAL_TYPE_DISPLAY_PORT &&
1170
+ sink->sink_signal != SIGNAL_TYPE_EDP)
1171
+ return false;
1172
+
1173
+ /* Check for enabled DIG to identify enabled display */
1174
+ if (!link->link_enc->funcs->is_dig_enabled(link->link_enc))
1175
+ return false;
1176
+
1177
+ enc_inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);
1178
+
1179
+ if (enc_inst == ENGINE_ID_UNKNOWN)
1180
+ return false;
1181
+
1182
+ for (i = 0; i < dc->res_pool->stream_enc_count; i++) {
1183
+ if (dc->res_pool->stream_enc[i]->id == enc_inst) {
1184
+
1185
+ se = dc->res_pool->stream_enc[i];
1186
+
1187
+ tg_inst = dc->res_pool->stream_enc[i]->funcs->dig_source_otg(
1188
+ dc->res_pool->stream_enc[i]);
1189
+ break;
1190
+ }
1191
+ }
1192
+
1193
+ // tg_inst not found
1194
+ if (i == dc->res_pool->stream_enc_count)
1195
+ return false;
1196
+
1197
+ if (tg_inst >= dc->res_pool->timing_generator_count)
1198
+ return false;
1199
+
1200
+ tg = dc->res_pool->timing_generators[tg_inst];
1201
+
1202
+ if (!tg->funcs->get_hw_timing)
1203
+ return false;
1204
+
1205
+ if (!tg->funcs->get_hw_timing(tg, &hw_crtc_timing))
1206
+ return false;
1207
+
1208
+ if (crtc_timing->h_total != hw_crtc_timing.h_total)
1209
+ return false;
1210
+
1211
+ if (crtc_timing->h_border_left != hw_crtc_timing.h_border_left)
1212
+ return false;
1213
+
1214
+ if (crtc_timing->h_addressable != hw_crtc_timing.h_addressable)
1215
+ return false;
1216
+
1217
+ if (crtc_timing->h_border_right != hw_crtc_timing.h_border_right)
1218
+ return false;
1219
+
1220
+ if (crtc_timing->h_front_porch != hw_crtc_timing.h_front_porch)
1221
+ return false;
1222
+
1223
+ if (crtc_timing->h_sync_width != hw_crtc_timing.h_sync_width)
1224
+ return false;
1225
+
1226
+ if (crtc_timing->v_total != hw_crtc_timing.v_total)
1227
+ return false;
1228
+
1229
+ if (crtc_timing->v_border_top != hw_crtc_timing.v_border_top)
1230
+ return false;
1231
+
1232
+ if (crtc_timing->v_addressable != hw_crtc_timing.v_addressable)
1233
+ return false;
1234
+
1235
+ if (crtc_timing->v_border_bottom != hw_crtc_timing.v_border_bottom)
1236
+ return false;
1237
+
1238
+ if (crtc_timing->v_front_porch != hw_crtc_timing.v_front_porch)
1239
+ return false;
1240
+
1241
+ if (crtc_timing->v_sync_width != hw_crtc_timing.v_sync_width)
1242
+ return false;
1243
+
1244
+ if (dc_is_dp_signal(link->connector_signal)) {
1245
+ unsigned int pix_clk_100hz;
1246
+
1247
+ dc->res_pool->dp_clock_source->funcs->get_pixel_clk_frequency_100hz(
1248
+ dc->res_pool->dp_clock_source,
1249
+ tg_inst, &pix_clk_100hz);
1250
+
1251
+ if (crtc_timing->pix_clk_100hz != pix_clk_100hz)
1252
+ return false;
1253
+
1254
+ if (!se->funcs->dp_get_pixel_format)
1255
+ return false;
1256
+
1257
+ if (!se->funcs->dp_get_pixel_format(
1258
+ se,
1259
+ &hw_crtc_timing.pixel_encoding,
1260
+ &hw_crtc_timing.display_color_depth))
1261
+ return false;
1262
+
1263
+ if (hw_crtc_timing.display_color_depth != crtc_timing->display_color_depth)
1264
+ return false;
1265
+
1266
+ if (hw_crtc_timing.pixel_encoding != crtc_timing->pixel_encoding)
1267
+ return false;
1268
+ }
1269
+
1270
+ return true;
8431271 }
8441272
8451273 bool dc_enable_stereo(
....@@ -867,6 +1295,27 @@
8671295 return ret;
8681296 }
8691297
1298
+void dc_trigger_sync(struct dc *dc, struct dc_state *context)
1299
+{
1300
+ if (context->stream_count > 1 && !dc->debug.disable_timing_sync) {
1301
+ enable_timing_multisync(dc, context);
1302
+ program_timing_sync(dc, context);
1303
+ }
1304
+}
1305
+
1306
+static uint8_t get_stream_mask(struct dc *dc, struct dc_state *context)
1307
+{
1308
+ int i;
1309
+ unsigned int stream_mask = 0;
1310
+
1311
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
1312
+ if (context->res_ctx.pipe_ctx[i].stream)
1313
+ stream_mask |= 1 << i;
1314
+ }
1315
+
1316
+ return stream_mask;
1317
+}
1318
+
8701319 /*
8711320 * Applies given context to HW and copy it into current context.
8721321 * It's up to the user to release the src context afterwards.
....@@ -879,32 +1328,45 @@
8791328 int i, k, l;
8801329 struct dc_stream_state *dc_streams[MAX_STREAMS] = {0};
8811330
882
- disable_dangling_plane(dc, context);
1331
+#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
1332
+ dc_allow_idle_optimizations(dc, false);
1333
+#endif
8831334
8841335 for (i = 0; i < context->stream_count; i++)
8851336 dc_streams[i] = context->streams[i];
8861337
887
- if (!dcb->funcs->is_accelerated_mode(dcb))
1338
+ if (!dcb->funcs->is_accelerated_mode(dcb)) {
1339
+ disable_vbios_mode_if_required(dc, context);
8881340 dc->hwss.enable_accelerated_mode(dc, context);
1341
+ }
8891342
890
- dc->hwss.set_bandwidth(dc, context, false);
1343
+ for (i = 0; i < context->stream_count; i++)
1344
+ if (context->streams[i]->apply_seamless_boot_optimization)
1345
+ dc->optimize_seamless_boot_streams++;
8911346
1347
+ if (context->stream_count > dc->optimize_seamless_boot_streams ||
1348
+ context->stream_count == 0)
1349
+ dc->hwss.prepare_bandwidth(dc, context);
1350
+
1351
+ disable_dangling_plane(dc, context);
8921352 /* re-program planes for existing stream, in case we need to
8931353 * free up plane resource for later use
8941354 */
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 */
1355
+ if (dc->hwss.apply_ctx_for_surface) {
1356
+ for (i = 0; i < context->stream_count; i++) {
1357
+ if (context->streams[i]->mode_changed)
1358
+ continue;
1359
+ apply_ctx_interdependent_lock(dc, context, context->streams[i], true);
1360
+ dc->hwss.apply_ctx_for_surface(
1361
+ dc, context->streams[i],
1362
+ context->stream_status[i].plane_count,
1363
+ context); /* use new pipe config in new context */
1364
+ apply_ctx_interdependent_lock(dc, context, context->streams[i], false);
1365
+ dc->hwss.post_unlock_program_front_end(dc, context);
1366
+ }
9031367 }
9041368
9051369 /* Program hardware */
906
- dc->hwss.ready_shared_resources(dc, context);
907
-
9081370 for (i = 0; i < dc->res_pool->pipe_count; i++) {
9091371 pipe = &context->res_ctx.pipe_ctx[i];
9101372 dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe);
....@@ -915,22 +1377,30 @@
9151377 if (result != DC_OK)
9161378 return result;
9171379
918
- if (context->stream_count > 1) {
919
- enable_timing_multisync(dc, context);
920
- program_timing_sync(dc, context);
921
- }
1380
+ dc_trigger_sync(dc, context);
9221381
9231382 /* Program all planes within new context*/
1383
+ if (dc->hwss.program_front_end_for_ctx) {
1384
+ dc->hwss.interdependent_update_lock(dc, context, true);
1385
+ dc->hwss.program_front_end_for_ctx(dc, context);
1386
+ dc->hwss.interdependent_update_lock(dc, context, false);
1387
+ dc->hwss.post_unlock_program_front_end(dc, context);
1388
+ }
9241389 for (i = 0; i < context->stream_count; i++) {
925
- const struct dc_sink *sink = context->streams[i]->sink;
1390
+ const struct dc_link *link = context->streams[i]->link;
9261391
9271392 if (!context->streams[i]->mode_changed)
9281393 continue;
9291394
930
- dc->hwss.apply_ctx_for_surface(
931
- dc, context->streams[i],
932
- context->stream_status[i].plane_count,
933
- context);
1395
+ if (dc->hwss.apply_ctx_for_surface) {
1396
+ apply_ctx_interdependent_lock(dc, context, context->streams[i], true);
1397
+ dc->hwss.apply_ctx_for_surface(
1398
+ dc, context->streams[i],
1399
+ context->stream_status[i].plane_count,
1400
+ context);
1401
+ apply_ctx_interdependent_lock(dc, context, context->streams[i], false);
1402
+ dc->hwss.post_unlock_program_front_end(dc, context);
1403
+ }
9341404
9351405 /*
9361406 * enable stereo
....@@ -947,18 +1417,28 @@
9471417 }
9481418 }
9491419
950
- CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}",
1420
+ CONN_MSG_MODE(link, "{%dx%d, %dx%d@%dKhz}",
9511421 context->streams[i]->timing.h_addressable,
9521422 context->streams[i]->timing.v_addressable,
9531423 context->streams[i]->timing.h_total,
9541424 context->streams[i]->timing.v_total,
955
- context->streams[i]->timing.pix_clk_khz);
1425
+ context->streams[i]->timing.pix_clk_100hz / 10);
9561426 }
9571427
9581428 dc_enable_stereo(dc, context, dc_streams, context->stream_count);
9591429
960
- /* pplib is notified if disp_num changed */
961
- dc->hwss.set_bandwidth(dc, context, true);
1430
+ if (context->stream_count > dc->optimize_seamless_boot_streams ||
1431
+ context->stream_count == 0) {
1432
+ /* Must wait for no flips to be pending before doing optimize bw */
1433
+ wait_for_no_pipes_pending(dc, context);
1434
+ /* pplib is notified if disp_num changed */
1435
+ dc->hwss.optimize_bandwidth(dc, context);
1436
+ }
1437
+
1438
+ context->stream_mask = get_stream_mask(dc, context);
1439
+
1440
+ if (context->stream_mask != dc->current_state->stream_mask)
1441
+ dc_dmub_srv_notify_stream_mask(dc->ctx->dmub_srv, context->stream_mask);
9621442
9631443 for (i = 0; i < context->stream_count; i++)
9641444 context->streams[i]->mode_changed = false;
....@@ -968,8 +1448,6 @@
9681448 dc->current_state = context;
9691449
9701450 dc_retain_state(dc->current_state);
971
-
972
- dc->hwss.optimize_shared_resources(dc);
9731451
9741452 return result;
9751453 }
....@@ -996,6 +1474,43 @@
9961474 return (result == DC_OK);
9971475 }
9981476
1477
+#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
1478
+bool dc_acquire_release_mpc_3dlut(
1479
+ struct dc *dc, bool acquire,
1480
+ struct dc_stream_state *stream,
1481
+ struct dc_3dlut **lut,
1482
+ struct dc_transfer_func **shaper)
1483
+{
1484
+ int pipe_idx;
1485
+ bool ret = false;
1486
+ bool found_pipe_idx = false;
1487
+ const struct resource_pool *pool = dc->res_pool;
1488
+ struct resource_context *res_ctx = &dc->current_state->res_ctx;
1489
+ int mpcc_id = 0;
1490
+
1491
+ if (pool && res_ctx) {
1492
+ if (acquire) {
1493
+ /*find pipe idx for the given stream*/
1494
+ for (pipe_idx = 0; pipe_idx < pool->pipe_count; pipe_idx++) {
1495
+ if (res_ctx->pipe_ctx[pipe_idx].stream == stream) {
1496
+ found_pipe_idx = true;
1497
+ mpcc_id = res_ctx->pipe_ctx[pipe_idx].plane_res.hubp->inst;
1498
+ break;
1499
+ }
1500
+ }
1501
+ } else
1502
+ found_pipe_idx = true;/*for release pipe_idx is not required*/
1503
+
1504
+ if (found_pipe_idx) {
1505
+ if (acquire && pool->funcs->acquire_post_bldn_3dlut)
1506
+ ret = pool->funcs->acquire_post_bldn_3dlut(res_ctx, pool, mpcc_id, lut, shaper);
1507
+ else if (acquire == false && pool->funcs->release_post_bldn_3dlut)
1508
+ ret = pool->funcs->release_post_bldn_3dlut(res_ctx, pool, lut, shaper);
1509
+ }
1510
+ }
1511
+ return ret;
1512
+}
1513
+#endif
9991514 static bool is_flip_pending_in_pipes(struct dc *dc, struct dc_state *context)
10001515 {
10011516 int i;
....@@ -1021,6 +1536,9 @@
10211536 int i;
10221537 struct dc_state *context = dc->current_state;
10231538
1539
+ if ((!dc->optimized_required) || dc->optimize_seamless_boot_streams > 0)
1540
+ return true;
1541
+
10241542 post_surface_trace(dc);
10251543
10261544 if (is_flip_pending_in_pipes(dc, context))
....@@ -1033,22 +1551,76 @@
10331551 dc->hwss.disable_plane(dc, &context->res_ctx.pipe_ctx[i]);
10341552 }
10351553
1036
- dc->optimized_required = false;
1554
+ dc->hwss.optimize_bandwidth(dc, context);
10371555
1038
- dc->hwss.set_bandwidth(dc, context, true);
1556
+ dc->optimized_required = false;
1557
+ dc->wm_optimized_required = false;
1558
+
10391559 return true;
10401560 }
10411561
1042
-struct dc_state *dc_create_state(void)
1562
+static void init_state(struct dc *dc, struct dc_state *context)
10431563 {
1044
- struct dc_state *context = kzalloc(sizeof(struct dc_state),
1045
- GFP_KERNEL);
1564
+ /* Each context must have their own instance of VBA and in order to
1565
+ * initialize and obtain IP and SOC the base DML instance from DC is
1566
+ * initially copied into every context
1567
+ */
1568
+#ifdef CONFIG_DRM_AMD_DC_DCN
1569
+ memcpy(&context->bw_ctx.dml, &dc->dml, sizeof(struct display_mode_lib));
1570
+#endif
1571
+}
1572
+
1573
+struct dc_state *dc_create_state(struct dc *dc)
1574
+{
1575
+ struct dc_state *context = kvzalloc(sizeof(struct dc_state),
1576
+ GFP_KERNEL);
10461577
10471578 if (!context)
10481579 return NULL;
10491580
1581
+ init_state(dc, context);
1582
+
10501583 kref_init(&context->refcount);
1584
+
10511585 return context;
1586
+}
1587
+
1588
+struct dc_state *dc_copy_state(struct dc_state *src_ctx)
1589
+{
1590
+ int i, j;
1591
+ struct dc_state *new_ctx = kvmalloc(sizeof(struct dc_state), GFP_KERNEL);
1592
+
1593
+ if (!new_ctx)
1594
+ return NULL;
1595
+ memcpy(new_ctx, src_ctx, sizeof(struct dc_state));
1596
+
1597
+ for (i = 0; i < MAX_PIPES; i++) {
1598
+ struct pipe_ctx *cur_pipe = &new_ctx->res_ctx.pipe_ctx[i];
1599
+
1600
+ if (cur_pipe->top_pipe)
1601
+ cur_pipe->top_pipe = &new_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx];
1602
+
1603
+ if (cur_pipe->bottom_pipe)
1604
+ cur_pipe->bottom_pipe = &new_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
1605
+
1606
+ if (cur_pipe->prev_odm_pipe)
1607
+ cur_pipe->prev_odm_pipe = &new_ctx->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx];
1608
+
1609
+ if (cur_pipe->next_odm_pipe)
1610
+ cur_pipe->next_odm_pipe = &new_ctx->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx];
1611
+
1612
+ }
1613
+
1614
+ for (i = 0; i < new_ctx->stream_count; i++) {
1615
+ dc_stream_retain(new_ctx->streams[i]);
1616
+ for (j = 0; j < new_ctx->stream_status[i].plane_count; j++)
1617
+ dc_plane_state_retain(
1618
+ new_ctx->stream_status[i].plane_states[j]);
1619
+ }
1620
+
1621
+ kref_init(&new_ctx->refcount);
1622
+
1623
+ return new_ctx;
10521624 }
10531625
10541626 void dc_retain_state(struct dc_state *context)
....@@ -1060,12 +1632,61 @@
10601632 {
10611633 struct dc_state *context = container_of(kref, struct dc_state, refcount);
10621634 dc_resource_state_destruct(context);
1063
- kfree(context);
1635
+ kvfree(context);
10641636 }
10651637
10661638 void dc_release_state(struct dc_state *context)
10671639 {
10681640 kref_put(&context->refcount, dc_state_free);
1641
+}
1642
+
1643
+bool dc_set_generic_gpio_for_stereo(bool enable,
1644
+ struct gpio_service *gpio_service)
1645
+{
1646
+ enum gpio_result gpio_result = GPIO_RESULT_NON_SPECIFIC_ERROR;
1647
+ struct gpio_pin_info pin_info;
1648
+ struct gpio *generic;
1649
+ struct gpio_generic_mux_config *config = kzalloc(sizeof(struct gpio_generic_mux_config),
1650
+ GFP_KERNEL);
1651
+
1652
+ if (!config)
1653
+ return false;
1654
+ pin_info = dal_gpio_get_generic_pin_info(gpio_service, GPIO_ID_GENERIC, 0);
1655
+
1656
+ if (pin_info.mask == 0xFFFFFFFF || pin_info.offset == 0xFFFFFFFF) {
1657
+ kfree(config);
1658
+ return false;
1659
+ } else {
1660
+ generic = dal_gpio_service_create_generic_mux(
1661
+ gpio_service,
1662
+ pin_info.offset,
1663
+ pin_info.mask);
1664
+ }
1665
+
1666
+ if (!generic) {
1667
+ kfree(config);
1668
+ return false;
1669
+ }
1670
+
1671
+ gpio_result = dal_gpio_open(generic, GPIO_MODE_OUTPUT);
1672
+
1673
+ config->enable_output_from_mux = enable;
1674
+ config->mux_select = GPIO_SIGNAL_SOURCE_PASS_THROUGH_STEREO_SYNC;
1675
+
1676
+ if (gpio_result == GPIO_RESULT_OK)
1677
+ gpio_result = dal_mux_setup_config(generic, config);
1678
+
1679
+ if (gpio_result == GPIO_RESULT_OK) {
1680
+ dal_gpio_close(generic);
1681
+ dal_gpio_destroy_generic_mux(&generic);
1682
+ kfree(config);
1683
+ return true;
1684
+ } else {
1685
+ dal_gpio_close(generic);
1686
+ dal_gpio_destroy_generic_mux(&generic);
1687
+ kfree(config);
1688
+ return false;
1689
+ }
10691690 }
10701691
10711692 static bool is_surface_in_context(
....@@ -1085,91 +1706,91 @@
10851706 return false;
10861707 }
10871708
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
-
11141709 static enum surface_update_type get_plane_info_update_type(const struct dc_surface_update *u)
11151710 {
11161711 union surface_update_flags *update_flags = &u->surface->update_flags;
1712
+ enum surface_update_type update_type = UPDATE_TYPE_FAST;
11171713
11181714 if (!u->plane_info)
11191715 return UPDATE_TYPE_FAST;
11201716
1121
- if (u->plane_info->color_space != u->surface->color_space)
1717
+ if (u->plane_info->color_space != u->surface->color_space) {
11221718 update_flags->bits.color_space_change = 1;
1719
+ elevate_update_type(&update_type, UPDATE_TYPE_MED);
1720
+ }
11231721
1124
- if (u->plane_info->horizontal_mirror != u->surface->horizontal_mirror)
1722
+ if (u->plane_info->horizontal_mirror != u->surface->horizontal_mirror) {
11251723 update_flags->bits.horizontal_mirror_change = 1;
1724
+ elevate_update_type(&update_type, UPDATE_TYPE_MED);
1725
+ }
11261726
1127
- if (u->plane_info->rotation != u->surface->rotation)
1727
+ if (u->plane_info->rotation != u->surface->rotation) {
11281728 update_flags->bits.rotation_change = 1;
1729
+ elevate_update_type(&update_type, UPDATE_TYPE_FULL);
1730
+ }
11291731
1130
- if (u->plane_info->format != u->surface->format)
1732
+ if (u->plane_info->format != u->surface->format) {
11311733 update_flags->bits.pixel_format_change = 1;
1734
+ elevate_update_type(&update_type, UPDATE_TYPE_FULL);
1735
+ }
11321736
1133
- if (u->plane_info->stereo_format != u->surface->stereo_format)
1737
+ if (u->plane_info->stereo_format != u->surface->stereo_format) {
11341738 update_flags->bits.stereo_format_change = 1;
1739
+ elevate_update_type(&update_type, UPDATE_TYPE_FULL);
1740
+ }
11351741
1136
- if (u->plane_info->per_pixel_alpha != u->surface->per_pixel_alpha)
1742
+ if (u->plane_info->per_pixel_alpha != u->surface->per_pixel_alpha) {
11371743 update_flags->bits.per_pixel_alpha_change = 1;
1744
+ elevate_update_type(&update_type, UPDATE_TYPE_MED);
1745
+ }
1746
+
1747
+ if (u->plane_info->global_alpha_value != u->surface->global_alpha_value) {
1748
+ update_flags->bits.global_alpha_change = 1;
1749
+ elevate_update_type(&update_type, UPDATE_TYPE_MED);
1750
+ }
11381751
11391752 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)
1753
+ || u->plane_info->dcc.independent_64b_blks != u->surface->dcc.independent_64b_blks
1754
+ || u->plane_info->dcc.meta_pitch != u->surface->dcc.meta_pitch) {
11421755 update_flags->bits.dcc_change = 1;
1756
+ elevate_update_type(&update_type, UPDATE_TYPE_MED);
1757
+ }
11431758
1144
- if (pixel_format_to_bpp(u->plane_info->format) !=
1145
- pixel_format_to_bpp(u->surface->format))
1759
+ if (resource_pixel_format_to_bpp(u->plane_info->format) !=
1760
+ resource_pixel_format_to_bpp(u->surface->format)) {
11461761 /* different bytes per element will require full bandwidth
11471762 * and DML calculation
11481763 */
11491764 update_flags->bits.bpp_change = 1;
1765
+ elevate_update_type(&update_type, UPDATE_TYPE_FULL);
1766
+ }
1767
+
1768
+ if (u->plane_info->plane_size.surface_pitch != u->surface->plane_size.surface_pitch
1769
+ || u->plane_info->plane_size.chroma_pitch != u->surface->plane_size.chroma_pitch) {
1770
+ update_flags->bits.plane_size_change = 1;
1771
+ elevate_update_type(&update_type, UPDATE_TYPE_MED);
1772
+ }
1773
+
11501774
11511775 if (memcmp(&u->plane_info->tiling_info, &u->surface->tiling_info,
11521776 sizeof(union dc_tiling_info)) != 0) {
11531777 update_flags->bits.swizzle_change = 1;
1778
+ elevate_update_type(&update_type, UPDATE_TYPE_MED);
1779
+
11541780 /* todo: below are HW dependent, we should add a hook to
11551781 * DCE/N resource and validated there.
11561782 */
1157
- if (u->plane_info->tiling_info.gfx9.swizzle != DC_SW_LINEAR)
1783
+ if (u->plane_info->tiling_info.gfx9.swizzle != DC_SW_LINEAR) {
11581784 /* swizzled mode requires RQ to be setup properly,
11591785 * thus need to run DML to calculate RQ settings
11601786 */
11611787 update_flags->bits.bandwidth_change = 1;
1788
+ elevate_update_type(&update_type, UPDATE_TYPE_FULL);
1789
+ }
11621790 }
11631791
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;
1792
+ /* This should be UPDATE_TYPE_FAST if nothing has changed. */
1793
+ return update_type;
11731794 }
11741795
11751796 static enum surface_update_type get_scaling_info_update_type(
....@@ -1183,7 +1804,10 @@
11831804 if (u->scaling_info->clip_rect.width != u->surface->clip_rect.width
11841805 || u->scaling_info->clip_rect.height != u->surface->clip_rect.height
11851806 || u->scaling_info->dst_rect.width != u->surface->dst_rect.width
1186
- || u->scaling_info->dst_rect.height != u->surface->dst_rect.height) {
1807
+ || u->scaling_info->dst_rect.height != u->surface->dst_rect.height
1808
+ || u->scaling_info->scaling_quality.integer_scaling !=
1809
+ u->surface->scaling_quality.integer_scaling
1810
+ ) {
11871811 update_flags->bits.scaling_change = 1;
11881812
11891813 if ((u->scaling_info->dst_rect.width < u->surface->dst_rect.width
....@@ -1199,7 +1823,7 @@
11991823
12001824 update_flags->bits.scaling_change = 1;
12011825 if (u->scaling_info->src_rect.width > u->surface->src_rect.width
1202
- && u->scaling_info->src_rect.height > u->surface->src_rect.height)
1826
+ || u->scaling_info->src_rect.height > u->surface->src_rect.height)
12031827 /* Making src rect bigger requires a bandwidth change */
12041828 update_flags->bits.clock_change = 1;
12051829 }
....@@ -1213,11 +1837,11 @@
12131837 update_flags->bits.position_change = 1;
12141838
12151839 if (update_flags->bits.clock_change
1216
- || update_flags->bits.bandwidth_change)
1840
+ || update_flags->bits.bandwidth_change
1841
+ || update_flags->bits.scaling_change)
12171842 return UPDATE_TYPE_FULL;
12181843
1219
- if (update_flags->bits.scaling_change
1220
- || update_flags->bits.position_change)
1844
+ if (update_flags->bits.position_change)
12211845 return UPDATE_TYPE_MED;
12221846
12231847 return UPDATE_TYPE_FAST;
....@@ -1231,23 +1855,21 @@
12311855 enum surface_update_type overall_type = UPDATE_TYPE_FAST;
12321856 union surface_update_flags *update_flags = &u->surface->update_flags;
12331857
1858
+ if (!is_surface_in_context(context, u->surface) || u->surface->force_full_update) {
1859
+ update_flags->raw = 0xFFFFFFFF;
1860
+ return UPDATE_TYPE_FULL;
1861
+ }
1862
+
12341863 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
- }
12451864
12461865 type = get_plane_info_update_type(u);
12471866 elevate_update_type(&overall_type, type);
12481867
12491868 type = get_scaling_info_update_type(u);
12501869 elevate_update_type(&overall_type, type);
1870
+
1871
+ if (u->flip_addr)
1872
+ update_flags->bits.addr_update = 1;
12511873
12521874 if (u->in_transfer_func)
12531875 update_flags->bits.in_transfer_func_change = 1;
....@@ -1257,6 +1879,9 @@
12571879
12581880 if (u->coeff_reduction_factor)
12591881 update_flags->bits.coeff_reduction_change = 1;
1882
+
1883
+ if (u->gamut_remap_matrix)
1884
+ update_flags->bits.gamut_remap_change = 1;
12601885
12611886 if (u->gamma) {
12621887 enum surface_pixel_format format = SURFACE_PIXEL_FORMAT_GRPH_BEGIN;
....@@ -1270,6 +1895,12 @@
12701895 update_flags->bits.gamma_change = 1;
12711896 }
12721897
1898
+ if (u->hdr_mult.value)
1899
+ if (u->hdr_mult.value != u->surface->hdr_mult.value) {
1900
+ update_flags->bits.hdr_mult = 1;
1901
+ elevate_update_type(&overall_type, UPDATE_TYPE_MED);
1902
+ }
1903
+
12731904 if (update_flags->bits.in_transfer_func_change) {
12741905 type = UPDATE_TYPE_MED;
12751906 elevate_update_type(&overall_type, type);
....@@ -1277,7 +1908,8 @@
12771908
12781909 if (update_flags->bits.input_csc_change
12791910 || update_flags->bits.coeff_reduction_change
1280
- || update_flags->bits.gamma_change) {
1911
+ || update_flags->bits.gamma_change
1912
+ || update_flags->bits.gamut_remap_change) {
12811913 type = UPDATE_TYPE_FULL;
12821914 elevate_update_type(&overall_type, type);
12831915 }
....@@ -1295,18 +1927,51 @@
12951927 int i;
12961928 enum surface_update_type overall_type = UPDATE_TYPE_FAST;
12971929
1298
- if (stream_status == NULL || stream_status->plane_count != surface_count)
1299
- return UPDATE_TYPE_FULL;
1930
+#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
1931
+ if (dc->idle_optimizations_allowed)
1932
+ overall_type = UPDATE_TYPE_FULL;
13001933
1301
- if (stream_update)
1302
- return UPDATE_TYPE_FULL;
1934
+#endif
1935
+ if (stream_status == NULL || stream_status->plane_count != surface_count)
1936
+ overall_type = UPDATE_TYPE_FULL;
1937
+
1938
+ /* some stream updates require passive update */
1939
+ if (stream_update) {
1940
+ union stream_update_flags *su_flags = &stream_update->stream->update_flags;
1941
+
1942
+ if ((stream_update->src.height != 0 && stream_update->src.width != 0) ||
1943
+ (stream_update->dst.height != 0 && stream_update->dst.width != 0) ||
1944
+ stream_update->integer_scaling_update)
1945
+ su_flags->bits.scaling = 1;
1946
+
1947
+ if (stream_update->out_transfer_func)
1948
+ su_flags->bits.out_tf = 1;
1949
+
1950
+ if (stream_update->abm_level)
1951
+ su_flags->bits.abm_level = 1;
1952
+
1953
+ if (stream_update->dpms_off)
1954
+ su_flags->bits.dpms_off = 1;
1955
+
1956
+ if (stream_update->gamut_remap)
1957
+ su_flags->bits.gamut_remap = 1;
1958
+
1959
+ if (stream_update->wb_update)
1960
+ su_flags->bits.wb_update = 1;
1961
+
1962
+ if (stream_update->dsc_config)
1963
+ su_flags->bits.dsc_changed = 1;
1964
+
1965
+ if (su_flags->raw != 0)
1966
+ overall_type = UPDATE_TYPE_FULL;
1967
+
1968
+ if (stream_update->output_csc_transform || stream_update->output_color_space)
1969
+ su_flags->bits.out_csc = 1;
1970
+ }
13031971
13041972 for (i = 0 ; i < surface_count; i++) {
13051973 enum surface_update_type type =
13061974 det_surface_update(dc, &updates[i]);
1307
-
1308
- if (type == UPDATE_TYPE_FULL)
1309
- return type;
13101975
13111976 elevate_update_type(&overall_type, type);
13121977 }
....@@ -1314,6 +1979,11 @@
13141979 return overall_type;
13151980 }
13161981
1982
+/**
1983
+ * dc_check_update_surfaces_for_stream() - Determine update type (fast, med, or full)
1984
+ *
1985
+ * See :c:type:`enum surface_update_type <surface_update_type>` for explanation of update types
1986
+ */
13171987 enum surface_update_type dc_check_update_surfaces_for_stream(
13181988 struct dc *dc,
13191989 struct dc_surface_update *updates,
....@@ -1324,13 +1994,34 @@
13241994 int i;
13251995 enum surface_update_type type;
13261996
1997
+ if (stream_update)
1998
+ stream_update->stream->update_flags.raw = 0;
13271999 for (i = 0; i < surface_count; i++)
13282000 updates[i].surface->update_flags.raw = 0;
13292001
13302002 type = check_update_surfaces_for_stream(dc, updates, surface_count, stream_update, stream_status);
1331
- if (type == UPDATE_TYPE_FULL)
2003
+ if (type == UPDATE_TYPE_FULL) {
2004
+ if (stream_update) {
2005
+ uint32_t dsc_changed = stream_update->stream->update_flags.bits.dsc_changed;
2006
+ stream_update->stream->update_flags.raw = 0xFFFFFFFF;
2007
+ stream_update->stream->update_flags.bits.dsc_changed = dsc_changed;
2008
+ }
13322009 for (i = 0; i < surface_count; i++)
13332010 updates[i].surface->update_flags.raw = 0xFFFFFFFF;
2011
+ }
2012
+
2013
+ if (type == UPDATE_TYPE_FAST) {
2014
+ // If there's an available clock comparator, we use that.
2015
+ if (dc->clk_mgr->funcs->are_clock_states_equal) {
2016
+ if (!dc->clk_mgr->funcs->are_clock_states_equal(&dc->clk_mgr->clks, &dc->current_state->bw_ctx.bw.dcn.clk))
2017
+ dc->optimized_required = true;
2018
+ // Else we fallback to mem compare.
2019
+ } 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) {
2020
+ dc->optimized_required = true;
2021
+ }
2022
+
2023
+ dc->optimized_required |= dc->wm_optimized_required;
2024
+ }
13342025
13352026 return type;
13362027 }
....@@ -1352,6 +2043,328 @@
13522043
13532044 static const enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL;
13542045
2046
+static void copy_surface_update_to_plane(
2047
+ struct dc_plane_state *surface,
2048
+ struct dc_surface_update *srf_update)
2049
+{
2050
+ if (srf_update->flip_addr) {
2051
+ surface->address = srf_update->flip_addr->address;
2052
+ surface->flip_immediate =
2053
+ srf_update->flip_addr->flip_immediate;
2054
+ surface->time.time_elapsed_in_us[surface->time.index] =
2055
+ srf_update->flip_addr->flip_timestamp_in_us -
2056
+ surface->time.prev_update_time_in_us;
2057
+ surface->time.prev_update_time_in_us =
2058
+ srf_update->flip_addr->flip_timestamp_in_us;
2059
+ surface->time.index++;
2060
+ if (surface->time.index >= DC_PLANE_UPDATE_TIMES_MAX)
2061
+ surface->time.index = 0;
2062
+
2063
+ surface->triplebuffer_flips = srf_update->flip_addr->triplebuffer_flips;
2064
+ }
2065
+
2066
+ if (srf_update->scaling_info) {
2067
+ surface->scaling_quality =
2068
+ srf_update->scaling_info->scaling_quality;
2069
+ surface->dst_rect =
2070
+ srf_update->scaling_info->dst_rect;
2071
+ surface->src_rect =
2072
+ srf_update->scaling_info->src_rect;
2073
+ surface->clip_rect =
2074
+ srf_update->scaling_info->clip_rect;
2075
+ }
2076
+
2077
+ if (srf_update->plane_info) {
2078
+ surface->color_space =
2079
+ srf_update->plane_info->color_space;
2080
+ surface->format =
2081
+ srf_update->plane_info->format;
2082
+ surface->plane_size =
2083
+ srf_update->plane_info->plane_size;
2084
+ surface->rotation =
2085
+ srf_update->plane_info->rotation;
2086
+ surface->horizontal_mirror =
2087
+ srf_update->plane_info->horizontal_mirror;
2088
+ surface->stereo_format =
2089
+ srf_update->plane_info->stereo_format;
2090
+ surface->tiling_info =
2091
+ srf_update->plane_info->tiling_info;
2092
+ surface->visible =
2093
+ srf_update->plane_info->visible;
2094
+ surface->per_pixel_alpha =
2095
+ srf_update->plane_info->per_pixel_alpha;
2096
+ surface->global_alpha =
2097
+ srf_update->plane_info->global_alpha;
2098
+ surface->global_alpha_value =
2099
+ srf_update->plane_info->global_alpha_value;
2100
+ surface->dcc =
2101
+ srf_update->plane_info->dcc;
2102
+ surface->layer_index =
2103
+ srf_update->plane_info->layer_index;
2104
+ }
2105
+
2106
+ if (srf_update->gamma &&
2107
+ (surface->gamma_correction !=
2108
+ srf_update->gamma)) {
2109
+ memcpy(&surface->gamma_correction->entries,
2110
+ &srf_update->gamma->entries,
2111
+ sizeof(struct dc_gamma_entries));
2112
+ surface->gamma_correction->is_identity =
2113
+ srf_update->gamma->is_identity;
2114
+ surface->gamma_correction->num_entries =
2115
+ srf_update->gamma->num_entries;
2116
+ surface->gamma_correction->type =
2117
+ srf_update->gamma->type;
2118
+ }
2119
+
2120
+ if (srf_update->in_transfer_func &&
2121
+ (surface->in_transfer_func !=
2122
+ srf_update->in_transfer_func)) {
2123
+ surface->in_transfer_func->sdr_ref_white_level =
2124
+ srf_update->in_transfer_func->sdr_ref_white_level;
2125
+ surface->in_transfer_func->tf =
2126
+ srf_update->in_transfer_func->tf;
2127
+ surface->in_transfer_func->type =
2128
+ srf_update->in_transfer_func->type;
2129
+ memcpy(&surface->in_transfer_func->tf_pts,
2130
+ &srf_update->in_transfer_func->tf_pts,
2131
+ sizeof(struct dc_transfer_func_distributed_points));
2132
+ }
2133
+
2134
+ if (srf_update->func_shaper &&
2135
+ (surface->in_shaper_func !=
2136
+ srf_update->func_shaper))
2137
+ memcpy(surface->in_shaper_func, srf_update->func_shaper,
2138
+ sizeof(*surface->in_shaper_func));
2139
+
2140
+ if (srf_update->lut3d_func &&
2141
+ (surface->lut3d_func !=
2142
+ srf_update->lut3d_func))
2143
+ memcpy(surface->lut3d_func, srf_update->lut3d_func,
2144
+ sizeof(*surface->lut3d_func));
2145
+
2146
+ if (srf_update->hdr_mult.value)
2147
+ surface->hdr_mult =
2148
+ srf_update->hdr_mult;
2149
+
2150
+ if (srf_update->blend_tf &&
2151
+ (surface->blend_tf !=
2152
+ srf_update->blend_tf))
2153
+ memcpy(surface->blend_tf, srf_update->blend_tf,
2154
+ sizeof(*surface->blend_tf));
2155
+
2156
+ if (srf_update->input_csc_color_matrix)
2157
+ surface->input_csc_color_matrix =
2158
+ *srf_update->input_csc_color_matrix;
2159
+
2160
+ if (srf_update->coeff_reduction_factor)
2161
+ surface->coeff_reduction_factor =
2162
+ *srf_update->coeff_reduction_factor;
2163
+
2164
+ if (srf_update->gamut_remap_matrix)
2165
+ surface->gamut_remap_matrix =
2166
+ *srf_update->gamut_remap_matrix;
2167
+}
2168
+
2169
+static void copy_stream_update_to_stream(struct dc *dc,
2170
+ struct dc_state *context,
2171
+ struct dc_stream_state *stream,
2172
+ struct dc_stream_update *update)
2173
+{
2174
+ struct dc_context *dc_ctx = dc->ctx;
2175
+
2176
+ if (update == NULL || stream == NULL)
2177
+ return;
2178
+
2179
+ if (update->src.height && update->src.width)
2180
+ stream->src = update->src;
2181
+
2182
+ if (update->dst.height && update->dst.width)
2183
+ stream->dst = update->dst;
2184
+
2185
+ if (update->out_transfer_func &&
2186
+ stream->out_transfer_func != update->out_transfer_func) {
2187
+ stream->out_transfer_func->sdr_ref_white_level =
2188
+ update->out_transfer_func->sdr_ref_white_level;
2189
+ stream->out_transfer_func->tf = update->out_transfer_func->tf;
2190
+ stream->out_transfer_func->type =
2191
+ update->out_transfer_func->type;
2192
+ memcpy(&stream->out_transfer_func->tf_pts,
2193
+ &update->out_transfer_func->tf_pts,
2194
+ sizeof(struct dc_transfer_func_distributed_points));
2195
+ }
2196
+
2197
+ if (update->hdr_static_metadata)
2198
+ stream->hdr_static_metadata = *update->hdr_static_metadata;
2199
+
2200
+ if (update->abm_level)
2201
+ stream->abm_level = *update->abm_level;
2202
+
2203
+ if (update->periodic_interrupt)
2204
+ stream->periodic_interrupt = *update->periodic_interrupt;
2205
+
2206
+ if (update->gamut_remap)
2207
+ stream->gamut_remap_matrix = *update->gamut_remap;
2208
+
2209
+ /* Note: this being updated after mode set is currently not a use case
2210
+ * however if it arises OCSC would need to be reprogrammed at the
2211
+ * minimum
2212
+ */
2213
+ if (update->output_color_space)
2214
+ stream->output_color_space = *update->output_color_space;
2215
+
2216
+ if (update->output_csc_transform)
2217
+ stream->csc_color_matrix = *update->output_csc_transform;
2218
+
2219
+ if (update->vrr_infopacket)
2220
+ stream->vrr_infopacket = *update->vrr_infopacket;
2221
+
2222
+ if (update->dpms_off)
2223
+ stream->dpms_off = *update->dpms_off;
2224
+
2225
+ if (update->vsc_infopacket)
2226
+ stream->vsc_infopacket = *update->vsc_infopacket;
2227
+
2228
+ if (update->vsp_infopacket)
2229
+ stream->vsp_infopacket = *update->vsp_infopacket;
2230
+
2231
+ if (update->dither_option)
2232
+ stream->dither_option = *update->dither_option;
2233
+ /* update current stream with writeback info */
2234
+ if (update->wb_update) {
2235
+ int i;
2236
+
2237
+ stream->num_wb_info = update->wb_update->num_wb_info;
2238
+ ASSERT(stream->num_wb_info <= MAX_DWB_PIPES);
2239
+ for (i = 0; i < stream->num_wb_info; i++)
2240
+ stream->writeback_info[i] =
2241
+ update->wb_update->writeback_info[i];
2242
+ }
2243
+ if (update->dsc_config) {
2244
+ struct dc_dsc_config old_dsc_cfg = stream->timing.dsc_cfg;
2245
+ uint32_t old_dsc_enabled = stream->timing.flags.DSC;
2246
+ uint32_t enable_dsc = (update->dsc_config->num_slices_h != 0 &&
2247
+ update->dsc_config->num_slices_v != 0);
2248
+
2249
+ /* Use temporarry context for validating new DSC config */
2250
+ struct dc_state *dsc_validate_context = dc_create_state(dc);
2251
+
2252
+ if (dsc_validate_context) {
2253
+ dc_resource_state_copy_construct(dc->current_state, dsc_validate_context);
2254
+
2255
+ stream->timing.dsc_cfg = *update->dsc_config;
2256
+ stream->timing.flags.DSC = enable_dsc;
2257
+ if (!dc->res_pool->funcs->validate_bandwidth(dc, dsc_validate_context, true)) {
2258
+ stream->timing.dsc_cfg = old_dsc_cfg;
2259
+ stream->timing.flags.DSC = old_dsc_enabled;
2260
+ update->dsc_config = NULL;
2261
+ }
2262
+
2263
+ dc_release_state(dsc_validate_context);
2264
+ } else {
2265
+ DC_ERROR("Failed to allocate new validate context for DSC change\n");
2266
+ update->dsc_config = NULL;
2267
+ }
2268
+ }
2269
+}
2270
+
2271
+static void commit_planes_do_stream_update(struct dc *dc,
2272
+ struct dc_stream_state *stream,
2273
+ struct dc_stream_update *stream_update,
2274
+ enum surface_update_type update_type,
2275
+ struct dc_state *context)
2276
+{
2277
+ int j;
2278
+ bool should_program_abm;
2279
+
2280
+ // Stream updates
2281
+ for (j = 0; j < dc->res_pool->pipe_count; j++) {
2282
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
2283
+
2284
+ if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe && pipe_ctx->stream == stream) {
2285
+
2286
+ if (stream_update->periodic_interrupt && dc->hwss.setup_periodic_interrupt)
2287
+ dc->hwss.setup_periodic_interrupt(dc, pipe_ctx);
2288
+
2289
+ if ((stream_update->hdr_static_metadata && !stream->use_dynamic_meta) ||
2290
+ stream_update->vrr_infopacket ||
2291
+ stream_update->vsc_infopacket ||
2292
+ stream_update->vsp_infopacket) {
2293
+ resource_build_info_frame(pipe_ctx);
2294
+ dc->hwss.update_info_frame(pipe_ctx);
2295
+ }
2296
+
2297
+ if (stream_update->hdr_static_metadata &&
2298
+ stream->use_dynamic_meta &&
2299
+ dc->hwss.set_dmdata_attributes &&
2300
+ pipe_ctx->stream->dmdata_address.quad_part != 0)
2301
+ dc->hwss.set_dmdata_attributes(pipe_ctx);
2302
+
2303
+ if (stream_update->gamut_remap)
2304
+ dc_stream_set_gamut_remap(dc, stream);
2305
+
2306
+ if (stream_update->output_csc_transform)
2307
+ dc_stream_program_csc_matrix(dc, stream);
2308
+
2309
+ if (stream_update->dither_option) {
2310
+ struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe;
2311
+ resource_build_bit_depth_reduction_params(pipe_ctx->stream,
2312
+ &pipe_ctx->stream->bit_depth_params);
2313
+ pipe_ctx->stream_res.opp->funcs->opp_program_fmt(pipe_ctx->stream_res.opp,
2314
+ &stream->bit_depth_params,
2315
+ &stream->clamping);
2316
+ while (odm_pipe) {
2317
+ odm_pipe->stream_res.opp->funcs->opp_program_fmt(odm_pipe->stream_res.opp,
2318
+ &stream->bit_depth_params,
2319
+ &stream->clamping);
2320
+ odm_pipe = odm_pipe->next_odm_pipe;
2321
+ }
2322
+ }
2323
+
2324
+ /* Full fe update*/
2325
+ if (update_type == UPDATE_TYPE_FAST)
2326
+ continue;
2327
+
2328
+ if (stream_update->dsc_config)
2329
+ dp_update_dsc_config(pipe_ctx);
2330
+
2331
+ if (stream_update->dpms_off) {
2332
+ if (*stream_update->dpms_off) {
2333
+ core_link_disable_stream(pipe_ctx);
2334
+ /* for dpms, keep acquired resources*/
2335
+ if (pipe_ctx->stream_res.audio && !dc->debug.az_endpoint_mute_only)
2336
+ pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
2337
+
2338
+ dc->optimized_required = true;
2339
+
2340
+ } else {
2341
+ if (dc->optimize_seamless_boot_streams == 0)
2342
+ dc->hwss.prepare_bandwidth(dc, dc->current_state);
2343
+
2344
+ core_link_enable_stream(dc->current_state, pipe_ctx);
2345
+ }
2346
+ }
2347
+
2348
+ if (stream_update->abm_level && pipe_ctx->stream_res.abm) {
2349
+ should_program_abm = true;
2350
+
2351
+ // if otg funcs defined check if blanked before programming
2352
+ if (pipe_ctx->stream_res.tg->funcs->is_blanked)
2353
+ if (pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg))
2354
+ should_program_abm = false;
2355
+
2356
+ if (should_program_abm) {
2357
+ if (*stream_update->abm_level == ABM_LEVEL_IMMEDIATE_DISABLE) {
2358
+ dc->hwss.set_abm_immediate_disable(pipe_ctx);
2359
+ } else {
2360
+ pipe_ctx->stream_res.abm->funcs->set_abm_level(
2361
+ pipe_ctx->stream_res.abm, stream->abm_level);
2362
+ }
2363
+ }
2364
+ }
2365
+ }
2366
+ }
2367
+}
13552368
13562369 static void commit_planes_for_stream(struct dc *dc,
13572370 struct dc_surface_update *srf_updates,
....@@ -1361,72 +2374,205 @@
13612374 enum surface_update_type update_type,
13622375 struct dc_state *context)
13632376 {
2377
+ bool mpcc_disconnected = false;
13642378 int i, j;
13652379 struct pipe_ctx *top_pipe_to_program = NULL;
13662380
2381
+ if (dc->optimize_seamless_boot_streams > 0 && surface_count > 0) {
2382
+ /* Optimize seamless boot flag keeps clocks and watermarks high until
2383
+ * first flip. After first flip, optimization is required to lower
2384
+ * bandwidth. Important to note that it is expected UEFI will
2385
+ * only light up a single display on POST, therefore we only expect
2386
+ * one stream with seamless boot flag set.
2387
+ */
2388
+ if (stream->apply_seamless_boot_optimization) {
2389
+ stream->apply_seamless_boot_optimization = false;
2390
+ dc->optimize_seamless_boot_streams--;
2391
+
2392
+ if (dc->optimize_seamless_boot_streams == 0)
2393
+ dc->optimized_required = true;
2394
+ }
2395
+ }
2396
+
13672397 if (update_type == UPDATE_TYPE_FULL) {
1368
- dc->hwss.set_bandwidth(dc, context, false);
2398
+#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
2399
+ dc_allow_idle_optimizations(dc, false);
2400
+
2401
+#endif
2402
+ if (dc->optimize_seamless_boot_streams == 0)
2403
+ dc->hwss.prepare_bandwidth(dc, context);
2404
+
13692405 context_clock_trace(dc, context);
13702406 }
13712407
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;
2408
+ if (update_type != UPDATE_TYPE_FAST && dc->hwss.interdependent_update_lock &&
2409
+ dc->hwss.disconnect_pipes && dc->hwss.wait_for_pending_cleared){
2410
+ dc->hwss.interdependent_update_lock(dc, context, true);
2411
+ mpcc_disconnected = dc->hwss.disconnect_pipes(dc, context);
2412
+ dc->hwss.interdependent_update_lock(dc, context, false);
2413
+ if (mpcc_disconnected)
2414
+ dc->hwss.wait_for_pending_cleared(dc, context);
13792415 }
13802416
1381
- /* Full fe update*/
13822417 for (j = 0; j < dc->res_pool->pipe_count; j++) {
13832418 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
13842419
13852420 if (!pipe_ctx->top_pipe &&
2421
+ !pipe_ctx->prev_odm_pipe &&
2422
+ pipe_ctx->stream &&
2423
+ pipe_ctx->stream == stream) {
2424
+ top_pipe_to_program = pipe_ctx;
2425
+ }
2426
+ }
2427
+
2428
+ if ((update_type != UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed)
2429
+ if (top_pipe_to_program &&
2430
+ top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) {
2431
+ if (should_use_dmub_lock(stream->link)) {
2432
+ union dmub_hw_lock_flags hw_locks = { 0 };
2433
+ struct dmub_hw_lock_inst_flags inst_flags = { 0 };
2434
+
2435
+ hw_locks.bits.lock_dig = 1;
2436
+ inst_flags.dig_inst = top_pipe_to_program->stream_res.tg->inst;
2437
+
2438
+ dmub_hw_lock_mgr_cmd(dc->ctx->dmub_srv,
2439
+ true,
2440
+ &hw_locks,
2441
+ &inst_flags);
2442
+ } else
2443
+ top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable(
2444
+ top_pipe_to_program->stream_res.tg);
2445
+ }
2446
+
2447
+ if ((update_type != UPDATE_TYPE_FAST) && dc->hwss.interdependent_update_lock)
2448
+ dc->hwss.interdependent_update_lock(dc, context, true);
2449
+ else
2450
+ /* Lock the top pipe while updating plane addrs, since freesync requires
2451
+ * plane addr update event triggers to be synchronized.
2452
+ * top_pipe_to_program is expected to never be NULL
2453
+ */
2454
+ dc->hwss.pipe_control_lock(dc, top_pipe_to_program, true);
2455
+
2456
+
2457
+ // Stream updates
2458
+ if (stream_update)
2459
+ commit_planes_do_stream_update(dc, stream, stream_update, update_type, context);
2460
+
2461
+ if (surface_count == 0) {
2462
+ /*
2463
+ * In case of turning off screen, no need to program front end a second time.
2464
+ * just return after program blank.
2465
+ */
2466
+ if (dc->hwss.apply_ctx_for_surface)
2467
+ dc->hwss.apply_ctx_for_surface(dc, stream, 0, context);
2468
+ if (dc->hwss.program_front_end_for_ctx)
2469
+ dc->hwss.program_front_end_for_ctx(dc, context);
2470
+
2471
+ if ((update_type != UPDATE_TYPE_FAST) && dc->hwss.interdependent_update_lock)
2472
+ dc->hwss.interdependent_update_lock(dc, context, false);
2473
+ else
2474
+ dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false);
2475
+
2476
+ dc->hwss.post_unlock_program_front_end(dc, context);
2477
+ return;
2478
+ }
2479
+
2480
+ if (!IS_DIAG_DC(dc->ctx->dce_environment)) {
2481
+ for (i = 0; i < surface_count; i++) {
2482
+ struct dc_plane_state *plane_state = srf_updates[i].surface;
2483
+ /*set logical flag for lock/unlock use*/
2484
+ for (j = 0; j < dc->res_pool->pipe_count; j++) {
2485
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
2486
+ if (!pipe_ctx->plane_state)
2487
+ continue;
2488
+ if (pipe_ctx->plane_state != plane_state)
2489
+ continue;
2490
+ plane_state->triplebuffer_flips = false;
2491
+ if (update_type == UPDATE_TYPE_FAST &&
2492
+ dc->hwss.program_triplebuffer != NULL &&
2493
+ !plane_state->flip_immediate && dc->debug.enable_tri_buf) {
2494
+ /*triple buffer for VUpdate only*/
2495
+ plane_state->triplebuffer_flips = true;
2496
+ }
2497
+ }
2498
+ if (update_type == UPDATE_TYPE_FULL) {
2499
+ /* force vsync flip when reconfiguring pipes to prevent underflow */
2500
+ plane_state->flip_immediate = false;
2501
+ }
2502
+ }
2503
+ }
2504
+
2505
+ // Update Type FULL, Surface updates
2506
+ for (j = 0; j < dc->res_pool->pipe_count; j++) {
2507
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
2508
+
2509
+ if (!pipe_ctx->top_pipe &&
2510
+ !pipe_ctx->prev_odm_pipe &&
13862511 pipe_ctx->stream &&
13872512 pipe_ctx->stream == stream) {
13882513 struct dc_stream_status *stream_status = NULL;
13892514
1390
- top_pipe_to_program = pipe_ctx;
1391
-
1392
- if (update_type == UPDATE_TYPE_FAST || !pipe_ctx->plane_state)
2515
+ if (!pipe_ctx->plane_state)
13932516 continue;
13942517
1395
- stream_status =
1396
- stream_get_status(context, pipe_ctx->stream);
2518
+ /* Full fe update*/
2519
+ if (update_type == UPDATE_TYPE_FAST)
2520
+ continue;
13972521
1398
- dc->hwss.apply_ctx_for_surface(
1399
- dc, pipe_ctx->stream, stream_status->plane_count, context);
2522
+ ASSERT(!pipe_ctx->plane_state->triplebuffer_flips);
14002523
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);
2524
+ if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) {
2525
+ /*turn off triple buffer for full update*/
2526
+ dc->hwss.program_triplebuffer(
2527
+ dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips);
14102528 }
2529
+ stream_status =
2530
+ stream_get_status(context, pipe_ctx->stream);
14112531
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);
2532
+ if (dc->hwss.apply_ctx_for_surface)
2533
+ dc->hwss.apply_ctx_for_surface(
2534
+ dc, pipe_ctx->stream, stream_status->plane_count, context);
14172535 }
14182536 }
2537
+ if (dc->hwss.program_front_end_for_ctx && update_type != UPDATE_TYPE_FAST) {
2538
+ dc->hwss.program_front_end_for_ctx(dc, context);
2539
+#ifdef CONFIG_DRM_AMD_DC_DCN
2540
+ if (dc->debug.validate_dml_output) {
2541
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
2542
+ struct pipe_ctx cur_pipe = context->res_ctx.pipe_ctx[i];
2543
+ if (cur_pipe.stream == NULL)
2544
+ continue;
14192545
1420
- if (update_type == UPDATE_TYPE_FULL)
1421
- context_timing_trace(dc, &context->res_ctx);
2546
+ cur_pipe.plane_res.hubp->funcs->validate_dml_output(
2547
+ cur_pipe.plane_res.hubp, dc->ctx,
2548
+ &context->res_ctx.pipe_ctx[i].rq_regs,
2549
+ &context->res_ctx.pipe_ctx[i].dlg_regs,
2550
+ &context->res_ctx.pipe_ctx[i].ttu_regs);
2551
+ }
2552
+ }
2553
+#endif
2554
+ }
14222555
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
- */
2556
+ // Update Type FAST, Surface updates
14272557 if (update_type == UPDATE_TYPE_FAST) {
1428
- dc->hwss.pipe_control_lock(dc, top_pipe_to_program, true);
2558
+ if (dc->hwss.set_flip_control_gsl)
2559
+ for (i = 0; i < surface_count; i++) {
2560
+ struct dc_plane_state *plane_state = srf_updates[i].surface;
14292561
2562
+ for (j = 0; j < dc->res_pool->pipe_count; j++) {
2563
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
2564
+
2565
+ if (pipe_ctx->stream != stream)
2566
+ continue;
2567
+
2568
+ if (pipe_ctx->plane_state != plane_state)
2569
+ continue;
2570
+
2571
+ // GSL has to be used for flip immediate
2572
+ dc->hwss.set_flip_control_gsl(pipe_ctx,
2573
+ plane_state->flip_immediate);
2574
+ }
2575
+ }
14302576 /* Perform requested Updates */
14312577 for (i = 0; i < surface_count; i++) {
14322578 struct dc_plane_state *plane_state = srf_updates[i].surface;
....@@ -1439,28 +2585,67 @@
14392585
14402586 if (pipe_ctx->plane_state != plane_state)
14412587 continue;
1442
-
2588
+ /*program triple buffer after lock based on flip type*/
2589
+ if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) {
2590
+ /*only enable triplebuffer for fast_update*/
2591
+ dc->hwss.program_triplebuffer(
2592
+ dc, pipe_ctx, plane_state->triplebuffer_flips);
2593
+ }
14432594 if (srf_updates[i].flip_addr)
14442595 dc->hwss.update_plane_addr(dc, pipe_ctx);
14452596 }
14462597 }
1447
-
1448
- dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false);
14492598 }
14502599
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];
2600
+ if ((update_type != UPDATE_TYPE_FAST) && dc->hwss.interdependent_update_lock)
2601
+ dc->hwss.interdependent_update_lock(dc, context, false);
2602
+ else
2603
+ dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false);
14552604
1456
- if (pipe_ctx->stream != stream)
1457
- continue;
2605
+ if ((update_type != UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed)
2606
+ if (top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) {
2607
+ top_pipe_to_program->stream_res.tg->funcs->wait_for_state(
2608
+ top_pipe_to_program->stream_res.tg,
2609
+ CRTC_STATE_VACTIVE);
2610
+ top_pipe_to_program->stream_res.tg->funcs->wait_for_state(
2611
+ top_pipe_to_program->stream_res.tg,
2612
+ CRTC_STATE_VBLANK);
2613
+ top_pipe_to_program->stream_res.tg->funcs->wait_for_state(
2614
+ top_pipe_to_program->stream_res.tg,
2615
+ CRTC_STATE_VACTIVE);
14582616
1459
- if (stream_update->hdr_static_metadata) {
1460
- resource_build_info_frame(pipe_ctx);
1461
- dc->hwss.update_info_frame(pipe_ctx);
1462
- }
2617
+ if (stream && should_use_dmub_lock(stream->link)) {
2618
+ union dmub_hw_lock_flags hw_locks = { 0 };
2619
+ struct dmub_hw_lock_inst_flags inst_flags = { 0 };
2620
+
2621
+ hw_locks.bits.lock_dig = 1;
2622
+ inst_flags.dig_inst = top_pipe_to_program->stream_res.tg->inst;
2623
+
2624
+ dmub_hw_lock_mgr_cmd(dc->ctx->dmub_srv,
2625
+ false,
2626
+ &hw_locks,
2627
+ &inst_flags);
2628
+ } else
2629
+ top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_disable(
2630
+ top_pipe_to_program->stream_res.tg);
14632631 }
2632
+
2633
+ if (update_type != UPDATE_TYPE_FAST)
2634
+ dc->hwss.post_unlock_program_front_end(dc, context);
2635
+
2636
+ // Fire manual trigger only when bottom plane is flipped
2637
+ for (j = 0; j < dc->res_pool->pipe_count; j++) {
2638
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
2639
+
2640
+ if (pipe_ctx->bottom_pipe ||
2641
+ !pipe_ctx->stream ||
2642
+ pipe_ctx->stream != stream ||
2643
+ !pipe_ctx->plane_state->update_flags.bits.addr_update)
2644
+ continue;
2645
+
2646
+ if (pipe_ctx->stream_res.tg->funcs->program_manual_trigger)
2647
+ pipe_ctx->stream_res.tg->funcs->program_manual_trigger(pipe_ctx->stream_res.tg);
2648
+ }
14642649 }
14652650
14662651 void dc_commit_updates_for_stream(struct dc *dc,
....@@ -1468,7 +2653,6 @@
14682653 int surface_count,
14692654 struct dc_stream_state *stream,
14702655 struct dc_stream_update *stream_update,
1471
- struct dc_plane_state **plane_states,
14722656 struct dc_state *state)
14732657 {
14742658 const struct dc_stream_status *stream_status;
....@@ -1490,7 +2674,7 @@
14902674 if (update_type >= UPDATE_TYPE_FULL) {
14912675
14922676 /* initialize scratch memory for building context */
1493
- context = dc_create_state();
2677
+ context = dc_create_state(dc);
14942678 if (context == NULL) {
14952679 DC_ERROR("Failed to allocate new validate context!\n");
14962680 return;
....@@ -1511,24 +2695,28 @@
15112695 for (i = 0; i < surface_count; i++) {
15122696 struct dc_plane_state *surface = srf_updates[i].surface;
15132697
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
- }
2698
+ copy_surface_update_to_plane(surface, &srf_updates[i]);
15222699
15232700 if (update_type >= UPDATE_TYPE_MED) {
15242701 for (j = 0; j < dc->res_pool->pipe_count; j++) {
1525
- struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
2702
+ struct pipe_ctx *pipe_ctx =
2703
+ &context->res_ctx.pipe_ctx[j];
15262704
15272705 if (pipe_ctx->plane_state != surface)
15282706 continue;
15292707
15302708 resource_build_scaling_params(pipe_ctx);
15312709 }
2710
+ }
2711
+ }
2712
+
2713
+ copy_stream_update_to_stream(dc, context, stream, stream_update);
2714
+
2715
+ if (update_type >= UPDATE_TYPE_FULL) {
2716
+ if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false)) {
2717
+ DC_ERROR("Mode validation failed for stream update!\n");
2718
+ dc_release_state(context);
2719
+ return;
15322720 }
15332721 }
15342722
....@@ -1575,6 +2763,19 @@
15752763 return NULL;
15762764 }
15772765
2766
+struct dc_stream_state *dc_stream_find_from_link(const struct dc_link *link)
2767
+{
2768
+ uint8_t i;
2769
+ struct dc_context *ctx = link->ctx;
2770
+
2771
+ for (i = 0; i < ctx->dc->current_state->stream_count; i++) {
2772
+ if (ctx->dc->current_state->streams[i]->link == link)
2773
+ return ctx->dc->current_state->streams[i];
2774
+ }
2775
+
2776
+ return NULL;
2777
+}
2778
+
15782779 enum dc_irq_source dc_interrupt_to_irq_source(
15792780 struct dc *dc,
15802781 uint32_t src_id,
....@@ -1583,6 +2784,9 @@
15832784 return dal_irq_service_to_irq_source(dc->res_pool->irqs, src_id, ext_id);
15842785 }
15852786
2787
+/**
2788
+ * dc_interrupt_set() - Enable/disable an AMD hw interrupt source
2789
+ */
15862790 bool dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable)
15872791 {
15882792
....@@ -1597,55 +2801,81 @@
15972801 dal_irq_service_ack(dc->res_pool->irqs, src);
15982802 }
15992803
2804
+void dc_power_down_on_boot(struct dc *dc)
2805
+{
2806
+ if (dc->ctx->dce_environment != DCE_ENV_VIRTUAL_HW &&
2807
+ dc->hwss.power_down_on_boot)
2808
+ dc->hwss.power_down_on_boot(dc);
2809
+}
2810
+
16002811 void dc_set_power_state(
16012812 struct dc *dc,
16022813 enum dc_acpi_cm_power_state power_state)
16032814 {
16042815 struct kref refcount;
2816
+ struct display_mode_lib *dml;
16052817
16062818 switch (power_state) {
16072819 case DC_ACPI_CM_POWER_STATE_D0:
16082820 dc_resource_state_construct(dc, dc->current_state);
16092821
2822
+ if (dc->ctx->dmub_srv)
2823
+ dc_dmub_srv_wait_phy_init(dc->ctx->dmub_srv);
2824
+
16102825 dc->hwss.init_hw(dc);
16112826
1612
-#ifdef CONFIG_DRM_AMD_DC_DCN2_0
16132827 if (dc->hwss.init_sys_ctx != NULL &&
16142828 dc->vm_pa_config.valid) {
16152829 dc->hwss.init_sys_ctx(dc->hwseq, dc, &dc->vm_pa_config);
16162830 }
1617
-#endif
16182831
16192832 break;
16202833 default:
1621
-
1622
- dc->hwss.power_down(dc);
1623
-
2834
+ ASSERT(dc->current_state->stream_count == 0);
16242835 /* Zero out the current context so that on resume we start with
16252836 * clean state, and dc hw programming optimizations will not
16262837 * cause any trouble.
16272838 */
2839
+ dml = kzalloc(sizeof(struct display_mode_lib),
2840
+ GFP_KERNEL);
2841
+
2842
+ ASSERT(dml);
2843
+ if (!dml)
2844
+ return;
16282845
16292846 /* Preserve refcount */
16302847 refcount = dc->current_state->refcount;
2848
+ /* Preserve display mode lib */
2849
+ memcpy(dml, &dc->current_state->bw_ctx.dml, sizeof(struct display_mode_lib));
2850
+
16312851 dc_resource_state_destruct(dc->current_state);
16322852 memset(dc->current_state, 0,
16332853 sizeof(*dc->current_state));
16342854
16352855 dc->current_state->refcount = refcount;
2856
+ dc->current_state->bw_ctx.dml = *dml;
2857
+
2858
+ kfree(dml);
16362859
16372860 break;
16382861 }
1639
-
16402862 }
16412863
16422864 void dc_resume(struct dc *dc)
16432865 {
1644
-
16452866 uint32_t i;
16462867
16472868 for (i = 0; i < dc->link_count; i++)
16482869 core_link_resume(dc->links[i]);
2870
+}
2871
+
2872
+bool dc_is_dmcu_initialized(struct dc *dc)
2873
+{
2874
+ struct dmcu *dmcu = dc->res_pool->dmcu;
2875
+
2876
+ if (dmcu)
2877
+ return dmcu->funcs->is_dmcu_initialized(dmcu);
2878
+ return false;
16492879 }
16502880
16512881 bool dc_submit_i2c(
....@@ -1656,9 +2886,19 @@
16562886
16572887 struct dc_link *link = dc->links[link_index];
16582888 struct ddc_service *ddc = link->ddc;
2889
+ return dce_i2c_submit_command(
2890
+ dc->res_pool,
2891
+ ddc->ddc_pin,
2892
+ cmd);
2893
+}
16592894
1660
- return dal_i2caux_submit_i2c_command(
1661
- ddc->ctx->i2caux,
2895
+bool dc_submit_i2c_oem(
2896
+ struct dc *dc,
2897
+ struct i2c_command *cmd)
2898
+{
2899
+ struct ddc_service *ddc = dc->res_pool->oem_device;
2900
+ return dce_i2c_submit_command(
2901
+ dc->res_pool,
16622902 ddc->ddc_pin,
16632903 cmd);
16642904 }
....@@ -1678,6 +2918,11 @@
16782918 return true;
16792919 }
16802920
2921
+/**
2922
+ * dc_link_add_remote_sink() - Create a sink and attach it to an existing link
2923
+ *
2924
+ * EDID length is in bytes
2925
+ */
16812926 struct dc_sink *dc_link_add_remote_sink(
16822927 struct dc_link *link,
16832928 const uint8_t *edid,
....@@ -1736,6 +2981,12 @@
17362981 return NULL;
17372982 }
17382983
2984
+/**
2985
+ * dc_link_remove_remote_sink() - Remove a remote sink from a dc_link
2986
+ *
2987
+ * Note that this just removes the struct dc_sink - it doesn't
2988
+ * program hardware or alter other members of dc_link
2989
+ */
17392990 void dc_link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink)
17402991 {
17412992 int i;
....@@ -1761,3 +3012,105 @@
17613012 }
17623013 }
17633014 }
3015
+
3016
+void get_clock_requirements_for_state(struct dc_state *state, struct AsicStateEx *info)
3017
+{
3018
+ info->displayClock = (unsigned int)state->bw_ctx.bw.dcn.clk.dispclk_khz;
3019
+ info->engineClock = (unsigned int)state->bw_ctx.bw.dcn.clk.dcfclk_khz;
3020
+ info->memoryClock = (unsigned int)state->bw_ctx.bw.dcn.clk.dramclk_khz;
3021
+ info->maxSupportedDppClock = (unsigned int)state->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz;
3022
+ info->dppClock = (unsigned int)state->bw_ctx.bw.dcn.clk.dppclk_khz;
3023
+ info->socClock = (unsigned int)state->bw_ctx.bw.dcn.clk.socclk_khz;
3024
+ info->dcfClockDeepSleep = (unsigned int)state->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz;
3025
+ info->fClock = (unsigned int)state->bw_ctx.bw.dcn.clk.fclk_khz;
3026
+ info->phyClock = (unsigned int)state->bw_ctx.bw.dcn.clk.phyclk_khz;
3027
+}
3028
+enum dc_status dc_set_clock(struct dc *dc, enum dc_clock_type clock_type, uint32_t clk_khz, uint32_t stepping)
3029
+{
3030
+ if (dc->hwss.set_clock)
3031
+ return dc->hwss.set_clock(dc, clock_type, clk_khz, stepping);
3032
+ return DC_ERROR_UNEXPECTED;
3033
+}
3034
+void dc_get_clock(struct dc *dc, enum dc_clock_type clock_type, struct dc_clock_config *clock_cfg)
3035
+{
3036
+ if (dc->hwss.get_clock)
3037
+ dc->hwss.get_clock(dc, clock_type, clock_cfg);
3038
+}
3039
+
3040
+/* enable/disable eDP PSR without specify stream for eDP */
3041
+bool dc_set_psr_allow_active(struct dc *dc, bool enable)
3042
+{
3043
+ int i;
3044
+
3045
+ for (i = 0; i < dc->current_state->stream_count ; i++) {
3046
+ struct dc_link *link;
3047
+ struct dc_stream_state *stream = dc->current_state->streams[i];
3048
+
3049
+ link = stream->link;
3050
+ if (!link)
3051
+ continue;
3052
+
3053
+ if (link->psr_settings.psr_feature_enabled) {
3054
+ if (enable && !link->psr_settings.psr_allow_active)
3055
+ return dc_link_set_psr_allow_active(link, true, false);
3056
+ else if (!enable && link->psr_settings.psr_allow_active)
3057
+ return dc_link_set_psr_allow_active(link, false, true);
3058
+ }
3059
+ }
3060
+
3061
+ return true;
3062
+}
3063
+
3064
+#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
3065
+
3066
+void dc_allow_idle_optimizations(struct dc *dc, bool allow)
3067
+{
3068
+ if (dc->debug.disable_idle_power_optimizations)
3069
+ return;
3070
+
3071
+ if (allow == dc->idle_optimizations_allowed)
3072
+ return;
3073
+
3074
+ if (dc->hwss.apply_idle_power_optimizations && dc->hwss.apply_idle_power_optimizations(dc, allow))
3075
+ dc->idle_optimizations_allowed = allow;
3076
+}
3077
+
3078
+/*
3079
+ * blank all streams, and set min and max memory clock to
3080
+ * lowest and highest DPM level, respectively
3081
+ */
3082
+void dc_unlock_memory_clock_frequency(struct dc *dc)
3083
+{
3084
+ unsigned int i;
3085
+
3086
+ for (i = 0; i < MAX_PIPES; i++)
3087
+ if (dc->current_state->res_ctx.pipe_ctx[i].plane_state)
3088
+ core_link_disable_stream(&dc->current_state->res_ctx.pipe_ctx[i]);
3089
+
3090
+ dc->clk_mgr->funcs->set_hard_min_memclk(dc->clk_mgr, false);
3091
+ dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr);
3092
+}
3093
+
3094
+/*
3095
+ * set min memory clock to the min required for current mode,
3096
+ * max to maxDPM, and unblank streams
3097
+ */
3098
+void dc_lock_memory_clock_frequency(struct dc *dc)
3099
+{
3100
+ unsigned int i;
3101
+
3102
+ dc->clk_mgr->funcs->get_memclk_states_from_smu(dc->clk_mgr);
3103
+ dc->clk_mgr->funcs->set_hard_min_memclk(dc->clk_mgr, true);
3104
+ dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr);
3105
+
3106
+ for (i = 0; i < MAX_PIPES; i++)
3107
+ if (dc->current_state->res_ctx.pipe_ctx[i].plane_state)
3108
+ core_link_enable_stream(dc->current_state, &dc->current_state->res_ctx.pipe_ctx[i]);
3109
+}
3110
+
3111
+bool dc_is_plane_eligible_for_idle_optimizaitons(struct dc *dc,
3112
+ struct dc_plane_state *plane)
3113
+{
3114
+ return false;
3115
+}
3116
+#endif