drm/amd/display: Move output transfer function to stream updates
[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_GRPH_ARGB1555:
1055         case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
1056                 return 16;
1057         case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
1058         case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
1059         case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
1060         case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
1061                 return 32;
1062         case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
1063         case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
1064         case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
1065                 return 64;
1066         default:
1067                 ASSERT_CRITICAL(false);
1068                 return -1;
1069         }
1070 }
1071
1072 static enum surface_update_type get_plane_info_update_type(
1073                 const struct dc_surface_update *u,
1074                 int surface_index)
1075 {
1076         struct dc_plane_info temp_plane_info = { { { { 0 } } } };
1077
1078         if (!u->plane_info)
1079                 return UPDATE_TYPE_FAST;
1080
1081         /* Copy all parameters that will cause a full update
1082          * from current surface, the rest of the parameters
1083          * from provided plane configuration.
1084          * Perform memory compare and special validation
1085          * for those that can cause fast/medium updates
1086          */
1087
1088         /* Full update parameters */
1089         temp_plane_info.color_space = u->surface->color_space;
1090         temp_plane_info.dcc = u->surface->dcc;
1091         temp_plane_info.horizontal_mirror = u->surface->horizontal_mirror;
1092         temp_plane_info.plane_size = u->surface->plane_size;
1093         temp_plane_info.rotation = u->surface->rotation;
1094         temp_plane_info.stereo_format = u->surface->stereo_format;
1095         temp_plane_info.tiling_info = u->surface->tiling_info;
1096
1097         /* Special Validation parameters */
1098         temp_plane_info.format = u->plane_info->format;
1099
1100         if (surface_index == 0)
1101                 temp_plane_info.visible = u->plane_info->visible;
1102         else
1103                 temp_plane_info.visible = u->surface->visible;
1104
1105         if (memcmp(u->plane_info, &temp_plane_info,
1106                         sizeof(struct dc_plane_info)) != 0)
1107                 return UPDATE_TYPE_FULL;
1108
1109         if (pixel_format_to_bpp(u->plane_info->format) !=
1110                         pixel_format_to_bpp(u->surface->format)) {
1111                 return UPDATE_TYPE_FULL;
1112         } else {
1113                 return UPDATE_TYPE_MED;
1114         }
1115 }
1116
1117 static enum surface_update_type  get_scaling_info_update_type(
1118                 const struct dc_surface_update *u)
1119 {
1120         struct dc_scaling_info temp_scaling_info = { { 0 } };
1121
1122         if (!u->scaling_info)
1123                 return UPDATE_TYPE_FAST;
1124
1125         /* Copy all parameters that will cause a full update
1126          * from current surface, the rest of the parameters
1127          * from provided plane configuration.
1128          * Perform memory compare and special validation
1129          * for those that can cause fast/medium updates
1130          */
1131
1132         /* Full Update Parameters */
1133         temp_scaling_info.dst_rect = u->surface->dst_rect;
1134         temp_scaling_info.src_rect = u->surface->src_rect;
1135         temp_scaling_info.scaling_quality = u->surface->scaling_quality;
1136
1137         /* Special validation required */
1138         temp_scaling_info.clip_rect = u->scaling_info->clip_rect;
1139
1140         if (memcmp(u->scaling_info, &temp_scaling_info,
1141                         sizeof(struct dc_scaling_info)) != 0)
1142                 return UPDATE_TYPE_FULL;
1143
1144         /* Check Clip rectangles if not equal
1145          * difference is in offsets == > UPDATE_TYPE_MED
1146          * difference is in dimensions == > UPDATE_TYPE_FULL
1147          */
1148         if (memcmp(&u->scaling_info->clip_rect,
1149                         &u->surface->clip_rect, sizeof(struct rect)) != 0) {
1150                 if ((u->scaling_info->clip_rect.height ==
1151                         u->surface->clip_rect.height) &&
1152                         (u->scaling_info->clip_rect.width ==
1153                         u->surface->clip_rect.width)) {
1154                         return UPDATE_TYPE_MED;
1155                 } else {
1156                         return UPDATE_TYPE_FULL;
1157                 }
1158         }
1159
1160         return UPDATE_TYPE_FAST;
1161 }
1162
1163 static enum surface_update_type det_surface_update(
1164                 const struct core_dc *dc,
1165                 const struct dc_surface_update *u,
1166                 int surface_index)
1167 {
1168         const struct validate_context *context = dc->current_context;
1169         enum surface_update_type type = UPDATE_TYPE_FAST;
1170         enum surface_update_type overall_type = UPDATE_TYPE_FAST;
1171
1172         if (!is_surface_in_context(context, u->surface))
1173                 return UPDATE_TYPE_FULL;
1174
1175         type = get_plane_info_update_type(u, surface_index);
1176         if (overall_type < type)
1177                 overall_type = type;
1178
1179         type = get_scaling_info_update_type(u);
1180         if (overall_type < type)
1181                 overall_type = type;
1182
1183         if (u->in_transfer_func ||
1184                 u->hdr_static_metadata) {
1185                 if (overall_type < UPDATE_TYPE_MED)
1186                         overall_type = UPDATE_TYPE_MED;
1187         }
1188
1189         return overall_type;
1190 }
1191
1192 enum surface_update_type dc_check_update_surfaces_for_stream(
1193                 struct dc *dc,
1194                 struct dc_surface_update *updates,
1195                 int surface_count,
1196                 struct dc_stream_update *stream_update,
1197                 const struct dc_stream_status *stream_status)
1198 {
1199         struct core_dc *core_dc = DC_TO_CORE(dc);
1200         int i;
1201         enum surface_update_type overall_type = UPDATE_TYPE_FAST;
1202
1203         if (stream_status == NULL || stream_status->surface_count != surface_count)
1204                 return UPDATE_TYPE_FULL;
1205
1206         if (stream_update)
1207                 return UPDATE_TYPE_FULL;
1208
1209         for (i = 0 ; i < surface_count; i++) {
1210                 enum surface_update_type type =
1211                                 det_surface_update(core_dc, &updates[i], i);
1212
1213                 if (type == UPDATE_TYPE_FULL)
1214                         return type;
1215
1216                 if (overall_type < type)
1217                         overall_type = type;
1218         }
1219
1220         return overall_type;
1221 }
1222
1223 void dc_update_surfaces_for_stream(struct dc *dc,
1224                 struct dc_surface_update *surface_updates, int surface_count,
1225                 const struct dc_stream *dc_stream)
1226 {
1227         dc_update_surfaces_and_stream(dc, surface_updates, surface_count,
1228                         dc_stream, NULL);
1229 }
1230
1231 enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL;
1232
1233 void dc_update_surfaces_and_stream(struct dc *dc,
1234                 struct dc_surface_update *srf_updates, int surface_count,
1235                 const struct dc_stream *dc_stream,
1236                 struct dc_stream_update *stream_update)
1237 {
1238         struct core_dc *core_dc = DC_TO_CORE(dc);
1239         struct validate_context *context;
1240         int i, j;
1241         enum surface_update_type update_type;
1242         const struct dc_stream_status *stream_status;
1243         struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
1244
1245         stream_status = dc_stream_get_status(dc_stream);
1246         ASSERT(stream_status);
1247         if (!stream_status)
1248                 return; /* Cannot commit surface to stream that is not committed */
1249
1250         update_type = dc_check_update_surfaces_for_stream(
1251                         dc, srf_updates, surface_count, stream_update, stream_status);
1252
1253         if (update_type >= update_surface_trace_level)
1254                 update_surface_trace(dc, srf_updates, surface_count);
1255
1256         if (update_type >= UPDATE_TYPE_FULL) {
1257                 const struct dc_surface *new_surfaces[MAX_SURFACES] = { 0 };
1258
1259                 for (i = 0; i < surface_count; i++)
1260                         new_surfaces[i] = srf_updates[i].surface;
1261
1262                 /* initialize scratch memory for building context */
1263                 context = dm_alloc(sizeof(*context));
1264                 dc_resource_validate_ctx_copy_construct(
1265                                 core_dc->current_context, context);
1266
1267                 /* add surface to context */
1268                 if (!resource_attach_surfaces_to_context(
1269                                 new_surfaces, surface_count, dc_stream,
1270                                 context, core_dc->res_pool)) {
1271                         BREAK_TO_DEBUGGER();
1272                         goto fail;
1273                 }
1274         } else {
1275                 context = core_dc->current_context;
1276         }
1277
1278         /* update current stream with the new updates */
1279         if (stream_update) {
1280                 if ((stream_update->src.height != 0) &&
1281                                 (stream_update->src.width != 0))
1282                         stream->public.src = stream_update->src;
1283
1284                 if ((stream_update->dst.height != 0) &&
1285                                 (stream_update->dst.width != 0))
1286                         stream->public.dst = stream_update->dst;
1287
1288                 if (stream_update->out_transfer_func &&
1289                                 stream_update->out_transfer_func !=
1290                                 dc_stream->out_transfer_func) {
1291                         if (stream_update->out_transfer_func->type !=
1292                                         TF_TYPE_UNKNOWN) {
1293                                 if (dc_stream->out_transfer_func != NULL)
1294                                         dc_transfer_func_release
1295                                         (dc_stream->out_transfer_func);
1296                                 dc_transfer_func_retain(stream_update->
1297                                         out_transfer_func);
1298                                 stream->public.out_transfer_func =
1299                                         stream_update->out_transfer_func;
1300                         }
1301                 }
1302         }
1303
1304         /* save update parameters into surface */
1305         for (i = 0; i < surface_count; i++) {
1306                 struct core_surface *surface =
1307                                 DC_SURFACE_TO_CORE(srf_updates[i].surface);
1308
1309                 if (srf_updates[i].flip_addr) {
1310                         surface->public.address = srf_updates[i].flip_addr->address;
1311                         surface->public.flip_immediate =
1312                                         srf_updates[i].flip_addr->flip_immediate;
1313                 }
1314
1315                 if (srf_updates[i].scaling_info) {
1316                         surface->public.scaling_quality =
1317                                         srf_updates[i].scaling_info->scaling_quality;
1318                         surface->public.dst_rect =
1319                                         srf_updates[i].scaling_info->dst_rect;
1320                         surface->public.src_rect =
1321                                         srf_updates[i].scaling_info->src_rect;
1322                         surface->public.clip_rect =
1323                                         srf_updates[i].scaling_info->clip_rect;
1324                 }
1325
1326                 if (srf_updates[i].plane_info) {
1327                         surface->public.color_space =
1328                                         srf_updates[i].plane_info->color_space;
1329                         surface->public.format =
1330                                         srf_updates[i].plane_info->format;
1331                         surface->public.plane_size =
1332                                         srf_updates[i].plane_info->plane_size;
1333                         surface->public.rotation =
1334                                         srf_updates[i].plane_info->rotation;
1335                         surface->public.horizontal_mirror =
1336                                         srf_updates[i].plane_info->horizontal_mirror;
1337                         surface->public.stereo_format =
1338                                         srf_updates[i].plane_info->stereo_format;
1339                         surface->public.tiling_info =
1340                                         srf_updates[i].plane_info->tiling_info;
1341                         surface->public.visible =
1342                                         srf_updates[i].plane_info->visible;
1343                         surface->public.dcc =
1344                                         srf_updates[i].plane_info->dcc;
1345                 }
1346
1347                 if (update_type >= UPDATE_TYPE_MED) {
1348                         for (j = 0; j < core_dc->res_pool->pipe_count; j++) {
1349                                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
1350
1351                                 if (pipe_ctx->surface != surface)
1352                                         continue;
1353
1354                                 resource_build_scaling_params(pipe_ctx);
1355                         }
1356                 }
1357
1358                 if (srf_updates[i].gamma &&
1359                         srf_updates[i].gamma != surface->public.gamma_correction) {
1360                         if (surface->public.gamma_correction != NULL)
1361                                 dc_gamma_release(&surface->public.
1362                                                 gamma_correction);
1363
1364                         dc_gamma_retain(srf_updates[i].gamma);
1365                         surface->public.gamma_correction =
1366                                                 srf_updates[i].gamma;
1367                 }
1368
1369                 if (srf_updates[i].in_transfer_func &&
1370                         srf_updates[i].in_transfer_func != surface->public.in_transfer_func) {
1371                         if (surface->public.in_transfer_func != NULL)
1372                                 dc_transfer_func_release(
1373                                                 surface->public.
1374                                                 in_transfer_func);
1375
1376                         dc_transfer_func_retain(
1377                                         srf_updates[i].in_transfer_func);
1378                         surface->public.in_transfer_func =
1379                                         srf_updates[i].in_transfer_func;
1380                 }
1381
1382                 if (srf_updates[i].hdr_static_metadata)
1383                         surface->public.hdr_static_ctx =
1384                                 *(srf_updates[i].hdr_static_metadata);
1385         }
1386
1387         if (update_type == UPDATE_TYPE_FULL) {
1388                 if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) {
1389                         BREAK_TO_DEBUGGER();
1390                         goto fail;
1391                 } else
1392                         core_dc->hwss.set_bandwidth(core_dc, context, false);
1393         }
1394
1395         if (!surface_count)  /* reset */
1396                 core_dc->hwss.apply_ctx_for_surface(core_dc, NULL, context);
1397
1398         /* Lock pipes for provided surfaces */
1399         for (i = 0; i < surface_count; i++) {
1400                 struct core_surface *surface = DC_SURFACE_TO_CORE(srf_updates[i].surface);
1401
1402                 for (j = 0; j < core_dc->res_pool->pipe_count; j++) {
1403                         struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
1404
1405                         if (pipe_ctx->surface != surface)
1406                                 continue;
1407                         if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) {
1408                                 core_dc->hwss.pipe_control_lock(
1409                                                 core_dc,
1410                                                 pipe_ctx,
1411                                                 true);
1412                         }
1413                 }
1414         }
1415
1416         /* Perform requested Updates */
1417         for (i = 0; i < surface_count; i++) {
1418                 struct core_surface *surface = DC_SURFACE_TO_CORE(srf_updates[i].surface);
1419
1420                 if (update_type >= UPDATE_TYPE_MED) {
1421                                 core_dc->hwss.apply_ctx_for_surface(
1422                                                 core_dc, surface, context);
1423                                 context_timing_trace(dc, &context->res_ctx);
1424                 }
1425
1426                 for (j = 0; j < core_dc->res_pool->pipe_count; j++) {
1427                         struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
1428                         struct pipe_ctx *cur_pipe_ctx;
1429                         bool is_new_pipe_surface = true;
1430
1431                         if (pipe_ctx->surface != surface)
1432                                 continue;
1433
1434                         if (srf_updates[i].flip_addr)
1435                                 core_dc->hwss.update_plane_addr(core_dc, pipe_ctx);
1436
1437                         if (update_type == UPDATE_TYPE_FAST)
1438                                 continue;
1439
1440                         cur_pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[j];
1441                         if (cur_pipe_ctx->surface == pipe_ctx->surface)
1442                                 is_new_pipe_surface = false;
1443
1444                         if (is_new_pipe_surface ||
1445                                         srf_updates[i].in_transfer_func)
1446                                 core_dc->hwss.set_input_transfer_func(
1447                                                 pipe_ctx, pipe_ctx->surface);
1448
1449                         if (is_new_pipe_surface ||
1450                                 (stream_update != NULL &&
1451                                         stream_update->out_transfer_func !=
1452                                                         NULL)) {
1453                                 core_dc->hwss.set_output_transfer_func(
1454                                                 pipe_ctx, pipe_ctx->stream);
1455                         }
1456
1457                         if (srf_updates[i].hdr_static_metadata) {
1458                                 resource_build_info_frame(pipe_ctx);
1459                                 core_dc->hwss.update_info_frame(pipe_ctx);
1460                         }
1461                 }
1462         }
1463
1464         /* Unlock pipes */
1465         for (i = core_dc->res_pool->pipe_count - 1; i >= 0; i--) {
1466                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1467
1468                 for (j = 0; j < surface_count; j++) {
1469                         if (srf_updates[j].surface == &pipe_ctx->surface->public) {
1470                                 if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) {
1471                                         core_dc->hwss.pipe_control_lock(
1472                                                         core_dc,
1473                                                         pipe_ctx,
1474                                                         false);
1475                                 }
1476                                 break;
1477                         }
1478                 }
1479         }
1480
1481         if (core_dc->current_context != context) {
1482                 dc_resource_validate_ctx_destruct(core_dc->current_context);
1483                 dm_free(core_dc->current_context);
1484
1485                 core_dc->current_context = context;
1486         }
1487         return;
1488
1489 fail:
1490         dc_resource_validate_ctx_destruct(context);
1491         dm_free(context);
1492 }
1493
1494 uint8_t dc_get_current_stream_count(const struct dc *dc)
1495 {
1496         struct core_dc *core_dc = DC_TO_CORE(dc);
1497         return core_dc->current_context->stream_count;
1498 }
1499
1500 struct dc_stream *dc_get_stream_at_index(const struct dc *dc, uint8_t i)
1501 {
1502         struct core_dc *core_dc = DC_TO_CORE(dc);
1503         if (i < core_dc->current_context->stream_count)
1504                 return &(core_dc->current_context->streams[i]->public);
1505         return NULL;
1506 }
1507
1508 const struct dc_link *dc_get_link_at_index(const struct dc *dc, uint32_t link_index)
1509 {
1510         struct core_dc *core_dc = DC_TO_CORE(dc);
1511         return &core_dc->links[link_index]->public;
1512 }
1513
1514 const struct graphics_object_id dc_get_link_id_at_index(
1515         struct dc *dc, uint32_t link_index)
1516 {
1517         struct core_dc *core_dc = DC_TO_CORE(dc);
1518         return core_dc->links[link_index]->link_id;
1519 }
1520
1521 enum dc_irq_source dc_get_hpd_irq_source_at_index(
1522         struct dc *dc, uint32_t link_index)
1523 {
1524         struct core_dc *core_dc = DC_TO_CORE(dc);
1525         return core_dc->links[link_index]->public.irq_source_hpd;
1526 }
1527
1528 const struct audio **dc_get_audios(struct dc *dc)
1529 {
1530         struct core_dc *core_dc = DC_TO_CORE(dc);
1531         return (const struct audio **)core_dc->res_pool->audios;
1532 }
1533
1534 void dc_flip_surface_addrs(
1535                 struct dc *dc,
1536                 const struct dc_surface *const surfaces[],
1537                 struct dc_flip_addrs flip_addrs[],
1538                 uint32_t count)
1539 {
1540         struct core_dc *core_dc = DC_TO_CORE(dc);
1541         int i, j;
1542
1543         for (i = 0; i < count; i++) {
1544                 struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]);
1545
1546                 surface->public.address = flip_addrs[i].address;
1547                 surface->public.flip_immediate = flip_addrs[i].flip_immediate;
1548
1549                 for (j = 0; j < core_dc->res_pool->pipe_count; j++) {
1550                         struct pipe_ctx *pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[j];
1551
1552                         if (pipe_ctx->surface != surface)
1553                                 continue;
1554
1555                         core_dc->hwss.update_plane_addr(core_dc, pipe_ctx);
1556                 }
1557         }
1558 }
1559
1560 enum dc_irq_source dc_interrupt_to_irq_source(
1561                 struct dc *dc,
1562                 uint32_t src_id,
1563                 uint32_t ext_id)
1564 {
1565         struct core_dc *core_dc = DC_TO_CORE(dc);
1566         return dal_irq_service_to_irq_source(core_dc->res_pool->irqs, src_id, ext_id);
1567 }
1568
1569 void dc_interrupt_set(const struct dc *dc, enum dc_irq_source src, bool enable)
1570 {
1571         struct core_dc *core_dc = DC_TO_CORE(dc);
1572         dal_irq_service_set(core_dc->res_pool->irqs, src, enable);
1573 }
1574
1575 void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src)
1576 {
1577         struct core_dc *core_dc = DC_TO_CORE(dc);
1578         dal_irq_service_ack(core_dc->res_pool->irqs, src);
1579 }
1580
1581 void dc_set_power_state(
1582         struct dc *dc,
1583         enum dc_acpi_cm_power_state power_state)
1584 {
1585         struct core_dc *core_dc = DC_TO_CORE(dc);
1586
1587         switch (power_state) {
1588         case DC_ACPI_CM_POWER_STATE_D0:
1589                 core_dc->hwss.init_hw(core_dc);
1590                 break;
1591         default:
1592
1593                 core_dc->hwss.power_down(core_dc);
1594
1595                 /* Zero out the current context so that on resume we start with
1596                  * clean state, and dc hw programming optimizations will not
1597                  * cause any trouble.
1598                  */
1599                 memset(core_dc->current_context, 0,
1600                                 sizeof(*core_dc->current_context));
1601
1602                 break;
1603         }
1604
1605 }
1606
1607 void dc_resume(const struct dc *dc)
1608 {
1609         struct core_dc *core_dc = DC_TO_CORE(dc);
1610
1611         uint32_t i;
1612
1613         for (i = 0; i < core_dc->link_count; i++)
1614                 core_link_resume(core_dc->links[i]);
1615 }
1616
1617 bool dc_read_aux_dpcd(
1618                 struct dc *dc,
1619                 uint32_t link_index,
1620                 uint32_t address,
1621                 uint8_t *data,
1622                 uint32_t size)
1623 {
1624         struct core_dc *core_dc = DC_TO_CORE(dc);
1625
1626         struct core_link *link = core_dc->links[link_index];
1627         enum ddc_result r = dal_ddc_service_read_dpcd_data(
1628                         link->public.ddc,
1629                         false,
1630                         I2C_MOT_UNDEF,
1631                         address,
1632                         data,
1633                         size);
1634         return r == DDC_RESULT_SUCESSFULL;
1635 }
1636
1637 bool dc_write_aux_dpcd(
1638                 struct dc *dc,
1639                 uint32_t link_index,
1640                 uint32_t address,
1641                 const uint8_t *data,
1642                 uint32_t size)
1643 {
1644         struct core_dc *core_dc = DC_TO_CORE(dc);
1645         struct core_link *link = core_dc->links[link_index];
1646
1647         enum ddc_result r = dal_ddc_service_write_dpcd_data(
1648                         link->public.ddc,
1649                         false,
1650                         I2C_MOT_UNDEF,
1651                         address,
1652                         data,
1653                         size);
1654         return r == DDC_RESULT_SUCESSFULL;
1655 }
1656
1657 bool dc_read_aux_i2c(
1658                 struct dc *dc,
1659                 uint32_t link_index,
1660                 enum i2c_mot_mode mot,
1661                 uint32_t address,
1662                 uint8_t *data,
1663                 uint32_t size)
1664 {
1665         struct core_dc *core_dc = DC_TO_CORE(dc);
1666
1667                 struct core_link *link = core_dc->links[link_index];
1668                 enum ddc_result r = dal_ddc_service_read_dpcd_data(
1669                         link->public.ddc,
1670                         true,
1671                         mot,
1672                         address,
1673                         data,
1674                         size);
1675                 return r == DDC_RESULT_SUCESSFULL;
1676 }
1677
1678 bool dc_write_aux_i2c(
1679                 struct dc *dc,
1680                 uint32_t link_index,
1681                 enum i2c_mot_mode mot,
1682                 uint32_t address,
1683                 const uint8_t *data,
1684                 uint32_t size)
1685 {
1686         struct core_dc *core_dc = DC_TO_CORE(dc);
1687         struct core_link *link = core_dc->links[link_index];
1688
1689         enum ddc_result r = dal_ddc_service_write_dpcd_data(
1690                         link->public.ddc,
1691                         true,
1692                         mot,
1693                         address,
1694                         data,
1695                         size);
1696         return r == DDC_RESULT_SUCESSFULL;
1697 }
1698
1699 bool dc_query_ddc_data(
1700                 struct dc *dc,
1701                 uint32_t link_index,
1702                 uint32_t address,
1703                 uint8_t *write_buf,
1704                 uint32_t write_size,
1705                 uint8_t *read_buf,
1706                 uint32_t read_size) {
1707
1708         struct core_dc *core_dc = DC_TO_CORE(dc);
1709
1710         struct core_link *link = core_dc->links[link_index];
1711
1712         bool result = dal_ddc_service_query_ddc_data(
1713                         link->public.ddc,
1714                         address,
1715                         write_buf,
1716                         write_size,
1717                         read_buf,
1718                         read_size);
1719
1720         return result;
1721 }
1722
1723 bool dc_submit_i2c(
1724                 struct dc *dc,
1725                 uint32_t link_index,
1726                 struct i2c_command *cmd)
1727 {
1728         struct core_dc *core_dc = DC_TO_CORE(dc);
1729
1730         struct core_link *link = core_dc->links[link_index];
1731         struct ddc_service *ddc = link->public.ddc;
1732
1733         return dal_i2caux_submit_i2c_command(
1734                 ddc->ctx->i2caux,
1735                 ddc->ddc_pin,
1736                 cmd);
1737 }
1738
1739 static bool link_add_remote_sink_helper(struct core_link *core_link, struct dc_sink *sink)
1740 {
1741         struct dc_link *dc_link = &core_link->public;
1742
1743         if (dc_link->sink_count >= MAX_SINKS_PER_LINK) {
1744                 BREAK_TO_DEBUGGER();
1745                 return false;
1746         }
1747
1748         dc_sink_retain(sink);
1749
1750         dc_link->remote_sinks[dc_link->sink_count] = sink;
1751         dc_link->sink_count++;
1752
1753         return true;
1754 }
1755
1756 struct dc_sink *dc_link_add_remote_sink(
1757                 const struct dc_link *link,
1758                 const uint8_t *edid,
1759                 int len,
1760                 struct dc_sink_init_data *init_data)
1761 {
1762         struct dc_sink *dc_sink;
1763         enum dc_edid_status edid_status;
1764         struct core_link *core_link = DC_LINK_TO_LINK(link);
1765
1766         if (len > MAX_EDID_BUFFER_SIZE) {
1767                 dm_error("Max EDID buffer size breached!\n");
1768                 return NULL;
1769         }
1770
1771         if (!init_data) {
1772                 BREAK_TO_DEBUGGER();
1773                 return NULL;
1774         }
1775
1776         if (!init_data->link) {
1777                 BREAK_TO_DEBUGGER();
1778                 return NULL;
1779         }
1780
1781         dc_sink = dc_sink_create(init_data);
1782
1783         if (!dc_sink)
1784                 return NULL;
1785
1786         memmove(dc_sink->dc_edid.raw_edid, edid, len);
1787         dc_sink->dc_edid.length = len;
1788
1789         if (!link_add_remote_sink_helper(
1790                         core_link,
1791                         dc_sink))
1792                 goto fail_add_sink;
1793
1794         edid_status = dm_helpers_parse_edid_caps(
1795                         core_link->ctx,
1796                         &dc_sink->dc_edid,
1797                         &dc_sink->edid_caps);
1798
1799         if (edid_status != EDID_OK)
1800                 goto fail;
1801
1802         return dc_sink;
1803 fail:
1804         dc_link_remove_remote_sink(link, dc_sink);
1805 fail_add_sink:
1806         dc_sink_release(dc_sink);
1807         return NULL;
1808 }
1809
1810 void dc_link_set_sink(const struct dc_link *link, struct dc_sink *sink)
1811 {
1812         struct core_link *core_link = DC_LINK_TO_LINK(link);
1813         struct dc_link *dc_link = &core_link->public;
1814
1815         dc_link->local_sink = sink;
1816
1817         if (sink == NULL) {
1818                 dc_link->type = dc_connection_none;
1819         } else {
1820                 dc_link->type = dc_connection_single;
1821         }
1822 }
1823
1824 void dc_link_remove_remote_sink(const struct dc_link *link, const struct dc_sink *sink)
1825 {
1826         int i;
1827         struct core_link *core_link = DC_LINK_TO_LINK(link);
1828         struct dc_link *dc_link = &core_link->public;
1829
1830         if (!link->sink_count) {
1831                 BREAK_TO_DEBUGGER();
1832                 return;
1833         }
1834
1835         for (i = 0; i < dc_link->sink_count; i++) {
1836                 if (dc_link->remote_sinks[i] == sink) {
1837                         dc_sink_release(sink);
1838                         dc_link->remote_sinks[i] = NULL;
1839
1840                         /* shrink array to remove empty place */
1841                         while (i < dc_link->sink_count - 1) {
1842                                 dc_link->remote_sinks[i] = dc_link->remote_sinks[i+1];
1843                                 i++;
1844                         }
1845                         dc_link->remote_sinks[i] = NULL;
1846                         dc_link->sink_count--;
1847                         return;
1848                 }
1849         }
1850 }
1851
1852 bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data)
1853 {
1854         int i;
1855         struct core_dc *core_dc = DC_TO_CORE(dc);
1856         struct mem_input *mi = NULL;
1857
1858         for (i = 0; i < core_dc->res_pool->pipe_count; i++) {
1859                 if (core_dc->res_pool->mis[i] != NULL) {
1860                         mi = core_dc->res_pool->mis[i];
1861                         break;
1862                 }
1863         }
1864         if (mi == NULL) {
1865                 dm_error("no mem_input!\n");
1866                 return false;
1867         }
1868
1869         if (mi->funcs->mem_input_update_dchub)
1870                 mi->funcs->mem_input_update_dchub(mi, dh_data);
1871         else
1872                 ASSERT(mi->funcs->mem_input_update_dchub);
1873
1874
1875         return true;
1876
1877 }
1878