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_RK3188)
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 <plat/vpu_service.h>
42 #include "../../video/rockchip/rga/rga.h"
43 #if defined(CONFIG_ARCH_RK30)||defined(CONFIG_ARCH_RK3188)
44 #include <mach/rk30_camera.h>
49 #if defined(CONFIG_ARCH_RK2928)
50 #include <mach/rk2928_camera.h>
53 #define SOFT_RST_CIF1 (SOFT_RST_MAX+1)
55 #include <asm/cacheflush.h>
57 module_param(debug, int, S_IRUGO|S_IWUSR);
59 #define dprintk(level, fmt, arg...) do { \
61 printk(KERN_WARNING"rk_camera: " fmt , ## arg); } while (0)
63 #define RKCAMERA_TR(format, ...) printk(KERN_ERR format, ## __VA_ARGS__)
64 #define RKCAMERA_DG(format, ...) dprintk(1, format, ## __VA_ARGS__)
66 #define CIF_CIF_CTRL 0x00
67 #define CIF_CIF_INTEN 0x04
68 #define CIF_CIF_INTSTAT 0x08
69 #define CIF_CIF_FOR 0x0c
70 #define CIF_CIF_LINE_NUM_ADDR 0x10
71 #define CIF_CIF_FRM0_ADDR_Y 0x14
72 #define CIF_CIF_FRM0_ADDR_UV 0x18
73 #define CIF_CIF_FRM1_ADDR_Y 0x1c
74 #define CIF_CIF_FRM1_ADDR_UV 0x20
75 #define CIF_CIF_VIR_LINE_WIDTH 0x24
76 #define CIF_CIF_SET_SIZE 0x28
77 #define CIF_CIF_SCM_ADDR_Y 0x2c
78 #define CIF_CIF_SCM_ADDR_U 0x30
79 #define CIF_CIF_SCM_ADDR_V 0x34
80 #define CIF_CIF_WB_UP_FILTER 0x38
81 #define CIF_CIF_WB_LOW_FILTER 0x3c
82 #define CIF_CIF_WBC_CNT 0x40
83 #define CIF_CIF_CROP 0x44
84 #define CIF_CIF_SCL_CTRL 0x48
85 #define CIF_CIF_SCL_DST 0x4c
86 #define CIF_CIF_SCL_FCT 0x50
87 #define CIF_CIF_SCL_VALID_NUM 0x54
88 #define CIF_CIF_LINE_LOOP_CTR 0x58
89 #define CIF_CIF_FRAME_STATUS 0x60
90 #define CIF_CIF_CUR_DST 0x64
91 #define CIF_CIF_LAST_LINE 0x68
92 #define CIF_CIF_LAST_PIX 0x6c
94 //The key register bit descrition
95 // CIF_CTRL Reg , ignore SCM,WBC,ISP,
96 #define DISABLE_CAPTURE (0x00<<0)
97 #define ENABLE_CAPTURE (0x01<<0)
98 #define MODE_ONEFRAME (0x00<<1)
99 #define MODE_PINGPONG (0x01<<1)
100 #define MODE_LINELOOP (0x02<<1)
101 #define AXI_BURST_16 (0x0F << 12)
104 #define FRAME_END_EN (0x01<<1)
105 #define BUS_ERR_EN (0x01<<6)
106 #define SCL_ERR_EN (0x01<<7)
109 #define VSY_HIGH_ACTIVE (0x01<<0)
110 #define VSY_LOW_ACTIVE (0x00<<0)
111 #define HSY_LOW_ACTIVE (0x01<<1)
112 #define HSY_HIGH_ACTIVE (0x00<<1)
113 #define INPUT_MODE_YUV (0x00<<2)
114 #define INPUT_MODE_PAL (0x02<<2)
115 #define INPUT_MODE_NTSC (0x03<<2)
116 #define INPUT_MODE_RAW (0x04<<2)
117 #define INPUT_MODE_JPEG (0x05<<2)
118 #define INPUT_MODE_MIPI (0x06<<2)
119 #define YUV_INPUT_ORDER_UYVY(ori) (ori & (~(0x03<<5)))
120 #define YUV_INPUT_ORDER_YVYU(ori) ((ori & (~(0x01<<6)))|(0x01<<5))
121 #define YUV_INPUT_ORDER_VYUY(ori) ((ori & (~(0x01<<5))) | (0x1<<6))
122 #define YUV_INPUT_ORDER_YUYV(ori) (ori|(0x03<<5))
123 #define YUV_INPUT_422 (0x00<<7)
124 #define YUV_INPUT_420 (0x01<<7)
125 #define INPUT_420_ORDER_EVEN (0x00<<8)
126 #define INPUT_420_ORDER_ODD (0x01<<8)
127 #define CCIR_INPUT_ORDER_ODD (0x00<<9)
128 #define CCIR_INPUT_ORDER_EVEN (0x01<<9)
129 #define RAW_DATA_WIDTH_8 (0x00<<11)
130 #define RAW_DATA_WIDTH_10 (0x01<<11)
131 #define RAW_DATA_WIDTH_12 (0x02<<11)
132 #define YUV_OUTPUT_422 (0x00<<16)
133 #define YUV_OUTPUT_420 (0x01<<16)
134 #define OUTPUT_420_ORDER_EVEN (0x00<<17)
135 #define OUTPUT_420_ORDER_ODD (0x01<<17)
136 #define RAWD_DATA_LITTLE_ENDIAN (0x00<<18)
137 #define RAWD_DATA_BIG_ENDIAN (0x01<<18)
138 #define UV_STORAGE_ORDER_UVUV (0x00<<19)
139 #define UV_STORAGE_ORDER_VUVU (0x01<<19)
142 #define ENABLE_SCL_DOWN (0x01<<0)
143 #define DISABLE_SCL_DOWN (0x00<<0)
144 #define ENABLE_SCL_UP (0x01<<1)
145 #define DISABLE_SCL_UP (0x00<<1)
146 #define ENABLE_YUV_16BIT_BYPASS (0x01<<4)
147 #define DISABLE_YUV_16BIT_BYPASS (0x00<<4)
148 #define ENABLE_RAW_16BIT_BYPASS (0x01<<5)
149 #define DISABLE_RAW_16BIT_BYPASS (0x00<<5)
150 #define ENABLE_32BIT_BYPASS (0x01<<6)
151 #define DISABLE_32BIT_BYPASS (0x00<<6)
154 #define MIN(x,y) ((x<y) ? x: y)
155 #define MAX(x,y) ((x>y) ? x: y)
156 #define RK_SENSOR_24MHZ 24*1000*1000 /* MHz */
157 #define RK_SENSOR_48MHZ 48
159 #define write_cif_reg(base,addr, val) __raw_writel(val, addr+(base))
160 #define read_cif_reg(base,addr) __raw_readl(addr+(base))
161 #define mask_cif_reg(addr, msk, val) write_cif_reg(addr, (val)|((~(msk))&read_cif_reg(addr)))
163 #if defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK3188)
165 #define CRU_PCLK_REG30 0xbc
166 #define ENANABLE_INVERT_PCLK_CIF0 ((0x1<<24)|(0x1<<8))
167 #define DISABLE_INVERT_PCLK_CIF0 ((0x1<<24)|(0x0<<8))
168 #define ENANABLE_INVERT_PCLK_CIF1 ((0x1<<28)|(0x1<<12))
169 #define DISABLE_INVERT_PCLK_CIF1 ((0x1<<28)|(0x0<<12))
171 #define CRU_CIF_RST_REG30 0x128
172 #define MASK_RST_CIF0 (0x01 << 30)
173 #define MASK_RST_CIF1 (0x01 << 31)
174 #define RQUEST_RST_CIF0 (0x01 << 14)
175 #define RQUEST_RST_CIF1 (0x01 << 15)
177 #define write_cru_reg(addr, val) __raw_writel(val, addr+RK30_CRU_BASE)
178 #define read_cru_reg(addr) __raw_readl(addr+RK30_CRU_BASE)
179 #define mask_cru_reg(addr, msk, val) write_cru_reg(addr,(val)|((~(msk))&read_cru_reg(addr)))
182 #if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)
184 #define CIF_DRIVER_STRENGTH_2MA (0x00 << 12)
185 #define CIF_DRIVER_STRENGTH_4MA (0x01 << 12)
186 #define CIF_DRIVER_STRENGTH_8MA (0x02 << 12)
187 #define CIF_DRIVER_STRENGTH_12MA (0x03 << 12)
188 #define CIF_DRIVER_STRENGTH_MASK (0x03 << 28)
191 #define CIF_CLKOUT_AMP_3V3 (0x00 << 10)
192 #define CIF_CLKOUT_AMP_1V8 (0x01 << 10)
193 #define CIF_CLKOUT_AMP_MASK (0x01 << 26)
195 #define write_grf_reg(addr, val) __raw_writel(val, addr+RK30_GRF_BASE)
196 #define read_grf_reg(addr) __raw_readl(addr+RK30_GRF_BASE)
197 #define mask_grf_reg(addr, msk, val) write_grf_reg(addr,(val)|((~(msk))&read_grf_reg(addr)))
199 #define write_grf_reg(addr, val)
200 #define read_grf_reg(addr) 0
201 #define mask_grf_reg(addr, msk, val)
204 #if defined(CONFIG_ARCH_RK2928)
205 #define write_cru_reg(addr, val)
206 #define read_cru_reg(addr) 0
207 #define mask_cru_reg(addr, msk, val)
211 //when work_with_ipp is not enabled,CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_OFF is not defined.something wrong with it
212 #ifdef CONFIG_VIDEO_RK29_WORK_IPP//CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_OFF
213 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_OFF
214 #define CAM_WORKQUEUE_IS_EN() ((pcdev->host_width != pcdev->icd->user_width) || (pcdev->host_height != pcdev->icd->user_height)\
215 || (pcdev->icd_cb.sensor_cb))
216 #define CAM_IPPWORK_IS_EN() ((pcdev->host_width != pcdev->icd->user_width) || (pcdev->host_height != pcdev->icd->user_height))
218 #define CAM_WORKQUEUE_IS_EN() (true)
219 #define CAM_IPPWORK_IS_EN() ((pcdev->zoominfo.a.c.width != pcdev->icd->user_width) || (pcdev->zoominfo.a.c.height != pcdev->icd->user_height))
221 #else //CONFIG_VIDEO_RK29_WORK_IPP
222 #define CAM_WORKQUEUE_IS_EN() (false)
223 #define CAM_IPPWORK_IS_EN() (false)
226 #define IS_CIF0() (pcdev->hostid == RK_CAM_PLATFORM_DEV_ID_0)
227 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP)
228 #define CROP_ALIGN_BYTES (0x03)
229 #define CIF_DO_CROP 0
230 #elif (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_ARM)
231 #define CROP_ALIGN_BYTES (0x03)
232 #define CIF_DO_CROP 0
233 #elif (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_RGA)
234 #define CROP_ALIGN_BYTES (0x03)
235 #define CIF_DO_CROP 0
236 #elif(CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_PP)
237 #define CROP_ALIGN_BYTES (0x0F)
238 #define CIF_DO_CROP 1
242 * Driver Version Note
244 *v0.0.x : this driver is 2.6.32 kernel driver;
245 *v0.1.x : this driver is 3.0.8 kernel driver;
247 *v0.x.1 : this driver first support rk2918;
248 *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
249 * and V4L2_PIX_FMT_YUV422P;
250 *v0.x.3 : this driver support VIDIOC_ENUM_FRAMEINTERVALS;
251 *v0.x.4 : this driver support digital zoom;
252 *v0.x.5 : this driver support test framerate and query framerate from board file configuration;
253 *v0.x.6 : this driver improve test framerate method;
254 *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
255 we do crop with cif and do scale with ipp , we will fix this next version.
256 *v0.x.8 : temp version,reinit capture list when setup video buf.
257 *v0.x.9 : 1. add the case of IPP unsupportted ,just cropped by CIF(not do the scale) this version.
258 2. flush workqueue when releas buffer
259 *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
261 2. when the flash is on ,flash off in a fixed time to prevent from flash light too hot.
262 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
263 4. add menu configs for convineuent to customize sensor series
264 *v0.x.b: specify the version is NOT sure stable.
265 *v0.x.c: 1. add cif reset when resolution changed to avoid of collecting data erro
266 2. irq process is splitted to two step.
267 *v0.x.e: fix bugs of early suspend when display_pd is closed.
268 *v0.x.f: fix calculate ipp memory size is enough or not in try_fmt function;
269 *v0.x.11: fix struct rk_camera_work may be reentrant
270 *v0.x.13: 1.add scale by arm,rga and pp.
271 2.CIF do the crop when digital zoom.
272 3.fix bug in prob func:request mem twice.
273 4.video_vq may be null when reinit work,fix it
274 5.arm scale algorithm has something wrong(may exceed the bound of width or height) ,fix it.
276 * 1. support rk3066b;
278 * 1. support 8Mega picture;
280 * 1. invalidate the limit which scale is invalidat when scale ratio > 2;
281 *v0.x.1b: 1. fix oops bug when using arm to do scale_crop if preview buffer is not allocated correctly
282 2. rk_camera_set_fmt will called twice, optimize the procedure. at the first time call ,just to do the sensor init.
285 * 1. fix query resolution error;
287 * 1. add mv9335+ov5650 driver;
288 * 2. fix 2928 digitzoom erro(arm crop scale) of selected zone;
290 * 1. support rk3188; Must soft reset cif controller after each frame irq;
292 #define RK_CAM_VERSION_CODE KERNEL_VERSION(0, 2, 0x1f)
294 /* limit to rk29 hardware capabilities */
295 #define RK_CAM_BUS_PARAM (SOCAM_MASTER |\
296 SOCAM_HSYNC_ACTIVE_HIGH |\
297 SOCAM_HSYNC_ACTIVE_LOW |\
298 SOCAM_VSYNC_ACTIVE_HIGH |\
299 SOCAM_VSYNC_ACTIVE_LOW |\
300 SOCAM_PCLK_SAMPLE_RISING |\
301 SOCAM_PCLK_SAMPLE_FALLING|\
302 SOCAM_DATA_ACTIVE_HIGH |\
303 SOCAM_DATA_ACTIVE_LOW|\
304 SOCAM_DATAWIDTH_8|SOCAM_DATAWIDTH_10|\
305 SOCAM_MCLK_24MHZ |SOCAM_MCLK_48MHZ)
307 #define RK_CAM_W_MIN 48
308 #define RK_CAM_H_MIN 32
309 #define RK_CAM_W_MAX 3856 /* ddl@rock-chips.com : 10M Pixel */
310 #define RK_CAM_H_MAX 2764
311 #define RK_CAM_FRAME_INVAL_INIT 3
312 #define RK_CAM_FRAME_INVAL_DC 3 /* ddl@rock-chips.com : */
313 #define RK30_CAM_FRAME_MEASURE 5
314 extern void videobuf_dma_contig_free(struct videobuf_queue *q, struct videobuf_buffer *buf);
315 extern dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf);
316 /* buffer for one video frame */
317 struct rk_camera_buffer
319 /* common v4l buffer stuff -- must be first */
320 struct videobuf_buffer vb;
321 enum v4l2_mbus_pixelcode code;
324 enum rk_camera_reg_state
332 unsigned int cifCtrl;
333 unsigned int cifCrop;
335 unsigned int cifIntEn;
337 unsigned int cifVirWidth;
338 unsigned int cifScale;
339 // unsigned int VipCrm;
340 enum rk_camera_reg_state Inval;
342 struct rk_camera_work
344 struct videobuf_buffer *vb;
345 struct rk_camera_dev *pcdev;
346 struct work_struct work;
347 struct list_head queue;
350 struct rk_camera_frmivalenum
352 struct v4l2_frmivalenum fival;
353 struct rk_camera_frmivalenum *nxt;
355 struct rk_camera_frmivalinfo
357 struct soc_camera_device *icd;
358 struct rk_camera_frmivalenum *fival_list;
360 struct rk_camera_zoominfo
362 struct semaphore sem;
368 #if CAMERA_VIDEOBUF_ARM_ACCESS
369 struct rk29_camera_vbinfo
371 unsigned int phy_addr;
372 void __iomem *vir_addr;
376 struct rk_camera_timer{
377 struct rk_camera_dev *pcdev;
378 struct hrtimer timer;
383 struct soc_camera_host soc_host;
385 /* RK2827x is only supposed to handle one camera on its Quick Capture
386 * interface. If anyone ever builds hardware to enable more than
387 * one camera, they will have to modify this driver too */
388 struct soc_camera_device *icd;
390 //************must modify start************/
392 struct clk *aclk_cif;
393 struct clk *hclk_cif;
394 struct clk *cif_clk_in;
395 struct clk *cif_clk_out;
396 //************must modify end************/
398 int frame_inval; /* ddl@rock-chips.com : The first frames is invalidate */
401 unsigned int last_fps;
402 unsigned long frame_interval;
405 unsigned int vipmem_phybase;
406 void __iomem *vipmem_virbase;
407 unsigned int vipmem_size;
408 unsigned int vipmem_bsize;
409 #if CAMERA_VIDEOBUF_ARM_ACCESS
410 struct rk29_camera_vbinfo *vbinfo;
411 unsigned int vbinfo_count;
415 int host_left; //sensor output size ?
421 struct rk29camera_platform_data *pdata;
422 struct resource *res;
423 struct list_head capture;
424 struct rk_camera_zoominfo zoominfo;
428 struct videobuf_buffer *active;
429 struct rk_camera_reg reginfo_suspend;
430 struct workqueue_struct *camera_wq;
431 struct rk_camera_work *camera_work;
432 struct list_head camera_work_queue;
433 spinlock_t camera_work_lock;
434 unsigned int camera_work_count;
435 struct rk_camera_timer fps_timer;
436 struct rk_camera_work camera_reinit_work;
438 rk29_camera_sensor_cb_s icd_cb;
439 struct rk_camera_frmivalinfo icd_frmival[2];
440 // atomic_t to_process_frames;
442 unsigned int reinit_times;
443 struct videobuf_queue *video_vq;
445 struct timeval first_tv;
448 static const struct v4l2_queryctrl rk_camera_controls[] =
450 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
452 .id = V4L2_CID_ZOOM_ABSOLUTE,
453 .type = V4L2_CTRL_TYPE_INTEGER,
454 .name = "DigitalZoom Control",
458 .default_value = 100,
463 static DEFINE_MUTEX(camera_lock);
464 static const char *rk_cam_driver_description = "RK_Camera";
466 static int rk_camera_s_stream(struct soc_camera_device *icd, int enable);
467 static void rk_camera_capture_process(struct work_struct *work);
471 * Videobuf operations
473 static int rk_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
476 struct soc_camera_device *icd = vq->priv_data;
477 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
478 struct rk_camera_dev *pcdev = ici->priv;
480 struct rk_camera_work *wk;
482 struct soc_mbus_pixelfmt fmt;
484 int bytes_per_line_host;
485 fmt.packing = SOC_MBUS_PACKING_1_5X8;
487 bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
488 icd->current_fmt->host_fmt);
489 if(icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_RGB565)
490 bytes_per_line_host = soc_mbus_bytes_per_line(pcdev->host_width,
492 else if(icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_RGB24)
493 bytes_per_line_host = pcdev->host_width*3;
495 bytes_per_line_host = soc_mbus_bytes_per_line(pcdev->host_width,
496 icd->current_fmt->host_fmt);
497 dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size);
499 if (bytes_per_line_host < 0)
500 return bytes_per_line_host;
502 /* planar capture requires Y, U and V buffers to be page aligned */
503 *size = PAGE_ALIGN(bytes_per_line*icd->user_height); /* Y pages UV pages, yuv422*/
504 pcdev->vipmem_bsize = PAGE_ALIGN(bytes_per_line_host * pcdev->host_height);
506 if (CAM_WORKQUEUE_IS_EN()) {
507 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_OFF
508 if (CAM_IPPWORK_IS_EN())
511 BUG_ON(pcdev->vipmem_size<pcdev->vipmem_bsize);
512 if (*count > pcdev->vipmem_size/pcdev->vipmem_bsize) { /* Buffers must be limited, when this resolution is genered by IPP */
513 *count = pcdev->vipmem_size/pcdev->vipmem_bsize;
516 if ((pcdev->camera_work_count != *count) && pcdev->camera_work) {
517 kfree(pcdev->camera_work);
518 pcdev->camera_work = NULL;
519 pcdev->camera_work_count = 0;
522 if (pcdev->camera_work == NULL) {
523 pcdev->camera_work = wk = kzalloc(sizeof(struct rk_camera_work)*(*count), GFP_KERNEL);
524 if (pcdev->camera_work == NULL) {
525 RKCAMERA_TR("\n %s kmalloc fail\n", __FUNCTION__);
528 INIT_LIST_HEAD(&pcdev->camera_work_queue);
530 for (i=0; i<(*count); i++) {
532 list_add_tail(&wk->queue, &pcdev->camera_work_queue);
535 pcdev->camera_work_count = (*count);
537 #if CAMERA_VIDEOBUF_ARM_ACCESS
538 if (pcdev->vbinfo && (pcdev->vbinfo_count != *count)) {
539 kfree(pcdev->vbinfo);
540 pcdev->vbinfo = NULL;
541 pcdev->vbinfo_count = 0x00;
544 if (pcdev->vbinfo == NULL) {
545 pcdev->vbinfo = kzalloc(sizeof(struct rk29_camera_vbinfo)*(*count), GFP_KERNEL);
546 if (pcdev->vbinfo == NULL) {
547 RKCAMERA_TR("\n %s vbinfo kmalloc fail\n", __FUNCTION__);
550 memset(pcdev->vbinfo,0,sizeof(struct rk29_camera_vbinfo)*(*count));
551 pcdev->vbinfo_count = *count;
555 pcdev->video_vq = vq;
556 RKCAMERA_DG("%s..%d.. videobuf size:%d, vipmem_buf size:%d, count:%d \n",__FUNCTION__,__LINE__, *size,pcdev->vipmem_size, *count);
560 static void rk_videobuf_free(struct videobuf_queue *vq, struct rk_camera_buffer *buf)
562 struct soc_camera_device *icd = vq->priv_data;
564 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
565 &buf->vb, buf->vb.baddr, buf->vb.bsize);
567 /* ddl@rock-chips.com: buf_release called soc_camera_streamoff and soc_camera_close*/
568 if (buf->vb.state == VIDEOBUF_NEEDS_INIT)
574 * This waits until this buffer is out of danger, i.e., until it is no
575 * longer in STATE_QUEUED or STATE_ACTIVE
577 //videobuf_waiton(vq, &buf->vb, 0, 0);
578 videobuf_dma_contig_free(vq, &buf->vb);
579 dev_dbg(&icd->dev, "%s freed\n", __func__);
580 buf->vb.state = VIDEOBUF_NEEDS_INIT;
583 static int rk_videobuf_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, enum v4l2_field field)
585 struct soc_camera_device *icd = vq->priv_data;
586 struct rk_camera_buffer *buf;
588 int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
589 icd->current_fmt->host_fmt);
590 if ((bytes_per_line < 0) || (vb->boff == 0))
593 buf = container_of(vb, struct rk_camera_buffer, vb);
595 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
596 vb, vb->baddr, vb->bsize);
598 /* Added list head initialization on alloc */
599 WARN_ON(!list_empty(&vb->queue));
601 BUG_ON(NULL == icd->current_fmt);
603 if (buf->code != icd->current_fmt->code ||
604 vb->width != icd->user_width ||
605 vb->height != icd->user_height ||
606 vb->field != field) {
607 buf->code = icd->current_fmt->code;
608 vb->width = icd->user_width;
609 vb->height = icd->user_height;
611 vb->state = VIDEOBUF_NEEDS_INIT;
614 vb->size = bytes_per_line*vb->height; /* ddl@rock-chips.com : fmt->depth is coorect */
615 if (0 != vb->baddr && vb->bsize < vb->size) {
620 if (vb->state == VIDEOBUF_NEEDS_INIT) {
621 ret = videobuf_iolock(vq, vb, NULL);
625 vb->state = VIDEOBUF_PREPARED;
630 rk_videobuf_free(vq, buf);
634 static void rk_camera_store_register(struct rk_camera_dev *pcdev)
636 #if defined(CONFIG_ARCH_RK3188)
637 pcdev->reginfo_suspend.cifCtrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
638 pcdev->reginfo_suspend.cifCrop = read_cif_reg(pcdev->base,CIF_CIF_CROP);
639 pcdev->reginfo_suspend.cifFs = read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE);
640 pcdev->reginfo_suspend.cifIntEn = read_cif_reg(pcdev->base,CIF_CIF_INTEN);
641 pcdev->reginfo_suspend.cifFmt= read_cif_reg(pcdev->base,CIF_CIF_FOR);
642 pcdev->reginfo_suspend.cifVirWidth = read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH);
643 pcdev->reginfo_suspend.cifScale= read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL);
645 cru_set_soft_reset(SOFT_RST_CIF0, true);
647 cru_set_soft_reset(SOFT_RST_CIF0, false);
651 static void rk_camera_restore_register(struct rk_camera_dev *pcdev)
653 #if defined(CONFIG_ARCH_RK3188)
654 write_cif_reg(pcdev->base,CIF_CIF_CTRL, pcdev->reginfo_suspend.cifCtrl&~ENABLE_CAPTURE);
655 write_cif_reg(pcdev->base,CIF_CIF_INTEN, pcdev->reginfo_suspend.cifIntEn);
656 write_cif_reg(pcdev->base,CIF_CIF_CROP, pcdev->reginfo_suspend.cifCrop);
657 write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, pcdev->reginfo_suspend.cifFs);
658 write_cif_reg(pcdev->base,CIF_CIF_FOR, pcdev->reginfo_suspend.cifFmt);
659 write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH,pcdev->reginfo_suspend.cifVirWidth);
660 write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL, pcdev->reginfo_suspend.cifScale);
663 static inline void rk_videobuf_capture(struct videobuf_buffer *vb,struct rk_camera_dev *rk_pcdev)
665 unsigned int y_addr,uv_addr;
666 struct rk_camera_dev *pcdev = rk_pcdev;
669 if (CAM_WORKQUEUE_IS_EN()) {
670 y_addr = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
671 uv_addr = y_addr + pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height;
672 if (y_addr > (pcdev->vipmem_phybase + pcdev->vipmem_size - pcdev->vipmem_bsize)) {
673 RKCAMERA_TR("vipmem for IPP is overflow! %dx%d -> %dx%d vb_index:%d\n",pcdev->host_width,pcdev->host_height,
674 pcdev->icd->user_width,pcdev->icd->user_height, vb->i);
679 uv_addr = y_addr + vb->width * vb->height;
681 #if defined(CONFIG_ARCH_RK3188)
682 rk_camera_store_register(pcdev);
683 rk_camera_restore_register(pcdev);
685 write_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y, y_addr);
686 write_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV, uv_addr);
687 write_cif_reg(pcdev->base,CIF_CIF_FRM1_ADDR_Y, y_addr);
688 write_cif_reg(pcdev->base,CIF_CIF_FRM1_ADDR_UV, uv_addr);
689 write_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS, 0x00000002);//frame1 has been ready to receive data,frame 2 is not used
690 #if defined(CONFIG_ARCH_RK3188)
691 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL) | ENABLE_CAPTURE));
695 /* Locking: Caller holds q->irqlock */
696 static void rk_videobuf_queue(struct videobuf_queue *vq,
697 struct videobuf_buffer *vb)
699 struct soc_camera_device *icd = vq->priv_data;
700 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
701 struct rk_camera_dev *pcdev = ici->priv;
702 #if CAMERA_VIDEOBUF_ARM_ACCESS
703 struct rk29_camera_vbinfo *vb_info;
706 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
707 vb, vb->baddr, vb->bsize);
709 vb->state = VIDEOBUF_QUEUED;
710 if (list_empty(&pcdev->capture)) {
711 list_add_tail(&vb->queue, &pcdev->capture);
713 if (list_entry(pcdev->capture.next, struct videobuf_buffer, queue) != vb)
714 list_add_tail(&vb->queue, &pcdev->capture);
716 BUG(); /* ddl@rock-chips.com : The same videobuffer queue again */
718 #if CAMERA_VIDEOBUF_ARM_ACCESS
720 vb_info = pcdev->vbinfo+vb->i;
721 if ((vb_info->phy_addr != vb->boff) || (vb_info->size != vb->bsize)) {
722 if (vb_info->vir_addr) {
723 iounmap(vb_info->vir_addr);
724 release_mem_region(vb_info->phy_addr, vb_info->size);
725 vb_info->vir_addr = NULL;
726 vb_info->phy_addr = 0x00;
727 vb_info->size = 0x00;
730 if (request_mem_region(vb->boff,vb->bsize,"rk_camera_vb")) {
731 vb_info->vir_addr = ioremap_cached(vb->boff,vb->bsize);
734 if (vb_info->vir_addr) {
735 vb_info->size = vb->bsize;
736 vb_info->phy_addr = vb->boff;
738 RKCAMERA_TR("%s..%d:ioremap videobuf %d failed\n",__FUNCTION__,__LINE__, vb->i);
743 if (!pcdev->active) {
745 rk_videobuf_capture(vb,pcdev);
748 static int rk_pixfmt2ippfmt(unsigned int pixfmt, int *ippfmt)
752 case V4L2_PIX_FMT_NV16:
753 case V4L2_PIX_FMT_NV61:
755 *ippfmt = IPP_Y_CBCR_H2V1;
758 case V4L2_PIX_FMT_NV12:
759 case V4L2_PIX_FMT_NV21:
761 *ippfmt = IPP_Y_CBCR_H2V2;
765 goto rk_pixfmt2ippfmt_err;
769 rk_pixfmt2ippfmt_err:
773 static int rk_pixfmt2rgafmt(unsigned int pixfmt, int *ippfmt)
777 case V4L2_PIX_FMT_YUV420:
778 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.
779 case V4L2_PIX_FMT_YUYV:
781 *ippfmt = RK_FORMAT_YCbCr_420_SP;
784 case V4L2_PIX_FMT_YVU420:
785 case V4L2_PIX_FMT_VYUY:
786 case V4L2_PIX_FMT_YVYU:
788 *ippfmt = RK_FORMAT_YCrCb_420_SP;
791 case V4L2_PIX_FMT_RGB565:
793 *ippfmt = RK_FORMAT_RGB_565;
796 case V4L2_PIX_FMT_RGB24:
798 *ippfmt = RK_FORMAT_RGB_888;
802 goto rk_pixfmt2rgafmt_err;
806 rk_pixfmt2rgafmt_err:
809 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_PP)
810 static int rk_camera_scale_crop_pp(struct work_struct *work){
811 struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
812 struct videobuf_buffer *vb = camera_work->vb;
813 struct rk_camera_dev *pcdev = camera_work->pcdev;
815 unsigned long int flags;
821 vipdata_base = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
823 memset(&init, 0, sizeof(init));
824 init.srcAddr = vipdata_base;
825 init.srcFormat = PP_IN_FORMAT_YUV420SEMI;
826 init.srcWidth = init.srcHStride = pcdev->zoominfo.vir_width;
827 init.srcHeight = init.srcVStride = pcdev->zoominfo.vir_height;
829 init.dstAddr = vb->boff;
830 init.dstFormat = PP_OUT_FORMAT_YUV420INTERLAVE;
831 init.dstWidth = init.dstHStride = pcdev->icd->user_width;
832 init.dstHeight = init.dstVStride = pcdev->icd->user_height;
834 printk("srcWidth = %d,srcHeight = %d,dstWidth = %d,dstHeight = %d\n",init.srcWidth,init.srcHeight,init.dstWidth,init.dstHeight);
836 ret = ppOpInit(&hnd, &init);
842 printk("can not create ppOp handle\n");
848 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_RGA)
849 extern rga_service_info rga_service;
850 extern int rga_blit_sync(rga_session *session, struct rga_req *req);
851 extern void rga_service_session_clear(rga_session *session);
852 static int rk_camera_scale_crop_rga(struct work_struct *work){
853 struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
854 struct videobuf_buffer *vb = camera_work->vb;
855 struct rk_camera_dev *pcdev = camera_work->pcdev;
857 unsigned long int flags;
863 const struct soc_mbus_pixelfmt *fmt;
865 fmt = soc_mbus_get_fmtdesc(pcdev->icd->current_fmt->code);
866 vipdata_base = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
867 if((pcdev->icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_RGB565)
868 && (pcdev->icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_RGB24)){
869 RKCAMERA_TR("RGA not support this format !\n");
872 if ((pcdev->icd->user_width > 0x800) || (pcdev->icd->user_height > 0x800)) {
873 scale_times = MAX((pcdev->icd->user_width/0x800),(pcdev->icd->user_height/0x800));
878 session.pid = current->pid;
879 INIT_LIST_HEAD(&session.waiting);
880 INIT_LIST_HEAD(&session.running);
881 INIT_LIST_HEAD(&session.list_session);
882 init_waitqueue_head(&session.wait);
883 /* no need to protect */
884 list_add_tail(&session.list_session, &rga_service.session);
885 atomic_set(&session.task_running, 0);
886 atomic_set(&session.num_done, 0);
888 memset(&req,0,sizeof(struct rga_req));
889 req.src.act_w = pcdev->zoominfo.a.c.width/scale_times;
890 req.src.act_h = pcdev->zoominfo.a.c.height/scale_times;
892 req.src.vir_w = pcdev->zoominfo.vir_width;
893 req.src.vir_h =pcdev->zoominfo.vir_height;
894 req.src.yrgb_addr = vipdata_base;
895 req.src.uv_addr =vipdata_base + pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height;;
896 req.src.v_addr = req.src.uv_addr ;
897 req.src.format =fmt->fourcc;
898 rk_pixfmt2rgafmt(fmt->fourcc,&req.src.format);
899 req.src.x_offset = pcdev->zoominfo.a.c.left;
900 req.src.y_offset = pcdev->zoominfo.a.c.top;
902 req.dst.act_w = pcdev->icd->user_width/scale_times;
903 req.dst.act_h = pcdev->icd->user_height/scale_times;
905 req.dst.vir_w = pcdev->icd->user_width;
906 req.dst.vir_h = pcdev->icd->user_height;
907 req.dst.x_offset = 0;
908 req.dst.y_offset = 0;
909 req.dst.yrgb_addr = vb->boff;
910 rk_pixfmt2rgafmt(pcdev->icd->current_fmt->host_fmt->fourcc,&req.dst.format);
912 req.clip.xmax = req.dst.vir_w-1;
914 req.clip.ymax = req.dst.vir_h -1;
921 req.mmu_info.mmu_en = 0;
923 for (h=0; h<scale_times; h++) {
924 for (w=0; w<scale_times; w++) {
927 req.src.yrgb_addr = vipdata_base;
928 req.src.uv_addr =vipdata_base + pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height;;
929 req.src.x_offset = pcdev->zoominfo.a.c.left+w*pcdev->zoominfo.a.c.width/scale_times;
930 req.src.y_offset = pcdev->zoominfo.a.c.top+h*pcdev->zoominfo.a.c.height/scale_times;
931 req.dst.x_offset = pcdev->icd->user_width*w/scale_times;
932 req.dst.y_offset = pcdev->icd->user_height*h/scale_times;
933 req.dst.yrgb_addr = vb->boff ;
934 // 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);
935 // 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);
936 // RKCAMERA_TR("req.src.yrgb_addr = 0x%x,req.dst.yrgb_addr = 0x%x\n",req.src.yrgb_addr,req.dst.yrgb_addr);
938 while(rga_times-- > 0) {
939 if (rga_blit_sync(&session, &req)){
940 RKCAMERA_TR("rga do erro,do again,rga_times = %d!\n",rga_times);
946 if (rga_times <= 0) {
947 spin_lock_irqsave(&pcdev->lock, flags);
948 vb->state = VIDEOBUF_NEEDS_INIT;
949 spin_unlock_irqrestore(&pcdev->lock, flags);
950 mutex_lock(&rga_service.lock);
951 list_del(&session.list_session);
952 rga_service_session_clear(&session);
953 mutex_unlock(&rga_service.lock);
959 mutex_lock(&rga_service.lock);
960 list_del(&session.list_session);
961 rga_service_session_clear(&session);
962 mutex_unlock(&rga_service.lock);
971 #if ((defined(CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON)) && (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP))
973 static int rk_camera_scale_crop_ipp(struct work_struct *work)
975 struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
976 struct videobuf_buffer *vb = camera_work->vb;
977 struct rk_camera_dev *pcdev = camera_work->pcdev;
979 unsigned long int flags;
981 struct rk29_ipp_req ipp_req;
982 int src_y_offset,src_uv_offset,dst_y_offset,dst_uv_offset,src_y_size,dst_y_size;
988 * IPP Dest image resolution is 2047x1088, so scale operation break up some times
990 if ((pcdev->icd->user_width > 0x7f0) || (pcdev->icd->user_height > 0x430)) {
991 scale_times = MAX((pcdev->icd->user_width/0x7f0),(pcdev->icd->user_height/0x430));
996 memset(&ipp_req, 0, sizeof(struct rk29_ipp_req));
999 ipp_req.timeout = 3000;
1000 ipp_req.flag = IPP_ROT_0;
1001 ipp_req.store_clip_mode =1;
1002 ipp_req.src0.w = pcdev->zoominfo.a.c.width/scale_times;
1003 ipp_req.src0.h = pcdev->zoominfo.a.c.height/scale_times;
1004 ipp_req.src_vir_w = pcdev->zoominfo.vir_width;
1005 rk_pixfmt2ippfmt(pcdev->pixfmt, &ipp_req.src0.fmt);
1006 ipp_req.dst0.w = pcdev->icd->user_width/scale_times;
1007 ipp_req.dst0.h = pcdev->icd->user_height/scale_times;
1008 ipp_req.dst_vir_w = pcdev->icd->user_width;
1009 rk_pixfmt2ippfmt(pcdev->pixfmt, &ipp_req.dst0.fmt);
1010 vipdata_base = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
1011 src_y_size = pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height; //vipmem
1012 dst_y_size = pcdev->icd->user_width*pcdev->icd->user_height;
1013 for (h=0; h<scale_times; h++) {
1014 for (w=0; w<scale_times; w++) {
1016 src_y_offset = (pcdev->zoominfo.a.c.top + h*pcdev->zoominfo.a.c.height/scale_times)* pcdev->zoominfo.vir_width
1017 + pcdev->zoominfo.a.c.left + w*pcdev->zoominfo.a.c.width/scale_times;
1018 src_uv_offset = (pcdev->zoominfo.a.c.top + h*pcdev->zoominfo.a.c.height/scale_times)* pcdev->zoominfo.vir_width/2
1019 + pcdev->zoominfo.a.c.left + w*pcdev->zoominfo.a.c.width/scale_times;
1021 dst_y_offset = pcdev->icd->user_width*pcdev->icd->user_height*h/scale_times + pcdev->icd->user_width*w/scale_times;
1022 dst_uv_offset = pcdev->icd->user_width*pcdev->icd->user_height*h/scale_times/2 + pcdev->icd->user_width*w/scale_times;
1024 ipp_req.src0.YrgbMst = vipdata_base + src_y_offset;
1025 ipp_req.src0.CbrMst = vipdata_base + src_y_size + src_uv_offset;
1026 ipp_req.dst0.YrgbMst = vb->boff + dst_y_offset;
1027 ipp_req.dst0.CbrMst = vb->boff + dst_y_size + dst_uv_offset;
1028 while(ipp_times-- > 0) {
1029 if (ipp_blit_sync(&ipp_req)){
1030 RKCAMERA_TR("ipp do erro,do again,ipp_times = %d!\n",ipp_times);
1036 if (ipp_times <= 0) {
1037 spin_lock_irqsave(&pcdev->lock, flags);
1038 vb->state = VIDEOBUF_NEEDS_INIT;
1039 spin_unlock_irqrestore(&pcdev->lock, flags);
1040 RKCAMERA_TR("Capture image(vb->i:0x%x) which IPP operated is error:\n",vb->i);
1041 RKCAMERA_TR("widx:%d hidx:%d ",w,h);
1042 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);
1043 RKCAMERA_TR("ipp_req.src0.YrgbMst:0x%x ipp_req.src0.CbrMst:0x%x \n", ipp_req.src0.YrgbMst,ipp_req.src0.CbrMst);
1044 RKCAMERA_TR("ipp_req.src0.w:0x%x ipp_req.src0.h:0x%x \n",ipp_req.src0.w,ipp_req.src0.h);
1045 RKCAMERA_TR("ipp_req.src0.fmt:0x%x\n",ipp_req.src0.fmt);
1046 RKCAMERA_TR("ipp_req.dst0.YrgbMst:0x%x ipp_req.dst0.CbrMst:0x%x \n",ipp_req.dst0.YrgbMst,ipp_req.dst0.CbrMst);
1047 RKCAMERA_TR("ipp_req.dst0.w:0x%x ipp_req.dst0.h:0x%x \n",ipp_req.dst0.w ,ipp_req.dst0.h);
1048 RKCAMERA_TR("ipp_req.dst0.fmt:0x%x\n",ipp_req.dst0.fmt);
1049 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);
1050 RKCAMERA_TR("ipp_req.timeout:0x%x ipp_req.flag :0x%x\n",ipp_req.timeout,ipp_req.flag);
1060 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_ARM)
1061 static int rk_camera_scale_crop_arm(struct work_struct *work)
1063 struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
1064 struct videobuf_buffer *vb = camera_work->vb;
1065 struct rk_camera_dev *pcdev = camera_work->pcdev;
1066 struct rk29_camera_vbinfo *vb_info;
1067 unsigned char *psY,*pdY,*psUV,*pdUV;
1068 unsigned char *src,*dst;
1069 unsigned long src_phy,dst_phy;
1070 int srcW,srcH,cropW,cropH,dstW,dstH;
1071 long zoomindstxIntInv,zoomindstyIntInv;
1073 long yCoeff00,yCoeff01,xCoeff00,xCoeff01;
1078 src_phy = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
1079 src = psY = (unsigned char*)(pcdev->vipmem_virbase + vb->i*pcdev->vipmem_bsize);
1080 psUV = psY + pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height;
1082 srcW = pcdev->zoominfo.vir_width;
1083 srcH = pcdev->zoominfo.vir_height;
1084 cropW = pcdev->zoominfo.a.c.width;
1085 cropH = pcdev->zoominfo.a.c.height;
1087 psY = psY + pcdev->zoominfo.a.c.top*pcdev->zoominfo.vir_width+pcdev->zoominfo.a.c.left;
1088 psUV = psUV + pcdev->zoominfo.a.c.top*pcdev->zoominfo.vir_width/2+pcdev->zoominfo.a.c.left;
1090 vb_info = pcdev->vbinfo+vb->i;
1091 dst_phy = vb_info->phy_addr;
1092 dst = pdY = (unsigned char*)vb_info->vir_addr;
1093 pdUV = pdY + pcdev->icd->user_width*pcdev->icd->user_height;
1094 dstW = pcdev->icd->user_width;
1095 dstH = pcdev->icd->user_height;
1097 zoomindstxIntInv = ((unsigned long)(cropW)<<16)/dstW + 1;
1098 zoomindstyIntInv = ((unsigned long)(cropH)<<16)/dstH + 1;
1100 //for(y = 0; y<dstH - 1 ; y++ ) {
1101 for(y = 0; y<dstH; y++ ) {
1102 yCoeff00 = (y*zoomindstyIntInv)&0xffff;
1103 yCoeff01 = 0xffff - yCoeff00;
1104 sY = (y*zoomindstyIntInv >> 16);
1105 sY = (sY >= srcH - 1)? (srcH - 2) : sY;
1106 for(x = 0; x<dstW; x++ ) {
1107 xCoeff00 = (x*zoomindstxIntInv)&0xffff;
1108 xCoeff01 = 0xffff - xCoeff00;
1109 sX = (x*zoomindstxIntInv >> 16);
1110 sX = (sX >= srcW -1)?(srcW- 2) : sX;
1111 a = psY[sY*srcW + sX];
1112 b = psY[sY*srcW + sX + 1];
1113 c = psY[(sY+1)*srcW + sX];
1114 d = psY[(sY+1)*srcW + sX + 1];
1116 r0 = (a * xCoeff01 + b * xCoeff00)>>16 ;
1117 r1 = (c * xCoeff01 + d * xCoeff00)>>16 ;
1118 r0 = (r0 * yCoeff01 + r1 * yCoeff00)>>16;
1131 //for(y = 0; y<dstH - 1 ; y++ ) {
1132 for(y = 0; y<dstH; y++ ) {
1133 yCoeff00 = (y*zoomindstyIntInv)&0xffff;
1134 yCoeff01 = 0xffff - yCoeff00;
1135 sY = (y*zoomindstyIntInv >> 16);
1136 sY = (sY >= srcH -1)? (srcH - 2) : sY;
1137 for(x = 0; x<dstW; x++ ) {
1138 xCoeff00 = (x*zoomindstxIntInv)&0xffff;
1139 xCoeff01 = 0xffff - xCoeff00;
1140 sX = (x*zoomindstxIntInv >> 16);
1141 sX = (sX >= srcW -1)?(srcW- 2) : sX;
1143 a = psUV[(sY*srcW + sX)*2];
1144 b = psUV[(sY*srcW + sX + 1)*2];
1145 c = psUV[((sY+1)*srcW + sX)*2];
1146 d = psUV[((sY+1)*srcW + sX + 1)*2];
1148 r0 = (a * xCoeff01 + b * xCoeff00)>>16 ;
1149 r1 = (c * xCoeff01 + d * xCoeff00)>>16 ;
1150 r0 = (r0 * yCoeff01 + r1 * yCoeff00)>>16;
1155 a = psUV[(sY*srcW + sX)*2 + 1];
1156 b = psUV[(sY*srcW + sX + 1)*2 + 1];
1157 c = psUV[((sY+1)*srcW + sX)*2 + 1];
1158 d = psUV[((sY+1)*srcW + sX + 1)*2 + 1];
1160 r0 = (a * xCoeff01 + b * xCoeff00)>>16 ;
1161 r1 = (c * xCoeff01 + d * xCoeff00)>>16 ;
1162 r0 = (r0 * yCoeff01 + r1 * yCoeff00)>>16;
1168 rk_camera_scale_crop_arm_end:
1170 dmac_flush_range((void*)src,(void*)(src+pcdev->vipmem_bsize));
1171 outer_flush_range((phys_addr_t)src_phy,(phys_addr_t)(src_phy+pcdev->vipmem_bsize));
1173 dmac_flush_range((void*)dst,(void*)(dst+vb_info->size));
1174 outer_flush_range((phys_addr_t)dst_phy,(phys_addr_t)(dst_phy+vb_info->size));
1179 static void rk_camera_capture_process(struct work_struct *work)
1181 struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
1182 struct videobuf_buffer *vb = camera_work->vb;
1183 struct rk_camera_dev *pcdev = camera_work->pcdev;
1184 //enum v4l2_mbus_pixelcode icd_code = pcdev->icd->current_fmt->code;
1185 unsigned long flags = 0;
1188 if (!CAM_WORKQUEUE_IS_EN())
1189 goto rk_camera_capture_process_end;
1191 down(&pcdev->zoominfo.sem);
1192 if (pcdev->icd_cb.scale_crop_cb){
1193 err = (pcdev->icd_cb.scale_crop_cb)(work);
1195 up(&pcdev->zoominfo.sem);
1197 if (pcdev->icd_cb.sensor_cb)
1198 (pcdev->icd_cb.sensor_cb)(vb);
1200 rk_camera_capture_process_end:
1202 vb->state = VIDEOBUF_ERROR;
1204 if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) {
1205 vb->state = VIDEOBUF_DONE;
1209 wake_up(&(camera_work->vb->done));
1210 spin_lock_irqsave(&pcdev->camera_work_lock, flags);
1211 list_add_tail(&camera_work->queue, &pcdev->camera_work_queue);
1212 spin_unlock_irqrestore(&pcdev->camera_work_lock, flags);
1215 static irqreturn_t rk_camera_irq(int irq, void *data)
1217 struct rk_camera_dev *pcdev = data;
1218 struct videobuf_buffer *vb;
1219 struct rk_camera_work *wk;
1221 unsigned long tmp_intstat;
1222 unsigned long tmp_cifctrl;
1224 tmp_intstat = read_cif_reg(pcdev->base,CIF_CIF_INTSTAT);
1225 tmp_cifctrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
1226 if(pcdev->stop_cif == true)
1228 printk("cif has stopped by app,needn't to deal this irq\n");
1229 write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF); /* clear vip interrupte single */
1232 if ((tmp_intstat & 0x0200) /*&& ((tmp_intstat & 0x1)==0)*/){//bit9 =1 ,bit0 = 0
1233 write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0x0200); /* clear vip interrupte single */
1234 if(tmp_cifctrl & ENABLE_CAPTURE)
1235 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl & ~ENABLE_CAPTURE));
1239 /* ddl@rock-chps.com : Current VIP is run in One Frame Mode, Frame 1 is validate */
1240 if (read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS) & 0x01) {
1241 write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0x01); /* clear vip interrupte single */
1243 do_gettimeofday(&pcdev->first_tv);
1247 goto RK_CAMERA_IRQ_END;
1248 if (pcdev->frame_inval>0) {
1249 pcdev->frame_inval--;
1250 rk_videobuf_capture(pcdev->active,pcdev);
1251 goto RK_CAMERA_IRQ_END;
1252 } else if (pcdev->frame_inval) {
1253 RKCAMERA_TR("frame_inval : %0x",pcdev->frame_inval);
1254 pcdev->frame_inval = 0;
1256 if(pcdev->fps == RK30_CAM_FRAME_MEASURE) {
1257 do_gettimeofday(&tv);
1258 pcdev->frame_interval = ((tv.tv_sec*1000000 + tv.tv_usec) - (pcdev->first_tv.tv_sec*1000000 + pcdev->first_tv.tv_usec))
1259 /(RK30_CAM_FRAME_MEASURE-1);
1263 printk("no acticve buffer!!!\n");
1264 goto RK_CAMERA_IRQ_END;
1266 /* ddl@rock-chips.com : this vb may be deleted from queue */
1267 if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) {
1268 list_del_init(&vb->queue);
1270 pcdev->active = NULL;
1271 if (!list_empty(&pcdev->capture)) {
1272 pcdev->active = list_entry(pcdev->capture.next, struct videobuf_buffer, queue);
1273 if (pcdev->active) {
1274 WARN_ON(pcdev->active->state != VIDEOBUF_QUEUED);
1275 rk_videobuf_capture(pcdev->active,pcdev);
1278 if (pcdev->active == NULL) {
1279 RKCAMERA_DG("%s video_buf queue is empty!\n",__FUNCTION__);
1282 do_gettimeofday(&vb->ts);
1283 if (CAM_WORKQUEUE_IS_EN()) {
1284 if (!list_empty(&pcdev->camera_work_queue)) {
1285 wk = list_entry(pcdev->camera_work_queue.next, struct rk_camera_work, queue);
1286 list_del_init(&wk->queue);
1287 INIT_WORK(&(wk->work), rk_camera_capture_process);
1290 queue_work(pcdev->camera_wq, &(wk->work));
1293 if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) {
1294 vb->state = VIDEOBUF_DONE;
1303 if((tmp_cifctrl & ENABLE_CAPTURE) == 0)
1304 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl | ENABLE_CAPTURE));
1309 static void rk_videobuf_release(struct videobuf_queue *vq,
1310 struct videobuf_buffer *vb)
1312 struct rk_camera_buffer *buf = container_of(vb, struct rk_camera_buffer, vb);
1313 struct soc_camera_device *icd = vq->priv_data;
1314 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1315 struct rk_camera_dev *pcdev = ici->priv;
1316 #if CAMERA_VIDEOBUF_ARM_ACCESS
1317 struct rk29_camera_vbinfo *vb_info =NULL;
1321 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
1322 vb, vb->baddr, vb->bsize);
1326 case VIDEOBUF_ACTIVE:
1327 dev_dbg(&icd->dev, "%s (active)\n", __func__);
1329 case VIDEOBUF_QUEUED:
1330 dev_dbg(&icd->dev, "%s (queued)\n", __func__);
1332 case VIDEOBUF_PREPARED:
1333 dev_dbg(&icd->dev, "%s (prepared)\n", __func__);
1336 dev_dbg(&icd->dev, "%s (unknown)\n", __func__);
1340 if (vb == pcdev->active) {
1341 RKCAMERA_DG("%s Wait for this video buf(0x%x) write finished!\n ",__FUNCTION__,(unsigned int)vb);
1342 interruptible_sleep_on_timeout(&vb->done, msecs_to_jiffies(500));
1343 RKCAMERA_DG("%s This video buf(0x%x) write finished, release now!!\n",__FUNCTION__,(unsigned int)vb);
1346 flush_workqueue(pcdev->camera_wq);
1347 #if CAMERA_VIDEOBUF_ARM_ACCESS
1348 if ((pcdev->vbinfo) && (vb->i < pcdev->vbinfo_count)) {
1349 vb_info = pcdev->vbinfo + vb->i;
1351 if (vb_info->vir_addr) {
1352 iounmap(vb_info->vir_addr);
1353 release_mem_region(vb_info->phy_addr, vb_info->size);
1354 memset(vb_info, 0x00, sizeof(struct rk29_camera_vbinfo));
1359 rk_videobuf_free(vq, buf);
1362 static struct videobuf_queue_ops rk_videobuf_ops =
1364 .buf_setup = rk_videobuf_setup,
1365 .buf_prepare = rk_videobuf_prepare,
1366 .buf_queue = rk_videobuf_queue,
1367 .buf_release = rk_videobuf_release,
1370 static void rk_camera_init_videobuf(struct videobuf_queue *q,
1371 struct soc_camera_device *icd)
1373 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1374 struct rk_camera_dev *pcdev = ici->priv;
1376 /* We must pass NULL as dev pointer, then all pci_* dma operations
1377 * transform to normal dma_* ones. */
1378 videobuf_queue_dma_contig_init(q,
1380 ici->v4l2_dev.dev, &pcdev->lock,
1381 V4L2_BUF_TYPE_VIDEO_CAPTURE,
1383 sizeof(struct rk_camera_buffer),
1384 icd,&icd->video_lock);
1386 static int rk_camera_activate(struct rk_camera_dev *pcdev, struct soc_camera_device *icd)
1390 if(!pcdev->aclk_cif || !pcdev->hclk_cif || !pcdev->cif_clk_in || !pcdev->cif_clk_out){
1391 RKCAMERA_TR(KERN_ERR "failed to get cif clock source\n");
1393 goto RK_CAMERA_ACTIVE_ERR;
1396 clk_enable(pcdev->pd_cif);
1397 clk_enable(pcdev->aclk_cif);
1399 clk_enable(pcdev->hclk_cif);
1400 clk_enable(pcdev->cif_clk_in);
1402 //if (icd->ops->query_bus_param) /* ddl@rock-chips.com : Query Sensor's xclk */
1403 //sensor_bus_flags = icd->ops->query_bus_param(icd);
1404 clk_enable(pcdev->cif_clk_out);
1405 clk_set_rate(pcdev->cif_clk_out,RK_SENSOR_24MHZ);
1408 //soft reset the registers
1409 #if 0 //has somthing wrong when suspend and resume now
1411 printk("before set cru register reset cif0 0x%x\n\n",read_cru_reg(CRU_CIF_RST_REG30));
1414 printk("CIF_CIF_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CTRL));
1415 printk("CIF_CIF_INTEN = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTEN));
1416 printk("CIF_CIF_INTSTAT = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTSTAT));
1417 printk("CIF_CIF_FOR = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_FOR));
1418 printk("CIF_CIF_CROP = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CROP));
1419 printk("CIF_CIF_SET_SIZE = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE));
1420 printk("CIF_CIF_SCL_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL));
1421 printk("CRU_PCLK_REG30 = 0X%x\n",read_cru_reg(CRU_PCLK_REG30));
1422 printk("CIF_CIF_LAST_LINE = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_LINE));
1424 printk("CIF_CIF_LAST_PIX = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_PIX));
1425 printk("CIF_CIF_VIR_LINE_WIDTH = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH));
1426 printk("CIF_CIF_LINE_NUM_ADDR = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LINE_NUM_ADDR));
1427 printk("CIF_CIF_FRM0_ADDR_Y = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y));
1428 printk("CIF_CIF_FRM0_ADDR_UV = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV));
1429 printk("CIF_CIF_FRAME_STATUS = 0X%x\n\n",read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS));
1433 write_cru_reg(CRU_CIF_RST_REG30,(/*read_cru_reg(CRU_CIF_RST_REG30)|*/MASK_RST_CIF0|RQUEST_RST_CIF0 ));
1434 printk("set cru register reset cif0 0x%x\n",read_cru_reg(CRU_CIF_RST_REG30));
1435 write_cru_reg(CRU_CIF_RST_REG30,(read_cru_reg(CRU_CIF_RST_REG30)&(~RQUEST_RST_CIF0)) | MASK_RST_CIF0);
1437 printk("clean cru register reset cif0 0x%x\n",read_cru_reg(CRU_CIF_RST_REG30));
1439 write_cru_reg(CRU_CIF_RST_REG30,MASK_RST_CIF1|RQUEST_RST_CIF1 | (read_cru_reg(CRU_CIF_RST_REG30)));
1440 write_cru_reg(CRU_CIF_RST_REG30,(read_cru_reg(CRU_CIF_RST_REG30)&(~RQUEST_RST_CIF1)) | MASK_RST_CIF1);
1443 write_cif_reg(pcdev->base,CIF_CIF_CTRL,AXI_BURST_16|MODE_ONEFRAME|DISABLE_CAPTURE); /* ddl@rock-chips.com : vip ahb burst 16 */
1444 write_cif_reg(pcdev->base,CIF_CIF_INTEN, 0x01); //capture complete interrupt enable
1445 RKCAMERA_DG("%s..%d.. CIF_CIF_CTRL = 0x%x\n",__FUNCTION__,__LINE__,read_cif_reg(pcdev->base, CIF_CIF_CTRL));
1447 RK_CAMERA_ACTIVE_ERR:
1451 static void rk_camera_deactivate(struct rk_camera_dev *pcdev)
1453 clk_disable(pcdev->aclk_cif);
1455 clk_disable(pcdev->hclk_cif);
1456 clk_disable(pcdev->cif_clk_in);
1458 clk_disable(pcdev->cif_clk_out);
1459 clk_enable(pcdev->cif_clk_out);
1460 clk_set_rate(pcdev->cif_clk_out,48*1000*1000);
1461 clk_disable(pcdev->cif_clk_out);
1463 clk_disable(pcdev->pd_cif);
1468 /* The following two functions absolutely depend on the fact, that
1469 * there can be only one camera on RK28 quick capture interface */
1470 static int rk_camera_add_device(struct soc_camera_device *icd)
1472 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1473 struct rk_camera_dev *pcdev = ici->priv;
1474 struct device *control = to_soc_camera_control(icd);
1475 struct v4l2_subdev *sd;
1476 int ret,i,icd_catch;
1477 struct rk_camera_frmivalenum *fival_list,*fival_nxt;
1479 mutex_lock(&camera_lock);
1486 RKCAMERA_DG("%s driver attached to %s\n",RK29_CAM_DRV_NAME,dev_name(icd->pdev));
1488 pcdev->frame_inval = RK_CAM_FRAME_INVAL_INIT;
1489 pcdev->active = NULL;
1491 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
1492 pcdev->zoominfo.zoom_rate = 100;
1493 pcdev->fps_timer.istarted = false;
1495 /* ddl@rock-chips.com: capture list must be reset, because this list may be not empty,
1496 * if app havn't dequeue all videobuf before close camera device;
1498 INIT_LIST_HEAD(&pcdev->capture);
1500 ret = rk_camera_activate(pcdev,icd);
1503 /* ddl@rock-chips.com : v4l2_subdev is not created when ici->ops->add called in soc_camera_probe */
1505 sd = dev_get_drvdata(control);
1506 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_IOREQUEST,(void*)pcdev->pdata);
1508 ret = v4l2_subdev_call(sd,core, init, 0);
1512 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_CB_REGISTER,(void*)(&pcdev->icd_cb));
1515 pcdev->icd_init = 0;
1518 for (i=0; i<2; i++) {
1519 if (pcdev->icd_frmival[i].icd == icd)
1521 if (pcdev->icd_frmival[i].icd == NULL) {
1522 pcdev->icd_frmival[i].icd = icd;
1526 if (icd_catch == 0) {
1527 fival_list = pcdev->icd_frmival[0].fival_list;
1528 fival_nxt = fival_list;
1529 while(fival_nxt != NULL) {
1530 fival_nxt = fival_list->nxt;
1532 fival_list = fival_nxt;
1534 pcdev->icd_frmival[0].icd = icd;
1535 pcdev->icd_frmival[0].fival_list = kzalloc(sizeof(struct rk_camera_frmivalenum),GFP_KERNEL);
1538 mutex_unlock(&camera_lock);
1542 static void rk_camera_remove_device(struct soc_camera_device *icd)
1544 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1545 struct rk_camera_dev *pcdev = ici->priv;
1546 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1547 #if CAMERA_VIDEOBUF_ARM_ACCESS
1548 struct rk29_camera_vbinfo *vb_info;
1552 mutex_lock(&camera_lock);
1553 BUG_ON(icd != pcdev->icd);
1555 RKCAMERA_DG("%s driver detached from %s\n",RK29_CAM_DRV_NAME,dev_name(icd->pdev));
1557 /* ddl@rock-chips.com: Application will call VIDIOC_STREAMOFF before close device, but
1558 stream may be turn on again before close device, if suspend and resume happened. */
1559 if (read_cif_reg(pcdev->base,CIF_CIF_CTRL) & ENABLE_CAPTURE) {
1560 rk_camera_s_stream(icd,0);
1563 //soft reset the registers
1564 #if 0 //has somthing wrong when suspend and resume now
1566 write_cru_reg(CRU_CIF_RST_REG30,MASK_RST_CIF0|RQUEST_RST_CIF0 | (read_cru_reg(CRU_CIF_RST_REG30)));
1567 write_cru_reg(CRU_CIF_RST_REG30,(read_cru_reg(CRU_CIF_RST_REG30)&(~RQUEST_RST_CIF0)) | MASK_RST_CIF0);
1569 write_cru_reg(CRU_CIF_RST_REG30,MASK_RST_CIF1|RQUEST_RST_CIF1 | (read_cru_reg(CRU_CIF_RST_REG30)));
1570 write_cru_reg(CRU_CIF_RST_REG30,(read_cru_reg(CRU_CIF_RST_REG30)&(~RQUEST_RST_CIF1)) | MASK_RST_CIF1);
1573 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_DEACTIVATE,NULL);
1574 //if stream off is not been executed,timer is running.
1575 if(pcdev->fps_timer.istarted){
1576 hrtimer_cancel(&pcdev->fps_timer.timer);
1577 pcdev->fps_timer.istarted = false;
1579 flush_work(&(pcdev->camera_reinit_work.work));
1580 flush_workqueue((pcdev->camera_wq));
1582 if (pcdev->camera_work) {
1583 kfree(pcdev->camera_work);
1584 pcdev->camera_work = NULL;
1585 pcdev->camera_work_count = 0;
1586 INIT_LIST_HEAD(&pcdev->camera_work_queue);
1588 rk_camera_deactivate(pcdev);
1589 #if CAMERA_VIDEOBUF_ARM_ACCESS
1590 if (pcdev->vbinfo) {
1591 vb_info = pcdev->vbinfo;
1592 for (i=0; i<pcdev->vbinfo_count; i++) {
1593 if (vb_info->vir_addr) {
1594 iounmap(vb_info->vir_addr);
1595 release_mem_region(vb_info->phy_addr, vb_info->size);
1596 memset(vb_info, 0x00, sizeof(struct rk29_camera_vbinfo));
1600 kfree(pcdev->vbinfo);
1601 pcdev->vbinfo = NULL;
1602 pcdev->vbinfo_count = 0;
1605 pcdev->active = NULL;
1607 pcdev->icd_cb.sensor_cb = NULL;
1608 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
1609 /* ddl@rock-chips.com: capture list must be reset, because this list may be not empty,
1610 * if app havn't dequeue all videobuf before close camera device;
1612 INIT_LIST_HEAD(&pcdev->capture);
1614 mutex_unlock(&camera_lock);
1615 RKCAMERA_DG("%s exit\n",__FUNCTION__);
1619 static int rk_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
1621 unsigned long bus_flags, camera_flags, common_flags;
1622 unsigned int cif_ctrl_val = 0;
1623 const struct soc_mbus_pixelfmt *fmt;
1625 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1626 struct rk_camera_dev *pcdev = ici->priv;
1627 RKCAMERA_DG("%s..%d..\n",__FUNCTION__,__LINE__);
1629 fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code);
1633 bus_flags = RK_CAM_BUS_PARAM;
1634 /* If requested data width is supported by the platform, use it */
1635 switch (fmt->bits_per_sample) {
1637 if (!(bus_flags & SOCAM_DATAWIDTH_10))
1641 if (!(bus_flags & SOCAM_DATAWIDTH_9))
1645 if (!(bus_flags & SOCAM_DATAWIDTH_8))
1652 if (icd->ops->query_bus_param)
1653 camera_flags = icd->ops->query_bus_param(icd);
1657 common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
1658 if (!common_flags) {
1660 goto RK_CAMERA_SET_BUS_PARAM_END;
1663 ret = icd->ops->set_bus_param(icd, common_flags);
1665 goto RK_CAMERA_SET_BUS_PARAM_END;
1667 cif_ctrl_val = read_cif_reg(pcdev->base,CIF_CIF_FOR);
1668 RKCAMERA_DG("%s..%d..cif_ctrl_val = 0x%x\n",__FUNCTION__,__LINE__,cif_ctrl_val);
1669 if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) {
1671 write_cru_reg(CRU_PCLK_REG30, read_cru_reg(CRU_PCLK_REG30) | ENANABLE_INVERT_PCLK_CIF0);
1672 RKCAMERA_DG("enable cif0 pclk invert\n");
1674 write_cru_reg(CRU_PCLK_REG30, read_cru_reg(CRU_PCLK_REG30) | ENANABLE_INVERT_PCLK_CIF1);
1675 RKCAMERA_DG("enable cif1 pclk invert\n");
1679 write_cru_reg(CRU_PCLK_REG30, (read_cru_reg(CRU_PCLK_REG30) & 0xFFFFEFF ) | DISABLE_INVERT_PCLK_CIF0);
1680 RKCAMERA_DG("diable cif0 pclk invert\n");
1682 write_cru_reg(CRU_PCLK_REG30, (read_cru_reg(CRU_PCLK_REG30) & 0xFFFEFFF) | DISABLE_INVERT_PCLK_CIF1);
1683 RKCAMERA_DG("diable cif1 pclk invert\n");
1686 if (common_flags & SOCAM_HSYNC_ACTIVE_LOW) {
1687 cif_ctrl_val |= HSY_LOW_ACTIVE;
1689 cif_ctrl_val &= ~HSY_LOW_ACTIVE;
1691 if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH) {
1692 cif_ctrl_val |= VSY_HIGH_ACTIVE;
1694 cif_ctrl_val &= ~VSY_HIGH_ACTIVE;
1697 /* ddl@rock-chips.com : Don't enable capture here, enable in stream_on */
1698 //vip_ctrl_val |= ENABLE_CAPTURE;
1699 write_cif_reg(pcdev->base,CIF_CIF_FOR, cif_ctrl_val);
1700 RKCAMERA_DG("%s..ctrl:0x%x CIF_CIF_FOR=%x \n",__FUNCTION__,cif_ctrl_val,read_cif_reg(pcdev->base,CIF_CIF_FOR));
1702 RK_CAMERA_SET_BUS_PARAM_END:
1704 RKCAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
1708 static int rk_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
1710 unsigned long bus_flags, camera_flags;
1713 bus_flags = RK_CAM_BUS_PARAM;
1714 if (icd->ops->query_bus_param) {
1715 camera_flags = icd->ops->query_bus_param(icd);
1719 ret = soc_camera_bus_param_compatible(camera_flags, bus_flags) ;
1722 dev_warn(icd->dev.parent,
1723 "Flags incompatible: camera %lx, host %lx\n",
1724 camera_flags, bus_flags);
1728 static const struct soc_mbus_pixelfmt rk_camera_formats[] = {
1730 .fourcc = V4L2_PIX_FMT_NV12,
1731 .name = "YUV420 NV12",
1732 .bits_per_sample = 8,
1733 .packing = SOC_MBUS_PACKING_1_5X8,
1734 .order = SOC_MBUS_ORDER_LE,
1736 .fourcc = V4L2_PIX_FMT_NV16,
1737 .name = "YUV422 NV16",
1738 .bits_per_sample = 8,
1739 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1740 .order = SOC_MBUS_ORDER_LE,
1742 .fourcc = V4L2_PIX_FMT_NV21,
1743 .name = "YUV420 NV21",
1744 .bits_per_sample = 8,
1745 .packing = SOC_MBUS_PACKING_1_5X8,
1746 .order = SOC_MBUS_ORDER_LE,
1748 .fourcc = V4L2_PIX_FMT_NV61,
1749 .name = "YUV422 NV61",
1750 .bits_per_sample = 8,
1751 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1752 .order = SOC_MBUS_ORDER_LE,
1754 .fourcc = V4L2_PIX_FMT_RGB565,
1756 .bits_per_sample = 8,
1757 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1758 .order = SOC_MBUS_ORDER_LE,
1760 .fourcc = V4L2_PIX_FMT_RGB24,
1762 .bits_per_sample = 8,
1763 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1764 .order = SOC_MBUS_ORDER_LE,
1768 static void rk_camera_setup_format(struct soc_camera_device *icd, __u32 host_pixfmt, enum v4l2_mbus_pixelcode icd_code, struct v4l2_rect *rect)
1770 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1771 struct rk_camera_dev *pcdev = ici->priv;
1772 unsigned int cif_fs = 0,cif_crop = 0;
1773 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;
1775 const struct soc_mbus_pixelfmt *fmt;
1776 fmt = soc_mbus_get_fmtdesc(icd_code);
1778 if((host_pixfmt == V4L2_PIX_FMT_RGB565) || (host_pixfmt == V4L2_PIX_FMT_RGB24)){
1779 if(fmt->fourcc == V4L2_PIX_FMT_NV12)
1780 host_pixfmt = V4L2_PIX_FMT_NV12;
1781 else if(fmt->fourcc == V4L2_PIX_FMT_NV21)
1782 host_pixfmt = V4L2_PIX_FMT_NV21;
1784 switch (host_pixfmt)
1786 case V4L2_PIX_FMT_NV16:
1787 cif_fmt_val &= ~YUV_OUTPUT_422;
1788 cif_fmt_val &= ~UV_STORAGE_ORDER_UVUV;
1789 pcdev->frame_inval = RK_CAM_FRAME_INVAL_DC;
1790 pcdev->pixfmt = host_pixfmt;
1792 case V4L2_PIX_FMT_NV61:
1793 cif_fmt_val &= ~YUV_OUTPUT_422;
1794 cif_fmt_val |= UV_STORAGE_ORDER_VUVU;
1795 pcdev->frame_inval = RK_CAM_FRAME_INVAL_DC;
1796 pcdev->pixfmt = host_pixfmt;
1798 case V4L2_PIX_FMT_NV12:
1799 cif_fmt_val |= YUV_OUTPUT_420;
1800 cif_fmt_val &= ~UV_STORAGE_ORDER_UVUV;
1801 if (pcdev->frame_inval != RK_CAM_FRAME_INVAL_INIT)
1802 pcdev->frame_inval = RK_CAM_FRAME_INVAL_INIT;
1803 pcdev->pixfmt = host_pixfmt;
1805 case V4L2_PIX_FMT_NV21:
1806 cif_fmt_val |= YUV_OUTPUT_420;
1807 cif_fmt_val |= UV_STORAGE_ORDER_VUVU;
1808 if (pcdev->frame_inval != RK_CAM_FRAME_INVAL_INIT)
1809 pcdev->frame_inval = RK_CAM_FRAME_INVAL_INIT;
1810 pcdev->pixfmt = host_pixfmt;
1812 default: /* ddl@rock-chips.com : vip output format is hold when pixfmt is invalidate */
1813 cif_fmt_val |= YUV_OUTPUT_422;
1818 case V4L2_MBUS_FMT_UYVY8_2X8:
1819 cif_fmt_val = YUV_INPUT_ORDER_UYVY(cif_fmt_val);
1821 case V4L2_MBUS_FMT_YUYV8_2X8:
1822 cif_fmt_val = YUV_INPUT_ORDER_YUYV(cif_fmt_val);
1824 case V4L2_MBUS_FMT_YVYU8_2X8:
1825 cif_fmt_val = YUV_INPUT_ORDER_YVYU(cif_fmt_val);
1827 case V4L2_MBUS_FMT_VYUY8_2X8:
1828 cif_fmt_val = YUV_INPUT_ORDER_VYUY(cif_fmt_val);
1831 cif_fmt_val = YUV_INPUT_ORDER_YUYV(cif_fmt_val);
1836 #if (defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK2928))
1839 // pmu_set_idle_request(IDLE_REQ_VIO, true);
1840 cru_set_soft_reset(SOFT_RST_CIF0, true);
1842 cru_set_soft_reset(SOFT_RST_CIF0, false);
1843 // pmu_set_idle_request(IDLE_REQ_VIO, false);
1846 // pmu_set_idle_request(IDLE_REQ_VIO, true);
1847 cru_set_soft_reset(SOFT_RST_CIF1, true);
1849 cru_set_soft_reset(SOFT_RST_CIF1, false);
1850 // pmu_set_idle_request(IDLE_REQ_VIO, false);
1852 #elif defined(CONFIG_ARCH_RK3188)
1853 // pmu_set_idle_request(IDLE_REQ_VIO, true);
1854 cru_set_soft_reset(SOFT_RST_CIF0, true);
1856 cru_set_soft_reset(SOFT_RST_CIF0, false);
1857 // pmu_set_idle_request(IDLE_REQ_VIO, false);
1861 write_cif_reg(pcdev->base,CIF_CIF_CTRL,AXI_BURST_16|MODE_ONEFRAME|DISABLE_CAPTURE); /* ddl@rock-chips.com : vip ahb burst 16 */
1862 write_cif_reg(pcdev->base,CIF_CIF_INTEN, 0x01|0x200); //capture complete interrupt enable
1864 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 */
1866 // read_cif_reg(pcdev->base,CIF_CIF_INTSTAT); /* clear vip interrupte single */
1867 write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF);
1868 if((read_cif_reg(pcdev->base,CIF_CIF_CTRL) & MODE_PINGPONG)
1869 ||(read_cif_reg(pcdev->base,CIF_CIF_CTRL) & MODE_LINELOOP)) {
1871 } else{ // this is one frame mode
1872 cif_crop = (rect->left+ (rect->top<<16));
1873 cif_fs = ((rect->width ) + (rect->height<<16));
1876 write_cif_reg(pcdev->base,CIF_CIF_CROP, cif_crop);
1877 write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, cif_fs);
1878 write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH, rect->width);
1879 write_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS, 0x00000003);
1882 write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL,0x10);
1883 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));
1887 static int rk_camera_get_formats(struct soc_camera_device *icd, unsigned int idx,
1888 struct soc_camera_format_xlate *xlate)
1890 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1891 struct device *dev = icd->dev.parent;
1892 int formats = 0, ret;
1893 enum v4l2_mbus_pixelcode code;
1894 const struct soc_mbus_pixelfmt *fmt;
1896 ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
1898 /* No more formats */
1901 fmt = soc_mbus_get_fmtdesc(code);
1903 dev_err(dev, "Invalid format code #%u: %d\n", idx, code);
1907 ret = rk_camera_try_bus_param(icd, fmt->bits_per_sample);
1912 case V4L2_MBUS_FMT_UYVY8_2X8:
1913 case V4L2_MBUS_FMT_YUYV8_2X8:
1914 case V4L2_MBUS_FMT_YVYU8_2X8:
1915 case V4L2_MBUS_FMT_VYUY8_2X8:
1916 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE != RK_CAM_SCALE_CROP_RGA)
1919 xlate->host_fmt = &rk_camera_formats[0];
1922 dev_dbg(dev, "Providing format %s using code %d\n",
1923 rk_camera_formats[0].name,code);
1928 xlate->host_fmt = &rk_camera_formats[1];
1931 dev_dbg(dev, "Providing format %s using code %d\n",
1932 rk_camera_formats[1].name,code);
1937 xlate->host_fmt = &rk_camera_formats[2];
1940 dev_dbg(dev, "Providing format %s using code %d\n",
1941 rk_camera_formats[2].name,code);
1946 xlate->host_fmt = &rk_camera_formats[3];
1949 dev_dbg(dev, "Providing format %s using code %d\n",
1950 rk_camera_formats[3].name,code);
1956 xlate->host_fmt = &rk_camera_formats[4];
1959 dev_dbg(dev, "Providing format %s using code %d\n",
1960 rk_camera_formats[4].name,code);
1964 xlate->host_fmt = &rk_camera_formats[5];
1967 dev_dbg(dev, "Providing format %s using code %d\n",
1968 rk_camera_formats[5].name,code);
1979 static void rk_camera_put_formats(struct soc_camera_device *icd)
1984 static int rk_camera_set_crop(struct soc_camera_device *icd,
1985 struct v4l2_crop *a)
1987 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1988 struct v4l2_mbus_framefmt mf;
1989 u32 fourcc = icd->current_fmt->host_fmt->fourcc;
1992 ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
1996 if ((mf.width < (a->c.left + a->c.width)) || (mf.height < (a->c.top + a->c.height))) {
1998 mf.width = a->c.left + a->c.width;
1999 mf.height = a->c.top + a->c.height;
2001 v4l_bound_align_image(&mf.width, RK_CAM_W_MIN, RK_CAM_W_MAX, 1,
2002 &mf.height, RK_CAM_H_MIN, RK_CAM_H_MAX, 0,
2003 fourcc == V4L2_PIX_FMT_NV16 ?4 : 0);
2005 ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
2010 rk_camera_setup_format(icd, fourcc, mf.code, &a->c);
2012 icd->user_width = mf.width;
2013 icd->user_height = mf.height;
2018 static int rk_camera_set_fmt(struct soc_camera_device *icd,
2019 struct v4l2_format *f)
2021 struct device *dev = icd->dev.parent;
2022 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
2023 const struct soc_camera_format_xlate *xlate = NULL;
2024 struct soc_camera_host *ici =to_soc_camera_host(icd->dev.parent);
2025 struct rk_camera_dev *pcdev = ici->priv;
2026 struct v4l2_pix_format *pix = &f->fmt.pix;
2027 struct v4l2_mbus_framefmt mf;
2028 struct v4l2_rect rect;
2029 int ret,usr_w,usr_h;
2033 usr_h = pix->height;
2034 RKCAMERA_DG("%s enter width:%d height:%d\n",__FUNCTION__,usr_w,usr_h);
2035 xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
2037 dev_err(dev, "Format %x not found\n", pix->pixelformat);
2039 goto RK_CAMERA_SET_FMT_END;
2042 /* ddl@rock-chips.com: sensor init code transmit in here after open */
2043 if (pcdev->icd_init == 0) {
2044 v4l2_subdev_call(sd,core, init, 0);
2045 pcdev->icd_init = 1;
2048 stream_on = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
2049 if (stream_on & ENABLE_CAPTURE)
2050 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (stream_on & (~ENABLE_CAPTURE)));
2052 mf.width = pix->width;
2053 mf.height = pix->height;
2054 mf.field = pix->field;
2055 mf.colorspace = pix->colorspace;
2056 mf.code = xlate->code;
2057 ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
2058 if (mf.code != xlate->code)
2060 #ifdef CONFIG_VIDEO_RK29_WORK_IPP
2061 if ((mf.width != usr_w) || (mf.height != usr_h)) {
2063 if (unlikely((mf.width <16) || (mf.width > 8190) || (mf.height < 16) || (mf.height > 8190))) {
2064 RKCAMERA_TR("Senor and IPP both invalid source resolution(%dx%d)\n",mf.width,mf.height);
2066 goto RK_CAMERA_SET_FMT_END;
2068 if (unlikely((usr_w <16)||(usr_h < 16))) {
2069 RKCAMERA_TR("Senor and IPP both invalid destination resolution(%dx%d)\n",usr_w,usr_h);
2071 goto RK_CAMERA_SET_FMT_END;
2074 if((mf.width*10/mf.height) != (usr_w*10/usr_h)){
2075 ratio = ((mf.width*10/usr_w) >= (mf.height*10/usr_h))?(mf.height*10/usr_h):(mf.width*10/usr_w);
2076 pcdev->host_width = ratio*usr_w/10;
2077 pcdev->host_height = ratio*usr_h/10;
2078 //for ipp ,need 4 bit alligned.
2079 pcdev->host_width &= ~CROP_ALIGN_BYTES;
2080 pcdev->host_height &= ~CROP_ALIGN_BYTES;
2081 RKCAMERA_DG("ratio = %d ,host:%d*%d\n",ratio,pcdev->host_width,pcdev->host_height);
2083 else{ // needn't crop ,just scaled by ipp
2084 pcdev->host_width = mf.width;
2085 pcdev->host_height = mf.height;
2089 pcdev->host_width = usr_w;
2090 pcdev->host_height = usr_h;
2094 //according to crop and scale capability to change , here just cropt to user needed
2095 if (unlikely((mf.width <16) || (mf.width > 8190) || (mf.height < 16) || (mf.height > 8190))) {
2096 RKCAMERA_TR("Senor invalid source resolution(%dx%d)\n",mf.width,mf.height);
2098 goto RK_CAMERA_SET_FMT_END;
2100 if (unlikely((usr_w <16)||(usr_h < 16))) {
2101 RKCAMERA_TR("Senor invalid destination resolution(%dx%d)\n",usr_w,usr_h);
2103 goto RK_CAMERA_SET_FMT_END;
2105 pcdev->host_width = usr_w;
2106 pcdev->host_height = usr_h;
2110 RKCAMERA_DG("%s..%d.. host:%d*%d , sensor output:%d*%d,user demand:%d*%d\n",__FUNCTION__,__LINE__,
2111 pcdev->host_width,pcdev->host_height,mf.width,mf.height,usr_w,usr_h);
2112 rect.width = pcdev->host_width;
2113 rect.height = pcdev->host_height;
2114 rect.left = ((mf.width-pcdev->host_width )>>1)&(~0x01);
2115 rect.top = ((mf.height-pcdev->host_height)>>1)&(~0x01);
2116 pcdev->host_left = rect.left;
2117 pcdev->host_top = rect.top;
2119 down(&pcdev->zoominfo.sem);
2121 pcdev->zoominfo.a.c.left = 0;
2122 pcdev->zoominfo.a.c.top = 0;
2123 pcdev->zoominfo.a.c.width = pcdev->host_width*100/pcdev->zoominfo.zoom_rate;
2124 pcdev->zoominfo.a.c.width &= ~CROP_ALIGN_BYTES;
2125 pcdev->zoominfo.a.c.height = pcdev->host_height*100/pcdev->zoominfo.zoom_rate;
2126 pcdev->zoominfo.a.c.height &= ~CROP_ALIGN_BYTES;
2127 pcdev->zoominfo.vir_width = pcdev->zoominfo.a.c.width;
2128 pcdev->zoominfo.vir_height = pcdev->zoominfo.a.c.height;
2129 //recalculate the CIF width & height
2130 rect.width = pcdev->zoominfo.a.c.width ;
2131 rect.height = pcdev->zoominfo.a.c.height;
2132 rect.left = ((((pcdev->host_width - pcdev->zoominfo.a.c.width)>>1))+pcdev->host_left)&(~0x01);
2133 rect.top = ((((pcdev->host_height - pcdev->zoominfo.a.c.height)>>1))+pcdev->host_top)&(~0x01);
2135 pcdev->zoominfo.a.c.width = pcdev->host_width*100/pcdev->zoominfo.zoom_rate;
2136 pcdev->zoominfo.a.c.width &= ~CROP_ALIGN_BYTES;
2137 pcdev->zoominfo.a.c.height = pcdev->host_height*100/pcdev->zoominfo.zoom_rate;
2138 pcdev->zoominfo.a.c.height &= ~CROP_ALIGN_BYTES;
2139 //now digital zoom use ipp to do crop and scale
2140 if(pcdev->zoominfo.zoom_rate != 100){
2141 pcdev->zoominfo.a.c.left = ((pcdev->host_width - pcdev->zoominfo.a.c.width)>>1)&(~0x01);
2142 pcdev->zoominfo.a.c.top = ((pcdev->host_height - pcdev->zoominfo.a.c.height)>>1)&(~0x01);
2145 pcdev->zoominfo.a.c.left = 0;
2146 pcdev->zoominfo.a.c.top = 0;
2148 pcdev->zoominfo.vir_width = pcdev->host_width;
2149 pcdev->zoominfo.vir_height = pcdev->host_height;
2151 up(&pcdev->zoominfo.sem);
2153 /* ddl@rock-chips.com: IPP work limit check */
2154 if ((pcdev->zoominfo.a.c.width != usr_w) || (pcdev->zoominfo.a.c.height != usr_h)) {
2155 if (usr_w > 0x7f0) {
2156 if (((usr_w>>1)&0x3f) && (((usr_w>>1)&0x3f) <= 8)) {
2157 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));
2159 goto RK_CAMERA_SET_FMT_END;
2162 if ((usr_w&0x3f) && ((usr_w&0x3f) <= 8)) {
2163 RKCAMERA_TR("IPP Destination resolution(%dx%d, %d mod 64=%d is <= 8)",usr_w,usr_h, usr_w, (int)(usr_w&0x3f));
2165 goto RK_CAMERA_SET_FMT_END;
2169 RKCAMERA_DG("%s..%s icd width:%d user width:%d (zoom: %dx%d@(%d,%d)->%dx%d)\n",__FUNCTION__,xlate->host_fmt->name,
2170 rect.width, pix->width, pcdev->zoominfo.a.c.width,pcdev->zoominfo.a.c.height, pcdev->zoominfo.a.c.left,pcdev->zoominfo.a.c.top,
2171 pix->width, pix->height);
2172 rk_camera_setup_format(icd, pix->pixelformat, mf.code, &rect);
2174 if (CAM_IPPWORK_IS_EN()) {
2175 BUG_ON(pcdev->vipmem_phybase == 0);
2178 pix->height = usr_h;
2179 pix->field = mf.field;
2180 pix->colorspace = mf.colorspace;
2181 icd->current_fmt = xlate;
2182 pcdev->icd_width = mf.width;
2183 pcdev->icd_height = mf.height;
2186 RK_CAMERA_SET_FMT_END:
2187 if (stream_on & ENABLE_CAPTURE)
2188 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL) | ENABLE_CAPTURE));
2190 RKCAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
2193 static bool rk_camera_fmt_capturechk(struct v4l2_format *f)
2197 if ((f->fmt.pix.width == 1024) && (f->fmt.pix.height == 768)) {
2199 } else if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 1024)) {
2201 } else if ((f->fmt.pix.width == 1600) && (f->fmt.pix.height == 1200)) {
2203 } else if ((f->fmt.pix.width == 2048) && (f->fmt.pix.height == 1536)) {
2205 } else if ((f->fmt.pix.width == 2592) && (f->fmt.pix.height == 1944)) {
2207 } else if ((f->fmt.pix.width == 3264) && (f->fmt.pix.height == 2448)) {
2212 RKCAMERA_DG("%s %dx%d is capture format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
2215 static int rk_camera_try_fmt(struct soc_camera_device *icd,
2216 struct v4l2_format *f)
2218 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2219 struct rk_camera_dev *pcdev = ici->priv;
2220 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
2221 const struct soc_camera_format_xlate *xlate;
2222 struct v4l2_pix_format *pix = &f->fmt.pix;
2223 __u32 pixfmt = pix->pixelformat;
2224 int ret,usr_w,usr_h,i;
2225 bool is_capture = rk_camera_fmt_capturechk(f);
2226 bool vipmem_is_overflow = false;
2227 struct v4l2_mbus_framefmt mf;
2228 int bytes_per_line_host;
2231 usr_h = pix->height;
2233 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
2235 dev_err(icd->dev.parent, "Format (%c%c%c%c) not found\n", pixfmt & 0xFF, (pixfmt >> 8) & 0xFF,
2236 (pixfmt >> 16) & 0xFF, (pixfmt >> 24) & 0xFF);
2238 RKCAMERA_TR("%s(version:%c%c%c) support format:\n",rk_cam_driver_description,(RK_CAM_VERSION_CODE&0xff0000)>>16,
2239 (RK_CAM_VERSION_CODE&0xff00)>>8,(RK_CAM_VERSION_CODE&0xff));
2240 for (i = 0; i < icd->num_user_formats; i++)
2241 RKCAMERA_TR("(%c%c%c%c)-%s\n",
2242 icd->user_formats[i].host_fmt->fourcc & 0xFF, (icd->user_formats[i].host_fmt->fourcc >> 8) & 0xFF,
2243 (icd->user_formats[i].host_fmt->fourcc >> 16) & 0xFF, (icd->user_formats[i].host_fmt->fourcc >> 24) & 0xFF,
2244 icd->user_formats[i].host_fmt->name);
2245 goto RK_CAMERA_TRY_FMT_END;
2247 /* limit to rk29 hardware capabilities */
2248 v4l_bound_align_image(&pix->width, RK_CAM_W_MIN, RK_CAM_W_MAX, 1,
2249 &pix->height, RK_CAM_H_MIN, RK_CAM_H_MAX, 0,
2250 pixfmt == V4L2_PIX_FMT_NV16 ? 4 : 0);
2252 pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
2254 if (pix->bytesperline < 0)
2255 return pix->bytesperline;
2257 /* limit to sensor capabilities */
2258 memset(&mf,0x00,sizeof(struct v4l2_mbus_framefmt));
2259 mf.width = pix->width;
2260 mf.height = pix->height;
2261 mf.field = pix->field;
2262 mf.colorspace = pix->colorspace;
2263 mf.code = xlate->code;
2264 /* ddl@rock-chips.com : It is query max resolution only. */
2265 if ((usr_w == 10000) && (usr_h == 10000)) {
2266 mf.reserved[6] = 0xfefe5a5a;
2269 ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
2271 goto RK_CAMERA_TRY_FMT_END;
2274 if((usr_w == 10000) && (usr_h == 10000)) {
2275 pix->width = mf.width;
2276 pix->height = mf.height;
2277 RKCAMERA_DG("%s: Sensor resolution : %dx%d\n",__FUNCTION__,mf.width,mf.height);
2278 goto RK_CAMERA_TRY_FMT_END;
2280 RKCAMERA_DG("%s: user demand: %dx%d sensor output: %dx%d \n",__FUNCTION__,usr_w,usr_h,mf.width,mf.height);
2283 #ifdef CONFIG_VIDEO_RK29_WORK_IPP
2284 if ((mf.width != usr_w) || (mf.height != usr_h)) {
2285 bytes_per_line_host = soc_mbus_bytes_per_line(mf.width,icd->current_fmt->host_fmt);
2287 vipmem_is_overflow = (PAGE_ALIGN(bytes_per_line_host*mf.height) > pcdev->vipmem_size);
2289 /* Assume preview buffer minimum is 4 */
2290 vipmem_is_overflow = (PAGE_ALIGN(bytes_per_line_host*mf.height)*4 > pcdev->vipmem_size);
2292 if (vipmem_is_overflow == false) {
2294 pix->height = usr_h;
2296 RKCAMERA_TR("vipmem for IPP is overflow, This resolution(%dx%d -> %dx%d) is invalidate!\n",mf.width,mf.height,usr_w,usr_h);
2297 pix->width = mf.width;
2298 pix->height = mf.height;
2300 /* ddl@rock-chips.com: Invalidate these code, because sensor need interpolate */
2302 if ((mf.width < usr_w) || (mf.height < usr_h)) {
2303 if (((usr_w>>1) > mf.width) || ((usr_h>>1) > mf.height)) {
2304 RKCAMERA_TR("The aspect ratio(%dx%d/%dx%d) is bigger than 2 !\n",mf.width,mf.height,usr_w,usr_h);
2305 pix->width = mf.width;
2306 pix->height = mf.height;
2312 //need to change according to crop and scale capablicity
2313 if ((mf.width > usr_w) && (mf.height > usr_h)) {
2315 pix->height = usr_h;
2316 } else if ((mf.width < usr_w) && (mf.height < usr_h)) {
2317 RKCAMERA_TR("%dx%d can't scale up to %dx%d!\n",mf.width,mf.height,usr_w,usr_h);
2318 pix->width = mf.width;
2319 pix->height = mf.height;
2322 pix->colorspace = mf.colorspace;
2325 case V4L2_FIELD_ANY:
2326 case V4L2_FIELD_NONE:
2327 pix->field = V4L2_FIELD_NONE;
2330 /* TODO: support interlaced at least in pass-through mode */
2331 dev_err(icd->dev.parent, "Field type %d unsupported.\n",
2333 goto RK_CAMERA_TRY_FMT_END;
2336 RK_CAMERA_TRY_FMT_END:
2338 RKCAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
2342 static int rk_camera_reqbufs(struct soc_camera_device *icd,
2343 struct v4l2_requestbuffers *p)
2347 /* This is for locking debugging only. I removed spinlocks and now I
2348 * check whether .prepare is ever called on a linked buffer, or whether
2349 * a dma IRQ can occur for an in-work or unlinked buffer. Until now
2350 * it hadn't triggered */
2351 for (i = 0; i < p->count; i++) {
2352 struct rk_camera_buffer *buf = container_of(icd->vb_vidq.bufs[i],
2353 struct rk_camera_buffer, vb);
2355 INIT_LIST_HEAD(&buf->vb.queue);
2361 static unsigned int rk_camera_poll(struct file *file, poll_table *pt)
2363 struct soc_camera_device *icd = file->private_data;
2364 struct rk_camera_buffer *buf;
2366 buf = list_entry(icd->vb_vidq.stream.next, struct rk_camera_buffer,
2369 poll_wait(file, &buf->vb.done, pt);
2371 if (buf->vb.state == VIDEOBUF_DONE ||
2372 buf->vb.state == VIDEOBUF_ERROR)
2373 return POLLIN|POLLRDNORM;
2378 static int rk_camera_querycap(struct soc_camera_host *ici,
2379 struct v4l2_capability *cap)
2381 struct rk_camera_dev *pcdev = ici->priv;
2382 char orientation[5];
2385 strlcpy(cap->card, dev_name(pcdev->icd->pdev), sizeof(cap->card));
2386 memset(orientation,0x00,sizeof(orientation));
2387 for (i=0; i<RK_CAM_NUM;i++) {
2388 if ((pcdev->pdata->info[i].dev_name!=NULL) && (strcmp(dev_name(pcdev->icd->pdev), pcdev->pdata->info[i].dev_name) == 0)) {
2389 sprintf(orientation,"-%d",pcdev->pdata->info[i].orientation);
2393 if (orientation[0] != '-') {
2394 RKCAMERA_TR("%s: %s is not registered in rk29_camera_platform_data, orientation apply default value",__FUNCTION__,dev_name(pcdev->icd->pdev));
2395 if (strstr(dev_name(pcdev->icd->pdev),"front"))
2396 strcat(cap->card,"-270");
2398 strcat(cap->card,"-90");
2400 strcat(cap->card,orientation);
2402 cap->version = RK_CAM_VERSION_CODE;
2403 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
2407 static int rk_camera_suspend(struct soc_camera_device *icd, pm_message_t state)
2409 struct soc_camera_host *ici =
2410 to_soc_camera_host(icd->dev.parent);
2411 struct rk_camera_dev *pcdev = ici->priv;
2412 struct v4l2_subdev *sd;
2415 mutex_lock(&camera_lock);
2416 if ((pcdev->icd == icd) && (icd->ops->suspend)) {
2417 rk_camera_s_stream(icd, 0);
2418 sd = soc_camera_to_subdev(icd);
2419 v4l2_subdev_call(sd, video, s_stream, 0);
2420 ret = icd->ops->suspend(icd, state);
2422 pcdev->reginfo_suspend.cifCtrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
2423 pcdev->reginfo_suspend.cifCrop = read_cif_reg(pcdev->base,CIF_CIF_CROP);
2424 pcdev->reginfo_suspend.cifFs = read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE);
2425 pcdev->reginfo_suspend.cifIntEn = read_cif_reg(pcdev->base,CIF_CIF_INTEN);
2426 pcdev->reginfo_suspend.cifFmt= read_cif_reg(pcdev->base,CIF_CIF_FOR);
2427 pcdev->reginfo_suspend.cifVirWidth = read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH);
2428 pcdev->reginfo_suspend.cifScale= read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL);
2430 pcdev->reginfo_suspend.Inval = Reg_Validate;
2431 rk_camera_deactivate(pcdev);
2433 RKCAMERA_DG("%s Enter Success...\n", __FUNCTION__);
2435 RKCAMERA_DG("%s icd has been deattach, don't need enter suspend\n", __FUNCTION__);
2437 mutex_unlock(&camera_lock);
2441 static int rk_camera_resume(struct soc_camera_device *icd)
2443 struct soc_camera_host *ici =
2444 to_soc_camera_host(icd->dev.parent);
2445 struct rk_camera_dev *pcdev = ici->priv;
2446 struct v4l2_subdev *sd;
2449 mutex_lock(&camera_lock);
2450 if ((pcdev->icd == icd) && (icd->ops->resume)) {
2451 if (pcdev->reginfo_suspend.Inval == Reg_Validate) {
2452 rk_camera_activate(pcdev, icd);
2453 write_cif_reg(pcdev->base,CIF_CIF_CTRL, pcdev->reginfo_suspend.cifCtrl&~ENABLE_CAPTURE);
2454 write_cif_reg(pcdev->base,CIF_CIF_INTEN, pcdev->reginfo_suspend.cifIntEn);
2455 write_cif_reg(pcdev->base,CIF_CIF_CROP, pcdev->reginfo_suspend.cifCrop);
2456 write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, pcdev->reginfo_suspend.cifFs);
2457 write_cif_reg(pcdev->base,CIF_CIF_FOR, pcdev->reginfo_suspend.cifFmt);
2458 write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH,pcdev->reginfo_suspend.cifVirWidth);
2459 write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL, pcdev->reginfo_suspend.cifScale);
2460 rk_videobuf_capture(pcdev->active,pcdev);
2461 rk_camera_s_stream(icd, 1);
2462 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
2464 RKCAMERA_TR("Resume fail, vip register recored is invalidate!!\n");
2465 goto rk_camera_resume_end;
2468 ret = icd->ops->resume(icd);
2469 sd = soc_camera_to_subdev(icd);
2470 v4l2_subdev_call(sd, video, s_stream, 1);
2472 RKCAMERA_DG("%s Enter success\n",__FUNCTION__);
2474 RKCAMERA_DG("%s icd has been deattach, don't need enter resume\n", __FUNCTION__);
2477 rk_camera_resume_end:
2478 mutex_unlock(&camera_lock);
2482 static void rk_camera_reinit_work(struct work_struct *work)
2484 struct v4l2_subdev *sd;
2485 struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
2486 struct rk_camera_dev *pcdev = camera_work->pcdev;
2487 struct soc_camera_link *tmp_soc_cam_link;
2489 unsigned long flags = 0;
2490 if(pcdev->icd == NULL)
2492 sd = soc_camera_to_subdev(pcdev->icd);
2493 tmp_soc_cam_link = to_soc_camera_link(pcdev->icd);
2496 RKCAMERA_TR("CIF_CIF_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CTRL));
2497 RKCAMERA_TR("CIF_CIF_INTEN = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTEN));
2498 RKCAMERA_TR("CIF_CIF_INTSTAT = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTSTAT));
2499 RKCAMERA_TR("CIF_CIF_FOR = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_FOR));
2500 RKCAMERA_TR("CIF_CIF_CROP = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CROP));
2501 RKCAMERA_TR("CIF_CIF_SET_SIZE = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE));
2502 RKCAMERA_TR("CIF_CIF_SCL_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL));
2503 RKCAMERA_TR("CRU_PCLK_REG30 = 0X%x\n",read_cru_reg(CRU_PCLK_REG30));
2504 RKCAMERA_TR("CIF_CIF_LAST_LINE = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_LINE));
2506 RKCAMERA_TR("CIF_CIF_LAST_PIX = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_PIX));
2507 RKCAMERA_TR("CIF_CIF_VIR_LINE_WIDTH = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH));
2508 RKCAMERA_TR("CIF_CIF_LINE_NUM_ADDR = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LINE_NUM_ADDR));
2509 RKCAMERA_TR("CIF_CIF_FRM0_ADDR_Y = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y));
2510 RKCAMERA_TR("CIF_CIF_FRM0_ADDR_UV = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV));
2511 RKCAMERA_TR("CIF_CIF_FRAME_STATUS = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS));
2514 pcdev->stop_cif = true;
2515 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL)&(~ENABLE_CAPTURE)));
2516 RKCAMERA_DG("the reinit times = %d\n",pcdev->reinit_times);
2517 if(pcdev->video_vq && pcdev->video_vq->irqlock){
2518 spin_lock_irqsave(pcdev->video_vq->irqlock, flags);
2519 for (index = 0; index < VIDEO_MAX_FRAME; index++) {
2520 if (NULL == pcdev->video_vq->bufs[index])
2523 if (pcdev->video_vq->bufs[index]->state == VIDEOBUF_QUEUED)
2525 list_del_init(&pcdev->video_vq->bufs[index]->queue);
2526 pcdev->video_vq->bufs[index]->state = VIDEOBUF_NEEDS_INIT;
2527 wake_up_all(&pcdev->video_vq->bufs[index]->done);
2528 printk("wake up video buffer index = %d !!!\n",index);
2531 spin_unlock_irqrestore(pcdev->video_vq->irqlock, flags);
2533 RKCAMERA_TR("video queue has somthing wrong !!\n");
2536 RKCAMERA_TR("the %d reinit times ,wake up video buffers!\n ",pcdev->reinit_times);
2538 static enum hrtimer_restart rk_camera_fps_func(struct hrtimer *timer)
2540 struct rk_camera_frmivalenum *fival_nxt=NULL,*fival_pre=NULL, *fival_rec=NULL;
2541 struct rk_camera_timer *fps_timer = container_of(timer, struct rk_camera_timer, timer);
2542 struct rk_camera_dev *pcdev = fps_timer->pcdev;
2544 // static unsigned int last_fps = 0;
2545 struct soc_camera_link *tmp_soc_cam_link;
2546 tmp_soc_cam_link = to_soc_camera_link(pcdev->icd);
2548 RKCAMERA_DG("rk_camera_fps_func fps:0x%x\n",pcdev->fps);
2549 if ((pcdev->fps < 1) || (pcdev->last_fps == pcdev->fps)) {
2550 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);
2551 pcdev->camera_reinit_work.pcdev = pcdev;
2552 //INIT_WORK(&(pcdev->camera_reinit_work.work), rk_camera_reinit_work);
2553 pcdev->reinit_times++;
2554 queue_work(pcdev->camera_wq,&(pcdev->camera_reinit_work.work));
2555 } else if(!pcdev->timer_get_fps) {
2556 pcdev->timer_get_fps = true;
2557 for (i=0; i<2; i++) {
2558 if (pcdev->icd == pcdev->icd_frmival[i].icd) {
2559 fival_nxt = pcdev->icd_frmival[i].fival_list;
2564 fival_pre = fival_nxt;
2565 while (fival_nxt != NULL) {
2567 RKCAMERA_DG("%s %c%c%c%c %dx%d framerate : %d/%d\n", dev_name(&pcdev->icd->dev),
2568 fival_nxt->fival.pixel_format & 0xFF, (fival_nxt->fival.pixel_format >> 8) & 0xFF,
2569 (fival_nxt->fival.pixel_format >> 16) & 0xFF, (fival_nxt->fival.pixel_format >> 24),
2570 fival_nxt->fival.width, fival_nxt->fival.height, fival_nxt->fival.discrete.denominator,
2571 fival_nxt->fival.discrete.numerator);
2573 if (((fival_nxt->fival.pixel_format == pcdev->pixfmt)
2574 && (fival_nxt->fival.height == pcdev->icd->user_height)
2575 && (fival_nxt->fival.width == pcdev->icd->user_width))
2576 || (fival_nxt->fival.discrete.denominator == 0)) {
2578 if (fival_nxt->fival.discrete.denominator == 0) {
2579 fival_nxt->fival.index = 0;
2580 fival_nxt->fival.width = pcdev->icd->user_width;
2581 fival_nxt->fival.height= pcdev->icd->user_height;
2582 fival_nxt->fival.pixel_format = pcdev->pixfmt;
2583 fival_nxt->fival.discrete.denominator = pcdev->frame_interval;
2584 fival_nxt->fival.reserved[1] = (pcdev->icd_width<<16)
2585 |(pcdev->icd_height);
2586 fival_nxt->fival.discrete.numerator = 1000000;
2587 fival_nxt->fival.type = V4L2_FRMIVAL_TYPE_DISCRETE;
2590 fival_rec = fival_nxt;
2592 fival_pre = fival_nxt;
2593 fival_nxt = fival_nxt->nxt;
2596 if ((rec_flag == 0) && fival_pre) {
2597 fival_pre->nxt = kzalloc(sizeof(struct rk_camera_frmivalenum), GFP_ATOMIC);
2598 if (fival_pre->nxt != NULL) {
2599 fival_pre->nxt->fival.index = fival_pre->fival.index++;
2600 fival_pre->nxt->fival.width = pcdev->icd->user_width;
2601 fival_pre->nxt->fival.height= pcdev->icd->user_height;
2602 fival_pre->nxt->fival.pixel_format = pcdev->pixfmt;
2604 fival_pre->nxt->fival.discrete.denominator = pcdev->frame_interval;
2605 fival_pre->nxt->fival.reserved[1] = (pcdev->icd_width<<16)
2606 |(pcdev->icd_height);
2607 fival_pre->nxt->fival.discrete.numerator = 1000000;
2608 fival_pre->nxt->fival.type = V4L2_FRMIVAL_TYPE_DISCRETE;
2610 fival_rec = fival_pre->nxt;
2614 pcdev->last_fps = pcdev->fps ;
2615 pcdev->fps_timer.timer.node.expires= ktime_add_us(pcdev->fps_timer.timer.node.expires, ktime_to_us(ktime_set(3, 0)));
2616 pcdev->fps_timer.timer._softexpires= ktime_add_us(pcdev->fps_timer.timer._softexpires, ktime_to_us(ktime_set(3, 0)));
2617 //return HRTIMER_NORESTART;
2618 if(pcdev->reinit_times >=2)
2619 return HRTIMER_NORESTART;
2621 return HRTIMER_RESTART;
2623 static int rk_camera_s_stream(struct soc_camera_device *icd, int enable)
2625 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2626 struct rk_camera_dev *pcdev = ici->priv;
2629 unsigned long flags;
2631 WARN_ON(pcdev->icd != icd);
2633 cif_ctrl_val = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
2636 pcdev->last_fps = 0;
2637 pcdev->frame_interval = 0;
2638 hrtimer_cancel(&(pcdev->fps_timer.timer));
2639 pcdev->fps_timer.pcdev = pcdev;
2640 pcdev->timer_get_fps = false;
2641 pcdev->reinit_times = 0;
2642 pcdev->stop_cif = false;
2643 // hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL);
2644 cif_ctrl_val |= ENABLE_CAPTURE;
2645 write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val);
2646 hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL);
2647 pcdev->fps_timer.istarted = true;
2649 //cancel timer before stop cif
2650 ret = hrtimer_cancel(&pcdev->fps_timer.timer);
2651 pcdev->fps_timer.istarted = false;
2652 flush_work(&(pcdev->camera_reinit_work.work));
2654 cif_ctrl_val &= ~ENABLE_CAPTURE;
2655 spin_lock_irqsave(&pcdev->lock, flags);
2656 write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val);
2657 pcdev->stop_cif = true;
2658 spin_unlock_irqrestore(&pcdev->lock, flags);
2659 flush_workqueue((pcdev->camera_wq));
2660 RKCAMERA_DG("STREAM_OFF cancel timer and flush work:0x%x \n", ret);
2662 //must be reinit,or will be somthing wrong in irq process.
2663 if(enable == false){
2664 pcdev->active = NULL;
2665 INIT_LIST_HEAD(&pcdev->capture);
2667 RKCAMERA_DG("%s.. enable : 0x%x , CIF_CIF_CTRL = 0x%x\n", __FUNCTION__, enable,read_cif_reg(pcdev->base,CIF_CIF_CTRL));
2670 int rk_camera_enum_frameintervals(struct soc_camera_device *icd, struct v4l2_frmivalenum *fival)
2672 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2673 struct rk_camera_dev *pcdev = ici->priv;
2674 struct rk_camera_frmivalenum *fival_list = NULL;
2675 struct v4l2_frmivalenum *fival_head = NULL;
2676 int i,ret = 0,index;
2678 index = fival->index & 0x00ffffff;
2679 if ((fival->index & 0xff000000) == 0xff000000) { /* ddl@rock-chips.com: detect framerate */
2680 for (i=0; i<2; i++) {
2681 if (pcdev->icd_frmival[i].icd == icd) {
2682 fival_list = pcdev->icd_frmival[i].fival_list;
2686 if (fival_list != NULL) {
2688 while (fival_list != NULL) {
2689 if ((fival->pixel_format == fival_list->fival.pixel_format)
2690 && (fival->height == fival_list->fival.height)
2691 && (fival->width == fival_list->fival.width)) {
2696 fival_list = fival_list->nxt;
2699 if ((i==index) && (fival_list != NULL)) {
2700 memcpy(fival, &fival_list->fival, sizeof(struct v4l2_frmivalenum));
2705 RKCAMERA_TR("%s: fival_list is NULL\n",__FUNCTION__);
2710 for (i=0; i<RK_CAM_NUM; i++) {
2711 if (pcdev->pdata->info[i].dev_name && (strcmp(dev_name(pcdev->icd->pdev),pcdev->pdata->info[i].dev_name) == 0)) {
2712 fival_head = pcdev->pdata->info[i].fival;
2716 if (fival_head == NULL) {
2717 RKCAMERA_TR("%s: %s is not registered in rk_camera_platform_data!!",__FUNCTION__,dev_name(pcdev->icd->pdev));
2719 goto rk_camera_enum_frameintervals_end;
2723 while (fival_head->width && fival_head->height) {
2724 if ((fival->pixel_format == fival_head->pixel_format)
2725 && (fival->height == fival_head->height)
2726 && (fival->width == fival_head->width)) {
2735 if ((i == index) && (fival->height == fival_head->height) && (fival->width == fival_head->width)) {
2736 memcpy(fival, fival_head, sizeof(struct v4l2_frmivalenum));
2737 RKCAMERA_DG("%s %dx%d@%c%c%c%c framerate : %d/%d\n", dev_name(pcdev->icd->pdev),
2738 fival->width, fival->height,
2739 fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
2740 (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
2741 fival->discrete.denominator,fival->discrete.numerator);
2744 RKCAMERA_TR("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(pcdev->icd->pdev),
2745 fival->width,fival->height,
2746 fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
2747 (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
2750 RKCAMERA_DG("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(pcdev->icd->pdev),
2751 fival->width,fival->height,
2752 fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
2753 (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
2758 rk_camera_enum_frameintervals_end:
2762 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
2763 static int rk_camera_set_digit_zoom(struct soc_camera_device *icd,
2764 const struct v4l2_queryctrl *qctrl, int zoom_rate)
2767 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2768 struct rk_camera_dev *pcdev = ici->priv;
2770 unsigned long tmp_cifctrl;
2773 //change the crop and scale parameters
2776 a.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2777 //a.c.width = pcdev->host_width*100/zoom_rate;
2778 a.c.width = pcdev->host_width*100/zoom_rate;
2779 a.c.width &= ~CROP_ALIGN_BYTES;
2780 a.c.height = pcdev->host_height*100/zoom_rate;
2781 a.c.height &= ~CROP_ALIGN_BYTES;
2782 a.c.left = (((pcdev->host_width - a.c.width)>>1)+pcdev->host_left)&(~0x01);
2783 a.c.top = (((pcdev->host_height - a.c.height)>>1)+pcdev->host_top)&(~0x01);
2784 pcdev->stop_cif = true;
2785 tmp_cifctrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
2786 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl & ~ENABLE_CAPTURE));
2787 hrtimer_cancel(&(pcdev->fps_timer.timer));
2788 flush_workqueue((pcdev->camera_wq));
2789 down(&pcdev->zoominfo.sem);
2790 pcdev->zoominfo.a.c.left = 0;
2791 pcdev->zoominfo.a.c.top = 0;
2792 pcdev->zoominfo.a.c.width = a.c.width;
2793 pcdev->zoominfo.a.c.height = a.c.height;
2794 pcdev->zoominfo.vir_width = pcdev->zoominfo.a.c.width;
2795 pcdev->zoominfo.vir_height = pcdev->zoominfo.a.c.height;
2796 pcdev->frame_inval = 1;
2797 write_cif_reg(pcdev->base,CIF_CIF_CROP, (a.c.left + (a.c.top<<16)));
2798 write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, ((a.c.width ) + (a.c.height<<16)));
2799 write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH, a.c.width);
2800 write_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS, 0x00000002);//frame1 has been ready to receive data,frame 2 is not used
2802 rk_videobuf_capture(pcdev->active,pcdev);
2803 if(tmp_cifctrl & ENABLE_CAPTURE)
2804 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl | ENABLE_CAPTURE));
2805 up(&pcdev->zoominfo.sem);
2806 pcdev->stop_cif = false;
2807 hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL);
2808 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 );
2810 a.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2811 a.c.width = pcdev->host_width*100/zoom_rate;
2812 a.c.width &= ~CROP_ALIGN_BYTES;
2813 a.c.height = pcdev->host_height*100/zoom_rate;
2814 a.c.height &= ~CROP_ALIGN_BYTES;
2815 a.c.left = (pcdev->host_width - a.c.width)>>1;
2816 a.c.top = (pcdev->host_height - a.c.height)>>1;
2817 down(&pcdev->zoominfo.sem);
2818 pcdev->zoominfo.a.c.height = a.c.height;
2819 pcdev->zoominfo.a.c.width = a.c.width;
2820 pcdev->zoominfo.a.c.top = a.c.top;
2821 pcdev->zoominfo.a.c.left = a.c.left;
2822 pcdev->zoominfo.vir_width = pcdev->host_width;
2823 pcdev->zoominfo.vir_height= pcdev->host_height;
2824 up(&pcdev->zoominfo.sem);
2825 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 );
2831 static inline struct v4l2_queryctrl const *rk_camera_soc_camera_find_qctrl(
2832 struct soc_camera_host_ops *ops, int id)
2836 for (i = 0; i < ops->num_controls; i++)
2837 if (ops->controls[i].id == id)
2838 return &ops->controls[i];
2844 static int rk_camera_set_ctrl(struct soc_camera_device *icd,
2845 struct v4l2_control *sctrl)
2848 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2849 const struct v4l2_queryctrl *qctrl;
2850 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
2851 struct rk_camera_dev *pcdev = ici->priv;
2855 qctrl = rk_camera_soc_camera_find_qctrl(ici->ops, sctrl->id);
2858 goto rk_camera_set_ctrl_end;
2863 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
2864 case V4L2_CID_ZOOM_ABSOLUTE:
2866 if ((sctrl->value < qctrl->minimum) || (sctrl->value > qctrl->maximum)){
2868 goto rk_camera_set_ctrl_end;
2870 ret = rk_camera_set_digit_zoom(icd, qctrl, sctrl->value);
2872 pcdev->zoominfo.zoom_rate = sctrl->value;
2874 goto rk_camera_set_ctrl_end;
2883 rk_camera_set_ctrl_end:
2887 static struct soc_camera_host_ops rk_soc_camera_host_ops =
2889 .owner = THIS_MODULE,
2890 .add = rk_camera_add_device,
2891 .remove = rk_camera_remove_device,
2892 .suspend = rk_camera_suspend,
2893 .resume = rk_camera_resume,
2894 .enum_frameinervals = rk_camera_enum_frameintervals,
2895 .set_crop = rk_camera_set_crop,
2896 .get_formats = rk_camera_get_formats,
2897 .put_formats = rk_camera_put_formats,
2898 .set_fmt = rk_camera_set_fmt,
2899 .try_fmt = rk_camera_try_fmt,
2900 .init_videobuf = rk_camera_init_videobuf,
2901 .reqbufs = rk_camera_reqbufs,
2902 .poll = rk_camera_poll,
2903 .querycap = rk_camera_querycap,
2904 .set_bus_param = rk_camera_set_bus_param,
2905 .s_stream = rk_camera_s_stream, /* ddl@rock-chips.com : Add stream control for host */
2906 .set_ctrl = rk_camera_set_ctrl,
2907 .controls = rk_camera_controls,
2908 .num_controls = ARRAY_SIZE(rk_camera_controls)
2910 static void rk_camera_cif_iomux(int cif_index)
2912 #if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)
2915 iomux_set(CIF0_CLKOUT);
2916 write_grf_reg(GRF_IO_CON3, (CIF_DRIVER_STRENGTH_MASK|CIF_DRIVER_STRENGTH_8MA));
2917 write_grf_reg(GRF_IO_CON4, (CIF_CLKOUT_AMP_MASK|CIF_CLKOUT_AMP_1V8));
2918 #if (CONFIG_CAMERA_INPUT_FMT_SUPPORT & (RK_CAM_INPUT_FMT_RAW10|RK_CAM_INPUT_FMT_RAW12))
2922 #if (CONFIG_CAMERA_INPUT_FMT_SUPPORT & RK_CAM_INPUT_FMT_RAW12)
2923 iomux_set(CIF0_D10);
2924 iomux_set(CIF0_D11);
2925 RKCAMERA_TR("%s(%d): WARNING: Cif 0 is configurated that support RAW 12bit, so I2C3 is invalidate!!\n",__FUNCTION__,__LINE__);
2930 RKCAMERA_TR("%s(%d): Cif index(%d) is invalidate!!!\n",__FUNCTION__,__LINE__, cif_index);
2933 #elif defined(CONFIG_ARCH_RK30)
2936 rk30_mux_api_set(GPIO1B3_CIF0CLKOUT_NAME, GPIO1B_CIF0_CLKOUT);
2937 #if (CONFIG_CAMERA_INPUT_FMT_SUPPORT & (RK_CAM_INPUT_FMT_RAW10|RK_CAM_INPUT_FMT_RAW12))
2938 rk30_mux_api_set(GPIO1B4_CIF0DATA0_NAME, GPIO1B_CIF0_DATA0);
2939 rk30_mux_api_set(GPIO1B5_CIF0DATA1_NAME, GPIO1B_CIF0_DATA1);
2941 #if (CONFIG_CAMERA_INPUT_FMT_SUPPORT & RK_CAM_INPUT_FMT_RAW12)
2942 rk30_mux_api_set(GPIO1B6_CIFDATA10_NAME, GPIO1B_CIF_DATA10);
2943 rk30_mux_api_set(GPIO1B7_CIFDATA11_NAME, GPIO1B_CIF_DATA11);
2947 rk30_mux_api_set(GPIO1C0_CIF1DATA2_RMIICLKOUT_RMIICLKIN_NAME,GPIO1C_CIF1_DATA2);
2948 rk30_mux_api_set(GPIO1C1_CIFDATA3_RMIITXEN_NAME,GPIO1C_CIF_DATA3);
2949 rk30_mux_api_set(GPIO1C2_CIF1DATA4_RMIITXD1_NAME,GPIO1C_CIF1_DATA4);
2950 rk30_mux_api_set(GPIO1C3_CIFDATA5_RMIITXD0_NAME,GPIO1C_CIF_DATA5);
2951 rk30_mux_api_set(GPIO1C4_CIFDATA6_RMIIRXERR_NAME,GPIO1C_CIF_DATA6);
2952 rk30_mux_api_set(GPIO1C5_CIFDATA7_RMIICRSDVALID_NAME,GPIO1C_CIF_DATA7);
2953 rk30_mux_api_set(GPIO1C6_CIFDATA8_RMIIRXD1_NAME,GPIO1C_CIF_DATA8);
2954 rk30_mux_api_set(GPIO1C7_CIFDATA9_RMIIRXD0_NAME,GPIO1C_CIF_DATA9);
2956 rk30_mux_api_set(GPIO1D0_CIF1VSYNC_MIIMD_NAME,GPIO1D_CIF1_VSYNC);
2957 rk30_mux_api_set(GPIO1D1_CIF1HREF_MIIMDCLK_NAME,GPIO1D_CIF1_HREF);
2958 rk30_mux_api_set(GPIO1D2_CIF1CLKIN_NAME,GPIO1D_CIF1_CLKIN);
2959 rk30_mux_api_set(GPIO1D3_CIF1DATA0_NAME,GPIO1D_CIF1_DATA0);
2960 rk30_mux_api_set(GPIO1D4_CIF1DATA1_NAME,GPIO1D_CIF1_DATA1);
2961 rk30_mux_api_set(GPIO1D5_CIF1DATA10_NAME,GPIO1D_CIF1_DATA10);
2962 rk30_mux_api_set(GPIO1D6_CIF1DATA11_NAME,GPIO1D_CIF1_DATA11);
2963 rk30_mux_api_set(GPIO1D7_CIF1CLKOUT_NAME,GPIO1D_CIF1_CLKOUT);
2966 RKCAMERA_TR("%s(%d): Cif index(%d) is invalidate!!!\n",__FUNCTION__,__LINE__, cif_index);
2973 static int rk_camera_probe(struct platform_device *pdev)
2975 struct rk_camera_dev *pcdev;
2976 struct resource *res;
2977 struct rk_camera_frmivalenum *fival_list,*fival_nxt;
2978 struct rk29camera_mem_res *meminfo_ptr,*meminfo_ptrr;
2982 printk("%s version: v%d.%d.%d Zoom by %s\n",RK29_CAM_DRV_NAME,(RK_CAM_VERSION_CODE&0xff0000)>>16,
2983 (RK_CAM_VERSION_CODE&0xff00)>>8,RK_CAM_VERSION_CODE&0xff,CAMERA_SCALE_CROP_MACHINE);
2985 if ((pdev->id == RK_CAM_PLATFORM_DEV_ID_1) && (RK_SUPPORT_CIF1 == 0)) {
2986 RKCAMERA_TR("%s(%d): This chip is not support CIF1!!\n",__FUNCTION__,__LINE__);
2990 if ((pdev->id == RK_CAM_PLATFORM_DEV_ID_0) && (RK_SUPPORT_CIF0 == 0)) {
2991 RKCAMERA_TR("%s(%d): This chip is not support CIF0!!\n",__FUNCTION__,__LINE__);
2995 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2996 irq = platform_get_irq(pdev, 0);
2997 if (!res || irq < 0) {
3001 pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL);
3003 dev_err(&pdev->dev, "Could not allocate pcdev\n");
3008 pcdev->zoominfo.zoom_rate = 100;
3009 pcdev->hostid = pdev->id;
3010 /*config output clk*/ // must modify start
3012 pcdev->pd_cif = clk_get(NULL, "pd_cif0");
3013 pcdev->aclk_cif = clk_get(NULL, "aclk_cif0");
3014 pcdev->hclk_cif = clk_get(NULL, "hclk_cif0");
3015 pcdev->cif_clk_in = clk_get(NULL, "cif0_in");
3016 pcdev->cif_clk_out = clk_get(NULL, "cif0_out");
3017 rk_camera_cif_iomux(0);
3019 pcdev->pd_cif = clk_get(NULL, "pd_cif1");
3020 pcdev->aclk_cif = clk_get(NULL, "aclk_cif1");
3021 pcdev->hclk_cif = clk_get(NULL, "hclk_cif1");
3022 pcdev->cif_clk_in = clk_get(NULL, "cif1_in");
3023 pcdev->cif_clk_out = clk_get(NULL, "cif1_out");
3025 rk_camera_cif_iomux(1);
3028 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)){
3029 RKCAMERA_TR(KERN_ERR "%s(%d): failed to get cif clock source\n",__FUNCTION__,__LINE__);
3031 goto exit_reqmem_vip;
3034 dev_set_drvdata(&pdev->dev, pcdev);
3036 pcdev->pdata = pdev->dev.platform_data; /* ddl@rock-chips.com : Request IO in init function */
3038 if (pcdev->pdata && pcdev->pdata->io_init) {
3039 pcdev->pdata->io_init();
3041 #ifdef CONFIG_VIDEO_RK29_WORK_IPP
3042 meminfo_ptr = IS_CIF0()? (&pcdev->pdata->meminfo):(&pcdev->pdata->meminfo_cif1);
3043 meminfo_ptrr = IS_CIF0()? (&pcdev->pdata->meminfo_cif1):(&pcdev->pdata->meminfo);
3045 if (meminfo_ptr->vbase == NULL) {
3047 if ((meminfo_ptr->start == meminfo_ptrr->start)
3048 && (meminfo_ptr->size == meminfo_ptrr->size) && meminfo_ptrr->vbase) {
3050 meminfo_ptr->vbase = meminfo_ptrr->vbase;
3053 if (!request_mem_region(meminfo_ptr->start,meminfo_ptr->size,"rk29_vipmem")) {
3055 RKCAMERA_TR("%s(%d): request_mem_region(start:0x%x size:0x%x) failed \n",__FUNCTION__,__LINE__, pcdev->pdata->meminfo.start,pcdev->pdata->meminfo.size);
3056 goto exit_ioremap_vipmem;
3058 meminfo_ptr->vbase = pcdev->vipmem_virbase = ioremap_cached(meminfo_ptr->start,meminfo_ptr->size);
3059 if (pcdev->vipmem_virbase == NULL) {
3060 RKCAMERA_TR("%s(%d): ioremap of CIF internal memory(Ex:IPP process/raw process) failed\n",__FUNCTION__,__LINE__);
3062 goto exit_ioremap_vipmem;
3067 pcdev->vipmem_phybase = meminfo_ptr->start;
3068 pcdev->vipmem_size = meminfo_ptr->size;
3069 pcdev->vipmem_virbase = meminfo_ptr->vbase;
3071 INIT_LIST_HEAD(&pcdev->capture);
3072 INIT_LIST_HEAD(&pcdev->camera_work_queue);
3073 spin_lock_init(&pcdev->lock);
3074 spin_lock_init(&pcdev->camera_work_lock);
3075 sema_init(&pcdev->zoominfo.sem,1);
3078 * Request the regions.
3081 if (!request_mem_region(res->start, res->end - res->start + 1,
3082 RK29_CAM_DRV_NAME)) {
3084 goto exit_reqmem_vip;
3086 pcdev->base = ioremap(res->start, res->end - res->start + 1);
3087 if (pcdev->base == NULL) {
3088 dev_err(pcdev->dev, "ioremap() of registers failed\n");
3090 goto exit_ioremap_vip;
3095 pcdev->dev = &pdev->dev;
3097 /* config buffer address */
3100 err = request_irq(pcdev->irq, rk_camera_irq, 0, RK29_CAM_DRV_NAME,
3103 dev_err(pcdev->dev, "Camera interrupt register failed \n");
3108 //#ifdef CONFIG_VIDEO_RK29_WORK_IPP
3110 pcdev->camera_wq = create_workqueue("rk_cam_wkque_cif0");
3112 pcdev->camera_wq = create_workqueue("rk_cam_wkque_cif1");
3114 if (pcdev->camera_wq == NULL)
3118 pcdev->camera_reinit_work.pcdev = pcdev;
3119 INIT_WORK(&(pcdev->camera_reinit_work.work), rk_camera_reinit_work);
3121 for (i=0; i<2; i++) {
3122 pcdev->icd_frmival[i].icd = NULL;
3123 pcdev->icd_frmival[i].fival_list = kzalloc(sizeof(struct rk_camera_frmivalenum),GFP_KERNEL);
3126 pcdev->soc_host.drv_name = RK29_CAM_DRV_NAME;
3127 pcdev->soc_host.ops = &rk_soc_camera_host_ops;
3128 pcdev->soc_host.priv = pcdev;
3129 pcdev->soc_host.v4l2_dev.dev = &pdev->dev;
3130 pcdev->soc_host.nr = pdev->id;
3132 err = soc_camera_host_register(&pcdev->soc_host);
3135 pcdev->fps_timer.pcdev = pcdev;
3136 hrtimer_init(&(pcdev->fps_timer.timer), CLOCK_MONOTONIC, HRTIMER_MODE_REL);
3137 pcdev->fps_timer.timer.function = rk_camera_fps_func;
3138 pcdev->icd_cb.sensor_cb = NULL;
3139 #if ((defined(CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON)) && (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP))
3140 pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_ipp;
3141 #elif (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_ARM)
3142 pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_arm;
3143 #elif (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_RGA)
3144 pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_rga;
3145 #elif(CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_PP)
3146 pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_pp;
3148 RKCAMERA_DG("%s(%d) Exit \n",__FUNCTION__,__LINE__);
3153 for (i=0; i<2; i++) {
3154 fival_list = pcdev->icd_frmival[i].fival_list;
3155 fival_nxt = fival_list;
3156 while(fival_nxt != NULL) {
3157 fival_nxt = fival_list->nxt;
3159 fival_list = fival_nxt;
3163 free_irq(pcdev->irq, pcdev);
3164 if (pcdev->camera_wq) {
3165 destroy_workqueue(pcdev->camera_wq);
3166 pcdev->camera_wq = NULL;
3169 iounmap(pcdev->base);
3171 release_mem_region(res->start, res->end - res->start + 1);
3172 exit_ioremap_vipmem:
3173 if (pcdev->vipmem_virbase)
3174 iounmap(pcdev->vipmem_virbase);
3175 release_mem_region(pcdev->vipmem_phybase,pcdev->vipmem_size);
3178 pcdev->aclk_cif = NULL;
3180 pcdev->hclk_cif = NULL;
3181 if(pcdev->cif_clk_in)
3182 pcdev->cif_clk_in = NULL;
3183 if(pcdev->cif_clk_out)
3184 pcdev->cif_clk_out = NULL;
3193 static int __devexit rk_camera_remove(struct platform_device *pdev)
3195 struct rk_camera_dev *pcdev = platform_get_drvdata(pdev);
3196 struct resource *res;
3197 struct rk_camera_frmivalenum *fival_list,*fival_nxt;
3198 struct rk29camera_mem_res *meminfo_ptr,*meminfo_ptrr;
3201 free_irq(pcdev->irq, pcdev);
3203 if (pcdev->camera_wq) {
3204 destroy_workqueue(pcdev->camera_wq);
3205 pcdev->camera_wq = NULL;
3208 for (i=0; i<2; i++) {
3209 fival_list = pcdev->icd_frmival[i].fival_list;
3210 fival_nxt = fival_list;
3211 while(fival_nxt != NULL) {
3212 fival_nxt = fival_list->nxt;
3214 fival_list = fival_nxt;
3218 soc_camera_host_unregister(&pcdev->soc_host);
3220 meminfo_ptr = IS_CIF0()? (&pcdev->pdata->meminfo):(&pcdev->pdata->meminfo_cif1);
3221 meminfo_ptrr = IS_CIF0()? (&pcdev->pdata->meminfo_cif1):(&pcdev->pdata->meminfo);
3222 if (meminfo_ptr->vbase) {
3223 if (meminfo_ptr->vbase == meminfo_ptrr->vbase) {
3224 meminfo_ptr->vbase = NULL;
3226 iounmap((void __iomem*)pcdev->vipmem_phybase);
3227 release_mem_region(pcdev->vipmem_phybase, pcdev->vipmem_size);
3228 meminfo_ptr->vbase = NULL;
3233 iounmap((void __iomem*)pcdev->base);
3234 release_mem_region(res->start, res->end - res->start + 1);
3235 if (pcdev->pdata && pcdev->pdata->io_deinit) { /* ddl@rock-chips.com : Free IO in deinit function */
3236 pcdev->pdata->io_deinit(0);
3237 pcdev->pdata->io_deinit(1);
3242 dev_info(&pdev->dev, "RK28 Camera driver unloaded\n");
3247 static struct platform_driver rk_camera_driver =
3250 .name = RK29_CAM_DRV_NAME,
3252 .probe = rk_camera_probe,
3253 .remove = __devexit_p(rk_camera_remove),
3256 static int rk_camera_init_async(void *unused)
3258 platform_driver_register(&rk_camera_driver);
3262 static int __devinit rk_camera_init(void)
3264 RKCAMERA_DG("%s..%s..%d \n",__FUNCTION__,__FILE__,__LINE__);
3265 kthread_run(rk_camera_init_async, NULL, "rk_camera_init");
3269 static void __exit rk_camera_exit(void)
3271 platform_driver_unregister(&rk_camera_driver);
3274 device_initcall_sync(rk_camera_init);
3275 module_exit(rk_camera_exit);
3277 MODULE_DESCRIPTION("RKSoc Camera Host driver");
3278 MODULE_AUTHOR("ddl <ddl@rock-chips>");
3279 MODULE_LICENSE("GPL");