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