/drivers/media/video/gspca/m5602/m5602_po1030.c

https://bitbucket.org/wisechild/galaxy-nexus · C · 762 lines · 613 code · 127 blank · 22 comment · 63 complexity · 2d28d0fd738584aad108dd7833c6efc3 MD5 · raw file

  1. /*
  2. * Driver for the po1030 sensor
  3. *
  4. * Copyright (c) 2008 Erik Andrén
  5. * Copyright (c) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
  6. * Copyright (c) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
  7. *
  8. * Portions of code to USB interface and ALi driver software,
  9. * Copyright (c) 2006 Willem Duinker
  10. * v4l2 interface modeled after the V4L2 driver
  11. * for SN9C10x PC Camera Controllers
  12. *
  13. * This program is free software; you can redistribute it and/or
  14. * modify it under the terms of the GNU General Public License as
  15. * published by the Free Software Foundation, version 2.
  16. *
  17. */
  18. #include "m5602_po1030.h"
  19. static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
  20. static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
  21. static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
  22. static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val);
  23. static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
  24. static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
  25. static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
  26. static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
  27. static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val);
  28. static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val);
  29. static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
  30. static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
  31. static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
  32. static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
  33. static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev,
  34. __s32 val);
  35. static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev,
  36. __s32 *val);
  37. static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev,
  38. __s32 val);
  39. static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev,
  40. __s32 *val);
  41. static struct v4l2_pix_format po1030_modes[] = {
  42. {
  43. 640,
  44. 480,
  45. V4L2_PIX_FMT_SBGGR8,
  46. V4L2_FIELD_NONE,
  47. .sizeimage = 640 * 480,
  48. .bytesperline = 640,
  49. .colorspace = V4L2_COLORSPACE_SRGB,
  50. .priv = 2
  51. }
  52. };
  53. static const struct ctrl po1030_ctrls[] = {
  54. #define GAIN_IDX 0
  55. {
  56. {
  57. .id = V4L2_CID_GAIN,
  58. .type = V4L2_CTRL_TYPE_INTEGER,
  59. .name = "gain",
  60. .minimum = 0x00,
  61. .maximum = 0x4f,
  62. .step = 0x1,
  63. .default_value = PO1030_GLOBAL_GAIN_DEFAULT,
  64. .flags = V4L2_CTRL_FLAG_SLIDER
  65. },
  66. .set = po1030_set_gain,
  67. .get = po1030_get_gain
  68. },
  69. #define EXPOSURE_IDX 1
  70. {
  71. {
  72. .id = V4L2_CID_EXPOSURE,
  73. .type = V4L2_CTRL_TYPE_INTEGER,
  74. .name = "exposure",
  75. .minimum = 0x00,
  76. .maximum = 0x02ff,
  77. .step = 0x1,
  78. .default_value = PO1030_EXPOSURE_DEFAULT,
  79. .flags = V4L2_CTRL_FLAG_SLIDER
  80. },
  81. .set = po1030_set_exposure,
  82. .get = po1030_get_exposure
  83. },
  84. #define RED_BALANCE_IDX 2
  85. {
  86. {
  87. .id = V4L2_CID_RED_BALANCE,
  88. .type = V4L2_CTRL_TYPE_INTEGER,
  89. .name = "red balance",
  90. .minimum = 0x00,
  91. .maximum = 0xff,
  92. .step = 0x1,
  93. .default_value = PO1030_RED_GAIN_DEFAULT,
  94. .flags = V4L2_CTRL_FLAG_SLIDER
  95. },
  96. .set = po1030_set_red_balance,
  97. .get = po1030_get_red_balance
  98. },
  99. #define BLUE_BALANCE_IDX 3
  100. {
  101. {
  102. .id = V4L2_CID_BLUE_BALANCE,
  103. .type = V4L2_CTRL_TYPE_INTEGER,
  104. .name = "blue balance",
  105. .minimum = 0x00,
  106. .maximum = 0xff,
  107. .step = 0x1,
  108. .default_value = PO1030_BLUE_GAIN_DEFAULT,
  109. .flags = V4L2_CTRL_FLAG_SLIDER
  110. },
  111. .set = po1030_set_blue_balance,
  112. .get = po1030_get_blue_balance
  113. },
  114. #define HFLIP_IDX 4
  115. {
  116. {
  117. .id = V4L2_CID_HFLIP,
  118. .type = V4L2_CTRL_TYPE_BOOLEAN,
  119. .name = "horizontal flip",
  120. .minimum = 0,
  121. .maximum = 1,
  122. .step = 1,
  123. .default_value = 0,
  124. },
  125. .set = po1030_set_hflip,
  126. .get = po1030_get_hflip
  127. },
  128. #define VFLIP_IDX 5
  129. {
  130. {
  131. .id = V4L2_CID_VFLIP,
  132. .type = V4L2_CTRL_TYPE_BOOLEAN,
  133. .name = "vertical flip",
  134. .minimum = 0,
  135. .maximum = 1,
  136. .step = 1,
  137. .default_value = 0,
  138. },
  139. .set = po1030_set_vflip,
  140. .get = po1030_get_vflip
  141. },
  142. #define AUTO_WHITE_BALANCE_IDX 6
  143. {
  144. {
  145. .id = V4L2_CID_AUTO_WHITE_BALANCE,
  146. .type = V4L2_CTRL_TYPE_BOOLEAN,
  147. .name = "auto white balance",
  148. .minimum = 0,
  149. .maximum = 1,
  150. .step = 1,
  151. .default_value = 0,
  152. },
  153. .set = po1030_set_auto_white_balance,
  154. .get = po1030_get_auto_white_balance
  155. },
  156. #define AUTO_EXPOSURE_IDX 7
  157. {
  158. {
  159. .id = V4L2_CID_EXPOSURE_AUTO,
  160. .type = V4L2_CTRL_TYPE_BOOLEAN,
  161. .name = "auto exposure",
  162. .minimum = 0,
  163. .maximum = 1,
  164. .step = 1,
  165. .default_value = 0,
  166. },
  167. .set = po1030_set_auto_exposure,
  168. .get = po1030_get_auto_exposure
  169. },
  170. #define GREEN_BALANCE_IDX 8
  171. {
  172. {
  173. .id = M5602_V4L2_CID_GREEN_BALANCE,
  174. .type = V4L2_CTRL_TYPE_INTEGER,
  175. .name = "green balance",
  176. .minimum = 0x00,
  177. .maximum = 0xff,
  178. .step = 0x1,
  179. .default_value = PO1030_GREEN_GAIN_DEFAULT,
  180. .flags = V4L2_CTRL_FLAG_SLIDER
  181. },
  182. .set = po1030_set_green_balance,
  183. .get = po1030_get_green_balance
  184. },
  185. };
  186. static void po1030_dump_registers(struct sd *sd);
  187. int po1030_probe(struct sd *sd)
  188. {
  189. u8 dev_id_h = 0, i;
  190. s32 *sensor_settings;
  191. if (force_sensor) {
  192. if (force_sensor == PO1030_SENSOR) {
  193. info("Forcing a %s sensor", po1030.name);
  194. goto sensor_found;
  195. }
  196. /* If we want to force another sensor, don't try to probe this
  197. * one */
  198. return -ENODEV;
  199. }
  200. PDEBUG(D_PROBE, "Probing for a po1030 sensor");
  201. /* Run the pre-init to actually probe the unit */
  202. for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) {
  203. u8 data = preinit_po1030[i][2];
  204. if (preinit_po1030[i][0] == SENSOR)
  205. m5602_write_sensor(sd,
  206. preinit_po1030[i][1], &data, 1);
  207. else
  208. m5602_write_bridge(sd, preinit_po1030[i][1], data);
  209. }
  210. if (m5602_read_sensor(sd, PO1030_DEVID_H, &dev_id_h, 1))
  211. return -ENODEV;
  212. if (dev_id_h == 0x30) {
  213. info("Detected a po1030 sensor");
  214. goto sensor_found;
  215. }
  216. return -ENODEV;
  217. sensor_found:
  218. sensor_settings = kmalloc(
  219. ARRAY_SIZE(po1030_ctrls) * sizeof(s32), GFP_KERNEL);
  220. if (!sensor_settings)
  221. return -ENOMEM;
  222. sd->gspca_dev.cam.cam_mode = po1030_modes;
  223. sd->gspca_dev.cam.nmodes = ARRAY_SIZE(po1030_modes);
  224. sd->desc->ctrls = po1030_ctrls;
  225. sd->desc->nctrls = ARRAY_SIZE(po1030_ctrls);
  226. for (i = 0; i < ARRAY_SIZE(po1030_ctrls); i++)
  227. sensor_settings[i] = po1030_ctrls[i].qctrl.default_value;
  228. sd->sensor_priv = sensor_settings;
  229. return 0;
  230. }
  231. int po1030_init(struct sd *sd)
  232. {
  233. s32 *sensor_settings = sd->sensor_priv;
  234. int i, err = 0;
  235. /* Init the sensor */
  236. for (i = 0; i < ARRAY_SIZE(init_po1030) && !err; i++) {
  237. u8 data[2] = {0x00, 0x00};
  238. switch (init_po1030[i][0]) {
  239. case BRIDGE:
  240. err = m5602_write_bridge(sd,
  241. init_po1030[i][1],
  242. init_po1030[i][2]);
  243. break;
  244. case SENSOR:
  245. data[0] = init_po1030[i][2];
  246. err = m5602_write_sensor(sd,
  247. init_po1030[i][1], data, 1);
  248. break;
  249. default:
  250. info("Invalid stream command, exiting init");
  251. return -EINVAL;
  252. }
  253. }
  254. if (err < 0)
  255. return err;
  256. if (dump_sensor)
  257. po1030_dump_registers(sd);
  258. err = po1030_set_exposure(&sd->gspca_dev,
  259. sensor_settings[EXPOSURE_IDX]);
  260. if (err < 0)
  261. return err;
  262. err = po1030_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
  263. if (err < 0)
  264. return err;
  265. err = po1030_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
  266. if (err < 0)
  267. return err;
  268. err = po1030_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
  269. if (err < 0)
  270. return err;
  271. err = po1030_set_red_balance(&sd->gspca_dev,
  272. sensor_settings[RED_BALANCE_IDX]);
  273. if (err < 0)
  274. return err;
  275. err = po1030_set_blue_balance(&sd->gspca_dev,
  276. sensor_settings[BLUE_BALANCE_IDX]);
  277. if (err < 0)
  278. return err;
  279. err = po1030_set_green_balance(&sd->gspca_dev,
  280. sensor_settings[GREEN_BALANCE_IDX]);
  281. if (err < 0)
  282. return err;
  283. err = po1030_set_auto_white_balance(&sd->gspca_dev,
  284. sensor_settings[AUTO_WHITE_BALANCE_IDX]);
  285. if (err < 0)
  286. return err;
  287. err = po1030_set_auto_exposure(&sd->gspca_dev,
  288. sensor_settings[AUTO_EXPOSURE_IDX]);
  289. return err;
  290. }
  291. int po1030_start(struct sd *sd)
  292. {
  293. struct cam *cam = &sd->gspca_dev.cam;
  294. int i, err = 0;
  295. int width = cam->cam_mode[sd->gspca_dev.curr_mode].width;
  296. int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
  297. int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
  298. u8 data;
  299. switch (width) {
  300. case 320:
  301. data = PO1030_SUBSAMPLING;
  302. err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1);
  303. if (err < 0)
  304. return err;
  305. data = ((width + 3) >> 8) & 0xff;
  306. err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1);
  307. if (err < 0)
  308. return err;
  309. data = (width + 3) & 0xff;
  310. err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_L, &data, 1);
  311. if (err < 0)
  312. return err;
  313. data = ((height + 1) >> 8) & 0xff;
  314. err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_H, &data, 1);
  315. if (err < 0)
  316. return err;
  317. data = (height + 1) & 0xff;
  318. err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1);
  319. height += 6;
  320. width -= 1;
  321. break;
  322. case 640:
  323. data = 0;
  324. err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1);
  325. if (err < 0)
  326. return err;
  327. data = ((width + 7) >> 8) & 0xff;
  328. err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1);
  329. if (err < 0)
  330. return err;
  331. data = (width + 7) & 0xff;
  332. err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_L, &data, 1);
  333. if (err < 0)
  334. return err;
  335. data = ((height + 3) >> 8) & 0xff;
  336. err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_H, &data, 1);
  337. if (err < 0)
  338. return err;
  339. data = (height + 3) & 0xff;
  340. err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1);
  341. height += 12;
  342. width -= 2;
  343. break;
  344. }
  345. err = m5602_write_bridge(sd, M5602_XB_SENSOR_TYPE, 0x0c);
  346. if (err < 0)
  347. return err;
  348. err = m5602_write_bridge(sd, M5602_XB_LINE_OF_FRAME_H, 0x81);
  349. if (err < 0)
  350. return err;
  351. err = m5602_write_bridge(sd, M5602_XB_PIX_OF_LINE_H, 0x82);
  352. if (err < 0)
  353. return err;
  354. err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0x01);
  355. if (err < 0)
  356. return err;
  357. err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA,
  358. ((ver_offs >> 8) & 0xff));
  359. if (err < 0)
  360. return err;
  361. err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff));
  362. if (err < 0)
  363. return err;
  364. for (i = 0; i < 2 && !err; i++)
  365. err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
  366. if (err < 0)
  367. return err;
  368. err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
  369. if (err < 0)
  370. return err;
  371. err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
  372. if (err < 0)
  373. return err;
  374. for (i = 0; i < 2 && !err; i++)
  375. err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
  376. for (i = 0; i < 2 && !err; i++)
  377. err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
  378. for (i = 0; i < 2 && !err; i++)
  379. err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0);
  380. if (err < 0)
  381. return err;
  382. err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width >> 8) & 0xff);
  383. if (err < 0)
  384. return err;
  385. err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width & 0xff));
  386. if (err < 0)
  387. return err;
  388. err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
  389. return err;
  390. }
  391. static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
  392. {
  393. struct sd *sd = (struct sd *) gspca_dev;
  394. s32 *sensor_settings = sd->sensor_priv;
  395. *val = sensor_settings[EXPOSURE_IDX];
  396. PDEBUG(D_V4L2, "Exposure read as %d", *val);
  397. return 0;
  398. }
  399. static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
  400. {
  401. struct sd *sd = (struct sd *) gspca_dev;
  402. s32 *sensor_settings = sd->sensor_priv;
  403. u8 i2c_data;
  404. int err;
  405. sensor_settings[EXPOSURE_IDX] = val;
  406. PDEBUG(D_V4L2, "Set exposure to %d", val & 0xffff);
  407. i2c_data = ((val & 0xff00) >> 8);
  408. PDEBUG(D_V4L2, "Set exposure to high byte to 0x%x",
  409. i2c_data);
  410. err = m5602_write_sensor(sd, PO1030_INTEGLINES_H,
  411. &i2c_data, 1);
  412. if (err < 0)
  413. return err;
  414. i2c_data = (val & 0xff);
  415. PDEBUG(D_V4L2, "Set exposure to low byte to 0x%x",
  416. i2c_data);
  417. err = m5602_write_sensor(sd, PO1030_INTEGLINES_M,
  418. &i2c_data, 1);
  419. return err;
  420. }
  421. static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
  422. {
  423. struct sd *sd = (struct sd *) gspca_dev;
  424. s32 *sensor_settings = sd->sensor_priv;
  425. *val = sensor_settings[GAIN_IDX];
  426. PDEBUG(D_V4L2, "Read global gain %d", *val);
  427. return 0;
  428. }
  429. static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val)
  430. {
  431. struct sd *sd = (struct sd *) gspca_dev;
  432. s32 *sensor_settings = sd->sensor_priv;
  433. u8 i2c_data;
  434. int err;
  435. sensor_settings[GAIN_IDX] = val;
  436. i2c_data = val & 0xff;
  437. PDEBUG(D_V4L2, "Set global gain to %d", i2c_data);
  438. err = m5602_write_sensor(sd, PO1030_GLOBALGAIN,
  439. &i2c_data, 1);
  440. return err;
  441. }
  442. static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
  443. {
  444. struct sd *sd = (struct sd *) gspca_dev;
  445. s32 *sensor_settings = sd->sensor_priv;
  446. *val = sensor_settings[HFLIP_IDX];
  447. PDEBUG(D_V4L2, "Read hflip %d", *val);
  448. return 0;
  449. }
  450. static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
  451. {
  452. struct sd *sd = (struct sd *) gspca_dev;
  453. s32 *sensor_settings = sd->sensor_priv;
  454. u8 i2c_data;
  455. int err;
  456. sensor_settings[HFLIP_IDX] = val;
  457. PDEBUG(D_V4L2, "Set hflip %d", val);
  458. err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
  459. if (err < 0)
  460. return err;
  461. i2c_data = (0x7f & i2c_data) | ((val & 0x01) << 7);
  462. err = m5602_write_sensor(sd, PO1030_CONTROL2,
  463. &i2c_data, 1);
  464. return err;
  465. }
  466. static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
  467. {
  468. struct sd *sd = (struct sd *) gspca_dev;
  469. s32 *sensor_settings = sd->sensor_priv;
  470. *val = sensor_settings[VFLIP_IDX];
  471. PDEBUG(D_V4L2, "Read vflip %d", *val);
  472. return 0;
  473. }
  474. static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
  475. {
  476. struct sd *sd = (struct sd *) gspca_dev;
  477. s32 *sensor_settings = sd->sensor_priv;
  478. u8 i2c_data;
  479. int err;
  480. sensor_settings[VFLIP_IDX] = val;
  481. PDEBUG(D_V4L2, "Set vflip %d", val);
  482. err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
  483. if (err < 0)
  484. return err;
  485. i2c_data = (i2c_data & 0xbf) | ((val & 0x01) << 6);
  486. err = m5602_write_sensor(sd, PO1030_CONTROL2,
  487. &i2c_data, 1);
  488. return err;
  489. }
  490. static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
  491. {
  492. struct sd *sd = (struct sd *) gspca_dev;
  493. s32 *sensor_settings = sd->sensor_priv;
  494. *val = sensor_settings[RED_BALANCE_IDX];
  495. PDEBUG(D_V4L2, "Read red gain %d", *val);
  496. return 0;
  497. }
  498. static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
  499. {
  500. struct sd *sd = (struct sd *) gspca_dev;
  501. s32 *sensor_settings = sd->sensor_priv;
  502. u8 i2c_data;
  503. int err;
  504. sensor_settings[RED_BALANCE_IDX] = val;
  505. i2c_data = val & 0xff;
  506. PDEBUG(D_V4L2, "Set red gain to %d", i2c_data);
  507. err = m5602_write_sensor(sd, PO1030_RED_GAIN,
  508. &i2c_data, 1);
  509. return err;
  510. }
  511. static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
  512. {
  513. struct sd *sd = (struct sd *) gspca_dev;
  514. s32 *sensor_settings = sd->sensor_priv;
  515. *val = sensor_settings[BLUE_BALANCE_IDX];
  516. PDEBUG(D_V4L2, "Read blue gain %d", *val);
  517. return 0;
  518. }
  519. static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
  520. {
  521. struct sd *sd = (struct sd *) gspca_dev;
  522. s32 *sensor_settings = sd->sensor_priv;
  523. u8 i2c_data;
  524. int err;
  525. sensor_settings[BLUE_BALANCE_IDX] = val;
  526. i2c_data = val & 0xff;
  527. PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data);
  528. err = m5602_write_sensor(sd, PO1030_BLUE_GAIN,
  529. &i2c_data, 1);
  530. return err;
  531. }
  532. static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val)
  533. {
  534. struct sd *sd = (struct sd *) gspca_dev;
  535. s32 *sensor_settings = sd->sensor_priv;
  536. *val = sensor_settings[GREEN_BALANCE_IDX];
  537. PDEBUG(D_V4L2, "Read green gain %d", *val);
  538. return 0;
  539. }
  540. static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
  541. {
  542. struct sd *sd = (struct sd *) gspca_dev;
  543. s32 *sensor_settings = sd->sensor_priv;
  544. u8 i2c_data;
  545. int err;
  546. sensor_settings[GREEN_BALANCE_IDX] = val;
  547. i2c_data = val & 0xff;
  548. PDEBUG(D_V4L2, "Set green gain to %d", i2c_data);
  549. err = m5602_write_sensor(sd, PO1030_GREEN_1_GAIN,
  550. &i2c_data, 1);
  551. if (err < 0)
  552. return err;
  553. return m5602_write_sensor(sd, PO1030_GREEN_2_GAIN,
  554. &i2c_data, 1);
  555. }
  556. static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev,
  557. __s32 *val)
  558. {
  559. struct sd *sd = (struct sd *) gspca_dev;
  560. s32 *sensor_settings = sd->sensor_priv;
  561. *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
  562. PDEBUG(D_V4L2, "Auto white balancing is %d", *val);
  563. return 0;
  564. }
  565. static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev,
  566. __s32 val)
  567. {
  568. struct sd *sd = (struct sd *) gspca_dev;
  569. s32 *sensor_settings = sd->sensor_priv;
  570. u8 i2c_data;
  571. int err;
  572. sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
  573. err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
  574. if (err < 0)
  575. return err;
  576. PDEBUG(D_V4L2, "Set auto white balance to %d", val);
  577. i2c_data = (i2c_data & 0xfe) | (val & 0x01);
  578. err = m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
  579. return err;
  580. }
  581. static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev,
  582. __s32 *val)
  583. {
  584. struct sd *sd = (struct sd *) gspca_dev;
  585. s32 *sensor_settings = sd->sensor_priv;
  586. *val = sensor_settings[AUTO_EXPOSURE_IDX];
  587. PDEBUG(D_V4L2, "Auto exposure is %d", *val);
  588. return 0;
  589. }
  590. static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev,
  591. __s32 val)
  592. {
  593. struct sd *sd = (struct sd *) gspca_dev;
  594. s32 *sensor_settings = sd->sensor_priv;
  595. u8 i2c_data;
  596. int err;
  597. sensor_settings[AUTO_EXPOSURE_IDX] = val;
  598. err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
  599. if (err < 0)
  600. return err;
  601. PDEBUG(D_V4L2, "Set auto exposure to %d", val);
  602. i2c_data = (i2c_data & 0xfd) | ((val & 0x01) << 1);
  603. return m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
  604. }
  605. void po1030_disconnect(struct sd *sd)
  606. {
  607. sd->sensor = NULL;
  608. kfree(sd->sensor_priv);
  609. }
  610. static void po1030_dump_registers(struct sd *sd)
  611. {
  612. int address;
  613. u8 value = 0;
  614. info("Dumping the po1030 sensor core registers");
  615. for (address = 0; address < 0x7f; address++) {
  616. m5602_read_sensor(sd, address, &value, 1);
  617. info("register 0x%x contains 0x%x",
  618. address, value);
  619. }
  620. info("po1030 register state dump complete");
  621. info("Probing for which registers that are read/write");
  622. for (address = 0; address < 0xff; address++) {
  623. u8 old_value, ctrl_value;
  624. u8 test_value[2] = {0xff, 0xff};
  625. m5602_read_sensor(sd, address, &old_value, 1);
  626. m5602_write_sensor(sd, address, test_value, 1);
  627. m5602_read_sensor(sd, address, &ctrl_value, 1);
  628. if (ctrl_value == test_value[0])
  629. info("register 0x%x is writeable", address);
  630. else
  631. info("register 0x%x is read only", address);
  632. /* Restore original value */
  633. m5602_write_sensor(sd, address, &old_value, 1);
  634. }
  635. }