diff options
Diffstat (limited to 'drivers/media/video/tw9910.c')
-rw-r--r-- | drivers/media/video/tw9910.c | 120 |
1 files changed, 86 insertions, 34 deletions
diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index 94bd5b09f057..fbf4130dfc5d 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c | |||
@@ -715,8 +715,88 @@ tw9910_set_fmt_error: | |||
715 | return ret; | 715 | return ret; |
716 | } | 716 | } |
717 | 717 | ||
718 | static int tw9910_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | ||
719 | { | ||
720 | struct i2c_client *client = sd->priv; | ||
721 | struct tw9910_priv *priv = to_tw9910(client); | ||
722 | |||
723 | if (!priv->scale) { | ||
724 | int ret; | ||
725 | struct v4l2_crop crop = { | ||
726 | .c = { | ||
727 | .left = 0, | ||
728 | .top = 0, | ||
729 | .width = 640, | ||
730 | .height = 480, | ||
731 | }, | ||
732 | }; | ||
733 | ret = tw9910_s_crop(sd, &crop); | ||
734 | if (ret < 0) | ||
735 | return ret; | ||
736 | } | ||
737 | |||
738 | a->c.left = 0; | ||
739 | a->c.top = 0; | ||
740 | a->c.width = priv->scale->width; | ||
741 | a->c.height = priv->scale->height; | ||
742 | a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
743 | |||
744 | return 0; | ||
745 | } | ||
746 | |||
747 | static int tw9910_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) | ||
748 | { | ||
749 | a->bounds.left = 0; | ||
750 | a->bounds.top = 0; | ||
751 | a->bounds.width = 768; | ||
752 | a->bounds.height = 576; | ||
753 | a->defrect.left = 0; | ||
754 | a->defrect.top = 0; | ||
755 | a->defrect.width = 640; | ||
756 | a->defrect.height = 480; | ||
757 | a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
758 | a->pixelaspect.numerator = 1; | ||
759 | a->pixelaspect.denominator = 1; | ||
760 | |||
761 | return 0; | ||
762 | } | ||
763 | |||
764 | static int tw9910_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | ||
765 | { | ||
766 | struct i2c_client *client = sd->priv; | ||
767 | struct tw9910_priv *priv = to_tw9910(client); | ||
768 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
769 | |||
770 | if (!priv->scale) { | ||
771 | int ret; | ||
772 | struct v4l2_crop crop = { | ||
773 | .c = { | ||
774 | .left = 0, | ||
775 | .top = 0, | ||
776 | .width = 640, | ||
777 | .height = 480, | ||
778 | }, | ||
779 | }; | ||
780 | ret = tw9910_s_crop(sd, &crop); | ||
781 | if (ret < 0) | ||
782 | return ret; | ||
783 | } | ||
784 | |||
785 | f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
786 | |||
787 | pix->width = priv->scale->width; | ||
788 | pix->height = priv->scale->height; | ||
789 | pix->pixelformat = V4L2_PIX_FMT_VYUY; | ||
790 | pix->colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
791 | pix->field = V4L2_FIELD_INTERLACED; | ||
792 | |||
793 | return 0; | ||
794 | } | ||
795 | |||
718 | static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 796 | static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) |
719 | { | 797 | { |
798 | struct i2c_client *client = sd->priv; | ||
799 | struct tw9910_priv *priv = to_tw9910(client); | ||
720 | struct v4l2_pix_format *pix = &f->fmt.pix; | 800 | struct v4l2_pix_format *pix = &f->fmt.pix; |
721 | /* See tw9910_s_crop() - no proper cropping support */ | 801 | /* See tw9910_s_crop() - no proper cropping support */ |
722 | struct v4l2_crop a = { | 802 | struct v4l2_crop a = { |
@@ -741,8 +821,8 @@ static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | |||
741 | 821 | ||
742 | ret = tw9910_s_crop(sd, &a); | 822 | ret = tw9910_s_crop(sd, &a); |
743 | if (!ret) { | 823 | if (!ret) { |
744 | pix->width = a.c.width; | 824 | pix->width = priv->scale->width; |
745 | pix->height = a.c.height; | 825 | pix->height = priv->scale->height; |
746 | } | 826 | } |
747 | return ret; | 827 | return ret; |
748 | } | 828 | } |
@@ -838,8 +918,11 @@ static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = { | |||
838 | 918 | ||
839 | static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = { | 919 | static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = { |
840 | .s_stream = tw9910_s_stream, | 920 | .s_stream = tw9910_s_stream, |
921 | .g_fmt = tw9910_g_fmt, | ||
841 | .s_fmt = tw9910_s_fmt, | 922 | .s_fmt = tw9910_s_fmt, |
842 | .try_fmt = tw9910_try_fmt, | 923 | .try_fmt = tw9910_try_fmt, |
924 | .cropcap = tw9910_cropcap, | ||
925 | .g_crop = tw9910_g_crop, | ||
843 | .s_crop = tw9910_s_crop, | 926 | .s_crop = tw9910_s_crop, |
844 | }; | 927 | }; |
845 | 928 | ||
@@ -852,20 +935,6 @@ static struct v4l2_subdev_ops tw9910_subdev_ops = { | |||
852 | * i2c_driver function | 935 | * i2c_driver function |
853 | */ | 936 | */ |
854 | 937 | ||
855 | /* This is called during probe, so, setting rect_max is Ok here: scale == 1 */ | ||
856 | static void limit_to_scale(struct soc_camera_device *icd, | ||
857 | const struct tw9910_scale_ctrl *scale) | ||
858 | { | ||
859 | if (scale->width > icd->rect_max.width) | ||
860 | icd->rect_max.width = scale->width; | ||
861 | if (scale->width < icd->width_min) | ||
862 | icd->width_min = scale->width; | ||
863 | if (scale->height > icd->rect_max.height) | ||
864 | icd->rect_max.height = scale->height; | ||
865 | if (scale->height < icd->height_min) | ||
866 | icd->height_min = scale->height; | ||
867 | } | ||
868 | |||
869 | static int tw9910_probe(struct i2c_client *client, | 938 | static int tw9910_probe(struct i2c_client *client, |
870 | const struct i2c_device_id *did) | 939 | const struct i2c_device_id *did) |
871 | 940 | ||
@@ -876,8 +945,7 @@ static int tw9910_probe(struct i2c_client *client, | |||
876 | struct i2c_adapter *adapter = | 945 | struct i2c_adapter *adapter = |
877 | to_i2c_adapter(client->dev.parent); | 946 | to_i2c_adapter(client->dev.parent); |
878 | struct soc_camera_link *icl; | 947 | struct soc_camera_link *icl; |
879 | const struct tw9910_scale_ctrl *scale; | 948 | int ret; |
880 | int i, ret; | ||
881 | 949 | ||
882 | if (!icd) { | 950 | if (!icd) { |
883 | dev_err(&client->dev, "TW9910: missing soc-camera data!\n"); | 951 | dev_err(&client->dev, "TW9910: missing soc-camera data!\n"); |
@@ -908,22 +976,6 @@ static int tw9910_probe(struct i2c_client *client, | |||
908 | icd->ops = &tw9910_ops; | 976 | icd->ops = &tw9910_ops; |
909 | icd->iface = info->link.bus_id; | 977 | icd->iface = info->link.bus_id; |
910 | 978 | ||
911 | /* | ||
912 | * set width and height | ||
913 | */ | ||
914 | icd->rect_max.width = tw9910_ntsc_scales[0].width; /* set default */ | ||
915 | icd->width_min = tw9910_ntsc_scales[0].width; | ||
916 | icd->rect_max.height = tw9910_ntsc_scales[0].height; | ||
917 | icd->height_min = tw9910_ntsc_scales[0].height; | ||
918 | |||
919 | scale = tw9910_ntsc_scales; | ||
920 | for (i = 0; i < ARRAY_SIZE(tw9910_ntsc_scales); i++) | ||
921 | limit_to_scale(icd, scale + i); | ||
922 | |||
923 | scale = tw9910_pal_scales; | ||
924 | for (i = 0; i < ARRAY_SIZE(tw9910_pal_scales); i++) | ||
925 | limit_to_scale(icd, scale + i); | ||
926 | |||
927 | ret = tw9910_video_probe(icd, client); | 979 | ret = tw9910_video_probe(icd, client); |
928 | if (ret) { | 980 | if (ret) { |
929 | icd->ops = NULL; | 981 | icd->ops = NULL; |