int mdp4_overlay_writeback_on(struct platform_device *pdev) { struct msm_fb_data_type *mfd; struct fb_info *fbi; uint8 *buf; struct mdp4_overlay_pipe *pipe; int bpp; int ret; uint32 data; mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); if (!mfd) return -ENODEV; if (mfd->key != MFD_KEY) return -EINVAL; writeback_mfd = mfd; wb_pdev = pdev; fbi = mfd->fbi; bpp = fbi->var.bits_per_pixel / 8; buf = (uint8 *) fbi->fix.smem_start; buf += fbi->var.xoffset * bpp + fbi->var.yoffset * fbi->fix.line_length; mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); mdp_clk_ctrl(1); if (writeback_pipe == NULL) { pipe = mdp4_overlay_pipe_alloc(OVERLAY_TYPE_BF, MDP4_MIXER2); if (pipe == NULL) pr_info("%s: pipe_alloc failed\n", __func__); pipe->pipe_used++; pipe->mixer_stage = MDP4_MIXER_STAGE_BASE; pipe->mixer_num = MDP4_MIXER2; pipe->src_format = MDP_ARGB_8888; mdp4_overlay_panel_mode(pipe->mixer_num, MDP4_PANEL_WRITEBACK); ret = mdp4_overlay_format2pipe(pipe); if (ret < 0) pr_info("%s: format2type failed\n", __func__); writeback_pipe = pipe; } else { pipe = writeback_pipe; } ret = panel_next_on(pdev); if (hdmi_prim_display) data = 0x01; else data = 0x02; outpdw(MDP_BASE + 0x100F4, data); MDP_OUTP(MDP_BASE + MDP4_OVERLAYPROC1_BASE + 0x5004, ((0x0 & 0xFFF) << 16) | (0x0 & 0xFFF)); MDP_OUTP(MDP_BASE + MDP4_OVERLAYPROC1_BASE + 0x5008, (0x0 & 0xFFF)); mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); return ret; }
int mdp4_lcdc_on(struct platform_device *pdev) { int lcdc_width; int lcdc_height; int lcdc_bpp; int lcdc_border_clr; int lcdc_underflow_clr; int lcdc_hsync_skew; int hsync_period; int hsync_ctrl; int vsync_period; int display_hctl; int display_v_start; int display_v_end; int active_hctl; int active_h_start; int active_h_end; int active_v_start; int active_v_end; int ctrl_polarity; int h_back_porch; int h_front_porch; int v_back_porch; int v_front_porch; int hsync_pulse_width; int vsync_pulse_width; int hsync_polarity; int vsync_polarity; int data_en_polarity; int hsync_start_x; int hsync_end_x; uint8 *buf; unsigned int buf_offset; int bpp, ptype; struct fb_info *fbi; struct fb_var_screeninfo *var; struct msm_fb_data_type *mfd; struct mdp4_overlay_pipe *pipe; int ret = 0; int cndx = 0; struct vsycn_ctrl *vctrl; vctrl = &vsync_ctrl_db[cndx]; mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); if (!mfd) return -ENODEV; if (mfd->key != MFD_KEY) return -EINVAL; mutex_lock(&mfd->dma->ov_mutex); vctrl->mfd = mfd; vctrl->dev = mfd->fbi->dev; vctrl->vsync_irq_enabled = 0; /* mdp clock on */ mdp_clk_ctrl(1); fbi = mfd->fbi; var = &fbi->var; bpp = fbi->var.bits_per_pixel / 8; buf = (uint8 *) fbi->fix.smem_start; buf_offset = calc_fb_offset(mfd, fbi, bpp); if (vctrl->base_pipe == NULL) { ptype = mdp4_overlay_format2type(mfd->fb_imgType); if (ptype < 0) printk(KERN_INFO "%s: format2type failed\n", __func__); pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER0); if (pipe == NULL) printk(KERN_INFO "%s: pipe_alloc failed\n", __func__); pipe->pipe_used++; pipe->mixer_stage = MDP4_MIXER_STAGE_BASE; pipe->mixer_num = MDP4_MIXER0; pipe->src_format = mfd->fb_imgType; mdp4_overlay_panel_mode(pipe->mixer_num, MDP4_PANEL_LCDC); ret = mdp4_overlay_format2pipe(pipe); if (ret < 0) printk(KERN_INFO "%s: format2pipe failed\n", __func__); mdp4_init_writeback_buf(mfd, MDP4_MIXER0); pipe->ov_blt_addr = 0; pipe->dma_blt_addr = 0; vctrl->base_pipe = pipe; /* keep it */ } else { pipe = vctrl->base_pipe; } pipe->src_height = fbi->var.yres; pipe->src_width = fbi->var.xres; pipe->src_h = fbi->var.yres; pipe->src_w = fbi->var.xres; pipe->src_y = 0; pipe->src_x = 0; pipe->dst_h = fbi->var.yres; pipe->dst_w = fbi->var.xres; if (mfd->display_iova) pipe->srcp0_addr = mfd->display_iova + buf_offset; else pipe->srcp0_addr = (uint32)(buf + buf_offset); pipe->srcp0_ystride = fbi->fix.line_length; pipe->bpp = bpp; mdp4_overlay_solidfill_init(pipe); mdp4_overlay_mdp_pipe_req(pipe, mfd); mdp4_calc_blt_mdp_bw(mfd, pipe); atomic_set(&vctrl->suspend, 0); mdp4_overlay_dmap_xy(pipe); mdp4_overlay_dmap_cfg(mfd, 1); mdp4_overlay_rgb_setup(pipe); mdp4_overlayproc_cfg(pipe); mdp4_overlay_reg_flush(pipe, 1); mdp4_mixer_stage_up(pipe, 0); /* * LCDC timing setting */ h_back_porch = var->left_margin; h_front_porch = var->right_margin; v_back_porch = var->upper_margin; v_front_porch = var->lower_margin; hsync_pulse_width = var->hsync_len; vsync_pulse_width = var->vsync_len; lcdc_border_clr = mfd->panel_info.lcdc.border_clr; lcdc_underflow_clr = mfd->panel_info.lcdc.underflow_clr; lcdc_hsync_skew = mfd->panel_info.lcdc.hsync_skew; lcdc_width = var->xres + mfd->panel_info.lcdc.xres_pad; lcdc_height = var->yres + mfd->panel_info.lcdc.yres_pad; lcdc_bpp = mfd->panel_info.bpp; hsync_period = hsync_pulse_width + h_back_porch + h_front_porch; if ((mfd->panel_info.type == LVDS_PANEL) && (mfd->panel_info.lvds.channel_mode == LVDS_DUAL_CHANNEL_MODE)) hsync_period += lcdc_width / 2; else hsync_period += lcdc_width; hsync_ctrl = (hsync_period << 16) | hsync_pulse_width; hsync_start_x = hsync_pulse_width + h_back_porch; hsync_end_x = hsync_period - h_front_porch - 1; display_hctl = (hsync_end_x << 16) | hsync_start_x; vsync_period = (vsync_pulse_width + v_back_porch + lcdc_height + v_front_porch) * hsync_period; display_v_start = (vsync_pulse_width + v_back_porch) * hsync_period + lcdc_hsync_skew; display_v_end = vsync_period - (v_front_porch * hsync_period) + lcdc_hsync_skew - 1; if (lcdc_width != var->xres) { active_h_start = hsync_start_x + first_pixel_start_x; active_h_end = active_h_start + var->xres - 1; active_hctl = ACTIVE_START_X_EN | (active_h_end << 16) | active_h_start; } else { active_hctl = 0; } if (lcdc_height != var->yres) { active_v_start = display_v_start + first_pixel_start_y * hsync_period; active_v_end = active_v_start + (var->yres) * hsync_period - 1; active_v_start |= ACTIVE_START_Y_EN; } else { active_v_start = 0; active_v_end = 0; } #ifdef CONFIG_FB_MSM_MDP40 if (mfd->panel_info.lcdc.is_sync_active_high) { hsync_polarity = 0; vsync_polarity = 0; } else { hsync_polarity = 1; vsync_polarity = 1; } lcdc_underflow_clr |= 0x80000000; /* enable recovery */ #else hsync_polarity = 0; vsync_polarity = 0; #endif data_en_polarity = 0; ctrl_polarity = (data_en_polarity << 2) | (vsync_polarity << 1) | (hsync_polarity); mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); MDP_OUTP(MDP_BASE + LCDC_BASE + 0x4, hsync_ctrl); MDP_OUTP(MDP_BASE + LCDC_BASE + 0x8, vsync_period); MDP_OUTP(MDP_BASE + LCDC_BASE + 0xc, vsync_pulse_width * hsync_period); MDP_OUTP(MDP_BASE + LCDC_BASE + 0x10, display_hctl); MDP_OUTP(MDP_BASE + LCDC_BASE + 0x14, display_v_start); MDP_OUTP(MDP_BASE + LCDC_BASE + 0x18, display_v_end); MDP_OUTP(MDP_BASE + LCDC_BASE + 0x28, lcdc_border_clr); MDP_OUTP(MDP_BASE + LCDC_BASE + 0x2c, lcdc_underflow_clr); MDP_OUTP(MDP_BASE + LCDC_BASE + 0x30, lcdc_hsync_skew); MDP_OUTP(MDP_BASE + LCDC_BASE + 0x38, ctrl_polarity); MDP_OUTP(MDP_BASE + LCDC_BASE + 0x1c, active_hctl); MDP_OUTP(MDP_BASE + LCDC_BASE + 0x20, active_v_start); MDP_OUTP(MDP_BASE + LCDC_BASE + 0x24, active_v_end); mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); mdp_histogram_ctrl_all(TRUE); mdp4_overlay_lcdc_start(); mutex_unlock(&mfd->dma->ov_mutex); return ret; }
int mdp4_dtv_off(struct platform_device *pdev) { struct msm_fb_data_type *mfd; int ret = 0; int cndx = 0; int undx; struct vsycn_ctrl *vctrl; struct mdp4_overlay_pipe *pipe; struct vsync_update *vp; mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); vctrl = &vsync_ctrl_db[cndx]; mdp4_dtv_wait4vsync(cndx); atomic_set(&vctrl->vsync_resume, 0); complete_all(&vctrl->vsync_comp); pipe = vctrl->base_pipe; if (pipe != NULL) { mdp4_dtv_stop(mfd); /* sanity check, free pipes besides base layer */ mdp4_overlay_unset_mixer(pipe->mixer_num); if (hdmi_prim_display && mfd->ref_cnt == 0) { /* adb stop */ if (pipe->pipe_type == OVERLAY_TYPE_BF) mdp4_overlay_borderfill_stage_down(pipe); /* base pipe may change after borderfill_stage_down */ pipe = vctrl->base_pipe; mdp4_mixer_stage_down(pipe, 1); mdp4_overlay_pipe_free(pipe); /* pipe == rgb2 */ vctrl->base_pipe = NULL; } else { mdp4_mixer_stage_down(pipe, 1); mdp4_overlay_pipe_free(pipe); vctrl->base_pipe = NULL; } } mdp4_dtv_tg_off(vctrl); atomic_set(&vctrl->suspend, 1); if (vctrl->vsync_irq_enabled) { vctrl->vsync_irq_enabled = 0; vsync_irq_disable(INTR_PRIMARY_VSYNC, MDP_PRIM_VSYNC_TERM); } undx = vctrl->update_ndx; vp = &vctrl->vlist[undx]; if (vp->update_cnt) { /* * pipe's iommu will be freed at next overlay play * and iommu_drop statistic will be increased by one */ vp->update_cnt = 0; /* empty queue */ } mdp4_overlay_panel_mode_unset(MDP4_MIXER1, MDP4_PANEL_DTV); ret = panel_next_off(pdev); mdp_footswitch_ctrl(FALSE); /* Mdp clock disable */ mdp_clk_ctrl(0); pr_info("%s:\n", __func__); return ret; }
/* 3D side by side */ void mdp4_dsi_cmd_3d_sbys(struct msm_fb_data_type *mfd, struct msmfb_overlay_3d *r3d) { struct fb_info *fbi; int bpp; uint8 *src = NULL; int cndx = 0; struct vsycn_ctrl *vctrl; struct mdp4_overlay_pipe *pipe; vctrl = &vsync_ctrl_db[cndx]; pipe = vctrl->base_pipe; if (pipe == NULL) return; if (pipe->pipe_used == 0 || pipe->mixer_stage != MDP4_MIXER_STAGE_BASE) { pr_err("%s: NOT baselayer\n", __func__); return; } pipe->is_3d = r3d->is_3d; pipe->src_height_3d = r3d->height; pipe->src_width_3d = r3d->width; if (pipe->is_3d) mdp4_overlay_panel_3d(pipe->mixer_num, MDP4_3D_SIDE_BY_SIDE); else mdp4_overlay_panel_3d(pipe->mixer_num, MDP4_3D_NONE); fbi = mfd->fbi; if (pipe->is_3d) { bpp = fbi->var.bits_per_pixel / 8; pipe->src_height = pipe->src_height_3d; pipe->src_width = pipe->src_width_3d; pipe->src_h = pipe->src_height_3d; pipe->src_w = pipe->src_width_3d; pipe->dst_h = pipe->src_height_3d; pipe->dst_w = pipe->src_width_3d; pipe->srcp0_ystride = msm_fb_line_length(0, pipe->src_width, bpp); } else { /* 2D */ pipe->src_height = fbi->var.yres; pipe->src_width = fbi->var.xres; pipe->src_h = fbi->var.yres; pipe->src_w = fbi->var.xres; pipe->dst_h = fbi->var.yres; pipe->dst_w = fbi->var.xres; pipe->srcp0_ystride = fbi->fix.line_length; } pipe->src_y = 0; pipe->src_x = 0; pipe->dst_y = 0; pipe->dst_x = 0; pipe->srcp0_addr = (uint32)src; mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); mdp_clk_ctrl(1); mdp4_overlay_rgb_setup(pipe); mdp4_overlay_reg_flush(pipe, 1); mdp4_mixer_stage_up(pipe, 0); mdp4_overlayproc_cfg(pipe); mdp4_overlay_dmap_xy(pipe); mdp4_overlay_dmap_cfg(mfd, 0); mdp4_mixer_stage_commit(pipe->mixer_num); /* MDP cmd block disable */ mdp_clk_ctrl(0); mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); }
int mdp4_dsi_cmd_off(struct platform_device *pdev) { int ret = 0; int cndx = 0; struct msm_fb_data_type *mfd; struct vsycn_ctrl *vctrl; struct mdp4_overlay_pipe *pipe; struct vsync_update *vp; int undx; int need_wait, cnt; unsigned long flags; pr_debug("%s+: pid=%d\n", __func__, current->pid); mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); vctrl = &vsync_ctrl_db[cndx]; pipe = vctrl->base_pipe; if (pipe == NULL) { pr_err("%s: NO base pipe\n", __func__); return ret; } need_wait = 0; mutex_lock(&vctrl->update_lock); atomic_set(&vctrl->suspend, 1); complete_all(&vctrl->vsync_comp); pr_debug("%s: clk=%d pan=%d\n", __func__, vctrl->clk_enabled, vctrl->pan_display); if (vctrl->clk_enabled) need_wait = 1; mutex_unlock(&vctrl->update_lock); cnt = 0; if (need_wait) { while (vctrl->clk_enabled) { msleep(20); cnt++; if (cnt > 10) break; } } if (cnt > 10) { spin_lock_irqsave(&vctrl->spin_lock, flags); vctrl->clk_control = 0; vctrl->clk_enabled = 0; vctrl->expire_tick = 0; spin_unlock_irqrestore(&vctrl->spin_lock, flags); mipi_dsi_clk_cfg(0); mdp_clk_ctrl(0); pr_err("%s: Error, SET_CLK_OFF by force\n", __func__); } /* sanity check, free pipes besides base layer */ mdp4_overlay_unset_mixer(pipe->mixer_num); mdp4_mixer_stage_down(pipe, 1); mdp4_overlay_pipe_free(pipe); vctrl->base_pipe = NULL; undx = vctrl->update_ndx; vp = &vctrl->vlist[undx]; if (vp->update_cnt) { /* * pipe's iommu will be freed at next overlay play * and iommu_drop statistic will be increased by one */ vp->update_cnt = 0; /* empty queue */ } pr_debug("%s-:\n", __func__); return ret; }
void mdp4_dsi_cmd_overlay(struct msm_fb_data_type *mfd) { int cndx = 0; struct vsycn_ctrl *vctrl; struct mdp4_overlay_pipe *pipe; unsigned long flags; int clk_set_on = 0; mutex_lock(&mfd->dma->ov_mutex); vctrl = &vsync_ctrl_db[cndx]; if (!mfd->panel_power_on) { mutex_unlock(&mfd->dma->ov_mutex); return; } pipe = vctrl->base_pipe; if (pipe == NULL) { pr_err("%s: NO base pipe\n", __func__); mutex_unlock(&mfd->dma->ov_mutex); return; } mutex_lock(&vctrl->update_lock); if (atomic_read(&vctrl->suspend)) { mutex_unlock(&vctrl->update_lock); mutex_unlock(&mfd->dma->ov_mutex); pr_err("%s: suspended, no more pan display\n", __func__); return; } spin_lock_irqsave(&vctrl->spin_lock, flags); vctrl->clk_control = 0; vctrl->pan_display++; if (!vctrl->clk_enabled) { clk_set_on = 1; vctrl->clk_enabled = 1; vctrl->expire_tick = VSYNC_EXPIRE_TICK; } spin_unlock_irqrestore(&vctrl->spin_lock, flags); if (clk_set_on) { pr_debug("%s: SET_CLK_ON\n", __func__); mipi_dsi_clk_cfg(1); mdp_clk_ctrl(1); vsync_irq_enable(INTR_PRIMARY_RDPTR, MDP_PRIM_RDPTR_TERM); } mutex_unlock(&vctrl->update_lock); if (pipe->mixer_stage == MDP4_MIXER_STAGE_BASE) { mdp4_mipi_vsync_enable(mfd, pipe, 0); mdp4_overlay_setup_pipe_addr(mfd, pipe); mdp4_dsi_cmd_pipe_queue(0, pipe); } mdp4_overlay_mdp_perf_upd(mfd, 1); mdp4_dsi_cmd_pipe_commit(cndx, 1); mdp4_overlay_mdp_perf_upd(mfd, 0); mutex_unlock(&mfd->dma->ov_mutex); }
int mdp4_lcdc_off(struct platform_device *pdev) { int ret = 0; int cndx = 0; struct msm_fb_data_type *mfd; struct vsycn_ctrl *vctrl; struct mdp4_overlay_pipe *pipe; unsigned long flags; int need_wait = 0; mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); vctrl = &vsync_ctrl_db[cndx]; pipe = vctrl->base_pipe; atomic_set(&vctrl->suspend, 1); msleep(20); /* >= 17 ms */ if (pipe->ov_blt_addr) { spin_lock_irqsave(&vctrl->spin_lock, flags); if (vctrl->ov_koff != vctrl->ov_done) need_wait = 1; spin_unlock_irqrestore(&vctrl->spin_lock, flags); if (need_wait) mdp4_lcdc_wait4ov(0); } mdp_histogram_ctrl_all(FALSE); MDP_OUTP(MDP_BASE + LCDC_BASE, 0); lcdc_enabled = 0; if (pipe) { /* sanity check, free pipes besides base layer */ mdp4_overlay_unset_mixer(pipe->mixer_num); if (mfd->ref_cnt == 0) { /* adb stop */ if (pipe->pipe_type == OVERLAY_TYPE_BF) mdp4_overlay_borderfill_stage_down(pipe); /* base pipe may change after borderfill_stage_down */ pipe = vctrl->base_pipe; mdp4_mixer_stage_down(pipe, 1); mdp4_overlay_pipe_free(pipe); vctrl->base_pipe = NULL; } else { /* system suspending */ mdp4_mixer_stage_down(vctrl->base_pipe, 1); mdp4_overlay_iommu_pipe_free( vctrl->base_pipe->pipe_ndx, 1); } } vctrl->fake_vsync = 1; /* MDP clock disable */ mdp_clk_ctrl(0); mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); return ret; }
int mdp4_mddi_pipe_commit(int cndx, int wait) { 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 need_dmap_wait = 0; int need_ov_wait = 0; int cnt = 0, clk_set_on = 0; vctrl = &vsync_ctrl_db[0]; 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); spin_lock_irqsave(&vctrl->spin_lock, flags); vctrl->clk_control = 0; vctrl->pan_display++; if (!vctrl->clk_enabled) { clk_set_on = 1; vctrl->clk_enabled = 1; vctrl->expire_tick = VSYNC_EXPIRE_TICK; } spin_unlock_irqrestore(&vctrl->spin_lock, flags); if (clk_set_on) { pr_debug("%s: SET_CLK_ON\n", __func__); mdp_clk_ctrl(1); vsync_irq_enable(INTR_PRIMARY_RDPTR, MDP_PRIM_RDPTR_TERM); } /* free previous committed iommu back to pool */ mdp4_overlay_iommu_unmap_freelist(MDP4_MIXER0); spin_lock_irqsave(&vctrl->spin_lock, flags); if (pipe->ov_blt_addr) { /* Blt */ if (vctrl->blt_wait) { INIT_COMPLETION(vctrl->dmap_comp); need_dmap_wait = 1; } if (vctrl->ov_koff != vctrl->ov_done) { INIT_COMPLETION(vctrl->ov_comp); need_ov_wait = 1; } } else { /* direct out */ if (vctrl->dmap_koff != vctrl->dmap_done) { INIT_COMPLETION(vctrl->dmap_comp); pr_debug("%s: wait, ok=%d od=%d dk=%d dd=%d cpu=%d\n", __func__, vctrl->ov_koff, vctrl->ov_done, vctrl->dmap_koff, vctrl->dmap_done, smp_processor_id()); need_dmap_wait = 1; } } spin_unlock_irqrestore(&vctrl->spin_lock, flags); if (need_dmap_wait) { pr_debug("%s: wait4dmap\n", __func__); mdp4_mddi_wait4dmap(0); } if (need_ov_wait) { pr_debug("%s: wait4ov\n", __func__); mdp4_mddi_wait4ov(0); } if (pipe->ov_blt_addr) { if (vctrl->blt_end) { vctrl->blt_end = 0; pipe->ov_blt_addr = 0; pipe->dma_blt_addr = 0; } } if (vctrl->blt_change) { mdp4_overlayproc_cfg(pipe); mdp4_overlay_dmap_xy(pipe); vctrl->blt_change = 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(MDP4_MIXER0); pipe = vctrl->base_pipe; spin_lock_irqsave(&vctrl->spin_lock, flags); if (pipe->ov_blt_addr) { mdp4_mddi_blt_ov_update(pipe); pipe->ov_cnt++; vctrl->ov_koff++; INIT_COMPLETION(vctrl->ov_comp); vsync_irq_enable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM); } else { INIT_COMPLETION(vctrl->dmap_comp); vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM); vctrl->dmap_koff++; } pr_debug("%s: kickoff, pid=%d\n", __func__, current->pid); /* kickoff overlay engine */ mdp4_stat.kickoff_ov0++; outpdw(MDP_BASE + 0x0004, 0); mb(); /* make sure kickoff ececuted */ spin_unlock_irqrestore(&vctrl->spin_lock, flags); mdp4_stat.overlay_commit[pipe->mixer_num]++; if (wait) { if (pipe->ov_blt_addr) mdp4_mddi_wait4ov(0); else mdp4_mddi_wait4dmap(0); } return cnt; }
void msm_lcd_recovery(void) { struct msm_fb_data_type *mfd; struct fb_info *info = NULL; int ret; int i; int vsync_status; suspended_recovery_flg = 0; if (!num_registered_fb){ mipi_sharp_lcd_init_det_info(); return; } info = registered_fb[0]; if (!info){ mipi_sharp_lcd_init_det_info(); return; } lock_recovery(); if(mipi_dsi_get_err_contention_lp1_flag() == 3) { SHLCDC_ERRLOG_REC(FB,LCD,MSM_FB_KERL,EEVENTID_FB_RECOVERY_ERR,0); MSM_FB_WARNING("msm_lcd_recovery already retry over. return\n"); unlock_recovery(); return; } mfd = (struct msm_fb_data_type *)info->par; if(!mfd->panel_power_on) { SHLCDC_ERRLOG_REC(FB,LCD,MSM_FB_KERL,EEVENTID_FB_RECOVERY_ERR,1); MSM_FB_WARNING("msm_lcd_recovery already suspend. return\n"); suspended_recovery_flg = 1; unlock_recovery(); return; } mipi_sharp_stat_inc(SHDISP_STAT_INC_RECOVERY); mdp_clk_ctrl(1); vsync_status = mdp4_overlay_vsync_get_status(); if(vsync_status){ ret = mdp4_overlay_vsync_ctrl(info, 0); } SHLCDC_EVENTLOG_REC(FB,LCD,MSM_FB_KERL,EEVENTID_FB_RECOVERY,0); MSM_FB_WARNING("msm_lcd_recovery start\n"); lcd_recovering = LCD_RECOVERY_ACTIVE; for (i=0; i<LCD_RECOVERY_LOOP_MAX; i++) { msm_fb_suspend_sub_recovery(mfd); mipi_sharp_delay_us(40000); shdisp_api_do_recovery(); msm_fb_resume_sub_recovery(mfd); msm_fb_resume_sub_recovery_phase2(info); ret = shdisp_api_check_recovery(); if (ret == SHDISP_RESULT_SUCCESS) { lcd_recovering = LCD_RECOVERY_STOP; mipi_sharp_lcd_init_det_info(); SHLCDC_EVENTLOG_REC(FB,LCD,MSM_FB_KERL,EEVENTID_FB_RECOVERY,1); MSM_FB_WARNING("msm_lcd_recovery completed\n"); if(vsync_status){ ret = mdp4_overlay_vsync_ctrl(info, 1); } mdp_clk_ctrl(0); unlock_recovery(); return; } } lcd_recovering = LCD_RECOVERY_STOP; if(shdisp_api_get_mipi_dsi_det_recovery_flag()) { mipi_dsi_clr_err_int_mask0_b25(); } SHLCDC_ERRLOG_REC(FB,LCD,MSM_FB_KERL,EEVENTID_FB_RECOVERY_OVER,0); MSM_FB_ERR("msm_lcd_recovery retry over\n"); unlock_recovery(); }
int mdp4_dsi_video_off(struct platform_device *pdev) { int ret = 0; int cndx = 0; struct msm_fb_data_type *mfd; struct vsycn_ctrl *vctrl; struct mdp4_overlay_pipe *pipe; unsigned long flags; int need_wait = 0; mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); vctrl = &vsync_ctrl_db[cndx]; pipe = vctrl->base_pipe; atomic_set(&vctrl->suspend, 1); atomic_set(&vctrl->vsync_resume, 0); #ifdef CONFIG_PANTECH_LCD_FIX_VSYNC_ERROR_WHEN_RESTART_ONLY_ANDROID vctrl->vsync_irq_enabled = 0; #endif msleep(20); /* >= 17 ms */ complete_all(&vctrl->vsync_comp); if (pipe->ov_blt_addr) { spin_lock_irqsave(&vctrl->spin_lock, flags); if (vctrl->ov_koff != vctrl->ov_done) need_wait = 1; spin_unlock_irqrestore(&vctrl->spin_lock, flags); if (need_wait) mdp4_dsi_video_wait4ov(0); } mdp_histogram_ctrl_all(FALSE); MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0); dsi_video_enabled = 0; if (pipe) { /* sanity check, free pipes besides base layer */ mdp4_overlay_unset_mixer(pipe->mixer_num); if (mfd->ref_cnt == 0) { /* adb stop */ if (pipe->pipe_type == OVERLAY_TYPE_BF) mdp4_overlay_borderfill_stage_down(pipe); /* base pipe may change after borderfill_stage_down */ pipe = vctrl->base_pipe; mdp4_mixer_stage_down(pipe, 1); mdp4_overlay_pipe_free(pipe); vctrl->base_pipe = NULL; } else { /* system suspending */ mdp4_mixer_stage_down(vctrl->base_pipe, 1); mdp4_overlay_iommu_pipe_free( vctrl->base_pipe->pipe_ndx, 1); } } /* mdp clock off */ mdp_clk_ctrl(0); mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); return ret; }
int mdp4_dtv_off(struct platform_device *pdev) { struct msm_fb_data_type *mfd; int ret = 0; int cndx = 0; int undx; struct vsycn_ctrl *vctrl; struct mdp4_overlay_pipe *pipe; struct vsync_update *vp; int mixer = 0; mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); mutex_lock(&mfd->dma->ov_mutex); vctrl = &vsync_ctrl_db[cndx]; mdp4_dtv_wait4vsync(cndx); wake_up_interruptible_all(&vctrl->wait_queue); pipe = vctrl->base_pipe; if (pipe != NULL) { mixer = pipe->mixer_num; /* sanity check, free pipes besides base layer */ mdp4_overlay_unset_mixer(mixer); if (hdmi_prim_display && mfd->ref_cnt == 0) { /* adb stop */ if (pipe->pipe_type == OVERLAY_TYPE_BF) mdp4_overlay_borderfill_stage_down(pipe); /* pipe == rgb2 */ vctrl->base_pipe = NULL; } else { mdp4_mixer_stage_down(pipe, 1); mdp4_overlay_pipe_free(pipe, 1); vctrl->base_pipe = NULL; } } mdp4_dtv_tg_off(vctrl); atomic_set(&vctrl->suspend, 1); mdp4_overlay_panel_mode_unset(MDP4_MIXER1, MDP4_PANEL_DTV); undx = vctrl->update_ndx; vp = &vctrl->vlist[undx]; if (vp->update_cnt) { /* * pipe's iommu will be freed at next overlay play * and iommu_drop statistic will be increased by one */ pr_warn("%s: update_cnt=%d\n", __func__, vp->update_cnt); mdp4_dtv_pipe_clean(vp); } ret = panel_next_off(pdev); mdp_footswitch_ctrl(FALSE); /* * clean up ion freelist * there need two stage to empty ion free list * therefore need call unmap freelist twice */ mdp4_overlay_iommu_unmap_freelist(mixer); mdp4_overlay_iommu_unmap_freelist(mixer); /* Mdp clock disable */ mdp_clk_ctrl(0); mutex_unlock(&mfd->dma->ov_mutex); pr_info("%s:\n", __func__); return ret; }
int mdp4_lcdc_off(struct platform_device *pdev) { int ret = 0; int cndx = 0; struct msm_fb_data_type *mfd; struct vsycn_ctrl *vctrl; struct mdp4_overlay_pipe *pipe; struct vsync_update *vp; unsigned long flags; int undx, need_wait = 0; mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); vctrl = &vsync_ctrl_db[cndx]; pipe = vctrl->base_pipe; atomic_set(&vctrl->suspend, 1); atomic_set(&vctrl->vsync_resume, 0); msleep(20); /* */ complete_all(&vctrl->vsync_comp); if (pipe->ov_blt_addr) { spin_lock_irqsave(&vctrl->spin_lock, flags); if (vctrl->ov_koff != vctrl->ov_done) need_wait = 1; spin_unlock_irqrestore(&vctrl->spin_lock, flags); if (need_wait) mdp4_lcdc_wait4ov(0); } mdp_histogram_ctrl_all(FALSE); MDP_OUTP(MDP_BASE + LCDC_BASE, 0); lcdc_enabled = 0; if (vctrl->vsync_irq_enabled) { vctrl->vsync_irq_enabled = 0; vsync_irq_disable(INTR_PRIMARY_VSYNC, MDP_PRIM_VSYNC_TERM); } undx = vctrl->update_ndx; vp = &vctrl->vlist[undx]; if (vp->update_cnt) { /* */ vp->update_cnt = 0; /* */ } if (pipe) { /* */ mdp4_overlay_unset_mixer(pipe->mixer_num); if (mfd->ref_cnt == 0) { /* */ if (pipe->pipe_type == OVERLAY_TYPE_BF) mdp4_overlay_borderfill_stage_down(pipe); /* */ pipe = vctrl->base_pipe; mdp4_mixer_stage_down(pipe, 1); mdp4_overlay_pipe_free(pipe); vctrl->base_pipe = NULL; } else { /* */ mdp4_mixer_stage_down(vctrl->base_pipe, 1); mdp4_overlay_iommu_pipe_free( vctrl->base_pipe->pipe_ndx, 1); } } /* */ mdp_clk_ctrl(0); mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); return ret; }
int mdp4_dsi_video_off(struct platform_device *pdev) { int ret = 0; int cndx = 0; struct msm_fb_data_type *mfd; struct vsycn_ctrl *vctrl; struct mdp4_overlay_pipe *pipe; struct vsync_update *vp; unsigned long flags; int undx, need_wait = 0; mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); vctrl = &vsync_ctrl_db[cndx]; pipe = vctrl->base_pipe; atomic_set(&vctrl->suspend, 1); atomic_set(&vctrl->vsync_resume, 0); msleep(20); /* >= 17 ms */ complete_all(&vctrl->vsync_comp); if (pipe->ov_blt_addr) { spin_lock_irqsave(&vctrl->spin_lock, flags); if (vctrl->ov_koff != vctrl->ov_done) need_wait = 1; spin_unlock_irqrestore(&vctrl->spin_lock, flags); if (need_wait) mdp4_dsi_video_wait4ov(0); } MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0); dsi_video_enabled = 0; mdp_histogram_ctrl_all(FALSE); undx = vctrl->update_ndx; vp = &vctrl->vlist[undx]; if (vp->update_cnt) { /* * pipe's iommu will be freed at next overlay play * and iommu_drop statistic will be increased by one */ vp->update_cnt = 0; /* empty queue */ } if (pipe) { /* sanity check, free pipes besides base layer */ mdp4_overlay_unset_mixer(pipe->mixer_num); if (mfd->ref_cnt == 0) { /* adb stop */ if (pipe->pipe_type == OVERLAY_TYPE_BF) mdp4_overlay_borderfill_stage_down(pipe); /* base pipe may change after borderfill_stage_down */ pipe = vctrl->base_pipe; mdp4_mixer_stage_down(pipe, 1); mdp4_overlay_pipe_free(pipe); vctrl->base_pipe = NULL; msleep(20); } else { /* system suspending */ mdp4_mixer_stage_down(vctrl->base_pipe, 1); mdp4_overlay_iommu_pipe_free( vctrl->base_pipe->pipe_ndx, 1); } } if (vctrl->vsync_irq_enabled) { vctrl->vsync_irq_enabled = 0; vsync_irq_disable(INTR_PRIMARY_VSYNC, MDP_PRIM_VSYNC_TERM); } /* mdp clock off */ mdp_clk_ctrl(0); mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); return ret; }
int mdp4_lcdc_off(struct platform_device *pdev) { int ret = 0; int cndx = 0; struct msm_fb_data_type *mfd; struct vsycn_ctrl *vctrl; struct mdp4_overlay_pipe *pipe; struct vsync_update *vp; unsigned long flags; int undx, need_wait = 0; int mixer = 0; mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); mutex_lock(&mfd->dma->ov_mutex); vctrl = &vsync_ctrl_db[cndx]; pipe = vctrl->base_pipe; mdp4_lcdc_wait4vsync(cndx); wake_up_interruptible_all(&vctrl->wait_queue); if (pipe->ov_blt_addr) { spin_lock_irqsave(&vctrl->spin_lock, flags); if (vctrl->ov_koff != vctrl->ov_done) need_wait = 1; spin_unlock_irqrestore(&vctrl->spin_lock, flags); if (need_wait) mdp4_lcdc_wait4ov(0); } mdp_histogram_ctrl_all(FALSE); lcdc_enabled = 0; undx = vctrl->update_ndx; vp = &vctrl->vlist[undx]; if (vp->update_cnt) { /* * pipe's iommu will be freed at next overlay play * and iommu_drop statistic will be increased by one */ pr_warn("%s: update_cnt=%d\n", __func__, vp->update_cnt); mdp4_lcdc_pipe_clean(vp); } if (pipe) { /* sanity check, free pipes besides base layer */ mixer = pipe->mixer_num; mdp4_overlay_unset_mixer(mixer); if (mfd->ref_cnt == 0) { /* adb stop */ if (pipe->pipe_type == OVERLAY_TYPE_BF) mdp4_overlay_borderfill_stage_down(pipe); /* base pipe may change after borderfill_stage_down */ pipe = vctrl->base_pipe; mdp4_mixer_stage_down(pipe, 1); mdp4_overlay_pipe_free(pipe, 1); vctrl->base_pipe = NULL; } else { /* system suspending */ mdp4_mixer_stage_down(vctrl->base_pipe, 1); mdp4_overlay_iommu_pipe_free( vctrl->base_pipe->pipe_ndx, 1); } } mdp4_lcdc_tg_off(vctrl); atomic_set(&vctrl->suspend, 1); /* * clean up ion freelist * there need two stage to empty ion free list * therefore need call unmap freelist twice */ mdp4_overlay_iommu_unmap_freelist(mixer); mdp4_overlay_iommu_unmap_freelist(mixer); /* MDP clock disable */ mdp_clk_ctrl(0); mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); mutex_unlock(&mfd->dma->ov_mutex); return ret; }
int mdp4_dsi_cmd_off(struct platform_device *pdev) { int ret = 0; int cndx = 0; struct msm_fb_data_type *mfd; struct vsycn_ctrl *vctrl; struct mdp4_overlay_pipe *pipe; struct vsync_update *vp; int undx; int need_wait, cnt; unsigned long flags; int mixer = 0; pr_debug("%s+: pid=%d\n", __func__, current->pid); mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); mutex_lock(&mfd->dma->ov_mutex); vctrl = &vsync_ctrl_db[cndx]; pipe = vctrl->base_pipe; if (pipe == NULL) { pr_err("%s: NO base pipe\n", __func__); mutex_unlock(&mfd->dma->ov_mutex); return ret; } need_wait = 0; mutex_lock(&vctrl->update_lock); wake_up_interruptible_all(&vctrl->wait_queue); pr_debug("%s: clk=%d pan=%d\n", __func__, vctrl->clk_enabled, vctrl->pan_display); if (vctrl->clk_enabled) need_wait = 1; mutex_unlock(&vctrl->update_lock); cnt = 0; if (need_wait) { while (vctrl->clk_enabled) { msleep(20); cnt++; if (cnt > 10) break; } } if (cnt > 10) { spin_lock_irqsave(&vctrl->spin_lock, flags); vctrl->clk_control = 0; vctrl->clk_enabled = 0; vctrl->expire_tick = 0; spin_unlock_irqrestore(&vctrl->spin_lock, flags); mipi_dsi_clk_cfg(0); mdp_clk_ctrl(0); pr_err("%s: Error, SET_CLK_OFF by force\n", __func__); } if (vctrl->vsync_enabled) { vsync_irq_disable(INTR_PRIMARY_RDPTR, MDP_PRIM_RDPTR_TERM); vctrl->vsync_enabled = 0; } undx = vctrl->update_ndx; vp = &vctrl->vlist[undx]; if (vp->update_cnt) { /* * pipe's iommu will be freed at next overlay play * and iommu_drop statistic will be increased by one */ pr_warn("%s: update_cnt=%d\n", __func__, vp->update_cnt); mdp4_dsi_cmd_pipe_clean(vp); } if (pipe) { /* sanity check, free pipes besides base layer */ mixer = pipe->mixer_num; mdp4_overlay_unset_mixer(mixer); if (mfd->ref_cnt == 0) { /* adb stop */ if (pipe->pipe_type == OVERLAY_TYPE_BF) mdp4_overlay_borderfill_stage_down(pipe); /* base pipe may change after borderfill_stage_down */ pipe = vctrl->base_pipe; mdp4_mixer_stage_down(pipe, 1); mdp4_overlay_pipe_free(pipe, 1); vctrl->base_pipe = NULL; } else { /* system suspending */ mdp4_mixer_stage_down(pipe, 1); mdp4_overlay_iommu_pipe_free(pipe->pipe_ndx, 1); } } atomic_set(&vctrl->suspend, 1); /* * clean up ion freelist * there need two stage to empty ion free list * therefore need call unmap freelist twice */ mdp4_overlay_iommu_unmap_freelist(mixer); mdp4_overlay_iommu_unmap_freelist(mixer); mutex_unlock(&mfd->dma->ov_mutex); pr_debug("%s-:\n", __func__); return ret; }
int mdp4_dsi_video_on(struct platform_device *pdev) { int dsi_width; int dsi_height; int dsi_bpp; int dsi_border_clr; int dsi_underflow_clr; int dsi_hsync_skew; int hsync_period; int hsync_ctrl; int vsync_period; int display_hctl; int display_v_start; int display_v_end; int active_hctl; int active_h_start; int active_h_end; int active_v_start; int active_v_end; int ctrl_polarity; int h_back_porch; int h_front_porch; int v_back_porch; int v_front_porch; int hsync_pulse_width; int vsync_pulse_width; int hsync_polarity; int vsync_polarity; int data_en_polarity; int hsync_start_x; int hsync_end_x; uint8 *buf; unsigned int buf_offset; int bpp, ptype; struct fb_info *fbi; struct fb_var_screeninfo *var; struct msm_fb_data_type *mfd; struct mdp4_overlay_pipe *pipe; int ret = 0; int cndx = 0; struct vsycn_ctrl *vctrl; struct msm_panel_info *pinfo; vctrl = &vsync_ctrl_db[cndx]; mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); pinfo = &mfd->panel_info; if (!mfd) return -ENODEV; if (mfd->key != MFD_KEY) return -EINVAL; vctrl->mfd = mfd; vctrl->dev = mfd->fbi->dev; vctrl->blt_ctrl = pinfo->lcd.blt_ctrl; /* mdp clock on */ mdp_clk_ctrl(1); fbi = mfd->fbi; var = &fbi->var; bpp = fbi->var.bits_per_pixel / 8; buf = (uint8 *) fbi->fix.smem_start; buf_offset = calc_fb_offset(mfd, fbi, bpp); if (vctrl->base_pipe == NULL) { ptype = mdp4_overlay_format2type(mfd->fb_imgType); if (ptype < 0) printk(KERN_INFO "%s: format2type failed\n", __func__); pipe = mdp4_overlay_pipe_alloc(ptype, MDP4_MIXER0); if (pipe == NULL) { printk(KERN_INFO "%s: pipe_alloc failed\n", __func__); return -EBUSY; } pipe->pipe_used++; pipe->mixer_stage = MDP4_MIXER_STAGE_BASE; pipe->mixer_num = MDP4_MIXER0; pipe->src_format = mfd->fb_imgType; mdp4_overlay_panel_mode(pipe->mixer_num, MDP4_PANEL_DSI_VIDEO); ret = mdp4_overlay_format2pipe(pipe); if (ret < 0) printk(KERN_INFO "%s: format2type failed\n", __func__); pipe->ov_blt_addr = 0; pipe->dma_blt_addr = 0; vctrl->base_pipe = pipe; /* keep it */ mdp4_init_writeback_buf(mfd, MDP4_MIXER0); } else { pipe = vctrl->base_pipe; } atomic_set(&vctrl->suspend, 0); if (!(mfd->cont_splash_done)) { mfd->cont_splash_done = 1; MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0); mdp4_dsi_video_wait4vsync(0); mipi_dsi_controller_cfg(0); } pipe->src_height = fbi->var.yres; pipe->src_width = fbi->var.xres; pipe->src_h = fbi->var.yres; pipe->src_w = fbi->var.xres; pipe->src_y = 0; pipe->src_x = 0; pipe->dst_h = fbi->var.yres; pipe->dst_w = fbi->var.xres; pipe->srcp0_ystride = fbi->fix.line_length; pipe->bpp = bpp; if (mfd->display_iova) pipe->srcp0_addr = mfd->display_iova + buf_offset; else pipe->srcp0_addr = (uint32)(buf + buf_offset); pipe->dst_h = fbi->var.yres; pipe->dst_w = fbi->var.xres; mdp4_overlay_mdp_pipe_req(pipe, mfd); mdp4_calc_blt_mdp_bw(mfd, pipe); mdp4_overlay_dmap_xy(pipe); /* dma_p */ mdp4_overlay_dmap_cfg(mfd, 1); mdp4_overlay_rgb_setup(pipe); mdp4_overlayproc_cfg(pipe); mdp4_overlay_reg_flush(pipe, 1); mdp4_mixer_stage_up(pipe, 0); mdp4_mixer_stage_commit(pipe->mixer_num); /* * DSI timing setting */ h_back_porch = var->left_margin; h_front_porch = var->right_margin; v_back_porch = var->upper_margin; v_front_porch = var->lower_margin; hsync_pulse_width = var->hsync_len; vsync_pulse_width = var->vsync_len; dsi_border_clr = mfd->panel_info.lcdc.border_clr; dsi_underflow_clr = mfd->panel_info.lcdc.underflow_clr; dsi_hsync_skew = mfd->panel_info.lcdc.hsync_skew; dsi_width = mfd->panel_info.xres + mfd->panel_info.lcdc.xres_pad; dsi_height = mfd->panel_info.yres + mfd->panel_info.lcdc.yres_pad; dsi_bpp = mfd->panel_info.bpp; hsync_period = hsync_pulse_width + h_back_porch + dsi_width + h_front_porch; hsync_ctrl = (hsync_period << 16) | hsync_pulse_width; hsync_start_x = h_back_porch + hsync_pulse_width; hsync_end_x = hsync_period - h_front_porch - 1; display_hctl = (hsync_end_x << 16) | hsync_start_x; vsync_period = (vsync_pulse_width + v_back_porch + dsi_height + v_front_porch); display_v_start = ((vsync_pulse_width + v_back_porch) * hsync_period) + dsi_hsync_skew; display_v_end = ((vsync_period - v_front_porch) * hsync_period) + dsi_hsync_skew - 1; if (dsi_width != var->xres) { active_h_start = hsync_start_x + first_pixel_start_x; active_h_end = active_h_start + var->xres - 1; active_hctl = ACTIVE_START_X_EN | (active_h_end << 16) | active_h_start; } else { active_hctl = 0; } if (dsi_height != var->yres) { active_v_start = display_v_start + first_pixel_start_y * hsync_period; active_v_end = active_v_start + (var->yres) * hsync_period - 1; active_v_start |= ACTIVE_START_Y_EN; } else { active_v_start = 0; active_v_end = 0; } dsi_underflow_clr |= 0x80000000; /* enable recovery */ hsync_polarity = 0; vsync_polarity = 0; data_en_polarity = 0; ctrl_polarity = (data_en_polarity << 2) | (vsync_polarity << 1) | (hsync_polarity); mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x4, hsync_ctrl); MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x8, vsync_period * hsync_period); MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0xc, vsync_pulse_width * hsync_period); MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x10, display_hctl); MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x14, display_v_start); MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x18, display_v_end); MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x1c, active_hctl); MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x20, active_v_start); MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x24, active_v_end); MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x28, dsi_border_clr); MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x2c, dsi_underflow_clr); MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x30, dsi_hsync_skew); MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x38, ctrl_polarity); mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); mdp_histogram_ctrl_all(TRUE); mdp4_overlay_dsi_video_start(); return ret; }
int mdp4_dtv_off(struct platform_device *pdev) { struct msm_fb_data_type *mfd; int ret = 0; int cndx = 0; int undx; struct vsycn_ctrl *vctrl; struct mdp4_overlay_pipe *pipe; struct vsync_update *vp; int mixer = 0; mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); mutex_lock(&mfd->dma->ov_mutex); vctrl = &vsync_ctrl_db[cndx]; mdp4_dtv_wait4vsync(cndx); atomic_set(&vctrl->vsync_resume, 0); complete_all(&vctrl->vsync_comp); vctrl->wait_vsync_cnt = 0; pipe = vctrl->base_pipe; if (pipe != NULL) { mixer = pipe->mixer_num; mdp4_overlay_unset_mixer(mixer); if (hdmi_prim_display && mfd->ref_cnt == 0) { if (pipe->pipe_type == OVERLAY_TYPE_BF) mdp4_overlay_borderfill_stage_down(pipe); vctrl->base_pipe = NULL; } else { mdp4_mixer_stage_down(pipe, 1); mdp4_overlay_pipe_free(pipe, 1); vctrl->base_pipe = NULL; } } mdp4_dtv_tg_off(vctrl); atomic_set(&vctrl->suspend, 1); mdp4_overlay_panel_mode_unset(MDP4_MIXER1, MDP4_PANEL_DTV); undx = vctrl->update_ndx; vp = &vctrl->vlist[undx]; if (vp->update_cnt) { pr_warn("%s: update_cnt=%d\n", __func__, vp->update_cnt); mdp4_dtv_pipe_clean(vp); } ret = panel_next_off(pdev); #if 0 mdp_footswitch_ctrl(FALSE); #endif mdp4_overlay_iommu_unmap_freelist(mixer); mdp4_overlay_iommu_unmap_freelist(mixer); mdp_clk_ctrl(0); mutex_unlock(&mfd->dma->ov_mutex); pr_info("%s:\n", __func__); return ret; }