]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/gpu/drm/amd/display/dc/core/dc_resource.c
drm/amd/display: Use function pointer for update_plane_addr
[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"
ff5ef992
AD
42#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
43#include "dcn10/dcn10_resource.h"
44#endif
2c8ad2d5 45#include "dce120/dce120_resource.h"
4562236b
HW
46
47enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id)
48{
49 enum dce_version dc_version = DCE_VERSION_UNKNOWN;
50 switch (asic_id.chip_family) {
51
52 case FAMILY_CI:
4562236b
HW
53 dc_version = DCE_VERSION_8_0;
54 break;
ebfdf0d0
AD
55 case FAMILY_KV:
56 if (ASIC_REV_IS_KALINDI(asic_id.hw_internal_rev) ||
57 ASIC_REV_IS_BHAVANI(asic_id.hw_internal_rev) ||
58 ASIC_REV_IS_GODAVARI(asic_id.hw_internal_rev))
59 dc_version = DCE_VERSION_8_3;
60 else
61 dc_version = DCE_VERSION_8_1;
62 break;
4562236b
HW
63 case FAMILY_CZ:
64 dc_version = DCE_VERSION_11_0;
65 break;
66
67 case FAMILY_VI:
68 if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) ||
69 ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) {
70 dc_version = DCE_VERSION_10_0;
71 break;
72 }
73 if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) ||
b264d345
JL
74 ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) ||
75 ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) {
4562236b
HW
76 dc_version = DCE_VERSION_11_2;
77 }
78 break;
2c8ad2d5
AD
79 case FAMILY_AI:
80 dc_version = DCE_VERSION_12_0;
81 break;
ff5ef992
AD
82#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
83 case FAMILY_RV:
84 dc_version = DCN_VERSION_1_0;
85 break;
86#endif
4562236b
HW
87 default:
88 dc_version = DCE_VERSION_UNKNOWN;
89 break;
90 }
91 return dc_version;
92}
93
94struct resource_pool *dc_create_resource_pool(
95 struct core_dc *dc,
96 int num_virtual_links,
97 enum dce_version dc_version,
98 struct hw_asic_id asic_id)
99{
5ac3d3c9 100 struct resource_pool *res_pool = NULL;
4562236b
HW
101
102 switch (dc_version) {
103 case DCE_VERSION_8_0:
7992a629
AD
104 res_pool = dce80_create_resource_pool(
105 num_virtual_links, dc);
106 break;
ebfdf0d0 107 case DCE_VERSION_8_1:
7992a629
AD
108 res_pool = dce81_create_resource_pool(
109 num_virtual_links, dc);
110 break;
ebfdf0d0 111 case DCE_VERSION_8_3:
7992a629 112 res_pool = dce83_create_resource_pool(
4562236b 113 num_virtual_links, dc);
5ac3d3c9 114 break;
4562236b 115 case DCE_VERSION_10_0:
5ac3d3c9 116 res_pool = dce100_create_resource_pool(
4562236b 117 num_virtual_links, dc);
5ac3d3c9 118 break;
4562236b 119 case DCE_VERSION_11_0:
5ac3d3c9 120 res_pool = dce110_create_resource_pool(
4562236b 121 num_virtual_links, dc, asic_id);
5ac3d3c9 122 break;
4562236b 123 case DCE_VERSION_11_2:
5ac3d3c9 124 res_pool = dce112_create_resource_pool(
4562236b 125 num_virtual_links, dc);
5ac3d3c9 126 break;
2c8ad2d5
AD
127 case DCE_VERSION_12_0:
128 res_pool = dce120_create_resource_pool(
129 num_virtual_links, dc);
130 break;
ff5ef992
AD
131
132#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
133 case DCN_VERSION_1_0:
134 res_pool = dcn10_create_resource_pool(
503a7c6f 135 num_virtual_links, dc);
ff5ef992
AD
136 break;
137#endif
3639fa68
ZF
138
139
4562236b
HW
140 default:
141 break;
142 }
5ac3d3c9 143 if (res_pool != NULL) {
1515a47b 144 struct dc_firmware_info fw_info = { { 0 } };
5ac3d3c9
CL
145
146 if (dc->ctx->dc_bios->funcs->get_firmware_info(
147 dc->ctx->dc_bios, &fw_info) == BP_RESULT_OK) {
148 res_pool->ref_clock_inKhz = fw_info.pll_info.crystal_frequency;
149 } else
150 ASSERT_CRITICAL(false);
151 }
4562236b 152
5ac3d3c9 153 return res_pool;
4562236b
HW
154}
155
156void dc_destroy_resource_pool(struct core_dc *dc)
157{
158 if (dc) {
159 if (dc->res_pool)
160 dc->res_pool->funcs->destroy(&dc->res_pool);
161
162 if (dc->hwseq)
163 dm_free(dc->hwseq);
164 }
165}
166
167static void update_num_audio(
168 const struct resource_straps *straps,
169 unsigned int *num_audio,
170 struct audio_support *aud_support)
171{
b8e9eb72
CL
172 aud_support->dp_audio = true;
173 aud_support->hdmi_audio_native = false;
174 aud_support->hdmi_audio_on_dongle = false;
175
4562236b 176 if (straps->hdmi_disable == 0) {
4562236b
HW
177 if (straps->dc_pinstraps_audio & 0x2) {
178 aud_support->hdmi_audio_on_dongle = true;
b8e9eb72 179 aud_support->hdmi_audio_native = true;
4562236b
HW
180 }
181 }
182
183 switch (straps->audio_stream_number) {
184 case 0: /* multi streams supported */
185 break;
186 case 1: /* multi streams not supported */
187 *num_audio = 1;
188 break;
189 default:
190 DC_ERR("DC: unexpected audio fuse!\n");
17a96033 191 }
4562236b
HW
192}
193
194bool resource_construct(
195 unsigned int num_virtual_links,
196 struct core_dc *dc,
197 struct resource_pool *pool,
198 const struct resource_create_funcs *create_funcs)
199{
200 struct dc_context *ctx = dc->ctx;
201 const struct resource_caps *caps = pool->res_cap;
202 int i;
203 unsigned int num_audio = caps->num_audio;
204 struct resource_straps straps = {0};
205
206 if (create_funcs->read_dce_straps)
207 create_funcs->read_dce_straps(dc->ctx, &straps);
208
209 pool->audio_count = 0;
210 if (create_funcs->create_audio) {
211 /* find the total number of streams available via the
212 * AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT
213 * registers (one for each pin) starting from pin 1
214 * up to the max number of audio pins.
215 * We stop on the first pin where
216 * PORT_CONNECTIVITY == 1 (as instructed by HW team).
217 */
218 update_num_audio(&straps, &num_audio, &pool->audio_support);
219 for (i = 0; i < pool->pipe_count && i < num_audio; i++) {
220 struct audio *aud = create_funcs->create_audio(ctx, i);
221
222 if (aud == NULL) {
223 DC_ERR("DC: failed to create audio!\n");
224 return false;
225 }
226
227 if (!aud->funcs->endpoint_valid(aud)) {
228 aud->funcs->destroy(&aud);
229 break;
230 }
231
232 pool->audios[i] = aud;
233 pool->audio_count++;
234 }
235 }
236
237 pool->stream_enc_count = 0;
238 if (create_funcs->create_stream_encoder) {
239 for (i = 0; i < caps->num_stream_encoder; i++) {
240 pool->stream_enc[i] = create_funcs->create_stream_encoder(i, ctx);
241 if (pool->stream_enc[i] == NULL)
242 DC_ERR("DC: failed to create stream_encoder!\n");
243 pool->stream_enc_count++;
244 }
245 }
246
247 for (i = 0; i < num_virtual_links; i++) {
248 pool->stream_enc[pool->stream_enc_count] =
249 virtual_stream_encoder_create(
250 ctx, ctx->dc_bios);
251 if (pool->stream_enc[pool->stream_enc_count] == NULL) {
252 DC_ERR("DC: failed to create stream_encoder!\n");
253 return false;
254 }
255 pool->stream_enc_count++;
256 }
257
258 dc->hwseq = create_funcs->create_hwseq(ctx);
259
260 return true;
261}
262
263
264void resource_unreference_clock_source(
265 struct resource_context *res_ctx,
a2b8659d 266 const struct resource_pool *pool,
8c737fcc 267 struct clock_source **clock_source)
4562236b
HW
268{
269 int i;
a2b8659d
TC
270 for (i = 0; i < pool->clk_src_count; i++) {
271 if (pool->clock_sources[i] != *clock_source)
4562236b
HW
272 continue;
273
274 res_ctx->clock_source_ref_count[i]--;
275
276 if (res_ctx->clock_source_ref_count[i] == 0)
8c737fcc 277 (*clock_source)->funcs->cs_power_down(*clock_source);
4562236b
HW
278
279 break;
280 }
281
a2b8659d 282 if (pool->dp_clock_source == *clock_source) {
4562236b
HW
283 res_ctx->dp_clock_source_ref_count--;
284
285 if (res_ctx->dp_clock_source_ref_count == 0)
8c737fcc 286 (*clock_source)->funcs->cs_power_down(*clock_source);
4562236b 287 }
8c737fcc 288 *clock_source = NULL;
4562236b
HW
289}
290
291void resource_reference_clock_source(
292 struct resource_context *res_ctx,
a2b8659d 293 const struct resource_pool *pool,
4562236b
HW
294 struct clock_source *clock_source)
295{
296 int i;
a2b8659d
TC
297 for (i = 0; i < pool->clk_src_count; i++) {
298 if (pool->clock_sources[i] != clock_source)
4562236b
HW
299 continue;
300
301 res_ctx->clock_source_ref_count[i]++;
302 break;
303 }
304
a2b8659d 305 if (pool->dp_clock_source == clock_source)
4562236b
HW
306 res_ctx->dp_clock_source_ref_count++;
307}
308
309bool resource_are_streams_timing_synchronizable(
0971c40e
HW
310 struct dc_stream_state *stream1,
311 struct dc_stream_state *stream2)
4562236b 312{
4fa086b9 313 if (stream1->timing.h_total != stream2->timing.h_total)
4562236b
HW
314 return false;
315
4fa086b9 316 if (stream1->timing.v_total != stream2->timing.v_total)
4562236b
HW
317 return false;
318
4fa086b9
LSL
319 if (stream1->timing.h_addressable
320 != stream2->timing.h_addressable)
4562236b
HW
321 return false;
322
4fa086b9
LSL
323 if (stream1->timing.v_addressable
324 != stream2->timing.v_addressable)
4562236b
HW
325 return false;
326
4fa086b9
LSL
327 if (stream1->timing.pix_clk_khz
328 != stream2->timing.pix_clk_khz)
4562236b
HW
329 return false;
330
331 if (stream1->phy_pix_clk != stream2->phy_pix_clk
7e2fe319
CL
332 && (!dc_is_dp_signal(stream1->signal)
333 || !dc_is_dp_signal(stream2->signal)))
4562236b
HW
334 return false;
335
336 return true;
337}
338
339static bool is_sharable_clk_src(
340 const struct pipe_ctx *pipe_with_clk_src,
341 const struct pipe_ctx *pipe)
342{
343 if (pipe_with_clk_src->clock_source == NULL)
344 return false;
345
346 if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL)
347 return false;
348
349 if (dc_is_dp_signal(pipe_with_clk_src->stream->signal))
350 return false;
351
352 if (dc_is_hdmi_signal(pipe_with_clk_src->stream->signal)
353 && dc_is_dvi_signal(pipe->stream->signal))
354 return false;
355
356 if (dc_is_hdmi_signal(pipe->stream->signal)
357 && dc_is_dvi_signal(pipe_with_clk_src->stream->signal))
358 return false;
359
360 if (!resource_are_streams_timing_synchronizable(
361 pipe_with_clk_src->stream, pipe->stream))
362 return false;
363
364 return true;
365}
366
367struct clock_source *resource_find_used_clk_src_for_sharing(
368 struct resource_context *res_ctx,
369 struct pipe_ctx *pipe_ctx)
370{
371 int i;
372
373 for (i = 0; i < MAX_PIPES; i++) {
374 if (is_sharable_clk_src(&res_ctx->pipe_ctx[i], pipe_ctx))
375 return res_ctx->pipe_ctx[i].clock_source;
376 }
377
378 return NULL;
379}
380
381static enum pixel_format convert_pixel_format_to_dalsurface(
382 enum surface_pixel_format surface_pixel_format)
383{
384 enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
385
386 switch (surface_pixel_format) {
387 case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
388 dal_pixel_format = PIXEL_FORMAT_INDEX8;
389 break;
390 case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
391 dal_pixel_format = PIXEL_FORMAT_RGB565;
392 break;
393 case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
394 dal_pixel_format = PIXEL_FORMAT_RGB565;
395 break;
396 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
397 dal_pixel_format = PIXEL_FORMAT_ARGB8888;
398 break;
8693049a 399 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
4562236b
HW
400 dal_pixel_format = PIXEL_FORMAT_ARGB8888;
401 break;
402 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
403 dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
404 break;
405 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
406 dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
407 break;
408 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
409 dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS;
410 break;
411 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
412 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
413 dal_pixel_format = PIXEL_FORMAT_FP16;
414 break;
415 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
4562236b 416 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
87449a90 417 dal_pixel_format = PIXEL_FORMAT_420BPP8;
4562236b 418 break;
ffbcd19a
VP
419 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
420 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
87449a90 421 dal_pixel_format = PIXEL_FORMAT_420BPP10;
ffbcd19a 422 break;
4562236b
HW
423 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
424 default:
425 dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
426 break;
427 }
428 return dal_pixel_format;
429}
430
431static void rect_swap_helper(struct rect *rect)
432{
433 uint32_t temp = 0;
434
435 temp = rect->height;
436 rect->height = rect->width;
437 rect->width = temp;
438
439 temp = rect->x;
440 rect->x = rect->y;
441 rect->y = temp;
442}
443
b2d0a103 444static void calculate_viewport(struct pipe_ctx *pipe_ctx)
4562236b 445{
3be5262e 446 const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
0971c40e 447 const struct dc_stream_state *stream = pipe_ctx->stream;
6702a9ac 448 struct scaler_data *data = &pipe_ctx->plane_res.scl_data;
3be5262e 449 struct rect surf_src = plane_state->src_rect;
1fbd2cfc 450 struct rect clip = { 0 };
87449a90
AK
451 int vpc_div = (data->format == PIXEL_FORMAT_420BPP8
452 || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1;
1fbd2cfc 453 bool pri_split = pipe_ctx->bottom_pipe &&
3be5262e 454 pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state;
1fbd2cfc 455 bool sec_split = pipe_ctx->top_pipe &&
3be5262e 456 pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state;
4562236b 457
7f5c22d1
VP
458 if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE ||
459 stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) {
7b779c99
VP
460 pri_split = false;
461 sec_split = false;
462 }
86006a7f 463
3be5262e
HW
464 if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 ||
465 pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270)
86006a7f
DL
466 rect_swap_helper(&surf_src);
467
4562236b
HW
468 /* The actual clip is an intersection between stream
469 * source and surface clip
470 */
3be5262e
HW
471 clip.x = stream->src.x > plane_state->clip_rect.x ?
472 stream->src.x : plane_state->clip_rect.x;
4562236b 473
1fbd2cfc 474 clip.width = stream->src.x + stream->src.width <
3be5262e 475 plane_state->clip_rect.x + plane_state->clip_rect.width ?
1fbd2cfc 476 stream->src.x + stream->src.width - clip.x :
3be5262e 477 plane_state->clip_rect.x + plane_state->clip_rect.width - clip.x ;
4562236b 478
3be5262e
HW
479 clip.y = stream->src.y > plane_state->clip_rect.y ?
480 stream->src.y : plane_state->clip_rect.y;
4562236b 481
1fbd2cfc 482 clip.height = stream->src.y + stream->src.height <
3be5262e 483 plane_state->clip_rect.y + plane_state->clip_rect.height ?
1fbd2cfc 484 stream->src.y + stream->src.height - clip.y :
3be5262e 485 plane_state->clip_rect.y + plane_state->clip_rect.height - clip.y ;
4562236b 486
86006a7f 487 /* offset = surf_src.ofs + (clip.ofs - surface->dst_rect.ofs) * scl_ratio
4562236b
HW
488 * num_pixels = clip.num_pix * scl_ratio
489 */
3be5262e
HW
490 data->viewport.x = surf_src.x + (clip.x - plane_state->dst_rect.x) *
491 surf_src.width / plane_state->dst_rect.width;
b2d0a103 492 data->viewport.width = clip.width *
3be5262e 493 surf_src.width / plane_state->dst_rect.width;
4562236b 494
3be5262e
HW
495 data->viewport.y = surf_src.y + (clip.y - plane_state->dst_rect.y) *
496 surf_src.height / plane_state->dst_rect.height;
b2d0a103 497 data->viewport.height = clip.height *
3be5262e 498 surf_src.height / plane_state->dst_rect.height;
4562236b 499
b2d0a103
DL
500 /* Round down, compensate in init */
501 data->viewport_c.x = data->viewport.x / vpc_div;
502 data->viewport_c.y = data->viewport.y / vpc_div;
503 data->inits.h_c = (data->viewport.x % vpc_div) != 0 ?
504 dal_fixed31_32_half : dal_fixed31_32_zero;
505 data->inits.v_c = (data->viewport.y % vpc_div) != 0 ?
506 dal_fixed31_32_half : dal_fixed31_32_zero;
507 /* Round up, assume original video size always even dimensions */
508 data->viewport_c.width = (data->viewport.width + vpc_div - 1) / vpc_div;
509 data->viewport_c.height = (data->viewport.height + vpc_div - 1) / vpc_div;
510
511 /* Handle hsplit */
1fbd2cfc
DL
512 if (pri_split || sec_split) {
513 /* HMirror XOR Secondary_pipe XOR Rotation_180 */
3be5262e
HW
514 bool right_view = (sec_split != plane_state->horizontal_mirror) !=
515 (plane_state->rotation == ROTATION_ANGLE_180);
1fbd2cfc 516
3be5262e
HW
517 if (plane_state->rotation == ROTATION_ANGLE_90
518 || plane_state->rotation == ROTATION_ANGLE_270)
1fbd2cfc 519 /* Secondary_pipe XOR Rotation_270 */
3be5262e 520 right_view = (plane_state->rotation == ROTATION_ANGLE_270) != sec_split;
9e6c74ce
DL
521
522 if (right_view) {
523 data->viewport.width /= 2;
524 data->viewport_c.width /= 2;
525 data->viewport.x += data->viewport.width;
526 data->viewport_c.x += data->viewport_c.width;
527 /* Ceil offset pipe */
528 data->viewport.width += data->viewport.width % 2;
529 data->viewport_c.width += data->viewport_c.width % 2;
530 } else {
531 data->viewport.width /= 2;
532 data->viewport_c.width /= 2;
533 }
b2d0a103 534 }
1fbd2cfc 535
3be5262e
HW
536 if (plane_state->rotation == ROTATION_ANGLE_90 ||
537 plane_state->rotation == ROTATION_ANGLE_270) {
1fbd2cfc
DL
538 rect_swap_helper(&data->viewport_c);
539 rect_swap_helper(&data->viewport);
540 }
4562236b
HW
541}
542
b2d0a103 543static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip)
4562236b 544{
3be5262e 545 const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
0971c40e 546 const struct dc_stream_state *stream = pipe_ctx->stream;
3be5262e
HW
547 struct rect surf_src = plane_state->src_rect;
548 struct rect surf_clip = plane_state->clip_rect;
c802570e 549 int recout_full_x, recout_full_y;
4562236b 550
3be5262e
HW
551 if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 ||
552 pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270)
86006a7f
DL
553 rect_swap_helper(&surf_src);
554
6702a9ac 555 pipe_ctx->plane_res.scl_data.recout.x = stream->dst.x;
4fa086b9 556 if (stream->src.x < surf_clip.x)
6702a9ac 557 pipe_ctx->plane_res.scl_data.recout.x += (surf_clip.x
4fa086b9
LSL
558 - stream->src.x) * stream->dst.width
559 / stream->src.width;
4562236b 560
6702a9ac 561 pipe_ctx->plane_res.scl_data.recout.width = surf_clip.width *
4fa086b9 562 stream->dst.width / stream->src.width;
6702a9ac 563 if (pipe_ctx->plane_res.scl_data.recout.width + pipe_ctx->plane_res.scl_data.recout.x >
4fa086b9 564 stream->dst.x + stream->dst.width)
6702a9ac 565 pipe_ctx->plane_res.scl_data.recout.width =
4fa086b9 566 stream->dst.x + stream->dst.width
6702a9ac 567 - pipe_ctx->plane_res.scl_data.recout.x;
4562236b 568
6702a9ac 569 pipe_ctx->plane_res.scl_data.recout.y = stream->dst.y;
4fa086b9 570 if (stream->src.y < surf_clip.y)
6702a9ac 571 pipe_ctx->plane_res.scl_data.recout.y += (surf_clip.y
4fa086b9
LSL
572 - stream->src.y) * stream->dst.height
573 / stream->src.height;
4562236b 574
6702a9ac 575 pipe_ctx->plane_res.scl_data.recout.height = surf_clip.height *
4fa086b9 576 stream->dst.height / stream->src.height;
6702a9ac 577 if (pipe_ctx->plane_res.scl_data.recout.height + pipe_ctx->plane_res.scl_data.recout.y >
4fa086b9 578 stream->dst.y + stream->dst.height)
6702a9ac 579 pipe_ctx->plane_res.scl_data.recout.height =
4fa086b9 580 stream->dst.y + stream->dst.height
6702a9ac 581 - pipe_ctx->plane_res.scl_data.recout.y;
b2d0a103 582
7b779c99 583 /* Handle h & vsplit */
3be5262e
HW
584 if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->plane_state ==
585 pipe_ctx->plane_state) {
4fa086b9 586 if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) {
6702a9ac
HW
587 pipe_ctx->plane_res.scl_data.recout.height /= 2;
588 pipe_ctx->plane_res.scl_data.recout.y += pipe_ctx->plane_res.scl_data.recout.height;
7b779c99 589 /* Floor primary pipe, ceil 2ndary pipe */
6702a9ac 590 pipe_ctx->plane_res.scl_data.recout.height += pipe_ctx->plane_res.scl_data.recout.height % 2;
7b779c99 591 } else {
6702a9ac
HW
592 pipe_ctx->plane_res.scl_data.recout.width /= 2;
593 pipe_ctx->plane_res.scl_data.recout.x += pipe_ctx->plane_res.scl_data.recout.width;
594 pipe_ctx->plane_res.scl_data.recout.width += pipe_ctx->plane_res.scl_data.recout.width % 2;
7b779c99
VP
595 }
596 } else if (pipe_ctx->bottom_pipe &&
3be5262e 597 pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state) {
4fa086b9 598 if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM)
6702a9ac 599 pipe_ctx->plane_res.scl_data.recout.height /= 2;
7b779c99 600 else
6702a9ac 601 pipe_ctx->plane_res.scl_data.recout.width /= 2;
b2d0a103
DL
602 }
603
86006a7f
DL
604 /* Unclipped recout offset = stream dst offset + ((surf dst offset - stream surf_src offset)
605 * * 1/ stream scaling ratio) - (surf surf_src offset * 1/ full scl
c802570e
DL
606 * ratio)
607 */
3be5262e 608 recout_full_x = stream->dst.x + (plane_state->dst_rect.x - stream->src.x)
4fa086b9 609 * stream->dst.width / stream->src.width -
3be5262e 610 surf_src.x * plane_state->dst_rect.width / surf_src.width
4fa086b9 611 * stream->dst.width / stream->src.width;
3be5262e 612 recout_full_y = stream->dst.y + (plane_state->dst_rect.y - stream->src.y)
4fa086b9 613 * stream->dst.height / stream->src.height -
3be5262e 614 surf_src.y * plane_state->dst_rect.height / surf_src.height
4fa086b9 615 * stream->dst.height / stream->src.height;
c802570e 616
6702a9ac
HW
617 recout_skip->width = pipe_ctx->plane_res.scl_data.recout.x - recout_full_x;
618 recout_skip->height = pipe_ctx->plane_res.scl_data.recout.y - recout_full_y;
4562236b
HW
619}
620
b2d0a103 621static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx)
4562236b 622{
3be5262e 623 const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
0971c40e 624 const struct dc_stream_state *stream = pipe_ctx->stream;
3be5262e 625 struct rect surf_src = plane_state->src_rect;
4fa086b9
LSL
626 const int in_w = stream->src.width;
627 const int in_h = stream->src.height;
628 const int out_w = stream->dst.width;
629 const int out_h = stream->dst.height;
4562236b 630
3be5262e
HW
631 if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 ||
632 pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270)
86006a7f
DL
633 rect_swap_helper(&surf_src);
634
6702a9ac 635 pipe_ctx->plane_res.scl_data.ratios.horz = dal_fixed31_32_from_fraction(
86006a7f 636 surf_src.width,
3be5262e 637 plane_state->dst_rect.width);
6702a9ac 638 pipe_ctx->plane_res.scl_data.ratios.vert = dal_fixed31_32_from_fraction(
86006a7f 639 surf_src.height,
3be5262e 640 plane_state->dst_rect.height);
4562236b 641
4fa086b9 642 if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE)
6702a9ac 643 pipe_ctx->plane_res.scl_data.ratios.horz.value *= 2;
4fa086b9 644 else if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM)
6702a9ac 645 pipe_ctx->plane_res.scl_data.ratios.vert.value *= 2;
4562236b 646
6702a9ac
HW
647 pipe_ctx->plane_res.scl_data.ratios.vert.value = div64_s64(
648 pipe_ctx->plane_res.scl_data.ratios.vert.value * in_h, out_h);
649 pipe_ctx->plane_res.scl_data.ratios.horz.value = div64_s64(
650 pipe_ctx->plane_res.scl_data.ratios.horz.value * in_w, out_w);
4562236b 651
6702a9ac
HW
652 pipe_ctx->plane_res.scl_data.ratios.horz_c = pipe_ctx->plane_res.scl_data.ratios.horz;
653 pipe_ctx->plane_res.scl_data.ratios.vert_c = pipe_ctx->plane_res.scl_data.ratios.vert;
4562236b 654
6702a9ac
HW
655 if (pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP8
656 || pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP10) {
657 pipe_ctx->plane_res.scl_data.ratios.horz_c.value /= 2;
658 pipe_ctx->plane_res.scl_data.ratios.vert_c.value /= 2;
4562236b
HW
659 }
660}
661
b2d0a103
DL
662static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *recout_skip)
663{
6702a9ac 664 struct scaler_data *data = &pipe_ctx->plane_res.scl_data;
3be5262e 665 struct rect src = pipe_ctx->plane_state->src_rect;
87449a90
AK
666 int vpc_div = (data->format == PIXEL_FORMAT_420BPP8
667 || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1;
b2d0a103 668
86006a7f 669
3be5262e
HW
670 if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 ||
671 pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) {
86006a7f 672 rect_swap_helper(&src);
1fbd2cfc
DL
673 rect_swap_helper(&data->viewport_c);
674 rect_swap_helper(&data->viewport);
675 }
676
b2d0a103
DL
677 /*
678 * Init calculated according to formula:
679 * init = (scaling_ratio + number_of_taps + 1) / 2
680 * init_bot = init + scaling_ratio
681 * init_c = init + truncated_vp_c_offset(from calculate viewport)
682 */
683 data->inits.h = dal_fixed31_32_div_int(
684 dal_fixed31_32_add_int(data->ratios.horz, data->taps.h_taps + 1), 2);
685
686 data->inits.h_c = dal_fixed31_32_add(data->inits.h_c, dal_fixed31_32_div_int(
687 dal_fixed31_32_add_int(data->ratios.horz_c, data->taps.h_taps_c + 1), 2));
688
689 data->inits.v = dal_fixed31_32_div_int(
690 dal_fixed31_32_add_int(data->ratios.vert, data->taps.v_taps + 1), 2);
691
692 data->inits.v_c = dal_fixed31_32_add(data->inits.v_c, dal_fixed31_32_div_int(
693 dal_fixed31_32_add_int(data->ratios.vert_c, data->taps.v_taps_c + 1), 2));
694
695
696 /* Adjust for viewport end clip-off */
697 if ((data->viewport.x + data->viewport.width) < (src.x + src.width)) {
698 int vp_clip = src.x + src.width - data->viewport.width - data->viewport.x;
1fbd2cfc
DL
699 int int_part = dal_fixed31_32_floor(
700 dal_fixed31_32_sub(data->inits.h, data->ratios.horz));
b2d0a103 701
1fbd2cfc 702 int_part = int_part > 0 ? int_part : 0;
b2d0a103
DL
703 data->viewport.width += int_part < vp_clip ? int_part : vp_clip;
704 }
705 if ((data->viewport.y + data->viewport.height) < (src.y + src.height)) {
706 int vp_clip = src.y + src.height - data->viewport.height - data->viewport.y;
1fbd2cfc
DL
707 int int_part = dal_fixed31_32_floor(
708 dal_fixed31_32_sub(data->inits.v, data->ratios.vert));
b2d0a103 709
1fbd2cfc 710 int_part = int_part > 0 ? int_part : 0;
b2d0a103
DL
711 data->viewport.height += int_part < vp_clip ? int_part : vp_clip;
712 }
713 if ((data->viewport_c.x + data->viewport_c.width) < (src.x + src.width) / vpc_div) {
714 int vp_clip = (src.x + src.width) / vpc_div -
715 data->viewport_c.width - data->viewport_c.x;
1fbd2cfc
DL
716 int int_part = dal_fixed31_32_floor(
717 dal_fixed31_32_sub(data->inits.h_c, data->ratios.horz_c));
b2d0a103 718
1fbd2cfc 719 int_part = int_part > 0 ? int_part : 0;
b2d0a103
DL
720 data->viewport_c.width += int_part < vp_clip ? int_part : vp_clip;
721 }
722 if ((data->viewport_c.y + data->viewport_c.height) < (src.y + src.height) / vpc_div) {
723 int vp_clip = (src.y + src.height) / vpc_div -
724 data->viewport_c.height - data->viewport_c.y;
1fbd2cfc
DL
725 int int_part = dal_fixed31_32_floor(
726 dal_fixed31_32_sub(data->inits.v_c, data->ratios.vert_c));
b2d0a103 727
1fbd2cfc 728 int_part = int_part > 0 ? int_part : 0;
b2d0a103
DL
729 data->viewport_c.height += int_part < vp_clip ? int_part : vp_clip;
730 }
731
732 /* Adjust for non-0 viewport offset */
733 if (data->viewport.x) {
734 int int_part;
735
736 data->inits.h = dal_fixed31_32_add(data->inits.h, dal_fixed31_32_mul_int(
737 data->ratios.horz, recout_skip->width));
738 int_part = dal_fixed31_32_floor(data->inits.h) - data->viewport.x;
739 if (int_part < data->taps.h_taps) {
740 int int_adj = data->viewport.x >= (data->taps.h_taps - int_part) ?
741 (data->taps.h_taps - int_part) : data->viewport.x;
742 data->viewport.x -= int_adj;
743 data->viewport.width += int_adj;
744 int_part += int_adj;
745 } else if (int_part > data->taps.h_taps) {
746 data->viewport.x += int_part - data->taps.h_taps;
747 data->viewport.width -= int_part - data->taps.h_taps;
748 int_part = data->taps.h_taps;
749 }
750 data->inits.h.value &= 0xffffffff;
751 data->inits.h = dal_fixed31_32_add_int(data->inits.h, int_part);
752 }
753
754 if (data->viewport_c.x) {
755 int int_part;
756
757 data->inits.h_c = dal_fixed31_32_add(data->inits.h_c, dal_fixed31_32_mul_int(
758 data->ratios.horz_c, recout_skip->width));
759 int_part = dal_fixed31_32_floor(data->inits.h_c) - data->viewport_c.x;
760 if (int_part < data->taps.h_taps_c) {
761 int int_adj = data->viewport_c.x >= (data->taps.h_taps_c - int_part) ?
762 (data->taps.h_taps_c - int_part) : data->viewport_c.x;
763 data->viewport_c.x -= int_adj;
764 data->viewport_c.width += int_adj;
765 int_part += int_adj;
766 } else if (int_part > data->taps.h_taps_c) {
767 data->viewport_c.x += int_part - data->taps.h_taps_c;
768 data->viewport_c.width -= int_part - data->taps.h_taps_c;
769 int_part = data->taps.h_taps_c;
770 }
771 data->inits.h_c.value &= 0xffffffff;
772 data->inits.h_c = dal_fixed31_32_add_int(data->inits.h_c, int_part);
773 }
774
775 if (data->viewport.y) {
776 int int_part;
777
778 data->inits.v = dal_fixed31_32_add(data->inits.v, dal_fixed31_32_mul_int(
779 data->ratios.vert, recout_skip->height));
780 int_part = dal_fixed31_32_floor(data->inits.v) - data->viewport.y;
781 if (int_part < data->taps.v_taps) {
782 int int_adj = data->viewport.y >= (data->taps.v_taps - int_part) ?
783 (data->taps.v_taps - int_part) : data->viewport.y;
784 data->viewport.y -= int_adj;
785 data->viewport.height += int_adj;
786 int_part += int_adj;
787 } else if (int_part > data->taps.v_taps) {
788 data->viewport.y += int_part - data->taps.v_taps;
789 data->viewport.height -= int_part - data->taps.v_taps;
790 int_part = data->taps.v_taps;
791 }
792 data->inits.v.value &= 0xffffffff;
793 data->inits.v = dal_fixed31_32_add_int(data->inits.v, int_part);
794 }
795
796 if (data->viewport_c.y) {
797 int int_part;
798
799 data->inits.v_c = dal_fixed31_32_add(data->inits.v_c, dal_fixed31_32_mul_int(
800 data->ratios.vert_c, recout_skip->height));
801 int_part = dal_fixed31_32_floor(data->inits.v_c) - data->viewport_c.y;
802 if (int_part < data->taps.v_taps_c) {
803 int int_adj = data->viewport_c.y >= (data->taps.v_taps_c - int_part) ?
804 (data->taps.v_taps_c - int_part) : data->viewport_c.y;
805 data->viewport_c.y -= int_adj;
806 data->viewport_c.height += int_adj;
807 int_part += int_adj;
808 } else if (int_part > data->taps.v_taps_c) {
809 data->viewport_c.y += int_part - data->taps.v_taps_c;
810 data->viewport_c.height -= int_part - data->taps.v_taps_c;
811 int_part = data->taps.v_taps_c;
812 }
813 data->inits.v_c.value &= 0xffffffff;
814 data->inits.v_c = dal_fixed31_32_add_int(data->inits.v_c, int_part);
815 }
816
817 /* Interlaced inits based on final vert inits */
818 data->inits.v_bot = dal_fixed31_32_add(data->inits.v, data->ratios.vert);
819 data->inits.v_c_bot = dal_fixed31_32_add(data->inits.v_c, data->ratios.vert_c);
1fbd2cfc 820
3be5262e
HW
821 if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 ||
822 pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) {
1fbd2cfc
DL
823 rect_swap_helper(&data->viewport_c);
824 rect_swap_helper(&data->viewport);
825 }
b2d0a103
DL
826}
827
828bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
4562236b 829{
3be5262e 830 const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
4fa086b9 831 struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
b2d0a103
DL
832 struct view recout_skip = { 0 };
833 bool res = false;
834
4562236b
HW
835 /* Important: scaling ratio calculation requires pixel format,
836 * lb depth calculation requires recout and taps require scaling ratios.
b2d0a103 837 * Inits require viewport, taps, ratios and recout of split pipe
4562236b 838 */
6702a9ac 839 pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface(
3be5262e 840 pipe_ctx->plane_state->format);
b2d0a103
DL
841
842 calculate_scaling_ratios(pipe_ctx);
4562236b 843
b2d0a103 844 calculate_viewport(pipe_ctx);
4562236b 845
6702a9ac 846 if (pipe_ctx->plane_res.scl_data.viewport.height < 16 || pipe_ctx->plane_res.scl_data.viewport.width < 16)
4562236b
HW
847 return false;
848
b2d0a103 849 calculate_recout(pipe_ctx, &recout_skip);
4562236b
HW
850
851 /**
852 * Setting line buffer pixel depth to 24bpp yields banding
853 * on certain displays, such as the Sharp 4k
854 */
6702a9ac 855 pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP;
4562236b 856
6702a9ac
HW
857 pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable;
858 pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable;
4562236b
HW
859
860 /* Taps calculations */
86a66c4e
HW
861 res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps(
862 pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality);
4562236b
HW
863
864 if (!res) {
865 /* Try 24 bpp linebuffer */
6702a9ac 866 pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP;
4562236b 867
86a66c4e
HW
868 res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps(
869 pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality);
4562236b
HW
870 }
871
b2d0a103 872 if (res)
1fbd2cfc 873 /* May need to re-check lb size after this in some obscure scenario */
b2d0a103
DL
874 calculate_inits_and_adj_vp(pipe_ctx, &recout_skip);
875
4562236b
HW
876 dm_logger_write(pipe_ctx->stream->ctx->logger, LOG_SCALER,
877 "%s: Viewport:\nheight:%d width:%d x:%d "
878 "y:%d\n dst_rect:\nheight:%d width:%d x:%d "
879 "y:%d\n",
880 __func__,
6702a9ac
HW
881 pipe_ctx->plane_res.scl_data.viewport.height,
882 pipe_ctx->plane_res.scl_data.viewport.width,
883 pipe_ctx->plane_res.scl_data.viewport.x,
884 pipe_ctx->plane_res.scl_data.viewport.y,
3be5262e
HW
885 plane_state->dst_rect.height,
886 plane_state->dst_rect.width,
887 plane_state->dst_rect.x,
888 plane_state->dst_rect.y);
4562236b
HW
889
890 return res;
891}
892
893
894enum dc_status resource_build_scaling_params_for_context(
895 const struct core_dc *dc,
896 struct validate_context *context)
897{
898 int i;
899
900 for (i = 0; i < MAX_PIPES; i++) {
3be5262e 901 if (context->res_ctx.pipe_ctx[i].plane_state != NULL &&
4562236b 902 context->res_ctx.pipe_ctx[i].stream != NULL)
b2d0a103 903 if (!resource_build_scaling_params(&context->res_ctx.pipe_ctx[i]))
f84a8161 904 return DC_FAIL_SCALING;
4562236b
HW
905 }
906
907 return DC_OK;
908}
909
a2b8659d
TC
910struct pipe_ctx *find_idle_secondary_pipe(
911 struct resource_context *res_ctx,
912 const struct resource_pool *pool)
4562236b
HW
913{
914 int i;
915 struct pipe_ctx *secondary_pipe = NULL;
916
917 /*
918 * search backwards for the second pipe to keep pipe
919 * assignment more consistent
920 */
921
a2b8659d 922 for (i = pool->pipe_count - 1; i >= 0; i--) {
4562236b
HW
923 if (res_ctx->pipe_ctx[i].stream == NULL) {
924 secondary_pipe = &res_ctx->pipe_ctx[i];
925 secondary_pipe->pipe_idx = i;
926 break;
927 }
928 }
929
930
931 return secondary_pipe;
932}
933
934struct pipe_ctx *resource_get_head_pipe_for_stream(
935 struct resource_context *res_ctx,
0971c40e 936 struct dc_stream_state *stream)
4562236b
HW
937{
938 int i;
a2b8659d 939 for (i = 0; i < MAX_PIPES; i++) {
4562236b 940 if (res_ctx->pipe_ctx[i].stream == stream &&
8e9c4c8c 941 res_ctx->pipe_ctx[i].stream_res.stream_enc) {
4562236b
HW
942 return &res_ctx->pipe_ctx[i];
943 break;
944 }
945 }
946 return NULL;
947}
948
949/*
ab2541b6
AC
950 * A free_pipe for a stream is defined here as a pipe
951 * that has no surface attached yet
4562236b 952 */
ab2541b6 953static struct pipe_ctx *acquire_free_pipe_for_stream(
745cc746 954 struct validate_context *context,
a2b8659d 955 const struct resource_pool *pool,
0971c40e 956 struct dc_stream_state *stream)
4562236b
HW
957{
958 int i;
745cc746 959 struct resource_context *res_ctx = &context->res_ctx;
4562236b
HW
960
961 struct pipe_ctx *head_pipe = NULL;
962
963 /* Find head pipe, which has the back end set up*/
964
965 head_pipe = resource_get_head_pipe_for_stream(res_ctx, stream);
966
967 if (!head_pipe)
968 ASSERT(0);
969
3be5262e 970 if (!head_pipe->plane_state)
4562236b
HW
971 return head_pipe;
972
973 /* Re-use pipe already acquired for this stream if available*/
a2b8659d 974 for (i = pool->pipe_count - 1; i >= 0; i--) {
4562236b 975 if (res_ctx->pipe_ctx[i].stream == stream &&
3be5262e 976 !res_ctx->pipe_ctx[i].plane_state) {
4562236b
HW
977 return &res_ctx->pipe_ctx[i];
978 }
979 }
980
981 /*
982 * At this point we have no re-useable pipe for this stream and we need
983 * to acquire an idle one to satisfy the request
984 */
985
a2b8659d 986 if (!pool->funcs->acquire_idle_pipe_for_layer)
4562236b
HW
987 return NULL;
988
a2b8659d 989 return pool->funcs->acquire_idle_pipe_for_layer(context, pool, stream);
4562236b
HW
990
991}
992
ab2541b6 993static void release_free_pipes_for_stream(
4562236b 994 struct resource_context *res_ctx,
0971c40e 995 struct dc_stream_state *stream)
4562236b
HW
996{
997 int i;
4562236b 998
a2b8659d 999 for (i = MAX_PIPES - 1; i >= 0; i--) {
05a19c39 1000 /* never release the topmost pipe*/
4562236b 1001 if (res_ctx->pipe_ctx[i].stream == stream &&
05a19c39 1002 res_ctx->pipe_ctx[i].top_pipe &&
3be5262e 1003 !res_ctx->pipe_ctx[i].plane_state) {
05a19c39 1004 memset(&res_ctx->pipe_ctx[i], 0, sizeof(struct pipe_ctx));
4562236b
HW
1005 }
1006 }
1007}
1008
0f9a536f
DL
1009#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
1010static int acquire_first_split_pipe(
1011 struct resource_context *res_ctx,
1012 const struct resource_pool *pool,
0971c40e 1013 struct dc_stream_state *stream)
0f9a536f
DL
1014{
1015 int i;
1016
1017 for (i = 0; i < pool->pipe_count; i++) {
1018 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
1019
1020 if (pipe_ctx->top_pipe &&
3be5262e 1021 pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state) {
0f9a536f
DL
1022 pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe;
1023 if (pipe_ctx->bottom_pipe)
1024 pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe;
1025
1026 memset(pipe_ctx, 0, sizeof(*pipe_ctx));
6b670fa9 1027 pipe_ctx->stream_res.tg = pool->timing_generators[i];
86a66c4e
HW
1028 pipe_ctx->plane_res.mi = pool->mis[i];
1029 pipe_ctx->plane_res.ipp = pool->ipps[i];
1030 pipe_ctx->plane_res.xfm = pool->transforms[i];
a6a6cb34 1031 pipe_ctx->stream_res.opp = pool->opps[i];
0f9a536f
DL
1032 pipe_ctx->dis_clk = pool->display_clock;
1033 pipe_ctx->pipe_idx = i;
0f9a536f
DL
1034
1035 pipe_ctx->stream = stream;
1036 return i;
1037 }
1038 }
1039 return -1;
1040}
1041#endif
1042
4562236b 1043bool resource_attach_surfaces_to_context(
3be5262e 1044 struct dc_plane_state * const *plane_states,
4562236b 1045 int surface_count,
0971c40e 1046 struct dc_stream_state *stream,
a2b8659d
TC
1047 struct validate_context *context,
1048 const struct resource_pool *pool)
4562236b
HW
1049{
1050 int i;
1051 struct pipe_ctx *tail_pipe;
ab2541b6 1052 struct dc_stream_status *stream_status = NULL;
4562236b
HW
1053
1054
1055 if (surface_count > MAX_SURFACE_NUM) {
1056 dm_error("Surface: can not attach %d surfaces! Maximum is: %d\n",
1057 surface_count, MAX_SURFACE_NUM);
1058 return false;
1059 }
1060
ab2541b6 1061 for (i = 0; i < context->stream_count; i++)
4fa086b9 1062 if (context->streams[i] == stream) {
ab2541b6 1063 stream_status = &context->stream_status[i];
4562236b
HW
1064 break;
1065 }
ab2541b6
AC
1066 if (stream_status == NULL) {
1067 dm_error("Existing stream not found; failed to attach surfaces\n");
4562236b
HW
1068 return false;
1069 }
1070
1071 /* retain new surfaces */
1072 for (i = 0; i < surface_count; i++)
3be5262e 1073 dc_plane_state_retain(plane_states[i]);
4562236b 1074
05a19c39
DL
1075 /* detach surfaces from pipes */
1076 for (i = 0; i < pool->pipe_count; i++)
1077 if (context->res_ctx.pipe_ctx[i].stream == stream) {
3be5262e 1078 context->res_ctx.pipe_ctx[i].plane_state = NULL;
05a19c39
DL
1079 context->res_ctx.pipe_ctx[i].bottom_pipe = NULL;
1080 }
4562236b
HW
1081
1082 /* release existing surfaces*/
3be5262e
HW
1083 for (i = 0; i < stream_status->plane_count; i++)
1084 dc_plane_state_release(stream_status->plane_states[i]);
4562236b 1085
3be5262e
HW
1086 for (i = surface_count; i < stream_status->plane_count; i++)
1087 stream_status->plane_states[i] = NULL;
4562236b 1088
4562236b
HW
1089 tail_pipe = NULL;
1090 for (i = 0; i < surface_count; i++) {
3be5262e 1091 struct dc_plane_state *plane_state = plane_states[i];
a2b8659d 1092 struct pipe_ctx *free_pipe = acquire_free_pipe_for_stream(
4fa086b9 1093 context, pool, stream);
4562236b 1094
0f9a536f
DL
1095#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
1096 if (!free_pipe) {
1097 int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream);
1098 if (pipe_idx >= 0)
1099 free_pipe = &context->res_ctx.pipe_ctx[pipe_idx];
1100 }
1101#endif
4562236b 1102 if (!free_pipe) {
3be5262e 1103 stream_status->plane_states[i] = NULL;
4562236b
HW
1104 return false;
1105 }
1106
3be5262e 1107 free_pipe->plane_state = plane_state;
4562236b
HW
1108
1109 if (tail_pipe) {
6b670fa9 1110 free_pipe->stream_res.tg = tail_pipe->stream_res.tg;
a6a6cb34 1111 free_pipe->stream_res.opp = tail_pipe->stream_res.opp;
8e9c4c8c 1112 free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc;
afaacef4 1113 free_pipe->stream_res.audio = tail_pipe->stream_res.audio;
cfe4645e 1114 free_pipe->clock_source = tail_pipe->clock_source;
4562236b
HW
1115 free_pipe->top_pipe = tail_pipe;
1116 tail_pipe->bottom_pipe = free_pipe;
1117 }
1118
1119 tail_pipe = free_pipe;
1120 }
1121
4fa086b9 1122 release_free_pipes_for_stream(&context->res_ctx, stream);
4562236b
HW
1123
1124 /* assign new surfaces*/
1125 for (i = 0; i < surface_count; i++)
3be5262e 1126 stream_status->plane_states[i] = plane_states[i];
4562236b 1127
3be5262e 1128 stream_status->plane_count = surface_count;
4562236b
HW
1129
1130 return true;
1131}
1132
1133
0971c40e
HW
1134static bool is_timing_changed(struct dc_stream_state *cur_stream,
1135 struct dc_stream_state *new_stream)
4562236b
HW
1136{
1137 if (cur_stream == NULL)
1138 return true;
1139
1140 /* If sink pointer changed, it means this is a hotplug, we should do
1141 * full hw setting.
1142 */
1143 if (cur_stream->sink != new_stream->sink)
1144 return true;
1145
1146 /* If output color space is changed, need to reprogram info frames */
4fa086b9 1147 if (cur_stream->output_color_space != new_stream->output_color_space)
4562236b
HW
1148 return true;
1149
1150 return memcmp(
4fa086b9
LSL
1151 &cur_stream->timing,
1152 &new_stream->timing,
4562236b
HW
1153 sizeof(struct dc_crtc_timing)) != 0;
1154}
1155
1156static bool are_stream_backends_same(
0971c40e 1157 struct dc_stream_state *stream_a, struct dc_stream_state *stream_b)
4562236b
HW
1158{
1159 if (stream_a == stream_b)
1160 return true;
1161
1162 if (stream_a == NULL || stream_b == NULL)
1163 return false;
1164
1165 if (is_timing_changed(stream_a, stream_b))
1166 return false;
1167
1168 return true;
1169}
1170
d54d29db 1171bool dc_is_stream_unchanged(
0971c40e 1172 struct dc_stream_state *old_stream, struct dc_stream_state *stream)
4562236b 1173{
4562236b 1174
ab2541b6
AC
1175 if (!are_stream_backends_same(old_stream, stream))
1176 return false;
4562236b
HW
1177
1178 return true;
1179}
1180
1181bool resource_validate_attach_surfaces(
1182 const struct dc_validation_set set[],
1183 int set_count,
1184 const struct validate_context *old_context,
a2b8659d
TC
1185 struct validate_context *context,
1186 const struct resource_pool *pool)
4562236b
HW
1187{
1188 int i, j;
1189
1190 for (i = 0; i < set_count; i++) {
430ef426 1191 for (j = 0; old_context && j < old_context->stream_count; j++)
d54d29db 1192 if (dc_is_stream_unchanged(
ab2541b6
AC
1193 old_context->streams[j],
1194 context->streams[i])) {
4562236b 1195 if (!resource_attach_surfaces_to_context(
3be5262e
HW
1196 old_context->stream_status[j].plane_states,
1197 old_context->stream_status[j].plane_count,
4fa086b9 1198 context->streams[i],
a2b8659d 1199 context, pool))
4562236b 1200 return false;
ab2541b6 1201 context->stream_status[i] = old_context->stream_status[j];
4562236b 1202 }
3be5262e 1203 if (set[i].plane_count != 0)
4562236b 1204 if (!resource_attach_surfaces_to_context(
3be5262e
HW
1205 set[i].plane_states,
1206 set[i].plane_count,
4fa086b9 1207 context->streams[i],
a2b8659d 1208 context, pool))
4562236b
HW
1209 return false;
1210
1211 }
1212
1213 return true;
1214}
1215
1216/* Maximum TMDS single link pixel clock 165MHz */
1217#define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000
909e8c9e 1218#define TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST 297000
4562236b
HW
1219
1220static void set_stream_engine_in_use(
1221 struct resource_context *res_ctx,
a2b8659d 1222 const struct resource_pool *pool,
4562236b
HW
1223 struct stream_encoder *stream_enc)
1224{
1225 int i;
1226
a2b8659d
TC
1227 for (i = 0; i < pool->stream_enc_count; i++) {
1228 if (pool->stream_enc[i] == stream_enc)
4562236b
HW
1229 res_ctx->is_stream_enc_acquired[i] = true;
1230 }
1231}
1232
1233/* TODO: release audio object */
1234static void set_audio_in_use(
1235 struct resource_context *res_ctx,
a2b8659d 1236 const struct resource_pool *pool,
4562236b
HW
1237 struct audio *audio)
1238{
1239 int i;
a2b8659d
TC
1240 for (i = 0; i < pool->audio_count; i++) {
1241 if (pool->audios[i] == audio)
4562236b 1242 res_ctx->is_audio_acquired[i] = true;
4562236b
HW
1243 }
1244}
1245
1246static int acquire_first_free_pipe(
1247 struct resource_context *res_ctx,
a2b8659d 1248 const struct resource_pool *pool,
0971c40e 1249 struct dc_stream_state *stream)
4562236b
HW
1250{
1251 int i;
1252
a2b8659d 1253 for (i = 0; i < pool->pipe_count; i++) {
4562236b
HW
1254 if (!res_ctx->pipe_ctx[i].stream) {
1255 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
1256
6b670fa9 1257 pipe_ctx->stream_res.tg = pool->timing_generators[i];
86a66c4e
HW
1258 pipe_ctx->plane_res.mi = pool->mis[i];
1259 pipe_ctx->plane_res.ipp = pool->ipps[i];
1260 pipe_ctx->plane_res.xfm = pool->transforms[i];
a6a6cb34 1261 pipe_ctx->stream_res.opp = pool->opps[i];
a2b8659d 1262 pipe_ctx->dis_clk = pool->display_clock;
4562236b
HW
1263 pipe_ctx->pipe_idx = i;
1264
ff5ef992 1265
4562236b
HW
1266 pipe_ctx->stream = stream;
1267 return i;
1268 }
1269 }
1270 return -1;
1271}
1272
1273static struct stream_encoder *find_first_free_match_stream_enc_for_link(
1274 struct resource_context *res_ctx,
a2b8659d 1275 const struct resource_pool *pool,
0971c40e 1276 struct dc_stream_state *stream)
4562236b
HW
1277{
1278 int i;
1279 int j = -1;
d0778ebf 1280 struct dc_link *link = stream->sink->link;
4562236b 1281
a2b8659d 1282 for (i = 0; i < pool->stream_enc_count; i++) {
4562236b 1283 if (!res_ctx->is_stream_enc_acquired[i] &&
a2b8659d 1284 pool->stream_enc[i]) {
4562236b
HW
1285 /* Store first available for MST second display
1286 * in daisy chain use case */
1287 j = i;
a2b8659d 1288 if (pool->stream_enc[i]->id ==
4562236b 1289 link->link_enc->preferred_engine)
a2b8659d 1290 return pool->stream_enc[i];
4562236b
HW
1291 }
1292 }
1293
1294 /*
1295 * below can happen in cases when stream encoder is acquired:
1296 * 1) for second MST display in chain, so preferred engine already
1297 * acquired;
1298 * 2) for another link, which preferred engine already acquired by any
1299 * MST configuration.
1300 *
1301 * If signal is of DP type and preferred engine not found, return last available
1302 *
1303 * TODO - This is just a patch up and a generic solution is
1304 * required for non DP connectors.
1305 */
1306
1307 if (j >= 0 && dc_is_dp_signal(stream->signal))
a2b8659d 1308 return pool->stream_enc[j];
4562236b
HW
1309
1310 return NULL;
1311}
1312
a2b8659d
TC
1313static struct audio *find_first_free_audio(
1314 struct resource_context *res_ctx,
1315 const struct resource_pool *pool)
4562236b
HW
1316{
1317 int i;
a2b8659d 1318 for (i = 0; i < pool->audio_count; i++) {
4562236b 1319 if (res_ctx->is_audio_acquired[i] == false) {
a2b8659d 1320 return pool->audios[i];
4562236b
HW
1321 }
1322 }
1323
1324 return 0;
1325}
1326
0971c40e 1327static void update_stream_signal(struct dc_stream_state *stream)
4562236b 1328{
4fa086b9
LSL
1329 if (stream->output_signal == SIGNAL_TYPE_NONE) {
1330 struct dc_sink *dc_sink = stream->sink;
8b32076c
ST
1331
1332 if (dc_sink->sink_signal == SIGNAL_TYPE_NONE)
d0778ebf 1333 stream->signal = stream->sink->link->connector_signal;
4562236b 1334 else
8b32076c
ST
1335 stream->signal = dc_sink->sink_signal;
1336 } else {
4fa086b9 1337 stream->signal = stream->output_signal;
8b32076c
ST
1338 }
1339
56dcade3 1340 if (dc_is_dvi_signal(stream->signal)) {
4fa086b9
LSL
1341 if (stream->timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST &&
1342 stream->sink->sink_signal != SIGNAL_TYPE_DVI_SINGLE_LINK)
56dcade3
HW
1343 stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK;
1344 else
1345 stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
1346 }
4562236b
HW
1347}
1348
1349bool resource_is_stream_unchanged(
0971c40e 1350 struct validate_context *old_context, struct dc_stream_state *stream)
4562236b 1351{
ab2541b6 1352 int i;
4562236b 1353
ab2541b6 1354 for (i = 0; i < old_context->stream_count; i++) {
0971c40e 1355 struct dc_stream_state *old_stream = old_context->streams[i];
4562236b 1356
ab2541b6 1357 if (are_stream_backends_same(old_stream, stream))
4562236b 1358 return true;
4562236b
HW
1359 }
1360
1361 return false;
1362}
1363
1364static void copy_pipe_ctx(
1365 const struct pipe_ctx *from_pipe_ctx, struct pipe_ctx *to_pipe_ctx)
1366{
3be5262e 1367 struct dc_plane_state *plane_state = to_pipe_ctx->plane_state;
0971c40e 1368 struct dc_stream_state *stream = to_pipe_ctx->stream;
4562236b
HW
1369
1370 *to_pipe_ctx = *from_pipe_ctx;
1371 to_pipe_ctx->stream = stream;
3be5262e
HW
1372 if (plane_state != NULL)
1373 to_pipe_ctx->plane_state = plane_state;
4562236b
HW
1374}
1375
0971c40e
HW
1376static struct dc_stream_state *find_pll_sharable_stream(
1377 struct dc_stream_state *stream_needs_pll,
4562236b
HW
1378 struct validate_context *context)
1379{
ab2541b6 1380 int i;
4562236b 1381
ab2541b6 1382 for (i = 0; i < context->stream_count; i++) {
0971c40e 1383 struct dc_stream_state *stream_has_pll = context->streams[i];
4562236b 1384
ab2541b6
AC
1385 /* We are looking for non dp, non virtual stream */
1386 if (resource_are_streams_timing_synchronizable(
1387 stream_needs_pll, stream_has_pll)
1388 && !dc_is_dp_signal(stream_has_pll->signal)
d0778ebf 1389 && stream_has_pll->sink->link->connector_signal
ab2541b6
AC
1390 != SIGNAL_TYPE_VIRTUAL)
1391 return stream_has_pll;
4562236b 1392
4562236b
HW
1393 }
1394
1395 return NULL;
1396}
1397
1398static int get_norm_pix_clk(const struct dc_crtc_timing *timing)
1399{
1400 uint32_t pix_clk = timing->pix_clk_khz;
1401 uint32_t normalized_pix_clk = pix_clk;
1402
1403 if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
1404 pix_clk /= 2;
cc4d99b8
CL
1405 if (timing->pixel_encoding != PIXEL_ENCODING_YCBCR422) {
1406 switch (timing->display_color_depth) {
1407 case COLOR_DEPTH_888:
1408 normalized_pix_clk = pix_clk;
1409 break;
1410 case COLOR_DEPTH_101010:
1411 normalized_pix_clk = (pix_clk * 30) / 24;
1412 break;
1413 case COLOR_DEPTH_121212:
1414 normalized_pix_clk = (pix_clk * 36) / 24;
4562236b 1415 break;
cc4d99b8
CL
1416 case COLOR_DEPTH_161616:
1417 normalized_pix_clk = (pix_clk * 48) / 24;
4562236b 1418 break;
cc4d99b8
CL
1419 default:
1420 ASSERT(0);
4562236b 1421 break;
cc4d99b8 1422 }
4562236b 1423 }
4562236b
HW
1424 return normalized_pix_clk;
1425}
1426
0971c40e 1427static void calculate_phy_pix_clks(struct dc_stream_state *stream)
4562236b 1428{
9345d987
AG
1429 update_stream_signal(stream);
1430
1431 /* update actual pixel clock on all streams */
1432 if (dc_is_hdmi_signal(stream->signal))
1433 stream->phy_pix_clk = get_norm_pix_clk(
4fa086b9 1434 &stream->timing);
9345d987
AG
1435 else
1436 stream->phy_pix_clk =
4fa086b9 1437 stream->timing.pix_clk_khz;
4562236b
HW
1438}
1439
1440enum dc_status resource_map_pool_resources(
1441 const struct core_dc *dc,
430ef426
DL
1442 struct validate_context *context,
1443 struct validate_context *old_context)
4562236b 1444{
a2b8659d 1445 const struct resource_pool *pool = dc->res_pool;
ab2541b6 1446 int i, j;
4562236b 1447
430ef426 1448 for (i = 0; old_context && i < context->stream_count; i++) {
0971c40e 1449 struct dc_stream_state *stream = context->streams[i];
4562236b 1450
430ef426
DL
1451 if (!resource_is_stream_unchanged(old_context, stream)) {
1452 if (stream != NULL && old_context->streams[i] != NULL) {
4b679bc3 1453 stream->bit_depth_params =
430ef426
DL
1454 old_context->streams[i]->bit_depth_params;
1455 stream->clamping = old_context->streams[i]->clamping;
a2b8659d
TC
1456 continue;
1457 }
4b679bc3 1458 }
7e2fe319 1459
ab2541b6 1460 /* mark resources used for stream that is already active */
a2b8659d 1461 for (j = 0; j < pool->pipe_count; j++) {
ab2541b6
AC
1462 struct pipe_ctx *pipe_ctx =
1463 &context->res_ctx.pipe_ctx[j];
1464 const struct pipe_ctx *old_pipe_ctx =
430ef426 1465 &old_context->res_ctx.pipe_ctx[j];
4562236b 1466
ab2541b6
AC
1467 if (!are_stream_backends_same(old_pipe_ctx->stream, stream))
1468 continue;
8c737fcc 1469
268cadbd
YS
1470 if (old_pipe_ctx->top_pipe)
1471 continue;
1472
ab2541b6
AC
1473 pipe_ctx->stream = stream;
1474 copy_pipe_ctx(old_pipe_ctx, pipe_ctx);
4562236b 1475
ab2541b6 1476 /* Split pipe resource, do not acquire back end */
8e9c4c8c 1477 if (!pipe_ctx->stream_res.stream_enc)
ab2541b6 1478 continue;
4562236b 1479
ab2541b6 1480 set_stream_engine_in_use(
a2b8659d 1481 &context->res_ctx, pool,
8e9c4c8c 1482 pipe_ctx->stream_res.stream_enc);
ab2541b6
AC
1483
1484 /* Switch to dp clock source only if there is
1485 * no non dp stream that shares the same timing
1486 * with the dp stream.
1487 */
1488 if (dc_is_dp_signal(pipe_ctx->stream->signal) &&
1489 !find_pll_sharable_stream(stream, context))
a2b8659d 1490 pipe_ctx->clock_source = pool->dp_clock_source;
ab2541b6
AC
1491
1492 resource_reference_clock_source(
a2b8659d 1493 &context->res_ctx, pool,
ab2541b6
AC
1494 pipe_ctx->clock_source);
1495
a2b8659d 1496 set_audio_in_use(&context->res_ctx, pool,
afaacef4 1497 pipe_ctx->stream_res.audio);
4562236b
HW
1498 }
1499 }
1500
ab2541b6 1501 for (i = 0; i < context->stream_count; i++) {
0971c40e 1502 struct dc_stream_state *stream = context->streams[i];
ab2541b6
AC
1503 struct pipe_ctx *pipe_ctx = NULL;
1504 int pipe_idx = -1;
4562236b 1505
430ef426 1506 if (old_context && resource_is_stream_unchanged(old_context, stream))
ab2541b6
AC
1507 continue;
1508 /* acquire new resources */
5d11e9fc
DL
1509 pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream);
1510#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
1511 if (pipe_idx < 0)
1512 acquire_first_split_pipe(&context->res_ctx, pool, stream);
1513#endif
ab2541b6
AC
1514 if (pipe_idx < 0)
1515 return DC_NO_CONTROLLER_RESOURCE;
1516
ab2541b6
AC
1517 pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx];
1518
8e9c4c8c 1519 pipe_ctx->stream_res.stream_enc =
ab2541b6 1520 find_first_free_match_stream_enc_for_link(
a2b8659d 1521 &context->res_ctx, pool, stream);
ab2541b6 1522
8e9c4c8c 1523 if (!pipe_ctx->stream_res.stream_enc)
ab2541b6
AC
1524 return DC_NO_STREAM_ENG_RESOURCE;
1525
1526 set_stream_engine_in_use(
a2b8659d 1527 &context->res_ctx, pool,
8e9c4c8c 1528 pipe_ctx->stream_res.stream_enc);
ab2541b6
AC
1529
1530 /* TODO: Add check if ASIC support and EDID audio */
b73a22d3 1531 if (!stream->sink->converter_disable_audio &&
ab2541b6 1532 dc_is_audio_capable_signal(pipe_ctx->stream->signal) &&
4fa086b9 1533 stream->audio_info.mode_count) {
afaacef4 1534 pipe_ctx->stream_res.audio = find_first_free_audio(
a2b8659d 1535 &context->res_ctx, pool);
ab2541b6
AC
1536
1537 /*
1538 * Audio assigned in order first come first get.
1539 * There are asics which has number of audio
1540 * resources less then number of pipes
1541 */
afaacef4 1542 if (pipe_ctx->stream_res.audio)
ab2541b6 1543 set_audio_in_use(
a2b8659d 1544 &context->res_ctx, pool,
afaacef4 1545 pipe_ctx->stream_res.audio);
4562236b 1546 }
ab2541b6 1547
6b670fa9 1548 context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst;
4562236b
HW
1549 }
1550
1551 return DC_OK;
1552}
1553
ab2541b6
AC
1554/* first stream in the context is used to populate the rest */
1555void validate_guaranteed_copy_streams(
4562236b 1556 struct validate_context *context,
ab2541b6 1557 int max_streams)
4562236b
HW
1558{
1559 int i;
1560
ab2541b6
AC
1561 for (i = 1; i < max_streams; i++) {
1562 context->streams[i] = context->streams[0];
4562236b
HW
1563
1564 copy_pipe_ctx(&context->res_ctx.pipe_ctx[0],
1565 &context->res_ctx.pipe_ctx[i]);
1566 context->res_ctx.pipe_ctx[i].stream =
1567 context->res_ctx.pipe_ctx[0].stream;
1568
4fa086b9 1569 dc_stream_retain(context->streams[i]);
ab2541b6 1570 context->stream_count++;
4562236b
HW
1571 }
1572}
1573
6e4d6bee
TC
1574static void patch_gamut_packet_checksum(
1575 struct encoder_info_packet *gamut_packet)
4562236b 1576{
4562236b 1577 /* For gamut we recalc checksum */
6e4d6bee 1578 if (gamut_packet->valid) {
4562236b
HW
1579 uint8_t chk_sum = 0;
1580 uint8_t *ptr;
1581 uint8_t i;
1582
4562236b 1583 /*start of the Gamut data. */
6e4d6bee 1584 ptr = &gamut_packet->sb[3];
4562236b 1585
6e4d6bee 1586 for (i = 0; i <= gamut_packet->sb[1]; i++)
4562236b
HW
1587 chk_sum += ptr[i];
1588
6e4d6bee 1589 gamut_packet->sb[2] = (uint8_t) (0x100 - chk_sum);
1646a6fe 1590 }
4562236b
HW
1591}
1592
1593static void set_avi_info_frame(
6e4d6bee 1594 struct encoder_info_packet *info_packet,
4562236b
HW
1595 struct pipe_ctx *pipe_ctx)
1596{
0971c40e 1597 struct dc_stream_state *stream = pipe_ctx->stream;
4562236b
HW
1598 enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
1599 struct info_frame info_frame = { {0} };
1600 uint32_t pixel_encoding = 0;
1601 enum scanning_type scan_type = SCANNING_TYPE_NODATA;
1602 enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA;
1603 bool itc = false;
50e27654 1604 uint8_t itc_value = 0;
4562236b 1605 uint8_t cn0_cn1 = 0;
50e27654 1606 unsigned int cn0_cn1_value = 0;
4562236b
HW
1607 uint8_t *check_sum = NULL;
1608 uint8_t byte_index = 0;
e8d726b7 1609 union hdmi_info_packet *hdmi_info = &info_frame.avi_info_packet.info_packet_hdmi;
50e27654 1610 union display_content_support support = {0};
4fa086b9 1611 unsigned int vic = pipe_ctx->stream->timing.vic;
15e17335 1612 enum dc_timing_3d_format format;
4562236b 1613
4fa086b9 1614 color_space = pipe_ctx->stream->output_color_space;
e5f2038e 1615 if (color_space == COLOR_SPACE_UNKNOWN)
4fa086b9 1616 color_space = (stream->timing.pixel_encoding == PIXEL_ENCODING_RGB) ?
e5f2038e 1617 COLOR_SPACE_SRGB:COLOR_SPACE_YCBCR709;
4562236b
HW
1618
1619 /* Initialize header */
e8d726b7 1620 hdmi_info->bits.header.info_frame_type = HDMI_INFOFRAME_TYPE_AVI;
4562236b
HW
1621 /* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall
1622 * not be used in HDMI 2.0 (Section 10.1) */
e8d726b7
RA
1623 hdmi_info->bits.header.version = 2;
1624 hdmi_info->bits.header.length = HDMI_AVI_INFOFRAME_SIZE;
4562236b
HW
1625
1626 /*
1627 * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built
1628 * according to HDMI 2.0 spec (Section 10.1)
1629 */
1630
4fa086b9 1631 switch (stream->timing.pixel_encoding) {
4562236b
HW
1632 case PIXEL_ENCODING_YCBCR422:
1633 pixel_encoding = 1;
1634 break;
1635
1636 case PIXEL_ENCODING_YCBCR444:
1637 pixel_encoding = 2;
1638 break;
1639 case PIXEL_ENCODING_YCBCR420:
1640 pixel_encoding = 3;
1641 break;
1642
1643 case PIXEL_ENCODING_RGB:
1644 default:
1645 pixel_encoding = 0;
1646 }
1647
1648 /* Y0_Y1_Y2 : The pixel encoding */
1649 /* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */
e8d726b7 1650 hdmi_info->bits.Y0_Y1_Y2 = pixel_encoding;
4562236b
HW
1651
1652 /* A0 = 1 Active Format Information valid */
e8d726b7 1653 hdmi_info->bits.A0 = ACTIVE_FORMAT_VALID;
4562236b
HW
1654
1655 /* B0, B1 = 3; Bar info data is valid */
e8d726b7 1656 hdmi_info->bits.B0_B1 = BAR_INFO_BOTH_VALID;
4562236b 1657
e8d726b7 1658 hdmi_info->bits.SC0_SC1 = PICTURE_SCALING_UNIFORM;
4562236b
HW
1659
1660 /* S0, S1 : Underscan / Overscan */
1661 /* TODO: un-hardcode scan type */
1662 scan_type = SCANNING_TYPE_UNDERSCAN;
e8d726b7 1663 hdmi_info->bits.S0_S1 = scan_type;
4562236b
HW
1664
1665 /* C0, C1 : Colorimetry */
8fde5884 1666 if (color_space == COLOR_SPACE_YCBCR709 ||
15e17335 1667 color_space == COLOR_SPACE_YCBCR709_LIMITED)
e8d726b7 1668 hdmi_info->bits.C0_C1 = COLORIMETRY_ITU709;
8fde5884
CL
1669 else if (color_space == COLOR_SPACE_YCBCR601 ||
1670 color_space == COLOR_SPACE_YCBCR601_LIMITED)
e8d726b7 1671 hdmi_info->bits.C0_C1 = COLORIMETRY_ITU601;
8fde5884 1672 else {
e8d726b7 1673 hdmi_info->bits.C0_C1 = COLORIMETRY_NO_DATA;
8fde5884 1674 }
534db198 1675 if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE ||
8fde5884
CL
1676 color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE ||
1677 color_space == COLOR_SPACE_2020_YCBCR) {
e8d726b7
RA
1678 hdmi_info->bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR;
1679 hdmi_info->bits.C0_C1 = COLORIMETRY_EXTENDED;
534db198 1680 } else if (color_space == COLOR_SPACE_ADOBERGB) {
e8d726b7
RA
1681 hdmi_info->bits.EC0_EC2 = COLORIMETRYEX_ADOBERGB;
1682 hdmi_info->bits.C0_C1 = COLORIMETRY_EXTENDED;
534db198
AZ
1683 }
1684
4562236b 1685 /* TODO: un-hardcode aspect ratio */
4fa086b9 1686 aspect = stream->timing.aspect_ratio;
4562236b
HW
1687
1688 switch (aspect) {
1689 case ASPECT_RATIO_4_3:
1690 case ASPECT_RATIO_16_9:
e8d726b7 1691 hdmi_info->bits.M0_M1 = aspect;
4562236b
HW
1692 break;
1693
1694 case ASPECT_RATIO_NO_DATA:
1695 case ASPECT_RATIO_64_27:
1696 case ASPECT_RATIO_256_135:
1697 default:
e8d726b7 1698 hdmi_info->bits.M0_M1 = 0;
4562236b
HW
1699 }
1700
1701 /* Active Format Aspect ratio - same as Picture Aspect Ratio. */
e8d726b7 1702 hdmi_info->bits.R0_R3 = ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE;
4562236b
HW
1703
1704 /* TODO: un-hardcode cn0_cn1 and itc */
50e27654 1705
4562236b 1706 cn0_cn1 = 0;
50e27654
ZF
1707 cn0_cn1_value = 0;
1708
1709 itc = true;
1710 itc_value = 1;
1711
4fa086b9 1712 support = stream->sink->edid_caps.content_support;
4562236b
HW
1713
1714 if (itc) {
50e27654
ZF
1715 if (!support.bits.valid_content_type) {
1716 cn0_cn1_value = 0;
1717 } else {
1718 if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GRAPHICS) {
1719 if (support.bits.graphics_content == 1) {
1720 cn0_cn1_value = 0;
1721 }
1722 } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_PHOTO) {
1723 if (support.bits.photo_content == 1) {
1724 cn0_cn1_value = 1;
1725 } else {
1726 cn0_cn1_value = 0;
1727 itc_value = 0;
1728 }
1729 } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_CINEMA) {
1730 if (support.bits.cinema_content == 1) {
1731 cn0_cn1_value = 2;
1732 } else {
1733 cn0_cn1_value = 0;
1734 itc_value = 0;
1735 }
1736 } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GAME) {
1737 if (support.bits.game_content == 1) {
1738 cn0_cn1_value = 3;
1739 } else {
1740 cn0_cn1_value = 0;
1741 itc_value = 0;
1742 }
1743 }
1744 }
1745 hdmi_info->bits.CN0_CN1 = cn0_cn1_value;
1746 hdmi_info->bits.ITC = itc_value;
4562236b
HW
1747 }
1748
1749 /* TODO : We should handle YCC quantization */
1750 /* but we do not have matrix calculation */
4fa086b9
LSL
1751 if (stream->sink->edid_caps.qs_bit == 1 &&
1752 stream->sink->edid_caps.qy_bit == 1) {
50e27654
ZF
1753 if (color_space == COLOR_SPACE_SRGB ||
1754 color_space == COLOR_SPACE_2020_RGB_FULLRANGE) {
1755 hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_FULL_RANGE;
1756 hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_FULL_RANGE;
1757 } else if (color_space == COLOR_SPACE_SRGB_LIMITED ||
1758 color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) {
1759 hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_LIMITED_RANGE;
1760 hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE;
1761 } else {
1762 hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE;
1763 hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE;
1764 }
4562236b 1765 } else {
e8d726b7 1766 hdmi_info->bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE;
50e27654 1767 hdmi_info->bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE;
4562236b 1768 }
50e27654 1769
15e17335 1770 ///VIC
4fa086b9 1771 format = stream->timing.timing_3d_format;
15e17335
CL
1772 /*todo, add 3DStereo support*/
1773 if (format != TIMING_3D_FORMAT_NONE) {
1774 // Based on HDMI specs hdmi vic needs to be converted to cea vic when 3D is enabled
4fa086b9 1775 switch (pipe_ctx->stream->timing.hdmi_vic) {
15e17335
CL
1776 case 1:
1777 vic = 95;
1778 break;
1779 case 2:
1780 vic = 94;
1781 break;
1782 case 3:
1783 vic = 93;
1784 break;
1785 case 4:
1786 vic = 98;
1787 break;
1788 default:
1789 break;
1790 }
1791 }
1792 hdmi_info->bits.VIC0_VIC7 = vic;
4562236b
HW
1793
1794 /* pixel repetition
1795 * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel
1796 * repetition start from 1 */
e8d726b7 1797 hdmi_info->bits.PR0_PR3 = 0;
4562236b
HW
1798
1799 /* Bar Info
1800 * barTop: Line Number of End of Top Bar.
1801 * barBottom: Line Number of Start of Bottom Bar.
1802 * barLeft: Pixel Number of End of Left Bar.
1803 * barRight: Pixel Number of Start of Right Bar. */
4fa086b9
LSL
1804 hdmi_info->bits.bar_top = stream->timing.v_border_top;
1805 hdmi_info->bits.bar_bottom = (stream->timing.v_total
1806 - stream->timing.v_border_bottom + 1);
1807 hdmi_info->bits.bar_left = stream->timing.h_border_left;
1808 hdmi_info->bits.bar_right = (stream->timing.h_total
1809 - stream->timing.h_border_right + 1);
4562236b
HW
1810
1811 /* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */
e8d726b7
RA
1812 check_sum = &info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.sb[0];
1813
3e183c5f 1814 *check_sum = HDMI_INFOFRAME_TYPE_AVI + HDMI_AVI_INFOFRAME_SIZE + 2;
4562236b 1815
3e183c5f 1816 for (byte_index = 1; byte_index <= HDMI_AVI_INFOFRAME_SIZE; byte_index++)
e8d726b7 1817 *check_sum += hdmi_info->packet_raw_data.sb[byte_index];
4562236b
HW
1818
1819 /* one byte complement */
1820 *check_sum = (uint8_t) (0x100 - *check_sum);
1821
1822 /* Store in hw_path_mode */
e8d726b7
RA
1823 info_packet->hb0 = hdmi_info->packet_raw_data.hb0;
1824 info_packet->hb1 = hdmi_info->packet_raw_data.hb1;
1825 info_packet->hb2 = hdmi_info->packet_raw_data.hb2;
4562236b 1826
e66e4d64
HW
1827 for (byte_index = 0; byte_index < sizeof(info_frame.avi_info_packet.
1828 info_packet_hdmi.packet_raw_data.sb); byte_index++)
4562236b 1829 info_packet->sb[byte_index] = info_frame.avi_info_packet.
e66e4d64 1830 info_packet_hdmi.packet_raw_data.sb[byte_index];
4562236b
HW
1831
1832 info_packet->valid = true;
1833}
1834
6e4d6bee
TC
1835static void set_vendor_info_packet(
1836 struct encoder_info_packet *info_packet,
0971c40e 1837 struct dc_stream_state *stream)
4562236b
HW
1838{
1839 uint32_t length = 0;
1840 bool hdmi_vic_mode = false;
1841 uint8_t checksum = 0;
1842 uint32_t i = 0;
1843 enum dc_timing_3d_format format;
15e17335
CL
1844 // Can be different depending on packet content /*todo*/
1845 // unsigned int length = pPathMode->dolbyVision ? 24 : 5;
1846
1847 info_packet->valid = false;
4562236b 1848
4fa086b9
LSL
1849 format = stream->timing.timing_3d_format;
1850 if (stream->view_format == VIEW_3D_FORMAT_NONE)
7f5c22d1 1851 format = TIMING_3D_FORMAT_NONE;
4562236b
HW
1852
1853 /* Can be different depending on packet content */
1854 length = 5;
1855
4fa086b9
LSL
1856 if (stream->timing.hdmi_vic != 0
1857 && stream->timing.h_total >= 3840
1858 && stream->timing.v_total >= 2160)
4562236b
HW
1859 hdmi_vic_mode = true;
1860
1861 /* According to HDMI 1.4a CTS, VSIF should be sent
1862 * for both 3D stereo and HDMI VIC modes.
1863 * For all other modes, there is no VSIF sent. */
1864
1865 if (format == TIMING_3D_FORMAT_NONE && !hdmi_vic_mode)
1866 return;
1867
1868 /* 24bit IEEE Registration identifier (0x000c03). LSB first. */
1869 info_packet->sb[1] = 0x03;
1870 info_packet->sb[2] = 0x0C;
1871 info_packet->sb[3] = 0x00;
1872
1873 /*PB4: 5 lower bytes = 0 (reserved). 3 higher bits = HDMI_Video_Format.
1874 * The value for HDMI_Video_Format are:
1875 * 0x0 (0b000) - No additional HDMI video format is presented in this
1876 * packet
1877 * 0x1 (0b001) - Extended resolution format present. 1 byte of HDMI_VIC
1878 * parameter follows
1879 * 0x2 (0b010) - 3D format indication present. 3D_Structure and
1880 * potentially 3D_Ext_Data follows
1881 * 0x3..0x7 (0b011..0b111) - reserved for future use */
1882 if (format != TIMING_3D_FORMAT_NONE)
1883 info_packet->sb[4] = (2 << 5);
1884 else if (hdmi_vic_mode)
1885 info_packet->sb[4] = (1 << 5);
1886
1887 /* PB5: If PB4 claims 3D timing (HDMI_Video_Format = 0x2):
1888 * 4 lower bites = 0 (reserved). 4 higher bits = 3D_Structure.
1889 * The value for 3D_Structure are:
1890 * 0x0 - Frame Packing
1891 * 0x1 - Field Alternative
1892 * 0x2 - Line Alternative
1893 * 0x3 - Side-by-Side (full)
1894 * 0x4 - L + depth
1895 * 0x5 - L + depth + graphics + graphics-depth
1896 * 0x6 - Top-and-Bottom
1897 * 0x7 - Reserved for future use
1898 * 0x8 - Side-by-Side (Half)
1899 * 0x9..0xE - Reserved for future use
1900 * 0xF - Not used */
1901 switch (format) {
1902 case TIMING_3D_FORMAT_HW_FRAME_PACKING:
1903 case TIMING_3D_FORMAT_SW_FRAME_PACKING:
1904 info_packet->sb[5] = (0x0 << 4);
1905 break;
1906
1907 case TIMING_3D_FORMAT_SIDE_BY_SIDE:
1908 case TIMING_3D_FORMAT_SBS_SW_PACKED:
1909 info_packet->sb[5] = (0x8 << 4);
1910 length = 6;
1911 break;
1912
1913 case TIMING_3D_FORMAT_TOP_AND_BOTTOM:
1914 case TIMING_3D_FORMAT_TB_SW_PACKED:
1915 info_packet->sb[5] = (0x6 << 4);
1916 break;
1917
1918 default:
1919 break;
1920 }
1921
1922 /*PB5: If PB4 is set to 0x1 (extended resolution format)
1923 * fill PB5 with the correct HDMI VIC code */
1924 if (hdmi_vic_mode)
4fa086b9 1925 info_packet->sb[5] = stream->timing.hdmi_vic;
4562236b
HW
1926
1927 /* Header */
3e183c5f 1928 info_packet->hb0 = HDMI_INFOFRAME_TYPE_VENDOR; /* VSIF packet type. */
4562236b
HW
1929 info_packet->hb1 = 0x01; /* Version */
1930
1931 /* 4 lower bits = Length, 4 higher bits = 0 (reserved) */
1932 info_packet->hb2 = (uint8_t) (length);
1933
1934 /* Calculate checksum */
1935 checksum = 0;
1936 checksum += info_packet->hb0;
1937 checksum += info_packet->hb1;
1938 checksum += info_packet->hb2;
1939
1940 for (i = 1; i <= length; i++)
1941 checksum += info_packet->sb[i];
1942
1943 info_packet->sb[0] = (uint8_t) (0x100 - checksum);
1944
1945 info_packet->valid = true;
1946}
1947
6e4d6bee
TC
1948static void set_spd_info_packet(
1949 struct encoder_info_packet *info_packet,
0971c40e 1950 struct dc_stream_state *stream)
4562236b
HW
1951{
1952 /* SPD info packet for FreeSync */
1953
1954 unsigned char checksum = 0;
1955 unsigned int idx, payload_size = 0;
1956
1957 /* Check if Freesync is supported. Return if false. If true,
1958 * set the corresponding bit in the info packet
1959 */
4fa086b9 1960 if (stream->freesync_ctx.supported == false)
4562236b
HW
1961 return;
1962
1963 if (dc_is_hdmi_signal(stream->signal)) {
1964
1965 /* HEADER */
1966
1967 /* HB0 = Packet Type = 0x83 (Source Product
1968 * Descriptor InfoFrame)
1969 */
3e183c5f 1970 info_packet->hb0 = HDMI_INFOFRAME_TYPE_SPD;
4562236b
HW
1971
1972 /* HB1 = Version = 0x01 */
1973 info_packet->hb1 = 0x01;
1974
1975 /* HB2 = [Bits 7:5 = 0] [Bits 4:0 = Length = 0x08] */
1976 info_packet->hb2 = 0x08;
1977
1978 payload_size = 0x08;
1979
1980 } else if (dc_is_dp_signal(stream->signal)) {
1981
1982 /* HEADER */
1983
1984 /* HB0 = Secondary-data Packet ID = 0 - Only non-zero
1985 * when used to associate audio related info packets
1986 */
1987 info_packet->hb0 = 0x00;
1988
1989 /* HB1 = Packet Type = 0x83 (Source Product
1990 * Descriptor InfoFrame)
1991 */
3e183c5f 1992 info_packet->hb1 = HDMI_INFOFRAME_TYPE_SPD;
4562236b
HW
1993
1994 /* HB2 = [Bits 7:0 = Least significant eight bits -
1995 * For INFOFRAME, the value must be 1Bh]
1996 */
1997 info_packet->hb2 = 0x1B;
1998
1999 /* HB3 = [Bits 7:2 = INFOFRAME SDP Version Number = 0x1]
2000 * [Bits 1:0 = Most significant two bits = 0x00]
2001 */
2002 info_packet->hb3 = 0x04;
2003
2004 payload_size = 0x1B;
2005 }
2006
2007 /* PB1 = 0x1A (24bit AMD IEEE OUI (0x00001A) - Byte 0) */
2008 info_packet->sb[1] = 0x1A;
2009
2010 /* PB2 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 1) */
2011 info_packet->sb[2] = 0x00;
2012
2013 /* PB3 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 2) */
2014 info_packet->sb[3] = 0x00;
2015
2016 /* PB4 = Reserved */
2017 info_packet->sb[4] = 0x00;
2018
2019 /* PB5 = Reserved */
2020 info_packet->sb[5] = 0x00;
2021
2022 /* PB6 = [Bits 7:3 = Reserved] */
2023 info_packet->sb[6] = 0x00;
2024
4fa086b9 2025 if (stream->freesync_ctx.supported == true)
4562236b
HW
2026 /* PB6 = [Bit 0 = FreeSync Supported] */
2027 info_packet->sb[6] |= 0x01;
2028
4fa086b9 2029 if (stream->freesync_ctx.enabled == true)
4562236b
HW
2030 /* PB6 = [Bit 1 = FreeSync Enabled] */
2031 info_packet->sb[6] |= 0x02;
2032
4fa086b9 2033 if (stream->freesync_ctx.active == true)
4562236b
HW
2034 /* PB6 = [Bit 2 = FreeSync Active] */
2035 info_packet->sb[6] |= 0x04;
2036
2037 /* PB7 = FreeSync Minimum refresh rate (Hz) */
4fa086b9 2038 info_packet->sb[7] = (unsigned char) (stream->freesync_ctx.
4562236b
HW
2039 min_refresh_in_micro_hz / 1000000);
2040
2041 /* PB8 = FreeSync Maximum refresh rate (Hz)
2042 *
2043 * Note: We do not use the maximum capable refresh rate
2044 * of the panel, because we should never go above the field
2045 * rate of the mode timing set.
2046 */
4fa086b9 2047 info_packet->sb[8] = (unsigned char) (stream->freesync_ctx.
4562236b
HW
2048 nominal_refresh_in_micro_hz / 1000000);
2049
2050 /* PB9 - PB27 = Reserved */
2051 for (idx = 9; idx <= 27; idx++)
2052 info_packet->sb[idx] = 0x00;
2053
2054 /* Calculate checksum */
2055 checksum += info_packet->hb0;
2056 checksum += info_packet->hb1;
2057 checksum += info_packet->hb2;
2058 checksum += info_packet->hb3;
2059
2060 for (idx = 1; idx <= payload_size; idx++)
2061 checksum += info_packet->sb[idx];
2062
2063 /* PB0 = Checksum (one byte complement) */
2064 info_packet->sb[0] = (unsigned char) (0x100 - checksum);
2065
2066 info_packet->valid = true;
2067}
2068
1646a6fe 2069static void set_hdr_static_info_packet(
6e4d6bee 2070 struct encoder_info_packet *info_packet,
3be5262e 2071 struct dc_plane_state *plane_state,
0971c40e 2072 struct dc_stream_state *stream)
1646a6fe 2073{
e5cf325b 2074 uint16_t i = 0;
1646a6fe 2075 enum signal_type signal = stream->signal;
e5cf325b
HW
2076 struct dc_hdr_static_metadata hdr_metadata;
2077 uint32_t data;
1646a6fe 2078
3be5262e 2079 if (!plane_state)
1646a6fe
AW
2080 return;
2081
3be5262e 2082 hdr_metadata = plane_state->hdr_static_ctx;
1646a6fe 2083
70063a59 2084 if (!hdr_metadata.hdr_supported)
10bff005
YS
2085 return;
2086
1646a6fe
AW
2087 if (dc_is_hdmi_signal(signal)) {
2088 info_packet->valid = true;
2089
2090 info_packet->hb0 = 0x87;
2091 info_packet->hb1 = 0x01;
2092 info_packet->hb2 = 0x1A;
2093 i = 1;
2094 } else if (dc_is_dp_signal(signal)) {
2095 info_packet->valid = true;
2096
2097 info_packet->hb0 = 0x00;
2098 info_packet->hb1 = 0x87;
2099 info_packet->hb2 = 0x1D;
2100 info_packet->hb3 = (0x13 << 2);
2101 i = 2;
2102 }
2103
1646a6fe
AW
2104 data = hdr_metadata.is_hdr;
2105 info_packet->sb[i++] = data ? 0x02 : 0x00;
2106 info_packet->sb[i++] = 0x00;
2107
2108 data = hdr_metadata.chromaticity_green_x / 2;
2109 info_packet->sb[i++] = data & 0xFF;
2110 info_packet->sb[i++] = (data & 0xFF00) >> 8;
2111
2112 data = hdr_metadata.chromaticity_green_y / 2;
2113 info_packet->sb[i++] = data & 0xFF;
2114 info_packet->sb[i++] = (data & 0xFF00) >> 8;
2115
2116 data = hdr_metadata.chromaticity_blue_x / 2;
2117 info_packet->sb[i++] = data & 0xFF;
2118 info_packet->sb[i++] = (data & 0xFF00) >> 8;
2119
2120 data = hdr_metadata.chromaticity_blue_y / 2;
2121 info_packet->sb[i++] = data & 0xFF;
2122 info_packet->sb[i++] = (data & 0xFF00) >> 8;
2123
2124 data = hdr_metadata.chromaticity_red_x / 2;
2125 info_packet->sb[i++] = data & 0xFF;
2126 info_packet->sb[i++] = (data & 0xFF00) >> 8;
2127
2128 data = hdr_metadata.chromaticity_red_y / 2;
2129 info_packet->sb[i++] = data & 0xFF;
2130 info_packet->sb[i++] = (data & 0xFF00) >> 8;
2131
2132 data = hdr_metadata.chromaticity_white_point_x / 2;
2133 info_packet->sb[i++] = data & 0xFF;
2134 info_packet->sb[i++] = (data & 0xFF00) >> 8;
2135
2136 data = hdr_metadata.chromaticity_white_point_y / 2;
2137 info_packet->sb[i++] = data & 0xFF;
2138 info_packet->sb[i++] = (data & 0xFF00) >> 8;
2139
2140 data = hdr_metadata.max_luminance;
2141 info_packet->sb[i++] = data & 0xFF;
2142 info_packet->sb[i++] = (data & 0xFF00) >> 8;
2143
2144 data = hdr_metadata.min_luminance;
2145 info_packet->sb[i++] = data & 0xFF;
2146 info_packet->sb[i++] = (data & 0xFF00) >> 8;
2147
2148 data = hdr_metadata.maximum_content_light_level;
2149 info_packet->sb[i++] = data & 0xFF;
2150 info_packet->sb[i++] = (data & 0xFF00) >> 8;
2151
2152 data = hdr_metadata.maximum_frame_average_light_level;
2153 info_packet->sb[i++] = data & 0xFF;
2154 info_packet->sb[i++] = (data & 0xFF00) >> 8;
2155
2156 if (dc_is_hdmi_signal(signal)) {
2157 uint32_t checksum = 0;
2158
2159 checksum += info_packet->hb0;
2160 checksum += info_packet->hb1;
2161 checksum += info_packet->hb2;
2162
2163 for (i = 1; i <= info_packet->hb2; i++)
2164 checksum += info_packet->sb[i];
2165
2166 info_packet->sb[0] = 0x100 - checksum;
2167 } else if (dc_is_dp_signal(signal)) {
2168 info_packet->sb[0] = 0x01;
2169 info_packet->sb[1] = 0x1A;
2170 }
2171}
2172
6e4d6bee
TC
2173static void set_vsc_info_packet(
2174 struct encoder_info_packet *info_packet,
0971c40e 2175 struct dc_stream_state *stream)
4562236b
HW
2176{
2177 unsigned int vscPacketRevision = 0;
2178 unsigned int i;
2179
94267b3d 2180 if (stream->sink->link->psr_enabled) {
4562236b
HW
2181 vscPacketRevision = 2;
2182 }
2183
2184 /* VSC packet not needed based on the features
2185 * supported by this DP display
2186 */
2187 if (vscPacketRevision == 0)
2188 return;
2189
2190 if (vscPacketRevision == 0x2) {
2191 /* Secondary-data Packet ID = 0*/
2192 info_packet->hb0 = 0x00;
2193 /* 07h - Packet Type Value indicating Video
2194 * Stream Configuration packet
2195 */
2196 info_packet->hb1 = 0x07;
2197 /* 02h = VSC SDP supporting 3D stereo and PSR
2198 * (applies to eDP v1.3 or higher).
2199 */
2200 info_packet->hb2 = 0x02;
2201 /* 08h = VSC packet supporting 3D stereo + PSR
2202 * (HB2 = 02h).
2203 */
2204 info_packet->hb3 = 0x08;
2205
2206 for (i = 0; i < 28; i++)
2207 info_packet->sb[i] = 0;
2208
2209 info_packet->valid = true;
2210 }
2211
2212 /*TODO: stereo 3D support and extend pixel encoding colorimetry*/
2213}
2214
8122a253 2215void dc_resource_validate_ctx_destruct(struct validate_context *context)
4562236b
HW
2216{
2217 int i, j;
2218
ab2541b6 2219 for (i = 0; i < context->stream_count; i++) {
3be5262e
HW
2220 for (j = 0; j < context->stream_status[i].plane_count; j++)
2221 dc_plane_state_release(
2222 context->stream_status[i].plane_states[j]);
4562236b 2223
3be5262e 2224 context->stream_status[i].plane_count = 0;
4fa086b9 2225 dc_stream_release(context->streams[i]);
ab2541b6 2226 context->streams[i] = NULL;
4562236b
HW
2227 }
2228}
2229
2230/*
ab2541b6 2231 * Copy src_ctx into dst_ctx and retain all surfaces and streams referenced
4562236b
HW
2232 * by the src_ctx
2233 */
8122a253 2234void dc_resource_validate_ctx_copy_construct(
4562236b
HW
2235 const struct validate_context *src_ctx,
2236 struct validate_context *dst_ctx)
2237{
2238 int i, j;
e8cd2643 2239 atomic_t ref_count = dst_ctx->ref_count;
4562236b
HW
2240
2241 *dst_ctx = *src_ctx;
2242
a2b8659d 2243 for (i = 0; i < MAX_PIPES; i++) {
4562236b
HW
2244 struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i];
2245
2246 if (cur_pipe->top_pipe)
2247 cur_pipe->top_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx];
2248
2249 if (cur_pipe->bottom_pipe)
2250 cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
2251
2252 }
2253
ab2541b6 2254 for (i = 0; i < dst_ctx->stream_count; i++) {
4fa086b9 2255 dc_stream_retain(dst_ctx->streams[i]);
3be5262e
HW
2256 for (j = 0; j < dst_ctx->stream_status[i].plane_count; j++)
2257 dc_plane_state_retain(
2258 dst_ctx->stream_status[i].plane_states[j]);
4562236b 2259 }
9a3afbb3
AG
2260
2261 /* context refcount should not be overridden */
2262 dst_ctx->ref_count = ref_count;
2263
4562236b
HW
2264}
2265
2266struct clock_source *dc_resource_find_first_free_pll(
a2b8659d
TC
2267 struct resource_context *res_ctx,
2268 const struct resource_pool *pool)
4562236b
HW
2269{
2270 int i;
2271
a2b8659d 2272 for (i = 0; i < pool->clk_src_count; ++i) {
4562236b 2273 if (res_ctx->clock_source_ref_count[i] == 0)
a2b8659d 2274 return pool->clock_sources[i];
4562236b
HW
2275 }
2276
2277 return NULL;
2278}
2279
2280void resource_build_info_frame(struct pipe_ctx *pipe_ctx)
2281{
2282 enum signal_type signal = SIGNAL_TYPE_NONE;
96c50c0d 2283 struct encoder_info_frame *info = &pipe_ctx->stream_res.encoder_info_frame;
4562236b
HW
2284
2285 /* default all packets to invalid */
6e4d6bee
TC
2286 info->avi.valid = false;
2287 info->gamut.valid = false;
2288 info->vendor.valid = false;
630e3573 2289 info->spd.valid = false;
6e4d6bee
TC
2290 info->hdrsmd.valid = false;
2291 info->vsc.valid = false;
4562236b
HW
2292
2293 signal = pipe_ctx->stream->signal;
2294
2295 /* HDMi and DP have different info packets*/
2296 if (dc_is_hdmi_signal(signal)) {
6e4d6bee
TC
2297 set_avi_info_frame(&info->avi, pipe_ctx);
2298
2299 set_vendor_info_packet(&info->vendor, pipe_ctx->stream);
2300
2301 set_spd_info_packet(&info->spd, pipe_ctx->stream);
2302
2303 set_hdr_static_info_packet(&info->hdrsmd,
3be5262e 2304 pipe_ctx->plane_state, pipe_ctx->stream);
6e4d6bee 2305
a33fa99d 2306 } else if (dc_is_dp_signal(signal)) {
6e4d6bee
TC
2307 set_vsc_info_packet(&info->vsc, pipe_ctx->stream);
2308
2309 set_spd_info_packet(&info->spd, pipe_ctx->stream);
2310
2311 set_hdr_static_info_packet(&info->hdrsmd,
3be5262e 2312 pipe_ctx->plane_state, pipe_ctx->stream);
a33fa99d 2313 }
4562236b 2314
6e4d6bee 2315 patch_gamut_packet_checksum(&info->gamut);
4562236b
HW
2316}
2317
2318enum dc_status resource_map_clock_resources(
2319 const struct core_dc *dc,
430ef426
DL
2320 struct validate_context *context,
2321 struct validate_context *old_context)
4562236b 2322{
ab2541b6 2323 int i, j;
a2b8659d 2324 const struct resource_pool *pool = dc->res_pool;
4562236b
HW
2325
2326 /* acquire new resources */
ab2541b6 2327 for (i = 0; i < context->stream_count; i++) {
0971c40e 2328 struct dc_stream_state *stream = context->streams[i];
4562236b 2329
430ef426 2330 if (old_context && resource_is_stream_unchanged(old_context, stream))
ab2541b6
AC
2331 continue;
2332
2333 for (j = 0; j < MAX_PIPES; j++) {
2334 struct pipe_ctx *pipe_ctx =
2335 &context->res_ctx.pipe_ctx[j];
4562236b 2336
ab2541b6 2337 if (context->res_ctx.pipe_ctx[j].stream != stream)
4562236b
HW
2338 continue;
2339
ab2541b6
AC
2340 if (dc_is_dp_signal(pipe_ctx->stream->signal)
2341 || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL)
a2b8659d 2342 pipe_ctx->clock_source = pool->dp_clock_source;
ab2541b6
AC
2343 else {
2344 pipe_ctx->clock_source = NULL;
4562236b 2345
ab2541b6
AC
2346 if (!dc->public.config.disable_disp_pll_sharing)
2347 resource_find_used_clk_src_for_sharing(
2348 &context->res_ctx,
2349 pipe_ctx);
4562236b 2350
ab2541b6 2351 if (pipe_ctx->clock_source == NULL)
4562236b 2352 pipe_ctx->clock_source =
a2b8659d
TC
2353 dc_resource_find_first_free_pll(
2354 &context->res_ctx,
2355 pool);
ab2541b6 2356 }
4562236b 2357
ab2541b6
AC
2358 if (pipe_ctx->clock_source == NULL)
2359 return DC_NO_CLOCK_SOURCE_RESOURCE;
4562236b 2360
ab2541b6 2361 resource_reference_clock_source(
a2b8659d 2362 &context->res_ctx, pool,
ab2541b6 2363 pipe_ctx->clock_source);
4562236b 2364
ab2541b6
AC
2365 /* only one cs per stream regardless of mpo */
2366 break;
4562236b
HW
2367 }
2368 }
2369
2370 return DC_OK;
2371}
2372
2373/*
2374 * Note: We need to disable output if clock sources change,
2375 * since bios does optimization and doesn't apply if changing
2376 * PHY when not already disabled.
2377 */
2378bool pipe_need_reprogram(
2379 struct pipe_ctx *pipe_ctx_old,
2380 struct pipe_ctx *pipe_ctx)
2381{
cfe4645e
DL
2382 if (!pipe_ctx_old->stream)
2383 return false;
2384
4562236b
HW
2385 if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink)
2386 return true;
2387
2388 if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal)
2389 return true;
2390
afaacef4 2391 if (pipe_ctx_old->stream_res.audio != pipe_ctx->stream_res.audio)
4562236b
HW
2392 return true;
2393
2394 if (pipe_ctx_old->clock_source != pipe_ctx->clock_source
2395 && pipe_ctx_old->stream != pipe_ctx->stream)
2396 return true;
2397
8e9c4c8c 2398 if (pipe_ctx_old->stream_res.stream_enc != pipe_ctx->stream_res.stream_enc)
4562236b
HW
2399 return true;
2400
2401 if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream))
2402 return true;
2403
2404
2405 return false;
2406}
529cad0f 2407
0971c40e 2408void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream,
529cad0f
DW
2409 struct bit_depth_reduction_params *fmt_bit_depth)
2410{
4fa086b9 2411 enum dc_dither_option option = stream->dither_option;
529cad0f 2412 enum dc_pixel_encoding pixel_encoding =
4fa086b9 2413 stream->timing.pixel_encoding;
529cad0f
DW
2414
2415 memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth));
2416
2417 if (option == DITHER_OPTION_DISABLE)
2418 return;
2419
2420 if (option == DITHER_OPTION_TRUN6) {
2421 fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
2422 fmt_bit_depth->flags.TRUNCATE_DEPTH = 0;
2423 } else if (option == DITHER_OPTION_TRUN8 ||
2424 option == DITHER_OPTION_TRUN8_SPATIAL6 ||
2425 option == DITHER_OPTION_TRUN8_FM6) {
2426 fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
2427 fmt_bit_depth->flags.TRUNCATE_DEPTH = 1;
2428 } else if (option == DITHER_OPTION_TRUN10 ||
2429 option == DITHER_OPTION_TRUN10_SPATIAL6 ||
2430 option == DITHER_OPTION_TRUN10_SPATIAL8 ||
2431 option == DITHER_OPTION_TRUN10_FM8 ||
2432 option == DITHER_OPTION_TRUN10_FM6 ||
2433 option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) {
2434 fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
2435 fmt_bit_depth->flags.TRUNCATE_DEPTH = 2;
2436 }
2437
2438 /* special case - Formatter can only reduce by 4 bits at most.
2439 * When reducing from 12 to 6 bits,
2440 * HW recommends we use trunc with round mode
2441 * (if we did nothing, trunc to 10 bits would be used)
2442 * note that any 12->10 bit reduction is ignored prior to DCE8,
2443 * as the input was 10 bits.
2444 */
2445 if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM ||
2446 option == DITHER_OPTION_SPATIAL6 ||
2447 option == DITHER_OPTION_FM6) {
2448 fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
2449 fmt_bit_depth->flags.TRUNCATE_DEPTH = 2;
2450 fmt_bit_depth->flags.TRUNCATE_MODE = 1;
2451 }
2452
2453 /* spatial dither
2454 * note that spatial modes 1-3 are never used
2455 */
2456 if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM ||
2457 option == DITHER_OPTION_SPATIAL6 ||
2458 option == DITHER_OPTION_TRUN10_SPATIAL6 ||
2459 option == DITHER_OPTION_TRUN8_SPATIAL6) {
2460 fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
2461 fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0;
2462 fmt_bit_depth->flags.HIGHPASS_RANDOM = 1;
2463 fmt_bit_depth->flags.RGB_RANDOM =
2464 (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0;
2465 } else if (option == DITHER_OPTION_SPATIAL8_FRAME_RANDOM ||
2466 option == DITHER_OPTION_SPATIAL8 ||
2467 option == DITHER_OPTION_SPATIAL8_FM6 ||
2468 option == DITHER_OPTION_TRUN10_SPATIAL8 ||
2469 option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) {
2470 fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
2471 fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1;
2472 fmt_bit_depth->flags.HIGHPASS_RANDOM = 1;
2473 fmt_bit_depth->flags.RGB_RANDOM =
2474 (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0;
2475 } else if (option == DITHER_OPTION_SPATIAL10_FRAME_RANDOM ||
2476 option == DITHER_OPTION_SPATIAL10 ||
2477 option == DITHER_OPTION_SPATIAL10_FM8 ||
2478 option == DITHER_OPTION_SPATIAL10_FM6) {
2479 fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
2480 fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2;
2481 fmt_bit_depth->flags.HIGHPASS_RANDOM = 1;
2482 fmt_bit_depth->flags.RGB_RANDOM =
2483 (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0;
2484 }
2485
2486 if (option == DITHER_OPTION_SPATIAL6 ||
2487 option == DITHER_OPTION_SPATIAL8 ||
2488 option == DITHER_OPTION_SPATIAL10) {
2489 fmt_bit_depth->flags.FRAME_RANDOM = 0;
2490 } else {
2491 fmt_bit_depth->flags.FRAME_RANDOM = 1;
2492 }
2493
2494 //////////////////////
2495 //// temporal dither
2496 //////////////////////
2497 if (option == DITHER_OPTION_FM6 ||
2498 option == DITHER_OPTION_SPATIAL8_FM6 ||
2499 option == DITHER_OPTION_SPATIAL10_FM6 ||
2500 option == DITHER_OPTION_TRUN10_FM6 ||
2501 option == DITHER_OPTION_TRUN8_FM6 ||
2502 option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) {
2503 fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1;
2504 fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 0;
2505 } else if (option == DITHER_OPTION_FM8 ||
2506 option == DITHER_OPTION_SPATIAL10_FM8 ||
2507 option == DITHER_OPTION_TRUN10_FM8) {
2508 fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1;
2509 fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 1;
2510 } else if (option == DITHER_OPTION_FM10) {
2511 fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1;
2512 fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 2;
2513 }
2514
2515 fmt_bit_depth->pixel_encoding = pixel_encoding;
2516}
9345d987 2517
0971c40e 2518bool dc_validate_stream(const struct dc *dc, struct dc_stream_state *stream)
9345d987
AG
2519{
2520 struct core_dc *core_dc = DC_TO_CORE(dc);
2521 struct dc_context *dc_ctx = core_dc->ctx;
4fa086b9 2522 struct dc_link *link = stream->sink->link;
9345d987
AG
2523 struct timing_generator *tg = core_dc->res_pool->timing_generators[0];
2524 enum dc_status res = DC_OK;
2525
4fa086b9 2526 calculate_phy_pix_clks(stream);
9345d987 2527
4fa086b9 2528 if (!tg->funcs->validate_timing(tg, &stream->timing))
9345d987
AG
2529 res = DC_FAIL_CONTROLLER_VALIDATE;
2530
2531 if (res == DC_OK)
2532 if (!link->link_enc->funcs->validate_output_with_stream(
4fa086b9 2533 link->link_enc, stream))
9345d987
AG
2534 res = DC_FAIL_ENC_VALIDATE;
2535
2536 /* TODO: validate audio ASIC caps, encoder */
2537
2538 if (res == DC_OK)
4fa086b9 2539 res = dc_link_validate_mode_timing(stream,
9345d987 2540 link,
4fa086b9 2541 &stream->timing);
9345d987
AG
2542
2543 if (res != DC_OK)
2544 DC_ERROR("Failed validation for stream %p, err:%d, !\n",
2545 stream, res);
2546
2547 return res == DC_OK;
2548}
792671d7 2549
c9614aeb 2550bool dc_validate_plane(const struct dc *dc, const struct dc_plane_state *plane_state)
792671d7
AG
2551{
2552 struct core_dc *core_dc = DC_TO_CORE(dc);
2553
2554 /* TODO For now validates pixel format only */
c9614aeb
HW
2555 if (core_dc->res_pool->funcs->validate_plane)
2556 return core_dc->res_pool->funcs->validate_plane(plane_state) == DC_OK;
792671d7
AG
2557
2558 return true;
2559}