m5602_s5k4aa.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. /*
  2. * Driver for the s5k4aa 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_s5k4aa.h"
  19. static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
  20. static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
  21. static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
  22. static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
  23. static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
  24. static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
  25. static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
  26. static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val);
  27. static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val);
  28. static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val);
  29. static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
  30. static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
  31. static
  32. const
  33. struct dmi_system_id s5k4aa_vflip_dmi_table[] = {
  34. {
  35. .ident = "Fujitsu-Siemens Amilo Xa 2528",
  36. .matches = {
  37. DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
  38. DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xa 2528")
  39. }
  40. }, {
  41. .ident = "Fujitsu-Siemens Amilo Xi 2550",
  42. .matches = {
  43. DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
  44. DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2550")
  45. }
  46. }, {
  47. .ident = "MSI GX700",
  48. .matches = {
  49. DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
  50. DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
  51. DMI_MATCH(DMI_BIOS_DATE, "07/26/2007")
  52. }
  53. }, {
  54. .ident = "MSI GX700/GX705/EX700",
  55. .matches = {
  56. DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
  57. DMI_MATCH(DMI_PRODUCT_NAME, "GX700/GX705/EX700")
  58. }
  59. }, {
  60. .ident = "MSI L735",
  61. .matches = {
  62. DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
  63. DMI_MATCH(DMI_PRODUCT_NAME, "MS-1717X")
  64. }
  65. }, {
  66. .ident = "Lenovo Y300",
  67. .matches = {
  68. DMI_MATCH(DMI_SYS_VENDOR, "L3000 Y300"),
  69. DMI_MATCH(DMI_PRODUCT_NAME, "Y300")
  70. }
  71. },
  72. { }
  73. };
  74. static struct v4l2_pix_format s5k4aa_modes[] = {
  75. {
  76. 640,
  77. 480,
  78. V4L2_PIX_FMT_SBGGR8,
  79. V4L2_FIELD_NONE,
  80. .sizeimage =
  81. 640 * 480,
  82. .bytesperline = 640,
  83. .colorspace = V4L2_COLORSPACE_SRGB,
  84. .priv = 0
  85. },
  86. {
  87. 1280,
  88. 1024,
  89. V4L2_PIX_FMT_SBGGR8,
  90. V4L2_FIELD_NONE,
  91. .sizeimage =
  92. 1280 * 1024,
  93. .bytesperline = 1280,
  94. .colorspace = V4L2_COLORSPACE_SRGB,
  95. .priv = 0
  96. }
  97. };
  98. static const struct ctrl s5k4aa_ctrls[] = {
  99. #define VFLIP_IDX 0
  100. {
  101. {
  102. .id = V4L2_CID_VFLIP,
  103. .type = V4L2_CTRL_TYPE_BOOLEAN,
  104. .name = "vertical flip",
  105. .minimum = 0,
  106. .maximum = 1,
  107. .step = 1,
  108. .default_value = 0
  109. },
  110. .set = s5k4aa_set_vflip,
  111. .get = s5k4aa_get_vflip
  112. },
  113. #define HFLIP_IDX 1
  114. {
  115. {
  116. .id = V4L2_CID_HFLIP,
  117. .type = V4L2_CTRL_TYPE_BOOLEAN,
  118. .name = "horizontal flip",
  119. .minimum = 0,
  120. .maximum = 1,
  121. .step = 1,
  122. .default_value = 0
  123. },
  124. .set = s5k4aa_set_hflip,
  125. .get = s5k4aa_get_hflip
  126. },
  127. #define GAIN_IDX 2
  128. {
  129. {
  130. .id = V4L2_CID_GAIN,
  131. .type = V4L2_CTRL_TYPE_INTEGER,
  132. .name = "Gain",
  133. .minimum = 0,
  134. .maximum = 127,
  135. .step = 1,
  136. .default_value = S5K4AA_DEFAULT_GAIN,
  137. .flags = V4L2_CTRL_FLAG_SLIDER
  138. },
  139. .set = s5k4aa_set_gain,
  140. .get = s5k4aa_get_gain
  141. },
  142. #define EXPOSURE_IDX 3
  143. {
  144. {
  145. .id = V4L2_CID_EXPOSURE,
  146. .type = V4L2_CTRL_TYPE_INTEGER,
  147. .name = "Exposure",
  148. .minimum = 13,
  149. .maximum = 0xfff,
  150. .step = 1,
  151. .default_value = 0x100,
  152. .flags = V4L2_CTRL_FLAG_SLIDER
  153. },
  154. .set = s5k4aa_set_exposure,
  155. .get = s5k4aa_get_exposure
  156. },
  157. #define NOISE_SUPP_IDX 4
  158. {
  159. {
  160. .id = V4L2_CID_PRIVATE_BASE,
  161. .type = V4L2_CTRL_TYPE_BOOLEAN,
  162. .name = "Noise suppression (smoothing)",
  163. .minimum = 0,
  164. .maximum = 1,
  165. .step = 1,
  166. .default_value = 1,
  167. },
  168. .set = s5k4aa_set_noise,
  169. .get = s5k4aa_get_noise
  170. },
  171. #define BRIGHTNESS_IDX 5
  172. {
  173. {
  174. .id = V4L2_CID_BRIGHTNESS,
  175. .type = V4L2_CTRL_TYPE_INTEGER,
  176. .name = "Brightness",
  177. .minimum = 0,
  178. .maximum = 0x1f,
  179. .step = 1,
  180. .default_value = S5K4AA_DEFAULT_BRIGHTNESS,
  181. },
  182. .set = s5k4aa_set_brightness,
  183. .get = s5k4aa_get_brightness
  184. },
  185. };
  186. static void s5k4aa_dump_registers(struct sd *sd);
  187. int s5k4aa_probe(struct sd *sd)
  188. {
  189. u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  190. const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75};
  191. int i, err = 0;
  192. s32 *sensor_settings;
  193. if (force_sensor) {
  194. if (force_sensor == S5K4AA_SENSOR) {
  195. info("Forcing a %s sensor", s5k4aa.name);
  196. goto sensor_found;
  197. }
  198. /* If we want to force another sensor, don't try to probe this
  199. * one */
  200. return -ENODEV;
  201. }
  202. info("Probing for a s5k4aa sensor");
  203. /* Preinit the sensor */
  204. for (i = 0; i < ARRAY_SIZE(preinit_s5k4aa) && !err; i++) {
  205. u8 data[2] = {0x00, 0x00};
  206. switch (preinit_s5k4aa[i][0]) {
  207. case BRIDGE:
  208. err = m5602_write_bridge(sd,
  209. preinit_s5k4aa[i][1],
  210. preinit_s5k4aa[i][2]);
  211. break;
  212. case SENSOR:
  213. data[0] = preinit_s5k4aa[i][2];
  214. err = m5602_write_sensor(sd,
  215. preinit_s5k4aa[i][1],
  216. data, 1);
  217. break;
  218. case SENSOR_LONG:
  219. data[0] = preinit_s5k4aa[i][2];
  220. data[1] = preinit_s5k4aa[i][3];
  221. err = m5602_write_sensor(sd,
  222. preinit_s5k4aa[i][1],
  223. data, 2);
  224. break;
  225. default:
  226. info("Invalid stream command, exiting init");
  227. return -EINVAL;
  228. }
  229. }
  230. /* Test some registers, but we don't know their exact meaning yet */
  231. if (m5602_read_sensor(sd, 0x00, prod_id, 2))
  232. return -ENODEV;
  233. if (m5602_read_sensor(sd, 0x02, prod_id+2, 2))
  234. return -ENODEV;
  235. if (m5602_read_sensor(sd, 0x04, prod_id+4, 2))
  236. return -ENODEV;
  237. if (memcmp(prod_id, expected_prod_id, sizeof(prod_id)))
  238. return -ENODEV;
  239. else
  240. info("Detected a s5k4aa sensor");
  241. sensor_found:
  242. sensor_settings = kmalloc(
  243. ARRAY_SIZE(s5k4aa_ctrls) * sizeof(s32), GFP_KERNEL);
  244. if (!sensor_settings)
  245. return -ENOMEM;
  246. sd->gspca_dev.cam.cam_mode = s5k4aa_modes;
  247. sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k4aa_modes);
  248. sd->desc->ctrls = s5k4aa_ctrls;
  249. sd->desc->nctrls = ARRAY_SIZE(s5k4aa_ctrls);
  250. for (i = 0; i < ARRAY_SIZE(s5k4aa_ctrls); i++)
  251. sensor_settings[i] = s5k4aa_ctrls[i].qctrl.default_value;
  252. sd->sensor_priv = sensor_settings;
  253. return 0;
  254. }
  255. int s5k4aa_start(struct sd *sd)
  256. {
  257. int i, err = 0;
  258. u8 data[2];
  259. struct cam *cam = &sd->gspca_dev.cam;
  260. s32 *sensor_settings = sd->sensor_priv;
  261. switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) {
  262. case 1280:
  263. PDEBUG(D_V4L2, "Configuring camera for SXGA mode");
  264. for (i = 0; i < ARRAY_SIZE(SXGA_s5k4aa); i++) {
  265. switch (SXGA_s5k4aa[i][0]) {
  266. case BRIDGE:
  267. err = m5602_write_bridge(sd,
  268. SXGA_s5k4aa[i][1],
  269. SXGA_s5k4aa[i][2]);
  270. break;
  271. case SENSOR:
  272. data[0] = SXGA_s5k4aa[i][2];
  273. err = m5602_write_sensor(sd,
  274. SXGA_s5k4aa[i][1],
  275. data, 1);
  276. break;
  277. case SENSOR_LONG:
  278. data[0] = SXGA_s5k4aa[i][2];
  279. data[1] = SXGA_s5k4aa[i][3];
  280. err = m5602_write_sensor(sd,
  281. SXGA_s5k4aa[i][1],
  282. data, 2);
  283. break;
  284. default:
  285. err("Invalid stream command, exiting init");
  286. return -EINVAL;
  287. }
  288. }
  289. err = s5k4aa_set_noise(&sd->gspca_dev, 0);
  290. if (err < 0)
  291. return err;
  292. break;
  293. case 640:
  294. PDEBUG(D_V4L2, "Configuring camera for VGA mode");
  295. for (i = 0; i < ARRAY_SIZE(VGA_s5k4aa); i++) {
  296. switch (VGA_s5k4aa[i][0]) {
  297. case BRIDGE:
  298. err = m5602_write_bridge(sd,
  299. VGA_s5k4aa[i][1],
  300. VGA_s5k4aa[i][2]);
  301. break;
  302. case SENSOR:
  303. data[0] = VGA_s5k4aa[i][2];
  304. err = m5602_write_sensor(sd,
  305. VGA_s5k4aa[i][1],
  306. data, 1);
  307. break;
  308. case SENSOR_LONG:
  309. data[0] = VGA_s5k4aa[i][2];
  310. data[1] = VGA_s5k4aa[i][3];
  311. err = m5602_write_sensor(sd,
  312. VGA_s5k4aa[i][1],
  313. data, 2);
  314. break;
  315. default:
  316. err("Invalid stream command, exiting init");
  317. return -EINVAL;
  318. }
  319. }
  320. err = s5k4aa_set_noise(&sd->gspca_dev, 1);
  321. if (err < 0)
  322. return err;
  323. break;
  324. }
  325. if (err < 0)
  326. return err;
  327. err = s5k4aa_set_exposure(&sd->gspca_dev,
  328. sensor_settings[EXPOSURE_IDX]);
  329. if (err < 0)
  330. return err;
  331. err = s5k4aa_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
  332. if (err < 0)
  333. return err;
  334. err = s5k4aa_set_brightness(&sd->gspca_dev,
  335. sensor_settings[BRIGHTNESS_IDX]);
  336. if (err < 0)
  337. return err;
  338. err = s5k4aa_set_noise(&sd->gspca_dev, sensor_settings[NOISE_SUPP_IDX]);
  339. if (err < 0)
  340. return err;
  341. err = s5k4aa_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
  342. if (err < 0)
  343. return err;
  344. return s5k4aa_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
  345. }
  346. int s5k4aa_init(struct sd *sd)
  347. {
  348. int i, err = 0;
  349. for (i = 0; i < ARRAY_SIZE(init_s5k4aa) && !err; i++) {
  350. u8 data[2] = {0x00, 0x00};
  351. switch (init_s5k4aa[i][0]) {
  352. case BRIDGE:
  353. err = m5602_write_bridge(sd,
  354. init_s5k4aa[i][1],
  355. init_s5k4aa[i][2]);
  356. break;
  357. case SENSOR:
  358. data[0] = init_s5k4aa[i][2];
  359. err = m5602_write_sensor(sd,
  360. init_s5k4aa[i][1], data, 1);
  361. break;
  362. case SENSOR_LONG:
  363. data[0] = init_s5k4aa[i][2];
  364. data[1] = init_s5k4aa[i][3];
  365. err = m5602_write_sensor(sd,
  366. init_s5k4aa[i][1], data, 2);
  367. break;
  368. default:
  369. info("Invalid stream command, exiting init");
  370. return -EINVAL;
  371. }
  372. }
  373. if (dump_sensor)
  374. s5k4aa_dump_registers(sd);
  375. return err;
  376. }
  377. static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
  378. {
  379. struct sd *sd = (struct sd *) gspca_dev;
  380. s32 *sensor_settings = sd->sensor_priv;
  381. *val = sensor_settings[EXPOSURE_IDX];
  382. PDEBUG(D_V4L2, "Read exposure %d", *val);
  383. return 0;
  384. }
  385. static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
  386. {
  387. struct sd *sd = (struct sd *) gspca_dev;
  388. s32 *sensor_settings = sd->sensor_priv;
  389. u8 data = S5K4AA_PAGE_MAP_2;
  390. int err;
  391. sensor_settings[EXPOSURE_IDX] = val;
  392. PDEBUG(D_V4L2, "Set exposure to %d", val);
  393. err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
  394. if (err < 0)
  395. return err;
  396. data = (val >> 8) & 0xff;
  397. err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1);
  398. if (err < 0)
  399. return err;
  400. data = val & 0xff;
  401. err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
  402. return err;
  403. }
  404. static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
  405. {
  406. struct sd *sd = (struct sd *) gspca_dev;
  407. s32 *sensor_settings = sd->sensor_priv;
  408. *val = sensor_settings[VFLIP_IDX];
  409. PDEBUG(D_V4L2, "Read vertical flip %d", *val);
  410. return 0;
  411. }
  412. static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
  413. {
  414. struct sd *sd = (struct sd *) gspca_dev;
  415. s32 *sensor_settings = sd->sensor_priv;
  416. u8 data = S5K4AA_PAGE_MAP_2;
  417. int err;
  418. sensor_settings[VFLIP_IDX] = val;
  419. PDEBUG(D_V4L2, "Set vertical flip to %d", val);
  420. err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
  421. if (err < 0)
  422. return err;
  423. err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
  424. if (err < 0)
  425. return err;
  426. if (dmi_check_system(s5k4aa_vflip_dmi_table))
  427. val = !val;
  428. data = ((data & ~S5K4AA_RM_V_FLIP) | ((val & 0x01) << 7));
  429. err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
  430. if (err < 0)
  431. return err;
  432. err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
  433. if (err < 0)
  434. return err;
  435. data = (data & 0xfe) | !val;
  436. err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
  437. return err;
  438. }
  439. static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
  440. {
  441. struct sd *sd = (struct sd *) gspca_dev;
  442. s32 *sensor_settings = sd->sensor_priv;
  443. *val = sensor_settings[HFLIP_IDX];
  444. PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
  445. return 0;
  446. }
  447. static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
  448. {
  449. struct sd *sd = (struct sd *) gspca_dev;
  450. s32 *sensor_settings = sd->sensor_priv;
  451. u8 data = S5K4AA_PAGE_MAP_2;
  452. int err;
  453. sensor_settings[HFLIP_IDX] = val;
  454. PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
  455. err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
  456. if (err < 0)
  457. return err;
  458. err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
  459. if (err < 0)
  460. return err;
  461. if (dmi_check_system(s5k4aa_vflip_dmi_table))
  462. val = !val;
  463. data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6));
  464. err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
  465. if (err < 0)
  466. return err;
  467. err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
  468. if (err < 0)
  469. return err;
  470. data = (data & 0xfe) | !val;
  471. err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
  472. return err;
  473. }
  474. static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
  475. {
  476. struct sd *sd = (struct sd *) gspca_dev;
  477. s32 *sensor_settings = sd->sensor_priv;
  478. *val = sensor_settings[GAIN_IDX];
  479. PDEBUG(D_V4L2, "Read gain %d", *val);
  480. return 0;
  481. }
  482. static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val)
  483. {
  484. struct sd *sd = (struct sd *) gspca_dev;
  485. s32 *sensor_settings = sd->sensor_priv;
  486. u8 data = S5K4AA_PAGE_MAP_2;
  487. int err;
  488. sensor_settings[GAIN_IDX] = val;
  489. PDEBUG(D_V4L2, "Set gain to %d", val);
  490. err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
  491. if (err < 0)
  492. return err;
  493. data = val & 0xff;
  494. err = m5602_write_sensor(sd, S5K4AA_GAIN, &data, 1);
  495. return err;
  496. }
  497. static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
  498. {
  499. struct sd *sd = (struct sd *) gspca_dev;
  500. s32 *sensor_settings = sd->sensor_priv;
  501. *val = sensor_settings[BRIGHTNESS_IDX];
  502. PDEBUG(D_V4L2, "Read brightness %d", *val);
  503. return 0;
  504. }
  505. static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
  506. {
  507. struct sd *sd = (struct sd *) gspca_dev;
  508. s32 *sensor_settings = sd->sensor_priv;
  509. u8 data = S5K4AA_PAGE_MAP_2;
  510. int err;
  511. sensor_settings[BRIGHTNESS_IDX] = val;
  512. PDEBUG(D_V4L2, "Set brightness to %d", val);
  513. err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
  514. if (err < 0)
  515. return err;
  516. data = val & 0xff;
  517. return m5602_write_sensor(sd, S5K4AA_BRIGHTNESS, &data, 1);
  518. }
  519. static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val)
  520. {
  521. struct sd *sd = (struct sd *) gspca_dev;
  522. s32 *sensor_settings = sd->sensor_priv;
  523. *val = sensor_settings[NOISE_SUPP_IDX];
  524. PDEBUG(D_V4L2, "Read noise %d", *val);
  525. return 0;
  526. }
  527. static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val)
  528. {
  529. struct sd *sd = (struct sd *) gspca_dev;
  530. s32 *sensor_settings = sd->sensor_priv;
  531. u8 data = S5K4AA_PAGE_MAP_2;
  532. int err;
  533. sensor_settings[NOISE_SUPP_IDX] = val;
  534. PDEBUG(D_V4L2, "Set noise to %d", val);
  535. err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
  536. if (err < 0)
  537. return err;
  538. data = val & 0x01;
  539. return m5602_write_sensor(sd, S5K4AA_NOISE_SUPP, &data, 1);
  540. }
  541. void s5k4aa_disconnect(struct sd *sd)
  542. {
  543. sd->sensor = NULL;
  544. kfree(sd->sensor_priv);
  545. }
  546. static void s5k4aa_dump_registers(struct sd *sd)
  547. {
  548. int address;
  549. u8 page, old_page;
  550. m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
  551. for (page = 0; page < 16; page++) {
  552. m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
  553. info("Dumping the s5k4aa register state for page 0x%x", page);
  554. for (address = 0; address <= 0xff; address++) {
  555. u8 value = 0;
  556. m5602_read_sensor(sd, address, &value, 1);
  557. info("register 0x%x contains 0x%x",
  558. address, value);
  559. }
  560. }
  561. info("s5k4aa register state dump complete");
  562. for (page = 0; page < 16; page++) {
  563. m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
  564. info("Probing for which registers that are "
  565. "read/write for page 0x%x", page);
  566. for (address = 0; address <= 0xff; address++) {
  567. u8 old_value, ctrl_value, test_value = 0xff;
  568. m5602_read_sensor(sd, address, &old_value, 1);
  569. m5602_write_sensor(sd, address, &test_value, 1);
  570. m5602_read_sensor(sd, address, &ctrl_value, 1);
  571. if (ctrl_value == test_value)
  572. info("register 0x%x is writeable", address);
  573. else
  574. info("register 0x%x is read only", address);
  575. /* Restore original value */
  576. m5602_write_sensor(sd, address, &old_value, 1);
  577. }
  578. }
  579. info("Read/write register probing complete");
  580. m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
  581. }