Commit 96fd004f authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

V4L/DVB: cx25840: add support for s_mbus_fmt

Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent c463d93f
...@@ -1025,59 +1025,72 @@ static int cx25840_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) ...@@ -1025,59 +1025,72 @@ static int cx25840_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
return 0; return 0;
} }
static int cx25840_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) static int cx25840_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
{ {
struct cx25840_state *state = to_state(sd); struct cx25840_state *state = to_state(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd); struct i2c_client *client = v4l2_get_subdevdata(sd);
struct v4l2_pix_format *pix;
int HSC, VSC, Vsrc, Hsrc, filter, Vlines; int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
int is_50Hz = !(state->std & V4L2_STD_525_60); int is_50Hz = !(state->std & V4L2_STD_525_60);
switch (fmt->type) { if (fmt->code != V4L2_MBUS_FMT_FIXED)
case V4L2_BUF_TYPE_VIDEO_CAPTURE: return -EINVAL;
pix = &(fmt->fmt.pix);
Vsrc = (cx25840_read(client, 0x476) & 0x3f) << 4; fmt->field = V4L2_FIELD_INTERLACED;
Vsrc |= (cx25840_read(client, 0x475) & 0xf0) >> 4; fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4; Vsrc = (cx25840_read(client, 0x476) & 0x3f) << 4;
Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4; Vsrc |= (cx25840_read(client, 0x475) & 0xf0) >> 4;
Vlines = pix->height + (is_50Hz ? 4 : 7); Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4;
Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4;
if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) || Vlines = fmt->height + (is_50Hz ? 4 : 7);
(Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
v4l_err(client, "%dx%d is not a valid size!\n",
pix->width, pix->height);
return -ERANGE;
}
HSC = (Hsrc * (1 << 20)) / pix->width - (1 << 20); if ((fmt->width * 16 < Hsrc) || (Hsrc < fmt->width) ||
VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9)); (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
VSC &= 0x1fff; v4l_err(client, "%dx%d is not a valid size!\n",
fmt->width, fmt->height);
return -ERANGE;
}
if (pix->width >= 385) HSC = (Hsrc * (1 << 20)) / fmt->width - (1 << 20);
filter = 0; VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
else if (pix->width > 192) VSC &= 0x1fff;
filter = 1;
else if (pix->width > 96) if (fmt->width >= 385)
filter = 2; filter = 0;
else else if (fmt->width > 192)
filter = 3; filter = 1;
else if (fmt->width > 96)
v4l_dbg(1, cx25840_debug, client, "decoder set size %dx%d -> scale %ux%u\n", filter = 2;
pix->width, pix->height, HSC, VSC); else
filter = 3;
/* HSCALE=HSC */
cx25840_write(client, 0x418, HSC & 0xff); v4l_dbg(1, cx25840_debug, client, "decoder set size %dx%d -> scale %ux%u\n",
cx25840_write(client, 0x419, (HSC >> 8) & 0xff); fmt->width, fmt->height, HSC, VSC);
cx25840_write(client, 0x41a, HSC >> 16);
/* VSCALE=VSC */ /* HSCALE=HSC */
cx25840_write(client, 0x41c, VSC & 0xff); cx25840_write(client, 0x418, HSC & 0xff);
cx25840_write(client, 0x41d, VSC >> 8); cx25840_write(client, 0x419, (HSC >> 8) & 0xff);
/* VS_INTRLACE=1 VFILT=filter */ cx25840_write(client, 0x41a, HSC >> 16);
cx25840_write(client, 0x41e, 0x8 | filter); /* VSCALE=VSC */
break; cx25840_write(client, 0x41c, VSC & 0xff);
cx25840_write(client, 0x41d, VSC >> 8);
/* VS_INTRLACE=1 VFILT=filter */
cx25840_write(client, 0x41e, 0x8 | filter);
return 0;
}
static int cx25840_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 cx25840_s_mbus_fmt(sd, &mbus_fmt);
default: default:
return -EINVAL; return -EINVAL;
...@@ -1629,6 +1642,7 @@ static const struct v4l2_subdev_video_ops cx25840_video_ops = { ...@@ -1629,6 +1642,7 @@ static const struct v4l2_subdev_video_ops cx25840_video_ops = {
.s_routing = cx25840_s_video_routing, .s_routing = cx25840_s_video_routing,
.g_fmt = cx25840_g_fmt, .g_fmt = cx25840_g_fmt,
.s_fmt = cx25840_s_fmt, .s_fmt = cx25840_s_fmt,
.s_mbus_fmt = cx25840_s_mbus_fmt,
.s_stream = cx25840_s_stream, .s_stream = cx25840_s_stream,
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment