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