1 | /* |
2 | * Copyright 2012-15 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 | |
28 | /* |
29 | * Pre-requisites: headers required by header of this unit |
30 | */ |
31 | #include "include/gpio_types.h" |
32 | #include "../hw_translate.h" |
33 | |
34 | #include "hw_translate_dce80.h" |
35 | |
36 | #include "dce/dce_8_0_d.h" |
37 | #include "dce/dce_8_0_sh_mask.h" |
38 | #include "smu/smu_7_0_1_d.h" |
39 | |
40 | /* |
41 | * @brief |
42 | * Returns index of first bit (starting with LSB) which is set |
43 | */ |
44 | static uint32_t index_from_vector( |
45 | uint32_t vector) |
46 | { |
47 | uint32_t result = 0; |
48 | uint32_t mask = 1; |
49 | |
50 | do { |
51 | if (vector == mask) |
52 | return result; |
53 | |
54 | ++result; |
55 | mask <<= 1; |
56 | } while (mask); |
57 | |
58 | BREAK_TO_DEBUGGER(); |
59 | |
60 | return GPIO_ENUM_UNKNOWN; |
61 | } |
62 | |
63 | static bool offset_to_id( |
64 | uint32_t offset, |
65 | uint32_t mask, |
66 | enum gpio_id *id, |
67 | uint32_t *en) |
68 | { |
69 | switch (offset) { |
70 | /* GENERIC */ |
71 | case mmDC_GPIO_GENERIC_A: |
72 | *id = GPIO_ID_GENERIC; |
73 | switch (mask) { |
74 | case DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK: |
75 | *en = GPIO_GENERIC_A; |
76 | return true; |
77 | case DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK: |
78 | *en = GPIO_GENERIC_B; |
79 | return true; |
80 | case DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK: |
81 | *en = GPIO_GENERIC_C; |
82 | return true; |
83 | case DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK: |
84 | *en = GPIO_GENERIC_D; |
85 | return true; |
86 | case DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK: |
87 | *en = GPIO_GENERIC_E; |
88 | return true; |
89 | case DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK: |
90 | *en = GPIO_GENERIC_F; |
91 | return true; |
92 | case DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK: |
93 | *en = GPIO_GENERIC_G; |
94 | return true; |
95 | default: |
96 | BREAK_TO_DEBUGGER(); |
97 | return false; |
98 | } |
99 | break; |
100 | /* HPD */ |
101 | case mmDC_GPIO_HPD_A: |
102 | *id = GPIO_ID_HPD; |
103 | switch (mask) { |
104 | case DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK: |
105 | *en = GPIO_HPD_1; |
106 | return true; |
107 | case DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK: |
108 | *en = GPIO_HPD_2; |
109 | return true; |
110 | case DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK: |
111 | *en = GPIO_HPD_3; |
112 | return true; |
113 | case DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK: |
114 | *en = GPIO_HPD_4; |
115 | return true; |
116 | case DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK: |
117 | *en = GPIO_HPD_5; |
118 | return true; |
119 | case DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK: |
120 | *en = GPIO_HPD_6; |
121 | return true; |
122 | default: |
123 | BREAK_TO_DEBUGGER(); |
124 | return false; |
125 | } |
126 | break; |
127 | /* SYNCA */ |
128 | case mmDC_GPIO_SYNCA_A: |
129 | *id = GPIO_ID_SYNC; |
130 | switch (mask) { |
131 | case DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK: |
132 | *en = GPIO_SYNC_HSYNC_A; |
133 | return true; |
134 | case DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK: |
135 | *en = GPIO_SYNC_VSYNC_A; |
136 | return true; |
137 | default: |
138 | BREAK_TO_DEBUGGER(); |
139 | return false; |
140 | } |
141 | break; |
142 | /* mmDC_GPIO_GENLK_MASK */ |
143 | case mmDC_GPIO_GENLK_A: |
144 | *id = GPIO_ID_GSL; |
145 | switch (mask) { |
146 | case DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK: |
147 | *en = GPIO_GSL_GENLOCK_CLOCK; |
148 | return true; |
149 | case DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK: |
150 | *en = GPIO_GSL_GENLOCK_VSYNC; |
151 | return true; |
152 | case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK: |
153 | *en = GPIO_GSL_SWAPLOCK_A; |
154 | return true; |
155 | case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK: |
156 | *en = GPIO_GSL_SWAPLOCK_B; |
157 | return true; |
158 | default: |
159 | BREAK_TO_DEBUGGER(); |
160 | return false; |
161 | } |
162 | break; |
163 | /* GPIOPAD */ |
164 | case mmGPIOPAD_A: |
165 | *id = GPIO_ID_GPIO_PAD; |
166 | *en = index_from_vector(vector: mask); |
167 | return (*en <= GPIO_GPIO_PAD_MAX); |
168 | /* DDC */ |
169 | /* we don't care about the GPIO_ID for DDC |
170 | * in DdcHandle it will use GPIO_ID_DDC_DATA/GPIO_ID_DDC_CLOCK |
171 | * directly in the create method */ |
172 | case mmDC_GPIO_DDC1_A: |
173 | *en = GPIO_DDC_LINE_DDC1; |
174 | return true; |
175 | case mmDC_GPIO_DDC2_A: |
176 | *en = GPIO_DDC_LINE_DDC2; |
177 | return true; |
178 | case mmDC_GPIO_DDC3_A: |
179 | *en = GPIO_DDC_LINE_DDC3; |
180 | return true; |
181 | case mmDC_GPIO_DDC4_A: |
182 | *en = GPIO_DDC_LINE_DDC4; |
183 | return true; |
184 | case mmDC_GPIO_DDC5_A: |
185 | *en = GPIO_DDC_LINE_DDC5; |
186 | return true; |
187 | case mmDC_GPIO_DDC6_A: |
188 | *en = GPIO_DDC_LINE_DDC6; |
189 | return true; |
190 | case mmDC_GPIO_DDCVGA_A: |
191 | *en = GPIO_DDC_LINE_DDC_VGA; |
192 | return true; |
193 | /* GPIO_I2CPAD */ |
194 | case mmDC_GPIO_I2CPAD_A: |
195 | *en = GPIO_DDC_LINE_I2C_PAD; |
196 | return true; |
197 | /* Not implemented */ |
198 | case mmDC_GPIO_PWRSEQ_A: |
199 | case mmDC_GPIO_PAD_STRENGTH_1: |
200 | case mmDC_GPIO_PAD_STRENGTH_2: |
201 | case mmDC_GPIO_DEBUG: |
202 | return false; |
203 | /* UNEXPECTED */ |
204 | default: |
205 | BREAK_TO_DEBUGGER(); |
206 | return false; |
207 | } |
208 | } |
209 | |
210 | static bool id_to_offset( |
211 | enum gpio_id id, |
212 | uint32_t en, |
213 | struct gpio_pin_info *info) |
214 | { |
215 | bool result = true; |
216 | |
217 | switch (id) { |
218 | case GPIO_ID_DDC_DATA: |
219 | info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK; |
220 | switch (en) { |
221 | case GPIO_DDC_LINE_DDC1: |
222 | info->offset = mmDC_GPIO_DDC1_A; |
223 | break; |
224 | case GPIO_DDC_LINE_DDC2: |
225 | info->offset = mmDC_GPIO_DDC2_A; |
226 | break; |
227 | case GPIO_DDC_LINE_DDC3: |
228 | info->offset = mmDC_GPIO_DDC3_A; |
229 | break; |
230 | case GPIO_DDC_LINE_DDC4: |
231 | info->offset = mmDC_GPIO_DDC4_A; |
232 | break; |
233 | case GPIO_DDC_LINE_DDC5: |
234 | info->offset = mmDC_GPIO_DDC5_A; |
235 | break; |
236 | case GPIO_DDC_LINE_DDC6: |
237 | info->offset = mmDC_GPIO_DDC6_A; |
238 | break; |
239 | case GPIO_DDC_LINE_DDC_VGA: |
240 | info->offset = mmDC_GPIO_DDCVGA_A; |
241 | break; |
242 | case GPIO_DDC_LINE_I2C_PAD: |
243 | info->offset = mmDC_GPIO_I2CPAD_A; |
244 | break; |
245 | default: |
246 | BREAK_TO_DEBUGGER(); |
247 | result = false; |
248 | } |
249 | break; |
250 | case GPIO_ID_DDC_CLOCK: |
251 | info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A_MASK; |
252 | switch (en) { |
253 | case GPIO_DDC_LINE_DDC1: |
254 | info->offset = mmDC_GPIO_DDC1_A; |
255 | break; |
256 | case GPIO_DDC_LINE_DDC2: |
257 | info->offset = mmDC_GPIO_DDC2_A; |
258 | break; |
259 | case GPIO_DDC_LINE_DDC3: |
260 | info->offset = mmDC_GPIO_DDC3_A; |
261 | break; |
262 | case GPIO_DDC_LINE_DDC4: |
263 | info->offset = mmDC_GPIO_DDC4_A; |
264 | break; |
265 | case GPIO_DDC_LINE_DDC5: |
266 | info->offset = mmDC_GPIO_DDC5_A; |
267 | break; |
268 | case GPIO_DDC_LINE_DDC6: |
269 | info->offset = mmDC_GPIO_DDC6_A; |
270 | break; |
271 | case GPIO_DDC_LINE_DDC_VGA: |
272 | info->offset = mmDC_GPIO_DDCVGA_A; |
273 | break; |
274 | case GPIO_DDC_LINE_I2C_PAD: |
275 | info->offset = mmDC_GPIO_I2CPAD_A; |
276 | break; |
277 | default: |
278 | BREAK_TO_DEBUGGER(); |
279 | result = false; |
280 | } |
281 | break; |
282 | case GPIO_ID_GENERIC: |
283 | info->offset = mmDC_GPIO_GENERIC_A; |
284 | switch (en) { |
285 | case GPIO_GENERIC_A: |
286 | info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK; |
287 | break; |
288 | case GPIO_GENERIC_B: |
289 | info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK; |
290 | break; |
291 | case GPIO_GENERIC_C: |
292 | info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK; |
293 | break; |
294 | case GPIO_GENERIC_D: |
295 | info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK; |
296 | break; |
297 | case GPIO_GENERIC_E: |
298 | info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK; |
299 | break; |
300 | case GPIO_GENERIC_F: |
301 | info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK; |
302 | break; |
303 | case GPIO_GENERIC_G: |
304 | info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK; |
305 | break; |
306 | default: |
307 | BREAK_TO_DEBUGGER(); |
308 | result = false; |
309 | } |
310 | break; |
311 | case GPIO_ID_HPD: |
312 | info->offset = mmDC_GPIO_HPD_A; |
313 | switch (en) { |
314 | case GPIO_HPD_1: |
315 | info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK; |
316 | break; |
317 | case GPIO_HPD_2: |
318 | info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK; |
319 | break; |
320 | case GPIO_HPD_3: |
321 | info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK; |
322 | break; |
323 | case GPIO_HPD_4: |
324 | info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK; |
325 | break; |
326 | case GPIO_HPD_5: |
327 | info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK; |
328 | break; |
329 | case GPIO_HPD_6: |
330 | info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK; |
331 | break; |
332 | default: |
333 | BREAK_TO_DEBUGGER(); |
334 | result = false; |
335 | } |
336 | break; |
337 | case GPIO_ID_SYNC: |
338 | switch (en) { |
339 | case GPIO_SYNC_HSYNC_A: |
340 | info->offset = mmDC_GPIO_SYNCA_A; |
341 | info->mask = DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK; |
342 | break; |
343 | case GPIO_SYNC_VSYNC_A: |
344 | info->offset = mmDC_GPIO_SYNCA_A; |
345 | info->mask = DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK; |
346 | break; |
347 | case GPIO_SYNC_HSYNC_B: |
348 | case GPIO_SYNC_VSYNC_B: |
349 | default: |
350 | BREAK_TO_DEBUGGER(); |
351 | result = false; |
352 | } |
353 | break; |
354 | case GPIO_ID_GSL: |
355 | switch (en) { |
356 | case GPIO_GSL_GENLOCK_CLOCK: |
357 | info->offset = mmDC_GPIO_GENLK_A; |
358 | info->mask = DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK; |
359 | break; |
360 | case GPIO_GSL_GENLOCK_VSYNC: |
361 | info->offset = mmDC_GPIO_GENLK_A; |
362 | info->mask = |
363 | DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK; |
364 | break; |
365 | case GPIO_GSL_SWAPLOCK_A: |
366 | info->offset = mmDC_GPIO_GENLK_A; |
367 | info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK; |
368 | break; |
369 | case GPIO_GSL_SWAPLOCK_B: |
370 | info->offset = mmDC_GPIO_GENLK_A; |
371 | info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK; |
372 | break; |
373 | default: |
374 | BREAK_TO_DEBUGGER(); |
375 | result = false; |
376 | } |
377 | break; |
378 | case GPIO_ID_GPIO_PAD: |
379 | info->offset = mmGPIOPAD_A; |
380 | info->mask = (1 << en); |
381 | result = (info->mask <= GPIO_GPIO_PAD_MAX); |
382 | break; |
383 | case GPIO_ID_VIP_PAD: |
384 | default: |
385 | BREAK_TO_DEBUGGER(); |
386 | result = false; |
387 | } |
388 | |
389 | if (result) { |
390 | info->offset_y = info->offset + 2; |
391 | info->offset_en = info->offset + 1; |
392 | info->offset_mask = info->offset - 1; |
393 | |
394 | info->mask_y = info->mask; |
395 | info->mask_en = info->mask; |
396 | info->mask_mask = info->mask; |
397 | } |
398 | |
399 | return result; |
400 | } |
401 | |
402 | static const struct hw_translate_funcs funcs = { |
403 | .offset_to_id = offset_to_id, |
404 | .id_to_offset = id_to_offset, |
405 | }; |
406 | |
407 | void dal_hw_translate_dce80_init( |
408 | struct hw_translate *translate) |
409 | { |
410 | translate->funcs = &funcs; |
411 | } |
412 | |