aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/mt9t031.c
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2009-08-25 10:50:46 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-09-18 23:19:17 -0400
commit6a6c8786725c0b3d143674effa8b772f47b1c189 (patch)
tree8bb76c5dcbd579f13e876bd1a0bb56bee4bcebdd /drivers/media/video/mt9t031.c
parent0166b74374cae3fa8bff0caef726a3d960a9a50a (diff)
V4L/DVB (12534): soc-camera: V4L2 API compliant scaling (S_FMT) and cropping (S_CROP)
The initial soc-camera scaling and cropping implementation turned out to be incompliant with the V4L2 API, e.g., it expected the user to specify cropping in output window pixels, instead of input window pixels. This patch converts the soc-camera core and all drivers to comply with the standard. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
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;