static void mdp4_dsi_cmd_wait4ov(int cndx) { struct vsycn_ctrl *vctrl; if (cndx >= MAX_CONTROLLER) { pr_err("%s: out or range: cndx=%d\n", __func__, cndx); return; } vctrl = &vsync_ctrl_db[cndx]; if (atomic_read(&vctrl->suspend) > 0) return; #ifdef MDP_HANG_DEBUG if (!wait_for_completion_timeout(&vctrl->ov_comp, msecs_to_jiffies(VSYNC_PERIOD*30))) { /* Does not receive interrupt from MDP, Something wrong */ mdp4_dump_regs(); panic("vctrl->ov_comp interrupt missing"); } #else wait_for_completion(&vctrl->ov_comp); #endif }
static void mdp4_dsi_video_wait4dmap(int cndx) { struct vsycn_ctrl *vctrl; ssize_t ret = 0; if (cndx >= MAX_CONTROLLER) { pr_err("%s: out or range: cndx=%d\n", __func__, cndx); return; } vctrl = &vsync_ctrl_db[cndx]; if (atomic_read(&vctrl->suspend) > 0) return; ret = wait_for_completion_interruptible_timeout( &vctrl->dmap_comp, msecs_to_jiffies(WAIT_FOR_COMPLETION_TIMEOUT)); if (ret < 0) { #ifdef MDP_HANG_DEBUG mdp4_dump_regs(); panic("vctrl->dmap_comp interrupt missing"); #endif pr_err("%s wait for completion error %x", __func__, ret); return; } else if (!ret) { #ifdef MDP_HANG_DEBUG mdp4_dump_regs(); panic("vctrl->dmap_comp interrupt missing"); #endif pr_err("%s wait for commit_comp timeout", __func__); wait_for_completion(&vctrl->dmap_comp); } }
void mdp4_dsi_cmd_wait4vsync(int cndx) { struct vsycn_ctrl *vctrl; struct mdp4_overlay_pipe *pipe; unsigned long flags; if (cndx >= MAX_CONTROLLER) { pr_err("%s: out or range: cndx=%d\n", __func__, cndx); return; } vctrl = &vsync_ctrl_db[cndx]; pipe = vctrl->base_pipe; if (atomic_read(&vctrl->suspend) > 0) return; spin_lock_irqsave(&vctrl->spin_lock, flags); if (vctrl->wait_vsync_cnt == 0) INIT_COMPLETION(vctrl->vsync_comp); vctrl->wait_vsync_cnt++; spin_unlock_irqrestore(&vctrl->spin_lock, flags); #ifdef MDP_HANG_DEBUG if (!wait_for_completion_timeout(&vctrl->vsync_comp, msecs_to_jiffies(VSYNC_PERIOD*30))) { /* Does not receive interrupt from MDP, Something wrong */ mdp4_dump_regs(); panic("vctrl->vsync_comp interrupt missing"); } #else wait_for_completion(&vctrl->vsync_comp); #endif mdp4_stat.wait4vsync0++; }
int mdp4_dsi_video_pipe_commit(int cndx, int wait) { static uint32 frameDropCnt = 0; // QC_1206 int lmCfg; // QC_1204 int i, undx; int mixer = 0; struct vsycn_ctrl *vctrl; struct vsync_update *vp; struct mdp4_overlay_pipe *pipe; struct mdp4_overlay_pipe *real_pipe; unsigned long flags; int cnt = 0; vctrl = &vsync_ctrl_db[cndx]; mutex_lock(&vctrl->update_lock); undx = vctrl->update_ndx; vp = &vctrl->vlist[undx]; pipe = vctrl->base_pipe; mixer = pipe->mixer_num; if (vp->update_cnt == 0) { mutex_unlock(&vctrl->update_lock); return cnt; } vctrl->update_ndx++; vctrl->update_ndx &= 0x01; vp->update_cnt = 0; /* reset */ if (vctrl->blt_free) { vctrl->blt_free--; // if (vctrl->blt_free == 0) // mdp4_free_writeback_buf(vctrl->mfd, mixer); } mutex_unlock(&vctrl->update_lock); /* free previous committed iommu back to pool */ mdp4_overlay_iommu_unmap_freelist(mixer); spin_lock_irqsave(&vctrl->spin_lock, flags); if (vctrl->ov_koff != vctrl->ov_done) { frameDropCnt++; // QC_1206 spin_unlock_irqrestore(&vctrl->spin_lock, flags); pr_err("%s: Error, frame dropped %d %d\n", __func__, vctrl->ov_koff, vctrl->ov_done); if (frameDropCnt >= 2) { // QC_1206 mdp4_dump_regs(); // QC_1205 lmCfg = inpdw(MDP_BASE + 0x10100); // QC_1204 pr_err("*** %s: lmCfg=%x, frameDropCnt=%d\n", __func__, lmCfg, frameDropCnt); // QC_1204 // retry ov0 pr_err("*** %s: Retrying OV0\n", __func__); // QC_1204 INIT_COMPLETION(vctrl->ov_comp); // QC_1204 vsync_irq_enable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM); // QC_1204 mb(); // QC_1204 outpdw(MDP_BASE + 0x0004, 0); // QC_1204 } return 0; } else { frameDropCnt = 0; // QC_1206 } spin_unlock_irqrestore(&vctrl->spin_lock, flags); mdp4_overlay_mdp_perf_upd(vctrl->mfd, 1); if (vctrl->blt_change) { pipe = vctrl->base_pipe; spin_lock_irqsave(&vctrl->spin_lock, flags); INIT_COMPLETION(vctrl->dmap_comp); INIT_COMPLETION(vctrl->ov_comp); vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM); spin_unlock_irqrestore(&vctrl->spin_lock, flags); mdp4_dsi_video_wait4dmap(0); if (pipe->ov_blt_addr) mdp4_dsi_video_wait4ov(0); } pipe = vp->plist; for (i = 0; i < OVERLAY_PIPE_MAX; i++, pipe++) { if (pipe->pipe_used) { cnt++; real_pipe = mdp4_overlay_ndx2pipe(pipe->pipe_ndx); if (real_pipe && real_pipe->pipe_used) { /* pipe not unset */ mdp4_overlay_vsync_commit(pipe); } /* free previous iommu to freelist * which will be freed at next * pipe_commit */ mdp4_overlay_iommu_pipe_free(pipe->pipe_ndx, 0); pipe->pipe_used = 0; /* clear */ } } mdp4_mixer_stage_commit(mixer); /* start timing generator & mmu if they are not started yet */ mdp4_overlay_dsi_video_start(); pipe = vctrl->base_pipe; spin_lock_irqsave(&vctrl->spin_lock, flags); if (pipe->ov_blt_addr) { mdp4_dsi_video_blt_ov_update(pipe); pipe->ov_cnt++; INIT_COMPLETION(vctrl->ov_comp); vsync_irq_enable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM); mb(); vctrl->ov_koff++; pr_err("*** %s: vctrl->ov_koff++=%d\n", __func__, vctrl->ov_koff); // QC_1204 lmCfg = inpdw(MDP_BASE + 0x10100); // QC_1204 pr_err("*** %s: lmCfg=%x\n", __func__, lmCfg); // QC_1204 /* kickoff overlay engine */ mdp4_stat.kickoff_ov0++; outpdw(MDP_BASE + 0x0004, 0); } else { /* schedule second phase update at dmap */ INIT_COMPLETION(vctrl->dmap_comp); vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM); } spin_unlock_irqrestore(&vctrl->spin_lock, flags); mdp4_stat.overlay_commit[pipe->mixer_num]++; if (wait) { if (pipe->ov_blt_addr) mdp4_dsi_video_wait4ov(0); else mdp4_dsi_video_wait4dmap(0); } return cnt; }