1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include <linux/slab.h>
27
28#include "dm_services.h"
29
30#include "resource.h"
31#include "include/irq_service_interface.h"
32#include "link_encoder.h"
33#include "stream_encoder.h"
34#include "opp.h"
35#include "timing_generator.h"
36#include "transform.h"
37#include "dccg.h"
38#include "dchubbub.h"
39#include "dpp.h"
40#include "core_types.h"
41#include "set_mode_types.h"
42#include "virtual/virtual_stream_encoder.h"
43#include "dpcd_defs.h"
44
45#if defined(CONFIG_DRM_AMD_DC_SI)
46#include "dce60/dce60_resource.h"
47#endif
48#include "dce80/dce80_resource.h"
49#include "dce100/dce100_resource.h"
50#include "dce110/dce110_resource.h"
51#include "dce112/dce112_resource.h"
52#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#include "dcn30/dcn30_resource.h"
58#include "dcn301/dcn301_resource.h"
59#include "dcn302/dcn302_resource.h"
60#endif
61
62#define DC_LOGGER_INIT(logger)
63
64enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id)
65{
66 enum dce_version dc_version = DCE_VERSION_UNKNOWN;
67 switch (asic_id.chip_family) {
68
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
81 case FAMILY_CI:
82 dc_version = DCE_VERSION_8_0;
83 break;
84 case FAMILY_KV:
85 if (ASIC_REV_IS_KALINDI(asic_id.hw_internal_rev) ||
86 ASIC_REV_IS_BHAVANI(asic_id.hw_internal_rev) ||
87 ASIC_REV_IS_GODAVARI(asic_id.hw_internal_rev))
88 dc_version = DCE_VERSION_8_3;
89 else
90 dc_version = DCE_VERSION_8_1;
91 break;
92 case FAMILY_CZ:
93 dc_version = DCE_VERSION_11_0;
94 break;
95
96 case FAMILY_VI:
97 if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) ||
98 ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) {
99 dc_version = DCE_VERSION_10_0;
100 break;
101 }
102 if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) ||
103 ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) ||
104 ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) {
105 dc_version = DCE_VERSION_11_2;
106 }
107 if (ASIC_REV_IS_VEGAM(asic_id.hw_internal_rev))
108 dc_version = DCE_VERSION_11_22;
109 break;
110 case FAMILY_AI:
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;
115 break;
116#if defined(CONFIG_DRM_AMD_DC_DCN)
117 case FAMILY_RV:
118 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;
125 break;
126
127 case FAMILY_NV:
128 dc_version = DCN_VERSION_2_0;
129 if (ASICREV_IS_SIENNA_CICHLID_P(asic_id.hw_internal_rev))
130 dc_version = DCN_VERSION_3_0;
131 if (ASICREV_IS_DIMGREY_CAVEFISH_P(asic_id.hw_internal_rev))
132 dc_version = DCN_VERSION_3_02;
133 break;
134
135 case FAMILY_VGH:
136 dc_version = DCN_VERSION_3_01;
137 break;
138#endif
139 default:
140 dc_version = DCE_VERSION_UNKNOWN;
141 break;
142 }
143 return dc_version;
144}
145
146struct resource_pool *dc_create_resource_pool(struct dc *dc,
147 const struct dc_init_data *init_data,
148 enum dce_version dc_version)
149{
150 struct resource_pool *res_pool = NULL;
151
152 switch (dc_version) {
153#if defined(CONFIG_DRM_AMD_DC_SI)
154 case DCE_VERSION_6_0:
155 res_pool = dce60_create_resource_pool(
156 init_data->num_virtual_links, dc);
157 break;
158 case DCE_VERSION_6_1:
159 res_pool = dce61_create_resource_pool(
160 init_data->num_virtual_links, dc);
161 break;
162 case DCE_VERSION_6_4:
163 res_pool = dce64_create_resource_pool(
164 init_data->num_virtual_links, dc);
165 break;
166#endif
167 case DCE_VERSION_8_0:
168 res_pool = dce80_create_resource_pool(
169 init_data->num_virtual_links, dc);
170 break;
171 case DCE_VERSION_8_1:
172 res_pool = dce81_create_resource_pool(
173 init_data->num_virtual_links, dc);
174 break;
175 case DCE_VERSION_8_3:
176 res_pool = dce83_create_resource_pool(
177 init_data->num_virtual_links, dc);
178 break;
179 case DCE_VERSION_10_0:
180 res_pool = dce100_create_resource_pool(
181 init_data->num_virtual_links, dc);
182 break;
183 case DCE_VERSION_11_0:
184 res_pool = dce110_create_resource_pool(
185 init_data->num_virtual_links, dc,
186 init_data->asic_id);
187 break;
188 case DCE_VERSION_11_2:
189 case DCE_VERSION_11_22:
190 res_pool = dce112_create_resource_pool(
191 init_data->num_virtual_links, dc);
192 break;
193 case DCE_VERSION_12_0:
194 case DCE_VERSION_12_1:
195 res_pool = dce120_create_resource_pool(
196 init_data->num_virtual_links, dc);
197 break;
198
199#if defined(CONFIG_DRM_AMD_DC_DCN)
200 case DCN_VERSION_1_0:
201 case DCN_VERSION_1_01:
202 res_pool = dcn10_create_resource_pool(init_data, dc);
203 break;
204 case DCN_VERSION_2_0:
205 res_pool = dcn20_create_resource_pool(init_data, dc);
206 break;
207 case DCN_VERSION_2_1:
208 res_pool = dcn21_create_resource_pool(init_data, dc);
209 break;
210 case DCN_VERSION_3_0:
211 res_pool = dcn30_create_resource_pool(init_data, dc);
212 break;
213 case DCN_VERSION_3_01:
214 res_pool = dcn301_create_resource_pool(init_data, dc);
215 break;
216 case DCN_VERSION_3_02:
217 res_pool = dcn302_create_resource_pool(init_data, dc);
218 break;
219#endif
220 default:
221 break;
222 }
223
224 if (res_pool != NULL) {
225 if (dc->ctx->dc_bios->fw_info_valid) {
226 res_pool->ref_clocks.xtalin_clock_inKhz =
227 dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
228
229
230
231
232
233
234 res_pool->ref_clocks.dccg_ref_clock_inKhz =
235 res_pool->ref_clocks.xtalin_clock_inKhz;
236 res_pool->ref_clocks.dchub_ref_clock_inKhz =
237 res_pool->ref_clocks.xtalin_clock_inKhz;
238 } else
239 ASSERT_CRITICAL(false);
240 }
241
242 return res_pool;
243}
244
245void dc_destroy_resource_pool(struct dc *dc)
246{
247 if (dc) {
248 if (dc->res_pool)
249 dc->res_pool->funcs->destroy(&dc->res_pool);
250
251 kfree(dc->hwseq);
252 }
253}
254
255static void update_num_audio(
256 const struct resource_straps *straps,
257 unsigned int *num_audio,
258 struct audio_support *aud_support)
259{
260 aud_support->dp_audio = true;
261 aud_support->hdmi_audio_native = false;
262 aud_support->hdmi_audio_on_dongle = false;
263
264 if (straps->hdmi_disable == 0) {
265 if (straps->dc_pinstraps_audio & 0x2) {
266 aud_support->hdmi_audio_on_dongle = true;
267 aud_support->hdmi_audio_native = true;
268 }
269 }
270
271 switch (straps->audio_stream_number) {
272 case 0:
273 break;
274 case 1:
275 *num_audio = 1;
276 break;
277 default:
278 DC_ERR("DC: unexpected audio fuse!\n");
279 }
280}
281
282bool resource_construct(
283 unsigned int num_virtual_links,
284 struct dc *dc,
285 struct resource_pool *pool,
286 const struct resource_create_funcs *create_funcs)
287{
288 struct dc_context *ctx = dc->ctx;
289 const struct resource_caps *caps = pool->res_cap;
290 int i;
291 unsigned int num_audio = caps->num_audio;
292 struct resource_straps straps = {0};
293
294 if (create_funcs->read_dce_straps)
295 create_funcs->read_dce_straps(dc->ctx, &straps);
296
297 pool->audio_count = 0;
298 if (create_funcs->create_audio) {
299
300
301
302
303
304
305
306 update_num_audio(&straps, &num_audio, &pool->audio_support);
307 for (i = 0; i < caps->num_audio; i++) {
308 struct audio *aud = create_funcs->create_audio(ctx, i);
309
310 if (aud == NULL) {
311 DC_ERR("DC: failed to create audio!\n");
312 return false;
313 }
314 if (!aud->funcs->endpoint_valid(aud)) {
315 aud->funcs->destroy(&aud);
316 break;
317 }
318 pool->audios[i] = aud;
319 pool->audio_count++;
320 }
321 }
322
323 pool->stream_enc_count = 0;
324 if (create_funcs->create_stream_encoder) {
325 for (i = 0; i < caps->num_stream_encoder; i++) {
326 pool->stream_enc[i] = create_funcs->create_stream_encoder(i, ctx);
327 if (pool->stream_enc[i] == NULL)
328 DC_ERR("DC: failed to create stream_encoder!\n");
329 pool->stream_enc_count++;
330 }
331 }
332
333#if defined(CONFIG_DRM_AMD_DC_DCN)
334 for (i = 0; i < caps->num_mpc_3dlut; i++) {
335 pool->mpc_lut[i] = dc_create_3dlut_func();
336 if (pool->mpc_lut[i] == NULL)
337 DC_ERR("DC: failed to create MPC 3dlut!\n");
338 pool->mpc_shaper[i] = dc_create_transfer_func();
339 if (pool->mpc_shaper[i] == NULL)
340 DC_ERR("DC: failed to create MPC shaper!\n");
341 }
342#endif
343 dc->caps.dynamic_audio = false;
344 if (pool->audio_count < pool->stream_enc_count) {
345 dc->caps.dynamic_audio = true;
346 }
347 for (i = 0; i < num_virtual_links; i++) {
348 pool->stream_enc[pool->stream_enc_count] =
349 virtual_stream_encoder_create(
350 ctx, ctx->dc_bios);
351 if (pool->stream_enc[pool->stream_enc_count] == NULL) {
352 DC_ERR("DC: failed to create stream_encoder!\n");
353 return false;
354 }
355 pool->stream_enc_count++;
356 }
357
358 dc->hwseq = create_funcs->create_hwseq(ctx);
359
360 return true;
361}
362static int find_matching_clock_source(
363 const struct resource_pool *pool,
364 struct clock_source *clock_source)
365{
366
367 int i;
368
369 for (i = 0; i < pool->clk_src_count; i++) {
370 if (pool->clock_sources[i] == clock_source)
371 return i;
372 }
373 return -1;
374}
375
376void resource_unreference_clock_source(
377 struct resource_context *res_ctx,
378 const struct resource_pool *pool,
379 struct clock_source *clock_source)
380{
381 int i = find_matching_clock_source(pool, clock_source);
382
383 if (i > -1)
384 res_ctx->clock_source_ref_count[i]--;
385
386 if (pool->dp_clock_source == clock_source)
387 res_ctx->dp_clock_source_ref_count--;
388}
389
390void resource_reference_clock_source(
391 struct resource_context *res_ctx,
392 const struct resource_pool *pool,
393 struct clock_source *clock_source)
394{
395 int i = find_matching_clock_source(pool, clock_source);
396
397 if (i > -1)
398 res_ctx->clock_source_ref_count[i]++;
399
400 if (pool->dp_clock_source == clock_source)
401 res_ctx->dp_clock_source_ref_count++;
402}
403
404int resource_get_clock_source_reference(
405 struct resource_context *res_ctx,
406 const struct resource_pool *pool,
407 struct clock_source *clock_source)
408{
409 int i = find_matching_clock_source(pool, clock_source);
410
411 if (i > -1)
412 return res_ctx->clock_source_ref_count[i];
413
414 if (pool->dp_clock_source == clock_source)
415 return res_ctx->dp_clock_source_ref_count;
416
417 return -1;
418}
419
420bool resource_are_vblanks_synchronizable(
421 struct dc_stream_state *stream1,
422 struct dc_stream_state *stream2)
423{
424 uint32_t base60_refresh_rates[] = {10, 20, 5};
425 uint8_t i;
426 uint8_t rr_count = sizeof(base60_refresh_rates)/sizeof(base60_refresh_rates[0]);
427 uint64_t frame_time_diff;
428
429 if (stream1->ctx->dc->config.vblank_alignment_dto_params &&
430 stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0 &&
431 dc_is_dp_signal(stream1->signal) &&
432 dc_is_dp_signal(stream2->signal) &&
433 false == stream1->has_non_synchronizable_pclk &&
434 false == stream2->has_non_synchronizable_pclk &&
435 stream1->timing.flags.VBLANK_SYNCHRONIZABLE &&
436 stream2->timing.flags.VBLANK_SYNCHRONIZABLE) {
437
438 if (stream1->timing.pix_clk_100hz*100/stream1->timing.h_total/
439 stream1->timing.v_total > 60)
440 return false;
441 if (stream2->timing.pix_clk_100hz*100/stream2->timing.h_total/
442 stream2->timing.v_total > 60)
443 return false;
444 frame_time_diff = (uint64_t)10000 *
445 stream1->timing.h_total *
446 stream1->timing.v_total *
447 stream2->timing.pix_clk_100hz;
448 frame_time_diff = div_u64(frame_time_diff, stream1->timing.pix_clk_100hz);
449 frame_time_diff = div_u64(frame_time_diff, stream2->timing.h_total);
450 frame_time_diff = div_u64(frame_time_diff, stream2->timing.v_total);
451 for (i = 0; i < rr_count; i++) {
452 int64_t diff = (int64_t)div_u64(frame_time_diff * base60_refresh_rates[i], 10) - 10000;
453
454 if (diff < 0)
455 diff = -diff;
456 if (diff < stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff)
457 return true;
458 }
459 }
460 return false;
461}
462
463bool resource_are_streams_timing_synchronizable(
464 struct dc_stream_state *stream1,
465 struct dc_stream_state *stream2)
466{
467 if (stream1->timing.h_total != stream2->timing.h_total)
468 return false;
469
470 if (stream1->timing.v_total != stream2->timing.v_total)
471 return false;
472
473 if (stream1->timing.h_addressable
474 != stream2->timing.h_addressable)
475 return false;
476
477 if (stream1->timing.v_addressable
478 != stream2->timing.v_addressable)
479 return false;
480
481 if (stream1->timing.v_front_porch
482 != stream2->timing.v_front_porch)
483 return false;
484
485 if (stream1->timing.pix_clk_100hz
486 != stream2->timing.pix_clk_100hz)
487 return false;
488
489 if (stream1->clamping.c_depth != stream2->clamping.c_depth)
490 return false;
491
492 if (stream1->phy_pix_clk != stream2->phy_pix_clk
493 && (!dc_is_dp_signal(stream1->signal)
494 || !dc_is_dp_signal(stream2->signal)))
495 return false;
496
497 if (stream1->view_format != stream2->view_format)
498 return false;
499
500 if (stream1->ignore_msa_timing_param || stream2->ignore_msa_timing_param)
501 return false;
502
503 return true;
504}
505static bool is_dp_and_hdmi_sharable(
506 struct dc_stream_state *stream1,
507 struct dc_stream_state *stream2)
508{
509 if (stream1->ctx->dc->caps.disable_dp_clk_share)
510 return false;
511
512 if (stream1->clamping.c_depth != COLOR_DEPTH_888 ||
513 stream2->clamping.c_depth != COLOR_DEPTH_888)
514 return false;
515
516 return true;
517
518}
519
520static bool is_sharable_clk_src(
521 const struct pipe_ctx *pipe_with_clk_src,
522 const struct pipe_ctx *pipe)
523{
524 if (pipe_with_clk_src->clock_source == NULL)
525 return false;
526
527 if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL)
528 return false;
529
530 if (dc_is_dp_signal(pipe_with_clk_src->stream->signal) ||
531 (dc_is_dp_signal(pipe->stream->signal) &&
532 !is_dp_and_hdmi_sharable(pipe_with_clk_src->stream,
533 pipe->stream)))
534 return false;
535
536 if (dc_is_hdmi_signal(pipe_with_clk_src->stream->signal)
537 && dc_is_dual_link_signal(pipe->stream->signal))
538 return false;
539
540 if (dc_is_hdmi_signal(pipe->stream->signal)
541 && dc_is_dual_link_signal(pipe_with_clk_src->stream->signal))
542 return false;
543
544 if (!resource_are_streams_timing_synchronizable(
545 pipe_with_clk_src->stream, pipe->stream))
546 return false;
547
548 return true;
549}
550
551struct clock_source *resource_find_used_clk_src_for_sharing(
552 struct resource_context *res_ctx,
553 struct pipe_ctx *pipe_ctx)
554{
555 int i;
556
557 for (i = 0; i < MAX_PIPES; i++) {
558 if (is_sharable_clk_src(&res_ctx->pipe_ctx[i], pipe_ctx))
559 return res_ctx->pipe_ctx[i].clock_source;
560 }
561
562 return NULL;
563}
564
565static enum pixel_format convert_pixel_format_to_dalsurface(
566 enum surface_pixel_format surface_pixel_format)
567{
568 enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
569
570 switch (surface_pixel_format) {
571 case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
572 dal_pixel_format = PIXEL_FORMAT_INDEX8;
573 break;
574 case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
575 dal_pixel_format = PIXEL_FORMAT_RGB565;
576 break;
577 case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
578 dal_pixel_format = PIXEL_FORMAT_RGB565;
579 break;
580 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
581 dal_pixel_format = PIXEL_FORMAT_ARGB8888;
582 break;
583 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
584 dal_pixel_format = PIXEL_FORMAT_ARGB8888;
585 break;
586 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
587 dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
588 break;
589 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
590 dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
591 break;
592 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
593 dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS;
594 break;
595 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
596 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
597 dal_pixel_format = PIXEL_FORMAT_FP16;
598 break;
599 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
600 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
601 dal_pixel_format = PIXEL_FORMAT_420BPP8;
602 break;
603 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
604 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
605 dal_pixel_format = PIXEL_FORMAT_420BPP10;
606 break;
607 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
608 default:
609 dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
610 break;
611 }
612 return dal_pixel_format;
613}
614
615static inline void get_vp_scan_direction(
616 enum dc_rotation_angle rotation,
617 bool horizontal_mirror,
618 bool *orthogonal_rotation,
619 bool *flip_vert_scan_dir,
620 bool *flip_horz_scan_dir)
621{
622 *orthogonal_rotation = false;
623 *flip_vert_scan_dir = false;
624 *flip_horz_scan_dir = false;
625 if (rotation == ROTATION_ANGLE_180) {
626 *flip_vert_scan_dir = true;
627 *flip_horz_scan_dir = true;
628 } else if (rotation == ROTATION_ANGLE_90) {
629 *orthogonal_rotation = true;
630 *flip_horz_scan_dir = true;
631 } else if (rotation == ROTATION_ANGLE_270) {
632 *orthogonal_rotation = true;
633 *flip_vert_scan_dir = true;
634 }
635
636 if (horizontal_mirror)
637 *flip_horz_scan_dir = !*flip_horz_scan_dir;
638}
639
640int get_num_mpc_splits(struct pipe_ctx *pipe)
641{
642 int mpc_split_count = 0;
643 struct pipe_ctx *other_pipe = pipe->bottom_pipe;
644
645 while (other_pipe && other_pipe->plane_state == pipe->plane_state) {
646 mpc_split_count++;
647 other_pipe = other_pipe->bottom_pipe;
648 }
649 other_pipe = pipe->top_pipe;
650 while (other_pipe && other_pipe->plane_state == pipe->plane_state) {
651 mpc_split_count++;
652 other_pipe = other_pipe->top_pipe;
653 }
654
655 return mpc_split_count;
656}
657
658int get_num_odm_splits(struct pipe_ctx *pipe)
659{
660 int odm_split_count = 0;
661 struct pipe_ctx *next_pipe = pipe->next_odm_pipe;
662 while (next_pipe) {
663 odm_split_count++;
664 next_pipe = next_pipe->next_odm_pipe;
665 }
666 pipe = pipe->prev_odm_pipe;
667 while (pipe) {
668 odm_split_count++;
669 pipe = pipe->prev_odm_pipe;
670 }
671 return odm_split_count;
672}
673
674static void calculate_split_count_and_index(struct pipe_ctx *pipe_ctx, int *split_count, int *split_idx)
675{
676 *split_count = get_num_odm_splits(pipe_ctx);
677 *split_idx = 0;
678 if (*split_count == 0) {
679
680 struct pipe_ctx *split_pipe = pipe_ctx->top_pipe;
681
682 *split_count = get_num_mpc_splits(pipe_ctx);
683 while (split_pipe && split_pipe->plane_state == pipe_ctx->plane_state) {
684 (*split_idx)++;
685 split_pipe = split_pipe->top_pipe;
686 }
687 } else {
688
689 struct pipe_ctx *split_pipe = pipe_ctx->prev_odm_pipe;
690
691 while (split_pipe) {
692 (*split_idx)++;
693 split_pipe = split_pipe->prev_odm_pipe;
694 }
695 }
696}
697
698static void calculate_viewport(struct pipe_ctx *pipe_ctx)
699{
700 const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
701 const struct dc_stream_state *stream = pipe_ctx->stream;
702 struct scaler_data *data = &pipe_ctx->plane_res.scl_data;
703 struct rect surf_src = plane_state->src_rect;
704 struct rect clip, dest;
705 int vpc_div = (data->format == PIXEL_FORMAT_420BPP8
706 || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1;
707 int split_count = 0;
708 int split_idx = 0;
709 bool orthogonal_rotation, flip_y_start, flip_x_start;
710
711 calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx);
712
713 if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE ||
714 stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) {
715 split_count = 0;
716 split_idx = 0;
717 }
718
719
720
721
722 dest = plane_state->dst_rect;
723 clip.x = stream->src.x > plane_state->clip_rect.x ?
724 stream->src.x : plane_state->clip_rect.x;
725
726 clip.width = stream->src.x + stream->src.width <
727 plane_state->clip_rect.x + plane_state->clip_rect.width ?
728 stream->src.x + stream->src.width - clip.x :
729 plane_state->clip_rect.x + plane_state->clip_rect.width - clip.x ;
730
731 clip.y = stream->src.y > plane_state->clip_rect.y ?
732 stream->src.y : plane_state->clip_rect.y;
733
734 clip.height = stream->src.y + stream->src.height <
735 plane_state->clip_rect.y + plane_state->clip_rect.height ?
736 stream->src.y + stream->src.height - clip.y :
737 plane_state->clip_rect.y + plane_state->clip_rect.height - clip.y ;
738
739
740
741
742
743 get_vp_scan_direction(
744 plane_state->rotation,
745 plane_state->horizontal_mirror,
746 &orthogonal_rotation,
747 &flip_y_start,
748 &flip_x_start);
749
750 if (orthogonal_rotation) {
751 swap(clip.x, clip.y);
752 swap(clip.width, clip.height);
753 swap(dest.x, dest.y);
754 swap(dest.width, dest.height);
755 }
756 if (flip_x_start) {
757 clip.x = dest.x + dest.width - clip.x - clip.width;
758 dest.x = 0;
759 }
760 if (flip_y_start) {
761 clip.y = dest.y + dest.height - clip.y - clip.height;
762 dest.y = 0;
763 }
764
765
766
767
768 data->viewport.x = surf_src.x + (clip.x - dest.x) * surf_src.width / dest.width;
769 data->viewport.width = clip.width * surf_src.width / dest.width;
770
771 data->viewport.y = surf_src.y + (clip.y - dest.y) * surf_src.height / dest.height;
772 data->viewport.height = clip.height * surf_src.height / dest.height;
773
774
775 if (split_count) {
776
777
778
779 int epimo = 0;
780
781 if (orthogonal_rotation) {
782 if (flip_y_start)
783 split_idx = split_count - split_idx;
784
785 epimo = split_count - data->viewport.height % (split_count + 1);
786
787 data->viewport.y += (data->viewport.height / (split_count + 1)) * split_idx;
788 if (split_idx > epimo)
789 data->viewport.y += split_idx - epimo - 1;
790 data->viewport.height = data->viewport.height / (split_count + 1) + (split_idx > epimo ? 1 : 0);
791 } else {
792 if (flip_x_start)
793 split_idx = split_count - split_idx;
794
795 epimo = split_count - data->viewport.width % (split_count + 1);
796
797 data->viewport.x += (data->viewport.width / (split_count + 1)) * split_idx;
798 if (split_idx > epimo)
799 data->viewport.x += split_idx - epimo - 1;
800 data->viewport.width = data->viewport.width / (split_count + 1) + (split_idx > epimo ? 1 : 0);
801 }
802 }
803
804
805 data->viewport_c.x = data->viewport.x / vpc_div;
806 data->viewport_c.y = data->viewport.y / vpc_div;
807 data->inits.h_c = (data->viewport.x % vpc_div) != 0 ? dc_fixpt_half : dc_fixpt_zero;
808 data->inits.v_c = (data->viewport.y % vpc_div) != 0 ? dc_fixpt_half : dc_fixpt_zero;
809
810
811 data->viewport_c.width = (data->viewport.width + vpc_div - 1) / vpc_div;
812 data->viewport_c.height = (data->viewport.height + vpc_div - 1) / vpc_div;
813
814 data->viewport_unadjusted = data->viewport;
815 data->viewport_c_unadjusted = data->viewport_c;
816}
817
818static void calculate_recout(struct pipe_ctx *pipe_ctx)
819{
820 const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
821 const struct dc_stream_state *stream = pipe_ctx->stream;
822 struct scaler_data *data = &pipe_ctx->plane_res.scl_data;
823 struct rect surf_clip = plane_state->clip_rect;
824 bool pri_split_tb = pipe_ctx->bottom_pipe &&
825 pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state &&
826 stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM;
827 bool sec_split_tb = pipe_ctx->top_pipe &&
828 pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state &&
829 stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM;
830 int split_count = 0;
831 int split_idx = 0;
832
833 calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx);
834
835
836
837
838 if (!pipe_ctx->prev_odm_pipe) {
839 data->recout.x = stream->dst.x;
840 if (stream->src.x < surf_clip.x)
841 data->recout.x += (surf_clip.x - stream->src.x) * stream->dst.width
842 / stream->src.width;
843
844 } else
845 data->recout.x = 0;
846
847 if (stream->src.x > surf_clip.x)
848 surf_clip.width -= stream->src.x - surf_clip.x;
849 data->recout.width = surf_clip.width * stream->dst.width / stream->src.width;
850 if (data->recout.width + data->recout.x > stream->dst.x + stream->dst.width)
851 data->recout.width = stream->dst.x + stream->dst.width - data->recout.x;
852
853 data->recout.y = stream->dst.y;
854 if (stream->src.y < surf_clip.y)
855 data->recout.y += (surf_clip.y - stream->src.y) * stream->dst.height
856 / stream->src.height;
857 else if (stream->src.y > surf_clip.y)
858 surf_clip.height -= stream->src.y - surf_clip.y;
859
860 data->recout.height = surf_clip.height * stream->dst.height / stream->src.height;
861 if (data->recout.height + data->recout.y > stream->dst.y + stream->dst.height)
862 data->recout.height = stream->dst.y + stream->dst.height - data->recout.y;
863
864
865 if (sec_split_tb) {
866 data->recout.y += data->recout.height / 2;
867
868 data->recout.height = (data->recout.height + 1) / 2;
869 } else if (pri_split_tb)
870 data->recout.height /= 2;
871 else if (split_count) {
872
873
874
875 int epimo = split_count - data->recout.width % (split_count + 1);
876
877
878 if (!pipe_ctx->next_odm_pipe && !pipe_ctx->prev_odm_pipe) {
879 data->recout.x += (data->recout.width / (split_count + 1)) * split_idx;
880 if (split_idx > epimo)
881 data->recout.x += split_idx - epimo - 1;
882 }
883 data->recout.width = data->recout.width / (split_count + 1) + (split_idx > epimo ? 1 : 0);
884 }
885}
886
887static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx)
888{
889 const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
890 const struct dc_stream_state *stream = pipe_ctx->stream;
891 struct rect surf_src = plane_state->src_rect;
892 const int in_w = stream->src.width;
893 const int in_h = stream->src.height;
894 const int out_w = stream->dst.width;
895 const int out_h = stream->dst.height;
896
897
898 if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 ||
899 pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270)
900 swap(surf_src.height, surf_src.width);
901
902 pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_from_fraction(
903 surf_src.width,
904 plane_state->dst_rect.width);
905 pipe_ctx->plane_res.scl_data.ratios.vert = dc_fixpt_from_fraction(
906 surf_src.height,
907 plane_state->dst_rect.height);
908
909 if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE)
910 pipe_ctx->plane_res.scl_data.ratios.horz.value *= 2;
911 else if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM)
912 pipe_ctx->plane_res.scl_data.ratios.vert.value *= 2;
913
914 pipe_ctx->plane_res.scl_data.ratios.vert.value = div64_s64(
915 pipe_ctx->plane_res.scl_data.ratios.vert.value * in_h, out_h);
916 pipe_ctx->plane_res.scl_data.ratios.horz.value = div64_s64(
917 pipe_ctx->plane_res.scl_data.ratios.horz.value * in_w, out_w);
918
919 pipe_ctx->plane_res.scl_data.ratios.horz_c = pipe_ctx->plane_res.scl_data.ratios.horz;
920 pipe_ctx->plane_res.scl_data.ratios.vert_c = pipe_ctx->plane_res.scl_data.ratios.vert;
921
922 if (pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP8
923 || pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP10) {
924 pipe_ctx->plane_res.scl_data.ratios.horz_c.value /= 2;
925 pipe_ctx->plane_res.scl_data.ratios.vert_c.value /= 2;
926 }
927 pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_truncate(
928 pipe_ctx->plane_res.scl_data.ratios.horz, 19);
929 pipe_ctx->plane_res.scl_data.ratios.vert = dc_fixpt_truncate(
930 pipe_ctx->plane_res.scl_data.ratios.vert, 19);
931 pipe_ctx->plane_res.scl_data.ratios.horz_c = dc_fixpt_truncate(
932 pipe_ctx->plane_res.scl_data.ratios.horz_c, 19);
933 pipe_ctx->plane_res.scl_data.ratios.vert_c = dc_fixpt_truncate(
934 pipe_ctx->plane_res.scl_data.ratios.vert_c, 19);
935}
936
937static inline void adjust_vp_and_init_for_seamless_clip(
938 bool flip_scan_dir,
939 int recout_skip,
940 int src_size,
941 int taps,
942 struct fixed31_32 ratio,
943 struct fixed31_32 *init,
944 int *vp_offset,
945 int *vp_size)
946{
947 if (!flip_scan_dir) {
948
949 if ((*vp_offset + *vp_size) < src_size) {
950 int vp_clip = src_size - *vp_size - *vp_offset;
951 int int_part = dc_fixpt_floor(dc_fixpt_sub(*init, ratio));
952
953 int_part = int_part > 0 ? int_part : 0;
954 *vp_size += int_part < vp_clip ? int_part : vp_clip;
955 }
956
957
958 if (*vp_offset) {
959 int int_part;
960
961 *init = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_skip));
962 int_part = dc_fixpt_floor(*init) - *vp_offset;
963 if (int_part < taps) {
964 int int_adj = *vp_offset >= (taps - int_part) ?
965 (taps - int_part) : *vp_offset;
966 *vp_offset -= int_adj;
967 *vp_size += int_adj;
968 int_part += int_adj;
969 } else if (int_part > taps) {
970 *vp_offset += int_part - taps;
971 *vp_size -= int_part - taps;
972 int_part = taps;
973 }
974 init->value &= 0xffffffff;
975 *init = dc_fixpt_add_int(*init, int_part);
976 }
977 } else {
978
979 if (*vp_offset) {
980 int int_part = dc_fixpt_floor(dc_fixpt_sub(*init, ratio));
981
982 int_part = int_part > 0 ? int_part : 0;
983 *vp_size += int_part < *vp_offset ? int_part : *vp_offset;
984 *vp_offset -= int_part < *vp_offset ? int_part : *vp_offset;
985 }
986
987
988 if ((*vp_offset + *vp_size) < src_size) {
989 int int_part;
990 int end_offset = src_size - *vp_offset - *vp_size;
991
992
993
994
995
996 *init = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_skip));
997
998
999
1000
1001 int_part = dc_fixpt_floor(*init) - end_offset;
1002 if (int_part < taps) {
1003 int int_adj = end_offset >= (taps - int_part) ?
1004 (taps - int_part) : end_offset;
1005 *vp_size += int_adj;
1006 int_part += int_adj;
1007 } else if (int_part > taps) {
1008 *vp_size += int_part - taps;
1009 int_part = taps;
1010 }
1011 init->value &= 0xffffffff;
1012 *init = dc_fixpt_add_int(*init, int_part);
1013 }
1014 }
1015}
1016
1017static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx)
1018{
1019 const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
1020 const struct dc_stream_state *stream = pipe_ctx->stream;
1021 struct pipe_ctx *odm_pipe = pipe_ctx;
1022 struct scaler_data *data = &pipe_ctx->plane_res.scl_data;
1023 struct rect src = pipe_ctx->plane_state->src_rect;
1024 int recout_skip_h, recout_skip_v, surf_size_h, surf_size_v;
1025 int vpc_div = (data->format == PIXEL_FORMAT_420BPP8
1026 || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1;
1027 bool orthogonal_rotation, flip_vert_scan_dir, flip_horz_scan_dir;
1028 int odm_idx = 0;
1029
1030
1031
1032
1033 get_vp_scan_direction(
1034 plane_state->rotation,
1035 plane_state->horizontal_mirror,
1036 &orthogonal_rotation,
1037 &flip_vert_scan_dir,
1038 &flip_horz_scan_dir);
1039
1040
1041 surf_size_h = src.x + src.width;
1042 surf_size_v = src.y + src.height;
1043 if (flip_horz_scan_dir)
1044 src.x = 0;
1045 if (flip_vert_scan_dir)
1046 src.y = 0;
1047 if (orthogonal_rotation) {
1048 swap(src.x, src.y);
1049 swap(src.width, src.height);
1050 }
1051
1052
1053 while (odm_pipe->prev_odm_pipe) {
1054 odm_idx++;
1055 odm_pipe = odm_pipe->prev_odm_pipe;
1056 }
1057
1058 recout_skip_h = odm_idx * data->recout.width;
1059
1060
1061
1062
1063
1064 recout_skip_h += odm_pipe->plane_res.scl_data.recout.x
1065 - (stream->dst.x + (plane_state->dst_rect.x - stream->src.x)
1066 * stream->dst.width / stream->src.width -
1067 src.x * plane_state->dst_rect.width / src.width
1068 * stream->dst.width / stream->src.width);
1069
1070
1071 recout_skip_v = data->recout.y - (stream->dst.y + (plane_state->dst_rect.y - stream->src.y)
1072 * stream->dst.height / stream->src.height -
1073 src.y * plane_state->dst_rect.height / src.height
1074 * stream->dst.height / stream->src.height);
1075 if (orthogonal_rotation)
1076 swap(recout_skip_h, recout_skip_v);
1077
1078
1079
1080
1081
1082
1083 data->inits.h = dc_fixpt_truncate(dc_fixpt_div_int(
1084 dc_fixpt_add_int(data->ratios.horz, data->taps.h_taps + 1), 2), 19);
1085
1086 data->inits.h_c = dc_fixpt_truncate(dc_fixpt_add(data->inits.h_c, dc_fixpt_div_int(
1087 dc_fixpt_add_int(data->ratios.horz_c, data->taps.h_taps_c + 1), 2)), 19);
1088
1089 data->inits.v = dc_fixpt_truncate(dc_fixpt_div_int(
1090 dc_fixpt_add_int(data->ratios.vert, data->taps.v_taps + 1), 2), 19);
1091
1092 data->inits.v_c = dc_fixpt_truncate(dc_fixpt_add(data->inits.v_c, dc_fixpt_div_int(
1093 dc_fixpt_add_int(data->ratios.vert_c, data->taps.v_taps_c + 1), 2)), 19);
1094
1095
1096
1097
1098
1099 adjust_vp_and_init_for_seamless_clip(
1100 flip_horz_scan_dir,
1101 recout_skip_h,
1102 surf_size_h,
1103 orthogonal_rotation ? data->taps.v_taps : data->taps.h_taps,
1104 orthogonal_rotation ? data->ratios.vert : data->ratios.horz,
1105 orthogonal_rotation ? &data->inits.v : &data->inits.h,
1106 &data->viewport.x,
1107 &data->viewport.width);
1108 adjust_vp_and_init_for_seamless_clip(
1109 flip_horz_scan_dir,
1110 recout_skip_h,
1111 surf_size_h / vpc_div,
1112 orthogonal_rotation ? data->taps.v_taps_c : data->taps.h_taps_c,
1113 orthogonal_rotation ? data->ratios.vert_c : data->ratios.horz_c,
1114 orthogonal_rotation ? &data->inits.v_c : &data->inits.h_c,
1115 &data->viewport_c.x,
1116 &data->viewport_c.width);
1117 adjust_vp_and_init_for_seamless_clip(
1118 flip_vert_scan_dir,
1119 recout_skip_v,
1120 surf_size_v,
1121 orthogonal_rotation ? data->taps.h_taps : data->taps.v_taps,
1122 orthogonal_rotation ? data->ratios.horz : data->ratios.vert,
1123 orthogonal_rotation ? &data->inits.h : &data->inits.v,
1124 &data->viewport.y,
1125 &data->viewport.height);
1126 adjust_vp_and_init_for_seamless_clip(
1127 flip_vert_scan_dir,
1128 recout_skip_v,
1129 surf_size_v / vpc_div,
1130 orthogonal_rotation ? data->taps.h_taps_c : data->taps.v_taps_c,
1131 orthogonal_rotation ? data->ratios.horz_c : data->ratios.vert_c,
1132 orthogonal_rotation ? &data->inits.h_c : &data->inits.v_c,
1133 &data->viewport_c.y,
1134 &data->viewport_c.height);
1135
1136
1137 data->inits.v_bot = dc_fixpt_add(data->inits.v, data->ratios.vert);
1138 data->inits.v_c_bot = dc_fixpt_add(data->inits.v_c, data->ratios.vert_c);
1139
1140}
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163static int shift_border_left_to_dst(struct pipe_ctx *pipe_ctx)
1164{
1165 int store_h_border_left = pipe_ctx->stream->timing.h_border_left;
1166
1167 if (store_h_border_left) {
1168 pipe_ctx->stream->timing.h_border_left = 0;
1169 pipe_ctx->stream->dst.x += store_h_border_left;
1170 }
1171 return store_h_border_left;
1172}
1173
1174static void restore_border_left_from_dst(struct pipe_ctx *pipe_ctx,
1175 int store_h_border_left)
1176{
1177 pipe_ctx->stream->dst.x -= store_h_border_left;
1178 pipe_ctx->stream->timing.h_border_left = store_h_border_left;
1179}
1180
1181bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
1182{
1183 const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
1184 struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
1185 bool res = false;
1186 int store_h_border_left = shift_border_left_to_dst(pipe_ctx);
1187 DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
1188
1189
1190
1191
1192 pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface(
1193 pipe_ctx->plane_state->format);
1194
1195 calculate_scaling_ratios(pipe_ctx);
1196
1197 calculate_viewport(pipe_ctx);
1198
1199 if (pipe_ctx->plane_res.scl_data.viewport.height < MIN_VIEWPORT_SIZE ||
1200 pipe_ctx->plane_res.scl_data.viewport.width < MIN_VIEWPORT_SIZE) {
1201 if (store_h_border_left) {
1202 restore_border_left_from_dst(pipe_ctx,
1203 store_h_border_left);
1204 }
1205 return false;
1206 }
1207
1208 calculate_recout(pipe_ctx);
1209
1210
1211
1212
1213
1214 pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP;
1215 pipe_ctx->plane_res.scl_data.lb_params.alpha_en = plane_state->per_pixel_alpha;
1216
1217 pipe_ctx->plane_res.scl_data.recout.x += timing->h_border_left;
1218 pipe_ctx->plane_res.scl_data.recout.y += timing->v_border_top;
1219
1220 pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable +
1221 store_h_border_left + timing->h_border_right;
1222 pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable +
1223 timing->v_border_top + timing->v_border_bottom;
1224 if (pipe_ctx->next_odm_pipe || pipe_ctx->prev_odm_pipe)
1225 pipe_ctx->plane_res.scl_data.h_active /= get_num_odm_splits(pipe_ctx) + 1;
1226
1227
1228 if (pipe_ctx->plane_res.xfm != NULL)
1229 res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps(
1230 pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality);
1231
1232 if (pipe_ctx->plane_res.dpp != NULL)
1233 res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps(
1234 pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality);
1235
1236
1237 if (!res) {
1238
1239 pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP;
1240
1241 if (pipe_ctx->plane_res.xfm != NULL)
1242 res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps(
1243 pipe_ctx->plane_res.xfm,
1244 &pipe_ctx->plane_res.scl_data,
1245 &plane_state->scaling_quality);
1246
1247 if (pipe_ctx->plane_res.dpp != NULL)
1248 res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps(
1249 pipe_ctx->plane_res.dpp,
1250 &pipe_ctx->plane_res.scl_data,
1251 &plane_state->scaling_quality);
1252 }
1253
1254 if (res)
1255
1256 calculate_inits_and_adj_vp(pipe_ctx);
1257
1258 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"
1259 "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",
1260 __func__,
1261 pipe_ctx->pipe_idx,
1262 pipe_ctx->plane_res.scl_data.viewport.height,
1263 pipe_ctx->plane_res.scl_data.viewport.width,
1264 pipe_ctx->plane_res.scl_data.viewport.x,
1265 pipe_ctx->plane_res.scl_data.viewport.y,
1266 pipe_ctx->plane_res.scl_data.recout.height,
1267 pipe_ctx->plane_res.scl_data.recout.width,
1268 pipe_ctx->plane_res.scl_data.recout.x,
1269 pipe_ctx->plane_res.scl_data.recout.y,
1270 pipe_ctx->plane_res.scl_data.h_active,
1271 pipe_ctx->plane_res.scl_data.v_active,
1272 plane_state->src_rect.height,
1273 plane_state->src_rect.width,
1274 plane_state->src_rect.x,
1275 plane_state->src_rect.y,
1276 plane_state->dst_rect.height,
1277 plane_state->dst_rect.width,
1278 plane_state->dst_rect.x,
1279 plane_state->dst_rect.y,
1280 plane_state->clip_rect.height,
1281 plane_state->clip_rect.width,
1282 plane_state->clip_rect.x,
1283 plane_state->clip_rect.y);
1284
1285 if (store_h_border_left)
1286 restore_border_left_from_dst(pipe_ctx, store_h_border_left);
1287
1288 return res;
1289}
1290
1291
1292enum dc_status resource_build_scaling_params_for_context(
1293 const struct dc *dc,
1294 struct dc_state *context)
1295{
1296 int i;
1297
1298 for (i = 0; i < MAX_PIPES; i++) {
1299 if (context->res_ctx.pipe_ctx[i].plane_state != NULL &&
1300 context->res_ctx.pipe_ctx[i].stream != NULL)
1301 if (!resource_build_scaling_params(&context->res_ctx.pipe_ctx[i]))
1302 return DC_FAIL_SCALING;
1303 }
1304
1305 return DC_OK;
1306}
1307
1308struct pipe_ctx *find_idle_secondary_pipe(
1309 struct resource_context *res_ctx,
1310 const struct resource_pool *pool,
1311 const struct pipe_ctx *primary_pipe)
1312{
1313 int i;
1314 struct pipe_ctx *secondary_pipe = NULL;
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344 if (primary_pipe) {
1345 int preferred_pipe_idx = (pool->pipe_count - 1) - primary_pipe->pipe_idx;
1346 if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
1347 secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
1348 secondary_pipe->pipe_idx = preferred_pipe_idx;
1349 }
1350 }
1351
1352
1353
1354
1355
1356 if (!secondary_pipe)
1357 for (i = pool->pipe_count - 1; i >= 0; i--) {
1358 if (res_ctx->pipe_ctx[i].stream == NULL) {
1359 secondary_pipe = &res_ctx->pipe_ctx[i];
1360 secondary_pipe->pipe_idx = i;
1361 break;
1362 }
1363 }
1364
1365 return secondary_pipe;
1366}
1367
1368struct pipe_ctx *resource_get_head_pipe_for_stream(
1369 struct resource_context *res_ctx,
1370 struct dc_stream_state *stream)
1371{
1372 int i;
1373
1374 for (i = 0; i < MAX_PIPES; i++) {
1375 if (res_ctx->pipe_ctx[i].stream == stream
1376 && !res_ctx->pipe_ctx[i].top_pipe
1377 && !res_ctx->pipe_ctx[i].prev_odm_pipe)
1378 return &res_ctx->pipe_ctx[i];
1379 }
1380 return NULL;
1381}
1382
1383static struct pipe_ctx *resource_get_tail_pipe(
1384 struct resource_context *res_ctx,
1385 struct pipe_ctx *head_pipe)
1386{
1387 struct pipe_ctx *tail_pipe;
1388
1389 tail_pipe = head_pipe->bottom_pipe;
1390
1391 while (tail_pipe) {
1392 head_pipe = tail_pipe;
1393 tail_pipe = tail_pipe->bottom_pipe;
1394 }
1395
1396 return head_pipe;
1397}
1398
1399
1400
1401
1402
1403static struct pipe_ctx *acquire_free_pipe_for_head(
1404 struct dc_state *context,
1405 const struct resource_pool *pool,
1406 struct pipe_ctx *head_pipe)
1407{
1408 int i;
1409 struct resource_context *res_ctx = &context->res_ctx;
1410
1411 if (!head_pipe->plane_state)
1412 return head_pipe;
1413
1414
1415 for (i = pool->pipe_count - 1; i >= 0; i--) {
1416 if (res_ctx->pipe_ctx[i].stream == head_pipe->stream &&
1417 !res_ctx->pipe_ctx[i].plane_state) {
1418 return &res_ctx->pipe_ctx[i];
1419 }
1420 }
1421
1422
1423
1424
1425
1426
1427 if (!pool->funcs->acquire_idle_pipe_for_layer)
1428 return NULL;
1429
1430 return pool->funcs->acquire_idle_pipe_for_layer(context, pool, head_pipe->stream);
1431}
1432
1433#if defined(CONFIG_DRM_AMD_DC_DCN)
1434static int acquire_first_split_pipe(
1435 struct resource_context *res_ctx,
1436 const struct resource_pool *pool,
1437 struct dc_stream_state *stream)
1438{
1439 int i;
1440
1441 for (i = 0; i < pool->pipe_count; i++) {
1442 struct pipe_ctx *split_pipe = &res_ctx->pipe_ctx[i];
1443
1444 if (split_pipe->top_pipe &&
1445 split_pipe->top_pipe->plane_state == split_pipe->plane_state) {
1446 split_pipe->top_pipe->bottom_pipe = split_pipe->bottom_pipe;
1447 if (split_pipe->bottom_pipe)
1448 split_pipe->bottom_pipe->top_pipe = split_pipe->top_pipe;
1449
1450 if (split_pipe->top_pipe->plane_state)
1451 resource_build_scaling_params(split_pipe->top_pipe);
1452
1453 memset(split_pipe, 0, sizeof(*split_pipe));
1454 split_pipe->stream_res.tg = pool->timing_generators[i];
1455 split_pipe->plane_res.hubp = pool->hubps[i];
1456 split_pipe->plane_res.ipp = pool->ipps[i];
1457 split_pipe->plane_res.dpp = pool->dpps[i];
1458 split_pipe->stream_res.opp = pool->opps[i];
1459 split_pipe->plane_res.mpcc_inst = pool->dpps[i]->inst;
1460 split_pipe->pipe_idx = i;
1461
1462 split_pipe->stream = stream;
1463 return i;
1464 }
1465 }
1466 return -1;
1467}
1468#endif
1469
1470bool dc_add_plane_to_context(
1471 const struct dc *dc,
1472 struct dc_stream_state *stream,
1473 struct dc_plane_state *plane_state,
1474 struct dc_state *context)
1475{
1476 int i;
1477 struct resource_pool *pool = dc->res_pool;
1478 struct pipe_ctx *head_pipe, *tail_pipe, *free_pipe;
1479 struct dc_stream_status *stream_status = NULL;
1480
1481 for (i = 0; i < context->stream_count; i++)
1482 if (context->streams[i] == stream) {
1483 stream_status = &context->stream_status[i];
1484 break;
1485 }
1486 if (stream_status == NULL) {
1487 dm_error("Existing stream not found; failed to attach surface!\n");
1488 return false;
1489 }
1490
1491
1492 if (stream_status->plane_count == MAX_SURFACE_NUM) {
1493 dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n",
1494 plane_state, MAX_SURFACE_NUM);
1495 return false;
1496 }
1497
1498 head_pipe = resource_get_head_pipe_for_stream(&context->res_ctx, stream);
1499
1500 if (!head_pipe) {
1501 dm_error("Head pipe not found for stream_state %p !\n", stream);
1502 return false;
1503 }
1504
1505
1506 dc_plane_state_retain(plane_state);
1507
1508 while (head_pipe) {
1509 free_pipe = acquire_free_pipe_for_head(context, pool, head_pipe);
1510
1511 #if defined(CONFIG_DRM_AMD_DC_DCN)
1512 if (!free_pipe) {
1513 int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream);
1514 if (pipe_idx >= 0)
1515 free_pipe = &context->res_ctx.pipe_ctx[pipe_idx];
1516 }
1517 #endif
1518 if (!free_pipe) {
1519 dc_plane_state_release(plane_state);
1520 return false;
1521 }
1522
1523 free_pipe->plane_state = plane_state;
1524
1525 if (head_pipe != free_pipe) {
1526 tail_pipe = resource_get_tail_pipe(&context->res_ctx, head_pipe);
1527 ASSERT(tail_pipe);
1528 free_pipe->stream_res.tg = tail_pipe->stream_res.tg;
1529 free_pipe->stream_res.abm = tail_pipe->stream_res.abm;
1530 free_pipe->stream_res.opp = tail_pipe->stream_res.opp;
1531 free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc;
1532 free_pipe->stream_res.audio = tail_pipe->stream_res.audio;
1533 free_pipe->clock_source = tail_pipe->clock_source;
1534 free_pipe->top_pipe = tail_pipe;
1535 tail_pipe->bottom_pipe = free_pipe;
1536 if (!free_pipe->next_odm_pipe && tail_pipe->next_odm_pipe && tail_pipe->next_odm_pipe->bottom_pipe) {
1537 free_pipe->next_odm_pipe = tail_pipe->next_odm_pipe->bottom_pipe;
1538 tail_pipe->next_odm_pipe->bottom_pipe->prev_odm_pipe = free_pipe;
1539 }
1540 if (!free_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe->bottom_pipe) {
1541 free_pipe->prev_odm_pipe = tail_pipe->prev_odm_pipe->bottom_pipe;
1542 tail_pipe->prev_odm_pipe->bottom_pipe->next_odm_pipe = free_pipe;
1543 }
1544 }
1545 head_pipe = head_pipe->next_odm_pipe;
1546 }
1547
1548 stream_status->plane_states[stream_status->plane_count] = plane_state;
1549
1550 stream_status->plane_count++;
1551
1552 return true;
1553}
1554
1555bool dc_remove_plane_from_context(
1556 const struct dc *dc,
1557 struct dc_stream_state *stream,
1558 struct dc_plane_state *plane_state,
1559 struct dc_state *context)
1560{
1561 int i;
1562 struct dc_stream_status *stream_status = NULL;
1563 struct resource_pool *pool = dc->res_pool;
1564
1565 for (i = 0; i < context->stream_count; i++)
1566 if (context->streams[i] == stream) {
1567 stream_status = &context->stream_status[i];
1568 break;
1569 }
1570
1571 if (stream_status == NULL) {
1572 dm_error("Existing stream not found; failed to remove plane.\n");
1573 return false;
1574 }
1575
1576
1577 for (i = pool->pipe_count - 1; i >= 0; i--) {
1578 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1579
1580 if (pipe_ctx->plane_state == plane_state) {
1581 if (pipe_ctx->top_pipe)
1582 pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe;
1583
1584
1585
1586
1587
1588 if (pipe_ctx->bottom_pipe && pipe_ctx->top_pipe)
1589 pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe;
1590
1591
1592
1593
1594
1595 if (!pipe_ctx->top_pipe)
1596 pipe_ctx->plane_state = NULL;
1597 else
1598 memset(pipe_ctx, 0, sizeof(*pipe_ctx));
1599 }
1600 }
1601
1602
1603 for (i = 0; i < stream_status->plane_count; i++) {
1604 if (stream_status->plane_states[i] == plane_state) {
1605
1606 dc_plane_state_release(stream_status->plane_states[i]);
1607 break;
1608 }
1609 }
1610
1611 if (i == stream_status->plane_count) {
1612 dm_error("Existing plane_state not found; failed to detach it!\n");
1613 return false;
1614 }
1615
1616 stream_status->plane_count--;
1617
1618
1619 for (; i < stream_status->plane_count; i++)
1620 stream_status->plane_states[i] = stream_status->plane_states[i + 1];
1621
1622 stream_status->plane_states[stream_status->plane_count] = NULL;
1623
1624 return true;
1625}
1626
1627bool dc_rem_all_planes_for_stream(
1628 const struct dc *dc,
1629 struct dc_stream_state *stream,
1630 struct dc_state *context)
1631{
1632 int i, old_plane_count;
1633 struct dc_stream_status *stream_status = NULL;
1634 struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 };
1635
1636 for (i = 0; i < context->stream_count; i++)
1637 if (context->streams[i] == stream) {
1638 stream_status = &context->stream_status[i];
1639 break;
1640 }
1641
1642 if (stream_status == NULL) {
1643 dm_error("Existing stream %p not found!\n", stream);
1644 return false;
1645 }
1646
1647 old_plane_count = stream_status->plane_count;
1648
1649 for (i = 0; i < old_plane_count; i++)
1650 del_planes[i] = stream_status->plane_states[i];
1651
1652 for (i = 0; i < old_plane_count; i++)
1653 if (!dc_remove_plane_from_context(dc, stream, del_planes[i], context))
1654 return false;
1655
1656 return true;
1657}
1658
1659static bool add_all_planes_for_stream(
1660 const struct dc *dc,
1661 struct dc_stream_state *stream,
1662 const struct dc_validation_set set[],
1663 int set_count,
1664 struct dc_state *context)
1665{
1666 int i, j;
1667
1668 for (i = 0; i < set_count; i++)
1669 if (set[i].stream == stream)
1670 break;
1671
1672 if (i == set_count) {
1673 dm_error("Stream %p not found in set!\n", stream);
1674 return false;
1675 }
1676
1677 for (j = 0; j < set[i].plane_count; j++)
1678 if (!dc_add_plane_to_context(dc, stream, set[i].plane_states[j], context))
1679 return false;
1680
1681 return true;
1682}
1683
1684bool dc_add_all_planes_for_stream(
1685 const struct dc *dc,
1686 struct dc_stream_state *stream,
1687 struct dc_plane_state * const *plane_states,
1688 int plane_count,
1689 struct dc_state *context)
1690{
1691 struct dc_validation_set set;
1692 int i;
1693
1694 set.stream = stream;
1695 set.plane_count = plane_count;
1696
1697 for (i = 0; i < plane_count; i++)
1698 set.plane_states[i] = plane_states[i];
1699
1700 return add_all_planes_for_stream(dc, stream, &set, 1, context);
1701}
1702
1703static bool is_timing_changed(struct dc_stream_state *cur_stream,
1704 struct dc_stream_state *new_stream)
1705{
1706 if (cur_stream == NULL)
1707 return true;
1708
1709
1710
1711
1712 if (cur_stream->sink != new_stream->sink)
1713 return true;
1714
1715
1716 if (cur_stream->output_color_space != new_stream->output_color_space)
1717 return true;
1718
1719 return memcmp(
1720 &cur_stream->timing,
1721 &new_stream->timing,
1722 sizeof(struct dc_crtc_timing)) != 0;
1723}
1724
1725static bool are_stream_backends_same(
1726 struct dc_stream_state *stream_a, struct dc_stream_state *stream_b)
1727{
1728 if (stream_a == stream_b)
1729 return true;
1730
1731 if (stream_a == NULL || stream_b == NULL)
1732 return false;
1733
1734 if (is_timing_changed(stream_a, stream_b))
1735 return false;
1736
1737 if (stream_a->dpms_off != stream_b->dpms_off)
1738 return false;
1739
1740 return true;
1741}
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751bool dc_is_stream_unchanged(
1752 struct dc_stream_state *old_stream, struct dc_stream_state *stream)
1753{
1754
1755 if (!are_stream_backends_same(old_stream, stream))
1756 return false;
1757
1758 if (old_stream->ignore_msa_timing_param != stream->ignore_msa_timing_param)
1759 return false;
1760
1761 return true;
1762}
1763
1764
1765
1766
1767bool dc_is_stream_scaling_unchanged(
1768 struct dc_stream_state *old_stream, struct dc_stream_state *stream)
1769{
1770 if (old_stream == stream)
1771 return true;
1772
1773 if (old_stream == NULL || stream == NULL)
1774 return false;
1775
1776 if (memcmp(&old_stream->src,
1777 &stream->src,
1778 sizeof(struct rect)) != 0)
1779 return false;
1780
1781 if (memcmp(&old_stream->dst,
1782 &stream->dst,
1783 sizeof(struct rect)) != 0)
1784 return false;
1785
1786 return true;
1787}
1788
1789static void update_stream_engine_usage(
1790 struct resource_context *res_ctx,
1791 const struct resource_pool *pool,
1792 struct stream_encoder *stream_enc,
1793 bool acquired)
1794{
1795 int i;
1796
1797 for (i = 0; i < pool->stream_enc_count; i++) {
1798 if (pool->stream_enc[i] == stream_enc)
1799 res_ctx->is_stream_enc_acquired[i] = acquired;
1800 }
1801}
1802
1803
1804void update_audio_usage(
1805 struct resource_context *res_ctx,
1806 const struct resource_pool *pool,
1807 struct audio *audio,
1808 bool acquired)
1809{
1810 int i;
1811 for (i = 0; i < pool->audio_count; i++) {
1812 if (pool->audios[i] == audio)
1813 res_ctx->is_audio_acquired[i] = acquired;
1814 }
1815}
1816
1817static int acquire_first_free_pipe(
1818 struct resource_context *res_ctx,
1819 const struct resource_pool *pool,
1820 struct dc_stream_state *stream)
1821{
1822 int i;
1823
1824 for (i = 0; i < pool->pipe_count; i++) {
1825 if (!res_ctx->pipe_ctx[i].stream) {
1826 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
1827
1828 pipe_ctx->stream_res.tg = pool->timing_generators[i];
1829 pipe_ctx->plane_res.mi = pool->mis[i];
1830 pipe_ctx->plane_res.hubp = pool->hubps[i];
1831 pipe_ctx->plane_res.ipp = pool->ipps[i];
1832 pipe_ctx->plane_res.xfm = pool->transforms[i];
1833 pipe_ctx->plane_res.dpp = pool->dpps[i];
1834 pipe_ctx->stream_res.opp = pool->opps[i];
1835 if (pool->dpps[i])
1836 pipe_ctx->plane_res.mpcc_inst = pool->dpps[i]->inst;
1837 pipe_ctx->pipe_idx = i;
1838
1839
1840 pipe_ctx->stream = stream;
1841 return i;
1842 }
1843 }
1844 return -1;
1845}
1846
1847static struct audio *find_first_free_audio(
1848 struct resource_context *res_ctx,
1849 const struct resource_pool *pool,
1850 enum engine_id id,
1851 enum dce_version dc_version)
1852{
1853 int i, available_audio_count;
1854
1855 available_audio_count = pool->audio_count;
1856
1857 for (i = 0; i < available_audio_count; i++) {
1858 if ((res_ctx->is_audio_acquired[i] == false) && (res_ctx->is_stream_enc_acquired[i] == true)) {
1859
1860 if (id != i)
1861 continue;
1862 return pool->audios[i];
1863 }
1864 }
1865
1866
1867 if ((id < available_audio_count) && (res_ctx->is_audio_acquired[id] == false)) {
1868 return pool->audios[id];
1869 }
1870
1871 for (i = 0; i < available_audio_count; i++) {
1872 if (res_ctx->is_audio_acquired[i] == false) {
1873 return pool->audios[i];
1874 }
1875 }
1876 return 0;
1877}
1878
1879
1880
1881
1882enum dc_status dc_add_stream_to_ctx(
1883 struct dc *dc,
1884 struct dc_state *new_ctx,
1885 struct dc_stream_state *stream)
1886{
1887 enum dc_status res;
1888 DC_LOGGER_INIT(dc->ctx->logger);
1889
1890 if (new_ctx->stream_count >= dc->res_pool->timing_generator_count) {
1891 DC_LOG_WARNING("Max streams reached, can't add stream %p !\n", stream);
1892 return DC_ERROR_UNEXPECTED;
1893 }
1894
1895 new_ctx->streams[new_ctx->stream_count] = stream;
1896 dc_stream_retain(stream);
1897 new_ctx->stream_count++;
1898
1899 res = dc->res_pool->funcs->add_stream_to_ctx(dc, new_ctx, stream);
1900 if (res != DC_OK)
1901 DC_LOG_WARNING("Adding stream %p to context failed with err %d!\n", stream, res);
1902
1903 return res;
1904}
1905
1906
1907
1908
1909enum dc_status dc_remove_stream_from_ctx(
1910 struct dc *dc,
1911 struct dc_state *new_ctx,
1912 struct dc_stream_state *stream)
1913{
1914 int i;
1915 struct dc_context *dc_ctx = dc->ctx;
1916 struct pipe_ctx *del_pipe = resource_get_head_pipe_for_stream(&new_ctx->res_ctx, stream);
1917 struct pipe_ctx *odm_pipe;
1918
1919 if (!del_pipe) {
1920 DC_ERROR("Pipe not found for stream %p !\n", stream);
1921 return DC_ERROR_UNEXPECTED;
1922 }
1923
1924 odm_pipe = del_pipe->next_odm_pipe;
1925
1926
1927 ASSERT(del_pipe->stream_res.stream_enc);
1928 update_stream_engine_usage(
1929 &new_ctx->res_ctx,
1930 dc->res_pool,
1931 del_pipe->stream_res.stream_enc,
1932 false);
1933
1934 if (dc->res_pool->funcs->link_enc_unassign)
1935 dc->res_pool->funcs->link_enc_unassign(new_ctx, del_pipe->stream);
1936
1937 if (del_pipe->stream_res.audio)
1938 update_audio_usage(
1939 &new_ctx->res_ctx,
1940 dc->res_pool,
1941 del_pipe->stream_res.audio,
1942 false);
1943
1944 resource_unreference_clock_source(&new_ctx->res_ctx,
1945 dc->res_pool,
1946 del_pipe->clock_source);
1947
1948 if (dc->res_pool->funcs->remove_stream_from_ctx)
1949 dc->res_pool->funcs->remove_stream_from_ctx(dc, new_ctx, stream);
1950
1951 while (odm_pipe) {
1952 struct pipe_ctx *next_odm_pipe = odm_pipe->next_odm_pipe;
1953
1954 memset(odm_pipe, 0, sizeof(*odm_pipe));
1955 odm_pipe = next_odm_pipe;
1956 }
1957 memset(del_pipe, 0, sizeof(*del_pipe));
1958
1959 for (i = 0; i < new_ctx->stream_count; i++)
1960 if (new_ctx->streams[i] == stream)
1961 break;
1962
1963 if (new_ctx->streams[i] != stream) {
1964 DC_ERROR("Context doesn't have stream %p !\n", stream);
1965 return DC_ERROR_UNEXPECTED;
1966 }
1967
1968 dc_stream_release(new_ctx->streams[i]);
1969 new_ctx->stream_count--;
1970
1971
1972 for (; i < new_ctx->stream_count; i++) {
1973 new_ctx->streams[i] = new_ctx->streams[i + 1];
1974 new_ctx->stream_status[i] = new_ctx->stream_status[i + 1];
1975 }
1976
1977 new_ctx->streams[new_ctx->stream_count] = NULL;
1978 memset(
1979 &new_ctx->stream_status[new_ctx->stream_count],
1980 0,
1981 sizeof(new_ctx->stream_status[0]));
1982
1983 return DC_OK;
1984}
1985
1986static struct dc_stream_state *find_pll_sharable_stream(
1987 struct dc_stream_state *stream_needs_pll,
1988 struct dc_state *context)
1989{
1990 int i;
1991
1992 for (i = 0; i < context->stream_count; i++) {
1993 struct dc_stream_state *stream_has_pll = context->streams[i];
1994
1995
1996 if (resource_are_streams_timing_synchronizable(
1997 stream_needs_pll, stream_has_pll)
1998 && !dc_is_dp_signal(stream_has_pll->signal)
1999 && stream_has_pll->link->connector_signal
2000 != SIGNAL_TYPE_VIRTUAL)
2001 return stream_has_pll;
2002
2003 }
2004
2005 return NULL;
2006}
2007
2008static int get_norm_pix_clk(const struct dc_crtc_timing *timing)
2009{
2010 uint32_t pix_clk = timing->pix_clk_100hz;
2011 uint32_t normalized_pix_clk = pix_clk;
2012
2013 if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
2014 pix_clk /= 2;
2015 if (timing->pixel_encoding != PIXEL_ENCODING_YCBCR422) {
2016 switch (timing->display_color_depth) {
2017 case COLOR_DEPTH_666:
2018 case COLOR_DEPTH_888:
2019 normalized_pix_clk = pix_clk;
2020 break;
2021 case COLOR_DEPTH_101010:
2022 normalized_pix_clk = (pix_clk * 30) / 24;
2023 break;
2024 case COLOR_DEPTH_121212:
2025 normalized_pix_clk = (pix_clk * 36) / 24;
2026 break;
2027 case COLOR_DEPTH_161616:
2028 normalized_pix_clk = (pix_clk * 48) / 24;
2029 break;
2030 default:
2031 ASSERT(0);
2032 break;
2033 }
2034 }
2035 return normalized_pix_clk;
2036}
2037
2038static void calculate_phy_pix_clks(struct dc_stream_state *stream)
2039{
2040
2041 if (dc_is_hdmi_signal(stream->signal))
2042 stream->phy_pix_clk = get_norm_pix_clk(
2043 &stream->timing) / 10;
2044 else
2045 stream->phy_pix_clk =
2046 stream->timing.pix_clk_100hz / 10;
2047
2048 if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
2049 stream->phy_pix_clk *= 2;
2050}
2051
2052static int acquire_resource_from_hw_enabled_state(
2053 struct resource_context *res_ctx,
2054 const struct resource_pool *pool,
2055 struct dc_stream_state *stream)
2056{
2057 struct dc_link *link = stream->link;
2058 unsigned int i, inst, tg_inst = 0;
2059
2060
2061 if (!link->link_enc->funcs->is_dig_enabled(link->link_enc))
2062 return -1;
2063
2064 inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);
2065
2066 if (inst == ENGINE_ID_UNKNOWN)
2067 return -1;
2068
2069 for (i = 0; i < pool->stream_enc_count; i++) {
2070 if (pool->stream_enc[i]->id == inst) {
2071 tg_inst = pool->stream_enc[i]->funcs->dig_source_otg(
2072 pool->stream_enc[i]);
2073 break;
2074 }
2075 }
2076
2077
2078 if (i == pool->stream_enc_count)
2079 return -1;
2080
2081 if (tg_inst >= pool->timing_generator_count)
2082 return -1;
2083
2084 if (!res_ctx->pipe_ctx[tg_inst].stream) {
2085 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[tg_inst];
2086
2087 pipe_ctx->stream_res.tg = pool->timing_generators[tg_inst];
2088 pipe_ctx->plane_res.mi = pool->mis[tg_inst];
2089 pipe_ctx->plane_res.hubp = pool->hubps[tg_inst];
2090 pipe_ctx->plane_res.ipp = pool->ipps[tg_inst];
2091 pipe_ctx->plane_res.xfm = pool->transforms[tg_inst];
2092 pipe_ctx->plane_res.dpp = pool->dpps[tg_inst];
2093 pipe_ctx->stream_res.opp = pool->opps[tg_inst];
2094
2095 if (pool->dpps[tg_inst]) {
2096 pipe_ctx->plane_res.mpcc_inst = pool->dpps[tg_inst]->inst;
2097
2098
2099 if (pool->mpc->funcs->read_mpcc_state) {
2100 struct mpcc_state s = {0};
2101
2102 pool->mpc->funcs->read_mpcc_state(pool->mpc, pipe_ctx->plane_res.mpcc_inst, &s);
2103
2104 if (s.dpp_id < MAX_MPCC)
2105 pool->mpc->mpcc_array[pipe_ctx->plane_res.mpcc_inst].dpp_id = s.dpp_id;
2106
2107 if (s.bot_mpcc_id < MAX_MPCC)
2108 pool->mpc->mpcc_array[pipe_ctx->plane_res.mpcc_inst].mpcc_bot =
2109 &pool->mpc->mpcc_array[s.bot_mpcc_id];
2110
2111 if (s.opp_id < MAX_OPP)
2112 pipe_ctx->stream_res.opp->mpc_tree_params.opp_id = s.opp_id;
2113 }
2114 }
2115 pipe_ctx->pipe_idx = tg_inst;
2116
2117 pipe_ctx->stream = stream;
2118 return tg_inst;
2119 }
2120
2121 return -1;
2122}
2123
2124static void mark_seamless_boot_stream(
2125 const struct dc *dc,
2126 struct dc_stream_state *stream)
2127{
2128 struct dc_bios *dcb = dc->ctx->dc_bios;
2129
2130
2131 if (dc->config.allow_seamless_boot_optimization &&
2132 !dcb->funcs->is_accelerated_mode(dcb)) {
2133 if (dc_validate_seamless_boot_timing(dc, stream->sink, &stream->timing))
2134 stream->apply_seamless_boot_optimization = true;
2135 }
2136}
2137
2138enum dc_status resource_map_pool_resources(
2139 const struct dc *dc,
2140 struct dc_state *context,
2141 struct dc_stream_state *stream)
2142{
2143 const struct resource_pool *pool = dc->res_pool;
2144 int i;
2145 struct dc_context *dc_ctx = dc->ctx;
2146 struct pipe_ctx *pipe_ctx = NULL;
2147 int pipe_idx = -1;
2148
2149 calculate_phy_pix_clks(stream);
2150
2151 mark_seamless_boot_stream(dc, stream);
2152
2153 if (stream->apply_seamless_boot_optimization) {
2154 pipe_idx = acquire_resource_from_hw_enabled_state(
2155 &context->res_ctx,
2156 pool,
2157 stream);
2158 if (pipe_idx < 0)
2159
2160 stream->apply_seamless_boot_optimization = false;
2161 }
2162
2163 if (pipe_idx < 0)
2164
2165 pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream);
2166
2167#ifdef CONFIG_DRM_AMD_DC_DCN
2168 if (pipe_idx < 0)
2169 pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream);
2170#endif
2171
2172 if (pipe_idx < 0 || context->res_ctx.pipe_ctx[pipe_idx].stream_res.tg == NULL)
2173 return DC_NO_CONTROLLER_RESOURCE;
2174
2175 pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx];
2176
2177 pipe_ctx->stream_res.stream_enc =
2178 dc->res_pool->funcs->find_first_free_match_stream_enc_for_link(
2179 &context->res_ctx, pool, stream);
2180
2181 if (!pipe_ctx->stream_res.stream_enc)
2182 return DC_NO_STREAM_ENC_RESOURCE;
2183
2184 update_stream_engine_usage(
2185 &context->res_ctx, pool,
2186 pipe_ctx->stream_res.stream_enc,
2187 true);
2188
2189
2190 if (!stream->converter_disable_audio &&
2191 dc_is_audio_capable_signal(pipe_ctx->stream->signal) &&
2192 stream->audio_info.mode_count && stream->audio_info.flags.all) {
2193 pipe_ctx->stream_res.audio = find_first_free_audio(
2194 &context->res_ctx, pool, pipe_ctx->stream_res.stream_enc->id, dc_ctx->dce_version);
2195
2196
2197
2198
2199
2200
2201 if (pipe_ctx->stream_res.audio)
2202 update_audio_usage(&context->res_ctx, pool,
2203 pipe_ctx->stream_res.audio, true);
2204 }
2205
2206
2207 if (pipe_ctx->stream && dc_is_embedded_signal(pipe_ctx->stream->signal)) {
2208#if defined(CONFIG_DRM_AMD_DC_DCN)
2209 if (pool->abm)
2210 pipe_ctx->stream_res.abm = pool->abm;
2211 else
2212 pipe_ctx->stream_res.abm = pool->multiple_abms[pipe_ctx->stream_res.tg->inst];
2213#else
2214 pipe_ctx->stream_res.abm = pool->abm;
2215#endif
2216 }
2217
2218 for (i = 0; i < context->stream_count; i++)
2219 if (context->streams[i] == stream) {
2220 context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst;
2221 context->stream_status[i].stream_enc_inst = pipe_ctx->stream_res.stream_enc->stream_enc_inst;
2222 context->stream_status[i].audio_inst =
2223 pipe_ctx->stream_res.audio ? pipe_ctx->stream_res.audio->inst : -1;
2224
2225 return DC_OK;
2226 }
2227
2228 DC_ERROR("Stream %p not found in new ctx!\n", stream);
2229 return DC_ERROR_UNEXPECTED;
2230}
2231
2232
2233
2234
2235
2236
2237
2238void dc_resource_state_copy_construct_current(
2239 const struct dc *dc,
2240 struct dc_state *dst_ctx)
2241{
2242 dc_resource_state_copy_construct(dc->current_state, dst_ctx);
2243}
2244
2245
2246void dc_resource_state_construct(
2247 const struct dc *dc,
2248 struct dc_state *dst_ctx)
2249{
2250 dst_ctx->clk_mgr = dc->clk_mgr;
2251}
2252
2253
2254bool dc_resource_is_dsc_encoding_supported(const struct dc *dc)
2255{
2256 return dc->res_pool->res_cap->num_dsc > 0;
2257}
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269enum dc_status dc_validate_global_state(
2270 struct dc *dc,
2271 struct dc_state *new_ctx,
2272 bool fast_validate)
2273{
2274 enum dc_status result = DC_ERROR_UNEXPECTED;
2275 int i, j;
2276
2277 if (!new_ctx)
2278 return DC_ERROR_UNEXPECTED;
2279
2280 if (dc->res_pool->funcs->validate_global) {
2281 result = dc->res_pool->funcs->validate_global(dc, new_ctx);
2282 if (result != DC_OK)
2283 return result;
2284 }
2285
2286 for (i = 0; i < new_ctx->stream_count; i++) {
2287 struct dc_stream_state *stream = new_ctx->streams[i];
2288
2289 for (j = 0; j < dc->res_pool->pipe_count; j++) {
2290 struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[j];
2291
2292 if (pipe_ctx->stream != stream)
2293 continue;
2294
2295 if (dc->res_pool->funcs->patch_unknown_plane_state &&
2296 pipe_ctx->plane_state &&
2297 pipe_ctx->plane_state->tiling_info.gfx9.swizzle == DC_SW_UNKNOWN) {
2298 result = dc->res_pool->funcs->patch_unknown_plane_state(pipe_ctx->plane_state);
2299 if (result != DC_OK)
2300 return result;
2301 }
2302
2303
2304
2305
2306
2307 if (dc_is_dp_signal(pipe_ctx->stream->signal) &&
2308 !find_pll_sharable_stream(stream, new_ctx)) {
2309
2310 resource_unreference_clock_source(
2311 &new_ctx->res_ctx,
2312 dc->res_pool,
2313 pipe_ctx->clock_source);
2314
2315 pipe_ctx->clock_source = dc->res_pool->dp_clock_source;
2316 resource_reference_clock_source(
2317 &new_ctx->res_ctx,
2318 dc->res_pool,
2319 pipe_ctx->clock_source);
2320 }
2321 }
2322 }
2323
2324 result = resource_build_scaling_params_for_context(dc, new_ctx);
2325
2326 if (result == DC_OK)
2327 if (!dc->res_pool->funcs->validate_bandwidth(dc, new_ctx, fast_validate))
2328 result = DC_FAIL_BANDWIDTH_VALIDATE;
2329
2330 return result;
2331}
2332
2333static void patch_gamut_packet_checksum(
2334 struct dc_info_packet *gamut_packet)
2335{
2336
2337 if (gamut_packet->valid) {
2338 uint8_t chk_sum = 0;
2339 uint8_t *ptr;
2340 uint8_t i;
2341
2342
2343 ptr = &gamut_packet->sb[3];
2344
2345 for (i = 0; i <= gamut_packet->sb[1]; i++)
2346 chk_sum += ptr[i];
2347
2348 gamut_packet->sb[2] = (uint8_t) (0x100 - chk_sum);
2349 }
2350}
2351
2352static void set_avi_info_frame(
2353 struct dc_info_packet *info_packet,
2354 struct pipe_ctx *pipe_ctx)
2355{
2356 struct dc_stream_state *stream = pipe_ctx->stream;
2357 enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
2358 uint32_t pixel_encoding = 0;
2359 enum scanning_type scan_type = SCANNING_TYPE_NODATA;
2360 enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA;
2361 bool itc = false;
2362 uint8_t itc_value = 0;
2363 uint8_t cn0_cn1 = 0;
2364 unsigned int cn0_cn1_value = 0;
2365 uint8_t *check_sum = NULL;
2366 uint8_t byte_index = 0;
2367 union hdmi_info_packet hdmi_info;
2368 union display_content_support support = {0};
2369 unsigned int vic = pipe_ctx->stream->timing.vic;
2370 enum dc_timing_3d_format format;
2371
2372 memset(&hdmi_info, 0, sizeof(union hdmi_info_packet));
2373
2374 color_space = pipe_ctx->stream->output_color_space;
2375 if (color_space == COLOR_SPACE_UNKNOWN)
2376 color_space = (stream->timing.pixel_encoding == PIXEL_ENCODING_RGB) ?
2377 COLOR_SPACE_SRGB:COLOR_SPACE_YCBCR709;
2378
2379
2380 hdmi_info.bits.header.info_frame_type = HDMI_INFOFRAME_TYPE_AVI;
2381
2382
2383 hdmi_info.bits.header.version = 2;
2384 hdmi_info.bits.header.length = HDMI_AVI_INFOFRAME_SIZE;
2385
2386
2387
2388
2389
2390
2391 switch (stream->timing.pixel_encoding) {
2392 case PIXEL_ENCODING_YCBCR422:
2393 pixel_encoding = 1;
2394 break;
2395
2396 case PIXEL_ENCODING_YCBCR444:
2397 pixel_encoding = 2;
2398 break;
2399 case PIXEL_ENCODING_YCBCR420:
2400 pixel_encoding = 3;
2401 break;
2402
2403 case PIXEL_ENCODING_RGB:
2404 default:
2405 pixel_encoding = 0;
2406 }
2407
2408
2409
2410 hdmi_info.bits.Y0_Y1_Y2 = pixel_encoding;
2411
2412
2413 hdmi_info.bits.A0 = ACTIVE_FORMAT_VALID;
2414
2415
2416 hdmi_info.bits.B0_B1 = BAR_INFO_BOTH_VALID;
2417
2418 hdmi_info.bits.SC0_SC1 = PICTURE_SCALING_UNIFORM;
2419
2420
2421
2422 scan_type = SCANNING_TYPE_UNDERSCAN;
2423 hdmi_info.bits.S0_S1 = scan_type;
2424
2425
2426 if (color_space == COLOR_SPACE_YCBCR709 ||
2427 color_space == COLOR_SPACE_YCBCR709_LIMITED)
2428 hdmi_info.bits.C0_C1 = COLORIMETRY_ITU709;
2429 else if (color_space == COLOR_SPACE_YCBCR601 ||
2430 color_space == COLOR_SPACE_YCBCR601_LIMITED)
2431 hdmi_info.bits.C0_C1 = COLORIMETRY_ITU601;
2432 else {
2433 hdmi_info.bits.C0_C1 = COLORIMETRY_NO_DATA;
2434 }
2435 if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE ||
2436 color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE ||
2437 color_space == COLOR_SPACE_2020_YCBCR) {
2438 hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR;
2439 hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED;
2440 } else if (color_space == COLOR_SPACE_ADOBERGB) {
2441 hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_ADOBERGB;
2442 hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED;
2443 }
2444
2445
2446 aspect = stream->timing.aspect_ratio;
2447
2448 switch (aspect) {
2449 case ASPECT_RATIO_4_3:
2450 case ASPECT_RATIO_16_9:
2451 hdmi_info.bits.M0_M1 = aspect;
2452 break;
2453
2454 case ASPECT_RATIO_NO_DATA:
2455 case ASPECT_RATIO_64_27:
2456 case ASPECT_RATIO_256_135:
2457 default:
2458 hdmi_info.bits.M0_M1 = 0;
2459 }
2460
2461
2462 hdmi_info.bits.R0_R3 = ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE;
2463
2464
2465
2466 cn0_cn1 = 0;
2467 cn0_cn1_value = 0;
2468
2469 itc = true;
2470 itc_value = 1;
2471
2472 support = stream->content_support;
2473
2474 if (itc) {
2475 if (!support.bits.valid_content_type) {
2476 cn0_cn1_value = 0;
2477 } else {
2478 if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GRAPHICS) {
2479 if (support.bits.graphics_content == 1) {
2480 cn0_cn1_value = 0;
2481 }
2482 } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_PHOTO) {
2483 if (support.bits.photo_content == 1) {
2484 cn0_cn1_value = 1;
2485 } else {
2486 cn0_cn1_value = 0;
2487 itc_value = 0;
2488 }
2489 } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_CINEMA) {
2490 if (support.bits.cinema_content == 1) {
2491 cn0_cn1_value = 2;
2492 } else {
2493 cn0_cn1_value = 0;
2494 itc_value = 0;
2495 }
2496 } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GAME) {
2497 if (support.bits.game_content == 1) {
2498 cn0_cn1_value = 3;
2499 } else {
2500 cn0_cn1_value = 0;
2501 itc_value = 0;
2502 }
2503 }
2504 }
2505 hdmi_info.bits.CN0_CN1 = cn0_cn1_value;
2506 hdmi_info.bits.ITC = itc_value;
2507 }
2508
2509 if (stream->qs_bit == 1) {
2510 if (color_space == COLOR_SPACE_SRGB ||
2511 color_space == COLOR_SPACE_2020_RGB_FULLRANGE)
2512 hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_FULL_RANGE;
2513 else if (color_space == COLOR_SPACE_SRGB_LIMITED ||
2514 color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE)
2515 hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_LIMITED_RANGE;
2516 else
2517 hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE;
2518 } else
2519 hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE;
2520
2521
2522
2523 if (stream->qy_bit == 1) {
2524 if (color_space == COLOR_SPACE_SRGB ||
2525 color_space == COLOR_SPACE_2020_RGB_FULLRANGE)
2526 hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE;
2527 else if (color_space == COLOR_SPACE_SRGB_LIMITED ||
2528 color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE)
2529 hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE;
2530 else
2531 hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE;
2532 } else
2533 hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE;
2534
2535
2536 format = stream->timing.timing_3d_format;
2537
2538 if (format != TIMING_3D_FORMAT_NONE) {
2539
2540 switch (pipe_ctx->stream->timing.hdmi_vic) {
2541 case 1:
2542 vic = 95;
2543 break;
2544 case 2:
2545 vic = 94;
2546 break;
2547 case 3:
2548 vic = 93;
2549 break;
2550 case 4:
2551 vic = 98;
2552 break;
2553 default:
2554 break;
2555 }
2556 }
2557
2558 hdmi_info.bits.VIC0_VIC7 = vic;
2559 if (vic >= 128)
2560 hdmi_info.bits.header.version = 3;
2561
2562
2563
2564 if (hdmi_info.bits.C0_C1 == COLORIMETRY_EXTENDED &&
2565 hdmi_info.bits.EC0_EC2 == COLORIMETRYEX_RESERVED) {
2566 hdmi_info.bits.header.version = 4;
2567 hdmi_info.bits.header.length = 14;
2568 }
2569
2570
2571
2572
2573 hdmi_info.bits.PR0_PR3 = 0;
2574
2575
2576
2577
2578
2579
2580 hdmi_info.bits.bar_top = stream->timing.v_border_top;
2581 hdmi_info.bits.bar_bottom = (stream->timing.v_total
2582 - stream->timing.v_border_bottom + 1);
2583 hdmi_info.bits.bar_left = stream->timing.h_border_left;
2584 hdmi_info.bits.bar_right = (stream->timing.h_total
2585 - stream->timing.h_border_right + 1);
2586
2587
2588
2589
2590
2591
2592 hdmi_info.bits.ACE0_ACE3 = 0;
2593
2594
2595 check_sum = &hdmi_info.packet_raw_data.sb[0];
2596
2597 *check_sum = HDMI_INFOFRAME_TYPE_AVI + hdmi_info.bits.header.length + hdmi_info.bits.header.version;
2598
2599 for (byte_index = 1; byte_index <= hdmi_info.bits.header.length; byte_index++)
2600 *check_sum += hdmi_info.packet_raw_data.sb[byte_index];
2601
2602
2603 *check_sum = (uint8_t) (0x100 - *check_sum);
2604
2605
2606 info_packet->hb0 = hdmi_info.packet_raw_data.hb0;
2607 info_packet->hb1 = hdmi_info.packet_raw_data.hb1;
2608 info_packet->hb2 = hdmi_info.packet_raw_data.hb2;
2609
2610 for (byte_index = 0; byte_index < sizeof(hdmi_info.packet_raw_data.sb); byte_index++)
2611 info_packet->sb[byte_index] = hdmi_info.packet_raw_data.sb[byte_index];
2612
2613 info_packet->valid = true;
2614}
2615
2616static void set_vendor_info_packet(
2617 struct dc_info_packet *info_packet,
2618 struct dc_stream_state *stream)
2619{
2620
2621
2622
2623
2624
2625 if (!stream->vsp_infopacket.valid)
2626 return;
2627
2628 *info_packet = stream->vsp_infopacket;
2629}
2630
2631static void set_spd_info_packet(
2632 struct dc_info_packet *info_packet,
2633 struct dc_stream_state *stream)
2634{
2635
2636
2637
2638
2639
2640 if (!stream->vrr_infopacket.valid)
2641 return;
2642
2643 *info_packet = stream->vrr_infopacket;
2644}
2645
2646static void set_hdr_static_info_packet(
2647 struct dc_info_packet *info_packet,
2648 struct dc_stream_state *stream)
2649{
2650
2651
2652 if (!stream->hdr_static_metadata.valid ||
2653 stream->use_dynamic_meta)
2654 return;
2655
2656 *info_packet = stream->hdr_static_metadata;
2657}
2658
2659static void set_vsc_info_packet(
2660 struct dc_info_packet *info_packet,
2661 struct dc_stream_state *stream)
2662{
2663 if (!stream->vsc_infopacket.valid)
2664 return;
2665
2666 *info_packet = stream->vsc_infopacket;
2667}
2668
2669void dc_resource_state_destruct(struct dc_state *context)
2670{
2671 int i, j;
2672
2673 for (i = 0; i < context->stream_count; i++) {
2674 for (j = 0; j < context->stream_status[i].plane_count; j++)
2675 dc_plane_state_release(
2676 context->stream_status[i].plane_states[j]);
2677
2678 context->stream_status[i].plane_count = 0;
2679 dc_stream_release(context->streams[i]);
2680 context->streams[i] = NULL;
2681 }
2682}
2683
2684void dc_resource_state_copy_construct(
2685 const struct dc_state *src_ctx,
2686 struct dc_state *dst_ctx)
2687{
2688 int i, j;
2689 struct kref refcount = dst_ctx->refcount;
2690
2691 *dst_ctx = *src_ctx;
2692
2693 for (i = 0; i < MAX_PIPES; i++) {
2694 struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i];
2695
2696 if (cur_pipe->top_pipe)
2697 cur_pipe->top_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx];
2698
2699 if (cur_pipe->bottom_pipe)
2700 cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
2701
2702 if (cur_pipe->next_odm_pipe)
2703 cur_pipe->next_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx];
2704
2705 if (cur_pipe->prev_odm_pipe)
2706 cur_pipe->prev_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx];
2707 }
2708
2709 for (i = 0; i < dst_ctx->stream_count; i++) {
2710 dc_stream_retain(dst_ctx->streams[i]);
2711 for (j = 0; j < dst_ctx->stream_status[i].plane_count; j++)
2712 dc_plane_state_retain(
2713 dst_ctx->stream_status[i].plane_states[j]);
2714 }
2715
2716
2717 dst_ctx->refcount = refcount;
2718
2719}
2720
2721struct clock_source *dc_resource_find_first_free_pll(
2722 struct resource_context *res_ctx,
2723 const struct resource_pool *pool)
2724{
2725 int i;
2726
2727 for (i = 0; i < pool->clk_src_count; ++i) {
2728 if (res_ctx->clock_source_ref_count[i] == 0)
2729 return pool->clock_sources[i];
2730 }
2731
2732 return NULL;
2733}
2734
2735void resource_build_info_frame(struct pipe_ctx *pipe_ctx)
2736{
2737 enum signal_type signal = SIGNAL_TYPE_NONE;
2738 struct encoder_info_frame *info = &pipe_ctx->stream_res.encoder_info_frame;
2739
2740
2741 info->avi.valid = false;
2742 info->gamut.valid = false;
2743 info->vendor.valid = false;
2744 info->spd.valid = false;
2745 info->hdrsmd.valid = false;
2746 info->vsc.valid = false;
2747
2748 signal = pipe_ctx->stream->signal;
2749
2750
2751 if (dc_is_hdmi_signal(signal)) {
2752 set_avi_info_frame(&info->avi, pipe_ctx);
2753
2754 set_vendor_info_packet(&info->vendor, pipe_ctx->stream);
2755
2756 set_spd_info_packet(&info->spd, pipe_ctx->stream);
2757
2758 set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream);
2759
2760 } else if (dc_is_dp_signal(signal)) {
2761 set_vsc_info_packet(&info->vsc, pipe_ctx->stream);
2762
2763 set_spd_info_packet(&info->spd, pipe_ctx->stream);
2764
2765 set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream);
2766 }
2767
2768 patch_gamut_packet_checksum(&info->gamut);
2769}
2770
2771enum dc_status resource_map_clock_resources(
2772 const struct dc *dc,
2773 struct dc_state *context,
2774 struct dc_stream_state *stream)
2775{
2776
2777 const struct resource_pool *pool = dc->res_pool;
2778 struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(
2779 &context->res_ctx, stream);
2780
2781 if (!pipe_ctx)
2782 return DC_ERROR_UNEXPECTED;
2783
2784 if (dc_is_dp_signal(pipe_ctx->stream->signal)
2785 || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL)
2786 pipe_ctx->clock_source = pool->dp_clock_source;
2787 else {
2788 pipe_ctx->clock_source = NULL;
2789
2790 if (!dc->config.disable_disp_pll_sharing)
2791 pipe_ctx->clock_source = resource_find_used_clk_src_for_sharing(
2792 &context->res_ctx,
2793 pipe_ctx);
2794
2795 if (pipe_ctx->clock_source == NULL)
2796 pipe_ctx->clock_source =
2797 dc_resource_find_first_free_pll(
2798 &context->res_ctx,
2799 pool);
2800 }
2801
2802 if (pipe_ctx->clock_source == NULL)
2803 return DC_NO_CLOCK_SOURCE_RESOURCE;
2804
2805 resource_reference_clock_source(
2806 &context->res_ctx, pool,
2807 pipe_ctx->clock_source);
2808
2809 return DC_OK;
2810}
2811
2812
2813
2814
2815
2816
2817bool pipe_need_reprogram(
2818 struct pipe_ctx *pipe_ctx_old,
2819 struct pipe_ctx *pipe_ctx)
2820{
2821 if (!pipe_ctx_old->stream)
2822 return false;
2823
2824 if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink)
2825 return true;
2826
2827 if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal)
2828 return true;
2829
2830 if (pipe_ctx_old->stream_res.audio != pipe_ctx->stream_res.audio)
2831 return true;
2832
2833 if (pipe_ctx_old->clock_source != pipe_ctx->clock_source
2834 && pipe_ctx_old->stream != pipe_ctx->stream)
2835 return true;
2836
2837 if (pipe_ctx_old->stream_res.stream_enc != pipe_ctx->stream_res.stream_enc)
2838 return true;
2839
2840 if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream))
2841 return true;
2842
2843 if (pipe_ctx_old->stream->dpms_off != pipe_ctx->stream->dpms_off)
2844 return true;
2845
2846 if (false == pipe_ctx_old->stream->link->link_state_valid &&
2847 false == pipe_ctx_old->stream->dpms_off)
2848 return true;
2849
2850 if (pipe_ctx_old->stream_res.dsc != pipe_ctx->stream_res.dsc)
2851 return true;
2852
2853
2854 if (pipe_ctx_old->stream->link_enc != pipe_ctx->stream->link_enc)
2855 return true;
2856
2857 return false;
2858}
2859
2860void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream,
2861 struct bit_depth_reduction_params *fmt_bit_depth)
2862{
2863 enum dc_dither_option option = stream->dither_option;
2864 enum dc_pixel_encoding pixel_encoding =
2865 stream->timing.pixel_encoding;
2866
2867 memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth));
2868
2869 if (option == DITHER_OPTION_DEFAULT) {
2870 switch (stream->timing.display_color_depth) {
2871 case COLOR_DEPTH_666:
2872 option = DITHER_OPTION_SPATIAL6;
2873 break;
2874 case COLOR_DEPTH_888:
2875 option = DITHER_OPTION_SPATIAL8;
2876 break;
2877 case COLOR_DEPTH_101010:
2878 option = DITHER_OPTION_SPATIAL10;
2879 break;
2880 default:
2881 option = DITHER_OPTION_DISABLE;
2882 }
2883 }
2884
2885 if (option == DITHER_OPTION_DISABLE)
2886 return;
2887
2888 if (option == DITHER_OPTION_TRUN6) {
2889 fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
2890 fmt_bit_depth->flags.TRUNCATE_DEPTH = 0;
2891 } else if (option == DITHER_OPTION_TRUN8 ||
2892 option == DITHER_OPTION_TRUN8_SPATIAL6 ||
2893 option == DITHER_OPTION_TRUN8_FM6) {
2894 fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
2895 fmt_bit_depth->flags.TRUNCATE_DEPTH = 1;
2896 } else if (option == DITHER_OPTION_TRUN10 ||
2897 option == DITHER_OPTION_TRUN10_SPATIAL6 ||
2898 option == DITHER_OPTION_TRUN10_SPATIAL8 ||
2899 option == DITHER_OPTION_TRUN10_FM8 ||
2900 option == DITHER_OPTION_TRUN10_FM6 ||
2901 option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) {
2902 fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
2903 fmt_bit_depth->flags.TRUNCATE_DEPTH = 2;
2904 }
2905
2906
2907
2908
2909
2910
2911
2912
2913 if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM ||
2914 option == DITHER_OPTION_SPATIAL6 ||
2915 option == DITHER_OPTION_FM6) {
2916 fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
2917 fmt_bit_depth->flags.TRUNCATE_DEPTH = 2;
2918 fmt_bit_depth->flags.TRUNCATE_MODE = 1;
2919 }
2920
2921
2922
2923
2924 if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM ||
2925 option == DITHER_OPTION_SPATIAL6 ||
2926 option == DITHER_OPTION_TRUN10_SPATIAL6 ||
2927 option == DITHER_OPTION_TRUN8_SPATIAL6) {
2928 fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
2929 fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0;
2930 fmt_bit_depth->flags.HIGHPASS_RANDOM = 1;
2931 fmt_bit_depth->flags.RGB_RANDOM =
2932 (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0;
2933 } else if (option == DITHER_OPTION_SPATIAL8_FRAME_RANDOM ||
2934 option == DITHER_OPTION_SPATIAL8 ||
2935 option == DITHER_OPTION_SPATIAL8_FM6 ||
2936 option == DITHER_OPTION_TRUN10_SPATIAL8 ||
2937 option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) {
2938 fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
2939 fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1;
2940 fmt_bit_depth->flags.HIGHPASS_RANDOM = 1;
2941 fmt_bit_depth->flags.RGB_RANDOM =
2942 (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0;
2943 } else if (option == DITHER_OPTION_SPATIAL10_FRAME_RANDOM ||
2944 option == DITHER_OPTION_SPATIAL10 ||
2945 option == DITHER_OPTION_SPATIAL10_FM8 ||
2946 option == DITHER_OPTION_SPATIAL10_FM6) {
2947 fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
2948 fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2;
2949 fmt_bit_depth->flags.HIGHPASS_RANDOM = 1;
2950 fmt_bit_depth->flags.RGB_RANDOM =
2951 (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0;
2952 }
2953
2954 if (option == DITHER_OPTION_SPATIAL6 ||
2955 option == DITHER_OPTION_SPATIAL8 ||
2956 option == DITHER_OPTION_SPATIAL10) {
2957 fmt_bit_depth->flags.FRAME_RANDOM = 0;
2958 } else {
2959 fmt_bit_depth->flags.FRAME_RANDOM = 1;
2960 }
2961
2962
2963
2964
2965 if (option == DITHER_OPTION_FM6 ||
2966 option == DITHER_OPTION_SPATIAL8_FM6 ||
2967 option == DITHER_OPTION_SPATIAL10_FM6 ||
2968 option == DITHER_OPTION_TRUN10_FM6 ||
2969 option == DITHER_OPTION_TRUN8_FM6 ||
2970 option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) {
2971 fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1;
2972 fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 0;
2973 } else if (option == DITHER_OPTION_FM8 ||
2974 option == DITHER_OPTION_SPATIAL10_FM8 ||
2975 option == DITHER_OPTION_TRUN10_FM8) {
2976 fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1;
2977 fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 1;
2978 } else if (option == DITHER_OPTION_FM10) {
2979 fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1;
2980 fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 2;
2981 }
2982
2983 fmt_bit_depth->pixel_encoding = pixel_encoding;
2984}
2985
2986enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream)
2987{
2988 struct dc_link *link = stream->link;
2989 struct timing_generator *tg = dc->res_pool->timing_generators[0];
2990 enum dc_status res = DC_OK;
2991
2992 calculate_phy_pix_clks(stream);
2993
2994 if (!tg->funcs->validate_timing(tg, &stream->timing))
2995 res = DC_FAIL_CONTROLLER_VALIDATE;
2996
2997 if (res == DC_OK) {
2998 if (!link->link_enc->funcs->validate_output_with_stream(
2999 link->link_enc, stream))
3000 res = DC_FAIL_ENC_VALIDATE;
3001 }
3002
3003
3004
3005 if (res == DC_OK)
3006 res = dc_link_validate_mode_timing(stream,
3007 link,
3008 &stream->timing);
3009
3010 return res;
3011}
3012
3013enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state)
3014{
3015 enum dc_status res = DC_OK;
3016
3017
3018 if (dc->res_pool->funcs->validate_plane)
3019 return dc->res_pool->funcs->validate_plane(plane_state, &dc->caps);
3020
3021 return res;
3022}
3023
3024unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format)
3025{
3026 switch (format) {
3027 case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
3028 return 8;
3029 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
3030 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
3031 return 12;
3032 case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
3033 case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
3034 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
3035 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
3036 return 16;
3037 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
3038 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
3039 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
3040 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
3041 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
3042#if defined(CONFIG_DRM_AMD_DC_DCN)
3043 case SURFACE_PIXEL_FORMAT_GRPH_RGBE:
3044 case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA:
3045#endif
3046 return 32;
3047 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
3048 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
3049 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
3050 return 64;
3051 default:
3052 ASSERT_CRITICAL(false);
3053 return -1;
3054 }
3055}
3056static unsigned int get_max_audio_sample_rate(struct audio_mode *modes)
3057{
3058 if (modes) {
3059 if (modes->sample_rates.rate.RATE_192)
3060 return 192000;
3061 if (modes->sample_rates.rate.RATE_176_4)
3062 return 176400;
3063 if (modes->sample_rates.rate.RATE_96)
3064 return 96000;
3065 if (modes->sample_rates.rate.RATE_88_2)
3066 return 88200;
3067 if (modes->sample_rates.rate.RATE_48)
3068 return 48000;
3069 if (modes->sample_rates.rate.RATE_44_1)
3070 return 44100;
3071 if (modes->sample_rates.rate.RATE_32)
3072 return 32000;
3073 }
3074
3075 return 441000;
3076}
3077
3078void get_audio_check(struct audio_info *aud_modes,
3079 struct audio_check *audio_chk)
3080{
3081 unsigned int i;
3082 unsigned int max_sample_rate = 0;
3083
3084 if (aud_modes) {
3085 audio_chk->audio_packet_type = 0x2;
3086
3087 audio_chk->max_audiosample_rate = 0;
3088 for (i = 0; i < aud_modes->mode_count; i++) {
3089 max_sample_rate = get_max_audio_sample_rate(&aud_modes->modes[i]);
3090 if (audio_chk->max_audiosample_rate < max_sample_rate)
3091 audio_chk->max_audiosample_rate = max_sample_rate;
3092
3093 }
3094
3095 if (audio_chk->max_audiosample_rate > 192000)
3096 audio_chk->audio_packet_type = 0x9;
3097 audio_chk->acat = 0;
3098 }
3099}
3100
3101