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