Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+22 −25
Original line number Diff line number Diff line
@@ -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 @@ static bool construct(
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;
+1 −0
Original line number Diff line number Diff line
@@ -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);
+12 −0
Original line number Diff line number Diff line
@@ -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)
+28 −0
Original line number Diff line number Diff line
@@ -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,
+10 −0
Original line number Diff line number Diff line
@@ -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
Loading