From e17ad1de031f2d5cade70eb0469a53f17d90d7c2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 9 May 2010 09:54:58 -0300 Subject: V4L/DVB: cx18: add s_mbus_fmt support Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-av-core.c | 126 +++++++++++++++++--------------- 1 file changed, 69 insertions(+), 57 deletions(-) (limited to 'drivers/media') 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) return cx18_av_g_sliced_fmt(sd, &fmt->fmt.sliced); } -static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +static int cx18_av_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt) { struct cx18_av_state *state = to_cx18_av_state(sd); struct cx18 *cx = v4l2_get_subdevdata(sd); - - struct v4l2_pix_format *pix; int HSC, VSC, Vsrc, Hsrc, filter, Vlines; int is_50Hz = !(state->std & V4L2_STD_525_60); - switch (fmt->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - pix = &(fmt->fmt.pix); + if (fmt->code != V4L2_MBUS_FMT_FIXED) + return -EINVAL; - Vsrc = (cx18_av_read(cx, 0x476) & 0x3f) << 4; - Vsrc |= (cx18_av_read(cx, 0x475) & 0xf0) >> 4; + fmt->field = V4L2_FIELD_INTERLACED; + fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; - Hsrc = (cx18_av_read(cx, 0x472) & 0x3f) << 4; - Hsrc |= (cx18_av_read(cx, 0x471) & 0xf0) >> 4; + Vsrc = (cx18_av_read(cx, 0x476) & 0x3f) << 4; + Vsrc |= (cx18_av_read(cx, 0x475) & 0xf0) >> 4; - /* - * This adjustment reflects the excess of vactive, set in - * cx18_av_std_setup(), above standard values: - * - * 480 + 1 for 60 Hz systems - * 576 + 3 for 50 Hz systems - */ - Vlines = pix->height + (is_50Hz ? 3 : 1); + Hsrc = (cx18_av_read(cx, 0x472) & 0x3f) << 4; + Hsrc |= (cx18_av_read(cx, 0x471) & 0xf0) >> 4; - /* - * Invalid height and width scaling requests are: - * 1. width less than 1/16 of the source width - * 2. width greater than the source width - * 3. height less than 1/8 of the source height - * 4. height greater than the source height - */ - if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) || - (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) { - CX18_ERR_DEV(sd, "%dx%d is not a valid size!\n", - pix->width, pix->height); - return -ERANGE; - } + /* + * This adjustment reflects the excess of vactive, set in + * cx18_av_std_setup(), above standard values: + * + * 480 + 1 for 60 Hz systems + * 576 + 3 for 50 Hz systems + */ + Vlines = fmt->height + (is_50Hz ? 3 : 1); - HSC = (Hsrc * (1 << 20)) / pix->width - (1 << 20); - VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9)); - VSC &= 0x1fff; + /* + * Invalid height and width scaling requests are: + * 1. width less than 1/16 of the source width + * 2. width greater than the source width + * 3. height less than 1/8 of the source height + * 4. height greater than the source height + */ + if ((fmt->width * 16 < Hsrc) || (Hsrc < fmt->width) || + (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) { + CX18_ERR_DEV(sd, "%dx%d is not a valid size!\n", + fmt->width, fmt->height); + return -ERANGE; + } - if (pix->width >= 385) - filter = 0; - else if (pix->width > 192) - filter = 1; - else if (pix->width > 96) - filter = 2; - else - filter = 3; + HSC = (Hsrc * (1 << 20)) / fmt->width - (1 << 20); + VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9)); + VSC &= 0x1fff; - CX18_DEBUG_INFO_DEV(sd, - "decoder set size %dx%d -> scale %ux%u\n", - pix->width, pix->height, HSC, VSC); - - /* HSCALE=HSC */ - cx18_av_write(cx, 0x418, HSC & 0xff); - cx18_av_write(cx, 0x419, (HSC >> 8) & 0xff); - cx18_av_write(cx, 0x41a, HSC >> 16); - /* VSCALE=VSC */ - cx18_av_write(cx, 0x41c, VSC & 0xff); - cx18_av_write(cx, 0x41d, VSC >> 8); - /* VS_INTRLACE=1 VFILT=filter */ - cx18_av_write(cx, 0x41e, 0x8 | filter); - break; + if (fmt->width >= 385) + filter = 0; + else if (fmt->width > 192) + filter = 1; + else if (fmt->width > 96) + filter = 2; + else + filter = 3; + + CX18_DEBUG_INFO_DEV(sd, + "decoder set size %dx%d -> scale %ux%u\n", + fmt->width, fmt->height, HSC, VSC); + + /* HSCALE=HSC */ + cx18_av_write(cx, 0x418, HSC & 0xff); + cx18_av_write(cx, 0x419, (HSC >> 8) & 0xff); + cx18_av_write(cx, 0x41a, HSC >> 16); + /* VSCALE=VSC */ + cx18_av_write(cx, 0x41c, VSC & 0xff); + cx18_av_write(cx, 0x41d, VSC >> 8); + /* VS_INTRLACE=1 VFILT=filter */ + cx18_av_write(cx, 0x41e, 0x8 | filter); + return 0; +} + +static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + struct v4l2_mbus_framefmt mbus_fmt; + + switch (fmt->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + mbus_fmt.width = fmt->fmt.pix.width; + mbus_fmt.height = fmt->fmt.pix.height; + mbus_fmt.code = V4L2_MBUS_FMT_FIXED; + return cx18_av_s_mbus_fmt(sd, &mbus_fmt); default: return -EINVAL; } - return 0; } 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 = { .s_stream = cx18_av_s_stream, .g_fmt = cx18_av_g_fmt, .s_fmt = cx18_av_s_fmt, + .s_mbus_fmt = cx18_av_s_mbus_fmt, }; static const struct v4l2_subdev_vbi_ops cx18_av_vbi_ops = { -- cgit v1.2.3