]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/gpu/drm/amd/display/dc/core/dc_resource.c
drm/amd/display: HDMI YCbCr422 12bpc pixel format issue
[mirror_ubuntu-jammy-kernel.git] / drivers / gpu / drm / amd / display / dc / core / dc_resource.c
CommitLineData
4562236b
HW
1/*
2* Copyright 2012-15 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: AMD
23 *
24 */
25#include "dm_services.h"
26
27#include "resource.h"
28#include "include/irq_service_interface.h"
29#include "link_encoder.h"
30#include "stream_encoder.h"
31#include "opp.h"
32#include "timing_generator.h"
33#include "transform.h"
34#include "set_mode_types.h"
4562236b
HW
35#include "virtual/virtual_stream_encoder.h"
36
37#include "dce80/dce80_resource.h"
38#include "dce100/dce100_resource.h"
39#include "dce110/dce110_resource.h"
40#include "dce112/dce112_resource.h"
41
42enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id)
43{
44 enum dce_version dc_version = DCE_VERSION_UNKNOWN;
45 switch (asic_id.chip_family) {
46
47 case FAMILY_CI:
48 case FAMILY_KV:
49 dc_version = DCE_VERSION_8_0;
50 break;
51 case FAMILY_CZ:
52 dc_version = DCE_VERSION_11_0;
53 break;
54
55 case FAMILY_VI:
56 if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) ||
57 ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) {
58 dc_version = DCE_VERSION_10_0;
59 break;
60 }
61 if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) ||
b264d345
JL
62 ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) ||
63 ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) {
4562236b
HW
64 dc_version = DCE_VERSION_11_2;
65 }
66 break;
67 default:
68 dc_version = DCE_VERSION_UNKNOWN;
69 break;
70 }
71 return dc_version;
72}
73
74struct resource_pool *dc_create_resource_pool(
75 struct core_dc *dc,
76 int num_virtual_links,
77 enum dce_version dc_version,
78 struct hw_asic_id asic_id)
79{
80
81 switch (dc_version) {
82 case DCE_VERSION_8_0:
83 return dce80_create_resource_pool(
84 num_virtual_links, dc);
85 case DCE_VERSION_10_0:
86 return dce100_create_resource_pool(
87 num_virtual_links, dc);
88 case DCE_VERSION_11_0:
89 return dce110_create_resource_pool(
90 num_virtual_links, dc, asic_id);
91 case DCE_VERSION_11_2:
92 return dce112_create_resource_pool(
93 num_virtual_links, dc);
94 default:
95 break;
96 }
97
98 return false;
99}
100
101void dc_destroy_resource_pool(struct core_dc *dc)
102{
103 if (dc) {
104 if (dc->res_pool)
105 dc->res_pool->funcs->destroy(&dc->res_pool);
106
107 if (dc->hwseq)
108 dm_free(dc->hwseq);
109 }
110}
111
112static void update_num_audio(
113 const struct resource_straps *straps,
114 unsigned int *num_audio,
115 struct audio_support *aud_support)
116{
117 if (straps->hdmi_disable == 0) {
118 aud_support->hdmi_audio_native = true;
119 aud_support->hdmi_audio_on_dongle = true;
120 aud_support->dp_audio = true;
121 } else {
122 if (straps->dc_pinstraps_audio & 0x2) {
123 aud_support->hdmi_audio_on_dongle = true;
124 aud_support->dp_audio = true;
125 } else {
126 aud_support->dp_audio = true;
127 }
128 }
129
130 switch (straps->audio_stream_number) {
131 case 0: /* multi streams supported */
132 break;
133 case 1: /* multi streams not supported */
134 *num_audio = 1;
135 break;
136 default:
137 DC_ERR("DC: unexpected audio fuse!\n");
138 };
139}
140
141bool resource_construct(
142 unsigned int num_virtual_links,
143 struct core_dc *dc,
144 struct resource_pool *pool,
145 const struct resource_create_funcs *create_funcs)
146{
147 struct dc_context *ctx = dc->ctx;
148 const struct resource_caps *caps = pool->res_cap;
149 int i;
150 unsigned int num_audio = caps->num_audio;
151 struct resource_straps straps = {0};
152
153 if (create_funcs->read_dce_straps)
154 create_funcs->read_dce_straps(dc->ctx, &straps);
155
156 pool->audio_count = 0;
157 if (create_funcs->create_audio) {
158 /* find the total number of streams available via the
159 * AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT
160 * registers (one for each pin) starting from pin 1
161 * up to the max number of audio pins.
162 * We stop on the first pin where
163 * PORT_CONNECTIVITY == 1 (as instructed by HW team).
164 */
165 update_num_audio(&straps, &num_audio, &pool->audio_support);
166 for (i = 0; i < pool->pipe_count && i < num_audio; i++) {
167 struct audio *aud = create_funcs->create_audio(ctx, i);
168
169 if (aud == NULL) {
170 DC_ERR("DC: failed to create audio!\n");
171 return false;
172 }
173
174 if (!aud->funcs->endpoint_valid(aud)) {
175 aud->funcs->destroy(&aud);
176 break;
177 }
178
179 pool->audios[i] = aud;
180 pool->audio_count++;
181 }
182 }
183
184 pool->stream_enc_count = 0;
185 if (create_funcs->create_stream_encoder) {
186 for (i = 0; i < caps->num_stream_encoder; i++) {
187 pool->stream_enc[i] = create_funcs->create_stream_encoder(i, ctx);
188 if (pool->stream_enc[i] == NULL)
189 DC_ERR("DC: failed to create stream_encoder!\n");
190 pool->stream_enc_count++;
191 }
192 }
193
194 for (i = 0; i < num_virtual_links; i++) {
195 pool->stream_enc[pool->stream_enc_count] =
196 virtual_stream_encoder_create(
197 ctx, ctx->dc_bios);
198 if (pool->stream_enc[pool->stream_enc_count] == NULL) {
199 DC_ERR("DC: failed to create stream_encoder!\n");
200 return false;
201 }
202 pool->stream_enc_count++;
203 }
204
205 dc->hwseq = create_funcs->create_hwseq(ctx);
206
207 return true;
208}
209
210
211void resource_unreference_clock_source(
212 struct resource_context *res_ctx,
8c737fcc 213 struct clock_source **clock_source)
4562236b
HW
214{
215 int i;
216 for (i = 0; i < res_ctx->pool->clk_src_count; i++) {
8c737fcc 217 if (res_ctx->pool->clock_sources[i] != *clock_source)
4562236b
HW
218 continue;
219
220 res_ctx->clock_source_ref_count[i]--;
221
222 if (res_ctx->clock_source_ref_count[i] == 0)
8c737fcc 223 (*clock_source)->funcs->cs_power_down(*clock_source);
4562236b
HW
224
225 break;
226 }
227
8c737fcc 228 if (res_ctx->pool->dp_clock_source == *clock_source) {
4562236b
HW
229 res_ctx->dp_clock_source_ref_count--;
230
231 if (res_ctx->dp_clock_source_ref_count == 0)
8c737fcc 232 (*clock_source)->funcs->cs_power_down(*clock_source);
4562236b 233 }
8c737fcc 234 *clock_source = NULL;
4562236b
HW
235}
236
237void resource_reference_clock_source(
238 struct resource_context *res_ctx,
239 struct clock_source *clock_source)
240{
241 int i;
242 for (i = 0; i < res_ctx->pool->clk_src_count; i++) {
243 if (res_ctx->pool->clock_sources[i] != clock_source)
244 continue;
245
246 res_ctx->clock_source_ref_count[i]++;
247 break;
248 }
249
250 if (res_ctx->pool->dp_clock_source == clock_source)
251 res_ctx->dp_clock_source_ref_count++;
252}
253
254bool resource_are_streams_timing_synchronizable(
255 const struct core_stream *stream1,
256 const struct core_stream *stream2)
257{
258 if (stream1->public.timing.h_total != stream2->public.timing.h_total)
259 return false;
260
261 if (stream1->public.timing.v_total != stream2->public.timing.v_total)
262 return false;
263
264 if (stream1->public.timing.h_addressable
265 != stream2->public.timing.h_addressable)
266 return false;
267
268 if (stream1->public.timing.v_addressable
269 != stream2->public.timing.v_addressable)
270 return false;
271
272 if (stream1->public.timing.pix_clk_khz
273 != stream2->public.timing.pix_clk_khz)
274 return false;
275
276 if (stream1->phy_pix_clk != stream2->phy_pix_clk
277 && !dc_is_dp_signal(stream1->signal)
278 && !dc_is_dp_signal(stream2->signal))
279 return false;
280
281 return true;
282}
283
284static bool is_sharable_clk_src(
285 const struct pipe_ctx *pipe_with_clk_src,
286 const struct pipe_ctx *pipe)
287{
288 if (pipe_with_clk_src->clock_source == NULL)
289 return false;
290
291 if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL)
292 return false;
293
294 if (dc_is_dp_signal(pipe_with_clk_src->stream->signal))
295 return false;
296
297 if (dc_is_hdmi_signal(pipe_with_clk_src->stream->signal)
298 && dc_is_dvi_signal(pipe->stream->signal))
299 return false;
300
301 if (dc_is_hdmi_signal(pipe->stream->signal)
302 && dc_is_dvi_signal(pipe_with_clk_src->stream->signal))
303 return false;
304
305 if (!resource_are_streams_timing_synchronizable(
306 pipe_with_clk_src->stream, pipe->stream))
307 return false;
308
309 return true;
310}
311
312struct clock_source *resource_find_used_clk_src_for_sharing(
313 struct resource_context *res_ctx,
314 struct pipe_ctx *pipe_ctx)
315{
316 int i;
317
318 for (i = 0; i < MAX_PIPES; i++) {
319 if (is_sharable_clk_src(&res_ctx->pipe_ctx[i], pipe_ctx))
320 return res_ctx->pipe_ctx[i].clock_source;
321 }
322
323 return NULL;
324}
325
326static enum pixel_format convert_pixel_format_to_dalsurface(
327 enum surface_pixel_format surface_pixel_format)
328{
329 enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
330
331 switch (surface_pixel_format) {
332 case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
333 dal_pixel_format = PIXEL_FORMAT_INDEX8;
334 break;
335 case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
336 dal_pixel_format = PIXEL_FORMAT_RGB565;
337 break;
338 case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
339 dal_pixel_format = PIXEL_FORMAT_RGB565;
340 break;
341 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
342 dal_pixel_format = PIXEL_FORMAT_ARGB8888;
343 break;
8693049a 344 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
4562236b
HW
345 dal_pixel_format = PIXEL_FORMAT_ARGB8888;
346 break;
347 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
348 dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
349 break;
350 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
351 dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
352 break;
353 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
354 dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS;
355 break;
356 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
357 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
358 dal_pixel_format = PIXEL_FORMAT_FP16;
359 break;
360 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
361 dal_pixel_format = PIXEL_FORMAT_420BPP12;
362 break;
363 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
364 dal_pixel_format = PIXEL_FORMAT_420BPP12;
365 break;
366 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
367 default:
368 dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
369 break;
370 }
371 return dal_pixel_format;
372}
373
374static void rect_swap_helper(struct rect *rect)
375{
376 uint32_t temp = 0;
377
378 temp = rect->height;
379 rect->height = rect->width;
380 rect->width = temp;
381
382 temp = rect->x;
383 rect->x = rect->y;
384 rect->y = temp;
385}
386
387static void calculate_viewport(
388 const struct dc_surface *surface,
389 struct pipe_ctx *pipe_ctx)
390{
391 struct rect stream_src = pipe_ctx->stream->public.src;
392 struct rect src = surface->src_rect;
393 struct rect dst = surface->dst_rect;
394 struct rect surface_clip = surface->clip_rect;
395 struct rect clip = {0};
396
397
398 if (surface->rotation == ROTATION_ANGLE_90 ||
399 surface->rotation == ROTATION_ANGLE_270) {
400 rect_swap_helper(&src);
401 rect_swap_helper(&dst);
402 rect_swap_helper(&surface_clip);
403 rect_swap_helper(&stream_src);
404 }
405
406 /* The actual clip is an intersection between stream
407 * source and surface clip
408 */
409 clip.x = stream_src.x > surface_clip.x ?
410 stream_src.x : surface_clip.x;
411
412 clip.width = stream_src.x + stream_src.width <
413 surface_clip.x + surface_clip.width ?
414 stream_src.x + stream_src.width - clip.x :
415 surface_clip.x + surface_clip.width - clip.x ;
416
417 clip.y = stream_src.y > surface_clip.y ?
418 stream_src.y : surface_clip.y;
419
420 clip.height = stream_src.y + stream_src.height <
421 surface_clip.y + surface_clip.height ?
422 stream_src.y + stream_src.height - clip.y :
423 surface_clip.y + surface_clip.height - clip.y ;
424
425 /* offset = src.ofs + (clip.ofs - dst.ofs) * scl_ratio
426 * num_pixels = clip.num_pix * scl_ratio
427 */
428 pipe_ctx->scl_data.viewport.x = src.x + (clip.x - dst.x) *
429 src.width / dst.width;
430 pipe_ctx->scl_data.viewport.width = clip.width *
431 src.width / dst.width;
432
433 pipe_ctx->scl_data.viewport.y = src.y + (clip.y - dst.y) *
434 src.height / dst.height;
435 pipe_ctx->scl_data.viewport.height = clip.height *
436 src.height / dst.height;
437
438 /* Minimum viewport such that 420/422 chroma vp is non 0 */
439 if (pipe_ctx->scl_data.viewport.width < 2)
440 pipe_ctx->scl_data.viewport.width = 2;
441 if (pipe_ctx->scl_data.viewport.height < 2)
442 pipe_ctx->scl_data.viewport.height = 2;
443}
444
445static void calculate_recout(
446 const struct dc_surface *surface,
447 struct pipe_ctx *pipe_ctx)
448{
449 struct core_stream *stream = pipe_ctx->stream;
450 struct rect clip = surface->clip_rect;
451
452 pipe_ctx->scl_data.recout.x = stream->public.dst.x;
453 if (stream->public.src.x < clip.x)
454 pipe_ctx->scl_data.recout.x += (clip.x
455 - stream->public.src.x) * stream->public.dst.width
456 / stream->public.src.width;
457
458 pipe_ctx->scl_data.recout.width = clip.width *
459 stream->public.dst.width / stream->public.src.width;
460 if (pipe_ctx->scl_data.recout.width + pipe_ctx->scl_data.recout.x >
461 stream->public.dst.x + stream->public.dst.width)
462 pipe_ctx->scl_data.recout.width =
463 stream->public.dst.x + stream->public.dst.width
464 - pipe_ctx->scl_data.recout.x;
465
466 pipe_ctx->scl_data.recout.y = stream->public.dst.y;
467 if (stream->public.src.y < clip.y)
468 pipe_ctx->scl_data.recout.y += (clip.y
469 - stream->public.src.y) * stream->public.dst.height
470 / stream->public.src.height;
471
472 pipe_ctx->scl_data.recout.height = clip.height *
473 stream->public.dst.height / stream->public.src.height;
474 if (pipe_ctx->scl_data.recout.height + pipe_ctx->scl_data.recout.y >
475 stream->public.dst.y + stream->public.dst.height)
476 pipe_ctx->scl_data.recout.height =
477 stream->public.dst.y + stream->public.dst.height
478 - pipe_ctx->scl_data.recout.y;
479}
480
481static void calculate_scaling_ratios(
482 const struct dc_surface *surface,
483 struct pipe_ctx *pipe_ctx)
484{
485 struct core_stream *stream = pipe_ctx->stream;
486 const uint32_t in_w = stream->public.src.width;
487 const uint32_t in_h = stream->public.src.height;
488 const uint32_t out_w = stream->public.dst.width;
489 const uint32_t out_h = stream->public.dst.height;
490
491 pipe_ctx->scl_data.ratios.horz = dal_fixed31_32_from_fraction(
492 surface->src_rect.width,
493 surface->dst_rect.width);
494 pipe_ctx->scl_data.ratios.vert = dal_fixed31_32_from_fraction(
495 surface->src_rect.height,
496 surface->dst_rect.height);
497
498 if (surface->stereo_format == PLANE_STEREO_FORMAT_SIDE_BY_SIDE)
499 pipe_ctx->scl_data.ratios.horz.value *= 2;
500 else if (surface->stereo_format == PLANE_STEREO_FORMAT_TOP_AND_BOTTOM)
501 pipe_ctx->scl_data.ratios.vert.value *= 2;
502
503 pipe_ctx->scl_data.ratios.vert.value = div64_s64(
504 pipe_ctx->scl_data.ratios.vert.value * in_h, out_h);
505 pipe_ctx->scl_data.ratios.horz.value = div64_s64(
506 pipe_ctx->scl_data.ratios.horz.value * in_w, out_w);
507
508 pipe_ctx->scl_data.ratios.horz_c = pipe_ctx->scl_data.ratios.horz;
509 pipe_ctx->scl_data.ratios.vert_c = pipe_ctx->scl_data.ratios.vert;
510
511 if (pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP12) {
512 pipe_ctx->scl_data.ratios.horz_c.value /= 2;
513 pipe_ctx->scl_data.ratios.vert_c.value /= 2;
514 }
515}
516
517bool resource_build_scaling_params(
518 const struct dc_surface *surface,
519 struct pipe_ctx *pipe_ctx)
520{
521 bool res;
522 struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing;
523 /* Important: scaling ratio calculation requires pixel format,
524 * lb depth calculation requires recout and taps require scaling ratios.
525 */
526 pipe_ctx->scl_data.format = convert_pixel_format_to_dalsurface(surface->format);
527
528 calculate_viewport(surface, pipe_ctx);
529
530 if (pipe_ctx->scl_data.viewport.height < 16 || pipe_ctx->scl_data.viewport.width < 16)
531 return false;
532
533 calculate_scaling_ratios(surface, pipe_ctx);
534
535 calculate_recout(surface, pipe_ctx);
536
537 /**
538 * Setting line buffer pixel depth to 24bpp yields banding
539 * on certain displays, such as the Sharp 4k
540 */
541 pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP;
542
543 pipe_ctx->scl_data.h_active = timing->h_addressable;
544 pipe_ctx->scl_data.v_active = timing->v_addressable;
545
546 /* Taps calculations */
547 res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps(
548 pipe_ctx->xfm, &pipe_ctx->scl_data, &surface->scaling_quality);
549
550 if (!res) {
551 /* Try 24 bpp linebuffer */
552 pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP;
553
554 res = pipe_ctx->xfm->funcs->transform_get_optimal_number_of_taps(
555 pipe_ctx->xfm, &pipe_ctx->scl_data, &surface->scaling_quality);
556 }
557
558 dm_logger_write(pipe_ctx->stream->ctx->logger, LOG_SCALER,
559 "%s: Viewport:\nheight:%d width:%d x:%d "
560 "y:%d\n dst_rect:\nheight:%d width:%d x:%d "
561 "y:%d\n",
562 __func__,
563 pipe_ctx->scl_data.viewport.height,
564 pipe_ctx->scl_data.viewport.width,
565 pipe_ctx->scl_data.viewport.x,
566 pipe_ctx->scl_data.viewport.y,
567 surface->dst_rect.height,
568 surface->dst_rect.width,
569 surface->dst_rect.x,
570 surface->dst_rect.y);
571
572 return res;
573}
574
575
576enum dc_status resource_build_scaling_params_for_context(
577 const struct core_dc *dc,
578 struct validate_context *context)
579{
580 int i;
581
582 for (i = 0; i < MAX_PIPES; i++) {
583 if (context->res_ctx.pipe_ctx[i].surface != NULL &&
584 context->res_ctx.pipe_ctx[i].stream != NULL)
585 if (!resource_build_scaling_params(
586 &context->res_ctx.pipe_ctx[i].surface->public,
587 &context->res_ctx.pipe_ctx[i]))
f84a8161 588 return DC_FAIL_SCALING;
4562236b
HW
589 }
590
591 return DC_OK;
592}
593
ab2541b6 594static void detach_surfaces_for_stream(
4562236b 595 struct validate_context *context,
ab2541b6 596 const struct dc_stream *dc_stream)
4562236b
HW
597{
598 int i;
ab2541b6 599 struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
4562236b
HW
600
601 for (i = 0; i < context->res_ctx.pool->pipe_count; i++) {
602 struct pipe_ctx *cur_pipe = &context->res_ctx.pipe_ctx[i];
603 if (cur_pipe->stream == stream) {
604 cur_pipe->surface = NULL;
605 cur_pipe->top_pipe = NULL;
606 cur_pipe->bottom_pipe = NULL;
607 }
608 }
609}
610
611struct pipe_ctx *find_idle_secondary_pipe(struct resource_context *res_ctx)
612{
613 int i;
614 struct pipe_ctx *secondary_pipe = NULL;
615
616 /*
617 * search backwards for the second pipe to keep pipe
618 * assignment more consistent
619 */
620
621 for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) {
622 if (res_ctx->pipe_ctx[i].stream == NULL) {
623 secondary_pipe = &res_ctx->pipe_ctx[i];
624 secondary_pipe->pipe_idx = i;
625 break;
626 }
627 }
628
629
630 return secondary_pipe;
631}
632
633struct pipe_ctx *resource_get_head_pipe_for_stream(
634 struct resource_context *res_ctx,
635 const struct core_stream *stream)
636{
637 int i;
638 for (i = 0; i < res_ctx->pool->pipe_count; i++) {
639 if (res_ctx->pipe_ctx[i].stream == stream &&
640 !res_ctx->pipe_ctx[i].top_pipe) {
641 return &res_ctx->pipe_ctx[i];
642 break;
643 }
644 }
645 return NULL;
646}
647
648/*
ab2541b6
AC
649 * A free_pipe for a stream is defined here as a pipe
650 * that has no surface attached yet
4562236b 651 */
ab2541b6 652static struct pipe_ctx *acquire_free_pipe_for_stream(
4562236b 653 struct resource_context *res_ctx,
ab2541b6 654 const struct dc_stream *dc_stream)
4562236b
HW
655{
656 int i;
ab2541b6 657 struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
4562236b
HW
658
659 struct pipe_ctx *head_pipe = NULL;
660
661 /* Find head pipe, which has the back end set up*/
662
663 head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream);
664
665 if (!head_pipe)
666 ASSERT(0);
667
668 if (!head_pipe->surface)
669 return head_pipe;
670
671 /* Re-use pipe already acquired for this stream if available*/
672 for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) {
673 if (res_ctx->pipe_ctx[i].stream == stream &&
674 !res_ctx->pipe_ctx[i].surface) {
675 return &res_ctx->pipe_ctx[i];
676 }
677 }
678
679 /*
680 * At this point we have no re-useable pipe for this stream and we need
681 * to acquire an idle one to satisfy the request
682 */
683
684 if(!res_ctx->pool->funcs->acquire_idle_pipe_for_layer)
685 return NULL;
686
687 return res_ctx->pool->funcs->acquire_idle_pipe_for_layer(res_ctx, stream);
688
689}
690
ab2541b6 691static void release_free_pipes_for_stream(
4562236b 692 struct resource_context *res_ctx,
ab2541b6 693 const struct dc_stream *dc_stream)
4562236b
HW
694{
695 int i;
ab2541b6 696 struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
4562236b
HW
697
698 for (i = res_ctx->pool->pipe_count - 1; i >= 0; i--) {
699 if (res_ctx->pipe_ctx[i].stream == stream &&
700 !res_ctx->pipe_ctx[i].surface) {
701 res_ctx->pipe_ctx[i].stream = NULL;
702 }
703 }
704}
705
706bool resource_attach_surfaces_to_context(
707 const struct dc_surface * const *surfaces,
708 int surface_count,
ab2541b6 709 const struct dc_stream *dc_stream,
4562236b
HW
710 struct validate_context *context)
711{
712 int i;
713 struct pipe_ctx *tail_pipe;
ab2541b6 714 struct dc_stream_status *stream_status = NULL;
4562236b
HW
715
716
717 if (surface_count > MAX_SURFACE_NUM) {
718 dm_error("Surface: can not attach %d surfaces! Maximum is: %d\n",
719 surface_count, MAX_SURFACE_NUM);
720 return false;
721 }
722
ab2541b6
AC
723 for (i = 0; i < context->stream_count; i++)
724 if (&context->streams[i]->public == dc_stream) {
725 stream_status = &context->stream_status[i];
4562236b
HW
726 break;
727 }
ab2541b6
AC
728 if (stream_status == NULL) {
729 dm_error("Existing stream not found; failed to attach surfaces\n");
4562236b
HW
730 return false;
731 }
732
733 /* retain new surfaces */
734 for (i = 0; i < surface_count; i++)
735 dc_surface_retain(surfaces[i]);
736
ab2541b6 737 detach_surfaces_for_stream(context, dc_stream);
4562236b
HW
738
739 /* release existing surfaces*/
ab2541b6
AC
740 for (i = 0; i < stream_status->surface_count; i++)
741 dc_surface_release(stream_status->surfaces[i]);
4562236b 742
ab2541b6
AC
743 for (i = surface_count; i < stream_status->surface_count; i++)
744 stream_status->surfaces[i] = NULL;
4562236b 745
ab2541b6 746 stream_status->surface_count = 0;
4562236b
HW
747
748 if (surface_count == 0)
749 return true;
750
751 tail_pipe = NULL;
752 for (i = 0; i < surface_count; i++) {
753 struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]);
ab2541b6
AC
754 struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream(
755 &context->res_ctx, dc_stream);
4562236b
HW
756
757 if (!free_pipe) {
ab2541b6 758 stream_status->surfaces[i] = NULL;
4562236b
HW
759 return false;
760 }
761
762 free_pipe->surface = surface;
763
764 if (tail_pipe) {
765 free_pipe->top_pipe = tail_pipe;
766 tail_pipe->bottom_pipe = free_pipe;
767 }
768
769 tail_pipe = free_pipe;
770 }
771
ab2541b6 772 release_free_pipes_for_stream(&context->res_ctx, dc_stream);
4562236b
HW
773
774 /* assign new surfaces*/
775 for (i = 0; i < surface_count; i++)
ab2541b6 776 stream_status->surfaces[i] = surfaces[i];
4562236b 777
ab2541b6 778 stream_status->surface_count = surface_count;
4562236b
HW
779
780 return true;
781}
782
783
784static bool is_timing_changed(const struct core_stream *cur_stream,
785 const struct core_stream *new_stream)
786{
787 if (cur_stream == NULL)
788 return true;
789
790 /* If sink pointer changed, it means this is a hotplug, we should do
791 * full hw setting.
792 */
793 if (cur_stream->sink != new_stream->sink)
794 return true;
795
796 /* If output color space is changed, need to reprogram info frames */
797 if (cur_stream->public.output_color_space !=
798 new_stream->public.output_color_space)
799 return true;
800
801 return memcmp(
802 &cur_stream->public.timing,
803 &new_stream->public.timing,
804 sizeof(struct dc_crtc_timing)) != 0;
805}
806
807static bool are_stream_backends_same(
808 const struct core_stream *stream_a, const struct core_stream *stream_b)
809{
810 if (stream_a == stream_b)
811 return true;
812
813 if (stream_a == NULL || stream_b == NULL)
814 return false;
815
816 if (is_timing_changed(stream_a, stream_b))
817 return false;
818
819 return true;
820}
821
ab2541b6
AC
822bool is_stream_unchanged(
823 const struct core_stream *old_stream, const struct core_stream *stream)
4562236b 824{
ab2541b6 825 if (old_stream == stream)
4562236b 826 return true;
4562236b 827
ab2541b6
AC
828 if (!are_stream_backends_same(old_stream, stream))
829 return false;
4562236b
HW
830
831 return true;
832}
833
834bool resource_validate_attach_surfaces(
835 const struct dc_validation_set set[],
836 int set_count,
837 const struct validate_context *old_context,
838 struct validate_context *context)
839{
840 int i, j;
841
842 for (i = 0; i < set_count; i++) {
ab2541b6
AC
843 for (j = 0; j < old_context->stream_count; j++)
844 if (is_stream_unchanged(
845 old_context->streams[j],
846 context->streams[i])) {
4562236b 847 if (!resource_attach_surfaces_to_context(
ab2541b6
AC
848 old_context->stream_status[j].surfaces,
849 old_context->stream_status[j].surface_count,
850 &context->streams[i]->public,
4562236b
HW
851 context))
852 return false;
ab2541b6 853 context->stream_status[i] = old_context->stream_status[j];
4562236b
HW
854 }
855 if (set[i].surface_count != 0)
856 if (!resource_attach_surfaces_to_context(
857 set[i].surfaces,
858 set[i].surface_count,
ab2541b6 859 &context->streams[i]->public,
4562236b
HW
860 context))
861 return false;
862
863 }
864
865 return true;
866}
867
868/* Maximum TMDS single link pixel clock 165MHz */
869#define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000
870
871static void set_stream_engine_in_use(
872 struct resource_context *res_ctx,
873 struct stream_encoder *stream_enc)
874{
875 int i;
876
877 for (i = 0; i < res_ctx->pool->stream_enc_count; i++) {
878 if (res_ctx->pool->stream_enc[i] == stream_enc)
879 res_ctx->is_stream_enc_acquired[i] = true;
880 }
881}
882
883/* TODO: release audio object */
884static void set_audio_in_use(
885 struct resource_context *res_ctx,
886 struct audio *audio)
887{
888 int i;
889 for (i = 0; i < res_ctx->pool->audio_count; i++) {
890 if (res_ctx->pool->audios[i] == audio) {
891 res_ctx->is_audio_acquired[i] = true;
892 }
893 }
894}
895
896static int acquire_first_free_pipe(
897 struct resource_context *res_ctx,
898 struct core_stream *stream)
899{
900 int i;
901
902 for (i = 0; i < res_ctx->pool->pipe_count; i++) {
903 if (!res_ctx->pipe_ctx[i].stream) {
904 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
905
906 pipe_ctx->tg = res_ctx->pool->timing_generators[i];
907 pipe_ctx->mi = res_ctx->pool->mis[i];
908 pipe_ctx->ipp = res_ctx->pool->ipps[i];
909 pipe_ctx->xfm = res_ctx->pool->transforms[i];
910 pipe_ctx->opp = res_ctx->pool->opps[i];
911 pipe_ctx->dis_clk = res_ctx->pool->display_clock;
912 pipe_ctx->pipe_idx = i;
913
914 pipe_ctx->stream = stream;
915 return i;
916 }
917 }
918 return -1;
919}
920
921static struct stream_encoder *find_first_free_match_stream_enc_for_link(
922 struct resource_context *res_ctx,
923 struct core_stream *stream)
924{
925 int i;
926 int j = -1;
927 struct core_link *link = stream->sink->link;
928
929 for (i = 0; i < res_ctx->pool->stream_enc_count; i++) {
930 if (!res_ctx->is_stream_enc_acquired[i] &&
931 res_ctx->pool->stream_enc[i]) {
932 /* Store first available for MST second display
933 * in daisy chain use case */
934 j = i;
935 if (res_ctx->pool->stream_enc[i]->id ==
936 link->link_enc->preferred_engine)
937 return res_ctx->pool->stream_enc[i];
938 }
939 }
940
941 /*
942 * below can happen in cases when stream encoder is acquired:
943 * 1) for second MST display in chain, so preferred engine already
944 * acquired;
945 * 2) for another link, which preferred engine already acquired by any
946 * MST configuration.
947 *
948 * If signal is of DP type and preferred engine not found, return last available
949 *
950 * TODO - This is just a patch up and a generic solution is
951 * required for non DP connectors.
952 */
953
954 if (j >= 0 && dc_is_dp_signal(stream->signal))
955 return res_ctx->pool->stream_enc[j];
956
957 return NULL;
958}
959
960static struct audio *find_first_free_audio(struct resource_context *res_ctx)
961{
962 int i;
963 for (i = 0; i < res_ctx->pool->audio_count; i++) {
964 if (res_ctx->is_audio_acquired[i] == false) {
965 return res_ctx->pool->audios[i];
966 }
967 }
968
969 return 0;
970}
971
972static void update_stream_signal(struct core_stream *stream)
973{
974 const struct dc_sink *dc_sink = stream->public.sink;
975
2796eaee
JA
976 if (dc_sink->sink_signal == SIGNAL_TYPE_NONE)
977 stream->signal = stream->sink->link->public.connector_signal;
978 else if (dc_sink->sink_signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
979 dc_sink->sink_signal == SIGNAL_TYPE_DVI_DUAL_LINK)
980 /* For asic supports dual link DVI, we should adjust signal type
981 * based on timing pixel clock. If pixel clock more than 165Mhz,
982 * signal is dual link, otherwise, single link.
983 */
984 if (stream->public.timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ)
4562236b
HW
985 stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK;
986 else
987 stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
2796eaee
JA
988 else
989 stream->signal = dc_sink->sink_signal;
4562236b
HW
990}
991
992bool resource_is_stream_unchanged(
ab2541b6 993 const struct validate_context *old_context, const struct core_stream *stream)
4562236b 994{
ab2541b6 995 int i;
4562236b 996
ab2541b6
AC
997 for (i = 0; i < old_context->stream_count; i++) {
998 const struct core_stream *old_stream = old_context->streams[i];
4562236b 999
ab2541b6 1000 if (are_stream_backends_same(old_stream, stream))
4562236b 1001 return true;
4562236b
HW
1002 }
1003
1004 return false;
1005}
1006
1007static void copy_pipe_ctx(
1008 const struct pipe_ctx *from_pipe_ctx, struct pipe_ctx *to_pipe_ctx)
1009{
1010 struct core_surface *surface = to_pipe_ctx->surface;
1011 struct core_stream *stream = to_pipe_ctx->stream;
1012
1013 *to_pipe_ctx = *from_pipe_ctx;
1014 to_pipe_ctx->stream = stream;
1015 if (surface != NULL)
1016 to_pipe_ctx->surface = surface;
1017}
1018
1019static struct core_stream *find_pll_sharable_stream(
1020 const struct core_stream *stream_needs_pll,
1021 struct validate_context *context)
1022{
ab2541b6 1023 int i;
4562236b 1024
ab2541b6
AC
1025 for (i = 0; i < context->stream_count; i++) {
1026 struct core_stream *stream_has_pll = context->streams[i];
4562236b 1027
ab2541b6
AC
1028 /* We are looking for non dp, non virtual stream */
1029 if (resource_are_streams_timing_synchronizable(
1030 stream_needs_pll, stream_has_pll)
1031 && !dc_is_dp_signal(stream_has_pll->signal)
1032 && stream_has_pll->sink->link->public.connector_signal
1033 != SIGNAL_TYPE_VIRTUAL)
1034 return stream_has_pll;
4562236b 1035
4562236b
HW
1036 }
1037
1038 return NULL;
1039}
1040
1041static int get_norm_pix_clk(const struct dc_crtc_timing *timing)
1042{
1043 uint32_t pix_clk = timing->pix_clk_khz;
1044 uint32_t normalized_pix_clk = pix_clk;
1045
1046 if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
1047 pix_clk /= 2;
cc4d99b8
CL
1048 if (timing->pixel_encoding != PIXEL_ENCODING_YCBCR422) {
1049 switch (timing->display_color_depth) {
1050 case COLOR_DEPTH_888:
1051 normalized_pix_clk = pix_clk;
1052 break;
1053 case COLOR_DEPTH_101010:
1054 normalized_pix_clk = (pix_clk * 30) / 24;
1055 break;
1056 case COLOR_DEPTH_121212:
1057 normalized_pix_clk = (pix_clk * 36) / 24;
4562236b 1058 break;
cc4d99b8
CL
1059 case COLOR_DEPTH_161616:
1060 normalized_pix_clk = (pix_clk * 48) / 24;
4562236b 1061 break;
cc4d99b8
CL
1062 default:
1063 ASSERT(0);
4562236b 1064 break;
cc4d99b8 1065 }
4562236b 1066 }
4562236b
HW
1067 return normalized_pix_clk;
1068}
1069
1070static void calculate_phy_pix_clks(
1071 const struct core_dc *dc,
1072 struct validate_context *context)
1073{
ab2541b6 1074 int i;
4562236b 1075
ab2541b6
AC
1076 for (i = 0; i < context->stream_count; i++) {
1077 struct core_stream *stream = context->streams[i];
4562236b 1078
ab2541b6 1079 update_stream_signal(stream);
4562236b 1080
ab2541b6
AC
1081 /* update actual pixel clock on all streams */
1082 if (dc_is_hdmi_signal(stream->signal))
1083 stream->phy_pix_clk = get_norm_pix_clk(
1084 &stream->public.timing);
1085 else
1086 stream->phy_pix_clk =
1087 stream->public.timing.pix_clk_khz;
4562236b
HW
1088 }
1089}
1090
1091enum dc_status resource_map_pool_resources(
1092 const struct core_dc *dc,
1093 struct validate_context *context)
1094{
ab2541b6 1095 int i, j;
4562236b
HW
1096
1097 calculate_phy_pix_clks(dc, context);
1098
ab2541b6
AC
1099 for (i = 0; i < context->stream_count; i++) {
1100 struct core_stream *stream = context->streams[i];
4562236b 1101
ab2541b6
AC
1102 if (!resource_is_stream_unchanged(dc->current_context, stream))
1103 continue;
4562236b 1104
ab2541b6
AC
1105 /* mark resources used for stream that is already active */
1106 for (j = 0; j < MAX_PIPES; j++) {
1107 struct pipe_ctx *pipe_ctx =
1108 &context->res_ctx.pipe_ctx[j];
1109 const struct pipe_ctx *old_pipe_ctx =
1110 &dc->current_context->res_ctx.pipe_ctx[j];
4562236b 1111
ab2541b6
AC
1112 if (!are_stream_backends_same(old_pipe_ctx->stream, stream))
1113 continue;
8c737fcc 1114
ab2541b6
AC
1115 pipe_ctx->stream = stream;
1116 copy_pipe_ctx(old_pipe_ctx, pipe_ctx);
4562236b 1117
ab2541b6
AC
1118 /* Split pipe resource, do not acquire back end */
1119 if (!pipe_ctx->stream_enc)
1120 continue;
4562236b 1121
ab2541b6
AC
1122 set_stream_engine_in_use(
1123 &context->res_ctx,
1124 pipe_ctx->stream_enc);
1125
1126 /* Switch to dp clock source only if there is
1127 * no non dp stream that shares the same timing
1128 * with the dp stream.
1129 */
1130 if (dc_is_dp_signal(pipe_ctx->stream->signal) &&
1131 !find_pll_sharable_stream(stream, context))
1132 pipe_ctx->clock_source =
1133 context->res_ctx.pool->dp_clock_source;
1134
1135 resource_reference_clock_source(
1136 &context->res_ctx,
1137 pipe_ctx->clock_source);
1138
1139 set_audio_in_use(&context->res_ctx,
1140 pipe_ctx->audio);
4562236b
HW
1141 }
1142 }
1143
ab2541b6
AC
1144 for (i = 0; i < context->stream_count; i++) {
1145 struct core_stream *stream = context->streams[i];
1146 struct pipe_ctx *pipe_ctx = NULL;
1147 int pipe_idx = -1;
4562236b 1148
ab2541b6
AC
1149 if (resource_is_stream_unchanged(dc->current_context, stream))
1150 continue;
1151 /* acquire new resources */
1152 pipe_idx = acquire_first_free_pipe(&context->res_ctx, stream);
1153 if (pipe_idx < 0)
1154 return DC_NO_CONTROLLER_RESOURCE;
1155
1156
1157 pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx];
1158
1159 pipe_ctx->stream_enc =
1160 find_first_free_match_stream_enc_for_link(
1161 &context->res_ctx, stream);
1162
1163 if (!pipe_ctx->stream_enc)
1164 return DC_NO_STREAM_ENG_RESOURCE;
1165
1166 set_stream_engine_in_use(
1167 &context->res_ctx,
1168 pipe_ctx->stream_enc);
1169
1170 /* TODO: Add check if ASIC support and EDID audio */
1171 if (!stream->sink->converter_disable_audio &&
1172 dc_is_audio_capable_signal(pipe_ctx->stream->signal) &&
1173 stream->public.audio_info.mode_count) {
1174 pipe_ctx->audio = find_first_free_audio(
1175 &context->res_ctx);
1176
1177 /*
1178 * Audio assigned in order first come first get.
1179 * There are asics which has number of audio
1180 * resources less then number of pipes
1181 */
1182 if (pipe_ctx->audio)
1183 set_audio_in_use(
4562236b 1184 &context->res_ctx,
ab2541b6 1185 pipe_ctx->audio);
4562236b 1186 }
ab2541b6
AC
1187
1188 context->stream_status[i].primary_otg_inst = pipe_ctx->tg->inst;
4562236b
HW
1189 }
1190
1191 return DC_OK;
1192}
1193
ab2541b6
AC
1194/* first stream in the context is used to populate the rest */
1195void validate_guaranteed_copy_streams(
4562236b 1196 struct validate_context *context,
ab2541b6 1197 int max_streams)
4562236b
HW
1198{
1199 int i;
1200
ab2541b6
AC
1201 for (i = 1; i < max_streams; i++) {
1202 context->streams[i] = context->streams[0];
4562236b
HW
1203
1204 copy_pipe_ctx(&context->res_ctx.pipe_ctx[0],
1205 &context->res_ctx.pipe_ctx[i]);
1206 context->res_ctx.pipe_ctx[i].stream =
1207 context->res_ctx.pipe_ctx[0].stream;
1208
ab2541b6
AC
1209 dc_stream_retain(&context->streams[i]->public);
1210 context->stream_count++;
4562236b
HW
1211 }
1212}
1213
6e4d6bee
TC
1214static void patch_gamut_packet_checksum(
1215 struct encoder_info_packet *gamut_packet)
4562236b 1216{
4562236b 1217 /* For gamut we recalc checksum */
6e4d6bee 1218 if (gamut_packet->valid) {
4562236b
HW
1219 uint8_t chk_sum = 0;
1220 uint8_t *ptr;
1221 uint8_t i;
1222
4562236b 1223 /*start of the Gamut data. */
6e4d6bee 1224 ptr = &gamut_packet->sb[3];
4562236b 1225
6e4d6bee 1226 for (i = 0; i <= gamut_packet->sb[1]; i++)
4562236b
HW
1227 chk_sum += ptr[i];
1228
6e4d6bee 1229 gamut_packet->sb[2] = (uint8_t) (0x100 - chk_sum);
1646a6fe 1230 }
4562236b
HW
1231}
1232
1233static void set_avi_info_frame(
6e4d6bee 1234 struct encoder_info_packet *info_packet,
4562236b
HW
1235 struct pipe_ctx *pipe_ctx)
1236{
1237 struct core_stream *stream = pipe_ctx->stream;
1238 enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
1239 struct info_frame info_frame = { {0} };
1240 uint32_t pixel_encoding = 0;
1241 enum scanning_type scan_type = SCANNING_TYPE_NODATA;
1242 enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA;
1243 bool itc = false;
1244 uint8_t cn0_cn1 = 0;
1245 uint8_t *check_sum = NULL;
1246 uint8_t byte_index = 0;
1247
4562236b
HW
1248 color_space = pipe_ctx->stream->public.output_color_space;
1249
1250 /* Initialize header */
1251 info_frame.avi_info_packet.info_packet_hdmi.bits.header.
3e183c5f 1252 info_frame_type = HDMI_INFOFRAME_TYPE_AVI;
4562236b
HW
1253 /* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall
1254 * not be used in HDMI 2.0 (Section 10.1) */
3e183c5f 1255 info_frame.avi_info_packet.info_packet_hdmi.bits.header.version = 2;
4562236b 1256 info_frame.avi_info_packet.info_packet_hdmi.bits.header.length =
3e183c5f 1257 HDMI_AVI_INFOFRAME_SIZE;
4562236b
HW
1258
1259 /*
1260 * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built
1261 * according to HDMI 2.0 spec (Section 10.1)
1262 */
1263
1264 switch (stream->public.timing.pixel_encoding) {
1265 case PIXEL_ENCODING_YCBCR422:
1266 pixel_encoding = 1;
1267 break;
1268
1269 case PIXEL_ENCODING_YCBCR444:
1270 pixel_encoding = 2;
1271 break;
1272 case PIXEL_ENCODING_YCBCR420:
1273 pixel_encoding = 3;
1274 break;
1275
1276 case PIXEL_ENCODING_RGB:
1277 default:
1278 pixel_encoding = 0;
1279 }
1280
1281 /* Y0_Y1_Y2 : The pixel encoding */
1282 /* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */
1283 info_frame.avi_info_packet.info_packet_hdmi.bits.Y0_Y1_Y2 =
1284 pixel_encoding;
1285
1286 /* A0 = 1 Active Format Information valid */
1287 info_frame.avi_info_packet.info_packet_hdmi.bits.A0 =
1288 ACTIVE_FORMAT_VALID;
1289
1290 /* B0, B1 = 3; Bar info data is valid */
1291 info_frame.avi_info_packet.info_packet_hdmi.bits.B0_B1 =
1292 BAR_INFO_BOTH_VALID;
1293
1294 info_frame.avi_info_packet.info_packet_hdmi.bits.SC0_SC1 =
1295 PICTURE_SCALING_UNIFORM;
1296
1297 /* S0, S1 : Underscan / Overscan */
1298 /* TODO: un-hardcode scan type */
1299 scan_type = SCANNING_TYPE_UNDERSCAN;
1300 info_frame.avi_info_packet.info_packet_hdmi.bits.S0_S1 = scan_type;
1301
1302 /* C0, C1 : Colorimetry */
8fde5884
CL
1303 if (color_space == COLOR_SPACE_YCBCR709 ||
1304 color_space == COLOR_SPACE_YCBCR709_LIMITED)
4562236b
HW
1305 info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
1306 COLORIMETRY_ITU709;
8fde5884
CL
1307 else if (color_space == COLOR_SPACE_YCBCR601 ||
1308 color_space == COLOR_SPACE_YCBCR601_LIMITED)
4562236b
HW
1309 info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
1310 COLORIMETRY_ITU601;
8fde5884
CL
1311 else {
1312 if (stream->public.timing.pixel_encoding != PIXEL_ENCODING_RGB)
1313 BREAK_TO_DEBUGGER();
4562236b
HW
1314 info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
1315 COLORIMETRY_NO_DATA;
8fde5884 1316 }
534db198 1317 if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE ||
8fde5884
CL
1318 color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE ||
1319 color_space == COLOR_SPACE_2020_YCBCR) {
534db198
AZ
1320 info_frame.avi_info_packet.info_packet_hdmi.bits.EC0_EC2 =
1321 COLORIMETRYEX_BT2020RGBYCBCR;
1322 info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
1323 COLORIMETRY_EXTENDED;
1324 } else if (color_space == COLOR_SPACE_ADOBERGB) {
1325 info_frame.avi_info_packet.info_packet_hdmi.bits.EC0_EC2 =
1326 COLORIMETRYEX_ADOBERGB;
1327 info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
1328 COLORIMETRY_EXTENDED;
1329 }
1330
4562236b
HW
1331 /* TODO: un-hardcode aspect ratio */
1332 aspect = stream->public.timing.aspect_ratio;
1333
1334 switch (aspect) {
1335 case ASPECT_RATIO_4_3:
1336 case ASPECT_RATIO_16_9:
1337 info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = aspect;
1338 break;
1339
1340 case ASPECT_RATIO_NO_DATA:
1341 case ASPECT_RATIO_64_27:
1342 case ASPECT_RATIO_256_135:
1343 default:
1344 info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = 0;
1345 }
1346
1347 /* Active Format Aspect ratio - same as Picture Aspect Ratio. */
1348 info_frame.avi_info_packet.info_packet_hdmi.bits.R0_R3 =
1349 ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE;
1350
1351 /* TODO: un-hardcode cn0_cn1 and itc */
1352 cn0_cn1 = 0;
1353 itc = false;
1354
1355 if (itc) {
1356 info_frame.avi_info_packet.info_packet_hdmi.bits.ITC = 1;
1357 info_frame.avi_info_packet.info_packet_hdmi.bits.CN0_CN1 =
1358 cn0_cn1;
1359 }
1360
1361 /* TODO : We should handle YCC quantization */
1362 /* but we do not have matrix calculation */
1363 if (color_space == COLOR_SPACE_SRGB) {
1364 info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
1365 RGB_QUANTIZATION_FULL_RANGE;
1366 info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 =
1367 YYC_QUANTIZATION_FULL_RANGE;
1368 } else if (color_space == COLOR_SPACE_SRGB_LIMITED) {
1369 info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
1370 RGB_QUANTIZATION_LIMITED_RANGE;
1371 info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 =
1372 YYC_QUANTIZATION_LIMITED_RANGE;
1373 } else {
1374 info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
1375 RGB_QUANTIZATION_DEFAULT_RANGE;
1376 info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 =
1377 YYC_QUANTIZATION_LIMITED_RANGE;
1378 }
1379
1380 info_frame.avi_info_packet.info_packet_hdmi.bits.VIC0_VIC7 =
1381 stream->public.timing.vic;
1382
1383 /* pixel repetition
1384 * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel
1385 * repetition start from 1 */
1386 info_frame.avi_info_packet.info_packet_hdmi.bits.PR0_PR3 = 0;
1387
1388 /* Bar Info
1389 * barTop: Line Number of End of Top Bar.
1390 * barBottom: Line Number of Start of Bottom Bar.
1391 * barLeft: Pixel Number of End of Left Bar.
1392 * barRight: Pixel Number of Start of Right Bar. */
1393 info_frame.avi_info_packet.info_packet_hdmi.bits.bar_top =
1394 stream->public.timing.v_border_top;
1395 info_frame.avi_info_packet.info_packet_hdmi.bits.bar_bottom =
1396 (stream->public.timing.v_border_top
1397 - stream->public.timing.v_border_bottom + 1);
1398 info_frame.avi_info_packet.info_packet_hdmi.bits.bar_left =
1399 stream->public.timing.h_border_left;
1400 info_frame.avi_info_packet.info_packet_hdmi.bits.bar_right =
1401 (stream->public.timing.h_total
1402 - stream->public.timing.h_border_right + 1);
1403
1404 /* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */
1405 check_sum =
1406 &info_frame.
1407 avi_info_packet.info_packet_hdmi.packet_raw_data.sb[0];
3e183c5f 1408 *check_sum = HDMI_INFOFRAME_TYPE_AVI + HDMI_AVI_INFOFRAME_SIZE + 2;
4562236b 1409
3e183c5f 1410 for (byte_index = 1; byte_index <= HDMI_AVI_INFOFRAME_SIZE; byte_index++)
4562236b
HW
1411 *check_sum += info_frame.avi_info_packet.info_packet_hdmi.
1412 packet_raw_data.sb[byte_index];
1413
1414 /* one byte complement */
1415 *check_sum = (uint8_t) (0x100 - *check_sum);
1416
1417 /* Store in hw_path_mode */
1418 info_packet->hb0 =
1419 info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb0;
1420 info_packet->hb1 =
1421 info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb1;
1422 info_packet->hb2 =
1423 info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb2;
1424
e66e4d64
HW
1425 for (byte_index = 0; byte_index < sizeof(info_frame.avi_info_packet.
1426 info_packet_hdmi.packet_raw_data.sb); byte_index++)
4562236b 1427 info_packet->sb[byte_index] = info_frame.avi_info_packet.
e66e4d64 1428 info_packet_hdmi.packet_raw_data.sb[byte_index];
4562236b
HW
1429
1430 info_packet->valid = true;
1431}
1432
6e4d6bee
TC
1433static void set_vendor_info_packet(
1434 struct encoder_info_packet *info_packet,
1435 struct core_stream *stream)
4562236b
HW
1436{
1437 uint32_t length = 0;
1438 bool hdmi_vic_mode = false;
1439 uint8_t checksum = 0;
1440 uint32_t i = 0;
1441 enum dc_timing_3d_format format;
1442
4562236b
HW
1443 format = stream->public.timing.timing_3d_format;
1444
1445 /* Can be different depending on packet content */
1446 length = 5;
1447
1448 if (stream->public.timing.hdmi_vic != 0
1449 && stream->public.timing.h_total >= 3840
1450 && stream->public.timing.v_total >= 2160)
1451 hdmi_vic_mode = true;
1452
1453 /* According to HDMI 1.4a CTS, VSIF should be sent
1454 * for both 3D stereo and HDMI VIC modes.
1455 * For all other modes, there is no VSIF sent. */
1456
1457 if (format == TIMING_3D_FORMAT_NONE && !hdmi_vic_mode)
1458 return;
1459
1460 /* 24bit IEEE Registration identifier (0x000c03). LSB first. */
1461 info_packet->sb[1] = 0x03;
1462 info_packet->sb[2] = 0x0C;
1463 info_packet->sb[3] = 0x00;
1464
1465 /*PB4: 5 lower bytes = 0 (reserved). 3 higher bits = HDMI_Video_Format.
1466 * The value for HDMI_Video_Format are:
1467 * 0x0 (0b000) - No additional HDMI video format is presented in this
1468 * packet
1469 * 0x1 (0b001) - Extended resolution format present. 1 byte of HDMI_VIC
1470 * parameter follows
1471 * 0x2 (0b010) - 3D format indication present. 3D_Structure and
1472 * potentially 3D_Ext_Data follows
1473 * 0x3..0x7 (0b011..0b111) - reserved for future use */
1474 if (format != TIMING_3D_FORMAT_NONE)
1475 info_packet->sb[4] = (2 << 5);
1476 else if (hdmi_vic_mode)
1477 info_packet->sb[4] = (1 << 5);
1478
1479 /* PB5: If PB4 claims 3D timing (HDMI_Video_Format = 0x2):
1480 * 4 lower bites = 0 (reserved). 4 higher bits = 3D_Structure.
1481 * The value for 3D_Structure are:
1482 * 0x0 - Frame Packing
1483 * 0x1 - Field Alternative
1484 * 0x2 - Line Alternative
1485 * 0x3 - Side-by-Side (full)
1486 * 0x4 - L + depth
1487 * 0x5 - L + depth + graphics + graphics-depth
1488 * 0x6 - Top-and-Bottom
1489 * 0x7 - Reserved for future use
1490 * 0x8 - Side-by-Side (Half)
1491 * 0x9..0xE - Reserved for future use
1492 * 0xF - Not used */
1493 switch (format) {
1494 case TIMING_3D_FORMAT_HW_FRAME_PACKING:
1495 case TIMING_3D_FORMAT_SW_FRAME_PACKING:
1496 info_packet->sb[5] = (0x0 << 4);
1497 break;
1498
1499 case TIMING_3D_FORMAT_SIDE_BY_SIDE:
1500 case TIMING_3D_FORMAT_SBS_SW_PACKED:
1501 info_packet->sb[5] = (0x8 << 4);
1502 length = 6;
1503 break;
1504
1505 case TIMING_3D_FORMAT_TOP_AND_BOTTOM:
1506 case TIMING_3D_FORMAT_TB_SW_PACKED:
1507 info_packet->sb[5] = (0x6 << 4);
1508 break;
1509
1510 default:
1511 break;
1512 }
1513
1514 /*PB5: If PB4 is set to 0x1 (extended resolution format)
1515 * fill PB5 with the correct HDMI VIC code */
1516 if (hdmi_vic_mode)
1517 info_packet->sb[5] = stream->public.timing.hdmi_vic;
1518
1519 /* Header */
3e183c5f 1520 info_packet->hb0 = HDMI_INFOFRAME_TYPE_VENDOR; /* VSIF packet type. */
4562236b
HW
1521 info_packet->hb1 = 0x01; /* Version */
1522
1523 /* 4 lower bits = Length, 4 higher bits = 0 (reserved) */
1524 info_packet->hb2 = (uint8_t) (length);
1525
1526 /* Calculate checksum */
1527 checksum = 0;
1528 checksum += info_packet->hb0;
1529 checksum += info_packet->hb1;
1530 checksum += info_packet->hb2;
1531
1532 for (i = 1; i <= length; i++)
1533 checksum += info_packet->sb[i];
1534
1535 info_packet->sb[0] = (uint8_t) (0x100 - checksum);
1536
1537 info_packet->valid = true;
1538}
1539
6e4d6bee
TC
1540static void set_spd_info_packet(
1541 struct encoder_info_packet *info_packet,
1542 struct core_stream *stream)
4562236b
HW
1543{
1544 /* SPD info packet for FreeSync */
1545
1546 unsigned char checksum = 0;
1547 unsigned int idx, payload_size = 0;
1548
1549 /* Check if Freesync is supported. Return if false. If true,
1550 * set the corresponding bit in the info packet
1551 */
1552 if (stream->public.freesync_ctx.supported == false)
1553 return;
1554
1555 if (dc_is_hdmi_signal(stream->signal)) {
1556
1557 /* HEADER */
1558
1559 /* HB0 = Packet Type = 0x83 (Source Product
1560 * Descriptor InfoFrame)
1561 */
3e183c5f 1562 info_packet->hb0 = HDMI_INFOFRAME_TYPE_SPD;
4562236b
HW
1563
1564 /* HB1 = Version = 0x01 */
1565 info_packet->hb1 = 0x01;
1566
1567 /* HB2 = [Bits 7:5 = 0] [Bits 4:0 = Length = 0x08] */
1568 info_packet->hb2 = 0x08;
1569
1570 payload_size = 0x08;
1571
1572 } else if (dc_is_dp_signal(stream->signal)) {
1573
1574 /* HEADER */
1575
1576 /* HB0 = Secondary-data Packet ID = 0 - Only non-zero
1577 * when used to associate audio related info packets
1578 */
1579 info_packet->hb0 = 0x00;
1580
1581 /* HB1 = Packet Type = 0x83 (Source Product
1582 * Descriptor InfoFrame)
1583 */
3e183c5f 1584 info_packet->hb1 = HDMI_INFOFRAME_TYPE_SPD;
4562236b
HW
1585
1586 /* HB2 = [Bits 7:0 = Least significant eight bits -
1587 * For INFOFRAME, the value must be 1Bh]
1588 */
1589 info_packet->hb2 = 0x1B;
1590
1591 /* HB3 = [Bits 7:2 = INFOFRAME SDP Version Number = 0x1]
1592 * [Bits 1:0 = Most significant two bits = 0x00]
1593 */
1594 info_packet->hb3 = 0x04;
1595
1596 payload_size = 0x1B;
1597 }
1598
1599 /* PB1 = 0x1A (24bit AMD IEEE OUI (0x00001A) - Byte 0) */
1600 info_packet->sb[1] = 0x1A;
1601
1602 /* PB2 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 1) */
1603 info_packet->sb[2] = 0x00;
1604
1605 /* PB3 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 2) */
1606 info_packet->sb[3] = 0x00;
1607
1608 /* PB4 = Reserved */
1609 info_packet->sb[4] = 0x00;
1610
1611 /* PB5 = Reserved */
1612 info_packet->sb[5] = 0x00;
1613
1614 /* PB6 = [Bits 7:3 = Reserved] */
1615 info_packet->sb[6] = 0x00;
1616
1617 if (stream->public.freesync_ctx.supported == true)
1618 /* PB6 = [Bit 0 = FreeSync Supported] */
1619 info_packet->sb[6] |= 0x01;
1620
1621 if (stream->public.freesync_ctx.enabled == true)
1622 /* PB6 = [Bit 1 = FreeSync Enabled] */
1623 info_packet->sb[6] |= 0x02;
1624
1625 if (stream->public.freesync_ctx.active == true)
1626 /* PB6 = [Bit 2 = FreeSync Active] */
1627 info_packet->sb[6] |= 0x04;
1628
1629 /* PB7 = FreeSync Minimum refresh rate (Hz) */
1630 info_packet->sb[7] = (unsigned char) (stream->public.freesync_ctx.
1631 min_refresh_in_micro_hz / 1000000);
1632
1633 /* PB8 = FreeSync Maximum refresh rate (Hz)
1634 *
1635 * Note: We do not use the maximum capable refresh rate
1636 * of the panel, because we should never go above the field
1637 * rate of the mode timing set.
1638 */
1639 info_packet->sb[8] = (unsigned char) (stream->public.freesync_ctx.
1640 nominal_refresh_in_micro_hz / 1000000);
1641
1642 /* PB9 - PB27 = Reserved */
1643 for (idx = 9; idx <= 27; idx++)
1644 info_packet->sb[idx] = 0x00;
1645
1646 /* Calculate checksum */
1647 checksum += info_packet->hb0;
1648 checksum += info_packet->hb1;
1649 checksum += info_packet->hb2;
1650 checksum += info_packet->hb3;
1651
1652 for (idx = 1; idx <= payload_size; idx++)
1653 checksum += info_packet->sb[idx];
1654
1655 /* PB0 = Checksum (one byte complement) */
1656 info_packet->sb[0] = (unsigned char) (0x100 - checksum);
1657
1658 info_packet->valid = true;
1659}
1660
1646a6fe 1661static void set_hdr_static_info_packet(
6e4d6bee 1662 struct encoder_info_packet *info_packet,
1646a6fe 1663 struct core_surface *surface,
6e4d6bee 1664 struct core_stream *stream)
1646a6fe 1665{
e5cf325b 1666 uint16_t i = 0;
1646a6fe 1667 enum signal_type signal = stream->signal;
e5cf325b
HW
1668 struct dc_hdr_static_metadata hdr_metadata;
1669 uint32_t data;
1646a6fe
AW
1670
1671 if (!surface)
1672 return;
1673
e5cf325b 1674 hdr_metadata = surface->public.hdr_static_ctx;
1646a6fe 1675
10bff005
YS
1676 if (!hdr_metadata.is_hdr)
1677 return;
1678
1646a6fe
AW
1679 if (dc_is_hdmi_signal(signal)) {
1680 info_packet->valid = true;
1681
1682 info_packet->hb0 = 0x87;
1683 info_packet->hb1 = 0x01;
1684 info_packet->hb2 = 0x1A;
1685 i = 1;
1686 } else if (dc_is_dp_signal(signal)) {
1687 info_packet->valid = true;
1688
1689 info_packet->hb0 = 0x00;
1690 info_packet->hb1 = 0x87;
1691 info_packet->hb2 = 0x1D;
1692 info_packet->hb3 = (0x13 << 2);
1693 i = 2;
1694 }
1695
1646a6fe
AW
1696 data = hdr_metadata.is_hdr;
1697 info_packet->sb[i++] = data ? 0x02 : 0x00;
1698 info_packet->sb[i++] = 0x00;
1699
1700 data = hdr_metadata.chromaticity_green_x / 2;
1701 info_packet->sb[i++] = data & 0xFF;
1702 info_packet->sb[i++] = (data & 0xFF00) >> 8;
1703
1704 data = hdr_metadata.chromaticity_green_y / 2;
1705 info_packet->sb[i++] = data & 0xFF;
1706 info_packet->sb[i++] = (data & 0xFF00) >> 8;
1707
1708 data = hdr_metadata.chromaticity_blue_x / 2;
1709 info_packet->sb[i++] = data & 0xFF;
1710 info_packet->sb[i++] = (data & 0xFF00) >> 8;
1711
1712 data = hdr_metadata.chromaticity_blue_y / 2;
1713 info_packet->sb[i++] = data & 0xFF;
1714 info_packet->sb[i++] = (data & 0xFF00) >> 8;
1715
1716 data = hdr_metadata.chromaticity_red_x / 2;
1717 info_packet->sb[i++] = data & 0xFF;
1718 info_packet->sb[i++] = (data & 0xFF00) >> 8;
1719
1720 data = hdr_metadata.chromaticity_red_y / 2;
1721 info_packet->sb[i++] = data & 0xFF;
1722 info_packet->sb[i++] = (data & 0xFF00) >> 8;
1723
1724 data = hdr_metadata.chromaticity_white_point_x / 2;
1725 info_packet->sb[i++] = data & 0xFF;
1726 info_packet->sb[i++] = (data & 0xFF00) >> 8;
1727
1728 data = hdr_metadata.chromaticity_white_point_y / 2;
1729 info_packet->sb[i++] = data & 0xFF;
1730 info_packet->sb[i++] = (data & 0xFF00) >> 8;
1731
1732 data = hdr_metadata.max_luminance;
1733 info_packet->sb[i++] = data & 0xFF;
1734 info_packet->sb[i++] = (data & 0xFF00) >> 8;
1735
1736 data = hdr_metadata.min_luminance;
1737 info_packet->sb[i++] = data & 0xFF;
1738 info_packet->sb[i++] = (data & 0xFF00) >> 8;
1739
1740 data = hdr_metadata.maximum_content_light_level;
1741 info_packet->sb[i++] = data & 0xFF;
1742 info_packet->sb[i++] = (data & 0xFF00) >> 8;
1743
1744 data = hdr_metadata.maximum_frame_average_light_level;
1745 info_packet->sb[i++] = data & 0xFF;
1746 info_packet->sb[i++] = (data & 0xFF00) >> 8;
1747
1748 if (dc_is_hdmi_signal(signal)) {
1749 uint32_t checksum = 0;
1750
1751 checksum += info_packet->hb0;
1752 checksum += info_packet->hb1;
1753 checksum += info_packet->hb2;
1754
1755 for (i = 1; i <= info_packet->hb2; i++)
1756 checksum += info_packet->sb[i];
1757
1758 info_packet->sb[0] = 0x100 - checksum;
1759 } else if (dc_is_dp_signal(signal)) {
1760 info_packet->sb[0] = 0x01;
1761 info_packet->sb[1] = 0x1A;
1762 }
1763}
1764
6e4d6bee
TC
1765static void set_vsc_info_packet(
1766 struct encoder_info_packet *info_packet,
1767 struct core_stream *stream)
4562236b
HW
1768{
1769 unsigned int vscPacketRevision = 0;
1770 unsigned int i;
1771
1772 if (stream->sink->link->public.psr_caps.psr_version != 0) {
1773 vscPacketRevision = 2;
1774 }
1775
1776 /* VSC packet not needed based on the features
1777 * supported by this DP display
1778 */
1779 if (vscPacketRevision == 0)
1780 return;
1781
1782 if (vscPacketRevision == 0x2) {
1783 /* Secondary-data Packet ID = 0*/
1784 info_packet->hb0 = 0x00;
1785 /* 07h - Packet Type Value indicating Video
1786 * Stream Configuration packet
1787 */
1788 info_packet->hb1 = 0x07;
1789 /* 02h = VSC SDP supporting 3D stereo and PSR
1790 * (applies to eDP v1.3 or higher).
1791 */
1792 info_packet->hb2 = 0x02;
1793 /* 08h = VSC packet supporting 3D stereo + PSR
1794 * (HB2 = 02h).
1795 */
1796 info_packet->hb3 = 0x08;
1797
1798 for (i = 0; i < 28; i++)
1799 info_packet->sb[i] = 0;
1800
1801 info_packet->valid = true;
1802 }
1803
1804 /*TODO: stereo 3D support and extend pixel encoding colorimetry*/
1805}
1806
1807void resource_validate_ctx_destruct(struct validate_context *context)
1808{
1809 int i, j;
1810
ab2541b6
AC
1811 for (i = 0; i < context->stream_count; i++) {
1812 for (j = 0; j < context->stream_status[i].surface_count; j++)
4562236b 1813 dc_surface_release(
ab2541b6 1814 context->stream_status[i].surfaces[j]);
4562236b 1815
ab2541b6
AC
1816 context->stream_status[i].surface_count = 0;
1817 dc_stream_release(&context->streams[i]->public);
1818 context->streams[i] = NULL;
4562236b
HW
1819 }
1820}
1821
1822/*
ab2541b6 1823 * Copy src_ctx into dst_ctx and retain all surfaces and streams referenced
4562236b
HW
1824 * by the src_ctx
1825 */
1826void resource_validate_ctx_copy_construct(
1827 const struct validate_context *src_ctx,
1828 struct validate_context *dst_ctx)
1829{
1830 int i, j;
1831
1832 *dst_ctx = *src_ctx;
1833
1834 for (i = 0; i < dst_ctx->res_ctx.pool->pipe_count; i++) {
1835 struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i];
1836
1837 if (cur_pipe->top_pipe)
1838 cur_pipe->top_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx];
1839
1840 if (cur_pipe->bottom_pipe)
1841 cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
1842
1843 }
1844
ab2541b6
AC
1845 for (i = 0; i < dst_ctx->stream_count; i++) {
1846 dc_stream_retain(&dst_ctx->streams[i]->public);
1847 for (j = 0; j < dst_ctx->stream_status[i].surface_count; j++)
4562236b 1848 dc_surface_retain(
ab2541b6 1849 dst_ctx->stream_status[i].surfaces[j]);
4562236b
HW
1850 }
1851}
1852
1853struct clock_source *dc_resource_find_first_free_pll(
1854 struct resource_context *res_ctx)
1855{
1856 int i;
1857
1858 for (i = 0; i < res_ctx->pool->clk_src_count; ++i) {
1859 if (res_ctx->clock_source_ref_count[i] == 0)
1860 return res_ctx->pool->clock_sources[i];
1861 }
1862
1863 return NULL;
1864}
1865
1866void resource_build_info_frame(struct pipe_ctx *pipe_ctx)
1867{
1868 enum signal_type signal = SIGNAL_TYPE_NONE;
6e4d6bee 1869 struct encoder_info_frame *info = &pipe_ctx->encoder_info_frame;
4562236b
HW
1870
1871 /* default all packets to invalid */
6e4d6bee
TC
1872 info->avi.valid = false;
1873 info->gamut.valid = false;
1874 info->vendor.valid = false;
1875 info->hdrsmd.valid = false;
1876 info->vsc.valid = false;
4562236b
HW
1877
1878 signal = pipe_ctx->stream->signal;
1879
1880 /* HDMi and DP have different info packets*/
1881 if (dc_is_hdmi_signal(signal)) {
6e4d6bee
TC
1882 set_avi_info_frame(&info->avi, pipe_ctx);
1883
1884 set_vendor_info_packet(&info->vendor, pipe_ctx->stream);
1885
1886 set_spd_info_packet(&info->spd, pipe_ctx->stream);
1887
1888 set_hdr_static_info_packet(&info->hdrsmd,
1889 pipe_ctx->surface, pipe_ctx->stream);
1890
a33fa99d 1891 } else if (dc_is_dp_signal(signal)) {
6e4d6bee
TC
1892 set_vsc_info_packet(&info->vsc, pipe_ctx->stream);
1893
1894 set_spd_info_packet(&info->spd, pipe_ctx->stream);
1895
1896 set_hdr_static_info_packet(&info->hdrsmd,
1897 pipe_ctx->surface, pipe_ctx->stream);
a33fa99d 1898 }
4562236b 1899
6e4d6bee 1900 patch_gamut_packet_checksum(&info->gamut);
4562236b
HW
1901}
1902
1903enum dc_status resource_map_clock_resources(
1904 const struct core_dc *dc,
1905 struct validate_context *context)
1906{
ab2541b6 1907 int i, j;
4562236b
HW
1908
1909 /* acquire new resources */
ab2541b6
AC
1910 for (i = 0; i < context->stream_count; i++) {
1911 const struct core_stream *stream = context->streams[i];
4562236b 1912
ab2541b6
AC
1913 if (resource_is_stream_unchanged(dc->current_context, stream))
1914 continue;
1915
1916 for (j = 0; j < MAX_PIPES; j++) {
1917 struct pipe_ctx *pipe_ctx =
1918 &context->res_ctx.pipe_ctx[j];
4562236b 1919
ab2541b6 1920 if (context->res_ctx.pipe_ctx[j].stream != stream)
4562236b
HW
1921 continue;
1922
ab2541b6
AC
1923 if (dc_is_dp_signal(pipe_ctx->stream->signal)
1924 || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL)
1925 pipe_ctx->clock_source =
1926 context->res_ctx.pool->dp_clock_source;
1927 else {
1928 pipe_ctx->clock_source = NULL;
4562236b 1929
ab2541b6
AC
1930 if (!dc->public.config.disable_disp_pll_sharing)
1931 resource_find_used_clk_src_for_sharing(
1932 &context->res_ctx,
1933 pipe_ctx);
4562236b 1934
ab2541b6 1935 if (pipe_ctx->clock_source == NULL)
4562236b 1936 pipe_ctx->clock_source =
ab2541b6
AC
1937 dc_resource_find_first_free_pll(&context->res_ctx);
1938 }
4562236b 1939
ab2541b6
AC
1940 if (pipe_ctx->clock_source == NULL)
1941 return DC_NO_CLOCK_SOURCE_RESOURCE;
4562236b 1942
ab2541b6
AC
1943 resource_reference_clock_source(
1944 &context->res_ctx,
1945 pipe_ctx->clock_source);
4562236b 1946
ab2541b6
AC
1947 /* only one cs per stream regardless of mpo */
1948 break;
4562236b
HW
1949 }
1950 }
1951
1952 return DC_OK;
1953}
1954
1955/*
1956 * Note: We need to disable output if clock sources change,
1957 * since bios does optimization and doesn't apply if changing
1958 * PHY when not already disabled.
1959 */
1960bool pipe_need_reprogram(
1961 struct pipe_ctx *pipe_ctx_old,
1962 struct pipe_ctx *pipe_ctx)
1963{
1964 if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink)
1965 return true;
1966
1967 if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal)
1968 return true;
1969
1970 if (pipe_ctx_old->audio != pipe_ctx->audio)
1971 return true;
1972
1973 if (pipe_ctx_old->clock_source != pipe_ctx->clock_source
1974 && pipe_ctx_old->stream != pipe_ctx->stream)
1975 return true;
1976
1977 if (pipe_ctx_old->stream_enc != pipe_ctx->stream_enc)
1978 return true;
1979
1980 if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream))
1981 return true;
1982
1983
1984 return false;
1985}