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