m5602_mt9m111.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. /*
  2. * Driver for the mt9m111 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. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  19. #include "m5602_mt9m111.h"
  20. static int mt9m111_s_ctrl(struct v4l2_ctrl *ctrl);
  21. static void mt9m111_dump_registers(struct sd *sd);
  22. static const unsigned char preinit_mt9m111[][4] = {
  23. {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
  24. {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
  25. {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
  26. {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
  27. {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
  28. {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
  29. {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
  30. {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
  31. {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
  32. {SENSOR, MT9M111_SC_RESET,
  33. MT9M111_RESET |
  34. MT9M111_RESTART |
  35. MT9M111_ANALOG_STANDBY |
  36. MT9M111_CHIP_DISABLE,
  37. MT9M111_SHOW_BAD_FRAMES |
  38. MT9M111_RESTART_BAD_FRAMES |
  39. MT9M111_SYNCHRONIZE_CHANGES},
  40. {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
  41. {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
  42. {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
  43. {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
  44. {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
  45. {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
  46. {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
  47. {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
  48. {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
  49. {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
  50. {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
  51. {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
  52. {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
  53. {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
  54. {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}
  55. };
  56. static const unsigned char init_mt9m111[][4] = {
  57. {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
  58. {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
  59. {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
  60. {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
  61. {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
  62. {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
  63. {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
  64. {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
  65. {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
  66. {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
  67. {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
  68. {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
  69. {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
  70. {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
  71. {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
  72. {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
  73. {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
  74. {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
  75. {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
  76. {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
  77. {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00,
  78. MT9M111_CP_OPERATING_MODE_CTL},
  79. {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
  80. {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00,
  81. MT9M111_2D_DEFECT_CORRECTION_ENABLE},
  82. {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00,
  83. MT9M111_2D_DEFECT_CORRECTION_ENABLE},
  84. {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
  85. {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
  86. {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
  87. {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
  88. {SENSOR, 0xcd, 0x00, 0x0e},
  89. {SENSOR, 0xd0, 0x00, 0x40},
  90. {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
  91. {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
  92. {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
  93. {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
  94. {SENSOR, 0x33, 0x03, 0x49},
  95. {SENSOR, 0x34, 0xc0, 0x19},
  96. {SENSOR, 0x3f, 0x20, 0x20},
  97. {SENSOR, 0x40, 0x20, 0x20},
  98. {SENSOR, 0x5a, 0xc0, 0x0a},
  99. {SENSOR, 0x70, 0x7b, 0x0a},
  100. {SENSOR, 0x71, 0xff, 0x00},
  101. {SENSOR, 0x72, 0x19, 0x0e},
  102. {SENSOR, 0x73, 0x18, 0x0f},
  103. {SENSOR, 0x74, 0x57, 0x32},
  104. {SENSOR, 0x75, 0x56, 0x34},
  105. {SENSOR, 0x76, 0x73, 0x35},
  106. {SENSOR, 0x77, 0x30, 0x12},
  107. {SENSOR, 0x78, 0x79, 0x02},
  108. {SENSOR, 0x79, 0x75, 0x06},
  109. {SENSOR, 0x7a, 0x77, 0x0a},
  110. {SENSOR, 0x7b, 0x78, 0x09},
  111. {SENSOR, 0x7c, 0x7d, 0x06},
  112. {SENSOR, 0x7d, 0x31, 0x10},
  113. {SENSOR, 0x7e, 0x00, 0x7e},
  114. {SENSOR, 0x80, 0x59, 0x04},
  115. {SENSOR, 0x81, 0x59, 0x04},
  116. {SENSOR, 0x82, 0x57, 0x0a},
  117. {SENSOR, 0x83, 0x58, 0x0b},
  118. {SENSOR, 0x84, 0x47, 0x0c},
  119. {SENSOR, 0x85, 0x48, 0x0e},
  120. {SENSOR, 0x86, 0x5b, 0x02},
  121. {SENSOR, 0x87, 0x00, 0x5c},
  122. {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, MT9M111_SEL_CONTEXT_B},
  123. {SENSOR, 0x60, 0x00, 0x80},
  124. {SENSOR, 0x61, 0x00, 0x00},
  125. {SENSOR, 0x62, 0x00, 0x00},
  126. {SENSOR, 0x63, 0x00, 0x00},
  127. {SENSOR, 0x64, 0x00, 0x00},
  128. {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, /* 13 */
  129. {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12}, /* 18 */
  130. {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00}, /* 1024 */
  131. {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10}, /* 1296 */
  132. {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60}, /* 352 */
  133. {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, /* 17 */
  134. {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60}, /* 352 */
  135. {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, /* 17 */
  136. {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f}, /* 271 */
  137. {SENSOR, 0x30, 0x04, 0x00},
  138. /* Set number of blank rows chosen to 400 */
  139. {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90},
  140. };
  141. static const unsigned char start_mt9m111[][4] = {
  142. {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
  143. {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
  144. {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
  145. {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
  146. {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
  147. {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
  148. {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
  149. {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
  150. {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
  151. {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
  152. {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
  153. };
  154. static struct v4l2_pix_format mt9m111_modes[] = {
  155. {
  156. 640,
  157. 480,
  158. V4L2_PIX_FMT_SBGGR8,
  159. V4L2_FIELD_NONE,
  160. .sizeimage = 640 * 480,
  161. .bytesperline = 640,
  162. .colorspace = V4L2_COLORSPACE_SRGB,
  163. .priv = 0
  164. }
  165. };
  166. static const struct v4l2_ctrl_ops mt9m111_ctrl_ops = {
  167. .s_ctrl = mt9m111_s_ctrl,
  168. };
  169. static const struct v4l2_ctrl_config mt9m111_greenbal_cfg = {
  170. .ops = &mt9m111_ctrl_ops,
  171. .id = M5602_V4L2_CID_GREEN_BALANCE,
  172. .name = "Green Balance",
  173. .type = V4L2_CTRL_TYPE_INTEGER,
  174. .min = 0,
  175. .max = 0x7ff,
  176. .step = 1,
  177. .def = MT9M111_GREEN_GAIN_DEFAULT,
  178. .flags = V4L2_CTRL_FLAG_SLIDER,
  179. };
  180. int mt9m111_probe(struct sd *sd)
  181. {
  182. u8 data[2] = {0x00, 0x00};
  183. int i;
  184. struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
  185. if (force_sensor) {
  186. if (force_sensor == MT9M111_SENSOR) {
  187. pr_info("Forcing a %s sensor\n", mt9m111.name);
  188. goto sensor_found;
  189. }
  190. /* If we want to force another sensor, don't try to probe this
  191. * one */
  192. return -ENODEV;
  193. }
  194. PDEBUG(D_PROBE, "Probing for a mt9m111 sensor");
  195. /* Do the preinit */
  196. for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) {
  197. if (preinit_mt9m111[i][0] == BRIDGE) {
  198. m5602_write_bridge(sd,
  199. preinit_mt9m111[i][1],
  200. preinit_mt9m111[i][2]);
  201. } else {
  202. data[0] = preinit_mt9m111[i][2];
  203. data[1] = preinit_mt9m111[i][3];
  204. m5602_write_sensor(sd,
  205. preinit_mt9m111[i][1], data, 2);
  206. }
  207. }
  208. if (m5602_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2))
  209. return -ENODEV;
  210. if ((data[0] == 0x14) && (data[1] == 0x3a)) {
  211. pr_info("Detected a mt9m111 sensor\n");
  212. goto sensor_found;
  213. }
  214. return -ENODEV;
  215. sensor_found:
  216. sd->gspca_dev.cam.cam_mode = mt9m111_modes;
  217. sd->gspca_dev.cam.nmodes = ARRAY_SIZE(mt9m111_modes);
  218. return 0;
  219. }
  220. int mt9m111_init(struct sd *sd)
  221. {
  222. int i, err = 0;
  223. /* Init the sensor */
  224. for (i = 0; i < ARRAY_SIZE(init_mt9m111) && !err; i++) {
  225. u8 data[2];
  226. if (init_mt9m111[i][0] == BRIDGE) {
  227. err = m5602_write_bridge(sd,
  228. init_mt9m111[i][1],
  229. init_mt9m111[i][2]);
  230. } else {
  231. data[0] = init_mt9m111[i][2];
  232. data[1] = init_mt9m111[i][3];
  233. err = m5602_write_sensor(sd,
  234. init_mt9m111[i][1], data, 2);
  235. }
  236. }
  237. if (dump_sensor)
  238. mt9m111_dump_registers(sd);
  239. return 0;
  240. }
  241. int mt9m111_init_controls(struct sd *sd)
  242. {
  243. struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
  244. sd->gspca_dev.vdev.ctrl_handler = hdl;
  245. v4l2_ctrl_handler_init(hdl, 7);
  246. sd->auto_white_bal = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops,
  247. V4L2_CID_AUTO_WHITE_BALANCE,
  248. 0, 1, 1, 0);
  249. sd->green_bal = v4l2_ctrl_new_custom(hdl, &mt9m111_greenbal_cfg, NULL);
  250. sd->red_bal = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops,
  251. V4L2_CID_RED_BALANCE, 0, 0x7ff, 1,
  252. MT9M111_RED_GAIN_DEFAULT);
  253. sd->blue_bal = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops,
  254. V4L2_CID_BLUE_BALANCE, 0, 0x7ff, 1,
  255. MT9M111_BLUE_GAIN_DEFAULT);
  256. v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops, V4L2_CID_GAIN, 0,
  257. (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2, 1,
  258. MT9M111_DEFAULT_GAIN);
  259. sd->hflip = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops, V4L2_CID_HFLIP,
  260. 0, 1, 1, 0);
  261. sd->vflip = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops, V4L2_CID_VFLIP,
  262. 0, 1, 1, 0);
  263. if (hdl->error) {
  264. pr_err("Could not initialize controls\n");
  265. return hdl->error;
  266. }
  267. v4l2_ctrl_auto_cluster(4, &sd->auto_white_bal, 0, false);
  268. v4l2_ctrl_cluster(2, &sd->hflip);
  269. return 0;
  270. }
  271. int mt9m111_start(struct sd *sd)
  272. {
  273. int i, err = 0;
  274. u8 data[2];
  275. struct cam *cam = &sd->gspca_dev.cam;
  276. struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
  277. int width = cam->cam_mode[sd->gspca_dev.curr_mode].width - 1;
  278. int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
  279. for (i = 0; i < ARRAY_SIZE(start_mt9m111) && !err; i++) {
  280. if (start_mt9m111[i][0] == BRIDGE) {
  281. err = m5602_write_bridge(sd,
  282. start_mt9m111[i][1],
  283. start_mt9m111[i][2]);
  284. } else {
  285. data[0] = start_mt9m111[i][2];
  286. data[1] = start_mt9m111[i][3];
  287. err = m5602_write_sensor(sd,
  288. start_mt9m111[i][1], data, 2);
  289. }
  290. }
  291. if (err < 0)
  292. return err;
  293. err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
  294. if (err < 0)
  295. return err;
  296. err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
  297. if (err < 0)
  298. return err;
  299. for (i = 0; i < 2 && !err; i++)
  300. err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
  301. if (err < 0)
  302. return err;
  303. err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
  304. if (err < 0)
  305. return err;
  306. err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2);
  307. if (err < 0)
  308. return err;
  309. for (i = 0; i < 2 && !err; i++)
  310. err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0);
  311. if (err < 0)
  312. return err;
  313. err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
  314. (width >> 8) & 0xff);
  315. if (err < 0)
  316. return err;
  317. err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, width & 0xff);
  318. if (err < 0)
  319. return err;
  320. err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
  321. if (err < 0)
  322. return err;
  323. switch (width) {
  324. case 640:
  325. PDEBUG(D_CONF, "Configuring camera for VGA mode");
  326. break;
  327. case 320:
  328. PDEBUG(D_CONF, "Configuring camera for QVGA mode");
  329. break;
  330. }
  331. return err;
  332. }
  333. void mt9m111_disconnect(struct sd *sd)
  334. {
  335. sd->sensor = NULL;
  336. }
  337. static int mt9m111_set_hvflip(struct gspca_dev *gspca_dev)
  338. {
  339. int err;
  340. u8 data[2] = {0x00, 0x00};
  341. struct sd *sd = (struct sd *) gspca_dev;
  342. int hflip;
  343. int vflip;
  344. PDEBUG(D_CONF, "Set hvflip to %d %d", sd->hflip->val, sd->vflip->val);
  345. /* The mt9m111 is flipped by default */
  346. hflip = !sd->hflip->val;
  347. vflip = !sd->vflip->val;
  348. /* Set the correct page map */
  349. err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
  350. if (err < 0)
  351. return err;
  352. data[0] = MT9M111_RMB_OVER_SIZED;
  353. if (gspca_dev->pixfmt.width == 640) {
  354. data[1] = MT9M111_RMB_ROW_SKIP_2X |
  355. MT9M111_RMB_COLUMN_SKIP_2X |
  356. (hflip << 1) | vflip;
  357. } else {
  358. data[1] = MT9M111_RMB_ROW_SKIP_4X |
  359. MT9M111_RMB_COLUMN_SKIP_4X |
  360. (hflip << 1) | vflip;
  361. }
  362. err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
  363. data, 2);
  364. return err;
  365. }
  366. static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev,
  367. __s32 val)
  368. {
  369. struct sd *sd = (struct sd *) gspca_dev;
  370. int err;
  371. u8 data[2];
  372. err = m5602_read_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2);
  373. if (err < 0)
  374. return err;
  375. data[1] = ((data[1] & 0xfd) | ((val & 0x01) << 1));
  376. err = m5602_write_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2);
  377. PDEBUG(D_CONF, "Set auto white balance %d", val);
  378. return err;
  379. }
  380. static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
  381. {
  382. int err, tmp;
  383. u8 data[2] = {0x00, 0x00};
  384. struct sd *sd = (struct sd *) gspca_dev;
  385. /* Set the correct page map */
  386. err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
  387. if (err < 0)
  388. return err;
  389. if (val >= INITIAL_MAX_GAIN * 2 * 2 * 2)
  390. return -EINVAL;
  391. if ((val >= INITIAL_MAX_GAIN * 2 * 2) &&
  392. (val < (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2))
  393. tmp = (1 << 10) | (val << 9) |
  394. (val << 8) | (val / 8);
  395. else if ((val >= INITIAL_MAX_GAIN * 2) &&
  396. (val < INITIAL_MAX_GAIN * 2 * 2))
  397. tmp = (1 << 9) | (1 << 8) | (val / 4);
  398. else if ((val >= INITIAL_MAX_GAIN) &&
  399. (val < INITIAL_MAX_GAIN * 2))
  400. tmp = (1 << 8) | (val / 2);
  401. else
  402. tmp = val;
  403. data[1] = (tmp & 0xff);
  404. data[0] = (tmp & 0xff00) >> 8;
  405. PDEBUG(D_CONF, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
  406. data[1], data[0]);
  407. err = m5602_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN,
  408. data, 2);
  409. return err;
  410. }
  411. static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
  412. {
  413. int err;
  414. u8 data[2];
  415. struct sd *sd = (struct sd *) gspca_dev;
  416. data[1] = (val & 0xff);
  417. data[0] = (val & 0xff00) >> 8;
  418. PDEBUG(D_CONF, "Set green balance %d", val);
  419. err = m5602_write_sensor(sd, MT9M111_SC_GREEN_1_GAIN,
  420. data, 2);
  421. if (err < 0)
  422. return err;
  423. return m5602_write_sensor(sd, MT9M111_SC_GREEN_2_GAIN,
  424. data, 2);
  425. }
  426. static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
  427. {
  428. u8 data[2];
  429. struct sd *sd = (struct sd *) gspca_dev;
  430. data[1] = (val & 0xff);
  431. data[0] = (val & 0xff00) >> 8;
  432. PDEBUG(D_CONF, "Set blue balance %d", val);
  433. return m5602_write_sensor(sd, MT9M111_SC_BLUE_GAIN,
  434. data, 2);
  435. }
  436. static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
  437. {
  438. u8 data[2];
  439. struct sd *sd = (struct sd *) gspca_dev;
  440. data[1] = (val & 0xff);
  441. data[0] = (val & 0xff00) >> 8;
  442. PDEBUG(D_CONF, "Set red balance %d", val);
  443. return m5602_write_sensor(sd, MT9M111_SC_RED_GAIN,
  444. data, 2);
  445. }
  446. static int mt9m111_s_ctrl(struct v4l2_ctrl *ctrl)
  447. {
  448. struct gspca_dev *gspca_dev =
  449. container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
  450. struct sd *sd = (struct sd *) gspca_dev;
  451. int err;
  452. if (!gspca_dev->streaming)
  453. return 0;
  454. switch (ctrl->id) {
  455. case V4L2_CID_AUTO_WHITE_BALANCE:
  456. err = mt9m111_set_auto_white_balance(gspca_dev, ctrl->val);
  457. if (err || ctrl->val)
  458. return err;
  459. err = mt9m111_set_green_balance(gspca_dev, sd->green_bal->val);
  460. if (err)
  461. return err;
  462. err = mt9m111_set_red_balance(gspca_dev, sd->red_bal->val);
  463. if (err)
  464. return err;
  465. err = mt9m111_set_blue_balance(gspca_dev, sd->blue_bal->val);
  466. break;
  467. case V4L2_CID_GAIN:
  468. err = mt9m111_set_gain(gspca_dev, ctrl->val);
  469. break;
  470. case V4L2_CID_HFLIP:
  471. err = mt9m111_set_hvflip(gspca_dev);
  472. break;
  473. default:
  474. return -EINVAL;
  475. }
  476. return err;
  477. }
  478. static void mt9m111_dump_registers(struct sd *sd)
  479. {
  480. u8 address, value[2] = {0x00, 0x00};
  481. pr_info("Dumping the mt9m111 register state\n");
  482. pr_info("Dumping the mt9m111 sensor core registers\n");
  483. value[1] = MT9M111_SENSOR_CORE;
  484. m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
  485. for (address = 0; address < 0xff; address++) {
  486. m5602_read_sensor(sd, address, value, 2);
  487. pr_info("register 0x%x contains 0x%x%x\n",
  488. address, value[0], value[1]);
  489. }
  490. pr_info("Dumping the mt9m111 color pipeline registers\n");
  491. value[1] = MT9M111_COLORPIPE;
  492. m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
  493. for (address = 0; address < 0xff; address++) {
  494. m5602_read_sensor(sd, address, value, 2);
  495. pr_info("register 0x%x contains 0x%x%x\n",
  496. address, value[0], value[1]);
  497. }
  498. pr_info("Dumping the mt9m111 camera control registers\n");
  499. value[1] = MT9M111_CAMERA_CONTROL;
  500. m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
  501. for (address = 0; address < 0xff; address++) {
  502. m5602_read_sensor(sd, address, value, 2);
  503. pr_info("register 0x%x contains 0x%x%x\n",
  504. address, value[0], value[1]);
  505. }
  506. pr_info("mt9m111 register state dump complete\n");
  507. }