m5602_mt9m111.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  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. #include "m5602_mt9m111.h"
  19. static struct v4l2_pix_format mt9m111_modes[] = {
  20. {
  21. 640,
  22. 480,
  23. V4L2_PIX_FMT_SBGGR8,
  24. V4L2_FIELD_NONE,
  25. .sizeimage = 640 * 480,
  26. .bytesperline = 640,
  27. .colorspace = V4L2_COLORSPACE_SRGB,
  28. .priv = 0
  29. }
  30. };
  31. static void mt9m111_dump_registers(struct sd *sd);
  32. int mt9m111_probe(struct sd *sd)
  33. {
  34. u8 data[2] = {0x00, 0x00};
  35. int i;
  36. if (force_sensor) {
  37. if (force_sensor == MT9M111_SENSOR) {
  38. info("Forcing a %s sensor", mt9m111.name);
  39. goto sensor_found;
  40. }
  41. /* If we want to force another sensor, don't try to probe this
  42. * one */
  43. return -ENODEV;
  44. }
  45. info("Probing for a mt9m111 sensor");
  46. /* Do the preinit */
  47. for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) {
  48. if (preinit_mt9m111[i][0] == BRIDGE) {
  49. m5602_write_bridge(sd,
  50. preinit_mt9m111[i][1],
  51. preinit_mt9m111[i][2]);
  52. } else {
  53. data[0] = preinit_mt9m111[i][2];
  54. data[1] = preinit_mt9m111[i][3];
  55. m5602_write_sensor(sd,
  56. preinit_mt9m111[i][1], data, 2);
  57. }
  58. }
  59. if (m5602_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2))
  60. return -ENODEV;
  61. if ((data[0] == 0x14) && (data[1] == 0x3a)) {
  62. info("Detected a mt9m111 sensor");
  63. goto sensor_found;
  64. }
  65. return -ENODEV;
  66. sensor_found:
  67. sd->gspca_dev.cam.cam_mode = mt9m111_modes;
  68. sd->gspca_dev.cam.nmodes = ARRAY_SIZE(mt9m111_modes);
  69. sd->desc->ctrls = mt9m111.ctrls;
  70. sd->desc->nctrls = ARRAY_SIZE(mt9m111_ctrls);
  71. return 0;
  72. }
  73. int mt9m111_init(struct sd *sd)
  74. {
  75. int i, err = 0;
  76. /* Init the sensor */
  77. for (i = 0; i < ARRAY_SIZE(init_mt9m111) && !err; i++) {
  78. u8 data[2];
  79. if (init_mt9m111[i][0] == BRIDGE) {
  80. err = m5602_write_bridge(sd,
  81. init_mt9m111[i][1],
  82. init_mt9m111[i][2]);
  83. } else {
  84. data[0] = init_mt9m111[i][2];
  85. data[1] = init_mt9m111[i][3];
  86. err = m5602_write_sensor(sd,
  87. init_mt9m111[i][1], data, 2);
  88. }
  89. }
  90. if (dump_sensor)
  91. mt9m111_dump_registers(sd);
  92. return (err < 0) ? err : 0;
  93. }
  94. int mt9m111_power_down(struct sd *sd)
  95. {
  96. return 0;
  97. }
  98. int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
  99. {
  100. int err;
  101. u8 data[2] = {0x00, 0x00};
  102. struct sd *sd = (struct sd *) gspca_dev;
  103. err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
  104. data, 2);
  105. *val = data[0] & MT9M111_RMB_MIRROR_ROWS;
  106. PDEBUG(D_V4L2, "Read vertical flip %d", *val);
  107. return err;
  108. }
  109. int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
  110. {
  111. int err;
  112. u8 data[2] = {0x00, 0x00};
  113. struct sd *sd = (struct sd *) gspca_dev;
  114. PDEBUG(D_V4L2, "Set vertical flip to %d", val);
  115. /* Set the correct page map */
  116. err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
  117. if (err < 0)
  118. return err;
  119. err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
  120. if (err < 0)
  121. return err;
  122. data[0] = (data[0] & 0xfe) | val;
  123. err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
  124. data, 2);
  125. return err;
  126. }
  127. int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
  128. {
  129. int err;
  130. u8 data[2] = {0x00, 0x00};
  131. struct sd *sd = (struct sd *) gspca_dev;
  132. err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
  133. data, 2);
  134. *val = data[0] & MT9M111_RMB_MIRROR_COLS;
  135. PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
  136. return err;
  137. }
  138. int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
  139. {
  140. int err;
  141. u8 data[2] = {0x00, 0x00};
  142. struct sd *sd = (struct sd *) gspca_dev;
  143. PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
  144. /* Set the correct page map */
  145. err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
  146. if (err < 0)
  147. return err;
  148. err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
  149. if (err < 0)
  150. return err;
  151. data[0] = (data[0] & 0xfd) | ((val << 1) & 0x02);
  152. err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
  153. data, 2);
  154. return err;
  155. }
  156. int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
  157. {
  158. int err, tmp;
  159. u8 data[2] = {0x00, 0x00};
  160. struct sd *sd = (struct sd *) gspca_dev;
  161. err = m5602_read_sensor(sd, MT9M111_SC_GLOBAL_GAIN, data, 2);
  162. tmp = ((data[1] << 8) | data[0]);
  163. *val = ((tmp & (1 << 10)) * 2) |
  164. ((tmp & (1 << 9)) * 2) |
  165. ((tmp & (1 << 8)) * 2) |
  166. (tmp & 0x7f);
  167. PDEBUG(D_V4L2, "Read gain %d", *val);
  168. return err;
  169. }
  170. int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
  171. {
  172. int err, tmp;
  173. u8 data[2] = {0x00, 0x00};
  174. struct sd *sd = (struct sd *) gspca_dev;
  175. /* Set the correct page map */
  176. err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
  177. if (err < 0)
  178. return err;
  179. if (val >= INITIAL_MAX_GAIN * 2 * 2 * 2)
  180. return -EINVAL;
  181. if ((val >= INITIAL_MAX_GAIN * 2 * 2) &&
  182. (val < (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2))
  183. tmp = (1 << 10) | (val << 9) |
  184. (val << 8) | (val / 8);
  185. else if ((val >= INITIAL_MAX_GAIN * 2) &&
  186. (val < INITIAL_MAX_GAIN * 2 * 2))
  187. tmp = (1 << 9) | (1 << 8) | (val / 4);
  188. else if ((val >= INITIAL_MAX_GAIN) &&
  189. (val < INITIAL_MAX_GAIN * 2))
  190. tmp = (1 << 8) | (val / 2);
  191. else
  192. tmp = val;
  193. data[1] = (tmp & 0xff00) >> 8;
  194. data[0] = (tmp & 0xff);
  195. PDEBUG(D_V4L2, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
  196. data[1], data[0]);
  197. err = m5602_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN,
  198. data, 2);
  199. return err;
  200. }
  201. static void mt9m111_dump_registers(struct sd *sd)
  202. {
  203. u8 address, value[2] = {0x00, 0x00};
  204. info("Dumping the mt9m111 register state");
  205. info("Dumping the mt9m111 sensor core registers");
  206. value[1] = MT9M111_SENSOR_CORE;
  207. m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
  208. for (address = 0; address < 0xff; address++) {
  209. m5602_read_sensor(sd, address, value, 2);
  210. info("register 0x%x contains 0x%x%x",
  211. address, value[0], value[1]);
  212. }
  213. info("Dumping the mt9m111 color pipeline registers");
  214. value[1] = MT9M111_COLORPIPE;
  215. m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
  216. for (address = 0; address < 0xff; address++) {
  217. m5602_read_sensor(sd, address, value, 2);
  218. info("register 0x%x contains 0x%x%x",
  219. address, value[0], value[1]);
  220. }
  221. info("Dumping the mt9m111 camera control registers");
  222. value[1] = MT9M111_CAMERA_CONTROL;
  223. m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
  224. for (address = 0; address < 0xff; address++) {
  225. m5602_read_sensor(sd, address, value, 2);
  226. info("register 0x%x contains 0x%x%x",
  227. address, value[0], value[1]);
  228. }
  229. info("mt9m111 register state dump complete");
  230. }