diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:27:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:27:49 +0000 |
commit | ace9429bb58fd418f0c81d4c2835699bddf6bde6 (patch) | |
tree | b2d64bc10158fdd5497876388cd68142ca374ed3 /drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c | |
parent | Initial commit. (diff) | |
download | linux-ace9429bb58fd418f0c81d4c2835699bddf6bde6.tar.xz linux-ace9429bb58fd418f0c81d4c2835699bddf6bde6.zip |
Adding upstream version 6.6.15.upstream/6.6.15
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c new file mode 100644 index 0000000000..660510842e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c @@ -0,0 +1,203 @@ +/* + * Copyright 2012-15 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/gpio_types.h" +#include "hw_gpio.h" + +#include "reg_helper.h" +#include "gpio_regs.h" + +#undef FN +#define FN(reg_name, field_name) \ + gpio->regs->field_name ## _shift, gpio->regs->field_name ## _mask + +#define CTX \ + gpio->base.ctx +#define REG(reg)\ + (gpio->regs->reg) + +static void store_registers( + struct hw_gpio *gpio) +{ + REG_GET(MASK_reg, MASK, &gpio->store.mask); + REG_GET(A_reg, A, &gpio->store.a); + REG_GET(EN_reg, EN, &gpio->store.en); + /* TODO store GPIO_MUX_CONTROL if we ever use it */ +} + +static void restore_registers( + struct hw_gpio *gpio) +{ + REG_UPDATE(MASK_reg, MASK, gpio->store.mask); + REG_UPDATE(A_reg, A, gpio->store.a); + REG_UPDATE(EN_reg, EN, gpio->store.en); + /* TODO restore GPIO_MUX_CONTROL if we ever use it */ +} + +bool dal_hw_gpio_open( + struct hw_gpio_pin *ptr, + enum gpio_mode mode) +{ + struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr); + + store_registers(pin); + + ptr->opened = (dal_hw_gpio_config_mode(pin, mode) == GPIO_RESULT_OK); + + return ptr->opened; +} + +enum gpio_result dal_hw_gpio_get_value( + const struct hw_gpio_pin *ptr, + uint32_t *value) +{ + const struct hw_gpio *gpio = FROM_HW_GPIO_PIN(ptr); + + enum gpio_result result = GPIO_RESULT_OK; + + switch (ptr->mode) { + case GPIO_MODE_INPUT: + case GPIO_MODE_OUTPUT: + case GPIO_MODE_HARDWARE: + case GPIO_MODE_FAST_OUTPUT: + REG_GET(Y_reg, Y, value); + break; + default: + result = GPIO_RESULT_NON_SPECIFIC_ERROR; + } + + return result; +} + +enum gpio_result dal_hw_gpio_set_value( + const struct hw_gpio_pin *ptr, + uint32_t value) +{ + struct hw_gpio *gpio = FROM_HW_GPIO_PIN(ptr); + + /* This is the public interface + * where the input comes from client, not shifted yet + * (because client does not know the shifts). */ + + switch (ptr->mode) { + case GPIO_MODE_OUTPUT: + REG_UPDATE(A_reg, A, value); + return GPIO_RESULT_OK; + case GPIO_MODE_FAST_OUTPUT: + /* We use (EN) to faster switch (used in DDC GPIO). + * So (A) is grounded, output is driven by (EN = 0) + * to pull the line down (output == 0) and (EN=1) + * then output is tri-state */ + REG_UPDATE(EN_reg, EN, ~value); + return GPIO_RESULT_OK; + default: + return GPIO_RESULT_NON_SPECIFIC_ERROR; + } +} + +enum gpio_result dal_hw_gpio_change_mode( + struct hw_gpio_pin *ptr, + enum gpio_mode mode) +{ + struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr); + + return dal_hw_gpio_config_mode(pin, mode); +} + +void dal_hw_gpio_close( + struct hw_gpio_pin *ptr) +{ + struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr); + + restore_registers(pin); + + ptr->mode = GPIO_MODE_UNKNOWN; + ptr->opened = false; +} + +enum gpio_result dal_hw_gpio_config_mode( + struct hw_gpio *gpio, + enum gpio_mode mode) +{ + gpio->base.mode = mode; + + switch (mode) { + case GPIO_MODE_INPUT: + /* turn off output enable, act as input pin; + * program the pin as GPIO, mask out signal driven by HW */ + REG_UPDATE(EN_reg, EN, 0); + REG_UPDATE(MASK_reg, MASK, 1); + return GPIO_RESULT_OK; + case GPIO_MODE_OUTPUT: + /* turn on output enable, act as output pin; + * program the pin as GPIO, mask out signal driven by HW */ + REG_UPDATE(A_reg, A, 0); + REG_UPDATE(MASK_reg, MASK, 1); + return GPIO_RESULT_OK; + case GPIO_MODE_FAST_OUTPUT: + /* grounding the A register then use the EN register bit + * will have faster effect on the rise time */ + REG_UPDATE(A_reg, A, 0); + REG_UPDATE(MASK_reg, MASK, 1); + return GPIO_RESULT_OK; + case GPIO_MODE_HARDWARE: + /* program the pin as tri-state, pin is driven by HW */ + REG_UPDATE(MASK_reg, MASK, 0); + return GPIO_RESULT_OK; + case GPIO_MODE_INTERRUPT: + /* Interrupt mode supported only by HPD (IrqGpio) pins. */ + REG_UPDATE(MASK_reg, MASK, 0); + return GPIO_RESULT_OK; + default: + return GPIO_RESULT_NON_SPECIFIC_ERROR; + } +} + +void dal_hw_gpio_construct( + struct hw_gpio *pin, + enum gpio_id id, + uint32_t en, + struct dc_context *ctx) +{ + pin->base.ctx = ctx; + pin->base.id = id; + pin->base.en = en; + pin->base.mode = GPIO_MODE_UNKNOWN; + pin->base.opened = false; + + pin->store.mask = 0; + pin->store.a = 0; + pin->store.en = 0; + pin->store.mux = 0; + + pin->mux_supported = false; +} + +void dal_hw_gpio_destruct( + struct hw_gpio *pin) +{ + ASSERT(!pin->base.opened); +} |