瀏覽代碼

disp: msm: defer panel TE disable with poms switch

DSI host vsync is expected to align with panel internal vsync
during transition from command mode to video mode operation.
In order to facilitate this, keep panel TE enabled in video mode
operation until it is aligned with vysnc.

Change-Id: I3fc59b01336b30cd436be332af6953c5a01be7fd
Signed-off-by: Narendra Muppalla <[email protected]>
Narendra Muppalla 5 年之前
父節點
當前提交
cd1e996b44
共有 4 個文件被更改,包括 45 次插入1 次删除
  1. 37 0
      msm/dsi/dsi_display.c
  2. 5 1
      msm/dsi/dsi_display.h
  3. 2 0
      msm/dsi/dsi_panel.c
  4. 1 0
      msm/dsi/dsi_panel.h

+ 37 - 0
msm/dsi/dsi_display.c

@@ -5819,6 +5819,7 @@ int dsi_display_get_info(struct drm_connector *connector,
 	info->max_height = 1080;
 	info->max_height = 1080;
 	info->qsync_min_fps =
 	info->qsync_min_fps =
 		display->panel->qsync_min_fps;
 		display->panel->qsync_min_fps;
+	info->poms_align_vsync = display->panel->poms_align_vsync;
 
 
 	switch (display->panel->panel_mode) {
 	switch (display->panel->panel_mode) {
 	case DSI_OP_VIDEO_MODE:
 	case DSI_OP_VIDEO_MODE:
@@ -7357,6 +7358,25 @@ int dsi_display_pre_disable(struct dsi_display *display)
 	return rc;
 	return rc;
 }
 }
 
 
+static void dsi_display_handle_poms_te(struct work_struct *work)
+{
+	struct dsi_display *display = NULL;
+	struct delayed_work *dw = to_delayed_work(work);
+	struct mipi_dsi_device *dsi;
+	int rc = 0;
+
+	display = container_of(dw, struct dsi_display, poms_te_work);
+	if (!display || !display->panel) {
+		DSI_ERR("Invalid params\n");
+		return;
+	}
+
+	dsi = &display->panel->mipi_device;
+	rc = mipi_dsi_dcs_set_tear_off(dsi);
+	if (rc < 0)
+		DSI_ERR("failed to set tear off\n");
+}
+
 int dsi_display_disable(struct dsi_display *display)
 int dsi_display_disable(struct dsi_display *display)
 {
 {
 	int rc = 0;
 	int rc = 0;
@@ -7369,6 +7389,11 @@ int dsi_display_disable(struct dsi_display *display)
 	SDE_EVT32(SDE_EVTLOG_FUNC_ENTRY);
 	SDE_EVT32(SDE_EVTLOG_FUNC_ENTRY);
 	mutex_lock(&display->display_lock);
 	mutex_lock(&display->display_lock);
 
 
+	/* cancel delayed work */
+	if (display->poms_pending &&
+			display->panel->poms_align_vsync)
+		cancel_delayed_work_sync(&display->poms_te_work);
+
 	rc = dsi_display_wake_up(display);
 	rc = dsi_display_wake_up(display);
 	if (rc)
 	if (rc)
 		DSI_ERR("[%s] display wake up failed, rc=%d\n",
 		DSI_ERR("[%s] display wake up failed, rc=%d\n",
@@ -7380,6 +7405,18 @@ int dsi_display_disable(struct dsi_display *display)
 			DSI_ERR("[%s]failed to disable DSI vid engine, rc=%d\n",
 			DSI_ERR("[%s]failed to disable DSI vid engine, rc=%d\n",
 			       display->name, rc);
 			       display->name, rc);
 	} else if (display->config.panel_mode == DSI_OP_CMD_MODE) {
 	} else if (display->config.panel_mode == DSI_OP_CMD_MODE) {
+		/**
+		 * On POMS request , disable panel TE through
+		 * delayed work queue.
+		 */
+		if (display->poms_pending &&
+				display->panel->poms_align_vsync) {
+			INIT_DELAYED_WORK(&display->poms_te_work,
+					dsi_display_handle_poms_te);
+			queue_delayed_work(system_wq,
+					&display->poms_te_work,
+					msecs_to_jiffies(100));
+		}
 		rc = dsi_display_cmd_engine_disable(display);
 		rc = dsi_display_cmd_engine_disable(display);
 		if (rc)
 		if (rc)
 			DSI_ERR("[%s]failed to disable DSI cmd engine, rc=%d\n",
 			DSI_ERR("[%s]failed to disable DSI cmd engine, rc=%d\n",

+ 5 - 1
msm/dsi/dsi_display.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
 /*
- * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
  */
  */
 
 
 #ifndef _DSI_DISPLAY_H_
 #ifndef _DSI_DISPLAY_H_
@@ -180,6 +180,7 @@ struct dsi_display_ext_bridge {
  * @misr_enable       Frame MISR enable/disable
  * @misr_enable       Frame MISR enable/disable
  * @misr_frame_count  Number of frames to accumulate the MISR value
  * @misr_frame_count  Number of frames to accumulate the MISR value
  * @esd_trigger       field indicating ESD trigger through debugfs
  * @esd_trigger       field indicating ESD trigger through debugfs
+ * @poms_te_work      POMS delayed work for disabling panel TE
  * @te_source         vsync source pin information
  * @te_source         vsync source pin information
  * @clk_gating_config Clocks for which clock gating needs to be enabled
  * @clk_gating_config Clocks for which clock gating needs to be enabled
  * @queue_cmd_waits   Indicates if wait for dma commands done has to be queued.
  * @queue_cmd_waits   Indicates if wait for dma commands done has to be queued.
@@ -261,6 +262,9 @@ struct dsi_display {
 	struct work_struct fifo_overflow_work;
 	struct work_struct fifo_overflow_work;
 	struct work_struct lp_rx_timeout_work;
 	struct work_struct lp_rx_timeout_work;
 
 
+	/* panel te delayed work */
+	struct delayed_work poms_te_work;
+
 	/* firmware panel data */
 	/* firmware panel data */
 	const struct firmware *fw;
 	const struct firmware *fw;
 	void *parser;
 	void *parser;

+ 2 - 0
msm/dsi/dsi_panel.c

@@ -1479,6 +1479,8 @@ static int dsi_panel_parse_panel_mode(struct dsi_panel *panel)
 		}
 		}
 	}
 	}
 
 
+	panel->poms_align_vsync = utils->read_bool(utils->data,
+					"qcom,poms-align-panel-vsync");
 	panel->panel_mode = panel_mode;
 	panel->panel_mode = panel_mode;
 	panel->panel_mode_switch_enabled = panel_mode_switch_enabled;
 	panel->panel_mode_switch_enabled = panel_mode_switch_enabled;
 error:
 error:

+ 1 - 0
msm/dsi/dsi_panel.h

@@ -171,6 +171,7 @@ struct dsi_panel {
 	struct dsi_cmd_engine_cfg cmd_config;
 	struct dsi_cmd_engine_cfg cmd_config;
 	enum dsi_op_mode panel_mode;
 	enum dsi_op_mode panel_mode;
 	bool panel_mode_switch_enabled;
 	bool panel_mode_switch_enabled;
+	bool poms_align_vsync;
 
 
 	struct dsi_dfps_capabilities dfps_caps;
 	struct dsi_dfps_capabilities dfps_caps;
 	struct dsi_dyn_clk_caps dyn_clk_caps;
 	struct dsi_dyn_clk_caps dyn_clk_caps;