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) ||\
13 defined(CONFIG_ARCH_RK30) ||\
14 defined(CONFIG_ARCH_RK3188) ||\
15 defined(CONFIG_ARCH_RK3026))
17 #include <linux/init.h>
18 #include <linux/module.h>
20 #include <linux/delay.h>
21 #include <linux/slab.h>
22 #include <linux/dma-mapping.h>
23 #include <linux/errno.h>
25 #include <linux/interrupt.h>
26 #include <linux/kernel.h>
28 #include <linux/moduleparam.h>
29 #include <linux/time.h>
30 #include <linux/clk.h>
31 #include <linux/version.h>
32 #include <linux/device.h>
33 #include <linux/platform_device.h>
34 #include <linux/mutex.h>
35 #include <linux/videodev2.h>
36 #include <linux/kthread.h>
37 #include <mach/iomux.h>
38 #include <media/v4l2-common.h>
39 #include <media/v4l2-dev.h>
40 #include <media/videobuf-dma-contig.h>
41 #include <media/soc_camera.h>
42 #include <media/soc_mediabus.h>
45 #include <plat/vpu_service.h>
46 #include "../../video/rockchip/rga/rga.h"
47 #if defined(CONFIG_ARCH_RK30)||defined(CONFIG_ARCH_RK3188)
48 #include <mach/rk30_camera.h>
52 #include <plat/efuse.h>
53 #if (defined(CONFIG_ARCH_RK2928) || defined(CONFIG_ARCH_RK3026))
54 #include <mach/rk2928_camera.h>
57 #define SOFT_RST_CIF1 (SOFT_RST_MAX+1)
59 #include <asm/cacheflush.h>
62 module_param(debug, int, S_IRUGO|S_IWUSR);
64 #define CAMMODULE_NAME "rk_cam_cif"
66 #define dprintk(level, fmt, arg...) do { \
68 printk(KERN_WARNING "%s(%d): " fmt,CAMMODULE_NAME,__LINE__,## arg); } while (0)
70 #define RKCAMERA_TR(format, ...) printk(KERN_ERR "%s(%d):" format,CAMMODULE_NAME,__LINE__,## __VA_ARGS__)
71 #define RKCAMERA_DG(format, ...) dprintk(1, format, ## __VA_ARGS__)
73 #define CIF_CIF_CTRL 0x00
74 #define CIF_CIF_INTEN 0x04
75 #define CIF_CIF_INTSTAT 0x08
76 #define CIF_CIF_FOR 0x0c
77 #define CIF_CIF_LINE_NUM_ADDR 0x10
78 #define CIF_CIF_FRM0_ADDR_Y 0x14
79 #define CIF_CIF_FRM0_ADDR_UV 0x18
80 #define CIF_CIF_FRM1_ADDR_Y 0x1c
81 #define CIF_CIF_FRM1_ADDR_UV 0x20
82 #define CIF_CIF_VIR_LINE_WIDTH 0x24
83 #define CIF_CIF_SET_SIZE 0x28
84 #define CIF_CIF_SCM_ADDR_Y 0x2c
85 #define CIF_CIF_SCM_ADDR_U 0x30
86 #define CIF_CIF_SCM_ADDR_V 0x34
87 #define CIF_CIF_WB_UP_FILTER 0x38
88 #define CIF_CIF_WB_LOW_FILTER 0x3c
89 #define CIF_CIF_WBC_CNT 0x40
90 #define CIF_CIF_CROP 0x44
91 #define CIF_CIF_SCL_CTRL 0x48
92 #define CIF_CIF_SCL_DST 0x4c
93 #define CIF_CIF_SCL_FCT 0x50
94 #define CIF_CIF_SCL_VALID_NUM 0x54
95 #define CIF_CIF_LINE_LOOP_CTR 0x58
96 #define CIF_CIF_FRAME_STATUS 0x60
97 #define CIF_CIF_CUR_DST 0x64
98 #define CIF_CIF_LAST_LINE 0x68
99 #define CIF_CIF_LAST_PIX 0x6c
101 //The key register bit descrition
102 // CIF_CTRL Reg , ignore SCM,WBC,ISP,
103 #define DISABLE_CAPTURE (0x00<<0)
104 #define ENABLE_CAPTURE (0x01<<0)
105 #define MODE_ONEFRAME (0x00<<1)
106 #define MODE_PINGPONG (0x01<<1)
107 #define MODE_LINELOOP (0x02<<1)
108 #define AXI_BURST_16 (0x0F << 12)
111 #define FRAME_END_EN (0x01<<1)
112 #define BUS_ERR_EN (0x01<<6)
113 #define SCL_ERR_EN (0x01<<7)
116 #define VSY_HIGH_ACTIVE (0x01<<0)
117 #define VSY_LOW_ACTIVE (0x00<<0)
118 #define HSY_LOW_ACTIVE (0x01<<1)
119 #define HSY_HIGH_ACTIVE (0x00<<1)
120 #define INPUT_MODE_YUV (0x00<<2)
121 #define INPUT_MODE_PAL (0x02<<2)
122 #define INPUT_MODE_NTSC (0x03<<2)
123 #define INPUT_MODE_RAW (0x04<<2)
124 #define INPUT_MODE_JPEG (0x05<<2)
125 #define INPUT_MODE_MIPI (0x06<<2)
126 #define YUV_INPUT_ORDER_UYVY(ori) (ori & (~(0x03<<5)))
127 #define YUV_INPUT_ORDER_YVYU(ori) ((ori & (~(0x01<<6)))|(0x01<<5))
128 #define YUV_INPUT_ORDER_VYUY(ori) ((ori & (~(0x01<<5))) | (0x1<<6))
129 #define YUV_INPUT_ORDER_YUYV(ori) (ori|(0x03<<5))
130 #define YUV_INPUT_422 (0x00<<7)
131 #define YUV_INPUT_420 (0x01<<7)
132 #define INPUT_420_ORDER_EVEN (0x00<<8)
133 #define INPUT_420_ORDER_ODD (0x01<<8)
134 #define CCIR_INPUT_ORDER_ODD (0x00<<9)
135 #define CCIR_INPUT_ORDER_EVEN (0x01<<9)
136 #define RAW_DATA_WIDTH_8 (0x00<<11)
137 #define RAW_DATA_WIDTH_10 (0x01<<11)
138 #define RAW_DATA_WIDTH_12 (0x02<<11)
139 #define YUV_OUTPUT_422 (0x00<<16)
140 #define YUV_OUTPUT_420 (0x01<<16)
141 #define OUTPUT_420_ORDER_EVEN (0x00<<17)
142 #define OUTPUT_420_ORDER_ODD (0x01<<17)
143 #define RAWD_DATA_LITTLE_ENDIAN (0x00<<18)
144 #define RAWD_DATA_BIG_ENDIAN (0x01<<18)
145 #define UV_STORAGE_ORDER_UVUV (0x00<<19)
146 #define UV_STORAGE_ORDER_VUVU (0x01<<19)
149 #define ENABLE_SCL_DOWN (0x01<<0)
150 #define DISABLE_SCL_DOWN (0x00<<0)
151 #define ENABLE_SCL_UP (0x01<<1)
152 #define DISABLE_SCL_UP (0x00<<1)
153 #define ENABLE_YUV_16BIT_BYPASS (0x01<<4)
154 #define DISABLE_YUV_16BIT_BYPASS (0x00<<4)
155 #define ENABLE_RAW_16BIT_BYPASS (0x01<<5)
156 #define DISABLE_RAW_16BIT_BYPASS (0x00<<5)
157 #define ENABLE_32BIT_BYPASS (0x01<<6)
158 #define DISABLE_32BIT_BYPASS (0x00<<6)
161 #define MIN(x,y) ((x<y) ? x: y)
162 #define MAX(x,y) ((x>y) ? x: y)
163 #define RK_SENSOR_24MHZ 24*1000*1000 /* MHz */
164 #define RK_SENSOR_48MHZ 48
166 #define write_cif_reg(base,addr, val) __raw_writel(val, addr+(base))
167 #define read_cif_reg(base,addr) __raw_readl(addr+(base))
168 #define mask_cif_reg(addr, msk, val) write_cif_reg(addr, (val)|((~(msk))&read_cif_reg(addr)))
170 #if defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK3188)
172 #define CRU_PCLK_REG30 0xbc
173 #define ENANABLE_INVERT_PCLK_CIF0 ((0x1<<24)|(0x1<<8))
174 #define DISABLE_INVERT_PCLK_CIF0 ((0x1<<24)|(0x0<<8))
175 #define ENANABLE_INVERT_PCLK_CIF1 ((0x1<<28)|(0x1<<12))
176 #define DISABLE_INVERT_PCLK_CIF1 ((0x1<<28)|(0x0<<12))
178 #define CRU_CIF_RST_REG30 0x128
179 #define MASK_RST_CIF0 (0x01 << 30)
180 #define MASK_RST_CIF1 (0x01 << 31)
181 #define RQUEST_RST_CIF0 (0x01 << 14)
182 #define RQUEST_RST_CIF1 (0x01 << 15)
184 #define write_cru_reg(addr, val) __raw_writel(val, addr+RK30_CRU_BASE)
185 #define read_cru_reg(addr) __raw_readl(addr+RK30_CRU_BASE)
186 #define mask_cru_reg(addr, msk, val) write_cru_reg(addr,(val)|((~(msk))&read_cru_reg(addr)))
189 #if defined(CONFIG_ARCH_RK3026)
191 #define CRU_PCLK_REG30 0xbc
192 #define ENANABLE_INVERT_PCLK_CIF0 ((0x1<<23)|(0x1<<7))
193 #define DISABLE_INVERT_PCLK_CIF0 ((0x1<<23)|(0x0<<7))
194 #define ENANABLE_INVERT_PCLK_CIF1 ENANABLE_INVERT_PCLK_CIF0
195 #define DISABLE_INVERT_PCLK_CIF1 DISABLE_INVERT_PCLK_CIF0
197 #define write_cru_reg(addr, val) __raw_writel(val, addr+RK30_CRU_BASE)
198 #define read_cru_reg(addr) __raw_readl(addr+RK30_CRU_BASE)
199 #define mask_cru_reg(addr, msk, val) write_cru_reg(addr,(val)|((~(msk))&read_cru_reg(addr)))
202 #if defined(CONFIG_ARCH_RK2928)
203 #define write_cru_reg(addr, val)
204 #define read_cru_reg(addr) 0
205 #define mask_cru_reg(addr, msk, val)
209 #if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)
211 #define CIF_DRIVER_STRENGTH_2MA (0x00 << 12)
212 #define CIF_DRIVER_STRENGTH_4MA (0x01 << 12)
213 #define CIF_DRIVER_STRENGTH_8MA (0x02 << 12)
214 #define CIF_DRIVER_STRENGTH_12MA (0x03 << 12)
215 #define CIF_DRIVER_STRENGTH_MASK (0x03 << 28)
218 #define CIF_CLKOUT_AMP_3V3 (0x00 << 10)
219 #define CIF_CLKOUT_AMP_1V8 (0x01 << 10)
220 #define CIF_CLKOUT_AMP_MASK (0x01 << 26)
222 #define write_grf_reg(addr, val) __raw_writel(val, addr+RK30_GRF_BASE)
223 #define read_grf_reg(addr) __raw_readl(addr+RK30_GRF_BASE)
224 #define mask_grf_reg(addr, msk, val) write_grf_reg(addr,(val)|((~(msk))&read_grf_reg(addr)))
226 #define write_grf_reg(addr, val)
227 #define read_grf_reg(addr) 0
228 #define mask_grf_reg(addr, msk, val)
231 #define CAM_WORKQUEUE_IS_EN() (true)
232 #define CAM_IPPWORK_IS_EN() ((pcdev->zoominfo.a.c.width != pcdev->icd->user_width) || (pcdev->zoominfo.a.c.height != pcdev->icd->user_height))
234 #define IS_CIF0() (pcdev->hostid == RK_CAM_PLATFORM_DEV_ID_0)
235 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP)
236 #define CROP_ALIGN_BYTES (0x03)
237 #define CIF_DO_CROP 0
238 #elif (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_ARM)
239 #define CROP_ALIGN_BYTES (0x0f)
240 #define CIF_DO_CROP 0
241 #elif (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_RGA)
242 #define CROP_ALIGN_BYTES (0x03)
243 #define CIF_DO_CROP 0
244 #elif(CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_PP)
245 #define CROP_ALIGN_BYTES (0x0F)
246 #define CIF_DO_CROP 1
250 * Driver Version Note
252 *v0.0.x : this driver is 2.6.32 kernel driver;
253 *v0.1.x : this driver is 3.0.8 kernel driver;
255 *v0.x.1 : this driver first support rk2918;
256 *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
257 * and V4L2_PIX_FMT_YUV422P;
258 *v0.x.3 : this driver support VIDIOC_ENUM_FRAMEINTERVALS;
259 *v0.x.4 : this driver support digital zoom;
260 *v0.x.5 : this driver support test framerate and query framerate from board file configuration;
261 *v0.x.6 : this driver improve test framerate method;
262 *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
263 we do crop with cif and do scale with ipp , we will fix this next version.
264 *v0.x.8 : temp version,reinit capture list when setup video buf.
265 *v0.x.9 : 1. add the case of IPP unsupportted ,just cropped by CIF(not do the scale) this version.
266 2. flush workqueue when releas buffer
267 *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
269 2. when the flash is on ,flash off in a fixed time to prevent from flash light too hot.
270 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
271 4. add menu configs for convineuent to customize sensor series
272 *v0.x.b: specify the version is NOT sure stable.
273 *v0.x.c: 1. add cif reset when resolution changed to avoid of collecting data erro
274 2. irq process is splitted to two step.
275 *v0.x.e: fix bugs of early suspend when display_pd is closed.
276 *v0.x.f: fix calculate ipp memory size is enough or not in try_fmt function;
277 *v0.x.11: fix struct rk_camera_work may be reentrant
278 *v0.x.13: 1.add scale by arm,rga and pp.
279 2.CIF do the crop when digital zoom.
280 3.fix bug in prob func:request mem twice.
281 4.video_vq may be null when reinit work,fix it
282 5.arm scale algorithm has something wrong(may exceed the bound of width or height) ,fix it.
284 * 1. support rk3066b;
286 * 1. support 8Mega picture;
288 * 1. invalidate the limit which scale is invalidat when scale ratio > 2;
289 *v0.x.1b: 1. fix oops bug when using arm to do scale_crop if preview buffer is not allocated correctly
290 2. rk_camera_set_fmt will called twice, optimize the procedure. at the first time call ,just to do the sensor init.
293 * 1. fix query resolution error;
295 * 1. add mv9335+ov5650 driver;
296 * 2. fix 2928 digitzoom erro(arm crop scale) of selected zone;
298 * 1. support rk3188; Must soft reset cif controller after each frame irq;
300 * 1. fix ctrl register capture bit may be turn on in rk_videobuf_capture function
303 * 1. compatible with generic_sensor;
306 * 1. fix use v4l2_mbus_framefmt.reserved array overflow in generic_sensor_s_fmt;
309 * 1. support rk3028 , read 3028 chip id by efuse for check cif controller is normal or not;
311 * 1. return real sensor output size in rk_camera_enum_frameintervals;
312 * 2. wake up vb after add camera work to list in rk_camera_capture_process;
314 * 1. this verison is support for 3188M, the version has been revert in v0.3.d;
316 * 1. this version is support foe rk3028a;
319 #define RK_CAM_VERSION_CODE KERNEL_VERSION(0, 3, 0xd)
320 static int version = RK_CAM_VERSION_CODE;
321 module_param(version, int, S_IRUGO);
323 /* limit to rk29 hardware capabilities */
324 #define RK_CAM_BUS_PARAM (SOCAM_MASTER |\
325 SOCAM_HSYNC_ACTIVE_HIGH |\
326 SOCAM_HSYNC_ACTIVE_LOW |\
327 SOCAM_VSYNC_ACTIVE_HIGH |\
328 SOCAM_VSYNC_ACTIVE_LOW |\
329 SOCAM_PCLK_SAMPLE_RISING |\
330 SOCAM_PCLK_SAMPLE_FALLING|\
331 SOCAM_DATA_ACTIVE_HIGH |\
332 SOCAM_DATA_ACTIVE_LOW|\
333 SOCAM_DATAWIDTH_8|SOCAM_DATAWIDTH_10|\
334 SOCAM_MCLK_24MHZ |SOCAM_MCLK_48MHZ)
336 #define RK_CAM_W_MIN 48
337 #define RK_CAM_H_MIN 32
338 #define RK_CAM_W_MAX 3856 /* ddl@rock-chips.com : 10M Pixel */
339 #define RK_CAM_H_MAX 2764
340 #define RK_CAM_FRAME_INVAL_INIT 3
341 #define RK_CAM_FRAME_INVAL_DC 3 /* ddl@rock-chips.com : */
342 #define RK30_CAM_FRAME_MEASURE 5
343 extern void videobuf_dma_contig_free(struct videobuf_queue *q, struct videobuf_buffer *buf);
344 extern dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf);
345 /* buffer for one video frame */
346 struct rk_camera_buffer
348 /* common v4l buffer stuff -- must be first */
349 struct videobuf_buffer vb;
350 enum v4l2_mbus_pixelcode code;
353 enum rk_camera_reg_state
361 unsigned int cifCtrl;
362 unsigned int cifCrop;
364 unsigned int cifIntEn;
366 unsigned int cifVirWidth;
367 unsigned int cifScale;
368 // unsigned int VipCrm;
369 enum rk_camera_reg_state Inval;
371 struct rk_camera_work
373 struct videobuf_buffer *vb;
374 struct rk_camera_dev *pcdev;
375 struct work_struct work;
376 struct list_head queue;
379 struct rk_camera_frmivalenum
381 struct v4l2_frmivalenum fival;
382 struct rk_camera_frmivalenum *nxt;
384 struct rk_camera_frmivalinfo
386 struct soc_camera_device *icd;
387 struct rk_camera_frmivalenum *fival_list;
389 struct rk_camera_zoominfo
391 struct semaphore sem;
397 #if CAMERA_VIDEOBUF_ARM_ACCESS
398 struct rk29_camera_vbinfo
400 unsigned int phy_addr;
401 void __iomem *vir_addr;
405 struct rk_camera_timer{
406 struct rk_camera_dev *pcdev;
407 struct hrtimer timer;
412 //************must modify start************/
414 struct clk *aclk_cif;
415 struct clk *hclk_cif;
416 struct clk *cif_clk_in;
417 struct clk *cif_clk_out;
418 //************must modify end************/
426 struct soc_camera_host soc_host;
428 /* RK2827x is only supposed to handle one camera on its Quick Capture
429 * interface. If anyone ever builds hardware to enable more than
430 * one camera, they will have to modify this driver too */
431 struct soc_camera_device *icd;
433 int frame_inval; /* ddl@rock-chips.com : The first frames is invalidate */
436 unsigned int last_fps;
437 unsigned long frame_interval;
440 unsigned int vipmem_phybase;
441 void __iomem *vipmem_virbase;
442 unsigned int vipmem_size;
443 unsigned int vipmem_bsize;
444 #if CAMERA_VIDEOBUF_ARM_ACCESS
445 struct rk29_camera_vbinfo *vbinfo;
446 unsigned int vbinfo_count;
450 int host_left; //sensor output size ?
456 struct rk29camera_platform_data *pdata;
457 struct resource *res;
458 struct list_head capture;
459 struct rk_camera_zoominfo zoominfo;
463 struct videobuf_buffer *active;
464 struct rk_camera_reg reginfo_suspend;
465 struct workqueue_struct *camera_wq;
466 struct rk_camera_work *camera_work;
467 struct list_head camera_work_queue;
468 spinlock_t camera_work_lock;
469 unsigned int camera_work_count;
470 struct rk_camera_timer fps_timer;
471 struct rk_camera_work camera_reinit_work;
473 rk29_camera_sensor_cb_s icd_cb;
474 struct rk_camera_frmivalinfo icd_frmival[2];
475 // atomic_t to_process_frames;
477 unsigned int reinit_times;
478 struct videobuf_queue *video_vq;
480 struct timeval first_tv;
485 static const struct v4l2_queryctrl rk_camera_controls[] =
488 .id = V4L2_CID_ZOOM_ABSOLUTE,
489 .type = V4L2_CTRL_TYPE_INTEGER,
490 .name = "DigitalZoom Control",
494 .default_value = 100,
498 static struct rk_cif_clk cif_clk[2];
500 static DEFINE_MUTEX(camera_lock);
501 static const char *rk_cam_driver_description = "RK_Camera";
503 static int rk_camera_s_stream(struct soc_camera_device *icd, int enable);
504 static void rk_camera_capture_process(struct work_struct *work);
505 static int rk_camera_scale_crop_arm(struct work_struct *work);
507 static void rk_camera_cif_reset(struct rk_camera_dev *pcdev, int only_rst)
509 int ctrl_reg,inten_reg,crop_reg,set_size_reg,for_reg,vir_line_width_reg,scl_reg;
510 enum cru_soft_reset cif_reset_index = SOFT_RST_CIF0;
512 if (IS_CIF0() == false) {
514 cif_reset_index = SOFT_RST_CIF1;
516 RKCAMERA_TR("%s: CIF1 is invalidate\n",__FUNCTION__);
521 if (only_rst == true) {
522 cru_set_soft_reset(cif_reset_index, true);
524 cru_set_soft_reset(cif_reset_index, false);
526 ctrl_reg = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
527 crop_reg = read_cif_reg(pcdev->base,CIF_CIF_CROP);
528 set_size_reg = read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE);
529 inten_reg = read_cif_reg(pcdev->base,CIF_CIF_INTEN);
530 for_reg = read_cif_reg(pcdev->base,CIF_CIF_FOR);
531 vir_line_width_reg = read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH);
532 scl_reg = read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL);
534 cru_set_soft_reset(cif_reset_index, true);
536 cru_set_soft_reset(cif_reset_index, false);
538 write_cif_reg(pcdev->base,CIF_CIF_CTRL, ctrl_reg&~ENABLE_CAPTURE);
539 write_cif_reg(pcdev->base,CIF_CIF_INTEN, inten_reg);
540 write_cif_reg(pcdev->base,CIF_CIF_CROP, crop_reg);
541 write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, set_size_reg);
542 write_cif_reg(pcdev->base,CIF_CIF_FOR, for_reg);
543 write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH,vir_line_width_reg);
544 write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL,scl_reg);
551 * Videobuf operations
553 static int rk_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
556 struct soc_camera_device *icd = vq->priv_data;
557 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
558 struct rk_camera_dev *pcdev = ici->priv;
560 struct rk_camera_work *wk;
562 struct soc_mbus_pixelfmt fmt;
564 int bytes_per_line_host;
565 fmt.packing = SOC_MBUS_PACKING_1_5X8;
567 bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
568 icd->current_fmt->host_fmt);
569 if(icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_RGB565)
570 bytes_per_line_host = soc_mbus_bytes_per_line(pcdev->host_width,
572 else if(icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_RGB24)
573 bytes_per_line_host = pcdev->host_width*3;
575 bytes_per_line_host = soc_mbus_bytes_per_line(pcdev->host_width,
576 icd->current_fmt->host_fmt);
577 dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size);
579 if (bytes_per_line_host < 0)
580 return bytes_per_line_host;
582 /* planar capture requires Y, U and V buffers to be page aligned */
583 *size = PAGE_ALIGN(bytes_per_line*icd->user_height); /* Y pages UV pages, yuv422*/
584 pcdev->vipmem_bsize = PAGE_ALIGN(bytes_per_line_host * pcdev->host_height);
586 if (CAM_WORKQUEUE_IS_EN()) {
588 if (CAM_IPPWORK_IS_EN()) {
589 BUG_ON(pcdev->vipmem_size<pcdev->vipmem_bsize);
590 if (*count > pcdev->vipmem_size/pcdev->vipmem_bsize) { /* Buffers must be limited, when this resolution is genered by IPP */
591 *count = pcdev->vipmem_size/pcdev->vipmem_bsize;
595 if ((pcdev->camera_work_count != *count) && pcdev->camera_work) {
596 kfree(pcdev->camera_work);
597 pcdev->camera_work = NULL;
598 pcdev->camera_work_count = 0;
601 if (pcdev->camera_work == NULL) {
602 pcdev->camera_work = wk = kzalloc(sizeof(struct rk_camera_work)*(*count), GFP_KERNEL);
603 if (pcdev->camera_work == NULL) {
604 RKCAMERA_TR("kmalloc failed\n");
607 INIT_LIST_HEAD(&pcdev->camera_work_queue);
609 for (i=0; i<(*count); i++) {
611 list_add_tail(&wk->queue, &pcdev->camera_work_queue);
614 pcdev->camera_work_count = (*count);
616 #if CAMERA_VIDEOBUF_ARM_ACCESS
617 if (pcdev->vbinfo && (pcdev->vbinfo_count != *count)) {
618 kfree(pcdev->vbinfo);
619 pcdev->vbinfo = NULL;
620 pcdev->vbinfo_count = 0x00;
623 if (pcdev->vbinfo == NULL) {
624 pcdev->vbinfo = kzalloc(sizeof(struct rk29_camera_vbinfo)*(*count), GFP_KERNEL);
625 if (pcdev->vbinfo == NULL) {
626 RKCAMERA_TR("vbinfo kmalloc fail\n");
629 memset(pcdev->vbinfo,0,sizeof(struct rk29_camera_vbinfo)*(*count));
630 pcdev->vbinfo_count = *count;
634 pcdev->video_vq = vq;
635 RKCAMERA_DG("videobuf size:%d, vipmem_buf size:%d, count:%d \n",*size,pcdev->vipmem_size, *count);
639 static void rk_videobuf_free(struct videobuf_queue *vq, struct rk_camera_buffer *buf)
641 struct soc_camera_device *icd = vq->priv_data;
643 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
644 &buf->vb, buf->vb.baddr, buf->vb.bsize);
646 /* ddl@rock-chips.com: buf_release called soc_camera_streamoff and soc_camera_close*/
647 if (buf->vb.state == VIDEOBUF_NEEDS_INIT)
653 * This waits until this buffer is out of danger, i.e., until it is no
654 * longer in STATE_QUEUED or STATE_ACTIVE
656 //videobuf_waiton(vq, &buf->vb, 0, 0);
657 videobuf_dma_contig_free(vq, &buf->vb);
658 dev_dbg(&icd->dev, "%s freed\n", __func__);
659 buf->vb.state = VIDEOBUF_NEEDS_INIT;
662 static int rk_videobuf_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, enum v4l2_field field)
664 struct soc_camera_device *icd = vq->priv_data;
665 struct rk_camera_buffer *buf;
667 int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
668 icd->current_fmt->host_fmt);
669 if ((bytes_per_line < 0) || (vb->boff == 0))
672 buf = container_of(vb, struct rk_camera_buffer, vb);
674 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
675 vb, vb->baddr, vb->bsize);
677 /* Added list head initialization on alloc */
678 WARN_ON(!list_empty(&vb->queue));
680 BUG_ON(NULL == icd->current_fmt);
682 if (buf->code != icd->current_fmt->code ||
683 vb->width != icd->user_width ||
684 vb->height != icd->user_height ||
685 vb->field != field) {
686 buf->code = icd->current_fmt->code;
687 vb->width = icd->user_width;
688 vb->height = icd->user_height;
690 vb->state = VIDEOBUF_NEEDS_INIT;
693 vb->size = bytes_per_line*vb->height; /* ddl@rock-chips.com : fmt->depth is coorect */
694 if (0 != vb->baddr && vb->bsize < vb->size) {
699 if (vb->state == VIDEOBUF_NEEDS_INIT) {
700 ret = videobuf_iolock(vq, vb, NULL);
704 vb->state = VIDEOBUF_PREPARED;
709 rk_videobuf_free(vq, buf);
714 static inline void rk_videobuf_capture(struct videobuf_buffer *vb,struct rk_camera_dev *rk_pcdev)
716 unsigned int y_addr,uv_addr;
717 struct rk_camera_dev *pcdev = rk_pcdev;
720 if (CAM_WORKQUEUE_IS_EN()) {
721 y_addr = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
722 uv_addr = y_addr + pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height;
723 if (y_addr > (pcdev->vipmem_phybase + pcdev->vipmem_size - pcdev->vipmem_bsize)) {
724 RKCAMERA_TR("vipmem for IPP is overflow! %dx%d -> %dx%d vb_index:%d\n",pcdev->host_width,pcdev->host_height,
725 pcdev->icd->user_width,pcdev->icd->user_height, vb->i);
730 uv_addr = y_addr + vb->width * vb->height;
732 #if defined(CONFIG_ARCH_RK3188)
733 rk_camera_cif_reset(pcdev,false);
735 write_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y, y_addr);
736 write_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV, uv_addr);
737 write_cif_reg(pcdev->base,CIF_CIF_FRM1_ADDR_Y, y_addr);
738 write_cif_reg(pcdev->base,CIF_CIF_FRM1_ADDR_UV, uv_addr);
739 write_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS, 0x00000002);//frame1 has been ready to receive data,frame 2 is not used
742 /* Locking: Caller holds q->irqlock */
743 static void rk_videobuf_queue(struct videobuf_queue *vq,
744 struct videobuf_buffer *vb)
746 struct soc_camera_device *icd = vq->priv_data;
747 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
748 struct rk_camera_dev *pcdev = ici->priv;
749 #if CAMERA_VIDEOBUF_ARM_ACCESS
750 struct rk29_camera_vbinfo *vb_info;
753 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
754 vb, vb->baddr, vb->bsize);
756 vb->state = VIDEOBUF_QUEUED;
757 if (list_empty(&pcdev->capture)) {
758 list_add_tail(&vb->queue, &pcdev->capture);
760 if (list_entry(pcdev->capture.next, struct videobuf_buffer, queue) != vb)
761 list_add_tail(&vb->queue, &pcdev->capture);
763 BUG(); /* ddl@rock-chips.com : The same videobuffer queue again */
765 #if CAMERA_VIDEOBUF_ARM_ACCESS
767 vb_info = pcdev->vbinfo+vb->i;
768 if ((vb_info->phy_addr != vb->boff) || (vb_info->size != vb->bsize)) {
769 if (vb_info->vir_addr) {
770 iounmap(vb_info->vir_addr);
771 release_mem_region(vb_info->phy_addr, vb_info->size);
772 vb_info->vir_addr = NULL;
773 vb_info->phy_addr = 0x00;
774 vb_info->size = 0x00;
777 if (request_mem_region(vb->boff,vb->bsize,"rk_camera_vb")) {
778 vb_info->vir_addr = ioremap_cached(vb->boff,vb->bsize);
781 if (vb_info->vir_addr) {
782 vb_info->size = vb->bsize;
783 vb_info->phy_addr = vb->boff;
785 RKCAMERA_TR("ioremap videobuf %d failed\n",vb->i);
790 if (!pcdev->active) {
792 rk_videobuf_capture(vb,pcdev);
795 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP)
796 static int rk_pixfmt2ippfmt(unsigned int pixfmt, int *ippfmt)
800 case V4L2_PIX_FMT_NV16:
801 case V4L2_PIX_FMT_NV61:
803 *ippfmt = IPP_Y_CBCR_H2V1;
806 case V4L2_PIX_FMT_NV12:
807 case V4L2_PIX_FMT_NV21:
809 *ippfmt = IPP_Y_CBCR_H2V2;
813 goto rk_pixfmt2ippfmt_err;
817 rk_pixfmt2ippfmt_err:
821 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_RGA)
822 static int rk_pixfmt2rgafmt(unsigned int pixfmt, int *ippfmt)
826 case V4L2_PIX_FMT_YUV420:
827 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.
828 case V4L2_PIX_FMT_YUYV:
830 *ippfmt = RK_FORMAT_YCbCr_420_SP;
833 case V4L2_PIX_FMT_YVU420:
834 case V4L2_PIX_FMT_VYUY:
835 case V4L2_PIX_FMT_YVYU:
837 *ippfmt = RK_FORMAT_YCrCb_420_SP;
840 case V4L2_PIX_FMT_RGB565:
842 *ippfmt = RK_FORMAT_RGB_565;
845 case V4L2_PIX_FMT_RGB24:
847 *ippfmt = RK_FORMAT_RGB_888;
851 goto rk_pixfmt2rgafmt_err;
855 rk_pixfmt2rgafmt_err:
859 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_PP)
860 static int rk_camera_scale_crop_pp(struct work_struct *work){
861 struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
862 struct videobuf_buffer *vb = camera_work->vb;
863 struct rk_camera_dev *pcdev = camera_work->pcdev;
865 unsigned long int flags;
871 vipdata_base = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
873 memset(&init, 0, sizeof(init));
874 init.srcAddr = vipdata_base;
875 init.srcFormat = PP_IN_FORMAT_YUV420SEMI;
876 init.srcWidth = init.srcHStride = pcdev->zoominfo.vir_width;
877 init.srcHeight = init.srcVStride = pcdev->zoominfo.vir_height;
879 init.dstAddr = vb->boff;
880 init.dstFormat = PP_OUT_FORMAT_YUV420INTERLAVE;
881 init.dstWidth = init.dstHStride = pcdev->icd->user_width;
882 init.dstHeight = init.dstVStride = pcdev->icd->user_height;
884 printk("srcWidth = %d,srcHeight = %d,dstWidth = %d,dstHeight = %d\n",init.srcWidth,init.srcHeight,init.dstWidth,init.dstHeight);
886 ret = ppOpInit(&hnd, &init);
892 printk("can not create ppOp handle\n");
898 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_RGA)
899 extern rga_service_info rga_service;
900 extern int rga_blit_sync(rga_session *session, struct rga_req *req);
901 extern void rga_service_session_clear(rga_session *session);
902 static int rk_camera_scale_crop_rga(struct work_struct *work){
903 struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
904 struct videobuf_buffer *vb = camera_work->vb;
905 struct rk_camera_dev *pcdev = camera_work->pcdev;
907 unsigned long int flags;
913 const struct soc_mbus_pixelfmt *fmt;
915 fmt = soc_mbus_get_fmtdesc(pcdev->icd->current_fmt->code);
916 vipdata_base = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
917 if((pcdev->icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_RGB565)
918 && (pcdev->icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_RGB24)){
919 RKCAMERA_TR("RGA not support this format !\n");
922 if ((pcdev->icd->user_width > 0x800) || (pcdev->icd->user_height > 0x800)) {
923 scale_times = MAX((pcdev->icd->user_width/0x800),(pcdev->icd->user_height/0x800));
928 session.pid = current->pid;
929 INIT_LIST_HEAD(&session.waiting);
930 INIT_LIST_HEAD(&session.running);
931 INIT_LIST_HEAD(&session.list_session);
932 init_waitqueue_head(&session.wait);
933 /* no need to protect */
934 list_add_tail(&session.list_session, &rga_service.session);
935 atomic_set(&session.task_running, 0);
936 atomic_set(&session.num_done, 0);
938 memset(&req,0,sizeof(struct rga_req));
939 req.src.act_w = pcdev->zoominfo.a.c.width/scale_times;
940 req.src.act_h = pcdev->zoominfo.a.c.height/scale_times;
942 req.src.vir_w = pcdev->zoominfo.vir_width;
943 req.src.vir_h =pcdev->zoominfo.vir_height;
944 req.src.yrgb_addr = vipdata_base;
945 req.src.uv_addr =vipdata_base + pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height;;
946 req.src.v_addr = req.src.uv_addr ;
947 req.src.format =fmt->fourcc;
948 rk_pixfmt2rgafmt(fmt->fourcc,&req.src.format);
949 req.src.x_offset = pcdev->zoominfo.a.c.left;
950 req.src.y_offset = pcdev->zoominfo.a.c.top;
952 req.dst.act_w = pcdev->icd->user_width/scale_times;
953 req.dst.act_h = pcdev->icd->user_height/scale_times;
955 req.dst.vir_w = pcdev->icd->user_width;
956 req.dst.vir_h = pcdev->icd->user_height;
957 req.dst.x_offset = 0;
958 req.dst.y_offset = 0;
959 req.dst.yrgb_addr = vb->boff;
960 rk_pixfmt2rgafmt(pcdev->icd->current_fmt->host_fmt->fourcc,&req.dst.format);
962 req.clip.xmax = req.dst.vir_w-1;
964 req.clip.ymax = req.dst.vir_h -1;
971 req.mmu_info.mmu_en = 0;
973 for (h=0; h<scale_times; h++) {
974 for (w=0; w<scale_times; w++) {
977 req.src.yrgb_addr = vipdata_base;
978 req.src.uv_addr =vipdata_base + pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height;;
979 req.src.x_offset = pcdev->zoominfo.a.c.left+w*pcdev->zoominfo.a.c.width/scale_times;
980 req.src.y_offset = pcdev->zoominfo.a.c.top+h*pcdev->zoominfo.a.c.height/scale_times;
981 req.dst.x_offset = pcdev->icd->user_width*w/scale_times;
982 req.dst.y_offset = pcdev->icd->user_height*h/scale_times;
983 req.dst.yrgb_addr = vb->boff ;
984 // 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);
985 // 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);
986 // RKCAMERA_TR("req.src.yrgb_addr = 0x%x,req.dst.yrgb_addr = 0x%x\n",req.src.yrgb_addr,req.dst.yrgb_addr);
988 while(rga_times-- > 0) {
989 if (rga_blit_sync(&session, &req)){
990 RKCAMERA_TR("rga do erro,do again,rga_times = %d!\n",rga_times);
996 if (rga_times <= 0) {
997 spin_lock_irqsave(&pcdev->lock, flags);
998 vb->state = VIDEOBUF_NEEDS_INIT;
999 spin_unlock_irqrestore(&pcdev->lock, flags);
1000 mutex_lock(&rga_service.lock);
1001 list_del(&session.list_session);
1002 rga_service_session_clear(&session);
1003 mutex_unlock(&rga_service.lock);
1009 mutex_lock(&rga_service.lock);
1010 list_del(&session.list_session);
1011 rga_service_session_clear(&session);
1012 mutex_unlock(&rga_service.lock);
1021 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP)
1023 static int rk_camera_scale_crop_ipp(struct work_struct *work)
1025 struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
1026 struct videobuf_buffer *vb = camera_work->vb;
1027 struct rk_camera_dev *pcdev = camera_work->pcdev;
1029 unsigned long int flags;
1031 struct rk29_ipp_req ipp_req;
1032 int src_y_offset,src_uv_offset,dst_y_offset,dst_uv_offset,src_y_size,dst_y_size;
1033 int scale_times,w,h;
1034 int ret = 0, scale_crop_ret=0;
1037 *ddl@rock-chips.com:
1038 * IPP Dest image resolution is 2047x1088, so scale operation break up some times
1040 if ((pcdev->icd->user_width > 0x7f0) || (pcdev->icd->user_height > 0x430)) {
1041 scale_times = MAX((pcdev->icd->user_width/0x7f0),(pcdev->icd->user_height/0x430));
1046 memset(&ipp_req, 0, sizeof(struct rk29_ipp_req));
1049 ipp_req.timeout = 3000;
1050 ipp_req.flag = IPP_ROT_0;
1051 ipp_req.store_clip_mode =1;
1052 ipp_req.src0.w = pcdev->zoominfo.a.c.width/scale_times;
1053 ipp_req.src0.h = pcdev->zoominfo.a.c.height/scale_times;
1054 ipp_req.src_vir_w = pcdev->zoominfo.vir_width;
1055 rk_pixfmt2ippfmt(pcdev->pixfmt, &ipp_req.src0.fmt);
1056 ipp_req.dst0.w = pcdev->icd->user_width/scale_times;
1057 ipp_req.dst0.h = pcdev->icd->user_height/scale_times;
1058 ipp_req.dst_vir_w = pcdev->icd->user_width;
1059 rk_pixfmt2ippfmt(pcdev->pixfmt, &ipp_req.dst0.fmt);
1060 vipdata_base = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
1061 src_y_size = pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height; //vipmem
1062 dst_y_size = pcdev->icd->user_width*pcdev->icd->user_height;
1063 for (h=0; h<scale_times; h++) {
1064 for (w=0; w<scale_times; w++) {
1065 src_y_offset = (pcdev->zoominfo.a.c.top + h*pcdev->zoominfo.a.c.height/scale_times)* pcdev->zoominfo.vir_width
1066 + pcdev->zoominfo.a.c.left + w*pcdev->zoominfo.a.c.width/scale_times;
1067 src_uv_offset = (pcdev->zoominfo.a.c.top + h*pcdev->zoominfo.a.c.height/scale_times)* pcdev->zoominfo.vir_width/2
1068 + pcdev->zoominfo.a.c.left + w*pcdev->zoominfo.a.c.width/scale_times;
1070 dst_y_offset = pcdev->icd->user_width*pcdev->icd->user_height*h/scale_times + pcdev->icd->user_width*w/scale_times;
1071 dst_uv_offset = pcdev->icd->user_width*pcdev->icd->user_height*h/scale_times/2 + pcdev->icd->user_width*w/scale_times;
1073 ipp_req.src0.YrgbMst = vipdata_base + src_y_offset;
1074 ipp_req.src0.CbrMst = vipdata_base + src_y_size + src_uv_offset;
1075 ipp_req.dst0.YrgbMst = vb->boff + dst_y_offset;
1076 ipp_req.dst0.CbrMst = vb->boff + dst_y_size + dst_uv_offset;
1078 if (ipp_blit_sync(&ipp_req)){
1079 RKCAMERA_TR("ipp do erro, so switch to arm \n");
1080 scale_crop_ret = 0x01;
1086 if (scale_crop_ret == 0x01) {
1087 ret = rk_camera_scale_crop_arm(work);
1091 spin_lock_irqsave(&pcdev->lock, flags);
1092 vb->state = VIDEOBUF_NEEDS_INIT;
1093 spin_unlock_irqrestore(&pcdev->lock, flags);
1094 RKCAMERA_TR("Capture image(vb->i:0x%x) which IPP and ARM operated is error:\n",vb->i);
1095 RKCAMERA_TR("widx:%d hidx:%d ",w,h);
1096 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);
1097 RKCAMERA_TR("ipp_req.src0.YrgbMst:0x%x ipp_req.src0.CbrMst:0x%x \n", ipp_req.src0.YrgbMst,ipp_req.src0.CbrMst);
1098 RKCAMERA_TR("ipp_req.src0.w:0x%x ipp_req.src0.h:0x%x \n",ipp_req.src0.w,ipp_req.src0.h);
1099 RKCAMERA_TR("ipp_req.src0.fmt:0x%x\n",ipp_req.src0.fmt);
1100 RKCAMERA_TR("ipp_req.dst0.YrgbMst:0x%x ipp_req.dst0.CbrMst:0x%x \n",ipp_req.dst0.YrgbMst,ipp_req.dst0.CbrMst);
1101 RKCAMERA_TR("ipp_req.dst0.w:0x%x ipp_req.dst0.h:0x%x \n",ipp_req.dst0.w ,ipp_req.dst0.h);
1102 RKCAMERA_TR("ipp_req.dst0.fmt:0x%x\n",ipp_req.dst0.fmt);
1103 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);
1104 RKCAMERA_TR("ipp_req.timeout:0x%x ipp_req.flag :0x%x\n",ipp_req.timeout,ipp_req.flag);
1110 static int rk_camera_scale_crop_arm(struct work_struct *work)
1112 struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
1113 struct videobuf_buffer *vb = camera_work->vb;
1114 struct rk_camera_dev *pcdev = camera_work->pcdev;
1115 struct rk29_camera_vbinfo *vb_info;
1116 unsigned char *psY,*pdY,*psUV,*pdUV;
1117 unsigned char *src,*dst;
1118 unsigned long src_phy,dst_phy;
1119 int srcW,srcH,cropW,cropH,dstW,dstH;
1120 long zoomindstxIntInv,zoomindstyIntInv;
1122 long yCoeff00,yCoeff01,xCoeff00,xCoeff01;
1125 int ret = 0, shift_bits = 0;
1127 src_phy = pcdev->vipmem_phybase + vb->i*pcdev->vipmem_bsize;
1128 src = psY = (unsigned char*)(pcdev->vipmem_virbase + vb->i*pcdev->vipmem_bsize);
1129 psUV = psY + pcdev->zoominfo.vir_width*pcdev->zoominfo.vir_height;
1131 srcW = pcdev->zoominfo.vir_width;
1132 srcH = pcdev->zoominfo.vir_height;
1133 cropW = pcdev->zoominfo.a.c.width;
1134 cropH = pcdev->zoominfo.a.c.height;
1136 psY = psY + pcdev->zoominfo.a.c.top*pcdev->zoominfo.vir_width+pcdev->zoominfo.a.c.left;
1137 psUV = psUV + pcdev->zoominfo.a.c.top*pcdev->zoominfo.vir_width/2+pcdev->zoominfo.a.c.left;
1139 vb_info = pcdev->vbinfo+vb->i;
1140 dst_phy = vb_info->phy_addr;
1141 dst = pdY = (unsigned char*)vb_info->vir_addr;
1142 pdUV = pdY + pcdev->icd->user_width*pcdev->icd->user_height;
1143 dstW = pcdev->icd->user_width;
1144 dstH = pcdev->icd->user_height;
1146 zoomindstxIntInv = ((unsigned long)(cropW)<<16)/dstW + 1;
1147 zoomindstyIntInv = ((unsigned long)(cropH)<<16)/dstH + 1;
1148 #ifdef CONFIG_SOC_RK3028
1149 shift_bits = (pcdev->chip_id == 0x42)?0:2;
1152 //for(y = 0; y<dstH - 1 ; y++ ) {
1153 for(y = 0; y<dstH; y++ ) {
1154 yCoeff00 = (y*zoomindstyIntInv)&0xffff;
1155 yCoeff01 = 0xffff - yCoeff00;
1156 sY = (y*zoomindstyIntInv >> 16);
1157 sY = (sY >= srcH - 1)? (srcH - 2) : sY;
1158 for(x = 0; x<dstW; x++ ) {
1159 xCoeff00 = (x*zoomindstxIntInv)&0xffff;
1160 xCoeff01 = 0xffff - xCoeff00;
1161 sX = (x*zoomindstxIntInv >> 16);
1162 sX = (sX >= srcW -1)?(srcW- 2) : sX;
1163 a = (psY[sY*srcW + sX]<<shift_bits);
1164 b = (psY[sY*srcW + sX + 1]<<shift_bits);
1165 c = (psY[(sY+1)*srcW + sX]<<shift_bits);
1166 d = (psY[(sY+1)*srcW + sX + 1]<<shift_bits);
1168 r0 = (a * xCoeff01 + b * xCoeff00)>>16 ;
1169 r1 = (c * xCoeff01 + d * xCoeff00)>>16 ;
1170 r0 = (r0 * yCoeff01 + r1 * yCoeff00)>>16;
1183 //for(y = 0; y<dstH - 1 ; y++ ) {
1184 for(y = 0; y<dstH; y++ ) {
1185 yCoeff00 = (y*zoomindstyIntInv)&0xffff;
1186 yCoeff01 = 0xffff - yCoeff00;
1187 sY = (y*zoomindstyIntInv >> 16);
1188 sY = (sY >= srcH -1)? (srcH - 2) : sY;
1189 for(x = 0; x<dstW; x++ ) {
1190 xCoeff00 = (x*zoomindstxIntInv)&0xffff;
1191 xCoeff01 = 0xffff - xCoeff00;
1192 sX = (x*zoomindstxIntInv >> 16);
1193 sX = (sX >= srcW -1)?(srcW- 2) : sX;
1195 a = (psUV[(sY*srcW + sX)*2]<<shift_bits);
1196 b = (psUV[(sY*srcW + sX + 1)*2]<<shift_bits);
1197 c = (psUV[((sY+1)*srcW + sX)*2]<<shift_bits);
1198 d = (psUV[((sY+1)*srcW + sX + 1)*2]<<shift_bits);
1201 r0 = (a * xCoeff01 + b * xCoeff00)>>16 ;
1202 r1 = (c * xCoeff01 + d * xCoeff00)>>16 ;
1203 r0 = (r0 * yCoeff01 + r1 * yCoeff00)>>16;
1208 a = (psUV[(sY*srcW + sX)*2 + 1]<<shift_bits);
1209 b = (psUV[(sY*srcW + sX + 1)*2 + 1]<<shift_bits);
1210 c = (psUV[((sY+1)*srcW + sX)*2 + 1]<<shift_bits);
1211 d = (psUV[((sY+1)*srcW + sX + 1)*2 + 1]<<shift_bits);
1213 r0 = (a * xCoeff01 + b * xCoeff00)>>16 ;
1214 r1 = (c * xCoeff01 + d * xCoeff00)>>16 ;
1215 r0 = (r0 * yCoeff01 + r1 * yCoeff00)>>16;
1222 dmac_flush_range((void*)src,(void*)(src+pcdev->vipmem_bsize));
1223 outer_flush_range((phys_addr_t)src_phy,(phys_addr_t)(src_phy+pcdev->vipmem_bsize));
1225 dmac_flush_range((void*)dst,(void*)(dst+vb_info->size));
1226 outer_flush_range((phys_addr_t)dst_phy,(phys_addr_t)(dst_phy+vb_info->size));
1230 static void rk_camera_capture_process(struct work_struct *work)
1232 struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
1233 struct videobuf_buffer *vb = camera_work->vb;
1234 struct rk_camera_dev *pcdev = camera_work->pcdev;
1235 //enum v4l2_mbus_pixelcode icd_code = pcdev->icd->current_fmt->code;
1236 unsigned long flags = 0;
1239 if (!CAM_WORKQUEUE_IS_EN())
1240 goto rk_camera_capture_process_end;
1242 down(&pcdev->zoominfo.sem);
1243 if (pcdev->icd_cb.scale_crop_cb){
1244 err = (pcdev->icd_cb.scale_crop_cb)(work);
1246 up(&pcdev->zoominfo.sem);
1248 if (pcdev->icd_cb.sensor_cb)
1249 (pcdev->icd_cb.sensor_cb)(vb);
1251 rk_camera_capture_process_end:
1253 vb->state = VIDEOBUF_ERROR;
1255 if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) {
1256 vb->state = VIDEOBUF_DONE;
1260 spin_lock_irqsave(&pcdev->camera_work_lock, flags);
1261 list_add_tail(&camera_work->queue, &pcdev->camera_work_queue);
1262 spin_unlock_irqrestore(&pcdev->camera_work_lock, flags);
1263 wake_up(&(camera_work->vb->done)); /* ddl@rock-chips.com : v0.3.9 */
1266 static irqreturn_t rk_camera_irq(int irq, void *data)
1268 struct rk_camera_dev *pcdev = data;
1269 struct videobuf_buffer *vb;
1270 struct rk_camera_work *wk;
1272 unsigned long tmp_intstat;
1273 unsigned long tmp_cifctrl;
1275 tmp_intstat = read_cif_reg(pcdev->base,CIF_CIF_INTSTAT);
1276 tmp_cifctrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
1277 if(pcdev->stop_cif == true) {
1278 printk("cif has stopped by app,needn't to deal this irq\n");
1279 write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF); /* clear vip interrupte single */
1283 if ((tmp_intstat & 0x0200)) { // Cif irq
1284 write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0x0200); /* clear vip interrupte single */
1285 if(tmp_cifctrl & ENABLE_CAPTURE)
1286 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl & ~ENABLE_CAPTURE));
1290 if ((tmp_intstat & 0x01)) { // dma irq
1291 /* ddl@rock-chps.com : Current VIP is run in One Frame Mode, Frame 1 is validate */
1292 if (read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS) & 0x01) {
1293 write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0x01); /* clear vip interrupte single */
1295 do_gettimeofday(&pcdev->first_tv);
1299 goto RK_CAMERA_IRQ_END;
1300 if (pcdev->frame_inval>0) {
1301 pcdev->frame_inval--;
1302 rk_videobuf_capture(pcdev->active,pcdev);
1303 goto RK_CAMERA_IRQ_END;
1304 } else if (pcdev->frame_inval) {
1305 RKCAMERA_TR("frame_inval : %0x",pcdev->frame_inval);
1306 pcdev->frame_inval = 0;
1308 if(pcdev->fps == RK30_CAM_FRAME_MEASURE) {
1309 do_gettimeofday(&tv);
1310 pcdev->frame_interval = ((tv.tv_sec*1000000 + tv.tv_usec) - (pcdev->first_tv.tv_sec*1000000 + pcdev->first_tv.tv_usec))
1311 /(RK30_CAM_FRAME_MEASURE-1);
1315 printk("no acticve buffer!!!\n");
1316 goto RK_CAMERA_IRQ_END;
1318 /* ddl@rock-chips.com : this vb may be deleted from queue */
1319 if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) {
1320 list_del_init(&vb->queue);
1322 pcdev->active = NULL;
1323 if (!list_empty(&pcdev->capture)) {
1324 pcdev->active = list_entry(pcdev->capture.next, struct videobuf_buffer, queue);
1325 if (pcdev->active) {
1326 WARN_ON(pcdev->active->state != VIDEOBUF_QUEUED);
1327 rk_videobuf_capture(pcdev->active,pcdev);
1330 if (pcdev->active == NULL) {
1331 RKCAMERA_DG("video_buf queue is empty!\n");
1334 do_gettimeofday(&vb->ts);
1335 if (CAM_WORKQUEUE_IS_EN()) {
1336 if (!list_empty(&pcdev->camera_work_queue)) {
1337 wk = list_entry(pcdev->camera_work_queue.next, struct rk_camera_work, queue);
1338 list_del_init(&wk->queue);
1339 INIT_WORK(&(wk->work), rk_camera_capture_process);
1342 queue_work(pcdev->camera_wq, &(wk->work));
1345 if ((vb->state == VIDEOBUF_QUEUED) || (vb->state == VIDEOBUF_ACTIVE)) {
1346 vb->state = VIDEOBUF_DONE;
1356 if((tmp_cifctrl & ENABLE_CAPTURE) == 0)
1357 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl | ENABLE_CAPTURE));
1362 static void rk_videobuf_release(struct videobuf_queue *vq,
1363 struct videobuf_buffer *vb)
1365 struct rk_camera_buffer *buf = container_of(vb, struct rk_camera_buffer, vb);
1366 struct soc_camera_device *icd = vq->priv_data;
1367 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1368 struct rk_camera_dev *pcdev = ici->priv;
1369 #if CAMERA_VIDEOBUF_ARM_ACCESS
1370 struct rk29_camera_vbinfo *vb_info =NULL;
1374 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
1375 vb, vb->baddr, vb->bsize);
1379 case VIDEOBUF_ACTIVE:
1380 dev_dbg(&icd->dev, "%s (active)\n", __func__);
1382 case VIDEOBUF_QUEUED:
1383 dev_dbg(&icd->dev, "%s (queued)\n", __func__);
1385 case VIDEOBUF_PREPARED:
1386 dev_dbg(&icd->dev, "%s (prepared)\n", __func__);
1389 dev_dbg(&icd->dev, "%s (unknown)\n", __func__);
1393 if (vb == pcdev->active) {
1394 RKCAMERA_DG("Wait for this video buf(0x%x) write finished!\n ",(unsigned int)vb);
1395 interruptible_sleep_on_timeout(&vb->done, msecs_to_jiffies(500));
1396 RKCAMERA_DG("This video buf(0x%x) write finished, release now!!\n",(unsigned int)vb);
1399 flush_workqueue(pcdev->camera_wq);
1400 #if CAMERA_VIDEOBUF_ARM_ACCESS
1401 if ((pcdev->vbinfo) && (vb->i < pcdev->vbinfo_count)) {
1402 vb_info = pcdev->vbinfo + vb->i;
1404 if (vb_info->vir_addr) {
1405 iounmap(vb_info->vir_addr);
1406 release_mem_region(vb_info->phy_addr, vb_info->size);
1407 memset(vb_info, 0x00, sizeof(struct rk29_camera_vbinfo));
1412 rk_videobuf_free(vq, buf);
1415 static struct videobuf_queue_ops rk_videobuf_ops =
1417 .buf_setup = rk_videobuf_setup,
1418 .buf_prepare = rk_videobuf_prepare,
1419 .buf_queue = rk_videobuf_queue,
1420 .buf_release = rk_videobuf_release,
1423 static void rk_camera_init_videobuf(struct videobuf_queue *q,
1424 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;
1429 /* We must pass NULL as dev pointer, then all pci_* dma operations
1430 * transform to normal dma_* ones. */
1431 videobuf_queue_dma_contig_init(q,
1433 ici->v4l2_dev.dev, &pcdev->lock,
1434 V4L2_BUF_TYPE_VIDEO_CAPTURE,
1436 sizeof(struct rk_camera_buffer),
1437 icd,&icd->video_lock);
1440 static int rk_camera_mclk_ctrl(int cif_idx, int on, int clk_rate)
1443 struct rk_cif_clk *clk;
1444 struct clk *cif_clk_out_div;
1446 cif = cif_idx - RK29_CAM_PLATFORM_DEV_ID;
1447 if ((cif<0)||(cif>1)) {
1448 RKCAMERA_TR(KERN_ERR "cif index(%d) is invalidate\n",cif_idx);
1450 goto rk_camera_clk_ctrl_end;
1453 clk = &cif_clk[cif];
1455 if(!clk->aclk_cif || !clk->hclk_cif || !clk->cif_clk_in || !clk->cif_clk_out) {
1456 RKCAMERA_TR(KERN_ERR "failed to get cif clock source\n");
1458 goto rk_camera_clk_ctrl_end;
1461 spin_lock(&clk->lock);
1462 if (on && !clk->on) {
1463 clk_enable(clk->pd_cif);
1464 clk_enable(clk->aclk_cif);
1465 clk_enable(clk->hclk_cif);
1466 clk_enable(clk->cif_clk_in);
1467 clk_enable(clk->cif_clk_out);
1468 clk_set_rate(clk->cif_clk_out,clk_rate);
1470 } else if (!on && clk->on) {
1471 clk_disable(clk->aclk_cif);
1472 clk_disable(clk->hclk_cif);
1473 clk_disable(clk->cif_clk_in);
1474 clk_disable(clk->cif_clk_out);
1475 clk_disable(clk->pd_cif);
1478 cif_clk_out_div = clk_get(NULL, "cif1_out_div");
1479 err = clk_set_parent(clk->cif_clk_out,cif_clk_out_div);
1481 cif_clk_out_div = clk_get(NULL, "cif0_out_div");
1482 if(IS_ERR_OR_NULL(cif_clk_out_div)){
1483 cif_clk_out_div = clk_get(NULL, "cif_out_div");
1485 err = clk_set_parent(clk->cif_clk_out, cif_clk_out_div);
1488 RKCAMERA_TR("WARNING %s_%s_%d: camera sensor mclk maybe not close, please check!!!\n", __FILE__, __FUNCTION__, __LINE__);
1490 spin_unlock(&clk->lock);
1491 rk_camera_clk_ctrl_end:
1495 static int rk_camera_activate(struct rk_camera_dev *pcdev, struct soc_camera_device *icd)
1498 * ddl@rock-chips.com : Cif clk control in rk_sensor_power which in rk_camera.c
1500 write_cif_reg(pcdev->base,CIF_CIF_CTRL,AXI_BURST_16|MODE_ONEFRAME|DISABLE_CAPTURE); /* ddl@rock-chips.com : vip ahb burst 16 */
1501 write_cif_reg(pcdev->base,CIF_CIF_INTEN, 0x01); //capture complete interrupt enable
1502 RKCAMERA_DG("CIF_CIF_CTRL = 0x%x\n",read_cif_reg(pcdev->base, CIF_CIF_CTRL));
1506 static void rk_camera_deactivate(struct rk_camera_dev *pcdev)
1509 * ddl@rock-chips.com : Cif clk control in rk_sensor_power which in rk_camera.c
1515 /* The following two functions absolutely depend on the fact, that
1516 * there can be only one camera on RK28 quick capture interface */
1517 static int rk_camera_add_device(struct soc_camera_device *icd)
1519 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1520 struct rk_camera_dev *pcdev = ici->priv;
1521 struct device *control = to_soc_camera_control(icd);
1522 struct v4l2_subdev *sd;
1523 int ret,i,icd_catch;
1524 struct rk_camera_frmivalenum *fival_list,*fival_nxt;
1526 mutex_lock(&camera_lock);
1533 RKCAMERA_DG("%s driver attached to %s\n",RK29_CAM_DRV_NAME,dev_name(icd->pdev));
1535 pcdev->frame_inval = RK_CAM_FRAME_INVAL_INIT;
1536 pcdev->active = NULL;
1538 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
1539 pcdev->zoominfo.zoom_rate = 100;
1540 pcdev->fps_timer.istarted = false;
1542 /* ddl@rock-chips.com: capture list must be reset, because this list may be not empty,
1543 * if app havn't dequeue all videobuf before close camera device;
1545 INIT_LIST_HEAD(&pcdev->capture);
1547 ret = rk_camera_activate(pcdev,icd);
1550 /* ddl@rock-chips.com : v4l2_subdev is not created when ici->ops->add called in soc_camera_probe */
1552 sd = dev_get_drvdata(control);
1553 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_IOREQUEST,(void*)pcdev->pdata);
1555 ret = v4l2_subdev_call(sd,core, init, 0);
1559 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_CB_REGISTER,(void*)(&pcdev->icd_cb));
1562 pcdev->icd_init = 0;
1565 for (i=0; i<2; i++) {
1566 if (pcdev->icd_frmival[i].icd == icd)
1568 if (pcdev->icd_frmival[i].icd == NULL) {
1569 pcdev->icd_frmival[i].icd = icd;
1573 if (icd_catch == 0) {
1574 fival_list = pcdev->icd_frmival[0].fival_list;
1575 fival_nxt = fival_list;
1576 while(fival_nxt != NULL) {
1577 fival_nxt = fival_list->nxt;
1579 fival_list = fival_nxt;
1581 pcdev->icd_frmival[0].icd = icd;
1582 pcdev->icd_frmival[0].fival_list = kzalloc(sizeof(struct rk_camera_frmivalenum),GFP_KERNEL);
1585 mutex_unlock(&camera_lock);
1589 static void rk_camera_remove_device(struct soc_camera_device *icd)
1591 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1592 struct rk_camera_dev *pcdev = ici->priv;
1593 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1594 #if CAMERA_VIDEOBUF_ARM_ACCESS
1595 struct rk29_camera_vbinfo *vb_info;
1599 mutex_lock(&camera_lock);
1600 BUG_ON(icd != pcdev->icd);
1602 RKCAMERA_DG("%s driver detached from %s\n",RK29_CAM_DRV_NAME,dev_name(icd->pdev));
1604 /* ddl@rock-chips.com: Application will call VIDIOC_STREAMOFF before close device, but
1605 stream may be turn on again before close device, if suspend and resume happened. */
1606 if (read_cif_reg(pcdev->base,CIF_CIF_CTRL) & ENABLE_CAPTURE) {
1607 rk_camera_s_stream(icd,0);
1610 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_DEACTIVATE,NULL);
1611 //if stream off is not been executed,timer is running.
1612 if(pcdev->fps_timer.istarted){
1613 hrtimer_cancel(&pcdev->fps_timer.timer);
1614 pcdev->fps_timer.istarted = false;
1616 flush_work(&(pcdev->camera_reinit_work.work));
1617 flush_workqueue((pcdev->camera_wq));
1619 if (pcdev->camera_work) {
1620 kfree(pcdev->camera_work);
1621 pcdev->camera_work = NULL;
1622 pcdev->camera_work_count = 0;
1623 INIT_LIST_HEAD(&pcdev->camera_work_queue);
1625 rk_camera_deactivate(pcdev);
1626 #if CAMERA_VIDEOBUF_ARM_ACCESS
1627 if (pcdev->vbinfo) {
1628 vb_info = pcdev->vbinfo;
1629 for (i=0; i<pcdev->vbinfo_count; i++) {
1630 if (vb_info->vir_addr) {
1631 iounmap(vb_info->vir_addr);
1632 release_mem_region(vb_info->phy_addr, vb_info->size);
1633 memset(vb_info, 0x00, sizeof(struct rk29_camera_vbinfo));
1637 kfree(pcdev->vbinfo);
1638 pcdev->vbinfo = NULL;
1639 pcdev->vbinfo_count = 0;
1642 pcdev->active = NULL;
1644 pcdev->icd_cb.sensor_cb = NULL;
1645 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
1646 /* ddl@rock-chips.com: capture list must be reset, because this list may be not empty,
1647 * if app havn't dequeue all videobuf before close camera device;
1649 INIT_LIST_HEAD(&pcdev->capture);
1651 mutex_unlock(&camera_lock);
1652 RKCAMERA_DG("%s exit\n",__FUNCTION__);
1656 static int rk_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
1658 unsigned long bus_flags, camera_flags, common_flags;
1659 unsigned int cif_ctrl_val = 0;
1660 const struct soc_mbus_pixelfmt *fmt;
1662 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1663 struct rk_camera_dev *pcdev = ici->priv;
1665 RKCAMERA_DG("%s enter\n",__FUNCTION__);
1667 fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code);
1671 bus_flags = RK_CAM_BUS_PARAM;
1672 /* If requested data width is supported by the platform, use it */
1673 switch (fmt->bits_per_sample) {
1675 if (!(bus_flags & SOCAM_DATAWIDTH_10))
1679 if (!(bus_flags & SOCAM_DATAWIDTH_9))
1683 if (!(bus_flags & SOCAM_DATAWIDTH_8))
1690 if (icd->ops->query_bus_param)
1691 camera_flags = icd->ops->query_bus_param(icd);
1695 common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
1696 if (!common_flags) {
1698 goto RK_CAMERA_SET_BUS_PARAM_END;
1701 ret = icd->ops->set_bus_param(icd, common_flags);
1703 goto RK_CAMERA_SET_BUS_PARAM_END;
1705 cif_ctrl_val = read_cif_reg(pcdev->base,CIF_CIF_FOR);
1706 RKCAMERA_DG("cif_ctrl_val = 0x%x\n",cif_ctrl_val);
1707 if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) {
1709 write_cru_reg(CRU_PCLK_REG30, read_cru_reg(CRU_PCLK_REG30) | ENANABLE_INVERT_PCLK_CIF0);
1710 RKCAMERA_DG("enable cif0 pclk invert\n");
1712 write_cru_reg(CRU_PCLK_REG30, read_cru_reg(CRU_PCLK_REG30) | ENANABLE_INVERT_PCLK_CIF1);
1713 RKCAMERA_DG("enable cif1 pclk invert\n");
1717 write_cru_reg(CRU_PCLK_REG30, (read_cru_reg(CRU_PCLK_REG30) & 0xFFFFEFF ) | DISABLE_INVERT_PCLK_CIF0);
1718 RKCAMERA_DG("diable cif0 pclk invert\n");
1720 write_cru_reg(CRU_PCLK_REG30, (read_cru_reg(CRU_PCLK_REG30) & 0xFFFEFFF) | DISABLE_INVERT_PCLK_CIF1);
1721 RKCAMERA_DG("diable cif1 pclk invert\n");
1724 if (common_flags & SOCAM_HSYNC_ACTIVE_LOW) {
1725 cif_ctrl_val |= HSY_LOW_ACTIVE;
1727 cif_ctrl_val &= ~HSY_LOW_ACTIVE;
1729 if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH) {
1730 cif_ctrl_val |= VSY_HIGH_ACTIVE;
1732 cif_ctrl_val &= ~VSY_HIGH_ACTIVE;
1735 /* ddl@rock-chips.com : Don't enable capture here, enable in stream_on */
1736 //vip_ctrl_val |= ENABLE_CAPTURE;
1737 write_cif_reg(pcdev->base,CIF_CIF_FOR, cif_ctrl_val);
1738 RKCAMERA_DG("ctrl:0x%x CIF_CIF_FOR=%x \n",cif_ctrl_val,read_cif_reg(pcdev->base,CIF_CIF_FOR));
1740 RK_CAMERA_SET_BUS_PARAM_END:
1742 RKCAMERA_TR("rk_camera_set_bus_param ret = %d \n", ret);
1746 static int rk_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
1748 unsigned long bus_flags, camera_flags;
1751 bus_flags = RK_CAM_BUS_PARAM;
1752 if (icd->ops->query_bus_param) {
1753 camera_flags = icd->ops->query_bus_param(icd);
1757 ret = soc_camera_bus_param_compatible(camera_flags, bus_flags) ;
1760 dev_warn(icd->dev.parent,
1761 "Flags incompatible: camera %lx, host %lx\n",
1762 camera_flags, bus_flags);
1766 static const struct soc_mbus_pixelfmt rk_camera_formats[] = {
1768 .fourcc = V4L2_PIX_FMT_NV12,
1769 .name = "YUV420 NV12",
1770 .bits_per_sample = 8,
1771 .packing = SOC_MBUS_PACKING_1_5X8,
1772 .order = SOC_MBUS_ORDER_LE,
1774 .fourcc = V4L2_PIX_FMT_NV16,
1775 .name = "YUV422 NV16",
1776 .bits_per_sample = 8,
1777 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1778 .order = SOC_MBUS_ORDER_LE,
1780 .fourcc = V4L2_PIX_FMT_NV21,
1781 .name = "YUV420 NV21",
1782 .bits_per_sample = 8,
1783 .packing = SOC_MBUS_PACKING_1_5X8,
1784 .order = SOC_MBUS_ORDER_LE,
1786 .fourcc = V4L2_PIX_FMT_NV61,
1787 .name = "YUV422 NV61",
1788 .bits_per_sample = 8,
1789 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1790 .order = SOC_MBUS_ORDER_LE,
1792 .fourcc = V4L2_PIX_FMT_RGB565,
1794 .bits_per_sample = 8,
1795 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1796 .order = SOC_MBUS_ORDER_LE,
1798 .fourcc = V4L2_PIX_FMT_RGB24,
1800 .bits_per_sample = 8,
1801 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1802 .order = SOC_MBUS_ORDER_LE,
1806 static void rk_camera_setup_format(struct soc_camera_device *icd, __u32 host_pixfmt, enum v4l2_mbus_pixelcode icd_code, struct v4l2_rect *rect)
1808 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1809 struct rk_camera_dev *pcdev = ici->priv;
1810 unsigned int cif_fs = 0,cif_crop = 0;
1811 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;
1813 const struct soc_mbus_pixelfmt *fmt;
1814 fmt = soc_mbus_get_fmtdesc(icd_code);
1816 if((host_pixfmt == V4L2_PIX_FMT_RGB565) || (host_pixfmt == V4L2_PIX_FMT_RGB24)){
1817 if(fmt->fourcc == V4L2_PIX_FMT_NV12)
1818 host_pixfmt = V4L2_PIX_FMT_NV12;
1819 else if(fmt->fourcc == V4L2_PIX_FMT_NV21)
1820 host_pixfmt = V4L2_PIX_FMT_NV21;
1822 switch (host_pixfmt)
1824 case V4L2_PIX_FMT_NV16:
1825 cif_fmt_val &= ~YUV_OUTPUT_422;
1826 cif_fmt_val &= ~UV_STORAGE_ORDER_UVUV;
1827 pcdev->frame_inval = RK_CAM_FRAME_INVAL_DC;
1828 pcdev->pixfmt = host_pixfmt;
1830 case V4L2_PIX_FMT_NV61:
1831 cif_fmt_val &= ~YUV_OUTPUT_422;
1832 cif_fmt_val |= UV_STORAGE_ORDER_VUVU;
1833 pcdev->frame_inval = RK_CAM_FRAME_INVAL_DC;
1834 pcdev->pixfmt = host_pixfmt;
1836 case V4L2_PIX_FMT_NV12:
1837 cif_fmt_val |= YUV_OUTPUT_420;
1838 cif_fmt_val &= ~UV_STORAGE_ORDER_UVUV;
1839 if (pcdev->frame_inval != RK_CAM_FRAME_INVAL_INIT)
1840 pcdev->frame_inval = RK_CAM_FRAME_INVAL_INIT;
1841 pcdev->pixfmt = host_pixfmt;
1843 case V4L2_PIX_FMT_NV21:
1844 cif_fmt_val |= YUV_OUTPUT_420;
1845 cif_fmt_val |= UV_STORAGE_ORDER_VUVU;
1846 if (pcdev->frame_inval != RK_CAM_FRAME_INVAL_INIT)
1847 pcdev->frame_inval = RK_CAM_FRAME_INVAL_INIT;
1848 pcdev->pixfmt = host_pixfmt;
1850 default: /* ddl@rock-chips.com : vip output format is hold when pixfmt is invalidate */
1851 cif_fmt_val |= YUV_OUTPUT_422;
1856 case V4L2_MBUS_FMT_UYVY8_2X8:
1857 cif_fmt_val = YUV_INPUT_ORDER_UYVY(cif_fmt_val);
1859 case V4L2_MBUS_FMT_YUYV8_2X8:
1860 cif_fmt_val = YUV_INPUT_ORDER_YUYV(cif_fmt_val);
1862 case V4L2_MBUS_FMT_YVYU8_2X8:
1863 cif_fmt_val = YUV_INPUT_ORDER_YVYU(cif_fmt_val);
1865 case V4L2_MBUS_FMT_VYUY8_2X8:
1866 cif_fmt_val = YUV_INPUT_ORDER_VYUY(cif_fmt_val);
1869 cif_fmt_val = YUV_INPUT_ORDER_YUYV(cif_fmt_val);
1874 rk_camera_cif_reset(pcdev,true);
1876 write_cif_reg(pcdev->base,CIF_CIF_CTRL,AXI_BURST_16|MODE_ONEFRAME|DISABLE_CAPTURE); /* ddl@rock-chips.com : vip ahb burst 16 */
1877 write_cif_reg(pcdev->base,CIF_CIF_INTEN, 0x01|0x200); //capture complete interrupt enable
1879 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 */
1881 write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF);
1882 if((read_cif_reg(pcdev->base,CIF_CIF_CTRL) & MODE_PINGPONG)
1883 ||(read_cif_reg(pcdev->base,CIF_CIF_CTRL) & MODE_LINELOOP)) {
1885 } else{ // this is one frame mode
1886 cif_crop = (rect->left+ (rect->top<<16));
1887 cif_fs = ((rect->width ) + (rect->height<<16));
1890 write_cif_reg(pcdev->base,CIF_CIF_CROP, cif_crop);
1891 write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, cif_fs);
1892 write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH, rect->width);
1893 write_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS, 0x00000003);
1896 write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL,0x10);
1897 RKCAMERA_DG("crop:0x%x fs:0x%x cif_fmt_val:0x%x CIF_CIF_FOR:0x%x\n",cif_crop,cif_fs,cif_fmt_val,read_cif_reg(pcdev->base,CIF_CIF_FOR));
1901 static int rk_camera_get_formats(struct soc_camera_device *icd, unsigned int idx,
1902 struct soc_camera_format_xlate *xlate)
1904 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1905 struct device *dev = icd->dev.parent;
1906 int formats = 0, ret;
1907 enum v4l2_mbus_pixelcode code;
1908 const struct soc_mbus_pixelfmt *fmt;
1910 ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
1912 /* No more formats */
1915 fmt = soc_mbus_get_fmtdesc(code);
1917 dev_err(dev, "Invalid format code #%u: %d\n", idx, code);
1921 ret = rk_camera_try_bus_param(icd, fmt->bits_per_sample);
1926 case V4L2_MBUS_FMT_UYVY8_2X8:
1927 case V4L2_MBUS_FMT_YUYV8_2X8:
1928 case V4L2_MBUS_FMT_YVYU8_2X8:
1929 case V4L2_MBUS_FMT_VYUY8_2X8:
1932 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE != RK_CAM_SCALE_CROP_RGA)
1935 xlate->host_fmt = &rk_camera_formats[0];
1938 dev_dbg(dev, "Providing format %s using code %d\n",
1939 rk_camera_formats[0].name,code);
1944 xlate->host_fmt = &rk_camera_formats[1];
1947 dev_dbg(dev, "Providing format %s using code %d\n",
1948 rk_camera_formats[1].name,code);
1953 xlate->host_fmt = &rk_camera_formats[2];
1956 dev_dbg(dev, "Providing format %s using code %d\n",
1957 rk_camera_formats[2].name,code);
1962 xlate->host_fmt = &rk_camera_formats[3];
1965 dev_dbg(dev, "Providing format %s using code %d\n",
1966 rk_camera_formats[3].name,code);
1972 xlate->host_fmt = &rk_camera_formats[4];
1975 dev_dbg(dev, "Providing format %s using code %d\n",
1976 rk_camera_formats[4].name,code);
1980 xlate->host_fmt = &rk_camera_formats[5];
1983 dev_dbg(dev, "Providing format %s using code %d\n",
1984 rk_camera_formats[5].name,code);
1996 static void rk_camera_put_formats(struct soc_camera_device *icd)
2001 static int rk_camera_set_crop(struct soc_camera_device *icd,
2002 struct v4l2_crop *a)
2004 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
2005 struct v4l2_mbus_framefmt mf;
2006 u32 fourcc = icd->current_fmt->host_fmt->fourcc;
2009 ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
2013 if ((mf.width < (a->c.left + a->c.width)) || (mf.height < (a->c.top + a->c.height))) {
2015 mf.width = a->c.left + a->c.width;
2016 mf.height = a->c.top + a->c.height;
2018 v4l_bound_align_image(&mf.width, RK_CAM_W_MIN, RK_CAM_W_MAX, 1,
2019 &mf.height, RK_CAM_H_MIN, RK_CAM_H_MAX, 0,
2020 fourcc == V4L2_PIX_FMT_NV16 ?4 : 0);
2022 ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
2027 rk_camera_setup_format(icd, fourcc, mf.code, &a->c);
2029 icd->user_width = mf.width;
2030 icd->user_height = mf.height;
2034 static bool rk_camera_fmt_capturechk(struct v4l2_format *f)
2038 if (f->fmt.pix.priv == 0xfefe5a5a) {
2042 if ((f->fmt.pix.width == 1024) && (f->fmt.pix.height == 768)) {
2044 } else if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 1024)) {
2046 } else if ((f->fmt.pix.width == 1600) && (f->fmt.pix.height == 1200)) {
2048 } else if ((f->fmt.pix.width == 2048) && (f->fmt.pix.height == 1536)) {
2050 } else if ((f->fmt.pix.width == 2592) && (f->fmt.pix.height == 1944)) {
2052 } else if ((f->fmt.pix.width == 3264) && (f->fmt.pix.height == 2448)) {
2057 RKCAMERA_DG("%dx%d is capture format\n",f->fmt.pix.width, f->fmt.pix.height);
2060 static int rk_camera_set_fmt(struct soc_camera_device *icd,
2061 struct v4l2_format *f)
2063 struct device *dev = icd->dev.parent;
2064 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
2065 const struct soc_camera_format_xlate *xlate = NULL;
2066 struct soc_camera_host *ici =to_soc_camera_host(icd->dev.parent);
2067 struct rk_camera_dev *pcdev = ici->priv;
2068 struct v4l2_pix_format *pix = &f->fmt.pix;
2069 struct v4l2_mbus_framefmt mf;
2070 struct v4l2_rect rect;
2071 int ret,usr_w,usr_h;
2075 usr_h = pix->height;
2077 RKCAMERA_DG("enter width:%d height:%d\n",usr_w,usr_h);
2078 xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
2080 dev_err(dev, "Format %x not found\n", pix->pixelformat);
2082 goto RK_CAMERA_SET_FMT_END;
2085 /* ddl@rock-chips.com: sensor init code transmit in here after open */
2086 if (pcdev->icd_init == 0) {
2087 v4l2_subdev_call(sd,core, init, 0);
2088 pcdev->icd_init = 1;
2091 stream_on = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
2092 if (stream_on & ENABLE_CAPTURE)
2093 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (stream_on & (~ENABLE_CAPTURE)));
2095 mf.width = pix->width;
2096 mf.height = pix->height;
2097 mf.field = pix->field;
2098 mf.colorspace = pix->colorspace;
2099 mf.code = xlate->code;
2100 mf.reserved[0] = pix->priv; /* ddl@rock-chips.com : v0.3.3 */
2102 ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
2103 if (mf.code != xlate->code)
2107 if ((mf.width != usr_w) || (mf.height != usr_h)) {
2109 if (unlikely((mf.width <16) || (mf.width > 8190) || (mf.height < 16) || (mf.height > 8190))) {
2110 RKCAMERA_TR("Senor and IPP both invalid source resolution(%dx%d)\n",mf.width,mf.height);
2112 goto RK_CAMERA_SET_FMT_END;
2114 if (unlikely((usr_w <16)||(usr_h < 16))) {
2115 RKCAMERA_TR("Senor and IPP both invalid destination resolution(%dx%d)\n",usr_w,usr_h);
2117 goto RK_CAMERA_SET_FMT_END;
2120 if((mf.width*10/mf.height) != (usr_w*10/usr_h)){
2121 ratio = ((mf.width*10/usr_w) >= (mf.height*10/usr_h))?(mf.height*10/usr_h):(mf.width*10/usr_w);
2122 pcdev->host_width = ratio*usr_w/10;
2123 pcdev->host_height = ratio*usr_h/10;
2124 //for ipp ,need 4 bit alligned.
2125 pcdev->host_width &= ~CROP_ALIGN_BYTES;
2126 pcdev->host_height &= ~CROP_ALIGN_BYTES;
2127 RKCAMERA_DG("ratio = %d ,host:%d*%d\n",ratio,pcdev->host_width,pcdev->host_height);
2128 } else { // needn't crop ,just scaled by ipp
2129 pcdev->host_width = mf.width;
2130 pcdev->host_height = mf.height;
2133 pcdev->host_width = usr_w;
2134 pcdev->host_height = usr_h;
2139 RKCAMERA_DG("host:%d*%d , sensor output:%d*%d,user demand:%d*%d\n",
2140 pcdev->host_width,pcdev->host_height,mf.width,mf.height,usr_w,usr_h);
2141 rect.width = pcdev->host_width;
2142 rect.height = pcdev->host_height;
2143 rect.left = ((mf.width-pcdev->host_width )>>1)&(~0x01);
2144 rect.top = ((mf.height-pcdev->host_height)>>1)&(~0x01);
2145 pcdev->host_left = rect.left;
2146 pcdev->host_top = rect.top;
2148 down(&pcdev->zoominfo.sem);
2150 pcdev->zoominfo.a.c.left = 0;
2151 pcdev->zoominfo.a.c.top = 0;
2152 pcdev->zoominfo.a.c.width = pcdev->host_width*100/pcdev->zoominfo.zoom_rate;
2153 pcdev->zoominfo.a.c.width &= ~CROP_ALIGN_BYTES;
2154 pcdev->zoominfo.a.c.height = pcdev->host_height*100/pcdev->zoominfo.zoom_rate;
2155 pcdev->zoominfo.a.c.height &= ~CROP_ALIGN_BYTES;
2156 pcdev->zoominfo.vir_width = pcdev->zoominfo.a.c.width;
2157 pcdev->zoominfo.vir_height = pcdev->zoominfo.a.c.height;
2158 //recalculate the CIF width & height
2159 rect.width = pcdev->zoominfo.a.c.width ;
2160 rect.height = pcdev->zoominfo.a.c.height;
2161 rect.left = ((((pcdev->host_width - pcdev->zoominfo.a.c.width)>>1))+pcdev->host_left)&(~0x01);
2162 rect.top = ((((pcdev->host_height - pcdev->zoominfo.a.c.height)>>1))+pcdev->host_top)&(~0x01);
2164 pcdev->zoominfo.a.c.width = pcdev->host_width*100/pcdev->zoominfo.zoom_rate;
2165 pcdev->zoominfo.a.c.width &= ~CROP_ALIGN_BYTES;
2166 pcdev->zoominfo.a.c.height = pcdev->host_height*100/pcdev->zoominfo.zoom_rate;
2167 pcdev->zoominfo.a.c.height &= ~CROP_ALIGN_BYTES;
2168 //now digital zoom use ipp to do crop and scale
2169 if(pcdev->zoominfo.zoom_rate != 100){
2170 pcdev->zoominfo.a.c.left = ((pcdev->host_width - pcdev->zoominfo.a.c.width)>>1)&(~0x01);
2171 pcdev->zoominfo.a.c.top = ((pcdev->host_height - pcdev->zoominfo.a.c.height)>>1)&(~0x01);
2173 pcdev->zoominfo.a.c.left = 0;
2174 pcdev->zoominfo.a.c.top = 0;
2176 pcdev->zoominfo.vir_width = pcdev->host_width;
2177 pcdev->zoominfo.vir_height = pcdev->host_height;
2179 up(&pcdev->zoominfo.sem);
2181 /* ddl@rock-chips.com: IPP work limit check */
2182 if ((pcdev->zoominfo.a.c.width != usr_w) || (pcdev->zoominfo.a.c.height != usr_h)) {
2183 if (usr_w > 0x7f0) {
2184 if (((usr_w>>1)&0x3f) && (((usr_w>>1)&0x3f) <= 8)) {
2185 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));
2187 goto RK_CAMERA_SET_FMT_END;
2190 if ((usr_w&0x3f) && ((usr_w&0x3f) <= 8)) {
2191 RKCAMERA_TR("IPP Destination resolution(%dx%d, %d mod 64=%d is <= 8)",usr_w,usr_h, usr_w, (int)(usr_w&0x3f));
2193 goto RK_CAMERA_SET_FMT_END;
2197 RKCAMERA_DG(" %s icd width:%d user width:%d (zoom: %dx%d@(%d,%d)->%dx%d)\n",xlate->host_fmt->name,
2198 rect.width, pix->width, pcdev->zoominfo.a.c.width,pcdev->zoominfo.a.c.height, pcdev->zoominfo.a.c.left,pcdev->zoominfo.a.c.top,
2199 pix->width, pix->height);
2200 rk_camera_setup_format(icd, pix->pixelformat, mf.code, &rect);
2202 if (CAM_IPPWORK_IS_EN()) {
2203 BUG_ON(pcdev->vipmem_phybase == 0);
2206 pix->height = usr_h;
2207 pix->field = mf.field;
2208 pix->colorspace = mf.colorspace;
2209 icd->current_fmt = xlate;
2210 pcdev->icd_width = mf.width;
2211 pcdev->icd_height = mf.height;
2214 RK_CAMERA_SET_FMT_END:
2215 if (stream_on & ENABLE_CAPTURE)
2216 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL) | ENABLE_CAPTURE));
2218 RKCAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
2222 static int rk_camera_try_fmt(struct soc_camera_device *icd,
2223 struct v4l2_format *f)
2225 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2226 struct rk_camera_dev *pcdev = ici->priv;
2227 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
2228 const struct soc_camera_format_xlate *xlate;
2229 struct v4l2_pix_format *pix = &f->fmt.pix;
2230 __u32 pixfmt = pix->pixelformat;
2231 int ret,usr_w,usr_h,i;
2232 bool is_capture = rk_camera_fmt_capturechk(f);
2233 bool vipmem_is_overflow = false;
2234 struct v4l2_mbus_framefmt mf;
2235 int bytes_per_line_host;
2238 usr_h = pix->height;
2240 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
2242 dev_err(icd->dev.parent, "Format (%c%c%c%c) not found\n", pixfmt & 0xFF, (pixfmt >> 8) & 0xFF,
2243 (pixfmt >> 16) & 0xFF, (pixfmt >> 24) & 0xFF);
2245 RKCAMERA_TR("%s(version:%c%c%c) support format:\n",rk_cam_driver_description,(RK_CAM_VERSION_CODE&0xff0000)>>16,
2246 (RK_CAM_VERSION_CODE&0xff00)>>8,(RK_CAM_VERSION_CODE&0xff));
2247 for (i = 0; i < icd->num_user_formats; i++)
2248 RKCAMERA_TR("(%c%c%c%c)-%s\n",
2249 icd->user_formats[i].host_fmt->fourcc & 0xFF, (icd->user_formats[i].host_fmt->fourcc >> 8) & 0xFF,
2250 (icd->user_formats[i].host_fmt->fourcc >> 16) & 0xFF, (icd->user_formats[i].host_fmt->fourcc >> 24) & 0xFF,
2251 icd->user_formats[i].host_fmt->name);
2252 goto RK_CAMERA_TRY_FMT_END;
2254 /* limit to rk29 hardware capabilities */
2255 v4l_bound_align_image(&pix->width, RK_CAM_W_MIN, RK_CAM_W_MAX, 1,
2256 &pix->height, RK_CAM_H_MIN, RK_CAM_H_MAX, 0,
2257 pixfmt == V4L2_PIX_FMT_NV16 ? 4 : 0);
2259 pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
2261 if (pix->bytesperline < 0)
2262 return pix->bytesperline;
2264 /* limit to sensor capabilities */
2265 memset(&mf,0x00,sizeof(struct v4l2_mbus_framefmt));
2266 mf.width = pix->width;
2267 mf.height = pix->height;
2268 mf.field = pix->field;
2269 mf.colorspace = pix->colorspace;
2270 mf.code = xlate->code;
2271 /* ddl@rock-chips.com : It is query max resolution only. */
2272 if ((usr_w == 10000) && (usr_h == 10000)) {
2273 mf.reserved[6] = 0xfefe5a5a;
2276 ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
2278 goto RK_CAMERA_TRY_FMT_END;
2281 if((usr_w == 10000) && (usr_h == 10000)) {
2282 pix->width = mf.width;
2283 pix->height = mf.height;
2284 RKCAMERA_DG("Sensor resolution : %dx%d\n",mf.width,mf.height);
2285 goto RK_CAMERA_TRY_FMT_END;
2287 RKCAMERA_DG("user demand: %dx%d sensor output: %dx%d \n",usr_w,usr_h,mf.width,mf.height);
2290 if ((mf.width != usr_w) || (mf.height != usr_h)) {
2291 bytes_per_line_host = soc_mbus_bytes_per_line(mf.width,icd->current_fmt->host_fmt);
2293 vipmem_is_overflow = (PAGE_ALIGN(bytes_per_line_host*mf.height) > pcdev->vipmem_size);
2295 /* Assume preview buffer minimum is 4 */
2296 vipmem_is_overflow = (PAGE_ALIGN(bytes_per_line_host*mf.height)*4 > pcdev->vipmem_size);
2298 if (vipmem_is_overflow == false) {
2300 pix->height = usr_h;
2302 RKCAMERA_TR("vipmem for IPP is overflow, This resolution(%dx%d -> %dx%d) is invalidate!\n",mf.width,mf.height,usr_w,usr_h);
2303 pix->width = mf.width;
2304 pix->height = mf.height;
2306 /* ddl@rock-chips.com: Invalidate these code, because sensor need interpolate */
2308 if ((mf.width < usr_w) || (mf.height < usr_h)) {
2309 if (((usr_w>>1) > mf.width) || ((usr_h>>1) > mf.height)) {
2310 RKCAMERA_TR("The aspect ratio(%dx%d/%dx%d) is bigger than 2 !\n",mf.width,mf.height,usr_w,usr_h);
2311 pix->width = mf.width;
2312 pix->height = mf.height;
2318 pix->colorspace = mf.colorspace;
2321 case V4L2_FIELD_ANY:
2322 case V4L2_FIELD_NONE:
2323 pix->field = V4L2_FIELD_NONE;
2326 /* TODO: support interlaced at least in pass-through mode */
2327 dev_err(icd->dev.parent, "Field type %d unsupported.\n",
2329 goto RK_CAMERA_TRY_FMT_END;
2332 RK_CAMERA_TRY_FMT_END:
2334 RKCAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
2338 static int rk_camera_reqbufs(struct soc_camera_device *icd,
2339 struct v4l2_requestbuffers *p)
2343 /* This is for locking debugging only. I removed spinlocks and now I
2344 * check whether .prepare is ever called on a linked buffer, or whether
2345 * a dma IRQ can occur for an in-work or unlinked buffer. Until now
2346 * it hadn't triggered */
2347 for (i = 0; i < p->count; i++) {
2348 struct rk_camera_buffer *buf = container_of(icd->vb_vidq.bufs[i],
2349 struct rk_camera_buffer, vb);
2351 INIT_LIST_HEAD(&buf->vb.queue);
2357 static unsigned int rk_camera_poll(struct file *file, poll_table *pt)
2359 struct soc_camera_device *icd = file->private_data;
2360 struct rk_camera_buffer *buf;
2362 buf = list_entry(icd->vb_vidq.stream.next, struct rk_camera_buffer,
2365 poll_wait(file, &buf->vb.done, pt);
2367 if (buf->vb.state == VIDEOBUF_DONE ||
2368 buf->vb.state == VIDEOBUF_ERROR)
2369 return POLLIN|POLLRDNORM;
2374 static int rk_camera_querycap(struct soc_camera_host *ici,
2375 struct v4l2_capability *cap)
2377 struct rk_camera_dev *pcdev = ici->priv;
2378 struct rkcamera_platform_data *new_camera;
2379 char orientation[5];
2382 strlcpy(cap->card, dev_name(pcdev->icd->pdev), sizeof(cap->card));
2383 memset(orientation,0x00,sizeof(orientation));
2384 for (i=0; i<RK_CAM_NUM;i++) {
2385 if ((pcdev->pdata->info[i].dev_name!=NULL) && (strcmp(dev_name(pcdev->icd->pdev), pcdev->pdata->info[i].dev_name) == 0)) {
2386 sprintf(orientation,"-%d",pcdev->pdata->info[i].orientation);
2391 new_camera = pcdev->pdata->register_dev_new;
2392 while (strstr(new_camera->dev_name,"end")==NULL) {
2393 if (strcmp(dev_name(pcdev->icd->pdev), new_camera->dev_name) == 0) {
2394 sprintf(orientation,"-%d",new_camera->orientation);
2399 if (orientation[0] != '-') {
2400 RKCAMERA_TR("%s: %s is not registered in rk29_camera_platform_data, orientation apply default value",__FUNCTION__,dev_name(pcdev->icd->pdev));
2401 if (strstr(dev_name(pcdev->icd->pdev),"front"))
2402 strcat(cap->card,"-270");
2404 strcat(cap->card,"-90");
2406 strcat(cap->card,orientation);
2408 cap->version = RK_CAM_VERSION_CODE;
2409 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
2413 static int rk_camera_suspend(struct soc_camera_device *icd, pm_message_t state)
2415 struct soc_camera_host *ici =
2416 to_soc_camera_host(icd->dev.parent);
2417 struct rk_camera_dev *pcdev = ici->priv;
2418 struct v4l2_subdev *sd;
2421 mutex_lock(&camera_lock);
2422 if ((pcdev->icd == icd) && (icd->ops->suspend)) {
2423 rk_camera_s_stream(icd, 0);
2424 sd = soc_camera_to_subdev(icd);
2425 v4l2_subdev_call(sd, video, s_stream, 0);
2426 ret = icd->ops->suspend(icd, state);
2428 pcdev->reginfo_suspend.cifCtrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
2429 pcdev->reginfo_suspend.cifCrop = read_cif_reg(pcdev->base,CIF_CIF_CROP);
2430 pcdev->reginfo_suspend.cifFs = read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE);
2431 pcdev->reginfo_suspend.cifIntEn = read_cif_reg(pcdev->base,CIF_CIF_INTEN);
2432 pcdev->reginfo_suspend.cifFmt= read_cif_reg(pcdev->base,CIF_CIF_FOR);
2433 pcdev->reginfo_suspend.cifVirWidth = read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH);
2434 pcdev->reginfo_suspend.cifScale= read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL);
2436 pcdev->reginfo_suspend.Inval = Reg_Validate;
2437 rk_camera_deactivate(pcdev);
2439 RKCAMERA_DG("%s Enter Success...\n", __FUNCTION__);
2441 RKCAMERA_DG("%s icd has been deattach, don't need enter suspend\n", __FUNCTION__);
2443 mutex_unlock(&camera_lock);
2447 static int rk_camera_resume(struct soc_camera_device *icd)
2449 struct soc_camera_host *ici =
2450 to_soc_camera_host(icd->dev.parent);
2451 struct rk_camera_dev *pcdev = ici->priv;
2452 struct v4l2_subdev *sd;
2455 mutex_lock(&camera_lock);
2456 if ((pcdev->icd == icd) && (icd->ops->resume)) {
2457 if (pcdev->reginfo_suspend.Inval == Reg_Validate) {
2458 rk_camera_activate(pcdev, icd);
2459 write_cif_reg(pcdev->base,CIF_CIF_CTRL, pcdev->reginfo_suspend.cifCtrl&~ENABLE_CAPTURE);
2460 write_cif_reg(pcdev->base,CIF_CIF_INTEN, pcdev->reginfo_suspend.cifIntEn);
2461 write_cif_reg(pcdev->base,CIF_CIF_CROP, pcdev->reginfo_suspend.cifCrop);
2462 write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, pcdev->reginfo_suspend.cifFs);
2463 write_cif_reg(pcdev->base,CIF_CIF_FOR, pcdev->reginfo_suspend.cifFmt);
2464 write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH,pcdev->reginfo_suspend.cifVirWidth);
2465 write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL, pcdev->reginfo_suspend.cifScale);
2466 rk_videobuf_capture(pcdev->active,pcdev);
2467 rk_camera_s_stream(icd, 1);
2468 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
2470 RKCAMERA_TR("Resume fail, vip register recored is invalidate!!\n");
2471 goto rk_camera_resume_end;
2474 ret = icd->ops->resume(icd);
2475 sd = soc_camera_to_subdev(icd);
2476 v4l2_subdev_call(sd, video, s_stream, 1);
2478 RKCAMERA_DG("%s Enter success\n",__FUNCTION__);
2480 RKCAMERA_DG("%s icd has been deattach, don't need enter resume\n", __FUNCTION__);
2483 rk_camera_resume_end:
2484 mutex_unlock(&camera_lock);
2488 static void rk_camera_reinit_work(struct work_struct *work)
2490 struct v4l2_subdev *sd;
2491 struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
2492 struct rk_camera_dev *pcdev = camera_work->pcdev;
2493 struct soc_camera_link *tmp_soc_cam_link;
2495 unsigned long flags = 0;
2496 if(pcdev->icd == NULL)
2498 sd = soc_camera_to_subdev(pcdev->icd);
2499 tmp_soc_cam_link = to_soc_camera_link(pcdev->icd);
2502 RKCAMERA_TR("CIF_CIF_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CTRL));
2503 RKCAMERA_TR("CIF_CIF_INTEN = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTEN));
2504 RKCAMERA_TR("CIF_CIF_INTSTAT = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTSTAT));
2505 RKCAMERA_TR("CIF_CIF_FOR = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_FOR));
2506 RKCAMERA_TR("CIF_CIF_CROP = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CROP));
2507 RKCAMERA_TR("CIF_CIF_SET_SIZE = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE));
2508 RKCAMERA_TR("CIF_CIF_SCL_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL));
2509 RKCAMERA_TR("CRU_PCLK_REG30 = 0X%x\n",read_cru_reg(CRU_PCLK_REG30));
2510 RKCAMERA_TR("CIF_CIF_LAST_LINE = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_LINE));
2512 RKCAMERA_TR("CIF_CIF_LAST_PIX = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_PIX));
2513 RKCAMERA_TR("CIF_CIF_VIR_LINE_WIDTH = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH));
2514 RKCAMERA_TR("CIF_CIF_LINE_NUM_ADDR = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LINE_NUM_ADDR));
2515 RKCAMERA_TR("CIF_CIF_FRM0_ADDR_Y = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y));
2516 RKCAMERA_TR("CIF_CIF_FRM0_ADDR_UV = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV));
2517 RKCAMERA_TR("CIF_CIF_FRAME_STATUS = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS));
2520 pcdev->stop_cif = true;
2521 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL)&(~ENABLE_CAPTURE)));
2522 RKCAMERA_DG("the reinit times = %d\n",pcdev->reinit_times);
2524 if(pcdev->video_vq && pcdev->video_vq->irqlock){
2525 spin_lock_irqsave(pcdev->video_vq->irqlock, flags);
2526 for (index = 0; index < VIDEO_MAX_FRAME; index++) {
2527 if (NULL == pcdev->video_vq->bufs[index])
2530 if (pcdev->video_vq->bufs[index]->state == VIDEOBUF_QUEUED) {
2531 list_del_init(&pcdev->video_vq->bufs[index]->queue);
2532 pcdev->video_vq->bufs[index]->state = VIDEOBUF_NEEDS_INIT;
2533 wake_up_all(&pcdev->video_vq->bufs[index]->done);
2534 printk("wake up video buffer index = %d !!!\n",index);
2537 spin_unlock_irqrestore(pcdev->video_vq->irqlock, flags);
2539 RKCAMERA_TR("video queue has somthing wrong !!\n");
2542 RKCAMERA_TR("the %d reinit times ,wake up video buffers!\n ",pcdev->reinit_times);
2544 static enum hrtimer_restart rk_camera_fps_func(struct hrtimer *timer)
2546 struct rk_camera_frmivalenum *fival_nxt=NULL,*fival_pre=NULL, *fival_rec=NULL;
2547 struct rk_camera_timer *fps_timer = container_of(timer, struct rk_camera_timer, timer);
2548 struct rk_camera_dev *pcdev = fps_timer->pcdev;
2550 // static unsigned int last_fps = 0;
2551 struct soc_camera_link *tmp_soc_cam_link;
2552 tmp_soc_cam_link = to_soc_camera_link(pcdev->icd);
2554 RKCAMERA_DG("rk_camera_fps_func fps:0x%x\n",pcdev->fps);
2555 if ((pcdev->fps < 1) || (pcdev->last_fps == pcdev->fps)) {
2556 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);
2557 pcdev->camera_reinit_work.pcdev = pcdev;
2558 //INIT_WORK(&(pcdev->camera_reinit_work.work), rk_camera_reinit_work);
2559 pcdev->reinit_times++;
2560 queue_work(pcdev->camera_wq,&(pcdev->camera_reinit_work.work));
2561 } else if(!pcdev->timer_get_fps) {
2562 pcdev->timer_get_fps = true;
2563 for (i=0; i<2; i++) {
2564 if (pcdev->icd == pcdev->icd_frmival[i].icd) {
2565 fival_nxt = pcdev->icd_frmival[i].fival_list;
2570 fival_pre = fival_nxt;
2571 while (fival_nxt != NULL) {
2573 RKCAMERA_DG("%s %c%c%c%c %dx%d framerate : %d/%d\n", dev_name(&pcdev->icd->dev),
2574 fival_nxt->fival.pixel_format & 0xFF, (fival_nxt->fival.pixel_format >> 8) & 0xFF,
2575 (fival_nxt->fival.pixel_format >> 16) & 0xFF, (fival_nxt->fival.pixel_format >> 24),
2576 fival_nxt->fival.width, fival_nxt->fival.height, fival_nxt->fival.discrete.denominator,
2577 fival_nxt->fival.discrete.numerator);
2579 if (((fival_nxt->fival.pixel_format == pcdev->pixfmt)
2580 && (fival_nxt->fival.height == pcdev->icd->user_height)
2581 && (fival_nxt->fival.width == pcdev->icd->user_width))
2582 || (fival_nxt->fival.discrete.denominator == 0)) {
2584 if (fival_nxt->fival.discrete.denominator == 0) {
2585 fival_nxt->fival.index = 0;
2586 fival_nxt->fival.width = pcdev->icd->user_width;
2587 fival_nxt->fival.height= pcdev->icd->user_height;
2588 fival_nxt->fival.pixel_format = pcdev->pixfmt;
2589 fival_nxt->fival.discrete.denominator = pcdev->frame_interval;
2590 fival_nxt->fival.reserved[1] = (pcdev->icd_width<<16)
2591 |(pcdev->icd_height);
2592 fival_nxt->fival.discrete.numerator = 1000000;
2593 fival_nxt->fival.type = V4L2_FRMIVAL_TYPE_DISCRETE;
2596 fival_rec = fival_nxt;
2598 fival_pre = fival_nxt;
2599 fival_nxt = fival_nxt->nxt;
2602 if ((rec_flag == 0) && fival_pre) {
2603 fival_pre->nxt = kzalloc(sizeof(struct rk_camera_frmivalenum), GFP_ATOMIC);
2604 if (fival_pre->nxt != NULL) {
2605 fival_pre->nxt->fival.index = fival_pre->fival.index++;
2606 fival_pre->nxt->fival.width = pcdev->icd->user_width;
2607 fival_pre->nxt->fival.height= pcdev->icd->user_height;
2608 fival_pre->nxt->fival.pixel_format = pcdev->pixfmt;
2610 fival_pre->nxt->fival.discrete.denominator = pcdev->frame_interval;
2611 fival_pre->nxt->fival.reserved[1] = (pcdev->icd_width<<16)
2612 |(pcdev->icd_height);
2613 fival_pre->nxt->fival.discrete.numerator = 1000000;
2614 fival_pre->nxt->fival.type = V4L2_FRMIVAL_TYPE_DISCRETE;
2616 fival_rec = fival_pre->nxt;
2620 pcdev->last_fps = pcdev->fps ;
2621 pcdev->fps_timer.timer.node.expires= ktime_add_us(pcdev->fps_timer.timer.node.expires, ktime_to_us(ktime_set(3, 0)));
2622 pcdev->fps_timer.timer._softexpires= ktime_add_us(pcdev->fps_timer.timer._softexpires, ktime_to_us(ktime_set(3, 0)));
2623 //return HRTIMER_NORESTART;
2624 if(pcdev->reinit_times >=2)
2625 return HRTIMER_NORESTART;
2627 return HRTIMER_RESTART;
2629 static int rk_camera_s_stream(struct soc_camera_device *icd, int enable)
2631 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2632 struct rk_camera_dev *pcdev = ici->priv;
2635 unsigned long flags;
2637 WARN_ON(pcdev->icd != icd);
2639 cif_ctrl_val = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
2642 pcdev->last_fps = 0;
2643 pcdev->frame_interval = 0;
2644 hrtimer_cancel(&(pcdev->fps_timer.timer));
2645 pcdev->fps_timer.pcdev = pcdev;
2646 pcdev->timer_get_fps = false;
2647 pcdev->reinit_times = 0;
2648 pcdev->stop_cif = false;
2650 cif_ctrl_val |= ENABLE_CAPTURE;
2651 write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val);
2652 hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL);
2653 pcdev->fps_timer.istarted = true;
2655 //cancel timer before stop cif
2656 ret = hrtimer_cancel(&pcdev->fps_timer.timer);
2657 pcdev->fps_timer.istarted = false;
2658 flush_work(&(pcdev->camera_reinit_work.work));
2660 cif_ctrl_val &= ~ENABLE_CAPTURE;
2661 spin_lock_irqsave(&pcdev->lock, flags);
2662 write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val);
2663 pcdev->stop_cif = true;
2664 spin_unlock_irqrestore(&pcdev->lock, flags);
2665 flush_workqueue((pcdev->camera_wq));
2666 RKCAMERA_DG("STREAM_OFF cancel timer and flush work:0x%x \n", ret);
2668 //must be reinit,or will be somthing wrong in irq process.
2669 if(enable == false) {
2670 pcdev->active = NULL;
2671 INIT_LIST_HEAD(&pcdev->capture);
2673 RKCAMERA_DG("s_stream: enable : 0x%x , CIF_CIF_CTRL = 0x%x\n",enable,read_cif_reg(pcdev->base,CIF_CIF_CTRL));
2676 int rk_camera_enum_frameintervals(struct soc_camera_device *icd, struct v4l2_frmivalenum *fival)
2678 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2679 struct rk_camera_dev *pcdev = ici->priv;
2680 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
2681 struct rk_camera_frmivalenum *fival_list = NULL;
2682 struct v4l2_frmivalenum *fival_head = NULL;
2683 struct rkcamera_platform_data *new_camera;
2684 int i,ret = 0,index;
2685 const struct soc_camera_format_xlate *xlate;
2686 struct v4l2_mbus_framefmt mf;
2689 index = fival->index & 0x00ffffff;
2690 if ((fival->index & 0xff000000) == 0xff000000) { /* ddl@rock-chips.com: detect framerate */
2691 for (i=0; i<2; i++) {
2692 if (pcdev->icd_frmival[i].icd == icd) {
2693 fival_list = pcdev->icd_frmival[i].fival_list;
2697 if (fival_list != NULL) {
2699 while (fival_list != NULL) {
2700 if ((fival->pixel_format == fival_list->fival.pixel_format)
2701 && (fival->height == fival_list->fival.height)
2702 && (fival->width == fival_list->fival.width)) {
2707 fival_list = fival_list->nxt;
2710 if ((i==index) && (fival_list != NULL)) {
2711 memcpy(fival, &fival_list->fival, sizeof(struct v4l2_frmivalenum));
2716 RKCAMERA_TR("%s: fival_list is NULL\n",__FUNCTION__);
2721 for (i=0; i<RK_CAM_NUM; i++) {
2722 if (pcdev->pdata->info[i].dev_name && (strcmp(dev_name(pcdev->icd->pdev),pcdev->pdata->info[i].dev_name) == 0)) {
2723 fival_head = pcdev->pdata->info[i].fival;
2729 while (fival_head->width && fival_head->height) {
2730 if ((fival->pixel_format == fival_head->pixel_format)
2731 && (fival->height == fival_head->height)
2732 && (fival->width == fival_head->width)) {
2741 if ((i == index) && (fival->height == fival_head->height) && (fival->width == fival_head->width)) {
2742 memcpy(fival, fival_head, sizeof(struct v4l2_frmivalenum));
2744 pixfmt = fival->pixel_format; /* ddl@rock-chips.com: v0.3.9 */
2745 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
2746 memset(&mf,0x00,sizeof(struct v4l2_mbus_framefmt));
2747 mf.width = fival->width;
2748 mf.height = fival->height;
2749 mf.code = xlate->code;
2751 v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
2753 fival->reserved[1] = (mf.width<<16)|(mf.height);
2755 RKCAMERA_DG("%s %dx%d@%c%c%c%c framerate : %d/%d\n", dev_name(pcdev->icd->pdev),
2756 fival->width, fival->height,
2757 fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
2758 (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
2759 fival->discrete.denominator,fival->discrete.numerator);
2762 RKCAMERA_TR("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(pcdev->icd->pdev),
2763 fival->width,fival->height,
2764 fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
2765 (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
2768 RKCAMERA_DG("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(pcdev->icd->pdev),
2769 fival->width,fival->height,
2770 fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
2771 (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
2774 goto rk_camera_enum_frameintervals_end;
2778 new_camera = pcdev->pdata->register_dev_new;
2779 while (strstr(new_camera->dev_name,"end")==NULL) {
2780 if (strcmp(new_camera->dev_name, dev_name(pcdev->icd->pdev)) == 0) {
2788 printk(KERN_ERR "%s(%d): %s have not found in new_camera[] and rk_camera_platform_data!",
2789 __FUNCTION__,__LINE__,dev_name(pcdev->icd->pdev));
2792 pixfmt = fival->pixel_format; /* ddl@rock-chips.com: v0.3.9 */
2793 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
2794 memset(&mf,0x00,sizeof(struct v4l2_mbus_framefmt));
2795 mf.width = fival->width;
2796 mf.height = fival->height;
2797 mf.code = xlate->code;
2799 v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
2801 fival->discrete.numerator= 1000;
2802 fival->discrete.denominator = 15000;
2803 fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
2804 fival->reserved[1] = (mf.width<<16)|(mf.height);
2808 rk_camera_enum_frameintervals_end:
2812 static int rk_camera_set_digit_zoom(struct soc_camera_device *icd,
2813 const struct v4l2_queryctrl *qctrl, int zoom_rate)
2816 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2817 struct rk_camera_dev *pcdev = ici->priv;
2819 unsigned long tmp_cifctrl;
2822 //change the crop and scale parameters
2825 a.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2826 //a.c.width = pcdev->host_width*100/zoom_rate;
2827 a.c.width = pcdev->host_width*100/zoom_rate;
2828 a.c.width &= ~CROP_ALIGN_BYTES;
2829 a.c.height = pcdev->host_height*100/zoom_rate;
2830 a.c.height &= ~CROP_ALIGN_BYTES;
2831 a.c.left = (((pcdev->host_width - a.c.width)>>1)+pcdev->host_left)&(~0x01);
2832 a.c.top = (((pcdev->host_height - a.c.height)>>1)+pcdev->host_top)&(~0x01);
2833 pcdev->stop_cif = true;
2834 tmp_cifctrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
2835 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl & ~ENABLE_CAPTURE));
2836 hrtimer_cancel(&(pcdev->fps_timer.timer));
2837 flush_workqueue((pcdev->camera_wq));
2839 down(&pcdev->zoominfo.sem);
2840 pcdev->zoominfo.a.c.left = 0;
2841 pcdev->zoominfo.a.c.top = 0;
2842 pcdev->zoominfo.a.c.width = a.c.width;
2843 pcdev->zoominfo.a.c.height = a.c.height;
2844 pcdev->zoominfo.vir_width = pcdev->zoominfo.a.c.width;
2845 pcdev->zoominfo.vir_height = pcdev->zoominfo.a.c.height;
2846 pcdev->frame_inval = 1;
2847 write_cif_reg(pcdev->base,CIF_CIF_CROP, (a.c.left + (a.c.top<<16)));
2848 write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, ((a.c.width ) + (a.c.height<<16)));
2849 write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH, a.c.width);
2850 write_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS, 0x00000002);//frame1 has been ready to receive data,frame 2 is not used
2852 rk_videobuf_capture(pcdev->active,pcdev);
2853 if(tmp_cifctrl & ENABLE_CAPTURE)
2854 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl | ENABLE_CAPTURE));
2855 up(&pcdev->zoominfo.sem);
2857 pcdev->stop_cif = false;
2858 hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL);
2859 RKCAMERA_DG("zoom_rate:%d (%dx%d at (%d,%d)-> %dx%d)\n", zoom_rate,a.c.width, a.c.height, a.c.left, a.c.top, icd->user_width, icd->user_height );
2861 a.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2862 a.c.width = pcdev->host_width*100/zoom_rate;
2863 a.c.width &= ~CROP_ALIGN_BYTES;
2864 a.c.height = pcdev->host_height*100/zoom_rate;
2865 a.c.height &= ~CROP_ALIGN_BYTES;
2866 a.c.left = (pcdev->host_width - a.c.width)>>1;
2867 a.c.top = (pcdev->host_height - a.c.height)>>1;
2869 down(&pcdev->zoominfo.sem);
2870 pcdev->zoominfo.a.c.height = a.c.height;
2871 pcdev->zoominfo.a.c.width = a.c.width;
2872 pcdev->zoominfo.a.c.top = a.c.top;
2873 pcdev->zoominfo.a.c.left = a.c.left;
2874 pcdev->zoominfo.vir_width = pcdev->host_width;
2875 pcdev->zoominfo.vir_height= pcdev->host_height;
2876 up(&pcdev->zoominfo.sem);
2878 RKCAMERA_DG("zoom_rate:%d (%dx%d at (%d,%d)-> %dx%d)\n", zoom_rate,a.c.width, a.c.height, a.c.left, a.c.top, icd->user_width, icd->user_height );
2884 static inline struct v4l2_queryctrl const *rk_camera_soc_camera_find_qctrl(
2885 struct soc_camera_host_ops *ops, int id)
2889 for (i = 0; i < ops->num_controls; i++)
2890 if (ops->controls[i].id == id)
2891 return &ops->controls[i];
2897 static int rk_camera_set_ctrl(struct soc_camera_device *icd,
2898 struct v4l2_control *sctrl)
2901 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2902 const struct v4l2_queryctrl *qctrl;
2903 struct rk_camera_dev *pcdev = ici->priv;
2907 qctrl = rk_camera_soc_camera_find_qctrl(ici->ops, sctrl->id);
2910 goto rk_camera_set_ctrl_end;
2915 case V4L2_CID_ZOOM_ABSOLUTE:
2917 if ((sctrl->value < qctrl->minimum) || (sctrl->value > qctrl->maximum)){
2919 goto rk_camera_set_ctrl_end;
2921 ret = rk_camera_set_digit_zoom(icd, qctrl, sctrl->value);
2923 pcdev->zoominfo.zoom_rate = sctrl->value;
2925 goto rk_camera_set_ctrl_end;
2933 rk_camera_set_ctrl_end:
2937 static struct soc_camera_host_ops rk_soc_camera_host_ops =
2939 .owner = THIS_MODULE,
2940 .add = rk_camera_add_device,
2941 .remove = rk_camera_remove_device,
2942 .suspend = rk_camera_suspend,
2943 .resume = rk_camera_resume,
2944 .enum_frameinervals = rk_camera_enum_frameintervals,
2945 .set_crop = rk_camera_set_crop,
2946 .get_formats = rk_camera_get_formats,
2947 .put_formats = rk_camera_put_formats,
2948 .set_fmt = rk_camera_set_fmt,
2949 .try_fmt = rk_camera_try_fmt,
2950 .init_videobuf = rk_camera_init_videobuf,
2951 .reqbufs = rk_camera_reqbufs,
2952 .poll = rk_camera_poll,
2953 .querycap = rk_camera_querycap,
2954 .set_bus_param = rk_camera_set_bus_param,
2955 .s_stream = rk_camera_s_stream, /* ddl@rock-chips.com : Add stream control for host */
2956 .set_ctrl = rk_camera_set_ctrl,
2957 .controls = rk_camera_controls,
2958 .num_controls = ARRAY_SIZE(rk_camera_controls)
2960 static void rk_camera_cif_iomux(int cif_index)
2962 #if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)
2966 iomux_set(CIF0_CLKOUT);
2967 write_grf_reg(GRF_IO_CON3, (CIF_DRIVER_STRENGTH_MASK|CIF_DRIVER_STRENGTH_8MA));
2968 write_grf_reg(GRF_IO_CON4, (CIF_CLKOUT_AMP_MASK|CIF_CLKOUT_AMP_1V8));
2969 #if (CONFIG_CAMERA_INPUT_FMT_SUPPORT & (RK_CAM_INPUT_FMT_RAW10|RK_CAM_INPUT_FMT_RAW12))
2973 #if (CONFIG_CAMERA_INPUT_FMT_SUPPORT & RK_CAM_INPUT_FMT_RAW12)
2974 iomux_set(CIF0_D10);
2975 iomux_set(CIF0_D11);
2976 RKCAMERA_TR("%s(%d): WARNING: Cif 0 is configurated that support RAW 12bit, so I2C3 is invalidate!!\n",__FUNCTION__,__LINE__);
2982 RKCAMERA_TR("%s(%d): Cif index(%d) is invalidate!!!\n",__FUNCTION__,__LINE__, cif_index);
2985 #elif defined(CONFIG_ARCH_RK30)
2989 rk30_mux_api_set(GPIO1B3_CIF0CLKOUT_NAME, GPIO1B_CIF0_CLKOUT);
2990 #if (CONFIG_CAMERA_INPUT_FMT_SUPPORT & (RK_CAM_INPUT_FMT_RAW10|RK_CAM_INPUT_FMT_RAW12))
2991 rk30_mux_api_set(GPIO1B4_CIF0DATA0_NAME, GPIO1B_CIF0_DATA0);
2992 rk30_mux_api_set(GPIO1B5_CIF0DATA1_NAME, GPIO1B_CIF0_DATA1);
2994 #if (CONFIG_CAMERA_INPUT_FMT_SUPPORT & RK_CAM_INPUT_FMT_RAW12)
2995 rk30_mux_api_set(GPIO1B6_CIFDATA10_NAME, GPIO1B_CIF_DATA10);
2996 rk30_mux_api_set(GPIO1B7_CIFDATA11_NAME, GPIO1B_CIF_DATA11);
3002 rk30_mux_api_set(GPIO1C0_CIF1DATA2_RMIICLKOUT_RMIICLKIN_NAME,GPIO1C_CIF1_DATA2);
3003 rk30_mux_api_set(GPIO1C1_CIFDATA3_RMIITXEN_NAME,GPIO1C_CIF_DATA3);
3004 rk30_mux_api_set(GPIO1C2_CIF1DATA4_RMIITXD1_NAME,GPIO1C_CIF1_DATA4);
3005 rk30_mux_api_set(GPIO1C3_CIFDATA5_RMIITXD0_NAME,GPIO1C_CIF_DATA5);
3006 rk30_mux_api_set(GPIO1C4_CIFDATA6_RMIIRXERR_NAME,GPIO1C_CIF_DATA6);
3007 rk30_mux_api_set(GPIO1C5_CIFDATA7_RMIICRSDVALID_NAME,GPIO1C_CIF_DATA7);
3008 rk30_mux_api_set(GPIO1C6_CIFDATA8_RMIIRXD1_NAME,GPIO1C_CIF_DATA8);
3009 rk30_mux_api_set(GPIO1C7_CIFDATA9_RMIIRXD0_NAME,GPIO1C_CIF_DATA9);
3011 rk30_mux_api_set(GPIO1D0_CIF1VSYNC_MIIMD_NAME,GPIO1D_CIF1_VSYNC);
3012 rk30_mux_api_set(GPIO1D1_CIF1HREF_MIIMDCLK_NAME,GPIO1D_CIF1_HREF);
3013 rk30_mux_api_set(GPIO1D2_CIF1CLKIN_NAME,GPIO1D_CIF1_CLKIN);
3014 rk30_mux_api_set(GPIO1D3_CIF1DATA0_NAME,GPIO1D_CIF1_DATA0);
3015 rk30_mux_api_set(GPIO1D4_CIF1DATA1_NAME,GPIO1D_CIF1_DATA1);
3016 rk30_mux_api_set(GPIO1D5_CIF1DATA10_NAME,GPIO1D_CIF1_DATA10);
3017 rk30_mux_api_set(GPIO1D6_CIF1DATA11_NAME,GPIO1D_CIF1_DATA11);
3018 rk30_mux_api_set(GPIO1D7_CIF1CLKOUT_NAME,GPIO1D_CIF1_CLKOUT);
3022 RKCAMERA_TR("%s(%d): Cif index(%d) is invalidate!!!\n",__FUNCTION__,__LINE__, cif_index);
3029 static int rk_camera_probe(struct platform_device *pdev)
3031 struct rk_camera_dev *pcdev;
3032 struct resource *res;
3033 struct rk_camera_frmivalenum *fival_list,*fival_nxt;
3034 struct rk29camera_mem_res *meminfo_ptr,*meminfo_ptrr;
3037 struct rk_cif_clk *clk=NULL;
3039 RKCAMERA_TR("%s version: v%d.%d.%d Zoom by %s",RK29_CAM_DRV_NAME,(RK_CAM_VERSION_CODE&0xff0000)>>16,
3040 (RK_CAM_VERSION_CODE&0xff00)>>8,RK_CAM_VERSION_CODE&0xff,CAMERA_SCALE_CROP_MACHINE);
3042 if ((pdev->id == RK_CAM_PLATFORM_DEV_ID_1) && (RK_SUPPORT_CIF1 == 0)) {
3043 RKCAMERA_TR("%s(%d): This chip is not support CIF1!!\n",__FUNCTION__,__LINE__);
3047 if ((pdev->id == RK_CAM_PLATFORM_DEV_ID_0) && (RK_SUPPORT_CIF0 == 0)) {
3048 RKCAMERA_TR("%s(%d): This chip is not support CIF0!!\n",__FUNCTION__,__LINE__);
3052 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
3053 irq = platform_get_irq(pdev, 0);
3054 if (!res || irq < 0) {
3058 pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL);
3060 dev_err(&pdev->dev, "Could not allocate pcdev\n");
3065 pcdev->zoominfo.zoom_rate = 100;
3066 pcdev->hostid = pdev->id;
3067 #ifdef CONFIG_SOC_RK3028
3068 pcdev->chip_id = rk3028_version_val();
3070 pcdev->chip_id = -1;
3075 cif_clk[0].pd_cif = clk_get(NULL, "pd_cif0");
3076 cif_clk[0].aclk_cif = clk_get(NULL, "aclk_cif0");
3077 cif_clk[0].hclk_cif = clk_get(NULL, "hclk_cif0");
3078 cif_clk[0].cif_clk_in = clk_get(NULL, "cif0_in");
3079 cif_clk[0].cif_clk_out = clk_get(NULL, "cif0_out");
3080 spin_lock_init(&cif_clk[0].lock);
3081 cif_clk[0].on = false;
3082 rk_camera_cif_iomux(0);
3085 cif_clk[1].pd_cif = clk_get(NULL, "pd_cif1");
3086 cif_clk[1].aclk_cif = clk_get(NULL, "aclk_cif1");
3087 cif_clk[1].hclk_cif = clk_get(NULL, "hclk_cif1");
3088 cif_clk[1].cif_clk_in = clk_get(NULL, "cif1_in");
3089 cif_clk[1].cif_clk_out = clk_get(NULL, "cif1_out");
3090 spin_lock_init(&cif_clk[1].lock);
3091 cif_clk[1].on = false;
3092 rk_camera_cif_iomux(1);
3095 dev_set_drvdata(&pdev->dev, pcdev);
3097 pcdev->pdata = pdev->dev.platform_data; /* ddl@rock-chips.com : Request IO in init function */
3099 if (pcdev->pdata && pcdev->pdata->io_init) {
3100 pcdev->pdata->io_init();
3102 if (pcdev->pdata->sensor_mclk == NULL)
3103 pcdev->pdata->sensor_mclk = rk_camera_mclk_ctrl;
3106 meminfo_ptr = IS_CIF0()? (&pcdev->pdata->meminfo):(&pcdev->pdata->meminfo_cif1);
3107 meminfo_ptrr = IS_CIF0()? (&pcdev->pdata->meminfo_cif1):(&pcdev->pdata->meminfo);
3109 if (meminfo_ptr->vbase == NULL) {
3111 if ((meminfo_ptr->start == meminfo_ptrr->start)
3112 && (meminfo_ptr->size == meminfo_ptrr->size) && meminfo_ptrr->vbase) {
3114 meminfo_ptr->vbase = meminfo_ptrr->vbase;
3117 if (!request_mem_region(meminfo_ptr->start,meminfo_ptr->size,"rk29_vipmem")) {
3119 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);
3120 goto exit_ioremap_vipmem;
3122 meminfo_ptr->vbase = pcdev->vipmem_virbase = ioremap_cached(meminfo_ptr->start,meminfo_ptr->size);
3123 if (pcdev->vipmem_virbase == NULL) {
3124 RKCAMERA_TR("%s(%d): ioremap of CIF internal memory(Ex:IPP process/raw process) failed\n",__FUNCTION__,__LINE__);
3126 goto exit_ioremap_vipmem;
3131 pcdev->vipmem_phybase = meminfo_ptr->start;
3132 pcdev->vipmem_size = meminfo_ptr->size;
3133 pcdev->vipmem_virbase = meminfo_ptr->vbase;
3135 INIT_LIST_HEAD(&pcdev->capture);
3136 INIT_LIST_HEAD(&pcdev->camera_work_queue);
3137 spin_lock_init(&pcdev->lock);
3138 spin_lock_init(&pcdev->camera_work_lock);
3139 sema_init(&pcdev->zoominfo.sem,1);
3142 * Request the regions.
3145 if (!request_mem_region(res->start, res->end - res->start + 1,
3146 RK29_CAM_DRV_NAME)) {
3148 goto exit_reqmem_vip;
3150 pcdev->base = ioremap(res->start, res->end - res->start + 1);
3151 if (pcdev->base == NULL) {
3152 dev_err(pcdev->dev, "ioremap() of registers failed\n");
3154 goto exit_ioremap_vip;
3159 pcdev->dev = &pdev->dev;
3161 /* config buffer address */
3164 err = request_irq(pcdev->irq, rk_camera_irq, 0, RK29_CAM_DRV_NAME,
3167 dev_err(pcdev->dev, "Camera interrupt register failed \n");
3173 pcdev->camera_wq = create_workqueue("rk_cam_wkque_cif0");
3175 pcdev->camera_wq = create_workqueue("rk_cam_wkque_cif1");
3177 if (pcdev->camera_wq == NULL) {
3178 RKCAMERA_TR("%s(%d): Create workqueue failed!\n",__FUNCTION__,__LINE__);
3182 pcdev->camera_reinit_work.pcdev = pcdev;
3183 INIT_WORK(&(pcdev->camera_reinit_work.work), rk_camera_reinit_work);
3185 for (i=0; i<2; i++) {
3186 pcdev->icd_frmival[i].icd = NULL;
3187 pcdev->icd_frmival[i].fival_list = kzalloc(sizeof(struct rk_camera_frmivalenum),GFP_KERNEL);
3190 pcdev->soc_host.drv_name = RK29_CAM_DRV_NAME;
3191 pcdev->soc_host.ops = &rk_soc_camera_host_ops;
3192 pcdev->soc_host.priv = pcdev;
3193 pcdev->soc_host.v4l2_dev.dev = &pdev->dev;
3194 pcdev->soc_host.nr = pdev->id;
3196 err = soc_camera_host_register(&pcdev->soc_host);
3198 RKCAMERA_TR("%s(%d): soc_camera_host_register failed\n",__FUNCTION__,__LINE__);
3201 pcdev->fps_timer.pcdev = pcdev;
3202 hrtimer_init(&(pcdev->fps_timer.timer), CLOCK_MONOTONIC, HRTIMER_MODE_REL);
3203 pcdev->fps_timer.timer.function = rk_camera_fps_func;
3204 pcdev->icd_cb.sensor_cb = NULL;
3206 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP)
3207 pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_ipp;
3208 #elif (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_ARM)
3209 pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_arm;
3210 #elif (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_RGA)
3211 pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_rga;
3212 #elif(CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_PP)
3213 pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_pp;
3215 RKCAMERA_DG("%s exit \n",__FUNCTION__);
3220 for (i=0; i<2; i++) {
3221 fival_list = pcdev->icd_frmival[i].fival_list;
3222 fival_nxt = fival_list;
3223 while(fival_nxt != NULL) {
3224 fival_nxt = fival_list->nxt;
3226 fival_list = fival_nxt;
3230 free_irq(pcdev->irq, pcdev);
3231 if (pcdev->camera_wq) {
3232 destroy_workqueue(pcdev->camera_wq);
3233 pcdev->camera_wq = NULL;
3236 iounmap(pcdev->base);
3238 release_mem_region(res->start, res->end - res->start + 1);
3239 exit_ioremap_vipmem:
3240 if (pcdev->vipmem_virbase)
3241 iounmap(pcdev->vipmem_virbase);
3242 release_mem_region(pcdev->vipmem_phybase,pcdev->vipmem_size);
3246 clk_put(clk->pd_cif);
3248 clk_put(clk->aclk_cif);
3250 clk_put(clk->hclk_cif);
3251 if (clk->cif_clk_in)
3252 clk_put(clk->cif_clk_in);
3253 if (clk->cif_clk_out)
3254 clk_put(clk->cif_clk_out);
3263 static int __devexit rk_camera_remove(struct platform_device *pdev)
3265 struct rk_camera_dev *pcdev = platform_get_drvdata(pdev);
3266 struct resource *res;
3267 struct rk_camera_frmivalenum *fival_list,*fival_nxt;
3268 struct rk29camera_mem_res *meminfo_ptr,*meminfo_ptrr;
3271 free_irq(pcdev->irq, pcdev);
3273 if (pcdev->camera_wq) {
3274 destroy_workqueue(pcdev->camera_wq);
3275 pcdev->camera_wq = NULL;
3278 for (i=0; i<2; i++) {
3279 fival_list = pcdev->icd_frmival[i].fival_list;
3280 fival_nxt = fival_list;
3281 while(fival_nxt != NULL) {
3282 fival_nxt = fival_list->nxt;
3284 fival_list = fival_nxt;
3288 soc_camera_host_unregister(&pcdev->soc_host);
3290 meminfo_ptr = IS_CIF0()? (&pcdev->pdata->meminfo):(&pcdev->pdata->meminfo_cif1);
3291 meminfo_ptrr = IS_CIF0()? (&pcdev->pdata->meminfo_cif1):(&pcdev->pdata->meminfo);
3292 if (meminfo_ptr->vbase) {
3293 if (meminfo_ptr->vbase == meminfo_ptrr->vbase) {
3294 meminfo_ptr->vbase = NULL;
3296 iounmap((void __iomem*)pcdev->vipmem_virbase);
3297 release_mem_region(pcdev->vipmem_phybase, pcdev->vipmem_size);
3298 meminfo_ptr->vbase = NULL;
3303 iounmap((void __iomem*)pcdev->base);
3304 release_mem_region(res->start, res->end - res->start + 1);
3305 if (pcdev->pdata && pcdev->pdata->io_deinit) { /* ddl@rock-chips.com : Free IO in deinit function */
3306 pcdev->pdata->io_deinit(0);
3307 pcdev->pdata->io_deinit(1);
3312 dev_info(&pdev->dev, "RK28 Camera driver unloaded\n");
3317 static struct platform_driver rk_camera_driver =
3320 .name = RK29_CAM_DRV_NAME,
3322 .probe = rk_camera_probe,
3323 .remove = __devexit_p(rk_camera_remove),
3326 static int rk_camera_init_async(void *unused)
3328 platform_driver_register(&rk_camera_driver);
3332 static int __devinit rk_camera_init(void)
3334 kthread_run(rk_camera_init_async, NULL, "rk_camera_init");
3338 static void __exit rk_camera_exit(void)
3340 platform_driver_unregister(&rk_camera_driver);
3343 device_initcall_sync(rk_camera_init);
3344 module_exit(rk_camera_exit);
3346 MODULE_DESCRIPTION("RKSoc Camera Host driver");
3347 MODULE_AUTHOR("ddl <ddl@rock-chips>");
3348 MODULE_LICENSE("GPL");