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/mt9v022.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/mt9v022.c')
-rw-r--r-- | drivers/media/video/mt9v022.c | 150 |
1 files changed, 90 insertions, 60 deletions
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index f60a9a107f20..91df7ec91fb6 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c | |||
@@ -64,41 +64,46 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\""); | |||
64 | #define MT9V022_COLUMN_SKIP 1 | 64 | #define MT9V022_COLUMN_SKIP 1 |
65 | #define MT9V022_ROW_SKIP 4 | 65 | #define MT9V022_ROW_SKIP 4 |
66 | 66 | ||
67 | static const struct soc_camera_data_format mt9v022_colour_formats[] = { | 67 | /* MT9V022 has only one fixed colorspace per pixelcode */ |
68 | struct mt9v022_datafmt { | ||
69 | enum v4l2_mbus_pixelcode code; | ||
70 | enum v4l2_colorspace colorspace; | ||
71 | }; | ||
72 | |||
73 | /* Find a data format by a pixel code in an array */ | ||
74 | static const struct mt9v022_datafmt *mt9v022_find_datafmt( | ||
75 | enum v4l2_mbus_pixelcode code, const struct mt9v022_datafmt *fmt, | ||
76 | int n) | ||
77 | { | ||
78 | int i; | ||
79 | for (i = 0; i < n; i++) | ||
80 | if (fmt[i].code == code) | ||
81 | return fmt + i; | ||
82 | |||
83 | return NULL; | ||
84 | } | ||
85 | |||
86 | static const struct mt9v022_datafmt mt9v022_colour_fmts[] = { | ||
68 | /* | 87 | /* |
69 | * Order important: first natively supported, | 88 | * Order important: first natively supported, |
70 | * second supported with a GPIO extender | 89 | * second supported with a GPIO extender |
71 | */ | 90 | */ |
72 | { | 91 | {V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB}, |
73 | .name = "Bayer (sRGB) 10 bit", | 92 | {V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB}, |
74 | .depth = 10, | ||
75 | .fourcc = V4L2_PIX_FMT_SBGGR16, | ||
76 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
77 | }, { | ||
78 | .name = "Bayer (sRGB) 8 bit", | ||
79 | .depth = 8, | ||
80 | .fourcc = V4L2_PIX_FMT_SBGGR8, | ||
81 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
82 | } | ||
83 | }; | 93 | }; |
84 | 94 | ||
85 | static const struct soc_camera_data_format mt9v022_monochrome_formats[] = { | 95 | static const struct mt9v022_datafmt mt9v022_monochrome_fmts[] = { |
86 | /* Order important - see above */ | 96 | /* Order important - see above */ |
87 | { | 97 | {V4L2_MBUS_FMT_Y10_1X10, V4L2_COLORSPACE_JPEG}, |
88 | .name = "Monochrome 10 bit", | 98 | {V4L2_MBUS_FMT_GREY8_1X8, V4L2_COLORSPACE_JPEG}, |
89 | .depth = 10, | ||
90 | .fourcc = V4L2_PIX_FMT_Y16, | ||
91 | }, { | ||
92 | .name = "Monochrome 8 bit", | ||
93 | .depth = 8, | ||
94 | .fourcc = V4L2_PIX_FMT_GREY, | ||
95 | }, | ||
96 | }; | 99 | }; |
97 | 100 | ||
98 | struct mt9v022 { | 101 | struct mt9v022 { |
99 | struct v4l2_subdev subdev; | 102 | struct v4l2_subdev subdev; |
100 | struct v4l2_rect rect; /* Sensor window */ | 103 | struct v4l2_rect rect; /* Sensor window */ |
101 | __u32 fourcc; | 104 | const struct mt9v022_datafmt *fmt; |
105 | const struct mt9v022_datafmt *fmts; | ||
106 | int num_fmts; | ||
102 | int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ | 107 | int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ |
103 | u16 chip_control; | 108 | u16 chip_control; |
104 | unsigned short y_skip_top; /* Lines to skip at the top */ | 109 | unsigned short y_skip_top; /* Lines to skip at the top */ |
@@ -275,8 +280,7 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | |||
275 | int ret; | 280 | int ret; |
276 | 281 | ||
277 | /* Bayer format - even size lengths */ | 282 | /* Bayer format - even size lengths */ |
278 | if (mt9v022->fourcc == V4L2_PIX_FMT_SBGGR8 || | 283 | if (mt9v022->fmts == mt9v022_colour_fmts) { |
279 | mt9v022->fourcc == V4L2_PIX_FMT_SBGGR16) { | ||
280 | rect.width = ALIGN(rect.width, 2); | 284 | rect.width = ALIGN(rect.width, 2); |
281 | rect.height = ALIGN(rect.height, 2); | 285 | rect.height = ALIGN(rect.height, 2); |
282 | /* Let the user play with the starting pixel */ | 286 | /* Let the user play with the starting pixel */ |
@@ -354,32 +358,32 @@ static int mt9v022_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) | |||
354 | return 0; | 358 | return 0; |
355 | } | 359 | } |
356 | 360 | ||
357 | static int mt9v022_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 361 | static int mt9v022_g_fmt(struct v4l2_subdev *sd, |
362 | struct v4l2_mbus_framefmt *mf) | ||
358 | { | 363 | { |
359 | struct i2c_client *client = sd->priv; | 364 | struct i2c_client *client = sd->priv; |
360 | struct mt9v022 *mt9v022 = to_mt9v022(client); | 365 | struct mt9v022 *mt9v022 = to_mt9v022(client); |
361 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
362 | 366 | ||
363 | pix->width = mt9v022->rect.width; | 367 | mf->width = mt9v022->rect.width; |
364 | pix->height = mt9v022->rect.height; | 368 | mf->height = mt9v022->rect.height; |
365 | pix->pixelformat = mt9v022->fourcc; | 369 | mf->code = mt9v022->fmt->code; |
366 | pix->field = V4L2_FIELD_NONE; | 370 | mf->colorspace = mt9v022->fmt->colorspace; |
367 | pix->colorspace = V4L2_COLORSPACE_SRGB; | 371 | mf->field = V4L2_FIELD_NONE; |
368 | 372 | ||
369 | return 0; | 373 | return 0; |
370 | } | 374 | } |
371 | 375 | ||
372 | static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 376 | static int mt9v022_s_fmt(struct v4l2_subdev *sd, |
377 | struct v4l2_mbus_framefmt *mf) | ||
373 | { | 378 | { |
374 | struct i2c_client *client = sd->priv; | 379 | struct i2c_client *client = sd->priv; |
375 | struct mt9v022 *mt9v022 = to_mt9v022(client); | 380 | struct mt9v022 *mt9v022 = to_mt9v022(client); |
376 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
377 | struct v4l2_crop a = { | 381 | struct v4l2_crop a = { |
378 | .c = { | 382 | .c = { |
379 | .left = mt9v022->rect.left, | 383 | .left = mt9v022->rect.left, |
380 | .top = mt9v022->rect.top, | 384 | .top = mt9v022->rect.top, |
381 | .width = pix->width, | 385 | .width = mf->width, |
382 | .height = pix->height, | 386 | .height = mf->height, |
383 | }, | 387 | }, |
384 | }; | 388 | }; |
385 | int ret; | 389 | int ret; |
@@ -388,14 +392,14 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | |||
388 | * The caller provides a supported format, as verified per call to | 392 | * The caller provides a supported format, as verified per call to |
389 | * icd->try_fmt(), datawidth is from our supported format list | 393 | * icd->try_fmt(), datawidth is from our supported format list |
390 | */ | 394 | */ |
391 | switch (pix->pixelformat) { | 395 | switch (mf->code) { |
392 | case V4L2_PIX_FMT_GREY: | 396 | case V4L2_MBUS_FMT_GREY8_1X8: |
393 | case V4L2_PIX_FMT_Y16: | 397 | case V4L2_MBUS_FMT_Y10_1X10: |
394 | if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM) | 398 | if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM) |
395 | return -EINVAL; | 399 | return -EINVAL; |
396 | break; | 400 | break; |
397 | case V4L2_PIX_FMT_SBGGR8: | 401 | case V4L2_MBUS_FMT_SBGGR8_1X8: |
398 | case V4L2_PIX_FMT_SBGGR16: | 402 | case V4L2_MBUS_FMT_SBGGR10_1X10: |
399 | if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC) | 403 | if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC) |
400 | return -EINVAL; | 404 | return -EINVAL; |
401 | break; | 405 | break; |
@@ -409,27 +413,39 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | |||
409 | /* No support for scaling on this camera, just crop. */ | 413 | /* No support for scaling on this camera, just crop. */ |
410 | ret = mt9v022_s_crop(sd, &a); | 414 | ret = mt9v022_s_crop(sd, &a); |
411 | if (!ret) { | 415 | if (!ret) { |
412 | pix->width = mt9v022->rect.width; | 416 | mf->width = mt9v022->rect.width; |
413 | pix->height = mt9v022->rect.height; | 417 | mf->height = mt9v022->rect.height; |
414 | mt9v022->fourcc = pix->pixelformat; | 418 | mt9v022->fmt = mt9v022_find_datafmt(mf->code, |
419 | mt9v022->fmts, mt9v022->num_fmts); | ||
420 | mf->colorspace = mt9v022->fmt->colorspace; | ||
415 | } | 421 | } |
416 | 422 | ||
417 | return ret; | 423 | return ret; |
418 | } | 424 | } |
419 | 425 | ||
420 | static int mt9v022_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 426 | static int mt9v022_try_fmt(struct v4l2_subdev *sd, |
427 | struct v4l2_mbus_framefmt *mf) | ||
421 | { | 428 | { |
422 | struct i2c_client *client = sd->priv; | 429 | struct i2c_client *client = sd->priv; |
423 | struct mt9v022 *mt9v022 = to_mt9v022(client); | 430 | struct mt9v022 *mt9v022 = to_mt9v022(client); |
424 | struct v4l2_pix_format *pix = &f->fmt.pix; | 431 | const struct mt9v022_datafmt *fmt; |
425 | int align = pix->pixelformat == V4L2_PIX_FMT_SBGGR8 || | 432 | int align = mf->code == V4L2_MBUS_FMT_SBGGR8_1X8 || |
426 | pix->pixelformat == V4L2_PIX_FMT_SBGGR16; | 433 | mf->code == V4L2_MBUS_FMT_SBGGR10_1X10; |
427 | 434 | ||
428 | v4l_bound_align_image(&pix->width, MT9V022_MIN_WIDTH, | 435 | v4l_bound_align_image(&mf->width, MT9V022_MIN_WIDTH, |
429 | MT9V022_MAX_WIDTH, align, | 436 | MT9V022_MAX_WIDTH, align, |
430 | &pix->height, MT9V022_MIN_HEIGHT + mt9v022->y_skip_top, | 437 | &mf->height, MT9V022_MIN_HEIGHT + mt9v022->y_skip_top, |
431 | MT9V022_MAX_HEIGHT + mt9v022->y_skip_top, align, 0); | 438 | MT9V022_MAX_HEIGHT + mt9v022->y_skip_top, align, 0); |
432 | 439 | ||
440 | fmt = mt9v022_find_datafmt(mf->code, mt9v022->fmts, | ||
441 | mt9v022->num_fmts); | ||
442 | if (!fmt) { | ||
443 | fmt = mt9v022->fmt; | ||
444 | mf->code = fmt->code; | ||
445 | } | ||
446 | |||
447 | mf->colorspace = fmt->colorspace; | ||
448 | |||
433 | return 0; | 449 | return 0; |
434 | } | 450 | } |
435 | 451 | ||
@@ -749,17 +765,17 @@ static int mt9v022_video_probe(struct soc_camera_device *icd, | |||
749 | !strcmp("color", sensor_type))) { | 765 | !strcmp("color", sensor_type))) { |
750 | ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11); | 766 | ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11); |
751 | mt9v022->model = V4L2_IDENT_MT9V022IX7ATC; | 767 | mt9v022->model = V4L2_IDENT_MT9V022IX7ATC; |
752 | icd->formats = mt9v022_colour_formats; | 768 | mt9v022->fmts = mt9v022_colour_fmts; |
753 | } else { | 769 | } else { |
754 | ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 0x11); | 770 | ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 0x11); |
755 | mt9v022->model = V4L2_IDENT_MT9V022IX7ATM; | 771 | mt9v022->model = V4L2_IDENT_MT9V022IX7ATM; |
756 | icd->formats = mt9v022_monochrome_formats; | 772 | mt9v022->fmts = mt9v022_monochrome_fmts; |
757 | } | 773 | } |
758 | 774 | ||
759 | if (ret < 0) | 775 | if (ret < 0) |
760 | goto ei2c; | 776 | goto ei2c; |
761 | 777 | ||
762 | icd->num_formats = 0; | 778 | mt9v022->num_fmts = 0; |
763 | 779 | ||
764 | /* | 780 | /* |
765 | * This is a 10bit sensor, so by default we only allow 10bit. | 781 | * This is a 10bit sensor, so by default we only allow 10bit. |
@@ -772,14 +788,14 @@ static int mt9v022_video_probe(struct soc_camera_device *icd, | |||
772 | flags = SOCAM_DATAWIDTH_10; | 788 | flags = SOCAM_DATAWIDTH_10; |
773 | 789 | ||
774 | if (flags & SOCAM_DATAWIDTH_10) | 790 | if (flags & SOCAM_DATAWIDTH_10) |
775 | icd->num_formats++; | 791 | mt9v022->num_fmts++; |
776 | else | 792 | else |
777 | icd->formats++; | 793 | mt9v022->fmts++; |
778 | 794 | ||
779 | if (flags & SOCAM_DATAWIDTH_8) | 795 | if (flags & SOCAM_DATAWIDTH_8) |
780 | icd->num_formats++; | 796 | mt9v022->num_fmts++; |
781 | 797 | ||
782 | mt9v022->fourcc = icd->formats->fourcc; | 798 | mt9v022->fmt = &mt9v022->fmts[0]; |
783 | 799 | ||
784 | dev_info(&client->dev, "Detected a MT9V022 chip ID %x, %s sensor\n", | 800 | dev_info(&client->dev, "Detected a MT9V022 chip ID %x, %s sensor\n", |
785 | data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ? | 801 | data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ? |
@@ -823,14 +839,28 @@ static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = { | |||
823 | #endif | 839 | #endif |
824 | }; | 840 | }; |
825 | 841 | ||
842 | static int mt9v022_enum_fmt(struct v4l2_subdev *sd, int index, | ||
843 | enum v4l2_mbus_pixelcode *code) | ||
844 | { | ||
845 | struct i2c_client *client = sd->priv; | ||
846 | struct mt9v022 *mt9v022 = to_mt9v022(client); | ||
847 | |||
848 | if ((unsigned int)index >= mt9v022->num_fmts) | ||
849 | return -EINVAL; | ||
850 | |||
851 | *code = mt9v022->fmts[index].code; | ||
852 | return 0; | ||
853 | } | ||
854 | |||
826 | static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = { | 855 | static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = { |
827 | .s_stream = mt9v022_s_stream, | 856 | .s_stream = mt9v022_s_stream, |
828 | .s_fmt = mt9v022_s_fmt, | 857 | .s_mbus_fmt = mt9v022_s_fmt, |
829 | .g_fmt = mt9v022_g_fmt, | 858 | .g_mbus_fmt = mt9v022_g_fmt, |
830 | .try_fmt = mt9v022_try_fmt, | 859 | .try_mbus_fmt = mt9v022_try_fmt, |
831 | .s_crop = mt9v022_s_crop, | 860 | .s_crop = mt9v022_s_crop, |
832 | .g_crop = mt9v022_g_crop, | 861 | .g_crop = mt9v022_g_crop, |
833 | .cropcap = mt9v022_cropcap, | 862 | .cropcap = mt9v022_cropcap, |
863 | .enum_mbus_fmt = mt9v022_enum_fmt, | ||
834 | }; | 864 | }; |
835 | 865 | ||
836 | static struct v4l2_subdev_sensor_ops mt9v022_subdev_sensor_ops = { | 866 | static struct v4l2_subdev_sensor_ops mt9v022_subdev_sensor_ops = { |