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  */
index_from_vector(uint32_t vector)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 
offset_to_id(uint32_t offset,uint32_t mask,enum gpio_id * id,uint32_t * en)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(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 
id_to_offset(enum gpio_id id,uint32_t en,struct gpio_pin_info * info)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 
dal_hw_translate_dce60_init(struct hw_translate * translate)407 void dal_hw_translate_dce60_init(
408 	struct hw_translate *translate)
409 {
410 	translate->funcs = &funcs;
411 }
412