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(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