MSM MDP4驱动显示过程

来源:互联网 发布:shell编程 编辑:程序博客网 时间:2024/05/16 06:46

记录了Qualcomm MSM8xxx MDP4上Overlay和Framebuffer显示过程,仅涉及驱动中部分,应用层参考Overlay HAL。

Overlay设置和提交过程

msmfb_overlay_set(struct fb_info *info, void __user *p)

è mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req)

申请pipe,并设置pipeclockbandwidth

int msmfb_overlay_play(struct fb_info *info, unsigned long *argp)

è int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req)

计算pipe输入缓冲地址、参数配置等;将request暂存,如对DSI CMD屏,是使用void mdp4_dsi_cmd_pipe_queue(int cndx, struct mdp4_overlay_pipe *pipe),而DSI VIDEO屏是使用void mdp4_dsi_video_pipe_queue(int cndx, struct mdp4_overlay_pipe *pipe)

base_pipe设置和提交,Layer Mix DMA

当送FBIOPUT_VSCREENINFOFBIOPAN_DISPLAY命令给FB设备时,最终会调用msm_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)

msm_fb_pan_display

è mdp_set_dma_pan_info(info, dirtyPtr, (var->activate == FB_ACTIVATE_VBL));   //设置DMA区域

è mdp_dma_pan_update(info);       //启动DMA,包括Layer Mixer合成和DMA输出

void mdp_dma_pan_update(struct fb_info *info)

è mfd->dma_fnc(mfd);

MIPI DSI CMD屏,该DMA函数是mdp4_dsi_cmd_overlay

[cpp] view plaincopy
  1. void mdp4_dsi_cmd_overlay(struct msm_fb_data_type *mfd)  
  2. {  
  3. ……  
  4.     pipe = vctrl->base_pipe;  
  5. ……  
  6.     if (pipe->mixer_stage == MDP4_MIXER_STAGE_BASE) {    // it is certain for base_pipe  
  7.                                   // it is setup in mdp4_overlay_update_dsi_cmd when dsi cmd panel is on.  
  8.         mdp4_mipi_vsync_enable(mfd, pipe, 0);  
  9.         mdp4_overlay_setup_pipe_addr(mfd, pipe);  
  10.         mdp4_dsi_cmd_pipe_queue(0, pipe);                   // arm the base pipe with framebuffer  
  11.     }  
  12.   
  13.     mdp4_overlay_mdp_perf_upd(mfd, 1);                            // level up the mdp performance  
  14.   
  15.     mutex_lock(&mfd->dma->ov_mutex);  
  16.     mdp4_dsi_cmd_pipe_commit(cndx, 0);                            // fire the overlay layer mixer and dma  
  17.     mdp4_overlay_mdp_perf_upd(mfd, 0);  
  18.     mutex_unlock(&mfd->dma->ov_mutex);  
  19. }  

其余相关代码引用并注释如下:

