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