diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2010-05-09 08:54:58 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-06-01 00:20:32 -0400 |
commit | e17ad1de031f2d5cade70eb0469a53f17d90d7c2 (patch) | |
tree | 5acfba0d71d91c05202d6814cfb803a75ad2c0ce | |
parent | 475977ac3db72c008f5aaa5f19bd991b72f26e42 (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>
-rw-r--r-- | drivers/media/video/cx18/cx18-av-core.c | 126 |
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 | ||
1031 | static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | 1031 | static 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 | |||
1102 | static 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 | ||
1107 | static int cx18_av_s_stream(struct v4l2_subdev *sd, int enable) | 1118 | static 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 | ||
1405 | static const struct v4l2_subdev_vbi_ops cx18_av_vbi_ops = { | 1417 | static const struct v4l2_subdev_vbi_ops cx18_av_vbi_ops = { |