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/mx3_camera.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/mx3_camera.c')
-rw-r--r-- | drivers/media/video/mx3_camera.c | 278 |
1 files changed, 161 insertions, 117 deletions
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c index ae7d48324493..bd297f567dc7 100644 --- a/drivers/media/video/mx3_camera.c +++ b/drivers/media/video/mx3_camera.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <media/v4l2-dev.h> | 23 | #include <media/v4l2-dev.h> |
24 | #include <media/videobuf-dma-contig.h> | 24 | #include <media/videobuf-dma-contig.h> |
25 | #include <media/soc_camera.h> | 25 | #include <media/soc_camera.h> |
26 | #include <media/soc_mediabus.h> | ||
26 | 27 | ||
27 | #include <mach/ipu.h> | 28 | #include <mach/ipu.h> |
28 | #include <mach/mx3_camera.h> | 29 | #include <mach/mx3_camera.h> |
@@ -63,7 +64,7 @@ | |||
63 | struct mx3_camera_buffer { | 64 | struct mx3_camera_buffer { |
64 | /* common v4l buffer stuff -- must be first */ | 65 | /* common v4l buffer stuff -- must be first */ |
65 | struct videobuf_buffer vb; | 66 | struct videobuf_buffer vb; |
66 | const struct soc_camera_data_format *fmt; | 67 | enum v4l2_mbus_pixelcode code; |
67 | 68 | ||
68 | /* One descriptot per scatterlist (per frame) */ | 69 | /* One descriptot per scatterlist (per frame) */ |
69 | struct dma_async_tx_descriptor *txd; | 70 | struct dma_async_tx_descriptor *txd; |
@@ -118,8 +119,6 @@ struct dma_chan_request { | |||
118 | enum ipu_channel id; | 119 | enum ipu_channel id; |
119 | }; | 120 | }; |
120 | 121 | ||
121 | static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt); | ||
122 | |||
123 | static u32 csi_reg_read(struct mx3_camera_dev *mx3, off_t reg) | 122 | static u32 csi_reg_read(struct mx3_camera_dev *mx3, off_t reg) |
124 | { | 123 | { |
125 | return __raw_readl(mx3->base + reg); | 124 | return __raw_readl(mx3->base + reg); |
@@ -211,17 +210,16 @@ static int mx3_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, | |||
211 | struct soc_camera_device *icd = vq->priv_data; | 210 | struct soc_camera_device *icd = vq->priv_data; |
212 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 211 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
213 | struct mx3_camera_dev *mx3_cam = ici->priv; | 212 | struct mx3_camera_dev *mx3_cam = ici->priv; |
214 | /* | 213 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, |
215 | * bits-per-pixel (depth) as specified in camera's pixel format does | 214 | icd->current_fmt->host_fmt); |
216 | * not necessarily match what the camera interface writes to RAM, but | 215 | |
217 | * it should be good enough for now. | 216 | if (bytes_per_line < 0) |
218 | */ | 217 | return bytes_per_line; |
219 | unsigned int bpp = DIV_ROUND_UP(icd->current_fmt->depth, 8); | ||
220 | 218 | ||
221 | if (!mx3_cam->idmac_channel[0]) | 219 | if (!mx3_cam->idmac_channel[0]) |
222 | return -EINVAL; | 220 | return -EINVAL; |
223 | 221 | ||
224 | *size = icd->user_width * icd->user_height * bpp; | 222 | *size = bytes_per_line * icd->user_height; |
225 | 223 | ||
226 | if (!*count) | 224 | if (!*count) |
227 | *count = 32; | 225 | *count = 32; |
@@ -241,21 +239,26 @@ static int mx3_videobuf_prepare(struct videobuf_queue *vq, | |||
241 | struct mx3_camera_dev *mx3_cam = ici->priv; | 239 | struct mx3_camera_dev *mx3_cam = ici->priv; |
242 | struct mx3_camera_buffer *buf = | 240 | struct mx3_camera_buffer *buf = |
243 | container_of(vb, struct mx3_camera_buffer, vb); | 241 | container_of(vb, struct mx3_camera_buffer, vb); |
244 | /* current_fmt _must_ always be set */ | 242 | size_t new_size; |
245 | size_t new_size = icd->user_width * icd->user_height * | ||
246 | ((icd->current_fmt->depth + 7) >> 3); | ||
247 | int ret; | 243 | int ret; |
244 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, | ||
245 | icd->current_fmt->host_fmt); | ||
246 | |||
247 | if (bytes_per_line < 0) | ||
248 | return bytes_per_line; | ||
249 | |||
250 | new_size = bytes_per_line * icd->user_height; | ||
248 | 251 | ||
249 | /* | 252 | /* |
250 | * I think, in buf_prepare you only have to protect global data, | 253 | * I think, in buf_prepare you only have to protect global data, |
251 | * the actual buffer is yours | 254 | * the actual buffer is yours |
252 | */ | 255 | */ |
253 | 256 | ||
254 | if (buf->fmt != icd->current_fmt || | 257 | if (buf->code != icd->current_fmt->code || |
255 | vb->width != icd->user_width || | 258 | vb->width != icd->user_width || |
256 | vb->height != icd->user_height || | 259 | vb->height != icd->user_height || |
257 | vb->field != field) { | 260 | vb->field != field) { |
258 | buf->fmt = icd->current_fmt; | 261 | buf->code = icd->current_fmt->code; |
259 | vb->width = icd->user_width; | 262 | vb->width = icd->user_width; |
260 | vb->height = icd->user_height; | 263 | vb->height = icd->user_height; |
261 | vb->field = field; | 264 | vb->field = field; |
@@ -348,13 +351,13 @@ static void mx3_videobuf_queue(struct videobuf_queue *vq, | |||
348 | struct dma_async_tx_descriptor *txd = buf->txd; | 351 | struct dma_async_tx_descriptor *txd = buf->txd; |
349 | struct idmac_channel *ichan = to_idmac_chan(txd->chan); | 352 | struct idmac_channel *ichan = to_idmac_chan(txd->chan); |
350 | struct idmac_video_param *video = &ichan->params.video; | 353 | struct idmac_video_param *video = &ichan->params.video; |
351 | const struct soc_camera_data_format *data_fmt = icd->current_fmt; | ||
352 | dma_cookie_t cookie; | 354 | dma_cookie_t cookie; |
355 | u32 fourcc = icd->current_fmt->host_fmt->fourcc; | ||
353 | 356 | ||
354 | BUG_ON(!irqs_disabled()); | 357 | BUG_ON(!irqs_disabled()); |
355 | 358 | ||
356 | /* This is the configuration of one sg-element */ | 359 | /* This is the configuration of one sg-element */ |
357 | video->out_pixel_fmt = fourcc_to_ipu_pix(data_fmt->fourcc); | 360 | video->out_pixel_fmt = fourcc_to_ipu_pix(fourcc); |
358 | video->out_width = icd->user_width; | 361 | video->out_width = icd->user_width; |
359 | video->out_height = icd->user_height; | 362 | video->out_height = icd->user_height; |
360 | video->out_stride = icd->user_width; | 363 | video->out_stride = icd->user_width; |
@@ -568,28 +571,33 @@ static int test_platform_param(struct mx3_camera_dev *mx3_cam, | |||
568 | * If requested data width is supported by the platform, use it or any | 571 | * If requested data width is supported by the platform, use it or any |
569 | * possible lower value - i.MX31 is smart enough to schift bits | 572 | * possible lower value - i.MX31 is smart enough to schift bits |
570 | */ | 573 | */ |
574 | if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15) | ||
575 | *flags |= SOCAM_DATAWIDTH_15 | SOCAM_DATAWIDTH_10 | | ||
576 | SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_4; | ||
577 | else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10) | ||
578 | *flags |= SOCAM_DATAWIDTH_10 | SOCAM_DATAWIDTH_8 | | ||
579 | SOCAM_DATAWIDTH_4; | ||
580 | else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8) | ||
581 | *flags |= SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_4; | ||
582 | else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4) | ||
583 | *flags |= SOCAM_DATAWIDTH_4; | ||
584 | |||
571 | switch (buswidth) { | 585 | switch (buswidth) { |
572 | case 15: | 586 | case 15: |
573 | if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15)) | 587 | if (!(*flags & SOCAM_DATAWIDTH_15)) |
574 | return -EINVAL; | 588 | return -EINVAL; |
575 | *flags |= SOCAM_DATAWIDTH_15 | SOCAM_DATAWIDTH_10 | | ||
576 | SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_4; | ||
577 | break; | 589 | break; |
578 | case 10: | 590 | case 10: |
579 | if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10)) | 591 | if (!(*flags & SOCAM_DATAWIDTH_10)) |
580 | return -EINVAL; | 592 | return -EINVAL; |
581 | *flags |= SOCAM_DATAWIDTH_10 | SOCAM_DATAWIDTH_8 | | ||
582 | SOCAM_DATAWIDTH_4; | ||
583 | break; | 593 | break; |
584 | case 8: | 594 | case 8: |
585 | if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8)) | 595 | if (!(*flags & SOCAM_DATAWIDTH_8)) |
586 | return -EINVAL; | 596 | return -EINVAL; |
587 | *flags |= SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_4; | ||
588 | break; | 597 | break; |
589 | case 4: | 598 | case 4: |
590 | if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4)) | 599 | if (!(*flags & SOCAM_DATAWIDTH_4)) |
591 | return -EINVAL; | 600 | return -EINVAL; |
592 | *flags |= SOCAM_DATAWIDTH_4; | ||
593 | break; | 601 | break; |
594 | default: | 602 | default: |
595 | dev_warn(mx3_cam->soc_host.v4l2_dev.dev, | 603 | dev_warn(mx3_cam->soc_host.v4l2_dev.dev, |
@@ -638,91 +646,92 @@ static bool chan_filter(struct dma_chan *chan, void *arg) | |||
638 | pdata->dma_dev == chan->device->dev; | 646 | pdata->dma_dev == chan->device->dev; |
639 | } | 647 | } |
640 | 648 | ||
641 | static const struct soc_camera_data_format mx3_camera_formats[] = { | 649 | static const struct soc_mbus_pixelfmt mx3_camera_formats[] = { |
642 | { | 650 | { |
643 | .name = "Bayer (sRGB) 8 bit", | 651 | .fourcc = V4L2_PIX_FMT_SBGGR8, |
644 | .depth = 8, | 652 | .name = "Bayer BGGR (sRGB) 8 bit", |
645 | .fourcc = V4L2_PIX_FMT_SBGGR8, | 653 | .bits_per_sample = 8, |
646 | .colorspace = V4L2_COLORSPACE_SRGB, | 654 | .packing = SOC_MBUS_PACKING_NONE, |
655 | .order = SOC_MBUS_ORDER_LE, | ||
647 | }, { | 656 | }, { |
648 | .name = "Monochrome 8 bit", | 657 | .fourcc = V4L2_PIX_FMT_GREY, |
649 | .depth = 8, | 658 | .name = "Monochrome 8 bit", |
650 | .fourcc = V4L2_PIX_FMT_GREY, | 659 | .bits_per_sample = 8, |
651 | .colorspace = V4L2_COLORSPACE_JPEG, | 660 | .packing = SOC_MBUS_PACKING_NONE, |
661 | .order = SOC_MBUS_ORDER_LE, | ||
652 | }, | 662 | }, |
653 | }; | 663 | }; |
654 | 664 | ||
655 | static bool buswidth_supported(struct soc_camera_host *ici, int depth) | 665 | /* This will be corrected as we get more formats */ |
666 | static bool mx3_camera_packing_supported(const struct soc_mbus_pixelfmt *fmt) | ||
656 | { | 667 | { |
657 | struct mx3_camera_dev *mx3_cam = ici->priv; | 668 | return fmt->packing == SOC_MBUS_PACKING_NONE || |
658 | 669 | (fmt->bits_per_sample == 8 && | |
659 | switch (depth) { | 670 | fmt->packing == SOC_MBUS_PACKING_2X8_PADHI) || |
660 | case 4: | 671 | (fmt->bits_per_sample > 8 && |
661 | return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4); | 672 | fmt->packing == SOC_MBUS_PACKING_EXTEND16); |
662 | case 8: | ||
663 | return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8); | ||
664 | case 10: | ||
665 | return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10); | ||
666 | case 15: | ||
667 | return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15); | ||
668 | } | ||
669 | return false; | ||
670 | } | 673 | } |
671 | 674 | ||
672 | static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx, | 675 | static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx, |
673 | struct soc_camera_format_xlate *xlate) | 676 | struct soc_camera_format_xlate *xlate) |
674 | { | 677 | { |
675 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 678 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
676 | int formats = 0, buswidth, ret; | 679 | struct device *dev = icd->dev.parent; |
680 | int formats = 0, ret; | ||
681 | enum v4l2_mbus_pixelcode code; | ||
682 | const struct soc_mbus_pixelfmt *fmt; | ||
677 | 683 | ||
678 | buswidth = icd->formats[idx].depth; | 684 | ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code); |
685 | if (ret < 0) | ||
686 | /* No more formats */ | ||
687 | return 0; | ||
679 | 688 | ||
680 | if (!buswidth_supported(ici, buswidth)) | 689 | fmt = soc_mbus_get_fmtdesc(code); |
690 | if (!fmt) { | ||
691 | dev_err(icd->dev.parent, | ||
692 | "Invalid format code #%d: %d\n", idx, code); | ||
681 | return 0; | 693 | return 0; |
694 | } | ||
682 | 695 | ||
683 | ret = mx3_camera_try_bus_param(icd, buswidth); | 696 | /* This also checks support for the requested bits-per-sample */ |
697 | ret = mx3_camera_try_bus_param(icd, fmt->bits_per_sample); | ||
684 | if (ret < 0) | 698 | if (ret < 0) |
685 | return 0; | 699 | return 0; |
686 | 700 | ||
687 | switch (icd->formats[idx].fourcc) { | 701 | switch (code) { |
688 | case V4L2_PIX_FMT_SGRBG10: | 702 | case V4L2_MBUS_FMT_SBGGR10_1X10: |
689 | formats++; | 703 | formats++; |
690 | if (xlate) { | 704 | if (xlate) { |
691 | xlate->host_fmt = &mx3_camera_formats[0]; | 705 | xlate->host_fmt = &mx3_camera_formats[0]; |
692 | xlate->cam_fmt = icd->formats + idx; | 706 | xlate->code = code; |
693 | xlate->buswidth = buswidth; | ||
694 | xlate++; | 707 | xlate++; |
695 | dev_dbg(icd->dev.parent, | 708 | dev_dbg(dev, "Providing format %s using code %d\n", |
696 | "Providing format %s using %s\n", | 709 | mx3_camera_formats[0].name, code); |
697 | mx3_camera_formats[0].name, | ||
698 | icd->formats[idx].name); | ||
699 | } | 710 | } |
700 | goto passthrough; | 711 | break; |
701 | case V4L2_PIX_FMT_Y16: | 712 | case V4L2_MBUS_FMT_Y10_1X10: |
702 | formats++; | 713 | formats++; |
703 | if (xlate) { | 714 | if (xlate) { |
704 | xlate->host_fmt = &mx3_camera_formats[1]; | 715 | xlate->host_fmt = &mx3_camera_formats[1]; |
705 | xlate->cam_fmt = icd->formats + idx; | 716 | xlate->code = code; |
706 | xlate->buswidth = buswidth; | ||
707 | xlate++; | 717 | xlate++; |
708 | dev_dbg(icd->dev.parent, | 718 | dev_dbg(dev, "Providing format %s using code %d\n", |
709 | "Providing format %s using %s\n", | 719 | mx3_camera_formats[1].name, code); |
710 | mx3_camera_formats[0].name, | ||
711 | icd->formats[idx].name); | ||
712 | } | 720 | } |
721 | break; | ||
713 | default: | 722 | default: |
714 | passthrough: | 723 | if (!mx3_camera_packing_supported(fmt)) |
715 | /* Generic pass-through */ | 724 | return 0; |
716 | formats++; | 725 | } |
717 | if (xlate) { | 726 | |
718 | xlate->host_fmt = icd->formats + idx; | 727 | /* Generic pass-through */ |
719 | xlate->cam_fmt = icd->formats + idx; | 728 | formats++; |
720 | xlate->buswidth = buswidth; | 729 | if (xlate) { |
721 | xlate++; | 730 | xlate->host_fmt = fmt; |
722 | dev_dbg(icd->dev.parent, | 731 | xlate->code = code; |
723 | "Providing format %s in pass-through mode\n", | 732 | xlate++; |
724 | icd->formats[idx].name); | 733 | dev_dbg(dev, "Providing format %x in pass-through mode\n", |
725 | } | 734 | xlate->host_fmt->fourcc); |
726 | } | 735 | } |
727 | 736 | ||
728 | return formats; | 737 | return formats; |
@@ -806,8 +815,7 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd, | |||
806 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 815 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
807 | struct mx3_camera_dev *mx3_cam = ici->priv; | 816 | struct mx3_camera_dev *mx3_cam = ici->priv; |
808 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 817 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
809 | struct v4l2_format f = {.type = V4L2_BUF_TYPE_VIDEO_CAPTURE}; | 818 | struct v4l2_mbus_framefmt mf; |
810 | struct v4l2_pix_format *pix = &f.fmt.pix; | ||
811 | int ret; | 819 | int ret; |
812 | 820 | ||
813 | soc_camera_limit_side(&rect->left, &rect->width, 0, 2, 4096); | 821 | soc_camera_limit_side(&rect->left, &rect->width, 0, 2, 4096); |
@@ -818,19 +826,19 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd, | |||
818 | return ret; | 826 | return ret; |
819 | 827 | ||
820 | /* The capture device might have changed its output */ | 828 | /* The capture device might have changed its output */ |
821 | ret = v4l2_subdev_call(sd, video, g_fmt, &f); | 829 | ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); |
822 | if (ret < 0) | 830 | if (ret < 0) |
823 | return ret; | 831 | return ret; |
824 | 832 | ||
825 | if (pix->width & 7) { | 833 | if (mf.width & 7) { |
826 | /* Ouch! We can only handle 8-byte aligned width... */ | 834 | /* Ouch! We can only handle 8-byte aligned width... */ |
827 | stride_align(&pix->width); | 835 | stride_align(&mf.width); |
828 | ret = v4l2_subdev_call(sd, video, s_fmt, &f); | 836 | ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf); |
829 | if (ret < 0) | 837 | if (ret < 0) |
830 | return ret; | 838 | return ret; |
831 | } | 839 | } |
832 | 840 | ||
833 | if (pix->width != icd->user_width || pix->height != icd->user_height) { | 841 | if (mf.width != icd->user_width || mf.height != icd->user_height) { |
834 | /* | 842 | /* |
835 | * We now know pixel formats and can decide upon DMA-channel(s) | 843 | * We now know pixel formats and can decide upon DMA-channel(s) |
836 | * So far only direct camera-to-memory is supported | 844 | * So far only direct camera-to-memory is supported |
@@ -841,14 +849,14 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd, | |||
841 | return ret; | 849 | return ret; |
842 | } | 850 | } |
843 | 851 | ||
844 | configure_geometry(mx3_cam, pix->width, pix->height); | 852 | configure_geometry(mx3_cam, mf.width, mf.height); |
845 | } | 853 | } |
846 | 854 | ||
847 | dev_dbg(icd->dev.parent, "Sensor cropped %dx%d\n", | 855 | dev_dbg(icd->dev.parent, "Sensor cropped %dx%d\n", |
848 | pix->width, pix->height); | 856 | mf.width, mf.height); |
849 | 857 | ||
850 | icd->user_width = pix->width; | 858 | icd->user_width = mf.width; |
851 | icd->user_height = pix->height; | 859 | icd->user_height = mf.height; |
852 | 860 | ||
853 | return ret; | 861 | return ret; |
854 | } | 862 | } |
@@ -861,6 +869,7 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, | |||
861 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 869 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
862 | const struct soc_camera_format_xlate *xlate; | 870 | const struct soc_camera_format_xlate *xlate; |
863 | struct v4l2_pix_format *pix = &f->fmt.pix; | 871 | struct v4l2_pix_format *pix = &f->fmt.pix; |
872 | struct v4l2_mbus_framefmt mf; | ||
864 | int ret; | 873 | int ret; |
865 | 874 | ||
866 | xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); | 875 | xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); |
@@ -885,11 +894,24 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, | |||
885 | 894 | ||
886 | configure_geometry(mx3_cam, pix->width, pix->height); | 895 | configure_geometry(mx3_cam, pix->width, pix->height); |
887 | 896 | ||
888 | ret = v4l2_subdev_call(sd, video, s_fmt, f); | 897 | mf.width = pix->width; |
889 | if (!ret) { | 898 | mf.height = pix->height; |
890 | icd->buswidth = xlate->buswidth; | 899 | mf.field = pix->field; |
891 | icd->current_fmt = xlate->host_fmt; | 900 | mf.colorspace = pix->colorspace; |
892 | } | 901 | mf.code = xlate->code; |
902 | |||
903 | ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf); | ||
904 | if (ret < 0) | ||
905 | return ret; | ||
906 | |||
907 | if (mf.code != xlate->code) | ||
908 | return -EINVAL; | ||
909 | |||
910 | pix->width = mf.width; | ||
911 | pix->height = mf.height; | ||
912 | pix->field = mf.field; | ||
913 | pix->colorspace = mf.colorspace; | ||
914 | icd->current_fmt = xlate; | ||
893 | 915 | ||
894 | dev_dbg(icd->dev.parent, "Sensor set %dx%d\n", pix->width, pix->height); | 916 | dev_dbg(icd->dev.parent, "Sensor set %dx%d\n", pix->width, pix->height); |
895 | 917 | ||
@@ -902,8 +924,8 @@ static int mx3_camera_try_fmt(struct soc_camera_device *icd, | |||
902 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 924 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
903 | const struct soc_camera_format_xlate *xlate; | 925 | const struct soc_camera_format_xlate *xlate; |
904 | struct v4l2_pix_format *pix = &f->fmt.pix; | 926 | struct v4l2_pix_format *pix = &f->fmt.pix; |
927 | struct v4l2_mbus_framefmt mf; | ||
905 | __u32 pixfmt = pix->pixelformat; | 928 | __u32 pixfmt = pix->pixelformat; |
906 | enum v4l2_field field; | ||
907 | int ret; | 929 | int ret; |
908 | 930 | ||
909 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); | 931 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); |
@@ -918,23 +940,37 @@ static int mx3_camera_try_fmt(struct soc_camera_device *icd, | |||
918 | if (pix->width > 4096) | 940 | if (pix->width > 4096) |
919 | pix->width = 4096; | 941 | pix->width = 4096; |
920 | 942 | ||
921 | pix->bytesperline = pix->width * | 943 | pix->bytesperline = soc_mbus_bytes_per_line(pix->width, |
922 | DIV_ROUND_UP(xlate->host_fmt->depth, 8); | 944 | xlate->host_fmt); |
945 | if (pix->bytesperline < 0) | ||
946 | return pix->bytesperline; | ||
923 | pix->sizeimage = pix->height * pix->bytesperline; | 947 | pix->sizeimage = pix->height * pix->bytesperline; |
924 | 948 | ||
925 | /* camera has to see its format, but the user the original one */ | ||
926 | pix->pixelformat = xlate->cam_fmt->fourcc; | ||
927 | /* limit to sensor capabilities */ | 949 | /* limit to sensor capabilities */ |
928 | ret = v4l2_subdev_call(sd, video, try_fmt, f); | 950 | mf.width = pix->width; |
929 | pix->pixelformat = xlate->host_fmt->fourcc; | 951 | mf.height = pix->height; |
952 | mf.field = pix->field; | ||
953 | mf.colorspace = pix->colorspace; | ||
954 | mf.code = xlate->code; | ||
930 | 955 | ||
931 | field = pix->field; | 956 | ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf); |
957 | if (ret < 0) | ||
958 | return ret; | ||
932 | 959 | ||
933 | if (field == V4L2_FIELD_ANY) { | 960 | pix->width = mf.width; |
961 | pix->height = mf.height; | ||
962 | pix->colorspace = mf.colorspace; | ||
963 | |||
964 | switch (mf.field) { | ||
965 | case V4L2_FIELD_ANY: | ||
934 | pix->field = V4L2_FIELD_NONE; | 966 | pix->field = V4L2_FIELD_NONE; |
935 | } else if (field != V4L2_FIELD_NONE) { | 967 | break; |
936 | dev_err(icd->dev.parent, "Field type %d unsupported.\n", field); | 968 | case V4L2_FIELD_NONE: |
937 | return -EINVAL; | 969 | break; |
970 | default: | ||
971 | dev_err(icd->dev.parent, "Field type %d unsupported.\n", | ||
972 | mf.field); | ||
973 | ret = -EINVAL; | ||
938 | } | 974 | } |
939 | 975 | ||
940 | return ret; | 976 | return ret; |
@@ -970,18 +1006,26 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) | |||
970 | struct mx3_camera_dev *mx3_cam = ici->priv; | 1006 | struct mx3_camera_dev *mx3_cam = ici->priv; |
971 | unsigned long bus_flags, camera_flags, common_flags; | 1007 | unsigned long bus_flags, camera_flags, common_flags; |
972 | u32 dw, sens_conf; | 1008 | u32 dw, sens_conf; |
973 | int ret = test_platform_param(mx3_cam, icd->buswidth, &bus_flags); | 1009 | const struct soc_mbus_pixelfmt *fmt; |
1010 | int buswidth; | ||
1011 | int ret; | ||
974 | const struct soc_camera_format_xlate *xlate; | 1012 | const struct soc_camera_format_xlate *xlate; |
975 | struct device *dev = icd->dev.parent; | 1013 | struct device *dev = icd->dev.parent; |
976 | 1014 | ||
1015 | fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code); | ||
1016 | if (!fmt) | ||
1017 | return -EINVAL; | ||
1018 | |||
1019 | buswidth = fmt->bits_per_sample; | ||
1020 | ret = test_platform_param(mx3_cam, buswidth, &bus_flags); | ||
1021 | |||
977 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); | 1022 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); |
978 | if (!xlate) { | 1023 | if (!xlate) { |
979 | dev_warn(dev, "Format %x not found\n", pixfmt); | 1024 | dev_warn(dev, "Format %x not found\n", pixfmt); |
980 | return -EINVAL; | 1025 | return -EINVAL; |
981 | } | 1026 | } |
982 | 1027 | ||
983 | dev_dbg(dev, "requested bus width %d bit: %d\n", | 1028 | dev_dbg(dev, "requested bus width %d bit: %d\n", buswidth, ret); |
984 | icd->buswidth, ret); | ||
985 | 1029 | ||
986 | if (ret < 0) | 1030 | if (ret < 0) |
987 | return ret; | 1031 | return ret; |
@@ -1082,7 +1126,7 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) | |||
1082 | sens_conf |= 1 << CSI_SENS_CONF_DATA_POL_SHIFT; | 1126 | sens_conf |= 1 << CSI_SENS_CONF_DATA_POL_SHIFT; |
1083 | 1127 | ||
1084 | /* Just do what we're asked to do */ | 1128 | /* Just do what we're asked to do */ |
1085 | switch (xlate->host_fmt->depth) { | 1129 | switch (xlate->host_fmt->bits_per_sample) { |
1086 | case 4: | 1130 | case 4: |
1087 | dw = 0 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; | 1131 | dw = 0 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; |
1088 | break; | 1132 | break; |