void mdp4_overlay_dsi_video_vsync_push(struct msm_fb_data_type *mfd, struct mdp4_overlay_pipe *pipe) { unsigned long flag; if (pipe->flags & MDP_OV_PLAY_NOWAIT) return; if (dsi_pipe->blt_addr) { mdp4_overlay_dsi_video_dma_busy_wait(mfd); mdp4_dsi_video_blt_ov_update(dsi_pipe); dsi_pipe->ov_cnt++; spin_lock_irqsave(&mdp_spin_lock, flag); outp32(MDP_INTR_CLEAR, INTR_OVERLAY0_DONE); mdp_intr_mask |= INTR_OVERLAY0_DONE; outp32(MDP_INTR_ENABLE, mdp_intr_mask); mdp_enable_irq(MDP_OVERLAY0_TERM); mfd->dma->busy = TRUE; mb(); /* make sure all registers updated */ spin_unlock_irqrestore(&mdp_spin_lock, flag); outpdw(MDP_BASE + 0x0004, 0); /* kickoff overlay engine */ mb(); mdp4_overlay_dsi_video_wait4event(mfd, INTR_DMA_P_DONE); } else { mdp4_overlay_dsi_video_wait4event(mfd, INTR_PRIMARY_VSYNC); } }
/* * make sure the MIPI_DSI_WRITEBACK_SIZE defined at boardfile * has enough space h * w * 3 * 2 */ static void mdp4_dsi_video_do_blt(struct msm_fb_data_type *mfd, int enable) { unsigned long flag; int data; int change = 0; spin_lock_irqsave(&mdp_spin_lock, flag); if (enable && dsi_pipe->blt_addr == 0) { dsi_pipe->blt_addr = dsi_pipe->blt_base; dsi_pipe->blt_cnt = 0; dsi_pipe->ov_cnt = 0; dsi_pipe->dmap_cnt = 0; change++; } else if (enable == 0 && dsi_pipe->blt_addr) { dsi_pipe->blt_addr = 0; change++; } pr_info("%s: enable=%d blt_addr=%x\n", __func__, enable, (int)dsi_pipe->blt_addr); spin_unlock_irqrestore(&mdp_spin_lock, flag); if (!change) return; /* * may need mutex here to sync with whom dsiable * timing generator */ data = inpdw(MDP_BASE + DSI_VIDEO_BASE); data &= 0x01; if (data) { /* timing generator enabled */ mdp4_overlay_dsi_video_wait4event(mfd, INTR_DMA_P_DONE); MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0); msleep(20); /* make sure last frame is finished */ mipi_dsi_controller_cfg(0); } mdp4_overlayproc_cfg(dsi_pipe); mdp4_overlay_dmap_xy(dsi_pipe); if (data) { /* timing generator enabled */ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 1); mdp4_overlay_dsi_video_wait4event(mfd, INTR_DMA_P_DONE); mdp4_overlay_dsi_video_wait4event(mfd, INTR_DMA_P_DONE); MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0); mipi_dsi_sw_reset(); mipi_dsi_controller_cfg(1); MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 1); } }
/* * make sure the MIPI_DSI_WRITEBACK_SIZE defined at boardfile * has enough space h * w * 3 * 2 */ static void mdp4_dsi_video_do_blt(struct msm_fb_data_type *mfd, int enable) { unsigned long flag; int data; int change = 0; mdp4_allocate_writeback_buf(mfd, MDP4_MIXER0); if (mfd->ov0_wb_buf->write_addr == 0) { pr_info("%s: no blt_base assigned\n", __func__); return; } spin_lock_irqsave(&mdp_spin_lock, flag); if (enable && dsi_pipe->ov_blt_addr == 0) { dsi_pipe->ov_blt_addr = mfd->ov0_wb_buf->write_addr; dsi_pipe->dma_blt_addr = mfd->ov0_wb_buf->read_addr; dsi_pipe->blt_cnt = 0; dsi_pipe->ov_cnt = 0; dsi_pipe->dmap_cnt = 0; mdp4_stat.blt_dsi_video++; change++; } else if (enable == 0 && dsi_pipe->ov_blt_addr) { dsi_pipe->ov_blt_addr = 0; dsi_pipe->dma_blt_addr = 0; change++; } if (!change) { spin_unlock_irqrestore(&mdp_spin_lock, flag); return; } pr_debug("%s: enable=%d ov_blt_addr=%x\n", __func__, enable, (int)dsi_pipe->ov_blt_addr); blt_cfg_changed = 1; spin_unlock_irqrestore(&mdp_spin_lock, flag); /* * may need mutex here to sync with whom dsiable * timing generator */ data = inpdw(MDP_BASE + DSI_VIDEO_BASE); data &= 0x01; if (data) { /* timing generator enabled */ mdp4_overlay_dsi_video_wait4event(mfd, INTR_DMA_P_DONE); msleep(20); } }
void mdp4_overlay_dsi_video_vsync_push(struct msm_fb_data_type *mfd, struct mdp4_overlay_pipe *pipe) { if (pipe->flags & MDP_OV_PLAY_NOWAIT) return; mdp4_overlay_dsi_video_wait4event(mfd, 1); /* change mdp clk while mdp is idle */ mdp4_set_perf_level(); }
static void mipi_mot_mipi_busy_wait(struct msm_fb_data_type *mfd) { /* Todo: consider to remove mdp4_dsi_cmd_dma_busy_wait * mipi_dsi_cmds_tx/rx wait for dma completion already. */ if (mfd->panel_info.type == MIPI_CMD_PANEL) { mdp4_dsi_cmd_dma_busy_wait(mfd); mipi_dsi_mdp_busy_wait(mfd); mdp4_dsi_blt_dmap_busy_wait(mfd); } else if (mfd->panel_info.type == MIPI_VIDEO_PANEL) { mdp4_overlay_dsi_video_wait4event(mfd, INTR_PRIMARY_VSYNC); } }
void mdp4_overlay_dsi_video_set_perf(struct msm_fb_data_type *mfd) { mdp4_overlay_dsi_video_wait4event(mfd, INTR_DMA_P_DONE); /* change mdp clk while mdp is idle */ mdp4_set_perf_level(); }
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; mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); if (!mfd) return -ENODEV; if (mfd->key != MFD_KEY) return -EINVAL; mdp4_overlay_ctrl_db_reset(); 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 (dsi_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__); dsi_pipe = pipe; /* keep it */ init_completion(&dsi_video_comp); mdp4_init_writeback_buf(mfd, MDP4_MIXER0); pipe->ov_blt_addr = 0; pipe->dma_blt_addr = 0; } else { pipe = dsi_pipe; } /* MDP cmd block enable */ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); if (!(mfd->cont_splash_done)) { mfd->cont_splash_done = 1; mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); mdp4_overlay_dsi_video_wait4event(mfd, INTR_DMA_P_DONE); /* disable timing generator */ MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0); mipi_dsi_controller_cfg(0); } if (is_mdp4_hw_reset()) { mdp4_hw_init(); outpdw(MDP_BASE + 0x0038, mdp4_display_intf); } 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_dmap_xy(pipe); /* dma_p */ mdp4_overlay_dmap_cfg(mfd, 1); mdp4_overlay_rgb_setup(pipe); mdp4_overlayproc_cfg(pipe); /* * 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_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); mdp4_overlay_reg_flush(pipe, 1); mdp4_mixer_stage_up(pipe); mdp_histogram_ctrl_all(TRUE); ret = panel_next_on(pdev); if (ret == 0) { mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_ON, FALSE); if (display_on != NULL) { msleep(50); display_on(pdev); } } /* MDP cmd block disable */ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); return ret; }
/* * make sure the MIPI_DSI_WRITEBACK_SIZE defined at boardfile * has enough space h * w * 3 * 2 */ static void mdp4_dsi_video_do_blt(struct msm_fb_data_type *mfd, int enable) { unsigned long flag; int data; int change = 0; mdp4_allocate_writeback_buf(mfd, MDP4_MIXER0); if (mfd->ov0_wb_buf->phys_addr == 0) { pr_info("%s: no blt_base assigned\n", __func__); return; } spin_lock_irqsave(&mdp_spin_lock, flag); if (enable && dsi_pipe->blt_addr == 0) { dsi_pipe->blt_addr = mfd->ov0_wb_buf->phys_addr; dsi_pipe->blt_cnt = 0; dsi_pipe->ov_cnt = 0; dsi_pipe->dmap_cnt = 0; mdp4_stat.blt_dsi_video++; change++; } else if (enable == 0 && dsi_pipe->blt_addr) { dsi_pipe->blt_addr = 0; change++; } if (!change) { spin_unlock_irqrestore(&mdp_spin_lock, flag); return; } pr_debug("%s: enable=%d blt_addr=%x\n", __func__, enable, (int)dsi_pipe->blt_addr); blt_cfg_changed = 1; #if defined (LGE_BLT_LOCKUP_WR) blt_ent++; #endif spin_unlock_irqrestore(&mdp_spin_lock, flag); /* * may need mutex here to sync with whom dsiable * timing generator */ data = inpdw(MDP_BASE + DSI_VIDEO_BASE); data &= 0x01; if (data) { /* timing generator enabled */ mdp4_overlay_dsi_video_wait4event(mfd, INTR_DMA_P_DONE); mdp4_overlay_dsi_video_wait4event(mfd, INTR_PRIMARY_VSYNC); } #if 0 /* removed by MSM8960AAAAANLYA1049A */ if (data) { /* timing generator enabled */ if (dsi_pipe->blt_addr) { MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 1); mdp4_overlay_dsi_video_prefill(mfd); mdp4_overlay_dsi_video_prefill(mfd); MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0); } mipi_dsi_sw_reset(); mipi_dsi_controller_cfg(1); MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 1); } #endif }
/* * make sure the MIPI_DSI_WRITEBACK_SIZE defined at boardfile * has enough space h * w * 3 * 2 */ static void mdp4_dsi_video_do_blt(struct msm_fb_data_type *mfd, int enable) { unsigned long flag; int data; int change = 0; mdp4_allocate_writeback_buf(mfd, MDP4_MIXER0); if (mfd->ov0_wb_buf->phys_addr == 0) { pr_info("%s: no blt_base assigned\n", __func__); return; } spin_lock_irqsave(&mdp_spin_lock, flag); if (enable && dsi_pipe->blt_addr == 0) { dsi_pipe->blt_addr = mfd->ov0_wb_buf->phys_addr; dsi_pipe->blt_cnt = 0; dsi_pipe->ov_cnt = 0; dsi_pipe->dmap_cnt = 0; mdp4_stat.blt_dsi_video++; change++; } else if (enable == 0 && dsi_pipe->blt_addr) { dsi_pipe->blt_addr = 0; change++; } #ifdef FEATURE_QUALCOMM_BUG_FIX_LCD_MDP_TIMING_GENERATOR_ON if (!change) { spin_unlock_irqrestore(&mdp_spin_lock, flag); return; } #endif pr_debug("%s: enable=%d blt_addr=%x\n", __func__, enable, (int)dsi_pipe->blt_addr); #ifdef FEATURE_QUALCOMM_BUG_FIX_LCD_MDP_TIMING_GENERATOR_ON blt_cfg_changed = 1; #endif spin_unlock_irqrestore(&mdp_spin_lock, flag); #ifndef FEATURE_QUALCOMM_BUG_FIX_LCD_MDP_TIMING_GENERATOR_ON if (!change) return; #endif /* * may need mutex here to sync with whom dsiable * timing generator */ data = inpdw(MDP_BASE + DSI_VIDEO_BASE); data &= 0x01; if (data) { /* timing generator enabled */ mdp4_overlay_dsi_video_wait4event(mfd, INTR_DMA_P_DONE); #ifdef FEATURE_QUALCOMM_BUG_FIX_LCD_MDP_TIMING_GENERATOR_ON // mdp4_overlay_dsi_video_wait4event(mfd, INTR_PRIMARY_VSYNC); if(enable) { mdp4_overlay_dsi_video_wait4event(mfd, INTR_DMA_P_DONE); } else { mdp4_overlay_dsi_video_wait4event(mfd, INTR_DMA_P_DONE); mdp4_overlay_dsi_video_wait4event(mfd, INTR_PRIMARY_VSYNC); } #else MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0); msleep(20); /* make sure last frame is finished */ mipi_dsi_controller_cfg(0); #endif } #ifndef FEATURE_QUALCOMM_BUG_FIX_LCD_MDP_TIMING_GENERATOR_ON mdp4_overlayproc_cfg(dsi_pipe); mdp4_overlay_dmap_xy(dsi_pipe); if (data) { /* timing generator enabled */ if (dsi_pipe->blt_addr) { MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 1); mdp4_overlay_dsi_video_prefill(mfd); mdp4_overlay_dsi_video_prefill(mfd); MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0); } mipi_dsi_sw_reset(); mipi_dsi_controller_cfg(1); MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 1); } #endif }