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