From f55d5421662ee6c2f32ec975e9c2bf6981689c41 Mon Sep 17 00:00:00 2001 From: hujing3 Date: Mon, 7 Dec 2020 15:35:25 +0800 Subject: [PATCH] kernel:dsi: ESD te support for video mode panel Add ESD TE check on video mode panel to fix TP noise issue when configed as read_reg ESD Change-Id: Idf6ce40fd4275a03f169f8c3bca48e56303b1c77 Signed-off-by: hujing3 Reviewed-on: https://gerrit.mot.com/1820691 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- msm/dsi/dsi_display.c | 98 +++++++++++++++++++++++++++++++++++++++++ msm/dsi/dsi_panel.c | 10 +++++ msm/dsi/dsi_panel.h | 8 ++++ msm/sde/sde_connector.c | 4 ++ 4 files changed, 120 insertions(+) diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index 194510fdd18e..bb61e950f30d 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -837,6 +837,21 @@ static int dsi_display_status_check_te(struct dsi_display *display) return rc; } +static int dsi_display_status_check_te_video(struct dsi_display *display) +{ + int rc = 1; + struct dsi_panel *panel = display->panel; + + if((panel->video_te_count - panel->video_te_count_priv) > 1) { + panel->video_te_count_priv = panel->video_te_count; + } else { + DSI_ERR("%s: video TE check ERROR te_count %d, priv =%d\n", __func__, panel->video_te_count, panel->video_te_count_priv); + rc = 0; + } + + return rc; +} + int dsi_display_check_status(struct drm_connector *connector, void *display, bool te_check_override) { @@ -895,6 +910,8 @@ int dsi_display_check_status(struct drm_connector *connector, void *display, rc = dsi_display_status_reg_read(dsi_display); } else if (status_mode == ESD_MODE_SW_BTA) { rc = dsi_display_status_bta_request(dsi_display); + } else if (status_mode == ESD_MODE_PANEL_TE_VIDEO) { + rc = dsi_display_status_check_te_video(dsi_display); } else if (status_mode == ESD_MODE_PANEL_TE) { rc = dsi_display_status_check_te(dsi_display); } else { @@ -4055,6 +4072,76 @@ error: return rc; } +static void dsi_video_te_irq_work(struct work_struct *work) +{ + struct dsi_panel *panel = NULL; + struct delayed_work *dw = to_delayed_work(work); + + panel = container_of(dw, struct dsi_panel, te_event_work); + if (!panel) { + DSI_ERR("%s: invalid panel data\n", __func__); + return; + } + + if(panel->video_te_count%60 == 0) + DSI_INFO("%s video te count = %d\n", __func__, panel->video_te_count); + + enable_irq(panel->video_te_irq); +} + +extern u32 interval_video_te; +static irqreturn_t dsi_video_te_interrupt(int irq, void *data) +{ + struct dsi_panel *panel = data; + + disable_irq_nosync(irq); + + if(panel->video_te_count++ < 3000) { + enable_irq(irq); + } else { + queue_delayed_work(panel->workq, &panel->te_event_work, msecs_to_jiffies(interval_video_te/3)); + //DSI_DEBUG("%s video_te_count=%d\n", __func__, panel->video_te_count); + } + + return IRQ_HANDLED; +} + +static int dsi_init_video_te_irq(struct dsi_panel *panel) +{ + int rc = -1; + + if (gpio_is_valid(panel->video_te_gpio)) { + rc = gpio_request(panel->video_te_gpio, "video-te-gpio"); + if (rc < 0) { + DSI_ERR("%s: video te gpio_request fail rc=%d\n", __func__,rc); + return rc ; + } + + rc = gpio_direction_input(panel->video_te_gpio); + if (rc < 0) { + DSI_ERR("%s: video te gpio_direction_input fail rc=%d\n", __func__ ,rc); + return rc ; + } + + panel->video_te_count_priv = 0; + panel->video_te_count = 3; + panel->video_te_irq = gpio_to_irq(panel->video_te_gpio); + DSI_INFO("%s: irq = %d, gpio=%d\n", __func__, panel->video_te_irq, panel->video_te_gpio); + + rc = request_threaded_irq(panel->video_te_irq, dsi_video_te_interrupt, NULL, + IRQF_TRIGGER_RISING|IRQF_ONESHOT, "video-te-irq", panel); + if (rc < 0) { + DSI_ERR("%s: video te request_irq fail rc=%d\n",__func__, rc); + return rc ; + } + } else { + DSI_ERR("%s: video te irq gpio not provided\n", __func__); + return rc ; + } + + return 0; +} + static int dsi_display_res_init(struct dsi_display *display) { int rc = 0; @@ -4117,6 +4204,17 @@ static int dsi_display_res_init(struct dsi_display *display) goto error_ctrl_put; } + if(display->panel->esd_config.status_mode == ESD_MODE_PANEL_TE_VIDEO) { + display->panel->workq = create_workqueue("mdss_dsi_video_te"); + if (!(display->panel->workq)) { + DSI_ERR("%s: Error creating video te workqueue\n", __func__); + goto error_ctrl_put; + } + + INIT_DELAYED_WORK(&(display->panel->te_event_work), dsi_video_te_irq_work); + dsi_init_video_te_irq(display->panel); + } + return 0; error_ctrl_put: for (i = i - 1; i >= 0; i--) { diff --git a/msm/dsi/dsi_panel.c b/msm/dsi/dsi_panel.c index 407d2f6ec4e9..ad0ed0f227e5 100755 --- a/msm/dsi/dsi_panel.c +++ b/msm/dsi/dsi_panel.c @@ -2761,6 +2761,12 @@ static int dsi_panel_parse_gpios(struct dsi_panel *panel) panel->reset_config.tp_rst_gpio = utils->get_named_gpio(utils->data, "qcom,mdss-dsi-tp-rst-gpio", 0); + panel->video_te_gpio = utils->get_named_gpio(utils->data, + "qcom,video-te-gpio", 0); + if (panel->video_te_gpio && gpio_is_valid(panel->video_te_gpio)) { + DSI_INFO("%s:%d, Video TE gpio is specified\n", __func__, __LINE__); + } + panel->reset_config.disp_en_gpio = utils->get_named_gpio(utils->data, "qcom,5v-boost-gpio", 0); @@ -3829,6 +3835,8 @@ static int dsi_panel_parse_esd_config(struct dsi_panel *panel) esd_config->status_mode = ESD_MODE_SW_BTA; } else if (!strcmp(string, "reg_read")) { esd_config->status_mode = ESD_MODE_REG_READ; + } else if (!strcmp(string, "te_signal_check_video")) { + esd_config->status_mode = ESD_MODE_PANEL_TE_VIDEO; } else if (!strcmp(string, "te_signal_check")) { if (panel->panel_mode == DSI_OP_CMD_MODE) { esd_config->status_mode = ESD_MODE_PANEL_TE; @@ -3858,6 +3866,8 @@ static int dsi_panel_parse_esd_config(struct dsi_panel *panel) esd_mode = "register_read"; } else if (panel->esd_config.status_mode == ESD_MODE_SW_BTA) { esd_mode = "bta_trigger"; + } else if (panel->esd_config.status_mode == ESD_MODE_PANEL_TE_VIDEO) { + esd_mode = "te_check_video"; } else if (panel->esd_config.status_mode == ESD_MODE_PANEL_TE) { esd_mode = "te_check"; } diff --git a/msm/dsi/dsi_panel.h b/msm/dsi/dsi_panel.h index 081443d3e61f..abec34230f6b 100644 --- a/msm/dsi/dsi_panel.h +++ b/msm/dsi/dsi_panel.h @@ -196,6 +196,7 @@ enum esd_check_status_mode { ESD_MODE_REG_READ, ESD_MODE_SW_BTA, ESD_MODE_PANEL_TE, + ESD_MODE_PANEL_TE_VIDEO, ESD_MODE_SW_SIM_SUCCESS, ESD_MODE_SW_SIM_FAILURE, ESD_MODE_MAX @@ -291,6 +292,13 @@ struct dsi_panel { struct drm_panel_hdr_properties hdr_props; struct drm_panel_esd_config esd_config; + struct workqueue_struct *workq; + struct delayed_work te_event_work; + int video_te_gpio; + u32 video_te_count; + u32 video_te_count_priv; + int video_te_irq; + struct dsi_parser_utils utils; bool lp11_init; diff --git a/msm/sde/sde_connector.c b/msm/sde/sde_connector.c index ee47ecab9170..6f7229831b46 100644 --- a/msm/sde/sde_connector.c +++ b/msm/sde/sde_connector.c @@ -2293,6 +2293,7 @@ int sde_connector_esd_status(struct drm_connector *conn) return ret; } +u32 interval_video_te = STATUS_CHECK_INTERVAL_MS; static void sde_connector_check_status_work(struct work_struct *work) { struct sde_connector *conn; @@ -2328,6 +2329,9 @@ static void sde_connector_check_status_work(struct work_struct *work) /* If debugfs property is not set then take default value */ interval = conn->esd_status_interval ? conn->esd_status_interval : STATUS_CHECK_INTERVAL_MS; + + interval_video_te = interval; + schedule_delayed_work(&conn->status_work, msecs_to_jiffies(interval)); return;