aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/mt9m111.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/mt9m111.c')
-rw-r--r--drivers/media/video/mt9m111.c112
1 files changed, 95 insertions, 17 deletions
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
index 3637376da755..920dd53c4cfa 100644
--- a/drivers/media/video/mt9m111.c
+++ b/drivers/media/video/mt9m111.c
@@ -194,7 +194,7 @@ static int mt9m111_reg_read(struct i2c_client *client, const u16 reg)
194 194
195 ret = reg_page_map_set(client, reg); 195 ret = reg_page_map_set(client, reg);
196 if (!ret) 196 if (!ret)
197 ret = swab16(i2c_smbus_read_word_data(client, (reg & 0xff))); 197 ret = swab16(i2c_smbus_read_word_data(client, reg & 0xff));
198 198
199 dev_dbg(&client->dev, "read reg.%03x -> %04x\n", reg, ret); 199 dev_dbg(&client->dev, "read reg.%03x -> %04x\n", reg, ret);
200 return ret; 200 return ret;
@@ -257,8 +257,8 @@ static int mt9m111_setup_rect(struct i2c_client *client,
257 int width = rect->width; 257 int width = rect->width;
258 int height = rect->height; 258 int height = rect->height;
259 259
260 if ((mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR8) 260 if (mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR8 ||
261 || (mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR16)) 261 mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR16)
262 is_raw_format = 1; 262 is_raw_format = 1;
263 else 263 else
264 is_raw_format = 0; 264 is_raw_format = 0;
@@ -395,23 +395,85 @@ static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f)
395 return 0; 395 return 0;
396} 396}
397 397
398static int mt9m111_make_rect(struct i2c_client *client,
399 struct v4l2_rect *rect)
400{
401 struct mt9m111 *mt9m111 = to_mt9m111(client);
402
403 if (mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR8 ||
404 mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR16) {
405 /* Bayer format - even size lengths */
406 rect->width = ALIGN(rect->width, 2);
407 rect->height = ALIGN(rect->height, 2);
408 /* Let the user play with the starting pixel */
409 }
410
411 /* FIXME: the datasheet doesn't specify minimum sizes */
412 soc_camera_limit_side(&rect->left, &rect->width,
413 MT9M111_MIN_DARK_COLS, 2, MT9M111_MAX_WIDTH);
414
415 soc_camera_limit_side(&rect->top, &rect->height,
416 MT9M111_MIN_DARK_ROWS, 2, MT9M111_MAX_HEIGHT);
417
418 return mt9m111_setup_rect(client, rect);
419}
420
398static int mt9m111_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) 421static int mt9m111_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
399{ 422{
400 struct v4l2_rect *rect = &a->c; 423 struct v4l2_rect rect = a->c;
401 struct i2c_client *client = sd->priv; 424 struct i2c_client *client = sd->priv;
402 struct mt9m111 *mt9m111 = to_mt9m111(client); 425 struct mt9m111 *mt9m111 = to_mt9m111(client);
403 int ret; 426 int ret;
404 427
405 dev_dbg(&client->dev, "%s left=%d, top=%d, width=%d, height=%d\n", 428 dev_dbg(&client->dev, "%s left=%d, top=%d, width=%d, height=%d\n",
406 __func__, rect->left, rect->top, rect->width, 429 __func__, rect.left, rect.top, rect.width, rect.height);
407 rect->height);
408 430
409 ret = mt9m111_setup_rect(client, rect); 431 ret = mt9m111_make_rect(client, &rect);
410 if (!ret) 432 if (!ret)
411 mt9m111->rect = *rect; 433 mt9m111->rect = rect;
412 return ret; 434 return ret;
413} 435}
414 436
437static int mt9m111_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
438{
439 struct i2c_client *client = sd->priv;
440 struct mt9m111 *mt9m111 = to_mt9m111(client);
441
442 a->c = mt9m111->rect;
443 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
444
445 return 0;
446}
447
448static int mt9m111_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
449{
450 a->bounds.left = MT9M111_MIN_DARK_COLS;
451 a->bounds.top = MT9M111_MIN_DARK_ROWS;
452 a->bounds.width = MT9M111_MAX_WIDTH;
453 a->bounds.height = MT9M111_MAX_HEIGHT;
454 a->defrect = a->bounds;
455 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
456 a->pixelaspect.numerator = 1;
457 a->pixelaspect.denominator = 1;
458
459 return 0;
460}
461
462static int mt9m111_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
463{
464 struct i2c_client *client = sd->priv;
465 struct mt9m111 *mt9m111 = to_mt9m111(client);
466 struct v4l2_pix_format *pix = &f->fmt.pix;
467
468 pix->width = mt9m111->rect.width;
469 pix->height = mt9m111->rect.height;
470 pix->pixelformat = mt9m111->pixfmt;
471 pix->field = V4L2_FIELD_NONE;
472 pix->colorspace = V4L2_COLORSPACE_SRGB;
473
474 return 0;
475}
476
415static int mt9m111_set_pixfmt(struct i2c_client *client, u32 pixfmt) 477static int mt9m111_set_pixfmt(struct i2c_client *client, u32 pixfmt)
416{ 478{
417 struct mt9m111 *mt9m111 = to_mt9m111(client); 479 struct mt9m111 *mt9m111 = to_mt9m111(client);
@@ -478,7 +540,7 @@ static int mt9m111_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
478 __func__, pix->pixelformat, rect.left, rect.top, rect.width, 540 __func__, pix->pixelformat, rect.left, rect.top, rect.width,
479 rect.height); 541 rect.height);
480 542
481 ret = mt9m111_setup_rect(client, &rect); 543 ret = mt9m111_make_rect(client, &rect);
482 if (!ret) 544 if (!ret)
483 ret = mt9m111_set_pixfmt(client, pix->pixelformat); 545 ret = mt9m111_set_pixfmt(client, pix->pixelformat);
484 if (!ret) 546 if (!ret)
@@ -489,11 +551,27 @@ static int mt9m111_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
489static int mt9m111_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) 551static int mt9m111_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
490{ 552{
491 struct v4l2_pix_format *pix = &f->fmt.pix; 553 struct v4l2_pix_format *pix = &f->fmt.pix;
554 bool bayer = pix->pixelformat == V4L2_PIX_FMT_SBGGR8 ||
555 pix->pixelformat == V4L2_PIX_FMT_SBGGR16;
556
557 /*
558 * With Bayer format enforce even side lengths, but let the user play
559 * with the starting pixel
560 */
492 561
493 if (pix->height > MT9M111_MAX_HEIGHT) 562 if (pix->height > MT9M111_MAX_HEIGHT)
494 pix->height = MT9M111_MAX_HEIGHT; 563 pix->height = MT9M111_MAX_HEIGHT;
564 else if (pix->height < 2)
565 pix->height = 2;
566 else if (bayer)
567 pix->height = ALIGN(pix->height, 2);
568
495 if (pix->width > MT9M111_MAX_WIDTH) 569 if (pix->width > MT9M111_MAX_WIDTH)
496 pix->width = MT9M111_MAX_WIDTH; 570 pix->width = MT9M111_MAX_WIDTH;
571 else if (pix->width < 2)
572 pix->width = 2;
573 else if (bayer)
574 pix->width = ALIGN(pix->width, 2);
497 575
498 return 0; 576 return 0;
499} 577}
@@ -906,8 +984,11 @@ static struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = {
906 984
907static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = { 985static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = {
908 .s_fmt = mt9m111_s_fmt, 986 .s_fmt = mt9m111_s_fmt,
987 .g_fmt = mt9m111_g_fmt,
909 .try_fmt = mt9m111_try_fmt, 988 .try_fmt = mt9m111_try_fmt,
910 .s_crop = mt9m111_s_crop, 989 .s_crop = mt9m111_s_crop,
990 .g_crop = mt9m111_g_crop,
991 .cropcap = mt9m111_cropcap,
911}; 992};
912 993
913static struct v4l2_subdev_ops mt9m111_subdev_ops = { 994static struct v4l2_subdev_ops mt9m111_subdev_ops = {
@@ -949,16 +1030,13 @@ static int mt9m111_probe(struct i2c_client *client,
949 1030
950 /* Second stage probe - when a capture adapter is there */ 1031 /* Second stage probe - when a capture adapter is there */
951 icd->ops = &mt9m111_ops; 1032 icd->ops = &mt9m111_ops;
952 icd->rect_max.left = MT9M111_MIN_DARK_COLS;
953 icd->rect_max.top = MT9M111_MIN_DARK_ROWS;
954 icd->rect_max.width = MT9M111_MAX_WIDTH;
955 icd->rect_max.height = MT9M111_MAX_HEIGHT;
956 icd->rect_current.left = icd->rect_max.left;
957 icd->rect_current.top = icd->rect_max.top;
958 icd->width_min = MT9M111_MIN_DARK_ROWS;
959 icd->height_min = MT9M111_MIN_DARK_COLS;
960 icd->y_skip_top = 0; 1033 icd->y_skip_top = 0;
961 1034
1035 mt9m111->rect.left = MT9M111_MIN_DARK_COLS;
1036 mt9m111->rect.top = MT9M111_MIN_DARK_ROWS;
1037 mt9m111->rect.width = MT9M111_MAX_WIDTH;
1038 mt9m111->rect.height = MT9M111_MAX_HEIGHT;
1039
962 ret = mt9m111_video_probe(icd, client); 1040 ret = mt9m111_video_probe(icd, client);
963 if (ret) { 1041 if (ret) {
964 icd->ops = NULL; 1042 icd->ops = NULL;