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

Commit 8fec101d authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: mdss: add support for ESD status thread based on TE signal"

parents 986c540b 06a99d7c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -344,6 +344,7 @@ Optional properties:
- qcom,mdss-dsi-panel-status-check-mode:Specifies the panel status check method for ESD recovery.
					"bta_check" = Uses BTA to check the panel status
					"reg_read" = Reads panel status register to check the panel status
					"te_signal_check" = Uses TE signal behaviour to check the panel status
- qcom,mdss-dsi-panel-status-value:	Specifies the value of the panel status register when the panel is
					in good state.
- qcom,dynamic-mode-switch-enabled:		Boolean used to mention whether panel supports
+69 −12
Original line number Diff line number Diff line
@@ -18,6 +18,64 @@
#include "mdss_dsi.h"
#include "mdss_mdp.h"

/*
 * mdss_report_panel_dead() - Sends the PANEL_ALIVE=0 status to HAL layer.
 * @pstatus_data   : dsi status data
 *
 * This function is called if the panel fails to respond as expected to
 * the register read/BTA or if the TE signal is not coming as expected
 * from the panel. The function sends the PANEL_ALIVE=0 status to HAL
 * layer.
 */
static void mdss_report_panel_dead(struct dsi_status_data *pstatus_data)
{
	char *envp[2] = {"PANEL_ALIVE=0", NULL};
	struct mdss_panel_data *pdata =
		dev_get_platdata(&pstatus_data->mfd->pdev->dev);
	if (!pdata) {
		pr_err("%s: Panel data not available\n", __func__);
		return;
	}

	pdata->panel_info.panel_dead = true;
	kobject_uevent_env(&pstatus_data->mfd->fbi->dev->kobj,
		KOBJ_CHANGE, envp);
	pr_err("%s: Panel has gone bad, sending uevent - %s\n",
		__func__, envp[0]);
	return;
}

/*
 * mdss_check_te_status() - Check the status of panel for TE based ESD.
 * @ctrl_pdata   : dsi controller data
 * @pstatus_data : dsi status data
 * @interval     : duration in milliseconds to schedule work queue
 *
 * This function is called when the TE signal from the panel doesn't arrive
 * after 'interval' milliseconds. If the TE IRQ is not ready, the workqueue
 * gets re-scheduled. Otherwise, report the panel to be dead due to ESD attack.
 */
static void mdss_check_te_status(struct mdss_dsi_ctrl_pdata *ctrl_pdata,
		struct dsi_status_data *pstatus_data, uint32_t interval)
{
	/*
	 * During resume, the panel status will be ON but due to race condition
	 * between ESD thread and display UNBLANK (or rather can be put as
	 * asynchronuous nature between these two threads), the ESD thread might
	 * reach this point before the TE IRQ line is enabled or before the
	 * first TE interrupt arrives after the TE IRQ line is enabled. For such
	 * cases, re-schedule the ESD thread.
	 */
	if (!atomic_read(&ctrl_pdata->te_irq_ready)) {
		schedule_delayed_work(&pstatus_data->check_status,
			msecs_to_jiffies(interval));
		pr_debug("%s: TE IRQ line not enabled yet\n", __func__);
		return;
	}

	mdss_report_panel_dead(pstatus_data);
}

