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