hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
....@@ -22,6 +22,9 @@
2222 * Authors: AMD
2323 *
2424 */
25
+
26
+#include <linux/slab.h>
27
+
2528 #include "dm_services.h"
2629
2730 #include "resource.h"
....@@ -31,20 +34,30 @@
3134 #include "opp.h"
3235 #include "timing_generator.h"
3336 #include "transform.h"
37
+#include "dccg.h"
38
+#include "dchubbub.h"
3439 #include "dpp.h"
3540 #include "core_types.h"
3641 #include "set_mode_types.h"
3742 #include "virtual/virtual_stream_encoder.h"
3843 #include "dpcd_defs.h"
3944
45
+#if defined(CONFIG_DRM_AMD_DC_SI)
46
+#include "dce60/dce60_resource.h"
47
+#endif
4048 #include "dce80/dce80_resource.h"
4149 #include "dce100/dce100_resource.h"
4250 #include "dce110/dce110_resource.h"
4351 #include "dce112/dce112_resource.h"
44
-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
45
-#include "dcn10/dcn10_resource.h"
46
-#endif
4752 #include "dce120/dce120_resource.h"
53
+#if defined(CONFIG_DRM_AMD_DC_DCN)
54
+#include "dcn10/dcn10_resource.h"
55
+#include "dcn20/dcn20_resource.h"
56
+#include "dcn21/dcn21_resource.h"
57
+#endif
58
+#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
59
+#include "../dcn30/dcn30_resource.h"
60
+#endif
4861
4962 #define DC_LOGGER_INIT(logger)
5063
....@@ -53,6 +66,18 @@
5366 enum dce_version dc_version = DCE_VERSION_UNKNOWN;
5467 switch (asic_id.chip_family) {
5568
69
+#if defined(CONFIG_DRM_AMD_DC_SI)
70
+ case FAMILY_SI:
71
+ if (ASIC_REV_IS_TAHITI_P(asic_id.hw_internal_rev) ||
72
+ ASIC_REV_IS_PITCAIRN_PM(asic_id.hw_internal_rev) ||
73
+ ASIC_REV_IS_CAPEVERDE_M(asic_id.hw_internal_rev))
74
+ dc_version = DCE_VERSION_6_0;
75
+ else if (ASIC_REV_IS_OLAND_M(asic_id.hw_internal_rev))
76
+ dc_version = DCE_VERSION_6_4;
77
+ else
78
+ dc_version = DCE_VERSION_6_1;
79
+ break;
80
+#endif
5681 case FAMILY_CI:
5782 dc_version = DCE_VERSION_8_0;
5883 break;
....@@ -83,13 +108,30 @@
83108 dc_version = DCE_VERSION_11_22;
84109 break;
85110 case FAMILY_AI:
86
- dc_version = DCE_VERSION_12_0;
111
+ if (ASICREV_IS_VEGA20_P(asic_id.hw_internal_rev))
112
+ dc_version = DCE_VERSION_12_1;
113
+ else
114
+ dc_version = DCE_VERSION_12_0;
87115 break;
88
-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
116
+#if defined(CONFIG_DRM_AMD_DC_DCN)
89117 case FAMILY_RV:
90118 dc_version = DCN_VERSION_1_0;
119
+ if (ASICREV_IS_RAVEN2(asic_id.hw_internal_rev))
120
+ dc_version = DCN_VERSION_1_01;
121
+ if (ASICREV_IS_RENOIR(asic_id.hw_internal_rev))
122
+ dc_version = DCN_VERSION_2_1;
123
+ if (ASICREV_IS_GREEN_SARDINE(asic_id.hw_internal_rev))
124
+ dc_version = DCN_VERSION_2_1;
91125 break;
92126 #endif
127
+
128
+ case FAMILY_NV:
129
+ dc_version = DCN_VERSION_2_0;
130
+#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
131
+ if (ASICREV_IS_SIENNA_CICHLID_P(asic_id.hw_internal_rev))
132
+ dc_version = DCN_VERSION_3_0;
133
+#endif
134
+ break;
93135 default:
94136 dc_version = DCE_VERSION_UNKNOWN;
95137 break;
....@@ -97,64 +139,99 @@
97139 return dc_version;
98140 }
99141
100
-struct resource_pool *dc_create_resource_pool(
101
- struct dc *dc,
102
- int num_virtual_links,
103
- enum dce_version dc_version,
104
- struct hw_asic_id asic_id)
142
+struct resource_pool *dc_create_resource_pool(struct dc *dc,
143
+ const struct dc_init_data *init_data,
144
+ enum dce_version dc_version)
105145 {
106146 struct resource_pool *res_pool = NULL;
107147
108148 switch (dc_version) {
149
+#if defined(CONFIG_DRM_AMD_DC_SI)
150
+ case DCE_VERSION_6_0:
151
+ res_pool = dce60_create_resource_pool(
152
+ init_data->num_virtual_links, dc);
153
+ break;
154
+ case DCE_VERSION_6_1:
155
+ res_pool = dce61_create_resource_pool(
156
+ init_data->num_virtual_links, dc);
157
+ break;
158
+ case DCE_VERSION_6_4:
159
+ res_pool = dce64_create_resource_pool(
160
+ init_data->num_virtual_links, dc);
161
+ break;
162
+#endif
109163 case DCE_VERSION_8_0:
110164 res_pool = dce80_create_resource_pool(
111
- num_virtual_links, dc);
165
+ init_data->num_virtual_links, dc);
112166 break;
113167 case DCE_VERSION_8_1:
114168 res_pool = dce81_create_resource_pool(
115
- num_virtual_links, dc);
169
+ init_data->num_virtual_links, dc);
116170 break;
117171 case DCE_VERSION_8_3:
118172 res_pool = dce83_create_resource_pool(
119
- num_virtual_links, dc);
173
+ init_data->num_virtual_links, dc);
120174 break;
121175 case DCE_VERSION_10_0:
122176 res_pool = dce100_create_resource_pool(
123
- num_virtual_links, dc);
177
+ init_data->num_virtual_links, dc);
124178 break;
125179 case DCE_VERSION_11_0:
126180 res_pool = dce110_create_resource_pool(
127
- num_virtual_links, dc, asic_id);
181
+ init_data->num_virtual_links, dc,
182
+ init_data->asic_id);
128183 break;
129184 case DCE_VERSION_11_2:
130185 case DCE_VERSION_11_22:
131186 res_pool = dce112_create_resource_pool(
132
- num_virtual_links, dc);
187
+ init_data->num_virtual_links, dc);
133188 break;
134189 case DCE_VERSION_12_0:
190
+ case DCE_VERSION_12_1:
135191 res_pool = dce120_create_resource_pool(
136
- num_virtual_links, dc);
192
+ init_data->num_virtual_links, dc);
137193 break;
138194
139
-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
195
+#if defined(CONFIG_DRM_AMD_DC_DCN)
140196 case DCN_VERSION_1_0:
141
- res_pool = dcn10_create_resource_pool(
142
- num_virtual_links, dc);
197
+ case DCN_VERSION_1_01:
198
+ res_pool = dcn10_create_resource_pool(init_data, dc);
199
+ break;
200
+
201
+
202
+ case DCN_VERSION_2_0:
203
+ res_pool = dcn20_create_resource_pool(init_data, dc);
204
+ break;
205
+ case DCN_VERSION_2_1:
206
+ res_pool = dcn21_create_resource_pool(init_data, dc);
143207 break;
144208 #endif
145
-
209
+#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
210
+ case DCN_VERSION_3_0:
211
+ res_pool = dcn30_create_resource_pool(init_data, dc);
212
+ break;
213
+#endif
146214
147215 default:
148216 break;
149217 }
150
- if (res_pool != NULL) {
151
- struct dc_firmware_info fw_info = { { 0 } };
152218
153
- if (dc->ctx->dc_bios->funcs->get_firmware_info(
154
- dc->ctx->dc_bios, &fw_info) == BP_RESULT_OK) {
155
- res_pool->ref_clock_inKhz = fw_info.pll_info.crystal_frequency;
156
- } else
157
- ASSERT_CRITICAL(false);
219
+ if (res_pool != NULL) {
220
+ if (dc->ctx->dc_bios->fw_info_valid) {
221
+ res_pool->ref_clocks.xtalin_clock_inKhz =
222
+ dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
223
+ /* initialize with firmware data first, no all
224
+ * ASIC have DCCG SW component. FPGA or
225
+ * simulation need initialization of
226
+ * dccg_ref_clock_inKhz, dchub_ref_clock_inKhz
227
+ * with xtalin_clock_inKhz
228
+ */
229
+ res_pool->ref_clocks.dccg_ref_clock_inKhz =
230
+ res_pool->ref_clocks.xtalin_clock_inKhz;
231
+ res_pool->ref_clocks.dchub_ref_clock_inKhz =
232
+ res_pool->ref_clocks.xtalin_clock_inKhz;
233
+ } else
234
+ ASSERT_CRITICAL(false);
158235 }
159236
160237 return res_pool;
....@@ -247,6 +324,17 @@
247324 pool->stream_enc_count++;
248325 }
249326 }
327
+
328
+#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
329
+ for (i = 0; i < caps->num_mpc_3dlut; i++) {
330
+ pool->mpc_lut[i] = dc_create_3dlut_func();
331
+ if (pool->mpc_lut[i] == NULL)
332
+ DC_ERR("DC: failed to create MPC 3dlut!\n");
333
+ pool->mpc_shaper[i] = dc_create_transfer_func();
334
+ if (pool->mpc_shaper[i] == NULL)
335
+ DC_ERR("DC: failed to create MPC shaper!\n");
336
+ }
337
+#endif
250338 dc->caps.dynamic_audio = false;
251339 if (pool->audio_count < pool->stream_enc_count) {
252340 dc->caps.dynamic_audio = true;
....@@ -342,8 +430,12 @@
342430 != stream2->timing.v_addressable)
343431 return false;
344432
345
- if (stream1->timing.pix_clk_khz
346
- != stream2->timing.pix_clk_khz)
433
+ if (stream1->timing.v_front_porch
434
+ != stream2->timing.v_front_porch)
435
+ return false;
436
+
437
+ if (stream1->timing.pix_clk_100hz
438
+ != stream2->timing.pix_clk_100hz)
347439 return false;
348440
349441 if (stream1->clamping.c_depth != stream2->clamping.c_depth)
....@@ -352,6 +444,12 @@
352444 if (stream1->phy_pix_clk != stream2->phy_pix_clk
353445 && (!dc_is_dp_signal(stream1->signal)
354446 || !dc_is_dp_signal(stream2->signal)))
447
+ return false;
448
+
449
+ if (stream1->view_format != stream2->view_format)
450
+ return false;
451
+
452
+ if (stream1->ignore_msa_timing_param || stream2->ignore_msa_timing_param)
355453 return false;
356454
357455 return true;
....@@ -364,8 +462,8 @@
364462 return false;
365463
366464 if (stream1->clamping.c_depth != COLOR_DEPTH_888 ||
367
- stream2->clamping.c_depth != COLOR_DEPTH_888)
368
- return false;
465
+ stream2->clamping.c_depth != COLOR_DEPTH_888)
466
+ return false;
369467
370468 return true;
371469
....@@ -466,10 +564,87 @@
466564 return dal_pixel_format;
467565 }
468566
469
-static void rect_swap_helper(struct rect *rect)
567
+static inline void get_vp_scan_direction(
568
+ enum dc_rotation_angle rotation,
569
+ bool horizontal_mirror,
570
+ bool *orthogonal_rotation,
571
+ bool *flip_vert_scan_dir,
572
+ bool *flip_horz_scan_dir)
470573 {
471
- swap(rect->height, rect->width);
472
- swap(rect->x, rect->y);
574
+ *orthogonal_rotation = false;
575
+ *flip_vert_scan_dir = false;
576
+ *flip_horz_scan_dir = false;
577
+ if (rotation == ROTATION_ANGLE_180) {
578
+ *flip_vert_scan_dir = true;
579
+ *flip_horz_scan_dir = true;
580
+ } else if (rotation == ROTATION_ANGLE_90) {
581
+ *orthogonal_rotation = true;
582
+ *flip_horz_scan_dir = true;
583
+ } else if (rotation == ROTATION_ANGLE_270) {
584
+ *orthogonal_rotation = true;
585
+ *flip_vert_scan_dir = true;
586
+ }
587
+
588
+ if (horizontal_mirror)
589
+ *flip_horz_scan_dir = !*flip_horz_scan_dir;
590
+}
591
+
592
+int get_num_mpc_splits(struct pipe_ctx *pipe)
593
+{
594
+ int mpc_split_count = 0;
595
+ struct pipe_ctx *other_pipe = pipe->bottom_pipe;
596
+
597
+ while (other_pipe && other_pipe->plane_state == pipe->plane_state) {
598
+ mpc_split_count++;
599
+ other_pipe = other_pipe->bottom_pipe;
600
+ }
601
+ other_pipe = pipe->top_pipe;
602
+ while (other_pipe && other_pipe->plane_state == pipe->plane_state) {
603
+ mpc_split_count++;
604
+ other_pipe = other_pipe->top_pipe;
605
+ }
606
+
607
+ return mpc_split_count;
608
+}
609
+
610
+int get_num_odm_splits(struct pipe_ctx *pipe)
611
+{
612
+ int odm_split_count = 0;
613
+ struct pipe_ctx *next_pipe = pipe->next_odm_pipe;
614
+ while (next_pipe) {
615
+ odm_split_count++;
616
+ next_pipe = next_pipe->next_odm_pipe;
617
+ }
618
+ pipe = pipe->prev_odm_pipe;
619
+ while (pipe) {
620
+ odm_split_count++;
621
+ pipe = pipe->prev_odm_pipe;
622
+ }
623
+ return odm_split_count;
624
+}
625
+
626
+static void calculate_split_count_and_index(struct pipe_ctx *pipe_ctx, int *split_count, int *split_idx)
627
+{
628
+ *split_count = get_num_odm_splits(pipe_ctx);
629
+ *split_idx = 0;
630
+ if (*split_count == 0) {
631
+ /*Check for mpc split*/
632
+ struct pipe_ctx *split_pipe = pipe_ctx->top_pipe;
633
+
634
+ *split_count = get_num_mpc_splits(pipe_ctx);
635
+ while (split_pipe && split_pipe->plane_state == pipe_ctx->plane_state) {
636
+ (*split_idx)++;
637
+ split_pipe = split_pipe->top_pipe;
638
+ }
639
+ } else {
640
+ /*Get odm split index*/
641
+ struct pipe_ctx *split_pipe = pipe_ctx->prev_odm_pipe;
642
+
643
+ while (split_pipe) {
644
+ (*split_idx)++;
645
+ split_pipe = split_pipe->prev_odm_pipe;
646
+ }
647
+ }
473648 }
474649
475650 static void calculate_viewport(struct pipe_ctx *pipe_ctx)
....@@ -478,27 +653,25 @@
478653 const struct dc_stream_state *stream = pipe_ctx->stream;
479654 struct scaler_data *data = &pipe_ctx->plane_res.scl_data;
480655 struct rect surf_src = plane_state->src_rect;
481
- struct rect clip = { 0 };
656
+ struct rect clip, dest;
482657 int vpc_div = (data->format == PIXEL_FORMAT_420BPP8
483658 || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1;
484
- bool pri_split = pipe_ctx->bottom_pipe &&
485
- pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state;
486
- bool sec_split = pipe_ctx->top_pipe &&
487
- pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state;
659
+ int split_count = 0;
660
+ int split_idx = 0;
661
+ bool orthogonal_rotation, flip_y_start, flip_x_start;
662
+
663
+ calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx);
488664
489665 if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE ||
490666 stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) {
491
- pri_split = false;
492
- sec_split = false;
667
+ split_count = 0;
668
+ split_idx = 0;
493669 }
494
-
495
- if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 ||
496
- pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270)
497
- rect_swap_helper(&surf_src);
498670
499671 /* The actual clip is an intersection between stream
500672 * source and surface clip
501673 */
674
+ dest = plane_state->dst_rect;
502675 clip.x = stream->src.x > plane_state->clip_rect.x ?
503676 stream->src.x : plane_state->clip_rect.x;
504677
....@@ -515,139 +688,148 @@
515688 stream->src.y + stream->src.height - clip.y :
516689 plane_state->clip_rect.y + plane_state->clip_rect.height - clip.y ;
517690
691
+ /*
692
+ * Need to calculate how scan origin is shifted in vp space
693
+ * to correctly rotate clip and dst
694
+ */
695
+ get_vp_scan_direction(
696
+ plane_state->rotation,
697
+ plane_state->horizontal_mirror,
698
+ &orthogonal_rotation,
699
+ &flip_y_start,
700
+ &flip_x_start);
701
+
702
+ if (orthogonal_rotation) {
703
+ swap(clip.x, clip.y);
704
+ swap(clip.width, clip.height);
705
+ swap(dest.x, dest.y);
706
+ swap(dest.width, dest.height);
707
+ }
708
+ if (flip_x_start) {
709
+ clip.x = dest.x + dest.width - clip.x - clip.width;
710
+ dest.x = 0;
711
+ }
712
+ if (flip_y_start) {
713
+ clip.y = dest.y + dest.height - clip.y - clip.height;
714
+ dest.y = 0;
715
+ }
716
+
518717 /* offset = surf_src.ofs + (clip.ofs - surface->dst_rect.ofs) * scl_ratio
519718 * num_pixels = clip.num_pix * scl_ratio
520719 */
521
- data->viewport.x = surf_src.x + (clip.x - plane_state->dst_rect.x) *
522
- surf_src.width / plane_state->dst_rect.width;
523
- data->viewport.width = clip.width *
524
- surf_src.width / plane_state->dst_rect.width;
720
+ data->viewport.x = surf_src.x + (clip.x - dest.x) * surf_src.width / dest.width;
721
+ data->viewport.width = clip.width * surf_src.width / dest.width;
525722
526
- data->viewport.y = surf_src.y + (clip.y - plane_state->dst_rect.y) *
527
- surf_src.height / plane_state->dst_rect.height;
528
- data->viewport.height = clip.height *
529
- surf_src.height / plane_state->dst_rect.height;
723
+ data->viewport.y = surf_src.y + (clip.y - dest.y) * surf_src.height / dest.height;
724
+ data->viewport.height = clip.height * surf_src.height / dest.height;
725
+
726
+ /* Handle split */
727
+ if (split_count) {
728
+ /* extra pixels in the division remainder need to go to pipes after
729
+ * the extra pixel index minus one(epimo) defined here as:
730
+ */
731
+ int epimo = 0;
732
+
733
+ if (orthogonal_rotation) {
734
+ if (flip_y_start)
735
+ split_idx = split_count - split_idx;
736
+
737
+ epimo = split_count - data->viewport.height % (split_count + 1);
738
+
739
+ data->viewport.y += (data->viewport.height / (split_count + 1)) * split_idx;
740
+ if (split_idx > epimo)
741
+ data->viewport.y += split_idx - epimo - 1;
742
+ data->viewport.height = data->viewport.height / (split_count + 1) + (split_idx > epimo ? 1 : 0);
743
+ } else {
744
+ if (flip_x_start)
745
+ split_idx = split_count - split_idx;
746
+
747
+ epimo = split_count - data->viewport.width % (split_count + 1);
748
+
749
+ data->viewport.x += (data->viewport.width / (split_count + 1)) * split_idx;
750
+ if (split_idx > epimo)
751
+ data->viewport.x += split_idx - epimo - 1;
752
+ data->viewport.width = data->viewport.width / (split_count + 1) + (split_idx > epimo ? 1 : 0);
753
+ }
754
+ }
530755
531756 /* Round down, compensate in init */
532757 data->viewport_c.x = data->viewport.x / vpc_div;
533758 data->viewport_c.y = data->viewport.y / vpc_div;
534
- data->inits.h_c = (data->viewport.x % vpc_div) != 0 ?
535
- dc_fixpt_half : dc_fixpt_zero;
536
- data->inits.v_c = (data->viewport.y % vpc_div) != 0 ?
537
- dc_fixpt_half : dc_fixpt_zero;
759
+ data->inits.h_c = (data->viewport.x % vpc_div) != 0 ? dc_fixpt_half : dc_fixpt_zero;
760
+ data->inits.v_c = (data->viewport.y % vpc_div) != 0 ? dc_fixpt_half : dc_fixpt_zero;
761
+
538762 /* Round up, assume original video size always even dimensions */
539763 data->viewport_c.width = (data->viewport.width + vpc_div - 1) / vpc_div;
540764 data->viewport_c.height = (data->viewport.height + vpc_div - 1) / vpc_div;
541765
542
- /* Handle hsplit */
543
- if (sec_split) {
544
- data->viewport.x += data->viewport.width / 2;
545
- data->viewport_c.x += data->viewport_c.width / 2;
546
- /* Ceil offset pipe */
547
- data->viewport.width = (data->viewport.width + 1) / 2;
548
- data->viewport_c.width = (data->viewport_c.width + 1) / 2;
549
- } else if (pri_split) {
550
- data->viewport.width /= 2;
551
- data->viewport_c.width /= 2;
552
- }
553
-
554
- if (plane_state->rotation == ROTATION_ANGLE_90 ||
555
- plane_state->rotation == ROTATION_ANGLE_270) {
556
- rect_swap_helper(&data->viewport_c);
557
- rect_swap_helper(&data->viewport);
558
- }
766
+ data->viewport_unadjusted = data->viewport;
767
+ data->viewport_c_unadjusted = data->viewport_c;
559768 }
560769
561
-static void calculate_recout(struct pipe_ctx *pipe_ctx, struct rect *recout_full)
770
+static void calculate_recout(struct pipe_ctx *pipe_ctx)
562771 {
563772 const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
564773 const struct dc_stream_state *stream = pipe_ctx->stream;
565
- struct rect surf_src = plane_state->src_rect;
774
+ struct scaler_data *data = &pipe_ctx->plane_res.scl_data;
566775 struct rect surf_clip = plane_state->clip_rect;
567
- bool pri_split = pipe_ctx->bottom_pipe &&
568
- pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state;
569
- bool sec_split = pipe_ctx->top_pipe &&
570
- pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state;
571
- bool top_bottom_split = stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM;
776
+ bool pri_split_tb = pipe_ctx->bottom_pipe &&
777
+ pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state &&
778
+ stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM;
779
+ bool sec_split_tb = pipe_ctx->top_pipe &&
780
+ pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state &&
781
+ stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM;
782
+ int split_count = 0;
783
+ int split_idx = 0;
572784
573
- if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 ||
574
- pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270)
575
- rect_swap_helper(&surf_src);
785
+ calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx);
576786
577
- pipe_ctx->plane_res.scl_data.recout.x = stream->dst.x;
578
- if (stream->src.x < surf_clip.x)
579
- pipe_ctx->plane_res.scl_data.recout.x += (surf_clip.x
580
- - stream->src.x) * stream->dst.width
787
+ /*
788
+ * Only the leftmost ODM pipe should be offset by a nonzero distance
789
+ */
790
+ if (!pipe_ctx->prev_odm_pipe) {
791
+ data->recout.x = stream->dst.x;
792
+ if (stream->src.x < surf_clip.x)
793
+ data->recout.x += (surf_clip.x - stream->src.x) * stream->dst.width
581794 / stream->src.width;
582795
583
- pipe_ctx->plane_res.scl_data.recout.width = surf_clip.width *
584
- stream->dst.width / stream->src.width;
585
- if (pipe_ctx->plane_res.scl_data.recout.width + pipe_ctx->plane_res.scl_data.recout.x >
586
- stream->dst.x + stream->dst.width)
587
- pipe_ctx->plane_res.scl_data.recout.width =
588
- stream->dst.x + stream->dst.width
589
- - pipe_ctx->plane_res.scl_data.recout.x;
796
+ } else
797
+ data->recout.x = 0;
590798
591
- pipe_ctx->plane_res.scl_data.recout.y = stream->dst.y;
799
+ data->recout.width = surf_clip.width * stream->dst.width / stream->src.width;
800
+ if (data->recout.width + data->recout.x > stream->dst.x + stream->dst.width)
801
+ data->recout.width = stream->dst.x + stream->dst.width - data->recout.x;
802
+
803
+ data->recout.y = stream->dst.y;
592804 if (stream->src.y < surf_clip.y)
593
- pipe_ctx->plane_res.scl_data.recout.y += (surf_clip.y
594
- - stream->src.y) * stream->dst.height
805
+ data->recout.y += (surf_clip.y - stream->src.y) * stream->dst.height
595806 / stream->src.height;
596807
597
- pipe_ctx->plane_res.scl_data.recout.height = surf_clip.height *
598
- stream->dst.height / stream->src.height;
599
- if (pipe_ctx->plane_res.scl_data.recout.height + pipe_ctx->plane_res.scl_data.recout.y >
600
- stream->dst.y + stream->dst.height)
601
- pipe_ctx->plane_res.scl_data.recout.height =
602
- stream->dst.y + stream->dst.height
603
- - pipe_ctx->plane_res.scl_data.recout.y;
808
+ data->recout.height = surf_clip.height * stream->dst.height / stream->src.height;
809
+ if (data->recout.height + data->recout.y > stream->dst.y + stream->dst.height)
810
+ data->recout.height = stream->dst.y + stream->dst.height - data->recout.y;
604811
605
- /* Handle h & vsplit */
606
- if (sec_split && top_bottom_split) {
607
- pipe_ctx->plane_res.scl_data.recout.y +=
608
- pipe_ctx->plane_res.scl_data.recout.height / 2;
812
+ /* Handle h & v split, handle rotation using viewport */
813
+ if (sec_split_tb) {
814
+ data->recout.y += data->recout.height / 2;
609815 /* Floor primary pipe, ceil 2ndary pipe */
610
- pipe_ctx->plane_res.scl_data.recout.height =
611
- (pipe_ctx->plane_res.scl_data.recout.height + 1) / 2;
612
- } else if (pri_split && top_bottom_split)
613
- pipe_ctx->plane_res.scl_data.recout.height /= 2;
614
- else if (pri_split || sec_split) {
615
- /* HMirror XOR Secondary_pipe XOR Rotation_180 */
616
- bool right_view = (sec_split != plane_state->horizontal_mirror) !=
617
- (plane_state->rotation == ROTATION_ANGLE_180);
816
+ data->recout.height = (data->recout.height + 1) / 2;
817
+ } else if (pri_split_tb)
818
+ data->recout.height /= 2;
819
+ else if (split_count) {
820
+ /* extra pixels in the division remainder need to go to pipes after
821
+ * the extra pixel index minus one(epimo) defined here as:
822
+ */
823
+ int epimo = split_count - data->recout.width % (split_count + 1);
618824
619
- if (plane_state->rotation == ROTATION_ANGLE_90
620
- || plane_state->rotation == ROTATION_ANGLE_270)
621
- /* Secondary_pipe XOR Rotation_270 */
622
- right_view = (plane_state->rotation == ROTATION_ANGLE_270) != sec_split;
623
-
624
- if (right_view) {
625
- pipe_ctx->plane_res.scl_data.recout.x +=
626
- pipe_ctx->plane_res.scl_data.recout.width / 2;
627
- /* Ceil offset pipe */
628
- pipe_ctx->plane_res.scl_data.recout.width =
629
- (pipe_ctx->plane_res.scl_data.recout.width + 1) / 2;
630
- } else {
631
- pipe_ctx->plane_res.scl_data.recout.width /= 2;
825
+ /*no recout offset due to odm */
826
+ if (!pipe_ctx->next_odm_pipe && !pipe_ctx->prev_odm_pipe) {
827
+ data->recout.x += (data->recout.width / (split_count + 1)) * split_idx;
828
+ if (split_idx > epimo)
829
+ data->recout.x += split_idx - epimo - 1;
632830 }
831
+ data->recout.width = data->recout.width / (split_count + 1) + (split_idx > epimo ? 1 : 0);
633832 }
634
- /* Unclipped recout offset = stream dst offset + ((surf dst offset - stream surf_src offset)
635
- * * 1/ stream scaling ratio) - (surf surf_src offset * 1/ full scl
636
- * ratio)
637
- */
638
- recout_full->x = stream->dst.x + (plane_state->dst_rect.x - stream->src.x)
639
- * stream->dst.width / stream->src.width -
640
- surf_src.x * plane_state->dst_rect.width / surf_src.width
641
- * stream->dst.width / stream->src.width;
642
- recout_full->y = stream->dst.y + (plane_state->dst_rect.y - stream->src.y)
643
- * stream->dst.height / stream->src.height -
644
- surf_src.y * plane_state->dst_rect.height / surf_src.height
645
- * stream->dst.height / stream->src.height;
646
-
647
- recout_full->width = plane_state->dst_rect.width
648
- * stream->dst.width / stream->src.width;
649
- recout_full->height = plane_state->dst_rect.height
650
- * stream->dst.height / stream->src.height;
651833 }
652834
653835 static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx)
....@@ -660,9 +842,10 @@
660842 const int out_w = stream->dst.width;
661843 const int out_h = stream->dst.height;
662844
845
+ /*Swap surf_src height and width since scaling ratios are in recout rotation*/
663846 if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 ||
664847 pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270)
665
- rect_swap_helper(&surf_src);
848
+ swap(surf_src.height, surf_src.width);
666849
667850 pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_from_fraction(
668851 surf_src.width,
....@@ -699,33 +882,146 @@
699882 pipe_ctx->plane_res.scl_data.ratios.vert_c, 19);
700883 }
701884
702
-static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct rect *recout_full)
885
+static inline void adjust_vp_and_init_for_seamless_clip(
886
+ bool flip_scan_dir,
887
+ int recout_skip,
888
+ int src_size,
889
+ int taps,
890
+ struct fixed31_32 ratio,
891
+ struct fixed31_32 *init,
892
+ int *vp_offset,
893
+ int *vp_size)
703894 {
895
+ if (!flip_scan_dir) {
896
+ /* Adjust for viewport end clip-off */
897
+ if ((*vp_offset + *vp_size) < src_size) {
898
+ int vp_clip = src_size - *vp_size - *vp_offset;
899
+ int int_part = dc_fixpt_floor(dc_fixpt_sub(*init, ratio));
900
+
901
+ int_part = int_part > 0 ? int_part : 0;
902
+ *vp_size += int_part < vp_clip ? int_part : vp_clip;
903
+ }
904
+
905
+ /* Adjust for non-0 viewport offset */
906
+ if (*vp_offset) {
907
+ int int_part;
908
+
909
+ *init = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_skip));
910
+ int_part = dc_fixpt_floor(*init) - *vp_offset;
911
+ if (int_part < taps) {
912
+ int int_adj = *vp_offset >= (taps - int_part) ?
913
+ (taps - int_part) : *vp_offset;
914
+ *vp_offset -= int_adj;
915
+ *vp_size += int_adj;
916
+ int_part += int_adj;
917
+ } else if (int_part > taps) {
918
+ *vp_offset += int_part - taps;
919
+ *vp_size -= int_part - taps;
920
+ int_part = taps;
921
+ }
922
+ init->value &= 0xffffffff;
923
+ *init = dc_fixpt_add_int(*init, int_part);
924
+ }
925
+ } else {
926
+ /* Adjust for non-0 viewport offset */
927
+ if (*vp_offset) {
928
+ int int_part = dc_fixpt_floor(dc_fixpt_sub(*init, ratio));
929
+
930
+ int_part = int_part > 0 ? int_part : 0;
931
+ *vp_size += int_part < *vp_offset ? int_part : *vp_offset;
932
+ *vp_offset -= int_part < *vp_offset ? int_part : *vp_offset;
933
+ }
934
+
935
+ /* Adjust for viewport end clip-off */
936
+ if ((*vp_offset + *vp_size) < src_size) {
937
+ int int_part;
938
+ int end_offset = src_size - *vp_offset - *vp_size;
939
+
940
+ /*
941
+ * this is init if vp had no offset, keep in mind this is from the
942
+ * right side of vp due to scan direction
943
+ */
944
+ *init = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_skip));
945
+ /*
946
+ * this is the difference between first pixel of viewport available to read
947
+ * and init position, takning into account scan direction
948
+ */
949
+ int_part = dc_fixpt_floor(*init) - end_offset;
950
+ if (int_part < taps) {
951
+ int int_adj = end_offset >= (taps - int_part) ?
952
+ (taps - int_part) : end_offset;
953
+ *vp_size += int_adj;
954
+ int_part += int_adj;
955
+ } else if (int_part > taps) {
956
+ *vp_size += int_part - taps;
957
+ int_part = taps;
958
+ }
959
+ init->value &= 0xffffffff;
960
+ *init = dc_fixpt_add_int(*init, int_part);
961
+ }
962
+ }
963
+}
964
+
965
+static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx)
966
+{
967
+ const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
968
+ const struct dc_stream_state *stream = pipe_ctx->stream;
969
+ struct pipe_ctx *odm_pipe = pipe_ctx;
704970 struct scaler_data *data = &pipe_ctx->plane_res.scl_data;
705971 struct rect src = pipe_ctx->plane_state->src_rect;
972
+ int recout_skip_h, recout_skip_v, surf_size_h, surf_size_v;
706973 int vpc_div = (data->format == PIXEL_FORMAT_420BPP8
707974 || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1;
708
- bool flip_vert_scan_dir = false, flip_horz_scan_dir = false;
975
+ bool orthogonal_rotation, flip_vert_scan_dir, flip_horz_scan_dir;
976
+ int odm_idx = 0;
709977
710978 /*
711979 * Need to calculate the scan direction for viewport to make adjustments
712980 */
713
- if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_180) {
714
- flip_vert_scan_dir = true;
715
- flip_horz_scan_dir = true;
716
- } else if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90)
717
- flip_vert_scan_dir = true;
718
- else if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270)
719
- flip_horz_scan_dir = true;
981
+ get_vp_scan_direction(
982
+ plane_state->rotation,
983
+ plane_state->horizontal_mirror,
984
+ &orthogonal_rotation,
985
+ &flip_vert_scan_dir,
986
+ &flip_horz_scan_dir);
720987
721
- if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 ||
722
- pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) {
723
- rect_swap_helper(&src);
724
- rect_swap_helper(&data->viewport_c);
725
- rect_swap_helper(&data->viewport);
726
- } else if (pipe_ctx->plane_state->horizontal_mirror)
727
- flip_horz_scan_dir = !flip_horz_scan_dir;
988
+ /* Calculate src rect rotation adjusted to recout space */
989
+ surf_size_h = src.x + src.width;
990
+ surf_size_v = src.y + src.height;
991
+ if (flip_horz_scan_dir)
992
+ src.x = 0;
993
+ if (flip_vert_scan_dir)
994
+ src.y = 0;
995
+ if (orthogonal_rotation) {
996
+ swap(src.x, src.y);
997
+ swap(src.width, src.height);
998
+ }
728999
1000
+ /*modified recout_skip_h calculation due to odm having no recout offset*/
1001
+ while (odm_pipe->prev_odm_pipe) {
1002
+ odm_idx++;
1003
+ odm_pipe = odm_pipe->prev_odm_pipe;
1004
+ }
1005
+ /*odm_pipe is the leftmost pipe in the ODM group*/
1006
+ recout_skip_h = odm_idx * data->recout.width;
1007
+
1008
+ /* Recout matching initial vp offset = recout_offset - (stream dst offset +
1009
+ * ((surf dst offset - stream src offset) * 1/ stream scaling ratio)
1010
+ * - (surf surf_src offset * 1/ full scl ratio))
1011
+ */
1012
+ recout_skip_h += odm_pipe->plane_res.scl_data.recout.x
1013
+ - (stream->dst.x + (plane_state->dst_rect.x - stream->src.x)
1014
+ * stream->dst.width / stream->src.width -
1015
+ src.x * plane_state->dst_rect.width / src.width
1016
+ * stream->dst.width / stream->src.width);
1017
+
1018
+
1019
+ recout_skip_v = data->recout.y - (stream->dst.y + (plane_state->dst_rect.y - stream->src.y)
1020
+ * stream->dst.height / stream->src.height -
1021
+ src.y * plane_state->dst_rect.height / src.height
1022
+ * stream->dst.height / stream->src.height);
1023
+ if (orthogonal_rotation)
1024
+ swap(recout_skip_h, recout_skip_v);
7291025 /*
7301026 * Init calculated according to formula:
7311027 * init = (scaling_ratio + number_of_taps + 1) / 2
....@@ -744,305 +1040,98 @@
7441040 data->inits.v_c = dc_fixpt_truncate(dc_fixpt_add(data->inits.v_c, dc_fixpt_div_int(
7451041 dc_fixpt_add_int(data->ratios.vert_c, data->taps.v_taps_c + 1), 2)), 19);
7461042
747
- if (!flip_horz_scan_dir) {
748
- /* Adjust for viewport end clip-off */
749
- if ((data->viewport.x + data->viewport.width) < (src.x + src.width)) {
750
- int vp_clip = src.x + src.width - data->viewport.width - data->viewport.x;
751
- int int_part = dc_fixpt_floor(
752
- dc_fixpt_sub(data->inits.h, data->ratios.horz));
753
-
754
- int_part = int_part > 0 ? int_part : 0;
755
- data->viewport.width += int_part < vp_clip ? int_part : vp_clip;
756
- }
757
- if ((data->viewport_c.x + data->viewport_c.width) < (src.x + src.width) / vpc_div) {
758
- int vp_clip = (src.x + src.width) / vpc_div -
759
- data->viewport_c.width - data->viewport_c.x;
760
- int int_part = dc_fixpt_floor(
761
- dc_fixpt_sub(data->inits.h_c, data->ratios.horz_c));
762
-
763
- int_part = int_part > 0 ? int_part : 0;
764
- data->viewport_c.width += int_part < vp_clip ? int_part : vp_clip;
765
- }
766
-
767
- /* Adjust for non-0 viewport offset */
768
- if (data->viewport.x) {
769
- int int_part;
770
-
771
- data->inits.h = dc_fixpt_add(data->inits.h, dc_fixpt_mul_int(
772
- data->ratios.horz, data->recout.x - recout_full->x));
773
- int_part = dc_fixpt_floor(data->inits.h) - data->viewport.x;
774
- if (int_part < data->taps.h_taps) {
775
- int int_adj = data->viewport.x >= (data->taps.h_taps - int_part) ?
776
- (data->taps.h_taps - int_part) : data->viewport.x;
777
- data->viewport.x -= int_adj;
778
- data->viewport.width += int_adj;
779
- int_part += int_adj;
780
- } else if (int_part > data->taps.h_taps) {
781
- data->viewport.x += int_part - data->taps.h_taps;
782
- data->viewport.width -= int_part - data->taps.h_taps;
783
- int_part = data->taps.h_taps;
784
- }
785
- data->inits.h.value &= 0xffffffff;
786
- data->inits.h = dc_fixpt_add_int(data->inits.h, int_part);
787
- }
788
-
789
- if (data->viewport_c.x) {
790
- int int_part;
791
-
792
- data->inits.h_c = dc_fixpt_add(data->inits.h_c, dc_fixpt_mul_int(
793
- data->ratios.horz_c, data->recout.x - recout_full->x));
794
- int_part = dc_fixpt_floor(data->inits.h_c) - data->viewport_c.x;
795
- if (int_part < data->taps.h_taps_c) {
796
- int int_adj = data->viewport_c.x >= (data->taps.h_taps_c - int_part) ?
797
- (data->taps.h_taps_c - int_part) : data->viewport_c.x;
798
- data->viewport_c.x -= int_adj;
799
- data->viewport_c.width += int_adj;
800
- int_part += int_adj;
801
- } else if (int_part > data->taps.h_taps_c) {
802
- data->viewport_c.x += int_part - data->taps.h_taps_c;
803
- data->viewport_c.width -= int_part - data->taps.h_taps_c;
804
- int_part = data->taps.h_taps_c;
805
- }
806
- data->inits.h_c.value &= 0xffffffff;
807
- data->inits.h_c = dc_fixpt_add_int(data->inits.h_c, int_part);
808
- }
809
- } else {
810
- /* Adjust for non-0 viewport offset */
811
- if (data->viewport.x) {
812
- int int_part = dc_fixpt_floor(
813
- dc_fixpt_sub(data->inits.h, data->ratios.horz));
814
-
815
- int_part = int_part > 0 ? int_part : 0;
816
- data->viewport.width += int_part < data->viewport.x ? int_part : data->viewport.x;
817
- data->viewport.x -= int_part < data->viewport.x ? int_part : data->viewport.x;
818
- }
819
- if (data->viewport_c.x) {
820
- int int_part = dc_fixpt_floor(
821
- dc_fixpt_sub(data->inits.h_c, data->ratios.horz_c));
822
-
823
- int_part = int_part > 0 ? int_part : 0;
824
- data->viewport_c.width += int_part < data->viewport_c.x ? int_part : data->viewport_c.x;
825
- data->viewport_c.x -= int_part < data->viewport_c.x ? int_part : data->viewport_c.x;
826
- }
827
-
828
- /* Adjust for viewport end clip-off */
829
- if ((data->viewport.x + data->viewport.width) < (src.x + src.width)) {
830
- int int_part;
831
- int end_offset = src.x + src.width
832
- - data->viewport.x - data->viewport.width;
833
-
834
- /*
835
- * this is init if vp had no offset, keep in mind this is from the
836
- * right side of vp due to scan direction
837
- */
838
- data->inits.h = dc_fixpt_add(data->inits.h, dc_fixpt_mul_int(
839
- data->ratios.horz, data->recout.x - recout_full->x));
840
- /*
841
- * this is the difference between first pixel of viewport available to read
842
- * and init position, takning into account scan direction
843
- */
844
- int_part = dc_fixpt_floor(data->inits.h) - end_offset;
845
- if (int_part < data->taps.h_taps) {
846
- int int_adj = end_offset >= (data->taps.h_taps - int_part) ?
847
- (data->taps.h_taps - int_part) : end_offset;
848
- data->viewport.width += int_adj;
849
- int_part += int_adj;
850
- } else if (int_part > data->taps.h_taps) {
851
- data->viewport.width += int_part - data->taps.h_taps;
852
- int_part = data->taps.h_taps;
853
- }
854
- data->inits.h.value &= 0xffffffff;
855
- data->inits.h = dc_fixpt_add_int(data->inits.h, int_part);
856
- }
857
-
858
- if ((data->viewport_c.x + data->viewport_c.width) < (src.x + src.width) / vpc_div) {
859
- int int_part;
860
- int end_offset = (src.x + src.width) / vpc_div
861
- - data->viewport_c.x - data->viewport_c.width;
862
-
863
- /*
864
- * this is init if vp had no offset, keep in mind this is from the
865
- * right side of vp due to scan direction
866
- */
867
- data->inits.h_c = dc_fixpt_add(data->inits.h_c, dc_fixpt_mul_int(
868
- data->ratios.horz_c, data->recout.x - recout_full->x));
869
- /*
870
- * this is the difference between first pixel of viewport available to read
871
- * and init position, takning into account scan direction
872
- */
873
- int_part = dc_fixpt_floor(data->inits.h_c) - end_offset;
874
- if (int_part < data->taps.h_taps_c) {
875
- int int_adj = end_offset >= (data->taps.h_taps_c - int_part) ?
876
- (data->taps.h_taps_c - int_part) : end_offset;
877
- data->viewport_c.width += int_adj;
878
- int_part += int_adj;
879
- } else if (int_part > data->taps.h_taps_c) {
880
- data->viewport_c.width += int_part - data->taps.h_taps_c;
881
- int_part = data->taps.h_taps_c;
882
- }
883
- data->inits.h_c.value &= 0xffffffff;
884
- data->inits.h_c = dc_fixpt_add_int(data->inits.h_c, int_part);
885
- }
886
-
887
- }
888
- if (!flip_vert_scan_dir) {
889
- /* Adjust for viewport end clip-off */
890
- if ((data->viewport.y + data->viewport.height) < (src.y + src.height)) {
891
- int vp_clip = src.y + src.height - data->viewport.height - data->viewport.y;
892
- int int_part = dc_fixpt_floor(
893
- dc_fixpt_sub(data->inits.v, data->ratios.vert));
894
-
895
- int_part = int_part > 0 ? int_part : 0;
896
- data->viewport.height += int_part < vp_clip ? int_part : vp_clip;
897
- }
898
- if ((data->viewport_c.y + data->viewport_c.height) < (src.y + src.height) / vpc_div) {
899
- int vp_clip = (src.y + src.height) / vpc_div -
900
- data->viewport_c.height - data->viewport_c.y;
901
- int int_part = dc_fixpt_floor(
902
- dc_fixpt_sub(data->inits.v_c, data->ratios.vert_c));
903
-
904
- int_part = int_part > 0 ? int_part : 0;
905
- data->viewport_c.height += int_part < vp_clip ? int_part : vp_clip;
906
- }
907
-
908
- /* Adjust for non-0 viewport offset */
909
- if (data->viewport.y) {
910
- int int_part;
911
-
912
- data->inits.v = dc_fixpt_add(data->inits.v, dc_fixpt_mul_int(
913
- data->ratios.vert, data->recout.y - recout_full->y));
914
- int_part = dc_fixpt_floor(data->inits.v) - data->viewport.y;
915
- if (int_part < data->taps.v_taps) {
916
- int int_adj = data->viewport.y >= (data->taps.v_taps - int_part) ?
917
- (data->taps.v_taps - int_part) : data->viewport.y;
918
- data->viewport.y -= int_adj;
919
- data->viewport.height += int_adj;
920
- int_part += int_adj;
921
- } else if (int_part > data->taps.v_taps) {
922
- data->viewport.y += int_part - data->taps.v_taps;
923
- data->viewport.height -= int_part - data->taps.v_taps;
924
- int_part = data->taps.v_taps;
925
- }
926
- data->inits.v.value &= 0xffffffff;
927
- data->inits.v = dc_fixpt_add_int(data->inits.v, int_part);
928
- }
929
-
930
- if (data->viewport_c.y) {
931
- int int_part;
932
-
933
- data->inits.v_c = dc_fixpt_add(data->inits.v_c, dc_fixpt_mul_int(
934
- data->ratios.vert_c, data->recout.y - recout_full->y));
935
- int_part = dc_fixpt_floor(data->inits.v_c) - data->viewport_c.y;
936
- if (int_part < data->taps.v_taps_c) {
937
- int int_adj = data->viewport_c.y >= (data->taps.v_taps_c - int_part) ?
938
- (data->taps.v_taps_c - int_part) : data->viewport_c.y;
939
- data->viewport_c.y -= int_adj;
940
- data->viewport_c.height += int_adj;
941
- int_part += int_adj;
942
- } else if (int_part > data->taps.v_taps_c) {
943
- data->viewport_c.y += int_part - data->taps.v_taps_c;
944
- data->viewport_c.height -= int_part - data->taps.v_taps_c;
945
- int_part = data->taps.v_taps_c;
946
- }
947
- data->inits.v_c.value &= 0xffffffff;
948
- data->inits.v_c = dc_fixpt_add_int(data->inits.v_c, int_part);
949
- }
950
- } else {
951
- /* Adjust for non-0 viewport offset */
952
- if (data->viewport.y) {
953
- int int_part = dc_fixpt_floor(
954
- dc_fixpt_sub(data->inits.v, data->ratios.vert));
955
-
956
- int_part = int_part > 0 ? int_part : 0;
957
- data->viewport.height += int_part < data->viewport.y ? int_part : data->viewport.y;
958
- data->viewport.y -= int_part < data->viewport.y ? int_part : data->viewport.y;
959
- }
960
- if (data->viewport_c.y) {
961
- int int_part = dc_fixpt_floor(
962
- dc_fixpt_sub(data->inits.v_c, data->ratios.vert_c));
963
-
964
- int_part = int_part > 0 ? int_part : 0;
965
- data->viewport_c.height += int_part < data->viewport_c.y ? int_part : data->viewport_c.y;
966
- data->viewport_c.y -= int_part < data->viewport_c.y ? int_part : data->viewport_c.y;
967
- }
968
-
969
- /* Adjust for viewport end clip-off */
970
- if ((data->viewport.y + data->viewport.height) < (src.y + src.height)) {
971
- int int_part;
972
- int end_offset = src.y + src.height
973
- - data->viewport.y - data->viewport.height;
974
-
975
- /*
976
- * this is init if vp had no offset, keep in mind this is from the
977
- * right side of vp due to scan direction
978
- */
979
- data->inits.v = dc_fixpt_add(data->inits.v, dc_fixpt_mul_int(
980
- data->ratios.vert, data->recout.y - recout_full->y));
981
- /*
982
- * this is the difference between first pixel of viewport available to read
983
- * and init position, taking into account scan direction
984
- */
985
- int_part = dc_fixpt_floor(data->inits.v) - end_offset;
986
- if (int_part < data->taps.v_taps) {
987
- int int_adj = end_offset >= (data->taps.v_taps - int_part) ?
988
- (data->taps.v_taps - int_part) : end_offset;
989
- data->viewport.height += int_adj;
990
- int_part += int_adj;
991
- } else if (int_part > data->taps.v_taps) {
992
- data->viewport.height += int_part - data->taps.v_taps;
993
- int_part = data->taps.v_taps;
994
- }
995
- data->inits.v.value &= 0xffffffff;
996
- data->inits.v = dc_fixpt_add_int(data->inits.v, int_part);
997
- }
998
-
999
- if ((data->viewport_c.y + data->viewport_c.height) < (src.y + src.height) / vpc_div) {
1000
- int int_part;
1001
- int end_offset = (src.y + src.height) / vpc_div
1002
- - data->viewport_c.y - data->viewport_c.height;
1003
-
1004
- /*
1005
- * this is init if vp had no offset, keep in mind this is from the
1006
- * right side of vp due to scan direction
1007
- */
1008
- data->inits.v_c = dc_fixpt_add(data->inits.v_c, dc_fixpt_mul_int(
1009
- data->ratios.vert_c, data->recout.y - recout_full->y));
1010
- /*
1011
- * this is the difference between first pixel of viewport available to read
1012
- * and init position, taking into account scan direction
1013
- */
1014
- int_part = dc_fixpt_floor(data->inits.v_c) - end_offset;
1015
- if (int_part < data->taps.v_taps_c) {
1016
- int int_adj = end_offset >= (data->taps.v_taps_c - int_part) ?
1017
- (data->taps.v_taps_c - int_part) : end_offset;
1018
- data->viewport_c.height += int_adj;
1019
- int_part += int_adj;
1020
- } else if (int_part > data->taps.v_taps_c) {
1021
- data->viewport_c.height += int_part - data->taps.v_taps_c;
1022
- int_part = data->taps.v_taps_c;
1023
- }
1024
- data->inits.v_c.value &= 0xffffffff;
1025
- data->inits.v_c = dc_fixpt_add_int(data->inits.v_c, int_part);
1026
- }
1027
- }
1043
+ /*
1044
+ * Taps, inits and scaling ratios are in recout space need to rotate
1045
+ * to viewport rotation before adjustment
1046
+ */
1047
+ adjust_vp_and_init_for_seamless_clip(
1048
+ flip_horz_scan_dir,
1049
+ recout_skip_h,
1050
+ surf_size_h,
1051
+ orthogonal_rotation ? data->taps.v_taps : data->taps.h_taps,
1052
+ orthogonal_rotation ? data->ratios.vert : data->ratios.horz,
1053
+ orthogonal_rotation ? &data->inits.v : &data->inits.h,
1054
+ &data->viewport.x,
1055
+ &data->viewport.width);
1056
+ adjust_vp_and_init_for_seamless_clip(
1057
+ flip_horz_scan_dir,
1058
+ recout_skip_h,
1059
+ surf_size_h / vpc_div,
1060
+ orthogonal_rotation ? data->taps.v_taps_c : data->taps.h_taps_c,
1061
+ orthogonal_rotation ? data->ratios.vert_c : data->ratios.horz_c,
1062
+ orthogonal_rotation ? &data->inits.v_c : &data->inits.h_c,
1063
+ &data->viewport_c.x,
1064
+ &data->viewport_c.width);
1065
+ adjust_vp_and_init_for_seamless_clip(
1066
+ flip_vert_scan_dir,
1067
+ recout_skip_v,
1068
+ surf_size_v,
1069
+ orthogonal_rotation ? data->taps.h_taps : data->taps.v_taps,
1070
+ orthogonal_rotation ? data->ratios.horz : data->ratios.vert,
1071
+ orthogonal_rotation ? &data->inits.h : &data->inits.v,
1072
+ &data->viewport.y,
1073
+ &data->viewport.height);
1074
+ adjust_vp_and_init_for_seamless_clip(
1075
+ flip_vert_scan_dir,
1076
+ recout_skip_v,
1077
+ surf_size_v / vpc_div,
1078
+ orthogonal_rotation ? data->taps.h_taps_c : data->taps.v_taps_c,
1079
+ orthogonal_rotation ? data->ratios.horz_c : data->ratios.vert_c,
1080
+ orthogonal_rotation ? &data->inits.h_c : &data->inits.v_c,
1081
+ &data->viewport_c.y,
1082
+ &data->viewport_c.height);
10281083
10291084 /* Interlaced inits based on final vert inits */
10301085 data->inits.v_bot = dc_fixpt_add(data->inits.v, data->ratios.vert);
10311086 data->inits.v_c_bot = dc_fixpt_add(data->inits.v_c, data->ratios.vert_c);
10321087
1033
- if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 ||
1034
- pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) {
1035
- rect_swap_helper(&data->viewport_c);
1036
- rect_swap_helper(&data->viewport);
1088
+}
1089
+
1090
+/*
1091
+ * When handling 270 rotation in mixed SLS mode, we have
1092
+ * stream->timing.h_border_left that is non zero. If we are doing
1093
+ * pipe-splitting, this h_border_left value gets added to recout.x and when it
1094
+ * calls calculate_inits_and_adj_vp() and
1095
+ * adjust_vp_and_init_for_seamless_clip(), it can cause viewport.height for a
1096
+ * pipe to be incorrect.
1097
+ *
1098
+ * To fix this, instead of using stream->timing.h_border_left, we can use
1099
+ * stream->dst.x to represent the border instead. So we will set h_border_left
1100
+ * to 0 and shift the appropriate amount in stream->dst.x. We will then
1101
+ * perform all calculations in resource_build_scaling_params() based on this
1102
+ * and then restore the h_border_left and stream->dst.x to their original
1103
+ * values.
1104
+ *
1105
+ * shift_border_left_to_dst() will shift the amount of h_border_left to
1106
+ * stream->dst.x and set h_border_left to 0. restore_border_left_from_dst()
1107
+ * will restore h_border_left and stream->dst.x back to their original values
1108
+ * We also need to make sure pipe_ctx->plane_res.scl_data.h_active uses the
1109
+ * original h_border_left value in its calculation.
1110
+ */
1111
+int shift_border_left_to_dst(struct pipe_ctx *pipe_ctx)
1112
+{
1113
+ int store_h_border_left = pipe_ctx->stream->timing.h_border_left;
1114
+
1115
+ if (store_h_border_left) {
1116
+ pipe_ctx->stream->timing.h_border_left = 0;
1117
+ pipe_ctx->stream->dst.x += store_h_border_left;
10371118 }
1119
+ return store_h_border_left;
1120
+}
1121
+
1122
+void restore_border_left_from_dst(struct pipe_ctx *pipe_ctx,
1123
+ int store_h_border_left)
1124
+{
1125
+ pipe_ctx->stream->dst.x -= store_h_border_left;
1126
+ pipe_ctx->stream->timing.h_border_left = store_h_border_left;
10381127 }
10391128
10401129 bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
10411130 {
10421131 const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
10431132 struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
1044
- struct rect recout_full = { 0 };
10451133 bool res = false;
1134
+ int store_h_border_left = shift_border_left_to_dst(pipe_ctx);
10461135 DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
10471136 /* Important: scaling ratio calculation requires pixel format,
10481137 * lb depth calculation requires recout and taps require scaling ratios.
....@@ -1051,32 +1140,37 @@
10511140 pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface(
10521141 pipe_ctx->plane_state->format);
10531142
1054
- if (pipe_ctx->stream->timing.flags.INTERLACE)
1055
- pipe_ctx->stream->dst.height *= 2;
1056
-
10571143 calculate_scaling_ratios(pipe_ctx);
10581144
10591145 calculate_viewport(pipe_ctx);
10601146
1061
- if (pipe_ctx->plane_res.scl_data.viewport.height < 16 || pipe_ctx->plane_res.scl_data.viewport.width < 16)
1147
+ if (pipe_ctx->plane_res.scl_data.viewport.height < 12 ||
1148
+ pipe_ctx->plane_res.scl_data.viewport.width < 12) {
1149
+ if (store_h_border_left) {
1150
+ restore_border_left_from_dst(pipe_ctx,
1151
+ store_h_border_left);
1152
+ }
10621153 return false;
1154
+ }
10631155
1064
- calculate_recout(pipe_ctx, &recout_full);
1156
+ calculate_recout(pipe_ctx);
10651157
10661158 /**
10671159 * Setting line buffer pixel depth to 24bpp yields banding
10681160 * on certain displays, such as the Sharp 4k
10691161 */
10701162 pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP;
1163
+ pipe_ctx->plane_res.scl_data.lb_params.alpha_en = plane_state->per_pixel_alpha;
10711164
10721165 pipe_ctx->plane_res.scl_data.recout.x += timing->h_border_left;
10731166 pipe_ctx->plane_res.scl_data.recout.y += timing->v_border_top;
10741167
1075
- pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable + timing->h_border_left + timing->h_border_right;
1076
- pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable + timing->v_border_top + timing->v_border_bottom;
1077
- if (pipe_ctx->stream->timing.flags.INTERLACE)
1078
- pipe_ctx->plane_res.scl_data.v_active *= 2;
1079
-
1168
+ pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable +
1169
+ store_h_border_left + timing->h_border_right;
1170
+ pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable +
1171
+ timing->v_border_top + timing->v_border_bottom;
1172
+ if (pipe_ctx->next_odm_pipe || pipe_ctx->prev_odm_pipe)
1173
+ pipe_ctx->plane_res.scl_data.h_active /= get_num_odm_splits(pipe_ctx) + 1;
10801174
10811175 /* Taps calculations */
10821176 if (pipe_ctx->plane_res.xfm != NULL)
....@@ -1086,6 +1180,8 @@
10861180 if (pipe_ctx->plane_res.dpp != NULL)
10871181 res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps(
10881182 pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality);
1183
+
1184
+
10891185 if (!res) {
10901186 /* Try 24 bpp linebuffer */
10911187 pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP;
....@@ -1105,24 +1201,37 @@
11051201
11061202 if (res)
11071203 /* May need to re-check lb size after this in some obscure scenario */
1108
- calculate_inits_and_adj_vp(pipe_ctx, &recout_full);
1204
+ calculate_inits_and_adj_vp(pipe_ctx);
11091205
1110
- DC_LOG_SCALER(
1111
- "%s: Viewport:\nheight:%d width:%d x:%d "
1112
- "y:%d\n dst_rect:\nheight:%d width:%d x:%d "
1113
- "y:%d\n",
1114
- __func__,
1115
- pipe_ctx->plane_res.scl_data.viewport.height,
1116
- pipe_ctx->plane_res.scl_data.viewport.width,
1117
- pipe_ctx->plane_res.scl_data.viewport.x,
1118
- pipe_ctx->plane_res.scl_data.viewport.y,
1119
- plane_state->dst_rect.height,
1120
- plane_state->dst_rect.width,
1121
- plane_state->dst_rect.x,
1122
- plane_state->dst_rect.y);
1206
+ DC_LOG_SCALER("%s pipe %d:\nViewport: height:%d width:%d x:%d y:%d Recout: height:%d width:%d x:%d y:%d HACTIVE:%d VACTIVE:%d\n"
1207
+ "src_rect: height:%d width:%d x:%d y:%d dst_rect: height:%d width:%d x:%d y:%d clip_rect: height:%d width:%d x:%d y:%d\n",
1208
+ __func__,
1209
+ pipe_ctx->pipe_idx,
1210
+ pipe_ctx->plane_res.scl_data.viewport.height,
1211
+ pipe_ctx->plane_res.scl_data.viewport.width,
1212
+ pipe_ctx->plane_res.scl_data.viewport.x,
1213
+ pipe_ctx->plane_res.scl_data.viewport.y,
1214
+ pipe_ctx->plane_res.scl_data.recout.height,
1215
+ pipe_ctx->plane_res.scl_data.recout.width,
1216
+ pipe_ctx->plane_res.scl_data.recout.x,
1217
+ pipe_ctx->plane_res.scl_data.recout.y,
1218
+ pipe_ctx->plane_res.scl_data.h_active,
1219
+ pipe_ctx->plane_res.scl_data.v_active,
1220
+ plane_state->src_rect.height,
1221
+ plane_state->src_rect.width,
1222
+ plane_state->src_rect.x,
1223
+ plane_state->src_rect.y,
1224
+ plane_state->dst_rect.height,
1225
+ plane_state->dst_rect.width,
1226
+ plane_state->dst_rect.x,
1227
+ plane_state->dst_rect.y,
1228
+ plane_state->clip_rect.height,
1229
+ plane_state->clip_rect.width,
1230
+ plane_state->clip_rect.x,
1231
+ plane_state->clip_rect.y);
11231232
1124
- if (pipe_ctx->stream->timing.flags.INTERLACE)
1125
- pipe_ctx->stream->dst.height /= 2;
1233
+ if (store_h_border_left)
1234
+ restore_border_left_from_dst(pipe_ctx, store_h_border_left);
11261235
11271236 return res;
11281237 }
....@@ -1146,24 +1255,60 @@
11461255
11471256 struct pipe_ctx *find_idle_secondary_pipe(
11481257 struct resource_context *res_ctx,
1149
- const struct resource_pool *pool)
1258
+ const struct resource_pool *pool,
1259
+ const struct pipe_ctx *primary_pipe)
11501260 {
11511261 int i;
11521262 struct pipe_ctx *secondary_pipe = NULL;
11531263
11541264 /*
1155
- * search backwards for the second pipe to keep pipe
1156
- * assignment more consistent
1265
+ * We add a preferred pipe mapping to avoid the chance that
1266
+ * MPCCs already in use will need to be reassigned to other trees.
1267
+ * For example, if we went with the strict, assign backwards logic:
1268
+ *
1269
+ * (State 1)
1270
+ * Display A on, no surface, top pipe = 0
1271
+ * Display B on, no surface, top pipe = 1
1272
+ *
1273
+ * (State 2)
1274
+ * Display A on, no surface, top pipe = 0
1275
+ * Display B on, surface enable, top pipe = 1, bottom pipe = 5
1276
+ *
1277
+ * (State 3)
1278
+ * Display A on, surface enable, top pipe = 0, bottom pipe = 5
1279
+ * Display B on, surface enable, top pipe = 1, bottom pipe = 4
1280
+ *
1281
+ * The state 2->3 transition requires remapping MPCC 5 from display B
1282
+ * to display A.
1283
+ *
1284
+ * However, with the preferred pipe logic, state 2 would look like:
1285
+ *
1286
+ * (State 2)
1287
+ * Display A on, no surface, top pipe = 0
1288
+ * Display B on, surface enable, top pipe = 1, bottom pipe = 4
1289
+ *
1290
+ * This would then cause 2->3 to not require remapping any MPCCs.
11571291 */
1158
-
1159
- for (i = pool->pipe_count - 1; i >= 0; i--) {
1160
- if (res_ctx->pipe_ctx[i].stream == NULL) {
1161
- secondary_pipe = &res_ctx->pipe_ctx[i];
1162
- secondary_pipe->pipe_idx = i;
1163
- break;
1292
+ if (primary_pipe) {
1293
+ int preferred_pipe_idx = (pool->pipe_count - 1) - primary_pipe->pipe_idx;
1294
+ if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
1295
+ secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
1296
+ secondary_pipe->pipe_idx = preferred_pipe_idx;
11641297 }
11651298 }
11661299
1300
+ /*
1301
+ * search backwards for the second pipe to keep pipe
1302
+ * assignment more consistent
1303
+ */
1304
+ if (!secondary_pipe)
1305
+ for (i = pool->pipe_count - 1; i >= 0; i--) {
1306
+ if (res_ctx->pipe_ctx[i].stream == NULL) {
1307
+ secondary_pipe = &res_ctx->pipe_ctx[i];
1308
+ secondary_pipe->pipe_idx = i;
1309
+ break;
1310
+ }
1311
+ }
11671312
11681313 return secondary_pipe;
11691314 }
....@@ -1173,25 +1318,21 @@
11731318 struct dc_stream_state *stream)
11741319 {
11751320 int i;
1321
+
11761322 for (i = 0; i < MAX_PIPES; i++) {
1177
- if (res_ctx->pipe_ctx[i].stream == stream &&
1178
- !res_ctx->pipe_ctx[i].top_pipe) {
1323
+ if (res_ctx->pipe_ctx[i].stream == stream
1324
+ && !res_ctx->pipe_ctx[i].top_pipe
1325
+ && !res_ctx->pipe_ctx[i].prev_odm_pipe)
11791326 return &res_ctx->pipe_ctx[i];
1180
- break;
1181
- }
11821327 }
11831328 return NULL;
11841329 }
11851330
1186
-static struct pipe_ctx *resource_get_tail_pipe_for_stream(
1331
+static struct pipe_ctx *resource_get_tail_pipe(
11871332 struct resource_context *res_ctx,
1188
- struct dc_stream_state *stream)
1333
+ struct pipe_ctx *head_pipe)
11891334 {
1190
- struct pipe_ctx *head_pipe, *tail_pipe;
1191
- head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream);
1192
-
1193
- if (!head_pipe)
1194
- return NULL;
1335
+ struct pipe_ctx *tail_pipe;
11951336
11961337 tail_pipe = head_pipe->bottom_pipe;
11971338
....@@ -1207,31 +1348,20 @@
12071348 * A free_pipe for a stream is defined here as a pipe
12081349 * that has no surface attached yet
12091350 */
1210
-static struct pipe_ctx *acquire_free_pipe_for_stream(
1351
+static struct pipe_ctx *acquire_free_pipe_for_head(
12111352 struct dc_state *context,
12121353 const struct resource_pool *pool,
1213
- struct dc_stream_state *stream)
1354
+ struct pipe_ctx *head_pipe)
12141355 {
12151356 int i;
12161357 struct resource_context *res_ctx = &context->res_ctx;
1217
-
1218
- struct pipe_ctx *head_pipe = NULL;
1219
-
1220
- /* Find head pipe, which has the back end set up*/
1221
-
1222
- head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream);
1223
-
1224
- if (!head_pipe) {
1225
- ASSERT(0);
1226
- return NULL;
1227
- }
12281358
12291359 if (!head_pipe->plane_state)
12301360 return head_pipe;
12311361
12321362 /* Re-use pipe already acquired for this stream if available*/
12331363 for (i = pool->pipe_count - 1; i >= 0; i--) {
1234
- if (res_ctx->pipe_ctx[i].stream == stream &&
1364
+ if (res_ctx->pipe_ctx[i].stream == head_pipe->stream &&
12351365 !res_ctx->pipe_ctx[i].plane_state) {
12361366 return &res_ctx->pipe_ctx[i];
12371367 }
....@@ -1245,11 +1375,10 @@
12451375 if (!pool->funcs->acquire_idle_pipe_for_layer)
12461376 return NULL;
12471377
1248
- return pool->funcs->acquire_idle_pipe_for_layer(context, pool, stream);
1249
-
1378
+ return pool->funcs->acquire_idle_pipe_for_layer(context, pool, head_pipe->stream);
12501379 }
12511380
1252
-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
1381
+#if defined(CONFIG_DRM_AMD_DC_DCN)
12531382 static int acquire_first_split_pipe(
12541383 struct resource_context *res_ctx,
12551384 const struct resource_pool *pool,
....@@ -1258,24 +1387,27 @@
12581387 int i;
12591388
12601389 for (i = 0; i < pool->pipe_count; i++) {
1261
- struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
1390
+ struct pipe_ctx *split_pipe = &res_ctx->pipe_ctx[i];
12621391
1263
- if (pipe_ctx->top_pipe &&
1264
- pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state) {
1265
- pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe;
1266
- if (pipe_ctx->bottom_pipe)
1267
- pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe;
1392
+ if (split_pipe->top_pipe &&
1393
+ split_pipe->top_pipe->plane_state == split_pipe->plane_state) {
1394
+ split_pipe->top_pipe->bottom_pipe = split_pipe->bottom_pipe;
1395
+ if (split_pipe->bottom_pipe)
1396
+ split_pipe->bottom_pipe->top_pipe = split_pipe->top_pipe;
12681397
1269
- memset(pipe_ctx, 0, sizeof(*pipe_ctx));
1270
- pipe_ctx->stream_res.tg = pool->timing_generators[i];
1271
- pipe_ctx->plane_res.hubp = pool->hubps[i];
1272
- pipe_ctx->plane_res.ipp = pool->ipps[i];
1273
- pipe_ctx->plane_res.dpp = pool->dpps[i];
1274
- pipe_ctx->stream_res.opp = pool->opps[i];
1275
- pipe_ctx->plane_res.mpcc_inst = pool->dpps[i]->inst;
1276
- pipe_ctx->pipe_idx = i;
1398
+ if (split_pipe->top_pipe->plane_state)
1399
+ resource_build_scaling_params(split_pipe->top_pipe);
12771400
1278
- pipe_ctx->stream = stream;
1401
+ memset(split_pipe, 0, sizeof(*split_pipe));
1402
+ split_pipe->stream_res.tg = pool->timing_generators[i];
1403
+ split_pipe->plane_res.hubp = pool->hubps[i];
1404
+ split_pipe->plane_res.ipp = pool->ipps[i];
1405
+ split_pipe->plane_res.dpp = pool->dpps[i];
1406
+ split_pipe->stream_res.opp = pool->opps[i];
1407
+ split_pipe->plane_res.mpcc_inst = pool->dpps[i]->inst;
1408
+ split_pipe->pipe_idx = i;
1409
+
1410
+ split_pipe->stream = stream;
12791411 return i;
12801412 }
12811413 }
....@@ -1318,37 +1450,40 @@
13181450 return false;
13191451 }
13201452
1321
- free_pipe = acquire_free_pipe_for_stream(context, pool, stream);
1322
-
1323
-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
1324
- if (!free_pipe) {
1325
- int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream);
1326
- if (pipe_idx >= 0)
1327
- free_pipe = &context->res_ctx.pipe_ctx[pipe_idx];
1328
- }
1329
-#endif
1330
- if (!free_pipe)
1331
- return false;
1332
-
1333
- /* retain new surfaces */
1453
+ /* retain new surface, but only once per stream */
13341454 dc_plane_state_retain(plane_state);
1335
- free_pipe->plane_state = plane_state;
13361455
1337
- if (head_pipe != free_pipe) {
1456
+ while (head_pipe) {
1457
+ free_pipe = acquire_free_pipe_for_head(context, pool, head_pipe);
13381458
1339
- tail_pipe = resource_get_tail_pipe_for_stream(&context->res_ctx, stream);
1340
- ASSERT(tail_pipe);
1459
+ #if defined(CONFIG_DRM_AMD_DC_DCN)
1460
+ if (!free_pipe) {
1461
+ int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream);
1462
+ if (pipe_idx >= 0)
1463
+ free_pipe = &context->res_ctx.pipe_ctx[pipe_idx];
1464
+ }
1465
+ #endif
1466
+ if (!free_pipe) {
1467
+ dc_plane_state_release(plane_state);
1468
+ return false;
1469
+ }
13411470
1342
- free_pipe->stream_res.tg = tail_pipe->stream_res.tg;
1343
- free_pipe->stream_res.abm = tail_pipe->stream_res.abm;
1344
- free_pipe->stream_res.opp = tail_pipe->stream_res.opp;
1345
- free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc;
1346
- free_pipe->stream_res.audio = tail_pipe->stream_res.audio;
1347
- free_pipe->clock_source = tail_pipe->clock_source;
1348
- free_pipe->top_pipe = tail_pipe;
1349
- tail_pipe->bottom_pipe = free_pipe;
1471
+ free_pipe->plane_state = plane_state;
1472
+
1473
+ if (head_pipe != free_pipe) {
1474
+ tail_pipe = resource_get_tail_pipe(&context->res_ctx, head_pipe);
1475
+ ASSERT(tail_pipe);
1476
+ free_pipe->stream_res.tg = tail_pipe->stream_res.tg;
1477
+ free_pipe->stream_res.abm = tail_pipe->stream_res.abm;
1478
+ free_pipe->stream_res.opp = tail_pipe->stream_res.opp;
1479
+ free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc;
1480
+ free_pipe->stream_res.audio = tail_pipe->stream_res.audio;
1481
+ free_pipe->clock_source = tail_pipe->clock_source;
1482
+ free_pipe->top_pipe = tail_pipe;
1483
+ tail_pipe->bottom_pipe = free_pipe;
1484
+ }
1485
+ head_pipe = head_pipe->next_odm_pipe;
13501486 }
1351
-
13521487 /* assign new surfaces*/
13531488 stream_status->plane_states[stream_status->plane_count] = plane_state;
13541489
....@@ -1367,6 +1502,9 @@
13671502 struct dc_stream_status *stream_status = NULL;
13681503 struct resource_pool *pool = dc->res_pool;
13691504
1505
+ if (!plane_state)
1506
+ return true;
1507
+
13701508 for (i = 0; i < context->stream_count; i++)
13711509 if (context->streams[i] == stream) {
13721510 stream_status = &context->stream_status[i];
....@@ -1380,11 +1518,9 @@
13801518
13811519 /* release pipe for plane*/
13821520 for (i = pool->pipe_count - 1; i >= 0; i--) {
1383
- struct pipe_ctx *pipe_ctx;
1521
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
13841522
1385
- if (context->res_ctx.pipe_ctx[i].plane_state == plane_state) {
1386
- pipe_ctx = &context->res_ctx.pipe_ctx[i];
1387
-
1523
+ if (pipe_ctx->plane_state == plane_state) {
13881524 if (pipe_ctx->top_pipe)
13891525 pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe;
13901526
....@@ -1399,14 +1535,10 @@
13991535 * For head pipe detach surfaces from pipe for tail
14001536 * pipe just zero it out
14011537 */
1402
- if (!pipe_ctx->top_pipe || (!pipe_ctx->top_pipe->top_pipe &&
1403
- pipe_ctx->top_pipe->stream_res.opp != pipe_ctx->stream_res.opp)) {
1404
- pipe_ctx->top_pipe = NULL;
1538
+ if (!pipe_ctx->top_pipe)
14051539 pipe_ctx->plane_state = NULL;
1406
- pipe_ctx->bottom_pipe = NULL;
1407
- } else {
1540
+ else
14081541 memset(pipe_ctx, 0, sizeof(*pipe_ctx));
1409
- }
14101542 }
14111543 }
14121544
....@@ -1511,21 +1643,6 @@
15111643 return add_all_planes_for_stream(dc, stream, &set, 1, context);
15121644 }
15131645
1514
-
1515
-static bool is_hdr_static_meta_changed(struct dc_stream_state *cur_stream,
1516
- struct dc_stream_state *new_stream)
1517
-{
1518
- if (cur_stream == NULL)
1519
- return true;
1520
-
1521
- if (memcmp(&cur_stream->hdr_static_metadata,
1522
- &new_stream->hdr_static_metadata,
1523
- sizeof(struct dc_info_packet)) != 0)
1524
- return true;
1525
-
1526
- return false;
1527
-}
1528
-
15291646 static bool is_timing_changed(struct dc_stream_state *cur_stream,
15301647 struct dc_stream_state *new_stream)
15311648 {
....@@ -1560,12 +1677,23 @@
15601677 if (is_timing_changed(stream_a, stream_b))
15611678 return false;
15621679
1563
- if (is_hdr_static_meta_changed(stream_a, stream_b))
1680
+ if (stream_a->signal != stream_b->signal)
1681
+ return false;
1682
+
1683
+ if (stream_a->dpms_off != stream_b->dpms_off)
15641684 return false;
15651685
15661686 return true;
15671687 }
15681688
1689
+/**
1690
+ * dc_is_stream_unchanged() - Compare two stream states for equivalence.
1691
+ *
1692
+ * Checks if there a difference between the two states
1693
+ * that would require a mode change.
1694
+ *
1695
+ * Does not compare cursor position or attributes.
1696
+ */
15691697 bool dc_is_stream_unchanged(
15701698 struct dc_stream_state *old_stream, struct dc_stream_state *stream)
15711699 {
....@@ -1573,9 +1701,19 @@
15731701 if (!are_stream_backends_same(old_stream, stream))
15741702 return false;
15751703
1704
+ if (old_stream->ignore_msa_timing_param != stream->ignore_msa_timing_param)
1705
+ return false;
1706
+
1707
+ /*compare audio info*/
1708
+ if (memcmp(&old_stream->audio_info, &stream->audio_info, sizeof(stream->audio_info)) != 0)
1709
+ return false;
1710
+
15761711 return true;
15771712 }
15781713
1714
+/**
1715
+ * dc_is_stream_scaling_unchanged() - Compare scaling rectangles of two streams.
1716
+ */
15791717 bool dc_is_stream_scaling_unchanged(
15801718 struct dc_stream_state *old_stream, struct dc_stream_state *stream)
15811719 {
....@@ -1656,50 +1794,11 @@
16561794 return -1;
16571795 }
16581796
1659
-static struct stream_encoder *find_first_free_match_stream_enc_for_link(
1660
- struct resource_context *res_ctx,
1661
- const struct resource_pool *pool,
1662
- struct dc_stream_state *stream)
1663
-{
1664
- int i;
1665
- int j = -1;
1666
- struct dc_link *link = stream->sink->link;
1667
-
1668
- for (i = 0; i < pool->stream_enc_count; i++) {
1669
- if (!res_ctx->is_stream_enc_acquired[i] &&
1670
- pool->stream_enc[i]) {
1671
- /* Store first available for MST second display
1672
- * in daisy chain use case */
1673
- j = i;
1674
- if (pool->stream_enc[i]->id ==
1675
- link->link_enc->preferred_engine)
1676
- return pool->stream_enc[i];
1677
- }
1678
- }
1679
-
1680
- /*
1681
- * below can happen in cases when stream encoder is acquired:
1682
- * 1) for second MST display in chain, so preferred engine already
1683
- * acquired;
1684
- * 2) for another link, which preferred engine already acquired by any
1685
- * MST configuration.
1686
- *
1687
- * If signal is of DP type and preferred engine not found, return last available
1688
- *
1689
- * TODO - This is just a patch up and a generic solution is
1690
- * required for non DP connectors.
1691
- */
1692
-
1693
- if (j >= 0 && dc_is_dp_signal(stream->signal))
1694
- return pool->stream_enc[j];
1695
-
1696
- return NULL;
1697
-}
1698
-
16991797 static struct audio *find_first_free_audio(
17001798 struct resource_context *res_ctx,
17011799 const struct resource_pool *pool,
1702
- enum engine_id id)
1800
+ enum engine_id id,
1801
+ enum dce_version dc_version)
17031802 {
17041803 int i, available_audio_count;
17051804
....@@ -1727,31 +1826,19 @@
17271826 return 0;
17281827 }
17291828
1730
-bool resource_is_stream_unchanged(
1731
- struct dc_state *old_context, struct dc_stream_state *stream)
1732
-{
1733
- int i;
1734
-
1735
- for (i = 0; i < old_context->stream_count; i++) {
1736
- struct dc_stream_state *old_stream = old_context->streams[i];
1737
-
1738
- if (are_stream_backends_same(old_stream, stream))
1739
- return true;
1740
- }
1741
-
1742
- return false;
1743
-}
1744
-
1829
+/**
1830
+ * dc_add_stream_to_ctx() - Add a new dc_stream_state to a dc_state.
1831
+ */
17451832 enum dc_status dc_add_stream_to_ctx(
17461833 struct dc *dc,
17471834 struct dc_state *new_ctx,
17481835 struct dc_stream_state *stream)
17491836 {
1750
- struct dc_context *dc_ctx = dc->ctx;
17511837 enum dc_status res;
1838
+ DC_LOGGER_INIT(dc->ctx->logger);
17521839
17531840 if (new_ctx->stream_count >= dc->res_pool->timing_generator_count) {
1754
- DC_ERROR("Max streams reached, can't add stream %p !\n", stream);
1841
+ DC_LOG_WARNING("Max streams reached, can't add stream %p !\n", stream);
17551842 return DC_ERROR_UNEXPECTED;
17561843 }
17571844
....@@ -1761,11 +1848,14 @@
17611848
17621849 res = dc->res_pool->funcs->add_stream_to_ctx(dc, new_ctx, stream);
17631850 if (res != DC_OK)
1764
- DC_ERROR("Adding stream %p to context failed with err %d!\n", stream, res);
1851
+ DC_LOG_WARNING("Adding stream %p to context failed with err %d!\n", stream, res);
17651852
17661853 return res;
17671854 }
17681855
1856
+/**
1857
+ * dc_remove_stream_from_ctx() - Remove a stream from a dc_state.
1858
+ */
17691859 enum dc_status dc_remove_stream_from_ctx(
17701860 struct dc *dc,
17711861 struct dc_state *new_ctx,
....@@ -1773,43 +1863,45 @@
17731863 {
17741864 int i;
17751865 struct dc_context *dc_ctx = dc->ctx;
1776
- struct pipe_ctx *del_pipe = NULL;
1777
-
1778
- /* Release primary pipe */
1779
- for (i = 0; i < MAX_PIPES; i++) {
1780
- if (new_ctx->res_ctx.pipe_ctx[i].stream == stream &&
1781
- !new_ctx->res_ctx.pipe_ctx[i].top_pipe) {
1782
- del_pipe = &new_ctx->res_ctx.pipe_ctx[i];
1783
-
1784
- ASSERT(del_pipe->stream_res.stream_enc);
1785
- update_stream_engine_usage(
1786
- &new_ctx->res_ctx,
1787
- dc->res_pool,
1788
- del_pipe->stream_res.stream_enc,
1789
- false);
1790
-
1791
- if (del_pipe->stream_res.audio)
1792
- update_audio_usage(
1793
- &new_ctx->res_ctx,
1794
- dc->res_pool,
1795
- del_pipe->stream_res.audio,
1796
- false);
1797
-
1798
- resource_unreference_clock_source(&new_ctx->res_ctx,
1799
- dc->res_pool,
1800
- del_pipe->clock_source);
1801
-
1802
- if (dc->res_pool->funcs->remove_stream_from_ctx)
1803
- dc->res_pool->funcs->remove_stream_from_ctx(dc, new_ctx, stream);
1804
-
1805
- memset(del_pipe, 0, sizeof(*del_pipe));
1806
- }
1807
- }
1866
+ struct pipe_ctx *del_pipe = resource_get_head_pipe_for_stream(&new_ctx->res_ctx, stream);
1867
+ struct pipe_ctx *odm_pipe;
18081868
18091869 if (!del_pipe) {
18101870 DC_ERROR("Pipe not found for stream %p !\n", stream);
18111871 return DC_ERROR_UNEXPECTED;
18121872 }
1873
+
1874
+ odm_pipe = del_pipe->next_odm_pipe;
1875
+
1876
+ /* Release primary pipe */
1877
+ ASSERT(del_pipe->stream_res.stream_enc);
1878
+ update_stream_engine_usage(
1879
+ &new_ctx->res_ctx,
1880
+ dc->res_pool,
1881
+ del_pipe->stream_res.stream_enc,
1882
+ false);
1883
+
1884
+ if (del_pipe->stream_res.audio)
1885
+ update_audio_usage(
1886
+ &new_ctx->res_ctx,
1887
+ dc->res_pool,
1888
+ del_pipe->stream_res.audio,
1889
+ false);
1890
+
1891
+ resource_unreference_clock_source(&new_ctx->res_ctx,
1892
+ dc->res_pool,
1893
+ del_pipe->clock_source);
1894
+
1895
+ if (dc->res_pool->funcs->remove_stream_from_ctx)
1896
+ dc->res_pool->funcs->remove_stream_from_ctx(dc, new_ctx, stream);
1897
+
1898
+ while (odm_pipe) {
1899
+ struct pipe_ctx *next_odm_pipe = odm_pipe->next_odm_pipe;
1900
+
1901
+ memset(odm_pipe, 0, sizeof(*odm_pipe));
1902
+ odm_pipe = next_odm_pipe;
1903
+ }
1904
+ memset(del_pipe, 0, sizeof(*del_pipe));
18131905
18141906 for (i = 0; i < new_ctx->stream_count; i++)
18151907 if (new_ctx->streams[i] == stream)
....@@ -1851,7 +1943,7 @@
18511943 if (resource_are_streams_timing_synchronizable(
18521944 stream_needs_pll, stream_has_pll)
18531945 && !dc_is_dp_signal(stream_has_pll->signal)
1854
- && stream_has_pll->sink->link->connector_signal
1946
+ && stream_has_pll->link->connector_signal
18551947 != SIGNAL_TYPE_VIRTUAL)
18561948 return stream_has_pll;
18571949
....@@ -1862,7 +1954,7 @@
18621954
18631955 static int get_norm_pix_clk(const struct dc_crtc_timing *timing)
18641956 {
1865
- uint32_t pix_clk = timing->pix_clk_khz;
1957
+ uint32_t pix_clk = timing->pix_clk_100hz;
18661958 uint32_t normalized_pix_clk = pix_clk;
18671959
18681960 if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
....@@ -1895,10 +1987,85 @@
18951987 /* update actual pixel clock on all streams */
18961988 if (dc_is_hdmi_signal(stream->signal))
18971989 stream->phy_pix_clk = get_norm_pix_clk(
1898
- &stream->timing);
1990
+ &stream->timing) / 10;
18991991 else
19001992 stream->phy_pix_clk =
1901
- stream->timing.pix_clk_khz;
1993
+ stream->timing.pix_clk_100hz / 10;
1994
+
1995
+ if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
1996
+ stream->phy_pix_clk *= 2;
1997
+}
1998
+
1999
+static int acquire_resource_from_hw_enabled_state(
2000
+ struct resource_context *res_ctx,
2001
+ const struct resource_pool *pool,
2002
+ struct dc_stream_state *stream)
2003
+{
2004
+ struct dc_link *link = stream->link;
2005
+ unsigned int i, inst, tg_inst = 0;
2006
+
2007
+ /* Check for enabled DIG to identify enabled display */
2008
+ if (!link->link_enc->funcs->is_dig_enabled(link->link_enc))
2009
+ return -1;
2010
+
2011
+ inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);
2012
+
2013
+ if (inst == ENGINE_ID_UNKNOWN)
2014
+ return -1;
2015
+
2016
+ for (i = 0; i < pool->stream_enc_count; i++) {
2017
+ if (pool->stream_enc[i]->id == inst) {
2018
+ tg_inst = pool->stream_enc[i]->funcs->dig_source_otg(
2019
+ pool->stream_enc[i]);
2020
+ break;
2021
+ }
2022
+ }
2023
+
2024
+ // tg_inst not found
2025
+ if (i == pool->stream_enc_count)
2026
+ return -1;
2027
+
2028
+ if (tg_inst >= pool->timing_generator_count)
2029
+ return -1;
2030
+
2031
+ if (!res_ctx->pipe_ctx[tg_inst].stream) {
2032
+ struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[tg_inst];
2033
+
2034
+ pipe_ctx->stream_res.tg = pool->timing_generators[tg_inst];
2035
+ pipe_ctx->plane_res.mi = pool->mis[tg_inst];
2036
+ pipe_ctx->plane_res.hubp = pool->hubps[tg_inst];
2037
+ pipe_ctx->plane_res.ipp = pool->ipps[tg_inst];
2038
+ pipe_ctx->plane_res.xfm = pool->transforms[tg_inst];
2039
+ pipe_ctx->plane_res.dpp = pool->dpps[tg_inst];
2040
+ pipe_ctx->stream_res.opp = pool->opps[tg_inst];
2041
+
2042
+ if (pool->dpps[tg_inst]) {
2043
+ pipe_ctx->plane_res.mpcc_inst = pool->dpps[tg_inst]->inst;
2044
+
2045
+ // Read DPP->MPCC->OPP Pipe from HW State
2046
+ if (pool->mpc->funcs->read_mpcc_state) {
2047
+ struct mpcc_state s = {0};
2048
+
2049
+ pool->mpc->funcs->read_mpcc_state(pool->mpc, pipe_ctx->plane_res.mpcc_inst, &s);
2050
+
2051
+ if (s.dpp_id < MAX_MPCC)
2052
+ pool->mpc->mpcc_array[pipe_ctx->plane_res.mpcc_inst].dpp_id = s.dpp_id;
2053
+
2054
+ if (s.bot_mpcc_id < MAX_MPCC)
2055
+ pool->mpc->mpcc_array[pipe_ctx->plane_res.mpcc_inst].mpcc_bot =
2056
+ &pool->mpc->mpcc_array[s.bot_mpcc_id];
2057
+
2058
+ if (s.opp_id < MAX_OPP)
2059
+ pipe_ctx->stream_res.opp->mpc_tree_params.opp_id = s.opp_id;
2060
+ }
2061
+ }
2062
+ pipe_ctx->pipe_idx = tg_inst;
2063
+
2064
+ pipe_ctx->stream = stream;
2065
+ return tg_inst;
2066
+ }
2067
+
2068
+ return -1;
19022069 }
19032070
19042071 enum dc_status resource_map_pool_resources(
....@@ -1911,24 +2078,28 @@
19112078 struct dc_context *dc_ctx = dc->ctx;
19122079 struct pipe_ctx *pipe_ctx = NULL;
19132080 int pipe_idx = -1;
1914
-
1915
- /* TODO Check if this is needed */
1916
- /*if (!resource_is_stream_unchanged(old_context, stream)) {
1917
- if (stream != NULL && old_context->streams[i] != NULL) {
1918
- stream->bit_depth_params =
1919
- old_context->streams[i]->bit_depth_params;
1920
- stream->clamping = old_context->streams[i]->clamping;
1921
- continue;
1922
- }
1923
- }
1924
- */
2081
+ struct dc_bios *dcb = dc->ctx->dc_bios;
19252082
19262083 calculate_phy_pix_clks(stream);
19272084
1928
- /* acquire new resources */
1929
- pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream);
2085
+ /* TODO: Check Linux */
2086
+ if (dc->config.allow_seamless_boot_optimization &&
2087
+ !dcb->funcs->is_accelerated_mode(dcb)) {
2088
+ if (dc_validate_seamless_boot_timing(dc, stream->sink, &stream->timing))
2089
+ stream->apply_seamless_boot_optimization = true;
2090
+ }
19302091
1931
-#ifdef CONFIG_DRM_AMD_DC_DCN1_0
2092
+ if (stream->apply_seamless_boot_optimization)
2093
+ pipe_idx = acquire_resource_from_hw_enabled_state(
2094
+ &context->res_ctx,
2095
+ pool,
2096
+ stream);
2097
+
2098
+ if (pipe_idx < 0)
2099
+ /* acquire new resources */
2100
+ pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream);
2101
+
2102
+#ifdef CONFIG_DRM_AMD_DC_DCN
19322103 if (pipe_idx < 0)
19332104 pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream);
19342105 #endif
....@@ -1939,11 +2110,11 @@
19392110 pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx];
19402111
19412112 pipe_ctx->stream_res.stream_enc =
1942
- find_first_free_match_stream_enc_for_link(
2113
+ dc->res_pool->funcs->find_first_free_match_stream_enc_for_link(
19432114 &context->res_ctx, pool, stream);
19442115
19452116 if (!pipe_ctx->stream_res.stream_enc)
1946
- return DC_NO_STREAM_ENG_RESOURCE;
2117
+ return DC_NO_STREAM_ENC_RESOURCE;
19472118
19482119 update_stream_engine_usage(
19492120 &context->res_ctx, pool,
....@@ -1951,11 +2122,11 @@
19512122 true);
19522123
19532124 /* TODO: Add check if ASIC support and EDID audio */
1954
- if (!stream->sink->converter_disable_audio &&
2125
+ if (!stream->converter_disable_audio &&
19552126 dc_is_audio_capable_signal(pipe_ctx->stream->signal) &&
19562127 stream->audio_info.mode_count && stream->audio_info.flags.all) {
19572128 pipe_ctx->stream_res.audio = find_first_free_audio(
1958
- &context->res_ctx, pool, pipe_ctx->stream_res.stream_enc->id);
2129
+ &context->res_ctx, pool, pipe_ctx->stream_res.stream_enc->id, dc_ctx->dce_version);
19592130
19602131 /*
19612132 * Audio assigned in order first come first get.
....@@ -1968,13 +2139,24 @@
19682139 }
19692140
19702141 /* Add ABM to the resource if on EDP */
1971
- if (pipe_ctx->stream && dc_is_embedded_signal(pipe_ctx->stream->signal))
2142
+ if (pipe_ctx->stream && dc_is_embedded_signal(pipe_ctx->stream->signal)) {
2143
+#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
2144
+ if (pool->abm)
2145
+ pipe_ctx->stream_res.abm = pool->abm;
2146
+ else
2147
+ pipe_ctx->stream_res.abm = pool->multiple_abms[pipe_ctx->stream_res.tg->inst];
2148
+#else
19722149 pipe_ctx->stream_res.abm = pool->abm;
2150
+#endif
2151
+ }
19732152
19742153 for (i = 0; i < context->stream_count; i++)
19752154 if (context->streams[i] == stream) {
19762155 context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst;
1977
- context->stream_status[i].stream_enc_inst = pipe_ctx->stream_res.stream_enc->id;
2156
+ context->stream_status[i].stream_enc_inst = pipe_ctx->stream_res.stream_enc->stream_enc_inst;
2157
+ context->stream_status[i].audio_inst =
2158
+ pipe_ctx->stream_res.audio ? pipe_ctx->stream_res.audio->inst : -1;
2159
+
19782160 return DC_OK;
19792161 }
19802162
....@@ -1982,6 +2164,12 @@
19822164 return DC_ERROR_UNEXPECTED;
19832165 }
19842166
2167
+/**
2168
+ * dc_resource_state_copy_construct_current() - Creates a new dc_state from existing state
2169
+ * Is a shallow copy. Increments refcounts on existing streams and planes.
2170
+ * @dc: copy out of dc->current_state
2171
+ * @dst_ctx: copy into this
2172
+ */
19852173 void dc_resource_state_copy_construct_current(
19862174 const struct dc *dc,
19872175 struct dc_state *dst_ctx)
....@@ -1994,12 +2182,29 @@
19942182 const struct dc *dc,
19952183 struct dc_state *dst_ctx)
19962184 {
1997
- dst_ctx->dis_clk = dc->res_pool->dccg;
2185
+ dst_ctx->clk_mgr = dc->clk_mgr;
19982186 }
19992187
2188
+
2189
+bool dc_resource_is_dsc_encoding_supported(const struct dc *dc)
2190
+{
2191
+ return dc->res_pool->res_cap->num_dsc > 0;
2192
+}
2193
+
2194
+
2195
+/**
2196
+ * dc_validate_global_state() - Determine if HW can support a given state
2197
+ * Checks HW resource availability and bandwidth requirement.
2198
+ * @dc: dc struct for this driver
2199
+ * @new_ctx: state to be validated
2200
+ * @fast_validate: set to true if only yes/no to support matters
2201
+ *
2202
+ * Return: DC_OK if the result can be programmed. Otherwise, an error code.
2203
+ */
20002204 enum dc_status dc_validate_global_state(
20012205 struct dc *dc,
2002
- struct dc_state *new_ctx)
2206
+ struct dc_state *new_ctx,
2207
+ bool fast_validate)
20032208 {
20042209 enum dc_status result = DC_ERROR_UNEXPECTED;
20052210 int i, j;
....@@ -2021,6 +2226,14 @@
20212226
20222227 if (pipe_ctx->stream != stream)
20232228 continue;
2229
+
2230
+ if (dc->res_pool->funcs->patch_unknown_plane_state &&
2231
+ pipe_ctx->plane_state &&
2232
+ pipe_ctx->plane_state->tiling_info.gfx9.swizzle == DC_SW_UNKNOWN) {
2233
+ result = dc->res_pool->funcs->patch_unknown_plane_state(pipe_ctx->plane_state);
2234
+ if (result != DC_OK)
2235
+ return result;
2236
+ }
20242237
20252238 /* Switch to dp clock source only if there is
20262239 * no non dp stream that shares the same timing
....@@ -2046,7 +2259,7 @@
20462259 result = resource_build_scaling_params_for_context(dc, new_ctx);
20472260
20482261 if (result == DC_OK)
2049
- if (!dc->res_pool->funcs->validate_bandwidth(dc, new_ctx))
2262
+ if (!dc->res_pool->funcs->validate_bandwidth(dc, new_ctx, fast_validate))
20502263 result = DC_FAIL_BANDWIDTH_VALIDATE;
20512264
20522265 return result;
....@@ -2191,7 +2404,7 @@
21912404 itc = true;
21922405 itc_value = 1;
21932406
2194
- support = stream->sink->edid_caps.content_support;
2407
+ support = stream->content_support;
21952408
21962409 if (itc) {
21972410 if (!support.bits.valid_content_type) {
....@@ -2230,12 +2443,12 @@
22302443
22312444 /* TODO : We should handle YCC quantization */
22322445 /* but we do not have matrix calculation */
2233
- if (stream->sink->edid_caps.qs_bit == 1 &&
2234
- stream->sink->edid_caps.qy_bit == 1) {
2446
+ if (stream->qs_bit == 1 &&
2447
+ stream->qy_bit == 1) {
22352448 if (color_space == COLOR_SPACE_SRGB ||
22362449 color_space == COLOR_SPACE_2020_RGB_FULLRANGE) {
22372450 hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_FULL_RANGE;
2238
- hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_FULL_RANGE;
2451
+ hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE;
22392452 } else if (color_space == COLOR_SPACE_SRGB_LIMITED ||
22402453 color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) {
22412454 hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_LIMITED_RANGE;
....@@ -2271,7 +2484,18 @@
22712484 break;
22722485 }
22732486 }
2487
+ /* If VIC >= 128, the Source shall use AVI InfoFrame Version 3*/
22742488 hdmi_info.bits.VIC0_VIC7 = vic;
2489
+ if (vic >= 128)
2490
+ hdmi_info.bits.header.version = 3;
2491
+ /* If (C1, C0)=(1, 1) and (EC2, EC1, EC0)=(1, 1, 1),
2492
+ * the Source shall use 20 AVI InfoFrame Version 4
2493
+ */
2494
+ if (hdmi_info.bits.C0_C1 == COLORIMETRY_EXTENDED &&
2495
+ hdmi_info.bits.EC0_EC2 == COLORIMETRYEX_RESERVED) {
2496
+ hdmi_info.bits.header.version = 4;
2497
+ hdmi_info.bits.header.length = 14;
2498
+ }
22752499
22762500 /* pixel repetition
22772501 * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel
....@@ -2290,12 +2514,19 @@
22902514 hdmi_info.bits.bar_right = (stream->timing.h_total
22912515 - stream->timing.h_border_right + 1);
22922516
2517
+ /* Additional Colorimetry Extension
2518
+ * Used in conduction with C0-C1 and EC0-EC2
2519
+ * 0 = DCI-P3 RGB (D65)
2520
+ * 1 = DCI-P3 RGB (theater)
2521
+ */
2522
+ hdmi_info.bits.ACE0_ACE3 = 0;
2523
+
22932524 /* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */
22942525 check_sum = &hdmi_info.packet_raw_data.sb[0];
22952526
2296
- *check_sum = HDMI_INFOFRAME_TYPE_AVI + HDMI_AVI_INFOFRAME_SIZE + 2;
2527
+ *check_sum = HDMI_INFOFRAME_TYPE_AVI + hdmi_info.bits.header.length + hdmi_info.bits.header.version;
22972528
2298
- for (byte_index = 1; byte_index <= HDMI_AVI_INFOFRAME_SIZE; byte_index++)
2529
+ for (byte_index = 1; byte_index <= hdmi_info.bits.header.length; byte_index++)
22992530 *check_sum += hdmi_info.packet_raw_data.sb[byte_index];
23002531
23012532 /* one byte complement */
....@@ -2316,113 +2547,15 @@
23162547 struct dc_info_packet *info_packet,
23172548 struct dc_stream_state *stream)
23182549 {
2319
- uint32_t length = 0;
2320
- bool hdmi_vic_mode = false;
2321
- uint8_t checksum = 0;
2322
- uint32_t i = 0;
2323
- enum dc_timing_3d_format format;
2324
- // Can be different depending on packet content /*todo*/
2325
- // unsigned int length = pPathMode->dolbyVision ? 24 : 5;
2550
+ /* SPD info packet for FreeSync */
23262551
2327
- info_packet->valid = false;
2328
-
2329
- format = stream->timing.timing_3d_format;
2330
- if (stream->view_format == VIEW_3D_FORMAT_NONE)
2331
- format = TIMING_3D_FORMAT_NONE;
2332
-
2333
- /* Can be different depending on packet content */
2334
- length = 5;
2335
-
2336
- if (stream->timing.hdmi_vic != 0
2337
- && stream->timing.h_total >= 3840
2338
- && stream->timing.v_total >= 2160)
2339
- hdmi_vic_mode = true;
2340
-
2341
- /* According to HDMI 1.4a CTS, VSIF should be sent
2342
- * for both 3D stereo and HDMI VIC modes.
2343
- * For all other modes, there is no VSIF sent. */
2344
-
2345
- if (format == TIMING_3D_FORMAT_NONE && !hdmi_vic_mode)
2552
+ /* Check if Freesync is supported. Return if false. If true,
2553
+ * set the corresponding bit in the info packet
2554
+ */
2555
+ if (!stream->vsp_infopacket.valid)
23462556 return;
23472557
2348
- /* 24bit IEEE Registration identifier (0x000c03). LSB first. */
2349
- info_packet->sb[1] = 0x03;
2350
- info_packet->sb[2] = 0x0C;
2351
- info_packet->sb[3] = 0x00;
2352
-
2353
- /*PB4: 5 lower bytes = 0 (reserved). 3 higher bits = HDMI_Video_Format.
2354
- * The value for HDMI_Video_Format are:
2355
- * 0x0 (0b000) - No additional HDMI video format is presented in this
2356
- * packet
2357
- * 0x1 (0b001) - Extended resolution format present. 1 byte of HDMI_VIC
2358
- * parameter follows
2359
- * 0x2 (0b010) - 3D format indication present. 3D_Structure and
2360
- * potentially 3D_Ext_Data follows
2361
- * 0x3..0x7 (0b011..0b111) - reserved for future use */
2362
- if (format != TIMING_3D_FORMAT_NONE)
2363
- info_packet->sb[4] = (2 << 5);
2364
- else if (hdmi_vic_mode)
2365
- info_packet->sb[4] = (1 << 5);
2366
-
2367
- /* PB5: If PB4 claims 3D timing (HDMI_Video_Format = 0x2):
2368
- * 4 lower bites = 0 (reserved). 4 higher bits = 3D_Structure.
2369
- * The value for 3D_Structure are:
2370
- * 0x0 - Frame Packing
2371
- * 0x1 - Field Alternative
2372
- * 0x2 - Line Alternative
2373
- * 0x3 - Side-by-Side (full)
2374
- * 0x4 - L + depth
2375
- * 0x5 - L + depth + graphics + graphics-depth
2376
- * 0x6 - Top-and-Bottom
2377
- * 0x7 - Reserved for future use
2378
- * 0x8 - Side-by-Side (Half)
2379
- * 0x9..0xE - Reserved for future use
2380
- * 0xF - Not used */
2381
- switch (format) {
2382
- case TIMING_3D_FORMAT_HW_FRAME_PACKING:
2383
- case TIMING_3D_FORMAT_SW_FRAME_PACKING:
2384
- info_packet->sb[5] = (0x0 << 4);
2385
- break;
2386
-
2387
- case TIMING_3D_FORMAT_SIDE_BY_SIDE:
2388
- case TIMING_3D_FORMAT_SBS_SW_PACKED:
2389
- info_packet->sb[5] = (0x8 << 4);
2390
- length = 6;
2391
- break;
2392
-
2393
- case TIMING_3D_FORMAT_TOP_AND_BOTTOM:
2394
- case TIMING_3D_FORMAT_TB_SW_PACKED:
2395
- info_packet->sb[5] = (0x6 << 4);
2396
- break;
2397
-
2398
- default:
2399
- break;
2400
- }
2401
-
2402
- /*PB5: If PB4 is set to 0x1 (extended resolution format)
2403
- * fill PB5 with the correct HDMI VIC code */
2404
- if (hdmi_vic_mode)
2405
- info_packet->sb[5] = stream->timing.hdmi_vic;
2406
-
2407
- /* Header */
2408
- info_packet->hb0 = HDMI_INFOFRAME_TYPE_VENDOR; /* VSIF packet type. */
2409
- info_packet->hb1 = 0x01; /* Version */
2410
-
2411
- /* 4 lower bits = Length, 4 higher bits = 0 (reserved) */
2412
- info_packet->hb2 = (uint8_t) (length);
2413
-
2414
- /* Calculate checksum */
2415
- checksum = 0;
2416
- checksum += info_packet->hb0;
2417
- checksum += info_packet->hb1;
2418
- checksum += info_packet->hb2;
2419
-
2420
- for (i = 1; i <= length; i++)
2421
- checksum += info_packet->sb[i];
2422
-
2423
- info_packet->sb[0] = (uint8_t) (0x100 - checksum);
2424
-
2425
- info_packet->valid = true;
2558
+ *info_packet = stream->vsp_infopacket;
24262559 }
24272560
24282561 static void set_spd_info_packet(
....@@ -2431,119 +2564,13 @@
24312564 {
24322565 /* SPD info packet for FreeSync */
24332566
2434
- unsigned char checksum = 0;
2435
- unsigned int idx, payload_size = 0;
2436
-
24372567 /* Check if Freesync is supported. Return if false. If true,
24382568 * set the corresponding bit in the info packet
24392569 */
2440
- if (stream->freesync_ctx.supported == false)
2570
+ if (!stream->vrr_infopacket.valid)
24412571 return;
24422572
2443
- if (dc_is_hdmi_signal(stream->signal)) {
2444
-
2445
- /* HEADER */
2446
-
2447
- /* HB0 = Packet Type = 0x83 (Source Product
2448
- * Descriptor InfoFrame)
2449
- */
2450
- info_packet->hb0 = HDMI_INFOFRAME_TYPE_SPD;
2451
-
2452
- /* HB1 = Version = 0x01 */
2453
- info_packet->hb1 = 0x01;
2454
-
2455
- /* HB2 = [Bits 7:5 = 0] [Bits 4:0 = Length = 0x08] */
2456
- info_packet->hb2 = 0x08;
2457
-
2458
- payload_size = 0x08;
2459
-
2460
- } else if (dc_is_dp_signal(stream->signal)) {
2461
-
2462
- /* HEADER */
2463
-
2464
- /* HB0 = Secondary-data Packet ID = 0 - Only non-zero
2465
- * when used to associate audio related info packets
2466
- */
2467
- info_packet->hb0 = 0x00;
2468
-
2469
- /* HB1 = Packet Type = 0x83 (Source Product
2470
- * Descriptor InfoFrame)
2471
- */
2472
- info_packet->hb1 = HDMI_INFOFRAME_TYPE_SPD;
2473
-
2474
- /* HB2 = [Bits 7:0 = Least significant eight bits -
2475
- * For INFOFRAME, the value must be 1Bh]
2476
- */
2477
- info_packet->hb2 = 0x1B;
2478
-
2479
- /* HB3 = [Bits 7:2 = INFOFRAME SDP Version Number = 0x1]
2480
- * [Bits 1:0 = Most significant two bits = 0x00]
2481
- */
2482
- info_packet->hb3 = 0x04;
2483
-
2484
- payload_size = 0x1B;
2485
- }
2486
-
2487
- /* PB1 = 0x1A (24bit AMD IEEE OUI (0x00001A) - Byte 0) */
2488
- info_packet->sb[1] = 0x1A;
2489
-
2490
- /* PB2 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 1) */
2491
- info_packet->sb[2] = 0x00;
2492
-
2493
- /* PB3 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 2) */
2494
- info_packet->sb[3] = 0x00;
2495
-
2496
- /* PB4 = Reserved */
2497
- info_packet->sb[4] = 0x00;
2498
-
2499
- /* PB5 = Reserved */
2500
- info_packet->sb[5] = 0x00;
2501
-
2502
- /* PB6 = [Bits 7:3 = Reserved] */
2503
- info_packet->sb[6] = 0x00;
2504
-
2505
- if (stream->freesync_ctx.supported == true)
2506
- /* PB6 = [Bit 0 = FreeSync Supported] */
2507
- info_packet->sb[6] |= 0x01;
2508
-
2509
- if (stream->freesync_ctx.enabled == true)
2510
- /* PB6 = [Bit 1 = FreeSync Enabled] */
2511
- info_packet->sb[6] |= 0x02;
2512
-
2513
- if (stream->freesync_ctx.active == true)
2514
- /* PB6 = [Bit 2 = FreeSync Active] */
2515
- info_packet->sb[6] |= 0x04;
2516
-
2517
- /* PB7 = FreeSync Minimum refresh rate (Hz) */
2518
- info_packet->sb[7] = (unsigned char) (stream->freesync_ctx.
2519
- min_refresh_in_micro_hz / 1000000);
2520
-
2521
- /* PB8 = FreeSync Maximum refresh rate (Hz)
2522
- *
2523
- * Note: We do not use the maximum capable refresh rate
2524
- * of the panel, because we should never go above the field
2525
- * rate of the mode timing set.
2526
- */
2527
- info_packet->sb[8] = (unsigned char) (stream->freesync_ctx.
2528
- nominal_refresh_in_micro_hz / 1000000);
2529
-
2530
- /* PB9 - PB27 = Reserved */
2531
- for (idx = 9; idx <= 27; idx++)
2532
- info_packet->sb[idx] = 0x00;
2533
-
2534
- /* Calculate checksum */
2535
- checksum += info_packet->hb0;
2536
- checksum += info_packet->hb1;
2537
- checksum += info_packet->hb2;
2538
- checksum += info_packet->hb3;
2539
-
2540
- for (idx = 1; idx <= payload_size; idx++)
2541
- checksum += info_packet->sb[idx];
2542
-
2543
- /* PB0 = Checksum (one byte complement) */
2544
- info_packet->sb[0] = (unsigned char) (0x100 - checksum);
2545
-
2546
- info_packet->valid = true;
2573
+ *info_packet = stream->vrr_infopacket;
25472574 }
25482575
25492576 static void set_hdr_static_info_packet(
....@@ -2563,43 +2590,10 @@
25632590 struct dc_info_packet *info_packet,
25642591 struct dc_stream_state *stream)
25652592 {
2566
- unsigned int vscPacketRevision = 0;
2567
- unsigned int i;
2568
-
2569
- /*VSC packet set to 2 when DP revision >= 1.2*/
2570
- if (stream->psr_version != 0) {
2571
- vscPacketRevision = 2;
2572
- }
2573
-
2574
- /* VSC packet not needed based on the features
2575
- * supported by this DP display
2576
- */
2577
- if (vscPacketRevision == 0)
2593
+ if (!stream->vsc_infopacket.valid)
25782594 return;
25792595
2580
- if (vscPacketRevision == 0x2) {
2581
- /* Secondary-data Packet ID = 0*/
2582
- info_packet->hb0 = 0x00;
2583
- /* 07h - Packet Type Value indicating Video
2584
- * Stream Configuration packet
2585
- */
2586
- info_packet->hb1 = 0x07;
2587
- /* 02h = VSC SDP supporting 3D stereo and PSR
2588
- * (applies to eDP v1.3 or higher).
2589
- */
2590
- info_packet->hb2 = 0x02;
2591
- /* 08h = VSC packet supporting 3D stereo + PSR
2592
- * (HB2 = 02h).
2593
- */
2594
- info_packet->hb3 = 0x08;
2595
-
2596
- for (i = 0; i < 28; i++)
2597
- info_packet->sb[i] = 0;
2598
-
2599
- info_packet->valid = true;
2600
- }
2601
-
2602
- /*TODO: stereo 3D support and extend pixel encoding colorimetry*/
2596
+ *info_packet = stream->vsc_infopacket;
26032597 }
26042598
26052599 void dc_resource_state_destruct(struct dc_state *context)
....@@ -2617,10 +2611,6 @@
26172611 }
26182612 }
26192613
2620
-/*
2621
- * Copy src_ctx into dst_ctx and retain all surfaces and streams referenced
2622
- * by the src_ctx
2623
- */
26242614 void dc_resource_state_copy_construct(
26252615 const struct dc_state *src_ctx,
26262616 struct dc_state *dst_ctx)
....@@ -2639,6 +2629,11 @@
26392629 if (cur_pipe->bottom_pipe)
26402630 cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
26412631
2632
+ if (cur_pipe->next_odm_pipe)
2633
+ cur_pipe->next_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx];
2634
+
2635
+ if (cur_pipe->prev_odm_pipe)
2636
+ cur_pipe->prev_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx];
26422637 }
26432638
26442639 for (i = 0; i < dst_ctx->stream_count; i++) {
....@@ -2775,7 +2770,14 @@
27752770 if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream))
27762771 return true;
27772772
2778
- if (is_hdr_static_meta_changed(pipe_ctx_old->stream, pipe_ctx->stream))
2773
+ if (pipe_ctx_old->stream->dpms_off != pipe_ctx->stream->dpms_off)
2774
+ return true;
2775
+
2776
+ if (false == pipe_ctx_old->stream->link->link_state_valid &&
2777
+ false == pipe_ctx_old->stream->dpms_off)
2778
+ return true;
2779
+
2780
+ if (pipe_ctx_old->stream_res.dsc != pipe_ctx->stream_res.dsc)
27792781 return true;
27802782
27812783 return false;
....@@ -2909,9 +2911,8 @@
29092911
29102912 enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream)
29112913 {
2912
- struct dc *core_dc = dc;
2913
- struct dc_link *link = stream->sink->link;
2914
- struct timing_generator *tg = core_dc->res_pool->timing_generators[0];
2914
+ struct dc_link *link = stream->link;
2915
+ struct timing_generator *tg = dc->res_pool->timing_generators[0];
29152916 enum dc_status res = DC_OK;
29162917
29172918 calculate_phy_pix_clks(stream);
....@@ -2919,10 +2920,11 @@
29192920 if (!tg->funcs->validate_timing(tg, &stream->timing))
29202921 res = DC_FAIL_CONTROLLER_VALIDATE;
29212922
2922
- if (res == DC_OK)
2923
+ if (res == DC_OK) {
29232924 if (!link->link_enc->funcs->validate_output_with_stream(
29242925 link->link_enc, stream))
29252926 res = DC_FAIL_ENC_VALIDATE;
2927
+ }
29262928
29272929 /* TODO: validate audio ASIC caps, encoder */
29282930
....@@ -2944,3 +2946,81 @@
29442946
29452947 return res;
29462948 }
2949
+
2950
+unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format)
2951
+{
2952
+ switch (format) {
2953
+ case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
2954
+ return 8;
2955
+ case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
2956
+ case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
2957
+ return 12;
2958
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
2959
+ case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
2960
+ case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
2961
+ case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
2962
+ return 16;
2963
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
2964
+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
2965
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
2966
+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
2967
+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
2968
+#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
2969
+ case SURFACE_PIXEL_FORMAT_GRPH_RGBE:
2970
+ case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA:
2971
+#endif
2972
+ return 32;
2973
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
2974
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
2975
+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
2976
+ return 64;
2977
+ default:
2978
+ ASSERT_CRITICAL(false);
2979
+ return -1;
2980
+ }
2981
+}
2982
+static unsigned int get_max_audio_sample_rate(struct audio_mode *modes)
2983
+{
2984
+ if (modes) {
2985
+ if (modes->sample_rates.rate.RATE_192)
2986
+ return 192000;
2987
+ if (modes->sample_rates.rate.RATE_176_4)
2988
+ return 176400;
2989
+ if (modes->sample_rates.rate.RATE_96)
2990
+ return 96000;
2991
+ if (modes->sample_rates.rate.RATE_88_2)
2992
+ return 88200;
2993
+ if (modes->sample_rates.rate.RATE_48)
2994
+ return 48000;
2995
+ if (modes->sample_rates.rate.RATE_44_1)
2996
+ return 44100;
2997
+ if (modes->sample_rates.rate.RATE_32)
2998
+ return 32000;
2999
+ }
3000
+ /*original logic when no audio info*/
3001
+ return 441000;
3002
+}
3003
+
3004
+void get_audio_check(struct audio_info *aud_modes,
3005
+ struct audio_check *audio_chk)
3006
+{
3007
+ unsigned int i;
3008
+ unsigned int max_sample_rate = 0;
3009
+
3010
+ if (aud_modes) {
3011
+ audio_chk->audio_packet_type = 0x2;/*audio sample packet AP = .25 for layout0, 1 for layout1*/
3012
+
3013
+ audio_chk->max_audiosample_rate = 0;
3014
+ for (i = 0; i < aud_modes->mode_count; i++) {
3015
+ max_sample_rate = get_max_audio_sample_rate(&aud_modes->modes[i]);
3016
+ if (audio_chk->max_audiosample_rate < max_sample_rate)
3017
+ audio_chk->max_audiosample_rate = max_sample_rate;
3018
+ /*dts takes the same as type 2: AP = 0.25*/
3019
+ }
3020
+ /*check which one take more bandwidth*/
3021
+ if (audio_chk->max_audiosample_rate > 192000)
3022
+ audio_chk->audio_packet_type = 0x9;/*AP =1*/
3023
+ audio_chk->acat = 0;/*not support*/
3024
+ }
3025
+}
3026
+