2 * V4L2 Driver for RK28 camera host
4 * Copyright (C) 2006, Sascha Hauer, Pengutronix
5 * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 #ifdef CONFIG_ARCH_RK30
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>
41 #include <mach/rk30_camera.h>
46 module_param(debug, int, S_IRUGO|S_IWUSR);
48 #define dprintk(level, fmt, arg...) do { \
50 printk(KERN_WARNING"rk_camera: " fmt , ## arg); } while (0)
52 #define RKCAMERA_TR(format, ...) printk(KERN_ERR format, ## __VA_ARGS__)
53 #define RKCAMERA_DG(format, ...) dprintk(1, format, ## __VA_ARGS__)
56 #define CIF_CIF_CTRL 0x00
57 #define CIF_CIF_INTEN 0x04
58 #define CIF_CIF_INTSTAT 0x08
59 #define CIF_CIF_FOR 0x0c
60 #define CIF_CIF_LINE_NUM_ADDR 0x10
61 #define CIF_CIF_FRM0_ADDR_Y 0x14
62 #define CIF_CIF_FRM0_ADDR_UV 0x18
63 #define CIF_CIF_FRM1_ADDR_Y 0x1c
64 #define CIF_CIF_FRM1_ADDR_UV 0x20
65 #define CIF_CIF_VIR_LINE_WIDTH 0x24
66 #define CIF_CIF_SET_SIZE 0x28
67 #define CIF_CIF_SCM_ADDR_Y 0x2c
68 #define CIF_CIF_SCM_ADDR_U 0x30
69 #define CIF_CIF_SCM_ADDR_V 0x34
70 #define CIF_CIF_WB_UP_FILTER 0x38
71 #define CIF_CIF_WB_LOW_FILTER 0x3c
72 #define CIF_CIF_WBC_CNT 0x40
73 #define CIF_CIF_CROP 0x44
74 #define CIF_CIF_SCL_CTRL 0x48
75 #define CIF_CIF_SCL_DST 0x4c
76 #define CIF_CIF_SCL_FCT 0x50
77 #define CIF_CIF_SCL_VALID_NUM 0x54
78 #define CIF_CIF_LINE_LOOP_CTR 0x58
79 #define CIF_CIF_FRAME_STATUS 0x60
80 #define CIF_CIF_CUR_DST 0x64
81 #define CIF_CIF_LAST_LINE 0x68
82 #define CIF_CIF_LAST_PIX 0x6c
84 //The key register bit descrition
85 // CIF_CTRL Reg , ignore SCM,WBC,ISP,
86 #define DISABLE_CAPTURE (0x00<<0)
87 #define ENABLE_CAPTURE (0x01<<0)
88 #define MODE_ONEFRAME (0x00<<1)
89 #define MODE_PINGPONG (0x01<<1)
90 #define MODE_LINELOOP (0x02<<1)
91 #define AXI_BURST_16 (0x0F << 12)
94 #define FRAME_END_EN (0x01<<1)
95 #define BUS_ERR_EN (0x01<<6)
96 #define SCL_ERR_EN (0x01<<7)
99 #define VSY_HIGH_ACTIVE (0x01<<0)
100 #define VSY_LOW_ACTIVE (0x00<<0)
101 #define HSY_LOW_ACTIVE (0x01<<1)
102 #define HSY_HIGH_ACTIVE (0x00<<1)
103 #define INPUT_MODE_YUV (0x00<<2)
104 #define INPUT_MODE_PAL (0x02<<2)
105 #define INPUT_MODE_NTSC (0x03<<2)
106 #define INPUT_MODE_RAW (0x04<<2)
107 #define INPUT_MODE_JPEG (0x05<<2)
108 #define INPUT_MODE_MIPI (0x06<<2)
109 #define YUV_INPUT_ORDER_UYVY(ori) (ori & (~(0x03<<5)))
110 #define YUV_INPUT_ORDER_YVYU(ori) ((ori & (~(0x01<<6)))|(0x01<<5))
111 #define YUV_INPUT_ORDER_VYUY(ori) ((ori & (~(0x01<<5))) | (0x1<<6))
112 #define YUV_INPUT_ORDER_YUYV(ori) (ori|(0x03<<5))
113 #define YUV_INPUT_422 (0x00<<7)
114 #define YUV_INPUT_420 (0x01<<7)
115 #define INPUT_420_ORDER_EVEN (0x00<<8)
116 #define INPUT_420_ORDER_ODD (0x01<<8)
117 #define CCIR_INPUT_ORDER_ODD (0x00<<9)
118 #define CCIR_INPUT_ORDER_EVEN (0x01<<9)
119 #define RAW_DATA_WIDTH_8 (0x00<<11)
120 #define RAW_DATA_WIDTH_10 (0x01<<11)
121 #define RAW_DATA_WIDTH_12 (0x02<<11)
122 #define YUV_OUTPUT_422 (0x00<<16)
123 #define YUV_OUTPUT_420 (0x01<<16)
124 #define OUTPUT_420_ORDER_EVEN (0x00<<17)
125 #define OUTPUT_420_ORDER_ODD (0x01<<17)
126 #define RAWD_DATA_LITTLE_ENDIAN (0x00<<18)
127 #define RAWD_DATA_BIG_ENDIAN (0x01<<18)
128 #define UV_STORAGE_ORDER_UVUV (0x00<<19)
129 #define UV_STORAGE_ORDER_VUVU (0x01<<19)
132 #define ENABLE_SCL_DOWN (0x01<<0)
133 #define DISABLE_SCL_DOWN (0x00<<0)
134 #define ENABLE_SCL_UP (0x01<<1)
135 #define DISABLE_SCL_UP (0x00<<1)
136 #define ENABLE_YUV_16BIT_BYPASS (0x01<<4)
137 #define DISABLE_YUV_16BIT_BYPASS (0x00<<4)
138 #define ENABLE_RAW_16BIT_BYPASS (0x01<<5)
139 #define DISABLE_RAW_16BIT_BYPASS (0x00<<5)
140 #define ENABLE_32BIT_BYPASS (0x01<<6)
141 #define DISABLE_32BIT_BYPASS (0x00<<6)
144 #define CRU_PCLK_REG30 0xbc
145 #define ENANABLE_INVERT_PCLK_CIF0 ((0x1<<24)|(0x1<<8))
146 #define DISABLE_INVERT_PCLK_CIF0 ((0x1<<24)|(0x0<<8))
147 #define ENANABLE_INVERT_PCLK_CIF1 ((0x1<<28)|(0x1<<12))
148 #define DISABLE_INVERT_PCLK_CIF1 ((0x1<<28)|(0x0<<12))
150 #define CRU_CIF_RST_REG30 0x128
151 #define MASK_RST_CIF0 (0x01 << 30)
152 #define MASK_RST_CIF1 (0x01 << 31)
153 #define RQUEST_RST_CIF0 (0x01 << 14)
154 #define RQUEST_RST_CIF1 (0x01 << 15)
156 #define MIN(x,y) ((x<y) ? x: y)
157 #define MAX(x,y) ((x>y) ? x: y)
158 #define RK_SENSOR_24MHZ 24*1000*1000 /* MHz */
159 #define RK_SENSOR_48MHZ 48
161 #define write_cif_reg(base,addr, val) __raw_writel(val, addr+(base))
162 #define read_cif_reg(base,addr) __raw_readl(addr+(base))
163 #define mask_cif_reg(addr, msk, val) write_cif_reg(addr, (val)|((~(msk))&read_cif_reg(addr)))
165 #define write_cru_reg(addr, val) __raw_writel(val, addr+RK30_CRU_BASE)
166 #define read_cru_reg(addr) __raw_readl(addr+RK30_CRU_BASE)
167 #define mask_cru_reg(addr, msk, val) write_cru_reg(addr,(val)|((~(msk))&read_cru_reg(addr)))
169 //when work_with_ipp is not enabled,CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_OFF is not defined.something wrong with it
170 #ifdef CONFIG_VIDEO_RK29_WORK_IPP//CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_OFF
171 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_OFF
172 #define CAM_WORKQUEUE_IS_EN() ((pcdev->host_width != pcdev->icd->user_width) || (pcdev->host_height != pcdev->icd->user_height)\
173 || (pcdev->icd_cb.sensor_cb))
174 #define CAM_IPPWORK_IS_EN() ((pcdev->host_width != pcdev->icd->user_width) || (pcdev->host_height != pcdev->icd->user_height))
176 #define CAM_WORKQUEUE_IS_EN() (true)
177 #define CAM_IPPWORK_IS_EN() ((pcdev->zoominfo.a.c.width != pcdev->icd->user_width) || (pcdev->zoominfo.a.c.height != pcdev->icd->user_height))
179 #else //CONFIG_VIDEO_RK29_WORK_IPP
180 #define CAM_WORKQUEUE_IS_EN() (false)
181 #define CAM_IPPWORK_IS_EN() (false)
184 #define IS_CIF0() (pcdev->hostid == RK_CAM_PLATFORM_DEV_ID_0)
187 * Driver Version Note
189 *v0.0.x : this driver is 2.6.32 kernel driver;
190 *v0.1.x : this driver is 3.0.8 kernel driver;
192 *v0.x.1 : this driver first support rk2918;
193 *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
194 * and V4L2_PIX_FMT_YUV422P;
195 *v0.x.3 : this driver support VIDIOC_ENUM_FRAMEINTERVALS;
196 *v0.x.4 : this driver support digital zoom;
197 *v0.x.5 : this driver support test framerate and query framerate from board file configuration;
198 *v0.x.6 : this driver improve test framerate method;
199 *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
200 we do crop with cif and do scale with ipp , we will fix this next version.
201 *v0.x.8 : temp version,reinit capture list when setup video buf.
202 *v0.x.9 : 1. add the case of IPP unsupportted ,just cropped by CIF(not do the scale) this version.
203 2. flush workqueue when releas buffer
204 *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
206 2. when the flash is on ,flash off in a fixed time to prevent from flash light too hot.
207 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
208 4. add menu configs for convineuent to customize sensor series
209 *v0.x.b: specify the version is NOT sure stable.
210 *v0.x.c: 1. add cif reset when resolution changed to avoid of collecting data erro
211 2. irq process is splitted to two step.
212 *v0.x.e: fix bugs of early suspend when display_pd is closed.
214 #define RK_CAM_VERSION_CODE KERNEL_VERSION(0, 2, 0xc)
216 /* limit to rk29 hardware capabilities */
217 #define RK_CAM_BUS_PARAM (SOCAM_MASTER |\
218 SOCAM_HSYNC_ACTIVE_HIGH |\
219 SOCAM_HSYNC_ACTIVE_LOW |\
220 SOCAM_VSYNC_ACTIVE_HIGH |\
221 SOCAM_VSYNC_ACTIVE_LOW |\
222 SOCAM_PCLK_SAMPLE_RISING |\
223 SOCAM_PCLK_SAMPLE_FALLING|\
224 SOCAM_DATA_ACTIVE_HIGH |\
225 SOCAM_DATA_ACTIVE_LOW|\
226 SOCAM_DATAWIDTH_8|SOCAM_DATAWIDTH_10|\
227 SOCAM_MCLK_24MHZ |SOCAM_MCLK_48MHZ)
229 #define RK_CAM_W_MIN 48
230 #define RK_CAM_H_MIN 32
231 #define RK_CAM_W_MAX 3856 /* ddl@rock-chips.com : 10M Pixel */
232 #define RK_CAM_H_MAX 2764
233 #define RK_CAM_FRAME_INVAL_INIT 3
234 #define RK_CAM_FRAME_INVAL_DC 3 /* ddl@rock-chips.com : */
235 #define RK30_CAM_FRAME_MEASURE 5
236 extern void videobuf_dma_contig_free(struct videobuf_queue *q, struct videobuf_buffer *buf);
237 extern dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf);
239 /* buffer for one video frame */
240 struct rk_camera_buffer
242 /* common v4l buffer stuff -- must be first */
243 struct videobuf_buffer vb;
244 enum v4l2_mbus_pixelcode code;
247 enum rk_camera_reg_state
255 unsigned int cifCtrl;
256 unsigned int cifCrop;
258 unsigned int cifIntEn;
260 unsigned int cifVirWidth;
261 unsigned int cifScale;
262 // unsigned int VipCrm;
263 enum rk_camera_reg_state Inval;
265 struct rk_camera_work
267 struct videobuf_buffer *vb;
268 struct rk_camera_dev *pcdev;
269 struct work_struct work;
271 struct rk_camera_frmivalenum
273 struct v4l2_frmivalenum fival;
274 struct rk_camera_frmivalenum *nxt;
276 struct rk_camera_frmivalinfo
278 struct soc_camera_device *icd;
279 struct rk_camera_frmivalenum *fival_list;
281 struct rk_camera_zoominfo
283 struct semaphore sem;
288 struct rk_camera_timer{
289 struct rk_camera_dev *pcdev;
290 struct hrtimer timer;
295 struct soc_camera_host soc_host;
297 /* RK2827x is only supposed to handle one camera on its Quick Capture
298 * interface. If anyone ever builds hardware to enable more than
299 * one camera, they will have to modify this driver too */
300 struct soc_camera_device *icd;
302 //************must modify start************/
304 struct clk *aclk_cif;
305 struct clk *hclk_cif;
306 struct clk *cif_clk_in;
307 struct clk *cif_clk_out;
308 //************must modify end************/
310 int frame_inval; /* ddl@rock-chips.com : The first frames is invalidate */
313 unsigned int last_fps;
314 unsigned long frame_interval;
317 unsigned int vipmem_phybase;
318 unsigned int vipmem_size;
319 unsigned int vipmem_bsize;
321 int host_width; //croped size
323 int host_left; //sensor output size ?
329 struct rk29camera_platform_data *pdata;
330 struct resource *res;
331 struct list_head capture;
332 struct rk_camera_zoominfo zoominfo;
336 struct videobuf_buffer *active;
337 struct rk_camera_reg reginfo_suspend;
338 struct workqueue_struct *camera_wq;
339 struct rk_camera_work *camera_work;
340 unsigned int camera_work_count;
341 struct rk_camera_timer fps_timer;
342 struct rk_camera_work camera_reinit_work;
344 rk29_camera_sensor_cb_s icd_cb;
345 struct rk_camera_frmivalinfo icd_frmival[2];
346 // atomic_t to_process_frames;
348 unsigned int reinit_times;
349 struct videobuf_queue *video_vq;
351 struct timeval first_tv;
354 static const struct v4l2_queryctrl rk_camera_controls[] =
356 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
358 .id = V4L2_CID_ZOOM_ABSOLUTE,
359 .type = V4L2_CTRL_TYPE_INTEGER,
360 .name = "DigitalZoom Control",
364 .default_value = 100,
369 static DEFINE_MUTEX(camera_lock);
370 static const char *rk_cam_driver_description = "RK_Camera";
372 static int rk_camera_s_stream(struct soc_camera_device *icd, int enable);
373 static void rk_camera_capture_process(struct work_struct *work);
377 * Videobuf operations
379 static int rk_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
382 struct soc_camera_device *icd = vq->priv_data;
383 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
384 struct rk_camera_dev *pcdev = ici->priv;
385 int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
386 icd->current_fmt->host_fmt);
387 int bytes_per_line_host = soc_mbus_bytes_per_line(pcdev->host_width,
388 icd->current_fmt->host_fmt);
390 dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size);
392 if (bytes_per_line_host < 0)
393 return bytes_per_line_host;
395 /* planar capture requires Y, U and V buffers to be page aligned */
396 //*size = PAGE_ALIGN(bytes_per_line*icd->user_height); /* Y pages UV pages, yuv422*/
397 *size = PAGE_ALIGN(bytes_per_line*icd->user_height); /* Y pages UV pages, yuv422*/
398 pcdev->vipmem_bsize = PAGE_ALIGN(bytes_per_line_host * pcdev->host_height);
400 if (CAM_WORKQUEUE_IS_EN()) {
401 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_OFF
402 if (CAM_IPPWORK_IS_EN())
405 BUG_ON(pcdev->vipmem_size<pcdev->vipmem_bsize);
406 if (*count > pcdev->vipmem_size/pcdev->vipmem_bsize) { /* Buffers must be limited, when this resolution is genered by IPP */
407 *count = pcdev->vipmem_size/pcdev->vipmem_bsize;
410 if ((pcdev->camera_work_count != *count) && pcdev->camera_work) {
411 kfree(pcdev->camera_work);
412 pcdev->camera_work = NULL;
413 pcdev->camera_work_count = 0;
416 if (pcdev->camera_work == NULL) {
418 struct rk_camera_work *wk;
419 pcdev->camera_work = kmalloc(sizeof(struct rk_camera_work)*(*count), GFP_KERNEL);
420 if (pcdev->camera_work == NULL) {
421 RKCAMERA_TR("\n %s kmalloc fail\n", __FUNCTION__);
424 for(;wk_index < *count;wk_index++){
425 wk = pcdev->camera_work+wk_index;
426 INIT_WORK(&wk->work, rk_camera_capture_process);
428 pcdev->camera_work_count = *count;
431 pcdev->video_vq = vq;
432 RKCAMERA_DG("%s..%d.. videobuf size:%d, vipmem_buf size:%d, count:%d \n",__FUNCTION__,__LINE__, *size,pcdev->vipmem_size, *count);
436 static void rk_videobuf_free(struct videobuf_queue *vq, struct rk_camera_buffer *buf)
438 struct soc_camera_device *icd = vq->priv_data;
440 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
441 &buf->vb, buf->vb.baddr, buf->vb.bsize);
443 /* ddl@rock-chips.com: buf_release called soc_camera_streamoff and soc_camera_close*/
444 if (buf->vb.state == VIDEOBUF_NEEDS_INIT)
450 * This waits until this buffer is out of danger, i.e., until it is no
451 * longer in STATE_QUEUED or STATE_ACTIVE
453 //videobuf_waiton(vq, &buf->vb, 0, 0);
454 videobuf_dma_contig_free(vq, &buf->vb);
455 dev_dbg(&icd->dev, "%s freed\n", __func__);
456 buf->vb.state = VIDEOBUF_NEEDS_INIT;
459 static int rk_videobuf_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, enum v4l2_field field)
461 struct soc_camera_device *icd = vq->priv_data;
462 struct rk_camera_buffer *buf;
464 int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
465 icd->current_fmt->host_fmt);
466 if (bytes_per_line < 0)
467 return bytes_per_line;
469 buf = container_of(vb, struct rk_camera_buffer, vb);
471 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
472 vb, vb->baddr, vb->bsize);
474 //RK29CAMERA_TR("\n%s..%d.. \n",__FUNCTION__,__LINE__);
476 /* Added list head initialization on alloc */
477 WARN_ON(!list_empty(&vb->queue));
479 /* This can be useful if you want to see if we actually fill
480 * the buffer with something */
481 //memset((void *)vb->baddr, 0xaa, vb->bsize);
483 BUG_ON(NULL == icd->current_fmt);
485 if (buf->code != icd->current_fmt->code ||
486 vb->width != icd->user_width ||
487 vb->height != icd->user_height ||
488 vb->field != field) {
489 buf->code = icd->current_fmt->code;
490 vb->width = icd->user_width;
491 vb->height = icd->user_height;
493 vb->state = VIDEOBUF_NEEDS_INIT;
496 vb->size = bytes_per_line*vb->height; /* ddl@rock-chips.com : fmt->depth is coorect */
497 if (0 != vb->baddr && vb->bsize < vb->size) {
502 if (vb->state == VIDEOBUF_NEEDS_INIT) {
503 ret = videobuf_iolock(vq, vb, NULL);
507 vb->state = VIDEOBUF_PREPARED;
509 //RK29CAMERA_TR("\n%s..%d.. \n",__FUNCTION__,__LINE__);
512 rk_videobuf_free(vq, buf);
517 static inline void rk_videobuf_capture(struct videobuf_buffer *vb,struct rk_camera_dev *rk_pcdev)
519 unsigned int y_addr,uv_addr;
520 struct rk_camera_dev *pcdev = rk_pcdev;
523 if (CAM_WORKQUEUE_IS_EN()) {
524 y_addr = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
525 uv_addr = y_addr + pcdev->host_width*pcdev->host_height;
526 if (y_addr > (pcdev->vipmem_phybase + pcdev->vipmem_size - pcdev->vipmem_bsize)) {
527 RKCAMERA_TR("vipmem for IPP is overflow! %dx%d -> %dx%d vb_index:%d\n",pcdev->host_width,pcdev->host_height,
528 pcdev->icd->user_width,pcdev->icd->user_height, vb->i);
533 uv_addr = y_addr + vb->width * vb->height;
535 write_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y, y_addr);
536 write_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV, uv_addr);
537 //printk("y_addr = 0x%x, uv_addr = 0x%x \n",read_cif_reg(pcdev->base, CIF_CIF_FRM0_ADDR_Y),read_cif_reg(pcdev->base, CIF_CIF_FRM0_ADDR_UV));
538 write_cif_reg(pcdev->base,CIF_CIF_FRM1_ADDR_Y, y_addr);
539 write_cif_reg(pcdev->base,CIF_CIF_FRM1_ADDR_UV, uv_addr);
540 write_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS, 0x00000002);//frame1 has been ready to receive data,frame 2 is not used
543 /* Locking: Caller holds q->irqlock */
544 static void rk_videobuf_queue(struct videobuf_queue *vq,
545 struct videobuf_buffer *vb)
547 struct soc_camera_device *icd = vq->priv_data;
548 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
549 struct rk_camera_dev *pcdev = ici->priv;
551 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
552 vb, vb->baddr, vb->bsize);
554 vb->state = VIDEOBUF_QUEUED;
555 if (list_empty(&pcdev->capture)) {
556 list_add_tail(&vb->queue, &pcdev->capture);
558 if (list_entry(pcdev->capture.next, struct videobuf_buffer, queue) != vb)
559 list_add_tail(&vb->queue, &pcdev->capture);
561 BUG(); /* ddl@rock-chips.com : The same videobuffer queue again */
563 if (!pcdev->active) {
565 rk_videobuf_capture(vb,pcdev);
568 static int rk_pixfmt2ippfmt(unsigned int pixfmt, int *ippfmt)
572 case V4L2_PIX_FMT_NV16:
573 case V4L2_PIX_FMT_NV61:
575 *ippfmt = IPP_Y_CBCR_H2V1;
578 case V4L2_PIX_FMT_NV12:
579 case V4L2_PIX_FMT_NV21:
581 *ippfmt = IPP_Y_CBCR_H2V2;
585 goto rk_pixfmt2ippfmt_err;
589 rk_pixfmt2ippfmt_err:
592 static void rk_camera_capture_process(struct work_struct *work)
594 struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
595 struct videobuf_buffer *vb = camera_work->vb;
596 struct rk_camera_dev *pcdev = camera_work->pcdev;
597 struct rk29_ipp_req ipp_req;
598 unsigned long int flags;
599 int src_y_offset,src_uv_offset,dst_y_offset,dst_uv_offset,src_y_size,dst_y_size;
600 int scale_times,w,h,vipdata_base;
604 * IPP Dest image resolution is 2047x1088, so scale operation break up some times
606 if ((pcdev->icd->user_width > 0x7f0) || (pcdev->icd->user_height > 0x430)) {
607 scale_times = MAX((pcdev->icd->user_width/0x7f0),(pcdev->icd->user_height/0x430));
612 memset(&ipp_req, 0, sizeof(struct rk29_ipp_req));
615 down(&pcdev->zoominfo.sem);
616 ipp_req.timeout = 3000;
617 ipp_req.flag = IPP_ROT_0;
618 // if(pcdev->icd->user_width != pcdev->zoominfo.vir_width)
619 ipp_req.store_clip_mode =1;
620 ipp_req.src0.w = pcdev->zoominfo.a.c.width/scale_times;
621 ipp_req.src0.h = pcdev->zoominfo.a.c.height/scale_times;
622 //ipp_req.src_vir_w = pcdev->zoominfo.a.c.width;
623 ipp_req.src_vir_w = pcdev->zoominfo.vir_width;
624 rk_pixfmt2ippfmt(pcdev->pixfmt, &ipp_req.src0.fmt);
625 ipp_req.dst0.w = pcdev->icd->user_width/scale_times;
626 ipp_req.dst0.h = pcdev->icd->user_height/scale_times;
627 ipp_req.dst_vir_w = pcdev->icd->user_width;
628 rk_pixfmt2ippfmt(pcdev->pixfmt, &ipp_req.dst0.fmt);
629 vipdata_base = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
630 //src_y_size = pcdev->zoominfo.a.c.width*pcdev->zoominfo.a.c.height;
631 src_y_size = pcdev->host_width*pcdev->host_height; //vipmem
632 dst_y_size = pcdev->icd->user_width*pcdev->icd->user_height;
633 for (h=0; h<scale_times; h++) {
634 for (w=0; w<scale_times; w++) {
636 src_y_offset = (pcdev->zoominfo.a.c.top + h*pcdev->zoominfo.a.c.height/scale_times)* pcdev->host_width
637 + pcdev->zoominfo.a.c.left + w*pcdev->zoominfo.a.c.width/scale_times;
638 src_uv_offset = (pcdev->zoominfo.a.c.top + h*pcdev->zoominfo.a.c.height/scale_times)* pcdev->host_width/2
639 + pcdev->zoominfo.a.c.left + w*pcdev->zoominfo.a.c.width/scale_times;
641 dst_y_offset = pcdev->icd->user_width*pcdev->icd->user_height*h/scale_times + pcdev->icd->user_width*w/scale_times;
642 dst_uv_offset = pcdev->icd->user_width*pcdev->icd->user_height*h/scale_times/2 + pcdev->icd->user_width*w/scale_times;
644 ipp_req.src0.YrgbMst = vipdata_base + src_y_offset;
645 ipp_req.src0.CbrMst = vipdata_base + src_y_size + src_uv_offset;
646 ipp_req.dst0.YrgbMst = vb->boff + dst_y_offset;
647 ipp_req.dst0.CbrMst = vb->boff + dst_y_size + dst_uv_offset;
648 // printk("ipp_req.src0.YrgbMst = 0x%x , ipp_req.src0.CbrMst = 0x%x\n",ipp_req.src0.YrgbMst,ipp_req.src0.CbrMst);
649 // printk("ipp_req.dst0.YrgbMst = 0x%x , ipp_req.dst0.CbrMst = 0x%x\n",ipp_req.dst0.YrgbMst,ipp_req.dst0.CbrMst);
650 // printk("%dx%d@(%d,%d)->%dx%d\n",pcdev->zoominfo.a.c.width,pcdev->zoominfo.a.c.height,pcdev->zoominfo.a.c.left,pcdev->zoominfo.a.c.top,pcdev->icd->user_width,pcdev->icd->user_height);
651 // printk("ipp_req.src_vir_w:0x%x ipp_req.dst_vir_w :0x%x\n",ipp_req.src_vir_w ,ipp_req.dst_vir_w);
652 while(ipp_times-- > 0)
654 if (ipp_blit_sync(&ipp_req)){
655 RKCAMERA_TR("ipp do erro,do again,ipp_times = %d!\n",ipp_times);
663 spin_lock_irqsave(&pcdev->lock, flags);
664 vb->state = VIDEOBUF_NEEDS_INIT;
665 spin_unlock_irqrestore(&pcdev->lock, flags);
666 RKCAMERA_TR("Capture image(vb->i:0x%x) which IPP operated is error:\n",vb->i);
667 RKCAMERA_TR("widx:%d hidx:%d ",w,h);
668 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);
669 RKCAMERA_TR("ipp_req.src0.YrgbMst:0x%x ipp_req.src0.CbrMst:0x%x \n", ipp_req.src0.YrgbMst,ipp_req.src0.CbrMst);
670 RKCAMERA_TR("ipp_req.src0.w:0x%x ipp_req.src0.h:0x%x \n",ipp_req.src0.w,ipp_req.src0.h);
671 RKCAMERA_TR("ipp_req.src0.fmt:0x%x\n",ipp_req.src0.fmt);
672 RKCAMERA_TR("ipp_req.dst0.YrgbMst:0x%x ipp_req.dst0.CbrMst:0x%x \n",ipp_req.dst0.YrgbMst,ipp_req.dst0.CbrMst);
673 RKCAMERA_TR("ipp_req.dst0.w:0x%x ipp_req.dst0.h:0x%x \n",ipp_req.dst0.w ,ipp_req.dst0.h);
674 RKCAMERA_TR("ipp_req.dst0.fmt:0x%x\n",ipp_req.dst0.fmt);
675 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);
676 RKCAMERA_TR("ipp_req.timeout:0x%x ipp_req.flag :0x%x\n",ipp_req.timeout,ipp_req.flag);
683 if (pcdev->icd_cb.sensor_cb)
684 (pcdev->icd_cb.sensor_cb)(vb);
686 up(&pcdev->zoominfo.sem);
687 wake_up(&(camera_work->vb->done));
690 static irqreturn_t rk_camera_irq(int irq, void *data)
692 struct rk_camera_dev *pcdev = data;
693 struct videobuf_buffer *vb;
694 struct rk_camera_work *wk;
696 unsigned long tmp_intstat;
697 unsigned long tmp_cifctrl;
701 tmp_intstat = read_cif_reg(pcdev->base,CIF_CIF_INTSTAT);
702 tmp_cifctrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
703 if(pcdev->stop_cif == true)
705 printk("cif has stopped by app,needn't to deal this irq\n");
706 write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF); /* clear vip interrupte single */
709 if ((tmp_intstat & 0x0200) /*&& ((tmp_intstat & 0x1)==0)*/){//bit9 =1 ,bit0 = 0
710 write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0x0200); /* clear vip interrupte single */
711 if(tmp_cifctrl & ENABLE_CAPTURE)
712 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl & ~ENABLE_CAPTURE));
716 /* ddl@rock-chps.com : Current VIP is run in One Frame Mode, Frame 1 is validate */
717 if (read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS) & 0x01) {
718 write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0x01); /* clear vip interrupte single */
720 do_gettimeofday(&pcdev->first_tv);
724 goto RK_CAMERA_IRQ_END;
725 if (pcdev->frame_inval>0) {
726 pcdev->frame_inval--;
727 rk_videobuf_capture(pcdev->active,pcdev);
728 goto RK_CAMERA_IRQ_END;
729 } else if (pcdev->frame_inval) {
730 RKCAMERA_TR("frame_inval : %0x",pcdev->frame_inval);
731 pcdev->frame_inval = 0;
733 if(pcdev->fps == RK30_CAM_FRAME_MEASURE) {
734 do_gettimeofday(&tv);
735 pcdev->frame_interval = ((tv.tv_sec*1000000 + tv.tv_usec) - (pcdev->first_tv.tv_sec*1000000 + pcdev->first_tv.tv_usec))
736 /(RK30_CAM_FRAME_MEASURE-1);
740 printk("no acticve buffer!!!\n");
741 goto RK_CAMERA_IRQ_END;
743 /* ddl@rock-chips.com : this vb may be deleted from queue */
744 if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) {
745 list_del_init(&vb->queue);
747 pcdev->active = NULL;
748 if (!list_empty(&pcdev->capture)) {
749 pcdev->active = list_entry(pcdev->capture.next, struct videobuf_buffer, queue);
750 if (pcdev->active && (pcdev->active->state == VIDEOBUF_QUEUED)) {
751 rk_videobuf_capture(pcdev->active,pcdev);
753 else if(pcdev->active){
754 printk("vb state is wrong ,del it \n");
755 list_del_init(&(pcdev->active->queue));
756 pcdev->active->state = VIDEOBUF_NEEDS_INIT;
757 wake_up(&pcdev->active->done);
758 pcdev->active = NULL;
762 if (pcdev->active == NULL) {
763 RKCAMERA_DG("%s video_buf queue is empty!\n",__FUNCTION__);
766 if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) {
767 vb->state = VIDEOBUF_DONE;
768 do_gettimeofday(&vb->ts);
771 if (CAM_WORKQUEUE_IS_EN()) {
772 wk = pcdev->camera_work + vb->i;
773 //INIT_WORK(&(wk->work), rk_camera_capture_process);
776 queue_work(pcdev->camera_wq, &(wk->work));
784 if((tmp_cifctrl & ENABLE_CAPTURE) == 0)
785 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl | ENABLE_CAPTURE));
790 static void rk_videobuf_release(struct videobuf_queue *vq,
791 struct videobuf_buffer *vb)
793 struct rk_camera_buffer *buf = container_of(vb, struct rk_camera_buffer, vb);
794 struct soc_camera_device *icd = vq->priv_data;
795 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
796 struct rk_camera_dev *pcdev = ici->priv;
798 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
799 vb, vb->baddr, vb->bsize);
803 case VIDEOBUF_ACTIVE:
804 dev_dbg(&icd->dev, "%s (active)\n", __func__);
806 case VIDEOBUF_QUEUED:
807 dev_dbg(&icd->dev, "%s (queued)\n", __func__);
809 case VIDEOBUF_PREPARED:
810 dev_dbg(&icd->dev, "%s (prepared)\n", __func__);
813 dev_dbg(&icd->dev, "%s (unknown)\n", __func__);
818 // printk("flush work queue.......\n");
819 flush_workqueue(pcdev->camera_wq);
821 if (vb == pcdev->active) {
822 RKCAMERA_DG("%s Wait for this video buf(0x%x) write finished!\n ",__FUNCTION__,(unsigned int)vb);
823 interruptible_sleep_on_timeout(&vb->done, 100);
824 flush_workqueue(pcdev->camera_wq);
825 RKCAMERA_DG("%s This video buf(0x%x) write finished, release now!!\n",__FUNCTION__,(unsigned int)vb);
827 rk_videobuf_free(vq, buf);
830 static struct videobuf_queue_ops rk_videobuf_ops =
832 .buf_setup = rk_videobuf_setup,
833 .buf_prepare = rk_videobuf_prepare,
834 .buf_queue = rk_videobuf_queue,
835 .buf_release = rk_videobuf_release,
838 static void rk_camera_init_videobuf(struct videobuf_queue *q,
839 struct soc_camera_device *icd)
841 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
842 struct rk_camera_dev *pcdev = ici->priv;
844 /* We must pass NULL as dev pointer, then all pci_* dma operations
845 * transform to normal dma_* ones. */
846 videobuf_queue_dma_contig_init(q,
848 ici->v4l2_dev.dev, &pcdev->lock,
849 V4L2_BUF_TYPE_VIDEO_CAPTURE,
851 sizeof(struct rk_camera_buffer),
852 icd,&icd->video_lock);
854 static int rk_camera_activate(struct rk_camera_dev *pcdev, struct soc_camera_device *icd)
858 if(!pcdev->aclk_cif || !pcdev->hclk_cif || !pcdev->cif_clk_in || !pcdev->cif_clk_out){
859 RKCAMERA_TR(KERN_ERR "failed to get cif clock source\n");
861 goto RK_CAMERA_ACTIVE_ERR;
864 clk_enable(pcdev->pd_cif);
865 clk_enable(pcdev->aclk_cif);
867 clk_enable(pcdev->hclk_cif);
868 clk_enable(pcdev->cif_clk_in);
870 //if (icd->ops->query_bus_param) /* ddl@rock-chips.com : Query Sensor's xclk */
871 //sensor_bus_flags = icd->ops->query_bus_param(icd);
872 clk_enable(pcdev->cif_clk_out);
873 clk_set_rate(pcdev->cif_clk_out,RK_SENSOR_24MHZ);
876 //soft reset the registers
877 #if 0 //has somthing wrong when suspend and resume now
879 printk("before set cru register reset cif0 0x%x\n\n",read_cru_reg(CRU_CIF_RST_REG30));
882 printk("CIF_CIF_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CTRL));
883 printk("CIF_CIF_INTEN = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTEN));
884 printk("CIF_CIF_INTSTAT = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTSTAT));
885 printk("CIF_CIF_FOR = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_FOR));
886 printk("CIF_CIF_CROP = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CROP));
887 printk("CIF_CIF_SET_SIZE = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE));
888 printk("CIF_CIF_SCL_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL));
889 printk("CRU_PCLK_REG30 = 0X%x\n",read_cru_reg(CRU_PCLK_REG30));
890 printk("CIF_CIF_LAST_LINE = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_LINE));
892 printk("CIF_CIF_LAST_PIX = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_PIX));
893 printk("CIF_CIF_VIR_LINE_WIDTH = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH));
894 printk("CIF_CIF_LINE_NUM_ADDR = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LINE_NUM_ADDR));
895 printk("CIF_CIF_FRM0_ADDR_Y = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y));
896 printk("CIF_CIF_FRM0_ADDR_UV = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV));
897 printk("CIF_CIF_FRAME_STATUS = 0X%x\n\n",read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS));
901 write_cru_reg(CRU_CIF_RST_REG30,(/*read_cru_reg(CRU_CIF_RST_REG30)|*/MASK_RST_CIF0|RQUEST_RST_CIF0 ));
902 printk("set cru register reset cif0 0x%x\n",read_cru_reg(CRU_CIF_RST_REG30));
903 write_cru_reg(CRU_CIF_RST_REG30,(read_cru_reg(CRU_CIF_RST_REG30)&(~RQUEST_RST_CIF0)) | MASK_RST_CIF0);
905 printk("clean cru register reset cif0 0x%x\n",read_cru_reg(CRU_CIF_RST_REG30));
907 write_cru_reg(CRU_CIF_RST_REG30,MASK_RST_CIF1|RQUEST_RST_CIF1 | (read_cru_reg(CRU_CIF_RST_REG30)));
908 write_cru_reg(CRU_CIF_RST_REG30,(read_cru_reg(CRU_CIF_RST_REG30)&(~RQUEST_RST_CIF1)) | MASK_RST_CIF1);
911 write_cif_reg(pcdev->base,CIF_CIF_CTRL,AXI_BURST_16|MODE_ONEFRAME|DISABLE_CAPTURE); /* ddl@rock-chips.com : vip ahb burst 16 */
912 write_cif_reg(pcdev->base,CIF_CIF_INTEN, 0x01); //capture complete interrupt enable
913 RKCAMERA_DG("%s..%d.. CIF_CIF_CTRL = 0x%x\n",__FUNCTION__,__LINE__,read_cif_reg(pcdev->base, CIF_CIF_CTRL));
915 RK_CAMERA_ACTIVE_ERR:
919 static void rk_camera_deactivate(struct rk_camera_dev *pcdev)
921 //pcdev->active = NULL;
922 // printk("rk_camera_deactivate enter\n");
923 clk_disable(pcdev->aclk_cif);
925 clk_disable(pcdev->hclk_cif);
926 clk_disable(pcdev->cif_clk_in);
927 clk_disable(pcdev->cif_clk_out);
928 clk_disable(pcdev->pd_cif);
932 /* The following two functions absolutely depend on the fact, that
933 * there can be only one camera on RK28 quick capture interface */
934 static int rk_camera_add_device(struct soc_camera_device *icd)
936 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
937 struct rk_camera_dev *pcdev = ici->priv;
938 struct device *control = to_soc_camera_control(icd);
939 struct v4l2_subdev *sd;
941 struct rk_camera_frmivalenum *fival_list,*fival_nxt;
943 mutex_lock(&camera_lock);
950 dev_info(&icd->dev, "RK Camera driver attached to camera%d(%s)\n",
951 icd->devnum,dev_name(icd->pdev));
953 pcdev->frame_inval = RK_CAM_FRAME_INVAL_INIT;
954 pcdev->active = NULL;
956 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
957 pcdev->zoominfo.zoom_rate = 100;
958 pcdev->fps_timer.istarted = false;
960 /* ddl@rock-chips.com: capture list must be reset, because this list may be not empty,
961 * if app havn't dequeue all videobuf before close camera device;
963 INIT_LIST_HEAD(&pcdev->capture);
965 ret = rk_camera_activate(pcdev,icd);
968 /* ddl@rock-chips.com : v4l2_subdev is not created when ici->ops->add called in soc_camera_probe */
970 sd = dev_get_drvdata(control);
971 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_IOREQUEST,(void*)pcdev->pdata);
973 ret = v4l2_subdev_call(sd,core, init, 0);
977 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_CB_REGISTER,(void*)(&pcdev->icd_cb));
983 for (i=0; i<2; i++) {
984 if (pcdev->icd_frmival[i].icd == icd)
986 if (pcdev->icd_frmival[i].icd == NULL) {
987 pcdev->icd_frmival[i].icd = icd;
991 if (icd_catch == 0) {
992 fival_list = pcdev->icd_frmival[0].fival_list;
993 fival_nxt = fival_list;
994 while(fival_nxt != NULL) {
995 fival_nxt = fival_list->nxt;
997 fival_list = fival_nxt;
999 pcdev->icd_frmival[0].icd = icd;
1000 pcdev->icd_frmival[0].fival_list = kzalloc(sizeof(struct rk_camera_frmivalenum),GFP_KERNEL);
1002 RKCAMERA_TR("%s..%d.. \n",__FUNCTION__,__LINE__);
1004 mutex_unlock(&camera_lock);
1008 static void rk_camera_remove_device(struct soc_camera_device *icd)
1010 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1011 struct rk_camera_dev *pcdev = ici->priv;
1012 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1014 mutex_lock(&camera_lock);
1015 BUG_ON(icd != pcdev->icd);
1017 dev_info(&icd->dev, "RK Camera driver detached from camera%d(%s)\n",
1018 icd->devnum,dev_name(icd->pdev));
1020 /* ddl@rock-chips.com: Application will call VIDIOC_STREAMOFF before close device, but
1021 stream may be turn on again before close device, if suspend and resume happened. */
1022 if (read_cif_reg(pcdev->base,CIF_CIF_CTRL) & ENABLE_CAPTURE) {
1023 rk_camera_s_stream(icd,0);
1026 //soft reset the registers
1027 #if 0 //has somthing wrong when suspend and resume now
1029 write_cru_reg(CRU_CIF_RST_REG30,MASK_RST_CIF0|RQUEST_RST_CIF0 | (read_cru_reg(CRU_CIF_RST_REG30)));
1030 write_cru_reg(CRU_CIF_RST_REG30,(read_cru_reg(CRU_CIF_RST_REG30)&(~RQUEST_RST_CIF0)) | MASK_RST_CIF0);
1032 write_cru_reg(CRU_CIF_RST_REG30,MASK_RST_CIF1|RQUEST_RST_CIF1 | (read_cru_reg(CRU_CIF_RST_REG30)));
1033 write_cru_reg(CRU_CIF_RST_REG30,(read_cru_reg(CRU_CIF_RST_REG30)&(~RQUEST_RST_CIF1)) | MASK_RST_CIF1);
1036 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_DEACTIVATE,NULL);
1037 //if stream off is not been executed,timer is running.
1038 if(pcdev->fps_timer.istarted){
1039 hrtimer_cancel(&pcdev->fps_timer.timer);
1040 pcdev->fps_timer.istarted = false;
1042 flush_work(&(pcdev->camera_reinit_work.work));
1043 flush_workqueue((pcdev->camera_wq));
1045 if (pcdev->camera_work) {
1046 kfree(pcdev->camera_work);
1047 pcdev->camera_work = NULL;
1048 pcdev->camera_work_count = 0;
1050 rk_camera_deactivate(pcdev);
1051 pcdev->active = NULL;
1053 pcdev->icd_cb.sensor_cb = NULL;
1054 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
1055 /* ddl@rock-chips.com: capture list must be reset, because this list may be not empty,
1056 * if app havn't dequeue all videobuf before close camera device;
1058 INIT_LIST_HEAD(&pcdev->capture);
1060 mutex_unlock(&camera_lock);
1061 RKCAMERA_DG("%s exit\n",__FUNCTION__);
1065 static int rk_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
1067 unsigned long bus_flags, camera_flags, common_flags;
1068 unsigned int cif_ctrl_val = 0;
1069 const struct soc_mbus_pixelfmt *fmt;
1071 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1072 struct rk_camera_dev *pcdev = ici->priv;
1073 RKCAMERA_DG("%s..%d..\n",__FUNCTION__,__LINE__);
1075 fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code);
1079 bus_flags = RK_CAM_BUS_PARAM;
1080 /* If requested data width is supported by the platform, use it */
1081 switch (fmt->bits_per_sample) {
1083 if (!(bus_flags & SOCAM_DATAWIDTH_10))
1087 if (!(bus_flags & SOCAM_DATAWIDTH_9))
1091 if (!(bus_flags & SOCAM_DATAWIDTH_8))
1098 if (icd->ops->query_bus_param)
1099 camera_flags = icd->ops->query_bus_param(icd);
1103 common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
1104 if (!common_flags) {
1106 goto RK_CAMERA_SET_BUS_PARAM_END;
1109 ret = icd->ops->set_bus_param(icd, common_flags);
1111 goto RK_CAMERA_SET_BUS_PARAM_END;
1113 cif_ctrl_val = read_cif_reg(pcdev->base,CIF_CIF_FOR);
1114 RKCAMERA_DG("%s..%d..cif_ctrl_val = 0x%x\n",__FUNCTION__,__LINE__,cif_ctrl_val);
1115 if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) {
1118 write_cru_reg(CRU_PCLK_REG30, read_cru_reg(CRU_PCLK_REG30) | ENANABLE_INVERT_PCLK_CIF0);
1119 RKCAMERA_DG("enable cif0 pclk invert\n");
1123 write_cru_reg(CRU_PCLK_REG30, read_cru_reg(CRU_PCLK_REG30) | ENANABLE_INVERT_PCLK_CIF1);
1124 RKCAMERA_DG("enable cif1 pclk invert\n");
1129 write_cru_reg(CRU_PCLK_REG30, (read_cru_reg(CRU_PCLK_REG30) & 0xFFFFEFF ) | DISABLE_INVERT_PCLK_CIF0);
1130 RKCAMERA_DG("diable cif0 pclk invert\n");
1134 write_cru_reg(CRU_PCLK_REG30, (read_cru_reg(CRU_PCLK_REG30) & 0xFFFEFFF) | DISABLE_INVERT_PCLK_CIF1);
1135 RKCAMERA_DG("diable cif1 pclk invert\n");
1138 if (common_flags & SOCAM_HSYNC_ACTIVE_LOW) {
1139 cif_ctrl_val |= HSY_LOW_ACTIVE;
1141 cif_ctrl_val &= ~HSY_LOW_ACTIVE;
1143 if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH) {
1144 cif_ctrl_val |= VSY_HIGH_ACTIVE;
1146 cif_ctrl_val &= ~VSY_HIGH_ACTIVE;
1149 /* ddl@rock-chips.com : Don't enable capture here, enable in stream_on */
1150 //vip_ctrl_val |= ENABLE_CAPTURE;
1151 write_cif_reg(pcdev->base,CIF_CIF_FOR, cif_ctrl_val);
1152 RKCAMERA_DG("%s..ctrl:0x%x CIF_CIF_FOR=%x \n",__FUNCTION__,cif_ctrl_val,read_cif_reg(pcdev->base,CIF_CIF_FOR));
1154 RK_CAMERA_SET_BUS_PARAM_END:
1156 RKCAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
1160 static int rk_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
1162 unsigned long bus_flags, camera_flags;
1165 bus_flags = RK_CAM_BUS_PARAM;
1166 if (icd->ops->query_bus_param) {
1167 camera_flags = icd->ops->query_bus_param(icd);
1171 ret = soc_camera_bus_param_compatible(camera_flags, bus_flags) ;
1174 dev_warn(icd->dev.parent,
1175 "Flags incompatible: camera %lx, host %lx\n",
1176 camera_flags, bus_flags);
1180 static const struct soc_mbus_pixelfmt rk_camera_formats[] = {
1182 .fourcc = V4L2_PIX_FMT_NV12,
1183 .name = "YUV420 NV12",
1184 .bits_per_sample = 8,
1185 .packing = SOC_MBUS_PACKING_1_5X8,
1186 .order = SOC_MBUS_ORDER_LE,
1188 .fourcc = V4L2_PIX_FMT_NV16,
1189 .name = "YUV422 NV16",
1190 .bits_per_sample = 8,
1191 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1192 .order = SOC_MBUS_ORDER_LE,
1194 .fourcc = V4L2_PIX_FMT_NV21,
1195 .name = "YUV420 NV21",
1196 .bits_per_sample = 8,
1197 .packing = SOC_MBUS_PACKING_1_5X8,
1198 .order = SOC_MBUS_ORDER_LE,
1200 .fourcc = V4L2_PIX_FMT_NV61,
1201 .name = "YUV422 NV61",
1202 .bits_per_sample = 8,
1203 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1204 .order = SOC_MBUS_ORDER_LE,
1208 static void rk_camera_setup_format(struct soc_camera_device *icd, __u32 host_pixfmt, enum v4l2_mbus_pixelcode icd_code, struct v4l2_rect *rect)
1210 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1211 struct rk_camera_dev *pcdev = ici->priv;
1212 unsigned int cif_fs = 0,cif_crop = 0;
1213 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;
1214 switch (host_pixfmt)
1216 case V4L2_PIX_FMT_NV16:
1217 cif_fmt_val &= ~YUV_OUTPUT_422;
1218 cif_fmt_val &= ~UV_STORAGE_ORDER_UVUV;
1219 pcdev->frame_inval = RK_CAM_FRAME_INVAL_DC;
1220 pcdev->pixfmt = host_pixfmt;
1222 case V4L2_PIX_FMT_NV61:
1223 cif_fmt_val &= ~YUV_OUTPUT_422;
1224 cif_fmt_val |= UV_STORAGE_ORDER_VUVU;
1225 pcdev->frame_inval = RK_CAM_FRAME_INVAL_DC;
1226 pcdev->pixfmt = host_pixfmt;
1228 case V4L2_PIX_FMT_NV12:
1229 cif_fmt_val |= YUV_OUTPUT_420;
1230 cif_fmt_val &= ~UV_STORAGE_ORDER_UVUV;
1231 if (pcdev->frame_inval != RK_CAM_FRAME_INVAL_INIT)
1232 pcdev->frame_inval = RK_CAM_FRAME_INVAL_INIT;
1233 pcdev->pixfmt = host_pixfmt;
1235 case V4L2_PIX_FMT_NV21:
1236 cif_fmt_val |= YUV_OUTPUT_420;
1237 cif_fmt_val |= UV_STORAGE_ORDER_VUVU;
1238 if (pcdev->frame_inval != RK_CAM_FRAME_INVAL_INIT)
1239 pcdev->frame_inval = RK_CAM_FRAME_INVAL_INIT;
1240 pcdev->pixfmt = host_pixfmt;
1242 default: /* ddl@rock-chips.com : vip output format is hold when pixfmt is invalidate */
1243 cif_fmt_val |= YUV_OUTPUT_422;
1248 case V4L2_MBUS_FMT_UYVY8_2X8:
1249 cif_fmt_val = YUV_INPUT_ORDER_UYVY(cif_fmt_val);
1251 case V4L2_MBUS_FMT_YUYV8_2X8:
1252 cif_fmt_val = YUV_INPUT_ORDER_YUYV(cif_fmt_val);
1254 case V4L2_MBUS_FMT_YVYU8_2X8:
1255 cif_fmt_val = YUV_INPUT_ORDER_YVYU(cif_fmt_val);
1257 case V4L2_MBUS_FMT_VYUY8_2X8:
1258 cif_fmt_val = YUV_INPUT_ORDER_VYUY(cif_fmt_val);
1261 cif_fmt_val = YUV_INPUT_ORDER_YUYV(cif_fmt_val);
1268 // pmu_set_idle_request(IDLE_REQ_VIO, true);
1269 cru_set_soft_reset(SOFT_RST_CIF0, true);
1271 cru_set_soft_reset(SOFT_RST_CIF0, false);
1272 // pmu_set_idle_request(IDLE_REQ_VIO, false);
1275 // pmu_set_idle_request(IDLE_REQ_VIO, true);
1276 cru_set_soft_reset(SOFT_RST_CIF1, true);
1278 cru_set_soft_reset(SOFT_RST_CIF1, false);
1279 // pmu_set_idle_request(IDLE_REQ_VIO, false);
1282 write_cif_reg(pcdev->base,CIF_CIF_CTRL,AXI_BURST_16|MODE_ONEFRAME|DISABLE_CAPTURE); /* ddl@rock-chips.com : vip ahb burst 16 */
1283 write_cif_reg(pcdev->base,CIF_CIF_INTEN, 0x01|0x200); //capture complete interrupt enable
1285 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 */
1287 // read_cif_reg(pcdev->base,CIF_CIF_INTSTAT); /* clear vip interrupte single */
1288 write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF);
1289 if((read_cif_reg(pcdev->base,CIF_CIF_CTRL) & MODE_PINGPONG)
1290 ||(read_cif_reg(pcdev->base,CIF_CIF_CTRL) & MODE_LINELOOP)) // it is one frame mode
1294 else{ // this is one frame mode
1295 cif_crop = (rect->left+ (rect->top<<16));
1296 cif_fs = ((rect->width ) + (rect->height<<16));
1298 RKCAMERA_TR("%s..%d.. \n",__FUNCTION__,__LINE__);
1300 write_cif_reg(pcdev->base,CIF_CIF_CROP, cif_crop);
1301 write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, cif_fs);
1302 write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH, rect->width);
1303 write_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS, 0x00000003);
1305 write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL,0x10);
1306 //pcdev->host_width = rect->width;
1307 // pcdev->host_height = rect->height;
1308 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));
1312 static int rk_camera_get_formats(struct soc_camera_device *icd, unsigned int idx,
1313 struct soc_camera_format_xlate *xlate)
1315 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1316 struct device *dev = icd->dev.parent;
1317 int formats = 0, ret;
1318 enum v4l2_mbus_pixelcode code;
1319 const struct soc_mbus_pixelfmt *fmt;
1321 ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
1323 /* No more formats */
1326 fmt = soc_mbus_get_fmtdesc(code);
1328 dev_err(dev, "Invalid format code #%u: %d\n", idx, code);
1332 ret = rk_camera_try_bus_param(icd, fmt->bits_per_sample);
1337 case V4L2_MBUS_FMT_UYVY8_2X8:
1338 case V4L2_MBUS_FMT_YUYV8_2X8:
1339 case V4L2_MBUS_FMT_YVYU8_2X8:
1340 case V4L2_MBUS_FMT_VYUY8_2X8:
1343 xlate->host_fmt = &rk_camera_formats[0];
1346 dev_dbg(dev, "Providing format %s using code %d\n",
1347 rk_camera_formats[0].name,code);
1352 xlate->host_fmt = &rk_camera_formats[1];
1355 dev_dbg(dev, "Providing format %s using code %d\n",
1356 rk_camera_formats[1].name,code);
1361 xlate->host_fmt = &rk_camera_formats[2];
1364 dev_dbg(dev, "Providing format %s using code %d\n",
1365 rk_camera_formats[2].name,code);
1370 xlate->host_fmt = &rk_camera_formats[3];
1373 dev_dbg(dev, "Providing format %s using code %d\n",
1374 rk_camera_formats[3].name,code);
1384 static void rk_camera_put_formats(struct soc_camera_device *icd)
1389 static int rk_camera_set_crop(struct soc_camera_device *icd,
1390 struct v4l2_crop *a)
1392 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1393 struct v4l2_mbus_framefmt mf;
1394 u32 fourcc = icd->current_fmt->host_fmt->fourcc;
1397 ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
1401 if ((mf.width < (a->c.left + a->c.width)) || (mf.height < (a->c.top + a->c.height))) {
1403 mf.width = a->c.left + a->c.width;
1404 mf.height = a->c.top + a->c.height;
1406 v4l_bound_align_image(&mf.width, RK_CAM_W_MIN, RK_CAM_W_MAX, 1,
1407 &mf.height, RK_CAM_H_MIN, RK_CAM_H_MAX, 0,
1408 fourcc == V4L2_PIX_FMT_NV16 ?4 : 0);
1410 ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
1415 rk_camera_setup_format(icd, fourcc, mf.code, &a->c);
1417 icd->user_width = mf.width;
1418 icd->user_height = mf.height;
1423 static int rk_camera_set_fmt(struct soc_camera_device *icd,
1424 struct v4l2_format *f)
1426 struct device *dev = icd->dev.parent;
1427 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1428 const struct soc_camera_format_xlate *xlate = NULL;
1429 struct soc_camera_host *ici =to_soc_camera_host(icd->dev.parent);
1430 struct rk_camera_dev *pcdev = ici->priv;
1431 struct v4l2_pix_format *pix = &f->fmt.pix;
1432 struct v4l2_mbus_framefmt mf;
1433 struct v4l2_rect rect;
1434 int ret,usr_w,usr_h;
1438 usr_h = pix->height;
1439 RKCAMERA_TR("%s enter width:%d height:%d\n",__FUNCTION__,usr_w,usr_h);
1440 xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
1442 dev_err(dev, "Format %x not found\n", pix->pixelformat);
1444 goto RK_CAMERA_SET_FMT_END;
1447 /* ddl@rock-chips.com: sensor init code transmit in here after open */
1448 if (pcdev->icd_init == 0) {
1449 v4l2_subdev_call(sd,core, init, 0);
1450 pcdev->icd_init = 1;
1452 stream_on = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
1453 if (stream_on & ENABLE_CAPTURE)
1454 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (stream_on & (~ENABLE_CAPTURE)));
1456 mf.width = pix->width;
1457 mf.height = pix->height;
1458 mf.field = pix->field;
1459 mf.colorspace = pix->colorspace;
1460 mf.code = xlate->code;
1461 ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
1462 if (mf.code != xlate->code)
1464 #ifdef CONFIG_VIDEO_RK29_WORK_IPP
1465 if ((mf.width != usr_w) || (mf.height != usr_h)) {
1467 if (unlikely((mf.width <16) || (mf.width > 8190) || (mf.height < 16) || (mf.height > 8190))) {
1468 RKCAMERA_TR("Senor and IPP both invalid source resolution(%dx%d)\n",mf.width,mf.height);
1470 goto RK_CAMERA_SET_FMT_END;
1472 if (unlikely((usr_w <16)||(usr_h < 16))) {
1473 RKCAMERA_TR("Senor and IPP both invalid destination resolution(%dx%d)\n",usr_w,usr_h);
1475 goto RK_CAMERA_SET_FMT_END;
1478 if((mf.width*10/mf.height) != (usr_w*10/usr_h)){
1479 ratio = ((mf.width*10/usr_w) >= (mf.height*10/usr_h))?(mf.height*10/usr_h):(mf.width*10/usr_w);
1480 pcdev->host_width = ratio*usr_w/10;
1481 pcdev->host_height = ratio*usr_h/10;
1482 //for ipp ,need 4 bit alligned.
1483 pcdev->host_width &= ~0x03;
1484 pcdev->host_height &= ~0x03;
1485 RKCAMERA_DG("ratio = %d ,host:%d*%d\n",ratio,pcdev->host_width,pcdev->host_height);
1487 else{ // needn't crop ,just scaled by ipp
1488 // pcdev->host_width = usr_w;
1489 // pcdev->host_height = usr_h;
1490 pcdev->host_width = mf.width;
1491 pcdev->host_height = mf.height;
1495 pcdev->host_width = usr_w;
1496 pcdev->host_height = usr_h;
1499 //according to crop and scale capability to change , here just cropt to user needed
1500 if (unlikely((mf.width <16) || (mf.width > 8190) || (mf.height < 16) || (mf.height > 8190))) {
1501 RKCAMERA_TR("Senor invalid source resolution(%dx%d)\n",mf.width,mf.height);
1503 goto RK_CAMERA_SET_FMT_END;
1505 if (unlikely((usr_w <16)||(usr_h < 16))) {
1506 RKCAMERA_TR("Senor invalid destination resolution(%dx%d)\n",usr_w,usr_h);
1508 goto RK_CAMERA_SET_FMT_END;
1510 pcdev->host_width = usr_w;
1511 pcdev->host_height = usr_h;
1515 RKCAMERA_DG("%s..%d.. host:%d*%d , sensor output:%d*%d,user demand:%d*%d\n",__FUNCTION__,__LINE__,
1516 pcdev->host_width,pcdev->host_height,mf.width,mf.height,usr_w,usr_h);
1517 rect.width = pcdev->host_width;
1518 rect.height = pcdev->host_height;
1519 rect.left = ((mf.width-pcdev->host_width )>>1)&(~0x01);
1520 rect.top = ((mf.height-pcdev->host_height)>>1)&(~0x01);
1521 pcdev->host_left = rect.left;
1522 pcdev->host_top = rect.top;
1524 down(&pcdev->zoominfo.sem);
1525 pcdev->zoominfo.a.c.width = pcdev->host_width*100/pcdev->zoominfo.zoom_rate;
1526 pcdev->zoominfo.a.c.width &= ~0x03;
1527 pcdev->zoominfo.a.c.height = pcdev->host_height*100/pcdev->zoominfo.zoom_rate;
1528 pcdev->zoominfo.a.c.height &= ~0x03;
1529 //now digital zoom use ipp to do crop and scale
1530 if(pcdev->zoominfo.zoom_rate != 100){
1531 pcdev->zoominfo.a.c.left = ((pcdev->host_width - pcdev->zoominfo.a.c.width)>>1)&(~0x01);
1532 pcdev->zoominfo.a.c.top = ((pcdev->host_height - pcdev->zoominfo.a.c.height)>>1)&(~0x01);
1535 pcdev->zoominfo.a.c.left = 0;
1536 pcdev->zoominfo.a.c.top = 0;
1538 pcdev->zoominfo.vir_width = pcdev->host_width;
1539 up(&pcdev->zoominfo.sem);
1541 /* ddl@rock-chips.com: IPP work limit check */
1542 if ((pcdev->zoominfo.a.c.width != usr_w) || (pcdev->zoominfo.a.c.height != usr_h)) {
1543 if (usr_w > 0x7f0) {
1544 if (((usr_w>>1)&0x3f) && (((usr_w>>1)&0x3f) <= 8)) {
1545 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));
1547 goto RK_CAMERA_SET_FMT_END;
1550 if ((usr_w&0x3f) && ((usr_w&0x3f) <= 8)) {
1551 RKCAMERA_TR("IPP Destination resolution(%dx%d, %d mod 64=%d is <= 8)",usr_w,usr_h, usr_w, (int)(usr_w&0x3f));
1553 goto RK_CAMERA_SET_FMT_END;
1557 RKCAMERA_DG("%s..%s icd width:%d user width:%d (zoom: %dx%d@(%d,%d)->%dx%d)\n",__FUNCTION__,xlate->host_fmt->name,
1558 rect.width, pix->width, pcdev->zoominfo.a.c.width,pcdev->zoominfo.a.c.height, pcdev->zoominfo.a.c.left,pcdev->zoominfo.a.c.top,
1559 pix->width, pix->height);
1560 rk_camera_setup_format(icd, pix->pixelformat, mf.code, &rect);
1562 if (CAM_IPPWORK_IS_EN()) {
1563 BUG_ON(pcdev->vipmem_phybase == 0);
1566 pix->height = usr_h;
1567 pix->field = mf.field;
1568 pix->colorspace = mf.colorspace;
1569 icd->current_fmt = xlate;
1570 pcdev->icd_width = mf.width;
1571 pcdev->icd_height = mf.height;
1574 RK_CAMERA_SET_FMT_END:
1575 if (stream_on & ENABLE_CAPTURE)
1576 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL) | ENABLE_CAPTURE));
1578 RKCAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
1581 static bool rk_camera_fmt_capturechk(struct v4l2_format *f)
1585 if ((f->fmt.pix.width == 1024) && (f->fmt.pix.height == 768)) {
1587 } else if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 1024)) {
1589 } else if ((f->fmt.pix.width == 1600) && (f->fmt.pix.height == 1200)) {
1591 } else if ((f->fmt.pix.width == 2048) && (f->fmt.pix.height == 1536)) {
1593 } else if ((f->fmt.pix.width == 2592) && (f->fmt.pix.height == 1944)) {
1598 RKCAMERA_DG("%s %dx%d is capture format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
1601 static int rk_camera_try_fmt(struct soc_camera_device *icd,
1602 struct v4l2_format *f)
1604 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1605 struct rk_camera_dev *pcdev = ici->priv;
1606 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1607 const struct soc_camera_format_xlate *xlate;
1608 struct v4l2_pix_format *pix = &f->fmt.pix;
1609 __u32 pixfmt = pix->pixelformat;
1610 int ret,usr_w,usr_h,i;
1611 bool is_capture = rk_camera_fmt_capturechk(f);
1612 bool vipmem_is_overflow = false;
1613 struct v4l2_mbus_framefmt mf;
1616 usr_h = pix->height;
1617 RKCAMERA_DG("%s enter width:%d height:%d\n",__FUNCTION__,usr_w,usr_h);
1619 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
1621 dev_err(icd->dev.parent, "Format (%c%c%c%c) not found\n", pixfmt & 0xFF, (pixfmt >> 8) & 0xFF,
1622 (pixfmt >> 16) & 0xFF, (pixfmt >> 24) & 0xFF);
1624 RKCAMERA_TR("%s(version:%c%c%c) support format:\n",rk_cam_driver_description,(RK_CAM_VERSION_CODE&0xff0000)>>16,
1625 (RK_CAM_VERSION_CODE&0xff00)>>8,(RK_CAM_VERSION_CODE&0xff));
1626 for (i = 0; i < icd->num_user_formats; i++)
1627 RKCAMERA_TR("(%c%c%c%c)-%s\n",
1628 icd->user_formats[i].host_fmt->fourcc & 0xFF, (icd->user_formats[i].host_fmt->fourcc >> 8) & 0xFF,
1629 (icd->user_formats[i].host_fmt->fourcc >> 16) & 0xFF, (icd->user_formats[i].host_fmt->fourcc >> 24) & 0xFF,
1630 icd->user_formats[i].host_fmt->name);
1631 goto RK_CAMERA_TRY_FMT_END;
1633 /* limit to rk29 hardware capabilities */
1634 v4l_bound_align_image(&pix->width, RK_CAM_W_MIN, RK_CAM_W_MAX, 1,
1635 &pix->height, RK_CAM_H_MIN, RK_CAM_H_MAX, 0,
1636 pixfmt == V4L2_PIX_FMT_NV16 ? 4 : 0);
1638 pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
1640 if (pix->bytesperline < 0)
1641 return pix->bytesperline;
1643 /* limit to sensor capabilities */
1644 mf.width = pix->width;
1645 mf.height = pix->height;
1646 mf.field = pix->field;
1647 mf.colorspace = pix->colorspace;
1648 mf.code = xlate->code;
1650 ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
1652 goto RK_CAMERA_TRY_FMT_END;
1653 RKCAMERA_DG("%s mf.width:%d mf.height:%d\n",__FUNCTION__,mf.width,mf.height);
1654 #ifdef CONFIG_VIDEO_RK29_WORK_IPP
1655 if ((mf.width > usr_w) && (mf.height > usr_h)) {
1657 vipmem_is_overflow = (PAGE_ALIGN(pix->bytesperline*pix->height) > pcdev->vipmem_size);
1659 /* Assume preview buffer minimum is 4 */
1660 vipmem_is_overflow = (PAGE_ALIGN(pix->bytesperline*pix->height)*4 > pcdev->vipmem_size);
1662 if (vipmem_is_overflow == false) {
1664 pix->height = usr_h;
1666 RKCAMERA_TR("vipmem for IPP is overflow, This resolution(%dx%d -> %dx%d) is invalidate!\n",mf.width,mf.height,usr_w,usr_h);
1667 pix->width = mf.width;
1668 pix->height = mf.height;
1670 } else if ((mf.width < usr_w) && (mf.height < usr_h)) {
1671 if (((usr_w>>1) < mf.width) && ((usr_h>>1) < mf.height)) {
1673 vipmem_is_overflow = (PAGE_ALIGN(pix->bytesperline*pix->height) > pcdev->vipmem_size);
1675 vipmem_is_overflow = (PAGE_ALIGN(pix->bytesperline*pix->height)*4 > pcdev->vipmem_size);
1677 if (vipmem_is_overflow == false) {
1679 pix->height = usr_h;
1681 RKCAMERA_TR("vipmem for IPP is overflow, This resolution(%dx%d -> %dx%d) is invalidate!\n",mf.width,mf.height,usr_w,usr_h);
1682 pix->width = mf.width;
1683 pix->height = mf.height;
1686 RKCAMERA_TR("The aspect ratio(%dx%d/%dx%d) is bigger than 2 !\n",mf.width,mf.height,usr_w,usr_h);
1687 pix->width = mf.width;
1688 pix->height = mf.height;
1692 //need to change according to crop and scale capablicity
1693 if ((mf.width > usr_w) && (mf.height > usr_h)) {
1695 pix->height = usr_h;
1696 } else if ((mf.width < usr_w) && (mf.height < usr_h)) {
1697 RKCAMERA_TR("%dx%d can't scale up to %dx%d!\n",mf.width,mf.height,usr_w,usr_h);
1698 pix->width = mf.width;
1699 pix->height = mf.height;
1702 pix->colorspace = mf.colorspace;
1705 case V4L2_FIELD_ANY:
1706 case V4L2_FIELD_NONE:
1707 pix->field = V4L2_FIELD_NONE;
1710 /* TODO: support interlaced at least in pass-through mode */
1711 dev_err(icd->dev.parent, "Field type %d unsupported.\n",
1713 goto RK_CAMERA_TRY_FMT_END;
1716 RK_CAMERA_TRY_FMT_END:
1718 RKCAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
1722 static int rk_camera_reqbufs(struct soc_camera_device *icd,
1723 struct v4l2_requestbuffers *p)
1727 /* This is for locking debugging only. I removed spinlocks and now I
1728 * check whether .prepare is ever called on a linked buffer, or whether
1729 * a dma IRQ can occur for an in-work or unlinked buffer. Until now
1730 * it hadn't triggered */
1731 for (i = 0; i < p->count; i++) {
1732 struct rk_camera_buffer *buf = container_of(icd->vb_vidq.bufs[i],
1733 struct rk_camera_buffer, vb);
1735 INIT_LIST_HEAD(&buf->vb.queue);
1741 static unsigned int rk_camera_poll(struct file *file, poll_table *pt)
1743 struct soc_camera_device *icd = file->private_data;
1744 struct rk_camera_buffer *buf;
1746 buf = list_entry(icd->vb_vidq.stream.next, struct rk_camera_buffer,
1749 poll_wait(file, &buf->vb.done, pt);
1751 if (buf->vb.state == VIDEOBUF_DONE ||
1752 buf->vb.state == VIDEOBUF_ERROR)
1753 return POLLIN|POLLRDNORM;
1758 static int rk_camera_querycap(struct soc_camera_host *ici,
1759 struct v4l2_capability *cap)
1761 struct rk_camera_dev *pcdev = ici->priv;
1762 char orientation[5];
1765 strlcpy(cap->card, dev_name(pcdev->icd->pdev), sizeof(cap->card));
1766 memset(orientation,0x00,sizeof(orientation));
1767 for (i=0; i<RK_CAM_NUM;i++) {
1768 if ((pcdev->pdata->info[i].dev_name!=NULL) && (strcmp(dev_name(pcdev->icd->pdev), pcdev->pdata->info[i].dev_name) == 0)) {
1769 sprintf(orientation,"-%d",pcdev->pdata->info[i].orientation);
1773 if (orientation[0] != '-') {
1774 RKCAMERA_TR("%s: %s is not registered in rk29_camera_platform_data, orientation apply default value",__FUNCTION__,dev_name(pcdev->icd->pdev));
1775 if (strstr(dev_name(pcdev->icd->pdev),"front"))
1776 strcat(cap->card,"-270");
1778 strcat(cap->card,"-90");
1780 strcat(cap->card,orientation);
1782 cap->version = RK_CAM_VERSION_CODE;
1783 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1787 static void rk_camera_store_register(struct rk_camera_dev *pcdev)
1789 pcdev->reginfo_suspend.cifCtrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
1790 pcdev->reginfo_suspend.cifCrop = read_cif_reg(pcdev->base,CIF_CIF_CROP);
1791 pcdev->reginfo_suspend.cifFs = read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE);
1792 pcdev->reginfo_suspend.cifIntEn = read_cif_reg(pcdev->base,CIF_CIF_INTEN);
1793 pcdev->reginfo_suspend.cifFmt= read_cif_reg(pcdev->base,CIF_CIF_FOR);
1794 pcdev->reginfo_suspend.cifVirWidth = read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH);
1795 pcdev->reginfo_suspend.cifScale= read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL);
1797 static void rk_camera_restore_register(struct rk_camera_dev *pcdev)
1799 write_cif_reg(pcdev->base,CIF_CIF_CTRL, pcdev->reginfo_suspend.cifCtrl&~ENABLE_CAPTURE);
1800 write_cif_reg(pcdev->base,CIF_CIF_INTEN, pcdev->reginfo_suspend.cifIntEn);
1801 write_cif_reg(pcdev->base,CIF_CIF_CROP, pcdev->reginfo_suspend.cifCrop);
1802 write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, pcdev->reginfo_suspend.cifFs);
1803 write_cif_reg(pcdev->base,CIF_CIF_FOR, pcdev->reginfo_suspend.cifFmt);
1804 write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH,pcdev->reginfo_suspend.cifVirWidth);
1805 write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL, pcdev->reginfo_suspend.cifScale);
1807 static int rk_camera_suspend(struct soc_camera_device *icd, pm_message_t state)
1809 struct soc_camera_host *ici =
1810 to_soc_camera_host(icd->dev.parent);
1811 struct rk_camera_dev *pcdev = ici->priv;
1812 struct v4l2_subdev *sd;
1815 mutex_lock(&camera_lock);
1816 if ((pcdev->icd == icd) && (icd->ops->suspend)) {
1817 rk_camera_s_stream(icd, 0);
1818 sd = soc_camera_to_subdev(icd);
1819 v4l2_subdev_call(sd, video, s_stream, 0);
1820 ret = icd->ops->suspend(icd, state);
1822 pcdev->reginfo_suspend.cifCtrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
1823 pcdev->reginfo_suspend.cifCrop = read_cif_reg(pcdev->base,CIF_CIF_CROP);
1824 pcdev->reginfo_suspend.cifFs = read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE);
1825 pcdev->reginfo_suspend.cifIntEn = read_cif_reg(pcdev->base,CIF_CIF_INTEN);
1826 pcdev->reginfo_suspend.cifFmt= read_cif_reg(pcdev->base,CIF_CIF_FOR);
1827 pcdev->reginfo_suspend.cifVirWidth = read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH);
1828 pcdev->reginfo_suspend.cifScale= read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL);
1829 //pcdev->reginfo_suspend.VipCrm = read_vip_reg(pcdev->base,RK29_VIP_CRM);
1831 //tmp = pcdev->reginfo_suspend.cifFs>>16; /* ddl@rock-chips.com */
1832 //tmp += pcdev->reginfo_suspend.cifCrop>>16;
1833 //pcdev->reginfo_suspend.cifFs = (pcdev->reginfo_suspend.cifFs & 0xffff) | (tmp<<16);
1835 pcdev->reginfo_suspend.Inval = Reg_Validate;
1836 rk_camera_deactivate(pcdev);
1838 RKCAMERA_DG("%s Enter Success...\n", __FUNCTION__);
1840 RKCAMERA_DG("%s icd has been deattach, don't need enter suspend\n", __FUNCTION__);
1842 mutex_unlock(&camera_lock);
1846 static int rk_camera_resume(struct soc_camera_device *icd)
1848 struct soc_camera_host *ici =
1849 to_soc_camera_host(icd->dev.parent);
1850 struct rk_camera_dev *pcdev = ici->priv;
1851 struct v4l2_subdev *sd;
1854 mutex_lock(&camera_lock);
1855 if ((pcdev->icd == icd) && (icd->ops->resume)) {
1856 if (pcdev->reginfo_suspend.Inval == Reg_Validate) {
1857 rk_camera_activate(pcdev, icd);
1858 write_cif_reg(pcdev->base,CIF_CIF_CTRL, pcdev->reginfo_suspend.cifCtrl&~ENABLE_CAPTURE);
1859 write_cif_reg(pcdev->base,CIF_CIF_INTEN, pcdev->reginfo_suspend.cifIntEn);
1860 write_cif_reg(pcdev->base,CIF_CIF_CROP, pcdev->reginfo_suspend.cifCrop);
1861 write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, pcdev->reginfo_suspend.cifFs);
1862 write_cif_reg(pcdev->base,CIF_CIF_FOR, pcdev->reginfo_suspend.cifFmt);
1863 write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH,pcdev->reginfo_suspend.cifVirWidth);
1864 write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL, pcdev->reginfo_suspend.cifScale);
1865 rk_videobuf_capture(pcdev->active,pcdev);
1866 rk_camera_s_stream(icd, 1);
1867 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
1869 RKCAMERA_TR("Resume fail, vip register recored is invalidate!!\n");
1870 goto rk_camera_resume_end;
1873 ret = icd->ops->resume(icd);
1874 sd = soc_camera_to_subdev(icd);
1875 v4l2_subdev_call(sd, video, s_stream, 1);
1877 RKCAMERA_DG("%s Enter success\n",__FUNCTION__);
1879 RKCAMERA_DG("%s icd has been deattach, don't need enter resume\n", __FUNCTION__);
1882 rk_camera_resume_end:
1883 mutex_unlock(&camera_lock);
1887 static void rk_camera_reinit_work(struct work_struct *work)
1889 struct device *control;
1890 struct v4l2_subdev *sd;
1891 struct v4l2_mbus_framefmt mf;
1892 const struct soc_camera_format_xlate *xlate;
1894 struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
1895 struct rk_camera_dev *pcdev = camera_work->pcdev;
1896 struct videobuf_buffer *tmp_vb;
1897 struct soc_camera_link *tmp_soc_cam_link;
1899 unsigned long flags = 0;
1900 if(pcdev->icd == NULL)
1902 sd = soc_camera_to_subdev(pcdev->icd);
1903 tmp_soc_cam_link = to_soc_camera_link(pcdev->icd);
1906 RKCAMERA_TR("CIF_CIF_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CTRL));
1907 RKCAMERA_TR("CIF_CIF_INTEN = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTEN));
1908 RKCAMERA_TR("CIF_CIF_INTSTAT = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTSTAT));
1909 RKCAMERA_TR("CIF_CIF_FOR = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_FOR));
1910 RKCAMERA_TR("CIF_CIF_CROP = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CROP));
1911 RKCAMERA_TR("CIF_CIF_SET_SIZE = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE));
1912 RKCAMERA_TR("CIF_CIF_SCL_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL));
1913 RKCAMERA_TR("CRU_PCLK_REG30 = 0X%x\n",read_cru_reg(CRU_PCLK_REG30));
1914 RKCAMERA_TR("CIF_CIF_LAST_LINE = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_LINE));
1916 RKCAMERA_TR("CIF_CIF_LAST_PIX = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_PIX));
1917 RKCAMERA_TR("CIF_CIF_VIR_LINE_WIDTH = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH));
1918 RKCAMERA_TR("CIF_CIF_LINE_NUM_ADDR = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LINE_NUM_ADDR));
1919 RKCAMERA_TR("CIF_CIF_FRM0_ADDR_Y = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y));
1920 RKCAMERA_TR("CIF_CIF_FRM0_ADDR_UV = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV));
1921 RKCAMERA_TR("CIF_CIF_FRAME_STATUS = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS));
1923 if(1/*pcdev->reinit_times++ >= 2*/)
1925 pcdev->stop_cif = true;
1926 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL)&(~ENABLE_CAPTURE)));
1927 RKCAMERA_DG("the reinit times = %d\n",pcdev->reinit_times);
1929 while (!list_empty(&pcdev->capture)) {
1930 tmp_vb = list_entry(pcdev->capture.next, struct videobuf_buffer, queue);
1931 if (tmp_vb/* && (tmp_vb->state == VIDEOBUF_QUEUED)*/)
1933 printk("wake up video buffer index = %d ,state = %d, !!!\n",tmp_vb->i,tmp_vb->state);
1934 tmp_vb->state = VIDEOBUF_ERROR;
1935 list_del_init(&(tmp_vb->queue));
1936 wake_up(&tmp_vb->done);
1940 spin_lock_irqsave(pcdev->video_vq->irqlock, flags);
1941 for (index = 0; index < VIDEO_MAX_FRAME; index++) {
1942 if (NULL == pcdev->video_vq->bufs[index])
1944 if (pcdev->video_vq->bufs[index]->state == VIDEOBUF_QUEUED)
1946 list_del_init(&pcdev->video_vq->bufs[index]->queue);
1947 pcdev->video_vq->bufs[index]->state = VIDEOBUF_NEEDS_INIT;
1948 wake_up_all(&pcdev->video_vq->bufs[index]->done);
1949 printk("wake up video buffer index = %d !!!\n",index);
1952 spin_unlock_irqrestore(pcdev->video_vq->irqlock, flags);
1955 RKCAMERA_TR("the %d reinit times ,wake up video buffers!\n ",pcdev->reinit_times);
1956 }/*else{ //the first time,just reinit sensor ,don't wake up vb
1957 // rk_cif_poweroff(pcdev);
1958 RKCAMERA_DG("first time to reinit\n");
1961 // write_cru_reg(CRU_CIF_RST_REG30,(read_cru_reg(CRU_CIF_RST_REG30)|MASK_RST_CIF0|RQUEST_RST_CIF0 ));
1963 // write_cru_reg(CRU_CIF_RST_REG30,(read_cru_reg(CRU_CIF_RST_REG30)&(~RQUEST_RST_CIF0)) | MASK_RST_CIF0);
1964 rk_camera_store_register(pcdev);
1965 rk_camera_deactivate(pcdev);
1966 pmu_set_idle_request(IDLE_REQ_VIO, true);
1967 cru_set_soft_reset(SOFT_RST_CIF0, true);
1969 cru_set_soft_reset(SOFT_RST_CIF0, false);
1970 pmu_set_idle_request(IDLE_REQ_VIO, false);
1971 rk_camera_activate(pcdev,NULL);
1972 rk_camera_restore_register(pcdev);
1973 rk_videobuf_capture(pcdev->active,pcdev);
1974 printk("clean cru register reset cif0 0x%x\n",read_cru_reg(CRU_CIF_RST_REG30));
1977 // write_cru_reg(CRU_CIF_RST_REG30,MASK_RST_CIF1|RQUEST_RST_CIF1 | (read_cru_reg(CRU_CIF_RST_REG30)));
1978 // write_cru_reg(CRU_CIF_RST_REG30,(read_cru_reg(CRU_CIF_RST_REG30)&(~RQUEST_RST_CIF1)) | MASK_RST_CIF1);
1979 rk_camera_store_register(pcdev);
1980 rk_camera_deactivate(pcdev);
1981 pmu_set_idle_request(IDLE_REQ_VIO, true);
1982 cru_set_soft_reset(SOFT_RST_CIF1, true);
1984 cru_set_soft_reset(SOFT_RST_CIF1, false);
1985 pmu_set_idle_request(IDLE_REQ_VIO, false);
1986 rk_camera_activate(pcdev,NULL);
1987 rk_camera_restore_register(pcdev);
1988 rk_videobuf_capture(pcdev->active,pcdev);
1990 tmp_soc_cam_link->power(pcdev->icd->pdev,0);
1991 // rk_cif_poweron(pcdev);
1992 tmp_soc_cam_link->power(pcdev->icd->pdev,1);
1993 control = to_soc_camera_control(pcdev->icd);
1994 sd = dev_get_drvdata(control);
1995 ret = v4l2_subdev_call(sd,core, init, 1);
1997 mf.width = pcdev->icd->user_width;
1998 mf.height = pcdev->icd->user_height;
1999 xlate = soc_camera_xlate_by_fourcc(pcdev->icd, pcdev->icd->current_fmt->host_fmt->fourcc);
2000 mf.code = xlate->code;
2001 ret |= v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
2002 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL)|ENABLE_CAPTURE));
2004 RKCAMERA_TR("first time Camera host haven't recevie data from sensor,Reinit sensor now! ret:0x%x\n",ret);
2007 static enum hrtimer_restart rk_camera_fps_func(struct hrtimer *timer)
2009 struct rk_camera_frmivalenum *fival_nxt=NULL,*fival_pre=NULL, *fival_rec=NULL;
2010 struct rk_camera_timer *fps_timer = container_of(timer, struct rk_camera_timer, timer);
2011 struct rk_camera_dev *pcdev = fps_timer->pcdev;
2013 // static unsigned int last_fps = 0;
2014 struct soc_camera_link *tmp_soc_cam_link;
2015 tmp_soc_cam_link = to_soc_camera_link(pcdev->icd);
2017 RKCAMERA_DG("rk_camera_fps_func fps:0x%x\n",pcdev->fps);
2018 if ((pcdev->fps < 1) || (pcdev->last_fps == pcdev->fps)) {
2019 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);
2020 pcdev->camera_reinit_work.pcdev = pcdev;
2021 //INIT_WORK(&(pcdev->camera_reinit_work.work), rk_camera_reinit_work);
2022 pcdev->reinit_times++;
2023 queue_work(pcdev->camera_wq,&(pcdev->camera_reinit_work.work));
2024 } else if(!pcdev->timer_get_fps) {
2025 pcdev->timer_get_fps = true;
2026 for (i=0; i<2; i++) {
2027 if (pcdev->icd == pcdev->icd_frmival[i].icd) {
2028 fival_nxt = pcdev->icd_frmival[i].fival_list;
2033 fival_pre = fival_nxt;
2034 while (fival_nxt != NULL) {
2036 RKCAMERA_DG("%s %c%c%c%c %dx%d framerate : %d/%d\n", dev_name(&pcdev->icd->dev),
2037 fival_nxt->fival.pixel_format & 0xFF, (fival_nxt->fival.pixel_format >> 8) & 0xFF,
2038 (fival_nxt->fival.pixel_format >> 16) & 0xFF, (fival_nxt->fival.pixel_format >> 24),
2039 fival_nxt->fival.width, fival_nxt->fival.height, fival_nxt->fival.discrete.denominator,
2040 fival_nxt->fival.discrete.numerator);
2042 if (((fival_nxt->fival.pixel_format == pcdev->pixfmt)
2043 && (fival_nxt->fival.height == pcdev->icd->user_height)
2044 && (fival_nxt->fival.width == pcdev->icd->user_width))
2045 || (fival_nxt->fival.discrete.denominator == 0)) {
2047 if (fival_nxt->fival.discrete.denominator == 0) {
2048 fival_nxt->fival.index = 0;
2049 fival_nxt->fival.width = pcdev->icd->user_width;
2050 fival_nxt->fival.height= pcdev->icd->user_height;
2051 fival_nxt->fival.pixel_format = pcdev->pixfmt;
2052 fival_nxt->fival.discrete.denominator = pcdev->frame_interval;
2053 fival_nxt->fival.reserved[1] = (pcdev->icd_width<<16)
2054 |(pcdev->icd_height);
2055 fival_nxt->fival.discrete.numerator = 1000000;
2056 fival_nxt->fival.type = V4L2_FRMIVAL_TYPE_DISCRETE;
2059 fival_rec = fival_nxt;
2061 fival_pre = fival_nxt;
2062 fival_nxt = fival_nxt->nxt;
2065 if ((rec_flag == 0) && fival_pre) {
2066 fival_pre->nxt = kzalloc(sizeof(struct rk_camera_frmivalenum), GFP_ATOMIC);
2067 if (fival_pre->nxt != NULL) {
2068 fival_pre->nxt->fival.index = fival_pre->fival.index++;
2069 fival_pre->nxt->fival.width = pcdev->icd->user_width;
2070 fival_pre->nxt->fival.height= pcdev->icd->user_height;
2071 fival_pre->nxt->fival.pixel_format = pcdev->pixfmt;
2073 fival_pre->nxt->fival.discrete.denominator = pcdev->frame_interval;
2074 fival_pre->nxt->fival.reserved[1] = (pcdev->icd_width<<16)
2075 |(pcdev->icd_height);
2076 fival_pre->nxt->fival.discrete.numerator = 1000000;
2077 fival_pre->nxt->fival.type = V4L2_FRMIVAL_TYPE_DISCRETE;
2079 fival_rec = fival_pre->nxt;
2083 pcdev->last_fps = pcdev->fps ;
2084 pcdev->fps_timer.timer.node.expires= ktime_add_us(pcdev->fps_timer.timer.node.expires, ktime_to_us(ktime_set(3, 0)));
2085 pcdev->fps_timer.timer._softexpires= ktime_add_us(pcdev->fps_timer.timer._softexpires, ktime_to_us(ktime_set(3, 0)));
2086 //return HRTIMER_NORESTART;
2087 if(pcdev->reinit_times >=2)
2088 return HRTIMER_NORESTART;
2090 return HRTIMER_RESTART;
2092 static int rk_camera_s_stream(struct soc_camera_device *icd, int enable)
2094 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2095 struct rk_camera_dev *pcdev = ici->priv;
2098 unsigned long flags;
2100 WARN_ON(pcdev->icd != icd);
2102 cif_ctrl_val = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
2105 pcdev->last_fps = 0;
2106 pcdev->frame_interval = 0;
2107 hrtimer_cancel(&(pcdev->fps_timer.timer));
2108 pcdev->fps_timer.pcdev = pcdev;
2109 pcdev->timer_get_fps = false;
2110 pcdev->reinit_times = 0;
2111 pcdev->stop_cif = false;
2112 // hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL);
2113 cif_ctrl_val |= ENABLE_CAPTURE;
2114 write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val);
2115 hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL);
2116 pcdev->fps_timer.istarted = true;
2118 //cancel timer before stop cif
2119 ret = hrtimer_cancel(&pcdev->fps_timer.timer);
2120 pcdev->fps_timer.istarted = false;
2121 flush_work(&(pcdev->camera_reinit_work.work));
2123 cif_ctrl_val &= ~ENABLE_CAPTURE;
2124 spin_lock_irqsave(&pcdev->lock, flags);
2125 write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val);
2126 pcdev->stop_cif = true;
2127 spin_unlock_irqrestore(&pcdev->lock, flags);
2128 // printk("flush work end!!!!!!!!!\n");
2130 // write_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS, 0x00000003);//frame1 has been ready to receive data,frame 2 is not used
2131 // write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF); /* clear vip interrupte single */
2132 // write_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS,0); /* clear vip interrupte single */
2133 flush_workqueue((pcdev->camera_wq));
2134 RKCAMERA_DG("STREAM_OFF cancel timer and flush work:0x%x \n", ret);
2136 //must be reinit,or will be somthing wrong in irq process.
2137 if(enable == false){
2138 pcdev->active = NULL;
2139 INIT_LIST_HEAD(&pcdev->capture);
2141 RKCAMERA_DG("%s.. enable : 0x%x , CIF_CIF_CTRL = 0x%x\n", __FUNCTION__, enable,read_cif_reg(pcdev->base,CIF_CIF_CTRL));
2144 int rk_camera_enum_frameintervals(struct soc_camera_device *icd, struct v4l2_frmivalenum *fival)
2146 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2147 struct rk_camera_dev *pcdev = ici->priv;
2148 struct rk_camera_frmivalenum *fival_list = NULL;
2149 struct v4l2_frmivalenum *fival_head = NULL;
2150 int i,ret = 0,index;
2152 index = fival->index & 0x00ffffff;
2153 if ((fival->index & 0xff000000) == 0xff000000) { /* ddl@rock-chips.com: detect framerate */
2154 for (i=0; i<2; i++) {
2155 if (pcdev->icd_frmival[i].icd == icd) {
2156 fival_list = pcdev->icd_frmival[i].fival_list;
2160 if (fival_list != NULL) {
2162 while (fival_list != NULL) {
2163 if ((fival->pixel_format == fival_list->fival.pixel_format)
2164 && (fival->height == fival_list->fival.height)
2165 && (fival->width == fival_list->fival.width)) {
2170 fival_list = fival_list->nxt;
2173 if ((i==index) && (fival_list != NULL)) {
2174 memcpy(fival, &fival_list->fival, sizeof(struct v4l2_frmivalenum));
2179 RKCAMERA_TR("%s: fival_list is NULL\n",__FUNCTION__);
2184 for (i=0; i<RK_CAM_NUM; i++) {
2185 if (pcdev->pdata->info[i].dev_name && (strcmp(dev_name(pcdev->icd->pdev),pcdev->pdata->info[i].dev_name) == 0)) {
2186 fival_head = pcdev->pdata->info[i].fival;
2190 if (fival_head == NULL) {
2191 RKCAMERA_TR("%s: %s is not registered in rk_camera_platform_data!!",__FUNCTION__,dev_name(pcdev->icd->pdev));
2193 goto rk_camera_enum_frameintervals_end;
2197 while (fival_head->width && fival_head->height) {
2198 if ((fival->pixel_format == fival_head->pixel_format)
2199 && (fival->height == fival_head->height)
2200 && (fival->width == fival_head->width)) {
2209 if ((i == index) && (fival->height == fival_head->height) && (fival->width == fival_head->width)) {
2210 memcpy(fival, fival_head, sizeof(struct v4l2_frmivalenum));
2211 RKCAMERA_DG("%s %dx%d@%c%c%c%c framerate : %d/%d\n", dev_name(pcdev->icd->pdev),
2212 fival->width, fival->height,
2213 fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
2214 (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
2215 fival->discrete.denominator,fival->discrete.numerator);
2218 RKCAMERA_TR("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(pcdev->icd->pdev),
2219 fival->width,fival->height,
2220 fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
2221 (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
2224 RKCAMERA_DG("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(pcdev->icd->pdev),
2225 fival->width,fival->height,
2226 fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
2227 (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
2232 rk_camera_enum_frameintervals_end:
2236 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
2237 static int rk_camera_set_digit_zoom(struct soc_camera_device *icd,
2238 const struct v4l2_queryctrl *qctrl, int zoom_rate)
2241 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2242 struct rk_camera_dev *pcdev = ici->priv;
2245 unsigned int cif_fs = 0,cif_crop = 0;
2246 int work_index =0,stream_on = 0;
2247 /* ddl@rock-chips.com : The largest resolution is 2047x1088, so larger resolution must be operated some times
2248 (Assume operate times is 4),but resolution which ipp can operate ,it is width and height must be even. */
2249 a.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2250 a.c.width = pcdev->host_width*100/zoom_rate;
2252 a.c.height = pcdev->host_height*100/zoom_rate;
2253 a.c.height &= ~0x03;
2255 a.c.left = (((pcdev->host_width - a.c.width)>>1) +pcdev->host_left)&(~0x01);
2256 a.c.top = (((pcdev->host_height - a.c.height)>>1) + pcdev->host_top)&(~0x01);
2257 stream_on = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
2258 if (stream_on & ENABLE_CAPTURE)
2259 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (stream_on & (~ENABLE_CAPTURE)));
2260 if (CAM_IPPWORK_IS_EN() && (stream_on & ENABLE_CAPTURE)){
2261 for(;work_index < pcdev->camera_work_count;work_index++)
2262 flush_work(&((pcdev->camera_work + work_index)->work));
2263 pcdev->frame_inval = RK_CAM_FRAME_INVAL_DC;
2265 //printk("host_left = %d , host_top = %d\n",pcdev->host_left,pcdev->host_top);
2267 down(&pcdev->zoominfo.sem);
2268 pcdev->zoominfo.a.c.height = a.c.height;
2269 pcdev->zoominfo.a.c.width = a.c.width;
2270 pcdev->zoominfo.a.c.top = 0;
2271 pcdev->zoominfo.a.c.left = 0;
2272 pcdev->zoominfo.vir_width = a.c.width;
2273 up(&pcdev->zoominfo.sem);
2275 cif_crop = a.c.left+ (a.c.top<<16);
2276 cif_fs = a.c.width + ((a.c.height)<<16);
2277 //cif do the crop , ipp do the scale
2278 write_cif_reg(pcdev->base,CIF_CIF_CROP, cif_crop);
2279 write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, cif_fs);
2280 write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH, a.c.width);
2281 write_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS, 0x00000003);
2282 write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL,0x10);
2283 if (stream_on & ENABLE_CAPTURE)
2284 write_cif_reg(pcdev->base,CIF_CIF_CTRL, stream_on);
2286 //change the crop and scale parameters
2287 a.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2288 a.c.width = pcdev->host_width*100/zoom_rate;
2290 a.c.height = pcdev->host_height*100/zoom_rate;
2291 a.c.height &= ~0x03;
2292 a.c.left = (pcdev->host_width - a.c.width)>>1;
2293 a.c.top = (pcdev->host_height - a.c.height)>>1;
2294 down(&pcdev->zoominfo.sem);
2295 pcdev->zoominfo.a.c.height = a.c.height;
2296 pcdev->zoominfo.a.c.width = a.c.width;
2297 pcdev->zoominfo.a.c.top = a.c.top;
2298 pcdev->zoominfo.a.c.left = a.c.left;
2299 pcdev->zoominfo.vir_width = pcdev->host_width;
2300 up(&pcdev->zoominfo.sem);
2303 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 );
2308 static inline struct v4l2_queryctrl const *rk_camera_soc_camera_find_qctrl(
2309 struct soc_camera_host_ops *ops, int id)
2313 for (i = 0; i < ops->num_controls; i++)
2314 if (ops->controls[i].id == id)
2315 return &ops->controls[i];
2321 static int rk_camera_set_ctrl(struct soc_camera_device *icd,
2322 struct v4l2_control *sctrl)
2325 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2326 const struct v4l2_queryctrl *qctrl;
2327 struct rk_camera_dev *pcdev = ici->priv;
2330 qctrl = rk_camera_soc_camera_find_qctrl(ici->ops, sctrl->id);
2333 goto rk_camera_set_ctrl_end;
2338 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
2339 case V4L2_CID_ZOOM_ABSOLUTE:
2341 if ((sctrl->value < qctrl->minimum) || (sctrl->value > qctrl->maximum)){
2343 goto rk_camera_set_ctrl_end;
2345 ret = rk_camera_set_digit_zoom(icd, qctrl, sctrl->value);
2347 pcdev->zoominfo.zoom_rate = sctrl->value;
2349 goto rk_camera_set_ctrl_end;
2358 rk_camera_set_ctrl_end:
2362 static struct soc_camera_host_ops rk_soc_camera_host_ops =
2364 .owner = THIS_MODULE,
2365 .add = rk_camera_add_device,
2366 .remove = rk_camera_remove_device,
2367 .suspend = rk_camera_suspend,
2368 .resume = rk_camera_resume,
2369 .enum_frameinervals = rk_camera_enum_frameintervals,
2370 .set_crop = rk_camera_set_crop,
2371 .get_formats = rk_camera_get_formats,
2372 .put_formats = rk_camera_put_formats,
2373 .set_fmt = rk_camera_set_fmt,
2374 .try_fmt = rk_camera_try_fmt,
2375 .init_videobuf = rk_camera_init_videobuf,
2376 .reqbufs = rk_camera_reqbufs,
2377 .poll = rk_camera_poll,
2378 .querycap = rk_camera_querycap,
2379 .set_bus_param = rk_camera_set_bus_param,
2380 .s_stream = rk_camera_s_stream, /* ddl@rock-chips.com : Add stream control for host */
2381 .set_ctrl = rk_camera_set_ctrl,
2382 .controls = rk_camera_controls,
2383 .num_controls = ARRAY_SIZE(rk_camera_controls)
2386 static void rk_camera_cif_iomux(int cif_index)
2390 rk30_mux_api_set(GPIO1B3_CIF0CLKOUT_NAME, GPIO1B_CIF0_CLKOUT);
2393 rk30_mux_api_set(GPIO1C0_CIF1DATA2_RMIICLKOUT_RMIICLKIN_NAME,GPIO1C_CIF1_DATA2);
2394 rk30_mux_api_set(GPIO1C1_CIFDATA3_RMIITXEN_NAME,GPIO1C_CIF_DATA3);
2395 rk30_mux_api_set(GPIO1C2_CIF1DATA4_RMIITXD1_NAME,GPIO1C_CIF1_DATA4);
2396 rk30_mux_api_set(GPIO1C3_CIFDATA5_RMIITXD0_NAME,GPIO1C_CIF_DATA5);
2397 rk30_mux_api_set(GPIO1C4_CIFDATA6_RMIIRXERR_NAME,GPIO1C_CIF_DATA6);
2398 rk30_mux_api_set(GPIO1C5_CIFDATA7_RMIICRSDVALID_NAME,GPIO1C_CIF_DATA7);
2399 rk30_mux_api_set(GPIO1C6_CIFDATA8_RMIIRXD1_NAME,GPIO1C_CIF_DATA8);
2400 rk30_mux_api_set(GPIO1C7_CIFDATA9_RMIIRXD0_NAME,GPIO1C_CIF_DATA9);
2402 rk30_mux_api_set(GPIO1D0_CIF1VSYNC_MIIMD_NAME,GPIO1D_CIF1_VSYNC);
2403 rk30_mux_api_set(GPIO1D1_CIF1HREF_MIIMDCLK_NAME,GPIO1D_CIF1_HREF);
2404 rk30_mux_api_set(GPIO1D2_CIF1CLKIN_NAME,GPIO1D_CIF1_CLKIN);
2405 rk30_mux_api_set(GPIO1D3_CIF1DATA0_NAME,GPIO1D_CIF1_DATA0);
2406 rk30_mux_api_set(GPIO1D4_CIF1DATA1_NAME,GPIO1D_CIF1_DATA1);
2407 rk30_mux_api_set(GPIO1D5_CIF1DATA10_NAME,GPIO1D_CIF1_DATA10);
2408 rk30_mux_api_set(GPIO1D6_CIF1DATA11_NAME,GPIO1D_CIF1_DATA11);
2409 rk30_mux_api_set(GPIO1D7_CIF1CLKOUT_NAME,GPIO1D_CIF1_CLKOUT);
2412 printk("cif index is erro!!!\n");
2417 static int rk_camera_probe(struct platform_device *pdev)
2419 struct rk_camera_dev *pcdev;
2420 struct resource *res;
2421 struct rk_camera_frmivalenum *fival_list,*fival_nxt;
2425 RKCAMERA_DG("%s..%s..%d \n",__FUNCTION__,__FILE__,__LINE__);
2426 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2427 irq = platform_get_irq(pdev, 0);
2428 if (!res || irq < 0) {
2432 pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL);
2434 dev_err(&pdev->dev, "Could not allocate pcdev\n");
2439 pcdev->zoominfo.zoom_rate = 100;
2440 pcdev->hostid = pdev->id;
2441 /*config output clk*/ // must modify start
2443 // printk("it is cif 0!!!!!!!1\n");
2444 pcdev->pd_cif = clk_get(NULL, "pd_cif0");
2445 pcdev->aclk_cif = clk_get(NULL, "aclk_cif0");
2446 pcdev->hclk_cif = clk_get(NULL, "hclk_cif0");
2447 pcdev->cif_clk_in = clk_get(NULL, "cif0_in");
2448 pcdev->cif_clk_out = clk_get(NULL, "cif0_out");
2449 rk_camera_cif_iomux(0);
2452 // printk("it is cif 1!!!!!!!1\n");
2453 pcdev->pd_cif = clk_get(NULL, "pd_cif1");
2454 pcdev->aclk_cif = clk_get(NULL, "aclk_cif1");
2455 pcdev->hclk_cif = clk_get(NULL, "hclk_cif1");
2456 pcdev->cif_clk_in = clk_get(NULL, "cif1_in");
2457 pcdev->cif_clk_out = clk_get(NULL, "cif1_out");
2459 rk_camera_cif_iomux(1);
2461 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)){
2462 RKCAMERA_TR(KERN_ERR "failed to get cif clock source\n");
2464 goto exit_reqmem_vip;
2466 dev_set_drvdata(&pdev->dev, pcdev);
2468 pcdev->pdata = pdev->dev.platform_data; /* ddl@rock-chips.com : Request IO in init function */
2470 if (pcdev->pdata && pcdev->pdata->io_init) {
2471 pcdev->pdata->io_init();
2473 #ifdef CONFIG_VIDEO_RK29_WORK_IPP
2474 if (pcdev->pdata && IS_CIF0()) {
2475 pcdev->vipmem_phybase = pcdev->pdata->meminfo.start;
2476 pcdev->vipmem_size = pcdev->pdata->meminfo.size;
2477 RKCAMERA_TR("\n%s Memory(start:0x%x size:0x%x) for IPP obtain \n",__FUNCTION__, pcdev->pdata->meminfo.start,pcdev->pdata->meminfo.size);
2479 else if (pcdev->pdata){
2480 pcdev->vipmem_phybase = pcdev->pdata->meminfo_cif1.start;
2481 pcdev->vipmem_size = pcdev->pdata->meminfo_cif1.size;
2482 RKCAMERA_TR("\n%s Memory(start:0x%x size:0x%x) for IPP obtain \n",__FUNCTION__, pcdev->pdata->meminfo.start,pcdev->pdata->meminfo.size);
2485 RKCAMERA_TR("\n%s Memory for IPP have not obtain! IPP Function is fail\n",__FUNCTION__);
2486 pcdev->vipmem_phybase = 0;
2487 pcdev->vipmem_size = 0;
2490 INIT_LIST_HEAD(&pcdev->capture);
2491 spin_lock_init(&pcdev->lock);
2492 sema_init(&pcdev->zoominfo.sem,1);
2495 * Request the regions.
2498 if (!request_mem_region(res->start, res->end - res->start + 1,
2499 RK29_CAM_DRV_NAME)) {
2501 goto exit_reqmem_vip;
2503 pcdev->base = ioremap(res->start, res->end - res->start + 1);
2504 if (pcdev->base == NULL) {
2505 dev_err(pcdev->dev, "ioremap() of registers failed\n");
2507 goto exit_ioremap_vip;
2512 pcdev->dev = &pdev->dev;
2514 /* config buffer address */
2517 err = request_irq(pcdev->irq, rk_camera_irq, 0, RK29_CAM_DRV_NAME,
2520 dev_err(pcdev->dev, "Camera interrupt register failed \n");
2525 #ifdef CONFIG_VIDEO_RK29_WORK_IPP
2527 pcdev->camera_wq = create_workqueue("rk_cam_wkque_cif0");
2530 pcdev->camera_wq = create_workqueue("rk_cam_wkque_cif1");
2532 if (pcdev->camera_wq == NULL)
2536 pcdev->camera_reinit_work.pcdev = pcdev;
2537 INIT_WORK(&(pcdev->camera_reinit_work.work), rk_camera_reinit_work);
2539 for (i=0; i<2; i++) {
2540 pcdev->icd_frmival[i].icd = NULL;
2541 pcdev->icd_frmival[i].fival_list = kzalloc(sizeof(struct rk_camera_frmivalenum),GFP_KERNEL);
2544 pcdev->soc_host.drv_name = RK29_CAM_DRV_NAME;
2545 pcdev->soc_host.ops = &rk_soc_camera_host_ops;
2546 pcdev->soc_host.priv = pcdev;
2547 pcdev->soc_host.v4l2_dev.dev = &pdev->dev;
2548 pcdev->soc_host.nr = pdev->id;
2550 err = soc_camera_host_register(&pcdev->soc_host);
2553 pcdev->fps_timer.pcdev = pcdev;
2554 hrtimer_init(&(pcdev->fps_timer.timer), CLOCK_MONOTONIC, HRTIMER_MODE_REL);
2555 pcdev->fps_timer.timer.function = rk_camera_fps_func;
2556 pcdev->icd_cb.sensor_cb = NULL;
2557 // rk29_camdev_info_ptr = pcdev;
2558 RKCAMERA_DG("%s..%s..%d \n",__FUNCTION__,__FILE__,__LINE__);
2563 for (i=0; i<2; i++) {
2564 fival_list = pcdev->icd_frmival[i].fival_list;
2565 fival_nxt = fival_list;
2566 while(fival_nxt != NULL) {
2567 fival_nxt = fival_list->nxt;
2569 fival_list = fival_nxt;
2573 free_irq(pcdev->irq, pcdev);
2574 if (pcdev->camera_wq) {
2575 destroy_workqueue(pcdev->camera_wq);
2576 pcdev->camera_wq = NULL;
2579 iounmap(pcdev->base);
2581 release_mem_region(res->start, res->end - res->start + 1);
2585 pcdev->aclk_cif = NULL;
2587 pcdev->hclk_cif = NULL;
2588 if(pcdev->cif_clk_in)
2589 pcdev->cif_clk_in = NULL;
2590 if(pcdev->cif_clk_out)
2591 pcdev->cif_clk_out = NULL;
2595 // rk_camdev_info_ptr = NULL;
2600 static int __devexit rk_camera_remove(struct platform_device *pdev)
2602 struct rk_camera_dev *pcdev = platform_get_drvdata(pdev);
2603 struct resource *res;
2604 struct rk_camera_frmivalenum *fival_list,*fival_nxt;
2607 free_irq(pcdev->irq, pcdev);
2609 if (pcdev->camera_wq) {
2610 destroy_workqueue(pcdev->camera_wq);
2611 pcdev->camera_wq = NULL;
2614 for (i=0; i<2; i++) {
2615 fival_list = pcdev->icd_frmival[i].fival_list;
2616 fival_nxt = fival_list;
2617 while(fival_nxt != NULL) {
2618 fival_nxt = fival_list->nxt;
2620 fival_list = fival_nxt;
2624 soc_camera_host_unregister(&pcdev->soc_host);
2627 release_mem_region(res->start, res->end - res->start + 1);
2628 if (pcdev->pdata && pcdev->pdata->io_deinit) { /* ddl@rock-chips.com : Free IO in deinit function */
2629 pcdev->pdata->io_deinit(0);
2630 pcdev->pdata->io_deinit(1);
2634 // rk_camdev_info_ptr = NULL;
2635 dev_info(&pdev->dev, "RK28 Camera driver unloaded\n");
2640 static struct platform_driver rk_camera_driver =
2643 .name = RK29_CAM_DRV_NAME,
2645 .probe = rk_camera_probe,
2646 .remove = __devexit_p(rk_camera_remove),
2649 static int rk_camera_init_async(void *unused)
2651 RKCAMERA_DG("%s..%s..%d \n",__FUNCTION__,__FILE__,__LINE__);
2652 platform_driver_register(&rk_camera_driver);
2656 static int __devinit rk_camera_init(void)
2658 RKCAMERA_DG("%s..%s..%d \n",__FUNCTION__,__FILE__,__LINE__);
2659 kthread_run(rk_camera_init_async, NULL, "rk_camera_init");
2663 static void __exit rk_camera_exit(void)
2665 platform_driver_unregister(&rk_camera_driver);
2668 device_initcall_sync(rk_camera_init);
2669 module_exit(rk_camera_exit);
2671 MODULE_DESCRIPTION("RKSoc Camera Host driver");
2672 MODULE_AUTHOR("ddl <ddl@rock-chips>");
2673 MODULE_LICENSE("GPL");