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 <linux/slab.h>
31 
32 #include "dm_services.h"
33 
34 #include "include/gpio_interface.h"
35 #include "include/gpio_service_interface.h"
36 #include "hw_gpio.h"
37 #include "hw_translate.h"
38 #include "hw_factory.h"
39 #include "gpio_service.h"
40 
41 /*
42  * Post-requisites: headers required by this unit
43  */
44 
45 /*
46  * This unit
47  */
48 
49 /*
50  * @brief
51  * Public API
52  */
53 
54 enum gpio_result dal_gpio_open(
55 	struct gpio *gpio,
56 	enum gpio_mode mode)
57 {
58 	return dal_gpio_open_ex(gpio, mode);
59 }
60 
61 enum gpio_result dal_gpio_open_ex(
62 	struct gpio *gpio,
63 	enum gpio_mode mode)
64 {
65 	if (gpio->pin) {
66 		ASSERT_CRITICAL(false);
67 		return GPIO_RESULT_ALREADY_OPENED;
68 	}
69 
70 	gpio->mode = mode;
71 
72 	return dal_gpio_service_open(
73 		gpio->service, gpio->id, gpio->en, mode, &gpio->pin);
74 }
75 
76 enum gpio_result dal_gpio_get_value(
77 	const struct gpio *gpio,
78 	uint32_t *value)
79 {
80 	if (!gpio->pin) {
81 		BREAK_TO_DEBUGGER();
82 		return GPIO_RESULT_NULL_HANDLE;
83 	}
84 
85 	return gpio->pin->funcs->get_value(gpio->pin, value);
86 }
87 
88 enum gpio_result dal_gpio_set_value(
89 	const struct gpio *gpio,
90 	uint32_t value)
91 {
92 	if (!gpio->pin) {
93 		BREAK_TO_DEBUGGER();
94 		return GPIO_RESULT_NULL_HANDLE;
95 	}
96 
97 	return gpio->pin->funcs->set_value(gpio->pin, value);
98 }
99 
100 enum gpio_mode dal_gpio_get_mode(
101 	const struct gpio *gpio)
102 {
103 	return gpio->mode;
104 }
105 
106 enum gpio_result dal_gpio_lock_pin(
107 	struct gpio *gpio)
108 {
109 	return dal_gpio_service_lock(gpio->service, gpio->id, gpio->en);
110 }
111 
112 enum gpio_result dal_gpio_unlock_pin(
113 	struct gpio *gpio)
114 {
115 	return dal_gpio_service_unlock(gpio->service, gpio->id, gpio->en);
116 }
117 
118 enum gpio_result dal_gpio_change_mode(
119 	struct gpio *gpio,
120 	enum gpio_mode mode)
121 {
122 	if (!gpio->pin) {
123 		BREAK_TO_DEBUGGER();
124 		return GPIO_RESULT_NULL_HANDLE;
125 	}
126 
127 	return gpio->pin->funcs->change_mode(gpio->pin, mode);
128 }
129 
130 enum gpio_id dal_gpio_get_id(
131 	const struct gpio *gpio)
132 {
133 	return gpio->id;
134 }
135 
136 uint32_t dal_gpio_get_enum(
137 	const struct gpio *gpio)
138 {
139 	return gpio->en;
140 }
141 
142 enum gpio_result dal_gpio_set_config(
143 	struct gpio *gpio,
144 	const struct gpio_config_data *config_data)
145 {
146 	if (!gpio->pin) {
147 		BREAK_TO_DEBUGGER();
148 		return GPIO_RESULT_NULL_HANDLE;
149 	}
150 
151 	return gpio->pin->funcs->set_config(gpio->pin, config_data);
152 }
153 
154 enum gpio_result dal_gpio_get_pin_info(
155 	const struct gpio *gpio,
156 	struct gpio_pin_info *pin_info)
157 {
158 	return gpio->service->translate.funcs->id_to_offset(
159 		gpio->id, gpio->en, pin_info) ?
160 		GPIO_RESULT_OK : GPIO_RESULT_INVALID_DATA;
161 }
162 
163 enum sync_source dal_gpio_get_sync_source(
164 	const struct gpio *gpio)
165 {
166 	switch (gpio->id) {
167 	case GPIO_ID_GENERIC:
168 		switch (gpio->en) {
169 		case GPIO_GENERIC_A:
170 			return SYNC_SOURCE_IO_GENERIC_A;
171 		case GPIO_GENERIC_B:
172 			return SYNC_SOURCE_IO_GENERIC_B;
173 		case GPIO_GENERIC_C:
174 			return SYNC_SOURCE_IO_GENERIC_C;
175 		case GPIO_GENERIC_D:
176 			return SYNC_SOURCE_IO_GENERIC_D;
177 		case GPIO_GENERIC_E:
178 			return SYNC_SOURCE_IO_GENERIC_E;
179 		case GPIO_GENERIC_F:
180 			return SYNC_SOURCE_IO_GENERIC_F;
181 		default:
182 			return SYNC_SOURCE_NONE;
183 		}
184 	break;
185 	case GPIO_ID_SYNC:
186 		switch (gpio->en) {
187 		case GPIO_SYNC_HSYNC_A:
188 			return SYNC_SOURCE_IO_HSYNC_A;
189 		case GPIO_SYNC_VSYNC_A:
190 			return SYNC_SOURCE_IO_VSYNC_A;
191 		case GPIO_SYNC_HSYNC_B:
192 			return SYNC_SOURCE_IO_HSYNC_B;
193 		case GPIO_SYNC_VSYNC_B:
194 			return SYNC_SOURCE_IO_VSYNC_B;
195 		default:
196 			return SYNC_SOURCE_NONE;
197 		}
198 	break;
199 	case GPIO_ID_HPD:
200 		switch (gpio->en) {
201 		case GPIO_HPD_1:
202 			return SYNC_SOURCE_IO_HPD1;
203 		case GPIO_HPD_2:
204 			return SYNC_SOURCE_IO_HPD2;
205 		default:
206 			return SYNC_SOURCE_NONE;
207 		}
208 	break;
209 	case GPIO_ID_GSL:
210 		switch (gpio->en) {
211 		case GPIO_GSL_GENLOCK_CLOCK:
212 			return SYNC_SOURCE_GSL_IO_GENLOCK_CLOCK;
213 		case GPIO_GSL_GENLOCK_VSYNC:
214 			return SYNC_SOURCE_GSL_IO_GENLOCK_VSYNC;
215 		case GPIO_GSL_SWAPLOCK_A:
216 			return SYNC_SOURCE_GSL_IO_SWAPLOCK_A;
217 		case GPIO_GSL_SWAPLOCK_B:
218 			return SYNC_SOURCE_GSL_IO_SWAPLOCK_B;
219 		default:
220 			return SYNC_SOURCE_NONE;
221 		}
222 	break;
223 	default:
224 		return SYNC_SOURCE_NONE;
225 	}
226 }
227 
228 enum gpio_pin_output_state dal_gpio_get_output_state(
229 	const struct gpio *gpio)
230 {
231 	return gpio->output_state;
232 }
233 
234 void dal_gpio_close(
235 	struct gpio *gpio)
236 {
237 	if (!gpio)
238 		return;
239 
240 	dal_gpio_service_close(gpio->service, &gpio->pin);
241 
242 	gpio->mode = GPIO_MODE_UNKNOWN;
243 }
244 
245 /*
246  * @brief
247  * Creation and destruction
248  */
249 
250 struct gpio *dal_gpio_create(
251 	struct gpio_service *service,
252 	enum gpio_id id,
253 	uint32_t en,
254 	enum gpio_pin_output_state output_state)
255 {
256 	struct gpio *gpio = kzalloc(sizeof(struct gpio), GFP_KERNEL);
257 
258 	if (!gpio) {
259 		ASSERT_CRITICAL(false);
260 		return NULL;
261 	}
262 
263 	gpio->service = service;
264 	gpio->pin = NULL;
265 	gpio->id = id;
266 	gpio->en = en;
267 	gpio->mode = GPIO_MODE_UNKNOWN;
268 	gpio->output_state = output_state;
269 
270 	return gpio;
271 }
272 
273 void dal_gpio_destroy(
274 	struct gpio **gpio)
275 {
276 	if (!gpio || !*gpio) {
277 		ASSERT_CRITICAL(false);
278 		return;
279 	}
280 
281 	dal_gpio_close(*gpio);
282 
283 	kfree(*gpio);
284 
285 	*gpio = NULL;
286 }
287