Loading drivers/video/msm/mdss/mdss.h +1 −0 Original line number Diff line number Diff line Loading @@ -240,6 +240,7 @@ struct mdss_data_type { bool traffic_shaper_en; int iommu_ref_cnt; u32 latency_buff_per; atomic_t active_intf_cnt; u64 ab[MDSS_MAX_HW_BLK]; u64 ib[MDSS_MAX_HW_BLK]; Loading drivers/video/msm/mdss/mdss_mdp.c +69 −43 Original line number Diff line number Diff line Loading @@ -87,6 +87,7 @@ static DEFINE_SPINLOCK(mdp_lock); static DEFINE_MUTEX(mdp_clk_lock); static DEFINE_MUTEX(bus_bw_lock); static DEFINE_MUTEX(mdp_iommu_lock); static DEFINE_MUTEX(mdp_fs_idle_pc_lock); static struct mdss_panel_intf pan_types[] = { {"dsi", MDSS_PANEL_INTF_DSI}, Loading Loading @@ -774,6 +775,41 @@ int mdss_iommu_ctrl(int enable) return mdata->iommu_ref_cnt; } /** * mdss_mdp_idle_pc_restore() - Restore MDSS settings when exiting idle pc * * MDSS GDSC can be voted off during idle-screen usecase for MIPI DSI command * mode displays, referred to as MDSS idle power collapse. Upon subsequent * frame update, MDSS GDSC needs to turned back on and hw state needs to be * restored. */ static int mdss_mdp_idle_pc_restore(void) { struct mdss_data_type *mdata = mdss_mdp_get_mdata(); int rc = 0; mutex_lock(&mdp_fs_idle_pc_lock); if (!mdata->idle_pc) { pr_debug("no idle pc, no need to restore\n"); goto end; } pr_debug("called from %pS\n", __builtin_return_address(0)); rc = mdss_iommu_ctrl(1); if (IS_ERR_VALUE(rc)) { pr_err("mdss iommu attach failed rc=%d\n", rc); goto end; } mdss_hw_init(mdata); mdss_iommu_ctrl(0); mdss_mdp_ctl_restore(); mdata->idle_pc = false; end: mutex_unlock(&mdp_fs_idle_pc_lock); return rc; } /** * mdss_bus_bandwidth_ctrl() -- place bus bandwidth request * @enable: value of enable or disable Loading Loading @@ -814,6 +850,7 @@ void mdss_bus_bandwidth_ctrl(int enable) pm_runtime_put(&mdata->pdev->dev); } else { pm_runtime_get_sync(&mdata->pdev->dev); mdss_mdp_idle_pc_restore(); msm_bus_scale_client_update_request( mdata->bus_hdl, mdata->curr_bw_uc_idx); } Loading Loading @@ -849,10 +886,10 @@ void mdss_mdp_clk_ctrl(int enable) __func__, mdp_clk_cnt, changed, enable); if (changed) { mdata->clk_ena = enable; if (enable) pm_runtime_get_sync(&mdata->pdev->dev); mdata->clk_ena = enable; mdss_mdp_clk_update(MDSS_CLK_AHB, enable); mdss_mdp_clk_update(MDSS_CLK_AXI, enable); mdss_mdp_clk_update(MDSS_CLK_MDP_CORE, enable); Loading Loading @@ -1452,6 +1489,7 @@ static int mdss_mdp_probe(struct platform_device *pdev) mdss_res = mdata; mutex_init(&mdata->reg_lock); atomic_set(&mdata->sd_client_count, 0); atomic_set(&mdata->active_intf_cnt, 0); rc = msm_dss_ioremap_byname(pdev, &mdata->mdss_io, "mdp_phys"); if (rc) { Loading Loading @@ -2909,19 +2947,30 @@ vreg_set_voltage_fail: return rc; } /** * mdss_mdp_footswitch_ctrl() - Disable/enable MDSS GDSC and CX/Batfet rails * @mdata: MDP private data * @on: 1 to turn on footswitch, 0 to turn off footswitch * * When no active references to the MDP device node and it's child nodes are * held, MDSS GDSC can be turned off. However, any any panels are still * active (but likely in an idle state), the vote for the CX and the batfet * rails should not be released. */ static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on) { int ret; int active_cnt = 0; if (!mdata->fs) return; if (on) { pr_debug("Enable MDP FS\n"); if (!mdata->fs_ena) { pr_debug("Enable MDP FS\n"); ret = regulator_enable(mdata->fs); if (ret) pr_err("Footswitch failed to enable\n"); pr_warn("Footswitch failed to enable\n"); if (!mdata->idle_pc) { mdss_mdp_cx_ctrl(mdata, true); mdss_mdp_batfet_ctrl(mdata, true); Loading @@ -2929,52 +2978,27 @@ static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on) } mdata->fs_ena = true; } else { pr_debug("Disable MDP FS\n"); if (mdata->fs_ena) { regulator_disable(mdata->fs); if (!mdata->idle_pc) { pr_debug("Disable MDP FS\n"); active_cnt = atomic_read(&mdata->active_intf_cnt); if (active_cnt != 0) { /* * Turning off GDSC while overlays are still * active. */ mdata->idle_pc = true; pr_debug("idle pc. active overlays=%d\n", active_cnt); } else { mdss_mdp_cx_ctrl(mdata, false); mdss_mdp_batfet_ctrl(mdata, false); } regulator_disable(mdata->fs); } mdata->fs_ena = false; } } /** * mdss_mdp_footswitch_ctrl_idle_pc() - MDSS GDSC control with idle power collapse * @on: 1 to turn on footswitch, 0 to turn off footswitch * @dev: framebuffer device node * * MDSS GDSC can be voted off during idle-screen usecase for MIPI DSI command * mode displays. Upon subsequent frame update, MDSS GDSC needs to turned back * on and hw state needs to be restored. It returns error if footswitch control * API fails. */ int mdss_mdp_footswitch_ctrl_idle_pc(int on, struct device *dev) { struct mdss_data_type *mdata = mdss_mdp_get_mdata(); int rc = 0; pr_debug("called on=%d\n", on); if (on) { pm_runtime_get_sync(dev); rc = mdss_iommu_ctrl(1); if (IS_ERR_VALUE(rc)) { pr_err("mdss iommu attach failed rc=%d\n", rc); return rc; } mdss_hw_init(mdata); mdss_iommu_ctrl(0); mdata->idle_pc = false; } else { mdata->idle_pc = true; pm_runtime_put_sync(dev); } return 0; } int mdss_mdp_secure_display_ctrl(unsigned int enable) { struct sd_ctrl_req { Loading Loading @@ -3089,7 +3113,8 @@ static int mdss_mdp_runtime_resume(struct device *dev) if (!mdata) return -ENODEV; dev_dbg(dev, "pm_runtime: resuming...\n"); dev_dbg(dev, "pm_runtime: resuming. active overlay cnt=%d\n", atomic_read(&mdata->active_intf_cnt)); /* do not resume panels when coming out of idle power collapse */ if (!mdata->idle_pc) Loading @@ -3116,17 +3141,18 @@ static int mdss_mdp_runtime_suspend(struct device *dev) bool device_on = false; if (!mdata) return -ENODEV; dev_dbg(dev, "pm_runtime: suspending...\n"); dev_dbg(dev, "pm_runtime: suspending. active overlay cnt=%d\n", atomic_read(&mdata->active_intf_cnt)); if (mdata->clk_ena) { pr_err("MDP suspend failed\n"); return -EBUSY; } mdss_mdp_footswitch_ctrl(mdata, false); /* do not suspend panels when going in to idle power collapse */ if (!mdata->idle_pc) device_for_each_child(dev, &device_on, mdss_fb_suspres_panel); mdss_mdp_footswitch_ctrl(mdata, false); return 0; } Loading drivers/video/msm/mdss/mdss_mdp.h +2 −2 Original line number Diff line number Diff line Loading @@ -230,6 +230,7 @@ struct mdss_mdp_ctl { struct mdss_mdp_vsync_handler *); int (*config_fps_fnc) (struct mdss_mdp_ctl *ctl, struct mdss_mdp_ctl *sctl, int new_fps); int (*restore_fnc) (struct mdss_mdp_ctl *ctl); struct blocking_notifier_head notifier_head; Loading Loading @@ -889,7 +890,6 @@ int mdss_mdp_wb_get_format(struct msm_fb_data_type *mfd, int mdss_mdp_pipe_program_pixel_extn(struct mdss_mdp_pipe *pipe); int mdss_mdp_wb_set_secure(struct msm_fb_data_type *mfd, int enable); int mdss_mdp_wb_get_secure(struct msm_fb_data_type *mfd, uint8_t *enable); void mdss_mdp_ctl_restore(struct mdss_mdp_ctl *ctl); int mdss_mdp_footswitch_ctrl_idle_pc(int on, struct device *dev); void mdss_mdp_ctl_restore(void); int mdss_mdp_ctl_reset(struct mdss_mdp_ctl *ctl); #endif /* MDSS_MDP_H */ drivers/video/msm/mdss/mdss_mdp_ctl.c +22 −9 Original line number Diff line number Diff line Loading @@ -2097,23 +2097,36 @@ static void mdss_mdp_ctl_restore_sub(struct mdss_mdp_ctl *ctl) /* * mdss_mdp_ctl_restore() - restore mdp ctl path * @ctl: mdp controller. * * This function is called whenever MDP comes out of a power collapse as * a result of a screen update when DSI ULPS mode is enabled. It restores * the MDP controller's software state to the hardware registers. * a result of a screen update. It restores the MDP controller's software * state to the hardware registers. */ void mdss_mdp_ctl_restore(struct mdss_mdp_ctl *ctl) void mdss_mdp_ctl_restore(void) { struct mdss_mdp_ctl *ctl = NULL; struct mdss_mdp_ctl *sctl; struct mdss_data_type *mdata = mdss_mdp_get_mdata(); u32 cnum; sctl = mdss_mdp_get_split_ctl(ctl); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); for (cnum = MDSS_MDP_CTL0; cnum < mdata->nctl; cnum++) { ctl = mdata->ctl_off + cnum; if (!ctl->power_on) continue; pr_debug("restoring ctl%d, intf_type=%d\n", cnum, ctl->intf_type); ctl->play_cnt = 0; sctl = mdss_mdp_get_split_ctl(ctl); mdss_mdp_ctl_restore_sub(ctl); if (sctl) { mdss_mdp_ctl_restore_sub(sctl); mdss_mdp_ctl_split_display_enable(1, ctl, sctl); } if (ctl->restore_fnc) ctl->restore_fnc(ctl); } mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF); } Loading drivers/video/msm/mdss/mdss_mdp_intf_cmd.c +14 −47 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ */ #include <linux/kernel.h> #include <linux/pm_runtime.h> #include "mdss_mdp.h" #include "mdss_panel.h" Loading Loading @@ -45,12 +46,10 @@ struct mdss_mdp_cmd_ctx { spinlock_t clk_lock; spinlock_t koff_lock; struct work_struct clk_work; struct delayed_work pc_work; struct work_struct pp_done_work; atomic_t pp_done_cnt; struct mdss_panel_recovery recovery; struct mdss_mdp_cmd_ctx *sync_ctx; /* for partial update */ bool idle_pc; }; struct mdss_mdp_cmd_ctx mdss_mdp_cmd_ctx_list[MAX_SESSIONS]; Loading Loading @@ -217,31 +216,15 @@ static inline void mdss_mdp_cmd_clk_on(struct mdss_mdp_cmd_ctx *ctx) ctx->rdptr_enabled); if (!ctx->clk_enabled) { mdss_bus_bandwidth_ctrl(true); ctx->clk_enabled = 1; if (cancel_delayed_work_sync(&ctx->pc_work)) pr_debug("deleted pending power collapse work\n"); rc = mdss_iommu_ctrl(1); if (IS_ERR_VALUE(rc)) pr_err("IOMMU attach failed\n"); if (ctx->idle_pc) { mdss_mdp_footswitch_ctrl_idle_pc(1, &ctx->ctl->mfd->pdev->dev); mdss_mdp_ctl_restore(ctx->ctl); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); if (mdss_mdp_cmd_tearcheck_setup(ctx->ctl, true)) pr_warn("tearcheck setup failed\n"); ctx->idle_pc = false; } else { mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); } mdss_mdp_ctl_intf_event (ctx->ctl, MDSS_EVENT_PANEL_CLK_CTRL, (void *)1); mdss_mdp_hist_intr_setup(&mdata->hist_intr, MDSS_IRQ_RESUME); } spin_lock_irqsave(&ctx->clk_lock, flags); Loading Loading @@ -277,9 +260,6 @@ static inline void mdss_mdp_cmd_clk_off(struct mdss_mdp_cmd_ctx *ctx) mdss_iommu_ctrl(0); mdss_bus_bandwidth_ctrl(false); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF); if ((ctx->panel_on) && (mdata->idle_pc_enabled)) schedule_delayed_work(&ctx->pc_work, POWER_COLLAPSE_TIME); } mutex_unlock(&ctx->clk_mtx); } Loading Loading @@ -427,27 +407,6 @@ static void clk_ctrl_work(struct work_struct *work) mdss_mdp_cmd_clk_off(ctx); } static void __mdss_mdp_cmd_pc_work(struct work_struct *work) { struct delayed_work *dw = to_delayed_work(work); struct mdss_mdp_cmd_ctx *ctx = container_of(dw, struct mdss_mdp_cmd_ctx, pc_work); if (!ctx) { pr_err("%s: invalid ctx\n", __func__); return; } if (!ctx->panel_on) { pr_err("Panel is off. skipping power collapse\n"); return; } ctx->idle_pc = true; ctx->ctl->play_cnt = 0; mdss_mdp_footswitch_ctrl_idle_pc(0, &ctx->ctl->mfd->pdev->dev); } static int mdss_mdp_cmd_add_vsync_handler(struct mdss_mdp_ctl *ctl, struct mdss_mdp_vsync_handler *handle) { Loading Loading @@ -788,6 +747,17 @@ int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg) return 0; } int mdss_mdp_cmd_restore(struct mdss_mdp_ctl *ctl) { pr_debug("%s: called for ctl%d\n", __func__, ctl->num); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); if (mdss_mdp_cmd_tearcheck_setup(ctl, true)) pr_warn("%s: tearcheck setup failed\n", __func__); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF); return 0; } int mdss_mdp_cmd_intfs_stop(struct mdss_mdp_ctl *ctl, int session) { struct mdss_mdp_cmd_ctx *ctx; Loading Loading @@ -845,9 +815,6 @@ int mdss_mdp_cmd_intfs_stop(struct mdss_mdp_ctl *ctl, int session) if (cancel_work_sync(&ctx->clk_work)) pr_debug("no pending clk work\n"); if (cancel_delayed_work_sync(&ctx->pc_work)) pr_debug("deleted pending power collapse work\n"); mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_REGISTER_RECOVERY_HANDLER, NULL); Loading Loading @@ -960,7 +927,6 @@ static int mdss_mdp_cmd_intfs_setup(struct mdss_mdp_ctl *ctl, spin_lock_init(&ctx->koff_lock); mutex_init(&ctx->clk_mtx); INIT_WORK(&ctx->clk_work, clk_ctrl_work); INIT_DELAYED_WORK(&ctx->pc_work, __mdss_mdp_cmd_pc_work); INIT_WORK(&ctx->pp_done_work, pingpong_done_work); atomic_set(&ctx->pp_done_cnt, 0); INIT_LIST_HEAD(&ctx->vsync_handlers); Loading Loading @@ -1007,6 +973,7 @@ int mdss_mdp_cmd_start(struct mdss_mdp_ctl *ctl) ctl->add_vsync_handler = mdss_mdp_cmd_add_vsync_handler; ctl->remove_vsync_handler = mdss_mdp_cmd_remove_vsync_handler; ctl->read_line_cnt_fnc = mdss_mdp_cmd_line_count; ctl->restore_fnc = mdss_mdp_cmd_restore; pr_debug("%s:-\n", __func__); return 0; Loading Loading
drivers/video/msm/mdss/mdss.h +1 −0 Original line number Diff line number Diff line Loading @@ -240,6 +240,7 @@ struct mdss_data_type { bool traffic_shaper_en; int iommu_ref_cnt; u32 latency_buff_per; atomic_t active_intf_cnt; u64 ab[MDSS_MAX_HW_BLK]; u64 ib[MDSS_MAX_HW_BLK]; Loading
drivers/video/msm/mdss/mdss_mdp.c +69 −43 Original line number Diff line number Diff line Loading @@ -87,6 +87,7 @@ static DEFINE_SPINLOCK(mdp_lock); static DEFINE_MUTEX(mdp_clk_lock); static DEFINE_MUTEX(bus_bw_lock); static DEFINE_MUTEX(mdp_iommu_lock); static DEFINE_MUTEX(mdp_fs_idle_pc_lock); static struct mdss_panel_intf pan_types[] = { {"dsi", MDSS_PANEL_INTF_DSI}, Loading Loading @@ -774,6 +775,41 @@ int mdss_iommu_ctrl(int enable) return mdata->iommu_ref_cnt; } /** * mdss_mdp_idle_pc_restore() - Restore MDSS settings when exiting idle pc * * MDSS GDSC can be voted off during idle-screen usecase for MIPI DSI command * mode displays, referred to as MDSS idle power collapse. Upon subsequent * frame update, MDSS GDSC needs to turned back on and hw state needs to be * restored. */ static int mdss_mdp_idle_pc_restore(void) { struct mdss_data_type *mdata = mdss_mdp_get_mdata(); int rc = 0; mutex_lock(&mdp_fs_idle_pc_lock); if (!mdata->idle_pc) { pr_debug("no idle pc, no need to restore\n"); goto end; } pr_debug("called from %pS\n", __builtin_return_address(0)); rc = mdss_iommu_ctrl(1); if (IS_ERR_VALUE(rc)) { pr_err("mdss iommu attach failed rc=%d\n", rc); goto end; } mdss_hw_init(mdata); mdss_iommu_ctrl(0); mdss_mdp_ctl_restore(); mdata->idle_pc = false; end: mutex_unlock(&mdp_fs_idle_pc_lock); return rc; } /** * mdss_bus_bandwidth_ctrl() -- place bus bandwidth request * @enable: value of enable or disable Loading Loading @@ -814,6 +850,7 @@ void mdss_bus_bandwidth_ctrl(int enable) pm_runtime_put(&mdata->pdev->dev); } else { pm_runtime_get_sync(&mdata->pdev->dev); mdss_mdp_idle_pc_restore(); msm_bus_scale_client_update_request( mdata->bus_hdl, mdata->curr_bw_uc_idx); } Loading Loading @@ -849,10 +886,10 @@ void mdss_mdp_clk_ctrl(int enable) __func__, mdp_clk_cnt, changed, enable); if (changed) { mdata->clk_ena = enable; if (enable) pm_runtime_get_sync(&mdata->pdev->dev); mdata->clk_ena = enable; mdss_mdp_clk_update(MDSS_CLK_AHB, enable); mdss_mdp_clk_update(MDSS_CLK_AXI, enable); mdss_mdp_clk_update(MDSS_CLK_MDP_CORE, enable); Loading Loading @@ -1452,6 +1489,7 @@ static int mdss_mdp_probe(struct platform_device *pdev) mdss_res = mdata; mutex_init(&mdata->reg_lock); atomic_set(&mdata->sd_client_count, 0); atomic_set(&mdata->active_intf_cnt, 0); rc = msm_dss_ioremap_byname(pdev, &mdata->mdss_io, "mdp_phys"); if (rc) { Loading Loading @@ -2909,19 +2947,30 @@ vreg_set_voltage_fail: return rc; } /** * mdss_mdp_footswitch_ctrl() - Disable/enable MDSS GDSC and CX/Batfet rails * @mdata: MDP private data * @on: 1 to turn on footswitch, 0 to turn off footswitch * * When no active references to the MDP device node and it's child nodes are * held, MDSS GDSC can be turned off. However, any any panels are still * active (but likely in an idle state), the vote for the CX and the batfet * rails should not be released. */ static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on) { int ret; int active_cnt = 0; if (!mdata->fs) return; if (on) { pr_debug("Enable MDP FS\n"); if (!mdata->fs_ena) { pr_debug("Enable MDP FS\n"); ret = regulator_enable(mdata->fs); if (ret) pr_err("Footswitch failed to enable\n"); pr_warn("Footswitch failed to enable\n"); if (!mdata->idle_pc) { mdss_mdp_cx_ctrl(mdata, true); mdss_mdp_batfet_ctrl(mdata, true); Loading @@ -2929,52 +2978,27 @@ static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on) } mdata->fs_ena = true; } else { pr_debug("Disable MDP FS\n"); if (mdata->fs_ena) { regulator_disable(mdata->fs); if (!mdata->idle_pc) { pr_debug("Disable MDP FS\n"); active_cnt = atomic_read(&mdata->active_intf_cnt); if (active_cnt != 0) { /* * Turning off GDSC while overlays are still * active. */ mdata->idle_pc = true; pr_debug("idle pc. active overlays=%d\n", active_cnt); } else { mdss_mdp_cx_ctrl(mdata, false); mdss_mdp_batfet_ctrl(mdata, false); } regulator_disable(mdata->fs); } mdata->fs_ena = false; } } /** * mdss_mdp_footswitch_ctrl_idle_pc() - MDSS GDSC control with idle power collapse * @on: 1 to turn on footswitch, 0 to turn off footswitch * @dev: framebuffer device node * * MDSS GDSC can be voted off during idle-screen usecase for MIPI DSI command * mode displays. Upon subsequent frame update, MDSS GDSC needs to turned back * on and hw state needs to be restored. It returns error if footswitch control * API fails. */ int mdss_mdp_footswitch_ctrl_idle_pc(int on, struct device *dev) { struct mdss_data_type *mdata = mdss_mdp_get_mdata(); int rc = 0; pr_debug("called on=%d\n", on); if (on) { pm_runtime_get_sync(dev); rc = mdss_iommu_ctrl(1); if (IS_ERR_VALUE(rc)) { pr_err("mdss iommu attach failed rc=%d\n", rc); return rc; } mdss_hw_init(mdata); mdss_iommu_ctrl(0); mdata->idle_pc = false; } else { mdata->idle_pc = true; pm_runtime_put_sync(dev); } return 0; } int mdss_mdp_secure_display_ctrl(unsigned int enable) { struct sd_ctrl_req { Loading Loading @@ -3089,7 +3113,8 @@ static int mdss_mdp_runtime_resume(struct device *dev) if (!mdata) return -ENODEV; dev_dbg(dev, "pm_runtime: resuming...\n"); dev_dbg(dev, "pm_runtime: resuming. active overlay cnt=%d\n", atomic_read(&mdata->active_intf_cnt)); /* do not resume panels when coming out of idle power collapse */ if (!mdata->idle_pc) Loading @@ -3116,17 +3141,18 @@ static int mdss_mdp_runtime_suspend(struct device *dev) bool device_on = false; if (!mdata) return -ENODEV; dev_dbg(dev, "pm_runtime: suspending...\n"); dev_dbg(dev, "pm_runtime: suspending. active overlay cnt=%d\n", atomic_read(&mdata->active_intf_cnt)); if (mdata->clk_ena) { pr_err("MDP suspend failed\n"); return -EBUSY; } mdss_mdp_footswitch_ctrl(mdata, false); /* do not suspend panels when going in to idle power collapse */ if (!mdata->idle_pc) device_for_each_child(dev, &device_on, mdss_fb_suspres_panel); mdss_mdp_footswitch_ctrl(mdata, false); return 0; } Loading
drivers/video/msm/mdss/mdss_mdp.h +2 −2 Original line number Diff line number Diff line Loading @@ -230,6 +230,7 @@ struct mdss_mdp_ctl { struct mdss_mdp_vsync_handler *); int (*config_fps_fnc) (struct mdss_mdp_ctl *ctl, struct mdss_mdp_ctl *sctl, int new_fps); int (*restore_fnc) (struct mdss_mdp_ctl *ctl); struct blocking_notifier_head notifier_head; Loading Loading @@ -889,7 +890,6 @@ int mdss_mdp_wb_get_format(struct msm_fb_data_type *mfd, int mdss_mdp_pipe_program_pixel_extn(struct mdss_mdp_pipe *pipe); int mdss_mdp_wb_set_secure(struct msm_fb_data_type *mfd, int enable); int mdss_mdp_wb_get_secure(struct msm_fb_data_type *mfd, uint8_t *enable); void mdss_mdp_ctl_restore(struct mdss_mdp_ctl *ctl); int mdss_mdp_footswitch_ctrl_idle_pc(int on, struct device *dev); void mdss_mdp_ctl_restore(void); int mdss_mdp_ctl_reset(struct mdss_mdp_ctl *ctl); #endif /* MDSS_MDP_H */
drivers/video/msm/mdss/mdss_mdp_ctl.c +22 −9 Original line number Diff line number Diff line Loading @@ -2097,23 +2097,36 @@ static void mdss_mdp_ctl_restore_sub(struct mdss_mdp_ctl *ctl) /* * mdss_mdp_ctl_restore() - restore mdp ctl path * @ctl: mdp controller. * * This function is called whenever MDP comes out of a power collapse as * a result of a screen update when DSI ULPS mode is enabled. It restores * the MDP controller's software state to the hardware registers. * a result of a screen update. It restores the MDP controller's software * state to the hardware registers. */ void mdss_mdp_ctl_restore(struct mdss_mdp_ctl *ctl) void mdss_mdp_ctl_restore(void) { struct mdss_mdp_ctl *ctl = NULL; struct mdss_mdp_ctl *sctl; struct mdss_data_type *mdata = mdss_mdp_get_mdata(); u32 cnum; sctl = mdss_mdp_get_split_ctl(ctl); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); for (cnum = MDSS_MDP_CTL0; cnum < mdata->nctl; cnum++) { ctl = mdata->ctl_off + cnum; if (!ctl->power_on) continue; pr_debug("restoring ctl%d, intf_type=%d\n", cnum, ctl->intf_type); ctl->play_cnt = 0; sctl = mdss_mdp_get_split_ctl(ctl); mdss_mdp_ctl_restore_sub(ctl); if (sctl) { mdss_mdp_ctl_restore_sub(sctl); mdss_mdp_ctl_split_display_enable(1, ctl, sctl); } if (ctl->restore_fnc) ctl->restore_fnc(ctl); } mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF); } Loading
drivers/video/msm/mdss/mdss_mdp_intf_cmd.c +14 −47 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ */ #include <linux/kernel.h> #include <linux/pm_runtime.h> #include "mdss_mdp.h" #include "mdss_panel.h" Loading Loading @@ -45,12 +46,10 @@ struct mdss_mdp_cmd_ctx { spinlock_t clk_lock; spinlock_t koff_lock; struct work_struct clk_work; struct delayed_work pc_work; struct work_struct pp_done_work; atomic_t pp_done_cnt; struct mdss_panel_recovery recovery; struct mdss_mdp_cmd_ctx *sync_ctx; /* for partial update */ bool idle_pc; }; struct mdss_mdp_cmd_ctx mdss_mdp_cmd_ctx_list[MAX_SESSIONS]; Loading Loading @@ -217,31 +216,15 @@ static inline void mdss_mdp_cmd_clk_on(struct mdss_mdp_cmd_ctx *ctx) ctx->rdptr_enabled); if (!ctx->clk_enabled) { mdss_bus_bandwidth_ctrl(true); ctx->clk_enabled = 1; if (cancel_delayed_work_sync(&ctx->pc_work)) pr_debug("deleted pending power collapse work\n"); rc = mdss_iommu_ctrl(1); if (IS_ERR_VALUE(rc)) pr_err("IOMMU attach failed\n"); if (ctx->idle_pc) { mdss_mdp_footswitch_ctrl_idle_pc(1, &ctx->ctl->mfd->pdev->dev); mdss_mdp_ctl_restore(ctx->ctl); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); if (mdss_mdp_cmd_tearcheck_setup(ctx->ctl, true)) pr_warn("tearcheck setup failed\n"); ctx->idle_pc = false; } else { mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); } mdss_mdp_ctl_intf_event (ctx->ctl, MDSS_EVENT_PANEL_CLK_CTRL, (void *)1); mdss_mdp_hist_intr_setup(&mdata->hist_intr, MDSS_IRQ_RESUME); } spin_lock_irqsave(&ctx->clk_lock, flags); Loading Loading @@ -277,9 +260,6 @@ static inline void mdss_mdp_cmd_clk_off(struct mdss_mdp_cmd_ctx *ctx) mdss_iommu_ctrl(0); mdss_bus_bandwidth_ctrl(false); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF); if ((ctx->panel_on) && (mdata->idle_pc_enabled)) schedule_delayed_work(&ctx->pc_work, POWER_COLLAPSE_TIME); } mutex_unlock(&ctx->clk_mtx); } Loading Loading @@ -427,27 +407,6 @@ static void clk_ctrl_work(struct work_struct *work) mdss_mdp_cmd_clk_off(ctx); } static void __mdss_mdp_cmd_pc_work(struct work_struct *work) { struct delayed_work *dw = to_delayed_work(work); struct mdss_mdp_cmd_ctx *ctx = container_of(dw, struct mdss_mdp_cmd_ctx, pc_work); if (!ctx) { pr_err("%s: invalid ctx\n", __func__); return; } if (!ctx->panel_on) { pr_err("Panel is off. skipping power collapse\n"); return; } ctx->idle_pc = true; ctx->ctl->play_cnt = 0; mdss_mdp_footswitch_ctrl_idle_pc(0, &ctx->ctl->mfd->pdev->dev); } static int mdss_mdp_cmd_add_vsync_handler(struct mdss_mdp_ctl *ctl, struct mdss_mdp_vsync_handler *handle) { Loading Loading @@ -788,6 +747,17 @@ int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg) return 0; } int mdss_mdp_cmd_restore(struct mdss_mdp_ctl *ctl) { pr_debug("%s: called for ctl%d\n", __func__, ctl->num); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); if (mdss_mdp_cmd_tearcheck_setup(ctl, true)) pr_warn("%s: tearcheck setup failed\n", __func__); mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF); return 0; } int mdss_mdp_cmd_intfs_stop(struct mdss_mdp_ctl *ctl, int session) { struct mdss_mdp_cmd_ctx *ctx; Loading Loading @@ -845,9 +815,6 @@ int mdss_mdp_cmd_intfs_stop(struct mdss_mdp_ctl *ctl, int session) if (cancel_work_sync(&ctx->clk_work)) pr_debug("no pending clk work\n"); if (cancel_delayed_work_sync(&ctx->pc_work)) pr_debug("deleted pending power collapse work\n"); mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_REGISTER_RECOVERY_HANDLER, NULL); Loading Loading @@ -960,7 +927,6 @@ static int mdss_mdp_cmd_intfs_setup(struct mdss_mdp_ctl *ctl, spin_lock_init(&ctx->koff_lock); mutex_init(&ctx->clk_mtx); INIT_WORK(&ctx->clk_work, clk_ctrl_work); INIT_DELAYED_WORK(&ctx->pc_work, __mdss_mdp_cmd_pc_work); INIT_WORK(&ctx->pp_done_work, pingpong_done_work); atomic_set(&ctx->pp_done_cnt, 0); INIT_LIST_HEAD(&ctx->vsync_handlers); Loading Loading @@ -1007,6 +973,7 @@ int mdss_mdp_cmd_start(struct mdss_mdp_ctl *ctl) ctl->add_vsync_handler = mdss_mdp_cmd_add_vsync_handler; ctl->remove_vsync_handler = mdss_mdp_cmd_remove_vsync_handler; ctl->read_line_cnt_fnc = mdss_mdp_cmd_line_count; ctl->restore_fnc = mdss_mdp_cmd_restore; pr_debug("%s:-\n", __func__); return 0; Loading