Merge tag 'lsk-android-14.03' into develop-3.10
[firefly-linux-kernel-4.4.55.git] / drivers / media / video / rk_camsys / camsys_drv.c
1 #include <media/camsys_head.h>
2
3 #include "camsys_cif.h"
4 #include "camsys_marvin.h"
5 #include "camsys_mipicsi_phy.h"
6 #include "camsys_gpio.h"
7
8 unsigned int camsys_debug=1;
9 module_param(camsys_debug, int, S_IRUGO|S_IWUSR);
10
11 static int drv_version = CAMSYS_DRIVER_VERSION;
12 module_param(drv_version, int, S_IRUGO);
13 static int head_version = CAMSYS_HEAD_VERSION;
14 module_param(head_version, int, S_IRUGO);
15
16
17 typedef struct camsys_devs_s {
18     spinlock_t lock;
19     struct list_head devs;
20 } camsys_devs_t;
21
22 static camsys_devs_t camsys_devs;
23
24 static int camsys_i2c_write(camsys_i2c_info_t *i2cinfo, camsys_dev_t *camsys_dev)
25 {
26     int err = 0,i,j;
27     unsigned char buf[8],*bufp;
28     unsigned short msg_times,totallen,onelen;
29     struct i2c_msg msg[1];
30     struct i2c_adapter *adapter;
31     camsys_extdev_t *extdev;
32     
33     adapter = i2c_get_adapter(i2cinfo->bus_num);
34     if (adapter == NULL) {
35         camsys_err("Get %d i2c adapter is failed!",i2cinfo->bus_num);
36         err = -EINVAL;
37         goto end;
38     }
39     
40     if (i2cinfo->i2cbuf_directly) {
41         if (camsys_dev->devmems.i2cmem == NULL) {
42             camsys_err("%s has not i2c mem, it isn't support i2c buf write!",dev_name(camsys_dev->miscdev.this_device));
43             err = -EINVAL;
44             goto end;
45         }
46         totallen = (i2cinfo->i2cbuf_bytes&0xffff);
47         onelen = (i2cinfo->i2cbuf_bytes&0xffff0000)>>16;
48         msg_times = totallen/onelen;
49         if (totallen > camsys_dev->devmems.i2cmem->size) {
50             camsys_err("Want to write 0x%x bytes, i2c memory(size: 0x%x) is overlap",totallen,camsys_dev->devmems.i2cmem->size);
51             err = -EINVAL;
52             goto end;
53         }
54         bufp = (unsigned char*)camsys_dev->devmems.i2cmem->vir_base;        
55     } else {
56         for (i=0; i<i2cinfo->reg_size; i++) {
57             buf[i] = (i2cinfo->reg_addr>>((i2cinfo->reg_size-1-i)*8))&0xff;
58         }
59         for (j=0; j<i2cinfo->val_size; j++) {
60             buf[i+j] = (i2cinfo->val>>(i2cinfo->val_size-1-j))&0xff;
61         }
62         bufp = buf;
63         onelen = i2cinfo->val_size + i2cinfo->reg_size;
64         msg_times = 1;
65     }
66     
67         err = -EAGAIN;    
68     msg->addr = (i2cinfo->slave_addr>>1);
69     msg->flags = 0;
70     msg->scl_rate = i2cinfo->speed;
71    // msg->read_type = 0; 
72     msg->len = onelen;
73     for (i=0; i<msg_times; i++) {        
74         msg->buf = bufp+i*onelen;        
75                 err = i2c_transfer(adapter, msg, 1);            
76                 if (err < 0) {
77             camsys_err("i2c write dev(addr:0x%x) failed!",i2cinfo->slave_addr);
78                         udelay(10);
79                 }
80     }
81
82 end:
83 #if 0
84     #if ((defined CONFIG_ARCH_RK319X) || (CONFIG_ARCH_ROCKCHIP))
85     if (!list_empty(&camsys_dev->extdevs.active)) {
86         list_for_each_entry(extdev, &camsys_dev->extdevs.active, active) {
87             if (extdev->phy.type == CamSys_Phy_Cif) {
88                 if (extdev->phy.info.cif.fmt >= CamSys_Fmt_Raw_10b) {
89                     //iomux_set(CIF0_D0); // ZYC FOR 32
90                     //iomux_set(CIF0_D1); // ZYC FOR 32
91                 }
92             }
93         }
94     }
95     #endif
96 #endif
97     return err;
98 }
99
100 static int camsys_i2c_read(camsys_i2c_info_t *i2cinfo, camsys_dev_t *camsys_dev)
101 {
102     int err = 0,i,retry=2,tmp;
103     unsigned char buf[8];
104     struct i2c_msg msg[2];
105     struct i2c_adapter *adapter;
106     camsys_extdev_t *extdev;
107     
108     adapter = i2c_get_adapter(i2cinfo->bus_num);
109     if (adapter == NULL) {
110         camsys_err("Get %d i2c adapter is failed!",i2cinfo->bus_num);
111         err = -EINVAL;
112         goto end;
113     }
114     
115     for (i=0; i<i2cinfo->reg_size; i++) {
116         buf[i] = (i2cinfo->reg_addr>>((i2cinfo->reg_size-1-i)*8))&0xff;
117     }
118
119     msg[0].addr = (i2cinfo->slave_addr>>1);
120         msg[0].flags = 0;
121         msg[0].scl_rate = i2cinfo->speed;
122         //msg[0].read_type = 0;
123     msg[0].buf = buf;
124     msg[0].len = i2cinfo->reg_size;
125     
126     msg[1].addr = (i2cinfo->slave_addr>>1);
127         msg[1].flags = I2C_M_RD;
128         msg[1].scl_rate = i2cinfo->speed;
129 //      msg[1].read_type = 0;
130     msg[1].buf = buf;
131     msg[1].len = (unsigned short)i2cinfo->val_size;
132         err = -EAGAIN;    
133
134         while ((retry-- > 0) && (err < 0)) {                                             /* ddl@rock-chips.com :  Transfer again if transent is failed   */
135                 err = i2c_transfer(adapter, msg, 2);
136         
137                 if (err >= 0) {
138             err = 0;
139                 } else {
140                         camsys_err("i2c read dev(addr:0x%x) failed,try again-%d!",i2cinfo->slave_addr,retry);
141                         udelay(10);
142                 }
143         }
144
145     if (err==0) {        
146         i2cinfo->val = 0x00;
147         for(i=0; i<i2cinfo->val_size; i++) {
148             tmp = buf[i];
149             i2cinfo->val |= (tmp<<((i2cinfo->val_size-1-i)*8));
150         }
151     }
152     
153 end:
154 #if 0
155     #if ((defined CONFIG_ARCH_RK319X) || (CONFIG_ARCH_ROCKCHIP))
156     if (!list_empty(&camsys_dev->extdevs.active)) {
157         list_for_each_entry(extdev, &camsys_dev->extdevs.active, active) {
158             if (extdev->phy.type == CamSys_Phy_Cif) {
159                 if (extdev->phy.info.cif.fmt >= CamSys_Fmt_Raw_10b) {
160                     //iomux_set(CIF0_D0);//ZYC FOR 32
161                     //iomux_set(CIF0_D1);//ZYC FOR 32
162                 }
163             }
164         }
165     }
166     #endif
167 #endif 
168     return err;
169 }
170
171
172 static int camsys_extdev_register(camsys_devio_name_t *devio, camsys_dev_t *camsys_dev)
173 {
174     int err = 0,i;
175     camsys_extdev_t *extdev;
176     camsys_regulator_info_t *regulator_info;
177     camsys_regulator_t *regulator;
178     camsys_gpio_info_t *gpio_info;
179     camsys_gpio_t *gpio;
180     
181     if ((devio->dev_id & CAMSYS_DEVID_EXTERNAL) == 0) {
182         err = -EINVAL;
183         camsys_err("dev_id: 0x%x is not support for camsys!",devio->dev_id);
184         goto end;
185     }
186
187 #if 0
188     if (devio->phy.type == CamSys_Phy_Mipi) {
189         if (camsys_find_devmem(CAMSYS_REGISTER_MIPIPHY_RES_NAME, camsys_dev) == NULL) {
190             camsys_err("dev_id: 0x%x is connect to MIPI CSI, but %s isn't support",devio->dev_id,
191                 dev_name(camsys_dev->miscdev.this_device));
192
193             err = -EINVAL;
194             goto end;
195         }
196     }
197 #endif    
198
199     extdev = camsys_find_extdev(devio->dev_id, camsys_dev);
200     if (extdev != NULL) {
201         err = 0;
202         camsys_warn("Extdev(dev_id: 0x%x) has been registered in %s!",
203             devio->dev_id, dev_name(camsys_dev->miscdev.this_device));
204         goto end;
205     }
206
207     extdev = kzalloc(sizeof(camsys_extdev_t),GFP_KERNEL);
208     if (extdev == NULL) {
209         camsys_err("alloc camsys_extdev_t failed!");
210         err = -ENOMEM;
211         goto end;
212     }
213
214     regulator_info = &devio->avdd;
215     regulator = &extdev->avdd;
216     for (i=0; i<4; i++) {
217         if (strcmp(regulator_info->name,"NC")) {
218             regulator->ldo = regulator_get(NULL,regulator_info->name);
219             if (IS_ERR(regulator->ldo)) {
220                 camsys_err("Get %s regulator for dev_id 0x%x failed!",regulator_info->name,devio->dev_id);
221                 err = -EINVAL;
222                 goto fail;
223             }
224             
225             regulator->min_uv = regulator_info->min_uv;
226             regulator->max_uv = regulator_info->max_uv;
227             camsys_trace(1,"Get %s regulator(min: %duv  max: %duv) for dev_id 0x%x success",
228                         regulator_info->name,regulator->min_uv,regulator->max_uv,
229                         devio->dev_id);
230         } else {
231             regulator->ldo = NULL;
232             regulator->min_uv = 0;
233             regulator->max_uv = 0;
234         }
235
236         regulator++;
237         regulator_info++;
238     }
239
240     gpio_info = &devio->pwrdn;
241     gpio = &extdev->pwrdn;
242     for (i=0; i<5; i++) {
243         if (strcmp(gpio_info->name,"NC")) {
244             gpio->io = camsys_gpio_get(gpio_info->name);
245             if (gpio->io < 0) {
246                 camsys_err("Get %s gpio for dev_id 0x%x failed!",gpio_info->name,devio->dev_id);
247                 err = -EINVAL;
248                 goto fail;
249             }
250             if (gpio_request(gpio->io,"camsys_gpio")<0) {
251                 camsys_err("Request %s(%d) failed",gpio_info->name,gpio->io);
252             }
253             gpio->active = gpio_info->active;
254             camsys_trace(1,"Get %s(%d) gpio(active: %d) for dev_id 0x%x success!",
255                         gpio_info->name,gpio->io,gpio->active,devio->dev_id);
256         } else {
257             gpio->io = 0xffffffff;
258             gpio->active = 0xffffffff;
259         }
260
261         gpio++;
262         gpio_info++;
263     }
264
265     extdev->pdev = camsys_dev->pdev;
266     extdev->phy = devio->phy;
267     extdev->clk = devio->clk;
268     extdev->dev_id = devio->dev_id;
269     //spin_lock(&camsys_dev->lock);
270     mutex_lock(&camsys_dev->extdevs.mut);
271     list_add_tail(&extdev->list, &camsys_dev->extdevs.list);
272     //spin_unlock(&camsys_dev->lock);
273     mutex_unlock(&camsys_dev->extdevs.mut);
274
275     camsys_dev->iomux(extdev, (void*)camsys_dev);
276
277     camsys_trace(1,"Extdev(dev_id: 0x%x) register success",extdev->dev_id);
278
279     return 0;
280 fail:
281     if (extdev) { 
282         kfree(extdev);
283         extdev = NULL;
284     }
285 end:
286     
287     return err;
288 }
289
290 static int camsys_extdev_deregister(unsigned int dev_id, camsys_dev_t *camsys_dev, bool all)
291 {
292     int err = 0,i;
293     camsys_extdev_t *extdev;
294     camsys_regulator_t *regulator;
295     camsys_gpio_t *gpio;
296
297     if (all == false) {
298         if ((dev_id & CAMSYS_DEVID_EXTERNAL) == 0) {
299             err = -EINVAL;
300             camsys_err("dev_id: 0x%x is not support for %s!",dev_id, dev_name(camsys_dev->miscdev.this_device));
301             goto end;
302         }
303
304         extdev = camsys_find_extdev(dev_id, camsys_dev);
305         if (extdev != NULL) {
306             err = -EINVAL;
307             camsys_warn("Extdev(dev_id: 0x%x) isn't registered in %s!",
308                 dev_id, dev_name(camsys_dev->miscdev.this_device));
309             goto end;
310         }
311
312         regulator = &extdev->avdd;
313         for (i=0; i<4; i++) {
314             if (!IS_ERR_OR_NULL(regulator->ldo)) {
315                 while(regulator_is_enabled(regulator->ldo)>0)   
316                             regulator_disable(regulator->ldo);
317                         regulator_put(regulator->ldo);
318             }
319             regulator++;
320         }
321
322         gpio = &extdev->pwrdn;
323         for (i=0; i<5; i++) {
324             if (gpio->io!=0xffffffff) {                    
325                 gpio_free(gpio->io);
326             }
327             gpio++;
328         }
329
330         //spin_lock(&camsys_dev->lock);
331         mutex_lock(&camsys_dev->extdevs.mut);
332         list_del_init(&extdev->list);
333         list_del_init(&extdev->active);
334         //spin_unlock(&camsys_dev->lock);
335         mutex_unlock(&camsys_dev->extdevs.mut);
336         kfree(extdev);
337         extdev = NULL;
338         camsys_trace(1,"Extdev(dev_id: 0x%x) is deregister success", extdev->dev_id);
339     } else {
340         //spin_lock(&camsys_dev->lock);
341         mutex_lock(&camsys_dev->extdevs.mut);
342         while (!list_empty(&camsys_dev->extdevs.list)) {
343
344             extdev = list_first_entry(&camsys_dev->extdevs.list, camsys_extdev_t, list);
345             if (extdev) {
346                 regulator = &extdev->avdd;
347                 for (i=0; i<4; i++) {
348                     if (!IS_ERR(regulator->ldo)) {
349                         while(regulator_is_enabled(regulator->ldo)>0)   
350                                     regulator_disable(regulator->ldo);
351                                 regulator_put(regulator->ldo);
352                     }
353                     regulator++; 
354                 }
355
356                 gpio = &extdev->pwrdn;
357                 for (i=0; i<5; i++) {
358                     if (gpio->io!=0xffffffff) {                    
359                         gpio_free(gpio->io);
360                     }
361                     gpio++;
362                 }
363                 camsys_trace(1,"Extdev(dev_id: 0x%x) is deregister success", extdev->dev_id);
364                 list_del_init(&extdev->list);
365                 list_del_init(&extdev->active);
366                 kfree(extdev);
367                 extdev=NULL;
368             }
369         }
370         //spin_unlock(&camsys_dev->lock);        
371         mutex_unlock(&camsys_dev->extdevs.mut);
372         camsys_trace(1, "All extdev is deregister success!");
373     }
374     
375
376 end:    
377     return err;
378
379 }
380
381 static int camsys_sysctl(camsys_sysctrl_t *devctl, camsys_dev_t *camsys_dev)
382 {
383     int i;
384     int err = 0;    
385     camsys_extdev_t *extdev,*extdev2;
386
387     //spin_lock(&camsys_dev->lock);
388     mutex_lock(&camsys_dev->extdevs.mut);
389         if(devctl->ops == 0xaa){
390                 dump_stack();
391                 return 0;
392         }
393     //Internal 
394     if (camsys_dev->dev_id & devctl->dev_mask) {
395         switch (devctl->ops)
396         {
397             case CamSys_ClkIn:
398             {
399                 camsys_dev->clkin_cb(camsys_dev,devctl->on);
400                 break;
401             }
402
403             case CamSys_Rst:
404             {
405                 camsys_dev->reset_cb(camsys_dev);
406                 break;
407             }
408             #if 0
409             //for mipi
410             case CamSys_Gpio_Tag:
411             {
412                 if((camsys_dev->mipiphy.ops )){
413                     camsys_dev->mipiphy.ops(NULL,NULL,devctl->on);
414                 }
415             }
416             #endif
417             default:
418                 break;
419
420         }
421     }
422
423     //External
424     for (i=0; i<8; i++) {
425         if (devctl->dev_mask & (1<<(i+24))) {
426             extdev = camsys_find_extdev((1<<(i+24)), camsys_dev);
427             if (extdev) {
428                 camsys_sysctl_extdev(extdev, devctl, camsys_dev);
429
430                 if (devctl->ops == CamSys_ClkIn) {
431                     if (devctl->on) {
432                         list_add_tail(&extdev->active,&camsys_dev->extdevs.active);
433                     } else {
434                         if (!list_empty(&camsys_dev->extdevs.active)) {    /* ddla@rock-chips.com: v0.0.7 */
435                             list_for_each_entry(extdev2, &camsys_dev->extdevs.active, active) {
436                                 if (extdev2 == extdev) {
437                                     list_del_init(&extdev->active);
438                                     break;
439                                 }
440                             }
441                         }
442                     }
443                 }
444                 
445             } else {
446                 camsys_err("Can not find dev_id 0x%x device in %s!", (1<<(i+24)), dev_name(camsys_dev->miscdev.this_device));
447             }
448         }
449     }
450
451     //spin_unlock(&camsys_dev->lock);
452     mutex_unlock(&camsys_dev->extdevs.mut);
453     return err;
454 }
455 static int camsys_phy_ops (camsys_extdev_phy_t *phy, void* ptr, unsigned int on)
456 {
457     camsys_dev_t *camsys_dev = (camsys_dev_t*)ptr;
458     int err = 0;
459     
460     if (phy->type == CamSys_Phy_Mipi) {        
461         if (camsys_dev->mipiphy.ops && camsys_dev->mipiphy.clkin_cb) {
462             err =  camsys_dev->mipiphy.clkin_cb(camsys_dev,on);
463             err =  camsys_dev->mipiphy.ops(&phy->info.mipi,&camsys_dev->mipiphy, on);
464         } else {
465             camsys_err("%s isn't support mipi phy",dev_name(camsys_dev->miscdev.this_device));
466             err = -EINVAL;
467         }
468     } else if (phy->type == CamSys_Phy_Cif) {
469         if (camsys_dev->cifphy.ops && camsys_dev->cifphy.clkin_cb) {
470             err =  camsys_dev->cifphy.clkin_cb(camsys_dev,on);
471             err =  camsys_dev->cifphy.ops(&phy->info.cif,&camsys_dev->cifphy, on);
472         } else {
473             //camsys_err("%s isn't support cif phy",dev_name(camsys_dev->miscdev.this_device));
474             //err = -EINVAL;
475         }
476     }
477
478     return err;
479 }
480 static int camsys_irq_connect(camsys_irqcnnt_t *irqcnnt, camsys_dev_t *camsys_dev)
481 {
482     int err = 0,i;
483     camsys_irqpool_t *irqpool; 
484     unsigned long int flags;
485
486     if ((irqcnnt->mis != MRV_ISP_MIS) &&
487         (irqcnnt->mis != MRV_MIPI_MIS) &&
488         (irqcnnt->mis != MRV_MI_MIS)) {
489
490         camsys_err("this thread(pid: %d) irqcnnt->mis(0x%x) is invalidate, irq connect failed!",
491             irqcnnt->pid, irqcnnt->mis);
492
493         err = -EINVAL;
494         goto end;
495     }
496 #if 0
497     //zyc for test mipi
498     if((camsys_dev->mipiphy.ops ) && (irqcnnt->mis == MRV_ISP_MIS)){
499         camsys_dev->mipiphy.ops(NULL,NULL,0);
500     }
501 #endif    
502
503     spin_lock_irqsave(&camsys_dev->irq.lock,flags);
504     if (!list_empty(&camsys_dev->irq.irq_pool)) {
505         list_for_each_entry(irqpool, &camsys_dev->irq.irq_pool, list) {
506             if (irqpool->pid == irqcnnt->pid) {
507                 camsys_warn("this thread(pid: %d) had been connect irq!",current->pid);
508                 spin_unlock(&camsys_dev->irq.lock);
509                 goto end;
510             }
511         }
512     }
513     spin_unlock_irqrestore(&camsys_dev->irq.lock,flags);
514     
515     irqpool = kzalloc(sizeof(camsys_irqpool_t),GFP_KERNEL);
516     if (irqpool) {
517         spin_lock_init(&irqpool->lock);
518         irqpool->pid = irqcnnt->pid;
519         irqpool->timeout = irqcnnt->timeout;
520         irqpool->mis = irqcnnt->mis;
521         irqpool->icr = irqcnnt->icr;
522         INIT_LIST_HEAD(&irqpool->active);
523         INIT_LIST_HEAD(&irqpool->deactive);
524         init_waitqueue_head(&irqpool->done);
525         for (i=0; i<CAMSYS_IRQPOOL_NUM; i++) {
526             list_add_tail(&irqpool->pool[i].list, &irqpool->deactive);
527         }
528     }
529     
530     spin_lock_irqsave(&camsys_dev->irq.lock,flags);
531     //camsys_dev->irq.timeout = irqcnnt->timeout;
532     list_add_tail(&irqpool->list, &camsys_dev->irq.irq_pool);
533     spin_unlock_irqrestore(&camsys_dev->irq.lock,flags);
534     camsys_trace(1, "Thread(pid: %d) connect %s irq success! mis: 0x%x icr: 0x%x ", irqpool->pid, dev_name(camsys_dev->miscdev.this_device),
535         irqpool->mis,irqpool->icr);
536
537 end:
538     return err;
539 }
540 static int active_list_isnot_empty(camsys_irqpool_t *irqpool)
541 {
542     int err;
543     unsigned long int flags;
544     
545     spin_lock_irqsave(&irqpool->lock,flags);
546     err = list_empty(&irqpool->active);
547     spin_unlock_irqrestore(&irqpool->lock,flags);
548
549     return !err;
550     
551 }
552 static int camsys_irq_wait(camsys_irqsta_t *irqsta, camsys_dev_t *camsys_dev)
553 {
554     int err = 0;
555     bool find_pool = false;
556     camsys_irqstas_t *irqstas;
557     camsys_irqpool_t *irqpool;
558     unsigned long int flags;
559     
560     spin_lock_irqsave(&camsys_dev->irq.lock,flags);
561     if (!list_empty(&camsys_dev->irq.irq_pool)) {
562         list_for_each_entry(irqpool, &camsys_dev->irq.irq_pool, list) {
563             if (irqpool->pid == current->pid) {
564                 find_pool = true;
565                 break;
566             }
567         }
568     }
569     spin_unlock_irqrestore(&camsys_dev->irq.lock,flags);
570
571     if (find_pool == false) {
572         camsys_err("this thread(pid: %d) hasn't been connect irq, so wait irq failed!",current->pid);
573         err = -EINVAL;
574         goto end;
575     }
576     
577     
578     spin_lock_irqsave(&irqpool->lock,flags);
579     if (!list_empty(&irqpool->active)) {
580         irqstas = list_first_entry(&irqpool->active, camsys_irqstas_t, list);
581         *irqsta = irqstas->sta;
582         list_del_init(&irqstas->list);
583         list_add_tail(&irqstas->list,&irqpool->deactive);
584         spin_unlock_irqrestore(&irqpool->lock,flags);
585     } else {
586         spin_unlock_irqrestore(&irqpool->lock,flags);
587         
588         wait_event_interruptible_timeout(irqpool->done,
589             active_list_isnot_empty(irqpool),
590             usecs_to_jiffies(irqpool->timeout));
591
592         if (irqpool->pid == current->pid) {
593             if (active_list_isnot_empty(irqpool)) {
594                 spin_lock_irqsave(&irqpool->lock,flags);
595                 irqstas = list_first_entry(&irqpool->active, camsys_irqstas_t, list);
596                 *irqsta = irqstas->sta;
597                 list_del_init(&irqstas->list);
598                 list_add_tail(&irqstas->list,&irqpool->deactive);
599                 spin_unlock_irqrestore(&irqpool->lock,flags);
600             } else {
601            //     camsys_warn("Thread(pid: %d) wait irq timeout!!",current->pid);
602                 err = -EAGAIN;
603             }
604         } else {
605             camsys_warn("Thread(pid: %d) has been disconnect!",current->pid);
606             err = -EAGAIN;
607         }
608     }
609
610     if (err == 0) {
611         camsys_trace(3,"Thread(pid: %d) has been wake up for irq(mis: 0x%x ris:0x%x)!",
612                      current->pid, irqsta->mis, irqsta->ris);
613     }
614
615 end:
616     return err;
617 }
618
619 static int camsys_irq_disconnect(camsys_irqcnnt_t *irqcnnt, camsys_dev_t *camsys_dev, bool all)
620 {
621     int err = 0;
622     bool find_pool = false;
623     camsys_irqpool_t *irqpool;    
624     unsigned long int flags;
625     
626     if (all == false) {
627         spin_lock_irqsave(&camsys_dev->irq.lock,flags);
628                 if (!list_empty(&camsys_dev->irq.irq_pool)) {
629             list_for_each_entry(irqpool, &camsys_dev->irq.irq_pool, list) {
630                 if (irqpool->pid == irqcnnt->pid) {
631                     find_pool = true;
632                     irqpool->pid = 0;
633                     break;
634                 }
635             }
636         }
637         spin_unlock_irqrestore(&camsys_dev->irq.lock,flags);
638
639         if (find_pool == false) {
640             camsys_err("this thread(pid: %d) have not been connect irq!, disconnect failed",current->pid);         
641         } else {
642             wake_up_all(&irqpool->done);
643         }
644
645         camsys_trace(1, "Thread(pid: %d) disconnect %s irq success!", irqcnnt->pid, dev_name(camsys_dev->miscdev.this_device));
646    } else {
647         spin_lock_irqsave(&camsys_dev->irq.lock,flags);
648         while (!list_empty(&camsys_dev->irq.irq_pool)) {
649             irqpool = list_first_entry(&camsys_dev->irq.irq_pool, camsys_irqpool_t, list);
650             list_del_init(&irqpool->list);
651             irqpool->pid = 0;
652             wake_up_all(&irqpool->done);
653             kfree(irqpool);
654             irqpool = NULL;
655         }
656         spin_unlock_irqrestore(&camsys_dev->irq.lock,flags);
657
658         camsys_trace(1, "All thread disconnect %s irq success!", dev_name(camsys_dev->miscdev.this_device));
659    }
660
661
662     return err;
663 }
664
665 static int camsys_querymem (camsys_dev_t *camsys_dev,  camsys_querymem_t *qmem)
666 {
667     int err = 0;
668     
669     if (qmem->mem_type == CamSys_Mmap_RegisterMem) {
670         if (camsys_dev->devmems.registermem == NULL) {
671             camsys_err("%s register memory isn't been register!", dev_name(camsys_dev->miscdev.this_device));
672             err = -EINVAL;
673             goto end;
674         }
675
676         qmem->mem_size = camsys_dev->devmems.registermem->size;
677         qmem->mem_offset = CamSys_Mmap_RegisterMem*PAGE_SIZE;
678     } else if (qmem->mem_type == CamSys_Mmap_I2cMem) {
679         if (camsys_dev->devmems.i2cmem== NULL) {
680             camsys_err("%s i2c memory isn't been register!", dev_name(camsys_dev->miscdev.this_device));
681             err = -EINVAL;
682             goto end;
683         }
684
685         qmem->mem_size = camsys_dev->devmems.i2cmem->size;
686         qmem->mem_offset = CamSys_Mmap_I2cMem*PAGE_SIZE;
687     } else {
688         camsys_err("%d memory type have not in %s memory list",qmem->mem_type,dev_name(camsys_dev->miscdev.this_device));
689         err = -EINVAL;
690         goto end;
691     }
692     
693
694     return 0;
695 end: 
696     return err;
697 }
698 static int camsys_open(struct inode *inode, struct file *file)
699 {
700     int err = 0;
701     int minor = iminor(inode);
702     camsys_dev_t *camsys_dev;
703
704     spin_lock(&camsys_devs.lock);
705     list_for_each_entry(camsys_dev, &camsys_devs.devs, list) {
706         if (camsys_dev->miscdev.minor == minor) {
707             file->private_data = (void*)(camsys_dev);
708             break;
709         }
710     }
711     spin_unlock(&camsys_devs.lock);
712
713     //zyc add
714     INIT_LIST_HEAD(&camsys_dev->extdevs.active);
715
716     
717     if (file->private_data == NULL) {
718         camsys_err("Cann't find camsys_dev!");
719         err = -ENODEV;
720         goto end;
721     } else {     
722         camsys_trace(1,"%s(%p) is opened!",dev_name(camsys_dev->miscdev.this_device),camsys_dev);
723     }
724
725 end:
726     return err;
727 }
728
729 static int camsys_release(struct inode *inode, struct file *file)
730 {
731     camsys_dev_t *camsys_dev = (camsys_dev_t*)file->private_data;
732
733     camsys_irq_disconnect(NULL,camsys_dev, true);
734
735     camsys_trace(1,"%s(%p) is closed",dev_name(camsys_dev->miscdev.this_device),camsys_dev);
736
737     return 0;
738 }
739
740 /*
741 * The ioctl() implementation
742 */
743
744 static long camsys_ioctl(struct file *filp,unsigned int cmd, unsigned long arg)
745 {
746         long err = 0;
747     camsys_dev_t *camsys_dev = (camsys_dev_t*)filp->private_data; 
748     
749         if (_IOC_TYPE(cmd) != CAMSYS_IOC_MAGIC) { 
750         camsys_err("ioctl type(%c!=%c) is invalidate\n",_IOC_TYPE(cmd),CAMSYS_IOC_MAGIC);
751         err = -ENOTTY;
752         goto end;
753         }
754         if (_IOC_NR(cmd) > CAMSYS_IOC_MAXNR) {
755         camsys_err("ioctl index(%d>%d) is invalidate\n",_IOC_NR(cmd),CAMSYS_IOC_MAXNR);
756         err = -ENOTTY;
757         goto end;
758         }
759
760     if (_IOC_DIR(cmd) & _IOC_READ)
761         err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));     
762     else if (_IOC_DIR(cmd) & _IOC_WRITE)
763         err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
764
765     if (err) {
766         camsys_err("ioctl(0x%x) operation not permitted for %s",cmd,dev_name(camsys_dev->miscdev.this_device));
767         err = -EFAULT;
768         goto end;
769     }
770
771         switch (cmd) {
772
773             case CAMSYS_VERCHK:
774             {
775                 camsys_version_t camsys_ver;
776                 
777             camsys_ver.drv_ver = CAMSYS_DRIVER_VERSION;
778             camsys_ver.head_ver = CAMSYS_HEAD_VERSION;
779             if (copy_to_user((void __user *)arg,(void*)&camsys_ver, sizeof(camsys_version_t)))
780                 return -EFAULT;
781             break;
782             }
783
784             case CAMSYS_I2CRD:
785             {
786                 camsys_i2c_info_t i2cinfo;
787                 
788             if (copy_from_user((void*)&i2cinfo,(void __user *)arg, sizeof(camsys_i2c_info_t))) 
789                 return -EFAULT;
790
791             err = camsys_i2c_read(&i2cinfo,camsys_dev);
792             if (err==0) {
793                 if (copy_to_user((void __user *)arg,(void*)&i2cinfo, sizeof(camsys_i2c_info_t)))
794                     return -EFAULT;
795             }
796             break;
797             }
798
799             case CAMSYS_I2CWR:
800             {
801             camsys_i2c_info_t i2cinfo;
802                 
803             if (copy_from_user((void*)&i2cinfo,(void __user *)arg, sizeof(camsys_i2c_info_t))) 
804                 return -EFAULT;
805
806             err = camsys_i2c_write(&i2cinfo,camsys_dev);
807             break;
808             }
809
810         case CAMSYS_SYSCTRL:
811         {
812             camsys_sysctrl_t devctl;
813
814             if (copy_from_user((void*)&devctl,(void __user *)arg, sizeof(camsys_sysctrl_t))) 
815                 return -EFAULT;
816
817             err = camsys_sysctl(&devctl, camsys_dev);
818             break;
819         }
820
821         case CAMSYS_REGRD:
822         {
823
824             break;
825         }
826
827         case CAMSYS_REGWR:
828         {
829
830             break;
831         }
832
833         case CAMSYS_REGISTER_DEVIO:
834         {
835             camsys_devio_name_t devio;
836
837             if (copy_from_user((void*)&devio,(void __user *)arg, sizeof(camsys_devio_name_t))) 
838                 return -EFAULT;
839
840             err = camsys_extdev_register(&devio,camsys_dev);
841             break;
842         }
843
844         case CAMSYS_DEREGISTER_DEVIO:
845         {
846             unsigned int dev_id;
847
848             if (copy_from_user((void*)&dev_id,(void __user *)arg, sizeof(unsigned int)))
849                 return -EFAULT;
850
851             err = camsys_extdev_deregister(dev_id, camsys_dev, false);
852             break;
853         }
854
855         case CAMSYS_IRQCONNECT:
856         {
857             camsys_irqcnnt_t irqcnnt;
858
859             if (copy_from_user((void*)&irqcnnt,(void __user *)arg, sizeof(camsys_irqcnnt_t))) 
860                 return -EFAULT;
861             
862             err = camsys_irq_connect(&irqcnnt, camsys_dev);
863             
864             break;
865         }
866
867         case CAMSYS_IRQWAIT:
868         {
869             camsys_irqsta_t irqsta;
870
871             err = camsys_irq_wait(&irqsta, camsys_dev);
872             if (err==0) {
873                 if (copy_to_user((void __user *)arg,(void*)&irqsta, sizeof(camsys_irqsta_t))) 
874                     return -EFAULT;
875             }
876             break;
877         }
878
879         case CAMSYS_IRQDISCONNECT:
880         {
881             camsys_irqcnnt_t irqcnnt;
882
883             if (copy_from_user((void*)&irqcnnt,(void __user *)arg, sizeof(camsys_irqcnnt_t))) 
884                 return -EFAULT;
885             err = camsys_irq_disconnect(&irqcnnt,camsys_dev,false);
886                         break;
887         }
888
889         
890         case CAMSYS_QUREYMEM:
891         {
892             camsys_querymem_t qmem;
893
894             if (copy_from_user((void*)&qmem,(void __user *)arg, sizeof(camsys_querymem_t))) 
895                 return -EFAULT;
896             
897             err = camsys_querymem(camsys_dev,&qmem);
898             if (err == 0) {
899                 if (copy_to_user((void __user *)arg,(void*)&qmem, sizeof(camsys_querymem_t))) 
900                     return -EFAULT;
901             }
902             break;
903         }
904        
905         default :
906             break;
907         }
908
909 end:    
910         return err;
911
912 }
913 /*
914  * VMA operations.
915  */
916 static void camsys_vm_open(struct vm_area_struct *vma)
917 {
918     camsys_meminfo_t *meminfo = (camsys_meminfo_t*)vma->vm_private_data;
919
920     meminfo->vmas++;
921     return;
922 }
923
924 static void camsys_vm_close(struct vm_area_struct *vma)
925 {
926     camsys_meminfo_t *meminfo = (camsys_meminfo_t*)vma->vm_private_data;
927
928     meminfo->vmas--;
929     return;
930 }
931
932 static const struct vm_operations_struct camsys_vm_ops = {
933         .open           = camsys_vm_open,
934         .close          = camsys_vm_close,
935 };
936
937 int camsys_mmap(struct file *flip, struct vm_area_struct *vma)
938 {
939     camsys_dev_t *camsys_dev = (camsys_dev_t*)flip->private_data;
940         unsigned long addr, start, size;    
941         camsys_mmap_type_t mem_type;
942         camsys_meminfo_t *meminfo;              
943         int ret = 0;
944
945     mem_type = vma->vm_pgoff;     
946     
947     if (mem_type == CamSys_Mmap_RegisterMem) {
948         if (camsys_dev->devmems.registermem != NULL) {
949             meminfo = camsys_dev->devmems.registermem;
950         } else {
951             camsys_err("this camsys device has not register mem!");
952             ret = -EINVAL;
953             goto done;
954         }
955     } else if (mem_type == CamSys_Mmap_I2cMem) {
956         if (camsys_dev->devmems.i2cmem != NULL) {
957             meminfo = camsys_dev->devmems.i2cmem;
958         } else {
959             camsys_err("this camsys device has not i2c mem!");
960             ret = -EINVAL;
961             goto done;
962         }
963     } else {
964         camsys_err("mmap buffer type %d is invalidate!",mem_type);
965         ret = -EINVAL;
966         goto done;
967     }
968     
969     size = vma->vm_end - vma->vm_start;
970     if (size > meminfo->size) {
971         ret = -ENOMEM;
972         camsys_err("mmap size(0x%lx) > memory size(0x%x), so failed!",size,meminfo->size);
973         goto done;
974     }
975     
976         start = vma->vm_start;
977         addr = __phys_to_pfn(meminfo->phy_base);    
978         
979     if (remap_pfn_range(vma, start, addr,size,pgprot_noncached(vma->vm_page_prot))) { 
980         
981         ret = -EAGAIN;
982         goto done;
983     }
984     
985     vma->vm_ops = &camsys_vm_ops;
986     vma->vm_flags |= VM_IO;
987     vma->vm_flags |=VM_ACCOUNT;//same as VM_RESERVED;
988     vma->vm_private_data = (void*)meminfo;
989     camsys_vm_open(vma);
990
991 done:
992         return ret;
993 }
994
995 struct file_operations camsys_fops = {
996         .owner =            THIS_MODULE,
997     .open =             camsys_open,
998     .release =          camsys_release,
999         .unlocked_ioctl =   camsys_ioctl,
1000         .mmap =             camsys_mmap,
1001 };
1002
1003 static int camsys_platform_probe(struct platform_device *pdev){
1004     int err = 0;
1005         camsys_dev_t *camsys_dev;
1006     struct resource register_res ;
1007     struct device *dev = &pdev->dev;
1008     unsigned long i2cmem;
1009         camsys_meminfo_t *meminfo;
1010     unsigned int irq_id;
1011     err = of_address_to_resource(dev->of_node, 0, &register_res);
1012     if (err < 0){
1013         camsys_err("Get register resource from %s platform device failed!",pdev->name);
1014         err = -ENODEV;
1015         goto fail_end;
1016         }
1017
1018  
1019     //map irqs
1020     irq_id = irq_of_parse_and_map(dev->of_node, 0);
1021     if (irq_id < 0) {
1022         camsys_err("Get irq resource from %s platform device failed!",pdev->name);
1023         err = -ENODEV;
1024         goto fail_end;
1025     }
1026
1027     camsys_dev = (camsys_dev_t*)devm_kzalloc(&pdev->dev,sizeof(camsys_dev_t), GFP_KERNEL);
1028     if (camsys_dev == NULL) {
1029         camsys_err("Allocate camsys_dev for %s platform device failed",pdev->name);
1030         err = -ENOMEM;
1031         goto fail_end;
1032     }
1033
1034     //spin_lock_init(&camsys_dev->lock);
1035     mutex_init(&camsys_dev->extdevs.mut);
1036     INIT_LIST_HEAD(&camsys_dev->extdevs.list);
1037     INIT_LIST_HEAD(&camsys_dev->extdevs.active);
1038     INIT_LIST_HEAD(&camsys_dev->list);
1039     
1040
1041     //IRQ init
1042     camsys_dev->irq.irq_id = irq_id;  
1043     spin_lock_init(&camsys_dev->irq.lock);
1044     INIT_LIST_HEAD(&camsys_dev->irq.irq_pool); 
1045     //init_waitqueue_head(&camsys_dev->irq.irq_done);
1046     
1047     INIT_LIST_HEAD(&camsys_dev->devmems.memslist);
1048
1049
1050         //Register mem init
1051     meminfo = kzalloc(sizeof(camsys_meminfo_t),GFP_KERNEL);
1052     if (meminfo == NULL) {
1053         err = -ENOMEM;
1054         goto request_mem_fail;
1055     }
1056
1057     meminfo->vir_base = (unsigned int)devm_ioremap_resource(dev, &register_res);
1058     if (!meminfo->vir_base){
1059         camsys_err("%s ioremap %s failed",dev_name(&pdev->dev), CAMSYS_REGISTER_MEM_NAME);
1060         err = -ENXIO;
1061         goto request_mem_fail;
1062         }
1063
1064     strlcpy(meminfo->name, CAMSYS_REGISTER_MEM_NAME,sizeof(meminfo->name));
1065     meminfo->phy_base = register_res.start;
1066     meminfo->size = register_res.end - register_res.start + 1;  
1067     list_add_tail(&meminfo->list, &camsys_dev->devmems.memslist);
1068
1069
1070         //I2c mem init
1071     i2cmem = __get_free_page(GFP_KERNEL);
1072     if (i2cmem == 0) {
1073         camsys_err("Allocate i2cmem failed!");
1074         err = -ENOMEM;
1075         goto request_mem_fail;
1076     }
1077     SetPageReserved(virt_to_page(i2cmem));
1078     
1079     meminfo = kzalloc(sizeof(camsys_meminfo_t),GFP_KERNEL);
1080     if (meminfo == NULL) {
1081         err = -ENOMEM;
1082         goto request_mem_fail;
1083     }
1084     strlcpy(meminfo->name,CAMSYS_I2C_MEM_NAME,sizeof(meminfo->name));
1085     meminfo->vir_base = i2cmem;
1086     meminfo->phy_base = virt_to_phys((void*)i2cmem);
1087     meminfo->size = PAGE_SIZE;
1088     list_add_tail(&meminfo->list, &camsys_dev->devmems.memslist);
1089
1090     {
1091         unsigned int *tmpp;
1092
1093         tmpp = (unsigned int*)meminfo->vir_base;
1094         *tmpp = 0xfa561243;
1095     }
1096
1097     //Special init
1098
1099     {        
1100         if (camsys_mipiphy_probe_cb(pdev, camsys_dev) <0) {
1101             camsys_err("Mipi phy probe failed!");
1102         }
1103     }
1104
1105 #if 0
1106     if (strcmp(dev_name(&pdev->dev),CAMSYS_PLATFORM_MARVIN_NAME) == 0) {
1107         #if (defined(CONFIG_CAMSYS_MRV))
1108         camsys_mrv_probe_cb(pdev, camsys_dev);        
1109         #else
1110         camsys_err("Marvin controller camsys driver haven't been complie!!!");
1111         #endif
1112     } else {
1113         #if (defined(CONFIG_CAMSYS_CIF))
1114         camsys_cif_probe_cb(pdev,camsys_dev);
1115         #else
1116         camsys_err("CIF controller camsys driver haven't been complie!!!");
1117         #endif
1118     }
1119 #else
1120         #if (defined(CONFIG_CAMSYS_MRV))
1121         camsys_mrv_probe_cb(pdev, camsys_dev);        
1122         #elif (defined(CONFIG_CAMSYS_CIF))
1123         camsys_cif_probe_cb(pdev,camsys_dev);
1124         #else
1125         camsys_err("camsys driver haven't been complie!!!");
1126         #endif
1127 #endif
1128     camsys_trace(1, "%s memory:",dev_name(&pdev->dev));
1129     list_for_each_entry(meminfo, &camsys_dev->devmems.memslist, list) {
1130         if (strcmp(meminfo->name,CAMSYS_I2C_MEM_NAME) == 0) {
1131             camsys_dev->devmems.i2cmem = meminfo;
1132             camsys_trace(1,"    I2c memory (phy: 0x%x vir: 0x%x size: 0x%x)",
1133                         meminfo->phy_base,meminfo->vir_base,meminfo->size);
1134         }
1135         if (strcmp(meminfo->name,CAMSYS_REGISTER_MEM_NAME) == 0) {
1136             camsys_dev->devmems.registermem = meminfo;
1137             camsys_trace(1,"    Register memory (phy: 0x%x vir: 0x%x size: 0x%x)",
1138                         meminfo->phy_base,meminfo->vir_base,meminfo->size);
1139         }
1140     }
1141
1142
1143     camsys_dev->phy_cb = camsys_phy_ops;
1144     camsys_dev->pdev    =   pdev;
1145
1146     platform_set_drvdata(pdev,(void*)camsys_dev);
1147     //Camsys_devs list add    
1148     spin_lock(&camsys_devs.lock);    
1149     list_add_tail(&camsys_dev->list, &camsys_devs.devs);
1150     spin_unlock(&camsys_devs.lock);
1151
1152     
1153     camsys_trace(1, "Probe %s device success ", dev_name(&pdev->dev));
1154     return 0;
1155 request_mem_fail:
1156     if (camsys_dev != NULL) {
1157     
1158         while(!list_empty(&camsys_dev->devmems.memslist)) {
1159             meminfo = list_first_entry(&camsys_dev->devmems.memslist, camsys_meminfo_t, list);
1160             if (meminfo) {
1161                 list_del_init(&meminfo->list);
1162                 if (strcmp(meminfo->name,CAMSYS_REGISTER_MEM_NAME)==0) {
1163                     iounmap((void __iomem *)meminfo->vir_base);
1164                     release_mem_region(meminfo->phy_base,meminfo->size);
1165                 } else if (strcmp(meminfo->name,CAMSYS_I2C_MEM_NAME)==0) {
1166                     kfree((void*)meminfo->vir_base);
1167                 }
1168                 kfree(meminfo);
1169                 meminfo = NULL;
1170             }
1171         } 
1172     
1173         kfree(camsys_dev);
1174         camsys_dev = NULL;
1175     }
1176 fail_end:
1177     return -1;
1178
1179     
1180 }
1181 static int  camsys_platform_remove(struct platform_device *pdev)
1182 {
1183     camsys_dev_t *camsys_dev = platform_get_drvdata(pdev);
1184     camsys_meminfo_t *meminfo;
1185     
1186     if (camsys_dev) {
1187
1188         //Mem deinit
1189         while(!list_empty(&camsys_dev->devmems.memslist)) {
1190             meminfo = list_first_entry(&camsys_dev->devmems.memslist, camsys_meminfo_t, list);
1191             if (meminfo) {
1192                 list_del_init(&meminfo->list);
1193                 if (strcmp(meminfo->name,CAMSYS_REGISTER_MEM_NAME)==0) {
1194                     iounmap((void __iomem *)meminfo->vir_base);
1195                     release_mem_region(meminfo->phy_base,meminfo->size);
1196                 } else if (strcmp(meminfo->name,CAMSYS_I2C_MEM_NAME)==0) {
1197                     kfree((void*)meminfo->vir_base);
1198                 }
1199                 kfree(meminfo);
1200                 meminfo = NULL;
1201             }
1202         }        
1203
1204         //Irq deinit
1205         if (camsys_dev->irq.irq_id) {
1206             free_irq(camsys_dev->irq.irq_id, camsys_dev);
1207             camsys_irq_disconnect(NULL,camsys_dev,true);
1208         }
1209
1210         //Extdev deinit
1211         if (!list_empty(&camsys_dev->extdevs.list)) {
1212             camsys_extdev_deregister(0,camsys_dev,true);
1213         }
1214
1215         if (camsys_dev->mipiphy.remove) 
1216             camsys_dev->mipiphy.remove(pdev);
1217         if (camsys_dev->cifphy.remove)
1218             camsys_dev->cifphy.remove(pdev);
1219         camsys_dev->platform_remove(pdev);
1220
1221         misc_deregister(&camsys_dev->miscdev);
1222         
1223         spin_lock(&camsys_devs.lock);
1224         list_del_init(&camsys_dev->list);
1225         spin_unlock(&camsys_devs.lock);
1226
1227         kfree(camsys_dev);
1228         camsys_dev=NULL;
1229     } else {
1230         camsys_err("This platform device havn't obtain camsys_dev!");
1231     }
1232
1233     return 0;
1234 }
1235
1236
1237 static const struct of_device_id cif_of_match[] = {
1238     { .compatible = "rockchip,isp" },
1239 };
1240 MODULE_DEVICE_TABLE(of, cif_of_match);
1241
1242 static struct platform_driver camsys_platform_driver =
1243 {
1244     .driver     = {
1245         .name   = CAMSYS_PLATFORM_DRV_NAME,
1246         .of_match_table = of_match_ptr(cif_of_match),
1247     },
1248     .probe              = camsys_platform_probe,
1249     .remove             = (camsys_platform_remove),
1250 };
1251
1252 MODULE_ALIAS(CAMSYS_PLATFORM_DRV_NAME);
1253 static int __init camsys_platform_init(void)  
1254 {
1255     printk("CamSys driver version: v%d.%d.%d,  CamSys head file version: v%d.%d.%d\n",
1256         (CAMSYS_DRIVER_VERSION&0xff0000)>>16, (CAMSYS_DRIVER_VERSION&0xff00)>>8,
1257         CAMSYS_DRIVER_VERSION&0xff,
1258         (CAMSYS_HEAD_VERSION&0xff0000)>>16, (CAMSYS_HEAD_VERSION&0xff00)>>8,
1259         CAMSYS_HEAD_VERSION&0xff);
1260     spin_lock_init(&camsys_devs.lock);
1261     INIT_LIST_HEAD(&camsys_devs.devs);
1262     platform_driver_register(&camsys_platform_driver);
1263    // platform_driver_probe(&camsys_platform_driver, camsys_platform_probe_new);
1264     
1265     return 0;
1266 }  
1267   
1268 static void __exit camsys_platform_exit(void)  
1269 {
1270     platform_driver_unregister(&camsys_platform_driver);
1271
1272
1273 module_init(camsys_platform_init);              
1274 module_exit(camsys_platform_exit);      
1275
1276 MODULE_DESCRIPTION("RockChip Camera System");
1277 MODULE_AUTHOR("<ddl@rock-chips>");
1278 MODULE_LICENSE("GPL");
1279