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

Commit 5d993174 authored by Rajesh Bharathwaj's avatar Rajesh Bharathwaj
Browse files

drm:msm:dsi: support additional gpios in display panel



Adding support for additional gpios for dsi display panel in xr smartviewer
reference device.

Change-Id: I8816b0244037bf48eee9be62cdcc2fd8bcd84cc6
Signed-off-by: default avatarRajesh Bharathwaj <rajeshbharathwaj@codeaurora.org>
parent 9a3b96da
Loading
Loading
Loading
Loading
+316 −1
Original line number Original line Diff line number Diff line
/*
/*
 * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * it under the terms of the GNU General Public License version 2 and
@@ -252,6 +252,103 @@ static int dsi_panel_vreg_put(struct dsi_panel *panel)
	return rc;
	return rc;
}
}


static int dsi_panel_exd_gpio_request(struct dsi_panel *panel)
{
	int rc = 0;
	struct dsi_panel_exd_config *e_config = &panel->exd_config;

	if (!e_config->display_1p8_en && !e_config->led_5v_en &&
		!e_config->led_en1 && !e_config->led_en2 &&
		!e_config->oenab && !e_config->selab &&
		!e_config->switch_power)
		return 0;

	if (gpio_is_valid(e_config->display_1p8_en)) {
		rc = gpio_request(e_config->display_1p8_en, "display_1p8_en");
		if (rc) {
			pr_err("request for display_1p8_en failed, rc=%d\n",
				rc);
			goto error;
		}
	}

	if (gpio_is_valid(e_config->led_5v_en)) {
		rc = gpio_request(e_config->led_5v_en, "led_5v_en");
		if (rc) {
			pr_err("request for led_5v_en failed, rc=%d\n",
				rc);
			goto error_release_1p8;
		}
	}

	if (gpio_is_valid(e_config->led_en1)) {
		rc = gpio_request(e_config->led_en1, "led_en1");
		if (rc) {
			pr_err("request for led_en1 failed, rc=%d\n",
				rc);
			goto error_release_5v;
		}
	}

	if (gpio_is_valid(e_config->led_en2)) {
		rc = gpio_request(e_config->led_en2, "led_en2");
		if (rc) {
			pr_err("request for led_en2 failed, rc=%d\n",
				rc);
			goto error_release_led;
		}
	}

	if (gpio_is_valid(e_config->oenab)) {
		rc = gpio_request(e_config->oenab, "oenab");
		if (rc) {
			pr_err("request for oenab failed, rc=%d\n",
				rc);
			goto error_release_led2;
		}
	}

	if (gpio_is_valid(e_config->selab)) {
		rc = gpio_request(e_config->selab, "selab");
		if (rc) {
			pr_err("request for selab failed, rc=%d\n",
				rc);
			goto error_release_oenab;
		}
	}

	if (gpio_is_valid(e_config->switch_power)) {
		rc = gpio_request(e_config->switch_power, "switch_power");
		if (rc) {
			pr_err("request for switch_power failed, rc=%d\n",
				rc);
			goto error_release_selab;
		}
	}
	return rc;

error_release_selab:
	if (gpio_is_valid(e_config->selab))
		gpio_free(e_config->selab);
error_release_oenab:
	if (gpio_is_valid(e_config->oenab))
		gpio_free(e_config->oenab);
error_release_led2:
	if (gpio_is_valid(e_config->led_en2))
		gpio_free(e_config->led_en2);
error_release_led:
	if (gpio_is_valid(e_config->led_en1))
		gpio_free(e_config->led_en1);
error_release_5v:
	if (gpio_is_valid(e_config->led_5v_en))
		gpio_free(e_config->led_5v_en);
error_release_1p8:
	if (gpio_is_valid(e_config->display_1p8_en))
		gpio_free(e_config->display_1p8_en);
error:
	return rc;
}

static int dsi_panel_gpio_request(struct dsi_panel *panel)
static int dsi_panel_gpio_request(struct dsi_panel *panel)
{
{
	int rc = 0;
	int rc = 0;
@@ -303,6 +400,34 @@ static int dsi_panel_gpio_request(struct dsi_panel *panel)
	return rc;
	return rc;
}
}


static int dsi_panel_exd_gpio_release(struct dsi_panel *panel)
{
	struct dsi_panel_exd_config *e_config = &panel->exd_config;

	if (!e_config->display_1p8_en && !e_config->led_5v_en &&
		!e_config->led_en1 && !e_config->led_en2 &&
		!e_config->oenab && !e_config->selab &&
		!e_config->switch_power)
		return 0;

	if (gpio_is_valid(e_config->display_1p8_en))
		gpio_free(e_config->display_1p8_en);
	if (gpio_is_valid(e_config->led_5v_en))
		gpio_free(e_config->led_5v_en);
	if (gpio_is_valid(e_config->led_en1))
		gpio_free(e_config->led_en1);
	if (gpio_is_valid(e_config->led_en2))
		gpio_free(e_config->led_en2);
	if (gpio_is_valid(e_config->oenab))
		gpio_free(e_config->oenab);
	if (gpio_is_valid(e_config->selab))
		gpio_free(e_config->selab);
	if (gpio_is_valid(e_config->switch_power))
		gpio_free(e_config->switch_power);

	return 0;
}

static int dsi_panel_gpio_release(struct dsi_panel *panel)
static int dsi_panel_gpio_release(struct dsi_panel *panel)
{
{
	int rc = 0;
	int rc = 0;
@@ -426,6 +551,110 @@ static int dsi_panel_set_pinctrl_state(struct dsi_panel *panel, bool enable)
	return rc;
	return rc;
}
}


static int dsi_panel_exd_enable(struct dsi_panel *panel)
{
	int rc = 0;
	struct dsi_panel_exd_config *e_config = &panel->exd_config;

	if (!e_config->display_1p8_en && !e_config->led_5v_en &&
			!e_config->led_en1 && !e_config->led_en2 &&
			!e_config->oenab && !e_config->selab &&
			!e_config->switch_power)
		return 0;

	if (gpio_is_valid(e_config->display_1p8_en)) {
		rc = gpio_direction_output(e_config->display_1p8_en, 0);
		if (rc) {
			pr_err("unable to set dir for disp_1p8_en rc:%d\n",
				rc);
			goto exit;
		}
		gpio_set_value(e_config->display_1p8_en, 1);
	}

	if (gpio_is_valid(e_config->switch_power)) {
		rc = gpio_direction_output(e_config->switch_power, 0);
		if (rc) {
			pr_err("unable to set dir for switch_power rc:%d\n",
				rc);
			goto exit;
		}
		gpio_set_value(e_config->switch_power, 1);
	}

	if (gpio_is_valid(e_config->led_5v_en)) {
		rc = gpio_direction_output(e_config->led_5v_en, 0);
		if (rc) {
			pr_err("unable to set dir for led_5v_en rc:%d\n", rc);
			goto exit;
		}
		gpio_set_value(e_config->led_5v_en, 1);
	}

	if (gpio_is_valid(e_config->led_en1)) {
		rc = gpio_direction_output(e_config->led_en1, 0);
		if (rc) {
			pr_err("unable to set dir for led_en1 rc:%d\n", rc);
			goto exit;
		}
		gpio_set_value(e_config->led_en1, 1);
	}

	if (gpio_is_valid(e_config->led_en2)) {
		rc = gpio_direction_output(e_config->led_en2, 0);
		if (rc) {
			pr_err("unable to set dir for led_en2 rc:%d\n", rc);
			goto exit;
		}
		gpio_set_value(e_config->led_en2, 1);
	}

	if (gpio_is_valid(e_config->oenab)) {
		rc = gpio_direction_output(e_config->oenab, 0);
		if (rc) {
			pr_err("unable to set dir for oenab rc:%d\n", rc);
			goto exit;
		}
		gpio_set_value(e_config->oenab, 0);
	}

	if (gpio_is_valid(e_config->selab)) {
		rc = gpio_direction_output(e_config->selab, 0);
		if (rc) {
			pr_err("unable to set dir for selab rc:%d\n", rc);
			goto exit;
		}
		gpio_set_value(e_config->selab, 1);
	}
exit:
	return rc;
}

static void dsi_panel_exd_disable(struct dsi_panel *panel)
{
	struct dsi_panel_exd_config *e_config = &panel->exd_config;

	if (!e_config->display_1p8_en && !e_config->led_5v_en &&
		!e_config->led_en1 && !e_config->led_en2 &&
		!e_config->oenab && !e_config->selab &&
		!e_config->switch_power)
		return;

	if (gpio_is_valid(e_config->display_1p8_en))
		gpio_set_value(e_config->display_1p8_en, 0);
	if (gpio_is_valid(e_config->led_5v_en))
		gpio_set_value(e_config->led_5v_en, 0);
	if (gpio_is_valid(e_config->led_en1))
		gpio_set_value(e_config->led_en1, 0);
	if (gpio_is_valid(e_config->led_en2))
		gpio_set_value(e_config->led_en2, 0);
	if (gpio_is_valid(e_config->oenab))
		gpio_set_value(e_config->oenab, 1);
	if (gpio_is_valid(e_config->selab))
		gpio_set_value(e_config->selab, 0);
	if (gpio_is_valid(e_config->switch_power))
		gpio_set_value(e_config->switch_power, 0);
}


static int dsi_panel_power_on(struct dsi_panel *panel)
static int dsi_panel_power_on(struct dsi_panel *panel)
{
{
@@ -449,6 +678,13 @@ static int dsi_panel_power_on(struct dsi_panel *panel)
		goto error_disable_gpio;
		goto error_disable_gpio;
	}
	}


	rc = dsi_panel_exd_enable(panel);
	if (rc) {
		pr_err("[%s] failed to reset panel, rc=%d\n", panel->name, rc);
		dsi_panel_exd_disable(panel);
		goto error_disable_gpio;
	}

	goto exit;
	goto exit;


error_disable_gpio:
error_disable_gpio:
@@ -471,6 +707,8 @@ static int dsi_panel_power_off(struct dsi_panel *panel)
{
{
	int rc = 0;
	int rc = 0;


	dsi_panel_exd_disable(panel);

	if (gpio_is_valid(panel->reset_config.disp_en_gpio))
	if (gpio_is_valid(panel->reset_config.disp_en_gpio))
		gpio_set_value(panel->reset_config.disp_en_gpio, 0);
		gpio_set_value(panel->reset_config.disp_en_gpio, 0);


@@ -1887,6 +2125,63 @@ static int dsi_panel_parse_power_cfg(struct device *parent,
	return rc;
	return rc;
}
}


static int dsi_panel_exd_parse_gpios(struct dsi_panel *panel,
				 struct device_node *of_node)
{
	int rc = 0;
	struct dsi_panel_exd_config *e_config = &panel->exd_config;

	e_config->display_1p8_en = of_get_named_gpio(of_node,
			"qcom,1p8-en-gpio", 0);
	if (!e_config->display_1p8_en) {
		pr_debug("%s qcom,display-1p8-en-gpio not found\n", __func__);
		return -EINVAL;
	}

	e_config->led_5v_en = of_get_named_gpio(of_node,
				"qcom,led-5v-en-gpio", 0);
	if (!e_config->led_5v_en) {
		pr_debug("%s qcom,led-5v-en-gpio not found\n", __func__);
		return -EINVAL;
	}

	e_config->led_en1 = of_get_named_gpio(of_node,
				"qcom,led-driver-en1-gpio", 0);
	if (!e_config->led_en1) {
		pr_debug("%s qcom,led-driver-en1-gpio not found\n", __func__);
		return -EINVAL;
	}

	e_config->led_en2 = of_get_named_gpio(of_node,
				"qcom,led-driver-en2-gpio", 0);
	if (!e_config->led_en2) {
		pr_debug("%s qcom,led-driver-en2-gpio not found\n", __func__);
		return -EINVAL;
	}

	e_config->oenab = of_get_named_gpio(of_node,
				"qcom,oenab-gpio", 0);
	if (!e_config->oenab) {
		pr_debug("%s qcom,oenab-gpio not found\n", __func__);
		return -EINVAL;
	}

	e_config->selab = of_get_named_gpio(of_node,
				"qcom,selab-gpio", 0);
	if (!e_config->selab) {
		pr_debug("%s qcom,selab-gpio not found\n", __func__);
		return -EINVAL;
	}

	e_config->switch_power = of_get_named_gpio(of_node,
				"qcom,switch-power-gpio", 0);
	if (!e_config->switch_power) {
		pr_debug("%s qcom,switch_power not found\n", __func__);
		return -EINVAL;
	}
	return rc;
}

static int dsi_panel_parse_gpios(struct dsi_panel *panel,
static int dsi_panel_parse_gpios(struct dsi_panel *panel,
				 struct device_node *of_node)
				 struct device_node *of_node)
{
{
@@ -1942,6 +2237,12 @@ static int dsi_panel_parse_gpios(struct dsi_panel *panel,
		panel->reset_config.mode_sel_state = MODE_SEL_DUAL_PORT;
		panel->reset_config.mode_sel_state = MODE_SEL_DUAL_PORT;
	}
	}


	/* Extended display panel gpios parsed */
	rc = dsi_panel_exd_parse_gpios(panel, of_node);
	if (rc && rc != -EINVAL)
		pr_err("[%s] failed to parse gpios, rc=%d\n",
				panel->name, rc);

	/* TODO:  release memory */
	/* TODO:  release memory */
	rc = dsi_panel_parse_reset_sequence(panel, of_node);
	rc = dsi_panel_parse_reset_sequence(panel, of_node);
	if (rc) {
	if (rc) {
@@ -3105,8 +3406,17 @@ int dsi_panel_drv_init(struct dsi_panel *panel,
		goto error_gpio_release;
		goto error_gpio_release;
	}
	}


	rc = dsi_panel_exd_gpio_request(panel);
	if (rc) {
		pr_err("[%s] failed to request gpios, rc=%d\n", panel->name,
				rc);
		goto error_exd_gpio_release;
	}

	goto exit;
	goto exit;


error_exd_gpio_release:
	(void)dsi_panel_exd_gpio_release(panel);
error_gpio_release:
error_gpio_release:
	(void)dsi_panel_gpio_release(panel);
	(void)dsi_panel_gpio_release(panel);
error_pinctrl_deinit:
error_pinctrl_deinit:
@@ -3142,6 +3452,11 @@ int dsi_panel_drv_deinit(struct dsi_panel *panel)
		pr_err("[%s] failed to release gpios, rc=%d\n", panel->name,
		pr_err("[%s] failed to release gpios, rc=%d\n", panel->name,
		       rc);
		       rc);


	rc = dsi_panel_exd_gpio_release(panel);
	if (rc)
		pr_err("[%s] failed to release gpios, rc=%d\n", panel->name,
			rc);

	rc = dsi_panel_pinctrl_deinit(panel);
	rc = dsi_panel_pinctrl_deinit(panel);
	if (rc)
	if (rc)
		pr_err("[%s] failed to deinit gpios, rc=%d\n", panel->name,
		pr_err("[%s] failed to deinit gpios, rc=%d\n", panel->name,
+14 −1
Original line number Original line Diff line number Diff line
/*
/*
 * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * it under the terms of the GNU General Public License version 2 and
@@ -161,6 +161,17 @@ enum dsi_panel_type {
	DSI_PANEL_TYPE_MAX,
	DSI_PANEL_TYPE_MAX,
};
};


/* Extended Panel config for panels with additional gpios */
struct dsi_panel_exd_config {
	int display_1p8_en;
	int led_5v_en;
	int switch_power;
	int led_en1;
	int led_en2;
	int oenab;
	int selab;
};

struct dsi_panel {
struct dsi_panel {
	const char *name;
	const char *name;
	enum dsi_panel_type type;
	enum dsi_panel_type type;
@@ -204,6 +215,8 @@ struct dsi_panel {
	enum dsi_dms_mode dms_mode;
	enum dsi_dms_mode dms_mode;


	bool sync_broadcast_en;
	bool sync_broadcast_en;

	struct dsi_panel_exd_config exd_config;
};
};


static inline bool dsi_panel_ulps_feature_enabled(struct dsi_panel *panel)
static inline bool dsi_panel_ulps_feature_enabled(struct dsi_panel *panel)