1 frame update
struct vsync_update { int update_cnt; /* pipes to be updated */ struct completion vsync_comp; struct mdp4_overlay_pipe plist[OVERLAY_PIPE_MAX]; };
enum { OVERLAY_PIPE_VG1, /* video/graphic */ OVERLAY_PIPE_VG2, OVERLAY_PIPE_RGB1, OVERLAY_PIPE_RGB2, OVERLAY_PIPE_RGB3, OVERLAY_PIPE_VG3, OVERLAY_PIPE_VG4, OVERLAY_PIPE_MAX }; enum { OVERLAY_TYPE_RGB, OVERLAY_TYPE_VIDEO, OVERLAY_TYPE_BF }; enum { MDP4_MIXER0, MDP4_MIXER1, MDP4_MIXER2, MDP4_MIXER_MAX }; enum { OVERLAY_PLANE_INTERLEAVED, OVERLAY_PLANE_PLANAR, OVERLAY_PLANE_PSEUDO_PLANAR }; enum { MDP4_MIXER_STAGE_UNUNSED, /* pipe not used */ MDP4_MIXER_STAGE_BASE, MDP4_MIXER_STAGE0, /* zorder 0 */ MDP4_MIXER_STAGE1, /* zorder 1 */ MDP4_MIXER_STAGE2, /* zorder 2 */ MDP4_MIXER_STAGE3, /* zorder 3 */ MDP4_MIXER_STAGE_MAX }; enum { MDP4_FRAME_FORMAT_LINEAR, MDP4_FRAME_FORMAT_ARGB_TILE, MDP4_FRAME_FORMAT_VIDEO_SUPERTILE }; enum { MDP4_CHROMA_RGB, MDP4_CHROMA_H2V1, MDP4_CHROMA_H1V2, MDP4_CHROMA_420 };
static struct vsycn_ctrl { struct device *dev; int inited; int update_ndx; int ov_koff; int ov_done; atomic_t suspend; atomic_t vsync_resume; int wait_vsync_cnt; int blt_change; int blt_free; int blt_ctrl; int sysfs_created; struct mutex update_lock; struct completion ov_comp; struct completion dmap_comp; struct completion vsync_comp; spinlock_t spin_lock; struct msm_fb_data_type *mfd; struct mdp4_overlay_pipe *base_pipe; struct vsync_update vlist[2]; int vsync_irq_enabled; ktime_t vsync_time; } vsync_ctrl_db[MAX_CONTROLLER];
struct mdp4_overlay_ctrl { struct mdp4_overlay_pipe plist[OVERLAY_PIPE_MAX]; struct mdp4_overlay_pipe *stage[MDP4_MIXER_MAX][MDP4_MIXER_STAGE_MAX]; struct mdp4_overlay_pipe *baselayer[MDP4_MIXER_MAX]; struct blend_cfg blend[MDP4_MIXER_MAX][MDP4_MIXER_STAGE_MAX]; uint32 mixer_cfg[MDP4_MIXER_MAX]; // mixer:混合器(名词); blend:混合(动词) uint32 flush[MDP4_MIXER_MAX]; struct iommu_free_list iommu_free[MDP4_MIXER_MAX]; uint32 dmap_cfg[5]; uint32 cs_controller; uint32 panel_3d; uint32 panel_mode; uint32 mixer0_played; uint32 mixer1_played; uint32 mixer2_played; } mdp4_overlay_db = { .cs_controller = CS_CONTROLLER_0, .plist = { { .pipe_type = OVERLAY_TYPE_RGB, .pipe_num = OVERLAY_PIPE_RGB1, // 2 .pipe_ndx = 1, }, { .pipe_type = OVERLAY_TYPE_RGB, .pipe_num = OVERLAY_PIPE_RGB2, // 3 .pipe_ndx = 2, }, { .pipe_type = OVERLAY_TYPE_VIDEO, .pipe_num = OVERLAY_PIPE_VG1, // 0 .pipe_ndx = 3, }, { .pipe_type = OVERLAY_TYPE_VIDEO, .pipe_num = OVERLAY_PIPE_VG2, // 1 .pipe_ndx = 4, }, { .pipe_type = OVERLAY_TYPE_BF, .pipe_num = OVERLAY_PIPE_RGB3, // 4, mixer0 .pipe_ndx = 5, .mixer_num = MDP4_MIXER0, }, { .pipe_type = OVERLAY_TYPE_BF, .pipe_num = OVERLAY_PIPE_VG3, // 5, mixer1 .pipe_ndx = 6, .mixer_num = MDP4_MIXER1, }, { .pipe_type = OVERLAY_TYPE_BF, .pipe_num = OVERLAY_PIPE_VG4, // 6, mixer2 .pipe_ndx = 7, .mixer_num = MDP4_MIXER2, }, }, }; static DEFINE_MUTEX(iommu_mutex); static struct mdp4_overlay_ctrl *ctrl = &mdp4_overlay_db;
The registers of Mobile Display Processor(MDP) are accessible by ARM CPU through the Peripheral Bus AHB interface. For read accesses, the number of cycles before data is available is variable depending on the register being read.
ARM registers:
NOTE: RGB3 and Video/Graphics3 Pipe are used for the border color feature in LM. These two registers don't have fetch logic and just provide a solid background color for LM 0/1.
MDP ARM register grouping:
Global general operation
Interrupts
EBI2 LCD parameters
MDDI parameters
DSI 1 command mode parameters(ID_MAP and TRIGGER_EN)
DSI 2 command mode parameters
Internal Memory Chip Select control register
Synchronization registers (VSYNC_CLK, MDP_CLK)
MGEN2MAXI control registers
Client0 - VG1 read, Client1 - VG2 read, Client2 - RGB1 read, Client3 - RGB2 read, Client4 - DMA_P Image read, Client5 - DMA_P Cursor read, Client6 - DMA_S read, Client7 - DMA_E Image read, Client8 - DMA_E Cursor read, Client9 - Overlay0 write, Client10
-Overlay1 write
Overlay processor registers (Layer Mixer0, Layer Mixer1, V/G1 pipe, V/G2 pipe, RGB1/2/3 pipe, V/G3 pipe, Layer mixer2)
Primary Display Driver Settings
Secondary Display Driver Settings
External Display Driver Settings
DSI2 Video Mode/LCDC Timing Generator
DTV Timing Generator
DSI1 Video Mode/LCDC Timing Generator
Test Bus and MISR Access(MDP_CLK, HCLK, DCLK, TV_CLK, DSI_PCLK, AXI_CLK)
log:
[ 1.287715] mipi_global_lcd_probe: enter
[ 1.288631] mipi_global_lcd_probe: enter
[ 1.288814] setting pdata->panel_info.fb_num to 3. type: 8
[ 1.320952] FrameBuffer[0] 540x960 size=6266880 bytes is registered successfully!
[ 1.322600] mipi_global_lcd_probe: exit
[ 1.323882] setting pdata->panel_info.fb_num to 1. type: 10
[ 1.324462] Inside writeback_driver_init
[ 1.325103] Inside writeback_probe
[ 1.327239] FrameBuffer[1] 1280x720 size=0 bytes is registered successfully!
[ 1.330749]
[ 1.330779] msm_vidc_enc: Inside vid_enc_init()
[ 1.332031]
[ 1.332031] msm_vidc_enc: Inside vid_enc_vcd_init()
----------------------------------probe--------------------顺序为:
c0d68278 t __initcall_msm_fb_init6
c0d6827c t __initcall_mdp_driver_init6
c0d68280 t __initcall_mipi_dsi_driver_init6
c0d68284 t __initcall_mipi_video_mipi_global_wvga_pt_init6
c0d68288 t __initcall_writeback_panel_init6
c0d6828c t __initcall_writeback_driver_init6
c0d68290 t __initcall_vidc_init6
c0d68294 t __initcall_vid_dec_init6
c0d68298 t __initcall_vid_enc_init6
c0d6829c t __initcall_vfb_init6
c0d682a0 t __initcall_pty_init6
c0d682a4 t __initcall_sysrq_init6
c0d682a8 t __initcall_smux_init6
c0d682ac t __initcall_smux_ctl_init6
c0d682b0 t __initcall_msm_serial_hs_init6
c0d682b4 t __initcall_msm_serial_hsl_init6
c0d682b8 t __initcall_rand_initialize6
c0d682bc t __initcall_msm_rng_init6
c0d682c0 t __initcall_msm_rotator_init6
-------------------------------------end--------------
lcd on:
[ 9.747047] mipi_global_lcd_on: lcd begin to open, cmds = 147
[ 9.917106] mipi_global_lcd_on: lcd has opened successfully.
[ 9.922661] ....................alloc count = 4, mixer:0,pipe.mixer_num:0, ptype:0, pipe index:1, type:0
[ 9.922722] mdp4_overlay_rgb_setup:.........................srcp0_addr:0x20000, srcp0_ystride:2176
[ 9.922722] mdp4_overlayproc_cfg:-----------------directout mode
[ 10.067083] ....................alloc count = 5, mixer:0,pipe.mixer_num:0, ptype:2, pipe index:5, type:2
[ 10.145093] mdp4_dsi_video_pipe_commit:----------- pipe->ov_blt_addr is ZERO
[ 10.739722] mdp4_dmap_done_dsi_video: ---------------------mdp4_dmap_done_dsi_video
[ 11.190019] mdp4_dmap_done_dsi_video: ---------------------mdp4_dmap_done_dsi_video
[ 11.391942] ....................alloc count = 6, mixer:0,pipe.mixer_num:0, ptype:0, pipe index:1, type:0
[ 11.415992] mdp4_overlay_play:............1.............srcp0_addr:0x700000, srcp0_ystride:2176
[ 11.425789] mdp4_overlay_play:............2.............srcp0_addr:0x700000, srcp0_ystride:2176
[ 11.435464] mdp4_overlay_mdp_perf_upd mdp clk is changed [1] from 0 to 59080000
[ 11.459209] mdp4_dsi_video_pipe_commit:----------- mdp4_overlay_vsync_commit
[ 11.465344] mdp4_overlay_rgb_setup:.........................srcp0_addr:0x700000, srcp0_ystride:2176
[ 11.490767] mdp4_dsi_video_pipe_commit:----------- mdp4_overlay_iommu_pipe_free
[ 11.523546] mdp4_dmap_done_dsi_video: ---------------------mdp4_dmap_done_dsi_video
[ 11.615351] mdp4_overlay_play:............1.............srcp0_addr:0x900000, srcp0_ystride:2176
[ 11.632137] mdp4_overlay_play:............2.............srcp0_addr:0x900000, srcp0_ystride:2176
[ 11.641141] mdp4_dsi_video_pipe_commit:----------- mdp4_overlay_vsync_commit
[ 11.648130] mdp4_overlay_rgb_setup:.........................srcp0_addr:0x900000, srcp0_ystride:2176
[ 11.670685] mdp4_dsi_video_pipe_commit:----------- mdp4_overlay_iommu_pipe_free
[ 11.690340] mdp4_dmap_done_dsi_video: ---------------------mdp4_dmap_done_dsi_video
[ 11.876972] mdp4_overlay_play:............1.............srcp0_addr:0x700000, srcp0_ystride:2176
[ 11.885914] mdp4_overlay_play:............2.............srcp0_addr:0x700000, srcp0_ystride:2176
[ 11.947169] mdp4_dsi_video_pipe_commit:----------- mdp4_overlay_vsync_commit
[ 11.953334] mdp4_overlay_rgb_setup:.........................srcp0_addr:0x700000, srcp0_ystride:2176
[ 11.967251] mdp4_dsi_video_pipe_commit:----------- mdp4_overlay_iommu_pipe_free
[ 11.973844] mdp4_dmap_done_dsi_video: ---------------------mdp4_dmap_done_dsi_video
[ 12.140149] pil_get: 'q6' depends_on = 'none', count: 10
[ 12.146497] apr_tal: SMD_EVENT_OPEN
[ 12.180741] mdp4_overlay_play:............1.............srcp0_addr:0x900000, srcp0_ystride:2176
[ 12.199999] mdp4_overlay_play:............2.............srcp0_addr:0x900000, srcp0_ystride:2176
[ 12.208026] mdp4_dsi_video_pipe_commit:----------- mdp4_overlay_vsync_commit
[ 12.214832] mdp4_overlay_rgb_setup:.........................srcp0_addr:0x900000, srcp0_ystride:2176
[ 12.237356] mdp4_dsi_video_pipe_commit:----------- mdp4_overlay_iommu_pipe_free
[ 12.257347] mdp4_dmap_done_dsi_video: ---------------------mdp4_dmap_done_dsi_video
[ 12.364718] mdp4_overlay_play:............1.............srcp0_addr:0x700000, srcp0_ystride:2176
[ 12.389989] mdp4_overlay_play:............2.............srcp0_addr:0x700000, srcp0_ystride:2176
[ 12.407172] mdp4_dsi_video_pipe_commit:----------- mdp4_overlay_vsync_commit
[ 12.413337] mdp4_overlay_rgb_setup:.........................srcp0_addr:0x700000, srcp0_ystride:2176
[ 12.427224] mdp4_dsi_video_pipe_commit:----------- mdp4_overlay_iommu_pipe_free
[ 12.440805] mdp4_dmap_done_dsi_video: ---------------------mdp4_dmap_done_dsi_video
[ 12.569479] mdp4_overlay_play:............1.............srcp0_addr:0x900000, srcp0_ystride:2176
[ 12.585197] mdp4_overlay_play:............2.............srcp0_addr:0x900000, srcp0_ystride:2176
[ 12.616908] mdp4_dsi_video_pipe_commit:----------- mdp4_overlay_vsync_commit
[ 12.623195] mdp4_overlay_rgb_setup:.........................srcp0_addr:0x900000, srcp0_ystride:2176
[ 12.667205] mdp4_dsi_video_pipe_commit:----------- mdp4_overlay_iommu_pipe_free
[ 12.674286] mdp4_dmap_done_dsi_video: ---------------------mdp4_dmap_done_dsi_video
[ 12.759529] mdp4_overlay_play:............1.............srcp0_addr:0x700000, srcp0_ystride:2176
[ 12.787242] mdp4_overlay_play:............2.............srcp0_addr:0x700000, srcp0_ystride:2176
[ 12.795116] mdp4_dsi_video_pipe_commit:----------- mdp4_overlay_vsync_commit
[ 12.805127] mdp4_overlay_rgb_setup:.........................srcp0_addr:0x700000, srcp0_ystride:2176
[ 12.827224] mdp4_dsi_video_pipe_commit:----------- mdp4_overlay_iommu_pipe_free
[ 12.841049] mdp4_dmap_done_dsi_video: ---------------------mdp4_dmap_done_dsi_video
[ 12.976957] mdp4_overlay_play:............1.............srcp0_addr:0x900000, srcp0_ystride:2176
[ 12.989317] mdp4_overlay_play:............2.............srcp0_addr:0x900000, srcp0_ystride:2176
[ 13.012757] mdp4_dsi_video_pipe_commit:----------- mdp4_overlay_vsync_commit
[ 13.027163] mdp4_overlay_rgb_setup:.........................srcp0_addr:0x900000, srcp0_ystride:2176
[ 13.035434] mdp4_dsi_video_pipe_commit:----------- mdp4_overlay_iommu_pipe_free
[ 13.047428] mdp4_dsi_video_pipe_commit:----------- pipe->ov_blt_addr is ZERO
[ 13.057836] mdp4_dmap_done_dsi_video: ---------------------mdp4_dmap_done_dsi_video
[ 13.092934] mdp4_overlay_play:............1.............srcp0_addr:0x700000, srcp0_ystride:2176
[ 13.118022] mdp4_overlay_play:............2.............srcp0_addr:0x700000, srcp0_ystride:2176
[ 13.125866] mdp4_dsi_video_pipe_commit:----------- mdp4_overlay_vsync_commit
[ 13.142377] mdp4_overlay_rgb_setup:.........................srcp0_addr:0x700000, srcp0_ystride:2176
[ 13.150801] mdp4_dsi_video_pipe_commit:----------- mdp4_overlay_iommu_pipe_free
[ 13.174607] mdp4_dmap_done_dsi_video: ---------------------mdp4_dmap_done_dsi_video
[ 13.243125] mdp4_overlay_play:............1.............srcp0_addr:0x900000, srcp0_ystride:2176
[ 13.267968] mdp4_overlay_play:............2.............srcp0_addr:0x900000, srcp0_ystride:2176
[ 13.275965] mdp4_dsi_video_pipe_commit:----------- mdp4_overlay_vsync_commit
[ 13.283076] mdp4_overlay_rgb_setup:.........................srcp0_addr:0x900000, srcp0_ystride:2176
[ 13.309079] mdp4_dsi_video_pipe_commit:----------- mdp4_overlay_iommu_pipe_free
[ 13.341370] mdp4_dmap_done_dsi_video: ---------------------mdp4_dmap_done_dsi_video
[ 13.360201] mdp4_overlay_play:............1.............srcp0_addr:0x700000, srcp0_ystride:2176
[ 13.387273] mdp4_overlay_play:............2.............srcp0_addr:0x700000, srcp0_ystride:2176
[ 13.395116] mdp4_dsi_video_pipe_commit:----------- mdp4_overlay_vsync_commit
[ 13.407111] mdp4_overlay_rgb_setup:.........................srcp0_addr:0x700000, srcp0_ystride:2176
[ 13.415443] mdp4_dsi_video_pipe_commit:----------- mdp4_overlay_iommu_pipe_free
[ 13.458110] mdp4_dmap_done_dsi_video: ---------------------mdp4_dmap_done_dsi_video
[ 13.466229] mdp4_overlay_play:............1.............srcp0_addr:0x900000, srcp0_ystride:2176
[ 13.487227] mdp4_overlay_play:............2.............srcp0_addr:0x900000, srcp0_ystride:2176
[ 13.495101] mdp4_dsi_video_pipe_commit:----------- mdp4_overlay_vsync_commit
[ 13.507126] mdp4_overlay_rgb_setup:.........................srcp0_addr:0x900000, srcp0_ystride:2176
mdp 处理数据并update流程:
ioctl调用:
static int msmfb_display_commit(struct fb_info *info, unsigned long *argp) { int ret; struct mdp_display_commit disp_commit; ret = copy_from_user(&disp_commit, argp, sizeof(disp_commit)); if (ret) { pr_err("%s:copy_from_user failed", __func__); return ret; } ret = msm_fb_pan_display_ex(info, &disp_commit); return ret; }
msm_fb_pan_display_ex() -> schedule_work(&mfd->commit_work);
a. INIT_WORK(&mfd->commit_work, msm_fb_commit_wq_handler); // 通过这个工作队列更新
b. 通过调用mdp4_overlay_commit
if (fb_backup->disp_commit.flags & MDP_DISPLAY_COMMIT_OVERLAY) { mdp4_overlay_commit(info); }
mdp4_overlay_mdp_perf_upd(mfd, 1); // Implementation, as follow: mdp_set_core_clk(perf_req->mdp_clk_rate); // 设置core时钟:mdp_clk_rate mdp_bus_scale_update_request(...); // bandwidth update if ((mfd->panel_info.pdest == DISPLAY_1 && // use_ov_blt isn't used perf_req->use_ov_blt[0] && !perf_cur->use_ov_blt[0])) { if (mfd->panel_info.type == MIPI_VIDEO_PANEL) mdp4_dsi_video_blt_start(mfd); }
c. 对于video panel调用以下的case
case MIPI_VIDEO_PANEL: mdp4_dsi_video_pipe_commit(0, 1); break;
d. mdp4_overlay_vsync_commit
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); // 这个小函数非常重要,提交了需要更新的framebuffer,下面具体分析此函数 } /* 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 */ } }
(1) Implementation: mdp4_overlay_vsync_commit
void mdp4_overlay_vsync_commit(struct mdp4_overlay_pipe *pipe) { if (pipe->pipe_type == OVERLAY_TYPE_VIDEO) mdp4_overlay_vg_setup(pipe); /* video/graphic pipe */ else mdp4_overlay_rgb_setup(pipe); /* rgb pipe 对于UI一般情况下就是rgb pipe了 */ pr_debug("%s: pipe=%x ndx=%d num=%d used=%d\n", __func__, (int) pipe, pipe->pipe_ndx, pipe->pipe_num, pipe->pipe_used); mdp4_overlay_reg_flush(pipe, 1); mdp4_mixer_stage_up(pipe, 0); }
(2) Implementation:mdp4_overlay_rgb_setup
void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe) { char *rgb_base; uint32 src_size, src_xy, dst_size, dst_xy; uint32 format, pattern; uint32 curr, mask; uint32 offset = 0; int pnum; pnum = pipe->pipe_num - OVERLAY_PIPE_RGB1; /* start from 0 */ rgb_base = MDP_BASE + MDP4_RGB_BASE; rgb_base += (MDP4_RGB_OFF * pnum); src_size = ((pipe->src_h << 16) | pipe->src_w); src_xy = ((pipe->src_y << 16) | pipe->src_x); dst_size = ((pipe->dst_h << 16) | pipe->dst_w); dst_xy = ((pipe->dst_y << 16) | pipe->dst_x); if ((pipe->src_x + pipe->src_w) > 0x7FF) { offset += pipe->src_x * pipe->bpp; src_xy &= 0xFFFF0000; } if ((pipe->src_y + pipe->src_h) > 0x7FF) { offset += pipe->src_y * pipe->src_width * pipe->bpp; src_xy &= 0x0000FFFF; } format = mdp4_overlay_format(pipe); pattern = mdp4_overlay_unpack_pattern(pipe); mdp4_scale_setup(pipe); mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); /* Ensure proper covert matrix loaded when color space swaps */ curr = inpdw(rgb_base + 0x0058); /* Don't touch bits you don't want to configure*/ mask = 0xFFFEFFFF; pipe->op_mode = (pipe->op_mode & mask) | (curr & ~mask); outpdw(rgb_base + 0x0000, src_size); /* MDP_RGB_SRC_SIZE */ outpdw(rgb_base + 0x0004, src_xy); /* MDP_RGB_SRC_XY */ outpdw(rgb_base + 0x0008, dst_size); /* MDP_RGB_DST_SIZE */ outpdw(rgb_base + 0x000c, dst_xy); /* MDP_RGB_DST_XY */ outpdw(rgb_base + 0x0010, pipe->srcp0_addr + offset);// 对应于源地址,传到寄存器中 outpdw(rgb_base + 0x0040, pipe->srcp0_ystride);// 这里需要进一步打印出地址再进一步确认和overlay_play中如何控制? outpdw(rgb_base + 0x0050, format);/* MDP_RGB_SRC_FORMAT */ outpdw(rgb_base + 0x0054, pattern);/* MDP_RGB_SRC_UNPACK_PATTERN */ if (format & MDP4_FORMAT_SOLID_FILL) { u32 op_mode = pipe->op_mode; op_mode &= ~(MDP4_OP_FLIP_LR + MDP4_OP_SCALEX_EN); op_mode &= ~(MDP4_OP_FLIP_UD + MDP4_OP_SCALEY_EN); outpdw(rgb_base + 0x0058, op_mode);/* MDP_RGB_OP_MODE */ } else { if (pipe->op_mode & MDP4_OP_FLIP_LR && mdp_rev >= MDP_REV_42) { /* Enable x-scaling bit to enable LR flip */ /* for MDP > 4.2 targets */ pipe->op_mode |= 0x01; } outpdw(rgb_base + 0x0058, pipe->op_mode);/* MDP_RGB_OP_MODE */ } outpdw(rgb_base + 0x005c, pipe->phasex_step); outpdw(rgb_base + 0x0060, pipe->phasey_step); mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); mdp4_stat.pipe[pipe->pipe_num]++; }
e. 启动时序引擎
/* start timing generator & mmu if they are not started yet */ mdp4_overlay_dsi_video_start(); // 启动dsi video 控制
f. 使能中断位,DMA_P_DONE
if (pipe->ov_blt_addr) { // 这个addr 默认未使用所以走else分支,所以只打开了DMA_P_DONE中断 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++; /* 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); // enable INTR_DMA_P_DONE(DMA_P Transfer done) }
static void vsync_irq_enable(int intr, int term) { unsigned long flag; spin_lock_irqsave(&mdp_spin_lock, flag); outp32(MDP_INTR_CLEAR, intr); mdp_intr_mask |= intr; outp32(MDP_INTR_ENABLE, mdp_intr_mask); mdp_enable_irq(term); spin_unlock_irqrestore(&mdp_spin_lock, flag); pr_debug("%s: IRQ-en done, term=%x\n", __func__, term); }
h. 中断,一个是vsync,一个是dmap done
if (isr & INTR_PRIMARY_VSYNC) { mdp4_stat.intr_vsync_p++; if (panel & MDP4_PANEL_LCDC) mdp4_primary_vsync_lcdc(); else if (panel & MDP4_PANEL_DSI_VIDEO) mdp4_primary_vsync_dsi_video(); }
if (isr & INTR_DMA_P_DONE) { mdp4_stat.intr_dma_p++; dma = &dma2_data; if (panel & MDP4_PANEL_LCDC) mdp4_dmap_done_lcdc(0); else if (panel & MDP4_PANEL_DSI_VIDEO) mdp4_dmap_done_dsi_video(0); }
2 LCD resume time
- 537.952815</span>] request_suspend_state: wakeup (3->0) at 537941084255 (2013-05-27 10:53:03.049466690 UTC)
- [ 537.962307] get_prop_batt_temp: batt_temp phy = 312 meas = 0xc02b17ecec479268
- [ 537.972256] report_state_of_charge: calculated_soc = 73,last_soc = 73,start_percent = -22,charge_time_us = 0,catch_up_time_us = 0
- [ 538.007202] =====enter in rmi_f01_resume=====
- [ 538.031893] report_state_of_charge: Reported SOC = 73
- [ 538.063360] get_prop_batt_ocv: get_prop_batt_ocv:ocv_uv =3910136,ibatt_ua =329800.
- [ 538.064703] get_prop_batt_temp: batt_temp phy = 314 meas = 0xecc33000
[ 538.131878] mipi_global_lcd_on: ready for opening lcd
- [ 538.312559] mipi_global_lcd_on: lcd is on, count = 147
- [ 538.365298] mdp4_overlay_mdp_perf_upd mdp clk is changed [1] from 0 to 59080000
-
-
按照log可以发现从请求wakeup到lcd on大概花费了360ms,所以开屏的过程还是比较慢的,这里还没计算再次打开背光的时间,这个也要通过mipi发给LCD(lcd提供背光的话)。而主要的停留是在mipi lcd on cmds的低速发送上等待时间比较长,这个dma搬运的时间持续了180ms,不过这里有147条开屏的cmds要通过mipi发给lcd,所以dma搬运的过程肯定会消耗不少时间。
- [ 594.616419] mipi_global_lcd_off: ready for closing lcd
- [ 594.837784] mipi_global_lcd_off: lcd is off, count = 2
- [ 594.891255] request_suspend_state: sleep (0->3) at 594875256577 (2013-05-27 11:10:12.737098649 UTC)
- [ 594.899893] =====enter in rmi_f01_suspend=====
- [ 597.610926] PM: suspend entry 2013-05-27 11:10:15.456769024 UTC
从log可以发现从LCD off到LCD完成off花费了220ms,这命令比LCD on的时间更长,现在原因还不太确定。不过总的来说LCD 的开屏和关屏时间还是比较长。所以在开屏和关屏期间需要注意背光的控制不能在开屏过程或者关屏过程进行!
Bug如下:
------ watchdog state ------
- [!!!!] Read b3af1000 from IMEM successfully!
- [!!!!] An FIQ occured on the system!
- running dump version 1
- Core 0 PC: mipi_dsi_isr+3c <c03026e4>
- Core 0 LR: uncached_logk_pc+20 <c007d8e8>
- [<c03026e4>] mipi_dsi_isr+0x3c
- [<c00d4798>] handle_irq_event_percpu+0xb0
- [<c00d49b4>] handle_irq_event+0x3c
- [<c00d75a0>] handle_fasteoi_irq+0xdc
- [<c00d3ffc>] generic_handle_irq+0x30
- [<c000efb0>] handle_IRQ+0x7c
- [<c00085b8>] gic_handle_irq+0x94
- [<c080aa40>] __irq_svc+0x40
- [<c0088184>] __do_softirq+0x4c
- [<c00887b0>] irq_exit+0x48
- [<c000efb4>] handle_IRQ+0x80
- [<c00085b8>] gic_handle_irq+0x94
- [<c080aa40>] __irq_svc+0x40
- [<c080a674>] _raw_spin_unlock_irqrestore+0x10
- [<c03c3d40>] pm8xxx_get_irq_stat+0x134
- [<c0550f14>] pm_chg_get_rt_status+0x34
- [<c0555590>] unplug_check_worker+0x70
- [<c009a950>] process_one_work+0x27c
- [<c009acf8>] worker_thread+0x1a0
- [<c009ec80>] kthread+0x80
- [<c000f130>] kernel_thread_exit+0x0
- Core 1 PC: go_wfi+4 <c0024a88>
- Core 1 LR: msm_pm_idle_enter+68 <c0057194>
- [ 62.812635] mdp4_mixer_blend_setup: Error: no bg_pipe at mixer=0
- [ 63.244925] setup_clocks: Failed to set fs_mdp tv_src_clk rate to 0 Hz.
- [ 63.250602] fs_mdp: failed to disable
- [ 63.531176] mipi_dsi_ahb_ctrl: ahb clks already ON
- [ 63.537097] mipi_dsi_clk_enable: mipi_dsi_clks already ON
- [ 63.741126] mipi_dsi_cmd_dma_tx: dma timeout error
- [ 63.981168] mipi_dsi_cmd_dma_tx: dma timeout error
- [ 64.181138] mipi_dsi_cmd_dma_tx: dma timeout error
-
-
Bug 引起的根源是在充电模式下,直接调用了写文件的方式来让kernel suspend/resume,然后suspend和resume的切换又非常快导致suspend未完全结束,resume又开始执行,所以导致了中断、dsi dma异常,有些地方触摸屏也异常,很明显这里应该利用通知的方式等待系统完成suspend或者resume,才再次切换到下一种状态!