2 * V4L2 Driver for RK28 camera host
4 * Copyright (C) 2006, Sascha Hauer, Pengutronix
5 * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
13 #include <linux/init.h>
14 #include <linux/module.h>
16 #include <linux/delay.h>
17 #include <linux/slab.h>
18 #include <linux/dma-mapping.h>
19 #include <linux/errno.h>
21 #include <linux/interrupt.h>
22 #include <linux/kernel.h>
24 #include <linux/moduleparam.h>
25 #include <linux/time.h>
26 #include <linux/clk.h>
27 #include <linux/version.h>
28 #include <linux/device.h>
29 #include <linux/platform_device.h>
30 #include <linux/mutex.h>
31 #include <linux/videodev2.h>
32 #include <mach/rk29_camera.h>
33 #include <mach/rk29_iomap.h>
34 #include <mach/iomux.h>
35 #include <media/v4l2-common.h>
36 #include <media/v4l2-dev.h>
37 #include <media/videobuf-dma-contig.h>
38 #include <media/soc_camera.h>
39 #include <media/soc_mediabus.h>
40 #include <mach/rk29-ipp.h>
44 module_param(debug, int, S_IRUGO|S_IWUSR);
46 #define dprintk(level, fmt, arg...) do { \
48 printk(KERN_WARNING"rk29xx_camera: " fmt , ## arg); } while (0)
50 #define RK29CAMERA_TR(format, ...) printk(KERN_ERR format, ## __VA_ARGS__)
51 #define RK29CAMERA_DG(format, ...) dprintk(1, format, ## __VA_ARGS__)
54 #define RK29_VIP_AHBR_CTRL 0x00
55 #define RK29_VIP_INT_MASK 0x04
56 #define RK29_VIP_INT_STS 0x08
57 #define RK29_VIP_STS 0x0c
58 #define RK29_VIP_CTRL 0x10
59 #define RK29_VIP_CAPTURE_F1SA_Y 0x14
60 #define RK29_VIP_CAPTURE_F1SA_UV 0x18
61 #define RK29_VIP_CAPTURE_F1SA_Cr 0x1c
62 #define RK29_VIP_CAPTURE_F2SA_Y 0x20
63 #define RK29_VIP_CAPTURE_F2SA_UV 0x24
64 #define RK29_VIP_CAPTURE_F2SA_Cr 0x28
65 #define RK29_VIP_FB_SR 0x2c
66 #define RK29_VIP_FS 0x30
67 #define RK29_VIP_VIPRESERVED 0x34
68 #define RK29_VIP_CROP 0x38
69 #define RK29_VIP_CRM 0x3c
70 #define RK29_VIP_RESET 0x40
71 #define RK29_VIP_L_SFT 0x44
73 //The key register bit descrition
75 #define DISABLE_CAPTURE (0x00<<0)
76 #define ENABLE_CAPTURE (0x01<<0)
77 #define HSY_HIGH_ACTIVE (0x00<<1)
78 #define HSY_LOW_ACTIVE (0x01<<1)
79 #define VIP_CCIR656 (0x00<<2)
80 #define VIP_SENSOR (0x01<<2)
81 #define SENSOR_UYVY (0x00<<3)
82 #define SENSOR_YUYV (0x01<<3)
83 #define VIP_YUV (0x00<<4)
84 #define VIP_RAW (0x01<<4)
85 #define CON_OR_PIN (0x00<<5)
86 #define ONEFRAME (0x01<<5)
87 #define VIPREGYUV420 (0x00<<6)
88 #define VIPREGYUV422 (0x01<<6)
89 #define FIELD0_START (0x00<<7)
90 #define FIELD1_START (0x01<<7)
91 #define CONTINUOUS (0x00<<8)
92 #define PING_PONG (0x01<<8)
93 #define POSITIVE_EDGE (0x00<<9)
94 #define NEGATIVE_EDGE (0x01<<9)
95 #define VIPREGNTSC (0x00<<10)
96 #define VIPREGPAL (0x01<<10)
97 #define VIP_DATA_LITTLEEND (0x00<<11)
98 #define VIP_DATA_BIGEND (0x01<<11)
99 #define VSY_LOW_ACTIVE (0x00<<12)
100 #define VSY_HIGH_ACTIVE (0x01<<12)
101 #define VIP_RAWINPUT_BYPASS (0x00<<13)
102 #define VIP_RAWINPUT_POSITIVE_EDGE (0x01<<13)
103 #define VIP_RAWINPUT_NEGATIVE_EDGE (0x02<<13)
106 #define GRF_SOC_CON0_Reg 0xbc
107 #define VIP_AXIMASTER (0x00<<0)
108 #define VIP_AHBMASTER (0x01<<2)
111 #define GRF_OS_REG0 0xd0
112 #define VIP_ACLK_DIV_HCLK_1 (0x00<<0)
113 #define VIP_ACLK_DIV_HCLK_2 (0x01<<0)
116 #define MIN(x,y) ((x<y) ? x: y)
117 #define MAX(x,y) ((x>y) ? x: y)
118 #define RK29_SENSOR_24MHZ 24 /* MHz */
119 #define RK29_SENSOR_48MHZ 48
121 #define write_vip_reg(addr, val) __raw_writel(val, addr+(rk29_camdev_info_ptr->base))
122 #define read_vip_reg(addr) __raw_readl(addr+(rk29_camdev_info_ptr->base))
123 #define mask_vip_reg(addr, msk, val) write_vip_reg(addr, (val)|((~(msk))&read_vip_reg(addr)))
125 #define write_grf_reg(addr, val) __raw_writel(val, addr+RK29_GRF_BASE)
126 #define read_grf_reg(addr) __raw_readl(addr+RK29_GRF_BASE)
127 #define mask_grf_reg(addr, msk, val) write_vip_reg(addr, (val)|((~(msk))&read_vip_reg(addr)))
129 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_OFF
130 #define CAM_WORKQUEUE_IS_EN() ((pcdev->host_width != pcdev->icd->user_width) || (pcdev->host_height != pcdev->icd->user_height)\
131 || (pcdev->icd_cb.sensor_cb))
132 #define CAM_IPPWORK_IS_EN() ((pcdev->host_width != pcdev->icd->user_width) || (pcdev->host_height != pcdev->icd->user_height))
134 #define CAM_WORKQUEUE_IS_EN() (true)
135 #define CAM_IPPWORK_IS_EN() ((pcdev->zoominfo.a.c.width != pcdev->icd->user_width) || (pcdev->zoominfo.a.c.height != pcdev->icd->user_height))
139 * Driver Version Note
141 *v0.0.x : this driver is 2.6.32 kernel driver;
142 *v0.1.x : this driver is 3.0.8 kernel driver;
144 *v0.x.1 : this driver first support rk2918;
145 *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
146 * and V4L2_PIX_FMT_YUV422P;
147 *v0.x.3 : this driver support VIDIOC_ENUM_FRAMEINTERVALS;
148 *v0.x.4 : this driver support digital zoom;
149 *v0.x.5 : this driver support test framerate and query framerate from board file configuration;
150 *v0.x.6 : this driver improve test framerate method;
152 #define RK29_CAM_VERSION_CODE KERNEL_VERSION(0, 1, 6)
154 /* limit to rk29 hardware capabilities */
155 #define RK29_CAM_BUS_PARAM (SOCAM_MASTER |\
156 SOCAM_HSYNC_ACTIVE_HIGH |\
157 SOCAM_HSYNC_ACTIVE_LOW |\
158 SOCAM_VSYNC_ACTIVE_HIGH |\
159 SOCAM_VSYNC_ACTIVE_LOW |\
160 SOCAM_PCLK_SAMPLE_RISING |\
161 SOCAM_PCLK_SAMPLE_FALLING|\
162 SOCAM_DATA_ACTIVE_HIGH |\
163 SOCAM_DATA_ACTIVE_LOW|\
164 SOCAM_DATAWIDTH_8|SOCAM_DATAWIDTH_10|\
165 SOCAM_MCLK_24MHZ |SOCAM_MCLK_48MHZ)
167 #define RK29_CAM_W_MIN 48
168 #define RK29_CAM_H_MIN 32
169 #define RK29_CAM_W_MAX 3856 /* ddl@rock-chips.com : 10M Pixel */
170 #define RK29_CAM_H_MAX 2764
171 #define RK29_CAM_FRAME_INVAL_INIT 3
172 #define RK29_CAM_FRAME_INVAL_DC 3 /* ddl@rock-chips.com : */
173 #define RK29_CAM_FRAME_MEASURE 5
175 #define RK29_CAM_AXI 0
176 #define RK29_CAM_AHB 1
177 #define CONFIG_RK29_CAM_WORK_BUS RK29_CAM_AXI
179 extern void videobuf_dma_contig_free(struct videobuf_queue *q, struct videobuf_buffer *buf);
180 extern dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf);
182 /* buffer for one video frame */
185 /* common v4l buffer stuff -- must be first */
186 struct videobuf_buffer vb;
187 enum v4l2_mbus_pixelcode code;
190 enum rk29_camera_reg_state
196 struct rk29_camera_reg
198 unsigned int VipCtrl;
199 unsigned int VipCrop;
201 unsigned int VipIntMsk;
203 enum rk29_camera_reg_state Inval;
205 struct rk29_camera_work
207 struct videobuf_buffer *vb;
208 struct rk29_camera_dev *pcdev;
209 struct work_struct work;
211 struct rk29_camera_frmivalenum
213 struct v4l2_frmivalenum fival;
214 struct rk29_camera_frmivalenum *nxt;
216 struct rk29_camera_frmivalinfo
218 struct soc_camera_device *icd;
219 struct rk29_camera_frmivalenum *fival_list;
221 struct rk29_camera_zoominfo
223 struct semaphore sem;
227 struct rk29_camera_dev
229 struct soc_camera_host soc_host;
231 /* RK2827x is only supposed to handle one camera on its Quick Capture
232 * interface. If anyone ever builds hardware to enable more than
233 * one camera, they will have to modify this driver too */
234 struct soc_camera_device *icd;
236 struct clk *aclk_ddr_lcdc;
237 struct clk *aclk_disp_matrix;
239 struct clk *hclk_cpu_display;
240 struct clk *vip_slave;
243 struct clk *vip_input;
246 struct clk *hclk_disp_matrix;
247 struct clk *vip_matrix;
249 struct clk *pd_display;
252 void __iomem *grf_base;
253 int frame_inval; /* ddl@rock-chips.com : The first frames is invalidate */
256 unsigned long frame_interval;
258 unsigned int vipmem_phybase;
259 unsigned int vipmem_size;
260 unsigned int vipmem_bsize;
266 struct rk29camera_platform_data *pdata;
267 struct resource *res;
269 struct list_head capture;
270 struct rk29_camera_zoominfo zoominfo;
274 struct videobuf_buffer *active;
275 struct rk29_camera_reg reginfo_suspend;
276 struct workqueue_struct *camera_wq;
277 struct rk29_camera_work *camera_work;
278 unsigned int camera_work_count;
279 struct hrtimer fps_timer;
280 struct work_struct camera_reinit_work;
282 rk29_camera_sensor_cb_s icd_cb;
283 struct rk29_camera_frmivalinfo icd_frmival[2];
286 static const struct v4l2_queryctrl rk29_camera_controls[] =
288 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
290 .id = V4L2_CID_ZOOM_ABSOLUTE,
291 .type = V4L2_CTRL_TYPE_INTEGER,
292 .name = "DigitalZoom Control",
296 .default_value = 100,
301 static DEFINE_MUTEX(camera_lock);
302 static const char *rk29_cam_driver_description = "RK29_Camera";
303 static struct rk29_camera_dev *rk29_camdev_info_ptr;
305 static int rk29_camera_s_stream(struct soc_camera_device *icd, int enable);
309 * Videobuf operations
311 static int rk29_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
314 struct soc_camera_device *icd = vq->priv_data;
315 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
316 struct rk29_camera_dev *pcdev = ici->priv;
317 int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
318 icd->current_fmt->host_fmt);
320 dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size);
322 if (bytes_per_line < 0)
323 return bytes_per_line;
325 /* planar capture requires Y, U and V buffers to be page aligned */
326 *size = PAGE_ALIGN(bytes_per_line*icd->user_height); /* Y pages UV pages, yuv422*/
327 pcdev->vipmem_bsize = PAGE_ALIGN(bytes_per_line * pcdev->host_height);
330 if (CAM_WORKQUEUE_IS_EN()) {
331 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_OFF
332 if (CAM_IPPWORK_IS_EN())
335 BUG_ON(pcdev->vipmem_size<pcdev->vipmem_bsize);
336 if (*count > pcdev->vipmem_size/pcdev->vipmem_bsize) { /* Buffers must be limited, when this resolution is genered by IPP */
337 *count = pcdev->vipmem_size/pcdev->vipmem_bsize;
340 if ((pcdev->camera_work_count != *count) && pcdev->camera_work) {
341 kfree(pcdev->camera_work);
342 pcdev->camera_work = NULL;
343 pcdev->camera_work_count = 0;
346 if (pcdev->camera_work == NULL) {
347 pcdev->camera_work = kmalloc(sizeof(struct rk29_camera_work)*(*count), GFP_KERNEL);
348 if (pcdev->camera_work == NULL) {
349 RK29CAMERA_TR("\n %s kmalloc fail\n", __FUNCTION__);
352 pcdev->camera_work_count = *count;
356 RK29CAMERA_DG("%s..%d.. videobuf size:%d, vipmem_buf size:%d, count:%d \n",__FUNCTION__,__LINE__, *size,pcdev->vipmem_size, *count);
360 static void rk29_videobuf_free(struct videobuf_queue *vq, struct rk29_buffer *buf)
362 struct soc_camera_device *icd = vq->priv_data;
364 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
365 &buf->vb, buf->vb.baddr, buf->vb.bsize);
367 /* ddl@rock-chips.com: buf_release called soc_camera_streamoff and soc_camera_close*/
368 if (buf->vb.state == VIDEOBUF_NEEDS_INIT)
374 * This waits until this buffer is out of danger, i.e., until it is no
375 * longer in STATE_QUEUED or STATE_ACTIVE
377 //videobuf_waiton(vq, &buf->vb, 0, 0);
378 videobuf_dma_contig_free(vq, &buf->vb);
379 dev_dbg(&icd->dev, "%s freed\n", __func__);
380 buf->vb.state = VIDEOBUF_NEEDS_INIT;
383 static int rk29_videobuf_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, enum v4l2_field field)
385 struct soc_camera_device *icd = vq->priv_data;
386 struct rk29_buffer *buf;
388 int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
389 icd->current_fmt->host_fmt);
390 if (bytes_per_line < 0)
391 return bytes_per_line;
393 buf = container_of(vb, struct rk29_buffer, vb);
395 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
396 vb, vb->baddr, vb->bsize);
398 //RK29CAMERA_TR("\n%s..%d.. \n",__FUNCTION__,__LINE__);
400 /* Added list head initialization on alloc */
401 WARN_ON(!list_empty(&vb->queue));
403 /* This can be useful if you want to see if we actually fill
404 * the buffer with something */
405 //memset((void *)vb->baddr, 0xaa, vb->bsize);
407 BUG_ON(NULL == icd->current_fmt);
409 if (buf->code != icd->current_fmt->code ||
410 vb->width != icd->user_width ||
411 vb->height != icd->user_height ||
412 vb->field != field) {
413 buf->code = icd->current_fmt->code;
414 vb->width = icd->user_width;
415 vb->height = icd->user_height;
417 vb->state = VIDEOBUF_NEEDS_INIT;
420 vb->size = bytes_per_line*vb->height; /* ddl@rock-chips.com : fmt->depth is coorect */
421 if (0 != vb->baddr && vb->bsize < vb->size) {
426 if (vb->state == VIDEOBUF_NEEDS_INIT) {
427 ret = videobuf_iolock(vq, vb, NULL);
431 vb->state = VIDEOBUF_PREPARED;
433 //RK29CAMERA_TR("\n%s..%d.. \n",__FUNCTION__,__LINE__);
436 rk29_videobuf_free(vq, buf);
441 static inline void rk29_videobuf_capture(struct videobuf_buffer *vb)
443 unsigned int y_addr,uv_addr;
444 struct rk29_camera_dev *pcdev = rk29_camdev_info_ptr;
447 if (CAM_WORKQUEUE_IS_EN()) {
448 y_addr = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
449 uv_addr = y_addr + pcdev->host_width*pcdev->host_height;
451 if (y_addr > (pcdev->vipmem_phybase + pcdev->vipmem_size - pcdev->vipmem_bsize)) {
452 RK29CAMERA_TR("vipmem for IPP is overflow! %dx%d -> %dx%d vb_index:%d\n",pcdev->host_width,pcdev->host_height,
453 pcdev->icd->user_width,pcdev->icd->user_height, vb->i);
458 uv_addr = y_addr + vb->width * vb->height;
460 write_vip_reg(RK29_VIP_CAPTURE_F1SA_Y, y_addr);
461 write_vip_reg(RK29_VIP_CAPTURE_F1SA_UV, uv_addr);
462 write_vip_reg(RK29_VIP_CAPTURE_F2SA_Y, y_addr);
463 write_vip_reg(RK29_VIP_CAPTURE_F2SA_UV, uv_addr);
464 write_vip_reg(RK29_VIP_FB_SR, 0x00000002);//frame1 has been ready to receive data,frame 2 is not used
467 /* Locking: Caller holds q->irqlock */
468 static void rk29_videobuf_queue(struct videobuf_queue *vq,
469 struct videobuf_buffer *vb)
471 struct soc_camera_device *icd = vq->priv_data;
472 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
473 struct rk29_camera_dev *pcdev = ici->priv;
475 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
476 vb, vb->baddr, vb->bsize);
478 vb->state = VIDEOBUF_QUEUED;
480 if (list_empty(&pcdev->capture)) {
481 list_add_tail(&vb->queue, &pcdev->capture);
483 if (list_entry(pcdev->capture.next, struct videobuf_buffer, queue) != vb)
484 list_add_tail(&vb->queue, &pcdev->capture);
486 BUG(); /* ddl@rock-chips.com : The same videobuffer queue again */
488 if (!pcdev->active) {
490 rk29_videobuf_capture(vb);
493 static int rk29_pixfmt2ippfmt(unsigned int pixfmt, int *ippfmt)
497 case V4L2_PIX_FMT_NV16:
498 case V4L2_PIX_FMT_YUV422P:
500 *ippfmt = IPP_Y_CBCR_H2V1;
503 case V4L2_PIX_FMT_NV12:
504 case V4L2_PIX_FMT_YUV420:
506 *ippfmt = IPP_Y_CBCR_H2V2;
510 goto rk29_pixfmt2ippfmt_err;
514 rk29_pixfmt2ippfmt_err:
517 static void rk29_camera_capture_process(struct work_struct *work)
519 struct rk29_camera_work *camera_work = container_of(work, struct rk29_camera_work, work);
520 struct videobuf_buffer *vb = camera_work->vb;
521 struct rk29_camera_dev *pcdev = camera_work->pcdev;
522 struct rk29_ipp_req ipp_req;
523 unsigned long int flags;
524 int src_y_offset,src_uv_offset,dst_y_offset,dst_uv_offset,src_y_size,dst_y_size;
525 int scale_times,w,h,vipdata_base;
529 * IPP Dest image resolution is 2047x1088, so scale operation break up some times
531 if ((pcdev->icd->user_width > 0x7f0) || (pcdev->icd->user_height > 0x430)) {
532 scale_times = MAX((pcdev->icd->user_width/0x7f0),(pcdev->icd->user_height/0x430));
538 memset(&ipp_req, 0, sizeof(struct rk29_ipp_req));
540 down(&pcdev->zoominfo.sem);
542 ipp_req.timeout = 100;
543 ipp_req.flag = IPP_ROT_0;
544 ipp_req.src0.w = pcdev->zoominfo.a.c.width/scale_times;
545 ipp_req.src0.h = pcdev->zoominfo.a.c.height/scale_times;
546 ipp_req.src_vir_w = pcdev->host_width;
547 rk29_pixfmt2ippfmt(pcdev->pixfmt, &ipp_req.src0.fmt);
548 ipp_req.dst0.w = pcdev->icd->user_width/scale_times;
549 ipp_req.dst0.h = pcdev->icd->user_height/scale_times;
550 ipp_req.dst_vir_w = pcdev->icd->user_width;
551 rk29_pixfmt2ippfmt(pcdev->pixfmt, &ipp_req.dst0.fmt);
553 vipdata_base = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
554 src_y_size = pcdev->host_width*pcdev->host_height;
555 dst_y_size = pcdev->icd->user_width*pcdev->icd->user_height;
556 for (h=0; h<scale_times; h++) {
557 for (w=0; w<scale_times; w++) {
559 src_y_offset = (pcdev->zoominfo.a.c.top + h*pcdev->zoominfo.a.c.height/scale_times)* pcdev->host_width
560 + pcdev->zoominfo.a.c.left + w*pcdev->zoominfo.a.c.width/scale_times;
561 src_uv_offset = (pcdev->zoominfo.a.c.top + h*pcdev->zoominfo.a.c.height/scale_times)* pcdev->host_width/2
562 + pcdev->zoominfo.a.c.left + w*pcdev->zoominfo.a.c.width/scale_times;
564 dst_y_offset = pcdev->icd->user_width*pcdev->icd->user_height*h/scale_times + pcdev->icd->user_width*w/scale_times;
565 dst_uv_offset = pcdev->icd->user_width*pcdev->icd->user_height*h/scale_times/2 + pcdev->icd->user_width*w/scale_times;
567 ipp_req.src0.YrgbMst = vipdata_base + src_y_offset;
568 ipp_req.src0.CbrMst = vipdata_base + src_y_size + src_uv_offset;
569 ipp_req.dst0.YrgbMst = vb->boff + dst_y_offset;
570 ipp_req.dst0.CbrMst = vb->boff + dst_y_size + dst_uv_offset;
572 if (ipp_blit_sync(&ipp_req)) {
573 spin_lock_irqsave(&pcdev->lock, flags);
574 vb->state = VIDEOBUF_ERROR;
575 spin_unlock_irqrestore(&pcdev->lock, flags);
577 printk("Capture image(vb->i:0x%x) which IPP operated is error:\n",vb->i);
578 printk("widx:%d hidx:%d ",w,h);
579 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);
580 printk("ipp_req.src0.YrgbMst:0x%x ipp_req.src0.CbrMst:0x%x \n", ipp_req.src0.YrgbMst,ipp_req.src0.CbrMst);
581 printk("ipp_req.src0.w:0x%x ipp_req.src0.h:0x%x \n",ipp_req.src0.w,ipp_req.src0.h);
582 printk("ipp_req.src0.fmt:0x%x\n",ipp_req.src0.fmt);
583 printk("ipp_req.dst0.YrgbMst:0x%x ipp_req.dst0.CbrMst:0x%x \n",ipp_req.dst0.YrgbMst,ipp_req.dst0.CbrMst);
584 printk("ipp_req.dst0.w:0x%x ipp_req.dst0.h:0x%x \n",ipp_req.dst0.w ,ipp_req.dst0.h);
585 printk("ipp_req.dst0.fmt:0x%x\n",ipp_req.dst0.fmt);
586 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);
587 printk("ipp_req.timeout:0x%x ipp_req.flag :0x%x\n",ipp_req.timeout,ipp_req.flag);
594 if (pcdev->icd_cb.sensor_cb)
595 (pcdev->icd_cb.sensor_cb)(vb);
598 up(&pcdev->zoominfo.sem);
599 wake_up(&(camera_work->vb->done));
602 static irqreturn_t rk29_camera_irq(int irq, void *data)
604 struct rk29_camera_dev *pcdev = data;
605 struct videobuf_buffer *vb;
606 struct rk29_camera_work *wk;
607 static struct timeval first_tv;
610 read_vip_reg(RK29_VIP_INT_STS); /* clear vip interrupte single */
611 /* ddl@rock-chps.com : Current VIP is run in One Frame Mode, Frame 1 is validate */
612 if (read_vip_reg(RK29_VIP_FB_SR) & 0x01) {
614 do_gettimeofday(&first_tv);
618 goto RK29_CAMERA_IRQ_END;
620 if (pcdev->frame_inval>0) {
621 pcdev->frame_inval--;
622 rk29_videobuf_capture(pcdev->active);
623 goto RK29_CAMERA_IRQ_END;
624 } else if (pcdev->frame_inval) {
625 RK29CAMERA_TR("frame_inval : %0x",pcdev->frame_inval);
626 pcdev->frame_inval = 0;
629 if(pcdev->fps == RK29_CAM_FRAME_MEASURE) {
630 do_gettimeofday(&tv);
631 pcdev->frame_interval = ((tv.tv_sec*1000000 + tv.tv_usec) - (first_tv.tv_sec*1000000 + first_tv.tv_usec))
632 /(RK29_CAM_FRAME_MEASURE-1);
636 /* ddl@rock-chips.com : this vb may be deleted from queue */
637 if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) {
638 list_del_init(&vb->queue);
641 pcdev->active = NULL;
642 if (!list_empty(&pcdev->capture)) {
643 pcdev->active = list_entry(pcdev->capture.next, struct videobuf_buffer, queue);
645 rk29_videobuf_capture(pcdev->active);
649 if (pcdev->active == NULL) {
650 RK29CAMERA_DG("%s video_buf queue is empty!\n",__FUNCTION__);
653 if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) {
654 vb->state = VIDEOBUF_DONE;
655 do_gettimeofday(&vb->ts);
659 if (CAM_WORKQUEUE_IS_EN()) {
660 wk = pcdev->camera_work + vb->i;
661 INIT_WORK(&(wk->work), rk29_camera_capture_process);
664 queue_work(pcdev->camera_wq, &(wk->work));
675 static void rk29_videobuf_release(struct videobuf_queue *vq,
676 struct videobuf_buffer *vb)
678 struct rk29_buffer *buf = container_of(vb, struct rk29_buffer, vb);
679 struct soc_camera_device *icd = vq->priv_data;
680 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
681 struct rk29_camera_dev *pcdev = ici->priv;
683 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
684 vb, vb->baddr, vb->bsize);
688 case VIDEOBUF_ACTIVE:
689 dev_dbg(&icd->dev, "%s (active)\n", __func__);
691 case VIDEOBUF_QUEUED:
692 dev_dbg(&icd->dev, "%s (queued)\n", __func__);
694 case VIDEOBUF_PREPARED:
695 dev_dbg(&icd->dev, "%s (prepared)\n", __func__);
698 dev_dbg(&icd->dev, "%s (unknown)\n", __func__);
702 if (vb == pcdev->active) {
703 RK29CAMERA_DG("%s Wait for this video buf(0x%x) write finished!\n ",__FUNCTION__,(unsigned int)vb);
704 interruptible_sleep_on_timeout(&vb->done, 100);
705 RK29CAMERA_DG("%s This video buf(0x%x) write finished, release now!!\n",__FUNCTION__,(unsigned int)vb);
707 rk29_videobuf_free(vq, buf);
710 static struct videobuf_queue_ops rk29_videobuf_ops =
712 .buf_setup = rk29_videobuf_setup,
713 .buf_prepare = rk29_videobuf_prepare,
714 .buf_queue = rk29_videobuf_queue,
715 .buf_release = rk29_videobuf_release,
718 static void rk29_camera_init_videobuf(struct videobuf_queue *q,
719 struct soc_camera_device *icd)
721 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
722 struct rk29_camera_dev *pcdev = ici->priv;
724 /* We must pass NULL as dev pointer, then all pci_* dma operations
725 * transform to normal dma_* ones. */
726 videobuf_queue_dma_contig_init(q,
728 ici->v4l2_dev.dev, &pcdev->lock,
729 V4L2_BUF_TYPE_VIDEO_CAPTURE,
731 sizeof(struct rk29_buffer),
732 icd,&icd->video_lock);
734 static int rk29_camera_activate(struct rk29_camera_dev *pcdev, struct soc_camera_device *icd)
736 unsigned long sensor_bus_flags = SOCAM_MCLK_24MHZ;
739 RK29CAMERA_DG("%s..%d.. \n",__FUNCTION__,__LINE__);
740 if (!pcdev->aclk_ddr_lcdc || !pcdev->aclk_disp_matrix || !pcdev->hclk_cpu_display ||
741 !pcdev->vip_slave || !pcdev->vip_out || !pcdev->vip_input || !pcdev->vip_bus || !pcdev->pd_display ||
742 IS_ERR(pcdev->aclk_ddr_lcdc) || IS_ERR(pcdev->aclk_disp_matrix) || IS_ERR(pcdev->hclk_cpu_display) || IS_ERR(pcdev->pd_display) ||
743 IS_ERR(pcdev->vip_slave) || IS_ERR(pcdev->vip_out) || IS_ERR(pcdev->vip_input) || IS_ERR(pcdev->vip_bus)) {
745 RK29CAMERA_TR(KERN_ERR "failed to get vip_clk(axi) source\n");
746 goto RK29_CAMERA_ACTIVE_ERR;
749 if (!pcdev->hclk_disp_matrix || !pcdev->vip_matrix ||
750 IS_ERR(pcdev->hclk_disp_matrix) || IS_ERR(pcdev->vip_matrix)) {
752 RK29CAMERA_TR(KERN_ERR "failed to get vip_clk(ahb) source\n");
753 goto RK29_CAMERA_ACTIVE_ERR;
756 clk_enable(pcdev->pd_display);
758 clk_enable(pcdev->aclk_ddr_lcdc);
759 clk_enable(pcdev->aclk_disp_matrix);
761 clk_enable(pcdev->hclk_cpu_display);
762 clk_enable(pcdev->vip_slave);
764 #if (CONFIG_RK29_CAM_WORK_BUS==RK29_CAM_AHB)
765 clk_enable(pcdev->hclk_disp_matrix);
766 clk_enable(pcdev->vip_matrix);
769 clk_enable(pcdev->vip_input);
770 clk_enable(pcdev->vip_bus);
772 //if (icd->ops->query_bus_param) /* ddl@rock-chips.com : Query Sensor's xclk */
773 //sensor_bus_flags = icd->ops->query_bus_param(icd);
775 if (sensor_bus_flags & SOCAM_MCLK_48MHZ) {
776 parent = clk_get(NULL, "clk48m");
777 if (!parent || IS_ERR(parent))
778 goto RK29_CAMERA_ACTIVE_ERR;
779 } else if (sensor_bus_flags & SOCAM_MCLK_27MHZ) {
780 parent = clk_get(NULL, "extclk");
781 if (!parent || IS_ERR(parent))
782 goto RK29_CAMERA_ACTIVE_ERR;
784 parent = clk_get(NULL, "xin24m");
785 if (!parent || IS_ERR(parent))
786 goto RK29_CAMERA_ACTIVE_ERR;
789 clk_set_parent(pcdev->vip_out, parent);
791 clk_enable(pcdev->vip_out);
792 rk29_mux_api_set(GPIO1B4_VIPCLKOUT_NAME, GPIO1L_VIP_CLKOUT);
795 #if (CONFIG_RK29_CAM_WORK_BUS==RK29_CAM_AHB)
796 write_grf_reg(GRF_SOC_CON0_Reg, read_grf_reg(GRF_SOC_CON0_Reg)|VIP_AHBMASTER); //VIP Config to AHB
797 write_grf_reg(GRF_OS_REG0, read_grf_reg(GRF_OS_REG0)&(~VIP_ACLK_DIV_HCLK_2)); //aclk:hclk = 1:1
799 write_grf_reg(GRF_SOC_CON0_Reg, read_grf_reg(GRF_SOC_CON0_Reg)&(~VIP_AHBMASTER)); //VIP Config to AXI
800 write_grf_reg(GRF_OS_REG0, read_grf_reg(GRF_OS_REG0)|VIP_ACLK_DIV_HCLK_2); //aclk:hclk = 2:1
804 write_vip_reg(RK29_VIP_RESET, 0x76543210); /* ddl@rock-chips.com : vip software reset */
807 write_vip_reg(RK29_VIP_AHBR_CTRL, 0x07); /* ddl@rock-chips.com : vip ahb burst 16 */
808 write_vip_reg(RK29_VIP_INT_MASK, 0x01); //capture complete interrupt enable
809 write_vip_reg(RK29_VIP_CRM, 0x00000000); //Y/CB/CR color modification
812 RK29_CAMERA_ACTIVE_ERR:
816 static void rk29_camera_deactivate(struct rk29_camera_dev *pcdev)
818 //pcdev->active = NULL;
820 write_vip_reg(RK29_VIP_CTRL, 0);
821 read_vip_reg(RK29_VIP_INT_STS); //clear vip interrupte single
823 rk29_mux_api_set(GPIO1B4_VIPCLKOUT_NAME, GPIO1L_GPIO1B4);
824 clk_disable(pcdev->vip_out);
826 clk_disable(pcdev->vip_input);
827 clk_disable(pcdev->vip_bus);
829 #if (CONFIG_RK29_CAM_WORK_BUS==RK29_CAM_AHB)
830 clk_disable(pcdev->hclk_disp_matrix);
831 clk_disable(pcdev->vip_matrix);
834 clk_disable(pcdev->hclk_cpu_display);
835 clk_disable(pcdev->vip_slave);
837 clk_disable(pcdev->aclk_ddr_lcdc);
838 clk_disable(pcdev->aclk_disp_matrix);
840 clk_disable(pcdev->pd_display);
844 /* The following two functions absolutely depend on the fact, that
845 * there can be only one camera on RK28 quick capture interface */
846 static int rk29_camera_add_device(struct soc_camera_device *icd)
848 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
849 struct rk29_camera_dev *pcdev = ici->priv;
850 struct device *control = to_soc_camera_control(icd);
851 struct v4l2_subdev *sd;
853 struct rk29_camera_frmivalenum *fival_list,*fival_nxt;
855 mutex_lock(&camera_lock);
862 dev_info(&icd->dev, "RK29 Camera driver attached to camera%d(%s)\n",
863 icd->devnum,dev_name(icd->pdev));
865 pcdev->frame_inval = RK29_CAM_FRAME_INVAL_INIT;
866 pcdev->active = NULL;
868 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
869 pcdev->zoominfo.zoom_rate = 100;
871 /* ddl@rock-chips.com: capture list must be reset, because this list may be not empty,
872 * if app havn't dequeue all videobuf before close camera device;
874 INIT_LIST_HEAD(&pcdev->capture);
876 ret = rk29_camera_activate(pcdev,icd);
880 /* ddl@rock-chips.com : v4l2_subdev is not created when ici->ops->add called in soc_camera_probe */
882 sd = dev_get_drvdata(control);
883 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_IOREQUEST,(void*)pcdev->pdata);
885 ret = v4l2_subdev_call(sd,core, init, 0);
889 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_CB_REGISTER,(void*)(&pcdev->icd_cb));
896 for (i=0; i<2; i++) {
897 if (pcdev->icd_frmival[i].icd == icd)
899 if (pcdev->icd_frmival[i].icd == NULL) {
900 pcdev->icd_frmival[i].icd = icd;
905 if (icd_catch == 0) {
906 fival_list = pcdev->icd_frmival[0].fival_list;
907 fival_nxt = fival_list;
908 while(fival_nxt != NULL) {
909 fival_nxt = fival_list->nxt;
911 fival_list = fival_nxt;
913 pcdev->icd_frmival[0].icd = icd;
914 pcdev->icd_frmival[0].fival_list = kzalloc(sizeof(struct rk29_camera_frmivalenum),GFP_KERNEL);
917 mutex_unlock(&camera_lock);
921 static void rk29_camera_remove_device(struct soc_camera_device *icd)
923 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
924 struct rk29_camera_dev *pcdev = ici->priv;
925 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
927 mutex_lock(&camera_lock);
928 BUG_ON(icd != pcdev->icd);
930 dev_info(&icd->dev, "RK29 Camera driver detached from camera%d(%s)\n",
931 icd->devnum,dev_name(icd->pdev));
933 /* ddl@rock-chips.com: Application will call VIDIOC_STREAMOFF before close device, but
934 stream may be turn on again before close device, if suspend and resume happened. */
935 if (read_vip_reg(RK29_VIP_CTRL) & ENABLE_CAPTURE) {
936 rk29_camera_s_stream(icd,0);
939 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_DEACTIVATE,NULL);
940 rk29_camera_deactivate(pcdev);
942 if (pcdev->camera_work) {
943 kfree(pcdev->camera_work);
944 pcdev->camera_work = NULL;
945 pcdev->camera_work_count = 0;
948 pcdev->active = NULL;
950 pcdev->icd_cb.sensor_cb = NULL;
951 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
952 /* ddl@rock-chips.com: capture list must be reset, because this list may be not empty,
953 * if app havn't dequeue all videobuf before close camera device;
955 INIT_LIST_HEAD(&pcdev->capture);
957 mutex_unlock(&camera_lock);
958 RK29CAMERA_DG("%s exit\n",__FUNCTION__);
962 static int rk29_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
964 unsigned long bus_flags, camera_flags, common_flags;
965 unsigned int vip_ctrl_val = 0;
966 const struct soc_mbus_pixelfmt *fmt;
969 RK29CAMERA_DG("%s..%d..\n",__FUNCTION__,__LINE__);
971 fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code);
975 bus_flags = RK29_CAM_BUS_PARAM;
976 /* If requested data width is supported by the platform, use it */
977 switch (fmt->bits_per_sample) {
979 if (!(bus_flags & SOCAM_DATAWIDTH_10))
983 if (!(bus_flags & SOCAM_DATAWIDTH_9))
987 if (!(bus_flags & SOCAM_DATAWIDTH_8))
994 if (icd->ops->query_bus_param)
995 camera_flags = icd->ops->query_bus_param(icd);
999 common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
1000 if (!common_flags) {
1002 goto RK29_CAMERA_SET_BUS_PARAM_END;
1005 ret = icd->ops->set_bus_param(icd, common_flags);
1007 goto RK29_CAMERA_SET_BUS_PARAM_END;
1009 vip_ctrl_val = read_vip_reg(RK29_VIP_CTRL);
1010 if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) {
1011 vip_ctrl_val |= NEGATIVE_EDGE;
1013 vip_ctrl_val &= ~NEGATIVE_EDGE;
1015 if (common_flags & SOCAM_HSYNC_ACTIVE_LOW) {
1016 vip_ctrl_val |= HSY_LOW_ACTIVE;
1018 vip_ctrl_val &= ~HSY_LOW_ACTIVE;
1020 if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH) {
1021 vip_ctrl_val |= VSY_HIGH_ACTIVE;
1023 vip_ctrl_val &= ~VSY_HIGH_ACTIVE;
1026 /* ddl@rock-chips.com : Don't enable capture here, enable in stream_on */
1027 //vip_ctrl_val |= ENABLE_CAPTURE;
1029 write_vip_reg(RK29_VIP_CTRL, vip_ctrl_val);
1030 RK29CAMERA_DG("%s..ctrl:0x%x CtrReg=%x AXI_AHB:0x%x aclk_hclk:0x%x \n",__FUNCTION__,vip_ctrl_val,read_vip_reg(RK29_VIP_CTRL),
1031 read_grf_reg(GRF_SOC_CON0_Reg)&VIP_AHBMASTER, read_grf_reg(GRF_OS_REG0)&VIP_ACLK_DIV_HCLK_2);
1033 RK29_CAMERA_SET_BUS_PARAM_END:
1035 RK29CAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
1039 static int rk29_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
1041 unsigned long bus_flags, camera_flags;
1044 bus_flags = RK29_CAM_BUS_PARAM;
1045 if (icd->ops->query_bus_param) {
1046 camera_flags = icd->ops->query_bus_param(icd);
1050 ret = soc_camera_bus_param_compatible(camera_flags, bus_flags) ;
1053 dev_warn(icd->dev.parent,
1054 "Flags incompatible: camera %lx, host %lx\n",
1055 camera_flags, bus_flags);
1059 static const struct soc_mbus_pixelfmt rk29_camera_formats[] = {
1061 .fourcc = V4L2_PIX_FMT_NV12,
1062 .name = "YUV420 NV12",
1063 .bits_per_sample = 8,
1064 .packing = SOC_MBUS_PACKING_1_5X8,
1065 .order = SOC_MBUS_ORDER_LE,
1067 .fourcc = V4L2_PIX_FMT_NV16,
1068 .name = "YUV422 NV16",
1069 .bits_per_sample = 8,
1070 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1071 .order = SOC_MBUS_ORDER_LE,
1073 .fourcc = V4L2_PIX_FMT_YUV420,
1074 .name = "NV12(v0.0.1)",
1075 .bits_per_sample = 8,
1076 .packing = SOC_MBUS_PACKING_1_5X8,
1077 .order = SOC_MBUS_ORDER_LE,
1079 .fourcc = V4L2_PIX_FMT_YUV422P,
1080 .name = "NV16(v0.0.1)",
1081 .bits_per_sample = 8,
1082 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1083 .order = SOC_MBUS_ORDER_LE,
1087 static void rk29_camera_setup_format(struct soc_camera_device *icd, __u32 host_pixfmt, enum v4l2_mbus_pixelcode icd_code, struct v4l2_rect *rect)
1089 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1090 struct rk29_camera_dev *pcdev = ici->priv;
1091 unsigned int vip_fs = 0,vip_crop = 0;
1092 unsigned int vip_ctrl_val = VIP_SENSOR|ONEFRAME|DISABLE_CAPTURE;
1094 switch (host_pixfmt)
1096 case V4L2_PIX_FMT_NV16:
1097 case V4L2_PIX_FMT_YUV422P: /* ddl@rock-chips.com: V4L2_PIX_FMT_YUV422P is V4L2_PIX_FMT_NV16 actually in 0.0.1 driver */
1098 vip_ctrl_val |= VIPREGYUV422;
1099 pcdev->frame_inval = RK29_CAM_FRAME_INVAL_DC;
1100 pcdev->pixfmt = host_pixfmt;
1102 case V4L2_PIX_FMT_NV12:
1103 case V4L2_PIX_FMT_YUV420: /* ddl@rock-chips.com: V4L2_PIX_FMT_YUV420 is V4L2_PIX_FMT_NV12 actually in 0.0.1 driver */
1104 vip_ctrl_val |= VIPREGYUV420;
1105 if (pcdev->frame_inval != RK29_CAM_FRAME_INVAL_INIT)
1106 pcdev->frame_inval = RK29_CAM_FRAME_INVAL_INIT;
1107 pcdev->pixfmt = host_pixfmt;
1109 default: /* ddl@rock-chips.com : vip output format is hold when pixfmt is invalidate */
1110 vip_ctrl_val |= (read_vip_reg(RK29_VIP_CTRL) & VIPREGYUV422);
1116 case V4L2_MBUS_FMT_UYVY8_2X8:
1117 vip_ctrl_val |= SENSOR_UYVY;
1119 case V4L2_MBUS_FMT_YUYV8_2X8:
1120 vip_ctrl_val |= SENSOR_YUYV;
1123 vip_ctrl_val |= (read_vip_reg(RK29_VIP_CTRL) & SENSOR_YUYV);
1127 write_vip_reg(RK29_VIP_CTRL, vip_ctrl_val); /* ddl@rock-chips.com: VIP capture mode and capture format must be set before FS register set */
1129 read_vip_reg(RK29_VIP_INT_STS); /* clear vip interrupte single */
1131 if (vip_ctrl_val & ONEFRAME) {
1132 vip_crop = ((rect->left<<16) + rect->top);
1133 vip_fs = (((rect->width + rect->left)<<16) + (rect->height+rect->top));
1134 } else if (vip_ctrl_val & PING_PONG) {
1138 write_vip_reg(RK29_VIP_CROP, vip_crop);
1139 write_vip_reg(RK29_VIP_FS, vip_fs);
1141 write_vip_reg(RK29_VIP_FB_SR, 0x00000003);
1143 pcdev->host_width = rect->width;
1144 pcdev->host_height = rect->height;
1146 RK29CAMERA_DG("%s.. crop:0x%x fs:0x%x ctrl:0x%x CtrlReg:0x%x\n",__FUNCTION__,vip_crop,vip_fs,vip_ctrl_val,read_vip_reg(RK29_VIP_CTRL));
1150 static int rk29_camera_get_formats(struct soc_camera_device *icd, unsigned int idx,
1151 struct soc_camera_format_xlate *xlate)
1153 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1154 struct device *dev = icd->dev.parent;
1155 int formats = 0, ret;
1156 enum v4l2_mbus_pixelcode code;
1157 const struct soc_mbus_pixelfmt *fmt;
1159 ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
1161 /* No more formats */
1164 fmt = soc_mbus_get_fmtdesc(code);
1166 dev_err(dev, "Invalid format code #%u: %d\n", idx, code);
1170 ret = rk29_camera_try_bus_param(icd, fmt->bits_per_sample);
1175 case V4L2_MBUS_FMT_UYVY8_2X8:
1176 case V4L2_MBUS_FMT_YUYV8_2X8:
1179 xlate->host_fmt = &rk29_camera_formats[0];
1182 dev_dbg(dev, "Providing format %s using code %d\n",
1183 rk29_camera_formats[0].name,code);
1188 xlate->host_fmt = &rk29_camera_formats[1];
1191 dev_dbg(dev, "Providing format %s using code %d\n",
1192 rk29_camera_formats[1].name,code);
1197 xlate->host_fmt = &rk29_camera_formats[2];
1200 dev_dbg(dev, "Providing format %s using code %d\n",
1201 rk29_camera_formats[2].name,code);
1206 xlate->host_fmt = &rk29_camera_formats[3];
1209 dev_dbg(dev, "Providing format %s using code %d\n",
1210 rk29_camera_formats[3].name,code);;
1220 static void rk29_camera_put_formats(struct soc_camera_device *icd)
1225 static int rk29_camera_set_crop(struct soc_camera_device *icd,
1226 struct v4l2_crop *a)
1228 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1229 struct v4l2_mbus_framefmt mf;
1230 u32 fourcc = icd->current_fmt->host_fmt->fourcc;
1233 ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
1237 if ((mf.width < (a->c.left + a->c.width)) || (mf.height < (a->c.top + a->c.height))) {
1239 mf.width = a->c.left + a->c.width;
1240 mf.height = a->c.top + a->c.height;
1242 v4l_bound_align_image(&mf.width, RK29_CAM_W_MIN, RK29_CAM_W_MAX, 1,
1243 &mf.height, RK29_CAM_H_MIN, RK29_CAM_H_MAX, 0,
1244 fourcc == V4L2_PIX_FMT_NV16 ?4 : 0);
1246 ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
1251 rk29_camera_setup_format(icd, fourcc, mf.code, &a->c);
1253 icd->user_width = mf.width;
1254 icd->user_height = mf.height;
1259 static int rk29_camera_set_fmt(struct soc_camera_device *icd,
1260 struct v4l2_format *f)
1262 struct device *dev = icd->dev.parent;
1263 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1264 const struct soc_camera_format_xlate *xlate = NULL;
1265 struct soc_camera_host *ici =to_soc_camera_host(icd->dev.parent);
1266 struct rk29_camera_dev *pcdev = ici->priv;
1267 struct v4l2_pix_format *pix = &f->fmt.pix;
1268 struct v4l2_mbus_framefmt mf;
1269 struct v4l2_rect rect;
1270 int ret,usr_w,usr_h,icd_width,icd_height;
1274 usr_h = pix->height;
1275 RK29CAMERA_DG("%s enter width:%d height:%d\n",__FUNCTION__,usr_w,usr_h);
1277 xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
1279 dev_err(dev, "Format %x not found\n", pix->pixelformat);
1281 goto RK29_CAMERA_SET_FMT_END;
1284 /* ddl@rock-chips.com: sensor init code transmit in here after open */
1285 if (pcdev->icd_init == 0) {
1286 v4l2_subdev_call(sd,core, init, 0);
1287 pcdev->icd_init = 1;
1290 stream_on = read_vip_reg(RK29_VIP_CTRL);
1291 if (stream_on & ENABLE_CAPTURE)
1292 write_vip_reg(RK29_VIP_CTRL, (stream_on & (~ENABLE_CAPTURE)));
1294 mf.width = pix->width;
1295 mf.height = pix->height;
1296 mf.field = pix->field;
1297 mf.colorspace = pix->colorspace;
1298 mf.code = xlate->code;
1300 ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
1302 if (mf.code != xlate->code)
1305 icd_width = mf.width;
1306 icd_height = mf.height;
1307 #ifdef CONFIG_VIDEO_RK29_WORK_IPP
1308 if ((mf.width != usr_w) || (mf.height != usr_h)) {
1309 if (unlikely((mf.width <16) || (mf.width > 8190) || (mf.height < 16) || (mf.height > 8190))) {
1310 RK29CAMERA_TR("Senor and IPP both invalid source resolution(%dx%d)\n",mf.width,mf.height);
1312 goto RK29_CAMERA_SET_FMT_END;
1314 if (unlikely((usr_w <16)||(usr_h < 16))) {
1315 RK29CAMERA_TR("Senor and IPP both invalid destination resolution(%dx%d)\n",usr_w,usr_h);
1317 goto RK29_CAMERA_SET_FMT_END;
1328 rect.width = mf.width;
1329 rect.height = mf.height;
1331 down(&pcdev->zoominfo.sem);
1332 pcdev->zoominfo.a.c.width = rect.width*100/pcdev->zoominfo.zoom_rate;
1333 pcdev->zoominfo.a.c.width &= ~0x03;
1334 pcdev->zoominfo.a.c.height = rect.height*100/pcdev->zoominfo.zoom_rate;
1335 pcdev->zoominfo.a.c.height &= ~0x03;
1336 pcdev->zoominfo.a.c.left = ((rect.width - pcdev->zoominfo.a.c.width)>>1)&(~0x01);
1337 pcdev->zoominfo.a.c.top = ((rect.height - pcdev->zoominfo.a.c.height)>>1)&(~0x01);
1338 up(&pcdev->zoominfo.sem);
1340 /* ddl@rock-chips.com: IPP work limit check */
1341 if ((pcdev->zoominfo.a.c.width != usr_w) || (pcdev->zoominfo.a.c.height != usr_h)) {
1342 if (usr_w > 0x7f0) {
1343 if (((usr_w>>1)&0x3f) && (((usr_w>>1)&0x3f) <= 8)) {
1344 RK29CAMERA_TR("IPP Destination resolution(%dx%d, ((%d div 1) mod 64)=%d is <= 8)",usr_w,usr_h, usr_w, (int)((usr_w>>1)&0x3f));
1346 goto RK29_CAMERA_SET_FMT_END;
1349 if ((usr_w&0x3f) && ((usr_w&0x3f) <= 8)) {
1350 RK29CAMERA_TR("IPP Destination resolution(%dx%d, %d mod 64=%d is <= 8)",usr_w,usr_h, usr_w, (int)(usr_w&0x3f));
1352 goto RK29_CAMERA_SET_FMT_END;
1357 RK29CAMERA_DG("%s..%s icd width:%d host width:%d (zoom: %dx%d@(%d,%d)->%dx%d)\n",__FUNCTION__,xlate->host_fmt->name,
1358 rect.width, pix->width, pcdev->zoominfo.a.c.width,pcdev->zoominfo.a.c.height, pcdev->zoominfo.a.c.left,pcdev->zoominfo.a.c.top,
1359 pix->width, pix->height);
1360 rk29_camera_setup_format(icd, pix->pixelformat, mf.code, &rect);
1362 if (CAM_IPPWORK_IS_EN()) {
1363 BUG_ON(pcdev->vipmem_phybase == 0);
1365 pcdev->icd_width = icd_width;
1366 pcdev->icd_height = icd_height;
1368 pix->width = mf.width;
1369 pix->height = mf.height;
1370 pix->field = mf.field;
1371 pix->colorspace = mf.colorspace;
1372 icd->current_fmt = xlate;
1375 RK29_CAMERA_SET_FMT_END:
1376 if (stream_on & ENABLE_CAPTURE)
1377 write_vip_reg(RK29_VIP_CTRL, (read_vip_reg(RK29_VIP_CTRL) | ENABLE_CAPTURE));
1379 RK29CAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
1382 static bool rk29_camera_fmt_capturechk(struct v4l2_format *f)
1386 if ((f->fmt.pix.width == 1024) && (f->fmt.pix.height == 768)) {
1388 } else if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 1024)) {
1390 } else if ((f->fmt.pix.width == 1600) && (f->fmt.pix.height == 1200)) {
1392 } else if ((f->fmt.pix.width == 2048) && (f->fmt.pix.height == 1536)) {
1394 } else if ((f->fmt.pix.width == 2592) && (f->fmt.pix.height == 1944)) {
1399 RK29CAMERA_DG("%s %dx%d is capture format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
1402 static int rk29_camera_try_fmt(struct soc_camera_device *icd,
1403 struct v4l2_format *f)
1405 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1406 struct rk29_camera_dev *pcdev = ici->priv;
1407 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1408 const struct soc_camera_format_xlate *xlate;
1409 struct v4l2_pix_format *pix = &f->fmt.pix;
1410 __u32 pixfmt = pix->pixelformat;
1411 int ret,usr_w,usr_h,i;
1412 bool is_capture = rk29_camera_fmt_capturechk(f);
1413 bool vipmem_is_overflow = false;
1414 struct v4l2_mbus_framefmt mf;
1417 usr_h = pix->height;
1418 RK29CAMERA_DG("%s enter width:%d height:%d\n",__FUNCTION__,usr_w,usr_h);
1420 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
1422 dev_err(icd->dev.parent, "Format (%c%c%c%c) not found\n", pixfmt & 0xFF, (pixfmt >> 8) & 0xFF,
1423 (pixfmt >> 16) & 0xFF, (pixfmt >> 24) & 0xFF);
1425 RK29CAMERA_TR("%s(version:%c%c%c) support format:\n",rk29_cam_driver_description,(RK29_CAM_VERSION_CODE&0xff0000)>>16,
1426 (RK29_CAM_VERSION_CODE&0xff00)>>8,(RK29_CAM_VERSION_CODE&0xff));
1427 for (i = 0; i < icd->num_user_formats; i++)
1428 RK29CAMERA_TR("(%c%c%c%c)-%s\n",
1429 icd->user_formats[i].host_fmt->fourcc & 0xFF, (icd->user_formats[i].host_fmt->fourcc >> 8) & 0xFF,
1430 (icd->user_formats[i].host_fmt->fourcc >> 16) & 0xFF, (icd->user_formats[i].host_fmt->fourcc >> 24) & 0xFF,
1431 icd->user_formats[i].host_fmt->name);
1432 goto RK29_CAMERA_TRY_FMT_END;
1434 /* limit to rk29 hardware capabilities */
1435 v4l_bound_align_image(&pix->width, RK29_CAM_W_MIN, RK29_CAM_W_MAX, 1,
1436 &pix->height, RK29_CAM_H_MIN, RK29_CAM_H_MAX, 0,
1437 pixfmt == V4L2_PIX_FMT_NV16 ? 4 : 0);
1439 pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
1441 if (pix->bytesperline < 0)
1442 return pix->bytesperline;
1444 /* limit to sensor capabilities */
1445 mf.width = pix->width;
1446 mf.height = pix->height;
1447 mf.field = pix->field;
1448 mf.colorspace = pix->colorspace;
1449 mf.code = xlate->code;
1451 ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
1453 goto RK29_CAMERA_TRY_FMT_END;
1454 RK29CAMERA_DG("%s mf.width:%d mf.height:%d\n",__FUNCTION__,mf.width,mf.height);
1455 #ifdef CONFIG_VIDEO_RK29_WORK_IPP
1456 if ((mf.width > usr_w) && (mf.height > usr_h)) {
1458 vipmem_is_overflow = (PAGE_ALIGN(pix->bytesperline*pix->height) > pcdev->vipmem_size);
1460 /* Assume preview buffer minimum is 4 */
1461 vipmem_is_overflow = (PAGE_ALIGN(pix->bytesperline*pix->height)*4 > pcdev->vipmem_size);
1463 if (vipmem_is_overflow == false) {
1465 pix->height = usr_h;
1467 RK29CAMERA_TR("vipmem for IPP is overflow, This resolution(%dx%d -> %dx%d) is invalidate!\n",mf.width,mf.height,usr_w,usr_h);
1468 pix->width = mf.width;
1469 pix->height = mf.height;
1471 } else if ((mf.width < usr_w) && (mf.height < usr_h)) {
1472 if (((usr_w>>1) < mf.width) && ((usr_h>>1) < mf.height)) {
1474 vipmem_is_overflow = (PAGE_ALIGN(pix->bytesperline*pix->height) > pcdev->vipmem_size);
1476 vipmem_is_overflow = (PAGE_ALIGN(pix->bytesperline*pix->height)*4 > pcdev->vipmem_size);
1478 if (vipmem_is_overflow == false) {
1480 pix->height = usr_h;
1482 RK29CAMERA_TR("vipmem for IPP is overflow, This resolution(%dx%d -> %dx%d) is invalidate!\n",mf.width,mf.height,usr_w,usr_h);
1483 pix->width = mf.width;
1484 pix->height = mf.height;
1487 RK29CAMERA_TR("The aspect ratio(%dx%d/%dx%d) is bigger than 2 !\n",mf.width,mf.height,usr_w,usr_h);
1488 pix->width = mf.width;
1489 pix->height = mf.height;
1493 pix->width = mf.width;
1494 pix->height = mf.height;
1496 pix->colorspace = mf.colorspace;
1499 case V4L2_FIELD_ANY:
1500 case V4L2_FIELD_NONE:
1501 pix->field = V4L2_FIELD_NONE;
1504 /* TODO: support interlaced at least in pass-through mode */
1505 dev_err(icd->dev.parent, "Field type %d unsupported.\n",
1507 goto RK29_CAMERA_TRY_FMT_END;
1510 RK29_CAMERA_TRY_FMT_END:
1512 RK29CAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
1516 static int rk29_camera_reqbufs(struct soc_camera_device *icd,
1517 struct v4l2_requestbuffers *p)
1521 /* This is for locking debugging only. I removed spinlocks and now I
1522 * check whether .prepare is ever called on a linked buffer, or whether
1523 * a dma IRQ can occur for an in-work or unlinked buffer. Until now
1524 * it hadn't triggered */
1525 for (i = 0; i < p->count; i++) {
1526 struct rk29_buffer *buf = container_of(icd->vb_vidq.bufs[i],
1527 struct rk29_buffer, vb);
1529 INIT_LIST_HEAD(&buf->vb.queue);
1535 static unsigned int rk29_camera_poll(struct file *file, poll_table *pt)
1537 struct soc_camera_device *icd = file->private_data;
1538 struct rk29_buffer *buf;
1540 buf = list_entry(icd->vb_vidq.stream.next, struct rk29_buffer,
1543 poll_wait(file, &buf->vb.done, pt);
1545 if (buf->vb.state == VIDEOBUF_DONE ||
1546 buf->vb.state == VIDEOBUF_ERROR)
1547 return POLLIN|POLLRDNORM;
1552 static int rk29_camera_querycap(struct soc_camera_host *ici,
1553 struct v4l2_capability *cap)
1555 struct rk29_camera_dev *pcdev = ici->priv;
1556 char orientation[5];
1558 strlcpy(cap->card, dev_name(pcdev->icd->pdev), sizeof(cap->card));
1559 if (strcmp(dev_name(pcdev->icd->pdev), pcdev->pdata->info[0].dev_name) == 0) {
1560 sprintf(orientation,"-%d",pcdev->pdata->info[0].orientation);
1562 sprintf(orientation,"-%d",pcdev->pdata->info[1].orientation);
1564 strcat(cap->card,orientation);
1565 cap->version = RK29_CAM_VERSION_CODE;
1566 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1571 static int rk29_camera_suspend(struct soc_camera_device *icd, pm_message_t state)
1573 struct soc_camera_host *ici =
1574 to_soc_camera_host(icd->dev.parent);
1575 struct rk29_camera_dev *pcdev = ici->priv;
1576 struct v4l2_subdev *sd;
1579 mutex_lock(&camera_lock);
1580 if ((pcdev->icd == icd) && (icd->ops->suspend)) {
1581 rk29_camera_s_stream(icd, 0);
1582 sd = soc_camera_to_subdev(icd);
1583 v4l2_subdev_call(sd, video, s_stream, 0);
1584 ret = icd->ops->suspend(icd, state);
1586 pcdev->reginfo_suspend.VipCtrl = read_vip_reg(RK29_VIP_CTRL);
1587 pcdev->reginfo_suspend.VipCrop = read_vip_reg(RK29_VIP_CROP);
1588 pcdev->reginfo_suspend.VipFs = read_vip_reg(RK29_VIP_FS);
1589 pcdev->reginfo_suspend.VipIntMsk = read_vip_reg(RK29_VIP_INT_MASK);
1590 pcdev->reginfo_suspend.VipCrm = read_vip_reg(RK29_VIP_CRM);
1592 tmp = pcdev->reginfo_suspend.VipFs>>16; /* ddl@rock-chips.com */
1593 tmp += pcdev->reginfo_suspend.VipCrop>>16;
1594 pcdev->reginfo_suspend.VipFs = (pcdev->reginfo_suspend.VipFs & 0xffff) | (tmp<<16);
1596 pcdev->reginfo_suspend.Inval = Reg_Validate;
1597 rk29_camera_deactivate(pcdev);
1599 RK29CAMERA_DG("%s Enter Success...\n", __FUNCTION__);
1601 RK29CAMERA_DG("%s icd has been deattach, don't need enter suspend\n", __FUNCTION__);
1603 mutex_unlock(&camera_lock);
1607 static int rk29_camera_resume(struct soc_camera_device *icd)
1609 struct soc_camera_host *ici =
1610 to_soc_camera_host(icd->dev.parent);
1611 struct rk29_camera_dev *pcdev = ici->priv;
1612 struct v4l2_subdev *sd;
1615 mutex_lock(&camera_lock);
1616 if ((pcdev->icd == icd) && (icd->ops->resume)) {
1617 if (pcdev->reginfo_suspend.Inval == Reg_Validate) {
1618 rk29_camera_activate(pcdev, icd);
1619 write_vip_reg(RK29_VIP_INT_MASK, pcdev->reginfo_suspend.VipIntMsk);
1620 write_vip_reg(RK29_VIP_CRM, pcdev->reginfo_suspend.VipCrm);
1621 write_vip_reg(RK29_VIP_CTRL, pcdev->reginfo_suspend.VipCtrl&~ENABLE_CAPTURE);
1622 write_vip_reg(RK29_VIP_CROP, pcdev->reginfo_suspend.VipCrop);
1623 write_vip_reg(RK29_VIP_FS, pcdev->reginfo_suspend.VipFs);
1625 rk29_videobuf_capture(pcdev->active);
1626 rk29_camera_s_stream(icd, 1);
1627 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
1629 RK29CAMERA_TR("Resume fail, vip register recored is invalidate!!\n");
1630 goto rk29_camera_resume_end;
1633 ret = icd->ops->resume(icd);
1634 sd = soc_camera_to_subdev(icd);
1635 v4l2_subdev_call(sd, video, s_stream, 1);
1637 RK29CAMERA_DG("%s Enter success\n",__FUNCTION__);
1639 RK29CAMERA_DG("%s icd has been deattach, don't need enter resume\n", __FUNCTION__);
1642 rk29_camera_resume_end:
1643 mutex_unlock(&camera_lock);
1647 static void rk29_camera_reinit_work(struct work_struct *work)
1649 struct device *control;
1650 struct v4l2_subdev *sd;
1651 struct v4l2_mbus_framefmt mf;
1652 const struct soc_camera_format_xlate *xlate;
1655 write_vip_reg(RK29_VIP_CTRL, (read_vip_reg(RK29_VIP_CTRL)&(~ENABLE_CAPTURE)));
1657 control = to_soc_camera_control(rk29_camdev_info_ptr->icd);
1658 sd = dev_get_drvdata(control);
1659 ret = v4l2_subdev_call(sd,core, init, 1);
1661 mf.width = rk29_camdev_info_ptr->icd->user_width;
1662 mf.height = rk29_camdev_info_ptr->icd->user_height;
1663 xlate = soc_camera_xlate_by_fourcc(rk29_camdev_info_ptr->icd, rk29_camdev_info_ptr->icd->current_fmt->host_fmt->fourcc);
1664 mf.code = xlate->code;
1666 ret |= v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
1668 write_vip_reg(RK29_VIP_CTRL, (read_vip_reg(RK29_VIP_CTRL)|ENABLE_CAPTURE));
1670 RK29CAMERA_TR("Camera host haven't recevie data from sensor,Reinit sensor now! ret:0x%x\n",ret);
1672 static enum hrtimer_restart rk29_camera_fps_func(struct hrtimer *timer)
1674 struct rk29_camera_frmivalenum *fival_nxt=NULL,*fival_pre=NULL, *fival_rec=NULL;
1677 RK29CAMERA_DG("rk29_camera_fps_func fps:0x%x\n",rk29_camdev_info_ptr->fps);
1678 if (rk29_camdev_info_ptr->fps < 2) {
1679 RK29CAMERA_TR("Camera host haven't recevie data from sensor,Reinit sensor delay!\n");
1680 INIT_WORK(&rk29_camdev_info_ptr->camera_reinit_work, rk29_camera_reinit_work);
1681 queue_work(rk29_camdev_info_ptr->camera_wq,&(rk29_camdev_info_ptr->camera_reinit_work));
1683 for (i=0; i<2; i++) {
1684 if (rk29_camdev_info_ptr->icd == rk29_camdev_info_ptr->icd_frmival[i].icd) {
1685 fival_nxt = rk29_camdev_info_ptr->icd_frmival[i].fival_list;
1690 fival_pre = fival_nxt;
1691 while (fival_nxt != NULL) {
1693 RK29CAMERA_DG("%s %c%c%c%c %dx%d framerate : %d/%d\n", dev_name(&rk29_camdev_info_ptr->icd->dev),
1694 fival_nxt->fival.pixel_format & 0xFF, (fival_nxt->fival.pixel_format >> 8) & 0xFF,
1695 (fival_nxt->fival.pixel_format >> 16) & 0xFF, (fival_nxt->fival.pixel_format >> 24),
1696 fival_nxt->fival.width, fival_nxt->fival.height, fival_nxt->fival.discrete.denominator,
1697 fival_nxt->fival.discrete.numerator);
1699 if (((fival_nxt->fival.pixel_format == rk29_camdev_info_ptr->pixfmt)
1700 && (fival_nxt->fival.height == rk29_camdev_info_ptr->icd->user_height)
1701 && (fival_nxt->fival.width == rk29_camdev_info_ptr->icd->user_width))
1702 || (fival_nxt->fival.discrete.denominator == 0)) {
1704 fival_nxt->fival.index = 0;
1705 fival_nxt->fival.width = rk29_camdev_info_ptr->icd->user_width;
1706 fival_nxt->fival.height= rk29_camdev_info_ptr->icd->user_height;
1707 fival_nxt->fival.pixel_format = rk29_camdev_info_ptr->pixfmt;
1708 fival_nxt->fival.discrete.denominator = rk29_camdev_info_ptr->frame_interval;
1709 fival_nxt->fival.reserved[1] = (rk29_camdev_info_ptr->icd_width<<16)
1710 |(rk29_camdev_info_ptr->icd_height);
1711 fival_nxt->fival.discrete.numerator = 1000000;
1712 fival_nxt->fival.type = V4L2_FRMIVAL_TYPE_DISCRETE;
1715 fival_rec = fival_nxt;
1717 fival_pre = fival_nxt;
1718 fival_nxt = fival_nxt->nxt;
1721 if ((rec_flag == 0) && fival_pre) {
1722 fival_pre->nxt = kzalloc(sizeof(struct rk29_camera_frmivalenum), GFP_ATOMIC);
1723 if (fival_pre->nxt != NULL) {
1724 fival_pre->nxt->fival.index = fival_pre->fival.index++;
1725 fival_pre->nxt->fival.width = rk29_camdev_info_ptr->icd->user_width;
1726 fival_pre->nxt->fival.height= rk29_camdev_info_ptr->icd->user_height;
1727 fival_pre->nxt->fival.pixel_format = rk29_camdev_info_ptr->pixfmt;
1729 fival_pre->nxt->fival.discrete.denominator = rk29_camdev_info_ptr->frame_interval;
1731 fival_pre->nxt->fival.reserved[1] = (rk29_camdev_info_ptr->icd_width<<16)
1732 |(rk29_camdev_info_ptr->icd_height);
1734 fival_pre->nxt->fival.discrete.numerator = 1000000;
1735 fival_pre->nxt->fival.type = V4L2_FRMIVAL_TYPE_DISCRETE;
1737 fival_rec = fival_pre->nxt;
1742 return HRTIMER_NORESTART;
1744 static int rk29_camera_s_stream(struct soc_camera_device *icd, int enable)
1746 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1747 struct rk29_camera_dev *pcdev = ici->priv;
1751 WARN_ON(pcdev->icd != icd);
1752 pcdev->frame_interval = 0;
1753 vip_ctrl_val = read_vip_reg(RK29_VIP_CTRL);
1756 hrtimer_cancel(&pcdev->fps_timer);
1757 hrtimer_start(&pcdev->fps_timer,ktime_set(1, 0),HRTIMER_MODE_REL);
1758 vip_ctrl_val |= ENABLE_CAPTURE;
1760 vip_ctrl_val &= ~ENABLE_CAPTURE;
1761 ret = hrtimer_cancel(&pcdev->fps_timer);
1762 ret |= flush_work(&rk29_camdev_info_ptr->camera_reinit_work);
1763 RK29CAMERA_DG("STREAM_OFF cancel timer and flush work:0x%x \n", ret);
1765 write_vip_reg(RK29_VIP_CTRL, vip_ctrl_val);
1767 RK29CAMERA_DG("%s.. enable : 0x%x \n", __FUNCTION__, enable);
1770 int rk29_camera_enum_frameintervals(struct soc_camera_device *icd, struct v4l2_frmivalenum *fival)
1772 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1773 struct rk29_camera_dev *pcdev = ici->priv;
1774 struct rk29_camera_frmivalenum *fival_list = NULL;
1775 struct v4l2_frmivalenum *fival_head;
1776 int i,ret = 0,index;
1778 index = fival->index & 0x00ffffff;
1779 if ((fival->index & 0xff000000) == 0xff000000) { /* ddl@rock-chips.com: detect framerate */
1780 for (i=0; i<2; i++) {
1781 if (pcdev->icd_frmival[i].icd == icd) {
1782 fival_list = pcdev->icd_frmival[i].fival_list;
1786 if (fival_list != NULL) {
1788 while (fival_list != NULL) {
1789 if ((fival->pixel_format == fival_list->fival.pixel_format)
1790 && (fival->height == fival_list->fival.height)
1791 && (fival->width == fival_list->fival.width)) {
1796 fival_list = fival_list->nxt;
1799 if ((i==index) && (fival_list != NULL)) {
1800 memcpy(fival, &fival_list->fival, sizeof(struct v4l2_frmivalenum));
1805 RK29CAMERA_TR("%s: fival_list is NULL\n",__FUNCTION__);
1809 if (strcmp(dev_name(pcdev->icd->pdev),pcdev->pdata->info[0].dev_name) == 0) {
1810 fival_head = pcdev->pdata->info[0].fival;
1812 fival_head = pcdev->pdata->info[1].fival;
1815 while (fival_head->width && fival_head->height) {
1816 if ((fival->pixel_format == fival_head->pixel_format)
1817 && (fival->height == fival_head->height)
1818 && (fival->width == fival_head->width)) {
1827 if ((i == index) && (fival->height == fival_head->height) && (fival->width == fival_head->width)) {
1828 memcpy(fival, fival_head, sizeof(struct v4l2_frmivalenum));
1829 RK29CAMERA_DG("%s %dx%d@%c%c%c%c framerate : %d/%d\n", dev_name(&rk29_camdev_info_ptr->icd->dev),
1830 fival->width, fival->height,
1831 fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
1832 (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
1833 fival->discrete.denominator,fival->discrete.numerator);
1836 RK29CAMERA_TR("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(&rk29_camdev_info_ptr->icd->dev),
1837 fival->width,fival->height,
1838 fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
1839 (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
1842 RK29CAMERA_DG("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(&rk29_camdev_info_ptr->icd->dev),
1843 fival->width,fival->height,
1844 fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
1845 (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
1854 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
1855 static int rk29_camera_set_digit_zoom(struct soc_camera_device *icd,
1856 const struct v4l2_queryctrl *qctrl, int zoom_rate)
1859 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1860 struct rk29_camera_dev *pcdev = ici->priv;
1862 /* ddl@rock-chips.com : The largest resolution is 2047x1088, so larger resolution must be operated some times
1863 (Assume operate times is 4),but resolution which ipp can operate ,it is width and height must be even. */
1864 a.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1865 a.c.width = pcdev->host_width*100/zoom_rate;
1867 a.c.height = pcdev->host_height*100/zoom_rate;
1868 a.c.height &= ~0x03;
1870 a.c.left = ((pcdev->host_width - a.c.width)>>1)&(~0x01);
1871 a.c.top = ((pcdev->host_height - a.c.height)>>1)&(~0x01);
1873 down(&pcdev->zoominfo.sem);
1874 pcdev->zoominfo.a.c.height = a.c.height;
1875 pcdev->zoominfo.a.c.width = a.c.width;
1876 pcdev->zoominfo.a.c.top = a.c.top;
1877 pcdev->zoominfo.a.c.left = a.c.left;
1878 up(&pcdev->zoominfo.sem);
1880 RK29CAMERA_DG("%s..zoom_rate:%d (%dx%d at (%d,%d)-> %dx%d)\n",__FUNCTION__, zoom_rate,a.c.width, a.c.height, a.c.left, a.c.top, pcdev->host_width, pcdev->host_height );
1885 static inline struct v4l2_queryctrl const *rk29_camera_soc_camera_find_qctrl(
1886 struct soc_camera_host_ops *ops, int id)
1890 for (i = 0; i < ops->num_controls; i++)
1891 if (ops->controls[i].id == id)
1892 return &ops->controls[i];
1898 static int rk29_camera_set_ctrl(struct soc_camera_device *icd,
1899 struct v4l2_control *sctrl)
1902 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1903 const struct v4l2_queryctrl *qctrl;
1904 struct rk29_camera_dev *pcdev = ici->priv;
1907 qctrl = rk29_camera_soc_camera_find_qctrl(ici->ops, sctrl->id);
1910 goto rk29_camera_set_ctrl_end;
1915 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
1916 case V4L2_CID_ZOOM_ABSOLUTE:
1918 if ((sctrl->value < qctrl->minimum) || (sctrl->value > qctrl->maximum)){
1920 goto rk29_camera_set_ctrl_end;
1922 ret = rk29_camera_set_digit_zoom(icd, qctrl, sctrl->value);
1924 pcdev->zoominfo.zoom_rate = sctrl->value;
1926 goto rk29_camera_set_ctrl_end;
1935 rk29_camera_set_ctrl_end:
1939 static struct soc_camera_host_ops rk29_soc_camera_host_ops =
1941 .owner = THIS_MODULE,
1942 .add = rk29_camera_add_device,
1943 .remove = rk29_camera_remove_device,
1944 .suspend = rk29_camera_suspend,
1945 .resume = rk29_camera_resume,
1946 .enum_frameinervals = rk29_camera_enum_frameintervals,
1947 .set_crop = rk29_camera_set_crop,
1948 .get_formats = rk29_camera_get_formats,
1949 .put_formats = rk29_camera_put_formats,
1950 .set_fmt = rk29_camera_set_fmt,
1951 .try_fmt = rk29_camera_try_fmt,
1952 .init_videobuf = rk29_camera_init_videobuf,
1953 .reqbufs = rk29_camera_reqbufs,
1954 .poll = rk29_camera_poll,
1955 .querycap = rk29_camera_querycap,
1956 .set_bus_param = rk29_camera_set_bus_param,
1957 .s_stream = rk29_camera_s_stream, /* ddl@rock-chips.com : Add stream control for host */
1958 .set_ctrl = rk29_camera_set_ctrl,
1959 .controls = rk29_camera_controls,
1960 .num_controls = ARRAY_SIZE(rk29_camera_controls)
1963 static int rk29_camera_probe(struct platform_device *pdev)
1965 struct rk29_camera_dev *pcdev;
1966 struct resource *res;
1967 struct rk29_camera_frmivalenum *fival_list,*fival_nxt;
1971 RK29CAMERA_DG("%s..%s..%d \n",__FUNCTION__,__FILE__,__LINE__);
1972 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1973 irq = platform_get_irq(pdev, 0);
1974 if (!res || irq < 0) {
1979 pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL);
1981 dev_err(&pdev->dev, "Could not allocate pcdev\n");
1985 rk29_camdev_info_ptr = pcdev;
1987 /*config output clk*/
1988 pcdev->aclk_ddr_lcdc = clk_get(&pdev->dev, "aclk_ddr_lcdc");
1989 pcdev->aclk_disp_matrix = clk_get(&pdev->dev, "aclk_disp_matrix");
1991 pcdev->hclk_cpu_display = clk_get(&pdev->dev, "hclk_cpu_display");
1992 pcdev->vip_slave = clk_get(&pdev->dev, "vip_slave");
1993 pcdev->vip_out = clk_get(&pdev->dev,"vip_out");
1994 pcdev->vip_input = clk_get(&pdev->dev,"vip_input");
1995 pcdev->vip_bus = clk_get(&pdev->dev, "vip_bus");
1997 pcdev->hclk_disp_matrix = clk_get(&pdev->dev,"hclk_disp_matrix");
1998 pcdev->vip_matrix = clk_get(&pdev->dev,"vip_matrix");
2000 pcdev->pd_display = clk_get(&pdev->dev,"pd_display");
2002 pcdev->zoominfo.zoom_rate = 100;
2004 if (!pcdev->aclk_ddr_lcdc || !pcdev->aclk_disp_matrix || !pcdev->hclk_cpu_display ||
2005 !pcdev->vip_slave || !pcdev->vip_out || !pcdev->vip_input || !pcdev->vip_bus || !pcdev->pd_display ||
2006 IS_ERR(pcdev->aclk_ddr_lcdc) || IS_ERR(pcdev->aclk_disp_matrix) || IS_ERR(pcdev->hclk_cpu_display) || IS_ERR(pcdev->pd_display) ||
2007 IS_ERR(pcdev->vip_slave) || IS_ERR(pcdev->vip_out) || IS_ERR(pcdev->vip_input) || IS_ERR(pcdev->vip_bus)) {
2009 RK29CAMERA_TR(KERN_ERR "failed to get vip_clk(axi) source\n");
2014 if (!pcdev->hclk_disp_matrix || !pcdev->vip_matrix ||
2015 IS_ERR(pcdev->hclk_disp_matrix) || IS_ERR(pcdev->vip_matrix)) {
2017 RK29CAMERA_TR(KERN_ERR "failed to get vip_clk(ahb) source\n");
2022 dev_set_drvdata(&pdev->dev, pcdev);
2025 pcdev->pdata = pdev->dev.platform_data; /* ddl@rock-chips.com : Request IO in init function */
2026 if (pcdev->pdata && pcdev->pdata->io_init) {
2027 pcdev->pdata->io_init();
2029 #ifdef CONFIG_VIDEO_RK29_WORK_IPP
2030 if (pcdev->pdata && (strcmp(pcdev->pdata->meminfo.name,"camera_ipp_mem")==0)) {
2031 pcdev->vipmem_phybase = pcdev->pdata->meminfo.start;
2032 pcdev->vipmem_size = pcdev->pdata->meminfo.size;
2033 RK29CAMERA_DG("\n%s Memory(start:0x%x size:0x%x) for IPP obtain \n",__FUNCTION__, pcdev->pdata->meminfo.start,pcdev->pdata->meminfo.size);
2035 RK29CAMERA_TR("\n%s Memory for IPP have not obtain! IPP Function is fail\n",__FUNCTION__);
2036 pcdev->vipmem_phybase = 0;
2037 pcdev->vipmem_size = 0;
2040 INIT_LIST_HEAD(&pcdev->capture);
2041 spin_lock_init(&pcdev->lock);
2042 sema_init(&pcdev->zoominfo.sem,1);
2045 * Request the regions.
2047 if (!request_mem_region(res->start, res->end - res->start + 1,
2048 RK29_CAM_DRV_NAME)) {
2053 pcdev->base = ioremap(res->start, res->end - res->start + 1);
2054 if (pcdev->base == NULL) {
2055 dev_err(pcdev->dev, "ioremap() of registers failed\n");
2061 pcdev->dev = &pdev->dev;
2063 /* config buffer address */
2065 err = request_irq(pcdev->irq, rk29_camera_irq, 0, RK29_CAM_DRV_NAME,
2068 dev_err(pcdev->dev, "Camera interrupt register failed \n");
2072 pcdev->camera_wq = create_workqueue("rk_camera_workqueue");
2073 if (pcdev->camera_wq == NULL)
2075 INIT_WORK(&pcdev->camera_reinit_work, rk29_camera_reinit_work);
2077 for (i=0; i<2; i++) {
2078 pcdev->icd_frmival[i].icd = NULL;
2079 pcdev->icd_frmival[i].fival_list = kzalloc(sizeof(struct rk29_camera_frmivalenum),GFP_KERNEL);
2083 pcdev->soc_host.drv_name = RK29_CAM_DRV_NAME;
2084 pcdev->soc_host.ops = &rk29_soc_camera_host_ops;
2085 pcdev->soc_host.priv = pcdev;
2086 pcdev->soc_host.v4l2_dev.dev = &pdev->dev;
2087 pcdev->soc_host.nr = pdev->id;
2089 err = soc_camera_host_register(&pcdev->soc_host);
2093 hrtimer_init(&pcdev->fps_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
2094 pcdev->fps_timer.function = rk29_camera_fps_func;
2095 pcdev->icd_cb.sensor_cb = NULL;
2097 RK29CAMERA_DG("%s..%s..%d \n",__FUNCTION__,__FILE__,__LINE__);
2102 for (i=0; i<2; i++) {
2103 fival_list = pcdev->icd_frmival[i].fival_list;
2104 fival_nxt = fival_list;
2105 while(fival_nxt != NULL) {
2106 fival_nxt = fival_list->nxt;
2108 fival_list = fival_nxt;
2112 free_irq(pcdev->irq, pcdev);
2113 if (pcdev->camera_wq) {
2114 destroy_workqueue(pcdev->camera_wq);
2115 pcdev->camera_wq = NULL;
2118 iounmap(pcdev->base);
2120 release_mem_region(res->start, res->end - res->start + 1);
2122 if (pcdev->aclk_ddr_lcdc) {
2123 clk_put(pcdev->aclk_ddr_lcdc);
2124 pcdev->aclk_ddr_lcdc = NULL;
2126 if (pcdev->aclk_disp_matrix) {
2127 clk_put(pcdev->aclk_disp_matrix);
2128 pcdev->aclk_disp_matrix = NULL;
2130 if (pcdev->hclk_cpu_display) {
2131 clk_put(pcdev->hclk_cpu_display);
2132 pcdev->hclk_cpu_display = NULL;
2134 if (pcdev->vip_slave) {
2135 clk_put(pcdev->vip_slave);
2136 pcdev->vip_slave = NULL;
2138 if (pcdev->vip_out) {
2139 clk_put(pcdev->vip_out);
2140 pcdev->vip_out = NULL;
2142 if (pcdev->vip_input) {
2143 clk_put(pcdev->vip_input);
2144 pcdev->vip_input = NULL;
2146 if (pcdev->vip_bus) {
2147 clk_put(pcdev->vip_bus);
2148 pcdev->vip_bus = NULL;
2150 if (pcdev->hclk_disp_matrix) {
2151 clk_put(pcdev->hclk_disp_matrix);
2152 pcdev->hclk_disp_matrix = NULL;
2154 if (pcdev->vip_matrix) {
2155 clk_put(pcdev->vip_matrix);
2156 pcdev->vip_matrix = NULL;
2160 rk29_camdev_info_ptr = NULL;
2165 static int __devexit rk29_camera_remove(struct platform_device *pdev)
2167 struct rk29_camera_dev *pcdev = platform_get_drvdata(pdev);
2168 struct resource *res;
2169 struct rk29_camera_frmivalenum *fival_list,*fival_nxt;
2172 free_irq(pcdev->irq, pcdev);
2174 if (pcdev->camera_wq) {
2175 destroy_workqueue(pcdev->camera_wq);
2176 pcdev->camera_wq = NULL;
2179 for (i=0; i<2; i++) {
2180 fival_list = pcdev->icd_frmival[i].fival_list;
2181 fival_nxt = fival_list;
2182 while(fival_nxt != NULL) {
2183 fival_nxt = fival_list->nxt;
2185 fival_list = fival_nxt;
2189 soc_camera_host_unregister(&pcdev->soc_host);
2192 release_mem_region(res->start, res->end - res->start + 1);
2194 if (pcdev->pdata && pcdev->pdata->io_deinit) { /* ddl@rock-chips.com : Free IO in deinit function */
2195 pcdev->pdata->io_deinit(0);
2196 pcdev->pdata->io_deinit(1);
2200 rk29_camdev_info_ptr = NULL;
2201 dev_info(&pdev->dev, "RK28 Camera driver unloaded\n");
2206 static struct platform_driver rk29_camera_driver =
2209 .name = RK29_CAM_DRV_NAME,
2211 .probe = rk29_camera_probe,
2212 .remove = __devexit_p(rk29_camera_remove),
2216 static int __devinit rk29_camera_init(void)
2218 RK29CAMERA_DG("%s..%s..%d \n",__FUNCTION__,__FILE__,__LINE__);
2219 return platform_driver_register(&rk29_camera_driver);
2222 static void __exit rk29_camera_exit(void)
2224 platform_driver_unregister(&rk29_camera_driver);
2227 device_initcall_sync(rk29_camera_init);
2228 module_exit(rk29_camera_exit);
2230 MODULE_DESCRIPTION("RK29 Soc Camera Host driver");
2231 MODULE_AUTHOR("ddl <ddl@rock-chips>");
2232 MODULE_LICENSE("GPL");