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