* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
-
+#ifdef CONFIG_ARCH_RK29
#include <linux/init.h>
#include <linux/module.h>
#include <linux/io.h>
#include <media/soc_camera.h>
#include <media/soc_mediabus.h>
#include <mach/rk29-ipp.h>
-
+#include <asm/cacheflush.h>
static int debug;
-module_param(debug, int, S_IRUGO|S_IWUSR);
+module_param(debug, int, S_IRUGO|S_IWUSR|S_IWGRP);
#define dprintk(level, fmt, arg...) do { \
if (debug >= level) \
//Configure Macro
/*
* Driver Version Note
-*v0.0.1 : this driver first support rk2918;
-*v0.0.2 : fix this driver support v4l2 format is V4L2_PIX_FMT_NV12 and V4L2_PIX_FMT_NV16,is not V4L2_PIX_FMT_YUV420
+*
+*v0.0.x : this driver is 2.6.32 kernel driver;
+*v0.1.x : this driver is 3.0.8 kernel driver;
+*v0.2.x : this driver is rk30 3.0.8 kernel driver;
+*v0.3.x : this driver is camera-isp driver;
+*
+*v0.x.1 : this driver first support rk2918;
+*v0.x.2 : fix this driver support v4l2 format is V4L2_PIX_FMT_NV12 and V4L2_PIX_FMT_NV16,is not V4L2_PIX_FMT_YUV420
* and V4L2_PIX_FMT_YUV422P;
-*v0.0.3 : this driver support VIDIOC_ENUM_FRAMEINTERVALS;
-*v0.0.4 : this driver support digital zoom;
+*v0.x.3 : this driver support VIDIOC_ENUM_FRAMEINTERVALS;
+*v0.x.4 : this driver support digital zoom;
+*v0.x.5 : this driver support test framerate and query framerate from board file configuration;
+*v0.x.6 : this driver improve test framerate method;
+*v0.x.7 : this driver product resolution by IPP crop and scale, which user request but sensor can't support;
+* note: this version is only provide yifang client, which is not official version;
+*v0.x.8 : this driver and rk29_camera.c support upto 3 back-sensors and upto 3 front-sensors;
+*v0.x.9 : camera io code is compatible for rk29xx and rk30xx
+*v0.x.a : fix error when calculate crop left-top point coordinate;
+* note: this version provided as patch camera_patch_v1.1
+*v0.x.b : fix sensor autofocus thread may in running when reinit sensor if sensor haven't stream on in first init;
+*v0.x.c : fix work queue havn't been finished after close device;
+*v0.x.d : fix error when calculate crop left-top point coordinate;
+*v0.x.f : fix struct rk29_camera_work may be reentrant.
+*v0.x.11: add support zoom by arm;
*/
-#define RK29_CAM_VERSION_CODE KERNEL_VERSION(0, 1, 3)
+#define RK29_CAM_VERSION_CODE KERNEL_VERSION(0, 1, 0x11)
/* limit to rk29 hardware capabilities */
#define RK29_CAM_BUS_PARAM (SOCAM_MASTER |\
#define RK29_CAM_H_MAX 2764
#define RK29_CAM_FRAME_INVAL_INIT 3
#define RK29_CAM_FRAME_INVAL_DC 3 /* ddl@rock-chips.com : */
+#define RK29_CAM_FRAME_MEASURE 5
#define RK29_CAM_AXI 0
#define RK29_CAM_AHB 1
struct videobuf_buffer *vb;
struct rk29_camera_dev *pcdev;
struct work_struct work;
+ struct list_head queue;
+ unsigned int index;
};
struct rk29_camera_frmivalenum
{
struct v4l2_crop a;
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 rk29_camera_dev
{
struct soc_camera_host soc_host;
int frame_inval; /* ddl@rock-chips.com : The first frames is invalidate */
unsigned int irq;
unsigned int fps;
+ unsigned long frame_interval;
unsigned int pixfmt;
unsigned int vipmem_phybase;
+ void __iomem *vipmem_virbase;
unsigned int vipmem_size;
unsigned int vipmem_bsize;
+#if CAMERA_VIDEOBUF_ARM_ACCESS
+ struct rk29_camera_vbinfo *vbinfo;
+ unsigned int vbinfo_count;
+#endif
int host_width;
int host_height;
+ int icd_width;
+ int icd_height;
struct rk29camera_platform_data *pdata;
struct resource *res;
struct rk29_camera_reg reginfo_suspend;
struct workqueue_struct *camera_wq;
struct rk29_camera_work *camera_work;
+ struct list_head camera_work_queue;
+ spinlock_t camera_work_lock;
unsigned int camera_work_count;
struct hrtimer fps_timer;
struct work_struct camera_reinit_work;
struct rk29_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);
+ int i;
+ struct rk29_camera_work *wk;
dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size);
/* planar capture requires Y, U and V buffers to be page aligned */
*size = PAGE_ALIGN(bytes_per_line*icd->user_height); /* Y pages UV pages, yuv422*/
- pcdev->vipmem_bsize = PAGE_ALIGN(bytes_per_line * pcdev->host_height);
+ pcdev->vipmem_bsize = PAGE_ALIGN(bytes_per_line_host * pcdev->host_height);
if (CAM_WORKQUEUE_IS_EN()) {
if ((pcdev->camera_work_count != *count) && pcdev->camera_work) {
kfree(pcdev->camera_work);
pcdev->camera_work = NULL;
- pcdev->camera_work_count = 0;
+ pcdev->camera_work_count = 0;
}
if (pcdev->camera_work == NULL) {
- pcdev->camera_work = kmalloc(sizeof(struct rk29_camera_work)*(*count), GFP_KERNEL);
+ pcdev->camera_work = wk = kzalloc(sizeof(struct rk29_camera_work)*(*count), GFP_KERNEL);
if (pcdev->camera_work == NULL) {
RK29CAMERA_TR("\n %s kmalloc fail\n", __FUNCTION__);
BUG();
}
- pcdev->camera_work_count = *count;
+ INIT_LIST_HEAD(&pcdev->camera_work_queue);
+
+ for (i=0; i<(*count); i++) {
+ wk->index = i;
+ list_add_tail(&wk->queue, &pcdev->camera_work_queue);
+ wk++;
+ }
+ 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) {
+ RK29CAMERA_TR("\n %s vbinfo kmalloc fail\n", __FUNCTION__);
+ BUG();
+ }
+ pcdev->vbinfo_count = *count;
+ }
+#endif
}
RK29CAMERA_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 rk29_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,"rk29_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 {
+ RK29CAMERA_TR("%s..%d:ioremap videobuf %d failed\n",__FUNCTION__,__LINE__, vb->i);
+ }
+ }
+ }
+#endif
if (!pcdev->active) {
pcdev->active = vb;
rk29_videobuf_capture(vb);
rk29_pixfmt2ippfmt_err:
return -1;
}
-static void rk29_camera_capture_process(struct work_struct *work)
+#if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP)
+static int rk29_camera_scale_crop_ipp(struct work_struct *work)
{
struct rk29_camera_work *camera_work = container_of(work, struct rk29_camera_work, work);
struct videobuf_buffer *vb = camera_work->vb;
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 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 = 100;
ipp_req.flag = IPP_ROT_0;
ipp_req.src0.w = pcdev->zoominfo.a.c.width/scale_times;
RK29CAMERA_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);
RK29CAMERA_TR("ipp_req.timeout:0x%x ipp_req.flag :0x%x\n",ipp_req.timeout,ipp_req.flag);
- goto do_ipp_err;
+ goto rk29_camera_scale_crop_ipp_end;
}
}
}
+
+rk29_camera_scale_crop_ipp_end:
+ return ret;
+}
+#endif
+#if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_ARM)
+static int rk29_camera_scale_crop_arm(struct work_struct *work)
+{
+ struct rk29_camera_work *camera_work = container_of(work, struct rk29_camera_work, work);
+ struct videobuf_buffer *vb = camera_work->vb;
+ struct rk29_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;
+
- 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));
- return;
+ 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->host_width;
+ srcH = pcdev->host_height;
+ cropW = pcdev->zoominfo.a.c.width;
+ cropH = pcdev->zoominfo.a.c.height;
+ psY = psY + pcdev->host_width - pcdev->zoominfo.a.c.width;
+ psUV = psUV + pcdev->host_width - pcdev->zoominfo.a.c.width;
+
+ 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;
+ }
+
+rk29_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 rk29_camera_capture_process(struct work_struct *work)
+{
+ struct rk29_camera_work *camera_work = container_of(work, struct rk29_camera_work, work);
+ struct videobuf_buffer *vb = camera_work->vb;
+ struct rk29_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 rk29_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);
+
+rk29_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 rk29_camera_irq(int irq, void *data)
{
struct rk29_camera_dev *pcdev = data;
struct videobuf_buffer *vb;
struct rk29_camera_work *wk;
+ static struct timeval first_tv;
+ struct timeval tv;
read_vip_reg(RK29_VIP_INT_STS); /* clear vip interrupte single */
/* ddl@rock-chps.com : Current VIP is run in One Frame Mode, Frame 1 is validate */
if (read_vip_reg(RK29_VIP_FB_SR) & 0x01) {
+ if (!pcdev->fps) {
+ do_gettimeofday(&first_tv);
+ }
pcdev->fps++;
if (!pcdev->active)
goto RK29_CAMERA_IRQ_END;
- if (pcdev->frame_inval>0) {
+ if (pcdev->frame_inval>0) {
pcdev->frame_inval--;
rk29_videobuf_capture(pcdev->active);
goto RK29_CAMERA_IRQ_END;
pcdev->frame_inval = 0;
}
+ if(pcdev->fps == RK29_CAM_FRAME_MEASURE) {
+ do_gettimeofday(&tv);
+ pcdev->frame_interval = ((tv.tv_sec*1000000 + tv.tv_usec) - (first_tv.tv_sec*1000000 + first_tv.tv_usec))
+ /(RK29_CAM_FRAME_MEASURE-1);
+ }
+
vb = pcdev->active;
/* ddl@rock-chips.com : this vb may be deleted from queue */
if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) {
if (pcdev->active == NULL) {
RK29CAMERA_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()) {
- wk = pcdev->camera_work + vb->i;
- INIT_WORK(&(wk->work), rk29_camera_capture_process);
- wk->vb = vb;
- wk->pcdev = pcdev;
- queue_work(pcdev->camera_wq, &(wk->work));
+ if (!list_empty(&pcdev->camera_work_queue)) {
+ wk = list_entry(pcdev->camera_work_queue.next, struct rk29_camera_work, queue);
+ list_del_init(&wk->queue);
+ INIT_WORK(&(wk->work), rk29_camera_capture_process);
+ wk->vb = vb;
+ wk->pcdev = pcdev;
+ 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 rk29_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);
dev_dbg(&icd->dev, "%s (unknown)\n", __func__);
break;
}
-#endif
+#endif
if (vb == pcdev->active) {
RK29CAMERA_DG("%s Wait for this video buf(0x%x) write finished!\n ",__FUNCTION__,(unsigned int)vb);
- interruptible_sleep_on_timeout(&vb->done, 100);
+ interruptible_sleep_on_timeout(&vb->done, msecs_to_jiffies(500));
RK29CAMERA_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
rk29_videobuf_free(vq, buf);
}
goto ebusy;
}
- dev_info(&icd->dev, "RK29 Camera driver attached to camera%d(%s)\n",
- icd->devnum,dev_name(icd->pdev));
-
+ RK29CAMERA_DG("RK29 Camera driver attached to %s\n",dev_name(icd->pdev));
+
pcdev->frame_inval = RK29_CAM_FRAME_INVAL_INIT;
pcdev->active = NULL;
pcdev->icd = NULL;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct rk29_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);
- dev_info(&icd->dev, "RK29 Camera driver detached from camera%d(%s)\n",
- icd->devnum,dev_name(icd->pdev));
+ RK29CAMERA_DG("RK29 Camera driver detached from %s\n",dev_name(icd->pdev));
/* ddl@rock-chips.com: Application will call VIDIOC_STREAMOFF before close device, but
stream may be turn on again before close device, if suspend and resume happened. */
kfree(pcdev->camera_work);
pcdev->camera_work = NULL;
pcdev->camera_work_count = 0;
+ INIT_LIST_HEAD(&pcdev->camera_work_queue);
}
-
+#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;
pcdev->pixfmt = host_pixfmt;
break;
default: /* ddl@rock-chips.com : vip output format is hold when pixfmt is invalidate */
- vip_ctrl_val |= (read_vip_reg(RK29_VIP_CTRL) & VIPREGYUV422);
+ if (pcdev->frame_inval != RK29_CAM_FRAME_INVAL_INIT)
+ pcdev->frame_inval = RK29_CAM_FRAME_INVAL_INIT;
+ pcdev->pixfmt = host_pixfmt;
break;
}
switch (icd_code)
{
case V4L2_MBUS_FMT_UYVY8_2X8:
- vip_ctrl_val |= SENSOR_UYVY;
+ vip_ctrl_val |= (SENSOR_UYVY|VIP_YUV);
break;
case V4L2_MBUS_FMT_YUYV8_2X8:
- vip_ctrl_val |= SENSOR_YUYV;
+ vip_ctrl_val |= (SENSOR_YUYV|VIP_YUV);
break;
default :
vip_ctrl_val |= (read_vip_reg(RK29_VIP_CTRL) & SENSOR_YUYV);
struct v4l2_pix_format *pix = &f->fmt.pix;
struct v4l2_mbus_framefmt mf;
struct v4l2_rect rect;
- int ret,usr_w,usr_h;
+ int ret,usr_w,usr_h,icd_width,icd_height;
int stream_on = 0;
usr_w = pix->width;
if (mf.code != xlate->code)
return -EINVAL;
-
+
+ icd_width = mf.width;
+ icd_height = mf.height;
#ifdef CONFIG_VIDEO_RK29_WORK_IPP
if ((mf.width != usr_w) || (mf.height != usr_h)) {
if (unlikely((mf.width <16) || (mf.width > 8190) || (mf.height < 16) || (mf.height > 8190))) {
ret = -EINVAL;
goto RK29_CAMERA_SET_FMT_END;
}
- mf.width = usr_w;
- mf.height = usr_h;
}
#endif
icd->sense = NULL;
if (!ret) {
- rect.left = 0;
- rect.top = 0;
- rect.width = mf.width;
- rect.height = mf.height;
+
+ if (mf.width*usr_h == mf.height*usr_w) {
+ rect.width = mf.width;
+ rect.height = mf.height;
+ } else {
+ int ratio;
+ if (usr_w > usr_h) {
+ if (mf.width > usr_w) {
+ ratio = MIN((mf.width*10/usr_w),(mf.height*10/usr_h))-1;
+ rect.width = usr_w*ratio/10;
+ rect.height = usr_h*ratio/10;
+ } else {
+ ratio = MAX((usr_w*10/mf.width),(usr_h*10/mf.height))+1;
+ rect.width = usr_w*10/ratio;
+ rect.height = usr_h*10/ratio;
+ }
+ } else {
+ if (mf.height > usr_h) {
+ ratio = MIN((mf.width*10/usr_w),(mf.height*10/usr_h))-1;
+ rect.width = usr_w*ratio/10;
+ rect.height = usr_h*ratio/10;
+ } else {
+ ratio = MAX((usr_w*10/mf.width),(usr_h*10/mf.height))+1;
+ rect.width = usr_w*10/ratio;
+ rect.height = usr_h*10/ratio;
+ }
+ }
+ }
+
+ rect.left = (mf.width - rect.width)/2;
+ rect.top = (mf.height - rect.height)/2;
down(&pcdev->zoominfo.sem);
pcdev->zoominfo.a.c.width = rect.width*100/pcdev->zoominfo.zoom_rate;
pcdev->zoominfo.a.c.width &= ~0x03;
pcdev->zoominfo.a.c.height = rect.height*100/pcdev->zoominfo.zoom_rate;
pcdev->zoominfo.a.c.height &= ~0x03;
- pcdev->zoominfo.a.c.left = ((rect.width - pcdev->zoominfo.a.c.width)>>1)&(~0x01);
- pcdev->zoominfo.a.c.top = ((rect.height - pcdev->zoominfo.a.c.height)>>1)&(~0x01);
+ pcdev->zoominfo.a.c.left = ((rect.width - pcdev->zoominfo.a.c.width)/2 + rect.left)&(~0x01);
+ pcdev->zoominfo.a.c.top = ((rect.height - pcdev->zoominfo.a.c.height)/2 + rect.top)&(~0x01);
up(&pcdev->zoominfo.sem);
/* ddl@rock-chips.com: IPP work limit check */
}
}
- RK29CAMERA_DG("%s..%s icd width:%d host width:%d (zoom: %dx%d@(%d,%d)->%dx%d)\n",__FUNCTION__,xlate->host_fmt->name,
- rect.width, pix->width, pcdev->zoominfo.a.c.width,pcdev->zoominfo.a.c.height, pcdev->zoominfo.a.c.left,pcdev->zoominfo.a.c.top,
+ /* ddl@rock-chips.com: Crop is doing by IPP, not by VIP in rk2918 */
+ rect.left = 0;
+ rect.top = 0;
+ rect.width = mf.width;
+ rect.height = mf.height;
+
+ RK29CAMERA_DG("%s..%s Sensor output:%dx%d VIP output:%dx%d (zoom: %dx%d@(%d,%d)->%dx%d)\n",__FUNCTION__,xlate->host_fmt->name,
+ mf.width, mf.height,rect.width,rect.height, pcdev->zoominfo.a.c.width,pcdev->zoominfo.a.c.height, pcdev->zoominfo.a.c.left,pcdev->zoominfo.a.c.top,
pix->width, pix->height);
+
+
rk29_camera_setup_format(icd, pix->pixelformat, mf.code, &rect);
if (CAM_IPPWORK_IS_EN()) {
BUG_ON(pcdev->vipmem_phybase == 0);
}
+ pcdev->icd_width = icd_width;
+ pcdev->icd_height = icd_height;
- pix->width = mf.width;
- pix->height = mf.height;
+ pix->width = usr_w;
+ pix->height = usr_h;
pix->field = mf.field;
pix->colorspace = mf.colorspace;
icd->current_fmt = xlate;
if (stream_on & ENABLE_CAPTURE)
write_vip_reg(RK29_VIP_CTRL, (read_vip_reg(RK29_VIP_CTRL) | ENABLE_CAPTURE));
if (ret)
- RK29CAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
+ RK29CAMERA_TR("\n%s: Driver isn't support %dx%d resolution which user request!\n",__FUNCTION__,usr_w,usr_h);
return ret;
}
static bool rk29_camera_fmt_capturechk(struct v4l2_format *f)
bool is_capture = rk29_camera_fmt_capturechk(f);
bool vipmem_is_overflow = false;
struct v4l2_mbus_framefmt mf;
-
+ int bytes_per_line_host;
+
usr_w = pix->width;
usr_h = pix->height;
RK29CAMERA_DG("%s enter width:%d height:%d\n",__FUNCTION__,usr_w,usr_h);
goto RK29_CAMERA_TRY_FMT_END;
RK29CAMERA_DG("%s mf.width:%d mf.height:%d\n",__FUNCTION__,mf.width,mf.height);
#ifdef CONFIG_VIDEO_RK29_WORK_IPP
- if ((mf.width > usr_w) && (mf.height > usr_h)) {
+ if ((mf.width != usr_w) || (mf.height != usr_h)) {
+ bytes_per_line_host = soc_mbus_bytes_per_line(mf.width,icd->current_fmt->host_fmt);
if (is_capture) {
- vipmem_is_overflow = (PAGE_ALIGN(pix->bytesperline*pix->height) > pcdev->vipmem_size);
+ vipmem_is_overflow = (PAGE_ALIGN(bytes_per_line_host*mf.height) > pcdev->vipmem_size);
} else {
/* Assume preview buffer minimum is 4 */
- vipmem_is_overflow = (PAGE_ALIGN(pix->bytesperline*pix->height)*4 > pcdev->vipmem_size);
- }
+ vipmem_is_overflow = (PAGE_ALIGN(bytes_per_line_host*mf.height)*4 > pcdev->vipmem_size);
+ }
if (vipmem_is_overflow == false) {
pix->width = usr_w;
pix->height = usr_h;
pix->width = mf.width;
pix->height = mf.height;
}
- } else if ((mf.width < usr_w) && (mf.height < usr_h)) {
- if (((usr_w>>1) < mf.width) && ((usr_h>>1) < mf.height)) {
- if (is_capture) {
- vipmem_is_overflow = (PAGE_ALIGN(pix->bytesperline*pix->height) > pcdev->vipmem_size);
- } else {
- vipmem_is_overflow = (PAGE_ALIGN(pix->bytesperline*pix->height)*4 > pcdev->vipmem_size);
- }
- if (vipmem_is_overflow == false) {
- pix->width = usr_w;
- pix->height = usr_h;
- } else {
- RK29CAMERA_TR("vipmem for IPP is overflow, This resolution(%dx%d -> %dx%d) is invalidate!\n",mf.width,mf.height,usr_w,usr_h);
+
+ if ((mf.width < usr_w) || (mf.height < usr_h)) {
+ if (((usr_w>>1) > mf.width) || ((usr_h>>1) > mf.height)) {
+ RK29CAMERA_TR("The aspect ratio(%dx%d/%dx%d) is bigger than 2 !\n",mf.width,mf.height,usr_w,usr_h);
pix->width = mf.width;
pix->height = mf.height;
- }
- } else {
- RK29CAMERA_TR("The aspect ratio(%dx%d/%dx%d) is bigger than 2 !\n",mf.width,mf.height,usr_w,usr_h);
- pix->width = mf.width;
- pix->height = mf.height;
- }
+ }
+ }
}
#else
pix->width = mf.width;
pix->colorspace = mf.colorspace;
switch (mf.field) {
- case V4L2_FIELD_ANY:
- case V4L2_FIELD_NONE:
- pix->field = V4L2_FIELD_NONE;
- break;
- default:
- /* TODO: support interlaced at least in pass-through mode */
- dev_err(icd->dev.parent, "Field type %d unsupported.\n",
- mf.field);
- goto RK29_CAMERA_TRY_FMT_END;
+ case V4L2_FIELD_ANY:
+ case V4L2_FIELD_NONE:
+ pix->field = V4L2_FIELD_NONE;
+ break;
+ default:
+ /* TODO: support interlaced at least in pass-through mode */
+ dev_err(icd->dev.parent, "Field type %d unsupported.\n",
+ mf.field);
+ goto RK29_CAMERA_TRY_FMT_END;
}
RK29_CAMERA_TRY_FMT_END:
{
struct rk29_camera_dev *pcdev = ici->priv;
char orientation[5];
+ int i;
+
+ strlcpy(cap->card, dev_name(pcdev->icd->pdev), sizeof(cap->card));
- strlcpy(cap->card, dev_name(pcdev->icd->pdev), sizeof(cap->card));
- if (strcmp(dev_name(pcdev->icd->pdev), pcdev->pdata->gpio_res[0].dev_name) == 0) {
- sprintf(orientation,"-%d",pcdev->pdata->gpio_res[0].orientation);
+ memset(orientation,0x00,sizeof(orientation));
+ for (i=0; i<RK29_CAM_SUPPORT_NUMS;i++) {
+ if ((pcdev->pdata->info[i].dev_name!=NULL) && (strcmp(dev_name(pcdev->icd->pdev), pcdev->pdata->info[i].dev_name) == 0)) {
+ sprintf(orientation,"-%d",pcdev->pdata->info[i].orientation);
+ }
+ }
+
+ if (orientation[0] != '-') {
+ RK29CAMERA_TR("%s: %s is not registered in rk29_camera_platform_data, orientation apply default value",__FUNCTION__,dev_name(pcdev->icd->pdev));
+ if (strstr(dev_name(pcdev->icd->pdev),"front"))
+ strcat(cap->card,"-270");
+ else
+ strcat(cap->card,"-90");
} else {
- sprintf(orientation,"-%d",pcdev->pdata->gpio_res[1].orientation);
+ strcat(cap->card,orientation);
}
- strcat(cap->card,orientation);
+
cap->version = RK29_CAM_VERSION_CODE;
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
control = to_soc_camera_control(rk29_camdev_info_ptr->icd);
sd = dev_get_drvdata(control);
+ v4l2_subdev_call(sd, video, s_stream, 0); /* ddl@rock-chips.com: Avoid sensor autofocus thread is running */
ret = v4l2_subdev_call(sd,core, init, 1);
mf.width = rk29_camdev_info_ptr->icd->user_width;
mf.code = xlate->code;
ret |= v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
-
+ v4l2_subdev_call(sd, video, s_stream, 1);
write_vip_reg(RK29_VIP_CTRL, (read_vip_reg(RK29_VIP_CTRL)|ENABLE_CAPTURE));
RK29CAMERA_TR("Camera host haven't recevie data from sensor,Reinit sensor now! ret:0x%x\n",ret);
&& (fival_nxt->fival.height == rk29_camdev_info_ptr->icd->user_height)
&& (fival_nxt->fival.width == rk29_camdev_info_ptr->icd->user_width))
|| (fival_nxt->fival.discrete.denominator == 0)) {
-
- if (fival_nxt->fival.discrete.denominator == 0) {
- fival_nxt->fival.index = 0;
- fival_nxt->fival.width = rk29_camdev_info_ptr->icd->user_width;
- fival_nxt->fival.height= rk29_camdev_info_ptr->icd->user_height;
- fival_nxt->fival.pixel_format = rk29_camdev_info_ptr->pixfmt;
- fival_nxt->fival.discrete.denominator = rk29_camdev_info_ptr->fps+2;
- fival_nxt->fival.discrete.numerator = 1;
- fival_nxt->fival.type = V4L2_FRMIVAL_TYPE_DISCRETE;
- } else {
- if (abs(rk29_camdev_info_ptr->fps + 2 - fival_nxt->fival.discrete.numerator) > 2) {
- fival_nxt->fival.discrete.denominator = rk29_camdev_info_ptr->fps+2;
- fival_nxt->fival.discrete.numerator = 1;
- fival_nxt->fival.type = V4L2_FRMIVAL_TYPE_DISCRETE;
- }
- }
+
+ fival_nxt->fival.index = 0;
+ fival_nxt->fival.width = rk29_camdev_info_ptr->icd->user_width;
+ fival_nxt->fival.height= rk29_camdev_info_ptr->icd->user_height;
+ fival_nxt->fival.pixel_format = rk29_camdev_info_ptr->pixfmt;
+ fival_nxt->fival.discrete.denominator = rk29_camdev_info_ptr->frame_interval;
+ fival_nxt->fival.reserved[1] = (rk29_camdev_info_ptr->icd_width<<16)
+ |(rk29_camdev_info_ptr->icd_height);
+ fival_nxt->fival.discrete.numerator = 1000000;
+ fival_nxt->fival.type = V4L2_FRMIVAL_TYPE_DISCRETE;
+
rec_flag = 1;
fival_rec = fival_nxt;
}
fival_pre->nxt->fival.height= rk29_camdev_info_ptr->icd->user_height;
fival_pre->nxt->fival.pixel_format = rk29_camdev_info_ptr->pixfmt;
- fival_pre->nxt->fival.discrete.denominator = rk29_camdev_info_ptr->fps+2;
- fival_pre->nxt->fival.discrete.numerator = 1;
+ fival_pre->nxt->fival.discrete.denominator = rk29_camdev_info_ptr->frame_interval;
+
+ fival_pre->nxt->fival.reserved[1] = (rk29_camdev_info_ptr->icd_width<<16)
+ |(rk29_camdev_info_ptr->icd_height);
+
+ fival_pre->nxt->fival.discrete.numerator = 1000000;
fival_pre->nxt->fival.type = V4L2_FRMIVAL_TYPE_DISCRETE;
rec_flag = 1;
fival_rec = fival_pre->nxt;
int ret;
WARN_ON(pcdev->icd != icd);
-
+ pcdev->frame_interval = 0;
vip_ctrl_val = read_vip_reg(RK29_VIP_CTRL);
if (enable) {
pcdev->fps = 0;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct rk29_camera_dev *pcdev = ici->priv;
struct rk29_camera_frmivalenum *fival_list = NULL;
- int i,ret = 0;
+ struct v4l2_frmivalenum *fival_head=NULL;
+ int i,ret = 0,index;
- for (i=0; i<2; i++) {
- if (pcdev->icd_frmival[i].icd == icd) {
- fival_list = pcdev->icd_frmival[i].fival_list;
+ index = fival->index & 0x00ffffff;
+ if ((fival->index & 0xff000000) == 0xff000000) { /* ddl@rock-chips.com: detect framerate */
+ for (i=0; i<2; i++) {
+ if (pcdev->icd_frmival[i].icd == icd) {
+ fival_list = pcdev->icd_frmival[i].fival_list;
+ }
}
- }
-
- if (fival_list != NULL) {
+
+ if (fival_list != NULL) {
+ i = 0;
+ while (fival_list != NULL) {
+ if ((fival->pixel_format == fival_list->fival.pixel_format)
+ && (fival->height == fival_list->fival.height)
+ && (fival->width == fival_list->fival.width)) {
+ if (i == index)
+ break;
+ i++;
+ }
+ fival_list = fival_list->nxt;
+ }
+
+ if ((i==index) && (fival_list != NULL)) {
+ memcpy(fival, &fival_list->fival, sizeof(struct v4l2_frmivalenum));
+ } else {
+ ret = -EINVAL;
+ }
+ } else {
+ RK29CAMERA_TR("%s: fival_list is NULL\n",__FUNCTION__);
+ ret = -EINVAL;
+ }
+ } else {
+
+ for (i=0; i<RK29_CAM_SUPPORT_NUMS; i++) {
+ if (pcdev->pdata->info[i].dev_name && (strcmp(dev_name(pcdev->icd->pdev),pcdev->pdata->info[i].dev_name) == 0)) {
+ fival_head = pcdev->pdata->info[i].fival;
+ }
+ }
+
+ if (fival_head == NULL) {
+ RK29CAMERA_TR("%s: %s is not registered in rk29_camera_platform_data!!",__FUNCTION__,dev_name(pcdev->icd->pdev));
+ ret = -EINVAL;
+ goto rk29_camera_enum_frameintervals_end;
+ }
+
i = 0;
- while (fival_list != NULL) {
- if ((fival->pixel_format == fival_list->fival.pixel_format)
- && (fival->height == fival_list->fival.height)
- && (fival->width == fival_list->fival.width)) {
- if (i == fival->index)
+ while (fival_head->width && fival_head->height) {
+ if ((fival->pixel_format == fival_head->pixel_format)
+ && (fival->height == fival_head->height)
+ && (fival->width == fival_head->width)) {
+ if (i == index) {
break;
+ }
i++;
- }
- fival_list = fival_list->nxt;
+ }
+ fival_head++;
}
-
- if ((i==fival->index) && (fival_list != NULL)) {
- memcpy(fival, &fival_list->fival, sizeof(struct v4l2_frmivalenum));
+
+ if ((i == index) && (fival->height == fival_head->height) && (fival->width == fival_head->width)) {
+ memcpy(fival, fival_head, sizeof(struct v4l2_frmivalenum));
+ RK29CAMERA_DG("%s %dx%d@%c%c%c%c framerate : %d/%d\n", dev_name(rk29_camdev_info_ptr->icd->pdev),
+ fival->width, fival->height,
+ fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
+ (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
+ fival->discrete.denominator,fival->discrete.numerator);
} else {
+ if (index == 0)
+ RK29CAMERA_TR("%s have not catch %dx%d@%c%c%c%c index(%d) framerate\n",dev_name(rk29_camdev_info_ptr->icd->pdev),
+ fival->width,fival->height,
+ fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
+ (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
+ index);
+ else
+ RK29CAMERA_DG("%s have not catch %dx%d@%c%c%c%c index(%d) framerate\n",dev_name(rk29_camdev_info_ptr->icd->pdev),
+ fival->width,fival->height,
+ fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
+ (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
+ index);
ret = -EINVAL;
}
- } else {
- RK29CAMERA_TR("%s: fival_list is NULL\n",__FUNCTION__);
- ret = -EINVAL;
}
-
+rk29_camera_enum_frameintervals_end:
return ret;
}
int irq,i;
int err = 0;
- RK29CAMERA_DG("%s..%s..%d \n",__FUNCTION__,__FILE__,__LINE__);
+ RK29CAMERA_TR("RK29 Camera driver version: v%d.%d.%d Zoom by %s\n",(RK29_CAM_VERSION_CODE&0xff0000)>>16,
+ (RK29_CAM_VERSION_CODE&0xff00)>>8,RK29_CAM_VERSION_CODE&0xff,CAMERA_SCALE_CROP_MACHINE);
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irq = platform_get_irq(pdev, 0);
if (!res || irq < 0) {
if (pcdev->pdata && (strcmp(pcdev->pdata->meminfo.name,"camera_ipp_mem")==0)) {
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;
+ }
+
RK29CAMERA_DG("\n%s Memory(start:0x%x size:0x%x) for IPP obtain \n",__FUNCTION__, pcdev->pdata->meminfo.start,pcdev->pdata->meminfo.size);
} else {
RK29CAMERA_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);
+ INIT_LIST_HEAD(&pcdev->camera_work_queue);
spin_lock_init(&pcdev->lock);
+ spin_lock_init(&pcdev->camera_work_lock);
sema_init(&pcdev->zoominfo.sem,1);
/*
pcdev->fps_timer.function = rk29_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 = rk29_camera_scale_crop_ipp;
+#elif (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_ARM)
+ pcdev->icd_cb.scale_crop_cb = rk29_camera_scale_crop_arm;
+#endif
RK29CAMERA_DG("%s..%s..%d \n",__FUNCTION__,__FILE__,__LINE__);
return 0;
iounmap(pcdev->base);
exit_ioremap:
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:
if (pcdev->aclk_ddr_lcdc) {
clk_put(pcdev->aclk_ddr_lcdc);
soc_camera_host_unregister(&pcdev->soc_host);
+ iounmap((void __iomem*)pcdev->vipmem_phybase);
+ release_mem_region(pcdev->vipmem_phybase, pcdev->vipmem_size);
+
res = pcdev->res;
release_mem_region(res->start, res->end - res->start + 1);
MODULE_DESCRIPTION("RK29 Soc Camera Host driver");
MODULE_AUTHOR("ddl <ddl@rock-chips>");
MODULE_LICENSE("GPL");
+#endif