aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/tw9910.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/tw9910.c')
-rw-r--r--drivers/media/video/tw9910.c120
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
718static 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
747static 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
764static 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
718static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) 796static 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
839static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = { 919static 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 */
856static 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
869static int tw9910_probe(struct i2c_client *client, 938static 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;