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