This source file includes following definitions.
- dce110_init_pte
- enable_display_pipe_clock_gating
- dce110_enable_display_power_gating
- build_prescale_params
- dce110_set_input_transfer_func
- convert_to_custom_float
- dce110_translate_regamma_to_hw_format
- dce110_set_output_transfer_func
- dce110_update_info_frame
- dce110_enable_stream
- is_panel_backlight_on
- is_panel_powered_on
- link_transmitter_control
- dce110_edp_wait_for_hpd_ready
- dce110_edp_power_control
- dce110_edp_backlight_control
- dce110_enable_audio_stream
- dce110_disable_audio_stream
- dce110_disable_stream
- dce110_unblank_stream
- dce110_blank_stream
- dce110_set_avmute
- translate_to_dto_source
- build_audio_output
- get_surface_visual_confirm_color
- program_scaler
- dce110_enable_stream_timing
- apply_single_controller_ctx_to_hw
- power_down_encoders
- power_down_controllers
- power_down_clock_sources
- power_down_all_hw_blocks
- disable_vga_and_power_gate_all_controllers
- get_edp_stream
- get_edp_link
- get_edp_link_with_sink
- dce110_enable_accelerated_mode
- compute_pstate_blackout_duration
- dce110_set_displaymarks
- dce110_set_safe_displaymarks
- set_drr
- get_position
- set_static_screen_control
- should_enable_fbc
- enable_fbc
- dce110_reset_hw_ctx_wrap
- dce110_setup_audio_dto
- dce110_apply_ctx_to_hw
- set_default_colors
- program_surface_visibility
- program_gamut_remap
- update_plane_addr
- dce110_update_pending_status
- dce110_power_down
- wait_for_reset_trigger_to_occur
- dce110_enable_timing_synchronization
- dce110_enable_per_frame_crtc_position_reset
- init_pipes
- init_hw
- dce110_prepare_bandwidth
- dce110_optimize_bandwidth
- dce110_program_front_end_for_pipe
- dce110_apply_ctx_for_surface
- dce110_power_down_fe
- dce110_wait_for_mpcc_disconnect
- program_output_csc
- dce110_set_cursor_position
- dce110_set_cursor_attribute
- dce110_hw_sequencer_construct
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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_hw_sequencer.h"
36 #include "dce110_timing_generator.h"
37 #include "dce/dce_hwseq.h"
38 #include "gpio_service_interface.h"
39
40 #include "dce110_compressor.h"
41
42 #include "bios/bios_parser_helper.h"
43 #include "timing_generator.h"
44 #include "mem_input.h"
45 #include "opp.h"
46 #include "ipp.h"
47 #include "transform.h"
48 #include "stream_encoder.h"
49 #include "link_encoder.h"
50 #include "link_hwss.h"
51 #include "clock_source.h"
52 #include "clk_mgr.h"
53 #include "abm.h"
54 #include "audio.h"
55 #include "reg_helper.h"
56
57
58 #include "dce/dce_11_0_d.h"
59 #include "dce/dce_11_0_sh_mask.h"
60 #include "custom_float.h"
61
62 #include "atomfirmware.h"
63
64
65
66
67
68
69 #define PANEL_POWER_UP_TIMEOUT 300
70 #define PANEL_POWER_DOWN_TIMEOUT 500
71 #define HPD_CHECK_INTERVAL 10
72
73 #define CTX \
74 hws->ctx
75
76 #define DC_LOGGER_INIT()
77
78 #define REG(reg)\
79 hws->regs->reg
80
81 #undef FN
82 #define FN(reg_name, field_name) \
83 hws->shifts->field_name, hws->masks->field_name
84
85 struct dce110_hw_seq_reg_offsets {
86 uint32_t crtc;
87 };
88
89 static const struct dce110_hw_seq_reg_offsets reg_offsets[] = {
90 {
91 .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
92 },
93 {
94 .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
95 },
96 {
97 .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
98 },
99 {
100 .crtc = (mmCRTCV_GSL_CONTROL - mmCRTC_GSL_CONTROL),
101 }
102 };
103
104 #define HW_REG_BLND(reg, id)\
105 (reg + reg_offsets[id].blnd)
106
107 #define HW_REG_CRTC(reg, id)\
108 (reg + reg_offsets[id].crtc)
109
110 #define MAX_WATERMARK 0xFFFF
111 #define SAFE_NBP_MARK 0x7FFF
112
113
114
115
116
117 static void dce110_init_pte(struct dc_context *ctx)
118 {
119 uint32_t addr;
120 uint32_t value = 0;
121 uint32_t chunk_int = 0;
122 uint32_t chunk_mul = 0;
123
124 addr = mmUNP_DVMM_PTE_CONTROL;
125 value = dm_read_reg(ctx, addr);
126
127 set_reg_field_value(
128 value,
129 0,
130 DVMM_PTE_CONTROL,
131 DVMM_USE_SINGLE_PTE);
132
133 set_reg_field_value(
134 value,
135 1,
136 DVMM_PTE_CONTROL,
137 DVMM_PTE_BUFFER_MODE0);
138
139 set_reg_field_value(
140 value,
141 1,
142 DVMM_PTE_CONTROL,
143 DVMM_PTE_BUFFER_MODE1);
144
145 dm_write_reg(ctx, addr, value);
146
147 addr = mmDVMM_PTE_REQ;
148 value = dm_read_reg(ctx, addr);
149
150 chunk_int = get_reg_field_value(
151 value,
152 DVMM_PTE_REQ,
153 HFLIP_PTEREQ_PER_CHUNK_INT);
154
155 chunk_mul = get_reg_field_value(
156 value,
157 DVMM_PTE_REQ,
158 HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER);
159
160 if (chunk_int != 0x4 || chunk_mul != 0x4) {
161
162 set_reg_field_value(
163 value,
164 255,
165 DVMM_PTE_REQ,
166 MAX_PTEREQ_TO_ISSUE);
167
168 set_reg_field_value(
169 value,
170 4,
171 DVMM_PTE_REQ,
172 HFLIP_PTEREQ_PER_CHUNK_INT);
173
174 set_reg_field_value(
175 value,
176 4,
177 DVMM_PTE_REQ,
178 HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER);
179
180 dm_write_reg(ctx, addr, value);
181 }
182 }
183
184
185 static void enable_display_pipe_clock_gating(
186 struct dc_context *ctx,
187 bool clock_gating)
188 {
189
190 }
191
192 static bool dce110_enable_display_power_gating(
193 struct dc *dc,
194 uint8_t controller_id,
195 struct dc_bios *dcb,
196 enum pipe_gating_control power_gating)
197 {
198 enum bp_result bp_result = BP_RESULT_OK;
199 enum bp_pipe_control_action cntl;
200 struct dc_context *ctx = dc->ctx;
201 unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
202
203 if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment))
204 return true;
205
206 if (power_gating == PIPE_GATING_CONTROL_INIT)
207 cntl = ASIC_PIPE_INIT;
208 else if (power_gating == PIPE_GATING_CONTROL_ENABLE)
209 cntl = ASIC_PIPE_ENABLE;
210 else
211 cntl = ASIC_PIPE_DISABLE;
212
213 if (controller_id == underlay_idx)
214 controller_id = CONTROLLER_ID_UNDERLAY0 - 1;
215
216 if (power_gating != PIPE_GATING_CONTROL_INIT || controller_id == 0){
217
218 bp_result = dcb->funcs->enable_disp_power_gating(
219 dcb, controller_id + 1, cntl);
220
221
222
223
224
225
226
227
228 if (controller_id < CONTROLLER_ID_MAX - 1)
229 dm_write_reg(ctx,
230 HW_REG_CRTC(mmCRTC_MASTER_UPDATE_MODE, controller_id),
231 0);
232 }
233
234 if (power_gating != PIPE_GATING_CONTROL_ENABLE)
235 dce110_init_pte(ctx);
236
237 if (bp_result == BP_RESULT_OK)
238 return true;
239 else
240 return false;
241 }
242
243 static void build_prescale_params(struct ipp_prescale_params *prescale_params,
244 const struct dc_plane_state *plane_state)
245 {
246 prescale_params->mode = IPP_PRESCALE_MODE_FIXED_UNSIGNED;
247
248 switch (plane_state->format) {
249 case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
250 prescale_params->scale = 0x2082;
251 break;
252 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
253 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
254 prescale_params->scale = 0x2020;
255 break;
256 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
257 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
258 prescale_params->scale = 0x2008;
259 break;
260 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
261 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
262 prescale_params->scale = 0x2000;
263 break;
264 default:
265 ASSERT(false);
266 break;
267 }
268 }
269
270 static bool
271 dce110_set_input_transfer_func(struct pipe_ctx *pipe_ctx,
272 const struct dc_plane_state *plane_state)
273 {
274 struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp;
275 const struct dc_transfer_func *tf = NULL;
276 struct ipp_prescale_params prescale_params = { 0 };
277 bool result = true;
278
279 if (ipp == NULL)
280 return false;
281
282 if (plane_state->in_transfer_func)
283 tf = plane_state->in_transfer_func;
284
285 build_prescale_params(&prescale_params, plane_state);
286 ipp->funcs->ipp_program_prescale(ipp, &prescale_params);
287
288 if (plane_state->gamma_correction &&
289 !plane_state->gamma_correction->is_identity &&
290 dce_use_lut(plane_state->format))
291 ipp->funcs->ipp_program_input_lut(ipp, plane_state->gamma_correction);
292
293 if (tf == NULL) {
294
295 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB);
296 } else if (tf->type == TF_TYPE_PREDEFINED) {
297 switch (tf->tf) {
298 case TRANSFER_FUNCTION_SRGB:
299 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB);
300 break;
301 case TRANSFER_FUNCTION_BT709:
302 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_xvYCC);
303 break;
304 case TRANSFER_FUNCTION_LINEAR:
305 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS);
306 break;
307 case TRANSFER_FUNCTION_PQ:
308 default:
309 result = false;
310 break;
311 }
312 } else if (tf->type == TF_TYPE_BYPASS) {
313 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS);
314 } else {
315
316 result = false;
317 }
318
319 return result;
320 }
321
322 static bool convert_to_custom_float(struct pwl_result_data *rgb_resulted,
323 struct curve_points *arr_points,
324 uint32_t hw_points_num)
325 {
326 struct custom_float_format fmt;
327
328 struct pwl_result_data *rgb = rgb_resulted;
329
330 uint32_t i = 0;
331
332 fmt.exponenta_bits = 6;
333 fmt.mantissa_bits = 12;
334 fmt.sign = true;
335
336 if (!convert_to_custom_float_format(arr_points[0].x, &fmt,
337 &arr_points[0].custom_float_x)) {
338 BREAK_TO_DEBUGGER();
339 return false;
340 }
341
342 if (!convert_to_custom_float_format(arr_points[0].offset, &fmt,
343 &arr_points[0].custom_float_offset)) {
344 BREAK_TO_DEBUGGER();
345 return false;
346 }
347
348 if (!convert_to_custom_float_format(arr_points[0].slope, &fmt,
349 &arr_points[0].custom_float_slope)) {
350 BREAK_TO_DEBUGGER();
351 return false;
352 }
353
354 fmt.mantissa_bits = 10;
355 fmt.sign = false;
356
357 if (!convert_to_custom_float_format(arr_points[1].x, &fmt,
358 &arr_points[1].custom_float_x)) {
359 BREAK_TO_DEBUGGER();
360 return false;
361 }
362
363 if (!convert_to_custom_float_format(arr_points[1].y, &fmt,
364 &arr_points[1].custom_float_y)) {
365 BREAK_TO_DEBUGGER();
366 return false;
367 }
368
369 if (!convert_to_custom_float_format(arr_points[1].slope, &fmt,
370 &arr_points[1].custom_float_slope)) {
371 BREAK_TO_DEBUGGER();
372 return false;
373 }
374
375 fmt.mantissa_bits = 12;
376 fmt.sign = true;
377
378 while (i != hw_points_num) {
379 if (!convert_to_custom_float_format(rgb->red, &fmt,
380 &rgb->red_reg)) {
381 BREAK_TO_DEBUGGER();
382 return false;
383 }
384
385 if (!convert_to_custom_float_format(rgb->green, &fmt,
386 &rgb->green_reg)) {
387 BREAK_TO_DEBUGGER();
388 return false;
389 }
390
391 if (!convert_to_custom_float_format(rgb->blue, &fmt,
392 &rgb->blue_reg)) {
393 BREAK_TO_DEBUGGER();
394 return false;
395 }
396
397 if (!convert_to_custom_float_format(rgb->delta_red, &fmt,
398 &rgb->delta_red_reg)) {
399 BREAK_TO_DEBUGGER();
400 return false;
401 }
402
403 if (!convert_to_custom_float_format(rgb->delta_green, &fmt,
404 &rgb->delta_green_reg)) {
405 BREAK_TO_DEBUGGER();
406 return false;
407 }
408
409 if (!convert_to_custom_float_format(rgb->delta_blue, &fmt,
410 &rgb->delta_blue_reg)) {
411 BREAK_TO_DEBUGGER();
412 return false;
413 }
414
415 ++rgb;
416 ++i;
417 }
418
419 return true;
420 }
421
422 #define MAX_LOW_POINT 25
423 #define NUMBER_REGIONS 16
424 #define NUMBER_SW_SEGMENTS 16
425
426 static bool
427 dce110_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf,
428 struct pwl_params *regamma_params)
429 {
430 struct curve_points *arr_points;
431 struct pwl_result_data *rgb_resulted;
432 struct pwl_result_data *rgb;
433 struct pwl_result_data *rgb_plus_1;
434 struct fixed31_32 y_r;
435 struct fixed31_32 y_g;
436 struct fixed31_32 y_b;
437 struct fixed31_32 y1_min;
438 struct fixed31_32 y3_max;
439
440 int32_t region_start, region_end;
441 uint32_t i, j, k, seg_distr[NUMBER_REGIONS], increment, start_index, hw_points;
442
443 if (output_tf == NULL || regamma_params == NULL || output_tf->type == TF_TYPE_BYPASS)
444 return false;
445
446 arr_points = regamma_params->arr_points;
447 rgb_resulted = regamma_params->rgb_resulted;
448 hw_points = 0;
449
450 memset(regamma_params, 0, sizeof(struct pwl_params));
451
452 if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
453
454
455
456 region_start = -11;
457 region_end = region_start + NUMBER_REGIONS;
458
459 for (i = 0; i < NUMBER_REGIONS; i++)
460 seg_distr[i] = 4;
461
462 } else {
463
464
465
466
467
468
469 region_start = -10;
470 region_end = 1;
471
472 seg_distr[0] = 4;
473 seg_distr[1] = 4;
474 seg_distr[2] = 4;
475 seg_distr[3] = 4;
476 seg_distr[4] = 4;
477 seg_distr[5] = 4;
478 seg_distr[6] = 4;
479 seg_distr[7] = 4;
480 seg_distr[8] = 4;
481 seg_distr[9] = 4;
482 seg_distr[10] = 0;
483 seg_distr[11] = -1;
484 seg_distr[12] = -1;
485 seg_distr[13] = -1;
486 seg_distr[14] = -1;
487 seg_distr[15] = -1;
488 }
489
490 for (k = 0; k < 16; k++) {
491 if (seg_distr[k] != -1)
492 hw_points += (1 << seg_distr[k]);
493 }
494
495 j = 0;
496 for (k = 0; k < (region_end - region_start); k++) {
497 increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]);
498 start_index = (region_start + k + MAX_LOW_POINT) *
499 NUMBER_SW_SEGMENTS;
500 for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS;
501 i += increment) {
502 if (j == hw_points - 1)
503 break;
504 rgb_resulted[j].red = output_tf->tf_pts.red[i];
505 rgb_resulted[j].green = output_tf->tf_pts.green[i];
506 rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
507 j++;
508 }
509 }
510
511
512 start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS;
513 rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index];
514 rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index];
515 rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index];
516
517 arr_points[0].x = dc_fixpt_pow(dc_fixpt_from_int(2),
518 dc_fixpt_from_int(region_start));
519 arr_points[1].x = dc_fixpt_pow(dc_fixpt_from_int(2),
520 dc_fixpt_from_int(region_end));
521
522 y_r = rgb_resulted[0].red;
523 y_g = rgb_resulted[0].green;
524 y_b = rgb_resulted[0].blue;
525
526 y1_min = dc_fixpt_min(y_r, dc_fixpt_min(y_g, y_b));
527
528 arr_points[0].y = y1_min;
529 arr_points[0].slope = dc_fixpt_div(arr_points[0].y,
530 arr_points[0].x);
531
532 y_r = rgb_resulted[hw_points - 1].red;
533 y_g = rgb_resulted[hw_points - 1].green;
534 y_b = rgb_resulted[hw_points - 1].blue;
535
536
537
538
539 y3_max = dc_fixpt_max(y_r, dc_fixpt_max(y_g, y_b));
540
541 arr_points[1].y = y3_max;
542
543 arr_points[1].slope = dc_fixpt_zero;
544
545 if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
546
547
548
549 const struct fixed31_32 end_value = dc_fixpt_from_int(125);
550
551 arr_points[1].slope = dc_fixpt_div(
552 dc_fixpt_sub(dc_fixpt_one, arr_points[1].y),
553 dc_fixpt_sub(end_value, arr_points[1].x));
554 }
555
556 regamma_params->hw_points_num = hw_points;
557
558 k = 0;
559 for (i = 1; i < 16; i++) {
560 if (seg_distr[k] != -1) {
561 regamma_params->arr_curve_points[k].segments_num = seg_distr[k];
562 regamma_params->arr_curve_points[i].offset =
563 regamma_params->arr_curve_points[k].offset + (1 << seg_distr[k]);
564 }
565 k++;
566 }
567
568 if (seg_distr[k] != -1)
569 regamma_params->arr_curve_points[k].segments_num = seg_distr[k];
570
571 rgb = rgb_resulted;
572 rgb_plus_1 = rgb_resulted + 1;
573
574 i = 1;
575
576 while (i != hw_points + 1) {
577 if (dc_fixpt_lt(rgb_plus_1->red, rgb->red))
578 rgb_plus_1->red = rgb->red;
579 if (dc_fixpt_lt(rgb_plus_1->green, rgb->green))
580 rgb_plus_1->green = rgb->green;
581 if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue))
582 rgb_plus_1->blue = rgb->blue;
583
584 rgb->delta_red = dc_fixpt_sub(rgb_plus_1->red, rgb->red);
585 rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green);
586 rgb->delta_blue = dc_fixpt_sub(rgb_plus_1->blue, rgb->blue);
587
588 ++rgb_plus_1;
589 ++rgb;
590 ++i;
591 }
592
593 convert_to_custom_float(rgb_resulted, arr_points, hw_points);
594
595 return true;
596 }
597
598 static bool
599 dce110_set_output_transfer_func(struct pipe_ctx *pipe_ctx,
600 const struct dc_stream_state *stream)
601 {
602 struct transform *xfm = pipe_ctx->plane_res.xfm;
603
604 xfm->funcs->opp_power_on_regamma_lut(xfm, true);
605 xfm->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM;
606
607 if (stream->out_transfer_func &&
608 stream->out_transfer_func->type == TF_TYPE_PREDEFINED &&
609 stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) {
610 xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_SRGB);
611 } else if (dce110_translate_regamma_to_hw_format(stream->out_transfer_func,
612 &xfm->regamma_params)) {
613 xfm->funcs->opp_program_regamma_pwl(xfm, &xfm->regamma_params);
614 xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_USER);
615 } else {
616 xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_BYPASS);
617 }
618
619 xfm->funcs->opp_power_on_regamma_lut(xfm, false);
620
621 return true;
622 }
623
624 void dce110_update_info_frame(struct pipe_ctx *pipe_ctx)
625 {
626 bool is_hdmi_tmds;
627 bool is_dp;
628
629 ASSERT(pipe_ctx->stream);
630
631 if (pipe_ctx->stream_res.stream_enc == NULL)
632 return;
633
634 is_hdmi_tmds = dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal);
635 is_dp = dc_is_dp_signal(pipe_ctx->stream->signal);
636
637 if (!is_hdmi_tmds && !is_dp)
638 return;
639
640 if (is_hdmi_tmds)
641 pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets(
642 pipe_ctx->stream_res.stream_enc,
643 &pipe_ctx->stream_res.encoder_info_frame);
644 else
645 pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets(
646 pipe_ctx->stream_res.stream_enc,
647 &pipe_ctx->stream_res.encoder_info_frame);
648 }
649
650 void dce110_enable_stream(struct pipe_ctx *pipe_ctx)
651 {
652 enum dc_lane_count lane_count =
653 pipe_ctx->stream->link->cur_link_settings.lane_count;
654
655 struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
656 struct dc_link *link = pipe_ctx->stream->link;
657
658
659 uint32_t active_total_with_borders;
660 uint32_t early_control = 0;
661 struct timing_generator *tg = pipe_ctx->stream_res.tg;
662
663
664
665
666
667 link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
668 pipe_ctx->stream_res.stream_enc->id, true);
669
670 link->dc->hwss.update_info_frame(pipe_ctx);
671
672
673 active_total_with_borders =
674 timing->h_addressable
675 + timing->h_border_left
676 + timing->h_border_right;
677
678 if (lane_count != 0)
679 early_control = active_total_with_borders % lane_count;
680
681 if (early_control == 0)
682 early_control = lane_count;
683
684 tg->funcs->set_early_control(tg, early_control);
685
686
687 if (pipe_ctx->stream_res.audio != NULL) {
688 if (dc_is_dp_signal(pipe_ctx->stream->signal))
689 pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc);
690 }
691
692
693
694
695 }
696
697
698 static bool is_panel_backlight_on(struct dce_hwseq *hws)
699 {
700 uint32_t value;
701
702 REG_GET(LVTMA_PWRSEQ_CNTL, LVTMA_BLON, &value);
703
704 return value;
705 }
706
707 static bool is_panel_powered_on(struct dce_hwseq *hws)
708 {
709 uint32_t pwr_seq_state, dig_on, dig_on_ovrd;
710
711
712 REG_GET(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &pwr_seq_state);
713
714 REG_GET_2(LVTMA_PWRSEQ_CNTL, LVTMA_DIGON, &dig_on, LVTMA_DIGON_OVRD, &dig_on_ovrd);
715
716 return (pwr_seq_state == 1) || (dig_on == 1 && dig_on_ovrd == 1);
717 }
718
719 static enum bp_result link_transmitter_control(
720 struct dc_bios *bios,
721 struct bp_transmitter_control *cntl)
722 {
723 enum bp_result result;
724
725 result = bios->funcs->transmitter_control(bios, cntl);
726
727 return result;
728 }
729
730
731
732
733
734 void dce110_edp_wait_for_hpd_ready(
735 struct dc_link *link,
736 bool power_up)
737 {
738 struct dc_context *ctx = link->ctx;
739 struct graphics_object_id connector = link->link_enc->connector;
740 struct gpio *hpd;
741 bool edp_hpd_high = false;
742 uint32_t time_elapsed = 0;
743 uint32_t timeout = power_up ?
744 PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT;
745
746 if (dal_graphics_object_id_get_connector_id(connector)
747 != CONNECTOR_ID_EDP) {
748 BREAK_TO_DEBUGGER();
749 return;
750 }
751
752 if (!power_up)
753
754
755
756
757 return;
758
759
760
761
762
763
764
765
766 hpd = get_hpd_gpio(ctx->dc_bios, connector, ctx->gpio_service);
767
768 if (!hpd) {
769 BREAK_TO_DEBUGGER();
770 return;
771 }
772
773 dal_gpio_open(hpd, GPIO_MODE_INTERRUPT);
774
775
776
777 do {
778 uint32_t detected = 0;
779
780 dal_gpio_get_value(hpd, &detected);
781
782 if (!(detected ^ power_up)) {
783 edp_hpd_high = true;
784 break;
785 }
786
787 msleep(HPD_CHECK_INTERVAL);
788
789 time_elapsed += HPD_CHECK_INTERVAL;
790 } while (time_elapsed < timeout);
791
792 dal_gpio_close(hpd);
793
794 dal_gpio_destroy_irq(&hpd);
795
796 if (false == edp_hpd_high) {
797 DC_LOG_ERROR(
798 "%s: wait timed out!\n", __func__);
799 }
800 }
801
802 void dce110_edp_power_control(
803 struct dc_link *link,
804 bool power_up)
805 {
806 struct dc_context *ctx = link->ctx;
807 struct dce_hwseq *hwseq = ctx->dc->hwseq;
808 struct bp_transmitter_control cntl = { 0 };
809 enum bp_result bp_result;
810
811
812 if (dal_graphics_object_id_get_connector_id(link->link_enc->connector)
813 != CONNECTOR_ID_EDP) {
814 BREAK_TO_DEBUGGER();
815 return;
816 }
817
818 if (power_up != is_panel_powered_on(hwseq)) {
819
820 if (power_up) {
821 unsigned long long current_ts = dm_get_timestamp(ctx);
822 unsigned long long duration_in_ms =
823 div64_u64(dm_get_elapse_time_in_ns(
824 ctx,
825 current_ts,
826 link->link_trace.time_stamp.edp_poweroff), 1000000);
827 unsigned long long wait_time_ms = 0;
828
829
830 unsigned long long edp_poweroff_time_ms = 500;
831
832 if (link->local_sink != NULL)
833 edp_poweroff_time_ms =
834 500 + link->local_sink->edid_caps.panel_patch.extra_t12_ms;
835 if (link->link_trace.time_stamp.edp_poweroff == 0)
836 wait_time_ms = edp_poweroff_time_ms;
837 else if (duration_in_ms < edp_poweroff_time_ms)
838 wait_time_ms = edp_poweroff_time_ms - duration_in_ms;
839
840 if (wait_time_ms) {
841 msleep(wait_time_ms);
842 dm_output_to_console("%s: wait %lld ms to power on eDP.\n",
843 __func__, wait_time_ms);
844 }
845
846 }
847
848 DC_LOG_HW_RESUME_S3(
849 "%s: Panel Power action: %s\n",
850 __func__, (power_up ? "On":"Off"));
851
852 cntl.action = power_up ?
853 TRANSMITTER_CONTROL_POWER_ON :
854 TRANSMITTER_CONTROL_POWER_OFF;
855 cntl.transmitter = link->link_enc->transmitter;
856 cntl.connector_obj_id = link->link_enc->connector;
857 cntl.coherent = false;
858 cntl.lanes_number = LANE_COUNT_FOUR;
859 cntl.hpd_sel = link->link_enc->hpd_source;
860 bp_result = link_transmitter_control(ctx->dc_bios, &cntl);
861
862 if (!power_up)
863
864 link->link_trace.time_stamp.edp_poweroff = dm_get_timestamp(ctx);
865 else
866 link->link_trace.time_stamp.edp_poweron = dm_get_timestamp(ctx);
867
868 if (bp_result != BP_RESULT_OK)
869 DC_LOG_ERROR(
870 "%s: Panel Power bp_result: %d\n",
871 __func__, bp_result);
872 } else {
873 DC_LOG_HW_RESUME_S3(
874 "%s: Skipping Panel Power action: %s\n",
875 __func__, (power_up ? "On":"Off"));
876 }
877 }
878
879
880
881
882
883
884 void dce110_edp_backlight_control(
885 struct dc_link *link,
886 bool enable)
887 {
888 struct dc_context *ctx = link->ctx;
889 struct dce_hwseq *hws = ctx->dc->hwseq;
890 struct bp_transmitter_control cntl = { 0 };
891
892 if (dal_graphics_object_id_get_connector_id(link->link_enc->connector)
893 != CONNECTOR_ID_EDP) {
894 BREAK_TO_DEBUGGER();
895 return;
896 }
897
898 if (enable && is_panel_backlight_on(hws)) {
899 DC_LOG_HW_RESUME_S3(
900 "%s: panel already powered up. Do nothing.\n",
901 __func__);
902 return;
903 }
904
905
906
907 DC_LOG_HW_RESUME_S3(
908 "%s: backlight action: %s\n",
909 __func__, (enable ? "On":"Off"));
910
911 cntl.action = enable ?
912 TRANSMITTER_CONTROL_BACKLIGHT_ON :
913 TRANSMITTER_CONTROL_BACKLIGHT_OFF;
914
915
916 cntl.transmitter = link->link_enc->transmitter;
917 cntl.connector_obj_id = link->link_enc->connector;
918
919 cntl.lanes_number = LANE_COUNT_FOUR;
920 cntl.hpd_sel = link->link_enc->hpd_source;
921 cntl.signal = SIGNAL_TYPE_EDP;
922
923
924
925
926
927
928
929
930
931
932
933
934
935 if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON)
936 edp_receiver_ready_T7(link);
937 link_transmitter_control(ctx->dc_bios, &cntl);
938
939 if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_OFF)
940 edp_receiver_ready_T9(link);
941 }
942
943 void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx)
944 {
945
946 struct dc *core_dc;
947 struct pp_smu_funcs *pp_smu = NULL;
948 struct clk_mgr *clk_mgr;
949 unsigned int i, num_audio = 1;
950
951 if (!pipe_ctx->stream)
952 return;
953
954 core_dc = pipe_ctx->stream->ctx->dc;
955 clk_mgr = core_dc->clk_mgr;
956
957 if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == true)
958 return;
959
960 if (core_dc->res_pool->pp_smu)
961 pp_smu = core_dc->res_pool->pp_smu;
962
963 if (pipe_ctx->stream_res.audio) {
964 for (i = 0; i < MAX_PIPES; i++) {
965
966 if (core_dc->current_state->res_ctx.pipe_ctx[i].stream_res.audio != NULL)
967 num_audio++;
968 }
969
970 pipe_ctx->stream_res.audio->funcs->az_enable(pipe_ctx->stream_res.audio);
971
972 if (num_audio >= 1 && clk_mgr->funcs->enable_pme_wa)
973
974 clk_mgr->funcs->enable_pme_wa(clk_mgr);
975
976
977 pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
978 pipe_ctx->stream_res.stream_enc, false);
979 if (pipe_ctx->stream_res.audio)
980 pipe_ctx->stream_res.audio->enabled = true;
981 }
982 }
983
984 void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx)
985 {
986 struct dc *dc;
987 struct pp_smu_funcs *pp_smu = NULL;
988 struct clk_mgr *clk_mgr;
989
990 if (!pipe_ctx || !pipe_ctx->stream)
991 return;
992
993 dc = pipe_ctx->stream->ctx->dc;
994 clk_mgr = dc->clk_mgr;
995
996 if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == false)
997 return;
998
999 pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
1000 pipe_ctx->stream_res.stream_enc, true);
1001 if (pipe_ctx->stream_res.audio) {
1002 pipe_ctx->stream_res.audio->enabled = false;
1003
1004 if (dc->res_pool->pp_smu)
1005 pp_smu = dc->res_pool->pp_smu;
1006
1007 if (dc_is_dp_signal(pipe_ctx->stream->signal))
1008 pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable(
1009 pipe_ctx->stream_res.stream_enc);
1010 else
1011 pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable(
1012 pipe_ctx->stream_res.stream_enc);
1013
1014 if (clk_mgr->funcs->enable_pme_wa)
1015
1016 clk_mgr->funcs->enable_pme_wa(clk_mgr);
1017
1018
1019
1020
1021
1022
1023 }
1024 }
1025
1026 void dce110_disable_stream(struct pipe_ctx *pipe_ctx)
1027 {
1028 struct dc_stream_state *stream = pipe_ctx->stream;
1029 struct dc_link *link = stream->link;
1030 struct dc *dc = pipe_ctx->stream->ctx->dc;
1031
1032 if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal)) {
1033 pipe_ctx->stream_res.stream_enc->funcs->stop_hdmi_info_packets(
1034 pipe_ctx->stream_res.stream_enc);
1035 pipe_ctx->stream_res.stream_enc->funcs->hdmi_reset_stream_attribute(
1036 pipe_ctx->stream_res.stream_enc);
1037 }
1038
1039 if (dc_is_dp_signal(pipe_ctx->stream->signal))
1040 pipe_ctx->stream_res.stream_enc->funcs->stop_dp_info_packets(
1041 pipe_ctx->stream_res.stream_enc);
1042
1043 dc->hwss.disable_audio_stream(pipe_ctx);
1044
1045 link->link_enc->funcs->connect_dig_be_to_fe(
1046 link->link_enc,
1047 pipe_ctx->stream_res.stream_enc->id,
1048 false);
1049
1050 }
1051
1052 void dce110_unblank_stream(struct pipe_ctx *pipe_ctx,
1053 struct dc_link_settings *link_settings)
1054 {
1055 struct encoder_unblank_param params = { { 0 } };
1056 struct dc_stream_state *stream = pipe_ctx->stream;
1057 struct dc_link *link = stream->link;
1058
1059
1060 params.timing = pipe_ctx->stream->timing;
1061 params.link_settings.link_rate = link_settings->link_rate;
1062
1063 if (dc_is_dp_signal(pipe_ctx->stream->signal))
1064 pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms);
1065
1066 if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
1067 link->dc->hwss.edp_backlight_control(link, true);
1068 }
1069 }
1070
1071 void dce110_blank_stream(struct pipe_ctx *pipe_ctx)
1072 {
1073 struct dc_stream_state *stream = pipe_ctx->stream;
1074 struct dc_link *link = stream->link;
1075
1076 if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
1077 link->dc->hwss.edp_backlight_control(link, false);
1078 dc_link_set_abm_disable(link);
1079 }
1080
1081 if (dc_is_dp_signal(pipe_ctx->stream->signal))
1082 pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc);
1083 }
1084
1085
1086 void dce110_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
1087 {
1088 if (pipe_ctx != NULL && pipe_ctx->stream_res.stream_enc != NULL)
1089 pipe_ctx->stream_res.stream_enc->funcs->set_avmute(pipe_ctx->stream_res.stream_enc, enable);
1090 }
1091
1092 static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id)
1093 {
1094 switch (crtc_id) {
1095 case CONTROLLER_ID_D0:
1096 return DTO_SOURCE_ID0;
1097 case CONTROLLER_ID_D1:
1098 return DTO_SOURCE_ID1;
1099 case CONTROLLER_ID_D2:
1100 return DTO_SOURCE_ID2;
1101 case CONTROLLER_ID_D3:
1102 return DTO_SOURCE_ID3;
1103 case CONTROLLER_ID_D4:
1104 return DTO_SOURCE_ID4;
1105 case CONTROLLER_ID_D5:
1106 return DTO_SOURCE_ID5;
1107 default:
1108 return DTO_SOURCE_UNKNOWN;
1109 }
1110 }
1111
1112 static void build_audio_output(
1113 struct dc_state *state,
1114 const struct pipe_ctx *pipe_ctx,
1115 struct audio_output *audio_output)
1116 {
1117 const struct dc_stream_state *stream = pipe_ctx->stream;
1118 audio_output->engine_id = pipe_ctx->stream_res.stream_enc->id;
1119
1120 audio_output->signal = pipe_ctx->stream->signal;
1121
1122
1123
1124 audio_output->crtc_info.h_total =
1125 stream->timing.h_total;
1126
1127
1128
1129
1130
1131 audio_output->crtc_info.h_active =
1132 stream->timing.h_addressable
1133 + stream->timing.h_border_left
1134 + stream->timing.h_border_right;
1135
1136 audio_output->crtc_info.v_active =
1137 stream->timing.v_addressable
1138 + stream->timing.v_border_top
1139 + stream->timing.v_border_bottom;
1140
1141 audio_output->crtc_info.pixel_repetition = 1;
1142
1143 audio_output->crtc_info.interlaced =
1144 stream->timing.flags.INTERLACE;
1145
1146 audio_output->crtc_info.refresh_rate =
1147 (stream->timing.pix_clk_100hz*100)/
1148 (stream->timing.h_total*stream->timing.v_total);
1149
1150 audio_output->crtc_info.color_depth =
1151 stream->timing.display_color_depth;
1152
1153 audio_output->crtc_info.requested_pixel_clock_100Hz =
1154 pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz;
1155
1156 audio_output->crtc_info.calculated_pixel_clock_100Hz =
1157 pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz;
1158
1159
1160 if (dc_is_hdmi_signal(pipe_ctx->stream->signal) &&
1161 audio_output->crtc_info.requested_pixel_clock_100Hz ==
1162 (stream->timing.pix_clk_100hz)) {
1163 if (pipe_ctx->stream_res.pix_clk_params.pixel_encoding == PIXEL_ENCODING_YCBCR420) {
1164 audio_output->crtc_info.requested_pixel_clock_100Hz =
1165 audio_output->crtc_info.requested_pixel_clock_100Hz/2;
1166 audio_output->crtc_info.calculated_pixel_clock_100Hz =
1167 pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz/2;
1168
1169 }
1170 }
1171
1172 if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
1173 pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
1174 audio_output->pll_info.dp_dto_source_clock_in_khz =
1175 state->clk_mgr->funcs->get_dp_ref_clk_frequency(
1176 state->clk_mgr);
1177 }
1178
1179 audio_output->pll_info.feed_back_divider =
1180 pipe_ctx->pll_settings.feedback_divider;
1181
1182 audio_output->pll_info.dto_source =
1183 translate_to_dto_source(
1184 pipe_ctx->stream_res.tg->inst + 1);
1185
1186
1187 audio_output->pll_info.ss_enabled = true;
1188
1189 audio_output->pll_info.ss_percentage =
1190 pipe_ctx->pll_settings.ss_percentage;
1191 }
1192
1193 static void get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx,
1194 struct tg_color *color)
1195 {
1196 uint32_t color_value = MAX_TG_COLOR_VALUE * (4 - pipe_ctx->stream_res.tg->inst) / 4;
1197
1198 switch (pipe_ctx->plane_res.scl_data.format) {
1199 case PIXEL_FORMAT_ARGB8888:
1200
1201 color->color_r_cr = color_value;
1202 break;
1203
1204 case PIXEL_FORMAT_ARGB2101010:
1205
1206 color->color_b_cb = color_value;
1207 break;
1208 case PIXEL_FORMAT_420BPP8:
1209
1210 color->color_g_y = color_value;
1211 break;
1212 case PIXEL_FORMAT_420BPP10:
1213
1214 color->color_g_y = color_value;
1215 color->color_r_cr = color_value;
1216 break;
1217 case PIXEL_FORMAT_FP16:
1218
1219 color->color_r_cr = color_value;
1220 color->color_b_cb = color_value;
1221 color->color_g_y = color_value;
1222 break;
1223 default:
1224 break;
1225 }
1226 }
1227
1228 static void program_scaler(const struct dc *dc,
1229 const struct pipe_ctx *pipe_ctx)
1230 {
1231 struct tg_color color = {0};
1232
1233 #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
1234
1235 if (pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth == NULL)
1236 return;
1237 #endif
1238
1239 if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE)
1240 get_surface_visual_confirm_color(pipe_ctx, &color);
1241 else
1242 color_space_to_black_color(dc,
1243 pipe_ctx->stream->output_color_space,
1244 &color);
1245
1246 pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth(
1247 pipe_ctx->plane_res.xfm,
1248 pipe_ctx->plane_res.scl_data.lb_params.depth,
1249 &pipe_ctx->stream->bit_depth_params);
1250
1251 if (pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color) {
1252
1253
1254
1255
1256
1257 if (pipe_ctx->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
1258 color.color_r_cr = color.color_g_y;
1259
1260 pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color(
1261 pipe_ctx->stream_res.tg,
1262 &color);
1263 }
1264
1265 pipe_ctx->plane_res.xfm->funcs->transform_set_scaler(pipe_ctx->plane_res.xfm,
1266 &pipe_ctx->plane_res.scl_data);
1267 }
1268
1269 static enum dc_status dce110_enable_stream_timing(
1270 struct pipe_ctx *pipe_ctx,
1271 struct dc_state *context,
1272 struct dc *dc)
1273 {
1274 struct dc_stream_state *stream = pipe_ctx->stream;
1275 struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx.
1276 pipe_ctx[pipe_ctx->pipe_idx];
1277 struct tg_color black_color = {0};
1278
1279 if (!pipe_ctx_old->stream) {
1280
1281
1282 color_space_to_black_color(dc,
1283 stream->output_color_space, &black_color);
1284 pipe_ctx->stream_res.tg->funcs->set_blank_color(
1285 pipe_ctx->stream_res.tg,
1286 &black_color);
1287
1288
1289
1290
1291
1292 pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true);
1293
1294 if (false == pipe_ctx->clock_source->funcs->program_pix_clk(
1295 pipe_ctx->clock_source,
1296 &pipe_ctx->stream_res.pix_clk_params,
1297 &pipe_ctx->pll_settings)) {
1298 BREAK_TO_DEBUGGER();
1299 return DC_ERROR_UNEXPECTED;
1300 }
1301
1302 pipe_ctx->stream_res.tg->funcs->program_timing(
1303 pipe_ctx->stream_res.tg,
1304 &stream->timing,
1305 0,
1306 0,
1307 0,
1308 0,
1309 pipe_ctx->stream->signal,
1310 true);
1311 }
1312
1313 if (!pipe_ctx_old->stream) {
1314 if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc(
1315 pipe_ctx->stream_res.tg)) {
1316 BREAK_TO_DEBUGGER();
1317 return DC_ERROR_UNEXPECTED;
1318 }
1319 }
1320
1321 return DC_OK;
1322 }
1323
1324 static enum dc_status apply_single_controller_ctx_to_hw(
1325 struct pipe_ctx *pipe_ctx,
1326 struct dc_state *context,
1327 struct dc *dc)
1328 {
1329 struct dc_stream_state *stream = pipe_ctx->stream;
1330 struct drr_params params = {0};
1331 unsigned int event_triggers = 0;
1332 #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
1333 struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe;
1334 #endif
1335
1336 if (dc->hwss.disable_stream_gating) {
1337 dc->hwss.disable_stream_gating(dc, pipe_ctx);
1338 }
1339
1340 if (pipe_ctx->stream_res.audio != NULL) {
1341 struct audio_output audio_output;
1342
1343 build_audio_output(context, pipe_ctx, &audio_output);
1344
1345 if (dc_is_dp_signal(pipe_ctx->stream->signal))
1346 pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup(
1347 pipe_ctx->stream_res.stream_enc,
1348 pipe_ctx->stream_res.audio->inst,
1349 &pipe_ctx->stream->audio_info);
1350 else
1351 pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup(
1352 pipe_ctx->stream_res.stream_enc,
1353 pipe_ctx->stream_res.audio->inst,
1354 &pipe_ctx->stream->audio_info,
1355 &audio_output.crtc_info);
1356
1357 pipe_ctx->stream_res.audio->funcs->az_configure(
1358 pipe_ctx->stream_res.audio,
1359 pipe_ctx->stream->signal,
1360 &audio_output.crtc_info,
1361 &pipe_ctx->stream->audio_info);
1362 }
1363
1364
1365
1366 if (!pipe_ctx->stream->apply_seamless_boot_optimization)
1367 dc->hwss.enable_stream_timing(pipe_ctx, context, dc);
1368
1369 if (dc->hwss.setup_vupdate_interrupt)
1370 dc->hwss.setup_vupdate_interrupt(pipe_ctx);
1371
1372 params.vertical_total_min = stream->adjust.v_total_min;
1373 params.vertical_total_max = stream->adjust.v_total_max;
1374 if (pipe_ctx->stream_res.tg->funcs->set_drr)
1375 pipe_ctx->stream_res.tg->funcs->set_drr(
1376 pipe_ctx->stream_res.tg, ¶ms);
1377
1378
1379 if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0)
1380 event_triggers = 0x80;
1381 if (pipe_ctx->stream_res.tg->funcs->set_static_screen_control)
1382 pipe_ctx->stream_res.tg->funcs->set_static_screen_control(
1383 pipe_ctx->stream_res.tg, event_triggers);
1384
1385 if (!dc_is_virtual_signal(pipe_ctx->stream->signal))
1386 pipe_ctx->stream_res.stream_enc->funcs->dig_connect_to_otg(
1387 pipe_ctx->stream_res.stream_enc,
1388 pipe_ctx->stream_res.tg->inst);
1389
1390 pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion(
1391 pipe_ctx->stream_res.opp,
1392 COLOR_SPACE_YCBCR601,
1393 stream->timing.display_color_depth,
1394 stream->signal);
1395
1396 pipe_ctx->stream_res.opp->funcs->opp_program_fmt(
1397 pipe_ctx->stream_res.opp,
1398 &stream->bit_depth_params,
1399 &stream->clamping);
1400 #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
1401 while (odm_pipe) {
1402 odm_pipe->stream_res.opp->funcs->opp_set_dyn_expansion(
1403 odm_pipe->stream_res.opp,
1404 COLOR_SPACE_YCBCR601,
1405 stream->timing.display_color_depth,
1406 stream->signal);
1407
1408 odm_pipe->stream_res.opp->funcs->opp_program_fmt(
1409 odm_pipe->stream_res.opp,
1410 &stream->bit_depth_params,
1411 &stream->clamping);
1412 odm_pipe = odm_pipe->next_odm_pipe;
1413 }
1414 #endif
1415
1416 if (!stream->dpms_off)
1417 core_link_enable_stream(context, pipe_ctx);
1418
1419 pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
1420
1421 pipe_ctx->stream->link->psr_enabled = false;
1422
1423 return DC_OK;
1424 }
1425
1426
1427
1428 static void power_down_encoders(struct dc *dc)
1429 {
1430 int i;
1431 enum connector_id connector_id;
1432 enum signal_type signal = SIGNAL_TYPE_NONE;
1433
1434
1435
1436
1437 for (i = 0; i < dc->res_pool->stream_enc_count; i++) {
1438 dc->res_pool->stream_enc[i]->funcs->dp_blank(
1439 dc->res_pool->stream_enc[i]);
1440 }
1441
1442 for (i = 0; i < dc->link_count; i++) {
1443 connector_id = dal_graphics_object_id_get_connector_id(dc->links[i]->link_id);
1444 if ((connector_id == CONNECTOR_ID_DISPLAY_PORT) ||
1445 (connector_id == CONNECTOR_ID_EDP)) {
1446
1447 if (!dc->links[i]->wa_flags.dp_keep_receiver_powered)
1448 dp_receiver_power_ctrl(dc->links[i], false);
1449 if (connector_id == CONNECTOR_ID_EDP)
1450 signal = SIGNAL_TYPE_EDP;
1451 }
1452
1453 dc->links[i]->link_enc->funcs->disable_output(
1454 dc->links[i]->link_enc, signal);
1455 }
1456 }
1457
1458 static void power_down_controllers(struct dc *dc)
1459 {
1460 int i;
1461
1462 for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
1463 dc->res_pool->timing_generators[i]->funcs->disable_crtc(
1464 dc->res_pool->timing_generators[i]);
1465 }
1466 }
1467
1468 static void power_down_clock_sources(struct dc *dc)
1469 {
1470 int i;
1471
1472 if (dc->res_pool->dp_clock_source->funcs->cs_power_down(
1473 dc->res_pool->dp_clock_source) == false)
1474 dm_error("Failed to power down pll! (dp clk src)\n");
1475
1476 for (i = 0; i < dc->res_pool->clk_src_count; i++) {
1477 if (dc->res_pool->clock_sources[i]->funcs->cs_power_down(
1478 dc->res_pool->clock_sources[i]) == false)
1479 dm_error("Failed to power down pll! (clk src index=%d)\n", i);
1480 }
1481 }
1482
1483 static void power_down_all_hw_blocks(struct dc *dc)
1484 {
1485 power_down_encoders(dc);
1486
1487 power_down_controllers(dc);
1488
1489 power_down_clock_sources(dc);
1490
1491 if (dc->fbc_compressor)
1492 dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
1493 }
1494
1495 static void disable_vga_and_power_gate_all_controllers(
1496 struct dc *dc)
1497 {
1498 int i;
1499 struct timing_generator *tg;
1500 struct dc_context *ctx = dc->ctx;
1501
1502 for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
1503 tg = dc->res_pool->timing_generators[i];
1504
1505 if (tg->funcs->disable_vga)
1506 tg->funcs->disable_vga(tg);
1507 }
1508 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1509
1510
1511 enable_display_pipe_clock_gating(ctx,
1512 true);
1513
1514 dc->current_state->res_ctx.pipe_ctx[i].pipe_idx = i;
1515 dc->hwss.disable_plane(dc,
1516 &dc->current_state->res_ctx.pipe_ctx[i]);
1517 }
1518 }
1519
1520
1521 static struct dc_stream_state *get_edp_stream(struct dc_state *context)
1522 {
1523 int i;
1524
1525 for (i = 0; i < context->stream_count; i++) {
1526 if (context->streams[i]->signal == SIGNAL_TYPE_EDP)
1527 return context->streams[i];
1528 }
1529 return NULL;
1530 }
1531
1532 static struct dc_link *get_edp_link(struct dc *dc)
1533 {
1534 int i;
1535
1536
1537 for (i = 0; i < dc->link_count; i++) {
1538 if (dc->links[i]->connector_signal == SIGNAL_TYPE_EDP)
1539 return dc->links[i];
1540 }
1541 return NULL;
1542 }
1543
1544 static struct dc_link *get_edp_link_with_sink(
1545 struct dc *dc,
1546 struct dc_state *context)
1547 {
1548 int i;
1549 struct dc_link *link = NULL;
1550
1551
1552 for (i = 0; i < dc->link_count; i++) {
1553 if (dc->links[i]->local_sink &&
1554 dc->links[i]->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
1555 link = dc->links[i];
1556 break;
1557 }
1558 }
1559
1560 return link;
1561 }
1562
1563
1564
1565
1566
1567
1568
1569
1570 void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context)
1571 {
1572 int i;
1573 struct dc_link *edp_link_with_sink = get_edp_link_with_sink(dc, context);
1574 struct dc_link *edp_link = get_edp_link(dc);
1575 struct dc_stream_state *edp_stream = NULL;
1576 bool can_apply_edp_fast_boot = false;
1577 bool can_apply_seamless_boot = false;
1578 bool keep_edp_vdd_on = false;
1579
1580 if (dc->hwss.init_pipes)
1581 dc->hwss.init_pipes(dc, context);
1582
1583 edp_stream = get_edp_stream(context);
1584
1585
1586 if (edp_link && dc->ctx->dce_version != DCE_VERSION_8_0 &&
1587 dc->ctx->dce_version != DCE_VERSION_8_1 &&
1588 dc->ctx->dce_version != DCE_VERSION_8_3) {
1589
1590
1591 if (edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc)) {
1592
1593 if (edp_stream) {
1594 edp_stream->apply_edp_fast_boot_optimization = true;
1595 can_apply_edp_fast_boot = true;
1596 }
1597 }
1598
1599
1600 if (edp_stream)
1601 keep_edp_vdd_on = true;
1602 }
1603
1604
1605 for (i = 0; i < context->stream_count; i++) {
1606 if (context->streams[i]->apply_seamless_boot_optimization) {
1607 can_apply_seamless_boot = true;
1608 break;
1609 }
1610 }
1611
1612
1613
1614
1615 if (!can_apply_edp_fast_boot && !can_apply_seamless_boot) {
1616 if (edp_link_with_sink && !keep_edp_vdd_on) {
1617
1618 dc->hwss.edp_backlight_control(edp_link_with_sink, false);
1619 }
1620
1621 power_down_all_hw_blocks(dc);
1622 disable_vga_and_power_gate_all_controllers(dc);
1623 if (edp_link_with_sink && !keep_edp_vdd_on)
1624 dc->hwss.edp_power_control(edp_link_with_sink, false);
1625 }
1626 bios_set_scratch_acc_mode_change(dc->ctx->dc_bios);
1627 }
1628
1629 static uint32_t compute_pstate_blackout_duration(
1630 struct bw_fixed blackout_duration,
1631 const struct dc_stream_state *stream)
1632 {
1633 uint32_t total_dest_line_time_ns;
1634 uint32_t pstate_blackout_duration_ns;
1635
1636 pstate_blackout_duration_ns = 1000 * blackout_duration.value >> 24;
1637
1638 total_dest_line_time_ns = 1000000UL *
1639 (stream->timing.h_total * 10) /
1640 stream->timing.pix_clk_100hz +
1641 pstate_blackout_duration_ns;
1642
1643 return total_dest_line_time_ns;
1644 }
1645
1646 static void dce110_set_displaymarks(
1647 const struct dc *dc,
1648 struct dc_state *context)
1649 {
1650 uint8_t i, num_pipes;
1651 unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
1652
1653 for (i = 0, num_pipes = 0; i < MAX_PIPES; i++) {
1654 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1655 uint32_t total_dest_line_time_ns;
1656
1657 if (pipe_ctx->stream == NULL)
1658 continue;
1659
1660 total_dest_line_time_ns = compute_pstate_blackout_duration(
1661 dc->bw_vbios->blackout_duration, pipe_ctx->stream);
1662 pipe_ctx->plane_res.mi->funcs->mem_input_program_display_marks(
1663 pipe_ctx->plane_res.mi,
1664 context->bw_ctx.bw.dce.nbp_state_change_wm_ns[num_pipes],
1665 context->bw_ctx.bw.dce.stutter_exit_wm_ns[num_pipes],
1666 context->bw_ctx.bw.dce.stutter_entry_wm_ns[num_pipes],
1667 context->bw_ctx.bw.dce.urgent_wm_ns[num_pipes],
1668 total_dest_line_time_ns);
1669 if (i == underlay_idx) {
1670 num_pipes++;
1671 pipe_ctx->plane_res.mi->funcs->mem_input_program_chroma_display_marks(
1672 pipe_ctx->plane_res.mi,
1673 context->bw_ctx.bw.dce.nbp_state_change_wm_ns[num_pipes],
1674 context->bw_ctx.bw.dce.stutter_exit_wm_ns[num_pipes],
1675 context->bw_ctx.bw.dce.urgent_wm_ns[num_pipes],
1676 total_dest_line_time_ns);
1677 }
1678 num_pipes++;
1679 }
1680 }
1681
1682 void dce110_set_safe_displaymarks(
1683 struct resource_context *res_ctx,
1684 const struct resource_pool *pool)
1685 {
1686 int i;
1687 int underlay_idx = pool->underlay_pipe_index;
1688 struct dce_watermarks max_marks = {
1689 MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK };
1690 struct dce_watermarks nbp_marks = {
1691 SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK };
1692 struct dce_watermarks min_marks = { 0, 0, 0, 0};
1693
1694 for (i = 0; i < MAX_PIPES; i++) {
1695 if (res_ctx->pipe_ctx[i].stream == NULL || res_ctx->pipe_ctx[i].plane_res.mi == NULL)
1696 continue;
1697
1698 res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_display_marks(
1699 res_ctx->pipe_ctx[i].plane_res.mi,
1700 nbp_marks,
1701 max_marks,
1702 min_marks,
1703 max_marks,
1704 MAX_WATERMARK);
1705
1706 if (i == underlay_idx)
1707 res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_chroma_display_marks(
1708 res_ctx->pipe_ctx[i].plane_res.mi,
1709 nbp_marks,
1710 max_marks,
1711 max_marks,
1712 MAX_WATERMARK);
1713
1714 }
1715 }
1716
1717
1718
1719
1720
1721 static void set_drr(struct pipe_ctx **pipe_ctx,
1722 int num_pipes, unsigned int vmin, unsigned int vmax,
1723 unsigned int vmid, unsigned int vmid_frame_number)
1724 {
1725 int i = 0;
1726 struct drr_params params = {0};
1727
1728 unsigned int event_triggers = 0x80;
1729
1730 params.vertical_total_max = vmax;
1731 params.vertical_total_min = vmin;
1732
1733
1734
1735
1736
1737 for (i = 0; i < num_pipes; i++) {
1738 pipe_ctx[i]->stream_res.tg->funcs->set_drr(
1739 pipe_ctx[i]->stream_res.tg, ¶ms);
1740
1741 if (vmax != 0 && vmin != 0)
1742 pipe_ctx[i]->stream_res.tg->funcs->set_static_screen_control(
1743 pipe_ctx[i]->stream_res.tg,
1744 event_triggers);
1745 }
1746 }
1747
1748 static void get_position(struct pipe_ctx **pipe_ctx,
1749 int num_pipes,
1750 struct crtc_position *position)
1751 {
1752 int i = 0;
1753
1754
1755
1756 for (i = 0; i < num_pipes; i++)
1757 pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position);
1758 }
1759
1760 static void set_static_screen_control(struct pipe_ctx **pipe_ctx,
1761 int num_pipes, const struct dc_static_screen_events *events)
1762 {
1763 unsigned int i;
1764 unsigned int value = 0;
1765
1766 if (events->overlay_update)
1767 value |= 0x100;
1768 if (events->surface_update)
1769 value |= 0x80;
1770 if (events->cursor_update)
1771 value |= 0x2;
1772 if (events->force_trigger)
1773 value |= 0x1;
1774
1775 if (num_pipes) {
1776 struct dc *dc = pipe_ctx[0]->stream->ctx->dc;
1777
1778 if (dc->fbc_compressor)
1779 value |= 0x84;
1780 }
1781
1782 for (i = 0; i < num_pipes; i++)
1783 pipe_ctx[i]->stream_res.tg->funcs->
1784 set_static_screen_control(pipe_ctx[i]->stream_res.tg, value);
1785 }
1786
1787
1788
1789
1790 static bool should_enable_fbc(struct dc *dc,
1791 struct dc_state *context,
1792 uint32_t *pipe_idx)
1793 {
1794 uint32_t i;
1795 struct pipe_ctx *pipe_ctx = NULL;
1796 struct resource_context *res_ctx = &context->res_ctx;
1797 unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
1798
1799
1800 ASSERT(dc->fbc_compressor);
1801
1802
1803 if (!dc->ctx->fbc_gpu_addr)
1804 return false;
1805
1806
1807 if (context->stream_count != 1)
1808 return false;
1809
1810 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1811 if (res_ctx->pipe_ctx[i].stream) {
1812
1813 pipe_ctx = &res_ctx->pipe_ctx[i];
1814
1815 if (!pipe_ctx)
1816 continue;
1817
1818
1819 if (pipe_ctx->pipe_idx != underlay_idx) {
1820 *pipe_idx = i;
1821 break;
1822 }
1823 }
1824 }
1825
1826 if (i == dc->res_pool->pipe_count)
1827 return false;
1828
1829 if (!pipe_ctx->stream->link)
1830 return false;
1831
1832
1833 if (pipe_ctx->stream->link->connector_signal != SIGNAL_TYPE_EDP)
1834 return false;
1835
1836
1837 if (pipe_ctx->stream->link->psr_enabled)
1838 return false;
1839
1840
1841 if (!pipe_ctx->plane_state)
1842 return false;
1843
1844
1845 if (pipe_ctx->plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL)
1846 return false;
1847
1848 return true;
1849 }
1850
1851
1852
1853
1854 static void enable_fbc(
1855 struct dc *dc,
1856 struct dc_state *context)
1857 {
1858 uint32_t pipe_idx = 0;
1859
1860 if (should_enable_fbc(dc, context, &pipe_idx)) {
1861
1862 struct compr_addr_and_pitch_params params = {0, 0, 0};
1863 struct compressor *compr = dc->fbc_compressor;
1864 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx];
1865
1866 params.source_view_width = pipe_ctx->stream->timing.h_addressable;
1867 params.source_view_height = pipe_ctx->stream->timing.v_addressable;
1868 params.inst = pipe_ctx->stream_res.tg->inst;
1869 compr->compr_surface_address.quad_part = dc->ctx->fbc_gpu_addr;
1870
1871 compr->funcs->surface_address_and_pitch(compr, ¶ms);
1872 compr->funcs->set_fbc_invalidation_triggers(compr, 1);
1873
1874 compr->funcs->enable_fbc(compr, ¶ms);
1875 }
1876 }
1877
1878 static void dce110_reset_hw_ctx_wrap(
1879 struct dc *dc,
1880 struct dc_state *context)
1881 {
1882 int i;
1883
1884
1885
1886 for (i = 0; i < MAX_PIPES; i++) {
1887 struct pipe_ctx *pipe_ctx_old =
1888 &dc->current_state->res_ctx.pipe_ctx[i];
1889 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1890
1891
1892
1893
1894
1895
1896
1897 if (!pipe_ctx_old->stream || pipe_ctx_old->top_pipe)
1898 continue;
1899
1900 if (!pipe_ctx->stream ||
1901 pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) {
1902 struct clock_source *old_clk = pipe_ctx_old->clock_source;
1903
1904
1905
1906
1907 if (!pipe_ctx->stream || !pipe_ctx->stream->dpms_off) {
1908 core_link_disable_stream(pipe_ctx_old);
1909
1910
1911 if (pipe_ctx_old->stream_res.audio) {
1912
1913 pipe_ctx_old->stream_res.audio->funcs->
1914 az_disable(pipe_ctx_old->stream_res.audio);
1915
1916
1917 if (dc->caps.dynamic_audio == true) {
1918
1919
1920 update_audio_usage(&dc->current_state->res_ctx, dc->res_pool,
1921 pipe_ctx_old->stream_res.audio, false);
1922 pipe_ctx_old->stream_res.audio = NULL;
1923 }
1924 }
1925 }
1926
1927 pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true);
1928 if (!hwss_wait_for_blank_complete(pipe_ctx_old->stream_res.tg)) {
1929 dm_error("DC: failed to blank crtc!\n");
1930 BREAK_TO_DEBUGGER();
1931 }
1932 pipe_ctx_old->stream_res.tg->funcs->disable_crtc(pipe_ctx_old->stream_res.tg);
1933 pipe_ctx_old->plane_res.mi->funcs->free_mem_input(
1934 pipe_ctx_old->plane_res.mi, dc->current_state->stream_count);
1935
1936 if (old_clk && 0 == resource_get_clock_source_reference(&context->res_ctx,
1937 dc->res_pool,
1938 old_clk))
1939 old_clk->funcs->cs_power_down(old_clk);
1940
1941 dc->hwss.disable_plane(dc, pipe_ctx_old);
1942
1943 pipe_ctx_old->stream = NULL;
1944 }
1945 }
1946 }
1947
1948 static void dce110_setup_audio_dto(
1949 struct dc *dc,
1950 struct dc_state *context)
1951 {
1952 int i;
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1974 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1975
1976 if (pipe_ctx->stream == NULL)
1977 continue;
1978
1979 if (pipe_ctx->top_pipe)
1980 continue;
1981
1982 if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A)
1983 continue;
1984
1985 if (pipe_ctx->stream_res.audio != NULL) {
1986 struct audio_output audio_output;
1987
1988 build_audio_output(context, pipe_ctx, &audio_output);
1989
1990 pipe_ctx->stream_res.audio->funcs->wall_dto_setup(
1991 pipe_ctx->stream_res.audio,
1992 pipe_ctx->stream->signal,
1993 &audio_output.crtc_info,
1994 &audio_output.pll_info);
1995 break;
1996 }
1997 }
1998
1999
2000 if (i == dc->res_pool->pipe_count) {
2001 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2002 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2003
2004 if (pipe_ctx->stream == NULL)
2005 continue;
2006
2007 if (pipe_ctx->top_pipe)
2008 continue;
2009
2010 if (!dc_is_dp_signal(pipe_ctx->stream->signal))
2011 continue;
2012
2013 if (pipe_ctx->stream_res.audio != NULL) {
2014 struct audio_output audio_output;
2015
2016 build_audio_output(context, pipe_ctx, &audio_output);
2017
2018 pipe_ctx->stream_res.audio->funcs->wall_dto_setup(
2019 pipe_ctx->stream_res.audio,
2020 pipe_ctx->stream->signal,
2021 &audio_output.crtc_info,
2022 &audio_output.pll_info);
2023 break;
2024 }
2025 }
2026 }
2027 }
2028
2029 enum dc_status dce110_apply_ctx_to_hw(
2030 struct dc *dc,
2031 struct dc_state *context)
2032 {
2033 struct dc_bios *dcb = dc->ctx->dc_bios;
2034 enum dc_status status;
2035 int i;
2036
2037
2038
2039 dc->hwss.reset_hw_ctx_wrap(dc, context);
2040
2041
2042 if (context->stream_count <= 0)
2043 return DC_OK;
2044
2045
2046 dcb->funcs->set_scratch_critical_state(dcb, true);
2047
2048
2049 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2050 struct pipe_ctx *pipe_ctx_old =
2051 &dc->current_state->res_ctx.pipe_ctx[i];
2052 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2053
2054 if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe)
2055 continue;
2056
2057 if (pipe_ctx->stream == pipe_ctx_old->stream) {
2058 if (pipe_ctx_old->clock_source != pipe_ctx->clock_source)
2059 dce_crtc_switch_to_clk_src(dc->hwseq,
2060 pipe_ctx->clock_source, i);
2061 continue;
2062 }
2063
2064 dc->hwss.enable_display_power_gating(
2065 dc, i, dc->ctx->dc_bios,
2066 PIPE_GATING_CONTROL_DISABLE);
2067 }
2068
2069 if (dc->fbc_compressor)
2070 dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
2071
2072 dce110_setup_audio_dto(dc, context);
2073
2074 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2075 struct pipe_ctx *pipe_ctx_old =
2076 &dc->current_state->res_ctx.pipe_ctx[i];
2077 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2078
2079 if (pipe_ctx->stream == NULL)
2080 continue;
2081
2082 if (pipe_ctx->stream == pipe_ctx_old->stream &&
2083 pipe_ctx->stream->link->link_state_valid) {
2084 continue;
2085 }
2086
2087 if (pipe_ctx_old->stream && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx))
2088 continue;
2089
2090 if (pipe_ctx->top_pipe || pipe_ctx->prev_odm_pipe)
2091 continue;
2092
2093 status = apply_single_controller_ctx_to_hw(
2094 pipe_ctx,
2095 context,
2096 dc);
2097
2098 if (DC_OK != status)
2099 return status;
2100 }
2101
2102 if (dc->fbc_compressor)
2103 enable_fbc(dc, dc->current_state);
2104
2105 dcb->funcs->set_scratch_critical_state(dcb, false);
2106
2107 return DC_OK;
2108 }
2109
2110
2111
2112
2113 static void set_default_colors(struct pipe_ctx *pipe_ctx)
2114 {
2115 struct default_adjustment default_adjust = { 0 };
2116
2117 default_adjust.force_hw_default = false;
2118 default_adjust.in_color_space = pipe_ctx->plane_state->color_space;
2119 default_adjust.out_color_space = pipe_ctx->stream->output_color_space;
2120 default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW;
2121 default_adjust.surface_pixel_format = pipe_ctx->plane_res.scl_data.format;
2122
2123
2124 default_adjust.color_depth =
2125 pipe_ctx->stream->timing.display_color_depth;
2126
2127
2128 default_adjust.lb_color_depth = pipe_ctx->plane_res.scl_data.lb_params.depth;
2129
2130 pipe_ctx->plane_res.xfm->funcs->opp_set_csc_default(
2131 pipe_ctx->plane_res.xfm, &default_adjust);
2132 }
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154 static void program_surface_visibility(const struct dc *dc,
2155 struct pipe_ctx *pipe_ctx)
2156 {
2157 enum blnd_mode blender_mode = BLND_MODE_CURRENT_PIPE;
2158 bool blank_target = false;
2159
2160 if (pipe_ctx->bottom_pipe) {
2161
2162
2163 ASSERT(pipe_ctx->bottom_pipe->bottom_pipe == NULL);
2164
2165 if (pipe_ctx->bottom_pipe->plane_state->visible) {
2166 if (pipe_ctx->plane_state->visible)
2167 blender_mode = BLND_MODE_BLENDING;
2168 else
2169 blender_mode = BLND_MODE_OTHER_PIPE;
2170
2171 } else if (!pipe_ctx->plane_state->visible)
2172 blank_target = true;
2173
2174 } else if (!pipe_ctx->plane_state->visible)
2175 blank_target = true;
2176
2177 dce_set_blender_mode(dc->hwseq, pipe_ctx->stream_res.tg->inst, blender_mode);
2178 pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, blank_target);
2179
2180 }
2181
2182 static void program_gamut_remap(struct pipe_ctx *pipe_ctx)
2183 {
2184 int i = 0;
2185 struct xfm_grph_csc_adjustment adjust;
2186 memset(&adjust, 0, sizeof(adjust));
2187 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
2188
2189
2190 if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) {
2191 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
2192
2193 for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++)
2194 adjust.temperature_matrix[i] =
2195 pipe_ctx->stream->gamut_remap_matrix.matrix[i];
2196 }
2197
2198 pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust);
2199 }
2200 static void update_plane_addr(const struct dc *dc,
2201 struct pipe_ctx *pipe_ctx)
2202 {
2203 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
2204
2205 if (plane_state == NULL)
2206 return;
2207
2208 pipe_ctx->plane_res.mi->funcs->mem_input_program_surface_flip_and_addr(
2209 pipe_ctx->plane_res.mi,
2210 &plane_state->address,
2211 plane_state->flip_immediate);
2212
2213 plane_state->status.requested_address = plane_state->address;
2214 }
2215
2216 static void dce110_update_pending_status(struct pipe_ctx *pipe_ctx)
2217 {
2218 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
2219
2220 if (plane_state == NULL)
2221 return;
2222
2223 plane_state->status.is_flip_pending =
2224 pipe_ctx->plane_res.mi->funcs->mem_input_is_flip_pending(
2225 pipe_ctx->plane_res.mi);
2226
2227 if (plane_state->status.is_flip_pending && !plane_state->visible)
2228 pipe_ctx->plane_res.mi->current_address = pipe_ctx->plane_res.mi->request_address;
2229
2230 plane_state->status.current_address = pipe_ctx->plane_res.mi->current_address;
2231 if (pipe_ctx->plane_res.mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO &&
2232 pipe_ctx->stream_res.tg->funcs->is_stereo_left_eye) {
2233 plane_state->status.is_right_eye =\
2234 !pipe_ctx->stream_res.tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg);
2235 }
2236 }
2237
2238 void dce110_power_down(struct dc *dc)
2239 {
2240 power_down_all_hw_blocks(dc);
2241 disable_vga_and_power_gate_all_controllers(dc);
2242 }
2243
2244 static bool wait_for_reset_trigger_to_occur(
2245 struct dc_context *dc_ctx,
2246 struct timing_generator *tg)
2247 {
2248 bool rc = false;
2249
2250
2251
2252 const uint32_t frames_to_wait_on_triggered_reset = 10;
2253 uint32_t i;
2254
2255 for (i = 0; i < frames_to_wait_on_triggered_reset; i++) {
2256
2257 if (!tg->funcs->is_counter_moving(tg)) {
2258 DC_ERROR("TG counter is not moving!\n");
2259 break;
2260 }
2261
2262 if (tg->funcs->did_triggered_reset_occur(tg)) {
2263 rc = true;
2264
2265 DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n",
2266 i);
2267 break;
2268 }
2269
2270
2271 tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE);
2272 tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK);
2273 }
2274
2275 if (false == rc)
2276 DC_ERROR("GSL: Timeout on reset trigger!\n");
2277
2278 return rc;
2279 }
2280
2281
2282 static void dce110_enable_timing_synchronization(
2283 struct dc *dc,
2284 int group_index,
2285 int group_size,
2286 struct pipe_ctx *grouped_pipes[])
2287 {
2288 struct dc_context *dc_ctx = dc->ctx;
2289 struct dcp_gsl_params gsl_params = { 0 };
2290 int i;
2291
2292 DC_SYNC_INFO("GSL: Setting-up...\n");
2293
2294
2295
2296
2297 gsl_params.gsl_group = 0;
2298 gsl_params.gsl_master = grouped_pipes[0]->stream_res.tg->inst;
2299
2300 for (i = 0; i < group_size; i++)
2301 grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock(
2302 grouped_pipes[i]->stream_res.tg, &gsl_params);
2303
2304
2305 DC_SYNC_INFO("GSL: enabling trigger-reset\n");
2306
2307 for (i = 1 ; i < group_size; i++)
2308 grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger(
2309 grouped_pipes[i]->stream_res.tg,
2310 gsl_params.gsl_group);
2311
2312 for (i = 1 ; i < group_size; i++) {
2313 DC_SYNC_INFO("GSL: waiting for reset to occur.\n");
2314 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg);
2315 grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger(
2316 grouped_pipes[i]->stream_res.tg);
2317 }
2318
2319
2320
2321 DC_SYNC_INFO("GSL: Restoring register states.\n");
2322 for (i = 0; i < group_size; i++)
2323 grouped_pipes[i]->stream_res.tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->stream_res.tg);
2324
2325 DC_SYNC_INFO("GSL: Set-up complete.\n");
2326 }
2327
2328 static void dce110_enable_per_frame_crtc_position_reset(
2329 struct dc *dc,
2330 int group_size,
2331 struct pipe_ctx *grouped_pipes[])
2332 {
2333 struct dc_context *dc_ctx = dc->ctx;
2334 struct dcp_gsl_params gsl_params = { 0 };
2335 int i;
2336
2337 gsl_params.gsl_group = 0;
2338 gsl_params.gsl_master = 0;
2339
2340 for (i = 0; i < group_size; i++)
2341 grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock(
2342 grouped_pipes[i]->stream_res.tg, &gsl_params);
2343
2344 DC_SYNC_INFO("GSL: enabling trigger-reset\n");
2345
2346 for (i = 1; i < group_size; i++)
2347 grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset(
2348 grouped_pipes[i]->stream_res.tg,
2349 gsl_params.gsl_master,
2350 &grouped_pipes[i]->stream->triggered_crtc_reset);
2351
2352 DC_SYNC_INFO("GSL: waiting for reset to occur.\n");
2353 for (i = 1; i < group_size; i++)
2354 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg);
2355
2356 for (i = 0; i < group_size; i++)
2357 grouped_pipes[i]->stream_res.tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->stream_res.tg);
2358
2359 }
2360
2361 static void init_pipes(struct dc *dc, struct dc_state *context)
2362 {
2363
2364 }
2365
2366 static void init_hw(struct dc *dc)
2367 {
2368 int i;
2369 struct dc_bios *bp;
2370 struct transform *xfm;
2371 struct abm *abm;
2372 struct dmcu *dmcu;
2373
2374 bp = dc->ctx->dc_bios;
2375 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2376 xfm = dc->res_pool->transforms[i];
2377 xfm->funcs->transform_reset(xfm);
2378
2379 dc->hwss.enable_display_power_gating(
2380 dc, i, bp,
2381 PIPE_GATING_CONTROL_INIT);
2382 dc->hwss.enable_display_power_gating(
2383 dc, i, bp,
2384 PIPE_GATING_CONTROL_DISABLE);
2385 dc->hwss.enable_display_pipe_clock_gating(
2386 dc->ctx,
2387 true);
2388 }
2389
2390 dce_clock_gating_power_up(dc->hwseq, false);
2391
2392
2393 for (i = 0; i < dc->link_count; i++) {
2394
2395
2396
2397
2398 struct dc_link *link = dc->links[i];
2399
2400 link->link_enc->funcs->hw_init(link->link_enc);
2401 }
2402
2403 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2404 struct timing_generator *tg = dc->res_pool->timing_generators[i];
2405
2406 tg->funcs->disable_vga(tg);
2407
2408
2409
2410 tg->funcs->set_blank(tg, true);
2411 hwss_wait_for_blank_complete(tg);
2412 }
2413
2414 for (i = 0; i < dc->res_pool->audio_count; i++) {
2415 struct audio *audio = dc->res_pool->audios[i];
2416 audio->funcs->hw_init(audio);
2417 }
2418
2419 abm = dc->res_pool->abm;
2420 if (abm != NULL) {
2421 abm->funcs->init_backlight(abm);
2422 abm->funcs->abm_init(abm);
2423 }
2424
2425 dmcu = dc->res_pool->dmcu;
2426 if (dmcu != NULL && abm != NULL)
2427 abm->dmcu_is_running = dmcu->funcs->is_dmcu_initialized(dmcu);
2428
2429 if (dc->fbc_compressor)
2430 dc->fbc_compressor->funcs->power_up_fbc(dc->fbc_compressor);
2431
2432 }
2433
2434
2435 void dce110_prepare_bandwidth(
2436 struct dc *dc,
2437 struct dc_state *context)
2438 {
2439 struct clk_mgr *dccg = dc->clk_mgr;
2440
2441 dce110_set_safe_displaymarks(&context->res_ctx, dc->res_pool);
2442
2443 dccg->funcs->update_clocks(
2444 dccg,
2445 context,
2446 false);
2447 }
2448
2449 void dce110_optimize_bandwidth(
2450 struct dc *dc,
2451 struct dc_state *context)
2452 {
2453 struct clk_mgr *dccg = dc->clk_mgr;
2454
2455 dce110_set_displaymarks(dc, context);
2456
2457 dccg->funcs->update_clocks(
2458 dccg,
2459 context,
2460 true);
2461 }
2462
2463 static void dce110_program_front_end_for_pipe(
2464 struct dc *dc, struct pipe_ctx *pipe_ctx)
2465 {
2466 struct mem_input *mi = pipe_ctx->plane_res.mi;
2467 struct pipe_ctx *old_pipe = NULL;
2468 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
2469 struct xfm_grph_csc_adjustment adjust;
2470 struct out_csc_color_matrix tbl_entry;
2471 unsigned int i;
2472 DC_LOGGER_INIT();
2473 memset(&tbl_entry, 0, sizeof(tbl_entry));
2474
2475 if (dc->current_state)
2476 old_pipe = &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
2477
2478 memset(&adjust, 0, sizeof(adjust));
2479 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
2480
2481 dce_enable_fe_clock(dc->hwseq, mi->inst, true);
2482
2483 set_default_colors(pipe_ctx);
2484 if (pipe_ctx->stream->csc_color_matrix.enable_adjustment
2485 == true) {
2486 tbl_entry.color_space =
2487 pipe_ctx->stream->output_color_space;
2488
2489 for (i = 0; i < 12; i++)
2490 tbl_entry.regval[i] =
2491 pipe_ctx->stream->csc_color_matrix.matrix[i];
2492
2493 pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment
2494 (pipe_ctx->plane_res.xfm, &tbl_entry);
2495 }
2496
2497 if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) {
2498 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
2499
2500 for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++)
2501 adjust.temperature_matrix[i] =
2502 pipe_ctx->stream->gamut_remap_matrix.matrix[i];
2503 }
2504
2505 pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust);
2506
2507 pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
2508
2509 program_scaler(dc, pipe_ctx);
2510
2511 mi->funcs->mem_input_program_surface_config(
2512 mi,
2513 plane_state->format,
2514 &plane_state->tiling_info,
2515 &plane_state->plane_size,
2516 plane_state->rotation,
2517 NULL,
2518 false);
2519 if (mi->funcs->set_blank)
2520 mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible);
2521
2522 if (dc->config.gpu_vm_support)
2523 mi->funcs->mem_input_program_pte_vm(
2524 pipe_ctx->plane_res.mi,
2525 plane_state->format,
2526 &plane_state->tiling_info,
2527 plane_state->rotation);
2528
2529
2530 if (pipe_ctx->plane_state->update_flags.bits.full_update ||
2531 pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
2532 pipe_ctx->plane_state->update_flags.bits.gamma_change)
2533 dc->hwss.set_input_transfer_func(pipe_ctx, pipe_ctx->plane_state);
2534
2535 if (pipe_ctx->plane_state->update_flags.bits.full_update)
2536 dc->hwss.set_output_transfer_func(pipe_ctx, pipe_ctx->stream);
2537
2538 DC_LOG_SURFACE(
2539 "Pipe:%d %p: addr hi:0x%x, "
2540 "addr low:0x%x, "
2541 "src: %d, %d, %d,"
2542 " %d; dst: %d, %d, %d, %d;"
2543 "clip: %d, %d, %d, %d\n",
2544 pipe_ctx->pipe_idx,
2545 (void *) pipe_ctx->plane_state,
2546 pipe_ctx->plane_state->address.grph.addr.high_part,
2547 pipe_ctx->plane_state->address.grph.addr.low_part,
2548 pipe_ctx->plane_state->src_rect.x,
2549 pipe_ctx->plane_state->src_rect.y,
2550 pipe_ctx->plane_state->src_rect.width,
2551 pipe_ctx->plane_state->src_rect.height,
2552 pipe_ctx->plane_state->dst_rect.x,
2553 pipe_ctx->plane_state->dst_rect.y,
2554 pipe_ctx->plane_state->dst_rect.width,
2555 pipe_ctx->plane_state->dst_rect.height,
2556 pipe_ctx->plane_state->clip_rect.x,
2557 pipe_ctx->plane_state->clip_rect.y,
2558 pipe_ctx->plane_state->clip_rect.width,
2559 pipe_ctx->plane_state->clip_rect.height);
2560
2561 DC_LOG_SURFACE(
2562 "Pipe %d: width, height, x, y\n"
2563 "viewport:%d, %d, %d, %d\n"
2564 "recout: %d, %d, %d, %d\n",
2565 pipe_ctx->pipe_idx,
2566 pipe_ctx->plane_res.scl_data.viewport.width,
2567 pipe_ctx->plane_res.scl_data.viewport.height,
2568 pipe_ctx->plane_res.scl_data.viewport.x,
2569 pipe_ctx->plane_res.scl_data.viewport.y,
2570 pipe_ctx->plane_res.scl_data.recout.width,
2571 pipe_ctx->plane_res.scl_data.recout.height,
2572 pipe_ctx->plane_res.scl_data.recout.x,
2573 pipe_ctx->plane_res.scl_data.recout.y);
2574 }
2575
2576 static void dce110_apply_ctx_for_surface(
2577 struct dc *dc,
2578 const struct dc_stream_state *stream,
2579 int num_planes,
2580 struct dc_state *context)
2581 {
2582 int i;
2583
2584 if (num_planes == 0)
2585 return;
2586
2587 if (dc->fbc_compressor)
2588 dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
2589
2590 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2591 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2592 struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
2593
2594 if (stream == pipe_ctx->stream) {
2595 if (!pipe_ctx->top_pipe &&
2596 (pipe_ctx->plane_state || old_pipe_ctx->plane_state))
2597 dc->hwss.pipe_control_lock(dc, pipe_ctx, true);
2598 }
2599 }
2600
2601 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2602 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2603
2604 if (pipe_ctx->stream != stream)
2605 continue;
2606
2607
2608 pipe_ctx->plane_res.mi->funcs->allocate_mem_input(
2609 pipe_ctx->plane_res.mi,
2610 pipe_ctx->stream->timing.h_total,
2611 pipe_ctx->stream->timing.v_total,
2612 pipe_ctx->stream->timing.pix_clk_100hz / 10,
2613 context->stream_count);
2614
2615 dce110_program_front_end_for_pipe(dc, pipe_ctx);
2616
2617 dc->hwss.update_plane_addr(dc, pipe_ctx);
2618
2619 program_surface_visibility(dc, pipe_ctx);
2620
2621 }
2622
2623 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2624 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2625 struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
2626
2627 if ((stream == pipe_ctx->stream) &&
2628 (!pipe_ctx->top_pipe) &&
2629 (pipe_ctx->plane_state || old_pipe_ctx->plane_state))
2630 dc->hwss.pipe_control_lock(dc, pipe_ctx, false);
2631 }
2632
2633 if (dc->fbc_compressor)
2634 enable_fbc(dc, context);
2635 }
2636
2637 static void dce110_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx)
2638 {
2639 int fe_idx = pipe_ctx->plane_res.mi ?
2640 pipe_ctx->plane_res.mi->inst : pipe_ctx->pipe_idx;
2641
2642
2643 if (dc->current_state->res_ctx.pipe_ctx[fe_idx].stream)
2644 return;
2645
2646 dc->hwss.enable_display_power_gating(
2647 dc, fe_idx, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE);
2648
2649 dc->res_pool->transforms[fe_idx]->funcs->transform_reset(
2650 dc->res_pool->transforms[fe_idx]);
2651 }
2652
2653 static void dce110_wait_for_mpcc_disconnect(
2654 struct dc *dc,
2655 struct resource_pool *res_pool,
2656 struct pipe_ctx *pipe_ctx)
2657 {
2658
2659 }
2660
2661 static void program_output_csc(struct dc *dc,
2662 struct pipe_ctx *pipe_ctx,
2663 enum dc_color_space colorspace,
2664 uint16_t *matrix,
2665 int opp_id)
2666 {
2667 int i;
2668 struct out_csc_color_matrix tbl_entry;
2669
2670 if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) {
2671 enum dc_color_space color_space = pipe_ctx->stream->output_color_space;
2672
2673 for (i = 0; i < 12; i++)
2674 tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i];
2675
2676 tbl_entry.color_space = color_space;
2677
2678 pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment(
2679 pipe_ctx->plane_res.xfm, &tbl_entry);
2680 }
2681 }
2682
2683 void dce110_set_cursor_position(struct pipe_ctx *pipe_ctx)
2684 {
2685 struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position;
2686 struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp;
2687 struct mem_input *mi = pipe_ctx->plane_res.mi;
2688 struct dc_cursor_mi_param param = {
2689 .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10,
2690 .ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clocks.xtalin_clock_inKhz,
2691 .viewport = pipe_ctx->plane_res.scl_data.viewport,
2692 .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz,
2693 .v_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.vert,
2694 .rotation = pipe_ctx->plane_state->rotation,
2695 .mirror = pipe_ctx->plane_state->horizontal_mirror
2696 };
2697
2698 if (pipe_ctx->plane_state->address.type
2699 == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
2700 pos_cpy.enable = false;
2701
2702 if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state)
2703 pos_cpy.enable = false;
2704
2705 if (ipp->funcs->ipp_cursor_set_position)
2706 ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m);
2707 if (mi->funcs->set_cursor_position)
2708 mi->funcs->set_cursor_position(mi, &pos_cpy, ¶m);
2709 }
2710
2711 void dce110_set_cursor_attribute(struct pipe_ctx *pipe_ctx)
2712 {
2713 struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes;
2714
2715 if (pipe_ctx->plane_res.ipp &&
2716 pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes)
2717 pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes(
2718 pipe_ctx->plane_res.ipp, attributes);
2719
2720 if (pipe_ctx->plane_res.mi &&
2721 pipe_ctx->plane_res.mi->funcs->set_cursor_attributes)
2722 pipe_ctx->plane_res.mi->funcs->set_cursor_attributes(
2723 pipe_ctx->plane_res.mi, attributes);
2724
2725 if (pipe_ctx->plane_res.xfm &&
2726 pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes)
2727 pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes(
2728 pipe_ctx->plane_res.xfm, attributes);
2729 }
2730
2731 static const struct hw_sequencer_funcs dce110_funcs = {
2732 .program_gamut_remap = program_gamut_remap,
2733 .program_output_csc = program_output_csc,
2734 .init_hw = init_hw,
2735 .init_pipes = init_pipes,
2736 .apply_ctx_to_hw = dce110_apply_ctx_to_hw,
2737 .apply_ctx_for_surface = dce110_apply_ctx_for_surface,
2738 .update_plane_addr = update_plane_addr,
2739 .update_pending_status = dce110_update_pending_status,
2740 .set_input_transfer_func = dce110_set_input_transfer_func,
2741 .set_output_transfer_func = dce110_set_output_transfer_func,
2742 .power_down = dce110_power_down,
2743 .enable_accelerated_mode = dce110_enable_accelerated_mode,
2744 .enable_timing_synchronization = dce110_enable_timing_synchronization,
2745 .enable_per_frame_crtc_position_reset = dce110_enable_per_frame_crtc_position_reset,
2746 .update_info_frame = dce110_update_info_frame,
2747 .enable_stream = dce110_enable_stream,
2748 .disable_stream = dce110_disable_stream,
2749 .unblank_stream = dce110_unblank_stream,
2750 .blank_stream = dce110_blank_stream,
2751 .enable_audio_stream = dce110_enable_audio_stream,
2752 .disable_audio_stream = dce110_disable_audio_stream,
2753 .enable_display_pipe_clock_gating = enable_display_pipe_clock_gating,
2754 .enable_display_power_gating = dce110_enable_display_power_gating,
2755 .disable_plane = dce110_power_down_fe,
2756 .pipe_control_lock = dce_pipe_control_lock,
2757 .prepare_bandwidth = dce110_prepare_bandwidth,
2758 .optimize_bandwidth = dce110_optimize_bandwidth,
2759 .set_drr = set_drr,
2760 .get_position = get_position,
2761 .set_static_screen_control = set_static_screen_control,
2762 .reset_hw_ctx_wrap = dce110_reset_hw_ctx_wrap,
2763 .enable_stream_timing = dce110_enable_stream_timing,
2764 .disable_stream_gating = NULL,
2765 .enable_stream_gating = NULL,
2766 .setup_stereo = NULL,
2767 .set_avmute = dce110_set_avmute,
2768 .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect,
2769 .edp_backlight_control = dce110_edp_backlight_control,
2770 .edp_power_control = dce110_edp_power_control,
2771 .edp_wait_for_hpd_ready = dce110_edp_wait_for_hpd_ready,
2772 .set_cursor_position = dce110_set_cursor_position,
2773 .set_cursor_attribute = dce110_set_cursor_attribute
2774 };
2775
2776 void dce110_hw_sequencer_construct(struct dc *dc)
2777 {
2778 dc->hwss = dce110_funcs;
2779 }
2780