aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/tw9910.c
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2009-08-25 10:50:46 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-09-18 23:19:17 -0400
commit6a6c8786725c0b3d143674effa8b772f47b1c189 (patch)
tree8bb76c5dcbd579f13e876bd1a0bb56bee4bcebdd /drivers/media/video/tw9910.c
parent0166b74374cae3fa8bff0caef726a3d960a9a50a (diff)
V4L/DVB (12534): soc-camera: V4L2 API compliant scaling (S_FMT) and cropping (S_CROP)
The initial soc-camera scaling and cropping implementation turned out to be incompliant with the V4L2 API, e.g., it expected the user to specify cropping in output window pixels, instead of input window pixels. This patch converts the soc-camera core and all drivers to comply with the standard. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
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;