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)
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)
44 #include <mach/rk30_camera.h>
49 #if defined(CONFIG_ARCH_RK2928)
50 #include <mach/rk2928_camera.h>
52 #include <asm/cacheflush.h>
54 module_param(debug, int, S_IRUGO|S_IWUSR);
56 #define dprintk(level, fmt, arg...) do { \
58 printk(KERN_WARNING"rk_camera: " fmt , ## arg); } while (0)
60 #define RKCAMERA_TR(format, ...) printk(KERN_ERR format, ## __VA_ARGS__)
61 #define RKCAMERA_DG(format, ...) dprintk(1, format, ## __VA_ARGS__)
63 #define CIF_CIF_CTRL 0x00
64 #define CIF_CIF_INTEN 0x04
65 #define CIF_CIF_INTSTAT 0x08
66 #define CIF_CIF_FOR 0x0c
67 #define CIF_CIF_LINE_NUM_ADDR 0x10
68 #define CIF_CIF_FRM0_ADDR_Y 0x14
69 #define CIF_CIF_FRM0_ADDR_UV 0x18
70 #define CIF_CIF_FRM1_ADDR_Y 0x1c
71 #define CIF_CIF_FRM1_ADDR_UV 0x20
72 #define CIF_CIF_VIR_LINE_WIDTH 0x24
73 #define CIF_CIF_SET_SIZE 0x28
74 #define CIF_CIF_SCM_ADDR_Y 0x2c
75 #define CIF_CIF_SCM_ADDR_U 0x30
76 #define CIF_CIF_SCM_ADDR_V 0x34
77 #define CIF_CIF_WB_UP_FILTER 0x38
78 #define CIF_CIF_WB_LOW_FILTER 0x3c
79 #define CIF_CIF_WBC_CNT 0x40
80 #define CIF_CIF_CROP 0x44
81 #define CIF_CIF_SCL_CTRL 0x48
82 #define CIF_CIF_SCL_DST 0x4c
83 #define CIF_CIF_SCL_FCT 0x50
84 #define CIF_CIF_SCL_VALID_NUM 0x54
85 #define CIF_CIF_LINE_LOOP_CTR 0x58
86 #define CIF_CIF_FRAME_STATUS 0x60
87 #define CIF_CIF_CUR_DST 0x64
88 #define CIF_CIF_LAST_LINE 0x68
89 #define CIF_CIF_LAST_PIX 0x6c
91 //The key register bit descrition
92 // CIF_CTRL Reg , ignore SCM,WBC,ISP,
93 #define DISABLE_CAPTURE (0x00<<0)
94 #define ENABLE_CAPTURE (0x01<<0)
95 #define MODE_ONEFRAME (0x00<<1)
96 #define MODE_PINGPONG (0x01<<1)
97 #define MODE_LINELOOP (0x02<<1)
98 #define AXI_BURST_16 (0x0F << 12)
101 #define FRAME_END_EN (0x01<<1)
102 #define BUS_ERR_EN (0x01<<6)
103 #define SCL_ERR_EN (0x01<<7)
106 #define VSY_HIGH_ACTIVE (0x01<<0)
107 #define VSY_LOW_ACTIVE (0x00<<0)
108 #define HSY_LOW_ACTIVE (0x01<<1)
109 #define HSY_HIGH_ACTIVE (0x00<<1)
110 #define INPUT_MODE_YUV (0x00<<2)
111 #define INPUT_MODE_PAL (0x02<<2)
112 #define INPUT_MODE_NTSC (0x03<<2)
113 #define INPUT_MODE_RAW (0x04<<2)
114 #define INPUT_MODE_JPEG (0x05<<2)
115 #define INPUT_MODE_MIPI (0x06<<2)
116 #define YUV_INPUT_ORDER_UYVY(ori) (ori & (~(0x03<<5)))
117 #define YUV_INPUT_ORDER_YVYU(ori) ((ori & (~(0x01<<6)))|(0x01<<5))
118 #define YUV_INPUT_ORDER_VYUY(ori) ((ori & (~(0x01<<5))) | (0x1<<6))
119 #define YUV_INPUT_ORDER_YUYV(ori) (ori|(0x03<<5))
120 #define YUV_INPUT_422 (0x00<<7)
121 #define YUV_INPUT_420 (0x01<<7)
122 #define INPUT_420_ORDER_EVEN (0x00<<8)
123 #define INPUT_420_ORDER_ODD (0x01<<8)
124 #define CCIR_INPUT_ORDER_ODD (0x00<<9)
125 #define CCIR_INPUT_ORDER_EVEN (0x01<<9)
126 #define RAW_DATA_WIDTH_8 (0x00<<11)
127 #define RAW_DATA_WIDTH_10 (0x01<<11)
128 #define RAW_DATA_WIDTH_12 (0x02<<11)
129 #define YUV_OUTPUT_422 (0x00<<16)
130 #define YUV_OUTPUT_420 (0x01<<16)
131 #define OUTPUT_420_ORDER_EVEN (0x00<<17)
132 #define OUTPUT_420_ORDER_ODD (0x01<<17)
133 #define RAWD_DATA_LITTLE_ENDIAN (0x00<<18)
134 #define RAWD_DATA_BIG_ENDIAN (0x01<<18)
135 #define UV_STORAGE_ORDER_UVUV (0x00<<19)
136 #define UV_STORAGE_ORDER_VUVU (0x01<<19)
139 #define ENABLE_SCL_DOWN (0x01<<0)
140 #define DISABLE_SCL_DOWN (0x00<<0)
141 #define ENABLE_SCL_UP (0x01<<1)
142 #define DISABLE_SCL_UP (0x00<<1)
143 #define ENABLE_YUV_16BIT_BYPASS (0x01<<4)
144 #define DISABLE_YUV_16BIT_BYPASS (0x00<<4)
145 #define ENABLE_RAW_16BIT_BYPASS (0x01<<5)
146 #define DISABLE_RAW_16BIT_BYPASS (0x00<<5)
147 #define ENABLE_32BIT_BYPASS (0x01<<6)
148 #define DISABLE_32BIT_BYPASS (0x00<<6)
151 #define MIN(x,y) ((x<y) ? x: y)
152 #define MAX(x,y) ((x>y) ? x: y)
153 #define RK_SENSOR_24MHZ 24*1000*1000 /* MHz */
154 #define RK_SENSOR_48MHZ 48
156 #define write_cif_reg(base,addr, val) __raw_writel(val, addr+(base))
157 #define read_cif_reg(base,addr) __raw_readl(addr+(base))
158 #define mask_cif_reg(addr, msk, val) write_cif_reg(addr, (val)|((~(msk))&read_cif_reg(addr)))
160 #if defined(CONFIG_ARCH_RK30)
162 #define CRU_PCLK_REG30 0xbc
163 #define ENANABLE_INVERT_PCLK_CIF0 ((0x1<<24)|(0x1<<8))
164 #define DISABLE_INVERT_PCLK_CIF0 ((0x1<<24)|(0x0<<8))
165 #define ENANABLE_INVERT_PCLK_CIF1 ((0x1<<28)|(0x1<<12))
166 #define DISABLE_INVERT_PCLK_CIF1 ((0x1<<28)|(0x0<<12))
168 #define CRU_CIF_RST_REG30 0x128
169 #define MASK_RST_CIF0 (0x01 << 30)
170 #define MASK_RST_CIF1 (0x01 << 31)
171 #define RQUEST_RST_CIF0 (0x01 << 14)
172 #define RQUEST_RST_CIF1 (0x01 << 15)
174 #define write_cru_reg(addr, val) __raw_writel(val, addr+RK30_CRU_BASE)
175 #define read_cru_reg(addr) __raw_readl(addr+RK30_CRU_BASE)
176 #define mask_cru_reg(addr, msk, val) write_cru_reg(addr,(val)|((~(msk))&read_cru_reg(addr)))
179 #if defined(CONFIG_ARCH_RK3066B)
181 #define CIF_DRIVER_STRENGTH_2MA (0x00 << 12)
182 #define CIF_DRIVER_STRENGTH_4MA (0x01 << 12)
183 #define CIF_DRIVER_STRENGTH_8MA (0x02 << 12)
184 #define CIF_DRIVER_STRENGTH_12MA (0x03 << 12)
185 #define CIF_DRIVER_STRENGTH_MASK (0x03 << 28)
188 #define CIF_CLKOUT_AMP_3V3 (0x00 << 10)
189 #define CIF_CLKOUT_AMP_1V8 (0x01 << 10)
190 #define CIF_CLKOUT_AMP_MASK (0x01 << 26)
192 #define write_grf_reg(addr, val) __raw_writel(val, addr+RK30_GRF_BASE)
193 #define read_grf_reg(addr) __raw_readl(addr+RK30_GRF_BASE)
194 #define mask_grf_reg(addr, msk, val) write_grf_reg(addr,(val)|((~(msk))&read_grf_reg(addr)))
196 #define write_grf_reg(addr, val)
197 #define read_grf_reg(addr) 0
198 #define mask_grf_reg(addr, msk, val)
201 #if defined(CONFIG_ARCH_RK2928)
202 #define write_cru_reg(addr, val)
203 #define read_cru_reg(addr) 0
204 #define mask_cru_reg(addr, msk, val)
208 //when work_with_ipp is not enabled,CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_OFF is not defined.something wrong with it
209 #ifdef CONFIG_VIDEO_RK29_WORK_IPP//CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_OFF
210 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_OFF
211 #define CAM_WORKQUEUE_IS_EN() ((pcdev->host_width != pcdev->icd->user_width) || (pcdev->host_height != pcdev->icd->user_height)\
212 || (pcdev->icd_cb.sensor_cb))
213 #define CAM_IPPWORK_IS_EN() ((pcdev->host_width != pcdev->icd->user_width) || (pcdev->host_height != pcdev->icd->user_height))
215 #define CAM_WORKQUEUE_IS_EN() (true)
216 #define CAM_IPPWORK_IS_EN() ((pcdev->zoominfo.a.c.width != pcdev->icd->user_width) || (pcdev->zoominfo.a.c.height != pcdev->icd->user_height))
218 #else //CONFIG_VIDEO_RK29_WORK_IPP
219 #define CAM_WORKQUEUE_IS_EN() (false)
220 #define CAM_IPPWORK_IS_EN() (false)
223 #define IS_CIF0() (pcdev->hostid == RK_CAM_PLATFORM_DEV_ID_0)
224 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP)
225 #define CROP_ALIGN_BYTES (0x03)
226 #define CIF_DO_CROP 0
227 #elif (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_ARM)
228 #define CROP_ALIGN_BYTES (0x03)
229 #define CIF_DO_CROP 0
230 #elif (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_RGA)
231 #define CROP_ALIGN_BYTES (0x03)
232 #define CIF_DO_CROP 0
233 #elif(CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_PP)
234 #define CROP_ALIGN_BYTES (0x0F)
235 #define CIF_DO_CROP 1
239 * Driver Version Note
241 *v0.0.x : this driver is 2.6.32 kernel driver;
242 *v0.1.x : this driver is 3.0.8 kernel driver;
244 *v0.x.1 : this driver first support rk2918;
245 *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
246 * and V4L2_PIX_FMT_YUV422P;
247 *v0.x.3 : this driver support VIDIOC_ENUM_FRAMEINTERVALS;
248 *v0.x.4 : this driver support digital zoom;
249 *v0.x.5 : this driver support test framerate and query framerate from board file configuration;
250 *v0.x.6 : this driver improve test framerate method;
251 *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
252 we do crop with cif and do scale with ipp , we will fix this next version.
253 *v0.x.8 : temp version,reinit capture list when setup video buf.
254 *v0.x.9 : 1. add the case of IPP unsupportted ,just cropped by CIF(not do the scale) this version.
255 2. flush workqueue when releas buffer
256 *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
258 2. when the flash is on ,flash off in a fixed time to prevent from flash light too hot.
259 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
260 4. add menu configs for convineuent to customize sensor series
261 *v0.x.b: specify the version is NOT sure stable.
262 *v0.x.c: 1. add cif reset when resolution changed to avoid of collecting data erro
263 2. irq process is splitted to two step.
264 *v0.x.e: fix bugs of early suspend when display_pd is closed.
265 *v0.x.f: fix calculate ipp memory size is enough or not in try_fmt function;
266 *v0.x.11: fix struct rk_camera_work may be reentrant
267 *v0.x.13: 1.add scale by arm,rga and pp.
268 2.CIF do the crop when digital zoom.
269 3.fix bug in prob func:request mem twice.
270 4.video_vq may be null when reinit work,fix it
271 5.arm scale algorithm has something wrong(may exceed the bound of width or height) ,fix it.
273 * 1. support rk3066b;
275 * 1. support 8Mega picture;
277 * 1. invalidate the limit which scale is invalidat when scale ratio > 2;
279 #define RK_CAM_VERSION_CODE KERNEL_VERSION(0, 2, 0x19)
281 /* limit to rk29 hardware capabilities */
282 #define RK_CAM_BUS_PARAM (SOCAM_MASTER |\
283 SOCAM_HSYNC_ACTIVE_HIGH |\
284 SOCAM_HSYNC_ACTIVE_LOW |\
285 SOCAM_VSYNC_ACTIVE_HIGH |\
286 SOCAM_VSYNC_ACTIVE_LOW |\
287 SOCAM_PCLK_SAMPLE_RISING |\
288 SOCAM_PCLK_SAMPLE_FALLING|\
289 SOCAM_DATA_ACTIVE_HIGH |\
290 SOCAM_DATA_ACTIVE_LOW|\
291 SOCAM_DATAWIDTH_8|SOCAM_DATAWIDTH_10|\
292 SOCAM_MCLK_24MHZ |SOCAM_MCLK_48MHZ)
294 #define RK_CAM_W_MIN 48
295 #define RK_CAM_H_MIN 32
296 #define RK_CAM_W_MAX 3856 /* ddl@rock-chips.com : 10M Pixel */
297 #define RK_CAM_H_MAX 2764
298 #define RK_CAM_FRAME_INVAL_INIT 3
299 #define RK_CAM_FRAME_INVAL_DC 3 /* ddl@rock-chips.com : */
300 #define RK30_CAM_FRAME_MEASURE 5
301 extern void videobuf_dma_contig_free(struct videobuf_queue *q, struct videobuf_buffer *buf);
302 extern dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf);
304 /* buffer for one video frame */
305 struct rk_camera_buffer
307 /* common v4l buffer stuff -- must be first */
308 struct videobuf_buffer vb;
309 enum v4l2_mbus_pixelcode code;
312 enum rk_camera_reg_state
320 unsigned int cifCtrl;
321 unsigned int cifCrop;
323 unsigned int cifIntEn;
325 unsigned int cifVirWidth;
326 unsigned int cifScale;
327 // unsigned int VipCrm;
328 enum rk_camera_reg_state Inval;
330 struct rk_camera_work
332 struct videobuf_buffer *vb;
333 struct rk_camera_dev *pcdev;
334 struct work_struct work;
335 struct list_head queue;
338 struct rk_camera_frmivalenum
340 struct v4l2_frmivalenum fival;
341 struct rk_camera_frmivalenum *nxt;
343 struct rk_camera_frmivalinfo
345 struct soc_camera_device *icd;
346 struct rk_camera_frmivalenum *fival_list;
348 struct rk_camera_zoominfo
350 struct semaphore sem;
356 #if CAMERA_VIDEOBUF_ARM_ACCESS
357 struct rk29_camera_vbinfo
359 unsigned int phy_addr;
360 void __iomem *vir_addr;
364 struct rk_camera_timer{
365 struct rk_camera_dev *pcdev;
366 struct hrtimer timer;
371 struct soc_camera_host soc_host;
373 /* RK2827x is only supposed to handle one camera on its Quick Capture
374 * interface. If anyone ever builds hardware to enable more than
375 * one camera, they will have to modify this driver too */
376 struct soc_camera_device *icd;
378 //************must modify start************/
380 struct clk *aclk_cif;
381 struct clk *hclk_cif;
382 struct clk *cif_clk_in;
383 struct clk *cif_clk_out;
384 //************must modify end************/
386 int frame_inval; /* ddl@rock-chips.com : The first frames is invalidate */
389 unsigned int last_fps;
390 unsigned long frame_interval;
393 unsigned int vipmem_phybase;
394 void __iomem *vipmem_virbase;
395 unsigned int vipmem_size;
396 unsigned int vipmem_bsize;
397 #if CAMERA_VIDEOBUF_ARM_ACCESS
398 struct rk29_camera_vbinfo *vbinfo;
399 unsigned int vbinfo_count;
403 int host_left; //sensor output size ?
409 struct rk29camera_platform_data *pdata;
410 struct resource *res;
411 struct list_head capture;
412 struct rk_camera_zoominfo zoominfo;
416 struct videobuf_buffer *active;
417 struct rk_camera_reg reginfo_suspend;
418 struct workqueue_struct *camera_wq;
419 struct rk_camera_work *camera_work;
420 struct list_head camera_work_queue;
421 spinlock_t camera_work_lock;
422 unsigned int camera_work_count;
423 struct rk_camera_timer fps_timer;
424 struct rk_camera_work camera_reinit_work;
426 rk29_camera_sensor_cb_s icd_cb;
427 struct rk_camera_frmivalinfo icd_frmival[2];
428 // atomic_t to_process_frames;
430 unsigned int reinit_times;
431 struct videobuf_queue *video_vq;
433 struct timeval first_tv;
436 static const struct v4l2_queryctrl rk_camera_controls[] =
438 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
440 .id = V4L2_CID_ZOOM_ABSOLUTE,
441 .type = V4L2_CTRL_TYPE_INTEGER,
442 .name = "DigitalZoom Control",
446 .default_value = 100,
451 static DEFINE_MUTEX(camera_lock);
452 static const char *rk_cam_driver_description = "RK_Camera";
454 static int rk_camera_s_stream(struct soc_camera_device *icd, int enable);
455 static void rk_camera_capture_process(struct work_struct *work);
459 * Videobuf operations
461 static int rk_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
464 struct soc_camera_device *icd = vq->priv_data;
465 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
466 struct rk_camera_dev *pcdev = ici->priv;
468 struct rk_camera_work *wk;
470 struct soc_mbus_pixelfmt fmt;
472 int bytes_per_line_host;
473 fmt.packing = SOC_MBUS_PACKING_1_5X8;
475 bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
476 icd->current_fmt->host_fmt);
477 if(icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_RGB565)
478 bytes_per_line_host = soc_mbus_bytes_per_line(pcdev->host_width,
480 else if(icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_RGB24)
481 bytes_per_line_host = pcdev->host_width*3;
483 bytes_per_line_host = soc_mbus_bytes_per_line(pcdev->host_width,
484 icd->current_fmt->host_fmt);
485 printk("user code = %d,packing = %d",icd->current_fmt->code,fmt.packing);
486 dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size);
488 if (bytes_per_line_host < 0)
489 return bytes_per_line_host;
491 /* planar capture requires Y, U and V buffers to be page aligned */
492 *size = PAGE_ALIGN(bytes_per_line*icd->user_height); /* Y pages UV pages, yuv422*/
493 pcdev->vipmem_bsize = PAGE_ALIGN(bytes_per_line_host * pcdev->host_height);
495 if (CAM_WORKQUEUE_IS_EN()) {
496 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_OFF
497 if (CAM_IPPWORK_IS_EN())
500 BUG_ON(pcdev->vipmem_size<pcdev->vipmem_bsize);
501 if (*count > pcdev->vipmem_size/pcdev->vipmem_bsize) { /* Buffers must be limited, when this resolution is genered by IPP */
502 *count = pcdev->vipmem_size/pcdev->vipmem_bsize;
505 if ((pcdev->camera_work_count != *count) && pcdev->camera_work) {
506 kfree(pcdev->camera_work);
507 pcdev->camera_work = NULL;
508 pcdev->camera_work_count = 0;
511 if (pcdev->camera_work == NULL) {
512 pcdev->camera_work = wk = kzalloc(sizeof(struct rk_camera_work)*(*count), GFP_KERNEL);
513 if (pcdev->camera_work == NULL) {
514 RKCAMERA_TR("\n %s kmalloc fail\n", __FUNCTION__);
517 INIT_LIST_HEAD(&pcdev->camera_work_queue);
519 for (i=0; i<(*count); i++) {
521 list_add_tail(&wk->queue, &pcdev->camera_work_queue);
524 pcdev->camera_work_count = (*count);
526 #if CAMERA_VIDEOBUF_ARM_ACCESS
527 if (pcdev->vbinfo && (pcdev->vbinfo_count != *count)) {
528 kfree(pcdev->vbinfo);
529 pcdev->vbinfo = NULL;
530 pcdev->vbinfo_count = 0x00;
533 if (pcdev->vbinfo == NULL) {
534 pcdev->vbinfo = kzalloc(sizeof(struct rk29_camera_vbinfo)*(*count), GFP_KERNEL);
535 if (pcdev->vbinfo == NULL) {
536 RKCAMERA_TR("\n %s vbinfo kmalloc fail\n", __FUNCTION__);
539 pcdev->vbinfo_count = *count;
543 pcdev->video_vq = vq;
544 RKCAMERA_DG("%s..%d.. videobuf size:%d, vipmem_buf size:%d, count:%d \n",__FUNCTION__,__LINE__, *size,pcdev->vipmem_size, *count);
548 static void rk_videobuf_free(struct videobuf_queue *vq, struct rk_camera_buffer *buf)
550 struct soc_camera_device *icd = vq->priv_data;
552 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
553 &buf->vb, buf->vb.baddr, buf->vb.bsize);
555 /* ddl@rock-chips.com: buf_release called soc_camera_streamoff and soc_camera_close*/
556 if (buf->vb.state == VIDEOBUF_NEEDS_INIT)
562 * This waits until this buffer is out of danger, i.e., until it is no
563 * longer in STATE_QUEUED or STATE_ACTIVE
565 //videobuf_waiton(vq, &buf->vb, 0, 0);
566 videobuf_dma_contig_free(vq, &buf->vb);
567 dev_dbg(&icd->dev, "%s freed\n", __func__);
568 buf->vb.state = VIDEOBUF_NEEDS_INIT;
571 static int rk_videobuf_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, enum v4l2_field field)
573 struct soc_camera_device *icd = vq->priv_data;
574 struct rk_camera_buffer *buf;
576 int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
577 icd->current_fmt->host_fmt);
578 if (bytes_per_line < 0)
579 return bytes_per_line;
581 buf = container_of(vb, struct rk_camera_buffer, vb);
583 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
584 vb, vb->baddr, vb->bsize);
586 /* Added list head initialization on alloc */
587 WARN_ON(!list_empty(&vb->queue));
589 BUG_ON(NULL == icd->current_fmt);
591 if (buf->code != icd->current_fmt->code ||
592 vb->width != icd->user_width ||
593 vb->height != icd->user_height ||
594 vb->field != field) {
595 buf->code = icd->current_fmt->code;
596 vb->width = icd->user_width;
597 vb->height = icd->user_height;
599 vb->state = VIDEOBUF_NEEDS_INIT;
602 vb->size = bytes_per_line*vb->height; /* ddl@rock-chips.com : fmt->depth is coorect */
603 if (0 != vb->baddr && vb->bsize < vb->size) {
608 if (vb->state == VIDEOBUF_NEEDS_INIT) {
609 ret = videobuf_iolock(vq, vb, NULL);
613 vb->state = VIDEOBUF_PREPARED;
618 rk_videobuf_free(vq, buf);
623 static inline void rk_videobuf_capture(struct videobuf_buffer *vb,struct rk_camera_dev *rk_pcdev)
625 unsigned int y_addr,uv_addr;
626 struct rk_camera_dev *pcdev = rk_pcdev;
629 if (CAM_WORKQUEUE_IS_EN()) {
630 y_addr = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
631 uv_addr = y_addr + pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height;
632 if (y_addr > (pcdev->vipmem_phybase + pcdev->vipmem_size - pcdev->vipmem_bsize)) {
633 RKCAMERA_TR("vipmem for IPP is overflow! %dx%d -> %dx%d vb_index:%d\n",pcdev->host_width,pcdev->host_height,
634 pcdev->icd->user_width,pcdev->icd->user_height, vb->i);
639 uv_addr = y_addr + vb->width * vb->height;
641 write_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y, y_addr);
642 write_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV, uv_addr);
643 write_cif_reg(pcdev->base,CIF_CIF_FRM1_ADDR_Y, y_addr);
644 write_cif_reg(pcdev->base,CIF_CIF_FRM1_ADDR_UV, uv_addr);
645 write_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS, 0x00000002);//frame1 has been ready to receive data,frame 2 is not used
648 /* Locking: Caller holds q->irqlock */
649 static void rk_videobuf_queue(struct videobuf_queue *vq,
650 struct videobuf_buffer *vb)
652 struct soc_camera_device *icd = vq->priv_data;
653 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
654 struct rk_camera_dev *pcdev = ici->priv;
655 #if CAMERA_VIDEOBUF_ARM_ACCESS
656 struct rk29_camera_vbinfo *vb_info;
659 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
660 vb, vb->baddr, vb->bsize);
662 vb->state = VIDEOBUF_QUEUED;
663 if (list_empty(&pcdev->capture)) {
664 list_add_tail(&vb->queue, &pcdev->capture);
666 if (list_entry(pcdev->capture.next, struct videobuf_buffer, queue) != vb)
667 list_add_tail(&vb->queue, &pcdev->capture);
669 BUG(); /* ddl@rock-chips.com : The same videobuffer queue again */
671 #if CAMERA_VIDEOBUF_ARM_ACCESS
673 vb_info = pcdev->vbinfo+vb->i;
674 if ((vb_info->phy_addr != vb->boff) || (vb_info->size != vb->bsize)) {
675 if (vb_info->vir_addr) {
676 iounmap(vb_info->vir_addr);
677 release_mem_region(vb_info->phy_addr, vb_info->size);
678 vb_info->vir_addr = NULL;
679 vb_info->phy_addr = 0x00;
680 vb_info->size = 0x00;
683 if (request_mem_region(vb->boff,vb->bsize,"rk_camera_vb")) {
684 vb_info->vir_addr = ioremap_cached(vb->boff,vb->bsize);
687 if (vb_info->vir_addr) {
688 vb_info->size = vb->bsize;
689 vb_info->phy_addr = vb->boff;
691 RKCAMERA_TR("%s..%d:ioremap videobuf %d failed\n",__FUNCTION__,__LINE__, vb->i);
696 if (!pcdev->active) {
698 rk_videobuf_capture(vb,pcdev);
701 static int rk_pixfmt2ippfmt(unsigned int pixfmt, int *ippfmt)
705 case V4L2_PIX_FMT_NV16:
706 case V4L2_PIX_FMT_NV61:
708 *ippfmt = IPP_Y_CBCR_H2V1;
711 case V4L2_PIX_FMT_NV12:
712 case V4L2_PIX_FMT_NV21:
714 *ippfmt = IPP_Y_CBCR_H2V2;
718 goto rk_pixfmt2ippfmt_err;
722 rk_pixfmt2ippfmt_err:
726 static int rk_pixfmt2rgafmt(unsigned int pixfmt, int *ippfmt)
730 case V4L2_PIX_FMT_YUV420:
731 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.
732 case V4L2_PIX_FMT_YUYV:
734 *ippfmt = RK_FORMAT_YCbCr_420_SP;
737 case V4L2_PIX_FMT_YVU420:
738 case V4L2_PIX_FMT_VYUY:
739 case V4L2_PIX_FMT_YVYU:
741 *ippfmt = RK_FORMAT_YCrCb_420_SP;
744 case V4L2_PIX_FMT_RGB565:
746 *ippfmt = RK_FORMAT_RGB_565;
749 case V4L2_PIX_FMT_RGB24:
751 *ippfmt = RK_FORMAT_RGB_888;
755 goto rk_pixfmt2rgafmt_err;
759 rk_pixfmt2rgafmt_err:
762 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_PP)
763 static int rk_camera_scale_crop_pp(struct work_struct *work){
764 struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
765 struct videobuf_buffer *vb = camera_work->vb;
766 struct rk_camera_dev *pcdev = camera_work->pcdev;
768 unsigned long int flags;
774 vipdata_base = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
776 memset(&init, 0, sizeof(init));
777 init.srcAddr = vipdata_base;
778 init.srcFormat = PP_IN_FORMAT_YUV420SEMI;
779 init.srcWidth = init.srcHStride = pcdev->zoominfo.vir_width;
780 init.srcHeight = init.srcVStride = pcdev->zoominfo.vir_height;
782 init.dstAddr = vb->boff;
783 init.dstFormat = PP_OUT_FORMAT_YUV420INTERLAVE;
784 init.dstWidth = init.dstHStride = pcdev->icd->user_width;
785 init.dstHeight = init.dstVStride = pcdev->icd->user_height;
787 printk("srcWidth = %d,srcHeight = %d,dstWidth = %d,dstHeight = %d\n",init.srcWidth,init.srcHeight,init.dstWidth,init.dstHeight);
789 ret = ppOpInit(&hnd, &init);
795 printk("can not create ppOp handle\n");
801 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_RGA)
802 extern rga_service_info rga_service;
803 extern int rga_blit_sync(rga_session *session, struct rga_req *req);
804 extern void rga_service_session_clear(rga_session *session);
805 static int rk_camera_scale_crop_rga(struct work_struct *work){
806 struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
807 struct videobuf_buffer *vb = camera_work->vb;
808 struct rk_camera_dev *pcdev = camera_work->pcdev;
810 unsigned long int flags;
816 const struct soc_mbus_pixelfmt *fmt;
818 fmt = soc_mbus_get_fmtdesc(pcdev->icd->current_fmt->code);
819 vipdata_base = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
820 if((pcdev->icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_RGB565)
821 && (pcdev->icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_RGB24)){
822 RKCAMERA_TR("RGA not support this format !\n");
825 if ((pcdev->icd->user_width > 0x800) || (pcdev->icd->user_height > 0x800)) {
826 scale_times = MAX((pcdev->icd->user_width/0x800),(pcdev->icd->user_height/0x800));
831 session.pid = current->pid;
832 INIT_LIST_HEAD(&session.waiting);
833 INIT_LIST_HEAD(&session.running);
834 INIT_LIST_HEAD(&session.list_session);
835 init_waitqueue_head(&session.wait);
836 /* no need to protect */
837 list_add_tail(&session.list_session, &rga_service.session);
838 atomic_set(&session.task_running, 0);
839 atomic_set(&session.num_done, 0);
841 memset(&req,0,sizeof(struct rga_req));
842 req.src.act_w = pcdev->zoominfo.a.c.width/scale_times;
843 req.src.act_h = pcdev->zoominfo.a.c.height/scale_times;
845 req.src.vir_w = pcdev->zoominfo.vir_width;
846 req.src.vir_h =pcdev->zoominfo.vir_height;
847 req.src.yrgb_addr = vipdata_base;
848 req.src.uv_addr =vipdata_base + pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height;;
849 req.src.v_addr = req.src.uv_addr ;
850 req.src.format =fmt->fourcc;
851 rk_pixfmt2rgafmt(fmt->fourcc,&req.src.format);
852 req.src.x_offset = pcdev->zoominfo.a.c.left;
853 req.src.y_offset = pcdev->zoominfo.a.c.top;
855 req.dst.act_w = pcdev->icd->user_width/scale_times;
856 req.dst.act_h = pcdev->icd->user_height/scale_times;
858 req.dst.vir_w = pcdev->icd->user_width;
859 req.dst.vir_h = pcdev->icd->user_height;
860 req.dst.x_offset = 0;
861 req.dst.y_offset = 0;
862 req.dst.yrgb_addr = vb->boff;
863 rk_pixfmt2rgafmt(pcdev->icd->current_fmt->host_fmt->fourcc,&req.dst.format);
865 req.clip.xmax = req.dst.vir_w-1;
867 req.clip.ymax = req.dst.vir_h -1;
874 req.mmu_info.mmu_en = 0;
876 for (h=0; h<scale_times; h++) {
877 for (w=0; w<scale_times; w++) {
880 req.src.yrgb_addr = vipdata_base;
881 req.src.uv_addr =vipdata_base + pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height;;
882 req.src.x_offset = pcdev->zoominfo.a.c.left+w*pcdev->zoominfo.a.c.width/scale_times;
883 req.src.y_offset = pcdev->zoominfo.a.c.top+h*pcdev->zoominfo.a.c.height/scale_times;
884 req.dst.x_offset = pcdev->icd->user_width*w/scale_times;
885 req.dst.y_offset = pcdev->icd->user_height*h/scale_times;
886 req.dst.yrgb_addr = vb->boff ;
887 // 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);
888 // 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);
889 // RKCAMERA_TR("req.src.yrgb_addr = 0x%x,req.dst.yrgb_addr = 0x%x\n",req.src.yrgb_addr,req.dst.yrgb_addr);
891 while(rga_times-- > 0) {
892 if (rga_blit_sync(&session, &req)){
893 RKCAMERA_TR("rga do erro,do again,rga_times = %d!\n",rga_times);
899 if (rga_times <= 0) {
900 spin_lock_irqsave(&pcdev->lock, flags);
901 vb->state = VIDEOBUF_NEEDS_INIT;
902 spin_unlock_irqrestore(&pcdev->lock, flags);
903 mutex_lock(&rga_service.lock);
904 list_del(&session.list_session);
905 rga_service_session_clear(&session);
906 mutex_unlock(&rga_service.lock);
912 mutex_lock(&rga_service.lock);
913 list_del(&session.list_session);
914 rga_service_session_clear(&session);
915 mutex_unlock(&rga_service.lock);
924 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP)
926 static int rk_camera_scale_crop_ipp(struct work_struct *work)
928 struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
929 struct videobuf_buffer *vb = camera_work->vb;
930 struct rk_camera_dev *pcdev = camera_work->pcdev;
932 unsigned long int flags;
934 struct rk29_ipp_req ipp_req;
935 int src_y_offset,src_uv_offset,dst_y_offset,dst_uv_offset,src_y_size,dst_y_size;
941 * IPP Dest image resolution is 2047x1088, so scale operation break up some times
943 if ((pcdev->icd->user_width > 0x7f0) || (pcdev->icd->user_height > 0x430)) {
944 scale_times = MAX((pcdev->icd->user_width/0x7f0),(pcdev->icd->user_height/0x430));
949 memset(&ipp_req, 0, sizeof(struct rk29_ipp_req));
952 ipp_req.timeout = 3000;
953 ipp_req.flag = IPP_ROT_0;
954 ipp_req.store_clip_mode =1;
955 ipp_req.src0.w = pcdev->zoominfo.a.c.width/scale_times;
956 ipp_req.src0.h = pcdev->zoominfo.a.c.height/scale_times;
957 ipp_req.src_vir_w = pcdev->zoominfo.vir_width;
958 rk_pixfmt2ippfmt(pcdev->pixfmt, &ipp_req.src0.fmt);
959 ipp_req.dst0.w = pcdev->icd->user_width/scale_times;
960 ipp_req.dst0.h = pcdev->icd->user_height/scale_times;
961 ipp_req.dst_vir_w = pcdev->icd->user_width;
962 rk_pixfmt2ippfmt(pcdev->pixfmt, &ipp_req.dst0.fmt);
963 vipdata_base = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
964 src_y_size = pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height; //vipmem
965 dst_y_size = pcdev->icd->user_width*pcdev->icd->user_height;
966 for (h=0; h<scale_times; h++) {
967 for (w=0; w<scale_times; w++) {
969 src_y_offset = (pcdev->zoominfo.a.c.top + h*pcdev->zoominfo.a.c.height/scale_times)* pcdev->zoominfo.vir_width
970 + pcdev->zoominfo.a.c.left + w*pcdev->zoominfo.a.c.width/scale_times;
971 src_uv_offset = (pcdev->zoominfo.a.c.top + h*pcdev->zoominfo.a.c.height/scale_times)* pcdev->zoominfo.vir_width/2
972 + pcdev->zoominfo.a.c.left + w*pcdev->zoominfo.a.c.width/scale_times;
974 dst_y_offset = pcdev->icd->user_width*pcdev->icd->user_height*h/scale_times + pcdev->icd->user_width*w/scale_times;
975 dst_uv_offset = pcdev->icd->user_width*pcdev->icd->user_height*h/scale_times/2 + pcdev->icd->user_width*w/scale_times;
977 ipp_req.src0.YrgbMst = vipdata_base + src_y_offset;
978 ipp_req.src0.CbrMst = vipdata_base + src_y_size + src_uv_offset;
979 ipp_req.dst0.YrgbMst = vb->boff + dst_y_offset;
980 ipp_req.dst0.CbrMst = vb->boff + dst_y_size + dst_uv_offset;
981 while(ipp_times-- > 0) {
982 if (ipp_blit_sync(&ipp_req)){
983 RKCAMERA_TR("ipp do erro,do again,ipp_times = %d!\n",ipp_times);
989 if (ipp_times <= 0) {
990 spin_lock_irqsave(&pcdev->lock, flags);
991 vb->state = VIDEOBUF_NEEDS_INIT;
992 spin_unlock_irqrestore(&pcdev->lock, flags);
993 RKCAMERA_TR("Capture image(vb->i:0x%x) which IPP operated is error:\n",vb->i);
994 RKCAMERA_TR("widx:%d hidx:%d ",w,h);
995 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);
996 RKCAMERA_TR("ipp_req.src0.YrgbMst:0x%x ipp_req.src0.CbrMst:0x%x \n", ipp_req.src0.YrgbMst,ipp_req.src0.CbrMst);
997 RKCAMERA_TR("ipp_req.src0.w:0x%x ipp_req.src0.h:0x%x \n",ipp_req.src0.w,ipp_req.src0.h);
998 RKCAMERA_TR("ipp_req.src0.fmt:0x%x\n",ipp_req.src0.fmt);
999 RKCAMERA_TR("ipp_req.dst0.YrgbMst:0x%x ipp_req.dst0.CbrMst:0x%x \n",ipp_req.dst0.YrgbMst,ipp_req.dst0.CbrMst);
1000 RKCAMERA_TR("ipp_req.dst0.w:0x%x ipp_req.dst0.h:0x%x \n",ipp_req.dst0.w ,ipp_req.dst0.h);
1001 RKCAMERA_TR("ipp_req.dst0.fmt:0x%x\n",ipp_req.dst0.fmt);
1002 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);
1003 RKCAMERA_TR("ipp_req.timeout:0x%x ipp_req.flag :0x%x\n",ipp_req.timeout,ipp_req.flag);
1013 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_ARM)
1014 static int rk_camera_scale_crop_arm(struct work_struct *work)
1016 struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
1017 struct videobuf_buffer *vb = camera_work->vb;
1018 struct rk_camera_dev *pcdev = camera_work->pcdev;
1019 struct rk29_camera_vbinfo *vb_info;
1020 unsigned char *psY,*pdY,*psUV,*pdUV;
1021 unsigned char *src,*dst;
1022 unsigned long src_phy,dst_phy;
1023 int srcW,srcH,cropW,cropH,dstW,dstH;
1024 long zoomindstxIntInv,zoomindstyIntInv;
1026 long yCoeff00,yCoeff01,xCoeff00,xCoeff01;
1031 src_phy = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
1032 src = psY = (unsigned char*)(pcdev->vipmem_virbase + vb->i*pcdev->vipmem_bsize);
1033 psUV = psY + pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height;
1035 srcW = pcdev->zoominfo.vir_width;
1036 srcH = pcdev->zoominfo.vir_height;
1037 cropW = pcdev->zoominfo.a.c.width;
1038 cropH = pcdev->zoominfo.a.c.height;
1040 psY = psY + (srcW-cropW);
1041 psUV = psUV + (srcW-cropW);
1043 vb_info = pcdev->vbinfo+vb->i;
1044 dst_phy = vb_info->phy_addr;
1045 dst = pdY = (unsigned char*)vb_info->vir_addr;
1046 pdUV = pdY + pcdev->icd->user_width*pcdev->icd->user_height;
1047 dstW = pcdev->icd->user_width;
1048 dstH = pcdev->icd->user_height;
1050 zoomindstxIntInv = ((unsigned long)cropW<<16)/dstW + 1;
1051 zoomindstyIntInv = ((unsigned long)cropH<<16)/dstH + 1;
1054 //for(y = 0; y<dstH - 1 ; y++ ) {
1055 for(y = 0; y<dstH; y++ ) {
1056 yCoeff00 = (y*zoomindstyIntInv)&0xffff;
1057 yCoeff01 = 0xffff - yCoeff00;
1058 sY = (y*zoomindstyIntInv >> 16);
1059 sY = (sY >= srcH - 1)? (srcH - 2) : sY;
1060 for(x = 0; x<dstW; x++ ) {
1061 xCoeff00 = (x*zoomindstxIntInv)&0xffff;
1062 xCoeff01 = 0xffff - xCoeff00;
1063 sX = (x*zoomindstxIntInv >> 16);
1064 sX = (sX >= srcW -1)?(srcW- 2) : sX;
1065 a = psY[sY*srcW + sX];
1066 b = psY[sY*srcW + sX + 1];
1067 c = psY[(sY+1)*srcW + sX];
1068 d = psY[(sY+1)*srcW + sX + 1];
1070 r0 = (a * xCoeff01 + b * xCoeff00)>>16 ;
1071 r1 = (c * xCoeff01 + d * xCoeff00)>>16 ;
1072 r0 = (r0 * yCoeff01 + r1 * yCoeff00)>>16;
1085 //for(y = 0; y<dstH - 1 ; y++ ) {
1086 for(y = 0; y<dstH; y++ ) {
1087 yCoeff00 = (y*zoomindstyIntInv)&0xffff;
1088 yCoeff01 = 0xffff - yCoeff00;
1089 sY = (y*zoomindstyIntInv >> 16);
1090 sY = (sY >= srcH -1)? (srcH - 2) : sY;
1091 for(x = 0; x<dstW; x++ ) {
1092 xCoeff00 = (x*zoomindstxIntInv)&0xffff;
1093 xCoeff01 = 0xffff - xCoeff00;
1094 sX = (x*zoomindstxIntInv >> 16);
1095 sX = (sX >= srcW -1)?(srcW- 2) : sX;
1097 a = psUV[(sY*srcW + sX)*2];
1098 b = psUV[(sY*srcW + sX + 1)*2];
1099 c = psUV[((sY+1)*srcW + sX)*2];
1100 d = psUV[((sY+1)*srcW + sX + 1)*2];
1102 r0 = (a * xCoeff01 + b * xCoeff00)>>16 ;
1103 r1 = (c * xCoeff01 + d * xCoeff00)>>16 ;
1104 r0 = (r0 * yCoeff01 + r1 * yCoeff00)>>16;
1109 a = psUV[(sY*srcW + sX)*2 + 1];
1110 b = psUV[(sY*srcW + sX + 1)*2 + 1];
1111 c = psUV[((sY+1)*srcW + sX)*2 + 1];
1112 d = psUV[((sY+1)*srcW + sX + 1)*2 + 1];
1114 r0 = (a * xCoeff01 + b * xCoeff00)>>16 ;
1115 r1 = (c * xCoeff01 + d * xCoeff00)>>16 ;
1116 r0 = (r0 * yCoeff01 + r1 * yCoeff00)>>16;
1122 rk_camera_scale_crop_arm_end:
1124 dmac_flush_range((void*)src,(void*)(src+pcdev->vipmem_bsize));
1125 outer_flush_range((phys_addr_t)src_phy,(phys_addr_t)(src_phy+pcdev->vipmem_bsize));
1127 dmac_flush_range((void*)dst,(void*)(dst+vb_info->size));
1128 outer_flush_range((phys_addr_t)dst_phy,(phys_addr_t)(dst_phy+vb_info->size));
1133 static void rk_camera_capture_process(struct work_struct *work)
1135 struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
1136 struct videobuf_buffer *vb = camera_work->vb;
1137 struct rk_camera_dev *pcdev = camera_work->pcdev;
1138 //enum v4l2_mbus_pixelcode icd_code = pcdev->icd->current_fmt->code;
1139 unsigned long flags = 0;
1142 if (!CAM_WORKQUEUE_IS_EN())
1143 goto rk_camera_capture_process_end;
1145 down(&pcdev->zoominfo.sem);
1146 if (pcdev->icd_cb.scale_crop_cb){
1147 err = (pcdev->icd_cb.scale_crop_cb)(work);
1149 up(&pcdev->zoominfo.sem);
1151 if (pcdev->icd_cb.sensor_cb)
1152 (pcdev->icd_cb.sensor_cb)(vb);
1154 rk_camera_capture_process_end:
1156 vb->state = VIDEOBUF_ERROR;
1158 if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) {
1159 vb->state = VIDEOBUF_DONE;
1163 wake_up(&(camera_work->vb->done));
1164 spin_lock_irqsave(&pcdev->camera_work_lock, flags);
1165 list_add_tail(&camera_work->queue, &pcdev->camera_work_queue);
1166 spin_unlock_irqrestore(&pcdev->camera_work_lock, flags);
1169 static irqreturn_t rk_camera_irq(int irq, void *data)
1171 struct rk_camera_dev *pcdev = data;
1172 struct videobuf_buffer *vb;
1173 struct rk_camera_work *wk;
1175 unsigned long tmp_intstat;
1176 unsigned long tmp_cifctrl;
1178 tmp_intstat = read_cif_reg(pcdev->base,CIF_CIF_INTSTAT);
1179 tmp_cifctrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
1180 if(pcdev->stop_cif == true)
1182 printk("cif has stopped by app,needn't to deal this irq\n");
1183 write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF); /* clear vip interrupte single */
1186 if ((tmp_intstat & 0x0200) /*&& ((tmp_intstat & 0x1)==0)*/){//bit9 =1 ,bit0 = 0
1187 write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0x0200); /* clear vip interrupte single */
1188 if(tmp_cifctrl & ENABLE_CAPTURE)
1189 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl & ~ENABLE_CAPTURE));
1193 /* ddl@rock-chps.com : Current VIP is run in One Frame Mode, Frame 1 is validate */
1194 if (read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS) & 0x01) {
1195 write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0x01); /* clear vip interrupte single */
1197 do_gettimeofday(&pcdev->first_tv);
1201 goto RK_CAMERA_IRQ_END;
1202 if (pcdev->frame_inval>0) {
1203 pcdev->frame_inval--;
1204 rk_videobuf_capture(pcdev->active,pcdev);
1205 goto RK_CAMERA_IRQ_END;
1206 } else if (pcdev->frame_inval) {
1207 RKCAMERA_TR("frame_inval : %0x",pcdev->frame_inval);
1208 pcdev->frame_inval = 0;
1210 if(pcdev->fps == RK30_CAM_FRAME_MEASURE) {
1211 do_gettimeofday(&tv);
1212 pcdev->frame_interval = ((tv.tv_sec*1000000 + tv.tv_usec) - (pcdev->first_tv.tv_sec*1000000 + pcdev->first_tv.tv_usec))
1213 /(RK30_CAM_FRAME_MEASURE-1);
1217 printk("no acticve buffer!!!\n");
1218 goto RK_CAMERA_IRQ_END;
1220 /* ddl@rock-chips.com : this vb may be deleted from queue */
1221 if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) {
1222 list_del_init(&vb->queue);
1224 pcdev->active = NULL;
1225 if (!list_empty(&pcdev->capture)) {
1226 pcdev->active = list_entry(pcdev->capture.next, struct videobuf_buffer, queue);
1227 if (pcdev->active) {
1228 WARN_ON(pcdev->active->state != VIDEOBUF_QUEUED);
1229 rk_videobuf_capture(pcdev->active,pcdev);
1232 if (pcdev->active == NULL) {
1233 RKCAMERA_DG("%s video_buf queue is empty!\n",__FUNCTION__);
1236 do_gettimeofday(&vb->ts);
1237 if (CAM_WORKQUEUE_IS_EN()) {
1238 if (!list_empty(&pcdev->camera_work_queue)) {
1239 wk = list_entry(pcdev->camera_work_queue.next, struct rk_camera_work, queue);
1240 list_del_init(&wk->queue);
1241 INIT_WORK(&(wk->work), rk_camera_capture_process);
1244 queue_work(pcdev->camera_wq, &(wk->work));
1247 if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) {
1248 vb->state = VIDEOBUF_DONE;
1257 if((tmp_cifctrl & ENABLE_CAPTURE) == 0)
1258 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl | ENABLE_CAPTURE));
1263 static void rk_videobuf_release(struct videobuf_queue *vq,
1264 struct videobuf_buffer *vb)
1266 struct rk_camera_buffer *buf = container_of(vb, struct rk_camera_buffer, vb);
1267 struct soc_camera_device *icd = vq->priv_data;
1268 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1269 struct rk_camera_dev *pcdev = ici->priv;
1270 #if CAMERA_VIDEOBUF_ARM_ACCESS
1271 struct rk29_camera_vbinfo *vb_info =NULL;
1275 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
1276 vb, vb->baddr, vb->bsize);
1280 case VIDEOBUF_ACTIVE:
1281 dev_dbg(&icd->dev, "%s (active)\n", __func__);
1283 case VIDEOBUF_QUEUED:
1284 dev_dbg(&icd->dev, "%s (queued)\n", __func__);
1286 case VIDEOBUF_PREPARED:
1287 dev_dbg(&icd->dev, "%s (prepared)\n", __func__);
1290 dev_dbg(&icd->dev, "%s (unknown)\n", __func__);
1294 if (vb == pcdev->active) {
1295 RKCAMERA_DG("%s Wait for this video buf(0x%x) write finished!\n ",__FUNCTION__,(unsigned int)vb);
1296 interruptible_sleep_on_timeout(&vb->done, msecs_to_jiffies(500));
1297 RKCAMERA_DG("%s This video buf(0x%x) write finished, release now!!\n",__FUNCTION__,(unsigned int)vb);
1300 flush_workqueue(pcdev->camera_wq);
1301 #if CAMERA_VIDEOBUF_ARM_ACCESS
1302 if (pcdev->vbinfo) {
1303 vb_info = pcdev->vbinfo + vb->i;
1305 if (vb_info->vir_addr) {
1306 iounmap(vb_info->vir_addr);
1307 release_mem_region(vb_info->phy_addr, vb_info->size);
1308 memset(vb_info, 0x00, sizeof(struct rk29_camera_vbinfo));
1313 rk_videobuf_free(vq, buf);
1316 static struct videobuf_queue_ops rk_videobuf_ops =
1318 .buf_setup = rk_videobuf_setup,
1319 .buf_prepare = rk_videobuf_prepare,
1320 .buf_queue = rk_videobuf_queue,
1321 .buf_release = rk_videobuf_release,
1324 static void rk_camera_init_videobuf(struct videobuf_queue *q,
1325 struct soc_camera_device *icd)
1327 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1328 struct rk_camera_dev *pcdev = ici->priv;
1330 /* We must pass NULL as dev pointer, then all pci_* dma operations
1331 * transform to normal dma_* ones. */
1332 videobuf_queue_dma_contig_init(q,
1334 ici->v4l2_dev.dev, &pcdev->lock,
1335 V4L2_BUF_TYPE_VIDEO_CAPTURE,
1337 sizeof(struct rk_camera_buffer),
1338 icd,&icd->video_lock);
1340 static int rk_camera_activate(struct rk_camera_dev *pcdev, struct soc_camera_device *icd)
1344 if(!pcdev->aclk_cif || !pcdev->hclk_cif || !pcdev->cif_clk_in || !pcdev->cif_clk_out){
1345 RKCAMERA_TR(KERN_ERR "failed to get cif clock source\n");
1347 goto RK_CAMERA_ACTIVE_ERR;
1350 clk_enable(pcdev->pd_cif);
1351 clk_enable(pcdev->aclk_cif);
1353 clk_enable(pcdev->hclk_cif);
1354 clk_enable(pcdev->cif_clk_in);
1356 //if (icd->ops->query_bus_param) /* ddl@rock-chips.com : Query Sensor's xclk */
1357 //sensor_bus_flags = icd->ops->query_bus_param(icd);
1358 clk_enable(pcdev->cif_clk_out);
1359 clk_set_rate(pcdev->cif_clk_out,RK_SENSOR_24MHZ);
1362 //soft reset the registers
1363 #if 0 //has somthing wrong when suspend and resume now
1365 printk("before set cru register reset cif0 0x%x\n\n",read_cru_reg(CRU_CIF_RST_REG30));
1368 printk("CIF_CIF_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CTRL));
1369 printk("CIF_CIF_INTEN = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTEN));
1370 printk("CIF_CIF_INTSTAT = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTSTAT));
1371 printk("CIF_CIF_FOR = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_FOR));
1372 printk("CIF_CIF_CROP = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CROP));
1373 printk("CIF_CIF_SET_SIZE = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE));
1374 printk("CIF_CIF_SCL_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL));
1375 printk("CRU_PCLK_REG30 = 0X%x\n",read_cru_reg(CRU_PCLK_REG30));
1376 printk("CIF_CIF_LAST_LINE = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_LINE));
1378 printk("CIF_CIF_LAST_PIX = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_PIX));
1379 printk("CIF_CIF_VIR_LINE_WIDTH = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH));
1380 printk("CIF_CIF_LINE_NUM_ADDR = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LINE_NUM_ADDR));
1381 printk("CIF_CIF_FRM0_ADDR_Y = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y));
1382 printk("CIF_CIF_FRM0_ADDR_UV = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV));
1383 printk("CIF_CIF_FRAME_STATUS = 0X%x\n\n",read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS));
1387 write_cru_reg(CRU_CIF_RST_REG30,(/*read_cru_reg(CRU_CIF_RST_REG30)|*/MASK_RST_CIF0|RQUEST_RST_CIF0 ));
1388 printk("set cru register reset cif0 0x%x\n",read_cru_reg(CRU_CIF_RST_REG30));
1389 write_cru_reg(CRU_CIF_RST_REG30,(read_cru_reg(CRU_CIF_RST_REG30)&(~RQUEST_RST_CIF0)) | MASK_RST_CIF0);
1391 printk("clean cru register reset cif0 0x%x\n",read_cru_reg(CRU_CIF_RST_REG30));
1393 write_cru_reg(CRU_CIF_RST_REG30,MASK_RST_CIF1|RQUEST_RST_CIF1 | (read_cru_reg(CRU_CIF_RST_REG30)));
1394 write_cru_reg(CRU_CIF_RST_REG30,(read_cru_reg(CRU_CIF_RST_REG30)&(~RQUEST_RST_CIF1)) | MASK_RST_CIF1);
1397 write_cif_reg(pcdev->base,CIF_CIF_CTRL,AXI_BURST_16|MODE_ONEFRAME|DISABLE_CAPTURE); /* ddl@rock-chips.com : vip ahb burst 16 */
1398 write_cif_reg(pcdev->base,CIF_CIF_INTEN, 0x01); //capture complete interrupt enable
1399 RKCAMERA_DG("%s..%d.. CIF_CIF_CTRL = 0x%x\n",__FUNCTION__,__LINE__,read_cif_reg(pcdev->base, CIF_CIF_CTRL));
1401 RK_CAMERA_ACTIVE_ERR:
1405 static void rk_camera_deactivate(struct rk_camera_dev *pcdev)
1407 clk_disable(pcdev->aclk_cif);
1409 clk_disable(pcdev->hclk_cif);
1410 clk_disable(pcdev->cif_clk_in);
1412 clk_disable(pcdev->cif_clk_out);
1413 clk_enable(pcdev->cif_clk_out);
1414 clk_set_rate(pcdev->cif_clk_out,48*1000*1000);
1415 clk_disable(pcdev->cif_clk_out);
1417 clk_disable(pcdev->pd_cif);
1422 /* The following two functions absolutely depend on the fact, that
1423 * there can be only one camera on RK28 quick capture interface */
1424 static int rk_camera_add_device(struct soc_camera_device *icd)
1426 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1427 struct rk_camera_dev *pcdev = ici->priv;
1428 struct device *control = to_soc_camera_control(icd);
1429 struct v4l2_subdev *sd;
1430 int ret,i,icd_catch;
1431 struct rk_camera_frmivalenum *fival_list,*fival_nxt;
1433 mutex_lock(&camera_lock);
1440 RKCAMERA_DG("%s driver attached to %s\n",RK29_CAM_DRV_NAME,dev_name(icd->pdev));
1442 pcdev->frame_inval = RK_CAM_FRAME_INVAL_INIT;
1443 pcdev->active = NULL;
1445 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
1446 pcdev->zoominfo.zoom_rate = 100;
1447 pcdev->fps_timer.istarted = false;
1449 /* ddl@rock-chips.com: capture list must be reset, because this list may be not empty,
1450 * if app havn't dequeue all videobuf before close camera device;
1452 INIT_LIST_HEAD(&pcdev->capture);
1454 ret = rk_camera_activate(pcdev,icd);
1457 /* ddl@rock-chips.com : v4l2_subdev is not created when ici->ops->add called in soc_camera_probe */
1459 sd = dev_get_drvdata(control);
1460 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_IOREQUEST,(void*)pcdev->pdata);
1462 ret = v4l2_subdev_call(sd,core, init, 0);
1466 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_CB_REGISTER,(void*)(&pcdev->icd_cb));
1469 pcdev->icd_init = 0;
1472 for (i=0; i<2; i++) {
1473 if (pcdev->icd_frmival[i].icd == icd)
1475 if (pcdev->icd_frmival[i].icd == NULL) {
1476 pcdev->icd_frmival[i].icd = icd;
1480 if (icd_catch == 0) {
1481 fival_list = pcdev->icd_frmival[0].fival_list;
1482 fival_nxt = fival_list;
1483 while(fival_nxt != NULL) {
1484 fival_nxt = fival_list->nxt;
1486 fival_list = fival_nxt;
1488 pcdev->icd_frmival[0].icd = icd;
1489 pcdev->icd_frmival[0].fival_list = kzalloc(sizeof(struct rk_camera_frmivalenum),GFP_KERNEL);
1492 mutex_unlock(&camera_lock);
1496 static void rk_camera_remove_device(struct soc_camera_device *icd)
1498 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1499 struct rk_camera_dev *pcdev = ici->priv;
1500 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1501 #if CAMERA_VIDEOBUF_ARM_ACCESS
1502 struct rk29_camera_vbinfo *vb_info;
1506 mutex_lock(&camera_lock);
1507 BUG_ON(icd != pcdev->icd);
1509 RKCAMERA_DG("%s driver detached from %s\n",RK29_CAM_DRV_NAME,dev_name(icd->pdev));
1511 /* ddl@rock-chips.com: Application will call VIDIOC_STREAMOFF before close device, but
1512 stream may be turn on again before close device, if suspend and resume happened. */
1513 if (read_cif_reg(pcdev->base,CIF_CIF_CTRL) & ENABLE_CAPTURE) {
1514 rk_camera_s_stream(icd,0);
1517 //soft reset the registers
1518 #if 0 //has somthing wrong when suspend and resume now
1520 write_cru_reg(CRU_CIF_RST_REG30,MASK_RST_CIF0|RQUEST_RST_CIF0 | (read_cru_reg(CRU_CIF_RST_REG30)));
1521 write_cru_reg(CRU_CIF_RST_REG30,(read_cru_reg(CRU_CIF_RST_REG30)&(~RQUEST_RST_CIF0)) | MASK_RST_CIF0);
1523 write_cru_reg(CRU_CIF_RST_REG30,MASK_RST_CIF1|RQUEST_RST_CIF1 | (read_cru_reg(CRU_CIF_RST_REG30)));
1524 write_cru_reg(CRU_CIF_RST_REG30,(read_cru_reg(CRU_CIF_RST_REG30)&(~RQUEST_RST_CIF1)) | MASK_RST_CIF1);
1527 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_DEACTIVATE,NULL);
1528 //if stream off is not been executed,timer is running.
1529 if(pcdev->fps_timer.istarted){
1530 hrtimer_cancel(&pcdev->fps_timer.timer);
1531 pcdev->fps_timer.istarted = false;
1533 flush_work(&(pcdev->camera_reinit_work.work));
1534 flush_workqueue((pcdev->camera_wq));
1536 if (pcdev->camera_work) {
1537 kfree(pcdev->camera_work);
1538 pcdev->camera_work = NULL;
1539 pcdev->camera_work_count = 0;
1540 INIT_LIST_HEAD(&pcdev->camera_work_queue);
1542 rk_camera_deactivate(pcdev);
1543 #if CAMERA_VIDEOBUF_ARM_ACCESS
1544 if (pcdev->vbinfo) {
1545 vb_info = pcdev->vbinfo;
1546 for (i=0; i<pcdev->vbinfo_count; i++) {
1547 if (vb_info->vir_addr) {
1548 iounmap(vb_info->vir_addr);
1549 release_mem_region(vb_info->phy_addr, vb_info->size);
1550 memset(vb_info, 0x00, sizeof(struct rk29_camera_vbinfo));
1554 kfree(pcdev->vbinfo);
1555 pcdev->vbinfo = NULL;
1556 pcdev->vbinfo_count = 0;
1559 pcdev->active = NULL;
1561 pcdev->icd_cb.sensor_cb = NULL;
1562 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
1563 /* ddl@rock-chips.com: capture list must be reset, because this list may be not empty,
1564 * if app havn't dequeue all videobuf before close camera device;
1566 INIT_LIST_HEAD(&pcdev->capture);
1568 mutex_unlock(&camera_lock);
1569 RKCAMERA_DG("%s exit\n",__FUNCTION__);
1573 static int rk_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
1575 unsigned long bus_flags, camera_flags, common_flags;
1576 unsigned int cif_ctrl_val = 0;
1577 const struct soc_mbus_pixelfmt *fmt;
1579 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1580 struct rk_camera_dev *pcdev = ici->priv;
1581 RKCAMERA_DG("%s..%d..\n",__FUNCTION__,__LINE__);
1583 fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code);
1587 bus_flags = RK_CAM_BUS_PARAM;
1588 /* If requested data width is supported by the platform, use it */
1589 switch (fmt->bits_per_sample) {
1591 if (!(bus_flags & SOCAM_DATAWIDTH_10))
1595 if (!(bus_flags & SOCAM_DATAWIDTH_9))
1599 if (!(bus_flags & SOCAM_DATAWIDTH_8))
1606 if (icd->ops->query_bus_param)
1607 camera_flags = icd->ops->query_bus_param(icd);
1611 common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
1612 if (!common_flags) {
1614 goto RK_CAMERA_SET_BUS_PARAM_END;
1617 ret = icd->ops->set_bus_param(icd, common_flags);
1619 goto RK_CAMERA_SET_BUS_PARAM_END;
1621 cif_ctrl_val = read_cif_reg(pcdev->base,CIF_CIF_FOR);
1622 RKCAMERA_DG("%s..%d..cif_ctrl_val = 0x%x\n",__FUNCTION__,__LINE__,cif_ctrl_val);
1623 if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) {
1625 write_cru_reg(CRU_PCLK_REG30, read_cru_reg(CRU_PCLK_REG30) | ENANABLE_INVERT_PCLK_CIF0);
1626 RKCAMERA_DG("enable cif0 pclk invert\n");
1628 write_cru_reg(CRU_PCLK_REG30, read_cru_reg(CRU_PCLK_REG30) | ENANABLE_INVERT_PCLK_CIF1);
1629 RKCAMERA_DG("enable cif1 pclk invert\n");
1633 write_cru_reg(CRU_PCLK_REG30, (read_cru_reg(CRU_PCLK_REG30) & 0xFFFFEFF ) | DISABLE_INVERT_PCLK_CIF0);
1634 RKCAMERA_DG("diable cif0 pclk invert\n");
1636 write_cru_reg(CRU_PCLK_REG30, (read_cru_reg(CRU_PCLK_REG30) & 0xFFFEFFF) | DISABLE_INVERT_PCLK_CIF1);
1637 RKCAMERA_DG("diable cif1 pclk invert\n");
1640 if (common_flags & SOCAM_HSYNC_ACTIVE_LOW) {
1641 cif_ctrl_val |= HSY_LOW_ACTIVE;
1643 cif_ctrl_val &= ~HSY_LOW_ACTIVE;
1645 if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH) {
1646 cif_ctrl_val |= VSY_HIGH_ACTIVE;
1648 cif_ctrl_val &= ~VSY_HIGH_ACTIVE;
1651 /* ddl@rock-chips.com : Don't enable capture here, enable in stream_on */
1652 //vip_ctrl_val |= ENABLE_CAPTURE;
1653 write_cif_reg(pcdev->base,CIF_CIF_FOR, cif_ctrl_val);
1654 RKCAMERA_DG("%s..ctrl:0x%x CIF_CIF_FOR=%x \n",__FUNCTION__,cif_ctrl_val,read_cif_reg(pcdev->base,CIF_CIF_FOR));
1656 RK_CAMERA_SET_BUS_PARAM_END:
1658 RKCAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
1662 static int rk_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
1664 unsigned long bus_flags, camera_flags;
1667 bus_flags = RK_CAM_BUS_PARAM;
1668 if (icd->ops->query_bus_param) {
1669 camera_flags = icd->ops->query_bus_param(icd);
1673 ret = soc_camera_bus_param_compatible(camera_flags, bus_flags) ;
1676 dev_warn(icd->dev.parent,
1677 "Flags incompatible: camera %lx, host %lx\n",
1678 camera_flags, bus_flags);
1682 static const struct soc_mbus_pixelfmt rk_camera_formats[] = {
1684 .fourcc = V4L2_PIX_FMT_NV12,
1685 .name = "YUV420 NV12",
1686 .bits_per_sample = 8,
1687 .packing = SOC_MBUS_PACKING_1_5X8,
1688 .order = SOC_MBUS_ORDER_LE,
1690 .fourcc = V4L2_PIX_FMT_NV16,
1691 .name = "YUV422 NV16",
1692 .bits_per_sample = 8,
1693 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1694 .order = SOC_MBUS_ORDER_LE,
1696 .fourcc = V4L2_PIX_FMT_NV21,
1697 .name = "YUV420 NV21",
1698 .bits_per_sample = 8,
1699 .packing = SOC_MBUS_PACKING_1_5X8,
1700 .order = SOC_MBUS_ORDER_LE,
1702 .fourcc = V4L2_PIX_FMT_NV61,
1703 .name = "YUV422 NV61",
1704 .bits_per_sample = 8,
1705 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1706 .order = SOC_MBUS_ORDER_LE,
1708 .fourcc = V4L2_PIX_FMT_RGB565,
1710 .bits_per_sample = 8,
1711 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1712 .order = SOC_MBUS_ORDER_LE,
1714 .fourcc = V4L2_PIX_FMT_RGB24,
1716 .bits_per_sample = 8,
1717 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1718 .order = SOC_MBUS_ORDER_LE,
1722 static void rk_camera_setup_format(struct soc_camera_device *icd, __u32 host_pixfmt, enum v4l2_mbus_pixelcode icd_code, struct v4l2_rect *rect)
1724 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1725 struct rk_camera_dev *pcdev = ici->priv;
1726 unsigned int cif_fs = 0,cif_crop = 0;
1727 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;
1729 const struct soc_mbus_pixelfmt *fmt;
1730 fmt = soc_mbus_get_fmtdesc(icd_code);
1732 if((host_pixfmt == V4L2_PIX_FMT_RGB565) || (host_pixfmt == V4L2_PIX_FMT_RGB24)){
1733 if(fmt->fourcc == V4L2_PIX_FMT_NV12)
1734 host_pixfmt = V4L2_PIX_FMT_NV12;
1735 else if(fmt->fourcc == V4L2_PIX_FMT_NV21)
1736 host_pixfmt = V4L2_PIX_FMT_NV21;
1738 switch (host_pixfmt)
1740 case V4L2_PIX_FMT_NV16:
1741 cif_fmt_val &= ~YUV_OUTPUT_422;
1742 cif_fmt_val &= ~UV_STORAGE_ORDER_UVUV;
1743 pcdev->frame_inval = RK_CAM_FRAME_INVAL_DC;
1744 pcdev->pixfmt = host_pixfmt;
1746 case V4L2_PIX_FMT_NV61:
1747 cif_fmt_val &= ~YUV_OUTPUT_422;
1748 cif_fmt_val |= UV_STORAGE_ORDER_VUVU;
1749 pcdev->frame_inval = RK_CAM_FRAME_INVAL_DC;
1750 pcdev->pixfmt = host_pixfmt;
1752 case V4L2_PIX_FMT_NV12:
1753 cif_fmt_val |= YUV_OUTPUT_420;
1754 cif_fmt_val &= ~UV_STORAGE_ORDER_UVUV;
1755 if (pcdev->frame_inval != RK_CAM_FRAME_INVAL_INIT)
1756 pcdev->frame_inval = RK_CAM_FRAME_INVAL_INIT;
1757 pcdev->pixfmt = host_pixfmt;
1759 case V4L2_PIX_FMT_NV21:
1760 cif_fmt_val |= YUV_OUTPUT_420;
1761 cif_fmt_val |= UV_STORAGE_ORDER_VUVU;
1762 if (pcdev->frame_inval != RK_CAM_FRAME_INVAL_INIT)
1763 pcdev->frame_inval = RK_CAM_FRAME_INVAL_INIT;
1764 pcdev->pixfmt = host_pixfmt;
1766 default: /* ddl@rock-chips.com : vip output format is hold when pixfmt is invalidate */
1767 cif_fmt_val |= YUV_OUTPUT_422;
1772 case V4L2_MBUS_FMT_UYVY8_2X8:
1773 cif_fmt_val = YUV_INPUT_ORDER_UYVY(cif_fmt_val);
1775 case V4L2_MBUS_FMT_YUYV8_2X8:
1776 cif_fmt_val = YUV_INPUT_ORDER_YUYV(cif_fmt_val);
1778 case V4L2_MBUS_FMT_YVYU8_2X8:
1779 cif_fmt_val = YUV_INPUT_ORDER_YVYU(cif_fmt_val);
1781 case V4L2_MBUS_FMT_VYUY8_2X8:
1782 cif_fmt_val = YUV_INPUT_ORDER_VYUY(cif_fmt_val);
1785 cif_fmt_val = YUV_INPUT_ORDER_YUYV(cif_fmt_val);
1790 #ifdef CONFIG_ARCH_RK30
1793 // pmu_set_idle_request(IDLE_REQ_VIO, true);
1794 cru_set_soft_reset(SOFT_RST_CIF0, true);
1796 cru_set_soft_reset(SOFT_RST_CIF0, false);
1797 // pmu_set_idle_request(IDLE_REQ_VIO, false);
1800 // pmu_set_idle_request(IDLE_REQ_VIO, true);
1801 cru_set_soft_reset(SOFT_RST_CIF1, true);
1803 cru_set_soft_reset(SOFT_RST_CIF1, false);
1804 // pmu_set_idle_request(IDLE_REQ_VIO, false);
1808 write_cif_reg(pcdev->base,CIF_CIF_CTRL,AXI_BURST_16|MODE_ONEFRAME|DISABLE_CAPTURE); /* ddl@rock-chips.com : vip ahb burst 16 */
1809 write_cif_reg(pcdev->base,CIF_CIF_INTEN, 0x01|0x200); //capture complete interrupt enable
1811 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 */
1813 // read_cif_reg(pcdev->base,CIF_CIF_INTSTAT); /* clear vip interrupte single */
1814 write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF);
1815 if((read_cif_reg(pcdev->base,CIF_CIF_CTRL) & MODE_PINGPONG)
1816 ||(read_cif_reg(pcdev->base,CIF_CIF_CTRL) & MODE_LINELOOP)) {
1818 } else{ // this is one frame mode
1819 cif_crop = (rect->left+ (rect->top<<16));
1820 cif_fs = ((rect->width ) + (rect->height<<16));
1822 RKCAMERA_TR("%s..%d.. \n",__FUNCTION__,__LINE__);
1824 write_cif_reg(pcdev->base,CIF_CIF_CROP, cif_crop);
1825 write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, cif_fs);
1826 write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH, rect->width);
1827 write_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS, 0x00000003);
1830 write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL,0x10);
1831 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));
1835 static int rk_camera_get_formats(struct soc_camera_device *icd, unsigned int idx,
1836 struct soc_camera_format_xlate *xlate)
1838 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1839 struct device *dev = icd->dev.parent;
1840 int formats = 0, ret;
1841 enum v4l2_mbus_pixelcode code;
1842 const struct soc_mbus_pixelfmt *fmt;
1844 ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
1846 /* No more formats */
1849 fmt = soc_mbus_get_fmtdesc(code);
1851 dev_err(dev, "Invalid format code #%u: %d\n", idx, code);
1855 ret = rk_camera_try_bus_param(icd, fmt->bits_per_sample);
1860 case V4L2_MBUS_FMT_UYVY8_2X8:
1861 case V4L2_MBUS_FMT_YUYV8_2X8:
1862 case V4L2_MBUS_FMT_YVYU8_2X8:
1863 case V4L2_MBUS_FMT_VYUY8_2X8:
1864 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE != RK_CAM_SCALE_CROP_RGA)
1867 xlate->host_fmt = &rk_camera_formats[0];
1870 dev_dbg(dev, "Providing format %s using code %d\n",
1871 rk_camera_formats[0].name,code);
1876 xlate->host_fmt = &rk_camera_formats[1];
1879 dev_dbg(dev, "Providing format %s using code %d\n",
1880 rk_camera_formats[1].name,code);
1885 xlate->host_fmt = &rk_camera_formats[2];
1888 dev_dbg(dev, "Providing format %s using code %d\n",
1889 rk_camera_formats[2].name,code);
1894 xlate->host_fmt = &rk_camera_formats[3];
1897 dev_dbg(dev, "Providing format %s using code %d\n",
1898 rk_camera_formats[3].name,code);
1904 xlate->host_fmt = &rk_camera_formats[4];
1907 dev_dbg(dev, "Providing format %s using code %d\n",
1908 rk_camera_formats[4].name,code);
1912 xlate->host_fmt = &rk_camera_formats[5];
1915 dev_dbg(dev, "Providing format %s using code %d\n",
1916 rk_camera_formats[5].name,code);
1927 static void rk_camera_put_formats(struct soc_camera_device *icd)
1932 static int rk_camera_set_crop(struct soc_camera_device *icd,
1933 struct v4l2_crop *a)
1935 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1936 struct v4l2_mbus_framefmt mf;
1937 u32 fourcc = icd->current_fmt->host_fmt->fourcc;
1940 ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
1944 if ((mf.width < (a->c.left + a->c.width)) || (mf.height < (a->c.top + a->c.height))) {
1946 mf.width = a->c.left + a->c.width;
1947 mf.height = a->c.top + a->c.height;
1949 v4l_bound_align_image(&mf.width, RK_CAM_W_MIN, RK_CAM_W_MAX, 1,
1950 &mf.height, RK_CAM_H_MIN, RK_CAM_H_MAX, 0,
1951 fourcc == V4L2_PIX_FMT_NV16 ?4 : 0);
1953 ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
1958 rk_camera_setup_format(icd, fourcc, mf.code, &a->c);
1960 icd->user_width = mf.width;
1961 icd->user_height = mf.height;
1966 static int rk_camera_set_fmt(struct soc_camera_device *icd,
1967 struct v4l2_format *f)
1969 struct device *dev = icd->dev.parent;
1970 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1971 const struct soc_camera_format_xlate *xlate = NULL;
1972 struct soc_camera_host *ici =to_soc_camera_host(icd->dev.parent);
1973 struct rk_camera_dev *pcdev = ici->priv;
1974 struct v4l2_pix_format *pix = &f->fmt.pix;
1975 struct v4l2_mbus_framefmt mf;
1976 struct v4l2_rect rect;
1977 int ret,usr_w,usr_h;
1981 usr_h = pix->height;
1982 RKCAMERA_TR("%s enter width:%d height:%d\n",__FUNCTION__,usr_w,usr_h);
1983 xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
1985 dev_err(dev, "Format %x not found\n", pix->pixelformat);
1987 goto RK_CAMERA_SET_FMT_END;
1990 /* ddl@rock-chips.com: sensor init code transmit in here after open */
1991 if (pcdev->icd_init == 0) {
1992 v4l2_subdev_call(sd,core, init, 0);
1993 pcdev->icd_init = 1;
1995 stream_on = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
1996 if (stream_on & ENABLE_CAPTURE)
1997 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (stream_on & (~ENABLE_CAPTURE)));
1999 mf.width = pix->width;
2000 mf.height = pix->height;
2001 mf.field = pix->field;
2002 mf.colorspace = pix->colorspace;
2003 mf.code = xlate->code;
2004 ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
2005 if (mf.code != xlate->code)
2007 #ifdef CONFIG_VIDEO_RK29_WORK_IPP
2008 if ((mf.width != usr_w) || (mf.height != usr_h)) {
2010 if (unlikely((mf.width <16) || (mf.width > 8190) || (mf.height < 16) || (mf.height > 8190))) {
2011 RKCAMERA_TR("Senor and IPP both invalid source resolution(%dx%d)\n",mf.width,mf.height);
2013 goto RK_CAMERA_SET_FMT_END;
2015 if (unlikely((usr_w <16)||(usr_h < 16))) {
2016 RKCAMERA_TR("Senor and IPP both invalid destination resolution(%dx%d)\n",usr_w,usr_h);
2018 goto RK_CAMERA_SET_FMT_END;
2021 if((mf.width*10/mf.height) != (usr_w*10/usr_h)){
2022 ratio = ((mf.width*10/usr_w) >= (mf.height*10/usr_h))?(mf.height*10/usr_h):(mf.width*10/usr_w);
2023 pcdev->host_width = ratio*usr_w/10;
2024 pcdev->host_height = ratio*usr_h/10;
2025 //for ipp ,need 4 bit alligned.
2026 pcdev->host_width &= ~CROP_ALIGN_BYTES;
2027 pcdev->host_height &= ~CROP_ALIGN_BYTES;
2028 RKCAMERA_DG("ratio = %d ,host:%d*%d\n",ratio,pcdev->host_width,pcdev->host_height);
2030 else{ // needn't crop ,just scaled by ipp
2031 pcdev->host_width = mf.width;
2032 pcdev->host_height = mf.height;
2036 pcdev->host_width = usr_w;
2037 pcdev->host_height = usr_h;
2040 //according to crop and scale capability to change , here just cropt to user needed
2041 if (unlikely((mf.width <16) || (mf.width > 8190) || (mf.height < 16) || (mf.height > 8190))) {
2042 RKCAMERA_TR("Senor invalid source resolution(%dx%d)\n",mf.width,mf.height);
2044 goto RK_CAMERA_SET_FMT_END;
2046 if (unlikely((usr_w <16)||(usr_h < 16))) {
2047 RKCAMERA_TR("Senor invalid destination resolution(%dx%d)\n",usr_w,usr_h);
2049 goto RK_CAMERA_SET_FMT_END;
2051 pcdev->host_width = usr_w;
2052 pcdev->host_height = usr_h;
2056 RKCAMERA_DG("%s..%d.. host:%d*%d , sensor output:%d*%d,user demand:%d*%d\n",__FUNCTION__,__LINE__,
2057 pcdev->host_width,pcdev->host_height,mf.width,mf.height,usr_w,usr_h);
2058 rect.width = pcdev->host_width;
2059 rect.height = pcdev->host_height;
2060 rect.left = ((mf.width-pcdev->host_width )>>1)&(~0x01);
2061 rect.top = ((mf.height-pcdev->host_height)>>1)&(~0x01);
2062 pcdev->host_left = rect.left;
2063 pcdev->host_top = rect.top;
2065 down(&pcdev->zoominfo.sem);
2067 pcdev->zoominfo.a.c.left = 0;
2068 pcdev->zoominfo.a.c.top = 0;
2069 pcdev->zoominfo.a.c.width = pcdev->host_width*100/pcdev->zoominfo.zoom_rate;
2070 pcdev->zoominfo.a.c.width &= ~CROP_ALIGN_BYTES;
2071 pcdev->zoominfo.a.c.height = pcdev->host_height*100/pcdev->zoominfo.zoom_rate;
2072 pcdev->zoominfo.a.c.height &= ~CROP_ALIGN_BYTES;
2073 pcdev->zoominfo.vir_width = pcdev->zoominfo.a.c.width;
2074 pcdev->zoominfo.vir_height = pcdev->zoominfo.a.c.height;
2075 //recalculate the CIF width & height
2076 rect.width = pcdev->zoominfo.a.c.width ;
2077 rect.height = pcdev->zoominfo.a.c.height;
2078 rect.left = ((((pcdev->host_width - pcdev->zoominfo.a.c.width)>>1))+pcdev->host_left)&(~0x01);
2079 rect.top = ((((pcdev->host_height - pcdev->zoominfo.a.c.height)>>1))+pcdev->host_top)&(~0x01);
2081 pcdev->zoominfo.a.c.width = pcdev->host_width*100/pcdev->zoominfo.zoom_rate;
2082 pcdev->zoominfo.a.c.width &= ~CROP_ALIGN_BYTES;
2083 pcdev->zoominfo.a.c.height = pcdev->host_height*100/pcdev->zoominfo.zoom_rate;
2084 pcdev->zoominfo.a.c.height &= ~CROP_ALIGN_BYTES;
2085 //now digital zoom use ipp to do crop and scale
2086 if(pcdev->zoominfo.zoom_rate != 100){
2087 pcdev->zoominfo.a.c.left = ((pcdev->host_width - pcdev->zoominfo.a.c.width)>>1)&(~0x01);
2088 pcdev->zoominfo.a.c.top = ((pcdev->host_height - pcdev->zoominfo.a.c.height)>>1)&(~0x01);
2091 pcdev->zoominfo.a.c.left = 0;
2092 pcdev->zoominfo.a.c.top = 0;
2094 pcdev->zoominfo.vir_width = pcdev->host_width;
2095 pcdev->zoominfo.vir_height = pcdev->host_height;
2097 up(&pcdev->zoominfo.sem);
2099 /* ddl@rock-chips.com: IPP work limit check */
2100 if ((pcdev->zoominfo.a.c.width != usr_w) || (pcdev->zoominfo.a.c.height != usr_h)) {
2101 if (usr_w > 0x7f0) {
2102 if (((usr_w>>1)&0x3f) && (((usr_w>>1)&0x3f) <= 8)) {
2103 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));
2105 goto RK_CAMERA_SET_FMT_END;
2108 if ((usr_w&0x3f) && ((usr_w&0x3f) <= 8)) {
2109 RKCAMERA_TR("IPP Destination resolution(%dx%d, %d mod 64=%d is <= 8)",usr_w,usr_h, usr_w, (int)(usr_w&0x3f));
2111 goto RK_CAMERA_SET_FMT_END;
2115 RKCAMERA_DG("%s..%s icd width:%d user width:%d (zoom: %dx%d@(%d,%d)->%dx%d)\n",__FUNCTION__,xlate->host_fmt->name,
2116 rect.width, pix->width, pcdev->zoominfo.a.c.width,pcdev->zoominfo.a.c.height, pcdev->zoominfo.a.c.left,pcdev->zoominfo.a.c.top,
2117 pix->width, pix->height);
2118 rk_camera_setup_format(icd, pix->pixelformat, mf.code, &rect);
2120 if (CAM_IPPWORK_IS_EN()) {
2121 BUG_ON(pcdev->vipmem_phybase == 0);
2124 pix->height = usr_h;
2125 pix->field = mf.field;
2126 pix->colorspace = mf.colorspace;
2127 icd->current_fmt = xlate;
2128 pcdev->icd_width = mf.width;
2129 pcdev->icd_height = mf.height;
2132 RK_CAMERA_SET_FMT_END:
2133 if (stream_on & ENABLE_CAPTURE)
2134 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL) | ENABLE_CAPTURE));
2136 RKCAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
2139 static bool rk_camera_fmt_capturechk(struct v4l2_format *f)
2143 if ((f->fmt.pix.width == 1024) && (f->fmt.pix.height == 768)) {
2145 } else if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 1024)) {
2147 } else if ((f->fmt.pix.width == 1600) && (f->fmt.pix.height == 1200)) {
2149 } else if ((f->fmt.pix.width == 2048) && (f->fmt.pix.height == 1536)) {
2151 } else if ((f->fmt.pix.width == 2592) && (f->fmt.pix.height == 1944)) {
2153 } else if ((f->fmt.pix.width == 3264) && (f->fmt.pix.height == 2448)) {
2158 RKCAMERA_DG("%s %dx%d is capture format\n", __FUNCTION__, f->fmt.pix.width, f->fmt.pix.height);
2161 static int rk_camera_try_fmt(struct soc_camera_device *icd,
2162 struct v4l2_format *f)
2164 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2165 struct rk_camera_dev *pcdev = ici->priv;
2166 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
2167 const struct soc_camera_format_xlate *xlate;
2168 struct v4l2_pix_format *pix = &f->fmt.pix;
2169 __u32 pixfmt = pix->pixelformat;
2170 int ret,usr_w,usr_h,i;
2171 bool is_capture = rk_camera_fmt_capturechk(f);
2172 bool vipmem_is_overflow = false;
2173 struct v4l2_mbus_framefmt mf;
2174 int bytes_per_line_host;
2177 usr_h = pix->height;
2178 RKCAMERA_DG("%s enter width:%d height:%d\n",__FUNCTION__,usr_w,usr_h);
2180 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
2182 dev_err(icd->dev.parent, "Format (%c%c%c%c) not found\n", pixfmt & 0xFF, (pixfmt >> 8) & 0xFF,
2183 (pixfmt >> 16) & 0xFF, (pixfmt >> 24) & 0xFF);
2185 RKCAMERA_TR("%s(version:%c%c%c) support format:\n",rk_cam_driver_description,(RK_CAM_VERSION_CODE&0xff0000)>>16,
2186 (RK_CAM_VERSION_CODE&0xff00)>>8,(RK_CAM_VERSION_CODE&0xff));
2187 for (i = 0; i < icd->num_user_formats; i++)
2188 RKCAMERA_TR("(%c%c%c%c)-%s\n",
2189 icd->user_formats[i].host_fmt->fourcc & 0xFF, (icd->user_formats[i].host_fmt->fourcc >> 8) & 0xFF,
2190 (icd->user_formats[i].host_fmt->fourcc >> 16) & 0xFF, (icd->user_formats[i].host_fmt->fourcc >> 24) & 0xFF,
2191 icd->user_formats[i].host_fmt->name);
2192 goto RK_CAMERA_TRY_FMT_END;
2194 /* limit to rk29 hardware capabilities */
2195 v4l_bound_align_image(&pix->width, RK_CAM_W_MIN, RK_CAM_W_MAX, 1,
2196 &pix->height, RK_CAM_H_MIN, RK_CAM_H_MAX, 0,
2197 pixfmt == V4L2_PIX_FMT_NV16 ? 4 : 0);
2199 pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
2201 if (pix->bytesperline < 0)
2202 return pix->bytesperline;
2204 /* limit to sensor capabilities */
2205 memset(&mf,0x00,sizeof(struct v4l2_mbus_framefmt));
2206 mf.width = pix->width;
2207 mf.height = pix->height;
2208 mf.field = pix->field;
2209 mf.colorspace = pix->colorspace;
2210 mf.code = xlate->code;
2211 /* ddl@rock-chips.com : It is query max resolution only. */
2212 if ((usr_w == 10000) && (usr_h == 10000)) {
2213 mf.reserved[6] = 0xfefe5a5a;
2216 ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
2218 goto RK_CAMERA_TRY_FMT_END;
2219 RKCAMERA_DG("%s mf.width:%d mf.height:%d\n",__FUNCTION__,mf.width,mf.height);
2220 #ifdef CONFIG_VIDEO_RK29_WORK_IPP
2221 if ((mf.width != usr_w) || (mf.height != usr_h)) {
2222 bytes_per_line_host = soc_mbus_bytes_per_line(mf.width,icd->current_fmt->host_fmt);
2224 vipmem_is_overflow = (PAGE_ALIGN(bytes_per_line_host*mf.height) > pcdev->vipmem_size);
2226 /* Assume preview buffer minimum is 4 */
2227 vipmem_is_overflow = (PAGE_ALIGN(bytes_per_line_host*mf.height)*4 > pcdev->vipmem_size);
2229 if (vipmem_is_overflow == false) {
2231 pix->height = usr_h;
2233 RKCAMERA_TR("vipmem for IPP is overflow, This resolution(%dx%d -> %dx%d) is invalidate!\n",mf.width,mf.height,usr_w,usr_h);
2234 pix->width = mf.width;
2235 pix->height = mf.height;
2237 /* ddl@rock-chips.com: Invalidate these code, because sensor need interpolate */
2239 if ((mf.width < usr_w) || (mf.height < usr_h)) {
2240 if (((usr_w>>1) > mf.width) || ((usr_h>>1) > mf.height)) {
2241 RKCAMERA_TR("The aspect ratio(%dx%d/%dx%d) is bigger than 2 !\n",mf.width,mf.height,usr_w,usr_h);
2242 pix->width = mf.width;
2243 pix->height = mf.height;
2249 //need to change according to crop and scale capablicity
2250 if ((mf.width > usr_w) && (mf.height > usr_h)) {
2252 pix->height = usr_h;
2253 } else if ((mf.width < usr_w) && (mf.height < usr_h)) {
2254 RKCAMERA_TR("%dx%d can't scale up to %dx%d!\n",mf.width,mf.height,usr_w,usr_h);
2255 pix->width = mf.width;
2256 pix->height = mf.height;
2259 pix->colorspace = mf.colorspace;
2262 case V4L2_FIELD_ANY:
2263 case V4L2_FIELD_NONE:
2264 pix->field = V4L2_FIELD_NONE;
2267 /* TODO: support interlaced at least in pass-through mode */
2268 dev_err(icd->dev.parent, "Field type %d unsupported.\n",
2270 goto RK_CAMERA_TRY_FMT_END;
2273 RK_CAMERA_TRY_FMT_END:
2275 RKCAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
2279 static int rk_camera_reqbufs(struct soc_camera_device *icd,
2280 struct v4l2_requestbuffers *p)
2284 /* This is for locking debugging only. I removed spinlocks and now I
2285 * check whether .prepare is ever called on a linked buffer, or whether
2286 * a dma IRQ can occur for an in-work or unlinked buffer. Until now
2287 * it hadn't triggered */
2288 for (i = 0; i < p->count; i++) {
2289 struct rk_camera_buffer *buf = container_of(icd->vb_vidq.bufs[i],
2290 struct rk_camera_buffer, vb);
2292 INIT_LIST_HEAD(&buf->vb.queue);
2298 static unsigned int rk_camera_poll(struct file *file, poll_table *pt)
2300 struct soc_camera_device *icd = file->private_data;
2301 struct rk_camera_buffer *buf;
2303 buf = list_entry(icd->vb_vidq.stream.next, struct rk_camera_buffer,
2306 poll_wait(file, &buf->vb.done, pt);
2308 if (buf->vb.state == VIDEOBUF_DONE ||
2309 buf->vb.state == VIDEOBUF_ERROR)
2310 return POLLIN|POLLRDNORM;
2315 static int rk_camera_querycap(struct soc_camera_host *ici,
2316 struct v4l2_capability *cap)
2318 struct rk_camera_dev *pcdev = ici->priv;
2319 char orientation[5];
2322 strlcpy(cap->card, dev_name(pcdev->icd->pdev), sizeof(cap->card));
2323 memset(orientation,0x00,sizeof(orientation));
2324 for (i=0; i<RK_CAM_NUM;i++) {
2325 if ((pcdev->pdata->info[i].dev_name!=NULL) && (strcmp(dev_name(pcdev->icd->pdev), pcdev->pdata->info[i].dev_name) == 0)) {
2326 sprintf(orientation,"-%d",pcdev->pdata->info[i].orientation);
2330 if (orientation[0] != '-') {
2331 RKCAMERA_TR("%s: %s is not registered in rk29_camera_platform_data, orientation apply default value",__FUNCTION__,dev_name(pcdev->icd->pdev));
2332 if (strstr(dev_name(pcdev->icd->pdev),"front"))
2333 strcat(cap->card,"-270");
2335 strcat(cap->card,"-90");
2337 strcat(cap->card,orientation);
2339 cap->version = RK_CAM_VERSION_CODE;
2340 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
2344 static void rk_camera_store_register(struct rk_camera_dev *pcdev)
2346 pcdev->reginfo_suspend.cifCtrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
2347 pcdev->reginfo_suspend.cifCrop = read_cif_reg(pcdev->base,CIF_CIF_CROP);
2348 pcdev->reginfo_suspend.cifFs = read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE);
2349 pcdev->reginfo_suspend.cifIntEn = read_cif_reg(pcdev->base,CIF_CIF_INTEN);
2350 pcdev->reginfo_suspend.cifFmt= read_cif_reg(pcdev->base,CIF_CIF_FOR);
2351 pcdev->reginfo_suspend.cifVirWidth = read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH);
2352 pcdev->reginfo_suspend.cifScale= read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL);
2354 static void rk_camera_restore_register(struct rk_camera_dev *pcdev)
2356 write_cif_reg(pcdev->base,CIF_CIF_CTRL, pcdev->reginfo_suspend.cifCtrl&~ENABLE_CAPTURE);
2357 write_cif_reg(pcdev->base,CIF_CIF_INTEN, pcdev->reginfo_suspend.cifIntEn);
2358 write_cif_reg(pcdev->base,CIF_CIF_CROP, pcdev->reginfo_suspend.cifCrop);
2359 write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, pcdev->reginfo_suspend.cifFs);
2360 write_cif_reg(pcdev->base,CIF_CIF_FOR, pcdev->reginfo_suspend.cifFmt);
2361 write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH,pcdev->reginfo_suspend.cifVirWidth);
2362 write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL, pcdev->reginfo_suspend.cifScale);
2364 static int rk_camera_suspend(struct soc_camera_device *icd, pm_message_t state)
2366 struct soc_camera_host *ici =
2367 to_soc_camera_host(icd->dev.parent);
2368 struct rk_camera_dev *pcdev = ici->priv;
2369 struct v4l2_subdev *sd;
2372 mutex_lock(&camera_lock);
2373 if ((pcdev->icd == icd) && (icd->ops->suspend)) {
2374 rk_camera_s_stream(icd, 0);
2375 sd = soc_camera_to_subdev(icd);
2376 v4l2_subdev_call(sd, video, s_stream, 0);
2377 ret = icd->ops->suspend(icd, state);
2379 pcdev->reginfo_suspend.cifCtrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
2380 pcdev->reginfo_suspend.cifCrop = read_cif_reg(pcdev->base,CIF_CIF_CROP);
2381 pcdev->reginfo_suspend.cifFs = read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE);
2382 pcdev->reginfo_suspend.cifIntEn = read_cif_reg(pcdev->base,CIF_CIF_INTEN);
2383 pcdev->reginfo_suspend.cifFmt= read_cif_reg(pcdev->base,CIF_CIF_FOR);
2384 pcdev->reginfo_suspend.cifVirWidth = read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH);
2385 pcdev->reginfo_suspend.cifScale= read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL);
2387 pcdev->reginfo_suspend.Inval = Reg_Validate;
2388 rk_camera_deactivate(pcdev);
2390 RKCAMERA_DG("%s Enter Success...\n", __FUNCTION__);
2392 RKCAMERA_DG("%s icd has been deattach, don't need enter suspend\n", __FUNCTION__);
2394 mutex_unlock(&camera_lock);
2398 static int rk_camera_resume(struct soc_camera_device *icd)
2400 struct soc_camera_host *ici =
2401 to_soc_camera_host(icd->dev.parent);
2402 struct rk_camera_dev *pcdev = ici->priv;
2403 struct v4l2_subdev *sd;
2406 mutex_lock(&camera_lock);
2407 if ((pcdev->icd == icd) && (icd->ops->resume)) {
2408 if (pcdev->reginfo_suspend.Inval == Reg_Validate) {
2409 rk_camera_activate(pcdev, icd);
2410 write_cif_reg(pcdev->base,CIF_CIF_CTRL, pcdev->reginfo_suspend.cifCtrl&~ENABLE_CAPTURE);
2411 write_cif_reg(pcdev->base,CIF_CIF_INTEN, pcdev->reginfo_suspend.cifIntEn);
2412 write_cif_reg(pcdev->base,CIF_CIF_CROP, pcdev->reginfo_suspend.cifCrop);
2413 write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, pcdev->reginfo_suspend.cifFs);
2414 write_cif_reg(pcdev->base,CIF_CIF_FOR, pcdev->reginfo_suspend.cifFmt);
2415 write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH,pcdev->reginfo_suspend.cifVirWidth);
2416 write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL, pcdev->reginfo_suspend.cifScale);
2417 rk_videobuf_capture(pcdev->active,pcdev);
2418 rk_camera_s_stream(icd, 1);
2419 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
2421 RKCAMERA_TR("Resume fail, vip register recored is invalidate!!\n");
2422 goto rk_camera_resume_end;
2425 ret = icd->ops->resume(icd);
2426 sd = soc_camera_to_subdev(icd);
2427 v4l2_subdev_call(sd, video, s_stream, 1);
2429 RKCAMERA_DG("%s Enter success\n",__FUNCTION__);
2431 RKCAMERA_DG("%s icd has been deattach, don't need enter resume\n", __FUNCTION__);
2434 rk_camera_resume_end:
2435 mutex_unlock(&camera_lock);
2439 static void rk_camera_reinit_work(struct work_struct *work)
2441 struct v4l2_subdev *sd;
2442 struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
2443 struct rk_camera_dev *pcdev = camera_work->pcdev;
2444 struct soc_camera_link *tmp_soc_cam_link;
2446 unsigned long flags = 0;
2447 if(pcdev->icd == NULL)
2449 sd = soc_camera_to_subdev(pcdev->icd);
2450 tmp_soc_cam_link = to_soc_camera_link(pcdev->icd);
2453 RKCAMERA_TR("CIF_CIF_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CTRL));
2454 RKCAMERA_TR("CIF_CIF_INTEN = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTEN));
2455 RKCAMERA_TR("CIF_CIF_INTSTAT = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTSTAT));
2456 RKCAMERA_TR("CIF_CIF_FOR = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_FOR));
2457 RKCAMERA_TR("CIF_CIF_CROP = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CROP));
2458 RKCAMERA_TR("CIF_CIF_SET_SIZE = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE));
2459 RKCAMERA_TR("CIF_CIF_SCL_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL));
2460 RKCAMERA_TR("CRU_PCLK_REG30 = 0X%x\n",read_cru_reg(CRU_PCLK_REG30));
2461 RKCAMERA_TR("CIF_CIF_LAST_LINE = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_LINE));
2463 RKCAMERA_TR("CIF_CIF_LAST_PIX = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_PIX));
2464 RKCAMERA_TR("CIF_CIF_VIR_LINE_WIDTH = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH));
2465 RKCAMERA_TR("CIF_CIF_LINE_NUM_ADDR = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LINE_NUM_ADDR));
2466 RKCAMERA_TR("CIF_CIF_FRM0_ADDR_Y = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y));
2467 RKCAMERA_TR("CIF_CIF_FRM0_ADDR_UV = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV));
2468 RKCAMERA_TR("CIF_CIF_FRAME_STATUS = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS));
2471 pcdev->stop_cif = true;
2472 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL)&(~ENABLE_CAPTURE)));
2473 RKCAMERA_DG("the reinit times = %d\n",pcdev->reinit_times);
2474 if(pcdev->video_vq && pcdev->video_vq->irqlock){
2475 spin_lock_irqsave(pcdev->video_vq->irqlock, flags);
2476 for (index = 0; index < VIDEO_MAX_FRAME; index++) {
2477 if (NULL == pcdev->video_vq->bufs[index])
2480 if (pcdev->video_vq->bufs[index]->state == VIDEOBUF_QUEUED)
2482 list_del_init(&pcdev->video_vq->bufs[index]->queue);
2483 pcdev->video_vq->bufs[index]->state = VIDEOBUF_NEEDS_INIT;
2484 wake_up_all(&pcdev->video_vq->bufs[index]->done);
2485 printk("wake up video buffer index = %d !!!\n",index);
2488 spin_unlock_irqrestore(pcdev->video_vq->irqlock, flags);
2490 RKCAMERA_TR("video queue has somthing wrong !!\n");
2493 RKCAMERA_TR("the %d reinit times ,wake up video buffers!\n ",pcdev->reinit_times);
2495 static enum hrtimer_restart rk_camera_fps_func(struct hrtimer *timer)
2497 struct rk_camera_frmivalenum *fival_nxt=NULL,*fival_pre=NULL, *fival_rec=NULL;
2498 struct rk_camera_timer *fps_timer = container_of(timer, struct rk_camera_timer, timer);
2499 struct rk_camera_dev *pcdev = fps_timer->pcdev;
2501 // static unsigned int last_fps = 0;
2502 struct soc_camera_link *tmp_soc_cam_link;
2503 tmp_soc_cam_link = to_soc_camera_link(pcdev->icd);
2505 RKCAMERA_DG("rk_camera_fps_func fps:0x%x\n",pcdev->fps);
2506 if ((pcdev->fps < 1) || (pcdev->last_fps == pcdev->fps)) {
2507 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);
2508 pcdev->camera_reinit_work.pcdev = pcdev;
2509 //INIT_WORK(&(pcdev->camera_reinit_work.work), rk_camera_reinit_work);
2510 pcdev->reinit_times++;
2511 queue_work(pcdev->camera_wq,&(pcdev->camera_reinit_work.work));
2512 } else if(!pcdev->timer_get_fps) {
2513 pcdev->timer_get_fps = true;
2514 for (i=0; i<2; i++) {
2515 if (pcdev->icd == pcdev->icd_frmival[i].icd) {
2516 fival_nxt = pcdev->icd_frmival[i].fival_list;
2521 fival_pre = fival_nxt;
2522 while (fival_nxt != NULL) {
2524 RKCAMERA_DG("%s %c%c%c%c %dx%d framerate : %d/%d\n", dev_name(&pcdev->icd->dev),
2525 fival_nxt->fival.pixel_format & 0xFF, (fival_nxt->fival.pixel_format >> 8) & 0xFF,
2526 (fival_nxt->fival.pixel_format >> 16) & 0xFF, (fival_nxt->fival.pixel_format >> 24),
2527 fival_nxt->fival.width, fival_nxt->fival.height, fival_nxt->fival.discrete.denominator,
2528 fival_nxt->fival.discrete.numerator);
2530 if (((fival_nxt->fival.pixel_format == pcdev->pixfmt)
2531 && (fival_nxt->fival.height == pcdev->icd->user_height)
2532 && (fival_nxt->fival.width == pcdev->icd->user_width))
2533 || (fival_nxt->fival.discrete.denominator == 0)) {
2535 if (fival_nxt->fival.discrete.denominator == 0) {
2536 fival_nxt->fival.index = 0;
2537 fival_nxt->fival.width = pcdev->icd->user_width;
2538 fival_nxt->fival.height= pcdev->icd->user_height;
2539 fival_nxt->fival.pixel_format = pcdev->pixfmt;
2540 fival_nxt->fival.discrete.denominator = pcdev->frame_interval;
2541 fival_nxt->fival.reserved[1] = (pcdev->icd_width<<16)
2542 |(pcdev->icd_height);
2543 fival_nxt->fival.discrete.numerator = 1000000;
2544 fival_nxt->fival.type = V4L2_FRMIVAL_TYPE_DISCRETE;
2547 fival_rec = fival_nxt;
2549 fival_pre = fival_nxt;
2550 fival_nxt = fival_nxt->nxt;
2553 if ((rec_flag == 0) && fival_pre) {
2554 fival_pre->nxt = kzalloc(sizeof(struct rk_camera_frmivalenum), GFP_ATOMIC);
2555 if (fival_pre->nxt != NULL) {
2556 fival_pre->nxt->fival.index = fival_pre->fival.index++;
2557 fival_pre->nxt->fival.width = pcdev->icd->user_width;
2558 fival_pre->nxt->fival.height= pcdev->icd->user_height;
2559 fival_pre->nxt->fival.pixel_format = pcdev->pixfmt;
2561 fival_pre->nxt->fival.discrete.denominator = pcdev->frame_interval;
2562 fival_pre->nxt->fival.reserved[1] = (pcdev->icd_width<<16)
2563 |(pcdev->icd_height);
2564 fival_pre->nxt->fival.discrete.numerator = 1000000;
2565 fival_pre->nxt->fival.type = V4L2_FRMIVAL_TYPE_DISCRETE;
2567 fival_rec = fival_pre->nxt;
2571 pcdev->last_fps = pcdev->fps ;
2572 pcdev->fps_timer.timer.node.expires= ktime_add_us(pcdev->fps_timer.timer.node.expires, ktime_to_us(ktime_set(3, 0)));
2573 pcdev->fps_timer.timer._softexpires= ktime_add_us(pcdev->fps_timer.timer._softexpires, ktime_to_us(ktime_set(3, 0)));
2574 //return HRTIMER_NORESTART;
2575 if(pcdev->reinit_times >=2)
2576 return HRTIMER_NORESTART;
2578 return HRTIMER_RESTART;
2580 static int rk_camera_s_stream(struct soc_camera_device *icd, int enable)
2582 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2583 struct rk_camera_dev *pcdev = ici->priv;
2586 unsigned long flags;
2588 WARN_ON(pcdev->icd != icd);
2590 cif_ctrl_val = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
2593 pcdev->last_fps = 0;
2594 pcdev->frame_interval = 0;
2595 hrtimer_cancel(&(pcdev->fps_timer.timer));
2596 pcdev->fps_timer.pcdev = pcdev;
2597 pcdev->timer_get_fps = false;
2598 pcdev->reinit_times = 0;
2599 pcdev->stop_cif = false;
2600 // hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL);
2601 cif_ctrl_val |= ENABLE_CAPTURE;
2602 write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val);
2603 hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL);
2604 pcdev->fps_timer.istarted = true;
2606 //cancel timer before stop cif
2607 ret = hrtimer_cancel(&pcdev->fps_timer.timer);
2608 pcdev->fps_timer.istarted = false;
2609 flush_work(&(pcdev->camera_reinit_work.work));
2611 cif_ctrl_val &= ~ENABLE_CAPTURE;
2612 spin_lock_irqsave(&pcdev->lock, flags);
2613 write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val);
2614 pcdev->stop_cif = true;
2615 spin_unlock_irqrestore(&pcdev->lock, flags);
2616 flush_workqueue((pcdev->camera_wq));
2617 RKCAMERA_DG("STREAM_OFF cancel timer and flush work:0x%x \n", ret);
2619 //must be reinit,or will be somthing wrong in irq process.
2620 if(enable == false){
2621 pcdev->active = NULL;
2622 INIT_LIST_HEAD(&pcdev->capture);
2624 RKCAMERA_DG("%s.. enable : 0x%x , CIF_CIF_CTRL = 0x%x\n", __FUNCTION__, enable,read_cif_reg(pcdev->base,CIF_CIF_CTRL));
2627 int rk_camera_enum_frameintervals(struct soc_camera_device *icd, struct v4l2_frmivalenum *fival)
2629 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2630 struct rk_camera_dev *pcdev = ici->priv;
2631 struct rk_camera_frmivalenum *fival_list = NULL;
2632 struct v4l2_frmivalenum *fival_head = NULL;
2633 int i,ret = 0,index;
2635 index = fival->index & 0x00ffffff;
2636 if ((fival->index & 0xff000000) == 0xff000000) { /* ddl@rock-chips.com: detect framerate */
2637 for (i=0; i<2; i++) {
2638 if (pcdev->icd_frmival[i].icd == icd) {
2639 fival_list = pcdev->icd_frmival[i].fival_list;
2643 if (fival_list != NULL) {
2645 while (fival_list != NULL) {
2646 if ((fival->pixel_format == fival_list->fival.pixel_format)
2647 && (fival->height == fival_list->fival.height)
2648 && (fival->width == fival_list->fival.width)) {
2653 fival_list = fival_list->nxt;
2656 if ((i==index) && (fival_list != NULL)) {
2657 memcpy(fival, &fival_list->fival, sizeof(struct v4l2_frmivalenum));
2662 RKCAMERA_TR("%s: fival_list is NULL\n",__FUNCTION__);
2667 for (i=0; i<RK_CAM_NUM; i++) {
2668 if (pcdev->pdata->info[i].dev_name && (strcmp(dev_name(pcdev->icd->pdev),pcdev->pdata->info[i].dev_name) == 0)) {
2669 fival_head = pcdev->pdata->info[i].fival;
2673 if (fival_head == NULL) {
2674 RKCAMERA_TR("%s: %s is not registered in rk_camera_platform_data!!",__FUNCTION__,dev_name(pcdev->icd->pdev));
2676 goto rk_camera_enum_frameintervals_end;
2680 while (fival_head->width && fival_head->height) {
2681 if ((fival->pixel_format == fival_head->pixel_format)
2682 && (fival->height == fival_head->height)
2683 && (fival->width == fival_head->width)) {
2692 if ((i == index) && (fival->height == fival_head->height) && (fival->width == fival_head->width)) {
2693 memcpy(fival, fival_head, sizeof(struct v4l2_frmivalenum));
2694 RKCAMERA_DG("%s %dx%d@%c%c%c%c framerate : %d/%d\n", dev_name(pcdev->icd->pdev),
2695 fival->width, fival->height,
2696 fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
2697 (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
2698 fival->discrete.denominator,fival->discrete.numerator);
2701 RKCAMERA_TR("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(pcdev->icd->pdev),
2702 fival->width,fival->height,
2703 fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
2704 (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
2707 RKCAMERA_DG("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(pcdev->icd->pdev),
2708 fival->width,fival->height,
2709 fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
2710 (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
2715 rk_camera_enum_frameintervals_end:
2719 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
2720 static int rk_camera_set_digit_zoom(struct soc_camera_device *icd,
2721 const struct v4l2_queryctrl *qctrl, int zoom_rate)
2724 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2725 struct rk_camera_dev *pcdev = ici->priv;
2727 unsigned long tmp_cifctrl;
2730 //change the crop and scale parameters
2733 a.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2734 //a.c.width = pcdev->host_width*100/zoom_rate;
2735 a.c.width = pcdev->host_width*100/zoom_rate;
2736 a.c.width &= ~CROP_ALIGN_BYTES;
2737 a.c.height = pcdev->host_height*100/zoom_rate;
2738 a.c.height &= ~CROP_ALIGN_BYTES;
2739 a.c.left = (((pcdev->host_width - a.c.width)>>1)+pcdev->host_left)&(~0x01);
2740 a.c.top = (((pcdev->host_height - a.c.height)>>1)+pcdev->host_top)&(~0x01);
2741 pcdev->stop_cif = true;
2742 tmp_cifctrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
2743 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl & ~ENABLE_CAPTURE));
2744 hrtimer_cancel(&(pcdev->fps_timer.timer));
2745 flush_workqueue((pcdev->camera_wq));
2746 down(&pcdev->zoominfo.sem);
2747 pcdev->zoominfo.a.c.left = 0;
2748 pcdev->zoominfo.a.c.top = 0;
2749 pcdev->zoominfo.a.c.width = a.c.width;
2750 pcdev->zoominfo.a.c.height = a.c.height;
2751 pcdev->zoominfo.vir_width = pcdev->zoominfo.a.c.width;
2752 pcdev->zoominfo.vir_height = pcdev->zoominfo.a.c.height;
2753 pcdev->frame_inval = 1;
2754 write_cif_reg(pcdev->base,CIF_CIF_CROP, (a.c.left + (a.c.top<<16)));
2755 write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, ((a.c.width ) + (a.c.height<<16)));
2756 write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH, a.c.width);
2757 write_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS, 0x00000002);//frame1 has been ready to receive data,frame 2 is not used
2759 rk_videobuf_capture(pcdev->active,pcdev);
2760 if(tmp_cifctrl & ENABLE_CAPTURE)
2761 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl | ENABLE_CAPTURE));
2762 up(&pcdev->zoominfo.sem);
2763 pcdev->stop_cif = false;
2764 hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL);
2765 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 );
2767 a.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2768 a.c.width = pcdev->host_width*100/zoom_rate;
2769 a.c.width &= ~CROP_ALIGN_BYTES;
2770 a.c.height = pcdev->host_height*100/zoom_rate;
2771 a.c.height &= ~CROP_ALIGN_BYTES;
2772 a.c.left = (pcdev->host_width - a.c.width)>>1;
2773 a.c.top = (pcdev->host_height - a.c.height)>>1;
2774 down(&pcdev->zoominfo.sem);
2775 pcdev->zoominfo.a.c.height = a.c.height;
2776 pcdev->zoominfo.a.c.width = a.c.width;
2777 pcdev->zoominfo.a.c.top = a.c.top;
2778 pcdev->zoominfo.a.c.left = a.c.left;
2779 pcdev->zoominfo.vir_width = pcdev->host_width;
2780 pcdev->zoominfo.vir_height= pcdev->host_height;
2781 up(&pcdev->zoominfo.sem);
2782 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 );
2788 static inline struct v4l2_queryctrl const *rk_camera_soc_camera_find_qctrl(
2789 struct soc_camera_host_ops *ops, int id)
2793 for (i = 0; i < ops->num_controls; i++)
2794 if (ops->controls[i].id == id)
2795 return &ops->controls[i];
2801 static int rk_camera_set_ctrl(struct soc_camera_device *icd,
2802 struct v4l2_control *sctrl)
2805 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2806 const struct v4l2_queryctrl *qctrl;
2807 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
2808 struct rk_camera_dev *pcdev = ici->priv;
2812 qctrl = rk_camera_soc_camera_find_qctrl(ici->ops, sctrl->id);
2815 goto rk_camera_set_ctrl_end;
2820 #ifdef CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON
2821 case V4L2_CID_ZOOM_ABSOLUTE:
2823 if ((sctrl->value < qctrl->minimum) || (sctrl->value > qctrl->maximum)){
2825 goto rk_camera_set_ctrl_end;
2827 ret = rk_camera_set_digit_zoom(icd, qctrl, sctrl->value);
2829 pcdev->zoominfo.zoom_rate = sctrl->value;
2831 goto rk_camera_set_ctrl_end;
2840 rk_camera_set_ctrl_end:
2844 static struct soc_camera_host_ops rk_soc_camera_host_ops =
2846 .owner = THIS_MODULE,
2847 .add = rk_camera_add_device,
2848 .remove = rk_camera_remove_device,
2849 .suspend = rk_camera_suspend,
2850 .resume = rk_camera_resume,
2851 .enum_frameinervals = rk_camera_enum_frameintervals,
2852 .set_crop = rk_camera_set_crop,
2853 .get_formats = rk_camera_get_formats,
2854 .put_formats = rk_camera_put_formats,
2855 .set_fmt = rk_camera_set_fmt,
2856 .try_fmt = rk_camera_try_fmt,
2857 .init_videobuf = rk_camera_init_videobuf,
2858 .reqbufs = rk_camera_reqbufs,
2859 .poll = rk_camera_poll,
2860 .querycap = rk_camera_querycap,
2861 .set_bus_param = rk_camera_set_bus_param,
2862 .s_stream = rk_camera_s_stream, /* ddl@rock-chips.com : Add stream control for host */
2863 .set_ctrl = rk_camera_set_ctrl,
2864 .controls = rk_camera_controls,
2865 .num_controls = ARRAY_SIZE(rk_camera_controls)
2868 static void rk_camera_cif_iomux(int cif_index)
2870 #if defined(CONFIG_ARCH_RK3066B)
2873 rk30_mux_api_set(GPIO3B3_CIFCLKOUT_NAME, GPIO3B_CIFCLKOUT);
2874 write_grf_reg(GRF_IO_CON3, (CIF_DRIVER_STRENGTH_MASK|CIF_DRIVER_STRENGTH_8MA));
2875 write_grf_reg(GRF_IO_CON4, (CIF_CLKOUT_AMP_MASK|CIF_CLKOUT_AMP_1V8));
2876 #if (CONFIG_CAMERA_INPUT_FMT_SUPPORT & (RK_CAM_INPUT_FMT_RAW10|RK_CAM_INPUT_FMT_RAW12))
2877 rk30_mux_api_set(GPIO3B4_CIFDATA0_HSADCDATA8_NAME, GPIO3B_CIFDATA0);
2878 rk30_mux_api_set(GPIO3B5_CIFDATA1_HSADCDATA9_NAME, GPIO3B_CIFDATA1);
2880 #if (CONFIG_CAMERA_INPUT_FMT_SUPPORT & RK_CAM_INPUT_FMT_RAW12)
2881 rk30_mux_api_set(GPIO3B6_CIFDATA10_I2C3SDA_NAME, GPIO3B_CIFDATA10);
2882 rk30_mux_api_set(GPIO3B7_CIFDATA11_I2C3SCL_NAME, GPIO3B_CIFDATA11);
2883 RKCAMERA_TR("%s(%d): WARNING: Cif 0 is configurated that support RAW 12bit, so I2C3 is invalidate!!\n",__FUNCTION__,__LINE__);
2888 RKCAMERA_TR("%s(%d): Cif index(%d) is invalidate!!!\n",__FUNCTION__,__LINE__, cif_index);
2891 #elif defined(CONFIG_ARCH_RK30)
2894 rk30_mux_api_set(GPIO1B3_CIF0CLKOUT_NAME, GPIO1B_CIF0_CLKOUT);
2895 #if (CONFIG_CAMERA_INPUT_FMT_SUPPORT & (RK_CAM_INPUT_FMT_RAW10|RK_CAM_INPUT_FMT_RAW12))
2896 rk30_mux_api_set(GPIO1B4_CIF0DATA0_NAME, GPIO1B_CIF0_DATA0);
2897 rk30_mux_api_set(GPIO1B5_CIF0DATA1_NAME, GPIO1B_CIF0_DATA1);
2899 #if (CONFIG_CAMERA_INPUT_FMT_SUPPORT & RK_CAM_INPUT_FMT_RAW12)
2900 rk30_mux_api_set(GPIO1B6_CIFDATA10_NAME, GPIO1B_CIF_DATA10);
2901 rk30_mux_api_set(GPIO1B7_CIFDATA11_NAME, GPIO1B_CIF_DATA11);
2905 rk30_mux_api_set(GPIO1C0_CIF1DATA2_RMIICLKOUT_RMIICLKIN_NAME,GPIO1C_CIF1_DATA2);
2906 rk30_mux_api_set(GPIO1C1_CIFDATA3_RMIITXEN_NAME,GPIO1C_CIF_DATA3);
2907 rk30_mux_api_set(GPIO1C2_CIF1DATA4_RMIITXD1_NAME,GPIO1C_CIF1_DATA4);
2908 rk30_mux_api_set(GPIO1C3_CIFDATA5_RMIITXD0_NAME,GPIO1C_CIF_DATA5);
2909 rk30_mux_api_set(GPIO1C4_CIFDATA6_RMIIRXERR_NAME,GPIO1C_CIF_DATA6);
2910 rk30_mux_api_set(GPIO1C5_CIFDATA7_RMIICRSDVALID_NAME,GPIO1C_CIF_DATA7);
2911 rk30_mux_api_set(GPIO1C6_CIFDATA8_RMIIRXD1_NAME,GPIO1C_CIF_DATA8);
2912 rk30_mux_api_set(GPIO1C7_CIFDATA9_RMIIRXD0_NAME,GPIO1C_CIF_DATA9);
2914 rk30_mux_api_set(GPIO1D0_CIF1VSYNC_MIIMD_NAME,GPIO1D_CIF1_VSYNC);
2915 rk30_mux_api_set(GPIO1D1_CIF1HREF_MIIMDCLK_NAME,GPIO1D_CIF1_HREF);
2916 rk30_mux_api_set(GPIO1D2_CIF1CLKIN_NAME,GPIO1D_CIF1_CLKIN);
2917 rk30_mux_api_set(GPIO1D3_CIF1DATA0_NAME,GPIO1D_CIF1_DATA0);
2918 rk30_mux_api_set(GPIO1D4_CIF1DATA1_NAME,GPIO1D_CIF1_DATA1);
2919 rk30_mux_api_set(GPIO1D5_CIF1DATA10_NAME,GPIO1D_CIF1_DATA10);
2920 rk30_mux_api_set(GPIO1D6_CIF1DATA11_NAME,GPIO1D_CIF1_DATA11);
2921 rk30_mux_api_set(GPIO1D7_CIF1CLKOUT_NAME,GPIO1D_CIF1_CLKOUT);
2924 RKCAMERA_TR("%s(%d): Cif index(%d) is invalidate!!!\n",__FUNCTION__,__LINE__, cif_index);
2931 static int rk_camera_probe(struct platform_device *pdev)
2933 struct rk_camera_dev *pcdev;
2934 struct resource *res;
2935 struct rk_camera_frmivalenum *fival_list,*fival_nxt;
2936 struct rk29camera_mem_res *meminfo_ptr,*meminfo_ptrr;
2940 printk("%s version: v%d.%d.%d Zoom by %s\n",RK29_CAM_DRV_NAME,(RK_CAM_VERSION_CODE&0xff0000)>>16,
2941 (RK_CAM_VERSION_CODE&0xff00)>>8,RK_CAM_VERSION_CODE&0xff,CAMERA_SCALE_CROP_MACHINE);
2943 if ((pdev->id == RK_CAM_PLATFORM_DEV_ID_1) && (RK_SUPPORT_CIF1 == 0)) {
2944 RKCAMERA_TR("%s(%d): This chip is not support CIF1!!\n",__FUNCTION__,__LINE__);
2948 if ((pdev->id == RK_CAM_PLATFORM_DEV_ID_0) && (RK_SUPPORT_CIF0 == 0)) {
2949 RKCAMERA_TR("%s(%d): This chip is not support CIF0!!\n",__FUNCTION__,__LINE__);
2953 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2954 irq = platform_get_irq(pdev, 0);
2955 if (!res || irq < 0) {
2959 pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL);
2961 dev_err(&pdev->dev, "Could not allocate pcdev\n");
2966 pcdev->zoominfo.zoom_rate = 100;
2967 pcdev->hostid = pdev->id;
2968 /*config output clk*/ // must modify start
2970 pcdev->pd_cif = clk_get(NULL, "pd_cif0");
2971 pcdev->aclk_cif = clk_get(NULL, "aclk_cif0");
2972 pcdev->hclk_cif = clk_get(NULL, "hclk_cif0");
2973 pcdev->cif_clk_in = clk_get(NULL, "cif0_in");
2974 pcdev->cif_clk_out = clk_get(NULL, "cif0_out");
2975 rk_camera_cif_iomux(0);
2977 pcdev->pd_cif = clk_get(NULL, "pd_cif1");
2978 pcdev->aclk_cif = clk_get(NULL, "aclk_cif1");
2979 pcdev->hclk_cif = clk_get(NULL, "hclk_cif1");
2980 pcdev->cif_clk_in = clk_get(NULL, "cif1_in");
2981 pcdev->cif_clk_out = clk_get(NULL, "cif1_out");
2983 rk_camera_cif_iomux(1);
2986 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)){
2987 RKCAMERA_TR(KERN_ERR "%s(%d): failed to get cif clock source\n",__FUNCTION__,__LINE__);
2989 goto exit_reqmem_vip;
2992 dev_set_drvdata(&pdev->dev, pcdev);
2994 pcdev->pdata = pdev->dev.platform_data; /* ddl@rock-chips.com : Request IO in init function */
2996 if (pcdev->pdata && pcdev->pdata->io_init) {
2997 pcdev->pdata->io_init();
2999 #ifdef CONFIG_VIDEO_RK29_WORK_IPP
3000 meminfo_ptr = IS_CIF0()? (&pcdev->pdata->meminfo):(&pcdev->pdata->meminfo_cif1);
3001 meminfo_ptrr = IS_CIF0()? (&pcdev->pdata->meminfo_cif1):(&pcdev->pdata->meminfo);
3003 if (meminfo_ptr->vbase == NULL) {
3005 if ((meminfo_ptr->start == meminfo_ptrr->start)
3006 && (meminfo_ptr->size == meminfo_ptrr->size) && meminfo_ptrr->vbase) {
3008 meminfo_ptr->vbase = meminfo_ptrr->vbase;
3011 if (!request_mem_region(meminfo_ptr->start,meminfo_ptr->size,"rk29_vipmem")) {
3013 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);
3014 goto exit_ioremap_vipmem;
3016 meminfo_ptr->vbase = pcdev->vipmem_virbase = ioremap_cached(meminfo_ptr->start,meminfo_ptr->size);
3017 if (pcdev->vipmem_virbase == NULL) {
3018 RKCAMERA_TR("%s(%d): ioremap of CIF internal memory(Ex:IPP process/raw process) failed\n",__FUNCTION__,__LINE__);
3020 goto exit_ioremap_vipmem;
3025 pcdev->vipmem_phybase = meminfo_ptr->start;
3026 pcdev->vipmem_size = meminfo_ptr->size;
3027 pcdev->vipmem_virbase = meminfo_ptr->vbase;
3029 INIT_LIST_HEAD(&pcdev->capture);
3030 INIT_LIST_HEAD(&pcdev->camera_work_queue);
3031 spin_lock_init(&pcdev->lock);
3032 spin_lock_init(&pcdev->camera_work_lock);
3033 sema_init(&pcdev->zoominfo.sem,1);
3036 * Request the regions.
3039 if (!request_mem_region(res->start, res->end - res->start + 1,
3040 RK29_CAM_DRV_NAME)) {
3042 goto exit_reqmem_vip;
3044 pcdev->base = ioremap(res->start, res->end - res->start + 1);
3045 if (pcdev->base == NULL) {
3046 dev_err(pcdev->dev, "ioremap() of registers failed\n");
3048 goto exit_ioremap_vip;
3053 pcdev->dev = &pdev->dev;
3055 /* config buffer address */
3058 err = request_irq(pcdev->irq, rk_camera_irq, 0, RK29_CAM_DRV_NAME,
3061 dev_err(pcdev->dev, "Camera interrupt register failed \n");
3066 //#ifdef CONFIG_VIDEO_RK29_WORK_IPP
3068 pcdev->camera_wq = create_workqueue("rk_cam_wkque_cif0");
3070 pcdev->camera_wq = create_workqueue("rk_cam_wkque_cif1");
3072 if (pcdev->camera_wq == NULL)
3076 pcdev->camera_reinit_work.pcdev = pcdev;
3077 INIT_WORK(&(pcdev->camera_reinit_work.work), rk_camera_reinit_work);
3079 for (i=0; i<2; i++) {
3080 pcdev->icd_frmival[i].icd = NULL;
3081 pcdev->icd_frmival[i].fival_list = kzalloc(sizeof(struct rk_camera_frmivalenum),GFP_KERNEL);
3084 pcdev->soc_host.drv_name = RK29_CAM_DRV_NAME;
3085 pcdev->soc_host.ops = &rk_soc_camera_host_ops;
3086 pcdev->soc_host.priv = pcdev;
3087 pcdev->soc_host.v4l2_dev.dev = &pdev->dev;
3088 pcdev->soc_host.nr = pdev->id;
3090 err = soc_camera_host_register(&pcdev->soc_host);
3093 pcdev->fps_timer.pcdev = pcdev;
3094 hrtimer_init(&(pcdev->fps_timer.timer), CLOCK_MONOTONIC, HRTIMER_MODE_REL);
3095 pcdev->fps_timer.timer.function = rk_camera_fps_func;
3096 pcdev->icd_cb.sensor_cb = NULL;
3098 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP)
3099 pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_ipp;
3100 #elif (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_ARM)
3101 pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_arm;
3102 #elif (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_RGA)
3103 pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_rga;
3104 #elif(CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_PP)
3105 pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_pp;
3107 RKCAMERA_DG("%s(%d) Exit \n",__FUNCTION__,__LINE__);
3112 for (i=0; i<2; i++) {
3113 fival_list = pcdev->icd_frmival[i].fival_list;
3114 fival_nxt = fival_list;
3115 while(fival_nxt != NULL) {
3116 fival_nxt = fival_list->nxt;
3118 fival_list = fival_nxt;
3122 free_irq(pcdev->irq, pcdev);
3123 if (pcdev->camera_wq) {
3124 destroy_workqueue(pcdev->camera_wq);
3125 pcdev->camera_wq = NULL;
3128 iounmap(pcdev->base);
3130 release_mem_region(res->start, res->end - res->start + 1);
3131 exit_ioremap_vipmem:
3132 if (pcdev->vipmem_virbase)
3133 iounmap(pcdev->vipmem_virbase);
3134 release_mem_region(pcdev->vipmem_phybase,pcdev->vipmem_size);
3137 pcdev->aclk_cif = NULL;
3139 pcdev->hclk_cif = NULL;
3140 if(pcdev->cif_clk_in)
3141 pcdev->cif_clk_in = NULL;
3142 if(pcdev->cif_clk_out)
3143 pcdev->cif_clk_out = NULL;
3152 static int __devexit rk_camera_remove(struct platform_device *pdev)
3154 struct rk_camera_dev *pcdev = platform_get_drvdata(pdev);
3155 struct resource *res;
3156 struct rk_camera_frmivalenum *fival_list,*fival_nxt;
3157 struct rk29camera_mem_res *meminfo_ptr,*meminfo_ptrr;
3160 free_irq(pcdev->irq, pcdev);
3162 if (pcdev->camera_wq) {
3163 destroy_workqueue(pcdev->camera_wq);
3164 pcdev->camera_wq = NULL;
3167 for (i=0; i<2; i++) {
3168 fival_list = pcdev->icd_frmival[i].fival_list;
3169 fival_nxt = fival_list;
3170 while(fival_nxt != NULL) {
3171 fival_nxt = fival_list->nxt;
3173 fival_list = fival_nxt;
3177 soc_camera_host_unregister(&pcdev->soc_host);
3179 meminfo_ptr = IS_CIF0()? (&pcdev->pdata->meminfo):(&pcdev->pdata->meminfo_cif1);
3180 meminfo_ptrr = IS_CIF0()? (&pcdev->pdata->meminfo_cif1):(&pcdev->pdata->meminfo);
3181 if (meminfo_ptr->vbase) {
3182 if (meminfo_ptr->vbase == meminfo_ptrr->vbase) {
3183 meminfo_ptr->vbase = NULL;
3185 iounmap((void __iomem*)pcdev->vipmem_phybase);
3186 release_mem_region(pcdev->vipmem_phybase, pcdev->vipmem_size);
3187 meminfo_ptr->vbase = NULL;
3192 iounmap((void __iomem*)pcdev->base);
3193 release_mem_region(res->start, res->end - res->start + 1);
3194 if (pcdev->pdata && pcdev->pdata->io_deinit) { /* ddl@rock-chips.com : Free IO in deinit function */
3195 pcdev->pdata->io_deinit(0);
3196 pcdev->pdata->io_deinit(1);
3201 dev_info(&pdev->dev, "RK28 Camera driver unloaded\n");
3206 static struct platform_driver rk_camera_driver =
3209 .name = RK29_CAM_DRV_NAME,
3211 .probe = rk_camera_probe,
3212 .remove = __devexit_p(rk_camera_remove),
3215 static int rk_camera_init_async(void *unused)
3217 platform_driver_register(&rk_camera_driver);
3221 static int __devinit rk_camera_init(void)
3223 RKCAMERA_DG("%s..%s..%d \n",__FUNCTION__,__FILE__,__LINE__);
3224 kthread_run(rk_camera_init_async, NULL, "rk_camera_init");
3228 static void __exit rk_camera_exit(void)
3230 platform_driver_unregister(&rk_camera_driver);
3233 device_initcall_sync(rk_camera_init);
3234 module_exit(rk_camera_exit);
3236 MODULE_DESCRIPTION("RKSoc Camera Host driver");
3237 MODULE_AUTHOR("ddl <ddl@rock-chips>");
3238 MODULE_LICENSE("GPL");