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 #if defined(CONFIG_ARCH_RK2928) || defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK31)
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 <linux/kthread.h>
33 #include <mach/iomux.h>
34 #include <media/v4l2-common.h>
35 #include <media/v4l2-dev.h>
36 #include <media/videobuf-dma-contig.h>
37 #include <media/soc_camera.h>
38 #include <media/soc_mediabus.h>
42 #if defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK31)
43 #include <mach/rk30_camera.h>
48 #if defined(CONFIG_ARCH_RK2928)
49 #include <mach/rk2928_camera.h>
50 #include "../../video/rockchip/rga/rga.h"
52 #include <asm/cacheflush.h>
54 module_param(debug, int, S_IRUGO|S_IWUSR);
56 #define dprintk(level, fmt, arg...) do { \
58 printk(KERN_WARNING"rk_camera: " fmt , ## arg); } while (0)
60 #define RKCAMERA_TR(format, ...) printk(KERN_ERR format, ## __VA_ARGS__)
61 #define RKCAMERA_DG(format, ...) dprintk(1, format, ## __VA_ARGS__)
64 #define CIF_CIF_CTRL 0x00
65 #define CIF_CIF_INTEN 0x04
66 #define CIF_CIF_INTSTAT 0x08
67 #define CIF_CIF_FOR 0x0c
68 #define CIF_CIF_LINE_NUM_ADDR 0x10
69 #define CIF_CIF_FRM0_ADDR_Y 0x14
70 #define CIF_CIF_FRM0_ADDR_UV 0x18
71 #define CIF_CIF_FRM1_ADDR_Y 0x1c
72 #define CIF_CIF_FRM1_ADDR_UV 0x20
73 #define CIF_CIF_VIR_LINE_WIDTH 0x24
74 #define CIF_CIF_SET_SIZE 0x28
75 #define CIF_CIF_SCM_ADDR_Y 0x2c
76 #define CIF_CIF_SCM_ADDR_U 0x30
77 #define CIF_CIF_SCM_ADDR_V 0x34
78 #define CIF_CIF_WB_UP_FILTER 0x38
79 #define CIF_CIF_WB_LOW_FILTER 0x3c
80 #define CIF_CIF_WBC_CNT 0x40
81 #define CIF_CIF_CROP 0x44
82 #define CIF_CIF_SCL_CTRL 0x48
83 #define CIF_CIF_SCL_DST 0x4c
84 #define CIF_CIF_SCL_FCT 0x50
85 #define CIF_CIF_SCL_VALID_NUM 0x54
86 #define CIF_CIF_LINE_LOOP_CTR 0x58
87 #define CIF_CIF_FRAME_STATUS 0x60
88 #define CIF_CIF_CUR_DST 0x64
89 #define CIF_CIF_LAST_LINE 0x68
90 #define CIF_CIF_LAST_PIX 0x6c
92 //The key register bit descrition
93 // CIF_CTRL Reg , ignore SCM,WBC,ISP,
94 #define DISABLE_CAPTURE (0x00<<0)
95 #define ENABLE_CAPTURE (0x01<<0)
96 #define MODE_ONEFRAME (0x00<<1)
97 #define MODE_PINGPONG (0x01<<1)
98 #define MODE_LINELOOP (0x02<<1)
99 #define AXI_BURST_16 (0x0F << 12)
102 #define FRAME_END_EN (0x01<<1)
103 #define BUS_ERR_EN (0x01<<6)
104 #define SCL_ERR_EN (0x01<<7)
107 #define VSY_HIGH_ACTIVE (0x01<<0)
108 #define VSY_LOW_ACTIVE (0x00<<0)
109 #define HSY_LOW_ACTIVE (0x01<<1)
110 #define HSY_HIGH_ACTIVE (0x00<<1)
111 #define INPUT_MODE_YUV (0x00<<2)
112 #define INPUT_MODE_PAL (0x02<<2)
113 #define INPUT_MODE_NTSC (0x03<<2)
114 #define INPUT_MODE_RAW (0x04<<2)
115 #define INPUT_MODE_JPEG (0x05<<2)
116 #define INPUT_MODE_MIPI (0x06<<2)
117 #define YUV_INPUT_ORDER_UYVY(ori) (ori & (~(0x03<<5)))
118 #define YUV_INPUT_ORDER_YVYU(ori) ((ori & (~(0x01<<6)))|(0x01<<5))
119 #define YUV_INPUT_ORDER_VYUY(ori) ((ori & (~(0x01<<5))) | (0x1<<6))
120 #define YUV_INPUT_ORDER_YUYV(ori) (ori|(0x03<<5))
121 #define YUV_INPUT_422 (0x00<<7)
122 #define YUV_INPUT_420 (0x01<<7)
123 #define INPUT_420_ORDER_EVEN (0x00<<8)
124 #define INPUT_420_ORDER_ODD (0x01<<8)
125 #define CCIR_INPUT_ORDER_ODD (0x00<<9)
126 #define CCIR_INPUT_ORDER_EVEN (0x01<<9)
127 #define RAW_DATA_WIDTH_8 (0x00<<11)
128 #define RAW_DATA_WIDTH_10 (0x01<<11)
129 #define RAW_DATA_WIDTH_12 (0x02<<11)
130 #define YUV_OUTPUT_422 (0x00<<16)
131 #define YUV_OUTPUT_420 (0x01<<16)
132 #define OUTPUT_420_ORDER_EVEN (0x00<<17)
133 #define OUTPUT_420_ORDER_ODD (0x01<<17)
134 #define RAWD_DATA_LITTLE_ENDIAN (0x00<<18)
135 #define RAWD_DATA_BIG_ENDIAN (0x01<<18)
136 #define UV_STORAGE_ORDER_UVUV (0x00<<19)
137 #define UV_STORAGE_ORDER_VUVU (0x01<<19)
140 #define ENABLE_SCL_DOWN (0x01<<0)
141 #define DISABLE_SCL_DOWN (0x00<<0)
142 #define ENABLE_SCL_UP (0x01<<1)
143 #define DISABLE_SCL_UP (0x00<<1)
144 #define ENABLE_YUV_16BIT_BYPASS (0x01<<4)
145 #define DISABLE_YUV_16BIT_BYPASS (0x00<<4)
146 #define ENABLE_RAW_16BIT_BYPASS (0x01<<5)
147 #define DISABLE_RAW_16BIT_BYPASS (0x00<<5)
148 #define ENABLE_32BIT_BYPASS (0x01<<6)
149 #define DISABLE_32BIT_BYPASS (0x00<<6)
151 #if (defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK31))
153 #define CRU_PCLK_REG30 0xbc
154 #define ENANABLE_INVERT_PCLK_CIF0 ((0x1<<24)|(0x1<<8))
155 #define DISABLE_INVERT_PCLK_CIF0 ((0x1<<24)|(0x0<<8))
156 #define ENANABLE_INVERT_PCLK_CIF1 ((0x1<<28)|(0x1<<12))
157 #define DISABLE_INVERT_PCLK_CIF1 ((0x1<<28)|(0x0<<12))
159 #define CRU_CIF_RST_REG30 0x128
160 #define MASK_RST_CIF0 (0x01 << 30)
161 #define MASK_RST_CIF1 (0x01 << 31)
162 #define RQUEST_RST_CIF0 (0x01 << 14)
163 #define RQUEST_RST_CIF1 (0x01 << 15)
166 #define MIN(x,y) ((x<y) ? x: y)
167 #define MAX(x,y) ((x>y) ? x: y)
168 #define RK_SENSOR_24MHZ 24*1000*1000 /* MHz */
169 #define RK_SENSOR_48MHZ 48
171 #define write_cif_reg(base,addr, val) __raw_writel(val, addr+(base))
172 #define read_cif_reg(base,addr) __raw_readl(addr+(base))
173 #define mask_cif_reg(addr, msk, val) write_cif_reg(addr, (val)|((~(msk))&read_cif_reg(addr)))
175 #if (defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK31))
176 #define write_cru_reg(addr, val) __raw_writel(val, addr+RK30_CRU_BASE)
177 #define read_cru_reg(addr) __raw_readl(addr+RK30_CRU_BASE)
178 #define mask_cru_reg(addr, msk, val) write_cru_reg(addr,(val)|((~(msk))&read_cru_reg(addr)))
181 #if defined(CONFIG_ARCH_RK2928)
182 #define write_cru_reg(addr, val)
183 #define read_cru_reg(addr) 0
184 #define mask_cru_reg(addr, msk, val)
188 //when work_with_ipp is not enabled,CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_OFF is not defined.something wrong with it
189 #ifdef CONFIG_VIDEO_RK29_WORK_IPP//CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_OFF
190 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_OFF
191 #define CAM_WORKQUEUE_IS_EN() ((pcdev->host_width != pcdev->icd->user_width) || (pcdev->host_height != pcdev->icd->user_height)\
192 || (pcdev->icd_cb.sensor_cb))
193 #define CAM_IPPWORK_IS_EN() ((pcdev->host_width != pcdev->icd->user_width) || (pcdev->host_height != pcdev->icd->user_height))
195 #define CAM_WORKQUEUE_IS_EN() (true)
196 #define CAM_IPPWORK_IS_EN() ((pcdev->zoominfo.a.c.width != pcdev->icd->user_width) || (pcdev->zoominfo.a.c.height != pcdev->icd->user_height))
198 #else //CONFIG_VIDEO_RK29_WORK_IPP
199 #define CAM_WORKQUEUE_IS_EN() (false)
200 #define CAM_IPPWORK_IS_EN() (false)
203 #define IS_CIF0() (pcdev->hostid == RK_CAM_PLATFORM_DEV_ID_0)
206 * Driver Version Note
208 *v0.0.x : this driver is 2.6.32 kernel driver;
209 *v0.1.x : this driver is 3.0.8 kernel driver;
211 *v0.x.1 : this driver first support rk2918;
212 *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
213 * and V4L2_PIX_FMT_YUV422P;
214 *v0.x.3 : this driver support VIDIOC_ENUM_FRAMEINTERVALS;
215 *v0.x.4 : this driver support digital zoom;
216 *v0.x.5 : this driver support test framerate and query framerate from board file configuration;
217 *v0.x.6 : this driver improve test framerate method;
218 *v0.x.7 : digital zoom use the ipp to do scale and crop , otherwise ipp just do the scale. Something wrong with digital zoom if
219 we do crop with cif and do scale with ipp , we will fix this next version.
220 *v0.x.8 : temp version,reinit capture list when setup video buf.
221 *v0.x.9 : 1. add the case of IPP unsupportted ,just cropped by CIF(not do the scale) this version.
222 2. flush workqueue when releas buffer
223 *v0.x.a: 1. reset cif and wake up vb when cif have't receive data in a fixed time(now setted as 2 secs) so that app can
225 2. when the flash is on ,flash off in a fixed time to prevent from flash light too hot.
226 3. when front and back camera are the same sensor,and one has the flash ,other is not,flash can't work corrrectly ,fix it
227 4. add menu configs for convineuent to customize sensor series
228 *v0.x.b: specify the version is NOT sure stable.
229 *v0.x.c: 1. add cif reset when resolution changed to avoid of collecting data erro
230 2. irq process is splitted to two step.
231 *v0.x.e: fix bugs of early suspend when display_pd is closed.
232 *v0.x.f: fix calculate ipp memory size is enough or not in try_fmt function;
233 *v0.x.11: fix struct rk_camera_work may be reentrant
235 #define RK_CAM_VERSION_CODE KERNEL_VERSION(0, 2, 0x11)
237 /* limit to rk29 hardware capabilities */
238 #define RK_CAM_BUS_PARAM (SOCAM_MASTER |\
239 SOCAM_HSYNC_ACTIVE_HIGH |\
240 SOCAM_HSYNC_ACTIVE_LOW |\
241 SOCAM_VSYNC_ACTIVE_HIGH |\
242 SOCAM_VSYNC_ACTIVE_LOW |\
243 SOCAM_PCLK_SAMPLE_RISING |\
244 SOCAM_PCLK_SAMPLE_FALLING|\
245 SOCAM_DATA_ACTIVE_HIGH |\
246 SOCAM_DATA_ACTIVE_LOW|\
247 SOCAM_DATAWIDTH_8|SOCAM_DATAWIDTH_10|\
248 SOCAM_MCLK_24MHZ |SOCAM_MCLK_48MHZ)
250 #define RK_CAM_W_MIN 48
251 #define RK_CAM_H_MIN 32
252 #define RK_CAM_W_MAX 3856 /* ddl@rock-chips.com : 10M Pixel */
253 #define RK_CAM_H_MAX 2764
254 #define RK_CAM_FRAME_INVAL_INIT 3
255 #define RK_CAM_FRAME_INVAL_DC 3 /* ddl@rock-chips.com : */
256 #define RK30_CAM_FRAME_MEASURE 5
258 extern void videobuf_dma_contig_free(struct videobuf_queue *q, struct videobuf_buffer *buf);
259 extern dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf);
261 /* buffer for one video frame */
262 struct rk_camera_buffer
264 /* common v4l buffer stuff -- must be first */
265 struct videobuf_buffer vb;
266 enum v4l2_mbus_pixelcode code;
269 enum rk_camera_reg_state
277 unsigned int cifCtrl;
278 unsigned int cifCrop;
280 unsigned int cifIntEn;
282 unsigned int cifVirWidth;
283 unsigned int cifScale;
284 // unsigned int VipCrm;
285 enum rk_camera_reg_state Inval;
287 struct rk_camera_work
289 struct videobuf_buffer *vb;
290 struct rk_camera_dev *pcdev;
291 struct work_struct work;
292 struct list_head queue;
295 struct rk_camera_frmivalenum
297 struct v4l2_frmivalenum fival;
298 struct rk_camera_frmivalenum *nxt;
300 struct rk_camera_frmivalinfo
302 struct soc_camera_device *icd;
303 struct rk_camera_frmivalenum *fival_list;
305 struct rk_camera_zoominfo
307 struct semaphore sem;
313 #if CAMERA_VIDEOBUF_ARM_ACCESS
314 struct rk29_camera_vbinfo
316 unsigned int phy_addr;
317 void __iomem *vir_addr;
321 struct rk_camera_timer{
322 struct rk_camera_dev *pcdev;
323 struct hrtimer timer;
328 struct soc_camera_host soc_host;
330 /* RK2827x is only supposed to handle one camera on its Quick Capture
331 * interface. If anyone ever builds hardware to enable more than
332 * one camera, they will have to modify this driver too */
333 struct soc_camera_device *icd;
335 //************must modify start************/
337 struct clk *aclk_cif;
338 struct clk *hclk_cif;
339 struct clk *cif_clk_in;
340 struct clk *cif_clk_out;
341 //************must modify end************/
343 int frame_inval; /* ddl@rock-chips.com : The first frames is invalidate */
346 unsigned int last_fps;
347 unsigned long frame_interval;
350 unsigned int vipmem_phybase;
351 void __iomem *vipmem_virbase;
352 unsigned int vipmem_size;
353 unsigned int vipmem_bsize;
354 #if CAMERA_VIDEOBUF_ARM_ACCESS
355 struct rk29_camera_vbinfo *vbinfo;
356 unsigned int vbinfo_count;
360 int host_left; //sensor output size ?
366 struct rk29camera_platform_data *pdata;
367 struct resource *res;
368 struct list_head capture;
369 struct rk_camera_zoominfo zoominfo;
373 struct videobuf_buffer *active;
374 struct rk_camera_reg reginfo_suspend;
375 struct workqueue_struct *camera_wq;
376 struct rk_camera_work *camera_work;
377 struct list_head camera_work_queue;
378 spinlock_t camera_work_lock;
379 unsigned int camera_work_count;
380 struct rk_camera_timer fps_timer;
381 struct rk_camera_work camera_reinit_work;
383 rk29_camera_sensor_cb_s icd_cb;
384 struct rk_camera_frmivalinfo icd_frmival[2];
385 // atomic_t to_process_frames;
387 unsigned int reinit_times;
388 struct videobuf_queue *video_vq;
390 struct timeval first_tv;
393 static const struct v4l2_queryctrl rk_camera_controls[] =
395 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
397 .id = V4L2_CID_ZOOM_ABSOLUTE,
398 .type = V4L2_CTRL_TYPE_INTEGER,
399 .name = "DigitalZoom Control",
403 .default_value = 100,
408 static DEFINE_MUTEX(camera_lock);
409 static const char *rk_cam_driver_description = "RK_Camera";
411 static int rk_camera_s_stream(struct soc_camera_device *icd, int enable);
412 static void rk_camera_capture_process(struct work_struct *work);
416 * Videobuf operations
418 static int rk_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
421 struct soc_camera_device *icd = vq->priv_data;
422 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
423 struct rk_camera_dev *pcdev = ici->priv;
425 struct rk_camera_work *wk;
427 struct soc_mbus_pixelfmt fmt;
429 int bytes_per_line_host;
430 fmt.packing = SOC_MBUS_PACKING_1_5X8;
432 bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
433 icd->current_fmt->host_fmt);
434 if(icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_RGB565)
435 bytes_per_line_host = soc_mbus_bytes_per_line(pcdev->host_width,
437 else if(icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_RGB24)
438 bytes_per_line_host = pcdev->host_width*3;
440 bytes_per_line_host = soc_mbus_bytes_per_line(pcdev->host_width,
441 icd->current_fmt->host_fmt);
442 printk("user code = %d,packing = %d",icd->current_fmt->code,fmt.packing);
443 dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size);
445 if (bytes_per_line_host < 0)
446 return bytes_per_line_host;
447 /* planar capture requires Y, U and V buffers to be page aligned */
448 *size = PAGE_ALIGN(bytes_per_line*icd->user_height); /* Y pages UV pages, yuv422*/
449 pcdev->vipmem_bsize = PAGE_ALIGN(bytes_per_line_host * pcdev->host_height);
450 if (CAM_WORKQUEUE_IS_EN()) {
451 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_OFF
452 if (CAM_IPPWORK_IS_EN())
455 BUG_ON(pcdev->vipmem_size<pcdev->vipmem_bsize);
456 if (*count > pcdev->vipmem_size/pcdev->vipmem_bsize) { /* Buffers must be limited, when this resolution is genered by IPP */
457 *count = pcdev->vipmem_size/pcdev->vipmem_bsize;
460 if ((pcdev->camera_work_count != *count) && pcdev->camera_work) {
461 kfree(pcdev->camera_work);
462 pcdev->camera_work = NULL;
463 pcdev->camera_work_count = 0;
466 if (pcdev->camera_work == NULL) {
467 pcdev->camera_work = wk = kzalloc(sizeof(struct rk_camera_work)*(*count), GFP_KERNEL);
468 if (pcdev->camera_work == NULL) {
469 RKCAMERA_TR("\n %s kmalloc fail\n", __FUNCTION__);
472 INIT_LIST_HEAD(&pcdev->camera_work_queue);
474 for (i=0; i<(*count); i++) {
476 list_add_tail(&wk->queue, &pcdev->camera_work_queue);
479 pcdev->camera_work_count = (*count);
481 #if CAMERA_VIDEOBUF_ARM_ACCESS
482 if (pcdev->vbinfo && (pcdev->vbinfo_count != *count)) {
483 kfree(pcdev->vbinfo);
484 pcdev->vbinfo = NULL;
485 pcdev->vbinfo_count = 0x00;
488 if (pcdev->vbinfo == NULL) {
489 pcdev->vbinfo = kzalloc(sizeof(struct rk29_camera_vbinfo)*(*count), GFP_KERNEL);
490 if (pcdev->vbinfo == NULL) {
491 RKCAMERA_TR("\n %s vbinfo kmalloc fail\n", __FUNCTION__);
494 pcdev->vbinfo_count = *count;
498 pcdev->video_vq = vq;
499 RKCAMERA_DG("%s..%d.. videobuf size:%d, vipmem_buf size:%d, count:%d \n",__FUNCTION__,__LINE__, *size,pcdev->vipmem_size, *count);
503 static void rk_videobuf_free(struct videobuf_queue *vq, struct rk_camera_buffer *buf)
505 struct soc_camera_device *icd = vq->priv_data;
507 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
508 &buf->vb, buf->vb.baddr, buf->vb.bsize);
510 /* ddl@rock-chips.com: buf_release called soc_camera_streamoff and soc_camera_close*/
511 if (buf->vb.state == VIDEOBUF_NEEDS_INIT)
517 * This waits until this buffer is out of danger, i.e., until it is no
518 * longer in STATE_QUEUED or STATE_ACTIVE
520 //videobuf_waiton(vq, &buf->vb, 0, 0);
521 videobuf_dma_contig_free(vq, &buf->vb);
522 dev_dbg(&icd->dev, "%s freed\n", __func__);
523 buf->vb.state = VIDEOBUF_NEEDS_INIT;
526 static int rk_videobuf_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, enum v4l2_field field)
528 struct soc_camera_device *icd = vq->priv_data;
529 struct rk_camera_buffer *buf;
531 int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
532 icd->current_fmt->host_fmt);
533 if (bytes_per_line < 0)
534 return bytes_per_line;
536 buf = container_of(vb, struct rk_camera_buffer, vb);
538 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
539 vb, vb->baddr, vb->bsize);
541 /* Added list head initialization on alloc */
542 WARN_ON(!list_empty(&vb->queue));
544 BUG_ON(NULL == icd->current_fmt);
546 if (buf->code != icd->current_fmt->code ||
547 vb->width != icd->user_width ||
548 vb->height != icd->user_height ||
549 vb->field != field) {
550 buf->code = icd->current_fmt->code;
551 vb->width = icd->user_width;
552 vb->height = icd->user_height;
554 vb->state = VIDEOBUF_NEEDS_INIT;
557 vb->size = bytes_per_line*vb->height; /* ddl@rock-chips.com : fmt->depth is coorect */
558 if (0 != vb->baddr && vb->bsize < vb->size) {
563 if (vb->state == VIDEOBUF_NEEDS_INIT) {
564 ret = videobuf_iolock(vq, vb, NULL);
568 vb->state = VIDEOBUF_PREPARED;
573 rk_videobuf_free(vq, buf);
578 static inline void rk_videobuf_capture(struct videobuf_buffer *vb,struct rk_camera_dev *rk_pcdev)
580 unsigned int y_addr,uv_addr;
581 struct rk_camera_dev *pcdev = rk_pcdev;
584 if (CAM_WORKQUEUE_IS_EN()) {
585 y_addr = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
586 uv_addr = y_addr + pcdev->host_width*pcdev->host_height;
587 if (y_addr > (pcdev->vipmem_phybase + pcdev->vipmem_size - pcdev->vipmem_bsize)) {
588 RKCAMERA_TR("vipmem for IPP is overflow! %dx%d -> %dx%d vb_index:%d\n",pcdev->host_width,pcdev->host_height,
589 pcdev->icd->user_width,pcdev->icd->user_height, vb->i);
594 uv_addr = y_addr + vb->width * vb->height;
596 write_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y, y_addr);
597 write_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV, uv_addr);
598 write_cif_reg(pcdev->base,CIF_CIF_FRM1_ADDR_Y, y_addr);
599 write_cif_reg(pcdev->base,CIF_CIF_FRM1_ADDR_UV, uv_addr);
600 write_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS, 0x00000002);//frame1 has been ready to receive data,frame 2 is not used
603 /* Locking: Caller holds q->irqlock */
604 static void rk_videobuf_queue(struct videobuf_queue *vq,
605 struct videobuf_buffer *vb)
607 struct soc_camera_device *icd = vq->priv_data;
608 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
609 struct rk_camera_dev *pcdev = ici->priv;
610 struct rk29_camera_vbinfo *vb_info;
612 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
613 vb, vb->baddr, vb->bsize);
615 vb->state = VIDEOBUF_QUEUED;
616 if (list_empty(&pcdev->capture)) {
617 list_add_tail(&vb->queue, &pcdev->capture);
619 if (list_entry(pcdev->capture.next, struct videobuf_buffer, queue) != vb)
620 list_add_tail(&vb->queue, &pcdev->capture);
622 BUG(); /* ddl@rock-chips.com : The same videobuffer queue again */
624 #if CAMERA_VIDEOBUF_ARM_ACCESS
626 vb_info = pcdev->vbinfo+vb->i;
627 if ((vb_info->phy_addr != vb->boff) || (vb_info->size != vb->bsize)) {
628 if (vb_info->vir_addr) {
629 iounmap(vb_info->vir_addr);
630 release_mem_region(vb_info->phy_addr, vb_info->size);
631 vb_info->vir_addr = NULL;
632 vb_info->phy_addr = 0x00;
633 vb_info->size = 0x00;
636 if (request_mem_region(vb->boff,vb->bsize,"rk_camera_vb")) {
637 vb_info->vir_addr = ioremap_cached(vb->boff,vb->bsize);
640 if (vb_info->vir_addr) {
641 vb_info->size = vb->bsize;
642 vb_info->phy_addr = vb->boff;
644 RKCAMERA_TR("%s..%d:ioremap videobuf %d failed\n",__FUNCTION__,__LINE__, vb->i);
649 if (!pcdev->active) {
651 rk_videobuf_capture(vb,pcdev);
654 static int rk_pixfmt2ippfmt(unsigned int pixfmt, int *ippfmt)
658 case V4L2_PIX_FMT_NV16:
659 case V4L2_PIX_FMT_NV61:
661 *ippfmt = IPP_Y_CBCR_H2V1;
664 case V4L2_PIX_FMT_NV12:
665 case V4L2_PIX_FMT_NV21:
667 *ippfmt = IPP_Y_CBCR_H2V2;
671 goto rk_pixfmt2ippfmt_err;
675 rk_pixfmt2ippfmt_err:
679 static int rk_pixfmt2rgafmt(unsigned int pixfmt, int *ippfmt)
683 case V4L2_PIX_FMT_YUV420:
684 case V4L2_PIX_FMT_UYVY: // yuv 422, but sensor has defined this format(in fact ,should be defined yuv 420), treat this as yuv 420.
685 case V4L2_PIX_FMT_YUYV:
687 *ippfmt = RK_FORMAT_YCbCr_420_SP;
690 case V4L2_PIX_FMT_YVU420:
691 case V4L2_PIX_FMT_VYUY:
692 case V4L2_PIX_FMT_YVYU:
694 *ippfmt = RK_FORMAT_YCrCb_420_SP;
697 case V4L2_PIX_FMT_RGB565:
699 *ippfmt = RK_FORMAT_RGB_565;
702 case V4L2_PIX_FMT_RGB24:
704 *ippfmt = RK_FORMAT_RGB_888;
708 goto rk_pixfmt2rgafmt_err;
712 rk_pixfmt2rgafmt_err:
716 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_RGA)
717 extern rga_service_info rga_service;
718 extern int rga_blit_sync(rga_session *session, struct rga_req *req);
719 extern void rga_service_session_clear(rga_session *session);
720 static int rk_camera_scale_crop_rga(struct work_struct *work){
721 struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
722 struct videobuf_buffer *vb = camera_work->vb;
723 struct rk_camera_dev *pcdev = camera_work->pcdev;
725 unsigned long int flags;
731 const struct soc_mbus_pixelfmt *fmt;
733 fmt = soc_mbus_get_fmtdesc(pcdev->icd->current_fmt->code);
734 vipdata_base = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
735 if((pcdev->icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_RGB565)
736 && (pcdev->icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_RGB24)){
737 RKCAMERA_TR("RGA not support this format !\n");
740 if ((pcdev->icd->user_width > 0x800) || (pcdev->icd->user_height > 0x800)) {
741 scale_times = MAX((pcdev->icd->user_width/0x800),(pcdev->icd->user_height/0x800));
746 session.pid = current->pid;
747 INIT_LIST_HEAD(&session.waiting);
748 INIT_LIST_HEAD(&session.running);
749 INIT_LIST_HEAD(&session.list_session);
750 init_waitqueue_head(&session.wait);
751 /* no need to protect */
752 list_add_tail(&session.list_session, &rga_service.session);
753 atomic_set(&session.task_running, 0);
754 atomic_set(&session.num_done, 0);
756 memset(&req,0,sizeof(struct rga_req));
757 req.src.act_w = pcdev->zoominfo.a.c.width/scale_times;
758 req.src.act_h = pcdev->zoominfo.a.c.height/scale_times;
760 req.src.vir_w = pcdev->zoominfo.vir_width;
761 req.src.vir_h =pcdev->zoominfo.vir_height;
762 req.src.yrgb_addr = vipdata_base;
763 req.src.uv_addr =vipdata_base + req.src.vir_w*req.src.vir_h;
764 req.src.v_addr = req.src.uv_addr ;
765 req.src.format =fmt->fourcc;
766 rk_pixfmt2rgafmt(fmt->fourcc,&req.src.format);
767 req.src.x_offset = pcdev->zoominfo.a.c.left;
768 req.src.y_offset = pcdev->zoominfo.a.c.top;
770 req.dst.act_w = pcdev->icd->user_width/scale_times;
771 req.dst.act_h = pcdev->icd->user_height/scale_times;
773 req.dst.vir_w = pcdev->icd->user_width;
774 req.dst.vir_h = pcdev->icd->user_height;
775 req.dst.x_offset = 0;
776 req.dst.y_offset = 0;
777 req.dst.yrgb_addr = vb->boff;
778 rk_pixfmt2rgafmt(pcdev->icd->current_fmt->host_fmt->fourcc,&req.dst.format);
780 req.clip.xmax = req.dst.vir_w-1;
782 req.clip.ymax = req.dst.vir_h -1;
789 req.mmu_info.mmu_en = 0;
791 for (h=0; h<scale_times; h++) {
792 for (w=0; w<scale_times; w++) {
795 req.src.yrgb_addr = vipdata_base;
796 req.src.uv_addr =vipdata_base +req.src.vir_w *req.src.vir_h ;
797 req.src.x_offset = pcdev->zoominfo.a.c.left+w*pcdev->zoominfo.a.c.width/scale_times;
798 req.src.y_offset = pcdev->zoominfo.a.c.top+h*pcdev->zoominfo.a.c.height/scale_times;
799 req.dst.x_offset = pcdev->icd->user_width*w/scale_times;
800 req.dst.y_offset = pcdev->icd->user_height*h/scale_times;
801 req.dst.yrgb_addr = vb->boff ;
802 // RKCAMERA_TR("src.act_w = %d , src.act_h = %d! vir_w = %d , vir_h = %d,off_x = %d,off_y = %d\n",req.src.act_w,req.src.act_h ,req.src.vir_w,req.src.vir_h,req.src.x_offset,req.src.y_offset);
803 // RKCAMERA_TR("dst.act_w = %d , dst.act_h = %d! vir_w = %d , vir_h = %d,off_x = %d,off_y = %d\n",req.dst.act_w,req.dst.act_h ,req.dst.vir_w,req.dst.vir_h,req.dst.x_offset,req.dst.y_offset);
804 // RKCAMERA_TR("req.src.yrgb_addr = 0x%x,req.dst.yrgb_addr = 0x%x\n",req.src.yrgb_addr,req.dst.yrgb_addr);
806 while(rga_times-- > 0) {
807 if (rga_blit_sync(&session, &req)){
808 RKCAMERA_TR("rga do erro,do again,rga_times = %d!\n",rga_times);
814 if (rga_times <= 0) {
815 spin_lock_irqsave(&pcdev->lock, flags);
816 vb->state = VIDEOBUF_NEEDS_INIT;
817 spin_unlock_irqrestore(&pcdev->lock, flags);
818 mutex_lock(&rga_service.lock);
819 list_del(&session.list_session);
820 rga_service_session_clear(&session);
821 mutex_unlock(&rga_service.lock);
827 mutex_lock(&rga_service.lock);
828 list_del(&session.list_session);
829 rga_service_session_clear(&session);
830 mutex_unlock(&rga_service.lock);
839 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP)
841 static int rk_camera_scale_crop_ipp(struct work_struct *work)
843 struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
844 struct videobuf_buffer *vb = camera_work->vb;
845 struct rk_camera_dev *pcdev = camera_work->pcdev;
847 unsigned long int flags;
849 struct rk29_ipp_req ipp_req;
850 int src_y_offset,src_uv_offset,dst_y_offset,dst_uv_offset,src_y_size,dst_y_size;
855 * IPP Dest image resolution is 2047x1088, so scale operation break up some times
857 if ((pcdev->icd->user_width > 0x7f0) || (pcdev->icd->user_height > 0x430)) {
858 scale_times = MAX((pcdev->icd->user_width/0x7f0),(pcdev->icd->user_height/0x430));
863 memset(&ipp_req, 0, sizeof(struct rk29_ipp_req));
866 ipp_req.timeout = 3000;
867 ipp_req.flag = IPP_ROT_0;
868 ipp_req.store_clip_mode =1;
869 ipp_req.src0.w = pcdev->zoominfo.a.c.width/scale_times;
870 ipp_req.src0.h = pcdev->zoominfo.a.c.height/scale_times;
871 ipp_req.src_vir_w = pcdev->zoominfo.vir_width;
872 rk_pixfmt2ippfmt(pcdev->pixfmt, &ipp_req.src0.fmt);
873 ipp_req.dst0.w = pcdev->icd->user_width/scale_times;
874 ipp_req.dst0.h = pcdev->icd->user_height/scale_times;
875 ipp_req.dst_vir_w = pcdev->icd->user_width;
876 rk_pixfmt2ippfmt(pcdev->pixfmt, &ipp_req.dst0.fmt);
877 vipdata_base = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
878 src_y_size = pcdev->host_width*pcdev->host_height; //vipmem
879 dst_y_size = pcdev->icd->user_width*pcdev->icd->user_height;
880 for (h=0; h<scale_times; h++) {
881 for (w=0; w<scale_times; w++) {
883 src_y_offset = (pcdev->zoominfo.a.c.top + h*pcdev->zoominfo.a.c.height/scale_times)* pcdev->host_width
884 + pcdev->zoominfo.a.c.left + w*pcdev->zoominfo.a.c.width/scale_times;
885 src_uv_offset = (pcdev->zoominfo.a.c.top + h*pcdev->zoominfo.a.c.height/scale_times)* pcdev->host_width/2
886 + pcdev->zoominfo.a.c.left + w*pcdev->zoominfo.a.c.width/scale_times;
888 dst_y_offset = pcdev->icd->user_width*pcdev->icd->user_height*h/scale_times + pcdev->icd->user_width*w/scale_times;
889 dst_uv_offset = pcdev->icd->user_width*pcdev->icd->user_height*h/scale_times/2 + pcdev->icd->user_width*w/scale_times;
891 ipp_req.src0.YrgbMst = vipdata_base + src_y_offset;
892 ipp_req.src0.CbrMst = vipdata_base + src_y_size + src_uv_offset;
893 ipp_req.dst0.YrgbMst = vb->boff + dst_y_offset;
894 ipp_req.dst0.CbrMst = vb->boff + dst_y_size + dst_uv_offset;
895 while(ipp_times-- > 0) {
896 if (ipp_blit_sync(&ipp_req)){
897 RKCAMERA_TR("ipp do erro,do again,ipp_times = %d!\n",ipp_times);
903 if (ipp_times <= 0) {
904 spin_lock_irqsave(&pcdev->lock, flags);
905 vb->state = VIDEOBUF_NEEDS_INIT;
906 spin_unlock_irqrestore(&pcdev->lock, flags);
907 RKCAMERA_TR("Capture image(vb->i:0x%x) which IPP operated is error:\n",vb->i);
908 RKCAMERA_TR("widx:%d hidx:%d ",w,h);
909 RKCAMERA_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);
910 RKCAMERA_TR("ipp_req.src0.YrgbMst:0x%x ipp_req.src0.CbrMst:0x%x \n", ipp_req.src0.YrgbMst,ipp_req.src0.CbrMst);
911 RKCAMERA_TR("ipp_req.src0.w:0x%x ipp_req.src0.h:0x%x \n",ipp_req.src0.w,ipp_req.src0.h);
912 RKCAMERA_TR("ipp_req.src0.fmt:0x%x\n",ipp_req.src0.fmt);
913 RKCAMERA_TR("ipp_req.dst0.YrgbMst:0x%x ipp_req.dst0.CbrMst:0x%x \n",ipp_req.dst0.YrgbMst,ipp_req.dst0.CbrMst);
914 RKCAMERA_TR("ipp_req.dst0.w:0x%x ipp_req.dst0.h:0x%x \n",ipp_req.dst0.w ,ipp_req.dst0.h);
915 RKCAMERA_TR("ipp_req.dst0.fmt:0x%x\n",ipp_req.dst0.fmt);
916 RKCAMERA_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);
917 RKCAMERA_TR("ipp_req.timeout:0x%x ipp_req.flag :0x%x\n",ipp_req.timeout,ipp_req.flag);
928 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_ARM)
929 static int rk_camera_scale_crop_arm(struct work_struct *work)
931 struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
932 struct videobuf_buffer *vb = camera_work->vb;
933 struct rk_camera_dev *pcdev = camera_work->pcdev;
934 struct rk29_camera_vbinfo *vb_info;
935 unsigned char *psY,*pdY,*psUV,*pdUV;
936 unsigned char *src,*dst;
937 unsigned long src_phy,dst_phy;
938 int srcW,srcH,cropW,cropH,dstW,dstH;
939 long zoomindstxIntInv,zoomindstyIntInv;
941 long yCoeff00,yCoeff01,xCoeff00,xCoeff01;
946 src_phy = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
947 src = psY = (unsigned char*)(pcdev->vipmem_virbase + vb->i*pcdev->vipmem_bsize);
948 psUV = psY + pcdev->host_width*pcdev->host_height;
950 srcW = pcdev->zoominfo.vir_width;
951 srcH = pcdev->zoominfo.vir_height;
952 cropW = pcdev->zoominfo.a.c.width;
953 cropH = pcdev->zoominfo.a.c.height;
955 psY = psY + (srcW-cropW);
956 psUV = psUV + (srcW-cropW);
958 vb_info = pcdev->vbinfo+vb->i;
959 dst_phy = vb_info->phy_addr;
960 dst = pdY = (unsigned char*)vb_info->vir_addr;
961 pdUV = pdY + pcdev->icd->user_width*pcdev->icd->user_height;
962 dstW = pcdev->icd->user_width;
963 dstH = pcdev->icd->user_height;
965 zoomindstxIntInv = ((unsigned long)cropW<<16)/dstW + 1;
966 zoomindstyIntInv = ((unsigned long)cropH<<16)/dstH + 1;
969 //for(y = 0; y<dstH - 1 ; y++ ) {
970 for(y = 0; y<dstH; y++ ) {
971 yCoeff00 = (y*zoomindstyIntInv)&0xffff;
972 yCoeff01 = 0xffff - yCoeff00;
973 sY = (y*zoomindstyIntInv >> 16);
975 for(x = 0; x<dstW; x++ ) {
976 xCoeff00 = (x*zoomindstxIntInv)&0xffff;
977 xCoeff01 = 0xffff - xCoeff00;
978 sX = (x*zoomindstxIntInv >> 16);
980 a = psY[sY*srcW + sX];
981 b = psY[sY*srcW + sX + 1];
982 c = psY[(sY+1)*srcW + sX];
983 d = psY[(sY+1)*srcW + sX + 1];
985 r0 = (a * xCoeff01 + b * xCoeff00)>>16 ;
986 r1 = (c * xCoeff01 + d * xCoeff00)>>16 ;
987 r0 = (r0 * yCoeff01 + r1 * yCoeff00)>>16;
1000 //for(y = 0; y<dstH - 1 ; y++ ) {
1001 for(y = 0; y<dstH; y++ ) {
1002 yCoeff00 = (y*zoomindstyIntInv)&0xffff;
1003 yCoeff01 = 0xffff - yCoeff00;
1004 sY = (y*zoomindstyIntInv >> 16);
1006 for(x = 0; x<dstW; x++ ) {
1007 xCoeff00 = (x*zoomindstxIntInv)&0xffff;
1008 xCoeff01 = 0xffff - xCoeff00;
1009 sX = (x*zoomindstxIntInv >> 16);
1012 a = psUV[(sY*srcW + sX)*2];
1013 b = psUV[(sY*srcW + sX + 1)*2];
1014 c = psUV[((sY+1)*srcW + sX)*2];
1015 d = psUV[((sY+1)*srcW + sX + 1)*2];
1017 r0 = (a * xCoeff01 + b * xCoeff00)>>16 ;
1018 r1 = (c * xCoeff01 + d * xCoeff00)>>16 ;
1019 r0 = (r0 * yCoeff01 + r1 * yCoeff00)>>16;
1024 a = psUV[(sY*srcW + sX)*2 + 1];
1025 b = psUV[(sY*srcW + sX + 1)*2 + 1];
1026 c = psUV[((sY+1)*srcW + sX)*2 + 1];
1027 d = psUV[((sY+1)*srcW + sX + 1)*2 + 1];
1029 r0 = (a * xCoeff01 + b * xCoeff00)>>16 ;
1030 r1 = (c * xCoeff01 + d * xCoeff00)>>16 ;
1031 r0 = (r0 * yCoeff01 + r1 * yCoeff00)>>16;
1038 rk_camera_scale_crop_arm_end:
1040 dmac_flush_range((void*)src,(void*)(src+pcdev->vipmem_bsize));
1041 outer_flush_range((phys_addr_t)src_phy,(phys_addr_t)(src_phy+pcdev->vipmem_bsize));
1043 dmac_flush_range((void*)dst,(void*)(dst+vb_info->size));
1044 outer_flush_range((phys_addr_t)dst_phy,(phys_addr_t)(dst_phy+vb_info->size));
1049 static void rk_camera_capture_process(struct work_struct *work)
1051 struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
1052 struct videobuf_buffer *vb = camera_work->vb;
1053 struct rk_camera_dev *pcdev = camera_work->pcdev;
1054 //enum v4l2_mbus_pixelcode icd_code = pcdev->icd->current_fmt->code;
1055 unsigned long flags = 0;
1058 if (!CAM_WORKQUEUE_IS_EN())
1059 goto rk_camera_capture_process_end;
1061 down(&pcdev->zoominfo.sem);
1062 if (pcdev->icd_cb.scale_crop_cb){
1063 err = (pcdev->icd_cb.scale_crop_cb)(work);
1065 up(&pcdev->zoominfo.sem);
1067 if (pcdev->icd_cb.sensor_cb)
1068 (pcdev->icd_cb.sensor_cb)(vb);
1070 rk_camera_capture_process_end:
1072 vb->state = VIDEOBUF_ERROR;
1074 if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) {
1075 vb->state = VIDEOBUF_DONE;
1079 wake_up(&(camera_work->vb->done));
1080 spin_lock_irqsave(&pcdev->camera_work_lock, flags);
1081 list_add_tail(&camera_work->queue, &pcdev->camera_work_queue);
1082 spin_unlock_irqrestore(&pcdev->camera_work_lock, flags);
1085 static irqreturn_t rk_camera_irq(int irq, void *data)
1087 struct rk_camera_dev *pcdev = data;
1088 struct videobuf_buffer *vb;
1089 struct rk_camera_work *wk;
1091 unsigned long tmp_intstat;
1092 unsigned long tmp_cifctrl;
1094 tmp_intstat = read_cif_reg(pcdev->base,CIF_CIF_INTSTAT);
1095 tmp_cifctrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
1096 if(pcdev->stop_cif == true)
1098 printk("cif has stopped by app,needn't to deal this irq\n");
1099 write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF); /* clear vip interrupte single */
1102 if ((tmp_intstat & 0x0200) /*&& ((tmp_intstat & 0x1)==0)*/){//bit9 =1 ,bit0 = 0
1103 write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0x0200); /* clear vip interrupte single */
1104 if(tmp_cifctrl & ENABLE_CAPTURE)
1105 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl & ~ENABLE_CAPTURE));
1109 /* ddl@rock-chps.com : Current VIP is run in One Frame Mode, Frame 1 is validate */
1110 if (read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS) & 0x01) {
1111 write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0x01); /* clear vip interrupte single */
1113 do_gettimeofday(&pcdev->first_tv);
1117 goto RK_CAMERA_IRQ_END;
1118 if (pcdev->frame_inval>0) {
1119 pcdev->frame_inval--;
1120 rk_videobuf_capture(pcdev->active,pcdev);
1121 goto RK_CAMERA_IRQ_END;
1122 } else if (pcdev->frame_inval) {
1123 RKCAMERA_TR("frame_inval : %0x",pcdev->frame_inval);
1124 pcdev->frame_inval = 0;
1126 if(pcdev->fps == RK30_CAM_FRAME_MEASURE) {
1127 do_gettimeofday(&tv);
1128 pcdev->frame_interval = ((tv.tv_sec*1000000 + tv.tv_usec) - (pcdev->first_tv.tv_sec*1000000 + pcdev->first_tv.tv_usec))
1129 /(RK30_CAM_FRAME_MEASURE-1);
1133 printk("no acticve buffer!!!\n");
1134 goto RK_CAMERA_IRQ_END;
1136 /* ddl@rock-chips.com : this vb may be deleted from queue */
1137 if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) {
1138 list_del_init(&vb->queue);
1140 pcdev->active = NULL;
1141 if (!list_empty(&pcdev->capture)) {
1142 pcdev->active = list_entry(pcdev->capture.next, struct videobuf_buffer, queue);
1143 if (pcdev->active) {
1144 WARN_ON(pcdev->active->state != VIDEOBUF_QUEUED);
1145 rk_videobuf_capture(pcdev->active,pcdev);
1148 if (pcdev->active == NULL) {
1149 RKCAMERA_DG("%s video_buf queue is empty!\n",__FUNCTION__);
1152 do_gettimeofday(&vb->ts);
1153 if (CAM_WORKQUEUE_IS_EN()) {
1154 if (!list_empty(&pcdev->camera_work_queue)) {
1155 wk = list_entry(pcdev->camera_work_queue.next, struct rk_camera_work, queue);
1156 list_del_init(&wk->queue);
1157 INIT_WORK(&(wk->work), rk_camera_capture_process);
1160 queue_work(pcdev->camera_wq, &(wk->work));
1163 if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) {
1164 vb->state = VIDEOBUF_DONE;
1173 if((tmp_cifctrl & ENABLE_CAPTURE) == 0)
1174 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl | ENABLE_CAPTURE));
1179 static void rk_videobuf_release(struct videobuf_queue *vq,
1180 struct videobuf_buffer *vb)
1182 struct rk_camera_buffer *buf = container_of(vb, struct rk_camera_buffer, vb);
1183 struct soc_camera_device *icd = vq->priv_data;
1184 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1185 struct rk_camera_dev *pcdev = ici->priv;
1186 struct rk29_camera_vbinfo *vb_info =NULL;
1188 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
1189 vb, vb->baddr, vb->bsize);
1193 case VIDEOBUF_ACTIVE:
1194 dev_dbg(&icd->dev, "%s (active)\n", __func__);
1196 case VIDEOBUF_QUEUED:
1197 dev_dbg(&icd->dev, "%s (queued)\n", __func__);
1199 case VIDEOBUF_PREPARED:
1200 dev_dbg(&icd->dev, "%s (prepared)\n", __func__);
1203 dev_dbg(&icd->dev, "%s (unknown)\n", __func__);
1207 if (vb == pcdev->active) {
1208 RKCAMERA_DG("%s Wait for this video buf(0x%x) write finished!\n ",__FUNCTION__,(unsigned int)vb);
1209 interruptible_sleep_on_timeout(&vb->done, msecs_to_jiffies(500));
1210 RKCAMERA_DG("%s This video buf(0x%x) write finished, release now!!\n",__FUNCTION__,(unsigned int)vb);
1213 flush_workqueue(pcdev->camera_wq);
1214 #if CAMERA_VIDEOBUF_ARM_ACCESS
1215 if (pcdev->vbinfo) {
1216 vb_info = pcdev->vbinfo + vb->i;
1218 if (vb_info->vir_addr) {
1219 iounmap(vb_info->vir_addr);
1220 release_mem_region(vb_info->phy_addr, vb_info->size);
1221 memset(vb_info, 0x00, sizeof(struct rk29_camera_vbinfo));
1226 rk_videobuf_free(vq, buf);
1229 static struct videobuf_queue_ops rk_videobuf_ops =
1231 .buf_setup = rk_videobuf_setup,
1232 .buf_prepare = rk_videobuf_prepare,
1233 .buf_queue = rk_videobuf_queue,
1234 .buf_release = rk_videobuf_release,
1237 static void rk_camera_init_videobuf(struct videobuf_queue *q,
1238 struct soc_camera_device *icd)
1240 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1241 struct rk_camera_dev *pcdev = ici->priv;
1243 /* We must pass NULL as dev pointer, then all pci_* dma operations
1244 * transform to normal dma_* ones. */
1245 videobuf_queue_dma_contig_init(q,
1247 ici->v4l2_dev.dev, &pcdev->lock,
1248 V4L2_BUF_TYPE_VIDEO_CAPTURE,
1250 sizeof(struct rk_camera_buffer),
1251 icd,&icd->video_lock);
1253 static int rk_camera_activate(struct rk_camera_dev *pcdev, struct soc_camera_device *icd)
1257 if(!pcdev->aclk_cif || !pcdev->hclk_cif || !pcdev->cif_clk_in || !pcdev->cif_clk_out){
1258 RKCAMERA_TR(KERN_ERR "failed to get cif clock source\n");
1260 goto RK_CAMERA_ACTIVE_ERR;
1263 clk_enable(pcdev->pd_cif);
1264 clk_enable(pcdev->aclk_cif);
1266 clk_enable(pcdev->hclk_cif);
1267 clk_enable(pcdev->cif_clk_in);
1269 //if (icd->ops->query_bus_param) /* ddl@rock-chips.com : Query Sensor's xclk */
1270 //sensor_bus_flags = icd->ops->query_bus_param(icd);
1271 clk_enable(pcdev->cif_clk_out);
1272 clk_set_rate(pcdev->cif_clk_out,RK_SENSOR_24MHZ);
1275 //soft reset the registers
1276 #if 0 //has somthing wrong when suspend and resume now
1278 printk("before set cru register reset cif0 0x%x\n\n",read_cru_reg(CRU_CIF_RST_REG30));
1281 printk("CIF_CIF_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CTRL));
1282 printk("CIF_CIF_INTEN = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTEN));
1283 printk("CIF_CIF_INTSTAT = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTSTAT));
1284 printk("CIF_CIF_FOR = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_FOR));
1285 printk("CIF_CIF_CROP = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CROP));
1286 printk("CIF_CIF_SET_SIZE = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE));
1287 printk("CIF_CIF_SCL_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL));
1288 printk("CRU_PCLK_REG30 = 0X%x\n",read_cru_reg(CRU_PCLK_REG30));
1289 printk("CIF_CIF_LAST_LINE = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_LINE));
1291 printk("CIF_CIF_LAST_PIX = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_PIX));
1292 printk("CIF_CIF_VIR_LINE_WIDTH = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH));
1293 printk("CIF_CIF_LINE_NUM_ADDR = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LINE_NUM_ADDR));
1294 printk("CIF_CIF_FRM0_ADDR_Y = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y));
1295 printk("CIF_CIF_FRM0_ADDR_UV = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV));
1296 printk("CIF_CIF_FRAME_STATUS = 0X%x\n\n",read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS));
1300 write_cru_reg(CRU_CIF_RST_REG30,(/*read_cru_reg(CRU_CIF_RST_REG30)|*/MASK_RST_CIF0|RQUEST_RST_CIF0 ));
1301 printk("set cru register reset cif0 0x%x\n",read_cru_reg(CRU_CIF_RST_REG30));
1302 write_cru_reg(CRU_CIF_RST_REG30,(read_cru_reg(CRU_CIF_RST_REG30)&(~RQUEST_RST_CIF0)) | MASK_RST_CIF0);
1304 printk("clean cru register reset cif0 0x%x\n",read_cru_reg(CRU_CIF_RST_REG30));
1306 write_cru_reg(CRU_CIF_RST_REG30,MASK_RST_CIF1|RQUEST_RST_CIF1 | (read_cru_reg(CRU_CIF_RST_REG30)));
1307 write_cru_reg(CRU_CIF_RST_REG30,(read_cru_reg(CRU_CIF_RST_REG30)&(~RQUEST_RST_CIF1)) | MASK_RST_CIF1);
1310 write_cif_reg(pcdev->base,CIF_CIF_CTRL,AXI_BURST_16|MODE_ONEFRAME|DISABLE_CAPTURE); /* ddl@rock-chips.com : vip ahb burst 16 */
1311 write_cif_reg(pcdev->base,CIF_CIF_INTEN, 0x01); //capture complete interrupt enable
1312 RKCAMERA_DG("%s..%d.. CIF_CIF_CTRL = 0x%x\n",__FUNCTION__,__LINE__,read_cif_reg(pcdev->base, CIF_CIF_CTRL));
1314 RK_CAMERA_ACTIVE_ERR:
1318 static void rk_camera_deactivate(struct rk_camera_dev *pcdev)
1320 clk_disable(pcdev->aclk_cif);
1322 clk_disable(pcdev->hclk_cif);
1323 clk_disable(pcdev->cif_clk_in);
1324 clk_disable(pcdev->cif_clk_out);
1325 clk_enable(pcdev->cif_clk_out);
1326 clk_set_rate(pcdev->cif_clk_out,48*1000*1000);
1327 clk_disable(pcdev->cif_clk_out);
1329 clk_disable(pcdev->pd_cif);
1333 /* The following two functions absolutely depend on the fact, that
1334 * there can be only one camera on RK28 quick capture interface */
1335 static int rk_camera_add_device(struct soc_camera_device *icd)
1337 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1338 struct rk_camera_dev *pcdev = ici->priv;
1339 struct device *control = to_soc_camera_control(icd);
1340 struct v4l2_subdev *sd;
1341 int ret,i,icd_catch;
1342 struct rk_camera_frmivalenum *fival_list,*fival_nxt;
1344 mutex_lock(&camera_lock);
1351 dev_info(&icd->dev, "RK Camera driver attached to camera%d(%s)\n",
1352 icd->devnum,dev_name(icd->pdev));
1354 pcdev->frame_inval = RK_CAM_FRAME_INVAL_INIT;
1355 pcdev->active = NULL;
1357 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
1358 pcdev->zoominfo.zoom_rate = 100;
1359 pcdev->fps_timer.istarted = false;
1361 /* ddl@rock-chips.com: capture list must be reset, because this list may be not empty,
1362 * if app havn't dequeue all videobuf before close camera device;
1364 INIT_LIST_HEAD(&pcdev->capture);
1366 ret = rk_camera_activate(pcdev,icd);
1369 /* ddl@rock-chips.com : v4l2_subdev is not created when ici->ops->add called in soc_camera_probe */
1371 sd = dev_get_drvdata(control);
1372 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_IOREQUEST,(void*)pcdev->pdata);
1374 ret = v4l2_subdev_call(sd,core, init, 0);
1378 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_CB_REGISTER,(void*)(&pcdev->icd_cb));
1381 pcdev->icd_init = 0;
1384 for (i=0; i<2; i++) {
1385 if (pcdev->icd_frmival[i].icd == icd)
1387 if (pcdev->icd_frmival[i].icd == NULL) {
1388 pcdev->icd_frmival[i].icd = icd;
1392 if (icd_catch == 0) {
1393 fival_list = pcdev->icd_frmival[0].fival_list;
1394 fival_nxt = fival_list;
1395 while(fival_nxt != NULL) {
1396 fival_nxt = fival_list->nxt;
1398 fival_list = fival_nxt;
1400 pcdev->icd_frmival[0].icd = icd;
1401 pcdev->icd_frmival[0].fival_list = kzalloc(sizeof(struct rk_camera_frmivalenum),GFP_KERNEL);
1404 mutex_unlock(&camera_lock);
1408 static void rk_camera_remove_device(struct soc_camera_device *icd)
1410 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1411 struct rk_camera_dev *pcdev = ici->priv;
1412 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1413 struct rk29_camera_vbinfo *vb_info;
1416 mutex_lock(&camera_lock);
1417 BUG_ON(icd != pcdev->icd);
1419 dev_info(&icd->dev, "RK Camera driver detached from camera%d(%s)\n",
1420 icd->devnum,dev_name(icd->pdev));
1422 /* ddl@rock-chips.com: Application will call VIDIOC_STREAMOFF before close device, but
1423 stream may be turn on again before close device, if suspend and resume happened. */
1424 if (read_cif_reg(pcdev->base,CIF_CIF_CTRL) & ENABLE_CAPTURE) {
1425 rk_camera_s_stream(icd,0);
1428 //soft reset the registers
1429 #if 0 //has somthing wrong when suspend and resume now
1431 write_cru_reg(CRU_CIF_RST_REG30,MASK_RST_CIF0|RQUEST_RST_CIF0 | (read_cru_reg(CRU_CIF_RST_REG30)));
1432 write_cru_reg(CRU_CIF_RST_REG30,(read_cru_reg(CRU_CIF_RST_REG30)&(~RQUEST_RST_CIF0)) | MASK_RST_CIF0);
1434 write_cru_reg(CRU_CIF_RST_REG30,MASK_RST_CIF1|RQUEST_RST_CIF1 | (read_cru_reg(CRU_CIF_RST_REG30)));
1435 write_cru_reg(CRU_CIF_RST_REG30,(read_cru_reg(CRU_CIF_RST_REG30)&(~RQUEST_RST_CIF1)) | MASK_RST_CIF1);
1438 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_DEACTIVATE,NULL);
1439 //if stream off is not been executed,timer is running.
1440 if(pcdev->fps_timer.istarted){
1441 hrtimer_cancel(&pcdev->fps_timer.timer);
1442 pcdev->fps_timer.istarted = false;
1444 flush_work(&(pcdev->camera_reinit_work.work));
1445 flush_workqueue((pcdev->camera_wq));
1447 if (pcdev->camera_work) {
1448 kfree(pcdev->camera_work);
1449 pcdev->camera_work = NULL;
1450 pcdev->camera_work_count = 0;
1451 INIT_LIST_HEAD(&pcdev->camera_work_queue);
1453 rk_camera_deactivate(pcdev);
1454 #if CAMERA_VIDEOBUF_ARM_ACCESS
1455 if (pcdev->vbinfo) {
1456 vb_info = pcdev->vbinfo;
1457 for (i=0; i<pcdev->vbinfo_count; i++) {
1458 if (vb_info->vir_addr) {
1459 iounmap(vb_info->vir_addr);
1460 release_mem_region(vb_info->phy_addr, vb_info->size);
1461 memset(vb_info, 0x00, sizeof(struct rk29_camera_vbinfo));
1465 kfree(pcdev->vbinfo);
1466 pcdev->vbinfo = NULL;
1467 pcdev->vbinfo_count = 0;
1470 pcdev->active = NULL;
1472 pcdev->icd_cb.sensor_cb = NULL;
1473 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
1474 /* ddl@rock-chips.com: capture list must be reset, because this list may be not empty,
1475 * if app havn't dequeue all videobuf before close camera device;
1477 INIT_LIST_HEAD(&pcdev->capture);
1479 mutex_unlock(&camera_lock);
1480 RKCAMERA_DG("%s exit\n",__FUNCTION__);
1484 static int rk_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
1486 unsigned long bus_flags, camera_flags, common_flags;
1487 unsigned int cif_ctrl_val = 0;
1488 const struct soc_mbus_pixelfmt *fmt;
1490 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1491 struct rk_camera_dev *pcdev = ici->priv;
1492 RKCAMERA_DG("%s..%d..\n",__FUNCTION__,__LINE__);
1494 fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code);
1498 bus_flags = RK_CAM_BUS_PARAM;
1499 /* If requested data width is supported by the platform, use it */
1500 switch (fmt->bits_per_sample) {
1502 if (!(bus_flags & SOCAM_DATAWIDTH_10))
1506 if (!(bus_flags & SOCAM_DATAWIDTH_9))
1510 if (!(bus_flags & SOCAM_DATAWIDTH_8))
1517 if (icd->ops->query_bus_param)
1518 camera_flags = icd->ops->query_bus_param(icd);
1522 common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
1523 if (!common_flags) {
1525 goto RK_CAMERA_SET_BUS_PARAM_END;
1528 ret = icd->ops->set_bus_param(icd, common_flags);
1530 goto RK_CAMERA_SET_BUS_PARAM_END;
1532 cif_ctrl_val = read_cif_reg(pcdev->base,CIF_CIF_FOR);
1533 RKCAMERA_DG("%s..%d..cif_ctrl_val = 0x%x\n",__FUNCTION__,__LINE__,cif_ctrl_val);
1534 if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) {
1536 write_cru_reg(CRU_PCLK_REG30, read_cru_reg(CRU_PCLK_REG30) | ENANABLE_INVERT_PCLK_CIF0);
1537 RKCAMERA_DG("enable cif0 pclk invert\n");
1539 write_cru_reg(CRU_PCLK_REG30, read_cru_reg(CRU_PCLK_REG30) | ENANABLE_INVERT_PCLK_CIF1);
1540 RKCAMERA_DG("enable cif1 pclk invert\n");
1544 write_cru_reg(CRU_PCLK_REG30, (read_cru_reg(CRU_PCLK_REG30) & 0xFFFFEFF ) | DISABLE_INVERT_PCLK_CIF0);
1545 RKCAMERA_DG("diable cif0 pclk invert\n");
1547 write_cru_reg(CRU_PCLK_REG30, (read_cru_reg(CRU_PCLK_REG30) & 0xFFFEFFF) | DISABLE_INVERT_PCLK_CIF1);
1548 RKCAMERA_DG("diable cif1 pclk invert\n");
1551 if (common_flags & SOCAM_HSYNC_ACTIVE_LOW) {
1552 cif_ctrl_val |= HSY_LOW_ACTIVE;
1554 cif_ctrl_val &= ~HSY_LOW_ACTIVE;
1556 if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH) {
1557 cif_ctrl_val |= VSY_HIGH_ACTIVE;
1559 cif_ctrl_val &= ~VSY_HIGH_ACTIVE;
1562 /* ddl@rock-chips.com : Don't enable capture here, enable in stream_on */
1563 //vip_ctrl_val |= ENABLE_CAPTURE;
1564 write_cif_reg(pcdev->base,CIF_CIF_FOR, cif_ctrl_val);
1565 RKCAMERA_DG("%s..ctrl:0x%x CIF_CIF_FOR=%x \n",__FUNCTION__,cif_ctrl_val,read_cif_reg(pcdev->base,CIF_CIF_FOR));
1567 RK_CAMERA_SET_BUS_PARAM_END:
1569 RKCAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
1573 static int rk_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
1575 unsigned long bus_flags, camera_flags;
1578 bus_flags = RK_CAM_BUS_PARAM;
1579 if (icd->ops->query_bus_param) {
1580 camera_flags = icd->ops->query_bus_param(icd);
1584 ret = soc_camera_bus_param_compatible(camera_flags, bus_flags) ;
1587 dev_warn(icd->dev.parent,
1588 "Flags incompatible: camera %lx, host %lx\n",
1589 camera_flags, bus_flags);
1593 static const struct soc_mbus_pixelfmt rk_camera_formats[] = {
1595 .fourcc = V4L2_PIX_FMT_NV12,
1596 .name = "YUV420 NV12",
1597 .bits_per_sample = 8,
1598 .packing = SOC_MBUS_PACKING_1_5X8,
1599 .order = SOC_MBUS_ORDER_LE,
1601 .fourcc = V4L2_PIX_FMT_NV16,
1602 .name = "YUV422 NV16",
1603 .bits_per_sample = 8,
1604 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1605 .order = SOC_MBUS_ORDER_LE,
1607 .fourcc = V4L2_PIX_FMT_NV21,
1608 .name = "YUV420 NV21",
1609 .bits_per_sample = 8,
1610 .packing = SOC_MBUS_PACKING_1_5X8,
1611 .order = SOC_MBUS_ORDER_LE,
1613 .fourcc = V4L2_PIX_FMT_NV61,
1614 .name = "YUV422 NV61",
1615 .bits_per_sample = 8,
1616 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1617 .order = SOC_MBUS_ORDER_LE,
1619 .fourcc = V4L2_PIX_FMT_RGB565,
1621 .bits_per_sample = 8,
1622 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1623 .order = SOC_MBUS_ORDER_LE,
1625 .fourcc = V4L2_PIX_FMT_RGB24,
1627 .bits_per_sample = 8,
1628 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1629 .order = SOC_MBUS_ORDER_LE,
1633 static void rk_camera_setup_format(struct soc_camera_device *icd, __u32 host_pixfmt, enum v4l2_mbus_pixelcode icd_code, struct v4l2_rect *rect)
1635 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1636 struct rk_camera_dev *pcdev = ici->priv;
1637 unsigned int cif_fs = 0,cif_crop = 0;
1638 unsigned int cif_fmt_val = read_cif_reg(pcdev->base,CIF_CIF_FOR) | INPUT_MODE_YUV|YUV_INPUT_422|INPUT_420_ORDER_EVEN|OUTPUT_420_ORDER_EVEN;
1640 const struct soc_mbus_pixelfmt *fmt;
1641 fmt = soc_mbus_get_fmtdesc(icd_code);
1643 if((host_pixfmt == V4L2_PIX_FMT_RGB565) || (host_pixfmt == V4L2_PIX_FMT_RGB24)){
1644 if(fmt->fourcc == V4L2_PIX_FMT_NV12)
1645 host_pixfmt = V4L2_PIX_FMT_NV12;
1646 else if(fmt->fourcc == V4L2_PIX_FMT_NV21)
1647 host_pixfmt = V4L2_PIX_FMT_NV21;
1649 switch (host_pixfmt)
1651 case V4L2_PIX_FMT_NV16:
1652 cif_fmt_val &= ~YUV_OUTPUT_422;
1653 cif_fmt_val &= ~UV_STORAGE_ORDER_UVUV;
1654 pcdev->frame_inval = RK_CAM_FRAME_INVAL_DC;
1655 pcdev->pixfmt = host_pixfmt;
1657 case V4L2_PIX_FMT_NV61:
1658 cif_fmt_val &= ~YUV_OUTPUT_422;
1659 cif_fmt_val |= UV_STORAGE_ORDER_VUVU;
1660 pcdev->frame_inval = RK_CAM_FRAME_INVAL_DC;
1661 pcdev->pixfmt = host_pixfmt;
1663 case V4L2_PIX_FMT_NV12:
1664 cif_fmt_val |= YUV_OUTPUT_420;
1665 cif_fmt_val &= ~UV_STORAGE_ORDER_UVUV;
1666 if (pcdev->frame_inval != RK_CAM_FRAME_INVAL_INIT)
1667 pcdev->frame_inval = RK_CAM_FRAME_INVAL_INIT;
1668 pcdev->pixfmt = host_pixfmt;
1670 case V4L2_PIX_FMT_NV21:
1671 cif_fmt_val |= YUV_OUTPUT_420;
1672 cif_fmt_val |= UV_STORAGE_ORDER_VUVU;
1673 if (pcdev->frame_inval != RK_CAM_FRAME_INVAL_INIT)
1674 pcdev->frame_inval = RK_CAM_FRAME_INVAL_INIT;
1675 pcdev->pixfmt = host_pixfmt;
1677 default: /* ddl@rock-chips.com : vip output format is hold when pixfmt is invalidate */
1678 cif_fmt_val |= YUV_OUTPUT_422;
1683 case V4L2_MBUS_FMT_UYVY8_2X8:
1684 cif_fmt_val = YUV_INPUT_ORDER_UYVY(cif_fmt_val);
1686 case V4L2_MBUS_FMT_YUYV8_2X8:
1687 cif_fmt_val = YUV_INPUT_ORDER_YUYV(cif_fmt_val);
1689 case V4L2_MBUS_FMT_YVYU8_2X8:
1690 cif_fmt_val = YUV_INPUT_ORDER_YVYU(cif_fmt_val);
1692 case V4L2_MBUS_FMT_VYUY8_2X8:
1693 cif_fmt_val = YUV_INPUT_ORDER_VYUY(cif_fmt_val);
1696 cif_fmt_val = YUV_INPUT_ORDER_YUYV(cif_fmt_val);
1701 #ifdef CONFIG_ARCH_RK30
1704 // pmu_set_idle_request(IDLE_REQ_VIO, true);
1705 cru_set_soft_reset(SOFT_RST_CIF0, true);
1707 cru_set_soft_reset(SOFT_RST_CIF0, false);
1708 // pmu_set_idle_request(IDLE_REQ_VIO, false);
1711 // pmu_set_idle_request(IDLE_REQ_VIO, true);
1712 cru_set_soft_reset(SOFT_RST_CIF1, true);
1714 cru_set_soft_reset(SOFT_RST_CIF1, false);
1715 // pmu_set_idle_request(IDLE_REQ_VIO, false);
1719 write_cif_reg(pcdev->base,CIF_CIF_CTRL,AXI_BURST_16|MODE_ONEFRAME|DISABLE_CAPTURE); /* ddl@rock-chips.com : vip ahb burst 16 */
1720 write_cif_reg(pcdev->base,CIF_CIF_INTEN, 0x01|0x200); //capture complete interrupt enable
1722 write_cif_reg(pcdev->base,CIF_CIF_FOR,cif_fmt_val); /* ddl@rock-chips.com: VIP capture mode and capture format must be set before FS register set */
1724 // read_cif_reg(pcdev->base,CIF_CIF_INTSTAT); /* clear vip interrupte single */
1725 write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF);
1726 if((read_cif_reg(pcdev->base,CIF_CIF_CTRL) & MODE_PINGPONG)
1727 ||(read_cif_reg(pcdev->base,CIF_CIF_CTRL) & MODE_LINELOOP)) {
1729 } else{ // this is one frame mode
1730 cif_crop = (rect->left+ (rect->top<<16));
1731 cif_fs = ((rect->width ) + (rect->height<<16));
1733 RKCAMERA_TR("%s..%d.. \n",__FUNCTION__,__LINE__);
1735 write_cif_reg(pcdev->base,CIF_CIF_CROP, cif_crop);
1736 write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, cif_fs);
1737 write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH, rect->width);
1738 write_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS, 0x00000003);
1740 write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL,0x10);
1741 RKCAMERA_DG("%s.. crop:0x%x fs:0x%x cif_fmt_val:0x%x CIF_CIF_FOR:0x%x\n",__FUNCTION__,cif_crop,cif_fs,cif_fmt_val,read_cif_reg(pcdev->base,CIF_CIF_FOR));
1745 static int rk_camera_get_formats(struct soc_camera_device *icd, unsigned int idx,
1746 struct soc_camera_format_xlate *xlate)
1748 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1749 struct device *dev = icd->dev.parent;
1750 int formats = 0, ret;
1751 enum v4l2_mbus_pixelcode code;
1752 const struct soc_mbus_pixelfmt *fmt;
1754 ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
1756 /* No more formats */
1759 fmt = soc_mbus_get_fmtdesc(code);
1761 dev_err(dev, "Invalid format code #%u: %d\n", idx, code);
1765 ret = rk_camera_try_bus_param(icd, fmt->bits_per_sample);
1770 case V4L2_MBUS_FMT_UYVY8_2X8:
1771 case V4L2_MBUS_FMT_YUYV8_2X8:
1772 case V4L2_MBUS_FMT_YVYU8_2X8:
1773 case V4L2_MBUS_FMT_VYUY8_2X8:
1776 xlate->host_fmt = &rk_camera_formats[0];
1779 dev_dbg(dev, "Providing format %s using code %d\n",
1780 rk_camera_formats[0].name,code);
1785 xlate->host_fmt = &rk_camera_formats[1];
1788 dev_dbg(dev, "Providing format %s using code %d\n",
1789 rk_camera_formats[1].name,code);
1794 xlate->host_fmt = &rk_camera_formats[2];
1797 dev_dbg(dev, "Providing format %s using code %d\n",
1798 rk_camera_formats[2].name,code);
1803 xlate->host_fmt = &rk_camera_formats[3];
1806 dev_dbg(dev, "Providing format %s using code %d\n",
1807 rk_camera_formats[3].name,code);
1811 xlate->host_fmt = &rk_camera_formats[4];
1814 dev_dbg(dev, "Providing format %s using code %d\n",
1815 rk_camera_formats[4].name,code);
1819 xlate->host_fmt = &rk_camera_formats[5];
1822 dev_dbg(dev, "Providing format %s using code %d\n",
1823 rk_camera_formats[5].name,code);
1833 static void rk_camera_put_formats(struct soc_camera_device *icd)
1838 static int rk_camera_set_crop(struct soc_camera_device *icd,
1839 struct v4l2_crop *a)
1841 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1842 struct v4l2_mbus_framefmt mf;
1843 u32 fourcc = icd->current_fmt->host_fmt->fourcc;
1846 ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
1850 if ((mf.width < (a->c.left + a->c.width)) || (mf.height < (a->c.top + a->c.height))) {
1852 mf.width = a->c.left + a->c.width;
1853 mf.height = a->c.top + a->c.height;
1855 v4l_bound_align_image(&mf.width, RK_CAM_W_MIN, RK_CAM_W_MAX, 1,
1856 &mf.height, RK_CAM_H_MIN, RK_CAM_H_MAX, 0,
1857 fourcc == V4L2_PIX_FMT_NV16 ?4 : 0);
1859 ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
1864 rk_camera_setup_format(icd, fourcc, mf.code, &a->c);
1866 icd->user_width = mf.width;
1867 icd->user_height = mf.height;
1872 static int rk_camera_set_fmt(struct soc_camera_device *icd,
1873 struct v4l2_format *f)
1875 struct device *dev = icd->dev.parent;
1876 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1877 const struct soc_camera_format_xlate *xlate = NULL;
1878 struct soc_camera_host *ici =to_soc_camera_host(icd->dev.parent);
1879 struct rk_camera_dev *pcdev = ici->priv;
1880 struct v4l2_pix_format *pix = &f->fmt.pix;
1881 struct v4l2_mbus_framefmt mf;
1882 struct v4l2_rect rect;
1883 int ret,usr_w,usr_h;
1887 usr_h = pix->height;
1888 RKCAMERA_TR("%s enter width:%d height:%d\n",__FUNCTION__,usr_w,usr_h);
1889 xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
1891 dev_err(dev, "Format %x not found\n", pix->pixelformat);
1893 goto RK_CAMERA_SET_FMT_END;
1896 /* ddl@rock-chips.com: sensor init code transmit in here after open */
1897 if (pcdev->icd_init == 0) {
1898 v4l2_subdev_call(sd,core, init, 0);
1899 pcdev->icd_init = 1;
1901 stream_on = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
1902 if (stream_on & ENABLE_CAPTURE)
1903 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (stream_on & (~ENABLE_CAPTURE)));
1905 mf.width = pix->width;
1906 mf.height = pix->height;
1907 mf.field = pix->field;
1908 mf.colorspace = pix->colorspace;
1909 mf.code = xlate->code;
1910 ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
1911 if (mf.code != xlate->code)
1913 #ifdef CONFIG_VIDEO_RK29_WORK_IPP
1914 if ((mf.width != usr_w) || (mf.height != usr_h)) {
1916 if (unlikely((mf.width <16) || (mf.width > 8190) || (mf.height < 16) || (mf.height > 8190))) {
1917 RKCAMERA_TR("Senor and IPP both invalid source resolution(%dx%d)\n",mf.width,mf.height);
1919 goto RK_CAMERA_SET_FMT_END;
1921 if (unlikely((usr_w <16)||(usr_h < 16))) {
1922 RKCAMERA_TR("Senor and IPP both invalid destination resolution(%dx%d)\n",usr_w,usr_h);
1924 goto RK_CAMERA_SET_FMT_END;
1927 if((mf.width*10/mf.height) != (usr_w*10/usr_h)){
1928 ratio = ((mf.width*10/usr_w) >= (mf.height*10/usr_h))?(mf.height*10/usr_h):(mf.width*10/usr_w);
1929 pcdev->host_width = ratio*usr_w/10;
1930 pcdev->host_height = ratio*usr_h/10;
1931 //for ipp ,need 4 bit alligned.
1932 pcdev->host_width &= ~0x03;
1933 pcdev->host_height &= ~0x03;
1934 RKCAMERA_DG("ratio = %d ,host:%d*%d\n",ratio,pcdev->host_width,pcdev->host_height);
1936 else{ // needn't crop ,just scaled by ipp
1937 pcdev->host_width = mf.width;
1938 pcdev->host_height = mf.height;
1942 pcdev->host_width = usr_w;
1943 pcdev->host_height = usr_h;
1946 //according to crop and scale capability to change , here just cropt to user needed
1947 if (unlikely((mf.width <16) || (mf.width > 8190) || (mf.height < 16) || (mf.height > 8190))) {
1948 RKCAMERA_TR("Senor invalid source resolution(%dx%d)\n",mf.width,mf.height);
1950 goto RK_CAMERA_SET_FMT_END;
1952 if (unlikely((usr_w <16)||(usr_h < 16))) {
1953 RKCAMERA_TR("Senor invalid destination resolution(%dx%d)\n",usr_w,usr_h);
1955 goto RK_CAMERA_SET_FMT_END;
1957 pcdev->host_width = usr_w;
1958 pcdev->host_height = usr_h;
1962 RKCAMERA_DG("%s..%d.. host:%d*%d , sensor output:%d*%d,user demand:%d*%d\n",__FUNCTION__,__LINE__,
1963 pcdev->host_width,pcdev->host_height,mf.width,mf.height,usr_w,usr_h);
1964 rect.width = pcdev->host_width;
1965 rect.height = pcdev->host_height;
1966 rect.left = ((mf.width-pcdev->host_width )>>1)&(~0x01);
1967 rect.top = ((mf.height-pcdev->host_height)>>1)&(~0x01);
1968 pcdev->host_left = rect.left;
1969 pcdev->host_top = rect.top;
1971 down(&pcdev->zoominfo.sem);
1972 pcdev->zoominfo.a.c.width = pcdev->host_width*100/pcdev->zoominfo.zoom_rate;
1973 pcdev->zoominfo.a.c.width &= ~0x03;
1974 pcdev->zoominfo.a.c.height = pcdev->host_height*100/pcdev->zoominfo.zoom_rate;
1975 pcdev->zoominfo.a.c.height &= ~0x03;
1976 //now digital zoom use ipp to do crop and scale
1977 if(pcdev->zoominfo.zoom_rate != 100){
1978 pcdev->zoominfo.a.c.left = ((pcdev->host_width - pcdev->zoominfo.a.c.width)>>1)&(~0x01);
1979 pcdev->zoominfo.a.c.top = ((pcdev->host_height - pcdev->zoominfo.a.c.height)>>1)&(~0x01);
1982 pcdev->zoominfo.a.c.left = 0;
1983 pcdev->zoominfo.a.c.top = 0;
1985 pcdev->zoominfo.vir_width = pcdev->host_width;
1986 pcdev->zoominfo.vir_height = pcdev->host_height;
1987 up(&pcdev->zoominfo.sem);
1989 /* ddl@rock-chips.com: IPP work limit check */
1990 if ((pcdev->zoominfo.a.c.width != usr_w) || (pcdev->zoominfo.a.c.height != usr_h)) {
1991 if (usr_w > 0x7f0) {
1992 if (((usr_w>>1)&0x3f) && (((usr_w>>1)&0x3f) <= 8)) {
1993 RKCAMERA_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));
1995 goto RK_CAMERA_SET_FMT_END;
1998 if ((usr_w&0x3f) && ((usr_w&0x3f) <= 8)) {
1999 RKCAMERA_TR("IPP Destination resolution(%dx%d, %d mod 64=%d is <= 8)",usr_w,usr_h, usr_w, (int)(usr_w&0x3f));
2001 goto RK_CAMERA_SET_FMT_END;
2005 RKCAMERA_DG("%s..%s icd width:%d user width:%d (zoom: %dx%d@(%d,%d)->%dx%d)\n",__FUNCTION__,xlate->host_fmt->name,
2006 rect.width, pix->width, pcdev->zoominfo.a.c.width,pcdev->zoominfo.a.c.height, pcdev->zoominfo.a.c.left,pcdev->zoominfo.a.c.top,
2007 pix->width, pix->height);
2008 rk_camera_setup_format(icd, pix->pixelformat, mf.code, &rect);
2010 if (CAM_IPPWORK_IS_EN()) {
2011 BUG_ON(pcdev->vipmem_phybase == 0);
2014 pix->height = usr_h;
2015 pix->field = mf.field;
2016 pix->colorspace = mf.colorspace;
2017 icd->current_fmt = xlate;
2018 pcdev->icd_width = mf.width;
2019 pcdev->icd_height = mf.height;
2022 RK_CAMERA_SET_FMT_END:
2023 if (stream_on & ENABLE_CAPTURE)
2024 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL) | ENABLE_CAPTURE));
2026 RKCAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
2029 static bool rk_camera_fmt_capturechk(struct v4l2_format *f)
2033 if ((f->fmt.pix.width == 1024) && (f->fmt.pix.height == 768)) {
2035 } else if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 1024)) {
2037 } else if ((f->fmt.pix.width == 1600) && (f->fmt.pix.height == 1200)) {
2039 } else if ((f->fmt.pix.width == 2048) && (f->fmt.pix.height == 1536)) {
2041 } else if ((f->fmt.pix.width == 2592) && (f->fmt.pix.height == 1944)) {
2046 RKCAMERA_DG("%s %dx%d is capture format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
2049 static int rk_camera_try_fmt(struct soc_camera_device *icd,
2050 struct v4l2_format *f)
2052 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2053 struct rk_camera_dev *pcdev = ici->priv;
2054 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
2055 const struct soc_camera_format_xlate *xlate;
2056 struct v4l2_pix_format *pix = &f->fmt.pix;
2057 __u32 pixfmt = pix->pixelformat;
2058 int ret,usr_w,usr_h,i;
2059 bool is_capture = rk_camera_fmt_capturechk(f);
2060 bool vipmem_is_overflow = false;
2061 struct v4l2_mbus_framefmt mf;
2062 int bytes_per_line_host;
2065 usr_h = pix->height;
2066 RKCAMERA_DG("%s enter width:%d height:%d\n",__FUNCTION__,usr_w,usr_h);
2068 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
2070 dev_err(icd->dev.parent, "Format (%c%c%c%c) not found\n", pixfmt & 0xFF, (pixfmt >> 8) & 0xFF,
2071 (pixfmt >> 16) & 0xFF, (pixfmt >> 24) & 0xFF);
2073 RKCAMERA_TR("%s(version:%c%c%c) support format:\n",rk_cam_driver_description,(RK_CAM_VERSION_CODE&0xff0000)>>16,
2074 (RK_CAM_VERSION_CODE&0xff00)>>8,(RK_CAM_VERSION_CODE&0xff));
2075 for (i = 0; i < icd->num_user_formats; i++)
2076 RKCAMERA_TR("(%c%c%c%c)-%s\n",
2077 icd->user_formats[i].host_fmt->fourcc & 0xFF, (icd->user_formats[i].host_fmt->fourcc >> 8) & 0xFF,
2078 (icd->user_formats[i].host_fmt->fourcc >> 16) & 0xFF, (icd->user_formats[i].host_fmt->fourcc >> 24) & 0xFF,
2079 icd->user_formats[i].host_fmt->name);
2080 goto RK_CAMERA_TRY_FMT_END;
2082 /* limit to rk29 hardware capabilities */
2083 v4l_bound_align_image(&pix->width, RK_CAM_W_MIN, RK_CAM_W_MAX, 1,
2084 &pix->height, RK_CAM_H_MIN, RK_CAM_H_MAX, 0,
2085 pixfmt == V4L2_PIX_FMT_NV16 ? 4 : 0);
2087 pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
2089 if (pix->bytesperline < 0)
2090 return pix->bytesperline;
2092 /* limit to sensor capabilities */
2093 mf.width = pix->width;
2094 mf.height = pix->height;
2095 mf.field = pix->field;
2096 mf.colorspace = pix->colorspace;
2097 mf.code = xlate->code;
2099 ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
2101 goto RK_CAMERA_TRY_FMT_END;
2102 RKCAMERA_DG("%s mf.width:%d mf.height:%d\n",__FUNCTION__,mf.width,mf.height);
2103 #ifdef CONFIG_VIDEO_RK29_WORK_IPP
2104 if ((mf.width != usr_w) || (mf.height != usr_h)) {
2105 bytes_per_line_host = soc_mbus_bytes_per_line(mf.width,icd->current_fmt->host_fmt);
2107 vipmem_is_overflow = (PAGE_ALIGN(bytes_per_line_host*mf.height) > pcdev->vipmem_size);
2109 /* Assume preview buffer minimum is 4 */
2110 vipmem_is_overflow = (PAGE_ALIGN(bytes_per_line_host*mf.height)*4 > pcdev->vipmem_size);
2112 if (vipmem_is_overflow == false) {
2114 pix->height = usr_h;
2116 RKCAMERA_TR("vipmem for IPP is overflow, This resolution(%dx%d -> %dx%d) is invalidate!\n",mf.width,mf.height,usr_w,usr_h);
2117 pix->width = mf.width;
2118 pix->height = mf.height;
2121 if ((mf.width < usr_w) || (mf.height < usr_h)) {
2122 if (((usr_w>>1) > mf.width) || ((usr_h>>1) > mf.height)) {
2123 RKCAMERA_TR("The aspect ratio(%dx%d/%dx%d) is bigger than 2 !\n",mf.width,mf.height,usr_w,usr_h);
2124 pix->width = mf.width;
2125 pix->height = mf.height;
2130 //need to change according to crop and scale capablicity
2131 if ((mf.width > usr_w) && (mf.height > usr_h)) {
2133 pix->height = usr_h;
2134 } else if ((mf.width < usr_w) && (mf.height < usr_h)) {
2135 RKCAMERA_TR("%dx%d can't scale up to %dx%d!\n",mf.width,mf.height,usr_w,usr_h);
2136 pix->width = mf.width;
2137 pix->height = mf.height;
2140 pix->colorspace = mf.colorspace;
2143 case V4L2_FIELD_ANY:
2144 case V4L2_FIELD_NONE:
2145 pix->field = V4L2_FIELD_NONE;
2148 /* TODO: support interlaced at least in pass-through mode */
2149 dev_err(icd->dev.parent, "Field type %d unsupported.\n",
2151 goto RK_CAMERA_TRY_FMT_END;
2154 RK_CAMERA_TRY_FMT_END:
2156 RKCAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
2160 static int rk_camera_reqbufs(struct soc_camera_device *icd,
2161 struct v4l2_requestbuffers *p)
2165 /* This is for locking debugging only. I removed spinlocks and now I
2166 * check whether .prepare is ever called on a linked buffer, or whether
2167 * a dma IRQ can occur for an in-work or unlinked buffer. Until now
2168 * it hadn't triggered */
2169 for (i = 0; i < p->count; i++) {
2170 struct rk_camera_buffer *buf = container_of(icd->vb_vidq.bufs[i],
2171 struct rk_camera_buffer, vb);
2173 INIT_LIST_HEAD(&buf->vb.queue);
2179 static unsigned int rk_camera_poll(struct file *file, poll_table *pt)
2181 struct soc_camera_device *icd = file->private_data;
2182 struct rk_camera_buffer *buf;
2184 buf = list_entry(icd->vb_vidq.stream.next, struct rk_camera_buffer,
2187 poll_wait(file, &buf->vb.done, pt);
2189 if (buf->vb.state == VIDEOBUF_DONE ||
2190 buf->vb.state == VIDEOBUF_ERROR)
2191 return POLLIN|POLLRDNORM;
2196 static int rk_camera_querycap(struct soc_camera_host *ici,
2197 struct v4l2_capability *cap)
2199 struct rk_camera_dev *pcdev = ici->priv;
2200 char orientation[5];
2203 strlcpy(cap->card, dev_name(pcdev->icd->pdev), sizeof(cap->card));
2204 memset(orientation,0x00,sizeof(orientation));
2205 for (i=0; i<RK_CAM_NUM;i++) {
2206 if ((pcdev->pdata->info[i].dev_name!=NULL) && (strcmp(dev_name(pcdev->icd->pdev), pcdev->pdata->info[i].dev_name) == 0)) {
2207 sprintf(orientation,"-%d",pcdev->pdata->info[i].orientation);
2211 if (orientation[0] != '-') {
2212 RKCAMERA_TR("%s: %s is not registered in rk29_camera_platform_data, orientation apply default value",__FUNCTION__,dev_name(pcdev->icd->pdev));
2213 if (strstr(dev_name(pcdev->icd->pdev),"front"))
2214 strcat(cap->card,"-270");
2216 strcat(cap->card,"-90");
2218 strcat(cap->card,orientation);
2220 cap->version = RK_CAM_VERSION_CODE;
2221 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
2225 static void rk_camera_store_register(struct rk_camera_dev *pcdev)
2227 pcdev->reginfo_suspend.cifCtrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
2228 pcdev->reginfo_suspend.cifCrop = read_cif_reg(pcdev->base,CIF_CIF_CROP);
2229 pcdev->reginfo_suspend.cifFs = read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE);
2230 pcdev->reginfo_suspend.cifIntEn = read_cif_reg(pcdev->base,CIF_CIF_INTEN);
2231 pcdev->reginfo_suspend.cifFmt= read_cif_reg(pcdev->base,CIF_CIF_FOR);
2232 pcdev->reginfo_suspend.cifVirWidth = read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH);
2233 pcdev->reginfo_suspend.cifScale= read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL);
2235 static void rk_camera_restore_register(struct rk_camera_dev *pcdev)
2237 write_cif_reg(pcdev->base,CIF_CIF_CTRL, pcdev->reginfo_suspend.cifCtrl&~ENABLE_CAPTURE);
2238 write_cif_reg(pcdev->base,CIF_CIF_INTEN, pcdev->reginfo_suspend.cifIntEn);
2239 write_cif_reg(pcdev->base,CIF_CIF_CROP, pcdev->reginfo_suspend.cifCrop);
2240 write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, pcdev->reginfo_suspend.cifFs);
2241 write_cif_reg(pcdev->base,CIF_CIF_FOR, pcdev->reginfo_suspend.cifFmt);
2242 write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH,pcdev->reginfo_suspend.cifVirWidth);
2243 write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL, pcdev->reginfo_suspend.cifScale);
2245 static int rk_camera_suspend(struct soc_camera_device *icd, pm_message_t state)
2247 struct soc_camera_host *ici =
2248 to_soc_camera_host(icd->dev.parent);
2249 struct rk_camera_dev *pcdev = ici->priv;
2250 struct v4l2_subdev *sd;
2253 mutex_lock(&camera_lock);
2254 if ((pcdev->icd == icd) && (icd->ops->suspend)) {
2255 rk_camera_s_stream(icd, 0);
2256 sd = soc_camera_to_subdev(icd);
2257 v4l2_subdev_call(sd, video, s_stream, 0);
2258 ret = icd->ops->suspend(icd, state);
2260 pcdev->reginfo_suspend.cifCtrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
2261 pcdev->reginfo_suspend.cifCrop = read_cif_reg(pcdev->base,CIF_CIF_CROP);
2262 pcdev->reginfo_suspend.cifFs = read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE);
2263 pcdev->reginfo_suspend.cifIntEn = read_cif_reg(pcdev->base,CIF_CIF_INTEN);
2264 pcdev->reginfo_suspend.cifFmt= read_cif_reg(pcdev->base,CIF_CIF_FOR);
2265 pcdev->reginfo_suspend.cifVirWidth = read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH);
2266 pcdev->reginfo_suspend.cifScale= read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL);
2268 pcdev->reginfo_suspend.Inval = Reg_Validate;
2269 rk_camera_deactivate(pcdev);
2271 RKCAMERA_DG("%s Enter Success...\n", __FUNCTION__);
2273 RKCAMERA_DG("%s icd has been deattach, don't need enter suspend\n", __FUNCTION__);
2275 mutex_unlock(&camera_lock);
2279 static int rk_camera_resume(struct soc_camera_device *icd)
2281 struct soc_camera_host *ici =
2282 to_soc_camera_host(icd->dev.parent);
2283 struct rk_camera_dev *pcdev = ici->priv;
2284 struct v4l2_subdev *sd;
2287 mutex_lock(&camera_lock);
2288 if ((pcdev->icd == icd) && (icd->ops->resume)) {
2289 if (pcdev->reginfo_suspend.Inval == Reg_Validate) {
2290 rk_camera_activate(pcdev, icd);
2291 write_cif_reg(pcdev->base,CIF_CIF_CTRL, pcdev->reginfo_suspend.cifCtrl&~ENABLE_CAPTURE);
2292 write_cif_reg(pcdev->base,CIF_CIF_INTEN, pcdev->reginfo_suspend.cifIntEn);
2293 write_cif_reg(pcdev->base,CIF_CIF_CROP, pcdev->reginfo_suspend.cifCrop);
2294 write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, pcdev->reginfo_suspend.cifFs);
2295 write_cif_reg(pcdev->base,CIF_CIF_FOR, pcdev->reginfo_suspend.cifFmt);
2296 write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH,pcdev->reginfo_suspend.cifVirWidth);
2297 write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL, pcdev->reginfo_suspend.cifScale);
2298 rk_videobuf_capture(pcdev->active,pcdev);
2299 rk_camera_s_stream(icd, 1);
2300 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
2302 RKCAMERA_TR("Resume fail, vip register recored is invalidate!!\n");
2303 goto rk_camera_resume_end;
2306 ret = icd->ops->resume(icd);
2307 sd = soc_camera_to_subdev(icd);
2308 v4l2_subdev_call(sd, video, s_stream, 1);
2310 RKCAMERA_DG("%s Enter success\n",__FUNCTION__);
2312 RKCAMERA_DG("%s icd has been deattach, don't need enter resume\n", __FUNCTION__);
2315 rk_camera_resume_end:
2316 mutex_unlock(&camera_lock);
2320 static void rk_camera_reinit_work(struct work_struct *work)
2322 struct v4l2_subdev *sd;
2323 struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
2324 struct rk_camera_dev *pcdev = camera_work->pcdev;
2325 struct soc_camera_link *tmp_soc_cam_link;
2327 unsigned long flags = 0;
2328 if(pcdev->icd == NULL)
2330 sd = soc_camera_to_subdev(pcdev->icd);
2331 tmp_soc_cam_link = to_soc_camera_link(pcdev->icd);
2334 RKCAMERA_TR("CIF_CIF_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CTRL));
2335 RKCAMERA_TR("CIF_CIF_INTEN = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTEN));
2336 RKCAMERA_TR("CIF_CIF_INTSTAT = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTSTAT));
2337 RKCAMERA_TR("CIF_CIF_FOR = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_FOR));
2338 RKCAMERA_TR("CIF_CIF_CROP = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CROP));
2339 RKCAMERA_TR("CIF_CIF_SET_SIZE = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE));
2340 RKCAMERA_TR("CIF_CIF_SCL_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL));
2341 RKCAMERA_TR("CRU_PCLK_REG30 = 0X%x\n",read_cru_reg(CRU_PCLK_REG30));
2342 RKCAMERA_TR("CIF_CIF_LAST_LINE = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_LINE));
2344 RKCAMERA_TR("CIF_CIF_LAST_PIX = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_PIX));
2345 RKCAMERA_TR("CIF_CIF_VIR_LINE_WIDTH = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH));
2346 RKCAMERA_TR("CIF_CIF_LINE_NUM_ADDR = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LINE_NUM_ADDR));
2347 RKCAMERA_TR("CIF_CIF_FRM0_ADDR_Y = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y));
2348 RKCAMERA_TR("CIF_CIF_FRM0_ADDR_UV = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV));
2349 RKCAMERA_TR("CIF_CIF_FRAME_STATUS = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS));
2352 pcdev->stop_cif = true;
2353 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL)&(~ENABLE_CAPTURE)));
2354 RKCAMERA_DG("the reinit times = %d\n",pcdev->reinit_times);
2356 spin_lock_irqsave(pcdev->video_vq->irqlock, flags);
2357 for (index = 0; index < VIDEO_MAX_FRAME; index++) {
2358 if (NULL == pcdev->video_vq->bufs[index])
2361 if (pcdev->video_vq->bufs[index]->state == VIDEOBUF_QUEUED)
2363 list_del_init(&pcdev->video_vq->bufs[index]->queue);
2364 pcdev->video_vq->bufs[index]->state = VIDEOBUF_NEEDS_INIT;
2365 wake_up_all(&pcdev->video_vq->bufs[index]->done);
2366 printk("wake up video buffer index = %d !!!\n",index);
2369 spin_unlock_irqrestore(pcdev->video_vq->irqlock, flags);
2371 RKCAMERA_TR("the %d reinit times ,wake up video buffers!\n ",pcdev->reinit_times);
2373 static enum hrtimer_restart rk_camera_fps_func(struct hrtimer *timer)
2375 struct rk_camera_frmivalenum *fival_nxt=NULL,*fival_pre=NULL, *fival_rec=NULL;
2376 struct rk_camera_timer *fps_timer = container_of(timer, struct rk_camera_timer, timer);
2377 struct rk_camera_dev *pcdev = fps_timer->pcdev;
2379 // static unsigned int last_fps = 0;
2380 struct soc_camera_link *tmp_soc_cam_link;
2381 tmp_soc_cam_link = to_soc_camera_link(pcdev->icd);
2383 RKCAMERA_DG("rk_camera_fps_func fps:0x%x\n",pcdev->fps);
2384 if ((pcdev->fps < 1) || (pcdev->last_fps == pcdev->fps)) {
2385 RKCAMERA_TR("Camera host haven't recevie data from sensor,Reinit sensor delay,last fps = %d,pcdev->fps = %d!\n",pcdev->last_fps,pcdev->fps);
2386 pcdev->camera_reinit_work.pcdev = pcdev;
2387 //INIT_WORK(&(pcdev->camera_reinit_work.work), rk_camera_reinit_work);
2388 pcdev->reinit_times++;
2389 queue_work(pcdev->camera_wq,&(pcdev->camera_reinit_work.work));
2390 } else if(!pcdev->timer_get_fps) {
2391 pcdev->timer_get_fps = true;
2392 for (i=0; i<2; i++) {
2393 if (pcdev->icd == pcdev->icd_frmival[i].icd) {
2394 fival_nxt = pcdev->icd_frmival[i].fival_list;
2399 fival_pre = fival_nxt;
2400 while (fival_nxt != NULL) {
2402 RKCAMERA_DG("%s %c%c%c%c %dx%d framerate : %d/%d\n", dev_name(&pcdev->icd->dev),
2403 fival_nxt->fival.pixel_format & 0xFF, (fival_nxt->fival.pixel_format >> 8) & 0xFF,
2404 (fival_nxt->fival.pixel_format >> 16) & 0xFF, (fival_nxt->fival.pixel_format >> 24),
2405 fival_nxt->fival.width, fival_nxt->fival.height, fival_nxt->fival.discrete.denominator,
2406 fival_nxt->fival.discrete.numerator);
2408 if (((fival_nxt->fival.pixel_format == pcdev->pixfmt)
2409 && (fival_nxt->fival.height == pcdev->icd->user_height)
2410 && (fival_nxt->fival.width == pcdev->icd->user_width))
2411 || (fival_nxt->fival.discrete.denominator == 0)) {
2413 if (fival_nxt->fival.discrete.denominator == 0) {
2414 fival_nxt->fival.index = 0;
2415 fival_nxt->fival.width = pcdev->icd->user_width;
2416 fival_nxt->fival.height= pcdev->icd->user_height;
2417 fival_nxt->fival.pixel_format = pcdev->pixfmt;
2418 fival_nxt->fival.discrete.denominator = pcdev->frame_interval;
2419 fival_nxt->fival.reserved[1] = (pcdev->icd_width<<16)
2420 |(pcdev->icd_height);
2421 fival_nxt->fival.discrete.numerator = 1000000;
2422 fival_nxt->fival.type = V4L2_FRMIVAL_TYPE_DISCRETE;
2425 fival_rec = fival_nxt;
2427 fival_pre = fival_nxt;
2428 fival_nxt = fival_nxt->nxt;
2431 if ((rec_flag == 0) && fival_pre) {
2432 fival_pre->nxt = kzalloc(sizeof(struct rk_camera_frmivalenum), GFP_ATOMIC);
2433 if (fival_pre->nxt != NULL) {
2434 fival_pre->nxt->fival.index = fival_pre->fival.index++;
2435 fival_pre->nxt->fival.width = pcdev->icd->user_width;
2436 fival_pre->nxt->fival.height= pcdev->icd->user_height;
2437 fival_pre->nxt->fival.pixel_format = pcdev->pixfmt;
2439 fival_pre->nxt->fival.discrete.denominator = pcdev->frame_interval;
2440 fival_pre->nxt->fival.reserved[1] = (pcdev->icd_width<<16)
2441 |(pcdev->icd_height);
2442 fival_pre->nxt->fival.discrete.numerator = 1000000;
2443 fival_pre->nxt->fival.type = V4L2_FRMIVAL_TYPE_DISCRETE;
2445 fival_rec = fival_pre->nxt;
2449 pcdev->last_fps = pcdev->fps ;
2450 pcdev->fps_timer.timer.node.expires= ktime_add_us(pcdev->fps_timer.timer.node.expires, ktime_to_us(ktime_set(3, 0)));
2451 pcdev->fps_timer.timer._softexpires= ktime_add_us(pcdev->fps_timer.timer._softexpires, ktime_to_us(ktime_set(3, 0)));
2452 //return HRTIMER_NORESTART;
2453 if(pcdev->reinit_times >=2)
2454 return HRTIMER_NORESTART;
2456 return HRTIMER_RESTART;
2458 static int rk_camera_s_stream(struct soc_camera_device *icd, int enable)
2460 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2461 struct rk_camera_dev *pcdev = ici->priv;
2464 unsigned long flags;
2466 WARN_ON(pcdev->icd != icd);
2468 cif_ctrl_val = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
2471 pcdev->last_fps = 0;
2472 pcdev->frame_interval = 0;
2473 hrtimer_cancel(&(pcdev->fps_timer.timer));
2474 pcdev->fps_timer.pcdev = pcdev;
2475 pcdev->timer_get_fps = false;
2476 pcdev->reinit_times = 0;
2477 pcdev->stop_cif = false;
2478 // hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL);
2479 cif_ctrl_val |= ENABLE_CAPTURE;
2480 write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val);
2481 hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL);
2482 pcdev->fps_timer.istarted = true;
2484 //cancel timer before stop cif
2485 ret = hrtimer_cancel(&pcdev->fps_timer.timer);
2486 pcdev->fps_timer.istarted = false;
2487 flush_work(&(pcdev->camera_reinit_work.work));
2489 cif_ctrl_val &= ~ENABLE_CAPTURE;
2490 spin_lock_irqsave(&pcdev->lock, flags);
2491 write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val);
2492 pcdev->stop_cif = true;
2493 spin_unlock_irqrestore(&pcdev->lock, flags);
2494 flush_workqueue((pcdev->camera_wq));
2495 RKCAMERA_DG("STREAM_OFF cancel timer and flush work:0x%x \n", ret);
2497 //must be reinit,or will be somthing wrong in irq process.
2498 if(enable == false){
2499 pcdev->active = NULL;
2500 INIT_LIST_HEAD(&pcdev->capture);
2502 RKCAMERA_DG("%s.. enable : 0x%x , CIF_CIF_CTRL = 0x%x\n", __FUNCTION__, enable,read_cif_reg(pcdev->base,CIF_CIF_CTRL));
2505 int rk_camera_enum_frameintervals(struct soc_camera_device *icd, struct v4l2_frmivalenum *fival)
2507 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2508 struct rk_camera_dev *pcdev = ici->priv;
2509 struct rk_camera_frmivalenum *fival_list = NULL;
2510 struct v4l2_frmivalenum *fival_head = NULL;
2511 int i,ret = 0,index;
2513 index = fival->index & 0x00ffffff;
2514 if ((fival->index & 0xff000000) == 0xff000000) { /* ddl@rock-chips.com: detect framerate */
2515 for (i=0; i<2; i++) {
2516 if (pcdev->icd_frmival[i].icd == icd) {
2517 fival_list = pcdev->icd_frmival[i].fival_list;
2521 if (fival_list != NULL) {
2523 while (fival_list != NULL) {
2524 if ((fival->pixel_format == fival_list->fival.pixel_format)
2525 && (fival->height == fival_list->fival.height)
2526 && (fival->width == fival_list->fival.width)) {
2531 fival_list = fival_list->nxt;
2534 if ((i==index) && (fival_list != NULL)) {
2535 memcpy(fival, &fival_list->fival, sizeof(struct v4l2_frmivalenum));
2540 RKCAMERA_TR("%s: fival_list is NULL\n",__FUNCTION__);
2545 for (i=0; i<RK_CAM_NUM; i++) {
2546 if (pcdev->pdata->info[i].dev_name && (strcmp(dev_name(pcdev->icd->pdev),pcdev->pdata->info[i].dev_name) == 0)) {
2547 fival_head = pcdev->pdata->info[i].fival;
2551 if (fival_head == NULL) {
2552 RKCAMERA_TR("%s: %s is not registered in rk_camera_platform_data!!",__FUNCTION__,dev_name(pcdev->icd->pdev));
2554 goto rk_camera_enum_frameintervals_end;
2558 while (fival_head->width && fival_head->height) {
2559 if ((fival->pixel_format == fival_head->pixel_format)
2560 && (fival->height == fival_head->height)
2561 && (fival->width == fival_head->width)) {
2570 if ((i == index) && (fival->height == fival_head->height) && (fival->width == fival_head->width)) {
2571 memcpy(fival, fival_head, sizeof(struct v4l2_frmivalenum));
2572 RKCAMERA_DG("%s %dx%d@%c%c%c%c framerate : %d/%d\n", dev_name(pcdev->icd->pdev),
2573 fival->width, fival->height,
2574 fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
2575 (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
2576 fival->discrete.denominator,fival->discrete.numerator);
2579 RKCAMERA_TR("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(pcdev->icd->pdev),
2580 fival->width,fival->height,
2581 fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
2582 (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
2585 RKCAMERA_DG("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(pcdev->icd->pdev),
2586 fival->width,fival->height,
2587 fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
2588 (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
2593 rk_camera_enum_frameintervals_end:
2597 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
2598 static int rk_camera_set_digit_zoom(struct soc_camera_device *icd,
2599 const struct v4l2_queryctrl *qctrl, int zoom_rate)
2602 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2603 struct rk_camera_dev *pcdev = ici->priv;
2606 //change the crop and scale parameters
2607 a.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2608 a.c.width = pcdev->host_width*100/zoom_rate;
2610 a.c.height = pcdev->host_height*100/zoom_rate;
2611 a.c.height &= ~0x03;
2612 a.c.left = (pcdev->host_width - a.c.width)>>1;
2613 a.c.top = (pcdev->host_height - a.c.height)>>1;
2614 down(&pcdev->zoominfo.sem);
2615 pcdev->zoominfo.a.c.height = a.c.height;
2616 pcdev->zoominfo.a.c.width = a.c.width;
2617 pcdev->zoominfo.a.c.top = a.c.top;
2618 pcdev->zoominfo.a.c.left = a.c.left;
2619 pcdev->zoominfo.vir_width = pcdev->host_width;
2620 pcdev->zoominfo.vir_height= pcdev->host_height;
2621 up(&pcdev->zoominfo.sem);
2622 RKCAMERA_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, icd->user_width, icd->user_height );
2627 static inline struct v4l2_queryctrl const *rk_camera_soc_camera_find_qctrl(
2628 struct soc_camera_host_ops *ops, int id)
2632 for (i = 0; i < ops->num_controls; i++)
2633 if (ops->controls[i].id == id)
2634 return &ops->controls[i];
2640 static int rk_camera_set_ctrl(struct soc_camera_device *icd,
2641 struct v4l2_control *sctrl)
2644 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2645 const struct v4l2_queryctrl *qctrl;
2646 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
2647 struct rk_camera_dev *pcdev = ici->priv;
2651 qctrl = rk_camera_soc_camera_find_qctrl(ici->ops, sctrl->id);
2654 goto rk_camera_set_ctrl_end;
2659 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
2660 case V4L2_CID_ZOOM_ABSOLUTE:
2662 if ((sctrl->value < qctrl->minimum) || (sctrl->value > qctrl->maximum)){
2664 goto rk_camera_set_ctrl_end;
2666 ret = rk_camera_set_digit_zoom(icd, qctrl, sctrl->value);
2668 pcdev->zoominfo.zoom_rate = sctrl->value;
2670 goto rk_camera_set_ctrl_end;
2679 rk_camera_set_ctrl_end:
2683 static struct soc_camera_host_ops rk_soc_camera_host_ops =
2685 .owner = THIS_MODULE,
2686 .add = rk_camera_add_device,
2687 .remove = rk_camera_remove_device,
2688 .suspend = rk_camera_suspend,
2689 .resume = rk_camera_resume,
2690 .enum_frameinervals = rk_camera_enum_frameintervals,
2691 .set_crop = rk_camera_set_crop,
2692 .get_formats = rk_camera_get_formats,
2693 .put_formats = rk_camera_put_formats,
2694 .set_fmt = rk_camera_set_fmt,
2695 .try_fmt = rk_camera_try_fmt,
2696 .init_videobuf = rk_camera_init_videobuf,
2697 .reqbufs = rk_camera_reqbufs,
2698 .poll = rk_camera_poll,
2699 .querycap = rk_camera_querycap,
2700 .set_bus_param = rk_camera_set_bus_param,
2701 .s_stream = rk_camera_s_stream, /* ddl@rock-chips.com : Add stream control for host */
2702 .set_ctrl = rk_camera_set_ctrl,
2703 .controls = rk_camera_controls,
2704 .num_controls = ARRAY_SIZE(rk_camera_controls)
2707 static void rk_camera_cif_iomux(int cif_index)
2709 #ifdef CONFIG_ARCH_RK30
2712 rk30_mux_api_set(GPIO1B3_CIF0CLKOUT_NAME, GPIO1B_CIF0_CLKOUT);
2715 rk30_mux_api_set(GPIO1C0_CIF1DATA2_RMIICLKOUT_RMIICLKIN_NAME,GPIO1C_CIF1_DATA2);
2716 rk30_mux_api_set(GPIO1C1_CIFDATA3_RMIITXEN_NAME,GPIO1C_CIF_DATA3);
2717 rk30_mux_api_set(GPIO1C2_CIF1DATA4_RMIITXD1_NAME,GPIO1C_CIF1_DATA4);
2718 rk30_mux_api_set(GPIO1C3_CIFDATA5_RMIITXD0_NAME,GPIO1C_CIF_DATA5);
2719 rk30_mux_api_set(GPIO1C4_CIFDATA6_RMIIRXERR_NAME,GPIO1C_CIF_DATA6);
2720 rk30_mux_api_set(GPIO1C5_CIFDATA7_RMIICRSDVALID_NAME,GPIO1C_CIF_DATA7);
2721 rk30_mux_api_set(GPIO1C6_CIFDATA8_RMIIRXD1_NAME,GPIO1C_CIF_DATA8);
2722 rk30_mux_api_set(GPIO1C7_CIFDATA9_RMIIRXD0_NAME,GPIO1C_CIF_DATA9);
2724 rk30_mux_api_set(GPIO1D0_CIF1VSYNC_MIIMD_NAME,GPIO1D_CIF1_VSYNC);
2725 rk30_mux_api_set(GPIO1D1_CIF1HREF_MIIMDCLK_NAME,GPIO1D_CIF1_HREF);
2726 rk30_mux_api_set(GPIO1D2_CIF1CLKIN_NAME,GPIO1D_CIF1_CLKIN);
2727 rk30_mux_api_set(GPIO1D3_CIF1DATA0_NAME,GPIO1D_CIF1_DATA0);
2728 rk30_mux_api_set(GPIO1D4_CIF1DATA1_NAME,GPIO1D_CIF1_DATA1);
2729 rk30_mux_api_set(GPIO1D5_CIF1DATA10_NAME,GPIO1D_CIF1_DATA10);
2730 rk30_mux_api_set(GPIO1D6_CIF1DATA11_NAME,GPIO1D_CIF1_DATA11);
2731 rk30_mux_api_set(GPIO1D7_CIF1CLKOUT_NAME,GPIO1D_CIF1_CLKOUT);
2734 printk("cif index is erro!!!\n");
2741 static int rk_camera_probe(struct platform_device *pdev)
2743 struct rk_camera_dev *pcdev;
2744 struct resource *res;
2745 struct rk_camera_frmivalenum *fival_list,*fival_nxt;
2749 RKCAMERA_DG("%s(%d) Enter..\n",__FUNCTION__,__LINE__);
2751 if ((pdev->id == RK_CAM_PLATFORM_DEV_ID_1) && (RK_SUPPORT_CIF1 == 0)) {
2752 RKCAMERA_TR("%s(%d): This chip is not support CIF1!!\n",__FUNCTION__,__LINE__);
2756 if ((pdev->id == RK_CAM_PLATFORM_DEV_ID_0) && (RK_SUPPORT_CIF0 == 0)) {
2757 RKCAMERA_TR("%s(%d): This chip is not support CIF0!!\n",__FUNCTION__,__LINE__);
2761 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2762 irq = platform_get_irq(pdev, 0);
2763 if (!res || irq < 0) {
2767 pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL);
2769 dev_err(&pdev->dev, "Could not allocate pcdev\n");
2774 pcdev->zoominfo.zoom_rate = 100;
2775 pcdev->hostid = pdev->id;
2777 /*config output clk*/ // must modify start
2779 pcdev->pd_cif = clk_get(NULL, "pd_cif0");
2780 pcdev->aclk_cif = clk_get(NULL, "aclk_cif0");
2781 pcdev->hclk_cif = clk_get(NULL, "hclk_cif0");
2782 pcdev->cif_clk_in = clk_get(NULL, "cif0_in");
2783 pcdev->cif_clk_out = clk_get(NULL, "cif0_out");
2784 rk_camera_cif_iomux(0);
2786 pcdev->pd_cif = clk_get(NULL, "pd_cif1");
2787 pcdev->aclk_cif = clk_get(NULL, "aclk_cif1");
2788 pcdev->hclk_cif = clk_get(NULL, "hclk_cif1");
2789 pcdev->cif_clk_in = clk_get(NULL, "cif1_in");
2790 pcdev->cif_clk_out = clk_get(NULL, "cif1_out");
2792 rk_camera_cif_iomux(1);
2795 if(IS_ERR(pcdev->pd_cif) || IS_ERR(pcdev->aclk_cif) || IS_ERR(pcdev->hclk_cif) || IS_ERR(pcdev->cif_clk_in) || IS_ERR(pcdev->cif_clk_out)){
2796 RKCAMERA_TR(KERN_ERR "%s(%d): failed to get cif clock source\n",__FUNCTION__,__LINE__);
2798 goto exit_reqmem_vip;
2801 dev_set_drvdata(&pdev->dev, pcdev);
2803 pcdev->pdata = pdev->dev.platform_data; /* ddl@rock-chips.com : Request IO in init function */
2805 if (pcdev->pdata && pcdev->pdata->io_init) {
2806 pcdev->pdata->io_init();
2808 #ifdef CONFIG_VIDEO_RK29_WORK_IPP
2809 if (pcdev->pdata && IS_CIF0()) {
2810 pcdev->vipmem_phybase = pcdev->pdata->meminfo.start;
2811 pcdev->vipmem_size = pcdev->pdata->meminfo.size;
2813 if (!request_mem_region(pcdev->vipmem_phybase,pcdev->vipmem_size,"rk29_vipmem")) {
2815 goto exit_ioremap_vipmem;
2817 pcdev->vipmem_virbase = ioremap_cached(pcdev->vipmem_phybase,pcdev->vipmem_size);
2818 if (pcdev->vipmem_virbase == NULL) {
2819 dev_err(pcdev->dev, "ioremap() of vip internal memory(Ex:IPP process/raw process) failed\n");
2821 goto exit_ioremap_vipmem;
2823 RKCAMERA_TR("%s(%d): Memory(start:0x%x size:0x%x) for IPP obtain \n",__FUNCTION__,__LINE__, pcdev->pdata->meminfo.start,pcdev->pdata->meminfo.size);
2824 } else if (pcdev->pdata) {
2825 pcdev->vipmem_phybase = pcdev->pdata->meminfo_cif1.start;
2826 pcdev->vipmem_size = pcdev->pdata->meminfo_cif1.size;
2828 if (!request_mem_region(pcdev->vipmem_phybase,pcdev->vipmem_size,"rk29_vipmem")) {
2830 goto exit_ioremap_vipmem;
2832 pcdev->vipmem_virbase = ioremap_cached(pcdev->vipmem_phybase,pcdev->vipmem_size);
2833 if (pcdev->vipmem_virbase == NULL) {
2834 dev_err(pcdev->dev, "ioremap() of vip internal memory(Ex:IPP process/raw process) failed\n");
2836 goto exit_ioremap_vipmem;
2838 RKCAMERA_TR("%s(%d): Memory(start:0x%x size:0x%x) for IPP obtain \n",__FUNCTION__,__LINE__, pcdev->pdata->meminfo.start,pcdev->pdata->meminfo.size);
2840 RKCAMERA_TR("\n%s Memory for IPP have not obtain! IPP Function is fail\n",__FUNCTION__);
2841 pcdev->vipmem_phybase = 0;
2842 pcdev->vipmem_size = 0;
2843 pcdev->vipmem_virbase = 0;
2846 INIT_LIST_HEAD(&pcdev->capture);
2847 INIT_LIST_HEAD(&pcdev->camera_work_queue);
2848 spin_lock_init(&pcdev->lock);
2849 spin_lock_init(&pcdev->camera_work_lock);
2850 sema_init(&pcdev->zoominfo.sem,1);
2853 * Request the regions.
2856 if (!request_mem_region(res->start, res->end - res->start + 1,
2857 RK29_CAM_DRV_NAME)) {
2859 goto exit_reqmem_vip;
2861 pcdev->base = ioremap(res->start, res->end - res->start + 1);
2862 if (pcdev->base == NULL) {
2863 dev_err(pcdev->dev, "ioremap() of registers failed\n");
2865 goto exit_ioremap_vip;
2870 pcdev->dev = &pdev->dev;
2872 /* config buffer address */
2875 err = request_irq(pcdev->irq, rk_camera_irq, 0, RK29_CAM_DRV_NAME,
2878 dev_err(pcdev->dev, "Camera interrupt register failed \n");
2883 //#ifdef CONFIG_VIDEO_RK29_WORK_IPP
2885 pcdev->camera_wq = create_workqueue("rk_cam_wkque_cif0");
2887 pcdev->camera_wq = create_workqueue("rk_cam_wkque_cif1");
2889 if (pcdev->camera_wq == NULL)
2893 pcdev->camera_reinit_work.pcdev = pcdev;
2894 INIT_WORK(&(pcdev->camera_reinit_work.work), rk_camera_reinit_work);
2896 for (i=0; i<2; i++) {
2897 pcdev->icd_frmival[i].icd = NULL;
2898 pcdev->icd_frmival[i].fival_list = kzalloc(sizeof(struct rk_camera_frmivalenum),GFP_KERNEL);
2901 pcdev->soc_host.drv_name = RK29_CAM_DRV_NAME;
2902 pcdev->soc_host.ops = &rk_soc_camera_host_ops;
2903 pcdev->soc_host.priv = pcdev;
2904 pcdev->soc_host.v4l2_dev.dev = &pdev->dev;
2905 pcdev->soc_host.nr = pdev->id;
2907 err = soc_camera_host_register(&pcdev->soc_host);
2910 pcdev->fps_timer.pcdev = pcdev;
2911 hrtimer_init(&(pcdev->fps_timer.timer), CLOCK_MONOTONIC, HRTIMER_MODE_REL);
2912 pcdev->fps_timer.timer.function = rk_camera_fps_func;
2913 pcdev->icd_cb.sensor_cb = NULL;
2915 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP)
2916 pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_ipp;
2917 #elif (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_ARM)
2918 pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_arm;
2919 #elif (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_RGA)
2920 pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_rga;
2922 RKCAMERA_DG("%s(%d) Exit \n",__FUNCTION__,__LINE__);
2927 for (i=0; i<2; i++) {
2928 fival_list = pcdev->icd_frmival[i].fival_list;
2929 fival_nxt = fival_list;
2930 while(fival_nxt != NULL) {
2931 fival_nxt = fival_list->nxt;
2933 fival_list = fival_nxt;
2937 free_irq(pcdev->irq, pcdev);
2938 if (pcdev->camera_wq) {
2939 destroy_workqueue(pcdev->camera_wq);
2940 pcdev->camera_wq = NULL;
2943 iounmap(pcdev->base);
2945 release_mem_region(res->start, res->end - res->start + 1);
2946 exit_ioremap_vipmem:
2947 if (pcdev->vipmem_virbase)
2948 iounmap(pcdev->vipmem_virbase);
2949 release_mem_region(pcdev->vipmem_phybase,pcdev->vipmem_size);
2952 pcdev->aclk_cif = NULL;
2954 pcdev->hclk_cif = NULL;
2955 if(pcdev->cif_clk_in)
2956 pcdev->cif_clk_in = NULL;
2957 if(pcdev->cif_clk_out)
2958 pcdev->cif_clk_out = NULL;
2967 static int __devexit rk_camera_remove(struct platform_device *pdev)
2969 struct rk_camera_dev *pcdev = platform_get_drvdata(pdev);
2970 struct resource *res;
2971 struct rk_camera_frmivalenum *fival_list,*fival_nxt;
2974 free_irq(pcdev->irq, pcdev);
2976 if (pcdev->camera_wq) {
2977 destroy_workqueue(pcdev->camera_wq);
2978 pcdev->camera_wq = NULL;
2981 for (i=0; i<2; i++) {
2982 fival_list = pcdev->icd_frmival[i].fival_list;
2983 fival_nxt = fival_list;
2984 while(fival_nxt != NULL) {
2985 fival_nxt = fival_list->nxt;
2987 fival_list = fival_nxt;
2991 soc_camera_host_unregister(&pcdev->soc_host);
2994 release_mem_region(res->start, res->end - res->start + 1);
2995 if (pcdev->pdata && pcdev->pdata->io_deinit) { /* ddl@rock-chips.com : Free IO in deinit function */
2996 pcdev->pdata->io_deinit(0);
2997 pcdev->pdata->io_deinit(1);
3002 dev_info(&pdev->dev, "RK28 Camera driver unloaded\n");
3007 static struct platform_driver rk_camera_driver =
3010 .name = RK29_CAM_DRV_NAME,
3012 .probe = rk_camera_probe,
3013 .remove = __devexit_p(rk_camera_remove),
3016 static int rk_camera_init_async(void *unused)
3018 RKCAMERA_DG("%s..%s..%d \n",__FUNCTION__,__FILE__,__LINE__);
3019 platform_driver_register(&rk_camera_driver);
3023 static int __devinit rk_camera_init(void)
3025 RKCAMERA_DG("%s..%s..%d \n",__FUNCTION__,__FILE__,__LINE__);
3026 kthread_run(rk_camera_init_async, NULL, "rk_camera_init");
3030 static void __exit rk_camera_exit(void)
3032 platform_driver_unregister(&rk_camera_driver);
3035 device_initcall_sync(rk_camera_init);
3036 module_exit(rk_camera_exit);
3038 MODULE_DESCRIPTION("RKSoc Camera Host driver");
3039 MODULE_AUTHOR("ddl <ddl@rock-chips>");
3040 MODULE_LICENSE("GPL");