Commit | Line | Data |
---|---|---|
f523dd0d GL |
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> | |
7a707b89 | 15 | #include <linux/module.h> |
f523dd0d | 16 | |
32ca2085 GL |
17 | #include <media/soc_camera.h> |
18 | #include <media/soc_mediabus.h> | |
979ea1dd | 19 | #include <media/v4l2-subdev.h> |
f523dd0d | 20 | #include <media/v4l2-chip-ident.h> |
2dd7d29c | 21 | #include <media/v4l2-ctrls.h> |
f523dd0d | 22 | |
5d28d525 GL |
23 | /* |
24 | * mt9m001 i2c address 0x5d | |
979ea1dd | 25 | * The platform has to define ctruct i2c_board_info objects and link to them |
5d28d525 GL |
26 | * from struct soc_camera_link |
27 | */ | |
f523dd0d GL |
28 | |
29 | /* mt9m001 selected register addresses */ | |
30 | #define MT9M001_CHIP_VERSION 0x00 | |
31 | #define MT9M001_ROW_START 0x01 | |
32 | #define MT9M001_COLUMN_START 0x02 | |
33 | #define MT9M001_WINDOW_HEIGHT 0x03 | |
34 | #define MT9M001_WINDOW_WIDTH 0x04 | |
35 | #define MT9M001_HORIZONTAL_BLANKING 0x05 | |
36 | #define MT9M001_VERTICAL_BLANKING 0x06 | |
37 | #define MT9M001_OUTPUT_CONTROL 0x07 | |
38 | #define MT9M001_SHUTTER_WIDTH 0x09 | |
39 | #define MT9M001_FRAME_RESTART 0x0b | |
40 | #define MT9M001_SHUTTER_DELAY 0x0c | |
41 | #define MT9M001_RESET 0x0d | |
42 | #define MT9M001_READ_OPTIONS1 0x1e | |
43 | #define MT9M001_READ_OPTIONS2 0x20 | |
44 | #define MT9M001_GLOBAL_GAIN 0x35 | |
45 | #define MT9M001_CHIP_ENABLE 0xF1 | |
46 | ||
6a6c8786 GL |
47 | #define MT9M001_MAX_WIDTH 1280 |
48 | #define MT9M001_MAX_HEIGHT 1024 | |
49 | #define MT9M001_MIN_WIDTH 48 | |
50 | #define MT9M001_MIN_HEIGHT 32 | |
51 | #define MT9M001_COLUMN_SKIP 20 | |
52 | #define MT9M001_ROW_SKIP 12 | |
53 | ||
760697be GL |
54 | /* MT9M001 has only one fixed colorspace per pixelcode */ |
55 | struct mt9m001_datafmt { | |
56 | enum v4l2_mbus_pixelcode code; | |
57 | enum v4l2_colorspace colorspace; | |
58 | }; | |
59 | ||
60 | /* Find a data format by a pixel code in an array */ | |
61 | static const struct mt9m001_datafmt *mt9m001_find_datafmt( | |
62 | enum v4l2_mbus_pixelcode code, const struct mt9m001_datafmt *fmt, | |
63 | int n) | |
64 | { | |
65 | int i; | |
66 | for (i = 0; i < n; i++) | |
67 | if (fmt[i].code == code) | |
68 | return fmt + i; | |
69 | ||
70 | return NULL; | |
71 | } | |
72 | ||
73 | static const struct mt9m001_datafmt mt9m001_colour_fmts[] = { | |
5d28d525 GL |
74 | /* |
75 | * Order important: first natively supported, | |
76 | * second supported with a GPIO extender | |
77 | */ | |
760697be GL |
78 | {V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB}, |
79 | {V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB}, | |
f523dd0d GL |
80 | }; |
81 | ||
760697be | 82 | static const struct mt9m001_datafmt mt9m001_monochrome_fmts[] = { |
bb55de3b | 83 | /* Order important - see above */ |
760697be | 84 | {V4L2_MBUS_FMT_Y10_1X10, V4L2_COLORSPACE_JPEG}, |
07670433 | 85 | {V4L2_MBUS_FMT_Y8_1X8, V4L2_COLORSPACE_JPEG}, |
f523dd0d GL |
86 | }; |
87 | ||
88 | struct mt9m001 { | |
979ea1dd | 89 | struct v4l2_subdev subdev; |
2dd7d29c HV |
90 | struct v4l2_ctrl_handler hdl; |
91 | struct { | |
92 | /* exposure/auto-exposure cluster */ | |
93 | struct v4l2_ctrl *autoexposure; | |
94 | struct v4l2_ctrl *exposure; | |
95 | }; | |
6a6c8786 | 96 | struct v4l2_rect rect; /* Sensor window */ |
760697be GL |
97 | const struct mt9m001_datafmt *fmt; |
98 | const struct mt9m001_datafmt *fmts; | |
99 | int num_fmts; | |
f523dd0d | 100 | int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ |
2dd7d29c | 101 | unsigned int total_h; |
32536108 | 102 | unsigned short y_skip_top; /* Lines to skip at the top */ |
f523dd0d GL |
103 | }; |
104 | ||
979ea1dd GL |
105 | static struct mt9m001 *to_mt9m001(const struct i2c_client *client) |
106 | { | |
107 | return container_of(i2c_get_clientdata(client), struct mt9m001, subdev); | |
108 | } | |
109 | ||
9538e1c2 | 110 | static int reg_read(struct i2c_client *client, const u8 reg) |
f523dd0d | 111 | { |
3f877045 | 112 | return i2c_smbus_read_word_swapped(client, reg); |
f523dd0d GL |
113 | } |
114 | ||
9538e1c2 | 115 | static int reg_write(struct i2c_client *client, const u8 reg, |
f523dd0d GL |
116 | const u16 data) |
117 | { | |
3f877045 | 118 | return i2c_smbus_write_word_swapped(client, reg, data); |
f523dd0d GL |
119 | } |
120 | ||
9538e1c2 | 121 | static int reg_set(struct i2c_client *client, const u8 reg, |
f523dd0d GL |
122 | const u16 data) |
123 | { | |
124 | int ret; | |
125 | ||
9538e1c2 | 126 | ret = reg_read(client, reg); |
f523dd0d GL |
127 | if (ret < 0) |
128 | return ret; | |
9538e1c2 | 129 | return reg_write(client, reg, ret | data); |
f523dd0d GL |
130 | } |
131 | ||
9538e1c2 | 132 | static int reg_clear(struct i2c_client *client, const u8 reg, |
f523dd0d GL |
133 | const u16 data) |
134 | { | |
135 | int ret; | |
136 | ||
9538e1c2 | 137 | ret = reg_read(client, reg); |
f523dd0d GL |
138 | if (ret < 0) |
139 | return ret; | |
9538e1c2 | 140 | return reg_write(client, reg, ret & ~data); |
f523dd0d GL |
141 | } |
142 | ||
a4c56fd8 | 143 | static int mt9m001_init(struct i2c_client *client) |
f523dd0d GL |
144 | { |
145 | int ret; | |
146 | ||
85f8be68 | 147 | dev_dbg(&client->dev, "%s\n", __func__); |
f523dd0d | 148 | |
979ea1dd | 149 | /* |
96c75399 GL |
150 | * We don't know, whether platform provides reset, issue a soft reset |
151 | * too. This returns all registers to their default values. | |
979ea1dd GL |
152 | */ |
153 | ret = reg_write(client, MT9M001_RESET, 1); | |
154 | if (!ret) | |
155 | ret = reg_write(client, MT9M001_RESET, 0); | |
81034663 | 156 | |
11211641 GL |
157 | /* Disable chip, synchronous option update */ |
158 | if (!ret) | |
9538e1c2 | 159 | ret = reg_write(client, MT9M001_OUTPUT_CONTROL, 0); |
f523dd0d | 160 | |
11211641 | 161 | return ret; |
f523dd0d GL |
162 | } |
163 | ||
979ea1dd | 164 | static int mt9m001_s_stream(struct v4l2_subdev *sd, int enable) |
f523dd0d | 165 | { |
c4ce6d14 | 166 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
9538e1c2 | 167 | |
979ea1dd GL |
168 | /* Switch to master "normal" mode or stop sensor readout */ |
169 | if (reg_write(client, MT9M001_OUTPUT_CONTROL, enable ? 2 : 0) < 0) | |
f523dd0d GL |
170 | return -EIO; |
171 | return 0; | |
172 | } | |
173 | ||
08590b96 | 174 | static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) |
ad5f2e85 | 175 | { |
c4ce6d14 | 176 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
979ea1dd | 177 | struct mt9m001 *mt9m001 = to_mt9m001(client); |
6a6c8786 | 178 | struct v4l2_rect rect = a->c; |
ad5f2e85 GL |
179 | int ret; |
180 | const u16 hblank = 9, vblank = 25; | |
181 | ||
760697be | 182 | if (mt9m001->fmts == mt9m001_colour_fmts) |
6a6c8786 GL |
183 | /* |
184 | * Bayer format - even number of rows for simplicity, | |
185 | * but let the user play with the top row. | |
186 | */ | |
187 | rect.height = ALIGN(rect.height, 2); | |
188 | ||
189 | /* Datasheet requirement: see register description */ | |
190 | rect.width = ALIGN(rect.width, 2); | |
191 | rect.left = ALIGN(rect.left, 2); | |
192 | ||
193 | soc_camera_limit_side(&rect.left, &rect.width, | |
194 | MT9M001_COLUMN_SKIP, MT9M001_MIN_WIDTH, MT9M001_MAX_WIDTH); | |
195 | ||
196 | soc_camera_limit_side(&rect.top, &rect.height, | |
197 | MT9M001_ROW_SKIP, MT9M001_MIN_HEIGHT, MT9M001_MAX_HEIGHT); | |
198 | ||
2dd7d29c | 199 | mt9m001->total_h = rect.height + mt9m001->y_skip_top + vblank; |
96c75399 | 200 | |
f523dd0d | 201 | /* Blanking and start values - default... */ |
9538e1c2 | 202 | ret = reg_write(client, MT9M001_HORIZONTAL_BLANKING, hblank); |
11211641 | 203 | if (!ret) |
9538e1c2 | 204 | ret = reg_write(client, MT9M001_VERTICAL_BLANKING, vblank); |
f523dd0d | 205 | |
5d28d525 GL |
206 | /* |
207 | * The caller provides a supported format, as verified per | |
14178aa5 | 208 | * call to .try_mbus_fmt() |
5d28d525 | 209 | */ |
11211641 | 210 | if (!ret) |
6a6c8786 | 211 | ret = reg_write(client, MT9M001_COLUMN_START, rect.left); |
11211641 | 212 | if (!ret) |
6a6c8786 | 213 | ret = reg_write(client, MT9M001_ROW_START, rect.top); |
11211641 | 214 | if (!ret) |
6a6c8786 | 215 | ret = reg_write(client, MT9M001_WINDOW_WIDTH, rect.width - 1); |
11211641 | 216 | if (!ret) |
9538e1c2 | 217 | ret = reg_write(client, MT9M001_WINDOW_HEIGHT, |
32536108 | 218 | rect.height + mt9m001->y_skip_top - 1); |
2dd7d29c HV |
219 | if (!ret && v4l2_ctrl_g_ctrl(mt9m001->autoexposure) == V4L2_EXPOSURE_AUTO) |
220 | ret = reg_write(client, MT9M001_SHUTTER_WIDTH, mt9m001->total_h); | |
f523dd0d | 221 | |
6a6c8786 GL |
222 | if (!ret) |
223 | mt9m001->rect = rect; | |
224 | ||
11211641 | 225 | return ret; |
f523dd0d GL |
226 | } |
227 | ||
6a6c8786 GL |
228 | static int mt9m001_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) |
229 | { | |
c4ce6d14 | 230 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
6a6c8786 GL |
231 | struct mt9m001 *mt9m001 = to_mt9m001(client); |
232 | ||
233 | a->c = mt9m001->rect; | |
234 | a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
235 | ||
236 | return 0; | |
237 | } | |
238 | ||
239 | static int mt9m001_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) | |
240 | { | |
241 | a->bounds.left = MT9M001_COLUMN_SKIP; | |
242 | a->bounds.top = MT9M001_ROW_SKIP; | |
243 | a->bounds.width = MT9M001_MAX_WIDTH; | |
244 | a->bounds.height = MT9M001_MAX_HEIGHT; | |
245 | a->defrect = a->bounds; | |
246 | a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
247 | a->pixelaspect.numerator = 1; | |
248 | a->pixelaspect.denominator = 1; | |
249 | ||
250 | return 0; | |
251 | } | |
252 | ||
760697be GL |
253 | static int mt9m001_g_fmt(struct v4l2_subdev *sd, |
254 | struct v4l2_mbus_framefmt *mf) | |
6a6c8786 | 255 | { |
c4ce6d14 | 256 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
6a6c8786 | 257 | struct mt9m001 *mt9m001 = to_mt9m001(client); |
6a6c8786 | 258 | |
760697be GL |
259 | mf->width = mt9m001->rect.width; |
260 | mf->height = mt9m001->rect.height; | |
261 | mf->code = mt9m001->fmt->code; | |
262 | mf->colorspace = mt9m001->fmt->colorspace; | |
263 | mf->field = V4L2_FIELD_NONE; | |
6a6c8786 GL |
264 | |
265 | return 0; | |
266 | } | |
267 | ||
760697be GL |
268 | static int mt9m001_s_fmt(struct v4l2_subdev *sd, |
269 | struct v4l2_mbus_framefmt *mf) | |
09e231b3 | 270 | { |
c4ce6d14 | 271 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
6a6c8786 | 272 | struct mt9m001 *mt9m001 = to_mt9m001(client); |
08590b96 GL |
273 | struct v4l2_crop a = { |
274 | .c = { | |
6a6c8786 GL |
275 | .left = mt9m001->rect.left, |
276 | .top = mt9m001->rect.top, | |
760697be GL |
277 | .width = mf->width, |
278 | .height = mf->height, | |
08590b96 | 279 | }, |
09e231b3 | 280 | }; |
6a6c8786 | 281 | int ret; |
09e231b3 GL |
282 | |
283 | /* No support for scaling so far, just crop. TODO: use skipping */ | |
6a6c8786 GL |
284 | ret = mt9m001_s_crop(sd, &a); |
285 | if (!ret) { | |
760697be GL |
286 | mf->width = mt9m001->rect.width; |
287 | mf->height = mt9m001->rect.height; | |
288 | mt9m001->fmt = mt9m001_find_datafmt(mf->code, | |
289 | mt9m001->fmts, mt9m001->num_fmts); | |
290 | mf->colorspace = mt9m001->fmt->colorspace; | |
6a6c8786 GL |
291 | } |
292 | ||
293 | return ret; | |
09e231b3 GL |
294 | } |
295 | ||
760697be GL |
296 | static int mt9m001_try_fmt(struct v4l2_subdev *sd, |
297 | struct v4l2_mbus_framefmt *mf) | |
f523dd0d | 298 | { |
c4ce6d14 | 299 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
32536108 | 300 | struct mt9m001 *mt9m001 = to_mt9m001(client); |
760697be | 301 | const struct mt9m001_datafmt *fmt; |
64f5905e | 302 | |
760697be | 303 | v4l_bound_align_image(&mf->width, MT9M001_MIN_WIDTH, |
6a6c8786 | 304 | MT9M001_MAX_WIDTH, 1, |
760697be | 305 | &mf->height, MT9M001_MIN_HEIGHT + mt9m001->y_skip_top, |
32536108 | 306 | MT9M001_MAX_HEIGHT + mt9m001->y_skip_top, 0, 0); |
6a6c8786 | 307 | |
760697be GL |
308 | if (mt9m001->fmts == mt9m001_colour_fmts) |
309 | mf->height = ALIGN(mf->height - 1, 2); | |
310 | ||
311 | fmt = mt9m001_find_datafmt(mf->code, mt9m001->fmts, | |
312 | mt9m001->num_fmts); | |
313 | if (!fmt) { | |
314 | fmt = mt9m001->fmt; | |
315 | mf->code = fmt->code; | |
316 | } | |
317 | ||
318 | mf->colorspace = fmt->colorspace; | |
f523dd0d GL |
319 | |
320 | return 0; | |
321 | } | |
322 | ||
979ea1dd GL |
323 | static int mt9m001_g_chip_ident(struct v4l2_subdev *sd, |
324 | struct v4l2_dbg_chip_ident *id) | |
f523dd0d | 325 | { |
c4ce6d14 | 326 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
979ea1dd | 327 | struct mt9m001 *mt9m001 = to_mt9m001(client); |
f523dd0d | 328 | |
aecde8b5 | 329 | if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) |
f523dd0d GL |
330 | return -EINVAL; |
331 | ||
40e2e092 | 332 | if (id->match.addr != client->addr) |
f523dd0d GL |
333 | return -ENODEV; |
334 | ||
335 | id->ident = mt9m001->model; | |
336 | id->revision = 0; | |
337 | ||
338 | return 0; | |
339 | } | |
340 | ||
341 | #ifdef CONFIG_VIDEO_ADV_DEBUG | |
979ea1dd GL |
342 | static int mt9m001_g_register(struct v4l2_subdev *sd, |
343 | struct v4l2_dbg_register *reg) | |
f523dd0d | 344 | { |
c4ce6d14 | 345 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
f523dd0d | 346 | |
aecde8b5 | 347 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) |
f523dd0d GL |
348 | return -EINVAL; |
349 | ||
9538e1c2 | 350 | if (reg->match.addr != client->addr) |
f523dd0d GL |
351 | return -ENODEV; |
352 | ||
aecde8b5 | 353 | reg->size = 2; |
9538e1c2 | 354 | reg->val = reg_read(client, reg->reg); |
f523dd0d GL |
355 | |
356 | if (reg->val > 0xffff) | |
357 | return -EIO; | |
358 | ||
359 | return 0; | |
360 | } | |
361 | ||
979ea1dd GL |
362 | static int mt9m001_s_register(struct v4l2_subdev *sd, |
363 | struct v4l2_dbg_register *reg) | |
f523dd0d | 364 | { |
c4ce6d14 | 365 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
f523dd0d | 366 | |
aecde8b5 | 367 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) |
f523dd0d GL |
368 | return -EINVAL; |
369 | ||
9538e1c2 | 370 | if (reg->match.addr != client->addr) |
f523dd0d GL |
371 | return -ENODEV; |
372 | ||
9538e1c2 | 373 | if (reg_write(client, reg->reg, reg->val) < 0) |
f523dd0d GL |
374 | return -EIO; |
375 | ||
376 | return 0; | |
377 | } | |
378 | #endif | |
379 | ||
2dd7d29c | 380 | static int mt9m001_g_volatile_ctrl(struct v4l2_ctrl *ctrl) |
f523dd0d | 381 | { |
2dd7d29c HV |
382 | struct mt9m001 *mt9m001 = container_of(ctrl->handler, |
383 | struct mt9m001, hdl); | |
384 | s32 min, max; | |
f523dd0d GL |
385 | |
386 | switch (ctrl->id) { | |
f523dd0d | 387 | case V4L2_CID_EXPOSURE_AUTO: |
2dd7d29c HV |
388 | min = mt9m001->exposure->minimum; |
389 | max = mt9m001->exposure->maximum; | |
390 | mt9m001->exposure->val = | |
391 | (524 + (mt9m001->total_h - 1) * (max - min)) / 1048 + min; | |
96c75399 | 392 | break; |
f523dd0d GL |
393 | } |
394 | return 0; | |
395 | } | |
396 | ||
2dd7d29c | 397 | static int mt9m001_s_ctrl(struct v4l2_ctrl *ctrl) |
f523dd0d | 398 | { |
2dd7d29c HV |
399 | struct mt9m001 *mt9m001 = container_of(ctrl->handler, |
400 | struct mt9m001, hdl); | |
401 | struct v4l2_subdev *sd = &mt9m001->subdev; | |
c4ce6d14 | 402 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
2dd7d29c | 403 | struct v4l2_ctrl *exp = mt9m001->exposure; |
f523dd0d GL |
404 | int data; |
405 | ||
f523dd0d GL |
406 | switch (ctrl->id) { |
407 | case V4L2_CID_VFLIP: | |
2dd7d29c | 408 | if (ctrl->val) |
9538e1c2 | 409 | data = reg_set(client, MT9M001_READ_OPTIONS2, 0x8000); |
f523dd0d | 410 | else |
9538e1c2 | 411 | data = reg_clear(client, MT9M001_READ_OPTIONS2, 0x8000); |
f523dd0d GL |
412 | if (data < 0) |
413 | return -EIO; | |
2dd7d29c HV |
414 | return 0; |
415 | ||
f523dd0d | 416 | case V4L2_CID_GAIN: |
f523dd0d | 417 | /* See Datasheet Table 7, Gain settings. */ |
2dd7d29c | 418 | if (ctrl->val <= ctrl->default_value) { |
f523dd0d | 419 | /* Pack it into 0..1 step 0.125, register values 0..8 */ |
2dd7d29c HV |
420 | unsigned long range = ctrl->default_value - ctrl->minimum; |
421 | data = ((ctrl->val - ctrl->minimum) * 8 + range / 2) / range; | |
f523dd0d | 422 | |
85f8be68 | 423 | dev_dbg(&client->dev, "Setting gain %d\n", data); |
9538e1c2 | 424 | data = reg_write(client, MT9M001_GLOBAL_GAIN, data); |
f523dd0d GL |
425 | if (data < 0) |
426 | return -EIO; | |
427 | } else { | |
428 | /* Pack it into 1.125..15 variable step, register values 9..67 */ | |
429 | /* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */ | |
2dd7d29c HV |
430 | unsigned long range = ctrl->maximum - ctrl->default_value - 1; |
431 | unsigned long gain = ((ctrl->val - ctrl->default_value - 1) * | |
f523dd0d GL |
432 | 111 + range / 2) / range + 9; |
433 | ||
434 | if (gain <= 32) | |
435 | data = gain; | |
436 | else if (gain <= 64) | |
437 | data = ((gain - 32) * 16 + 16) / 32 + 80; | |
438 | else | |
439 | data = ((gain - 64) * 7 + 28) / 56 + 96; | |
440 | ||
85f8be68 | 441 | dev_dbg(&client->dev, "Setting gain from %d to %d\n", |
9538e1c2 GL |
442 | reg_read(client, MT9M001_GLOBAL_GAIN), data); |
443 | data = reg_write(client, MT9M001_GLOBAL_GAIN, data); | |
f523dd0d GL |
444 | if (data < 0) |
445 | return -EIO; | |
446 | } | |
2dd7d29c | 447 | return 0; |
f523dd0d | 448 | |
2dd7d29c HV |
449 | case V4L2_CID_EXPOSURE_AUTO: |
450 | if (ctrl->val == V4L2_EXPOSURE_MANUAL) { | |
451 | unsigned long range = exp->maximum - exp->minimum; | |
452 | unsigned long shutter = ((exp->val - exp->minimum) * 1048 + | |
f523dd0d GL |
453 | range / 2) / range + 1; |
454 | ||
85f8be68 GL |
455 | dev_dbg(&client->dev, |
456 | "Setting shutter width from %d to %lu\n", | |
2dd7d29c | 457 | reg_read(client, MT9M001_SHUTTER_WIDTH), shutter); |
9538e1c2 | 458 | if (reg_write(client, MT9M001_SHUTTER_WIDTH, shutter) < 0) |
f523dd0d | 459 | return -EIO; |
2dd7d29c | 460 | } else { |
f523dd0d | 461 | const u16 vblank = 25; |
2dd7d29c HV |
462 | |
463 | mt9m001->total_h = mt9m001->rect.height + | |
32536108 | 464 | mt9m001->y_skip_top + vblank; |
2dd7d29c | 465 | if (reg_write(client, MT9M001_SHUTTER_WIDTH, mt9m001->total_h) < 0) |
f523dd0d | 466 | return -EIO; |
2dd7d29c HV |
467 | } |
468 | return 0; | |
f523dd0d | 469 | } |
2dd7d29c | 470 | return -EINVAL; |
f523dd0d GL |
471 | } |
472 | ||
5d28d525 GL |
473 | /* |
474 | * Interface active, can use i2c. If it fails, it can indeed mean, that | |
475 | * this wasn't our capture interface, so, we wait for the right one | |
476 | */ | |
14178aa5 | 477 | static int mt9m001_video_probe(struct soc_camera_link *icl, |
40e2e092 | 478 | struct i2c_client *client) |
f523dd0d | 479 | { |
979ea1dd | 480 | struct mt9m001 *mt9m001 = to_mt9m001(client); |
f523dd0d | 481 | s32 data; |
36034dc3 | 482 | unsigned long flags; |
a4c56fd8 | 483 | int ret; |
f523dd0d | 484 | |
f523dd0d | 485 | /* Enable the chip */ |
9538e1c2 | 486 | data = reg_write(client, MT9M001_CHIP_ENABLE, 1); |
85f8be68 | 487 | dev_dbg(&client->dev, "write: %d\n", data); |
f523dd0d GL |
488 | |
489 | /* Read out the chip version register */ | |
9538e1c2 | 490 | data = reg_read(client, MT9M001_CHIP_VERSION); |
f523dd0d GL |
491 | |
492 | /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */ | |
493 | switch (data) { | |
494 | case 0x8411: | |
495 | case 0x8421: | |
496 | mt9m001->model = V4L2_IDENT_MT9M001C12ST; | |
760697be | 497 | mt9m001->fmts = mt9m001_colour_fmts; |
f523dd0d GL |
498 | break; |
499 | case 0x8431: | |
500 | mt9m001->model = V4L2_IDENT_MT9M001C12STM; | |
760697be | 501 | mt9m001->fmts = mt9m001_monochrome_fmts; |
f523dd0d GL |
502 | break; |
503 | default: | |
85f8be68 | 504 | dev_err(&client->dev, |
f523dd0d | 505 | "No MT9M001 chip detected, register read %x\n", data); |
40e2e092 | 506 | return -ENODEV; |
f523dd0d GL |
507 | } |
508 | ||
760697be | 509 | mt9m001->num_fmts = 0; |
36034dc3 SH |
510 | |
511 | /* | |
512 | * This is a 10bit sensor, so by default we only allow 10bit. | |
513 | * The platform may support different bus widths due to | |
514 | * different routing of the data lines. | |
515 | */ | |
516 | if (icl->query_bus_param) | |
517 | flags = icl->query_bus_param(icl); | |
518 | else | |
519 | flags = SOCAM_DATAWIDTH_10; | |
520 | ||
521 | if (flags & SOCAM_DATAWIDTH_10) | |
760697be | 522 | mt9m001->num_fmts++; |
36034dc3 | 523 | else |
760697be | 524 | mt9m001->fmts++; |
36034dc3 SH |
525 | |
526 | if (flags & SOCAM_DATAWIDTH_8) | |
760697be | 527 | mt9m001->num_fmts++; |
36034dc3 | 528 | |
760697be | 529 | mt9m001->fmt = &mt9m001->fmts[0]; |
6a6c8786 | 530 | |
85f8be68 | 531 | dev_info(&client->dev, "Detected a MT9M001 chip ID %x (%s)\n", data, |
f523dd0d GL |
532 | data == 0x8431 ? "C12STM" : "C12ST"); |
533 | ||
a4c56fd8 GL |
534 | ret = mt9m001_init(client); |
535 | if (ret < 0) | |
536 | dev_err(&client->dev, "Failed to initialise the camera\n"); | |
537 | ||
96c75399 | 538 | /* mt9m001_init() has reset the chip, returning registers to defaults */ |
2dd7d29c | 539 | return v4l2_ctrl_handler_setup(&mt9m001->hdl); |
f523dd0d GL |
540 | } |
541 | ||
14178aa5 | 542 | static void mt9m001_video_remove(struct soc_camera_link *icl) |
f523dd0d | 543 | { |
594bb46d GL |
544 | if (icl->free_bus) |
545 | icl->free_bus(icl); | |
f523dd0d GL |
546 | } |
547 | ||
32536108 GL |
548 | static int mt9m001_g_skip_top_lines(struct v4l2_subdev *sd, u32 *lines) |
549 | { | |
c4ce6d14 | 550 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
32536108 GL |
551 | struct mt9m001 *mt9m001 = to_mt9m001(client); |
552 | ||
553 | *lines = mt9m001->y_skip_top; | |
554 | ||
555 | return 0; | |
556 | } | |
557 | ||
2dd7d29c HV |
558 | static const struct v4l2_ctrl_ops mt9m001_ctrl_ops = { |
559 | .g_volatile_ctrl = mt9m001_g_volatile_ctrl, | |
560 | .s_ctrl = mt9m001_s_ctrl, | |
561 | }; | |
562 | ||
979ea1dd | 563 | static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = { |
979ea1dd GL |
564 | .g_chip_ident = mt9m001_g_chip_ident, |
565 | #ifdef CONFIG_VIDEO_ADV_DEBUG | |
566 | .g_register = mt9m001_g_register, | |
567 | .s_register = mt9m001_s_register, | |
568 | #endif | |
569 | }; | |
570 | ||
3805f201 | 571 | static int mt9m001_enum_fmt(struct v4l2_subdev *sd, unsigned int index, |
760697be GL |
572 | enum v4l2_mbus_pixelcode *code) |
573 | { | |
c4ce6d14 | 574 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
760697be GL |
575 | struct mt9m001 *mt9m001 = to_mt9m001(client); |
576 | ||
3805f201 | 577 | if (index >= mt9m001->num_fmts) |
760697be GL |
578 | return -EINVAL; |
579 | ||
580 | *code = mt9m001->fmts[index].code; | |
581 | return 0; | |
582 | } | |
583 | ||
32ca2085 GL |
584 | static int mt9m001_g_mbus_config(struct v4l2_subdev *sd, |
585 | struct v4l2_mbus_config *cfg) | |
586 | { | |
587 | struct i2c_client *client = v4l2_get_subdevdata(sd); | |
14178aa5 | 588 | struct soc_camera_link *icl = soc_camera_i2c_to_link(client); |
32ca2085 GL |
589 | |
590 | /* MT9M001 has all capture_format parameters fixed */ | |
591 | cfg->flags = V4L2_MBUS_PCLK_SAMPLE_FALLING | | |
592 | V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH | | |
593 | V4L2_MBUS_DATA_ACTIVE_HIGH | V4L2_MBUS_MASTER; | |
594 | cfg->type = V4L2_MBUS_PARALLEL; | |
595 | cfg->flags = soc_camera_apply_board_flags(icl, cfg); | |
596 | ||
597 | return 0; | |
598 | } | |
599 | ||
600 | static int mt9m001_s_mbus_config(struct v4l2_subdev *sd, | |
601 | const struct v4l2_mbus_config *cfg) | |
602 | { | |
14178aa5 | 603 | const struct i2c_client *client = v4l2_get_subdevdata(sd); |
14178aa5 | 604 | struct soc_camera_link *icl = soc_camera_i2c_to_link(client); |
443f483a GL |
605 | struct mt9m001 *mt9m001 = to_mt9m001(client); |
606 | unsigned int bps = soc_mbus_get_fmtdesc(mt9m001->fmt->code)->bits_per_sample; | |
32ca2085 GL |
607 | |
608 | if (icl->set_bus_param) | |
609 | return icl->set_bus_param(icl, 1 << (bps - 1)); | |
610 | ||
611 | /* | |
612 | * Without board specific bus width settings we only support the | |
613 | * sensors native bus width | |
614 | */ | |
615 | return bps == 10 ? 0 : -EINVAL; | |
616 | } | |
617 | ||
979ea1dd GL |
618 | static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = { |
619 | .s_stream = mt9m001_s_stream, | |
760697be GL |
620 | .s_mbus_fmt = mt9m001_s_fmt, |
621 | .g_mbus_fmt = mt9m001_g_fmt, | |
622 | .try_mbus_fmt = mt9m001_try_fmt, | |
08590b96 | 623 | .s_crop = mt9m001_s_crop, |
6a6c8786 GL |
624 | .g_crop = mt9m001_g_crop, |
625 | .cropcap = mt9m001_cropcap, | |
760697be | 626 | .enum_mbus_fmt = mt9m001_enum_fmt, |
32ca2085 GL |
627 | .g_mbus_config = mt9m001_g_mbus_config, |
628 | .s_mbus_config = mt9m001_s_mbus_config, | |
979ea1dd GL |
629 | }; |
630 | ||
32536108 GL |
631 | static struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = { |
632 | .g_skip_top_lines = mt9m001_g_skip_top_lines, | |
633 | }; | |
634 | ||
979ea1dd GL |
635 | static struct v4l2_subdev_ops mt9m001_subdev_ops = { |
636 | .core = &mt9m001_subdev_core_ops, | |
637 | .video = &mt9m001_subdev_video_ops, | |
32536108 | 638 | .sensor = &mt9m001_subdev_sensor_ops, |
979ea1dd GL |
639 | }; |
640 | ||
d2653e92 JD |
641 | static int mt9m001_probe(struct i2c_client *client, |
642 | const struct i2c_device_id *did) | |
f523dd0d GL |
643 | { |
644 | struct mt9m001 *mt9m001; | |
f523dd0d | 645 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
14178aa5 | 646 | struct soc_camera_link *icl = soc_camera_i2c_to_link(client); |
f523dd0d GL |
647 | int ret; |
648 | ||
649 | if (!icl) { | |
650 | dev_err(&client->dev, "MT9M001 driver needs platform data\n"); | |
651 | return -EINVAL; | |
652 | } | |
653 | ||
654 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { | |
655 | dev_warn(&adapter->dev, | |
656 | "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); | |
657 | return -EIO; | |
658 | } | |
659 | ||
660 | mt9m001 = kzalloc(sizeof(struct mt9m001), GFP_KERNEL); | |
661 | if (!mt9m001) | |
662 | return -ENOMEM; | |
663 | ||
979ea1dd | 664 | v4l2_i2c_subdev_init(&mt9m001->subdev, client, &mt9m001_subdev_ops); |
2dd7d29c HV |
665 | v4l2_ctrl_handler_init(&mt9m001->hdl, 4); |
666 | v4l2_ctrl_new_std(&mt9m001->hdl, &mt9m001_ctrl_ops, | |
667 | V4L2_CID_VFLIP, 0, 1, 1, 0); | |
668 | v4l2_ctrl_new_std(&mt9m001->hdl, &mt9m001_ctrl_ops, | |
669 | V4L2_CID_GAIN, 0, 127, 1, 64); | |
670 | mt9m001->exposure = v4l2_ctrl_new_std(&mt9m001->hdl, &mt9m001_ctrl_ops, | |
671 | V4L2_CID_EXPOSURE, 1, 255, 1, 255); | |
672 | /* | |
673 | * Simulated autoexposure. If enabled, we calculate shutter width | |
674 | * ourselves in the driver based on vertical blanking and frame width | |
675 | */ | |
676 | mt9m001->autoexposure = v4l2_ctrl_new_std_menu(&mt9m001->hdl, | |
677 | &mt9m001_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, 1, 0, | |
678 | V4L2_EXPOSURE_AUTO); | |
679 | mt9m001->subdev.ctrl_handler = &mt9m001->hdl; | |
680 | if (mt9m001->hdl.error) { | |
681 | int err = mt9m001->hdl.error; | |
f523dd0d | 682 | |
2dd7d29c HV |
683 | kfree(mt9m001); |
684 | return err; | |
685 | } | |
686 | v4l2_ctrl_auto_cluster(2, &mt9m001->autoexposure, | |
687 | V4L2_EXPOSURE_MANUAL, true); | |
6a6c8786 | 688 | |
2dd7d29c | 689 | /* Second stage probe - when a capture adapter is there */ |
32536108 | 690 | mt9m001->y_skip_top = 0; |
6a6c8786 GL |
691 | mt9m001->rect.left = MT9M001_COLUMN_SKIP; |
692 | mt9m001->rect.top = MT9M001_ROW_SKIP; | |
693 | mt9m001->rect.width = MT9M001_MAX_WIDTH; | |
694 | mt9m001->rect.height = MT9M001_MAX_HEIGHT; | |
695 | ||
14178aa5 | 696 | ret = mt9m001_video_probe(icl, client); |
40e2e092 | 697 | if (ret) { |
2dd7d29c | 698 | v4l2_ctrl_handler_free(&mt9m001->hdl); |
40e2e092 GL |
699 | kfree(mt9m001); |
700 | } | |
f523dd0d | 701 | |
f523dd0d GL |
702 | return ret; |
703 | } | |
704 | ||
705 | static int mt9m001_remove(struct i2c_client *client) | |
706 | { | |
979ea1dd | 707 | struct mt9m001 *mt9m001 = to_mt9m001(client); |
14178aa5 | 708 | struct soc_camera_link *icl = soc_camera_i2c_to_link(client); |
f523dd0d | 709 | |
2dd7d29c HV |
710 | v4l2_device_unregister_subdev(&mt9m001->subdev); |
711 | v4l2_ctrl_handler_free(&mt9m001->hdl); | |
14178aa5 | 712 | mt9m001_video_remove(icl); |
f523dd0d GL |
713 | kfree(mt9m001); |
714 | ||
715 | return 0; | |
716 | } | |
717 | ||
3760f736 JD |
718 | static const struct i2c_device_id mt9m001_id[] = { |
719 | { "mt9m001", 0 }, | |
720 | { } | |
721 | }; | |
722 | MODULE_DEVICE_TABLE(i2c, mt9m001_id); | |
723 | ||
f523dd0d GL |
724 | static struct i2c_driver mt9m001_i2c_driver = { |
725 | .driver = { | |
726 | .name = "mt9m001", | |
727 | }, | |
728 | .probe = mt9m001_probe, | |
729 | .remove = mt9m001_remove, | |
3760f736 | 730 | .id_table = mt9m001_id, |
f523dd0d GL |
731 | }; |
732 | ||
c6e8d86f | 733 | module_i2c_driver(mt9m001_i2c_driver); |
f523dd0d GL |
734 | |
735 | MODULE_DESCRIPTION("Micron MT9M001 Camera driver"); | |
736 | MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>"); | |
737 | MODULE_LICENSE("GPL"); |