Loading drivers/video/msm/mdss/dsi_host_v2.c +12 −1 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include "dsi_io_v2.h" #include "dsi_host_v2.h" #include "mdss_debug.h" #include "mdp3.h" #define DSI_POLL_SLEEP_US 1000 #define DSI_POLL_TIMEOUT_US 16000 Loading Loading @@ -971,7 +972,13 @@ int msm_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) mutex_unlock(&ctrl->cmd_mutex); return ret; } /* * mdss interrupt is generated in mdp core clock domain * mdp clock need to be enabled to receive dsi interrupt * also, axi bus bandwidth need since dsi controller will * fetch dcs commands from axi bus */ mdp3_res_update(1, 1, MDP3_CLIENT_DMA_P); msm_dsi_clk_ctrl(&ctrl->panel_data, 1); if (0 == (req->flags & CMD_REQ_LP_MODE)) Loading @@ -986,6 +993,7 @@ int msm_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) dsi_set_tx_power_mode(1); msm_dsi_clk_ctrl(&ctrl->panel_data, 0); mdp3_res_update(0, 1, MDP3_CLIENT_DMA_P); mutex_unlock(&ctrl->cmd_mutex); return 0; Loading Loading @@ -1431,13 +1439,16 @@ static int msm_dsi_clk_ctrl(struct mdss_panel_data *pdata, int enable) &byteclk_rate, &pclk_rate); msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, dsiclk_rate, byteclk_rate, pclk_rate); msm_dsi_prepare_clocks(); msm_dsi_clk_enable(); } } else { dsi_host_private->clk_count--; if (dsi_host_private->clk_count == 0) { msm_dsi_clear_irq(ctrl_pdata, ctrl_pdata->dsi_irq_mask); msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, 0, 0, 0); msm_dsi_clk_disable(); msm_dsi_unprepare_clocks(); msm_dsi_ahb_ctrl(0); } } Loading drivers/video/msm/mdss/mdp3.c +131 −68 Original line number Diff line number Diff line Loading @@ -191,11 +191,11 @@ static irqreturn_t mdp3_irq_handler(int irq, void *ptr) u32 mdp_status = 0; spin_lock(&mdata->irq_lock); if (!mdata->irq_mask) if (!mdata->irq_mask) { pr_err("spurious interrupt\n"); clk_enable(mdp3_res->clocks[MDP3_CLK_AHB]); clk_enable(mdp3_res->clocks[MDP3_CLK_CORE]); spin_unlock(&mdata->irq_lock); return IRQ_HANDLED; } mdp_status = MDP3_REG_READ(MDP3_REG_INTR_STATUS); mdp_interrupt = mdp_status; Loading @@ -211,9 +211,6 @@ static irqreturn_t mdp3_irq_handler(int irq, void *ptr) } MDP3_REG_WRITE(MDP3_REG_INTR_CLEAR, mdp_status); clk_disable(mdp3_res->clocks[MDP3_CLK_AHB]); clk_disable(mdp3_res->clocks[MDP3_CLK_CORE]); spin_unlock(&mdata->irq_lock); return IRQ_HANDLED; Loading Loading @@ -281,19 +278,51 @@ void mdp3_irq_register(void) pr_debug("mdp3_irq_register\n"); spin_lock_irqsave(&mdp3_res->irq_lock, flag); mdp3_res->irq_ref_cnt++; if (mdp3_res->irq_ref_cnt == 1) { MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irq_mask); enable_irq(mdp3_res->irq); } spin_unlock_irqrestore(&mdp3_res->irq_lock, flag); } void mdp3_irq_deregister(void) { unsigned long flag; bool irq_enabled = true; pr_debug("mdp3_irq_deregister\n"); spin_lock_irqsave(&mdp3_res->irq_lock, flag); memset(mdp3_res->irq_ref_count, 0, sizeof(u32) * MDP3_MAX_INTR); mdp3_res->irq_mask = 0; MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, 0); mdp3_res->irq_ref_cnt--; /* This can happen if suspend is called first */ if (mdp3_res->irq_ref_cnt < 0) { irq_enabled = false; mdp3_res->irq_ref_cnt = 0; } if (mdp3_res->irq_ref_cnt == 0 && irq_enabled) disable_irq_nosync(mdp3_res->irq); spin_unlock_irqrestore(&mdp3_res->irq_lock, flag); } void mdp3_irq_suspend(void) { unsigned long flag; bool irq_enabled = true; pr_debug("%s\n", __func__); spin_lock_irqsave(&mdp3_res->irq_lock, flag); mdp3_res->irq_ref_cnt--; if (mdp3_res->irq_ref_cnt < 0) { irq_enabled = false; mdp3_res->irq_ref_cnt = 0; } if (mdp3_res->irq_ref_cnt == 0 && irq_enabled) { MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, 0); disable_irq_nosync(mdp3_res->irq); } spin_unlock_irqrestore(&mdp3_res->irq_lock, flag); } Loading Loading @@ -403,6 +432,12 @@ int mdp3_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota) } bus_handle->current_bus_idx = bus_idx; rc = msm_bus_scale_client_update_request(bus_handle->handle, bus_idx); if (!rc && ab_quota != 0 && ib_quota != 0) { bus_handle->restore_ab = ab_quota; bus_handle->restore_ib = ib_quota; } return rc; } Loading @@ -425,10 +460,18 @@ static int mdp3_clk_update(u32 clk_idx, u32 enable) count = mdp3_res->clock_ref_count[clk_idx]; if (count == 1 && enable) { pr_debug("clk=%d en=%d\n", clk_idx, enable); ret = clk_prepare(clk); if (ret) { pr_err("%s: Failed to prepare clock %d", __func__, clk_idx); mdp3_res->clock_ref_count[clk_idx]--; return ret; } ret = clk_enable(clk); } else if (count == 0) { pr_debug("clk=%d disable\n", clk_idx); clk_disable(clk); clk_unprepare(clk); ret = 0; } else if (count < 0) { pr_err("clk=%d count=%d\n", clk_idx, count); Loading Loading @@ -580,54 +623,76 @@ int mdp3_clk_enable(int enable, int dsi_clk) return rc; } int mdp3_clk_prepare(void) void mdp3_bus_bw_iommu_enable(int enable, int client) { int rc = 0; struct mdp3_bus_handle_map *bus_handle; int client_idx; u64 ab, ib; int ref_cnt; mutex_lock(&mdp3_res->res_mutex); mdp3_res->clk_prepare_count++; if (mdp3_res->clk_prepare_count == 1) { rc = clk_prepare(mdp3_res->clocks[MDP3_CLK_AHB]); if (rc < 0) goto error0; rc = clk_prepare(mdp3_res->clocks[MDP3_CLK_CORE]); if (rc < 0) goto error1; rc = clk_prepare(mdp3_res->clocks[MDP3_CLK_VSYNC]); if (rc < 0) goto error2; rc = clk_prepare(mdp3_res->clocks[MDP3_CLK_DSI]); if (rc < 0) goto error3; if (client == MDP3_CLIENT_DMA_P) { client_idx = MDP3_BUS_HANDLE_DMA; } else if (client == MDP3_CLIENT_PPP) { client_idx = MDP3_BUS_HANDLE_PPP; } else { pr_err("invalid client %d\n", client); return; } mutex_unlock(&mdp3_res->res_mutex); return rc; error3: clk_unprepare(mdp3_res->clocks[MDP3_CLK_VSYNC]); error2: clk_unprepare(mdp3_res->clocks[MDP3_CLK_CORE]); error1: clk_unprepare(mdp3_res->clocks[MDP3_CLK_AHB]); error0: mdp3_res->clk_prepare_count--; bus_handle = &mdp3_res->bus_handle[client_idx]; if (bus_handle->handle < 1) { pr_err("invalid bus handle %d\n", bus_handle->handle); return; } mutex_lock(&mdp3_res->res_mutex); if (enable) bus_handle->ref_cnt++; else bus_handle->ref_cnt--; ref_cnt = bus_handle->ref_cnt; mutex_unlock(&mdp3_res->res_mutex); return rc; if (enable && ref_cnt == 1) { if (mdp3_res->allow_iommu_update) mdp3_iommu_enable(client); ab = bus_handle->restore_ab; ib = bus_handle->restore_ib; mdp3_bus_scale_set_quota(client, ab, ib); } else if (!enable && ref_cnt == 0) { mdp3_bus_scale_set_quota(client, 0, 0); mdp3_iommu_disable(client); } else if (ref_cnt < 0) { pr_err("Ref count < 0, bus client=%d, ref_cnt=%d", client_idx, ref_cnt); } } void mdp3_clk_unprepare(void) int mdp3_res_update(int enable, int dsi_clk, int client) { mutex_lock(&mdp3_res->res_mutex); mdp3_res->clk_prepare_count--; if (mdp3_res->clk_prepare_count == 0) { clk_unprepare(mdp3_res->clocks[MDP3_CLK_AHB]); clk_unprepare(mdp3_res->clocks[MDP3_CLK_CORE]); clk_unprepare(mdp3_res->clocks[MDP3_CLK_VSYNC]); clk_unprepare(mdp3_res->clocks[MDP3_CLK_DSI]); } else if (mdp3_res->clk_prepare_count < 0) { pr_err("mdp3 clk unprepare mismatch\n"); int rc = 0; if (enable) { rc = mdp3_clk_enable(enable, dsi_clk); if (rc < 0) { pr_err("mdp3_clk_enable failed, enable=%d, dsi_clk=%d\n", enable, dsi_clk); goto done; } mutex_unlock(&mdp3_res->res_mutex); mdp3_irq_register(); mdp3_bus_bw_iommu_enable(enable, client); } else { mdp3_bus_bw_iommu_enable(enable, client); mdp3_irq_suspend(); rc = mdp3_clk_enable(enable, dsi_clk); if (rc < 0) { pr_err("mdp3_clk_enable failed, enable=%d, dsi_clk=%d\n", enable, dsi_clk); goto done; } } done: return rc; } int mdp3_get_mdp_dsi_clk(void) Loading @@ -646,7 +711,6 @@ int mdp3_put_mdp_dsi_clk(void) int rc; mutex_lock(&mdp3_res->res_mutex); rc = mdp3_clk_update(MDP3_CLK_DSI, 0); clk_unprepare(mdp3_res->clocks[MDP3_CLK_DSI]); mutex_unlock(&mdp3_res->res_mutex); return rc; } Loading Loading @@ -1847,6 +1911,7 @@ static int mdp3_is_display_on(struct mdss_panel_data *pdata) static int mdp3_continuous_splash_on(struct mdss_panel_data *pdata) { struct mdss_panel_info *panel_info = &pdata->panel_info; struct mdp3_bus_handle_map *bus_handle; u64 ab, ib; int rc; Loading @@ -1858,26 +1923,23 @@ static int mdp3_continuous_splash_on(struct mdss_panel_data *pdata) mdp3_clk_set_rate(MDP3_CLK_CORE, MDP_CORE_CLK_RATE, MDP3_CLIENT_DMA_P); rc = mdp3_clk_prepare(); if (rc) { pr_err("fail to prepare clk\n"); return rc; } rc = mdp3_clk_enable(1, 1); if (rc) { pr_err("fail to enable clk\n"); mdp3_clk_unprepare(); return rc; bus_handle = &mdp3_res->bus_handle[MDP3_BUS_HANDLE_DMA]; if (bus_handle->handle < 1) { pr_err("invalid bus handle %d\n", bus_handle->handle); return -EINVAL; } ab = panel_info->xres * panel_info->yres * 4; ab *= panel_info->mipi.frame_rate; ib = (ab * 3) / 2; rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_DMA_P, ab, ib); bus_handle->restore_ab = ab; bus_handle->restore_ib = ib; rc = mdp3_res_update(1, 1, MDP3_CLIENT_DMA_P); if (rc) { pr_err("fail to request bus bandwidth\n"); goto splash_on_err; pr_err("fail to enable clk\n"); return rc; } rc = mdp3_ppp_init(); Loading @@ -1886,8 +1948,6 @@ static int mdp3_continuous_splash_on(struct mdss_panel_data *pdata) goto splash_on_err; } mdp3_irq_register(); if (pdata->event_handler) { rc = pdata->event_handler(pdata, MDSS_EVENT_CONT_SPLASH_BEGIN, NULL); Loading @@ -1907,10 +1967,9 @@ static int mdp3_continuous_splash_on(struct mdss_panel_data *pdata) return 0; splash_on_err: if (mdp3_clk_enable(0, 1)) if (mdp3_res_update(0, 1, MDP3_CLIENT_DMA_P)) pr_err("%s: Unable to disable mdp3 clocks\n", __func__); mdp3_clk_unprepare(); return rc; } Loading @@ -1930,6 +1989,12 @@ static int mdp3_panel_register_done(struct mdss_panel_data *pdata) rc = mdp3_continuous_splash_on(pdata); } } /* * We want to prevent iommu from being enabled if there is * continue splash screen. This would have happened in * res_update in continuous_splash_on without this flag. */ mdp3_res->allow_iommu_update = true; return rc; } Loading @@ -1944,11 +2009,9 @@ static int mdp3_debug_dump_stats(void *data, char *buf, int len) static void mdp3_debug_enable_clock(int on) { if (on) { mdp3_clk_prepare(); mdp3_clk_enable(1, 0); } else { mdp3_clk_enable(0, 0); mdp3_clk_unprepare(); } } Loading drivers/video/msm/mdss/mdp3.h +6 −2 Original line number Diff line number Diff line Loading @@ -73,6 +73,9 @@ struct mdp3_bus_handle_map { struct msm_bus_paths *usecases; struct msm_bus_scale_pdata *scale_pdata; int current_bus_idx; int ref_cnt; u64 restore_ab; u64 restore_ib; u32 handle; }; Loading Loading @@ -133,6 +136,7 @@ struct mdp3_hw_resource { struct ion_client *ion_client; struct mdp3_iommu_domain_map *domains; struct mdp3_iommu_ctx_map *iommu_contexts; bool allow_iommu_update; struct ion_handle *ion_handle; struct mutex iommu_lock; struct rb_root iommu_root; Loading @@ -143,6 +147,7 @@ struct mdp3_hw_resource { spinlock_t irq_lock; u32 irq_ref_count[MDP3_MAX_INTR]; u32 irq_mask; int irq_ref_cnt; struct mdp3_intr_cb callbacks[MDP3_MAX_INTR]; u32 underrun_cnt; Loading Loading @@ -182,8 +187,7 @@ void mdp3_irq_register(void); void mdp3_irq_deregister(void); int mdp3_clk_set_rate(int clk_type, unsigned long clk_rate, int client); int mdp3_clk_enable(int enable, int dsi_clk); int mdp3_clk_prepare(void); void mdp3_clk_unprepare(void); int mdp3_res_update(int enable, int dsi_clk, int client); int mdp3_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota); int mdp3_put_img(struct mdp3_img_data *data, int client); int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data, Loading drivers/video/msm/mdss/mdp3_ctrl.c +6 −34 Original line number Diff line number Diff line Loading @@ -338,7 +338,7 @@ static int mdp3_ctrl_clk_enable(struct msm_fb_data_type *mfd, int enable) (!enable && session->clk_on == 1)) { rc = panel->event_handler(panel, MDSS_EVENT_PANEL_CLK_CTRL, (void *)enable); rc |= mdp3_clk_enable(enable, 1); rc |= mdp3_res_update(enable, 1, MDP3_CLIENT_DMA_P); } else { pr_debug("enable = %d, clk_on=%d\n", enable, session->clk_on); } Loading Loading @@ -374,24 +374,15 @@ static int mdp3_ctrl_res_req_clk(struct msm_fb_data_type *mfd, int status) mdp3_clk_set_rate(MDP3_CLK_VSYNC, MDP_VSYNC_CLK_RATE, MDP3_CLIENT_DMA_P); rc = mdp3_clk_prepare(); if (rc) { pr_err("mdp3 clk prepare fail\n"); return rc; } rc = mdp3_clk_enable(1, 1); rc = mdp3_res_update(1, 1, MDP3_CLIENT_DMA_P); if (rc) { pr_err("mdp3 clk enable fail\n"); mdp3_clk_unprepare(); return rc; } } else { rc = mdp3_clk_enable(0, 1); rc = mdp3_res_update(0, 1, MDP3_CLIENT_DMA_P); if (rc) pr_err("mdp3 clk disable fail\n"); else mdp3_clk_unprepare(); } return rc; } Loading Loading @@ -588,12 +579,6 @@ static int mdp3_ctrl_on(struct msm_fb_data_type *mfd) mdp3_ctrl_notifier_register(mdp3_session, &mdp3_session->mfd->mdp_sync_pt_data.notifier); rc = mdp3_iommu_enable(MDP3_CLIENT_DMA_P); if (rc) { pr_err("fail to attach MDP DMA SMMU\n"); goto on_error; } /* request bus bandwidth before DSI DMA traffic */ rc = mdp3_ctrl_res_req_bus(mfd, 1); if (rc) { Loading @@ -616,8 +601,6 @@ static int mdp3_ctrl_on(struct msm_fb_data_type *mfd) goto on_error; } mdp3_irq_register(); rc = mdp3_ctrl_dma_init(mfd, mdp3_session->dma); if (rc) { pr_err("dma init failed\n"); Loading @@ -635,7 +618,6 @@ static int mdp3_ctrl_on(struct msm_fb_data_type *mfd) pr_err("display interface init failed\n"); goto on_error; } mdp3_session->clk_on = 1; mdp3_session->first_commit = true; Loading Loading @@ -687,7 +669,7 @@ static int mdp3_ctrl_off(struct msm_fb_data_type *mfd) pr_debug("mdp3_ctrl_off stop clock\n"); if (mdp3_session->clk_on) { rc = mdp3_clk_enable(0, 1); rc = mdp3_res_update(0, 1, MDP3_CLIENT_DMA_P); if (rc) pr_err("mdp clock resource release failed\n"); Loading @@ -698,16 +680,6 @@ static int mdp3_ctrl_off(struct msm_fb_data_type *mfd) if (rc) pr_err("fail to turn off the panel\n"); } mdp3_clk_unprepare(); pr_debug("mdp3_ctrl_off release bus\n"); rc = mdp3_ctrl_res_req_bus(mfd, 0); if (rc) pr_err("mdp bus resource release failed\n"); rc = mdp3_iommu_disable(MDP3_CLIENT_DMA_P); if (rc) pr_err("fail to dettach MDP DMA SMMU\n"); mdp3_ctrl_notifier_unregister(mdp3_session, &mdp3_session->mfd->mdp_sync_pt_data.notifier); Loading Loading @@ -1317,7 +1289,7 @@ static int mdp3_histogram_start(struct mdp3_session_data *session, return -EBUSY; } mdp3_clk_enable(1, 0); mdp3_res_update(1, 0, MDP3_CLIENT_DMA_P); ret = session->dma->histo_op(session->dma, MDP3_DMA_HISTO_OP_RESET); if (ret) { pr_err("mdp3_histogram_start reset error\n"); Loading @@ -1343,7 +1315,7 @@ static int mdp3_histogram_start(struct mdp3_session_data *session, session->histo_status = 1; histogram_start_err: mdp3_clk_enable(0, 0); mdp3_res_update(0, 0, MDP3_CLIENT_DMA_P); mutex_unlock(&session->histo_lock); return ret; } Loading drivers/video/msm/mdss/mdp3_ppp.c +2 −13 Original line number Diff line number Diff line Loading @@ -386,14 +386,14 @@ int mdp3_ppp_turnon(struct msm_fb_data_type *mfd, int on_off) ab = req_bw; } mdp3_clk_set_rate(MDP3_CLK_CORE, rate, MDP3_CLIENT_PPP); rc = mdp3_clk_enable(on_off, 0); rc = mdp3_res_update(on_off, 0, MDP3_CLIENT_PPP); if (rc < 0) { pr_err("%s: mdp3_clk_enable failed\n", __func__); return rc; } rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_PPP, ab, ib); if (rc < 0) { mdp3_clk_enable(!on_off, 0); mdp3_res_update(!on_off, 0, MDP3_CLIENT_PPP); pr_err("%s: scale_set_quota failed\n", __func__); return rc; } Loading Loading @@ -1039,14 +1039,10 @@ void mdp3_free_fw_timer_func(unsigned long arg) static void mdp3_free_bw_wq_handler(struct work_struct *work) { struct msm_fb_data_type *mfd = ppp_stat->mfd; int rc; mutex_lock(&ppp_stat->config_ppp_mutex); if (ppp_stat->bw_on) { mdp3_ppp_turnon(mfd, 0); rc = mdp3_iommu_disable(MDP3_CLIENT_PPP); if (rc < 0) WARN(1, "Unable to disable ppp iommu\n"); } mutex_unlock(&ppp_stat->config_ppp_mutex); } Loading @@ -1065,16 +1061,9 @@ static void mdp3_ppp_blit_wq_handler(struct work_struct *work) } if (!ppp_stat->bw_on) { rc = mdp3_iommu_enable(MDP3_CLIENT_PPP); if (rc < 0) { mutex_unlock(&ppp_stat->config_ppp_mutex); pr_err("%s: mdp3_iommu_enable failed\n", __func__); return; } ppp_stat->bw_optimal = mdp3_optimal_bw(req->count); mdp3_ppp_turnon(mfd, 1); if (rc < 0) { mdp3_iommu_disable(MDP3_CLIENT_PPP); mutex_unlock(&ppp_stat->config_ppp_mutex); pr_err("%s: Enable ppp resources failed\n", __func__); return; Loading Loading
drivers/video/msm/mdss/dsi_host_v2.c +12 −1 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include "dsi_io_v2.h" #include "dsi_host_v2.h" #include "mdss_debug.h" #include "mdp3.h" #define DSI_POLL_SLEEP_US 1000 #define DSI_POLL_TIMEOUT_US 16000 Loading Loading @@ -971,7 +972,13 @@ int msm_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) mutex_unlock(&ctrl->cmd_mutex); return ret; } /* * mdss interrupt is generated in mdp core clock domain * mdp clock need to be enabled to receive dsi interrupt * also, axi bus bandwidth need since dsi controller will * fetch dcs commands from axi bus */ mdp3_res_update(1, 1, MDP3_CLIENT_DMA_P); msm_dsi_clk_ctrl(&ctrl->panel_data, 1); if (0 == (req->flags & CMD_REQ_LP_MODE)) Loading @@ -986,6 +993,7 @@ int msm_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp) dsi_set_tx_power_mode(1); msm_dsi_clk_ctrl(&ctrl->panel_data, 0); mdp3_res_update(0, 1, MDP3_CLIENT_DMA_P); mutex_unlock(&ctrl->cmd_mutex); return 0; Loading Loading @@ -1431,13 +1439,16 @@ static int msm_dsi_clk_ctrl(struct mdss_panel_data *pdata, int enable) &byteclk_rate, &pclk_rate); msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, dsiclk_rate, byteclk_rate, pclk_rate); msm_dsi_prepare_clocks(); msm_dsi_clk_enable(); } } else { dsi_host_private->clk_count--; if (dsi_host_private->clk_count == 0) { msm_dsi_clear_irq(ctrl_pdata, ctrl_pdata->dsi_irq_mask); msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, 0, 0, 0); msm_dsi_clk_disable(); msm_dsi_unprepare_clocks(); msm_dsi_ahb_ctrl(0); } } Loading
drivers/video/msm/mdss/mdp3.c +131 −68 Original line number Diff line number Diff line Loading @@ -191,11 +191,11 @@ static irqreturn_t mdp3_irq_handler(int irq, void *ptr) u32 mdp_status = 0; spin_lock(&mdata->irq_lock); if (!mdata->irq_mask) if (!mdata->irq_mask) { pr_err("spurious interrupt\n"); clk_enable(mdp3_res->clocks[MDP3_CLK_AHB]); clk_enable(mdp3_res->clocks[MDP3_CLK_CORE]); spin_unlock(&mdata->irq_lock); return IRQ_HANDLED; } mdp_status = MDP3_REG_READ(MDP3_REG_INTR_STATUS); mdp_interrupt = mdp_status; Loading @@ -211,9 +211,6 @@ static irqreturn_t mdp3_irq_handler(int irq, void *ptr) } MDP3_REG_WRITE(MDP3_REG_INTR_CLEAR, mdp_status); clk_disable(mdp3_res->clocks[MDP3_CLK_AHB]); clk_disable(mdp3_res->clocks[MDP3_CLK_CORE]); spin_unlock(&mdata->irq_lock); return IRQ_HANDLED; Loading Loading @@ -281,19 +278,51 @@ void mdp3_irq_register(void) pr_debug("mdp3_irq_register\n"); spin_lock_irqsave(&mdp3_res->irq_lock, flag); mdp3_res->irq_ref_cnt++; if (mdp3_res->irq_ref_cnt == 1) { MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irq_mask); enable_irq(mdp3_res->irq); } spin_unlock_irqrestore(&mdp3_res->irq_lock, flag); } void mdp3_irq_deregister(void) { unsigned long flag; bool irq_enabled = true; pr_debug("mdp3_irq_deregister\n"); spin_lock_irqsave(&mdp3_res->irq_lock, flag); memset(mdp3_res->irq_ref_count, 0, sizeof(u32) * MDP3_MAX_INTR); mdp3_res->irq_mask = 0; MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, 0); mdp3_res->irq_ref_cnt--; /* This can happen if suspend is called first */ if (mdp3_res->irq_ref_cnt < 0) { irq_enabled = false; mdp3_res->irq_ref_cnt = 0; } if (mdp3_res->irq_ref_cnt == 0 && irq_enabled) disable_irq_nosync(mdp3_res->irq); spin_unlock_irqrestore(&mdp3_res->irq_lock, flag); } void mdp3_irq_suspend(void) { unsigned long flag; bool irq_enabled = true; pr_debug("%s\n", __func__); spin_lock_irqsave(&mdp3_res->irq_lock, flag); mdp3_res->irq_ref_cnt--; if (mdp3_res->irq_ref_cnt < 0) { irq_enabled = false; mdp3_res->irq_ref_cnt = 0; } if (mdp3_res->irq_ref_cnt == 0 && irq_enabled) { MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, 0); disable_irq_nosync(mdp3_res->irq); } spin_unlock_irqrestore(&mdp3_res->irq_lock, flag); } Loading Loading @@ -403,6 +432,12 @@ int mdp3_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota) } bus_handle->current_bus_idx = bus_idx; rc = msm_bus_scale_client_update_request(bus_handle->handle, bus_idx); if (!rc && ab_quota != 0 && ib_quota != 0) { bus_handle->restore_ab = ab_quota; bus_handle->restore_ib = ib_quota; } return rc; } Loading @@ -425,10 +460,18 @@ static int mdp3_clk_update(u32 clk_idx, u32 enable) count = mdp3_res->clock_ref_count[clk_idx]; if (count == 1 && enable) { pr_debug("clk=%d en=%d\n", clk_idx, enable); ret = clk_prepare(clk); if (ret) { pr_err("%s: Failed to prepare clock %d", __func__, clk_idx); mdp3_res->clock_ref_count[clk_idx]--; return ret; } ret = clk_enable(clk); } else if (count == 0) { pr_debug("clk=%d disable\n", clk_idx); clk_disable(clk); clk_unprepare(clk); ret = 0; } else if (count < 0) { pr_err("clk=%d count=%d\n", clk_idx, count); Loading Loading @@ -580,54 +623,76 @@ int mdp3_clk_enable(int enable, int dsi_clk) return rc; } int mdp3_clk_prepare(void) void mdp3_bus_bw_iommu_enable(int enable, int client) { int rc = 0; struct mdp3_bus_handle_map *bus_handle; int client_idx; u64 ab, ib; int ref_cnt; mutex_lock(&mdp3_res->res_mutex); mdp3_res->clk_prepare_count++; if (mdp3_res->clk_prepare_count == 1) { rc = clk_prepare(mdp3_res->clocks[MDP3_CLK_AHB]); if (rc < 0) goto error0; rc = clk_prepare(mdp3_res->clocks[MDP3_CLK_CORE]); if (rc < 0) goto error1; rc = clk_prepare(mdp3_res->clocks[MDP3_CLK_VSYNC]); if (rc < 0) goto error2; rc = clk_prepare(mdp3_res->clocks[MDP3_CLK_DSI]); if (rc < 0) goto error3; if (client == MDP3_CLIENT_DMA_P) { client_idx = MDP3_BUS_HANDLE_DMA; } else if (client == MDP3_CLIENT_PPP) { client_idx = MDP3_BUS_HANDLE_PPP; } else { pr_err("invalid client %d\n", client); return; } mutex_unlock(&mdp3_res->res_mutex); return rc; error3: clk_unprepare(mdp3_res->clocks[MDP3_CLK_VSYNC]); error2: clk_unprepare(mdp3_res->clocks[MDP3_CLK_CORE]); error1: clk_unprepare(mdp3_res->clocks[MDP3_CLK_AHB]); error0: mdp3_res->clk_prepare_count--; bus_handle = &mdp3_res->bus_handle[client_idx]; if (bus_handle->handle < 1) { pr_err("invalid bus handle %d\n", bus_handle->handle); return; } mutex_lock(&mdp3_res->res_mutex); if (enable) bus_handle->ref_cnt++; else bus_handle->ref_cnt--; ref_cnt = bus_handle->ref_cnt; mutex_unlock(&mdp3_res->res_mutex); return rc; if (enable && ref_cnt == 1) { if (mdp3_res->allow_iommu_update) mdp3_iommu_enable(client); ab = bus_handle->restore_ab; ib = bus_handle->restore_ib; mdp3_bus_scale_set_quota(client, ab, ib); } else if (!enable && ref_cnt == 0) { mdp3_bus_scale_set_quota(client, 0, 0); mdp3_iommu_disable(client); } else if (ref_cnt < 0) { pr_err("Ref count < 0, bus client=%d, ref_cnt=%d", client_idx, ref_cnt); } } void mdp3_clk_unprepare(void) int mdp3_res_update(int enable, int dsi_clk, int client) { mutex_lock(&mdp3_res->res_mutex); mdp3_res->clk_prepare_count--; if (mdp3_res->clk_prepare_count == 0) { clk_unprepare(mdp3_res->clocks[MDP3_CLK_AHB]); clk_unprepare(mdp3_res->clocks[MDP3_CLK_CORE]); clk_unprepare(mdp3_res->clocks[MDP3_CLK_VSYNC]); clk_unprepare(mdp3_res->clocks[MDP3_CLK_DSI]); } else if (mdp3_res->clk_prepare_count < 0) { pr_err("mdp3 clk unprepare mismatch\n"); int rc = 0; if (enable) { rc = mdp3_clk_enable(enable, dsi_clk); if (rc < 0) { pr_err("mdp3_clk_enable failed, enable=%d, dsi_clk=%d\n", enable, dsi_clk); goto done; } mutex_unlock(&mdp3_res->res_mutex); mdp3_irq_register(); mdp3_bus_bw_iommu_enable(enable, client); } else { mdp3_bus_bw_iommu_enable(enable, client); mdp3_irq_suspend(); rc = mdp3_clk_enable(enable, dsi_clk); if (rc < 0) { pr_err("mdp3_clk_enable failed, enable=%d, dsi_clk=%d\n", enable, dsi_clk); goto done; } } done: return rc; } int mdp3_get_mdp_dsi_clk(void) Loading @@ -646,7 +711,6 @@ int mdp3_put_mdp_dsi_clk(void) int rc; mutex_lock(&mdp3_res->res_mutex); rc = mdp3_clk_update(MDP3_CLK_DSI, 0); clk_unprepare(mdp3_res->clocks[MDP3_CLK_DSI]); mutex_unlock(&mdp3_res->res_mutex); return rc; } Loading Loading @@ -1847,6 +1911,7 @@ static int mdp3_is_display_on(struct mdss_panel_data *pdata) static int mdp3_continuous_splash_on(struct mdss_panel_data *pdata) { struct mdss_panel_info *panel_info = &pdata->panel_info; struct mdp3_bus_handle_map *bus_handle; u64 ab, ib; int rc; Loading @@ -1858,26 +1923,23 @@ static int mdp3_continuous_splash_on(struct mdss_panel_data *pdata) mdp3_clk_set_rate(MDP3_CLK_CORE, MDP_CORE_CLK_RATE, MDP3_CLIENT_DMA_P); rc = mdp3_clk_prepare(); if (rc) { pr_err("fail to prepare clk\n"); return rc; } rc = mdp3_clk_enable(1, 1); if (rc) { pr_err("fail to enable clk\n"); mdp3_clk_unprepare(); return rc; bus_handle = &mdp3_res->bus_handle[MDP3_BUS_HANDLE_DMA]; if (bus_handle->handle < 1) { pr_err("invalid bus handle %d\n", bus_handle->handle); return -EINVAL; } ab = panel_info->xres * panel_info->yres * 4; ab *= panel_info->mipi.frame_rate; ib = (ab * 3) / 2; rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_DMA_P, ab, ib); bus_handle->restore_ab = ab; bus_handle->restore_ib = ib; rc = mdp3_res_update(1, 1, MDP3_CLIENT_DMA_P); if (rc) { pr_err("fail to request bus bandwidth\n"); goto splash_on_err; pr_err("fail to enable clk\n"); return rc; } rc = mdp3_ppp_init(); Loading @@ -1886,8 +1948,6 @@ static int mdp3_continuous_splash_on(struct mdss_panel_data *pdata) goto splash_on_err; } mdp3_irq_register(); if (pdata->event_handler) { rc = pdata->event_handler(pdata, MDSS_EVENT_CONT_SPLASH_BEGIN, NULL); Loading @@ -1907,10 +1967,9 @@ static int mdp3_continuous_splash_on(struct mdss_panel_data *pdata) return 0; splash_on_err: if (mdp3_clk_enable(0, 1)) if (mdp3_res_update(0, 1, MDP3_CLIENT_DMA_P)) pr_err("%s: Unable to disable mdp3 clocks\n", __func__); mdp3_clk_unprepare(); return rc; } Loading @@ -1930,6 +1989,12 @@ static int mdp3_panel_register_done(struct mdss_panel_data *pdata) rc = mdp3_continuous_splash_on(pdata); } } /* * We want to prevent iommu from being enabled if there is * continue splash screen. This would have happened in * res_update in continuous_splash_on without this flag. */ mdp3_res->allow_iommu_update = true; return rc; } Loading @@ -1944,11 +2009,9 @@ static int mdp3_debug_dump_stats(void *data, char *buf, int len) static void mdp3_debug_enable_clock(int on) { if (on) { mdp3_clk_prepare(); mdp3_clk_enable(1, 0); } else { mdp3_clk_enable(0, 0); mdp3_clk_unprepare(); } } Loading
drivers/video/msm/mdss/mdp3.h +6 −2 Original line number Diff line number Diff line Loading @@ -73,6 +73,9 @@ struct mdp3_bus_handle_map { struct msm_bus_paths *usecases; struct msm_bus_scale_pdata *scale_pdata; int current_bus_idx; int ref_cnt; u64 restore_ab; u64 restore_ib; u32 handle; }; Loading Loading @@ -133,6 +136,7 @@ struct mdp3_hw_resource { struct ion_client *ion_client; struct mdp3_iommu_domain_map *domains; struct mdp3_iommu_ctx_map *iommu_contexts; bool allow_iommu_update; struct ion_handle *ion_handle; struct mutex iommu_lock; struct rb_root iommu_root; Loading @@ -143,6 +147,7 @@ struct mdp3_hw_resource { spinlock_t irq_lock; u32 irq_ref_count[MDP3_MAX_INTR]; u32 irq_mask; int irq_ref_cnt; struct mdp3_intr_cb callbacks[MDP3_MAX_INTR]; u32 underrun_cnt; Loading Loading @@ -182,8 +187,7 @@ void mdp3_irq_register(void); void mdp3_irq_deregister(void); int mdp3_clk_set_rate(int clk_type, unsigned long clk_rate, int client); int mdp3_clk_enable(int enable, int dsi_clk); int mdp3_clk_prepare(void); void mdp3_clk_unprepare(void); int mdp3_res_update(int enable, int dsi_clk, int client); int mdp3_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota); int mdp3_put_img(struct mdp3_img_data *data, int client); int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data, Loading
drivers/video/msm/mdss/mdp3_ctrl.c +6 −34 Original line number Diff line number Diff line Loading @@ -338,7 +338,7 @@ static int mdp3_ctrl_clk_enable(struct msm_fb_data_type *mfd, int enable) (!enable && session->clk_on == 1)) { rc = panel->event_handler(panel, MDSS_EVENT_PANEL_CLK_CTRL, (void *)enable); rc |= mdp3_clk_enable(enable, 1); rc |= mdp3_res_update(enable, 1, MDP3_CLIENT_DMA_P); } else { pr_debug("enable = %d, clk_on=%d\n", enable, session->clk_on); } Loading Loading @@ -374,24 +374,15 @@ static int mdp3_ctrl_res_req_clk(struct msm_fb_data_type *mfd, int status) mdp3_clk_set_rate(MDP3_CLK_VSYNC, MDP_VSYNC_CLK_RATE, MDP3_CLIENT_DMA_P); rc = mdp3_clk_prepare(); if (rc) { pr_err("mdp3 clk prepare fail\n"); return rc; } rc = mdp3_clk_enable(1, 1); rc = mdp3_res_update(1, 1, MDP3_CLIENT_DMA_P); if (rc) { pr_err("mdp3 clk enable fail\n"); mdp3_clk_unprepare(); return rc; } } else { rc = mdp3_clk_enable(0, 1); rc = mdp3_res_update(0, 1, MDP3_CLIENT_DMA_P); if (rc) pr_err("mdp3 clk disable fail\n"); else mdp3_clk_unprepare(); } return rc; } Loading Loading @@ -588,12 +579,6 @@ static int mdp3_ctrl_on(struct msm_fb_data_type *mfd) mdp3_ctrl_notifier_register(mdp3_session, &mdp3_session->mfd->mdp_sync_pt_data.notifier); rc = mdp3_iommu_enable(MDP3_CLIENT_DMA_P); if (rc) { pr_err("fail to attach MDP DMA SMMU\n"); goto on_error; } /* request bus bandwidth before DSI DMA traffic */ rc = mdp3_ctrl_res_req_bus(mfd, 1); if (rc) { Loading @@ -616,8 +601,6 @@ static int mdp3_ctrl_on(struct msm_fb_data_type *mfd) goto on_error; } mdp3_irq_register(); rc = mdp3_ctrl_dma_init(mfd, mdp3_session->dma); if (rc) { pr_err("dma init failed\n"); Loading @@ -635,7 +618,6 @@ static int mdp3_ctrl_on(struct msm_fb_data_type *mfd) pr_err("display interface init failed\n"); goto on_error; } mdp3_session->clk_on = 1; mdp3_session->first_commit = true; Loading Loading @@ -687,7 +669,7 @@ static int mdp3_ctrl_off(struct msm_fb_data_type *mfd) pr_debug("mdp3_ctrl_off stop clock\n"); if (mdp3_session->clk_on) { rc = mdp3_clk_enable(0, 1); rc = mdp3_res_update(0, 1, MDP3_CLIENT_DMA_P); if (rc) pr_err("mdp clock resource release failed\n"); Loading @@ -698,16 +680,6 @@ static int mdp3_ctrl_off(struct msm_fb_data_type *mfd) if (rc) pr_err("fail to turn off the panel\n"); } mdp3_clk_unprepare(); pr_debug("mdp3_ctrl_off release bus\n"); rc = mdp3_ctrl_res_req_bus(mfd, 0); if (rc) pr_err("mdp bus resource release failed\n"); rc = mdp3_iommu_disable(MDP3_CLIENT_DMA_P); if (rc) pr_err("fail to dettach MDP DMA SMMU\n"); mdp3_ctrl_notifier_unregister(mdp3_session, &mdp3_session->mfd->mdp_sync_pt_data.notifier); Loading Loading @@ -1317,7 +1289,7 @@ static int mdp3_histogram_start(struct mdp3_session_data *session, return -EBUSY; } mdp3_clk_enable(1, 0); mdp3_res_update(1, 0, MDP3_CLIENT_DMA_P); ret = session->dma->histo_op(session->dma, MDP3_DMA_HISTO_OP_RESET); if (ret) { pr_err("mdp3_histogram_start reset error\n"); Loading @@ -1343,7 +1315,7 @@ static int mdp3_histogram_start(struct mdp3_session_data *session, session->histo_status = 1; histogram_start_err: mdp3_clk_enable(0, 0); mdp3_res_update(0, 0, MDP3_CLIENT_DMA_P); mutex_unlock(&session->histo_lock); return ret; } Loading
drivers/video/msm/mdss/mdp3_ppp.c +2 −13 Original line number Diff line number Diff line Loading @@ -386,14 +386,14 @@ int mdp3_ppp_turnon(struct msm_fb_data_type *mfd, int on_off) ab = req_bw; } mdp3_clk_set_rate(MDP3_CLK_CORE, rate, MDP3_CLIENT_PPP); rc = mdp3_clk_enable(on_off, 0); rc = mdp3_res_update(on_off, 0, MDP3_CLIENT_PPP); if (rc < 0) { pr_err("%s: mdp3_clk_enable failed\n", __func__); return rc; } rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_PPP, ab, ib); if (rc < 0) { mdp3_clk_enable(!on_off, 0); mdp3_res_update(!on_off, 0, MDP3_CLIENT_PPP); pr_err("%s: scale_set_quota failed\n", __func__); return rc; } Loading Loading @@ -1039,14 +1039,10 @@ void mdp3_free_fw_timer_func(unsigned long arg) static void mdp3_free_bw_wq_handler(struct work_struct *work) { struct msm_fb_data_type *mfd = ppp_stat->mfd; int rc; mutex_lock(&ppp_stat->config_ppp_mutex); if (ppp_stat->bw_on) { mdp3_ppp_turnon(mfd, 0); rc = mdp3_iommu_disable(MDP3_CLIENT_PPP); if (rc < 0) WARN(1, "Unable to disable ppp iommu\n"); } mutex_unlock(&ppp_stat->config_ppp_mutex); } Loading @@ -1065,16 +1061,9 @@ static void mdp3_ppp_blit_wq_handler(struct work_struct *work) } if (!ppp_stat->bw_on) { rc = mdp3_iommu_enable(MDP3_CLIENT_PPP); if (rc < 0) { mutex_unlock(&ppp_stat->config_ppp_mutex); pr_err("%s: mdp3_iommu_enable failed\n", __func__); return; } ppp_stat->bw_optimal = mdp3_optimal_bw(req->count); mdp3_ppp_turnon(mfd, 1); if (rc < 0) { mdp3_iommu_disable(MDP3_CLIENT_PPP); mutex_unlock(&ppp_stat->config_ppp_mutex); pr_err("%s: Enable ppp resources failed\n", __func__); return; Loading