Ver código fonte

Merge "disp: msm: sde: align timing engine vsync based on panel vsync"

qctecmdr 5 anos atrás
pai
commit
5d2e2f435f

+ 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->qsync_min_fps =
 		display->panel->qsync_min_fps;
+	info->poms_align_vsync = display->panel->poms_align_vsync;
 
 	switch (display->panel->panel_mode) {
 	case DSI_OP_VIDEO_MODE:
@@ -7357,6 +7358,25 @@ int dsi_display_pre_disable(struct dsi_display *display)
 	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 rc = 0;
@@ -7369,6 +7389,11 @@ int dsi_display_disable(struct dsi_display *display)
 	SDE_EVT32(SDE_EVTLOG_FUNC_ENTRY);
 	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);
 	if (rc)
 		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",
 			       display->name, rc);
 	} 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);
 		if (rc)
 			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 */
 /*
- * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
  */
 
 #ifndef _DSI_DISPLAY_H_
@@ -180,6 +180,7 @@ struct dsi_display_ext_bridge {
  * @misr_enable       Frame MISR enable/disable
  * @misr_frame_count  Number of frames to accumulate the MISR value
  * @esd_trigger       field indicating ESD trigger through debugfs
+ * @poms_te_work      POMS delayed work for disabling panel TE
  * @te_source         vsync source pin information
  * @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.
@@ -261,6 +262,9 @@ struct dsi_display {
 	struct work_struct fifo_overflow_work;
 	struct work_struct lp_rx_timeout_work;
 
+	/* panel te delayed work */
+	struct delayed_work poms_te_work;
+
 	/* firmware panel data */
 	const struct firmware *fw;
 	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_switch_enabled = panel_mode_switch_enabled;
 error:

+ 1 - 0
msm/dsi/dsi_panel.h

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

+ 2 - 0
msm/msm_drv.h

@@ -679,6 +679,7 @@ struct msm_resource_caps_info {
  * @display_type:       Enum for type of display
  * @is_te_using_watchdog_timer:  Boolean to indicate watchdog TE is
  *				 used instead of panel TE in cmd mode panels
+ * @poms_align_vsync:   poms with vsync aligned
  * @roi_caps:           Region of interest capability info
  * @qsync_min_fps	Minimum fps supported by Qsync feature
  * @te_source		vsync source pin information
@@ -701,6 +702,7 @@ struct msm_display_info {
 
 	uint32_t display_type;
 	bool is_te_using_watchdog_timer;
+	bool poms_align_vsync;
 	struct msm_roi_caps roi_caps;
 
 	uint32_t qsync_min_fps;

+ 1 - 0
msm/sde/sde_encoder.c

@@ -2582,6 +2582,7 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
 		phys->comp_ratio = comp_info->comp_ratio;
 		phys->wide_bus_en = sde_enc->mode_info.wide_bus_en;
 		phys->frame_trigger_mode = sde_enc->frame_trigger_mode;
+		phys->poms_align_vsync = disp_info->poms_align_vsync;
 		if (phys->comp_type == MSM_DISPLAY_COMPRESSION_DSC) {
 			phys->dsc_extra_pclk_cycle_cnt =
 				comp_info->dsc_info.pclk_per_line;

+ 2 - 0
msm/sde/sde_encoder_phys.h

@@ -271,6 +271,7 @@ struct sde_encoder_irq {
  * @dsc_extra_pclk_cycle_cnt: Extra pclk cycle count for DSC over DP
  * @dsc_extra_disp_width: Additional display width for DSC over DP
  * @wide_bus_en:	Wide-bus configuraiton
+ * @poms_align_vsync:   poms with vsync aligned
  * @enc_spinlock:	Virtual-Encoder-Wide Spin Lock for IRQ purposes
  * @enable_state:	Enable state tracking
  * @vblank_refcount:	Reference count of vblank request
@@ -317,6 +318,7 @@ struct sde_encoder_phys {
 	u32 dsc_extra_pclk_cycle_cnt;
 	u32 dsc_extra_disp_width;
 	bool wide_bus_en;
+	bool poms_align_vsync;
 	spinlock_t *enc_spinlock;
 	enum sde_enc_enable_state enable_state;
 	struct mutex *vblank_ctl_lock;

+ 1 - 0
msm/sde/sde_encoder_phys_vid.c

@@ -88,6 +88,7 @@ static void drm_mode_to_intf_timing_params(
 					vid_enc->base.comp_ratio);
 	}
 
+	timing->poms_align_vsync = phys_enc->poms_align_vsync;
 	timing->height = mode->vdisplay;	/* active height */
 	timing->xres = timing->width;
 	timing->yres = timing->height;

+ 4 - 0
msm/sde/sde_hw_catalog.c

@@ -2150,6 +2150,10 @@ static int sde_intf_parse_dt(struct device_node *np,
 
 			set_bit(SDE_INTF_TE, &intf->features);
 		}
+
+		if (SDE_HW_MAJOR(sde_cfg->hwversion) >=
+				SDE_HW_MAJOR(SDE_HW_VER_700))
+			set_bit(SDE_INTF_TE_ALIGN_VSYNC, &intf->features);
 	}
 
 end:

+ 2 - 0
msm/sde/sde_hw_catalog.h

@@ -449,11 +449,13 @@ enum {
  * @SDE_INTF_INPUT_CTRL         Supports the setting of pp block from which
  *                              pixel data arrives to this INTF
  * @SDE_INTF_TE                 INTF block has TE configuration support
+ * @SDE_INTF_TE_ALIGN_VSYNC     INTF block has POMS Align vsync support
  * @SDE_INTF_MAX
  */
 enum {
 	SDE_INTF_INPUT_CTRL = 0x1,
 	SDE_INTF_TE,
+	SDE_INTF_TE_ALIGN_VSYNC,
 	SDE_INTF_MAX
 };
 

+ 5 - 0
msm/sde/sde_hw_intf.c

@@ -309,6 +309,11 @@ static void sde_hw_intf_setup_timing_engine(struct sde_hw_intf *ctx,
 	if (p->wide_bus_en)
 		intf_cfg2 |= BIT(0);
 
+	/* Synchronize timing engine enable to TE */
+	if ((ctx->cap->features & BIT(SDE_INTF_TE_ALIGN_VSYNC))
+			&& p->poms_align_vsync)
+		intf_cfg2 |= BIT(16);
+
 	if (ctx->cfg.split_link_en)
 		SDE_REG_WRITE(c, INTF_REG_SPLIT_LINK, 0x3);
 

+ 1 - 0
msm/sde/sde_hw_intf.h

@@ -37,6 +37,7 @@ struct intf_timing_params {
 	bool compression_en;
 	u32 extra_dto_cycles;	/* for DP only */
 	bool dsc_4hs_merge;	/* DSC 4HS merge */
+	bool poms_align_vsync;	/* poms with vsync aligned */
 };
 
 struct intf_prog_fetch {