aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@pengutronix.de>2008-04-22 13:42:04 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-04-24 13:07:42 -0400
commitf523dd0da985ef618d6f986217f0dd0975072515 (patch)
treea810142210dbf21bada93005ba43084d6745a77c
parent3bc43840c3fbffaf8216883a37b336a41050d7f7 (diff)
V4L/DVB (7173): Add support for the MT9M001 camera
This driver supports Micron MT9M001 monochrome and colour cameras. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@pengutronix.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r--drivers/media/video/Kconfig15
-rw-r--r--drivers/media/video/Makefile1
-rw-r--r--drivers/media/video/mt9m001.c694
3 files changed, 710 insertions, 0 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index fb4bf089c68f..393bbf92b100 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -845,6 +845,21 @@ config SOC_CAMERA
845 over a bus like PCI or USB. For example some i2c camera connected 845 over a bus like PCI or USB. For example some i2c camera connected
846 directly to the data bus of an SoC. 846 directly to the data bus of an SoC.
847 847
848config SOC_CAMERA_MT9M001
849 tristate "mt9m001 support"
850 depends on SOC_CAMERA && GENERIC_GPIO
851 select GPIO_PCA953X if MT9M001_PCA9536_SWITCH
852 help
853 This driver supports MT9M001 cameras from Micron, monochrome
854 and colour models.
855
856config MT9M001_PCA9536_SWITCH
857 bool "pca9536 datawidth switch for mt9m001"
858 depends on SOC_CAMERA_MT9M001
859 help
860 Select this if your MT9M001 camera uses a PCA9536 I2C GPIO
861 extender to switch between 8 and 10 bit datawidth modes
862
848config VIDEO_PXA27x 863config VIDEO_PXA27x
849 tristate "PXA27x Quick Capture Interface driver" 864 tristate "PXA27x Quick Capture Interface driver"
850 depends on VIDEO_DEV && PXA27x 865 depends on VIDEO_DEV && PXA27x
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 874ed967f416..9321f68e52a7 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -138,6 +138,7 @@ obj-$(CONFIG_VIDEO_CX23885) += cx23885/
138 138
139obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o 139obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o
140obj-$(CONFIG_SOC_CAMERA) += soc_camera.o 140obj-$(CONFIG_SOC_CAMERA) += soc_camera.o
141obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o
141 142
142EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core 143EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
143EXTRA_CFLAGS += -Idrivers/media/dvb/frontends 144EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
new file mode 100644
index 000000000000..3c5867c378d3
--- /dev/null
+++ b/drivers/media/video/mt9m001.c
@@ -0,0 +1,694 @@
1/*
2 * Driver for MT9M001 CMOS Image Sensor from Micron
3 *
4 * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
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 version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/videodev2.h>
12#include <linux/slab.h>
13#include <linux/i2c.h>
14#include <linux/log2.h>
15
16#include <media/v4l2-common.h>
17#include <media/v4l2-chip-ident.h>
18#include <media/soc_camera.h>
19
20#include <asm/gpio.h>
21
22/* mt9m001 i2c address 0x5d
23 * The platform has to define i2c_board_info
24 * and call i2c_register_board_info() */
25
26/* mt9m001 selected register addresses */
27#define MT9M001_CHIP_VERSION 0x00
28#define MT9M001_ROW_START 0x01
29#define MT9M001_COLUMN_START 0x02
30#define MT9M001_WINDOW_HEIGHT 0x03
31#define MT9M001_WINDOW_WIDTH 0x04
32#define MT9M001_HORIZONTAL_BLANKING 0x05
33#define MT9M001_VERTICAL_BLANKING 0x06
34#define MT9M001_OUTPUT_CONTROL 0x07
35#define MT9M001_SHUTTER_WIDTH 0x09
36#define MT9M001_FRAME_RESTART 0x0b
37#define MT9M001_SHUTTER_DELAY 0x0c
38#define MT9M001_RESET 0x0d
39#define MT9M001_READ_OPTIONS1 0x1e
40#define MT9M001_READ_OPTIONS2 0x20
41#define MT9M001_GLOBAL_GAIN 0x35
42#define MT9M001_CHIP_ENABLE 0xF1
43
44static const struct soc_camera_data_format mt9m001_colour_formats[] = {
45 {
46 .name = "RGB Bayer (sRGB)",
47 .depth = 16,
48 .fourcc = V4L2_PIX_FMT_SBGGR8,
49 .colorspace = V4L2_COLORSPACE_SRGB,
50 }
51};
52
53static const struct soc_camera_data_format mt9m001_monochrome_formats[] = {
54 {
55 .name = "Monochrome 10 bit",
56 .depth = 10,
57 .fourcc = V4L2_PIX_FMT_Y16,
58 }, {
59 .name = "Monochrome 8 bit",
60 .depth = 8,
61 .fourcc = V4L2_PIX_FMT_GREY,
62 },
63};
64
65struct mt9m001 {
66 struct i2c_client *client;
67 struct soc_camera_device icd;
68 int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
69 int switch_gpio;
70 unsigned char autoexposure;
71 unsigned char datawidth;
72};
73
74static int reg_read(struct soc_camera_device *icd, const u8 reg)
75{
76 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
77 struct i2c_client *client = mt9m001->client;
78 s32 data = i2c_smbus_read_word_data(client, reg);
79 return data < 0 ? data : swab16(data);
80}
81
82static int reg_write(struct soc_camera_device *icd, const u8 reg,
83 const u16 data)
84{
85 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
86 return i2c_smbus_write_word_data(mt9m001->client, reg, swab16(data));
87}
88
89static int reg_set(struct soc_camera_device *icd, const u8 reg,
90 const u16 data)
91{
92 int ret;
93
94 ret = reg_read(icd, reg);
95 if (ret < 0)
96 return ret;
97 return reg_write(icd, reg, ret | data);
98}
99
100static int reg_clear(struct soc_camera_device *icd, const u8 reg,
101 const u16 data)
102{
103 int ret;
104
105 ret = reg_read(icd, reg);
106 if (ret < 0)
107 return ret;
108 return reg_write(icd, reg, ret & ~data);
109}
110
111static int mt9m001_init(struct soc_camera_device *icd)
112{
113 int ret;
114
115 /* Disable chip, synchronous option update */
116 dev_dbg(icd->vdev->dev, "%s\n", __FUNCTION__);
117
118 ret = reg_write(icd, MT9M001_RESET, 1);
119 if (ret >= 0)
120 ret = reg_write(icd, MT9M001_RESET, 0);
121 if (ret >= 0)
122 ret = reg_write(icd, MT9M001_OUTPUT_CONTROL, 0);
123
124 return ret >= 0 ? 0 : -EIO;
125}
126
127static int mt9m001_release(struct soc_camera_device *icd)
128{
129 /* Disable the chip */
130 reg_write(icd, MT9M001_OUTPUT_CONTROL, 0);
131 return 0;
132}
133
134static int mt9m001_start_capture(struct soc_camera_device *icd)
135{
136 /* Switch to master "normal" mode */
137 if (reg_write(icd, MT9M001_OUTPUT_CONTROL, 2) < 0)
138 return -EIO;
139 return 0;
140}
141
142static int mt9m001_stop_capture(struct soc_camera_device *icd)
143{
144 /* Stop sensor readout */
145 if (reg_write(icd, MT9M001_OUTPUT_CONTROL, 0) < 0)
146 return -EIO;
147 return 0;
148}
149
150static int bus_switch_request(struct mt9m001 *mt9m001,
151 struct soc_camera_link *icl)
152{
153#ifdef CONFIG_MT9M001_PCA9536_SWITCH
154 int ret;
155 unsigned int gpio = icl->gpio;
156
157 if (gpio != NO_GPIO) {
158 /* We have a data bus switch. */
159 ret = gpio_request(gpio, "mt9m001");
160 if (ret < 0) {
161 dev_err(&mt9m001->client->dev, "Cannot get GPIO %u\n",
162 gpio);
163 return ret;
164 }
165
166 ret = gpio_direction_output(gpio, 0);
167 if (ret < 0) {
168 dev_err(&mt9m001->client->dev,
169 "Cannot set GPIO %u to output\n", gpio);
170 gpio_free(gpio);
171 return ret;
172 }
173 }
174
175 mt9m001->switch_gpio = gpio;
176#else
177 mt9m001->switch_gpio = NO_GPIO;
178#endif
179 return 0;
180}
181
182static void bus_switch_release(struct mt9m001 *mt9m001)
183{
184#ifdef CONFIG_MT9M001_PCA9536_SWITCH
185 if (mt9m001->switch_gpio != NO_GPIO)
186 gpio_free(mt9m001->switch_gpio);
187#endif
188}
189
190static int bus_switch_act(struct mt9m001 *mt9m001, int go8bit)
191{
192#ifdef CONFIG_MT9M001_PCA9536_SWITCH
193 if (mt9m001->switch_gpio == NO_GPIO)
194 return -ENODEV;
195
196 gpio_set_value_cansleep(mt9m001->switch_gpio, go8bit);
197 return 0;
198#else
199 return -ENODEV;
200#endif
201}
202
203static int mt9m001_set_capture_format(struct soc_camera_device *icd,
204 __u32 pixfmt, struct v4l2_rect *rect, unsigned int flags)
205{
206 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
207 unsigned int width_flag = flags & (IS_DATAWIDTH_10 | IS_DATAWIDTH_9 |
208 IS_DATAWIDTH_8);
209 int ret;
210 const u16 hblank = 9, vblank = 25;
211
212 /* MT9M001 has all capture_format parameters fixed */
213 if (!(flags & IS_MASTER) ||
214 !(flags & IS_PCLK_SAMPLE_RISING) ||
215 !(flags & IS_HSYNC_ACTIVE_HIGH) ||
216 !(flags & IS_VSYNC_ACTIVE_HIGH))
217 return -EINVAL;
218
219 /* Only one width bit may be set */
220 if (!is_power_of_2(width_flag))
221 return -EINVAL;
222
223 if ((mt9m001->datawidth != 10 && (width_flag == IS_DATAWIDTH_10)) ||
224 (mt9m001->datawidth != 9 && (width_flag == IS_DATAWIDTH_9)) ||
225 (mt9m001->datawidth != 8 && (width_flag == IS_DATAWIDTH_8))) {
226 /* data width switch requested */
227 if (mt9m001->switch_gpio == NO_GPIO)
228 return -EINVAL;
229
230 /* Well, we actually only can do 10 or 8 bits... */
231 if (width_flag == IS_DATAWIDTH_9)
232 return -EINVAL;
233 ret = bus_switch_act(mt9m001,
234 width_flag == IS_DATAWIDTH_8);
235 if (ret < 0)
236 return ret;
237
238 mt9m001->datawidth = width_flag == IS_DATAWIDTH_8 ? 8 : 10;
239 }
240
241 /* Blanking and start values - default... */
242 ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank);
243 if (ret >= 0)
244 ret = reg_write(icd, MT9M001_VERTICAL_BLANKING, vblank);
245
246 /* The caller provides a supported format, as verified per
247 * call to icd->try_fmt_cap() */
248 if (ret >= 0)
249 ret = reg_write(icd, MT9M001_COLUMN_START, rect->left);
250 if (ret >= 0)
251 ret = reg_write(icd, MT9M001_ROW_START, rect->top);
252 if (ret >= 0)
253 ret = reg_write(icd, MT9M001_WINDOW_WIDTH, rect->width - 1);
254 if (ret >= 0)
255 ret = reg_write(icd, MT9M001_WINDOW_HEIGHT,
256 rect->height + icd->y_skip_top - 1);
257 if (ret >= 0 && mt9m001->autoexposure) {
258 ret = reg_write(icd, MT9M001_SHUTTER_WIDTH,
259 rect->height + icd->y_skip_top + vblank);
260 if (ret >= 0) {
261 const struct v4l2_queryctrl *qctrl =
262 soc_camera_find_qctrl(icd->ops,
263 V4L2_CID_EXPOSURE);
264 icd->exposure = (524 + (rect->height + icd->y_skip_top +
265 vblank - 1) *
266 (qctrl->maximum - qctrl->minimum)) /
267 1048 + qctrl->minimum;
268 }
269 }
270
271 return ret < 0 ? ret : 0;
272}
273
274static int mt9m001_try_fmt_cap(struct soc_camera_device *icd,
275 struct v4l2_format *f)
276{
277 if (f->fmt.pix.height < 32 + icd->y_skip_top)
278 f->fmt.pix.height = 32 + icd->y_skip_top;
279 if (f->fmt.pix.height > 1024 + icd->y_skip_top)
280 f->fmt.pix.height = 1024 + icd->y_skip_top;
281 if (f->fmt.pix.width < 48)
282 f->fmt.pix.width = 48;
283 if (f->fmt.pix.width > 1280)
284 f->fmt.pix.width = 1280;
285 f->fmt.pix.width &= ~0x01; /* has to be even, unsure why was ~3 */
286
287 return 0;
288}
289
290static int mt9m001_get_chip_id(struct soc_camera_device *icd,
291 struct v4l2_chip_ident *id)
292{
293 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
294
295 if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR)
296 return -EINVAL;
297
298 if (id->match_chip != mt9m001->client->addr)
299 return -ENODEV;
300
301 id->ident = mt9m001->model;
302 id->revision = 0;
303
304 return 0;
305}
306
307#ifdef CONFIG_VIDEO_ADV_DEBUG
308static int mt9m001_get_register(struct soc_camera_device *icd,
309 struct v4l2_register *reg)
310{
311 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
312
313 if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
314 return -EINVAL;
315
316 if (reg->match_chip != mt9m001->client->addr)
317 return -ENODEV;
318
319 reg->val = reg_read(icd, reg->reg);
320
321 if (reg->val > 0xffff)
322 return -EIO;
323
324 return 0;
325}
326
327static int mt9m001_set_register(struct soc_camera_device *icd,
328 struct v4l2_register *reg)
329{
330 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
331
332 if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
333 return -EINVAL;
334
335 if (reg->match_chip != mt9m001->client->addr)
336 return -ENODEV;
337
338 if (reg_write(icd, reg->reg, reg->val) < 0)
339 return -EIO;
340
341 return 0;
342}
343#endif
344
345static unsigned int mt9m001_get_datawidth(struct soc_camera_device *icd)
346{
347 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
348 return mt9m001->datawidth;
349}
350
351const struct v4l2_queryctrl mt9m001_controls[] = {
352 {
353 .id = V4L2_CID_VFLIP,
354 .type = V4L2_CTRL_TYPE_BOOLEAN,
355 .name = "Flip Vertically",
356 .minimum = 0,
357 .maximum = 1,
358 .step = 1,
359 .default_value = 0,
360 }, {
361 .id = V4L2_CID_GAIN,
362 .type = V4L2_CTRL_TYPE_INTEGER,
363 .name = "Gain",
364 .minimum = 0,
365 .maximum = 127,
366 .step = 1,
367 .default_value = 64,
368 .flags = V4L2_CTRL_FLAG_SLIDER,
369 }, {
370 .id = V4L2_CID_EXPOSURE,
371 .type = V4L2_CTRL_TYPE_INTEGER,
372 .name = "Exposure",
373 .minimum = 1,
374 .maximum = 255,
375 .step = 1,
376 .default_value = 255,
377 .flags = V4L2_CTRL_FLAG_SLIDER,
378 }, {
379 .id = V4L2_CID_EXPOSURE_AUTO,
380 .type = V4L2_CTRL_TYPE_BOOLEAN,
381 .name = "Automatic Exposure",
382 .minimum = 0,
383 .maximum = 1,
384 .step = 1,
385 .default_value = 1,
386 }
387};
388
389static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl);
390static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl);
391
392static struct soc_camera_ops mt9m001_ops = {
393 .owner = THIS_MODULE,
394 .init = mt9m001_init,
395 .release = mt9m001_release,
396 .start_capture = mt9m001_start_capture,
397 .stop_capture = mt9m001_stop_capture,
398 .set_capture_format = mt9m001_set_capture_format,
399 .try_fmt_cap = mt9m001_try_fmt_cap,
400 .formats = NULL, /* Filled in later depending on the */
401 .num_formats = 0, /* camera type and data widths */
402 .get_datawidth = mt9m001_get_datawidth,
403 .controls = mt9m001_controls,
404 .num_controls = ARRAY_SIZE(mt9m001_controls),
405 .get_control = mt9m001_get_control,
406 .set_control = mt9m001_set_control,
407 .get_chip_id = mt9m001_get_chip_id,
408#ifdef CONFIG_VIDEO_ADV_DEBUG
409 .get_register = mt9m001_get_register,
410 .set_register = mt9m001_set_register,
411#endif
412};
413
414static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
415{
416 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
417 int data;
418
419 switch (ctrl->id) {
420 case V4L2_CID_VFLIP:
421 data = reg_read(icd, MT9M001_READ_OPTIONS2);
422 if (data < 0)
423 return -EIO;
424 ctrl->value = !!(data & 0x8000);
425 break;
426 case V4L2_CID_EXPOSURE_AUTO:
427 ctrl->value = mt9m001->autoexposure;
428 break;
429 }
430 return 0;
431}
432
433static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
434{
435 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
436 const struct v4l2_queryctrl *qctrl;
437 int data;
438
439 qctrl = soc_camera_find_qctrl(&mt9m001_ops, ctrl->id);
440
441 if (!qctrl)
442 return -EINVAL;
443
444 switch (ctrl->id) {
445 case V4L2_CID_VFLIP:
446 if (ctrl->value)
447 data = reg_set(icd, MT9M001_READ_OPTIONS2, 0x8000);
448 else
449 data = reg_clear(icd, MT9M001_READ_OPTIONS2, 0x8000);
450 if (data < 0)
451 return -EIO;
452 break;
453 case V4L2_CID_GAIN:
454 if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
455 return -EINVAL;
456 /* See Datasheet Table 7, Gain settings. */
457 if (ctrl->value <= qctrl->default_value) {
458 /* Pack it into 0..1 step 0.125, register values 0..8 */
459 unsigned long range = qctrl->default_value - qctrl->minimum;
460 data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range;
461
462 dev_dbg(&icd->dev, "Setting gain %d\n", data);
463 data = reg_write(icd, MT9M001_GLOBAL_GAIN, data);
464 if (data < 0)
465 return -EIO;
466 } else {
467 /* Pack it into 1.125..15 variable step, register values 9..67 */
468 /* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */
469 unsigned long range = qctrl->maximum - qctrl->default_value - 1;
470 unsigned long gain = ((ctrl->value - qctrl->default_value - 1) *
471 111 + range / 2) / range + 9;
472
473 if (gain <= 32)
474 data = gain;
475 else if (gain <= 64)
476 data = ((gain - 32) * 16 + 16) / 32 + 80;
477 else
478 data = ((gain - 64) * 7 + 28) / 56 + 96;
479
480 dev_dbg(&icd->dev, "Setting gain from %d to %d\n",
481 reg_read(icd, MT9M001_GLOBAL_GAIN), data);
482 data = reg_write(icd, MT9M001_GLOBAL_GAIN, data);
483 if (data < 0)
484 return -EIO;
485 }
486
487 /* Success */
488 icd->gain = ctrl->value;
489 break;
490 case V4L2_CID_EXPOSURE:
491 /* mt9m001 has maximum == default */
492 if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
493 return -EINVAL;
494 else {
495 unsigned long range = qctrl->maximum - qctrl->minimum;
496 unsigned long shutter = ((ctrl->value - qctrl->minimum) * 1048 +
497 range / 2) / range + 1;
498
499 dev_dbg(&icd->dev, "Setting shutter width from %d to %lu\n",
500 reg_read(icd, MT9M001_SHUTTER_WIDTH), shutter);
501 if (reg_write(icd, MT9M001_SHUTTER_WIDTH, shutter) < 0)
502 return -EIO;
503 icd->exposure = ctrl->value;
504 mt9m001->autoexposure = 0;
505 }
506 break;
507 case V4L2_CID_EXPOSURE_AUTO:
508 if (ctrl->value) {
509 const u16 vblank = 25;
510 if (reg_write(icd, MT9M001_SHUTTER_WIDTH, icd->height +
511 icd->y_skip_top + vblank) < 0)
512 return -EIO;
513 qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
514 icd->exposure = (524 + (icd->height + icd->y_skip_top + vblank - 1) *
515 (qctrl->maximum - qctrl->minimum)) /
516 1048 + qctrl->minimum;
517 mt9m001->autoexposure = 1;
518 } else
519 mt9m001->autoexposure = 0;
520 break;
521 }
522 return 0;
523}
524
525/* Interface active, can use i2c. If it fails, it can indeed mean, that
526 * this wasn't our capture interface, so, we wait for the right one */
527static int mt9m001_video_probe(struct soc_camera_device *icd)
528{
529 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
530 s32 data;
531 int ret;
532
533 /* We must have a parent by now. And it cannot be a wrong one.
534 * So this entire test is completely redundant. */
535 if (!icd->dev.parent ||
536 to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
537 return -ENODEV;
538
539 /* Enable the chip */
540 data = reg_write(&mt9m001->icd, MT9M001_CHIP_ENABLE, 1);
541 dev_dbg(&icd->dev, "write: %d\n", data);
542
543 /* Read out the chip version register */
544 data = reg_read(icd, MT9M001_CHIP_VERSION);
545
546 /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
547 switch (data) {
548 case 0x8411:
549 case 0x8421:
550 mt9m001->model = V4L2_IDENT_MT9M001C12ST;
551 mt9m001_ops.formats = mt9m001_colour_formats;
552 mt9m001_ops.num_formats = ARRAY_SIZE(mt9m001_colour_formats);
553 break;
554 case 0x8431:
555 mt9m001->model = V4L2_IDENT_MT9M001C12STM;
556 mt9m001_ops.formats = mt9m001_monochrome_formats;
557 if (mt9m001->client->dev.platform_data)
558 mt9m001_ops.num_formats = ARRAY_SIZE(mt9m001_monochrome_formats);
559 else
560 mt9m001_ops.num_formats = 1;
561 break;
562 default:
563 ret = -ENODEV;
564 dev_err(&icd->dev,
565 "No MT9M001 chip detected, register read %x\n", data);
566 goto ei2c;
567 }
568
569 dev_info(&icd->dev, "Detected a MT9M001 chip ID %x (%s)\n", data,
570 data == 0x8431 ? "C12STM" : "C12ST");
571
572 /* Now that we know the model, we can start video */
573 ret = soc_camera_video_start(icd);
574 if (ret)
575 goto eisis;
576
577 return 0;
578
579eisis:
580ei2c:
581 return ret;
582}
583
584static void mt9m001_video_remove(struct soc_camera_device *icd)
585{
586 struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
587
588 dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m001->client->addr,
589 mt9m001->icd.dev.parent, mt9m001->icd.vdev);
590 soc_camera_video_stop(&mt9m001->icd);
591}
592
593static int mt9m001_probe(struct i2c_client *client)
594{
595 struct mt9m001 *mt9m001;
596 struct soc_camera_device *icd;
597 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
598 struct soc_camera_link *icl = client->dev.platform_data;
599 int ret;
600
601 if (!icl) {
602 dev_err(&client->dev, "MT9M001 driver needs platform data\n");
603 return -EINVAL;
604 }
605
606 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
607 dev_warn(&adapter->dev,
608 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
609 return -EIO;
610 }
611
612 mt9m001 = kzalloc(sizeof(struct mt9m001), GFP_KERNEL);
613 if (!mt9m001)
614 return -ENOMEM;
615
616 mt9m001->client = client;
617 i2c_set_clientdata(client, mt9m001);
618
619 /* Second stage probe - when a capture adapter is there */
620 icd = &mt9m001->icd;
621 icd->probe = mt9m001_video_probe;
622 icd->remove = mt9m001_video_remove;
623 icd->ops = &mt9m001_ops;
624 icd->control = &client->dev;
625 icd->x_min = 20;
626 icd->y_min = 12;
627 icd->x_current = 20;
628 icd->y_current = 12;
629 icd->width_min = 48;
630 icd->width_max = 1280;
631 icd->height_min = 32;
632 icd->height_max = 1024;
633 icd->y_skip_top = 1;
634 icd->iface = icl->bus_id;
635 /* Default datawidth - this is the only width this camera (normally)
636 * supports. It is only with extra logic that it can support
637 * other widths. Therefore it seems to be a sensible default. */
638 mt9m001->datawidth = 10;
639 /* Simulated autoexposure. If enabled, we calculate shutter width
640 * ourselves in the driver based on vertical blanking and frame width */
641 mt9m001->autoexposure = 1;
642
643 ret = bus_switch_request(mt9m001, icl);
644 if (ret)
645 goto eswinit;
646
647 ret = soc_camera_device_register(icd);
648 if (ret)
649 goto eisdr;
650
651 return 0;
652
653eisdr:
654 bus_switch_release(mt9m001);
655eswinit:
656 kfree(mt9m001);
657 return ret;
658}
659
660static int mt9m001_remove(struct i2c_client *client)
661{
662 struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
663
664 soc_camera_device_unregister(&mt9m001->icd);
665 bus_switch_release(mt9m001);
666 kfree(mt9m001);
667
668 return 0;
669}
670
671static struct i2c_driver mt9m001_i2c_driver = {
672 .driver = {
673 .name = "mt9m001",
674 },
675 .probe = mt9m001_probe,
676 .remove = mt9m001_remove,
677};
678
679static int __init mt9m001_mod_init(void)
680{
681 return i2c_add_driver(&mt9m001_i2c_driver);
682}
683
684static void __exit mt9m001_mod_exit(void)
685{
686 i2c_del_driver(&mt9m001_i2c_driver);
687}
688
689module_init(mt9m001_mod_init);
690module_exit(mt9m001_mod_exit);
691
692MODULE_DESCRIPTION("Micron MT9M001 Camera driver");
693MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
694MODULE_LICENSE("GPL");