summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c')
-rw-r--r--drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c191
1 files changed, 151 insertions, 40 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c
index dada04296025..942d9f0b6df2 100644
--- a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c
+++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c
@@ -51,12 +51,12 @@
*/
struct gpio_service *dal_gpio_service_create(
- enum dce_version dce_version_major,
- enum dce_version dce_version_minor,
+ enum dce_version dce_version,
+ enum dce_environment dce_environment,
struct dc_context *ctx)
{
struct gpio_service *service;
- uint32_t index_of_id;
+ int32_t index_of_id;
service = kzalloc(sizeof(struct gpio_service), GFP_KERNEL);
@@ -65,14 +65,14 @@ struct gpio_service *dal_gpio_service_create(
return NULL;
}
- if (!dal_hw_translate_init(&service->translate, dce_version_major,
- dce_version_minor)) {
+ if (!dal_hw_translate_init(&service->translate, dce_version,
+ dce_environment)) {
BREAK_TO_DEBUGGER();
goto failure_1;
}
- if (!dal_hw_factory_init(&service->factory, dce_version_major,
- dce_version_minor)) {
+ if (!dal_hw_factory_init(&service->factory, dce_version,
+ dce_environment)) {
BREAK_TO_DEBUGGER();
goto failure_1;
}
@@ -112,7 +112,7 @@ struct gpio_service *dal_gpio_service_create(
return service;
failure_2:
- while (index_of_id) {
+ while (index_of_id > 0) {
--index_of_id;
kfree(service->busyness[index_of_id]);
}
@@ -128,7 +128,7 @@ struct gpio *dal_gpio_service_create_irq(
uint32_t offset,
uint32_t mask)
{
- enum gpio_id id;
+ enum gpio_id id = 0;
uint32_t en;
if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) {
@@ -139,6 +139,57 @@ struct gpio *dal_gpio_service_create_irq(
return dal_gpio_create_irq(service, id, en);
}
+struct gpio *dal_gpio_service_create_generic_mux(
+ struct gpio_service *service,
+ uint32_t offset,
+ uint32_t mask)
+{
+ enum gpio_id id = 0;
+ uint32_t en;
+ struct gpio *generic;
+
+ if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) {
+ ASSERT_CRITICAL(false);
+ return NULL;
+ }
+
+ generic = dal_gpio_create(
+ service, id, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
+
+ return generic;
+}
+
+void dal_gpio_destroy_generic_mux(
+ struct gpio **mux)
+{
+ if (!mux || !*mux) {
+ ASSERT_CRITICAL(false);
+ return;
+ }
+
+ dal_gpio_destroy(mux);
+ kfree(*mux);
+
+ *mux = NULL;
+}
+
+struct gpio_pin_info dal_gpio_get_generic_pin_info(
+ struct gpio_service *service,
+ enum gpio_id id,
+ uint32_t en)
+{
+ struct gpio_pin_info pin = {0};
+
+ if (service->translate.funcs->id_to_offset) {
+ service->translate.funcs->id_to_offset(id, en, &pin);
+ } else {
+ pin.mask = 0xFFFFFFFF;
+ pin.offset = 0xFFFFFFFF;
+ }
+
+ return pin;
+}
+
void dal_gpio_service_destroy(
struct gpio_service **ptr)
{
@@ -163,6 +214,21 @@ void dal_gpio_service_destroy(
*ptr = NULL;
}
+enum gpio_result dal_mux_setup_config(
+ struct gpio *mux,
+ struct gpio_generic_mux_config *config)
+{
+ struct gpio_config_data config_data;
+
+ if (!config)
+ return GPIO_RESULT_INVALID_DATA;
+
+ config_data.config.generic_mux = *config;
+ config_data.type = GPIO_CONFIG_TYPE_GENERIC_MUX;
+
+ return dal_gpio_set_config(mux, &config_data);
+}
+
/*
* @brief
* Private API.
@@ -173,6 +239,9 @@ static bool is_pin_busy(
enum gpio_id id,
uint32_t en)
{
+ if (id == GPIO_ID_UNKNOWN)
+ return false;
+
return service->busyness[id][en];
}
@@ -181,6 +250,9 @@ static void set_pin_busy(
enum gpio_id id,
uint32_t en)
{
+ if (id == GPIO_ID_UNKNOWN)
+ return;
+
service->busyness[id][en] = true;
}
@@ -189,17 +261,50 @@ static void set_pin_free(
enum gpio_id id,
uint32_t en)
{
+ if (id == GPIO_ID_UNKNOWN)
+ return;
+
service->busyness[id][en] = false;
}
-enum gpio_result dal_gpio_service_open(
+enum gpio_result dal_gpio_service_lock(
struct gpio_service *service,
enum gpio_id id,
- uint32_t en,
- enum gpio_mode mode,
- struct hw_gpio_pin **ptr)
+ uint32_t en)
{
- struct hw_gpio_pin *pin;
+ if (id != GPIO_ID_UNKNOWN && !service->busyness[id]) {
+ ASSERT_CRITICAL(false);
+ return GPIO_RESULT_OPEN_FAILED;
+ }
+
+ set_pin_busy(service, id, en);
+ return GPIO_RESULT_OK;
+}
+
+enum gpio_result dal_gpio_service_unlock(
+ struct gpio_service *service,
+ enum gpio_id id,
+ uint32_t en)
+{
+ if (id != GPIO_ID_UNKNOWN && !service->busyness[id]) {
+ ASSERT_CRITICAL(false);
+ return GPIO_RESULT_OPEN_FAILED;
+ }
+
+ set_pin_free(service, id, en);
+ return GPIO_RESULT_OK;
+}
+
+enum gpio_result dal_gpio_service_open(
+ struct gpio *gpio)
+{
+ struct gpio_service *service = gpio->service;
+ enum gpio_id id = gpio->id;
+ uint32_t en = gpio->en;
+ enum gpio_mode mode = gpio->mode;
+
+ struct hw_gpio_pin **pin = &gpio->pin;
+
if (!service->busyness[id]) {
ASSERT_CRITICAL(false);
@@ -213,50 +318,43 @@ enum gpio_result dal_gpio_service_open(
switch (id) {
case GPIO_ID_DDC_DATA:
- pin = service->factory.funcs->create_ddc_data(
- service->ctx, id, en);
- service->factory.funcs->define_ddc_registers(pin, en);
+ *pin = service->factory.funcs->get_ddc_pin(gpio);
+ service->factory.funcs->define_ddc_registers(*pin, en);
break;
case GPIO_ID_DDC_CLOCK:
- pin = service->factory.funcs->create_ddc_clock(
- service->ctx, id, en);
- service->factory.funcs->define_ddc_registers(pin, en);
+ *pin = service->factory.funcs->get_ddc_pin(gpio);
+ service->factory.funcs->define_ddc_registers(*pin, en);
break;
case GPIO_ID_GENERIC:
- pin = service->factory.funcs->create_generic(
- service->ctx, id, en);
+ *pin = service->factory.funcs->get_generic_pin(gpio);
+ service->factory.funcs->define_generic_registers(*pin, en);
break;
case GPIO_ID_HPD:
- pin = service->factory.funcs->create_hpd(
- service->ctx, id, en);
- service->factory.funcs->define_hpd_registers(pin, en);
+ *pin = service->factory.funcs->get_hpd_pin(gpio);
+ service->factory.funcs->define_hpd_registers(*pin, en);
break;
+
+ //TODO: gsl and sync support? create_sync and create_gsl are NULL
case GPIO_ID_SYNC:
- pin = service->factory.funcs->create_sync(
- service->ctx, id, en);
- break;
case GPIO_ID_GSL:
- pin = service->factory.funcs->create_gsl(
- service->ctx, id, en);
break;
default:
ASSERT_CRITICAL(false);
return GPIO_RESULT_NON_SPECIFIC_ERROR;
}
- if (!pin) {
+ if (!*pin) {
ASSERT_CRITICAL(false);
return GPIO_RESULT_NON_SPECIFIC_ERROR;
}
- if (!pin->funcs->open(pin, mode)) {
+ if (!(*pin)->funcs->open(*pin, mode)) {
ASSERT_CRITICAL(false);
- dal_gpio_service_close(service, &pin);
+ dal_gpio_service_close(service, pin);
return GPIO_RESULT_OPEN_FAILED;
}
set_pin_busy(service, id, en);
- *ptr = pin;
return GPIO_RESULT_OK;
}
@@ -278,11 +376,10 @@ void dal_gpio_service_close(
pin->funcs->close(pin);
- pin->funcs->destroy(ptr);
+ *ptr = NULL;
}
}
-
enum dc_irq_source dal_irq_get_source(
const struct gpio *irq)
{
@@ -314,6 +411,20 @@ enum dc_irq_source dal_irq_get_rx_source(
}
}
+enum dc_irq_source dal_irq_get_read_request(
+ const struct gpio *irq)
+{
+ enum gpio_id id = dal_gpio_get_id(irq);
+
+ switch (id) {
+ case GPIO_ID_HPD:
+ return (enum dc_irq_source)(DC_IRQ_SOURCE_DCI2C_RR_DDC1 +
+ dal_gpio_get_enum(irq));
+ default:
+ return DC_IRQ_SOURCE_INVALID;
+ }
+}
+
enum gpio_result dal_irq_setup_hpd_filter(
struct gpio *irq,
struct gpio_hpd_config *config)
@@ -346,7 +457,6 @@ struct gpio *dal_gpio_create_irq(
case GPIO_ID_GPIO_PAD:
break;
default:
- id = GPIO_ID_HPD;
ASSERT_CRITICAL(false);
return NULL;
}
@@ -369,7 +479,6 @@ void dal_gpio_destroy_irq(
return;
}
- dal_gpio_close(*irq);
dal_gpio_destroy(irq);
kfree(*irq);
@@ -558,7 +667,9 @@ enum gpio_result dal_ddc_set_config(
void dal_ddc_close(
struct ddc *ddc)
{
- dal_gpio_close(ddc->pin_clock);
- dal_gpio_close(ddc->pin_data);
+ if (ddc != NULL) {
+ dal_gpio_close(ddc->pin_clock);
+ dal_gpio_close(ddc->pin_data);
+ }
}