root/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dal_gpio_service_create
  2. dal_gpio_service_create_irq
  3. dal_gpio_service_create_generic_mux
  4. dal_gpio_destroy_generic_mux
  5. dal_gpio_get_generic_pin_info
  6. dal_gpio_service_destroy
  7. dal_mux_setup_config
  8. is_pin_busy
  9. set_pin_busy
  10. set_pin_free
  11. dal_gpio_service_lock
  12. dal_gpio_service_unlock
  13. dal_gpio_service_open
  14. dal_gpio_service_close
  15. dal_irq_get_source
  16. dal_irq_get_rx_source
  17. dal_irq_setup_hpd_filter
  18. dal_gpio_create_irq
  19. dal_gpio_destroy_irq
  20. dal_gpio_create_ddc
  21. dal_gpio_destroy_ddc
  22. dal_ddc_open
  23. dal_ddc_change_mode
  24. dal_ddc_get_line
  25. dal_ddc_set_config
  26. dal_ddc_close

   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 #include "include/gpio_interface.h"
  34 #include "include/gpio_service_interface.h"
  35 #include "hw_translate.h"
  36 #include "hw_factory.h"
  37 
  38 /*
  39  * Header of this unit
  40  */
  41 
  42 #include "gpio_service.h"
  43 
  44 /*
  45  * Post-requisites: headers required by this unit
  46  */
  47 
  48 #include "hw_gpio.h"
  49 
  50 /*
  51  * @brief
  52  * Public API.
  53  */
  54 
  55 struct gpio_service *dal_gpio_service_create(
  56         enum dce_version dce_version_major,
  57         enum dce_version dce_version_minor,
  58         struct dc_context *ctx)
  59 {
  60         struct gpio_service *service;
  61         uint32_t index_of_id;
  62 
  63         service = kzalloc(sizeof(struct gpio_service), GFP_KERNEL);
  64 
  65         if (!service) {
  66                 BREAK_TO_DEBUGGER();
  67                 return NULL;
  68         }
  69 
  70         if (!dal_hw_translate_init(&service->translate, dce_version_major,
  71                         dce_version_minor)) {
  72                 BREAK_TO_DEBUGGER();
  73                 goto failure_1;
  74         }
  75 
  76         if (!dal_hw_factory_init(&service->factory, dce_version_major,
  77                         dce_version_minor)) {
  78                 BREAK_TO_DEBUGGER();
  79                 goto failure_1;
  80         }
  81 
  82         /* allocate and initialize busyness storage */
  83         {
  84                 index_of_id = 0;
  85                 service->ctx = ctx;
  86 
  87                 do {
  88                         uint32_t number_of_bits =
  89                                 service->factory.number_of_pins[index_of_id];
  90                         uint32_t i = 0;
  91 
  92                         if (number_of_bits)  {
  93                                 service->busyness[index_of_id] =
  94                                         kcalloc(number_of_bits, sizeof(char),
  95                                                 GFP_KERNEL);
  96 
  97                                 if (!service->busyness[index_of_id]) {
  98                                         BREAK_TO_DEBUGGER();
  99                                         goto failure_2;
 100                                 }
 101 
 102                                 do {
 103                                         service->busyness[index_of_id][i] = 0;
 104                                         ++i;
 105                                 } while (i < number_of_bits);
 106                         } else {
 107                                 service->busyness[index_of_id] = NULL;
 108                         }
 109 
 110                         ++index_of_id;
 111                 } while (index_of_id < GPIO_ID_COUNT);
 112         }
 113 
 114         return service;
 115 
 116 failure_2:
 117         while (index_of_id) {
 118                 --index_of_id;
 119                 kfree(service->busyness[index_of_id]);
 120         }
 121 
 122 failure_1:
 123         kfree(service);
 124 
 125         return NULL;
 126 }
 127 
 128 struct gpio *dal_gpio_service_create_irq(
 129         struct gpio_service *service,
 130         uint32_t offset,
 131         uint32_t mask)
 132 {
 133         enum gpio_id id;
 134         uint32_t en;
 135 
 136         if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) {
 137                 ASSERT_CRITICAL(false);
 138                 return NULL;
 139         }
 140 
 141         return dal_gpio_create_irq(service, id, en);
 142 }
 143 
 144 struct gpio *dal_gpio_service_create_generic_mux(
 145         struct gpio_service *service,
 146         uint32_t offset,
 147         uint32_t mask)
 148 {
 149         enum gpio_id id;
 150         uint32_t en;
 151         struct gpio *generic;
 152 
 153         if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) {
 154                 ASSERT_CRITICAL(false);
 155                 return NULL;
 156         }
 157 
 158         generic = dal_gpio_create(
 159                 service, id, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
 160 
 161         return generic;
 162 }
 163 
 164 void dal_gpio_destroy_generic_mux(
 165         struct gpio **mux)
 166 {
 167         if (!mux || !*mux) {
 168                 ASSERT_CRITICAL(false);
 169                 return;
 170         }
 171 
 172         dal_gpio_close(*mux);
 173         dal_gpio_destroy(mux);
 174         kfree(*mux);
 175 
 176         *mux = NULL;
 177 }
 178 
 179 struct gpio_pin_info dal_gpio_get_generic_pin_info(
 180         struct gpio_service *service,
 181         enum gpio_id id,
 182         uint32_t en)
 183 {
 184         struct gpio_pin_info pin;
 185 
 186         if (service->translate.funcs->id_to_offset) {
 187                 service->translate.funcs->id_to_offset(id, en, &pin);
 188         } else {
 189                 pin.mask = 0xFFFFFFFF;
 190                 pin.offset = 0xFFFFFFFF;
 191         }
 192 
 193         return pin;
 194 }
 195 
 196 void dal_gpio_service_destroy(
 197         struct gpio_service **ptr)
 198 {
 199         if (!ptr || !*ptr) {
 200                 BREAK_TO_DEBUGGER();
 201                 return;
 202         }
 203 
 204         /* free business storage */
 205         {
 206                 uint32_t index_of_id = 0;
 207 
 208                 do {
 209                         kfree((*ptr)->busyness[index_of_id]);
 210 
 211                         ++index_of_id;
 212                 } while (index_of_id < GPIO_ID_COUNT);
 213         }
 214 
 215         kfree(*ptr);
 216 
 217         *ptr = NULL;
 218 }
 219 
 220 enum gpio_result dal_mux_setup_config(
 221         struct gpio *mux,
 222         struct gpio_generic_mux_config *config)
 223 {
 224         struct gpio_config_data config_data;
 225 
 226         if (!config)
 227                 return GPIO_RESULT_INVALID_DATA;
 228 
 229         config_data.config.generic_mux = *config;
 230         config_data.type = GPIO_CONFIG_TYPE_GENERIC_MUX;
 231 
 232         return dal_gpio_set_config(mux, &config_data);
 233 }
 234 
 235 /*
 236  * @brief
 237  * Private API.
 238  */
 239 
 240 static bool is_pin_busy(
 241         const struct gpio_service *service,
 242         enum gpio_id id,
 243         uint32_t en)
 244 {
 245         return service->busyness[id][en];
 246 }
 247 
 248 static void set_pin_busy(
 249         struct gpio_service *service,
 250         enum gpio_id id,
 251         uint32_t en)
 252 {
 253         service->busyness[id][en] = true;
 254 }
 255 
 256 static void set_pin_free(
 257         struct gpio_service *service,
 258         enum gpio_id id,
 259         uint32_t en)
 260 {
 261         service->busyness[id][en] = false;
 262 }
 263 
 264 enum gpio_result dal_gpio_service_lock(
 265         struct gpio_service *service,
 266         enum gpio_id id,
 267         uint32_t en)
 268 {
 269         if (!service->busyness[id]) {
 270                 ASSERT_CRITICAL(false);
 271                 return GPIO_RESULT_OPEN_FAILED;
 272         }
 273 
 274         set_pin_busy(service, id, en);
 275         return GPIO_RESULT_OK;
 276 }
 277 
 278 enum gpio_result dal_gpio_service_unlock(
 279         struct gpio_service *service,
 280         enum gpio_id id,
 281         uint32_t en)
 282 {
 283         if (!service->busyness[id]) {
 284                 ASSERT_CRITICAL(false);
 285                 return GPIO_RESULT_OPEN_FAILED;
 286         }
 287 
 288         set_pin_free(service, id, en);
 289         return GPIO_RESULT_OK;
 290 }
 291 
 292 enum gpio_result dal_gpio_service_open(
 293         struct gpio *gpio)
 294 {
 295         struct gpio_service *service = gpio->service;
 296         enum gpio_id id = gpio->id;
 297         uint32_t en = gpio->en;
 298         enum gpio_mode mode = gpio->mode;
 299 
 300         struct hw_gpio_pin **pin = &gpio->pin;
 301 
 302 
 303         if (!service->busyness[id]) {
 304                 ASSERT_CRITICAL(false);
 305                 return GPIO_RESULT_OPEN_FAILED;
 306         }
 307 
 308         if (is_pin_busy(service, id, en)) {
 309                 ASSERT_CRITICAL(false);
 310                 return GPIO_RESULT_DEVICE_BUSY;
 311         }
 312 
 313         switch (id) {
 314         case GPIO_ID_DDC_DATA:
 315                 *pin = service->factory.funcs->get_ddc_pin(gpio);
 316                 service->factory.funcs->define_ddc_registers(*pin, en);
 317         break;
 318         case GPIO_ID_DDC_CLOCK:
 319                 *pin = service->factory.funcs->get_ddc_pin(gpio);
 320                 service->factory.funcs->define_ddc_registers(*pin, en);
 321         break;
 322         case GPIO_ID_GENERIC:
 323                 *pin = service->factory.funcs->get_generic_pin(gpio);
 324                 service->factory.funcs->define_generic_registers(*pin, en);
 325         break;
 326         case GPIO_ID_HPD:
 327                 *pin = service->factory.funcs->get_hpd_pin(gpio);
 328                 service->factory.funcs->define_hpd_registers(*pin, en);
 329         break;
 330 
 331         //TODO: gsl and sync support? create_sync and create_gsl are NULL
 332         case GPIO_ID_SYNC:
 333         case GPIO_ID_GSL:
 334         break;
 335         default:
 336                 ASSERT_CRITICAL(false);
 337                 return GPIO_RESULT_NON_SPECIFIC_ERROR;
 338         }
 339 
 340         if (!*pin) {
 341                 ASSERT_CRITICAL(false);
 342                 return GPIO_RESULT_NON_SPECIFIC_ERROR;
 343         }
 344 
 345         if (!(*pin)->funcs->open(*pin, mode)) {
 346                 ASSERT_CRITICAL(false);
 347                 dal_gpio_service_close(service, pin);
 348                 return GPIO_RESULT_OPEN_FAILED;
 349         }
 350 
 351         set_pin_busy(service, id, en);
 352         return GPIO_RESULT_OK;
 353 }
 354 
 355 void dal_gpio_service_close(
 356         struct gpio_service *service,
 357         struct hw_gpio_pin **ptr)
 358 {
 359         struct hw_gpio_pin *pin;
 360 
 361         if (!ptr) {
 362                 ASSERT_CRITICAL(false);
 363                 return;
 364         }
 365 
 366         pin = *ptr;
 367 
 368         if (pin) {
 369                 set_pin_free(service, pin->id, pin->en);
 370 
 371                 pin->funcs->close(pin);
 372 
 373                 *ptr = NULL;
 374         }
 375 }
 376 
 377 enum dc_irq_source dal_irq_get_source(
 378         const struct gpio *irq)
 379 {
 380         enum gpio_id id = dal_gpio_get_id(irq);
 381 
 382         switch (id) {
 383         case GPIO_ID_HPD:
 384                 return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1 +
 385                         dal_gpio_get_enum(irq));
 386         case GPIO_ID_GPIO_PAD:
 387                 return (enum dc_irq_source)(DC_IRQ_SOURCE_GPIOPAD0 +
 388                         dal_gpio_get_enum(irq));
 389         default:
 390                 return DC_IRQ_SOURCE_INVALID;
 391         }
 392 }
 393 
 394 enum dc_irq_source dal_irq_get_rx_source(
 395         const struct gpio *irq)
 396 {
 397         enum gpio_id id = dal_gpio_get_id(irq);
 398 
 399         switch (id) {
 400         case GPIO_ID_HPD:
 401                 return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1RX +
 402                         dal_gpio_get_enum(irq));
 403         default:
 404                 return DC_IRQ_SOURCE_INVALID;
 405         }
 406 }
 407 
 408 enum gpio_result dal_irq_setup_hpd_filter(
 409         struct gpio *irq,
 410         struct gpio_hpd_config *config)
 411 {
 412         struct gpio_config_data config_data;
 413 
 414         if (!config)
 415                 return GPIO_RESULT_INVALID_DATA;
 416 
 417         config_data.type = GPIO_CONFIG_TYPE_HPD;
 418         config_data.config.hpd = *config;
 419 
 420         return dal_gpio_set_config(irq, &config_data);
 421 }
 422 
 423 /*
 424  * @brief
 425  * Creation and destruction
 426  */
 427 
 428 struct gpio *dal_gpio_create_irq(
 429         struct gpio_service *service,
 430         enum gpio_id id,
 431         uint32_t en)
 432 {
 433         struct gpio *irq;
 434 
 435         switch (id) {
 436         case GPIO_ID_HPD:
 437         case GPIO_ID_GPIO_PAD:
 438         break;
 439         default:
 440                 id = GPIO_ID_HPD;
 441                 ASSERT_CRITICAL(false);
 442                 return NULL;
 443         }
 444 
 445         irq = dal_gpio_create(
 446                 service, id, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
 447 
 448         if (irq)
 449                 return irq;
 450 
 451         ASSERT_CRITICAL(false);
 452         return NULL;
 453 }
 454 
 455 void dal_gpio_destroy_irq(
 456         struct gpio **irq)
 457 {
 458         if (!irq || !*irq) {
 459                 ASSERT_CRITICAL(false);
 460                 return;
 461         }
 462 
 463         dal_gpio_close(*irq);
 464         dal_gpio_destroy(irq);
 465         kfree(*irq);
 466 
 467         *irq = NULL;
 468 }
 469 
 470 struct ddc *dal_gpio_create_ddc(
 471         struct gpio_service *service,
 472         uint32_t offset,
 473         uint32_t mask,
 474         struct gpio_ddc_hw_info *info)
 475 {
 476         enum gpio_id id;
 477         uint32_t en;
 478         struct ddc *ddc;
 479 
 480         if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en))
 481                 return NULL;
 482 
 483         ddc = kzalloc(sizeof(struct ddc), GFP_KERNEL);
 484 
 485         if (!ddc) {
 486                 BREAK_TO_DEBUGGER();
 487                 return NULL;
 488         }
 489 
 490         ddc->pin_data = dal_gpio_create(
 491                 service, GPIO_ID_DDC_DATA, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
 492 
 493         if (!ddc->pin_data) {
 494                 BREAK_TO_DEBUGGER();
 495                 goto failure_1;
 496         }
 497 
 498         ddc->pin_clock = dal_gpio_create(
 499                 service, GPIO_ID_DDC_CLOCK, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
 500 
 501         if (!ddc->pin_clock) {
 502                 BREAK_TO_DEBUGGER();
 503                 goto failure_2;
 504         }
 505 
 506         ddc->hw_info = *info;
 507 
 508         ddc->ctx = service->ctx;
 509 
 510         return ddc;
 511 
 512 failure_2:
 513         dal_gpio_destroy(&ddc->pin_data);
 514 
 515 failure_1:
 516         kfree(ddc);
 517 
 518         return NULL;
 519 }
 520 
 521 void dal_gpio_destroy_ddc(
 522         struct ddc **ddc)
 523 {
 524         if (!ddc || !*ddc) {
 525                 BREAK_TO_DEBUGGER();
 526                 return;
 527         }
 528 
 529         dal_ddc_close(*ddc);
 530         dal_gpio_destroy(&(*ddc)->pin_data);
 531         dal_gpio_destroy(&(*ddc)->pin_clock);
 532         kfree(*ddc);
 533 
 534         *ddc = NULL;
 535 }
 536 
 537 enum gpio_result dal_ddc_open(
 538         struct ddc *ddc,
 539         enum gpio_mode mode,
 540         enum gpio_ddc_config_type config_type)
 541 {
 542         enum gpio_result result;
 543 
 544         struct gpio_config_data config_data;
 545         struct hw_gpio *hw_data;
 546         struct hw_gpio *hw_clock;
 547 
 548         result = dal_gpio_open_ex(ddc->pin_data, mode);
 549 
 550         if (result != GPIO_RESULT_OK) {
 551                 BREAK_TO_DEBUGGER();
 552                 return result;
 553         }
 554 
 555         result = dal_gpio_open_ex(ddc->pin_clock, mode);
 556 
 557         if (result != GPIO_RESULT_OK) {
 558                 BREAK_TO_DEBUGGER();
 559                 goto failure;
 560         }
 561 
 562         /* DDC clock and data pins should belong
 563          * to the same DDC block id,
 564          * we use the data pin to set the pad mode. */
 565 
 566         if (mode == GPIO_MODE_INPUT)
 567                 /* this is from detect_sink_type,
 568                  * we need extra delay there */
 569                 config_data.type = GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE;
 570         else
 571                 config_data.type = GPIO_CONFIG_TYPE_DDC;
 572 
 573         config_data.config.ddc.type = config_type;
 574 
 575         hw_data = FROM_HW_GPIO_PIN(ddc->pin_data->pin);
 576         hw_clock = FROM_HW_GPIO_PIN(ddc->pin_clock->pin);
 577 
 578         config_data.config.ddc.data_en_bit_present = hw_data->store.en != 0;
 579         config_data.config.ddc.clock_en_bit_present = hw_clock->store.en != 0;
 580 
 581         result = dal_gpio_set_config(ddc->pin_data, &config_data);
 582 
 583         if (result == GPIO_RESULT_OK)
 584                 return result;
 585 
 586         BREAK_TO_DEBUGGER();
 587 
 588         dal_gpio_close(ddc->pin_clock);
 589 
 590 failure:
 591         dal_gpio_close(ddc->pin_data);
 592 
 593         return result;
 594 }
 595 
 596 enum gpio_result dal_ddc_change_mode(
 597         struct ddc *ddc,
 598         enum gpio_mode mode)
 599 {
 600         enum gpio_result result;
 601 
 602         enum gpio_mode original_mode =
 603                 dal_gpio_get_mode(ddc->pin_data);
 604 
 605         result = dal_gpio_change_mode(ddc->pin_data, mode);
 606 
 607         /* [anaumov] DAL2 code returns GPIO_RESULT_NON_SPECIFIC_ERROR
 608          * in case of failures;
 609          * set_mode() is so that, in case of failure,
 610          * we must explicitly set original mode */
 611 
 612         if (result != GPIO_RESULT_OK)
 613                 goto failure;
 614 
 615         result = dal_gpio_change_mode(ddc->pin_clock, mode);
 616 
 617         if (result == GPIO_RESULT_OK)
 618                 return result;
 619 
 620         dal_gpio_change_mode(ddc->pin_clock, original_mode);
 621 
 622 failure:
 623         dal_gpio_change_mode(ddc->pin_data, original_mode);
 624 
 625         return result;
 626 }
 627 
 628 enum gpio_ddc_line dal_ddc_get_line(
 629         const struct ddc *ddc)
 630 {
 631         return (enum gpio_ddc_line)dal_gpio_get_enum(ddc->pin_data);
 632 }
 633 
 634 enum gpio_result dal_ddc_set_config(
 635         struct ddc *ddc,
 636         enum gpio_ddc_config_type config_type)
 637 {
 638         struct gpio_config_data config_data;
 639 
 640         config_data.type = GPIO_CONFIG_TYPE_DDC;
 641 
 642         config_data.config.ddc.type = config_type;
 643         config_data.config.ddc.data_en_bit_present = false;
 644         config_data.config.ddc.clock_en_bit_present = false;
 645 
 646         return dal_gpio_set_config(ddc->pin_data, &config_data);
 647 }
 648 
 649 void dal_ddc_close(
 650         struct ddc *ddc)
 651 {
 652         dal_gpio_close(ddc->pin_clock);
 653         dal_gpio_close(ddc->pin_data);
 654 }
 655 

/* [<][>][^][v][top][bottom][index][help] */