From 82a500834e1ed52904732f2c5dbb28b415e15e56 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 20 Aug 2012 16:18:30 +0800 Subject: [PATCH] camera rk30: add scale by arm,rga and pp. --- arch/arm/mach-rk30/include/mach/rk30_camera.h | 18 + drivers/media/video/rk30_camera_oneframe.c | 665 ++++++++++++++++-- 2 files changed, 614 insertions(+), 69 deletions(-) diff --git a/arch/arm/mach-rk30/include/mach/rk30_camera.h b/arch/arm/mach-rk30/include/mach/rk30_camera.h index 85391efff2e3..b8539fe86357 100755 --- a/arch/arm/mach-rk30/include/mach/rk30_camera.h +++ b/arch/arm/mach-rk30/include/mach/rk30_camera.h @@ -35,5 +35,23 @@ #include +#define CONFIG_CAMERA_SCALE_CROP_MACHINE RK_CAM_SCALE_CROP_IPP + +#if (CONFIG_CAMERA_SCALE_CROP_MACHINE==RK_CAM_SCALE_CROP_ARM) + #define CAMERA_SCALE_CROP_MACHINE "arm" +#elif (CONFIG_CAMERA_SCALE_CROP_MACHINE==RK_CAM_SCALE_CROP_IPP) + #define CAMERA_SCALE_CROP_MACHINE "ipp" +#elif (CONFIG_CAMERA_SCALE_CROP_MACHINE==RK_CAM_SCALE_CROP_RGA) + #define CAMERA_SCALE_CROP_MACHINE "rga" +#elif (CONFIG_CAMERA_SCALE_CROP_MACHINE==RK_CAM_SCALE_CROP_PP) + #define CAMERA_SCALE_CROP_MACHINE "pp" +#endif + +#if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_ARM) + #define CAMERA_VIDEOBUF_ARM_ACCESS 1 +#else + #define CAMERA_VIDEOBUF_ARM_ACCESS 0 +#endif + #endif diff --git a/drivers/media/video/rk30_camera_oneframe.c b/drivers/media/video/rk30_camera_oneframe.c index b77d345e94ce..768760ed7b7c 100755 --- a/drivers/media/video/rk30_camera_oneframe.c +++ b/drivers/media/video/rk30_camera_oneframe.c @@ -38,7 +38,8 @@ #include #include #include - +#include +#include "../../video/rockchip/rga/rga.h" #if defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK31) #include #include @@ -47,8 +48,9 @@ #if defined(CONFIG_ARCH_RK2928) #include +#include "../../video/rockchip/rga/rga.h" #endif - +#include static int debug ; module_param(debug, int, S_IRUGO|S_IWUSR); @@ -230,6 +232,7 @@ module_param(debug, int, S_IRUGO|S_IWUSR); *v0.x.e: fix bugs of early suspend when display_pd is closed. *v0.x.f: fix calculate ipp memory size is enough or not in try_fmt function; *v0.x.11: fix struct rk_camera_work may be reentrant +*v0.x.13: add scale by arm,rga and pp. */ #define RK_CAM_VERSION_CODE KERNEL_VERSION(0, 2, 0x11) @@ -305,8 +308,17 @@ struct rk_camera_zoominfo struct semaphore sem; struct v4l2_crop a; int vir_width; + int vir_height; int zoom_rate; }; +#if CAMERA_VIDEOBUF_ARM_ACCESS +struct rk29_camera_vbinfo +{ + unsigned int phy_addr; + void __iomem *vir_addr; + unsigned int size; +}; +#endif struct rk_camera_timer{ struct rk_camera_dev *pcdev; struct hrtimer timer; @@ -337,10 +349,14 @@ struct rk_camera_dev unsigned int pixfmt; //for ipp unsigned int vipmem_phybase; + void __iomem *vipmem_virbase; unsigned int vipmem_size; unsigned int vipmem_bsize; - - int host_width; //croped size +#if CAMERA_VIDEOBUF_ARM_ACCESS + struct rk29_camera_vbinfo *vbinfo; + unsigned int vbinfo_count; +#endif + int host_width; int host_height; int host_left; //sensor output size ? int host_top; @@ -406,13 +422,25 @@ static int rk_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, struct soc_camera_device *icd = vq->priv_data; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct rk_camera_dev *pcdev = ici->priv; - int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, - icd->current_fmt->host_fmt); - int bytes_per_line_host = soc_mbus_bytes_per_line(pcdev->host_width, - icd->current_fmt->host_fmt); - unsigned int i; + unsigned int i; struct rk_camera_work *wk; + struct soc_mbus_pixelfmt fmt; + int bytes_per_line; + int bytes_per_line_host; + fmt.packing = SOC_MBUS_PACKING_1_5X8; + + bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, + icd->current_fmt->host_fmt); + if(icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_RGB565) + bytes_per_line_host = soc_mbus_bytes_per_line(pcdev->host_width, + &fmt); + else if(icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_RGB24) + bytes_per_line_host = pcdev->host_width*3; + else + bytes_per_line_host = soc_mbus_bytes_per_line(pcdev->host_width, + icd->current_fmt->host_fmt); + printk("user code = %d,packing = %d",icd->current_fmt->code,fmt.packing); dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size); if (bytes_per_line_host < 0) @@ -453,7 +481,22 @@ static int rk_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, } pcdev->camera_work_count = (*count); } - +#if CAMERA_VIDEOBUF_ARM_ACCESS + if (pcdev->vbinfo && (pcdev->vbinfo_count != *count)) { + kfree(pcdev->vbinfo); + pcdev->vbinfo = NULL; + pcdev->vbinfo_count = 0x00; + } + + if (pcdev->vbinfo == NULL) { + pcdev->vbinfo = kzalloc(sizeof(struct rk29_camera_vbinfo)*(*count), GFP_KERNEL); + if (pcdev->vbinfo == NULL) { + RKCAMERA_TR("\n %s vbinfo kmalloc fail\n", __FUNCTION__); + BUG(); + } + pcdev->vbinfo_count = *count; + } +#endif } pcdev->video_vq = vq; RKCAMERA_DG("%s..%d.. videobuf size:%d, vipmem_buf size:%d, count:%d \n",__FUNCTION__,__LINE__, *size,pcdev->vipmem_size, *count); @@ -567,6 +610,7 @@ static void rk_videobuf_queue(struct videobuf_queue *vq, struct soc_camera_device *icd = vq->priv_data; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct rk_camera_dev *pcdev = ici->priv; + struct rk29_camera_vbinfo *vb_info; dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, vb, vb->baddr, vb->bsize); @@ -580,6 +624,31 @@ static void rk_videobuf_queue(struct videobuf_queue *vq, else BUG(); /* ddl@rock-chips.com : The same videobuffer queue again */ } +#if CAMERA_VIDEOBUF_ARM_ACCESS + if (pcdev->vbinfo) { + vb_info = pcdev->vbinfo+vb->i; + if ((vb_info->phy_addr != vb->boff) || (vb_info->size != vb->bsize)) { + if (vb_info->vir_addr) { + iounmap(vb_info->vir_addr); + release_mem_region(vb_info->phy_addr, vb_info->size); + vb_info->vir_addr = NULL; + vb_info->phy_addr = 0x00; + vb_info->size = 0x00; + } + + if (request_mem_region(vb->boff,vb->bsize,"rk_camera_vb")) { + vb_info->vir_addr = ioremap_cached(vb->boff,vb->bsize); + } + + if (vb_info->vir_addr) { + vb_info->size = vb->bsize; + vb_info->phy_addr = vb->boff; + } else { + RKCAMERA_TR("%s..%d:ioremap videobuf %d failed\n",__FUNCTION__,__LINE__, vb->i); + } + } + } +#endif if (!pcdev->active) { pcdev->active = vb; rk_videobuf_capture(vb,pcdev); @@ -609,16 +678,219 @@ static int rk_pixfmt2ippfmt(unsigned int pixfmt, int *ippfmt) rk_pixfmt2ippfmt_err: return -1; } -static void rk_camera_capture_process(struct work_struct *work) + +static int rk_pixfmt2rgafmt(unsigned int pixfmt, int *ippfmt) { + switch (pixfmt) + { + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_UYVY: // yuv 422, but sensor has defined this format(in fact ,should be defined yuv 420), treat this as yuv 420. + case V4L2_PIX_FMT_YUYV: + { + *ippfmt = RK_FORMAT_YCbCr_420_SP; + break; + } + case V4L2_PIX_FMT_YVU420: + case V4L2_PIX_FMT_VYUY: + case V4L2_PIX_FMT_YVYU: + { + *ippfmt = RK_FORMAT_YCrCb_420_SP; + break; + } + case V4L2_PIX_FMT_RGB565: + { + *ippfmt = RK_FORMAT_RGB_565; + break; + } + case V4L2_PIX_FMT_RGB24: + { + *ippfmt = RK_FORMAT_RGB_888; + break; + } + default: + goto rk_pixfmt2rgafmt_err; + } + + return 0; +rk_pixfmt2rgafmt_err: + return -1; +} +#if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_PP) +static int rk_camera_scale_crop_pp(struct work_struct *work){ struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work); struct videobuf_buffer *vb = camera_work->vb; struct rk_camera_dev *pcdev = camera_work->pcdev; - struct rk29_ipp_req ipp_req; + int vipdata_base; + unsigned long int flags; + int scale_times,w,h; + int src_y_offset; + PP_OP_HANDLE hnd; + PP_OPERATION init; + int ret = 0; + vipdata_base = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize; + + memset(&init, 0, sizeof(init)); + init.srcAddr = vipdata_base; + init.srcFormat = PP_IN_FORMAT_YUV420SEMI; + init.srcWidth = init.srcHStride = pcdev->zoominfo.vir_width; + init.srcHeight = init.srcVStride = pcdev->zoominfo.vir_height; + + init.dstAddr = vb->boff; + init.dstFormat = PP_OUT_FORMAT_YUV420INTERLAVE; + init.dstWidth = init.dstHStride = pcdev->icd->user_width; + init.dstHeight = init.dstVStride = pcdev->icd->user_height; + + printk("srcWidth = %d,srcHeight = %d,dstWidth = %d,dstHeight = %d\n",init.srcWidth,init.srcHeight,init.dstWidth,init.dstHeight); + #if 0 + ret = ppOpInit(&hnd, &init); + if (!ret) { + ppOpPerform(hnd); + ppOpSync(hnd); + ppOpRelease(hnd); + } else { + printk("can not create ppOp handle\n"); + } + #endif + return ret; +} +#endif +#if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_RGA) +extern rga_service_info rga_service; +extern int rga_blit_sync(rga_session *session, struct rga_req *req); +extern void rga_service_session_clear(rga_session *session); +static int rk_camera_scale_crop_rga(struct work_struct *work){ + struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work); + struct videobuf_buffer *vb = camera_work->vb; + struct rk_camera_dev *pcdev = camera_work->pcdev; + int vipdata_base; unsigned long int flags; - int src_y_offset,src_uv_offset,dst_y_offset,dst_uv_offset,src_y_size,dst_y_size; - int scale_times,w,h,vipdata_base; + int scale_times,w,h; + int src_y_offset; + struct rga_req req; + rga_session session; + int rga_times = 3; + const struct soc_mbus_pixelfmt *fmt; + int ret = 0; + fmt = soc_mbus_get_fmtdesc(pcdev->icd->current_fmt->code); + vipdata_base = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize; + if((pcdev->icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_RGB565) + && (pcdev->icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_RGB24)){ + RKCAMERA_TR("RGA not support this format !\n"); + goto do_ipp_err; + } + if ((pcdev->icd->user_width > 0x800) || (pcdev->icd->user_height > 0x800)) { + scale_times = MAX((pcdev->icd->user_width/0x800),(pcdev->icd->user_height/0x800)); + scale_times++; + } else { + scale_times = 1; + } + session.pid = current->pid; + INIT_LIST_HEAD(&session.waiting); + INIT_LIST_HEAD(&session.running); + INIT_LIST_HEAD(&session.list_session); + init_waitqueue_head(&session.wait); + /* no need to protect */ + list_add_tail(&session.list_session, &rga_service.session); + atomic_set(&session.task_running, 0); + atomic_set(&session.num_done, 0); + + memset(&req,0,sizeof(struct rga_req)); + req.src.act_w = pcdev->zoominfo.a.c.width/scale_times; + req.src.act_h = pcdev->zoominfo.a.c.height/scale_times; + + req.src.vir_w = pcdev->zoominfo.vir_width; + req.src.vir_h =pcdev->zoominfo.vir_height; + req.src.yrgb_addr = vipdata_base; + req.src.uv_addr =vipdata_base + req.src.vir_w*req.src.vir_h; + req.src.v_addr = req.src.uv_addr ; + req.src.format =fmt->fourcc; + rk_pixfmt2rgafmt(fmt->fourcc,&req.src.format); + req.src.x_offset = pcdev->zoominfo.a.c.left; + req.src.y_offset = pcdev->zoominfo.a.c.top; + + req.dst.act_w = pcdev->icd->user_width/scale_times; + req.dst.act_h = pcdev->icd->user_height/scale_times; + + req.dst.vir_w = pcdev->icd->user_width; + req.dst.vir_h = pcdev->icd->user_height; + req.dst.x_offset = 0; + req.dst.y_offset = 0; + req.dst.yrgb_addr = vb->boff; + rk_pixfmt2rgafmt(pcdev->icd->current_fmt->host_fmt->fourcc,&req.dst.format); + req.clip.xmin = 0; + req.clip.xmax = req.dst.vir_w-1; + req.clip.ymin = 0; + req.clip.ymax = req.dst.vir_h -1; + + req.rotate_mode = 1; + req.scale_mode = 2; + + req.sina = 0; + req.cosa = 65536; + req.mmu_info.mmu_en = 0; + + for (h=0; hzoominfo.a.c.left+w*pcdev->zoominfo.a.c.width/scale_times; + req.src.y_offset = pcdev->zoominfo.a.c.top+h*pcdev->zoominfo.a.c.height/scale_times; + req.dst.x_offset = pcdev->icd->user_width*w/scale_times; + req.dst.y_offset = pcdev->icd->user_height*h/scale_times; + req.dst.yrgb_addr = vb->boff ; + // RKCAMERA_TR("src.act_w = %d , src.act_h = %d! vir_w = %d , vir_h = %d,off_x = %d,off_y = %d\n",req.src.act_w,req.src.act_h ,req.src.vir_w,req.src.vir_h,req.src.x_offset,req.src.y_offset); + // RKCAMERA_TR("dst.act_w = %d , dst.act_h = %d! vir_w = %d , vir_h = %d,off_x = %d,off_y = %d\n",req.dst.act_w,req.dst.act_h ,req.dst.vir_w,req.dst.vir_h,req.dst.x_offset,req.dst.y_offset); + // RKCAMERA_TR("req.src.yrgb_addr = 0x%x,req.dst.yrgb_addr = 0x%x\n",req.src.yrgb_addr,req.dst.yrgb_addr); + + while(rga_times-- > 0) { + if (rga_blit_sync(&session, &req)){ + RKCAMERA_TR("rga do erro,do again,rga_times = %d!\n",rga_times); + } else { + break; + } + } + + if (rga_times <= 0) { + spin_lock_irqsave(&pcdev->lock, flags); + vb->state = VIDEOBUF_NEEDS_INIT; + spin_unlock_irqrestore(&pcdev->lock, flags); + mutex_lock(&rga_service.lock); + list_del(&session.list_session); + rga_service_session_clear(&session); + mutex_unlock(&rga_service.lock); + goto session_done; + } + } + } + session_done: + mutex_lock(&rga_service.lock); + list_del(&session.list_session); + rga_service_session_clear(&session); + mutex_unlock(&rga_service.lock); + + do_ipp_err: + + return ret; + +} + +#endif +#if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP) + +static int rk_camera_scale_crop_ipp(struct work_struct *work) +{ + struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work); + struct videobuf_buffer *vb = camera_work->vb; + struct rk_camera_dev *pcdev = camera_work->pcdev; + int vipdata_base; + unsigned long int flags; + + struct rk29_ipp_req ipp_req; + int src_y_offset,src_uv_offset,dst_y_offset,dst_uv_offset,src_y_size,dst_y_size; + int scale_times,w,h; + int ret = 0; /* *ddl@rock-chips.com: * IPP Dest image resolution is 2047x1088, so scale operation break up some times @@ -632,7 +904,6 @@ static void rk_camera_capture_process(struct work_struct *work) memset(&ipp_req, 0, sizeof(struct rk29_ipp_req)); - down(&pcdev->zoominfo.sem); ipp_req.timeout = 3000; ipp_req.flag = IPP_ROT_0; ipp_req.store_clip_mode =1; @@ -691,15 +962,166 @@ 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)); - spin_lock_irqsave(&pcdev->camera_work_lock, flags); - list_add_tail(&camera_work->queue, &pcdev->camera_work_queue); - spin_unlock_irqrestore(&pcdev->camera_work_lock, flags); - return; + return ret; +} +#endif +#if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_ARM) +static int rk_camera_scale_crop_arm(struct work_struct *work) +{ + struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work); + struct videobuf_buffer *vb = camera_work->vb; + struct rk_camera_dev *pcdev = camera_work->pcdev; + struct rk29_camera_vbinfo *vb_info; + unsigned char *psY,*pdY,*psUV,*pdUV; + unsigned char *src,*dst; + unsigned long src_phy,dst_phy; + int srcW,srcH,cropW,cropH,dstW,dstH; + long zoomindstxIntInv,zoomindstyIntInv; + long x,y; + long yCoeff00,yCoeff01,xCoeff00,xCoeff01; + long sX,sY; + long r0,r1,a,b,c,d; + int ret = 0; + + src_phy = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize; + src = psY = (unsigned char*)(pcdev->vipmem_virbase + vb->i*pcdev->vipmem_bsize); + psUV = psY + pcdev->host_width*pcdev->host_height; + + srcW = pcdev->zoominfo.vir_width; + srcH = pcdev->zoominfo.vir_height; + cropW = pcdev->zoominfo.a.c.width; + cropH = pcdev->zoominfo.a.c.height; + + psY = psY + (srcW-cropW); + psUV = psUV + (srcW-cropW); + + vb_info = pcdev->vbinfo+vb->i; + dst_phy = vb_info->phy_addr; + dst = pdY = (unsigned char*)vb_info->vir_addr; + pdUV = pdY + pcdev->icd->user_width*pcdev->icd->user_height; + dstW = pcdev->icd->user_width; + dstH = pcdev->icd->user_height; + + zoomindstxIntInv = ((unsigned long)cropW<<16)/dstW + 1; + zoomindstyIntInv = ((unsigned long)cropH<<16)/dstH + 1; + + //y + //for(y = 0; y> 16); + + for(x = 0; x> 16); + + a = psY[sY*srcW + sX]; + b = psY[sY*srcW + sX + 1]; + c = psY[(sY+1)*srcW + sX]; + d = psY[(sY+1)*srcW + sX + 1]; + + r0 = (a * xCoeff01 + b * xCoeff00)>>16 ; + r1 = (c * xCoeff01 + d * xCoeff00)>>16 ; + r0 = (r0 * yCoeff01 + r1 * yCoeff00)>>16; + + pdY[x] = r0; + } + pdY += dstW; + } + + dstW /= 2; + dstH /= 2; + srcW /= 2; + srcH /= 2; + + //UV + //for(y = 0; y> 16); + + for(x = 0; x> 16); + + //U + a = psUV[(sY*srcW + sX)*2]; + b = psUV[(sY*srcW + sX + 1)*2]; + c = psUV[((sY+1)*srcW + sX)*2]; + d = psUV[((sY+1)*srcW + sX + 1)*2]; + + r0 = (a * xCoeff01 + b * xCoeff00)>>16 ; + r1 = (c * xCoeff01 + d * xCoeff00)>>16 ; + r0 = (r0 * yCoeff01 + r1 * yCoeff00)>>16; + + pdUV[x*2] = r0; + + //V + a = psUV[(sY*srcW + sX)*2 + 1]; + b = psUV[(sY*srcW + sX + 1)*2 + 1]; + c = psUV[((sY+1)*srcW + sX)*2 + 1]; + d = psUV[((sY+1)*srcW + sX + 1)*2 + 1]; + + r0 = (a * xCoeff01 + b * xCoeff00)>>16 ; + r1 = (c * xCoeff01 + d * xCoeff00)>>16 ; + r0 = (r0 * yCoeff01 + r1 * yCoeff00)>>16; + + pdUV[x*2 + 1] = r0; + } + pdUV += dstW*2; + } + +rk_camera_scale_crop_arm_end: + + dmac_flush_range((void*)src,(void*)(src+pcdev->vipmem_bsize)); + outer_flush_range((phys_addr_t)src_phy,(phys_addr_t)(src_phy+pcdev->vipmem_bsize)); + + dmac_flush_range((void*)dst,(void*)(dst+vb_info->size)); + outer_flush_range((phys_addr_t)dst_phy,(phys_addr_t)(dst_phy+vb_info->size)); + + return ret; +} +#endif +static void rk_camera_capture_process(struct work_struct *work) +{ + struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work); + struct videobuf_buffer *vb = camera_work->vb; + struct rk_camera_dev *pcdev = camera_work->pcdev; + //enum v4l2_mbus_pixelcode icd_code = pcdev->icd->current_fmt->code; + unsigned long flags = 0; + int err = 0; + + if (!CAM_WORKQUEUE_IS_EN()) + goto rk_camera_capture_process_end; + + down(&pcdev->zoominfo.sem); + if (pcdev->icd_cb.scale_crop_cb){ + err = (pcdev->icd_cb.scale_crop_cb)(work); + } + up(&pcdev->zoominfo.sem); + + if (pcdev->icd_cb.sensor_cb) + (pcdev->icd_cb.sensor_cb)(vb); + +rk_camera_capture_process_end: + if (err) { + vb->state = VIDEOBUF_ERROR; + } else { + if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) { + vb->state = VIDEOBUF_DONE; + vb->field_count++; + } + } + wake_up(&(camera_work->vb->done)); + spin_lock_irqsave(&pcdev->camera_work_lock, flags); + list_add_tail(&camera_work->queue, &pcdev->camera_work_queue); + spin_unlock_irqrestore(&pcdev->camera_work_lock, flags); + return; } static irqreturn_t rk_camera_irq(int irq, void *data) { @@ -768,11 +1190,7 @@ static irqreturn_t rk_camera_irq(int irq, void *data) RKCAMERA_DG("%s video_buf queue is empty!\n",__FUNCTION__); } - if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) { - vb->state = VIDEOBUF_DONE; - do_gettimeofday(&vb->ts); - vb->field_count++; - } + do_gettimeofday(&vb->ts); if (CAM_WORKQUEUE_IS_EN()) { if (!list_empty(&pcdev->camera_work_queue)) { wk = list_entry(pcdev->camera_work_queue.next, struct rk_camera_work, queue); @@ -783,6 +1201,10 @@ static irqreturn_t rk_camera_irq(int irq, void *data) queue_work(pcdev->camera_wq, &(wk->work)); } } else { + if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) { + vb->state = VIDEOBUF_DONE; + vb->field_count++; + } wake_up(&vb->done); } @@ -802,6 +1224,7 @@ static void rk_videobuf_release(struct videobuf_queue *vq, struct soc_camera_device *icd = vq->priv_data; struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct rk_camera_dev *pcdev = ici->priv; + struct rk29_camera_vbinfo *vb_info =NULL; #ifdef DEBUG dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); @@ -822,16 +1245,25 @@ static void rk_videobuf_release(struct videobuf_queue *vq, break; } #endif - if (vb->i == 0) { - flush_workqueue(pcdev->camera_wq); - } - if (vb == pcdev->active) { RKCAMERA_DG("%s Wait for this video buf(0x%x) write finished!\n ",__FUNCTION__,(unsigned int)vb); interruptible_sleep_on_timeout(&vb->done, msecs_to_jiffies(500)); - flush_workqueue(pcdev->camera_wq); RKCAMERA_DG("%s This video buf(0x%x) write finished, release now!!\n",__FUNCTION__,(unsigned int)vb); } + + flush_workqueue(pcdev->camera_wq); +#if CAMERA_VIDEOBUF_ARM_ACCESS + if (pcdev->vbinfo) { + vb_info = pcdev->vbinfo + vb->i; + + if (vb_info->vir_addr) { + iounmap(vb_info->vir_addr); + release_mem_region(vb_info->phy_addr, vb_info->size); + memset(vb_info, 0x00, sizeof(struct rk29_camera_vbinfo)); + } + + } +#endif rk_videobuf_free(vq, buf); } @@ -1020,6 +1452,8 @@ static void rk_camera_remove_device(struct soc_camera_device *icd) struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct rk_camera_dev *pcdev = ici->priv; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct rk29_camera_vbinfo *vb_info; + unsigned int i; mutex_lock(&camera_lock); BUG_ON(icd != pcdev->icd); @@ -1059,6 +1493,22 @@ static void rk_camera_remove_device(struct soc_camera_device *icd) INIT_LIST_HEAD(&pcdev->camera_work_queue); } rk_camera_deactivate(pcdev); +#if CAMERA_VIDEOBUF_ARM_ACCESS + if (pcdev->vbinfo) { + vb_info = pcdev->vbinfo; + for (i=0; ivbinfo_count; i++) { + if (vb_info->vir_addr) { + iounmap(vb_info->vir_addr); + release_mem_region(vb_info->phy_addr, vb_info->size); + memset(vb_info, 0x00, sizeof(struct rk29_camera_vbinfo)); + } + vb_info++; + } + kfree(pcdev->vbinfo); + pcdev->vbinfo = NULL; + pcdev->vbinfo_count = 0; + } +#endif pcdev->active = NULL; pcdev->icd = NULL; pcdev->icd_cb.sensor_cb = NULL; @@ -1207,6 +1657,18 @@ static const struct soc_mbus_pixelfmt rk_camera_formats[] = { .bits_per_sample = 8, .packing = SOC_MBUS_PACKING_2X8_PADHI, .order = SOC_MBUS_ORDER_LE, + },{ + .fourcc = V4L2_PIX_FMT_RGB565, + .name = "RGB565", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_2X8_PADHI, + .order = SOC_MBUS_ORDER_LE, + },{ + .fourcc = V4L2_PIX_FMT_RGB24, + .name = "RGB888", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_2X8_PADHI, + .order = SOC_MBUS_ORDER_LE, } }; @@ -1216,6 +1678,16 @@ static void rk_camera_setup_format(struct soc_camera_device *icd, __u32 host_pix struct rk_camera_dev *pcdev = ici->priv; unsigned int cif_fs = 0,cif_crop = 0; unsigned int cif_fmt_val = read_cif_reg(pcdev->base,CIF_CIF_FOR) | INPUT_MODE_YUV|YUV_INPUT_422|INPUT_420_ORDER_EVEN|OUTPUT_420_ORDER_EVEN; + + const struct soc_mbus_pixelfmt *fmt; + fmt = soc_mbus_get_fmtdesc(icd_code); + + if((host_pixfmt == V4L2_PIX_FMT_RGB565) || (host_pixfmt == V4L2_PIX_FMT_RGB24)){ + if(fmt->fourcc == V4L2_PIX_FMT_NV12) + host_pixfmt = V4L2_PIX_FMT_NV12; + else if(fmt->fourcc == V4L2_PIX_FMT_NV21) + host_pixfmt = V4L2_PIX_FMT_NV21; + } switch (host_pixfmt) { case V4L2_PIX_FMT_NV16: @@ -1342,42 +1814,62 @@ static int rk_camera_get_formats(struct soc_camera_device *icd, unsigned int idx case V4L2_MBUS_FMT_YUYV8_2X8: case V4L2_MBUS_FMT_YVYU8_2X8: case V4L2_MBUS_FMT_VYUY8_2X8: - formats++; - if (xlate) { - xlate->host_fmt = &rk_camera_formats[0]; - xlate->code = code; - xlate++; - dev_dbg(dev, "Providing format %s using code %d\n", - rk_camera_formats[0].name,code); - } - - formats++; - if (xlate) { - xlate->host_fmt = &rk_camera_formats[1]; - xlate->code = code; - xlate++; - dev_dbg(dev, "Providing format %s using code %d\n", - rk_camera_formats[1].name,code); - } - - formats++; - if (xlate) { - xlate->host_fmt = &rk_camera_formats[2]; - xlate->code = code; - xlate++; - dev_dbg(dev, "Providing format %s using code %d\n", - rk_camera_formats[2].name,code); - } - - formats++; - if (xlate) { - xlate->host_fmt = &rk_camera_formats[3]; - xlate->code = code; - xlate++; - dev_dbg(dev, "Providing format %s using code %d\n", - rk_camera_formats[3].name,code); - } +#if (CONFIG_CAMERA_SCALE_CROP_MACHINE != RK_CAM_SCALE_CROP_RGA) + formats++; + if (xlate) { + xlate->host_fmt = &rk_camera_formats[0]; + xlate->code = code; + xlate++; + dev_dbg(dev, "Providing format %s using code %d\n", + rk_camera_formats[0].name,code); + } + + formats++; + if (xlate) { + xlate->host_fmt = &rk_camera_formats[1]; + xlate->code = code; + xlate++; + dev_dbg(dev, "Providing format %s using code %d\n", + rk_camera_formats[1].name,code); + } + + formats++; + if (xlate) { + xlate->host_fmt = &rk_camera_formats[2]; + xlate->code = code; + xlate++; + dev_dbg(dev, "Providing format %s using code %d\n", + rk_camera_formats[2].name,code); + } + + formats++; + if (xlate) { + xlate->host_fmt = &rk_camera_formats[3]; + xlate->code = code; + xlate++; + dev_dbg(dev, "Providing format %s using code %d\n", + rk_camera_formats[3].name,code); + } + break; +#else + formats++; + if (xlate) { + xlate->host_fmt = &rk_camera_formats[4]; + xlate->code = code; + xlate++; + dev_dbg(dev, "Providing format %s using code %d\n", + rk_camera_formats[4].name,code); + } + formats++; + if (xlate) { + xlate->host_fmt = &rk_camera_formats[5]; + xlate->code = code; + xlate++; + dev_dbg(dev, "Providing format %s using code %d\n", + rk_camera_formats[5].name,code); + } break; +#endif default: break; } @@ -2361,15 +2853,38 @@ 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; + + if (!request_mem_region(pcdev->vipmem_phybase,pcdev->vipmem_size,"rk29_vipmem")) { + err = -EBUSY; + goto exit_ioremap_vipmem; + } + pcdev->vipmem_virbase = ioremap_cached(pcdev->vipmem_phybase,pcdev->vipmem_size); + if (pcdev->vipmem_virbase == NULL) { + dev_err(pcdev->dev, "ioremap() of vip internal memory(Ex:IPP process/raw process) failed\n"); + err = -ENXIO; + goto exit_ioremap_vipmem; + } RKCAMERA_TR("%s(%d): Memory(start:0x%x size:0x%x) for IPP obtain \n",__FUNCTION__,__LINE__, 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; + + if (!request_mem_region(pcdev->vipmem_phybase,pcdev->vipmem_size,"rk29_vipmem")) { + err = -EBUSY; + goto exit_ioremap_vipmem; + } + pcdev->vipmem_virbase = ioremap_cached(pcdev->vipmem_phybase,pcdev->vipmem_size); + if (pcdev->vipmem_virbase == NULL) { + dev_err(pcdev->dev, "ioremap() of vip internal memory(Ex:IPP process/raw process) failed\n"); + err = -ENXIO; + goto exit_ioremap_vipmem; + } RKCAMERA_TR("%s(%d): Memory(start:0x%x size:0x%x) for IPP obtain \n",__FUNCTION__,__LINE__, 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__); pcdev->vipmem_phybase = 0; pcdev->vipmem_size = 0; + pcdev->vipmem_virbase = 0; } #endif INIT_LIST_HEAD(&pcdev->capture); @@ -2441,6 +2956,15 @@ static int rk_camera_probe(struct platform_device *pdev) pcdev->fps_timer.timer.function = rk_camera_fps_func; pcdev->icd_cb.sensor_cb = NULL; +#if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP) + pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_ipp; +#elif (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_ARM) + pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_arm; +#elif (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_RGA) + pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_rga; +#elif(CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_PP) + pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_pp; +#endif RKCAMERA_DG("%s(%d) Exit \n",__FUNCTION__,__LINE__); return 0; @@ -2465,7 +2989,10 @@ exit_reqirq: iounmap(pcdev->base); exit_ioremap_vip: release_mem_region(res->start, res->end - res->start + 1); - +exit_ioremap_vipmem: + if (pcdev->vipmem_virbase) + iounmap(pcdev->vipmem_virbase); + release_mem_region(pcdev->vipmem_phybase,pcdev->vipmem_size); exit_reqmem_vip: if(pcdev->aclk_cif) pcdev->aclk_cif = NULL; -- 2.34.1