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