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