This source file includes following definitions.
- print_microsec
- log_mpc_crc
- dcn10_log_hubbub_state
- dcn10_log_hubp_states
- dcn10_log_hw_state
- dcn10_did_underflow_occur
- dcn10_enable_power_gating_plane
- dcn10_disable_vga
- dcn10_dpp_pg_control
- dcn10_hubp_pg_control
- power_on_plane
- undo_DEGVIDCN10_253_wa
- apply_DEGVIDCN10_253_wa
- dcn10_bios_golden_init
- false_optc_underflow_wa
- dcn10_enable_stream_timing
- dcn10_reset_back_end_for_pipe
- dcn10_hw_wa_force_recovery
- dcn10_verify_allow_pstate_change_high
- hwss1_plane_atomic_disconnect
- dcn10_plane_atomic_power_down
- dcn10_plane_atomic_disable
- dcn10_disable_plane
- dcn10_init_pipes
- dcn10_init_hw
- dcn10_reset_hw_ctx_wrap
- patch_address_for_sbs_tb_stereo
- dcn10_update_plane_addr
- dcn10_set_input_transfer_func
- log_tf
- dcn10_set_output_transfer_func
- dcn10_pipe_control_lock
- wait_for_reset_trigger_to_occur
- dcn10_enable_timing_synchronization
- dcn10_enable_per_frame_crtc_position_reset
- mmhub_read_vm_system_aperture_settings
- mmhub_read_vm_context0_settings
- dcn10_program_pte_vm
- dcn10_enable_plane
- dcn10_program_gamut_remap
- dcn10_is_rear_mpo_fix_required
- dcn10_set_csc_adjustment_rgb_mpo_fix
- dcn10_program_output_csc
- is_lower_pipe_tree_visible
- is_upper_pipe_tree_visible
- is_pipe_tree_visible
- is_rgb_cspace
- dcn10_get_surface_visual_confirm_color
- dcn10_get_hdr_visual_confirm_color
- fixed_point_to_int_frac
- dcn10_build_prescale_params
- update_dpp
- dcn10_update_mpcc
- update_scaler
- update_dchubp_dpp
- dcn10_blank_pixel_data
- set_hdr_multiplier
- dcn10_program_pipe
- program_all_pipe_in_tree
- find_top_pipe_for_stream
- dcn10_apply_ctx_for_surface
- dcn10_stereo_hw_frame_pack_wa
- dcn10_prepare_bandwidth
- dcn10_optimize_bandwidth
- dcn10_set_drr
- dcn10_get_position
- dcn10_set_static_screen_control
- dcn10_config_stereo_parameters
- dcn10_setup_stereo
- get_hubp_by_inst
- dcn10_wait_for_mpcc_disconnect
- dcn10_dummy_display_power_gating
- dcn10_update_pending_status
- dcn10_update_dchub
- dcn10_set_cursor_position
- dcn10_set_cursor_attribute
- dcn10_set_cursor_sdr_white_level
- apply_front_porch_workaround
- get_vupdate_offset_from_vsync
- lock_all_pipes
- calc_vupdate_position
- cal_vline_position
- dcn10_setup_periodic_interrupt
- dcn10_setup_vupdate_interrupt
- dcn10_unblank_stream
- dcn10_send_immediate_sdp_message
- dcn10_set_clock
- dcn10_get_clock
- dcn10_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 #include "dm_services.h"
28 #include "core_types.h"
29 #include "resource.h"
30 #include "custom_float.h"
31 #include "dcn10_hw_sequencer.h"
32 #include "dce110/dce110_hw_sequencer.h"
33 #include "dce/dce_hwseq.h"
34 #include "abm.h"
35 #include "dmcu.h"
36 #include "dcn10_optc.h"
37 #include "dcn10/dcn10_dpp.h"
38 #include "dcn10/dcn10_mpc.h"
39 #include "timing_generator.h"
40 #include "opp.h"
41 #include "ipp.h"
42 #include "mpc.h"
43 #include "reg_helper.h"
44 #include "dcn10_hubp.h"
45 #include "dcn10_hubbub.h"
46 #include "dcn10_cm_common.h"
47 #include "dc_link_dp.h"
48 #include "dccg.h"
49 #include "clk_mgr.h"
50
51
52 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
53 #include "dsc.h"
54 #endif
55
56 #define DC_LOGGER_INIT(logger)
57
58 #define CTX \
59 hws->ctx
60 #define REG(reg)\
61 hws->regs->reg
62
63 #undef FN
64 #define FN(reg_name, field_name) \
65 hws->shifts->field_name, hws->masks->field_name
66
67
68 #define DTN_INFO_MICRO_SEC(ref_cycle) \
69 print_microsec(dc_ctx, log_ctx, ref_cycle)
70
71 void print_microsec(struct dc_context *dc_ctx,
72 struct dc_log_buffer_ctx *log_ctx,
73 uint32_t ref_cycle)
74 {
75 const uint32_t ref_clk_mhz = dc_ctx->dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000;
76 static const unsigned int frac = 1000;
77 uint32_t us_x10 = (ref_cycle * frac) / ref_clk_mhz;
78
79 DTN_INFO(" %11d.%03d",
80 us_x10 / frac,
81 us_x10 % frac);
82 }
83
84 static void log_mpc_crc(struct dc *dc,
85 struct dc_log_buffer_ctx *log_ctx)
86 {
87 struct dc_context *dc_ctx = dc->ctx;
88 struct dce_hwseq *hws = dc->hwseq;
89
90 if (REG(MPC_CRC_RESULT_GB))
91 DTN_INFO("MPC_CRC_RESULT_GB:%d MPC_CRC_RESULT_C:%d MPC_CRC_RESULT_AR:%d\n",
92 REG_READ(MPC_CRC_RESULT_GB), REG_READ(MPC_CRC_RESULT_C), REG_READ(MPC_CRC_RESULT_AR));
93 if (REG(DPP_TOP0_DPP_CRC_VAL_B_A))
94 DTN_INFO("DPP_TOP0_DPP_CRC_VAL_B_A:%d DPP_TOP0_DPP_CRC_VAL_R_G:%d\n",
95 REG_READ(DPP_TOP0_DPP_CRC_VAL_B_A), REG_READ(DPP_TOP0_DPP_CRC_VAL_R_G));
96 }
97
98 void dcn10_log_hubbub_state(struct dc *dc, struct dc_log_buffer_ctx *log_ctx)
99 {
100 struct dc_context *dc_ctx = dc->ctx;
101 struct dcn_hubbub_wm wm;
102 int i;
103
104 memset(&wm, 0, sizeof(struct dcn_hubbub_wm));
105 dc->res_pool->hubbub->funcs->wm_read_state(dc->res_pool->hubbub, &wm);
106
107 DTN_INFO("HUBBUB WM: data_urgent pte_meta_urgent"
108 " sr_enter sr_exit dram_clk_change\n");
109
110 for (i = 0; i < 4; i++) {
111 struct dcn_hubbub_wm_set *s;
112
113 s = &wm.sets[i];
114 DTN_INFO("WM_Set[%d]:", s->wm_set);
115 DTN_INFO_MICRO_SEC(s->data_urgent);
116 DTN_INFO_MICRO_SEC(s->pte_meta_urgent);
117 DTN_INFO_MICRO_SEC(s->sr_enter);
118 DTN_INFO_MICRO_SEC(s->sr_exit);
119 DTN_INFO_MICRO_SEC(s->dram_clk_chanage);
120 DTN_INFO("\n");
121 }
122
123 DTN_INFO("\n");
124 }
125
126 static void dcn10_log_hubp_states(struct dc *dc, void *log_ctx)
127 {
128 struct dc_context *dc_ctx = dc->ctx;
129 struct resource_pool *pool = dc->res_pool;
130 int i;
131
132 DTN_INFO("HUBP: format addr_hi width height"
133 " rot mir sw_mode dcc_en blank_en ttu_dis underflow"
134 " min_ttu_vblank qos_low_wm qos_high_wm\n");
135 for (i = 0; i < pool->pipe_count; i++) {
136 struct hubp *hubp = pool->hubps[i];
137 struct dcn_hubp_state *s = &(TO_DCN10_HUBP(hubp)->state);
138
139 hubp->funcs->hubp_read_state(hubp);
140
141 if (!s->blank_en) {
142 DTN_INFO("[%2d]: %5xh %6xh %5d %6d %2xh %2xh %6xh"
143 " %6d %8d %7d %8xh",
144 hubp->inst,
145 s->pixel_format,
146 s->inuse_addr_hi,
147 s->viewport_width,
148 s->viewport_height,
149 s->rotation_angle,
150 s->h_mirror_en,
151 s->sw_mode,
152 s->dcc_en,
153 s->blank_en,
154 s->ttu_disable,
155 s->underflow_status);
156 DTN_INFO_MICRO_SEC(s->min_ttu_vblank);
157 DTN_INFO_MICRO_SEC(s->qos_level_low_wm);
158 DTN_INFO_MICRO_SEC(s->qos_level_high_wm);
159 DTN_INFO("\n");
160 }
161 }
162
163 DTN_INFO("\n=========RQ========\n");
164 DTN_INFO("HUBP: drq_exp_m prq_exp_m mrq_exp_m crq_exp_m plane1_ba L:chunk_s min_chu_s meta_ch_s"
165 " min_m_c_s dpte_gr_s mpte_gr_s swath_hei pte_row_h C:chunk_s min_chu_s meta_ch_s"
166 " min_m_c_s dpte_gr_s mpte_gr_s swath_hei pte_row_h\n");
167 for (i = 0; i < pool->pipe_count; i++) {
168 struct dcn_hubp_state *s = &(TO_DCN10_HUBP(pool->hubps[i])->state);
169 struct _vcs_dpi_display_rq_regs_st *rq_regs = &s->rq_regs;
170
171 if (!s->blank_en)
172 DTN_INFO("[%2d]: %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh\n",
173 pool->hubps[i]->inst, rq_regs->drq_expansion_mode, rq_regs->prq_expansion_mode, rq_regs->mrq_expansion_mode,
174 rq_regs->crq_expansion_mode, rq_regs->plane1_base_address, rq_regs->rq_regs_l.chunk_size,
175 rq_regs->rq_regs_l.min_chunk_size, rq_regs->rq_regs_l.meta_chunk_size,
176 rq_regs->rq_regs_l.min_meta_chunk_size, rq_regs->rq_regs_l.dpte_group_size,
177 rq_regs->rq_regs_l.mpte_group_size, rq_regs->rq_regs_l.swath_height,
178 rq_regs->rq_regs_l.pte_row_height_linear, rq_regs->rq_regs_c.chunk_size, rq_regs->rq_regs_c.min_chunk_size,
179 rq_regs->rq_regs_c.meta_chunk_size, rq_regs->rq_regs_c.min_meta_chunk_size,
180 rq_regs->rq_regs_c.dpte_group_size, rq_regs->rq_regs_c.mpte_group_size,
181 rq_regs->rq_regs_c.swath_height, rq_regs->rq_regs_c.pte_row_height_linear);
182 }
183
184 DTN_INFO("========DLG========\n");
185 DTN_INFO("HUBP: rc_hbe dlg_vbe min_d_y_n rc_per_ht rc_x_a_s "
186 " dst_y_a_s dst_y_pf dst_y_vvb dst_y_rvb dst_y_vfl dst_y_rfl rf_pix_fq"
187 " vratio_pf vrat_pf_c rc_pg_vbl rc_pg_vbc rc_mc_vbl rc_mc_vbc rc_pg_fll"
188 " rc_pg_flc rc_mc_fll rc_mc_flc pr_nom_l pr_nom_c rc_pg_nl rc_pg_nc "
189 " mr_nom_l mr_nom_c rc_mc_nl rc_mc_nc rc_ld_pl rc_ld_pc rc_ld_l "
190 " rc_ld_c cha_cur0 ofst_cur1 cha_cur1 vr_af_vc0 ddrq_limt x_rt_dlay"
191 " x_rp_dlay x_rr_sfl\n");
192 for (i = 0; i < pool->pipe_count; i++) {
193 struct dcn_hubp_state *s = &(TO_DCN10_HUBP(pool->hubps[i])->state);
194 struct _vcs_dpi_display_dlg_regs_st *dlg_regs = &s->dlg_attr;
195
196 if (!s->blank_en)
197 DTN_INFO("[%2d]: %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh"
198 "% 8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh"
199 " %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh\n",
200 pool->hubps[i]->inst, dlg_regs->refcyc_h_blank_end, dlg_regs->dlg_vblank_end, dlg_regs->min_dst_y_next_start,
201 dlg_regs->refcyc_per_htotal, dlg_regs->refcyc_x_after_scaler, dlg_regs->dst_y_after_scaler,
202 dlg_regs->dst_y_prefetch, dlg_regs->dst_y_per_vm_vblank, dlg_regs->dst_y_per_row_vblank,
203 dlg_regs->dst_y_per_vm_flip, dlg_regs->dst_y_per_row_flip, dlg_regs->ref_freq_to_pix_freq,
204 dlg_regs->vratio_prefetch, dlg_regs->vratio_prefetch_c, dlg_regs->refcyc_per_pte_group_vblank_l,
205 dlg_regs->refcyc_per_pte_group_vblank_c, dlg_regs->refcyc_per_meta_chunk_vblank_l,
206 dlg_regs->refcyc_per_meta_chunk_vblank_c, dlg_regs->refcyc_per_pte_group_flip_l,
207 dlg_regs->refcyc_per_pte_group_flip_c, dlg_regs->refcyc_per_meta_chunk_flip_l,
208 dlg_regs->refcyc_per_meta_chunk_flip_c, dlg_regs->dst_y_per_pte_row_nom_l,
209 dlg_regs->dst_y_per_pte_row_nom_c, dlg_regs->refcyc_per_pte_group_nom_l,
210 dlg_regs->refcyc_per_pte_group_nom_c, dlg_regs->dst_y_per_meta_row_nom_l,
211 dlg_regs->dst_y_per_meta_row_nom_c, dlg_regs->refcyc_per_meta_chunk_nom_l,
212 dlg_regs->refcyc_per_meta_chunk_nom_c, dlg_regs->refcyc_per_line_delivery_pre_l,
213 dlg_regs->refcyc_per_line_delivery_pre_c, dlg_regs->refcyc_per_line_delivery_l,
214 dlg_regs->refcyc_per_line_delivery_c, dlg_regs->chunk_hdl_adjust_cur0, dlg_regs->dst_y_offset_cur1,
215 dlg_regs->chunk_hdl_adjust_cur1, dlg_regs->vready_after_vcount0, dlg_regs->dst_y_delta_drq_limit,
216 dlg_regs->xfc_reg_transfer_delay, dlg_regs->xfc_reg_precharge_delay,
217 dlg_regs->xfc_reg_remote_surface_flip_latency);
218 }
219
220 DTN_INFO("========TTU========\n");
221 DTN_INFO("HUBP: qos_ll_wm qos_lh_wm mn_ttu_vb qos_l_flp rc_rd_p_l rc_rd_l rc_rd_p_c"
222 " rc_rd_c rc_rd_c0 rc_rd_pc0 rc_rd_c1 rc_rd_pc1 qos_lf_l qos_rds_l"
223 " qos_lf_c qos_rds_c qos_lf_c0 qos_rds_c0 qos_lf_c1 qos_rds_c1\n");
224 for (i = 0; i < pool->pipe_count; i++) {
225 struct dcn_hubp_state *s = &(TO_DCN10_HUBP(pool->hubps[i])->state);
226 struct _vcs_dpi_display_ttu_regs_st *ttu_regs = &s->ttu_attr;
227
228 if (!s->blank_en)
229 DTN_INFO("[%2d]: %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh\n",
230 pool->hubps[i]->inst, ttu_regs->qos_level_low_wm, ttu_regs->qos_level_high_wm, ttu_regs->min_ttu_vblank,
231 ttu_regs->qos_level_flip, ttu_regs->refcyc_per_req_delivery_pre_l, ttu_regs->refcyc_per_req_delivery_l,
232 ttu_regs->refcyc_per_req_delivery_pre_c, ttu_regs->refcyc_per_req_delivery_c, ttu_regs->refcyc_per_req_delivery_cur0,
233 ttu_regs->refcyc_per_req_delivery_pre_cur0, ttu_regs->refcyc_per_req_delivery_cur1,
234 ttu_regs->refcyc_per_req_delivery_pre_cur1, ttu_regs->qos_level_fixed_l, ttu_regs->qos_ramp_disable_l,
235 ttu_regs->qos_level_fixed_c, ttu_regs->qos_ramp_disable_c, ttu_regs->qos_level_fixed_cur0,
236 ttu_regs->qos_ramp_disable_cur0, ttu_regs->qos_level_fixed_cur1, ttu_regs->qos_ramp_disable_cur1);
237 }
238 DTN_INFO("\n");
239 }
240
241 void dcn10_log_hw_state(struct dc *dc,
242 struct dc_log_buffer_ctx *log_ctx)
243 {
244 struct dc_context *dc_ctx = dc->ctx;
245 struct resource_pool *pool = dc->res_pool;
246 int i;
247
248 DTN_INFO_BEGIN();
249
250 dcn10_log_hubbub_state(dc, log_ctx);
251
252 dcn10_log_hubp_states(dc, log_ctx);
253
254 DTN_INFO("DPP: IGAM format IGAM mode DGAM mode RGAM mode"
255 " GAMUT mode C11 C12 C13 C14 C21 C22 C23 C24 "
256 "C31 C32 C33 C34\n");
257 for (i = 0; i < pool->pipe_count; i++) {
258 struct dpp *dpp = pool->dpps[i];
259 struct dcn_dpp_state s = {0};
260
261 dpp->funcs->dpp_read_state(dpp, &s);
262
263 if (!s.is_enabled)
264 continue;
265
266 DTN_INFO("[%2d]: %11xh %-11s %-11s %-11s"
267 "%8x %08xh %08xh %08xh %08xh %08xh %08xh",
268 dpp->inst,
269 s.igam_input_format,
270 (s.igam_lut_mode == 0) ? "BypassFixed" :
271 ((s.igam_lut_mode == 1) ? "BypassFloat" :
272 ((s.igam_lut_mode == 2) ? "RAM" :
273 ((s.igam_lut_mode == 3) ? "RAM" :
274 "Unknown"))),
275 (s.dgam_lut_mode == 0) ? "Bypass" :
276 ((s.dgam_lut_mode == 1) ? "sRGB" :
277 ((s.dgam_lut_mode == 2) ? "Ycc" :
278 ((s.dgam_lut_mode == 3) ? "RAM" :
279 ((s.dgam_lut_mode == 4) ? "RAM" :
280 "Unknown")))),
281 (s.rgam_lut_mode == 0) ? "Bypass" :
282 ((s.rgam_lut_mode == 1) ? "sRGB" :
283 ((s.rgam_lut_mode == 2) ? "Ycc" :
284 ((s.rgam_lut_mode == 3) ? "RAM" :
285 ((s.rgam_lut_mode == 4) ? "RAM" :
286 "Unknown")))),
287 s.gamut_remap_mode,
288 s.gamut_remap_c11_c12,
289 s.gamut_remap_c13_c14,
290 s.gamut_remap_c21_c22,
291 s.gamut_remap_c23_c24,
292 s.gamut_remap_c31_c32,
293 s.gamut_remap_c33_c34);
294 DTN_INFO("\n");
295 }
296 DTN_INFO("\n");
297
298 DTN_INFO("MPCC: OPP DPP MPCCBOT MODE ALPHA_MODE PREMULT OVERLAP_ONLY IDLE\n");
299 for (i = 0; i < pool->pipe_count; i++) {
300 struct mpcc_state s = {0};
301
302 pool->mpc->funcs->read_mpcc_state(pool->mpc, i, &s);
303 if (s.opp_id != 0xf)
304 DTN_INFO("[%2d]: %2xh %2xh %6xh %4d %10d %7d %12d %4d\n",
305 i, s.opp_id, s.dpp_id, s.bot_mpcc_id,
306 s.mode, s.alpha_mode, s.pre_multiplied_alpha, s.overlap_only,
307 s.idle);
308 }
309 DTN_INFO("\n");
310
311 DTN_INFO("OTG: v_bs v_be v_ss v_se vpol vmax vmin vmax_sel vmin_sel"
312 " h_bs h_be h_ss h_se hpol htot vtot underflow\n");
313
314 for (i = 0; i < pool->timing_generator_count; i++) {
315 struct timing_generator *tg = pool->timing_generators[i];
316 struct dcn_otg_state s = {0};
317
318 optc1_read_otg_state(DCN10TG_FROM_TG(tg), &s);
319
320
321 if ((s.otg_enabled & 1) == 0)
322 continue;
323
324 DTN_INFO("[%d]: %5d %5d %5d %5d %5d %5d %5d %9d %9d %5d %5d %5d"
325 " %5d %5d %5d %5d %9d\n",
326 tg->inst,
327 s.v_blank_start,
328 s.v_blank_end,
329 s.v_sync_a_start,
330 s.v_sync_a_end,
331 s.v_sync_a_pol,
332 s.v_total_max,
333 s.v_total_min,
334 s.v_total_max_sel,
335 s.v_total_min_sel,
336 s.h_blank_start,
337 s.h_blank_end,
338 s.h_sync_a_start,
339 s.h_sync_a_end,
340 s.h_sync_a_pol,
341 s.h_total,
342 s.v_total,
343 s.underflow_occurred_status);
344
345
346
347
348
349 tg->funcs->clear_optc_underflow(tg);
350 }
351 DTN_INFO("\n");
352
353 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
354 DTN_INFO("DSC: CLOCK_EN SLICE_WIDTH Bytes_pp\n");
355 for (i = 0; i < pool->res_cap->num_dsc; i++) {
356 struct display_stream_compressor *dsc = pool->dscs[i];
357 struct dcn_dsc_state s = {0};
358
359 dsc->funcs->dsc_read_state(dsc, &s);
360 DTN_INFO("[%d]: %-9d %-12d %-10d\n",
361 dsc->inst,
362 s.dsc_clock_en,
363 s.dsc_slice_width,
364 s.dsc_bytes_per_pixel);
365 DTN_INFO("\n");
366 }
367 DTN_INFO("\n");
368
369 DTN_INFO("S_ENC: DSC_MODE SEC_GSP7_LINE_NUM"
370 " VBID6_LINE_REFERENCE VBID6_LINE_NUM SEC_GSP7_ENABLE SEC_STREAM_ENABLE\n");
371 for (i = 0; i < pool->stream_enc_count; i++) {
372 struct stream_encoder *enc = pool->stream_enc[i];
373 struct enc_state s = {0};
374
375 if (enc->funcs->enc_read_state) {
376 enc->funcs->enc_read_state(enc, &s);
377 DTN_INFO("[%-3d]: %-9d %-18d %-21d %-15d %-16d %-17d\n",
378 enc->id,
379 s.dsc_mode,
380 s.sec_gsp_pps_line_num,
381 s.vbid6_line_reference,
382 s.vbid6_line_num,
383 s.sec_gsp_pps_enable,
384 s.sec_stream_enable);
385 DTN_INFO("\n");
386 }
387 }
388 DTN_INFO("\n");
389
390 DTN_INFO("L_ENC: DPHY_FEC_EN DPHY_FEC_READY_SHADOW DPHY_FEC_ACTIVE_STATUS\n");
391 for (i = 0; i < dc->link_count; i++) {
392 struct link_encoder *lenc = dc->links[i]->link_enc;
393
394 struct link_enc_state s = {0};
395
396 if (lenc->funcs->read_state) {
397 lenc->funcs->read_state(lenc, &s);
398 DTN_INFO("[%-3d]: %-12d %-22d %-22d\n",
399 i,
400 s.dphy_fec_en,
401 s.dphy_fec_ready_shadow,
402 s.dphy_fec_active_status);
403 DTN_INFO("\n");
404 }
405 }
406 DTN_INFO("\n");
407 #endif
408
409 DTN_INFO("\nCALCULATED Clocks: dcfclk_khz:%d dcfclk_deep_sleep_khz:%d dispclk_khz:%d\n"
410 "dppclk_khz:%d max_supported_dppclk_khz:%d fclk_khz:%d socclk_khz:%d\n\n",
411 dc->current_state->bw_ctx.bw.dcn.clk.dcfclk_khz,
412 dc->current_state->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz,
413 dc->current_state->bw_ctx.bw.dcn.clk.dispclk_khz,
414 dc->current_state->bw_ctx.bw.dcn.clk.dppclk_khz,
415 dc->current_state->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz,
416 dc->current_state->bw_ctx.bw.dcn.clk.fclk_khz,
417 dc->current_state->bw_ctx.bw.dcn.clk.socclk_khz);
418
419 log_mpc_crc(dc, log_ctx);
420
421 DTN_INFO_END();
422 }
423
424 bool dcn10_did_underflow_occur(struct dc *dc, struct pipe_ctx *pipe_ctx)
425 {
426 struct hubp *hubp = pipe_ctx->plane_res.hubp;
427 struct timing_generator *tg = pipe_ctx->stream_res.tg;
428
429 if (tg->funcs->is_optc_underflow_occurred(tg)) {
430 tg->funcs->clear_optc_underflow(tg);
431 return true;
432 }
433
434 if (hubp->funcs->hubp_get_underflow_status(hubp)) {
435 hubp->funcs->hubp_clear_underflow(hubp);
436 return true;
437 }
438 return false;
439 }
440
441 static void dcn10_enable_power_gating_plane(
442 struct dce_hwseq *hws,
443 bool enable)
444 {
445 bool force_on = 1;
446
447 if (enable)
448 force_on = 0;
449
450
451 REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, force_on);
452 REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, force_on);
453 REG_UPDATE(DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, force_on);
454 REG_UPDATE(DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, force_on);
455
456
457 REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, force_on);
458 REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, force_on);
459 REG_UPDATE(DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, force_on);
460 REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on);
461 }
462
463 static void dcn10_disable_vga(
464 struct dce_hwseq *hws)
465 {
466 unsigned int in_vga1_mode = 0;
467 unsigned int in_vga2_mode = 0;
468 unsigned int in_vga3_mode = 0;
469 unsigned int in_vga4_mode = 0;
470
471 REG_GET(D1VGA_CONTROL, D1VGA_MODE_ENABLE, &in_vga1_mode);
472 REG_GET(D2VGA_CONTROL, D2VGA_MODE_ENABLE, &in_vga2_mode);
473 REG_GET(D3VGA_CONTROL, D3VGA_MODE_ENABLE, &in_vga3_mode);
474 REG_GET(D4VGA_CONTROL, D4VGA_MODE_ENABLE, &in_vga4_mode);
475
476 if (in_vga1_mode == 0 && in_vga2_mode == 0 &&
477 in_vga3_mode == 0 && in_vga4_mode == 0)
478 return;
479
480 REG_WRITE(D1VGA_CONTROL, 0);
481 REG_WRITE(D2VGA_CONTROL, 0);
482 REG_WRITE(D3VGA_CONTROL, 0);
483 REG_WRITE(D4VGA_CONTROL, 0);
484
485
486
487
488
489
490
491
492 REG_UPDATE(VGA_TEST_CONTROL, VGA_TEST_ENABLE, 1);
493 REG_UPDATE(VGA_TEST_CONTROL, VGA_TEST_RENDER_START, 1);
494 }
495
496 static void dcn10_dpp_pg_control(
497 struct dce_hwseq *hws,
498 unsigned int dpp_inst,
499 bool power_on)
500 {
501 uint32_t power_gate = power_on ? 0 : 1;
502 uint32_t pwr_status = power_on ? 0 : 2;
503
504 if (hws->ctx->dc->debug.disable_dpp_power_gate)
505 return;
506 if (REG(DOMAIN1_PG_CONFIG) == 0)
507 return;
508
509 switch (dpp_inst) {
510 case 0:
511 REG_UPDATE(DOMAIN1_PG_CONFIG,
512 DOMAIN1_POWER_GATE, power_gate);
513
514 REG_WAIT(DOMAIN1_PG_STATUS,
515 DOMAIN1_PGFSM_PWR_STATUS, pwr_status,
516 1, 1000);
517 break;
518 case 1:
519 REG_UPDATE(DOMAIN3_PG_CONFIG,
520 DOMAIN3_POWER_GATE, power_gate);
521
522 REG_WAIT(DOMAIN3_PG_STATUS,
523 DOMAIN3_PGFSM_PWR_STATUS, pwr_status,
524 1, 1000);
525 break;
526 case 2:
527 REG_UPDATE(DOMAIN5_PG_CONFIG,
528 DOMAIN5_POWER_GATE, power_gate);
529
530 REG_WAIT(DOMAIN5_PG_STATUS,
531 DOMAIN5_PGFSM_PWR_STATUS, pwr_status,
532 1, 1000);
533 break;
534 case 3:
535 REG_UPDATE(DOMAIN7_PG_CONFIG,
536 DOMAIN7_POWER_GATE, power_gate);
537
538 REG_WAIT(DOMAIN7_PG_STATUS,
539 DOMAIN7_PGFSM_PWR_STATUS, pwr_status,
540 1, 1000);
541 break;
542 default:
543 BREAK_TO_DEBUGGER();
544 break;
545 }
546 }
547
548 static void dcn10_hubp_pg_control(
549 struct dce_hwseq *hws,
550 unsigned int hubp_inst,
551 bool power_on)
552 {
553 uint32_t power_gate = power_on ? 0 : 1;
554 uint32_t pwr_status = power_on ? 0 : 2;
555
556 if (hws->ctx->dc->debug.disable_hubp_power_gate)
557 return;
558 if (REG(DOMAIN0_PG_CONFIG) == 0)
559 return;
560
561 switch (hubp_inst) {
562 case 0:
563 REG_UPDATE(DOMAIN0_PG_CONFIG,
564 DOMAIN0_POWER_GATE, power_gate);
565
566 REG_WAIT(DOMAIN0_PG_STATUS,
567 DOMAIN0_PGFSM_PWR_STATUS, pwr_status,
568 1, 1000);
569 break;
570 case 1:
571 REG_UPDATE(DOMAIN2_PG_CONFIG,
572 DOMAIN2_POWER_GATE, power_gate);
573
574 REG_WAIT(DOMAIN2_PG_STATUS,
575 DOMAIN2_PGFSM_PWR_STATUS, pwr_status,
576 1, 1000);
577 break;
578 case 2:
579 REG_UPDATE(DOMAIN4_PG_CONFIG,
580 DOMAIN4_POWER_GATE, power_gate);
581
582 REG_WAIT(DOMAIN4_PG_STATUS,
583 DOMAIN4_PGFSM_PWR_STATUS, pwr_status,
584 1, 1000);
585 break;
586 case 3:
587 REG_UPDATE(DOMAIN6_PG_CONFIG,
588 DOMAIN6_POWER_GATE, power_gate);
589
590 REG_WAIT(DOMAIN6_PG_STATUS,
591 DOMAIN6_PGFSM_PWR_STATUS, pwr_status,
592 1, 1000);
593 break;
594 default:
595 BREAK_TO_DEBUGGER();
596 break;
597 }
598 }
599
600 static void power_on_plane(
601 struct dce_hwseq *hws,
602 int plane_id)
603 {
604 DC_LOGGER_INIT(hws->ctx->logger);
605 if (REG(DC_IP_REQUEST_CNTL)) {
606 REG_SET(DC_IP_REQUEST_CNTL, 0,
607 IP_REQUEST_EN, 1);
608 hws->ctx->dc->hwss.dpp_pg_control(hws, plane_id, true);
609 hws->ctx->dc->hwss.hubp_pg_control(hws, plane_id, true);
610 REG_SET(DC_IP_REQUEST_CNTL, 0,
611 IP_REQUEST_EN, 0);
612 DC_LOG_DEBUG(
613 "Un-gated front end for pipe %d\n", plane_id);
614 }
615 }
616
617 static void undo_DEGVIDCN10_253_wa(struct dc *dc)
618 {
619 struct dce_hwseq *hws = dc->hwseq;
620 struct hubp *hubp = dc->res_pool->hubps[0];
621
622 if (!hws->wa_state.DEGVIDCN10_253_applied)
623 return;
624
625 hubp->funcs->set_blank(hubp, true);
626
627 REG_SET(DC_IP_REQUEST_CNTL, 0,
628 IP_REQUEST_EN, 1);
629
630 dc->hwss.hubp_pg_control(hws, 0, false);
631 REG_SET(DC_IP_REQUEST_CNTL, 0,
632 IP_REQUEST_EN, 0);
633
634 hws->wa_state.DEGVIDCN10_253_applied = false;
635 }
636
637 static void apply_DEGVIDCN10_253_wa(struct dc *dc)
638 {
639 struct dce_hwseq *hws = dc->hwseq;
640 struct hubp *hubp = dc->res_pool->hubps[0];
641 int i;
642
643 if (dc->debug.disable_stutter)
644 return;
645
646 if (!hws->wa.DEGVIDCN10_253)
647 return;
648
649 for (i = 0; i < dc->res_pool->pipe_count; i++) {
650 if (!dc->res_pool->hubps[i]->power_gated)
651 return;
652 }
653
654
655
656 REG_SET(DC_IP_REQUEST_CNTL, 0,
657 IP_REQUEST_EN, 1);
658
659 dc->hwss.hubp_pg_control(hws, 0, true);
660 REG_SET(DC_IP_REQUEST_CNTL, 0,
661 IP_REQUEST_EN, 0);
662
663 hubp->funcs->set_hubp_blank_en(hubp, false);
664 hws->wa_state.DEGVIDCN10_253_applied = true;
665 }
666
667 static void dcn10_bios_golden_init(struct dc *dc)
668 {
669 struct dc_bios *bp = dc->ctx->dc_bios;
670 int i;
671 bool allow_self_fresh_force_enable = true;
672
673 if (dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled)
674 allow_self_fresh_force_enable =
675 dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled(dc->res_pool->hubbub);
676
677
678
679
680
681
682
683
684
685
686 bp->funcs->enable_disp_power_gating(bp,
687 CONTROLLER_ID_D0, ASIC_PIPE_INIT);
688
689 for (i = 0; i < dc->res_pool->pipe_count; i++) {
690
691 bp->funcs->enable_disp_power_gating(bp,
692 CONTROLLER_ID_D0 + i, ASIC_PIPE_DISABLE);
693 }
694
695 if (dc->res_pool->hubbub->funcs->allow_self_refresh_control)
696 if (allow_self_fresh_force_enable == false &&
697 dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled(dc->res_pool->hubbub))
698 dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub, true);
699
700 }
701
702 static void false_optc_underflow_wa(
703 struct dc *dc,
704 const struct dc_stream_state *stream,
705 struct timing_generator *tg)
706 {
707 int i;
708 bool underflow;
709
710 if (!dc->hwseq->wa.false_optc_underflow)
711 return;
712
713 underflow = tg->funcs->is_optc_underflow_occurred(tg);
714
715 for (i = 0; i < dc->res_pool->pipe_count; i++) {
716 struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
717
718 if (old_pipe_ctx->stream != stream)
719 continue;
720
721 dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, old_pipe_ctx);
722 }
723
724 if (tg->funcs->set_blank_data_double_buffer)
725 tg->funcs->set_blank_data_double_buffer(tg, true);
726
727 if (tg->funcs->is_optc_underflow_occurred(tg) && !underflow)
728 tg->funcs->clear_optc_underflow(tg);
729 }
730
731 static enum dc_status dcn10_enable_stream_timing(
732 struct pipe_ctx *pipe_ctx,
733 struct dc_state *context,
734 struct dc *dc)
735 {
736 struct dc_stream_state *stream = pipe_ctx->stream;
737 enum dc_color_space color_space;
738 struct tg_color black_color = {0};
739
740
741
742
743
744 if (pipe_ctx->top_pipe != NULL)
745 return DC_OK;
746
747
748
749
750
751
752 pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, true);
753
754 if (false == pipe_ctx->clock_source->funcs->program_pix_clk(
755 pipe_ctx->clock_source,
756 &pipe_ctx->stream_res.pix_clk_params,
757 &pipe_ctx->pll_settings)) {
758 BREAK_TO_DEBUGGER();
759 return DC_ERROR_UNEXPECTED;
760 }
761
762 pipe_ctx->stream_res.tg->funcs->program_timing(
763 pipe_ctx->stream_res.tg,
764 &stream->timing,
765 pipe_ctx->pipe_dlg_param.vready_offset,
766 pipe_ctx->pipe_dlg_param.vstartup_start,
767 pipe_ctx->pipe_dlg_param.vupdate_offset,
768 pipe_ctx->pipe_dlg_param.vupdate_width,
769 pipe_ctx->stream->signal,
770 true);
771
772 #if 0
773
774
775
776 inst_offset = reg_offsets[pipe_ctx->stream_res.tg->inst].fmt;
777
778 pipe_ctx->stream_res.opp->funcs->opp_program_fmt(
779 pipe_ctx->stream_res.opp,
780 &stream->bit_depth_params,
781 &stream->clamping);
782 #endif
783
784 color_space = stream->output_color_space;
785 color_space_to_black_color(dc, color_space, &black_color);
786
787 if (pipe_ctx->stream_res.tg->funcs->set_blank_color)
788 pipe_ctx->stream_res.tg->funcs->set_blank_color(
789 pipe_ctx->stream_res.tg,
790 &black_color);
791
792 if (pipe_ctx->stream_res.tg->funcs->is_blanked &&
793 !pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg)) {
794 pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true);
795 hwss_wait_for_blank_complete(pipe_ctx->stream_res.tg);
796 false_optc_underflow_wa(dc, pipe_ctx->stream, pipe_ctx->stream_res.tg);
797 }
798
799
800 if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc(pipe_ctx->stream_res.tg)) {
801 BREAK_TO_DEBUGGER();
802 return DC_ERROR_UNEXPECTED;
803 }
804
805
806
807
808
809
810
811
812
813 return DC_OK;
814 }
815
816 static void dcn10_reset_back_end_for_pipe(
817 struct dc *dc,
818 struct pipe_ctx *pipe_ctx,
819 struct dc_state *context)
820 {
821 int i;
822 DC_LOGGER_INIT(dc->ctx->logger);
823 if (pipe_ctx->stream_res.stream_enc == NULL) {
824 pipe_ctx->stream = NULL;
825 return;
826 }
827
828 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
829
830 if (!pipe_ctx->stream->dpms_off)
831 core_link_disable_stream(pipe_ctx);
832 else if (pipe_ctx->stream_res.audio)
833 dc->hwss.disable_audio_stream(pipe_ctx);
834
835 if (pipe_ctx->stream_res.audio) {
836
837 pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
838
839
840 if (dc->caps.dynamic_audio == true) {
841
842
843 update_audio_usage(&dc->current_state->res_ctx, dc->res_pool,
844 pipe_ctx->stream_res.audio, false);
845 pipe_ctx->stream_res.audio = NULL;
846 }
847 }
848 }
849
850
851
852
853
854 if (pipe_ctx->top_pipe == NULL) {
855 pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg);
856
857 pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false);
858 if (pipe_ctx->stream_res.tg->funcs->set_drr)
859 pipe_ctx->stream_res.tg->funcs->set_drr(
860 pipe_ctx->stream_res.tg, NULL);
861 }
862
863 for (i = 0; i < dc->res_pool->pipe_count; i++)
864 if (&dc->current_state->res_ctx.pipe_ctx[i] == pipe_ctx)
865 break;
866
867 if (i == dc->res_pool->pipe_count)
868 return;
869
870 pipe_ctx->stream = NULL;
871 DC_LOG_DEBUG("Reset back end for pipe %d, tg:%d\n",
872 pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst);
873 }
874
875 static bool dcn10_hw_wa_force_recovery(struct dc *dc)
876 {
877 struct hubp *hubp ;
878 unsigned int i;
879 bool need_recover = true;
880
881 if (!dc->debug.recovery_enabled)
882 return false;
883
884 for (i = 0; i < dc->res_pool->pipe_count; i++) {
885 struct pipe_ctx *pipe_ctx =
886 &dc->current_state->res_ctx.pipe_ctx[i];
887 if (pipe_ctx != NULL) {
888 hubp = pipe_ctx->plane_res.hubp;
889 if (hubp != NULL && hubp->funcs->hubp_get_underflow_status) {
890 if (hubp->funcs->hubp_get_underflow_status(hubp) != 0) {
891
892 need_recover = true;
893 }
894 }
895 }
896 }
897 if (!need_recover)
898 return false;
899
900
901
902
903
904
905
906
907
908
909 for (i = 0; i < dc->res_pool->pipe_count; i++) {
910 struct pipe_ctx *pipe_ctx =
911 &dc->current_state->res_ctx.pipe_ctx[i];
912 if (pipe_ctx != NULL) {
913 hubp = pipe_ctx->plane_res.hubp;
914
915 if (hubp != NULL && hubp->funcs->set_hubp_blank_en)
916 hubp->funcs->set_hubp_blank_en(hubp, true);
917 }
918 }
919
920 hubbub1_soft_reset(dc->res_pool->hubbub, true);
921
922 for (i = 0; i < dc->res_pool->pipe_count; i++) {
923 struct pipe_ctx *pipe_ctx =
924 &dc->current_state->res_ctx.pipe_ctx[i];
925 if (pipe_ctx != NULL) {
926 hubp = pipe_ctx->plane_res.hubp;
927
928 if (hubp != NULL && hubp->funcs->hubp_disable_control)
929 hubp->funcs->hubp_disable_control(hubp, true);
930 }
931 }
932 for (i = 0; i < dc->res_pool->pipe_count; i++) {
933 struct pipe_ctx *pipe_ctx =
934 &dc->current_state->res_ctx.pipe_ctx[i];
935 if (pipe_ctx != NULL) {
936 hubp = pipe_ctx->plane_res.hubp;
937
938 if (hubp != NULL && hubp->funcs->hubp_disable_control)
939 hubp->funcs->hubp_disable_control(hubp, true);
940 }
941 }
942
943 hubbub1_soft_reset(dc->res_pool->hubbub, false);
944 for (i = 0; i < dc->res_pool->pipe_count; i++) {
945 struct pipe_ctx *pipe_ctx =
946 &dc->current_state->res_ctx.pipe_ctx[i];
947 if (pipe_ctx != NULL) {
948 hubp = pipe_ctx->plane_res.hubp;
949
950 if (hubp != NULL && hubp->funcs->set_hubp_blank_en)
951 hubp->funcs->set_hubp_blank_en(hubp, true);
952 }
953 }
954 return true;
955
956 }
957
958
959 void dcn10_verify_allow_pstate_change_high(struct dc *dc)
960 {
961 static bool should_log_hw_state;
962
963 if (!hubbub1_verify_allow_pstate_change_high(dc->res_pool->hubbub)) {
964 if (should_log_hw_state) {
965 dcn10_log_hw_state(dc, NULL);
966 }
967 BREAK_TO_DEBUGGER();
968 if (dcn10_hw_wa_force_recovery(dc)) {
969
970 if (!hubbub1_verify_allow_pstate_change_high(dc->res_pool->hubbub))
971 BREAK_TO_DEBUGGER();
972 }
973 }
974 }
975
976
977 void hwss1_plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx)
978 {
979 struct hubp *hubp = pipe_ctx->plane_res.hubp;
980 int dpp_id = pipe_ctx->plane_res.dpp->inst;
981 struct mpc *mpc = dc->res_pool->mpc;
982 struct mpc_tree *mpc_tree_params;
983 struct mpcc *mpcc_to_remove = NULL;
984 struct output_pixel_processor *opp = pipe_ctx->stream_res.opp;
985
986 mpc_tree_params = &(opp->mpc_tree_params);
987 mpcc_to_remove = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, dpp_id);
988
989
990 if (mpcc_to_remove == NULL)
991 return;
992
993 mpc->funcs->remove_mpcc(mpc, mpc_tree_params, mpcc_to_remove);
994 if (opp != NULL)
995 opp->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
996
997 dc->optimized_required = true;
998
999 if (hubp->funcs->hubp_disconnect)
1000 hubp->funcs->hubp_disconnect(hubp);
1001
1002 if (dc->debug.sanity_checks)
1003 dcn10_verify_allow_pstate_change_high(dc);
1004 }
1005
1006 static void dcn10_plane_atomic_power_down(struct dc *dc,
1007 struct dpp *dpp,
1008 struct hubp *hubp)
1009 {
1010 struct dce_hwseq *hws = dc->hwseq;
1011 DC_LOGGER_INIT(dc->ctx->logger);
1012
1013 if (REG(DC_IP_REQUEST_CNTL)) {
1014 REG_SET(DC_IP_REQUEST_CNTL, 0,
1015 IP_REQUEST_EN, 1);
1016 dc->hwss.dpp_pg_control(hws, dpp->inst, false);
1017 dc->hwss.hubp_pg_control(hws, hubp->inst, false);
1018 dpp->funcs->dpp_reset(dpp);
1019 REG_SET(DC_IP_REQUEST_CNTL, 0,
1020 IP_REQUEST_EN, 0);
1021 DC_LOG_DEBUG(
1022 "Power gated front end %d\n", hubp->inst);
1023 }
1024 }
1025
1026
1027
1028
1029 static void dcn10_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
1030 {
1031 struct hubp *hubp = pipe_ctx->plane_res.hubp;
1032 struct dpp *dpp = pipe_ctx->plane_res.dpp;
1033 int opp_id = hubp->opp_id;
1034
1035 dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe_ctx);
1036
1037 hubp->funcs->hubp_clk_cntl(hubp, false);
1038
1039 dpp->funcs->dpp_dppclk_control(dpp, false, false);
1040
1041 if (opp_id != 0xf && pipe_ctx->stream_res.opp->mpc_tree_params.opp_list == NULL)
1042 pipe_ctx->stream_res.opp->funcs->opp_pipe_clock_control(
1043 pipe_ctx->stream_res.opp,
1044 false);
1045
1046 hubp->power_gated = true;
1047 dc->optimized_required = false;
1048
1049 dc->hwss.plane_atomic_power_down(dc,
1050 pipe_ctx->plane_res.dpp,
1051 pipe_ctx->plane_res.hubp);
1052
1053 pipe_ctx->stream = NULL;
1054 memset(&pipe_ctx->stream_res, 0, sizeof(pipe_ctx->stream_res));
1055 memset(&pipe_ctx->plane_res, 0, sizeof(pipe_ctx->plane_res));
1056 pipe_ctx->top_pipe = NULL;
1057 pipe_ctx->bottom_pipe = NULL;
1058 pipe_ctx->plane_state = NULL;
1059 }
1060
1061 static void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx)
1062 {
1063 DC_LOGGER_INIT(dc->ctx->logger);
1064
1065 if (!pipe_ctx->plane_res.hubp || pipe_ctx->plane_res.hubp->power_gated)
1066 return;
1067
1068 dc->hwss.plane_atomic_disable(dc, pipe_ctx);
1069
1070 apply_DEGVIDCN10_253_wa(dc);
1071
1072 DC_LOG_DC("Power down front end %d\n",
1073 pipe_ctx->pipe_idx);
1074 }
1075
1076 static void dcn10_init_pipes(struct dc *dc, struct dc_state *context)
1077 {
1078 int i;
1079 bool can_apply_seamless_boot = false;
1080
1081 for (i = 0; i < context->stream_count; i++) {
1082 if (context->streams[i]->apply_seamless_boot_optimization) {
1083 can_apply_seamless_boot = true;
1084 break;
1085 }
1086 }
1087
1088 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1089 struct timing_generator *tg = dc->res_pool->timing_generators[i];
1090 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1091
1092
1093
1094
1095
1096 if (pipe_ctx->stream != NULL && can_apply_seamless_boot)
1097 continue;
1098
1099
1100
1101
1102 if (tg->funcs->is_tg_enabled(tg)) {
1103 if (dc->hwss.init_blank != NULL) {
1104 dc->hwss.init_blank(dc, tg);
1105 tg->funcs->lock(tg);
1106 } else {
1107 tg->funcs->lock(tg);
1108 tg->funcs->set_blank(tg, true);
1109 hwss_wait_for_blank_complete(tg);
1110 }
1111 }
1112 }
1113
1114 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1115 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1116
1117
1118 if (pipe_ctx->stream != NULL && can_apply_seamless_boot)
1119 continue;
1120
1121 dc->res_pool->mpc->funcs->mpc_init_single_inst(
1122 dc->res_pool->mpc, i);
1123 }
1124
1125 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1126 struct timing_generator *tg = dc->res_pool->timing_generators[i];
1127 struct hubp *hubp = dc->res_pool->hubps[i];
1128 struct dpp *dpp = dc->res_pool->dpps[i];
1129 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1130
1131
1132
1133
1134
1135 if (can_apply_seamless_boot &&
1136 pipe_ctx->stream != NULL &&
1137 pipe_ctx->stream_res.tg->funcs->is_tg_enabled(
1138 pipe_ctx->stream_res.tg))
1139 continue;
1140
1141
1142 pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
1143
1144 dpp->funcs->dpp_reset(dpp);
1145
1146 pipe_ctx->stream_res.tg = tg;
1147 pipe_ctx->pipe_idx = i;
1148
1149 pipe_ctx->plane_res.hubp = hubp;
1150 pipe_ctx->plane_res.dpp = dpp;
1151 pipe_ctx->plane_res.mpcc_inst = dpp->inst;
1152 hubp->mpcc_id = dpp->inst;
1153 hubp->opp_id = OPP_ID_INVALID;
1154 hubp->power_gated = false;
1155
1156 dc->res_pool->opps[i]->mpc_tree_params.opp_id = dc->res_pool->opps[i]->inst;
1157 dc->res_pool->opps[i]->mpc_tree_params.opp_list = NULL;
1158 dc->res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
1159 pipe_ctx->stream_res.opp = dc->res_pool->opps[i];
1160
1161 dc->hwss.plane_atomic_disconnect(dc, pipe_ctx);
1162
1163 if (tg->funcs->is_tg_enabled(tg))
1164 tg->funcs->unlock(tg);
1165
1166 dc->hwss.disable_plane(dc, pipe_ctx);
1167
1168 pipe_ctx->stream_res.tg = NULL;
1169 pipe_ctx->plane_res.hubp = NULL;
1170
1171 tg->funcs->tg_init(tg);
1172 }
1173 }
1174
1175 static void dcn10_init_hw(struct dc *dc)
1176 {
1177 int i;
1178 struct abm *abm = dc->res_pool->abm;
1179 struct dmcu *dmcu = dc->res_pool->dmcu;
1180 struct dce_hwseq *hws = dc->hwseq;
1181 struct dc_bios *dcb = dc->ctx->dc_bios;
1182 struct resource_pool *res_pool = dc->res_pool;
1183
1184 if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
1185 dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
1186
1187
1188 if (dc->res_pool->dccg && dc->res_pool->dccg->funcs->dccg_init)
1189 dc->res_pool->dccg->funcs->dccg_init(res_pool->dccg);
1190
1191 if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
1192
1193 REG_WRITE(REFCLK_CNTL, 0);
1194 REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
1195 REG_WRITE(DIO_MEM_PWR_CTRL, 0);
1196
1197 if (!dc->debug.disable_clock_gate) {
1198
1199 REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
1200
1201 REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
1202
1203 REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
1204 }
1205
1206
1207 dc->hwss.enable_power_gating_plane(hws, true);
1208
1209 return;
1210 }
1211
1212 if (!dcb->funcs->is_accelerated_mode(dcb))
1213 dc->hwss.disable_vga(dc->hwseq);
1214
1215 dc->hwss.bios_golden_init(dc);
1216 if (dc->ctx->dc_bios->fw_info_valid) {
1217 res_pool->ref_clocks.xtalin_clock_inKhz =
1218 dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
1219
1220 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
1221 if (res_pool->dccg && res_pool->hubbub) {
1222
1223 (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
1224 dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
1225 &res_pool->ref_clocks.dccg_ref_clock_inKhz);
1226
1227 (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
1228 res_pool->ref_clocks.dccg_ref_clock_inKhz,
1229 &res_pool->ref_clocks.dchub_ref_clock_inKhz);
1230 } else {
1231
1232 res_pool->ref_clocks.dccg_ref_clock_inKhz =
1233 res_pool->ref_clocks.xtalin_clock_inKhz;
1234 res_pool->ref_clocks.dchub_ref_clock_inKhz =
1235 res_pool->ref_clocks.xtalin_clock_inKhz;
1236 }
1237 }
1238 } else
1239 ASSERT_CRITICAL(false);
1240
1241 for (i = 0; i < dc->link_count; i++) {
1242
1243
1244
1245
1246 struct dc_link *link = dc->links[i];
1247
1248 link->link_enc->funcs->hw_init(link->link_enc);
1249
1250
1251 if (link->link_enc->funcs->is_dig_enabled &&
1252 link->link_enc->funcs->is_dig_enabled(link->link_enc))
1253 link->link_status.link_active = true;
1254 }
1255
1256
1257 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
1258 for (i = 0; i < res_pool->res_cap->num_dsc; i++)
1259 if (dc->hwss.dsc_pg_control != NULL)
1260 dc->hwss.dsc_pg_control(hws, res_pool->dscs[i]->inst, false);
1261 #endif
1262
1263
1264
1265
1266
1267
1268
1269 if (dcb->funcs->is_accelerated_mode(dcb) || dc->config.power_down_display_on_boot) {
1270 dc->hwss.init_pipes(dc, dc->current_state);
1271 }
1272
1273 for (i = 0; i < res_pool->audio_count; i++) {
1274 struct audio *audio = res_pool->audios[i];
1275
1276 audio->funcs->hw_init(audio);
1277 }
1278
1279 if (abm != NULL) {
1280 abm->funcs->init_backlight(abm);
1281 abm->funcs->abm_init(abm);
1282 }
1283
1284 if (dmcu != NULL)
1285 dmcu->funcs->dmcu_init(dmcu);
1286
1287 if (abm != NULL && dmcu != NULL)
1288 abm->dmcu_is_running = dmcu->funcs->is_dmcu_initialized(dmcu);
1289
1290
1291 REG_WRITE(DIO_MEM_PWR_CTRL, 0);
1292
1293 if (!dc->debug.disable_clock_gate) {
1294
1295 REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
1296
1297 REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
1298
1299 REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
1300 }
1301
1302 dc->hwss.enable_power_gating_plane(dc->hwseq, true);
1303 }
1304
1305 static void dcn10_reset_hw_ctx_wrap(
1306 struct dc *dc,
1307 struct dc_state *context)
1308 {
1309 int i;
1310
1311
1312 for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) {
1313 struct pipe_ctx *pipe_ctx_old =
1314 &dc->current_state->res_ctx.pipe_ctx[i];
1315 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1316
1317 if (!pipe_ctx_old->stream)
1318 continue;
1319
1320 if (pipe_ctx_old->top_pipe)
1321 continue;
1322
1323 if (!pipe_ctx->stream ||
1324 pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) {
1325 struct clock_source *old_clk = pipe_ctx_old->clock_source;
1326
1327 dcn10_reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_state);
1328 if (dc->hwss.enable_stream_gating)
1329 dc->hwss.enable_stream_gating(dc, pipe_ctx);
1330 if (old_clk)
1331 old_clk->funcs->cs_power_down(old_clk);
1332 }
1333 }
1334 }
1335
1336 static bool patch_address_for_sbs_tb_stereo(
1337 struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr)
1338 {
1339 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
1340 bool sec_split = pipe_ctx->top_pipe &&
1341 pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state;
1342 if (sec_split && plane_state->address.type == PLN_ADDR_TYPE_GRPH_STEREO &&
1343 (pipe_ctx->stream->timing.timing_3d_format ==
1344 TIMING_3D_FORMAT_SIDE_BY_SIDE ||
1345 pipe_ctx->stream->timing.timing_3d_format ==
1346 TIMING_3D_FORMAT_TOP_AND_BOTTOM)) {
1347 *addr = plane_state->address.grph_stereo.left_addr;
1348 plane_state->address.grph_stereo.left_addr =
1349 plane_state->address.grph_stereo.right_addr;
1350 return true;
1351 } else {
1352 if (pipe_ctx->stream->view_format != VIEW_3D_FORMAT_NONE &&
1353 plane_state->address.type != PLN_ADDR_TYPE_GRPH_STEREO) {
1354 plane_state->address.type = PLN_ADDR_TYPE_GRPH_STEREO;
1355 plane_state->address.grph_stereo.right_addr =
1356 plane_state->address.grph_stereo.left_addr;
1357 }
1358 }
1359 return false;
1360 }
1361
1362
1363
1364 static void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx)
1365 {
1366 bool addr_patched = false;
1367 PHYSICAL_ADDRESS_LOC addr;
1368 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
1369
1370 if (plane_state == NULL)
1371 return;
1372
1373 addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr);
1374
1375 pipe_ctx->plane_res.hubp->funcs->hubp_program_surface_flip_and_addr(
1376 pipe_ctx->plane_res.hubp,
1377 &plane_state->address,
1378 plane_state->flip_immediate);
1379
1380 plane_state->status.requested_address = plane_state->address;
1381
1382 if (plane_state->flip_immediate)
1383 plane_state->status.current_address = plane_state->address;
1384
1385 if (addr_patched)
1386 pipe_ctx->plane_state->address.grph_stereo.left_addr = addr;
1387 }
1388
1389 static bool dcn10_set_input_transfer_func(struct pipe_ctx *pipe_ctx,
1390 const struct dc_plane_state *plane_state)
1391 {
1392 struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
1393 const struct dc_transfer_func *tf = NULL;
1394 bool result = true;
1395
1396 if (dpp_base == NULL)
1397 return false;
1398
1399 if (plane_state->in_transfer_func)
1400 tf = plane_state->in_transfer_func;
1401
1402 if (plane_state->gamma_correction &&
1403 !dpp_base->ctx->dc->debug.always_use_regamma
1404 && !plane_state->gamma_correction->is_identity
1405 && dce_use_lut(plane_state->format))
1406 dpp_base->funcs->dpp_program_input_lut(dpp_base, plane_state->gamma_correction);
1407
1408 if (tf == NULL)
1409 dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS);
1410 else if (tf->type == TF_TYPE_PREDEFINED) {
1411 switch (tf->tf) {
1412 case TRANSFER_FUNCTION_SRGB:
1413 dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_HW_sRGB);
1414 break;
1415 case TRANSFER_FUNCTION_BT709:
1416 dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_HW_xvYCC);
1417 break;
1418 case TRANSFER_FUNCTION_LINEAR:
1419 dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS);
1420 break;
1421 case TRANSFER_FUNCTION_PQ:
1422 default:
1423 result = false;
1424 break;
1425 }
1426 } else if (tf->type == TF_TYPE_BYPASS) {
1427 dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS);
1428 } else {
1429 cm_helper_translate_curve_to_degamma_hw_format(tf,
1430 &dpp_base->degamma_params);
1431 dpp_base->funcs->dpp_program_degamma_pwl(dpp_base,
1432 &dpp_base->degamma_params);
1433 result = true;
1434 }
1435
1436 return result;
1437 }
1438
1439 #define MAX_NUM_HW_POINTS 0x200
1440
1441 static void log_tf(struct dc_context *ctx,
1442 struct dc_transfer_func *tf, uint32_t hw_points_num)
1443 {
1444
1445
1446
1447 int i = 0;
1448
1449 DC_LOGGER_INIT(ctx->logger);
1450 DC_LOG_GAMMA("Gamma Correction TF");
1451 DC_LOG_ALL_GAMMA("Logging all tf points...");
1452 DC_LOG_ALL_TF_CHANNELS("Logging all channels...");
1453
1454 for (i = 0; i < hw_points_num; i++) {
1455 DC_LOG_GAMMA("R\t%d\t%llu\n", i, tf->tf_pts.red[i].value);
1456 DC_LOG_ALL_TF_CHANNELS("G\t%d\t%llu\n", i, tf->tf_pts.green[i].value);
1457 DC_LOG_ALL_TF_CHANNELS("B\t%d\t%llu\n", i, tf->tf_pts.blue[i].value);
1458 }
1459
1460 for (i = hw_points_num; i < MAX_NUM_HW_POINTS; i++) {
1461 DC_LOG_ALL_GAMMA("R\t%d\t%llu\n", i, tf->tf_pts.red[i].value);
1462 DC_LOG_ALL_TF_CHANNELS("G\t%d\t%llu\n", i, tf->tf_pts.green[i].value);
1463 DC_LOG_ALL_TF_CHANNELS("B\t%d\t%llu\n", i, tf->tf_pts.blue[i].value);
1464 }
1465 }
1466
1467 static bool
1468 dcn10_set_output_transfer_func(struct pipe_ctx *pipe_ctx,
1469 const struct dc_stream_state *stream)
1470 {
1471 struct dpp *dpp = pipe_ctx->plane_res.dpp;
1472
1473 if (dpp == NULL)
1474 return false;
1475
1476 dpp->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM;
1477
1478 if (stream->out_transfer_func &&
1479 stream->out_transfer_func->type == TF_TYPE_PREDEFINED &&
1480 stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB)
1481 dpp->funcs->dpp_program_regamma_pwl(dpp, NULL, OPP_REGAMMA_SRGB);
1482
1483
1484
1485
1486 else if (cm_helper_translate_curve_to_hw_format(
1487 stream->out_transfer_func,
1488 &dpp->regamma_params, false)) {
1489 dpp->funcs->dpp_program_regamma_pwl(
1490 dpp,
1491 &dpp->regamma_params, OPP_REGAMMA_USER);
1492 } else
1493 dpp->funcs->dpp_program_regamma_pwl(dpp, NULL, OPP_REGAMMA_BYPASS);
1494
1495 if (stream != NULL && stream->ctx != NULL &&
1496 stream->out_transfer_func != NULL) {
1497 log_tf(stream->ctx,
1498 stream->out_transfer_func,
1499 dpp->regamma_params.hw_points_num);
1500 }
1501
1502 return true;
1503 }
1504
1505 static void dcn10_pipe_control_lock(
1506 struct dc *dc,
1507 struct pipe_ctx *pipe,
1508 bool lock)
1509 {
1510
1511
1512
1513 if (pipe->top_pipe)
1514 return;
1515
1516 if (dc->debug.sanity_checks)
1517 dcn10_verify_allow_pstate_change_high(dc);
1518
1519 if (lock)
1520 pipe->stream_res.tg->funcs->lock(pipe->stream_res.tg);
1521 else
1522 pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg);
1523
1524 if (dc->debug.sanity_checks)
1525 dcn10_verify_allow_pstate_change_high(dc);
1526 }
1527
1528 static bool wait_for_reset_trigger_to_occur(
1529 struct dc_context *dc_ctx,
1530 struct timing_generator *tg)
1531 {
1532 bool rc = false;
1533
1534
1535
1536 const uint32_t frames_to_wait_on_triggered_reset = 10;
1537 int i;
1538
1539 for (i = 0; i < frames_to_wait_on_triggered_reset; i++) {
1540
1541 if (!tg->funcs->is_counter_moving(tg)) {
1542 DC_ERROR("TG counter is not moving!\n");
1543 break;
1544 }
1545
1546 if (tg->funcs->did_triggered_reset_occur(tg)) {
1547 rc = true;
1548
1549 DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n",
1550 i);
1551 break;
1552 }
1553
1554
1555 tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE);
1556 tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK);
1557 }
1558
1559 if (false == rc)
1560 DC_ERROR("GSL: Timeout on reset trigger!\n");
1561
1562 return rc;
1563 }
1564
1565 static void dcn10_enable_timing_synchronization(
1566 struct dc *dc,
1567 int group_index,
1568 int group_size,
1569 struct pipe_ctx *grouped_pipes[])
1570 {
1571 struct dc_context *dc_ctx = dc->ctx;
1572 int i;
1573
1574 DC_SYNC_INFO("Setting up OTG reset trigger\n");
1575
1576 for (i = 1; i < group_size; i++)
1577 grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger(
1578 grouped_pipes[i]->stream_res.tg,
1579 grouped_pipes[0]->stream_res.tg->inst);
1580
1581 DC_SYNC_INFO("Waiting for trigger\n");
1582
1583
1584
1585
1586
1587 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[1]->stream_res.tg);
1588 for (i = 1; i < group_size; i++)
1589 grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger(
1590 grouped_pipes[i]->stream_res.tg);
1591
1592 DC_SYNC_INFO("Sync complete\n");
1593 }
1594
1595 static void dcn10_enable_per_frame_crtc_position_reset(
1596 struct dc *dc,
1597 int group_size,
1598 struct pipe_ctx *grouped_pipes[])
1599 {
1600 struct dc_context *dc_ctx = dc->ctx;
1601 int i;
1602
1603 DC_SYNC_INFO("Setting up\n");
1604 for (i = 0; i < group_size; i++)
1605 if (grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset)
1606 grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset(
1607 grouped_pipes[i]->stream_res.tg,
1608 0,
1609 &grouped_pipes[i]->stream->triggered_crtc_reset);
1610
1611 DC_SYNC_INFO("Waiting for trigger\n");
1612
1613 for (i = 0; i < group_size; i++)
1614 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg);
1615
1616 DC_SYNC_INFO("Multi-display sync is complete\n");
1617 }
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742 static void mmhub_read_vm_system_aperture_settings(struct dcn10_hubp *hubp1,
1743 struct vm_system_aperture_param *apt,
1744 struct dce_hwseq *hws)
1745 {
1746 PHYSICAL_ADDRESS_LOC physical_page_number;
1747 uint32_t logical_addr_low;
1748 uint32_t logical_addr_high;
1749
1750 REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB,
1751 PHYSICAL_PAGE_NUMBER_MSB, &physical_page_number.high_part);
1752 REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB,
1753 PHYSICAL_PAGE_NUMBER_LSB, &physical_page_number.low_part);
1754
1755 REG_GET(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
1756 LOGICAL_ADDR, &logical_addr_low);
1757
1758 REG_GET(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
1759 LOGICAL_ADDR, &logical_addr_high);
1760
1761 apt->sys_default.quad_part = physical_page_number.quad_part << 12;
1762 apt->sys_low.quad_part = (int64_t)logical_addr_low << 18;
1763 apt->sys_high.quad_part = (int64_t)logical_addr_high << 18;
1764 }
1765
1766
1767 static void mmhub_read_vm_context0_settings(struct dcn10_hubp *hubp1,
1768 struct vm_context0_param *vm0,
1769 struct dce_hwseq *hws)
1770 {
1771 PHYSICAL_ADDRESS_LOC fb_base;
1772 PHYSICAL_ADDRESS_LOC fb_offset;
1773 uint32_t fb_base_value;
1774 uint32_t fb_offset_value;
1775
1776 REG_GET(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, &fb_base_value);
1777 REG_GET(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, &fb_offset_value);
1778
1779 REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32,
1780 PAGE_DIRECTORY_ENTRY_HI32, &vm0->pte_base.high_part);
1781 REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
1782 PAGE_DIRECTORY_ENTRY_LO32, &vm0->pte_base.low_part);
1783
1784 REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32,
1785 LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_start.high_part);
1786 REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32,
1787 LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_start.low_part);
1788
1789 REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32,
1790 LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_end.high_part);
1791 REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32,
1792 LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_end.low_part);
1793
1794 REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32,
1795 PHYSICAL_PAGE_ADDR_HI4, &vm0->fault_default.high_part);
1796 REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32,
1797 PHYSICAL_PAGE_ADDR_LO32, &vm0->fault_default.low_part);
1798
1799
1800
1801
1802
1803
1804
1805 fb_base.quad_part = (uint64_t)fb_base_value << 24;
1806 fb_offset.quad_part = (uint64_t)fb_offset_value << 24;
1807 vm0->pte_base.quad_part += fb_base.quad_part;
1808 vm0->pte_base.quad_part -= fb_offset.quad_part;
1809 }
1810
1811
1812 void dcn10_program_pte_vm(struct dce_hwseq *hws, struct hubp *hubp)
1813 {
1814 struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);
1815 struct vm_system_aperture_param apt = { {{ 0 } } };
1816 struct vm_context0_param vm0 = { { { 0 } } };
1817
1818 mmhub_read_vm_system_aperture_settings(hubp1, &apt, hws);
1819 mmhub_read_vm_context0_settings(hubp1, &vm0, hws);
1820
1821 hubp->funcs->hubp_set_vm_system_aperture_settings(hubp, &apt);
1822 hubp->funcs->hubp_set_vm_context0_settings(hubp, &vm0);
1823 }
1824
1825 static void dcn10_enable_plane(
1826 struct dc *dc,
1827 struct pipe_ctx *pipe_ctx,
1828 struct dc_state *context)
1829 {
1830 struct dce_hwseq *hws = dc->hwseq;
1831
1832 if (dc->debug.sanity_checks) {
1833 dcn10_verify_allow_pstate_change_high(dc);
1834 }
1835
1836 undo_DEGVIDCN10_253_wa(dc);
1837
1838 power_on_plane(dc->hwseq,
1839 pipe_ctx->plane_res.hubp->inst);
1840
1841
1842 pipe_ctx->plane_res.hubp->funcs->hubp_clk_cntl(pipe_ctx->plane_res.hubp, true);
1843
1844
1845 pipe_ctx->stream_res.opp->funcs->opp_pipe_clock_control(
1846 pipe_ctx->stream_res.opp,
1847 true);
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886 if (dc->config.gpu_vm_support)
1887 dcn10_program_pte_vm(hws, pipe_ctx->plane_res.hubp);
1888
1889 if (dc->debug.sanity_checks) {
1890 dcn10_verify_allow_pstate_change_high(dc);
1891 }
1892 }
1893
1894 static void dcn10_program_gamut_remap(struct pipe_ctx *pipe_ctx)
1895 {
1896 int i = 0;
1897 struct dpp_grph_csc_adjustment adjust;
1898 memset(&adjust, 0, sizeof(adjust));
1899 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
1900
1901
1902 if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) {
1903 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
1904 for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++)
1905 adjust.temperature_matrix[i] =
1906 pipe_ctx->stream->gamut_remap_matrix.matrix[i];
1907 }
1908
1909 pipe_ctx->plane_res.dpp->funcs->dpp_set_gamut_remap(pipe_ctx->plane_res.dpp, &adjust);
1910 }
1911
1912
1913 static bool dcn10_is_rear_mpo_fix_required(struct pipe_ctx *pipe_ctx, enum dc_color_space colorspace)
1914 {
1915 if (pipe_ctx->plane_state && pipe_ctx->plane_state->layer_index > 0 && is_rgb_cspace(colorspace)) {
1916 if (pipe_ctx->top_pipe) {
1917 struct pipe_ctx *top = pipe_ctx->top_pipe;
1918
1919 while (top->top_pipe)
1920 top = top->top_pipe;
1921 if (top->plane_state && top->plane_state->layer_index == 0)
1922 return true;
1923 }
1924 }
1925 return false;
1926 }
1927
1928 static void dcn10_set_csc_adjustment_rgb_mpo_fix(struct pipe_ctx *pipe_ctx, uint16_t *matrix)
1929 {
1930
1931 uint16_t rgb_bias = matrix[3];
1932
1933 matrix[3] = 0;
1934 matrix[7] = 0;
1935 matrix[11] = 0;
1936 pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment(pipe_ctx->plane_res.dpp, matrix);
1937 matrix[3] = rgb_bias;
1938 matrix[7] = rgb_bias;
1939 matrix[11] = rgb_bias;
1940 }
1941
1942 static void dcn10_program_output_csc(struct dc *dc,
1943 struct pipe_ctx *pipe_ctx,
1944 enum dc_color_space colorspace,
1945 uint16_t *matrix,
1946 int opp_id)
1947 {
1948 if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) {
1949 if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment != NULL) {
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959 int16_t rgb_bias = matrix[3];
1960
1961
1962 if (rgb_bias > 0 && dcn10_is_rear_mpo_fix_required(pipe_ctx, colorspace)) {
1963 dcn10_set_csc_adjustment_rgb_mpo_fix(pipe_ctx, matrix);
1964 } else {
1965 pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment(pipe_ctx->plane_res.dpp, matrix);
1966 }
1967 }
1968 } else {
1969 if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_default != NULL)
1970 pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_default(pipe_ctx->plane_res.dpp, colorspace);
1971 }
1972 }
1973
1974 bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx)
1975 {
1976 if (pipe_ctx->plane_state && pipe_ctx->plane_state->visible)
1977 return true;
1978 if (pipe_ctx->bottom_pipe && is_lower_pipe_tree_visible(pipe_ctx->bottom_pipe))
1979 return true;
1980 return false;
1981 }
1982
1983 bool is_upper_pipe_tree_visible(struct pipe_ctx *pipe_ctx)
1984 {
1985 if (pipe_ctx->plane_state && pipe_ctx->plane_state->visible)
1986 return true;
1987 if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe))
1988 return true;
1989 return false;
1990 }
1991
1992 bool is_pipe_tree_visible(struct pipe_ctx *pipe_ctx)
1993 {
1994 if (pipe_ctx->plane_state && pipe_ctx->plane_state->visible)
1995 return true;
1996 if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe))
1997 return true;
1998 if (pipe_ctx->bottom_pipe && is_lower_pipe_tree_visible(pipe_ctx->bottom_pipe))
1999 return true;
2000 return false;
2001 }
2002
2003 bool is_rgb_cspace(enum dc_color_space output_color_space)
2004 {
2005 switch (output_color_space) {
2006 case COLOR_SPACE_SRGB:
2007 case COLOR_SPACE_SRGB_LIMITED:
2008 case COLOR_SPACE_2020_RGB_FULLRANGE:
2009 case COLOR_SPACE_2020_RGB_LIMITEDRANGE:
2010 case COLOR_SPACE_ADOBERGB:
2011 return true;
2012 case COLOR_SPACE_YCBCR601:
2013 case COLOR_SPACE_YCBCR709:
2014 case COLOR_SPACE_YCBCR601_LIMITED:
2015 case COLOR_SPACE_YCBCR709_LIMITED:
2016 case COLOR_SPACE_2020_YCBCR:
2017 return false;
2018 default:
2019
2020 BREAK_TO_DEBUGGER();
2021 return false;
2022 }
2023 }
2024
2025 void dcn10_get_surface_visual_confirm_color(
2026 const struct pipe_ctx *pipe_ctx,
2027 struct tg_color *color)
2028 {
2029 uint32_t color_value = MAX_TG_COLOR_VALUE;
2030
2031 switch (pipe_ctx->plane_res.scl_data.format) {
2032 case PIXEL_FORMAT_ARGB8888:
2033
2034 color->color_r_cr = color_value;
2035 break;
2036
2037 case PIXEL_FORMAT_ARGB2101010:
2038
2039 color->color_b_cb = color_value;
2040 break;
2041 case PIXEL_FORMAT_420BPP8:
2042
2043 color->color_g_y = color_value;
2044 break;
2045 case PIXEL_FORMAT_420BPP10:
2046
2047 color->color_g_y = color_value;
2048 color->color_r_cr = color_value;
2049 break;
2050 case PIXEL_FORMAT_FP16:
2051
2052 color->color_r_cr = color_value;
2053 color->color_b_cb = color_value;
2054 color->color_g_y = color_value;
2055 break;
2056 default:
2057 break;
2058 }
2059 }
2060
2061 void dcn10_get_hdr_visual_confirm_color(
2062 struct pipe_ctx *pipe_ctx,
2063 struct tg_color *color)
2064 {
2065 uint32_t color_value = MAX_TG_COLOR_VALUE;
2066
2067
2068 struct pipe_ctx *top_pipe_ctx = pipe_ctx;
2069
2070 while (top_pipe_ctx->top_pipe != NULL)
2071 top_pipe_ctx = top_pipe_ctx->top_pipe;
2072
2073 switch (top_pipe_ctx->plane_res.scl_data.format) {
2074 case PIXEL_FORMAT_ARGB2101010:
2075 if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_PQ) {
2076
2077 color->color_r_cr = color_value;
2078 }
2079 break;
2080 case PIXEL_FORMAT_FP16:
2081 if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_PQ) {
2082
2083 color->color_b_cb = color_value;
2084 } else if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) {
2085
2086 color->color_g_y = color_value;
2087 }
2088 break;
2089 default:
2090
2091 color->color_r_cr = color_value/2;
2092 color->color_b_cb = color_value/2;
2093 color->color_g_y = color_value/2;
2094 break;
2095 }
2096 }
2097
2098 static uint16_t fixed_point_to_int_frac(
2099 struct fixed31_32 arg,
2100 uint8_t integer_bits,
2101 uint8_t fractional_bits)
2102 {
2103 int32_t numerator;
2104 int32_t divisor = 1 << fractional_bits;
2105
2106 uint16_t result;
2107
2108 uint16_t d = (uint16_t)dc_fixpt_floor(
2109 dc_fixpt_abs(
2110 arg));
2111
2112 if (d <= (uint16_t)(1 << integer_bits) - (1 / (uint16_t)divisor))
2113 numerator = (uint16_t)dc_fixpt_floor(
2114 dc_fixpt_mul_int(
2115 arg,
2116 divisor));
2117 else {
2118 numerator = dc_fixpt_floor(
2119 dc_fixpt_sub(
2120 dc_fixpt_from_int(
2121 1LL << integer_bits),
2122 dc_fixpt_recip(
2123 dc_fixpt_from_int(
2124 divisor))));
2125 }
2126
2127 if (numerator >= 0)
2128 result = (uint16_t)numerator;
2129 else
2130 result = (uint16_t)(
2131 (1 << (integer_bits + fractional_bits + 1)) + numerator);
2132
2133 if ((result != 0) && dc_fixpt_lt(
2134 arg, dc_fixpt_zero))
2135 result |= 1 << (integer_bits + fractional_bits);
2136
2137 return result;
2138 }
2139
2140 void dcn10_build_prescale_params(struct dc_bias_and_scale *bias_and_scale,
2141 const struct dc_plane_state *plane_state)
2142 {
2143 if (plane_state->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN
2144 && plane_state->format != SURFACE_PIXEL_FORMAT_INVALID
2145 && plane_state->input_csc_color_matrix.enable_adjustment
2146 && plane_state->coeff_reduction_factor.value != 0) {
2147 bias_and_scale->scale_blue = fixed_point_to_int_frac(
2148 dc_fixpt_mul(plane_state->coeff_reduction_factor,
2149 dc_fixpt_from_fraction(256, 255)),
2150 2,
2151 13);
2152 bias_and_scale->scale_red = bias_and_scale->scale_blue;
2153 bias_and_scale->scale_green = bias_and_scale->scale_blue;
2154 } else {
2155 bias_and_scale->scale_blue = 0x2000;
2156 bias_and_scale->scale_red = 0x2000;
2157 bias_and_scale->scale_green = 0x2000;
2158 }
2159 }
2160
2161 static void update_dpp(struct dpp *dpp, struct dc_plane_state *plane_state)
2162 {
2163 struct dc_bias_and_scale bns_params = {0};
2164
2165
2166 dpp->funcs->dpp_setup(dpp,
2167 plane_state->format,
2168 EXPANSION_MODE_ZERO,
2169 plane_state->input_csc_color_matrix,
2170 #ifdef CONFIG_DRM_AMD_DC_DCN2_0
2171 plane_state->color_space,
2172 NULL);
2173 #else
2174 plane_state->color_space);
2175 #endif
2176
2177
2178 dcn10_build_prescale_params(&bns_params, plane_state);
2179 if (dpp->funcs->dpp_program_bias_and_scale)
2180 dpp->funcs->dpp_program_bias_and_scale(dpp, &bns_params);
2181 }
2182
2183 static void dcn10_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
2184 {
2185 struct hubp *hubp = pipe_ctx->plane_res.hubp;
2186 struct mpcc_blnd_cfg blnd_cfg = {{0}};
2187 bool per_pixel_alpha = pipe_ctx->plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe;
2188 int mpcc_id;
2189 struct mpcc *new_mpcc;
2190 struct mpc *mpc = dc->res_pool->mpc;
2191 struct mpc_tree *mpc_tree_params = &(pipe_ctx->stream_res.opp->mpc_tree_params);
2192
2193 if (dc->debug.visual_confirm == VISUAL_CONFIRM_HDR) {
2194 dcn10_get_hdr_visual_confirm_color(
2195 pipe_ctx, &blnd_cfg.black_color);
2196 } else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE) {
2197 dcn10_get_surface_visual_confirm_color(
2198 pipe_ctx, &blnd_cfg.black_color);
2199 } else {
2200 color_space_to_black_color(
2201 dc, pipe_ctx->stream->output_color_space,
2202 &blnd_cfg.black_color);
2203 }
2204
2205 if (per_pixel_alpha)
2206 blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
2207 else
2208 blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA;
2209
2210 blnd_cfg.overlap_only = false;
2211 blnd_cfg.global_gain = 0xff;
2212
2213 if (pipe_ctx->plane_state->global_alpha)
2214 blnd_cfg.global_alpha = pipe_ctx->plane_state->global_alpha_value;
2215 else
2216 blnd_cfg.global_alpha = 0xff;
2217
2218
2219
2220
2221 blnd_cfg.pre_multiplied_alpha = is_rgb_cspace(
2222 pipe_ctx->stream->output_color_space)
2223 && per_pixel_alpha;
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234 mpcc_id = hubp->inst;
2235
2236
2237 if (!pipe_ctx->plane_state->update_flags.bits.full_update) {
2238 mpc->funcs->update_blending(mpc, &blnd_cfg, mpcc_id);
2239 return;
2240 }
2241
2242
2243 new_mpcc = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, mpcc_id);
2244
2245 if (new_mpcc != NULL)
2246 mpc->funcs->remove_mpcc(mpc, mpc_tree_params, new_mpcc);
2247 else
2248 if (dc->debug.sanity_checks)
2249 mpc->funcs->assert_mpcc_idle_before_connect(
2250 dc->res_pool->mpc, mpcc_id);
2251
2252
2253 new_mpcc = mpc->funcs->insert_plane(dc->res_pool->mpc,
2254 mpc_tree_params,
2255 &blnd_cfg,
2256 NULL,
2257 NULL,
2258 hubp->inst,
2259 mpcc_id);
2260
2261 ASSERT(new_mpcc != NULL);
2262
2263 hubp->opp_id = pipe_ctx->stream_res.opp->inst;
2264 hubp->mpcc_id = mpcc_id;
2265 }
2266
2267 static void update_scaler(struct pipe_ctx *pipe_ctx)
2268 {
2269 bool per_pixel_alpha =
2270 pipe_ctx->plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe;
2271
2272 pipe_ctx->plane_res.scl_data.lb_params.alpha_en = per_pixel_alpha;
2273 pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP;
2274
2275 pipe_ctx->plane_res.dpp->funcs->dpp_set_scaler(
2276 pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data);
2277 }
2278
2279 void update_dchubp_dpp(
2280 struct dc *dc,
2281 struct pipe_ctx *pipe_ctx,
2282 struct dc_state *context)
2283 {
2284 struct hubp *hubp = pipe_ctx->plane_res.hubp;
2285 struct dpp *dpp = pipe_ctx->plane_res.dpp;
2286 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
2287 struct plane_size size = plane_state->plane_size;
2288 unsigned int compat_level = 0;
2289
2290
2291
2292
2293
2294 if (plane_state->update_flags.bits.full_update) {
2295 bool should_divided_by_2 = context->bw_ctx.bw.dcn.clk.dppclk_khz <=
2296 dc->clk_mgr->clks.dispclk_khz / 2;
2297
2298 dpp->funcs->dpp_dppclk_control(
2299 dpp,
2300 should_divided_by_2,
2301 true);
2302
2303 if (dc->res_pool->dccg)
2304 dc->res_pool->dccg->funcs->update_dpp_dto(
2305 dc->res_pool->dccg,
2306 dpp->inst,
2307 pipe_ctx->plane_res.bw.dppclk_khz,
2308 false);
2309 else
2310 dc->clk_mgr->clks.dppclk_khz = should_divided_by_2 ?
2311 dc->clk_mgr->clks.dispclk_khz / 2 :
2312 dc->clk_mgr->clks.dispclk_khz;
2313 }
2314
2315
2316
2317
2318
2319 if (plane_state->update_flags.bits.full_update) {
2320 hubp->funcs->hubp_vtg_sel(hubp, pipe_ctx->stream_res.tg->inst);
2321
2322 hubp->funcs->hubp_setup(
2323 hubp,
2324 &pipe_ctx->dlg_regs,
2325 &pipe_ctx->ttu_regs,
2326 &pipe_ctx->rq_regs,
2327 &pipe_ctx->pipe_dlg_param);
2328 hubp->funcs->hubp_setup_interdependent(
2329 hubp,
2330 &pipe_ctx->dlg_regs,
2331 &pipe_ctx->ttu_regs);
2332 }
2333
2334 size.surface_size = pipe_ctx->plane_res.scl_data.viewport;
2335
2336 if (plane_state->update_flags.bits.full_update ||
2337 plane_state->update_flags.bits.bpp_change)
2338 update_dpp(dpp, plane_state);
2339
2340 if (plane_state->update_flags.bits.full_update ||
2341 plane_state->update_flags.bits.per_pixel_alpha_change ||
2342 plane_state->update_flags.bits.global_alpha_change)
2343 dc->hwss.update_mpcc(dc, pipe_ctx);
2344
2345 if (plane_state->update_flags.bits.full_update ||
2346 plane_state->update_flags.bits.per_pixel_alpha_change ||
2347 plane_state->update_flags.bits.global_alpha_change ||
2348 plane_state->update_flags.bits.scaling_change ||
2349 plane_state->update_flags.bits.position_change) {
2350 update_scaler(pipe_ctx);
2351 }
2352
2353 if (plane_state->update_flags.bits.full_update ||
2354 plane_state->update_flags.bits.scaling_change ||
2355 plane_state->update_flags.bits.position_change) {
2356 hubp->funcs->mem_program_viewport(
2357 hubp,
2358 &pipe_ctx->plane_res.scl_data.viewport,
2359 &pipe_ctx->plane_res.scl_data.viewport_c);
2360 }
2361
2362 if (pipe_ctx->stream->cursor_attributes.address.quad_part != 0) {
2363 dc->hwss.set_cursor_position(pipe_ctx);
2364 dc->hwss.set_cursor_attribute(pipe_ctx);
2365
2366 if (dc->hwss.set_cursor_sdr_white_level)
2367 dc->hwss.set_cursor_sdr_white_level(pipe_ctx);
2368 }
2369
2370 if (plane_state->update_flags.bits.full_update) {
2371
2372 dc->hwss.program_gamut_remap(pipe_ctx);
2373
2374 dc->hwss.program_output_csc(dc,
2375 pipe_ctx,
2376 pipe_ctx->stream->output_color_space,
2377 pipe_ctx->stream->csc_color_matrix.matrix,
2378 pipe_ctx->stream_res.opp->inst);
2379 }
2380
2381 if (plane_state->update_flags.bits.full_update ||
2382 plane_state->update_flags.bits.pixel_format_change ||
2383 plane_state->update_flags.bits.horizontal_mirror_change ||
2384 plane_state->update_flags.bits.rotation_change ||
2385 plane_state->update_flags.bits.swizzle_change ||
2386 plane_state->update_flags.bits.dcc_change ||
2387 plane_state->update_flags.bits.bpp_change ||
2388 plane_state->update_flags.bits.scaling_change ||
2389 plane_state->update_flags.bits.plane_size_change) {
2390 hubp->funcs->hubp_program_surface_config(
2391 hubp,
2392 plane_state->format,
2393 &plane_state->tiling_info,
2394 &size,
2395 plane_state->rotation,
2396 &plane_state->dcc,
2397 plane_state->horizontal_mirror,
2398 compat_level);
2399 }
2400
2401 hubp->power_gated = false;
2402
2403 dc->hwss.update_plane_addr(dc, pipe_ctx);
2404
2405 if (is_pipe_tree_visible(pipe_ctx))
2406 hubp->funcs->set_blank(hubp, false);
2407 }
2408
2409 static void dcn10_blank_pixel_data(
2410 struct dc *dc,
2411 struct pipe_ctx *pipe_ctx,
2412 bool blank)
2413 {
2414 enum dc_color_space color_space;
2415 struct tg_color black_color = {0};
2416 struct stream_resource *stream_res = &pipe_ctx->stream_res;
2417 struct dc_stream_state *stream = pipe_ctx->stream;
2418
2419
2420 color_space = stream->output_color_space;
2421 color_space_to_black_color(dc, color_space, &black_color);
2422
2423
2424
2425
2426
2427
2428 if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
2429 black_color.color_r_cr = black_color.color_g_y;
2430
2431
2432 if (stream_res->tg->funcs->set_blank_color)
2433 stream_res->tg->funcs->set_blank_color(
2434 stream_res->tg,
2435 &black_color);
2436
2437 if (!blank) {
2438 if (stream_res->tg->funcs->set_blank)
2439 stream_res->tg->funcs->set_blank(stream_res->tg, blank);
2440 if (stream_res->abm) {
2441 stream_res->abm->funcs->set_pipe(stream_res->abm, stream_res->tg->inst + 1);
2442 stream_res->abm->funcs->set_abm_level(stream_res->abm, stream->abm_level);
2443 }
2444 } else if (blank) {
2445 if (stream_res->abm)
2446 stream_res->abm->funcs->set_abm_immediate_disable(stream_res->abm);
2447 if (stream_res->tg->funcs->set_blank)
2448 stream_res->tg->funcs->set_blank(stream_res->tg, blank);
2449 }
2450 }
2451
2452 void set_hdr_multiplier(struct pipe_ctx *pipe_ctx)
2453 {
2454 struct fixed31_32 multiplier = dc_fixpt_from_fraction(
2455 pipe_ctx->plane_state->sdr_white_level, 80);
2456 uint32_t hw_mult = 0x1f000;
2457 struct custom_float_format fmt;
2458
2459 fmt.exponenta_bits = 6;
2460 fmt.mantissa_bits = 12;
2461 fmt.sign = true;
2462
2463 if (pipe_ctx->plane_state->sdr_white_level > 80)
2464 convert_to_custom_float_format(multiplier, &fmt, &hw_mult);
2465
2466 pipe_ctx->plane_res.dpp->funcs->dpp_set_hdr_multiplier(
2467 pipe_ctx->plane_res.dpp, hw_mult);
2468 }
2469
2470 void dcn10_program_pipe(
2471 struct dc *dc,
2472 struct pipe_ctx *pipe_ctx,
2473 struct dc_state *context)
2474 {
2475 if (pipe_ctx->plane_state->update_flags.bits.full_update)
2476 dcn10_enable_plane(dc, pipe_ctx, context);
2477
2478 update_dchubp_dpp(dc, pipe_ctx, context);
2479
2480 set_hdr_multiplier(pipe_ctx);
2481
2482 if (pipe_ctx->plane_state->update_flags.bits.full_update ||
2483 pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
2484 pipe_ctx->plane_state->update_flags.bits.gamma_change)
2485 dc->hwss.set_input_transfer_func(pipe_ctx, pipe_ctx->plane_state);
2486
2487
2488
2489
2490
2491
2492
2493 if (pipe_ctx->plane_state->update_flags.bits.full_update)
2494 dc->hwss.set_output_transfer_func(pipe_ctx, pipe_ctx->stream);
2495 }
2496
2497 static void program_all_pipe_in_tree(
2498 struct dc *dc,
2499 struct pipe_ctx *pipe_ctx,
2500 struct dc_state *context)
2501 {
2502 if (pipe_ctx->top_pipe == NULL) {
2503 bool blank = !is_pipe_tree_visible(pipe_ctx);
2504
2505 pipe_ctx->stream_res.tg->funcs->program_global_sync(
2506 pipe_ctx->stream_res.tg,
2507 pipe_ctx->pipe_dlg_param.vready_offset,
2508 pipe_ctx->pipe_dlg_param.vstartup_start,
2509 pipe_ctx->pipe_dlg_param.vupdate_offset,
2510 pipe_ctx->pipe_dlg_param.vupdate_width);
2511
2512 pipe_ctx->stream_res.tg->funcs->set_vtg_params(
2513 pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
2514
2515 dc->hwss.blank_pixel_data(dc, pipe_ctx, blank);
2516
2517 }
2518
2519 if (pipe_ctx->plane_state != NULL)
2520 dcn10_program_pipe(dc, pipe_ctx, context);
2521
2522 if (pipe_ctx->bottom_pipe != NULL && pipe_ctx->bottom_pipe != pipe_ctx)
2523 program_all_pipe_in_tree(dc, pipe_ctx->bottom_pipe, context);
2524 }
2525
2526 struct pipe_ctx *find_top_pipe_for_stream(
2527 struct dc *dc,
2528 struct dc_state *context,
2529 const struct dc_stream_state *stream)
2530 {
2531 int i;
2532
2533 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2534 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2535 struct pipe_ctx *old_pipe_ctx =
2536 &dc->current_state->res_ctx.pipe_ctx[i];
2537
2538 if (!pipe_ctx->plane_state && !old_pipe_ctx->plane_state)
2539 continue;
2540
2541 if (pipe_ctx->stream != stream)
2542 continue;
2543
2544 if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe)
2545 return pipe_ctx;
2546 }
2547 return NULL;
2548 }
2549
2550 static void dcn10_apply_ctx_for_surface(
2551 struct dc *dc,
2552 const struct dc_stream_state *stream,
2553 int num_planes,
2554 struct dc_state *context)
2555 {
2556 int i;
2557 struct timing_generator *tg;
2558 uint32_t underflow_check_delay_us;
2559 bool removed_pipe[4] = { false };
2560 bool interdependent_update = false;
2561 struct pipe_ctx *top_pipe_to_program =
2562 find_top_pipe_for_stream(dc, context, stream);
2563 DC_LOGGER_INIT(dc->ctx->logger);
2564
2565 if (!top_pipe_to_program)
2566 return;
2567
2568 tg = top_pipe_to_program->stream_res.tg;
2569
2570 interdependent_update = top_pipe_to_program->plane_state &&
2571 top_pipe_to_program->plane_state->update_flags.bits.full_update;
2572
2573 underflow_check_delay_us = dc->debug.underflow_assert_delay_us;
2574
2575 if (underflow_check_delay_us != 0xFFFFFFFF && dc->hwss.did_underflow_occur)
2576 ASSERT(dc->hwss.did_underflow_occur(dc, top_pipe_to_program));
2577
2578 if (interdependent_update)
2579 lock_all_pipes(dc, context, true);
2580 else
2581 dcn10_pipe_control_lock(dc, top_pipe_to_program, true);
2582
2583 if (underflow_check_delay_us != 0xFFFFFFFF)
2584 udelay(underflow_check_delay_us);
2585
2586 if (underflow_check_delay_us != 0xFFFFFFFF && dc->hwss.did_underflow_occur)
2587 ASSERT(dc->hwss.did_underflow_occur(dc, top_pipe_to_program));
2588
2589 if (num_planes == 0) {
2590
2591 dc->hwss.blank_pixel_data(dc, top_pipe_to_program, true);
2592 }
2593
2594
2595 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2596 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2597 struct pipe_ctx *old_pipe_ctx =
2598 &dc->current_state->res_ctx.pipe_ctx[i];
2599
2600
2601
2602
2603
2604
2605 if (pipe_ctx->plane_state && !old_pipe_ctx->plane_state) {
2606 if (old_pipe_ctx->stream_res.tg == tg &&
2607 old_pipe_ctx->plane_res.hubp &&
2608 old_pipe_ctx->plane_res.hubp->opp_id != OPP_ID_INVALID)
2609 dc->hwss.disable_plane(dc, old_pipe_ctx);
2610 }
2611
2612 if ((!pipe_ctx->plane_state ||
2613 pipe_ctx->stream_res.tg != old_pipe_ctx->stream_res.tg) &&
2614 old_pipe_ctx->plane_state &&
2615 old_pipe_ctx->stream_res.tg == tg) {
2616
2617 dc->hwss.plane_atomic_disconnect(dc, old_pipe_ctx);
2618 removed_pipe[i] = true;
2619
2620 DC_LOG_DC("Reset mpcc for pipe %d\n",
2621 old_pipe_ctx->pipe_idx);
2622 }
2623 }
2624
2625 if (num_planes > 0)
2626 program_all_pipe_in_tree(dc, top_pipe_to_program, context);
2627
2628 #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
2629
2630 if ((stream->num_wb_info > 0) && (dc->hwss.program_all_writeback_pipes_in_tree))
2631 dc->hwss.program_all_writeback_pipes_in_tree(dc, stream, context);
2632 #endif
2633 if (interdependent_update)
2634 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2635 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2636
2637 if (!pipe_ctx->stream || pipe_ctx->stream == stream ||
2638 !pipe_ctx->plane_state || !tg->funcs->is_tg_enabled(tg))
2639 continue;
2640
2641 pipe_ctx->plane_res.hubp->funcs->hubp_setup_interdependent(
2642 pipe_ctx->plane_res.hubp,
2643 &pipe_ctx->dlg_regs,
2644 &pipe_ctx->ttu_regs);
2645 }
2646
2647 if (interdependent_update)
2648 lock_all_pipes(dc, context, false);
2649 else
2650 dcn10_pipe_control_lock(dc, top_pipe_to_program, false);
2651
2652 if (num_planes == 0)
2653 false_optc_underflow_wa(dc, stream, tg);
2654
2655 for (i = 0; i < dc->res_pool->pipe_count; i++)
2656 if (removed_pipe[i])
2657 dc->hwss.disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
2658
2659 for (i = 0; i < dc->res_pool->pipe_count; i++)
2660 if (removed_pipe[i]) {
2661 dc->hwss.optimize_bandwidth(dc, context);
2662 break;
2663 }
2664
2665 if (dc->hwseq->wa.DEGVIDCN10_254)
2666 hubbub1_wm_change_req_wa(dc->res_pool->hubbub);
2667 }
2668
2669 static void dcn10_stereo_hw_frame_pack_wa(struct dc *dc, struct dc_state *context)
2670 {
2671 uint8_t i;
2672
2673 for (i = 0; i < context->stream_count; i++) {
2674 if (context->streams[i]->timing.timing_3d_format
2675 == TIMING_3D_FORMAT_HW_FRAME_PACKING) {
2676
2677
2678
2679 hubbub1_allow_self_refresh_control(dc->res_pool->hubbub, false);
2680 break;
2681 }
2682 }
2683 }
2684
2685 static void dcn10_prepare_bandwidth(
2686 struct dc *dc,
2687 struct dc_state *context)
2688 {
2689 struct hubbub *hubbub = dc->res_pool->hubbub;
2690
2691 if (dc->debug.sanity_checks)
2692 dcn10_verify_allow_pstate_change_high(dc);
2693
2694 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
2695 if (context->stream_count == 0)
2696 context->bw_ctx.bw.dcn.clk.phyclk_khz = 0;
2697
2698 dc->clk_mgr->funcs->update_clocks(
2699 dc->clk_mgr,
2700 context,
2701 false);
2702 }
2703
2704 hubbub->funcs->program_watermarks(hubbub,
2705 &context->bw_ctx.bw.dcn.watermarks,
2706 dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
2707 true);
2708 dcn10_stereo_hw_frame_pack_wa(dc, context);
2709
2710 if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE)
2711 dcn_bw_notify_pplib_of_wm_ranges(dc);
2712
2713 if (dc->debug.sanity_checks)
2714 dcn10_verify_allow_pstate_change_high(dc);
2715 }
2716
2717 static void dcn10_optimize_bandwidth(
2718 struct dc *dc,
2719 struct dc_state *context)
2720 {
2721 struct hubbub *hubbub = dc->res_pool->hubbub;
2722
2723 if (dc->debug.sanity_checks)
2724 dcn10_verify_allow_pstate_change_high(dc);
2725
2726 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
2727 if (context->stream_count == 0)
2728 context->bw_ctx.bw.dcn.clk.phyclk_khz = 0;
2729
2730 dc->clk_mgr->funcs->update_clocks(
2731 dc->clk_mgr,
2732 context,
2733 true);
2734 }
2735
2736 hubbub->funcs->program_watermarks(hubbub,
2737 &context->bw_ctx.bw.dcn.watermarks,
2738 dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
2739 true);
2740 dcn10_stereo_hw_frame_pack_wa(dc, context);
2741
2742 if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE)
2743 dcn_bw_notify_pplib_of_wm_ranges(dc);
2744
2745 if (dc->debug.sanity_checks)
2746 dcn10_verify_allow_pstate_change_high(dc);
2747 }
2748
2749 static void dcn10_set_drr(struct pipe_ctx **pipe_ctx,
2750 int num_pipes, unsigned int vmin, unsigned int vmax,
2751 unsigned int vmid, unsigned int vmid_frame_number)
2752 {
2753 int i = 0;
2754 struct drr_params params = {0};
2755
2756 unsigned int event_triggers = 0x800;
2757
2758 params.vertical_total_max = vmax;
2759 params.vertical_total_min = vmin;
2760 params.vertical_total_mid = vmid;
2761 params.vertical_total_mid_frame_num = vmid_frame_number;
2762
2763
2764
2765
2766
2767 for (i = 0; i < num_pipes; i++) {
2768 pipe_ctx[i]->stream_res.tg->funcs->set_drr(
2769 pipe_ctx[i]->stream_res.tg, ¶ms);
2770 if (vmax != 0 && vmin != 0)
2771 pipe_ctx[i]->stream_res.tg->funcs->set_static_screen_control(
2772 pipe_ctx[i]->stream_res.tg,
2773 event_triggers);
2774 }
2775 }
2776
2777 static void dcn10_get_position(struct pipe_ctx **pipe_ctx,
2778 int num_pipes,
2779 struct crtc_position *position)
2780 {
2781 int i = 0;
2782
2783
2784
2785 for (i = 0; i < num_pipes; i++)
2786 pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position);
2787 }
2788
2789 static void dcn10_set_static_screen_control(struct pipe_ctx **pipe_ctx,
2790 int num_pipes, const struct dc_static_screen_events *events)
2791 {
2792 unsigned int i;
2793 unsigned int value = 0;
2794
2795 if (events->surface_update)
2796 value |= 0x80;
2797 if (events->cursor_update)
2798 value |= 0x2;
2799 if (events->force_trigger)
2800 value |= 0x1;
2801
2802 for (i = 0; i < num_pipes; i++)
2803 pipe_ctx[i]->stream_res.tg->funcs->
2804 set_static_screen_control(pipe_ctx[i]->stream_res.tg, value);
2805 }
2806
2807 static void dcn10_config_stereo_parameters(
2808 struct dc_stream_state *stream, struct crtc_stereo_flags *flags)
2809 {
2810 enum view_3d_format view_format = stream->view_format;
2811 enum dc_timing_3d_format timing_3d_format =\
2812 stream->timing.timing_3d_format;
2813 bool non_stereo_timing = false;
2814
2815 if (timing_3d_format == TIMING_3D_FORMAT_NONE ||
2816 timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE ||
2817 timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM)
2818 non_stereo_timing = true;
2819
2820 if (non_stereo_timing == false &&
2821 view_format == VIEW_3D_FORMAT_FRAME_SEQUENTIAL) {
2822
2823 flags->PROGRAM_STEREO = 1;
2824 flags->PROGRAM_POLARITY = 1;
2825 if (timing_3d_format == TIMING_3D_FORMAT_INBAND_FA ||
2826 timing_3d_format == TIMING_3D_FORMAT_DP_HDMI_INBAND_FA ||
2827 timing_3d_format == TIMING_3D_FORMAT_SIDEBAND_FA) {
2828 enum display_dongle_type dongle = \
2829 stream->link->ddc->dongle_type;
2830 if (dongle == DISPLAY_DONGLE_DP_VGA_CONVERTER ||
2831 dongle == DISPLAY_DONGLE_DP_DVI_CONVERTER ||
2832 dongle == DISPLAY_DONGLE_DP_HDMI_CONVERTER)
2833 flags->DISABLE_STEREO_DP_SYNC = 1;
2834 }
2835 flags->RIGHT_EYE_POLARITY =\
2836 stream->timing.flags.RIGHT_EYE_3D_POLARITY;
2837 if (timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
2838 flags->FRAME_PACKED = 1;
2839 }
2840
2841 return;
2842 }
2843
2844 static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc)
2845 {
2846 struct crtc_stereo_flags flags = { 0 };
2847 struct dc_stream_state *stream = pipe_ctx->stream;
2848
2849 dcn10_config_stereo_parameters(stream, &flags);
2850
2851 if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_SIDEBAND_FA) {
2852 if (!dc_set_generic_gpio_for_stereo(true, dc->ctx->gpio_service))
2853 dc_set_generic_gpio_for_stereo(false, dc->ctx->gpio_service);
2854 } else {
2855 dc_set_generic_gpio_for_stereo(false, dc->ctx->gpio_service);
2856 }
2857
2858 pipe_ctx->stream_res.opp->funcs->opp_program_stereo(
2859 pipe_ctx->stream_res.opp,
2860 flags.PROGRAM_STEREO == 1 ? true:false,
2861 &stream->timing);
2862
2863 pipe_ctx->stream_res.tg->funcs->program_stereo(
2864 pipe_ctx->stream_res.tg,
2865 &stream->timing,
2866 &flags);
2867
2868 return;
2869 }
2870
2871 static struct hubp *get_hubp_by_inst(struct resource_pool *res_pool, int mpcc_inst)
2872 {
2873 int i;
2874
2875 for (i = 0; i < res_pool->pipe_count; i++) {
2876 if (res_pool->hubps[i]->inst == mpcc_inst)
2877 return res_pool->hubps[i];
2878 }
2879 ASSERT(false);
2880 return NULL;
2881 }
2882
2883 static void dcn10_wait_for_mpcc_disconnect(
2884 struct dc *dc,
2885 struct resource_pool *res_pool,
2886 struct pipe_ctx *pipe_ctx)
2887 {
2888 int mpcc_inst;
2889
2890 if (dc->debug.sanity_checks) {
2891 dcn10_verify_allow_pstate_change_high(dc);
2892 }
2893
2894 if (!pipe_ctx->stream_res.opp)
2895 return;
2896
2897 for (mpcc_inst = 0; mpcc_inst < MAX_PIPES; mpcc_inst++) {
2898 if (pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst]) {
2899 struct hubp *hubp = get_hubp_by_inst(res_pool, mpcc_inst);
2900
2901 res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, mpcc_inst);
2902 pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst] = false;
2903 hubp->funcs->set_blank(hubp, true);
2904 }
2905 }
2906
2907 if (dc->debug.sanity_checks) {
2908 dcn10_verify_allow_pstate_change_high(dc);
2909 }
2910
2911 }
2912
2913 static bool dcn10_dummy_display_power_gating(
2914 struct dc *dc,
2915 uint8_t controller_id,
2916 struct dc_bios *dcb,
2917 enum pipe_gating_control power_gating)
2918 {
2919 return true;
2920 }
2921
2922 static void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx)
2923 {
2924 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
2925 struct timing_generator *tg = pipe_ctx->stream_res.tg;
2926 bool flip_pending;
2927
2928 if (plane_state == NULL)
2929 return;
2930
2931 flip_pending = pipe_ctx->plane_res.hubp->funcs->hubp_is_flip_pending(
2932 pipe_ctx->plane_res.hubp);
2933
2934 plane_state->status.is_flip_pending = plane_state->status.is_flip_pending || flip_pending;
2935
2936 if (!flip_pending)
2937 plane_state->status.current_address = plane_state->status.requested_address;
2938
2939 if (plane_state->status.current_address.type == PLN_ADDR_TYPE_GRPH_STEREO &&
2940 tg->funcs->is_stereo_left_eye) {
2941 plane_state->status.is_right_eye =
2942 !tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg);
2943 }
2944 }
2945
2946 static void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data)
2947 {
2948 struct hubbub *hubbub = hws->ctx->dc->res_pool->hubbub;
2949
2950
2951 hubbub->funcs->update_dchub(hubbub, dh_data);
2952 }
2953
2954 static void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
2955 {
2956 struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position;
2957 struct hubp *hubp = pipe_ctx->plane_res.hubp;
2958 struct dpp *dpp = pipe_ctx->plane_res.dpp;
2959 struct dc_cursor_mi_param param = {
2960 .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10,
2961 .ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clocks.dchub_ref_clock_inKhz,
2962 .viewport = pipe_ctx->plane_res.scl_data.viewport,
2963 .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz,
2964 .v_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.vert,
2965 .rotation = pipe_ctx->plane_state->rotation,
2966 .mirror = pipe_ctx->plane_state->horizontal_mirror
2967 };
2968 uint32_t x_plane = pipe_ctx->plane_state->dst_rect.x;
2969 uint32_t y_plane = pipe_ctx->plane_state->dst_rect.y;
2970 uint32_t x_offset = min(x_plane, pos_cpy.x);
2971 uint32_t y_offset = min(y_plane, pos_cpy.y);
2972
2973 pos_cpy.x -= x_offset;
2974 pos_cpy.y -= y_offset;
2975 pos_cpy.x_hotspot += (x_plane - x_offset);
2976 pos_cpy.y_hotspot += (y_plane - y_offset);
2977
2978 if (pipe_ctx->plane_state->address.type
2979 == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
2980 pos_cpy.enable = false;
2981
2982
2983 if (param.rotation == ROTATION_ANGLE_90) {
2984 uint32_t temp_x = pos_cpy.x;
2985 pos_cpy.x = pipe_ctx->plane_res.scl_data.viewport.width -
2986 (pos_cpy.y - pipe_ctx->plane_res.scl_data.viewport.x) + pipe_ctx->plane_res.scl_data.viewport.x;
2987 pos_cpy.y = temp_x;
2988 }
2989
2990 else if (param.rotation == ROTATION_ANGLE_270) {
2991 uint32_t temp_y = pos_cpy.y;
2992 if (pos_cpy.x > pipe_ctx->plane_res.scl_data.viewport.height) {
2993 pos_cpy.x = pos_cpy.x - pipe_ctx->plane_res.scl_data.viewport.height;
2994 pos_cpy.y = pipe_ctx->plane_res.scl_data.viewport.height - pos_cpy.x;
2995 } else {
2996 pos_cpy.y = 2 * pipe_ctx->plane_res.scl_data.viewport.height - pos_cpy.x;
2997 }
2998 pos_cpy.x = temp_y;
2999 }
3000
3001 else if (param.rotation == ROTATION_ANGLE_180) {
3002 if (pos_cpy.x >= pipe_ctx->plane_res.scl_data.viewport.width + pipe_ctx->plane_res.scl_data.viewport.x) {
3003 pos_cpy.x = 2 * pipe_ctx->plane_res.scl_data.viewport.width
3004 - pos_cpy.x + 2 * pipe_ctx->plane_res.scl_data.viewport.x;
3005 } else {
3006 uint32_t temp_x = pos_cpy.x;
3007 pos_cpy.x = 2 * pipe_ctx->plane_res.scl_data.viewport.x - pos_cpy.x;
3008 if (temp_x >= pipe_ctx->plane_res.scl_data.viewport.x + (int)hubp->curs_attr.width
3009 || pos_cpy.x <= (int)hubp->curs_attr.width + pipe_ctx->plane_state->src_rect.x) {
3010 pos_cpy.x = temp_x + pipe_ctx->plane_res.scl_data.viewport.width;
3011 }
3012 }
3013 pos_cpy.y = pipe_ctx->plane_res.scl_data.viewport.height - pos_cpy.y;
3014 }
3015
3016 hubp->funcs->set_cursor_position(hubp, &pos_cpy, ¶m);
3017 dpp->funcs->set_cursor_position(dpp, &pos_cpy, ¶m, hubp->curs_attr.width, hubp->curs_attr.height);
3018 }
3019
3020 static void dcn10_set_cursor_attribute(struct pipe_ctx *pipe_ctx)
3021 {
3022 struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes;
3023
3024 pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes(
3025 pipe_ctx->plane_res.hubp, attributes);
3026 pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes(
3027 pipe_ctx->plane_res.dpp, attributes);
3028 }
3029
3030 static void dcn10_set_cursor_sdr_white_level(struct pipe_ctx *pipe_ctx)
3031 {
3032 uint32_t sdr_white_level = pipe_ctx->stream->cursor_attributes.sdr_white_level;
3033 struct fixed31_32 multiplier;
3034 struct dpp_cursor_attributes opt_attr = { 0 };
3035 uint32_t hw_scale = 0x3c00;
3036 struct custom_float_format fmt;
3037
3038 if (!pipe_ctx->plane_res.dpp->funcs->set_optional_cursor_attributes)
3039 return;
3040
3041 fmt.exponenta_bits = 5;
3042 fmt.mantissa_bits = 10;
3043 fmt.sign = true;
3044
3045 if (sdr_white_level > 80) {
3046 multiplier = dc_fixpt_from_fraction(sdr_white_level, 80);
3047 convert_to_custom_float_format(multiplier, &fmt, &hw_scale);
3048 }
3049
3050 opt_attr.scale = hw_scale;
3051 opt_attr.bias = 0;
3052
3053 pipe_ctx->plane_res.dpp->funcs->set_optional_cursor_attributes(
3054 pipe_ctx->plane_res.dpp, &opt_attr);
3055 }
3056
3057
3058
3059
3060
3061
3062
3063 static void apply_front_porch_workaround(
3064 struct dc_crtc_timing *timing)
3065 {
3066 if (timing->flags.INTERLACE == 1) {
3067 if (timing->v_front_porch < 2)
3068 timing->v_front_porch = 2;
3069 } else {
3070 if (timing->v_front_porch < 1)
3071 timing->v_front_porch = 1;
3072 }
3073 }
3074
3075 int get_vupdate_offset_from_vsync(struct pipe_ctx *pipe_ctx)
3076 {
3077 const struct dc_crtc_timing *dc_crtc_timing = &pipe_ctx->stream->timing;
3078 struct dc_crtc_timing patched_crtc_timing;
3079 int vesa_sync_start;
3080 int asic_blank_end;
3081 int interlace_factor;
3082 int vertical_line_start;
3083
3084 patched_crtc_timing = *dc_crtc_timing;
3085 apply_front_porch_workaround(&patched_crtc_timing);
3086
3087 interlace_factor = patched_crtc_timing.flags.INTERLACE ? 2 : 1;
3088
3089 vesa_sync_start = patched_crtc_timing.v_addressable +
3090 patched_crtc_timing.v_border_bottom +
3091 patched_crtc_timing.v_front_porch;
3092
3093 asic_blank_end = (patched_crtc_timing.v_total -
3094 vesa_sync_start -
3095 patched_crtc_timing.v_border_top)
3096 * interlace_factor;
3097
3098 vertical_line_start = asic_blank_end -
3099 pipe_ctx->pipe_dlg_param.vstartup_start + 1;
3100
3101 return vertical_line_start;
3102 }
3103
3104 void lock_all_pipes(struct dc *dc,
3105 struct dc_state *context,
3106 bool lock)
3107 {
3108 struct pipe_ctx *pipe_ctx;
3109 struct timing_generator *tg;
3110 int i;
3111
3112 for (i = 0; i < dc->res_pool->pipe_count; i++) {
3113 pipe_ctx = &context->res_ctx.pipe_ctx[i];
3114 tg = pipe_ctx->stream_res.tg;
3115
3116
3117
3118
3119 if (pipe_ctx->top_pipe ||
3120 !pipe_ctx->stream || !pipe_ctx->plane_state ||
3121 !tg->funcs->is_tg_enabled(tg))
3122 continue;
3123
3124 if (lock)
3125 tg->funcs->lock(tg);
3126 else
3127 tg->funcs->unlock(tg);
3128 }
3129 }
3130
3131 static void calc_vupdate_position(
3132 struct pipe_ctx *pipe_ctx,
3133 uint32_t *start_line,
3134 uint32_t *end_line)
3135 {
3136 const struct dc_crtc_timing *dc_crtc_timing = &pipe_ctx->stream->timing;
3137 int vline_int_offset_from_vupdate =
3138 pipe_ctx->stream->periodic_interrupt0.lines_offset;
3139 int vupdate_offset_from_vsync = get_vupdate_offset_from_vsync(pipe_ctx);
3140 int start_position;
3141
3142 if (vline_int_offset_from_vupdate > 0)
3143 vline_int_offset_from_vupdate--;
3144 else if (vline_int_offset_from_vupdate < 0)
3145 vline_int_offset_from_vupdate++;
3146
3147 start_position = vline_int_offset_from_vupdate + vupdate_offset_from_vsync;
3148
3149 if (start_position >= 0)
3150 *start_line = start_position;
3151 else
3152 *start_line = dc_crtc_timing->v_total + start_position - 1;
3153
3154 *end_line = *start_line + 2;
3155
3156 if (*end_line >= dc_crtc_timing->v_total)
3157 *end_line = 2;
3158 }
3159
3160 static void cal_vline_position(
3161 struct pipe_ctx *pipe_ctx,
3162 enum vline_select vline,
3163 uint32_t *start_line,
3164 uint32_t *end_line)
3165 {
3166 enum vertical_interrupt_ref_point ref_point = INVALID_POINT;
3167
3168 if (vline == VLINE0)
3169 ref_point = pipe_ctx->stream->periodic_interrupt0.ref_point;
3170 else if (vline == VLINE1)
3171 ref_point = pipe_ctx->stream->periodic_interrupt1.ref_point;
3172
3173 switch (ref_point) {
3174 case START_V_UPDATE:
3175 calc_vupdate_position(
3176 pipe_ctx,
3177 start_line,
3178 end_line);
3179 break;
3180 case START_V_SYNC:
3181
3182 break;
3183 default:
3184 ASSERT(0);
3185 break;
3186 }
3187 }
3188
3189 static void dcn10_setup_periodic_interrupt(
3190 struct pipe_ctx *pipe_ctx,
3191 enum vline_select vline)
3192 {
3193 struct timing_generator *tg = pipe_ctx->stream_res.tg;
3194
3195 if (vline == VLINE0) {
3196 uint32_t start_line = 0;
3197 uint32_t end_line = 0;
3198
3199 cal_vline_position(pipe_ctx, vline, &start_line, &end_line);
3200
3201 tg->funcs->setup_vertical_interrupt0(tg, start_line, end_line);
3202
3203 } else if (vline == VLINE1) {
3204 pipe_ctx->stream_res.tg->funcs->setup_vertical_interrupt1(
3205 tg,
3206 pipe_ctx->stream->periodic_interrupt1.lines_offset);
3207 }
3208 }
3209
3210 static void dcn10_setup_vupdate_interrupt(struct pipe_ctx *pipe_ctx)
3211 {
3212 struct timing_generator *tg = pipe_ctx->stream_res.tg;
3213 int start_line = get_vupdate_offset_from_vsync(pipe_ctx);
3214
3215 if (start_line < 0) {
3216 ASSERT(0);
3217 start_line = 0;
3218 }
3219
3220 if (tg->funcs->setup_vertical_interrupt2)
3221 tg->funcs->setup_vertical_interrupt2(tg, start_line);
3222 }
3223
3224 static void dcn10_unblank_stream(struct pipe_ctx *pipe_ctx,
3225 struct dc_link_settings *link_settings)
3226 {
3227 struct encoder_unblank_param params = { { 0 } };
3228 struct dc_stream_state *stream = pipe_ctx->stream;
3229 struct dc_link *link = stream->link;
3230
3231
3232 params.timing = pipe_ctx->stream->timing;
3233
3234 params.link_settings.link_rate = link_settings->link_rate;
3235
3236 if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
3237 if (params.timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
3238 params.timing.pix_clk_100hz /= 2;
3239 pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms);
3240 }
3241
3242 if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
3243 link->dc->hwss.edp_backlight_control(link, true);
3244 }
3245 }
3246
3247 static void dcn10_send_immediate_sdp_message(struct pipe_ctx *pipe_ctx,
3248 const uint8_t *custom_sdp_message,
3249 unsigned int sdp_message_size)
3250 {
3251 if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
3252 pipe_ctx->stream_res.stream_enc->funcs->send_immediate_sdp_message(
3253 pipe_ctx->stream_res.stream_enc,
3254 custom_sdp_message,
3255 sdp_message_size);
3256 }
3257 }
3258 static enum dc_status dcn10_set_clock(struct dc *dc,
3259 enum dc_clock_type clock_type,
3260 uint32_t clk_khz,
3261 uint32_t stepping)
3262 {
3263 struct dc_state *context = dc->current_state;
3264 struct dc_clock_config clock_cfg = {0};
3265 struct dc_clocks *current_clocks = &context->bw_ctx.bw.dcn.clk;
3266
3267 if (dc->clk_mgr && dc->clk_mgr->funcs->get_clock)
3268 dc->clk_mgr->funcs->get_clock(dc->clk_mgr,
3269 context, clock_type, &clock_cfg);
3270
3271 if (!dc->clk_mgr->funcs->get_clock)
3272 return DC_FAIL_UNSUPPORTED_1;
3273
3274 if (clk_khz > clock_cfg.max_clock_khz)
3275 return DC_FAIL_CLK_EXCEED_MAX;
3276
3277 if (clk_khz < clock_cfg.min_clock_khz)
3278 return DC_FAIL_CLK_BELOW_MIN;
3279
3280 if (clk_khz < clock_cfg.bw_requirequired_clock_khz)
3281 return DC_FAIL_CLK_BELOW_CFG_REQUIRED;
3282
3283
3284 if (clock_type == DC_CLOCK_TYPE_DISPCLK)
3285 current_clocks->dispclk_khz = clk_khz;
3286 else if (clock_type == DC_CLOCK_TYPE_DPPCLK)
3287 current_clocks->dppclk_khz = clk_khz;
3288 else
3289 return DC_ERROR_UNEXPECTED;
3290
3291 if (dc->clk_mgr && dc->clk_mgr->funcs->update_clocks)
3292 dc->clk_mgr->funcs->update_clocks(dc->clk_mgr,
3293 context, true);
3294 return DC_OK;
3295
3296 }
3297
3298 static void dcn10_get_clock(struct dc *dc,
3299 enum dc_clock_type clock_type,
3300 struct dc_clock_config *clock_cfg)
3301 {
3302 struct dc_state *context = dc->current_state;
3303
3304 if (dc->clk_mgr && dc->clk_mgr->funcs->get_clock)
3305 dc->clk_mgr->funcs->get_clock(dc->clk_mgr, context, clock_type, clock_cfg);
3306
3307 }
3308
3309 static const struct hw_sequencer_funcs dcn10_funcs = {
3310 .program_gamut_remap = dcn10_program_gamut_remap,
3311 .init_hw = dcn10_init_hw,
3312 .init_pipes = dcn10_init_pipes,
3313 .apply_ctx_to_hw = dce110_apply_ctx_to_hw,
3314 .apply_ctx_for_surface = dcn10_apply_ctx_for_surface,
3315 .update_plane_addr = dcn10_update_plane_addr,
3316 .plane_atomic_disconnect = hwss1_plane_atomic_disconnect,
3317 .update_dchub = dcn10_update_dchub,
3318 .update_mpcc = dcn10_update_mpcc,
3319 .update_pending_status = dcn10_update_pending_status,
3320 .set_input_transfer_func = dcn10_set_input_transfer_func,
3321 .set_output_transfer_func = dcn10_set_output_transfer_func,
3322 .program_output_csc = dcn10_program_output_csc,
3323 .power_down = dce110_power_down,
3324 .enable_accelerated_mode = dce110_enable_accelerated_mode,
3325 .enable_timing_synchronization = dcn10_enable_timing_synchronization,
3326 .enable_per_frame_crtc_position_reset = dcn10_enable_per_frame_crtc_position_reset,
3327 .update_info_frame = dce110_update_info_frame,
3328 .send_immediate_sdp_message = dcn10_send_immediate_sdp_message,
3329 .enable_stream = dce110_enable_stream,
3330 .disable_stream = dce110_disable_stream,
3331 .unblank_stream = dcn10_unblank_stream,
3332 .blank_stream = dce110_blank_stream,
3333 .enable_audio_stream = dce110_enable_audio_stream,
3334 .disable_audio_stream = dce110_disable_audio_stream,
3335 .enable_display_power_gating = dcn10_dummy_display_power_gating,
3336 .disable_plane = dcn10_disable_plane,
3337 .blank_pixel_data = dcn10_blank_pixel_data,
3338 .pipe_control_lock = dcn10_pipe_control_lock,
3339 .prepare_bandwidth = dcn10_prepare_bandwidth,
3340 .optimize_bandwidth = dcn10_optimize_bandwidth,
3341 .reset_hw_ctx_wrap = dcn10_reset_hw_ctx_wrap,
3342 .enable_stream_timing = dcn10_enable_stream_timing,
3343 .set_drr = dcn10_set_drr,
3344 .get_position = dcn10_get_position,
3345 .set_static_screen_control = dcn10_set_static_screen_control,
3346 .setup_stereo = dcn10_setup_stereo,
3347 .set_avmute = dce110_set_avmute,
3348 .log_hw_state = dcn10_log_hw_state,
3349 .get_hw_state = dcn10_get_hw_state,
3350 .clear_status_bits = dcn10_clear_status_bits,
3351 .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect,
3352 .edp_backlight_control = dce110_edp_backlight_control,
3353 .edp_power_control = dce110_edp_power_control,
3354 .edp_wait_for_hpd_ready = dce110_edp_wait_for_hpd_ready,
3355 .set_cursor_position = dcn10_set_cursor_position,
3356 .set_cursor_attribute = dcn10_set_cursor_attribute,
3357 .set_cursor_sdr_white_level = dcn10_set_cursor_sdr_white_level,
3358 .disable_stream_gating = NULL,
3359 .enable_stream_gating = NULL,
3360 .setup_periodic_interrupt = dcn10_setup_periodic_interrupt,
3361 .setup_vupdate_interrupt = dcn10_setup_vupdate_interrupt,
3362 .set_clock = dcn10_set_clock,
3363 .get_clock = dcn10_get_clock,
3364 .did_underflow_occur = dcn10_did_underflow_occur,
3365 .init_blank = NULL,
3366 .disable_vga = dcn10_disable_vga,
3367 .bios_golden_init = dcn10_bios_golden_init,
3368 .plane_atomic_disable = dcn10_plane_atomic_disable,
3369 .plane_atomic_power_down = dcn10_plane_atomic_power_down,
3370 .enable_power_gating_plane = dcn10_enable_power_gating_plane,
3371 .dpp_pg_control = dcn10_dpp_pg_control,
3372 .hubp_pg_control = dcn10_hubp_pg_control,
3373 .dsc_pg_control = NULL,
3374 };
3375
3376
3377 void dcn10_hw_sequencer_construct(struct dc *dc)
3378 {
3379 dc->hwss = dcn10_funcs;
3380 }
3381