Advertisement
Guest User

ov7740.c

a guest
Mar 13th, 2015
564
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 41.32 KB | None | 0 0
  1. /*
  2. * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved.
  3. */
  4.  
  5. /*
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10.  
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15.  
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. */
  20.  
  21. #define DEBUG 8
  22.  
  23. #include <linux/module.h>
  24. #include <linux/init.h>
  25. #include <linux/slab.h>
  26. #include <linux/ctype.h>
  27. #include <linux/types.h>
  28. #include <linux/delay.h>
  29. #include <linux/clk.h>
  30. #include <linux/of_device.h>
  31. #include <linux/i2c.h>
  32. #include <linux/of_gpio.h>
  33. #include <linux/pinctrl/consumer.h>
  34. #include <linux/regulator/consumer.h>
  35. #include <linux/fsl_devices.h>
  36. #include <media/v4l2-chip-ident.h>
  37. #include <media/v4l2-int-device.h>
  38. #include "mxc_v4l2_capture.h"
  39.  
  40. //#define USE_BT656
  41. //#define USE_RAW
  42.  
  43. #define OV7740_VOLTAGE_ANALOG 2800000
  44. #define OV7740_VOLTAGE_DIGITAL_CORE 1500000
  45. #define OV7740_VOLTAGE_DIGITAL_IO 1800000
  46.  
  47. #define MIN_FPS 30
  48. #define MAX_FPS 60
  49. #define DEFAULT_FPS 30
  50.  
  51. #define OV7740_XCLK_MIN 6000000
  52. #define OV7740_XCLK_MAX 27000000
  53.  
  54. #define OV7740_CHIP_ID_HIGH_BYTE 0x1C
  55. #define OV7740_CHIP_ID_HIGH_BYTE_READ 0x7F
  56. #define OV7740_CHIP_ID_LOW_BYTE 0x1D
  57. #define OV7740_CHIP_ID_LOW_BYTE_READ 0xA2
  58.  
  59. enum ov7740_mode {
  60. ov7740_mode_MIN = 0,
  61. ov7740_mode_VGA_640_480 = 0,
  62. ov7740_mode_QVGA_320_240 = 1,
  63. ov7740_mode_MAX = 1
  64. };
  65.  
  66. enum ov7740_frame_rate {
  67. ov7740_15_fps,
  68. ov7740_30_fps
  69. };
  70.  
  71. static int ov7740_framerates[] = {
  72. [ov7740_15_fps] = 15,
  73. [ov7740_30_fps] = 30,
  74. };
  75.  
  76. struct reg_value {
  77. u16 u16RegAddr;
  78. u8 u8Val;
  79. u8 u8Mask;
  80. u32 u32Delay_ms;
  81. };
  82.  
  83. struct ov7740_mode_info {
  84. enum ov7740_mode mode;
  85. u32 width;
  86. u32 height;
  87. struct reg_value *init_data_ptr;
  88. u32 init_data_size;
  89. };
  90.  
  91. const char *stringize_mode(u32 mode){
  92. switch(mode)
  93. {
  94. case ov7740_mode_VGA_640_480 :
  95. return "ov7740_mode_VGA_640_480";
  96. break;
  97. case ov7740_mode_QVGA_320_240 :
  98. return "ov7740_mode_QVGA_320_240";
  99. break;
  100. }
  101. return "Unknown mode";
  102. }
  103.  
  104. const char *stringize_pixelformat(u32 palette){
  105. switch(palette)
  106. {
  107. case V4L2_PIX_FMT_RGB565 :
  108. return "V4L2_PIX_FMT_RGB565";
  109. break;
  110. case V4L2_PIX_FMT_YUYV :
  111. return "V4L2_PIX_FMT_YUYV";
  112. break;
  113. case V4L2_PIX_FMT_YVU420 :
  114. return "V4L2_PIX_FMT_YVU420";
  115. break;
  116. case V4L2_PIX_FMT_YUV420 :
  117. return "V4L2_PIX_FMT_YUV420";
  118. break;
  119. case V4L2_PIX_FMT_YUV422P :
  120. return "V4L2_PIX_FMT_YUV422P";
  121. break;
  122. }
  123. return "Unknown pixelformat";
  124. }
  125.  
  126. /*!
  127. * Maintains the information on the current state of the sesor.
  128. */
  129. static struct sensor_data ov7740_data;
  130. //static int pwn_gpio, rst_gpio;
  131.  
  132. static struct reg_value ov7740_setting_15fps_QVGA_320_240[] = {
  133. {0x12,0x80, 0 , 10},
  134. {0x13,0x00, 0 , 0},
  135.  
  136. {0x11,0x03, 0 , 0},
  137. #ifdef USE_BT656 /* BT656 0x12=>0x20 ou 0x31 */
  138. {0x12,0x20, 0 , 0},
  139. #else
  140. #ifdef USE_RAW
  141. {0x12,0x01, 0 , 0},
  142. #else
  143. {0x12,0x00, 0 , 0}, /* YUYV */
  144. #endif /* USE_RAW */
  145. #endif /* USE_BT656 */
  146. {0xd5,0x10, 0 , 0},
  147.  
  148. {0x0c,0x12, 0 , 0}, /* swap to YUYV */
  149. {0x0d,0x34, 0 , 0},
  150. {0x0e,0xe3, 0 , 0}, /* Output driving to 4x */
  151.  
  152. {0x17,0x25, 0 , 0},
  153. {0x18,0xa0, 0 , 0},
  154. {0x19,0x03, 0 , 0},
  155. {0x1a,0xf0, 0 , 0},
  156. {0x1b,0x89, 0 , 0},
  157. {0x1e,0x13, 0 , 0},
  158. {0x22,0x03, 0 , 0},
  159. {0x29,0x17, 0 , 0},
  160. {0x2b,0xf8, 0 , 0},
  161. {0x2c,0x01, 0 , 0},
  162. {0x31,0x50, 0 , 0},
  163. {0x32,0x78, 0 , 0},
  164. {0x33,0xc4, 0 , 0},
  165.  
  166. {0x3a,0xb4, 0 , 0},
  167. {0x36,0x3f, 0 , 0},
  168.  
  169. {0x04,0x60, 0 , 0},
  170. {0x27,0x80, 0 , 0},
  171. {0x3d,0x0f, 0 , 0},
  172. {0x3e,0x82, 0 , 0},
  173. {0x3f,0x40, 0 , 0},
  174. {0x40,0x7f, 0 , 0},
  175. {0x41,0x6a, 0 , 0},
  176. {0x42,0x29, 0 , 0},
  177. {0x44,0xe5, 0 , 0},
  178. {0x45,0x41, 0 , 0},
  179. {0x47,0x42, 0 , 0},
  180. {0x48,0x00, 0 , 0},
  181. {0x49,0x61, 0 , 0},
  182. {0x4a,0xa1, 0 , 0},
  183. {0x4b,0x46, 0 , 0},
  184. {0x4c,0x18, 0 , 0},
  185. {0x4d,0x50, 0 , 0},
  186. {0x4e,0x13, 0 , 0},
  187. {0x64,0x00, 0 , 0},
  188. {0x67,0x88, 0 , 0},
  189. {0x68,0x1a, 0 , 0},
  190.  
  191. {0x14,0x38, 0 , 0},
  192. {0x24,0x3c, 0 , 0},
  193. {0x25,0x30, 0 , 0},
  194. {0x26,0x72, 0 , 0},
  195. {0x50,0x4c, 0 , 0},
  196. {0x51,0x3f, 0 , 0},
  197. {0x52,0x00, 0 , 0},
  198. {0x53,0x00, 0 , 0},
  199. {0x20,0x00, 0 , 0},
  200. {0x21,0x57, 0 , 0},
  201. {0x38,0x14, 0 , 0},
  202. {0xe9,0x00, 0 , 0},
  203. {0x56,0x55, 0 , 0},
  204. {0x57,0xff, 0 , 0},
  205. {0x58,0xff, 0 , 0},
  206. {0x59,0xff, 0 , 0},
  207. {0x5f,0x04, 0 , 0},
  208. {0x13,0xff, 0 , 0},
  209.  
  210. {0x80,0x7d, 0 , 0},
  211. {0x81,0x3f, 0 , 0},/* YUV422 enabled */
  212. {0x82,0x3f, 0 , 0},
  213. {0x83,0x03, 0 , 0},
  214. {0x38,0x11, 0 , 0},
  215. {0x84,0x70, 0 , 0},
  216. {0x85,0x00, 0 , 0},
  217. {0x86,0x03, 0 , 0},
  218. {0x87,0x01, 0 , 0},
  219. {0x88,0x05, 0 , 0},
  220. {0x89,0x30, 0 , 0},
  221. {0x8d,0x30, 0 , 0},
  222. {0x8f,0x85, 0 , 0},
  223. {0x93,0x30, 0 , 0},
  224. {0x95,0x85, 0 , 0},
  225. {0x99,0x30, 0 , 0},
  226. {0x9b,0x85, 0 , 0},
  227.  
  228. {0x9c,0x08, 0 , 0},
  229. {0x9d,0x12, 0 , 0},
  230. {0x9e,0x23, 0 , 0},
  231. {0x9f,0x45, 0 , 0},
  232. {0xa0,0x55, 0 , 0},
  233. {0xa1,0x64, 0 , 0},
  234. {0xa2,0x72, 0 , 0},
  235. {0xa3,0x7f, 0 , 0},
  236. {0xa4,0x8b, 0 , 0},
  237. {0xa5,0x95, 0 , 0},
  238. {0xa6,0xa7, 0 , 0},
  239. {0xa7,0xb5, 0 , 0},
  240. {0xa8,0xcb, 0 , 0},
  241. {0xa9,0xdd, 0 , 0},
  242. {0xaa,0xec, 0 , 0},
  243. {0xab,0x1a, 0 , 0},
  244.  
  245. {0xce,0x78, 0 , 0},
  246. {0xcf,0x6e, 0 , 0},
  247. {0xd0,0x0a, 0 , 0},
  248. {0xd1,0x0c, 0 , 0},
  249. {0xd2,0x84, 0 , 0},
  250. {0xd3,0x90, 0 , 0},
  251. {0xd4,0x1e, 0 , 0},
  252.  
  253. {0x5a,0x24, 0 , 0},
  254. {0x5b,0x1f, 0 , 0},
  255. {0x5c,0x88, 0 , 0},
  256. {0x5d,0x60, 0 , 0},
  257.  
  258. {0xac,0x6e, 0 , 0},
  259. {0xbe,0xff, 0 , 0},
  260. {0xbf,0x00, 0 , 0},
  261. {0xe5,0x8c, 0 , 0},
  262.  
  263. {0x70,0x00, 0 , 0},
  264. {0x71,0x34, 0 , 0},
  265. {0x74,0x28, 0 , 0},
  266. {0x75,0x98, 0 , 0},
  267. {0x76,0x00, 0 , 0},
  268. {0x77,0x08, 0 , 0},
  269. {0x78,0x01, 0 , 0},
  270. {0x79,0xc2, 0 , 0},
  271. {0x7d,0x02, 0 , 0},
  272. {0x7a,0x9c, 0 , 0},
  273. {0x7b,0x40, 0 , 0},
  274. {0xec,0x02, 0 , 0},
  275. {0x7c,0x0c, 0 , 0},
  276.  
  277.  
  278. };
  279.  
  280. static struct reg_value ov7740_setting_30fps_QVGA_320_240[] = {
  281. {0x12,0x80, 0 , 10},
  282. {0x13,0x00, 0 , 0},
  283.  
  284. {0x11,0x01, 0 , 0},
  285. #ifdef USE_BT656 /* BT656 0x12=>0x20 ou 0x31 */
  286. {0x12,0x20, 0 , 0},
  287. #else
  288. #ifdef USE_RAW
  289. {0x12,0x01, 0 , 0},
  290. #else
  291. {0x12,0x00, 0 , 0}, /* YUYV */
  292. #endif /* USE_RAW */
  293. #endif /* USE_BT656 */
  294. {0xd5,0x10, 0 , 0},
  295.  
  296. {0x0c,0x12, 0 , 0}, /* swap to YUYV */
  297. {0x0d,0x34, 0 , 0},
  298. {0x0e,0xe3, 0 , 0}, /* Output driving to 4x */
  299.  
  300. {0x17,0x25, 0 , 0},
  301. {0x18,0xa0, 0 , 0},
  302. {0x19,0x03, 0 , 0},
  303. {0x1a,0xf0, 0 , 0},
  304. {0x1b,0x89, 0 , 0},
  305. {0x1e,0x13, 0 , 0},
  306. {0x22,0x03, 0 , 0},
  307. {0x29,0x17, 0 , 0},
  308. {0x2b,0xf8, 0 , 0},
  309. {0x2c,0x01, 0 , 0},
  310. {0x31,0x50, 0 , 0},
  311. {0x32,0x78, 0 , 0},
  312. {0x33,0xc4, 0 , 0},
  313.  
  314. {0x3a,0xb4, 0 , 0},
  315. {0x36,0x3f, 0 , 0},
  316.  
  317. {0x04,0x60, 0 , 0},
  318. {0x27,0x80, 0 , 0},
  319. {0x3d,0x0f, 0 , 0},
  320. {0x3e,0x82, 0 , 0},
  321. {0x3f,0x40, 0 , 0},
  322. {0x40,0x7f, 0 , 0},
  323. {0x41,0x6a, 0 , 0},
  324. {0x42,0x29, 0 , 0},
  325. {0x44,0xe5, 0 , 0},
  326. {0x45,0x41, 0 , 0},
  327. {0x47,0x42, 0 , 0},
  328. {0x48,0x00, 0 , 0},
  329. {0x49,0x61, 0 , 0},
  330. {0x4a,0xa1, 0 , 0},
  331. {0x4b,0x46, 0 , 0},
  332. {0x4c,0x18, 0 , 0},
  333. {0x4d,0x50, 0 , 0},
  334. {0x4e,0x13, 0 , 0},
  335. {0x64,0x00, 0 , 0},
  336. {0x67,0x88, 0 , 0},
  337. {0x68,0x1a, 0 , 0},
  338.  
  339. {0x14,0x38, 0 , 0},
  340. {0x24,0x3c, 0 , 0},
  341. {0x25,0x30, 0 , 0},
  342. {0x26,0x72, 0 , 0},
  343. {0x50,0x97, 0 , 0},
  344. {0x51,0x7e, 0 , 0},
  345. {0x52,0x00, 0 , 0},
  346. {0x53,0x00, 0 , 0},
  347. {0x20,0x00, 0 , 0},
  348. {0x21,0x23, 0 , 0},
  349. {0x38,0x14, 0 , 0},
  350. {0xe9,0x00, 0 , 0},
  351. {0x56,0x55, 0 , 0},
  352. {0x57,0xff, 0 , 0},
  353. {0x58,0xff, 0 , 0},
  354. {0x59,0xff, 0 , 0},
  355. {0x5f,0x04, 0 , 0},
  356. {0x13,0xff, 0 , 0},
  357.  
  358. {0x80,0x7d, 0 , 0},
  359. {0x81,0x3f, 0 , 0},/* YUV422 enabled */
  360. {0x82,0x3f, 0 , 0},
  361. {0x83,0x03, 0 , 0},
  362. {0x38,0x11, 0 , 0},
  363. {0x84,0x70, 0 , 0},
  364. {0x85,0x00, 0 , 0},
  365. {0x86,0x03, 0 , 0},
  366. {0x87,0x01, 0 , 0},
  367. {0x88,0x05, 0 , 0},
  368. {0x89,0x30, 0 , 0},
  369. {0x8d,0x30, 0 , 0},
  370. {0x8f,0x85, 0 , 0},
  371. {0x93,0x30, 0 , 0},
  372. {0x95,0x85, 0 , 0},
  373. {0x99,0x30, 0 , 0},
  374. {0x9b,0x85, 0 , 0},
  375.  
  376. {0x9c,0x08, 0 , 0},
  377. {0x9d,0x12, 0 , 0},
  378. {0x9e,0x23, 0 , 0},
  379. {0x9f,0x45, 0 , 0},
  380. {0xa0,0x55, 0 , 0},
  381. {0xa1,0x64, 0 , 0},
  382. {0xa2,0x72, 0 , 0},
  383. {0xa3,0x7f, 0 , 0},
  384. {0xa4,0x8b, 0 , 0},
  385. {0xa5,0x95, 0 , 0},
  386. {0xa6,0xa7, 0 , 0},
  387. {0xa7,0xb5, 0 , 0},
  388. {0xa8,0xcb, 0 , 0},
  389. {0xa9,0xdd, 0 , 0},
  390. {0xaa,0xec, 0 , 0},
  391. {0xab,0x1a, 0 , 0},
  392.  
  393. {0xce,0x78, 0 , 0},
  394. {0xcf,0x6e, 0 , 0},
  395. {0xd0,0x0a, 0 , 0},
  396. {0xd1,0x0c, 0 , 0},
  397. {0xd2,0x84, 0 , 0},
  398. {0xd3,0x90, 0 , 0},
  399. {0xd4,0x1e, 0 , 0},
  400.  
  401. {0x5a,0x24, 0 , 0},
  402. {0x5b,0x1f, 0 , 0},
  403. {0x5c,0x88, 0 , 0},
  404. {0x5d,0x60, 0 , 0},
  405.  
  406. {0xac,0x6e, 0 , 0},
  407. {0xbe,0xff, 0 , 0},
  408. {0xbf,0x00, 0 , 0},
  409. {0xe5,0x8c, 0 , 0},
  410.  
  411. {0x70,0x00, 0 , 0},
  412. {0x71,0x34, 0 , 0},
  413. {0x74,0x28, 0 , 0},
  414. {0x75,0x98, 0 , 0},
  415. {0x76,0x00, 0 , 0},
  416. {0x77,0x08, 0 , 0},
  417. {0x78,0x01, 0 , 0},
  418. {0x79,0xc2, 0 , 0},
  419. {0x7d,0x02, 0 , 0},
  420. {0x7a,0x9c, 0 , 0},
  421. {0x7b,0x40, 0 , 0},
  422. {0xec,0x02, 0 , 0},
  423. {0x7c,0x0c, 0 , 0},
  424.  
  425. };
  426. static struct reg_value ov7740_setting_15fps_VGA_640_480[] = {
  427. {0x12,0x80, 0 , 10},
  428. {0x13,0x00, 0 , 0},
  429.  
  430. {0x11,0x03, 0 , 0},
  431. #ifdef USE_BT656 /* BT656 0x12=>0x20 ou 0x31 */
  432. {0x12,0x20, 0 , 0},
  433. #else
  434. #ifdef USE_RAW
  435. {0x12,0x01, 0 , 0},
  436. #else
  437. {0x12,0x00, 0 , 0}, /* YUYV */
  438. #endif /* USE_RAW */
  439. #endif /* USE_BT656 */
  440. {0xd5,0x10, 0 , 0},
  441.  
  442. {0x0c,0x12, 0 , 0}, /* swap to YUYV */
  443. {0x0d,0x34, 0 , 0},
  444. {0x0e,0xe3, 0 , 0}, /* Output driving to 4x */
  445.  
  446. {0x17,0x25, 0 , 0},
  447. {0x18,0xa0, 0 , 0},
  448. {0x19,0x03, 0 , 0},
  449. {0x1a,0xf0, 0 , 0},
  450. {0x1b,0x89, 0 , 0},
  451. {0x1e,0x13, 0 , 0},
  452. {0x22,0x03, 0 , 0},
  453. {0x29,0x17, 0 , 0},
  454. {0x2b,0xf8, 0 , 0},
  455. {0x2c,0x01, 0 , 0},
  456. {0x31,0xa0, 0 , 0},
  457. {0x32,0xf0, 0 , 0},
  458. {0x33,0xc4, 0 , 0},
  459.  
  460. {0x3a,0xb4, 0 , 0},
  461. {0x36,0x3f, 0 , 0},
  462.  
  463. {0x04,0x60, 0 , 0},
  464. {0x27,0x80, 0 , 0},
  465. {0x3d,0x0f, 0 , 0},
  466. {0x3e,0x82, 0 , 0},
  467. {0x3f,0x40, 0 , 0},
  468. {0x40,0x7f, 0 , 0},
  469. {0x41,0x6a, 0 , 0},
  470. {0x42,0x29, 0 , 0},
  471. {0x44,0xe5, 0 , 0},
  472. {0x45,0x41, 0 , 0},
  473. {0x47,0x42, 0 , 0},
  474. {0x48,0x00, 0 , 0},
  475. {0x49,0x61, 0 , 0},
  476. {0x4a,0xa1, 0 , 0},
  477. {0x4b,0x46, 0 , 0},
  478. {0x4c,0x18, 0 , 0},
  479. {0x4d,0x50, 0 , 0},
  480. {0x4e,0x13, 0 , 0},
  481. {0x64,0x00, 0 , 0},
  482. {0x67,0x88, 0 , 0},
  483. {0x68,0x1a, 0 , 0},
  484.  
  485. {0x14,0x38, 0 , 0},
  486. {0x24,0x3c, 0 , 0},
  487. {0x25,0x30, 0 , 0},
  488. {0x26,0x72, 0 , 0},
  489. {0x50,0x4c, 0 , 0},
  490. {0x51,0x3f, 0 , 0},
  491. {0x52,0x00, 0 , 0},
  492. {0x53,0x00, 0 , 0},
  493. {0x20,0x00, 0 , 0},
  494. {0x21,0x57, 0 , 0},
  495. {0x38,0x14, 0 , 0},
  496. {0xe9,0x00, 0 , 0},
  497. {0x56,0x55, 0 , 0},
  498. {0x57,0xff, 0 , 0},
  499. {0x58,0xff, 0 , 0},
  500. {0x59,0xff, 0 , 0},
  501. {0x5f,0x04, 0 , 0},
  502. {0x13,0xff, 0 , 0},
  503.  
  504. {0x80,0x7d, 0 , 0},
  505. {0x81,0x3f, 0 , 0},/* YUV422 enabled */
  506. {0x82,0x32, 0 , 0},
  507. {0x83,0x03, 0 , 0},
  508. {0x38,0x11, 0 , 0},
  509. {0x84,0x70, 0 , 0},
  510. {0x85,0x00, 0 , 0},
  511. {0x86,0x03, 0 , 0},
  512. {0x87,0x01, 0 , 0},
  513. {0x88,0x05, 0 , 0},
  514. {0x89,0x30, 0 , 0},
  515. {0x8d,0x30, 0 , 0},
  516. {0x8f,0x85, 0 , 0},
  517. {0x93,0x30, 0 , 0},
  518. {0x95,0x85, 0 , 0},
  519. {0x99,0x30, 0 , 0},
  520. {0x9b,0x85, 0 , 0},
  521.  
  522. {0x9c,0x08, 0 , 0},
  523. {0x9d,0x12, 0 , 0},
  524. {0x9e,0x23, 0 , 0},
  525. {0x9f,0x45, 0 , 0},
  526. {0xa0,0x55, 0 , 0},
  527. {0xa1,0x64, 0 , 0},
  528. {0xa2,0x72, 0 , 0},
  529. {0xa3,0x7f, 0 , 0},
  530. {0xa4,0x8b, 0 , 0},
  531. {0xa5,0x95, 0 , 0},
  532. {0xa6,0xa7, 0 , 0},
  533. {0xa7,0xb5, 0 , 0},
  534. {0xa8,0xcb, 0 , 0},
  535. {0xa9,0xdd, 0 , 0},
  536. {0xaa,0xec, 0 , 0},
  537. {0xab,0x1a, 0 , 0},
  538.  
  539. {0xce,0x78, 0 , 0},
  540. {0xcf,0x6e, 0 , 0},
  541. {0xd0,0x0a, 0 , 0},
  542. {0xd1,0x0c, 0 , 0},
  543. {0xd2,0x84, 0 , 0},
  544. {0xd3,0x90, 0 , 0},
  545. {0xd4,0x1e, 0 , 0},
  546.  
  547. {0x5a,0x24, 0 , 0},
  548. {0x5b,0x1f, 0 , 0},
  549. {0x5c,0x88, 0 , 0},
  550. {0x5d,0x60, 0 , 0},
  551.  
  552. {0xac,0x6e, 0 , 0},
  553. {0xbe,0xff, 0 , 0},
  554. {0xbf,0x00, 0 , 0},
  555.  
  556. {0x70,0x00, 0 , 0},
  557. {0x71,0x34, 0 , 0},
  558. {0x74,0x28, 0 , 0},
  559. {0x75,0x98, 0 , 0},
  560. {0x76,0x00, 0 , 0},
  561. {0x77,0x08, 0 , 0},
  562. {0x78,0x01, 0 , 0},
  563. {0x79,0xc2, 0 , 0},
  564. {0x7d,0x02, 0 , 0},
  565. {0x7a,0x9c, 0 , 0},
  566. {0x7b,0x40, 0 , 0},
  567. {0xec,0x82, 0 , 0},
  568. {0x7c,0x0c, 0 , 0},
  569. };
  570.  
  571. //default one
  572. static struct reg_value ov7740_setting_30fps_VGA_640_480[] = {
  573.  
  574. {0x12,0x80, 0 , 10},
  575. {0x13,0x00, 0 , 0},
  576.  
  577. {0x11,0x01, 0 , 0},
  578. #ifdef USE_BT656 /* BT656 0x12=>0x20 ou 0x31 */
  579. {0x12,0x20, 0 , 0},
  580. #else
  581. #ifdef USE_RAW
  582. {0x12,0x01, 0 , 0},
  583. #else
  584. {0x12,0x00, 0 , 0}, /* YUYV */
  585. #endif /* USE_RAW */
  586. #endif /* USE_BT656 */
  587. {0xd5,0x10, 0 , 0},
  588.  
  589. {0x0c,0x12, 0 , 0}, /* swap to YUYV */
  590. {0x0d,0x34, 0 , 0},
  591. {0x0e,0xe3, 0 , 0}, /* Output driving to 4x */
  592.  
  593. {0x17,0x25, 0 , 0},
  594. {0x18,0xa0, 0 , 0},
  595. {0x19,0x03, 0 , 0},
  596. {0x1a,0xf0, 0 , 0},
  597. {0x1b,0x89, 0 , 0},
  598. {0x1e,0x13, 0 , 0},
  599. {0x22,0x03, 0 , 0},
  600. {0x29,0x17, 0 , 0},
  601. {0x2b,0xf8, 0 , 0},
  602. {0x2c,0x01, 0 , 0},
  603. {0x31,0xa0, 0 , 0},
  604. {0x32,0xf0, 0 , 0},
  605. {0x33,0xc4, 0 , 0},
  606.  
  607. {0x3a,0xb4, 0 , 0},
  608. {0x36,0x3f, 0 , 0},
  609.  
  610. {0x04,0x60, 0 , 0},
  611. {0x27,0x80, 0 , 0},
  612. {0x3d,0x0f, 0 , 0},
  613. {0x3e,0x82, 0 , 0},
  614. {0x3f,0x40, 0 , 0},
  615. {0x40,0x7f, 0 , 0},
  616. {0x41,0x6a, 0 , 0},
  617. {0x42,0x29, 0 , 0},
  618. {0x44,0xe5, 0 , 0},
  619. {0x45,0x41, 0 , 0},
  620. {0x47,0x42, 0 , 0},
  621. {0x48,0x00, 0 , 0},
  622. {0x49,0x61, 0 , 0},
  623. {0x4a,0xa1, 0 , 0},
  624. {0x4b,0x46, 0 , 0},
  625. {0x4c,0x18, 0 , 0},
  626. {0x4d,0x50, 0 , 0},
  627. {0x4e,0x13, 0 , 0},
  628. {0x64,0x00, 0 , 0},
  629. {0x67,0x88, 0 , 0},
  630. {0x68,0x1a, 0 , 0},
  631.  
  632. {0x14,0x38, 0 , 0},
  633. {0x24,0x3c, 0 , 0},
  634. {0x25,0x30, 0 , 0},
  635. {0x26,0x72, 0 , 0},
  636. {0x50,0x97, 0 , 0},
  637. {0x51,0x7e, 0 , 0},
  638. {0x52,0x00, 0 , 0},
  639. {0x53,0x00, 0 , 0},
  640. {0x20,0x00, 0 , 0},
  641. {0x21,0x23, 0 , 0},
  642. {0x38,0x14, 0 , 0},
  643. {0xe9,0x00, 0 , 0},
  644. {0x56,0x55, 0 , 0},
  645. {0x57,0xff, 0 , 0},
  646. {0x58,0xff, 0 , 0},
  647. {0x59,0xff, 0 , 0},
  648. {0x5f,0x04, 0 , 0},
  649. {0x13,0xff, 0 , 0},
  650.  
  651. {0x80,0x7d, 0 , 0},
  652. {0x81,0x3f, 0 , 0},/* YUV422 enabled */
  653. {0x82,0x32, 0 , 0},
  654. {0x83,0x03, 0 , 0},
  655. {0x38,0x11, 0 , 0},
  656. {0x84,0x70, 0 , 0},
  657. {0x85,0x00, 0 , 0},
  658. {0x86,0x03, 0 , 0},
  659. {0x87,0x01, 0 , 0},
  660. {0x88,0x05, 0 , 0},
  661. {0x89,0x30, 0 , 0},
  662. {0x8d,0x30, 0 , 0},
  663. {0x8f,0x85, 0 , 0},
  664. {0x93,0x30, 0 , 0},
  665. {0x95,0x85, 0 , 0},
  666. {0x99,0x30, 0 , 0},
  667. {0x9b,0x85, 0 , 0},
  668.  
  669. {0x9c,0x08, 0 , 0},
  670. {0x9d,0x12, 0 , 0},
  671. {0x9e,0x23, 0 , 0},
  672. {0x9f,0x45, 0 , 0},
  673. {0xa0,0x55, 0 , 0},
  674. {0xa1,0x64, 0 , 0},
  675. {0xa2,0x72, 0 , 0},
  676. {0xa3,0x7f, 0 , 0},
  677. {0xa4,0x8b, 0 , 0},
  678. {0xa5,0x95, 0 , 0},
  679. {0xa6,0xa7, 0 , 0},
  680. {0xa7,0xb5, 0 , 0},
  681. {0xa8,0xcb, 0 , 0},
  682. {0xa9,0xdd, 0 , 0},
  683. {0xaa,0xec, 0 , 0},
  684. {0xab,0x1a, 0 , 0},
  685.  
  686. {0xce,0x78, 0 , 0},
  687. {0xcf,0x6e, 0 , 0},
  688. {0xd0,0x0a, 0 , 0},
  689. {0xd1,0x0c, 0 , 0},
  690. {0xd2,0x84, 0 , 0},
  691. {0xd3,0x90, 0 , 0},
  692. {0xd4,0x1e, 0 , 0},
  693.  
  694. {0x5a,0x24, 0 , 0},
  695. {0x5b,0x1f, 0 , 0},
  696. {0x5c,0x88, 0 , 0},
  697. {0x5d,0x60, 0 , 0},
  698.  
  699. {0xac,0x6e, 0 , 0},
  700. {0xbe,0xff, 0 , 0},
  701. {0xbf,0x00, 0 , 0},
  702.  
  703. {0x70,0x00, 0 , 0},
  704. {0x71,0x34, 0 , 0},
  705. {0x74,0x28, 0 , 0},
  706. {0x75,0x98, 0 , 0},
  707. {0x76,0x00, 0 , 0},
  708. {0x77,0x08, 0 , 0},
  709. {0x78,0x01, 0 , 0},
  710. {0x79,0xc2, 0 , 0},
  711. {0x7d,0x02, 0 , 0},
  712. {0x7a,0x9c, 0 , 0},
  713. {0x7b,0x40, 0 , 0},
  714. {0xec,0x82, 0 , 0},
  715. {0x7c,0x0c, 0 , 0},
  716.  
  717. };
  718.  
  719. static struct ov7740_mode_info ov7740_mode_info_data[2][ov7740_mode_MAX + 1] = {
  720. {
  721. {ov7740_mode_VGA_640_480, 640, 480,
  722. ov7740_setting_15fps_VGA_640_480,
  723. ARRAY_SIZE(ov7740_setting_15fps_VGA_640_480)},
  724.  
  725. {ov7740_mode_QVGA_320_240, 320, 240,
  726. ov7740_setting_15fps_QVGA_320_240,
  727. ARRAY_SIZE(ov7740_setting_15fps_QVGA_320_240)},
  728.  
  729. },
  730.  
  731.  
  732.  
  733. {
  734. {ov7740_mode_VGA_640_480, 640, 480,
  735. ov7740_setting_30fps_VGA_640_480,
  736. ARRAY_SIZE(ov7740_setting_30fps_VGA_640_480)},
  737.  
  738. {ov7740_mode_QVGA_320_240, 320, 240,
  739. ov7740_setting_30fps_QVGA_320_240,
  740. ARRAY_SIZE(ov7740_setting_30fps_QVGA_320_240)},
  741.  
  742. },
  743. };
  744.  
  745. static struct regulator *io_regulator;
  746. static struct regulator *core_regulator;
  747. static struct regulator *analog_regulator;
  748. static struct regulator *gpo_regulator;
  749.  
  750. static int ov7740_probe(struct i2c_client *adapter,
  751. const struct i2c_device_id *device_id);
  752. static int ov7740_remove(struct i2c_client *client);
  753.  
  754. static s32 ov7740_read_reg(u16 reg, u8 *val);
  755. static s32 ov7740_write_reg(u16 reg, u8 val);
  756.  
  757. static const struct i2c_device_id ov7740_id[] = {
  758. {"ov7740", 0},
  759. {"ov564x", 0},
  760. {},
  761. };
  762.  
  763. MODULE_DEVICE_TABLE(i2c, ov7740_id);
  764.  
  765. static struct i2c_driver ov7740_i2c_driver = {
  766. .driver = {
  767. .owner = THIS_MODULE,
  768. .name = "ov7740",
  769. },
  770. .probe = ov7740_probe,
  771. .remove = ov7740_remove,
  772. .id_table = ov7740_id,
  773. };
  774.  
  775. static void ov7740_standby(s32 enable)
  776. {
  777. return ;
  778. }
  779.  
  780. static void ov7740_reset(void)
  781. {
  782. return ;
  783. }
  784.  
  785. static int ov7740_power_on(struct device *dev)
  786. {
  787. return 0;
  788. }
  789. /*!
  790. * ovx_write_reg I2C write function
  791. *
  792. * @param reg : register to write
  793. * @param value : value to write
  794. * @return Error code indicating success or failure
  795. */
  796. static s32 ov7740_write_reg(u16 reg, u8 val)
  797. {
  798. u8 au8Buf[2] = {0};
  799.  
  800. if(reg > 0xff){
  801. pr_info("%s: register too high :0x%02x\n",__func__,reg);
  802. return -1;
  803. }
  804.  
  805. au8Buf[0] = reg & 0xff;
  806. au8Buf[1] = val;
  807.  
  808. if (i2c_master_send(ov7740_data.i2c_client, au8Buf, 2) < 0) {
  809. pr_err("%s:write reg error:reg=%x,val=%x\n",
  810. __func__, reg, val);
  811. return -1;
  812. }
  813. return 0;
  814. }
  815.  
  816. /*!
  817. * ovx_read_reg I2C write function
  818. *
  819. * @param reg : register to read
  820. * @param value : value read, -1 if no value is read
  821. * @return Error code indicating success or failure
  822. */
  823. static s32 ov7740_read_reg(u16 reg, u8 *value)
  824. {
  825. int returned = 0;
  826. u8 au8RegBuf[1] = {0};
  827. u8 u8RdVal = 0;
  828.  
  829. if(reg > 0xff){
  830. pr_info("%s: register too high :0x%02x\n",__func__,reg);
  831. return -1;
  832. }
  833. au8RegBuf[0] = reg & 0xff;
  834.  
  835. returned = i2c_master_send(ov7740_data.i2c_client, au8RegBuf, 1);
  836. if (1 != returned) {
  837. pr_err("%s:write reg error:reg=%x error:%d\n",
  838. __func__, reg,returned);
  839. return -1;
  840. }
  841.  
  842. if (1 != i2c_master_recv(ov7740_data.i2c_client, &u8RdVal, 1)) {
  843. pr_err("%s:read reg error:reg=%x,val=%x\n",
  844. __func__, reg, u8RdVal);
  845. return -1;
  846. }
  847.  
  848. *value = u8RdVal;
  849.  
  850. return u8RdVal;
  851. }
  852.  
  853. static int ov7740_init_mode(enum ov7740_frame_rate frame_rate,
  854. enum ov7740_mode mode)
  855. {
  856. struct reg_value *pModeSetting = NULL;
  857. s32 i = 0;
  858. s32 iModeSettingArySize = 0;
  859. register u32 Delay_ms = 0;
  860. register u16 RegAddr = 0;
  861. register u8 Mask = 0;
  862. register u8 Val = 0;
  863. u8 RegVal = 0;
  864. int retval = 0;
  865.  
  866. pr_info("%s mode is %s and framerate is %d\n",__func__,stringize_mode(mode),ov7740_framerates[frame_rate]);
  867. if (mode > ov7740_mode_MAX || mode < ov7740_mode_MIN) {
  868. pr_err("Wrong ov7740 mode detected!\n");
  869. return -1;
  870. }
  871.  
  872. pModeSetting = ov7740_mode_info_data[frame_rate][mode].init_data_ptr;
  873. iModeSettingArySize =
  874. ov7740_mode_info_data[frame_rate][mode].init_data_size;
  875.  
  876. ov7740_data.pix.width = ov7740_mode_info_data[frame_rate][mode].width;
  877. ov7740_data.pix.height = ov7740_mode_info_data[frame_rate][mode].height;
  878. pr_info("%s use w:%d, h:%d\n",__func__,ov7740_data.pix.width,ov7740_data.pix.height);
  879. if (ov7740_data.pix.width == 0 || ov7740_data.pix.height == 0 ||
  880. pModeSetting == NULL || iModeSettingArySize == 0)
  881. return -EINVAL;
  882.  
  883. for (i = 0; i < iModeSettingArySize; ++i, ++pModeSetting) {
  884. Delay_ms = pModeSetting->u32Delay_ms;
  885. RegAddr = pModeSetting->u16RegAddr;
  886. Val = pModeSetting->u8Val;
  887. Mask = pModeSetting->u8Mask;
  888.  
  889. if (Mask) {
  890. retval = ov7740_read_reg(RegAddr, &RegVal);
  891. if (retval < 0) {
  892. pr_err("read reg error addr=0x%x", RegAddr);
  893. goto err;
  894. }
  895.  
  896. RegVal &= ~(u8)Mask;
  897. Val &= Mask;
  898. Val |= RegVal;
  899. }
  900.  
  901. retval = ov7740_write_reg(RegAddr, Val);
  902. if (retval < 0) {
  903. pr_err("write reg error addr=0x%x", RegAddr);
  904. goto err;
  905. }
  906.  
  907. if (Delay_ms)
  908. msleep(Delay_ms);
  909. }
  910. err:
  911. return retval;
  912. }
  913.  
  914. /* --------------- IOCTL functions from v4l2_int_ioctl_desc --------------- */
  915. /***********************************************************************
  916. * IOCTL Functions from v4l2_int_ioctl_desc.
  917. ***********************************************************************/
  918.  
  919. /*!
  920. * ioctl_g_ifparm - V4L2 sensor interface handler for vidioc_int_g_ifparm_num
  921. * s: pointer to standard V4L2 device structure
  922. * p: pointer to standard V4L2 vidioc_int_g_ifparm_num ioctl structure
  923. *
  924. * Gets slave interface parameters.
  925. * Calculates the required xclk value to support the requested
  926. * clock parameters in p. This value is returned in the p
  927. * parameter.
  928. *
  929. * vidioc_int_g_ifparm returns platform-specific information about the
  930. * interface settings used by the sensor.
  931. *
  932. * Called on open.
  933. */
  934. static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
  935. {
  936. pr_info("%s start\n",__func__);
  937. if (s == NULL) {
  938. pr_err(" ERROR!! no slave device set!\n");
  939. return -1;
  940. }
  941.  
  942. memset(p, 0, sizeof(*p));
  943. p->if_type = V4L2_IF_TYPE_BT656;
  944. p->u.bt656.latch_clk_inv = 1;//data sur front montant de pixclk
  945. p->u.bt656.swap = 0;//if 1 it is for test
  946. #ifdef USE_BT656
  947. //IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE
  948. pr_info("Use BT656 progressive synchronization code\n");
  949. p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_BT_8BIT;
  950. p->u.bt656.bt_sync_correct = 0; /* 1 Indicate external vsync */
  951. p->u.bt656.clock_curr = 0;//in mxc_v4l2_capture
  952. #else
  953. pr_info("Not using BT656 synchronization code\n");
  954. p->u.bt656.frame_start_on_rising_vs = 1;/* Not handled by imx */
  955. p->u.bt656.bt_sync_correct = 1; /* Indicate external vsync */
  956. p->u.bt656.latch_clk_inv = 0; /* 1 : clock on falling edge */
  957. p->u.bt656.nobt_hs_inv = 0;
  958. p->u.bt656.nobt_vs_inv = 0;
  959. p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
  960. /* p->u.bt656.clock_curr = ov7740_data.mclk; external clock */
  961. #if 0
  962. ov7740_data.sen.pix.priv = 1; /* 1 is used to indicate TV in */
  963. #endif
  964. #endif
  965. pr_info(" clock_curr=mclk=%d\n", ov7740_data.mclk);
  966. p->u.bt656.clock_min = OV7740_XCLK_MIN;
  967. p->u.bt656.clock_max = OV7740_XCLK_MAX;
  968.  
  969. return 0;
  970. }
  971.  
  972. /*!
  973. * ioctl_s_power - V4L2 sensor interface handler for VIDIOC_S_POWER ioctl
  974. * @s: pointer to standard V4L2 device structure
  975. * @on: indicates power mode (on or off)
  976. *
  977. * Turns the power on or off, depending on the value of on and returns the
  978. * appropriate error code.
  979. */
  980. static int ioctl_s_power(struct v4l2_int_device *s, int on)
  981. {
  982. struct sensor_data *sensor = s->priv;
  983.  
  984. if (on && !sensor->on) {
  985. if (io_regulator)
  986. if (regulator_enable(io_regulator) != 0)
  987. return -EIO;
  988. if (core_regulator)
  989. if (regulator_enable(core_regulator) != 0)
  990. return -EIO;
  991. if (gpo_regulator)
  992. if (regulator_enable(gpo_regulator) != 0)
  993. return -EIO;
  994. if (analog_regulator)
  995. if (regulator_enable(analog_regulator) != 0)
  996. return -EIO;
  997. /* Make sure power on */
  998. ov7740_standby(0);
  999. } else if (!on && sensor->on) {
  1000. if (analog_regulator)
  1001. regulator_disable(analog_regulator);
  1002. if (core_regulator)
  1003. regulator_disable(core_regulator);
  1004. if (io_regulator)
  1005. regulator_disable(io_regulator);
  1006. if (gpo_regulator)
  1007. regulator_disable(gpo_regulator);
  1008.  
  1009. ov7740_standby(1);
  1010. }
  1011.  
  1012. sensor->on = on;
  1013.  
  1014. return 0;
  1015. }
  1016.  
  1017. /*!
  1018. * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
  1019. * @s: pointer to standard V4L2 device structure
  1020. * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
  1021. *
  1022. * Returns the sensor's video CAPTURE parameters.
  1023. */
  1024. static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
  1025. {
  1026. struct sensor_data *sensor = s->priv;
  1027. struct v4l2_captureparm *cparm = &a->parm.capture;
  1028. int ret = 0;
  1029.  
  1030. pr_info("%s start\n",__func__);
  1031. switch (a->type) {
  1032. /* This is the only case currently handled. */
  1033. case V4L2_BUF_TYPE_VIDEO_CAPTURE:
  1034. memset(a, 0, sizeof(*a));
  1035. a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1036. cparm->capability = sensor->streamcap.capability;
  1037. cparm->timeperframe = sensor->streamcap.timeperframe;
  1038. cparm->capturemode = sensor->streamcap.capturemode;
  1039. ret = 0;
  1040. break;
  1041.  
  1042. /* These are all the possible cases. */
  1043. case V4L2_BUF_TYPE_VIDEO_OUTPUT:
  1044. case V4L2_BUF_TYPE_VIDEO_OVERLAY:
  1045. case V4L2_BUF_TYPE_VBI_CAPTURE:
  1046. case V4L2_BUF_TYPE_VBI_OUTPUT:
  1047. case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
  1048. case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
  1049. ret = -EINVAL;
  1050. break;
  1051.  
  1052. default:
  1053. pr_info(" type is unknown - %d\n", a->type);
  1054. ret = -EINVAL;
  1055. break;
  1056. }
  1057.  
  1058. return ret;
  1059. }
  1060.  
  1061. /*!
  1062. * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
  1063. * @s: pointer to standard V4L2 device structure
  1064. * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
  1065. *
  1066. * Configures the sensor to use the input parameters, if possible. If
  1067. * not possible, reverts to the old parameters and returns the
  1068. * appropriate error code.
  1069. */
  1070. static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
  1071. {
  1072. struct sensor_data *sensor = s->priv;
  1073. struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
  1074. u32 tgt_fps, old_fps; /* target frames per secound */
  1075. enum ov7740_frame_rate new_frame_rate, old_frame_rate;
  1076. int ret = 0;
  1077.  
  1078. /* Make sure power on */
  1079. ov7740_standby(0);
  1080.  
  1081. pr_info("%s start\n",__func__);
  1082. switch (a->type) {
  1083. /* This is the only case currently handled. */
  1084. case V4L2_BUF_TYPE_VIDEO_CAPTURE:
  1085. /* Check that the new frame rate is allowed. */
  1086. if ((timeperframe->numerator == 0) ||
  1087. (timeperframe->denominator == 0)) {
  1088. timeperframe->denominator = DEFAULT_FPS;
  1089. timeperframe->numerator = 1;
  1090. }
  1091.  
  1092. tgt_fps = timeperframe->denominator /
  1093. timeperframe->numerator;
  1094.  
  1095. if (tgt_fps > MAX_FPS) {
  1096. timeperframe->denominator = MAX_FPS;
  1097. timeperframe->numerator = 1;
  1098. } else if (tgt_fps < MIN_FPS) {
  1099. timeperframe->denominator = MIN_FPS;
  1100. timeperframe->numerator = 1;
  1101. }
  1102.  
  1103. /* Actual frame rate we use */
  1104. tgt_fps = timeperframe->denominator /
  1105. timeperframe->numerator;
  1106.  
  1107. if (tgt_fps == 15)
  1108. new_frame_rate = ov7740_15_fps;
  1109. else if (tgt_fps == 30)
  1110. new_frame_rate = ov7740_30_fps;
  1111. else {
  1112. pr_err(" The camera frame rate is not supported!\n");
  1113. return -EINVAL;
  1114. }
  1115.  
  1116. if (sensor->streamcap.timeperframe.numerator != 0)
  1117. old_fps = sensor->streamcap.timeperframe.denominator /
  1118. sensor->streamcap.timeperframe.numerator;
  1119. else
  1120. old_fps = 30;
  1121.  
  1122. if (old_fps == 15)
  1123. old_frame_rate = ov7740_15_fps;
  1124. else if (old_fps == 30)
  1125. old_frame_rate = ov7740_30_fps;
  1126. else
  1127. old_frame_rate = ov7740_30_fps;
  1128.  
  1129. ret = ov7740_init_mode(new_frame_rate,
  1130. sensor->streamcap.capturemode);
  1131. if (ret < 0)
  1132. return ret;
  1133.  
  1134. sensor->streamcap.timeperframe = *timeperframe;
  1135. sensor->streamcap.capturemode =
  1136. (u32)a->parm.capture.capturemode;
  1137. break;
  1138.  
  1139. /* These are all the possible cases. */
  1140. case V4L2_BUF_TYPE_VIDEO_OUTPUT:
  1141. case V4L2_BUF_TYPE_VIDEO_OVERLAY:
  1142. case V4L2_BUF_TYPE_VBI_CAPTURE:
  1143. case V4L2_BUF_TYPE_VBI_OUTPUT:
  1144. case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
  1145. case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
  1146. pr_info(" type is not " \
  1147. "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n",
  1148. a->type);
  1149. ret = -EINVAL;
  1150. break;
  1151.  
  1152. default:
  1153. pr_info(" type is unknown - %d\n", a->type);
  1154. ret = -EINVAL;
  1155. break;
  1156. }
  1157.  
  1158. return ret;
  1159. }
  1160.  
  1161. /*!
  1162. * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap
  1163. * @s: pointer to standard V4L2 device structure
  1164. * @f: pointer to standard V4L2 v4l2_format structure
  1165. *
  1166. * Returns the sensor's current pixel format in the v4l2_format
  1167. * parameter.
  1168. */
  1169. static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f)
  1170. {
  1171. struct sensor_data *sensor = s->priv;
  1172.  
  1173. pr_info("%s start\n",__func__);
  1174. f->fmt.pix = sensor->pix;
  1175.  
  1176. return 0;
  1177. }
  1178.  
  1179. /*!
  1180. * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl
  1181. * @s: pointer to standard V4L2 device structure
  1182. * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure
  1183. *
  1184. * If the requested control is supported, returns the control's current
  1185. * value from the video_control[] array. Otherwise, returns -EINVAL
  1186. * if the control is not supported.
  1187. */
  1188. static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
  1189. {
  1190. int ret = 0;
  1191.  
  1192. switch (vc->id) {
  1193. case V4L2_CID_BRIGHTNESS:
  1194. vc->value = ov7740_data.brightness;
  1195. break;
  1196. case V4L2_CID_HUE:
  1197. vc->value = ov7740_data.hue;
  1198. break;
  1199. case V4L2_CID_CONTRAST:
  1200. vc->value = ov7740_data.contrast;
  1201. break;
  1202. case V4L2_CID_SATURATION:
  1203. vc->value = ov7740_data.saturation;
  1204. break;
  1205. case V4L2_CID_RED_BALANCE:
  1206. vc->value = ov7740_data.red;
  1207. break;
  1208. case V4L2_CID_BLUE_BALANCE:
  1209. vc->value = ov7740_data.blue;
  1210. break;
  1211. case V4L2_CID_EXPOSURE:
  1212. vc->value = ov7740_data.ae_mode;
  1213. break;
  1214. default:
  1215. ret = -EINVAL;
  1216. }
  1217.  
  1218. return ret;
  1219. }
  1220.  
  1221. /*!
  1222. * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl
  1223. * @s: pointer to standard V4L2 device structure
  1224. * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure
  1225. *
  1226. * If the requested control is supported, sets the control's current
  1227. * value in HW (and updates the video_control[] array). Otherwise,
  1228. * returns -EINVAL if the control is not supported.
  1229. */
  1230. static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
  1231. {
  1232. int retval = 0;
  1233.  
  1234. pr_info("In ov7740:ioctl_s_ctrl %d\n",
  1235. vc->id);
  1236.  
  1237. switch (vc->id) {
  1238. case V4L2_CID_BRIGHTNESS:
  1239. break;
  1240. case V4L2_CID_CONTRAST:
  1241. break;
  1242. case V4L2_CID_SATURATION:
  1243. break;
  1244. case V4L2_CID_HUE:
  1245. break;
  1246. case V4L2_CID_AUTO_WHITE_BALANCE:
  1247. break;
  1248. case V4L2_CID_DO_WHITE_BALANCE:
  1249. break;
  1250. case V4L2_CID_RED_BALANCE:
  1251. break;
  1252. case V4L2_CID_BLUE_BALANCE:
  1253. break;
  1254. case V4L2_CID_GAMMA:
  1255. break;
  1256. case V4L2_CID_EXPOSURE:
  1257. break;
  1258. case V4L2_CID_AUTOGAIN:
  1259. break;
  1260. case V4L2_CID_GAIN:
  1261. break;
  1262. case V4L2_CID_HFLIP:
  1263. break;
  1264. case V4L2_CID_VFLIP:
  1265. break;
  1266. case V4L2_CID_MXC_ROT:
  1267. case V4L2_CID_MXC_VF_ROT:
  1268. break;
  1269. default:
  1270. retval = -EPERM;
  1271. break;
  1272. }
  1273.  
  1274. return retval;
  1275. }
  1276.  
  1277. /*!
  1278. * ioctl_enum_framesizes - V4L2 sensor interface handler for
  1279. * VIDIOC_ENUM_FRAMESIZES ioctl
  1280. * @s: pointer to standard V4L2 device structure
  1281. * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure
  1282. *
  1283. * Return 0 if successful, otherwise -EINVAL.
  1284. */
  1285. static int ioctl_enum_framesizes(struct v4l2_int_device *s,
  1286. struct v4l2_frmsizeenum *fsize)
  1287. {
  1288. if (fsize->index > ov7740_mode_MAX)
  1289. return -EINVAL;
  1290.  
  1291. fsize->pixel_format = ov7740_data.pix.pixelformat;
  1292. fsize->discrete.width =
  1293. max(ov7740_mode_info_data[0][fsize->index].width,
  1294. ov7740_mode_info_data[1][fsize->index].width);
  1295. fsize->discrete.height =
  1296. max(ov7740_mode_info_data[0][fsize->index].height,
  1297. ov7740_mode_info_data[1][fsize->index].height);
  1298. pr_info("%s get w:%d, h:%d, pixelformat:%s\n",__func__,fsize->discrete.width,fsize->discrete.height,stringize_pixelformat(fsize->pixel_format));
  1299. return 0;
  1300. }
  1301.  
  1302. /*!
  1303. * ioctl_enum_frameintervals - V4L2 sensor interface handler for
  1304. * VIDIOC_ENUM_FRAMEINTERVALS ioctl
  1305. * @s: pointer to standard V4L2 device structure
  1306. * @fival: standard V4L2 VIDIOC_ENUM_FRAMEINTERVALS ioctl structure
  1307. *
  1308. * Return 0 if successful, otherwise -EINVAL.
  1309. */
  1310. static int ioctl_enum_frameintervals(struct v4l2_int_device *s,
  1311. struct v4l2_frmivalenum *fival)
  1312. {
  1313. int i, j, count;
  1314.  
  1315. if (fival->index < 0 || fival->index > ov7740_mode_MAX)
  1316. return -EINVAL;
  1317.  
  1318. if (fival->pixel_format == 0 || fival->width == 0 ||
  1319. fival->height == 0) {
  1320. pr_warning("Please assign pixelformat, width and height.\n");
  1321. return -EINVAL;
  1322. }
  1323.  
  1324. fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
  1325. fival->discrete.numerator = 1;
  1326.  
  1327. count = 0;
  1328. for (i = 0; i < ARRAY_SIZE(ov7740_mode_info_data); i++) {
  1329. for (j = 0; j < (ov7740_mode_MAX + 1); j++) {
  1330. if (fival->pixel_format == ov7740_data.pix.pixelformat
  1331. && fival->width == ov7740_mode_info_data[i][j].width
  1332. && fival->height == ov7740_mode_info_data[i][j].height
  1333. && ov7740_mode_info_data[i][j].init_data_ptr != NULL) {
  1334. count++;
  1335. }
  1336. if (fival->index == (count - 1)) {
  1337. fival->discrete.denominator =
  1338. ov7740_framerates[i];
  1339. return 0;
  1340. }
  1341. }
  1342. }
  1343. pr_info("%s get numerator:%d, denominator:%d\n",__func__,fival->discrete.numerator,fival->discrete.denominator);
  1344.  
  1345. return -EINVAL;
  1346. }
  1347.  
  1348. /*!
  1349. * ioctl_g_chip_ident - V4L2 sensor interface handler for
  1350. * VIDIOC_DBG_G_CHIP_IDENT ioctl
  1351. * @s: pointer to standard V4L2 device structure
  1352. * @id: pointer to int
  1353. *
  1354. * Return 0.
  1355. */
  1356. static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id)
  1357. {
  1358. ((struct v4l2_dbg_chip_ident *)id)->match.type =
  1359. V4L2_CHIP_MATCH_I2C_DRIVER;
  1360. strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name, "ov7740_camera");
  1361.  
  1362. return 0;
  1363. }
  1364.  
  1365. /*!
  1366. * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT
  1367. * @s: pointer to standard V4L2 device structure
  1368. */
  1369. static int ioctl_init(struct v4l2_int_device *s)
  1370. {
  1371.  
  1372. return 0;
  1373. }
  1374.  
  1375. /*!
  1376. * ioctl_enum_fmt_cap - V4L2 sensor interface handler for VIDIOC_ENUM_FMT
  1377. * @s: pointer to standard V4L2 device structure
  1378. * @fmt: pointer to standard V4L2 fmt description structure
  1379. *
  1380. * Return 0.
  1381. */
  1382. static int ioctl_enum_fmt_cap(struct v4l2_int_device *s,
  1383. struct v4l2_fmtdesc *fmt)
  1384. {
  1385. if (fmt->index > 0) /* only 1 pixelformat support so far */
  1386. return -EINVAL;
  1387.  
  1388. fmt->pixelformat = ov7740_data.pix.pixelformat;
  1389.  
  1390. return 0;
  1391. }
  1392.  
  1393. /*!
  1394. * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num
  1395. * @s: pointer to standard V4L2 device structure
  1396. *
  1397. * Initialise the device when slave attaches to the master.
  1398. */
  1399. static int ioctl_dev_init(struct v4l2_int_device *s)
  1400. {
  1401. struct sensor_data *sensor = s->priv;
  1402. u32 tgt_xclk; /* target xclk */
  1403. u32 tgt_fps; /* target frames per secound */
  1404. enum ov7740_frame_rate frame_rate;
  1405.  
  1406. ov7740_data.on = true;
  1407.  
  1408. /* mclk */
  1409. tgt_xclk = ov7740_data.mclk;
  1410. tgt_xclk = min(tgt_xclk, (u32)OV7740_XCLK_MAX);
  1411. tgt_xclk = max(tgt_xclk, (u32)OV7740_XCLK_MIN);
  1412. ov7740_data.mclk = tgt_xclk;
  1413.  
  1414. pr_info(" Setting mclk to %d MHz\n", tgt_xclk / 1000000);
  1415.  
  1416. /* Default camera frame rate is set in probe */
  1417. tgt_fps = sensor->streamcap.timeperframe.denominator /
  1418. sensor->streamcap.timeperframe.numerator;
  1419.  
  1420. if (tgt_fps == 15)
  1421. frame_rate = ov7740_15_fps;
  1422. else if (tgt_fps == 30){
  1423. frame_rate = ov7740_30_fps;
  1424. }
  1425. else
  1426. return -EINVAL; /* Only support 15fps or 30fps now. */
  1427.  
  1428. return ov7740_init_mode(frame_rate,sensor->streamcap.capturemode);
  1429. }
  1430.  
  1431. /*!
  1432. * ioctl_dev_exit - V4L2 sensor interface handler for vidioc_int_dev_exit_num
  1433. * @s: pointer to standard V4L2 device structure
  1434. *
  1435. * Delinitialise the device when slave detaches to the master.
  1436. */
  1437. static int ioctl_dev_exit(struct v4l2_int_device *s)
  1438. {
  1439. return 0;
  1440. }
  1441.  
  1442. /*!
  1443. * This structure defines all the ioctls for this module and links them to the
  1444. * enumeration.
  1445. */
  1446. static struct v4l2_int_ioctl_desc ov7740_ioctl_desc[] = {
  1447. { vidioc_int_dev_init_num,
  1448. (v4l2_int_ioctl_func *)ioctl_dev_init },
  1449. { vidioc_int_dev_exit_num, ioctl_dev_exit},
  1450. { vidioc_int_s_power_num,
  1451. (v4l2_int_ioctl_func *)ioctl_s_power },
  1452. { vidioc_int_g_ifparm_num,
  1453. (v4l2_int_ioctl_func *)ioctl_g_ifparm },
  1454. /* { vidioc_int_g_needs_reset_num,
  1455. (v4l2_int_ioctl_func *)ioctl_g_needs_reset }, */
  1456. /* { vidioc_int_reset_num,
  1457. (v4l2_int_ioctl_func *)ioctl_reset }, */
  1458. { vidioc_int_init_num,
  1459. (v4l2_int_ioctl_func *)ioctl_init },
  1460. { vidioc_int_enum_fmt_cap_num,
  1461. (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap },
  1462. /* { vidioc_int_try_fmt_cap_num,
  1463. (v4l2_int_ioctl_func *)ioctl_try_fmt_cap }, */
  1464. { vidioc_int_g_fmt_cap_num,
  1465. (v4l2_int_ioctl_func *)ioctl_g_fmt_cap },
  1466. /* { vidioc_int_s_fmt_cap_num,
  1467. (v4l2_int_ioctl_func *)ioctl_s_fmt_cap }, */
  1468. { vidioc_int_g_parm_num,
  1469. (v4l2_int_ioctl_func *)ioctl_g_parm },
  1470. { vidioc_int_s_parm_num,
  1471. (v4l2_int_ioctl_func *)ioctl_s_parm },
  1472. /* { vidioc_int_queryctrl_num,
  1473. (v4l2_int_ioctl_func *)ioctl_queryctrl }, */
  1474. { vidioc_int_g_ctrl_num,
  1475. (v4l2_int_ioctl_func *)ioctl_g_ctrl },
  1476. { vidioc_int_s_ctrl_num,
  1477. (v4l2_int_ioctl_func *)ioctl_s_ctrl },
  1478. { vidioc_int_enum_framesizes_num,
  1479. (v4l2_int_ioctl_func *)ioctl_enum_framesizes },
  1480. { vidioc_int_enum_frameintervals_num,
  1481. (v4l2_int_ioctl_func *)ioctl_enum_frameintervals },
  1482. { vidioc_int_g_chip_ident_num,
  1483. (v4l2_int_ioctl_func *)ioctl_g_chip_ident },
  1484. };
  1485.  
  1486. static struct v4l2_int_slave ov7740_slave = {
  1487. .ioctls = ov7740_ioctl_desc,
  1488. .num_ioctls = ARRAY_SIZE(ov7740_ioctl_desc),
  1489. };
  1490.  
  1491. static struct v4l2_int_device ov7740_int_device = {
  1492. .module = THIS_MODULE,
  1493. .name = "ov7740",
  1494. .type = v4l2_int_type_slave,
  1495. .u = {
  1496. .slave = &ov7740_slave,
  1497. },
  1498. };
  1499.  
  1500. /*!
  1501. * ov7740 I2C probe function
  1502. *
  1503. * @param adapter struct i2c_adapter *
  1504. * @return Error code indicating success or failure
  1505. */
  1506. static int ov7740_probe(struct i2c_client *client,
  1507. const struct i2c_device_id *id)
  1508. {
  1509. struct pinctrl *pinctrl;
  1510. struct device *dev = &client->dev;
  1511. int retval;
  1512. u8 chip_id_high, chip_id_low;
  1513.  
  1514. /* ov7740 pinctrl */
  1515. pinctrl = devm_pinctrl_get_select_default(dev);
  1516. if (IS_ERR(pinctrl)) {
  1517. dev_err(dev, "ov7740 setup pinctrl failed!");
  1518. return PTR_ERR(pinctrl);
  1519. }
  1520. #if 0
  1521. /* request power down pin */
  1522. pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0);
  1523. if (!gpio_is_valid(pwn_gpio)) {
  1524. dev_warn(dev, "no sensor pwdn pin available");
  1525. return -EINVAL;
  1526. }
  1527. retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH,
  1528. "ov7740_pwdn");
  1529. if (retval < 0)
  1530. return retval;
  1531.  
  1532. /* request reset pin */
  1533. rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0);
  1534. if (!gpio_is_valid(rst_gpio)) {
  1535. dev_warn(dev, "no sensor reset pin available");
  1536. return -EINVAL;
  1537. }
  1538. retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH,
  1539. "ov7740_reset");
  1540. if (retval < 0)
  1541. return retval;
  1542. #endif
  1543. /* Set initial values for the sensor struct. */
  1544. memset(&ov7740_data, 0, sizeof(ov7740_data));
  1545. ov7740_data.sensor_clk = devm_clk_get(dev, "csi_mclk");
  1546. if (IS_ERR(ov7740_data.sensor_clk)) {
  1547. /* assuming clock enabled by default */
  1548. ov7740_data.sensor_clk = NULL;
  1549. dev_err(dev, "clock-frequency missing or invalid\n");
  1550. return PTR_ERR(ov7740_data.sensor_clk);
  1551. }
  1552. retval = of_property_read_u32(dev->of_node, "mclk",
  1553. (u32 *) &(ov7740_data.mclk));
  1554. if (retval) {
  1555. dev_err(dev, "mclk missing or invalid\n");
  1556. return retval;
  1557. }
  1558. //#define FORCE_27MHZ
  1559. #ifdef FORCE_27MHZ
  1560. ov7740_data.mclk = 27000000; /* Not working ... */
  1561. #endif
  1562. pr_info("Using mclk to %d Hz\n",ov7740_data.mclk);
  1563.  
  1564. retval = of_property_read_u32(dev->of_node, "mclk_source",
  1565. (u32 *) &(ov7740_data.mclk_source));
  1566. if (retval) {
  1567. dev_err(dev, "mclk_source missing or invalid\n");
  1568. return retval;
  1569. }
  1570. pr_info("Using mclk_source to %d\n",ov7740_data.mclk_source);
  1571.  
  1572. retval = of_property_read_u32(dev->of_node, "csi_id",
  1573. &(ov7740_data.csi));
  1574. if (retval) {
  1575. dev_err(dev, "csi_id missing or invalid\n");
  1576. return retval;
  1577. }
  1578.  
  1579. clk_prepare_enable(ov7740_data.sensor_clk);
  1580.  
  1581. ov7740_data.io_init = ov7740_reset;
  1582. ov7740_data.i2c_client = client;
  1583. #ifdef USE_RAW
  1584. ov7740_data.pix.pixelformat = V4L2_PIX_FMT_RGB565;
  1585. #else
  1586. #if 1
  1587. ov7740_data.pix.pixelformat = V4L2_PIX_FMT_YUYV; /* Changed by register 0x0c set 0x12 for YUYV */
  1588. #else
  1589. ov7740_data.pix.pixelformat = V4L2_PIX_FMT_YUV420;
  1590. /* ov7740_data.pix.pixelformat = V4L2_PIX_FMT_YUV422P; */
  1591. #endif
  1592. #endif
  1593. pr_info("Using %s pixelformat\n",stringize_pixelformat(ov7740_data.pix.pixelformat));
  1594. ov7740_data.pix.width = 640;
  1595. ov7740_data.pix.height = 480;
  1596. #if 0
  1597. /* https://community.freescale.com/thread/328880 */
  1598. ov7740_data.pix.priv = 0; /* 1 : indicate TV in format */
  1599. #endif
  1600. /* V4L2_CAP_TIMEPERFRAME which indicates that the device can vary its frame rate */
  1601. /* V4L2_MODE_HIGHQUALITY, intended to put the hardware into a high-quality mode suitable for single-frame captures */
  1602. ov7740_data.streamcap.capability = V4L2_MODE_HIGHQUALITY |
  1603. V4L2_CAP_TIMEPERFRAME;
  1604. ov7740_data.streamcap.capturemode = 0;
  1605. ov7740_data.streamcap.timeperframe.denominator = DEFAULT_FPS;
  1606. ov7740_data.streamcap.timeperframe.numerator = 1;
  1607.  
  1608. ov7740_power_on(&client->dev);
  1609.  
  1610. ov7740_reset();
  1611.  
  1612. ov7740_standby(0);
  1613.  
  1614. retval = ov7740_read_reg(OV7740_CHIP_ID_HIGH_BYTE, &chip_id_high);
  1615. if (retval < 0 || chip_id_high != OV7740_CHIP_ID_HIGH_BYTE_READ) {
  1616. pr_warning("camera ov7740 is not found\n");
  1617. clk_disable_unprepare(ov7740_data.sensor_clk);
  1618. return -ENODEV;
  1619. }
  1620. retval = ov7740_read_reg(OV7740_CHIP_ID_LOW_BYTE, &chip_id_low);
  1621. if (retval < 0 || chip_id_low != OV7740_CHIP_ID_LOW_BYTE_READ) {
  1622. pr_warning("camera ov7740 is not found\n");
  1623. clk_disable_unprepare(ov7740_data.sensor_clk);
  1624. return -ENODEV;
  1625. }
  1626.  
  1627. ov7740_standby(1);
  1628.  
  1629. ov7740_int_device.priv = &ov7740_data;
  1630. retval = v4l2_int_device_register(&ov7740_int_device);
  1631.  
  1632. pr_info("camera ov7740 is found\n");
  1633. return retval;
  1634. }
  1635.  
  1636. /*!
  1637. * ov7740 I2C detach function
  1638. *
  1639. * @param client struct i2c_client *
  1640. * @return Error code indicating success or failure
  1641. */
  1642. static int ov7740_remove(struct i2c_client *client)
  1643. {
  1644. v4l2_int_device_unregister(&ov7740_int_device);
  1645. //TODO
  1646. //clk_disable_unprepare(ov7740_data.sensor_clk);
  1647.  
  1648. if (gpo_regulator)
  1649. regulator_disable(gpo_regulator);
  1650.  
  1651. if (analog_regulator)
  1652. regulator_disable(analog_regulator);
  1653.  
  1654. if (core_regulator)
  1655. regulator_disable(core_regulator);
  1656.  
  1657. if (io_regulator)
  1658. regulator_disable(io_regulator);
  1659.  
  1660. return 0;
  1661. }
  1662.  
  1663. /*!
  1664. * ov7740 init function
  1665. * Called by insmod ov7740_camera.ko.
  1666. *
  1667. * @return Error code indicating success or failure
  1668. */
  1669. static __init int ov7740_init(void)
  1670. {
  1671. u8 err;
  1672.  
  1673. err = i2c_add_driver(&ov7740_i2c_driver);
  1674. if (err != 0)
  1675. pr_err("%s:driver registration failed, error=%d\n",
  1676. __func__, err);
  1677.  
  1678. return err;
  1679. }
  1680.  
  1681. /*!
  1682. * OV7740 cleanup function
  1683. * Called on rmmod ov7740_camera.ko
  1684. *
  1685. * @return Error code indicating success or failure
  1686. */
  1687. static void __exit ov7740_clean(void)
  1688. {
  1689. i2c_del_driver(&ov7740_i2c_driver);
  1690. }
  1691.  
  1692. module_init(ov7740_init);
  1693. module_exit(ov7740_clean);
  1694.  
  1695. MODULE_AUTHOR("Aurelien BOUIN");
  1696. MODULE_DESCRIPTION("OV7740 Camera Driver");
  1697. MODULE_LICENSE("GPL");
  1698. MODULE_VERSION("1.0");
  1699. MODULE_ALIAS("CSI");
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement