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