File: | dev/pci/drm/amd/display/dc/dcn201/dcn201_hwseq.c |
Warning: | line 545, column 2 Value stored to 'hubp' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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" |
27 | #include "basics/dc_common.h" |
28 | #include "core_types.h" |
29 | #include "resource.h" |
30 | #include "dcn201_hwseq.h" |
31 | #include "dcn201_optc.h" |
32 | #include "dce/dce_hwseq.h" |
33 | #include "hubp.h" |
34 | #include "dchubbub.h" |
35 | #include "timing_generator.h" |
36 | #include "opp.h" |
37 | #include "ipp.h" |
38 | #include "mpc.h" |
39 | #include "dccg.h" |
40 | #include "clk_mgr.h" |
41 | #include "reg_helper.h" |
42 | |
43 | #define CTXhws->ctx \ |
44 | hws->ctx |
45 | |
46 | #define REG(reg)hws->regs->reg\ |
47 | hws->regs->reg |
48 | |
49 | #define DC_LOGGERdc->ctx->logger \ |
50 | dc->ctx->logger |
51 | |
52 | #undef FN |
53 | #define FN(reg_name, field_name)hws->shifts->field_name, hws->masks->field_name \ |
54 | hws->shifts->field_name, hws->masks->field_name |
55 | |
56 | static bool_Bool patch_address_for_sbs_tb_stereo( |
57 | struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOCunion large_integer *addr) |
58 | { |
59 | struct dc_plane_state *plane_state = pipe_ctx->plane_state; |
60 | bool_Bool sec_split = pipe_ctx->top_pipe && |
61 | pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state; |
62 | |
63 | if (sec_split && plane_state->address.type == PLN_ADDR_TYPE_GRPH_STEREO && |
64 | (pipe_ctx->stream->timing.timing_3d_format == |
65 | TIMING_3D_FORMAT_SIDE_BY_SIDE || |
66 | pipe_ctx->stream->timing.timing_3d_format == |
67 | TIMING_3D_FORMAT_TOP_AND_BOTTOM)) { |
68 | *addr = plane_state->address.grph_stereo.left_addr; |
69 | plane_state->address.grph_stereo.left_addr = |
70 | plane_state->address.grph_stereo.right_addr; |
71 | return true1; |
72 | } else { |
73 | if (pipe_ctx->stream->view_format != VIEW_3D_FORMAT_NONE && |
74 | plane_state->address.type != PLN_ADDR_TYPE_GRPH_STEREO) { |
75 | plane_state->address.type = PLN_ADDR_TYPE_GRPH_STEREO; |
76 | plane_state->address.grph_stereo.right_addr = |
77 | plane_state->address.grph_stereo.left_addr; |
78 | plane_state->address.grph_stereo.right_meta_addr = |
79 | plane_state->address.grph_stereo.left_meta_addr; |
80 | } |
81 | } |
82 | return false0; |
83 | } |
84 | |
85 | static bool_Bool gpu_addr_to_uma(struct dce_hwseq *hwseq, |
86 | PHYSICAL_ADDRESS_LOCunion large_integer *addr) |
87 | { |
88 | bool_Bool is_in_uma; |
89 | |
90 | if (hwseq->fb_base.quad_part <= addr->quad_part && |
91 | addr->quad_part < hwseq->fb_top.quad_part) { |
92 | addr->quad_part -= hwseq->fb_base.quad_part; |
93 | addr->quad_part += hwseq->fb_offset.quad_part; |
94 | is_in_uma = true1; |
95 | } else if (hwseq->fb_offset.quad_part <= addr->quad_part && |
96 | addr->quad_part <= hwseq->uma_top.quad_part) { |
97 | is_in_uma = true1; |
98 | } else { |
99 | is_in_uma = false0; |
100 | } |
101 | return is_in_uma; |
102 | } |
103 | |
104 | static void plane_address_in_gpu_space_to_uma(struct dce_hwseq *hwseq, |
105 | struct dc_plane_address *addr) |
106 | { |
107 | switch (addr->type) { |
108 | case PLN_ADDR_TYPE_GRAPHICS: |
109 | gpu_addr_to_uma(hwseq, &addr->grph.addr); |
110 | gpu_addr_to_uma(hwseq, &addr->grph.meta_addr); |
111 | break; |
112 | case PLN_ADDR_TYPE_GRPH_STEREO: |
113 | gpu_addr_to_uma(hwseq, &addr->grph_stereo.left_addr); |
114 | gpu_addr_to_uma(hwseq, &addr->grph_stereo.left_meta_addr); |
115 | gpu_addr_to_uma(hwseq, &addr->grph_stereo.right_addr); |
116 | gpu_addr_to_uma(hwseq, &addr->grph_stereo.right_meta_addr); |
117 | break; |
118 | case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE: |
119 | gpu_addr_to_uma(hwseq, &addr->video_progressive.luma_addr); |
120 | gpu_addr_to_uma(hwseq, &addr->video_progressive.luma_meta_addr); |
121 | gpu_addr_to_uma(hwseq, &addr->video_progressive.chroma_addr); |
122 | gpu_addr_to_uma(hwseq, &addr->video_progressive.chroma_meta_addr); |
123 | break; |
124 | default: |
125 | BREAK_TO_DEBUGGER()do { ___drm_dbg(((void *)0), DRM_UT_DRIVER, "%s():%d\n", __func__ , 125); do {} while (0); } while (0); |
126 | break; |
127 | } |
128 | } |
129 | |
130 | void dcn201_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx) |
131 | { |
132 | bool_Bool addr_patched = false0; |
133 | PHYSICAL_ADDRESS_LOCunion large_integer addr; |
134 | struct dc_plane_state *plane_state = pipe_ctx->plane_state; |
135 | struct dce_hwseq *hws = dc->hwseq; |
136 | struct dc_plane_address uma; |
137 | |
138 | if (plane_state == NULL((void *)0)) |
139 | return; |
140 | |
141 | uma = plane_state->address; |
142 | addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr); |
143 | |
144 | plane_address_in_gpu_space_to_uma(hws, &uma); |
145 | |
146 | pipe_ctx->plane_res.hubp->funcs->hubp_program_surface_flip_and_addr( |
147 | pipe_ctx->plane_res.hubp, |
148 | &uma, |
149 | plane_state->flip_immediate); |
150 | |
151 | plane_state->status.requested_address = plane_state->address; |
152 | |
153 | if (plane_state->flip_immediate) |
154 | plane_state->status.current_address = plane_state->address; |
155 | |
156 | if (addr_patched) |
157 | pipe_ctx->plane_state->address.grph_stereo.left_addr = addr; |
158 | } |
159 | |
160 | /* Blank pixel data during initialization */ |
161 | void dcn201_init_blank( |
162 | struct dc *dc, |
163 | struct timing_generator *tg) |
164 | { |
165 | struct dce_hwseq *hws = dc->hwseq; |
166 | enum dc_color_space color_space; |
167 | struct tg_color black_color = {0}; |
168 | struct output_pixel_processor *opp = NULL((void *)0); |
169 | uint32_t num_opps, opp_id_src0, opp_id_src1; |
170 | uint32_t otg_active_width, otg_active_height; |
171 | |
172 | /* program opp dpg blank color */ |
173 | color_space = COLOR_SPACE_SRGB; |
174 | color_space_to_black_color(dc, color_space, &black_color); |
175 | |
176 | /* get the OTG active size */ |
177 | tg->funcs->get_otg_active_size(tg, |
178 | &otg_active_width, |
179 | &otg_active_height); |
180 | |
181 | /* get the OPTC source */ |
182 | tg->funcs->get_optc_source(tg, &num_opps, &opp_id_src0, &opp_id_src1); |
183 | ASSERT(opp_id_src0 < dc->res_pool->res_cap->num_opp)do { if (({ static int __warned; int __ret = !!(!(opp_id_src0 < dc->res_pool->res_cap->num_opp)); if (__ret && !__warned) { printf("WARNING %s failed at %s:%d\n", "!(opp_id_src0 < dc->res_pool->res_cap->num_opp)" , "/usr/src/sys/dev/pci/drm/amd/display/dc/dcn201/dcn201_hwseq.c" , 183); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do {} while (0); } while (0); |
184 | opp = dc->res_pool->opps[opp_id_src0]; |
185 | |
186 | opp->funcs->opp_set_disp_pattern_generator( |
187 | opp, |
188 | CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR, |
189 | CONTROLLER_DP_COLOR_SPACE_UDEFINED, |
190 | COLOR_DEPTH_UNDEFINED, |
191 | &black_color, |
192 | otg_active_width, |
193 | otg_active_height, |
194 | 0); |
195 | |
196 | hws->funcs.wait_for_blank_complete(opp); |
197 | } |
198 | |
199 | static void read_mmhub_vm_setup(struct dce_hwseq *hws) |
200 | { |
201 | uint32_t fb_base = REG_READ(MC_VM_FB_LOCATION_BASE)dm_read_reg_func(hws->ctx, hws->regs->MC_VM_FB_LOCATION_BASE , __func__); |
202 | uint32_t fb_top = REG_READ(MC_VM_FB_LOCATION_TOP)dm_read_reg_func(hws->ctx, hws->regs->MC_VM_FB_LOCATION_TOP , __func__); |
203 | uint32_t fb_offset = REG_READ(MC_VM_FB_OFFSET)dm_read_reg_func(hws->ctx, hws->regs->MC_VM_FB_OFFSET , __func__); |
204 | |
205 | /* MC_VM_FB_LOCATION_TOP is in pages, actual top should add 1 */ |
206 | fb_top++; |
207 | |
208 | /* bit 23:0 in register map to bit 47:24 in address */ |
209 | hws->fb_base.low_part = fb_base; |
210 | hws->fb_base.quad_part <<= 24; |
211 | |
212 | hws->fb_top.low_part = fb_top; |
213 | hws->fb_top.quad_part <<= 24; |
214 | hws->fb_offset.low_part = fb_offset; |
215 | hws->fb_offset.quad_part <<= 24; |
216 | |
217 | hws->uma_top.quad_part = hws->fb_top.quad_part |
218 | - hws->fb_base.quad_part + hws->fb_offset.quad_part; |
219 | } |
220 | |
221 | void dcn201_init_hw(struct dc *dc) |
222 | { |
223 | int i, j; |
224 | struct dce_hwseq *hws = dc->hwseq; |
225 | struct resource_pool *res_pool = dc->res_pool; |
226 | struct dc_state *context = dc->current_state; |
227 | |
228 | if (res_pool->dccg->funcs->dccg_init) |
229 | res_pool->dccg->funcs->dccg_init(res_pool->dccg); |
230 | |
231 | if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks) |
232 | dc->clk_mgr->funcs->init_clocks(dc->clk_mgr); |
233 | |
234 | if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)(dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS)) { |
235 | REG_WRITE(RBBMIF_TIMEOUT_DIS, 0xFFFFFFFF)dm_write_reg_func(hws->ctx, hws->regs->RBBMIF_TIMEOUT_DIS , 0xFFFFFFFF, __func__); |
236 | REG_WRITE(RBBMIF_TIMEOUT_DIS_2, 0xFFFFFFFF)dm_write_reg_func(hws->ctx, hws->regs->RBBMIF_TIMEOUT_DIS_2 , 0xFFFFFFFF, __func__); |
237 | |
238 | hws->funcs.dccg_init(hws); |
239 | |
240 | REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, 2)generic_reg_update_ex(hws->ctx, hws->regs->DCHUBBUB_GLOBAL_TIMER_CNTL , 1, hws->shifts->DCHUBBUB_GLOBAL_TIMER_REFDIV, hws-> masks->DCHUBBUB_GLOBAL_TIMER_REFDIV, 2); |
241 | REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1)generic_reg_update_ex(hws->ctx, hws->regs->DCHUBBUB_GLOBAL_TIMER_CNTL , 1, hws->shifts->DCHUBBUB_GLOBAL_TIMER_ENABLE, hws-> masks->DCHUBBUB_GLOBAL_TIMER_ENABLE, 1); |
242 | REG_WRITE(REFCLK_CNTL, 0)dm_write_reg_func(hws->ctx, hws->regs->REFCLK_CNTL, 0 , __func__); |
243 | } else { |
244 | hws->funcs.bios_golden_init(dc); |
245 | |
246 | if (dc->ctx->dc_bios->fw_info_valid) { |
247 | res_pool->ref_clocks.xtalin_clock_inKhz = |
248 | dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency; |
249 | |
250 | if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)(dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS)) { |
251 | if (res_pool->dccg && res_pool->hubbub) { |
252 | (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg, |
253 | dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency, |
254 | &res_pool->ref_clocks.dccg_ref_clock_inKhz); |
255 | |
256 | (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub, |
257 | res_pool->ref_clocks.dccg_ref_clock_inKhz, |
258 | &res_pool->ref_clocks.dchub_ref_clock_inKhz); |
259 | } else { |
260 | res_pool->ref_clocks.dccg_ref_clock_inKhz = |
261 | res_pool->ref_clocks.xtalin_clock_inKhz; |
262 | res_pool->ref_clocks.dchub_ref_clock_inKhz = |
263 | res_pool->ref_clocks.xtalin_clock_inKhz; |
264 | } |
265 | } |
266 | } else |
267 | ASSERT_CRITICAL(false)do { if (({ int __ret = !!(!(0)); if (__ret) printf("WARNING %s failed at %s:%d\n" , "!(0)", "/usr/src/sys/dev/pci/drm/amd/display/dc/dcn201/dcn201_hwseq.c" , 267); __builtin_expect(!!(__ret), 0); })) do {} while (0); } while (0); |
268 | for (i = 0; i < dc->link_count; i++) { |
269 | /* Power up AND update implementation according to the |
270 | * required signal (which may be different from the |
271 | * default signal on connector). |
272 | */ |
273 | struct dc_link *link = dc->links[i]; |
274 | |
275 | link->link_enc->funcs->hw_init(link->link_enc); |
276 | } |
277 | if (hws->fb_offset.quad_part == 0) |
278 | read_mmhub_vm_setup(hws); |
279 | } |
280 | |
281 | /* Blank pixel data with OPP DPG */ |
282 | for (i = 0; i < res_pool->timing_generator_count; i++) { |
283 | struct timing_generator *tg = res_pool->timing_generators[i]; |
284 | |
285 | if (tg->funcs->is_tg_enabled(tg)) { |
286 | dcn201_init_blank(dc, tg); |
287 | } |
288 | } |
289 | |
290 | for (i = 0; i < res_pool->timing_generator_count; i++) { |
291 | struct timing_generator *tg = res_pool->timing_generators[i]; |
292 | |
293 | if (tg->funcs->is_tg_enabled(tg)) |
294 | tg->funcs->lock(tg); |
295 | } |
296 | |
297 | for (i = 0; i < res_pool->pipe_count; i++) { |
298 | struct dpp *dpp = res_pool->dpps[i]; |
299 | |
300 | dpp->funcs->dpp_reset(dpp); |
301 | } |
302 | |
303 | /* Reset all MPCC muxes */ |
304 | res_pool->mpc->funcs->mpc_init(res_pool->mpc); |
305 | |
306 | /* initialize OPP mpc_tree parameter */ |
307 | for (i = 0; i < res_pool->res_cap->num_opp; i++) { |
308 | res_pool->opps[i]->mpc_tree_params.opp_id = res_pool->opps[i]->inst; |
309 | res_pool->opps[i]->mpc_tree_params.opp_list = NULL((void *)0); |
310 | for (j = 0; j < MAX_PIPES6; j++) |
311 | res_pool->opps[i]->mpcc_disconnect_pending[j] = false0; |
312 | } |
313 | |
314 | for (i = 0; i < res_pool->timing_generator_count; i++) { |
315 | struct timing_generator *tg = res_pool->timing_generators[i]; |
316 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; |
317 | struct hubp *hubp = res_pool->hubps[i]; |
318 | struct dpp *dpp = res_pool->dpps[i]; |
319 | |
320 | pipe_ctx->stream_res.tg = tg; |
321 | pipe_ctx->pipe_idx = i; |
322 | |
323 | pipe_ctx->plane_res.hubp = hubp; |
324 | pipe_ctx->plane_res.dpp = dpp; |
325 | pipe_ctx->plane_res.mpcc_inst = dpp->inst; |
326 | hubp->mpcc_id = dpp->inst; |
327 | hubp->opp_id = OPP_ID_INVALID0xf; |
328 | hubp->power_gated = false0; |
329 | pipe_ctx->stream_res.opp = NULL((void *)0); |
330 | |
331 | hubp->funcs->hubp_init(hubp); |
332 | |
333 | res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true1; |
334 | pipe_ctx->stream_res.opp = res_pool->opps[i]; |
335 | /*To do: number of MPCC != number of opp*/ |
336 | hws->funcs.plane_atomic_disconnect(dc, pipe_ctx); |
337 | } |
338 | |
339 | /* initialize DWB pointer to MCIF_WB */ |
340 | for (i = 0; i < res_pool->res_cap->num_dwb; i++) |
341 | res_pool->dwbc[i]->mcif = res_pool->mcif_wb[i]; |
342 | |
343 | for (i = 0; i < res_pool->timing_generator_count; i++) { |
344 | struct timing_generator *tg = res_pool->timing_generators[i]; |
345 | |
346 | if (tg->funcs->is_tg_enabled(tg)) |
347 | tg->funcs->unlock(tg); |
348 | } |
349 | |
350 | for (i = 0; i < res_pool->pipe_count; i++) { |
351 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; |
352 | |
353 | dc->hwss.disable_plane(dc, pipe_ctx); |
354 | |
355 | pipe_ctx->stream_res.tg = NULL((void *)0); |
356 | pipe_ctx->plane_res.hubp = NULL((void *)0); |
357 | } |
358 | |
359 | for (i = 0; i < res_pool->timing_generator_count; i++) { |
360 | struct timing_generator *tg = res_pool->timing_generators[i]; |
361 | |
362 | tg->funcs->tg_init(tg); |
363 | } |
364 | |
365 | /* end of FPGA. Below if real ASIC */ |
366 | if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)(dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS)) |
367 | return; |
368 | |
369 | for (i = 0; i < res_pool->audio_count; i++) { |
370 | struct audio *audio = res_pool->audios[i]; |
371 | |
372 | audio->funcs->hw_init(audio); |
373 | } |
374 | |
375 | /* power AFMT HDMI memory TODO: may move to dis/en output save power*/ |
376 | REG_WRITE(DIO_MEM_PWR_CTRL, 0)dm_write_reg_func(hws->ctx, hws->regs->DIO_MEM_PWR_CTRL , 0, __func__); |
377 | |
378 | if (!dc->debug.disable_clock_gate) { |
379 | /* enable all DCN clock gating */ |
380 | REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0)dm_write_reg_func(hws->ctx, hws->regs->DCCG_GATE_DISABLE_CNTL , 0, __func__); |
381 | |
382 | REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0)dm_write_reg_func(hws->ctx, hws->regs->DCCG_GATE_DISABLE_CNTL2 , 0, __func__); |
383 | |
384 | REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0)generic_reg_update_ex(hws->ctx, hws->regs->DCFCLK_CNTL , 1, hws->shifts->DCFCLK_GATE_DIS, hws->masks->DCFCLK_GATE_DIS , 0); |
385 | } |
386 | } |
387 | |
388 | /* trigger HW to start disconnect plane from stream on the next vsync */ |
389 | void dcn201_plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx) |
390 | { |
391 | struct dce_hwseq *hws = dc->hwseq; |
392 | struct hubp *hubp = pipe_ctx->plane_res.hubp; |
393 | int dpp_id = pipe_ctx->plane_res.dpp->inst; |
394 | struct mpc *mpc = dc->res_pool->mpc; |
395 | struct mpc_tree *mpc_tree_params; |
396 | struct mpcc *mpcc_to_remove = NULL((void *)0); |
397 | struct output_pixel_processor *opp = pipe_ctx->stream_res.opp; |
398 | bool_Bool mpcc_removed = false0; |
399 | |
400 | mpc_tree_params = &(opp->mpc_tree_params); |
401 | |
402 | /* check if this plane is being used by an MPCC in the secondary blending chain */ |
403 | if (mpc->funcs->get_mpcc_for_dpp_from_secondary) |
404 | mpcc_to_remove = mpc->funcs->get_mpcc_for_dpp_from_secondary(mpc_tree_params, dpp_id); |
405 | |
406 | /* remove MPCC from secondary if being used */ |
407 | if (mpcc_to_remove != NULL((void *)0) && mpc->funcs->remove_mpcc_from_secondary) { |
408 | mpc->funcs->remove_mpcc_from_secondary(mpc, mpc_tree_params, mpcc_to_remove); |
409 | mpcc_removed = true1; |
410 | } |
411 | |
412 | /* check if this MPCC is already being used for this plane (dpp) in the primary blending chain */ |
413 | mpcc_to_remove = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, dpp_id); |
414 | if (mpcc_to_remove != NULL((void *)0)) { |
415 | mpc->funcs->remove_mpcc(mpc, mpc_tree_params, mpcc_to_remove); |
416 | mpcc_removed = true1; |
417 | } |
418 | |
419 | /*Already reset*/ |
420 | if (mpcc_removed == false0) |
421 | return; |
422 | |
423 | if (opp != NULL((void *)0)) |
424 | opp->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true1; |
425 | |
426 | dc->optimized_required = true1; |
427 | |
428 | if (hubp->funcs->hubp_disconnect) |
429 | hubp->funcs->hubp_disconnect(hubp); |
430 | |
431 | if (dc->debug.sanity_checks) |
432 | hws->funcs.verify_allow_pstate_change_high(dc); |
433 | } |
434 | |
435 | void dcn201_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx) |
436 | { |
437 | struct hubp *hubp = pipe_ctx->plane_res.hubp; |
438 | struct mpcc_blnd_cfg blnd_cfg; |
439 | bool_Bool per_pixel_alpha = pipe_ctx->plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe; |
440 | int mpcc_id, dpp_id; |
441 | struct mpcc *new_mpcc; |
442 | struct mpcc *remove_mpcc = NULL((void *)0); |
443 | struct mpc *mpc = dc->res_pool->mpc; |
444 | struct mpc_tree *mpc_tree_params = &(pipe_ctx->stream_res.opp->mpc_tree_params); |
445 | |
446 | if (dc->debug.visual_confirm == VISUAL_CONFIRM_HDR) { |
447 | get_hdr_visual_confirm_color( |
448 | pipe_ctx, &blnd_cfg.black_color); |
449 | } else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE) { |
450 | get_surface_visual_confirm_color( |
451 | pipe_ctx, &blnd_cfg.black_color); |
452 | } else { |
453 | color_space_to_black_color( |
454 | dc, pipe_ctx->stream->output_color_space, |
455 | &blnd_cfg.black_color); |
456 | } |
457 | |
458 | if (per_pixel_alpha) |
459 | blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA; |
460 | else |
461 | blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA; |
462 | |
463 | blnd_cfg.overlap_only = false0; |
464 | |
465 | if (pipe_ctx->plane_state->global_alpha_value) |
466 | blnd_cfg.global_alpha = pipe_ctx->plane_state->global_alpha_value; |
467 | else |
468 | blnd_cfg.global_alpha = 0xff; |
469 | |
470 | blnd_cfg.global_gain = 0xff; |
471 | blnd_cfg.background_color_bpc = 4; |
472 | blnd_cfg.bottom_gain_mode = 0; |
473 | blnd_cfg.top_gain = 0x1f000; |
474 | blnd_cfg.bottom_inside_gain = 0x1f000; |
475 | blnd_cfg.bottom_outside_gain = 0x1f000; |
476 | /*the input to MPCC is RGB*/ |
477 | blnd_cfg.black_color.color_b_cb = 0; |
478 | blnd_cfg.black_color.color_g_y = 0; |
479 | blnd_cfg.black_color.color_r_cr = 0; |
480 | |
481 | /* DCN1.0 has output CM before MPC which seems to screw with |
482 | * pre-multiplied alpha. This is a w/a hopefully unnecessary for DCN2. |
483 | */ |
484 | blnd_cfg.pre_multiplied_alpha = per_pixel_alpha; |
485 | |
486 | /* |
487 | * TODO: remove hack |
488 | * Note: currently there is a bug in init_hw such that |
489 | * on resume from hibernate, BIOS sets up MPCC0, and |
490 | * we do mpcc_remove but the mpcc cannot go to idle |
491 | * after remove. This cause us to pick mpcc1 here, |
492 | * which causes a pstate hang for yet unknown reason. |
493 | */ |
494 | dpp_id = hubp->inst; |
495 | mpcc_id = dpp_id; |
496 | |
497 | /* If there is no full update, don't need to touch MPC tree*/ |
498 | if (!pipe_ctx->plane_state->update_flags.bits.full_update) { |
499 | dc->hwss.update_visual_confirm_color(dc, pipe_ctx, &blnd_cfg.black_color, mpcc_id); |
500 | mpc->funcs->update_blending(mpc, &blnd_cfg, mpcc_id); |
501 | return; |
502 | } |
503 | |
504 | /* check if this plane is being used by an MPCC in the secondary blending chain */ |
505 | if (mpc->funcs->get_mpcc_for_dpp_from_secondary) |
506 | remove_mpcc = mpc->funcs->get_mpcc_for_dpp_from_secondary(mpc_tree_params, dpp_id); |
507 | |
508 | /* remove MPCC from secondary if being used */ |
509 | if (remove_mpcc != NULL((void *)0) && mpc->funcs->remove_mpcc_from_secondary) |
510 | mpc->funcs->remove_mpcc_from_secondary(mpc, mpc_tree_params, remove_mpcc); |
511 | |
512 | /* check if this MPCC is already being used for this plane (dpp) in the primary blending chain */ |
513 | remove_mpcc = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, dpp_id); |
514 | /* remove MPCC if being used */ |
515 | |
516 | if (remove_mpcc != NULL((void *)0)) |
517 | mpc->funcs->remove_mpcc(mpc, mpc_tree_params, remove_mpcc); |
518 | else |
519 | if (dc->debug.sanity_checks) |
520 | mpc->funcs->assert_mpcc_idle_before_connect( |
521 | dc->res_pool->mpc, mpcc_id); |
522 | |
523 | /* Call MPC to insert new plane */ |
524 | dc->hwss.update_visual_confirm_color(dc, pipe_ctx, &blnd_cfg.black_color, mpcc_id); |
525 | new_mpcc = mpc->funcs->insert_plane(dc->res_pool->mpc, |
526 | mpc_tree_params, |
527 | &blnd_cfg, |
528 | NULL((void *)0), |
529 | NULL((void *)0), |
530 | dpp_id, |
531 | mpcc_id); |
532 | |
533 | ASSERT(new_mpcc != NULL)do { if (({ static int __warned; int __ret = !!(!(new_mpcc != ((void *)0))); if (__ret && !__warned) { printf("WARNING %s failed at %s:%d\n" , "!(new_mpcc != ((void *)0))", "/usr/src/sys/dev/pci/drm/amd/display/dc/dcn201/dcn201_hwseq.c" , 533); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do {} while (0); } while (0); |
534 | hubp->opp_id = pipe_ctx->stream_res.opp->inst; |
535 | hubp->mpcc_id = mpcc_id; |
536 | } |
537 | |
538 | void dcn201_pipe_control_lock( |
539 | struct dc *dc, |
540 | struct pipe_ctx *pipe, |
541 | bool_Bool lock) |
542 | { |
543 | struct dce_hwseq *hws = dc->hwseq; |
544 | struct hubp *hubp = NULL((void *)0); |
545 | hubp = dc->res_pool->hubps[pipe->pipe_idx]; |
Value stored to 'hubp' is never read | |
546 | /* use TG master update lock to lock everything on the TG |
547 | * therefore only top pipe need to lock |
548 | */ |
549 | if (pipe->top_pipe) |
550 | return; |
551 | |
552 | if (dc->debug.sanity_checks) |
553 | hws->funcs.verify_allow_pstate_change_high(dc); |
554 | |
555 | if (pipe->plane_state != NULL((void *)0) && pipe->plane_state->triplebuffer_flips) { |
556 | if (lock) |
557 | pipe->stream_res.tg->funcs->triplebuffer_lock(pipe->stream_res.tg); |
558 | else |
559 | pipe->stream_res.tg->funcs->triplebuffer_unlock(pipe->stream_res.tg); |
560 | } else { |
561 | if (lock) |
562 | pipe->stream_res.tg->funcs->lock(pipe->stream_res.tg); |
563 | else |
564 | pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg); |
565 | } |
566 | |
567 | if (dc->debug.sanity_checks) |
568 | hws->funcs.verify_allow_pstate_change_high(dc); |
569 | } |
570 | |
571 | void dcn201_set_cursor_attribute(struct pipe_ctx *pipe_ctx) |
572 | { |
573 | struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes; |
574 | |
575 | gpu_addr_to_uma(pipe_ctx->stream->ctx->dc->hwseq, &attributes->address); |
576 | |
577 | pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes( |
578 | pipe_ctx->plane_res.hubp, attributes); |
579 | pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes( |
580 | pipe_ctx->plane_res.dpp, attributes); |
581 | } |
582 | |
583 | void dcn201_set_dmdata_attributes(struct pipe_ctx *pipe_ctx) |
584 | { |
585 | struct dc_dmdata_attributes attr = { 0 }; |
586 | struct hubp *hubp = pipe_ctx->plane_res.hubp; |
587 | |
588 | gpu_addr_to_uma(pipe_ctx->stream->ctx->dc->hwseq, |
589 | &pipe_ctx->stream->dmdata_address); |
590 | |
591 | attr.dmdata_mode = DMDATA_HW_MODE; |
592 | attr.dmdata_size = |
593 | dc_is_hdmi_signal(pipe_ctx->stream->signal) ? 32 : 36; |
594 | attr.address.quad_part = |
595 | pipe_ctx->stream->dmdata_address.quad_part; |
596 | attr.dmdata_dl_delta = 0; |
597 | attr.dmdata_qos_mode = 0; |
598 | attr.dmdata_qos_level = 0; |
599 | attr.dmdata_repeat = 1; /* always repeat */ |
600 | attr.dmdata_updated = 1; |
601 | attr.dmdata_sw_data = NULL((void *)0); |
602 | |
603 | hubp->funcs->dmdata_set_attributes(hubp, &attr); |
604 | } |
605 | |
606 | void dcn201_unblank_stream(struct pipe_ctx *pipe_ctx, |
607 | struct dc_link_settings *link_settings) |
608 | { |
609 | struct encoder_unblank_param params = { { 0 } }; |
610 | struct dc_stream_state *stream = pipe_ctx->stream; |
611 | struct dc_link *link = stream->link; |
612 | struct dce_hwseq *hws = link->dc->hwseq; |
613 | |
614 | /* only 3 items below are used by unblank */ |
615 | params.timing = pipe_ctx->stream->timing; |
616 | |
617 | params.link_settings.link_rate = link_settings->link_rate; |
618 | |
619 | if (dc_is_dp_signal(pipe_ctx->stream->signal)) { |
620 | /*check whether it is half the rate*/ |
621 | if (optc201_is_two_pixels_per_containter(&stream->timing)) |
622 | params.timing.pix_clk_100hz /= 2; |
623 | |
624 | pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(link, pipe_ctx->stream_res.stream_enc, ¶ms); |
625 | } |
626 | |
627 | if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) { |
628 | hws->funcs.edp_backlight_control(link, true1); |
629 | } |
630 | } |