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
26 #include <linux/delay.h>
27
28 #include "dm_services.h"
29 #include "dc.h"
30 #include "dc_bios_types.h"
31 #include "core_types.h"
32 #include "core_status.h"
33 #include "resource.h"
34 #include "dm_helpers.h"
35 #include "dce110_timing_generator.h"
36 #include "dce/dce_hwseq.h"
37 #include "gpio_service_interface.h"
38
39 #include "dce110_compressor.h"
40
41 #include "bios/bios_parser_helper.h"
42 #include "timing_generator.h"
43 #include "mem_input.h"
44 #include "opp.h"
45 #include "ipp.h"
46 #include "transform.h"
47 #include "stream_encoder.h"
48 #include "link_encoder.h"
49 #include "link_hwss.h"
50 #include "dc_link_dp.h"
51 #if defined(CONFIG_DRM_AMD_DC_DCN)
52 #include "dccg.h"
53 #endif
54 #include "clock_source.h"
55 #include "clk_mgr.h"
56 #include "abm.h"
57 #include "audio.h"
58 #include "reg_helper.h"
59 #include "panel_cntl.h"
60
61 /* include DCE11 register header files */
62 #include "dce/dce_11_0_d.h"
63 #include "dce/dce_11_0_sh_mask.h"
64 #include "custom_float.h"
65
66 #include "atomfirmware.h"
67
68 #include "dcn10/dcn10_hw_sequencer.h"
69
70 #define GAMMA_HW_POINTS_NUM 256
71
72 /*
73 * All values are in milliseconds;
74 * For eDP, after power-up/power/down,
75 * 300/500 msec max. delay from LCDVCC to black video generation
76 */
77 #define PANEL_POWER_UP_TIMEOUT 300
78 #define PANEL_POWER_DOWN_TIMEOUT 500
79 #define HPD_CHECK_INTERVAL 10
80 #define OLED_POST_T7_DELAY 100
81 #define OLED_PRE_T11_DELAY 150
82
83 #define CTX \
84 hws->ctx
85
86 #define DC_LOGGER_INIT()
87
88 #define REG(reg)\
89 hws->regs->reg
90
91 #undef FN
92 #define FN(reg_name, field_name) \
93 hws->shifts->field_name, hws->masks->field_name
94
95 struct dce110_hw_seq_reg_offsets {
96 uint32_t crtc;
97 };
98
99 static const struct dce110_hw_seq_reg_offsets reg_offsets[] = {
100 {
101 .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
102 },
103 {
104 .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
105 },
106 {
107 .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
108 },
109 {
110 .crtc = (mmCRTCV_GSL_CONTROL - mmCRTC_GSL_CONTROL),
111 }
112 };
113
114 #define HW_REG_BLND(reg, id)\
115 (reg + reg_offsets[id].blnd)
116
117 #define HW_REG_CRTC(reg, id)\
118 (reg + reg_offsets[id].crtc)
119
120 #define MAX_WATERMARK 0xFFFF
121 #define SAFE_NBP_MARK 0x7FFF
122
123 /*******************************************************************************
124 * Private definitions
125 ******************************************************************************/
126 /***************************PIPE_CONTROL***********************************/
dce110_init_pte(struct dc_context * ctx)127 static void dce110_init_pte(struct dc_context *ctx)
128 {
129 uint32_t addr;
130 uint32_t value = 0;
131 uint32_t chunk_int = 0;
132 uint32_t chunk_mul = 0;
133
134 addr = mmUNP_DVMM_PTE_CONTROL;
135 value = dm_read_reg(ctx, addr);
136
137 set_reg_field_value(
138 value,
139 0,
140 DVMM_PTE_CONTROL,
141 DVMM_USE_SINGLE_PTE);
142
143 set_reg_field_value(
144 value,
145 1,
146 DVMM_PTE_CONTROL,
147 DVMM_PTE_BUFFER_MODE0);
148
149 set_reg_field_value(
150 value,
151 1,
152 DVMM_PTE_CONTROL,
153 DVMM_PTE_BUFFER_MODE1);
154
155 dm_write_reg(ctx, addr, value);
156
157 addr = mmDVMM_PTE_REQ;
158 value = dm_read_reg(ctx, addr);
159
160 chunk_int = get_reg_field_value(
161 value,
162 DVMM_PTE_REQ,
163 HFLIP_PTEREQ_PER_CHUNK_INT);
164
165 chunk_mul = get_reg_field_value(
166 value,
167 DVMM_PTE_REQ,
168 HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER);
169
170 if (chunk_int != 0x4 || chunk_mul != 0x4) {
171
172 set_reg_field_value(
173 value,
174 255,
175 DVMM_PTE_REQ,
176 MAX_PTEREQ_TO_ISSUE);
177
178 set_reg_field_value(
179 value,
180 4,
181 DVMM_PTE_REQ,
182 HFLIP_PTEREQ_PER_CHUNK_INT);
183
184 set_reg_field_value(
185 value,
186 4,
187 DVMM_PTE_REQ,
188 HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER);
189
190 dm_write_reg(ctx, addr, value);
191 }
192 }
193 /**************************************************************************/
194
enable_display_pipe_clock_gating(struct dc_context * ctx,bool clock_gating)195 static void enable_display_pipe_clock_gating(
196 struct dc_context *ctx,
197 bool clock_gating)
198 {
199 /*TODO*/
200 }
201
dce110_enable_display_power_gating(struct dc * dc,uint8_t controller_id,struct dc_bios * dcb,enum pipe_gating_control power_gating)202 static bool dce110_enable_display_power_gating(
203 struct dc *dc,
204 uint8_t controller_id,
205 struct dc_bios *dcb,
206 enum pipe_gating_control power_gating)
207 {
208 enum bp_result bp_result = BP_RESULT_OK;
209 enum bp_pipe_control_action cntl;
210 struct dc_context *ctx = dc->ctx;
211 unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
212
213 if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment))
214 return true;
215
216 if (power_gating == PIPE_GATING_CONTROL_INIT)
217 cntl = ASIC_PIPE_INIT;
218 else if (power_gating == PIPE_GATING_CONTROL_ENABLE)
219 cntl = ASIC_PIPE_ENABLE;
220 else
221 cntl = ASIC_PIPE_DISABLE;
222
223 if (controller_id == underlay_idx)
224 controller_id = CONTROLLER_ID_UNDERLAY0 - 1;
225
226 if (power_gating != PIPE_GATING_CONTROL_INIT || controller_id == 0){
227
228 bp_result = dcb->funcs->enable_disp_power_gating(
229 dcb, controller_id + 1, cntl);
230
231 /* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2
232 * by default when command table is called
233 *
234 * Bios parser accepts controller_id = 6 as indicative of
235 * underlay pipe in dce110. But we do not support more
236 * than 3.
237 */
238 if (controller_id < CONTROLLER_ID_MAX - 1)
239 dm_write_reg(ctx,
240 HW_REG_CRTC(mmCRTC_MASTER_UPDATE_MODE, controller_id),
241 0);
242 }
243
244 if (power_gating != PIPE_GATING_CONTROL_ENABLE)
245 dce110_init_pte(ctx);
246
247 if (bp_result == BP_RESULT_OK)
248 return true;
249 else
250 return false;
251 }
252
build_prescale_params(struct ipp_prescale_params * prescale_params,const struct dc_plane_state * plane_state)253 static void build_prescale_params(struct ipp_prescale_params *prescale_params,
254 const struct dc_plane_state *plane_state)
255 {
256 prescale_params->mode = IPP_PRESCALE_MODE_FIXED_UNSIGNED;
257
258 switch (plane_state->format) {
259 case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
260 prescale_params->scale = 0x2082;
261 break;
262 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
263 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
264 prescale_params->scale = 0x2020;
265 break;
266 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
267 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
268 prescale_params->scale = 0x2008;
269 break;
270 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
271 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616:
272 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
273 prescale_params->scale = 0x2000;
274 break;
275 default:
276 ASSERT(false);
277 break;
278 }
279 }
280
281 static bool
dce110_set_input_transfer_func(struct dc * dc,struct pipe_ctx * pipe_ctx,const struct dc_plane_state * plane_state)282 dce110_set_input_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx,
283 const struct dc_plane_state *plane_state)
284 {
285 struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp;
286 const struct dc_transfer_func *tf = NULL;
287 struct ipp_prescale_params prescale_params = { 0 };
288 bool result = true;
289
290 if (ipp == NULL)
291 return false;
292
293 if (plane_state->in_transfer_func)
294 tf = plane_state->in_transfer_func;
295
296 build_prescale_params(&prescale_params, plane_state);
297 ipp->funcs->ipp_program_prescale(ipp, &prescale_params);
298
299 if (plane_state->gamma_correction &&
300 !plane_state->gamma_correction->is_identity &&
301 dce_use_lut(plane_state->format))
302 ipp->funcs->ipp_program_input_lut(ipp, plane_state->gamma_correction);
303
304 if (tf == NULL) {
305 /* Default case if no input transfer function specified */
306 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB);
307 } else if (tf->type == TF_TYPE_PREDEFINED) {
308 switch (tf->tf) {
309 case TRANSFER_FUNCTION_SRGB:
310 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB);
311 break;
312 case TRANSFER_FUNCTION_BT709:
313 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_xvYCC);
314 break;
315 case TRANSFER_FUNCTION_LINEAR:
316 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS);
317 break;
318 case TRANSFER_FUNCTION_PQ:
319 default:
320 result = false;
321 break;
322 }
323 } else if (tf->type == TF_TYPE_BYPASS) {
324 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS);
325 } else {
326 /*TF_TYPE_DISTRIBUTED_POINTS - Not supported in DCE 11*/
327 result = false;
328 }
329
330 return result;
331 }
332
convert_to_custom_float(struct pwl_result_data * rgb_resulted,struct curve_points * arr_points,uint32_t hw_points_num)333 static bool convert_to_custom_float(struct pwl_result_data *rgb_resulted,
334 struct curve_points *arr_points,
335 uint32_t hw_points_num)
336 {
337 struct custom_float_format fmt;
338
339 struct pwl_result_data *rgb = rgb_resulted;
340
341 uint32_t i = 0;
342
343 fmt.exponenta_bits = 6;
344 fmt.mantissa_bits = 12;
345 fmt.sign = true;
346
347 if (!convert_to_custom_float_format(arr_points[0].x, &fmt,
348 &arr_points[0].custom_float_x)) {
349 BREAK_TO_DEBUGGER();
350 return false;
351 }
352
353 if (!convert_to_custom_float_format(arr_points[0].offset, &fmt,
354 &arr_points[0].custom_float_offset)) {
355 BREAK_TO_DEBUGGER();
356 return false;
357 }
358
359 if (!convert_to_custom_float_format(arr_points[0].slope, &fmt,
360 &arr_points[0].custom_float_slope)) {
361 BREAK_TO_DEBUGGER();
362 return false;
363 }
364
365 fmt.mantissa_bits = 10;
366 fmt.sign = false;
367
368 if (!convert_to_custom_float_format(arr_points[1].x, &fmt,
369 &arr_points[1].custom_float_x)) {
370 BREAK_TO_DEBUGGER();
371 return false;
372 }
373
374 if (!convert_to_custom_float_format(arr_points[1].y, &fmt,
375 &arr_points[1].custom_float_y)) {
376 BREAK_TO_DEBUGGER();
377 return false;
378 }
379
380 if (!convert_to_custom_float_format(arr_points[1].slope, &fmt,
381 &arr_points[1].custom_float_slope)) {
382 BREAK_TO_DEBUGGER();
383 return false;
384 }
385
386 fmt.mantissa_bits = 12;
387 fmt.sign = true;
388
389 while (i != hw_points_num) {
390 if (!convert_to_custom_float_format(rgb->red, &fmt,
391 &rgb->red_reg)) {
392 BREAK_TO_DEBUGGER();
393 return false;
394 }
395
396 if (!convert_to_custom_float_format(rgb->green, &fmt,
397 &rgb->green_reg)) {
398 BREAK_TO_DEBUGGER();
399 return false;
400 }
401
402 if (!convert_to_custom_float_format(rgb->blue, &fmt,
403 &rgb->blue_reg)) {
404 BREAK_TO_DEBUGGER();
405 return false;
406 }
407
408 if (!convert_to_custom_float_format(rgb->delta_red, &fmt,
409 &rgb->delta_red_reg)) {
410 BREAK_TO_DEBUGGER();
411 return false;
412 }
413
414 if (!convert_to_custom_float_format(rgb->delta_green, &fmt,
415 &rgb->delta_green_reg)) {
416 BREAK_TO_DEBUGGER();
417 return false;
418 }
419
420 if (!convert_to_custom_float_format(rgb->delta_blue, &fmt,
421 &rgb->delta_blue_reg)) {
422 BREAK_TO_DEBUGGER();
423 return false;
424 }
425
426 ++rgb;
427 ++i;
428 }
429
430 return true;
431 }
432
433 #define MAX_LOW_POINT 25
434 #define NUMBER_REGIONS 16
435 #define NUMBER_SW_SEGMENTS 16
436
437 static bool
dce110_translate_regamma_to_hw_format(const struct dc_transfer_func * output_tf,struct pwl_params * regamma_params)438 dce110_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf,
439 struct pwl_params *regamma_params)
440 {
441 struct curve_points *arr_points;
442 struct pwl_result_data *rgb_resulted;
443 struct pwl_result_data *rgb;
444 struct pwl_result_data *rgb_plus_1;
445 struct fixed31_32 y_r;
446 struct fixed31_32 y_g;
447 struct fixed31_32 y_b;
448 struct fixed31_32 y1_min;
449 struct fixed31_32 y3_max;
450
451 int32_t region_start, region_end;
452 uint32_t i, j, k, seg_distr[NUMBER_REGIONS], increment, start_index, hw_points;
453
454 if (output_tf == NULL || regamma_params == NULL || output_tf->type == TF_TYPE_BYPASS)
455 return false;
456
457 arr_points = regamma_params->arr_points;
458 rgb_resulted = regamma_params->rgb_resulted;
459 hw_points = 0;
460
461 memset(regamma_params, 0, sizeof(struct pwl_params));
462
463 if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
464 /* 16 segments
465 * segments are from 2^-11 to 2^5
466 */
467 region_start = -11;
468 region_end = region_start + NUMBER_REGIONS;
469
470 for (i = 0; i < NUMBER_REGIONS; i++)
471 seg_distr[i] = 4;
472
473 } else {
474 /* 10 segments
475 * segment is from 2^-10 to 2^1
476 * We include an extra segment for range [2^0, 2^1). This is to
477 * ensure that colors with normalized values of 1 don't miss the
478 * LUT.
479 */
480 region_start = -10;
481 region_end = 1;
482
483 seg_distr[0] = 4;
484 seg_distr[1] = 4;
485 seg_distr[2] = 4;
486 seg_distr[3] = 4;
487 seg_distr[4] = 4;
488 seg_distr[5] = 4;
489 seg_distr[6] = 4;
490 seg_distr[7] = 4;
491 seg_distr[8] = 4;
492 seg_distr[9] = 4;
493 seg_distr[10] = 0;
494 seg_distr[11] = -1;
495 seg_distr[12] = -1;
496 seg_distr[13] = -1;
497 seg_distr[14] = -1;
498 seg_distr[15] = -1;
499 }
500
501 for (k = 0; k < 16; k++) {
502 if (seg_distr[k] != -1)
503 hw_points += (1 << seg_distr[k]);
504 }
505
506 j = 0;
507 for (k = 0; k < (region_end - region_start); k++) {
508 increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]);
509 start_index = (region_start + k + MAX_LOW_POINT) *
510 NUMBER_SW_SEGMENTS;
511 for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS;
512 i += increment) {
513 if (j == hw_points - 1)
514 break;
515 rgb_resulted[j].red = output_tf->tf_pts.red[i];
516 rgb_resulted[j].green = output_tf->tf_pts.green[i];
517 rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
518 j++;
519 }
520 }
521
522 /* last point */
523 start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS;
524 rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index];
525 rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index];
526 rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index];
527
528 arr_points[0].x = dc_fixpt_pow(dc_fixpt_from_int(2),
529 dc_fixpt_from_int(region_start));
530 arr_points[1].x = dc_fixpt_pow(dc_fixpt_from_int(2),
531 dc_fixpt_from_int(region_end));
532
533 y_r = rgb_resulted[0].red;
534 y_g = rgb_resulted[0].green;
535 y_b = rgb_resulted[0].blue;
536
537 y1_min = dc_fixpt_min(y_r, dc_fixpt_min(y_g, y_b));
538
539 arr_points[0].y = y1_min;
540 arr_points[0].slope = dc_fixpt_div(arr_points[0].y,
541 arr_points[0].x);
542
543 y_r = rgb_resulted[hw_points - 1].red;
544 y_g = rgb_resulted[hw_points - 1].green;
545 y_b = rgb_resulted[hw_points - 1].blue;
546
547 /* see comment above, m_arrPoints[1].y should be the Y value for the
548 * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)
549 */
550 y3_max = dc_fixpt_max(y_r, dc_fixpt_max(y_g, y_b));
551
552 arr_points[1].y = y3_max;
553
554 arr_points[1].slope = dc_fixpt_zero;
555
556 if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
557 /* for PQ, we want to have a straight line from last HW X point,
558 * and the slope to be such that we hit 1.0 at 10000 nits.
559 */
560 const struct fixed31_32 end_value = dc_fixpt_from_int(125);
561
562 arr_points[1].slope = dc_fixpt_div(
563 dc_fixpt_sub(dc_fixpt_one, arr_points[1].y),
564 dc_fixpt_sub(end_value, arr_points[1].x));
565 }
566
567 regamma_params->hw_points_num = hw_points;
568
569 k = 0;
570 for (i = 1; i < 16; i++) {
571 if (seg_distr[k] != -1) {
572 regamma_params->arr_curve_points[k].segments_num = seg_distr[k];
573 regamma_params->arr_curve_points[i].offset =
574 regamma_params->arr_curve_points[k].offset + (1 << seg_distr[k]);
575 }
576 k++;
577 }
578
579 if (seg_distr[k] != -1)
580 regamma_params->arr_curve_points[k].segments_num = seg_distr[k];
581
582 rgb = rgb_resulted;
583 rgb_plus_1 = rgb_resulted + 1;
584
585 i = 1;
586
587 while (i != hw_points + 1) {
588 if (dc_fixpt_lt(rgb_plus_1->red, rgb->red))
589 rgb_plus_1->red = rgb->red;
590 if (dc_fixpt_lt(rgb_plus_1->green, rgb->green))
591 rgb_plus_1->green = rgb->green;
592 if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue))
593 rgb_plus_1->blue = rgb->blue;
594
595 rgb->delta_red = dc_fixpt_sub(rgb_plus_1->red, rgb->red);
596 rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green);
597 rgb->delta_blue = dc_fixpt_sub(rgb_plus_1->blue, rgb->blue);
598
599 ++rgb_plus_1;
600 ++rgb;
601 ++i;
602 }
603
604 convert_to_custom_float(rgb_resulted, arr_points, hw_points);
605
606 return true;
607 }
608
609 static bool
dce110_set_output_transfer_func(struct dc * dc,struct pipe_ctx * pipe_ctx,const struct dc_stream_state * stream)610 dce110_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx,
611 const struct dc_stream_state *stream)
612 {
613 struct transform *xfm = pipe_ctx->plane_res.xfm;
614
615 xfm->funcs->opp_power_on_regamma_lut(xfm, true);
616 xfm->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM;
617
618 if (stream->out_transfer_func &&
619 stream->out_transfer_func->type == TF_TYPE_PREDEFINED &&
620 stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) {
621 xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_SRGB);
622 } else if (dce110_translate_regamma_to_hw_format(stream->out_transfer_func,
623 &xfm->regamma_params)) {
624 xfm->funcs->opp_program_regamma_pwl(xfm, &xfm->regamma_params);
625 xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_USER);
626 } else {
627 xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_BYPASS);
628 }
629
630 xfm->funcs->opp_power_on_regamma_lut(xfm, false);
631
632 return true;
633 }
634
dce110_update_info_frame(struct pipe_ctx * pipe_ctx)635 void dce110_update_info_frame(struct pipe_ctx *pipe_ctx)
636 {
637 bool is_hdmi_tmds;
638 bool is_dp;
639
640 ASSERT(pipe_ctx->stream);
641
642 if (pipe_ctx->stream_res.stream_enc == NULL)
643 return; /* this is not root pipe */
644
645 is_hdmi_tmds = dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal);
646 is_dp = dc_is_dp_signal(pipe_ctx->stream->signal);
647
648 if (!is_hdmi_tmds && !is_dp)
649 return;
650
651 if (is_hdmi_tmds)
652 pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets(
653 pipe_ctx->stream_res.stream_enc,
654 &pipe_ctx->stream_res.encoder_info_frame);
655 else
656 pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets(
657 pipe_ctx->stream_res.stream_enc,
658 &pipe_ctx->stream_res.encoder_info_frame);
659 }
660
dce110_enable_stream(struct pipe_ctx * pipe_ctx)661 void dce110_enable_stream(struct pipe_ctx *pipe_ctx)
662 {
663 enum dc_lane_count lane_count =
664 pipe_ctx->stream->link->cur_link_settings.lane_count;
665 struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
666 struct dc_link *link = pipe_ctx->stream->link;
667 const struct dc *dc = link->dc;
668
669 uint32_t active_total_with_borders;
670 uint32_t early_control = 0;
671 struct timing_generator *tg = pipe_ctx->stream_res.tg;
672
673 /* For MST, there are multiply stream go to only one link.
674 * connect DIG back_end to front_end while enable_stream and
675 * disconnect them during disable_stream
676 * BY this, it is logic clean to separate stream and link */
677 link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
678 pipe_ctx->stream_res.stream_enc->id, true);
679
680 dc->hwss.update_info_frame(pipe_ctx);
681
682 /* enable early control to avoid corruption on DP monitor*/
683 active_total_with_borders =
684 timing->h_addressable
685 + timing->h_border_left
686 + timing->h_border_right;
687
688 if (lane_count != 0)
689 early_control = active_total_with_borders % lane_count;
690
691 if (early_control == 0)
692 early_control = lane_count;
693
694 tg->funcs->set_early_control(tg, early_control);
695
696 /* enable audio only within mode set */
697 if (pipe_ctx->stream_res.audio != NULL) {
698 if (dc_is_dp_signal(pipe_ctx->stream->signal))
699 pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc);
700 }
701
702
703
704
705 }
706
link_transmitter_control(struct dc_bios * bios,struct bp_transmitter_control * cntl)707 static enum bp_result link_transmitter_control(
708 struct dc_bios *bios,
709 struct bp_transmitter_control *cntl)
710 {
711 enum bp_result result;
712
713 result = bios->funcs->transmitter_control(bios, cntl);
714
715 return result;
716 }
717
718 /*
719 * @brief
720 * eDP only.
721 */
dce110_edp_wait_for_hpd_ready(struct dc_link * link,bool power_up)722 void dce110_edp_wait_for_hpd_ready(
723 struct dc_link *link,
724 bool power_up)
725 {
726 struct dc_context *ctx = link->ctx;
727 struct graphics_object_id connector = link->link_enc->connector;
728 struct gpio *hpd;
729 struct dc_sink *sink = link->local_sink;
730 bool edp_hpd_high = false;
731 uint32_t time_elapsed = 0;
732 uint32_t timeout = power_up ?
733 PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT;
734
735 if (dal_graphics_object_id_get_connector_id(connector)
736 != CONNECTOR_ID_EDP) {
737 BREAK_TO_DEBUGGER();
738 return;
739 }
740
741 if (!power_up)
742 /*
743 * From KV, we will not HPD low after turning off VCC -
744 * instead, we will check the SW timer in power_up().
745 */
746 return;
747
748 /*
749 * When we power on/off the eDP panel,
750 * we need to wait until SENSE bit is high/low.
751 */
752
753 /* obtain HPD */
754 /* TODO what to do with this? */
755 hpd = get_hpd_gpio(ctx->dc_bios, connector, ctx->gpio_service);
756
757 if (!hpd) {
758 BREAK_TO_DEBUGGER();
759 return;
760 }
761
762 if (sink != NULL) {
763 if (sink->edid_caps.panel_patch.extra_t3_ms > 0) {
764 int extra_t3_in_ms = sink->edid_caps.panel_patch.extra_t3_ms;
765
766 msleep(extra_t3_in_ms);
767 }
768 }
769
770 dal_gpio_open(hpd, GPIO_MODE_INTERRUPT);
771
772 /* wait until timeout or panel detected */
773
774 do {
775 uint32_t detected = 0;
776
777 dal_gpio_get_value(hpd, &detected);
778
779 if (!(detected ^ power_up)) {
780 edp_hpd_high = true;
781 break;
782 }
783
784 msleep(HPD_CHECK_INTERVAL);
785
786 time_elapsed += HPD_CHECK_INTERVAL;
787 } while (time_elapsed < timeout);
788
789 dal_gpio_close(hpd);
790
791 dal_gpio_destroy_irq(&hpd);
792
793 if (false == edp_hpd_high) {
794 DC_LOG_ERROR(
795 "%s: wait timed out!\n", __func__);
796 }
797 }
798
dce110_edp_power_control(struct dc_link * link,bool power_up)799 void dce110_edp_power_control(
800 struct dc_link *link,
801 bool power_up)
802 {
803 struct dc_context *ctx = link->ctx;
804 struct bp_transmitter_control cntl = { 0 };
805 enum bp_result bp_result;
806 uint8_t panel_instance;
807
808
809 if (dal_graphics_object_id_get_connector_id(link->link_enc->connector)
810 != CONNECTOR_ID_EDP) {
811 BREAK_TO_DEBUGGER();
812 return;
813 }
814
815 if (!link->panel_cntl)
816 return;
817 if (power_up !=
818 link->panel_cntl->funcs->is_panel_powered_on(link->panel_cntl)) {
819
820 unsigned long long current_ts = dm_get_timestamp(ctx);
821 unsigned long long time_since_edp_poweroff_ms =
822 div64_u64(dm_get_elapse_time_in_ns(
823 ctx,
824 current_ts,
825 link->link_trace.time_stamp.edp_poweroff), 1000000);
826 unsigned long long time_since_edp_poweron_ms =
827 div64_u64(dm_get_elapse_time_in_ns(
828 ctx,
829 current_ts,
830 link->link_trace.time_stamp.edp_poweron), 1000000);
831 DC_LOG_HW_RESUME_S3(
832 "%s: transition: power_up=%d current_ts=%llu edp_poweroff=%llu edp_poweron=%llu time_since_edp_poweroff_ms=%llu time_since_edp_poweron_ms=%llu",
833 __func__,
834 power_up,
835 current_ts,
836 link->link_trace.time_stamp.edp_poweroff,
837 link->link_trace.time_stamp.edp_poweron,
838 time_since_edp_poweroff_ms,
839 time_since_edp_poweron_ms);
840
841 /* Send VBIOS command to prompt eDP panel power */
842 if (power_up) {
843 /* edp requires a min of 500ms from LCDVDD off to on */
844 unsigned long long remaining_min_edp_poweroff_time_ms = 500;
845
846 /* add time defined by a patch, if any (usually patch extra_t12_ms is 0) */
847 if (link->local_sink != NULL)
848 remaining_min_edp_poweroff_time_ms +=
849 link->local_sink->edid_caps.panel_patch.extra_t12_ms;
850
851 /* Adjust remaining_min_edp_poweroff_time_ms if this is not the first time. */
852 if (link->link_trace.time_stamp.edp_poweroff != 0) {
853 if (time_since_edp_poweroff_ms < remaining_min_edp_poweroff_time_ms)
854 remaining_min_edp_poweroff_time_ms =
855 remaining_min_edp_poweroff_time_ms - time_since_edp_poweroff_ms;
856 else
857 remaining_min_edp_poweroff_time_ms = 0;
858 }
859
860 if (remaining_min_edp_poweroff_time_ms) {
861 DC_LOG_HW_RESUME_S3(
862 "%s: remaining_min_edp_poweroff_time_ms=%llu: begin wait.\n",
863 __func__, remaining_min_edp_poweroff_time_ms);
864 msleep(remaining_min_edp_poweroff_time_ms);
865 DC_LOG_HW_RESUME_S3(
866 "%s: remaining_min_edp_poweroff_time_ms=%llu: end wait.\n",
867 __func__, remaining_min_edp_poweroff_time_ms);
868 dm_output_to_console("%s: wait %lld ms to power on eDP.\n",
869 __func__, remaining_min_edp_poweroff_time_ms);
870 } else {
871 DC_LOG_HW_RESUME_S3(
872 "%s: remaining_min_edp_poweroff_time_ms=%llu: no wait required.\n",
873 __func__, remaining_min_edp_poweroff_time_ms);
874 }
875 }
876
877 DC_LOG_HW_RESUME_S3(
878 "%s: BEGIN: Panel Power action: %s\n",
879 __func__, (power_up ? "On":"Off"));
880
881 cntl.action = power_up ?
882 TRANSMITTER_CONTROL_POWER_ON :
883 TRANSMITTER_CONTROL_POWER_OFF;
884 cntl.transmitter = link->link_enc->transmitter;
885 cntl.connector_obj_id = link->link_enc->connector;
886 cntl.coherent = false;
887 cntl.lanes_number = LANE_COUNT_FOUR;
888 cntl.hpd_sel = link->link_enc->hpd_source;
889 panel_instance = link->panel_cntl->inst;
890
891 if (ctx->dc->ctx->dmub_srv &&
892 ctx->dc->debug.dmub_command_table) {
893 if (cntl.action == TRANSMITTER_CONTROL_POWER_ON)
894 bp_result = ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios,
895 LVTMA_CONTROL_POWER_ON,
896 panel_instance);
897 else
898 bp_result = ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios,
899 LVTMA_CONTROL_POWER_OFF,
900 panel_instance);
901 }
902
903 bp_result = link_transmitter_control(ctx->dc_bios, &cntl);
904
905 DC_LOG_HW_RESUME_S3(
906 "%s: END: Panel Power action: %s bp_result=%u\n",
907 __func__, (power_up ? "On":"Off"),
908 bp_result);
909
910 if (!power_up)
911 /*save driver power off time stamp*/
912 link->link_trace.time_stamp.edp_poweroff = dm_get_timestamp(ctx);
913 else
914 link->link_trace.time_stamp.edp_poweron = dm_get_timestamp(ctx);
915
916 DC_LOG_HW_RESUME_S3(
917 "%s: updated values: edp_poweroff=%llu edp_poweron=%llu\n",
918 __func__,
919 link->link_trace.time_stamp.edp_poweroff,
920 link->link_trace.time_stamp.edp_poweron);
921
922 if (bp_result != BP_RESULT_OK)
923 DC_LOG_ERROR(
924 "%s: Panel Power bp_result: %d\n",
925 __func__, bp_result);
926 } else {
927 DC_LOG_HW_RESUME_S3(
928 "%s: Skipping Panel Power action: %s\n",
929 __func__, (power_up ? "On":"Off"));
930 }
931 }
932
dce110_edp_wait_for_T12(struct dc_link * link)933 void dce110_edp_wait_for_T12(
934 struct dc_link *link)
935 {
936 struct dc_context *ctx = link->ctx;
937
938 if (dal_graphics_object_id_get_connector_id(link->link_enc->connector)
939 != CONNECTOR_ID_EDP) {
940 BREAK_TO_DEBUGGER();
941 return;
942 }
943
944 if (!link->panel_cntl)
945 return;
946
947 if (!link->panel_cntl->funcs->is_panel_powered_on(link->panel_cntl) &&
948 link->link_trace.time_stamp.edp_poweroff != 0) {
949 unsigned int t12_duration = 500; // Default T12 as per spec
950 unsigned long long current_ts = dm_get_timestamp(ctx);
951 unsigned long long time_since_edp_poweroff_ms =
952 div64_u64(dm_get_elapse_time_in_ns(
953 ctx,
954 current_ts,
955 link->link_trace.time_stamp.edp_poweroff), 1000000);
956
957 t12_duration += link->local_sink->edid_caps.panel_patch.extra_t12_ms; // Add extra T12
958
959 if (time_since_edp_poweroff_ms < t12_duration)
960 msleep(t12_duration - time_since_edp_poweroff_ms);
961 }
962 }
963
964 /*todo: cloned in stream enc, fix*/
965 /*
966 * @brief
967 * eDP only. Control the backlight of the eDP panel
968 */
dce110_edp_backlight_control(struct dc_link * link,bool enable)969 void dce110_edp_backlight_control(
970 struct dc_link *link,
971 bool enable)
972 {
973 struct dc_context *ctx = link->ctx;
974 struct bp_transmitter_control cntl = { 0 };
975 uint8_t panel_instance;
976
977 if (dal_graphics_object_id_get_connector_id(link->link_enc->connector)
978 != CONNECTOR_ID_EDP) {
979 BREAK_TO_DEBUGGER();
980 return;
981 }
982
983 if (link->panel_cntl && !(link->dpcd_sink_ext_caps.bits.oled ||
984 link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1 ||
985 link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1)) {
986 bool is_backlight_on = link->panel_cntl->funcs->is_panel_backlight_on(link->panel_cntl);
987
988 if ((enable && is_backlight_on) || (!enable && !is_backlight_on)) {
989 DC_LOG_HW_RESUME_S3(
990 "%s: panel already powered up/off. Do nothing.\n",
991 __func__);
992 return;
993 }
994 }
995
996 /* Send VBIOS command to control eDP panel backlight */
997
998 DC_LOG_HW_RESUME_S3(
999 "%s: backlight action: %s\n",
1000 __func__, (enable ? "On":"Off"));
1001
1002 cntl.action = enable ?
1003 TRANSMITTER_CONTROL_BACKLIGHT_ON :
1004 TRANSMITTER_CONTROL_BACKLIGHT_OFF;
1005
1006 /*cntl.engine_id = ctx->engine;*/
1007 cntl.transmitter = link->link_enc->transmitter;
1008 cntl.connector_obj_id = link->link_enc->connector;
1009 /*todo: unhardcode*/
1010 cntl.lanes_number = LANE_COUNT_FOUR;
1011 cntl.hpd_sel = link->link_enc->hpd_source;
1012 cntl.signal = SIGNAL_TYPE_EDP;
1013
1014 /* For eDP, the following delays might need to be considered
1015 * after link training completed:
1016 * idle period - min. accounts for required BS-Idle pattern,
1017 * max. allows for source frame synchronization);
1018 * 50 msec max. delay from valid video data from source
1019 * to video on dislpay or backlight enable.
1020 *
1021 * Disable the delay for now.
1022 * Enable it in the future if necessary.
1023 */
1024 /* dc_service_sleep_in_milliseconds(50); */
1025 /*edp 1.2*/
1026 panel_instance = link->panel_cntl->inst;
1027
1028 if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON) {
1029 if (!link->dc->config.edp_no_power_sequencing)
1030 /*
1031 * Sometimes, DP receiver chip power-controlled externally by an
1032 * Embedded Controller could be treated and used as eDP,
1033 * if it drives mobile display. In this case,
1034 * we shouldn't be doing power-sequencing, hence we can skip
1035 * waiting for T7-ready.
1036 */
1037 edp_receiver_ready_T7(link);
1038 else
1039 DC_LOG_DC("edp_receiver_ready_T7 skipped\n");
1040 }
1041
1042 if (ctx->dc->ctx->dmub_srv &&
1043 ctx->dc->debug.dmub_command_table) {
1044 if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON)
1045 ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios,
1046 LVTMA_CONTROL_LCD_BLON,
1047 panel_instance);
1048 else
1049 ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios,
1050 LVTMA_CONTROL_LCD_BLOFF,
1051 panel_instance);
1052 }
1053
1054 link_transmitter_control(ctx->dc_bios, &cntl);
1055
1056 if (enable && link->dpcd_sink_ext_caps.bits.oled)
1057 msleep(OLED_POST_T7_DELAY);
1058
1059 if (link->dpcd_sink_ext_caps.bits.oled ||
1060 link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1 ||
1061 link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1)
1062 dc_link_backlight_enable_aux(link, enable);
1063
1064 /*edp 1.2*/
1065 if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_OFF) {
1066 if (!link->dc->config.edp_no_power_sequencing)
1067 /*
1068 * Sometimes, DP receiver chip power-controlled externally by an
1069 * Embedded Controller could be treated and used as eDP,
1070 * if it drives mobile display. In this case,
1071 * we shouldn't be doing power-sequencing, hence we can skip
1072 * waiting for T9-ready.
1073 */
1074 edp_add_delay_for_T9(link);
1075 else
1076 DC_LOG_DC("edp_receiver_ready_T9 skipped\n");
1077 }
1078
1079 if (!enable && link->dpcd_sink_ext_caps.bits.oled)
1080 msleep(OLED_PRE_T11_DELAY);
1081 }
1082
dce110_enable_audio_stream(struct pipe_ctx * pipe_ctx)1083 void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx)
1084 {
1085 /* notify audio driver for audio modes of monitor */
1086 struct dc *dc;
1087 struct clk_mgr *clk_mgr;
1088 unsigned int i, num_audio = 1;
1089
1090 if (!pipe_ctx->stream)
1091 return;
1092
1093 dc = pipe_ctx->stream->ctx->dc;
1094 clk_mgr = dc->clk_mgr;
1095
1096 if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == true)
1097 return;
1098
1099 if (pipe_ctx->stream_res.audio) {
1100 for (i = 0; i < MAX_PIPES; i++) {
1101 /*current_state not updated yet*/
1102 if (dc->current_state->res_ctx.pipe_ctx[i].stream_res.audio != NULL)
1103 num_audio++;
1104 }
1105
1106 pipe_ctx->stream_res.audio->funcs->az_enable(pipe_ctx->stream_res.audio);
1107
1108 if (num_audio >= 1 && clk_mgr->funcs->enable_pme_wa)
1109 /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/
1110 clk_mgr->funcs->enable_pme_wa(clk_mgr);
1111 /* un-mute audio */
1112 /* TODO: audio should be per stream rather than per link */
1113 pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
1114 pipe_ctx->stream_res.stream_enc, false);
1115 if (pipe_ctx->stream_res.audio)
1116 pipe_ctx->stream_res.audio->enabled = true;
1117 }
1118 }
1119
dce110_disable_audio_stream(struct pipe_ctx * pipe_ctx)1120 void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx)
1121 {
1122 struct dc *dc;
1123 struct clk_mgr *clk_mgr;
1124
1125 if (!pipe_ctx || !pipe_ctx->stream)
1126 return;
1127
1128 dc = pipe_ctx->stream->ctx->dc;
1129 clk_mgr = dc->clk_mgr;
1130
1131 if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == false)
1132 return;
1133
1134 pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
1135 pipe_ctx->stream_res.stream_enc, true);
1136 if (pipe_ctx->stream_res.audio) {
1137 pipe_ctx->stream_res.audio->enabled = false;
1138
1139 if (dc_is_dp_signal(pipe_ctx->stream->signal))
1140 pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable(
1141 pipe_ctx->stream_res.stream_enc);
1142 else
1143 pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable(
1144 pipe_ctx->stream_res.stream_enc);
1145
1146 if (clk_mgr->funcs->enable_pme_wa)
1147 /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/
1148 clk_mgr->funcs->enable_pme_wa(clk_mgr);
1149
1150 /* TODO: notify audio driver for if audio modes list changed
1151 * add audio mode list change flag */
1152 /* dal_audio_disable_azalia_audio_jack_presence(stream->audio,
1153 * stream->stream_engine_id);
1154 */
1155 }
1156 }
1157
dce110_disable_stream(struct pipe_ctx * pipe_ctx)1158 void dce110_disable_stream(struct pipe_ctx *pipe_ctx)
1159 {
1160 struct dc_stream_state *stream = pipe_ctx->stream;
1161 struct dc_link *link = stream->link;
1162 struct dc *dc = pipe_ctx->stream->ctx->dc;
1163
1164 if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal)) {
1165 pipe_ctx->stream_res.stream_enc->funcs->stop_hdmi_info_packets(
1166 pipe_ctx->stream_res.stream_enc);
1167 pipe_ctx->stream_res.stream_enc->funcs->hdmi_reset_stream_attribute(
1168 pipe_ctx->stream_res.stream_enc);
1169 }
1170
1171 if (dc_is_dp_signal(pipe_ctx->stream->signal))
1172 pipe_ctx->stream_res.stream_enc->funcs->stop_dp_info_packets(
1173 pipe_ctx->stream_res.stream_enc);
1174
1175 dc->hwss.disable_audio_stream(pipe_ctx);
1176
1177 link->link_enc->funcs->connect_dig_be_to_fe(
1178 link->link_enc,
1179 pipe_ctx->stream_res.stream_enc->id,
1180 false);
1181
1182 }
1183
dce110_unblank_stream(struct pipe_ctx * pipe_ctx,struct dc_link_settings * link_settings)1184 void dce110_unblank_stream(struct pipe_ctx *pipe_ctx,
1185 struct dc_link_settings *link_settings)
1186 {
1187 struct encoder_unblank_param params = { { 0 } };
1188 struct dc_stream_state *stream = pipe_ctx->stream;
1189 struct dc_link *link = stream->link;
1190 struct dce_hwseq *hws = link->dc->hwseq;
1191
1192 /* only 3 items below are used by unblank */
1193 params.timing = pipe_ctx->stream->timing;
1194 params.link_settings.link_rate = link_settings->link_rate;
1195
1196 if (dc_is_dp_signal(pipe_ctx->stream->signal))
1197 pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms);
1198
1199 if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
1200 hws->funcs.edp_backlight_control(link, true);
1201 }
1202 }
1203
dce110_blank_stream(struct pipe_ctx * pipe_ctx)1204 void dce110_blank_stream(struct pipe_ctx *pipe_ctx)
1205 {
1206 struct dc_stream_state *stream = pipe_ctx->stream;
1207 struct dc_link *link = stream->link;
1208 struct dce_hwseq *hws = link->dc->hwseq;
1209
1210 if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
1211 hws->funcs.edp_backlight_control(link, false);
1212 link->dc->hwss.set_abm_immediate_disable(pipe_ctx);
1213 }
1214
1215 if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
1216 pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc);
1217
1218 if (!dc_is_embedded_signal(pipe_ctx->stream->signal)) {
1219 /*
1220 * After output is idle pattern some sinks need time to recognize the stream
1221 * has changed or they enter protection state and hang.
1222 */
1223 msleep(60);
1224 } else if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP)
1225 edp_receiver_ready_T9(link);
1226 }
1227
1228 }
1229
1230
dce110_set_avmute(struct pipe_ctx * pipe_ctx,bool enable)1231 void dce110_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
1232 {
1233 if (pipe_ctx != NULL && pipe_ctx->stream_res.stream_enc != NULL)
1234 pipe_ctx->stream_res.stream_enc->funcs->set_avmute(pipe_ctx->stream_res.stream_enc, enable);
1235 }
1236
translate_to_dto_source(enum controller_id crtc_id)1237 static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id)
1238 {
1239 switch (crtc_id) {
1240 case CONTROLLER_ID_D0:
1241 return DTO_SOURCE_ID0;
1242 case CONTROLLER_ID_D1:
1243 return DTO_SOURCE_ID1;
1244 case CONTROLLER_ID_D2:
1245 return DTO_SOURCE_ID2;
1246 case CONTROLLER_ID_D3:
1247 return DTO_SOURCE_ID3;
1248 case CONTROLLER_ID_D4:
1249 return DTO_SOURCE_ID4;
1250 case CONTROLLER_ID_D5:
1251 return DTO_SOURCE_ID5;
1252 default:
1253 return DTO_SOURCE_UNKNOWN;
1254 }
1255 }
1256
build_audio_output(struct dc_state * state,const struct pipe_ctx * pipe_ctx,struct audio_output * audio_output)1257 static void build_audio_output(
1258 struct dc_state *state,
1259 const struct pipe_ctx *pipe_ctx,
1260 struct audio_output *audio_output)
1261 {
1262 const struct dc_stream_state *stream = pipe_ctx->stream;
1263 audio_output->engine_id = pipe_ctx->stream_res.stream_enc->id;
1264
1265 audio_output->signal = pipe_ctx->stream->signal;
1266
1267 /* audio_crtc_info */
1268
1269 audio_output->crtc_info.h_total =
1270 stream->timing.h_total;
1271
1272 /*
1273 * Audio packets are sent during actual CRTC blank physical signal, we
1274 * need to specify actual active signal portion
1275 */
1276 audio_output->crtc_info.h_active =
1277 stream->timing.h_addressable
1278 + stream->timing.h_border_left
1279 + stream->timing.h_border_right;
1280
1281 audio_output->crtc_info.v_active =
1282 stream->timing.v_addressable
1283 + stream->timing.v_border_top
1284 + stream->timing.v_border_bottom;
1285
1286 audio_output->crtc_info.pixel_repetition = 1;
1287
1288 audio_output->crtc_info.interlaced =
1289 stream->timing.flags.INTERLACE;
1290
1291 audio_output->crtc_info.refresh_rate =
1292 (stream->timing.pix_clk_100hz*100)/
1293 (stream->timing.h_total*stream->timing.v_total);
1294
1295 audio_output->crtc_info.color_depth =
1296 stream->timing.display_color_depth;
1297
1298 audio_output->crtc_info.requested_pixel_clock_100Hz =
1299 pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz;
1300
1301 audio_output->crtc_info.calculated_pixel_clock_100Hz =
1302 pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz;
1303
1304 /*for HDMI, audio ACR is with deep color ratio factor*/
1305 if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal) &&
1306 audio_output->crtc_info.requested_pixel_clock_100Hz ==
1307 (stream->timing.pix_clk_100hz)) {
1308 if (pipe_ctx->stream_res.pix_clk_params.pixel_encoding == PIXEL_ENCODING_YCBCR420) {
1309 audio_output->crtc_info.requested_pixel_clock_100Hz =
1310 audio_output->crtc_info.requested_pixel_clock_100Hz/2;
1311 audio_output->crtc_info.calculated_pixel_clock_100Hz =
1312 pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz/2;
1313
1314 }
1315 }
1316
1317 if (state->clk_mgr &&
1318 (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
1319 pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)) {
1320 audio_output->pll_info.dp_dto_source_clock_in_khz =
1321 state->clk_mgr->funcs->get_dp_ref_clk_frequency(
1322 state->clk_mgr);
1323 }
1324
1325 audio_output->pll_info.feed_back_divider =
1326 pipe_ctx->pll_settings.feedback_divider;
1327
1328 audio_output->pll_info.dto_source =
1329 translate_to_dto_source(
1330 pipe_ctx->stream_res.tg->inst + 1);
1331
1332 /* TODO hard code to enable for now. Need get from stream */
1333 audio_output->pll_info.ss_enabled = true;
1334
1335 audio_output->pll_info.ss_percentage =
1336 pipe_ctx->pll_settings.ss_percentage;
1337 }
1338
program_scaler(const struct dc * dc,const struct pipe_ctx * pipe_ctx)1339 static void program_scaler(const struct dc *dc,
1340 const struct pipe_ctx *pipe_ctx)
1341 {
1342 struct tg_color color = {0};
1343
1344 #if defined(CONFIG_DRM_AMD_DC_DCN)
1345 /* TOFPGA */
1346 if (pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth == NULL)
1347 return;
1348 #endif
1349
1350 if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE)
1351 get_surface_visual_confirm_color(pipe_ctx, &color);
1352 else
1353 color_space_to_black_color(dc,
1354 pipe_ctx->stream->output_color_space,
1355 &color);
1356
1357 pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth(
1358 pipe_ctx->plane_res.xfm,
1359 pipe_ctx->plane_res.scl_data.lb_params.depth,
1360 &pipe_ctx->stream->bit_depth_params);
1361
1362 if (pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color) {
1363 /*
1364 * The way 420 is packed, 2 channels carry Y component, 1 channel
1365 * alternate between Cb and Cr, so both channels need the pixel
1366 * value for Y
1367 */
1368 if (pipe_ctx->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
1369 color.color_r_cr = color.color_g_y;
1370
1371 pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color(
1372 pipe_ctx->stream_res.tg,
1373 &color);
1374 }
1375
1376 pipe_ctx->plane_res.xfm->funcs->transform_set_scaler(pipe_ctx->plane_res.xfm,
1377 &pipe_ctx->plane_res.scl_data);
1378 }
1379
dce110_enable_stream_timing(struct pipe_ctx * pipe_ctx,struct dc_state * context,struct dc * dc)1380 static enum dc_status dce110_enable_stream_timing(
1381 struct pipe_ctx *pipe_ctx,
1382 struct dc_state *context,
1383 struct dc *dc)
1384 {
1385 struct dc_stream_state *stream = pipe_ctx->stream;
1386 struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx.
1387 pipe_ctx[pipe_ctx->pipe_idx];
1388 struct tg_color black_color = {0};
1389
1390 if (!pipe_ctx_old->stream) {
1391
1392 /* program blank color */
1393 color_space_to_black_color(dc,
1394 stream->output_color_space, &black_color);
1395 pipe_ctx->stream_res.tg->funcs->set_blank_color(
1396 pipe_ctx->stream_res.tg,
1397 &black_color);
1398
1399 /*
1400 * Must blank CRTC after disabling power gating and before any
1401 * programming, otherwise CRTC will be hung in bad state
1402 */
1403 pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true);
1404
1405 if (false == pipe_ctx->clock_source->funcs->program_pix_clk(
1406 pipe_ctx->clock_source,
1407 &pipe_ctx->stream_res.pix_clk_params,
1408 &pipe_ctx->pll_settings)) {
1409 BREAK_TO_DEBUGGER();
1410 return DC_ERROR_UNEXPECTED;
1411 }
1412
1413 pipe_ctx->stream_res.tg->funcs->program_timing(
1414 pipe_ctx->stream_res.tg,
1415 &stream->timing,
1416 0,
1417 0,
1418 0,
1419 0,
1420 pipe_ctx->stream->signal,
1421 true);
1422 }
1423
1424 if (!pipe_ctx_old->stream) {
1425 if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc(
1426 pipe_ctx->stream_res.tg)) {
1427 BREAK_TO_DEBUGGER();
1428 return DC_ERROR_UNEXPECTED;
1429 }
1430 }
1431
1432 return DC_OK;
1433 }
1434
apply_single_controller_ctx_to_hw(struct pipe_ctx * pipe_ctx,struct dc_state * context,struct dc * dc)1435 static enum dc_status apply_single_controller_ctx_to_hw(
1436 struct pipe_ctx *pipe_ctx,
1437 struct dc_state *context,
1438 struct dc *dc)
1439 {
1440 struct dc_stream_state *stream = pipe_ctx->stream;
1441 struct drr_params params = {0};
1442 unsigned int event_triggers = 0;
1443 struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe;
1444 struct dce_hwseq *hws = dc->hwseq;
1445
1446 if (hws->funcs.disable_stream_gating) {
1447 hws->funcs.disable_stream_gating(dc, pipe_ctx);
1448 }
1449
1450 if (pipe_ctx->stream_res.audio != NULL) {
1451 struct audio_output audio_output;
1452
1453 build_audio_output(context, pipe_ctx, &audio_output);
1454
1455 if (dc_is_dp_signal(pipe_ctx->stream->signal))
1456 pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup(
1457 pipe_ctx->stream_res.stream_enc,
1458 pipe_ctx->stream_res.audio->inst,
1459 &pipe_ctx->stream->audio_info);
1460 else
1461 pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup(
1462 pipe_ctx->stream_res.stream_enc,
1463 pipe_ctx->stream_res.audio->inst,
1464 &pipe_ctx->stream->audio_info,
1465 &audio_output.crtc_info);
1466
1467 pipe_ctx->stream_res.audio->funcs->az_configure(
1468 pipe_ctx->stream_res.audio,
1469 pipe_ctx->stream->signal,
1470 &audio_output.crtc_info,
1471 &pipe_ctx->stream->audio_info);
1472 }
1473
1474 /* */
1475 /* Do not touch stream timing on seamless boot optimization. */
1476 if (!pipe_ctx->stream->apply_seamless_boot_optimization)
1477 hws->funcs.enable_stream_timing(pipe_ctx, context, dc);
1478
1479 if (hws->funcs.setup_vupdate_interrupt)
1480 hws->funcs.setup_vupdate_interrupt(dc, pipe_ctx);
1481
1482 params.vertical_total_min = stream->adjust.v_total_min;
1483 params.vertical_total_max = stream->adjust.v_total_max;
1484 if (pipe_ctx->stream_res.tg->funcs->set_drr)
1485 pipe_ctx->stream_res.tg->funcs->set_drr(
1486 pipe_ctx->stream_res.tg, ¶ms);
1487
1488 // DRR should set trigger event to monitor surface update event
1489 if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0)
1490 event_triggers = 0x80;
1491 /* Event triggers and num frames initialized for DRR, but can be
1492 * later updated for PSR use. Note DRR trigger events are generated
1493 * regardless of whether num frames met.
1494 */
1495 if (pipe_ctx->stream_res.tg->funcs->set_static_screen_control)
1496 pipe_ctx->stream_res.tg->funcs->set_static_screen_control(
1497 pipe_ctx->stream_res.tg, event_triggers, 2);
1498
1499 if (!dc_is_virtual_signal(pipe_ctx->stream->signal))
1500 pipe_ctx->stream_res.stream_enc->funcs->dig_connect_to_otg(
1501 pipe_ctx->stream_res.stream_enc,
1502 pipe_ctx->stream_res.tg->inst);
1503
1504 pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion(
1505 pipe_ctx->stream_res.opp,
1506 COLOR_SPACE_YCBCR601,
1507 stream->timing.display_color_depth,
1508 stream->signal);
1509
1510 pipe_ctx->stream_res.opp->funcs->opp_program_fmt(
1511 pipe_ctx->stream_res.opp,
1512 &stream->bit_depth_params,
1513 &stream->clamping);
1514 while (odm_pipe) {
1515 odm_pipe->stream_res.opp->funcs->opp_set_dyn_expansion(
1516 odm_pipe->stream_res.opp,
1517 COLOR_SPACE_YCBCR601,
1518 stream->timing.display_color_depth,
1519 stream->signal);
1520
1521 odm_pipe->stream_res.opp->funcs->opp_program_fmt(
1522 odm_pipe->stream_res.opp,
1523 &stream->bit_depth_params,
1524 &stream->clamping);
1525 odm_pipe = odm_pipe->next_odm_pipe;
1526 }
1527
1528 if (!stream->dpms_off)
1529 core_link_enable_stream(context, pipe_ctx);
1530
1531 pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
1532
1533 pipe_ctx->stream->link->psr_settings.psr_feature_enabled = false;
1534
1535 return DC_OK;
1536 }
1537
1538 /******************************************************************************/
1539
power_down_encoders(struct dc * dc)1540 static void power_down_encoders(struct dc *dc)
1541 {
1542 int i;
1543
1544 /* do not know BIOS back-front mapping, simply blank all. It will not
1545 * hurt for non-DP
1546 */
1547 for (i = 0; i < dc->res_pool->stream_enc_count; i++) {
1548 dc->res_pool->stream_enc[i]->funcs->dp_blank(
1549 dc->res_pool->stream_enc[i]);
1550 }
1551
1552 for (i = 0; i < dc->link_count; i++) {
1553 enum signal_type signal = dc->links[i]->connector_signal;
1554
1555 if ((signal == SIGNAL_TYPE_EDP) ||
1556 (signal == SIGNAL_TYPE_DISPLAY_PORT))
1557 if (!dc->links[i]->wa_flags.dp_keep_receiver_powered)
1558 dp_receiver_power_ctrl(dc->links[i], false);
1559
1560 if (signal != SIGNAL_TYPE_EDP)
1561 signal = SIGNAL_TYPE_NONE;
1562
1563 dc->links[i]->link_enc->funcs->disable_output(
1564 dc->links[i]->link_enc, signal);
1565
1566 dc->links[i]->link_status.link_active = false;
1567 memset(&dc->links[i]->cur_link_settings, 0,
1568 sizeof(dc->links[i]->cur_link_settings));
1569 }
1570 }
1571
power_down_controllers(struct dc * dc)1572 static void power_down_controllers(struct dc *dc)
1573 {
1574 int i;
1575
1576 for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
1577 dc->res_pool->timing_generators[i]->funcs->disable_crtc(
1578 dc->res_pool->timing_generators[i]);
1579 }
1580 }
1581
power_down_clock_sources(struct dc * dc)1582 static void power_down_clock_sources(struct dc *dc)
1583 {
1584 int i;
1585
1586 if (dc->res_pool->dp_clock_source->funcs->cs_power_down(
1587 dc->res_pool->dp_clock_source) == false)
1588 dm_error("Failed to power down pll! (dp clk src)\n");
1589
1590 for (i = 0; i < dc->res_pool->clk_src_count; i++) {
1591 if (dc->res_pool->clock_sources[i]->funcs->cs_power_down(
1592 dc->res_pool->clock_sources[i]) == false)
1593 dm_error("Failed to power down pll! (clk src index=%d)\n", i);
1594 }
1595 }
1596
power_down_all_hw_blocks(struct dc * dc)1597 static void power_down_all_hw_blocks(struct dc *dc)
1598 {
1599 power_down_encoders(dc);
1600
1601 power_down_controllers(dc);
1602
1603 power_down_clock_sources(dc);
1604
1605 if (dc->fbc_compressor)
1606 dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
1607 }
1608
disable_vga_and_power_gate_all_controllers(struct dc * dc)1609 static void disable_vga_and_power_gate_all_controllers(
1610 struct dc *dc)
1611 {
1612 int i;
1613 struct timing_generator *tg;
1614 struct dc_context *ctx = dc->ctx;
1615
1616 for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
1617 tg = dc->res_pool->timing_generators[i];
1618
1619 if (tg->funcs->disable_vga)
1620 tg->funcs->disable_vga(tg);
1621 }
1622 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1623 /* Enable CLOCK gating for each pipe BEFORE controller
1624 * powergating. */
1625 enable_display_pipe_clock_gating(ctx,
1626 true);
1627
1628 dc->current_state->res_ctx.pipe_ctx[i].pipe_idx = i;
1629 dc->hwss.disable_plane(dc,
1630 &dc->current_state->res_ctx.pipe_ctx[i]);
1631 }
1632 }
1633
1634
get_edp_streams(struct dc_state * context,struct dc_stream_state ** edp_streams,int * edp_stream_num)1635 static void get_edp_streams(struct dc_state *context,
1636 struct dc_stream_state **edp_streams,
1637 int *edp_stream_num)
1638 {
1639 int i;
1640
1641 *edp_stream_num = 0;
1642 for (i = 0; i < context->stream_count; i++) {
1643 if (context->streams[i]->signal == SIGNAL_TYPE_EDP) {
1644 edp_streams[*edp_stream_num] = context->streams[i];
1645 if (++(*edp_stream_num) == MAX_NUM_EDP)
1646 return;
1647 }
1648 }
1649 }
1650
get_edp_links_with_sink(struct dc * dc,struct dc_link ** edp_links_with_sink,int * edp_with_sink_num)1651 static void get_edp_links_with_sink(
1652 struct dc *dc,
1653 struct dc_link **edp_links_with_sink,
1654 int *edp_with_sink_num)
1655 {
1656 int i;
1657
1658 /* check if there is an eDP panel not in use */
1659 *edp_with_sink_num = 0;
1660 for (i = 0; i < dc->link_count; i++) {
1661 if (dc->links[i]->local_sink &&
1662 dc->links[i]->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
1663 edp_links_with_sink[*edp_with_sink_num] = dc->links[i];
1664 if (++(*edp_with_sink_num) == MAX_NUM_EDP)
1665 return;
1666 }
1667 }
1668 }
1669
1670 /*
1671 * When ASIC goes from VBIOS/VGA mode to driver/accelerated mode we need:
1672 * 1. Power down all DC HW blocks
1673 * 2. Disable VGA engine on all controllers
1674 * 3. Enable power gating for controller
1675 * 4. Set acc_mode_change bit (VBIOS will clear this bit when going to FSDOS)
1676 */
dce110_enable_accelerated_mode(struct dc * dc,struct dc_state * context)1677 void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context)
1678 {
1679 struct dc_link *edp_links_with_sink[MAX_NUM_EDP];
1680 struct dc_link *edp_links[MAX_NUM_EDP];
1681 struct dc_stream_state *edp_streams[MAX_NUM_EDP];
1682 struct dc_link *edp_link_with_sink = NULL;
1683 struct dc_link *edp_link = NULL;
1684 struct dc_stream_state *edp_stream = NULL;
1685 struct dce_hwseq *hws = dc->hwseq;
1686 int edp_with_sink_num;
1687 int edp_num;
1688 int edp_stream_num;
1689 int i;
1690 bool can_apply_edp_fast_boot = false;
1691 bool can_apply_seamless_boot = false;
1692 bool keep_edp_vdd_on = false;
1693 DC_LOGGER_INIT();
1694
1695
1696 get_edp_links_with_sink(dc, edp_links_with_sink, &edp_with_sink_num);
1697 get_edp_links(dc, edp_links, &edp_num);
1698
1699 if (hws->funcs.init_pipes)
1700 hws->funcs.init_pipes(dc, context);
1701
1702 get_edp_streams(context, edp_streams, &edp_stream_num);
1703
1704 // Check fastboot support, disable on DCE8 because of blank screens
1705 if (edp_num && dc->ctx->dce_version != DCE_VERSION_8_0 &&
1706 dc->ctx->dce_version != DCE_VERSION_8_1 &&
1707 dc->ctx->dce_version != DCE_VERSION_8_3) {
1708 for (i = 0; i < edp_num; i++) {
1709 edp_link = edp_links[i];
1710 // enable fastboot if backend is enabled on eDP
1711 if (edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc)) {
1712 /* Set optimization flag on eDP stream*/
1713 if (edp_stream_num && edp_link->link_status.link_active) {
1714 edp_stream = edp_streams[0];
1715 can_apply_edp_fast_boot = !is_edp_ilr_optimization_required(edp_stream->link, &edp_stream->timing);
1716 edp_stream->apply_edp_fast_boot_optimization = can_apply_edp_fast_boot;
1717 if (can_apply_edp_fast_boot)
1718 DC_LOG_EVENT_LINK_TRAINING("eDP fast boot disabled to optimize link rate\n");
1719
1720 break;
1721 }
1722 }
1723 }
1724 // We are trying to enable eDP, don't power down VDD
1725 if (edp_stream_num)
1726 keep_edp_vdd_on = true;
1727 }
1728
1729 // Check seamless boot support
1730 for (i = 0; i < context->stream_count; i++) {
1731 if (context->streams[i]->apply_seamless_boot_optimization) {
1732 can_apply_seamless_boot = true;
1733 break;
1734 }
1735 }
1736
1737 /* eDP should not have stream in resume from S4 and so even with VBios post
1738 * it should get turned off
1739 */
1740 if (edp_with_sink_num)
1741 edp_link_with_sink = edp_links_with_sink[0];
1742
1743 if (!can_apply_edp_fast_boot && !can_apply_seamless_boot) {
1744 if (edp_link_with_sink && !keep_edp_vdd_on) {
1745 /*turn off backlight before DP_blank and encoder powered down*/
1746 hws->funcs.edp_backlight_control(edp_link_with_sink, false);
1747 }
1748 /*resume from S3, no vbios posting, no need to power down again*/
1749 clk_mgr_exit_optimized_pwr_state(dc, dc->clk_mgr);
1750
1751 power_down_all_hw_blocks(dc);
1752 disable_vga_and_power_gate_all_controllers(dc);
1753 if (edp_link_with_sink && !keep_edp_vdd_on)
1754 dc->hwss.edp_power_control(edp_link_with_sink, false);
1755 clk_mgr_optimize_pwr_state(dc, dc->clk_mgr);
1756 }
1757 bios_set_scratch_acc_mode_change(dc->ctx->dc_bios, 1);
1758 }
1759
compute_pstate_blackout_duration(struct bw_fixed blackout_duration,const struct dc_stream_state * stream)1760 static uint32_t compute_pstate_blackout_duration(
1761 struct bw_fixed blackout_duration,
1762 const struct dc_stream_state *stream)
1763 {
1764 uint32_t total_dest_line_time_ns;
1765 uint32_t pstate_blackout_duration_ns;
1766
1767 pstate_blackout_duration_ns = 1000 * blackout_duration.value >> 24;
1768
1769 total_dest_line_time_ns = 1000000UL *
1770 (stream->timing.h_total * 10) /
1771 stream->timing.pix_clk_100hz +
1772 pstate_blackout_duration_ns;
1773
1774 return total_dest_line_time_ns;
1775 }
1776
dce110_set_displaymarks(const struct dc * dc,struct dc_state * context)1777 static void dce110_set_displaymarks(
1778 const struct dc *dc,
1779 struct dc_state *context)
1780 {
1781 uint8_t i, num_pipes;
1782 unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
1783
1784 for (i = 0, num_pipes = 0; i < MAX_PIPES; i++) {
1785 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1786 uint32_t total_dest_line_time_ns;
1787
1788 if (pipe_ctx->stream == NULL)
1789 continue;
1790
1791 total_dest_line_time_ns = compute_pstate_blackout_duration(
1792 dc->bw_vbios->blackout_duration, pipe_ctx->stream);
1793 pipe_ctx->plane_res.mi->funcs->mem_input_program_display_marks(
1794 pipe_ctx->plane_res.mi,
1795 context->bw_ctx.bw.dce.nbp_state_change_wm_ns[num_pipes],
1796 context->bw_ctx.bw.dce.stutter_exit_wm_ns[num_pipes],
1797 context->bw_ctx.bw.dce.stutter_entry_wm_ns[num_pipes],
1798 context->bw_ctx.bw.dce.urgent_wm_ns[num_pipes],
1799 total_dest_line_time_ns);
1800 if (i == underlay_idx) {
1801 num_pipes++;
1802 pipe_ctx->plane_res.mi->funcs->mem_input_program_chroma_display_marks(
1803 pipe_ctx->plane_res.mi,
1804 context->bw_ctx.bw.dce.nbp_state_change_wm_ns[num_pipes],
1805 context->bw_ctx.bw.dce.stutter_exit_wm_ns[num_pipes],
1806 context->bw_ctx.bw.dce.urgent_wm_ns[num_pipes],
1807 total_dest_line_time_ns);
1808 }
1809 num_pipes++;
1810 }
1811 }
1812
dce110_set_safe_displaymarks(struct resource_context * res_ctx,const struct resource_pool * pool)1813 void dce110_set_safe_displaymarks(
1814 struct resource_context *res_ctx,
1815 const struct resource_pool *pool)
1816 {
1817 int i;
1818 int underlay_idx = pool->underlay_pipe_index;
1819 struct dce_watermarks max_marks = {
1820 MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK };
1821 struct dce_watermarks nbp_marks = {
1822 SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK };
1823 struct dce_watermarks min_marks = { 0, 0, 0, 0};
1824
1825 for (i = 0; i < MAX_PIPES; i++) {
1826 if (res_ctx->pipe_ctx[i].stream == NULL || res_ctx->pipe_ctx[i].plane_res.mi == NULL)
1827 continue;
1828
1829 res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_display_marks(
1830 res_ctx->pipe_ctx[i].plane_res.mi,
1831 nbp_marks,
1832 max_marks,
1833 min_marks,
1834 max_marks,
1835 MAX_WATERMARK);
1836
1837 if (i == underlay_idx)
1838 res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_chroma_display_marks(
1839 res_ctx->pipe_ctx[i].plane_res.mi,
1840 nbp_marks,
1841 max_marks,
1842 max_marks,
1843 MAX_WATERMARK);
1844
1845 }
1846 }
1847
1848 /*******************************************************************************
1849 * Public functions
1850 ******************************************************************************/
1851
set_drr(struct pipe_ctx ** pipe_ctx,int num_pipes,struct dc_crtc_timing_adjust adjust)1852 static void set_drr(struct pipe_ctx **pipe_ctx,
1853 int num_pipes, struct dc_crtc_timing_adjust adjust)
1854 {
1855 int i = 0;
1856 struct drr_params params = {0};
1857 // DRR should set trigger event to monitor surface update event
1858 unsigned int event_triggers = 0x80;
1859 // Note DRR trigger events are generated regardless of whether num frames met.
1860 unsigned int num_frames = 2;
1861
1862 params.vertical_total_max = adjust.v_total_max;
1863 params.vertical_total_min = adjust.v_total_min;
1864
1865 /* TODO: If multiple pipes are to be supported, you need
1866 * some GSL stuff. Static screen triggers may be programmed differently
1867 * as well.
1868 */
1869 for (i = 0; i < num_pipes; i++) {
1870 pipe_ctx[i]->stream_res.tg->funcs->set_drr(
1871 pipe_ctx[i]->stream_res.tg, ¶ms);
1872
1873 if (adjust.v_total_max != 0 && adjust.v_total_min != 0)
1874 pipe_ctx[i]->stream_res.tg->funcs->set_static_screen_control(
1875 pipe_ctx[i]->stream_res.tg,
1876 event_triggers, num_frames);
1877 }
1878 }
1879
get_position(struct pipe_ctx ** pipe_ctx,int num_pipes,struct crtc_position * position)1880 static void get_position(struct pipe_ctx **pipe_ctx,
1881 int num_pipes,
1882 struct crtc_position *position)
1883 {
1884 int i = 0;
1885
1886 /* TODO: handle pipes > 1
1887 */
1888 for (i = 0; i < num_pipes; i++)
1889 pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position);
1890 }
1891
set_static_screen_control(struct pipe_ctx ** pipe_ctx,int num_pipes,const struct dc_static_screen_params * params)1892 static void set_static_screen_control(struct pipe_ctx **pipe_ctx,
1893 int num_pipes, const struct dc_static_screen_params *params)
1894 {
1895 unsigned int i;
1896 unsigned int triggers = 0;
1897
1898 if (params->triggers.overlay_update)
1899 triggers |= 0x100;
1900 if (params->triggers.surface_update)
1901 triggers |= 0x80;
1902 if (params->triggers.cursor_update)
1903 triggers |= 0x2;
1904 if (params->triggers.force_trigger)
1905 triggers |= 0x1;
1906
1907 if (num_pipes) {
1908 struct dc *dc = pipe_ctx[0]->stream->ctx->dc;
1909
1910 if (dc->fbc_compressor)
1911 triggers |= 0x84;
1912 }
1913
1914 for (i = 0; i < num_pipes; i++)
1915 pipe_ctx[i]->stream_res.tg->funcs->
1916 set_static_screen_control(pipe_ctx[i]->stream_res.tg,
1917 triggers, params->num_frames);
1918 }
1919
1920 /*
1921 * Check if FBC can be enabled
1922 */
should_enable_fbc(struct dc * dc,struct dc_state * context,uint32_t * pipe_idx)1923 static bool should_enable_fbc(struct dc *dc,
1924 struct dc_state *context,
1925 uint32_t *pipe_idx)
1926 {
1927 uint32_t i;
1928 struct pipe_ctx *pipe_ctx = NULL;
1929 struct resource_context *res_ctx = &context->res_ctx;
1930 unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
1931
1932
1933 ASSERT(dc->fbc_compressor);
1934
1935 /* FBC memory should be allocated */
1936 if (!dc->ctx->fbc_gpu_addr)
1937 return false;
1938
1939 /* Only supports single display */
1940 if (context->stream_count != 1)
1941 return false;
1942
1943 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1944 if (res_ctx->pipe_ctx[i].stream) {
1945
1946 pipe_ctx = &res_ctx->pipe_ctx[i];
1947
1948 if (!pipe_ctx)
1949 continue;
1950
1951 /* fbc not applicable on underlay pipe */
1952 if (pipe_ctx->pipe_idx != underlay_idx) {
1953 *pipe_idx = i;
1954 break;
1955 }
1956 }
1957 }
1958
1959 if (i == dc->res_pool->pipe_count)
1960 return false;
1961
1962 if (!pipe_ctx->stream->link)
1963 return false;
1964
1965 /* Only supports eDP */
1966 if (pipe_ctx->stream->link->connector_signal != SIGNAL_TYPE_EDP)
1967 return false;
1968
1969 /* PSR should not be enabled */
1970 if (pipe_ctx->stream->link->psr_settings.psr_feature_enabled)
1971 return false;
1972
1973 /* Nothing to compress */
1974 if (!pipe_ctx->plane_state)
1975 return false;
1976
1977 /* Only for non-linear tiling */
1978 if (pipe_ctx->plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL)
1979 return false;
1980
1981 return true;
1982 }
1983
1984 /*
1985 * Enable FBC
1986 */
enable_fbc(struct dc * dc,struct dc_state * context)1987 static void enable_fbc(
1988 struct dc *dc,
1989 struct dc_state *context)
1990 {
1991 uint32_t pipe_idx = 0;
1992
1993 if (should_enable_fbc(dc, context, &pipe_idx)) {
1994 /* Program GRPH COMPRESSED ADDRESS and PITCH */
1995 struct compr_addr_and_pitch_params params = {0, 0, 0};
1996 struct compressor *compr = dc->fbc_compressor;
1997 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx];
1998
1999 params.source_view_width = pipe_ctx->stream->timing.h_addressable;
2000 params.source_view_height = pipe_ctx->stream->timing.v_addressable;
2001 params.inst = pipe_ctx->stream_res.tg->inst;
2002 compr->compr_surface_address.quad_part = dc->ctx->fbc_gpu_addr;
2003
2004 compr->funcs->surface_address_and_pitch(compr, ¶ms);
2005 compr->funcs->set_fbc_invalidation_triggers(compr, 1);
2006
2007 compr->funcs->enable_fbc(compr, ¶ms);
2008 }
2009 }
2010
dce110_reset_hw_ctx_wrap(struct dc * dc,struct dc_state * context)2011 static void dce110_reset_hw_ctx_wrap(
2012 struct dc *dc,
2013 struct dc_state *context)
2014 {
2015 int i;
2016
2017 /* Reset old context */
2018 /* look up the targets that have been removed since last commit */
2019 for (i = 0; i < MAX_PIPES; i++) {
2020 struct pipe_ctx *pipe_ctx_old =
2021 &dc->current_state->res_ctx.pipe_ctx[i];
2022 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2023
2024 /* Note: We need to disable output if clock sources change,
2025 * since bios does optimization and doesn't apply if changing
2026 * PHY when not already disabled.
2027 */
2028
2029 /* Skip underlay pipe since it will be handled in commit surface*/
2030 if (!pipe_ctx_old->stream || pipe_ctx_old->top_pipe)
2031 continue;
2032
2033 if (!pipe_ctx->stream ||
2034 pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) {
2035 struct clock_source *old_clk = pipe_ctx_old->clock_source;
2036
2037 /* Disable if new stream is null. O/w, if stream is
2038 * disabled already, no need to disable again.
2039 */
2040 if (!pipe_ctx->stream || !pipe_ctx->stream->dpms_off) {
2041 core_link_disable_stream(pipe_ctx_old);
2042
2043 /* free acquired resources*/
2044 if (pipe_ctx_old->stream_res.audio) {
2045 /*disable az_endpoint*/
2046 pipe_ctx_old->stream_res.audio->funcs->
2047 az_disable(pipe_ctx_old->stream_res.audio);
2048
2049 /*free audio*/
2050 if (dc->caps.dynamic_audio == true) {
2051 /*we have to dynamic arbitrate the audio endpoints*/
2052 /*we free the resource, need reset is_audio_acquired*/
2053 update_audio_usage(&dc->current_state->res_ctx, dc->res_pool,
2054 pipe_ctx_old->stream_res.audio, false);
2055 pipe_ctx_old->stream_res.audio = NULL;
2056 }
2057 }
2058 }
2059
2060 pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true);
2061 if (!hwss_wait_for_blank_complete(pipe_ctx_old->stream_res.tg)) {
2062 dm_error("DC: failed to blank crtc!\n");
2063 BREAK_TO_DEBUGGER();
2064 }
2065 pipe_ctx_old->stream_res.tg->funcs->disable_crtc(pipe_ctx_old->stream_res.tg);
2066 pipe_ctx_old->plane_res.mi->funcs->free_mem_input(
2067 pipe_ctx_old->plane_res.mi, dc->current_state->stream_count);
2068
2069 if (old_clk && 0 == resource_get_clock_source_reference(&context->res_ctx,
2070 dc->res_pool,
2071 old_clk))
2072 old_clk->funcs->cs_power_down(old_clk);
2073
2074 dc->hwss.disable_plane(dc, pipe_ctx_old);
2075
2076 pipe_ctx_old->stream = NULL;
2077 }
2078 }
2079 }
2080
dce110_setup_audio_dto(struct dc * dc,struct dc_state * context)2081 static void dce110_setup_audio_dto(
2082 struct dc *dc,
2083 struct dc_state *context)
2084 {
2085 int i;
2086
2087 /* program audio wall clock. use HDMI as clock source if HDMI
2088 * audio active. Otherwise, use DP as clock source
2089 * first, loop to find any HDMI audio, if not, loop find DP audio
2090 */
2091 /* Setup audio rate clock source */
2092 /* Issue:
2093 * Audio lag happened on DP monitor when unplug a HDMI monitor
2094 *
2095 * Cause:
2096 * In case of DP and HDMI connected or HDMI only, DCCG_AUDIO_DTO_SEL
2097 * is set to either dto0 or dto1, audio should work fine.
2098 * In case of DP connected only, DCCG_AUDIO_DTO_SEL should be dto1,
2099 * set to dto0 will cause audio lag.
2100 *
2101 * Solution:
2102 * Not optimized audio wall dto setup. When mode set, iterate pipe_ctx,
2103 * find first available pipe with audio, setup audio wall DTO per topology
2104 * instead of per pipe.
2105 */
2106 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2107 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2108
2109 if (pipe_ctx->stream == NULL)
2110 continue;
2111
2112 if (pipe_ctx->top_pipe)
2113 continue;
2114 if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A)
2115 continue;
2116 if (pipe_ctx->stream_res.audio != NULL &&
2117 pipe_ctx->stream_res.audio->enabled == false) {
2118 struct audio_output audio_output;
2119
2120 build_audio_output(context, pipe_ctx, &audio_output);
2121
2122 #if defined(CONFIG_DRM_AMD_DC_DCN)
2123 /* For DCN3.1, audio to HPO FRL encoder is using audio DTBCLK DTO */
2124 if (dc->res_pool->dccg && dc->res_pool->dccg->funcs->set_audio_dtbclk_dto) {
2125 /* disable audio DTBCLK DTO */
2126 dc->res_pool->dccg->funcs->set_audio_dtbclk_dto(
2127 dc->res_pool->dccg, 0);
2128
2129 pipe_ctx->stream_res.audio->funcs->wall_dto_setup(
2130 pipe_ctx->stream_res.audio,
2131 pipe_ctx->stream->signal,
2132 &audio_output.crtc_info,
2133 &audio_output.pll_info);
2134 } else
2135 pipe_ctx->stream_res.audio->funcs->wall_dto_setup(
2136 pipe_ctx->stream_res.audio,
2137 pipe_ctx->stream->signal,
2138 &audio_output.crtc_info,
2139 &audio_output.pll_info);
2140 #else
2141 pipe_ctx->stream_res.audio->funcs->wall_dto_setup(
2142 pipe_ctx->stream_res.audio,
2143 pipe_ctx->stream->signal,
2144 &audio_output.crtc_info,
2145 &audio_output.pll_info);
2146 #endif
2147 break;
2148 }
2149 }
2150
2151 /* no HDMI audio is found, try DP audio */
2152 if (i == dc->res_pool->pipe_count) {
2153 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2154 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2155
2156 if (pipe_ctx->stream == NULL)
2157 continue;
2158
2159 if (pipe_ctx->top_pipe)
2160 continue;
2161
2162 if (!dc_is_dp_signal(pipe_ctx->stream->signal))
2163 continue;
2164
2165 if (pipe_ctx->stream_res.audio != NULL &&
2166 pipe_ctx->stream_res.audio->enabled == false) {
2167 struct audio_output audio_output;
2168
2169 build_audio_output(context, pipe_ctx, &audio_output);
2170
2171 pipe_ctx->stream_res.audio->funcs->wall_dto_setup(
2172 pipe_ctx->stream_res.audio,
2173 pipe_ctx->stream->signal,
2174 &audio_output.crtc_info,
2175 &audio_output.pll_info);
2176 break;
2177 }
2178 }
2179 }
2180 }
2181
dce110_apply_ctx_to_hw(struct dc * dc,struct dc_state * context)2182 enum dc_status dce110_apply_ctx_to_hw(
2183 struct dc *dc,
2184 struct dc_state *context)
2185 {
2186 struct dce_hwseq *hws = dc->hwseq;
2187 struct dc_bios *dcb = dc->ctx->dc_bios;
2188 enum dc_status status;
2189 int i;
2190
2191 /* Reset old context */
2192 /* look up the targets that have been removed since last commit */
2193 hws->funcs.reset_hw_ctx_wrap(dc, context);
2194
2195 /* Skip applying if no targets */
2196 if (context->stream_count <= 0)
2197 return DC_OK;
2198
2199 /* Apply new context */
2200 dcb->funcs->set_scratch_critical_state(dcb, true);
2201
2202 /* below is for real asic only */
2203 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2204 struct pipe_ctx *pipe_ctx_old =
2205 &dc->current_state->res_ctx.pipe_ctx[i];
2206 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2207
2208 if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe)
2209 continue;
2210
2211 if (pipe_ctx->stream == pipe_ctx_old->stream) {
2212 if (pipe_ctx_old->clock_source != pipe_ctx->clock_source)
2213 dce_crtc_switch_to_clk_src(dc->hwseq,
2214 pipe_ctx->clock_source, i);
2215 continue;
2216 }
2217
2218 hws->funcs.enable_display_power_gating(
2219 dc, i, dc->ctx->dc_bios,
2220 PIPE_GATING_CONTROL_DISABLE);
2221 }
2222
2223 if (dc->fbc_compressor)
2224 dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
2225
2226 dce110_setup_audio_dto(dc, context);
2227
2228 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2229 struct pipe_ctx *pipe_ctx_old =
2230 &dc->current_state->res_ctx.pipe_ctx[i];
2231 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2232
2233 if (pipe_ctx->stream == NULL)
2234 continue;
2235
2236 if (pipe_ctx->stream == pipe_ctx_old->stream &&
2237 pipe_ctx->stream->link->link_state_valid) {
2238 continue;
2239 }
2240
2241 if (pipe_ctx_old->stream && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx))
2242 continue;
2243
2244 if (pipe_ctx->top_pipe || pipe_ctx->prev_odm_pipe)
2245 continue;
2246
2247 status = apply_single_controller_ctx_to_hw(
2248 pipe_ctx,
2249 context,
2250 dc);
2251
2252 if (DC_OK != status)
2253 return status;
2254 }
2255
2256 if (dc->fbc_compressor)
2257 enable_fbc(dc, dc->current_state);
2258
2259 dcb->funcs->set_scratch_critical_state(dcb, false);
2260
2261 return DC_OK;
2262 }
2263
2264 /*******************************************************************************
2265 * Front End programming
2266 ******************************************************************************/
set_default_colors(struct pipe_ctx * pipe_ctx)2267 static void set_default_colors(struct pipe_ctx *pipe_ctx)
2268 {
2269 struct default_adjustment default_adjust = { 0 };
2270
2271 default_adjust.force_hw_default = false;
2272 default_adjust.in_color_space = pipe_ctx->plane_state->color_space;
2273 default_adjust.out_color_space = pipe_ctx->stream->output_color_space;
2274 default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW;
2275 default_adjust.surface_pixel_format = pipe_ctx->plane_res.scl_data.format;
2276
2277 /* display color depth */
2278 default_adjust.color_depth =
2279 pipe_ctx->stream->timing.display_color_depth;
2280
2281 /* Lb color depth */
2282 default_adjust.lb_color_depth = pipe_ctx->plane_res.scl_data.lb_params.depth;
2283
2284 pipe_ctx->plane_res.xfm->funcs->opp_set_csc_default(
2285 pipe_ctx->plane_res.xfm, &default_adjust);
2286 }
2287
2288
2289 /*******************************************************************************
2290 * In order to turn on/off specific surface we will program
2291 * Blender + CRTC
2292 *
2293 * In case that we have two surfaces and they have a different visibility
2294 * we can't turn off the CRTC since it will turn off the entire display
2295 *
2296 * |----------------------------------------------- |
2297 * |bottom pipe|curr pipe | | |
2298 * |Surface |Surface | Blender | CRCT |
2299 * |visibility |visibility | Configuration| |
2300 * |------------------------------------------------|
2301 * | off | off | CURRENT_PIPE | blank |
2302 * | off | on | CURRENT_PIPE | unblank |
2303 * | on | off | OTHER_PIPE | unblank |
2304 * | on | on | BLENDING | unblank |
2305 * -------------------------------------------------|
2306 *
2307 ******************************************************************************/
program_surface_visibility(const struct dc * dc,struct pipe_ctx * pipe_ctx)2308 static void program_surface_visibility(const struct dc *dc,
2309 struct pipe_ctx *pipe_ctx)
2310 {
2311 enum blnd_mode blender_mode = BLND_MODE_CURRENT_PIPE;
2312 bool blank_target = false;
2313
2314 if (pipe_ctx->bottom_pipe) {
2315
2316 /* For now we are supporting only two pipes */
2317 ASSERT(pipe_ctx->bottom_pipe->bottom_pipe == NULL);
2318
2319 if (pipe_ctx->bottom_pipe->plane_state->visible) {
2320 if (pipe_ctx->plane_state->visible)
2321 blender_mode = BLND_MODE_BLENDING;
2322 else
2323 blender_mode = BLND_MODE_OTHER_PIPE;
2324
2325 } else if (!pipe_ctx->plane_state->visible)
2326 blank_target = true;
2327
2328 } else if (!pipe_ctx->plane_state->visible)
2329 blank_target = true;
2330
2331 dce_set_blender_mode(dc->hwseq, pipe_ctx->stream_res.tg->inst, blender_mode);
2332 pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, blank_target);
2333
2334 }
2335
program_gamut_remap(struct pipe_ctx * pipe_ctx)2336 static void program_gamut_remap(struct pipe_ctx *pipe_ctx)
2337 {
2338 int i = 0;
2339 struct xfm_grph_csc_adjustment adjust;
2340 memset(&adjust, 0, sizeof(adjust));
2341 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
2342
2343
2344 if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) {
2345 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
2346
2347 for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++)
2348 adjust.temperature_matrix[i] =
2349 pipe_ctx->stream->gamut_remap_matrix.matrix[i];
2350 }
2351
2352 pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust);
2353 }
update_plane_addr(const struct dc * dc,struct pipe_ctx * pipe_ctx)2354 static void update_plane_addr(const struct dc *dc,
2355 struct pipe_ctx *pipe_ctx)
2356 {
2357 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
2358
2359 if (plane_state == NULL)
2360 return;
2361
2362 pipe_ctx->plane_res.mi->funcs->mem_input_program_surface_flip_and_addr(
2363 pipe_ctx->plane_res.mi,
2364 &plane_state->address,
2365 plane_state->flip_immediate);
2366
2367 plane_state->status.requested_address = plane_state->address;
2368 }
2369
dce110_update_pending_status(struct pipe_ctx * pipe_ctx)2370 static void dce110_update_pending_status(struct pipe_ctx *pipe_ctx)
2371 {
2372 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
2373
2374 if (plane_state == NULL)
2375 return;
2376
2377 plane_state->status.is_flip_pending =
2378 pipe_ctx->plane_res.mi->funcs->mem_input_is_flip_pending(
2379 pipe_ctx->plane_res.mi);
2380
2381 if (plane_state->status.is_flip_pending && !plane_state->visible)
2382 pipe_ctx->plane_res.mi->current_address = pipe_ctx->plane_res.mi->request_address;
2383
2384 plane_state->status.current_address = pipe_ctx->plane_res.mi->current_address;
2385 if (pipe_ctx->plane_res.mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO &&
2386 pipe_ctx->stream_res.tg->funcs->is_stereo_left_eye) {
2387 plane_state->status.is_right_eye =\
2388 !pipe_ctx->stream_res.tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg);
2389 }
2390 }
2391
dce110_power_down(struct dc * dc)2392 void dce110_power_down(struct dc *dc)
2393 {
2394 power_down_all_hw_blocks(dc);
2395 disable_vga_and_power_gate_all_controllers(dc);
2396 }
2397
wait_for_reset_trigger_to_occur(struct dc_context * dc_ctx,struct timing_generator * tg)2398 static bool wait_for_reset_trigger_to_occur(
2399 struct dc_context *dc_ctx,
2400 struct timing_generator *tg)
2401 {
2402 bool rc = false;
2403
2404 /* To avoid endless loop we wait at most
2405 * frames_to_wait_on_triggered_reset frames for the reset to occur. */
2406 const uint32_t frames_to_wait_on_triggered_reset = 10;
2407 uint32_t i;
2408
2409 for (i = 0; i < frames_to_wait_on_triggered_reset; i++) {
2410
2411 if (!tg->funcs->is_counter_moving(tg)) {
2412 DC_ERROR("TG counter is not moving!\n");
2413 break;
2414 }
2415
2416 if (tg->funcs->did_triggered_reset_occur(tg)) {
2417 rc = true;
2418 /* usually occurs at i=1 */
2419 DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n",
2420 i);
2421 break;
2422 }
2423
2424 /* Wait for one frame. */
2425 tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE);
2426 tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK);
2427 }
2428
2429 if (false == rc)
2430 DC_ERROR("GSL: Timeout on reset trigger!\n");
2431
2432 return rc;
2433 }
2434
2435 /* Enable timing synchronization for a group of Timing Generators. */
dce110_enable_timing_synchronization(struct dc * dc,int group_index,int group_size,struct pipe_ctx * grouped_pipes[])2436 static void dce110_enable_timing_synchronization(
2437 struct dc *dc,
2438 int group_index,
2439 int group_size,
2440 struct pipe_ctx *grouped_pipes[])
2441 {
2442 struct dc_context *dc_ctx = dc->ctx;
2443 struct dcp_gsl_params gsl_params = { 0 };
2444 int i;
2445
2446 DC_SYNC_INFO("GSL: Setting-up...\n");
2447
2448 /* Designate a single TG in the group as a master.
2449 * Since HW doesn't care which one, we always assign
2450 * the 1st one in the group. */
2451 gsl_params.gsl_group = 0;
2452 gsl_params.gsl_master = grouped_pipes[0]->stream_res.tg->inst;
2453
2454 for (i = 0; i < group_size; i++)
2455 grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock(
2456 grouped_pipes[i]->stream_res.tg, &gsl_params);
2457
2458 /* Reset slave controllers on master VSync */
2459 DC_SYNC_INFO("GSL: enabling trigger-reset\n");
2460
2461 for (i = 1 /* skip the master */; i < group_size; i++)
2462 grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger(
2463 grouped_pipes[i]->stream_res.tg,
2464 gsl_params.gsl_group);
2465
2466 for (i = 1 /* skip the master */; i < group_size; i++) {
2467 DC_SYNC_INFO("GSL: waiting for reset to occur.\n");
2468 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg);
2469 grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger(
2470 grouped_pipes[i]->stream_res.tg);
2471 }
2472
2473 /* GSL Vblank synchronization is a one time sync mechanism, assumption
2474 * is that the sync'ed displays will not drift out of sync over time*/
2475 DC_SYNC_INFO("GSL: Restoring register states.\n");
2476 for (i = 0; i < group_size; i++)
2477 grouped_pipes[i]->stream_res.tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->stream_res.tg);
2478
2479 DC_SYNC_INFO("GSL: Set-up complete.\n");
2480 }
2481
dce110_enable_per_frame_crtc_position_reset(struct dc * dc,int group_size,struct pipe_ctx * grouped_pipes[])2482 static void dce110_enable_per_frame_crtc_position_reset(
2483 struct dc *dc,
2484 int group_size,
2485 struct pipe_ctx *grouped_pipes[])
2486 {
2487 struct dc_context *dc_ctx = dc->ctx;
2488 struct dcp_gsl_params gsl_params = { 0 };
2489 int i;
2490
2491 gsl_params.gsl_group = 0;
2492 gsl_params.gsl_master = 0;
2493
2494 for (i = 0; i < group_size; i++)
2495 grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock(
2496 grouped_pipes[i]->stream_res.tg, &gsl_params);
2497
2498 DC_SYNC_INFO("GSL: enabling trigger-reset\n");
2499
2500 for (i = 1; i < group_size; i++)
2501 grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset(
2502 grouped_pipes[i]->stream_res.tg,
2503 gsl_params.gsl_master,
2504 &grouped_pipes[i]->stream->triggered_crtc_reset);
2505
2506 DC_SYNC_INFO("GSL: waiting for reset to occur.\n");
2507 for (i = 1; i < group_size; i++)
2508 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg);
2509
2510 for (i = 0; i < group_size; i++)
2511 grouped_pipes[i]->stream_res.tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->stream_res.tg);
2512
2513 }
2514
init_pipes(struct dc * dc,struct dc_state * context)2515 static void init_pipes(struct dc *dc, struct dc_state *context)
2516 {
2517 // Do nothing
2518 }
2519
init_hw(struct dc * dc)2520 static void init_hw(struct dc *dc)
2521 {
2522 int i;
2523 struct dc_bios *bp;
2524 struct transform *xfm;
2525 struct abm *abm;
2526 struct dmcu *dmcu;
2527 struct dce_hwseq *hws = dc->hwseq;
2528 uint32_t backlight = MAX_BACKLIGHT_LEVEL;
2529
2530 bp = dc->ctx->dc_bios;
2531 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2532 xfm = dc->res_pool->transforms[i];
2533 xfm->funcs->transform_reset(xfm);
2534
2535 hws->funcs.enable_display_power_gating(
2536 dc, i, bp,
2537 PIPE_GATING_CONTROL_INIT);
2538 hws->funcs.enable_display_power_gating(
2539 dc, i, bp,
2540 PIPE_GATING_CONTROL_DISABLE);
2541 hws->funcs.enable_display_pipe_clock_gating(
2542 dc->ctx,
2543 true);
2544 }
2545
2546 dce_clock_gating_power_up(dc->hwseq, false);
2547 /***************************************/
2548
2549 for (i = 0; i < dc->link_count; i++) {
2550 /****************************************/
2551 /* Power up AND update implementation according to the
2552 * required signal (which may be different from the
2553 * default signal on connector). */
2554 struct dc_link *link = dc->links[i];
2555
2556 link->link_enc->funcs->hw_init(link->link_enc);
2557 }
2558
2559 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2560 struct timing_generator *tg = dc->res_pool->timing_generators[i];
2561
2562 tg->funcs->disable_vga(tg);
2563
2564 /* Blank controller using driver code instead of
2565 * command table. */
2566 tg->funcs->set_blank(tg, true);
2567 hwss_wait_for_blank_complete(tg);
2568 }
2569
2570 for (i = 0; i < dc->res_pool->audio_count; i++) {
2571 struct audio *audio = dc->res_pool->audios[i];
2572 audio->funcs->hw_init(audio);
2573 }
2574
2575 for (i = 0; i < dc->link_count; i++) {
2576 struct dc_link *link = dc->links[i];
2577
2578 if (link->panel_cntl)
2579 backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl);
2580 }
2581
2582 abm = dc->res_pool->abm;
2583 if (abm != NULL)
2584 abm->funcs->abm_init(abm, backlight);
2585
2586 dmcu = dc->res_pool->dmcu;
2587 if (dmcu != NULL && abm != NULL)
2588 abm->dmcu_is_running = dmcu->funcs->is_dmcu_initialized(dmcu);
2589
2590 if (dc->fbc_compressor)
2591 dc->fbc_compressor->funcs->power_up_fbc(dc->fbc_compressor);
2592
2593 }
2594
2595
dce110_prepare_bandwidth(struct dc * dc,struct dc_state * context)2596 void dce110_prepare_bandwidth(
2597 struct dc *dc,
2598 struct dc_state *context)
2599 {
2600 struct clk_mgr *dccg = dc->clk_mgr;
2601
2602 dce110_set_safe_displaymarks(&context->res_ctx, dc->res_pool);
2603
2604 dccg->funcs->update_clocks(
2605 dccg,
2606 context,
2607 false);
2608 }
2609
dce110_optimize_bandwidth(struct dc * dc,struct dc_state * context)2610 void dce110_optimize_bandwidth(
2611 struct dc *dc,
2612 struct dc_state *context)
2613 {
2614 struct clk_mgr *dccg = dc->clk_mgr;
2615
2616 dce110_set_displaymarks(dc, context);
2617
2618 dccg->funcs->update_clocks(
2619 dccg,
2620 context,
2621 true);
2622 }
2623
dce110_program_front_end_for_pipe(struct dc * dc,struct pipe_ctx * pipe_ctx)2624 static void dce110_program_front_end_for_pipe(
2625 struct dc *dc, struct pipe_ctx *pipe_ctx)
2626 {
2627 struct mem_input *mi = pipe_ctx->plane_res.mi;
2628 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
2629 struct xfm_grph_csc_adjustment adjust;
2630 struct out_csc_color_matrix tbl_entry;
2631 unsigned int i;
2632 struct dce_hwseq *hws = dc->hwseq;
2633
2634 DC_LOGGER_INIT();
2635 memset(&tbl_entry, 0, sizeof(tbl_entry));
2636
2637 memset(&adjust, 0, sizeof(adjust));
2638 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
2639
2640 dce_enable_fe_clock(dc->hwseq, mi->inst, true);
2641
2642 set_default_colors(pipe_ctx);
2643 if (pipe_ctx->stream->csc_color_matrix.enable_adjustment
2644 == true) {
2645 tbl_entry.color_space =
2646 pipe_ctx->stream->output_color_space;
2647
2648 for (i = 0; i < 12; i++)
2649 tbl_entry.regval[i] =
2650 pipe_ctx->stream->csc_color_matrix.matrix[i];
2651
2652 pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment
2653 (pipe_ctx->plane_res.xfm, &tbl_entry);
2654 }
2655
2656 if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) {
2657 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
2658
2659 for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++)
2660 adjust.temperature_matrix[i] =
2661 pipe_ctx->stream->gamut_remap_matrix.matrix[i];
2662 }
2663
2664 pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust);
2665
2666 pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
2667
2668 program_scaler(dc, pipe_ctx);
2669
2670 mi->funcs->mem_input_program_surface_config(
2671 mi,
2672 plane_state->format,
2673 &plane_state->tiling_info,
2674 &plane_state->plane_size,
2675 plane_state->rotation,
2676 NULL,
2677 false);
2678 if (mi->funcs->set_blank)
2679 mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible);
2680
2681 if (dc->config.gpu_vm_support)
2682 mi->funcs->mem_input_program_pte_vm(
2683 pipe_ctx->plane_res.mi,
2684 plane_state->format,
2685 &plane_state->tiling_info,
2686 plane_state->rotation);
2687
2688 /* Moved programming gamma from dc to hwss */
2689 if (pipe_ctx->plane_state->update_flags.bits.full_update ||
2690 pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
2691 pipe_ctx->plane_state->update_flags.bits.gamma_change)
2692 hws->funcs.set_input_transfer_func(dc, pipe_ctx, pipe_ctx->plane_state);
2693
2694 if (pipe_ctx->plane_state->update_flags.bits.full_update)
2695 hws->funcs.set_output_transfer_func(dc, pipe_ctx, pipe_ctx->stream);
2696
2697 DC_LOG_SURFACE(
2698 "Pipe:%d %p: addr hi:0x%x, "
2699 "addr low:0x%x, "
2700 "src: %d, %d, %d,"
2701 " %d; dst: %d, %d, %d, %d;"
2702 "clip: %d, %d, %d, %d\n",
2703 pipe_ctx->pipe_idx,
2704 (void *) pipe_ctx->plane_state,
2705 pipe_ctx->plane_state->address.grph.addr.high_part,
2706 pipe_ctx->plane_state->address.grph.addr.low_part,
2707 pipe_ctx->plane_state->src_rect.x,
2708 pipe_ctx->plane_state->src_rect.y,
2709 pipe_ctx->plane_state->src_rect.width,
2710 pipe_ctx->plane_state->src_rect.height,
2711 pipe_ctx->plane_state->dst_rect.x,
2712 pipe_ctx->plane_state->dst_rect.y,
2713 pipe_ctx->plane_state->dst_rect.width,
2714 pipe_ctx->plane_state->dst_rect.height,
2715 pipe_ctx->plane_state->clip_rect.x,
2716 pipe_ctx->plane_state->clip_rect.y,
2717 pipe_ctx->plane_state->clip_rect.width,
2718 pipe_ctx->plane_state->clip_rect.height);
2719
2720 DC_LOG_SURFACE(
2721 "Pipe %d: width, height, x, y\n"
2722 "viewport:%d, %d, %d, %d\n"
2723 "recout: %d, %d, %d, %d\n",
2724 pipe_ctx->pipe_idx,
2725 pipe_ctx->plane_res.scl_data.viewport.width,
2726 pipe_ctx->plane_res.scl_data.viewport.height,
2727 pipe_ctx->plane_res.scl_data.viewport.x,
2728 pipe_ctx->plane_res.scl_data.viewport.y,
2729 pipe_ctx->plane_res.scl_data.recout.width,
2730 pipe_ctx->plane_res.scl_data.recout.height,
2731 pipe_ctx->plane_res.scl_data.recout.x,
2732 pipe_ctx->plane_res.scl_data.recout.y);
2733 }
2734
dce110_apply_ctx_for_surface(struct dc * dc,const struct dc_stream_state * stream,int num_planes,struct dc_state * context)2735 static void dce110_apply_ctx_for_surface(
2736 struct dc *dc,
2737 const struct dc_stream_state *stream,
2738 int num_planes,
2739 struct dc_state *context)
2740 {
2741 int i;
2742
2743 if (num_planes == 0)
2744 return;
2745
2746 if (dc->fbc_compressor)
2747 dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
2748
2749 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2750 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2751
2752 if (pipe_ctx->stream != stream)
2753 continue;
2754
2755 /* Need to allocate mem before program front end for Fiji */
2756 pipe_ctx->plane_res.mi->funcs->allocate_mem_input(
2757 pipe_ctx->plane_res.mi,
2758 pipe_ctx->stream->timing.h_total,
2759 pipe_ctx->stream->timing.v_total,
2760 pipe_ctx->stream->timing.pix_clk_100hz / 10,
2761 context->stream_count);
2762
2763 dce110_program_front_end_for_pipe(dc, pipe_ctx);
2764
2765 dc->hwss.update_plane_addr(dc, pipe_ctx);
2766
2767 program_surface_visibility(dc, pipe_ctx);
2768
2769 }
2770
2771 if (dc->fbc_compressor)
2772 enable_fbc(dc, context);
2773 }
2774
dce110_post_unlock_program_front_end(struct dc * dc,struct dc_state * context)2775 static void dce110_post_unlock_program_front_end(
2776 struct dc *dc,
2777 struct dc_state *context)
2778 {
2779 }
2780
dce110_power_down_fe(struct dc * dc,struct pipe_ctx * pipe_ctx)2781 static void dce110_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx)
2782 {
2783 struct dce_hwseq *hws = dc->hwseq;
2784 int fe_idx = pipe_ctx->plane_res.mi ?
2785 pipe_ctx->plane_res.mi->inst : pipe_ctx->pipe_idx;
2786
2787 /* Do not power down fe when stream is active on dce*/
2788 if (dc->current_state->res_ctx.pipe_ctx[fe_idx].stream)
2789 return;
2790
2791 hws->funcs.enable_display_power_gating(
2792 dc, fe_idx, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE);
2793
2794 dc->res_pool->transforms[fe_idx]->funcs->transform_reset(
2795 dc->res_pool->transforms[fe_idx]);
2796 }
2797
dce110_wait_for_mpcc_disconnect(struct dc * dc,struct resource_pool * res_pool,struct pipe_ctx * pipe_ctx)2798 static void dce110_wait_for_mpcc_disconnect(
2799 struct dc *dc,
2800 struct resource_pool *res_pool,
2801 struct pipe_ctx *pipe_ctx)
2802 {
2803 /* do nothing*/
2804 }
2805
program_output_csc(struct dc * dc,struct pipe_ctx * pipe_ctx,enum dc_color_space colorspace,uint16_t * matrix,int opp_id)2806 static void program_output_csc(struct dc *dc,
2807 struct pipe_ctx *pipe_ctx,
2808 enum dc_color_space colorspace,
2809 uint16_t *matrix,
2810 int opp_id)
2811 {
2812 int i;
2813 struct out_csc_color_matrix tbl_entry;
2814
2815 if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) {
2816 enum dc_color_space color_space = pipe_ctx->stream->output_color_space;
2817
2818 for (i = 0; i < 12; i++)
2819 tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i];
2820
2821 tbl_entry.color_space = color_space;
2822
2823 pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment(
2824 pipe_ctx->plane_res.xfm, &tbl_entry);
2825 }
2826 }
2827
dce110_set_cursor_position(struct pipe_ctx * pipe_ctx)2828 static void dce110_set_cursor_position(struct pipe_ctx *pipe_ctx)
2829 {
2830 struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position;
2831 struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp;
2832 struct mem_input *mi = pipe_ctx->plane_res.mi;
2833 struct dc_cursor_mi_param param = {
2834 .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10,
2835 .ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clocks.xtalin_clock_inKhz,
2836 .viewport = pipe_ctx->plane_res.scl_data.viewport,
2837 .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz,
2838 .v_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.vert,
2839 .rotation = pipe_ctx->plane_state->rotation,
2840 .mirror = pipe_ctx->plane_state->horizontal_mirror
2841 };
2842
2843 /**
2844 * If the cursor's source viewport is clipped then we need to
2845 * translate the cursor to appear in the correct position on
2846 * the screen.
2847 *
2848 * This translation isn't affected by scaling so it needs to be
2849 * done *after* we adjust the position for the scale factor.
2850 *
2851 * This is only done by opt-in for now since there are still
2852 * some usecases like tiled display that might enable the
2853 * cursor on both streams while expecting dc to clip it.
2854 */
2855 if (pos_cpy.translate_by_source) {
2856 pos_cpy.x += pipe_ctx->plane_state->src_rect.x;
2857 pos_cpy.y += pipe_ctx->plane_state->src_rect.y;
2858 }
2859
2860 if (pipe_ctx->plane_state->address.type
2861 == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
2862 pos_cpy.enable = false;
2863
2864 if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state)
2865 pos_cpy.enable = false;
2866
2867 if (ipp->funcs->ipp_cursor_set_position)
2868 ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m);
2869 if (mi->funcs->set_cursor_position)
2870 mi->funcs->set_cursor_position(mi, &pos_cpy, ¶m);
2871 }
2872
dce110_set_cursor_attribute(struct pipe_ctx * pipe_ctx)2873 static void dce110_set_cursor_attribute(struct pipe_ctx *pipe_ctx)
2874 {
2875 struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes;
2876
2877 if (pipe_ctx->plane_res.ipp &&
2878 pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes)
2879 pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes(
2880 pipe_ctx->plane_res.ipp, attributes);
2881
2882 if (pipe_ctx->plane_res.mi &&
2883 pipe_ctx->plane_res.mi->funcs->set_cursor_attributes)
2884 pipe_ctx->plane_res.mi->funcs->set_cursor_attributes(
2885 pipe_ctx->plane_res.mi, attributes);
2886
2887 if (pipe_ctx->plane_res.xfm &&
2888 pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes)
2889 pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes(
2890 pipe_ctx->plane_res.xfm, attributes);
2891 }
2892
dce110_set_backlight_level(struct pipe_ctx * pipe_ctx,uint32_t backlight_pwm_u16_16,uint32_t frame_ramp)2893 bool dce110_set_backlight_level(struct pipe_ctx *pipe_ctx,
2894 uint32_t backlight_pwm_u16_16,
2895 uint32_t frame_ramp)
2896 {
2897 struct dc_link *link = pipe_ctx->stream->link;
2898 struct dc *dc = link->ctx->dc;
2899 struct abm *abm = pipe_ctx->stream_res.abm;
2900 struct panel_cntl *panel_cntl = link->panel_cntl;
2901 struct dmcu *dmcu = dc->res_pool->dmcu;
2902 bool fw_set_brightness = true;
2903 /* DMCU -1 for all controller id values,
2904 * therefore +1 here
2905 */
2906 uint32_t controller_id = pipe_ctx->stream_res.tg->inst + 1;
2907
2908 if (abm == NULL || panel_cntl == NULL || (abm->funcs->set_backlight_level_pwm == NULL))
2909 return false;
2910
2911 if (dmcu)
2912 fw_set_brightness = dmcu->funcs->is_dmcu_initialized(dmcu);
2913
2914 if (!fw_set_brightness && panel_cntl->funcs->driver_set_backlight)
2915 panel_cntl->funcs->driver_set_backlight(panel_cntl, backlight_pwm_u16_16);
2916 else
2917 abm->funcs->set_backlight_level_pwm(
2918 abm,
2919 backlight_pwm_u16_16,
2920 frame_ramp,
2921 controller_id,
2922 link->panel_cntl->inst);
2923
2924 return true;
2925 }
2926
dce110_set_abm_immediate_disable(struct pipe_ctx * pipe_ctx)2927 void dce110_set_abm_immediate_disable(struct pipe_ctx *pipe_ctx)
2928 {
2929 struct abm *abm = pipe_ctx->stream_res.abm;
2930 struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl;
2931
2932 if (abm)
2933 abm->funcs->set_abm_immediate_disable(abm,
2934 pipe_ctx->stream->link->panel_cntl->inst);
2935
2936 if (panel_cntl)
2937 panel_cntl->funcs->store_backlight_level(panel_cntl);
2938 }
2939
dce110_set_pipe(struct pipe_ctx * pipe_ctx)2940 void dce110_set_pipe(struct pipe_ctx *pipe_ctx)
2941 {
2942 struct abm *abm = pipe_ctx->stream_res.abm;
2943 struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl;
2944 uint32_t otg_inst = pipe_ctx->stream_res.tg->inst + 1;
2945
2946 if (abm && panel_cntl)
2947 abm->funcs->set_pipe(abm, otg_inst, panel_cntl->inst);
2948 }
2949
2950 static const struct hw_sequencer_funcs dce110_funcs = {
2951 .program_gamut_remap = program_gamut_remap,
2952 .program_output_csc = program_output_csc,
2953 .init_hw = init_hw,
2954 .apply_ctx_to_hw = dce110_apply_ctx_to_hw,
2955 .apply_ctx_for_surface = dce110_apply_ctx_for_surface,
2956 .post_unlock_program_front_end = dce110_post_unlock_program_front_end,
2957 .update_plane_addr = update_plane_addr,
2958 .update_pending_status = dce110_update_pending_status,
2959 .enable_accelerated_mode = dce110_enable_accelerated_mode,
2960 .enable_timing_synchronization = dce110_enable_timing_synchronization,
2961 .enable_per_frame_crtc_position_reset = dce110_enable_per_frame_crtc_position_reset,
2962 .update_info_frame = dce110_update_info_frame,
2963 .enable_stream = dce110_enable_stream,
2964 .disable_stream = dce110_disable_stream,
2965 .unblank_stream = dce110_unblank_stream,
2966 .blank_stream = dce110_blank_stream,
2967 .enable_audio_stream = dce110_enable_audio_stream,
2968 .disable_audio_stream = dce110_disable_audio_stream,
2969 .disable_plane = dce110_power_down_fe,
2970 .pipe_control_lock = dce_pipe_control_lock,
2971 .interdependent_update_lock = NULL,
2972 .cursor_lock = dce_pipe_control_lock,
2973 .prepare_bandwidth = dce110_prepare_bandwidth,
2974 .optimize_bandwidth = dce110_optimize_bandwidth,
2975 .set_drr = set_drr,
2976 .get_position = get_position,
2977 .set_static_screen_control = set_static_screen_control,
2978 .setup_stereo = NULL,
2979 .set_avmute = dce110_set_avmute,
2980 .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect,
2981 .edp_backlight_control = dce110_edp_backlight_control,
2982 .edp_power_control = dce110_edp_power_control,
2983 .edp_wait_for_hpd_ready = dce110_edp_wait_for_hpd_ready,
2984 .set_cursor_position = dce110_set_cursor_position,
2985 .set_cursor_attribute = dce110_set_cursor_attribute,
2986 .set_backlight_level = dce110_set_backlight_level,
2987 .set_abm_immediate_disable = dce110_set_abm_immediate_disable,
2988 .set_pipe = dce110_set_pipe,
2989 };
2990
2991 static const struct hwseq_private_funcs dce110_private_funcs = {
2992 .init_pipes = init_pipes,
2993 .update_plane_addr = update_plane_addr,
2994 .set_input_transfer_func = dce110_set_input_transfer_func,
2995 .set_output_transfer_func = dce110_set_output_transfer_func,
2996 .power_down = dce110_power_down,
2997 .enable_display_pipe_clock_gating = enable_display_pipe_clock_gating,
2998 .enable_display_power_gating = dce110_enable_display_power_gating,
2999 .reset_hw_ctx_wrap = dce110_reset_hw_ctx_wrap,
3000 .enable_stream_timing = dce110_enable_stream_timing,
3001 .disable_stream_gating = NULL,
3002 .enable_stream_gating = NULL,
3003 .edp_backlight_control = dce110_edp_backlight_control,
3004 };
3005
dce110_hw_sequencer_construct(struct dc * dc)3006 void dce110_hw_sequencer_construct(struct dc *dc)
3007 {
3008 dc->hwss = dce110_funcs;
3009 dc->hwseq->funcs = dce110_private_funcs;
3010 }
3011
3012