File: | dev/pci/drm/amd/display/dc/dcn21/dcn21_hwseq.c |
Warning: | line 222, column 69 Access to field 'inst' results in a dereference of a null pointer (loaded from variable 'panel_cntl') |
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 "dm_helpers.h" | |||
28 | #include "core_types.h" | |||
29 | #include "resource.h" | |||
30 | #include "dce/dce_hwseq.h" | |||
31 | #include "dce110/dce110_hw_sequencer.h" | |||
32 | #include "dcn21_hwseq.h" | |||
33 | #include "vmid.h" | |||
34 | #include "reg_helper.h" | |||
35 | #include "hw/clk_mgr.h" | |||
36 | #include "dc_dmub_srv.h" | |||
37 | #include "abm.h" | |||
38 | ||||
39 | ||||
40 | #define DC_LOGGER_INIT(logger) | |||
41 | ||||
42 | #define CTXhws->ctx \ | |||
43 | hws->ctx | |||
44 | #define REG(reg)hws->regs->reg\ | |||
45 | hws->regs->reg | |||
46 | ||||
47 | #undef FN | |||
48 | #define FN(reg_name, field_name)hws->shifts->field_name, hws->masks->field_name \ | |||
49 | hws->shifts->field_name, hws->masks->field_name | |||
50 | ||||
51 | /* Temporary read settings, future will get values from kmd directly */ | |||
52 | static void mmhub_update_page_table_config(struct dcn_hubbub_phys_addr_config *config, | |||
53 | struct dce_hwseq *hws) | |||
54 | { | |||
55 | uint32_t page_table_base_hi; | |||
56 | uint32_t page_table_base_lo; | |||
57 | ||||
58 | REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32,generic_reg_get(hws->ctx, hws->regs->VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32 , hws->shifts->PAGE_DIRECTORY_ENTRY_HI32, hws->masks ->PAGE_DIRECTORY_ENTRY_HI32, &page_table_base_hi) | |||
59 | PAGE_DIRECTORY_ENTRY_HI32, &page_table_base_hi)generic_reg_get(hws->ctx, hws->regs->VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32 , hws->shifts->PAGE_DIRECTORY_ENTRY_HI32, hws->masks ->PAGE_DIRECTORY_ENTRY_HI32, &page_table_base_hi); | |||
60 | REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,generic_reg_get(hws->ctx, hws->regs->VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32 , hws->shifts->PAGE_DIRECTORY_ENTRY_LO32, hws->masks ->PAGE_DIRECTORY_ENTRY_LO32, &page_table_base_lo) | |||
61 | PAGE_DIRECTORY_ENTRY_LO32, &page_table_base_lo)generic_reg_get(hws->ctx, hws->regs->VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32 , hws->shifts->PAGE_DIRECTORY_ENTRY_LO32, hws->masks ->PAGE_DIRECTORY_ENTRY_LO32, &page_table_base_lo); | |||
62 | ||||
63 | config->gart_config.page_table_base_addr = ((uint64_t)page_table_base_hi << 32) | page_table_base_lo; | |||
64 | ||||
65 | } | |||
66 | ||||
67 | int dcn21_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_space_config *pa_config) | |||
68 | { | |||
69 | struct dcn_hubbub_phys_addr_config config; | |||
70 | ||||
71 | config.system_aperture.fb_top = pa_config->system_aperture.fb_top; | |||
72 | config.system_aperture.fb_offset = pa_config->system_aperture.fb_offset; | |||
73 | config.system_aperture.fb_base = pa_config->system_aperture.fb_base; | |||
74 | config.system_aperture.agp_top = pa_config->system_aperture.agp_top; | |||
75 | config.system_aperture.agp_bot = pa_config->system_aperture.agp_bot; | |||
76 | config.system_aperture.agp_base = pa_config->system_aperture.agp_base; | |||
77 | config.gart_config.page_table_start_addr = pa_config->gart_config.page_table_start_addr; | |||
78 | config.gart_config.page_table_end_addr = pa_config->gart_config.page_table_end_addr; | |||
79 | config.gart_config.page_table_base_addr = pa_config->gart_config.page_table_base_addr; | |||
80 | ||||
81 | mmhub_update_page_table_config(&config, hws); | |||
82 | ||||
83 | return dc->res_pool->hubbub->funcs->init_dchub_sys_ctx(dc->res_pool->hubbub, &config); | |||
84 | } | |||
85 | ||||
86 | // work around for Renoir s0i3, if register is programmed, bypass golden init. | |||
87 | ||||
88 | bool_Bool dcn21_s0i3_golden_init_wa(struct dc *dc) | |||
89 | { | |||
90 | struct dce_hwseq *hws = dc->hwseq; | |||
91 | uint32_t value = 0; | |||
92 | ||||
93 | value = REG_READ(MICROSECOND_TIME_BASE_DIV)dm_read_reg_func(hws->ctx, hws->regs->MICROSECOND_TIME_BASE_DIV , __func__); | |||
94 | ||||
95 | return value != 0x00120464; | |||
96 | } | |||
97 | ||||
98 | void dcn21_exit_optimized_pwr_state( | |||
99 | const struct dc *dc, | |||
100 | struct dc_state *context) | |||
101 | { | |||
102 | dc->clk_mgr->funcs->update_clocks( | |||
103 | dc->clk_mgr, | |||
104 | context, | |||
105 | false0); | |||
106 | } | |||
107 | ||||
108 | void dcn21_optimize_pwr_state( | |||
109 | const struct dc *dc, | |||
110 | struct dc_state *context) | |||
111 | { | |||
112 | dc->clk_mgr->funcs->update_clocks( | |||
113 | dc->clk_mgr, | |||
114 | context, | |||
115 | true1); | |||
116 | } | |||
117 | ||||
118 | /* If user hotplug a HDMI monitor while in monitor off, | |||
119 | * OS will do a mode set (with output timing) but keep output off. | |||
120 | * In this case DAL will ask vbios to power up the pll in the PHY. | |||
121 | * If user unplug the monitor (while we are on monitor off) or | |||
122 | * system attempt to enter modern standby (which we will disable PLL), | |||
123 | * PHY will hang on the next mode set attempt. | |||
124 | * if enable PLL follow by disable PLL (without executing lane enable/disable), | |||
125 | * RDPCS_PHY_DP_MPLLB_STATE remains 1, | |||
126 | * which indicate that PLL disable attempt actually didn't go through. | |||
127 | * As a workaround, insert PHY lane enable/disable before PLL disable. | |||
128 | */ | |||
129 | void dcn21_PLAT_58856_wa(struct dc_state *context, struct pipe_ctx *pipe_ctx) | |||
130 | { | |||
131 | if (!pipe_ctx->stream->dpms_off) | |||
132 | return; | |||
133 | ||||
134 | pipe_ctx->stream->dpms_off = false0; | |||
135 | core_link_enable_stream(context, pipe_ctx); | |||
136 | core_link_disable_stream(pipe_ctx); | |||
137 | pipe_ctx->stream->dpms_off = true1; | |||
138 | } | |||
139 | ||||
140 | static bool_Bool dmub_abm_set_pipe(struct abm *abm, uint32_t otg_inst, uint32_t option, uint32_t panel_inst) | |||
141 | { | |||
142 | union dmub_rb_cmd cmd; | |||
143 | struct dc_context *dc = abm->ctx; | |||
144 | uint32_t ramping_boundary = 0xFFFF; | |||
145 | ||||
146 | memset(&cmd, 0, sizeof(cmd))__builtin_memset((&cmd), (0), (sizeof(cmd))); | |||
147 | cmd.abm_set_pipe.header.type = DMUB_CMD__ABM; | |||
148 | cmd.abm_set_pipe.header.sub_type = DMUB_CMD__ABM_SET_PIPE; | |||
149 | cmd.abm_set_pipe.abm_set_pipe_data.otg_inst = otg_inst; | |||
150 | cmd.abm_set_pipe.abm_set_pipe_data.set_pipe_option = option; | |||
151 | cmd.abm_set_pipe.abm_set_pipe_data.panel_inst = panel_inst; | |||
152 | cmd.abm_set_pipe.abm_set_pipe_data.ramping_boundary = ramping_boundary; | |||
153 | cmd.abm_set_pipe.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_pipe_data); | |||
154 | ||||
155 | dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); | |||
156 | dc_dmub_srv_cmd_execute(dc->dmub_srv); | |||
157 | dc_dmub_srv_wait_idle(dc->dmub_srv); | |||
158 | ||||
159 | return true1; | |||
160 | } | |||
161 | ||||
162 | void dcn21_set_abm_immediate_disable(struct pipe_ctx *pipe_ctx) | |||
163 | { | |||
164 | struct abm *abm = pipe_ctx->stream_res.abm; | |||
165 | uint32_t otg_inst = pipe_ctx->stream_res.tg->inst; | |||
166 | struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl; | |||
167 | ||||
168 | struct dmcu *dmcu = pipe_ctx->stream->ctx->dc->res_pool->dmcu; | |||
169 | ||||
170 | if (dmcu) { | |||
171 | dce110_set_abm_immediate_disable(pipe_ctx); | |||
172 | return; | |||
173 | } | |||
174 | ||||
175 | if (abm && panel_cntl) { | |||
176 | dmub_abm_set_pipe(abm, otg_inst, SET_ABM_PIPE_IMMEDIATELY_DISABLE255, | |||
177 | panel_cntl->inst); | |||
178 | panel_cntl->funcs->store_backlight_level(panel_cntl); | |||
179 | } | |||
180 | } | |||
181 | ||||
182 | void dcn21_set_pipe(struct pipe_ctx *pipe_ctx) | |||
183 | { | |||
184 | struct abm *abm = pipe_ctx->stream_res.abm; | |||
185 | uint32_t otg_inst = pipe_ctx->stream_res.tg->inst; | |||
186 | struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl; | |||
187 | struct dmcu *dmcu = pipe_ctx->stream->ctx->dc->res_pool->dmcu; | |||
188 | ||||
189 | if (dmcu) { | |||
190 | dce110_set_pipe(pipe_ctx); | |||
191 | return; | |||
192 | } | |||
193 | ||||
194 | if (abm && panel_cntl) | |||
195 | dmub_abm_set_pipe(abm, otg_inst, SET_ABM_PIPE_NORMAL1, panel_cntl->inst); | |||
196 | } | |||
197 | ||||
198 | bool_Bool dcn21_set_backlight_level(struct pipe_ctx *pipe_ctx, | |||
199 | uint32_t backlight_pwm_u16_16, | |||
200 | uint32_t frame_ramp) | |||
201 | { | |||
202 | union dmub_rb_cmd cmd; | |||
203 | struct dc_context *dc = pipe_ctx->stream->ctx; | |||
204 | struct abm *abm = pipe_ctx->stream_res.abm; | |||
205 | uint32_t otg_inst = pipe_ctx->stream_res.tg->inst; | |||
206 | struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl; | |||
| ||||
207 | ||||
208 | if (dc->dc->res_pool->dmcu) { | |||
209 | dce110_set_backlight_level(pipe_ctx, backlight_pwm_u16_16, frame_ramp); | |||
210 | return true1; | |||
211 | } | |||
212 | ||||
213 | if (abm && panel_cntl) | |||
214 | dmub_abm_set_pipe(abm, otg_inst, SET_ABM_PIPE_NORMAL1, panel_cntl->inst); | |||
215 | ||||
216 | memset(&cmd, 0, sizeof(cmd))__builtin_memset((&cmd), (0), (sizeof(cmd))); | |||
217 | cmd.abm_set_backlight.header.type = DMUB_CMD__ABM; | |||
218 | cmd.abm_set_backlight.header.sub_type = DMUB_CMD__ABM_SET_BACKLIGHT; | |||
219 | cmd.abm_set_backlight.abm_set_backlight_data.frame_ramp = frame_ramp; | |||
220 | cmd.abm_set_backlight.abm_set_backlight_data.backlight_user_level = backlight_pwm_u16_16; | |||
221 | cmd.abm_set_backlight.abm_set_backlight_data.version = DMUB_CMD_ABM_CONTROL_VERSION_10x1; | |||
222 | cmd.abm_set_backlight.abm_set_backlight_data.panel_mask = (0x01 << panel_cntl->inst); | |||
| ||||
223 | cmd.abm_set_backlight.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_backlight_data); | |||
224 | ||||
225 | dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); | |||
226 | dc_dmub_srv_cmd_execute(dc->dmub_srv); | |||
227 | dc_dmub_srv_wait_idle(dc->dmub_srv); | |||
228 | ||||
229 | return true1; | |||
230 | } | |||
231 | ||||
232 | bool_Bool dcn21_is_abm_supported(struct dc *dc, | |||
233 | struct dc_state *context, struct dc_stream_state *stream) | |||
234 | { | |||
235 | int i; | |||
236 | ||||
237 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | |||
238 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; | |||
239 | ||||
240 | if (pipe_ctx->stream == stream && | |||
241 | (pipe_ctx->prev_odm_pipe == NULL((void *)0) && pipe_ctx->next_odm_pipe == NULL((void *)0))) | |||
242 | return true1; | |||
243 | } | |||
244 | return false0; | |||
245 | } | |||
246 |