drm/amd/display: enable odm + full screen mpo on dcn21
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / display / dc / core / dc_resource.c
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
26 #include <linux/slab.h>
27
28 #include "dm_services.h"
29
30 #include "resource.h"
31 #include "include/irq_service_interface.h"
32 #include "link_encoder.h"
33 #include "stream_encoder.h"
34 #include "opp.h"
35 #include "timing_generator.h"
36 #include "transform.h"
37 #include "dccg.h"
38 #include "dchubbub.h"
39 #include "dpp.h"
40 #include "core_types.h"
41 #include "set_mode_types.h"
42 #include "virtual/virtual_stream_encoder.h"
43 #include "dpcd_defs.h"
44
45 #if defined(CONFIG_DRM_AMD_DC_SI)
46 #include "dce60/dce60_resource.h"
47 #endif
48 #include "dce80/dce80_resource.h"
49 #include "dce100/dce100_resource.h"
50 #include "dce110/dce110_resource.h"
51 #include "dce112/dce112_resource.h"
52 #include "dce120/dce120_resource.h"
53 #if defined(CONFIG_DRM_AMD_DC_DCN)
54 #include "dcn10/dcn10_resource.h"
55 #include "dcn20/dcn20_resource.h"
56 #include "dcn21/dcn21_resource.h"
57 #endif
58 #if defined(CONFIG_DRM_AMD_DC_DCN3_0)
59 #include "../dcn30/dcn30_resource.h"
60 #endif
61 #if defined(CONFIG_DRM_AMD_DC_DCN3_01)
62 #include "../dcn301/dcn301_resource.h"
63 #endif
64 #if defined(CONFIG_DRM_AMD_DC_DCN3_02)
65 #include "../dcn302/dcn302_resource.h"
66 #endif
67
68 #define DC_LOGGER_INIT(logger)
69
70 enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id)
71 {
72         enum dce_version dc_version = DCE_VERSION_UNKNOWN;
73         switch (asic_id.chip_family) {
74
75 #if defined(CONFIG_DRM_AMD_DC_SI)
76         case FAMILY_SI:
77                 if (ASIC_REV_IS_TAHITI_P(asic_id.hw_internal_rev) ||
78                     ASIC_REV_IS_PITCAIRN_PM(asic_id.hw_internal_rev) ||
79                     ASIC_REV_IS_CAPEVERDE_M(asic_id.hw_internal_rev))
80                         dc_version = DCE_VERSION_6_0;
81                 else if (ASIC_REV_IS_OLAND_M(asic_id.hw_internal_rev))
82                         dc_version = DCE_VERSION_6_4;
83                 else
84                         dc_version = DCE_VERSION_6_1;
85                 break;
86 #endif
87         case FAMILY_CI:
88                 dc_version = DCE_VERSION_8_0;
89                 break;
90         case FAMILY_KV:
91                 if (ASIC_REV_IS_KALINDI(asic_id.hw_internal_rev) ||
92                     ASIC_REV_IS_BHAVANI(asic_id.hw_internal_rev) ||
93                     ASIC_REV_IS_GODAVARI(asic_id.hw_internal_rev))
94                         dc_version = DCE_VERSION_8_3;
95                 else
96                         dc_version = DCE_VERSION_8_1;
97                 break;
98         case FAMILY_CZ:
99                 dc_version = DCE_VERSION_11_0;
100                 break;
101
102         case FAMILY_VI:
103                 if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) ||
104                                 ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) {
105                         dc_version = DCE_VERSION_10_0;
106                         break;
107                 }
108                 if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) ||
109                                 ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) ||
110                                 ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) {
111                         dc_version = DCE_VERSION_11_2;
112                 }
113                 if (ASIC_REV_IS_VEGAM(asic_id.hw_internal_rev))
114                         dc_version = DCE_VERSION_11_22;
115                 break;
116         case FAMILY_AI:
117                 if (ASICREV_IS_VEGA20_P(asic_id.hw_internal_rev))
118                         dc_version = DCE_VERSION_12_1;
119                 else
120                         dc_version = DCE_VERSION_12_0;
121                 break;
122 #if defined(CONFIG_DRM_AMD_DC_DCN)
123         case FAMILY_RV:
124                 dc_version = DCN_VERSION_1_0;
125                 if (ASICREV_IS_RAVEN2(asic_id.hw_internal_rev))
126                         dc_version = DCN_VERSION_1_01;
127                 if (ASICREV_IS_RENOIR(asic_id.hw_internal_rev))
128                         dc_version = DCN_VERSION_2_1;
129 #if defined(CONFIG_DRM_AMD_DC_GREEN_SARDINE)
130                 if (ASICREV_IS_GREEN_SARDINE(asic_id.hw_internal_rev))
131                         dc_version = DCN_VERSION_2_1;
132 #endif
133                 break;
134 #endif
135
136         case FAMILY_NV:
137                 dc_version = DCN_VERSION_2_0;
138 #if defined(CONFIG_DRM_AMD_DC_DCN3_0)
139                 if (ASICREV_IS_SIENNA_CICHLID_P(asic_id.hw_internal_rev))
140                         dc_version = DCN_VERSION_3_0;
141 #endif
142 #if defined(CONFIG_DRM_AMD_DC_DCN3_02)
143                 if (ASICREV_IS_DIMGREY_CAVEFISH_P(asic_id.hw_internal_rev))
144                         dc_version = DCN_VERSION_3_02;
145 #endif
146                 break;
147
148 #if defined(CONFIG_DRM_AMD_DC_DCN3_01)
149         case FAMILY_VGH:
150                 dc_version = DCN_VERSION_3_01;
151                 break;
152 #endif
153         default:
154                 dc_version = DCE_VERSION_UNKNOWN;
155                 break;
156         }
157         return dc_version;
158 }
159
160 struct resource_pool *dc_create_resource_pool(struct dc  *dc,
161                                               const struct dc_init_data *init_data,
162                                               enum dce_version dc_version)
163 {
164         struct resource_pool *res_pool = NULL;
165
166         switch (dc_version) {
167 #if defined(CONFIG_DRM_AMD_DC_SI)
168         case DCE_VERSION_6_0:
169                 res_pool = dce60_create_resource_pool(
170                         init_data->num_virtual_links, dc);
171                 break;
172         case DCE_VERSION_6_1:
173                 res_pool = dce61_create_resource_pool(
174                         init_data->num_virtual_links, dc);
175                 break;
176         case DCE_VERSION_6_4:
177                 res_pool = dce64_create_resource_pool(
178                         init_data->num_virtual_links, dc);
179                 break;
180 #endif
181         case DCE_VERSION_8_0:
182                 res_pool = dce80_create_resource_pool(
183                                 init_data->num_virtual_links, dc);
184                 break;
185         case DCE_VERSION_8_1:
186                 res_pool = dce81_create_resource_pool(
187                                 init_data->num_virtual_links, dc);
188                 break;
189         case DCE_VERSION_8_3:
190                 res_pool = dce83_create_resource_pool(
191                                 init_data->num_virtual_links, dc);
192                 break;
193         case DCE_VERSION_10_0:
194                 res_pool = dce100_create_resource_pool(
195                                 init_data->num_virtual_links, dc);
196                 break;
197         case DCE_VERSION_11_0:
198                 res_pool = dce110_create_resource_pool(
199                                 init_data->num_virtual_links, dc,
200                                 init_data->asic_id);
201                 break;
202         case DCE_VERSION_11_2:
203         case DCE_VERSION_11_22:
204                 res_pool = dce112_create_resource_pool(
205                                 init_data->num_virtual_links, dc);
206                 break;
207         case DCE_VERSION_12_0:
208         case DCE_VERSION_12_1:
209                 res_pool = dce120_create_resource_pool(
210                                 init_data->num_virtual_links, dc);
211                 break;
212
213 #if defined(CONFIG_DRM_AMD_DC_DCN)
214         case DCN_VERSION_1_0:
215         case DCN_VERSION_1_01:
216                 res_pool = dcn10_create_resource_pool(init_data, dc);
217                 break;
218
219
220         case DCN_VERSION_2_0:
221                 res_pool = dcn20_create_resource_pool(init_data, dc);
222                 break;
223         case DCN_VERSION_2_1:
224                 res_pool = dcn21_create_resource_pool(init_data, dc);
225                 break;
226 #endif
227 #if defined(CONFIG_DRM_AMD_DC_DCN3_0)
228         case DCN_VERSION_3_0:
229                 res_pool = dcn30_create_resource_pool(init_data, dc);
230                 break;
231 #endif
232
233 #if defined(CONFIG_DRM_AMD_DC_DCN3_01)
234         case DCN_VERSION_3_01:
235                 res_pool = dcn301_create_resource_pool(init_data, dc);
236                 break;
237 #endif
238 #if defined(CONFIG_DRM_AMD_DC_DCN3_02)
239         case DCN_VERSION_3_02:
240                 res_pool = dcn302_create_resource_pool(init_data, dc);
241                 break;
242
243 #endif
244         default:
245                 break;
246         }
247
248         if (res_pool != NULL) {
249                 if (dc->ctx->dc_bios->fw_info_valid) {
250                         res_pool->ref_clocks.xtalin_clock_inKhz =
251                                 dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
252                         /* initialize with firmware data first, no all
253                          * ASIC have DCCG SW component. FPGA or
254                          * simulation need initialization of
255                          * dccg_ref_clock_inKhz, dchub_ref_clock_inKhz
256                          * with xtalin_clock_inKhz
257                          */
258                         res_pool->ref_clocks.dccg_ref_clock_inKhz =
259                                 res_pool->ref_clocks.xtalin_clock_inKhz;
260                         res_pool->ref_clocks.dchub_ref_clock_inKhz =
261                                 res_pool->ref_clocks.xtalin_clock_inKhz;
262                 } else
263                         ASSERT_CRITICAL(false);
264         }
265
266         return res_pool;
267 }
268
269 void dc_destroy_resource_pool(struct dc  *dc)
270 {
271         if (dc) {
272                 if (dc->res_pool)
273                         dc->res_pool->funcs->destroy(&dc->res_pool);
274
275                 kfree(dc->hwseq);
276         }
277 }
278
279 static void update_num_audio(
280         const struct resource_straps *straps,
281         unsigned int *num_audio,
282         struct audio_support *aud_support)
283 {
284         aud_support->dp_audio = true;
285         aud_support->hdmi_audio_native = false;
286         aud_support->hdmi_audio_on_dongle = false;
287
288         if (straps->hdmi_disable == 0) {
289                 if (straps->dc_pinstraps_audio & 0x2) {
290                         aud_support->hdmi_audio_on_dongle = true;
291                         aud_support->hdmi_audio_native = true;
292                 }
293         }
294
295         switch (straps->audio_stream_number) {
296         case 0: /* multi streams supported */
297                 break;
298         case 1: /* multi streams not supported */
299                 *num_audio = 1;
300                 break;
301         default:
302                 DC_ERR("DC: unexpected audio fuse!\n");
303         }
304 }
305
306 bool resource_construct(
307         unsigned int num_virtual_links,
308         struct dc  *dc,
309         struct resource_pool *pool,
310         const struct resource_create_funcs *create_funcs)
311 {
312         struct dc_context *ctx = dc->ctx;
313         const struct resource_caps *caps = pool->res_cap;
314         int i;
315         unsigned int num_audio = caps->num_audio;
316         struct resource_straps straps = {0};
317
318         if (create_funcs->read_dce_straps)
319                 create_funcs->read_dce_straps(dc->ctx, &straps);
320
321         pool->audio_count = 0;
322         if (create_funcs->create_audio) {
323                 /* find the total number of streams available via the
324                  * AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT
325                  * registers (one for each pin) starting from pin 1
326                  * up to the max number of audio pins.
327                  * We stop on the first pin where
328                  * PORT_CONNECTIVITY == 1 (as instructed by HW team).
329                  */
330                 update_num_audio(&straps, &num_audio, &pool->audio_support);
331                 for (i = 0; i < caps->num_audio; i++) {
332                         struct audio *aud = create_funcs->create_audio(ctx, i);
333
334                         if (aud == NULL) {
335                                 DC_ERR("DC: failed to create audio!\n");
336                                 return false;
337                         }
338                         if (!aud->funcs->endpoint_valid(aud)) {
339                                 aud->funcs->destroy(&aud);
340                                 break;
341                         }
342                         pool->audios[i] = aud;
343                         pool->audio_count++;
344                 }
345         }
346
347         pool->stream_enc_count = 0;
348         if (create_funcs->create_stream_encoder) {
349                 for (i = 0; i < caps->num_stream_encoder; i++) {
350                         pool->stream_enc[i] = create_funcs->create_stream_encoder(i, ctx);
351                         if (pool->stream_enc[i] == NULL)
352                                 DC_ERR("DC: failed to create stream_encoder!\n");
353                         pool->stream_enc_count++;
354                 }
355         }
356
357 #if defined(CONFIG_DRM_AMD_DC_DCN3_0)
358         for (i = 0; i < caps->num_mpc_3dlut; i++) {
359                 pool->mpc_lut[i] = dc_create_3dlut_func();
360                 if (pool->mpc_lut[i] == NULL)
361                         DC_ERR("DC: failed to create MPC 3dlut!\n");
362                 pool->mpc_shaper[i] = dc_create_transfer_func();
363                 if (pool->mpc_shaper[i] == NULL)
364                         DC_ERR("DC: failed to create MPC shaper!\n");
365         }
366 #endif
367         dc->caps.dynamic_audio = false;
368         if (pool->audio_count < pool->stream_enc_count) {
369                 dc->caps.dynamic_audio = true;
370         }
371         for (i = 0; i < num_virtual_links; i++) {
372                 pool->stream_enc[pool->stream_enc_count] =
373                         virtual_stream_encoder_create(
374                                         ctx, ctx->dc_bios);
375                 if (pool->stream_enc[pool->stream_enc_count] == NULL) {
376                         DC_ERR("DC: failed to create stream_encoder!\n");
377                         return false;
378                 }
379                 pool->stream_enc_count++;
380         }
381
382         dc->hwseq = create_funcs->create_hwseq(ctx);
383
384         return true;
385 }
386 static int find_matching_clock_source(
387                 const struct resource_pool *pool,
388                 struct clock_source *clock_source)
389 {
390
391         int i;
392
393         for (i = 0; i < pool->clk_src_count; i++) {
394                 if (pool->clock_sources[i] == clock_source)
395                         return i;
396         }
397         return -1;
398 }
399
400 void resource_unreference_clock_source(
401                 struct resource_context *res_ctx,
402                 const struct resource_pool *pool,
403                 struct clock_source *clock_source)
404 {
405         int i = find_matching_clock_source(pool, clock_source);
406
407         if (i > -1)
408                 res_ctx->clock_source_ref_count[i]--;
409
410         if (pool->dp_clock_source == clock_source)
411                 res_ctx->dp_clock_source_ref_count--;
412 }
413
414 void resource_reference_clock_source(
415                 struct resource_context *res_ctx,
416                 const struct resource_pool *pool,
417                 struct clock_source *clock_source)
418 {
419         int i = find_matching_clock_source(pool, clock_source);
420
421         if (i > -1)
422                 res_ctx->clock_source_ref_count[i]++;
423
424         if (pool->dp_clock_source == clock_source)
425                 res_ctx->dp_clock_source_ref_count++;
426 }
427
428 int resource_get_clock_source_reference(
429                 struct resource_context *res_ctx,
430                 const struct resource_pool *pool,
431                 struct clock_source *clock_source)
432 {
433         int i = find_matching_clock_source(pool, clock_source);
434
435         if (i > -1)
436                 return res_ctx->clock_source_ref_count[i];
437
438         if (pool->dp_clock_source == clock_source)
439                 return res_ctx->dp_clock_source_ref_count;
440
441         return -1;
442 }
443
444 bool resource_are_streams_timing_synchronizable(
445         struct dc_stream_state *stream1,
446         struct dc_stream_state *stream2)
447 {
448         if (stream1->timing.h_total != stream2->timing.h_total)
449                 return false;
450
451         if (stream1->timing.v_total != stream2->timing.v_total)
452                 return false;
453
454         if (stream1->timing.h_addressable
455                                 != stream2->timing.h_addressable)
456                 return false;
457
458         if (stream1->timing.v_addressable
459                                 != stream2->timing.v_addressable)
460                 return false;
461
462         if (stream1->timing.v_front_porch
463                                 != stream2->timing.v_front_porch)
464                 return false;
465
466         if (stream1->timing.pix_clk_100hz
467                                 != stream2->timing.pix_clk_100hz)
468                 return false;
469
470         if (stream1->clamping.c_depth != stream2->clamping.c_depth)
471                 return false;
472
473         if (stream1->phy_pix_clk != stream2->phy_pix_clk
474                         && (!dc_is_dp_signal(stream1->signal)
475                         || !dc_is_dp_signal(stream2->signal)))
476                 return false;
477
478         if (stream1->view_format != stream2->view_format)
479                 return false;
480
481         if (stream1->ignore_msa_timing_param || stream2->ignore_msa_timing_param)
482                 return false;
483
484         return true;
485 }
486 static bool is_dp_and_hdmi_sharable(
487                 struct dc_stream_state *stream1,
488                 struct dc_stream_state *stream2)
489 {
490         if (stream1->ctx->dc->caps.disable_dp_clk_share)
491                 return false;
492
493         if (stream1->clamping.c_depth != COLOR_DEPTH_888 ||
494                 stream2->clamping.c_depth != COLOR_DEPTH_888)
495                 return false;
496
497         return true;
498
499 }
500
501 static bool is_sharable_clk_src(
502         const struct pipe_ctx *pipe_with_clk_src,
503         const struct pipe_ctx *pipe)
504 {
505         if (pipe_with_clk_src->clock_source == NULL)
506                 return false;
507
508         if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL)
509                 return false;
510
511         if (dc_is_dp_signal(pipe_with_clk_src->stream->signal) ||
512                 (dc_is_dp_signal(pipe->stream->signal) &&
513                 !is_dp_and_hdmi_sharable(pipe_with_clk_src->stream,
514                                      pipe->stream)))
515                 return false;
516
517         if (dc_is_hdmi_signal(pipe_with_clk_src->stream->signal)
518                         && dc_is_dual_link_signal(pipe->stream->signal))
519                 return false;
520
521         if (dc_is_hdmi_signal(pipe->stream->signal)
522                         && dc_is_dual_link_signal(pipe_with_clk_src->stream->signal))
523                 return false;
524
525         if (!resource_are_streams_timing_synchronizable(
526                         pipe_with_clk_src->stream, pipe->stream))
527                 return false;
528
529         return true;
530 }
531
532 struct clock_source *resource_find_used_clk_src_for_sharing(
533                                         struct resource_context *res_ctx,
534                                         struct pipe_ctx *pipe_ctx)
535 {
536         int i;
537
538         for (i = 0; i < MAX_PIPES; i++) {
539                 if (is_sharable_clk_src(&res_ctx->pipe_ctx[i], pipe_ctx))
540                         return res_ctx->pipe_ctx[i].clock_source;
541         }
542
543         return NULL;
544 }
545
546 static enum pixel_format convert_pixel_format_to_dalsurface(
547                 enum surface_pixel_format surface_pixel_format)
548 {
549         enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
550
551         switch (surface_pixel_format) {
552         case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
553                 dal_pixel_format = PIXEL_FORMAT_INDEX8;
554                 break;
555         case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
556                 dal_pixel_format = PIXEL_FORMAT_RGB565;
557                 break;
558         case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
559                 dal_pixel_format = PIXEL_FORMAT_RGB565;
560                 break;
561         case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
562                 dal_pixel_format = PIXEL_FORMAT_ARGB8888;
563                 break;
564         case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
565                 dal_pixel_format = PIXEL_FORMAT_ARGB8888;
566                 break;
567         case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
568                 dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
569                 break;
570         case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
571                 dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
572                 break;
573         case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
574                 dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS;
575                 break;
576         case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
577         case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
578                 dal_pixel_format = PIXEL_FORMAT_FP16;
579                 break;
580         case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
581         case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
582                 dal_pixel_format = PIXEL_FORMAT_420BPP8;
583                 break;
584         case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
585         case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
586                 dal_pixel_format = PIXEL_FORMAT_420BPP10;
587                 break;
588         case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
589         default:
590                 dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
591                 break;
592         }
593         return dal_pixel_format;
594 }
595
596 static inline void get_vp_scan_direction(
597         enum dc_rotation_angle rotation,
598         bool horizontal_mirror,
599         bool *orthogonal_rotation,
600         bool *flip_vert_scan_dir,
601         bool *flip_horz_scan_dir)
602 {
603         *orthogonal_rotation = false;
604         *flip_vert_scan_dir = false;
605         *flip_horz_scan_dir = false;
606         if (rotation == ROTATION_ANGLE_180) {
607                 *flip_vert_scan_dir = true;
608                 *flip_horz_scan_dir = true;
609         } else if (rotation == ROTATION_ANGLE_90) {
610                 *orthogonal_rotation = true;
611                 *flip_horz_scan_dir = true;
612         } else if (rotation == ROTATION_ANGLE_270) {
613                 *orthogonal_rotation = true;
614                 *flip_vert_scan_dir = true;
615         }
616
617         if (horizontal_mirror)
618                 *flip_horz_scan_dir = !*flip_horz_scan_dir;
619 }
620
621 int get_num_mpc_splits(struct pipe_ctx *pipe)
622 {
623         int mpc_split_count = 0;
624         struct pipe_ctx *other_pipe = pipe->bottom_pipe;
625
626         while (other_pipe && other_pipe->plane_state == pipe->plane_state) {
627                 mpc_split_count++;
628                 other_pipe = other_pipe->bottom_pipe;
629         }
630         other_pipe = pipe->top_pipe;
631         while (other_pipe && other_pipe->plane_state == pipe->plane_state) {
632                 mpc_split_count++;
633                 other_pipe = other_pipe->top_pipe;
634         }
635
636         return mpc_split_count;
637 }
638
639 int get_num_odm_splits(struct pipe_ctx *pipe)
640 {
641         int odm_split_count = 0;
642         struct pipe_ctx *next_pipe = pipe->next_odm_pipe;
643         while (next_pipe) {
644                 odm_split_count++;
645                 next_pipe = next_pipe->next_odm_pipe;
646         }
647         pipe = pipe->prev_odm_pipe;
648         while (pipe) {
649                 odm_split_count++;
650                 pipe = pipe->prev_odm_pipe;
651         }
652         return odm_split_count;
653 }
654
655 static void calculate_split_count_and_index(struct pipe_ctx *pipe_ctx, int *split_count, int *split_idx)
656 {
657         *split_count = get_num_odm_splits(pipe_ctx);
658         *split_idx = 0;
659         if (*split_count == 0) {
660                 /*Check for mpc split*/
661                 struct pipe_ctx *split_pipe = pipe_ctx->top_pipe;
662
663                 *split_count = get_num_mpc_splits(pipe_ctx);
664                 while (split_pipe && split_pipe->plane_state == pipe_ctx->plane_state) {
665                         (*split_idx)++;
666                         split_pipe = split_pipe->top_pipe;
667                 }
668         } else {
669                 /*Get odm split index*/
670                 struct pipe_ctx *split_pipe = pipe_ctx->prev_odm_pipe;
671
672                 while (split_pipe) {
673                         (*split_idx)++;
674                         split_pipe = split_pipe->prev_odm_pipe;
675                 }
676         }
677 }
678
679 static void calculate_viewport(struct pipe_ctx *pipe_ctx)
680 {
681         const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
682         const struct dc_stream_state *stream = pipe_ctx->stream;
683         struct scaler_data *data = &pipe_ctx->plane_res.scl_data;
684         struct rect surf_src = plane_state->src_rect;
685         struct rect clip, dest;
686         int vpc_div = (data->format == PIXEL_FORMAT_420BPP8
687                         || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1;
688         int split_count = 0;
689         int split_idx = 0;
690         bool orthogonal_rotation, flip_y_start, flip_x_start;
691
692         calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx);
693
694         if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE ||
695                 stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) {
696                 split_count = 0;
697                 split_idx = 0;
698         }
699
700         /* The actual clip is an intersection between stream
701          * source and surface clip
702          */
703         dest = plane_state->dst_rect;
704         clip.x = stream->src.x > plane_state->clip_rect.x ?
705                         stream->src.x : plane_state->clip_rect.x;
706
707         clip.width = stream->src.x + stream->src.width <
708                         plane_state->clip_rect.x + plane_state->clip_rect.width ?
709                         stream->src.x + stream->src.width - clip.x :
710                         plane_state->clip_rect.x + plane_state->clip_rect.width - clip.x ;
711
712         clip.y = stream->src.y > plane_state->clip_rect.y ?
713                         stream->src.y : plane_state->clip_rect.y;
714
715         clip.height = stream->src.y + stream->src.height <
716                         plane_state->clip_rect.y + plane_state->clip_rect.height ?
717                         stream->src.y + stream->src.height - clip.y :
718                         plane_state->clip_rect.y + plane_state->clip_rect.height - clip.y ;
719
720         /*
721          * Need to calculate how scan origin is shifted in vp space
722          * to correctly rotate clip and dst
723          */
724         get_vp_scan_direction(
725                         plane_state->rotation,
726                         plane_state->horizontal_mirror,
727                         &orthogonal_rotation,
728                         &flip_y_start,
729                         &flip_x_start);
730
731         if (orthogonal_rotation) {
732                 swap(clip.x, clip.y);
733                 swap(clip.width, clip.height);
734                 swap(dest.x, dest.y);
735                 swap(dest.width, dest.height);
736         }
737         if (flip_x_start) {
738                 clip.x = dest.x + dest.width - clip.x - clip.width;
739                 dest.x = 0;
740         }
741         if (flip_y_start) {
742                 clip.y = dest.y + dest.height - clip.y - clip.height;
743                 dest.y = 0;
744         }
745
746         /* offset = surf_src.ofs + (clip.ofs - surface->dst_rect.ofs) * scl_ratio
747          * num_pixels = clip.num_pix * scl_ratio
748          */
749         data->viewport.x = surf_src.x + (clip.x - dest.x) * surf_src.width / dest.width;
750         data->viewport.width = clip.width * surf_src.width / dest.width;
751
752         data->viewport.y = surf_src.y + (clip.y - dest.y) * surf_src.height / dest.height;
753         data->viewport.height = clip.height * surf_src.height / dest.height;
754
755         /* Handle split */
756         if (split_count) {
757                 /* extra pixels in the division remainder need to go to pipes after
758                  * the extra pixel index minus one(epimo) defined here as:
759                  */
760                 int epimo = 0;
761
762                 if (orthogonal_rotation) {
763                         if (flip_y_start)
764                                 split_idx = split_count - split_idx;
765
766                         epimo = split_count - data->viewport.height % (split_count + 1);
767
768                         data->viewport.y += (data->viewport.height / (split_count + 1)) * split_idx;
769                         if (split_idx > epimo)
770                                 data->viewport.y += split_idx - epimo - 1;
771                         data->viewport.height = data->viewport.height / (split_count + 1) + (split_idx > epimo ? 1 : 0);
772                 } else {
773                         if (flip_x_start)
774                                 split_idx = split_count - split_idx;
775
776                         epimo = split_count - data->viewport.width % (split_count + 1);
777
778                         data->viewport.x += (data->viewport.width / (split_count + 1)) * split_idx;
779                         if (split_idx > epimo)
780                                 data->viewport.x += split_idx - epimo - 1;
781                         data->viewport.width = data->viewport.width / (split_count + 1) + (split_idx > epimo ? 1 : 0);
782                 }
783         }
784
785         /* Round down, compensate in init */
786         data->viewport_c.x = data->viewport.x / vpc_div;
787         data->viewport_c.y = data->viewport.y / vpc_div;
788         data->inits.h_c = (data->viewport.x % vpc_div) != 0 ? dc_fixpt_half : dc_fixpt_zero;
789         data->inits.v_c = (data->viewport.y % vpc_div) != 0 ? dc_fixpt_half : dc_fixpt_zero;
790
791         /* Round up, assume original video size always even dimensions */
792         data->viewport_c.width = (data->viewport.width + vpc_div - 1) / vpc_div;
793         data->viewport_c.height = (data->viewport.height + vpc_div - 1) / vpc_div;
794
795         data->viewport_unadjusted = data->viewport;
796         data->viewport_c_unadjusted = data->viewport_c;
797 }
798
799 static void calculate_recout(struct pipe_ctx *pipe_ctx)
800 {
801         const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
802         const struct dc_stream_state *stream = pipe_ctx->stream;
803         struct scaler_data *data = &pipe_ctx->plane_res.scl_data;
804         struct rect surf_clip = plane_state->clip_rect;
805         bool pri_split_tb = pipe_ctx->bottom_pipe &&
806                         pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state &&
807                         stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM;
808         bool sec_split_tb = pipe_ctx->top_pipe &&
809                         pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state &&
810                         stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM;
811         int split_count = 0;
812         int split_idx = 0;
813
814         calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx);
815
816         /*
817          * Only the leftmost ODM pipe should be offset by a nonzero distance
818          */
819         if (!pipe_ctx->prev_odm_pipe) {
820                 data->recout.x = stream->dst.x;
821                 if (stream->src.x < surf_clip.x)
822                         data->recout.x += (surf_clip.x - stream->src.x) * stream->dst.width
823                                                 / stream->src.width;
824
825         } else
826                 data->recout.x = 0;
827
828         data->recout.width = surf_clip.width * stream->dst.width / stream->src.width;
829         if (data->recout.width + data->recout.x > stream->dst.x + stream->dst.width)
830                 data->recout.width = stream->dst.x + stream->dst.width - data->recout.x;
831
832         data->recout.y = stream->dst.y;
833         if (stream->src.y < surf_clip.y)
834                 data->recout.y += (surf_clip.y - stream->src.y) * stream->dst.height
835                                                 / stream->src.height;
836
837         data->recout.height = surf_clip.height * stream->dst.height / stream->src.height;
838         if (data->recout.height + data->recout.y > stream->dst.y + stream->dst.height)
839                 data->recout.height = stream->dst.y + stream->dst.height - data->recout.y;
840
841         /* Handle h & v split, handle rotation using viewport */
842         if (sec_split_tb) {
843                 data->recout.y += data->recout.height / 2;
844                 /* Floor primary pipe, ceil 2ndary pipe */
845                 data->recout.height = (data->recout.height + 1) / 2;
846         } else if (pri_split_tb)
847                 data->recout.height /= 2;
848         else if (split_count) {
849                 /* extra pixels in the division remainder need to go to pipes after
850                  * the extra pixel index minus one(epimo) defined here as:
851                  */
852                 int epimo = split_count - data->recout.width % (split_count + 1);
853
854                 /*no recout offset due to odm */
855                 if (!pipe_ctx->next_odm_pipe && !pipe_ctx->prev_odm_pipe) {
856                         data->recout.x += (data->recout.width / (split_count + 1)) * split_idx;
857                         if (split_idx > epimo)
858                                 data->recout.x += split_idx - epimo - 1;
859                 }
860                 data->recout.width = data->recout.width / (split_count + 1) + (split_idx > epimo ? 1 : 0);
861         }
862 }
863
864 static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx)
865 {
866         const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
867         const struct dc_stream_state *stream = pipe_ctx->stream;
868         struct rect surf_src = plane_state->src_rect;
869         const int in_w = stream->src.width;
870         const int in_h = stream->src.height;
871         const int out_w = stream->dst.width;
872         const int out_h = stream->dst.height;
873
874         /*Swap surf_src height and width since scaling ratios are in recout rotation*/
875         if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 ||
876                         pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270)
877                 swap(surf_src.height, surf_src.width);
878
879         pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_from_fraction(
880                                         surf_src.width,
881                                         plane_state->dst_rect.width);
882         pipe_ctx->plane_res.scl_data.ratios.vert = dc_fixpt_from_fraction(
883                                         surf_src.height,
884                                         plane_state->dst_rect.height);
885
886         if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE)
887                 pipe_ctx->plane_res.scl_data.ratios.horz.value *= 2;
888         else if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM)
889                 pipe_ctx->plane_res.scl_data.ratios.vert.value *= 2;
890
891         pipe_ctx->plane_res.scl_data.ratios.vert.value = div64_s64(
892                 pipe_ctx->plane_res.scl_data.ratios.vert.value * in_h, out_h);
893         pipe_ctx->plane_res.scl_data.ratios.horz.value = div64_s64(
894                 pipe_ctx->plane_res.scl_data.ratios.horz.value * in_w, out_w);
895
896         pipe_ctx->plane_res.scl_data.ratios.horz_c = pipe_ctx->plane_res.scl_data.ratios.horz;
897         pipe_ctx->plane_res.scl_data.ratios.vert_c = pipe_ctx->plane_res.scl_data.ratios.vert;
898
899         if (pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP8
900                         || pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP10) {
901                 pipe_ctx->plane_res.scl_data.ratios.horz_c.value /= 2;
902                 pipe_ctx->plane_res.scl_data.ratios.vert_c.value /= 2;
903         }
904         pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_truncate(
905                         pipe_ctx->plane_res.scl_data.ratios.horz, 19);
906         pipe_ctx->plane_res.scl_data.ratios.vert = dc_fixpt_truncate(
907                         pipe_ctx->plane_res.scl_data.ratios.vert, 19);
908         pipe_ctx->plane_res.scl_data.ratios.horz_c = dc_fixpt_truncate(
909                         pipe_ctx->plane_res.scl_data.ratios.horz_c, 19);
910         pipe_ctx->plane_res.scl_data.ratios.vert_c = dc_fixpt_truncate(
911                         pipe_ctx->plane_res.scl_data.ratios.vert_c, 19);
912 }
913
914 static inline void adjust_vp_and_init_for_seamless_clip(
915                 bool flip_scan_dir,
916                 int recout_skip,
917                 int src_size,
918                 int taps,
919                 struct fixed31_32 ratio,
920                 struct fixed31_32 *init,
921                 int *vp_offset,
922                 int *vp_size)
923 {
924         if (!flip_scan_dir) {
925                 /* Adjust for viewport end clip-off */
926                 if ((*vp_offset + *vp_size) < src_size) {
927                         int vp_clip = src_size - *vp_size - *vp_offset;
928                         int int_part = dc_fixpt_floor(dc_fixpt_sub(*init, ratio));
929
930                         int_part = int_part > 0 ? int_part : 0;
931                         *vp_size += int_part < vp_clip ? int_part : vp_clip;
932                 }
933
934                 /* Adjust for non-0 viewport offset */
935                 if (*vp_offset) {
936                         int int_part;
937
938                         *init = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_skip));
939                         int_part = dc_fixpt_floor(*init) - *vp_offset;
940                         if (int_part < taps) {
941                                 int int_adj = *vp_offset >= (taps - int_part) ?
942                                                         (taps - int_part) : *vp_offset;
943                                 *vp_offset -= int_adj;
944                                 *vp_size += int_adj;
945                                 int_part += int_adj;
946                         } else if (int_part > taps) {
947                                 *vp_offset += int_part - taps;
948                                 *vp_size -= int_part - taps;
949                                 int_part = taps;
950                         }
951                         init->value &= 0xffffffff;
952                         *init = dc_fixpt_add_int(*init, int_part);
953                 }
954         } else {
955                 /* Adjust for non-0 viewport offset */
956                 if (*vp_offset) {
957                         int int_part = dc_fixpt_floor(dc_fixpt_sub(*init, ratio));
958
959                         int_part = int_part > 0 ? int_part : 0;
960                         *vp_size += int_part < *vp_offset ? int_part : *vp_offset;
961                         *vp_offset -= int_part < *vp_offset ? int_part : *vp_offset;
962                 }
963
964                 /* Adjust for viewport end clip-off */
965                 if ((*vp_offset + *vp_size) < src_size) {
966                         int int_part;
967                         int end_offset = src_size - *vp_offset - *vp_size;
968
969                         /*
970                          * this is init if vp had no offset, keep in mind this is from the
971                          * right side of vp due to scan direction
972                          */
973                         *init = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_skip));
974                         /*
975                          * this is the difference between first pixel of viewport available to read
976                          * and init position, takning into account scan direction
977                          */
978                         int_part = dc_fixpt_floor(*init) - end_offset;
979                         if (int_part < taps) {
980                                 int int_adj = end_offset >= (taps - int_part) ?
981                                                         (taps - int_part) : end_offset;
982                                 *vp_size += int_adj;
983                                 int_part += int_adj;
984                         } else if (int_part > taps) {
985                                 *vp_size += int_part - taps;
986                                 int_part = taps;
987                         }
988                         init->value &= 0xffffffff;
989                         *init = dc_fixpt_add_int(*init, int_part);
990                 }
991         }
992 }
993
994 static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx)
995 {
996         const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
997         const struct dc_stream_state *stream = pipe_ctx->stream;
998         struct pipe_ctx *odm_pipe = pipe_ctx;
999         struct scaler_data *data = &pipe_ctx->plane_res.scl_data;
1000         struct rect src = pipe_ctx->plane_state->src_rect;
1001         int recout_skip_h, recout_skip_v, surf_size_h, surf_size_v;
1002         int vpc_div = (data->format == PIXEL_FORMAT_420BPP8
1003                         || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1;
1004         bool orthogonal_rotation, flip_vert_scan_dir, flip_horz_scan_dir;
1005         int odm_idx = 0;
1006
1007         /*
1008          * Need to calculate the scan direction for viewport to make adjustments
1009          */
1010         get_vp_scan_direction(
1011                         plane_state->rotation,
1012                         plane_state->horizontal_mirror,
1013                         &orthogonal_rotation,
1014                         &flip_vert_scan_dir,
1015                         &flip_horz_scan_dir);
1016
1017         /* Calculate src rect rotation adjusted to recout space */
1018         surf_size_h = src.x + src.width;
1019         surf_size_v = src.y + src.height;
1020         if (flip_horz_scan_dir)
1021                 src.x = 0;
1022         if (flip_vert_scan_dir)
1023                 src.y = 0;
1024         if (orthogonal_rotation) {
1025                 swap(src.x, src.y);
1026                 swap(src.width, src.height);
1027         }
1028
1029         /*modified recout_skip_h calculation due to odm having no recout offset*/
1030         while (odm_pipe->prev_odm_pipe) {
1031                 odm_idx++;
1032                 odm_pipe = odm_pipe->prev_odm_pipe;
1033         }
1034         /*odm_pipe is the leftmost pipe in the ODM group*/
1035         recout_skip_h = odm_idx * data->recout.width;
1036
1037         /* Recout matching initial vp offset = recout_offset - (stream dst offset +
1038          *                      ((surf dst offset - stream src offset) * 1/ stream scaling ratio)
1039          *                      - (surf surf_src offset * 1/ full scl ratio))
1040          */
1041         recout_skip_h += odm_pipe->plane_res.scl_data.recout.x
1042                                 - (stream->dst.x + (plane_state->dst_rect.x - stream->src.x)
1043                                         * stream->dst.width / stream->src.width -
1044                                         src.x * plane_state->dst_rect.width / src.width
1045                                         * stream->dst.width / stream->src.width);
1046
1047
1048         recout_skip_v = data->recout.y - (stream->dst.y + (plane_state->dst_rect.y - stream->src.y)
1049                                         * stream->dst.height / stream->src.height -
1050                                         src.y * plane_state->dst_rect.height / src.height
1051                                         * stream->dst.height / stream->src.height);
1052         if (orthogonal_rotation)
1053                 swap(recout_skip_h, recout_skip_v);
1054         /*
1055          * Init calculated according to formula:
1056          *      init = (scaling_ratio + number_of_taps + 1) / 2
1057          *      init_bot = init + scaling_ratio
1058          *      init_c = init + truncated_vp_c_offset(from calculate viewport)
1059          */
1060         data->inits.h = dc_fixpt_truncate(dc_fixpt_div_int(
1061                         dc_fixpt_add_int(data->ratios.horz, data->taps.h_taps + 1), 2), 19);
1062
1063         data->inits.h_c = dc_fixpt_truncate(dc_fixpt_add(data->inits.h_c, dc_fixpt_div_int(
1064                         dc_fixpt_add_int(data->ratios.horz_c, data->taps.h_taps_c + 1), 2)), 19);
1065
1066         data->inits.v = dc_fixpt_truncate(dc_fixpt_div_int(
1067                         dc_fixpt_add_int(data->ratios.vert, data->taps.v_taps + 1), 2), 19);
1068
1069         data->inits.v_c = dc_fixpt_truncate(dc_fixpt_add(data->inits.v_c, dc_fixpt_div_int(
1070                         dc_fixpt_add_int(data->ratios.vert_c, data->taps.v_taps_c + 1), 2)), 19);
1071
1072         /*
1073          * Taps, inits and scaling ratios are in recout space need to rotate
1074          * to viewport rotation before adjustment
1075          */
1076         adjust_vp_and_init_for_seamless_clip(
1077                         flip_horz_scan_dir,
1078                         recout_skip_h,
1079                         surf_size_h,
1080                         orthogonal_rotation ? data->taps.v_taps : data->taps.h_taps,
1081                         orthogonal_rotation ? data->ratios.vert : data->ratios.horz,
1082                         orthogonal_rotation ? &data->inits.v : &data->inits.h,
1083                         &data->viewport.x,
1084                         &data->viewport.width);
1085         adjust_vp_and_init_for_seamless_clip(
1086                         flip_horz_scan_dir,
1087                         recout_skip_h,
1088                         surf_size_h / vpc_div,
1089                         orthogonal_rotation ? data->taps.v_taps_c : data->taps.h_taps_c,
1090                         orthogonal_rotation ? data->ratios.vert_c : data->ratios.horz_c,
1091                         orthogonal_rotation ? &data->inits.v_c : &data->inits.h_c,
1092                         &data->viewport_c.x,
1093                         &data->viewport_c.width);
1094         adjust_vp_and_init_for_seamless_clip(
1095                         flip_vert_scan_dir,
1096                         recout_skip_v,
1097                         surf_size_v,
1098                         orthogonal_rotation ? data->taps.h_taps : data->taps.v_taps,
1099                         orthogonal_rotation ? data->ratios.horz : data->ratios.vert,
1100                         orthogonal_rotation ? &data->inits.h : &data->inits.v,
1101                         &data->viewport.y,
1102                         &data->viewport.height);
1103         adjust_vp_and_init_for_seamless_clip(
1104                         flip_vert_scan_dir,
1105                         recout_skip_v,
1106                         surf_size_v / vpc_div,
1107                         orthogonal_rotation ? data->taps.h_taps_c : data->taps.v_taps_c,
1108                         orthogonal_rotation ? data->ratios.horz_c : data->ratios.vert_c,
1109                         orthogonal_rotation ? &data->inits.h_c : &data->inits.v_c,
1110                         &data->viewport_c.y,
1111                         &data->viewport_c.height);
1112
1113         /* Interlaced inits based on final vert inits */
1114         data->inits.v_bot = dc_fixpt_add(data->inits.v, data->ratios.vert);
1115         data->inits.v_c_bot = dc_fixpt_add(data->inits.v_c, data->ratios.vert_c);
1116
1117 }
1118
1119 /*
1120  * When handling 270 rotation in mixed SLS mode, we have
1121  * stream->timing.h_border_left that is non zero.  If we are doing
1122  * pipe-splitting, this h_border_left value gets added to recout.x and when it
1123  * calls calculate_inits_and_adj_vp() and
1124  * adjust_vp_and_init_for_seamless_clip(), it can cause viewport.height for a
1125  * pipe to be incorrect.
1126  *
1127  * To fix this, instead of using stream->timing.h_border_left, we can use
1128  * stream->dst.x to represent the border instead.  So we will set h_border_left
1129  * to 0 and shift the appropriate amount in stream->dst.x.  We will then
1130  * perform all calculations in resource_build_scaling_params() based on this
1131  * and then restore the h_border_left and stream->dst.x to their original
1132  * values.
1133  *
1134  * shift_border_left_to_dst() will shift the amount of h_border_left to
1135  * stream->dst.x and set h_border_left to 0.  restore_border_left_from_dst()
1136  * will restore h_border_left and stream->dst.x back to their original values
1137  * We also need to make sure pipe_ctx->plane_res.scl_data.h_active uses the
1138  * original h_border_left value in its calculation.
1139  */
1140 int shift_border_left_to_dst(struct pipe_ctx *pipe_ctx)
1141 {
1142         int store_h_border_left = pipe_ctx->stream->timing.h_border_left;
1143
1144         if (store_h_border_left) {
1145                 pipe_ctx->stream->timing.h_border_left = 0;
1146                 pipe_ctx->stream->dst.x += store_h_border_left;
1147         }
1148         return store_h_border_left;
1149 }
1150
1151 void restore_border_left_from_dst(struct pipe_ctx *pipe_ctx,
1152                                   int store_h_border_left)
1153 {
1154         pipe_ctx->stream->dst.x -= store_h_border_left;
1155         pipe_ctx->stream->timing.h_border_left = store_h_border_left;
1156 }
1157
1158 bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
1159 {
1160         const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
1161         struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
1162         bool res = false;
1163         int store_h_border_left = shift_border_left_to_dst(pipe_ctx);
1164         DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
1165         /* Important: scaling ratio calculation requires pixel format,
1166          * lb depth calculation requires recout and taps require scaling ratios.
1167          * Inits require viewport, taps, ratios and recout of split pipe
1168          */
1169         pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface(
1170                         pipe_ctx->plane_state->format);
1171
1172         calculate_scaling_ratios(pipe_ctx);
1173
1174         calculate_viewport(pipe_ctx);
1175
1176         if (pipe_ctx->plane_res.scl_data.viewport.height < 12 ||
1177                 pipe_ctx->plane_res.scl_data.viewport.width < 12) {
1178                 if (store_h_border_left) {
1179                         restore_border_left_from_dst(pipe_ctx,
1180                                 store_h_border_left);
1181                 }
1182                 return false;
1183         }
1184
1185         calculate_recout(pipe_ctx);
1186
1187         /**
1188          * Setting line buffer pixel depth to 24bpp yields banding
1189          * on certain displays, such as the Sharp 4k
1190          */
1191         pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP;
1192         pipe_ctx->plane_res.scl_data.lb_params.alpha_en = plane_state->per_pixel_alpha;
1193
1194         pipe_ctx->plane_res.scl_data.recout.x += timing->h_border_left;
1195         pipe_ctx->plane_res.scl_data.recout.y += timing->v_border_top;
1196
1197         pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable +
1198                 store_h_border_left + timing->h_border_right;
1199         pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable +
1200                 timing->v_border_top + timing->v_border_bottom;
1201         if (pipe_ctx->next_odm_pipe || pipe_ctx->prev_odm_pipe)
1202                 pipe_ctx->plane_res.scl_data.h_active /= get_num_odm_splits(pipe_ctx) + 1;
1203
1204         /* Taps calculations */
1205         if (pipe_ctx->plane_res.xfm != NULL)
1206                 res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps(
1207                                 pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality);
1208
1209         if (pipe_ctx->plane_res.dpp != NULL)
1210                 res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps(
1211                                 pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality);
1212
1213
1214         if (!res) {
1215                 /* Try 24 bpp linebuffer */
1216                 pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP;
1217
1218                 if (pipe_ctx->plane_res.xfm != NULL)
1219                         res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps(
1220                                         pipe_ctx->plane_res.xfm,
1221                                         &pipe_ctx->plane_res.scl_data,
1222                                         &plane_state->scaling_quality);
1223
1224                 if (pipe_ctx->plane_res.dpp != NULL)
1225                         res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps(
1226                                         pipe_ctx->plane_res.dpp,
1227                                         &pipe_ctx->plane_res.scl_data,
1228                                         &plane_state->scaling_quality);
1229         }
1230
1231         if (res)
1232                 /* May need to re-check lb size after this in some obscure scenario */
1233                 calculate_inits_and_adj_vp(pipe_ctx);
1234
1235         DC_LOG_SCALER("%s pipe %d:\nViewport: height:%d width:%d x:%d y:%d  Recout: height:%d width:%d x:%d y:%d  HACTIVE:%d VACTIVE:%d\n"
1236                         "src_rect: height:%d width:%d x:%d y:%d  dst_rect: height:%d width:%d x:%d y:%d  clip_rect: height:%d width:%d x:%d y:%d\n",
1237                         __func__,
1238                         pipe_ctx->pipe_idx,
1239                         pipe_ctx->plane_res.scl_data.viewport.height,
1240                         pipe_ctx->plane_res.scl_data.viewport.width,
1241                         pipe_ctx->plane_res.scl_data.viewport.x,
1242                         pipe_ctx->plane_res.scl_data.viewport.y,
1243                         pipe_ctx->plane_res.scl_data.recout.height,
1244                         pipe_ctx->plane_res.scl_data.recout.width,
1245                         pipe_ctx->plane_res.scl_data.recout.x,
1246                         pipe_ctx->plane_res.scl_data.recout.y,
1247                         pipe_ctx->plane_res.scl_data.h_active,
1248                         pipe_ctx->plane_res.scl_data.v_active,
1249                         plane_state->src_rect.height,
1250                         plane_state->src_rect.width,
1251                         plane_state->src_rect.x,
1252                         plane_state->src_rect.y,
1253                         plane_state->dst_rect.height,
1254                         plane_state->dst_rect.width,
1255                         plane_state->dst_rect.x,
1256                         plane_state->dst_rect.y,
1257                         plane_state->clip_rect.height,
1258                         plane_state->clip_rect.width,
1259                         plane_state->clip_rect.x,
1260                         plane_state->clip_rect.y);
1261
1262         if (store_h_border_left)
1263                 restore_border_left_from_dst(pipe_ctx, store_h_border_left);
1264
1265         return res;
1266 }
1267
1268
1269 enum dc_status resource_build_scaling_params_for_context(
1270         const struct dc  *dc,
1271         struct dc_state *context)
1272 {
1273         int i;
1274
1275         for (i = 0; i < MAX_PIPES; i++) {
1276                 if (context->res_ctx.pipe_ctx[i].plane_state != NULL &&
1277                                 context->res_ctx.pipe_ctx[i].stream != NULL)
1278                         if (!resource_build_scaling_params(&context->res_ctx.pipe_ctx[i]))
1279                                 return DC_FAIL_SCALING;
1280         }
1281
1282         return DC_OK;
1283 }
1284
1285 struct pipe_ctx *find_idle_secondary_pipe(
1286                 struct resource_context *res_ctx,
1287                 const struct resource_pool *pool,
1288                 const struct pipe_ctx *primary_pipe)
1289 {
1290         int i;
1291         struct pipe_ctx *secondary_pipe = NULL;
1292
1293         /*
1294          * We add a preferred pipe mapping to avoid the chance that
1295          * MPCCs already in use will need to be reassigned to other trees.
1296          * For example, if we went with the strict, assign backwards logic:
1297          *
1298          * (State 1)
1299          * Display A on, no surface, top pipe = 0
1300          * Display B on, no surface, top pipe = 1
1301          *
1302          * (State 2)
1303          * Display A on, no surface, top pipe = 0
1304          * Display B on, surface enable, top pipe = 1, bottom pipe = 5
1305          *
1306          * (State 3)
1307          * Display A on, surface enable, top pipe = 0, bottom pipe = 5
1308          * Display B on, surface enable, top pipe = 1, bottom pipe = 4
1309          *
1310          * The state 2->3 transition requires remapping MPCC 5 from display B
1311          * to display A.
1312          *
1313          * However, with the preferred pipe logic, state 2 would look like:
1314          *
1315          * (State 2)
1316          * Display A on, no surface, top pipe = 0
1317          * Display B on, surface enable, top pipe = 1, bottom pipe = 4
1318          *
1319          * This would then cause 2->3 to not require remapping any MPCCs.
1320          */
1321         if (primary_pipe) {
1322                 int preferred_pipe_idx = (pool->pipe_count - 1) - primary_pipe->pipe_idx;
1323                 if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) {
1324                         secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx];
1325                         secondary_pipe->pipe_idx = preferred_pipe_idx;
1326                 }
1327         }
1328
1329         /*
1330          * search backwards for the second pipe to keep pipe
1331          * assignment more consistent
1332          */
1333         if (!secondary_pipe)
1334                 for (i = pool->pipe_count - 1; i >= 0; i--) {
1335                         if (res_ctx->pipe_ctx[i].stream == NULL) {
1336                                 secondary_pipe = &res_ctx->pipe_ctx[i];
1337                                 secondary_pipe->pipe_idx = i;
1338                                 break;
1339                         }
1340                 }
1341
1342         return secondary_pipe;
1343 }
1344
1345 struct pipe_ctx *resource_get_head_pipe_for_stream(
1346                 struct resource_context *res_ctx,
1347                 struct dc_stream_state *stream)
1348 {
1349         int i;
1350
1351         for (i = 0; i < MAX_PIPES; i++) {
1352                 if (res_ctx->pipe_ctx[i].stream == stream
1353                                 && !res_ctx->pipe_ctx[i].top_pipe
1354                                 && !res_ctx->pipe_ctx[i].prev_odm_pipe)
1355                         return &res_ctx->pipe_ctx[i];
1356         }
1357         return NULL;
1358 }
1359
1360 static struct pipe_ctx *resource_get_tail_pipe(
1361                 struct resource_context *res_ctx,
1362                 struct pipe_ctx *head_pipe)
1363 {
1364         struct pipe_ctx *tail_pipe;
1365
1366         tail_pipe = head_pipe->bottom_pipe;
1367
1368         while (tail_pipe) {
1369                 head_pipe = tail_pipe;
1370                 tail_pipe = tail_pipe->bottom_pipe;
1371         }
1372
1373         return head_pipe;
1374 }
1375
1376 /*
1377  * A free_pipe for a stream is defined here as a pipe
1378  * that has no surface attached yet
1379  */
1380 static struct pipe_ctx *acquire_free_pipe_for_head(
1381                 struct dc_state *context,
1382                 const struct resource_pool *pool,
1383                 struct pipe_ctx *head_pipe)
1384 {
1385         int i;
1386         struct resource_context *res_ctx = &context->res_ctx;
1387
1388         if (!head_pipe->plane_state)
1389                 return head_pipe;
1390
1391         /* Re-use pipe already acquired for this stream if available*/
1392         for (i = pool->pipe_count - 1; i >= 0; i--) {
1393                 if (res_ctx->pipe_ctx[i].stream == head_pipe->stream &&
1394                                 !res_ctx->pipe_ctx[i].plane_state) {
1395                         return &res_ctx->pipe_ctx[i];
1396                 }
1397         }
1398
1399         /*
1400          * At this point we have no re-useable pipe for this stream and we need
1401          * to acquire an idle one to satisfy the request
1402          */
1403
1404         if (!pool->funcs->acquire_idle_pipe_for_layer)
1405                 return NULL;
1406
1407         return pool->funcs->acquire_idle_pipe_for_layer(context, pool, head_pipe->stream);
1408 }
1409
1410 #if defined(CONFIG_DRM_AMD_DC_DCN)
1411 static int acquire_first_split_pipe(
1412                 struct resource_context *res_ctx,
1413                 const struct resource_pool *pool,
1414                 struct dc_stream_state *stream)
1415 {
1416         int i;
1417
1418         for (i = 0; i < pool->pipe_count; i++) {
1419                 struct pipe_ctx *split_pipe = &res_ctx->pipe_ctx[i];
1420
1421                 if (split_pipe->top_pipe &&
1422                                 split_pipe->top_pipe->plane_state == split_pipe->plane_state) {
1423                         split_pipe->top_pipe->bottom_pipe = split_pipe->bottom_pipe;
1424                         if (split_pipe->bottom_pipe)
1425                                 split_pipe->bottom_pipe->top_pipe = split_pipe->top_pipe;
1426
1427                         if (split_pipe->top_pipe->plane_state)
1428                                 resource_build_scaling_params(split_pipe->top_pipe);
1429
1430                         memset(split_pipe, 0, sizeof(*split_pipe));
1431                         split_pipe->stream_res.tg = pool->timing_generators[i];
1432                         split_pipe->plane_res.hubp = pool->hubps[i];
1433                         split_pipe->plane_res.ipp = pool->ipps[i];
1434                         split_pipe->plane_res.dpp = pool->dpps[i];
1435                         split_pipe->stream_res.opp = pool->opps[i];
1436                         split_pipe->plane_res.mpcc_inst = pool->dpps[i]->inst;
1437                         split_pipe->pipe_idx = i;
1438
1439                         split_pipe->stream = stream;
1440                         return i;
1441                 }
1442         }
1443         return -1;
1444 }
1445 #endif
1446
1447 bool dc_add_plane_to_context(
1448                 const struct dc *dc,
1449                 struct dc_stream_state *stream,
1450                 struct dc_plane_state *plane_state,
1451                 struct dc_state *context)
1452 {
1453         int i;
1454         struct resource_pool *pool = dc->res_pool;
1455         struct pipe_ctx *head_pipe, *tail_pipe, *free_pipe;
1456         struct dc_stream_status *stream_status = NULL;
1457
1458         for (i = 0; i < context->stream_count; i++)
1459                 if (context->streams[i] == stream) {
1460                         stream_status = &context->stream_status[i];
1461                         break;
1462                 }
1463         if (stream_status == NULL) {
1464                 dm_error("Existing stream not found; failed to attach surface!\n");
1465                 return false;
1466         }
1467
1468
1469         if (stream_status->plane_count == MAX_SURFACE_NUM) {
1470                 dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n",
1471                                 plane_state, MAX_SURFACE_NUM);
1472                 return false;
1473         }
1474
1475         head_pipe = resource_get_head_pipe_for_stream(&context->res_ctx, stream);
1476
1477         if (!head_pipe) {
1478                 dm_error("Head pipe not found for stream_state %p !\n", stream);
1479                 return false;
1480         }
1481
1482         /* retain new surface, but only once per stream */
1483         dc_plane_state_retain(plane_state);
1484
1485         while (head_pipe) {
1486                 free_pipe = acquire_free_pipe_for_head(context, pool, head_pipe);
1487
1488         #if defined(CONFIG_DRM_AMD_DC_DCN)
1489                 if (!free_pipe) {
1490                         int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream);
1491                         if (pipe_idx >= 0)
1492                                 free_pipe = &context->res_ctx.pipe_ctx[pipe_idx];
1493                 }
1494         #endif
1495                 if (!free_pipe) {
1496                         dc_plane_state_release(plane_state);
1497                         return false;
1498                 }
1499
1500                 free_pipe->plane_state = plane_state;
1501
1502                 if (head_pipe != free_pipe) {
1503                         tail_pipe = resource_get_tail_pipe(&context->res_ctx, head_pipe);
1504                         ASSERT(tail_pipe);
1505                         free_pipe->stream_res.tg = tail_pipe->stream_res.tg;
1506                         free_pipe->stream_res.abm = tail_pipe->stream_res.abm;
1507                         free_pipe->stream_res.opp = tail_pipe->stream_res.opp;
1508                         free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc;
1509                         free_pipe->stream_res.audio = tail_pipe->stream_res.audio;
1510                         free_pipe->clock_source = tail_pipe->clock_source;
1511                         free_pipe->top_pipe = tail_pipe;
1512                         tail_pipe->bottom_pipe = free_pipe;
1513                         if (!free_pipe->next_odm_pipe && tail_pipe->next_odm_pipe && tail_pipe->next_odm_pipe->bottom_pipe) {
1514                                 free_pipe->next_odm_pipe = tail_pipe->next_odm_pipe->bottom_pipe;
1515                                 tail_pipe->next_odm_pipe->bottom_pipe->prev_odm_pipe = free_pipe;
1516                         }
1517                         if (!free_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe->bottom_pipe) {
1518                                 free_pipe->prev_odm_pipe = tail_pipe->prev_odm_pipe->bottom_pipe;
1519                                 tail_pipe->prev_odm_pipe->bottom_pipe->next_odm_pipe = free_pipe;
1520                         }
1521                 }
1522                 head_pipe = head_pipe->next_odm_pipe;
1523         }
1524         /* assign new surfaces*/
1525         stream_status->plane_states[stream_status->plane_count] = plane_state;
1526
1527         stream_status->plane_count++;
1528
1529         return true;
1530 }
1531
1532 bool dc_remove_plane_from_context(
1533                 const struct dc *dc,
1534                 struct dc_stream_state *stream,
1535                 struct dc_plane_state *plane_state,
1536                 struct dc_state *context)
1537 {
1538         int i;
1539         struct dc_stream_status *stream_status = NULL;
1540         struct resource_pool *pool = dc->res_pool;
1541
1542         for (i = 0; i < context->stream_count; i++)
1543                 if (context->streams[i] == stream) {
1544                         stream_status = &context->stream_status[i];
1545                         break;
1546                 }
1547
1548         if (stream_status == NULL) {
1549                 dm_error("Existing stream not found; failed to remove plane.\n");
1550                 return false;
1551         }
1552
1553         /* release pipe for plane*/
1554         for (i = pool->pipe_count - 1; i >= 0; i--) {
1555                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1556
1557                 if (pipe_ctx->plane_state == plane_state) {
1558                         if (pipe_ctx->top_pipe)
1559                                 pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe;
1560
1561                         /* Second condition is to avoid setting NULL to top pipe
1562                          * of tail pipe making it look like head pipe in subsequent
1563                          * deletes
1564                          */
1565                         if (pipe_ctx->bottom_pipe && pipe_ctx->top_pipe)
1566                                 pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe;
1567
1568                         /*
1569                          * For head pipe detach surfaces from pipe for tail
1570                          * pipe just zero it out
1571                          */
1572                         if (!pipe_ctx->top_pipe)
1573                                 pipe_ctx->plane_state = NULL;
1574                         else
1575                                 memset(pipe_ctx, 0, sizeof(*pipe_ctx));
1576                 }
1577         }
1578
1579
1580         for (i = 0; i < stream_status->plane_count; i++) {
1581                 if (stream_status->plane_states[i] == plane_state) {
1582
1583                         dc_plane_state_release(stream_status->plane_states[i]);
1584                         break;
1585                 }
1586         }
1587
1588         if (i == stream_status->plane_count) {
1589                 dm_error("Existing plane_state not found; failed to detach it!\n");
1590                 return false;
1591         }
1592
1593         stream_status->plane_count--;
1594
1595         /* Start at the plane we've just released, and move all the planes one index forward to "trim" the array */
1596         for (; i < stream_status->plane_count; i++)
1597                 stream_status->plane_states[i] = stream_status->plane_states[i + 1];
1598
1599         stream_status->plane_states[stream_status->plane_count] = NULL;
1600
1601         return true;
1602 }
1603
1604 bool dc_rem_all_planes_for_stream(
1605                 const struct dc *dc,
1606                 struct dc_stream_state *stream,
1607                 struct dc_state *context)
1608 {
1609         int i, old_plane_count;
1610         struct dc_stream_status *stream_status = NULL;
1611         struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 };
1612
1613         for (i = 0; i < context->stream_count; i++)
1614                         if (context->streams[i] == stream) {
1615                                 stream_status = &context->stream_status[i];
1616                                 break;
1617                         }
1618
1619         if (stream_status == NULL) {
1620                 dm_error("Existing stream %p not found!\n", stream);
1621                 return false;
1622         }
1623
1624         old_plane_count = stream_status->plane_count;
1625
1626         for (i = 0; i < old_plane_count; i++)
1627                 del_planes[i] = stream_status->plane_states[i];
1628
1629         for (i = 0; i < old_plane_count; i++)
1630                 if (!dc_remove_plane_from_context(dc, stream, del_planes[i], context))
1631                         return false;
1632
1633         return true;
1634 }
1635
1636 static bool add_all_planes_for_stream(
1637                 const struct dc *dc,
1638                 struct dc_stream_state *stream,
1639                 const struct dc_validation_set set[],
1640                 int set_count,
1641                 struct dc_state *context)
1642 {
1643         int i, j;
1644
1645         for (i = 0; i < set_count; i++)
1646                 if (set[i].stream == stream)
1647                         break;
1648
1649         if (i == set_count) {
1650                 dm_error("Stream %p not found in set!\n", stream);
1651                 return false;
1652         }
1653
1654         for (j = 0; j < set[i].plane_count; j++)
1655                 if (!dc_add_plane_to_context(dc, stream, set[i].plane_states[j], context))
1656                         return false;
1657
1658         return true;
1659 }
1660
1661 bool dc_add_all_planes_for_stream(
1662                 const struct dc *dc,
1663                 struct dc_stream_state *stream,
1664                 struct dc_plane_state * const *plane_states,
1665                 int plane_count,
1666                 struct dc_state *context)
1667 {
1668         struct dc_validation_set set;
1669         int i;
1670
1671         set.stream = stream;
1672         set.plane_count = plane_count;
1673
1674         for (i = 0; i < plane_count; i++)
1675                 set.plane_states[i] = plane_states[i];
1676
1677         return add_all_planes_for_stream(dc, stream, &set, 1, context);
1678 }
1679
1680 static bool is_timing_changed(struct dc_stream_state *cur_stream,
1681                 struct dc_stream_state *new_stream)
1682 {
1683         if (cur_stream == NULL)
1684                 return true;
1685
1686         /* If sink pointer changed, it means this is a hotplug, we should do
1687          * full hw setting.
1688          */
1689         if (cur_stream->sink != new_stream->sink)
1690                 return true;
1691
1692         /* If output color space is changed, need to reprogram info frames */
1693         if (cur_stream->output_color_space != new_stream->output_color_space)
1694                 return true;
1695
1696         return memcmp(
1697                 &cur_stream->timing,
1698                 &new_stream->timing,
1699                 sizeof(struct dc_crtc_timing)) != 0;
1700 }
1701
1702 static bool are_stream_backends_same(
1703         struct dc_stream_state *stream_a, struct dc_stream_state *stream_b)
1704 {
1705         if (stream_a == stream_b)
1706                 return true;
1707
1708         if (stream_a == NULL || stream_b == NULL)
1709                 return false;
1710
1711         if (is_timing_changed(stream_a, stream_b))
1712                 return false;
1713
1714         if (stream_a->dpms_off != stream_b->dpms_off)
1715                 return false;
1716
1717         return true;
1718 }
1719
1720 /**
1721  * dc_is_stream_unchanged() - Compare two stream states for equivalence.
1722  *
1723  * Checks if there a difference between the two states
1724  * that would require a mode change.
1725  *
1726  * Does not compare cursor position or attributes.
1727  */
1728 bool dc_is_stream_unchanged(
1729         struct dc_stream_state *old_stream, struct dc_stream_state *stream)
1730 {
1731
1732         if (!are_stream_backends_same(old_stream, stream))
1733                 return false;
1734
1735         if (old_stream->ignore_msa_timing_param != stream->ignore_msa_timing_param)
1736                 return false;
1737
1738         return true;
1739 }
1740
1741 /**
1742  * dc_is_stream_scaling_unchanged() - Compare scaling rectangles of two streams.
1743  */
1744 bool dc_is_stream_scaling_unchanged(
1745         struct dc_stream_state *old_stream, struct dc_stream_state *stream)
1746 {
1747         if (old_stream == stream)
1748                 return true;
1749
1750         if (old_stream == NULL || stream == NULL)
1751                 return false;
1752
1753         if (memcmp(&old_stream->src,
1754                         &stream->src,
1755                         sizeof(struct rect)) != 0)
1756                 return false;
1757
1758         if (memcmp(&old_stream->dst,
1759                         &stream->dst,
1760                         sizeof(struct rect)) != 0)
1761                 return false;
1762
1763         return true;
1764 }
1765
1766 static void update_stream_engine_usage(
1767                 struct resource_context *res_ctx,
1768                 const struct resource_pool *pool,
1769                 struct stream_encoder *stream_enc,
1770                 bool acquired)
1771 {
1772         int i;
1773
1774         for (i = 0; i < pool->stream_enc_count; i++) {
1775                 if (pool->stream_enc[i] == stream_enc)
1776                         res_ctx->is_stream_enc_acquired[i] = acquired;
1777         }
1778 }
1779
1780 /* TODO: release audio object */
1781 void update_audio_usage(
1782                 struct resource_context *res_ctx,
1783                 const struct resource_pool *pool,
1784                 struct audio *audio,
1785                 bool acquired)
1786 {
1787         int i;
1788         for (i = 0; i < pool->audio_count; i++) {
1789                 if (pool->audios[i] == audio)
1790                         res_ctx->is_audio_acquired[i] = acquired;
1791         }
1792 }
1793
1794 static int acquire_first_free_pipe(
1795                 struct resource_context *res_ctx,
1796                 const struct resource_pool *pool,
1797                 struct dc_stream_state *stream)
1798 {
1799         int i;
1800
1801         for (i = 0; i < pool->pipe_count; i++) {
1802                 if (!res_ctx->pipe_ctx[i].stream) {
1803                         struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
1804
1805                         pipe_ctx->stream_res.tg = pool->timing_generators[i];
1806                         pipe_ctx->plane_res.mi = pool->mis[i];
1807                         pipe_ctx->plane_res.hubp = pool->hubps[i];
1808                         pipe_ctx->plane_res.ipp = pool->ipps[i];
1809                         pipe_ctx->plane_res.xfm = pool->transforms[i];
1810                         pipe_ctx->plane_res.dpp = pool->dpps[i];
1811                         pipe_ctx->stream_res.opp = pool->opps[i];
1812                         if (pool->dpps[i])
1813                                 pipe_ctx->plane_res.mpcc_inst = pool->dpps[i]->inst;
1814                         pipe_ctx->pipe_idx = i;
1815
1816
1817                         pipe_ctx->stream = stream;
1818                         return i;
1819                 }
1820         }
1821         return -1;
1822 }
1823
1824 static struct audio *find_first_free_audio(
1825                 struct resource_context *res_ctx,
1826                 const struct resource_pool *pool,
1827                 enum engine_id id,
1828                 enum dce_version dc_version)
1829 {
1830         int i, available_audio_count;
1831
1832         available_audio_count = pool->audio_count;
1833
1834         for (i = 0; i < available_audio_count; i++) {
1835                 if ((res_ctx->is_audio_acquired[i] == false) && (res_ctx->is_stream_enc_acquired[i] == true)) {
1836                         /*we have enough audio endpoint, find the matching inst*/
1837                         if (id != i)
1838                                 continue;
1839                         return pool->audios[i];
1840                 }
1841         }
1842
1843         /* use engine id to find free audio */
1844         if ((id < available_audio_count) && (res_ctx->is_audio_acquired[id] == false)) {
1845                 return pool->audios[id];
1846         }
1847         /*not found the matching one, first come first serve*/
1848         for (i = 0; i < available_audio_count; i++) {
1849                 if (res_ctx->is_audio_acquired[i] == false) {
1850                         return pool->audios[i];
1851                 }
1852         }
1853         return 0;
1854 }
1855
1856 /**
1857  * dc_add_stream_to_ctx() - Add a new dc_stream_state to a dc_state.
1858  */
1859 enum dc_status dc_add_stream_to_ctx(
1860                 struct dc *dc,
1861                 struct dc_state *new_ctx,
1862                 struct dc_stream_state *stream)
1863 {
1864         enum dc_status res;
1865         DC_LOGGER_INIT(dc->ctx->logger);
1866
1867         if (new_ctx->stream_count >= dc->res_pool->timing_generator_count) {
1868                 DC_LOG_WARNING("Max streams reached, can't add stream %p !\n", stream);
1869                 return DC_ERROR_UNEXPECTED;
1870         }
1871
1872         new_ctx->streams[new_ctx->stream_count] = stream;
1873         dc_stream_retain(stream);
1874         new_ctx->stream_count++;
1875
1876         res = dc->res_pool->funcs->add_stream_to_ctx(dc, new_ctx, stream);
1877         if (res != DC_OK)
1878                 DC_LOG_WARNING("Adding stream %p to context failed with err %d!\n", stream, res);
1879
1880         return res;
1881 }
1882
1883 /**
1884  * dc_remove_stream_from_ctx() - Remove a stream from a dc_state.
1885  */
1886 enum dc_status dc_remove_stream_from_ctx(
1887                         struct dc *dc,
1888                         struct dc_state *new_ctx,
1889                         struct dc_stream_state *stream)
1890 {
1891         int i;
1892         struct dc_context *dc_ctx = dc->ctx;
1893         struct pipe_ctx *del_pipe = resource_get_head_pipe_for_stream(&new_ctx->res_ctx, stream);
1894         struct pipe_ctx *odm_pipe;
1895
1896         if (!del_pipe) {
1897                 DC_ERROR("Pipe not found for stream %p !\n", stream);
1898                 return DC_ERROR_UNEXPECTED;
1899         }
1900
1901         odm_pipe = del_pipe->next_odm_pipe;
1902
1903         /* Release primary pipe */
1904         ASSERT(del_pipe->stream_res.stream_enc);
1905         update_stream_engine_usage(
1906                         &new_ctx->res_ctx,
1907                                 dc->res_pool,
1908                         del_pipe->stream_res.stream_enc,
1909                         false);
1910
1911         if (del_pipe->stream_res.audio)
1912                 update_audio_usage(
1913                         &new_ctx->res_ctx,
1914                         dc->res_pool,
1915                         del_pipe->stream_res.audio,
1916                         false);
1917
1918         resource_unreference_clock_source(&new_ctx->res_ctx,
1919                                           dc->res_pool,
1920                                           del_pipe->clock_source);
1921
1922         if (dc->res_pool->funcs->remove_stream_from_ctx)
1923                 dc->res_pool->funcs->remove_stream_from_ctx(dc, new_ctx, stream);
1924
1925         while (odm_pipe) {
1926                 struct pipe_ctx *next_odm_pipe = odm_pipe->next_odm_pipe;
1927
1928                 memset(odm_pipe, 0, sizeof(*odm_pipe));
1929                 odm_pipe = next_odm_pipe;
1930         }
1931         memset(del_pipe, 0, sizeof(*del_pipe));
1932
1933         for (i = 0; i < new_ctx->stream_count; i++)
1934                 if (new_ctx->streams[i] == stream)
1935                         break;
1936
1937         if (new_ctx->streams[i] != stream) {
1938                 DC_ERROR("Context doesn't have stream %p !\n", stream);
1939                 return DC_ERROR_UNEXPECTED;
1940         }
1941
1942         dc_stream_release(new_ctx->streams[i]);
1943         new_ctx->stream_count--;
1944
1945         /* Trim back arrays */
1946         for (; i < new_ctx->stream_count; i++) {
1947                 new_ctx->streams[i] = new_ctx->streams[i + 1];
1948                 new_ctx->stream_status[i] = new_ctx->stream_status[i + 1];
1949         }
1950
1951         new_ctx->streams[new_ctx->stream_count] = NULL;
1952         memset(
1953                         &new_ctx->stream_status[new_ctx->stream_count],
1954                         0,
1955                         sizeof(new_ctx->stream_status[0]));
1956
1957         return DC_OK;
1958 }
1959
1960 static struct dc_stream_state *find_pll_sharable_stream(
1961                 struct dc_stream_state *stream_needs_pll,
1962                 struct dc_state *context)
1963 {
1964         int i;
1965
1966         for (i = 0; i < context->stream_count; i++) {
1967                 struct dc_stream_state *stream_has_pll = context->streams[i];
1968
1969                 /* We are looking for non dp, non virtual stream */
1970                 if (resource_are_streams_timing_synchronizable(
1971                         stream_needs_pll, stream_has_pll)
1972                         && !dc_is_dp_signal(stream_has_pll->signal)
1973                         && stream_has_pll->link->connector_signal
1974                         != SIGNAL_TYPE_VIRTUAL)
1975                         return stream_has_pll;
1976
1977         }
1978
1979         return NULL;
1980 }
1981
1982 static int get_norm_pix_clk(const struct dc_crtc_timing *timing)
1983 {
1984         uint32_t pix_clk = timing->pix_clk_100hz;
1985         uint32_t normalized_pix_clk = pix_clk;
1986
1987         if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
1988                 pix_clk /= 2;
1989         if (timing->pixel_encoding != PIXEL_ENCODING_YCBCR422) {
1990                 switch (timing->display_color_depth) {
1991                 case COLOR_DEPTH_666:
1992                 case COLOR_DEPTH_888:
1993                         normalized_pix_clk = pix_clk;
1994                         break;
1995                 case COLOR_DEPTH_101010:
1996                         normalized_pix_clk = (pix_clk * 30) / 24;
1997                         break;
1998                 case COLOR_DEPTH_121212:
1999                         normalized_pix_clk = (pix_clk * 36) / 24;
2000                 break;
2001                 case COLOR_DEPTH_161616:
2002                         normalized_pix_clk = (pix_clk * 48) / 24;
2003                 break;
2004                 default:
2005                         ASSERT(0);
2006                 break;
2007                 }
2008         }
2009         return normalized_pix_clk;
2010 }
2011
2012 static void calculate_phy_pix_clks(struct dc_stream_state *stream)
2013 {
2014         /* update actual pixel clock on all streams */
2015         if (dc_is_hdmi_signal(stream->signal))
2016                 stream->phy_pix_clk = get_norm_pix_clk(
2017                         &stream->timing) / 10;
2018         else
2019                 stream->phy_pix_clk =
2020                         stream->timing.pix_clk_100hz / 10;
2021
2022         if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
2023                 stream->phy_pix_clk *= 2;
2024 }
2025
2026 static int acquire_resource_from_hw_enabled_state(
2027                 struct resource_context *res_ctx,
2028                 const struct resource_pool *pool,
2029                 struct dc_stream_state *stream)
2030 {
2031         struct dc_link *link = stream->link;
2032         unsigned int i, inst, tg_inst = 0;
2033
2034         /* Check for enabled DIG to identify enabled display */
2035         if (!link->link_enc->funcs->is_dig_enabled(link->link_enc))
2036                 return -1;
2037
2038         inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);
2039
2040         if (inst == ENGINE_ID_UNKNOWN)
2041                 return -1;
2042
2043         for (i = 0; i < pool->stream_enc_count; i++) {
2044                 if (pool->stream_enc[i]->id == inst) {
2045                         tg_inst = pool->stream_enc[i]->funcs->dig_source_otg(
2046                                 pool->stream_enc[i]);
2047                         break;
2048                 }
2049         }
2050
2051         // tg_inst not found
2052         if (i == pool->stream_enc_count)
2053                 return -1;
2054
2055         if (tg_inst >= pool->timing_generator_count)
2056                 return -1;
2057
2058         if (!res_ctx->pipe_ctx[tg_inst].stream) {
2059                 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[tg_inst];
2060
2061                 pipe_ctx->stream_res.tg = pool->timing_generators[tg_inst];
2062                 pipe_ctx->plane_res.mi = pool->mis[tg_inst];
2063                 pipe_ctx->plane_res.hubp = pool->hubps[tg_inst];
2064                 pipe_ctx->plane_res.ipp = pool->ipps[tg_inst];
2065                 pipe_ctx->plane_res.xfm = pool->transforms[tg_inst];
2066                 pipe_ctx->plane_res.dpp = pool->dpps[tg_inst];
2067                 pipe_ctx->stream_res.opp = pool->opps[tg_inst];
2068
2069                 if (pool->dpps[tg_inst]) {
2070                         pipe_ctx->plane_res.mpcc_inst = pool->dpps[tg_inst]->inst;
2071
2072                         // Read DPP->MPCC->OPP Pipe from HW State
2073                         if (pool->mpc->funcs->read_mpcc_state) {
2074                                 struct mpcc_state s = {0};
2075
2076                                 pool->mpc->funcs->read_mpcc_state(pool->mpc, pipe_ctx->plane_res.mpcc_inst, &s);
2077
2078                                 if (s.dpp_id < MAX_MPCC)
2079                                         pool->mpc->mpcc_array[pipe_ctx->plane_res.mpcc_inst].dpp_id = s.dpp_id;
2080
2081                                 if (s.bot_mpcc_id < MAX_MPCC)
2082                                         pool->mpc->mpcc_array[pipe_ctx->plane_res.mpcc_inst].mpcc_bot =
2083                                                         &pool->mpc->mpcc_array[s.bot_mpcc_id];
2084
2085                                 if (s.opp_id < MAX_OPP)
2086                                         pipe_ctx->stream_res.opp->mpc_tree_params.opp_id = s.opp_id;
2087                         }
2088                 }
2089                 pipe_ctx->pipe_idx = tg_inst;
2090
2091                 pipe_ctx->stream = stream;
2092                 return tg_inst;
2093         }
2094
2095         return -1;
2096 }
2097
2098 enum dc_status resource_map_pool_resources(
2099                 const struct dc  *dc,
2100                 struct dc_state *context,
2101                 struct dc_stream_state *stream)
2102 {
2103         const struct resource_pool *pool = dc->res_pool;
2104         int i;
2105         struct dc_context *dc_ctx = dc->ctx;
2106         struct pipe_ctx *pipe_ctx = NULL;
2107         int pipe_idx = -1;
2108         struct dc_bios *dcb = dc->ctx->dc_bios;
2109
2110         calculate_phy_pix_clks(stream);
2111
2112         /* TODO: Check Linux */
2113         if (dc->config.allow_seamless_boot_optimization &&
2114                         !dcb->funcs->is_accelerated_mode(dcb)) {
2115                 if (dc_validate_seamless_boot_timing(dc, stream->sink, &stream->timing))
2116                         stream->apply_seamless_boot_optimization = true;
2117         }
2118
2119         if (stream->apply_seamless_boot_optimization)
2120                 pipe_idx = acquire_resource_from_hw_enabled_state(
2121                                 &context->res_ctx,
2122                                 pool,
2123                                 stream);
2124
2125         if (pipe_idx < 0)
2126                 /* acquire new resources */
2127                 pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream);
2128
2129 #ifdef CONFIG_DRM_AMD_DC_DCN
2130         if (pipe_idx < 0)
2131                 pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream);
2132 #endif
2133
2134         if (pipe_idx < 0 || context->res_ctx.pipe_ctx[pipe_idx].stream_res.tg == NULL)
2135                 return DC_NO_CONTROLLER_RESOURCE;
2136
2137         pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx];
2138
2139         pipe_ctx->stream_res.stream_enc =
2140                 dc->res_pool->funcs->find_first_free_match_stream_enc_for_link(
2141                         &context->res_ctx, pool, stream);
2142
2143         if (!pipe_ctx->stream_res.stream_enc)
2144                 return DC_NO_STREAM_ENC_RESOURCE;
2145
2146         update_stream_engine_usage(
2147                 &context->res_ctx, pool,
2148                 pipe_ctx->stream_res.stream_enc,
2149                 true);
2150
2151         /* TODO: Add check if ASIC support and EDID audio */
2152         if (!stream->converter_disable_audio &&
2153             dc_is_audio_capable_signal(pipe_ctx->stream->signal) &&
2154             stream->audio_info.mode_count && stream->audio_info.flags.all) {
2155                 pipe_ctx->stream_res.audio = find_first_free_audio(
2156                 &context->res_ctx, pool, pipe_ctx->stream_res.stream_enc->id, dc_ctx->dce_version);
2157
2158                 /*
2159                  * Audio assigned in order first come first get.
2160                  * There are asics which has number of audio
2161                  * resources less then number of pipes
2162                  */
2163                 if (pipe_ctx->stream_res.audio)
2164                         update_audio_usage(&context->res_ctx, pool,
2165                                            pipe_ctx->stream_res.audio, true);
2166         }
2167
2168         /* Add ABM to the resource if on EDP */
2169         if (pipe_ctx->stream && dc_is_embedded_signal(pipe_ctx->stream->signal)) {
2170 #if defined(CONFIG_DRM_AMD_DC_DCN3_0)
2171                 if (pool->abm)
2172                         pipe_ctx->stream_res.abm = pool->abm;
2173                 else
2174                         pipe_ctx->stream_res.abm = pool->multiple_abms[pipe_ctx->stream_res.tg->inst];
2175 #else
2176                 pipe_ctx->stream_res.abm = pool->abm;
2177 #endif
2178         }
2179
2180         for (i = 0; i < context->stream_count; i++)
2181                 if (context->streams[i] == stream) {
2182                         context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst;
2183                         context->stream_status[i].stream_enc_inst = pipe_ctx->stream_res.stream_enc->stream_enc_inst;
2184                         context->stream_status[i].audio_inst =
2185                                 pipe_ctx->stream_res.audio ? pipe_ctx->stream_res.audio->inst : -1;
2186
2187                         return DC_OK;
2188                 }
2189
2190         DC_ERROR("Stream %p not found in new ctx!\n", stream);
2191         return DC_ERROR_UNEXPECTED;
2192 }
2193
2194 /**
2195  * dc_resource_state_copy_construct_current() - Creates a new dc_state from existing state
2196  * Is a shallow copy.  Increments refcounts on existing streams and planes.
2197  * @dc: copy out of dc->current_state
2198  * @dst_ctx: copy into this
2199  */
2200 void dc_resource_state_copy_construct_current(
2201                 const struct dc *dc,
2202                 struct dc_state *dst_ctx)
2203 {
2204         dc_resource_state_copy_construct(dc->current_state, dst_ctx);
2205 }
2206
2207
2208 void dc_resource_state_construct(
2209                 const struct dc *dc,
2210                 struct dc_state *dst_ctx)
2211 {
2212         dst_ctx->clk_mgr = dc->clk_mgr;
2213 }
2214
2215
2216 bool dc_resource_is_dsc_encoding_supported(const struct dc *dc)
2217 {
2218         return dc->res_pool->res_cap->num_dsc > 0;
2219 }
2220
2221
2222 /**
2223  * dc_validate_global_state() - Determine if HW can support a given state
2224  * Checks HW resource availability and bandwidth requirement.
2225  * @dc: dc struct for this driver
2226  * @new_ctx: state to be validated
2227  * @fast_validate: set to true if only yes/no to support matters
2228  *
2229  * Return: DC_OK if the result can be programmed.  Otherwise, an error code.
2230  */
2231 enum dc_status dc_validate_global_state(
2232                 struct dc *dc,
2233                 struct dc_state *new_ctx,
2234                 bool fast_validate)
2235 {
2236         enum dc_status result = DC_ERROR_UNEXPECTED;
2237         int i, j;
2238
2239         if (!new_ctx)
2240                 return DC_ERROR_UNEXPECTED;
2241
2242         if (dc->res_pool->funcs->validate_global) {
2243                 result = dc->res_pool->funcs->validate_global(dc, new_ctx);
2244                 if (result != DC_OK)
2245                         return result;
2246         }
2247
2248         for (i = 0; i < new_ctx->stream_count; i++) {
2249                 struct dc_stream_state *stream = new_ctx->streams[i];
2250
2251                 for (j = 0; j < dc->res_pool->pipe_count; j++) {
2252                         struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[j];
2253
2254                         if (pipe_ctx->stream != stream)
2255                                 continue;
2256
2257                         if (dc->res_pool->funcs->patch_unknown_plane_state &&
2258                                         pipe_ctx->plane_state &&
2259                                         pipe_ctx->plane_state->tiling_info.gfx9.swizzle == DC_SW_UNKNOWN) {
2260                                 result = dc->res_pool->funcs->patch_unknown_plane_state(pipe_ctx->plane_state);
2261                                 if (result != DC_OK)
2262                                         return result;
2263                         }
2264
2265                         /* Switch to dp clock source only if there is
2266                          * no non dp stream that shares the same timing
2267                          * with the dp stream.
2268                          */
2269                         if (dc_is_dp_signal(pipe_ctx->stream->signal) &&
2270                                 !find_pll_sharable_stream(stream, new_ctx)) {
2271
2272                                 resource_unreference_clock_source(
2273                                                 &new_ctx->res_ctx,
2274                                                 dc->res_pool,
2275                                                 pipe_ctx->clock_source);
2276
2277                                 pipe_ctx->clock_source = dc->res_pool->dp_clock_source;
2278                                 resource_reference_clock_source(
2279                                                 &new_ctx->res_ctx,
2280                                                 dc->res_pool,
2281                                                  pipe_ctx->clock_source);
2282                         }
2283                 }
2284         }
2285
2286         result = resource_build_scaling_params_for_context(dc, new_ctx);
2287
2288         if (result == DC_OK)
2289                 if (!dc->res_pool->funcs->validate_bandwidth(dc, new_ctx, fast_validate))
2290                         result = DC_FAIL_BANDWIDTH_VALIDATE;
2291
2292         return result;
2293 }
2294
2295 static void patch_gamut_packet_checksum(
2296                 struct dc_info_packet *gamut_packet)
2297 {
2298         /* For gamut we recalc checksum */
2299         if (gamut_packet->valid) {
2300                 uint8_t chk_sum = 0;
2301                 uint8_t *ptr;
2302                 uint8_t i;
2303
2304                 /*start of the Gamut data. */
2305                 ptr = &gamut_packet->sb[3];
2306
2307                 for (i = 0; i <= gamut_packet->sb[1]; i++)
2308                         chk_sum += ptr[i];
2309
2310                 gamut_packet->sb[2] = (uint8_t) (0x100 - chk_sum);
2311         }
2312 }
2313
2314 static void set_avi_info_frame(
2315                 struct dc_info_packet *info_packet,
2316                 struct pipe_ctx *pipe_ctx)
2317 {
2318         struct dc_stream_state *stream = pipe_ctx->stream;
2319         enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
2320         uint32_t pixel_encoding = 0;
2321         enum scanning_type scan_type = SCANNING_TYPE_NODATA;
2322         enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA;
2323         bool itc = false;
2324         uint8_t itc_value = 0;
2325         uint8_t cn0_cn1 = 0;
2326         unsigned int cn0_cn1_value = 0;
2327         uint8_t *check_sum = NULL;
2328         uint8_t byte_index = 0;
2329         union hdmi_info_packet hdmi_info;
2330         union display_content_support support = {0};
2331         unsigned int vic = pipe_ctx->stream->timing.vic;
2332         enum dc_timing_3d_format format;
2333
2334         memset(&hdmi_info, 0, sizeof(union hdmi_info_packet));
2335
2336         color_space = pipe_ctx->stream->output_color_space;
2337         if (color_space == COLOR_SPACE_UNKNOWN)
2338                 color_space = (stream->timing.pixel_encoding == PIXEL_ENCODING_RGB) ?
2339                         COLOR_SPACE_SRGB:COLOR_SPACE_YCBCR709;
2340
2341         /* Initialize header */
2342         hdmi_info.bits.header.info_frame_type = HDMI_INFOFRAME_TYPE_AVI;
2343         /* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall
2344         * not be used in HDMI 2.0 (Section 10.1) */
2345         hdmi_info.bits.header.version = 2;
2346         hdmi_info.bits.header.length = HDMI_AVI_INFOFRAME_SIZE;
2347
2348         /*
2349          * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built
2350          * according to HDMI 2.0 spec (Section 10.1)
2351          */
2352
2353         switch (stream->timing.pixel_encoding) {
2354         case PIXEL_ENCODING_YCBCR422:
2355                 pixel_encoding = 1;
2356                 break;
2357
2358         case PIXEL_ENCODING_YCBCR444:
2359                 pixel_encoding = 2;
2360                 break;
2361         case PIXEL_ENCODING_YCBCR420:
2362                 pixel_encoding = 3;
2363                 break;
2364
2365         case PIXEL_ENCODING_RGB:
2366         default:
2367                 pixel_encoding = 0;
2368         }
2369
2370         /* Y0_Y1_Y2 : The pixel encoding */
2371         /* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */
2372         hdmi_info.bits.Y0_Y1_Y2 = pixel_encoding;
2373
2374         /* A0 = 1 Active Format Information valid */
2375         hdmi_info.bits.A0 = ACTIVE_FORMAT_VALID;
2376
2377         /* B0, B1 = 3; Bar info data is valid */
2378         hdmi_info.bits.B0_B1 = BAR_INFO_BOTH_VALID;
2379
2380         hdmi_info.bits.SC0_SC1 = PICTURE_SCALING_UNIFORM;
2381
2382         /* S0, S1 : Underscan / Overscan */
2383         /* TODO: un-hardcode scan type */
2384         scan_type = SCANNING_TYPE_UNDERSCAN;
2385         hdmi_info.bits.S0_S1 = scan_type;
2386
2387         /* C0, C1 : Colorimetry */
2388         if (color_space == COLOR_SPACE_YCBCR709 ||
2389                         color_space == COLOR_SPACE_YCBCR709_LIMITED)
2390                 hdmi_info.bits.C0_C1 = COLORIMETRY_ITU709;
2391         else if (color_space == COLOR_SPACE_YCBCR601 ||
2392                         color_space == COLOR_SPACE_YCBCR601_LIMITED)
2393                 hdmi_info.bits.C0_C1 = COLORIMETRY_ITU601;
2394         else {
2395                 hdmi_info.bits.C0_C1 = COLORIMETRY_NO_DATA;
2396         }
2397         if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE ||
2398                         color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE ||
2399                         color_space == COLOR_SPACE_2020_YCBCR) {
2400                 hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR;
2401                 hdmi_info.bits.C0_C1   = COLORIMETRY_EXTENDED;
2402         } else if (color_space == COLOR_SPACE_ADOBERGB) {
2403                 hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_ADOBERGB;
2404                 hdmi_info.bits.C0_C1   = COLORIMETRY_EXTENDED;
2405         }
2406
2407         /* TODO: un-hardcode aspect ratio */
2408         aspect = stream->timing.aspect_ratio;
2409
2410         switch (aspect) {
2411         case ASPECT_RATIO_4_3:
2412         case ASPECT_RATIO_16_9:
2413                 hdmi_info.bits.M0_M1 = aspect;
2414                 break;
2415
2416         case ASPECT_RATIO_NO_DATA:
2417         case ASPECT_RATIO_64_27:
2418         case ASPECT_RATIO_256_135:
2419         default:
2420                 hdmi_info.bits.M0_M1 = 0;
2421         }
2422
2423         /* Active Format Aspect ratio - same as Picture Aspect Ratio. */
2424         hdmi_info.bits.R0_R3 = ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE;
2425
2426         /* TODO: un-hardcode cn0_cn1 and itc */
2427
2428         cn0_cn1 = 0;
2429         cn0_cn1_value = 0;
2430
2431         itc = true;
2432         itc_value = 1;
2433
2434         support = stream->content_support;
2435
2436         if (itc) {
2437                 if (!support.bits.valid_content_type) {
2438                         cn0_cn1_value = 0;
2439                 } else {
2440                         if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GRAPHICS) {
2441                                 if (support.bits.graphics_content == 1) {
2442                                         cn0_cn1_value = 0;
2443                                 }
2444                         } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_PHOTO) {
2445                                 if (support.bits.photo_content == 1) {
2446                                         cn0_cn1_value = 1;
2447                                 } else {
2448                                         cn0_cn1_value = 0;
2449                                         itc_value = 0;
2450                                 }
2451                         } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_CINEMA) {
2452                                 if (support.bits.cinema_content == 1) {
2453                                         cn0_cn1_value = 2;
2454                                 } else {
2455                                         cn0_cn1_value = 0;
2456                                         itc_value = 0;
2457                                 }
2458                         } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GAME) {
2459                                 if (support.bits.game_content == 1) {
2460                                         cn0_cn1_value = 3;
2461                                 } else {
2462                                         cn0_cn1_value = 0;
2463                                         itc_value = 0;
2464                                 }
2465                         }
2466                 }
2467                 hdmi_info.bits.CN0_CN1 = cn0_cn1_value;
2468                 hdmi_info.bits.ITC = itc_value;
2469         }
2470
2471         /* TODO : We should handle YCC quantization */
2472         /* but we do not have matrix calculation */
2473         if (stream->qs_bit == 1 &&
2474                         stream->qy_bit == 1) {
2475                 if (color_space == COLOR_SPACE_SRGB ||
2476                         color_space == COLOR_SPACE_2020_RGB_FULLRANGE) {
2477                         hdmi_info.bits.Q0_Q1   = RGB_QUANTIZATION_FULL_RANGE;
2478                         hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE;
2479                 } else if (color_space == COLOR_SPACE_SRGB_LIMITED ||
2480                                         color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) {
2481                         hdmi_info.bits.Q0_Q1   = RGB_QUANTIZATION_LIMITED_RANGE;
2482                         hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE;
2483                 } else {
2484                         hdmi_info.bits.Q0_Q1   = RGB_QUANTIZATION_DEFAULT_RANGE;
2485                         hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE;
2486                 }
2487         } else {
2488                 hdmi_info.bits.Q0_Q1   = RGB_QUANTIZATION_DEFAULT_RANGE;
2489                 hdmi_info.bits.YQ0_YQ1   = YYC_QUANTIZATION_LIMITED_RANGE;
2490         }
2491
2492         ///VIC
2493         format = stream->timing.timing_3d_format;
2494         /*todo, add 3DStereo support*/
2495         if (format != TIMING_3D_FORMAT_NONE) {
2496                 // Based on HDMI specs hdmi vic needs to be converted to cea vic when 3D is enabled
2497                 switch (pipe_ctx->stream->timing.hdmi_vic) {
2498                 case 1:
2499                         vic = 95;
2500                         break;
2501                 case 2:
2502                         vic = 94;
2503                         break;
2504                 case 3:
2505                         vic = 93;
2506                         break;
2507                 case 4:
2508                         vic = 98;
2509                         break;
2510                 default:
2511                         break;
2512                 }
2513         }
2514         /* If VIC >= 128, the Source shall use AVI InfoFrame Version 3*/
2515         hdmi_info.bits.VIC0_VIC7 = vic;
2516         if (vic >= 128)
2517                 hdmi_info.bits.header.version = 3;
2518         /* If (C1, C0)=(1, 1) and (EC2, EC1, EC0)=(1, 1, 1),
2519          * the Source shall use 20 AVI InfoFrame Version 4
2520          */
2521         if (hdmi_info.bits.C0_C1 == COLORIMETRY_EXTENDED &&
2522                         hdmi_info.bits.EC0_EC2 == COLORIMETRYEX_RESERVED) {
2523                 hdmi_info.bits.header.version = 4;
2524                 hdmi_info.bits.header.length = 14;
2525         }
2526
2527         /* pixel repetition
2528          * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel
2529          * repetition start from 1 */
2530         hdmi_info.bits.PR0_PR3 = 0;
2531
2532         /* Bar Info
2533          * barTop:    Line Number of End of Top Bar.
2534          * barBottom: Line Number of Start of Bottom Bar.
2535          * barLeft:   Pixel Number of End of Left Bar.
2536          * barRight:  Pixel Number of Start of Right Bar. */
2537         hdmi_info.bits.bar_top = stream->timing.v_border_top;
2538         hdmi_info.bits.bar_bottom = (stream->timing.v_total
2539                         - stream->timing.v_border_bottom + 1);
2540         hdmi_info.bits.bar_left  = stream->timing.h_border_left;
2541         hdmi_info.bits.bar_right = (stream->timing.h_total
2542                         - stream->timing.h_border_right + 1);
2543
2544     /* Additional Colorimetry Extension
2545      * Used in conduction with C0-C1 and EC0-EC2
2546      * 0 = DCI-P3 RGB (D65)
2547      * 1 = DCI-P3 RGB (theater)
2548      */
2549         hdmi_info.bits.ACE0_ACE3 = 0;
2550
2551         /* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */
2552         check_sum = &hdmi_info.packet_raw_data.sb[0];
2553
2554         *check_sum = HDMI_INFOFRAME_TYPE_AVI + hdmi_info.bits.header.length + hdmi_info.bits.header.version;
2555
2556         for (byte_index = 1; byte_index <= hdmi_info.bits.header.length; byte_index++)
2557                 *check_sum += hdmi_info.packet_raw_data.sb[byte_index];
2558
2559         /* one byte complement */
2560         *check_sum = (uint8_t) (0x100 - *check_sum);
2561
2562         /* Store in hw_path_mode */
2563         info_packet->hb0 = hdmi_info.packet_raw_data.hb0;
2564         info_packet->hb1 = hdmi_info.packet_raw_data.hb1;
2565         info_packet->hb2 = hdmi_info.packet_raw_data.hb2;
2566
2567         for (byte_index = 0; byte_index < sizeof(hdmi_info.packet_raw_data.sb); byte_index++)
2568                 info_packet->sb[byte_index] = hdmi_info.packet_raw_data.sb[byte_index];
2569
2570         info_packet->valid = true;
2571 }
2572
2573 static void set_vendor_info_packet(
2574                 struct dc_info_packet *info_packet,
2575                 struct dc_stream_state *stream)
2576 {
2577         /* SPD info packet for FreeSync */
2578
2579         /* Check if Freesync is supported. Return if false. If true,
2580          * set the corresponding bit in the info packet
2581          */
2582         if (!stream->vsp_infopacket.valid)
2583                 return;
2584
2585         *info_packet = stream->vsp_infopacket;
2586 }
2587
2588 static void set_spd_info_packet(
2589                 struct dc_info_packet *info_packet,
2590                 struct dc_stream_state *stream)
2591 {
2592         /* SPD info packet for FreeSync */
2593
2594         /* Check if Freesync is supported. Return if false. If true,
2595          * set the corresponding bit in the info packet
2596          */
2597         if (!stream->vrr_infopacket.valid)
2598                 return;
2599
2600         *info_packet = stream->vrr_infopacket;
2601 }
2602
2603 static void set_hdr_static_info_packet(
2604                 struct dc_info_packet *info_packet,
2605                 struct dc_stream_state *stream)
2606 {
2607         /* HDR Static Metadata info packet for HDR10 */
2608
2609         if (!stream->hdr_static_metadata.valid ||
2610                         stream->use_dynamic_meta)
2611                 return;
2612
2613         *info_packet = stream->hdr_static_metadata;
2614 }
2615
2616 static void set_vsc_info_packet(
2617                 struct dc_info_packet *info_packet,
2618                 struct dc_stream_state *stream)
2619 {
2620         if (!stream->vsc_infopacket.valid)
2621                 return;
2622
2623         *info_packet = stream->vsc_infopacket;
2624 }
2625
2626 void dc_resource_state_destruct(struct dc_state *context)
2627 {
2628         int i, j;
2629
2630         for (i = 0; i < context->stream_count; i++) {
2631                 for (j = 0; j < context->stream_status[i].plane_count; j++)
2632                         dc_plane_state_release(
2633                                 context->stream_status[i].plane_states[j]);
2634
2635                 context->stream_status[i].plane_count = 0;
2636                 dc_stream_release(context->streams[i]);
2637                 context->streams[i] = NULL;
2638         }
2639 }
2640
2641 void dc_resource_state_copy_construct(
2642                 const struct dc_state *src_ctx,
2643                 struct dc_state *dst_ctx)
2644 {
2645         int i, j;
2646         struct kref refcount = dst_ctx->refcount;
2647
2648         *dst_ctx = *src_ctx;
2649
2650         for (i = 0; i < MAX_PIPES; i++) {
2651                 struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i];
2652
2653                 if (cur_pipe->top_pipe)
2654                         cur_pipe->top_pipe =  &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx];
2655
2656                 if (cur_pipe->bottom_pipe)
2657                         cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
2658
2659                 if (cur_pipe->next_odm_pipe)
2660                         cur_pipe->next_odm_pipe =  &dst_ctx->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx];
2661
2662                 if (cur_pipe->prev_odm_pipe)
2663                         cur_pipe->prev_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx];
2664         }
2665
2666         for (i = 0; i < dst_ctx->stream_count; i++) {
2667                 dc_stream_retain(dst_ctx->streams[i]);
2668                 for (j = 0; j < dst_ctx->stream_status[i].plane_count; j++)
2669                         dc_plane_state_retain(
2670                                 dst_ctx->stream_status[i].plane_states[j]);
2671         }
2672
2673         /* context refcount should not be overridden */
2674         dst_ctx->refcount = refcount;
2675
2676 }
2677
2678 struct clock_source *dc_resource_find_first_free_pll(
2679                 struct resource_context *res_ctx,
2680                 const struct resource_pool *pool)
2681 {
2682         int i;
2683
2684         for (i = 0; i < pool->clk_src_count; ++i) {
2685                 if (res_ctx->clock_source_ref_count[i] == 0)
2686                         return pool->clock_sources[i];
2687         }
2688
2689         return NULL;
2690 }
2691
2692 void resource_build_info_frame(struct pipe_ctx *pipe_ctx)
2693 {
2694         enum signal_type signal = SIGNAL_TYPE_NONE;
2695         struct encoder_info_frame *info = &pipe_ctx->stream_res.encoder_info_frame;
2696
2697         /* default all packets to invalid */
2698         info->avi.valid = false;
2699         info->gamut.valid = false;
2700         info->vendor.valid = false;
2701         info->spd.valid = false;
2702         info->hdrsmd.valid = false;
2703         info->vsc.valid = false;
2704
2705         signal = pipe_ctx->stream->signal;
2706
2707         /* HDMi and DP have different info packets*/
2708         if (dc_is_hdmi_signal(signal)) {
2709                 set_avi_info_frame(&info->avi, pipe_ctx);
2710
2711                 set_vendor_info_packet(&info->vendor, pipe_ctx->stream);
2712
2713                 set_spd_info_packet(&info->spd, pipe_ctx->stream);
2714
2715                 set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream);
2716
2717         } else if (dc_is_dp_signal(signal)) {
2718                 set_vsc_info_packet(&info->vsc, pipe_ctx->stream);
2719
2720                 set_spd_info_packet(&info->spd, pipe_ctx->stream);
2721
2722                 set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream);
2723         }
2724
2725         patch_gamut_packet_checksum(&info->gamut);
2726 }
2727
2728 enum dc_status resource_map_clock_resources(
2729                 const struct dc  *dc,
2730                 struct dc_state *context,
2731                 struct dc_stream_state *stream)
2732 {
2733         /* acquire new resources */
2734         const struct resource_pool *pool = dc->res_pool;
2735         struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(
2736                                 &context->res_ctx, stream);
2737
2738         if (!pipe_ctx)
2739                 return DC_ERROR_UNEXPECTED;
2740
2741         if (dc_is_dp_signal(pipe_ctx->stream->signal)
2742                 || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL)
2743                 pipe_ctx->clock_source = pool->dp_clock_source;
2744         else {
2745                 pipe_ctx->clock_source = NULL;
2746
2747                 if (!dc->config.disable_disp_pll_sharing)
2748                         pipe_ctx->clock_source = resource_find_used_clk_src_for_sharing(
2749                                 &context->res_ctx,
2750                                 pipe_ctx);
2751
2752                 if (pipe_ctx->clock_source == NULL)
2753                         pipe_ctx->clock_source =
2754                                 dc_resource_find_first_free_pll(
2755                                         &context->res_ctx,
2756                                         pool);
2757         }
2758
2759         if (pipe_ctx->clock_source == NULL)
2760                 return DC_NO_CLOCK_SOURCE_RESOURCE;
2761
2762         resource_reference_clock_source(
2763                 &context->res_ctx, pool,
2764                 pipe_ctx->clock_source);
2765
2766         return DC_OK;
2767 }
2768
2769 /*
2770  * Note: We need to disable output if clock sources change,
2771  * since bios does optimization and doesn't apply if changing
2772  * PHY when not already disabled.
2773  */
2774 bool pipe_need_reprogram(
2775                 struct pipe_ctx *pipe_ctx_old,
2776                 struct pipe_ctx *pipe_ctx)
2777 {
2778         if (!pipe_ctx_old->stream)
2779                 return false;
2780
2781         if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink)
2782                 return true;
2783
2784         if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal)
2785                 return true;
2786
2787         if (pipe_ctx_old->stream_res.audio != pipe_ctx->stream_res.audio)
2788                 return true;
2789
2790         if (pipe_ctx_old->clock_source != pipe_ctx->clock_source
2791                         && pipe_ctx_old->stream != pipe_ctx->stream)
2792                 return true;
2793
2794         if (pipe_ctx_old->stream_res.stream_enc != pipe_ctx->stream_res.stream_enc)
2795                 return true;
2796
2797         if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream))
2798                 return true;
2799
2800         if (pipe_ctx_old->stream->dpms_off != pipe_ctx->stream->dpms_off)
2801                 return true;
2802
2803         if (false == pipe_ctx_old->stream->link->link_state_valid &&
2804                 false == pipe_ctx_old->stream->dpms_off)
2805                 return true;
2806
2807         if (pipe_ctx_old->stream_res.dsc != pipe_ctx->stream_res.dsc)
2808                 return true;
2809
2810         return false;
2811 }
2812
2813 void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream,
2814                 struct bit_depth_reduction_params *fmt_bit_depth)
2815 {
2816         enum dc_dither_option option = stream->dither_option;
2817         enum dc_pixel_encoding pixel_encoding =
2818                         stream->timing.pixel_encoding;
2819
2820         memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth));
2821
2822         if (option == DITHER_OPTION_DEFAULT) {
2823                 switch (stream->timing.display_color_depth) {
2824                 case COLOR_DEPTH_666:
2825                         option = DITHER_OPTION_SPATIAL6;
2826                         break;
2827                 case COLOR_DEPTH_888:
2828                         option = DITHER_OPTION_SPATIAL8;
2829                         break;
2830                 case COLOR_DEPTH_101010:
2831                         option = DITHER_OPTION_SPATIAL10;
2832                         break;
2833                 default:
2834                         option = DITHER_OPTION_DISABLE;
2835                 }
2836         }
2837
2838         if (option == DITHER_OPTION_DISABLE)
2839                 return;
2840
2841         if (option == DITHER_OPTION_TRUN6) {
2842                 fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
2843                 fmt_bit_depth->flags.TRUNCATE_DEPTH = 0;
2844         } else if (option == DITHER_OPTION_TRUN8 ||
2845                         option == DITHER_OPTION_TRUN8_SPATIAL6 ||
2846                         option == DITHER_OPTION_TRUN8_FM6) {
2847                 fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
2848                 fmt_bit_depth->flags.TRUNCATE_DEPTH = 1;
2849         } else if (option == DITHER_OPTION_TRUN10        ||
2850                         option == DITHER_OPTION_TRUN10_SPATIAL6   ||
2851                         option == DITHER_OPTION_TRUN10_SPATIAL8   ||
2852                         option == DITHER_OPTION_TRUN10_FM8     ||
2853                         option == DITHER_OPTION_TRUN10_FM6     ||
2854                         option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) {
2855                 fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
2856                 fmt_bit_depth->flags.TRUNCATE_DEPTH = 2;
2857         }
2858
2859         /* special case - Formatter can only reduce by 4 bits at most.
2860          * When reducing from 12 to 6 bits,
2861          * HW recommends we use trunc with round mode
2862          * (if we did nothing, trunc to 10 bits would be used)
2863          * note that any 12->10 bit reduction is ignored prior to DCE8,
2864          * as the input was 10 bits.
2865          */
2866         if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM ||
2867                         option == DITHER_OPTION_SPATIAL6 ||
2868                         option == DITHER_OPTION_FM6) {
2869                 fmt_bit_depth->flags.TRUNCATE_ENABLED = 1;
2870                 fmt_bit_depth->flags.TRUNCATE_DEPTH = 2;
2871                 fmt_bit_depth->flags.TRUNCATE_MODE = 1;
2872         }
2873
2874         /* spatial dither
2875          * note that spatial modes 1-3 are never used
2876          */
2877         if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM            ||
2878                         option == DITHER_OPTION_SPATIAL6 ||
2879                         option == DITHER_OPTION_TRUN10_SPATIAL6      ||
2880                         option == DITHER_OPTION_TRUN8_SPATIAL6) {
2881                 fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
2882                 fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0;
2883                 fmt_bit_depth->flags.HIGHPASS_RANDOM = 1;
2884                 fmt_bit_depth->flags.RGB_RANDOM =
2885                                 (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0;
2886         } else if (option == DITHER_OPTION_SPATIAL8_FRAME_RANDOM            ||
2887                         option == DITHER_OPTION_SPATIAL8 ||
2888                         option == DITHER_OPTION_SPATIAL8_FM6        ||
2889                         option == DITHER_OPTION_TRUN10_SPATIAL8      ||
2890                         option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) {
2891                 fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
2892                 fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1;
2893                 fmt_bit_depth->flags.HIGHPASS_RANDOM = 1;
2894                 fmt_bit_depth->flags.RGB_RANDOM =
2895                                 (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0;
2896         } else if (option == DITHER_OPTION_SPATIAL10_FRAME_RANDOM ||
2897                         option == DITHER_OPTION_SPATIAL10 ||
2898                         option == DITHER_OPTION_SPATIAL10_FM8 ||
2899                         option == DITHER_OPTION_SPATIAL10_FM6) {
2900                 fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
2901                 fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2;
2902                 fmt_bit_depth->flags.HIGHPASS_RANDOM = 1;
2903                 fmt_bit_depth->flags.RGB_RANDOM =
2904                                 (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0;
2905         }
2906
2907         if (option == DITHER_OPTION_SPATIAL6 ||
2908                         option == DITHER_OPTION_SPATIAL8 ||
2909                         option == DITHER_OPTION_SPATIAL10) {
2910                 fmt_bit_depth->flags.FRAME_RANDOM = 0;
2911         } else {
2912                 fmt_bit_depth->flags.FRAME_RANDOM = 1;
2913         }
2914
2915         //////////////////////
2916         //// temporal dither
2917         //////////////////////
2918         if (option == DITHER_OPTION_FM6           ||
2919                         option == DITHER_OPTION_SPATIAL8_FM6     ||
2920                         option == DITHER_OPTION_SPATIAL10_FM6     ||
2921                         option == DITHER_OPTION_TRUN10_FM6     ||
2922                         option == DITHER_OPTION_TRUN8_FM6      ||
2923                         option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) {
2924                 fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1;
2925                 fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 0;
2926         } else if (option == DITHER_OPTION_FM8        ||
2927                         option == DITHER_OPTION_SPATIAL10_FM8  ||
2928                         option == DITHER_OPTION_TRUN10_FM8) {
2929                 fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1;
2930                 fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 1;
2931         } else if (option == DITHER_OPTION_FM10) {
2932                 fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1;
2933                 fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 2;
2934         }
2935
2936         fmt_bit_depth->pixel_encoding = pixel_encoding;
2937 }
2938
2939 enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream)
2940 {
2941         struct dc_link *link = stream->link;
2942         struct timing_generator *tg = dc->res_pool->timing_generators[0];
2943         enum dc_status res = DC_OK;
2944
2945         calculate_phy_pix_clks(stream);
2946
2947         if (!tg->funcs->validate_timing(tg, &stream->timing))
2948                 res = DC_FAIL_CONTROLLER_VALIDATE;
2949
2950         if (res == DC_OK) {
2951                 if (!link->link_enc->funcs->validate_output_with_stream(
2952                                                 link->link_enc, stream))
2953                         res = DC_FAIL_ENC_VALIDATE;
2954         }
2955
2956         /* TODO: validate audio ASIC caps, encoder */
2957
2958         if (res == DC_OK)
2959                 res = dc_link_validate_mode_timing(stream,
2960                       link,
2961                       &stream->timing);
2962
2963         return res;
2964 }
2965
2966 enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state)
2967 {
2968         enum dc_status res = DC_OK;
2969
2970         /* TODO For now validates pixel format only */
2971         if (dc->res_pool->funcs->validate_plane)
2972                 return dc->res_pool->funcs->validate_plane(plane_state, &dc->caps);
2973
2974         return res;
2975 }
2976
2977 unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format)
2978 {
2979         switch (format) {
2980         case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
2981                 return 8;
2982         case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
2983         case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
2984                 return 12;
2985         case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
2986         case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
2987         case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
2988         case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
2989                 return 16;
2990         case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
2991         case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
2992         case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
2993         case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
2994         case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
2995 #if defined(CONFIG_DRM_AMD_DC_DCN3_0)
2996         case SURFACE_PIXEL_FORMAT_GRPH_RGBE:
2997         case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA:
2998 #endif
2999                 return 32;
3000         case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
3001         case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
3002         case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
3003                 return 64;
3004         default:
3005                 ASSERT_CRITICAL(false);
3006                 return -1;
3007         }
3008 }
3009 static unsigned int get_max_audio_sample_rate(struct audio_mode *modes)
3010 {
3011         if (modes) {
3012                 if (modes->sample_rates.rate.RATE_192)
3013                         return 192000;
3014                 if (modes->sample_rates.rate.RATE_176_4)
3015                         return 176400;
3016                 if (modes->sample_rates.rate.RATE_96)
3017                         return 96000;
3018                 if (modes->sample_rates.rate.RATE_88_2)
3019                         return 88200;
3020                 if (modes->sample_rates.rate.RATE_48)
3021                         return 48000;
3022                 if (modes->sample_rates.rate.RATE_44_1)
3023                         return 44100;
3024                 if (modes->sample_rates.rate.RATE_32)
3025                         return 32000;
3026         }
3027         /*original logic when no audio info*/
3028         return 441000;
3029 }
3030
3031 void get_audio_check(struct audio_info *aud_modes,
3032         struct audio_check *audio_chk)
3033 {
3034         unsigned int i;
3035         unsigned int max_sample_rate = 0;
3036
3037         if (aud_modes) {
3038                 audio_chk->audio_packet_type = 0x2;/*audio sample packet AP = .25 for layout0, 1 for layout1*/
3039
3040                 audio_chk->max_audiosample_rate = 0;
3041                 for (i = 0; i < aud_modes->mode_count; i++) {
3042                         max_sample_rate = get_max_audio_sample_rate(&aud_modes->modes[i]);
3043                         if (audio_chk->max_audiosample_rate < max_sample_rate)
3044                                 audio_chk->max_audiosample_rate = max_sample_rate;
3045                         /*dts takes the same as type 2: AP = 0.25*/
3046                 }
3047                 /*check which one take more bandwidth*/
3048                 if (audio_chk->max_audiosample_rate > 192000)
3049                         audio_chk->audio_packet_type = 0x9;/*AP =1*/
3050                 audio_chk->acat = 0;/*not support*/
3051         }
3052 }
3053