drm/amd/display: Connect DC resource to FBC compressor
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / display / dc / core / dc.c
1 /*
2  * Copyright 2015 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 "dc.h"
28
29 #include "core_status.h"
30 #include "core_types.h"
31 #include "hw_sequencer.h"
32
33 #include "resource.h"
34
35 #include "clock_source.h"
36 #include "dc_bios_types.h"
37
38 #include "dce_calcs.h"
39 #include "bios_parser_interface.h"
40 #include "include/irq_service_interface.h"
41 #include "transform.h"
42 #include "timing_generator.h"
43 #include "virtual/virtual_link_encoder.h"
44
45 #include "link_hwss.h"
46 #include "link_encoder.h"
47
48 #include "dc_link_ddc.h"
49 #include "dm_helpers.h"
50 #include "mem_input.h"
51
52 /*******************************************************************************
53  * Private functions
54  ******************************************************************************/
55 static void destroy_links(struct core_dc *dc)
56 {
57         uint32_t i;
58
59         for (i = 0; i < dc->link_count; i++) {
60                 if (NULL != dc->links[i])
61                         link_destroy(&dc->links[i]);
62         }
63 }
64
65 static bool create_links(
66                 struct core_dc *dc,
67                 uint32_t num_virtual_links)
68 {
69         int i;
70         int connectors_num;
71         struct dc_bios *bios = dc->ctx->dc_bios;
72
73         dc->link_count = 0;
74
75         connectors_num = bios->funcs->get_connectors_number(bios);
76
77         if (connectors_num > ENUM_ID_COUNT) {
78                 dm_error(
79                         "DC: Number of connectors %d exceeds maximum of %d!\n",
80                         connectors_num,
81                         ENUM_ID_COUNT);
82                 return false;
83         }
84
85         if (connectors_num == 0 && num_virtual_links == 0) {
86                 dm_error("DC: Number of connectors is zero!\n");
87         }
88
89         dm_output_to_console(
90                 "DC: %s: connectors_num: physical:%d, virtual:%d\n",
91                 __func__,
92                 connectors_num,
93                 num_virtual_links);
94
95         for (i = 0; i < connectors_num; i++) {
96                 struct link_init_data link_init_params = {0};
97                 struct core_link *link;
98
99                 link_init_params.ctx = dc->ctx;
100                 /* next BIOS object table connector */
101                 link_init_params.connector_index = i;
102                 link_init_params.link_index = dc->link_count;
103                 link_init_params.dc = dc;
104                 link = link_create(&link_init_params);
105
106                 if (link) {
107                         dc->links[dc->link_count] = link;
108                         link->dc = dc;
109                         ++dc->link_count;
110                 }
111         }
112
113         for (i = 0; i < num_virtual_links; i++) {
114                 struct core_link *link = dm_alloc(sizeof(*link));
115                 struct encoder_init_data enc_init = {0};
116
117                 if (link == NULL) {
118                         BREAK_TO_DEBUGGER();
119                         goto failed_alloc;
120                 }
121
122                 link->ctx = dc->ctx;
123                 link->dc = dc;
124                 link->public.connector_signal = SIGNAL_TYPE_VIRTUAL;
125                 link->link_id.type = OBJECT_TYPE_CONNECTOR;
126                 link->link_id.id = CONNECTOR_ID_VIRTUAL;
127                 link->link_id.enum_id = ENUM_ID_1;
128                 link->link_enc = dm_alloc(sizeof(*link->link_enc));
129
130                 enc_init.ctx = dc->ctx;
131                 enc_init.channel = CHANNEL_ID_UNKNOWN;
132                 enc_init.hpd_source = HPD_SOURCEID_UNKNOWN;
133                 enc_init.transmitter = TRANSMITTER_UNKNOWN;
134                 enc_init.connector = link->link_id;
135                 enc_init.encoder.type = OBJECT_TYPE_ENCODER;
136                 enc_init.encoder.id = ENCODER_ID_INTERNAL_VIRTUAL;
137                 enc_init.encoder.enum_id = ENUM_ID_1;
138                 virtual_link_encoder_construct(link->link_enc, &enc_init);
139
140                 link->public.link_index = dc->link_count;
141                 dc->links[dc->link_count] = link;
142                 dc->link_count++;
143         }
144
145         return true;
146
147 failed_alloc:
148         return false;
149 }
150
151 static bool stream_adjust_vmin_vmax(struct dc *dc,
152                 const struct dc_stream **stream, int num_streams,
153                 int vmin, int vmax)
154 {
155         /* TODO: Support multiple streams */
156         struct core_dc *core_dc = DC_TO_CORE(dc);
157         struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[0]);
158         int i = 0;
159         bool ret = false;
160
161         for (i = 0; i < MAX_PIPES; i++) {
162                 struct pipe_ctx *pipe = &core_dc->current_context->res_ctx.pipe_ctx[i];
163
164                 if (pipe->stream == core_stream && pipe->stream_enc) {
165                         core_dc->hwss.set_drr(&pipe, 1, vmin, vmax);
166
167                         /* build and update the info frame */
168                         resource_build_info_frame(pipe);
169                         core_dc->hwss.update_info_frame(pipe);
170
171                         ret = true;
172                 }
173         }
174         return ret;
175 }
176
177 static bool stream_get_crtc_position(struct dc *dc,
178                 const struct dc_stream **stream, int num_streams,
179                 unsigned int *v_pos, unsigned int *nom_v_pos)
180 {
181         /* TODO: Support multiple streams */
182         struct core_dc *core_dc = DC_TO_CORE(dc);
183         struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[0]);
184         int i = 0;
185         bool ret = false;
186         struct crtc_position position;
187
188         for (i = 0; i < MAX_PIPES; i++) {
189                 struct pipe_ctx *pipe =
190                                 &core_dc->current_context->res_ctx.pipe_ctx[i];
191
192                 if (pipe->stream == core_stream && pipe->stream_enc) {
193                         core_dc->hwss.get_position(&pipe, 1, &position);
194
195                         *v_pos = position.vertical_count;
196                         *nom_v_pos = position.nominal_vcount;
197                         ret = true;
198                 }
199         }
200         return ret;
201 }
202
203 static bool set_gamut_remap(struct dc *dc, const struct dc_stream *stream)
204 {
205         struct core_dc *core_dc = DC_TO_CORE(dc);
206         struct core_stream *core_stream = DC_STREAM_TO_CORE(stream);
207         int i = 0;
208         bool ret = false;
209         struct pipe_ctx *pipes;
210
211         for (i = 0; i < MAX_PIPES; i++) {
212                 if (core_dc->current_context->res_ctx.pipe_ctx[i].stream
213                                 == core_stream) {
214
215                         pipes = &core_dc->current_context->res_ctx.pipe_ctx[i];
216                         core_dc->hwss.program_gamut_remap(pipes);
217                         ret = true;
218                 }
219         }
220
221         return ret;
222 }
223
224 static void set_static_screen_events(struct dc *dc,
225                 const struct dc_stream **stream,
226                 int num_streams,
227                 const struct dc_static_screen_events *events)
228 {
229         struct core_dc *core_dc = DC_TO_CORE(dc);
230         int i = 0;
231         int j = 0;
232         struct pipe_ctx *pipes_affected[MAX_PIPES];
233         int num_pipes_affected = 0;
234
235         for (i = 0; i < num_streams; i++) {
236                 struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[i]);
237
238                 for (j = 0; j < MAX_PIPES; j++) {
239                         if (core_dc->current_context->res_ctx.pipe_ctx[j].stream
240                                         == core_stream) {
241                                 pipes_affected[num_pipes_affected++] =
242                                                 &core_dc->current_context->res_ctx.pipe_ctx[j];
243                         }
244                 }
245         }
246
247         core_dc->hwss.set_static_screen_control(pipes_affected, num_pipes_affected, events);
248 }
249
250 static void set_drive_settings(struct dc *dc,
251                 struct link_training_settings *lt_settings,
252                 const struct dc_link *link)
253 {
254         struct core_dc *core_dc = DC_TO_CORE(dc);
255         int i;
256
257         for (i = 0; i < core_dc->link_count; i++) {
258                 if (&core_dc->links[i]->public == link)
259                         break;
260         }
261
262         if (i >= core_dc->link_count)
263                 ASSERT_CRITICAL(false);
264
265         dc_link_dp_set_drive_settings(&core_dc->links[i]->public, lt_settings);
266 }
267
268 static void perform_link_training(struct dc *dc,
269                 struct dc_link_settings *link_setting,
270                 bool skip_video_pattern)
271 {
272         struct core_dc *core_dc = DC_TO_CORE(dc);
273         int i;
274
275         for (i = 0; i < core_dc->link_count; i++)
276                 dc_link_dp_perform_link_training(
277                         &core_dc->links[i]->public,
278                         link_setting,
279                         skip_video_pattern);
280 }
281
282 static void set_preferred_link_settings(struct dc *dc,
283                 struct dc_link_settings *link_setting,
284                 const struct dc_link *link)
285 {
286         struct core_link *core_link = DC_LINK_TO_CORE(link);
287
288         core_link->public.verified_link_cap.lane_count =
289                                 link_setting->lane_count;
290         core_link->public.verified_link_cap.link_rate =
291                                 link_setting->link_rate;
292         dp_retrain_link_dp_test(core_link, link_setting, false);
293 }
294
295 static void enable_hpd(const struct dc_link *link)
296 {
297         dc_link_dp_enable_hpd(link);
298 }
299
300 static void disable_hpd(const struct dc_link *link)
301 {
302         dc_link_dp_disable_hpd(link);
303 }
304
305
306 static void set_test_pattern(
307                 const struct dc_link *link,
308                 enum dp_test_pattern test_pattern,
309                 const struct link_training_settings *p_link_settings,
310                 const unsigned char *p_custom_pattern,
311                 unsigned int cust_pattern_size)
312 {
313         if (link != NULL)
314                 dc_link_dp_set_test_pattern(
315                         link,
316                         test_pattern,
317                         p_link_settings,
318                         p_custom_pattern,
319                         cust_pattern_size);
320 }
321
322 void set_dither_option(const struct dc_stream *dc_stream,
323                 enum dc_dither_option option)
324 {
325         struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
326         struct bit_depth_reduction_params params;
327         struct core_link *core_link = DC_LINK_TO_CORE(stream->status.link);
328         struct pipe_ctx *pipes =
329                         core_link->dc->current_context->res_ctx.pipe_ctx;
330
331         memset(&params, 0, sizeof(params));
332         if (!stream)
333                 return;
334         if (option > DITHER_OPTION_MAX)
335                 return;
336         if (option == DITHER_OPTION_DEFAULT) {
337                 switch (stream->public.timing.display_color_depth) {
338                 case COLOR_DEPTH_666:
339                         stream->public.dither_option = DITHER_OPTION_SPATIAL6;
340                         break;
341                 case COLOR_DEPTH_888:
342                         stream->public.dither_option = DITHER_OPTION_SPATIAL8;
343                         break;
344                 case COLOR_DEPTH_101010:
345                         stream->public.dither_option = DITHER_OPTION_SPATIAL10;
346                         break;
347                 default:
348                         option = DITHER_OPTION_DISABLE;
349                 }
350         } else {
351                 stream->public.dither_option = option;
352         }
353         resource_build_bit_depth_reduction_params(stream,
354                                 &params);
355         stream->bit_depth_params = params;
356         pipes->opp->funcs->
357                 opp_program_bit_depth_reduction(pipes->opp, &params);
358 }
359
360 static void allocate_dc_stream_funcs(struct core_dc *core_dc)
361 {
362         if (core_dc->hwss.set_drr != NULL) {
363                 core_dc->public.stream_funcs.adjust_vmin_vmax =
364                                 stream_adjust_vmin_vmax;
365         }
366
367         core_dc->public.stream_funcs.set_static_screen_events =
368                         set_static_screen_events;
369
370         core_dc->public.stream_funcs.get_crtc_position =
371                         stream_get_crtc_position;
372
373         core_dc->public.stream_funcs.set_gamut_remap =
374                         set_gamut_remap;
375
376         core_dc->public.stream_funcs.set_dither_option =
377                         set_dither_option;
378
379         core_dc->public.link_funcs.set_drive_settings =
380                         set_drive_settings;
381
382         core_dc->public.link_funcs.perform_link_training =
383                         perform_link_training;
384
385         core_dc->public.link_funcs.set_preferred_link_settings =
386                         set_preferred_link_settings;
387
388         core_dc->public.link_funcs.enable_hpd =
389                         enable_hpd;
390
391         core_dc->public.link_funcs.disable_hpd =
392                         disable_hpd;
393
394         core_dc->public.link_funcs.set_test_pattern =
395                         set_test_pattern;
396 }
397
398 static void destruct(struct core_dc *dc)
399 {
400         dc_resource_validate_ctx_destruct(dc->current_context);
401
402         destroy_links(dc);
403
404         dc_destroy_resource_pool(dc);
405
406         if (dc->ctx->gpio_service)
407                 dal_gpio_service_destroy(&dc->ctx->gpio_service);
408
409         if (dc->ctx->i2caux)
410                 dal_i2caux_destroy(&dc->ctx->i2caux);
411
412         if (dc->ctx->created_bios)
413                 dal_bios_parser_destroy(&dc->ctx->dc_bios);
414
415         if (dc->ctx->logger)
416                 dal_logger_destroy(&dc->ctx->logger);
417
418         dm_free(dc->current_context);
419         dc->current_context = NULL;
420
421         dm_free(dc->ctx);
422         dc->ctx = NULL;
423 }
424
425 static bool construct(struct core_dc *dc,
426                 const struct dc_init_data *init_params)
427 {
428         struct dal_logger *logger;
429         struct dc_context *dc_ctx = dm_alloc(sizeof(*dc_ctx));
430         enum dce_version dc_version = DCE_VERSION_UNKNOWN;
431
432         if (!dc_ctx) {
433                 dm_error("%s: failed to create ctx\n", __func__);
434                 goto ctx_fail;
435         }
436
437         dc->current_context = dm_alloc(sizeof(*dc->current_context));
438
439         if (!dc->current_context) {
440                 dm_error("%s: failed to create validate ctx\n", __func__);
441                 goto val_ctx_fail;
442         }
443
444         dc_ctx->cgs_device = init_params->cgs_device;
445         dc_ctx->driver_context = init_params->driver;
446         dc_ctx->dc = &dc->public;
447         dc_ctx->asic_id = init_params->asic_id;
448
449         /* Create logger */
450         logger = dal_logger_create(dc_ctx);
451
452         if (!logger) {
453                 /* can *not* call logger. call base driver 'print error' */
454                 dm_error("%s: failed to create Logger!\n", __func__);
455                 goto logger_fail;
456         }
457         dc_ctx->logger = logger;
458         dc->ctx = dc_ctx;
459         dc->ctx->dce_environment = init_params->dce_environment;
460
461         dc_version = resource_parse_asic_id(init_params->asic_id);
462         dc->ctx->dce_version = dc_version;
463
464         /* Resource should construct all asic specific resources.
465          * This should be the only place where we need to parse the asic id
466          */
467         if (init_params->vbios_override)
468                 dc_ctx->dc_bios = init_params->vbios_override;
469         else {
470                 /* Create BIOS parser */
471                 struct bp_init_data bp_init_data;
472
473                 bp_init_data.ctx = dc_ctx;
474                 bp_init_data.bios = init_params->asic_id.atombios_base_address;
475
476                 dc_ctx->dc_bios = dal_bios_parser_create(
477                                 &bp_init_data, dc_version);
478
479                 if (!dc_ctx->dc_bios) {
480                         ASSERT_CRITICAL(false);
481                         goto bios_fail;
482                 }
483
484                 dc_ctx->created_bios = true;
485                 }
486
487         /* Create I2C AUX */
488         dc_ctx->i2caux = dal_i2caux_create(dc_ctx);
489
490         if (!dc_ctx->i2caux) {
491                 ASSERT_CRITICAL(false);
492                 goto failed_to_create_i2caux;
493         }
494
495         /* Create GPIO service */
496         dc_ctx->gpio_service = dal_gpio_service_create(
497                         dc_version,
498                         dc_ctx->dce_environment,
499                         dc_ctx);
500
501         if (!dc_ctx->gpio_service) {
502                 ASSERT_CRITICAL(false);
503                 goto gpio_fail;
504         }
505
506         dc->res_pool = dc_create_resource_pool(
507                         dc,
508                         init_params->num_virtual_links,
509                         dc_version,
510                         init_params->asic_id);
511         if (!dc->res_pool)
512                 goto create_resource_fail;
513
514         if (!create_links(dc, init_params->num_virtual_links))
515                 goto create_links_fail;
516
517         allocate_dc_stream_funcs(dc);
518
519         return true;
520
521         /**** error handling here ****/
522 create_links_fail:
523 create_resource_fail:
524 gpio_fail:
525 failed_to_create_i2caux:
526 bios_fail:
527 logger_fail:
528 val_ctx_fail:
529 ctx_fail:
530         destruct(dc);
531         return false;
532 }
533
534 /*
535 void ProgramPixelDurationV(unsigned int pixelClockInKHz )
536 {
537         fixed31_32 pixel_duration = Fixed31_32(100000000, pixelClockInKHz) * 10;
538         unsigned int pixDurationInPico = round(pixel_duration);
539
540         DPG_PIPE_ARBITRATION_CONTROL1 arb_control;
541
542         arb_control.u32All = ReadReg (mmDPGV0_PIPE_ARBITRATION_CONTROL1);
543         arb_control.bits.PIXEL_DURATION = pixDurationInPico;
544         WriteReg (mmDPGV0_PIPE_ARBITRATION_CONTROL1, arb_control.u32All);
545
546         arb_control.u32All = ReadReg (mmDPGV1_PIPE_ARBITRATION_CONTROL1);
547         arb_control.bits.PIXEL_DURATION = pixDurationInPico;
548         WriteReg (mmDPGV1_PIPE_ARBITRATION_CONTROL1, arb_control.u32All);
549
550         WriteReg (mmDPGV0_PIPE_ARBITRATION_CONTROL2, 0x4000800);
551         WriteReg (mmDPGV0_REPEATER_PROGRAM, 0x11);
552
553         WriteReg (mmDPGV1_PIPE_ARBITRATION_CONTROL2, 0x4000800);
554         WriteReg (mmDPGV1_REPEATER_PROGRAM, 0x11);
555 }
556 */
557
558 /*******************************************************************************
559  * Public functions
560  ******************************************************************************/
561
562 struct dc *dc_create(const struct dc_init_data *init_params)
563  {
564         struct core_dc *core_dc = dm_alloc(sizeof(*core_dc));
565         unsigned int full_pipe_count;
566
567         if (NULL == core_dc)
568                 goto alloc_fail;
569
570         if (false == construct(core_dc, init_params))
571                 goto construct_fail;
572
573         /*TODO: separate HW and SW initialization*/
574         core_dc->hwss.init_hw(core_dc);
575
576         full_pipe_count = core_dc->res_pool->pipe_count;
577         if (core_dc->res_pool->underlay_pipe_index != NO_UNDERLAY_PIPE)
578                 full_pipe_count--;
579         core_dc->public.caps.max_streams = min(
580                         full_pipe_count,
581                         core_dc->res_pool->stream_enc_count);
582
583         core_dc->public.caps.max_links = core_dc->link_count;
584         core_dc->public.caps.max_audios = core_dc->res_pool->audio_count;
585
586         core_dc->public.config = init_params->flags;
587
588         dm_logger_write(core_dc->ctx->logger, LOG_DC,
589                         "Display Core initialized\n");
590
591
592         /* TODO: missing feature to be enabled */
593         core_dc->public.debug.disable_dfs_bypass = true;
594
595         return &core_dc->public;
596
597 construct_fail:
598         dm_free(core_dc);
599
600 alloc_fail:
601         return NULL;
602 }
603
604 void dc_destroy(struct dc **dc)
605 {
606         struct core_dc *core_dc = DC_TO_CORE(*dc);
607         destruct(core_dc);
608         dm_free(core_dc);
609         *dc = NULL;
610 }
611
612 static bool is_validation_required(
613                 const struct core_dc *dc,
614                 const struct dc_validation_set set[],
615                 int set_count)
616 {
617         const struct validate_context *context = dc->current_context;
618         int i, j;
619
620         if (context->stream_count != set_count)
621                 return true;
622
623         for (i = 0; i < set_count; i++) {
624
625                 if (set[i].surface_count != context->stream_status[i].surface_count)
626                         return true;
627                 if (!is_stream_unchanged(DC_STREAM_TO_CORE(set[i].stream), context->streams[i]))
628                         return true;
629
630                 for (j = 0; j < set[i].surface_count; j++) {
631                         struct dc_surface temp_surf;
632                         memset(&temp_surf, 0, sizeof(temp_surf));
633
634                         temp_surf = *context->stream_status[i].surfaces[j];
635                         temp_surf.clip_rect = set[i].surfaces[j]->clip_rect;
636                         temp_surf.dst_rect.x = set[i].surfaces[j]->dst_rect.x;
637                         temp_surf.dst_rect.y = set[i].surfaces[j]->dst_rect.y;
638
639                         if (memcmp(&temp_surf, set[i].surfaces[j], sizeof(temp_surf)) != 0)
640                                 return true;
641                 }
642         }
643
644         return false;
645 }
646
647 struct validate_context *dc_get_validate_context(
648                 const struct dc *dc,
649                 const struct dc_validation_set set[],
650                 uint8_t set_count)
651 {
652         struct core_dc *core_dc = DC_TO_CORE(dc);
653         enum dc_status result = DC_ERROR_UNEXPECTED;
654         struct validate_context *context;
655
656         context = dm_alloc(sizeof(struct validate_context));
657         if (context == NULL)
658                 goto context_alloc_fail;
659
660         if (!is_validation_required(core_dc, set, set_count)) {
661                 dc_resource_validate_ctx_copy_construct(core_dc->current_context, context);
662                 return context;
663         }
664
665         result = core_dc->res_pool->funcs->validate_with_context(
666                         core_dc, set, set_count, context, core_dc->current_context);
667
668 context_alloc_fail:
669         if (result != DC_OK) {
670                 dm_logger_write(core_dc->ctx->logger, LOG_WARNING,
671                                 "%s:resource validation failed, dc_status:%d\n",
672                                 __func__,
673                                 result);
674
675                 dc_resource_validate_ctx_destruct(context);
676                 dm_free(context);
677                 context = NULL;
678         }
679
680         return context;
681
682 }
683
684 bool dc_validate_resources(
685                 const struct dc *dc,
686                 const struct dc_validation_set set[],
687                 uint8_t set_count)
688 {
689         struct core_dc *core_dc = DC_TO_CORE(dc);
690         enum dc_status result = DC_ERROR_UNEXPECTED;
691         struct validate_context *context;
692
693         context = dm_alloc(sizeof(struct validate_context));
694         if (context == NULL)
695                 goto context_alloc_fail;
696
697         result = core_dc->res_pool->funcs->validate_with_context(
698                                 core_dc, set, set_count, context, NULL);
699
700 context_alloc_fail:
701         if (result != DC_OK) {
702                 dm_logger_write(core_dc->ctx->logger, LOG_WARNING,
703                                 "%s:resource validation failed, dc_status:%d\n",
704                                 __func__,
705                                 result);
706         }
707
708         dc_resource_validate_ctx_destruct(context);
709         dm_free(context);
710         context = NULL;
711
712         return result == DC_OK;
713 }
714
715 bool dc_validate_guaranteed(
716                 const struct dc *dc,
717                 const struct dc_stream *stream)
718 {
719         struct core_dc *core_dc = DC_TO_CORE(dc);
720         enum dc_status result = DC_ERROR_UNEXPECTED;
721         struct validate_context *context;
722
723         context = dm_alloc(sizeof(struct validate_context));
724         if (context == NULL)
725                 goto context_alloc_fail;
726
727         result = core_dc->res_pool->funcs->validate_guaranteed(
728                                         core_dc, stream, context);
729
730         dc_resource_validate_ctx_destruct(context);
731         dm_free(context);
732
733 context_alloc_fail:
734         if (result != DC_OK) {
735                 dm_logger_write(core_dc->ctx->logger, LOG_WARNING,
736                         "%s:guaranteed validation failed, dc_status:%d\n",
737                         __func__,
738                         result);
739                 }
740
741         return (result == DC_OK);
742 }
743
744 static void program_timing_sync(
745                 struct core_dc *core_dc,
746                 struct validate_context *ctx)
747 {
748         int i, j;
749         int group_index = 0;
750         int pipe_count = core_dc->res_pool->pipe_count;
751         struct pipe_ctx *unsynced_pipes[MAX_PIPES] = { NULL };
752
753         for (i = 0; i < pipe_count; i++) {
754                 if (!ctx->res_ctx.pipe_ctx[i].stream || ctx->res_ctx.pipe_ctx[i].top_pipe)
755                         continue;
756
757                 unsynced_pipes[i] = &ctx->res_ctx.pipe_ctx[i];
758         }
759
760         for (i = 0; i < pipe_count; i++) {
761                 int group_size = 1;
762                 struct pipe_ctx *pipe_set[MAX_PIPES];
763
764                 if (!unsynced_pipes[i])
765                         continue;
766
767                 pipe_set[0] = unsynced_pipes[i];
768                 unsynced_pipes[i] = NULL;
769
770                 /* Add tg to the set, search rest of the tg's for ones with
771                  * same timing, add all tgs with same timing to the group
772                  */
773                 for (j = i + 1; j < pipe_count; j++) {
774                         if (!unsynced_pipes[j])
775                                 continue;
776
777                         if (resource_are_streams_timing_synchronizable(
778                                         unsynced_pipes[j]->stream,
779                                         pipe_set[0]->stream)) {
780                                 pipe_set[group_size] = unsynced_pipes[j];
781                                 unsynced_pipes[j] = NULL;
782                                 group_size++;
783                         }
784                 }
785
786                 /* set first unblanked pipe as master */
787                 for (j = 0; j < group_size; j++) {
788                         struct pipe_ctx *temp;
789
790                         if (!pipe_set[j]->tg->funcs->is_blanked(pipe_set[j]->tg)) {
791                                 if (j == 0)
792                                         break;
793
794                                 temp = pipe_set[0];
795                                 pipe_set[0] = pipe_set[j];
796                                 pipe_set[j] = temp;
797                                 break;
798                         }
799                 }
800
801                 /* remove any other unblanked pipes as they have already been synced */
802                 for (j = j + 1; j < group_size; j++) {
803                         if (!pipe_set[j]->tg->funcs->is_blanked(pipe_set[j]->tg)) {
804                                 group_size--;
805                                 pipe_set[j] = pipe_set[group_size];
806                                 j--;
807                         }
808                 }
809
810                 if (group_size > 1) {
811                         core_dc->hwss.enable_timing_synchronization(
812                                 core_dc, group_index, group_size, pipe_set);
813                         group_index++;
814                 }
815         }
816 }
817
818 static bool streams_changed(
819                 struct core_dc *dc,
820                 const struct dc_stream *streams[],
821                 uint8_t stream_count)
822 {
823         uint8_t i;
824
825         if (stream_count != dc->current_context->stream_count)
826                 return true;
827
828         for (i = 0; i < dc->current_context->stream_count; i++) {
829                 if (&dc->current_context->streams[i]->public != streams[i])
830                         return true;
831         }
832
833         return false;
834 }
835
836 bool dc_enable_stereo(
837         struct dc *dc,
838         struct validate_context *context,
839         const struct dc_stream *streams[],
840         uint8_t stream_count)
841 {
842         bool ret = true;
843         int i, j;
844         struct pipe_ctx *pipe;
845         struct core_dc *core_dc = DC_TO_CORE(dc);
846
847 #ifdef ENABLE_FBC
848         struct compressor *fbc_compressor = core_dc->fbc_compressor;
849 #endif
850
851         for (i = 0; i < MAX_PIPES; i++) {
852                 if (context != NULL)
853                         pipe = &context->res_ctx.pipe_ctx[i];
854                 else
855                         pipe = &core_dc->current_context->res_ctx.pipe_ctx[i];
856                 for (j = 0 ; pipe && j < stream_count; j++)  {
857                         if (streams[j] && streams[j] == &pipe->stream->public &&
858                                 core_dc->hwss.setup_stereo)
859                                 core_dc->hwss.setup_stereo(pipe, core_dc);
860                 }
861         }
862
863 #ifdef ENABLE_FBC
864         if (fbc_compressor != NULL &&
865             fbc_compressor->funcs->is_fbc_enabled_in_hw(core_dc->fbc_compressor,
866                                                         &pipe->tg->inst))
867                 fbc_compressor->funcs->disable_fbc(fbc_compressor);
868
869 #endif
870         return ret;
871 }
872
873 bool dc_commit_streams(
874         struct dc *dc,
875         const struct dc_stream *streams[],
876         uint8_t stream_count)
877 {
878         struct core_dc *core_dc = DC_TO_CORE(dc);
879         struct dc_bios *dcb = core_dc->ctx->dc_bios;
880         enum dc_status result = DC_ERROR_UNEXPECTED;
881         struct validate_context *context;
882         struct dc_validation_set set[MAX_STREAMS] = { {0, {0} } };
883         int i, j;
884
885         if (false == streams_changed(core_dc, streams, stream_count))
886                 return DC_OK;
887
888         dm_logger_write(core_dc->ctx->logger, LOG_DC, "%s: %d streams\n",
889                                 __func__, stream_count);
890
891         for (i = 0; i < stream_count; i++) {
892                 const struct dc_stream *stream = streams[i];
893                 const struct dc_stream_status *status = dc_stream_get_status(stream);
894                 int j;
895
896                 dc_stream_log(stream,
897                                 core_dc->ctx->logger,
898                                 LOG_DC);
899
900                 set[i].stream = stream;
901
902                 if (status) {
903                         set[i].surface_count = status->surface_count;
904                         for (j = 0; j < status->surface_count; j++)
905                                 set[i].surfaces[j] = status->surfaces[j];
906                 }
907
908         }
909
910         context = dm_alloc(sizeof(struct validate_context));
911         if (context == NULL)
912                 goto context_alloc_fail;
913
914         result = core_dc->res_pool->funcs->validate_with_context(
915                         core_dc, set, stream_count, context, core_dc->current_context);
916         if (result != DC_OK){
917                 dm_logger_write(core_dc->ctx->logger, LOG_ERROR,
918                                         "%s: Context validation failed! dc_status:%d\n",
919                                         __func__,
920                                         result);
921                 BREAK_TO_DEBUGGER();
922                 dc_resource_validate_ctx_destruct(context);
923                 goto fail;
924         }
925
926         if (!dcb->funcs->is_accelerated_mode(dcb)) {
927                 core_dc->hwss.enable_accelerated_mode(core_dc);
928         }
929
930         if (result == DC_OK) {
931                 result = core_dc->hwss.apply_ctx_to_hw(core_dc, context);
932         }
933
934         program_timing_sync(core_dc, context);
935
936         for (i = 0; i < context->stream_count; i++) {
937                 const struct core_sink *sink = context->streams[i]->sink;
938
939                 for (j = 0; j < context->stream_status[i].surface_count; j++) {
940                         struct core_surface *surface =
941                                         DC_SURFACE_TO_CORE(context->stream_status[i].surfaces[j]);
942
943                         core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context);
944                         dc_enable_stereo(dc, context, streams, stream_count);
945                 }
946
947                 CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}",
948                                 context->streams[i]->public.timing.h_addressable,
949                                 context->streams[i]->public.timing.v_addressable,
950                                 context->streams[i]->public.timing.h_total,
951                                 context->streams[i]->public.timing.v_total,
952                                 context->streams[i]->public.timing.pix_clk_khz);
953         }
954
955         dc_resource_validate_ctx_destruct(core_dc->current_context);
956         dm_free(core_dc->current_context);
957
958         core_dc->current_context = context;
959
960         return (result == DC_OK);
961
962 fail:
963         dm_free(context);
964
965 context_alloc_fail:
966         return (result == DC_OK);
967 }
968
969 bool dc_post_update_surfaces_to_stream(struct dc *dc)
970 {
971         int i;
972         struct core_dc *core_dc = DC_TO_CORE(dc);
973         struct validate_context *context = core_dc->current_context;
974
975         post_surface_trace(dc);
976
977         for (i = 0; i < core_dc->res_pool->pipe_count; i++)
978                 if (context->res_ctx.pipe_ctx[i].stream == NULL
979                                 || context->res_ctx.pipe_ctx[i].surface == NULL)
980                         core_dc->hwss.power_down_front_end(core_dc, i);
981
982         /* 3rd param should be true, temp w/a for RV*/
983 #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
984         core_dc->hwss.set_bandwidth(core_dc, context, core_dc->ctx->dce_version != DCN_VERSION_1_0);
985 #else
986         core_dc->hwss.set_bandwidth(core_dc, context, true);
987 #endif
988         return true;
989 }
990
991 bool dc_commit_surfaces_to_stream(
992                 struct dc *dc,
993                 const struct dc_surface **new_surfaces,
994                 uint8_t new_surface_count,
995                 const struct dc_stream *dc_stream)
996 {
997         struct dc_surface_update updates[MAX_SURFACES];
998         struct dc_flip_addrs flip_addr[MAX_SURFACES];
999         struct dc_plane_info plane_info[MAX_SURFACES];
1000         struct dc_scaling_info scaling_info[MAX_SURFACES];
1001         int i;
1002         struct dc_stream_update *stream_update =
1003                         dm_alloc(sizeof(struct dc_stream_update));
1004
1005         if (!stream_update) {
1006                 BREAK_TO_DEBUGGER();
1007                 return false;
1008         }
1009
1010         memset(updates, 0, sizeof(updates));
1011         memset(flip_addr, 0, sizeof(flip_addr));
1012         memset(plane_info, 0, sizeof(plane_info));
1013         memset(scaling_info, 0, sizeof(scaling_info));
1014
1015         stream_update->src = dc_stream->src;
1016         stream_update->dst = dc_stream->dst;
1017
1018         for (i = 0; i < new_surface_count; i++) {
1019                 updates[i].surface = new_surfaces[i];
1020                 updates[i].gamma =
1021                         (struct dc_gamma *)new_surfaces[i]->gamma_correction;
1022                 flip_addr[i].address = new_surfaces[i]->address;
1023                 flip_addr[i].flip_immediate = new_surfaces[i]->flip_immediate;
1024                 plane_info[i].color_space = new_surfaces[i]->color_space;
1025                 plane_info[i].format = new_surfaces[i]->format;
1026                 plane_info[i].plane_size = new_surfaces[i]->plane_size;
1027                 plane_info[i].rotation = new_surfaces[i]->rotation;
1028                 plane_info[i].horizontal_mirror = new_surfaces[i]->horizontal_mirror;
1029                 plane_info[i].stereo_format = new_surfaces[i]->stereo_format;
1030                 plane_info[i].tiling_info = new_surfaces[i]->tiling_info;
1031                 plane_info[i].visible = new_surfaces[i]->visible;
1032                 plane_info[i].per_pixel_alpha = new_surfaces[i]->per_pixel_alpha;
1033                 plane_info[i].dcc = new_surfaces[i]->dcc;
1034                 scaling_info[i].scaling_quality = new_surfaces[i]->scaling_quality;
1035                 scaling_info[i].src_rect = new_surfaces[i]->src_rect;
1036                 scaling_info[i].dst_rect = new_surfaces[i]->dst_rect;
1037                 scaling_info[i].clip_rect = new_surfaces[i]->clip_rect;
1038
1039                 updates[i].flip_addr = &flip_addr[i];
1040                 updates[i].plane_info = &plane_info[i];
1041                 updates[i].scaling_info = &scaling_info[i];
1042         }
1043
1044         dc_update_surfaces_and_stream(
1045                         dc,
1046                         updates,
1047                         new_surface_count,
1048                         dc_stream, stream_update);
1049
1050         dc_post_update_surfaces_to_stream(dc);
1051
1052         dm_free(stream_update);
1053         return true;
1054 }
1055
1056 static bool is_surface_in_context(
1057                 const struct validate_context *context,
1058                 const struct dc_surface *surface)
1059 {
1060         int j;
1061
1062         for (j = 0; j < MAX_PIPES; j++) {
1063                 const struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
1064
1065                 if (surface == &pipe_ctx->surface->public) {
1066                         return true;
1067                 }
1068         }
1069
1070         return false;
1071 }
1072
1073 static unsigned int pixel_format_to_bpp(enum surface_pixel_format format)
1074 {
1075         switch (format) {
1076         case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
1077         case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
1078                 return 12;
1079         case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
1080         case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
1081         case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
1082         case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
1083                 return 16;
1084         case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
1085         case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
1086         case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
1087         case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
1088                 return 32;
1089         case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
1090         case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
1091         case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
1092                 return 64;
1093         default:
1094                 ASSERT_CRITICAL(false);
1095                 return -1;
1096         }
1097 }
1098
1099 static enum surface_update_type get_plane_info_update_type(
1100                 const struct dc_surface_update *u,
1101                 int surface_index)
1102 {
1103         struct dc_plane_info temp_plane_info;
1104         memset(&temp_plane_info, 0, sizeof(temp_plane_info));
1105
1106         if (!u->plane_info)
1107                 return UPDATE_TYPE_FAST;
1108
1109         temp_plane_info = *u->plane_info;
1110
1111         /* Copy all parameters that will cause a full update
1112          * from current surface, the rest of the parameters
1113          * from provided plane configuration.
1114          * Perform memory compare and special validation
1115          * for those that can cause fast/medium updates
1116          */
1117
1118         /* Full update parameters */
1119         temp_plane_info.color_space = u->surface->color_space;
1120         temp_plane_info.dcc = u->surface->dcc;
1121         temp_plane_info.horizontal_mirror = u->surface->horizontal_mirror;
1122         temp_plane_info.plane_size = u->surface->plane_size;
1123         temp_plane_info.rotation = u->surface->rotation;
1124         temp_plane_info.stereo_format = u->surface->stereo_format;
1125         temp_plane_info.tiling_info = u->surface->tiling_info;
1126
1127         if (surface_index == 0)
1128                 temp_plane_info.visible = u->plane_info->visible;
1129         else
1130                 temp_plane_info.visible = u->surface->visible;
1131
1132         if (memcmp(u->plane_info, &temp_plane_info,
1133                         sizeof(struct dc_plane_info)) != 0)
1134                 return UPDATE_TYPE_FULL;
1135
1136         if (pixel_format_to_bpp(u->plane_info->format) !=
1137                         pixel_format_to_bpp(u->surface->format)) {
1138                 return UPDATE_TYPE_FULL;
1139         } else {
1140                 return UPDATE_TYPE_MED;
1141         }
1142 }
1143
1144 static enum surface_update_type  get_scaling_info_update_type(
1145                 const struct dc_surface_update *u)
1146 {
1147         if (!u->scaling_info)
1148                 return UPDATE_TYPE_FAST;
1149
1150         if (u->scaling_info->src_rect.width != u->surface->src_rect.width
1151                         || u->scaling_info->src_rect.height != u->surface->src_rect.height
1152                         || u->scaling_info->clip_rect.width != u->surface->clip_rect.width
1153                         || u->scaling_info->clip_rect.height != u->surface->clip_rect.height
1154                         || u->scaling_info->dst_rect.width != u->surface->dst_rect.width
1155                         || u->scaling_info->dst_rect.height != u->surface->dst_rect.height)
1156                 return UPDATE_TYPE_FULL;
1157
1158         if (u->scaling_info->src_rect.x != u->surface->src_rect.x
1159                         || u->scaling_info->src_rect.y != u->surface->src_rect.y
1160                         || u->scaling_info->clip_rect.x != u->surface->clip_rect.x
1161                         || u->scaling_info->clip_rect.y != u->surface->clip_rect.y
1162                         || u->scaling_info->dst_rect.x != u->surface->dst_rect.x
1163                         || u->scaling_info->dst_rect.y != u->surface->dst_rect.y)
1164                 return UPDATE_TYPE_MED;
1165
1166         return UPDATE_TYPE_FAST;
1167 }
1168
1169 static enum surface_update_type det_surface_update(
1170                 const struct core_dc *dc,
1171                 const struct dc_surface_update *u,
1172                 int surface_index)
1173 {
1174         const struct validate_context *context = dc->current_context;
1175         enum surface_update_type type = UPDATE_TYPE_FAST;
1176         enum surface_update_type overall_type = UPDATE_TYPE_FAST;
1177
1178         if (!is_surface_in_context(context, u->surface))
1179                 return UPDATE_TYPE_FULL;
1180
1181         type = get_plane_info_update_type(u, surface_index);
1182         if (overall_type < type)
1183                 overall_type = type;
1184
1185         type = get_scaling_info_update_type(u);
1186         if (overall_type < type)
1187                 overall_type = type;
1188
1189         if (u->in_transfer_func ||
1190                 u->hdr_static_metadata) {
1191                 if (overall_type < UPDATE_TYPE_MED)
1192                         overall_type = UPDATE_TYPE_MED;
1193         }
1194
1195         return overall_type;
1196 }
1197
1198 enum surface_update_type dc_check_update_surfaces_for_stream(
1199                 struct dc *dc,
1200                 struct dc_surface_update *updates,
1201                 int surface_count,
1202                 struct dc_stream_update *stream_update,
1203                 const struct dc_stream_status *stream_status)
1204 {
1205         struct core_dc *core_dc = DC_TO_CORE(dc);
1206         int i;
1207         enum surface_update_type overall_type = UPDATE_TYPE_FAST;
1208
1209         if (stream_status == NULL || stream_status->surface_count != surface_count)
1210                 return UPDATE_TYPE_FULL;
1211
1212         if (stream_update)
1213                 return UPDATE_TYPE_FULL;
1214
1215         for (i = 0 ; i < surface_count; i++) {
1216                 enum surface_update_type type =
1217                                 det_surface_update(core_dc, &updates[i], i);
1218
1219                 if (type == UPDATE_TYPE_FULL)
1220                         return type;
1221
1222                 if (overall_type < type)
1223                         overall_type = type;
1224         }
1225
1226         return overall_type;
1227 }
1228
1229 enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL;
1230
1231 void dc_update_surfaces_and_stream(struct dc *dc,
1232                 struct dc_surface_update *srf_updates, int surface_count,
1233                 const struct dc_stream *dc_stream,
1234                 struct dc_stream_update *stream_update)
1235 {
1236         struct core_dc *core_dc = DC_TO_CORE(dc);
1237         struct validate_context *context;
1238         int i, j;
1239         enum surface_update_type update_type;
1240         const struct dc_stream_status *stream_status;
1241         struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
1242
1243         stream_status = dc_stream_get_status(dc_stream);
1244         ASSERT(stream_status);
1245         if (!stream_status)
1246                 return; /* Cannot commit surface to stream that is not committed */
1247
1248 #ifdef ENABLE_FBC
1249         if (srf_updates->flip_addr) {
1250                 if (srf_updates->flip_addr->address.grph.addr.low_part == 0)
1251                         ASSERT(0);
1252         }
1253 #endif
1254         context = core_dc->current_context;
1255
1256         /* update current stream with the new updates */
1257         if (stream_update) {
1258                 if ((stream_update->src.height != 0) &&
1259                                 (stream_update->src.width != 0))
1260                         stream->public.src = stream_update->src;
1261
1262                 if ((stream_update->dst.height != 0) &&
1263                                 (stream_update->dst.width != 0))
1264                         stream->public.dst = stream_update->dst;
1265
1266                 if (stream_update->out_transfer_func &&
1267                                 stream_update->out_transfer_func !=
1268                                                 dc_stream->out_transfer_func) {
1269                         if (dc_stream->out_transfer_func != NULL)
1270                                 dc_transfer_func_release(dc_stream->out_transfer_func);
1271                         dc_transfer_func_retain(stream_update->out_transfer_func);
1272                         stream->public.out_transfer_func =
1273                                 stream_update->out_transfer_func;
1274                 }
1275         }
1276
1277         /* do not perform surface update if surface has invalid dimensions
1278          * (all zero) and no scaling_info is provided
1279          */
1280         if (surface_count > 0 &&
1281                         srf_updates->surface->src_rect.width == 0 &&
1282                         srf_updates->surface->src_rect.height == 0 &&
1283                         srf_updates->surface->dst_rect.width == 0 &&
1284                         srf_updates->surface->dst_rect.height == 0 &&
1285                         !srf_updates->scaling_info) {
1286                 ASSERT(false);
1287                 return;
1288         }
1289
1290         update_type = dc_check_update_surfaces_for_stream(
1291                         dc, srf_updates, surface_count, stream_update, stream_status);
1292
1293         if (update_type >= update_surface_trace_level)
1294                 update_surface_trace(dc, srf_updates, surface_count);
1295
1296         if (update_type >= UPDATE_TYPE_FULL) {
1297                 const struct dc_surface *new_surfaces[MAX_SURFACES] = {0};
1298
1299                 for (i = 0; i < surface_count; i++)
1300                         new_surfaces[i] = srf_updates[i].surface;
1301
1302                 /* initialize scratch memory for building context */
1303                 context = dm_alloc(sizeof(*context));
1304                 dc_resource_validate_ctx_copy_construct(
1305                                 core_dc->current_context, context);
1306
1307                 /* add surface to context */
1308                 if (!resource_attach_surfaces_to_context(
1309                                 new_surfaces, surface_count, dc_stream,
1310                                 context, core_dc->res_pool)) {
1311                         BREAK_TO_DEBUGGER();
1312                         goto fail;
1313                 }
1314         }
1315
1316         /* save update parameters into surface */
1317         for (i = 0; i < surface_count; i++) {
1318                 struct core_surface *surface =
1319                                 DC_SURFACE_TO_CORE(srf_updates[i].surface);
1320
1321                 if (srf_updates[i].flip_addr) {
1322                         surface->public.address = srf_updates[i].flip_addr->address;
1323                         surface->public.flip_immediate =
1324                                         srf_updates[i].flip_addr->flip_immediate;
1325                 }
1326
1327                 if (srf_updates[i].scaling_info) {
1328                         surface->public.scaling_quality =
1329                                         srf_updates[i].scaling_info->scaling_quality;
1330                         surface->public.dst_rect =
1331                                         srf_updates[i].scaling_info->dst_rect;
1332                         surface->public.src_rect =
1333                                         srf_updates[i].scaling_info->src_rect;
1334                         surface->public.clip_rect =
1335                                         srf_updates[i].scaling_info->clip_rect;
1336                 }
1337
1338                 if (srf_updates[i].plane_info) {
1339                         surface->public.color_space =
1340                                         srf_updates[i].plane_info->color_space;
1341                         surface->public.format =
1342                                         srf_updates[i].plane_info->format;
1343                         surface->public.plane_size =
1344                                         srf_updates[i].plane_info->plane_size;
1345                         surface->public.rotation =
1346                                         srf_updates[i].plane_info->rotation;
1347                         surface->public.horizontal_mirror =
1348                                         srf_updates[i].plane_info->horizontal_mirror;
1349                         surface->public.stereo_format =
1350                                         srf_updates[i].plane_info->stereo_format;
1351                         surface->public.tiling_info =
1352                                         srf_updates[i].plane_info->tiling_info;
1353                         surface->public.visible =
1354                                         srf_updates[i].plane_info->visible;
1355                         surface->public.per_pixel_alpha =
1356                                         srf_updates[i].plane_info->per_pixel_alpha;
1357                         surface->public.dcc =
1358                                         srf_updates[i].plane_info->dcc;
1359                 }
1360
1361                 if (update_type >= UPDATE_TYPE_MED) {
1362                         for (j = 0; j < core_dc->res_pool->pipe_count; j++) {
1363                                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
1364
1365                                 if (pipe_ctx->surface != surface)
1366                                         continue;
1367
1368                                 resource_build_scaling_params(pipe_ctx);
1369                         }
1370                 }
1371
1372                 if (srf_updates[i].gamma &&
1373                         srf_updates[i].gamma != surface->public.gamma_correction) {
1374                         if (surface->public.gamma_correction != NULL)
1375                                 dc_gamma_release(&surface->public.
1376                                                 gamma_correction);
1377
1378                         dc_gamma_retain(srf_updates[i].gamma);
1379                         surface->public.gamma_correction =
1380                                                 srf_updates[i].gamma;
1381                 }
1382
1383                 if (srf_updates[i].in_transfer_func &&
1384                         srf_updates[i].in_transfer_func != surface->public.in_transfer_func) {
1385                         if (surface->public.in_transfer_func != NULL)
1386                                 dc_transfer_func_release(
1387                                                 surface->public.
1388                                                 in_transfer_func);
1389
1390                         dc_transfer_func_retain(
1391                                         srf_updates[i].in_transfer_func);
1392                         surface->public.in_transfer_func =
1393                                         srf_updates[i].in_transfer_func;
1394                 }
1395
1396                 if (srf_updates[i].hdr_static_metadata)
1397                         surface->public.hdr_static_ctx =
1398                                 *(srf_updates[i].hdr_static_metadata);
1399         }
1400
1401         if (update_type == UPDATE_TYPE_FULL) {
1402                 if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) {
1403                         BREAK_TO_DEBUGGER();
1404                         goto fail;
1405                 } else {
1406                         core_dc->hwss.set_bandwidth(core_dc, context, false);
1407                         context_clock_trace(dc, context);
1408                 }
1409         }
1410
1411         if (surface_count == 0)
1412                 core_dc->hwss.apply_ctx_for_surface(core_dc, NULL, context);
1413
1414         /* Lock pipes for provided surfaces, or all active if full update*/
1415         for (i = 0; i < surface_count; i++) {
1416                 struct core_surface *surface = DC_SURFACE_TO_CORE(srf_updates[i].surface);
1417
1418                 for (j = 0; j < core_dc->res_pool->pipe_count; j++) {
1419                         struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
1420
1421                         if (update_type != UPDATE_TYPE_FULL && pipe_ctx->surface != surface)
1422                                 continue;
1423                         if (!pipe_ctx->surface || pipe_ctx->top_pipe)
1424                                 continue;
1425
1426                         if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) {
1427                                 core_dc->hwss.pipe_control_lock(
1428                                                 core_dc,
1429                                                 pipe_ctx,
1430                                                 true);
1431                         }
1432                 }
1433                 if (update_type == UPDATE_TYPE_FULL)
1434                         break;
1435         }
1436
1437         /* Full fe update*/
1438         for (j = 0; j < core_dc->res_pool->pipe_count; j++) {
1439                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
1440                 struct pipe_ctx *cur_pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[j];
1441                 bool is_new_pipe_surface = cur_pipe_ctx->surface != pipe_ctx->surface;
1442                 struct dc_cursor_position position = { 0 };
1443
1444                 if (update_type != UPDATE_TYPE_FULL || !pipe_ctx->surface)
1445                         continue;
1446
1447                 if (!pipe_ctx->top_pipe)
1448                         core_dc->hwss.apply_ctx_for_surface(
1449                                         core_dc, pipe_ctx->surface, context);
1450
1451                 /* TODO: this is a hack w/a for switching from mpo to pipe split */
1452                 dc_stream_set_cursor_position(&pipe_ctx->stream->public, &position);
1453
1454                 if (is_new_pipe_surface) {
1455                         core_dc->hwss.update_plane_addr(core_dc, pipe_ctx);
1456                         core_dc->hwss.set_input_transfer_func(
1457                                         pipe_ctx, pipe_ctx->surface);
1458                         core_dc->hwss.set_output_transfer_func(
1459                                         pipe_ctx, pipe_ctx->stream);
1460                 }
1461         }
1462
1463         if (update_type > UPDATE_TYPE_FAST)
1464                 context_timing_trace(dc, &context->res_ctx);
1465
1466         /* Perform requested Updates */
1467         for (i = 0; i < surface_count; i++) {
1468                 struct core_surface *surface = DC_SURFACE_TO_CORE(srf_updates[i].surface);
1469
1470                 if (update_type == UPDATE_TYPE_MED)
1471                         core_dc->hwss.apply_ctx_for_surface(
1472                                         core_dc, surface, context);
1473
1474                 for (j = 0; j < core_dc->res_pool->pipe_count; j++) {
1475                         struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
1476
1477                         if (pipe_ctx->surface != surface)
1478                                 continue;
1479
1480                         if (srf_updates[i].flip_addr)
1481                                 core_dc->hwss.update_plane_addr(core_dc, pipe_ctx);
1482
1483                         if (update_type == UPDATE_TYPE_FAST)
1484                                 continue;
1485
1486                         if (srf_updates[i].in_transfer_func)
1487                                 core_dc->hwss.set_input_transfer_func(
1488                                                 pipe_ctx, pipe_ctx->surface);
1489
1490                         if (stream_update != NULL &&
1491                                         stream_update->out_transfer_func != NULL) {
1492                                 core_dc->hwss.set_output_transfer_func(
1493                                                 pipe_ctx, pipe_ctx->stream);
1494                         }
1495
1496                         if (srf_updates[i].hdr_static_metadata) {
1497                                 resource_build_info_frame(pipe_ctx);
1498                                 core_dc->hwss.update_info_frame(pipe_ctx);
1499                         }
1500                 }
1501         }
1502
1503         /* Unlock pipes */
1504         for (i = core_dc->res_pool->pipe_count - 1; i >= 0; i--) {
1505                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1506
1507                 for (j = 0; j < surface_count; j++) {
1508                         if (update_type != UPDATE_TYPE_FULL &&
1509                                         srf_updates[j].surface != &pipe_ctx->surface->public)
1510                                 continue;
1511                         if (!pipe_ctx->surface || pipe_ctx->top_pipe)
1512                                 continue;
1513
1514                         if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) {
1515                                 core_dc->hwss.pipe_control_lock(
1516                                                 core_dc,
1517                                                 pipe_ctx,
1518                                                 false);
1519                         }
1520                         break;
1521                 }
1522         }
1523
1524         if (core_dc->current_context != context) {
1525                 dc_resource_validate_ctx_destruct(core_dc->current_context);
1526                 dm_free(core_dc->current_context);
1527
1528                 core_dc->current_context = context;
1529         }
1530         return;
1531
1532 fail:
1533         dc_resource_validate_ctx_destruct(context);
1534         dm_free(context);
1535 }
1536
1537 uint8_t dc_get_current_stream_count(const struct dc *dc)
1538 {
1539         struct core_dc *core_dc = DC_TO_CORE(dc);
1540         return core_dc->current_context->stream_count;
1541 }
1542
1543 struct dc_stream *dc_get_stream_at_index(const struct dc *dc, uint8_t i)
1544 {
1545         struct core_dc *core_dc = DC_TO_CORE(dc);
1546         if (i < core_dc->current_context->stream_count)
1547                 return &(core_dc->current_context->streams[i]->public);
1548         return NULL;
1549 }
1550
1551 const struct dc_link *dc_get_link_at_index(const struct dc *dc, uint32_t link_index)
1552 {
1553         struct core_dc *core_dc = DC_TO_CORE(dc);
1554         return &core_dc->links[link_index]->public;
1555 }
1556
1557 const struct graphics_object_id dc_get_link_id_at_index(
1558         struct dc *dc, uint32_t link_index)
1559 {
1560         struct core_dc *core_dc = DC_TO_CORE(dc);
1561         return core_dc->links[link_index]->link_id;
1562 }
1563
1564 enum dc_irq_source dc_get_hpd_irq_source_at_index(
1565         struct dc *dc, uint32_t link_index)
1566 {
1567         struct core_dc *core_dc = DC_TO_CORE(dc);
1568         return core_dc->links[link_index]->public.irq_source_hpd;
1569 }
1570
1571 const struct audio **dc_get_audios(struct dc *dc)
1572 {
1573         struct core_dc *core_dc = DC_TO_CORE(dc);
1574         return (const struct audio **)core_dc->res_pool->audios;
1575 }
1576
1577 enum dc_irq_source dc_interrupt_to_irq_source(
1578                 struct dc *dc,
1579                 uint32_t src_id,
1580                 uint32_t ext_id)
1581 {
1582         struct core_dc *core_dc = DC_TO_CORE(dc);
1583         return dal_irq_service_to_irq_source(core_dc->res_pool->irqs, src_id, ext_id);
1584 }
1585
1586 void dc_interrupt_set(const struct dc *dc, enum dc_irq_source src, bool enable)
1587 {
1588         struct core_dc *core_dc;
1589
1590         if (dc == NULL)
1591                 return;
1592         core_dc = DC_TO_CORE(dc);
1593
1594         dal_irq_service_set(core_dc->res_pool->irqs, src, enable);
1595 }
1596
1597 void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src)
1598 {
1599         struct core_dc *core_dc = DC_TO_CORE(dc);
1600         dal_irq_service_ack(core_dc->res_pool->irqs, src);
1601 }
1602
1603 void dc_set_power_state(
1604         struct dc *dc,
1605         enum dc_acpi_cm_power_state power_state)
1606 {
1607         struct core_dc *core_dc = DC_TO_CORE(dc);
1608
1609         switch (power_state) {
1610         case DC_ACPI_CM_POWER_STATE_D0:
1611                 core_dc->hwss.init_hw(core_dc);
1612                 break;
1613         default:
1614
1615                 core_dc->hwss.power_down(core_dc);
1616
1617                 /* Zero out the current context so that on resume we start with
1618                  * clean state, and dc hw programming optimizations will not
1619                  * cause any trouble.
1620                  */
1621                 memset(core_dc->current_context, 0,
1622                                 sizeof(*core_dc->current_context));
1623
1624                 break;
1625         }
1626
1627 }
1628
1629 void dc_resume(const struct dc *dc)
1630 {
1631         struct core_dc *core_dc = DC_TO_CORE(dc);
1632
1633         uint32_t i;
1634
1635         for (i = 0; i < core_dc->link_count; i++)
1636                 core_link_resume(core_dc->links[i]);
1637 }
1638
1639 bool dc_read_aux_dpcd(
1640                 struct dc *dc,
1641                 uint32_t link_index,
1642                 uint32_t address,
1643                 uint8_t *data,
1644                 uint32_t size)
1645 {
1646         struct core_dc *core_dc = DC_TO_CORE(dc);
1647
1648         struct core_link *link = core_dc->links[link_index];
1649         enum ddc_result r = dal_ddc_service_read_dpcd_data(
1650                         link->public.ddc,
1651                         false,
1652                         I2C_MOT_UNDEF,
1653                         address,
1654                         data,
1655                         size);
1656         return r == DDC_RESULT_SUCESSFULL;
1657 }
1658
1659 bool dc_write_aux_dpcd(
1660                 struct dc *dc,
1661                 uint32_t link_index,
1662                 uint32_t address,
1663                 const uint8_t *data,
1664                 uint32_t size)
1665 {
1666         struct core_dc *core_dc = DC_TO_CORE(dc);
1667         struct core_link *link = core_dc->links[link_index];
1668
1669         enum ddc_result r = dal_ddc_service_write_dpcd_data(
1670                         link->public.ddc,
1671                         false,
1672                         I2C_MOT_UNDEF,
1673                         address,
1674                         data,
1675                         size);
1676         return r == DDC_RESULT_SUCESSFULL;
1677 }
1678
1679 bool dc_read_aux_i2c(
1680                 struct dc *dc,
1681                 uint32_t link_index,
1682                 enum i2c_mot_mode mot,
1683                 uint32_t address,
1684                 uint8_t *data,
1685                 uint32_t size)
1686 {
1687         struct core_dc *core_dc = DC_TO_CORE(dc);
1688
1689                 struct core_link *link = core_dc->links[link_index];
1690                 enum ddc_result r = dal_ddc_service_read_dpcd_data(
1691                         link->public.ddc,
1692                         true,
1693                         mot,
1694                         address,
1695                         data,
1696                         size);
1697                 return r == DDC_RESULT_SUCESSFULL;
1698 }
1699
1700 bool dc_write_aux_i2c(
1701                 struct dc *dc,
1702                 uint32_t link_index,
1703                 enum i2c_mot_mode mot,
1704                 uint32_t address,
1705                 const uint8_t *data,
1706                 uint32_t size)
1707 {
1708         struct core_dc *core_dc = DC_TO_CORE(dc);
1709         struct core_link *link = core_dc->links[link_index];
1710
1711         enum ddc_result r = dal_ddc_service_write_dpcd_data(
1712                         link->public.ddc,
1713                         true,
1714                         mot,
1715                         address,
1716                         data,
1717                         size);
1718         return r == DDC_RESULT_SUCESSFULL;
1719 }
1720
1721 bool dc_query_ddc_data(
1722                 struct dc *dc,
1723                 uint32_t link_index,
1724                 uint32_t address,
1725                 uint8_t *write_buf,
1726                 uint32_t write_size,
1727                 uint8_t *read_buf,
1728                 uint32_t read_size) {
1729
1730         struct core_dc *core_dc = DC_TO_CORE(dc);
1731
1732         struct core_link *link = core_dc->links[link_index];
1733
1734         bool result = dal_ddc_service_query_ddc_data(
1735                         link->public.ddc,
1736                         address,
1737                         write_buf,
1738                         write_size,
1739                         read_buf,
1740                         read_size);
1741
1742         return result;
1743 }
1744
1745 bool dc_submit_i2c(
1746                 struct dc *dc,
1747                 uint32_t link_index,
1748                 struct i2c_command *cmd)
1749 {
1750         struct core_dc *core_dc = DC_TO_CORE(dc);
1751
1752         struct core_link *link = core_dc->links[link_index];
1753         struct ddc_service *ddc = link->public.ddc;
1754
1755         return dal_i2caux_submit_i2c_command(
1756                 ddc->ctx->i2caux,
1757                 ddc->ddc_pin,
1758                 cmd);
1759 }
1760
1761 static bool link_add_remote_sink_helper(struct core_link *core_link, struct dc_sink *sink)
1762 {
1763         struct dc_link *dc_link = &core_link->public;
1764
1765         if (dc_link->sink_count >= MAX_SINKS_PER_LINK) {
1766                 BREAK_TO_DEBUGGER();
1767                 return false;
1768         }
1769
1770         dc_sink_retain(sink);
1771
1772         dc_link->remote_sinks[dc_link->sink_count] = sink;
1773         dc_link->sink_count++;
1774
1775         return true;
1776 }
1777
1778 struct dc_sink *dc_link_add_remote_sink(
1779                 const struct dc_link *link,
1780                 const uint8_t *edid,
1781                 int len,
1782                 struct dc_sink_init_data *init_data)
1783 {
1784         struct dc_sink *dc_sink;
1785         enum dc_edid_status edid_status;
1786         struct core_link *core_link = DC_LINK_TO_LINK(link);
1787
1788         if (len > MAX_EDID_BUFFER_SIZE) {
1789                 dm_error("Max EDID buffer size breached!\n");
1790                 return NULL;
1791         }
1792
1793         if (!init_data) {
1794                 BREAK_TO_DEBUGGER();
1795                 return NULL;
1796         }
1797
1798         if (!init_data->link) {
1799                 BREAK_TO_DEBUGGER();
1800                 return NULL;
1801         }
1802
1803         dc_sink = dc_sink_create(init_data);
1804
1805         if (!dc_sink)
1806                 return NULL;
1807
1808         memmove(dc_sink->dc_edid.raw_edid, edid, len);
1809         dc_sink->dc_edid.length = len;
1810
1811         if (!link_add_remote_sink_helper(
1812                         core_link,
1813                         dc_sink))
1814                 goto fail_add_sink;
1815
1816         edid_status = dm_helpers_parse_edid_caps(
1817                         core_link->ctx,
1818                         &dc_sink->dc_edid,
1819                         &dc_sink->edid_caps);
1820
1821         if (edid_status != EDID_OK)
1822                 goto fail;
1823
1824         return dc_sink;
1825 fail:
1826         dc_link_remove_remote_sink(link, dc_sink);
1827 fail_add_sink:
1828         dc_sink_release(dc_sink);
1829         return NULL;
1830 }
1831
1832 void dc_link_set_sink(const struct dc_link *link, struct dc_sink *sink)
1833 {
1834         struct core_link *core_link = DC_LINK_TO_LINK(link);
1835         struct dc_link *dc_link = &core_link->public;
1836
1837         dc_link->local_sink = sink;
1838
1839         if (sink == NULL) {
1840                 dc_link->type = dc_connection_none;
1841         } else {
1842                 dc_link->type = dc_connection_single;
1843         }
1844 }
1845
1846 void dc_link_remove_remote_sink(const struct dc_link *link, const struct dc_sink *sink)
1847 {
1848         int i;
1849         struct core_link *core_link = DC_LINK_TO_LINK(link);
1850         struct dc_link *dc_link = &core_link->public;
1851
1852         if (!link->sink_count) {
1853                 BREAK_TO_DEBUGGER();
1854                 return;
1855         }
1856
1857         for (i = 0; i < dc_link->sink_count; i++) {
1858                 if (dc_link->remote_sinks[i] == sink) {
1859                         dc_sink_release(sink);
1860                         dc_link->remote_sinks[i] = NULL;
1861
1862                         /* shrink array to remove empty place */
1863                         while (i < dc_link->sink_count - 1) {
1864                                 dc_link->remote_sinks[i] = dc_link->remote_sinks[i+1];
1865                                 i++;
1866                         }
1867                         dc_link->remote_sinks[i] = NULL;
1868                         dc_link->sink_count--;
1869                         return;
1870                 }
1871         }
1872 }
1873
1874 bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data)
1875 {
1876         int i;
1877         struct core_dc *core_dc = DC_TO_CORE(dc);
1878         struct mem_input *mi = NULL;
1879
1880         for (i = 0; i < core_dc->res_pool->pipe_count; i++) {
1881                 if (core_dc->res_pool->mis[i] != NULL) {
1882                         mi = core_dc->res_pool->mis[i];
1883                         break;
1884                 }
1885         }
1886         if (mi == NULL) {
1887                 dm_error("no mem_input!\n");
1888                 return false;
1889         }
1890
1891         if (mi->funcs->mem_input_update_dchub)
1892                 mi->funcs->mem_input_update_dchub(mi, dh_data);
1893         else
1894                 ASSERT(mi->funcs->mem_input_update_dchub);
1895
1896
1897         return true;
1898
1899 }
1900