#include <media/soc_mediabus.h>
#include <mach/io.h>
#include <plat/ipp.h>
-
+#include <plat/vpu_service.h>
+#include "../../video/rockchip/rga/rga.h"
#if defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK31)
#include <mach/rk30_camera.h>
#include <mach/cru.h>
#if defined(CONFIG_ARCH_RK2928)
#include <mach/rk2928_camera.h>
+#include "../../video/rockchip/rga/rga.h"
#endif
-
+#include <asm/cacheflush.h>
static int debug ;
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)
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;
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;
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)
}
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);
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);
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);
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; h<scale_times; h++) {
+ for (w=0; w<scale_times; w++) {
+ rga_times = 3;
+ req.src.yrgb_addr = vipdata_base;
+ req.src.uv_addr =vipdata_base +req.src.vir_w *req.src.vir_h ;
+ req.src.x_offset = pcdev->zoominfo.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
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;
}
}
- 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<dstH - 1 ; y++ ) {
+ for(y = 0; y<dstH; y++ ) {
+ yCoeff00 = (y*zoomindstyIntInv)&0xffff;
+ yCoeff01 = 0xffff - yCoeff00;
+ sY = (y*zoomindstyIntInv >> 16);
+
+ for(x = 0; x<dstW; x++ ) {
+ xCoeff00 = (x*zoomindstxIntInv)&0xffff;
+ xCoeff01 = 0xffff - xCoeff00;
+ sX = (x*zoomindstxIntInv >> 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<dstH - 1 ; y++ ) {
+ for(y = 0; y<dstH; y++ ) {
+ yCoeff00 = (y*zoomindstyIntInv)&0xffff;
+ yCoeff01 = 0xffff - yCoeff00;
+ sY = (y*zoomindstyIntInv >> 16);
+
+ for(x = 0; x<dstW; x++ ) {
+ xCoeff00 = (x*zoomindstxIntInv)&0xffff;
+ xCoeff01 = 0xffff - xCoeff00;
+ sX = (x*zoomindstxIntInv >> 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)
{
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);
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);
}
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);
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);
}
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);
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; i<pcdev->vbinfo_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;
.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,
}
};
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:
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;
}
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);
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;
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;