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