aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/mt9m001.c
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2009-12-11 09:46:49 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-12-16 06:27:29 -0500
commit760697beca338599a65484389c7abbe54aedb664 (patch)
tree515735429d2240629a6f048ab1a7fefaf5299e46 /drivers/media/video/mt9m001.c
parent9a74251d8bee7a25fee89a0be3ccea73e01c1a05 (diff)
V4L/DVB (13659): soc-camera: convert to the new mediabus API
Convert soc-camera core and all soc-camera drivers to the new mediabus API. This also takes soc-camera client drivers one step closer to also be usable with generic v4l2-subdev host drivers. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Acked-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/mt9m001.c')
-rw-r--r--drivers/media/video/mt9m001.c141
1 files changed, 85 insertions, 56 deletions
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
index cc9066000c2d..b62c0bd3f8ea 100644
--- a/drivers/media/video/mt9m001.c
+++ b/drivers/media/video/mt9m001.c
@@ -48,41 +48,46 @@
48#define MT9M001_COLUMN_SKIP 20 48#define MT9M001_COLUMN_SKIP 20
49#define MT9M001_ROW_SKIP 12 49#define MT9M001_ROW_SKIP 12
50 50
51static const struct soc_camera_data_format mt9m001_colour_formats[] = { 51/* MT9M001 has only one fixed colorspace per pixelcode */
52struct mt9m001_datafmt {
53 enum v4l2_mbus_pixelcode code;
54 enum v4l2_colorspace colorspace;
55};
56
57/* Find a data format by a pixel code in an array */
58static const struct mt9m001_datafmt *mt9m001_find_datafmt(
59 enum v4l2_mbus_pixelcode code, const struct mt9m001_datafmt *fmt,
60 int n)
61{
62 int i;
63 for (i = 0; i < n; i++)
64 if (fmt[i].code == code)
65 return fmt + i;
66
67 return NULL;
68}
69
70static const struct mt9m001_datafmt mt9m001_colour_fmts[] = {
52 /* 71 /*
53 * Order important: first natively supported, 72 * Order important: first natively supported,
54 * second supported with a GPIO extender 73 * second supported with a GPIO extender
55 */ 74 */
56 { 75 {V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB},
57 .name = "Bayer (sRGB) 10 bit", 76 {V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
58 .depth = 10,
59 .fourcc = V4L2_PIX_FMT_SBGGR16,
60 .colorspace = V4L2_COLORSPACE_SRGB,
61 }, {
62 .name = "Bayer (sRGB) 8 bit",
63 .depth = 8,
64 .fourcc = V4L2_PIX_FMT_SBGGR8,
65 .colorspace = V4L2_COLORSPACE_SRGB,
66 }
67}; 77};
68 78
69static const struct soc_camera_data_format mt9m001_monochrome_formats[] = { 79static const struct mt9m001_datafmt mt9m001_monochrome_fmts[] = {
70 /* Order important - see above */ 80 /* Order important - see above */
71 { 81 {V4L2_MBUS_FMT_Y10_1X10, V4L2_COLORSPACE_JPEG},
72 .name = "Monochrome 10 bit", 82 {V4L2_MBUS_FMT_GREY8_1X8, V4L2_COLORSPACE_JPEG},
73 .depth = 10,
74 .fourcc = V4L2_PIX_FMT_Y16,
75 }, {
76 .name = "Monochrome 8 bit",
77 .depth = 8,
78 .fourcc = V4L2_PIX_FMT_GREY,
79 },
80}; 83};
81 84
82struct mt9m001 { 85struct mt9m001 {
83 struct v4l2_subdev subdev; 86 struct v4l2_subdev subdev;
84 struct v4l2_rect rect; /* Sensor window */ 87 struct v4l2_rect rect; /* Sensor window */
85 __u32 fourcc; 88 const struct mt9m001_datafmt *fmt;
89 const struct mt9m001_datafmt *fmts;
90 int num_fmts;
86 int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ 91 int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
87 unsigned int gain; 92 unsigned int gain;
88 unsigned int exposure; 93 unsigned int exposure;
@@ -209,8 +214,7 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
209 const u16 hblank = 9, vblank = 25; 214 const u16 hblank = 9, vblank = 25;
210 unsigned int total_h; 215 unsigned int total_h;
211 216
212 if (mt9m001->fourcc == V4L2_PIX_FMT_SBGGR8 || 217 if (mt9m001->fmts == mt9m001_colour_fmts)
213 mt9m001->fourcc == V4L2_PIX_FMT_SBGGR16)
214 /* 218 /*
215 * Bayer format - even number of rows for simplicity, 219 * Bayer format - even number of rows for simplicity,
216 * but let the user play with the top row. 220 * but let the user play with the top row.
@@ -290,32 +294,32 @@ static int mt9m001_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
290 return 0; 294 return 0;
291} 295}
292 296
293static 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)
294{ 299{
295 struct i2c_client *client = sd->priv; 300 struct i2c_client *client = sd->priv;
296 struct mt9m001 *mt9m001 = to_mt9m001(client); 301 struct mt9m001 *mt9m001 = to_mt9m001(client);
297 struct v4l2_pix_format *pix = &f->fmt.pix;
298 302
299 pix->width = mt9m001->rect.width; 303 mf->width = mt9m001->rect.width;
300 pix->height = mt9m001->rect.height; 304 mf->height = mt9m001->rect.height;
301 pix->pixelformat = mt9m001->fourcc; 305 mf->code = mt9m001->fmt->code;
302 pix->field = V4L2_FIELD_NONE; 306 mf->colorspace = mt9m001->fmt->colorspace;
303 pix->colorspace = V4L2_COLORSPACE_SRGB; 307 mf->field = V4L2_FIELD_NONE;
304 308
305 return 0; 309 return 0;
306} 310}
307 311
308static 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)
309{ 314{
310 struct i2c_client *client = sd->priv; 315 struct i2c_client *client = sd->priv;
311 struct mt9m001 *mt9m001 = to_mt9m001(client); 316 struct mt9m001 *mt9m001 = to_mt9m001(client);
312 struct v4l2_pix_format *pix = &f->fmt.pix;
313 struct v4l2_crop a = { 317 struct v4l2_crop a = {
314 .c = { 318 .c = {
315 .left = mt9m001->rect.left, 319 .left = mt9m001->rect.left,
316 .top = mt9m001->rect.top, 320 .top = mt9m001->rect.top,
317 .width = pix->width, 321 .width = mf->width,
318 .height = pix->height, 322 .height = mf->height,
319 }, 323 },
320 }; 324 };
321 int ret; 325 int ret;
@@ -323,28 +327,39 @@ static int mt9m001_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
323 /* No support for scaling so far, just crop. TODO: use skipping */ 327 /* No support for scaling so far, just crop. TODO: use skipping */
324 ret = mt9m001_s_crop(sd, &a); 328 ret = mt9m001_s_crop(sd, &a);
325 if (!ret) { 329 if (!ret) {
326 pix->width = mt9m001->rect.width; 330 mf->width = mt9m001->rect.width;
327 pix->height = mt9m001->rect.height; 331 mf->height = mt9m001->rect.height;
328 mt9m001->fourcc = pix->pixelformat; 332 mt9m001->fmt = mt9m001_find_datafmt(mf->code,
333 mt9m001->fmts, mt9m001->num_fmts);
334 mf->colorspace = mt9m001->fmt->colorspace;
329 } 335 }
330 336
331 return ret; 337 return ret;
332} 338}
333 339
334static 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)
335{ 342{
336 struct i2c_client *client = sd->priv; 343 struct i2c_client *client = sd->priv;
337 struct mt9m001 *mt9m001 = to_mt9m001(client); 344 struct mt9m001 *mt9m001 = to_mt9m001(client);
338 struct v4l2_pix_format *pix = &f->fmt.pix; 345 const struct mt9m001_datafmt *fmt;
339 346
340 v4l_bound_align_image(&pix->width, MT9M001_MIN_WIDTH, 347 v4l_bound_align_image(&mf->width, MT9M001_MIN_WIDTH,
341 MT9M001_MAX_WIDTH, 1, 348 MT9M001_MAX_WIDTH, 1,
342 &pix->height, MT9M001_MIN_HEIGHT + mt9m001->y_skip_top, 349 &mf->height, MT9M001_MIN_HEIGHT + mt9m001->y_skip_top,
343 MT9M001_MAX_HEIGHT + mt9m001->y_skip_top, 0, 0); 350 MT9M001_MAX_HEIGHT + mt9m001->y_skip_top, 0, 0);
344 351
345 if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8 || 352 if (mt9m001->fmts == mt9m001_colour_fmts)
346 pix->pixelformat == V4L2_PIX_FMT_SBGGR16) 353 mf->height = ALIGN(mf->height - 1, 2);
347 pix->height = ALIGN(pix->height - 1, 2); 354
355 fmt = mt9m001_find_datafmt(mf->code, mt9m001->fmts,
356 mt9m001->num_fmts);
357 if (!fmt) {
358 fmt = mt9m001->fmt;
359 mf->code = fmt->code;
360 }
361
362 mf->colorspace = fmt->colorspace;
348 363
349 return 0; 364 return 0;
350} 365}
@@ -608,11 +623,11 @@ static int mt9m001_video_probe(struct soc_camera_device *icd,
608 case 0x8411: 623 case 0x8411:
609 case 0x8421: 624 case 0x8421:
610 mt9m001->model = V4L2_IDENT_MT9M001C12ST; 625 mt9m001->model = V4L2_IDENT_MT9M001C12ST;
611 icd->formats = mt9m001_colour_formats; 626 mt9m001->fmts = mt9m001_colour_fmts;
612 break; 627 break;
613 case 0x8431: 628 case 0x8431:
614 mt9m001->model = V4L2_IDENT_MT9M001C12STM; 629 mt9m001->model = V4L2_IDENT_MT9M001C12STM;
615 icd->formats = mt9m001_monochrome_formats; 630 mt9m001->fmts = mt9m001_monochrome_fmts;
616 break; 631 break;
617 default: 632 default:
618 dev_err(&client->dev, 633 dev_err(&client->dev,
@@ -620,7 +635,7 @@ static int mt9m001_video_probe(struct soc_camera_device *icd,
620 return -ENODEV; 635 return -ENODEV;
621 } 636 }
622 637
623 icd->num_formats = 0; 638 mt9m001->num_fmts = 0;
624 639
625 /* 640 /*
626 * 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.
@@ -633,14 +648,14 @@ static int mt9m001_video_probe(struct soc_camera_device *icd,
633 flags = SOCAM_DATAWIDTH_10; 648 flags = SOCAM_DATAWIDTH_10;
634 649
635 if (flags & SOCAM_DATAWIDTH_10) 650 if (flags & SOCAM_DATAWIDTH_10)
636 icd->num_formats++; 651 mt9m001->num_fmts++;
637 else 652 else
638 icd->formats++; 653 mt9m001->fmts++;
639 654
640 if (flags & SOCAM_DATAWIDTH_8) 655 if (flags & SOCAM_DATAWIDTH_8)
641 icd->num_formats++; 656 mt9m001->num_fmts++;
642 657
643 mt9m001->fourcc = icd->formats->fourcc; 658 mt9m001->fmt = &mt9m001->fmts[0];
644 659
645 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,
646 data == 0x8431 ? "C12STM" : "C12ST"); 661 data == 0x8431 ? "C12STM" : "C12ST");
@@ -686,14 +701,28 @@ static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = {
686#endif 701#endif
687}; 702};
688 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
689static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = { 717static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = {
690 .s_stream = mt9m001_s_stream, 718 .s_stream = mt9m001_s_stream,
691 .s_fmt = mt9m001_s_fmt, 719 .s_mbus_fmt = mt9m001_s_fmt,
692 .g_fmt = mt9m001_g_fmt, 720 .g_mbus_fmt = mt9m001_g_fmt,
693 .try_fmt = mt9m001_try_fmt, 721 .try_mbus_fmt = mt9m001_try_fmt,
694 .s_crop = mt9m001_s_crop, 722 .s_crop = mt9m001_s_crop,
695 .g_crop = mt9m001_g_crop, 723 .g_crop = mt9m001_g_crop,
696 .cropcap = mt9m001_cropcap, 724 .cropcap = mt9m001_cropcap,
725 .enum_mbus_fmt = mt9m001_enum_fmt,
697}; 726};
698 727
699static struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = { 728static struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = {