aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/mt9m001.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/mt9m001.c')
-rw-r--r--drivers/media/video/mt9m001.c205
1 files changed, 131 insertions, 74 deletions
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
index 45388d2ce2fd..b62c0bd3f8ea 100644
--- a/drivers/media/video/mt9m001.c
+++ b/drivers/media/video/mt9m001.c
@@ -17,9 +17,11 @@
17#include <media/v4l2-chip-ident.h> 17#include <media/v4l2-chip-ident.h>
18#include <media/soc_camera.h> 18#include <media/soc_camera.h>
19 19
20/* mt9m001 i2c address 0x5d 20/*
21 * mt9m001 i2c address 0x5d
21 * The platform has to define ctruct i2c_board_info objects and link to them 22 * The platform has to define ctruct i2c_board_info objects and link to them
22 * from struct soc_camera_link */ 23 * from struct soc_camera_link
24 */
23 25
24/* mt9m001 selected register addresses */ 26/* mt9m001 selected register addresses */
25#define MT9M001_CHIP_VERSION 0x00 27#define MT9M001_CHIP_VERSION 0x00
@@ -46,42 +48,50 @@
46#define MT9M001_COLUMN_SKIP 20 48#define MT9M001_COLUMN_SKIP 20
47#define MT9M001_ROW_SKIP 12 49#define MT9M001_ROW_SKIP 12
48 50
49static const struct soc_camera_data_format mt9m001_colour_formats[] = { 51/* MT9M001 has only one fixed colorspace per pixelcode */
50 /* Order important: first natively supported, 52struct mt9m001_datafmt {
51 * second supported with a GPIO extender */ 53 enum v4l2_mbus_pixelcode code;
52 { 54 enum v4l2_colorspace colorspace;
53 .name = "Bayer (sRGB) 10 bit", 55};
54 .depth = 10, 56
55 .fourcc = V4L2_PIX_FMT_SBGGR16, 57/* Find a data format by a pixel code in an array */
56 .colorspace = V4L2_COLORSPACE_SRGB, 58static const struct mt9m001_datafmt *mt9m001_find_datafmt(
57 }, { 59 enum v4l2_mbus_pixelcode code, const struct mt9m001_datafmt *fmt,
58 .name = "Bayer (sRGB) 8 bit", 60 int n)
59 .depth = 8, 61{
60 .fourcc = V4L2_PIX_FMT_SBGGR8, 62 int i;
61 .colorspace = V4L2_COLORSPACE_SRGB, 63 for (i = 0; i < n; i++)
62 } 64 if (fmt[i].code == code)
65 return fmt + i;
66
67 return NULL;
68}
69
70static const struct mt9m001_datafmt mt9m001_colour_fmts[] = {
71 /*
72 * Order important: first natively supported,
73 * second supported with a GPIO extender
74 */
75 {V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB},
76 {V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
63}; 77};
64 78
65static const struct soc_camera_data_format mt9m001_monochrome_formats[] = { 79static const struct mt9m001_datafmt mt9m001_monochrome_fmts[] = {
66 /* Order important - see above */ 80 /* Order important - see above */
67 { 81 {V4L2_MBUS_FMT_Y10_1X10, V4L2_COLORSPACE_JPEG},
68 .name = "Monochrome 10 bit", 82 {V4L2_MBUS_FMT_GREY8_1X8, V4L2_COLORSPACE_JPEG},
69 .depth = 10,
70 .fourcc = V4L2_PIX_FMT_Y16,
71 }, {
72 .name = "Monochrome 8 bit",
73 .depth = 8,
74 .fourcc = V4L2_PIX_FMT_GREY,
75 },
76}; 83};
77 84
78struct mt9m001 { 85struct mt9m001 {
79 struct v4l2_subdev subdev; 86 struct v4l2_subdev subdev;
80 struct v4l2_rect rect; /* Sensor window */ 87 struct v4l2_rect rect; /* Sensor window */
81 __u32 fourcc; 88 const struct mt9m001_datafmt *fmt;
89 const struct mt9m001_datafmt *fmts;
90 int num_fmts;
82 int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ 91 int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
83 unsigned int gain; 92 unsigned int gain;
84 unsigned int exposure; 93 unsigned int exposure;
94 unsigned short y_skip_top; /* Lines to skip at the top */
85 unsigned char autoexposure; 95 unsigned char autoexposure;
86}; 96};
87 97
@@ -204,8 +214,7 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
204 const u16 hblank = 9, vblank = 25; 214 const u16 hblank = 9, vblank = 25;
205 unsigned int total_h; 215 unsigned int total_h;
206 216
207 if (mt9m001->fourcc == V4L2_PIX_FMT_SBGGR8 || 217 if (mt9m001->fmts == mt9m001_colour_fmts)
208 mt9m001->fourcc == V4L2_PIX_FMT_SBGGR16)
209 /* 218 /*
210 * Bayer format - even number of rows for simplicity, 219 * Bayer format - even number of rows for simplicity,
211 * but let the user play with the top row. 220 * but let the user play with the top row.
@@ -222,15 +231,17 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
222 soc_camera_limit_side(&rect.top, &rect.height, 231 soc_camera_limit_side(&rect.top, &rect.height,
223 MT9M001_ROW_SKIP, MT9M001_MIN_HEIGHT, MT9M001_MAX_HEIGHT); 232 MT9M001_ROW_SKIP, MT9M001_MIN_HEIGHT, MT9M001_MAX_HEIGHT);
224 233
225 total_h = rect.height + icd->y_skip_top + vblank; 234 total_h = rect.height + mt9m001->y_skip_top + vblank;
226 235
227 /* Blanking and start values - default... */ 236 /* Blanking and start values - default... */
228 ret = reg_write(client, MT9M001_HORIZONTAL_BLANKING, hblank); 237 ret = reg_write(client, MT9M001_HORIZONTAL_BLANKING, hblank);
229 if (!ret) 238 if (!ret)
230 ret = reg_write(client, MT9M001_VERTICAL_BLANKING, vblank); 239 ret = reg_write(client, MT9M001_VERTICAL_BLANKING, vblank);
231 240
232 /* The caller provides a supported format, as verified per 241 /*
233 * call to icd->try_fmt() */ 242 * The caller provides a supported format, as verified per
243 * call to icd->try_fmt()
244 */
234 if (!ret) 245 if (!ret)
235 ret = reg_write(client, MT9M001_COLUMN_START, rect.left); 246 ret = reg_write(client, MT9M001_COLUMN_START, rect.left);
236 if (!ret) 247 if (!ret)
@@ -239,7 +250,7 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
239 ret = reg_write(client, MT9M001_WINDOW_WIDTH, rect.width - 1); 250 ret = reg_write(client, MT9M001_WINDOW_WIDTH, rect.width - 1);
240 if (!ret) 251 if (!ret)
241 ret = reg_write(client, MT9M001_WINDOW_HEIGHT, 252 ret = reg_write(client, MT9M001_WINDOW_HEIGHT,
242 rect.height + icd->y_skip_top - 1); 253 rect.height + mt9m001->y_skip_top - 1);
243 if (!ret && mt9m001->autoexposure) { 254 if (!ret && mt9m001->autoexposure) {
244 ret = reg_write(client, MT9M001_SHUTTER_WIDTH, total_h); 255 ret = reg_write(client, MT9M001_SHUTTER_WIDTH, total_h);
245 if (!ret) { 256 if (!ret) {
@@ -283,32 +294,32 @@ static int mt9m001_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
283 return 0; 294 return 0;
284} 295}
285 296
286static int mt9m001_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) 297static int mt9m001_g_fmt(struct v4l2_subdev *sd,
298 struct v4l2_mbus_framefmt *mf)
287{ 299{
288 struct i2c_client *client = sd->priv; 300 struct i2c_client *client = sd->priv;
289 struct mt9m001 *mt9m001 = to_mt9m001(client); 301 struct mt9m001 *mt9m001 = to_mt9m001(client);
290 struct v4l2_pix_format *pix = &f->fmt.pix;
291 302
292 pix->width = mt9m001->rect.width; 303 mf->width = mt9m001->rect.width;
293 pix->height = mt9m001->rect.height; 304 mf->height = mt9m001->rect.height;
294 pix->pixelformat = mt9m001->fourcc; 305 mf->code = mt9m001->fmt->code;
295 pix->field = V4L2_FIELD_NONE; 306 mf->colorspace = mt9m001->fmt->colorspace;
296 pix->colorspace = V4L2_COLORSPACE_SRGB; 307 mf->field = V4L2_FIELD_NONE;
297 308
298 return 0; 309 return 0;
299} 310}
300 311
301static int mt9m001_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) 312static int mt9m001_s_fmt(struct v4l2_subdev *sd,
313 struct v4l2_mbus_framefmt *mf)
302{ 314{
303 struct i2c_client *client = sd->priv; 315 struct i2c_client *client = sd->priv;
304 struct mt9m001 *mt9m001 = to_mt9m001(client); 316 struct mt9m001 *mt9m001 = to_mt9m001(client);
305 struct v4l2_pix_format *pix = &f->fmt.pix;
306 struct v4l2_crop a = { 317 struct v4l2_crop a = {
307 .c = { 318 .c = {
308 .left = mt9m001->rect.left, 319 .left = mt9m001->rect.left,
309 .top = mt9m001->rect.top, 320 .top = mt9m001->rect.top,
310 .width = pix->width, 321 .width = mf->width,
311 .height = pix->height, 322 .height = mf->height,
312 }, 323 },
313 }; 324 };
314 int ret; 325 int ret;
@@ -316,28 +327,39 @@ static int mt9m001_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
316 /* No support for scaling so far, just crop. TODO: use skipping */ 327 /* No support for scaling so far, just crop. TODO: use skipping */
317 ret = mt9m001_s_crop(sd, &a); 328 ret = mt9m001_s_crop(sd, &a);
318 if (!ret) { 329 if (!ret) {
319 pix->width = mt9m001->rect.width; 330 mf->width = mt9m001->rect.width;
320 pix->height = mt9m001->rect.height; 331 mf->height = mt9m001->rect.height;
321 mt9m001->fourcc = pix->pixelformat; 332 mt9m001->fmt = mt9m001_find_datafmt(mf->code,
333 mt9m001->fmts, mt9m001->num_fmts);
334 mf->colorspace = mt9m001->fmt->colorspace;
322 } 335 }
323 336
324 return ret; 337 return ret;
325} 338}
326 339
327static int mt9m001_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) 340static int mt9m001_try_fmt(struct v4l2_subdev *sd,
341 struct v4l2_mbus_framefmt *mf)
328{ 342{
329 struct i2c_client *client = sd->priv; 343 struct i2c_client *client = sd->priv;
330 struct soc_camera_device *icd = client->dev.platform_data; 344 struct mt9m001 *mt9m001 = to_mt9m001(client);
331 struct v4l2_pix_format *pix = &f->fmt.pix; 345 const struct mt9m001_datafmt *fmt;
332 346
333 v4l_bound_align_image(&pix->width, MT9M001_MIN_WIDTH, 347 v4l_bound_align_image(&mf->width, MT9M001_MIN_WIDTH,
334 MT9M001_MAX_WIDTH, 1, 348 MT9M001_MAX_WIDTH, 1,
335 &pix->height, MT9M001_MIN_HEIGHT + icd->y_skip_top, 349 &mf->height, MT9M001_MIN_HEIGHT + mt9m001->y_skip_top,
336 MT9M001_MAX_HEIGHT + icd->y_skip_top, 0, 0); 350 MT9M001_MAX_HEIGHT + mt9m001->y_skip_top, 0, 0);
351
352 if (mt9m001->fmts == mt9m001_colour_fmts)
353 mf->height = ALIGN(mf->height - 1, 2);
337 354
338 if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8 || 355 fmt = mt9m001_find_datafmt(mf->code, mt9m001->fmts,
339 pix->pixelformat == V4L2_PIX_FMT_SBGGR16) 356 mt9m001->num_fmts);
340 pix->height = ALIGN(pix->height - 1, 2); 357 if (!fmt) {
358 fmt = mt9m001->fmt;
359 mf->code = fmt->code;
360 }
361
362 mf->colorspace = fmt->colorspace;
341 363
342 return 0; 364 return 0;
343} 365}
@@ -552,7 +574,7 @@ static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
552 if (ctrl->value) { 574 if (ctrl->value) {
553 const u16 vblank = 25; 575 const u16 vblank = 25;
554 unsigned int total_h = mt9m001->rect.height + 576 unsigned int total_h = mt9m001->rect.height +
555 icd->y_skip_top + vblank; 577 mt9m001->y_skip_top + vblank;
556 if (reg_write(client, MT9M001_SHUTTER_WIDTH, 578 if (reg_write(client, MT9M001_SHUTTER_WIDTH,
557 total_h) < 0) 579 total_h) < 0)
558 return -EIO; 580 return -EIO;
@@ -568,8 +590,10 @@ static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
568 return 0; 590 return 0;
569} 591}
570 592
571/* Interface active, can use i2c. If it fails, it can indeed mean, that 593/*
572 * this wasn't our capture interface, so, we wait for the right one */ 594 * Interface active, can use i2c. If it fails, it can indeed mean, that
595 * this wasn't our capture interface, so, we wait for the right one
596 */
573static int mt9m001_video_probe(struct soc_camera_device *icd, 597static int mt9m001_video_probe(struct soc_camera_device *icd,
574 struct i2c_client *client) 598 struct i2c_client *client)
575{ 599{
@@ -579,8 +603,10 @@ static int mt9m001_video_probe(struct soc_camera_device *icd,
579 unsigned long flags; 603 unsigned long flags;
580 int ret; 604 int ret;
581 605
582 /* We must have a parent by now. And it cannot be a wrong one. 606 /*
583 * So this entire test is completely redundant. */ 607 * We must have a parent by now. And it cannot be a wrong one.
608 * So this entire test is completely redundant.
609 */
584 if (!icd->dev.parent || 610 if (!icd->dev.parent ||
585 to_soc_camera_host(icd->dev.parent)->nr != icd->iface) 611 to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
586 return -ENODEV; 612 return -ENODEV;
@@ -597,11 +623,11 @@ static int mt9m001_video_probe(struct soc_camera_device *icd,
597 case 0x8411: 623 case 0x8411:
598 case 0x8421: 624 case 0x8421:
599 mt9m001->model = V4L2_IDENT_MT9M001C12ST; 625 mt9m001->model = V4L2_IDENT_MT9M001C12ST;
600 icd->formats = mt9m001_colour_formats; 626 mt9m001->fmts = mt9m001_colour_fmts;
601 break; 627 break;
602 case 0x8431: 628 case 0x8431:
603 mt9m001->model = V4L2_IDENT_MT9M001C12STM; 629 mt9m001->model = V4L2_IDENT_MT9M001C12STM;
604 icd->formats = mt9m001_monochrome_formats; 630 mt9m001->fmts = mt9m001_monochrome_fmts;
605 break; 631 break;
606 default: 632 default:
607 dev_err(&client->dev, 633 dev_err(&client->dev,
@@ -609,7 +635,7 @@ static int mt9m001_video_probe(struct soc_camera_device *icd,
609 return -ENODEV; 635 return -ENODEV;
610 } 636 }
611 637
612 icd->num_formats = 0; 638 mt9m001->num_fmts = 0;
613 639
614 /* 640 /*
615 * This is a 10bit sensor, so by default we only allow 10bit. 641 * This is a 10bit sensor, so by default we only allow 10bit.
@@ -622,14 +648,14 @@ static int mt9m001_video_probe(struct soc_camera_device *icd,
622 flags = SOCAM_DATAWIDTH_10; 648 flags = SOCAM_DATAWIDTH_10;
623 649
624 if (flags & SOCAM_DATAWIDTH_10) 650 if (flags & SOCAM_DATAWIDTH_10)
625 icd->num_formats++; 651 mt9m001->num_fmts++;
626 else 652 else
627 icd->formats++; 653 mt9m001->fmts++;
628 654
629 if (flags & SOCAM_DATAWIDTH_8) 655 if (flags & SOCAM_DATAWIDTH_8)
630 icd->num_formats++; 656 mt9m001->num_fmts++;
631 657
632 mt9m001->fourcc = icd->formats->fourcc; 658 mt9m001->fmt = &mt9m001->fmts[0];
633 659
634 dev_info(&client->dev, "Detected a MT9M001 chip ID %x (%s)\n", data, 660 dev_info(&client->dev, "Detected a MT9M001 chip ID %x (%s)\n", data,
635 data == 0x8431 ? "C12STM" : "C12ST"); 661 data == 0x8431 ? "C12STM" : "C12ST");
@@ -655,6 +681,16 @@ static void mt9m001_video_remove(struct soc_camera_device *icd)
655 icl->free_bus(icl); 681 icl->free_bus(icl);
656} 682}
657 683
684static int mt9m001_g_skip_top_lines(struct v4l2_subdev *sd, u32 *lines)
685{
686 struct i2c_client *client = sd->priv;
687 struct mt9m001 *mt9m001 = to_mt9m001(client);
688
689 *lines = mt9m001->y_skip_top;
690
691 return 0;
692}
693
658static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = { 694static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = {
659 .g_ctrl = mt9m001_g_ctrl, 695 .g_ctrl = mt9m001_g_ctrl,
660 .s_ctrl = mt9m001_s_ctrl, 696 .s_ctrl = mt9m001_s_ctrl,
@@ -665,19 +701,38 @@ static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = {
665#endif 701#endif
666}; 702};
667 703
704static int mt9m001_enum_fmt(struct v4l2_subdev *sd, int index,
705 enum v4l2_mbus_pixelcode *code)
706{
707 struct i2c_client *client = sd->priv;
708 struct mt9m001 *mt9m001 = to_mt9m001(client);
709
710 if ((unsigned int)index >= mt9m001->num_fmts)
711 return -EINVAL;
712
713 *code = mt9m001->fmts[index].code;
714 return 0;
715}
716
668static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = { 717static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = {
669 .s_stream = mt9m001_s_stream, 718 .s_stream = mt9m001_s_stream,
670 .s_fmt = mt9m001_s_fmt, 719 .s_mbus_fmt = mt9m001_s_fmt,
671 .g_fmt = mt9m001_g_fmt, 720 .g_mbus_fmt = mt9m001_g_fmt,
672 .try_fmt = mt9m001_try_fmt, 721 .try_mbus_fmt = mt9m001_try_fmt,
673 .s_crop = mt9m001_s_crop, 722 .s_crop = mt9m001_s_crop,
674 .g_crop = mt9m001_g_crop, 723 .g_crop = mt9m001_g_crop,
675 .cropcap = mt9m001_cropcap, 724 .cropcap = mt9m001_cropcap,
725 .enum_mbus_fmt = mt9m001_enum_fmt,
726};
727
728static struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = {
729 .g_skip_top_lines = mt9m001_g_skip_top_lines,
676}; 730};
677 731
678static struct v4l2_subdev_ops mt9m001_subdev_ops = { 732static struct v4l2_subdev_ops mt9m001_subdev_ops = {
679 .core = &mt9m001_subdev_core_ops, 733 .core = &mt9m001_subdev_core_ops,
680 .video = &mt9m001_subdev_video_ops, 734 .video = &mt9m001_subdev_video_ops,
735 .sensor = &mt9m001_subdev_sensor_ops,
681}; 736};
682 737
683static int mt9m001_probe(struct i2c_client *client, 738static int mt9m001_probe(struct i2c_client *client,
@@ -714,15 +769,17 @@ static int mt9m001_probe(struct i2c_client *client,
714 769
715 /* Second stage probe - when a capture adapter is there */ 770 /* Second stage probe - when a capture adapter is there */
716 icd->ops = &mt9m001_ops; 771 icd->ops = &mt9m001_ops;
717 icd->y_skip_top = 0;
718 772
773 mt9m001->y_skip_top = 0;
719 mt9m001->rect.left = MT9M001_COLUMN_SKIP; 774 mt9m001->rect.left = MT9M001_COLUMN_SKIP;
720 mt9m001->rect.top = MT9M001_ROW_SKIP; 775 mt9m001->rect.top = MT9M001_ROW_SKIP;
721 mt9m001->rect.width = MT9M001_MAX_WIDTH; 776 mt9m001->rect.width = MT9M001_MAX_WIDTH;
722 mt9m001->rect.height = MT9M001_MAX_HEIGHT; 777 mt9m001->rect.height = MT9M001_MAX_HEIGHT;
723 778
724 /* Simulated autoexposure. If enabled, we calculate shutter width 779 /*
725 * ourselves in the driver based on vertical blanking and frame width */ 780 * Simulated autoexposure. If enabled, we calculate shutter width
781 * ourselves in the driver based on vertical blanking and frame width
782 */
726 mt9m001->autoexposure = 1; 783 mt9m001->autoexposure = 1;
727 784
728 ret = mt9m001_video_probe(icd, client); 785 ret = mt9m001_video_probe(icd, client);