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