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

V4L/DVB: cx25840: add support for s_mbus_fmt

parent c463d93f
Loading
Loading
Loading
Loading
+55 −41
Original line number Diff line number Diff line
@@ -1025,17 +1025,18 @@ static int cx25840_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
	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 i2c_client *client = 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;

	fmt->field = V4L2_FIELD_INTERLACED;
	fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;

	Vsrc = (cx25840_read(client, 0x476) & 0x3f) << 4;
	Vsrc |= (cx25840_read(client, 0x475) & 0xf0) >> 4;
@@ -1043,30 +1044,30 @@ static int cx25840_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
	Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4;
	Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4;

		Vlines = pix->height + (is_50Hz ? 4 : 7);
	Vlines = fmt->height + (is_50Hz ? 4 : 7);

		if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) ||
	if ((fmt->width * 16 < Hsrc) || (Hsrc < fmt->width) ||
			(Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
		v4l_err(client, "%dx%d is not a valid size!\n",
				    pix->width, pix->height);
				fmt->width, fmt->height);
		return -ERANGE;
	}

		HSC = (Hsrc * (1 << 20)) / pix->width - (1 << 20);
	HSC = (Hsrc * (1 << 20)) / fmt->width - (1 << 20);
	VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
	VSC &= 0x1fff;

		if (pix->width >= 385)
	if (fmt->width >= 385)
		filter = 0;
		else if (pix->width > 192)
	else if (fmt->width > 192)
		filter = 1;
		else if (pix->width > 96)
	else if (fmt->width > 96)
		filter = 2;
	else
		filter = 3;

	v4l_dbg(1, cx25840_debug, client, "decoder set size %dx%d -> scale  %ux%u\n",
			    pix->width, pix->height, HSC, VSC);
			fmt->width, fmt->height, HSC, VSC);

	/* HSCALE=HSC */
	cx25840_write(client, 0x418, HSC & 0xff);
@@ -1077,7 +1078,19 @@ static int cx25840_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
	cx25840_write(client, 0x41d, VSC >> 8);
	/* VS_INTRLACE=1 VFILT=filter */
	cx25840_write(client, 0x41e, 0x8 | filter);
		break;
	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:
		return -EINVAL;
@@ -1629,6 +1642,7 @@ static const struct v4l2_subdev_video_ops cx25840_video_ops = {
	.s_routing = cx25840_s_video_routing,
	.g_fmt = cx25840_g_fmt,
	.s_fmt = cx25840_s_fmt,
	.s_mbus_fmt = cx25840_s_mbus_fmt,
	.s_stream = cx25840_s_stream,
};