diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2009-12-11 09:46:49 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-12-16 06:27:29 -0500 |
commit | 760697beca338599a65484389c7abbe54aedb664 (patch) | |
tree | 515735429d2240629a6f048ab1a7fefaf5299e46 /drivers/media/video/mt9m001.c | |
parent | 9a74251d8bee7a25fee89a0be3ccea73e01c1a05 (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.c | 141 |
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 | ||
51 | static const struct soc_camera_data_format mt9m001_colour_formats[] = { | 51 | /* MT9M001 has only one fixed colorspace per pixelcode */ |
52 | struct 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 */ | ||
58 | static 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 | |||
70 | static 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 | ||
69 | static const struct soc_camera_data_format mt9m001_monochrome_formats[] = { | 79 | static 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 | ||
82 | struct mt9m001 { | 85 | struct 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 | ||
293 | static int mt9m001_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 297 | static 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 | ||
308 | static int mt9m001_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 312 | static 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 | ||
334 | static int mt9m001_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 340 | static 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 | ||
704 | static 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 | |||
689 | static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = { | 717 | static 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 | ||
699 | static struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = { | 728 | static struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = { |