From 1690f2c24372885c3bc16cc07b97e4aad750973d Mon Sep 17 00:00:00 2001 From: root Date: Sat, 14 Jul 2012 10:07:45 +0800 Subject: [PATCH] fix bugs of early suspend when display_pd is closed. --- drivers/media/video/rk30_camera_oneframe.c | 129 +++++++++++++-------- 1 file changed, 78 insertions(+), 51 deletions(-) diff --git a/drivers/media/video/rk30_camera_oneframe.c b/drivers/media/video/rk30_camera_oneframe.c index b576178e4693..1d5e368d540d 100755 --- a/drivers/media/video/rk30_camera_oneframe.c +++ b/drivers/media/video/rk30_camera_oneframe.c @@ -209,7 +209,7 @@ module_param(debug, int, S_IRUGO|S_IWUSR); *v0.x.b: specify the version is NOT sure stable. *v0.x.c: 1. add cif reset when resolution changed to avoid of collecting data erro 2. irq process is splitted to two step. - +*v0.x.e: fix bugs of early suspend when display_pd is closed. */ #define RK_CAM_VERSION_CODE KERNEL_VERSION(0, 2, 0xc) @@ -370,6 +370,7 @@ static DEFINE_MUTEX(camera_lock); static const char *rk_cam_driver_description = "RK_Camera"; static int rk_camera_s_stream(struct soc_camera_device *icd, int enable); +static void rk_camera_capture_process(struct work_struct *work); /* @@ -413,11 +414,17 @@ static int rk_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, } if (pcdev->camera_work == NULL) { + int wk_index = 0; + struct rk_camera_work *wk; pcdev->camera_work = kmalloc(sizeof(struct rk_camera_work)*(*count), GFP_KERNEL); if (pcdev->camera_work == NULL) { RKCAMERA_TR("\n %s kmalloc fail\n", __FUNCTION__); BUG(); } + for(;wk_index < *count;wk_index++){ + wk = pcdev->camera_work+wk_index; + INIT_WORK(&wk->work, rk_camera_capture_process); + } pcdev->camera_work_count = *count; } } @@ -603,10 +610,10 @@ static void rk_camera_capture_process(struct work_struct *work) scale_times = 1; } memset(&ipp_req, 0, sizeof(struct rk29_ipp_req)); - - down(&pcdev->zoominfo.sem); - ipp_req.timeout = 100; + + down(&pcdev->zoominfo.sem); + ipp_req.timeout = 3000; ipp_req.flag = IPP_ROT_0; // if(pcdev->icd->user_width != pcdev->zoominfo.vir_width) ipp_req.store_clip_mode =1; @@ -625,7 +632,7 @@ static void rk_camera_capture_process(struct work_struct *work) dst_y_size = pcdev->icd->user_width*pcdev->icd->user_height; for (h=0; hzoominfo.a.c.top + h*pcdev->zoominfo.a.c.height/scale_times)* pcdev->host_width + pcdev->zoominfo.a.c.left + w*pcdev->zoominfo.a.c.width/scale_times; src_uv_offset = (pcdev->zoominfo.a.c.top + h*pcdev->zoominfo.a.c.height/scale_times)* pcdev->host_width/2 @@ -642,22 +649,31 @@ static void rk_camera_capture_process(struct work_struct *work) // printk("ipp_req.dst0.YrgbMst = 0x%x , ipp_req.dst0.CbrMst = 0x%x\n",ipp_req.dst0.YrgbMst,ipp_req.dst0.CbrMst); // printk("%dx%d@(%d,%d)->%dx%d\n",pcdev->zoominfo.a.c.width,pcdev->zoominfo.a.c.height,pcdev->zoominfo.a.c.left,pcdev->zoominfo.a.c.top,pcdev->icd->user_width,pcdev->icd->user_height); // printk("ipp_req.src_vir_w:0x%x ipp_req.dst_vir_w :0x%x\n",ipp_req.src_vir_w ,ipp_req.dst_vir_w); - if (ipp_blit_sync(&ipp_req)) { + while(ipp_times-- > 0) + { + if (ipp_blit_sync(&ipp_req)){ + RKCAMERA_TR("ipp do erro,do again,ipp_times = %d!\n",ipp_times); + } + else{ + break; + } + } + if (ipp_times <= 0) + { spin_lock_irqsave(&pcdev->lock, flags); - vb->state = VIDEOBUF_ERROR; + vb->state = VIDEOBUF_NEEDS_INIT; spin_unlock_irqrestore(&pcdev->lock, flags); - - RKCAMERA_TR("Capture image(vb->i:0x%x) which IPP operated is error:\n",vb->i); - RKCAMERA_TR("widx:%d hidx:%d ",w,h); - RKCAMERA_TR("%dx%d@(%d,%d)->%dx%d\n",pcdev->zoominfo.a.c.width,pcdev->zoominfo.a.c.height,pcdev->zoominfo.a.c.left,pcdev->zoominfo.a.c.top,pcdev->icd->user_width,pcdev->icd->user_height); - RKCAMERA_TR("ipp_req.src0.YrgbMst:0x%x ipp_req.src0.CbrMst:0x%x \n", ipp_req.src0.YrgbMst,ipp_req.src0.CbrMst); - RKCAMERA_TR("ipp_req.src0.w:0x%x ipp_req.src0.h:0x%x \n",ipp_req.src0.w,ipp_req.src0.h); - RKCAMERA_TR("ipp_req.src0.fmt:0x%x\n",ipp_req.src0.fmt); - RKCAMERA_TR("ipp_req.dst0.YrgbMst:0x%x ipp_req.dst0.CbrMst:0x%x \n",ipp_req.dst0.YrgbMst,ipp_req.dst0.CbrMst); - RKCAMERA_TR("ipp_req.dst0.w:0x%x ipp_req.dst0.h:0x%x \n",ipp_req.dst0.w ,ipp_req.dst0.h); - RKCAMERA_TR("ipp_req.dst0.fmt:0x%x\n",ipp_req.dst0.fmt); - RKCAMERA_TR("ipp_req.src_vir_w:0x%x ipp_req.dst_vir_w :0x%x\n",ipp_req.src_vir_w ,ipp_req.dst_vir_w); - RKCAMERA_TR("ipp_req.timeout:0x%x ipp_req.flag :0x%x\n",ipp_req.timeout,ipp_req.flag); + RKCAMERA_TR("Capture image(vb->i:0x%x) which IPP operated is error:\n",vb->i); + RKCAMERA_TR("widx:%d hidx:%d ",w,h); + RKCAMERA_TR("%dx%d@(%d,%d)->%dx%d\n",pcdev->zoominfo.a.c.width,pcdev->zoominfo.a.c.height,pcdev->zoominfo.a.c.left,pcdev->zoominfo.a.c.top,pcdev->icd->user_width,pcdev->icd->user_height); + RKCAMERA_TR("ipp_req.src0.YrgbMst:0x%x ipp_req.src0.CbrMst:0x%x \n", ipp_req.src0.YrgbMst,ipp_req.src0.CbrMst); + RKCAMERA_TR("ipp_req.src0.w:0x%x ipp_req.src0.h:0x%x \n",ipp_req.src0.w,ipp_req.src0.h); + RKCAMERA_TR("ipp_req.src0.fmt:0x%x\n",ipp_req.src0.fmt); + RKCAMERA_TR("ipp_req.dst0.YrgbMst:0x%x ipp_req.dst0.CbrMst:0x%x \n",ipp_req.dst0.YrgbMst,ipp_req.dst0.CbrMst); + RKCAMERA_TR("ipp_req.dst0.w:0x%x ipp_req.dst0.h:0x%x \n",ipp_req.dst0.w ,ipp_req.dst0.h); + RKCAMERA_TR("ipp_req.dst0.fmt:0x%x\n",ipp_req.dst0.fmt); + RKCAMERA_TR("ipp_req.src_vir_w:0x%x ipp_req.dst_vir_w :0x%x\n",ipp_req.src_vir_w ,ipp_req.dst_vir_w); + RKCAMERA_TR("ipp_req.timeout:0x%x ipp_req.flag :0x%x\n",ipp_req.timeout,ipp_req.flag); goto do_ipp_err; } @@ -666,7 +682,6 @@ static void rk_camera_capture_process(struct work_struct *work) if (pcdev->icd_cb.sensor_cb) (pcdev->icd_cb.sensor_cb)(vb); - do_ipp_err: up(&pcdev->zoominfo.sem); wake_up(&(camera_work->vb->done)); @@ -738,7 +753,10 @@ static irqreturn_t rk_camera_irq(int irq, void *data) else if(pcdev->active){ printk("vb state is wrong ,del it \n"); list_del_init(&(pcdev->active->queue)); + pcdev->active->state = VIDEOBUF_NEEDS_INIT; + wake_up(&pcdev->active->done); pcdev->active = NULL; + } } if (pcdev->active == NULL) { @@ -752,7 +770,7 @@ static irqreturn_t rk_camera_irq(int irq, void *data) } if (CAM_WORKQUEUE_IS_EN()) { wk = pcdev->camera_work + vb->i; - INIT_WORK(&(wk->work), rk_camera_capture_process); + //INIT_WORK(&(wk->work), rk_camera_capture_process); wk->vb = vb; wk->pcdev = pcdev; queue_work(pcdev->camera_wq, &(wk->work)); @@ -901,6 +919,7 @@ RK_CAMERA_ACTIVE_ERR: static void rk_camera_deactivate(struct rk_camera_dev *pcdev) { //pcdev->active = NULL; + // printk("rk_camera_deactivate enter\n"); clk_disable(pcdev->aclk_cif); clk_disable(pcdev->hclk_cif); @@ -1003,6 +1022,7 @@ static void rk_camera_remove_device(struct soc_camera_device *icd) if (read_cif_reg(pcdev->base,CIF_CIF_CTRL) & ENABLE_CAPTURE) { rk_camera_s_stream(icd,0); } + //soft reset the registers #if 0 //has somthing wrong when suspend and resume now if(IS_CIF0()){ @@ -1014,7 +1034,6 @@ static void rk_camera_remove_device(struct soc_camera_device *icd) } #endif v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_DEACTIVATE,NULL); - rk_camera_deactivate(pcdev); //if stream off is not been executed,timer is running. if(pcdev->fps_timer.istarted){ hrtimer_cancel(&pcdev->fps_timer.timer); @@ -1028,7 +1047,7 @@ static void rk_camera_remove_device(struct soc_camera_device *icd) pcdev->camera_work = NULL; pcdev->camera_work_count = 0; } - + rk_camera_deactivate(pcdev); pcdev->active = NULL; pcdev->icd = NULL; pcdev->icd_cb.sensor_cb = NULL; @@ -1884,26 +1903,27 @@ static void rk_camera_reinit_work(struct work_struct *work) tmp_soc_cam_link = to_soc_camera_link(pcdev->icd); //dump regs { - RKCAMERA_DG("CIF_CIF_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CTRL)); - RKCAMERA_DG("CIF_CIF_INTEN = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTEN)); - RKCAMERA_DG("CIF_CIF_INTSTAT = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTSTAT)); - RKCAMERA_DG("CIF_CIF_FOR = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_FOR)); - RKCAMERA_DG("CIF_CIF_CROP = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CROP)); - RKCAMERA_DG("CIF_CIF_SET_SIZE = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE)); - RKCAMERA_DG("CIF_CIF_SCL_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL)); - RKCAMERA_DG("CRU_PCLK_REG30 = 0X%x\n",read_cru_reg(CRU_PCLK_REG30)); - RKCAMERA_DG("CIF_CIF_LAST_LINE = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_LINE)); + RKCAMERA_TR("CIF_CIF_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CTRL)); + RKCAMERA_TR("CIF_CIF_INTEN = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTEN)); + RKCAMERA_TR("CIF_CIF_INTSTAT = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTSTAT)); + RKCAMERA_TR("CIF_CIF_FOR = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_FOR)); + RKCAMERA_TR("CIF_CIF_CROP = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CROP)); + RKCAMERA_TR("CIF_CIF_SET_SIZE = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE)); + RKCAMERA_TR("CIF_CIF_SCL_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL)); + RKCAMERA_TR("CRU_PCLK_REG30 = 0X%x\n",read_cru_reg(CRU_PCLK_REG30)); + RKCAMERA_TR("CIF_CIF_LAST_LINE = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_LINE)); - RKCAMERA_DG("CIF_CIF_LAST_PIX = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_PIX)); - RKCAMERA_DG("CIF_CIF_VIR_LINE_WIDTH = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH)); - RKCAMERA_DG("CIF_CIF_LINE_NUM_ADDR = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LINE_NUM_ADDR)); - RKCAMERA_DG("CIF_CIF_FRM0_ADDR_Y = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y)); - RKCAMERA_DG("CIF_CIF_FRM0_ADDR_UV = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV)); - RKCAMERA_DG("CIF_CIF_FRAME_STATUS = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS)); + RKCAMERA_TR("CIF_CIF_LAST_PIX = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_PIX)); + RKCAMERA_TR("CIF_CIF_VIR_LINE_WIDTH = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH)); + RKCAMERA_TR("CIF_CIF_LINE_NUM_ADDR = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LINE_NUM_ADDR)); + RKCAMERA_TR("CIF_CIF_FRM0_ADDR_Y = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y)); + RKCAMERA_TR("CIF_CIF_FRM0_ADDR_UV = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV)); + RKCAMERA_TR("CIF_CIF_FRAME_STATUS = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS)); } - write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL)&(~ENABLE_CAPTURE))); - if(1/*pcdev->reinit_times++ > 0*/) + if(1/*pcdev->reinit_times++ >= 2*/) { + pcdev->stop_cif = true; + write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL)&(~ENABLE_CAPTURE))); RKCAMERA_DG("the reinit times = %d\n",pcdev->reinit_times); #if 0 while (!list_empty(&pcdev->capture)) { @@ -1917,11 +1937,12 @@ static void rk_camera_reinit_work(struct work_struct *work) } } #else - spin_lock_irqsave(pcdev->video_vq->irqlock, flags); + spin_lock_irqsave(pcdev->video_vq->irqlock, flags); for (index = 0; index < VIDEO_MAX_FRAME; index++) { if (NULL == pcdev->video_vq->bufs[index]) continue; - if (pcdev->video_vq->bufs[index]->state == VIDEOBUF_QUEUED) { + if (pcdev->video_vq->bufs[index]->state == VIDEOBUF_QUEUED) + { list_del_init(&pcdev->video_vq->bufs[index]->queue); pcdev->video_vq->bufs[index]->state = VIDEOBUF_NEEDS_INIT; wake_up_all(&pcdev->video_vq->bufs[index]->done); @@ -1932,7 +1953,7 @@ static void rk_camera_reinit_work(struct work_struct *work) #endif RKCAMERA_TR("the %d reinit times ,wake up video buffers!\n ",pcdev->reinit_times); - }else{ //the first time,just reinit sensor ,don't wake up vb + }/*else{ //the first time,just reinit sensor ,don't wake up vb // rk_cif_poweroff(pcdev); RKCAMERA_DG("first time to reinit\n"); // return; @@ -1981,7 +2002,7 @@ static void rk_camera_reinit_work(struct work_struct *work) write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL)|ENABLE_CAPTURE)); RKCAMERA_TR("first time Camera host haven't recevie data from sensor,Reinit sensor now! ret:0x%x\n",ret); - } + }*/ } static enum hrtimer_restart rk_camera_fps_func(struct hrtimer *timer) { @@ -1998,6 +2019,7 @@ static enum hrtimer_restart rk_camera_fps_func(struct hrtimer *timer) RKCAMERA_TR("Camera host haven't recevie data from sensor,Reinit sensor delay,last fps = %d,pcdev->fps = %d!\n",pcdev->last_fps,pcdev->fps); pcdev->camera_reinit_work.pcdev = pcdev; //INIT_WORK(&(pcdev->camera_reinit_work.work), rk_camera_reinit_work); + pcdev->reinit_times++; queue_work(pcdev->camera_wq,&(pcdev->camera_reinit_work.work)); } else if(!pcdev->timer_get_fps) { pcdev->timer_get_fps = true; @@ -2062,7 +2084,10 @@ static enum hrtimer_restart rk_camera_fps_func(struct hrtimer *timer) pcdev->fps_timer.timer.node.expires= ktime_add_us(pcdev->fps_timer.timer.node.expires, ktime_to_us(ktime_set(3, 0))); pcdev->fps_timer.timer._softexpires= ktime_add_us(pcdev->fps_timer.timer._softexpires, ktime_to_us(ktime_set(3, 0))); //return HRTIMER_NORESTART; - return HRTIMER_RESTART; + if(pcdev->reinit_times >=2) + return HRTIMER_NORESTART; + else + return HRTIMER_RESTART; } static int rk_camera_s_stream(struct soc_camera_device *icd, int enable) { @@ -2090,19 +2115,21 @@ static int rk_camera_s_stream(struct soc_camera_device *icd, int enable) hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL); pcdev->fps_timer.istarted = true; } else { - cif_ctrl_val &= ~ENABLE_CAPTURE; + //cancel timer before stop cif + ret = hrtimer_cancel(&pcdev->fps_timer.timer); + pcdev->fps_timer.istarted = false; + flush_work(&(pcdev->camera_reinit_work.work)); + cif_ctrl_val &= ~ENABLE_CAPTURE; spin_lock_irqsave(&pcdev->lock, flags); write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val); pcdev->stop_cif = true; spin_unlock_irqrestore(&pcdev->lock, flags); + // printk("flush work end!!!!!!!!!\n"); // mdelay(3*1000); // write_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS, 0x00000003);//frame1 has been ready to receive data,frame 2 is not used // write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF); /* clear vip interrupte single */ // write_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS,0); /* clear vip interrupte single */ - ret = hrtimer_cancel(&pcdev->fps_timer.timer); - pcdev->fps_timer.istarted = false; - flush_work(&(pcdev->camera_reinit_work.work)); flush_workqueue((pcdev->camera_wq)); RKCAMERA_DG("STREAM_OFF cancel timer and flush work:0x%x \n", ret); } @@ -2447,12 +2474,12 @@ static int rk_camera_probe(struct platform_device *pdev) if (pcdev->pdata && IS_CIF0()) { pcdev->vipmem_phybase = pcdev->pdata->meminfo.start; pcdev->vipmem_size = pcdev->pdata->meminfo.size; - RKCAMERA_DG("\n%s Memory(start:0x%x size:0x%x) for IPP obtain \n",__FUNCTION__, pcdev->pdata->meminfo.start,pcdev->pdata->meminfo.size); + RKCAMERA_TR("\n%s Memory(start:0x%x size:0x%x) for IPP obtain \n",__FUNCTION__, pcdev->pdata->meminfo.start,pcdev->pdata->meminfo.size); } else if (pcdev->pdata){ pcdev->vipmem_phybase = pcdev->pdata->meminfo_cif1.start; pcdev->vipmem_size = pcdev->pdata->meminfo_cif1.size; - RKCAMERA_DG("\n%s Memory(start:0x%x size:0x%x) for IPP obtain \n",__FUNCTION__, pcdev->pdata->meminfo.start,pcdev->pdata->meminfo.size); + RKCAMERA_TR("\n%s Memory(start:0x%x size:0x%x) for IPP obtain \n",__FUNCTION__, pcdev->pdata->meminfo.start,pcdev->pdata->meminfo.size); } else{ RKCAMERA_TR("\n%s Memory for IPP have not obtain! IPP Function is fail\n",__FUNCTION__); -- 2.34.1