aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2010-05-09 08:54:58 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-06-01 00:20:32 -0400
commite17ad1de031f2d5cade70eb0469a53f17d90d7c2 (patch)
tree5acfba0d71d91c05202d6814cfb803a75ad2c0ce /drivers
parent475977ac3db72c008f5aaa5f19bd991b72f26e42 (diff)
V4L/DVB: cx18: add s_mbus_fmt support
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/cx18/cx18-av-core.c126
1 files changed, 69 insertions, 57 deletions
diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c
index 0e5006b14279..39f484621a45 100644
--- a/drivers/media/video/cx18/cx18-av-core.c
+++ b/drivers/media/video/cx18/cx18-av-core.c
@@ -1028,80 +1028,91 @@ static int cx18_av_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
1028 return cx18_av_g_sliced_fmt(sd, &fmt->fmt.sliced); 1028 return cx18_av_g_sliced_fmt(sd, &fmt->fmt.sliced);
1029} 1029}
1030 1030
1031static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) 1031static int cx18_av_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
1032{ 1032{
1033 struct cx18_av_state *state = to_cx18_av_state(sd); 1033 struct cx18_av_state *state = to_cx18_av_state(sd);
1034 struct cx18 *cx = v4l2_get_subdevdata(sd); 1034 struct cx18 *cx = v4l2_get_subdevdata(sd);
1035
1036 struct v4l2_pix_format *pix;
1037 int HSC, VSC, Vsrc, Hsrc, filter, Vlines; 1035 int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
1038 int is_50Hz = !(state->std & V4L2_STD_525_60); 1036 int is_50Hz = !(state->std & V4L2_STD_525_60);
1039 1037
1040 switch (fmt->type) { 1038 if (fmt->code != V4L2_MBUS_FMT_FIXED)
1041 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 1039 return -EINVAL;
1042 pix = &(fmt->fmt.pix);
1043 1040
1044 Vsrc = (cx18_av_read(cx, 0x476) & 0x3f) << 4; 1041 fmt->field = V4L2_FIELD_INTERLACED;
1045 Vsrc |= (cx18_av_read(cx, 0x475) & 0xf0) >> 4; 1042 fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
1046 1043
1047 Hsrc = (cx18_av_read(cx, 0x472) & 0x3f) << 4; 1044 Vsrc = (cx18_av_read(cx, 0x476) & 0x3f) << 4;
1048 Hsrc |= (cx18_av_read(cx, 0x471) & 0xf0) >> 4; 1045 Vsrc |= (cx18_av_read(cx, 0x475) & 0xf0) >> 4;
1049 1046
1050 /* 1047 Hsrc = (cx18_av_read(cx, 0x472) & 0x3f) << 4;
1051 * This adjustment reflects the excess of vactive, set in 1048 Hsrc |= (cx18_av_read(cx, 0x471) & 0xf0) >> 4;
1052 * cx18_av_std_setup(), above standard values:
1053 *
1054 * 480 + 1 for 60 Hz systems
1055 * 576 + 3 for 50 Hz systems
1056 */
1057 Vlines = pix->height + (is_50Hz ? 3 : 1);
1058 1049
1059 /* 1050 /*
1060 * Invalid height and width scaling requests are: 1051 * This adjustment reflects the excess of vactive, set in
1061 * 1. width less than 1/16 of the source width 1052 * cx18_av_std_setup(), above standard values:
1062 * 2. width greater than the source width 1053 *
1063 * 3. height less than 1/8 of the source height 1054 * 480 + 1 for 60 Hz systems
1064 * 4. height greater than the source height 1055 * 576 + 3 for 50 Hz systems
1065 */ 1056 */
1066 if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) || 1057 Vlines = fmt->height + (is_50Hz ? 3 : 1);
1067 (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
1068 CX18_ERR_DEV(sd, "%dx%d is not a valid size!\n",
1069 pix->width, pix->height);
1070 return -ERANGE;
1071 }
1072 1058
1073 HSC = (Hsrc * (1 << 20)) / pix->width - (1 << 20); 1059 /*
1074 VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9)); 1060 * Invalid height and width scaling requests are:
1075 VSC &= 0x1fff; 1061 * 1. width less than 1/16 of the source width
1062 * 2. width greater than the source width
1063 * 3. height less than 1/8 of the source height
1064 * 4. height greater than the source height
1065 */
1066 if ((fmt->width * 16 < Hsrc) || (Hsrc < fmt->width) ||
1067 (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
1068 CX18_ERR_DEV(sd, "%dx%d is not a valid size!\n",
1069 fmt->width, fmt->height);
1070 return -ERANGE;
1071 }
1076 1072
1077 if (pix->width >= 385) 1073 HSC = (Hsrc * (1 << 20)) / fmt->width - (1 << 20);
1078 filter = 0; 1074 VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
1079 else if (pix->width > 192) 1075 VSC &= 0x1fff;
1080 filter = 1;
1081 else if (pix->width > 96)
1082 filter = 2;
1083 else
1084 filter = 3;
1085 1076
1086 CX18_DEBUG_INFO_DEV(sd, 1077 if (fmt->width >= 385)
1087 "decoder set size %dx%d -> scale %ux%u\n", 1078 filter = 0;
1088 pix->width, pix->height, HSC, VSC); 1079 else if (fmt->width > 192)
1089 1080 filter = 1;
1090 /* HSCALE=HSC */ 1081 else if (fmt->width > 96)
1091 cx18_av_write(cx, 0x418, HSC & 0xff); 1082 filter = 2;
1092 cx18_av_write(cx, 0x419, (HSC >> 8) & 0xff); 1083 else
1093 cx18_av_write(cx, 0x41a, HSC >> 16); 1084 filter = 3;
1094 /* VSCALE=VSC */ 1085
1095 cx18_av_write(cx, 0x41c, VSC & 0xff); 1086 CX18_DEBUG_INFO_DEV(sd,
1096 cx18_av_write(cx, 0x41d, VSC >> 8); 1087 "decoder set size %dx%d -> scale %ux%u\n",
1097 /* VS_INTRLACE=1 VFILT=filter */ 1088 fmt->width, fmt->height, HSC, VSC);
1098 cx18_av_write(cx, 0x41e, 0x8 | filter); 1089
1099 break; 1090 /* HSCALE=HSC */
1091 cx18_av_write(cx, 0x418, HSC & 0xff);
1092 cx18_av_write(cx, 0x419, (HSC >> 8) & 0xff);
1093 cx18_av_write(cx, 0x41a, HSC >> 16);
1094 /* VSCALE=VSC */
1095 cx18_av_write(cx, 0x41c, VSC & 0xff);
1096 cx18_av_write(cx, 0x41d, VSC >> 8);
1097 /* VS_INTRLACE=1 VFILT=filter */
1098 cx18_av_write(cx, 0x41e, 0x8 | filter);
1099 return 0;
1100}
1101
1102static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
1103{
1104 struct v4l2_mbus_framefmt mbus_fmt;
1105
1106 switch (fmt->type) {
1107 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1108 mbus_fmt.width = fmt->fmt.pix.width;
1109 mbus_fmt.height = fmt->fmt.pix.height;
1110 mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
1111 return cx18_av_s_mbus_fmt(sd, &mbus_fmt);
1100 1112
1101 default: 1113 default:
1102 return -EINVAL; 1114 return -EINVAL;
1103 } 1115 }
1104 return 0;
1105} 1116}
1106 1117
1107static int cx18_av_s_stream(struct v4l2_subdev *sd, int enable) 1118static int cx18_av_s_stream(struct v4l2_subdev *sd, int enable)
@@ -1400,6 +1411,7 @@ static const struct v4l2_subdev_video_ops cx18_av_video_ops = {
1400 .s_stream = cx18_av_s_stream, 1411 .s_stream = cx18_av_s_stream,
1401 .g_fmt = cx18_av_g_fmt, 1412 .g_fmt = cx18_av_g_fmt,
1402 .s_fmt = cx18_av_s_fmt, 1413 .s_fmt = cx18_av_s_fmt,
1414 .s_mbus_fmt = cx18_av_s_mbus_fmt,
1403}; 1415};
1404 1416
1405static const struct v4l2_subdev_vbi_ops cx18_av_vbi_ops = { 1417static const struct v4l2_subdev_vbi_ops cx18_av_vbi_ops = {