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