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;
1445 cif = cif_idx - RK29_CAM_PLATFORM_DEV_ID;
1446 if ((cif<0)||(cif>1)) {
1447 RKCAMERA_TR(KERN_ERR "cif index(%d) is invalidate\n",cif_idx);
1449 goto rk_camera_clk_ctrl_end;
1452 clk = &cif_clk[cif];
1454 if(!clk->aclk_cif || !clk->hclk_cif || !clk->cif_clk_in || !clk->cif_clk_out) {
1455 RKCAMERA_TR(KERN_ERR "failed to get cif clock source\n");
1457 goto rk_camera_clk_ctrl_end;
1460 spin_lock(&clk->lock);
1461 if (on && !clk->on) {
1462 clk_enable(clk->pd_cif);
1463 clk_enable(clk->aclk_cif);
1464 clk_enable(clk->hclk_cif);
1465 clk_enable(clk->cif_clk_in);
1466 clk_enable(clk->cif_clk_out);
1467 clk_set_rate(clk->cif_clk_out,clk_rate);
1469 } else if (!on && clk->on) {
1470 clk_disable(clk->aclk_cif);
1471 clk_disable(clk->hclk_cif);
1472 clk_disable(clk->cif_clk_in);
1473 clk_disable(clk->cif_clk_out);
1474 clk_disable(clk->pd_cif);
1477 err = clk_set_parent(clk->cif_clk_out, clk_get(NULL, "cif1_out_div"));
1479 err = clk_set_parent(clk->cif_clk_out, clk_get(NULL, "cif0_out_div"));
1482 spin_unlock(&clk->lock);
1483 rk_camera_clk_ctrl_end:
1487 static int rk_camera_activate(struct rk_camera_dev *pcdev, struct soc_camera_device *icd)
1490 * ddl@rock-chips.com : Cif clk control in rk_sensor_power which in rk_camera.c
1492 write_cif_reg(pcdev->base,CIF_CIF_CTRL,AXI_BURST_16|MODE_ONEFRAME|DISABLE_CAPTURE); /* ddl@rock-chips.com : vip ahb burst 16 */
1493 write_cif_reg(pcdev->base,CIF_CIF_INTEN, 0x01); //capture complete interrupt enable
1494 RKCAMERA_DG("CIF_CIF_CTRL = 0x%x\n",read_cif_reg(pcdev->base, CIF_CIF_CTRL));
1498 static void rk_camera_deactivate(struct rk_camera_dev *pcdev)
1501 * ddl@rock-chips.com : Cif clk control in rk_sensor_power which in rk_camera.c
1507 /* The following two functions absolutely depend on the fact, that
1508 * there can be only one camera on RK28 quick capture interface */
1509 static int rk_camera_add_device(struct soc_camera_device *icd)
1511 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1512 struct rk_camera_dev *pcdev = ici->priv;
1513 struct device *control = to_soc_camera_control(icd);
1514 struct v4l2_subdev *sd;
1515 int ret,i,icd_catch;
1516 struct rk_camera_frmivalenum *fival_list,*fival_nxt;
1518 mutex_lock(&camera_lock);
1525 RKCAMERA_DG("%s driver attached to %s\n",RK29_CAM_DRV_NAME,dev_name(icd->pdev));
1527 pcdev->frame_inval = RK_CAM_FRAME_INVAL_INIT;
1528 pcdev->active = NULL;
1530 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
1531 pcdev->zoominfo.zoom_rate = 100;
1532 pcdev->fps_timer.istarted = false;
1534 /* ddl@rock-chips.com: capture list must be reset, because this list may be not empty,
1535 * if app havn't dequeue all videobuf before close camera device;
1537 INIT_LIST_HEAD(&pcdev->capture);
1539 ret = rk_camera_activate(pcdev,icd);
1542 /* ddl@rock-chips.com : v4l2_subdev is not created when ici->ops->add called in soc_camera_probe */
1544 sd = dev_get_drvdata(control);
1545 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_IOREQUEST,(void*)pcdev->pdata);
1547 ret = v4l2_subdev_call(sd,core, init, 0);
1551 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_CB_REGISTER,(void*)(&pcdev->icd_cb));
1554 pcdev->icd_init = 0;
1557 for (i=0; i<2; i++) {
1558 if (pcdev->icd_frmival[i].icd == icd)
1560 if (pcdev->icd_frmival[i].icd == NULL) {
1561 pcdev->icd_frmival[i].icd = icd;
1565 if (icd_catch == 0) {
1566 fival_list = pcdev->icd_frmival[0].fival_list;
1567 fival_nxt = fival_list;
1568 while(fival_nxt != NULL) {
1569 fival_nxt = fival_list->nxt;
1571 fival_list = fival_nxt;
1573 pcdev->icd_frmival[0].icd = icd;
1574 pcdev->icd_frmival[0].fival_list = kzalloc(sizeof(struct rk_camera_frmivalenum),GFP_KERNEL);
1577 mutex_unlock(&camera_lock);
1581 static void rk_camera_remove_device(struct soc_camera_device *icd)
1583 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1584 struct rk_camera_dev *pcdev = ici->priv;
1585 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1586 #if CAMERA_VIDEOBUF_ARM_ACCESS
1587 struct rk29_camera_vbinfo *vb_info;
1591 mutex_lock(&camera_lock);
1592 BUG_ON(icd != pcdev->icd);
1594 RKCAMERA_DG("%s driver detached from %s\n",RK29_CAM_DRV_NAME,dev_name(icd->pdev));
1596 /* ddl@rock-chips.com: Application will call VIDIOC_STREAMOFF before close device, but
1597 stream may be turn on again before close device, if suspend and resume happened. */
1598 if (read_cif_reg(pcdev->base,CIF_CIF_CTRL) & ENABLE_CAPTURE) {
1599 rk_camera_s_stream(icd,0);
1602 v4l2_subdev_call(sd, core, ioctl, RK29_CAM_SUBDEV_DEACTIVATE,NULL);
1603 //if stream off is not been executed,timer is running.
1604 if(pcdev->fps_timer.istarted){
1605 hrtimer_cancel(&pcdev->fps_timer.timer);
1606 pcdev->fps_timer.istarted = false;
1608 flush_work(&(pcdev->camera_reinit_work.work));
1609 flush_workqueue((pcdev->camera_wq));
1611 if (pcdev->camera_work) {
1612 kfree(pcdev->camera_work);
1613 pcdev->camera_work = NULL;
1614 pcdev->camera_work_count = 0;
1615 INIT_LIST_HEAD(&pcdev->camera_work_queue);
1617 rk_camera_deactivate(pcdev);
1618 #if CAMERA_VIDEOBUF_ARM_ACCESS
1619 if (pcdev->vbinfo) {
1620 vb_info = pcdev->vbinfo;
1621 for (i=0; i<pcdev->vbinfo_count; i++) {
1622 if (vb_info->vir_addr) {
1623 iounmap(vb_info->vir_addr);
1624 release_mem_region(vb_info->phy_addr, vb_info->size);
1625 memset(vb_info, 0x00, sizeof(struct rk29_camera_vbinfo));
1629 kfree(pcdev->vbinfo);
1630 pcdev->vbinfo = NULL;
1631 pcdev->vbinfo_count = 0;
1634 pcdev->active = NULL;
1636 pcdev->icd_cb.sensor_cb = NULL;
1637 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
1638 /* ddl@rock-chips.com: capture list must be reset, because this list may be not empty,
1639 * if app havn't dequeue all videobuf before close camera device;
1641 INIT_LIST_HEAD(&pcdev->capture);
1643 mutex_unlock(&camera_lock);
1644 RKCAMERA_DG("%s exit\n",__FUNCTION__);
1648 static int rk_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
1650 unsigned long bus_flags, camera_flags, common_flags;
1651 unsigned int cif_ctrl_val = 0;
1652 const struct soc_mbus_pixelfmt *fmt;
1654 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1655 struct rk_camera_dev *pcdev = ici->priv;
1657 RKCAMERA_DG("%s enter\n",__FUNCTION__);
1659 fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code);
1663 bus_flags = RK_CAM_BUS_PARAM;
1664 /* If requested data width is supported by the platform, use it */
1665 switch (fmt->bits_per_sample) {
1667 if (!(bus_flags & SOCAM_DATAWIDTH_10))
1671 if (!(bus_flags & SOCAM_DATAWIDTH_9))
1675 if (!(bus_flags & SOCAM_DATAWIDTH_8))
1682 if (icd->ops->query_bus_param)
1683 camera_flags = icd->ops->query_bus_param(icd);
1687 common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
1688 if (!common_flags) {
1690 goto RK_CAMERA_SET_BUS_PARAM_END;
1693 ret = icd->ops->set_bus_param(icd, common_flags);
1695 goto RK_CAMERA_SET_BUS_PARAM_END;
1697 cif_ctrl_val = read_cif_reg(pcdev->base,CIF_CIF_FOR);
1698 RKCAMERA_DG("cif_ctrl_val = 0x%x\n",cif_ctrl_val);
1699 if (common_flags & SOCAM_PCLK_SAMPLE_FALLING) {
1701 write_cru_reg(CRU_PCLK_REG30, read_cru_reg(CRU_PCLK_REG30) | ENANABLE_INVERT_PCLK_CIF0);
1702 RKCAMERA_DG("enable cif0 pclk invert\n");
1704 write_cru_reg(CRU_PCLK_REG30, read_cru_reg(CRU_PCLK_REG30) | ENANABLE_INVERT_PCLK_CIF1);
1705 RKCAMERA_DG("enable cif1 pclk invert\n");
1709 write_cru_reg(CRU_PCLK_REG30, (read_cru_reg(CRU_PCLK_REG30) & 0xFFFFEFF ) | DISABLE_INVERT_PCLK_CIF0);
1710 RKCAMERA_DG("diable cif0 pclk invert\n");
1712 write_cru_reg(CRU_PCLK_REG30, (read_cru_reg(CRU_PCLK_REG30) & 0xFFFEFFF) | DISABLE_INVERT_PCLK_CIF1);
1713 RKCAMERA_DG("diable cif1 pclk invert\n");
1716 if (common_flags & SOCAM_HSYNC_ACTIVE_LOW) {
1717 cif_ctrl_val |= HSY_LOW_ACTIVE;
1719 cif_ctrl_val &= ~HSY_LOW_ACTIVE;
1721 if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH) {
1722 cif_ctrl_val |= VSY_HIGH_ACTIVE;
1724 cif_ctrl_val &= ~VSY_HIGH_ACTIVE;
1727 /* ddl@rock-chips.com : Don't enable capture here, enable in stream_on */
1728 //vip_ctrl_val |= ENABLE_CAPTURE;
1729 write_cif_reg(pcdev->base,CIF_CIF_FOR, cif_ctrl_val);
1730 RKCAMERA_DG("ctrl:0x%x CIF_CIF_FOR=%x \n",cif_ctrl_val,read_cif_reg(pcdev->base,CIF_CIF_FOR));
1732 RK_CAMERA_SET_BUS_PARAM_END:
1734 RKCAMERA_TR("rk_camera_set_bus_param ret = %d \n", ret);
1738 static int rk_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
1740 unsigned long bus_flags, camera_flags;
1743 bus_flags = RK_CAM_BUS_PARAM;
1744 if (icd->ops->query_bus_param) {
1745 camera_flags = icd->ops->query_bus_param(icd);
1749 ret = soc_camera_bus_param_compatible(camera_flags, bus_flags) ;
1752 dev_warn(icd->dev.parent,
1753 "Flags incompatible: camera %lx, host %lx\n",
1754 camera_flags, bus_flags);
1758 static const struct soc_mbus_pixelfmt rk_camera_formats[] = {
1760 .fourcc = V4L2_PIX_FMT_NV12,
1761 .name = "YUV420 NV12",
1762 .bits_per_sample = 8,
1763 .packing = SOC_MBUS_PACKING_1_5X8,
1764 .order = SOC_MBUS_ORDER_LE,
1766 .fourcc = V4L2_PIX_FMT_NV16,
1767 .name = "YUV422 NV16",
1768 .bits_per_sample = 8,
1769 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1770 .order = SOC_MBUS_ORDER_LE,
1772 .fourcc = V4L2_PIX_FMT_NV21,
1773 .name = "YUV420 NV21",
1774 .bits_per_sample = 8,
1775 .packing = SOC_MBUS_PACKING_1_5X8,
1776 .order = SOC_MBUS_ORDER_LE,
1778 .fourcc = V4L2_PIX_FMT_NV61,
1779 .name = "YUV422 NV61",
1780 .bits_per_sample = 8,
1781 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1782 .order = SOC_MBUS_ORDER_LE,
1784 .fourcc = V4L2_PIX_FMT_RGB565,
1786 .bits_per_sample = 8,
1787 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1788 .order = SOC_MBUS_ORDER_LE,
1790 .fourcc = V4L2_PIX_FMT_RGB24,
1792 .bits_per_sample = 8,
1793 .packing = SOC_MBUS_PACKING_2X8_PADHI,
1794 .order = SOC_MBUS_ORDER_LE,
1798 static void rk_camera_setup_format(struct soc_camera_device *icd, __u32 host_pixfmt, enum v4l2_mbus_pixelcode icd_code, struct v4l2_rect *rect)
1800 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1801 struct rk_camera_dev *pcdev = ici->priv;
1802 unsigned int cif_fs = 0,cif_crop = 0;
1803 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;
1805 const struct soc_mbus_pixelfmt *fmt;
1806 fmt = soc_mbus_get_fmtdesc(icd_code);
1808 if((host_pixfmt == V4L2_PIX_FMT_RGB565) || (host_pixfmt == V4L2_PIX_FMT_RGB24)){
1809 if(fmt->fourcc == V4L2_PIX_FMT_NV12)
1810 host_pixfmt = V4L2_PIX_FMT_NV12;
1811 else if(fmt->fourcc == V4L2_PIX_FMT_NV21)
1812 host_pixfmt = V4L2_PIX_FMT_NV21;
1814 switch (host_pixfmt)
1816 case V4L2_PIX_FMT_NV16:
1817 cif_fmt_val &= ~YUV_OUTPUT_422;
1818 cif_fmt_val &= ~UV_STORAGE_ORDER_UVUV;
1819 pcdev->frame_inval = RK_CAM_FRAME_INVAL_DC;
1820 pcdev->pixfmt = host_pixfmt;
1822 case V4L2_PIX_FMT_NV61:
1823 cif_fmt_val &= ~YUV_OUTPUT_422;
1824 cif_fmt_val |= UV_STORAGE_ORDER_VUVU;
1825 pcdev->frame_inval = RK_CAM_FRAME_INVAL_DC;
1826 pcdev->pixfmt = host_pixfmt;
1828 case V4L2_PIX_FMT_NV12:
1829 cif_fmt_val |= YUV_OUTPUT_420;
1830 cif_fmt_val &= ~UV_STORAGE_ORDER_UVUV;
1831 if (pcdev->frame_inval != RK_CAM_FRAME_INVAL_INIT)
1832 pcdev->frame_inval = RK_CAM_FRAME_INVAL_INIT;
1833 pcdev->pixfmt = host_pixfmt;
1835 case V4L2_PIX_FMT_NV21:
1836 cif_fmt_val |= YUV_OUTPUT_420;
1837 cif_fmt_val |= UV_STORAGE_ORDER_VUVU;
1838 if (pcdev->frame_inval != RK_CAM_FRAME_INVAL_INIT)
1839 pcdev->frame_inval = RK_CAM_FRAME_INVAL_INIT;
1840 pcdev->pixfmt = host_pixfmt;
1842 default: /* ddl@rock-chips.com : vip output format is hold when pixfmt is invalidate */
1843 cif_fmt_val |= YUV_OUTPUT_422;
1848 case V4L2_MBUS_FMT_UYVY8_2X8:
1849 cif_fmt_val = YUV_INPUT_ORDER_UYVY(cif_fmt_val);
1851 case V4L2_MBUS_FMT_YUYV8_2X8:
1852 cif_fmt_val = YUV_INPUT_ORDER_YUYV(cif_fmt_val);
1854 case V4L2_MBUS_FMT_YVYU8_2X8:
1855 cif_fmt_val = YUV_INPUT_ORDER_YVYU(cif_fmt_val);
1857 case V4L2_MBUS_FMT_VYUY8_2X8:
1858 cif_fmt_val = YUV_INPUT_ORDER_VYUY(cif_fmt_val);
1861 cif_fmt_val = YUV_INPUT_ORDER_YUYV(cif_fmt_val);
1866 rk_camera_cif_reset(pcdev,true);
1868 write_cif_reg(pcdev->base,CIF_CIF_CTRL,AXI_BURST_16|MODE_ONEFRAME|DISABLE_CAPTURE); /* ddl@rock-chips.com : vip ahb burst 16 */
1869 write_cif_reg(pcdev->base,CIF_CIF_INTEN, 0x01|0x200); //capture complete interrupt enable
1871 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 */
1873 write_cif_reg(pcdev->base,CIF_CIF_INTSTAT,0xFFFFFFFF);
1874 if((read_cif_reg(pcdev->base,CIF_CIF_CTRL) & MODE_PINGPONG)
1875 ||(read_cif_reg(pcdev->base,CIF_CIF_CTRL) & MODE_LINELOOP)) {
1877 } else{ // this is one frame mode
1878 cif_crop = (rect->left+ (rect->top<<16));
1879 cif_fs = ((rect->width ) + (rect->height<<16));
1882 write_cif_reg(pcdev->base,CIF_CIF_CROP, cif_crop);
1883 write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, cif_fs);
1884 write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH, rect->width);
1885 write_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS, 0x00000003);
1888 write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL,0x10);
1889 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));
1893 static int rk_camera_get_formats(struct soc_camera_device *icd, unsigned int idx,
1894 struct soc_camera_format_xlate *xlate)
1896 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1897 struct device *dev = icd->dev.parent;
1898 int formats = 0, ret;
1899 enum v4l2_mbus_pixelcode code;
1900 const struct soc_mbus_pixelfmt *fmt;
1902 ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
1904 /* No more formats */
1907 fmt = soc_mbus_get_fmtdesc(code);
1909 dev_err(dev, "Invalid format code #%u: %d\n", idx, code);
1913 ret = rk_camera_try_bus_param(icd, fmt->bits_per_sample);
1918 case V4L2_MBUS_FMT_UYVY8_2X8:
1919 case V4L2_MBUS_FMT_YUYV8_2X8:
1920 case V4L2_MBUS_FMT_YVYU8_2X8:
1921 case V4L2_MBUS_FMT_VYUY8_2X8:
1924 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE != RK_CAM_SCALE_CROP_RGA)
1927 xlate->host_fmt = &rk_camera_formats[0];
1930 dev_dbg(dev, "Providing format %s using code %d\n",
1931 rk_camera_formats[0].name,code);
1936 xlate->host_fmt = &rk_camera_formats[1];
1939 dev_dbg(dev, "Providing format %s using code %d\n",
1940 rk_camera_formats[1].name,code);
1945 xlate->host_fmt = &rk_camera_formats[2];
1948 dev_dbg(dev, "Providing format %s using code %d\n",
1949 rk_camera_formats[2].name,code);
1954 xlate->host_fmt = &rk_camera_formats[3];
1957 dev_dbg(dev, "Providing format %s using code %d\n",
1958 rk_camera_formats[3].name,code);
1964 xlate->host_fmt = &rk_camera_formats[4];
1967 dev_dbg(dev, "Providing format %s using code %d\n",
1968 rk_camera_formats[4].name,code);
1972 xlate->host_fmt = &rk_camera_formats[5];
1975 dev_dbg(dev, "Providing format %s using code %d\n",
1976 rk_camera_formats[5].name,code);
1988 static void rk_camera_put_formats(struct soc_camera_device *icd)
1993 static int rk_camera_set_crop(struct soc_camera_device *icd,
1994 struct v4l2_crop *a)
1996 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1997 struct v4l2_mbus_framefmt mf;
1998 u32 fourcc = icd->current_fmt->host_fmt->fourcc;
2001 ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
2005 if ((mf.width < (a->c.left + a->c.width)) || (mf.height < (a->c.top + a->c.height))) {
2007 mf.width = a->c.left + a->c.width;
2008 mf.height = a->c.top + a->c.height;
2010 v4l_bound_align_image(&mf.width, RK_CAM_W_MIN, RK_CAM_W_MAX, 1,
2011 &mf.height, RK_CAM_H_MIN, RK_CAM_H_MAX, 0,
2012 fourcc == V4L2_PIX_FMT_NV16 ?4 : 0);
2014 ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
2019 rk_camera_setup_format(icd, fourcc, mf.code, &a->c);
2021 icd->user_width = mf.width;
2022 icd->user_height = mf.height;
2026 static bool rk_camera_fmt_capturechk(struct v4l2_format *f)
2030 if (f->fmt.pix.priv == 0xfefe5a5a) {
2034 if ((f->fmt.pix.width == 1024) && (f->fmt.pix.height == 768)) {
2036 } else if ((f->fmt.pix.width == 1280) && (f->fmt.pix.height == 1024)) {
2038 } else if ((f->fmt.pix.width == 1600) && (f->fmt.pix.height == 1200)) {
2040 } else if ((f->fmt.pix.width == 2048) && (f->fmt.pix.height == 1536)) {
2042 } else if ((f->fmt.pix.width == 2592) && (f->fmt.pix.height == 1944)) {
2044 } else if ((f->fmt.pix.width == 3264) && (f->fmt.pix.height == 2448)) {
2049 RKCAMERA_DG("%dx%d is capture format\n",f->fmt.pix.width, f->fmt.pix.height);
2052 static int rk_camera_set_fmt(struct soc_camera_device *icd,
2053 struct v4l2_format *f)
2055 struct device *dev = icd->dev.parent;
2056 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
2057 const struct soc_camera_format_xlate *xlate = NULL;
2058 struct soc_camera_host *ici =to_soc_camera_host(icd->dev.parent);
2059 struct rk_camera_dev *pcdev = ici->priv;
2060 struct v4l2_pix_format *pix = &f->fmt.pix;
2061 struct v4l2_mbus_framefmt mf;
2062 struct v4l2_rect rect;
2063 int ret,usr_w,usr_h;
2067 usr_h = pix->height;
2069 RKCAMERA_DG("enter width:%d height:%d\n",usr_w,usr_h);
2070 xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
2072 dev_err(dev, "Format %x not found\n", pix->pixelformat);
2074 goto RK_CAMERA_SET_FMT_END;
2077 /* ddl@rock-chips.com: sensor init code transmit in here after open */
2078 if (pcdev->icd_init == 0) {
2079 v4l2_subdev_call(sd,core, init, 0);
2080 pcdev->icd_init = 1;
2083 stream_on = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
2084 if (stream_on & ENABLE_CAPTURE)
2085 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (stream_on & (~ENABLE_CAPTURE)));
2087 mf.width = pix->width;
2088 mf.height = pix->height;
2089 mf.field = pix->field;
2090 mf.colorspace = pix->colorspace;
2091 mf.code = xlate->code;
2092 mf.reserved[0] = pix->priv; /* ddl@rock-chips.com : v0.3.3 */
2094 ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
2095 if (mf.code != xlate->code)
2099 if ((mf.width != usr_w) || (mf.height != usr_h)) {
2101 if (unlikely((mf.width <16) || (mf.width > 8190) || (mf.height < 16) || (mf.height > 8190))) {
2102 RKCAMERA_TR("Senor and IPP both invalid source resolution(%dx%d)\n",mf.width,mf.height);
2104 goto RK_CAMERA_SET_FMT_END;
2106 if (unlikely((usr_w <16)||(usr_h < 16))) {
2107 RKCAMERA_TR("Senor and IPP both invalid destination resolution(%dx%d)\n",usr_w,usr_h);
2109 goto RK_CAMERA_SET_FMT_END;
2112 if((mf.width*10/mf.height) != (usr_w*10/usr_h)){
2113 ratio = ((mf.width*10/usr_w) >= (mf.height*10/usr_h))?(mf.height*10/usr_h):(mf.width*10/usr_w);
2114 pcdev->host_width = ratio*usr_w/10;
2115 pcdev->host_height = ratio*usr_h/10;
2116 //for ipp ,need 4 bit alligned.
2117 pcdev->host_width &= ~CROP_ALIGN_BYTES;
2118 pcdev->host_height &= ~CROP_ALIGN_BYTES;
2119 RKCAMERA_DG("ratio = %d ,host:%d*%d\n",ratio,pcdev->host_width,pcdev->host_height);
2120 } else { // needn't crop ,just scaled by ipp
2121 pcdev->host_width = mf.width;
2122 pcdev->host_height = mf.height;
2125 pcdev->host_width = usr_w;
2126 pcdev->host_height = usr_h;
2131 RKCAMERA_DG("host:%d*%d , sensor output:%d*%d,user demand:%d*%d\n",
2132 pcdev->host_width,pcdev->host_height,mf.width,mf.height,usr_w,usr_h);
2133 rect.width = pcdev->host_width;
2134 rect.height = pcdev->host_height;
2135 rect.left = ((mf.width-pcdev->host_width )>>1)&(~0x01);
2136 rect.top = ((mf.height-pcdev->host_height)>>1)&(~0x01);
2137 pcdev->host_left = rect.left;
2138 pcdev->host_top = rect.top;
2140 down(&pcdev->zoominfo.sem);
2142 pcdev->zoominfo.a.c.left = 0;
2143 pcdev->zoominfo.a.c.top = 0;
2144 pcdev->zoominfo.a.c.width = pcdev->host_width*100/pcdev->zoominfo.zoom_rate;
2145 pcdev->zoominfo.a.c.width &= ~CROP_ALIGN_BYTES;
2146 pcdev->zoominfo.a.c.height = pcdev->host_height*100/pcdev->zoominfo.zoom_rate;
2147 pcdev->zoominfo.a.c.height &= ~CROP_ALIGN_BYTES;
2148 pcdev->zoominfo.vir_width = pcdev->zoominfo.a.c.width;
2149 pcdev->zoominfo.vir_height = pcdev->zoominfo.a.c.height;
2150 //recalculate the CIF width & height
2151 rect.width = pcdev->zoominfo.a.c.width ;
2152 rect.height = pcdev->zoominfo.a.c.height;
2153 rect.left = ((((pcdev->host_width - pcdev->zoominfo.a.c.width)>>1))+pcdev->host_left)&(~0x01);
2154 rect.top = ((((pcdev->host_height - pcdev->zoominfo.a.c.height)>>1))+pcdev->host_top)&(~0x01);
2156 pcdev->zoominfo.a.c.width = pcdev->host_width*100/pcdev->zoominfo.zoom_rate;
2157 pcdev->zoominfo.a.c.width &= ~CROP_ALIGN_BYTES;
2158 pcdev->zoominfo.a.c.height = pcdev->host_height*100/pcdev->zoominfo.zoom_rate;
2159 pcdev->zoominfo.a.c.height &= ~CROP_ALIGN_BYTES;
2160 //now digital zoom use ipp to do crop and scale
2161 if(pcdev->zoominfo.zoom_rate != 100){
2162 pcdev->zoominfo.a.c.left = ((pcdev->host_width - pcdev->zoominfo.a.c.width)>>1)&(~0x01);
2163 pcdev->zoominfo.a.c.top = ((pcdev->host_height - pcdev->zoominfo.a.c.height)>>1)&(~0x01);
2165 pcdev->zoominfo.a.c.left = 0;
2166 pcdev->zoominfo.a.c.top = 0;
2168 pcdev->zoominfo.vir_width = pcdev->host_width;
2169 pcdev->zoominfo.vir_height = pcdev->host_height;
2171 up(&pcdev->zoominfo.sem);
2173 /* ddl@rock-chips.com: IPP work limit check */
2174 if ((pcdev->zoominfo.a.c.width != usr_w) || (pcdev->zoominfo.a.c.height != usr_h)) {
2175 if (usr_w > 0x7f0) {
2176 if (((usr_w>>1)&0x3f) && (((usr_w>>1)&0x3f) <= 8)) {
2177 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));
2179 goto RK_CAMERA_SET_FMT_END;
2182 if ((usr_w&0x3f) && ((usr_w&0x3f) <= 8)) {
2183 RKCAMERA_TR("IPP Destination resolution(%dx%d, %d mod 64=%d is <= 8)",usr_w,usr_h, usr_w, (int)(usr_w&0x3f));
2185 goto RK_CAMERA_SET_FMT_END;
2189 RKCAMERA_DG(" %s icd width:%d user width:%d (zoom: %dx%d@(%d,%d)->%dx%d)\n",xlate->host_fmt->name,
2190 rect.width, pix->width, pcdev->zoominfo.a.c.width,pcdev->zoominfo.a.c.height, pcdev->zoominfo.a.c.left,pcdev->zoominfo.a.c.top,
2191 pix->width, pix->height);
2192 rk_camera_setup_format(icd, pix->pixelformat, mf.code, &rect);
2194 if (CAM_IPPWORK_IS_EN()) {
2195 BUG_ON(pcdev->vipmem_phybase == 0);
2198 pix->height = usr_h;
2199 pix->field = mf.field;
2200 pix->colorspace = mf.colorspace;
2201 icd->current_fmt = xlate;
2202 pcdev->icd_width = mf.width;
2203 pcdev->icd_height = mf.height;
2206 RK_CAMERA_SET_FMT_END:
2207 if (stream_on & ENABLE_CAPTURE)
2208 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL) | ENABLE_CAPTURE));
2210 RKCAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
2214 static int rk_camera_try_fmt(struct soc_camera_device *icd,
2215 struct v4l2_format *f)
2217 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2218 struct rk_camera_dev *pcdev = ici->priv;
2219 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
2220 const struct soc_camera_format_xlate *xlate;
2221 struct v4l2_pix_format *pix = &f->fmt.pix;
2222 __u32 pixfmt = pix->pixelformat;
2223 int ret,usr_w,usr_h,i;
2224 bool is_capture = rk_camera_fmt_capturechk(f);
2225 bool vipmem_is_overflow = false;
2226 struct v4l2_mbus_framefmt mf;
2227 int bytes_per_line_host;
2230 usr_h = pix->height;
2232 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
2234 dev_err(icd->dev.parent, "Format (%c%c%c%c) not found\n", pixfmt & 0xFF, (pixfmt >> 8) & 0xFF,
2235 (pixfmt >> 16) & 0xFF, (pixfmt >> 24) & 0xFF);
2237 RKCAMERA_TR("%s(version:%c%c%c) support format:\n",rk_cam_driver_description,(RK_CAM_VERSION_CODE&0xff0000)>>16,
2238 (RK_CAM_VERSION_CODE&0xff00)>>8,(RK_CAM_VERSION_CODE&0xff));
2239 for (i = 0; i < icd->num_user_formats; i++)
2240 RKCAMERA_TR("(%c%c%c%c)-%s\n",
2241 icd->user_formats[i].host_fmt->fourcc & 0xFF, (icd->user_formats[i].host_fmt->fourcc >> 8) & 0xFF,
2242 (icd->user_formats[i].host_fmt->fourcc >> 16) & 0xFF, (icd->user_formats[i].host_fmt->fourcc >> 24) & 0xFF,
2243 icd->user_formats[i].host_fmt->name);
2244 goto RK_CAMERA_TRY_FMT_END;
2246 /* limit to rk29 hardware capabilities */
2247 v4l_bound_align_image(&pix->width, RK_CAM_W_MIN, RK_CAM_W_MAX, 1,
2248 &pix->height, RK_CAM_H_MIN, RK_CAM_H_MAX, 0,
2249 pixfmt == V4L2_PIX_FMT_NV16 ? 4 : 0);
2251 pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
2253 if (pix->bytesperline < 0)
2254 return pix->bytesperline;
2256 /* limit to sensor capabilities */
2257 memset(&mf,0x00,sizeof(struct v4l2_mbus_framefmt));
2258 mf.width = pix->width;
2259 mf.height = pix->height;
2260 mf.field = pix->field;
2261 mf.colorspace = pix->colorspace;
2262 mf.code = xlate->code;
2263 /* ddl@rock-chips.com : It is query max resolution only. */
2264 if ((usr_w == 10000) && (usr_h == 10000)) {
2265 mf.reserved[6] = 0xfefe5a5a;
2268 ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
2270 goto RK_CAMERA_TRY_FMT_END;
2273 if((usr_w == 10000) && (usr_h == 10000)) {
2274 pix->width = mf.width;
2275 pix->height = mf.height;
2276 RKCAMERA_DG("Sensor resolution : %dx%d\n",mf.width,mf.height);
2277 goto RK_CAMERA_TRY_FMT_END;
2279 RKCAMERA_DG("user demand: %dx%d sensor output: %dx%d \n",usr_w,usr_h,mf.width,mf.height);
2282 if ((mf.width != usr_w) || (mf.height != usr_h)) {
2283 bytes_per_line_host = soc_mbus_bytes_per_line(mf.width,icd->current_fmt->host_fmt);
2285 vipmem_is_overflow = (PAGE_ALIGN(bytes_per_line_host*mf.height) > pcdev->vipmem_size);
2287 /* Assume preview buffer minimum is 4 */
2288 vipmem_is_overflow = (PAGE_ALIGN(bytes_per_line_host*mf.height)*4 > pcdev->vipmem_size);
2290 if (vipmem_is_overflow == false) {
2292 pix->height = usr_h;
2294 RKCAMERA_TR("vipmem for IPP is overflow, This resolution(%dx%d -> %dx%d) is invalidate!\n",mf.width,mf.height,usr_w,usr_h);
2295 pix->width = mf.width;
2296 pix->height = mf.height;
2298 /* ddl@rock-chips.com: Invalidate these code, because sensor need interpolate */
2300 if ((mf.width < usr_w) || (mf.height < usr_h)) {
2301 if (((usr_w>>1) > mf.width) || ((usr_h>>1) > mf.height)) {
2302 RKCAMERA_TR("The aspect ratio(%dx%d/%dx%d) is bigger than 2 !\n",mf.width,mf.height,usr_w,usr_h);
2303 pix->width = mf.width;
2304 pix->height = mf.height;
2310 pix->colorspace = mf.colorspace;
2313 case V4L2_FIELD_ANY:
2314 case V4L2_FIELD_NONE:
2315 pix->field = V4L2_FIELD_NONE;
2318 /* TODO: support interlaced at least in pass-through mode */
2319 dev_err(icd->dev.parent, "Field type %d unsupported.\n",
2321 goto RK_CAMERA_TRY_FMT_END;
2324 RK_CAMERA_TRY_FMT_END:
2326 RKCAMERA_TR("\n%s..%d.. ret = %d \n",__FUNCTION__,__LINE__, ret);
2330 static int rk_camera_reqbufs(struct soc_camera_device *icd,
2331 struct v4l2_requestbuffers *p)
2335 /* This is for locking debugging only. I removed spinlocks and now I
2336 * check whether .prepare is ever called on a linked buffer, or whether
2337 * a dma IRQ can occur for an in-work or unlinked buffer. Until now
2338 * it hadn't triggered */
2339 for (i = 0; i < p->count; i++) {
2340 struct rk_camera_buffer *buf = container_of(icd->vb_vidq.bufs[i],
2341 struct rk_camera_buffer, vb);
2343 INIT_LIST_HEAD(&buf->vb.queue);
2349 static unsigned int rk_camera_poll(struct file *file, poll_table *pt)
2351 struct soc_camera_device *icd = file->private_data;
2352 struct rk_camera_buffer *buf;
2354 buf = list_entry(icd->vb_vidq.stream.next, struct rk_camera_buffer,
2357 poll_wait(file, &buf->vb.done, pt);
2359 if (buf->vb.state == VIDEOBUF_DONE ||
2360 buf->vb.state == VIDEOBUF_ERROR)
2361 return POLLIN|POLLRDNORM;
2366 static int rk_camera_querycap(struct soc_camera_host *ici,
2367 struct v4l2_capability *cap)
2369 struct rk_camera_dev *pcdev = ici->priv;
2370 struct rkcamera_platform_data *new_camera;
2371 char orientation[5];
2374 strlcpy(cap->card, dev_name(pcdev->icd->pdev), sizeof(cap->card));
2375 memset(orientation,0x00,sizeof(orientation));
2376 for (i=0; i<RK_CAM_NUM;i++) {
2377 if ((pcdev->pdata->info[i].dev_name!=NULL) && (strcmp(dev_name(pcdev->icd->pdev), pcdev->pdata->info[i].dev_name) == 0)) {
2378 sprintf(orientation,"-%d",pcdev->pdata->info[i].orientation);
2383 new_camera = pcdev->pdata->register_dev_new;
2384 while (strstr(new_camera->dev_name,"end")==NULL) {
2385 if (strcmp(dev_name(pcdev->icd->pdev), new_camera->dev_name) == 0) {
2386 sprintf(orientation,"-%d",new_camera->orientation);
2391 if (orientation[0] != '-') {
2392 RKCAMERA_TR("%s: %s is not registered in rk29_camera_platform_data, orientation apply default value",__FUNCTION__,dev_name(pcdev->icd->pdev));
2393 if (strstr(dev_name(pcdev->icd->pdev),"front"))
2394 strcat(cap->card,"-270");
2396 strcat(cap->card,"-90");
2398 strcat(cap->card,orientation);
2400 cap->version = RK_CAM_VERSION_CODE;
2401 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
2405 static int rk_camera_suspend(struct soc_camera_device *icd, pm_message_t state)
2407 struct soc_camera_host *ici =
2408 to_soc_camera_host(icd->dev.parent);
2409 struct rk_camera_dev *pcdev = ici->priv;
2410 struct v4l2_subdev *sd;
2413 mutex_lock(&camera_lock);
2414 if ((pcdev->icd == icd) && (icd->ops->suspend)) {
2415 rk_camera_s_stream(icd, 0);
2416 sd = soc_camera_to_subdev(icd);
2417 v4l2_subdev_call(sd, video, s_stream, 0);
2418 ret = icd->ops->suspend(icd, state);
2420 pcdev->reginfo_suspend.cifCtrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
2421 pcdev->reginfo_suspend.cifCrop = read_cif_reg(pcdev->base,CIF_CIF_CROP);
2422 pcdev->reginfo_suspend.cifFs = read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE);
2423 pcdev->reginfo_suspend.cifIntEn = read_cif_reg(pcdev->base,CIF_CIF_INTEN);
2424 pcdev->reginfo_suspend.cifFmt= read_cif_reg(pcdev->base,CIF_CIF_FOR);
2425 pcdev->reginfo_suspend.cifVirWidth = read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH);
2426 pcdev->reginfo_suspend.cifScale= read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL);
2428 pcdev->reginfo_suspend.Inval = Reg_Validate;
2429 rk_camera_deactivate(pcdev);
2431 RKCAMERA_DG("%s Enter Success...\n", __FUNCTION__);
2433 RKCAMERA_DG("%s icd has been deattach, don't need enter suspend\n", __FUNCTION__);
2435 mutex_unlock(&camera_lock);
2439 static int rk_camera_resume(struct soc_camera_device *icd)
2441 struct soc_camera_host *ici =
2442 to_soc_camera_host(icd->dev.parent);
2443 struct rk_camera_dev *pcdev = ici->priv;
2444 struct v4l2_subdev *sd;
2447 mutex_lock(&camera_lock);
2448 if ((pcdev->icd == icd) && (icd->ops->resume)) {
2449 if (pcdev->reginfo_suspend.Inval == Reg_Validate) {
2450 rk_camera_activate(pcdev, icd);
2451 write_cif_reg(pcdev->base,CIF_CIF_CTRL, pcdev->reginfo_suspend.cifCtrl&~ENABLE_CAPTURE);
2452 write_cif_reg(pcdev->base,CIF_CIF_INTEN, pcdev->reginfo_suspend.cifIntEn);
2453 write_cif_reg(pcdev->base,CIF_CIF_CROP, pcdev->reginfo_suspend.cifCrop);
2454 write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, pcdev->reginfo_suspend.cifFs);
2455 write_cif_reg(pcdev->base,CIF_CIF_FOR, pcdev->reginfo_suspend.cifFmt);
2456 write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH,pcdev->reginfo_suspend.cifVirWidth);
2457 write_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL, pcdev->reginfo_suspend.cifScale);
2458 rk_videobuf_capture(pcdev->active,pcdev);
2459 rk_camera_s_stream(icd, 1);
2460 pcdev->reginfo_suspend.Inval = Reg_Invalidate;
2462 RKCAMERA_TR("Resume fail, vip register recored is invalidate!!\n");
2463 goto rk_camera_resume_end;
2466 ret = icd->ops->resume(icd);
2467 sd = soc_camera_to_subdev(icd);
2468 v4l2_subdev_call(sd, video, s_stream, 1);
2470 RKCAMERA_DG("%s Enter success\n",__FUNCTION__);
2472 RKCAMERA_DG("%s icd has been deattach, don't need enter resume\n", __FUNCTION__);
2475 rk_camera_resume_end:
2476 mutex_unlock(&camera_lock);
2480 static void rk_camera_reinit_work(struct work_struct *work)
2482 struct v4l2_subdev *sd;
2483 struct rk_camera_work *camera_work = container_of(work, struct rk_camera_work, work);
2484 struct rk_camera_dev *pcdev = camera_work->pcdev;
2485 struct soc_camera_link *tmp_soc_cam_link;
2487 unsigned long flags = 0;
2488 if(pcdev->icd == NULL)
2490 sd = soc_camera_to_subdev(pcdev->icd);
2491 tmp_soc_cam_link = to_soc_camera_link(pcdev->icd);
2494 RKCAMERA_TR("CIF_CIF_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CTRL));
2495 RKCAMERA_TR("CIF_CIF_INTEN = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTEN));
2496 RKCAMERA_TR("CIF_CIF_INTSTAT = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_INTSTAT));
2497 RKCAMERA_TR("CIF_CIF_FOR = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_FOR));
2498 RKCAMERA_TR("CIF_CIF_CROP = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_CROP));
2499 RKCAMERA_TR("CIF_CIF_SET_SIZE = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SET_SIZE));
2500 RKCAMERA_TR("CIF_CIF_SCL_CTRL = 0x%x\n",read_cif_reg(pcdev->base,CIF_CIF_SCL_CTRL));
2501 RKCAMERA_TR("CRU_PCLK_REG30 = 0X%x\n",read_cru_reg(CRU_PCLK_REG30));
2502 RKCAMERA_TR("CIF_CIF_LAST_LINE = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_LINE));
2504 RKCAMERA_TR("CIF_CIF_LAST_PIX = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LAST_PIX));
2505 RKCAMERA_TR("CIF_CIF_VIR_LINE_WIDTH = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH));
2506 RKCAMERA_TR("CIF_CIF_LINE_NUM_ADDR = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_LINE_NUM_ADDR));
2507 RKCAMERA_TR("CIF_CIF_FRM0_ADDR_Y = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_Y));
2508 RKCAMERA_TR("CIF_CIF_FRM0_ADDR_UV = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRM0_ADDR_UV));
2509 RKCAMERA_TR("CIF_CIF_FRAME_STATUS = 0X%x\n",read_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS));
2512 pcdev->stop_cif = true;
2513 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (read_cif_reg(pcdev->base,CIF_CIF_CTRL)&(~ENABLE_CAPTURE)));
2514 RKCAMERA_DG("the reinit times = %d\n",pcdev->reinit_times);
2516 if(pcdev->video_vq && pcdev->video_vq->irqlock){
2517 spin_lock_irqsave(pcdev->video_vq->irqlock, flags);
2518 for (index = 0; index < VIDEO_MAX_FRAME; index++) {
2519 if (NULL == pcdev->video_vq->bufs[index])
2522 if (pcdev->video_vq->bufs[index]->state == VIDEOBUF_QUEUED) {
2523 list_del_init(&pcdev->video_vq->bufs[index]->queue);
2524 pcdev->video_vq->bufs[index]->state = VIDEOBUF_NEEDS_INIT;
2525 wake_up_all(&pcdev->video_vq->bufs[index]->done);
2526 printk("wake up video buffer index = %d !!!\n",index);
2529 spin_unlock_irqrestore(pcdev->video_vq->irqlock, flags);
2531 RKCAMERA_TR("video queue has somthing wrong !!\n");
2534 RKCAMERA_TR("the %d reinit times ,wake up video buffers!\n ",pcdev->reinit_times);
2536 static enum hrtimer_restart rk_camera_fps_func(struct hrtimer *timer)
2538 struct rk_camera_frmivalenum *fival_nxt=NULL,*fival_pre=NULL, *fival_rec=NULL;
2539 struct rk_camera_timer *fps_timer = container_of(timer, struct rk_camera_timer, timer);
2540 struct rk_camera_dev *pcdev = fps_timer->pcdev;
2542 // static unsigned int last_fps = 0;
2543 struct soc_camera_link *tmp_soc_cam_link;
2544 tmp_soc_cam_link = to_soc_camera_link(pcdev->icd);
2546 RKCAMERA_DG("rk_camera_fps_func fps:0x%x\n",pcdev->fps);
2547 if ((pcdev->fps < 1) || (pcdev->last_fps == pcdev->fps)) {
2548 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);
2549 pcdev->camera_reinit_work.pcdev = pcdev;
2550 //INIT_WORK(&(pcdev->camera_reinit_work.work), rk_camera_reinit_work);
2551 pcdev->reinit_times++;
2552 queue_work(pcdev->camera_wq,&(pcdev->camera_reinit_work.work));
2553 } else if(!pcdev->timer_get_fps) {
2554 pcdev->timer_get_fps = true;
2555 for (i=0; i<2; i++) {
2556 if (pcdev->icd == pcdev->icd_frmival[i].icd) {
2557 fival_nxt = pcdev->icd_frmival[i].fival_list;
2562 fival_pre = fival_nxt;
2563 while (fival_nxt != NULL) {
2565 RKCAMERA_DG("%s %c%c%c%c %dx%d framerate : %d/%d\n", dev_name(&pcdev->icd->dev),
2566 fival_nxt->fival.pixel_format & 0xFF, (fival_nxt->fival.pixel_format >> 8) & 0xFF,
2567 (fival_nxt->fival.pixel_format >> 16) & 0xFF, (fival_nxt->fival.pixel_format >> 24),
2568 fival_nxt->fival.width, fival_nxt->fival.height, fival_nxt->fival.discrete.denominator,
2569 fival_nxt->fival.discrete.numerator);
2571 if (((fival_nxt->fival.pixel_format == pcdev->pixfmt)
2572 && (fival_nxt->fival.height == pcdev->icd->user_height)
2573 && (fival_nxt->fival.width == pcdev->icd->user_width))
2574 || (fival_nxt->fival.discrete.denominator == 0)) {
2576 if (fival_nxt->fival.discrete.denominator == 0) {
2577 fival_nxt->fival.index = 0;
2578 fival_nxt->fival.width = pcdev->icd->user_width;
2579 fival_nxt->fival.height= pcdev->icd->user_height;
2580 fival_nxt->fival.pixel_format = pcdev->pixfmt;
2581 fival_nxt->fival.discrete.denominator = pcdev->frame_interval;
2582 fival_nxt->fival.reserved[1] = (pcdev->icd_width<<16)
2583 |(pcdev->icd_height);
2584 fival_nxt->fival.discrete.numerator = 1000000;
2585 fival_nxt->fival.type = V4L2_FRMIVAL_TYPE_DISCRETE;
2588 fival_rec = fival_nxt;
2590 fival_pre = fival_nxt;
2591 fival_nxt = fival_nxt->nxt;
2594 if ((rec_flag == 0) && fival_pre) {
2595 fival_pre->nxt = kzalloc(sizeof(struct rk_camera_frmivalenum), GFP_ATOMIC);
2596 if (fival_pre->nxt != NULL) {
2597 fival_pre->nxt->fival.index = fival_pre->fival.index++;
2598 fival_pre->nxt->fival.width = pcdev->icd->user_width;
2599 fival_pre->nxt->fival.height= pcdev->icd->user_height;
2600 fival_pre->nxt->fival.pixel_format = pcdev->pixfmt;
2602 fival_pre->nxt->fival.discrete.denominator = pcdev->frame_interval;
2603 fival_pre->nxt->fival.reserved[1] = (pcdev->icd_width<<16)
2604 |(pcdev->icd_height);
2605 fival_pre->nxt->fival.discrete.numerator = 1000000;
2606 fival_pre->nxt->fival.type = V4L2_FRMIVAL_TYPE_DISCRETE;
2608 fival_rec = fival_pre->nxt;
2612 pcdev->last_fps = pcdev->fps ;
2613 pcdev->fps_timer.timer.node.expires= ktime_add_us(pcdev->fps_timer.timer.node.expires, ktime_to_us(ktime_set(3, 0)));
2614 pcdev->fps_timer.timer._softexpires= ktime_add_us(pcdev->fps_timer.timer._softexpires, ktime_to_us(ktime_set(3, 0)));
2615 //return HRTIMER_NORESTART;
2616 if(pcdev->reinit_times >=2)
2617 return HRTIMER_NORESTART;
2619 return HRTIMER_RESTART;
2621 static int rk_camera_s_stream(struct soc_camera_device *icd, int enable)
2623 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2624 struct rk_camera_dev *pcdev = ici->priv;
2627 unsigned long flags;
2629 WARN_ON(pcdev->icd != icd);
2631 cif_ctrl_val = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
2634 pcdev->last_fps = 0;
2635 pcdev->frame_interval = 0;
2636 hrtimer_cancel(&(pcdev->fps_timer.timer));
2637 pcdev->fps_timer.pcdev = pcdev;
2638 pcdev->timer_get_fps = false;
2639 pcdev->reinit_times = 0;
2640 pcdev->stop_cif = false;
2642 cif_ctrl_val |= ENABLE_CAPTURE;
2643 write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val);
2644 hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL);
2645 pcdev->fps_timer.istarted = true;
2647 //cancel timer before stop cif
2648 ret = hrtimer_cancel(&pcdev->fps_timer.timer);
2649 pcdev->fps_timer.istarted = false;
2650 flush_work(&(pcdev->camera_reinit_work.work));
2652 cif_ctrl_val &= ~ENABLE_CAPTURE;
2653 spin_lock_irqsave(&pcdev->lock, flags);
2654 write_cif_reg(pcdev->base,CIF_CIF_CTRL, cif_ctrl_val);
2655 pcdev->stop_cif = true;
2656 spin_unlock_irqrestore(&pcdev->lock, flags);
2657 flush_workqueue((pcdev->camera_wq));
2658 RKCAMERA_DG("STREAM_OFF cancel timer and flush work:0x%x \n", ret);
2660 //must be reinit,or will be somthing wrong in irq process.
2661 if(enable == false) {
2662 pcdev->active = NULL;
2663 INIT_LIST_HEAD(&pcdev->capture);
2665 RKCAMERA_DG("s_stream: enable : 0x%x , CIF_CIF_CTRL = 0x%x\n",enable,read_cif_reg(pcdev->base,CIF_CIF_CTRL));
2668 int rk_camera_enum_frameintervals(struct soc_camera_device *icd, struct v4l2_frmivalenum *fival)
2670 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2671 struct rk_camera_dev *pcdev = ici->priv;
2672 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
2673 struct rk_camera_frmivalenum *fival_list = NULL;
2674 struct v4l2_frmivalenum *fival_head = NULL;
2675 struct rkcamera_platform_data *new_camera;
2676 int i,ret = 0,index;
2677 const struct soc_camera_format_xlate *xlate;
2678 struct v4l2_mbus_framefmt mf;
2681 index = fival->index & 0x00ffffff;
2682 if ((fival->index & 0xff000000) == 0xff000000) { /* ddl@rock-chips.com: detect framerate */
2683 for (i=0; i<2; i++) {
2684 if (pcdev->icd_frmival[i].icd == icd) {
2685 fival_list = pcdev->icd_frmival[i].fival_list;
2689 if (fival_list != NULL) {
2691 while (fival_list != NULL) {
2692 if ((fival->pixel_format == fival_list->fival.pixel_format)
2693 && (fival->height == fival_list->fival.height)
2694 && (fival->width == fival_list->fival.width)) {
2699 fival_list = fival_list->nxt;
2702 if ((i==index) && (fival_list != NULL)) {
2703 memcpy(fival, &fival_list->fival, sizeof(struct v4l2_frmivalenum));
2708 RKCAMERA_TR("%s: fival_list is NULL\n",__FUNCTION__);
2713 for (i=0; i<RK_CAM_NUM; i++) {
2714 if (pcdev->pdata->info[i].dev_name && (strcmp(dev_name(pcdev->icd->pdev),pcdev->pdata->info[i].dev_name) == 0)) {
2715 fival_head = pcdev->pdata->info[i].fival;
2721 while (fival_head->width && fival_head->height) {
2722 if ((fival->pixel_format == fival_head->pixel_format)
2723 && (fival->height == fival_head->height)
2724 && (fival->width == fival_head->width)) {
2733 if ((i == index) && (fival->height == fival_head->height) && (fival->width == fival_head->width)) {
2734 memcpy(fival, fival_head, sizeof(struct v4l2_frmivalenum));
2736 pixfmt = fival->pixel_format; /* ddl@rock-chips.com: v0.3.9 */
2737 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
2738 memset(&mf,0x00,sizeof(struct v4l2_mbus_framefmt));
2739 mf.width = fival->width;
2740 mf.height = fival->height;
2741 mf.code = xlate->code;
2743 v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
2745 fival->reserved[1] = (mf.width<<16)|(mf.height);
2747 RKCAMERA_DG("%s %dx%d@%c%c%c%c framerate : %d/%d\n", dev_name(pcdev->icd->pdev),
2748 fival->width, fival->height,
2749 fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
2750 (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
2751 fival->discrete.denominator,fival->discrete.numerator);
2754 RKCAMERA_TR("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(pcdev->icd->pdev),
2755 fival->width,fival->height,
2756 fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
2757 (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
2760 RKCAMERA_DG("%s have not catch %d%d@%c%c%c%c index(%d) framerate\n",dev_name(pcdev->icd->pdev),
2761 fival->width,fival->height,
2762 fival->pixel_format & 0xFF, (fival->pixel_format >> 8) & 0xFF,
2763 (fival->pixel_format >> 16) & 0xFF, (fival->pixel_format >> 24),
2766 goto rk_camera_enum_frameintervals_end;
2770 new_camera = pcdev->pdata->register_dev_new;
2771 while (strstr(new_camera->dev_name,"end")==NULL) {
2772 if (strcmp(new_camera->dev_name, dev_name(pcdev->icd->pdev)) == 0) {
2780 printk(KERN_ERR "%s(%d): %s have not found in new_camera[] and rk_camera_platform_data!",
2781 __FUNCTION__,__LINE__,dev_name(pcdev->icd->pdev));
2784 pixfmt = fival->pixel_format; /* ddl@rock-chips.com: v0.3.9 */
2785 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
2786 memset(&mf,0x00,sizeof(struct v4l2_mbus_framefmt));
2787 mf.width = fival->width;
2788 mf.height = fival->height;
2789 mf.code = xlate->code;
2791 v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
2793 fival->discrete.numerator= 1000;
2794 fival->discrete.denominator = 15000;
2795 fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
2796 fival->reserved[1] = (mf.width<<16)|(mf.height);
2800 rk_camera_enum_frameintervals_end:
2804 static int rk_camera_set_digit_zoom(struct soc_camera_device *icd,
2805 const struct v4l2_queryctrl *qctrl, int zoom_rate)
2808 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2809 struct rk_camera_dev *pcdev = ici->priv;
2811 unsigned long tmp_cifctrl;
2814 //change the crop and scale parameters
2817 a.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2818 //a.c.width = pcdev->host_width*100/zoom_rate;
2819 a.c.width = pcdev->host_width*100/zoom_rate;
2820 a.c.width &= ~CROP_ALIGN_BYTES;
2821 a.c.height = pcdev->host_height*100/zoom_rate;
2822 a.c.height &= ~CROP_ALIGN_BYTES;
2823 a.c.left = (((pcdev->host_width - a.c.width)>>1)+pcdev->host_left)&(~0x01);
2824 a.c.top = (((pcdev->host_height - a.c.height)>>1)+pcdev->host_top)&(~0x01);
2825 pcdev->stop_cif = true;
2826 tmp_cifctrl = read_cif_reg(pcdev->base,CIF_CIF_CTRL);
2827 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl & ~ENABLE_CAPTURE));
2828 hrtimer_cancel(&(pcdev->fps_timer.timer));
2829 flush_workqueue((pcdev->camera_wq));
2831 down(&pcdev->zoominfo.sem);
2832 pcdev->zoominfo.a.c.left = 0;
2833 pcdev->zoominfo.a.c.top = 0;
2834 pcdev->zoominfo.a.c.width = a.c.width;
2835 pcdev->zoominfo.a.c.height = a.c.height;
2836 pcdev->zoominfo.vir_width = pcdev->zoominfo.a.c.width;
2837 pcdev->zoominfo.vir_height = pcdev->zoominfo.a.c.height;
2838 pcdev->frame_inval = 1;
2839 write_cif_reg(pcdev->base,CIF_CIF_CROP, (a.c.left + (a.c.top<<16)));
2840 write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, ((a.c.width ) + (a.c.height<<16)));
2841 write_cif_reg(pcdev->base,CIF_CIF_VIR_LINE_WIDTH, a.c.width);
2842 write_cif_reg(pcdev->base,CIF_CIF_FRAME_STATUS, 0x00000002);//frame1 has been ready to receive data,frame 2 is not used
2844 rk_videobuf_capture(pcdev->active,pcdev);
2845 if(tmp_cifctrl & ENABLE_CAPTURE)
2846 write_cif_reg(pcdev->base,CIF_CIF_CTRL, (tmp_cifctrl | ENABLE_CAPTURE));
2847 up(&pcdev->zoominfo.sem);
2849 pcdev->stop_cif = false;
2850 hrtimer_start(&(pcdev->fps_timer.timer),ktime_set(3, 0),HRTIMER_MODE_REL);
2851 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 );
2853 a.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2854 a.c.width = pcdev->host_width*100/zoom_rate;
2855 a.c.width &= ~CROP_ALIGN_BYTES;
2856 a.c.height = pcdev->host_height*100/zoom_rate;
2857 a.c.height &= ~CROP_ALIGN_BYTES;
2858 a.c.left = (pcdev->host_width - a.c.width)>>1;
2859 a.c.top = (pcdev->host_height - a.c.height)>>1;
2861 down(&pcdev->zoominfo.sem);
2862 pcdev->zoominfo.a.c.height = a.c.height;
2863 pcdev->zoominfo.a.c.width = a.c.width;
2864 pcdev->zoominfo.a.c.top = a.c.top;
2865 pcdev->zoominfo.a.c.left = a.c.left;
2866 pcdev->zoominfo.vir_width = pcdev->host_width;
2867 pcdev->zoominfo.vir_height= pcdev->host_height;
2868 up(&pcdev->zoominfo.sem);
2870 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 );
2876 static inline struct v4l2_queryctrl const *rk_camera_soc_camera_find_qctrl(
2877 struct soc_camera_host_ops *ops, int id)
2881 for (i = 0; i < ops->num_controls; i++)
2882 if (ops->controls[i].id == id)
2883 return &ops->controls[i];
2889 static int rk_camera_set_ctrl(struct soc_camera_device *icd,
2890 struct v4l2_control *sctrl)
2893 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2894 const struct v4l2_queryctrl *qctrl;
2895 struct rk_camera_dev *pcdev = ici->priv;
2899 qctrl = rk_camera_soc_camera_find_qctrl(ici->ops, sctrl->id);
2902 goto rk_camera_set_ctrl_end;
2907 case V4L2_CID_ZOOM_ABSOLUTE:
2909 if ((sctrl->value < qctrl->minimum) || (sctrl->value > qctrl->maximum)){
2911 goto rk_camera_set_ctrl_end;
2913 ret = rk_camera_set_digit_zoom(icd, qctrl, sctrl->value);
2915 pcdev->zoominfo.zoom_rate = sctrl->value;
2917 goto rk_camera_set_ctrl_end;
2925 rk_camera_set_ctrl_end:
2929 static struct soc_camera_host_ops rk_soc_camera_host_ops =
2931 .owner = THIS_MODULE,
2932 .add = rk_camera_add_device,
2933 .remove = rk_camera_remove_device,
2934 .suspend = rk_camera_suspend,
2935 .resume = rk_camera_resume,
2936 .enum_frameinervals = rk_camera_enum_frameintervals,
2937 .set_crop = rk_camera_set_crop,
2938 .get_formats = rk_camera_get_formats,
2939 .put_formats = rk_camera_put_formats,
2940 .set_fmt = rk_camera_set_fmt,
2941 .try_fmt = rk_camera_try_fmt,
2942 .init_videobuf = rk_camera_init_videobuf,
2943 .reqbufs = rk_camera_reqbufs,
2944 .poll = rk_camera_poll,
2945 .querycap = rk_camera_querycap,
2946 .set_bus_param = rk_camera_set_bus_param,
2947 .s_stream = rk_camera_s_stream, /* ddl@rock-chips.com : Add stream control for host */
2948 .set_ctrl = rk_camera_set_ctrl,
2949 .controls = rk_camera_controls,
2950 .num_controls = ARRAY_SIZE(rk_camera_controls)
2952 static void rk_camera_cif_iomux(int cif_index)
2954 #if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)
2958 iomux_set(CIF0_CLKOUT);
2959 write_grf_reg(GRF_IO_CON3, (CIF_DRIVER_STRENGTH_MASK|CIF_DRIVER_STRENGTH_8MA));
2960 write_grf_reg(GRF_IO_CON4, (CIF_CLKOUT_AMP_MASK|CIF_CLKOUT_AMP_1V8));
2961 #if (CONFIG_CAMERA_INPUT_FMT_SUPPORT & (RK_CAM_INPUT_FMT_RAW10|RK_CAM_INPUT_FMT_RAW12))
2965 #if (CONFIG_CAMERA_INPUT_FMT_SUPPORT & RK_CAM_INPUT_FMT_RAW12)
2966 iomux_set(CIF0_D10);
2967 iomux_set(CIF0_D11);
2968 RKCAMERA_TR("%s(%d): WARNING: Cif 0 is configurated that support RAW 12bit, so I2C3 is invalidate!!\n",__FUNCTION__,__LINE__);
2974 RKCAMERA_TR("%s(%d): Cif index(%d) is invalidate!!!\n",__FUNCTION__,__LINE__, cif_index);
2977 #elif defined(CONFIG_ARCH_RK30)
2981 rk30_mux_api_set(GPIO1B3_CIF0CLKOUT_NAME, GPIO1B_CIF0_CLKOUT);
2982 #if (CONFIG_CAMERA_INPUT_FMT_SUPPORT & (RK_CAM_INPUT_FMT_RAW10|RK_CAM_INPUT_FMT_RAW12))
2983 rk30_mux_api_set(GPIO1B4_CIF0DATA0_NAME, GPIO1B_CIF0_DATA0);
2984 rk30_mux_api_set(GPIO1B5_CIF0DATA1_NAME, GPIO1B_CIF0_DATA1);
2986 #if (CONFIG_CAMERA_INPUT_FMT_SUPPORT & RK_CAM_INPUT_FMT_RAW12)
2987 rk30_mux_api_set(GPIO1B6_CIFDATA10_NAME, GPIO1B_CIF_DATA10);
2988 rk30_mux_api_set(GPIO1B7_CIFDATA11_NAME, GPIO1B_CIF_DATA11);
2994 rk30_mux_api_set(GPIO1C0_CIF1DATA2_RMIICLKOUT_RMIICLKIN_NAME,GPIO1C_CIF1_DATA2);
2995 rk30_mux_api_set(GPIO1C1_CIFDATA3_RMIITXEN_NAME,GPIO1C_CIF_DATA3);
2996 rk30_mux_api_set(GPIO1C2_CIF1DATA4_RMIITXD1_NAME,GPIO1C_CIF1_DATA4);
2997 rk30_mux_api_set(GPIO1C3_CIFDATA5_RMIITXD0_NAME,GPIO1C_CIF_DATA5);
2998 rk30_mux_api_set(GPIO1C4_CIFDATA6_RMIIRXERR_NAME,GPIO1C_CIF_DATA6);
2999 rk30_mux_api_set(GPIO1C5_CIFDATA7_RMIICRSDVALID_NAME,GPIO1C_CIF_DATA7);
3000 rk30_mux_api_set(GPIO1C6_CIFDATA8_RMIIRXD1_NAME,GPIO1C_CIF_DATA8);
3001 rk30_mux_api_set(GPIO1C7_CIFDATA9_RMIIRXD0_NAME,GPIO1C_CIF_DATA9);
3003 rk30_mux_api_set(GPIO1D0_CIF1VSYNC_MIIMD_NAME,GPIO1D_CIF1_VSYNC);
3004 rk30_mux_api_set(GPIO1D1_CIF1HREF_MIIMDCLK_NAME,GPIO1D_CIF1_HREF);
3005 rk30_mux_api_set(GPIO1D2_CIF1CLKIN_NAME,GPIO1D_CIF1_CLKIN);
3006 rk30_mux_api_set(GPIO1D3_CIF1DATA0_NAME,GPIO1D_CIF1_DATA0);
3007 rk30_mux_api_set(GPIO1D4_CIF1DATA1_NAME,GPIO1D_CIF1_DATA1);
3008 rk30_mux_api_set(GPIO1D5_CIF1DATA10_NAME,GPIO1D_CIF1_DATA10);
3009 rk30_mux_api_set(GPIO1D6_CIF1DATA11_NAME,GPIO1D_CIF1_DATA11);
3010 rk30_mux_api_set(GPIO1D7_CIF1CLKOUT_NAME,GPIO1D_CIF1_CLKOUT);
3014 RKCAMERA_TR("%s(%d): Cif index(%d) is invalidate!!!\n",__FUNCTION__,__LINE__, cif_index);
3021 static int rk_camera_probe(struct platform_device *pdev)
3023 struct rk_camera_dev *pcdev;
3024 struct resource *res;
3025 struct rk_camera_frmivalenum *fival_list,*fival_nxt;
3026 struct rk29camera_mem_res *meminfo_ptr,*meminfo_ptrr;
3029 struct rk_cif_clk *clk=NULL;
3031 RKCAMERA_TR("%s version: v%d.%d.%d Zoom by %s",RK29_CAM_DRV_NAME,(RK_CAM_VERSION_CODE&0xff0000)>>16,
3032 (RK_CAM_VERSION_CODE&0xff00)>>8,RK_CAM_VERSION_CODE&0xff,CAMERA_SCALE_CROP_MACHINE);
3034 if ((pdev->id == RK_CAM_PLATFORM_DEV_ID_1) && (RK_SUPPORT_CIF1 == 0)) {
3035 RKCAMERA_TR("%s(%d): This chip is not support CIF1!!\n",__FUNCTION__,__LINE__);
3039 if ((pdev->id == RK_CAM_PLATFORM_DEV_ID_0) && (RK_SUPPORT_CIF0 == 0)) {
3040 RKCAMERA_TR("%s(%d): This chip is not support CIF0!!\n",__FUNCTION__,__LINE__);
3044 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
3045 irq = platform_get_irq(pdev, 0);
3046 if (!res || irq < 0) {
3050 pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL);
3052 dev_err(&pdev->dev, "Could not allocate pcdev\n");
3057 pcdev->zoominfo.zoom_rate = 100;
3058 pcdev->hostid = pdev->id;
3059 #ifdef CONFIG_SOC_RK3028
3060 pcdev->chip_id = rk3028_version_val();
3062 pcdev->chip_id = -1;
3067 cif_clk[0].pd_cif = clk_get(NULL, "pd_cif0");
3068 cif_clk[0].aclk_cif = clk_get(NULL, "aclk_cif0");
3069 cif_clk[0].hclk_cif = clk_get(NULL, "hclk_cif0");
3070 cif_clk[0].cif_clk_in = clk_get(NULL, "cif0_in");
3071 cif_clk[0].cif_clk_out = clk_get(NULL, "cif0_out");
3072 spin_lock_init(&cif_clk[0].lock);
3073 cif_clk[0].on = false;
3074 rk_camera_cif_iomux(0);
3077 cif_clk[1].pd_cif = clk_get(NULL, "pd_cif1");
3078 cif_clk[1].aclk_cif = clk_get(NULL, "aclk_cif1");
3079 cif_clk[1].hclk_cif = clk_get(NULL, "hclk_cif1");
3080 cif_clk[1].cif_clk_in = clk_get(NULL, "cif1_in");
3081 cif_clk[1].cif_clk_out = clk_get(NULL, "cif1_out");
3082 spin_lock_init(&cif_clk[1].lock);
3083 cif_clk[1].on = false;
3084 rk_camera_cif_iomux(1);
3087 dev_set_drvdata(&pdev->dev, pcdev);
3089 pcdev->pdata = pdev->dev.platform_data; /* ddl@rock-chips.com : Request IO in init function */
3091 if (pcdev->pdata && pcdev->pdata->io_init) {
3092 pcdev->pdata->io_init();
3094 if (pcdev->pdata->sensor_mclk == NULL)
3095 pcdev->pdata->sensor_mclk = rk_camera_mclk_ctrl;
3098 meminfo_ptr = IS_CIF0()? (&pcdev->pdata->meminfo):(&pcdev->pdata->meminfo_cif1);
3099 meminfo_ptrr = IS_CIF0()? (&pcdev->pdata->meminfo_cif1):(&pcdev->pdata->meminfo);
3101 if (meminfo_ptr->vbase == NULL) {
3103 if ((meminfo_ptr->start == meminfo_ptrr->start)
3104 && (meminfo_ptr->size == meminfo_ptrr->size) && meminfo_ptrr->vbase) {
3106 meminfo_ptr->vbase = meminfo_ptrr->vbase;
3109 if (!request_mem_region(meminfo_ptr->start,meminfo_ptr->size,"rk29_vipmem")) {
3111 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);
3112 goto exit_ioremap_vipmem;
3114 meminfo_ptr->vbase = pcdev->vipmem_virbase = ioremap_cached(meminfo_ptr->start,meminfo_ptr->size);
3115 if (pcdev->vipmem_virbase == NULL) {
3116 RKCAMERA_TR("%s(%d): ioremap of CIF internal memory(Ex:IPP process/raw process) failed\n",__FUNCTION__,__LINE__);
3118 goto exit_ioremap_vipmem;
3123 pcdev->vipmem_phybase = meminfo_ptr->start;
3124 pcdev->vipmem_size = meminfo_ptr->size;
3125 pcdev->vipmem_virbase = meminfo_ptr->vbase;
3127 INIT_LIST_HEAD(&pcdev->capture);
3128 INIT_LIST_HEAD(&pcdev->camera_work_queue);
3129 spin_lock_init(&pcdev->lock);
3130 spin_lock_init(&pcdev->camera_work_lock);
3131 sema_init(&pcdev->zoominfo.sem,1);
3134 * Request the regions.
3137 if (!request_mem_region(res->start, res->end - res->start + 1,
3138 RK29_CAM_DRV_NAME)) {
3140 goto exit_reqmem_vip;
3142 pcdev->base = ioremap(res->start, res->end - res->start + 1);
3143 if (pcdev->base == NULL) {
3144 dev_err(pcdev->dev, "ioremap() of registers failed\n");
3146 goto exit_ioremap_vip;
3151 pcdev->dev = &pdev->dev;
3153 /* config buffer address */
3156 err = request_irq(pcdev->irq, rk_camera_irq, 0, RK29_CAM_DRV_NAME,
3159 dev_err(pcdev->dev, "Camera interrupt register failed \n");
3165 pcdev->camera_wq = create_workqueue("rk_cam_wkque_cif0");
3167 pcdev->camera_wq = create_workqueue("rk_cam_wkque_cif1");
3169 if (pcdev->camera_wq == NULL) {
3170 RKCAMERA_TR("%s(%d): Create workqueue failed!\n",__FUNCTION__,__LINE__);
3174 pcdev->camera_reinit_work.pcdev = pcdev;
3175 INIT_WORK(&(pcdev->camera_reinit_work.work), rk_camera_reinit_work);
3177 for (i=0; i<2; i++) {
3178 pcdev->icd_frmival[i].icd = NULL;
3179 pcdev->icd_frmival[i].fival_list = kzalloc(sizeof(struct rk_camera_frmivalenum),GFP_KERNEL);
3182 pcdev->soc_host.drv_name = RK29_CAM_DRV_NAME;
3183 pcdev->soc_host.ops = &rk_soc_camera_host_ops;
3184 pcdev->soc_host.priv = pcdev;
3185 pcdev->soc_host.v4l2_dev.dev = &pdev->dev;
3186 pcdev->soc_host.nr = pdev->id;
3188 err = soc_camera_host_register(&pcdev->soc_host);
3190 RKCAMERA_TR("%s(%d): soc_camera_host_register failed\n",__FUNCTION__,__LINE__);
3193 pcdev->fps_timer.pcdev = pcdev;
3194 hrtimer_init(&(pcdev->fps_timer.timer), CLOCK_MONOTONIC, HRTIMER_MODE_REL);
3195 pcdev->fps_timer.timer.function = rk_camera_fps_func;
3196 pcdev->icd_cb.sensor_cb = NULL;
3198 #if (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_IPP)
3199 pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_ipp;
3200 #elif (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_ARM)
3201 pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_arm;
3202 #elif (CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_RGA)
3203 pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_rga;
3204 #elif(CONFIG_CAMERA_SCALE_CROP_MACHINE == RK_CAM_SCALE_CROP_PP)
3205 pcdev->icd_cb.scale_crop_cb = rk_camera_scale_crop_pp;
3207 RKCAMERA_DG("%s exit \n",__FUNCTION__);
3212 for (i=0; i<2; i++) {
3213 fival_list = pcdev->icd_frmival[i].fival_list;
3214 fival_nxt = fival_list;
3215 while(fival_nxt != NULL) {
3216 fival_nxt = fival_list->nxt;
3218 fival_list = fival_nxt;
3222 free_irq(pcdev->irq, pcdev);
3223 if (pcdev->camera_wq) {
3224 destroy_workqueue(pcdev->camera_wq);
3225 pcdev->camera_wq = NULL;
3228 iounmap(pcdev->base);
3230 release_mem_region(res->start, res->end - res->start + 1);
3231 exit_ioremap_vipmem:
3232 if (pcdev->vipmem_virbase)
3233 iounmap(pcdev->vipmem_virbase);
3234 release_mem_region(pcdev->vipmem_phybase,pcdev->vipmem_size);
3238 clk_put(clk->pd_cif);
3240 clk_put(clk->aclk_cif);
3242 clk_put(clk->hclk_cif);
3243 if (clk->cif_clk_in)
3244 clk_put(clk->cif_clk_in);
3245 if (clk->cif_clk_out)
3246 clk_put(clk->cif_clk_out);
3255 static int __devexit rk_camera_remove(struct platform_device *pdev)
3257 struct rk_camera_dev *pcdev = platform_get_drvdata(pdev);
3258 struct resource *res;
3259 struct rk_camera_frmivalenum *fival_list,*fival_nxt;
3260 struct rk29camera_mem_res *meminfo_ptr,*meminfo_ptrr;
3263 free_irq(pcdev->irq, pcdev);
3265 if (pcdev->camera_wq) {
3266 destroy_workqueue(pcdev->camera_wq);
3267 pcdev->camera_wq = NULL;
3270 for (i=0; i<2; i++) {
3271 fival_list = pcdev->icd_frmival[i].fival_list;
3272 fival_nxt = fival_list;
3273 while(fival_nxt != NULL) {
3274 fival_nxt = fival_list->nxt;
3276 fival_list = fival_nxt;
3280 soc_camera_host_unregister(&pcdev->soc_host);
3282 meminfo_ptr = IS_CIF0()? (&pcdev->pdata->meminfo):(&pcdev->pdata->meminfo_cif1);
3283 meminfo_ptrr = IS_CIF0()? (&pcdev->pdata->meminfo_cif1):(&pcdev->pdata->meminfo);
3284 if (meminfo_ptr->vbase) {
3285 if (meminfo_ptr->vbase == meminfo_ptrr->vbase) {
3286 meminfo_ptr->vbase = NULL;
3288 iounmap((void __iomem*)pcdev->vipmem_virbase);
3289 release_mem_region(pcdev->vipmem_phybase, pcdev->vipmem_size);
3290 meminfo_ptr->vbase = NULL;
3295 iounmap((void __iomem*)pcdev->base);
3296 release_mem_region(res->start, res->end - res->start + 1);
3297 if (pcdev->pdata && pcdev->pdata->io_deinit) { /* ddl@rock-chips.com : Free IO in deinit function */
3298 pcdev->pdata->io_deinit(0);
3299 pcdev->pdata->io_deinit(1);
3304 dev_info(&pdev->dev, "RK28 Camera driver unloaded\n");
3309 static struct platform_driver rk_camera_driver =
3312 .name = RK29_CAM_DRV_NAME,
3314 .probe = rk_camera_probe,
3315 .remove = __devexit_p(rk_camera_remove),
3318 static int rk_camera_init_async(void *unused)
3320 platform_driver_register(&rk_camera_driver);
3324 static int __devinit rk_camera_init(void)
3326 kthread_run(rk_camera_init_async, NULL, "rk_camera_init");
3330 static void __exit rk_camera_exit(void)
3332 platform_driver_unregister(&rk_camera_driver);
3335 device_initcall_sync(rk_camera_init);
3336 module_exit(rk_camera_exit);
3338 MODULE_DESCRIPTION("RKSoc Camera Host driver");
3339 MODULE_AUTHOR("ddl <ddl@rock-chips>");
3340 MODULE_LICENSE("GPL");