linux/drivers/gpu/drm/amd/display/dc/gpio/gpio_base.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
  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
  54enum 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
  61enum 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
  80enum 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
  92enum 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
 104enum gpio_mode dal_gpio_get_mode(
 105        const struct gpio *gpio)
 106{
 107        return gpio->mode;
 108}
 109
 110enum 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
 116enum 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
 122enum 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
 134enum gpio_id dal_gpio_get_id(
 135        const struct gpio *gpio)
 136{
 137        return gpio->id;
 138}
 139
 140uint32_t dal_gpio_get_enum(
 141        const struct gpio *gpio)
 142{
 143        return gpio->en;
 144}
 145
 146enum 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
 158enum 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
 167enum 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
 232enum gpio_pin_output_state dal_gpio_get_output_state(
 233        const struct gpio *gpio)
 234{
 235        return gpio->output_state;
 236}
 237
 238struct hw_ddc *dal_gpio_get_ddc(struct gpio *gpio)
 239{
 240        return gpio->hw_container.ddc;
 241}
 242
 243struct hw_hpd *dal_gpio_get_hpd(struct gpio *gpio)
 244{
 245        return gpio->hw_container.hpd;
 246}
 247
 248struct hw_generic *dal_gpio_get_generic(struct gpio *gpio)
 249{
 250        return gpio->hw_container.generic;
 251}
 252
 253void 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
 269struct 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
 316void 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