Update from product codes
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / media / sprd_dcam / common / dcam_img.c
1 /*
2  * Copyright (C) 2012 Spreadtrum Communications Inc.
3  *
4  * This software is licensed under the terms of the GNU General Public
5  * License version 2, as published by the Free Software Foundation, and
6  * may be copied, distributed, and modified under those terms.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  */
13 #include <linux/module.h>
14 #include <linux/delay.h>
15 #include <linux/errno.h>
16 #include <linux/fs.h>
17 #include <linux/kernel.h>
18 #include <linux/mm.h>
19 #include <linux/ioport.h>
20 #include <linux/init.h>
21 #include <linux/sched.h>
22 #include <linux/version.h>
23 #include <linux/mutex.h>
24 #include <linux/interrupt.h>
25 #include <linux/kthread.h>
26 #include <linux/highmem.h>
27 #include <linux/freezer.h>
28 #include <linux/platform_device.h>
29 #include <linux/miscdevice.h>
30 #ifndef CONFIG_64BIT
31 #include <soc/sprd/board.h>
32 #include <soc/sprd/hardware.h>
33 #include <soc/sprd/adi.h>
34 #endif
35 #include <linux/module.h>
36 #include <linux/slab.h>
37 #include <linux/proc_fs.h>
38 #include <linux/of.h>
39 #include <linux/of_device.h>
40
41 #include <linux/vmalloc.h>
42 #include "dcam_drv.h"
43
44 #include <asm/io.h>
45
46
47 #include <../flash/flash.h>
48 #include <video/sprd_img.h>
49
50 #include "../../sprd_sensor/csi2/csi_api.h"
51
52 //#define LOCAL   static
53 #define LOCAL
54
55 #define IMG_DEVICE_NAME                         "sprd_image"
56 #define IMAGE_MINOR                             MISC_DYNAMIC_MINOR
57 #define DCAM_INVALID_FOURCC                     0xFFFFFFFF
58 #define DCAM_MAJOR_VERSION                      1
59 #define DCAM_MINOR_VERSION                      0
60 #define DCAM_RELEASE                            0
61 #define DCAM_QUEUE_LENGTH                       16
62 #define DCAM_TIMING_LEN                         16
63 #if CONFIG_SC_FPGA
64 #define DCAM_TIMEOUT                            (2000*100)
65 #else
66 #define DCAM_TIMEOUT                            1500
67 #endif
68
69 #define DCAM_ZOOM_LEVEL_MAX                     4
70 #define DCAM_ZOOM_STEP(x, y)                   (((x) - (y)) / DCAM_ZOOM_LEVEL_MAX)
71 #define DCAM_PIXEL_ALIGNED                         4
72 #define DCAM_WIDTH(w)                          ((w)& ~(DCAM_PIXEL_ALIGNED - 1))
73 #define DCAM_HEIGHT(h)                          ((h)& ~(DCAM_PIXEL_ALIGNED - 1))
74
75 #define DEBUG_STR                               "Error L %d, %s: \n"
76 #define DEBUG_ARGS                              __LINE__,__FUNCTION__
77 #define IMG_RTN_IF_ERR(n)          \
78         do {                        \
79                 if(unlikely(n)) {                \
80                         printk(DEBUG_STR,DEBUG_ARGS);            \
81                         goto exit;       \
82                 }                        \
83         } while(0)
84
85 #define IMG_PRINT_IF_ERR(n)          \
86         do {                        \
87                 if(unlikely(n)) {                \
88                         printk(DEBUG_STR,DEBUG_ARGS);            \
89                 }                        \
90         } while(0)
91
92 #define DCAM_VERSION \
93         KERNEL_VERSION(DCAM_MAJOR_VERSION, DCAM_MINOR_VERSION, DCAM_RELEASE)
94
95 typedef int (*path_cfg_func)(enum dcam_cfg_id, void *);
96
97 enum
98 {
99         PATH_IDLE  = 0x00,
100         PATH_RUN,
101 };
102
103 struct dcam_format {
104         char                       *name;
105         uint32_t                   fourcc;
106         int                        depth;
107 };
108
109 struct dcam_node {
110         uint32_t                   irq_flag;
111         uint32_t                   f_type;
112         uint32_t                   index;
113         uint32_t                   height;
114         uint32_t                   yaddr;
115         uint32_t                   uaddr;
116         uint32_t                   vaddr;
117         uint32_t                   yaddr_vir;
118         uint32_t                   uaddr_vir;
119         uint32_t                   vaddr_vir;
120         uint32_t                   invalid_flag;
121         uint32_t                   reserved;
122 };
123
124 struct dcam_queue {
125         struct dcam_node           node[DCAM_QUEUE_LENGTH];
126         struct dcam_node           *write;
127         struct dcam_node           *read;
128         uint32_t                           wcnt;
129         uint32_t                           rcnt;
130 };
131
132 struct dcam_img_buf_addr {
133         struct dcam_addr           frm_addr;
134         struct dcam_addr           frm_addr_vir;
135 };
136
137 struct dcam_img_buf_queue {
138         struct dcam_img_buf_addr   buf_addr[DCAM_FRM_CNT_MAX];
139         struct dcam_img_buf_addr   *write;
140         struct dcam_img_buf_addr   *read;
141         uint32_t                   wcnt;
142         uint32_t                   rcnt;
143 };
144
145 struct dcam_path_spec {
146         uint32_t                   is_work;
147         uint32_t                   is_from_isp;
148         uint32_t                   rot_mode;
149         uint32_t                   status;
150         struct dcam_size           in_size;
151         struct dcam_path_dec       img_deci;
152         struct dcam_rect           in_rect;
153         struct dcam_rect           in_rect_current;
154         struct dcam_rect           in_rect_backup;
155         struct dcam_size           out_size;
156         enum   dcam_fmt            out_fmt;
157         struct dcam_endian_sel     end_sel;
158         uint32_t                   fourcc;
159         uint32_t                   pixel_depth;
160         uint32_t                   frm_id_base;
161         uint32_t                   frm_type;
162         uint32_t                   index[DCAM_FRM_CNT_MAX];
163         //struct dcam_addr           frm_addr[DCAM_FRM_CNT_MAX];
164         //struct dcam_addr           frm_addr_vir[DCAM_FRM_CNT_MAX];
165         struct dcam_img_buf_queue  buf_queue;
166         struct dcam_addr           frm_reserved_addr;
167         struct dcam_addr           frm_reserved_addr_vir;
168         struct dcam_frame          *frm_ptr[DCAM_FRM_CNT_MAX];
169         uint32_t                   frm_cnt_act;
170         uint32_t                   path_frm_deci;
171         uint32_t                   shrink;
172 };
173
174 struct dcam_info {
175         uint32_t                   if_mode;
176         uint32_t                   sn_mode;
177         uint32_t                   yuv_ptn;
178         uint32_t                   data_bits;
179         uint32_t                   is_loose;
180         uint32_t                   lane_num;
181         uint32_t                   pclk;
182         struct dcam_cap_sync_pol   sync_pol;
183         uint32_t                   frm_deci;
184         struct dcam_cap_dec        img_deci;
185         struct dcam_size           cap_in_size;
186         struct dcam_rect           cap_in_rect;
187         struct dcam_size           cap_out_size;
188         struct dcam_size           dst_size;
189         uint32_t                   pxl_fmt;
190         uint32_t                   need_isp_tool;
191         uint32_t                   need_isp;
192         uint32_t                   need_shrink;
193         struct dcam_rect           path_input_rect;
194
195         struct dcam_path_spec      dcam_path[DCAM_PATH_NUM];
196
197         uint32_t                   capture_mode;
198         uint32_t                   skip_number;
199         uint32_t                   flash_status;
200         uint32_t                   after_af;
201         uint32_t                   is_smooth_zoom;
202         struct timeval             timestamp;
203         struct timeval             frame_last_timestamp;
204         uint32_t                   camera_id;
205 };
206
207 struct dcam_dev {
208         struct mutex             dcam_mutex;
209         struct semaphore         irq_sem;
210         atomic_t                 users;
211         struct dcam_info         dcam_cxt;
212         atomic_t                 stream_on;
213         uint32_t                 stream_mode;
214         struct dcam_queue        queue;
215         struct timer_list        dcam_timer;
216         atomic_t                 run_flag;
217         uint32_t                 got_resizer;
218         struct proc_dir_entry*   proc_file;
219         struct semaphore         flash_thread_sem;
220         struct task_struct*      flash_thread;
221         uint32_t                 is_flash_thread_stop;
222         uint32_t                 frame_skipped;
223         struct semaphore         zoom_thread_sem;
224         struct task_struct*      zoom_thread;
225         uint32_t                 is_zoom_thread_stop;
226         uint32_t                 zoom_level;
227         uint32_t                 channel_id;
228         void                     *driver_data;
229 };
230
231 #ifndef __SIMULATOR__
232 LOCAL int sprd_img_tx_done(struct dcam_frame *frame, void* param);
233 LOCAL int sprd_img_tx_error(struct dcam_frame *frame, void* param);
234 LOCAL int sprd_img_no_mem(struct dcam_frame *frame, void* param);
235 LOCAL int sprd_img_queue_write(struct dcam_queue *queue, struct dcam_node *node);
236 LOCAL int sprd_img_queue_read(struct dcam_queue *queue, struct dcam_node *node);
237 LOCAL int sprd_img_queue_disable(struct dcam_queue *queue, uint32_t channel_id);
238 LOCAL int sprd_img_queue_enable(struct dcam_queue *queue, uint32_t channel_id);
239 LOCAL int sprd_img_buf_queue_init(struct dcam_img_buf_queue *queue);
240 LOCAL int sprd_img_queue_init(struct dcam_queue *queue);
241 LOCAL int sprd_img_buf_queue_write(struct dcam_img_buf_queue *queue, struct dcam_img_buf_addr *buf_addr);
242 LOCAL int sprd_img_buf_queue_read(struct dcam_img_buf_queue *queue, struct dcam_img_buf_addr *buf_addr);
243 LOCAL int sprd_start_timer(struct timer_list *dcam_timer, uint32_t time_val);
244 LOCAL int sprd_stop_timer(struct timer_list *dcam_timer);
245 LOCAL int sprd_img_streampause(struct file *file, uint32_t channel_id, uint32_t reconfig_flag);
246 LOCAL int sprd_img_streamresume(struct file *file, uint32_t channel_id);
247 LOCAL int sprd_img_reg_isr(struct dcam_dev* param);
248 LOCAL int sprd_img_reg_path2_isr(struct dcam_dev* param);
249 LOCAL int sprd_img_unreg_isr(struct dcam_dev* param);
250 LOCAL int sprd_img_unreg_path2_isr(struct dcam_dev* param);
251 /*LOCAL int sprd_img_proc_read(char *page, char **start,off_t off, int count, int *eof, void *data);*/
252 LOCAL void sprd_img_print_reg(void);
253 LOCAL int sprd_img_start_zoom(struct dcam_frame *frame, void* param);
254 LOCAL int sprd_img_path_cfg_output_addr(path_cfg_func path_cfg, struct dcam_path_spec* path_spec);
255 LOCAL int sprd_img_local_clear_path_buffer(struct dcam_dev *dev, int path_id);
256
257 LOCAL struct dcam_format dcam_img_fmt[] = {
258         {
259                 .name     = "4:2:2, packed, YUYV",
260                 .fourcc   = IMG_PIX_FMT_YUYV,
261                 .depth    = 16,
262         },
263         {
264                 .name     = "4:2:2, packed, YVYU",
265                 .fourcc   = IMG_PIX_FMT_YVYU,
266                 .depth    = 16,
267         },
268         {
269                 .name     = "4:2:2, packed, UYVY",
270                 .fourcc   = IMG_PIX_FMT_UYVY,
271                 .depth    = 16,
272         },
273         {
274                 .name     = "4:2:2, packed, VYUY",
275                 .fourcc   = IMG_PIX_FMT_VYUY,
276                 .depth    = 16,
277         },
278         {
279                 .name     = "YUV 4:2:2, planar, (Y-Cb-Cr)",
280                 .fourcc   = IMG_PIX_FMT_YUV422P,
281                 .depth    = 16,
282         },
283         {
284                 .name     = "YUV 4:2:0 planar (Y-CbCr)",
285                 .fourcc   = IMG_PIX_FMT_NV12,
286                 .depth    = 12,
287         },
288         {
289                 .name     = "YVU 4:2:0 planar (Y-CrCb)",
290                 .fourcc   = IMG_PIX_FMT_NV21,
291                 .depth    = 12,
292         },
293
294         {
295                 .name     = "YUV 4:2:0 planar (Y-Cb-Cr)",
296                 .fourcc   = IMG_PIX_FMT_YUV420,
297                 .depth    = 12,
298         },
299         {
300                 .name     = "YVU 4:2:0 planar (Y-Cr-Cb)",
301                 .fourcc   = IMG_PIX_FMT_YVU420,
302                 .depth    = 12,
303         },
304         {
305                 .name     = "RGB565 (LE)",
306                 .fourcc   = IMG_PIX_FMT_RGB565,
307                 .depth    = 16,
308         },
309         {
310                 .name     = "RGB565 (BE)",
311                 .fourcc   = IMG_PIX_FMT_RGB565X,
312                 .depth    = 16,
313         },
314         {
315                 .name     = "RawRGB",
316                 .fourcc   = IMG_PIX_FMT_GREY,
317                 .depth    = 8,
318         },
319         {
320                 .name     = "JPEG",
321                 .fourcc   = IMG_PIX_FMT_JPEG,
322                 .depth    = 8,
323         },
324 };
325 #else
326 LOCAL struct dcam_format dcam_img_fmt[] = {
327         {"4:2:2, packed, YUYV", IMG_PIX_FMT_YUYV, 16},
328         {"4:2:2, packed, YVYU", IMG_PIX_FMT_YVYU, 16},
329         {"4:2:2, packed, UYVY", IMG_PIX_FMT_UYVY, 16},
330         {"4:2:2, packed, VYUY", IMG_PIX_FMT_VYUY, 16},
331         {"YUV 4:2:2, planar, (Y-Cb-Cr)", IMG_PIX_FMT_YUV422P, 16},
332         {"YUV 4:2:0 planar (Y-CbCr)", IMG_PIX_FMT_NV12, 12},
333         {"YVU 4:2:0 planar (Y-CrCb)", IMG_PIX_FMT_NV21, 12},
334         {"YUV 4:2:0 planar (Y-Cb-Cr)", IMG_PIX_FMT_YUV420, 12},
335         {"YVU 4:2:0 planar (Y-Cr-Cb)", IMG_PIX_FMT_YVU420, 12},
336         {"RGB565 (LE)", IMG_PIX_FMT_RGB565, 16},
337         {"RGB565 (BE)", IMG_PIX_FMT_RGB565X, 16},
338         {"RawRGB", IMG_PIX_FMT_GREY, 8},
339         {"JPEG", IMG_PIX_FMT_JPEG, 8}
340 };
341 #endif
342
343 enum cmr_flash_status {
344         FLASH_CLOSE = 0x0,
345         FLASH_OPEN = 0x1,
346         FLASH_TORCH = 0x2,      /*user only set flash to close/open/torch state */
347         FLASH_AUTO = 0x3,
348         FLASH_CLOSE_AFTER_OPEN = 0x10,  /* following is set to sensor */
349         FLASH_HIGH_LIGHT = 0x11,
350         FLASH_OPEN_ON_RECORDING = 0x22,
351         FLASH_CLOSE_AFTER_AUTOFOCUS = 0x30,
352         FLASH_STATUS_MAX
353 };
354
355 #define DISCARD_FRAME_TIME (10000)
356
357 LOCAL int img_get_timestamp(struct timeval *tv)
358 {
359         struct timespec ts;
360
361         ktime_get_ts(&ts);
362         tv->tv_sec = ts.tv_sec;
363         tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
364         return 0;
365 }
366 extern int flash_torch_status;
367 LOCAL int sprd_img_setflash(uint32_t flash_mode)
368 {
369         if(flash_torch_status==1)
370                 return 0;
371         switch (flash_mode) {
372         case FLASH_OPEN:        /*flash on */
373         case FLASH_TORCH:        /*for torch */
374                 /*low light */
375                 sprd_flash_on();
376                 break;
377         case FLASH_HIGH_LIGHT:
378                 /*high light */
379                 sprd_flash_high_light();
380                 break;
381         case FLASH_CLOSE_AFTER_OPEN:     /*close flash */
382         case FLASH_CLOSE_AFTER_AUTOFOCUS:
383         case FLASH_CLOSE:
384                 /*close the light */
385                 sprd_flash_close();
386                 break;
387         default:
388                 printk("sprd_img_setflash unknow mode:flash_mode 0x%x \n", flash_mode);
389                 break;
390         }
391
392         DCAM_TRACE("sprd_img_setflash: flash_mode 0x%x  \n", flash_mode);
393
394         return 0;
395 }
396
397 LOCAL int sprd_img_opt_flash(struct dcam_frame *frame, void* param)
398 {
399         struct dcam_dev          *dev = (struct dcam_dev*)param;
400         struct dcam_info         *info = NULL;
401
402         if (dev == NULL) {
403                 DCAM_TRACE("SPRD_IMG: sprd_img_opt_flash, dev is NULL \n");
404                 return 0;
405         }
406
407         info = &dev->dcam_cxt;
408         if (info->flash_status < FLASH_STATUS_MAX) {
409                 DCAM_TRACE("SPRD_IMG: sprd_img_opt_flash, status %d \n", info->flash_status);
410                 if(info->flash_status == FLASH_CLOSE_AFTER_AUTOFOCUS) {
411                         img_get_timestamp(&info->timestamp);
412                         info->after_af = 1;
413                         DCAM_TRACE("SPRD_IMG: sprd_img_opt_flash, time, %d %d \n",
414                                 (int)info->timestamp.tv_sec, (int)info->timestamp.tv_usec);
415                 }
416                 sprd_img_setflash(info->flash_status);
417                 info->flash_status = FLASH_STATUS_MAX;
418         }
419
420         return 0;
421 }
422
423 LOCAL int sprd_img_start_flash(struct dcam_frame *frame, void* param)
424 {
425         struct dcam_dev          *dev = (struct dcam_dev*)param;
426         struct dcam_info         *info = NULL;
427         uint32_t                 need_light = 1;
428
429         if (dev == NULL) {
430                 DCAM_TRACE("SPRD_IMG: sprd_img_start_flash, dev is NULL \n");
431                 return -1;
432         }
433
434         info = &dev->dcam_cxt;
435         if (info->flash_status < FLASH_STATUS_MAX) {
436                 if (FLASH_HIGH_LIGHT == info->flash_status) {
437                         dev->frame_skipped ++;
438                         if (dev->frame_skipped >= info->skip_number) {
439                                 //flash lighted at the last SOF before the right capture frame
440                                 DCAM_TRACE("V4L2: waiting finished \n");
441                         } else {
442                                 need_light = 0;
443                                 DCAM_TRACE("V4L2: wait for the next SOF, %d ,%d \n",
444                                         dev->frame_skipped, info->skip_number);
445                         }
446                 }
447                 if (need_light) {
448                         up(&dev->flash_thread_sem);
449                 }
450         }
451
452         return 0;
453 }
454
455 int flash_thread_loop(void *arg)
456 {
457         struct dcam_dev          *dev = (struct dcam_dev*)arg;
458
459         if (dev == NULL) {
460                 DCAM_TRACE("SPRD_IMG: flash_thread_loop, dev is NULL \n");
461                 return -1;
462         }
463         while (1) {
464                 if (0 == down_interruptible(&dev->flash_thread_sem)) {
465                         if (dev->is_flash_thread_stop) {
466                                 sprd_img_setflash(0);
467                                 DCAM_TRACE("SPRD_IMG: flash_thread_loop stop \n");
468                                 break;
469                         }
470                         sprd_img_opt_flash(NULL, arg);
471                 } else {
472                         DCAM_TRACE("SPRD_IMG: flash int!");
473                         break;
474                 }
475         }
476         dev->is_flash_thread_stop = 0;
477
478         return 0;
479 }
480
481 int dcam_create_flash_thread(void* param)
482 {
483         struct dcam_dev          *dev = (struct dcam_dev*)param;
484
485         if (dev == NULL) {
486                 DCAM_TRACE("SPRD_IMG: dcam_create_flash_thread, dev is NULL \n");
487                 return -1;
488         }
489         dev->is_flash_thread_stop = 0;
490         sema_init(&dev->flash_thread_sem, 0);
491         dev->flash_thread = kthread_run(flash_thread_loop, param, "dcam_flash_thread");
492         if (IS_ERR(dev->flash_thread)) {
493                 printk("SPRD_IMG: dcam_create_flash_thread error!\n");
494                 return -1;
495         }
496         return 0;
497 }
498
499 int dcam_stop_flash_thread(void* param)
500 {
501         struct dcam_dev          *dev = (struct dcam_dev*)param;
502         int cnt = 0;
503
504         if (dev == NULL) {
505                 DCAM_TRACE("SPRD_IMG: sprd_img_opt_flash, dev is NULL \n");
506                 return -1;
507         }
508         if (dev->flash_thread) {
509                 dev->is_flash_thread_stop = 1;
510                 up(&dev->flash_thread_sem);
511                 if (0 != dev->is_flash_thread_stop) {
512                         while (cnt < 500) {
513                                 cnt++;
514                                 if (0 == dev->is_flash_thread_stop)
515                                         break;
516                                 msleep(1);
517                         }
518                 }
519                 dev->flash_thread = NULL;
520         }
521
522         return 0;
523 }
524
525 LOCAL int sprd_img_discard_frame(struct dcam_frame *frame, void* param)
526 {
527         int                                  ret = DCAM_RTN_PARA_ERR;
528         struct dcam_dev          *dev = (struct dcam_dev*)param;
529         struct dcam_info         *info = NULL;
530         struct timeval           timestamp;
531         uint32_t                 flag = 0;
532
533         info = &dev->dcam_cxt;
534         img_get_timestamp(&timestamp);
535         DCAM_TRACE("SPRD_IMG: sprd_img_discard_frame, time, %d %d \n",
536                 (int)timestamp.tv_sec, (int)timestamp.tv_usec);
537         if ((timestamp.tv_sec == info->timestamp.tv_sec)
538                 && (timestamp.tv_usec -info->timestamp.tv_usec >= DISCARD_FRAME_TIME)){
539                 flag = 1;
540         } else if (timestamp.tv_sec > info->timestamp.tv_sec) {
541                 if ((1000000 -info->timestamp.tv_sec) + timestamp.tv_sec >= DISCARD_FRAME_TIME) {
542                         flag = 1;
543                 }
544         }
545
546         if (flag) {
547                 DCAM_TRACE("SPRD_IMG: sprd_img_discard_frame,unlock frame %p \n", frame);
548                 //dcam_frame_unlock(frame);
549                 ret =  DCAM_RTN_SUCCESS;
550         }
551         return ret;
552 }
553
554 LOCAL struct dcam_format *sprd_img_get_format(uint32_t fourcc)
555 {
556         struct dcam_format       *fmt;
557         uint32_t                 i;
558
559         for (i = 0; i < ARRAY_SIZE(dcam_img_fmt); i++) {
560                 fmt = &dcam_img_fmt[i];
561                 if (fmt->fourcc == fourcc)
562                         break;
563         }
564
565         if (unlikely(i == ARRAY_SIZE(dcam_img_fmt)))
566                 return NULL;
567
568         return &dcam_img_fmt[i];
569 }
570
571 LOCAL uint32_t sprd_img_get_fourcc(struct dcam_path_spec *path)
572 {
573         uint32_t                 fourcc = DCAM_INVALID_FOURCC;
574
575         switch (path->out_fmt) {
576         case DCAM_YUV422:
577                 fourcc = IMG_PIX_FMT_YUV422P;
578                 break;
579         case DCAM_YUV420:
580                 if (likely(DCAM_ENDIAN_LITTLE == path->end_sel.uv_endian))
581                         fourcc = IMG_PIX_FMT_NV12;
582                 else
583                         fourcc = IMG_PIX_FMT_NV21;
584                 break;
585         case DCAM_YUV420_3FRAME:
586                 fourcc = IMG_PIX_FMT_YUV420;
587                 break;
588         case DCAM_RGB565:
589                 if (likely(DCAM_ENDIAN_HALFBIG == path->end_sel.uv_endian))
590                         fourcc = IMG_PIX_FMT_RGB565;
591                 else
592                         fourcc = IMG_PIX_FMT_RGB565X;
593                 break;
594         case DCAM_RAWRGB:
595                 fourcc = IMG_PIX_FMT_GREY;
596                 break;
597         case DCAM_JPEG:
598                 fourcc = IMG_PIX_FMT_JPEG;
599                 break;
600         default:
601                 break;
602         }
603         return fourcc;
604 }
605
606 LOCAL uint32_t sprd_img_get_deci_factor(uint32_t src_size, uint32_t dst_size)
607 {
608         uint32_t                 factor = 0;
609
610         if (0 == src_size || 0 == dst_size) {
611                 return factor;
612         }
613
614         for (factor = 0; factor < DCAM_CAP_X_DECI_FAC_MAX; factor ++) {
615                 if (src_size < (uint32_t)(dst_size * (1 << factor))) {
616                         break;
617                 }
618         }
619
620         return factor;
621 }
622
623 LOCAL uint32_t sprd_img_endian_sel(uint32_t fourcc, struct dcam_path_spec *path)
624 {
625         uint32_t                 depth = 0;
626
627         if (IMG_PIX_FMT_YUV422P == fourcc ||
628                 IMG_PIX_FMT_RGB565 == fourcc ||
629                 IMG_PIX_FMT_RGB565X == fourcc) {
630                 depth = 16;
631                 if (IMG_PIX_FMT_YUV422P == fourcc) {
632                         path->out_fmt = DCAM_YUV422;
633                 } else {
634                         path->out_fmt = DCAM_RGB565;
635                         if (IMG_PIX_FMT_RGB565 == fourcc) {
636                                 path->end_sel.y_endian = DCAM_ENDIAN_HALFBIG;
637                         } else {
638                                 path->end_sel.y_endian = DCAM_ENDIAN_BIG;
639                         }
640                 }
641         } else {
642                 depth = 12;
643                 if (IMG_PIX_FMT_YUV420 == fourcc ||
644                         IMG_PIX_FMT_YVU420 == fourcc) {
645                         path->out_fmt = DCAM_YUV420_3FRAME;
646                 } else {
647                         path->out_fmt = DCAM_YUV420;
648                         if (IMG_PIX_FMT_NV12 == fourcc) {
649                                 path->end_sel.uv_endian = DCAM_ENDIAN_LITTLE;
650                         } else {
651                                 path->end_sel.uv_endian = DCAM_ENDIAN_HALFBIG;
652                         }
653                 }
654         }
655
656         return depth;
657 }
658
659 LOCAL int sprd_img_check_path0_cap(uint32_t fourcc,
660                                         struct sprd_img_format *f,
661                                         struct dcam_info   *info)
662 {
663         struct dcam_path_spec    *path = &info->dcam_path[DCAM_PATH0];
664
665         DCAM_TRACE("SPRD_IMG: check format for path0\n");
666
667         path->is_from_isp = f->need_isp;
668         path->rot_mode = f->reserved[0];
669
670         path->frm_type = f->channel_id;
671         path->is_work = 0;
672         DCAM_TRACE("zcf sprd_img_check_path0_cap  rot_mode:%d\n",path->rot_mode);
673
674         switch (fourcc) {
675         case IMG_PIX_FMT_GREY:
676                 path->out_fmt = info->is_loose; // 0 - word/packet, 1 - half word
677                 break;
678
679         case IMG_PIX_FMT_JPEG:
680                 path->out_fmt = 0; // 0 - word, 1 - half word
681                 path->end_sel.y_endian = DCAM_ENDIAN_LITTLE;
682                 break;
683
684         case IMG_PIX_FMT_YUYV:
685                 path->out_fmt = DCAM_OUTPUT_YVYU_1FRAME;
686                 path->end_sel.y_endian = DCAM_ENDIAN_LITTLE;
687                 break;
688
689         case IMG_PIX_FMT_NV21:
690         case IMG_PIX_FMT_NV12:
691                 path->out_fmt = DCAM_OUTPUT_YUV420;
692                 path->end_sel.y_endian = DCAM_ENDIAN_LITTLE;
693                 if (IMG_PIX_FMT_NV12 == fourcc) {
694                         path->end_sel.uv_endian = DCAM_ENDIAN_LITTLE;
695                 } else {
696                         path->end_sel.uv_endian = DCAM_ENDIAN_HALFBIG;
697                 }
698                 DCAM_TRACE("SPRD_IMG: path->end_sel.uv_endian=%d \n", path->end_sel.uv_endian);
699                 break;
700
701         default:
702                 printk("SPRD_IMG: unsupported image format for path0 0x%x \n", fourcc);
703                 return -EINVAL;
704         }
705         path->fourcc = fourcc;
706
707         DCAM_TRACE("SPRD_IMG: check format for path0: out_fmt=%d, is_loose=%d \n", path->out_fmt, info->is_loose);
708         path->out_size.w = f->width;
709         path->out_size.h = f->height;
710
711         path->is_work = 1;
712
713         return 0;
714 }
715
716 LOCAL int sprd_img_check_path1_cap(uint32_t fourcc,
717                                         struct sprd_img_format *f,
718                                         struct dcam_info   *info)
719 {
720         uint32_t                 maxw, maxh, tempw,temph;
721         uint32_t                 depth_pixel = 0;
722         struct dcam_path_spec    *path = &info->dcam_path[DCAM_PATH1];
723         uint32_t                 need_recal = 0;
724
725         DCAM_TRACE("SPRD_IMG: check format for path1 \n");
726
727         path->frm_type = f->channel_id;
728         path->is_from_isp = f->need_isp;
729         path->rot_mode = f->reserved[0];
730         path->end_sel.y_endian = DCAM_ENDIAN_LITTLE;
731         path->end_sel.uv_endian = DCAM_ENDIAN_LITTLE;
732         path->is_work = 0;
733         path->pixel_depth = 0;
734         path->img_deci.x_factor = 0;
735         path->img_deci.y_factor = 0;
736         tempw = path->in_rect.w;
737         temph = path->in_rect.h;
738         info->img_deci.x_factor = 0;
739         f->need_binning = 0;
740         DCAM_TRACE("zcf sprd_img_check_path1_cap  rot_mode:%d\n",path->rot_mode);
741         /*app should fill in this field(fmt.pix.priv) to set the base index of frame buffer,
742         and lately this field will return the flag whether ISP is needed for this work path*/
743
744         switch (fourcc) {
745         case IMG_PIX_FMT_GREY:
746         case IMG_PIX_FMT_JPEG:
747         case IMG_PIX_FMT_YUYV:
748         case IMG_PIX_FMT_YVYU:
749         case IMG_PIX_FMT_UYVY:
750         case IMG_PIX_FMT_VYUY:
751                 if (unlikely(f->width != tempw ||
752                         f->height != temph)) {
753                         /*need need scaling or triming*/
754                         printk("SPRD_IMG: Can not scaling for this image fmt src %d %d, dst %d %d \n",
755                                         tempw,
756                                         temph,
757                                         f->width,
758                                         f->height);
759                         return -EINVAL;
760                 }
761
762                 if (unlikely(DCAM_CAP_MODE_JPEG != info->sn_mode &&
763                         IMG_PIX_FMT_JPEG == fourcc)) {
764                         /* the output of sensor is not JPEG which is needed by app*/
765                         printk("SPRD_IMG: It's not JPEG sensor \n");
766                         return -EINVAL;
767                 }
768
769                 if (unlikely(DCAM_CAP_MODE_RAWRGB != info->sn_mode &&
770                         IMG_PIX_FMT_GREY == fourcc)) {
771                         /* the output of sensor is not RawRGB which is needed by app*/
772                         printk("SPRD_IMG: It's not RawRGB sensor \n");
773                         return -EINVAL;
774                 }
775
776                 if (IMG_PIX_FMT_GREY == fourcc) {
777                         if (DCAM_CAP_IF_CSI2 == info->if_mode && 0 == info->is_loose) {
778                                 depth_pixel = 10;
779                         } else {
780                                 depth_pixel = 16;
781                         }
782                         DCAM_TRACE("SPRD_IMG: RawRGB sensor, %d %d \n", info->is_loose, depth_pixel);
783                 } else if (IMG_PIX_FMT_JPEG == fourcc) {
784                         depth_pixel = 8;
785                 } else {
786                         depth_pixel = 16;
787                 }
788
789                 if (IMG_PIX_FMT_GREY == fourcc) {
790                         path->out_fmt = DCAM_RAWRGB;
791                         path->end_sel.y_endian = DCAM_ENDIAN_BIG;
792                 } else {
793                         path->out_fmt = DCAM_JPEG;
794                 }
795                 break;
796         case IMG_PIX_FMT_YUV422P:
797         case IMG_PIX_FMT_YUV420:
798         case IMG_PIX_FMT_YVU420:
799         case IMG_PIX_FMT_NV12:
800         case IMG_PIX_FMT_NV21:
801         case IMG_PIX_FMT_RGB565:
802         case IMG_PIX_FMT_RGB565X:
803                 if (DCAM_CAP_MODE_RAWRGB == info->sn_mode &&
804                         path->is_from_isp) {
805                         if (unlikely(info->cap_out_size.w > DCAM_ISP_LINE_BUF_LENGTH)) {
806                                 if (0 == info->if_mode) {
807                                         /*CCIR CAP, no bining*/
808                                         printk("SPRD_IMG: CCIR CAP, no bining for this path, %d %d \n",
809                                                 f->width,
810                                                 f->height);
811                                         return -EINVAL;
812                                 } else {
813                                         /*MIPI CAP, support 1/2 bining*/
814                                         DCAM_TRACE("Need Binning \n");
815                                         tempw = tempw >> 1;
816                                         if (unlikely(tempw > DCAM_ISP_LINE_BUF_LENGTH)) {
817                                                 printk("SPRD_IMG: the width is out of ISP line buffer, %d %d \n",
818                                                         tempw,
819                                                         DCAM_ISP_LINE_BUF_LENGTH);
820                                                 return -EINVAL;
821                                         }
822                                         info->img_deci.x_factor = 1;
823                                         f->need_binning = 1;
824                                         DCAM_TRACE("x_factor, %d \n", info->img_deci.x_factor);
825                                         path->in_size.w = path->in_size.w >> 1;
826                                         path->in_rect.x = path->in_rect.x >> 1;
827                                         path->in_rect.w = path->in_rect.w >> 1;
828                                         path->in_rect.w = path->in_rect.w & (~3);
829                                 }
830                         }
831                 }
832                 if (DCAM_CAP_MODE_YUV == info->sn_mode ||
833                         DCAM_CAP_MODE_SPI == info->sn_mode) {
834                         if (tempw != f->width || temph != f->height) {
835                                 /*scaling needed*/
836                                 if (unlikely(f->width > DCAM_PATH1_LINE_BUF_LENGTH)) {
837                                         /*out of scaling capbility*/
838                                         printk("SPRD_IMG: the output width %d can not be more than %d \n",
839                                                 f->width,
840                                                 DCAM_PATH1_LINE_BUF_LENGTH);
841                                         return -EINVAL;
842                                 }
843
844                                 /* To check whether the output size is too lager*/
845                                 maxw = tempw * DCAM_SC_COEFF_UP_MAX;
846                                 maxh = temph * DCAM_SC_COEFF_UP_MAX;
847                                 if (unlikely(f->width > maxw || f->height > maxh)) {
848                                         /*out of scaling capbility*/
849                                         printk("SPRD_IMG: the output size is too large, %d %d \n",
850                                                 f->width,
851                                                 f->height);
852                                         return -EINVAL;
853                                 }
854
855                                 /* To check whether the output size is too small*/
856                                 maxw = f->width * DCAM_SC_COEFF_DOWN_MAX;
857                                 if (unlikely( tempw > maxw)) {
858                                         path->img_deci.x_factor = sprd_img_get_deci_factor(tempw, maxw);
859                                         if (path->img_deci.x_factor > DCAM_PATH_DECI_FAC_MAX) {
860                                                 printk("SPRD_IMG: the output size is too small, %d %d \n",
861                                                         f->width,
862                                                         f->height);
863                                                 return -EINVAL;
864                                         }
865                                 }
866
867                                 maxh = f->height * DCAM_SC_COEFF_DOWN_MAX;
868                                 if (unlikely(temph > maxh)) {
869                                         path->img_deci.y_factor = sprd_img_get_deci_factor(temph, maxh);
870                                         if (path->img_deci.y_factor > DCAM_PATH_DECI_FAC_MAX) {
871                                                 printk("SPRD_IMG: the output size is too small, %d %d \n",
872                                                         f->width,
873                                                         f->height);
874                                                 return -EINVAL;
875                                         }
876                                 }
877
878                                 if (path->img_deci.x_factor) {
879                                         tempw           = path->in_rect.w >> 1;
880                                         need_recal      = 1;
881                                 }
882
883                                 if (path->img_deci.y_factor) {
884                                         temph           = path->in_rect.h >> 1;
885                                         need_recal      = 1;
886                                 }
887
888                                 if (need_recal && (tempw != f->width || temph != f->height)) {
889                                         /*scaling needed*/
890                                         if (unlikely(f->width > DCAM_PATH1_LINE_BUF_LENGTH)) {
891                                                 /*out of scaling capbility*/
892                                                 printk("SPRD_IMG: the output width %d can not be more than %d \n",
893                                                         f->width,
894                                                         DCAM_PATH1_LINE_BUF_LENGTH);
895                                                 return -EINVAL;
896                                         }
897                                 }
898                         }
899                 } else if (DCAM_CAP_MODE_RAWRGB == info->sn_mode) {
900                         if (path->is_from_isp) {
901
902                                 if (tempw != f->width ||
903                                         temph != f->height) {
904                                         /*scaling needed*/
905                                         maxw = f->width * DCAM_SC_COEFF_DOWN_MAX;
906                                         maxw = maxw * (1 << DCAM_PATH_DECI_FAC_MAX);
907                                         maxh = f->height * DCAM_SC_COEFF_DOWN_MAX;
908                                         maxh = maxh * (1 << DCAM_PATH_DECI_FAC_MAX);
909                                         if (unlikely(tempw > maxw || temph > maxh)) {
910                                                 /*out of scaling capbility*/
911                                                 printk("SPRD_IMG: the output size is too small, %d %d \n",
912                                                                 f->width,
913                                                                 f->height);
914                                                 return -EINVAL;
915                                         }
916
917                                         if (unlikely(f->width > DCAM_PATH1_LINE_BUF_LENGTH)) {
918                                                 /*out of scaling capbility*/
919                                                 printk("SPRD_IMG: the output width %d can not be more than %d \n",
920                                                         f->width,
921                                                         DCAM_PATH1_LINE_BUF_LENGTH);
922                                                 return -EINVAL;
923                                         }
924
925                                         maxw = tempw * DCAM_SC_COEFF_UP_MAX;
926                                         maxh = temph * DCAM_SC_COEFF_UP_MAX;
927                                         if (unlikely(f->width > maxw || f->height > maxh)) {
928                                                 /*out of scaling capbility*/
929                                                 printk("SPRD_IMG: the output size is too large, %d %d \n",
930                                                         f->width,
931                                                         f->height);
932                                                 return -EINVAL;
933                                         }
934                                 }
935                         } else {
936                                 /*no ISP ,only RawRGB data can be sampled*/
937                                 printk("SPRD_IMG: RawRGB sensor, no ISP, format 0x%x can't be supported \n",
938                                                 fourcc);
939                                 return -EINVAL;
940                         }
941                 }
942
943                 depth_pixel = sprd_img_endian_sel(fourcc, path);
944                 break;
945         default:
946                 printk("SPRD_IMG: unsupported image format for path2 0x%x \n", fourcc);
947                 return -EINVAL;
948         }
949
950         path->fourcc = fourcc;
951         path->pixel_depth = depth_pixel;
952         f->bytesperline = (f->width * depth_pixel) >> 3;
953         path->out_size.w = f->width;
954         path->out_size.h = f->height;
955         path->is_work = 1;
956         return 0;
957 }
958
959 LOCAL int sprd_img_check_path2_cap(uint32_t fourcc,
960                                         struct sprd_img_format *f,
961                                         struct dcam_info   *info)
962 {
963         uint32_t                 maxw, maxh, tempw,temph;
964         uint32_t                 depth_pixel = 0;
965         struct dcam_path_spec    *path = &info->dcam_path[DCAM_PATH2];
966         uint32_t                 need_recal = 0;
967
968         //return -EINVAL;
969
970         DCAM_TRACE("SPRD_IMG: check format for path2 \n");
971
972         path->frm_type = f->channel_id;
973         path->is_from_isp = f->need_isp;
974         path->rot_mode= f->reserved[0];
975         path->end_sel.y_endian = DCAM_ENDIAN_LITTLE;
976         path->end_sel.uv_endian = DCAM_ENDIAN_LITTLE;
977         path->is_work = 0;
978         path->pixel_depth = 0;
979         DCAM_TRACE("zcf sprd_img_check_path2_cap rot:%d\n",path->rot_mode);
980         if (info->img_deci.x_factor) {
981                 tempw = path->in_rect.w >> 1;
982                 path->in_size.w = path->in_size.w >> 1;
983                 path->in_rect.w = path->in_rect.w >> 1;
984                 path->in_rect.x = path->in_rect.x >> 1;
985         } else {
986                 tempw = path->in_rect.w;
987         }
988         temph = path->in_rect.h;
989         switch (fourcc) {
990         case IMG_PIX_FMT_YUV422P:
991         case IMG_PIX_FMT_YUV420:
992         case IMG_PIX_FMT_YVU420:
993         case IMG_PIX_FMT_NV12:
994         case IMG_PIX_FMT_NV21:
995
996                 if (DCAM_CAP_MODE_JPEG == info->sn_mode ||
997                         info->sn_mode >= DCAM_CAP_MODE_MAX) {
998                         return -EINVAL;
999                 }
1000
1001                 if (DCAM_CAP_MODE_RAWRGB == info->sn_mode) {
1002                         path->is_from_isp = 1;
1003                 }
1004
1005                 if (DCAM_CAP_MODE_YUV == info->sn_mode ||
1006                         DCAM_CAP_MODE_SPI == info->sn_mode) {
1007                         if (tempw != f->width || temph != f->height) {
1008                                 /*scaling needed*/
1009                                 if (unlikely(f->width > DCAM_PATH2_LINE_BUF_LENGTH)) {
1010                                         /*out of scaling capbility*/
1011                                         printk("SPRD_IMG: the output width %d can not be more than %d \n",
1012                                                 f->width,
1013                                                 DCAM_PATH2_LINE_BUF_LENGTH);
1014                                         return -EINVAL;
1015                                 }
1016
1017                                 /* To check whether the output size is too lager*/
1018                                 maxw = tempw * DCAM_SC_COEFF_UP_MAX;
1019                                 maxh = temph * DCAM_SC_COEFF_UP_MAX;
1020                                 if (unlikely(f->width > maxw || f->height > maxh)) {
1021                                         /*out of scaling capbility*/
1022                                         printk("SPRD_IMG: the output size is too large, %d %d \n",
1023                                                 f->width,
1024                                                 f->height);
1025                                         return -EINVAL;
1026                                 }
1027
1028                                 /* To check whether the output size is too small*/
1029                                 maxw = f->width * DCAM_SC_COEFF_DOWN_MAX;
1030                                 if (unlikely( tempw > maxw)) {
1031                                         path->img_deci.x_factor = sprd_img_get_deci_factor(tempw, maxw);
1032                                         if (path->img_deci.x_factor > DCAM_PATH_DECI_FAC_MAX) {
1033                                                 printk("SPRD_IMG: the output size is too small, %d %d \n",
1034                                                         f->width,
1035                                                         f->height);
1036                                                 return -EINVAL;
1037                                         }
1038                                 }
1039
1040                                 maxh = f->height * DCAM_SC_COEFF_DOWN_MAX;
1041                                 if (unlikely(temph > maxh)) {
1042                                         path->img_deci.y_factor = sprd_img_get_deci_factor(temph, maxh);
1043                                         if (path->img_deci.y_factor > DCAM_PATH_DECI_FAC_MAX) {
1044                                                 printk("SPRD_IMG: the output size is too small, %d %d \n",
1045                                                         f->width,
1046                                                         f->height);
1047                                                 return -EINVAL;
1048                                         }
1049                                 }
1050
1051                                 if (path->img_deci.x_factor) {
1052                                         tempw           = path->in_rect.w >> 1;
1053                                         need_recal      = 1;
1054                                 }
1055
1056                                 if (path->img_deci.y_factor) {
1057                                         temph           = path->in_rect.h >> 1;
1058                                         need_recal      = 1;
1059                                 }
1060
1061                                 if (need_recal && (tempw != f->width || temph != f->height)) {
1062                                         /*scaling needed*/
1063                                         if (unlikely(f->width > DCAM_PATH2_LINE_BUF_LENGTH)) {
1064                                                 /*out of scaling capbility*/
1065                                                 printk("SPRD_IMG: the output width %d can not be more than %d \n",
1066                                                         f->width,
1067                                                         DCAM_PATH2_LINE_BUF_LENGTH);
1068                                                 return -EINVAL;
1069                                         }
1070                                 }
1071                         }
1072                 } else if (DCAM_CAP_MODE_RAWRGB == info->sn_mode) {
1073                         if (path->is_from_isp) {
1074
1075                                 if (tempw != f->width ||
1076                                         temph != f->height) {
1077                                         /*scaling needed*/
1078                                         maxw = f->width * DCAM_SC_COEFF_DOWN_MAX;
1079                                         maxw = maxw * (1 << DCAM_PATH_DECI_FAC_MAX);
1080                                         maxh = f->height * DCAM_SC_COEFF_DOWN_MAX;
1081                                         maxh = maxh * (1 << DCAM_PATH_DECI_FAC_MAX);
1082                                         if (unlikely(tempw > maxw || temph > maxh)) {
1083                                                 /*out of scaling capbility*/
1084                                                 printk("SPRD_IMG: the output size is too small, %d %d \n",
1085                                                                 f->width,
1086                                                                 f->height);
1087                                                 return -EINVAL;
1088                                         }
1089
1090                                         if (unlikely(f->width > DCAM_PATH2_LINE_BUF_LENGTH)) {
1091                                                 /*out of scaling capbility*/
1092                                                 printk("SPRD_IMG: the output width %d can not be more than %d \n",
1093                                                         f->width,
1094                                                         DCAM_PATH2_LINE_BUF_LENGTH);
1095                                                 return -EINVAL;
1096                                         }
1097
1098                                         maxw = tempw * DCAM_SC_COEFF_UP_MAX;
1099                                         maxh = temph * DCAM_SC_COEFF_UP_MAX;
1100                                         if (unlikely(f->width > maxw || f->height > maxh)) {
1101                                                 /*out of scaling capbility*/
1102                                                 printk("SPRD_IMG: the output size is too large, %d %d \n",
1103                                                         f->width,
1104                                                         f->height);
1105                                                 return -EINVAL;
1106                                         }
1107                                 }
1108                         } else {
1109                                 /*no ISP ,only RawRGB data can be sampled*/
1110                                 printk("SPRD_IMG: RawRGB sensor, no ISP, format 0x%x can't be supported \n",
1111                                                 fourcc);
1112                                 return -EINVAL;
1113                         }
1114                 }
1115
1116
1117                 depth_pixel = sprd_img_endian_sel(fourcc, path);
1118                 //path->end_sel.uv_endian = DCAM_ENDIAN_LITTLE; // tmp fix: output is vu, jpeg only support vu
1119                 break;
1120         default:
1121                 printk("SPRD_IMG: unsupported image format for path2 0x%x \n", fourcc);
1122                 return -EINVAL;
1123         }
1124
1125         path->fourcc = fourcc;
1126         f->need_isp = path->is_from_isp;
1127         path->pixel_depth = depth_pixel;
1128         f->bytesperline = (f->width * depth_pixel) >> 3;
1129         path->out_size.w = f->width;
1130         path->out_size.h = f->height;
1131         path->is_work = 1;
1132
1133         return 0;
1134 }
1135
1136 LOCAL int sprd_img_cap_cfg(struct dcam_info* info)
1137 {
1138         int                      ret = DCAM_RTN_SUCCESS;
1139         uint32_t                 param = 0;
1140
1141         if (NULL == info)
1142                 return -EINVAL;
1143
1144         ret = dcam_cap_cfg(DCAM_CAP_SYNC_POL, &info->sync_pol);
1145         IMG_RTN_IF_ERR(ret);
1146
1147         if ((info->dcam_path[DCAM_PATH0].is_work && info->dcam_path[DCAM_PATH0].is_from_isp) ||
1148                 (info->dcam_path[DCAM_PATH1].is_work && info->dcam_path[DCAM_PATH1].is_from_isp) ||
1149                 (info->dcam_path[DCAM_PATH2].is_work && info->dcam_path[DCAM_PATH2].is_from_isp)) {
1150                 param = 1;
1151         } else {
1152                 param = 0;
1153         }
1154         ret = dcam_cap_cfg(DCAM_CAP_TO_ISP, &param);
1155         IMG_RTN_IF_ERR(ret);
1156
1157         ret = dcam_cap_cfg(DCAM_CAP_YUV_TYPE, &info->yuv_ptn);
1158         IMG_RTN_IF_ERR(ret);
1159
1160         ret = dcam_cap_cfg(DCAM_CAP_DATA_BITS, &info->data_bits);
1161         IMG_RTN_IF_ERR(ret);
1162
1163         if (DCAM_CAP_MODE_RAWRGB == info->sn_mode &&
1164                 DCAM_CAP_IF_CSI2 == info->if_mode)
1165         {
1166                 ret = dcam_cap_cfg(DCAM_CAP_DATA_PACKET, &info->is_loose);
1167                 IMG_RTN_IF_ERR(ret);
1168         }
1169
1170         ret = dcam_cap_cfg(DCAM_CAP_FRM_DECI, &info->frm_deci);
1171         IMG_RTN_IF_ERR(ret);
1172
1173         ret = dcam_cap_cfg(DCAM_CAP_INPUT_RECT, &info->cap_in_rect);
1174         IMG_RTN_IF_ERR(ret);
1175
1176         ret = dcam_cap_cfg(DCAM_CAP_FRM_COUNT_CLR, NULL);
1177         IMG_RTN_IF_ERR(ret);
1178
1179         ret = dcam_cap_cfg(DCAM_CAP_PRE_SKIP_CNT, &info->skip_number);
1180         IMG_RTN_IF_ERR(ret);
1181
1182         ret = dcam_cap_cfg(DCAM_CAP_SAMPLE_MODE, &info->capture_mode);
1183         IMG_RTN_IF_ERR(ret);
1184
1185         ret = dcam_cap_cfg(DCAM_CAP_ZOOM_MODE, &info->is_smooth_zoom);
1186
1187         ret = dcam_cap_cfg(DCAM_CAP_IMAGE_XY_DECI, &info->img_deci);
1188
1189 exit:
1190         return ret;
1191 }
1192
1193 LOCAL void sprd_img_frm_pop(struct dcam_frame *frame, void* param)
1194 {
1195 #if 0
1196         uint32_t                 i = 0;
1197         uint32_t                 frame_count = 0;
1198         struct dcam_path_spec    *path = NULL;
1199         struct dcam_dev          *dev = (struct dcam_dev*)param;
1200         struct dcam_info         *info = NULL;
1201
1202         info = &dev->dcam_cxt;
1203
1204         switch (frame->type) {
1205         case DCAM_PATH0:
1206                 path = &info->dcam_path[DCAM_PATH0];
1207                 break;
1208         case DCAM_PATH1:
1209                 path = &info->dcam_path[DCAM_PATH1];
1210                 break;
1211         case DCAM_PATH2:
1212                 path = &info->dcam_path[DCAM_PATH2];
1213                 break;
1214         default:
1215                 printk("SPRD_IMG error: sprd_img_frm_pop, path 0x%x \n", frame->type);
1216                 return -EINVAL;
1217         }
1218         DCAM_TRACE("SPRD_IMG: sprd_img_frm_pop start, path 0x%x \n", frame->type);
1219         DCAM_TRACE("SPRD_IMG: sprd_img_frm_pop, yaddr 0x%x 0x%x \n", frame->yaddr, path->frm_addr[0].yaddr);
1220         if (frame->yaddr == path->frm_addr[0].yaddr) {
1221                 for (i = 0; i < path->frm_cnt_act - 1; i++) {
1222                         path->frm_addr[i]     = path->frm_addr[i+1];
1223                         path->frm_addr_vir[i] = path->frm_addr_vir[i+1];
1224                 }
1225                 path->frm_cnt_act--;
1226                 memset(&path->frm_addr[path->frm_cnt_act], 0, sizeof(struct dcam_addr));
1227                 memset(&path->frm_addr_vir[path->frm_cnt_act], 0, sizeof(struct dcam_addr));
1228         } else {
1229                 printk("SPRD_IMG error: sprd_img_frm_pop, yaddr 0x%x 0x%x \n", frame->yaddr, path->frm_addr[0].yaddr);
1230         }
1231         DCAM_TRACE("SPRD_IMG: sprd_img_frm_pop end, path 0x%x yaddr 0x%x \n", frame->type, frame->yaddr);
1232 #endif
1233         return;
1234 }
1235
1236 LOCAL int sprd_img_tx_done(struct dcam_frame *frame, void* param)
1237 {
1238         int                      ret = DCAM_RTN_SUCCESS;
1239         struct dcam_dev          *dev = (struct dcam_dev*)param;
1240         struct dcam_path_spec    *path;
1241         struct dcam_node         node;
1242         uint32_t                 fmr_index;
1243         struct dcam_img_buf_addr buf_addr;
1244
1245         if (NULL == frame || NULL == param || 0 == atomic_read(&dev->stream_on))
1246                 return -EINVAL;
1247         path = &dev->dcam_cxt.dcam_path[frame->type];
1248         if (PATH_IDLE == path->status) {
1249                 return ret;
1250         }
1251
1252         atomic_set(&dev->run_flag, 1);
1253
1254         memset((void*)&node, 0, sizeof(struct dcam_node));
1255         node.irq_flag = IMG_TX_DONE;
1256         node.f_type   = frame->type;
1257         node.index    = frame->fid;
1258         node.height   = frame->height;
1259         node.yaddr    = frame->yaddr;
1260         node.uaddr    = frame->uaddr;
1261         node.vaddr    = frame->vaddr;
1262         node.yaddr_vir = frame->yaddr_vir;
1263         node.uaddr_vir = frame->uaddr_vir;
1264         node.vaddr_vir = frame->vaddr_vir;
1265
1266         DCAM_TRACE("SPRD_IMG: flag 0x%x type 0x%x index 0x%x \n",
1267                 node.irq_flag, node.f_type, node.index);
1268
1269 /*      path = &dev->dcam_cxt.dcam_path[frame->type];
1270         ret = sprd_img_buf_queue_read(&path->buf_queue, &buf_addr);
1271         if (ret)
1272                 return ret;
1273
1274         node.yaddr_vir = buf_addr.frm_addr_vir.yaddr;
1275         node.uaddr_vir = buf_addr.frm_addr_vir.uaddr;
1276         node.vaddr_vir = buf_addr.frm_addr_vir.vaddr;
1277 */
1278
1279         //printk("SPRD_IMG: DCAM_PATH = %d\n", frame->type);
1280         
1281         if (DCAM_PATH0 == frame->type && DCAM_CAP_MODE_JPEG == dev->dcam_cxt.sn_mode) {
1282                 dcam_cap_get_info(DCAM_CAP_JPEG_GET_LENGTH, &node.reserved);
1283                 printk("SPRD_IMG: JPEG length 0x%x \n", node.reserved);
1284                 if (node.reserved < DCAM_JPEG_LENGTH_MIN) {
1285                         return sprd_img_tx_error(frame, param);
1286                 }
1287         }
1288
1289 #if defined(CONFIG_MACH_GRANDPRIME3G_VE) || defined(CONFIG_MACH_Z3)
1290         if (dev->dcam_cxt.after_af && DCAM_PATH1 == frame->type) {
1291                 ret = sprd_img_discard_frame(frame, param);
1292                 if (DCAM_RTN_SUCCESS == ret) {
1293                         dev->dcam_cxt.after_af = 0;
1294                         node.irq_flag = IMG_CANCELED_BUF;
1295                 }
1296         }
1297 #else
1298         if (DCAM_PATH1 == frame->type) {
1299                 ret = sprd_img_discard_frame(frame, param);
1300                 if (DCAM_RTN_PARA_ERR == ret) {
1301                         dev->dcam_cxt.after_af = 0;
1302                         node.irq_flag = IMG_CANCELED_BUF;
1303                 }
1304         }
1305 #endif
1306
1307         ret = sprd_img_queue_write(&dev->queue, &node);
1308         if (ret)
1309                 return ret;
1310
1311         up(&dev->irq_sem);
1312         return ret;
1313 }
1314
1315 LOCAL int sprd_img_tx_error(struct dcam_frame *frame, void* param)
1316 {
1317         int                      ret = DCAM_RTN_SUCCESS;
1318         struct dcam_dev          *dev = (struct dcam_dev*)param;
1319         struct dcam_path_spec    *path;
1320         struct dcam_node         node;
1321         struct dcam_img_buf_addr buf_addr;
1322
1323         if (NULL == param || 0 == atomic_read(&dev->stream_on))
1324                 return -EINVAL;
1325
1326         memset((void*)&node, 0, sizeof(struct dcam_node));
1327         atomic_set(&dev->run_flag, 1);//to avoid time out processing
1328         node.irq_flag = IMG_TX_ERR;
1329         if (NULL != frame) {
1330                 node.f_type   = frame->type;
1331                 node.index    = frame->fid;
1332                 node.height   = frame->height;
1333                 node.yaddr    = frame->yaddr;
1334                 node.uaddr    = frame->uaddr;
1335                 node.vaddr    = frame->vaddr;
1336                 node.yaddr_vir = frame->yaddr_vir;
1337                 node.uaddr_vir = frame->uaddr_vir;
1338                 node.vaddr_vir = frame->vaddr_vir;
1339
1340 /*              path = &dev->dcam_cxt.dcam_path[frame->type];
1341                 ret = sprd_img_buf_queue_read(&path->buf_queue, &buf_addr);
1342                 if (ret)
1343                         return ret;
1344
1345                 node.yaddr_vir = buf_addr.frm_addr_vir.yaddr;
1346                 node.uaddr_vir = buf_addr.frm_addr_vir.uaddr;
1347                 node.vaddr_vir = buf_addr.frm_addr_vir.vaddr;*/
1348         }
1349         ret = sprd_img_queue_write(&dev->queue, &node);
1350         if (ret)
1351                 return ret;
1352
1353         up(&dev->irq_sem);
1354
1355         printk("SPRD_IMG: tx_error \n");
1356         //mm_clk_register_trace();
1357         return ret;
1358 }
1359
1360 LOCAL int sprd_img_no_mem(struct dcam_frame *frame, void* param)
1361 {
1362         int                      ret = DCAM_RTN_SUCCESS;
1363         struct dcam_dev          *dev = (struct dcam_dev*)param;
1364         struct dcam_path_spec    *path;
1365         struct dcam_node         node;
1366         struct dcam_img_buf_addr buf_addr;
1367
1368         if (NULL == param || 0 == atomic_read(&dev->stream_on))
1369                 return -EINVAL;
1370         atomic_set(&dev->run_flag, 1);//to avoid time out processing
1371
1372         memset((void*)&node, 0, sizeof(struct dcam_node));
1373         node.irq_flag = IMG_NO_MEM;
1374         node.f_type   = frame->type;
1375         node.index    = frame->fid;
1376         node.height   = frame->height;
1377         node.yaddr    = frame->yaddr;
1378         node.uaddr    = frame->uaddr;
1379         node.vaddr    = frame->vaddr;
1380         node.yaddr_vir = frame->yaddr_vir;
1381         node.uaddr_vir = frame->uaddr_vir;
1382         node.vaddr_vir = frame->vaddr_vir;
1383
1384
1385 /*      path = &dev->dcam_cxt.dcam_path[frame->type];
1386         ret = sprd_img_buf_queue_read(&path->buf_queue, &buf_addr);
1387         if (ret)
1388                 return ret;
1389
1390         node.yaddr_vir = buf_addr.frm_addr_vir.yaddr;
1391         node.uaddr_vir = buf_addr.frm_addr_vir.uaddr;
1392         node.vaddr_vir = buf_addr.frm_addr_vir.vaddr;*/
1393         ret = sprd_img_queue_write(&dev->queue, &node);
1394         if (ret)
1395                 return ret;
1396
1397         up(&dev->irq_sem);
1398         printk("SPRD_IMG: no mem \n");
1399         return ret;
1400 }
1401
1402 LOCAL int sprd_img_tx_stop(void* param)
1403 {
1404         int                      ret = DCAM_RTN_SUCCESS;
1405         struct dcam_dev          *dev = (struct dcam_dev*)param;
1406         struct dcam_node         node;
1407
1408         memset((void*)&node, 0, sizeof(struct dcam_node));
1409         node.irq_flag = IMG_TX_STOP;
1410         ret = sprd_img_queue_write(&dev->queue, &node);
1411         if (ret)
1412                 return ret;
1413
1414         up(&dev->irq_sem);
1415
1416         return ret;
1417 }
1418
1419 LOCAL int sprd_img_reg_isr(struct dcam_dev* param)
1420 {
1421         dcam_reg_isr(DCAM_PATH0_DONE,   sprd_img_tx_done,       param);
1422         dcam_reg_isr(DCAM_PATH1_DONE,   sprd_img_tx_done,       param);
1423         dcam_reg_isr(DCAM_PATH0_OV,     sprd_img_tx_error,      param);
1424         dcam_reg_isr(DCAM_PATH1_OV,     sprd_img_tx_error,      param);
1425         dcam_reg_isr(DCAM_ISP_OV,       sprd_img_tx_error,      param);
1426         dcam_reg_isr(DCAM_MIPI_OV,      sprd_img_tx_error,      param);
1427         dcam_reg_isr(DCAM_SN_LINE_ERR,  sprd_img_tx_error,      param);
1428         dcam_reg_isr(DCAM_SN_FRAME_ERR, sprd_img_tx_error,      param);
1429         dcam_reg_isr(DCAM_JPEG_BUF_OV,  sprd_img_no_mem,        param);
1430         dcam_reg_isr(DCAM_SN_EOF,       sprd_img_start_flash,   param);
1431         dcam_reg_isr(DCAM_PATH1_SOF,    sprd_img_start_zoom,    param);
1432
1433         return 0;
1434 }
1435
1436 LOCAL int sprd_img_reg_path2_isr(struct dcam_dev* param)
1437 {
1438         dcam_reg_isr(DCAM_PATH2_DONE,   sprd_img_tx_done,  param);
1439         dcam_reg_isr(DCAM_PATH2_OV,     sprd_img_tx_error, param);
1440
1441         return 0;
1442 }
1443
1444 LOCAL int sprd_img_unreg_isr(struct dcam_dev* param)
1445 {
1446         dcam_reg_isr(DCAM_PATH0_DONE,   NULL, param);
1447         dcam_reg_isr(DCAM_PATH1_DONE,   NULL, param);
1448         dcam_reg_isr(DCAM_PATH0_OV,     NULL, param);
1449         dcam_reg_isr(DCAM_PATH1_OV,     NULL, param);
1450         dcam_reg_isr(DCAM_ISP_OV,       NULL, param);
1451         dcam_reg_isr(DCAM_MIPI_OV,      NULL, param);
1452         dcam_reg_isr(DCAM_SN_LINE_ERR,  NULL, param);
1453         dcam_reg_isr(DCAM_SN_FRAME_ERR, NULL, param);
1454         dcam_reg_isr(DCAM_JPEG_BUF_OV,  NULL, param);
1455         dcam_reg_isr(DCAM_SN_EOF,       NULL,   param);
1456         dcam_reg_isr(DCAM_PATH1_SOF,    NULL,    param);
1457
1458         return 0;
1459 }
1460
1461 LOCAL int sprd_img_unreg_path2_isr(struct dcam_dev* param)
1462 {
1463         dcam_reg_isr(DCAM_PATH2_DONE,   NULL,  NULL);
1464         dcam_reg_isr(DCAM_PATH2_OV,     NULL,  NULL);
1465
1466         return 0;
1467 }
1468
1469 LOCAL int sprd_img_path0_cfg(path_cfg_func path_cfg,
1470                                 struct dcam_path_spec* path_spec)
1471 {
1472         int                      ret = DCAM_RTN_SUCCESS;
1473         uint32_t                 param, i;
1474
1475         if (NULL == path_cfg || NULL == path_spec)
1476                 return -EINVAL;
1477
1478         if (path_spec->is_from_isp) {
1479                 param = 1;
1480         } else {
1481                 param = 0;
1482         }
1483         ret = path_cfg(DCAM_PATH_SRC_SEL, &param);
1484         /*IMG_RTN_IF_ERR(ret);*/
1485
1486         ret = path_cfg(DCAM_PATH_ROT_MODE, &path_spec->rot_mode);
1487         IMG_RTN_IF_ERR(ret);
1488
1489         ret = path_cfg(DCAM_PATH_INPUT_SIZE, &path_spec->in_size);
1490         IMG_RTN_IF_ERR(ret);
1491
1492         ret = path_cfg(DCAM_PATH_INPUT_RECT, &path_spec->in_rect);
1493         /*IMG_RTN_IF_ERR(ret);*/
1494
1495         ret = path_cfg(DCAM_PATH_OUTPUT_FORMAT, &path_spec->out_fmt);
1496         IMG_RTN_IF_ERR(ret);
1497
1498         ret = path_cfg(DCAM_PATH_FRAME_BASE_ID, &path_spec->frm_id_base);
1499         IMG_RTN_IF_ERR(ret);
1500
1501         ret = path_cfg(DCAM_PATH_FRAME_TYPE, &path_spec->frm_type);
1502         IMG_RTN_IF_ERR(ret);
1503
1504         ret = path_cfg(DCAM_PATH_DATA_ENDIAN, &path_spec->end_sel);
1505         IMG_RTN_IF_ERR(ret);
1506
1507         ret = path_cfg(DCAM_PATH_FRM_DECI, &path_spec->path_frm_deci);
1508         IMG_RTN_IF_ERR(ret);
1509
1510         ret = sprd_img_path_cfg_output_addr(path_cfg, path_spec);
1511         IMG_RTN_IF_ERR(ret);
1512
1513         ret = path_cfg(DCAM_PATH_OUTPUT_RESERVED_ADDR, &path_spec->frm_reserved_addr);
1514
1515         param = 1;
1516         ret = path_cfg(DCAM_PATH_ENABLE, &param);
1517
1518 exit:
1519         return ret;
1520 }
1521
1522 LOCAL int sprd_img_path_cfg(path_cfg_func path_cfg,
1523                                 struct dcam_path_spec* path_spec)
1524 {
1525         int                      ret = DCAM_RTN_SUCCESS;
1526         uint32_t                 param, i;
1527
1528         if (NULL == path_cfg || NULL == path_spec)
1529                 return -EINVAL;
1530
1531         if (path_spec->is_from_isp) {
1532                 param = 1;
1533         } else {
1534                 param = 0;
1535         }
1536         ret = path_cfg(DCAM_PATH_SRC_SEL, &param);
1537         IMG_RTN_IF_ERR(ret);
1538
1539         ret = path_cfg(DCAM_PATH_ROT_MODE, &path_spec->rot_mode);
1540         IMG_RTN_IF_ERR(ret);
1541
1542         ret = path_cfg(DCAM_PATH_INPUT_SIZE, &path_spec->in_size);
1543         IMG_RTN_IF_ERR(ret);
1544
1545         ret = path_cfg(DCAM_PATH_INPUT_RECT, &path_spec->in_rect);
1546         IMG_RTN_IF_ERR(ret);
1547
1548         ret = path_cfg(DCAM_PATH_OUTPUT_SIZE, &path_spec->out_size);
1549         IMG_RTN_IF_ERR(ret);
1550
1551         ret = path_cfg(DCAM_PATH_OUTPUT_FORMAT, &path_spec->out_fmt);
1552         IMG_RTN_IF_ERR(ret);
1553
1554         ret = path_cfg(DCAM_PATH_FRAME_BASE_ID, &path_spec->frm_id_base);
1555         IMG_RTN_IF_ERR(ret);
1556
1557         ret = path_cfg(DCAM_PATH_FRAME_TYPE, &path_spec->frm_type);
1558         IMG_RTN_IF_ERR(ret);
1559
1560         ret = path_cfg(DCAM_PATH_DATA_ENDIAN, &path_spec->end_sel);
1561         IMG_RTN_IF_ERR(ret);
1562
1563         ret = path_cfg(DCAM_PATH_FRM_DECI, &path_spec->path_frm_deci);
1564         IMG_RTN_IF_ERR(ret);
1565
1566         ret = sprd_img_path_cfg_output_addr(path_cfg, path_spec);
1567         IMG_RTN_IF_ERR(ret);
1568
1569         ret = path_cfg(DCAM_PATH_OUTPUT_RESERVED_ADDR, &path_spec->frm_reserved_addr);
1570
1571         ret = path_cfg(DCAM_PATH_SHRINK, &path_spec->shrink);
1572
1573         param = 1;
1574         ret = path_cfg(DCAM_PATH_ENABLE, &param);
1575
1576 exit:
1577         return ret;
1578 }
1579
1580 LOCAL int sprd_img_path_lightly_cfg(path_cfg_func path_cfg,
1581                                 struct dcam_path_spec* path_spec)
1582 {
1583         int                      ret = DCAM_RTN_SUCCESS;
1584         uint32_t                 param;
1585
1586         if (NULL == path_cfg || NULL == path_spec)
1587                 return -EINVAL;
1588
1589         if (path_spec->is_from_isp) {
1590                 param = 1;
1591         } else {
1592                 param = 0;
1593         }
1594         ret = path_cfg(DCAM_PATH_SRC_SEL, &param);
1595         IMG_RTN_IF_ERR(ret);
1596
1597         ret = path_cfg(DCAM_PATH_INPUT_SIZE, &path_spec->in_size);
1598         IMG_RTN_IF_ERR(ret);
1599
1600         ret = path_cfg(DCAM_PATH_INPUT_RECT, &path_spec->in_rect);
1601         IMG_RTN_IF_ERR(ret);
1602
1603         ret = path_cfg(DCAM_PATH_OUTPUT_SIZE, &path_spec->out_size);
1604         IMG_RTN_IF_ERR(ret);
1605
1606         ret = path_cfg(DCAM_PATH_OUTPUT_FORMAT, &path_spec->out_fmt);
1607         IMG_RTN_IF_ERR(ret);
1608
1609         ret = path_cfg(DCAM_PATH_FRAME_BASE_ID, &path_spec->frm_id_base);
1610         IMG_RTN_IF_ERR(ret);
1611
1612         ret = path_cfg(DCAM_PATH_FRAME_TYPE, &path_spec->frm_type);
1613         IMG_RTN_IF_ERR(ret);
1614
1615         ret = path_cfg(DCAM_PATH_DATA_ENDIAN, &path_spec->end_sel);
1616         IMG_RTN_IF_ERR(ret);
1617
1618 exit:
1619         return ret;
1620 }
1621
1622 LOCAL int sprd_img_local_clear_path_buffer(struct dcam_dev *dev, int path_id)
1623 {
1624         int                                     ret = 0;
1625         struct dcam_path_spec    *path = NULL;
1626
1627         if (unlikely(NULL == dev)) {
1628                 return -EINVAL;
1629         }
1630
1631         if (DCAM_PATH1 == path_id) {
1632                 path = &dev->dcam_cxt.dcam_path[DCAM_PATH1];
1633         } else if (DCAM_PATH2 == path_id) {
1634                 path = &dev->dcam_cxt.dcam_path[DCAM_PATH2];
1635         } else if (DCAM_PATH0 == path_id) {
1636                 path = &dev->dcam_cxt.dcam_path[DCAM_PATH0];
1637         }
1638         if (unlikely(NULL == path))
1639                 return -EINVAL;
1640
1641         path->is_work = 0;
1642         path->frm_cnt_act = 0;
1643         sprd_img_buf_queue_init(&path->buf_queue);
1644
1645         DCAM_TRACE("SPRD_IMG: clear path buffer, frm_cnt_act %d \n", path->frm_cnt_act);
1646
1647         return 0;
1648 }
1649
1650 LOCAL int sprd_img_local_deinit(struct dcam_dev *dev)
1651 {
1652         int                                     ret = 0;
1653         struct dcam_path_spec    *path = &dev->dcam_cxt.dcam_path[DCAM_PATH1];
1654         DCAM_TRACE("SPRD_IMG: sprd_img_local_deinit, frm_cnt_act %d \n", path->frm_cnt_act);
1655         if (unlikely(NULL == dev || NULL == path)) {
1656                 return -EINVAL;
1657         }
1658         path->is_work = 0;
1659         path->frm_cnt_act = 0;
1660         sprd_img_buf_queue_init(&path->buf_queue);
1661
1662         path = &dev->dcam_cxt.dcam_path[DCAM_PATH2];
1663         if (unlikely(NULL == path))
1664                 return -EINVAL;
1665         path->is_work = 0;
1666         path->frm_cnt_act = 0;
1667         sprd_img_buf_queue_init(&path->buf_queue);
1668
1669         path = &dev->dcam_cxt.dcam_path[DCAM_PATH0];
1670         if (unlikely(NULL == path))
1671                 return -EINVAL;
1672         path->is_work = 0;
1673         path->frm_cnt_act = 0;
1674         sprd_img_buf_queue_init(&path->buf_queue);
1675
1676         ret = sprd_img_queue_init(&dev->queue);
1677         if (unlikely(ret != 0)) {
1678                 printk("SPRD_IMG: Failed to init queue \n");
1679                 return -EINVAL;
1680         }
1681
1682         printk("SPRD_IMG: sprd_img_local_deinit, frm_cnt_act %d \n", path->frm_cnt_act);
1683
1684         return 0;
1685 }
1686
1687 LOCAL int sprd_img_queue_init(struct dcam_queue *queue)
1688 {
1689         if (NULL == queue)
1690                 return -EINVAL;
1691
1692         memset(queue, 0, sizeof(*queue));
1693         queue->write = &queue->node[0];
1694         queue->read  = &queue->node[0];
1695
1696         return 0;
1697 }
1698
1699 LOCAL int sprd_img_queue_write(struct dcam_queue *queue, struct dcam_node *node)
1700 {
1701         struct dcam_node         *ori_node;
1702         unsigned long                 lock_flag;
1703
1704         if (NULL == queue || NULL == node)
1705                 return -EINVAL;
1706
1707         ori_node = queue->write;
1708         queue->wcnt++;
1709         DCAM_TRACE("SPRD_IMG: sprd_img_queue_write \n");
1710         *queue->write++ = *node;
1711         if (queue->write > &queue->node[DCAM_QUEUE_LENGTH-1]) {
1712                 queue->write = &queue->node[0];
1713         }
1714
1715         if (queue->write == queue->read) {
1716                 queue->write = ori_node;
1717                 printk("SPRD_IMG: warning, queue is full, cannot write, flag 0x%x type 0x%x index 0x%x wcht %d %d\n",
1718                         node->irq_flag, node->f_type, node->index, queue->wcnt, queue->rcnt);
1719         }
1720
1721         return 0;
1722 }
1723
1724 LOCAL int sprd_img_queue_read(struct dcam_queue *queue, struct dcam_node *node)
1725 {
1726         int                      ret = DCAM_RTN_SUCCESS;
1727         int                      flag = 0;
1728
1729         if (NULL == queue || NULL == node)
1730                 return -EINVAL;
1731
1732         DCAM_TRACE("SPRD_IMG: sprd_img_queue_read \n");
1733
1734         if  (queue->read != queue->write) {
1735                 flag = 1;
1736                 *node = *queue->read;
1737                 queue->read->yaddr = 0;
1738                 queue->read->yaddr_vir = 0;
1739                 queue->read++;
1740                 queue->rcnt++;
1741                 if (queue->read > &queue->node[DCAM_QUEUE_LENGTH-1]) {
1742                         queue->read = &queue->node[0];
1743                 }
1744         }
1745         if (!flag) {
1746                 ret = EAGAIN;
1747         }
1748         DCAM_TRACE("SPRD_IMG: sprd_img_queue_read type %d \n", node->f_type);
1749         return ret;
1750 }
1751
1752 LOCAL int sprd_img_queue_disable(struct dcam_queue *queue, uint32_t channel_id)
1753 {
1754         struct dcam_node            *cur_node;
1755
1756         if (NULL == queue)
1757                 return -EINVAL;
1758
1759         cur_node = queue->read;
1760          while (cur_node != queue->write) {
1761                 if (channel_id == cur_node->f_type) {
1762                         cur_node->invalid_flag = 1;
1763                 }
1764                 if (cur_node >= &queue->node[DCAM_QUEUE_LENGTH-1]) {
1765                         cur_node = &queue->node[0];
1766                 } else {
1767                         cur_node++;
1768                 }
1769         }
1770         
1771
1772         return 0;
1773 }
1774
1775 LOCAL int sprd_img_queue_enable(struct dcam_queue *queue, uint32_t channel_id)
1776 {
1777         struct dcam_node            *cur_node;
1778         unsigned int                    i = 0;
1779
1780         if (NULL == queue)
1781                 return -EINVAL;
1782
1783         for (i=0 ; i < DCAM_QUEUE_LENGTH ; i++) {
1784                         queue->node[i].invalid_flag = 0;
1785         }
1786
1787         return 0;
1788 }
1789
1790 LOCAL int sprd_img_buf_queue_init(struct dcam_img_buf_queue *queue)
1791 {
1792         if (NULL == queue)
1793                 return -EINVAL;
1794
1795         DCAM_TRACE("SPRD_IMG: sprd_img_buf_queue_init \n");
1796         memset(queue, 0, sizeof(*queue));
1797         queue->write = &queue->buf_addr[0];
1798         queue->read  = &queue->buf_addr[0];
1799
1800         return 0;
1801 }
1802
1803 LOCAL int sprd_img_buf_queue_write(struct dcam_img_buf_queue *queue, struct dcam_img_buf_addr *buf_addr)
1804 {
1805         struct dcam_img_buf_addr         *ori_node;
1806
1807         if (NULL == queue || NULL == buf_addr)
1808                 return -EINVAL;
1809
1810         ori_node = queue->write;
1811         DCAM_TRACE("SPRD_IMG: sprd_img_buf_queue_write \n");
1812         *queue->write++ = *buf_addr;
1813         queue->wcnt++;
1814         if (queue->write > &queue->buf_addr[DCAM_FRM_CNT_MAX-1]) {
1815                 queue->write = &queue->buf_addr[0];
1816         }
1817
1818         if (queue->write == queue->read) {
1819                 queue->write = ori_node;
1820                 printk("SPRD_IMG: warning, queue is full, cannot write %d %d", queue->wcnt, queue->rcnt);
1821                 return -EINVAL;
1822         }
1823
1824         return 0;
1825 }
1826
1827 LOCAL int sprd_img_buf_queue_read(struct dcam_img_buf_queue *queue, struct dcam_img_buf_addr *buf_addr)
1828 {
1829         int                      ret = DCAM_RTN_SUCCESS;
1830
1831         if (NULL == queue || NULL == buf_addr)
1832                 return -EINVAL;
1833
1834         DCAM_TRACE("SPRD_IMG: sprd_img_buf_queue_read \n");
1835         if (queue->read != queue->write) {
1836                 *buf_addr = *queue->read++;
1837                 queue->rcnt++;
1838                 if (queue->read > &queue->buf_addr[DCAM_FRM_CNT_MAX-1]) {
1839                         queue->read = &queue->buf_addr[0];
1840                 }
1841         } else {
1842                 printk("SPRD_IMG: buf_queue_read fail %d\n", queue->rcnt);
1843                 ret = EAGAIN;
1844         }
1845
1846         DCAM_TRACE("SPRD_IMG: sprd_img_buf_queue_read \n");
1847         return ret;
1848 }
1849
1850 LOCAL int sprd_img_path_cfg_output_addr(path_cfg_func path_cfg, struct dcam_path_spec* path_spec)
1851 {
1852         int                         ret = DCAM_RTN_SUCCESS;
1853         struct dcam_img_buf_addr    *cur_node;
1854         struct dcam_img_buf_queue   *queue;
1855         struct dcam_addr            frm_addr;
1856
1857         if (NULL == path_cfg || NULL == path_spec)
1858                 return -EINVAL;
1859
1860         queue = &path_spec->buf_queue;
1861
1862         for (cur_node = queue->read; cur_node != queue->write; cur_node++) {
1863                 if (cur_node > &queue->buf_addr[DCAM_FRM_CNT_MAX-1]) {
1864                         cur_node = &queue->buf_addr[0];
1865                 }
1866                 frm_addr.yaddr = cur_node->frm_addr.yaddr;
1867                 frm_addr.uaddr = cur_node->frm_addr.uaddr;
1868                 frm_addr.vaddr = cur_node->frm_addr.vaddr;
1869                 frm_addr.yaddr_vir = cur_node->frm_addr_vir.yaddr;
1870                 frm_addr.uaddr_vir = cur_node->frm_addr_vir.uaddr;
1871                 frm_addr.vaddr_vir = cur_node->frm_addr_vir.vaddr;
1872                 ret = path_cfg(DCAM_PATH_OUTPUT_ADDR, &frm_addr);
1873                 IMG_RTN_IF_ERR(ret);
1874         }
1875
1876 exit:
1877         return ret;
1878 }
1879
1880
1881 LOCAL int sprd_img_get_path_index(uint32_t channel_id)
1882 {
1883         int path_index;
1884
1885         switch (channel_id) {
1886         case DCAM_PATH0:
1887                 path_index = DCAM_PATH_IDX_0;
1888                 break;
1889         case DCAM_PATH1:
1890                 path_index = DCAM_PATH_IDX_1;
1891                 break;
1892         case DCAM_PATH2:
1893                 path_index = DCAM_PATH_IDX_2;
1894                 break;
1895         default:
1896                 path_index = DCAM_PATH_IDX_NONE;
1897                 printk("SPRD_IMG: get path index error, invalid channel_id=0x%x \n", channel_id);
1898         }
1899         return path_index;
1900 }
1901
1902 LOCAL int img_get_zoom_rect(struct dcam_rect *src_rect, struct dcam_rect *dst_rect, struct dcam_rect *output_rect, uint32_t zoom_level)
1903 {
1904         uint32_t trim_width = 0;
1905         uint32_t trim_height = 0;
1906         uint32_t zoom_step_w = 0, zoom_step_h = 0;
1907
1908         if (NULL == src_rect || NULL == dst_rect || NULL == output_rect) {
1909                 printk("SPRD_IMG: img_get_zoom_rect: %p, %p, %p\n", src_rect, dst_rect, output_rect);
1910                 return -EINVAL;
1911         }
1912
1913         if (0 == dst_rect->w || 0 == dst_rect->h) {
1914                 printk("SPRD_IMG: img_get_zoom_rect: dst0x%x, 0x%x\n", dst_rect->w, dst_rect->h);
1915                 return -EINVAL;
1916         }
1917
1918         if (src_rect->w > dst_rect->w && src_rect->h > dst_rect->h) {
1919                 zoom_step_w = DCAM_ZOOM_STEP(src_rect->w, dst_rect->w);
1920                 zoom_step_w &= ~1;
1921                 zoom_step_w *= zoom_level;
1922                 trim_width = src_rect->w - zoom_step_w;
1923
1924                 zoom_step_h = DCAM_ZOOM_STEP(src_rect->h, dst_rect->h);
1925                 zoom_step_h &= ~1;
1926                 zoom_step_h *= zoom_level;
1927                 trim_height = src_rect->h - zoom_step_h;
1928
1929                 output_rect->x = src_rect->x + ((src_rect->w - trim_width) >> 1);
1930                 output_rect->y = src_rect->y + ((src_rect->h - trim_height) >> 1);
1931         } else if (src_rect->w < dst_rect->w && src_rect->h < dst_rect->h) {
1932                 zoom_step_w = DCAM_ZOOM_STEP(dst_rect->w, src_rect->w);
1933                 zoom_step_w &= ~1;
1934                 zoom_step_w *= zoom_level;
1935                 trim_width = src_rect->w + zoom_step_w;
1936
1937                 zoom_step_h = DCAM_ZOOM_STEP(dst_rect->h, src_rect->h);
1938                 zoom_step_h &= ~1;
1939                 zoom_step_h *= zoom_level;
1940                 trim_height = src_rect->h + zoom_step_h;
1941
1942                 output_rect->x = src_rect->x - ((trim_width - src_rect->w) >> 1);
1943                 output_rect->y = src_rect->y - ((trim_height - src_rect->h) >> 1);
1944         } else {
1945                 printk("SPRD_IMG: SPRD_IMG img_get_zoom_rect: param error\n");
1946                 return -EINVAL;
1947         }
1948
1949         output_rect->x = DCAM_WIDTH(output_rect->x);
1950         output_rect->y = DCAM_HEIGHT(output_rect->y);
1951         output_rect->w = DCAM_WIDTH(trim_width);
1952         output_rect->h = DCAM_HEIGHT(trim_height);
1953         DCAM_TRACE("SPRD_IMG: zoom_level %d, trim rect, %d %d %d %d\n",
1954                 zoom_level,
1955                 output_rect->x,
1956                 output_rect->y,
1957                 output_rect->w,
1958                 output_rect->h);
1959
1960         return 0;
1961 }
1962
1963 LOCAL int sprd_img_start_zoom(struct dcam_frame *frame, void* param)
1964 {
1965         struct dcam_dev          *dev = (struct dcam_dev*)param;
1966
1967         if (dev == NULL) {
1968                 DCAM_TRACE("SPRD_IMG: sprd_img_start_zoom, dev is NULL \n");
1969                 return -1;
1970         }
1971         DCAM_TRACE("SPRD_IMG: start zoom level %d \n", dev->zoom_level);
1972         if (dev->zoom_level <= DCAM_ZOOM_LEVEL_MAX && dev->dcam_cxt.is_smooth_zoom) {
1973                 up(&dev->zoom_thread_sem);
1974         } else {
1975                 dcam_stop_sc_coeff();
1976         }
1977
1978         return 0;
1979 }
1980
1981 int sprd_img_zoom_thread_loop(void *arg)
1982 {
1983         struct dcam_dev          *dev = (struct dcam_dev*)arg;
1984         int                      ret = DCAM_RTN_SUCCESS;
1985         struct dcam_rect         zoom_rect = {0};
1986         struct dcam_path_spec    *path = NULL;
1987         enum dcam_path_index     path_index;
1988
1989         if (dev == NULL) {
1990                 printk("SPRD_IMG: zoom_thread_loop, dev is NULL \n");
1991                 return -1;
1992         }
1993         while (1) {
1994                 if (0 == down_interruptible(&dev->zoom_thread_sem)) {
1995                         DCAM_TRACE("SPRD_IMG: zoom thread level %d \n", dev->zoom_level);
1996                         if (dev->is_zoom_thread_stop) {
1997                                 DCAM_TRACE("SPRD_IMG: zoom_thread_loop stop \n");
1998                                 break;
1999                         }
2000
2001                         if (dev->zoom_level > DCAM_ZOOM_LEVEL_MAX) {
2002                                 continue;
2003                         }
2004                         mutex_lock(&dev->dcam_mutex);
2005                         path = &dev->dcam_cxt.dcam_path[dev->channel_id];
2006                         path_index = sprd_img_get_path_index(dev->channel_id);
2007                         if (dev->zoom_level < DCAM_ZOOM_LEVEL_MAX) {
2008                                 ret = img_get_zoom_rect(&path->in_rect_backup, &path->in_rect, &zoom_rect, dev->zoom_level);
2009                                 if (!ret) {
2010                                         memcpy((void*)&path->in_rect_current, (void*)&zoom_rect, sizeof(struct dcam_rect));
2011                                         dcam_update_path(path_index, &path->in_size, &zoom_rect, &path->out_size);
2012                                 }
2013                         } else {
2014                                 dcam_update_path(path_index, &path->in_size, &path->in_rect, &path->out_size);
2015                                 memcpy((void*)&path->in_rect_backup, (void*)&path->in_rect, sizeof(struct dcam_rect));
2016                                 memcpy((void*)&path->in_rect_current, (void*)&path->in_rect_backup, sizeof(struct dcam_rect));
2017                         }
2018                         dev->zoom_level++;
2019                         mutex_unlock(&dev->dcam_mutex);
2020                         DCAM_TRACE("SPRD_IMG: zoom thread level  %d  end \n", dev->zoom_level);
2021
2022                 } else {
2023                         printk("SPRD_IMG: zoom int!");
2024                         break;
2025                 }
2026         }
2027         dev->is_zoom_thread_stop = 0;
2028
2029         return 0;
2030 }
2031
2032 int sprd_img_create_zoom_thread(void* param)
2033 {
2034         struct dcam_dev          *dev = (struct dcam_dev*)param;
2035
2036         if (dev == NULL) {
2037                 DCAM_TRACE("create_zoom_thread, dev is NULL \n");
2038                 return -1;
2039         }
2040         DCAM_TRACE("SPRD_IMG: create_zoom_thread E!\n");
2041
2042         dev->is_zoom_thread_stop = 0;
2043         dev->zoom_level = DCAM_ZOOM_LEVEL_MAX + 1;
2044         sema_init(&dev->zoom_thread_sem, 0);
2045         dev->zoom_thread = kthread_run(sprd_img_zoom_thread_loop, param, "img_zoom_thread");
2046         if (IS_ERR(dev->zoom_thread)) {
2047                 printk("SPRD_IMG: create_zoom_thread error!\n");
2048                 return -1;
2049         }
2050         return 0;
2051 }
2052
2053 int sprd_img_stop_zoom_thread(void* param)
2054 {
2055         struct dcam_dev          *dev = (struct dcam_dev*)param;
2056         int cnt = 0;
2057
2058         if (dev == NULL) {
2059                 DCAM_TRACE("stop_zoom_thread, dev is NULL \n");
2060                 return -1;
2061         }
2062         DCAM_TRACE("SPRD_IMG: stop_zoom_thread E!\n");
2063         if (dev->zoom_thread) {
2064                 dev->is_zoom_thread_stop = 1;
2065                 up(&dev->zoom_thread_sem);
2066                 if (dev->is_zoom_thread_stop != 0) {
2067                         while (cnt < 500) {
2068                                 cnt++;
2069                                 if (0 == dev->is_zoom_thread_stop)
2070                                         break;
2071                                 msleep(1);
2072                         }
2073                 }
2074                 dev->zoom_thread = NULL;
2075         }
2076
2077         return 0;
2078 }
2079
2080 LOCAL int sprd_img_update_video(struct file *file, uint32_t channel_id)
2081 {
2082         struct dcam_dev          *dev = file->private_data;
2083         int                      ret = DCAM_RTN_SUCCESS;
2084         struct dcam_path_spec    *path = NULL;
2085         path_cfg_func            path_cfg;
2086         enum dcam_path_index     path_index;
2087
2088
2089         DCAM_TRACE("SPRD_IMG: sprd_img_update_video, channel=%d \n", channel_id);
2090
2091         mutex_lock(&dev->dcam_mutex);
2092
2093         path = &dev->dcam_cxt.dcam_path[channel_id];
2094         path_index = sprd_img_get_path_index(channel_id);
2095
2096         if (DCAM_PATH0 == channel_id) {
2097                 path_cfg = dcam_path0_cfg;
2098         } else if (DCAM_PATH1 == channel_id) {
2099                 path_cfg = dcam_path1_cfg;
2100         }else if (DCAM_PATH2 == channel_id) {
2101                 path_cfg = dcam_path2_cfg;
2102         }
2103
2104         if (dev->dcam_cxt.is_smooth_zoom && DCAM_PATH0 != channel_id) {
2105                 dev->zoom_level = 1;
2106                 dev->channel_id = channel_id;
2107                 if (0 == path->in_rect_backup.w || 0 == path->in_rect_backup.h) {
2108                         path->in_rect_backup.x = 0;
2109                         path->in_rect_backup.y = 0;
2110                         path->in_rect_backup.w = path->in_size.w;
2111                         path->in_rect_backup.h = path->in_size.h;
2112                         memcpy((void*)&path->in_rect_current, (void*)&path->in_rect_backup, sizeof(struct dcam_rect));
2113                 } else {
2114                         memcpy((void*)&path->in_rect_backup, (void*)&path->in_rect_current, sizeof(struct dcam_rect));
2115                 }
2116
2117                 DCAM_TRACE("SPRD_IMG: in_size{%d %d}, in_rect{%d %d %d %d}, in_rect_backup{%d %d %d %d}, out_size{%d %d}\n",
2118                                 path->in_size.w,
2119                                 path->in_size.h,
2120                                 path->in_rect.x,
2121                                 path->in_rect.y,
2122                                 path->in_rect.w,
2123                                 path->in_rect.h,
2124                                 path->in_rect_backup.x,
2125                                 path->in_rect_backup.y,
2126                                 path->in_rect_backup.w,
2127                                 path->in_rect_backup.h,
2128                                 path->out_size.w,
2129                                 path->out_size.h);
2130         } else {
2131                 DCAM_TRACE("SPRD_IMG: in_size{%d %d}, in_rect{%d %d %d %d}, out_size{%d %d}\n",
2132                                 path->in_size.w,
2133                                 path->in_size.h,
2134                                 path->in_rect.x,
2135                                 path->in_rect.y,
2136                                 path->in_rect.w,
2137                                 path->in_rect.h,
2138                                 path->out_size.w,
2139                                 path->out_size.h);
2140                 ret = dcam_update_path(path_index, &path->in_size, &path->in_rect, &path->out_size);
2141         }
2142
2143         mutex_unlock(&dev->dcam_mutex);
2144         DCAM_TRACE("SPRD_IMG: update video 0x%x \n", ret);
2145         if (ret) {
2146                 printk("SPRD_IMG: Failed to update video 0x%x \n", ret);
2147         }
2148
2149         return ret;
2150 }
2151
2152 LOCAL int sprd_img_streampause(struct file *file, uint32_t channel_id, uint32_t reconfig_flag)
2153 {
2154         struct dcam_dev          *dev = file->private_data;
2155         struct dcam_path_spec    *path = NULL;
2156         int                      ret = 0;
2157         enum dcam_path_index     path_index;
2158
2159         printk("SPRD_IMG: pause, channel %d ,recfg flag %d\n", channel_id, reconfig_flag);
2160
2161         path = &dev->dcam_cxt.dcam_path[channel_id];
2162         path_index = sprd_img_get_path_index(channel_id);
2163
2164         if (PATH_RUN == path->status) {
2165                 path->status = PATH_IDLE;
2166                 ret = dcam_stop_path(path_index);
2167                 IMG_PRINT_IF_ERR(ret);
2168                 if ((reconfig_flag)/* && (DCAM_PATH2 == channel_id)*/) {
2169                         //path->is_work = 0;
2170                         path->frm_cnt_act = 0;
2171                         sprd_img_buf_queue_init(&path->buf_queue);
2172                         sprd_img_queue_disable(&dev->queue, channel_id);
2173                         ret = sprd_img_unreg_path2_isr(dev);
2174                         IMG_PRINT_IF_ERR(ret);
2175                 }
2176
2177                 if (DCAM_PATH2 == channel_id && dev->got_resizer) {
2178                         dcam_rel_resizer();
2179                         dev->got_resizer = 0;
2180                 }
2181                 printk("SPRD_IMG: pause, channel=%d done \n", channel_id);
2182         } else {
2183                 printk("SPRD_IMG: pause, path %d not running, status=%d \n",
2184                         channel_id, path->status);
2185         }
2186
2187         return ret;
2188 }
2189
2190 LOCAL int sprd_img_streamresume(struct file *file, uint32_t channel_id)
2191 {
2192         struct dcam_dev          *dev = NULL;
2193         struct dcam_path_spec    *path = NULL;
2194         enum dcam_path_index     path_index;
2195         path_cfg_func            path_cfg;
2196         int                      ret = 0;
2197         int                      on_flag = 1;
2198
2199         DCAM_TRACE("SPRD_IMG: resume, channel=%d \n", channel_id);
2200
2201         dev = file->private_data;
2202         if (!dev) {
2203                 printk("SPRD_IMG: dev is NULL \n");
2204                 return -EFAULT;
2205         }
2206
2207         path = &dev->dcam_cxt.dcam_path[channel_id];
2208         path_index = sprd_img_get_path_index(channel_id);
2209
2210         if (unlikely(0 == atomic_read(&dev->stream_on))) {
2211                 printk("SPRD_IMG: resume stream not on\n");
2212                 ret = sprd_img_local_deinit(dev);
2213                 if (unlikely(ret)) {
2214                         printk(DEBUG_STR,DEBUG_ARGS);
2215                 }
2216                 on_flag = 0;
2217         }
2218         if (PATH_IDLE == path->status && on_flag) {
2219                 if (path->is_work) {
2220                         if (DCAM_PATH0 == channel_id) {
2221                                 path_cfg = dcam_path0_cfg;
2222                         } else if (DCAM_PATH1 == channel_id) {
2223                                 path_cfg = dcam_path1_cfg;
2224                         } else if (DCAM_PATH2 == channel_id) {
2225                                 if (0 == dev->got_resizer) {
2226                                          /* if not owned resiezer, try to get it */
2227                                         if (unlikely(dcam_get_resizer(DCAM_WAIT_FOREVER))) {
2228                                                 /*no wait to get the controller of resizer, failed*/
2229                                                 printk("SPRD_IMG: resume, path2 has been occupied by other app \n");
2230                                                 return -EIO;
2231                                         }
2232                                         dev->got_resizer = 1;
2233                                 }
2234                                 ret = sprd_img_reg_path2_isr(dev);
2235                                 IMG_PRINT_IF_ERR(ret);
2236                                 path_cfg = dcam_path2_cfg;
2237                         } else {
2238                                 printk("SPRD_IMG: resume, invalid channel_id=0x%x \n", channel_id);
2239                                 return -EINVAL;
2240                         }
2241
2242                         if (DCAM_PATH0 == channel_id) {
2243                                 ret = sprd_img_path0_cfg(path_cfg, path);
2244                         } else {
2245                                 ret = sprd_img_path_cfg(path_cfg, path);
2246                         }
2247                         sprd_img_queue_enable(&dev->queue, channel_id);
2248                         IMG_RTN_IF_ERR(ret);
2249                         ret = dcam_start_path(path_index);
2250                         IMG_PRINT_IF_ERR(ret);
2251
2252                         path->status = PATH_RUN;
2253                 }else{
2254                         DCAM_TRACE("SPRD_IMG: resume, path %d no parameter, is_work=%d, cannot resume \n",
2255                                 channel_id, path->is_work);
2256                 }
2257         }else{
2258                 DCAM_TRACE("SPRD_IMG: resume, path %d not idle, status=%d, cannot resume \n",
2259                         channel_id, path->status);
2260         }
2261 exit:
2262         if (ret) {
2263                 DCAM_TRACE("SPRD_IMG: fail resume, path %d, ret = 0x%x\n", channel_id, ret);
2264         }
2265         return ret;
2266 }
2267
2268 LOCAL void sprd_img_print_reg(void)
2269 {
2270         uint32_t*                reg_buf = NULL;
2271         uint32_t                 reg_buf_len = 0x400;
2272         int                      ret;
2273         uint32_t                 print_len = 0, print_cnt = 0;
2274
2275         reg_buf = (uint32_t*)vzalloc(reg_buf_len);
2276         if (NULL == reg_buf)
2277                 return;
2278
2279         ret = dcam_read_registers(reg_buf, &reg_buf_len);
2280         if (ret) {
2281                 vfree(reg_buf);
2282                 return;
2283         }
2284
2285         mm_clk_register_trace();
2286         printk("dcam registers \n");
2287         while (print_len < reg_buf_len) {
2288                 printk("offset 0x%03x : 0x%08x, 0x%08x, 0x%08x, 0x%08x \n",
2289                         print_len,
2290                         reg_buf[print_cnt],
2291                         reg_buf[print_cnt+1],
2292                         reg_buf[print_cnt+2],
2293                         reg_buf[print_cnt+3]);
2294                 print_cnt += 4;
2295                 print_len += 16;
2296         }
2297 #if 0
2298         ret = csi_read_registers(reg_buf, &reg_buf_len);
2299         if (ret) {
2300                 vfree(reg_buf);
2301                 return;
2302         }
2303
2304         print_len = 0;
2305         print_cnt = 0;
2306         printk("csi registers \n");
2307         while (print_len < reg_buf_len) {
2308                 printk("offset 0x%3x : 0x%8x, 0x%8x, 0x%8x, 0x%8x \n",
2309                         print_len,
2310                         reg_buf[print_cnt],
2311                         reg_buf[print_cnt+1],
2312                         reg_buf[print_cnt+2],
2313                         reg_buf[print_cnt+3]);
2314                 print_cnt += 4;
2315                 print_len += 16;
2316         }
2317 #endif
2318         udelay(1);
2319         vfree(reg_buf);
2320
2321         return;
2322
2323 }
2324 LOCAL void sprd_timer_callback(unsigned long data)
2325 {
2326         struct dcam_dev          *dev = (struct dcam_dev*)data;
2327         struct dcam_node         node;
2328         int                      ret = 0;
2329
2330         DCAM_TRACE("SPRD_IMG: sprd_timer_callback \n");
2331
2332         if (0 == data || 0 == atomic_read(&dev->stream_on)) {
2333                 printk("SPRD_IMG: timer cb error \n");
2334                 return;
2335         }
2336
2337         if (0 == atomic_read(&dev->run_flag)) {
2338                 printk("DCAM timeout.\n");
2339                 node.irq_flag = IMG_TIMEOUT;
2340                 node.invalid_flag = 0;
2341                 ret = sprd_img_queue_write(&dev->queue, &node);
2342                 if (ret) {
2343                         printk("SPRD_IMG: timer cb write queue error \n");
2344                 }
2345                 up(&dev->irq_sem);
2346         }
2347 }
2348 LOCAL int sprd_init_timer(struct timer_list *dcam_timer, unsigned long data)
2349 {
2350         int                      ret = 0;
2351
2352         setup_timer(dcam_timer, sprd_timer_callback, data);
2353         return ret;
2354 }
2355 LOCAL int sprd_start_timer(struct timer_list *dcam_timer, uint32_t time_val)
2356 {
2357         int                      ret = 0;
2358
2359         DCAM_TRACE("SPRD_IMG: starting timer %ld \n",jiffies);
2360         ret = mod_timer(dcam_timer, jiffies + msecs_to_jiffies(time_val));
2361         if (ret) {
2362                 printk("SPRD_IMG: Error in mod_timer %d \n",ret);
2363         }
2364         return ret;
2365 }
2366
2367 LOCAL int sprd_stop_timer(struct timer_list *dcam_timer)
2368 {
2369         int                      ret = 0;
2370
2371         DCAM_TRACE("SPRD_IMG: stop timer \n");
2372         del_timer_sync(dcam_timer);
2373         return ret;
2374 }
2375
2376 LOCAL int sprd_init_handle(struct dcam_dev *dev)
2377 {
2378         struct dcam_info         *info = &dev->dcam_cxt;
2379         struct dcam_path_spec    *path;
2380         uint32_t                 i = 0;
2381
2382         if (NULL == info) {
2383                 printk("SPRD_IMG: init handle fail \n");
2384                 return -EINVAL;
2385         }
2386         info->flash_status = FLASH_STATUS_MAX;
2387         info->after_af = 0;
2388         for (i = 0; i < DCAM_PATH_MAX; i++) {
2389                 path = &info->dcam_path[i];
2390                 if (NULL == path) {
2391                         printk("SPRD_IMG: init path %d fail \n", i);
2392                         return -EINVAL;
2393                 }
2394                 memset((void*)path->frm_ptr,
2395                         0,
2396                         (uint32_t)(DCAM_FRM_CNT_MAX * sizeof(struct dcam_frame*)));
2397                 path->frm_cnt_act = 0;
2398                 sprd_img_buf_queue_init(&path->buf_queue);
2399                 path->status = PATH_IDLE;
2400         }
2401         atomic_set(&dev->stream_on, 0);
2402         dev->got_resizer = 0;
2403         return 0;
2404 }
2405
2406 LOCAL int sprd_img_k_open(struct inode *node, struct file *file)
2407 {
2408         struct dcam_dev          *dev = NULL;
2409         struct miscdevice        *md = file->private_data;
2410         int                      ret = 0;
2411
2412         dev = vzalloc(sizeof(*dev));
2413         if (!dev) {
2414                 ret = -ENOMEM;
2415                 printk("sprd_img_k_open fail alloc \n");
2416                 return ret;
2417         }
2418
2419         mutex_init(&dev->dcam_mutex);
2420         sema_init(&dev->irq_sem, 0);
2421
2422         if (unlikely(atomic_inc_return(&dev->users) > 1)) {
2423                 ret = -EBUSY;
2424                 goto exit;
2425         }
2426
2427         DCAM_TRACE("sprd_img_k_open \n");
2428         ret = dcam_module_en(md->this_device->of_node);
2429         if (unlikely(ret != 0)) {
2430                 printk("SPRD_IMG: Failed to enable dcam module \n");
2431                 ret = -EIO;
2432                 goto exit;
2433         }
2434
2435         ret = sprd_img_queue_init(&dev->queue);
2436         if (unlikely(ret != 0)) {
2437                 printk("SPRD_IMG: Failed to init queue \n");
2438                 ret = -EIO;
2439                 goto exit;
2440         }
2441
2442         ret = sprd_init_timer(&dev->dcam_timer,(unsigned long)dev);
2443         if (unlikely(ret != 0)) {
2444                 printk("SPRD_IMG: Failed to init timer \n");
2445                 ret = -EIO;
2446                 goto exit;
2447         }
2448
2449         ret = sprd_init_handle(dev);
2450         if (unlikely(ret != 0)) {
2451                 printk("SPRD_IMG: Failed to init queue \n");
2452                 ret = -EIO;
2453                 goto exit;
2454         }
2455
2456         ret = dcam_create_flash_thread(dev);
2457         if (unlikely(ret != 0)) {
2458                 printk("SPRD_IMG: Failed to create flash thread \n");
2459                 ret = -EIO;
2460                 goto exit;
2461         }
2462
2463         ret = sprd_img_create_zoom_thread(dev);
2464         if (unlikely(ret != 0)) {
2465                 printk("SPRD_IMG: Failed to create zoom thread \n");
2466                 ret = -EIO;
2467                 goto exit;
2468         }
2469
2470         dev->driver_data = (void*)md;
2471         file->private_data = (void*)dev;
2472
2473 exit:
2474         if (unlikely(ret)) {
2475                 atomic_dec(&dev->users);
2476         } else {
2477 #if 0
2478                 dev->proc_file = create_proc_read_entry(DCAM_PROC_FILE_NAME,
2479                                                 0444,
2480                                                 NULL,
2481                                                 sprd_img_proc_read,
2482                                                 (void*)dev);
2483                 if (unlikely(NULL == dev->proc_file)) {
2484                         printk("SPRD_IMG: Can't create an entry for video0 in /proc \n");
2485                         ret = ENOMEM;
2486                 }
2487 #endif
2488         }
2489
2490         printk("sprd_img_k_open %d \n", ret);
2491         return ret;
2492 }
2493
2494 static int sprd_img_k_release(struct inode *node, struct file *file)
2495 {
2496         struct dcam_dev                  *dev = NULL;
2497         struct miscdevice        *md = NULL;
2498         int                                      ret = 0;
2499
2500         DCAM_TRACE("SPRD_IMG: Close start\n");
2501 #if 0
2502         if (dev->proc_file) {
2503                 DCAM_TRACE("SPRD_IMG: sprd_img_k_release \n");
2504                 remove_proc_entry(DCAM_PROC_FILE_NAME, NULL);
2505                 dev->proc_file = NULL;
2506         }
2507 #endif
2508
2509         dev = file->private_data;
2510         if (!dev)
2511                 goto exit;
2512
2513         md = dev->driver_data;
2514
2515         mutex_lock(&dev->dcam_mutex);
2516         dcam_reset(DCAM_RST_ALL, 0);
2517         if (dev->got_resizer) {
2518                 dcam_rel_resizer();
2519                 dev->got_resizer = 0;
2520                 sprd_img_unreg_path2_isr(dev);
2521         }
2522
2523         atomic_set(&dev->stream_on, 0);
2524         dcam_module_deinit(dev->dcam_cxt.if_mode, dev->dcam_cxt.sn_mode);
2525         sprd_img_local_deinit(dev);
2526         sema_init(&dev->irq_sem, 0);
2527         ret = dcam_module_dis(md->this_device->of_node);
2528         if (unlikely(0 != ret)) {
2529                 printk("SPRD_IMG: Failed to enable dcam module \n");
2530                 ret = -EIO;
2531         }
2532         sprd_stop_timer(&dev->dcam_timer);
2533         atomic_dec(&dev->users);
2534         dcam_stop_flash_thread(dev);
2535         sprd_img_stop_zoom_thread(dev);
2536         mutex_unlock(&dev->dcam_mutex);
2537
2538         vfree(dev);
2539         dev = NULL;
2540         file->private_data = NULL;
2541
2542 exit:
2543         DCAM_TRACE("SPRD_IMG: Close end.\n");
2544         return ret;
2545 }
2546
2547 static long sprd_img_k_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2548 {
2549         struct dcam_dev          *dev = NULL;
2550         struct dcam_info                 *info = NULL;
2551         uint32_t                                 path_cnt;
2552         uint32_t                 channel_id;
2553         uint32_t                 mode;
2554         uint32_t                 skip_num;
2555         uint32_t                 flash_status;
2556         uint32_t                 zoom;
2557         struct sprd_img_parm     parm;
2558         struct sprd_img_size     size;
2559         struct sprd_img_rect     rect;
2560         struct dcam_path_spec    *path = NULL;
2561         struct dcam_rect         *input_rect;
2562         struct dcam_size         *input_size;
2563         path_cfg_func            path_cfg;
2564         int                      ret = DCAM_RTN_SUCCESS;
2565
2566         DCAM_TRACE("sprd_img_k_ioctl: cmd: 0x%x \n", cmd);
2567
2568         dev = file->private_data;
2569         if (!dev) {
2570                 ret = -EFAULT;
2571                 printk("sprd_img_k_ioctl: dev is NULL \n");
2572                 goto exit;
2573         }
2574
2575         info = &dev->dcam_cxt;
2576
2577         switch (cmd) {
2578         case SPRD_IMG_IO_SET_MODE:
2579                 mutex_lock(&dev->dcam_mutex);
2580                 ret = copy_from_user(&mode, (uint32_t *)arg, sizeof(uint32_t));
2581                 if (ret) {
2582                         printk("sprd_img_k_ioctl: fail to get user info \n");
2583                         mutex_unlock(&dev->dcam_mutex);
2584                         goto exit;
2585                 }
2586                 dev->dcam_cxt.capture_mode = mode;
2587                 mutex_unlock(&dev->dcam_mutex);
2588                 DCAM_TRACE("SPRD_IMG: capture mode %d \n", dev->dcam_cxt.capture_mode);
2589                 break;
2590
2591         case SPRD_IMG_IO_SET_SKIP_NUM:
2592                 mutex_lock(&dev->dcam_mutex);
2593                 ret = copy_from_user(&skip_num, (uint32_t *)arg, sizeof(uint32_t));
2594                 if (ret) {
2595                         printk("sprd_img_k_ioctl: fail to get user info \n");
2596                         mutex_unlock(&dev->dcam_mutex);
2597                         goto exit;
2598                 }
2599                 dev->dcam_cxt.skip_number = skip_num;
2600                 mutex_unlock(&dev->dcam_mutex);
2601                 DCAM_TRACE("SPRD_IMG: cap skip number %d \n", dev->dcam_cxt.skip_number);
2602                 break;
2603
2604         case SPRD_IMG_IO_SET_SENSOR_SIZE:
2605                 mutex_lock(&dev->dcam_mutex);
2606                 ret = copy_from_user(&size, (struct sprd_img_size *)arg, sizeof(struct sprd_img_size));
2607                 if (ret) {
2608                         printk("sprd_img_k_ioctl: fail to get user info \n");
2609                         mutex_unlock(&dev->dcam_mutex);
2610                         goto exit;
2611                 }
2612                 dev->dcam_cxt.cap_in_size.w = size.w;
2613                 dev->dcam_cxt.cap_in_size.h = size.h;
2614                 mutex_unlock(&dev->dcam_mutex);
2615                 DCAM_TRACE("SPRD_IMG: sensor size %d %d \n",
2616                         dev->dcam_cxt.cap_in_size.w,
2617                         dev->dcam_cxt.cap_in_size.h);
2618                 break;
2619
2620         case SPRD_IMG_IO_SET_SENSOR_TRIM:
2621                 mutex_lock(&dev->dcam_mutex);
2622                 ret = copy_from_user(&rect, (struct sprd_img_rect *)arg, sizeof(struct sprd_img_rect));
2623                 if (ret) {
2624                         printk("sprd_img_k_ioctl: fail to get user info \n");
2625                         mutex_unlock(&dev->dcam_mutex);
2626                         goto exit;
2627                 }
2628                 dev->dcam_cxt.cap_in_rect.x = rect.x;
2629                 dev->dcam_cxt.cap_in_rect.y = rect.y;
2630                 dev->dcam_cxt.cap_in_rect.w = rect.w;
2631                 dev->dcam_cxt.cap_in_rect.h = rect.h;
2632
2633                 dev->dcam_cxt.cap_out_size.w = dev->dcam_cxt.cap_in_rect.w;
2634                 dev->dcam_cxt.cap_out_size.h = dev->dcam_cxt.cap_in_rect.h;
2635                 mutex_unlock(&dev->dcam_mutex);
2636                 DCAM_TRACE("SPRD_IMG: sensor trim x y w h %d %d %d %d\n",
2637                         dev->dcam_cxt.cap_in_rect.x,
2638                         dev->dcam_cxt.cap_in_rect.y,
2639                         dev->dcam_cxt.cap_in_rect.w,
2640                         dev->dcam_cxt.cap_in_rect.h);
2641                 break;
2642
2643         case SPRD_IMG_IO_SET_FRM_ID_BASE:
2644                 mutex_lock(&dev->dcam_mutex);
2645                 ret = copy_from_user(&parm, (struct sprd_img_parm *)arg, sizeof(struct sprd_img_parm));
2646                 if (ret) {
2647                         printk("sprd_img_k_ioctl: fail to get user info \n");
2648                         mutex_unlock(&dev->dcam_mutex);
2649                         goto exit;
2650                 }
2651                 switch (parm.channel_id) {
2652                 case DCAM_PATH0:
2653                 case DCAM_PATH1:
2654                 case DCAM_PATH2:
2655                         dev->dcam_cxt.dcam_path[parm.channel_id].frm_id_base = parm.frame_base_id;
2656                         break;
2657                 default:
2658                         printk("SPRD_IMG: Wrong channel ID, %d  \n", parm.channel_id);
2659                         mutex_unlock(&dev->dcam_mutex);
2660                         goto exit;
2661                 }
2662                 mutex_unlock(&dev->dcam_mutex);
2663                 DCAM_TRACE("SPRD_IMG: channel %d, base id 0x%x \n",
2664                         parm.channel_id,
2665                         parm.frame_base_id);
2666                 break;
2667
2668         case SPRD_IMG_IO_SET_CROP:
2669                 mutex_lock(&dev->dcam_mutex);
2670                 ret = copy_from_user(&parm, (struct sprd_img_parm *)arg, sizeof(struct sprd_img_parm));
2671                 if (ret) {
2672                         printk("sprd_img_k_ioctl: fail to get user info \n");
2673                         mutex_unlock(&dev->dcam_mutex);
2674                         goto exit;
2675                 }
2676
2677                 if (unlikely(parm.crop_rect.x + parm.crop_rect.w > dev->dcam_cxt.cap_in_size.w ||
2678                         parm.crop_rect.y + parm.crop_rect.h > dev->dcam_cxt.cap_in_size.h)) {
2679                         mutex_unlock(&dev->dcam_mutex);
2680                         ret = -EINVAL;
2681                         goto exit;
2682                 }
2683
2684                 DCAM_TRACE("SPRD_IMG: SPRD_IMG_IO_SET_CROP, window %d %d %d %d \n",
2685                         parm.crop_rect.x,
2686                         parm.crop_rect.y,
2687                         parm.crop_rect.w,
2688                         parm.crop_rect.h);
2689
2690                 switch (parm.channel_id) {
2691                 case DCAM_PATH0:
2692                 case DCAM_PATH1:
2693                 case DCAM_PATH2:
2694                         input_size = &dev->dcam_cxt.dcam_path[parm.channel_id].in_size;
2695                         input_rect = &dev->dcam_cxt.dcam_path[parm.channel_id].in_rect;
2696                         break;
2697                 default:
2698                         printk("SPRD_IMG: Wrong channel ID, %d  \n", parm.channel_id);
2699                         mutex_unlock(&dev->dcam_mutex);
2700                         goto exit;
2701                 }
2702
2703                 input_size->w = dev->dcam_cxt.cap_out_size.w;
2704                 input_size->h = dev->dcam_cxt.cap_out_size.h;
2705                 input_rect->x = parm.crop_rect.x;
2706                 input_rect->y = parm.crop_rect.y;
2707                 input_rect->w = parm.crop_rect.w;
2708                 input_rect->h = parm.crop_rect.h;
2709
2710                 DCAM_TRACE("SPRD_IMG: SPRD_IMG_IO_SET_CROP, Path %d, cap crop: cap_rect %d %d %d %d, cap_out:%d %d \n",
2711                                 parm.channel_id, input_rect->x, input_rect->y,
2712                                 input_rect->w, input_rect->h,
2713                                 input_size->w, input_size->h);
2714                 mutex_unlock(&dev->dcam_mutex);
2715                 break;
2716
2717         case SPRD_IMG_IO_SET_FLASH:
2718                 mutex_lock(&dev->dcam_mutex);
2719                 ret = copy_from_user(&flash_status, (uint32_t *)arg, sizeof(uint32_t));
2720                 if (ret) {
2721                         printk("sprd_img_k_ioctl: fail to get user info \n");
2722                         mutex_unlock(&dev->dcam_mutex);
2723                         goto exit;
2724                 }
2725                 dev->dcam_cxt.flash_status = flash_status;
2726                 mutex_unlock(&dev->dcam_mutex);
2727                 if ((dev->dcam_cxt.flash_status == FLASH_CLOSE_AFTER_OPEN)
2728                         || (dev->dcam_cxt.flash_status == FLASH_CLOSE)
2729                         || (dev->dcam_cxt.flash_status == FLASH_CLOSE_AFTER_AUTOFOCUS)) {
2730                         up(&dev->flash_thread_sem);
2731                 }
2732                 DCAM_TRACE("SPRD_IMG: SPRD_IMG_IO_SET_FLASH, flash status %d \n", dev->dcam_cxt.flash_status);
2733                 break;
2734
2735         case SPRD_IMG_IO_SET_OUTPUT_SIZE:
2736                 DCAM_TRACE("SPRD_IMG: set output size \n");
2737                 mutex_lock(&dev->dcam_mutex);
2738                 ret = copy_from_user(&parm, (struct sprd_img_parm *)arg, sizeof(struct sprd_img_parm));
2739                 if (ret) {
2740                         printk("sprd_img_k_ioctl: fail to get user info \n");
2741                         mutex_unlock(&dev->dcam_mutex);
2742                         goto exit;
2743                 }
2744                 dev->dcam_cxt.dst_size.w = parm.dst_size.w;
2745                 dev->dcam_cxt.dst_size.h = parm.dst_size.h;
2746                 dev->dcam_cxt.pxl_fmt = parm.pixel_fmt;
2747                 dev->dcam_cxt.need_isp_tool = parm.need_isp_tool;
2748                 dev->dcam_cxt.need_isp = parm.need_isp;
2749                 dev->dcam_cxt.need_shrink = parm.shrink;
2750                 dev->dcam_cxt.camera_id = parm.camera_id;
2751                 dev->dcam_cxt.path_input_rect.x = parm.crop_rect.x;
2752                 dev->dcam_cxt.path_input_rect.y = parm.crop_rect.y;
2753                 dev->dcam_cxt.path_input_rect.w = parm.crop_rect.w;
2754                 dev->dcam_cxt.path_input_rect.h = parm.crop_rect.h;
2755                 mutex_unlock(&dev->dcam_mutex);
2756                 break;
2757
2758         case SPRD_IMG_IO_SET_ZOOM_MODE:
2759                 mutex_lock(&dev->dcam_mutex);
2760                 ret = copy_from_user(&zoom, (uint32_t *)arg, sizeof(uint32_t));
2761                 if (ret) {
2762                         printk("sprd_img_k_ioctl: fail to get user info \n");
2763                         mutex_unlock(&dev->dcam_mutex);
2764                         goto exit;
2765                 }
2766                 dev->dcam_cxt.is_smooth_zoom = zoom;
2767                 mutex_unlock(&dev->dcam_mutex);
2768                 DCAM_TRACE("SPRD_IMG: SPRD_IMG_IO_SET_ZOOM_MODE, zoom mode %d \n", dev->dcam_cxt.is_smooth_zoom);
2769                 break;
2770
2771         case SPRD_IMG_IO_SET_SENSOR_IF:
2772         {
2773                 struct sprd_img_sensor_if sensor_if;
2774
2775                 DCAM_TRACE("SPRD_IMG: set sensor if \n");
2776                 mutex_lock(&dev->dcam_mutex);
2777                 ret = copy_from_user(&sensor_if, (struct sprd_img_sensor_if *)arg, sizeof(struct sprd_img_sensor_if));
2778                 if (unlikely(ret)) {
2779                         printk("sprd_img_k_ioctl: fail to get user info \n");
2780                         mutex_unlock(&dev->dcam_mutex);
2781                         goto exit;
2782                 }
2783
2784                 if (IF_OPEN == sensor_if.res[0]) {
2785                         dev->dcam_cxt.if_mode     = sensor_if.if_type;
2786                         dev->dcam_cxt.sn_mode     = sensor_if.img_fmt;
2787                         dev->dcam_cxt.yuv_ptn     = sensor_if.img_ptn;
2788                         dev->dcam_cxt.frm_deci    = sensor_if.frm_deci;
2789
2790                         DCAM_TRACE("SPRD_IMG: interface %d, mode %d frm_deci %d \n",
2791                                 dev->dcam_cxt.if_mode,
2792                                 dev->dcam_cxt.sn_mode,
2793                                 dev->dcam_cxt.frm_deci);
2794
2795                         if (DCAM_CAP_IF_CCIR == dev->dcam_cxt.if_mode) {
2796                                 /* CCIR interface */
2797                                 dev->dcam_cxt.sync_pol.vsync_pol = sensor_if.if_spec.ccir.v_sync_pol;
2798                                 dev->dcam_cxt.sync_pol.hsync_pol = sensor_if.if_spec.ccir.h_sync_pol;
2799                                 dev->dcam_cxt.sync_pol.pclk_pol  = sensor_if.if_spec.ccir.pclk_pol;
2800                                 dev->dcam_cxt.data_bits          = 8;
2801                                 DCAM_TRACE("SPRD_IMG: CIR interface, vsync %d hsync %d pclk %d psrc %d bits %d \n",
2802                                         dev->dcam_cxt.sync_pol.vsync_pol,
2803                                         dev->dcam_cxt.sync_pol.hsync_pol,
2804                                         dev->dcam_cxt.sync_pol.pclk_pol,
2805                                         dev->dcam_cxt.sync_pol.pclk_src,
2806                                         dev->dcam_cxt.data_bits);
2807                         } else {
2808                                 dev->dcam_cxt.sync_pol.need_href = sensor_if.if_spec.mipi.use_href;
2809                                 dev->dcam_cxt.is_loose           = sensor_if.if_spec.mipi.is_loose;
2810                                 dev->dcam_cxt.data_bits          = sensor_if.if_spec.mipi.bits_per_pxl;
2811                                 dev->dcam_cxt.lane_num           = sensor_if.if_spec.mipi.lane_num;
2812                                 dev->dcam_cxt.pclk               = sensor_if.if_spec.mipi.pclk;
2813                                 DCAM_TRACE("SPRD_IMG: MIPI interface, ref %d is_loose %d bits %d lanes %d pclk %d\n",
2814                                         dev->dcam_cxt.sync_pol.need_href,
2815                                         dev->dcam_cxt.is_loose,
2816                                         dev->dcam_cxt.data_bits,
2817                                         dev->dcam_cxt.lane_num,
2818                                         dev->dcam_cxt.pclk);
2819                         }
2820                 }
2821                 mutex_unlock(&dev->dcam_mutex);
2822                 break;
2823         }
2824
2825         case SPRD_IMG_IO_SET_FRAME_ADDR:
2826                 DCAM_TRACE("SPRD_IMG: set frame addr \n");
2827                 mutex_lock(&dev->dcam_mutex);
2828                 ret = copy_from_user(&parm, (struct sprd_img_parm *)arg, sizeof(struct sprd_img_parm));
2829                 if (ret) {
2830                         printk("sprd_img_k_ioctl: fail to get user info \n");
2831                         mutex_unlock(&dev->dcam_mutex);
2832                         goto exit;
2833                 }
2834                 DCAM_TRACE("SPRD_IMG: SPRD_IMG_IO_SET_FRAME_ADDR = %d \n",parm.channel_id);
2835
2836                 switch (parm.channel_id) {
2837                 case DCAM_PATH0:
2838                         path = &info->dcam_path[DCAM_PATH0];
2839                         path_cnt = DCAM_PATH_0_FRM_CNT_MAX;
2840                         path_cfg = dcam_path0_cfg;
2841                         break;
2842                 case DCAM_PATH1:
2843                         path = &info->dcam_path[DCAM_PATH1];
2844                         path_cnt = DCAM_PATH_1_FRM_CNT_MAX;
2845                         path_cfg = dcam_path1_cfg;
2846                         break;
2847                 case DCAM_PATH2:
2848                         path = &info->dcam_path[DCAM_PATH2];
2849                         path_cnt = DCAM_PATH_2_FRM_CNT_MAX;
2850                         path_cfg = dcam_path2_cfg;
2851                         break;
2852                 default:
2853                         printk("SPRD_IMG error: SPRD_IMG_IO_SET_FRAME_ADDR, path 0x%x \n", parm.channel_id);
2854                         mutex_unlock(&dev->dcam_mutex);
2855                         return -EINVAL;
2856                 }
2857
2858
2859                 DCAM_TRACE("SPRD_IMG: SPRD_IMG_IO_SET_FRAME_ADDR, status %d, frm_cnt_act %d \n",
2860                         path->status, path->frm_cnt_act);
2861
2862                 if (unlikely(0 == parm.frame_addr.y)) {
2863                         printk("SPRD_IMG: No yaddr \n");
2864                         mutex_unlock(&dev->dcam_mutex);
2865                         ret = -EINVAL;
2866                 } else {
2867                         if (1 == parm.is_reserved_buf) {
2868                                 path->frm_reserved_addr.yaddr = parm.frame_addr.y;
2869                                 path->frm_reserved_addr.uaddr = parm.frame_addr.u;
2870                                 path->frm_reserved_addr.vaddr = parm.frame_addr.v;
2871                                 path->frm_reserved_addr_vir.yaddr = parm.frame_addr_vir.y;
2872                                 path->frm_reserved_addr_vir.uaddr = parm.frame_addr_vir.u;
2873                                 path->frm_reserved_addr_vir.vaddr = parm.frame_addr_vir.v;
2874                         } else {
2875                                 struct dcam_addr         frame_addr;
2876                                 struct dcam_img_buf_addr buf_addr;
2877
2878                                 frame_addr.yaddr = parm.frame_addr.y;
2879                                 frame_addr.uaddr = parm.frame_addr.u;
2880                                 frame_addr.vaddr = parm.frame_addr.v;
2881                                 frame_addr.yaddr_vir = parm.frame_addr_vir.y;
2882                                 frame_addr.uaddr_vir = parm.frame_addr_vir.u;
2883                                 frame_addr.vaddr_vir = parm.frame_addr_vir.v;
2884
2885                                 DCAM_TRACE("SPRD_IMG: SPRD_IMG_IO_SET_FRAME_ADDR, yaddr: 0x%x, uaddr: 0x%x, vaddr: 0x%x\n",
2886                                         parm.frame_addr.y,
2887                                         parm.frame_addr.u,
2888                                         parm.frame_addr.v);
2889
2890                                 if (unlikely(1 == atomic_read(&dev->stream_on)) && path->status == PATH_RUN) {
2891                                         ret = path_cfg(DCAM_PATH_OUTPUT_ADDR, &frame_addr);
2892                                 } else {
2893                                         buf_addr.frm_addr.yaddr = parm.frame_addr.y;
2894                                         buf_addr.frm_addr.uaddr = parm.frame_addr.u;
2895                                         buf_addr.frm_addr.vaddr = parm.frame_addr.v;
2896                                         buf_addr.frm_addr_vir.yaddr = parm.frame_addr_vir.y;
2897                                         buf_addr.frm_addr_vir.uaddr = parm.frame_addr_vir.u;
2898                                         buf_addr.frm_addr_vir.vaddr = parm.frame_addr_vir.v;
2899                                         ret = sprd_img_buf_queue_write(&path->buf_queue, &buf_addr);
2900                                 }
2901                         } 
2902                 }
2903                 mutex_unlock(&dev->dcam_mutex);
2904                 break;
2905
2906         case SPRD_IMG_IO_PATH_FRM_DECI:
2907                 mutex_lock(&dev->dcam_mutex);
2908                 ret = copy_from_user(&parm, (struct sprd_img_parm *)arg, sizeof(struct sprd_img_parm));
2909                 if (ret) {
2910                         printk("sprd_img_k_ioctl: fail to get user info \n");
2911                         mutex_unlock(&dev->dcam_mutex);
2912                         goto exit;
2913                 }
2914                 path = &dev->dcam_cxt.dcam_path[parm.channel_id];
2915                 path->path_frm_deci = 0;//parm.deci; // aiden tmp changes
2916                 mutex_unlock(&dev->dcam_mutex);
2917                 DCAM_TRACE("SPRD_IMG: channel %d, frm_deci=%d \n", parm.channel_id, path->path_frm_deci);
2918                 break;
2919
2920         case SPRD_IMG_IO_SET_SHRINK:
2921                 mutex_lock(&dev->dcam_mutex);
2922                 ret = copy_from_user(&parm, (struct sprd_img_parm *)arg, sizeof(struct sprd_img_parm));
2923                 if (ret) {
2924                         printk("sprd_img_k_ioctl: fail to get user info \n");
2925                         mutex_unlock(&dev->dcam_mutex);
2926                         goto exit;
2927                 }
2928                 path = &dev->dcam_cxt.dcam_path[parm.channel_id];
2929                 path->shrink = parm.shrink;
2930                 mutex_unlock(&dev->dcam_mutex);
2931                 DCAM_TRACE("SPRD_IMG: channel %d, shrink=%d \n", parm.channel_id, path->shrink);
2932                 break;
2933
2934         case SPRD_IMG_IO_PATH_PAUSE:
2935                 ret = copy_from_user(&parm, (struct sprd_img_parm *)arg, sizeof(struct sprd_img_parm));
2936                 if (ret) {
2937                         printk("sprd_img_k_ioctl: fail to get user info \n");
2938                         goto exit;
2939                 }
2940                 sprd_img_streampause(file, parm.channel_id, parm.reserved[0]);
2941                 break;
2942
2943         case SPRD_IMG_IO_PATH_RESUME:
2944                 ret = copy_from_user(&channel_id, (uint32_t *)arg, sizeof(uint32_t));
2945                 if (ret) {
2946                         printk("sprd_img_k_ioctl: fail to get user info \n");
2947                         goto exit;
2948                 }
2949                 sprd_img_streamresume(file, channel_id);
2950                 break;
2951
2952         case SPRD_IMG_IO_STREAM_ON:
2953         {
2954                 struct dcam_path_spec *path_0 = NULL;
2955                 struct dcam_path_spec *path_1 = NULL;
2956                 struct dcam_path_spec *path_2 = NULL;
2957
2958                 DCAM_TRACE("SPRD_IMG: SPRD_IMG_IO_STREAM_ON \n");
2959
2960                 mutex_lock(&dev->dcam_mutex);
2961
2962                 path_0 = &dev->dcam_cxt.dcam_path[DCAM_PATH0];
2963                 path_1 = &dev->dcam_cxt.dcam_path[DCAM_PATH1];
2964                 path_2 = &dev->dcam_cxt.dcam_path[DCAM_PATH2];
2965                 memset((void*)path_0->frm_ptr,
2966                         0,
2967                         (uint32_t)(DCAM_FRM_CNT_MAX * sizeof(struct dcam_frame*)));
2968                 memset((void*)path_1->frm_ptr,
2969                         0,
2970                         (uint32_t)(DCAM_FRM_CNT_MAX * sizeof(struct dcam_frame*)));
2971                 memset((void*)path_2->frm_ptr,
2972                         0,
2973                         (uint32_t)(DCAM_FRM_CNT_MAX * sizeof(struct dcam_frame*)));
2974
2975                 DCAM_TRACE("SPRD_IMG: streamon, is_work: path_0 = %d, path_1 = %d, path_2 = %d, stream_on = %d \n",
2976                         path_0->is_work, path_1->is_work, path_2->is_work, atomic_read(&dev->stream_on));
2977
2978                 memset((void*)&path_1->in_rect_backup, 0x00, sizeof(struct dcam_rect));
2979                 memset((void*)&path_1->in_rect_current, 0x00, sizeof(struct dcam_rect));
2980
2981                 do {
2982                         /* dcam driver module initialization */
2983                         ret = dcam_module_init(dev->dcam_cxt.if_mode, dev->dcam_cxt.sn_mode);
2984                         if (unlikely(ret)) {
2985                                 printk(DEBUG_STR,DEBUG_ARGS);
2986                                 break;
2987                         }
2988
2989                         ret = sprd_img_queue_init(&dev->queue);
2990                         if (unlikely(ret != 0)) {
2991                                 printk("SPRD_IMG: Failed to init queue \n");
2992                                 break;
2993                         }
2994
2995                         ret = sprd_img_reg_isr(dev);
2996                         if (unlikely(ret)) {
2997                                 printk(DEBUG_STR,DEBUG_ARGS);
2998                                 break;
2999                         }
3000
3001                         /* config cap sub-module */
3002                         ret = sprd_img_cap_cfg(&dev->dcam_cxt);
3003                         if (unlikely(ret)) {
3004                                 printk(DEBUG_STR,DEBUG_ARGS);
3005                                 break;
3006                         }
3007
3008                         /* config path1 sub-module if necessary*/
3009                         if (path_1->is_work) {
3010                                 ret = sprd_img_path_cfg(dcam_path1_cfg, path_1);
3011                                 if (unlikely(ret)) {
3012                                         printk(DEBUG_STR,DEBUG_ARGS);
3013                                         break;
3014                                 }
3015                                 path_1->status = PATH_RUN;
3016                         } else {
3017                                 ret = dcam_path1_cfg(DCAM_PATH_ENABLE, &path_1->is_work);
3018                                 if (unlikely(ret)) {
3019                                         printk(DEBUG_STR,DEBUG_ARGS);
3020                                         break;
3021                                 }
3022                         }
3023
3024                         /* config path2 sub-module if necessary*/
3025                         if (path_2->is_work) {
3026                                 ret = sprd_img_path_cfg(dcam_path2_cfg, path_2);
3027                                 if (unlikely(ret)) {
3028                                         printk(DEBUG_STR,DEBUG_ARGS);
3029                                         break;
3030                                 }
3031                                 ret = sprd_img_reg_path2_isr(dev);
3032                                 if (unlikely(ret)) {
3033                                         printk(DEBUG_STR,DEBUG_ARGS);
3034                                         break;
3035                                 }
3036                                 path_2->status = PATH_RUN;
3037                         } else {
3038                                 ret = dcam_path2_cfg(DCAM_PATH_ENABLE, &path_2->is_work);
3039                                 if (unlikely(ret)) {
3040                                         printk(DEBUG_STR,DEBUG_ARGS);
3041                                         break;
3042                                 }
3043                         }
3044
3045                         if (path_0->is_work) {
3046                                 ret = sprd_img_path0_cfg(dcam_path0_cfg, path_0);
3047                                 if (unlikely(ret)) {
3048                                         printk(DEBUG_STR,DEBUG_ARGS);
3049                                         break;
3050                                 }
3051                                 path_0->status = PATH_RUN;
3052                         } else {
3053                                 ret = dcam_path0_cfg(DCAM_PATH_ENABLE, &path_0->is_work);
3054                                 if (unlikely(ret)) {
3055                                         printk(DEBUG_STR,DEBUG_ARGS);
3056                                         break;
3057                                 }
3058                         }
3059                 } while(0);
3060                 dev->frame_skipped = 0;
3061                 if (FLASH_HIGH_LIGHT == dev->dcam_cxt.flash_status) {
3062                         if (0 == dev->dcam_cxt.skip_number) {
3063                                 sprd_img_start_flash(NULL, dev);
3064                         }
3065                 }
3066
3067                 ret = dcam_start();
3068                 atomic_set(&dev->stream_on, 1);
3069
3070                 if (ret) {
3071                         sprd_img_unreg_path2_isr(dev);
3072                         sprd_img_unreg_isr(dev);
3073                         printk("SPRD_IMG: Failed to start stream 0x%x \n", ret);
3074                 } else {
3075                         atomic_set(&dev->run_flag, 0);
3076                         sprd_start_timer(&dev->dcam_timer, DCAM_TIMEOUT);
3077                 }
3078
3079                 mutex_unlock(&dev->dcam_mutex);
3080                 break;
3081         }
3082
3083         case SPRD_IMG_IO_STREAM_OFF:
3084         {
3085                 struct dcam_path_spec *path_0 = NULL;
3086                 struct dcam_path_spec *path_1 = NULL;
3087                 struct dcam_path_spec *path_2 = NULL;
3088
3089                 DCAM_TRACE("SPRD_IMG: SPRD_IMG_IO_STREAM_OFF \n");
3090
3091                 mutex_lock(&dev->dcam_mutex);
3092
3093                 path_0 = &dev->dcam_cxt.dcam_path[DCAM_PATH0];
3094                 path_1 = &dev->dcam_cxt.dcam_path[DCAM_PATH1];
3095                 path_2 = &dev->dcam_cxt.dcam_path[DCAM_PATH2];
3096
3097                 DCAM_TRACE("SPRD_IMG: streamoff, is_work: path_0 = %d, path_1 = %d, path_2 = %d, stream_on = %d \n",
3098                         path_0->is_work, path_1->is_work, path_2->is_work, atomic_read(&dev->stream_on));
3099
3100                 if (unlikely(0 == atomic_read(&dev->stream_on))) {
3101                         printk("SPRD_IMG: stream not on\n");
3102                         ret = sprd_img_local_deinit(dev);
3103                         if (unlikely(ret)) {
3104                                 printk(DEBUG_STR,DEBUG_ARGS);
3105                         }
3106                         mutex_unlock(&dev->dcam_mutex);
3107                         goto exit;
3108                 }
3109
3110                 do {
3111                         ret = sprd_stop_timer(&dev->dcam_timer);
3112                         if (unlikely(ret)) {
3113                                 printk(DEBUG_STR,DEBUG_ARGS);
3114                                 break;
3115                         }
3116                         if (dev->got_resizer) {
3117                                 dcam_rel_resizer();
3118                                 dev->got_resizer = 0;
3119                         }
3120
3121                         ret = dcam_stop();
3122                         if (unlikely(ret)) {
3123                                 printk(DEBUG_STR,DEBUG_ARGS);
3124                                 break;
3125                         }
3126
3127                         ret = dcam_stop_cap();
3128                         if (unlikely(ret)) {
3129                                 printk(DEBUG_STR,DEBUG_ARGS);
3130                                 break;
3131                         }
3132
3133                         ret = sprd_img_unreg_isr(dev);
3134                         if (unlikely(ret)) {
3135                                 printk(DEBUG_STR,DEBUG_ARGS);
3136                                 break;
3137                         }
3138
3139                         if (path_1->is_work) {
3140                                 path_1->status = PATH_IDLE;
3141                                 path_1->is_work = 0;
3142                         }
3143
3144                         if (path_2->is_work) {
3145                                 path_2->status = PATH_IDLE;
3146
3147                                 ret = sprd_img_unreg_path2_isr(dev);
3148                                 if (unlikely(ret)) {
3149                                         printk(DEBUG_STR,DEBUG_ARGS);
3150                                         break;
3151                                 }
3152                 
3153                                 path_2->is_work = 0;
3154                         }
3155
3156                         if (path_0->is_work) {
3157                                 path_0->status = PATH_IDLE;
3158                                 path_0->is_work = 0;
3159                         }
3160                         DCAM_TRACE("SPRD_IMG: off, path work %d %d %d \n", path_0->is_work, path_1->is_work, path_2->is_work);
3161                         atomic_set(&dev->stream_on, 0);
3162                 #if 0
3163                         if (DCAM_CAP_IF_CSI2 == dev->dcam_cxt.if_mode) {
3164                                 ret = csi_api_close();
3165                                 if (unlikely(ret)) {
3166                                         printk(DEBUG_STR,DEBUG_ARGS);
3167                                         break;
3168                                 }
3169                         }
3170                 #endif
3171
3172                         ret = dcam_module_deinit(dev->dcam_cxt.if_mode, dev->dcam_cxt.sn_mode);
3173                         if (unlikely(ret)) {
3174                                 printk(DEBUG_STR,DEBUG_ARGS);
3175                                 break;
3176                         }
3177
3178                         ret = sprd_img_local_deinit(dev);
3179                         if (unlikely(ret)) {
3180                                 printk(DEBUG_STR,DEBUG_ARGS);
3181                                 break;
3182                         }
3183                 } while(0);
3184
3185                 mutex_unlock(&dev->dcam_mutex);
3186                 break;
3187         }
3188
3189         case SPRD_IMG_IO_GET_FMT:
3190         {
3191                 struct dcam_format          *fmt;
3192                 struct sprd_img_get_fmt     fmt_desc;
3193
3194                 DCAM_TRACE("SPRD_IMG: SPRD_IMG_IO_GET_FMT \n");
3195                 ret = copy_from_user(&fmt_desc, (struct sprd_img_get_fmt *)arg, sizeof(struct sprd_img_get_fmt));
3196                 if (ret) {
3197                         printk("sprd_img_k_ioctl: fail to get user info \n");
3198                         goto exit;
3199                 }
3200                 if (unlikely(fmt_desc.index >= ARRAY_SIZE(dcam_img_fmt)))
3201                         return -EINVAL;
3202
3203                 fmt = &dcam_img_fmt[fmt_desc.index];
3204                 fmt_desc.fmt = fmt->fourcc;
3205
3206                 ret = copy_to_user((struct sprd_img_get_fmt *)arg, &fmt_desc, sizeof(struct sprd_img_get_fmt));
3207                 break;
3208         }
3209
3210         case SPRD_IMG_IO_GET_CH_ID:
3211         {
3212                 struct dcam_path_spec    *path_0 = NULL;
3213                 struct dcam_path_spec    *path_1 = NULL;
3214                 struct dcam_path_spec    *path_2 = NULL;
3215                 struct dcam_get_path_id  path_id;
3216
3217                 DCAM_TRACE("SPRD_IMG: SPRD_IMG_IO_GET_CH_ID \n");
3218                 path_0 = &dev->dcam_cxt.dcam_path[DCAM_PATH0];
3219                 path_1 = &dev->dcam_cxt.dcam_path[DCAM_PATH1];
3220                 path_2 = &dev->dcam_cxt.dcam_path[DCAM_PATH2];
3221
3222                 memset((void*)&path_id, 0, sizeof(struct dcam_get_path_id));
3223                 path_id.input_size.w = dev->dcam_cxt.cap_in_rect.w;
3224                 path_id.input_size.h = dev->dcam_cxt.cap_in_rect.h;
3225                 path_id.output_size.w = dev->dcam_cxt.dst_size.w;
3226                 path_id.output_size.h = dev->dcam_cxt.dst_size.h;
3227                 path_id.fourcc = dev->dcam_cxt.pxl_fmt;
3228                 path_id.need_isp_tool = dev->dcam_cxt.need_isp_tool;
3229                 path_id.need_isp = dev->dcam_cxt.need_isp;
3230                 path_id.camera_id = dev->dcam_cxt.camera_id;
3231                 path_id.need_shrink = dev->dcam_cxt.need_shrink;
3232                 path_id.input_trim.x = dev->dcam_cxt.path_input_rect.x;
3233                 path_id.input_trim.y = dev->dcam_cxt.path_input_rect.y;
3234                 path_id.input_trim.w = dev->dcam_cxt.path_input_rect.w;
3235                 path_id.input_trim.h = dev->dcam_cxt.path_input_rect.h;
3236                 DCAM_TRACE("SPRD_IMG: get param, path work %d %d %d \n", path_0->is_work, path_1->is_work, path_2->is_work);
3237                 path_id.is_path_work[DCAM_PATH0] = path_0->is_work;
3238                 path_id.is_path_work[DCAM_PATH1] = path_1->is_work;
3239                 path_id.is_path_work[DCAM_PATH2] = path_2->is_work;
3240                 ret = dcam_get_path_id(&path_id, &channel_id);
3241                 ret = copy_to_user((uint32_t *)arg, &channel_id, sizeof(uint32_t));
3242                 sprd_img_local_clear_path_buffer(dev, channel_id);
3243                 DCAM_TRACE("SPRD_IMG: get channel_id %d \n", channel_id);
3244                 break;
3245         }
3246
3247         case SPRD_IMG_IO_GET_TIME:
3248         {
3249                 struct timeval           time;
3250                 struct sprd_img_time     utime;
3251
3252                 DCAM_TRACE("SPRD_IMG: SPRD_IMG_IO_GET_TIME \n");
3253                 img_get_timestamp(&time);
3254                 utime.sec = time.tv_sec;
3255                 utime.usec = time.tv_usec;
3256                 ret = copy_to_user((struct sprd_img_time *)arg, &utime, sizeof(struct sprd_img_time));
3257                 break;
3258         }
3259
3260         case SPRD_IMG_IO_CHECK_FMT:
3261         {
3262                 struct dcam_format       *fmt;
3263                 struct sprd_img_format   img_format;
3264
3265                 DCAM_TRACE("SPRD_IMG: SPRD_IMG_IO_CHECK_FMT \n");
3266                 ret = copy_from_user(&img_format, (struct sprd_img_format *)arg, sizeof(struct sprd_img_format));
3267                 if (ret) {
3268                         printk("sprd_img_k_ioctl: fail to get user info \n");
3269                         goto exit;
3270                 }
3271
3272                 fmt = sprd_img_get_format(img_format.fourcc);
3273                 if (unlikely(!fmt)) {
3274                         printk("SPRD_IMG: Fourcc format (0x%08x) invalid. \n",
3275                                 img_format.fourcc);
3276                         return -EINVAL;
3277                 }
3278
3279                 if (DCAM_PATH1 == img_format.channel_id) {
3280                         mutex_lock(&dev->dcam_mutex);
3281                         ret = sprd_img_check_path1_cap(fmt->fourcc, &img_format, &dev->dcam_cxt);
3282                         mutex_unlock(&dev->dcam_mutex);
3283                         channel_id = DCAM_PATH1;
3284                 } else if (DCAM_PATH2 == img_format.channel_id) {
3285                         if (img_format.is_lightly) {
3286                                 mutex_lock(&dev->dcam_mutex);
3287                                 ret = sprd_img_check_path2_cap(fmt->fourcc, &img_format, &dev->dcam_cxt);
3288                                 mutex_unlock(&dev->dcam_mutex);
3289                         } else {
3290                                 if (unlikely(dcam_get_resizer(DCAM_WAIT_FOREVER))) {
3291                                         /*no wait to get the controller of resizer, failed*/
3292                                         printk("SPRD_IMG: path2 has been occupied by other app \n");
3293                                         return -EIO;
3294                                 }
3295                                 dev->got_resizer = 1;
3296                                 mutex_lock(&dev->dcam_mutex);
3297                                 ret = sprd_img_check_path2_cap(fmt->fourcc, &img_format, &dev->dcam_cxt);
3298                                 mutex_unlock(&dev->dcam_mutex);
3299                                 if (ret) {
3300                                         /*failed to set path2, release the controller of resizer*/
3301                                         dcam_rel_resizer();
3302                                         dev->got_resizer = 0;
3303                                 }
3304                         }
3305                         channel_id = DCAM_PATH2;
3306                 } else if (DCAM_PATH0 == img_format.channel_id) {
3307                         mutex_lock(&dev->dcam_mutex);
3308                         ret = sprd_img_check_path0_cap(fmt->fourcc, &img_format, &dev->dcam_cxt);
3309                         mutex_unlock(&dev->dcam_mutex);
3310                         channel_id = DCAM_PATH0;
3311                 } else {
3312                         printk("SPRD_IMG: Buf type invalid. \n");
3313                         return -EINVAL;
3314                 }
3315
3316                 memcpy((void*)&img_format.reserved[0], (void*)&dev->dcam_cxt.dcam_path[channel_id].end_sel, sizeof(struct dcam_endian_sel));
3317                 if ((0 == ret) && (0 != atomic_read(&dev->stream_on))) {
3318                         if (DCAM_PATH0 == channel_id || DCAM_PATH1 == channel_id || DCAM_PATH2 == channel_id) {
3319                                 ret = sprd_img_update_video(file, channel_id);
3320                         }
3321                 }
3322                 ret = copy_to_user((struct sprd_img_format *)arg, &img_format, sizeof(struct sprd_img_format));
3323                 break;
3324         }
3325
3326         default:
3327                 printk("sprd_img_k_ioctl: invalid cmd %d \n", cmd);
3328                 break;
3329         }
3330
3331
3332 exit:
3333         return ret;
3334 }
3335
3336 LOCAL int sprd_img_check_frame_timestamp(struct dcam_dev* param, struct timeval *tv)
3337 {
3338         int                      ret = DCAM_RTN_SUCCESS;
3339         struct dcam_dev          *dev = (struct dcam_dev*)param;
3340         struct dcam_info         *info = NULL;
3341         struct timeval           timestamp;
3342         uint32_t                 flag = 0;
3343
3344         info = &dev->dcam_cxt;
3345         timestamp.tv_sec = tv->tv_sec;
3346         timestamp.tv_usec = tv->tv_usec;
3347         DCAM_TRACE("SPRD_IMG: check_frame_timestamp, time, %d %d \n",
3348                 (int)timestamp.tv_sec, (int)timestamp.tv_usec);
3349         if ((timestamp.tv_sec == info->frame_last_timestamp.tv_sec)
3350                 && (timestamp.tv_usec - info->frame_last_timestamp.tv_usec >= 1)){
3351                 flag = 0;
3352         } else if (timestamp.tv_sec > info->frame_last_timestamp.tv_sec) {
3353                 flag = 0;
3354         } else {
3355                 flag = 1;
3356         }
3357
3358         if (flag) {
3359                 printk("SPRD_IMG: check_frame_timestamp, %d %d %d %d \n", (int)timestamp.tv_sec, (int)timestamp.tv_usec, 
3360                         (int)info->frame_last_timestamp.tv_sec, (int)info->frame_last_timestamp.tv_usec);
3361                 ret =  DCAM_RTN_PARA_ERR;
3362         }
3363         else {
3364                 info->frame_last_timestamp.tv_sec = timestamp.tv_sec;
3365                 info->frame_last_timestamp.tv_usec = timestamp.tv_usec;
3366         }
3367
3368         return ret;
3369 }
3370
3371 ssize_t sprd_img_read(struct file *file, char __user *u_data, size_t cnt, loff_t *cnt_ret)
3372 {
3373         struct dcam_dev          *dev = file->private_data;
3374         struct dcam_node         node;
3375         struct dcam_path_spec    *path;
3376         struct sprd_img_read_op  read_op;
3377         struct timeval           time;
3378         struct dcam_path_capability path_capability;
3379         int                      fmr_index, i;
3380         int                      ret = 0;
3381
3382         DCAM_TRACE("SPRD_IMG: sprd_img_read %ld, dev %p \n", cnt, dev);
3383
3384         if (!dev)
3385                 return -EFAULT;
3386
3387         if (cnt < sizeof(struct sprd_img_read_op)) {
3388                 printk("sprd_img_read: error, cnt %ld read_op %ld \n", cnt, sizeof(struct sprd_img_read_op));
3389                 return -EIO;
3390         }
3391
3392         ret = copy_from_user(&read_op, (struct sprd_img_read_op *)u_data, sizeof(struct sprd_img_read_op));
3393         if (ret) {
3394                 printk("sprd_img_read: fail to get user info \n");
3395                 return ret;
3396         }
3397
3398         switch (read_op.cmd) {
3399         case SPRD_IMG_GET_SCALE_CAP:
3400                 DCAM_TRACE("SPRD_IMG: get scale capbility \n");
3401                 read_op.parm.reserved[0] = DCAM_PATH2_LINE_BUF_LENGTH;
3402                 read_op.parm.reserved[1] = DCAM_SC_COEFF_UP_MAX;
3403                 read_op.parm.reserved[2] = DCAM_SCALING_THRESHOLD;
3404                 DCAM_TRACE("SPRD_IMG: sprd_img_read line threshold %d, sc factor %d, scaling %d.\n",
3405                         read_op.parm.reserved[0], 
3406                         read_op.parm.reserved[1],
3407                         read_op.parm.reserved[2]);
3408                 break;
3409
3410         case SPRD_IMG_GET_FRM_BUFFER:
3411                 DCAM_TRACE("SPRD_IMG: read frame buffer \n");
3412                 memset(&read_op, 0, sizeof(struct sprd_img_read_op));
3413                 while (1) {
3414                         ret = down_interruptible(&dev->irq_sem);
3415                         if (0 == ret) {
3416                                 break;
3417                         } else if (-EINTR == ret) {
3418                                 read_op.evt = IMG_SYS_BUSY;
3419                                 ret = DCAM_RTN_SUCCESS;
3420                                 goto read_end;
3421                         }else {
3422                                 printk("SPRD_IMG: read frame buffer, failed to down, %d \n", ret);
3423                                 return -EPERM;
3424                         }
3425                 }
3426
3427                 if (sprd_img_queue_read(&dev->queue, &node)) {
3428                         printk("SPRD_IMG: read frame buffer, queue is null \n");
3429                         read_op.evt = IMG_SYS_BUSY;
3430                         ret = DCAM_RTN_SUCCESS;
3431                         goto read_end;
3432                 } else {
3433                         if (node.invalid_flag) {
3434                                 printk("SPRD_IMG: read frame buffer, invalid node\n");
3435                                 read_op.evt = IMG_SYS_BUSY;
3436                                 ret = DCAM_RTN_SUCCESS;
3437                                 goto read_end;
3438                         }
3439                 }
3440
3441                 img_get_timestamp(&time);
3442                 DCAM_TRACE("SPRD_IMG: time, %ld %ld \n", (unsigned long)time.tv_sec, (unsigned long)time.tv_usec);
3443
3444                 read_op.evt = node.irq_flag;
3445                 if (IMG_TX_DONE == read_op.evt  || IMG_CANCELED_BUF == read_op.evt) {
3446                         read_op.parm.frame.channel_id = node.f_type;
3447                         path = &dev->dcam_cxt.dcam_path[read_op.parm.frame.channel_id];
3448                         DCAM_TRACE("SPRD_IMG: node, 0x%x %d %d \n", node, node.index, path->frm_id_base);
3449                         read_op.parm.frame.index = path->frm_id_base;//node.index;
3450                         read_op.parm.frame.height = node.height;
3451                         read_op.parm.frame.length = node.reserved;
3452                         read_op.parm.frame.sec = time.tv_sec;
3453                         read_op.parm.frame.usec = time.tv_usec;
3454                         //fmr_index  = node.index - path->frm_id_base;
3455                         //read_op.parm.frame.real_index = path->index[fmr_index];
3456                         read_op.parm.frame.frm_base_id = path->frm_id_base;
3457                         read_op.parm.frame.img_fmt = path->fourcc;
3458                         read_op.parm.frame.yaddr = node.yaddr;
3459                         read_op.parm.frame.uaddr = node.uaddr;
3460                         read_op.parm.frame.vaddr = node.vaddr;
3461                         read_op.parm.frame.yaddr_vir = node.yaddr_vir;
3462                         read_op.parm.frame.uaddr_vir = node.uaddr_vir;
3463                         read_op.parm.frame.vaddr_vir = node.vaddr_vir;
3464                         DCAM_TRACE("index %d real_index %d frm_id_base %d fmr_index %d \n",
3465                                 read_op.parm.frame.index,
3466                                 read_op.parm.frame.real_index,
3467                                 read_op.parm.frame.frm_base_id,
3468                                 fmr_index);
3469                         if (path != NULL) {
3470                                 DCAM_TRACE("SPRD_IMG: read, %d %d %d \n", node.index, path->frm_id_base, node.index-path->frm_id_base);
3471                                 if (sprd_img_check_frame_timestamp(dev, &time)) {
3472                                         read_op.evt = IMG_CANCELED_BUF;
3473                                         ret = DCAM_RTN_SUCCESS;
3474                                         goto read_end;
3475                                 }
3476                         }
3477                 } else {
3478                         if (IMG_TIMEOUT == read_op.evt ||
3479                                 IMG_TX_ERR == read_op.evt)
3480                                 sprd_img_print_reg();
3481                 }
3482                 DCAM_TRACE("SPRD_IMG: read frame buffer, evt 0x%x channel_id 0x%x index 0x%x \n",
3483                         read_op.evt,
3484                         read_op.parm.frame.channel_id,
3485                         read_op.parm.frame.index);
3486                 break;
3487
3488         case SPRD_IMG_GET_PATH_CAP:
3489                 DCAM_TRACE("SPRD_IMG: get path capbility \n");
3490                 dcam_get_path_capability(&path_capability);
3491                 read_op.parm.capability.count = path_capability.count;
3492                 for (i = 0; i< path_capability.count; i++) {
3493                         read_op.parm.capability.path_info[i].line_buf          = path_capability.path_info[i].line_buf;
3494                         read_op.parm.capability.path_info[i].support_yuv       = path_capability.path_info[i].support_yuv;
3495                         read_op.parm.capability.path_info[i].support_raw       = path_capability.path_info[i].support_raw;
3496                         read_op.parm.capability.path_info[i].support_jpeg      = path_capability.path_info[i].support_jpeg;
3497                         read_op.parm.capability.path_info[i].support_scaling   = path_capability.path_info[i].support_scaling;
3498                         read_op.parm.capability.path_info[i].support_trim       = path_capability.path_info[i].support_trim;
3499                         read_op.parm.capability.path_info[i].is_scaleing_path  = path_capability.path_info[i].is_scaleing_path;
3500                 }
3501                 break;
3502
3503         default:
3504                 printk("SPRD_IMG: sprd_img_read, invalid cmd \n");
3505                 return EINVAL;
3506         }
3507 read_end:
3508         return copy_to_user((struct sprd_img_read_op *)u_data, &read_op, sizeof(struct sprd_img_read_op));
3509 }
3510
3511 ssize_t sprd_img_write(struct file *file, const char __user * u_data, size_t cnt, loff_t *cnt_ret)
3512 {
3513         struct dcam_dev          *dev = file->private_data;
3514         struct dcam_info         *info = &dev->dcam_cxt;
3515         struct dcam_path_spec    *path;
3516         struct sprd_img_write_op write_op;
3517         uint32_t                 index;
3518         int                      ret = 0;
3519
3520         DCAM_TRACE("SPRD_IMG: sprd_img_write %ld, dev %p \n", cnt, dev);
3521
3522         if (!dev)
3523                 return -EFAULT;
3524
3525         if (cnt < sizeof(struct sprd_img_write_op)) {
3526                 printk("sprd_img_write: error, cnt %ld read_op %ld \n", cnt, sizeof(struct sprd_img_write_op));
3527                 return -EIO;
3528         }
3529
3530         ret = copy_from_user(&write_op, (struct sprd_img_write_op *)u_data, sizeof(struct sprd_img_write_op));
3531         if (ret) {
3532                 printk("sprd_img_write: fail to get user info \n");
3533                 return ret;
3534         }
3535
3536         switch (write_op.cmd) {
3537         case SPRD_IMG_STOP_DCAM:
3538                 mutex_lock(&dev->dcam_mutex);
3539                 ret = sprd_img_tx_stop(dev);
3540                 if (ret)
3541                         ret = 0;
3542                 else
3543                         ret = 1;
3544                 mutex_unlock(&dev->dcam_mutex);
3545                 break;
3546
3547         case SPRD_IMG_FREE_FRAME:
3548                 if (0 == atomic_read(&dev->stream_on)) {
3549                         printk("SPRD_IMG: dev close, no need free!");
3550                         break;
3551                 }
3552                 switch (write_op.channel_id) {
3553                 case DCAM_PATH0:
3554                 case DCAM_PATH1:
3555                 case DCAM_PATH2:
3556                         path = &info->dcam_path[write_op.channel_id];
3557                         break;
3558                 default:
3559                         printk("SPRD_IMG: error free frame buffer, channel_id 0x%x \n", write_op.channel_id);
3560                         return -EINVAL;
3561                 }
3562
3563                 if (PATH_IDLE == path->status) {
3564                         DCAM_TRACE("SPRD_IMG: error free frame buffer, wrong status, channel_id 0x%x \n",
3565                                 write_op.channel_id);
3566                         return -EINVAL;
3567                 }
3568
3569                 if (unlikely(write_op.index > path->frm_id_base + path->frm_cnt_act - 1)) {
3570                         printk("SPRD_IMG: error, index %d, frm_id_base %d frm_cnt_act %d \n",
3571                                 write_op.index, path->frm_id_base, path->frm_cnt_act);
3572                         ret = -EINVAL;
3573                 } else if (write_op.index < path->frm_id_base) {
3574                         printk("SPRD_IMG: error, index %d, frm_id_base %d \n",
3575                                 write_op.index, path->frm_id_base);
3576                         ret = -EINVAL;
3577                 } else {
3578                         index = write_op.index - path->frm_id_base;
3579                         if (path->frm_ptr[index]) {
3580                                 dcam_frame_unlock(path->frm_ptr[index]);
3581                         }
3582                         DCAM_TRACE("SPRD_IMG: free frame buffer, channel_id 0x%x, index 0x%x \n",
3583                                 write_op.channel_id, write_op.index);
3584                 }
3585                 break;
3586
3587         default:
3588                 printk("SPRD_IMG: cmd error! \n");
3589                 ret = -EINVAL;
3590                 break;
3591         }
3592
3593         return ret;
3594 }
3595
3596 #if 0
3597 LOCAL int  sprd_img_proc_read(char           *page,
3598                         char           **start,
3599                         off_t          off,
3600                         int            count,
3601                         int            *eof,
3602                         void           *data)
3603 {
3604         int                      len = 0, ret;
3605         struct dcam_dev          *dev = (struct dcam_dev*)data;
3606         uint32_t*                reg_buf;
3607         uint32_t                 reg_buf_len = 0x400;
3608         uint32_t                 print_len = 0, print_cnt = 0;
3609
3610         (void)start; (void)off; (void)count; (void)eof;
3611
3612         len += sprintf(page + len, "Context for DCAM device \n");
3613         len += sprintf(page + len, "*************************************************************** \n");
3614         len += sprintf(page + len, "SPRD_ION_MM_SIZE: 0x%x \n", SPRD_ION_MM_SIZE);
3615         len += sprintf(page + len, "the configuration of CAP \n");
3616         len += sprintf(page + len, " 1. interface mode,       %d \n", dev->dcam_cxt.if_mode);
3617         len += sprintf(page + len, " 2. sensor mode,          %d \n", dev->dcam_cxt.sn_mode);
3618         len += sprintf(page + len, " 3. YUV pattern,          %d \n", dev->dcam_cxt.yuv_ptn);
3619         len += sprintf(page + len, " 4. sync polarities,      v %d h %d p %d href %d \n",
3620                         dev->dcam_cxt.sync_pol.vsync_pol,
3621                         dev->dcam_cxt.sync_pol.hsync_pol,
3622                         dev->dcam_cxt.sync_pol.pclk_pol,
3623                         dev->dcam_cxt.sync_pol.need_href);
3624         len += sprintf(page + len, " 5. Data bit-width,       %d \n", dev->dcam_cxt.data_bits);
3625         len += sprintf(page + len, " 6. need ISP,             %d \n", dev->dcam_cxt.dcam_path[DCAM_PATH1].is_from_isp);
3626         len += sprintf(page + len, "*************************************************************** \n");
3627         len += sprintf(page + len, "the configuration of PATH1 \n");
3628         len += sprintf(page + len, " 1. input rect,           %d %d %d %d \n",
3629                         dev->dcam_cxt.dcam_path[DCAM_PATH1].in_rect.x,
3630                         dev->dcam_cxt.dcam_path[DCAM_PATH1].in_rect.y,
3631                         dev->dcam_cxt.dcam_path[DCAM_PATH1].in_rect.w,
3632                         dev->dcam_cxt.dcam_path[DCAM_PATH1].in_rect.h);
3633         len += sprintf(page + len, " 2. output size,          %d %d \n",
3634                 dev->dcam_cxt.dcam_path[DCAM_PATH1].out_size.w,
3635                 dev->dcam_cxt.dcam_path[DCAM_PATH1].out_size.h);
3636         len += sprintf(page + len, " 3. output format,        %d \n",
3637                 dev->dcam_cxt.dcam_path[DCAM_PATH1].out_fmt);
3638         len += sprintf(page + len, " 4. frame base index,     0x%x \n", dev->dcam_cxt.dcam_path[DCAM_PATH1].frm_id_base);
3639         len += sprintf(page + len, " 5. frame count,          0x%x \n", dev->dcam_cxt.dcam_path[DCAM_PATH1].frm_cnt_act);
3640         len += sprintf(page + len, " 6. frame type,           0x%x \n", dev->dcam_cxt.dcam_path[DCAM_PATH1].frm_type);
3641         for (print_cnt = 0; print_cnt < DCAM_PATH_1_FRM_CNT_MAX; print_cnt ++) {
3642                 len += sprintf(page + len, "%2d. frame buffer%d, 0x%08x 0x%08x 0x%08x \n",
3643                         (6 + print_cnt),
3644                         print_cnt,
3645                         dev->dcam_cxt.dcam_path[DCAM_PATH1].frm_addr[print_cnt].yaddr,
3646                         dev->dcam_cxt.dcam_path[DCAM_PATH1].frm_addr[print_cnt].uaddr,
3647                         dev->dcam_cxt.dcam_path[DCAM_PATH1].frm_addr[print_cnt].vaddr);
3648         }
3649
3650         if (dev->dcam_cxt.dcam_path[DCAM_PATH2].is_work) {
3651         len += sprintf(page + len, "*************************************************************** \n");
3652                 len += sprintf(page + len, "the configuration of PATH2 \n");
3653                 len += sprintf(page + len, " 1. input rect,       %d %d %d %d \n",
3654                                 dev->dcam_cxt.dcam_path[DCAM_PATH2].in_rect.x,
3655                                 dev->dcam_cxt.dcam_path[DCAM_PATH2].in_rect.y,
3656                                 dev->dcam_cxt.dcam_path[DCAM_PATH2].in_rect.w,
3657                                 dev->dcam_cxt.dcam_path[DCAM_PATH2].in_rect.h);
3658                 len += sprintf(page + len, " 2. output size,      %d %d \n",
3659                         dev->dcam_cxt.dcam_path[DCAM_PATH2].out_size.w,
3660                         dev->dcam_cxt.dcam_path[DCAM_PATH2].out_size.h);
3661                 len += sprintf(page + len, " 3. output format,    %d \n",
3662                         dev->dcam_cxt.dcam_path[DCAM_PATH2].out_fmt);
3663                 len += sprintf(page + len, " 4. frame base index, 0x%x \n", dev->dcam_cxt.dcam_path[DCAM_PATH2].frm_id_base);
3664                 len += sprintf(page + len, " 5. frame count,      0x%x \n", dev->dcam_cxt.dcam_path[DCAM_PATH2].frm_cnt_act);
3665                 len += sprintf(page + len, " 6. frame type,       0x%x \n", dev->dcam_cxt.dcam_path[DCAM_PATH2].frm_type);
3666                 for (print_cnt = 0; print_cnt < DCAM_PATH_2_FRM_CNT_MAX; print_cnt ++) {
3667                         len += sprintf(page + len, "%2d. frame buffer%d, 0x%8x 0x%8x 0x%8x \n",
3668                                 (6 + print_cnt),
3669                                 print_cnt,
3670                                 dev->dcam_cxt.dcam_path[DCAM_PATH2].frm_addr[print_cnt].yaddr,
3671                                 dev->dcam_cxt.dcam_path[DCAM_PATH2].frm_addr[print_cnt].uaddr,
3672                                 dev->dcam_cxt.dcam_path[DCAM_PATH2].frm_addr[print_cnt].vaddr);
3673                 }
3674
3675         }
3676
3677         reg_buf = (uint32_t*)vzalloc(reg_buf_len);
3678         ret = dcam_read_registers(reg_buf, &reg_buf_len);
3679         if (ret) {
3680                 vfree(reg_buf);
3681                 return len;
3682         }
3683
3684         len += sprintf(page + len, "*************************************************************** \n");
3685         len += sprintf(page + len, "dcam registers \n");
3686         print_cnt = 0;
3687         while (print_len < reg_buf_len) {
3688                 len += sprintf(page + len, "offset 0x%03x: 0x%08x, 0x%08x, 0x%08x, 0x%08x \n",
3689                         print_len,
3690                         reg_buf[print_cnt],
3691                         reg_buf[print_cnt+1],
3692                         reg_buf[print_cnt+2],
3693                         reg_buf[print_cnt+3]);
3694                 print_cnt += 4;
3695                 print_len += 16;
3696         }
3697
3698         ret = csi_read_registers(reg_buf, &reg_buf_len);
3699         if (ret) {
3700                 vfree(reg_buf);
3701                 return len;
3702         }
3703
3704         len += sprintf(page + len, "*************************************************************** \n");
3705         len += sprintf(page + len, "csi host registers \n");
3706         print_cnt = 0;
3707         print_len = 0;
3708         while (print_len < reg_buf_len) {
3709                 len += sprintf(page + len, "offset 0x%03x: 0x%08x, 0x%08x, 0x%08x, 0x%08x \n",
3710                         print_len,
3711                         reg_buf[print_cnt],
3712                         reg_buf[print_cnt+1],
3713                         reg_buf[print_cnt+2],
3714                         reg_buf[print_cnt+3]);
3715                 print_cnt += 4;
3716                 print_len += 16;
3717         }
3718         len += sprintf(page + len, "*************************************************************** \n");
3719         len += sprintf(page + len, "The end of DCAM device \n");
3720         msleep(10);
3721         vfree(reg_buf);
3722
3723         return len;
3724 }
3725 #endif
3726
3727 static struct file_operations image_fops = {
3728         .owner          = THIS_MODULE,
3729         .open           = sprd_img_k_open,
3730         .unlocked_ioctl = sprd_img_k_ioctl,
3731 #ifdef CONFIG_COMPAT
3732         .compat_ioctl   = sprd_img_k_ioctl,
3733 #endif
3734         .release        = sprd_img_k_release,
3735         .read           = sprd_img_read,
3736         .write          = sprd_img_write,
3737 };
3738
3739 static struct miscdevice image_dev = {
3740         .minor = IMAGE_MINOR,
3741         .name = IMG_DEVICE_NAME,
3742         .fops = &image_fops,
3743 };
3744
3745
3746 int sprd_img_probe(struct platform_device *pdev)
3747 {
3748         int ret = 0;
3749
3750         DCAM_TRACE(KERN_ALERT "sprd_img_probe called\n");
3751
3752         ret = misc_register(&image_dev);
3753         if (ret) {
3754                 printk(KERN_ERR "cannot register miscdev on minor=%d (%d)\n",
3755                         IMAGE_MINOR, ret);
3756                 ret = -EACCES;
3757                 goto exit;
3758         }
3759         image_dev.this_device->of_node = pdev->dev.of_node;
3760         parse_baseaddress(pdev->dev.of_node);
3761
3762         printk(KERN_ALERT "sprd_img_probe Success\n");
3763         goto exit;
3764
3765 exit:
3766         return ret;
3767 }
3768
3769 static int sprd_img_remove(struct platform_device *pdev)
3770 {
3771         misc_deregister(&image_dev);
3772         return 0;
3773 }
3774
3775 static void sprd_img_shutdown(struct platform_device *pdev)
3776 {
3777         sprd_flash_close();
3778 }
3779
3780 LOCAL const struct of_device_id  of_match_table_dcam[] = {
3781         { .compatible = "sprd,sprd_dcam", },
3782         { },
3783 };
3784 LOCAL struct platform_driver sprd_img_driver = {
3785         .probe = sprd_img_probe,
3786         .remove = sprd_img_remove,
3787         .shutdown = sprd_img_shutdown,
3788         .driver = {
3789                    .owner = THIS_MODULE,
3790                    .name = IMG_DEVICE_NAME,
3791                    .of_match_table = of_match_ptr(of_match_table_dcam),
3792                    },
3793 };
3794
3795 int __init sprd_img_k_init(void)
3796 {
3797         if (platform_driver_register(&sprd_img_driver) != 0) {
3798                 printk("platform device register Failed \n");
3799                 return -1;
3800         }
3801
3802         if (dcam_scale_coeff_alloc()) {
3803                 printk("dcam_scale_coeff_alloc Failed \n");
3804                 return -1;
3805         }
3806
3807         printk(KERN_INFO "Video Technology Magazine Virtual Video "
3808                "Capture Board ver %u.%u.%u successfully loaded.\n",
3809                (DCAM_VERSION >> 16) & 0xFF, (DCAM_VERSION >> 8) & 0xFF,
3810                DCAM_VERSION & 0xFF);
3811         return 0;
3812 }
3813
3814 void sprd_img_k_exit(void)
3815 {
3816         dcam_scale_coeff_free();
3817         platform_driver_unregister(&sprd_img_driver);
3818 }
3819
3820 module_init(sprd_img_k_init);
3821 module_exit(sprd_img_k_exit);
3822 MODULE_DESCRIPTION("DCAM Driver");
3823 MODULE_AUTHOR("Multimedia_Camera@Spreadtrum");
3824 MODULE_LICENSE("GPL");
3825