| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405 |
- /*
- * MAIN AF voice coil motor driver
- *
- *
- */
- #include <linux/module.h>
- #include <linux/i2c.h>
- #include <linux/delay.h>
- #include <linux/platform_device.h>
- #include <linux/cdev.h>
- #include <linux/uaccess.h>
- #include <linux/fs.h>
- #include <asm/atomic.h>
- #ifdef CONFIG_COMPAT
- #include <linux/compat.h>
- #endif
- #include "lens_info.h"
- #include "lens_list.h"
- #define AF_DRVNAME "MAINAF"
- #if defined(CONFIG_MTK_LEGACY)
- #define I2C_CONFIG_SETTING 1
- #elif defined(CONFIG_OF)
- #define I2C_CONFIG_SETTING 2 /* device tree */
- #else
- #define I2C_CONFIG_SETTING 1
- #endif
- #if I2C_CONFIG_SETTING == 1
- #define LENS_I2C_BUSNUM 0
- #define I2C_REGISTER_ID 0x28
- #endif
- #define PLATFORM_DRIVER_NAME "lens_actuator_main_af"
- #define AF_DRIVER_CLASS_NAME "actuatordrv_main_af"
- #if I2C_CONFIG_SETTING == 1
- static struct i2c_board_info kd_lens_dev __initdata = {
- I2C_BOARD_INFO(AF_DRVNAME, I2C_REGISTER_ID)
- };
- #endif
- #define AF_DEBUG
- #ifdef AF_DEBUG
- #define LOG_INF(format, args...) pr_debug(AF_DRVNAME " [%s] " format, __func__, ##args)
- #else
- #define LOG_INF(format, args...)
- #endif
- static stAF_DrvList g_stAF_DrvList[MAX_NUM_OF_LENS] = {
- #ifdef CONFIG_MTK_LENS_WV511AAF_SUPPORT
- {1, AFDRV_WV511AAF, WV511AAF_SetI2Cclient, WV511AAF_Ioctl, WV511AAF_Release},
- #endif
- #ifdef CONFIG_MTK_LENS_BU6424AF_SUPPORT
- {1, AFDRV_BU6424AF, BU6424AF_SetI2Cclient, BU6424AF_Ioctl, BU6424AF_Release},
- #endif
- #ifdef CONFIG_MTK_LENS_BU6429AF_SUPPORT
- {1, AFDRV_BU6429AF, BU6429AF_SetI2Cclient, BU6429AF_Ioctl, BU6429AF_Release},
- #endif
- #ifdef CONFIG_MTK_LENS_DW9714AF_SUPPORT
- {1, AFDRV_DW9714AF, DW9714AF_SetI2Cclient, DW9714AF_Ioctl, DW9714AF_Release},
- #endif
- #ifdef CONFIG_MTK_LENS_DW9814AF_SUPPORT
- {1, AFDRV_DW9814AF, DW9814AF_SetI2Cclient, DW9814AF_Ioctl, DW9814AF_Release},
- #endif
- #ifdef CONFIG_MTK_LENS_DW9718AF_SUPPORT
- {1, AFDRV_DW9718AF, DW9718AF_SetI2Cclient, DW9718AF_Ioctl, DW9718AF_Release},
- #endif
- #ifdef CONFIG_MTK_LENS_LC898122AF_SUPPORT
- {1, AFDRV_LC898122AF, LC898122AF_SetI2Cclient, LC898122AF_Ioctl, LC898122AF_Release},
- #endif
- #ifdef CONFIG_MTK_LENS_LC898212AF_SUPPORT
- {1, AFDRV_LC898212AF, LC898212AF_SetI2Cclient, LC898212AF_Ioctl, LC898212AF_Release},
- #endif
- #ifdef CONFIG_MTK_LENS_LC898212XDAF_SUPPORT
- {1, AFDRV_LC898212XDAF, LC898212XDAF_SetI2Cclient, LC898212XDAF_Ioctl, LC898212XDAF_Release},
- #endif
- #ifdef CONFIG_MTK_LENS_FM50AF_SUPPORT
- {1, AFDRV_FM50AF, FM50AF_SetI2Cclient, FM50AF_Ioctl, FM50AF_Release},
- #endif
- #ifdef CONFIG_MTK_LENS_AD5820AF_SUPPORT
- {1, AFDRV_AD5820AF, AD5820AF_SetI2Cclient, AD5820AF_Ioctl, AD5820AF_Release},
- #endif
-
- #ifdef CONFIG_MTK_LENS_AK7371AF_SUPPORT
- {1, AFDRV_AK7371AF, AK7371AF_SetI2Cclient, AK7371AF_Ioctl, AK7371AF_Release},
- #endif
- };
- static stAF_DrvList *g_pstAF_CurDrv;
- static spinlock_t g_AF_SpinLock;
- static int g_s4AF_Opened;
- static struct i2c_client *g_pstAF_I2Cclient;
- static dev_t g_AF_devno;
- static struct cdev *g_pAF_CharDrv;
- static struct class *actuator_class;
- static long AF_SetMotorName(__user stAF_MotorName * pstMotorName)
- {
- long i4RetValue = -1;
- int i;
- stAF_MotorName stMotorName;
- if (copy_from_user(&stMotorName , pstMotorName, sizeof(stAF_MotorName)))
- LOG_INF("copy to user failed when getting motor information\n");
- LOG_INF("Set Motor Name : %s\n", stMotorName.uMotorName);
- for (i = 0; i < MAX_NUM_OF_LENS; i++) {
- if (g_stAF_DrvList[i].uEnable != 1)
- break;
- LOG_INF("Search Motor Name : %s\n", g_stAF_DrvList[i].uDrvName);
- if (strcmp(stMotorName.uMotorName, g_stAF_DrvList[i].uDrvName) == 0) {
- g_pstAF_CurDrv = &g_stAF_DrvList[i];
- g_pstAF_CurDrv->pAF_SetI2Cclient(g_pstAF_I2Cclient, &g_AF_SpinLock, &g_s4AF_Opened);
- i4RetValue = 1;
- break;
- }
- }
- return i4RetValue;
- }
- /* ////////////////////////////////////////////////////////////// */
- static long AF_Ioctl(struct file *a_pstFile, unsigned int a_u4Command, unsigned long a_u4Param)
- {
- long i4RetValue = 0;
- switch (a_u4Command) {
- case AFIOC_S_SETDRVNAME:
- i4RetValue = AF_SetMotorName((__user stAF_MotorName *)(a_u4Param));
- break;
- default:
- if (g_pstAF_CurDrv)
- i4RetValue = g_pstAF_CurDrv->pAF_Ioctl(a_pstFile, a_u4Command, a_u4Param);
- break;
- }
- return i4RetValue;
- }
- /* Main jobs: */
- /* 1.check for device-specified errors, device not ready. */
- /* 2.Initialize the device if it is opened for the first time. */
- /* 3.Update f_op pointer. */
- /* 4.Fill data structures into private_data */
- /* CAM_RESET */
- static int AF_Open(struct inode *a_pstInode, struct file *a_pstFile)
- {
- LOG_INF("Start\n");
- if (g_s4AF_Opened) {
- LOG_INF("The device is opened\n");
- return -EBUSY;
- }
- spin_lock(&g_AF_SpinLock);
- g_s4AF_Opened = 1;
- spin_unlock(&g_AF_SpinLock);
- LOG_INF("End\n");
- return 0;
- }
- /* Main jobs: */
- /* 1.Deallocate anything that "open" allocated in private_data. */
- /* 2.Shut down the device on last close. */
- /* 3.Only called once on last time. */
- /* Q1 : Try release multiple times. */
- static int AF_Release(struct inode *a_pstInode, struct file *a_pstFile)
- {
- LOG_INF("Start\n");
- if (g_pstAF_CurDrv) {
- g_pstAF_CurDrv->pAF_Release(a_pstInode, a_pstFile);
- g_pstAF_CurDrv = NULL;
- } else {
- spin_lock(&g_AF_SpinLock);
- g_s4AF_Opened = 0;
- spin_unlock(&g_AF_SpinLock);
- }
- LOG_INF("End\n");
- return 0;
- }
- static const struct file_operations g_stAF_fops = {
- .owner = THIS_MODULE,
- .open = AF_Open,
- .release = AF_Release,
- .unlocked_ioctl = AF_Ioctl,
- #ifdef CONFIG_COMPAT
- .compat_ioctl = AF_Ioctl,
- #endif
- };
- static inline int Register_AF_CharDrv(void)
- {
- struct device *vcm_device = NULL;
- LOG_INF("Start\n");
- /* Allocate char driver no. */
- if (alloc_chrdev_region(&g_AF_devno, 0, 1, AF_DRVNAME)) {
- LOG_INF("Allocate device no failed\n");
- return -EAGAIN;
- }
- /* Allocate driver */
- g_pAF_CharDrv = cdev_alloc();
- if (NULL == g_pAF_CharDrv) {
- unregister_chrdev_region(g_AF_devno, 1);
- LOG_INF("Allocate mem for kobject failed\n");
- return -ENOMEM;
- }
- /* Attatch file operation. */
- cdev_init(g_pAF_CharDrv, &g_stAF_fops);
- g_pAF_CharDrv->owner = THIS_MODULE;
- /* Add to system */
- if (cdev_add(g_pAF_CharDrv, g_AF_devno, 1)) {
- LOG_INF("Attatch file operation failed\n");
- unregister_chrdev_region(g_AF_devno, 1);
- return -EAGAIN;
- }
- actuator_class = class_create(THIS_MODULE, AF_DRIVER_CLASS_NAME);
- if (IS_ERR(actuator_class)) {
- int ret = PTR_ERR(actuator_class);
- LOG_INF("Unable to create class, err = %d\n", ret);
- return ret;
- }
- vcm_device = device_create(actuator_class, NULL, g_AF_devno, NULL, AF_DRVNAME);
- if (NULL == vcm_device)
- return -EIO;
- LOG_INF("End\n");
- return 0;
- }
- static inline void Unregister_AF_CharDrv(void)
- {
- LOG_INF("Start\n");
- /* Release char driver */
- cdev_del(g_pAF_CharDrv);
- unregister_chrdev_region(g_AF_devno, 1);
- device_destroy(actuator_class, g_AF_devno);
- class_destroy(actuator_class);
- LOG_INF("End\n");
- }
- /* //////////////////////////////////////////////////////////////////// */
- static int AF_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id);
- static int AF_i2c_remove(struct i2c_client *client);
- static const struct i2c_device_id AF_i2c_id[] = { {AF_DRVNAME, 0}, {} };
- /* Compatible name must be the same with that defined in codegen.dws and cust_i2c.dtsi */
- /* TOOL : kernel-3.10\tools\dct */
- /* PATH : vendor\mediatek\proprietary\custom\#project#\kernel\dct\dct */
- #if I2C_CONFIG_SETTING == 2
- static const struct of_device_id MAINAF_of_match[] = {
- {.compatible = "mediatek,CAMERA_MAIN_AF"},
- {},
- };
- #endif
- static struct i2c_driver AF_i2c_driver = {
- .probe = AF_i2c_probe,
- .remove = AF_i2c_remove,
- .driver.name = AF_DRVNAME,
- #if I2C_CONFIG_SETTING == 2
- .driver.of_match_table = MAINAF_of_match,
- #endif
- .id_table = AF_i2c_id,
- };
- static int AF_i2c_remove(struct i2c_client *client)
- {
- return 0;
- }
- /* Kirby: add new-style driver {*/
- static int AF_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
- {
- int i4RetValue = 0;
- LOG_INF("Start\n");
- /* Kirby: add new-style driver { */
- g_pstAF_I2Cclient = client;
- /* Register char driver */
- i4RetValue = Register_AF_CharDrv();
- if (i4RetValue) {
- LOG_INF(" register char device failed!\n");
- return i4RetValue;
- }
- spin_lock_init(&g_AF_SpinLock);
- LOG_INF("Attached!!\n");
- return 0;
- }
- static int AF_probe(struct platform_device *pdev)
- {
- return i2c_add_driver(&AF_i2c_driver);
- }
- static int AF_remove(struct platform_device *pdev)
- {
- i2c_del_driver(&AF_i2c_driver);
- return 0;
- }
- static int AF_suspend(struct platform_device *pdev, pm_message_t mesg)
- {
- return 0;
- }
- static int AF_resume(struct platform_device *pdev)
- {
- return 0;
- }
- /* platform structure */
- static struct platform_driver g_stAF_Driver = {
- .probe = AF_probe,
- .remove = AF_remove,
- .suspend = AF_suspend,
- .resume = AF_resume,
- .driver = {
- .name = PLATFORM_DRIVER_NAME,
- .owner = THIS_MODULE,
- }
- };
- static struct platform_device g_stAF_device = {
- .name = PLATFORM_DRIVER_NAME,
- .id = 0,
- .dev = {}
- };
- static int __init MAINAF_i2C_init(void)
- {
- #if I2C_CONFIG_SETTING == 1
- i2c_register_board_info(LENS_I2C_BUSNUM, &kd_lens_dev, 1);
- #endif
- if (platform_device_register(&g_stAF_device)) {
- LOG_INF("failed to register AF driver\n");
- return -ENODEV;
- }
- if (platform_driver_register(&g_stAF_Driver)) {
- LOG_INF("Failed to register AF driver\n");
- return -ENODEV;
- }
- return 0;
- }
- static void __exit MAINAF_i2C_exit(void)
- {
- platform_driver_unregister(&g_stAF_Driver);
- }
- module_init(MAINAF_i2C_init);
- module_exit(MAINAF_i2C_exit);
- MODULE_DESCRIPTION("MAINAF lens module driver");
- MODULE_AUTHOR("KY Chen <ky.chen@Mediatek.com>");
- MODULE_LICENSE("GPL");
|