]>
Commit | Line | Data |
---|---|---|
bff65b77 HW |
1 | /* |
2 | * Copyright 2018 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 | ||
d7929c1e AD |
26 | #include <linux/slab.h> |
27 | ||
bff65b77 HW |
28 | #include "dm_services.h" |
29 | ||
30 | #include "include/logger_interface.h" | |
31 | ||
32 | #include "../dce110/irq_service_dce110.h" | |
33 | ||
34 | #include "dcn/dcn_2_0_0_offset.h" | |
35 | #include "dcn/dcn_2_0_0_sh_mask.h" | |
36 | #include "navi10_ip_offset.h" | |
37 | ||
38 | ||
39 | #include "irq_service_dcn20.h" | |
40 | ||
41 | #include "ivsrcid/dcn/irqsrcs_dcn_1_0.h" | |
42 | ||
43 | enum dc_irq_source to_dal_irq_source_dcn20( | |
44 | struct irq_service *irq_service, | |
45 | uint32_t src_id, | |
46 | uint32_t ext_id) | |
47 | { | |
48 | switch (src_id) { | |
49 | case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP: | |
50 | return DC_IRQ_SOURCE_VBLANK1; | |
51 | case DCN_1_0__SRCID__DC_D2_OTG_VSTARTUP: | |
52 | return DC_IRQ_SOURCE_VBLANK2; | |
53 | case DCN_1_0__SRCID__DC_D3_OTG_VSTARTUP: | |
54 | return DC_IRQ_SOURCE_VBLANK3; | |
55 | case DCN_1_0__SRCID__DC_D4_OTG_VSTARTUP: | |
56 | return DC_IRQ_SOURCE_VBLANK4; | |
57 | case DCN_1_0__SRCID__DC_D5_OTG_VSTARTUP: | |
58 | return DC_IRQ_SOURCE_VBLANK5; | |
59 | case DCN_1_0__SRCID__DC_D6_OTG_VSTARTUP: | |
60 | return DC_IRQ_SOURCE_VBLANK6; | |
61 | case DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT: | |
62 | return DC_IRQ_SOURCE_PFLIP1; | |
63 | case DCN_1_0__SRCID__HUBP1_FLIP_INTERRUPT: | |
64 | return DC_IRQ_SOURCE_PFLIP2; | |
65 | case DCN_1_0__SRCID__HUBP2_FLIP_INTERRUPT: | |
66 | return DC_IRQ_SOURCE_PFLIP3; | |
67 | case DCN_1_0__SRCID__HUBP3_FLIP_INTERRUPT: | |
68 | return DC_IRQ_SOURCE_PFLIP4; | |
69 | case DCN_1_0__SRCID__HUBP4_FLIP_INTERRUPT: | |
70 | return DC_IRQ_SOURCE_PFLIP5; | |
71 | case DCN_1_0__SRCID__HUBP5_FLIP_INTERRUPT: | |
72 | return DC_IRQ_SOURCE_PFLIP6; | |
b37727fb | 73 | case DCN_1_0__SRCID__OTG0_IHC_V_UPDATE_NO_LOCK_INTERRUPT: |
74 | return DC_IRQ_SOURCE_VUPDATE1; | |
75 | case DCN_1_0__SRCID__OTG1_IHC_V_UPDATE_NO_LOCK_INTERRUPT: | |
76 | return DC_IRQ_SOURCE_VUPDATE2; | |
77 | case DCN_1_0__SRCID__OTG2_IHC_V_UPDATE_NO_LOCK_INTERRUPT: | |
78 | return DC_IRQ_SOURCE_VUPDATE3; | |
79 | case DCN_1_0__SRCID__OTG3_IHC_V_UPDATE_NO_LOCK_INTERRUPT: | |
80 | return DC_IRQ_SOURCE_VUPDATE4; | |
81 | case DCN_1_0__SRCID__OTG4_IHC_V_UPDATE_NO_LOCK_INTERRUPT: | |
82 | return DC_IRQ_SOURCE_VUPDATE5; | |
83 | case DCN_1_0__SRCID__OTG5_IHC_V_UPDATE_NO_LOCK_INTERRUPT: | |
84 | return DC_IRQ_SOURCE_VUPDATE6; | |
bff65b77 HW |
85 | |
86 | case DCN_1_0__SRCID__DC_HPD1_INT: | |
87 | /* generic src_id for all HPD and HPDRX interrupts */ | |
88 | switch (ext_id) { | |
89 | case DCN_1_0__CTXID__DC_HPD1_INT: | |
90 | return DC_IRQ_SOURCE_HPD1; | |
91 | case DCN_1_0__CTXID__DC_HPD2_INT: | |
92 | return DC_IRQ_SOURCE_HPD2; | |
93 | case DCN_1_0__CTXID__DC_HPD3_INT: | |
94 | return DC_IRQ_SOURCE_HPD3; | |
95 | case DCN_1_0__CTXID__DC_HPD4_INT: | |
96 | return DC_IRQ_SOURCE_HPD4; | |
97 | case DCN_1_0__CTXID__DC_HPD5_INT: | |
98 | return DC_IRQ_SOURCE_HPD5; | |
99 | case DCN_1_0__CTXID__DC_HPD6_INT: | |
100 | return DC_IRQ_SOURCE_HPD6; | |
101 | case DCN_1_0__CTXID__DC_HPD1_RX_INT: | |
102 | return DC_IRQ_SOURCE_HPD1RX; | |
103 | case DCN_1_0__CTXID__DC_HPD2_RX_INT: | |
104 | return DC_IRQ_SOURCE_HPD2RX; | |
105 | case DCN_1_0__CTXID__DC_HPD3_RX_INT: | |
106 | return DC_IRQ_SOURCE_HPD3RX; | |
107 | case DCN_1_0__CTXID__DC_HPD4_RX_INT: | |
108 | return DC_IRQ_SOURCE_HPD4RX; | |
109 | case DCN_1_0__CTXID__DC_HPD5_RX_INT: | |
110 | return DC_IRQ_SOURCE_HPD5RX; | |
111 | case DCN_1_0__CTXID__DC_HPD6_RX_INT: | |
112 | return DC_IRQ_SOURCE_HPD6RX; | |
113 | default: | |
114 | return DC_IRQ_SOURCE_INVALID; | |
115 | } | |
116 | break; | |
117 | ||
118 | default: | |
119 | return DC_IRQ_SOURCE_INVALID; | |
120 | } | |
121 | } | |
122 | ||
123 | static bool hpd_ack( | |
124 | struct irq_service *irq_service, | |
125 | const struct irq_source_info *info) | |
126 | { | |
127 | uint32_t addr = info->status_reg; | |
128 | uint32_t value = dm_read_reg(irq_service->ctx, addr); | |
129 | uint32_t current_status = | |
130 | get_reg_field_value( | |
131 | value, | |
132 | HPD0_DC_HPD_INT_STATUS, | |
133 | DC_HPD_SENSE_DELAYED); | |
134 | ||
135 | dal_irq_service_ack_generic(irq_service, info); | |
136 | ||
137 | value = dm_read_reg(irq_service->ctx, info->enable_reg); | |
138 | ||
139 | set_reg_field_value( | |
140 | value, | |
141 | current_status ? 0 : 1, | |
142 | HPD0_DC_HPD_INT_CONTROL, | |
143 | DC_HPD_INT_POLARITY); | |
144 | ||
145 | dm_write_reg(irq_service->ctx, info->enable_reg, value); | |
146 | ||
147 | return true; | |
148 | } | |
149 | ||
150 | static const struct irq_source_info_funcs hpd_irq_info_funcs = { | |
151 | .set = NULL, | |
152 | .ack = hpd_ack | |
153 | }; | |
154 | ||
155 | static const struct irq_source_info_funcs hpd_rx_irq_info_funcs = { | |
156 | .set = NULL, | |
157 | .ack = NULL | |
158 | }; | |
159 | ||
160 | static const struct irq_source_info_funcs pflip_irq_info_funcs = { | |
161 | .set = NULL, | |
162 | .ack = NULL | |
163 | }; | |
164 | ||
165 | static const struct irq_source_info_funcs vblank_irq_info_funcs = { | |
166 | .set = NULL, | |
167 | .ack = NULL | |
168 | }; | |
169 | ||
e40837af NK |
170 | static const struct irq_source_info_funcs vupdate_no_lock_irq_info_funcs = { |
171 | .set = NULL, | |
172 | .ack = NULL | |
173 | }; | |
174 | ||
bff65b77 HW |
175 | #undef BASE_INNER |
176 | #define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg | |
177 | ||
178 | /* compile time expand base address. */ | |
179 | #define BASE(seg) \ | |
180 | BASE_INNER(seg) | |
181 | ||
182 | ||
183 | #define SRI(reg_name, block, id)\ | |
184 | BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ | |
185 | mm ## block ## id ## _ ## reg_name | |
186 | ||
187 | ||
188 | #define IRQ_REG_ENTRY(block, reg_num, reg1, mask1, reg2, mask2)\ | |
189 | .enable_reg = SRI(reg1, block, reg_num),\ | |
190 | .enable_mask = \ | |
191 | block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ | |
192 | .enable_value = {\ | |
193 | block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ | |
194 | ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ | |
195 | },\ | |
196 | .ack_reg = SRI(reg2, block, reg_num),\ | |
197 | .ack_mask = \ | |
198 | block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK,\ | |
199 | .ack_value = \ | |
200 | block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK \ | |
201 | ||
202 | ||
203 | ||
204 | #define hpd_int_entry(reg_num)\ | |
205 | [DC_IRQ_SOURCE_HPD1 + reg_num] = {\ | |
206 | IRQ_REG_ENTRY(HPD, reg_num,\ | |
207 | DC_HPD_INT_CONTROL, DC_HPD_INT_EN,\ | |
208 | DC_HPD_INT_CONTROL, DC_HPD_INT_ACK),\ | |
209 | .status_reg = SRI(DC_HPD_INT_STATUS, HPD, reg_num),\ | |
210 | .funcs = &hpd_irq_info_funcs\ | |
211 | } | |
212 | ||
213 | #define hpd_rx_int_entry(reg_num)\ | |
214 | [DC_IRQ_SOURCE_HPD1RX + reg_num] = {\ | |
215 | IRQ_REG_ENTRY(HPD, reg_num,\ | |
216 | DC_HPD_INT_CONTROL, DC_HPD_RX_INT_EN,\ | |
217 | DC_HPD_INT_CONTROL, DC_HPD_RX_INT_ACK),\ | |
218 | .status_reg = SRI(DC_HPD_INT_STATUS, HPD, reg_num),\ | |
219 | .funcs = &hpd_rx_irq_info_funcs\ | |
220 | } | |
221 | #define pflip_int_entry(reg_num)\ | |
222 | [DC_IRQ_SOURCE_PFLIP1 + reg_num] = {\ | |
223 | IRQ_REG_ENTRY(HUBPREQ, reg_num,\ | |
224 | DCSURF_SURFACE_FLIP_INTERRUPT, SURFACE_FLIP_INT_MASK,\ | |
225 | DCSURF_SURFACE_FLIP_INTERRUPT, SURFACE_FLIP_CLEAR),\ | |
226 | .funcs = &pflip_irq_info_funcs\ | |
227 | } | |
228 | ||
e40837af NK |
229 | /* vupdate_no_lock_int_entry maps to DC_IRQ_SOURCE_VUPDATEx, to match semantic |
230 | * of DCE's DC_IRQ_SOURCE_VUPDATEx. | |
231 | */ | |
232 | #define vupdate_no_lock_int_entry(reg_num)\ | |
bff65b77 HW |
233 | [DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\ |
234 | IRQ_REG_ENTRY(OTG, reg_num,\ | |
e40837af NK |
235 | OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_INT_EN,\ |
236 | OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_CLEAR),\ | |
237 | .funcs = &vupdate_no_lock_irq_info_funcs\ | |
bff65b77 HW |
238 | } |
239 | ||
240 | #define vblank_int_entry(reg_num)\ | |
241 | [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\ | |
242 | IRQ_REG_ENTRY(OTG, reg_num,\ | |
243 | OTG_GLOBAL_SYNC_STATUS, VSTARTUP_INT_EN,\ | |
244 | OTG_GLOBAL_SYNC_STATUS, VSTARTUP_EVENT_CLEAR),\ | |
245 | .funcs = &vblank_irq_info_funcs\ | |
246 | } | |
247 | ||
248 | #define dummy_irq_entry() \ | |
249 | {\ | |
250 | .funcs = &dummy_irq_info_funcs\ | |
251 | } | |
252 | ||
253 | #define i2c_int_entry(reg_num) \ | |
254 | [DC_IRQ_SOURCE_I2C_DDC ## reg_num] = dummy_irq_entry() | |
255 | ||
256 | #define dp_sink_int_entry(reg_num) \ | |
257 | [DC_IRQ_SOURCE_DPSINK ## reg_num] = dummy_irq_entry() | |
258 | ||
259 | #define gpio_pad_int_entry(reg_num) \ | |
260 | [DC_IRQ_SOURCE_GPIOPAD ## reg_num] = dummy_irq_entry() | |
261 | ||
262 | #define dc_underflow_int_entry(reg_num) \ | |
263 | [DC_IRQ_SOURCE_DC ## reg_num ## UNDERFLOW] = dummy_irq_entry() | |
264 | ||
265 | static const struct irq_source_info_funcs dummy_irq_info_funcs = { | |
266 | .set = dal_irq_service_dummy_set, | |
267 | .ack = dal_irq_service_dummy_ack | |
268 | }; | |
269 | ||
270 | static const struct irq_source_info | |
271 | irq_source_info_dcn20[DAL_IRQ_SOURCES_NUMBER] = { | |
272 | [DC_IRQ_SOURCE_INVALID] = dummy_irq_entry(), | |
273 | hpd_int_entry(0), | |
274 | hpd_int_entry(1), | |
275 | hpd_int_entry(2), | |
276 | hpd_int_entry(3), | |
277 | hpd_int_entry(4), | |
278 | hpd_int_entry(5), | |
279 | hpd_rx_int_entry(0), | |
280 | hpd_rx_int_entry(1), | |
281 | hpd_rx_int_entry(2), | |
282 | hpd_rx_int_entry(3), | |
283 | hpd_rx_int_entry(4), | |
284 | hpd_rx_int_entry(5), | |
285 | i2c_int_entry(1), | |
286 | i2c_int_entry(2), | |
287 | i2c_int_entry(3), | |
288 | i2c_int_entry(4), | |
289 | i2c_int_entry(5), | |
290 | i2c_int_entry(6), | |
291 | dp_sink_int_entry(1), | |
292 | dp_sink_int_entry(2), | |
293 | dp_sink_int_entry(3), | |
294 | dp_sink_int_entry(4), | |
295 | dp_sink_int_entry(5), | |
296 | dp_sink_int_entry(6), | |
297 | [DC_IRQ_SOURCE_TIMER] = dummy_irq_entry(), | |
298 | pflip_int_entry(0), | |
299 | pflip_int_entry(1), | |
300 | pflip_int_entry(2), | |
301 | pflip_int_entry(3), | |
728321e5 AD |
302 | pflip_int_entry(4), |
303 | pflip_int_entry(5), | |
bff65b77 HW |
304 | [DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(), |
305 | gpio_pad_int_entry(0), | |
306 | gpio_pad_int_entry(1), | |
307 | gpio_pad_int_entry(2), | |
308 | gpio_pad_int_entry(3), | |
309 | gpio_pad_int_entry(4), | |
310 | gpio_pad_int_entry(5), | |
311 | gpio_pad_int_entry(6), | |
312 | gpio_pad_int_entry(7), | |
313 | gpio_pad_int_entry(8), | |
314 | gpio_pad_int_entry(9), | |
315 | gpio_pad_int_entry(10), | |
316 | gpio_pad_int_entry(11), | |
317 | gpio_pad_int_entry(12), | |
318 | gpio_pad_int_entry(13), | |
319 | gpio_pad_int_entry(14), | |
320 | gpio_pad_int_entry(15), | |
321 | gpio_pad_int_entry(16), | |
322 | gpio_pad_int_entry(17), | |
323 | gpio_pad_int_entry(18), | |
324 | gpio_pad_int_entry(19), | |
325 | gpio_pad_int_entry(20), | |
326 | gpio_pad_int_entry(21), | |
327 | gpio_pad_int_entry(22), | |
328 | gpio_pad_int_entry(23), | |
329 | gpio_pad_int_entry(24), | |
330 | gpio_pad_int_entry(25), | |
331 | gpio_pad_int_entry(26), | |
332 | gpio_pad_int_entry(27), | |
333 | gpio_pad_int_entry(28), | |
334 | gpio_pad_int_entry(29), | |
335 | gpio_pad_int_entry(30), | |
336 | dc_underflow_int_entry(1), | |
337 | dc_underflow_int_entry(2), | |
338 | dc_underflow_int_entry(3), | |
339 | dc_underflow_int_entry(4), | |
340 | dc_underflow_int_entry(5), | |
341 | dc_underflow_int_entry(6), | |
342 | [DC_IRQ_SOURCE_DMCU_SCP] = dummy_irq_entry(), | |
343 | [DC_IRQ_SOURCE_VBIOS_SW] = dummy_irq_entry(), | |
e40837af NK |
344 | vupdate_no_lock_int_entry(0), |
345 | vupdate_no_lock_int_entry(1), | |
346 | vupdate_no_lock_int_entry(2), | |
347 | vupdate_no_lock_int_entry(3), | |
348 | vupdate_no_lock_int_entry(4), | |
349 | vupdate_no_lock_int_entry(5), | |
bff65b77 HW |
350 | vblank_int_entry(0), |
351 | vblank_int_entry(1), | |
352 | vblank_int_entry(2), | |
353 | vblank_int_entry(3), | |
354 | vblank_int_entry(4), | |
355 | vblank_int_entry(5), | |
356 | }; | |
357 | ||
358 | static const struct irq_service_funcs irq_service_funcs_dcn20 = { | |
359 | .to_dal_irq_source = to_dal_irq_source_dcn20 | |
360 | }; | |
361 | ||
d9e32672 | 362 | static void dcn20_irq_construct( |
bff65b77 HW |
363 | struct irq_service *irq_service, |
364 | struct irq_service_init_data *init_data) | |
365 | { | |
366 | dal_irq_service_construct(irq_service, init_data); | |
367 | ||
368 | irq_service->info = irq_source_info_dcn20; | |
369 | irq_service->funcs = &irq_service_funcs_dcn20; | |
370 | } | |
371 | ||
372 | struct irq_service *dal_irq_service_dcn20_create( | |
373 | struct irq_service_init_data *init_data) | |
374 | { | |
375 | struct irq_service *irq_service = kzalloc(sizeof(*irq_service), | |
376 | GFP_KERNEL); | |
377 | ||
378 | if (!irq_service) | |
379 | return NULL; | |
380 | ||
d9e32672 | 381 | dcn20_irq_construct(irq_service, init_data); |
bff65b77 HW |
382 | return irq_service; |
383 | } |