xref: /netbsd-src/sys/external/bsd/drm2/dist/drm/amd/display/dc/gpio/amdgpu_gpio_base.c (revision 41ec02673d281bbb3d38e6c78504ce6e30c228c1)
1 /*	$NetBSD: amdgpu_gpio_base.c,v 1.2 2021/12/18 23:45:04 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 /*
29  * Pre-requisites: headers required by header of this unit
30  */
31 
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: amdgpu_gpio_base.c,v 1.2 2021/12/18 23:45:04 riastradh Exp $");
34 
35 #include <linux/slab.h>
36 
37 #include "dm_services.h"
38 
39 #include "include/gpio_interface.h"
40 #include "include/gpio_service_interface.h"
41 #include "hw_gpio.h"
42 #include "hw_translate.h"
43 #include "hw_factory.h"
44 #include "gpio_service.h"
45 
46 /*
47  * Post-requisites: headers required by this unit
48  */
49 
50 /*
51  * This unit
52  */
53 
54 /*
55  * @brief
56  * Public API
57  */
58 
dal_gpio_open(struct gpio * gpio,enum gpio_mode mode)59 enum gpio_result dal_gpio_open(
60 	struct gpio *gpio,
61 	enum gpio_mode mode)
62 {
63 	return dal_gpio_open_ex(gpio, mode);
64 }
65 
dal_gpio_open_ex(struct gpio * gpio,enum gpio_mode mode)66 enum gpio_result dal_gpio_open_ex(
67 	struct gpio *gpio,
68 	enum gpio_mode mode)
69 {
70 	if (gpio->pin) {
71 		ASSERT_CRITICAL(false);
72 		return GPIO_RESULT_ALREADY_OPENED;
73 	}
74 
75 	// No action if allocation failed during gpio construct
76 	if (!gpio->hw_container.ddc) {
77 		ASSERT_CRITICAL(false);
78 		return GPIO_RESULT_NON_SPECIFIC_ERROR;
79 	}
80 	gpio->mode = mode;
81 
82 	return dal_gpio_service_open(gpio);
83 }
84 
dal_gpio_get_value(const struct gpio * gpio,uint32_t * value)85 enum gpio_result dal_gpio_get_value(
86 	const struct gpio *gpio,
87 	uint32_t *value)
88 {
89 	if (!gpio->pin) {
90 		BREAK_TO_DEBUGGER();
91 		return GPIO_RESULT_NULL_HANDLE;
92 	}
93 
94 	return gpio->pin->funcs->get_value(gpio->pin, value);
95 }
96 
dal_gpio_set_value(const struct gpio * gpio,uint32_t value)97 enum gpio_result dal_gpio_set_value(
98 	const struct gpio *gpio,
99 	uint32_t value)
100 {
101 	if (!gpio->pin) {
102 		BREAK_TO_DEBUGGER();
103 		return GPIO_RESULT_NULL_HANDLE;
104 	}
105 
106 	return gpio->pin->funcs->set_value(gpio->pin, value);
107 }
108 
dal_gpio_get_mode(const struct gpio * gpio)109 enum gpio_mode dal_gpio_get_mode(
110 	const struct gpio *gpio)
111 {
112 	return gpio->mode;
113 }
114 
dal_gpio_lock_pin(struct gpio * gpio)115 enum gpio_result dal_gpio_lock_pin(
116 	struct gpio *gpio)
117 {
118 	return dal_gpio_service_lock(gpio->service, gpio->id, gpio->en);
119 }
120 
dal_gpio_unlock_pin(struct gpio * gpio)121 enum gpio_result dal_gpio_unlock_pin(
122 	struct gpio *gpio)
123 {
124 	return dal_gpio_service_unlock(gpio->service, gpio->id, gpio->en);
125 }
126 
dal_gpio_change_mode(struct gpio * gpio,enum gpio_mode mode)127 enum gpio_result dal_gpio_change_mode(
128 	struct gpio *gpio,
129 	enum gpio_mode mode)
130 {
131 	if (!gpio->pin) {
132 		BREAK_TO_DEBUGGER();
133 		return GPIO_RESULT_NULL_HANDLE;
134 	}
135 
136 	return gpio->pin->funcs->change_mode(gpio->pin, mode);
137 }
138 
dal_gpio_get_id(const struct gpio * gpio)139 enum gpio_id dal_gpio_get_id(
140 	const struct gpio *gpio)
141 {
142 	return gpio->id;
143 }
144 
dal_gpio_get_enum(const struct gpio * gpio)145 uint32_t dal_gpio_get_enum(
146 	const struct gpio *gpio)
147 {
148 	return gpio->en;
149 }
150 
dal_gpio_set_config(struct gpio * gpio,const struct gpio_config_data * config_data)151 enum gpio_result dal_gpio_set_config(
152 	struct gpio *gpio,
153 	const struct gpio_config_data *config_data)
154 {
155 	if (!gpio->pin) {
156 		BREAK_TO_DEBUGGER();
157 		return GPIO_RESULT_NULL_HANDLE;
158 	}
159 
160 	return gpio->pin->funcs->set_config(gpio->pin, config_data);
161 }
162 
dal_gpio_get_pin_info(const struct gpio * gpio,struct gpio_pin_info * pin_info)163 enum gpio_result dal_gpio_get_pin_info(
164 	const struct gpio *gpio,
165 	struct gpio_pin_info *pin_info)
166 {
167 	return gpio->service->translate.funcs->id_to_offset(
168 		gpio->id, gpio->en, pin_info) ?
169 		GPIO_RESULT_OK : GPIO_RESULT_INVALID_DATA;
170 }
171 
dal_gpio_get_sync_source(const struct gpio * gpio)172 enum sync_source dal_gpio_get_sync_source(
173 	const struct gpio *gpio)
174 {
175 	switch (gpio->id) {
176 	case GPIO_ID_GENERIC:
177 		switch (gpio->en) {
178 		case GPIO_GENERIC_A:
179 			return SYNC_SOURCE_IO_GENERIC_A;
180 		case GPIO_GENERIC_B:
181 			return SYNC_SOURCE_IO_GENERIC_B;
182 		case GPIO_GENERIC_C:
183 			return SYNC_SOURCE_IO_GENERIC_C;
184 		case GPIO_GENERIC_D:
185 			return SYNC_SOURCE_IO_GENERIC_D;
186 		case GPIO_GENERIC_E:
187 			return SYNC_SOURCE_IO_GENERIC_E;
188 		case GPIO_GENERIC_F:
189 			return SYNC_SOURCE_IO_GENERIC_F;
190 		default:
191 			return SYNC_SOURCE_NONE;
192 		}
193 	break;
194 	case GPIO_ID_SYNC:
195 		switch (gpio->en) {
196 		case GPIO_SYNC_HSYNC_A:
197 			return SYNC_SOURCE_IO_HSYNC_A;
198 		case GPIO_SYNC_VSYNC_A:
199 			return SYNC_SOURCE_IO_VSYNC_A;
200 		case GPIO_SYNC_HSYNC_B:
201 			return SYNC_SOURCE_IO_HSYNC_B;
202 		case GPIO_SYNC_VSYNC_B:
203 			return SYNC_SOURCE_IO_VSYNC_B;
204 		default:
205 			return SYNC_SOURCE_NONE;
206 		}
207 	break;
208 	case GPIO_ID_HPD:
209 		switch (gpio->en) {
210 		case GPIO_HPD_1:
211 			return SYNC_SOURCE_IO_HPD1;
212 		case GPIO_HPD_2:
213 			return SYNC_SOURCE_IO_HPD2;
214 		default:
215 			return SYNC_SOURCE_NONE;
216 		}
217 	break;
218 	case GPIO_ID_GSL:
219 		switch (gpio->en) {
220 		case GPIO_GSL_GENLOCK_CLOCK:
221 			return SYNC_SOURCE_GSL_IO_GENLOCK_CLOCK;
222 		case GPIO_GSL_GENLOCK_VSYNC:
223 			return SYNC_SOURCE_GSL_IO_GENLOCK_VSYNC;
224 		case GPIO_GSL_SWAPLOCK_A:
225 			return SYNC_SOURCE_GSL_IO_SWAPLOCK_A;
226 		case GPIO_GSL_SWAPLOCK_B:
227 			return SYNC_SOURCE_GSL_IO_SWAPLOCK_B;
228 		default:
229 			return SYNC_SOURCE_NONE;
230 		}
231 	break;
232 	default:
233 		return SYNC_SOURCE_NONE;
234 	}
235 }
236 
dal_gpio_get_output_state(const struct gpio * gpio)237 enum gpio_pin_output_state dal_gpio_get_output_state(
238 	const struct gpio *gpio)
239 {
240 	return gpio->output_state;
241 }
242 
dal_gpio_get_ddc(struct gpio * gpio)243 struct hw_ddc *dal_gpio_get_ddc(struct gpio *gpio)
244 {
245 	return gpio->hw_container.ddc;
246 }
247 
dal_gpio_get_hpd(struct gpio * gpio)248 struct hw_hpd *dal_gpio_get_hpd(struct gpio *gpio)
249 {
250 	return gpio->hw_container.hpd;
251 }
252 
dal_gpio_get_generic(struct gpio * gpio)253 struct hw_generic *dal_gpio_get_generic(struct gpio *gpio)
254 {
255 	return gpio->hw_container.generic;
256 }
257 
dal_gpio_close(struct gpio * gpio)258 void dal_gpio_close(
259 	struct gpio *gpio)
260 {
261 	if (!gpio)
262 		return;
263 
264 	dal_gpio_service_close(gpio->service, &gpio->pin);
265 
266 	gpio->mode = GPIO_MODE_UNKNOWN;
267 }
268 
269 /*
270  * @brief
271  * Creation and destruction
272  */
273 
dal_gpio_create(struct gpio_service * service,enum gpio_id id,uint32_t en,enum gpio_pin_output_state output_state)274 struct gpio *dal_gpio_create(
275 	struct gpio_service *service,
276 	enum gpio_id id,
277 	uint32_t en,
278 	enum gpio_pin_output_state output_state)
279 {
280 	struct gpio *gpio = kzalloc(sizeof(struct gpio), GFP_KERNEL);
281 
282 	if (!gpio) {
283 		ASSERT_CRITICAL(false);
284 		return NULL;
285 	}
286 
287 	gpio->service = service;
288 	gpio->pin = NULL;
289 	gpio->id = id;
290 	gpio->en = en;
291 	gpio->mode = GPIO_MODE_UNKNOWN;
292 	gpio->output_state = output_state;
293 
294 	//initialize hw_container union based on id
295 	switch (gpio->id) {
296 	case GPIO_ID_DDC_DATA:
297 		gpio->service->factory.funcs->init_ddc_data(&gpio->hw_container.ddc, service->ctx, id, en);
298 		break;
299 	case GPIO_ID_DDC_CLOCK:
300 		gpio->service->factory.funcs->init_ddc_data(&gpio->hw_container.ddc, service->ctx, id, en);
301 		break;
302 	case GPIO_ID_GENERIC:
303 		gpio->service->factory.funcs->init_generic(&gpio->hw_container.generic, service->ctx, id, en);
304 		break;
305 	case GPIO_ID_HPD:
306 		gpio->service->factory.funcs->init_hpd(&gpio->hw_container.hpd, service->ctx, id, en);
307 		break;
308 	// TODO: currently gpio for sync and gsl does not get created, might need it later
309 	case GPIO_ID_SYNC:
310 		break;
311 	case GPIO_ID_GSL:
312 		break;
313 	default:
314 		ASSERT_CRITICAL(false);
315 		gpio->pin = NULL;
316 	}
317 
318 	return gpio;
319 }
320 
dal_gpio_destroy(struct gpio ** gpio)321 void dal_gpio_destroy(
322 	struct gpio **gpio)
323 {
324 	if (!gpio || !*gpio) {
325 		ASSERT_CRITICAL(false);
326 		return;
327 	}
328 
329 	switch ((*gpio)->id) {
330 	case GPIO_ID_DDC_DATA:
331 		kfree((*gpio)->hw_container.ddc);
332 		(*gpio)->hw_container.ddc = NULL;
333 		break;
334 	case GPIO_ID_DDC_CLOCK:
335 		//TODO: might want to change it to init_ddc_clock
336 		kfree((*gpio)->hw_container.ddc);
337 		(*gpio)->hw_container.ddc = NULL;
338 		break;
339 	case GPIO_ID_GENERIC:
340 		kfree((*gpio)->hw_container.generic);
341 		(*gpio)->hw_container.generic = NULL;
342 		break;
343 	case GPIO_ID_HPD:
344 		kfree((*gpio)->hw_container.hpd);
345 		(*gpio)->hw_container.hpd = NULL;
346 		break;
347 	// TODO: currently gpio for sync and gsl does not get created, might need it later
348 	case GPIO_ID_SYNC:
349 		break;
350 	case GPIO_ID_GSL:
351 		break;
352 	default:
353 		break;
354 	}
355 
356 	kfree(*gpio);
357 
358 	*gpio = NULL;
359 }
360