aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/mt9t031.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/mt9t031.c')
-rw-r--r--drivers/media/video/mt9t031.c220
1 files changed, 130 insertions, 90 deletions
diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c
index cd3eb7731ac2..f234ba602049 100644
--- a/drivers/media/video/mt9t031.c
+++ b/drivers/media/video/mt9t031.c
@@ -47,7 +47,7 @@
47#define MT9T031_MAX_HEIGHT 1536 47#define MT9T031_MAX_HEIGHT 1536
48#define MT9T031_MAX_WIDTH 2048 48#define MT9T031_MAX_WIDTH 2048
49#define MT9T031_MIN_HEIGHT 2 49#define MT9T031_MIN_HEIGHT 2
50#define MT9T031_MIN_WIDTH 2 50#define MT9T031_MIN_WIDTH 18
51#define MT9T031_HORIZONTAL_BLANK 142 51#define MT9T031_HORIZONTAL_BLANK 142
52#define MT9T031_VERTICAL_BLANK 25 52#define MT9T031_VERTICAL_BLANK 25
53#define MT9T031_COLUMN_SKIP 32 53#define MT9T031_COLUMN_SKIP 32
@@ -69,10 +69,11 @@ static const struct soc_camera_data_format mt9t031_colour_formats[] = {
69 69
70struct mt9t031 { 70struct mt9t031 {
71 struct v4l2_subdev subdev; 71 struct v4l2_subdev subdev;
72 struct v4l2_rect rect; /* Sensor window */
72 int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */ 73 int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */
73 unsigned char autoexposure;
74 u16 xskip; 74 u16 xskip;
75 u16 yskip; 75 u16 yskip;
76 unsigned char autoexposure;
76}; 77};
77 78
78static struct mt9t031 *to_mt9t031(const struct i2c_client *client) 79static struct mt9t031 *to_mt9t031(const struct i2c_client *client)
@@ -218,56 +219,68 @@ static unsigned long mt9t031_query_bus_param(struct soc_camera_device *icd)
218 return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM); 219 return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM);
219} 220}
220 221
221/* Round up minima and round down maxima */ 222/* target must be _even_ */
222static void recalculate_limits(struct soc_camera_device *icd, 223static u16 mt9t031_skip(s32 *source, s32 target, s32 max)
223 u16 xskip, u16 yskip)
224{ 224{
225 icd->rect_max.left = (MT9T031_COLUMN_SKIP + xskip - 1) / xskip; 225 unsigned int skip;
226 icd->rect_max.top = (MT9T031_ROW_SKIP + yskip - 1) / yskip; 226
227 icd->width_min = (MT9T031_MIN_WIDTH + xskip - 1) / xskip; 227 if (*source < target + target / 2) {
228 icd->height_min = (MT9T031_MIN_HEIGHT + yskip - 1) / yskip; 228 *source = target;
229 icd->rect_max.width = MT9T031_MAX_WIDTH / xskip; 229 return 1;
230 icd->rect_max.height = MT9T031_MAX_HEIGHT / yskip; 230 }
231
232 skip = min(max, *source + target / 2) / target;
233 if (skip > 8)
234 skip = 8;
235 *source = target * skip;
236
237 return skip;
231} 238}
232 239
240/* rect is the sensor rectangle, the caller guarantees parameter validity */
233static int mt9t031_set_params(struct soc_camera_device *icd, 241static int mt9t031_set_params(struct soc_camera_device *icd,
234 struct v4l2_rect *rect, u16 xskip, u16 yskip) 242 struct v4l2_rect *rect, u16 xskip, u16 yskip)
235{ 243{
236 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); 244 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
237 struct mt9t031 *mt9t031 = to_mt9t031(client); 245 struct mt9t031 *mt9t031 = to_mt9t031(client);
238 int ret; 246 int ret;
239 u16 xbin, ybin, width, height, left, top; 247 u16 xbin, ybin;
240 const u16 hblank = MT9T031_HORIZONTAL_BLANK, 248 const u16 hblank = MT9T031_HORIZONTAL_BLANK,
241 vblank = MT9T031_VERTICAL_BLANK; 249 vblank = MT9T031_VERTICAL_BLANK;
242 250
243 width = rect->width * xskip;
244 height = rect->height * yskip;
245 left = rect->left * xskip;
246 top = rect->top * yskip;
247
248 xbin = min(xskip, (u16)3); 251 xbin = min(xskip, (u16)3);
249 ybin = min(yskip, (u16)3); 252 ybin = min(yskip, (u16)3);
250 253
251 dev_dbg(&client->dev, "xskip %u, width %u/%u, yskip %u, height %u/%u\n", 254 /*
252 xskip, width, rect->width, yskip, height, rect->height); 255 * Could just do roundup(rect->left, [xy]bin * 2); but this is cheaper.
253 256 * There is always a valid suitably aligned value. The worst case is
254 /* Could just do roundup(rect->left, [xy]bin * 2); but this is cheaper */ 257 * xbin = 3, width = 2048. Then we will start at 36, the last read out
258 * pixel will be 2083, which is < 2085 - first black pixel.
259 *
260 * MT9T031 datasheet imposes window left border alignment, depending on
261 * the selected xskip. Failing to conform to this requirement produces
262 * dark horizontal stripes in the image. However, even obeying to this
263 * requirement doesn't eliminate the stripes in all configurations. They
264 * appear "locally reproducibly," but can differ between tests under
265 * different lighting conditions.
266 */
255 switch (xbin) { 267 switch (xbin) {
256 case 2: 268 case 1:
257 left = (left + 3) & ~3; 269 rect->left &= ~1;
258 break; 270 break;
259 case 3:
260 left = roundup(left, 6);
261 }
262
263 switch (ybin) {
264 case 2: 271 case 2:
265 top = (top + 3) & ~3; 272 rect->left &= ~3;
266 break; 273 break;
267 case 3: 274 case 3:
268 top = roundup(top, 6); 275 rect->left = rect->left > roundup(MT9T031_COLUMN_SKIP, 6) ?
276 (rect->left / 6) * 6 : roundup(MT9T031_COLUMN_SKIP, 6);
269 } 277 }
270 278
279 rect->top &= ~1;
280
281 dev_dbg(&client->dev, "skip %u:%u, rect %ux%u@%u:%u\n",
282 xskip, yskip, rect->width, rect->height, rect->left, rect->top);
283
271 /* Disable register update, reconfigure atomically */ 284 /* Disable register update, reconfigure atomically */
272 ret = reg_set(client, MT9T031_OUTPUT_CONTROL, 1); 285 ret = reg_set(client, MT9T031_OUTPUT_CONTROL, 1);
273 if (ret < 0) 286 if (ret < 0)
@@ -287,27 +300,29 @@ static int mt9t031_set_params(struct soc_camera_device *icd,
287 ret = reg_write(client, MT9T031_ROW_ADDRESS_MODE, 300 ret = reg_write(client, MT9T031_ROW_ADDRESS_MODE,
288 ((ybin - 1) << 4) | (yskip - 1)); 301 ((ybin - 1) << 4) | (yskip - 1));
289 } 302 }
290 dev_dbg(&client->dev, "new physical left %u, top %u\n", left, top); 303 dev_dbg(&client->dev, "new physical left %u, top %u\n",
304 rect->left, rect->top);
291 305
292 /* The caller provides a supported format, as guaranteed by 306 /* The caller provides a supported format, as guaranteed by
293 * icd->try_fmt_cap(), soc_camera_s_crop() and soc_camera_cropcap() */ 307 * icd->try_fmt_cap(), soc_camera_s_crop() and soc_camera_cropcap() */
294 if (ret >= 0) 308 if (ret >= 0)
295 ret = reg_write(client, MT9T031_COLUMN_START, left); 309 ret = reg_write(client, MT9T031_COLUMN_START, rect->left);
296 if (ret >= 0) 310 if (ret >= 0)
297 ret = reg_write(client, MT9T031_ROW_START, top); 311 ret = reg_write(client, MT9T031_ROW_START, rect->top);
298 if (ret >= 0) 312 if (ret >= 0)
299 ret = reg_write(client, MT9T031_WINDOW_WIDTH, width - 1); 313 ret = reg_write(client, MT9T031_WINDOW_WIDTH, rect->width - 1);
300 if (ret >= 0) 314 if (ret >= 0)
301 ret = reg_write(client, MT9T031_WINDOW_HEIGHT, 315 ret = reg_write(client, MT9T031_WINDOW_HEIGHT,
302 height + icd->y_skip_top - 1); 316 rect->height + icd->y_skip_top - 1);
303 if (ret >= 0 && mt9t031->autoexposure) { 317 if (ret >= 0 && mt9t031->autoexposure) {
304 ret = set_shutter(client, height + icd->y_skip_top + vblank); 318 ret = set_shutter(client,
319 rect->height + icd->y_skip_top + vblank);
305 if (ret >= 0) { 320 if (ret >= 0) {
306 const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; 321 const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank;
307 const struct v4l2_queryctrl *qctrl = 322 const struct v4l2_queryctrl *qctrl =
308 soc_camera_find_qctrl(icd->ops, 323 soc_camera_find_qctrl(icd->ops,
309 V4L2_CID_EXPOSURE); 324 V4L2_CID_EXPOSURE);
310 icd->exposure = (shutter_max / 2 + (height + 325 icd->exposure = (shutter_max / 2 + (rect->height +
311 icd->y_skip_top + vblank - 1) * 326 icd->y_skip_top + vblank - 1) *
312 (qctrl->maximum - qctrl->minimum)) / 327 (qctrl->maximum - qctrl->minimum)) /
313 shutter_max + qctrl->minimum; 328 shutter_max + qctrl->minimum;
@@ -318,27 +333,72 @@ static int mt9t031_set_params(struct soc_camera_device *icd,
318 if (ret >= 0) 333 if (ret >= 0)
319 ret = reg_clear(client, MT9T031_OUTPUT_CONTROL, 1); 334 ret = reg_clear(client, MT9T031_OUTPUT_CONTROL, 1);
320 335
336 if (ret >= 0) {
337 mt9t031->rect = *rect;
338 mt9t031->xskip = xskip;
339 mt9t031->yskip = yskip;
340 }
341
321 return ret < 0 ? ret : 0; 342 return ret < 0 ? ret : 0;
322} 343}
323 344
324static int mt9t031_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) 345static int mt9t031_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
325{ 346{
326 struct v4l2_rect *rect = &a->c; 347 struct v4l2_rect rect = a->c;
327 struct i2c_client *client = sd->priv; 348 struct i2c_client *client = sd->priv;
328 struct mt9t031 *mt9t031 = to_mt9t031(client); 349 struct mt9t031 *mt9t031 = to_mt9t031(client);
329 struct soc_camera_device *icd = client->dev.platform_data; 350 struct soc_camera_device *icd = client->dev.platform_data;
330 351
331 /* Make sure we don't exceed sensor limits */ 352 rect.width = ALIGN(rect.width, 2);
332 if (rect->left + rect->width > icd->rect_max.left + icd->rect_max.width) 353 rect.height = ALIGN(rect.height, 2);
333 rect->left = icd->rect_max.width + icd->rect_max.left - 354
334 rect->width; 355 soc_camera_limit_side(&rect.left, &rect.width,
356 MT9T031_COLUMN_SKIP, MT9T031_MIN_WIDTH, MT9T031_MAX_WIDTH);
357
358 soc_camera_limit_side(&rect.top, &rect.height,
359 MT9T031_ROW_SKIP, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT);
360
361 return mt9t031_set_params(icd, &rect, mt9t031->xskip, mt9t031->yskip);
362}
363
364static int mt9t031_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
365{
366 struct i2c_client *client = sd->priv;
367 struct mt9t031 *mt9t031 = to_mt9t031(client);
368
369 a->c = mt9t031->rect;
370 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
335 371
336 if (rect->top + rect->height > icd->rect_max.height + icd->rect_max.top) 372 return 0;
337 rect->top = icd->rect_max.height + icd->rect_max.top - 373}
338 rect->height; 374
375static int mt9t031_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
376{
377 a->bounds.left = MT9T031_COLUMN_SKIP;
378 a->bounds.top = MT9T031_ROW_SKIP;
379 a->bounds.width = MT9T031_MAX_WIDTH;
380 a->bounds.height = MT9T031_MAX_HEIGHT;
381 a->defrect = a->bounds;
382 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
383 a->pixelaspect.numerator = 1;
384 a->pixelaspect.denominator = 1;
339 385
340 /* CROP - no change in scaling, or in limits */ 386 return 0;
341 return mt9t031_set_params(icd, rect, mt9t031->xskip, mt9t031->yskip); 387}
388
389static int mt9t031_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
390{
391 struct i2c_client *client = sd->priv;
392 struct mt9t031 *mt9t031 = to_mt9t031(client);
393 struct v4l2_pix_format *pix = &f->fmt.pix;
394
395 pix->width = mt9t031->rect.width / mt9t031->xskip;
396 pix->height = mt9t031->rect.height / mt9t031->yskip;
397 pix->pixelformat = V4L2_PIX_FMT_SGRBG10;
398 pix->field = V4L2_FIELD_NONE;
399 pix->colorspace = V4L2_COLORSPACE_SRGB;
400
401 return 0;
342} 402}
343 403
344static int mt9t031_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) 404static int mt9t031_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
@@ -346,40 +406,25 @@ static int mt9t031_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
346 struct i2c_client *client = sd->priv; 406 struct i2c_client *client = sd->priv;
347 struct mt9t031 *mt9t031 = to_mt9t031(client); 407 struct mt9t031 *mt9t031 = to_mt9t031(client);
348 struct soc_camera_device *icd = client->dev.platform_data; 408 struct soc_camera_device *icd = client->dev.platform_data;
349 int ret; 409 struct v4l2_pix_format *pix = &f->fmt.pix;
350 u16 xskip, yskip; 410 u16 xskip, yskip;
351 struct v4l2_rect rect = { 411 struct v4l2_rect rect = mt9t031->rect;
352 .left = icd->rect_current.left,
353 .top = icd->rect_current.top,
354 .width = f->fmt.pix.width,
355 .height = f->fmt.pix.height,
356 };
357 412
358 /* 413 /*
359 * try_fmt has put rectangle within limits. 414 * try_fmt has put width and height within limits.
360 * S_FMT - use binning and skipping for scaling, recalculate 415 * S_FMT: use binning and skipping for scaling
361 * limits, used for cropping
362 */ 416 */
363 /* Is this more optimal than just a division? */ 417 xskip = mt9t031_skip(&rect.width, pix->width, MT9T031_MAX_WIDTH);
364 for (xskip = 8; xskip > 1; xskip--) 418 yskip = mt9t031_skip(&rect.height, pix->height, MT9T031_MAX_HEIGHT);
365 if (rect.width * xskip <= MT9T031_MAX_WIDTH)
366 break;
367
368 for (yskip = 8; yskip > 1; yskip--)
369 if (rect.height * yskip <= MT9T031_MAX_HEIGHT)
370 break;
371
372 recalculate_limits(icd, xskip, yskip);
373
374 ret = mt9t031_set_params(icd, &rect, xskip, yskip);
375 if (!ret) {
376 mt9t031->xskip = xskip;
377 mt9t031->yskip = yskip;
378 }
379 419
380 return ret; 420 /* mt9t031_set_params() doesn't change width and height */
421 return mt9t031_set_params(icd, &rect, xskip, yskip);
381} 422}
382 423
424/*
425 * If a user window larger than sensor window is requested, we'll increase the
426 * sensor window.
427 */
383static int mt9t031_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) 428static int mt9t031_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
384{ 429{
385 struct v4l2_pix_format *pix = &f->fmt.pix; 430 struct v4l2_pix_format *pix = &f->fmt.pix;
@@ -620,12 +665,12 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
620 if (ctrl->value) { 665 if (ctrl->value) {
621 const u16 vblank = MT9T031_VERTICAL_BLANK; 666 const u16 vblank = MT9T031_VERTICAL_BLANK;
622 const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; 667 const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank;
623 if (set_shutter(client, icd->rect_current.height + 668 if (set_shutter(client, mt9t031->rect.height +
624 icd->y_skip_top + vblank) < 0) 669 icd->y_skip_top + vblank) < 0)
625 return -EIO; 670 return -EIO;
626 qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); 671 qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
627 icd->exposure = (shutter_max / 2 + 672 icd->exposure = (shutter_max / 2 +
628 (icd->rect_current.height + 673 (mt9t031->rect.height +
629 icd->y_skip_top + vblank - 1) * 674 icd->y_skip_top + vblank - 1) *
630 (qctrl->maximum - qctrl->minimum)) / 675 (qctrl->maximum - qctrl->minimum)) /
631 shutter_max + qctrl->minimum; 676 shutter_max + qctrl->minimum;
@@ -645,12 +690,6 @@ static int mt9t031_video_probe(struct i2c_client *client)
645 struct mt9t031 *mt9t031 = to_mt9t031(client); 690 struct mt9t031 *mt9t031 = to_mt9t031(client);
646 s32 data; 691 s32 data;
647 692
648 /* We must have a parent by now. And it cannot be a wrong one.
649 * So this entire test is completely redundant. */
650 if (!icd->dev.parent ||
651 to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
652 return -ENODEV;
653
654 /* Enable the chip */ 693 /* Enable the chip */
655 data = reg_write(client, MT9T031_CHIP_ENABLE, 1); 694 data = reg_write(client, MT9T031_CHIP_ENABLE, 1);
656 dev_dbg(&client->dev, "write: %d\n", data); 695 dev_dbg(&client->dev, "write: %d\n", data);
@@ -688,8 +727,11 @@ static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = {
688static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = { 727static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = {
689 .s_stream = mt9t031_s_stream, 728 .s_stream = mt9t031_s_stream,
690 .s_fmt = mt9t031_s_fmt, 729 .s_fmt = mt9t031_s_fmt,
730 .g_fmt = mt9t031_g_fmt,
691 .try_fmt = mt9t031_try_fmt, 731 .try_fmt = mt9t031_try_fmt,
692 .s_crop = mt9t031_s_crop, 732 .s_crop = mt9t031_s_crop,
733 .g_crop = mt9t031_g_crop,
734 .cropcap = mt9t031_cropcap,
693}; 735};
694 736
695static struct v4l2_subdev_ops mt9t031_subdev_ops = { 737static struct v4l2_subdev_ops mt9t031_subdev_ops = {
@@ -731,15 +773,13 @@ static int mt9t031_probe(struct i2c_client *client,
731 773
732 /* Second stage probe - when a capture adapter is there */ 774 /* Second stage probe - when a capture adapter is there */
733 icd->ops = &mt9t031_ops; 775 icd->ops = &mt9t031_ops;
734 icd->rect_max.left = MT9T031_COLUMN_SKIP;
735 icd->rect_max.top = MT9T031_ROW_SKIP;
736 icd->rect_current.left = icd->rect_max.left;
737 icd->rect_current.top = icd->rect_max.top;
738 icd->width_min = MT9T031_MIN_WIDTH;
739 icd->rect_max.width = MT9T031_MAX_WIDTH;
740 icd->height_min = MT9T031_MIN_HEIGHT;
741 icd->rect_max.height = MT9T031_MAX_HEIGHT;
742 icd->y_skip_top = 0; 776 icd->y_skip_top = 0;
777
778 mt9t031->rect.left = MT9T031_COLUMN_SKIP;
779 mt9t031->rect.top = MT9T031_ROW_SKIP;
780 mt9t031->rect.width = MT9T031_MAX_WIDTH;
781 mt9t031->rect.height = MT9T031_MAX_HEIGHT;
782
743 /* Simulated autoexposure. If enabled, we calculate shutter width 783 /* Simulated autoexposure. If enabled, we calculate shutter width
744 * ourselves in the driver based on vertical blanking and frame width */ 784 * ourselves in the driver based on vertical blanking and frame width */
745 mt9t031->autoexposure = 1; 785 mt9t031->autoexposure = 1;