1 /******************************************************************************
2 * isp.c - MT6589 Linux ISP Device Driver
4 * Copyright 2008-2009 MediaTek Co.,Ltd.
7 * This file provid the other drivers ISP relative functions
9 ******************************************************************************/
11 #include <linux/types.h>
12 #include <linux/device.h>
13 #include <linux/cdev.h>
14 #include <linux/platform_device.h>
15 #include <linux/interrupt.h>
17 //seanlin 111223 fix conpilier error #include <asm/tcm.h>
18 #include <linux/proc_fs.h> //proc file use
20 #include <linux/spinlock.h>
22 #include <linux/delay.h>
23 #include <linux/uaccess.h>
24 #include <asm/atomic.h>
25 #include <linux/sched.h>
28 #include <mach/mt_reg_base.h> //seanlin 111223 fix conpilier error #include <mach/hardware.h>
30 //#include <mach/mt6575_pll.h>
31 #include <mach/isp.h> //seanlin 111223
34 /*******************************************************************************
36 ********************************************************************************/
37 #define ISP_TAG "[ISP] "
38 #define ISP_LOG(fmt, arg...) printk(ISP_TAG fmt, ##arg)//printk()//seanlin@110715
39 #define ISP_ERR(fmt, arg...) printk(ISP_TAG "Err: %5d:, "fmt, __LINE__, ##arg)
41 #define ISP_WR32(addr, data) iowrite32(data, addr)
42 #define ISP_RD32(addr) ioread32(addr)
43 #define ISP_SET_BIT(reg, bit) ((*(volatile u32*)(reg)) |= (u32)(1 << (bit)))
44 #define ISP_CLR_BIT(reg, bit) ((*(volatile u32*)(reg)) &= ~((u32)(1 << (bit))))
46 #define ISP_BASE CAMINF_BASE
47 #define ISP_BASE_SHIFT (CAMINF_BASE+0x4000) //seanlin 120105
48 #define ISP_DEV_NAME "mt-isp" // senalin111228 "mt6589-isp"
50 /*******************************************************************************
52 ********************************************************************************/
53 // Register definition
54 #define ISP_PHSCNT (ISP_BASE + 0x000)
55 #define ISP_VFCON (ISP_BASE + 0x018)
56 #define ISP_INTEN (ISP_BASE + 0x01c)
57 #define ISP_INTSTA (ISP_BASE + 0x020)
58 #define ISP_PATH (ISP_BASE + 0x024)
59 #define ISP_RAWGAIN0 (ISP_BASE + 0x16C)
60 #define ISP_RAWGAIN1 (ISP_BASE + 0x170)
61 #define ISP_RESET (ISP_BASE + 0x1D8)
62 #define ISP_TGSTATUS (ISP_BASE + 0x1DC)
63 #define ISP_SHADING1 (ISP_BASE + 0x214)
64 #define ISP_VERSION (ISP_BASE + 0x274)
66 #define ISP_G1MEMPDN (MMSYS1_CONFIG_BASE + 0x30c)
69 #define ISP_INT_OVERRUN_MASK ((u32)0x6)
70 #define ISP_INT_EXP_DONE ((u32)0x1)
71 #define ISP_INT_IDLE ((u32)0x1 << 3)
72 #define ISP_INT_ISP_DONE ((u32)0x1 << 4)
73 #define ISP_INT_VSYNC ((u32)0x1 << 10)
75 #define ISP_DBG_INT 0x0001
76 #define ISP_DBG_HOLD_REG 0x0002
77 #define ISP_DBG_READ_REG 0x0004
78 #define ISP_DBG_WRITE_REG 0x0008
79 #define ISP_DBG_CLK 0x0010
80 #define ISP_DBG_TASKLET 0x0020
81 #define ISP_DBG_WORKQUEUE 0x0040
83 /*******************************************************************************
85 ********************************************************************************/
86 static spinlock_t isp_lock
;
87 static u8
*pcmd_buf
= NULL
;
88 static u8
*pread_buf
= NULL
;
89 static u8
*pwrite_buf
= NULL
;
90 static u32 buf_size
= 4096;
91 static atomic_t hold_reg
;
92 static atomic_t writing_reg
;
93 static u32 hold_count
;
94 static wait_queue_head_t isp_wait_queue
;
95 static u32 irq_status
;
96 static u32 dbgMask
= 0x000000FF;
97 static struct work_struct isp_work_queue
;
99 /*******************************************************************************
101 ********************************************************************************/
102 static unsigned long ms_to_jiffies(unsigned long ms
)
104 return ((ms
* HZ
+ 512) >> 10);
107 /*******************************************************************************
109 ********************************************************************************/
110 static int mt_isp_clk_ctrl(int en
)
112 if (dbgMask
& ISP_DBG_CLK
) {
113 ISP_LOG("[mt_isp_clk_ctrl] %d \n", en
);
117 //hwEnableClock(MT65XX_PDN_MM_ISP, "ISP");
118 //hwEnableClock(MT65XX_PDN_MM_RESZ_LB, "ISP");
119 // ISP_CLR_BIT(ISP_G1MEMPDN, 9);
122 //hwDisableClock(MT65XX_PDN_MM_ISP, "ISP");
123 //hwDisableClock(MT65XX_PDN_MM_RESZ_LB, "ISP");
124 // ISP_SET_BIT(ISP_G1MEMPDN, 9);
130 /*******************************************************************************
132 ********************************************************************************/
133 static inline void mt_isp_reset(void)
135 #if 0 //seanlin 111226
136 // ensure the view finder is disabe
137 ISP_CLR_BIT(ISP_VFCON
, 6);
139 ISP_WR32(ISP_RESET
, 1);
140 // delay at least 100us for reset the ISp (HW suggest)
142 ISP_WR32(ISP_RESET
, 0);
148 /*******************************************************************************
150 ********************************************************************************/
151 static int mt_isp_read_reg(mt_isp_reg_io_t
*preg_io
)
154 int size
= preg_io
->count
* sizeof(mt_isp_reg_t
);
155 mt_isp_reg_t
*preg
= (mt_isp_reg_t
*) pread_buf
;
158 if (dbgMask
& ISP_DBG_READ_REG
) {
159 // ISP_LOG("[mt_isp_read_reg] data: 0x%x, count: %d \n", (u32) preg_io->data, (u32) preg_io->count);
162 if (size
> buf_size
) {
163 ISP_ERR("size too big \n");
166 if (copy_from_user((u8
*)preg
, (u8
*) preg_io
->data
, size
) != 0) {
167 ISP_ERR("copy_from_user failed \n");
169 goto mt_isp_read_reg_exit
;
172 for (i
= 0; i
< preg_io
->count
; i
++) {
173 preg
[i
].val
= ISP_RD32(ISP_BASE
+ preg
[i
].addr
);
174 if (dbgMask
& ISP_DBG_READ_REG
) {
175 // ISP_LOG(" addr/val: 0x%08x/0x%08x \n", (u32) (ISP_BASE + preg[i].addr), (u32) preg[i].val);
179 if (copy_to_user((u8
*) preg_io
->data
, (u8
*) preg
, size
) != 0) {
180 ISP_ERR("copy_to_user failed \n");
182 goto mt_isp_read_reg_exit
;
185 mt_isp_read_reg_exit
:
190 /*******************************************************************************
192 ********************************************************************************/
193 static int mt_isp_write_reg_to_hw(mt_isp_reg_t
*preg
, u32 count
)
198 if (dbgMask
& ISP_DBG_WRITE_REG
) {
199 //seanlin ISP_LOG("[mt_isp_write_reg_to_hw] \n");
202 for (i
= 0; i
< count
; i
++) {
203 if (dbgMask
& ISP_DBG_WRITE_REG
) {
204 //seanlin ISP_LOG(" addr/val: 0x%08x/0x%08x \n", (u32) (ISP_BASE + preg[i].addr), (u32) preg[i].val);
206 if(preg
[i
].addr
<0xa000) //seanlin if(preg[i].addr<0x7100) //seanlin
208 ISP_WR32(ISP_BASE
+ preg
[i
].addr
, preg
[i
].val
);
212 ISP_LOG("SKIP 0x%8x\n",preg
[i
].addr
); //seanlin 120103
219 /*******************************************************************************
221 ********************************************************************************/
222 void mt_isp_tasklet_write_reg(unsigned long arg
)
224 mt_isp_reg_t
*preg
= (mt_isp_reg_t
*) pwrite_buf
;
226 if (dbgMask
& ISP_DBG_HOLD_REG
) {
227 //seanlin ISP_LOG("[mt_isp_tasklet_write_reg] preg: 0x%x, count: %d \n", (u32) preg, hold_count);
230 mt_isp_write_reg_to_hw(preg
, hold_count
);
233 atomic_set(&writing_reg
, 0);
234 wake_up_interruptible(&isp_wait_queue
);
237 DECLARE_TASKLET(tasklet_write_reg
, mt_isp_tasklet_write_reg
, 0);
239 /*******************************************************************************
241 ********************************************************************************/
242 //extern int kdSensorSyncFunctionPtr(UINT16 *pRAWGain);
243 //extern int kdSetSensorSyncFlag(BOOL bSensorSync);
244 void mt_isp_work_queue(unsigned long param
)
248 // Synchronization the exposure time, sensor gain and raw gain.
249 //kdSensorSyncFunctionPtr(&rawGain[0]);
250 //kdSetSensorSyncFlag(FALSE);
252 if ((rawGain
[0] != 0) && (rawGain
[1] != 0) && (rawGain
[2] != 0) && (rawGain
[3] != 0) ) {
253 ISP_WR32(ISP_RAWGAIN0
, ((u32
) rawGain
[0] << 0) | ((u32
) rawGain
[1] << 16));
254 ISP_WR32(ISP_RAWGAIN1
, ((u32
) rawGain
[2] << 0) | ((u32
) rawGain
[3] << 16));
258 /*******************************************************************************
260 ********************************************************************************/
261 static int mt_isp_write_reg(mt_isp_reg_io_t
*preg_io
)
264 int size
= preg_io
->count
* sizeof(mt_isp_reg_t
);
265 int hold_size
= hold_count
* sizeof(mt_isp_reg_t
);
266 mt_isp_reg_t
*preg
= (mt_isp_reg_t
*) (pwrite_buf
+ hold_size
);
268 if (dbgMask
& ISP_DBG_WRITE_REG
) {
269 //seanlin ISP_LOG("[mt_isp_write_reg] data: 0x%x, count: %d \n", (u32) preg_io->data, (u32) preg_io->count);
272 if (atomic_read(&hold_reg
)) {
273 if (atomic_read(&writing_reg
)) {
275 // Should wait until write done
276 if (dbgMask
& ISP_DBG_TASKLET
) {
277 //seanlin ISP_LOG("[mt_isp_write_reg] Start wait ... \n");
279 timeout
= wait_event_interruptible_timeout(
280 isp_wait_queue
, atomic_read(&writing_reg
) == 0 , ms_to_jiffies(500));
281 if (dbgMask
& ISP_DBG_TASKLET
) {
282 //seanlin ISP_LOG("[mt_isp_write_reg] End wait \n");
285 ISP_ERR("Should not happen \n");
287 goto mt_isp_write_reg_exit
;
292 if ((size
+ hold_size
) > buf_size
) {
293 ISP_ERR("size too big \n");
295 goto mt_isp_write_reg_exit
;
298 if (copy_from_user((u8
*)preg
, (u8
*) preg_io
->data
, size
) != 0) {
299 ISP_ERR("copy_from_user failed \n");
301 goto mt_isp_write_reg_exit
;
304 if (atomic_read(&hold_reg
)) {
305 // Write register to buffer
306 hold_count
+= preg_io
->count
;
309 // Write register to hw
310 ret
= mt_isp_write_reg_to_hw(preg
, preg_io
->count
);
313 mt_isp_write_reg_exit
:
318 /*******************************************************************************
320 ********************************************************************************/
321 static int mt_isp_hold_reg(u32 is_hold
)
325 if (dbgMask
& ISP_DBG_HOLD_REG
) {
326 ISP_LOG("[mt_isp_hold_reg] %d, %d \n", is_hold
, atomic_read(&hold_reg
));
330 if (atomic_read(&hold_reg
)) {
331 // Hold is switching from on to off,
332 // Should write register to hw now
333 atomic_set(&writing_reg
, 1);
336 atomic_set(&hold_reg
, is_hold
);
341 /*******************************************************************************
343 ********************************************************************************/
344 static int mt_isp_wait_irq(u32 wait_irq_status
)
349 if (dbgMask
& ISP_DBG_INT
) {
350 ISP_LOG("[mt_isp_wait_irq] \n" );
353 timeout
= wait_event_interruptible_timeout(
354 isp_wait_queue
, (wait_irq_status
& irq_status
), 3 * HZ
);
356 ISP_ERR("wait_event_interruptible_timeout timeout, %d, %d \n", wait_irq_status
, irq_status
);
360 spin_lock_irq(&isp_lock
);
362 if (dbgMask
& ISP_DBG_INT
) {
363 ISP_LOG("irq_status: 0x%x \n", irq_status
);
366 irq_status
&= ~(wait_irq_status
);
368 spin_unlock_irq(&isp_lock
);
373 /*******************************************************************************
375 ********************************************************************************/
376 static int mt_isp_dump_reg(void)
381 ISP_LOG("[mt_isp_dump_reg] E \n" );
383 spin_lock_irq(&isp_lock
);
385 for (i
= 0x4000; i
< 0x5e10; i
+= 4) {
386 ISP_LOG(" addr, val: 0x%08x, 0x%08x \n", ISP_BASE
+ i
, ISP_RD32(ISP_BASE
+ i
));
389 spin_unlock_irq(&isp_lock
);
391 ISP_LOG("[mt_isp_dump_reg] X \n" );
395 #if 0 // seanlin 111223 fix conpilier error
396 /*******************************************************************************
398 ********************************************************************************/
399 static __tcmfunc irqreturn_t
mt_isp_irq(int irq
, void *dev_id
)
402 irq_status
|= ISP_RD32(ISP_INTSTA
);
404 //if (dbgMask & ISP_DBG_INT) {
405 ISP_LOG("[mt_isp_irq] 0x%x \n", irq_status
);
408 if (irq_status
& ISP_INT_OVERRUN_MASK
) {
409 ISP_ERR("ISP_INT_OVERRUN_MASK: 0x%x \n", irq_status
);
410 irq_status
&= ~(ISP_INT_OVERRUN_MASK
);
412 //Incomplete frame error handling
413 if(ioread32((ROT_DMA0_BASE
+ 0x18)) >> 31)
415 ISP_LOG("Speed up ROTDMA0!!\n");
416 mt65xx_reg_sync_writel(0 , (ROT_DMA0_BASE
+ 0x300));
418 else if(ioread32((ROT_DMA1_BASE
+ 0x18)) >> 31)
420 ISP_LOG("Speed up ROTDMA1!!\n");
421 mt65xx_reg_sync_writel(0 , (ROT_DMA1_BASE
+ 0x300));
423 else if(ioread32((ROT_DMA2_BASE
+ 0x18)) >> 31)
425 ISP_LOG("Speed up ROTDMA2!!\n");
426 mt65xx_reg_sync_writel(0 , (ROT_DMA2_BASE
+ 0x300));
428 ISP_LOG("speed up ROTDMA done \n");
429 // ensure the view finder is disabe
430 ISP_CLR_BIT(ISP_VFCON
, 6);
432 //ISP_WR32(ISP_RESET, 1);
433 mt65xx_reg_sync_writel(0x10000,ISP_RESET
);
434 //ISP_SET_BIT(ISP_RESET, 16); //SW reset
435 //ISP_SET_BIT(ISP_RESET, 0); //HW reset
436 // delay at least 100us for reset the ISp (HW suggest)
438 //ISP_WR32(ISP_RESET, 0);
439 mt65xx_reg_sync_writel(0,ISP_RESET
);
440 //ISP_CLR_BIT(ISP_RESET, 16); //SW reset
441 //ISP_CLR_BIT(ISP_RESET, 0); //HW reset
442 ISP_SET_BIT(ISP_VFCON
, 6);
444 ISP_LOG("ISP reset done\n");
448 wake_up_interruptible(&isp_wait_queue
);
450 if (irq_status
& ISP_INT_VSYNC
) {
451 if (dbgMask
& ISP_DBG_WORKQUEUE
) {
452 ISP_LOG("[mt_isp_irq] schedule_work \n");
454 schedule_work(&isp_work_queue
);
455 irq_status
&= ~(ISP_INT_VSYNC
);
457 // If ISP exp int is done, wake up tasklet to write register if it is buffered
458 if ((atomic_read(&writing_reg
)) && (irq_status
& ISP_INT_EXP_DONE
)) {
459 if (dbgMask
& ISP_DBG_TASKLET
) {
460 ISP_LOG("[mt_isp_irq] tasklet_schedule \n");
462 tasklet_schedule(&tasklet_write_reg
);
463 irq_status
&= ~(ISP_INT_EXP_DONE
);
469 /*******************************************************************************
471 ********************************************************************************/
472 static long mt_isp_ioctl(struct file
*file
,
478 if( pcmd_buf
== NULL
||
481 ISP_ERR("buf is null\n");
484 if (_IOC_DIR(cmd
) != _IOC_NONE
) {
486 if (_IOC_DIR(cmd
) & _IOC_WRITE
) {
487 if (copy_from_user(pcmd_buf
, (void *) arg
, _IOC_SIZE(cmd
)) != 0) {
488 ISP_ERR("copy_from_user failed \n");
495 case MT_ISP_IOC_T_RESET
:
496 ISP_LOG("[MT_ISP_IOC_T_RESET] \n");
499 case MT_ISP_IOC_G_READ_REG
:
500 ret
= mt_isp_read_reg((mt_isp_reg_io_t
*) pcmd_buf
);
502 case MT_ISP_IOC_S_WRITE_REG
:
503 ret
= mt_isp_write_reg((mt_isp_reg_io_t
*) pcmd_buf
);
505 case MT_ISP_IOC_T_HOLD_REG
:
506 ret
= mt_isp_hold_reg(*(u32
*) pcmd_buf
);
508 //case MT_ISP_IOC_T_RUN:
510 case MT_ISP_IOC_T_WAIT_IRQ
:
511 ret
= mt_isp_wait_irq(*(u32
*) pcmd_buf
);
513 case MT_ISP_IOC_T_DUMP_REG
:
514 ret
= mt_isp_dump_reg();
516 case MT_ISP_IOC_T_DBG_FLAG
:
517 ISP_LOG("[MT_ISP_IOC_T_DBG_FLAG]: 0x%x \n", *(u32
*) pcmd_buf
);
518 dbgMask
= *(u32
*) pcmd_buf
;
521 ISP_ERR("[mt_isp_ioctl] unknown cmd \n");
526 if (_IOC_READ
& _IOC_DIR(cmd
)) {
527 if (copy_to_user((void __user
*) arg
, pcmd_buf
, _IOC_SIZE(cmd
)) != 0) {
528 ISP_ERR("copy_to_user failed \n");
536 /*******************************************************************************
538 ********************************************************************************/
539 static int mt_isp_open(struct inode
*inode
, struct file
*file
)
543 ISP_LOG("[mt_isp_open] \n");
545 spin_lock_irq(&isp_lock
);
547 // Buffer has been allocated
548 ISP_ERR(" open more than once \n");
549 goto mt_isp_open_exit
;
551 // Allocate buffer for cmd/read/write buffer
552 if (pcmd_buf
!= NULL
) {
553 ISP_ERR("pcmd_buf is not null \n");
555 if (pread_buf
!= NULL
) {
556 ISP_ERR("pread_buf is not null \n");
558 if (pwrite_buf
!= NULL
) {
559 ISP_ERR("pread_buf is not null \n");
561 pcmd_buf
= (u8
*) kmalloc(buf_size
, GFP_KERNEL
);
562 if (pcmd_buf
== NULL
) {
563 ISP_ERR("kmalloc failed \n ");
565 goto mt_isp_open_exit
;
567 pread_buf
= (u8
*) kmalloc(buf_size
, GFP_KERNEL
);
568 if (pread_buf
== NULL
) {
569 ISP_ERR("kmalloc failed \n ");
571 goto mt_isp_open_exit
;
573 pwrite_buf
= (u8
*) kmalloc(buf_size
, GFP_KERNEL
);
574 if (pwrite_buf
== NULL
) {
575 ISP_ERR("kmalloc failed \n ");
577 goto mt_isp_open_exit
;
580 atomic_set(&hold_reg
, 0);
581 atomic_set(&writing_reg
, 0);
585 init_waitqueue_head(&isp_wait_queue
);
587 INIT_WORK(&isp_work_queue
, mt_isp_work_queue
);
607 spin_unlock_irq(&isp_lock
);
612 /*******************************************************************************
614 ********************************************************************************/
615 static int mt_isp_release(struct inode
*inode
, struct file
*file
)
617 ISP_LOG("[mt_isp_release] \n");
638 /*******************************************************************************
640 ********************************************************************************/
641 static int mt_isp_mmap(struct file
*file
, struct vm_area_struct
*vma
)
643 // ISP_LOG("[mt_isp_mmap] \n");
645 vma
->vm_page_prot
= pgprot_noncached(vma
->vm_page_prot
);
646 if (remap_pfn_range(vma
, vma
->vm_start
, vma
->vm_pgoff
,
647 vma
->vm_end
- vma
->vm_start
, vma
->vm_page_prot
)) {
654 /*******************************************************************************
656 ********************************************************************************/
657 static dev_t dev_isp
;
658 static struct cdev
*pcdev_isp
= NULL
;
659 static struct class *pclass_isp
= NULL
;
660 static const struct file_operations mt_isp_fops
= {
661 .owner
= THIS_MODULE
,
663 .release
= mt_isp_release
,
664 //.flush = mt_isp_flush,
666 .unlocked_ioctl
= mt_isp_ioctl
667 //seanlin 111223 fix conpilier error .ioctl = mt_isp_ioctl
669 static int isp_irq_num
;
671 /*******************************************************************************
673 ********************************************************************************/
674 inline static void mt_isp_unregister_char_driver(void)
676 // ISP_LOG("[mt_isp_unregister_char_driver] \n");
678 //Release char driver
679 if (pcdev_isp
!= NULL
) {
684 unregister_chrdev_region(dev_isp
, 1);
687 /*******************************************************************************
689 ********************************************************************************/
690 inline static int mt_isp_register_char_driver(void)
694 ISP_LOG("[mt_isp_register_char_driver] \n");
696 if ( (ret
= alloc_chrdev_region(&dev_isp
, 0, 1, ISP_DEV_NAME
)) < 0 ) {
697 ISP_ERR("alloc_chrdev_region failed, %d \n", ret
);
698 ISP_LOG("[alloc_chrdev_region failed] \n");
702 pcdev_isp
= cdev_alloc();
703 if (pcdev_isp
== NULL
) {
704 ISP_ERR("cdev_alloc failed\n");
705 ISP_LOG("[cdev_alloc failed] \n");
707 goto mt_isp_register_char_driver_exit
;
709 //Attatch file operation.
710 cdev_init(pcdev_isp
, &mt_isp_fops
);
712 pcdev_isp
->owner
= THIS_MODULE
;
714 if ( (ret
= cdev_add(pcdev_isp
, dev_isp
, 1)) < 0) {
715 ISP_ERR("Attatch file operation failed, %d \n", ret
);
716 goto mt_isp_register_char_driver_exit
;
719 ISP_LOG("[mt_isp_register_char_driver]OKOK \n");
721 mt_isp_register_char_driver_exit
:
724 mt_isp_unregister_char_driver();
730 /*******************************************************************************
732 ********************************************************************************/
733 static int mt_isp_probe(struct platform_device
*pdev
)
736 struct resource
*pres
= NULL
;
739 ISP_LOG("[mt_isp_probe] enter \n");
740 // Check platform_device parameters
742 dev_err(&pdev
->dev
, "pdev is NULL \n");
745 // Register char driver
746 if ( (ret
= mt_isp_register_char_driver()) ) {
747 dev_err(&pdev
->dev
, "register char failed \n");
750 // Mapping CAM_REGISTERS
751 for (i
= 0; i
< 2; i
++) {
752 pres
= platform_get_resource(pdev
, IORESOURCE_MEM
, i
);
754 dev_err(&pdev
->dev
, "platform_get_resource failed \n");
756 goto mt_isp_probe_exit
;
758 pres
= request_mem_region(pres
->start
, pres
->end
- pres
->start
+ 1, pdev
->name
);
760 dev_err(&pdev
->dev
, "request_mem_region failed \n");
762 goto mt_isp_probe_exit
;
765 // Request CAM_ISP IRQ
767 isp_irq_num
= platform_get_irq(pdev
, 0);
768 ISP_LOG("IRQ Num = %d \n", isp_irq_num
);
769 if ( (ret
= request_irq(isp_irq_num
, mt_isp_irq
, 0, pdev
->name
, NULL
)) ) {
770 dev_err(&pdev
->dev
, "request IRQ failed\n");
771 goto mt_isp_probe_exit
;
773 mt6575_irq_set_sens(MT6575_CAM_IRQ_LINE
,MT65xx_LEVEL_SENSITIVE
);
775 // Someone has enable isp irq ??
776 // enable_irq(isp_irq_num);
778 // Create class register
779 pclass_isp
= class_create(THIS_MODULE
, "ispdrv");
780 if (IS_ERR(pclass_isp
)) {
781 ret
= PTR_ERR(pclass_isp
);
782 ISP_ERR("Unable to create class, err = %d\n", ret
);
785 // FIXME: error handling
786 device_create(pclass_isp
, NULL
, dev_isp
, NULL
, ISP_DEV_NAME
);
787 // Initialize critical section
788 spin_lock_init(&isp_lock
);
793 mt_isp_unregister_char_driver();
796 ISP_LOG("[mt_isp_probe] exit \n");
801 /*******************************************************************************
802 * Called when the device is being detached from the driver
803 ********************************************************************************/
804 static int mt_isp_remove(struct platform_device
*pdev
)
806 struct resource
*pres
;
810 ISP_LOG("[mt_isp_remove] \n");
811 // unregister char driver.
812 mt_isp_unregister_char_driver();
813 // unmaping ISP CAM_REGISTER registers
814 for (i
= 0; i
< 2; i
++) {
815 pres
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
816 release_mem_region(pres
->start
, (pres
->end
- pres
->start
+ 1));
819 disable_irq(isp_irq_num
);
820 irq_num
= platform_get_irq(pdev
, 0);
821 free_irq(irq_num
, NULL
);
823 device_destroy(pclass_isp
, dev_isp
);
825 class_destroy(pclass_isp
);
831 /*******************************************************************************
833 ********************************************************************************/
834 static int mt_isp_suspend(struct platform_device
*pdev
, pm_message_t mesg
)
839 /*******************************************************************************
841 ********************************************************************************/
842 static int mt_isp_resume(struct platform_device
*pdev
)
847 /*******************************************************************************
849 ********************************************************************************/
850 static struct platform_driver isp_driver
= {
851 .probe
= mt_isp_probe
,
852 .remove
= mt_isp_remove
,
853 .suspend
= mt_isp_suspend
,
854 .resume
= mt_isp_resume
,
857 .owner
= THIS_MODULE
,
861 /*******************************************************************************
863 ********************************************************************************/
865 mt_isp_dump_reg_to_proc(
866 char *page
, char **start
, off_t off
, int count
, int *eof
, void *data
873 ISP_LOG("[mt_isp_dump_reg_to_proc] \n");
876 p
+= sprintf(p
, "\n\r MT6589 ISP Register \n\r");
877 p
+= sprintf(p
,"======General Setting ====\n\r");
878 for (u4Index
=0x4000; u4Index
< 0x4010; u4Index
+= 4) {
879 p
+= sprintf(p
,"+0x%0x 0x%0x\n\r", u4Index
, ISP_RD32(ISP_BASE
+ u4Index
));
881 p
+= sprintf(p
,"======STATUS Setting ====\n\r");
882 for (u4Index
= 0x4020; u4Index
<= 0x4024; u4Index
+= 4) {
883 p
+= sprintf(p
,"+0x%0x 0x%0x\n\r", u4Index
, ISP_RD32(ISP_BASE
+ u4Index
));
886 for (u4Index
= 0x000043BC; u4Index
<= 0x000043BC; u4Index
+=4) {
887 p
+= sprintf(p
, "CAM_IMGO_ERR_STAT\n+0x%0x 0x%0x\n\r", u4Index
, ISP_RD32(ISP_BASE
+ u4Index
));
890 for (u4Index
= 0x0000439C; u4Index
<= 0x0000439C; u4Index
+=4) {
891 p
+= sprintf(p
, "CAM_IMGI_ERR_STAT\n+0x%0x 0x%0x\n\r", u4Index
, ISP_RD32(ISP_BASE
+ u4Index
));
894 for (u4Index
= 0x00004164; u4Index
<= 0x00004164; u4Index
+=4) {
895 p
+= sprintf(p
, "CTL_DBG_PORT\n+0x%0x 0x%0x\n\r", u4Index
, ISP_RD32(ISP_BASE
+ u4Index
));
908 return len
< count
? len
: count
;
911 /*******************************************************************************
913 ********************************************************************************/
914 static int mt_isp_reg_debug(
915 struct file
*file
, const char *buffer
, unsigned long count
, void *data
919 u32 u4CopyBufSize
= (count
< (sizeof(regBuf
) - 1)) ? (count
) : (sizeof(regBuf
) - 1);
923 if (copy_from_user(regBuf
, buffer
, u4CopyBufSize
))
926 if (sscanf(regBuf
, "%x %x", &u4Addr
, &u4Data
) == 2) {
927 iowrite32(u4Data
, ISP_BASE
+ u4Addr
);
928 ISP_LOG("write addr = 0x%08x, data = 0x%08x\n", u4Addr
, ioread32(ISP_BASE
+ u4Addr
));
930 else if (sscanf(regBuf
, "%x", &u4Addr
) == 1) {
931 ISP_LOG("read addr = 0x%08x, data = 0x%08x\n", u4Addr
, ioread32(ISP_BASE
+ u4Addr
));
937 /*******************************************************************************
939 ********************************************************************************/
940 static int __init
mt_isp_init(void)
943 struct proc_dir_entry
*prEntry
;
945 ISP_LOG("[mt_isp_init] \n");
947 if ((ret
= platform_driver_register(&isp_driver
)) < 0) {
948 ISP_ERR("platform_driver_register fail \n");
952 prEntry
= create_proc_entry("driver/isp_reg", 0, NULL
);
954 prEntry
->read_proc
= mt_isp_dump_reg_to_proc
;
955 prEntry
->write_proc
= mt_isp_reg_debug
;
956 ISP_ERR("add /proc/driver/isp_reg entry OK \n");
959 ISP_ERR("add /proc/driver/isp_reg entry fail \n");
965 /*******************************************************************************
967 ********************************************************************************/
968 static void __exit
mt_isp_exit(void)
970 ISP_LOG("[mt_isp_exit] \n");
972 platform_driver_unregister(&isp_driver
);
975 /*******************************************************************************
977 ********************************************************************************/
978 module_init(mt_isp_init
);
979 module_exit(mt_isp_exit
);
980 MODULE_DESCRIPTION("MT6589 ISP driver");
981 MODULE_AUTHOR("ME3");
982 MODULE_LICENSE("GPL");