OSDN Git Service

drm/amd/display: add gpio lock/unlock
authorChiawen Huang <chiawen.huang@amd.com>
Fri, 18 Jan 2019 06:07:54 +0000 (14:07 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 6 Feb 2019 02:16:23 +0000 (21:16 -0500)
[Why]
When querying HPD via GPIO flow,
it will create a new gpio object then free in the end of query.
There is a irql issue for HPD querying at ISR level.

[How]
Therefore, creating the HPD gpio object in dc_link and set it as unlcok in default.
1. reducing unnecessary malloc/free when HPD querying.
2. reducing init GPIO flow.
3. add lock/unlock to prevent multi gpio service running.

Signed-off-by: Chiawen Huang <chiawen.huang@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Acked-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/core/dc_link.c
drivers/gpu/drm/amd/display/dc/dc_link.h
drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c
drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c
drivers/gpu/drm/amd/display/dc/gpio/gpio_service.h
drivers/gpu/drm/amd/display/include/gpio_interface.h

index 8ff5d42..137d3c1 100644 (file)
@@ -76,6 +76,12 @@ static void destruct(struct dc_link *link)
 {
        int i;
 
+       if (link->hpd_gpio != NULL) {
+               dal_gpio_close(link->hpd_gpio);
+               dal_gpio_destroy_irq(&link->hpd_gpio);
+               link->hpd_gpio = NULL;
+       }
+
        if (link->ddc)
                dal_ddc_service_destroy(&link->ddc);
 
@@ -931,18 +937,11 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
 
 bool dc_link_get_hpd_state(struct dc_link *dc_link)
 {
-       struct gpio *hpd_pin;
        uint32_t state;
 
-       hpd_pin = get_hpd_gpio(dc_link->ctx->dc_bios,
-                                       dc_link->link_id, dc_link->ctx->gpio_service);
-       if (hpd_pin == NULL)
-               ASSERT(false);
-
-       dal_gpio_open(hpd_pin, GPIO_MODE_INTERRUPT);
-       dal_gpio_get_value(hpd_pin, &state);
-       dal_gpio_close(hpd_pin);
-       dal_gpio_destroy_irq(&hpd_pin);
+       dal_gpio_lock_pin(dc_link->hpd_gpio);
+       dal_gpio_get_value(dc_link->hpd_gpio, &state);
+       dal_gpio_unlock_pin(dc_link->hpd_gpio);
 
        return state;
 }
@@ -1098,7 +1097,6 @@ static bool construct(
        const struct link_init_data *init_params)
 {
        uint8_t i;
-       struct gpio *hpd_gpio = NULL;
        struct ddc_service_init_data ddc_service_init_data = { { 0 } };
        struct dc_context *dc_ctx = init_params->ctx;
        struct encoder_init_data enc_init_data = { 0 };
@@ -1128,10 +1126,11 @@ static bool construct(
        if (link->dc->res_pool->funcs->link_init)
                link->dc->res_pool->funcs->link_init(link);
 
-       hpd_gpio = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
-
-       if (hpd_gpio != NULL)
-               link->irq_source_hpd = dal_irq_get_source(hpd_gpio);
+       link->hpd_gpio = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
+       dal_gpio_open(link->hpd_gpio, GPIO_MODE_INTERRUPT);
+       dal_gpio_unlock_pin(link->hpd_gpio);
+       if (link->hpd_gpio != NULL)
+               link->irq_source_hpd = dal_irq_get_source(link->hpd_gpio);
 
        switch (link->link_id.id) {
        case CONNECTOR_ID_HDMI_TYPE_A:
@@ -1149,18 +1148,18 @@ static bool construct(
        case CONNECTOR_ID_DISPLAY_PORT:
                link->connector_signal =        SIGNAL_TYPE_DISPLAY_PORT;
 
-               if (hpd_gpio != NULL)
+               if (link->hpd_gpio != NULL)
                        link->irq_source_hpd_rx =
-                                       dal_irq_get_rx_source(hpd_gpio);
+                                       dal_irq_get_rx_source(link->hpd_gpio);
 
                break;
        case CONNECTOR_ID_EDP:
                link->connector_signal = SIGNAL_TYPE_EDP;
 
-               if (hpd_gpio != NULL) {
+               if (link->hpd_gpio != NULL) {
                        link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
                        link->irq_source_hpd_rx =
-                                       dal_irq_get_rx_source(hpd_gpio);
+                                       dal_irq_get_rx_source(link->hpd_gpio);
                }
                break;
        case CONNECTOR_ID_LVDS:
@@ -1171,10 +1170,7 @@ static bool construct(
                goto create_fail;
        }
 
-       if (hpd_gpio != NULL) {
-               dal_gpio_destroy_irq(&hpd_gpio);
-               hpd_gpio = NULL;
-       }
+
 
        /* TODO: #DAL3 Implement id to str function.*/
        LINK_INFO("Connector[%d] description:"
@@ -1277,8 +1273,9 @@ link_enc_create_fail:
 ddc_create_fail:
 create_fail:
 
-       if (hpd_gpio != NULL) {
-               dal_gpio_destroy_irq(&hpd_gpio);
+       if (link->hpd_gpio != NULL) {
+               dal_gpio_destroy_irq(&link->hpd_gpio);
+               link->hpd_gpio = NULL;
        }
 
        return false;
index f249ff9..d26bbda 100644 (file)
@@ -125,6 +125,7 @@ struct dc_link {
        struct dc_link_status link_status;
 
        struct link_trace link_trace;
+       struct gpio *hpd_gpio;
 };
 
 const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link);
index 1d1efd7..cf76ea2 100644 (file)
@@ -101,6 +101,18 @@ enum gpio_mode dal_gpio_get_mode(
        return gpio->mode;
 }
 
+enum gpio_result dal_gpio_lock_pin(
+       struct gpio *gpio)
+{
+       return dal_gpio_service_lock(gpio->service, gpio->id, gpio->en);
+}
+
+enum gpio_result dal_gpio_unlock_pin(
+       struct gpio *gpio)
+{
+       return dal_gpio_service_unlock(gpio->service, gpio->id, gpio->en);
+}
+
 enum gpio_result dal_gpio_change_mode(
        struct gpio *gpio,
        enum gpio_mode mode)
index dada042..3c63a3c 100644 (file)
@@ -192,6 +192,34 @@ static void set_pin_free(
        service->busyness[id][en] = false;
 }
 
+enum gpio_result dal_gpio_service_lock(
+       struct gpio_service *service,
+       enum gpio_id id,
+       uint32_t en)
+{
+       if (!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 (!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_service *service,
        enum gpio_id id,
index 1d501a4..0c678af 100644 (file)
@@ -52,4 +52,14 @@ void dal_gpio_service_close(
        struct gpio_service *service,
        struct hw_gpio_pin **ptr);
 
+enum gpio_result dal_gpio_service_lock(
+       struct gpio_service *service,
+       enum gpio_id id,
+       uint32_t en);
+
+enum gpio_result dal_gpio_service_unlock(
+       struct gpio_service *service,
+       enum gpio_id id,
+       uint32_t en);
+
 #endif
index e4fd310..7de6419 100644 (file)
@@ -59,6 +59,14 @@ enum gpio_result dal_gpio_change_mode(
        struct gpio *gpio,
        enum gpio_mode mode);
 
+/* Lock Pin */
+enum gpio_result dal_gpio_lock_pin(
+       struct gpio *gpio);
+
+/* Unlock Pin */
+enum gpio_result dal_gpio_unlock_pin(
+       struct gpio *gpio);
+
 /* Get the GPIO id */
 enum gpio_id dal_gpio_get_id(
        const struct gpio *gpio);