diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index b002c0e9f990..b2af75e510ee 100644 --- a/msm/dsi/dsi_display.c +++ b/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", diff --git a/msm/dsi/dsi_display.h b/msm/dsi/dsi_display.h index 4c41f3dd7316..21762c891c86 100644 --- a/msm/dsi/dsi_display.h +++ b/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; diff --git a/msm/dsi/dsi_panel.c b/msm/dsi/dsi_panel.c index 1085801d56dd..3e872e04f113 100644 --- a/msm/dsi/dsi_panel.c +++ b/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: diff --git a/msm/dsi/dsi_panel.h b/msm/dsi/dsi_panel.h index 4b10e457a224..946bbf0bcb89 100644 --- a/msm/dsi/dsi_panel.h +++ b/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; diff --git a/msm/msm_drv.h b/msm/msm_drv.h index d8fb43e25b31..59c72000b2af 100644 --- a/msm/msm_drv.h +++ b/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; diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index b72fa2f08ddf..48a05273e3ee 100644 --- a/msm/sde/sde_encoder.c +++ b/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; diff --git a/msm/sde/sde_encoder_phys.h b/msm/sde/sde_encoder_phys.h index 698aab7b1d66..8a4eff00deb6 100644 --- a/msm/sde/sde_encoder_phys.h +++ b/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; diff --git a/msm/sde/sde_encoder_phys_vid.c b/msm/sde/sde_encoder_phys_vid.c index fb3ee711eb25..a9dbc173868a 100644 --- a/msm/sde/sde_encoder_phys_vid.c +++ b/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; diff --git a/msm/sde/sde_hw_catalog.c b/msm/sde/sde_hw_catalog.c index b4f27d64c2a2..fc608cf79628 100644 --- a/msm/sde/sde_hw_catalog.c +++ b/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: diff --git a/msm/sde/sde_hw_catalog.h b/msm/sde/sde_hw_catalog.h index 4cdf2be96d35..9964ccabb9f5 100644 --- a/msm/sde/sde_hw_catalog.h +++ b/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 }; diff --git a/msm/sde/sde_hw_intf.c b/msm/sde/sde_hw_intf.c index 8024aadc0b48..7f6c9afdb40e 100644 --- a/msm/sde/sde_hw_intf.c +++ b/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); diff --git a/msm/sde/sde_hw_intf.h b/msm/sde/sde_hw_intf.h index 790147103f9d..c7e32d44e2d0 100644 --- a/msm/sde/sde_hw_intf.h +++ b/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 {