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