aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorRobert Jarzmik <robert.jarzmik@free.fr>2008-12-01 07:45:35 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-12-30 06:38:24 -0500
commit2a48fc739df213b8f98b4effd95ce5ec93bca3da (patch)
tree8a5bcd3e361b33b259c63c22137c1e38d72c0465 /drivers/media
parentc2786ad27104c558b92343e8816e18654aae1759 (diff)
V4L/DVB (9791): pxa-camera: pixel format negotiation
Use the new format-negotiation infrastructure, support all four YUV422 packed and the planar formats. The new translation structure enables to build the format list with buswidth, depth, host format and camera format checked, so that it's not done anymore on try_fmt nor set_fmt. Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/pxa_camera.c207
1 files changed, 165 insertions, 42 deletions
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index 665eef236f5b..97923e1bd06d 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -765,6 +765,9 @@ static int test_platform_param(struct pxa_camera_dev *pcdev,
765 if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8)) 765 if (!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8))
766 return -EINVAL; 766 return -EINVAL;
767 *flags |= SOCAM_DATAWIDTH_8; 767 *flags |= SOCAM_DATAWIDTH_8;
768 break;
769 default:
770 return -EINVAL;
768 } 771 }
769 772
770 return 0; 773 return 0;
@@ -823,12 +826,10 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
823 * We fix bit-per-pixel equal to data-width... */ 826 * We fix bit-per-pixel equal to data-width... */
824 switch (common_flags & SOCAM_DATAWIDTH_MASK) { 827 switch (common_flags & SOCAM_DATAWIDTH_MASK) {
825 case SOCAM_DATAWIDTH_10: 828 case SOCAM_DATAWIDTH_10:
826 icd->buswidth = 10;
827 dw = 4; 829 dw = 4;
828 bpp = 0x40; 830 bpp = 0x40;
829 break; 831 break;
830 case SOCAM_DATAWIDTH_9: 832 case SOCAM_DATAWIDTH_9:
831 icd->buswidth = 9;
832 dw = 3; 833 dw = 3;
833 bpp = 0x20; 834 bpp = 0x20;
834 break; 835 break;
@@ -836,7 +837,6 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
836 /* Actually it can only be 8 now, 837 /* Actually it can only be 8 now,
837 * default is just to silence compiler warnings */ 838 * default is just to silence compiler warnings */
838 case SOCAM_DATAWIDTH_8: 839 case SOCAM_DATAWIDTH_8:
839 icd->buswidth = 8;
840 dw = 2; 840 dw = 2;
841 bpp = 0; 841 bpp = 0;
842 } 842 }
@@ -862,7 +862,17 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
862 case V4L2_PIX_FMT_YUV422P: 862 case V4L2_PIX_FMT_YUV422P:
863 pcdev->channels = 3; 863 pcdev->channels = 3;
864 cicr1 |= CICR1_YCBCR_F; 864 cicr1 |= CICR1_YCBCR_F;
865 /*
866 * Normally, pxa bus wants as input UYVY format. We allow all
867 * reorderings of the YUV422 format, as no processing is done,
868 * and the YUV stream is just passed through without any
869 * transformation. Note that UYVY is the only format that
870 * should be used if pxa framebuffer Overlay2 is used.
871 */
872 case V4L2_PIX_FMT_UYVY:
873 case V4L2_PIX_FMT_VYUY:
865 case V4L2_PIX_FMT_YUYV: 874 case V4L2_PIX_FMT_YUYV:
875 case V4L2_PIX_FMT_YVYU:
866 cicr1 |= CICR1_COLOR_SP_VAL(2); 876 cicr1 |= CICR1_COLOR_SP_VAL(2);
867 break; 877 break;
868 case V4L2_PIX_FMT_RGB555: 878 case V4L2_PIX_FMT_RGB555:
@@ -888,13 +898,14 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
888 return 0; 898 return 0;
889} 899}
890 900
891static int pxa_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt) 901static int pxa_camera_try_bus_param(struct soc_camera_device *icd,
902 unsigned char buswidth)
892{ 903{
893 struct soc_camera_host *ici = 904 struct soc_camera_host *ici =
894 to_soc_camera_host(icd->dev.parent); 905 to_soc_camera_host(icd->dev.parent);
895 struct pxa_camera_dev *pcdev = ici->priv; 906 struct pxa_camera_dev *pcdev = ici->priv;
896 unsigned long bus_flags, camera_flags; 907 unsigned long bus_flags, camera_flags;
897 int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags); 908 int ret = test_platform_param(pcdev, buswidth, &bus_flags);
898 909
899 if (ret < 0) 910 if (ret < 0)
900 return ret; 911 return ret;
@@ -904,25 +915,139 @@ static int pxa_camera_try_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
904 return soc_camera_bus_param_compatible(camera_flags, bus_flags) ? 0 : -EINVAL; 915 return soc_camera_bus_param_compatible(camera_flags, bus_flags) ? 0 : -EINVAL;
905} 916}
906 917
918static const struct soc_camera_data_format pxa_camera_formats[] = {
919 {
920 .name = "Planar YUV422 16 bit",
921 .depth = 16,
922 .fourcc = V4L2_PIX_FMT_YUV422P,
923 .colorspace = V4L2_COLORSPACE_JPEG,
924 },
925};
926
927static bool buswidth_supported(struct soc_camera_device *icd, int depth)
928{
929 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
930 struct pxa_camera_dev *pcdev = ici->priv;
931
932 switch (depth) {
933 case 8:
934 return !!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8);
935 case 9:
936 return !!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9);
937 case 10:
938 return !!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10);
939 }
940 return false;
941}
942
943static int required_buswidth(const struct soc_camera_data_format *fmt)
944{
945 switch (fmt->fourcc) {
946 case V4L2_PIX_FMT_UYVY:
947 case V4L2_PIX_FMT_VYUY:
948 case V4L2_PIX_FMT_YUYV:
949 case V4L2_PIX_FMT_YVYU:
950 case V4L2_PIX_FMT_RGB565:
951 case V4L2_PIX_FMT_RGB555:
952 return 8;
953 default:
954 return fmt->depth;
955 }
956}
957
958static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx,
959 struct soc_camera_format_xlate *xlate)
960{
961 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
962 int formats = 0, buswidth, ret;
963
964 buswidth = required_buswidth(icd->formats + idx);
965
966 if (!buswidth_supported(icd, buswidth))
967 return 0;
968
969 ret = pxa_camera_try_bus_param(icd, buswidth);
970 if (ret < 0)
971 return 0;
972
973 switch (icd->formats[idx].fourcc) {
974 case V4L2_PIX_FMT_UYVY:
975 formats++;
976 if (xlate) {
977 xlate->host_fmt = &pxa_camera_formats[0];
978 xlate->cam_fmt = icd->formats + idx;
979 xlate->buswidth = buswidth;
980 xlate++;
981 dev_dbg(&ici->dev, "Providing format %s using %s\n",
982 pxa_camera_formats[0].name,
983 icd->formats[idx].name);
984 }
985 case V4L2_PIX_FMT_VYUY:
986 case V4L2_PIX_FMT_YUYV:
987 case V4L2_PIX_FMT_YVYU:
988 case V4L2_PIX_FMT_RGB565:
989 case V4L2_PIX_FMT_RGB555:
990 formats++;
991 if (xlate) {
992 xlate->host_fmt = icd->formats + idx;
993 xlate->cam_fmt = icd->formats + idx;
994 xlate->buswidth = buswidth;
995 xlate++;
996 dev_dbg(&ici->dev, "Providing format %s packed\n",
997 icd->formats[idx].name);
998 }
999 break;
1000 default:
1001 /* Generic pass-through */
1002 formats++;
1003 if (xlate) {
1004 xlate->host_fmt = icd->formats + idx;
1005 xlate->cam_fmt = icd->formats + idx;
1006 xlate->buswidth = icd->formats[idx].depth;
1007 xlate++;
1008 dev_dbg(&ici->dev,
1009 "Providing format %s in pass-through mode\n",
1010 icd->formats[idx].name);
1011 }
1012 }
1013
1014 return formats;
1015}
1016
907static int pxa_camera_set_fmt(struct soc_camera_device *icd, 1017static int pxa_camera_set_fmt(struct soc_camera_device *icd,
908 __u32 pixfmt, struct v4l2_rect *rect) 1018 __u32 pixfmt, struct v4l2_rect *rect)
909{ 1019{
910 const struct soc_camera_data_format *cam_fmt; 1020 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
911 int ret; 1021 const struct soc_camera_data_format *host_fmt, *cam_fmt = NULL;
1022 const struct soc_camera_format_xlate *xlate;
1023 int ret, buswidth;
912 1024
913 /* 1025 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
914 * TODO: find a suitable supported by the SoC output format, check 1026 if (!xlate) {
915 * whether the sensor supports one of acceptable input formats. 1027 dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
916 */ 1028 return -EINVAL;
917 if (pixfmt) {
918 cam_fmt = soc_camera_format_by_fourcc(icd, pixfmt);
919 if (!cam_fmt)
920 return -EINVAL;
921 } 1029 }
922 1030
923 ret = icd->ops->set_fmt(icd, pixfmt, rect); 1031 buswidth = xlate->buswidth;
924 if (pixfmt && !ret) 1032 host_fmt = xlate->host_fmt;
925 icd->current_fmt = cam_fmt; 1033 cam_fmt = xlate->cam_fmt;
1034
1035 switch (pixfmt) {
1036 case 0: /* Only geometry change */
1037 ret = icd->ops->set_fmt(icd, pixfmt, rect);
1038 break;
1039 default:
1040 ret = icd->ops->set_fmt(icd, cam_fmt->fourcc, rect);
1041 }
1042
1043 if (ret < 0)
1044 dev_warn(&ici->dev, "Failed to configure for format %x\n",
1045 pixfmt);
1046
1047 if (pixfmt && !ret) {
1048 icd->buswidth = buswidth;
1049 icd->current_fmt = host_fmt;
1050 }
926 1051
927 return ret; 1052 return ret;
928} 1053}
@@ -930,34 +1055,31 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd,
930static int pxa_camera_try_fmt(struct soc_camera_device *icd, 1055static int pxa_camera_try_fmt(struct soc_camera_device *icd,
931 struct v4l2_format *f) 1056 struct v4l2_format *f)
932{ 1057{
933 const struct soc_camera_data_format *cam_fmt; 1058 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
934 int ret = pxa_camera_try_bus_param(icd, f->fmt.pix.pixelformat); 1059 const struct soc_camera_format_xlate *xlate;
935 1060 struct v4l2_pix_format *pix = &f->fmt.pix;
936 if (ret < 0) 1061 __u32 pixfmt = pix->pixelformat;
937 return ret;
938 1062
939 /* 1063 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
940 * TODO: find a suitable supported by the SoC output format, check 1064 if (!xlate) {
941 * whether the sensor supports one of acceptable input formats. 1065 dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
942 */
943 cam_fmt = soc_camera_format_by_fourcc(icd, f->fmt.pix.pixelformat);
944 if (!cam_fmt)
945 return -EINVAL; 1066 return -EINVAL;
1067 }
946 1068
947 /* limit to pxa hardware capabilities */ 1069 /* limit to pxa hardware capabilities */
948 if (f->fmt.pix.height < 32) 1070 if (pix->height < 32)
949 f->fmt.pix.height = 32; 1071 pix->height = 32;
950 if (f->fmt.pix.height > 2048) 1072 if (pix->height > 2048)
951 f->fmt.pix.height = 2048; 1073 pix->height = 2048;
952 if (f->fmt.pix.width < 48) 1074 if (pix->width < 48)
953 f->fmt.pix.width = 48; 1075 pix->width = 48;
954 if (f->fmt.pix.width > 2048) 1076 if (pix->width > 2048)
955 f->fmt.pix.width = 2048; 1077 pix->width = 2048;
956 f->fmt.pix.width &= ~0x01; 1078 pix->width &= ~0x01;
957 1079
958 f->fmt.pix.bytesperline = f->fmt.pix.width * 1080 pix->bytesperline = pix->width *
959 DIV_ROUND_UP(cam_fmt->depth, 8); 1081 DIV_ROUND_UP(xlate->host_fmt->depth, 8);
960 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; 1082 pix->sizeimage = pix->height * pix->bytesperline;
961 1083
962 /* limit to sensor capabilities */ 1084 /* limit to sensor capabilities */
963 return icd->ops->try_fmt(icd, f); 1085 return icd->ops->try_fmt(icd, f);
@@ -1068,6 +1190,7 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = {
1068 .remove = pxa_camera_remove_device, 1190 .remove = pxa_camera_remove_device,
1069 .suspend = pxa_camera_suspend, 1191 .suspend = pxa_camera_suspend,
1070 .resume = pxa_camera_resume, 1192 .resume = pxa_camera_resume,
1193 .get_formats = pxa_camera_get_formats,
1071 .set_fmt = pxa_camera_set_fmt, 1194 .set_fmt = pxa_camera_set_fmt,
1072 .try_fmt = pxa_camera_try_fmt, 1195 .try_fmt = pxa_camera_try_fmt,
1073 .init_videobuf = pxa_camera_init_videobuf, 1196 .init_videobuf = pxa_camera_init_videobuf,