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.
12 #ifdef CONFIG_ARCH_RK29
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|S_IWGRP);
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;
151 *v0.x.7 : this driver product resolution by IPP crop and scale, which user request but sensor can't support;
152 * note: this version is only provide yifang client, which is not official version;
153 *v0.x.8 : this driver and rk29_camera.c support upto 3 back-sensors and upto 3 front-sensors;
154 *v0.x.9 : camera io code is compatible for rk29xx and rk30xx
156 #define RK29_CAM_VERSION_CODE KERNEL_VERSION(0, 1, 9)
158 /* limit to rk29 hardware capabilities */
159 #define RK29_CAM_BUS_PARAM (SOCAM_MASTER |\
160 SOCAM_HSYNC_ACTIVE_HIGH |\
161 SOCAM_HSYNC_ACTIVE_LOW |\
162 SOCAM_VSYNC_ACTIVE_HIGH |\
163 SOCAM_VSYNC_ACTIVE_LOW |\
164 SOCAM_PCLK_SAMPLE_RISING |\
165 SOCAM_PCLK_SAMPLE_FALLING|\
166 SOCAM_DATA_ACTIVE_HIGH |\
167 SOCAM_DATA_ACTIVE_LOW|\
168 SOCAM_DATAWIDTH_8|SOCAM_DATAWIDTH_10|\
169 SOCAM_MCLK_24MHZ |SOCAM_MCLK_48MHZ)
171 #define RK29_CAM_W_MIN 48
172 #define RK29_CAM_H_MIN 32
173 #define RK29_CAM_W_MAX 3856 /* ddl@rock-chips.com : 10M Pixel */
174 #define RK29_CAM_H_MAX 2764
175 #define RK29_CAM_FRAME_INVAL_INIT 3
176 #define RK29_CAM_FRAME_INVAL_DC 3 /* ddl@rock-chips.com : */
177 #define RK29_CAM_FRAME_MEASURE 5
179 #define RK29_CAM_AXI 0
180 #define RK29_CAM_AHB 1
181 #define CONFIG_RK29_CAM_WORK_BUS RK29_CAM_AXI
183 extern void videobuf_dma_contig_free(struct videobuf_queue *q, struct videobuf_buffer *buf);
184 extern dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf);
186 /* buffer for one video frame */
189 /* common v4l buffer stuff -- must be first */
190 struct videobuf_buffer vb;
191 enum v4l2_mbus_pixelcode code;
194 enum rk29_camera_reg_state
200 struct rk29_camera_reg
202 unsigned int VipCtrl;
203 unsigned int VipCrop;
205 unsigned int VipIntMsk;
207 enum rk29_camera_reg_state Inval;
209 struct rk29_camera_work
211 struct videobuf_buffer *vb;
212 struct rk29_camera_dev *pcdev;
213 struct work_struct work;
215 struct rk29_camera_frmivalenum
217 struct v4l2_frmivalenum fival;
218 struct rk29_camera_frmivalenum *nxt;
220 struct rk29_camera_frmivalinfo
222 struct soc_camera_device *icd;
223 struct rk29_camera_frmivalenum *fival_list;
225 struct rk29_camera_zoominfo
227 struct semaphore sem;
231 struct rk29_camera_dev
233 struct soc_camera_host soc_host;
235 /* RK2827x is only supposed to handle one camera on its Quick Capture
236 * interface. If anyone ever builds hardware to enable more than
237 * one camera, they will have to modify this driver too */
238 struct soc_camera_device *icd;
240 struct clk *aclk_ddr_lcdc;
241 struct clk *aclk_disp_matrix;
243 struct clk *hclk_cpu_display;
244 struct clk *vip_slave;
247 struct clk *vip_input;
250 struct clk *hclk_disp_matrix;
251 struct clk *vip_matrix;
253 struct clk *pd_display;
256 void __iomem *grf_base;
257 int frame_inval; /* ddl@rock-chips.com : The first frames is invalidate */
260 unsigned long frame_interval;
262 unsigned int vipmem_phybase;
263 unsigned int vipmem_size;
264 unsigned int vipmem_bsize;
270 struct rk29camera_platform_data *pdata;
271 struct resource *res;
273 struct list_head capture;
274 struct rk29_camera_zoominfo zoominfo;
278 struct videobuf_buffer *active;
279 struct rk29_camera_reg reginfo_suspend;
280 struct workqueue_struct *camera_wq;
281 struct rk29_camera_work *camera_work;
282 unsigned int camera_work_count;
283 struct hrtimer fps_timer;
284 struct work_struct camera_reinit_work;
286 rk29_camera_sensor_cb_s icd_cb;
287 struct rk29_camera_frmivalinfo icd_frmival[2];
290 static const struct v4l2_queryctrl rk29_camera_controls[] =
292 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
294 .id = V4L2_CID_ZOOM_ABSOLUTE,
295 .type = V4L2_CTRL_TYPE_INTEGER,
296 .name = "DigitalZoom Control",
300 .default_value = 100,
305 static DEFINE_MUTEX(camera_lock);
306 static const char *rk29_cam_driver_description = "RK29_Camera";
307 static struct rk29_camera_dev *rk29_camdev_info_ptr;
309 static int rk29_camera_s_stream(struct soc_camera_device *icd, int enable);
313 * Videobuf operations
315 static int rk29_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
318 struct soc_camera_device *icd = vq->priv_data;
319 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
320 struct rk29_camera_dev *pcdev = ici->priv;
321 int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
322 icd->current_fmt->host_fmt);
323 int bytes_per_line_host = soc_mbus_bytes_per_line(pcdev->host_width,
324 icd->current_fmt->host_fmt);
326 dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size);
328 if (bytes_per_line < 0)
329 return bytes_per_line;
331 /* planar capture requires Y, U and V buffers to be page aligned */
332 *size = PAGE_ALIGN(bytes_per_line*icd->user_height); /* Y pages UV pages, yuv422*/
333 pcdev->vipmem_bsize = PAGE_ALIGN(bytes_per_line_host * pcdev->host_height);
336 if (CAM_WORKQUEUE_IS_EN()) {
337 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_OFF
338 if (CAM_IPPWORK_IS_EN())
341 BUG_ON(pcdev->vipmem_size<pcdev->vipmem_bsize);
342 if (*count > pcdev->vipmem_size/pcdev->vipmem_bsize) { /* Buffers must be limited, when this resolution is genered by IPP */
343 *count = pcdev->vipmem_size/pcdev->vipmem_bsize;
346 if ((pcdev->camera_work_count != *count) && pcdev->camera_work) {
347 kfree(pcdev->camera_work);
348 pcdev->camera_work = NULL;
349 pcdev->camera_work_count = 0;
352 if (pcdev->camera_work == NULL) {
353 pcdev->camera_work = kmalloc(sizeof(struct rk29_camera_work)*(*count), GFP_KERNEL);
354 if (pcdev->camera_work == NULL) {
355 RK29CAMERA_TR("\n %s kmalloc fail\n", __FUNCTION__);
358 pcdev->camera_work_count = *count;
362 RK29CAMERA_DG("%s..%d.. videobuf size:%d, vipmem_buf size:%d, count:%d \n",__FUNCTION__,__LINE__, *size,pcdev->vipmem_size, *count);
366 static void rk29_videobuf_free(struct videobuf_queue *vq, struct rk29_buffer *buf)
368 struct soc_camera_device *icd = vq->priv_data;
370 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
371 &buf->vb, buf->vb.baddr, buf->vb.bsize);
373 /* ddl@rock-chips.com: buf_release called soc_camera_streamoff and soc_camera_close*/
374 if (buf->vb.state == VIDEOBUF_NEEDS_INIT)
380 * This waits until this buffer is out of danger, i.e., until it is no
381 * longer in STATE_QUEUED or STATE_ACTIVE
383 //videobuf_waiton(vq, &buf->vb, 0, 0);
384 videobuf_dma_contig_free(vq, &buf->vb);
385 dev_dbg(&icd->dev, "%s freed\n", __func__);
386 buf->vb.state = VIDEOBUF_NEEDS_INIT;
389 static int rk29_videobuf_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, enum v4l2_field field)
391 struct soc_camera_device *icd = vq->priv_data;
392 struct rk29_buffer *buf;
394 int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
395 icd->current_fmt->host_fmt);
396 if (bytes_per_line < 0)
397 return bytes_per_line;
399 buf = container_of(vb, struct rk29_buffer, vb);
401 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
402 vb, vb->baddr, vb->bsize);
404 //RK29CAMERA_TR("\n%s..%d.. \n",__FUNCTION__,__LINE__);
406 /* Added list head initialization on alloc */
407 WARN_ON(!list_empty(&vb->queue));
409 /* This can be useful if you want to see if we actually fill
410 * the buffer with something */
411 //memset((void *)vb->baddr, 0xaa, vb->bsize);
413 BUG_ON(NULL == icd->current_fmt);
415 if (buf->code != icd->current_fmt->code ||
416 vb->width != icd->user_width ||
417 vb->height != icd->user_height ||
418 vb->field != field) {
419 buf->code = icd->current_fmt->code;
420 vb->width = icd->user_width;
421 vb->height = icd->user_height;
423 vb->state = VIDEOBUF_NEEDS_INIT;
426 vb->size = bytes_per_line*vb->height; /* ddl@rock-chips.com : fmt->depth is coorect */
427 if (0 != vb->baddr && vb->bsize < vb->size) {
432 if (vb->state == VIDEOBUF_NEEDS_INIT) {
433 ret = videobuf_iolock(vq, vb, NULL);
437 vb->state = VIDEOBUF_PREPARED;
439 //RK29CAMERA_TR("\n%s..%d.. \n",__FUNCTION__,__LINE__);
442 rk29_videobuf_free(vq, buf);
447 static inline void rk29_videobuf_capture(struct videobuf_buffer *vb)
449 unsigned int y_addr,uv_addr;
450 struct rk29_camera_dev *pcdev = rk29_camdev_info_ptr;
453 if (CAM_WORKQUEUE_IS_EN()) {
454 y_addr = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
455 uv_addr = y_addr + pcdev->host_width*pcdev->host_height;
457 if (y_addr > (pcdev->vipmem_phybase + pcdev->vipmem_size - pcdev->vipmem_bsize)) {
458 RK29CAMERA_TR("vipmem for IPP is overflow! %dx%d -> %dx%d vb_index:%d\n",pcdev->host_width,pcdev->host_height,
459 pcdev->icd->user_width,pcdev->icd->user_height, vb->i);
464 uv_addr = y_addr + vb->width * vb->height;
466 write_vip_reg(RK29_VIP_CAPTURE_F1SA_Y, y_addr);
467 write_vip_reg(RK29_VIP_CAPTURE_F1SA_UV, uv_addr);
468 write_vip_reg(RK29_VIP_CAPTURE_F2SA_Y, y_addr);
469 write_vip_reg(RK29_VIP_CAPTURE_F2SA_UV, uv_addr);
470 write_vip_reg(RK29_VIP_FB_SR, 0x00000002);//frame1 has been ready to receive data,frame 2 is not used
473 /* Locking: Caller holds q->irqlock */
474 static void rk29_videobuf_queue(struct videobuf_queue *vq,
475 struct videobuf_buffer *vb)
477 struct soc_camera_device *icd = vq->priv_data;
478 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
479 struct rk29_camera_dev *pcdev = ici->priv;
481 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
482 vb, vb->baddr, vb->bsize);
484 vb->state = VIDEOBUF_QUEUED;
486 if (list_empty(&pcdev->capture)) {
487 list_add_tail(&vb->queue, &pcdev->capture);
489 if (list_entry(pcdev->capture.next, struct videobuf_buffer, queue) != vb)
490 list_add_tail(&vb->queue, &pcdev->capture);
492 BUG(); /* ddl@rock-chips.com : The same videobuffer queue again */
494 if (!pcdev->active) {
496 rk29_videobuf_capture(vb);
499 static int rk29_pixfmt2ippfmt(unsigned int pixfmt, int *ippfmt)
503 case V4L2_PIX_FMT_NV16:
504 case V4L2_PIX_FMT_YUV422P:
506 *ippfmt = IPP_Y_CBCR_H2V1;
509 case V4L2_PIX_FMT_NV12:
510 case V4L2_PIX_FMT_YUV420:
512 *ippfmt = IPP_Y_CBCR_H2V2;
516 goto rk29_pixfmt2ippfmt_err;
520 rk29_pixfmt2ippfmt_err:
523 static void rk29_camera_capture_process(struct work_struct *work)
525 struct rk29_camera_work *camera_work = container_of(work, struct rk29_camera_work, work);
526 struct videobuf_buffer *vb = camera_work->vb;
527 struct rk29_camera_dev *pcdev = camera_work->pcdev;
528 struct rk29_ipp_req ipp_req;
529 unsigned long int flags;
530 int src_y_offset,src_uv_offset,dst_y_offset,dst_uv_offset,src_y_size,dst_y_size;
531 int scale_times,w,h,vipdata_base;
535 * IPP Dest image resolution is 2047x1088, so scale operation break up some times
537 if ((pcdev->icd->user_width > 0x7f0) || (pcdev->icd->user_height > 0x430)) {
538 scale_times = MAX((pcdev->icd->user_width/0x7f0),(pcdev->icd->user_height/0x430));
544 memset(&ipp_req, 0, sizeof(struct rk29_ipp_req));
546 down(&pcdev->zoominfo.sem);
548 ipp_req.timeout = 100;
549 ipp_req.flag = IPP_ROT_0;
550 ipp_req.src0.w = pcdev->zoominfo.a.c.width/scale_times;
551 ipp_req.src0.h = pcdev->zoominfo.a.c.height/scale_times;
552 ipp_req.src_vir_w = pcdev->host_width;
553 rk29_pixfmt2ippfmt(pcdev->pixfmt, &ipp_req.src0.fmt);
554 ipp_req.dst0.w = pcdev->icd->user_width/scale_times;
555 ipp_req.dst0.h = pcdev->icd->user_height/scale_times;
556 ipp_req.dst_vir_w = pcdev->icd->user_width;
557 rk29_pixfmt2ippfmt(pcdev->pixfmt, &ipp_req.dst0.fmt);
559 vipdata_base = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
560 src_y_size = pcdev->host_width*pcdev->host_height;
561 dst_y_size = pcdev->icd->user_width*pcdev->icd->user_height;
563 for (h=0; h<scale_times; h++) {
564 for (w=0; w<scale_times; w++) {
566 src_y_offset = (pcdev->zoominfo.a.c.top + h*pcdev->zoominfo.a.c.height/scale_times)* pcdev->host_width
567 + pcdev->zoominfo.a.c.left + w*pcdev->zoominfo.a.c.width/scale_times;
568 src_uv_offset = (pcdev->zoominfo.a.c.top + h*pcdev->zoominfo.a.c.height/scale_times)* pcdev->host_width/2
569 + pcdev->zoominfo.a.c.left + w*pcdev->zoominfo.a.c.width/scale_times;
571 dst_y_offset = pcdev->icd->user_width*pcdev->icd->user_height*h/scale_times + pcdev->icd->user_width*w/scale_times;
572 dst_uv_offset = pcdev->icd->user_width*pcdev->icd->user_height*h/scale_times/2 + pcdev->icd->user_width*w/scale_times;
574 ipp_req.src0.YrgbMst = vipdata_base + src_y_offset;
575 ipp_req.src0.CbrMst = vipdata_base + src_y_size + src_uv_offset;
576 ipp_req.dst0.YrgbMst = vb->boff + dst_y_offset;
577 ipp_req.dst0.CbrMst = vb->boff + dst_y_size + dst_uv_offset;
579 if (ipp_blit_sync(&ipp_req)) {
580 spin_lock_irqsave(&pcdev->lock, flags);
581 vb->state = VIDEOBUF_ERROR;
582 spin_unlock_irqrestore(&pcdev->lock, flags);
584 RK29CAMERA_TR("Capture image(vb->i:0x%x) which IPP operated is error:\n",vb->i);
585 RK29CAMERA_TR("widx:%d hidx:%d ",w,h);
586 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);
587 RK29CAMERA_TR("ipp_req.src0.YrgbMst:0x%x ipp_req.src0.CbrMst:0x%x \n", ipp_req.src0.YrgbMst,ipp_req.src0.CbrMst);
588 RK29CAMERA_TR("ipp_req.src0.w:0x%x ipp_req.src0.h:0x%x \n",ipp_req.src0.w,ipp_req.src0.h);
589 RK29CAMERA_TR("ipp_req.src0.fmt:0x%x\n",ipp_req.src0.fmt);
590 RK29CAMERA_TR("ipp_req.dst0.YrgbMst:0x%x ipp_req.dst0.CbrMst:0x%x \n",ipp_req.dst0.YrgbMst,ipp_req.dst0.CbrMst);
591 RK29CAMERA_TR("ipp_req.dst0.w:0x%x ipp_req.dst0.h:0x%x \n",ipp_req.dst0.w ,ipp_req.dst0.h);
592 RK29CAMERA_TR("ipp_req.dst0.fmt:0x%x\n",ipp_req.dst0.fmt);
593 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);
594 RK29CAMERA_TR("ipp_req.timeout:0x%x ipp_req.flag :0x%x\n",ipp_req.timeout,ipp_req.flag);
601 if (pcdev->icd_cb.sensor_cb)
602 (pcdev->icd_cb.sensor_cb)(vb);
605 up(&pcdev->zoominfo.sem);
606 wake_up(&(camera_work->vb->done));
609 static irqreturn_t rk29_camera_irq(int irq, void *data)
611 struct rk29_camera_dev *pcdev = data;
612 struct videobuf_buffer *vb;
613 struct rk29_camera_work *wk;
614 static struct timeval first_tv;
617 read_vip_reg(RK29_VIP_INT_STS); /* clear vip interrupte single */
618 /* ddl@rock-chps.com : Current VIP is run in One Frame Mode, Frame 1 is validate */
619 if (read_vip_reg(RK29_VIP_FB_SR) & 0x01) {
621 do_gettimeofday(&first_tv);
625 goto RK29_CAMERA_IRQ_END;
627 if (pcdev->frame_inval>0) {
628 pcdev->frame_inval--;
629 rk29_videobuf_capture(pcdev->active);
630 goto RK29_CAMERA_IRQ_END;
631 } else if (pcdev->frame_inval) {
632 RK29CAMERA_TR("frame_inval : %0x",pcdev->frame_inval);
633 pcdev->frame_inval = 0;
636 if(pcdev->fps == RK29_CAM_FRAME_MEASURE) {
637 do_gettimeofday(&tv);
638 pcdev->frame_interval = ((tv.tv_sec*1000000 + tv.tv_usec) - (first_tv.tv_sec*1000000 + first_tv.tv_usec))
639 /(RK29_CAM_FRAME_MEASURE-1);
643 /* ddl@rock-chips.com : this vb may be deleted from queue */
644 if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) {
645 list_del_init(&vb->queue);
648 pcdev->active = NULL;
649 if (!list_empty(&pcdev->capture)) {
650 pcdev->active = list_entry(pcdev->capture.next, struct videobuf_buffer, queue);
652 rk29_videobuf_capture(pcdev->active);
656 if (pcdev->active == NULL) {
657 RK29CAMERA_DG("%s video_buf queue is empty!\n",__FUNCTION__);
660 if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) {
661 vb->state = VIDEOBUF_DONE;
662 do_gettimeofday(&vb->ts);
666 if (CAM_WORKQUEUE_IS_EN()) {
667 wk = pcdev->camera_work + vb->i;
668 INIT_WORK(&(wk->work), rk29_camera_capture_process);
671 queue_work(pcdev->camera_wq, &(wk->work));
682 static void rk29_videobuf_release(struct videobuf_queue *vq,
683 struct videobuf_buffer *vb)
685 struct rk29_buffer *buf = container_of(vb, struct rk29_buffer, vb);
686 struct soc_camera_device *icd = vq->priv_data;
687 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
688 struct rk29_camera_dev *pcdev = ici->priv;
690 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
691 vb, vb->baddr, vb->bsize);
695 case VIDEOBUF_ACTIVE:
696 dev_dbg(&icd->dev, "%s (active)\n", __func__);
698 case VIDEOBUF_QUEUED:
699 dev_dbg(&icd->dev, "%s (queued)\n", __func__);
701 case VIDEOBUF_PREPARED:
702 dev_dbg(&icd->dev, "%s (prepared)\n", __func__);
705 dev_dbg(&icd->dev, "%s (unknown)\n", __func__);
709 if (vb == pcdev->active) {
710 RK29CAMERA_DG("%s Wait for this video buf(0x%x) write finished!\n ",__FUNCTION__,(unsigned int)vb);
711 interruptible_sleep_on_timeout(&vb->done, 100);
712 RK29CAMERA_DG("%s This video buf(0x%x) write finished, release now!!\n",__FUNCTION__,(unsigned int)vb);
714 rk29_videobuf_free(vq, buf);
717 static struct videobuf_queue_ops rk29_videobuf_ops =
719 .buf_setup = rk29_videobuf_setup,
720 .buf_prepare = rk29_videobuf_prepare,
721 .buf_queue = rk29_videobuf_queue,
722 .buf_release = rk29_videobuf_release,
725 static void rk29_camera_init_videobuf(struct videobuf_queue *q,
726 struct soc_camera_device *icd)
728 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
729 struct rk29_camera_dev *pcdev = ici->priv;
731 /* We must pass NULL as dev pointer, then all pci_* dma operations
732 * transform to normal dma_* ones. */
733 videobuf_queue_dma_contig_init(q,
735 ici->v4l2_dev.dev, &pcdev->lock,
736 V4L2_BUF_TYPE_VIDEO_CAPTURE,
738 sizeof(struct rk29_buffer),
739 icd,&icd->video_lock);
741 static int rk29_camera_activate(struct rk29_camera_dev *pcdev, struct soc_camera_device *icd)
743 unsigned long sensor_bus_flags = SOCAM_MCLK_24MHZ;
746 RK29CAMERA_DG("%s..%d.. \n",__FUNCTION__,__LINE__);
747 if (!pcdev->aclk_ddr_lcdc || !pcdev->aclk_disp_matrix || !pcdev->hclk_cpu_display ||
748 !pcdev->vip_slave || !pcdev->vip_out || !pcdev->vip_input || !pcdev->vip_bus || !pcdev->pd_display ||
749 IS_ERR(pcdev->aclk_ddr_lcdc) || IS_ERR(pcdev->aclk_disp_matrix) || IS_ERR(pcdev->hclk_cpu_display) || IS_ERR(pcdev->pd_display) ||
750 IS_ERR(pcdev->vip_slave) || IS_ERR(pcdev->vip_out) || IS_ERR(pcdev->vip_input) || IS_ERR(pcdev->vip_bus)) {
752 RK29CAMERA_TR(KERN_ERR "failed to get vip_clk(axi) source\n");
753 goto RK29_CAMERA_ACTIVE_ERR;
756 if (!pcdev->hclk_disp_matrix || !pcdev->vip_matrix ||
757 IS_ERR(pcdev->hclk_disp_matrix) || IS_ERR(pcdev->vip_matrix)) {
759 RK29CAMERA_TR(KERN_ERR "failed to get vip_clk(ahb) source\n");
760 goto RK29_CAMERA_ACTIVE_ERR;
763 clk_enable(pcdev->pd_display);
765 clk_enable(pcdev->aclk_ddr_lcdc);
766 clk_enable(pcdev->aclk_disp_matrix);
768 clk_enable(pcdev->hclk_cpu_display);
769 clk_enable(pcdev->vip_slave);
771 #if (CONFIG_RK29_CAM_WORK_BUS==RK29_CAM_AHB)
772 clk_enable(pcdev->hclk_disp_matrix);
773 clk_enable(pcdev->vip_matrix);
776 clk_enable(pcdev->vip_input);
777 clk_enable(pcdev->vip_bus);
779 //if (icd->ops->query_bus_param) /* ddl@rock-chips.com : Query Sensor's xclk */
780 //sensor_bus_flags = icd->ops->query_bus_param(icd);
782 if (sensor_bus_flags & SOCAM_MCLK_48MHZ) {
783 parent = clk_get(NULL, "clk48m");
784 if (!parent || IS_ERR(parent))
785 goto RK29_CAMERA_ACTIVE_ERR;
786 } else if (sensor_bus_flags & SOCAM_MCLK_27MHZ) {
787 parent = clk_get(NULL, "extclk");
788 if (!parent || IS_ERR(parent))
789 goto RK29_CAMERA_ACTIVE_ERR;
791 parent = clk_get(NULL, "xin24m");
792 if (!parent || IS_ERR(parent))
793 goto RK29_CAMERA_ACTIVE_ERR;
796 clk_set_parent(pcdev->vip_out, parent);
798 clk_enable(pcdev->vip_out);
799 rk29_mux_api_set(GPIO1B4_VIPCLKOUT_NAME, GPIO1L_VIP_CLKOUT);
802 #if (CONFIG_RK29_CAM_WORK_BUS==RK29_CAM_AHB)
803 write_grf_reg(GRF_SOC_CON0_Reg, read_grf_reg(GRF_SOC_CON0_Reg)|VIP_AHBMASTER); //VIP Config to AHB
804 write_grf_reg(GRF_OS_REG0, read_grf_reg(GRF_OS_REG0)&(~VIP_ACLK_DIV_HCLK_2)); //aclk:hclk = 1:1
806 write_grf_reg(GRF_SOC_CON0_Reg, read_grf_reg(GRF_SOC_CON0_Reg)&(~VIP_AHBMASTER)); //VIP Config to AXI
807 write_grf_reg(GRF_OS_REG0, read_grf_reg(GRF_OS_REG0)|VIP_ACLK_DIV_HCLK_2); //aclk:hclk = 2:1
811 write_vip_reg(RK29_VIP_RESET, 0x76543210); /* ddl@rock-chips.com : vip software reset */
814 write_vip_reg(RK29_VIP_AHBR_CTRL, 0x07); /* ddl@rock-chips.com : vip ahb burst 16 */
815 write_vip_reg(RK29_VIP_INT_MASK, 0x01); //capture complete interrupt enable
816 write_vip_reg(RK29_VIP_CRM, 0x00000000); //Y/CB/CR color modification
819 RK29_CAMERA_ACTIVE_ERR:
823 static void rk29_camera_deactivate(struct rk29_camera_dev *pcdev)
825 //pcdev->active = NULL;
827 write_vip_reg(RK29_VIP_CTRL, 0);
828 read_vip_reg(RK29_VIP_INT_STS); //clear vip interrupte single
830 rk29_mux_api_set(GPIO1B4_VIPCLKOUT_NAME, GPIO1L_GPIO1B4);
831 clk_disable(pcdev->vip_out);
833 clk_disable(pcdev->vip_input);
834 clk_disable(pcdev->vip_bus);
836 #if (CONFIG_RK29_CAM_WORK_BUS==RK29_CAM_AHB)
837 clk_disable(pcdev->hclk_disp_matrix);
838 clk_disable(pcdev->vip_matrix);
841 clk_disable(pcdev->hclk_cpu_display);
842 clk_disable(pcdev->vip_slave);
844 clk_disable(pcdev->aclk_ddr_lcdc);
845 clk_disable(pcdev->aclk_disp_matrix);
847 clk_disable(pcdev->pd_display);
851 /* The following two functions absolutely depend on the fact, that
852 * there can be only one camera on RK28 quick capture interface */
853 static int rk29_camera_add_device(struct soc_camera_device *icd)
855 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
856 struct rk29_camera_dev *pcdev = ici->priv;
857 struct device *control = to_soc_camera_control(icd);
858 struct v4l2_subdev *sd;
860 struct rk29_camera_frmivalenum *fival_list,*fival_nxt;
862 mutex_lock(&camera_lock);
869 RK29CAMERA_DG("RK29 Camera driver attached to %s\n",dev_name(icd->pdev));
871 pcdev->frame_inval = RK29_CAM_FRAME_INVAL_INIT;
872 pcdev->active = NULL;
874 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
875 pcdev->zoominfo.zoom_rate = 100;
877 /* ddl@rock-chips.com: capture list must be reset, because this list may be not empty,
878 * if app havn't dequeue all videobuf before close camera device;
880 INIT_LIST_HEAD(&pcdev->capture);
882 ret = rk29_camera_activate(pcdev,icd);
886 /* ddl@rock-chips.com : v4l2_subdev is not created when ici->ops->add called in soc_camera_probe */
888 sd = dev_get_drvdata(control);
889 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_IOREQUEST,(void*)pcdev->pdata);
891 ret = v4l2_subdev_call(sd,core, init, 0);
895 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_CB_REGISTER,(void*)(&pcdev->icd_cb));
902 for (i=0; i<2; i++) {
903 if (pcdev->icd_frmival[i].icd == icd)
905 if (pcdev->icd_frmival[i].icd == NULL) {
906 pcdev->icd_frmival[i].icd = icd;
911 if (icd_catch == 0) {
912 fival_list = pcdev->icd_frmival[0].fival_list;
913 fival_nxt = fival_list;
914 while(fival_nxt != NULL) {
915 fival_nxt = fival_list->nxt;
917 fival_list = fival_nxt;
919 pcdev->icd_frmival[0].icd = icd;
920 pcdev->icd_frmival[0].fival_list = kzalloc(sizeof(struct rk29_camera_frmivalenum),GFP_KERNEL);
923 mutex_unlock(&camera_lock);
927 static void rk29_camera_remove_device(struct soc_camera_device *icd)
929 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
930 struct rk29_camera_dev *pcdev = ici->priv;
931 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
933 mutex_lock(&camera_lock);
934 BUG_ON(icd != pcdev->icd);
936 RK29CAMERA_DG("RK29 Camera driver detached from %s\n",dev_name(icd->pdev));
938 /* ddl@rock-chips.com: Application will call VIDIOC_STREAMOFF before close device, but
939 stream may be turn on again before close device, if suspend and resume happened. */
940 if (read_vip_reg(RK29_VIP_CTRL) & ENABLE_CAPTURE) {
941 rk29_camera_s_stream(icd,0);
944 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_DEACTIVATE,NULL);
945 rk29_camera_deactivate(pcdev);
947 if (pcdev->camera_work) {
948 kfree(pcdev->camera_work);
949 pcdev->camera_work = NULL;
950 pcdev->camera_work_count = 0;
953 pcdev->active = NULL;
955 pcdev->icd_cb.sensor_cb = NULL;
956 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
957 /* ddl@rock-chips.com: capture list must be reset, because this list may be not empty,
958 * if app havn't dequeue all videobuf before close camera device;
960 INIT_LIST_HEAD(&pcdev->capture);
962 mutex_unlock(&camera_lock);
963 RK29CAMERA_DG("%s exit\n",__FUNCTION__);
967 static int rk29_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
969 unsigned long bus_flags, camera_flags, common_flags;
970 unsigned int vip_ctrl_val = 0;
971 const struct soc_mbus_pixelfmt *fmt;
974 RK29CAMERA_DG("%s..%d..\n",__FUNCTION__,__LINE__);
976 fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code);
980 bus_flags = RK29_CAM_BUS_PARAM;
981 /* If requested data width is supported by the platform, use it */
982 switch (fmt->bits_per_sample) {
984 if (!(bus_flags & SOCAM_DATAWIDTH_10))
988 if (!(bus_flags & SOCAM_DATAWIDTH_9))
992 if (!(bus_flags & SOCAM_DATAWIDTH_8))
999 if (icd->ops->query_bus_param)
1000 camera_flags = icd->ops->query_bus_param(icd);
1004 common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
1005 if (!common_flags) {
1007 goto RK29_CAMERA_SET_BUS_PARAM_END;
1010 ret = icd->ops->set_bus_param(icd, common_flags);
1012 goto RK29_CAMERA_SET_BUS_PARAM_END;
1014 vip_ctrl_val = read_vip_reg(RK29_VIP_CTRL);
1015 if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) {
1016 vip_ctrl_val |= NEGATIVE_EDGE;
1018 vip_ctrl_val &= ~NEGATIVE_EDGE;
1020 if (common_flags & SOCAM_HSYNC_ACTIVE_LOW) {
1021 vip_ctrl_val |= HSY_LOW_ACTIVE;
1023 vip_ctrl_val &= ~HSY_LOW_ACTIVE;
1025 if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH) {
1026 vip_ctrl_val |= VSY_HIGH_ACTIVE;
1028 vip_ctrl_val &= ~VSY_HIGH_ACTIVE;
1031 /* ddl@rock-chips.com : Don't enable capture here, enable in stream_on */
1032 //vip_ctrl_val |= ENABLE_CAPTURE;
1034 write_vip_reg(RK29_VIP_CTRL, vip_ctrl_val);
1035 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),
1036 read_grf_reg(GRF_SOC_CON0_Reg)&VIP_AHBMASTER, read_grf_reg(GRF_OS_REG0)&VIP_ACLK_DIV_HCLK_2);
1038 RK29_CAMERA_SET_BUS_PARAM_END:
1040 RK29CAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
1044 static int rk29_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
1046 unsigned long bus_flags, camera_flags;
1049 bus_flags = RK29_CAM_BUS_PARAM;
1050 if (icd->ops->query_bus_param) {
1051 camera_flags = icd->ops->query_bus_param(icd);
1055 ret = soc_camera_bus_param_compatible(camera_flags, bus_flags) ;
1058 dev_warn(icd->dev.parent,
1059 "Flags incompatible: camera %lx, host %lx\n",
1060 camera_flags, bus_flags);
1064 static const struct soc_mbus_pixelfmt rk29_camera_formats[] = {
1066 .fourcc = V4L2_PIX_FMT_NV12,
1067 .name = "YUV420 NV12",
1068 .bits_per_sample = 8,
1069 .packing = SOC_MBUS_PACKING_1_5X8,
1070 .order = SOC_MBUS_ORDER_LE,
1072 .fourcc = V4L2_PIX_FMT_NV16,
1073 .name = "YUV422 NV16",
1074 .bits_per_sample = 8,
1075 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1076 .order = SOC_MBUS_ORDER_LE,
1078 .fourcc = V4L2_PIX_FMT_YUV420,
1079 .name = "NV12(v0.0.1)",
1080 .bits_per_sample = 8,
1081 .packing = SOC_MBUS_PACKING_1_5X8,
1082 .order = SOC_MBUS_ORDER_LE,
1084 .fourcc = V4L2_PIX_FMT_YUV422P,
1085 .name = "NV16(v0.0.1)",
1086 .bits_per_sample = 8,
1087 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1088 .order = SOC_MBUS_ORDER_LE,
1092 static void rk29_camera_setup_format(struct soc_camera_device *icd, __u32 host_pixfmt, enum v4l2_mbus_pixelcode icd_code, struct v4l2_rect *rect)
1094 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1095 struct rk29_camera_dev *pcdev = ici->priv;
1096 unsigned int vip_fs = 0,vip_crop = 0;
1097 unsigned int vip_ctrl_val = VIP_SENSOR|ONEFRAME|DISABLE_CAPTURE;
1099 switch (host_pixfmt)
1101 case V4L2_PIX_FMT_NV16:
1102 case V4L2_PIX_FMT_YUV422P: /* ddl@rock-chips.com: V4L2_PIX_FMT_YUV422P is V4L2_PIX_FMT_NV16 actually in 0.0.1 driver */
1103 vip_ctrl_val |= VIPREGYUV422;
1104 pcdev->frame_inval = RK29_CAM_FRAME_INVAL_DC;
1105 pcdev->pixfmt = host_pixfmt;
1107 case V4L2_PIX_FMT_NV12:
1108 case V4L2_PIX_FMT_YUV420: /* ddl@rock-chips.com: V4L2_PIX_FMT_YUV420 is V4L2_PIX_FMT_NV12 actually in 0.0.1 driver */
1109 vip_ctrl_val |= VIPREGYUV420;
1110 if (pcdev->frame_inval != RK29_CAM_FRAME_INVAL_INIT)
1111 pcdev->frame_inval = RK29_CAM_FRAME_INVAL_INIT;
1112 pcdev->pixfmt = host_pixfmt;
1114 default: /* ddl@rock-chips.com : vip output format is hold when pixfmt is invalidate */
1115 vip_ctrl_val |= (read_vip_reg(RK29_VIP_CTRL) & VIPREGYUV422);
1121 case V4L2_MBUS_FMT_UYVY8_2X8:
1122 vip_ctrl_val |= SENSOR_UYVY;
1124 case V4L2_MBUS_FMT_YUYV8_2X8:
1125 vip_ctrl_val |= SENSOR_YUYV;
1128 vip_ctrl_val |= (read_vip_reg(RK29_VIP_CTRL) & SENSOR_YUYV);
1132 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 */
1134 read_vip_reg(RK29_VIP_INT_STS); /* clear vip interrupte single */
1136 if (vip_ctrl_val & ONEFRAME) {
1137 vip_crop = ((rect->left<<16) + rect->top);
1138 vip_fs = (((rect->width + rect->left)<<16) + (rect->height+rect->top));
1139 } else if (vip_ctrl_val & PING_PONG) {
1143 write_vip_reg(RK29_VIP_CROP, vip_crop);
1144 write_vip_reg(RK29_VIP_FS, vip_fs);
1146 write_vip_reg(RK29_VIP_FB_SR, 0x00000003);
1148 pcdev->host_width = rect->width;
1149 pcdev->host_height = rect->height;
1151 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));
1155 static int rk29_camera_get_formats(struct soc_camera_device *icd, unsigned int idx,
1156 struct soc_camera_format_xlate *xlate)
1158 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1159 struct device *dev = icd->dev.parent;
1160 int formats = 0, ret;
1161 enum v4l2_mbus_pixelcode code;
1162 const struct soc_mbus_pixelfmt *fmt;
1164 ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
1166 /* No more formats */
1169 fmt = soc_mbus_get_fmtdesc(code);
1171 dev_err(dev, "Invalid format code #%u: %d\n", idx, code);
1175 ret = rk29_camera_try_bus_param(icd, fmt->bits_per_sample);
1180 case V4L2_MBUS_FMT_UYVY8_2X8:
1181 case V4L2_MBUS_FMT_YUYV8_2X8:
1184 xlate->host_fmt = &rk29_camera_formats[0];
1187 dev_dbg(dev, "Providing format %s using code %d\n",
1188 rk29_camera_formats[0].name,code);
1193 xlate->host_fmt = &rk29_camera_formats[1];
1196 dev_dbg(dev, "Providing format %s using code %d\n",
1197 rk29_camera_formats[1].name,code);
1202 xlate->host_fmt = &rk29_camera_formats[2];
1205 dev_dbg(dev, "Providing format %s using code %d\n",
1206 rk29_camera_formats[2].name,code);
1211 xlate->host_fmt = &rk29_camera_formats[3];
1214 dev_dbg(dev, "Providing format %s using code %d\n",
1215 rk29_camera_formats[3].name,code);;
1225 static void rk29_camera_put_formats(struct soc_camera_device *icd)
1230 static int rk29_camera_set_crop(struct soc_camera_device *icd,
1231 struct v4l2_crop *a)
1233 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1234 struct v4l2_mbus_framefmt mf;
1235 u32 fourcc = icd->current_fmt->host_fmt->fourcc;
1238 ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
1242 if ((mf.width < (a->c.left + a->c.width)) || (mf.height < (a->c.top + a->c.height))) {
1244 mf.width = a->c.left + a->c.width;
1245 mf.height = a->c.top + a->c.height;
1247 v4l_bound_align_image(&mf.width, RK29_CAM_W_MIN, RK29_CAM_W_MAX, 1,
1248 &mf.height, RK29_CAM_H_MIN, RK29_CAM_H_MAX, 0,
1249 fourcc == V4L2_PIX_FMT_NV16 ?4 : 0);
1251 ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
1256 rk29_camera_setup_format(icd, fourcc, mf.code, &a->c);
1258 icd->user_width = mf.width;
1259 icd->user_height = mf.height;
1264 static int rk29_camera_set_fmt(struct soc_camera_device *icd,
1265 struct v4l2_format *f)
1267 struct device *dev = icd->dev.parent;
1268 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1269 const struct soc_camera_format_xlate *xlate = NULL;
1270 struct soc_camera_host *ici =to_soc_camera_host(icd->dev.parent);
1271 struct rk29_camera_dev *pcdev = ici->priv;
1272 struct v4l2_pix_format *pix = &f->fmt.pix;
1273 struct v4l2_mbus_framefmt mf;
1274 struct v4l2_rect rect;
1275 int ret,usr_w,usr_h,icd_width,icd_height;
1279 usr_h = pix->height;
1280 RK29CAMERA_DG("%s enter width:%d height:%d\n",__FUNCTION__,usr_w,usr_h);
1282 xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
1284 dev_err(dev, "Format %x not found\n", pix->pixelformat);
1286 goto RK29_CAMERA_SET_FMT_END;
1289 /* ddl@rock-chips.com: sensor init code transmit in here after open */
1290 if (pcdev->icd_init == 0) {
1291 v4l2_subdev_call(sd,core, init, 0);
1292 pcdev->icd_init = 1;
1295 stream_on = read_vip_reg(RK29_VIP_CTRL);
1296 if (stream_on & ENABLE_CAPTURE)
1297 write_vip_reg(RK29_VIP_CTRL, (stream_on & (~ENABLE_CAPTURE)));
1299 mf.width = pix->width;
1300 mf.height = pix->height;
1301 mf.field = pix->field;
1302 mf.colorspace = pix->colorspace;
1303 mf.code = xlate->code;
1305 ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
1307 if (mf.code != xlate->code)
1310 icd_width = mf.width;
1311 icd_height = mf.height;
1312 #ifdef CONFIG_VIDEO_RK29_WORK_IPP
1313 if ((mf.width != usr_w) || (mf.height != usr_h)) {
1314 if (unlikely((mf.width <16) || (mf.width > 8190) || (mf.height < 16) || (mf.height > 8190))) {
1315 RK29CAMERA_TR("Senor and IPP both invalid source resolution(%dx%d)\n",mf.width,mf.height);
1317 goto RK29_CAMERA_SET_FMT_END;
1319 if (unlikely((usr_w <16)||(usr_h < 16))) {
1320 RK29CAMERA_TR("Senor and IPP both invalid destination resolution(%dx%d)\n",usr_w,usr_h);
1322 goto RK29_CAMERA_SET_FMT_END;
1330 if (mf.width*usr_h == mf.height*usr_w) {
1331 rect.width = mf.width;
1332 rect.height = mf.height;
1335 if (usr_w > usr_h) {
1336 if (mf.width > usr_w) {
1337 ratio = mf.width*10/usr_w;
1338 rect.width = usr_w*ratio/10;
1339 rect.height = usr_h*ratio/10;
1341 ratio = usr_w*10/mf.width + 1;
1342 rect.width = usr_w*10/ratio;
1343 rect.height = usr_h*10/ratio;
1346 if (mf.height > usr_h) {
1347 ratio = mf.height*10/usr_h;
1348 rect.width = usr_w*ratio/10;
1349 rect.height = usr_h*ratio/10;
1351 ratio = usr_h*10/mf.height + 1;
1352 rect.width = usr_w*10/ratio;
1353 rect.height = usr_h*10/ratio;
1358 rect.left = (mf.width - rect.width)/2;
1359 rect.top = (mf.height - rect.height)/2;
1361 down(&pcdev->zoominfo.sem);
1362 pcdev->zoominfo.a.c.width = rect.width*100/pcdev->zoominfo.zoom_rate;
1363 pcdev->zoominfo.a.c.width &= ~0x03;
1364 pcdev->zoominfo.a.c.height = rect.height*100/pcdev->zoominfo.zoom_rate;
1365 pcdev->zoominfo.a.c.height &= ~0x03;
1366 pcdev->zoominfo.a.c.left = ((rect.width - pcdev->zoominfo.a.c.width)/2 + rect.left)&(~0x01);
1367 pcdev->zoominfo.a.c.top = ((rect.height - pcdev->zoominfo.a.c.height)/2 + rect.top)&(~0x01);
1368 up(&pcdev->zoominfo.sem);
1370 /* ddl@rock-chips.com: IPP work limit check */
1371 if ((pcdev->zoominfo.a.c.width != usr_w) || (pcdev->zoominfo.a.c.height != usr_h)) {
1372 if (usr_w > 0x7f0) {
1373 if (((usr_w>>1)&0x3f) && (((usr_w>>1)&0x3f) <= 8)) {
1374 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));
1376 goto RK29_CAMERA_SET_FMT_END;
1379 if ((usr_w&0x3f) && ((usr_w&0x3f) <= 8)) {
1380 RK29CAMERA_TR("IPP Destination resolution(%dx%d, %d mod 64=%d is <= 8)",usr_w,usr_h, usr_w, (int)(usr_w&0x3f));
1382 goto RK29_CAMERA_SET_FMT_END;
1387 /* ddl@rock-chips.com: Crop is doing by IPP, not by VIP in rk2918 */
1390 rect.width = mf.width;
1391 rect.height = mf.height;
1393 RK29CAMERA_DG("%s..%s Sensor output:%dx%d VIP output:%dx%d (zoom: %dx%d@(%d,%d)->%dx%d)\n",__FUNCTION__,xlate->host_fmt->name,
1394 mf.width, mf.height,rect.width,rect.height, pcdev->zoominfo.a.c.width,pcdev->zoominfo.a.c.height, pcdev->zoominfo.a.c.left,pcdev->zoominfo.a.c.top,
1395 pix->width, pix->height);
1398 rk29_camera_setup_format(icd, pix->pixelformat, mf.code, &rect);
1400 if (CAM_IPPWORK_IS_EN()) {
1401 BUG_ON(pcdev->vipmem_phybase == 0);
1403 pcdev->icd_width = icd_width;
1404 pcdev->icd_height = icd_height;
1407 pix->height = usr_h;
1408 pix->field = mf.field;
1409 pix->colorspace = mf.colorspace;
1410 icd->current_fmt = xlate;
1413 RK29_CAMERA_SET_FMT_END:
1414 if (stream_on & ENABLE_CAPTURE)
1415 write_vip_reg(RK29_VIP_CTRL, (read_vip_reg(RK29_VIP_CTRL) | ENABLE_CAPTURE));
1417 RK29CAMERA_TR("\n%s: Driver isn't support %dx%d resolution which user request!\n",__FUNCTION__,usr_w,usr_h);
1420 static bool rk29_camera_fmt_capturechk(struct v4l2_format *f)
1424 if ((f->fmt.pix.width == 1024) && (f->fmt.pix.height == 768)) {
1426 } else if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 1024)) {
1428 } else if ((f->fmt.pix.width == 1600) && (f->fmt.pix.height == 1200)) {
1430 } else if ((f->fmt.pix.width == 2048) && (f->fmt.pix.height == 1536)) {
1432 } else if ((f->fmt.pix.width == 2592) && (f->fmt.pix.height == 1944)) {
1437 RK29CAMERA_DG("%s %dx%d is capture format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
1440 static int rk29_camera_try_fmt(struct soc_camera_device *icd,
1441 struct v4l2_format *f)
1443 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1444 struct rk29_camera_dev *pcdev = ici->priv;
1445 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1446 const struct soc_camera_format_xlate *xlate;
1447 struct v4l2_pix_format *pix = &f->fmt.pix;
1448 __u32 pixfmt = pix->pixelformat;
1449 int ret,usr_w,usr_h,i;
1450 bool is_capture = rk29_camera_fmt_capturechk(f);
1451 bool vipmem_is_overflow = false;
1452 struct v4l2_mbus_framefmt mf;
1453 int bytes_per_line_host;
1456 usr_h = pix->height;
1457 RK29CAMERA_DG("%s enter width:%d height:%d\n",__FUNCTION__,usr_w,usr_h);
1459 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
1461 dev_err(icd->dev.parent, "Format (%c%c%c%c) not found\n", pixfmt & 0xFF, (pixfmt >> 8) & 0xFF,
1462 (pixfmt >> 16) & 0xFF, (pixfmt >> 24) & 0xFF);
1464 RK29CAMERA_TR("%s(version:%c%c%c) support format:\n",rk29_cam_driver_description,(RK29_CAM_VERSION_CODE&0xff0000)>>16,
1465 (RK29_CAM_VERSION_CODE&0xff00)>>8,(RK29_CAM_VERSION_CODE&0xff));
1466 for (i = 0; i < icd->num_user_formats; i++)
1467 RK29CAMERA_TR("(%c%c%c%c)-%s\n",
1468 icd->user_formats[i].host_fmt->fourcc & 0xFF, (icd->user_formats[i].host_fmt->fourcc >> 8) & 0xFF,
1469 (icd->user_formats[i].host_fmt->fourcc >> 16) & 0xFF, (icd->user_formats[i].host_fmt->fourcc >> 24) & 0xFF,
1470 icd->user_formats[i].host_fmt->name);
1471 goto RK29_CAMERA_TRY_FMT_END;
1473 /* limit to rk29 hardware capabilities */
1474 v4l_bound_align_image(&pix->width, RK29_CAM_W_MIN, RK29_CAM_W_MAX, 1,
1475 &pix->height, RK29_CAM_H_MIN, RK29_CAM_H_MAX, 0,
1476 pixfmt == V4L2_PIX_FMT_NV16 ? 4 : 0);
1478 pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
1480 if (pix->bytesperline < 0)
1481 return pix->bytesperline;
1483 /* limit to sensor capabilities */
1484 mf.width = pix->width;
1485 mf.height = pix->height;
1486 mf.field = pix->field;
1487 mf.colorspace = pix->colorspace;
1488 mf.code = xlate->code;
1490 ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
1492 goto RK29_CAMERA_TRY_FMT_END;
1493 RK29CAMERA_DG("%s mf.width:%d mf.height:%d\n",__FUNCTION__,mf.width,mf.height);
1494 #ifdef CONFIG_VIDEO_RK29_WORK_IPP
1495 if ((mf.width != usr_w) || (mf.height != usr_h)) {
1496 bytes_per_line_host = soc_mbus_bytes_per_line(mf.width,icd->current_fmt->host_fmt);
1498 vipmem_is_overflow = (PAGE_ALIGN(bytes_per_line_host*mf.height) > pcdev->vipmem_size);
1500 /* Assume preview buffer minimum is 4 */
1501 vipmem_is_overflow = (PAGE_ALIGN(bytes_per_line_host*mf.height)*4 > pcdev->vipmem_size);
1503 if (vipmem_is_overflow == false) {
1505 pix->height = usr_h;
1507 RK29CAMERA_TR("vipmem for IPP is overflow, This resolution(%dx%d -> %dx%d) is invalidate!\n",mf.width,mf.height,usr_w,usr_h);
1508 pix->width = mf.width;
1509 pix->height = mf.height;
1512 if ((mf.width < usr_w) || (mf.height < usr_h)) {
1513 if (((usr_w>>1) > mf.width) || ((usr_h>>1) > mf.height)) {
1514 RK29CAMERA_TR("The aspect ratio(%dx%d/%dx%d) is bigger than 2 !\n",mf.width,mf.height,usr_w,usr_h);
1515 pix->width = mf.width;
1516 pix->height = mf.height;
1521 pix->width = mf.width;
1522 pix->height = mf.height;
1524 pix->colorspace = mf.colorspace;
1527 case V4L2_FIELD_ANY:
1528 case V4L2_FIELD_NONE:
1529 pix->field = V4L2_FIELD_NONE;
1532 /* TODO: support interlaced at least in pass-through mode */
1533 dev_err(icd->dev.parent, "Field type %d unsupported.\n",
1535 goto RK29_CAMERA_TRY_FMT_END;
1538 RK29_CAMERA_TRY_FMT_END:
1540 RK29CAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
1544 static int rk29_camera_reqbufs(struct soc_camera_device *icd,
1545 struct v4l2_requestbuffers *p)
1549 /* This is for locking debugging only. I removed spinlocks and now I
1550 * check whether .prepare is ever called on a linked buffer, or whether
1551 * a dma IRQ can occur for an in-work or unlinked buffer. Until now
1552 * it hadn't triggered */
1553 for (i = 0; i < p->count; i++) {
1554 struct rk29_buffer *buf = container_of(icd->vb_vidq.bufs[i],
1555 struct rk29_buffer, vb);
1557 INIT_LIST_HEAD(&buf->vb.queue);
1563 static unsigned int rk29_camera_poll(struct file *file, poll_table *pt)
1565 struct soc_camera_device *icd = file->private_data;
1566 struct rk29_buffer *buf;
1568 buf = list_entry(icd->vb_vidq.stream.next, struct rk29_buffer,
1571 poll_wait(file, &buf->vb.done, pt);
1573 if (buf->vb.state == VIDEOBUF_DONE ||
1574 buf->vb.state == VIDEOBUF_ERROR)
1575 return POLLIN|POLLRDNORM;
1580 static int rk29_camera_querycap(struct soc_camera_host *ici,
1581 struct v4l2_capability *cap)
1583 struct rk29_camera_dev *pcdev = ici->priv;
1584 char orientation[5];
1587 strlcpy(cap->card, dev_name(pcdev->icd->pdev), sizeof(cap->card));
1589 memset(orientation,0x00,sizeof(orientation));
1590 for (i=0; i<RK29_CAM_SUPPORT_NUMS;i++) {
1591 if ((pcdev->pdata->info[i].dev_name!=NULL) && (strcmp(dev_name(pcdev->icd->pdev), pcdev->pdata->info[i].dev_name) == 0)) {
1592 sprintf(orientation,"-%d",pcdev->pdata->info[i].orientation);
1596 if (orientation[0] != '-') {
1597 RK29CAMERA_TR("%s: %s is not registered in rk29_camera_platform_data, orientation apply default value",__FUNCTION__,dev_name(pcdev->icd->pdev));
1598 if (strstr(dev_name(pcdev->icd->pdev),"front"))
1599 strcat(cap->card,"-270");
1601 strcat(cap->card,"-90");
1603 strcat(cap->card,orientation);
1606 cap->version = RK29_CAM_VERSION_CODE;
1607 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1612 static int rk29_camera_suspend(struct soc_camera_device *icd, pm_message_t state)
1614 struct soc_camera_host *ici =
1615 to_soc_camera_host(icd->dev.parent);
1616 struct rk29_camera_dev *pcdev = ici->priv;
1617 struct v4l2_subdev *sd;
1620 mutex_lock(&camera_lock);
1621 if ((pcdev->icd == icd) && (icd->ops->suspend)) {
1622 rk29_camera_s_stream(icd, 0);
1623 sd = soc_camera_to_subdev(icd);
1624 v4l2_subdev_call(sd, video, s_stream, 0);
1625 ret = icd->ops->suspend(icd, state);
1627 pcdev->reginfo_suspend.VipCtrl = read_vip_reg(RK29_VIP_CTRL);
1628 pcdev->reginfo_suspend.VipCrop = read_vip_reg(RK29_VIP_CROP);
1629 pcdev->reginfo_suspend.VipFs = read_vip_reg(RK29_VIP_FS);
1630 pcdev->reginfo_suspend.VipIntMsk = read_vip_reg(RK29_VIP_INT_MASK);
1631 pcdev->reginfo_suspend.VipCrm = read_vip_reg(RK29_VIP_CRM);
1633 tmp = pcdev->reginfo_suspend.VipFs>>16; /* ddl@rock-chips.com */
1634 tmp += pcdev->reginfo_suspend.VipCrop>>16;
1635 pcdev->reginfo_suspend.VipFs = (pcdev->reginfo_suspend.VipFs & 0xffff) | (tmp<<16);
1637 pcdev->reginfo_suspend.Inval = Reg_Validate;
1638 rk29_camera_deactivate(pcdev);
1640 RK29CAMERA_DG("%s Enter Success...\n", __FUNCTION__);
1642 RK29CAMERA_DG("%s icd has been deattach, don't need enter suspend\n", __FUNCTION__);
1644 mutex_unlock(&camera_lock);
1648 static int rk29_camera_resume(struct soc_camera_device *icd)
1650 struct soc_camera_host *ici =
1651 to_soc_camera_host(icd->dev.parent);
1652 struct rk29_camera_dev *pcdev = ici->priv;
1653 struct v4l2_subdev *sd;
1656 mutex_lock(&camera_lock);
1657 if ((pcdev->icd == icd) && (icd->ops->resume)) {
1658 if (pcdev->reginfo_suspend.Inval == Reg_Validate) {
1659 rk29_camera_activate(pcdev, icd);
1660 write_vip_reg(RK29_VIP_INT_MASK, pcdev->reginfo_suspend.VipIntMsk);
1661 write_vip_reg(RK29_VIP_CRM, pcdev->reginfo_suspend.VipCrm);
1662 write_vip_reg(RK29_VIP_CTRL, pcdev->reginfo_suspend.VipCtrl&~ENABLE_CAPTURE);
1663 write_vip_reg(RK29_VIP_CROP, pcdev->reginfo_suspend.VipCrop);
1664 write_vip_reg(RK29_VIP_FS, pcdev->reginfo_suspend.VipFs);
1666 rk29_videobuf_capture(pcdev->active);
1667 rk29_camera_s_stream(icd, 1);
1668 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
1670 RK29CAMERA_TR("Resume fail, vip register recored is invalidate!!\n");
1671 goto rk29_camera_resume_end;
1674 ret = icd->ops->resume(icd);
1675 sd = soc_camera_to_subdev(icd);
1676 v4l2_subdev_call(sd, video, s_stream, 1);
1678 RK29CAMERA_DG("%s Enter success\n",__FUNCTION__);
1680 RK29CAMERA_DG("%s icd has been deattach, don't need enter resume\n", __FUNCTION__);
1683 rk29_camera_resume_end:
1684 mutex_unlock(&camera_lock);
1688 static void rk29_camera_reinit_work(struct work_struct *work)
1690 struct device *control;
1691 struct v4l2_subdev *sd;
1692 struct v4l2_mbus_framefmt mf;
1693 const struct soc_camera_format_xlate *xlate;
1696 write_vip_reg(RK29_VIP_CTRL, (read_vip_reg(RK29_VIP_CTRL)&(~ENABLE_CAPTURE)));
1698 control = to_soc_camera_control(rk29_camdev_info_ptr->icd);
1699 sd = dev_get_drvdata(control);
1700 ret = v4l2_subdev_call(sd,core, init, 1);
1702 mf.width = rk29_camdev_info_ptr->icd->user_width;
1703 mf.height = rk29_camdev_info_ptr->icd->user_height;
1704 xlate = soc_camera_xlate_by_fourcc(rk29_camdev_info_ptr->icd, rk29_camdev_info_ptr->icd->current_fmt->host_fmt->fourcc);
1705 mf.code = xlate->code;
1707 ret |= v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
1709 write_vip_reg(RK29_VIP_CTRL, (read_vip_reg(RK29_VIP_CTRL)|ENABLE_CAPTURE));
1711 RK29CAMERA_TR("Camera host haven't recevie data from sensor,Reinit sensor now! ret:0x%x\n",ret);
1713 static enum hrtimer_restart rk29_camera_fps_func(struct hrtimer *timer)
1715 struct rk29_camera_frmivalenum *fival_nxt=NULL,*fival_pre=NULL, *fival_rec=NULL;
1718 RK29CAMERA_DG("rk29_camera_fps_func fps:0x%x\n",rk29_camdev_info_ptr->fps);
1719 if (rk29_camdev_info_ptr->fps < 2) {
1720 RK29CAMERA_TR("Camera host haven't recevie data from sensor,Reinit sensor delay!\n");
1721 INIT_WORK(&rk29_camdev_info_ptr->camera_reinit_work, rk29_camera_reinit_work);
1722 queue_work(rk29_camdev_info_ptr->camera_wq,&(rk29_camdev_info_ptr->camera_reinit_work));
1724 for (i=0; i<2; i++) {
1725 if (rk29_camdev_info_ptr->icd == rk29_camdev_info_ptr->icd_frmival[i].icd) {
1726 fival_nxt = rk29_camdev_info_ptr->icd_frmival[i].fival_list;
1731 fival_pre = fival_nxt;
1732 while (fival_nxt != NULL) {
1734 RK29CAMERA_DG("%s %c%c%c%c %dx%d framerate : %d/%d\n", dev_name(&rk29_camdev_info_ptr->icd->dev),
1735 fival_nxt->fival.pixel_format & 0xFF, (fival_nxt->fival.pixel_format >> 8) & 0xFF,
1736 (fival_nxt->fival.pixel_format >> 16) & 0xFF, (fival_nxt->fival.pixel_format >> 24),
1737 fival_nxt->fival.width, fival_nxt->fival.height, fival_nxt->fival.discrete.denominator,
1738 fival_nxt->fival.discrete.numerator);
1740 if (((fival_nxt->fival.pixel_format == rk29_camdev_info_ptr->pixfmt)
1741 && (fival_nxt->fival.height == rk29_camdev_info_ptr->icd->user_height)
1742 && (fival_nxt->fival.width == rk29_camdev_info_ptr->icd->user_width))
1743 || (fival_nxt->fival.discrete.denominator == 0)) {
1745 fival_nxt->fival.index = 0;
1746 fival_nxt->fival.width = rk29_camdev_info_ptr->icd->user_width;
1747 fival_nxt->fival.height= rk29_camdev_info_ptr->icd->user_height;
1748 fival_nxt->fival.pixel_format = rk29_camdev_info_ptr->pixfmt;
1749 fival_nxt->fival.discrete.denominator = rk29_camdev_info_ptr->frame_interval;
1750 fival_nxt->fival.reserved[1] = (rk29_camdev_info_ptr->icd_width<<16)
1751 |(rk29_camdev_info_ptr->icd_height);
1752 fival_nxt->fival.discrete.numerator = 1000000;
1753 fival_nxt->fival.type = V4L2_FRMIVAL_TYPE_DISCRETE;
1756 fival_rec = fival_nxt;
1758 fival_pre = fival_nxt;
1759 fival_nxt = fival_nxt->nxt;
1762 if ((rec_flag == 0) && fival_pre) {
1763 fival_pre->nxt = kzalloc(sizeof(struct rk29_camera_frmivalenum), GFP_ATOMIC);
1764 if (fival_pre->nxt != NULL) {
1765 fival_pre->nxt->fival.index = fival_pre->fival.index++;
1766 fival_pre->nxt->fival.width = rk29_camdev_info_ptr->icd->user_width;
1767 fival_pre->nxt->fival.height= rk29_camdev_info_ptr->icd->user_height;
1768 fival_pre->nxt->fival.pixel_format = rk29_camdev_info_ptr->pixfmt;
1770 fival_pre->nxt->fival.discrete.denominator = rk29_camdev_info_ptr->frame_interval;
1772 fival_pre->nxt->fival.reserved[1] = (rk29_camdev_info_ptr->icd_width<<16)
1773 |(rk29_camdev_info_ptr->icd_height);
1775 fival_pre->nxt->fival.discrete.numerator = 1000000;
1776 fival_pre->nxt->fival.type = V4L2_FRMIVAL_TYPE_DISCRETE;
1778 fival_rec = fival_pre->nxt;
1783 return HRTIMER_NORESTART;
1785 static int rk29_camera_s_stream(struct soc_camera_device *icd, int enable)
1787 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1788 struct rk29_camera_dev *pcdev = ici->priv;
1792 WARN_ON(pcdev->icd != icd);
1793 pcdev->frame_interval = 0;
1794 vip_ctrl_val = read_vip_reg(RK29_VIP_CTRL);
1797 hrtimer_cancel(&pcdev->fps_timer);
1798 hrtimer_start(&pcdev->fps_timer,ktime_set(1, 0),HRTIMER_MODE_REL);
1799 vip_ctrl_val |= ENABLE_CAPTURE;
1801 vip_ctrl_val &= ~ENABLE_CAPTURE;
1802 ret = hrtimer_cancel(&pcdev->fps_timer);
1803 ret |= flush_work(&rk29_camdev_info_ptr->camera_reinit_work);
1804 RK29CAMERA_DG("STREAM_OFF cancel timer and flush work:0x%x \n", ret);
1806 write_vip_reg(RK29_VIP_CTRL, vip_ctrl_val);
1808 RK29CAMERA_DG("%s.. enable : 0x%x \n", __FUNCTION__, enable);
1811 int rk29_camera_enum_frameintervals(struct soc_camera_device *icd, struct v4l2_frmivalenum *fival)
1813 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1814 struct rk29_camera_dev *pcdev = ici->priv;
1815 struct rk29_camera_frmivalenum *fival_list = NULL;
1816 struct v4l2_frmivalenum *fival_head=NULL;
1817 int i,ret = 0,index;
1819 index = fival->index & 0x00ffffff;
1820 if ((fival->index & 0xff000000) == 0xff000000) { /* ddl@rock-chips.com: detect framerate */
1821 for (i=0; i<2; i++) {
1822 if (pcdev->icd_frmival[i].icd == icd) {
1823 fival_list = pcdev->icd_frmival[i].fival_list;
1827 if (fival_list != NULL) {
1829 while (fival_list != NULL) {
1830 if ((fival->pixel_format == fival_list->fival.pixel_format)
1831 && (fival->height == fival_list->fival.height)
1832 && (fival->width == fival_list->fival.width)) {
1837 fival_list = fival_list->nxt;
1840 if ((i==index) && (fival_list != NULL)) {
1841 memcpy(fival, &fival_list->fival, sizeof(struct v4l2_frmivalenum));
1846 RK29CAMERA_TR("%s: fival_list is NULL\n",__FUNCTION__);
1851 for (i=0; i<RK29_CAM_SUPPORT_NUMS; i++) {
1852 if (pcdev->pdata->info[i].dev_name && (strcmp(dev_name(pcdev->icd->pdev),pcdev->pdata->info[i].dev_name) == 0)) {
1853 fival_head = pcdev->pdata->info[i].fival;
1857 if (fival_head == NULL) {
1858 RK29CAMERA_TR("%s: %s is not registered in rk29_camera_platform_data!!",__FUNCTION__,dev_name(pcdev->icd->pdev));
1860 goto rk29_camera_enum_frameintervals_end;
1864 while (fival_head->width && fival_head->height) {
1865 if ((fival->pixel_format == fival_head->pixel_format)
1866 && (fival->height == fival_head->height)
1867 && (fival->width == fival_head->width)) {
1876 if ((i == index) && (fival->height == fival_head->height) && (fival->width == fival_head->width)) {
1877 memcpy(fival, fival_head, sizeof(struct v4l2_frmivalenum));
1878 RK29CAMERA_DG("%s %dx%d@%c%c%c%c framerate : %d/%d\n", dev_name(rk29_camdev_info_ptr->icd->pdev),
1879 fival->width, fival->height,
1880 fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
1881 (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
1882 fival->discrete.denominator,fival->discrete.numerator);
1885 RK29CAMERA_TR("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(rk29_camdev_info_ptr->icd->pdev),
1886 fival->width,fival->height,
1887 fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
1888 (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
1891 RK29CAMERA_DG("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(rk29_camdev_info_ptr->icd->pdev),
1892 fival->width,fival->height,
1893 fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
1894 (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
1899 rk29_camera_enum_frameintervals_end:
1903 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
1904 static int rk29_camera_set_digit_zoom(struct soc_camera_device *icd,
1905 const struct v4l2_queryctrl *qctrl, int zoom_rate)
1908 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1909 struct rk29_camera_dev *pcdev = ici->priv;
1911 /* ddl@rock-chips.com : The largest resolution is 2047x1088, so larger resolution must be operated some times
1912 (Assume operate times is 4),but resolution which ipp can operate ,it is width and height must be even. */
1913 a.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1914 a.c.width = pcdev->host_width*100/zoom_rate;
1916 a.c.height = pcdev->host_height*100/zoom_rate;
1917 a.c.height &= ~0x03;
1919 a.c.left = ((pcdev->host_width - a.c.width)>>1)&(~0x01);
1920 a.c.top = ((pcdev->host_height - a.c.height)>>1)&(~0x01);
1922 down(&pcdev->zoominfo.sem);
1923 pcdev->zoominfo.a.c.height = a.c.height;
1924 pcdev->zoominfo.a.c.width = a.c.width;
1925 pcdev->zoominfo.a.c.top = a.c.top;
1926 pcdev->zoominfo.a.c.left = a.c.left;
1927 up(&pcdev->zoominfo.sem);
1929 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 );
1934 static inline struct v4l2_queryctrl const *rk29_camera_soc_camera_find_qctrl(
1935 struct soc_camera_host_ops *ops, int id)
1939 for (i = 0; i < ops->num_controls; i++)
1940 if (ops->controls[i].id == id)
1941 return &ops->controls[i];
1947 static int rk29_camera_set_ctrl(struct soc_camera_device *icd,
1948 struct v4l2_control *sctrl)
1951 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1952 const struct v4l2_queryctrl *qctrl;
1953 struct rk29_camera_dev *pcdev = ici->priv;
1956 qctrl = rk29_camera_soc_camera_find_qctrl(ici->ops, sctrl->id);
1959 goto rk29_camera_set_ctrl_end;
1964 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
1965 case V4L2_CID_ZOOM_ABSOLUTE:
1967 if ((sctrl->value < qctrl->minimum) || (sctrl->value > qctrl->maximum)){
1969 goto rk29_camera_set_ctrl_end;
1971 ret = rk29_camera_set_digit_zoom(icd, qctrl, sctrl->value);
1973 pcdev->zoominfo.zoom_rate = sctrl->value;
1975 goto rk29_camera_set_ctrl_end;
1984 rk29_camera_set_ctrl_end:
1988 static struct soc_camera_host_ops rk29_soc_camera_host_ops =
1990 .owner = THIS_MODULE,
1991 .add = rk29_camera_add_device,
1992 .remove = rk29_camera_remove_device,
1993 .suspend = rk29_camera_suspend,
1994 .resume = rk29_camera_resume,
1995 .enum_frameinervals = rk29_camera_enum_frameintervals,
1996 .set_crop = rk29_camera_set_crop,
1997 .get_formats = rk29_camera_get_formats,
1998 .put_formats = rk29_camera_put_formats,
1999 .set_fmt = rk29_camera_set_fmt,
2000 .try_fmt = rk29_camera_try_fmt,
2001 .init_videobuf = rk29_camera_init_videobuf,
2002 .reqbufs = rk29_camera_reqbufs,
2003 .poll = rk29_camera_poll,
2004 .querycap = rk29_camera_querycap,
2005 .set_bus_param = rk29_camera_set_bus_param,
2006 .s_stream = rk29_camera_s_stream, /* ddl@rock-chips.com : Add stream control for host */
2007 .set_ctrl = rk29_camera_set_ctrl,
2008 .controls = rk29_camera_controls,
2009 .num_controls = ARRAY_SIZE(rk29_camera_controls)
2012 static int rk29_camera_probe(struct platform_device *pdev)
2014 struct rk29_camera_dev *pcdev;
2015 struct resource *res;
2016 struct rk29_camera_frmivalenum *fival_list,*fival_nxt;
2020 RK29CAMERA_TR("RK29 Camera driver version: v%d.%d.%d\n",(RK29_CAM_VERSION_CODE&0xff0000)>>16,
2021 (RK29_CAM_VERSION_CODE&0xff00)>>8,RK29_CAM_VERSION_CODE&0xff);
2023 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2024 irq = platform_get_irq(pdev, 0);
2025 if (!res || irq < 0) {
2030 pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL);
2032 dev_err(&pdev->dev, "Could not allocate pcdev\n");
2036 rk29_camdev_info_ptr = pcdev;
2038 /*config output clk*/
2039 pcdev->aclk_ddr_lcdc = clk_get(&pdev->dev, "aclk_ddr_lcdc");
2040 pcdev->aclk_disp_matrix = clk_get(&pdev->dev, "aclk_disp_matrix");
2042 pcdev->hclk_cpu_display = clk_get(&pdev->dev, "hclk_cpu_display");
2043 pcdev->vip_slave = clk_get(&pdev->dev, "vip_slave");
2044 pcdev->vip_out = clk_get(&pdev->dev,"vip_out");
2045 pcdev->vip_input = clk_get(&pdev->dev,"vip_input");
2046 pcdev->vip_bus = clk_get(&pdev->dev, "vip_bus");
2048 pcdev->hclk_disp_matrix = clk_get(&pdev->dev,"hclk_disp_matrix");
2049 pcdev->vip_matrix = clk_get(&pdev->dev,"vip_matrix");
2051 pcdev->pd_display = clk_get(&pdev->dev,"pd_display");
2053 pcdev->zoominfo.zoom_rate = 100;
2055 if (!pcdev->aclk_ddr_lcdc || !pcdev->aclk_disp_matrix || !pcdev->hclk_cpu_display ||
2056 !pcdev->vip_slave || !pcdev->vip_out || !pcdev->vip_input || !pcdev->vip_bus || !pcdev->pd_display ||
2057 IS_ERR(pcdev->aclk_ddr_lcdc) || IS_ERR(pcdev->aclk_disp_matrix) || IS_ERR(pcdev->hclk_cpu_display) || IS_ERR(pcdev->pd_display) ||
2058 IS_ERR(pcdev->vip_slave) || IS_ERR(pcdev->vip_out) || IS_ERR(pcdev->vip_input) || IS_ERR(pcdev->vip_bus)) {
2060 RK29CAMERA_TR(KERN_ERR "failed to get vip_clk(axi) source\n");
2065 if (!pcdev->hclk_disp_matrix || !pcdev->vip_matrix ||
2066 IS_ERR(pcdev->hclk_disp_matrix) || IS_ERR(pcdev->vip_matrix)) {
2068 RK29CAMERA_TR(KERN_ERR "failed to get vip_clk(ahb) source\n");
2073 dev_set_drvdata(&pdev->dev, pcdev);
2076 pcdev->pdata = pdev->dev.platform_data; /* ddl@rock-chips.com : Request IO in init function */
2077 if (pcdev->pdata && pcdev->pdata->io_init) {
2078 pcdev->pdata->io_init();
2080 #ifdef CONFIG_VIDEO_RK29_WORK_IPP
2081 if (pcdev->pdata && (strcmp(pcdev->pdata->meminfo.name,"camera_ipp_mem")==0)) {
2082 pcdev->vipmem_phybase = pcdev->pdata->meminfo.start;
2083 pcdev->vipmem_size = pcdev->pdata->meminfo.size;
2084 RK29CAMERA_DG("\n%s Memory(start:0x%x size:0x%x) for IPP obtain \n",__FUNCTION__, pcdev->pdata->meminfo.start,pcdev->pdata->meminfo.size);
2086 RK29CAMERA_TR("\n%s Memory for IPP have not obtain! IPP Function is fail\n",__FUNCTION__);
2087 pcdev->vipmem_phybase = 0;
2088 pcdev->vipmem_size = 0;
2091 INIT_LIST_HEAD(&pcdev->capture);
2092 spin_lock_init(&pcdev->lock);
2093 sema_init(&pcdev->zoominfo.sem,1);
2096 * Request the regions.
2098 if (!request_mem_region(res->start, res->end - res->start + 1,
2099 RK29_CAM_DRV_NAME)) {
2104 pcdev->base = ioremap(res->start, res->end - res->start + 1);
2105 if (pcdev->base == NULL) {
2106 dev_err(pcdev->dev, "ioremap() of registers failed\n");
2112 pcdev->dev = &pdev->dev;
2114 /* config buffer address */
2116 err = request_irq(pcdev->irq, rk29_camera_irq, 0, RK29_CAM_DRV_NAME,
2119 dev_err(pcdev->dev, "Camera interrupt register failed \n");
2123 pcdev->camera_wq = create_workqueue("rk_camera_workqueue");
2124 if (pcdev->camera_wq == NULL)
2126 INIT_WORK(&pcdev->camera_reinit_work, rk29_camera_reinit_work);
2128 for (i=0; i<2; i++) {
2129 pcdev->icd_frmival[i].icd = NULL;
2130 pcdev->icd_frmival[i].fival_list = kzalloc(sizeof(struct rk29_camera_frmivalenum),GFP_KERNEL);
2134 pcdev->soc_host.drv_name = RK29_CAM_DRV_NAME;
2135 pcdev->soc_host.ops = &rk29_soc_camera_host_ops;
2136 pcdev->soc_host.priv = pcdev;
2137 pcdev->soc_host.v4l2_dev.dev = &pdev->dev;
2138 pcdev->soc_host.nr = pdev->id;
2140 err = soc_camera_host_register(&pcdev->soc_host);
2144 hrtimer_init(&pcdev->fps_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
2145 pcdev->fps_timer.function = rk29_camera_fps_func;
2146 pcdev->icd_cb.sensor_cb = NULL;
2148 RK29CAMERA_DG("%s..%s..%d \n",__FUNCTION__,__FILE__,__LINE__);
2153 for (i=0; i<2; i++) {
2154 fival_list = pcdev->icd_frmival[i].fival_list;
2155 fival_nxt = fival_list;
2156 while(fival_nxt != NULL) {
2157 fival_nxt = fival_list->nxt;
2159 fival_list = fival_nxt;
2163 free_irq(pcdev->irq, pcdev);
2164 if (pcdev->camera_wq) {
2165 destroy_workqueue(pcdev->camera_wq);
2166 pcdev->camera_wq = NULL;
2169 iounmap(pcdev->base);
2171 release_mem_region(res->start, res->end - res->start + 1);
2173 if (pcdev->aclk_ddr_lcdc) {
2174 clk_put(pcdev->aclk_ddr_lcdc);
2175 pcdev->aclk_ddr_lcdc = NULL;
2177 if (pcdev->aclk_disp_matrix) {
2178 clk_put(pcdev->aclk_disp_matrix);
2179 pcdev->aclk_disp_matrix = NULL;
2181 if (pcdev->hclk_cpu_display) {
2182 clk_put(pcdev->hclk_cpu_display);
2183 pcdev->hclk_cpu_display = NULL;
2185 if (pcdev->vip_slave) {
2186 clk_put(pcdev->vip_slave);
2187 pcdev->vip_slave = NULL;
2189 if (pcdev->vip_out) {
2190 clk_put(pcdev->vip_out);
2191 pcdev->vip_out = NULL;
2193 if (pcdev->vip_input) {
2194 clk_put(pcdev->vip_input);
2195 pcdev->vip_input = NULL;
2197 if (pcdev->vip_bus) {
2198 clk_put(pcdev->vip_bus);
2199 pcdev->vip_bus = NULL;
2201 if (pcdev->hclk_disp_matrix) {
2202 clk_put(pcdev->hclk_disp_matrix);
2203 pcdev->hclk_disp_matrix = NULL;
2205 if (pcdev->vip_matrix) {
2206 clk_put(pcdev->vip_matrix);
2207 pcdev->vip_matrix = NULL;
2211 rk29_camdev_info_ptr = NULL;
2216 static int __devexit rk29_camera_remove(struct platform_device *pdev)
2218 struct rk29_camera_dev *pcdev = platform_get_drvdata(pdev);
2219 struct resource *res;
2220 struct rk29_camera_frmivalenum *fival_list,*fival_nxt;
2223 free_irq(pcdev->irq, pcdev);
2225 if (pcdev->camera_wq) {
2226 destroy_workqueue(pcdev->camera_wq);
2227 pcdev->camera_wq = NULL;
2230 for (i=0; i<2; i++) {
2231 fival_list = pcdev->icd_frmival[i].fival_list;
2232 fival_nxt = fival_list;
2233 while(fival_nxt != NULL) {
2234 fival_nxt = fival_list->nxt;
2236 fival_list = fival_nxt;
2240 soc_camera_host_unregister(&pcdev->soc_host);
2243 release_mem_region(res->start, res->end - res->start + 1);
2245 if (pcdev->pdata && pcdev->pdata->io_deinit) { /* ddl@rock-chips.com : Free IO in deinit function */
2246 pcdev->pdata->io_deinit(0);
2247 pcdev->pdata->io_deinit(1);
2251 rk29_camdev_info_ptr = NULL;
2252 dev_info(&pdev->dev, "RK28 Camera driver unloaded\n");
2257 static struct platform_driver rk29_camera_driver =
2260 .name = RK29_CAM_DRV_NAME,
2262 .probe = rk29_camera_probe,
2263 .remove = __devexit_p(rk29_camera_remove),
2267 static int __devinit rk29_camera_init(void)
2269 RK29CAMERA_DG("%s..%s..%d \n",__FUNCTION__,__FILE__,__LINE__);
2270 return platform_driver_register(&rk29_camera_driver);
2273 static void __exit rk29_camera_exit(void)
2275 platform_driver_unregister(&rk29_camera_driver);
2278 device_initcall_sync(rk29_camera_init);
2279 module_exit(rk29_camera_exit);
2281 MODULE_DESCRIPTION("RK29 Soc Camera Host driver");
2282 MODULE_AUTHOR("ddl <ddl@rock-chips>");
2283 MODULE_LICENSE("GPL");