/*
 * mdss_check_dsi_ctrl_status() - Check MDP5 DSI controller status periodically.
 * @work     : dsi controller status data
@@ -53,7 +111,8 @@ void mdss_check_dsi_ctrl_status(struct work_struct *work, uint32_t interval)

	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
							panel_data);
	if (!ctrl_pdata || !ctrl_pdata->check_status) {
	if (!ctrl_pdata || (!ctrl_pdata->check_status &&
		(ctrl_pdata->status_mode != ESD_TE))) {
		pr_err("%s: DSI ctrl or status_check callback not available\n",
								__func__);
		return;
@@ -70,7 +129,12 @@ void mdss_check_dsi_ctrl_status(struct work_struct *work, uint32_t interval)
	if (ctl->power_state == MDSS_PANEL_POWER_OFF) {
		schedule_delayed_work(&pstatus_data->check_status,
			msecs_to_jiffies(interval));
		pr_err("%s: ctl not powered on\n", __func__);
		pr_debug("%s: ctl not powered on\n", __func__);
		return;
	}

	if (ctrl_pdata->status_mode == ESD_TE) {
		mdss_check_te_status(ctrl_pdata, pstatus_data, interval);
		return;
	}

@@ -119,17 +183,10 @@ void mdss_check_dsi_ctrl_status(struct work_struct *work, uint32_t interval)
	mutex_unlock(&ctrl_pdata->mutex);

	if ((pstatus_data->mfd->panel_power_state == MDSS_PANEL_POWER_ON)) {
		if (ret > 0) {
		if (ret > 0)
			schedule_delayed_work(&pstatus_data->check_status,
				msecs_to_jiffies(interval));
		} else {
			char *envp[2] = {"PANEL_ALIVE=0", NULL};
			pdata->panel_info.panel_dead = true;
			ret = kobject_uevent_env(
				&pstatus_data->mfd->fbi->dev->kobj,
							KOBJ_CHANGE, envp);
			pr_err("%s: Panel has gone bad, sending uevent - %s\n",
							__func__, envp[0]);
		}
		else
			mdss_report_panel_dead(pstatus_data);
	}
}
+30 −2
Original line number Diff line number Diff line
@@ -706,8 +706,11 @@ static int mdss_dsi_unblank(struct mdss_panel_data *pdata)
	}

	if ((pdata->panel_info.type == MIPI_CMD_PANEL) &&
		mipi->vsync_enable && mipi->hw_vsync_mode)
		mipi->vsync_enable && mipi->hw_vsync_mode) {
		mdss_dsi_set_tear_on(ctrl_pdata);
		if (mdss_dsi_is_te_based_esd(ctrl_pdata))
			enable_irq(gpio_to_irq(ctrl_pdata->disp_te_gpio));
	}

error:
	mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0);
@@ -763,8 +766,14 @@ static int mdss_dsi_blank(struct mdss_panel_data *pdata, int power_state)
	}

	if ((pdata->panel_info.type == MIPI_CMD_PANEL) &&
		mipi->vsync_enable && mipi->hw_vsync_mode)
		mipi->vsync_enable && mipi->hw_vsync_mode) {
		if (mdss_dsi_is_te_based_esd(ctrl_pdata)) {
				disable_irq(gpio_to_irq(
					ctrl_pdata->disp_te_gpio));
				atomic_dec(&ctrl_pdata->te_irq_ready);
		}
		mdss_dsi_set_tear_off(ctrl_pdata);
	}

	if (ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT) {
		if (!pdata->panel_info.dynamic_switch_pending) {
@@ -1407,6 +1416,7 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev)
		platform_set_drvdata(pdev, ctrl_pdata);
	}
	ctrl_pdata->mdss_util = util;
	atomic_set(&ctrl_pdata->te_irq_ready, 0);

	ctrl_name = of_get_property(pdev->dev.of_node, "label", NULL);
	if (!ctrl_name)
@@ -1490,6 +1500,17 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev)
		goto error_pan_node;
	}

	if (mdss_dsi_is_te_based_esd(ctrl_pdata)) {
		rc = devm_request_irq(&pdev->dev,
			gpio_to_irq(ctrl_pdata->disp_te_gpio),
			hw_vsync_handler, IRQF_TRIGGER_FALLING,
			"VSYNC_GPIO", ctrl_pdata);
		if (rc) {
			pr_err("TE request_irq failed.\n");
			goto error_pan_node;
		}
		disable_irq(gpio_to_irq(ctrl_pdata->disp_te_gpio));
	}
	pr_debug("%s: Dsi Ctrl->%d initialized\n", __func__, index);
	return 0;

@@ -1752,6 +1773,13 @@ int dsi_panel_device_register(struct device_node *pan_node,
					__func__, __LINE__);
	}

	ctrl_pdata->disp_te_gpio = of_get_named_gpio(ctrl_pdev->dev.of_node,
		"qcom,platform-te-gpio", 0);

	if (!gpio_is_valid(ctrl_pdata->disp_te_gpio))
		pr_err("%s:%d, TE gpio not specified\n",
						__func__, __LINE__);

	ctrl_pdata->bklt_en_gpio = of_get_named_gpio(ctrl_pdev->dev.of_node,
		"qcom,platform-bklight-en-gpio", 0);
	if (!gpio_is_valid(ctrl_pdata->bklt_en_gpio))
+12 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <linux/mdss_io_util.h>
#include <linux/irqreturn.h>
#include <linux/pinctrl/consumer.h>
#include <linux/gpio.h>

#include "mdss_panel.h"
#include "mdss_dsi_cmd.h"
@@ -96,6 +97,7 @@ enum dsi_panel_status_mode {
	ESD_BTA,
	ESD_REG,
	ESD_REG_NT35596,
	ESD_TE,
	ESD_MAX,
};

@@ -315,6 +317,7 @@ struct mdss_dsi_ctrl_pdata {
	u8 ctrl_state;
	int panel_mode;
	int irq_cnt;
	int disp_te_gpio;
	int rst_gpio;
	int disp_en_gpio;
	int bklt_en_gpio;
@@ -329,6 +332,7 @@ struct mdss_dsi_ctrl_pdata {
	int pwm_enabled;
	bool panel_bias_vreg;
	bool dsi_irq_line;
	atomic_t te_irq_ready;

	bool cmd_sync_wait_broadcast;
	bool cmd_sync_wait_trigger;
@@ -420,6 +424,7 @@ void mdss_dsi_controller_cfg(int enable,
void mdss_dsi_sw_reset(struct mdss_dsi_ctrl_pdata *ctrl_pdata, bool restore);

irqreturn_t mdss_dsi_isr(int irq, void *ptr);
irqreturn_t hw_vsync_handler(int irq, void *data);
void mdss_dsi_irq_handler_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata);

void mdss_dsi_set_tx_power_mode(int mode, struct mdss_panel_data *pdata);
@@ -539,6 +544,13 @@ static inline bool mdss_dsi_is_ctrl_clk_slave(struct mdss_dsi_ctrl_pdata *ctrl)
		(ctrl->ndx == DSI_CTRL_CLK_SLAVE);
}

static inline bool mdss_dsi_is_te_based_esd(struct mdss_dsi_ctrl_pdata *ctrl)
{
	return (ctrl->status_mode == ESD_TE) &&
		gpio_is_valid(ctrl->disp_te_gpio) &&
		mdss_dsi_is_left_ctrl(ctrl);
}

static inline struct mdss_dsi_ctrl_pdata *mdss_dsi_get_ctrl_clk_master(void)
{
	return ctrl_list[DSI_CTRL_CLK_MASTER];
+5 −0
Original line number Diff line number Diff line
@@ -1595,6 +1595,11 @@ static int mdss_panel_parse_dt(struct device_node *np,
			ctrl_pdata->status_cmds_rlen = 8;
			ctrl_pdata->check_read_status =
						mdss_dsi_nt35596_read_status;
		} else if (!strcmp(data, "te_signal_check")) {
			if (pinfo->mipi.mode == DSI_CMD_MODE)
				ctrl_pdata->status_mode = ESD_TE;
			else
				pr_err("TE-ESD not valid for video mode\n");
		}
	}

Loading