]>
Commit | Line | Data |
---|---|---|
70ccab60 HW |
1 | /* |
2 | * Copyright 2016 Advanced Micro Devices, Inc. | |
3 | * | |
4 | * Permission is hereby granted, free of charge, to any person obtaining a | |
5 | * copy of this software and associated documentation files (the "Software"), | |
6 | * to deal in the Software without restriction, including without limitation | |
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
8 | * and/or sell copies of the Software, and to permit persons to whom the | |
9 | * Software is furnished to do so, subject to the following conditions: | |
10 | * | |
11 | * The above copyright notice and this permission notice shall be included in | |
12 | * all copies or substantial portions of the Software. | |
13 | * | |
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
20 | * OTHER DEALINGS IN THE SOFTWARE. | |
21 | * | |
22 | * Authors: AMD | |
23 | * | |
24 | */ | |
25 | ||
26 | #include "dm_services.h" | |
70ccab60 | 27 | #include "core_types.h" |
70ccab60 | 28 | #include "resource.h" |
b02c3b05 | 29 | #include "custom_float.h" |
70ccab60 HW |
30 | #include "dcn10_hw_sequencer.h" |
31 | #include "dce110/dce110_hw_sequencer.h" | |
5aff86c1 | 32 | #include "dce/dce_hwseq.h" |
70ccab60 | 33 | #include "abm.h" |
4952d4c5 | 34 | #include "dmcu.h" |
b51adc77 | 35 | #include "dcn10_optc.h" |
587cdfe9 VP |
36 | #include "dcn10/dcn10_dpp.h" |
37 | #include "dcn10/dcn10_mpc.h" | |
70ccab60 HW |
38 | #include "timing_generator.h" |
39 | #include "opp.h" | |
40 | #include "ipp.h" | |
b02c3b05 | 41 | #include "mpc.h" |
184debdb | 42 | #include "reg_helper.h" |
a6def445 | 43 | #include "custom_float.h" |
86be9a04 | 44 | #include "dcn10_hubp.h" |
62d591a8 | 45 | #include "dcn10_hubbub.h" |
b6295960 | 46 | #include "dcn10_cm_common.h" |
aa9c4abe | 47 | #include "dc_link_dp.h" |
ea2e8d92 | 48 | #include "dccg.h" |
70ccab60 | 49 | |
5d4b05dd BL |
50 | #define DC_LOGGER_INIT(logger) |
51 | ||
184debdb DL |
52 | #define CTX \ |
53 | hws->ctx | |
54 | #define REG(reg)\ | |
55 | hws->regs->reg | |
70ccab60 | 56 | |
184debdb DL |
57 | #undef FN |
58 | #define FN(reg_name, field_name) \ | |
59 | hws->shifts->field_name, hws->masks->field_name | |
70ccab60 | 60 | |
a052a516 | 61 | /*print is 17 wide, first two characters are spaces*/ |
62d591a8 | 62 | #define DTN_INFO_MICRO_SEC(ref_cycle) \ |
46659a83 | 63 | print_microsec(dc_ctx, log_ctx, ref_cycle) |
71395011 | 64 | |
46659a83 NK |
65 | void print_microsec(struct dc_context *dc_ctx, |
66 | struct dc_log_buffer_ctx *log_ctx, | |
67 | uint32_t ref_cycle) | |
eb4e33b7 | 68 | { |
a052a516 DL |
69 | const uint32_t ref_clk_mhz = dc_ctx->dc->res_pool->ref_clock_inKhz / 1000; |
70 | static const unsigned int frac = 1000; | |
eb4e33b7 TC |
71 | uint32_t us_x10 = (ref_cycle * frac) / ref_clk_mhz; |
72 | ||
a052a516 | 73 | DTN_INFO(" %11d.%03d", |
eb4e33b7 TC |
74 | us_x10 / frac, |
75 | us_x10 % frac); | |
76 | } | |
77 | ||
46659a83 NK |
78 | static void log_mpc_crc(struct dc *dc, |
79 | struct dc_log_buffer_ctx *log_ctx) | |
233dcd20 | 80 | { |
62d591a8 YHL |
81 | struct dc_context *dc_ctx = dc->ctx; |
82 | struct dce_hwseq *hws = dc->hwseq; | |
83 | ||
84 | if (REG(MPC_CRC_RESULT_GB)) | |
85 | DTN_INFO("MPC_CRC_RESULT_GB:%d MPC_CRC_RESULT_C:%d MPC_CRC_RESULT_AR:%d\n", | |
86 | REG_READ(MPC_CRC_RESULT_GB), REG_READ(MPC_CRC_RESULT_C), REG_READ(MPC_CRC_RESULT_AR)); | |
87 | if (REG(DPP_TOP0_DPP_CRC_VAL_B_A)) | |
88 | DTN_INFO("DPP_TOP0_DPP_CRC_VAL_B_A:%d DPP_TOP0_DPP_CRC_VAL_R_G:%d\n", | |
89 | REG_READ(DPP_TOP0_DPP_CRC_VAL_B_A), REG_READ(DPP_TOP0_DPP_CRC_VAL_R_G)); | |
233dcd20 TC |
90 | } |
91 | ||
46659a83 | 92 | void dcn10_log_hubbub_state(struct dc *dc, struct dc_log_buffer_ctx *log_ctx) |
233dcd20 TC |
93 | { |
94 | struct dc_context *dc_ctx = dc->ctx; | |
d02e0794 | 95 | struct dcn_hubbub_wm wm = {0}; |
233dcd20 TC |
96 | int i; |
97 | ||
c9ef081d | 98 | hubbub1_wm_read_state(dc->res_pool->hubbub, &wm); |
233dcd20 | 99 | |
a052a516 DL |
100 | DTN_INFO("HUBBUB WM: data_urgent pte_meta_urgent" |
101 | " sr_enter sr_exit dram_clk_change\n"); | |
233dcd20 TC |
102 | |
103 | for (i = 0; i < 4; i++) { | |
104 | struct dcn_hubbub_wm_set *s; | |
105 | ||
106 | s = &wm.sets[i]; | |
a052a516 | 107 | DTN_INFO("WM_Set[%d]:", s->wm_set); |
233dcd20 TC |
108 | DTN_INFO_MICRO_SEC(s->data_urgent); |
109 | DTN_INFO_MICRO_SEC(s->pte_meta_urgent); | |
110 | DTN_INFO_MICRO_SEC(s->sr_enter); | |
111 | DTN_INFO_MICRO_SEC(s->sr_exit); | |
112 | DTN_INFO_MICRO_SEC(s->dram_clk_chanage); | |
113 | DTN_INFO("\n"); | |
114 | } | |
115 | ||
116 | DTN_INFO("\n"); | |
117 | } | |
118 | ||
46659a83 | 119 | static void dcn10_log_hubp_states(struct dc *dc, void *log_ctx) |
71395011 TC |
120 | { |
121 | struct dc_context *dc_ctx = dc->ctx; | |
122 | struct resource_pool *pool = dc->res_pool; | |
123 | int i; | |
124 | ||
a052a516 DL |
125 | DTN_INFO("HUBP: format addr_hi width height" |
126 | " rot mir sw_mode dcc_en blank_en ttu_dis underflow" | |
127 | " min_ttu_vblank qos_low_wm qos_high_wm\n"); | |
71395011 | 128 | for (i = 0; i < pool->pipe_count; i++) { |
8feabd03 | 129 | struct hubp *hubp = pool->hubps[i]; |
34cb6b38 | 130 | struct dcn_hubp_state *s = &(TO_DCN10_HUBP(hubp)->state); |
71395011 | 131 | |
34cb6b38 | 132 | hubp->funcs->hubp_read_state(hubp); |
71395011 | 133 | |
a3cb1c1c NC |
134 | if (!s->blank_en) { |
135 | DTN_INFO("[%2d]: %5xh %6xh %5d %6d %2xh %2xh %6xh" | |
136 | " %6d %8d %7d %8xh", | |
137 | hubp->inst, | |
138 | s->pixel_format, | |
139 | s->inuse_addr_hi, | |
140 | s->viewport_width, | |
141 | s->viewport_height, | |
142 | s->rotation_angle, | |
143 | s->h_mirror_en, | |
144 | s->sw_mode, | |
145 | s->dcc_en, | |
146 | s->blank_en, | |
147 | s->ttu_disable, | |
148 | s->underflow_status); | |
149 | DTN_INFO_MICRO_SEC(s->min_ttu_vblank); | |
150 | DTN_INFO_MICRO_SEC(s->qos_level_low_wm); | |
151 | DTN_INFO_MICRO_SEC(s->qos_level_high_wm); | |
152 | DTN_INFO("\n"); | |
153 | } | |
71395011 | 154 | } |
34cb6b38 DL |
155 | |
156 | DTN_INFO("\n=========RQ========\n"); | |
157 | 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" | |
b9c1c67a | 158 | " min_m_c_s dpte_gr_s mpte_gr_s swath_hei pte_row_h C:chunk_s min_chu_s meta_ch_s" |
34cb6b38 DL |
159 | " min_m_c_s dpte_gr_s mpte_gr_s swath_hei pte_row_h\n"); |
160 | for (i = 0; i < pool->pipe_count; i++) { | |
161 | struct dcn_hubp_state *s = &(TO_DCN10_HUBP(pool->hubps[i])->state); | |
162 | struct _vcs_dpi_display_rq_regs_st *rq_regs = &s->rq_regs; | |
163 | ||
a3cb1c1c | 164 | if (!s->blank_en) |
b9c1c67a | 165 | 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", |
a3cb1c1c NC |
166 | pool->hubps[i]->inst, rq_regs->drq_expansion_mode, rq_regs->prq_expansion_mode, rq_regs->mrq_expansion_mode, |
167 | rq_regs->crq_expansion_mode, rq_regs->plane1_base_address, rq_regs->rq_regs_l.chunk_size, | |
168 | rq_regs->rq_regs_l.min_chunk_size, rq_regs->rq_regs_l.meta_chunk_size, | |
169 | rq_regs->rq_regs_l.min_meta_chunk_size, rq_regs->rq_regs_l.dpte_group_size, | |
170 | rq_regs->rq_regs_l.mpte_group_size, rq_regs->rq_regs_l.swath_height, | |
b9c1c67a DL |
171 | rq_regs->rq_regs_l.pte_row_height_linear, rq_regs->rq_regs_c.chunk_size, rq_regs->rq_regs_c.min_chunk_size, |
172 | rq_regs->rq_regs_c.meta_chunk_size, rq_regs->rq_regs_c.min_meta_chunk_size, | |
173 | rq_regs->rq_regs_c.dpte_group_size, rq_regs->rq_regs_c.mpte_group_size, | |
174 | rq_regs->rq_regs_c.swath_height, rq_regs->rq_regs_c.pte_row_height_linear); | |
34cb6b38 DL |
175 | } |
176 | ||
177 | DTN_INFO("========DLG========\n"); | |
178 | DTN_INFO("HUBP: rc_hbe dlg_vbe min_d_y_n rc_per_ht rc_x_a_s " | |
179 | " dst_y_a_s dst_y_pf dst_y_vvb dst_y_rvb dst_y_vfl dst_y_rfl rf_pix_fq" | |
180 | " vratio_pf vrat_pf_c rc_pg_vbl rc_pg_vbc rc_mc_vbl rc_mc_vbc rc_pg_fll" | |
181 | " rc_pg_flc rc_mc_fll rc_mc_flc pr_nom_l pr_nom_c rc_pg_nl rc_pg_nc " | |
182 | " mr_nom_l mr_nom_c rc_mc_nl rc_mc_nc rc_ld_pl rc_ld_pc rc_ld_l " | |
183 | " rc_ld_c cha_cur0 ofst_cur1 cha_cur1 vr_af_vc0 ddrq_limt x_rt_dlay" | |
184 | " x_rp_dlay x_rr_sfl\n"); | |
185 | for (i = 0; i < pool->pipe_count; i++) { | |
186 | struct dcn_hubp_state *s = &(TO_DCN10_HUBP(pool->hubps[i])->state); | |
187 | struct _vcs_dpi_display_dlg_regs_st *dlg_regs = &s->dlg_attr; | |
188 | ||
a3cb1c1c NC |
189 | if (!s->blank_en) |
190 | DTN_INFO("[%2d]: %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh" | |
191 | "% 8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh" | |
192 | " %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh\n", | |
193 | pool->hubps[i]->inst, dlg_regs->refcyc_h_blank_end, dlg_regs->dlg_vblank_end, dlg_regs->min_dst_y_next_start, | |
194 | dlg_regs->refcyc_per_htotal, dlg_regs->refcyc_x_after_scaler, dlg_regs->dst_y_after_scaler, | |
195 | dlg_regs->dst_y_prefetch, dlg_regs->dst_y_per_vm_vblank, dlg_regs->dst_y_per_row_vblank, | |
196 | dlg_regs->dst_y_per_vm_flip, dlg_regs->dst_y_per_row_flip, dlg_regs->ref_freq_to_pix_freq, | |
197 | dlg_regs->vratio_prefetch, dlg_regs->vratio_prefetch_c, dlg_regs->refcyc_per_pte_group_vblank_l, | |
198 | dlg_regs->refcyc_per_pte_group_vblank_c, dlg_regs->refcyc_per_meta_chunk_vblank_l, | |
199 | dlg_regs->refcyc_per_meta_chunk_vblank_c, dlg_regs->refcyc_per_pte_group_flip_l, | |
200 | dlg_regs->refcyc_per_pte_group_flip_c, dlg_regs->refcyc_per_meta_chunk_flip_l, | |
201 | dlg_regs->refcyc_per_meta_chunk_flip_c, dlg_regs->dst_y_per_pte_row_nom_l, | |
202 | dlg_regs->dst_y_per_pte_row_nom_c, dlg_regs->refcyc_per_pte_group_nom_l, | |
203 | dlg_regs->refcyc_per_pte_group_nom_c, dlg_regs->dst_y_per_meta_row_nom_l, | |
204 | dlg_regs->dst_y_per_meta_row_nom_c, dlg_regs->refcyc_per_meta_chunk_nom_l, | |
205 | dlg_regs->refcyc_per_meta_chunk_nom_c, dlg_regs->refcyc_per_line_delivery_pre_l, | |
206 | dlg_regs->refcyc_per_line_delivery_pre_c, dlg_regs->refcyc_per_line_delivery_l, | |
207 | dlg_regs->refcyc_per_line_delivery_c, dlg_regs->chunk_hdl_adjust_cur0, dlg_regs->dst_y_offset_cur1, | |
208 | dlg_regs->chunk_hdl_adjust_cur1, dlg_regs->vready_after_vcount0, dlg_regs->dst_y_delta_drq_limit, | |
209 | dlg_regs->xfc_reg_transfer_delay, dlg_regs->xfc_reg_precharge_delay, | |
210 | dlg_regs->xfc_reg_remote_surface_flip_latency); | |
34cb6b38 DL |
211 | } |
212 | ||
213 | DTN_INFO("========TTU========\n"); | |
214 | 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" | |
215 | " rc_rd_c rc_rd_c0 rc_rd_pc0 rc_rd_c1 rc_rd_pc1 qos_lf_l qos_rds_l" | |
216 | " qos_lf_c qos_rds_c qos_lf_c0 qos_rds_c0 qos_lf_c1 qos_rds_c1\n"); | |
217 | for (i = 0; i < pool->pipe_count; i++) { | |
218 | struct dcn_hubp_state *s = &(TO_DCN10_HUBP(pool->hubps[i])->state); | |
219 | struct _vcs_dpi_display_ttu_regs_st *ttu_regs = &s->ttu_attr; | |
220 | ||
a3cb1c1c NC |
221 | if (!s->blank_en) |
222 | DTN_INFO("[%2d]: %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh\n", | |
223 | pool->hubps[i]->inst, ttu_regs->qos_level_low_wm, ttu_regs->qos_level_high_wm, ttu_regs->min_ttu_vblank, | |
224 | ttu_regs->qos_level_flip, ttu_regs->refcyc_per_req_delivery_pre_l, ttu_regs->refcyc_per_req_delivery_l, | |
225 | ttu_regs->refcyc_per_req_delivery_pre_c, ttu_regs->refcyc_per_req_delivery_c, ttu_regs->refcyc_per_req_delivery_cur0, | |
226 | ttu_regs->refcyc_per_req_delivery_pre_cur0, ttu_regs->refcyc_per_req_delivery_cur1, | |
227 | ttu_regs->refcyc_per_req_delivery_pre_cur1, ttu_regs->qos_level_fixed_l, ttu_regs->qos_ramp_disable_l, | |
228 | ttu_regs->qos_level_fixed_c, ttu_regs->qos_ramp_disable_c, ttu_regs->qos_level_fixed_cur0, | |
229 | ttu_regs->qos_ramp_disable_cur0, ttu_regs->qos_level_fixed_cur1, ttu_regs->qos_ramp_disable_cur1); | |
34cb6b38 | 230 | } |
71395011 | 231 | DTN_INFO("\n"); |
34cb6b38 DL |
232 | } |
233 | ||
46659a83 NK |
234 | void dcn10_log_hw_state(struct dc *dc, |
235 | struct dc_log_buffer_ctx *log_ctx) | |
34cb6b38 DL |
236 | { |
237 | struct dc_context *dc_ctx = dc->ctx; | |
238 | struct resource_pool *pool = dc->res_pool; | |
239 | int i; | |
240 | ||
241 | DTN_INFO_BEGIN(); | |
242 | ||
46659a83 | 243 | dcn10_log_hubbub_state(dc, log_ctx); |
34cb6b38 | 244 | |
46659a83 | 245 | dcn10_log_hubp_states(dc, log_ctx); |
a052a516 | 246 | |
7c91bd43 AK |
247 | DTN_INFO("DPP: IGAM format IGAM mode DGAM mode RGAM mode" |
248 | " GAMUT mode C11 C12 C13 C14 C21 C22 C23 C24 " | |
249 | "C31 C32 C33 C34\n"); | |
250 | for (i = 0; i < pool->pipe_count; i++) { | |
251 | struct dpp *dpp = pool->dpps[i]; | |
d02e0794 | 252 | struct dcn_dpp_state s = {0}; |
7c91bd43 AK |
253 | |
254 | dpp->funcs->dpp_read_state(dpp, &s); | |
255 | ||
d02e0794 NC |
256 | if (!s.is_enabled) |
257 | continue; | |
258 | ||
7c91bd43 | 259 | DTN_INFO("[%2d]: %11xh %-11s %-11s %-11s" |
7b265fd9 | 260 | "%8x %08xh %08xh %08xh %08xh %08xh %08xh", |
7c91bd43 AK |
261 | dpp->inst, |
262 | s.igam_input_format, | |
263 | (s.igam_lut_mode == 0) ? "BypassFixed" : | |
264 | ((s.igam_lut_mode == 1) ? "BypassFloat" : | |
265 | ((s.igam_lut_mode == 2) ? "RAM" : | |
266 | ((s.igam_lut_mode == 3) ? "RAM" : | |
267 | "Unknown"))), | |
268 | (s.dgam_lut_mode == 0) ? "Bypass" : | |
269 | ((s.dgam_lut_mode == 1) ? "sRGB" : | |
270 | ((s.dgam_lut_mode == 2) ? "Ycc" : | |
271 | ((s.dgam_lut_mode == 3) ? "RAM" : | |
272 | ((s.dgam_lut_mode == 4) ? "RAM" : | |
273 | "Unknown")))), | |
274 | (s.rgam_lut_mode == 0) ? "Bypass" : | |
275 | ((s.rgam_lut_mode == 1) ? "sRGB" : | |
276 | ((s.rgam_lut_mode == 2) ? "Ycc" : | |
277 | ((s.rgam_lut_mode == 3) ? "RAM" : | |
278 | ((s.rgam_lut_mode == 4) ? "RAM" : | |
279 | "Unknown")))), | |
280 | s.gamut_remap_mode, | |
281 | s.gamut_remap_c11_c12, | |
282 | s.gamut_remap_c13_c14, | |
283 | s.gamut_remap_c21_c22, | |
284 | s.gamut_remap_c23_c24, | |
285 | s.gamut_remap_c31_c32, | |
286 | s.gamut_remap_c33_c34); | |
287 | DTN_INFO("\n"); | |
288 | } | |
289 | DTN_INFO("\n"); | |
290 | ||
a052a516 | 291 | DTN_INFO("MPCC: OPP DPP MPCCBOT MODE ALPHA_MODE PREMULT OVERLAP_ONLY IDLE\n"); |
dfd01f29 | 292 | for (i = 0; i < pool->pipe_count; i++) { |
dfd01f29 DL |
293 | struct mpcc_state s = {0}; |
294 | ||
a052a516 | 295 | pool->mpc->funcs->read_mpcc_state(pool->mpc, i, &s); |
1ba2faf2 DL |
296 | if (s.opp_id != 0xf) |
297 | DTN_INFO("[%2d]: %2xh %2xh %6xh %4d %10d %7d %12d %4d\n", | |
298 | i, s.opp_id, s.dpp_id, s.bot_mpcc_id, | |
299 | s.mode, s.alpha_mode, s.pre_multiplied_alpha, s.overlap_only, | |
300 | s.idle); | |
dfd01f29 DL |
301 | } |
302 | DTN_INFO("\n"); | |
71395011 | 303 | |
01fe3e48 | 304 | DTN_INFO("OTG: v_bs v_be v_ss v_se vpol vmax vmin vmax_sel vmin_sel" |
a052a516 | 305 | " h_bs h_be h_ss h_se hpol htot vtot underflow\n"); |
214435ff | 306 | |
3be1406a | 307 | for (i = 0; i < pool->timing_generator_count; i++) { |
214435ff | 308 | struct timing_generator *tg = pool->timing_generators[i]; |
6f54d0b1 | 309 | struct dcn_otg_state s = {0}; |
214435ff | 310 | |
40e045a9 | 311 | optc1_read_otg_state(DCN10TG_FROM_TG(tg), &s); |
214435ff | 312 | |
6f54d0b1 LT |
313 | //only print if OTG master is enabled |
314 | if ((s.otg_enabled & 1) == 0) | |
315 | continue; | |
316 | ||
01fe3e48 | 317 | DTN_INFO("[%d]: %5d %5d %5d %5d %5d %5d %5d %9d %9d %5d %5d %5d" |
a052a516 | 318 | " %5d %5d %5d %5d %9d\n", |
3be1406a | 319 | tg->inst, |
214435ff CM |
320 | s.v_blank_start, |
321 | s.v_blank_end, | |
322 | s.v_sync_a_start, | |
323 | s.v_sync_a_end, | |
324 | s.v_sync_a_pol, | |
325 | s.v_total_max, | |
326 | s.v_total_min, | |
01fe3e48 AK |
327 | s.v_total_max_sel, |
328 | s.v_total_min_sel, | |
214435ff CM |
329 | s.h_blank_start, |
330 | s.h_blank_end, | |
331 | s.h_sync_a_start, | |
332 | s.h_sync_a_end, | |
333 | s.h_sync_a_pol, | |
334 | s.h_total, | |
335 | s.v_total, | |
336 | s.underflow_occurred_status); | |
a944744b NC |
337 | |
338 | // Clear underflow for debug purposes | |
339 | // We want to keep underflow sticky bit on for the longevity tests outside of test environment. | |
340 | // This function is called only from Windows or Diags test environment, hence it's safe to clear | |
341 | // it from here without affecting the original intent. | |
342 | tg->funcs->clear_optc_underflow(tg); | |
214435ff CM |
343 | } |
344 | DTN_INFO("\n"); | |
345 | ||
a4765463 DL |
346 | DTN_INFO("\nCALCULATED Clocks: dcfclk_khz:%d dcfclk_deep_sleep_khz:%d dispclk_khz:%d\n" |
347 | "dppclk_khz:%d max_supported_dppclk_khz:%d fclk_khz:%d socclk_khz:%d\n\n", | |
d578839c DL |
348 | dc->current_state->bw.dcn.clk.dcfclk_khz, |
349 | dc->current_state->bw.dcn.clk.dcfclk_deep_sleep_khz, | |
350 | dc->current_state->bw.dcn.clk.dispclk_khz, | |
351 | dc->current_state->bw.dcn.clk.dppclk_khz, | |
352 | dc->current_state->bw.dcn.clk.max_supported_dppclk_khz, | |
353 | dc->current_state->bw.dcn.clk.fclk_khz, | |
354 | dc->current_state->bw.dcn.clk.socclk_khz); | |
0a93dc7f | 355 | |
46659a83 | 356 | log_mpc_crc(dc, log_ctx); |
71395011 TC |
357 | |
358 | DTN_INFO_END(); | |
359 | } | |
2b13d7d3 | 360 | |
70ccab60 | 361 | static void enable_power_gating_plane( |
184debdb | 362 | struct dce_hwseq *hws, |
70ccab60 HW |
363 | bool enable) |
364 | { | |
70ccab60 HW |
365 | bool force_on = 1; /* disable power gating */ |
366 | ||
367 | if (enable) | |
368 | force_on = 0; | |
369 | ||
370 | /* DCHUBP0/1/2/3 */ | |
184debdb DL |
371 | REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, force_on); |
372 | REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, force_on); | |
373 | REG_UPDATE(DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, force_on); | |
374 | REG_UPDATE(DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, force_on); | |
70ccab60 HW |
375 | |
376 | /* DPP0/1/2/3 */ | |
184debdb DL |
377 | REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, force_on); |
378 | REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, force_on); | |
379 | REG_UPDATE(DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, force_on); | |
380 | REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on); | |
70ccab60 HW |
381 | } |
382 | ||
0a87425a TC |
383 | static void disable_vga( |
384 | struct dce_hwseq *hws) | |
385 | { | |
5e9a4f08 CZ |
386 | unsigned int in_vga1_mode = 0; |
387 | unsigned int in_vga2_mode = 0; | |
388 | unsigned int in_vga3_mode = 0; | |
389 | unsigned int in_vga4_mode = 0; | |
390 | ||
391 | REG_GET(D1VGA_CONTROL, D1VGA_MODE_ENABLE, &in_vga1_mode); | |
392 | REG_GET(D2VGA_CONTROL, D2VGA_MODE_ENABLE, &in_vga2_mode); | |
393 | REG_GET(D3VGA_CONTROL, D3VGA_MODE_ENABLE, &in_vga3_mode); | |
394 | REG_GET(D4VGA_CONTROL, D4VGA_MODE_ENABLE, &in_vga4_mode); | |
395 | ||
396 | if (in_vga1_mode == 0 && in_vga2_mode == 0 && | |
397 | in_vga3_mode == 0 && in_vga4_mode == 0) | |
e18d3086 EY |
398 | return; |
399 | ||
0a87425a | 400 | REG_WRITE(D1VGA_CONTROL, 0); |
5e9a4f08 CZ |
401 | REG_WRITE(D2VGA_CONTROL, 0); |
402 | REG_WRITE(D3VGA_CONTROL, 0); | |
403 | REG_WRITE(D4VGA_CONTROL, 0); | |
90e3103e BL |
404 | |
405 | /* HW Engineer's Notes: | |
406 | * During switch from vga->extended, if we set the VGA_TEST_ENABLE and | |
407 | * then hit the VGA_TEST_RENDER_START, then the DCHUBP timing gets updated correctly. | |
408 | * | |
409 | * Then vBIOS will have it poll for the VGA_TEST_RENDER_DONE and unset | |
410 | * VGA_TEST_ENABLE, to leave it in the same state as before. | |
411 | */ | |
412 | REG_UPDATE(VGA_TEST_CONTROL, VGA_TEST_ENABLE, 1); | |
413 | REG_UPDATE(VGA_TEST_CONTROL, VGA_TEST_RENDER_START, 1); | |
0a87425a TC |
414 | } |
415 | ||
70ccab60 | 416 | static void dpp_pg_control( |
184debdb | 417 | struct dce_hwseq *hws, |
70ccab60 HW |
418 | unsigned int dpp_inst, |
419 | bool power_on) | |
420 | { | |
70ccab60 HW |
421 | uint32_t power_gate = power_on ? 0 : 1; |
422 | uint32_t pwr_status = power_on ? 0 : 2; | |
423 | ||
184debdb | 424 | if (hws->ctx->dc->debug.disable_dpp_power_gate) |
70ccab60 | 425 | return; |
7f93c1de CL |
426 | if (REG(DOMAIN1_PG_CONFIG) == 0) |
427 | return; | |
70ccab60 HW |
428 | |
429 | switch (dpp_inst) { | |
430 | case 0: /* DPP0 */ | |
184debdb | 431 | REG_UPDATE(DOMAIN1_PG_CONFIG, |
70ccab60 HW |
432 | DOMAIN1_POWER_GATE, power_gate); |
433 | ||
184debdb | 434 | REG_WAIT(DOMAIN1_PG_STATUS, |
8a5d8245 TC |
435 | DOMAIN1_PGFSM_PWR_STATUS, pwr_status, |
436 | 1, 1000); | |
70ccab60 HW |
437 | break; |
438 | case 1: /* DPP1 */ | |
184debdb | 439 | REG_UPDATE(DOMAIN3_PG_CONFIG, |
70ccab60 HW |
440 | DOMAIN3_POWER_GATE, power_gate); |
441 | ||
184debdb | 442 | REG_WAIT(DOMAIN3_PG_STATUS, |
8a5d8245 TC |
443 | DOMAIN3_PGFSM_PWR_STATUS, pwr_status, |
444 | 1, 1000); | |
70ccab60 HW |
445 | break; |
446 | case 2: /* DPP2 */ | |
184debdb | 447 | REG_UPDATE(DOMAIN5_PG_CONFIG, |
70ccab60 HW |
448 | DOMAIN5_POWER_GATE, power_gate); |
449 | ||
184debdb | 450 | REG_WAIT(DOMAIN5_PG_STATUS, |
8a5d8245 TC |
451 | DOMAIN5_PGFSM_PWR_STATUS, pwr_status, |
452 | 1, 1000); | |
70ccab60 HW |
453 | break; |
454 | case 3: /* DPP3 */ | |
184debdb | 455 | REG_UPDATE(DOMAIN7_PG_CONFIG, |
70ccab60 HW |
456 | DOMAIN7_POWER_GATE, power_gate); |
457 | ||
184debdb | 458 | REG_WAIT(DOMAIN7_PG_STATUS, |
8a5d8245 TC |
459 | DOMAIN7_PGFSM_PWR_STATUS, pwr_status, |
460 | 1, 1000); | |
70ccab60 HW |
461 | break; |
462 | default: | |
463 | BREAK_TO_DEBUGGER(); | |
464 | break; | |
465 | } | |
466 | } | |
467 | ||
468 | static void hubp_pg_control( | |
184debdb | 469 | struct dce_hwseq *hws, |
70ccab60 HW |
470 | unsigned int hubp_inst, |
471 | bool power_on) | |
472 | { | |
70ccab60 HW |
473 | uint32_t power_gate = power_on ? 0 : 1; |
474 | uint32_t pwr_status = power_on ? 0 : 2; | |
475 | ||
184debdb | 476 | if (hws->ctx->dc->debug.disable_hubp_power_gate) |
70ccab60 | 477 | return; |
7f93c1de CL |
478 | if (REG(DOMAIN0_PG_CONFIG) == 0) |
479 | return; | |
70ccab60 HW |
480 | |
481 | switch (hubp_inst) { | |
482 | case 0: /* DCHUBP0 */ | |
184debdb | 483 | REG_UPDATE(DOMAIN0_PG_CONFIG, |
70ccab60 HW |
484 | DOMAIN0_POWER_GATE, power_gate); |
485 | ||
184debdb | 486 | REG_WAIT(DOMAIN0_PG_STATUS, |
8a5d8245 TC |
487 | DOMAIN0_PGFSM_PWR_STATUS, pwr_status, |
488 | 1, 1000); | |
70ccab60 HW |
489 | break; |
490 | case 1: /* DCHUBP1 */ | |
184debdb | 491 | REG_UPDATE(DOMAIN2_PG_CONFIG, |
70ccab60 HW |
492 | DOMAIN2_POWER_GATE, power_gate); |
493 | ||
184debdb | 494 | REG_WAIT(DOMAIN2_PG_STATUS, |
8a5d8245 TC |
495 | DOMAIN2_PGFSM_PWR_STATUS, pwr_status, |
496 | 1, 1000); | |
70ccab60 HW |
497 | break; |
498 | case 2: /* DCHUBP2 */ | |
184debdb | 499 | REG_UPDATE(DOMAIN4_PG_CONFIG, |
70ccab60 HW |
500 | DOMAIN4_POWER_GATE, power_gate); |
501 | ||
184debdb | 502 | REG_WAIT(DOMAIN4_PG_STATUS, |
8a5d8245 TC |
503 | DOMAIN4_PGFSM_PWR_STATUS, pwr_status, |
504 | 1, 1000); | |
70ccab60 HW |
505 | break; |
506 | case 3: /* DCHUBP3 */ | |
184debdb | 507 | REG_UPDATE(DOMAIN6_PG_CONFIG, |
70ccab60 HW |
508 | DOMAIN6_POWER_GATE, power_gate); |
509 | ||
184debdb | 510 | REG_WAIT(DOMAIN6_PG_STATUS, |
8a5d8245 TC |
511 | DOMAIN6_PGFSM_PWR_STATUS, pwr_status, |
512 | 1, 1000); | |
70ccab60 HW |
513 | break; |
514 | default: | |
515 | BREAK_TO_DEBUGGER(); | |
516 | break; | |
517 | } | |
518 | } | |
519 | ||
520 | static void power_on_plane( | |
184debdb | 521 | struct dce_hwseq *hws, |
cfe4645e | 522 | int plane_id) |
70ccab60 | 523 | { |
5d4b05dd | 524 | DC_LOGGER_INIT(hws->ctx->logger); |
5df921d4 KC |
525 | if (REG(DC_IP_REQUEST_CNTL)) { |
526 | REG_SET(DC_IP_REQUEST_CNTL, 0, | |
527 | IP_REQUEST_EN, 1); | |
528 | dpp_pg_control(hws, plane_id, true); | |
529 | hubp_pg_control(hws, plane_id, true); | |
530 | REG_SET(DC_IP_REQUEST_CNTL, 0, | |
531 | IP_REQUEST_EN, 0); | |
1296423b | 532 | DC_LOG_DEBUG( |
5df921d4 KC |
533 | "Un-gated front end for pipe %d\n", plane_id); |
534 | } | |
70ccab60 HW |
535 | } |
536 | ||
41f97c07 HW |
537 | static void undo_DEGVIDCN10_253_wa(struct dc *dc) |
538 | { | |
539 | struct dce_hwseq *hws = dc->hwseq; | |
8feabd03 | 540 | struct hubp *hubp = dc->res_pool->hubps[0]; |
c9bb686b | 541 | |
7f914a62 | 542 | if (!hws->wa_state.DEGVIDCN10_253_applied) |
c9bb686b | 543 | return; |
41f97c07 | 544 | |
8feabd03 | 545 | hubp->funcs->set_blank(hubp, true); |
41f97c07 HW |
546 | |
547 | REG_SET(DC_IP_REQUEST_CNTL, 0, | |
548 | IP_REQUEST_EN, 1); | |
549 | ||
550 | hubp_pg_control(hws, 0, false); | |
551 | REG_SET(DC_IP_REQUEST_CNTL, 0, | |
552 | IP_REQUEST_EN, 0); | |
7f914a62 YS |
553 | |
554 | hws->wa_state.DEGVIDCN10_253_applied = false; | |
41f97c07 HW |
555 | } |
556 | ||
41f97c07 HW |
557 | static void apply_DEGVIDCN10_253_wa(struct dc *dc) |
558 | { | |
559 | struct dce_hwseq *hws = dc->hwseq; | |
8feabd03 | 560 | struct hubp *hubp = dc->res_pool->hubps[0]; |
7f914a62 | 561 | int i; |
41f97c07 | 562 | |
6bf52028 HW |
563 | if (dc->debug.disable_stutter) |
564 | return; | |
565 | ||
7f914a62 YS |
566 | if (!hws->wa.DEGVIDCN10_253) |
567 | return; | |
568 | ||
569 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | |
570 | if (!dc->res_pool->hubps[i]->power_gated) | |
571 | return; | |
572 | } | |
573 | ||
574 | /* all pipe power gated, apply work around to enable stutter. */ | |
575 | ||
41f97c07 HW |
576 | REG_SET(DC_IP_REQUEST_CNTL, 0, |
577 | IP_REQUEST_EN, 1); | |
578 | ||
579 | hubp_pg_control(hws, 0, true); | |
580 | REG_SET(DC_IP_REQUEST_CNTL, 0, | |
581 | IP_REQUEST_EN, 0); | |
582 | ||
8feabd03 | 583 | hubp->funcs->set_hubp_blank_en(hubp, false); |
7f914a62 | 584 | hws->wa_state.DEGVIDCN10_253_applied = true; |
41f97c07 HW |
585 | } |
586 | ||
fb3466a4 | 587 | static void bios_golden_init(struct dc *dc) |
70ccab60 HW |
588 | { |
589 | struct dc_bios *bp = dc->ctx->dc_bios; | |
590 | int i; | |
591 | ||
592 | /* initialize dcn global */ | |
593 | bp->funcs->enable_disp_power_gating(bp, | |
594 | CONTROLLER_ID_D0, ASIC_PIPE_INIT); | |
595 | ||
596 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | |
597 | /* initialize dcn per pipe */ | |
598 | bp->funcs->enable_disp_power_gating(bp, | |
599 | CONTROLLER_ID_D0 + i, ASIC_PIPE_DISABLE); | |
600 | } | |
601 | } | |
602 | ||
5cc2687c YS |
603 | static void false_optc_underflow_wa( |
604 | struct dc *dc, | |
605 | const struct dc_stream_state *stream, | |
606 | struct timing_generator *tg) | |
607 | { | |
608 | int i; | |
609 | bool underflow; | |
610 | ||
611 | if (!dc->hwseq->wa.false_optc_underflow) | |
612 | return; | |
613 | ||
614 | underflow = tg->funcs->is_optc_underflow_occurred(tg); | |
615 | ||
616 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | |
617 | struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; | |
618 | ||
619 | if (old_pipe_ctx->stream != stream) | |
620 | continue; | |
621 | ||
622 | dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, old_pipe_ctx); | |
623 | } | |
624 | ||
625 | tg->funcs->set_blank_data_double_buffer(tg, true); | |
626 | ||
627 | if (tg->funcs->is_optc_underflow_occurred(tg) && !underflow) | |
628 | tg->funcs->clear_optc_underflow(tg); | |
629 | } | |
630 | ||
3158223e | 631 | static enum dc_status dcn10_enable_stream_timing( |
70ccab60 | 632 | struct pipe_ctx *pipe_ctx, |
608ac7bb | 633 | struct dc_state *context, |
fb3466a4 | 634 | struct dc *dc) |
70ccab60 | 635 | { |
0971c40e | 636 | struct dc_stream_state *stream = pipe_ctx->stream; |
70ccab60 HW |
637 | enum dc_color_space color_space; |
638 | struct tg_color black_color = {0}; | |
98e6436d AK |
639 | struct drr_params params = {0}; |
640 | unsigned int event_triggers = 0; | |
70ccab60 | 641 | |
70ccab60 HW |
642 | /* by upper caller loop, pipe0 is parent pipe and be called first. |
643 | * back end is set up by for pipe0. Other children pipe share back end | |
644 | * with pipe 0. No program is needed. | |
645 | */ | |
646 | if (pipe_ctx->top_pipe != NULL) | |
647 | return DC_OK; | |
648 | ||
649 | /* TODO check if timing_changed, disable stream if timing changed */ | |
650 | ||
651 | /* HW program guide assume display already disable | |
652 | * by unplug sequence. OTG assume stop. | |
653 | */ | |
6b670fa9 | 654 | pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, true); |
70ccab60 HW |
655 | |
656 | if (false == pipe_ctx->clock_source->funcs->program_pix_clk( | |
657 | pipe_ctx->clock_source, | |
10688217 | 658 | &pipe_ctx->stream_res.pix_clk_params, |
70ccab60 HW |
659 | &pipe_ctx->pll_settings)) { |
660 | BREAK_TO_DEBUGGER(); | |
661 | return DC_ERROR_UNEXPECTED; | |
662 | } | |
6b670fa9 HW |
663 | pipe_ctx->stream_res.tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; |
664 | pipe_ctx->stream_res.tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; | |
665 | pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset; | |
666 | pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width; | |
70ccab60 | 667 | |
6b670fa9 | 668 | pipe_ctx->stream_res.tg->dlg_otg_param.signal = pipe_ctx->stream->signal; |
70ccab60 | 669 | |
6b670fa9 HW |
670 | pipe_ctx->stream_res.tg->funcs->program_timing( |
671 | pipe_ctx->stream_res.tg, | |
4fa086b9 | 672 | &stream->timing, |
70ccab60 HW |
673 | true); |
674 | ||
70ccab60 HW |
675 | #if 0 /* move to after enable_crtc */ |
676 | /* TODO: OPP FMT, ABM. etc. should be done here. */ | |
677 | /* or FPGA now. instance 0 only. TODO: move to opp.c */ | |
678 | ||
6b670fa9 | 679 | inst_offset = reg_offsets[pipe_ctx->stream_res.tg->inst].fmt; |
70ccab60 | 680 | |
a6a6cb34 HW |
681 | pipe_ctx->stream_res.opp->funcs->opp_program_fmt( |
682 | pipe_ctx->stream_res.opp, | |
70ccab60 HW |
683 | &stream->bit_depth_params, |
684 | &stream->clamping); | |
685 | #endif | |
686 | /* program otg blank color */ | |
4fa086b9 | 687 | color_space = stream->output_color_space; |
70ccab60 | 688 | color_space_to_black_color(dc, color_space, &black_color); |
70ccab60 | 689 | |
b51adc77 YHL |
690 | if (pipe_ctx->stream_res.tg->funcs->set_blank_color) |
691 | pipe_ctx->stream_res.tg->funcs->set_blank_color( | |
692 | pipe_ctx->stream_res.tg, | |
693 | &black_color); | |
694 | ||
695 | if (pipe_ctx->stream_res.tg->funcs->is_blanked && | |
696 | !pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg)) { | |
5cc2687c YS |
697 | pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true); |
698 | hwss_wait_for_blank_complete(pipe_ctx->stream_res.tg); | |
699 | false_optc_underflow_wa(dc, pipe_ctx->stream, pipe_ctx->stream_res.tg); | |
700 | } | |
70ccab60 HW |
701 | |
702 | /* VTG is within DCHUB command block. DCFCLK is always on */ | |
6b670fa9 | 703 | if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc(pipe_ctx->stream_res.tg)) { |
70ccab60 HW |
704 | BREAK_TO_DEBUGGER(); |
705 | return DC_ERROR_UNEXPECTED; | |
706 | } | |
707 | ||
98e6436d AK |
708 | params.vertical_total_min = stream->adjust.v_total_min; |
709 | params.vertical_total_max = stream->adjust.v_total_max; | |
710 | if (pipe_ctx->stream_res.tg->funcs->set_drr) | |
711 | pipe_ctx->stream_res.tg->funcs->set_drr( | |
712 | pipe_ctx->stream_res.tg, ¶ms); | |
713 | ||
714 | // DRR should set trigger event to monitor surface update event | |
715 | if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0) | |
716 | event_triggers = 0x80; | |
717 | if (pipe_ctx->stream_res.tg->funcs->set_static_screen_control) | |
718 | pipe_ctx->stream_res.tg->funcs->set_static_screen_control( | |
719 | pipe_ctx->stream_res.tg, event_triggers); | |
720 | ||
70ccab60 HW |
721 | /* TODO program crtc source select for non-virtual signal*/ |
722 | /* TODO program FMT */ | |
723 | /* TODO setup link_enc */ | |
724 | /* TODO set stream attributes */ | |
725 | /* TODO program audio */ | |
726 | /* TODO enable stream if timing changed */ | |
727 | /* TODO unblank stream if DP */ | |
728 | ||
729 | return DC_OK; | |
730 | } | |
731 | ||
732 | static void reset_back_end_for_pipe( | |
fb3466a4 | 733 | struct dc *dc, |
70ccab60 | 734 | struct pipe_ctx *pipe_ctx, |
608ac7bb | 735 | struct dc_state *context) |
70ccab60 HW |
736 | { |
737 | int i; | |
5d4b05dd | 738 | DC_LOGGER_INIT(dc->ctx->logger); |
8e9c4c8c | 739 | if (pipe_ctx->stream_res.stream_enc == NULL) { |
70ccab60 HW |
740 | pipe_ctx->stream = NULL; |
741 | return; | |
742 | } | |
743 | ||
d050f8ed HW |
744 | if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { |
745 | /* DPMS may already disable */ | |
746 | if (!pipe_ctx->stream->dpms_off) | |
747 | core_link_disable_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE); | |
ea7ea2a8 | 748 | else if (pipe_ctx->stream_res.audio) { |
1a05873f | 749 | dc->hwss.disable_audio_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE); |
ea7ea2a8 EY |
750 | } |
751 | ||
d050f8ed | 752 | } |
70ccab60 HW |
753 | |
754 | /* by upper caller loop, parent pipe: pipe0, will be reset last. | |
755 | * back end share by all pipes and will be disable only when disable | |
756 | * parent pipe. | |
757 | */ | |
758 | if (pipe_ctx->top_pipe == NULL) { | |
6b670fa9 | 759 | pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg); |
70ccab60 | 760 | |
6b670fa9 | 761 | pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false); |
70ccab60 HW |
762 | } |
763 | ||
70ccab60 | 764 | for (i = 0; i < dc->res_pool->pipe_count; i++) |
608ac7bb | 765 | if (&dc->current_state->res_ctx.pipe_ctx[i] == pipe_ctx) |
70ccab60 HW |
766 | break; |
767 | ||
768 | if (i == dc->res_pool->pipe_count) | |
769 | return; | |
770 | ||
771 | pipe_ctx->stream = NULL; | |
1296423b | 772 | DC_LOG_DEBUG("Reset back end for pipe %d, tg:%d\n", |
6b670fa9 | 773 | pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst); |
70ccab60 HW |
774 | } |
775 | ||
3ba43a59 CL |
776 | static bool dcn10_hw_wa_force_recovery(struct dc *dc) |
777 | { | |
778 | struct hubp *hubp ; | |
779 | unsigned int i; | |
780 | bool need_recover = true; | |
781 | ||
782 | if (!dc->debug.recovery_enabled) | |
783 | return false; | |
784 | ||
785 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | |
786 | struct pipe_ctx *pipe_ctx = | |
787 | &dc->current_state->res_ctx.pipe_ctx[i]; | |
788 | if (pipe_ctx != NULL) { | |
789 | hubp = pipe_ctx->plane_res.hubp; | |
95022795 | 790 | if (hubp != NULL && hubp->funcs->hubp_get_underflow_status) { |
3ba43a59 CL |
791 | if (hubp->funcs->hubp_get_underflow_status(hubp) != 0) { |
792 | /* one pipe underflow, we will reset all the pipes*/ | |
793 | need_recover = true; | |
794 | } | |
795 | } | |
796 | } | |
797 | } | |
798 | if (!need_recover) | |
799 | return false; | |
800 | /* | |
801 | DCHUBP_CNTL:HUBP_BLANK_EN=1 | |
802 | DCHUBBUB_SOFT_RESET:DCHUBBUB_GLOBAL_SOFT_RESET=1 | |
803 | DCHUBP_CNTL:HUBP_DISABLE=1 | |
804 | DCHUBP_CNTL:HUBP_DISABLE=0 | |
805 | DCHUBBUB_SOFT_RESET:DCHUBBUB_GLOBAL_SOFT_RESET=0 | |
806 | DCSURF_PRIMARY_SURFACE_ADDRESS | |
807 | DCHUBP_CNTL:HUBP_BLANK_EN=0 | |
808 | */ | |
809 | ||
810 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | |
811 | struct pipe_ctx *pipe_ctx = | |
812 | &dc->current_state->res_ctx.pipe_ctx[i]; | |
813 | if (pipe_ctx != NULL) { | |
814 | hubp = pipe_ctx->plane_res.hubp; | |
815 | /*DCHUBP_CNTL:HUBP_BLANK_EN=1*/ | |
95022795 | 816 | if (hubp != NULL && hubp->funcs->set_hubp_blank_en) |
3ba43a59 CL |
817 | hubp->funcs->set_hubp_blank_en(hubp, true); |
818 | } | |
819 | } | |
820 | /*DCHUBBUB_SOFT_RESET:DCHUBBUB_GLOBAL_SOFT_RESET=1*/ | |
821 | hubbub1_soft_reset(dc->res_pool->hubbub, true); | |
822 | ||
823 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | |
824 | struct pipe_ctx *pipe_ctx = | |
825 | &dc->current_state->res_ctx.pipe_ctx[i]; | |
826 | if (pipe_ctx != NULL) { | |
827 | hubp = pipe_ctx->plane_res.hubp; | |
828 | /*DCHUBP_CNTL:HUBP_DISABLE=1*/ | |
95022795 | 829 | if (hubp != NULL && hubp->funcs->hubp_disable_control) |
3ba43a59 CL |
830 | hubp->funcs->hubp_disable_control(hubp, true); |
831 | } | |
832 | } | |
833 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | |
834 | struct pipe_ctx *pipe_ctx = | |
835 | &dc->current_state->res_ctx.pipe_ctx[i]; | |
836 | if (pipe_ctx != NULL) { | |
837 | hubp = pipe_ctx->plane_res.hubp; | |
838 | /*DCHUBP_CNTL:HUBP_DISABLE=0*/ | |
95022795 | 839 | if (hubp != NULL && hubp->funcs->hubp_disable_control) |
3ba43a59 CL |
840 | hubp->funcs->hubp_disable_control(hubp, true); |
841 | } | |
842 | } | |
843 | /*DCHUBBUB_SOFT_RESET:DCHUBBUB_GLOBAL_SOFT_RESET=0*/ | |
844 | hubbub1_soft_reset(dc->res_pool->hubbub, false); | |
845 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | |
846 | struct pipe_ctx *pipe_ctx = | |
847 | &dc->current_state->res_ctx.pipe_ctx[i]; | |
848 | if (pipe_ctx != NULL) { | |
849 | hubp = pipe_ctx->plane_res.hubp; | |
850 | /*DCHUBP_CNTL:HUBP_BLANK_EN=0*/ | |
95022795 | 851 | if (hubp != NULL && hubp->funcs->set_hubp_blank_en) |
3ba43a59 CL |
852 | hubp->funcs->set_hubp_blank_en(hubp, true); |
853 | } | |
854 | } | |
855 | return true; | |
856 | ||
857 | } | |
858 | ||
859 | ||
c2437b1f | 860 | void dcn10_verify_allow_pstate_change_high(struct dc *dc) |
ea00f297 YHL |
861 | { |
862 | static bool should_log_hw_state; /* prevent hw state log by default */ | |
863 | ||
e70fe3b1 | 864 | if (!hubbub1_verify_allow_pstate_change_high(dc->res_pool->hubbub)) { |
ea00f297 | 865 | if (should_log_hw_state) { |
46659a83 | 866 | dcn10_log_hw_state(dc, NULL); |
ea00f297 | 867 | } |
ea00f297 | 868 | BREAK_TO_DEBUGGER(); |
3ba43a59 CL |
869 | if (dcn10_hw_wa_force_recovery(dc)) { |
870 | /*check again*/ | |
871 | if (!hubbub1_verify_allow_pstate_change_high(dc->res_pool->hubbub)) | |
872 | BREAK_TO_DEBUGGER(); | |
873 | } | |
ea00f297 YHL |
874 | } |
875 | } | |
876 | ||
a74b2734 | 877 | /* trigger HW to start disconnect plane from stream on the next vsync */ |
6b8e1eb7 | 878 | void hwss1_plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx) |
70ccab60 | 879 | { |
e07f541f YS |
880 | struct hubp *hubp = pipe_ctx->plane_res.hubp; |
881 | int dpp_id = pipe_ctx->plane_res.dpp->inst; | |
cc408d72 | 882 | struct mpc *mpc = dc->res_pool->mpc; |
feb4a3cd EB |
883 | struct mpc_tree *mpc_tree_params; |
884 | struct mpcc *mpcc_to_remove = NULL; | |
365acbaf | 885 | struct output_pixel_processor *opp = pipe_ctx->stream_res.opp; |
cc408d72 | 886 | |
365acbaf YS |
887 | mpc_tree_params = &(opp->mpc_tree_params); |
888 | mpcc_to_remove = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, dpp_id); | |
feb4a3cd | 889 | |
a74b2734 | 890 | /*Already reset*/ |
365acbaf | 891 | if (mpcc_to_remove == NULL) |
a74b2734 | 892 | return; |
70ccab60 | 893 | |
feb4a3cd | 894 | mpc->funcs->remove_mpcc(mpc, mpc_tree_params, mpcc_to_remove); |
7f93c1de CL |
895 | if (opp != NULL) |
896 | opp->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true; | |
e6c258cb | 897 | |
82c026d1 AJ |
898 | dc->optimized_required = true; |
899 | ||
e6c258cb YS |
900 | if (hubp->funcs->hubp_disconnect) |
901 | hubp->funcs->hubp_disconnect(hubp); | |
902 | ||
fb3466a4 | 903 | if (dc->debug.sanity_checks) |
ea00f297 | 904 | dcn10_verify_allow_pstate_change_high(dc); |
d65359d5 TC |
905 | } |
906 | ||
e07f541f | 907 | static void plane_atomic_power_down(struct dc *dc, struct pipe_ctx *pipe_ctx) |
a74b2734 TC |
908 | { |
909 | struct dce_hwseq *hws = dc->hwseq; | |
e07f541f | 910 | struct dpp *dpp = pipe_ctx->plane_res.dpp; |
5d4b05dd | 911 | DC_LOGGER_INIT(dc->ctx->logger); |
a74b2734 | 912 | |
e6c258cb YS |
913 | if (REG(DC_IP_REQUEST_CNTL)) { |
914 | REG_SET(DC_IP_REQUEST_CNTL, 0, | |
915 | IP_REQUEST_EN, 1); | |
e07f541f YS |
916 | dpp_pg_control(hws, dpp->inst, false); |
917 | hubp_pg_control(hws, pipe_ctx->plane_res.hubp->inst, false); | |
e6c258cb YS |
918 | dpp->funcs->dpp_reset(dpp); |
919 | REG_SET(DC_IP_REQUEST_CNTL, 0, | |
920 | IP_REQUEST_EN, 0); | |
1296423b | 921 | DC_LOG_DEBUG( |
e07f541f | 922 | "Power gated front end %d\n", pipe_ctx->pipe_idx); |
e6c258cb YS |
923 | } |
924 | } | |
a74b2734 | 925 | |
7f914a62 YS |
926 | /* disable HW used by plane. |
927 | * note: cannot disable until disconnect is complete | |
928 | */ | |
929 | static void plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx) | |
e6c258cb | 930 | { |
e07f541f | 931 | struct hubp *hubp = pipe_ctx->plane_res.hubp; |
f8e413bf | 932 | struct dpp *dpp = pipe_ctx->plane_res.dpp; |
7f914a62 | 933 | int opp_id = hubp->opp_id; |
a74b2734 | 934 | |
1ccda80f | 935 | dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe_ctx); |
a74b2734 | 936 | |
c8242b98 YS |
937 | hubp->funcs->hubp_clk_cntl(hubp, false); |
938 | ||
f8e413bf | 939 | dpp->funcs->dpp_dppclk_control(dpp, false, false); |
a74b2734 | 940 | |
2e9d6a57 | 941 | if (opp_id != 0xf && pipe_ctx->stream_res.opp->mpc_tree_params.opp_list == NULL) |
be2f449a YS |
942 | pipe_ctx->stream_res.opp->funcs->opp_pipe_clock_control( |
943 | pipe_ctx->stream_res.opp, | |
944 | false); | |
e6c258cb | 945 | |
7f914a62 | 946 | hubp->power_gated = true; |
82c026d1 | 947 | dc->optimized_required = false; /* We're powering off, no need to optimize */ |
a74b2734 | 948 | |
e07f541f | 949 | plane_atomic_power_down(dc, pipe_ctx); |
1ccda80f YS |
950 | |
951 | pipe_ctx->stream = NULL; | |
952 | memset(&pipe_ctx->stream_res, 0, sizeof(pipe_ctx->stream_res)); | |
953 | memset(&pipe_ctx->plane_res, 0, sizeof(pipe_ctx->plane_res)); | |
954 | pipe_ctx->top_pipe = NULL; | |
955 | pipe_ctx->bottom_pipe = NULL; | |
956 | pipe_ctx->plane_state = NULL; | |
7f914a62 YS |
957 | } |
958 | ||
959 | static void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx) | |
960 | { | |
5d4b05dd | 961 | DC_LOGGER_INIT(dc->ctx->logger); |
1296423b | 962 | |
24a30505 | 963 | if (!pipe_ctx->plane_res.hubp || pipe_ctx->plane_res.hubp->power_gated) |
7f914a62 YS |
964 | return; |
965 | ||
966 | plane_atomic_disable(dc, pipe_ctx); | |
967 | ||
968 | apply_DEGVIDCN10_253_wa(dc); | |
a74b2734 | 969 | |
1296423b | 970 | DC_LOG_DC("Power down front end %d\n", |
7f914a62 | 971 | pipe_ctx->pipe_idx); |
a74b2734 TC |
972 | } |
973 | ||
7a5086a7 YS |
974 | static void dcn10_init_hw(struct dc *dc) |
975 | { | |
4e1c1875 | 976 | int i; |
7a5086a7 YS |
977 | struct abm *abm = dc->res_pool->abm; |
978 | struct dmcu *dmcu = dc->res_pool->dmcu; | |
979 | struct dce_hwseq *hws = dc->hwseq; | |
0af4096d YS |
980 | struct dc_bios *dcb = dc->ctx->dc_bios; |
981 | struct dc_state *context = dc->current_state; | |
7a5086a7 YS |
982 | |
983 | if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { | |
984 | REG_WRITE(REFCLK_CNTL, 0); | |
985 | REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1); | |
986 | REG_WRITE(DIO_MEM_PWR_CTRL, 0); | |
987 | ||
988 | if (!dc->debug.disable_clock_gate) { | |
989 | /* enable all DCN clock gating */ | |
990 | REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); | |
991 | ||
992 | REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0); | |
993 | ||
994 | REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0); | |
995 | } | |
996 | ||
997 | enable_power_gating_plane(dc->hwseq, true); | |
529c690b | 998 | } else { |
7a5086a7 | 999 | |
529c690b | 1000 | if (!dcb->funcs->is_accelerated_mode(dcb)) { |
ceb9831d YS |
1001 | bool allow_self_fresh_force_enable = |
1002 | hububu1_is_allow_self_refresh_enabled(dc->res_pool->hubbub); | |
1003 | ||
529c690b | 1004 | bios_golden_init(dc); |
ceb9831d YS |
1005 | |
1006 | /* WA for making DF sleep when idle after resume from S0i3. | |
1007 | * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE is set to 1 by | |
1008 | * command table, if DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 0 | |
1009 | * before calling command table and it changed to 1 after, | |
1010 | * it should be set back to 0. | |
1011 | */ | |
1012 | if (allow_self_fresh_force_enable == false && | |
1013 | hububu1_is_allow_self_refresh_enabled(dc->res_pool->hubbub)) | |
1014 | hubbub1_disable_allow_self_refresh(dc->res_pool->hubbub); | |
1015 | ||
529c690b EB |
1016 | disable_vga(dc->hwseq); |
1017 | } | |
7a5086a7 | 1018 | |
529c690b EB |
1019 | for (i = 0; i < dc->link_count; i++) { |
1020 | /* Power up AND update implementation according to the | |
1021 | * required signal (which may be different from the | |
1022 | * default signal on connector). | |
1023 | */ | |
1024 | struct dc_link *link = dc->links[i]; | |
7a5086a7 | 1025 | |
529c690b EB |
1026 | if (link->link_enc->connector.id == CONNECTOR_ID_EDP) |
1027 | dc->hwss.edp_power_control(link, true); | |
069d418f | 1028 | |
529c690b EB |
1029 | link->link_enc->funcs->hw_init(link->link_enc); |
1030 | } | |
7a5086a7 YS |
1031 | } |
1032 | ||
1033 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | |
7a5086a7 YS |
1034 | struct timing_generator *tg = dc->res_pool->timing_generators[i]; |
1035 | ||
0af4096d YS |
1036 | if (tg->funcs->is_tg_enabled(tg)) |
1037 | tg->funcs->lock(tg); | |
1038 | } | |
7a5086a7 | 1039 | |
0af4096d YS |
1040 | /* Blank controller using driver code instead of |
1041 | * command table. | |
1042 | */ | |
1043 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | |
1044 | struct timing_generator *tg = dc->res_pool->timing_generators[i]; | |
1045 | ||
1046 | if (tg->funcs->is_tg_enabled(tg)) { | |
1047 | tg->funcs->set_blank(tg, true); | |
1048 | hwss_wait_for_blank_complete(tg); | |
1049 | } | |
1050 | } | |
7a5086a7 | 1051 | |
4e1c1875 EB |
1052 | /* Reset all MPCC muxes */ |
1053 | dc->res_pool->mpc->funcs->mpc_init(dc->res_pool->mpc); | |
feb4a3cd | 1054 | |
0d8be241 | 1055 | for (i = 0; i < dc->res_pool->timing_generator_count; i++) { |
0af4096d YS |
1056 | struct timing_generator *tg = dc->res_pool->timing_generators[i]; |
1057 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; | |
621fd3e3 | 1058 | struct hubp *hubp = dc->res_pool->hubps[i]; |
e07f541f | 1059 | struct dpp *dpp = dc->res_pool->dpps[i]; |
621fd3e3 | 1060 | |
0af4096d YS |
1061 | pipe_ctx->stream_res.tg = tg; |
1062 | pipe_ctx->pipe_idx = i; | |
621fd3e3 AJ |
1063 | |
1064 | pipe_ctx->plane_res.hubp = hubp; | |
e07f541f YS |
1065 | pipe_ctx->plane_res.dpp = dpp; |
1066 | pipe_ctx->plane_res.mpcc_inst = dpp->inst; | |
1067 | hubp->mpcc_id = dpp->inst; | |
4e1c1875 | 1068 | hubp->opp_id = 0xf; |
621fd3e3 | 1069 | hubp->power_gated = false; |
0af4096d | 1070 | |
f23d5584 EB |
1071 | dc->res_pool->opps[i]->mpc_tree_params.opp_id = dc->res_pool->opps[i]->inst; |
1072 | dc->res_pool->opps[i]->mpc_tree_params.opp_list = NULL; | |
e07f541f | 1073 | dc->res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true; |
cc55b1f5 | 1074 | pipe_ctx->stream_res.opp = dc->res_pool->opps[i]; |
1ccda80f | 1075 | |
6b8e1eb7 | 1076 | hwss1_plane_atomic_disconnect(dc, pipe_ctx); |
0af4096d YS |
1077 | } |
1078 | ||
1079 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | |
1080 | struct timing_generator *tg = dc->res_pool->timing_generators[i]; | |
1081 | ||
1082 | if (tg->funcs->is_tg_enabled(tg)) | |
1083 | tg->funcs->unlock(tg); | |
1084 | } | |
1085 | ||
1086 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | |
1087 | struct timing_generator *tg = dc->res_pool->timing_generators[i]; | |
1088 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; | |
1089 | ||
7f914a62 | 1090 | dcn10_disable_plane(dc, pipe_ctx); |
073a45e8 | 1091 | |
0af4096d YS |
1092 | pipe_ctx->stream_res.tg = NULL; |
1093 | pipe_ctx->plane_res.hubp = NULL; | |
1094 | ||
073a45e8 | 1095 | tg->funcs->tg_init(tg); |
7a5086a7 YS |
1096 | } |
1097 | ||
529c690b EB |
1098 | /* end of FPGA. Below if real ASIC */ |
1099 | if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) | |
1100 | return; | |
1101 | ||
7a5086a7 YS |
1102 | for (i = 0; i < dc->res_pool->audio_count; i++) { |
1103 | struct audio *audio = dc->res_pool->audios[i]; | |
1104 | ||
1105 | audio->funcs->hw_init(audio); | |
1106 | } | |
1107 | ||
1108 | if (abm != NULL) { | |
1109 | abm->funcs->init_backlight(abm); | |
1110 | abm->funcs->abm_init(abm); | |
1111 | } | |
1112 | ||
1113 | if (dmcu != NULL) | |
1114 | dmcu->funcs->dmcu_init(dmcu); | |
1115 | ||
1116 | /* power AFMT HDMI memory TODO: may move to dis/en output save power*/ | |
1117 | REG_WRITE(DIO_MEM_PWR_CTRL, 0); | |
1118 | ||
1119 | if (!dc->debug.disable_clock_gate) { | |
1120 | /* enable all DCN clock gating */ | |
1121 | REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); | |
1122 | ||
1123 | REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0); | |
1124 | ||
1125 | REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0); | |
1126 | } | |
1127 | ||
1128 | enable_power_gating_plane(dc->hwseq, true); | |
99326ee3 | 1129 | |
84e7fc05 | 1130 | memset(&dc->res_pool->clk_mgr->clks, 0, sizeof(dc->res_pool->clk_mgr->clks)); |
7a5086a7 YS |
1131 | } |
1132 | ||
cfe4645e | 1133 | static void reset_hw_ctx_wrap( |
fb3466a4 | 1134 | struct dc *dc, |
608ac7bb | 1135 | struct dc_state *context) |
70ccab60 HW |
1136 | { |
1137 | int i; | |
1138 | ||
cfe4645e | 1139 | /* Reset Back End*/ |
70ccab60 HW |
1140 | for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { |
1141 | struct pipe_ctx *pipe_ctx_old = | |
608ac7bb | 1142 | &dc->current_state->res_ctx.pipe_ctx[i]; |
70ccab60 HW |
1143 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; |
1144 | ||
1145 | if (!pipe_ctx_old->stream) | |
1146 | continue; | |
1147 | ||
56e6ed45 YS |
1148 | if (pipe_ctx_old->top_pipe) |
1149 | continue; | |
1150 | ||
70ccab60 | 1151 | if (!pipe_ctx->stream || |
21e67d4d HW |
1152 | pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { |
1153 | struct clock_source *old_clk = pipe_ctx_old->clock_source; | |
1154 | ||
608ac7bb | 1155 | reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_state); |
21e67d4d HW |
1156 | if (old_clk) |
1157 | old_clk->funcs->cs_power_down(old_clk); | |
1158 | } | |
70ccab60 | 1159 | } |
21e67d4d | 1160 | |
70ccab60 HW |
1161 | } |
1162 | ||
cfe4645e DL |
1163 | static bool patch_address_for_sbs_tb_stereo( |
1164 | struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr) | |
70ccab60 | 1165 | { |
3be5262e | 1166 | struct dc_plane_state *plane_state = pipe_ctx->plane_state; |
70ccab60 | 1167 | bool sec_split = pipe_ctx->top_pipe && |
3be5262e HW |
1168 | pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state; |
1169 | if (sec_split && plane_state->address.type == PLN_ADDR_TYPE_GRPH_STEREO && | |
4fa086b9 | 1170 | (pipe_ctx->stream->timing.timing_3d_format == |
70ccab60 | 1171 | TIMING_3D_FORMAT_SIDE_BY_SIDE || |
4fa086b9 | 1172 | pipe_ctx->stream->timing.timing_3d_format == |
70ccab60 | 1173 | TIMING_3D_FORMAT_TOP_AND_BOTTOM)) { |
3be5262e HW |
1174 | *addr = plane_state->address.grph_stereo.left_addr; |
1175 | plane_state->address.grph_stereo.left_addr = | |
1176 | plane_state->address.grph_stereo.right_addr; | |
70ccab60 | 1177 | return true; |
cdc5e048 | 1178 | } else { |
4fa086b9 | 1179 | if (pipe_ctx->stream->view_format != VIEW_3D_FORMAT_NONE && |
3be5262e HW |
1180 | plane_state->address.type != PLN_ADDR_TYPE_GRPH_STEREO) { |
1181 | plane_state->address.type = PLN_ADDR_TYPE_GRPH_STEREO; | |
1182 | plane_state->address.grph_stereo.right_addr = | |
1183 | plane_state->address.grph_stereo.left_addr; | |
cdc5e048 | 1184 | } |
70ccab60 HW |
1185 | } |
1186 | return false; | |
1187 | } | |
1188 | ||
9d6f264b | 1189 | |
9d6f264b | 1190 | |
fb3466a4 | 1191 | static void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx) |
70ccab60 HW |
1192 | { |
1193 | bool addr_patched = false; | |
1194 | PHYSICAL_ADDRESS_LOC addr; | |
3be5262e | 1195 | struct dc_plane_state *plane_state = pipe_ctx->plane_state; |
70ccab60 | 1196 | |
3be5262e | 1197 | if (plane_state == NULL) |
70ccab60 | 1198 | return; |
68199bd1 | 1199 | |
70ccab60 | 1200 | addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr); |
68199bd1 | 1201 | |
8feabd03 YHL |
1202 | pipe_ctx->plane_res.hubp->funcs->hubp_program_surface_flip_and_addr( |
1203 | pipe_ctx->plane_res.hubp, | |
3be5262e HW |
1204 | &plane_state->address, |
1205 | plane_state->flip_immediate); | |
68199bd1 | 1206 | |
3be5262e | 1207 | plane_state->status.requested_address = plane_state->address; |
68199bd1 TC |
1208 | |
1209 | if (plane_state->flip_immediate) | |
1210 | plane_state->status.current_address = plane_state->address; | |
1211 | ||
70ccab60 | 1212 | if (addr_patched) |
3be5262e | 1213 | pipe_ctx->plane_state->address.grph_stereo.left_addr = addr; |
70ccab60 HW |
1214 | } |
1215 | ||
a6114e85 HW |
1216 | static bool dcn10_set_input_transfer_func(struct pipe_ctx *pipe_ctx, |
1217 | const struct dc_plane_state *plane_state) | |
70ccab60 | 1218 | { |
d94585a0 | 1219 | struct dpp *dpp_base = pipe_ctx->plane_res.dpp; |
7b0c470f | 1220 | const struct dc_transfer_func *tf = NULL; |
70ccab60 HW |
1221 | bool result = true; |
1222 | ||
d94585a0 | 1223 | if (dpp_base == NULL) |
70ccab60 HW |
1224 | return false; |
1225 | ||
3be5262e HW |
1226 | if (plane_state->in_transfer_func) |
1227 | tf = plane_state->in_transfer_func; | |
70ccab60 | 1228 | |
f9549850 | 1229 | if (plane_state->gamma_correction && |
8ce504b9 ML |
1230 | !dpp_base->ctx->dc->debug.always_use_regamma |
1231 | && !plane_state->gamma_correction->is_identity | |
e43a432c | 1232 | && dce_use_lut(plane_state->format)) |
a6114e85 | 1233 | dpp_base->funcs->dpp_program_input_lut(dpp_base, plane_state->gamma_correction); |
5aff86c1 | 1234 | |
70ccab60 | 1235 | if (tf == NULL) |
5fa2ec4f | 1236 | dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS); |
7b0c470f LSL |
1237 | else if (tf->type == TF_TYPE_PREDEFINED) { |
1238 | switch (tf->tf) { | |
70ccab60 | 1239 | case TRANSFER_FUNCTION_SRGB: |
a6114e85 | 1240 | dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_HW_sRGB); |
70ccab60 HW |
1241 | break; |
1242 | case TRANSFER_FUNCTION_BT709: | |
a6114e85 | 1243 | dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_HW_xvYCC); |
70ccab60 HW |
1244 | break; |
1245 | case TRANSFER_FUNCTION_LINEAR: | |
a6114e85 | 1246 | dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS); |
70ccab60 HW |
1247 | break; |
1248 | case TRANSFER_FUNCTION_PQ: | |
70ccab60 HW |
1249 | default: |
1250 | result = false; | |
1251 | break; | |
1252 | } | |
7b0c470f | 1253 | } else if (tf->type == TF_TYPE_BYPASS) { |
5fa2ec4f | 1254 | dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS); |
70ccab60 | 1255 | } else { |
78e4405c DF |
1256 | cm_helper_translate_curve_to_degamma_hw_format(tf, |
1257 | &dpp_base->degamma_params); | |
1258 | dpp_base->funcs->dpp_program_degamma_pwl(dpp_base, | |
1259 | &dpp_base->degamma_params); | |
1260 | result = true; | |
70ccab60 HW |
1261 | } |
1262 | ||
1263 | return result; | |
1264 | } | |
70ccab60 | 1265 | |
70ccab60 | 1266 | |
70ccab60 | 1267 | |
70ccab60 | 1268 | |
70ccab60 | 1269 | |
a6114e85 HW |
1270 | static bool |
1271 | dcn10_set_output_transfer_func(struct pipe_ctx *pipe_ctx, | |
1272 | const struct dc_stream_state *stream) | |
70ccab60 | 1273 | { |
d94585a0 | 1274 | struct dpp *dpp = pipe_ctx->plane_res.dpp; |
70ccab60 | 1275 | |
d94585a0 | 1276 | if (dpp == NULL) |
f46661dd AZ |
1277 | return false; |
1278 | ||
d94585a0 | 1279 | dpp->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; |
70ccab60 | 1280 | |
4fa086b9 | 1281 | if (stream->out_transfer_func && |
a6114e85 HW |
1282 | stream->out_transfer_func->type == TF_TYPE_PREDEFINED && |
1283 | stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) | |
5fa2ec4f | 1284 | dpp->funcs->dpp_program_regamma_pwl(dpp, NULL, OPP_REGAMMA_SRGB); |
675634c5 YS |
1285 | |
1286 | /* dcn10_translate_regamma_to_hw_format takes 750us, only do it when full | |
1287 | * update. | |
1288 | */ | |
b6295960 | 1289 | else if (cm_helper_translate_curve_to_hw_format( |
675634c5 | 1290 | stream->out_transfer_func, |
b6295960 | 1291 | &dpp->regamma_params, false)) { |
675634c5 YS |
1292 | dpp->funcs->dpp_program_regamma_pwl( |
1293 | dpp, | |
1294 | &dpp->regamma_params, OPP_REGAMMA_USER); | |
1295 | } else | |
5fa2ec4f | 1296 | dpp->funcs->dpp_program_regamma_pwl(dpp, NULL, OPP_REGAMMA_BYPASS); |
70ccab60 HW |
1297 | |
1298 | return true; | |
1299 | } | |
1300 | ||
1301 | static void dcn10_pipe_control_lock( | |
fb3466a4 | 1302 | struct dc *dc, |
70ccab60 HW |
1303 | struct pipe_ctx *pipe, |
1304 | bool lock) | |
1305 | { | |
70ccab60 HW |
1306 | /* use TG master update lock to lock everything on the TG |
1307 | * therefore only top pipe need to lock | |
1308 | */ | |
1309 | if (pipe->top_pipe) | |
1310 | return; | |
1311 | ||
fb3466a4 | 1312 | if (dc->debug.sanity_checks) |
ea00f297 | 1313 | dcn10_verify_allow_pstate_change_high(dc); |
2b13d7d3 | 1314 | |
70ccab60 | 1315 | if (lock) |
6b670fa9 | 1316 | pipe->stream_res.tg->funcs->lock(pipe->stream_res.tg); |
70ccab60 | 1317 | else |
6b670fa9 | 1318 | pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg); |
2b13d7d3 | 1319 | |
fb3466a4 | 1320 | if (dc->debug.sanity_checks) |
ea00f297 | 1321 | dcn10_verify_allow_pstate_change_high(dc); |
70ccab60 HW |
1322 | } |
1323 | ||
1324 | static bool wait_for_reset_trigger_to_occur( | |
1325 | struct dc_context *dc_ctx, | |
1326 | struct timing_generator *tg) | |
1327 | { | |
1328 | bool rc = false; | |
1329 | ||
1330 | /* To avoid endless loop we wait at most | |
1331 | * frames_to_wait_on_triggered_reset frames for the reset to occur. */ | |
1332 | const uint32_t frames_to_wait_on_triggered_reset = 10; | |
1333 | int i; | |
1334 | ||
1335 | for (i = 0; i < frames_to_wait_on_triggered_reset; i++) { | |
1336 | ||
1337 | if (!tg->funcs->is_counter_moving(tg)) { | |
1338 | DC_ERROR("TG counter is not moving!\n"); | |
1339 | break; | |
1340 | } | |
1341 | ||
1342 | if (tg->funcs->did_triggered_reset_occur(tg)) { | |
1343 | rc = true; | |
1344 | /* usually occurs at i=1 */ | |
1345 | DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n", | |
1346 | i); | |
1347 | break; | |
1348 | } | |
1349 | ||
1350 | /* Wait for one frame. */ | |
1351 | tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE); | |
1352 | tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK); | |
1353 | } | |
1354 | ||
1355 | if (false == rc) | |
1356 | DC_ERROR("GSL: Timeout on reset trigger!\n"); | |
1357 | ||
1358 | return rc; | |
1359 | } | |
1360 | ||
1361 | static void dcn10_enable_timing_synchronization( | |
fb3466a4 | 1362 | struct dc *dc, |
70ccab60 HW |
1363 | int group_index, |
1364 | int group_size, | |
1365 | struct pipe_ctx *grouped_pipes[]) | |
1366 | { | |
1367 | struct dc_context *dc_ctx = dc->ctx; | |
1368 | int i; | |
1369 | ||
1370 | DC_SYNC_INFO("Setting up OTG reset trigger\n"); | |
1371 | ||
1372 | for (i = 1; i < group_size; i++) | |
6b670fa9 | 1373 | grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger( |
fa2123db ML |
1374 | grouped_pipes[i]->stream_res.tg, |
1375 | grouped_pipes[0]->stream_res.tg->inst); | |
70ccab60 HW |
1376 | |
1377 | DC_SYNC_INFO("Waiting for trigger\n"); | |
1378 | ||
1379 | /* Need to get only check 1 pipe for having reset as all the others are | |
1380 | * synchronized. Look at last pipe programmed to reset. | |
1381 | */ | |
fa2123db | 1382 | |
6b670fa9 | 1383 | wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[1]->stream_res.tg); |
70ccab60 | 1384 | for (i = 1; i < group_size; i++) |
6b670fa9 HW |
1385 | grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger( |
1386 | grouped_pipes[i]->stream_res.tg); | |
70ccab60 HW |
1387 | |
1388 | DC_SYNC_INFO("Sync complete\n"); | |
1389 | } | |
1390 | ||
fa2123db ML |
1391 | static void dcn10_enable_per_frame_crtc_position_reset( |
1392 | struct dc *dc, | |
1393 | int group_size, | |
1394 | struct pipe_ctx *grouped_pipes[]) | |
1395 | { | |
1396 | struct dc_context *dc_ctx = dc->ctx; | |
1397 | int i; | |
1398 | ||
1399 | DC_SYNC_INFO("Setting up\n"); | |
1400 | for (i = 0; i < group_size; i++) | |
7f93c1de CL |
1401 | if (grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset) |
1402 | grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset( | |
1403 | grouped_pipes[i]->stream_res.tg, | |
37cd85ce | 1404 | 0, |
7f93c1de | 1405 | &grouped_pipes[i]->stream->triggered_crtc_reset); |
fa2123db ML |
1406 | |
1407 | DC_SYNC_INFO("Waiting for trigger\n"); | |
1408 | ||
03736f4c | 1409 | for (i = 0; i < group_size; i++) |
fa2123db ML |
1410 | wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg); |
1411 | ||
1412 | DC_SYNC_INFO("Multi-display sync is complete\n"); | |
1413 | } | |
1414 | ||
b8fce2c9 | 1415 | /*static void print_rq_dlg_ttu( |
fb3466a4 | 1416 | struct dc *core_dc, |
c9742685 DL |
1417 | struct pipe_ctx *pipe_ctx) |
1418 | { | |
2f3fd67a | 1419 | DC_LOG_BANDWIDTH_CALCS(core_dc->ctx->logger, |
c9742685 DL |
1420 | "\n============== DML TTU Output parameters [%d] ==============\n" |
1421 | "qos_level_low_wm: %d, \n" | |
1422 | "qos_level_high_wm: %d, \n" | |
1423 | "min_ttu_vblank: %d, \n" | |
1424 | "qos_level_flip: %d, \n" | |
1425 | "refcyc_per_req_delivery_l: %d, \n" | |
1426 | "qos_level_fixed_l: %d, \n" | |
1427 | "qos_ramp_disable_l: %d, \n" | |
1428 | "refcyc_per_req_delivery_pre_l: %d, \n" | |
1429 | "refcyc_per_req_delivery_c: %d, \n" | |
1430 | "qos_level_fixed_c: %d, \n" | |
1431 | "qos_ramp_disable_c: %d, \n" | |
1432 | "refcyc_per_req_delivery_pre_c: %d\n" | |
1433 | "=============================================================\n", | |
1434 | pipe_ctx->pipe_idx, | |
1435 | pipe_ctx->ttu_regs.qos_level_low_wm, | |
1436 | pipe_ctx->ttu_regs.qos_level_high_wm, | |
1437 | pipe_ctx->ttu_regs.min_ttu_vblank, | |
1438 | pipe_ctx->ttu_regs.qos_level_flip, | |
1439 | pipe_ctx->ttu_regs.refcyc_per_req_delivery_l, | |
1440 | pipe_ctx->ttu_regs.qos_level_fixed_l, | |
1441 | pipe_ctx->ttu_regs.qos_ramp_disable_l, | |
1442 | pipe_ctx->ttu_regs.refcyc_per_req_delivery_pre_l, | |
1443 | pipe_ctx->ttu_regs.refcyc_per_req_delivery_c, | |
1444 | pipe_ctx->ttu_regs.qos_level_fixed_c, | |
1445 | pipe_ctx->ttu_regs.qos_ramp_disable_c, | |
1446 | pipe_ctx->ttu_regs.refcyc_per_req_delivery_pre_c | |
1447 | ); | |
1448 | ||
2f3fd67a | 1449 | DC_LOG_BANDWIDTH_CALCS(core_dc->ctx->logger, |
c9742685 DL |
1450 | "\n============== DML DLG Output parameters [%d] ==============\n" |
1451 | "refcyc_h_blank_end: %d, \n" | |
1452 | "dlg_vblank_end: %d, \n" | |
1453 | "min_dst_y_next_start: %d, \n" | |
1454 | "refcyc_per_htotal: %d, \n" | |
1455 | "refcyc_x_after_scaler: %d, \n" | |
1456 | "dst_y_after_scaler: %d, \n" | |
1457 | "dst_y_prefetch: %d, \n" | |
1458 | "dst_y_per_vm_vblank: %d, \n" | |
1459 | "dst_y_per_row_vblank: %d, \n" | |
1460 | "ref_freq_to_pix_freq: %d, \n" | |
1461 | "vratio_prefetch: %d, \n" | |
1462 | "refcyc_per_pte_group_vblank_l: %d, \n" | |
1463 | "refcyc_per_meta_chunk_vblank_l: %d, \n" | |
1464 | "dst_y_per_pte_row_nom_l: %d, \n" | |
1465 | "refcyc_per_pte_group_nom_l: %d, \n", | |
1466 | pipe_ctx->pipe_idx, | |
1467 | pipe_ctx->dlg_regs.refcyc_h_blank_end, | |
1468 | pipe_ctx->dlg_regs.dlg_vblank_end, | |
1469 | pipe_ctx->dlg_regs.min_dst_y_next_start, | |
1470 | pipe_ctx->dlg_regs.refcyc_per_htotal, | |
1471 | pipe_ctx->dlg_regs.refcyc_x_after_scaler, | |
1472 | pipe_ctx->dlg_regs.dst_y_after_scaler, | |
1473 | pipe_ctx->dlg_regs.dst_y_prefetch, | |
1474 | pipe_ctx->dlg_regs.dst_y_per_vm_vblank, | |
1475 | pipe_ctx->dlg_regs.dst_y_per_row_vblank, | |
1476 | pipe_ctx->dlg_regs.ref_freq_to_pix_freq, | |
1477 | pipe_ctx->dlg_regs.vratio_prefetch, | |
1478 | pipe_ctx->dlg_regs.refcyc_per_pte_group_vblank_l, | |
1479 | pipe_ctx->dlg_regs.refcyc_per_meta_chunk_vblank_l, | |
1480 | pipe_ctx->dlg_regs.dst_y_per_pte_row_nom_l, | |
1481 | pipe_ctx->dlg_regs.refcyc_per_pte_group_nom_l | |
1482 | ); | |
1483 | ||
2f3fd67a | 1484 | DC_LOG_BANDWIDTH_CALCS(core_dc->ctx->logger, |
c9742685 DL |
1485 | "\ndst_y_per_meta_row_nom_l: %d, \n" |
1486 | "refcyc_per_meta_chunk_nom_l: %d, \n" | |
1487 | "refcyc_per_line_delivery_pre_l: %d, \n" | |
1488 | "refcyc_per_line_delivery_l: %d, \n" | |
1489 | "vratio_prefetch_c: %d, \n" | |
1490 | "refcyc_per_pte_group_vblank_c: %d, \n" | |
1491 | "refcyc_per_meta_chunk_vblank_c: %d, \n" | |
1492 | "dst_y_per_pte_row_nom_c: %d, \n" | |
1493 | "refcyc_per_pte_group_nom_c: %d, \n" | |
1494 | "dst_y_per_meta_row_nom_c: %d, \n" | |
1495 | "refcyc_per_meta_chunk_nom_c: %d, \n" | |
1496 | "refcyc_per_line_delivery_pre_c: %d, \n" | |
1497 | "refcyc_per_line_delivery_c: %d \n" | |
1498 | "========================================================\n", | |
1499 | pipe_ctx->dlg_regs.dst_y_per_meta_row_nom_l, | |
1500 | pipe_ctx->dlg_regs.refcyc_per_meta_chunk_nom_l, | |
1501 | pipe_ctx->dlg_regs.refcyc_per_line_delivery_pre_l, | |
1502 | pipe_ctx->dlg_regs.refcyc_per_line_delivery_l, | |
1503 | pipe_ctx->dlg_regs.vratio_prefetch_c, | |
1504 | pipe_ctx->dlg_regs.refcyc_per_pte_group_vblank_c, | |
1505 | pipe_ctx->dlg_regs.refcyc_per_meta_chunk_vblank_c, | |
1506 | pipe_ctx->dlg_regs.dst_y_per_pte_row_nom_c, | |
1507 | pipe_ctx->dlg_regs.refcyc_per_pte_group_nom_c, | |
1508 | pipe_ctx->dlg_regs.dst_y_per_meta_row_nom_c, | |
1509 | pipe_ctx->dlg_regs.refcyc_per_meta_chunk_nom_c, | |
1510 | pipe_ctx->dlg_regs.refcyc_per_line_delivery_pre_c, | |
1511 | pipe_ctx->dlg_regs.refcyc_per_line_delivery_c | |
1512 | ); | |
1513 | ||
2f3fd67a | 1514 | DC_LOG_BANDWIDTH_CALCS(core_dc->ctx->logger, |
c9742685 DL |
1515 | "\n============== DML RQ Output parameters [%d] ==============\n" |
1516 | "chunk_size: %d \n" | |
1517 | "min_chunk_size: %d \n" | |
1518 | "meta_chunk_size: %d \n" | |
1519 | "min_meta_chunk_size: %d \n" | |
1520 | "dpte_group_size: %d \n" | |
1521 | "mpte_group_size: %d \n" | |
1522 | "swath_height: %d \n" | |
1523 | "pte_row_height_linear: %d \n" | |
1524 | "========================================================\n", | |
1525 | pipe_ctx->pipe_idx, | |
1526 | pipe_ctx->rq_regs.rq_regs_l.chunk_size, | |
1527 | pipe_ctx->rq_regs.rq_regs_l.min_chunk_size, | |
1528 | pipe_ctx->rq_regs.rq_regs_l.meta_chunk_size, | |
1529 | pipe_ctx->rq_regs.rq_regs_l.min_meta_chunk_size, | |
1530 | pipe_ctx->rq_regs.rq_regs_l.dpte_group_size, | |
1531 | pipe_ctx->rq_regs.rq_regs_l.mpte_group_size, | |
1532 | pipe_ctx->rq_regs.rq_regs_l.swath_height, | |
1533 | pipe_ctx->rq_regs.rq_regs_l.pte_row_height_linear | |
1534 | ); | |
1535 | } | |
b8fce2c9 | 1536 | */ |
c9742685 | 1537 | |
a4e6d14e YS |
1538 | static void mmhub_read_vm_system_aperture_settings(struct dcn10_hubp *hubp1, |
1539 | struct vm_system_aperture_param *apt, | |
1540 | struct dce_hwseq *hws) | |
1541 | { | |
1542 | PHYSICAL_ADDRESS_LOC physical_page_number; | |
1543 | uint32_t logical_addr_low; | |
1544 | uint32_t logical_addr_high; | |
1545 | ||
1546 | REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, | |
1547 | PHYSICAL_PAGE_NUMBER_MSB, &physical_page_number.high_part); | |
1548 | REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, | |
1549 | PHYSICAL_PAGE_NUMBER_LSB, &physical_page_number.low_part); | |
1550 | ||
1551 | REG_GET(MC_VM_SYSTEM_APERTURE_LOW_ADDR, | |
1552 | LOGICAL_ADDR, &logical_addr_low); | |
1553 | ||
1554 | REG_GET(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, | |
1555 | LOGICAL_ADDR, &logical_addr_high); | |
1556 | ||
1557 | apt->sys_default.quad_part = physical_page_number.quad_part << 12; | |
1558 | apt->sys_low.quad_part = (int64_t)logical_addr_low << 18; | |
1559 | apt->sys_high.quad_part = (int64_t)logical_addr_high << 18; | |
1560 | } | |
1561 | ||
1562 | /* Temporary read settings, future will get values from kmd directly */ | |
1563 | static void mmhub_read_vm_context0_settings(struct dcn10_hubp *hubp1, | |
1564 | struct vm_context0_param *vm0, | |
1565 | struct dce_hwseq *hws) | |
1566 | { | |
1567 | PHYSICAL_ADDRESS_LOC fb_base; | |
1568 | PHYSICAL_ADDRESS_LOC fb_offset; | |
1569 | uint32_t fb_base_value; | |
1570 | uint32_t fb_offset_value; | |
1571 | ||
1572 | REG_GET(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, &fb_base_value); | |
1573 | REG_GET(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, &fb_offset_value); | |
1574 | ||
1575 | REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32, | |
1576 | PAGE_DIRECTORY_ENTRY_HI32, &vm0->pte_base.high_part); | |
1577 | REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32, | |
1578 | PAGE_DIRECTORY_ENTRY_LO32, &vm0->pte_base.low_part); | |
1579 | ||
1580 | REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32, | |
1581 | LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_start.high_part); | |
1582 | REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32, | |
1583 | LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_start.low_part); | |
1584 | ||
1585 | REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32, | |
1586 | LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_end.high_part); | |
1587 | REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32, | |
1588 | LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_end.low_part); | |
1589 | ||
1590 | REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32, | |
1591 | PHYSICAL_PAGE_ADDR_HI4, &vm0->fault_default.high_part); | |
1592 | REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32, | |
1593 | PHYSICAL_PAGE_ADDR_LO32, &vm0->fault_default.low_part); | |
1594 | ||
1595 | /* | |
1596 | * The values in VM_CONTEXT0_PAGE_TABLE_BASE_ADDR is in UMA space. | |
1597 | * Therefore we need to do | |
1598 | * DCN_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR = VM_CONTEXT0_PAGE_TABLE_BASE_ADDR | |
1599 | * - DCHUBBUB_SDPIF_FB_OFFSET + DCHUBBUB_SDPIF_FB_BASE | |
1600 | */ | |
1601 | fb_base.quad_part = (uint64_t)fb_base_value << 24; | |
1602 | fb_offset.quad_part = (uint64_t)fb_offset_value << 24; | |
1603 | vm0->pte_base.quad_part += fb_base.quad_part; | |
1604 | vm0->pte_base.quad_part -= fb_offset.quad_part; | |
1605 | } | |
1606 | ||
1607 | ||
560a77f5 | 1608 | void dcn10_program_pte_vm(struct dce_hwseq *hws, struct hubp *hubp) |
a4e6d14e YS |
1609 | { |
1610 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); | |
1611 | struct vm_system_aperture_param apt = { {{ 0 } } }; | |
1612 | struct vm_context0_param vm0 = { { { 0 } } }; | |
1613 | ||
1614 | mmhub_read_vm_system_aperture_settings(hubp1, &apt, hws); | |
1615 | mmhub_read_vm_context0_settings(hubp1, &vm0, hws); | |
1616 | ||
1617 | hubp->funcs->hubp_set_vm_system_aperture_settings(hubp, &apt); | |
1618 | hubp->funcs->hubp_set_vm_context0_settings(hubp, &vm0); | |
1619 | } | |
1620 | ||
7f914a62 | 1621 | static void dcn10_enable_plane( |
fb3466a4 | 1622 | struct dc *dc, |
70ccab60 | 1623 | struct pipe_ctx *pipe_ctx, |
608ac7bb | 1624 | struct dc_state *context) |
70ccab60 | 1625 | { |
184debdb | 1626 | struct dce_hwseq *hws = dc->hwseq; |
70ccab60 | 1627 | |
fb3466a4 | 1628 | if (dc->debug.sanity_checks) { |
ea00f297 | 1629 | dcn10_verify_allow_pstate_change_high(dc); |
665da60f CM |
1630 | } |
1631 | ||
7f914a62 YS |
1632 | undo_DEGVIDCN10_253_wa(dc); |
1633 | ||
184debdb | 1634 | power_on_plane(dc->hwseq, |
e07f541f | 1635 | pipe_ctx->plane_res.hubp->inst); |
70ccab60 | 1636 | |
c9742685 | 1637 | /* enable DCFCLK current DCHUB */ |
c8242b98 | 1638 | pipe_ctx->plane_res.hubp->funcs->hubp_clk_cntl(pipe_ctx->plane_res.hubp, true); |
d21becbe TC |
1639 | |
1640 | /* make sure OPP_PIPE_CLOCK_EN = 1 */ | |
be2f449a YS |
1641 | pipe_ctx->stream_res.opp->funcs->opp_pipe_clock_control( |
1642 | pipe_ctx->stream_res.opp, | |
1643 | true); | |
c9742685 | 1644 | |
b8fce2c9 | 1645 | /* TODO: enable/disable in dm as per update type. |
3be5262e | 1646 | if (plane_state) { |
2f3fd67a | 1647 | DC_LOG_DC(dc->ctx->logger, |
c9742685 DL |
1648 | "Pipe:%d 0x%x: addr hi:0x%x, " |
1649 | "addr low:0x%x, " | |
1650 | "src: %d, %d, %d," | |
1651 | " %d; dst: %d, %d, %d, %d;\n", | |
70ccab60 | 1652 | pipe_ctx->pipe_idx, |
3be5262e HW |
1653 | plane_state, |
1654 | plane_state->address.grph.addr.high_part, | |
1655 | plane_state->address.grph.addr.low_part, | |
1656 | plane_state->src_rect.x, | |
1657 | plane_state->src_rect.y, | |
1658 | plane_state->src_rect.width, | |
1659 | plane_state->src_rect.height, | |
1660 | plane_state->dst_rect.x, | |
1661 | plane_state->dst_rect.y, | |
1662 | plane_state->dst_rect.width, | |
1663 | plane_state->dst_rect.height); | |
c9742685 | 1664 | |
2f3fd67a | 1665 | DC_LOG_DC(dc->ctx->logger, |
3eea71e3 | 1666 | "Pipe %d: width, height, x, y format:%d\n" |
c9742685 DL |
1667 | "viewport:%d, %d, %d, %d\n" |
1668 | "recout: %d, %d, %d, %d\n", | |
1669 | pipe_ctx->pipe_idx, | |
3eea71e3 | 1670 | plane_state->format, |
6702a9ac HW |
1671 | pipe_ctx->plane_res.scl_data.viewport.width, |
1672 | pipe_ctx->plane_res.scl_data.viewport.height, | |
1673 | pipe_ctx->plane_res.scl_data.viewport.x, | |
1674 | pipe_ctx->plane_res.scl_data.viewport.y, | |
1675 | pipe_ctx->plane_res.scl_data.recout.width, | |
1676 | pipe_ctx->plane_res.scl_data.recout.height, | |
1677 | pipe_ctx->plane_res.scl_data.recout.x, | |
1678 | pipe_ctx->plane_res.scl_data.recout.y); | |
c9742685 | 1679 | print_rq_dlg_ttu(dc, pipe_ctx); |
70ccab60 | 1680 | } |
b8fce2c9 | 1681 | */ |
a4e6d14e YS |
1682 | if (dc->config.gpu_vm_support) |
1683 | dcn10_program_pte_vm(hws, pipe_ctx->plane_res.hubp); | |
665da60f | 1684 | |
fb3466a4 | 1685 | if (dc->debug.sanity_checks) { |
ea00f297 | 1686 | dcn10_verify_allow_pstate_change_high(dc); |
665da60f | 1687 | } |
70ccab60 HW |
1688 | } |
1689 | ||
1690 | static void program_gamut_remap(struct pipe_ctx *pipe_ctx) | |
1691 | { | |
146a9f63 | 1692 | int i = 0; |
d94585a0 | 1693 | struct dpp_grph_csc_adjustment adjust; |
70ccab60 HW |
1694 | memset(&adjust, 0, sizeof(adjust)); |
1695 | adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; | |
1696 | ||
1697 | ||
4fa086b9 | 1698 | if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { |
70ccab60 | 1699 | adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; |
146a9f63 KK |
1700 | for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++) |
1701 | adjust.temperature_matrix[i] = | |
1702 | pipe_ctx->stream->gamut_remap_matrix.matrix[i]; | |
70ccab60 HW |
1703 | } |
1704 | ||
d94585a0 | 1705 | pipe_ctx->plane_res.dpp->funcs->dpp_set_gamut_remap(pipe_ctx->plane_res.dpp, &adjust); |
70ccab60 HW |
1706 | } |
1707 | ||
3917a470 KK |
1708 | static void dcn10_program_output_csc(struct dc *dc, |
1709 | struct pipe_ctx *pipe_ctx, | |
abe07e80 | 1710 | enum dc_color_space colorspace, |
3917a470 KK |
1711 | uint16_t *matrix, |
1712 | int opp_id) | |
abe07e80 | 1713 | { |
56ef6ed9 | 1714 | if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) { |
3917a470 KK |
1715 | if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment != NULL) |
1716 | pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment(pipe_ctx->plane_res.dpp, matrix); | |
ea826d64 | 1717 | } else { |
afbeb263 YHL |
1718 | if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_default != NULL) |
1719 | pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_default(pipe_ctx->plane_res.dpp, colorspace); | |
abe07e80 YHL |
1720 | } |
1721 | } | |
de4a2967 | 1722 | |
560a77f5 | 1723 | bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx) |
4b28b76b | 1724 | { |
3be5262e | 1725 | if (pipe_ctx->plane_state->visible) |
4b28b76b DL |
1726 | return true; |
1727 | if (pipe_ctx->bottom_pipe && is_lower_pipe_tree_visible(pipe_ctx->bottom_pipe)) | |
1728 | return true; | |
1729 | return false; | |
1730 | } | |
1731 | ||
560a77f5 | 1732 | bool is_upper_pipe_tree_visible(struct pipe_ctx *pipe_ctx) |
4b28b76b | 1733 | { |
3be5262e | 1734 | if (pipe_ctx->plane_state->visible) |
4b28b76b DL |
1735 | return true; |
1736 | if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe)) | |
1737 | return true; | |
1738 | return false; | |
1739 | } | |
1740 | ||
560a77f5 | 1741 | bool is_pipe_tree_visible(struct pipe_ctx *pipe_ctx) |
4b28b76b | 1742 | { |
3be5262e | 1743 | if (pipe_ctx->plane_state->visible) |
4b28b76b DL |
1744 | return true; |
1745 | if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe)) | |
1746 | return true; | |
1747 | if (pipe_ctx->bottom_pipe && is_lower_pipe_tree_visible(pipe_ctx->bottom_pipe)) | |
1748 | return true; | |
1749 | return false; | |
1750 | } | |
1751 | ||
b3a1cbc0 | 1752 | bool is_rgb_cspace(enum dc_color_space output_color_space) |
ad327346 DL |
1753 | { |
1754 | switch (output_color_space) { | |
1755 | case COLOR_SPACE_SRGB: | |
1756 | case COLOR_SPACE_SRGB_LIMITED: | |
1757 | case COLOR_SPACE_2020_RGB_FULLRANGE: | |
1758 | case COLOR_SPACE_2020_RGB_LIMITEDRANGE: | |
1759 | case COLOR_SPACE_ADOBERGB: | |
1760 | return true; | |
1761 | case COLOR_SPACE_YCBCR601: | |
1762 | case COLOR_SPACE_YCBCR709: | |
1763 | case COLOR_SPACE_YCBCR601_LIMITED: | |
1764 | case COLOR_SPACE_YCBCR709_LIMITED: | |
1765 | case COLOR_SPACE_2020_YCBCR: | |
1766 | return false; | |
1767 | default: | |
1768 | /* Add a case to switch */ | |
1769 | BREAK_TO_DEBUGGER(); | |
1770 | return false; | |
1771 | } | |
1772 | } | |
1773 | ||
d9672a5b | 1774 | void dcn10_get_surface_visual_confirm_color( |
87449a90 AK |
1775 | const struct pipe_ctx *pipe_ctx, |
1776 | struct tg_color *color) | |
1777 | { | |
1778 | uint32_t color_value = MAX_TG_COLOR_VALUE; | |
1779 | ||
6702a9ac | 1780 | switch (pipe_ctx->plane_res.scl_data.format) { |
87449a90 AK |
1781 | case PIXEL_FORMAT_ARGB8888: |
1782 | /* set boarder color to red */ | |
1783 | color->color_r_cr = color_value; | |
1784 | break; | |
1785 | ||
1786 | case PIXEL_FORMAT_ARGB2101010: | |
1787 | /* set boarder color to blue */ | |
1788 | color->color_b_cb = color_value; | |
1789 | break; | |
1790 | case PIXEL_FORMAT_420BPP8: | |
1791 | /* set boarder color to green */ | |
1792 | color->color_g_y = color_value; | |
1793 | break; | |
1794 | case PIXEL_FORMAT_420BPP10: | |
1795 | /* set boarder color to yellow */ | |
1796 | color->color_g_y = color_value; | |
1797 | color->color_r_cr = color_value; | |
1798 | break; | |
1799 | case PIXEL_FORMAT_FP16: | |
1800 | /* set boarder color to white */ | |
1801 | color->color_r_cr = color_value; | |
1802 | color->color_b_cb = color_value; | |
1803 | color->color_g_y = color_value; | |
1804 | break; | |
1805 | default: | |
1806 | break; | |
1807 | } | |
1808 | } | |
1809 | ||
d9672a5b | 1810 | void dcn10_get_hdr_visual_confirm_color( |
bf53769d GL |
1811 | struct pipe_ctx *pipe_ctx, |
1812 | struct tg_color *color) | |
1813 | { | |
1814 | uint32_t color_value = MAX_TG_COLOR_VALUE; | |
1815 | ||
1816 | // Determine the overscan color based on the top-most (desktop) plane's context | |
1817 | struct pipe_ctx *top_pipe_ctx = pipe_ctx; | |
1818 | ||
1819 | while (top_pipe_ctx->top_pipe != NULL) | |
1820 | top_pipe_ctx = top_pipe_ctx->top_pipe; | |
1821 | ||
1822 | switch (top_pipe_ctx->plane_res.scl_data.format) { | |
1823 | case PIXEL_FORMAT_ARGB2101010: | |
1824 | if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_UNITY) { | |
1825 | /* HDR10, ARGB2101010 - set boarder color to red */ | |
1826 | color->color_r_cr = color_value; | |
1827 | } | |
1828 | break; | |
1829 | case PIXEL_FORMAT_FP16: | |
1830 | if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_PQ) { | |
1831 | /* HDR10, FP16 - set boarder color to blue */ | |
1832 | color->color_b_cb = color_value; | |
1833 | } else if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) { | |
1834 | /* FreeSync 2 HDR - set boarder color to green */ | |
1835 | color->color_g_y = color_value; | |
1836 | } | |
1837 | break; | |
1838 | default: | |
1839 | /* SDR - set boarder color to Gray */ | |
1840 | color->color_r_cr = color_value/2; | |
1841 | color->color_b_cb = color_value/2; | |
1842 | color->color_g_y = color_value/2; | |
1843 | break; | |
1844 | } | |
1845 | } | |
1846 | ||
de4a2967 S |
1847 | static uint16_t fixed_point_to_int_frac( |
1848 | struct fixed31_32 arg, | |
1849 | uint8_t integer_bits, | |
1850 | uint8_t fractional_bits) | |
1851 | { | |
1852 | int32_t numerator; | |
1853 | int32_t divisor = 1 << fractional_bits; | |
1854 | ||
1855 | uint16_t result; | |
1856 | ||
eb0e5154 DL |
1857 | uint16_t d = (uint16_t)dc_fixpt_floor( |
1858 | dc_fixpt_abs( | |
de4a2967 S |
1859 | arg)); |
1860 | ||
1861 | if (d <= (uint16_t)(1 << integer_bits) - (1 / (uint16_t)divisor)) | |
eb0e5154 DL |
1862 | numerator = (uint16_t)dc_fixpt_floor( |
1863 | dc_fixpt_mul_int( | |
de4a2967 S |
1864 | arg, |
1865 | divisor)); | |
1866 | else { | |
eb0e5154 DL |
1867 | numerator = dc_fixpt_floor( |
1868 | dc_fixpt_sub( | |
1869 | dc_fixpt_from_int( | |
de4a2967 | 1870 | 1LL << integer_bits), |
eb0e5154 DL |
1871 | dc_fixpt_recip( |
1872 | dc_fixpt_from_int( | |
de4a2967 S |
1873 | divisor)))); |
1874 | } | |
1875 | ||
1876 | if (numerator >= 0) | |
1877 | result = (uint16_t)numerator; | |
1878 | else | |
1879 | result = (uint16_t)( | |
1880 | (1 << (integer_bits + fractional_bits + 1)) + numerator); | |
1881 | ||
eb0e5154 DL |
1882 | if ((result != 0) && dc_fixpt_lt( |
1883 | arg, dc_fixpt_zero)) | |
de4a2967 S |
1884 | result |= 1 << (integer_bits + fractional_bits); |
1885 | ||
1886 | return result; | |
1887 | } | |
1888 | ||
1889 | void build_prescale_params(struct dc_bias_and_scale *bias_and_scale, | |
1890 | const struct dc_plane_state *plane_state) | |
1891 | { | |
1892 | if (plane_state->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN | |
1893 | && plane_state->format != SURFACE_PIXEL_FORMAT_INVALID | |
1894 | && plane_state->input_csc_color_matrix.enable_adjustment | |
1895 | && plane_state->coeff_reduction_factor.value != 0) { | |
1896 | bias_and_scale->scale_blue = fixed_point_to_int_frac( | |
eb0e5154 DL |
1897 | dc_fixpt_mul(plane_state->coeff_reduction_factor, |
1898 | dc_fixpt_from_fraction(256, 255)), | |
de4a2967 S |
1899 | 2, |
1900 | 13); | |
1901 | bias_and_scale->scale_red = bias_and_scale->scale_blue; | |
1902 | bias_and_scale->scale_green = bias_and_scale->scale_blue; | |
1903 | } else { | |
1904 | bias_and_scale->scale_blue = 0x2000; | |
1905 | bias_and_scale->scale_red = 0x2000; | |
1906 | bias_and_scale->scale_green = 0x2000; | |
1907 | } | |
1908 | } | |
1909 | ||
480bd0cf | 1910 | static void update_dpp(struct dpp *dpp, struct dc_plane_state *plane_state) |
70ccab60 | 1911 | { |
de4a2967 | 1912 | struct dc_bias_and_scale bns_params = {0}; |
cbfd33fd | 1913 | |
de4a2967 | 1914 | // program the input csc |
5fa2ec4f | 1915 | dpp->funcs->dpp_setup(dpp, |
3be5262e | 1916 | plane_state->format, |
de4a2967 S |
1917 | EXPANSION_MODE_ZERO, |
1918 | plane_state->input_csc_color_matrix, | |
1919 | COLOR_SPACE_YCBCR601_LIMITED); | |
1920 | ||
1921 | //set scale and bias registers | |
1922 | build_prescale_params(&bns_params, plane_state); | |
5fa2ec4f YHL |
1923 | if (dpp->funcs->dpp_program_bias_and_scale) |
1924 | dpp->funcs->dpp_program_bias_and_scale(dpp, &bns_params); | |
480bd0cf YS |
1925 | } |
1926 | ||
c2437b1f | 1927 | static void dcn10_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx) |
480bd0cf | 1928 | { |
480bd0cf | 1929 | struct hubp *hubp = pipe_ctx->plane_res.hubp; |
35fb7220 | 1930 | struct mpcc_blnd_cfg blnd_cfg = {{0}}; |
feb4a3cd EB |
1931 | bool per_pixel_alpha = pipe_ctx->plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe; |
1932 | int mpcc_id; | |
1933 | struct mpcc *new_mpcc; | |
1934 | struct mpc *mpc = dc->res_pool->mpc; | |
1935 | struct mpc_tree *mpc_tree_params = &(pipe_ctx->stream_res.opp->mpc_tree_params); | |
480bd0cf | 1936 | |
bf53769d GL |
1937 | if (dc->debug.visual_confirm == VISUAL_CONFIRM_HDR) { |
1938 | dcn10_get_hdr_visual_confirm_color( | |
1939 | pipe_ctx, &blnd_cfg.black_color); | |
1940 | } else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE) { | |
cc408d72 | 1941 | dcn10_get_surface_visual_confirm_color( |
feb4a3cd | 1942 | pipe_ctx, &blnd_cfg.black_color); |
bf53769d | 1943 | } else { |
cc408d72 | 1944 | color_space_to_black_color( |
bf53769d GL |
1945 | dc, pipe_ctx->stream->output_color_space, |
1946 | &blnd_cfg.black_color); | |
1947 | } | |
feb4a3cd EB |
1948 | |
1949 | if (per_pixel_alpha) | |
1950 | blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA; | |
1951 | else | |
1952 | blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA; | |
1953 | ||
1954 | blnd_cfg.overlap_only = false; | |
feb4a3cd EB |
1955 | blnd_cfg.global_gain = 0xff; |
1956 | ||
94a4ffd1 GL |
1957 | if (pipe_ctx->plane_state->global_alpha) |
1958 | blnd_cfg.global_alpha = pipe_ctx->plane_state->global_alpha_value; | |
1959 | else | |
1960 | blnd_cfg.global_alpha = 0xff; | |
1961 | ||
ad327346 DL |
1962 | /* DCN1.0 has output CM before MPC which seems to screw with |
1963 | * pre-multiplied alpha. | |
1964 | */ | |
feb4a3cd | 1965 | blnd_cfg.pre_multiplied_alpha = is_rgb_cspace( |
4fa086b9 | 1966 | pipe_ctx->stream->output_color_space) |
ad327346 | 1967 | && per_pixel_alpha; |
feb4a3cd | 1968 | |
4173c0bd | 1969 | |
feb4a3cd EB |
1970 | /* |
1971 | * TODO: remove hack | |
1972 | * Note: currently there is a bug in init_hw such that | |
1973 | * on resume from hibernate, BIOS sets up MPCC0, and | |
1974 | * we do mpcc_remove but the mpcc cannot go to idle | |
1975 | * after remove. This cause us to pick mpcc1 here, | |
1976 | * which causes a pstate hang for yet unknown reason. | |
1977 | */ | |
1978 | mpcc_id = hubp->inst; | |
1979 | ||
4173c0bd EY |
1980 | /* If there is no full update, don't need to touch MPC tree*/ |
1981 | if (!pipe_ctx->plane_state->update_flags.bits.full_update) { | |
1982 | mpc->funcs->update_blending(mpc, &blnd_cfg, mpcc_id); | |
1983 | return; | |
1984 | } | |
1985 | ||
feb4a3cd EB |
1986 | /* check if this MPCC is already being used */ |
1987 | new_mpcc = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, mpcc_id); | |
1988 | /* remove MPCC if being used */ | |
1989 | if (new_mpcc != NULL) | |
1990 | mpc->funcs->remove_mpcc(mpc, mpc_tree_params, new_mpcc); | |
49fac0b4 EB |
1991 | else |
1992 | if (dc->debug.sanity_checks) | |
1993 | mpc->funcs->assert_mpcc_idle_before_connect( | |
1994 | dc->res_pool->mpc, mpcc_id); | |
feb4a3cd EB |
1995 | |
1996 | /* Call MPC to insert new plane */ | |
1997 | new_mpcc = mpc->funcs->insert_plane(dc->res_pool->mpc, | |
1998 | mpc_tree_params, | |
1999 | &blnd_cfg, | |
2000 | NULL, | |
2001 | NULL, | |
2002 | hubp->inst, | |
2003 | mpcc_id); | |
2004 | ||
2005 | ASSERT(new_mpcc != NULL); | |
2006 | ||
2007 | hubp->opp_id = pipe_ctx->stream_res.opp->inst; | |
2008 | hubp->mpcc_id = mpcc_id; | |
480bd0cf YS |
2009 | } |
2010 | ||
2011 | static void update_scaler(struct pipe_ctx *pipe_ctx) | |
2012 | { | |
2013 | bool per_pixel_alpha = | |
2014 | pipe_ctx->plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe; | |
2015 | ||
6702a9ac HW |
2016 | pipe_ctx->plane_res.scl_data.lb_params.alpha_en = per_pixel_alpha; |
2017 | pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; | |
70ccab60 | 2018 | /* scaler configuration */ |
d94585a0 YHL |
2019 | pipe_ctx->plane_res.dpp->funcs->dpp_set_scaler( |
2020 | pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data); | |
480bd0cf YS |
2021 | } |
2022 | ||
560a77f5 | 2023 | void update_dchubp_dpp( |
480bd0cf YS |
2024 | struct dc *dc, |
2025 | struct pipe_ctx *pipe_ctx, | |
2026 | struct dc_state *context) | |
2027 | { | |
480bd0cf YS |
2028 | struct hubp *hubp = pipe_ctx->plane_res.hubp; |
2029 | struct dpp *dpp = pipe_ctx->plane_res.dpp; | |
2030 | struct dc_plane_state *plane_state = pipe_ctx->plane_state; | |
2031 | union plane_size size = plane_state->plane_size; | |
a465feae | 2032 | unsigned int compat_level = 0; |
480bd0cf YS |
2033 | |
2034 | /* depends on DML calculation, DPP clock value may change dynamically */ | |
45bb8dd6 YS |
2035 | /* If request max dpp clk is lower than current dispclk, no need to |
2036 | * divided by 2 | |
2037 | */ | |
16a29dd3 | 2038 | if (plane_state->update_flags.bits.full_update) { |
d578839c | 2039 | bool should_divided_by_2 = context->bw.dcn.clk.dppclk_khz <= |
84e7fc05 | 2040 | dc->res_pool->clk_mgr->clks.dispclk_khz / 2; |
45bb8dd6 | 2041 | |
f8e413bf YS |
2042 | dpp->funcs->dpp_dppclk_control( |
2043 | dpp, | |
45bb8dd6 | 2044 | should_divided_by_2, |
f8e413bf YS |
2045 | true); |
2046 | ||
ea2e8d92 DL |
2047 | if (dc->res_pool->dccg) |
2048 | dc->res_pool->dccg->funcs->update_dpp_dto( | |
2049 | dc->res_pool->dccg, | |
2050 | dpp->inst, | |
2051 | pipe_ctx->plane_res.bw.calc.dppclk_khz); | |
2052 | else | |
2053 | dc->res_pool->clk_mgr->clks.dppclk_khz = should_divided_by_2 ? | |
84e7fc05 DL |
2054 | dc->res_pool->clk_mgr->clks.dispclk_khz / 2 : |
2055 | dc->res_pool->clk_mgr->clks.dispclk_khz; | |
480bd0cf YS |
2056 | } |
2057 | ||
2058 | /* TODO: Need input parameter to tell current DCHUB pipe tie to which OTG | |
2059 | * VTG is within DCHUBBUB which is commond block share by each pipe HUBP. | |
2060 | * VTG is 1:1 mapping with OTG. Each pipe HUBP will select which VTG | |
2061 | */ | |
2062 | if (plane_state->update_flags.bits.full_update) { | |
c8242b98 | 2063 | hubp->funcs->hubp_vtg_sel(hubp, pipe_ctx->stream_res.tg->inst); |
d94585a0 | 2064 | |
480bd0cf YS |
2065 | hubp->funcs->hubp_setup( |
2066 | hubp, | |
2067 | &pipe_ctx->dlg_regs, | |
2068 | &pipe_ctx->ttu_regs, | |
2069 | &pipe_ctx->rq_regs, | |
2070 | &pipe_ctx->pipe_dlg_param); | |
1a1adf17 DL |
2071 | hubp->funcs->hubp_setup_interdependent( |
2072 | hubp, | |
2073 | &pipe_ctx->dlg_regs, | |
2074 | &pipe_ctx->ttu_regs); | |
480bd0cf | 2075 | } |
70ccab60 | 2076 | |
480bd0cf | 2077 | size.grph.surface_size = pipe_ctx->plane_res.scl_data.viewport; |
70ccab60 | 2078 | |
480bd0cf YS |
2079 | if (plane_state->update_flags.bits.full_update || |
2080 | plane_state->update_flags.bits.bpp_change) | |
2081 | update_dpp(dpp, plane_state); | |
2082 | ||
2083 | if (plane_state->update_flags.bits.full_update || | |
94a4ffd1 GL |
2084 | plane_state->update_flags.bits.per_pixel_alpha_change || |
2085 | plane_state->update_flags.bits.global_alpha_change) | |
c2437b1f | 2086 | dc->hwss.update_mpcc(dc, pipe_ctx); |
480bd0cf YS |
2087 | |
2088 | if (plane_state->update_flags.bits.full_update || | |
2089 | plane_state->update_flags.bits.per_pixel_alpha_change || | |
94a4ffd1 | 2090 | plane_state->update_flags.bits.global_alpha_change || |
480bd0cf YS |
2091 | plane_state->update_flags.bits.scaling_change || |
2092 | plane_state->update_flags.bits.position_change) { | |
2093 | update_scaler(pipe_ctx); | |
2094 | } | |
2095 | ||
2096 | if (plane_state->update_flags.bits.full_update || | |
16a29dd3 AJ |
2097 | plane_state->update_flags.bits.scaling_change || |
2098 | plane_state->update_flags.bits.position_change) { | |
480bd0cf YS |
2099 | hubp->funcs->mem_program_viewport( |
2100 | hubp, | |
2101 | &pipe_ctx->plane_res.scl_data.viewport, | |
2102 | &pipe_ctx->plane_res.scl_data.viewport_c); | |
2103 | } | |
2104 | ||
33fd17d9 EY |
2105 | if (pipe_ctx->stream->cursor_attributes.address.quad_part != 0) { |
2106 | dc->hwss.set_cursor_position(pipe_ctx); | |
2107 | dc->hwss.set_cursor_attribute(pipe_ctx); | |
2108 | } | |
2109 | ||
480bd0cf YS |
2110 | if (plane_state->update_flags.bits.full_update) { |
2111 | /*gamut remap*/ | |
2112 | program_gamut_remap(pipe_ctx); | |
2113 | ||
8e357610 | 2114 | dc->hwss.program_output_csc(dc, |
480bd0cf YS |
2115 | pipe_ctx, |
2116 | pipe_ctx->stream->output_color_space, | |
2117 | pipe_ctx->stream->csc_color_matrix.matrix, | |
2118 | hubp->opp_id); | |
2119 | } | |
2120 | ||
2121 | if (plane_state->update_flags.bits.full_update || | |
3aa0cadd | 2122 | plane_state->update_flags.bits.pixel_format_change || |
480bd0cf YS |
2123 | plane_state->update_flags.bits.horizontal_mirror_change || |
2124 | plane_state->update_flags.bits.rotation_change || | |
2125 | plane_state->update_flags.bits.swizzle_change || | |
e9dd9223 | 2126 | plane_state->update_flags.bits.dcc_change || |
f8668c09 EY |
2127 | plane_state->update_flags.bits.bpp_change || |
2128 | plane_state->update_flags.bits.scaling_change) { | |
480bd0cf YS |
2129 | hubp->funcs->hubp_program_surface_config( |
2130 | hubp, | |
2131 | plane_state->format, | |
2132 | &plane_state->tiling_info, | |
2133 | &size, | |
2134 | plane_state->rotation, | |
2135 | &plane_state->dcc, | |
a465feae CL |
2136 | plane_state->horizontal_mirror, |
2137 | compat_level); | |
480bd0cf | 2138 | } |
70ccab60 | 2139 | |
7f914a62 YS |
2140 | hubp->power_gated = false; |
2141 | ||
50d4cfdc YS |
2142 | dc->hwss.update_plane_addr(dc, pipe_ctx); |
2143 | ||
8eb5def9 | 2144 | if (is_pipe_tree_visible(pipe_ctx)) |
8feabd03 | 2145 | hubp->funcs->set_blank(hubp, false); |
70ccab60 HW |
2146 | } |
2147 | ||
3158223e | 2148 | static void dcn10_blank_pixel_data( |
9aef1a31 | 2149 | struct dc *dc, |
ea4a2020 | 2150 | struct pipe_ctx *pipe_ctx, |
aa5a5777 S |
2151 | bool blank) |
2152 | { | |
9aef1a31 S |
2153 | enum dc_color_space color_space; |
2154 | struct tg_color black_color = {0}; | |
ea4a2020 EB |
2155 | struct stream_resource *stream_res = &pipe_ctx->stream_res; |
2156 | struct dc_stream_state *stream = pipe_ctx->stream; | |
9aef1a31 S |
2157 | |
2158 | /* program otg blank color */ | |
2159 | color_space = stream->output_color_space; | |
2160 | color_space_to_black_color(dc, color_space, &black_color); | |
2161 | ||
12750d16 EY |
2162 | /* |
2163 | * The way 420 is packed, 2 channels carry Y component, 1 channel | |
2164 | * alternate between Cb and Cr, so both channels need the pixel | |
2165 | * value for Y | |
2166 | */ | |
2167 | if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) | |
2168 | black_color.color_r_cr = black_color.color_g_y; | |
2169 | ||
2170 | ||
3158223e EB |
2171 | if (stream_res->tg->funcs->set_blank_color) |
2172 | stream_res->tg->funcs->set_blank_color( | |
2173 | stream_res->tg, | |
9aef1a31 | 2174 | &black_color); |
aa5a5777 S |
2175 | |
2176 | if (!blank) { | |
3158223e EB |
2177 | if (stream_res->tg->funcs->set_blank) |
2178 | stream_res->tg->funcs->set_blank(stream_res->tg, blank); | |
2179 | if (stream_res->abm) | |
2180 | stream_res->abm->funcs->set_abm_level(stream_res->abm, stream->abm_level); | |
aa5a5777 | 2181 | } else if (blank) { |
3158223e EB |
2182 | if (stream_res->abm) |
2183 | stream_res->abm->funcs->set_abm_immediate_disable(stream_res->abm); | |
2184 | if (stream_res->tg->funcs->set_blank) | |
2185 | stream_res->tg->funcs->set_blank(stream_res->tg, blank); | |
aa5a5777 S |
2186 | } |
2187 | } | |
9d6f264b | 2188 | |
560a77f5 | 2189 | void set_hdr_multiplier(struct pipe_ctx *pipe_ctx) |
a4056c2a | 2190 | { |
eb0e5154 | 2191 | struct fixed31_32 multiplier = dc_fixpt_from_fraction( |
a4056c2a KK |
2192 | pipe_ctx->plane_state->sdr_white_level, 80); |
2193 | uint32_t hw_mult = 0x1f000; // 1.0 default multiplier | |
2194 | struct custom_float_format fmt; | |
2195 | ||
2196 | fmt.exponenta_bits = 6; | |
2197 | fmt.mantissa_bits = 12; | |
2198 | fmt.sign = true; | |
2199 | ||
2200 | if (pipe_ctx->plane_state->sdr_white_level > 80) | |
2201 | convert_to_custom_float_format(multiplier, &fmt, &hw_mult); | |
2202 | ||
2203 | pipe_ctx->plane_res.dpp->funcs->dpp_set_hdr_multiplier( | |
2204 | pipe_ctx->plane_res.dpp, hw_mult); | |
2205 | } | |
2206 | ||
c2437b1f EB |
2207 | void dcn10_program_pipe( |
2208 | struct dc *dc, | |
2209 | struct pipe_ctx *pipe_ctx, | |
2210 | struct dc_state *context) | |
2211 | { | |
2212 | if (pipe_ctx->plane_state->update_flags.bits.full_update) | |
2213 | dcn10_enable_plane(dc, pipe_ctx, context); | |
2214 | ||
2215 | update_dchubp_dpp(dc, pipe_ctx, context); | |
2216 | ||
2217 | set_hdr_multiplier(pipe_ctx); | |
2218 | ||
2219 | if (pipe_ctx->plane_state->update_flags.bits.full_update || | |
2220 | pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change || | |
2221 | pipe_ctx->plane_state->update_flags.bits.gamma_change) | |
2222 | dc->hwss.set_input_transfer_func(pipe_ctx, pipe_ctx->plane_state); | |
2223 | ||
2224 | /* dcn10_translate_regamma_to_hw_format takes 750us to finish | |
2225 | * only do gamma programming for full update. | |
2226 | * TODO: This can be further optimized/cleaned up | |
2227 | * Always call this for now since it does memcmp inside before | |
2228 | * doing heavy calculation and programming | |
2229 | */ | |
2230 | if (pipe_ctx->plane_state->update_flags.bits.full_update) | |
2231 | dc->hwss.set_output_transfer_func(pipe_ctx, pipe_ctx->stream); | |
2232 | } | |
2233 | ||
70ccab60 | 2234 | static void program_all_pipe_in_tree( |
fb3466a4 | 2235 | struct dc *dc, |
70ccab60 | 2236 | struct pipe_ctx *pipe_ctx, |
608ac7bb | 2237 | struct dc_state *context) |
70ccab60 | 2238 | { |
1a2c82a2 | 2239 | if (pipe_ctx->top_pipe == NULL) { |
aa5a5777 | 2240 | bool blank = !is_pipe_tree_visible(pipe_ctx); |
70ccab60 | 2241 | |
6b670fa9 HW |
2242 | pipe_ctx->stream_res.tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; |
2243 | pipe_ctx->stream_res.tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; | |
2244 | pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset; | |
2245 | pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width; | |
2246 | pipe_ctx->stream_res.tg->dlg_otg_param.signal = pipe_ctx->stream->signal; | |
cbfd33fd | 2247 | |
6b670fa9 HW |
2248 | pipe_ctx->stream_res.tg->funcs->program_global_sync( |
2249 | pipe_ctx->stream_res.tg); | |
b51adc77 | 2250 | |
ea4a2020 | 2251 | dc->hwss.blank_pixel_data(dc, pipe_ctx, blank); |
bf53769d | 2252 | |
1a2c82a2 | 2253 | } |
cbfd33fd | 2254 | |
3be5262e | 2255 | if (pipe_ctx->plane_state != NULL) { |
c2437b1f | 2256 | dcn10_program_pipe(dc, pipe_ctx, context); |
70ccab60 HW |
2257 | } |
2258 | ||
8ff15a8f | 2259 | if (pipe_ctx->bottom_pipe != NULL && pipe_ctx->bottom_pipe != pipe_ctx) { |
70ccab60 | 2260 | program_all_pipe_in_tree(dc, pipe_ctx->bottom_pipe, context); |
8ff15a8f | 2261 | } |
70ccab60 HW |
2262 | } |
2263 | ||
560a77f5 | 2264 | struct pipe_ctx *find_top_pipe_for_stream( |
e6c258cb YS |
2265 | struct dc *dc, |
2266 | struct dc_state *context, | |
2267 | const struct dc_stream_state *stream) | |
2268 | { | |
2269 | int i; | |
2270 | ||
2271 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | |
2272 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; | |
2273 | struct pipe_ctx *old_pipe_ctx = | |
2274 | &dc->current_state->res_ctx.pipe_ctx[i]; | |
2275 | ||
2276 | if (!pipe_ctx->plane_state && !old_pipe_ctx->plane_state) | |
2277 | continue; | |
2278 | ||
2279 | if (pipe_ctx->stream != stream) | |
2280 | continue; | |
2281 | ||
2282 | if (!pipe_ctx->top_pipe) | |
2283 | return pipe_ctx; | |
2284 | } | |
2285 | return NULL; | |
2286 | } | |
2287 | ||
70ccab60 | 2288 | static void dcn10_apply_ctx_for_surface( |
fb3466a4 | 2289 | struct dc *dc, |
3e9ad616 EY |
2290 | const struct dc_stream_state *stream, |
2291 | int num_planes, | |
608ac7bb | 2292 | struct dc_state *context) |
70ccab60 | 2293 | { |
e6c258cb YS |
2294 | int i; |
2295 | struct timing_generator *tg; | |
2296 | bool removed_pipe[4] = { false }; | |
e6c258cb YS |
2297 | struct pipe_ctx *top_pipe_to_program = |
2298 | find_top_pipe_for_stream(dc, context, stream); | |
5d4b05dd | 2299 | DC_LOGGER_INIT(dc->ctx->logger); |
e6c258cb YS |
2300 | |
2301 | if (!top_pipe_to_program) | |
2302 | return; | |
2303 | ||
2304 | tg = top_pipe_to_program->stream_res.tg; | |
70ccab60 | 2305 | |
8d6a741b | 2306 | dcn10_pipe_control_lock(dc, top_pipe_to_program, true); |
3e9ad616 EY |
2307 | |
2308 | if (num_planes == 0) { | |
e6c258cb | 2309 | /* OTG blank before remove all front end */ |
ea4a2020 | 2310 | dc->hwss.blank_pixel_data(dc, top_pipe_to_program, true); |
3e9ad616 | 2311 | } |
7f10f3c2 | 2312 | |
e6c258cb | 2313 | /* Disconnect unused mpcc */ |
71a2f23e | 2314 | for (i = 0; i < dc->res_pool->pipe_count; i++) { |
cfe4645e DL |
2315 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; |
2316 | struct pipe_ctx *old_pipe_ctx = | |
608ac7bb | 2317 | &dc->current_state->res_ctx.pipe_ctx[i]; |
4bdbab3e EY |
2318 | /* |
2319 | * Powergate reused pipes that are not powergated | |
2320 | * fairly hacky right now, using opp_id as indicator | |
e6c258cb YS |
2321 | * TODO: After move dc_post to dc_update, this will |
2322 | * be removed. | |
4bdbab3e | 2323 | */ |
3be5262e | 2324 | if (pipe_ctx->plane_state && !old_pipe_ctx->plane_state) { |
e6c258cb YS |
2325 | if (old_pipe_ctx->stream_res.tg == tg && |
2326 | old_pipe_ctx->plane_res.hubp && | |
2327 | old_pipe_ctx->plane_res.hubp->opp_id != 0xf) { | |
aef5f523 | 2328 | dcn10_disable_plane(dc, old_pipe_ctx); |
aa985070 EY |
2329 | /* |
2330 | * power down fe will unlock when calling reset, need | |
2331 | * to lock it back here. Messy, need rework. | |
2332 | */ | |
6b670fa9 | 2333 | pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg); |
aa985070 | 2334 | } |
4bdbab3e | 2335 | } |
cfe4645e | 2336 | |
e6c258cb YS |
2337 | if (!pipe_ctx->plane_state && |
2338 | old_pipe_ctx->plane_state && | |
2339 | old_pipe_ctx->stream_res.tg == tg) { | |
7f10f3c2 | 2340 | |
c2437b1f | 2341 | dc->hwss.plane_atomic_disconnect(dc, old_pipe_ctx); |
e6c258cb | 2342 | removed_pipe[i] = true; |
cfe4645e | 2343 | |
c910a717 | 2344 | DC_LOG_DC("Reset mpcc for pipe %d\n", |
cfe4645e DL |
2345 | old_pipe_ctx->pipe_idx); |
2346 | } | |
71a2f23e | 2347 | } |
cfe4645e | 2348 | |
457fbe76 | 2349 | if (num_planes > 0) |
e6c258cb YS |
2350 | program_all_pipe_in_tree(dc, top_pipe_to_program, context); |
2351 | ||
8d6a741b | 2352 | dcn10_pipe_control_lock(dc, top_pipe_to_program, false); |
70ccab60 | 2353 | |
1a1adf17 DL |
2354 | if (top_pipe_to_program->plane_state && |
2355 | top_pipe_to_program->plane_state->update_flags.bits.full_update) | |
2356 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | |
2357 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; | |
f5c412ac | 2358 | tg = pipe_ctx->stream_res.tg; |
1a1adf17 | 2359 | /* Skip inactive pipes and ones already updated */ |
6fd3583b | 2360 | if (!pipe_ctx->stream || pipe_ctx->stream == stream |
f5c412ac RL |
2361 | || !pipe_ctx->plane_state |
2362 | || !tg->funcs->is_tg_enabled(tg)) | |
1a1adf17 DL |
2363 | continue; |
2364 | ||
f5c412ac | 2365 | tg->funcs->lock(tg); |
1a1adf17 DL |
2366 | |
2367 | pipe_ctx->plane_res.hubp->funcs->hubp_setup_interdependent( | |
2368 | pipe_ctx->plane_res.hubp, | |
2369 | &pipe_ctx->dlg_regs, | |
2370 | &pipe_ctx->ttu_regs); | |
1a1adf17 | 2371 | |
f5c412ac RL |
2372 | tg->funcs->unlock(tg); |
2373 | } | |
1a1adf17 | 2374 | |
5cc2687c YS |
2375 | if (num_planes == 0) |
2376 | false_optc_underflow_wa(dc, stream, tg); | |
2377 | ||
e21db6db | 2378 | for (i = 0; i < dc->res_pool->pipe_count; i++) |
8e504bcc | 2379 | if (removed_pipe[i]) |
e21db6db | 2380 | dcn10_disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]); |
7144d3cf | 2381 | |
e21db6db DL |
2382 | if (dc->hwseq->wa.DEGVIDCN10_254) |
2383 | hubbub1_wm_change_req_wa(dc->res_pool->hubbub); | |
70ccab60 HW |
2384 | } |
2385 | ||
9566b675 | 2386 | static void dcn10_prepare_bandwidth( |
fb3466a4 | 2387 | struct dc *dc, |
9566b675 | 2388 | struct dc_state *context) |
70ccab60 | 2389 | { |
c910a717 | 2390 | if (dc->debug.sanity_checks) |
ea00f297 | 2391 | dcn10_verify_allow_pstate_change_high(dc); |
665da60f | 2392 | |
e21db6db DL |
2393 | if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { |
2394 | if (context->stream_count == 0) | |
2395 | context->bw.dcn.clk.phyclk_khz = 0; | |
70ccab60 | 2396 | |
84e7fc05 DL |
2397 | dc->res_pool->clk_mgr->funcs->update_clocks( |
2398 | dc->res_pool->clk_mgr, | |
24f7dd7e | 2399 | context, |
9566b675 DL |
2400 | false); |
2401 | } | |
2402 | ||
2403 | hubbub1_program_watermarks(dc->res_pool->hubbub, | |
2404 | &context->bw.dcn.watermarks, | |
2405 | dc->res_pool->ref_clock_inKhz / 1000, | |
2406 | true); | |
2407 | ||
2408 | if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE) | |
2409 | dcn_bw_notify_pplib_of_wm_ranges(dc); | |
2410 | ||
2411 | if (dc->debug.sanity_checks) | |
2412 | dcn10_verify_allow_pstate_change_high(dc); | |
2413 | } | |
2414 | ||
2415 | static void dcn10_optimize_bandwidth( | |
2416 | struct dc *dc, | |
2417 | struct dc_state *context) | |
2418 | { | |
2419 | if (dc->debug.sanity_checks) | |
2420 | dcn10_verify_allow_pstate_change_high(dc); | |
2421 | ||
2422 | if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { | |
2423 | if (context->stream_count == 0) | |
2424 | context->bw.dcn.clk.phyclk_khz = 0; | |
2425 | ||
84e7fc05 DL |
2426 | dc->res_pool->clk_mgr->funcs->update_clocks( |
2427 | dc->res_pool->clk_mgr, | |
9566b675 DL |
2428 | context, |
2429 | true); | |
e21db6db | 2430 | } |
fab55d61 | 2431 | |
e21db6db DL |
2432 | hubbub1_program_watermarks(dc->res_pool->hubbub, |
2433 | &context->bw.dcn.watermarks, | |
2434 | dc->res_pool->ref_clock_inKhz / 1000, | |
2435 | true); | |
2b13d7d3 | 2436 | |
24f7dd7e DL |
2437 | if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE) |
2438 | dcn_bw_notify_pplib_of_wm_ranges(dc); | |
2439 | ||
c910a717 | 2440 | if (dc->debug.sanity_checks) |
ea00f297 | 2441 | dcn10_verify_allow_pstate_change_high(dc); |
70ccab60 HW |
2442 | } |
2443 | ||
70ccab60 HW |
2444 | static void set_drr(struct pipe_ctx **pipe_ctx, |
2445 | int num_pipes, int vmin, int vmax) | |
2446 | { | |
2447 | int i = 0; | |
2448 | struct drr_params params = {0}; | |
98e6436d AK |
2449 | // DRR should set trigger event to monitor surface update event |
2450 | unsigned int event_triggers = 0x80; | |
70ccab60 HW |
2451 | |
2452 | params.vertical_total_max = vmax; | |
2453 | params.vertical_total_min = vmin; | |
2454 | ||
2455 | /* TODO: If multiple pipes are to be supported, you need | |
98e6436d AK |
2456 | * some GSL stuff. Static screen triggers may be programmed differently |
2457 | * as well. | |
70ccab60 HW |
2458 | */ |
2459 | for (i = 0; i < num_pipes; i++) { | |
98e6436d AK |
2460 | pipe_ctx[i]->stream_res.tg->funcs->set_drr( |
2461 | pipe_ctx[i]->stream_res.tg, ¶ms); | |
2462 | if (vmax != 0 && vmin != 0) | |
2463 | pipe_ctx[i]->stream_res.tg->funcs->set_static_screen_control( | |
2464 | pipe_ctx[i]->stream_res.tg, | |
2465 | event_triggers); | |
70ccab60 HW |
2466 | } |
2467 | } | |
2468 | ||
2469 | static void get_position(struct pipe_ctx **pipe_ctx, | |
2470 | int num_pipes, | |
2471 | struct crtc_position *position) | |
2472 | { | |
2473 | int i = 0; | |
2474 | ||
2475 | /* TODO: handle pipes > 1 | |
2476 | */ | |
2477 | for (i = 0; i < num_pipes; i++) | |
6b670fa9 | 2478 | pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position); |
70ccab60 HW |
2479 | } |
2480 | ||
2481 | static void set_static_screen_control(struct pipe_ctx **pipe_ctx, | |
2482 | int num_pipes, const struct dc_static_screen_events *events) | |
2483 | { | |
2484 | unsigned int i; | |
2485 | unsigned int value = 0; | |
2486 | ||
2487 | if (events->surface_update) | |
2488 | value |= 0x80; | |
2489 | if (events->cursor_update) | |
2490 | value |= 0x2; | |
ed8462ac CL |
2491 | if (events->force_trigger) |
2492 | value |= 0x1; | |
70ccab60 HW |
2493 | |
2494 | for (i = 0; i < num_pipes; i++) | |
6b670fa9 HW |
2495 | pipe_ctx[i]->stream_res.tg->funcs-> |
2496 | set_static_screen_control(pipe_ctx[i]->stream_res.tg, value); | |
70ccab60 HW |
2497 | } |
2498 | ||
4fac6da2 | 2499 | static void dcn10_config_stereo_parameters( |
0971c40e | 2500 | struct dc_stream_state *stream, struct crtc_stereo_flags *flags) |
7f5c22d1 | 2501 | { |
4fa086b9 | 2502 | enum view_3d_format view_format = stream->view_format; |
7f5c22d1 | 2503 | enum dc_timing_3d_format timing_3d_format =\ |
4fa086b9 | 2504 | stream->timing.timing_3d_format; |
7f5c22d1 VP |
2505 | bool non_stereo_timing = false; |
2506 | ||
2507 | if (timing_3d_format == TIMING_3D_FORMAT_NONE || | |
2508 | timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE || | |
2509 | timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM) | |
2510 | non_stereo_timing = true; | |
2511 | ||
2512 | if (non_stereo_timing == false && | |
2513 | view_format == VIEW_3D_FORMAT_FRAME_SEQUENTIAL) { | |
2514 | ||
2515 | flags->PROGRAM_STEREO = 1; | |
2516 | flags->PROGRAM_POLARITY = 1; | |
2517 | if (timing_3d_format == TIMING_3D_FORMAT_INBAND_FA || | |
2518 | timing_3d_format == TIMING_3D_FORMAT_DP_HDMI_INBAND_FA || | |
2519 | timing_3d_format == TIMING_3D_FORMAT_SIDEBAND_FA) { | |
2520 | enum display_dongle_type dongle = \ | |
d0778ebf | 2521 | stream->sink->link->ddc->dongle_type; |
7f5c22d1 VP |
2522 | if (dongle == DISPLAY_DONGLE_DP_VGA_CONVERTER || |
2523 | dongle == DISPLAY_DONGLE_DP_DVI_CONVERTER || | |
2524 | dongle == DISPLAY_DONGLE_DP_HDMI_CONVERTER) | |
2525 | flags->DISABLE_STEREO_DP_SYNC = 1; | |
2526 | } | |
2527 | flags->RIGHT_EYE_POLARITY =\ | |
4fa086b9 | 2528 | stream->timing.flags.RIGHT_EYE_3D_POLARITY; |
7f5c22d1 VP |
2529 | if (timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) |
2530 | flags->FRAME_PACKED = 1; | |
2531 | } | |
2532 | ||
2533 | return; | |
2534 | } | |
2535 | ||
fb3466a4 | 2536 | static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc) |
7f5c22d1 VP |
2537 | { |
2538 | struct crtc_stereo_flags flags = { 0 }; | |
0971c40e | 2539 | struct dc_stream_state *stream = pipe_ctx->stream; |
7f5c22d1 VP |
2540 | |
2541 | dcn10_config_stereo_parameters(stream, &flags); | |
2542 | ||
72d520d4 | 2543 | pipe_ctx->stream_res.opp->funcs->opp_program_stereo( |
a6a6cb34 | 2544 | pipe_ctx->stream_res.opp, |
7f5c22d1 | 2545 | flags.PROGRAM_STEREO == 1 ? true:false, |
72d520d4 | 2546 | &stream->timing); |
7f5c22d1 | 2547 | |
6b670fa9 HW |
2548 | pipe_ctx->stream_res.tg->funcs->program_stereo( |
2549 | pipe_ctx->stream_res.tg, | |
4fa086b9 | 2550 | &stream->timing, |
7f5c22d1 VP |
2551 | &flags); |
2552 | ||
7f5c22d1 VP |
2553 | return; |
2554 | } | |
2555 | ||
e07f541f YS |
2556 | static struct hubp *get_hubp_by_inst(struct resource_pool *res_pool, int mpcc_inst) |
2557 | { | |
2558 | int i; | |
2559 | ||
2560 | for (i = 0; i < res_pool->pipe_count; i++) { | |
2561 | if (res_pool->hubps[i]->inst == mpcc_inst) | |
2562 | return res_pool->hubps[i]; | |
2563 | } | |
2564 | ASSERT(false); | |
2565 | return NULL; | |
2566 | } | |
2567 | ||
6be425f3 | 2568 | static void dcn10_wait_for_mpcc_disconnect( |
fb3466a4 | 2569 | struct dc *dc, |
6be425f3 EY |
2570 | struct resource_pool *res_pool, |
2571 | struct pipe_ctx *pipe_ctx) | |
87480687 | 2572 | { |
e07f541f | 2573 | int mpcc_inst; |
87480687 | 2574 | |
fb3466a4 | 2575 | if (dc->debug.sanity_checks) { |
ea00f297 | 2576 | dcn10_verify_allow_pstate_change_high(dc); |
665da60f CM |
2577 | } |
2578 | ||
a6a6cb34 | 2579 | if (!pipe_ctx->stream_res.opp) |
6be425f3 EY |
2580 | return; |
2581 | ||
e07f541f YS |
2582 | for (mpcc_inst = 0; mpcc_inst < MAX_PIPES; mpcc_inst++) { |
2583 | if (pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst]) { | |
2584 | struct hubp *hubp = get_hubp_by_inst(res_pool, mpcc_inst); | |
2585 | ||
2586 | res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, mpcc_inst); | |
2587 | pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst] = false; | |
2588 | hubp->funcs->set_blank(hubp, true); | |
2f3fd67a | 2589 | /*DC_LOG_ERROR(dc->ctx->logger, |
6be425f3 EY |
2590 | "[debug_mpo: wait_for_mpcc finished waiting on mpcc %d]\n", |
2591 | i);*/ | |
87480687 EY |
2592 | } |
2593 | } | |
6be425f3 | 2594 | |
fb3466a4 | 2595 | if (dc->debug.sanity_checks) { |
ea00f297 | 2596 | dcn10_verify_allow_pstate_change_high(dc); |
665da60f CM |
2597 | } |
2598 | ||
87480687 EY |
2599 | } |
2600 | ||
4fac6da2 | 2601 | static bool dcn10_dummy_display_power_gating( |
fb3466a4 | 2602 | struct dc *dc, |
4fac6da2 DL |
2603 | uint8_t controller_id, |
2604 | struct dc_bios *dcb, | |
2b13d7d3 TC |
2605 | enum pipe_gating_control power_gating) |
2606 | { | |
2607 | return true; | |
2608 | } | |
2609 | ||
33fd17d9 | 2610 | static void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) |
2b13d7d3 | 2611 | { |
3be5262e | 2612 | struct dc_plane_state *plane_state = pipe_ctx->plane_state; |
6b670fa9 | 2613 | struct timing_generator *tg = pipe_ctx->stream_res.tg; |
68199bd1 | 2614 | bool flip_pending; |
2b13d7d3 | 2615 | |
3be5262e | 2616 | if (plane_state == NULL) |
2b13d7d3 TC |
2617 | return; |
2618 | ||
68199bd1 | 2619 | flip_pending = pipe_ctx->plane_res.hubp->funcs->hubp_is_flip_pending( |
8feabd03 | 2620 | pipe_ctx->plane_res.hubp); |
2b13d7d3 | 2621 | |
68199bd1 TC |
2622 | plane_state->status.is_flip_pending = flip_pending; |
2623 | ||
2624 | if (!flip_pending) | |
2625 | plane_state->status.current_address = plane_state->status.requested_address; | |
2626 | ||
2627 | if (plane_state->status.current_address.type == PLN_ADDR_TYPE_GRPH_STEREO && | |
2b13d7d3 | 2628 | tg->funcs->is_stereo_left_eye) { |
3be5262e | 2629 | plane_state->status.is_right_eye = |
6b670fa9 | 2630 | !tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg); |
2b13d7d3 TC |
2631 | } |
2632 | } | |
4fac6da2 | 2633 | |
33fd17d9 | 2634 | static void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data) |
afa9104b | 2635 | { |
7f93c1de CL |
2636 | if (hws->ctx->dc->res_pool->hubbub != NULL) { |
2637 | struct hubp *hubp = hws->ctx->dc->res_pool->hubps[0]; | |
2638 | ||
2639 | if (hubp->funcs->hubp_update_dchub) | |
2640 | hubp->funcs->hubp_update_dchub(hubp, dh_data); | |
2641 | else | |
2642 | hubbub1_update_dchub(hws->ctx->dc->res_pool->hubbub, dh_data); | |
2643 | } | |
afa9104b | 2644 | } |
0cb8a881 | 2645 | |
33fd17d9 EY |
2646 | static void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx) |
2647 | { | |
2648 | struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position; | |
2649 | struct hubp *hubp = pipe_ctx->plane_res.hubp; | |
2650 | struct dpp *dpp = pipe_ctx->plane_res.dpp; | |
2651 | struct dc_cursor_mi_param param = { | |
2652 | .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_khz, | |
2653 | .ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clock_inKhz, | |
39a9f4d8 DL |
2654 | .viewport = pipe_ctx->plane_res.scl_data.viewport, |
2655 | .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz, | |
2656 | .v_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.vert, | |
08ed681c DL |
2657 | .rotation = pipe_ctx->plane_state->rotation, |
2658 | .mirror = pipe_ctx->plane_state->horizontal_mirror | |
33fd17d9 EY |
2659 | }; |
2660 | ||
94a4ffd1 GL |
2661 | pos_cpy.x -= pipe_ctx->plane_state->dst_rect.x; |
2662 | pos_cpy.y -= pipe_ctx->plane_state->dst_rect.y; | |
2663 | ||
33fd17d9 EY |
2664 | if (pipe_ctx->plane_state->address.type |
2665 | == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) | |
2666 | pos_cpy.enable = false; | |
2667 | ||
33fd17d9 | 2668 | hubp->funcs->set_cursor_position(hubp, &pos_cpy, ¶m); |
94a4ffd1 | 2669 | dpp->funcs->set_cursor_position(dpp, &pos_cpy, ¶m, hubp->curs_attr.width, hubp->curs_attr.height); |
33fd17d9 EY |
2670 | } |
2671 | ||
2672 | static void dcn10_set_cursor_attribute(struct pipe_ctx *pipe_ctx) | |
2673 | { | |
2674 | struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes; | |
2675 | ||
2676 | pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes( | |
2677 | pipe_ctx->plane_res.hubp, attributes); | |
2678 | pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes( | |
2679 | pipe_ctx->plane_res.dpp, attributes->color_format); | |
2680 | } | |
2681 | ||
6d92b5c2 KK |
2682 | static void dcn10_set_cursor_sdr_white_level(struct pipe_ctx *pipe_ctx) |
2683 | { | |
2684 | uint32_t sdr_white_level = pipe_ctx->stream->cursor_attributes.sdr_white_level; | |
2685 | struct fixed31_32 multiplier; | |
2686 | struct dpp_cursor_attributes opt_attr = { 0 }; | |
2687 | uint32_t hw_scale = 0x3c00; // 1.0 default multiplier | |
2688 | struct custom_float_format fmt; | |
2689 | ||
2690 | if (!pipe_ctx->plane_res.dpp->funcs->set_optional_cursor_attributes) | |
2691 | return; | |
2692 | ||
2693 | fmt.exponenta_bits = 5; | |
2694 | fmt.mantissa_bits = 10; | |
2695 | fmt.sign = true; | |
2696 | ||
2697 | if (sdr_white_level > 80) { | |
2698 | multiplier = dc_fixpt_from_fraction(sdr_white_level, 80); | |
2699 | convert_to_custom_float_format(multiplier, &fmt, &hw_scale); | |
2700 | } | |
2701 | ||
2702 | opt_attr.scale = hw_scale; | |
2703 | opt_attr.bias = 0; | |
2704 | ||
2705 | pipe_ctx->plane_res.dpp->funcs->set_optional_cursor_attributes( | |
2706 | pipe_ctx->plane_res.dpp, &opt_attr); | |
2707 | } | |
2708 | ||
70ccab60 | 2709 | static const struct hw_sequencer_funcs dcn10_funcs = { |
1bf56e62 | 2710 | .program_gamut_remap = program_gamut_remap, |
b02c3b05 | 2711 | .init_hw = dcn10_init_hw, |
70ccab60 HW |
2712 | .apply_ctx_to_hw = dce110_apply_ctx_to_hw, |
2713 | .apply_ctx_for_surface = dcn10_apply_ctx_for_surface, | |
503a7c6f | 2714 | .update_plane_addr = dcn10_update_plane_addr, |
c2437b1f | 2715 | .plane_atomic_disconnect = hwss1_plane_atomic_disconnect, |
afa9104b | 2716 | .update_dchub = dcn10_update_dchub, |
c2437b1f | 2717 | .update_mpcc = dcn10_update_mpcc, |
2b13d7d3 | 2718 | .update_pending_status = dcn10_update_pending_status, |
70ccab60 HW |
2719 | .set_input_transfer_func = dcn10_set_input_transfer_func, |
2720 | .set_output_transfer_func = dcn10_set_output_transfer_func, | |
8e357610 | 2721 | .program_output_csc = dcn10_program_output_csc, |
70ccab60 HW |
2722 | .power_down = dce110_power_down, |
2723 | .enable_accelerated_mode = dce110_enable_accelerated_mode, | |
2724 | .enable_timing_synchronization = dcn10_enable_timing_synchronization, | |
fa2123db | 2725 | .enable_per_frame_crtc_position_reset = dcn10_enable_per_frame_crtc_position_reset, |
70ccab60 HW |
2726 | .update_info_frame = dce110_update_info_frame, |
2727 | .enable_stream = dce110_enable_stream, | |
2728 | .disable_stream = dce110_disable_stream, | |
2729 | .unblank_stream = dce110_unblank_stream, | |
41b49742 | 2730 | .blank_stream = dce110_blank_stream, |
1a05873f AK |
2731 | .enable_audio_stream = dce110_enable_audio_stream, |
2732 | .disable_audio_stream = dce110_disable_audio_stream, | |
4fac6da2 | 2733 | .enable_display_power_gating = dcn10_dummy_display_power_gating, |
7f914a62 | 2734 | .disable_plane = dcn10_disable_plane, |
3158223e | 2735 | .blank_pixel_data = dcn10_blank_pixel_data, |
70ccab60 | 2736 | .pipe_control_lock = dcn10_pipe_control_lock, |
9566b675 DL |
2737 | .prepare_bandwidth = dcn10_prepare_bandwidth, |
2738 | .optimize_bandwidth = dcn10_optimize_bandwidth, | |
70ccab60 | 2739 | .reset_hw_ctx_wrap = reset_hw_ctx_wrap, |
3158223e | 2740 | .enable_stream_timing = dcn10_enable_stream_timing, |
70ccab60 HW |
2741 | .set_drr = set_drr, |
2742 | .get_position = get_position, | |
7f5c22d1 | 2743 | .set_static_screen_control = set_static_screen_control, |
15e17335 CL |
2744 | .setup_stereo = dcn10_setup_stereo, |
2745 | .set_avmute = dce110_set_avmute, | |
87480687 | 2746 | .log_hw_state = dcn10_log_hw_state, |
dd730435 | 2747 | .get_hw_state = dcn10_get_hw_state, |
eb6b29d6 | 2748 | .clear_status_bits = dcn10_clear_status_bits, |
41f97c07 | 2749 | .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect, |
87401969 | 2750 | .edp_backlight_control = hwss_edp_backlight_control, |
904623ee YS |
2751 | .edp_power_control = hwss_edp_power_control, |
2752 | .edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready, | |
33fd17d9 | 2753 | .set_cursor_position = dcn10_set_cursor_position, |
6d92b5c2 KK |
2754 | .set_cursor_attribute = dcn10_set_cursor_attribute, |
2755 | .set_cursor_sdr_white_level = dcn10_set_cursor_sdr_white_level | |
70ccab60 HW |
2756 | }; |
2757 | ||
2758 | ||
fb3466a4 | 2759 | void dcn10_hw_sequencer_construct(struct dc *dc) |
70ccab60 HW |
2760 | { |
2761 | dc->hwss = dcn10_funcs; | |
70ccab60 HW |
2762 | } |
2763 |