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

Commit 79ac7827 authored by raghavendra ambadas's avatar raghavendra ambadas Committed by Nirmal Abraham
Browse files

fbdev: msm: Add SPI display support for mdss driver



Add changes to support both mdss and mdp3 driver
for SPI panel display.

Change-Id: Ia2a41e2dbf84d4a0ec2c2018d83cdf2b35c697b5
Signed-off-by: default avatarRaghavendra Ambadas <rambad@codeaurora.org>
parent 7dae21e8
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -98,6 +98,7 @@ static struct mdss_panel_intf pan_types[] = {
	{"dsi", MDSS_PANEL_INTF_DSI},
	{"edp", MDSS_PANEL_INTF_EDP},
	{"hdmi", MDSS_PANEL_INTF_HDMI},
	{"spi", MDSS_PANEL_INTF_SPI},
};
static char mdss_mdp_panel[MDSS_MAX_PANEL_LEN];

+35 −5
Original line number Diff line number Diff line
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2018, 2020, The Linux Foundation. All rights reserved.
 *
 * 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
@@ -121,7 +121,8 @@ int mdss_spi_tx_parameter(const void *buf, size_t len)
	return rc;
}

int mdss_spi_tx_pixel(const void *buf, size_t len)
#ifdef TARGET_HW_MDSS_MDP3
int mdp3_spi_tx_pixel(const void *buf, size_t len)
{
	int rc = 0;
	struct spi_transfer t = {
@@ -142,6 +143,35 @@ int mdss_spi_tx_pixel(const void *buf, size_t len)

	return rc;
}
#else
int mdss_spi_tx_pixel(const void *buf, size_t len,
	void (*spi_tx_compelet)(void *), void *ctx)
{
	int rc = 0;
	static struct spi_transfer t;
	static struct spi_message m;

	if (!mdss_spi_client) {
		pr_err("%s: spi client not available\n", __func__);
		return -EINVAL;
	}

	mdss_spi_client->bits_per_word = 16;
	t.tx_buf = buf;
	t.len = len;
	spi_message_init(&m);
	m.complete = spi_tx_compelet;
	m.context = ctx;

	spi_message_add_tail(&t, &m);
	rc = spi_async(mdss_spi_client, &m);

	if (rc)
		pr_err("%s: send FrameBuffer data failed\n", __func__);

	return rc;
}
#endif

static int mdss_spi_client_probe(struct spi_device *spidev)
{
+9 −4
Original line number Diff line number Diff line
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2018, 2020, The Linux Foundation. All rights reserved.
 *
 * 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
@@ -10,11 +10,16 @@
 * GNU General Public License for more details.
 */

#ifndef __MDSS_SPI_CLINET_H__
#define __MDSS_SPI_CLINET_H__
#ifndef __MDSS_SPI_CLIENT_H__
#define __MDSS_SPI_CLIENT_H__

int mdss_spi_tx_command(const void *buf);
int mdss_spi_tx_parameter(const void *buf, size_t len);
int mdss_spi_tx_pixel(const void *buf, size_t len);
#ifdef TARGET_HW_MDSS_MDP3
int mdp3_spi_tx_pixel(const void *buf, size_t len);
#else
int mdss_spi_tx_pixel(const void *buf, size_t len,
		void (*spi_tx_compelet)(void *), void *ctx);
#endif
int mdss_spi_read_data(u8 reg_addr, u8 *data, u8 len);
#endif /* End of __MDSS_SPI_CLINET_H__ */
+12 −7
Original line number Diff line number Diff line
@@ -284,9 +284,13 @@ int mdss_spi_display_pre_commit(struct msm_fb_data_type *mfd,

	/* remove padding and copy to continuous buffer */
	while (scan_count < panel_yres) {
		memcpy((ctrl_pdata->back_buf + scan_count * actual_stride),
			(ctrl_pdata->image_data.addr + scan_count *
			(actual_stride + padding_length)), actual_stride);
		if (!(ctrl_pdata->back_buf) || !(ctrl_pdata->image_data.addr)) {
			pr_err("Null Pointer, return\n");
			return 0;
		}
		memcpy((ctrl_pdata->back_buf + (scan_count * actual_stride)),
			(ctrl_pdata->image_data.addr + (scan_count *
			(actual_stride + padding_length))), actual_stride);
				scan_count++;
	}

@@ -334,7 +338,7 @@ int mdss_spi_display_atomic_validate(struct msm_fb_data_type *mfd,
	return 0;
}

int mdss_spi_panel_kickoff(struct msm_fb_data_type *mfd,
int mdss_spi_display_kickoff(struct msm_fb_data_type *mfd,
			struct mdp_display_commit *data)
{
	struct spi_panel_data *ctrl_pdata = NULL;
@@ -361,10 +365,11 @@ int mdss_spi_panel_kickoff(struct msm_fb_data_type *mfd,
		mutex_unlock(&ctrl_pdata->spi_tx_mutex);
		return rc;
	}

#ifndef TARGET_HW_MDSS_MDP3
	rc = mdss_spi_tx_pixel(ctrl_pdata->front_buf,
				ctrl_pdata->byte_per_frame,
				mdss_spi_tx_fb_complete, ctrl_pdata);
#endif
	mdss_spi_display_notify(ctrl_pdata, MDP_NOTIFY_FRAME_FLUSHED);

	mutex_unlock(&ctrl_pdata->spi_tx_mutex);
@@ -629,7 +634,7 @@ int mdss_spi_overlay_init(struct msm_fb_data_type *mfd)
	spi_display_interface->cursor_update = NULL;

	spi_display_interface->ioctl_handler = spi_display_ioctl_handler;
	spi_display_interface->kickoff_fnc = mdss_spi_panel_kickoff;
	spi_display_interface->kickoff_fnc = mdss_spi_display_kickoff;
	spi_display_interface->pre_commit = mdss_spi_display_pre_commit;
	spi_display_interface->atomic_validate =
				mdss_spi_display_atomic_validate;
+180 −107
Original line number Diff line number Diff line
@@ -24,10 +24,12 @@
#include "mdss_panel.h"
#include "mdss_spi_panel.h"
#include "mdss_spi_client.h"
#ifdef TARGET_HW_MDSS_MDP3
#include "mdp3.h"
#endif

DEFINE_LED_TRIGGER(bl_led_trigger);
static int mdss_spi_panel_reset(struct mdss_panel_data *pdata, int enable)
int mdss_spi_panel_reset(struct mdss_panel_data *pdata, int enable)
{
	struct spi_panel_data *ctrl_pdata = NULL;
	struct mdss_panel_info *pinfo = NULL;
@@ -92,11 +94,13 @@ static int mdss_spi_panel_reset(struct mdss_panel_data *pdata, int enable)
		gpio_direction_output(ctrl_pdata->disp_dc_gpio, 0);
		gpio_free(ctrl_pdata->disp_dc_gpio);
	}
	if (pinfo->cont_splash_enabled)
		pinfo->cont_splash_enabled = false;
	return rc;
}


static int mdss_spi_panel_pinctrl_set_state(
int mdss_spi_panel_pinctrl_set_state(
	struct spi_panel_data *ctrl_pdata,
	bool active)
{
@@ -149,7 +153,71 @@ static int mdss_spi_panel_pinctrl_init(struct platform_device *pdev)

	return 0;
}
#ifndef TARGET_HW_MDSS_MDP3
static int mdss_spi_panel_power_on(struct mdss_panel_data *pdata)
{
	int ret = 0;
	struct spi_panel_data *ctrl_pdata = NULL;

	if (WARN_ON(!pdata))
		return -EINVAL;

	ctrl_pdata = container_of(pdata, struct spi_panel_data,
					panel_data);
	ret = msm_mdss_enable_vreg(
			ctrl_pdata->panel_power_data.vreg_config,
			ctrl_pdata->panel_power_data.num_vreg, 1);
	if (ret) {
		pr_err("%s: failed to enable vregs for PANEL_PM\n",
						__func__);
		return ret;
	}

	/*
	 * If continuous splash screen feature is enabled, then we need to
	 * request all the GPIOs that have already been configured in the
	 * bootloader. This needs to be done irresepective of whether
	 * the lp11_init flag is set or not.
	 */
	if (pdata->panel_info.cont_splash_enabled) {
		if (mdss_spi_panel_pinctrl_set_state(ctrl_pdata, true))
			pr_err("reset enable: pinctrl not enabled\n");
		ret = mdss_spi_panel_reset(pdata, 1);
		if (ret)
			pr_err("%s: Panel reset failed. rc=%d\n",
				__func__, ret);
	}

	return ret;
}

static int mdss_spi_panel_power_off(struct mdss_panel_data *pdata)
{
	int ret = 0;
	struct spi_panel_data *ctrl_pdata = NULL;

	if (WARN_ON(!pdata))
		return -EINVAL;
	ctrl_pdata = container_of(pdata, struct spi_panel_data,
					panel_data);
	ret = mdss_spi_panel_reset(pdata, 0);
	if (ret)
		pr_warn("%s: Panel reset failed. rc=%d\n", __func__, ret);

	if (mdss_spi_panel_pinctrl_set_state(ctrl_pdata, false))
		pr_warn("reset disable: pinctrl not enabled\n");

	ret = msm_mdss_enable_vreg(
		ctrl_pdata->panel_power_data.vreg_config,
		ctrl_pdata->panel_power_data.num_vreg, 0);
	if (ret)
		pr_err("%s: failed to disable vregs for PANEL_PM\n",
					__func__);

	return ret;
}

#else

static int mdss_spi_panel_power_on(struct mdss_panel_data *pdata)
{
@@ -227,9 +295,9 @@ static int mdss_spi_panel_power_off(struct mdss_panel_data *pdata)
end:
	return ret;
}
#endif


static int mdss_spi_panel_power_ctrl(struct mdss_panel_data *pdata,
int mdss_spi_panel_power_ctrl(struct mdss_panel_data *pdata,
	int power_state)
{
	int ret;
@@ -392,7 +460,7 @@ int is_spi_panel_continuous_splash_on(struct mdss_panel_data *pdata)
	return true;
}

static void enable_spi_panel_te_irq(struct spi_panel_data *ctrl_pdata,
void enable_spi_panel_te_irq(struct spi_panel_data *ctrl_pdata,
							bool enable)
{
	static bool is_enabled = true;
@@ -413,7 +481,7 @@ static void enable_spi_panel_te_irq(struct spi_panel_data *ctrl_pdata,

	is_enabled = enable;
}

#ifdef TARGET_HW_MDSS_MDP3
int mdss_spi_panel_kickoff(struct mdss_panel_data *pdata,
			char __iomem *buf, int len, int dma_stride)
{
@@ -462,11 +530,25 @@ int mdss_spi_panel_kickoff(struct mdss_panel_data *pdata,
	if (rc == 0)
		pr_err("wait panel TE time out\n");

	rc = mdss_spi_tx_pixel(tx_buf, ctrl_pdata->byte_pre_frame);
	rc = mdp3_spi_tx_pixel(tx_buf, ctrl_pdata->byte_per_frame);
	mutex_unlock(&ctrl_pdata->spi_tx_mutex);

	return rc;
}
#else
void mdss_spi_tx_fb_complete(void *ctx)
{
	struct spi_panel_data *ctrl_pdata = ctx;

	if (atomic_add_unless(&ctrl_pdata->koff_cnt, -1, 0)) {
		if (atomic_read(&ctrl_pdata->koff_cnt)) {
			pr_err("%s: too many kickoffs=%d\n", __func__,
				atomic_read(&ctrl_pdata->koff_cnt));
		}
		wake_up_all(&ctrl_pdata->tx_done_waitq);
	}
}
#endif

static int mdss_spi_read_panel_data(struct mdss_panel_data *pdata,
		u8 reg_addr, u8 *data, u8 len)
@@ -486,7 +568,7 @@ static int mdss_spi_read_panel_data(struct mdss_panel_data *pdata,
	return rc;
}

static int mdss_spi_panel_on(struct mdss_panel_data *pdata)
int mdss_spi_panel_on(struct mdss_panel_data *pdata)
{
	struct spi_panel_data *ctrl = NULL;
	struct mdss_panel_info *pinfo;
@@ -522,7 +604,7 @@ static int mdss_spi_panel_on(struct mdss_panel_data *pdata)
}


static int mdss_spi_panel_off(struct mdss_panel_data *pdata)
int mdss_spi_panel_off(struct mdss_panel_data *pdata)
{
	struct spi_panel_data *ctrl = NULL;
	struct mdss_panel_info *pinfo;
@@ -1008,6 +1090,16 @@ static int mdss_spi_panel_parse_dt(struct device_node *np,
	rc = of_property_read_u32(np, "qcom,mdss-spi-v-pulse-width", &tmp);
	pinfo->lcdc.v_pulse_width = (!rc ? tmp : 2);

	/*
	 * Due to SPI clock limit, frame rate of SPI display can olny reach to
	 * ~30fps with resolution is 240*240 and format is rgb565.
	 * VSYNC frequency should be match frame rate for avoid flicker issue.
	 * but some panels can't support that TE frequency lower than 30Hz, so
	 * we need to set double the TE frequency in this case.
	 */
	rc = of_property_read_u32(np, "qcom,mdss-spi-panel-te-per-vsync", &tmp);
	ctrl_pdata->vsync_per_te = (!rc ? tmp : 2);
	pr_debug("%s: vsync_per_te=%d\n", __func__, ctrl_pdata->vsync_per_te);

	rc = of_property_read_u32(np, "qcom,mdss-spi-bpp", &tmp);
	if (rc) {
@@ -1105,6 +1197,7 @@ static void mdss_spi_panel_pwm_cfg(struct spi_panel_data *ctrl)
	if (ctrl->pwm_bl == NULL || IS_ERR(ctrl->pwm_bl)) {
		pr_err("%s: Error: lpg_chan=%d pwm request failed",
				__func__, ctrl->pwm_lpg_chan);
		ctrl->pwm_bl = NULL;
	}
	ctrl->pwm_enabled = 0;
}
@@ -1167,7 +1260,8 @@ static void mdss_spi_panel_bklt_pwm(struct spi_panel_data *ctrl, int level)
		ctrl->pwm_enabled = 1;
	}
}

#if defined(CONFIG_FB_MSM_MDSS_SPI_PANEL) && defined(CONFIG_SPI_QUP)
#ifdef TARGET_HW_MDSS_MDP3
static void mdss_spi_panel_bl_ctrl(struct mdss_panel_data *pdata,
							u32 bl_level)
{
@@ -1179,8 +1273,7 @@ static void mdss_spi_panel_bl_ctrl(struct mdss_panel_data *pdata,
		mdss_spi_panel_bl_ctrl_update(pdata, bl_level);
	}
}

#if defined(CONFIG_FB_MSM_MDSS_SPI_PANEL) && defined(CONFIG_SPI_QUP)
#endif
void mdss_spi_panel_bl_ctrl_update(struct mdss_panel_data *pdata,
							u32 bl_level)
{
@@ -1211,7 +1304,6 @@ void mdss_spi_panel_bl_ctrl_update(struct mdss_panel_data *pdata,
	}
}
#endif

static int mdss_spi_panel_init(struct device_node *node,
	struct spi_panel_data	*ctrl_pdata,
	bool cmd_cfg_cont_splash)
@@ -1243,10 +1335,10 @@ static int mdss_spi_panel_init(struct device_node *node,
		return rc;
	}

	ctrl_pdata->byte_pre_frame = pinfo->xres * pinfo->yres * pinfo->bpp/8;

	ctrl_pdata->tx_buf = kmalloc(ctrl_pdata->byte_pre_frame, GFP_KERNEL);

	ctrl_pdata->byte_per_frame = pinfo->xres * pinfo->yres * pinfo->bpp/8;
	ctrl_pdata->tx_buf = kzalloc(ctrl_pdata->byte_per_frame, GFP_KERNEL);
	ctrl_pdata->front_buf = kzalloc(ctrl_pdata->byte_per_frame, GFP_KERNEL);
	ctrl_pdata->back_buf = kmalloc(ctrl_pdata->byte_per_frame, GFP_KERNEL);
	if (!cmd_cfg_cont_splash)
		pinfo->cont_splash_enabled = false;

@@ -1259,7 +1351,11 @@ static int mdss_spi_panel_init(struct device_node *node,

	ctrl_pdata->on = mdss_spi_panel_on;
	ctrl_pdata->off = mdss_spi_panel_off;
#ifdef TARGET_HW_MDSS_MDP3
	ctrl_pdata->panel_data.set_backlight = mdss_spi_panel_bl_ctrl;
#else
	ctrl_pdata->panel_data.set_backlight = mdss_spi_panel_bl_ctrl_update;
#endif

	return 0;
}
@@ -1281,11 +1377,10 @@ static int mdss_spi_get_panel_cfg(char *panel_cfg,
		return 0;
	}

	pr_debug("%s:%d: cfg:[%s]\n", __func__, __LINE__,
	pr_err("%s:%d: cfg:[%s]\n", __func__, __LINE__,
		 pan_cfg->arg_cfg);
	ctrl_pdata->panel_data.panel_info.is_prim_panel = true;
	rc = strlcpy(panel_cfg, pan_cfg->arg_cfg,
		     sizeof(pan_cfg->arg_cfg));
	rc = strlcpy(panel_cfg, "spi", sizeof(MDSS_MAX_PANEL_LEN));
	return rc;
}

@@ -1316,7 +1411,7 @@ static int mdss_spi_panel_regulator_init(struct platform_device *pdev)
	return rc;

}

#ifdef TARGET_HW_MDSS_MDP3
static irqreturn_t spi_panel_te_handler(int irq, void *data)
{
	struct spi_panel_data *ctrl_pdata = (struct spi_panel_data *)data;
@@ -1370,6 +1465,55 @@ void mdp3_spi_vsync_enable(struct mdss_panel_data *pdata,
			enable_spi_panel_te_irq(ctrl_pdata, false);
	}
}
#else
static void mdss_spi_display_handle_vsync(struct spi_panel_data *ctrl_pdata,
					ktime_t t)
{
	ctrl_pdata->vsync_time = t;
	sysfs_notify_dirent(ctrl_pdata->vsync_event_sd);
}

static irqreturn_t spi_panel_te_handler(int irq, void *data)
{
	struct spi_panel_data *ctrl_pdata = (struct spi_panel_data *)data;
	ktime_t vsync_time;

	complete(&ctrl_pdata->spi_panel_te);

	if (ctrl_pdata->vsync_enable && (ctrl_pdata->te_count ==
				ctrl_pdata->vsync_per_te)) {
		vsync_time = ktime_get();
		mdss_spi_display_handle_vsync(ctrl_pdata, vsync_time);
		ctrl_pdata->te_count = 0;
	}

	return IRQ_HANDLED;
}
#endif

void mdss_spi_vsync_enable(struct mdss_panel_data *pdata, int enable)
{
	struct spi_panel_data *ctrl_pdata = NULL;

	if (WARN_ON(!pdata))
		return;

	ctrl_pdata = container_of(pdata, struct spi_panel_data,
					panel_data);
	mutex_lock(&ctrl_pdata->te_mutex);
	if (enable) {
		if (ctrl_pdata->vsync_enable == false) {
			enable_spi_panel_te_irq(ctrl_pdata, true);
			ctrl_pdata->vsync_enable = true;
		}
	} else {
		if (ctrl_pdata->vsync_enable == true) {
			enable_spi_panel_te_irq(ctrl_pdata, false);
			ctrl_pdata->vsync_enable = false;
		}
	}
	mutex_unlock(&ctrl_pdata->te_mutex);
}

static struct device_node *mdss_spi_pref_prim_panel(
		struct platform_device *pdev)
@@ -1465,6 +1609,8 @@ static int spi_panel_device_register(struct device_node *pan_node,
	rc = mdss_register_panel(ctrl_pdev, &(ctrl_pdata->panel_data));
	if (rc) {
		pr_err("%s: unable to register SPI panel\n", __func__);
		gpio_free(ctrl_pdata->rst_gpio);
		gpio_free(ctrl_pdata->disp_dc_gpio);
		return rc;
	}

@@ -1473,89 +1619,20 @@ static int spi_panel_device_register(struct device_node *pan_node,
}


/**
 * mdss_spi_find_panel_of_node(): find device node of spi panel
 * @pdev: platform_device of the spi ctrl node
 * @panel_cfg: string containing intf specific config data
 *
 * Function finds the panel device node using the interface
 * specific configuration data. This configuration data is
 * could be derived from the result of bootloader's GCDB
 * panel detection mechanism. If such config data doesn't
 * exist then this panel returns the default panel configured
 * in the device tree.
 *
 * returns pointer to panel node on success, NULL on error.
 */
static struct device_node *mdss_spi_find_panel_of_node(
		struct platform_device *pdev, char *panel_cfg)
int mdss_spi_wait_tx_done(struct spi_panel_data *ctrl_pdata)
{
	int len, i;
	int ctrl_id = pdev->id - 1;
	char panel_name[MDSS_MAX_PANEL_LEN] = "";
	char ctrl_id_stream[3] =  "0:";
	char *stream = NULL, *pan = NULL;
	struct device_node *spi_pan_node = NULL, *mdss_node = NULL;

	len = strlen(panel_cfg);
	if (!len) {
		/* no panel cfg chg, parse dt */
		pr_err("%s:%d: no cmd line cfg present\n",
			 __func__, __LINE__);
		goto end;
	} else {
		if (ctrl_id == 1)
			strlcpy(ctrl_id_stream, "1:", 3);

		stream = strnstr(panel_cfg, ctrl_id_stream, len);
		if (!stream) {
			pr_err("controller config is not present\n");
			goto end;
		}
		stream += 2;

		pan = strnchr(stream, strlen(stream), ':');
		if (!pan) {
			strlcpy(panel_name, stream, MDSS_MAX_PANEL_LEN);
		} else {
			for (i = 0; (stream + i) < pan; i++)
				panel_name[i] = *(stream + i);
			panel_name[i] = 0;
		}

		pr_debug("%s:%d:%s:%s\n", __func__, __LINE__,
			 panel_cfg, panel_name);

		mdss_node = of_parse_phandle(pdev->dev.of_node,
					     "qcom,mdss-mdp", 0);
		if (!mdss_node) {
			pr_err("%s: %d: mdss_node null\n",
			       __func__, __LINE__);
			return NULL;
		}
	int rc = 0;

		spi_pan_node = of_find_node_by_name(mdss_node,
						    panel_name);
		if (!spi_pan_node) {
			pr_err("%s: invalid pan node, selecting prim panel\n",
			       __func__);
			goto end;
		}
		return spi_pan_node;
	}
end:
	if (strcmp(panel_name, NONE_PANEL))
		spi_pan_node = mdss_spi_pref_prim_panel(pdev);
	of_node_put(mdss_node);
	return spi_pan_node;
	rc = wait_event_timeout(ctrl_pdata->tx_done_waitq,
			atomic_read(&ctrl_pdata->koff_cnt) == 0,
			KOFF_TIMEOUT);
		return rc;
}


static int mdss_spi_panel_probe(struct platform_device *pdev)
{
	int rc = 0;
	struct spi_panel_data	*ctrl_pdata;
	struct mdss_panel_cfg *pan_cfg = NULL;
	struct device_node *spi_pan_node = NULL;
	bool cmd_cfg_cont_splash = true;
	char panel_cfg[MDSS_MAX_PANEL_LEN];
@@ -1578,15 +1655,6 @@ static int mdss_spi_panel_probe(struct platform_device *pdev)
		return -ENOTSUPP;
	}

	pan_cfg = util->panel_intf_type(MDSS_PANEL_INTF_DSI);
	if (IS_ERR(pan_cfg)) {
		pr_err("%s: return MDSS_PANEL_INTF_DSI\n", __func__);
		return PTR_ERR(pan_cfg);
	} else if (pan_cfg) {
		pr_err("%s: DSI is primary\n", __func__);
		return -ENODEV;
	}

	ctrl_pdata = platform_get_drvdata(pdev);
	if (!ctrl_pdata) {
		ctrl_pdata = devm_kzalloc(&pdev->dev,
@@ -1642,7 +1710,7 @@ static int mdss_spi_panel_probe(struct platform_device *pdev)
			__func__, __LINE__);

	/* find panel device node */
	spi_pan_node = mdss_spi_find_panel_of_node(pdev, panel_cfg);
	spi_pan_node = mdss_spi_pref_prim_panel(pdev);
	if (!spi_pan_node) {
		pr_err("%s: can't find panel node %s\n", __func__, panel_cfg);
		goto error_pan_node;
@@ -1667,6 +1735,8 @@ static int mdss_spi_panel_probe(struct platform_device *pdev)

	init_completion(&ctrl_pdata->spi_panel_te);
	mutex_init(&ctrl_pdata->spi_tx_mutex);
	mutex_init(&ctrl_pdata->te_mutex);
	init_waitqueue_head(&ctrl_pdata->tx_done_waitq);

	rc = devm_request_irq(&pdev->dev,
		gpio_to_irq(ctrl_pdata->disp_te_gpio),
@@ -1674,12 +1744,15 @@ static int mdss_spi_panel_probe(struct platform_device *pdev)
		"TE_GPIO", ctrl_pdata);
	if (rc) {
		pr_err("TE request_irq failed.\n");
		return rc;
		goto error_te_request;
	}

	pr_debug("%s: spi panel  initialized\n", __func__);
	return 0;

error_te_request:
	mutex_destroy(&ctrl_pdata->spi_tx_mutex);
	mutex_destroy(&ctrl_pdata->te_mutex);
error_pan_node:
	of_node_put(spi_pan_node);
error_vreg:
Loading