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