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