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