aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2010-05-09 08:48:50 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-06-01 00:20:25 -0400
commit96fd004fe40b8e3beff2a6e27ae0411a4d315f1e (patch)
tree0e924c76988e3852f558c73c05f980b3dfa793c8 /drivers/media/video
parentc463d93f22254f46168b49ad1149d1ec1e904711 (diff)
V4L/DVB: cx25840: add support for s_mbus_fmt
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/cx25840/cx25840-core.c96
1 files changed, 55 insertions, 41 deletions
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index 8b6fb3544376..f0cbc9d066bd 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -1025,59 +1025,72 @@ static int cx25840_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
1025 return 0; 1025 return 0;
1026} 1026}
1027 1027
1028static int cx25840_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) 1028static int cx25840_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
1029{ 1029{
1030 struct cx25840_state *state = to_state(sd); 1030 struct cx25840_state *state = to_state(sd);
1031 struct i2c_client *client = v4l2_get_subdevdata(sd); 1031 struct i2c_client *client = v4l2_get_subdevdata(sd);
1032 struct v4l2_pix_format *pix;
1033 int HSC, VSC, Vsrc, Hsrc, filter, Vlines; 1032 int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
1034 int is_50Hz = !(state->std & V4L2_STD_525_60); 1033 int is_50Hz = !(state->std & V4L2_STD_525_60);
1035 1034
1036 switch (fmt->type) { 1035 if (fmt->code != V4L2_MBUS_FMT_FIXED)
1037 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 1036 return -EINVAL;
1038 pix = &(fmt->fmt.pix);
1039 1037
1040 Vsrc = (cx25840_read(client, 0x476) & 0x3f) << 4; 1038 fmt->field = V4L2_FIELD_INTERLACED;
1041 Vsrc |= (cx25840_read(client, 0x475) & 0xf0) >> 4; 1039 fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
1042 1040
1043 Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4; 1041 Vsrc = (cx25840_read(client, 0x476) & 0x3f) << 4;
1044 Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4; 1042 Vsrc |= (cx25840_read(client, 0x475) & 0xf0) >> 4;
1045 1043
1046 Vlines = pix->height + (is_50Hz ? 4 : 7); 1044 Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4;
1045 Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4;
1047 1046
1048 if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) || 1047 Vlines = fmt->height + (is_50Hz ? 4 : 7);
1049 (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
1050 v4l_err(client, "%dx%d is not a valid size!\n",
1051 pix->width, pix->height);
1052 return -ERANGE;
1053 }
1054 1048
1055 HSC = (Hsrc * (1 << 20)) / pix->width - (1 << 20); 1049 if ((fmt->width * 16 < Hsrc) || (Hsrc < fmt->width) ||
1056 VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9)); 1050 (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
1057 VSC &= 0x1fff; 1051 v4l_err(client, "%dx%d is not a valid size!\n",
1052 fmt->width, fmt->height);
1053 return -ERANGE;
1054 }
1058 1055
1059 if (pix->width >= 385) 1056 HSC = (Hsrc * (1 << 20)) / fmt->width - (1 << 20);
1060 filter = 0; 1057 VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
1061 else if (pix->width > 192) 1058 VSC &= 0x1fff;
1062 filter = 1; 1059
1063 else if (pix->width > 96) 1060 if (fmt->width >= 385)
1064 filter = 2; 1061 filter = 0;
1065 else 1062 else if (fmt->width > 192)
1066 filter = 3; 1063 filter = 1;
1067 1064 else if (fmt->width > 96)
1068 v4l_dbg(1, cx25840_debug, client, "decoder set size %dx%d -> scale %ux%u\n", 1065 filter = 2;
1069 pix->width, pix->height, HSC, VSC); 1066 else
1070 1067 filter = 3;
1071 /* HSCALE=HSC */ 1068
1072 cx25840_write(client, 0x418, HSC & 0xff); 1069 v4l_dbg(1, cx25840_debug, client, "decoder set size %dx%d -> scale %ux%u\n",
1073 cx25840_write(client, 0x419, (HSC >> 8) & 0xff); 1070 fmt->width, fmt->height, HSC, VSC);
1074 cx25840_write(client, 0x41a, HSC >> 16); 1071
1075 /* VSCALE=VSC */ 1072 /* HSCALE=HSC */
1076 cx25840_write(client, 0x41c, VSC & 0xff); 1073 cx25840_write(client, 0x418, HSC & 0xff);
1077 cx25840_write(client, 0x41d, VSC >> 8); 1074 cx25840_write(client, 0x419, (HSC >> 8) & 0xff);
1078 /* VS_INTRLACE=1 VFILT=filter */ 1075 cx25840_write(client, 0x41a, HSC >> 16);
1079 cx25840_write(client, 0x41e, 0x8 | filter); 1076 /* VSCALE=VSC */
1080 break; 1077 cx25840_write(client, 0x41c, VSC & 0xff);
1078 cx25840_write(client, 0x41d, VSC >> 8);
1079 /* VS_INTRLACE=1 VFILT=filter */
1080 cx25840_write(client, 0x41e, 0x8 | filter);
1081 return 0;
1082}
1083
1084static int cx25840_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
1085{
1086 struct v4l2_mbus_framefmt mbus_fmt;
1087
1088 switch (fmt->type) {
1089 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1090 mbus_fmt.width = fmt->fmt.pix.width;
1091 mbus_fmt.height = fmt->fmt.pix.height;
1092 mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
1093 return cx25840_s_mbus_fmt(sd, &mbus_fmt);
1081 1094
1082 default: 1095 default:
1083 return -EINVAL; 1096 return -EINVAL;
@@ -1629,6 +1642,7 @@ static const struct v4l2_subdev_video_ops cx25840_video_ops = {
1629 .s_routing = cx25840_s_video_routing, 1642 .s_routing = cx25840_s_video_routing,
1630 .g_fmt = cx25840_g_fmt, 1643 .g_fmt = cx25840_g_fmt,
1631 .s_fmt = cx25840_s_fmt, 1644 .s_fmt = cx25840_s_fmt,
1645 .s_mbus_fmt = cx25840_s_mbus_fmt,
1632 .s_stream = cx25840_s_stream, 1646 .s_stream = cx25840_s_stream,
1633}; 1647};
1634 1648