8 #include <linux/platform_device.h>
9 #include <linux/delay.h>
10 #include <linux/cdev.h>
11 #include <linux/uaccess.h>
12 #include <linux/slab.h>
14 #include "kd_camera_hw.h"
16 #include "cam_cal_define.h"
18 #include "dummy_cam_cal.h"
19 #include <asm/system.h> // for SMP
21 //#define CAM_CALGETDLT_DEBUG //test
22 //#define CAM_CAL_DEBUG //test
24 #define CAM_CALDB printk
26 #define CAM_CALDB(x,...)
30 static DEFINE_SPINLOCK(g_CAM_CALLock
); // for SMP
32 #define CAM_CAL_I2C_BUSNUM 1
33 static struct i2c_board_info __initdata kd_cam_cal_dev
={ I2C_BOARD_INFO("dummy_cam_cal", 0xAB>>1)}; //make dummy_eeprom co-exist
35 /*******************************************************************************
37 ********************************************************************************/
38 #define CAM_CAL_ICS_REVISION 1 //seanlin111208
39 /*******************************************************************************
41 ********************************************************************************/
42 #define CAM_CAL_DRVNAME "dummy_cam_cal"
43 #define CAM_CAL_I2C_GROUP_ID 0
44 /*******************************************************************************
46 ********************************************************************************/
48 static unsigned short g_pu2Normal_i2c[] = {S24CS64A_DEVICE_ID , I2C_CLIENT_END};
49 static unsigned short g_u2Ignore = I2C_CLIENT_END;
50 static struct i2c_client_address_data g_stCAM_CAL_Addr_data = {
51 .normal_i2c = g_pu2Normal_i2c,
55 static struct i2c_client
* g_pstI2Cclient
= NULL
;
57 //81 is used for V4L driver
58 static dev_t g_CAM_CALdevno
= MKDEV(CAM_CAL_DEV_MAJOR_NUMBER
,0);
59 static struct cdev
* g_pCAM_CAL_CharDrv
= NULL
;
60 //static spinlock_t g_CAM_CALLock;
61 static struct class *CAM_CAL_class
= NULL
;
62 static atomic_t g_CAM_CALatomic
;
63 /*******************************************************************************
65 ********************************************************************************/
66 // maximun read length is limited at "I2C_FIFO_SIZE" in I2c-mt65xx.c which is 8 bytes
67 int iWriteCAM_CAL(u16 a_u2Addr
, u32 a_u4Bytes
, u8
* puDataInBytes
)
71 char puSendCmd
[8] = {(char)(a_u2Addr
>> 8) , (char)(a_u2Addr
& 0xFF) ,
75 CAM_CALDB("[CAM_CAL] exceed I2c-mt65xx.c 8 bytes limitation (include address 2 Byte)\n");
79 for(u4Index
= 0 ; u4Index
< a_u4Bytes
; u4Index
+= 1 )
81 puSendCmd
[(u4Index
+ 2)] = puDataInBytes
[u4Index
];
84 i4RetValue
= i2c_master_send(g_pstI2Cclient
, puSendCmd
, (a_u4Bytes
+ 2));
85 if (i4RetValue
!= (a_u4Bytes
+ 2))
87 CAM_CALDB("[CAM_CAL] I2C write failed!! \n");
90 mdelay(10); //for tWR singnal --> write data form buffer to memory.
92 //CAM_CALDB("[CAM_CAL] iWriteCAM_CAL done!! \n");
97 // maximun read length is limited at "I2C_FIFO_SIZE" in I2c-mt65xx.c which is 8 bytes
98 int iReadCAM_CAL(u16 a_u2Addr
, u32 ui4_length
, u8
* a_puBuff
)
101 char puReadCmd
[2] = {(char)(a_u2Addr
>> 8) , (char)(a_u2Addr
& 0xFF)};
103 //CAM_CALDB("[CAM_CAL] iReadCAM_CAL!! \n");
107 CAM_CALDB("[CAM_CAL] exceed I2c-mt65xx.c 8 bytes limitation\n");
110 spin_lock(&g_CAM_CALLock
); //for SMP
111 g_pstI2Cclient
->addr
= g_pstI2Cclient
->addr
& (I2C_MASK_FLAG
| I2C_WR_FLAG
);
112 spin_unlock(&g_CAM_CALLock
); // for SMP
114 //CAM_CALDB("[EERPOM] i2c_master_send \n");
115 i4RetValue
= i2c_master_send(g_pstI2Cclient
, puReadCmd
, 2);
118 CAM_CALDB("[CAM_CAL] I2C send read address failed!! \n");
122 //CAM_CALDB("[EERPOM] i2c_master_recv \n");
123 i4RetValue
= i2c_master_recv(g_pstI2Cclient
, (char *)a_puBuff
, ui4_length
);
124 if (i4RetValue
!= ui4_length
)
126 CAM_CALDB("[CAM_CAL] I2C read data failed!! \n");
129 spin_lock(&g_CAM_CALLock
); //for SMP
130 g_pstI2Cclient
->addr
= g_pstI2Cclient
->addr
& I2C_MASK_FLAG
;
131 spin_unlock(&g_CAM_CALLock
); // for SMP
133 //CAM_CALDB("[CAM_CAL] iReadCAM_CAL done!! \n");
138 static int iWriteData(unsigned int ui4_offset
, unsigned int ui4_length
, unsigned char * pinputdata
)
141 int i4ResidueDataLength
;
146 CAM_CALDB("[CAM_CAL] iWriteData\n" );
149 if (ui4_offset
+ ui4_length
>= 0x2000)
151 CAM_CALDB("[CAM_CAL] Write Error!! S-24CS64A not supprt address >= 0x2000!! \n" );
155 i4ResidueDataLength
= (int)ui4_length
;
156 u4CurrentOffset
= ui4_offset
;
158 CAM_CALDB("[CAM_CAL] iWriteData u4CurrentOffset is %d \n",u4CurrentOffset
);
161 if(i4ResidueDataLength
>= 6)
163 i4RetValue
= iWriteCAM_CAL((u16
)u4CurrentOffset
, 6, pBuff
);
166 CAM_CALDB("[CAM_CAL] I2C iWriteData failed!! \n");
170 i4ResidueDataLength
-= 6;
171 u4CurrentOffset
= ui4_offset
+ u4IncOffset
;
172 pBuff
= pinputdata
+ u4IncOffset
;
176 i4RetValue
= iWriteCAM_CAL((u16
)u4CurrentOffset
, i4ResidueDataLength
, pBuff
);
179 CAM_CALDB("[CAM_CAL] I2C iWriteData failed!! \n");
183 i4ResidueDataLength
-= 6;
184 u4CurrentOffset
= ui4_offset
+ u4IncOffset
;
185 pBuff
= pinputdata
+ u4IncOffset
;
188 }while (i4ResidueDataLength
> 0);
189 CAM_CALDB("[CAM_CAL] iWriteData done\n" );
194 //int iReadData(stCAM_CAL_INFO_STRUCT * st_pOutputBuffer)
195 static int iReadData(unsigned int ui4_offset
, unsigned int ui4_length
, unsigned char * pinputdata
)
198 int i4ResidueDataLength
;
202 CAM_CALDB("[CAM_CAL] iReadData \n" );
204 if (ui4_offset
+ ui4_length
>= 0x2000)
206 CAM_CALDB("[CAM_CAL] Read Error!! S-24CS64A not supprt address >= 0x2000!! \n" );
210 i4ResidueDataLength
= (int)ui4_length
;
211 u4CurrentOffset
= ui4_offset
;
215 if(i4ResidueDataLength
>= 8)
217 i4RetValue
= iReadCAM_CAL((u16
)u4CurrentOffset
, 8, pBuff
);
220 CAM_CALDB("[CAM_CAL] I2C iReadData failed!! \n");
224 i4ResidueDataLength
-= 8;
225 u4CurrentOffset
= ui4_offset
+ u4IncOffset
;
226 pBuff
= pinputdata
+ u4IncOffset
;
230 i4RetValue
= iReadCAM_CAL((u16
)u4CurrentOffset
, i4ResidueDataLength
, pBuff
);
233 CAM_CALDB("[CAM_CAL] I2C iReadData failed!! \n");
237 i4ResidueDataLength
-= 8;
238 u4CurrentOffset
= ui4_offset
+ u4IncOffset
;
239 pBuff
= pinputdata
+ u4IncOffset
;
242 }while (i4ResidueDataLength
> 0);
243 //fix warning MSG CAM_CALDB("[CAM_CAL] iReadData finial address is %d length is %d buffer address is 0x%x\n",u4CurrentOffset, i4ResidueDataLength, pBuff);
244 CAM_CALDB("[CAM_CAL] iReadData done\n" );
249 /*******************************************************************************
251 ********************************************************************************/
252 #define NEW_UNLOCK_IOCTL
253 #ifndef NEW_UNLOCK_IOCTL
254 static int CAM_CAL_Ioctl(struct inode
* a_pstInode
,
255 struct file
* a_pstFile
,
256 unsigned int a_u4Command
,
257 unsigned long a_u4Param
)
259 static long CAM_CAL_Ioctl(
261 unsigned int a_u4Command
,
262 unsigned long a_u4Param
268 u8
* pWorkingBuff
= NULL
;
269 stCAM_CAL_INFO_STRUCT
*ptempbuf
;
271 #ifdef CAM_CALGETDLT_DEBUG
272 struct timeval ktv1
, ktv2
;
273 unsigned long TimeIntervalUS
;
276 if(_IOC_NONE
== _IOC_DIR(a_u4Command
))
281 pBuff
= (u8
*)kmalloc(sizeof(stCAM_CAL_INFO_STRUCT
),GFP_KERNEL
);
285 CAM_CALDB("[CAM_CAL] ioctl allocate mem failed\n");
289 if(_IOC_WRITE
& _IOC_DIR(a_u4Command
))
291 if(copy_from_user((u8
*) pBuff
, (u8
*) a_u4Param
, sizeof(stCAM_CAL_INFO_STRUCT
)))
292 { //get input structure address
294 CAM_CALDB("[CAM_CAL] ioctl copy from user failed\n");
300 ptempbuf
= (stCAM_CAL_INFO_STRUCT
*)pBuff
;
301 pWorkingBuff
= (u8
*)kmalloc(ptempbuf
->u4Length
,GFP_KERNEL
);
302 if(NULL
== pWorkingBuff
)
305 CAM_CALDB("[CAM_CAL] ioctl allocate mem failed\n");
308 //fix warning MSG CAM_CALDB("[CAM_CAL] init Working buffer address 0x%x command is 0x%08x\n", pWorkingBuff, a_u4Command);
311 if(copy_from_user((u8
*)pWorkingBuff
, (u8
*)ptempbuf
->pu1Params
, ptempbuf
->u4Length
))
315 CAM_CALDB("[CAM_CAL] ioctl copy from user failed\n");
321 case CAM_CALIOC_S_WRITE
:
322 CAM_CALDB("[CAM_CAL] Write CMD \n");
323 #ifdef CAM_CALGETDLT_DEBUG
324 do_gettimeofday(&ktv1
);
326 i4RetValue
= iWriteData((u16
)ptempbuf
->u4Offset
, ptempbuf
->u4Length
, pWorkingBuff
);
327 #ifdef CAM_CALGETDLT_DEBUG
328 do_gettimeofday(&ktv2
);
329 if(ktv2
.tv_sec
> ktv1
.tv_sec
)
331 TimeIntervalUS
= ktv1
.tv_usec
+ 1000000 - ktv2
.tv_usec
;
335 TimeIntervalUS
= ktv2
.tv_usec
- ktv1
.tv_usec
;
337 printk("Write data %d bytes take %lu us\n",ptempbuf
->u4Length
, TimeIntervalUS
);
340 case CAM_CALIOC_G_READ
:
341 CAM_CALDB("[CAM_CAL] Read CMD \n");
342 #ifdef CAM_CALGETDLT_DEBUG
343 do_gettimeofday(&ktv1
);
345 CAM_CALDB("[CAM_CAL] offset %d \n", ptempbuf
->u4Offset
);
346 CAM_CALDB("[CAM_CAL] length %d \n", ptempbuf
->u4Length
);
347 //fix warning MSG CAM_CALDB("[CAM_CAL] Before read Working buffer address 0x%x \n", pWorkingBuff);
349 i4RetValue
= iReadData((u16
)ptempbuf
->u4Offset
, ptempbuf
->u4Length
, pWorkingBuff
);
350 //fix warning MSG CAM_CALDB("[CAM_CAL] After read Working buffer address 0x%x \n", pWorkingBuff);
353 #ifdef CAM_CALGETDLT_DEBUG
354 do_gettimeofday(&ktv2
);
355 if(ktv2
.tv_sec
> ktv1
.tv_sec
)
357 TimeIntervalUS
= ktv1
.tv_usec
+ 1000000 - ktv2
.tv_usec
;
361 TimeIntervalUS
= ktv2
.tv_usec
- ktv1
.tv_usec
;
363 printk("Read data %d bytes take %lu us\n",ptempbuf
->u4Length
, TimeIntervalUS
);
368 CAM_CALDB("[CAM_CAL] No CMD \n");
373 if(_IOC_READ
& _IOC_DIR(a_u4Command
))
375 //copy data to user space buffer, keep other input paremeter unchange.
376 CAM_CALDB("[CAM_CAL] to user length %d \n", ptempbuf
->u4Length
);
377 //fix warning MSG CAM_CALDB("[CAM_CAL] to user Working buffer address 0x%x \n", pWorkingBuff);
378 if(copy_to_user((u8 __user
*) ptempbuf
->pu1Params
, (u8
*)pWorkingBuff
, ptempbuf
->u4Length
))
382 CAM_CALDB("[CAM_CAL] ioctl copy to user failed\n");
393 static u32 g_u4Opened
= 0;
396 // 1.check for device-specified errors, device not ready.
397 // 2.Initialize the device if it is opened for the first time.
398 static int CAM_CAL_Open(struct inode
* a_pstInode
, struct file
* a_pstFile
)
400 CAM_CALDB("[S24CAM_CAL] CAM_CAL_Open\n");
401 spin_lock(&g_CAM_CALLock
);
404 spin_unlock(&g_CAM_CALLock
);
410 atomic_set(&g_CAM_CALatomic
,0);
412 spin_unlock(&g_CAM_CALLock
);
414 //#if defined(MT6572)
417 //if(TRUE != hwPowerOn(MT65XX_POWER_LDO_VCAMA, VOL_2800, "S24CS64A"))
419 // CAM_CALDB("[CAM_CAL] Fail to enable analog gain\n");
428 // 1.Deallocate anything that "open" allocated in private_data.
429 // 2.Shut down the device on last close.
430 // 3.Only called once on last time.
431 // Q1 : Try release multiple times.
432 static int CAM_CAL_Release(struct inode
* a_pstInode
, struct file
* a_pstFile
)
434 spin_lock(&g_CAM_CALLock
);
438 atomic_set(&g_CAM_CALatomic
,0);
440 spin_unlock(&g_CAM_CALLock
);
445 static const struct file_operations g_stCAM_CAL_fops
=
447 .owner
= THIS_MODULE
,
448 .open
= CAM_CAL_Open
,
449 .release
= CAM_CAL_Release
,
450 //.ioctl = CAM_CAL_Ioctl
451 .unlocked_ioctl
= CAM_CAL_Ioctl
454 #define CAM_CAL_DYNAMIC_ALLOCATE_DEVNO 1
455 inline static int RegisterCAM_CALCharDrv(void)
457 struct device
* CAM_CAL_device
= NULL
;
459 #if CAM_CAL_DYNAMIC_ALLOCATE_DEVNO
460 if( alloc_chrdev_region(&g_CAM_CALdevno
, 0, 1,CAM_CAL_DRVNAME
) )
462 CAM_CALDB("[CAM_CAL] Allocate device no failed\n");
467 if( register_chrdev_region( g_CAM_CALdevno
, 1 , CAM_CAL_DRVNAME
) )
469 CAM_CALDB("[CAM_CAL] Register device no failed\n");
476 g_pCAM_CAL_CharDrv
= cdev_alloc();
478 if(NULL
== g_pCAM_CAL_CharDrv
)
480 unregister_chrdev_region(g_CAM_CALdevno
, 1);
482 CAM_CALDB("[CAM_CAL] Allocate mem for kobject failed\n");
487 //Attatch file operation.
488 cdev_init(g_pCAM_CAL_CharDrv
, &g_stCAM_CAL_fops
);
490 g_pCAM_CAL_CharDrv
->owner
= THIS_MODULE
;
493 if(cdev_add(g_pCAM_CAL_CharDrv
, g_CAM_CALdevno
, 1))
495 CAM_CALDB("[CAM_CAL] Attatch file operation failed\n");
497 unregister_chrdev_region(g_CAM_CALdevno
, 1);
502 CAM_CAL_class
= class_create(THIS_MODULE
, "CAM_CALdrv");
503 if (IS_ERR(CAM_CAL_class
)) {
504 int ret
= PTR_ERR(CAM_CAL_class
);
505 CAM_CALDB("Unable to create class, err = %d\n", ret
);
508 CAM_CAL_device
= device_create(CAM_CAL_class
, NULL
, g_CAM_CALdevno
, NULL
, CAM_CAL_DRVNAME
);
513 inline static void UnregisterCAM_CALCharDrv(void)
515 //Release char driver
516 cdev_del(g_pCAM_CAL_CharDrv
);
518 unregister_chrdev_region(g_CAM_CALdevno
, 1);
520 device_destroy(CAM_CAL_class
, g_CAM_CALdevno
);
521 class_destroy(CAM_CAL_class
);
525 //////////////////////////////////////////////////////////////////////
526 #ifndef CAM_CAL_ICS_REVISION
527 static int CAM_CAL_i2c_detect(struct i2c_client
*client
, int kind
, struct i2c_board_info
*info
);
529 static int CAM_CAL_i2c_detect(struct i2c_client
*client
, struct i2c_board_info
*info
);
532 static int CAM_CAL_i2c_probe(struct i2c_client
*client
, const struct i2c_device_id
*id
);
533 static int CAM_CAL_i2c_remove(struct i2c_client
*);
535 static const struct i2c_device_id CAM_CAL_i2c_id
[] = {{CAM_CAL_DRVNAME
,0},{}};
536 #if 0 //test110314 Please use the same I2C Group ID as Sensor
537 static unsigned short force
[] = {CAM_CAL_I2C_GROUP_ID
, S24CS64A_DEVICE_ID
, I2C_CLIENT_END
, I2C_CLIENT_END
};
539 //static unsigned short force[] = {CAM_CAL_I2C_GROUP_ID, S24CS64A_DEVICE_ID, I2C_CLIENT_END, I2C_CLIENT_END};
541 //static const unsigned short * const forces[] = { force, NULL };
542 //static struct i2c_client_address_data addr_data = { .forces = forces,};
545 static struct i2c_driver CAM_CAL_i2c_driver
= {
546 .probe
= CAM_CAL_i2c_probe
,
547 .remove
= CAM_CAL_i2c_remove
,
548 // .detect = CAM_CAL_i2c_detect,
549 .driver
.name
= CAM_CAL_DRVNAME
,
550 .id_table
= CAM_CAL_i2c_id
,
553 #ifndef CAM_CAL_ICS_REVISION
554 static int CAM_CAL_i2c_detect(struct i2c_client
*client
, int kind
, struct i2c_board_info
*info
) {
555 strcpy(info
->type
, CAM_CAL_DRVNAME
);
559 static int CAM_CAL_i2c_probe(struct i2c_client
*client
, const struct i2c_device_id
*id
) {
561 CAM_CALDB("[CAM_CAL] Attach I2C \n");
562 // spin_lock_init(&g_CAM_CALLock);
564 //get sensor i2c client
565 spin_lock(&g_CAM_CALLock
); //for SMP
566 g_pstI2Cclient
= client
;
567 g_pstI2Cclient
->addr
= S24CS64A_DEVICE_ID
>>1;
568 spin_unlock(&g_CAM_CALLock
); // for SMP
570 CAM_CALDB("[CAM_CAL] g_pstI2Cclient->addr = 0x%8x \n",g_pstI2Cclient
->addr
);
571 //Register char driver
572 i4RetValue
= RegisterCAM_CALCharDrv();
575 CAM_CALDB("[CAM_CAL] register char device failed!\n");
580 CAM_CALDB("[CAM_CAL] Attached!! \n");
584 static int CAM_CAL_i2c_remove(struct i2c_client
*client
)
589 static int CAM_CAL_probe(struct platform_device
*pdev
)
591 return i2c_add_driver(&CAM_CAL_i2c_driver
);
594 static int CAM_CAL_remove(struct platform_device
*pdev
)
596 i2c_del_driver(&CAM_CAL_i2c_driver
);
600 // platform structure
601 static struct platform_driver g_stCAM_CAL_Driver
= {
602 .probe
= CAM_CAL_probe
,
603 .remove
= CAM_CAL_remove
,
605 .name
= CAM_CAL_DRVNAME
,
606 .owner
= THIS_MODULE
,
611 static struct platform_device g_stCAM_CAL_Device
= {
612 .name
= CAM_CAL_DRVNAME
,
618 static int __init
CAM_CAL_i2C_init(void)
620 i2c_register_board_info(CAM_CAL_I2C_BUSNUM
, &kd_cam_cal_dev
, 1);
621 if(platform_driver_register(&g_stCAM_CAL_Driver
)){
622 CAM_CALDB("failed to register CAM_CAL driver\n");
626 if (platform_device_register(&g_stCAM_CAL_Device
))
628 CAM_CALDB("failed to register CAM_CAL driver\n");
635 static void __exit
CAM_CAL_i2C_exit(void)
637 platform_driver_unregister(&g_stCAM_CAL_Driver
);
640 module_init(CAM_CAL_i2C_init
);
641 module_exit(CAM_CAL_i2C_exit
);
643 MODULE_DESCRIPTION("CAM_CAL driver");
644 MODULE_AUTHOR("Sean Lin <Sean.Lin@Mediatek.com>");
645 MODULE_LICENSE("GPL");