BU6429AF.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. /*
  2. * BU6429AF voice coil motor driver
  3. *
  4. *
  5. */
  6. #include <linux/i2c.h>
  7. #include <linux/delay.h>
  8. #include <linux/uaccess.h>
  9. #include <linux/fs.h>
  10. #include "lens_info.h"
  11. #define AF_DRVNAME "BU6429AF_DRV"
  12. #define AF_I2C_SLAVE_ADDR 0x18
  13. #define AF_DEBUG
  14. #ifdef AF_DEBUG
  15. #define LOG_INF(format, args...) pr_debug(AF_DRVNAME " [%s] " format, __func__, ##args)
  16. #else
  17. #define LOG_INF(format, args...)
  18. #endif
  19. /* if use ISRC mode, should modify variables in init_setting */
  20. #define USE_ISRC_MODE_S5K2P8_SENSOR
  21. static struct i2c_client *g_pstAF_I2Cclient;
  22. static int *g_pAF_Opened;
  23. static spinlock_t *g_pAF_SpinLock;
  24. static unsigned long g_u4AF_INF;
  25. static unsigned long g_u4AF_MACRO = 1023;
  26. static unsigned long g_u4TargetPosition;
  27. static unsigned long g_u4CurrPosition;
  28. static int s4AF_ReadReg(unsigned short *a_pu2Result)
  29. {
  30. int i4RetValue = 0;
  31. char pBuff[2];
  32. g_pstAF_I2Cclient->addr = AF_I2C_SLAVE_ADDR;
  33. g_pstAF_I2Cclient->addr = g_pstAF_I2Cclient->addr >> 1;
  34. i4RetValue = i2c_master_recv(g_pstAF_I2Cclient, pBuff, 2);
  35. if (i4RetValue < 0) {
  36. LOG_INF("I2C read failed!!\n");
  37. return -1;
  38. }
  39. *a_pu2Result = (((u16) pBuff[0]) << 2) + (pBuff[1]);
  40. return 0;
  41. }
  42. static int s4AF_WriteReg(u16 a_u2Data)
  43. {
  44. int i4RetValue = 0;
  45. #ifdef USE_ISRC_MODE_S5K2P8_SENSOR
  46. char puSendCmd[2] = {(char)(((a_u2Data >> 8) & 0x03) | 0xC4), (char)(a_u2Data & 0xFF)};
  47. #else
  48. char puSendCmd[2] = {(char)(((a_u2Data >> 8) & 0x03) | 0xC0), (char)(a_u2Data & 0xFF)};
  49. #endif
  50. g_pstAF_I2Cclient->addr = AF_I2C_SLAVE_ADDR;
  51. g_pstAF_I2Cclient->addr = g_pstAF_I2Cclient->addr >> 1;
  52. i4RetValue = i2c_master_send(g_pstAF_I2Cclient, puSendCmd, 2);
  53. if (i4RetValue < 0) {
  54. LOG_INF("I2C send failed!!\n");
  55. return -1;
  56. }
  57. return 0;
  58. }
  59. #ifdef USE_ISRC_MODE_S5K2P8_SENSOR
  60. static int init_setting(void)
  61. {
  62. int i4RetValue;
  63. char puSendCmd[2];
  64. char PS, EN, Wx, Mode, Qfact, MSB, resonant_frequency;
  65. /* following 1 variables should be modified by module */
  66. /* resonant_frequency = 106; 1 ~ 255 0.4*106=72.4Hz */
  67. resonant_frequency = 123; /* 79HZ */
  68. /* following 1 variables for ISRC mode */
  69. Mode = 0; /* 0~2 0 0.5x mode ;1 0.8x mode;2 1.0x mode */
  70. /* following 1 variables for Q fact,modified by module */
  71. Qfact = 6; /* if Qfact=15 no need to set Q fact */
  72. PS = 1; /* power state */
  73. EN = 0; /* set to 1 when init */
  74. Mode = 1; /* 0: direct mode 1: ISRC mode */
  75. MSB = (char)((PS << 7) & (EN << 6) & (Mode << 2));
  76. /* convert frequency to register setting */
  77. if (resonant_frequency > 255)
  78. resonant_frequency = 255;
  79. /* step1: power on */
  80. /* puSendCmd[2] = (char)(0xc2), (char)(0x00); */
  81. puSendCmd[0] = (char)(0xc2);
  82. puSendCmd[1] = (char)(0x00);
  83. i4RetValue = i2c_master_send(g_pstAF_I2Cclient, puSendCmd, 2);
  84. if (i4RetValue < 0) {
  85. LOG_INF("I2C send failed!!\n");
  86. return -1;
  87. }
  88. /* step2: set Q fact adjustment */
  89. #if 0
  90. if (Mode == 0) {
  91. char i;
  92. char puQValue[21][2] = {
  93. {(char)(0xe8), (char)(0x3f)},
  94. {(char)(0xe8), (char)(0x3f)},
  95. {(char)(0xe8), (char)(0x6f)},
  96. {(char)(0xe8), (char)(0x6f)},
  97. {(char)(0xe8), (char)(0xc9)},
  98. {(char)(0xe8), (char)(0xc9)},
  99. {(char)(0xe9), (char)(0x38)},
  100. {(char)(0xe9), (char)(0x38)},
  101. {(char)(0xe9), (char)(0x83)},
  102. {(char)(0xe9), (char)(0x83)},
  103. {(char)(0xe9), (char)(0xca)},
  104. {(char)(0xe9), (char)(0xca)},
  105. {(char)(0xe9), (char)(0xef)},
  106. {(char)(0xe9), (char)(0xef)},
  107. {(char)(0xea), (char)(0x00)},
  108. {(char)(0xea), (char)(0x00)},
  109. {(char)(0xea), (char)(0x00)},
  110. {(char)(0xea), (char)(0x00)},
  111. {(char)(0xea), (char)(0x00)},
  112. {(char)(0xea), (char)(0x00)},
  113. {(char)(0xea), (char)(0x00)}
  114. };
  115. for (i = 0; i < 21; i++) {
  116. i4RetValue = i2c_master_send(g_pstAF_I2Cclient, puQValue[i], 2);
  117. if (i4RetValue < 0) {
  118. LOG_INF("I2C send Q fact %d failed!!\n", i);
  119. return -1;
  120. }
  121. }
  122. }
  123. #endif
  124. /* step3: resonant_frequency */
  125. Wx = 0x2;
  126. /* puSendCmd[2] = (char)((MSB) & (Wx << 3)), (char)(resonant_frequency & 0xff); */
  127. puSendCmd[0] = (char)((MSB) & (Wx << 3));
  128. puSendCmd[1] = (char)(resonant_frequency & 0xff);
  129. i4RetValue = i2c_master_send(g_pstAF_I2Cclient, puSendCmd, 2);
  130. if (i4RetValue < 0) {
  131. LOG_INF("I2C send failed!!\n");
  132. return -1;
  133. }
  134. /* step4: set ISRC mode */
  135. Wx = 0x1;
  136. /* puSendCmd[2] = (char)((MSB) & (Wx << 3)), (char)(Mode & 0xff); */
  137. puSendCmd[0] = (char)((MSB) & (Wx << 3));
  138. puSendCmd[1] = (char)(Mode & 0xff);
  139. i4RetValue = i2c_master_send(g_pstAF_I2Cclient, puSendCmd, 2);
  140. if (i4RetValue < 0) {
  141. LOG_INF("I2C send failed!!\n");
  142. return -1;
  143. }
  144. return 0;
  145. }
  146. #endif
  147. static inline int getAFInfo(__user stAF_MotorInfo *pstMotorInfo)
  148. {
  149. stAF_MotorInfo stMotorInfo;
  150. stMotorInfo.u4MacroPosition = g_u4AF_MACRO;
  151. stMotorInfo.u4InfPosition = g_u4AF_INF;
  152. stMotorInfo.u4CurrentPosition = g_u4CurrPosition;
  153. stMotorInfo.bIsSupportSR = 1;
  154. stMotorInfo.bIsMotorMoving = 1;
  155. if (*g_pAF_Opened >= 1)
  156. stMotorInfo.bIsMotorOpen = 1;
  157. else
  158. stMotorInfo.bIsMotorOpen = 0;
  159. if (copy_to_user(pstMotorInfo, &stMotorInfo, sizeof(stAF_MotorInfo)))
  160. LOG_INF("copy to user failed when getting motor information\n");
  161. return 0;
  162. }
  163. static inline int moveAF(unsigned long a_u4Position)
  164. {
  165. int ret = 0;
  166. if ((a_u4Position > g_u4AF_MACRO) || (a_u4Position < g_u4AF_INF)) {
  167. LOG_INF("out of range\n");
  168. return -EINVAL;
  169. }
  170. if (*g_pAF_Opened == 1) {
  171. unsigned short InitPos;
  172. ret = s4AF_ReadReg(&InitPos);
  173. #ifdef USE_ISRC_MODE_S5K2P8_SENSOR
  174. init_setting();
  175. #endif
  176. if (ret == 0) {
  177. LOG_INF("Init Pos %6d\n", InitPos);
  178. spin_lock(g_pAF_SpinLock);
  179. g_u4CurrPosition = (unsigned long)InitPos;
  180. spin_unlock(g_pAF_SpinLock);
  181. } else {
  182. spin_lock(g_pAF_SpinLock);
  183. g_u4CurrPosition = 0;
  184. spin_unlock(g_pAF_SpinLock);
  185. }
  186. spin_lock(g_pAF_SpinLock);
  187. *g_pAF_Opened = 2;
  188. spin_unlock(g_pAF_SpinLock);
  189. }
  190. if (g_u4CurrPosition == a_u4Position)
  191. return 0;
  192. spin_lock(g_pAF_SpinLock);
  193. g_u4TargetPosition = a_u4Position;
  194. spin_unlock(g_pAF_SpinLock);
  195. /* LOG_INF("move [curr] %d [target] %d\n", g_u4CurrPosition, g_u4TargetPosition); */
  196. if (s4AF_WriteReg((unsigned short)g_u4TargetPosition) == 0) {
  197. spin_lock(g_pAF_SpinLock);
  198. g_u4CurrPosition = (unsigned long)g_u4TargetPosition;
  199. spin_unlock(g_pAF_SpinLock);
  200. } else {
  201. LOG_INF("set I2C failed when moving the motor\n");
  202. }
  203. return 0;
  204. }
  205. static inline int setAFInf(unsigned long a_u4Position)
  206. {
  207. spin_lock(g_pAF_SpinLock);
  208. g_u4AF_INF = a_u4Position;
  209. spin_unlock(g_pAF_SpinLock);
  210. return 0;
  211. }
  212. static inline int setAFMacro(unsigned long a_u4Position)
  213. {
  214. spin_lock(g_pAF_SpinLock);
  215. g_u4AF_MACRO = a_u4Position;
  216. spin_unlock(g_pAF_SpinLock);
  217. return 0;
  218. }
  219. /* ////////////////////////////////////////////////////////////// */
  220. long BU6429AF_Ioctl(struct file *a_pstFile, unsigned int a_u4Command, unsigned long a_u4Param)
  221. {
  222. long i4RetValue = 0;
  223. switch (a_u4Command) {
  224. case AFIOC_G_MOTORINFO:
  225. i4RetValue = getAFInfo((__user stAF_MotorInfo *) (a_u4Param));
  226. break;
  227. case AFIOC_T_MOVETO:
  228. i4RetValue = moveAF(a_u4Param);
  229. break;
  230. case AFIOC_T_SETINFPOS:
  231. i4RetValue = setAFInf(a_u4Param);
  232. break;
  233. case AFIOC_T_SETMACROPOS:
  234. i4RetValue = setAFMacro(a_u4Param);
  235. break;
  236. default:
  237. LOG_INF("No CMD\n");
  238. i4RetValue = -EPERM;
  239. break;
  240. }
  241. return i4RetValue;
  242. }
  243. /* Main jobs: */
  244. /* 1.Deallocate anything that "open" allocated in private_data. */
  245. /* 2.Shut down the device on last close. */
  246. /* 3.Only called once on last time. */
  247. /* Q1 : Try release multiple times. */
  248. int BU6429AF_Release(struct inode *a_pstInode, struct file *a_pstFile)
  249. {
  250. LOG_INF("Start\n");
  251. if (*g_pAF_Opened == 2) {
  252. char puSendCmd[2];
  253. puSendCmd[0] = (char)(0x00);
  254. puSendCmd[1] = (char)(0x00);
  255. i2c_master_send(g_pstAF_I2Cclient, puSendCmd, 2);
  256. LOG_INF("Wait\n");
  257. /*s4AF_WriteReg(200);
  258. msleep(20);
  259. s4AF_WriteReg(100);
  260. msleep(20);*/
  261. }
  262. if (*g_pAF_Opened) {
  263. LOG_INF("Free\n");
  264. spin_lock(g_pAF_SpinLock);
  265. *g_pAF_Opened = 0;
  266. spin_unlock(g_pAF_SpinLock);
  267. }
  268. LOG_INF("End\n");
  269. return 0;
  270. }
  271. void BU6429AF_SetI2Cclient(struct i2c_client *pstAF_I2Cclient, spinlock_t *pAF_SpinLock, int *pAF_Opened)
  272. {
  273. g_pstAF_I2Cclient = pstAF_I2Cclient;
  274. g_pAF_SpinLock = pAF_SpinLock;
  275. g_pAF_Opened = pAF_Opened;
  276. }