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.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
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,才再次切换到下一种状态!
3 LCD点亮注意事项
4 screenshot
#1: adb shell
#2: adb root
#3: screencap -p /data/xxx.png
#4: adb pull /data/xxx.png Your_pc_workspaceIf You're Running Ice Cream Sandwich (4.0) and Above
If you have a shiny new phone with Ice Cream Sandwich or above, screenshots are built right into your phone! Just press the Volume Down and Power buttons at the same time, hold them for a second, and your phone will take a screenshot. It'll show up in your Gallery app for you to share with whomever you wish!
5 Test MIPI Signal
1) 测试的引脚一定要注意选择一个便于测试的引脚来测试,这个引脚可能是在一个相连的元器件的一端,比如某个电阻、电容、二极管、或者其他小芯片的某个引脚的非接地端;
2 ) MIPI信号的低速数据可以通过读的方式来读出数据或者可以通过发送的低速波形来读数据,不过要注意读出的数据为以下字节序(orise9605a, 小字节序),比如0x51,发送的波形为1000_1010,由于波形中含有协议部分的其他字节,另外要注意发送是LWRITE还是WRITE,如果是LWRITE的话,将是0x39,长包的格式比短包多一些;如果是WRITE的话,将是0x13,也就是0'b1100_1000,我们观察波形来验证我所说的是否是正确的:
发现0x51和0x13了么?OK,根据这个波形,证明结果是符合预期的。
3) 示波器的使用normal模式一般作为触发;auto模式一般作为持续更新;
4)HS swing / LP swing
5) 注意调节触发方式,从而将能保证触发刚好到达你所需要的波形处;
6)orise driver ic应该在LP00或者LP11时进行reset,并且拉高后需要保持一段时间,其他状态下driver ic行为可能异常;
如果复位发生在LP11然后后面出现类似于高速的信号,可能会使driver IC行为异常,但是波形却无法看出时序有任何问题,如下图所示:
上图中clock and data lane同时出现了一个类似电容放电的波形,这里可能是phy的复位,此过程根据系统延时时间会略有不同,一般15ms左右,下面一副图看起来更加标准一些,不过这个曲线看起来有点华丽,所以失去了真实。下面我们继续讨论复位后的行为,根据上图,我们可以看到数据线上有许多稀疏的拉到0的或者密集的拉到0的波形,实际上当展开后,你将发现密集的往往中间将会是高速信号,而稀疏的可能是vsync或者低速cmd信号。
回到主题的内容,既然这里有个持续15ms左右的200mV脉冲,那我们的reset位置放在何处比较好呢?由于此波形是从lk跳转到kernel的情形,复位前data和clock lane的状态为LP11,当phy复位时data线和clock线同时被拉到200mV,看起来200mV是pmos放电无法到GND的结果,假设把lcd driver IC复位放在这个phy复位前,发现一个严重的问题,就是这个时候让driver IC勿认为当前host请求进入了高速,driver IC也进入high speed mode,由于后面还需要给driver IC发送on cmd,这些on cmd有两种:1种可以在高速模式下发送,也就是cmd1,;还一种一般是在低速模式下发送,这种只有单个命令的指令在高速下发送才可以成功,有多个parameter的指令都无法发送成功。而当前driver IC处在它自己认为的高速状态(实际只是host端的phy复位信号),导致了cmd2的多个parameter的cmd发送无法成功,从而进一步将会导致首次lcd无法正常显示图像,此种复位波形如下:
GREEN: Reset Signal Yellow:Data Lane
根据这个波形可以发现,其实host端已经将所有的cmd发送给了driver IC,只是driver勿认了当前的时序,导致cmd无法被成功执行;既然这样会导致这个问题,那我们干脆不去复位不是就可以了,如果从可以工作来说这样做,确实可以使首次lcd被点亮,但是其实这样也是有问题的,因为首次的cmd始终没有被正常发送给driver IC,所以如果前一次lk的cmds和kernel中cmds不完全匹配或者几乎不一致也会导致显示画面效果不是你想要得效果,所以这样做依然是有风险的,最好的方式就是把复位推后到host phy复位完成后,实际测试下来这种方式是最理想的效果,如下图所示:
sleep in -> sleep out
lk -> kernel
现在可以发现复位信号到了host phy复位后,cmds的发送也相应的推后了,实测这种方式能较好的工作,测试中还发现了一个问题,目前还没完全分析出来,那就是host端复位的实际时机,比如我们观察以下的波形可以一个有趣的现象,观察波形我们可以发现driver IC的复位刚好在host端phy的复位波形中,如图:
It's fun.
7)避免lcd在从bootloader切换到kernel闪屏的一种有效的办法是先发背光为0(如果lcd当前为开的情况下);
8)仔细分析波形,并理解时序,不放过每一个可能的细节。
本文详细解读了MIPIDisplayProcessor(MDP)在更新流程中的关键步骤,包括ioctl调用、工作队列更新、overlay管道更新、颜色配置、时序引擎启动与中断处理,以及LCD开屏和关屏注意事项。同时,文章探讨了MIPIDisplayProcessor(MDP)在不同场景下的表现,如充电模式下快速suspend/resume导致的中断和dma异常问题,以及LCD背光测试方法和显示原理。此外,文章还提供了MIPIDisplayProcessor(MDP)与其他组件交互的实例,以及测试MIPISignal的方法和注意事项。
1万+

被折叠的 条评论
为什么被折叠?



