Commit ac627caf authored by Chiawen Huang's avatar Chiawen Huang Committed by Alex Deucher

drm/amd/display: add gpio lock/unlock

[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: default avatarChiawen Huang <chiawen.huang@amd.com>
Reviewed-by: default avatarTony Cheng <Tony.Cheng@amd.com>
Acked-by: default avatarBhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent cf7d98d2
...@@ -76,6 +76,12 @@ static void destruct(struct dc_link *link) ...@@ -76,6 +76,12 @@ static void destruct(struct dc_link *link)
{ {
int i; 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) if (link->ddc)
dal_ddc_service_destroy(&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) ...@@ -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) bool dc_link_get_hpd_state(struct dc_link *dc_link)
{ {
struct gpio *hpd_pin;
uint32_t state; uint32_t state;
hpd_pin = get_hpd_gpio(dc_link->ctx->dc_bios, dal_gpio_lock_pin(dc_link->hpd_gpio);
dc_link->link_id, dc_link->ctx->gpio_service); dal_gpio_get_value(dc_link->hpd_gpio, &state);
if (hpd_pin == NULL) dal_gpio_unlock_pin(dc_link->hpd_gpio);
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);
return state; return state;
} }
...@@ -1098,7 +1097,6 @@ static bool construct( ...@@ -1098,7 +1097,6 @@ static bool construct(
const struct link_init_data *init_params) const struct link_init_data *init_params)
{ {
uint8_t i; uint8_t i;
struct gpio *hpd_gpio = NULL;
struct ddc_service_init_data ddc_service_init_data = { { 0 } }; struct ddc_service_init_data ddc_service_init_data = { { 0 } };
struct dc_context *dc_ctx = init_params->ctx; struct dc_context *dc_ctx = init_params->ctx;
struct encoder_init_data enc_init_data = { 0 }; struct encoder_init_data enc_init_data = { 0 };
...@@ -1128,10 +1126,11 @@ static bool construct( ...@@ -1128,10 +1126,11 @@ static bool construct(
if (link->dc->res_pool->funcs->link_init) if (link->dc->res_pool->funcs->link_init)
link->dc->res_pool->funcs->link_init(link); link->dc->res_pool->funcs->link_init(link);
hpd_gpio = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service); 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);
if (hpd_gpio != NULL) dal_gpio_unlock_pin(link->hpd_gpio);
link->irq_source_hpd = dal_irq_get_source(hpd_gpio); if (link->hpd_gpio != NULL)
link->irq_source_hpd = dal_irq_get_source(link->hpd_gpio);
switch (link->link_id.id) { switch (link->link_id.id) {
case CONNECTOR_ID_HDMI_TYPE_A: case CONNECTOR_ID_HDMI_TYPE_A:
...@@ -1149,18 +1148,18 @@ static bool construct( ...@@ -1149,18 +1148,18 @@ static bool construct(
case CONNECTOR_ID_DISPLAY_PORT: case CONNECTOR_ID_DISPLAY_PORT:
link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT; link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
if (hpd_gpio != NULL) if (link->hpd_gpio != NULL)
link->irq_source_hpd_rx = link->irq_source_hpd_rx =
dal_irq_get_rx_source(hpd_gpio); dal_irq_get_rx_source(link->hpd_gpio);
break; break;
case CONNECTOR_ID_EDP: case CONNECTOR_ID_EDP:
link->connector_signal = SIGNAL_TYPE_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 = DC_IRQ_SOURCE_INVALID;
link->irq_source_hpd_rx = link->irq_source_hpd_rx =
dal_irq_get_rx_source(hpd_gpio); dal_irq_get_rx_source(link->hpd_gpio);
} }
break; break;
case CONNECTOR_ID_LVDS: case CONNECTOR_ID_LVDS:
...@@ -1171,10 +1170,7 @@ static bool construct( ...@@ -1171,10 +1170,7 @@ static bool construct(
goto create_fail; goto create_fail;
} }
if (hpd_gpio != NULL) {
dal_gpio_destroy_irq(&hpd_gpio);
hpd_gpio = NULL;
}
/* TODO: #DAL3 Implement id to str function.*/ /* TODO: #DAL3 Implement id to str function.*/
LINK_INFO("Connector[%d] description:" LINK_INFO("Connector[%d] description:"
...@@ -1277,8 +1273,9 @@ static bool construct( ...@@ -1277,8 +1273,9 @@ static bool construct(
ddc_create_fail: ddc_create_fail:
create_fail: create_fail:
if (hpd_gpio != NULL) { if (link->hpd_gpio != NULL) {
dal_gpio_destroy_irq(&hpd_gpio); dal_gpio_destroy_irq(&link->hpd_gpio);
link->hpd_gpio = NULL;
} }
return false; return false;
......
...@@ -125,6 +125,7 @@ struct dc_link { ...@@ -125,6 +125,7 @@ struct dc_link {
struct dc_link_status link_status; struct dc_link_status link_status;
struct link_trace link_trace; struct link_trace link_trace;
struct gpio *hpd_gpio;
}; };
const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link); const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link);
......
...@@ -101,6 +101,18 @@ enum gpio_mode dal_gpio_get_mode( ...@@ -101,6 +101,18 @@ enum gpio_mode dal_gpio_get_mode(
return gpio->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( enum gpio_result dal_gpio_change_mode(
struct gpio *gpio, struct gpio *gpio,
enum gpio_mode mode) enum gpio_mode mode)
......
...@@ -192,6 +192,34 @@ static void set_pin_free( ...@@ -192,6 +192,34 @@ static void set_pin_free(
service->busyness[id][en] = false; 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( enum gpio_result dal_gpio_service_open(
struct gpio_service *service, struct gpio_service *service,
enum gpio_id id, enum gpio_id id,
......
...@@ -52,4 +52,14 @@ void dal_gpio_service_close( ...@@ -52,4 +52,14 @@ void dal_gpio_service_close(
struct gpio_service *service, struct gpio_service *service,
struct hw_gpio_pin **ptr); 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 #endif
...@@ -59,6 +59,14 @@ enum gpio_result dal_gpio_change_mode( ...@@ -59,6 +59,14 @@ enum gpio_result dal_gpio_change_mode(
struct gpio *gpio, struct gpio *gpio,
enum gpio_mode mode); 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 */ /* Get the GPIO id */
enum gpio_id dal_gpio_get_id( enum gpio_id dal_gpio_get_id(
const struct gpio *gpio); const struct gpio *gpio);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment