diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
commit | fcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch) | |
tree | a57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/media/video/mt9t031.c | |
parent | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff) |
Diffstat (limited to 'drivers/media/video/mt9t031.c')
-rw-r--r-- | drivers/media/video/mt9t031.c | 933 |
1 files changed, 933 insertions, 0 deletions
diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c new file mode 100644 index 00000000000..30547cc3f89 --- /dev/null +++ b/drivers/media/video/mt9t031.c | |||
@@ -0,0 +1,933 @@ | |||
1 | /* | ||
2 | * Driver for MT9T031 CMOS Image Sensor from Micron | ||
3 | * | ||
4 | * Copyright (C) 2008, Guennadi Liakhovetski, DENX Software Engineering <lg@denx.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/device.h> | ||
12 | #include <linux/i2c.h> | ||
13 | #include <linux/log2.h> | ||
14 | #include <linux/pm.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/videodev2.h> | ||
17 | |||
18 | #include <media/soc_camera.h> | ||
19 | #include <media/v4l2-chip-ident.h> | ||
20 | #include <media/v4l2-subdev.h> | ||
21 | |||
22 | /* | ||
23 | * mt9t031 i2c address 0x5d | ||
24 | * The platform has to define i2c_board_info and link to it from | ||
25 | * struct soc_camera_link | ||
26 | */ | ||
27 | |||
28 | /* mt9t031 selected register addresses */ | ||
29 | #define MT9T031_CHIP_VERSION 0x00 | ||
30 | #define MT9T031_ROW_START 0x01 | ||
31 | #define MT9T031_COLUMN_START 0x02 | ||
32 | #define MT9T031_WINDOW_HEIGHT 0x03 | ||
33 | #define MT9T031_WINDOW_WIDTH 0x04 | ||
34 | #define MT9T031_HORIZONTAL_BLANKING 0x05 | ||
35 | #define MT9T031_VERTICAL_BLANKING 0x06 | ||
36 | #define MT9T031_OUTPUT_CONTROL 0x07 | ||
37 | #define MT9T031_SHUTTER_WIDTH_UPPER 0x08 | ||
38 | #define MT9T031_SHUTTER_WIDTH 0x09 | ||
39 | #define MT9T031_PIXEL_CLOCK_CONTROL 0x0a | ||
40 | #define MT9T031_FRAME_RESTART 0x0b | ||
41 | #define MT9T031_SHUTTER_DELAY 0x0c | ||
42 | #define MT9T031_RESET 0x0d | ||
43 | #define MT9T031_READ_MODE_1 0x1e | ||
44 | #define MT9T031_READ_MODE_2 0x20 | ||
45 | #define MT9T031_READ_MODE_3 0x21 | ||
46 | #define MT9T031_ROW_ADDRESS_MODE 0x22 | ||
47 | #define MT9T031_COLUMN_ADDRESS_MODE 0x23 | ||
48 | #define MT9T031_GLOBAL_GAIN 0x35 | ||
49 | #define MT9T031_CHIP_ENABLE 0xF8 | ||
50 | |||
51 | #define MT9T031_MAX_HEIGHT 1536 | ||
52 | #define MT9T031_MAX_WIDTH 2048 | ||
53 | #define MT9T031_MIN_HEIGHT 2 | ||
54 | #define MT9T031_MIN_WIDTH 18 | ||
55 | #define MT9T031_HORIZONTAL_BLANK 142 | ||
56 | #define MT9T031_VERTICAL_BLANK 25 | ||
57 | #define MT9T031_COLUMN_SKIP 32 | ||
58 | #define MT9T031_ROW_SKIP 20 | ||
59 | |||
60 | #define MT9T031_BUS_PARAM (SOCAM_PCLK_SAMPLE_RISING | \ | ||
61 | SOCAM_PCLK_SAMPLE_FALLING | SOCAM_HSYNC_ACTIVE_HIGH | \ | ||
62 | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | \ | ||
63 | SOCAM_MASTER | SOCAM_DATAWIDTH_10) | ||
64 | |||
65 | struct mt9t031 { | ||
66 | struct v4l2_subdev subdev; | ||
67 | struct v4l2_rect rect; /* Sensor window */ | ||
68 | int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */ | ||
69 | u16 xskip; | ||
70 | u16 yskip; | ||
71 | unsigned int gain; | ||
72 | unsigned short y_skip_top; /* Lines to skip at the top */ | ||
73 | unsigned int exposure; | ||
74 | unsigned char autoexposure; | ||
75 | }; | ||
76 | |||
77 | static struct mt9t031 *to_mt9t031(const struct i2c_client *client) | ||
78 | { | ||
79 | return container_of(i2c_get_clientdata(client), struct mt9t031, subdev); | ||
80 | } | ||
81 | |||
82 | static int reg_read(struct i2c_client *client, const u8 reg) | ||
83 | { | ||
84 | s32 data = i2c_smbus_read_word_data(client, reg); | ||
85 | return data < 0 ? data : swab16(data); | ||
86 | } | ||
87 | |||
88 | static int reg_write(struct i2c_client *client, const u8 reg, | ||
89 | const u16 data) | ||
90 | { | ||
91 | return i2c_smbus_write_word_data(client, reg, swab16(data)); | ||
92 | } | ||
93 | |||
94 | static int reg_set(struct i2c_client *client, const u8 reg, | ||
95 | const u16 data) | ||
96 | { | ||
97 | int ret; | ||
98 | |||
99 | ret = reg_read(client, reg); | ||
100 | if (ret < 0) | ||
101 | return ret; | ||
102 | return reg_write(client, reg, ret | data); | ||
103 | } | ||
104 | |||
105 | static int reg_clear(struct i2c_client *client, const u8 reg, | ||
106 | const u16 data) | ||
107 | { | ||
108 | int ret; | ||
109 | |||
110 | ret = reg_read(client, reg); | ||
111 | if (ret < 0) | ||
112 | return ret; | ||
113 | return reg_write(client, reg, ret & ~data); | ||
114 | } | ||
115 | |||
116 | static int set_shutter(struct i2c_client *client, const u32 data) | ||
117 | { | ||
118 | int ret; | ||
119 | |||
120 | ret = reg_write(client, MT9T031_SHUTTER_WIDTH_UPPER, data >> 16); | ||
121 | |||
122 | if (ret >= 0) | ||
123 | ret = reg_write(client, MT9T031_SHUTTER_WIDTH, data & 0xffff); | ||
124 | |||
125 | return ret; | ||
126 | } | ||
127 | |||
128 | static int get_shutter(struct i2c_client *client, u32 *data) | ||
129 | { | ||
130 | int ret; | ||
131 | |||
132 | ret = reg_read(client, MT9T031_SHUTTER_WIDTH_UPPER); | ||
133 | *data = ret << 16; | ||
134 | |||
135 | if (ret >= 0) | ||
136 | ret = reg_read(client, MT9T031_SHUTTER_WIDTH); | ||
137 | *data |= ret & 0xffff; | ||
138 | |||
139 | return ret < 0 ? ret : 0; | ||
140 | } | ||
141 | |||
142 | static int mt9t031_idle(struct i2c_client *client) | ||
143 | { | ||
144 | int ret; | ||
145 | |||
146 | /* Disable chip output, synchronous option update */ | ||
147 | ret = reg_write(client, MT9T031_RESET, 1); | ||
148 | if (ret >= 0) | ||
149 | ret = reg_write(client, MT9T031_RESET, 0); | ||
150 | if (ret >= 0) | ||
151 | ret = reg_clear(client, MT9T031_OUTPUT_CONTROL, 2); | ||
152 | |||
153 | return ret >= 0 ? 0 : -EIO; | ||
154 | } | ||
155 | |||
156 | static int mt9t031_disable(struct i2c_client *client) | ||
157 | { | ||
158 | /* Disable the chip */ | ||
159 | reg_clear(client, MT9T031_OUTPUT_CONTROL, 2); | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static int mt9t031_s_stream(struct v4l2_subdev *sd, int enable) | ||
165 | { | ||
166 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
167 | int ret; | ||
168 | |||
169 | if (enable) | ||
170 | /* Switch to master "normal" mode */ | ||
171 | ret = reg_set(client, MT9T031_OUTPUT_CONTROL, 2); | ||
172 | else | ||
173 | /* Stop sensor readout */ | ||
174 | ret = reg_clear(client, MT9T031_OUTPUT_CONTROL, 2); | ||
175 | |||
176 | if (ret < 0) | ||
177 | return -EIO; | ||
178 | |||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static int mt9t031_set_bus_param(struct soc_camera_device *icd, | ||
183 | unsigned long flags) | ||
184 | { | ||
185 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | ||
186 | |||
187 | /* The caller should have queried our parameters, check anyway */ | ||
188 | if (flags & ~MT9T031_BUS_PARAM) | ||
189 | return -EINVAL; | ||
190 | |||
191 | if (flags & SOCAM_PCLK_SAMPLE_FALLING) | ||
192 | reg_clear(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000); | ||
193 | else | ||
194 | reg_set(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000); | ||
195 | |||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | static unsigned long mt9t031_query_bus_param(struct soc_camera_device *icd) | ||
200 | { | ||
201 | struct soc_camera_link *icl = to_soc_camera_link(icd); | ||
202 | |||
203 | return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM); | ||
204 | } | ||
205 | |||
206 | enum { | ||
207 | MT9T031_CTRL_VFLIP, | ||
208 | MT9T031_CTRL_HFLIP, | ||
209 | MT9T031_CTRL_GAIN, | ||
210 | MT9T031_CTRL_EXPOSURE, | ||
211 | MT9T031_CTRL_EXPOSURE_AUTO, | ||
212 | }; | ||
213 | |||
214 | static const struct v4l2_queryctrl mt9t031_controls[] = { | ||
215 | [MT9T031_CTRL_VFLIP] = { | ||
216 | .id = V4L2_CID_VFLIP, | ||
217 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
218 | .name = "Flip Vertically", | ||
219 | .minimum = 0, | ||
220 | .maximum = 1, | ||
221 | .step = 1, | ||
222 | .default_value = 0, | ||
223 | }, | ||
224 | [MT9T031_CTRL_HFLIP] = { | ||
225 | .id = V4L2_CID_HFLIP, | ||
226 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
227 | .name = "Flip Horizontally", | ||
228 | .minimum = 0, | ||
229 | .maximum = 1, | ||
230 | .step = 1, | ||
231 | .default_value = 0, | ||
232 | }, | ||
233 | [MT9T031_CTRL_GAIN] = { | ||
234 | .id = V4L2_CID_GAIN, | ||
235 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
236 | .name = "Gain", | ||
237 | .minimum = 0, | ||
238 | .maximum = 127, | ||
239 | .step = 1, | ||
240 | .default_value = 64, | ||
241 | .flags = V4L2_CTRL_FLAG_SLIDER, | ||
242 | }, | ||
243 | [MT9T031_CTRL_EXPOSURE] = { | ||
244 | .id = V4L2_CID_EXPOSURE, | ||
245 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
246 | .name = "Exposure", | ||
247 | .minimum = 1, | ||
248 | .maximum = 255, | ||
249 | .step = 1, | ||
250 | .default_value = 255, | ||
251 | .flags = V4L2_CTRL_FLAG_SLIDER, | ||
252 | }, | ||
253 | [MT9T031_CTRL_EXPOSURE_AUTO] = { | ||
254 | .id = V4L2_CID_EXPOSURE_AUTO, | ||
255 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
256 | .name = "Automatic Exposure", | ||
257 | .minimum = 0, | ||
258 | .maximum = 1, | ||
259 | .step = 1, | ||
260 | .default_value = 1, | ||
261 | } | ||
262 | }; | ||
263 | |||
264 | static struct soc_camera_ops mt9t031_ops = { | ||
265 | .set_bus_param = mt9t031_set_bus_param, | ||
266 | .query_bus_param = mt9t031_query_bus_param, | ||
267 | .controls = mt9t031_controls, | ||
268 | .num_controls = ARRAY_SIZE(mt9t031_controls), | ||
269 | }; | ||
270 | |||
271 | /* target must be _even_ */ | ||
272 | static u16 mt9t031_skip(s32 *source, s32 target, s32 max) | ||
273 | { | ||
274 | unsigned int skip; | ||
275 | |||
276 | if (*source < target + target / 2) { | ||
277 | *source = target; | ||
278 | return 1; | ||
279 | } | ||
280 | |||
281 | skip = min(max, *source + target / 2) / target; | ||
282 | if (skip > 8) | ||
283 | skip = 8; | ||
284 | *source = target * skip; | ||
285 | |||
286 | return skip; | ||
287 | } | ||
288 | |||
289 | /* rect is the sensor rectangle, the caller guarantees parameter validity */ | ||
290 | static int mt9t031_set_params(struct i2c_client *client, | ||
291 | struct v4l2_rect *rect, u16 xskip, u16 yskip) | ||
292 | { | ||
293 | struct mt9t031 *mt9t031 = to_mt9t031(client); | ||
294 | int ret; | ||
295 | u16 xbin, ybin; | ||
296 | const u16 hblank = MT9T031_HORIZONTAL_BLANK, | ||
297 | vblank = MT9T031_VERTICAL_BLANK; | ||
298 | |||
299 | xbin = min(xskip, (u16)3); | ||
300 | ybin = min(yskip, (u16)3); | ||
301 | |||
302 | /* | ||
303 | * Could just do roundup(rect->left, [xy]bin * 2); but this is cheaper. | ||
304 | * There is always a valid suitably aligned value. The worst case is | ||
305 | * xbin = 3, width = 2048. Then we will start at 36, the last read out | ||
306 | * pixel will be 2083, which is < 2085 - first black pixel. | ||
307 | * | ||
308 | * MT9T031 datasheet imposes window left border alignment, depending on | ||
309 | * the selected xskip. Failing to conform to this requirement produces | ||
310 | * dark horizontal stripes in the image. However, even obeying to this | ||
311 | * requirement doesn't eliminate the stripes in all configurations. They | ||
312 | * appear "locally reproducibly," but can differ between tests under | ||
313 | * different lighting conditions. | ||
314 | */ | ||
315 | switch (xbin) { | ||
316 | case 1: | ||
317 | rect->left &= ~1; | ||
318 | break; | ||
319 | case 2: | ||
320 | rect->left &= ~3; | ||
321 | break; | ||
322 | case 3: | ||
323 | rect->left = rect->left > roundup(MT9T031_COLUMN_SKIP, 6) ? | ||
324 | (rect->left / 6) * 6 : roundup(MT9T031_COLUMN_SKIP, 6); | ||
325 | } | ||
326 | |||
327 | rect->top &= ~1; | ||
328 | |||
329 | dev_dbg(&client->dev, "skip %u:%u, rect %ux%u@%u:%u\n", | ||
330 | xskip, yskip, rect->width, rect->height, rect->left, rect->top); | ||
331 | |||
332 | /* Disable register update, reconfigure atomically */ | ||
333 | ret = reg_set(client, MT9T031_OUTPUT_CONTROL, 1); | ||
334 | if (ret < 0) | ||
335 | return ret; | ||
336 | |||
337 | /* Blanking and start values - default... */ | ||
338 | ret = reg_write(client, MT9T031_HORIZONTAL_BLANKING, hblank); | ||
339 | if (ret >= 0) | ||
340 | ret = reg_write(client, MT9T031_VERTICAL_BLANKING, vblank); | ||
341 | |||
342 | if (yskip != mt9t031->yskip || xskip != mt9t031->xskip) { | ||
343 | /* Binning, skipping */ | ||
344 | if (ret >= 0) | ||
345 | ret = reg_write(client, MT9T031_COLUMN_ADDRESS_MODE, | ||
346 | ((xbin - 1) << 4) | (xskip - 1)); | ||
347 | if (ret >= 0) | ||
348 | ret = reg_write(client, MT9T031_ROW_ADDRESS_MODE, | ||
349 | ((ybin - 1) << 4) | (yskip - 1)); | ||
350 | } | ||
351 | dev_dbg(&client->dev, "new physical left %u, top %u\n", | ||
352 | rect->left, rect->top); | ||
353 | |||
354 | /* | ||
355 | * The caller provides a supported format, as guaranteed by | ||
356 | * icd->try_fmt_cap(), soc_camera_s_crop() and soc_camera_cropcap() | ||
357 | */ | ||
358 | if (ret >= 0) | ||
359 | ret = reg_write(client, MT9T031_COLUMN_START, rect->left); | ||
360 | if (ret >= 0) | ||
361 | ret = reg_write(client, MT9T031_ROW_START, rect->top); | ||
362 | if (ret >= 0) | ||
363 | ret = reg_write(client, MT9T031_WINDOW_WIDTH, rect->width - 1); | ||
364 | if (ret >= 0) | ||
365 | ret = reg_write(client, MT9T031_WINDOW_HEIGHT, | ||
366 | rect->height + mt9t031->y_skip_top - 1); | ||
367 | if (ret >= 0 && mt9t031->autoexposure) { | ||
368 | unsigned int total_h = rect->height + mt9t031->y_skip_top + vblank; | ||
369 | ret = set_shutter(client, total_h); | ||
370 | if (ret >= 0) { | ||
371 | const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; | ||
372 | const struct v4l2_queryctrl *qctrl = | ||
373 | &mt9t031_controls[MT9T031_CTRL_EXPOSURE]; | ||
374 | mt9t031->exposure = (shutter_max / 2 + (total_h - 1) * | ||
375 | (qctrl->maximum - qctrl->minimum)) / | ||
376 | shutter_max + qctrl->minimum; | ||
377 | } | ||
378 | } | ||
379 | |||
380 | /* Re-enable register update, commit all changes */ | ||
381 | if (ret >= 0) | ||
382 | ret = reg_clear(client, MT9T031_OUTPUT_CONTROL, 1); | ||
383 | |||
384 | if (ret >= 0) { | ||
385 | mt9t031->rect = *rect; | ||
386 | mt9t031->xskip = xskip; | ||
387 | mt9t031->yskip = yskip; | ||
388 | } | ||
389 | |||
390 | return ret < 0 ? ret : 0; | ||
391 | } | ||
392 | |||
393 | static int mt9t031_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | ||
394 | { | ||
395 | struct v4l2_rect rect = a->c; | ||
396 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
397 | struct mt9t031 *mt9t031 = to_mt9t031(client); | ||
398 | |||
399 | rect.width = ALIGN(rect.width, 2); | ||
400 | rect.height = ALIGN(rect.height, 2); | ||
401 | |||
402 | soc_camera_limit_side(&rect.left, &rect.width, | ||
403 | MT9T031_COLUMN_SKIP, MT9T031_MIN_WIDTH, MT9T031_MAX_WIDTH); | ||
404 | |||
405 | soc_camera_limit_side(&rect.top, &rect.height, | ||
406 | MT9T031_ROW_SKIP, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT); | ||
407 | |||
408 | return mt9t031_set_params(client, &rect, mt9t031->xskip, mt9t031->yskip); | ||
409 | } | ||
410 | |||
411 | static int mt9t031_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | ||
412 | { | ||
413 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
414 | struct mt9t031 *mt9t031 = to_mt9t031(client); | ||
415 | |||
416 | a->c = mt9t031->rect; | ||
417 | a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
418 | |||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | static int mt9t031_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) | ||
423 | { | ||
424 | a->bounds.left = MT9T031_COLUMN_SKIP; | ||
425 | a->bounds.top = MT9T031_ROW_SKIP; | ||
426 | a->bounds.width = MT9T031_MAX_WIDTH; | ||
427 | a->bounds.height = MT9T031_MAX_HEIGHT; | ||
428 | a->defrect = a->bounds; | ||
429 | a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
430 | a->pixelaspect.numerator = 1; | ||
431 | a->pixelaspect.denominator = 1; | ||
432 | |||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | static int mt9t031_g_fmt(struct v4l2_subdev *sd, | ||
437 | struct v4l2_mbus_framefmt *mf) | ||
438 | { | ||
439 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
440 | struct mt9t031 *mt9t031 = to_mt9t031(client); | ||
441 | |||
442 | mf->width = mt9t031->rect.width / mt9t031->xskip; | ||
443 | mf->height = mt9t031->rect.height / mt9t031->yskip; | ||
444 | mf->code = V4L2_MBUS_FMT_SBGGR10_1X10; | ||
445 | mf->colorspace = V4L2_COLORSPACE_SRGB; | ||
446 | mf->field = V4L2_FIELD_NONE; | ||
447 | |||
448 | return 0; | ||
449 | } | ||
450 | |||
451 | static int mt9t031_s_fmt(struct v4l2_subdev *sd, | ||
452 | struct v4l2_mbus_framefmt *mf) | ||
453 | { | ||
454 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
455 | struct mt9t031 *mt9t031 = to_mt9t031(client); | ||
456 | u16 xskip, yskip; | ||
457 | struct v4l2_rect rect = mt9t031->rect; | ||
458 | |||
459 | /* | ||
460 | * try_fmt has put width and height within limits. | ||
461 | * S_FMT: use binning and skipping for scaling | ||
462 | */ | ||
463 | xskip = mt9t031_skip(&rect.width, mf->width, MT9T031_MAX_WIDTH); | ||
464 | yskip = mt9t031_skip(&rect.height, mf->height, MT9T031_MAX_HEIGHT); | ||
465 | |||
466 | mf->code = V4L2_MBUS_FMT_SBGGR10_1X10; | ||
467 | mf->colorspace = V4L2_COLORSPACE_SRGB; | ||
468 | |||
469 | /* mt9t031_set_params() doesn't change width and height */ | ||
470 | return mt9t031_set_params(client, &rect, xskip, yskip); | ||
471 | } | ||
472 | |||
473 | /* | ||
474 | * If a user window larger than sensor window is requested, we'll increase the | ||
475 | * sensor window. | ||
476 | */ | ||
477 | static int mt9t031_try_fmt(struct v4l2_subdev *sd, | ||
478 | struct v4l2_mbus_framefmt *mf) | ||
479 | { | ||
480 | v4l_bound_align_image( | ||
481 | &mf->width, MT9T031_MIN_WIDTH, MT9T031_MAX_WIDTH, 1, | ||
482 | &mf->height, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT, 1, 0); | ||
483 | |||
484 | mf->code = V4L2_MBUS_FMT_SBGGR10_1X10; | ||
485 | mf->colorspace = V4L2_COLORSPACE_SRGB; | ||
486 | |||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | static int mt9t031_g_chip_ident(struct v4l2_subdev *sd, | ||
491 | struct v4l2_dbg_chip_ident *id) | ||
492 | { | ||
493 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
494 | struct mt9t031 *mt9t031 = to_mt9t031(client); | ||
495 | |||
496 | if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) | ||
497 | return -EINVAL; | ||
498 | |||
499 | if (id->match.addr != client->addr) | ||
500 | return -ENODEV; | ||
501 | |||
502 | id->ident = mt9t031->model; | ||
503 | id->revision = 0; | ||
504 | |||
505 | return 0; | ||
506 | } | ||
507 | |||
508 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
509 | static int mt9t031_g_register(struct v4l2_subdev *sd, | ||
510 | struct v4l2_dbg_register *reg) | ||
511 | { | ||
512 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
513 | |||
514 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) | ||
515 | return -EINVAL; | ||
516 | |||
517 | if (reg->match.addr != client->addr) | ||
518 | return -ENODEV; | ||
519 | |||
520 | reg->val = reg_read(client, reg->reg); | ||
521 | |||
522 | if (reg->val > 0xffff) | ||
523 | return -EIO; | ||
524 | |||
525 | return 0; | ||
526 | } | ||
527 | |||
528 | static int mt9t031_s_register(struct v4l2_subdev *sd, | ||
529 | struct v4l2_dbg_register *reg) | ||
530 | { | ||
531 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
532 | |||
533 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) | ||
534 | return -EINVAL; | ||
535 | |||
536 | if (reg->match.addr != client->addr) | ||
537 | return -ENODEV; | ||
538 | |||
539 | if (reg_write(client, reg->reg, reg->val) < 0) | ||
540 | return -EIO; | ||
541 | |||
542 | return 0; | ||
543 | } | ||
544 | #endif | ||
545 | |||
546 | static int mt9t031_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
547 | { | ||
548 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
549 | struct mt9t031 *mt9t031 = to_mt9t031(client); | ||
550 | int data; | ||
551 | |||
552 | switch (ctrl->id) { | ||
553 | case V4L2_CID_VFLIP: | ||
554 | data = reg_read(client, MT9T031_READ_MODE_2); | ||
555 | if (data < 0) | ||
556 | return -EIO; | ||
557 | ctrl->value = !!(data & 0x8000); | ||
558 | break; | ||
559 | case V4L2_CID_HFLIP: | ||
560 | data = reg_read(client, MT9T031_READ_MODE_2); | ||
561 | if (data < 0) | ||
562 | return -EIO; | ||
563 | ctrl->value = !!(data & 0x4000); | ||
564 | break; | ||
565 | case V4L2_CID_EXPOSURE_AUTO: | ||
566 | ctrl->value = mt9t031->autoexposure; | ||
567 | break; | ||
568 | case V4L2_CID_GAIN: | ||
569 | ctrl->value = mt9t031->gain; | ||
570 | break; | ||
571 | case V4L2_CID_EXPOSURE: | ||
572 | ctrl->value = mt9t031->exposure; | ||
573 | break; | ||
574 | } | ||
575 | return 0; | ||
576 | } | ||
577 | |||
578 | static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
579 | { | ||
580 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
581 | struct mt9t031 *mt9t031 = to_mt9t031(client); | ||
582 | const struct v4l2_queryctrl *qctrl; | ||
583 | int data; | ||
584 | |||
585 | switch (ctrl->id) { | ||
586 | case V4L2_CID_VFLIP: | ||
587 | if (ctrl->value) | ||
588 | data = reg_set(client, MT9T031_READ_MODE_2, 0x8000); | ||
589 | else | ||
590 | data = reg_clear(client, MT9T031_READ_MODE_2, 0x8000); | ||
591 | if (data < 0) | ||
592 | return -EIO; | ||
593 | break; | ||
594 | case V4L2_CID_HFLIP: | ||
595 | if (ctrl->value) | ||
596 | data = reg_set(client, MT9T031_READ_MODE_2, 0x4000); | ||
597 | else | ||
598 | data = reg_clear(client, MT9T031_READ_MODE_2, 0x4000); | ||
599 | if (data < 0) | ||
600 | return -EIO; | ||
601 | break; | ||
602 | case V4L2_CID_GAIN: | ||
603 | qctrl = &mt9t031_controls[MT9T031_CTRL_GAIN]; | ||
604 | if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum) | ||
605 | return -EINVAL; | ||
606 | /* See Datasheet Table 7, Gain settings. */ | ||
607 | if (ctrl->value <= qctrl->default_value) { | ||
608 | /* Pack it into 0..1 step 0.125, register values 0..8 */ | ||
609 | unsigned long range = qctrl->default_value - qctrl->minimum; | ||
610 | data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range; | ||
611 | |||
612 | dev_dbg(&client->dev, "Setting gain %d\n", data); | ||
613 | data = reg_write(client, MT9T031_GLOBAL_GAIN, data); | ||
614 | if (data < 0) | ||
615 | return -EIO; | ||
616 | } else { | ||
617 | /* Pack it into 1.125..128 variable step, register values 9..0x7860 */ | ||
618 | /* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */ | ||
619 | unsigned long range = qctrl->maximum - qctrl->default_value - 1; | ||
620 | /* calculated gain: map 65..127 to 9..1024 step 0.125 */ | ||
621 | unsigned long gain = ((ctrl->value - qctrl->default_value - 1) * | ||
622 | 1015 + range / 2) / range + 9; | ||
623 | |||
624 | if (gain <= 32) /* calculated gain 9..32 -> 9..32 */ | ||
625 | data = gain; | ||
626 | else if (gain <= 64) /* calculated gain 33..64 -> 0x51..0x60 */ | ||
627 | data = ((gain - 32) * 16 + 16) / 32 + 80; | ||
628 | else | ||
629 | /* calculated gain 65..1024 -> (1..120) << 8 + 0x60 */ | ||
630 | data = (((gain - 64 + 7) * 32) & 0xff00) | 0x60; | ||
631 | |||
632 | dev_dbg(&client->dev, "Set gain from 0x%x to 0x%x\n", | ||
633 | reg_read(client, MT9T031_GLOBAL_GAIN), data); | ||
634 | data = reg_write(client, MT9T031_GLOBAL_GAIN, data); | ||
635 | if (data < 0) | ||
636 | return -EIO; | ||
637 | } | ||
638 | |||
639 | /* Success */ | ||
640 | mt9t031->gain = ctrl->value; | ||
641 | break; | ||
642 | case V4L2_CID_EXPOSURE: | ||
643 | qctrl = &mt9t031_controls[MT9T031_CTRL_EXPOSURE]; | ||
644 | /* mt9t031 has maximum == default */ | ||
645 | if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum) | ||
646 | return -EINVAL; | ||
647 | else { | ||
648 | const unsigned long range = qctrl->maximum - qctrl->minimum; | ||
649 | const u32 shutter = ((ctrl->value - qctrl->minimum) * 1048 + | ||
650 | range / 2) / range + 1; | ||
651 | u32 old; | ||
652 | |||
653 | get_shutter(client, &old); | ||
654 | dev_dbg(&client->dev, "Set shutter from %u to %u\n", | ||
655 | old, shutter); | ||
656 | if (set_shutter(client, shutter) < 0) | ||
657 | return -EIO; | ||
658 | mt9t031->exposure = ctrl->value; | ||
659 | mt9t031->autoexposure = 0; | ||
660 | } | ||
661 | break; | ||
662 | case V4L2_CID_EXPOSURE_AUTO: | ||
663 | if (ctrl->value) { | ||
664 | const u16 vblank = MT9T031_VERTICAL_BLANK; | ||
665 | const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; | ||
666 | unsigned int total_h = mt9t031->rect.height + | ||
667 | mt9t031->y_skip_top + vblank; | ||
668 | |||
669 | if (set_shutter(client, total_h) < 0) | ||
670 | return -EIO; | ||
671 | qctrl = &mt9t031_controls[MT9T031_CTRL_EXPOSURE]; | ||
672 | mt9t031->exposure = (shutter_max / 2 + (total_h - 1) * | ||
673 | (qctrl->maximum - qctrl->minimum)) / | ||
674 | shutter_max + qctrl->minimum; | ||
675 | mt9t031->autoexposure = 1; | ||
676 | } else | ||
677 | mt9t031->autoexposure = 0; | ||
678 | break; | ||
679 | default: | ||
680 | return -EINVAL; | ||
681 | } | ||
682 | return 0; | ||
683 | } | ||
684 | |||
685 | /* | ||
686 | * Power Management: | ||
687 | * This function does nothing for now but must be present for pm to work | ||
688 | */ | ||
689 | static int mt9t031_runtime_suspend(struct device *dev) | ||
690 | { | ||
691 | return 0; | ||
692 | } | ||
693 | |||
694 | /* | ||
695 | * Power Management: | ||
696 | * COLUMN_ADDRESS_MODE and ROW_ADDRESS_MODE are not rewritten if unchanged | ||
697 | * they are however changed at reset if the platform hook is present | ||
698 | * thus we rewrite them with the values stored by the driver | ||
699 | */ | ||
700 | static int mt9t031_runtime_resume(struct device *dev) | ||
701 | { | ||
702 | struct video_device *vdev = to_video_device(dev); | ||
703 | struct soc_camera_device *icd = dev_get_drvdata(vdev->parent); | ||
704 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
705 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
706 | struct mt9t031 *mt9t031 = to_mt9t031(client); | ||
707 | |||
708 | int ret; | ||
709 | u16 xbin, ybin; | ||
710 | |||
711 | xbin = min(mt9t031->xskip, (u16)3); | ||
712 | ybin = min(mt9t031->yskip, (u16)3); | ||
713 | |||
714 | ret = reg_write(client, MT9T031_COLUMN_ADDRESS_MODE, | ||
715 | ((xbin - 1) << 4) | (mt9t031->xskip - 1)); | ||
716 | if (ret < 0) | ||
717 | return ret; | ||
718 | |||
719 | ret = reg_write(client, MT9T031_ROW_ADDRESS_MODE, | ||
720 | ((ybin - 1) << 4) | (mt9t031->yskip - 1)); | ||
721 | if (ret < 0) | ||
722 | return ret; | ||
723 | |||
724 | return 0; | ||
725 | } | ||
726 | |||
727 | static struct dev_pm_ops mt9t031_dev_pm_ops = { | ||
728 | .runtime_suspend = mt9t031_runtime_suspend, | ||
729 | .runtime_resume = mt9t031_runtime_resume, | ||
730 | }; | ||
731 | |||
732 | static struct device_type mt9t031_dev_type = { | ||
733 | .name = "MT9T031", | ||
734 | .pm = &mt9t031_dev_pm_ops, | ||
735 | }; | ||
736 | |||
737 | /* | ||
738 | * Interface active, can use i2c. If it fails, it can indeed mean, that | ||
739 | * this wasn't our capture interface, so, we wait for the right one | ||
740 | */ | ||
741 | static int mt9t031_video_probe(struct i2c_client *client) | ||
742 | { | ||
743 | struct mt9t031 *mt9t031 = to_mt9t031(client); | ||
744 | struct video_device *vdev = soc_camera_i2c_to_vdev(client); | ||
745 | s32 data; | ||
746 | int ret; | ||
747 | |||
748 | /* Enable the chip */ | ||
749 | data = reg_write(client, MT9T031_CHIP_ENABLE, 1); | ||
750 | dev_dbg(&client->dev, "write: %d\n", data); | ||
751 | |||
752 | /* Read out the chip version register */ | ||
753 | data = reg_read(client, MT9T031_CHIP_VERSION); | ||
754 | |||
755 | switch (data) { | ||
756 | case 0x1621: | ||
757 | mt9t031->model = V4L2_IDENT_MT9T031; | ||
758 | break; | ||
759 | default: | ||
760 | dev_err(&client->dev, | ||
761 | "No MT9T031 chip detected, register read %x\n", data); | ||
762 | return -ENODEV; | ||
763 | } | ||
764 | |||
765 | dev_info(&client->dev, "Detected a MT9T031 chip ID %x\n", data); | ||
766 | |||
767 | ret = mt9t031_idle(client); | ||
768 | if (ret < 0) | ||
769 | dev_err(&client->dev, "Failed to initialise the camera\n"); | ||
770 | else | ||
771 | vdev->dev.type = &mt9t031_dev_type; | ||
772 | |||
773 | /* mt9t031_idle() has reset the chip to default. */ | ||
774 | mt9t031->exposure = 255; | ||
775 | mt9t031->gain = 64; | ||
776 | |||
777 | return ret; | ||
778 | } | ||
779 | |||
780 | static int mt9t031_g_skip_top_lines(struct v4l2_subdev *sd, u32 *lines) | ||
781 | { | ||
782 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
783 | struct mt9t031 *mt9t031 = to_mt9t031(client); | ||
784 | |||
785 | *lines = mt9t031->y_skip_top; | ||
786 | |||
787 | return 0; | ||
788 | } | ||
789 | |||
790 | static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = { | ||
791 | .g_ctrl = mt9t031_g_ctrl, | ||
792 | .s_ctrl = mt9t031_s_ctrl, | ||
793 | .g_chip_ident = mt9t031_g_chip_ident, | ||
794 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
795 | .g_register = mt9t031_g_register, | ||
796 | .s_register = mt9t031_s_register, | ||
797 | #endif | ||
798 | }; | ||
799 | |||
800 | static int mt9t031_enum_fmt(struct v4l2_subdev *sd, unsigned int index, | ||
801 | enum v4l2_mbus_pixelcode *code) | ||
802 | { | ||
803 | if (index) | ||
804 | return -EINVAL; | ||
805 | |||
806 | *code = V4L2_MBUS_FMT_SBGGR10_1X10; | ||
807 | return 0; | ||
808 | } | ||
809 | |||
810 | static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = { | ||
811 | .s_stream = mt9t031_s_stream, | ||
812 | .s_mbus_fmt = mt9t031_s_fmt, | ||
813 | .g_mbus_fmt = mt9t031_g_fmt, | ||
814 | .try_mbus_fmt = mt9t031_try_fmt, | ||
815 | .s_crop = mt9t031_s_crop, | ||
816 | .g_crop = mt9t031_g_crop, | ||
817 | .cropcap = mt9t031_cropcap, | ||
818 | .enum_mbus_fmt = mt9t031_enum_fmt, | ||
819 | }; | ||
820 | |||
821 | static struct v4l2_subdev_sensor_ops mt9t031_subdev_sensor_ops = { | ||
822 | .g_skip_top_lines = mt9t031_g_skip_top_lines, | ||
823 | }; | ||
824 | |||
825 | static struct v4l2_subdev_ops mt9t031_subdev_ops = { | ||
826 | .core = &mt9t031_subdev_core_ops, | ||
827 | .video = &mt9t031_subdev_video_ops, | ||
828 | .sensor = &mt9t031_subdev_sensor_ops, | ||
829 | }; | ||
830 | |||
831 | static int mt9t031_probe(struct i2c_client *client, | ||
832 | const struct i2c_device_id *did) | ||
833 | { | ||
834 | struct mt9t031 *mt9t031; | ||
835 | struct soc_camera_device *icd = client->dev.platform_data; | ||
836 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | ||
837 | int ret; | ||
838 | |||
839 | if (icd) { | ||
840 | struct soc_camera_link *icl = to_soc_camera_link(icd); | ||
841 | if (!icl) { | ||
842 | dev_err(&client->dev, "MT9T031 driver needs platform data\n"); | ||
843 | return -EINVAL; | ||
844 | } | ||
845 | |||
846 | icd->ops = &mt9t031_ops; | ||
847 | } | ||
848 | |||
849 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { | ||
850 | dev_warn(&adapter->dev, | ||
851 | "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); | ||
852 | return -EIO; | ||
853 | } | ||
854 | |||
855 | mt9t031 = kzalloc(sizeof(struct mt9t031), GFP_KERNEL); | ||
856 | if (!mt9t031) | ||
857 | return -ENOMEM; | ||
858 | |||
859 | v4l2_i2c_subdev_init(&mt9t031->subdev, client, &mt9t031_subdev_ops); | ||
860 | |||
861 | mt9t031->y_skip_top = 0; | ||
862 | mt9t031->rect.left = MT9T031_COLUMN_SKIP; | ||
863 | mt9t031->rect.top = MT9T031_ROW_SKIP; | ||
864 | mt9t031->rect.width = MT9T031_MAX_WIDTH; | ||
865 | mt9t031->rect.height = MT9T031_MAX_HEIGHT; | ||
866 | |||
867 | /* | ||
868 | * Simulated autoexposure. If enabled, we calculate shutter width | ||
869 | * ourselves in the driver based on vertical blanking and frame width | ||
870 | */ | ||
871 | mt9t031->autoexposure = 1; | ||
872 | |||
873 | mt9t031->xskip = 1; | ||
874 | mt9t031->yskip = 1; | ||
875 | |||
876 | mt9t031_idle(client); | ||
877 | |||
878 | ret = mt9t031_video_probe(client); | ||
879 | |||
880 | mt9t031_disable(client); | ||
881 | |||
882 | if (ret) { | ||
883 | if (icd) | ||
884 | icd->ops = NULL; | ||
885 | kfree(mt9t031); | ||
886 | } | ||
887 | |||
888 | return ret; | ||
889 | } | ||
890 | |||
891 | static int mt9t031_remove(struct i2c_client *client) | ||
892 | { | ||
893 | struct mt9t031 *mt9t031 = to_mt9t031(client); | ||
894 | struct soc_camera_device *icd = client->dev.platform_data; | ||
895 | |||
896 | if (icd) | ||
897 | icd->ops = NULL; | ||
898 | kfree(mt9t031); | ||
899 | |||
900 | return 0; | ||
901 | } | ||
902 | |||
903 | static const struct i2c_device_id mt9t031_id[] = { | ||
904 | { "mt9t031", 0 }, | ||
905 | { } | ||
906 | }; | ||
907 | MODULE_DEVICE_TABLE(i2c, mt9t031_id); | ||
908 | |||
909 | static struct i2c_driver mt9t031_i2c_driver = { | ||
910 | .driver = { | ||
911 | .name = "mt9t031", | ||
912 | }, | ||
913 | .probe = mt9t031_probe, | ||
914 | .remove = mt9t031_remove, | ||
915 | .id_table = mt9t031_id, | ||
916 | }; | ||
917 | |||
918 | static int __init mt9t031_mod_init(void) | ||
919 | { | ||
920 | return i2c_add_driver(&mt9t031_i2c_driver); | ||
921 | } | ||
922 | |||
923 | static void __exit mt9t031_mod_exit(void) | ||
924 | { | ||
925 | i2c_del_driver(&mt9t031_i2c_driver); | ||
926 | } | ||
927 | |||
928 | module_init(mt9t031_mod_init); | ||
929 | module_exit(mt9t031_mod_exit); | ||
930 | |||
931 | MODULE_DESCRIPTION("Micron MT9T031 Camera driver"); | ||
932 | MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>"); | ||
933 | MODULE_LICENSE("GPL v2"); | ||