[cpp] view plaincopy
  1. int mdp4_dsi_cmd_pipe_commit(int cndx, int wait)  
  2. {  
  3.     int  i, undx;  
  4.     int mixer = 0;  
  5.     struct vsycn_ctrl *vctrl;  
  6.     struct vsync_update *vp;  
  7.     struct mdp4_overlay_pipe *pipe;  
  8.     struct mdp4_overlay_pipe *real_pipe;  
  9.     unsigned long flags;  
  10.     int need_dmap_wait = 0;  
  11.     int need_ov_wait = 0;  
  12.     int cnt = 0;  
  13.   
  14.                /**  
  15.                    *static struct vsycn_ctrl { … } vsync_ctrl_db [MAX_CONTROLLER] 
  16.                    * 在不同的显示器文件中有不同的定义,注意其是static的。 
  17.                    * 不同显示应用时关联不同的LayerMixer,所以同一种应用中, 
  18.                    * 使用具有同一mixer_num的pipe,mixer_num由应用分配的主pipe即该应用对应的 
  19.                    * vsync_ctrl_db的base_pipe指定。所有pipe的LayerMixer0是驱动中固定指定的。 
  20.                     */  
  21.     vctrl = &vsync_ctrl_db[0];  
  22.   
  23.     mutex_lock(&vctrl->update_lock);  
  24.     undx =  vctrl->update_ndx;  
  25.     vp = &vctrl->vlist[undx];  
  26.     pipe = vctrl->base_pipe;  
  27.     mixer = pipe->mixer_num;              // the Layer mixer used, LayerMixer0 here.  
  28.   
  29.     if (vp->update_cnt == 0) {  
  30.         mutex_unlock(&vctrl->update_lock);  
  31.         return cnt;  
  32.     }  
  33.   
  34.     //vctrl->update_ndx++;  
  35.     //vctrl->update_ndx &= 0x01;  
  36.     vp->update_cnt = 0;     /* reset */  
  37.     if (vctrl->blt_free) {  
  38.         vctrl->blt_free--;  
  39.         if (vctrl->blt_free == 0)  
  40.             mdp4_free_writeback_buf(vctrl->mfd, mixer);  
  41.     }  
  42.     mutex_unlock(&vctrl->update_lock);  
  43.   
  44.     /* free previous committed iommu back to pool */  
  45.     mdp4_overlay_iommu_unmap_freelist(mixer);  
  46.   
  47.     spin_lock_irqsave(&vctrl->spin_lock, flags);  
  48.     if (pipe->ov_blt_addr) {  
  49.         /* Blt */  
  50.         if (vctrl->blt_wait)  
  51.             need_dmap_wait = 1;  
  52.         if (vctrl->ov_koff != vctrl->ov_done) {  
  53.             INIT_COMPLETION(vctrl->ov_comp);  
  54.             need_ov_wait = 1;  
  55.         }  
  56.     } else {  
  57.         /* direct out */  
  58.         if (vctrl->dmap_koff != vctrl->dmap_done) {  
  59.             INIT_COMPLETION(vctrl->dmap_comp);  
  60.             pr_debug("%s: wait, ok=%d od=%d dk=%d dd=%d cpu=%d\n",  
  61.              __func__, vctrl->ov_koff, vctrl->ov_done,  
  62.             vctrl->dmap_koff, vctrl->dmap_done, smp_processor_id());  
  63.             need_dmap_wait = 1;  
  64.         }  
  65.     }  
  66.     spin_unlock_irqrestore(&vctrl->spin_lock, flags);  
  67.          /* setup completion for dmap wait in DIRECTOUT mode or overlay wait in BLT mode */  
  68.     if (need_dmap_wait) {  
  69.         pr_debug("%s: wait4dmap\n", __func__);  
  70.         mdp4_dsi_cmd_wait4dmap(0);  
  71.     }  
  72.   
  73.     if (need_ov_wait) {  
  74.         pr_debug("%s: wait4ov\n", __func__);  
  75.         mdp4_dsi_cmd_wait4ov(0);  
  76.     }  
  77.       
  78.     if (pipe->ov_blt_addr) {  
  79.         if (vctrl->blt_end) {  
  80.             vctrl->blt_end = 0;  
  81.             pipe->ov_blt_addr = 0;  
  82.             pipe->dma_blt_addr =  0;  
  83.             pr_info("%s: reset ov_blt_addr and dma_blt_addr\n", __func__);  
  84.         }  
  85.     }  
  86.   
  87.     /* if blt has some change, reconfig overlay proccessor and dmap*/  
  88.     if (vctrl->blt_change) {  
  89.         mdp4_overlayproc_cfg(pipe);  
  90.         mdp4_overlay_dmap_xy(pipe);  
  91.         vctrl->blt_change = 0;  
  92.     }  
  93.   
  94.     pipe = vp->plist;  
  95.                /*  
  96.                * All pipes used here is targeted to LayerMixer0.  
  97.                * These pipes are allocated with MIXER0 indeed,  
  98.                * and queued in vctrl->vlist[undx].plist[pipe->pipe_ndx - 1] again. 
  99.                * Obvious with target to MIXER0. 
  100.                */  
  101.     for (i = 0; i < OVERLAY_PIPE_MAX; i++, pipe++) {  
  102.         if (pipe->pipe_used) {  
  103.                            /* pipes in vp->plist maybe point to same physical pipe */  
  104.             cnt++;  
  105.             real_pipe = mdp4_overlay_ndx2pipe(pipe->pipe_ndx);  
  106.             if (real_pipe && real_pipe->pipe_used) {  
  107.                 /* pipe not unset */  
  108.                 mdp4_overlay_vsync_commit(pipe);   
  109.             }  
  110.             /* free previous iommu to freelist 
  111.             * which will be freed at next 
  112.             * pipe_commit 
  113.             */  
  114.             mdp4_overlay_iommu_pipe_free(pipe->pipe_ndx, 0);  
  115.             pipe->pipe_used = 0; /* clear */  
  116.         }  
  117.     }  
  118.   
  119.     /* tx dcs command if had any */  
  120.     mipi_dsi_cmdlist_commit(1);  
  121.          /* mixer here is MIXER0. Setup mixer’s each stage with pipe */  
  122.     mdp4_mixer_stage_commit(mixer);  
  123.   
  124.     pipe = vctrl->base_pipe;  
  125.     spin_lock_irqsave(&vctrl->spin_lock, flags);  
  126.     if (pipe->ov_blt_addr) {  
  127.         mdp4_dsi_cmd_blt_ov_update(pipe);  
  128.         pipe->ov_cnt++;  
  129.         vctrl->ov_koff++;  
  130.         INIT_COMPLETION(vctrl->ov_comp);  
  131.         vsync_irq_enable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);  
  132.     } else {  
  133.         INIT_COMPLETION(vctrl->dmap_comp);  
  134.         vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);  
  135.         vctrl->dmap_koff++;  
  136.     }  
  137.     pr_debug("%s: kickoff, pid=%d\n", __func__, current->pid);  
  138.     /* kickoff overlay engine */  
  139.     mdp4_stat.kickoff_ov0++;  
  140.     outpdw(MDP_BASE + 0x0004, 0);  
  141.     mb();  
  142.     spin_unlock_irqrestore(&vctrl->spin_lock, flags);  
  143.   
  144.     mdp4_stat.overlay_commit[pipe->mixer_num]++;  
  145.          /* wait for vsync */  
  146.     if (wait) {  
  147.         long long tick;  
  148.   
  149.         mdp4_dsi_cmd_wait4vsync(cndx, &tick);  
  150.     }  
  151.   
  152.     return cnt;  
  153. }  
  154. void mdp4_overlay_vsync_commit(struct mdp4_overlay_pipe *pipe)  
  155. {  
  156.     if (pipe->pipe_type == OVERLAY_TYPE_VIDEO)  
  157.         mdp4_overlay_vg_setup(pipe);    /* video/graphic pipe */  
  158.     else  
  159.         mdp4_overlay_rgb_setup(pipe);   /* rgb pipe */  
  160.   
  161.     pr_debug("%s: pipe=%x ndx=%d num=%d used=%d\n", __func__,  
  162.         (int) pipe, pipe->pipe_ndx, pipe->pipe_num, pipe->pipe_used);  
  163.     /* figure out the flush value to fill register */  
  164.          mdp4_overlay_reg_flush(pipe, 1);  
  165.          /* stage setup but not commit */  
  166.     mdp4_mixer_stage_up(pipe, 0);  
  167. }  
  168. void mdp4_mixer_stage_commit(int mixer)  
  169. {  
  170.     struct mdp4_overlay_pipe *pipe;  
  171.     int i, num;  
  172.     u32 data, stage;  
  173.     int off;  
  174.     unsigned long flags;  
  175.   
  176.     data = 0;  
  177.     for (i = MDP4_MIXER_STAGE_BASE; i < MDP4_MIXER_STAGE_MAX; i++) {  
  178.         pipe = ctrl->stage[mixer][i];  
  179.         if (pipe == NULL)  
  180.             continue;  
  181.         pr_debug("%s: mixer=%d ndx=%d stage=%d\n", __func__,  
  182.                     mixer, pipe->pipe_ndx, i);  
  183.         stage = pipe->mixer_stage;  
  184.         if (mixer >= MDP4_MIXER1)  
  185.             stage += 8;  
  186.         stage <<= (4 * pipe->pipe_num);  
  187.         data |= stage;  
  188.     }  
  189.   
  190.     /* 
  191.      * stage_commit may be called from overlay_unset 
  192.      * for command panel, mdp clocks may be off at this time. 
  193.      * so mdp clock enabled is necessary 
  194.      */  
  195.     mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);  
  196.     mdp_clk_ctrl(1);  
  197.   
  198.     mdp4_mixer_blend_setup(mixer);  
  199.   
  200.     off = 0;  
  201.     if (data != ctrl->mixer_cfg[mixer]) {  
  202.         ctrl->mixer_cfg[mixer] = data;  
  203.         if (mixer >= MDP4_MIXER2) {  
  204.             /* MDP_LAYERMIXER2_IN_CFG */  
  205.             off = 0x100f0;  
  206.         } else {  
  207.             /* mixer 0 or 1 */  
  208.             num = mixer + 1;  
  209.             num &= 0x01;  
  210.             data |= ctrl->mixer_cfg[num];  
  211.             off = 0x10100;  
  212.         }  
  213.         pr_debug("%s: mixer=%d data=%x flush=%x pid=%d\n", __func__,  
  214.                 mixer, data, ctrl->flush[mixer], current->pid);  
  215.     }  
  216.   
  217.     local_irq_save(flags);  
  218.     if (off)  
  219.         outpdw(MDP_BASE + off, data);  
  220.   
  221.     if (ctrl->flush[mixer]) {  
  222.         outpdw(MDP_BASE + 0x18000, ctrl->flush[mixer]);  
  223.         ctrl->flush[mixer] = 0;  
  224.     }  
  225.     local_irq_restore(flags);  
  226.     mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);  
  227.     mdp_clk_ctrl(0);  

原创粉丝点击