linux/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c
<<
>>
Prefs
   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
  55struct 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
 116failure_2:
 117        while (index_of_id) {
 118                --index_of_id;
 119                kfree(service->busyness[index_of_id]);
 120        }
 121
 122failure_1:
 123        kfree(service);
 124
 125        return NULL;
 126}
 127
 128struct 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
 144void dal_gpio_service_destroy(
 145        struct gpio_service **ptr)
 146{
 147        if (!ptr || !*ptr) {
 148                BREAK_TO_DEBUGGER();
 149                return;
 150        }
 151
 152        /* free business storage */
 153        {
 154                uint32_t index_of_id = 0;
 155
 156                do {
 157                        kfree((*ptr)->busyness[index_of_id]);
 158
 159                        ++index_of_id;
 160                } while (index_of_id < GPIO_ID_COUNT);
 161        }
 162
 163        kfree(*ptr);
 164
 165        *ptr = NULL;
 166}
 167
 168/*
 169 * @brief
 170 * Private API.
 171 */
 172
 173static bool is_pin_busy(
 174        const struct gpio_service *service,
 175        enum gpio_id id,
 176        uint32_t en)
 177{
 178        return service->busyness[id][en];
 179}
 180
 181static void set_pin_busy(
 182        struct gpio_service *service,
 183        enum gpio_id id,
 184        uint32_t en)
 185{
 186        service->busyness[id][en] = true;
 187}
 188
 189static void set_pin_free(
 190        struct gpio_service *service,
 191        enum gpio_id id,
 192        uint32_t en)
 193{
 194        service->busyness[id][en] = false;
 195}
 196
 197enum gpio_result dal_gpio_service_lock(
 198        struct gpio_service *service,
 199        enum gpio_id id,
 200        uint32_t en)
 201{
 202        if (!service->busyness[id]) {
 203                ASSERT_CRITICAL(false);
 204                return GPIO_RESULT_OPEN_FAILED;
 205        }
 206
 207        set_pin_busy(service, id, en);
 208        return GPIO_RESULT_OK;
 209}
 210
 211enum gpio_result dal_gpio_service_unlock(
 212        struct gpio_service *service,
 213        enum gpio_id id,
 214        uint32_t en)
 215{
 216        if (!service->busyness[id]) {
 217                ASSERT_CRITICAL(false);
 218                return GPIO_RESULT_OPEN_FAILED;
 219        }
 220
 221        set_pin_free(service, id, en);
 222        return GPIO_RESULT_OK;
 223}
 224
 225enum gpio_result dal_gpio_service_open(
 226        struct gpio_service *service,
 227        enum gpio_id id,
 228        uint32_t en,
 229        enum gpio_mode mode,
 230        struct hw_gpio_pin **ptr)
 231{
 232        struct hw_gpio_pin *pin;
 233
 234        if (!service->busyness[id]) {
 235                ASSERT_CRITICAL(false);
 236                return GPIO_RESULT_OPEN_FAILED;
 237        }
 238
 239        if (is_pin_busy(service, id, en)) {
 240                ASSERT_CRITICAL(false);
 241                return GPIO_RESULT_DEVICE_BUSY;
 242        }
 243
 244        switch (id) {
 245        case GPIO_ID_DDC_DATA:
 246                pin = service->factory.funcs->create_ddc_data(
 247                        service->ctx, id, en);
 248                service->factory.funcs->define_ddc_registers(pin, en);
 249        break;
 250        case GPIO_ID_DDC_CLOCK:
 251                pin = service->factory.funcs->create_ddc_clock(
 252                        service->ctx, id, en);
 253                service->factory.funcs->define_ddc_registers(pin, en);
 254        break;
 255        case GPIO_ID_GENERIC:
 256                pin = service->factory.funcs->create_generic(
 257                        service->ctx, id, en);
 258        break;
 259        case GPIO_ID_HPD:
 260                pin = service->factory.funcs->create_hpd(
 261                        service->ctx, id, en);
 262                service->factory.funcs->define_hpd_registers(pin, en);
 263        break;
 264        case GPIO_ID_SYNC:
 265                pin = service->factory.funcs->create_sync(
 266                        service->ctx, id, en);
 267        break;
 268        case GPIO_ID_GSL:
 269                pin = service->factory.funcs->create_gsl(
 270                        service->ctx, id, en);
 271        break;
 272        default:
 273                ASSERT_CRITICAL(false);
 274                return GPIO_RESULT_NON_SPECIFIC_ERROR;
 275        }
 276
 277        if (!pin) {
 278                ASSERT_CRITICAL(false);
 279                return GPIO_RESULT_NON_SPECIFIC_ERROR;
 280        }
 281
 282        if (!pin->funcs->open(pin, mode)) {
 283                ASSERT_CRITICAL(false);
 284                dal_gpio_service_close(service, &pin);
 285                return GPIO_RESULT_OPEN_FAILED;
 286        }
 287
 288        set_pin_busy(service, id, en);
 289        *ptr = pin;
 290        return GPIO_RESULT_OK;
 291}
 292
 293void dal_gpio_service_close(
 294        struct gpio_service *service,
 295        struct hw_gpio_pin **ptr)
 296{
 297        struct hw_gpio_pin *pin;
 298
 299        if (!ptr) {
 300                ASSERT_CRITICAL(false);
 301                return;
 302        }
 303
 304        pin = *ptr;
 305
 306        if (pin) {
 307                set_pin_free(service, pin->id, pin->en);
 308
 309                pin->funcs->close(pin);
 310
 311                pin->funcs->destroy(ptr);
 312        }
 313}
 314
 315
 316enum dc_irq_source dal_irq_get_source(
 317        const struct gpio *irq)
 318{
 319        enum gpio_id id = dal_gpio_get_id(irq);
 320
 321        switch (id) {
 322        case GPIO_ID_HPD:
 323                return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1 +
 324                        dal_gpio_get_enum(irq));
 325        case GPIO_ID_GPIO_PAD:
 326                return (enum dc_irq_source)(DC_IRQ_SOURCE_GPIOPAD0 +
 327                        dal_gpio_get_enum(irq));
 328        default:
 329                return DC_IRQ_SOURCE_INVALID;
 330        }
 331}
 332
 333enum dc_irq_source dal_irq_get_rx_source(
 334        const struct gpio *irq)
 335{
 336        enum gpio_id id = dal_gpio_get_id(irq);
 337
 338        switch (id) {
 339        case GPIO_ID_HPD:
 340                return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1RX +
 341                        dal_gpio_get_enum(irq));
 342        default:
 343                return DC_IRQ_SOURCE_INVALID;
 344        }
 345}
 346
 347enum gpio_result dal_irq_setup_hpd_filter(
 348        struct gpio *irq,
 349        struct gpio_hpd_config *config)
 350{
 351        struct gpio_config_data config_data;
 352
 353        if (!config)
 354                return GPIO_RESULT_INVALID_DATA;
 355
 356        config_data.type = GPIO_CONFIG_TYPE_HPD;
 357        config_data.config.hpd = *config;
 358
 359        return dal_gpio_set_config(irq, &config_data);
 360}
 361
 362/*
 363 * @brief
 364 * Creation and destruction
 365 */
 366
 367struct gpio *dal_gpio_create_irq(
 368        struct gpio_service *service,
 369        enum gpio_id id,
 370        uint32_t en)
 371{
 372        struct gpio *irq;
 373
 374        switch (id) {
 375        case GPIO_ID_HPD:
 376        case GPIO_ID_GPIO_PAD:
 377        break;
 378        default:
 379                id = GPIO_ID_HPD;
 380                ASSERT_CRITICAL(false);
 381                return NULL;
 382        }
 383
 384        irq = dal_gpio_create(
 385                service, id, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
 386
 387        if (irq)
 388                return irq;
 389
 390        ASSERT_CRITICAL(false);
 391        return NULL;
 392}
 393
 394void dal_gpio_destroy_irq(
 395        struct gpio **irq)
 396{
 397        if (!irq || !*irq) {
 398                ASSERT_CRITICAL(false);
 399                return;
 400        }
 401
 402        dal_gpio_close(*irq);
 403        dal_gpio_destroy(irq);
 404        kfree(*irq);
 405
 406        *irq = NULL;
 407}
 408
 409struct ddc *dal_gpio_create_ddc(
 410        struct gpio_service *service,
 411        uint32_t offset,
 412        uint32_t mask,
 413        struct gpio_ddc_hw_info *info)
 414{
 415        enum gpio_id id;
 416        uint32_t en;
 417        struct ddc *ddc;
 418
 419        if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en))
 420                return NULL;
 421
 422        ddc = kzalloc(sizeof(struct ddc), GFP_KERNEL);
 423
 424        if (!ddc) {
 425                BREAK_TO_DEBUGGER();
 426                return NULL;
 427        }
 428
 429        ddc->pin_data = dal_gpio_create(
 430                service, GPIO_ID_DDC_DATA, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
 431
 432        if (!ddc->pin_data) {
 433                BREAK_TO_DEBUGGER();
 434                goto failure_1;
 435        }
 436
 437        ddc->pin_clock = dal_gpio_create(
 438                service, GPIO_ID_DDC_CLOCK, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
 439
 440        if (!ddc->pin_clock) {
 441                BREAK_TO_DEBUGGER();
 442                goto failure_2;
 443        }
 444
 445        ddc->hw_info = *info;
 446
 447        ddc->ctx = service->ctx;
 448
 449        return ddc;
 450
 451failure_2:
 452        dal_gpio_destroy(&ddc->pin_data);
 453
 454failure_1:
 455        kfree(ddc);
 456
 457        return NULL;
 458}
 459
 460void dal_gpio_destroy_ddc(
 461        struct ddc **ddc)
 462{
 463        if (!ddc || !*ddc) {
 464                BREAK_TO_DEBUGGER();
 465                return;
 466        }
 467
 468        dal_ddc_close(*ddc);
 469        dal_gpio_destroy(&(*ddc)->pin_data);
 470        dal_gpio_destroy(&(*ddc)->pin_clock);
 471        kfree(*ddc);
 472
 473        *ddc = NULL;
 474}
 475
 476enum gpio_result dal_ddc_open(
 477        struct ddc *ddc,
 478        enum gpio_mode mode,
 479        enum gpio_ddc_config_type config_type)
 480{
 481        enum gpio_result result;
 482
 483        struct gpio_config_data config_data;
 484        struct hw_gpio *hw_data;
 485        struct hw_gpio *hw_clock;
 486
 487        result = dal_gpio_open_ex(ddc->pin_data, mode);
 488
 489        if (result != GPIO_RESULT_OK) {
 490                BREAK_TO_DEBUGGER();
 491                return result;
 492        }
 493
 494        result = dal_gpio_open_ex(ddc->pin_clock, mode);
 495
 496        if (result != GPIO_RESULT_OK) {
 497                BREAK_TO_DEBUGGER();
 498                goto failure;
 499        }
 500
 501        /* DDC clock and data pins should belong
 502         * to the same DDC block id,
 503         * we use the data pin to set the pad mode. */
 504
 505        if (mode == GPIO_MODE_INPUT)
 506                /* this is from detect_sink_type,
 507                 * we need extra delay there */
 508                config_data.type = GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE;
 509        else
 510                config_data.type = GPIO_CONFIG_TYPE_DDC;
 511
 512        config_data.config.ddc.type = config_type;
 513
 514        hw_data = FROM_HW_GPIO_PIN(ddc->pin_data->pin);
 515        hw_clock = FROM_HW_GPIO_PIN(ddc->pin_clock->pin);
 516
 517        config_data.config.ddc.data_en_bit_present = hw_data->store.en != 0;
 518        config_data.config.ddc.clock_en_bit_present = hw_clock->store.en != 0;
 519
 520        result = dal_gpio_set_config(ddc->pin_data, &config_data);
 521
 522        if (result == GPIO_RESULT_OK)
 523                return result;
 524
 525        BREAK_TO_DEBUGGER();
 526
 527        dal_gpio_close(ddc->pin_clock);
 528
 529failure:
 530        dal_gpio_close(ddc->pin_data);
 531
 532        return result;
 533}
 534
 535enum gpio_result dal_ddc_change_mode(
 536        struct ddc *ddc,
 537        enum gpio_mode mode)
 538{
 539        enum gpio_result result;
 540
 541        enum gpio_mode original_mode =
 542                dal_gpio_get_mode(ddc->pin_data);
 543
 544        result = dal_gpio_change_mode(ddc->pin_data, mode);
 545
 546        /* [anaumov] DAL2 code returns GPIO_RESULT_NON_SPECIFIC_ERROR
 547         * in case of failures;
 548         * set_mode() is so that, in case of failure,
 549         * we must explicitly set original mode */
 550
 551        if (result != GPIO_RESULT_OK)
 552                goto failure;
 553
 554        result = dal_gpio_change_mode(ddc->pin_clock, mode);
 555
 556        if (result == GPIO_RESULT_OK)
 557                return result;
 558
 559        dal_gpio_change_mode(ddc->pin_clock, original_mode);
 560
 561failure:
 562        dal_gpio_change_mode(ddc->pin_data, original_mode);
 563
 564        return result;
 565}
 566
 567enum gpio_ddc_line dal_ddc_get_line(
 568        const struct ddc *ddc)
 569{
 570        return (enum gpio_ddc_line)dal_gpio_get_enum(ddc->pin_data);
 571}
 572
 573enum gpio_result dal_ddc_set_config(
 574        struct ddc *ddc,
 575        enum gpio_ddc_config_type config_type)
 576{
 577        struct gpio_config_data config_data;
 578
 579        config_data.type = GPIO_CONFIG_TYPE_DDC;
 580
 581        config_data.config.ddc.type = config_type;
 582        config_data.config.ddc.data_en_bit_present = false;
 583        config_data.config.ddc.clock_en_bit_present = false;
 584
 585        return dal_gpio_set_config(ddc->pin_data, &config_data);
 586}
 587
 588void dal_ddc_close(
 589        struct ddc *ddc)
 590{
 591        dal_gpio_close(ddc->pin_clock);
 592        dal_gpio_close(ddc->pin_data);
 593}
 594
 595