1 /* $NetBSD: amdgpu_hw_translate_dce80.c,v 1.2 2021/12/18 23:45:05 riastradh Exp $ */
2
3 /*
4 * Copyright 2012-15 Advanced Micro Devices, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors: AMD
25 *
26 */
27
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: amdgpu_hw_translate_dce80.c,v 1.2 2021/12/18 23:45:05 riastradh Exp $");
30
31 #include "dm_services.h"
32
33 /*
34 * Pre-requisites: headers required by header of this unit
35 */
36 #include "include/gpio_types.h"
37 #include "../hw_translate.h"
38
39 #include "hw_translate_dce80.h"
40
41 #include "dce/dce_8_0_d.h"
42 #include "dce/dce_8_0_sh_mask.h"
43 #include "smu/smu_7_0_1_d.h"
44
45 /*
46 * @brief
47 * Returns index of first bit (starting with LSB) which is set
48 */
index_from_vector(uint32_t vector)49 static uint32_t index_from_vector(
50 uint32_t vector)
51 {
52 uint32_t result = 0;
53 uint32_t mask = 1;
54
55 do {
56 if (vector == mask)
57 return result;
58
59 ++result;
60 mask <<= 1;
61 } while (mask);
62
63 BREAK_TO_DEBUGGER();
64
65 return GPIO_ENUM_UNKNOWN;
66 }
67
offset_to_id(uint32_t offset,uint32_t mask,enum gpio_id * id,uint32_t * en)68 static bool offset_to_id(
69 uint32_t offset,
70 uint32_t mask,
71 enum gpio_id *id,
72 uint32_t *en)
73 {
74 switch (offset) {
75 /* GENERIC */
76 case mmDC_GPIO_GENERIC_A:
77 *id = GPIO_ID_GENERIC;
78 switch (mask) {
79 case DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK:
80 *en = GPIO_GENERIC_A;
81 return true;
82 case DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK:
83 *en = GPIO_GENERIC_B;
84 return true;
85 case DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK:
86 *en = GPIO_GENERIC_C;
87 return true;
88 case DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK:
89 *en = GPIO_GENERIC_D;
90 return true;
91 case DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK:
92 *en = GPIO_GENERIC_E;
93 return true;
94 case DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK:
95 *en = GPIO_GENERIC_F;
96 return true;
97 case DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK:
98 *en = GPIO_GENERIC_G;
99 return true;
100 default:
101 BREAK_TO_DEBUGGER();
102 return false;
103 }
104 break;
105 /* HPD */
106 case mmDC_GPIO_HPD_A:
107 *id = GPIO_ID_HPD;
108 switch (mask) {
109 case DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK:
110 *en = GPIO_HPD_1;
111 return true;
112 case DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK:
113 *en = GPIO_HPD_2;
114 return true;
115 case DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK:
116 *en = GPIO_HPD_3;
117 return true;
118 case DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK:
119 *en = GPIO_HPD_4;
120 return true;
121 case DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK:
122 *en = GPIO_HPD_5;
123 return true;
124 case DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK:
125 *en = GPIO_HPD_6;
126 return true;
127 default:
128 BREAK_TO_DEBUGGER();
129 return false;
130 }
131 break;
132 /* SYNCA */
133 case mmDC_GPIO_SYNCA_A:
134 *id = GPIO_ID_SYNC;
135 switch (mask) {
136 case DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK:
137 *en = GPIO_SYNC_HSYNC_A;
138 return true;
139 case DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK:
140 *en = GPIO_SYNC_VSYNC_A;
141 return true;
142 default:
143 BREAK_TO_DEBUGGER();
144 return false;
145 }
146 break;
147 /* mmDC_GPIO_GENLK_MASK */
148 case mmDC_GPIO_GENLK_A:
149 *id = GPIO_ID_GSL;
150 switch (mask) {
151 case DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK:
152 *en = GPIO_GSL_GENLOCK_CLOCK;
153 return true;
154 case DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK:
155 *en = GPIO_GSL_GENLOCK_VSYNC;
156 return true;
157 case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK:
158 *en = GPIO_GSL_SWAPLOCK_A;
159 return true;
160 case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK:
161 *en = GPIO_GSL_SWAPLOCK_B;
162 return true;
163 default:
164 BREAK_TO_DEBUGGER();
165 return false;
166 }
167 break;
168 /* GPIOPAD */
169 case mmGPIOPAD_A:
170 *id = GPIO_ID_GPIO_PAD;
171 *en = index_from_vector(mask);
172 return (*en <= GPIO_GPIO_PAD_MAX);
173 /* DDC */
174 /* we don't care about the GPIO_ID for DDC
175 * in DdcHandle it will use GPIO_ID_DDC_DATA/GPIO_ID_DDC_CLOCK
176 * directly in the create method */
177 case mmDC_GPIO_DDC1_A:
178 *en = GPIO_DDC_LINE_DDC1;
179 return true;
180 case mmDC_GPIO_DDC2_A:
181 *en = GPIO_DDC_LINE_DDC2;
182 return true;
183 case mmDC_GPIO_DDC3_A:
184 *en = GPIO_DDC_LINE_DDC3;
185 return true;
186 case mmDC_GPIO_DDC4_A:
187 *en = GPIO_DDC_LINE_DDC4;
188 return true;
189 case mmDC_GPIO_DDC5_A:
190 *en = GPIO_DDC_LINE_DDC5;
191 return true;
192 case mmDC_GPIO_DDC6_A:
193 *en = GPIO_DDC_LINE_DDC6;
194 return true;
195 case mmDC_GPIO_DDCVGA_A:
196 *en = GPIO_DDC_LINE_DDC_VGA;
197 return true;
198 /* GPIO_I2CPAD */
199 case mmDC_GPIO_I2CPAD_A:
200 *en = GPIO_DDC_LINE_I2C_PAD;
201 return true;
202 /* Not implemented */
203 case mmDC_GPIO_PWRSEQ_A:
204 case mmDC_GPIO_PAD_STRENGTH_1:
205 case mmDC_GPIO_PAD_STRENGTH_2:
206 case mmDC_GPIO_DEBUG:
207 return false;
208 /* UNEXPECTED */
209 default:
210 BREAK_TO_DEBUGGER();
211 return false;
212 }
213 }
214
id_to_offset(enum gpio_id id,uint32_t en,struct gpio_pin_info * info)215 static bool id_to_offset(
216 enum gpio_id id,
217 uint32_t en,
218 struct gpio_pin_info *info)
219 {
220 bool result = true;
221
222 switch (id) {
223 case GPIO_ID_DDC_DATA:
224 info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK;
225 switch (en) {
226 case GPIO_DDC_LINE_DDC1:
227 info->offset = mmDC_GPIO_DDC1_A;
228 break;
229 case GPIO_DDC_LINE_DDC2:
230 info->offset = mmDC_GPIO_DDC2_A;
231 break;
232 case GPIO_DDC_LINE_DDC3:
233 info->offset = mmDC_GPIO_DDC3_A;
234 break;
235 case GPIO_DDC_LINE_DDC4:
236 info->offset = mmDC_GPIO_DDC4_A;
237 break;
238 case GPIO_DDC_LINE_DDC5:
239 info->offset = mmDC_GPIO_DDC5_A;
240 break;
241 case GPIO_DDC_LINE_DDC6:
242 info->offset = mmDC_GPIO_DDC6_A;
243 break;
244 case GPIO_DDC_LINE_DDC_VGA:
245 info->offset = mmDC_GPIO_DDCVGA_A;
246 break;
247 case GPIO_DDC_LINE_I2C_PAD:
248 info->offset = mmDC_GPIO_I2CPAD_A;
249 break;
250 default:
251 BREAK_TO_DEBUGGER();
252 result = false;
253 }
254 break;
255 case GPIO_ID_DDC_CLOCK:
256 info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A_MASK;
257 switch (en) {
258 case GPIO_DDC_LINE_DDC1:
259 info->offset = mmDC_GPIO_DDC1_A;
260 break;
261 case GPIO_DDC_LINE_DDC2:
262 info->offset = mmDC_GPIO_DDC2_A;
263 break;
264 case GPIO_DDC_LINE_DDC3:
265 info->offset = mmDC_GPIO_DDC3_A;
266 break;
267 case GPIO_DDC_LINE_DDC4:
268 info->offset = mmDC_GPIO_DDC4_A;
269 break;
270 case GPIO_DDC_LINE_DDC5:
271 info->offset = mmDC_GPIO_DDC5_A;
272 break;
273 case GPIO_DDC_LINE_DDC6:
274 info->offset = mmDC_GPIO_DDC6_A;
275 break;
276 case GPIO_DDC_LINE_DDC_VGA:
277 info->offset = mmDC_GPIO_DDCVGA_A;
278 break;
279 case GPIO_DDC_LINE_I2C_PAD:
280 info->offset = mmDC_GPIO_I2CPAD_A;
281 break;
282 default:
283 BREAK_TO_DEBUGGER();
284 result = false;
285 }
286 break;
287 case GPIO_ID_GENERIC:
288 info->offset = mmDC_GPIO_GENERIC_A;
289 switch (en) {
290 case GPIO_GENERIC_A:
291 info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK;
292 break;
293 case GPIO_GENERIC_B:
294 info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK;
295 break;
296 case GPIO_GENERIC_C:
297 info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK;
298 break;
299 case GPIO_GENERIC_D:
300 info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK;
301 break;
302 case GPIO_GENERIC_E:
303 info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK;
304 break;
305 case GPIO_GENERIC_F:
306 info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK;
307 break;
308 case GPIO_GENERIC_G:
309 info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK;
310 break;
311 default:
312 BREAK_TO_DEBUGGER();
313 result = false;
314 }
315 break;
316 case GPIO_ID_HPD:
317 info->offset = mmDC_GPIO_HPD_A;
318 switch (en) {
319 case GPIO_HPD_1:
320 info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK;
321 break;
322 case GPIO_HPD_2:
323 info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK;
324 break;
325 case GPIO_HPD_3:
326 info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK;
327 break;
328 case GPIO_HPD_4:
329 info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK;
330 break;
331 case GPIO_HPD_5:
332 info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK;
333 break;
334 case GPIO_HPD_6:
335 info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK;
336 break;
337 default:
338 BREAK_TO_DEBUGGER();
339 result = false;
340 }
341 break;
342 case GPIO_ID_SYNC:
343 switch (en) {
344 case GPIO_SYNC_HSYNC_A:
345 info->offset = mmDC_GPIO_SYNCA_A;
346 info->mask = DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK;
347 break;
348 case GPIO_SYNC_VSYNC_A:
349 info->offset = mmDC_GPIO_SYNCA_A;
350 info->mask = DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK;
351 break;
352 case GPIO_SYNC_HSYNC_B:
353 case GPIO_SYNC_VSYNC_B:
354 default:
355 BREAK_TO_DEBUGGER();
356 result = false;
357 }
358 break;
359 case GPIO_ID_GSL:
360 switch (en) {
361 case GPIO_GSL_GENLOCK_CLOCK:
362 info->offset = mmDC_GPIO_GENLK_A;
363 info->mask = DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK;
364 break;
365 case GPIO_GSL_GENLOCK_VSYNC:
366 info->offset = mmDC_GPIO_GENLK_A;
367 info->mask =
368 DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK;
369 break;
370 case GPIO_GSL_SWAPLOCK_A:
371 info->offset = mmDC_GPIO_GENLK_A;
372 info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK;
373 break;
374 case GPIO_GSL_SWAPLOCK_B:
375 info->offset = mmDC_GPIO_GENLK_A;
376 info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK;
377 break;
378 default:
379 BREAK_TO_DEBUGGER();
380 result = false;
381 }
382 break;
383 case GPIO_ID_GPIO_PAD:
384 info->offset = mmGPIOPAD_A;
385 info->mask = (1 << en);
386 result = (info->mask <= GPIO_GPIO_PAD_MAX);
387 break;
388 case GPIO_ID_VIP_PAD:
389 default:
390 BREAK_TO_DEBUGGER();
391 result = false;
392 }
393
394 if (result) {
395 info->offset_y = info->offset + 2;
396 info->offset_en = info->offset + 1;
397 info->offset_mask = info->offset - 1;
398
399 info->mask_y = info->mask;
400 info->mask_en = info->mask;
401 info->mask_mask = info->mask;
402 }
403
404 return result;
405 }
406
407 static const struct hw_translate_funcs funcs = {
408 .offset_to_id = offset_to_id,
409 .id_to_offset = id_to_offset,
410 };
411
dal_hw_translate_dce80_init(struct hw_translate * translate)412 void dal_hw_translate_dce80_init(
413 struct hw_translate *translate)
414 {
415 translate->funcs = &funcs;
416 }
417