1/*
2 * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com>
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_dce60.h"
35
36#include "dce/dce_6_0_d.h"
37#include "dce/dce_6_0_sh_mask.h"
38#include "smu/smu_6_0_d.h"
39
40/*
41 * @brief
42 * Returns index of first bit (starting with LSB) which is set
43 */
44static 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
63static 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
210static 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
402static const struct hw_translate_funcs funcs = {
403 .offset_to_id = offset_to_id,
404 .id_to_offset = id_to_offset,
405};
406
407void dal_hw_translate_dce60_init(
408 struct hw_translate *translate)
409{
410 translate->funcs = &funcs;
411}
412

source code of linux/drivers/gpu/drm/amd/display/dc/gpio/dce60/hw_translate_dce60.c