aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-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,