xref: /netbsd-src/sys/external/bsd/drm2/dist/drm/amd/display/dc/gpio/dce80/amdgpu_hw_translate_dce80.c (revision 41ec02673d281bbb3d38e6c78504ce6e30c228c1)
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