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
140 *v0.0.1 : this driver first support rk2918;
141 *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
142 * and V4L2_PIX_FMT_YUV422P;
143 *v0.0.3 : this driver support VIDIOC_ENUM_FRAMEINTERVALS;
144 *v0.0.4 : this driver support digital zoom;
146 #define RK29_CAM_VERSION_CODE KERNEL_VERSION(0, 1, 3)
148 /* limit to rk29 hardware capabilities */
149 #define RK29_CAM_BUS_PARAM (SOCAM_MASTER |\
150 SOCAM_HSYNC_ACTIVE_HIGH |\
151 SOCAM_HSYNC_ACTIVE_LOW |\
152 SOCAM_VSYNC_ACTIVE_HIGH |\
153 SOCAM_VSYNC_ACTIVE_LOW |\
154 SOCAM_PCLK_SAMPLE_RISING |\
155 SOCAM_PCLK_SAMPLE_FALLING|\
156 SOCAM_DATA_ACTIVE_HIGH |\
157 SOCAM_DATA_ACTIVE_LOW|\
158 SOCAM_DATAWIDTH_8|SOCAM_DATAWIDTH_10|\
159 SOCAM_MCLK_24MHZ |SOCAM_MCLK_48MHZ)
161 #define RK29_CAM_W_MIN 48
162 #define RK29_CAM_H_MIN 32
163 #define RK29_CAM_W_MAX 3856 /* ddl@rock-chips.com : 10M Pixel */
164 #define RK29_CAM_H_MAX 2764
165 #define RK29_CAM_FRAME_INVAL_INIT 3
166 #define RK29_CAM_FRAME_INVAL_DC 3 /* ddl@rock-chips.com : */
168 #define RK29_CAM_AXI 0
169 #define RK29_CAM_AHB 1
170 #define CONFIG_RK29_CAM_WORK_BUS RK29_CAM_AXI
172 extern void videobuf_dma_contig_free(struct videobuf_queue *q, struct videobuf_buffer *buf);
173 extern dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf);
175 /* buffer for one video frame */
178 /* common v4l buffer stuff -- must be first */
179 struct videobuf_buffer vb;
180 enum v4l2_mbus_pixelcode code;
183 enum rk29_camera_reg_state
189 struct rk29_camera_reg
191 unsigned int VipCtrl;
192 unsigned int VipCrop;
194 unsigned int VipIntMsk;
196 enum rk29_camera_reg_state Inval;
198 struct rk29_camera_work
200 struct videobuf_buffer *vb;
201 struct rk29_camera_dev *pcdev;
202 struct work_struct work;
204 struct rk29_camera_frmivalenum
206 struct v4l2_frmivalenum fival;
207 struct rk29_camera_frmivalenum *nxt;
209 struct rk29_camera_frmivalinfo
211 struct soc_camera_device *icd;
212 struct rk29_camera_frmivalenum *fival_list;
214 struct rk29_camera_zoominfo
216 struct semaphore sem;
220 struct rk29_camera_dev
222 struct soc_camera_host soc_host;
224 /* RK2827x is only supposed to handle one camera on its Quick Capture
225 * interface. If anyone ever builds hardware to enable more than
226 * one camera, they will have to modify this driver too */
227 struct soc_camera_device *icd;
229 struct clk *aclk_ddr_lcdc;
230 struct clk *aclk_disp_matrix;
232 struct clk *hclk_cpu_display;
233 struct clk *vip_slave;
236 struct clk *vip_input;
239 struct clk *hclk_disp_matrix;
240 struct clk *vip_matrix;
242 struct clk *pd_display;
245 void __iomem *grf_base;
246 int frame_inval; /* ddl@rock-chips.com : The first frames is invalidate */
250 unsigned int vipmem_phybase;
251 unsigned int vipmem_size;
252 unsigned int vipmem_bsize;
256 struct rk29camera_platform_data *pdata;
257 struct resource *res;
259 struct list_head capture;
260 struct rk29_camera_zoominfo zoominfo;
264 struct videobuf_buffer *active;
265 struct rk29_camera_reg reginfo_suspend;
266 struct workqueue_struct *camera_wq;
267 struct rk29_camera_work *camera_work;
268 unsigned int camera_work_count;
269 struct hrtimer fps_timer;
270 struct work_struct camera_reinit_work;
272 rk29_camera_sensor_cb_s icd_cb;
273 struct rk29_camera_frmivalinfo icd_frmival[2];
276 static const struct v4l2_queryctrl rk29_camera_controls[] =
278 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
280 .id = V4L2_CID_ZOOM_ABSOLUTE,
281 .type = V4L2_CTRL_TYPE_INTEGER,
282 .name = "DigitalZoom Control",
286 .default_value = 100,
291 static DEFINE_MUTEX(camera_lock);
292 static const char *rk29_cam_driver_description = "RK29_Camera";
293 static struct rk29_camera_dev *rk29_camdev_info_ptr;
295 static int rk29_camera_s_stream(struct soc_camera_device *icd, int enable);
299 * Videobuf operations
301 static int rk29_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
304 struct soc_camera_device *icd = vq->priv_data;
305 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
306 struct rk29_camera_dev *pcdev = ici->priv;
307 int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
308 icd->current_fmt->host_fmt);
310 dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size);
312 if (bytes_per_line < 0)
313 return bytes_per_line;
315 /* planar capture requires Y, U and V buffers to be page aligned */
316 *size = PAGE_ALIGN(bytes_per_line*icd->user_height); /* Y pages UV pages, yuv422*/
317 pcdev->vipmem_bsize = PAGE_ALIGN(bytes_per_line * pcdev->host_height);
320 if (CAM_WORKQUEUE_IS_EN()) {
321 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_OFF
322 if (CAM_IPPWORK_IS_EN())
325 BUG_ON(pcdev->vipmem_size<pcdev->vipmem_bsize);
326 if (*count > pcdev->vipmem_size/pcdev->vipmem_bsize) { /* Buffers must be limited, when this resolution is genered by IPP */
327 *count = pcdev->vipmem_size/pcdev->vipmem_bsize;
330 if ((pcdev->camera_work_count != *count) && pcdev->camera_work) {
331 kfree(pcdev->camera_work);
332 pcdev->camera_work = NULL;
333 pcdev->camera_work_count = 0;
336 if (pcdev->camera_work == NULL) {
337 pcdev->camera_work = kmalloc(sizeof(struct rk29_camera_work)*(*count), GFP_KERNEL);
338 if (pcdev->camera_work == NULL) {
339 RK29CAMERA_TR("\n %s kmalloc fail\n", __FUNCTION__);
342 pcdev->camera_work_count = *count;
346 RK29CAMERA_DG("%s..%d.. videobuf size:%d, vipmem_buf size:%d, count:%d \n",__FUNCTION__,__LINE__, *size,pcdev->vipmem_size, *count);
350 static void rk29_videobuf_free(struct videobuf_queue *vq, struct rk29_buffer *buf)
352 struct soc_camera_device *icd = vq->priv_data;
354 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
355 &buf->vb, buf->vb.baddr, buf->vb.bsize);
357 /* ddl@rock-chips.com: buf_release called soc_camera_streamoff and soc_camera_close*/
358 if (buf->vb.state == VIDEOBUF_NEEDS_INIT)
364 * This waits until this buffer is out of danger, i.e., until it is no
365 * longer in STATE_QUEUED or STATE_ACTIVE
367 //videobuf_waiton(vq, &buf->vb, 0, 0);
368 videobuf_dma_contig_free(vq, &buf->vb);
369 dev_dbg(&icd->dev, "%s freed\n", __func__);
370 buf->vb.state = VIDEOBUF_NEEDS_INIT;
373 static int rk29_videobuf_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, enum v4l2_field field)
375 struct soc_camera_device *icd = vq->priv_data;
376 struct rk29_buffer *buf;
378 int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
379 icd->current_fmt->host_fmt);
380 if (bytes_per_line < 0)
381 return bytes_per_line;
383 buf = container_of(vb, struct rk29_buffer, vb);
385 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
386 vb, vb->baddr, vb->bsize);
388 //RK29CAMERA_TR("\n%s..%d.. \n",__FUNCTION__,__LINE__);
390 /* Added list head initialization on alloc */
391 WARN_ON(!list_empty(&vb->queue));
393 /* This can be useful if you want to see if we actually fill
394 * the buffer with something */
395 //memset((void *)vb->baddr, 0xaa, vb->bsize);
397 BUG_ON(NULL == icd->current_fmt);
399 if (buf->code != icd->current_fmt->code ||
400 vb->width != icd->user_width ||
401 vb->height != icd->user_height ||
402 vb->field != field) {
403 buf->code = icd->current_fmt->code;
404 vb->width = icd->user_width;
405 vb->height = icd->user_height;
407 vb->state = VIDEOBUF_NEEDS_INIT;
410 vb->size = bytes_per_line*vb->height; /* ddl@rock-chips.com : fmt->depth is coorect */
411 if (0 != vb->baddr && vb->bsize < vb->size) {
416 if (vb->state == VIDEOBUF_NEEDS_INIT) {
417 ret = videobuf_iolock(vq, vb, NULL);
421 vb->state = VIDEOBUF_PREPARED;
423 //RK29CAMERA_TR("\n%s..%d.. \n",__FUNCTION__,__LINE__);
426 rk29_videobuf_free(vq, buf);
431 static inline void rk29_videobuf_capture(struct videobuf_buffer *vb)
433 unsigned int y_addr,uv_addr;
434 struct rk29_camera_dev *pcdev = rk29_camdev_info_ptr;
437 if (CAM_WORKQUEUE_IS_EN()) {
438 y_addr = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
439 uv_addr = y_addr + pcdev->host_width*pcdev->host_height;
441 if (y_addr > (pcdev->vipmem_phybase + pcdev->vipmem_size - pcdev->vipmem_bsize)) {
442 RK29CAMERA_TR("vipmem for IPP is overflow! %dx%d -> %dx%d vb_index:%d\n",pcdev->host_width,pcdev->host_height,
443 pcdev->icd->user_width,pcdev->icd->user_height, vb->i);
448 uv_addr = y_addr + vb->width * vb->height;
450 write_vip_reg(RK29_VIP_CAPTURE_F1SA_Y, y_addr);
451 write_vip_reg(RK29_VIP_CAPTURE_F1SA_UV, uv_addr);
452 write_vip_reg(RK29_VIP_CAPTURE_F2SA_Y, y_addr);
453 write_vip_reg(RK29_VIP_CAPTURE_F2SA_UV, uv_addr);
454 write_vip_reg(RK29_VIP_FB_SR, 0x00000002);//frame1 has been ready to receive data,frame 2 is not used
457 /* Locking: Caller holds q->irqlock */
458 static void rk29_videobuf_queue(struct videobuf_queue *vq,
459 struct videobuf_buffer *vb)
461 struct soc_camera_device *icd = vq->priv_data;
462 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
463 struct rk29_camera_dev *pcdev = ici->priv;
465 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
466 vb, vb->baddr, vb->bsize);
468 vb->state = VIDEOBUF_QUEUED;
470 if (list_empty(&pcdev->capture)) {
471 list_add_tail(&vb->queue, &pcdev->capture);
473 if (list_entry(pcdev->capture.next, struct videobuf_buffer, queue) != vb)
474 list_add_tail(&vb->queue, &pcdev->capture);
476 BUG(); /* ddl@rock-chips.com : The same videobuffer queue again */
478 if (!pcdev->active) {
480 rk29_videobuf_capture(vb);
483 static int rk29_pixfmt2ippfmt(unsigned int pixfmt, int *ippfmt)
487 case V4L2_PIX_FMT_NV16:
488 case V4L2_PIX_FMT_YUV422P:
490 *ippfmt = IPP_Y_CBCR_H2V1;
493 case V4L2_PIX_FMT_NV12:
494 case V4L2_PIX_FMT_YUV420:
496 *ippfmt = IPP_Y_CBCR_H2V2;
500 goto rk29_pixfmt2ippfmt_err;
504 rk29_pixfmt2ippfmt_err:
507 static void rk29_camera_capture_process(struct work_struct *work)
509 struct rk29_camera_work *camera_work = container_of(work, struct rk29_camera_work, work);
510 struct videobuf_buffer *vb = camera_work->vb;
511 struct rk29_camera_dev *pcdev = camera_work->pcdev;
512 struct rk29_ipp_req ipp_req;
513 unsigned long int flags;
514 int src_y_offset,src_uv_offset,dst_y_offset,dst_uv_offset,src_y_size,dst_y_size;
515 int scale_times,w,h,vipdata_base;
519 * IPP Dest image resolution is 2047x1088, so scale operation break up some times
521 if ((pcdev->icd->user_width > 0x7f0) || (pcdev->icd->user_height > 0x430)) {
522 scale_times = MAX((pcdev->icd->user_width/0x7f0),(pcdev->icd->user_height/0x430));
528 memset(&ipp_req, 0, sizeof(struct rk29_ipp_req));
530 down(&pcdev->zoominfo.sem);
532 ipp_req.timeout = 100;
533 ipp_req.flag = IPP_ROT_0;
534 ipp_req.src0.w = pcdev->zoominfo.a.c.width/scale_times;
535 ipp_req.src0.h = pcdev->zoominfo.a.c.height/scale_times;
536 ipp_req.src_vir_w = pcdev->host_width;
537 rk29_pixfmt2ippfmt(pcdev->pixfmt, &ipp_req.src0.fmt);
538 ipp_req.dst0.w = pcdev->icd->user_width/scale_times;
539 ipp_req.dst0.h = pcdev->icd->user_height/scale_times;
540 ipp_req.dst_vir_w = pcdev->icd->user_width;
541 rk29_pixfmt2ippfmt(pcdev->pixfmt, &ipp_req.dst0.fmt);
543 vipdata_base = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
544 src_y_size = pcdev->host_width*pcdev->host_height;
545 dst_y_size = pcdev->icd->user_width*pcdev->icd->user_height;
547 for (h=0; h<scale_times; h++) {
548 for (w=0; w<scale_times; w++) {
550 src_y_offset = (pcdev->zoominfo.a.c.top + h*pcdev->zoominfo.a.c.height/scale_times)* pcdev->host_width
551 + pcdev->zoominfo.a.c.left + w*pcdev->zoominfo.a.c.width/scale_times;
552 src_uv_offset = (pcdev->zoominfo.a.c.top + h*pcdev->zoominfo.a.c.height/scale_times)* pcdev->host_width/2
553 + pcdev->zoominfo.a.c.left + w*pcdev->zoominfo.a.c.width/scale_times;
555 dst_y_offset = pcdev->icd->user_width*pcdev->icd->user_height*h/scale_times + pcdev->icd->user_width*w/scale_times;
556 dst_uv_offset = pcdev->icd->user_width*pcdev->icd->user_height*h/scale_times/2 + pcdev->icd->user_width*w/scale_times;
558 ipp_req.src0.YrgbMst = vipdata_base + src_y_offset;
559 ipp_req.src0.CbrMst = vipdata_base + src_y_size + src_uv_offset;
560 ipp_req.dst0.YrgbMst = vb->boff + dst_y_offset;
561 ipp_req.dst0.CbrMst = vb->boff + dst_y_size + dst_uv_offset;
563 if (ipp_blit_sync(&ipp_req)) {
564 spin_lock_irqsave(&pcdev->lock, flags);
565 vb->state = VIDEOBUF_ERROR;
566 spin_unlock_irqrestore(&pcdev->lock, flags);
568 RK29CAMERA_TR("Capture image(vb->i:0x%x) which IPP operated is error:\n",vb->i);
569 RK29CAMERA_TR("widx:%d hidx:%d ",w,h);
570 RK29CAMERA_TR("%dx%d@(%d,%d)->%dx%d\n",pcdev->zoominfo.a.c.width,pcdev->zoominfo.a.c.height,pcdev->zoominfo.a.c.left,pcdev->zoominfo.a.c.top,pcdev->icd->user_width,pcdev->icd->user_height);
571 RK29CAMERA_TR("ipp_req.src0.YrgbMst:0x%x ipp_req.src0.CbrMst:0x%x \n", ipp_req.src0.YrgbMst,ipp_req.src0.CbrMst);
572 RK29CAMERA_TR("ipp_req.src0.w:0x%x ipp_req.src0.h:0x%x \n",ipp_req.src0.w,ipp_req.src0.h);
573 RK29CAMERA_TR("ipp_req.src0.fmt:0x%x\n",ipp_req.src0.fmt);
574 RK29CAMERA_TR("ipp_req.dst0.YrgbMst:0x%x ipp_req.dst0.CbrMst:0x%x \n",ipp_req.dst0.YrgbMst,ipp_req.dst0.CbrMst);
575 RK29CAMERA_TR("ipp_req.dst0.w:0x%x ipp_req.dst0.h:0x%x \n",ipp_req.dst0.w ,ipp_req.dst0.h);
576 RK29CAMERA_TR("ipp_req.dst0.fmt:0x%x\n",ipp_req.dst0.fmt);
577 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);
578 RK29CAMERA_TR("ipp_req.timeout:0x%x ipp_req.flag :0x%x\n",ipp_req.timeout,ipp_req.flag);
585 if (pcdev->icd_cb.sensor_cb)
586 (pcdev->icd_cb.sensor_cb)(vb);
589 up(&pcdev->zoominfo.sem);
590 wake_up(&(camera_work->vb->done));
593 static irqreturn_t rk29_camera_irq(int irq, void *data)
595 struct rk29_camera_dev *pcdev = data;
596 struct videobuf_buffer *vb;
597 struct rk29_camera_work *wk;
599 read_vip_reg(RK29_VIP_INT_STS); /* clear vip interrupte single */
600 /* ddl@rock-chps.com : Current VIP is run in One Frame Mode, Frame 1 is validate */
601 if (read_vip_reg(RK29_VIP_FB_SR) & 0x01) {
604 goto RK29_CAMERA_IRQ_END;
606 if (pcdev->frame_inval>0) {
607 pcdev->frame_inval--;
608 rk29_videobuf_capture(pcdev->active);
609 goto RK29_CAMERA_IRQ_END;
610 } else if (pcdev->frame_inval) {
611 RK29CAMERA_TR("frame_inval : %0x",pcdev->frame_inval);
612 pcdev->frame_inval = 0;
616 /* ddl@rock-chips.com : this vb may be deleted from queue */
617 if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) {
618 list_del_init(&vb->queue);
621 pcdev->active = NULL;
622 if (!list_empty(&pcdev->capture)) {
623 pcdev->active = list_entry(pcdev->capture.next, struct videobuf_buffer, queue);
625 rk29_videobuf_capture(pcdev->active);
629 if (pcdev->active == NULL) {
630 RK29CAMERA_DG("%s video_buf queue is empty!\n",__FUNCTION__);
633 if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) {
634 vb->state = VIDEOBUF_DONE;
635 do_gettimeofday(&vb->ts);
639 if (CAM_WORKQUEUE_IS_EN()) {
640 wk = pcdev->camera_work + vb->i;
641 INIT_WORK(&(wk->work), rk29_camera_capture_process);
644 queue_work(pcdev->camera_wq, &(wk->work));
655 static void rk29_videobuf_release(struct videobuf_queue *vq,
656 struct videobuf_buffer *vb)
658 struct rk29_buffer *buf = container_of(vb, struct rk29_buffer, vb);
659 struct soc_camera_device *icd = vq->priv_data;
660 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
661 struct rk29_camera_dev *pcdev = ici->priv;
663 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
664 vb, vb->baddr, vb->bsize);
668 case VIDEOBUF_ACTIVE:
669 dev_dbg(&icd->dev, "%s (active)\n", __func__);
671 case VIDEOBUF_QUEUED:
672 dev_dbg(&icd->dev, "%s (queued)\n", __func__);
674 case VIDEOBUF_PREPARED:
675 dev_dbg(&icd->dev, "%s (prepared)\n", __func__);
678 dev_dbg(&icd->dev, "%s (unknown)\n", __func__);
682 if (vb == pcdev->active) {
683 RK29CAMERA_DG("%s Wait for this video buf(0x%x) write finished!\n ",__FUNCTION__,(unsigned int)vb);
684 interruptible_sleep_on_timeout(&vb->done, 100);
685 RK29CAMERA_DG("%s This video buf(0x%x) write finished, release now!!\n",__FUNCTION__,(unsigned int)vb);
687 rk29_videobuf_free(vq, buf);
690 static struct videobuf_queue_ops rk29_videobuf_ops =
692 .buf_setup = rk29_videobuf_setup,
693 .buf_prepare = rk29_videobuf_prepare,
694 .buf_queue = rk29_videobuf_queue,
695 .buf_release = rk29_videobuf_release,
698 static void rk29_camera_init_videobuf(struct videobuf_queue *q,
699 struct soc_camera_device *icd)
701 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
702 struct rk29_camera_dev *pcdev = ici->priv;
704 /* We must pass NULL as dev pointer, then all pci_* dma operations
705 * transform to normal dma_* ones. */
706 videobuf_queue_dma_contig_init(q,
708 ici->v4l2_dev.dev, &pcdev->lock,
709 V4L2_BUF_TYPE_VIDEO_CAPTURE,
711 sizeof(struct rk29_buffer),
712 icd,&icd->video_lock);
714 static int rk29_camera_activate(struct rk29_camera_dev *pcdev, struct soc_camera_device *icd)
716 unsigned long sensor_bus_flags = SOCAM_MCLK_24MHZ;
719 RK29CAMERA_DG("%s..%d.. \n",__FUNCTION__,__LINE__);
720 if (!pcdev->aclk_ddr_lcdc || !pcdev->aclk_disp_matrix || !pcdev->hclk_cpu_display ||
721 !pcdev->vip_slave || !pcdev->vip_out || !pcdev->vip_input || !pcdev->vip_bus || !pcdev->pd_display ||
722 IS_ERR(pcdev->aclk_ddr_lcdc) || IS_ERR(pcdev->aclk_disp_matrix) || IS_ERR(pcdev->hclk_cpu_display) || IS_ERR(pcdev->pd_display) ||
723 IS_ERR(pcdev->vip_slave) || IS_ERR(pcdev->vip_out) || IS_ERR(pcdev->vip_input) || IS_ERR(pcdev->vip_bus)) {
725 RK29CAMERA_TR(KERN_ERR "failed to get vip_clk(axi) source\n");
726 goto RK29_CAMERA_ACTIVE_ERR;
729 if (!pcdev->hclk_disp_matrix || !pcdev->vip_matrix ||
730 IS_ERR(pcdev->hclk_disp_matrix) || IS_ERR(pcdev->vip_matrix)) {
732 RK29CAMERA_TR(KERN_ERR "failed to get vip_clk(ahb) source\n");
733 goto RK29_CAMERA_ACTIVE_ERR;
736 clk_enable(pcdev->pd_display);
738 clk_enable(pcdev->aclk_ddr_lcdc);
739 clk_enable(pcdev->aclk_disp_matrix);
741 clk_enable(pcdev->hclk_cpu_display);
742 clk_enable(pcdev->vip_slave);
744 #if (CONFIG_RK29_CAM_WORK_BUS==RK29_CAM_AHB)
745 clk_enable(pcdev->hclk_disp_matrix);
746 clk_enable(pcdev->vip_matrix);
749 clk_enable(pcdev->vip_input);
750 clk_enable(pcdev->vip_bus);
752 //if (icd->ops->query_bus_param) /* ddl@rock-chips.com : Query Sensor's xclk */
753 //sensor_bus_flags = icd->ops->query_bus_param(icd);
755 if (sensor_bus_flags & SOCAM_MCLK_48MHZ) {
756 parent = clk_get(NULL, "clk48m");
757 if (!parent || IS_ERR(parent))
758 goto RK29_CAMERA_ACTIVE_ERR;
759 } else if (sensor_bus_flags & SOCAM_MCLK_27MHZ) {
760 parent = clk_get(NULL, "extclk");
761 if (!parent || IS_ERR(parent))
762 goto RK29_CAMERA_ACTIVE_ERR;
764 parent = clk_get(NULL, "xin24m");
765 if (!parent || IS_ERR(parent))
766 goto RK29_CAMERA_ACTIVE_ERR;
769 clk_set_parent(pcdev->vip_out, parent);
771 clk_enable(pcdev->vip_out);
772 rk29_mux_api_set(GPIO1B4_VIPCLKOUT_NAME, GPIO1L_VIP_CLKOUT);
775 #if (CONFIG_RK29_CAM_WORK_BUS==RK29_CAM_AHB)
776 write_grf_reg(GRF_SOC_CON0_Reg, read_grf_reg(GRF_SOC_CON0_Reg)|VIP_AHBMASTER); //VIP Config to AHB
777 write_grf_reg(GRF_OS_REG0, read_grf_reg(GRF_OS_REG0)&(~VIP_ACLK_DIV_HCLK_2)); //aclk:hclk = 1:1
779 write_grf_reg(GRF_SOC_CON0_Reg, read_grf_reg(GRF_SOC_CON0_Reg)&(~VIP_AHBMASTER)); //VIP Config to AXI
780 write_grf_reg(GRF_OS_REG0, read_grf_reg(GRF_OS_REG0)|VIP_ACLK_DIV_HCLK_2); //aclk:hclk = 2:1
784 write_vip_reg(RK29_VIP_RESET, 0x76543210); /* ddl@rock-chips.com : vip software reset */
787 write_vip_reg(RK29_VIP_AHBR_CTRL, 0x07); /* ddl@rock-chips.com : vip ahb burst 16 */
788 write_vip_reg(RK29_VIP_INT_MASK, 0x01); //capture complete interrupt enable
789 write_vip_reg(RK29_VIP_CRM, 0x00000000); //Y/CB/CR color modification
792 RK29_CAMERA_ACTIVE_ERR:
796 static void rk29_camera_deactivate(struct rk29_camera_dev *pcdev)
798 //pcdev->active = NULL;
800 write_vip_reg(RK29_VIP_CTRL, 0);
801 read_vip_reg(RK29_VIP_INT_STS); //clear vip interrupte single
803 rk29_mux_api_set(GPIO1B4_VIPCLKOUT_NAME, GPIO1L_GPIO1B4);
804 clk_disable(pcdev->vip_out);
806 clk_disable(pcdev->vip_input);
807 clk_disable(pcdev->vip_bus);
809 #if (CONFIG_RK29_CAM_WORK_BUS==RK29_CAM_AHB)
810 clk_disable(pcdev->hclk_disp_matrix);
811 clk_disable(pcdev->vip_matrix);
814 clk_disable(pcdev->hclk_cpu_display);
815 clk_disable(pcdev->vip_slave);
817 clk_disable(pcdev->aclk_ddr_lcdc);
818 clk_disable(pcdev->aclk_disp_matrix);
820 clk_disable(pcdev->pd_display);
824 /* The following two functions absolutely depend on the fact, that
825 * there can be only one camera on RK28 quick capture interface */
826 static int rk29_camera_add_device(struct soc_camera_device *icd)
828 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
829 struct rk29_camera_dev *pcdev = ici->priv;
830 struct device *control = to_soc_camera_control(icd);
831 struct v4l2_subdev *sd;
833 struct rk29_camera_frmivalenum *fival_list,*fival_nxt;
835 mutex_lock(&camera_lock);
842 dev_info(&icd->dev, "RK29 Camera driver attached to camera%d(%s)\n",
843 icd->devnum,dev_name(icd->pdev));
845 pcdev->frame_inval = RK29_CAM_FRAME_INVAL_INIT;
846 pcdev->active = NULL;
848 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
849 pcdev->zoominfo.zoom_rate = 100;
851 /* ddl@rock-chips.com: capture list must be reset, because this list may be not empty,
852 * if app havn't dequeue all videobuf before close camera device;
854 INIT_LIST_HEAD(&pcdev->capture);
856 ret = rk29_camera_activate(pcdev,icd);
860 /* ddl@rock-chips.com : v4l2_subdev is not created when ici->ops->add called in soc_camera_probe */
862 sd = dev_get_drvdata(control);
863 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_IOREQUEST,(void*)pcdev->pdata);
865 ret = v4l2_subdev_call(sd,core, init, 0);
869 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_CB_REGISTER,(void*)(&pcdev->icd_cb));
876 for (i=0; i<2; i++) {
877 if (pcdev->icd_frmival[i].icd == icd)
879 if (pcdev->icd_frmival[i].icd == NULL) {
880 pcdev->icd_frmival[i].icd = icd;
885 if (icd_catch == 0) {
886 fival_list = pcdev->icd_frmival[0].fival_list;
887 fival_nxt = fival_list;
888 while(fival_nxt != NULL) {
889 fival_nxt = fival_list->nxt;
891 fival_list = fival_nxt;
893 pcdev->icd_frmival[0].icd = icd;
894 pcdev->icd_frmival[0].fival_list = kzalloc(sizeof(struct rk29_camera_frmivalenum),GFP_KERNEL);
897 mutex_unlock(&camera_lock);
901 static void rk29_camera_remove_device(struct soc_camera_device *icd)
903 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
904 struct rk29_camera_dev *pcdev = ici->priv;
905 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
907 mutex_lock(&camera_lock);
908 BUG_ON(icd != pcdev->icd);
910 dev_info(&icd->dev, "RK29 Camera driver detached from camera%d(%s)\n",
911 icd->devnum,dev_name(icd->pdev));
913 /* ddl@rock-chips.com: Application will call VIDIOC_STREAMOFF before close device, but
914 stream may be turn on again before close device, if suspend and resume happened. */
915 if (read_vip_reg(RK29_VIP_CTRL) & ENABLE_CAPTURE) {
916 rk29_camera_s_stream(icd,0);
919 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_DEACTIVATE,NULL);
920 rk29_camera_deactivate(pcdev);
922 if (pcdev->camera_work) {
923 kfree(pcdev->camera_work);
924 pcdev->camera_work = NULL;
925 pcdev->camera_work_count = 0;
928 pcdev->active = NULL;
930 pcdev->icd_cb.sensor_cb = NULL;
931 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
932 /* ddl@rock-chips.com: capture list must be reset, because this list may be not empty,
933 * if app havn't dequeue all videobuf before close camera device;
935 INIT_LIST_HEAD(&pcdev->capture);
937 mutex_unlock(&camera_lock);
938 RK29CAMERA_DG("%s exit\n",__FUNCTION__);
942 static int rk29_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
944 unsigned long bus_flags, camera_flags, common_flags;
945 unsigned int vip_ctrl_val = 0;
946 const struct soc_mbus_pixelfmt *fmt;
949 RK29CAMERA_DG("%s..%d..\n",__FUNCTION__,__LINE__);
951 fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code);
955 bus_flags = RK29_CAM_BUS_PARAM;
956 /* If requested data width is supported by the platform, use it */
957 switch (fmt->bits_per_sample) {
959 if (!(bus_flags & SOCAM_DATAWIDTH_10))
963 if (!(bus_flags & SOCAM_DATAWIDTH_9))
967 if (!(bus_flags & SOCAM_DATAWIDTH_8))
974 if (icd->ops->query_bus_param)
975 camera_flags = icd->ops->query_bus_param(icd);
979 common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
982 goto RK29_CAMERA_SET_BUS_PARAM_END;
985 ret = icd->ops->set_bus_param(icd, common_flags);
987 goto RK29_CAMERA_SET_BUS_PARAM_END;
989 vip_ctrl_val = read_vip_reg(RK29_VIP_CTRL);
990 if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) {
991 vip_ctrl_val |= NEGATIVE_EDGE;
993 vip_ctrl_val &= ~NEGATIVE_EDGE;
995 if (common_flags & SOCAM_HSYNC_ACTIVE_LOW) {
996 vip_ctrl_val |= HSY_LOW_ACTIVE;
998 vip_ctrl_val &= ~HSY_LOW_ACTIVE;
1000 if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH) {
1001 vip_ctrl_val |= VSY_HIGH_ACTIVE;
1003 vip_ctrl_val &= ~VSY_HIGH_ACTIVE;
1006 /* ddl@rock-chips.com : Don't enable capture here, enable in stream_on */
1007 //vip_ctrl_val |= ENABLE_CAPTURE;
1009 write_vip_reg(RK29_VIP_CTRL, vip_ctrl_val);
1010 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),
1011 read_grf_reg(GRF_SOC_CON0_Reg)&VIP_AHBMASTER, read_grf_reg(GRF_OS_REG0)&VIP_ACLK_DIV_HCLK_2);
1013 RK29_CAMERA_SET_BUS_PARAM_END:
1015 RK29CAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
1019 static int rk29_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
1021 unsigned long bus_flags, camera_flags;
1024 bus_flags = RK29_CAM_BUS_PARAM;
1025 if (icd->ops->query_bus_param) {
1026 camera_flags = icd->ops->query_bus_param(icd);
1030 ret = soc_camera_bus_param_compatible(camera_flags, bus_flags) ;
1033 dev_warn(icd->dev.parent,
1034 "Flags incompatible: camera %lx, host %lx\n",
1035 camera_flags, bus_flags);
1039 static const struct soc_mbus_pixelfmt rk29_camera_formats[] = {
1041 .fourcc = V4L2_PIX_FMT_NV12,
1042 .name = "YUV420 NV12",
1043 .bits_per_sample = 8,
1044 .packing = SOC_MBUS_PACKING_1_5X8,
1045 .order = SOC_MBUS_ORDER_LE,
1047 .fourcc = V4L2_PIX_FMT_NV16,
1048 .name = "YUV422 NV16",
1049 .bits_per_sample = 8,
1050 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1051 .order = SOC_MBUS_ORDER_LE,
1053 .fourcc = V4L2_PIX_FMT_YUV420,
1054 .name = "NV12(v0.0.1)",
1055 .bits_per_sample = 8,
1056 .packing = SOC_MBUS_PACKING_1_5X8,
1057 .order = SOC_MBUS_ORDER_LE,
1059 .fourcc = V4L2_PIX_FMT_YUV422P,
1060 .name = "NV16(v0.0.1)",
1061 .bits_per_sample = 8,
1062 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1063 .order = SOC_MBUS_ORDER_LE,
1067 static void rk29_camera_setup_format(struct soc_camera_device *icd, __u32 host_pixfmt, enum v4l2_mbus_pixelcode icd_code, struct v4l2_rect *rect)
1069 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1070 struct rk29_camera_dev *pcdev = ici->priv;
1071 unsigned int vip_fs = 0,vip_crop = 0;
1072 unsigned int vip_ctrl_val = VIP_SENSOR|ONEFRAME|DISABLE_CAPTURE;
1074 switch (host_pixfmt)
1076 case V4L2_PIX_FMT_NV16:
1077 case V4L2_PIX_FMT_YUV422P: /* ddl@rock-chips.com: V4L2_PIX_FMT_YUV422P is V4L2_PIX_FMT_NV16 actually in 0.0.1 driver */
1078 vip_ctrl_val |= VIPREGYUV422;
1079 pcdev->frame_inval = RK29_CAM_FRAME_INVAL_DC;
1080 pcdev->pixfmt = host_pixfmt;
1082 case V4L2_PIX_FMT_NV12:
1083 case V4L2_PIX_FMT_YUV420: /* ddl@rock-chips.com: V4L2_PIX_FMT_YUV420 is V4L2_PIX_FMT_NV12 actually in 0.0.1 driver */
1084 vip_ctrl_val |= VIPREGYUV420;
1085 if (pcdev->frame_inval != RK29_CAM_FRAME_INVAL_INIT)
1086 pcdev->frame_inval = RK29_CAM_FRAME_INVAL_INIT;
1087 pcdev->pixfmt = host_pixfmt;
1089 default: /* ddl@rock-chips.com : vip output format is hold when pixfmt is invalidate */
1090 vip_ctrl_val |= (read_vip_reg(RK29_VIP_CTRL) & VIPREGYUV422);
1096 case V4L2_MBUS_FMT_UYVY8_2X8:
1097 vip_ctrl_val |= SENSOR_UYVY;
1099 case V4L2_MBUS_FMT_YUYV8_2X8:
1100 vip_ctrl_val |= SENSOR_YUYV;
1103 vip_ctrl_val |= (read_vip_reg(RK29_VIP_CTRL) & SENSOR_YUYV);
1107 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 */
1109 read_vip_reg(RK29_VIP_INT_STS); /* clear vip interrupte single */
1111 if (vip_ctrl_val & ONEFRAME) {
1112 vip_crop = ((rect->left<<16) + rect->top);
1113 vip_fs = (((rect->width + rect->left)<<16) + (rect->height+rect->top));
1114 } else if (vip_ctrl_val & PING_PONG) {
1118 write_vip_reg(RK29_VIP_CROP, vip_crop);
1119 write_vip_reg(RK29_VIP_FS, vip_fs);
1121 write_vip_reg(RK29_VIP_FB_SR, 0x00000003);
1123 pcdev->host_width = rect->width;
1124 pcdev->host_height = rect->height;
1126 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));
1130 static int rk29_camera_get_formats(struct soc_camera_device *icd, unsigned int idx,
1131 struct soc_camera_format_xlate *xlate)
1133 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1134 struct device *dev = icd->dev.parent;
1135 int formats = 0, ret;
1136 enum v4l2_mbus_pixelcode code;
1137 const struct soc_mbus_pixelfmt *fmt;
1139 ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
1141 /* No more formats */
1144 fmt = soc_mbus_get_fmtdesc(code);
1146 dev_err(dev, "Invalid format code #%u: %d\n", idx, code);
1150 ret = rk29_camera_try_bus_param(icd, fmt->bits_per_sample);
1155 case V4L2_MBUS_FMT_UYVY8_2X8:
1156 case V4L2_MBUS_FMT_YUYV8_2X8:
1159 xlate->host_fmt = &rk29_camera_formats[0];
1162 dev_dbg(dev, "Providing format %s using code %d\n",
1163 rk29_camera_formats[0].name,code);
1168 xlate->host_fmt = &rk29_camera_formats[1];
1171 dev_dbg(dev, "Providing format %s using code %d\n",
1172 rk29_camera_formats[1].name,code);
1177 xlate->host_fmt = &rk29_camera_formats[2];
1180 dev_dbg(dev, "Providing format %s using code %d\n",
1181 rk29_camera_formats[2].name,code);
1186 xlate->host_fmt = &rk29_camera_formats[3];
1189 dev_dbg(dev, "Providing format %s using code %d\n",
1190 rk29_camera_formats[3].name,code);;
1200 static void rk29_camera_put_formats(struct soc_camera_device *icd)
1205 static int rk29_camera_set_crop(struct soc_camera_device *icd,
1206 struct v4l2_crop *a)
1208 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1209 struct v4l2_mbus_framefmt mf;
1210 u32 fourcc = icd->current_fmt->host_fmt->fourcc;
1213 ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
1217 if ((mf.width < (a->c.left + a->c.width)) || (mf.height < (a->c.top + a->c.height))) {
1219 mf.width = a->c.left + a->c.width;
1220 mf.height = a->c.top + a->c.height;
1222 v4l_bound_align_image(&mf.width, RK29_CAM_W_MIN, RK29_CAM_W_MAX, 1,
1223 &mf.height, RK29_CAM_H_MIN, RK29_CAM_H_MAX, 0,
1224 fourcc == V4L2_PIX_FMT_NV16 ?4 : 0);
1226 ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
1231 rk29_camera_setup_format(icd, fourcc, mf.code, &a->c);
1233 icd->user_width = mf.width;
1234 icd->user_height = mf.height;
1239 static int rk29_camera_set_fmt(struct soc_camera_device *icd,
1240 struct v4l2_format *f)
1242 struct device *dev = icd->dev.parent;
1243 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1244 const struct soc_camera_format_xlate *xlate = NULL;
1245 struct soc_camera_host *ici =to_soc_camera_host(icd->dev.parent);
1246 struct rk29_camera_dev *pcdev = ici->priv;
1247 struct v4l2_pix_format *pix = &f->fmt.pix;
1248 struct v4l2_mbus_framefmt mf;
1249 struct v4l2_rect rect;
1250 int ret,usr_w,usr_h;
1254 usr_h = pix->height;
1255 RK29CAMERA_DG("%s enter width:%d height:%d\n",__FUNCTION__,usr_w,usr_h);
1257 xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
1259 dev_err(dev, "Format %x not found\n", pix->pixelformat);
1261 goto RK29_CAMERA_SET_FMT_END;
1264 /* ddl@rock-chips.com: sensor init code transmit in here after open */
1265 if (pcdev->icd_init == 0) {
1266 v4l2_subdev_call(sd,core, init, 0);
1267 pcdev->icd_init = 1;
1270 stream_on = read_vip_reg(RK29_VIP_CTRL);
1271 if (stream_on & ENABLE_CAPTURE)
1272 write_vip_reg(RK29_VIP_CTRL, (stream_on & (~ENABLE_CAPTURE)));
1274 mf.width = pix->width;
1275 mf.height = pix->height;
1276 mf.field = pix->field;
1277 mf.colorspace = pix->colorspace;
1278 mf.code = xlate->code;
1280 ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
1282 if (mf.code != xlate->code)
1285 #ifdef CONFIG_VIDEO_RK29_WORK_IPP
1286 if ((mf.width != usr_w) || (mf.height != usr_h)) {
1287 if (unlikely((mf.width <16) || (mf.width > 8190) || (mf.height < 16) || (mf.height > 8190))) {
1288 RK29CAMERA_TR("Senor and IPP both invalid source resolution(%dx%d)\n",mf.width,mf.height);
1290 goto RK29_CAMERA_SET_FMT_END;
1292 if (unlikely((usr_w <16)||(usr_h < 16))) {
1293 RK29CAMERA_TR("Senor and IPP both invalid destination resolution(%dx%d)\n",usr_w,usr_h);
1295 goto RK29_CAMERA_SET_FMT_END;
1306 rect.width = mf.width;
1307 rect.height = mf.height;
1309 down(&pcdev->zoominfo.sem);
1310 pcdev->zoominfo.a.c.width = rect.width*100/pcdev->zoominfo.zoom_rate;
1311 pcdev->zoominfo.a.c.width &= ~0x03;
1312 pcdev->zoominfo.a.c.height = rect.height*100/pcdev->zoominfo.zoom_rate;
1313 pcdev->zoominfo.a.c.height &= ~0x03;
1314 pcdev->zoominfo.a.c.left = ((rect.width - pcdev->zoominfo.a.c.width)>>1)&(~0x01);
1315 pcdev->zoominfo.a.c.top = ((rect.height - pcdev->zoominfo.a.c.height)>>1)&(~0x01);
1316 up(&pcdev->zoominfo.sem);
1318 /* ddl@rock-chips.com: IPP work limit check */
1319 if ((pcdev->zoominfo.a.c.width != usr_w) || (pcdev->zoominfo.a.c.height != usr_h)) {
1320 if (usr_w > 0x7f0) {
1321 if (((usr_w>>1)&0x3f) && (((usr_w>>1)&0x3f) <= 8)) {
1322 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));
1324 goto RK29_CAMERA_SET_FMT_END;
1327 if ((usr_w&0x3f) && ((usr_w&0x3f) <= 8)) {
1328 RK29CAMERA_TR("IPP Destination resolution(%dx%d, %d mod 64=%d is <= 8)",usr_w,usr_h, usr_w, (int)(usr_w&0x3f));
1330 goto RK29_CAMERA_SET_FMT_END;
1335 RK29CAMERA_DG("%s..%s icd width:%d host width:%d (zoom: %dx%d@(%d,%d)->%dx%d)\n",__FUNCTION__,xlate->host_fmt->name,
1336 rect.width, pix->width, pcdev->zoominfo.a.c.width,pcdev->zoominfo.a.c.height, pcdev->zoominfo.a.c.left,pcdev->zoominfo.a.c.top,
1337 pix->width, pix->height);
1338 rk29_camera_setup_format(icd, pix->pixelformat, mf.code, &rect);
1340 if (CAM_IPPWORK_IS_EN()) {
1341 BUG_ON(pcdev->vipmem_phybase == 0);
1344 pix->width = mf.width;
1345 pix->height = mf.height;
1346 pix->field = mf.field;
1347 pix->colorspace = mf.colorspace;
1348 icd->current_fmt = xlate;
1351 RK29_CAMERA_SET_FMT_END:
1352 if (stream_on & ENABLE_CAPTURE)
1353 write_vip_reg(RK29_VIP_CTRL, (read_vip_reg(RK29_VIP_CTRL) | ENABLE_CAPTURE));
1355 RK29CAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
1358 static bool rk29_camera_fmt_capturechk(struct v4l2_format *f)
1362 if ((f->fmt.pix.width == 1024) && (f->fmt.pix.height == 768)) {
1364 } else if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 1024)) {
1366 } else if ((f->fmt.pix.width == 1600) && (f->fmt.pix.height == 1200)) {
1368 } else if ((f->fmt.pix.width == 2048) && (f->fmt.pix.height == 1536)) {
1370 } else if ((f->fmt.pix.width == 2592) && (f->fmt.pix.height == 1944)) {
1375 RK29CAMERA_DG("%s %dx%d is capture format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
1378 static int rk29_camera_try_fmt(struct soc_camera_device *icd,
1379 struct v4l2_format *f)
1381 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1382 struct rk29_camera_dev *pcdev = ici->priv;
1383 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1384 const struct soc_camera_format_xlate *xlate;
1385 struct v4l2_pix_format *pix = &f->fmt.pix;
1386 __u32 pixfmt = pix->pixelformat;
1387 int ret,usr_w,usr_h,i;
1388 bool is_capture = rk29_camera_fmt_capturechk(f);
1389 bool vipmem_is_overflow = false;
1390 struct v4l2_mbus_framefmt mf;
1393 usr_h = pix->height;
1394 RK29CAMERA_DG("%s enter width:%d height:%d\n",__FUNCTION__,usr_w,usr_h);
1396 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
1398 dev_err(icd->dev.parent, "Format (%c%c%c%c) not found\n", pixfmt & 0xFF, (pixfmt >> 8) & 0xFF,
1399 (pixfmt >> 16) & 0xFF, (pixfmt >> 24) & 0xFF);
1401 RK29CAMERA_TR("%s(version:%c%c%c) support format:\n",rk29_cam_driver_description,(RK29_CAM_VERSION_CODE&0xff0000)>>16,
1402 (RK29_CAM_VERSION_CODE&0xff00)>>8,(RK29_CAM_VERSION_CODE&0xff));
1403 for (i = 0; i < icd->num_user_formats; i++)
1404 RK29CAMERA_TR("(%c%c%c%c)-%s\n",
1405 icd->user_formats[i].host_fmt->fourcc & 0xFF, (icd->user_formats[i].host_fmt->fourcc >> 8) & 0xFF,
1406 (icd->user_formats[i].host_fmt->fourcc >> 16) & 0xFF, (icd->user_formats[i].host_fmt->fourcc >> 24) & 0xFF,
1407 icd->user_formats[i].host_fmt->name);
1408 goto RK29_CAMERA_TRY_FMT_END;
1410 /* limit to rk29 hardware capabilities */
1411 v4l_bound_align_image(&pix->width, RK29_CAM_W_MIN, RK29_CAM_W_MAX, 1,
1412 &pix->height, RK29_CAM_H_MIN, RK29_CAM_H_MAX, 0,
1413 pixfmt == V4L2_PIX_FMT_NV16 ? 4 : 0);
1415 pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
1417 if (pix->bytesperline < 0)
1418 return pix->bytesperline;
1420 /* limit to sensor capabilities */
1421 mf.width = pix->width;
1422 mf.height = pix->height;
1423 mf.field = pix->field;
1424 mf.colorspace = pix->colorspace;
1425 mf.code = xlate->code;
1427 ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
1429 goto RK29_CAMERA_TRY_FMT_END;
1430 RK29CAMERA_DG("%s mf.width:%d mf.height:%d\n",__FUNCTION__,mf.width,mf.height);
1431 #ifdef CONFIG_VIDEO_RK29_WORK_IPP
1432 if ((mf.width > usr_w) && (mf.height > usr_h)) {
1434 vipmem_is_overflow = (PAGE_ALIGN(pix->bytesperline*pix->height) > pcdev->vipmem_size);
1436 /* Assume preview buffer minimum is 4 */
1437 vipmem_is_overflow = (PAGE_ALIGN(pix->bytesperline*pix->height)*4 > pcdev->vipmem_size);
1439 if (vipmem_is_overflow == false) {
1441 pix->height = usr_h;
1443 RK29CAMERA_TR("vipmem for IPP is overflow, This resolution(%dx%d -> %dx%d) is invalidate!\n",mf.width,mf.height,usr_w,usr_h);
1444 pix->width = mf.width;
1445 pix->height = mf.height;
1447 } else if ((mf.width < usr_w) && (mf.height < usr_h)) {
1448 if (((usr_w>>1) < mf.width) && ((usr_h>>1) < mf.height)) {
1450 vipmem_is_overflow = (PAGE_ALIGN(pix->bytesperline*pix->height) > pcdev->vipmem_size);
1452 vipmem_is_overflow = (PAGE_ALIGN(pix->bytesperline*pix->height)*4 > pcdev->vipmem_size);
1454 if (vipmem_is_overflow == false) {
1456 pix->height = usr_h;
1458 RK29CAMERA_TR("vipmem for IPP is overflow, This resolution(%dx%d -> %dx%d) is invalidate!\n",mf.width,mf.height,usr_w,usr_h);
1459 pix->width = mf.width;
1460 pix->height = mf.height;
1463 RK29CAMERA_TR("The aspect ratio(%dx%d/%dx%d) is bigger than 2 !\n",mf.width,mf.height,usr_w,usr_h);
1464 pix->width = mf.width;
1465 pix->height = mf.height;
1469 pix->width = mf.width;
1470 pix->height = mf.height;
1472 pix->colorspace = mf.colorspace;
1475 case V4L2_FIELD_ANY:
1476 case V4L2_FIELD_NONE:
1477 pix->field = V4L2_FIELD_NONE;
1480 /* TODO: support interlaced at least in pass-through mode */
1481 dev_err(icd->dev.parent, "Field type %d unsupported.\n",
1483 goto RK29_CAMERA_TRY_FMT_END;
1486 RK29_CAMERA_TRY_FMT_END:
1488 RK29CAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
1492 static int rk29_camera_reqbufs(struct soc_camera_device *icd,
1493 struct v4l2_requestbuffers *p)
1497 /* This is for locking debugging only. I removed spinlocks and now I
1498 * check whether .prepare is ever called on a linked buffer, or whether
1499 * a dma IRQ can occur for an in-work or unlinked buffer. Until now
1500 * it hadn't triggered */
1501 for (i = 0; i < p->count; i++) {
1502 struct rk29_buffer *buf = container_of(icd->vb_vidq.bufs[i],
1503 struct rk29_buffer, vb);
1505 INIT_LIST_HEAD(&buf->vb.queue);
1511 static unsigned int rk29_camera_poll(struct file *file, poll_table *pt)
1513 struct soc_camera_device *icd = file->private_data;
1514 struct rk29_buffer *buf;
1516 buf = list_entry(icd->vb_vidq.stream.next, struct rk29_buffer,
1519 poll_wait(file, &buf->vb.done, pt);
1521 if (buf->vb.state == VIDEOBUF_DONE ||
1522 buf->vb.state == VIDEOBUF_ERROR)
1523 return POLLIN|POLLRDNORM;
1528 static int rk29_camera_querycap(struct soc_camera_host *ici,
1529 struct v4l2_capability *cap)
1531 struct rk29_camera_dev *pcdev = ici->priv;
1532 char orientation[5];
1534 strlcpy(cap->card, dev_name(pcdev->icd->pdev), sizeof(cap->card));
1535 if (strcmp(dev_name(pcdev->icd->pdev), pcdev->pdata->gpio_res[0].dev_name) == 0) {
1536 sprintf(orientation,"-%d",pcdev->pdata->gpio_res[0].orientation);
1538 sprintf(orientation,"-%d",pcdev->pdata->gpio_res[1].orientation);
1540 strcat(cap->card,orientation);
1541 cap->version = RK29_CAM_VERSION_CODE;
1542 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1547 static int rk29_camera_suspend(struct soc_camera_device *icd, pm_message_t state)
1549 struct soc_camera_host *ici =
1550 to_soc_camera_host(icd->dev.parent);
1551 struct rk29_camera_dev *pcdev = ici->priv;
1552 struct v4l2_subdev *sd;
1555 mutex_lock(&camera_lock);
1556 if ((pcdev->icd == icd) && (icd->ops->suspend)) {
1557 rk29_camera_s_stream(icd, 0);
1558 sd = soc_camera_to_subdev(icd);
1559 v4l2_subdev_call(sd, video, s_stream, 0);
1560 ret = icd->ops->suspend(icd, state);
1562 pcdev->reginfo_suspend.VipCtrl = read_vip_reg(RK29_VIP_CTRL);
1563 pcdev->reginfo_suspend.VipCrop = read_vip_reg(RK29_VIP_CROP);
1564 pcdev->reginfo_suspend.VipFs = read_vip_reg(RK29_VIP_FS);
1565 pcdev->reginfo_suspend.VipIntMsk = read_vip_reg(RK29_VIP_INT_MASK);
1566 pcdev->reginfo_suspend.VipCrm = read_vip_reg(RK29_VIP_CRM);
1568 tmp = pcdev->reginfo_suspend.VipFs>>16; /* ddl@rock-chips.com */
1569 tmp += pcdev->reginfo_suspend.VipCrop>>16;
1570 pcdev->reginfo_suspend.VipFs = (pcdev->reginfo_suspend.VipFs & 0xffff) | (tmp<<16);
1572 pcdev->reginfo_suspend.Inval = Reg_Validate;
1573 rk29_camera_deactivate(pcdev);
1575 RK29CAMERA_DG("%s Enter Success...\n", __FUNCTION__);
1577 RK29CAMERA_DG("%s icd has been deattach, don't need enter suspend\n", __FUNCTION__);
1579 mutex_unlock(&camera_lock);
1583 static int rk29_camera_resume(struct soc_camera_device *icd)
1585 struct soc_camera_host *ici =
1586 to_soc_camera_host(icd->dev.parent);
1587 struct rk29_camera_dev *pcdev = ici->priv;
1588 struct v4l2_subdev *sd;
1591 mutex_lock(&camera_lock);
1592 if ((pcdev->icd == icd) && (icd->ops->resume)) {
1593 if (pcdev->reginfo_suspend.Inval == Reg_Validate) {
1594 rk29_camera_activate(pcdev, icd);
1595 write_vip_reg(RK29_VIP_INT_MASK, pcdev->reginfo_suspend.VipIntMsk);
1596 write_vip_reg(RK29_VIP_CRM, pcdev->reginfo_suspend.VipCrm);
1597 write_vip_reg(RK29_VIP_CTRL, pcdev->reginfo_suspend.VipCtrl&~ENABLE_CAPTURE);
1598 write_vip_reg(RK29_VIP_CROP, pcdev->reginfo_suspend.VipCrop);
1599 write_vip_reg(RK29_VIP_FS, pcdev->reginfo_suspend.VipFs);
1601 rk29_videobuf_capture(pcdev->active);
1602 rk29_camera_s_stream(icd, 1);
1603 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
1605 RK29CAMERA_TR("Resume fail, vip register recored is invalidate!!\n");
1606 goto rk29_camera_resume_end;
1609 ret = icd->ops->resume(icd);
1610 sd = soc_camera_to_subdev(icd);
1611 v4l2_subdev_call(sd, video, s_stream, 1);
1613 RK29CAMERA_DG("%s Enter success\n",__FUNCTION__);
1615 RK29CAMERA_DG("%s icd has been deattach, don't need enter resume\n", __FUNCTION__);
1618 rk29_camera_resume_end:
1619 mutex_unlock(&camera_lock);
1623 static void rk29_camera_reinit_work(struct work_struct *work)
1625 struct device *control;
1626 struct v4l2_subdev *sd;
1627 struct v4l2_mbus_framefmt mf;
1628 const struct soc_camera_format_xlate *xlate;
1631 write_vip_reg(RK29_VIP_CTRL, (read_vip_reg(RK29_VIP_CTRL)&(~ENABLE_CAPTURE)));
1633 control = to_soc_camera_control(rk29_camdev_info_ptr->icd);
1634 sd = dev_get_drvdata(control);
1635 ret = v4l2_subdev_call(sd,core, init, 1);
1637 mf.width = rk29_camdev_info_ptr->icd->user_width;
1638 mf.height = rk29_camdev_info_ptr->icd->user_height;
1639 xlate = soc_camera_xlate_by_fourcc(rk29_camdev_info_ptr->icd, rk29_camdev_info_ptr->icd->current_fmt->host_fmt->fourcc);
1640 mf.code = xlate->code;
1642 ret |= v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
1644 write_vip_reg(RK29_VIP_CTRL, (read_vip_reg(RK29_VIP_CTRL)|ENABLE_CAPTURE));
1646 RK29CAMERA_TR("Camera host haven't recevie data from sensor,Reinit sensor now! ret:0x%x\n",ret);
1648 static enum hrtimer_restart rk29_camera_fps_func(struct hrtimer *timer)
1650 struct rk29_camera_frmivalenum *fival_nxt=NULL,*fival_pre=NULL, *fival_rec=NULL;
1653 RK29CAMERA_DG("rk29_camera_fps_func fps:0x%x\n",rk29_camdev_info_ptr->fps);
1654 if (rk29_camdev_info_ptr->fps < 2) {
1655 RK29CAMERA_TR("Camera host haven't recevie data from sensor,Reinit sensor delay!\n");
1656 INIT_WORK(&rk29_camdev_info_ptr->camera_reinit_work, rk29_camera_reinit_work);
1657 queue_work(rk29_camdev_info_ptr->camera_wq,&(rk29_camdev_info_ptr->camera_reinit_work));
1659 for (i=0; i<2; i++) {
1660 if (rk29_camdev_info_ptr->icd == rk29_camdev_info_ptr->icd_frmival[i].icd) {
1661 fival_nxt = rk29_camdev_info_ptr->icd_frmival[i].fival_list;
1666 fival_pre = fival_nxt;
1667 while (fival_nxt != NULL) {
1669 RK29CAMERA_DG("%s %c%c%c%c %dx%d framerate : %d/%d\n", dev_name(&rk29_camdev_info_ptr->icd->dev),
1670 fival_nxt->fival.pixel_format & 0xFF, (fival_nxt->fival.pixel_format >> 8) & 0xFF,
1671 (fival_nxt->fival.pixel_format >> 16) & 0xFF, (fival_nxt->fival.pixel_format >> 24),
1672 fival_nxt->fival.width, fival_nxt->fival.height, fival_nxt->fival.discrete.denominator,
1673 fival_nxt->fival.discrete.numerator);
1675 if (((fival_nxt->fival.pixel_format == rk29_camdev_info_ptr->pixfmt)
1676 && (fival_nxt->fival.height == rk29_camdev_info_ptr->icd->user_height)
1677 && (fival_nxt->fival.width == rk29_camdev_info_ptr->icd->user_width))
1678 || (fival_nxt->fival.discrete.denominator == 0)) {
1680 if (fival_nxt->fival.discrete.denominator == 0) {
1681 fival_nxt->fival.index = 0;
1682 fival_nxt->fival.width = rk29_camdev_info_ptr->icd->user_width;
1683 fival_nxt->fival.height= rk29_camdev_info_ptr->icd->user_height;
1684 fival_nxt->fival.pixel_format = rk29_camdev_info_ptr->pixfmt;
1685 fival_nxt->fival.discrete.denominator = rk29_camdev_info_ptr->fps+2;
1686 fival_nxt->fival.discrete.numerator = 1;
1687 fival_nxt->fival.type = V4L2_FRMIVAL_TYPE_DISCRETE;
1689 if (abs(rk29_camdev_info_ptr->fps + 2 - fival_nxt->fival.discrete.numerator) > 2) {
1690 fival_nxt->fival.discrete.denominator = rk29_camdev_info_ptr->fps+2;
1691 fival_nxt->fival.discrete.numerator = 1;
1692 fival_nxt->fival.type = V4L2_FRMIVAL_TYPE_DISCRETE;
1696 fival_rec = fival_nxt;
1698 fival_pre = fival_nxt;
1699 fival_nxt = fival_nxt->nxt;
1702 if ((rec_flag == 0) && fival_pre) {
1703 fival_pre->nxt = kzalloc(sizeof(struct rk29_camera_frmivalenum), GFP_ATOMIC);
1704 if (fival_pre->nxt != NULL) {
1705 fival_pre->nxt->fival.index = fival_pre->fival.index++;
1706 fival_pre->nxt->fival.width = rk29_camdev_info_ptr->icd->user_width;
1707 fival_pre->nxt->fival.height= rk29_camdev_info_ptr->icd->user_height;
1708 fival_pre->nxt->fival.pixel_format = rk29_camdev_info_ptr->pixfmt;
1710 fival_pre->nxt->fival.discrete.denominator = rk29_camdev_info_ptr->fps+2;
1711 fival_pre->nxt->fival.discrete.numerator = 1;
1712 fival_pre->nxt->fival.type = V4L2_FRMIVAL_TYPE_DISCRETE;
1714 fival_rec = fival_pre->nxt;
1719 return HRTIMER_NORESTART;
1721 static int rk29_camera_s_stream(struct soc_camera_device *icd, int enable)
1723 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1724 struct rk29_camera_dev *pcdev = ici->priv;
1728 WARN_ON(pcdev->icd != icd);
1730 vip_ctrl_val = read_vip_reg(RK29_VIP_CTRL);
1733 hrtimer_cancel(&pcdev->fps_timer);
1734 hrtimer_start(&pcdev->fps_timer,ktime_set(1, 0),HRTIMER_MODE_REL);
1735 vip_ctrl_val |= ENABLE_CAPTURE;
1737 vip_ctrl_val &= ~ENABLE_CAPTURE;
1738 ret = hrtimer_cancel(&pcdev->fps_timer);
1739 ret |= flush_work(&rk29_camdev_info_ptr->camera_reinit_work);
1740 RK29CAMERA_DG("STREAM_OFF cancel timer and flush work:0x%x \n", ret);
1742 write_vip_reg(RK29_VIP_CTRL, vip_ctrl_val);
1744 RK29CAMERA_DG("%s.. enable : 0x%x \n", __FUNCTION__, enable);
1747 int rk29_camera_enum_frameintervals(struct soc_camera_device *icd, struct v4l2_frmivalenum *fival)
1749 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1750 struct rk29_camera_dev *pcdev = ici->priv;
1751 struct rk29_camera_frmivalenum *fival_list = NULL;
1754 for (i=0; i<2; i++) {
1755 if (pcdev->icd_frmival[i].icd == icd) {
1756 fival_list = pcdev->icd_frmival[i].fival_list;
1760 if (fival_list != NULL) {
1762 while (fival_list != NULL) {
1763 if ((fival->pixel_format == fival_list->fival.pixel_format)
1764 && (fival->height == fival_list->fival.height)
1765 && (fival->width == fival_list->fival.width)) {
1766 if (i == fival->index)
1770 fival_list = fival_list->nxt;
1773 if ((i==fival->index) && (fival_list != NULL)) {
1774 memcpy(fival, &fival_list->fival, sizeof(struct v4l2_frmivalenum));
1779 RK29CAMERA_TR("%s: fival_list is NULL\n",__FUNCTION__);
1786 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
1787 static int rk29_camera_set_digit_zoom(struct soc_camera_device *icd,
1788 const struct v4l2_queryctrl *qctrl, int zoom_rate)
1791 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1792 struct rk29_camera_dev *pcdev = ici->priv;
1794 /* ddl@rock-chips.com : The largest resolution is 2047x1088, so larger resolution must be operated some times
1795 (Assume operate times is 4),but resolution which ipp can operate ,it is width and height must be even. */
1796 a.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1797 a.c.width = pcdev->host_width*100/zoom_rate;
1799 a.c.height = pcdev->host_height*100/zoom_rate;
1800 a.c.height &= ~0x03;
1802 a.c.left = ((pcdev->host_width - a.c.width)>>1)&(~0x01);
1803 a.c.top = ((pcdev->host_height - a.c.height)>>1)&(~0x01);
1805 down(&pcdev->zoominfo.sem);
1806 pcdev->zoominfo.a.c.height = a.c.height;
1807 pcdev->zoominfo.a.c.width = a.c.width;
1808 pcdev->zoominfo.a.c.top = a.c.top;
1809 pcdev->zoominfo.a.c.left = a.c.left;
1810 up(&pcdev->zoominfo.sem);
1812 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 );
1817 static inline struct v4l2_queryctrl const *rk29_camera_soc_camera_find_qctrl(
1818 struct soc_camera_host_ops *ops, int id)
1822 for (i = 0; i < ops->num_controls; i++)
1823 if (ops->controls[i].id == id)
1824 return &ops->controls[i];
1830 static int rk29_camera_set_ctrl(struct soc_camera_device *icd,
1831 struct v4l2_control *sctrl)
1834 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1835 const struct v4l2_queryctrl *qctrl;
1836 struct rk29_camera_dev *pcdev = ici->priv;
1839 qctrl = rk29_camera_soc_camera_find_qctrl(ici->ops, sctrl->id);
1842 goto rk29_camera_set_ctrl_end;
1847 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
1848 case V4L2_CID_ZOOM_ABSOLUTE:
1850 if ((sctrl->value < qctrl->minimum) || (sctrl->value > qctrl->maximum)){
1852 goto rk29_camera_set_ctrl_end;
1854 ret = rk29_camera_set_digit_zoom(icd, qctrl, sctrl->value);
1856 pcdev->zoominfo.zoom_rate = sctrl->value;
1858 goto rk29_camera_set_ctrl_end;
1867 rk29_camera_set_ctrl_end:
1871 static struct soc_camera_host_ops rk29_soc_camera_host_ops =
1873 .owner = THIS_MODULE,
1874 .add = rk29_camera_add_device,
1875 .remove = rk29_camera_remove_device,
1876 .suspend = rk29_camera_suspend,
1877 .resume = rk29_camera_resume,
1878 .enum_frameinervals = rk29_camera_enum_frameintervals,
1879 .set_crop = rk29_camera_set_crop,
1880 .get_formats = rk29_camera_get_formats,
1881 .put_formats = rk29_camera_put_formats,
1882 .set_fmt = rk29_camera_set_fmt,
1883 .try_fmt = rk29_camera_try_fmt,
1884 .init_videobuf = rk29_camera_init_videobuf,
1885 .reqbufs = rk29_camera_reqbufs,
1886 .poll = rk29_camera_poll,
1887 .querycap = rk29_camera_querycap,
1888 .set_bus_param = rk29_camera_set_bus_param,
1889 .s_stream = rk29_camera_s_stream, /* ddl@rock-chips.com : Add stream control for host */
1890 .set_ctrl = rk29_camera_set_ctrl,
1891 .controls = rk29_camera_controls,
1892 .num_controls = ARRAY_SIZE(rk29_camera_controls)
1895 static int rk29_camera_probe(struct platform_device *pdev)
1897 struct rk29_camera_dev *pcdev;
1898 struct resource *res;
1899 struct rk29_camera_frmivalenum *fival_list,*fival_nxt;
1903 RK29CAMERA_DG("%s..%s..%d \n",__FUNCTION__,__FILE__,__LINE__);
1904 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1905 irq = platform_get_irq(pdev, 0);
1906 if (!res || irq < 0) {
1911 pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL);
1913 dev_err(&pdev->dev, "Could not allocate pcdev\n");
1917 rk29_camdev_info_ptr = pcdev;
1919 /*config output clk*/
1920 pcdev->aclk_ddr_lcdc = clk_get(&pdev->dev, "aclk_ddr_lcdc");
1921 pcdev->aclk_disp_matrix = clk_get(&pdev->dev, "aclk_disp_matrix");
1923 pcdev->hclk_cpu_display = clk_get(&pdev->dev, "hclk_cpu_display");
1924 pcdev->vip_slave = clk_get(&pdev->dev, "vip_slave");
1925 pcdev->vip_out = clk_get(&pdev->dev,"vip_out");
1926 pcdev->vip_input = clk_get(&pdev->dev,"vip_input");
1927 pcdev->vip_bus = clk_get(&pdev->dev, "vip_bus");
1929 pcdev->hclk_disp_matrix = clk_get(&pdev->dev,"hclk_disp_matrix");
1930 pcdev->vip_matrix = clk_get(&pdev->dev,"vip_matrix");
1932 pcdev->pd_display = clk_get(&pdev->dev,"pd_display");
1934 pcdev->zoominfo.zoom_rate = 100;
1936 if (!pcdev->aclk_ddr_lcdc || !pcdev->aclk_disp_matrix || !pcdev->hclk_cpu_display ||
1937 !pcdev->vip_slave || !pcdev->vip_out || !pcdev->vip_input || !pcdev->vip_bus || !pcdev->pd_display ||
1938 IS_ERR(pcdev->aclk_ddr_lcdc) || IS_ERR(pcdev->aclk_disp_matrix) || IS_ERR(pcdev->hclk_cpu_display) || IS_ERR(pcdev->pd_display) ||
1939 IS_ERR(pcdev->vip_slave) || IS_ERR(pcdev->vip_out) || IS_ERR(pcdev->vip_input) || IS_ERR(pcdev->vip_bus)) {
1941 RK29CAMERA_TR(KERN_ERR "failed to get vip_clk(axi) source\n");
1946 if (!pcdev->hclk_disp_matrix || !pcdev->vip_matrix ||
1947 IS_ERR(pcdev->hclk_disp_matrix) || IS_ERR(pcdev->vip_matrix)) {
1949 RK29CAMERA_TR(KERN_ERR "failed to get vip_clk(ahb) source\n");
1954 dev_set_drvdata(&pdev->dev, pcdev);
1957 pcdev->pdata = pdev->dev.platform_data; /* ddl@rock-chips.com : Request IO in init function */
1958 if (pcdev->pdata && pcdev->pdata->io_init) {
1959 pcdev->pdata->io_init();
1961 #ifdef CONFIG_VIDEO_RK29_WORK_IPP
1962 if (pcdev->pdata && (strcmp(pcdev->pdata->meminfo.name,"camera_ipp_mem")==0)) {
1963 pcdev->vipmem_phybase = pcdev->pdata->meminfo.start;
1964 pcdev->vipmem_size = pcdev->pdata->meminfo.size;
1965 RK29CAMERA_DG("\n%s Memory(start:0x%x size:0x%x) for IPP obtain \n",__FUNCTION__, pcdev->pdata->meminfo.start,pcdev->pdata->meminfo.size);
1967 RK29CAMERA_TR("\n%s Memory for IPP have not obtain! IPP Function is fail\n",__FUNCTION__);
1968 pcdev->vipmem_phybase = 0;
1969 pcdev->vipmem_size = 0;
1972 INIT_LIST_HEAD(&pcdev->capture);
1973 spin_lock_init(&pcdev->lock);
1974 sema_init(&pcdev->zoominfo.sem,1);
1977 * Request the regions.
1979 if (!request_mem_region(res->start, res->end - res->start + 1,
1980 RK29_CAM_DRV_NAME)) {
1985 pcdev->base = ioremap(res->start, res->end - res->start + 1);
1986 if (pcdev->base == NULL) {
1987 dev_err(pcdev->dev, "ioremap() of registers failed\n");
1993 pcdev->dev = &pdev->dev;
1995 /* config buffer address */
1997 err = request_irq(pcdev->irq, rk29_camera_irq, 0, RK29_CAM_DRV_NAME,
2000 dev_err(pcdev->dev, "Camera interrupt register failed \n");
2004 pcdev->camera_wq = create_workqueue("rk_camera_workqueue");
2005 if (pcdev->camera_wq == NULL)
2007 INIT_WORK(&pcdev->camera_reinit_work, rk29_camera_reinit_work);
2009 for (i=0; i<2; i++) {
2010 pcdev->icd_frmival[i].icd = NULL;
2011 pcdev->icd_frmival[i].fival_list = kzalloc(sizeof(struct rk29_camera_frmivalenum),GFP_KERNEL);
2015 pcdev->soc_host.drv_name = RK29_CAM_DRV_NAME;
2016 pcdev->soc_host.ops = &rk29_soc_camera_host_ops;
2017 pcdev->soc_host.priv = pcdev;
2018 pcdev->soc_host.v4l2_dev.dev = &pdev->dev;
2019 pcdev->soc_host.nr = pdev->id;
2021 err = soc_camera_host_register(&pcdev->soc_host);
2025 hrtimer_init(&pcdev->fps_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
2026 pcdev->fps_timer.function = rk29_camera_fps_func;
2027 pcdev->icd_cb.sensor_cb = NULL;
2029 RK29CAMERA_DG("%s..%s..%d \n",__FUNCTION__,__FILE__,__LINE__);
2034 for (i=0; i<2; i++) {
2035 fival_list = pcdev->icd_frmival[i].fival_list;
2036 fival_nxt = fival_list;
2037 while(fival_nxt != NULL) {
2038 fival_nxt = fival_list->nxt;
2040 fival_list = fival_nxt;
2044 free_irq(pcdev->irq, pcdev);
2045 if (pcdev->camera_wq) {
2046 destroy_workqueue(pcdev->camera_wq);
2047 pcdev->camera_wq = NULL;
2050 iounmap(pcdev->base);
2052 release_mem_region(res->start, res->end - res->start + 1);
2054 if (pcdev->aclk_ddr_lcdc) {
2055 clk_put(pcdev->aclk_ddr_lcdc);
2056 pcdev->aclk_ddr_lcdc = NULL;
2058 if (pcdev->aclk_disp_matrix) {
2059 clk_put(pcdev->aclk_disp_matrix);
2060 pcdev->aclk_disp_matrix = NULL;
2062 if (pcdev->hclk_cpu_display) {
2063 clk_put(pcdev->hclk_cpu_display);
2064 pcdev->hclk_cpu_display = NULL;
2066 if (pcdev->vip_slave) {
2067 clk_put(pcdev->vip_slave);
2068 pcdev->vip_slave = NULL;
2070 if (pcdev->vip_out) {
2071 clk_put(pcdev->vip_out);
2072 pcdev->vip_out = NULL;
2074 if (pcdev->vip_input) {
2075 clk_put(pcdev->vip_input);
2076 pcdev->vip_input = NULL;
2078 if (pcdev->vip_bus) {
2079 clk_put(pcdev->vip_bus);
2080 pcdev->vip_bus = NULL;
2082 if (pcdev->hclk_disp_matrix) {
2083 clk_put(pcdev->hclk_disp_matrix);
2084 pcdev->hclk_disp_matrix = NULL;
2086 if (pcdev->vip_matrix) {
2087 clk_put(pcdev->vip_matrix);
2088 pcdev->vip_matrix = NULL;
2092 rk29_camdev_info_ptr = NULL;
2097 static int __devexit rk29_camera_remove(struct platform_device *pdev)
2099 struct rk29_camera_dev *pcdev = platform_get_drvdata(pdev);
2100 struct resource *res;
2101 struct rk29_camera_frmivalenum *fival_list,*fival_nxt;
2104 free_irq(pcdev->irq, pcdev);
2106 if (pcdev->camera_wq) {
2107 destroy_workqueue(pcdev->camera_wq);
2108 pcdev->camera_wq = NULL;
2111 for (i=0; i<2; i++) {
2112 fival_list = pcdev->icd_frmival[i].fival_list;
2113 fival_nxt = fival_list;
2114 while(fival_nxt != NULL) {
2115 fival_nxt = fival_list->nxt;
2117 fival_list = fival_nxt;
2121 soc_camera_host_unregister(&pcdev->soc_host);
2124 release_mem_region(res->start, res->end - res->start + 1);
2126 if (pcdev->pdata && pcdev->pdata->io_deinit) { /* ddl@rock-chips.com : Free IO in deinit function */
2127 pcdev->pdata->io_deinit(0);
2128 pcdev->pdata->io_deinit(1);
2132 rk29_camdev_info_ptr = NULL;
2133 dev_info(&pdev->dev, "RK28 Camera driver unloaded\n");
2138 static struct platform_driver rk29_camera_driver =
2141 .name = RK29_CAM_DRV_NAME,
2143 .probe = rk29_camera_probe,
2144 .remove = __devexit_p(rk29_camera_remove),
2148 static int __devinit rk29_camera_init(void)
2150 RK29CAMERA_DG("%s..%s..%d \n",__FUNCTION__,__FILE__,__LINE__);
2151 return platform_driver_register(&rk29_camera_driver);
2154 static void __exit rk29_camera_exit(void)
2156 platform_driver_unregister(&rk29_camera_driver);
2159 device_initcall_sync(rk29_camera_init);
2160 module_exit(rk29_camera_exit);
2162 MODULE_DESCRIPTION("RK29 Soc Camera Host driver");
2163 MODULE_AUTHOR("ddl <ddl@rock-chips>");
2164 MODULE_LICENSE("GPL");