19eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors/*
29eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors * timblogiw.c timberdale FPGA LogiWin Video In driver
39eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors * Copyright (c) 2009-2010 Intel Corporation
49eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors *
59eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors * This program is free software; you can redistribute it and/or modify
69eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors * it under the terms of the GNU General Public License version 2 as
79eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors * published by the Free Software Foundation.
89eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors *
99eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors * This program is distributed in the hope that it will be useful,
109eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors * but WITHOUT ANY WARRANTY; without even the implied warranty of
119eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
129eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors * GNU General Public License for more details.
139eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors *
149eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors * You should have received a copy of the GNU General Public License
159eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors * along with this program; if not, write to the Free Software
169eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
179eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors */
189eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
199eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors/* Supports:
209eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors * Timberdale FPGA LogiWin Video In
219eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors */
229eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
239eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors#include <linux/platform_device.h>
249eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors#include <linux/slab.h>
259eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors#include <linux/dmaengine.h>
269eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors#include <linux/scatterlist.h>
279eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors#include <linux/interrupt.h>
289eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors#include <linux/list.h>
299eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors#include <linux/i2c.h>
307a707b89202f905bd9f9fbde326933c59a81214cPaul Gortmaker#include <linux/module.h>
319eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors#include <media/v4l2-ioctl.h>
329eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors#include <media/v4l2-device.h>
339eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors#include <media/videobuf-dma-contig.h>
349eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors#include <media/timb_video.h>
359eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
369eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors#define DRIVER_NAME			"timb-video"
379eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
389eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors#define TIMBLOGIWIN_NAME		"Timberdale Video-In"
399eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors#define TIMBLOGIW_VERSION_CODE		0x04
409eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
419eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors#define TIMBLOGIW_LINES_PER_DESC	44
429eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors#define TIMBLOGIW_MAX_VIDEO_MEM		16
439eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
449eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors#define TIMBLOGIW_HAS_DECODER(lw)	(lw->pdata.encoder.module_name)
459eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
469eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
479eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstruct timblogiw {
489eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device		video_dev;
499eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct v4l2_device		v4l2_dev; /* mutual exclusion */
509eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct mutex			lock;
519eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct device			*dev;
529eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timb_video_platform_data pdata;
539eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct v4l2_subdev		*sd_enc;	/* encoder */
549eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	bool				opened;
559eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors};
569eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
579eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstruct timblogiw_tvnorm {
589eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	v4l2_std_id std;
599eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	u16     width;
609eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	u16     height;
619eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	u8	fps;
629eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors};
639eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
649eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstruct timblogiw_fh {
659eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct videobuf_queue		vb_vidq;
669eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_tvnorm const	*cur_norm;
679eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct list_head		capture;
689eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct dma_chan			*chan;
699eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	spinlock_t			queue_lock; /* mutual exclusion */
709eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	unsigned int			frame_count;
719eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors};
729eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
739eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstruct timblogiw_buffer {
749eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	/* common v4l buffer stuff -- must be first */
759eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct videobuf_buffer	vb;
769eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct scatterlist	sg[16];
779eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dma_cookie_t		cookie;
789eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh	*fh;
799eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors};
809eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
819eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsconst struct timblogiw_tvnorm timblogiw_tvnorms[] = {
829eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	{
839eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		.std			= V4L2_STD_PAL,
849eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		.width			= 720,
859eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		.height			= 576,
869eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		.fps			= 25
879eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	},
889eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	{
899eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		.std			= V4L2_STD_NTSC,
909eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		.width			= 720,
919eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		.height			= 480,
929eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		.fps			= 30
939eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	}
949eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors};
959eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
969eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_bytes_per_line(const struct timblogiw_tvnorm *norm)
979eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
989eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return norm->width * 2;
999eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
1009eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
1019eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
1029eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_frame_size(const struct timblogiw_tvnorm *norm)
1039eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
1049eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return norm->height * timblogiw_bytes_per_line(norm);
1059eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
1069eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
1079eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic const struct timblogiw_tvnorm *timblogiw_get_norm(const v4l2_std_id std)
1089eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
1099eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	int i;
1109eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	for (i = 0; i < ARRAY_SIZE(timblogiw_tvnorms); i++)
1119eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		if (timblogiw_tvnorms[i].std & std)
1129eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			return timblogiw_tvnorms + i;
1139eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
1149eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	/* default to first element */
1159eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return timblogiw_tvnorms;
1169eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
1179eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
1189eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic void timblogiw_dma_cb(void *data)
1199eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
1209eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_buffer *buf = data;
1219eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = buf->fh;
1229eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct videobuf_buffer *vb = &buf->vb;
1239eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
1249eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	spin_lock(&fh->queue_lock);
1259eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
1269eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	/* mark the transfer done */
1279eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	buf->cookie = -1;
1289eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
1299eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	fh->frame_count++;
1309eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
1319eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (vb->state != VIDEOBUF_ERROR) {
1329eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		list_del(&vb->queue);
1339eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		do_gettimeofday(&vb->ts);
1349eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		vb->field_count = fh->frame_count * 2;
1359eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		vb->state = VIDEOBUF_DONE;
1369eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
1379eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		wake_up(&vb->done);
1389eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	}
1399eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
1409eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (!list_empty(&fh->capture)) {
1419eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		vb = list_entry(fh->capture.next, struct videobuf_buffer,
1429eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			queue);
1439eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		vb->state = VIDEOBUF_ACTIVE;
1449eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	}
1459eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
1469eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	spin_unlock(&fh->queue_lock);
1479eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
1489eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
1499eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic bool timblogiw_dma_filter_fn(struct dma_chan *chan, void *filter_param)
1509eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
15161ea3aa5bf309333c6655ccef825b4a765bff219Hans Verkuil	return chan->chan_id == (uintptr_t)filter_param;
1529eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
1539eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
1549eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors/* IOCTL functions */
1559eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
1569eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_g_fmt(struct file *file, void  *priv,
1579eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct v4l2_format *format)
1589eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
1599eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
1609eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw *lw = video_get_drvdata(vdev);
1619eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = priv;
1629eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
1639eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s entry\n", __func__);
1649eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
1659eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1669eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		return -EINVAL;
1679eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
1689eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	mutex_lock(&lw->lock);
1699eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
1709eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	format->fmt.pix.width = fh->cur_norm->width;
1719eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	format->fmt.pix.height = fh->cur_norm->height;
1729eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
1739eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	format->fmt.pix.bytesperline = timblogiw_bytes_per_line(fh->cur_norm);
1749eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	format->fmt.pix.sizeimage = timblogiw_frame_size(fh->cur_norm);
1759eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	format->fmt.pix.field = V4L2_FIELD_NONE;
1769eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
1779eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	mutex_unlock(&lw->lock);
1789eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
1799eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return 0;
1809eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
1819eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
1829eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_try_fmt(struct file *file, void  *priv,
1839eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct v4l2_format *format)
1849eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
1859eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
1869eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct v4l2_pix_format *pix = &format->fmt.pix;
1879eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
1889eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev,
1899eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		"%s - width=%d, height=%d, pixelformat=%d, field=%d\n"
1909eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		"bytes per line %d, size image: %d, colorspace: %d\n",
1919eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		__func__,
1929eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		pix->width, pix->height, pix->pixelformat, pix->field,
1939eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		pix->bytesperline, pix->sizeimage, pix->colorspace);
1949eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
1959eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1969eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		return -EINVAL;
1979eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
1989eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (pix->field != V4L2_FIELD_NONE)
1999eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		return -EINVAL;
2009eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
2019eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (pix->pixelformat != V4L2_PIX_FMT_UYVY)
2029eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		return -EINVAL;
2039eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
2049eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return 0;
2059eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
2069eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
2079eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_s_fmt(struct file *file, void  *priv,
2089eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct v4l2_format *format)
2099eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
2109eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
2119eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw *lw = video_get_drvdata(vdev);
2129eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = priv;
2139eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct v4l2_pix_format *pix = &format->fmt.pix;
2149eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	int err;
2159eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
2169eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	mutex_lock(&lw->lock);
2179eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
2189eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	err = timblogiw_try_fmt(file, priv, format);
2199eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (err)
2209eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		goto out;
2219eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
2229eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (videobuf_queue_is_busy(&fh->vb_vidq)) {
2239eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		dev_err(&vdev->dev, "%s queue busy\n", __func__);
2249eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		err = -EBUSY;
2259eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		goto out;
2269eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	}
2279eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
2289eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	pix->width = fh->cur_norm->width;
2299eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	pix->height = fh->cur_norm->height;
2309eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
2319eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsout:
2329eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	mutex_unlock(&lw->lock);
2339eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return err;
2349eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
2359eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
2369eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_querycap(struct file *file, void  *priv,
2379eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct v4l2_capability *cap)
2389eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
2399eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
2409eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
2419eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s: Entry\n",  __func__);
2429eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	memset(cap, 0, sizeof(*cap));
2439eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	strncpy(cap->card, TIMBLOGIWIN_NAME, sizeof(cap->card)-1);
244dcd745b723efc875ec5a8f44be028bd0704b12d6Dan Carpenter	strncpy(cap->driver, DRIVER_NAME, sizeof(cap->driver) - 1);
2459eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	strlcpy(cap->bus_info, vdev->name, sizeof(cap->bus_info));
2469eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	cap->version = TIMBLOGIW_VERSION_CODE;
2479eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
2489eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		V4L2_CAP_READWRITE;
2499eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
2509eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return 0;
2519eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
2529eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
2539eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_enum_fmt(struct file *file, void  *priv,
2549eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct v4l2_fmtdesc *fmt)
2559eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
2569eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
2579eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
2589eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s, index: %d\n",  __func__, fmt->index);
2599eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
2609eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (fmt->index != 0)
2619eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		return -EINVAL;
2629eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	memset(fmt, 0, sizeof(*fmt));
2639eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	fmt->index = 0;
2649eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2659eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	strncpy(fmt->description, "4:2:2, packed, YUYV",
2669eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		sizeof(fmt->description)-1);
2679eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	fmt->pixelformat = V4L2_PIX_FMT_UYVY;
2689eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
2699eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return 0;
2709eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
2719eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
2729eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_g_parm(struct file *file, void *priv,
2739eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct v4l2_streamparm *sp)
2749eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
2759eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = priv;
2769eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct v4l2_captureparm *cp = &sp->parm.capture;
2779eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
2789eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	cp->capability = V4L2_CAP_TIMEPERFRAME;
2799eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	cp->timeperframe.numerator = 1;
2809eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	cp->timeperframe.denominator = fh->cur_norm->fps;
2819eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
2829eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return 0;
2839eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
2849eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
2859eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_reqbufs(struct file *file, void  *priv,
2869eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct v4l2_requestbuffers *rb)
2879eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
2889eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
2899eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = priv;
2909eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
2919eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
2929eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
2939eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return videobuf_reqbufs(&fh->vb_vidq, rb);
2949eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
2959eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
2969eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_querybuf(struct file *file, void  *priv,
2979eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct v4l2_buffer *b)
2989eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
2999eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
3009eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = priv;
3019eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3029eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
3039eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3049eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return videobuf_querybuf(&fh->vb_vidq, b);
3059eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
3069eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3079eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_qbuf(struct file *file, void  *priv, struct v4l2_buffer *b)
3089eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
3099eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
3109eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = priv;
3119eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3129eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
3139eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3149eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return videobuf_qbuf(&fh->vb_vidq, b);
3159eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
3169eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3179eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_dqbuf(struct file *file, void  *priv,
3189eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct v4l2_buffer *b)
3199eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
3209eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
3219eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = priv;
3229eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3239eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
3249eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3259eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
3269eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
3279eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3289eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_g_std(struct file *file, void  *priv, v4l2_std_id *std)
3299eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
3309eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
3319eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = priv;
3329eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3339eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
3349eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3359eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	*std = fh->cur_norm->std;
3369eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return 0;
3379eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
3389eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3399eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_s_std(struct file *file, void  *priv, v4l2_std_id *std)
3409eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
3419eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
3429eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw *lw = video_get_drvdata(vdev);
3439eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = priv;
3449eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	int err = 0;
3459eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3469eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
3479eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3489eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	mutex_lock(&lw->lock);
3499eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3509eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (TIMBLOGIW_HAS_DECODER(lw))
3519eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		err = v4l2_subdev_call(lw->sd_enc, core, s_std, *std);
3529eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3539eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (!err)
3549eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		fh->cur_norm = timblogiw_get_norm(*std);
3559eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3569eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	mutex_unlock(&lw->lock);
3579eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3589eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return err;
3599eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
3609eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3619eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_enuminput(struct file *file, void  *priv,
3629eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct v4l2_input *inp)
3639eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
3649eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
3659eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	int i;
3669eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3679eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s: Entry\n",  __func__);
3689eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3699eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (inp->index != 0)
3709eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		return -EINVAL;
3719eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3729eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	inp->index = 0;
3739eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3749eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	strncpy(inp->name, "Timb input 1", sizeof(inp->name) - 1);
3759eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	inp->type = V4L2_INPUT_TYPE_CAMERA;
3769eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3779eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	inp->std = 0;
3789eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	for (i = 0; i < ARRAY_SIZE(timblogiw_tvnorms); i++)
3799eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		inp->std |= timblogiw_tvnorms[i].std;
3809eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3819eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return 0;
3829eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
3839eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3849eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_g_input(struct file *file, void  *priv,
3859eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	unsigned int *input)
3869eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
3879eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
3889eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3899eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s: Entry\n",  __func__);
3909eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3919eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	*input = 0;
3929eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3939eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return 0;
3949eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
3959eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3969eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_s_input(struct file *file, void  *priv, unsigned int input)
3979eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
3989eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
3999eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4009eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s: Entry\n",  __func__);
4019eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4029eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (input != 0)
4039eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		return -EINVAL;
4049eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return 0;
4059eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
4069eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4079eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_streamon(struct file *file, void  *priv, unsigned int type)
4089eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
4099eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
4109eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = priv;
4119eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4129eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
4139eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4149eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
4159eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		dev_dbg(&vdev->dev, "%s - No capture device\n", __func__);
4169eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		return -EINVAL;
4179eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	}
4189eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4199eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	fh->frame_count = 0;
4209eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return videobuf_streamon(&fh->vb_vidq);
4219eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
4229eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4239eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_streamoff(struct file *file, void  *priv,
4249eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	unsigned int type)
4259eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
4269eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
4279eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = priv;
4289eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4299eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s entry\n",  __func__);
4309eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4319eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
4329eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		return -EINVAL;
4339eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4349eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return videobuf_streamoff(&fh->vb_vidq);
4359eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
4369eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4379eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_querystd(struct file *file, void  *priv, v4l2_std_id *std)
4389eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
4399eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
4409eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw *lw = video_get_drvdata(vdev);
4419eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = priv;
4429eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4439eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s entry\n",  __func__);
4449eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4459eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (TIMBLOGIW_HAS_DECODER(lw))
4469eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		return v4l2_subdev_call(lw->sd_enc, video, querystd, std);
4479eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	else {
4489eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		*std = fh->cur_norm->std;
4499eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		return 0;
4509eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	}
4519eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
4529eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4539eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_enum_framesizes(struct file *file, void  *priv,
4549eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct v4l2_frmsizeenum *fsize)
4559eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
4569eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
4579eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = priv;
4589eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4599eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s - index: %d, format: %d\n",  __func__,
4609eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		fsize->index, fsize->pixel_format);
4619eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4629eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if ((fsize->index != 0) ||
4639eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		(fsize->pixel_format != V4L2_PIX_FMT_UYVY))
4649eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		return -EINVAL;
4659eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4669eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
4679eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	fsize->discrete.width = fh->cur_norm->width;
4689eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	fsize->discrete.height = fh->cur_norm->height;
4699eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4709eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return 0;
4719eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
4729eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4739eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors/* Video buffer functions */
4749eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4759eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
4769eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	unsigned int *size)
4779eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
4789eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = vq->priv_data;
4799eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4809eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	*size = timblogiw_frame_size(fh->cur_norm);
4819eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4829eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (!*count)
4839eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		*count = 32;
4849eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4859eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	while (*size * *count > TIMBLOGIW_MAX_VIDEO_MEM * 1024 * 1024)
4869eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		(*count)--;
4879eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4889eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return 0;
4899eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
4909eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4919eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
4929eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	enum v4l2_field field)
4939eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
4949eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = vq->priv_data;
4959eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer,
4969eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		vb);
4979eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	unsigned int data_size = timblogiw_frame_size(fh->cur_norm);
4989eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	int err = 0;
4999eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5009eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (vb->baddr && vb->bsize < data_size)
5019eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		/* User provided buffer, but it is too small */
5029eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		return -ENOMEM;
5039eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5049eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	vb->size = data_size;
5059eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	vb->width = fh->cur_norm->width;
5069eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	vb->height = fh->cur_norm->height;
5079eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	vb->field = field;
5089eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5099eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (vb->state == VIDEOBUF_NEEDS_INIT) {
5109eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		int i;
5119eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		unsigned int size;
5129eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		unsigned int bytes_per_desc = TIMBLOGIW_LINES_PER_DESC *
5139eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			timblogiw_bytes_per_line(fh->cur_norm);
5149eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		dma_addr_t addr;
5159eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5169eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		sg_init_table(buf->sg, ARRAY_SIZE(buf->sg));
5179eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5189eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		err = videobuf_iolock(vq, vb, NULL);
5199eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		if (err)
5209eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			goto err;
5219eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5229eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		addr = videobuf_to_dma_contig(vb);
5239eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		for (i = 0, size = 0; size < data_size; i++) {
5249eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			sg_dma_address(buf->sg + i) = addr + size;
5259eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			size += bytes_per_desc;
5269eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			sg_dma_len(buf->sg + i) = (size > data_size) ?
5279eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors				(bytes_per_desc - (size - data_size)) :
5289eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors				bytes_per_desc;
5299eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		}
5309eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5319eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		vb->state = VIDEOBUF_PREPARED;
5329eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		buf->cookie = -1;
5339eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		buf->fh = fh;
5349eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	}
5359eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5369eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return 0;
5379eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5389eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforserr:
5399eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	videobuf_dma_contig_free(vq, vb);
5409eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	vb->state = VIDEOBUF_NEEDS_INIT;
5419eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return err;
5429eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
5439eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5449eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
5459eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
5469eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = vq->priv_data;
5479eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer,
5489eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		vb);
5499eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct dma_async_tx_descriptor *desc;
5509eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	int sg_elems;
5519eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	int bytes_per_desc = TIMBLOGIW_LINES_PER_DESC *
5529eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		timblogiw_bytes_per_line(fh->cur_norm);
5539eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5549eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	sg_elems = timblogiw_frame_size(fh->cur_norm) / bytes_per_desc;
5559eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	sg_elems +=
5569eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		(timblogiw_frame_size(fh->cur_norm) % bytes_per_desc) ? 1 : 0;
5579eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5589eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (list_empty(&fh->capture))
5599eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		vb->state = VIDEOBUF_ACTIVE;
5609eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	else
5619eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		vb->state = VIDEOBUF_QUEUED;
5629eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5639eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	list_add_tail(&vb->queue, &fh->capture);
5649eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5659eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	spin_unlock_irq(&fh->queue_lock);
5669eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
56716052827d98fbc13c31ebad560af4bd53e2b4dd5Alexandre Bounine	desc = dmaengine_prep_slave_sg(fh->chan,
5681003cab8276cd34d9deab8ca9d148ee59f7728a7Vinod Koul		buf->sg, sg_elems, DMA_DEV_TO_MEM,
5699eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP);
5709eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (!desc) {
5719eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		spin_lock_irq(&fh->queue_lock);
5729eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		list_del_init(&vb->queue);
5739eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		vb->state = VIDEOBUF_PREPARED;
5749eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		return;
5759eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	}
5769eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5779eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	desc->callback_param = buf;
5789eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	desc->callback = timblogiw_dma_cb;
5799eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5809eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	buf->cookie = desc->tx_submit(desc);
5819eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5829eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	spin_lock_irq(&fh->queue_lock);
5839eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
5849eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5859eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic void buffer_release(struct videobuf_queue *vq,
5869eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct videobuf_buffer *vb)
5879eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
5889eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = vq->priv_data;
5899eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer,
5909eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		vb);
5919eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5929eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	videobuf_waiton(vq, vb, 0, 0);
5939eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (buf->cookie >= 0)
5949eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		dma_sync_wait(fh->chan, buf->cookie);
5959eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5969eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	videobuf_dma_contig_free(vq, vb);
5979eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	vb->state = VIDEOBUF_NEEDS_INIT;
5989eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
5999eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6009eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic struct videobuf_queue_ops timblogiw_video_qops = {
6019eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.buf_setup      = buffer_setup,
6029eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.buf_prepare    = buffer_prepare,
6039eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.buf_queue      = buffer_queue,
6049eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.buf_release    = buffer_release,
6059eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors};
6069eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6079eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors/* Device Operations functions */
6089eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6099eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_open(struct file *file)
6109eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
6119eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
6129eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw *lw = video_get_drvdata(vdev);
6139eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh;
6149eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	v4l2_std_id std;
6159eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dma_cap_mask_t mask;
6169eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	int err = 0;
6179eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6189eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s: entry\n", __func__);
6199eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6209eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	mutex_lock(&lw->lock);
6219eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (lw->opened) {
6229eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		err = -EBUSY;
6239eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		goto out;
6249eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	}
6259eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6269eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (TIMBLOGIW_HAS_DECODER(lw) && !lw->sd_enc) {
6279eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		struct i2c_adapter *adapt;
6289eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6299eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		/* find the video decoder */
6309eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		adapt = i2c_get_adapter(lw->pdata.i2c_adapter);
6319eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		if (!adapt) {
6329eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			dev_err(&vdev->dev, "No I2C bus #%d\n",
6339eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors				lw->pdata.i2c_adapter);
6349eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			err = -ENODEV;
6359eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			goto out;
6369eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		}
6379eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6389eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		/* now find the encoder */
6399eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		lw->sd_enc = v4l2_i2c_new_subdev_board(&lw->v4l2_dev, adapt,
6409eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			lw->pdata.encoder.info, NULL);
6419eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6429eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		i2c_put_adapter(adapt);
6439eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6449eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		if (!lw->sd_enc) {
6459eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			dev_err(&vdev->dev, "Failed to get encoder: %s\n",
6469eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors				lw->pdata.encoder.module_name);
6479eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			err = -ENODEV;
6489eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			goto out;
6499eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		}
6509eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	}
6519eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6529eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
6539eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (!fh) {
6549eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		err = -ENOMEM;
6559eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		goto out;
6569eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	}
6579eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6589eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	fh->cur_norm = timblogiw_tvnorms;
6599eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	timblogiw_querystd(file, fh, &std);
6609eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	fh->cur_norm = timblogiw_get_norm(std);
6619eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6629eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	INIT_LIST_HEAD(&fh->capture);
6639eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	spin_lock_init(&fh->queue_lock);
6649eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6659eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dma_cap_zero(mask);
6669eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dma_cap_set(DMA_SLAVE, mask);
6679eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dma_cap_set(DMA_PRIVATE, mask);
6689eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6699eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	/* find the DMA channel */
6709eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	fh->chan = dma_request_channel(mask, timblogiw_dma_filter_fn,
67161ea3aa5bf309333c6655ccef825b4a765bff219Hans Verkuil			(void *)(uintptr_t)lw->pdata.dma_channel);
6729eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (!fh->chan) {
6739eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		dev_err(&vdev->dev, "Failed to get DMA channel\n");
6749eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		kfree(fh);
6759eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		err = -ENODEV;
6769eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		goto out;
6779eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	}
6789eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6799eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	file->private_data = fh;
6809eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	videobuf_queue_dma_contig_init(&fh->vb_vidq,
6819eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		&timblogiw_video_qops, lw->dev, &fh->queue_lock,
6829eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
6839eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		sizeof(struct timblogiw_buffer), fh, NULL);
6849eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6859eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	lw->opened = true;
6869eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsout:
6879eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	mutex_unlock(&lw->lock);
6889eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6899eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return err;
6909eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
6919eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6929eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_close(struct file *file)
6939eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
6949eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
6959eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw *lw = video_get_drvdata(vdev);
6969eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = file->private_data;
6979eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6989eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s: Entry\n",  __func__);
6999eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7009eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	videobuf_stop(&fh->vb_vidq);
7019eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	videobuf_mmap_free(&fh->vb_vidq);
7029eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7039eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dma_release_channel(fh->chan);
7049eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7059eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	kfree(fh);
7069eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7079eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	mutex_lock(&lw->lock);
7089eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	lw->opened = false;
7099eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	mutex_unlock(&lw->lock);
7109eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return 0;
7119eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
7129eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7139eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic ssize_t timblogiw_read(struct file *file, char __user *data,
7149eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	size_t count, loff_t *ppos)
7159eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
7169eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
7179eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = file->private_data;
7189eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7199eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
7209eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7219eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return videobuf_read_stream(&fh->vb_vidq, data, count, ppos, 0,
7229eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		file->f_flags & O_NONBLOCK);
7239eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
7249eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7259eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic unsigned int timblogiw_poll(struct file *file,
7269eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct poll_table_struct *wait)
7279eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
7289eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
7299eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = file->private_data;
7309eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7319eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
7329eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7339eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return videobuf_poll_stream(file, &fh->vb_vidq, wait);
7349eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
7359eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7369eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_mmap(struct file *file, struct vm_area_struct *vma)
7379eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
7389eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
7399eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = file->private_data;
7409eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7419eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s: entry\n", __func__);
7429eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7439eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return videobuf_mmap_mapper(&fh->vb_vidq, vma);
7449eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
7459eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7469eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors/* Platform device functions */
7479eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
74849aefd2bcda80d33497f0f26702c67e372cacef3Stephen Rothwellstatic __devinitconst struct v4l2_ioctl_ops timblogiw_ioctl_ops = {
7499eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_querycap		= timblogiw_querycap,
7509eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_enum_fmt_vid_cap	= timblogiw_enum_fmt,
7519eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_g_fmt_vid_cap		= timblogiw_g_fmt,
7529eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_try_fmt_vid_cap		= timblogiw_try_fmt,
7539eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_s_fmt_vid_cap		= timblogiw_s_fmt,
7549eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_g_parm			= timblogiw_g_parm,
7559eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_reqbufs			= timblogiw_reqbufs,
7569eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_querybuf		= timblogiw_querybuf,
7579eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_qbuf			= timblogiw_qbuf,
7589eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_dqbuf			= timblogiw_dqbuf,
7599eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_g_std			= timblogiw_g_std,
7609eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_s_std			= timblogiw_s_std,
7619eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_enum_input		= timblogiw_enuminput,
7629eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_g_input			= timblogiw_g_input,
7639eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_s_input			= timblogiw_s_input,
7649eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_streamon		= timblogiw_streamon,
7659eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_streamoff		= timblogiw_streamoff,
7669eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_querystd		= timblogiw_querystd,
7679eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_enum_framesizes		= timblogiw_enum_framesizes,
7689eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors};
7699eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
77049aefd2bcda80d33497f0f26702c67e372cacef3Stephen Rothwellstatic __devinitconst struct v4l2_file_operations timblogiw_fops = {
7719eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.owner		= THIS_MODULE,
7729eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.open		= timblogiw_open,
7739eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.release	= timblogiw_close,
7749eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.unlocked_ioctl		= video_ioctl2, /* V4L2 ioctl handler */
7759eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.mmap		= timblogiw_mmap,
7769eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.read		= timblogiw_read,
7779eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.poll		= timblogiw_poll,
7789eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors};
7799eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
78049aefd2bcda80d33497f0f26702c67e372cacef3Stephen Rothwellstatic __devinitconst struct video_device timblogiw_template = {
7819eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.name		= TIMBLOGIWIN_NAME,
7829eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.fops		= &timblogiw_fops,
7839eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.ioctl_ops	= &timblogiw_ioctl_ops,
7849eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.release	= video_device_release_empty,
7859eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.minor		= -1,
7869eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.tvnorms	= V4L2_STD_PAL | V4L2_STD_NTSC
7879eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors};
7889eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7899eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int __devinit timblogiw_probe(struct platform_device *pdev)
7909eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
7919eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	int err;
7929eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw *lw = NULL;
7933271d382c3ffe61ef3d059ef47e635dbe031030eSamuel Ortiz	struct timb_video_platform_data *pdata = pdev->dev.platform_data;
7949eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7959eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (!pdata) {
7969eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		dev_err(&pdev->dev, "No platform data\n");
7979eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		err = -EINVAL;
7989eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		goto err;
7999eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	}
8009eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8019eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (!pdata->encoder.module_name)
8029eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		dev_info(&pdev->dev, "Running without decoder\n");
8039eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8049eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	lw = kzalloc(sizeof(*lw), GFP_KERNEL);
8059eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (!lw) {
8069eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		err = -ENOMEM;
8079eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		goto err;
8089eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	}
8099eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8109eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (pdev->dev.parent)
8119eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		lw->dev = pdev->dev.parent;
8129eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	else
8139eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		lw->dev = &pdev->dev;
8149eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8159eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	memcpy(&lw->pdata, pdata, sizeof(lw->pdata));
8169eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8179eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	mutex_init(&lw->lock);
8189eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8199eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	lw->video_dev = timblogiw_template;
8209eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8219eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	strlcpy(lw->v4l2_dev.name, DRIVER_NAME, sizeof(lw->v4l2_dev.name));
8229eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	err = v4l2_device_register(NULL, &lw->v4l2_dev);
8239eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (err)
8249eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		goto err_register;
8259eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8269eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	lw->video_dev.v4l2_dev = &lw->v4l2_dev;
8279eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8289eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	platform_set_drvdata(pdev, lw);
8299eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	video_set_drvdata(&lw->video_dev, lw);
8309eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8319eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	err = video_register_device(&lw->video_dev, VFL_TYPE_GRABBER, 0);
8329eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (err) {
8339eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		dev_err(&pdev->dev, "Error reg video: %d\n", err);
8349eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		goto err_request;
8359eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	}
8369eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8379eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8389eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return 0;
8399eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8409eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforserr_request:
8419eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	platform_set_drvdata(pdev, NULL);
8429eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	v4l2_device_unregister(&lw->v4l2_dev);
8439eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforserr_register:
8449eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	kfree(lw);
8459eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforserr:
8469eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_err(&pdev->dev, "Failed to register: %d\n", err);
8479eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8489eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return err;
8499eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
8509eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8519eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int __devexit timblogiw_remove(struct platform_device *pdev)
8529eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
8539eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw *lw = platform_get_drvdata(pdev);
8549eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8559eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	video_unregister_device(&lw->video_dev);
8569eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8579eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	v4l2_device_unregister(&lw->v4l2_dev);
8589eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8599eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	kfree(lw);
8609eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8619eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	platform_set_drvdata(pdev, NULL);
8629eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8639eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return 0;
8649eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
8659eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8669eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic struct platform_driver timblogiw_platform_driver = {
8679eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.driver = {
8689eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		.name	= DRIVER_NAME,
8699eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		.owner	= THIS_MODULE,
8709eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	},
8719eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.probe		= timblogiw_probe,
8729eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.remove		= __devexit_p(timblogiw_remove),
8739eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors};
8749eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8751d6629b1561ad34a6e6d17ece00bd65e1bab3724Axel Linmodule_platform_driver(timblogiw_platform_driver);
8769eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8779eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard RöjforsMODULE_DESCRIPTION(TIMBLOGIWIN_NAME);
8789eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard RöjforsMODULE_AUTHOR("Pelagicore AB <info@pelagicore.com>");
8799eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard RöjforsMODULE_LICENSE("GPL v2");
8809eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard RöjforsMODULE_ALIAS("platform:"DRIVER_NAME);
881