timblogiw.c revision dcd745b723efc875ec5a8f44be028bd0704b12d6
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/version.h>
249eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors#include <linux/platform_device.h>
259eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors#include <linux/slab.h>
269eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors#include <linux/dmaengine.h>
279eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors#include <linux/scatterlist.h>
289eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors#include <linux/interrupt.h>
299eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors#include <linux/list.h>
309eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors#include <linux/i2c.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{
1519eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return chan->chan_id == (int)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	memset(inp, 0, sizeof(*inp));
3739eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	inp->index = 0;
3749eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3759eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	strncpy(inp->name, "Timb input 1", sizeof(inp->name) - 1);
3769eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	inp->type = V4L2_INPUT_TYPE_CAMERA;
3779eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3789eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	inp->std = 0;
3799eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	for (i = 0; i < ARRAY_SIZE(timblogiw_tvnorms); i++)
3809eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		inp->std |= timblogiw_tvnorms[i].std;
3819eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3829eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return 0;
3839eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
3849eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3859eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_g_input(struct file *file, void  *priv,
3869eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	unsigned int *input)
3879eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
3889eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
3899eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3909eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s: Entry\n",  __func__);
3919eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3929eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	*input = 0;
3939eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3949eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return 0;
3959eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
3969eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
3979eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_s_input(struct file *file, void  *priv, unsigned int input)
3989eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
3999eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
4009eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4019eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s: Entry\n",  __func__);
4029eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4039eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (input != 0)
4049eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		return -EINVAL;
4059eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return 0;
4069eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
4079eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4089eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_streamon(struct file *file, void  *priv, unsigned int type)
4099eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
4109eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
4119eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = priv;
4129eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4139eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
4149eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4159eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
4169eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		dev_dbg(&vdev->dev, "%s - No capture device\n", __func__);
4179eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		return -EINVAL;
4189eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	}
4199eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4209eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	fh->frame_count = 0;
4219eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return videobuf_streamon(&fh->vb_vidq);
4229eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
4239eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4249eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_streamoff(struct file *file, void  *priv,
4259eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	unsigned int type)
4269eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
4279eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
4289eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = priv;
4299eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4309eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s entry\n",  __func__);
4319eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4329eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
4339eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		return -EINVAL;
4349eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4359eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return videobuf_streamoff(&fh->vb_vidq);
4369eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
4379eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4389eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_querystd(struct file *file, void  *priv, v4l2_std_id *std)
4399eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
4409eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
4419eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw *lw = video_get_drvdata(vdev);
4429eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = priv;
4439eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4449eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s entry\n",  __func__);
4459eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4469eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (TIMBLOGIW_HAS_DECODER(lw))
4479eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		return v4l2_subdev_call(lw->sd_enc, video, querystd, std);
4489eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	else {
4499eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		*std = fh->cur_norm->std;
4509eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		return 0;
4519eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	}
4529eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
4539eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4549eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_enum_framesizes(struct file *file, void  *priv,
4559eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct v4l2_frmsizeenum *fsize)
4569eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
4579eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
4589eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = priv;
4599eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4609eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s - index: %d, format: %d\n",  __func__,
4619eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		fsize->index, fsize->pixel_format);
4629eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4639eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if ((fsize->index != 0) ||
4649eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		(fsize->pixel_format != V4L2_PIX_FMT_UYVY))
4659eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		return -EINVAL;
4669eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4679eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
4689eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	fsize->discrete.width = fh->cur_norm->width;
4699eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	fsize->discrete.height = fh->cur_norm->height;
4709eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4719eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return 0;
4729eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
4739eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4749eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors/* Video buffer functions */
4759eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4769eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
4779eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	unsigned int *size)
4789eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
4799eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = vq->priv_data;
4809eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4819eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	*size = timblogiw_frame_size(fh->cur_norm);
4829eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4839eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (!*count)
4849eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		*count = 32;
4859eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4869eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	while (*size * *count > TIMBLOGIW_MAX_VIDEO_MEM * 1024 * 1024)
4879eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		(*count)--;
4889eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4899eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return 0;
4909eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
4919eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
4929eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
4939eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	enum v4l2_field field)
4949eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
4959eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = vq->priv_data;
4969eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer,
4979eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		vb);
4989eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	unsigned int data_size = timblogiw_frame_size(fh->cur_norm);
4999eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	int err = 0;
5009eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5019eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (vb->baddr && vb->bsize < data_size)
5029eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		/* User provided buffer, but it is too small */
5039eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		return -ENOMEM;
5049eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5059eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	vb->size = data_size;
5069eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	vb->width = fh->cur_norm->width;
5079eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	vb->height = fh->cur_norm->height;
5089eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	vb->field = field;
5099eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5109eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (vb->state == VIDEOBUF_NEEDS_INIT) {
5119eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		int i;
5129eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		unsigned int size;
5139eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		unsigned int bytes_per_desc = TIMBLOGIW_LINES_PER_DESC *
5149eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			timblogiw_bytes_per_line(fh->cur_norm);
5159eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		dma_addr_t addr;
5169eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5179eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		sg_init_table(buf->sg, ARRAY_SIZE(buf->sg));
5189eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5199eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		err = videobuf_iolock(vq, vb, NULL);
5209eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		if (err)
5219eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			goto err;
5229eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5239eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		addr = videobuf_to_dma_contig(vb);
5249eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		for (i = 0, size = 0; size < data_size; i++) {
5259eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			sg_dma_address(buf->sg + i) = addr + size;
5269eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			size += bytes_per_desc;
5279eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			sg_dma_len(buf->sg + i) = (size > data_size) ?
5289eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors				(bytes_per_desc - (size - data_size)) :
5299eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors				bytes_per_desc;
5309eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		}
5319eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5329eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		vb->state = VIDEOBUF_PREPARED;
5339eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		buf->cookie = -1;
5349eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		buf->fh = fh;
5359eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	}
5369eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5379eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return 0;
5389eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5399eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforserr:
5409eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	videobuf_dma_contig_free(vq, vb);
5419eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	vb->state = VIDEOBUF_NEEDS_INIT;
5429eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return err;
5439eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
5449eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5459eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
5469eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
5479eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = vq->priv_data;
5489eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer,
5499eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		vb);
5509eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct dma_async_tx_descriptor *desc;
5519eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	int sg_elems;
5529eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	int bytes_per_desc = TIMBLOGIW_LINES_PER_DESC *
5539eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		timblogiw_bytes_per_line(fh->cur_norm);
5549eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5559eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	sg_elems = timblogiw_frame_size(fh->cur_norm) / bytes_per_desc;
5569eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	sg_elems +=
5579eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		(timblogiw_frame_size(fh->cur_norm) % bytes_per_desc) ? 1 : 0;
5589eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5599eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (list_empty(&fh->capture))
5609eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		vb->state = VIDEOBUF_ACTIVE;
5619eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	else
5629eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		vb->state = VIDEOBUF_QUEUED;
5639eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5649eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	list_add_tail(&vb->queue, &fh->capture);
5659eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5669eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	spin_unlock_irq(&fh->queue_lock);
5679eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5689eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	desc = fh->chan->device->device_prep_slave_sg(fh->chan,
5699eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		buf->sg, sg_elems, DMA_FROM_DEVICE,
5709eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP);
5719eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (!desc) {
5729eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		spin_lock_irq(&fh->queue_lock);
5739eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		list_del_init(&vb->queue);
5749eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		vb->state = VIDEOBUF_PREPARED;
5759eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		return;
5769eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	}
5779eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5789eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	desc->callback_param = buf;
5799eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	desc->callback = timblogiw_dma_cb;
5809eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5819eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	buf->cookie = desc->tx_submit(desc);
5829eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5839eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	spin_lock_irq(&fh->queue_lock);
5849eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
5859eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5869eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic void buffer_release(struct videobuf_queue *vq,
5879eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct videobuf_buffer *vb)
5889eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
5899eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = vq->priv_data;
5909eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_buffer *buf = container_of(vb, struct timblogiw_buffer,
5919eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		vb);
5929eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5939eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	videobuf_waiton(vq, vb, 0, 0);
5949eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (buf->cookie >= 0)
5959eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		dma_sync_wait(fh->chan, buf->cookie);
5969eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
5979eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	videobuf_dma_contig_free(vq, vb);
5989eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	vb->state = VIDEOBUF_NEEDS_INIT;
5999eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
6009eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6019eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic struct videobuf_queue_ops timblogiw_video_qops = {
6029eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.buf_setup      = buffer_setup,
6039eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.buf_prepare    = buffer_prepare,
6049eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.buf_queue      = buffer_queue,
6059eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.buf_release    = buffer_release,
6069eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors};
6079eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6089eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors/* Device Operations functions */
6099eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6109eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_open(struct file *file)
6119eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
6129eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
6139eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw *lw = video_get_drvdata(vdev);
6149eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh;
6159eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	v4l2_std_id std;
6169eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dma_cap_mask_t mask;
6179eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	int err = 0;
6189eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6199eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s: entry\n", __func__);
6209eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6219eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	mutex_lock(&lw->lock);
6229eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (lw->opened) {
6239eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		err = -EBUSY;
6249eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		goto out;
6259eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	}
6269eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6279eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (TIMBLOGIW_HAS_DECODER(lw) && !lw->sd_enc) {
6289eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		struct i2c_adapter *adapt;
6299eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6309eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		/* find the video decoder */
6319eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		adapt = i2c_get_adapter(lw->pdata.i2c_adapter);
6329eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		if (!adapt) {
6339eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			dev_err(&vdev->dev, "No I2C bus #%d\n",
6349eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors				lw->pdata.i2c_adapter);
6359eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			err = -ENODEV;
6369eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			goto out;
6379eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		}
6389eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6399eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		/* now find the encoder */
6409eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		lw->sd_enc = v4l2_i2c_new_subdev_board(&lw->v4l2_dev, adapt,
6419eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			lw->pdata.encoder.info, NULL);
6429eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6439eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		i2c_put_adapter(adapt);
6449eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6459eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		if (!lw->sd_enc) {
6469eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			dev_err(&vdev->dev, "Failed to get encoder: %s\n",
6479eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors				lw->pdata.encoder.module_name);
6489eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			err = -ENODEV;
6499eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			goto out;
6509eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		}
6519eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	}
6529eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6539eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
6549eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (!fh) {
6559eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		err = -ENOMEM;
6569eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		goto out;
6579eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	}
6589eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6599eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	fh->cur_norm = timblogiw_tvnorms;
6609eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	timblogiw_querystd(file, fh, &std);
6619eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	fh->cur_norm = timblogiw_get_norm(std);
6629eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6639eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	INIT_LIST_HEAD(&fh->capture);
6649eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	spin_lock_init(&fh->queue_lock);
6659eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6669eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dma_cap_zero(mask);
6679eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dma_cap_set(DMA_SLAVE, mask);
6689eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dma_cap_set(DMA_PRIVATE, mask);
6699eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6709eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	/* find the DMA channel */
6719eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	fh->chan = dma_request_channel(mask, timblogiw_dma_filter_fn,
6729eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors			(void *)lw->pdata.dma_channel);
6739eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (!fh->chan) {
6749eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		dev_err(&vdev->dev, "Failed to get DMA channel\n");
6759eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		kfree(fh);
6769eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		err = -ENODEV;
6779eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		goto out;
6789eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	}
6799eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6809eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	file->private_data = fh;
6819eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	videobuf_queue_dma_contig_init(&fh->vb_vidq,
6829eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		&timblogiw_video_qops, lw->dev, &fh->queue_lock,
6839eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
6849eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		sizeof(struct timblogiw_buffer), fh, NULL);
6859eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6869eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	lw->opened = true;
6879eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsout:
6889eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	mutex_unlock(&lw->lock);
6899eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6909eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return err;
6919eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
6929eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6939eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_close(struct file *file)
6949eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
6959eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
6969eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw *lw = video_get_drvdata(vdev);
6979eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = file->private_data;
6989eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
6999eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s: Entry\n",  __func__);
7009eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7019eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	videobuf_stop(&fh->vb_vidq);
7029eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	videobuf_mmap_free(&fh->vb_vidq);
7039eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7049eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dma_release_channel(fh->chan);
7059eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7069eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	kfree(fh);
7079eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7089eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	mutex_lock(&lw->lock);
7099eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	lw->opened = false;
7109eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	mutex_unlock(&lw->lock);
7119eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return 0;
7129eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
7139eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7149eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic ssize_t timblogiw_read(struct file *file, char __user *data,
7159eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	size_t count, loff_t *ppos)
7169eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
7179eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
7189eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = file->private_data;
7199eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7209eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
7219eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7229eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return videobuf_read_stream(&fh->vb_vidq, data, count, ppos, 0,
7239eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		file->f_flags & O_NONBLOCK);
7249eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
7259eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7269eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic unsigned int timblogiw_poll(struct file *file,
7279eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct poll_table_struct *wait)
7289eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
7299eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
7309eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = file->private_data;
7319eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7329eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s: entry\n",  __func__);
7339eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7349eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return videobuf_poll_stream(file, &fh->vb_vidq, wait);
7359eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
7369eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7379eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int timblogiw_mmap(struct file *file, struct vm_area_struct *vma)
7389eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
7399eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct video_device *vdev = video_devdata(file);
7409eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw_fh *fh = file->private_data;
7419eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7429eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_dbg(&vdev->dev, "%s: entry\n", __func__);
7439eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7449eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return videobuf_mmap_mapper(&fh->vb_vidq, vma);
7459eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
7469eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7479eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors/* Platform device functions */
7489eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
74949aefd2bcda80d33497f0f26702c67e372cacef3Stephen Rothwellstatic __devinitconst struct v4l2_ioctl_ops timblogiw_ioctl_ops = {
7509eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_querycap		= timblogiw_querycap,
7519eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_enum_fmt_vid_cap	= timblogiw_enum_fmt,
7529eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_g_fmt_vid_cap		= timblogiw_g_fmt,
7539eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_try_fmt_vid_cap		= timblogiw_try_fmt,
7549eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_s_fmt_vid_cap		= timblogiw_s_fmt,
7559eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_g_parm			= timblogiw_g_parm,
7569eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_reqbufs			= timblogiw_reqbufs,
7579eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_querybuf		= timblogiw_querybuf,
7589eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_qbuf			= timblogiw_qbuf,
7599eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_dqbuf			= timblogiw_dqbuf,
7609eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_g_std			= timblogiw_g_std,
7619eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_s_std			= timblogiw_s_std,
7629eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_enum_input		= timblogiw_enuminput,
7639eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_g_input			= timblogiw_g_input,
7649eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_s_input			= timblogiw_s_input,
7659eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_streamon		= timblogiw_streamon,
7669eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_streamoff		= timblogiw_streamoff,
7679eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_querystd		= timblogiw_querystd,
7689eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.vidioc_enum_framesizes		= timblogiw_enum_framesizes,
7699eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors};
7709eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
77149aefd2bcda80d33497f0f26702c67e372cacef3Stephen Rothwellstatic __devinitconst struct v4l2_file_operations timblogiw_fops = {
7729eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.owner		= THIS_MODULE,
7739eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.open		= timblogiw_open,
7749eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.release	= timblogiw_close,
7759eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.unlocked_ioctl		= video_ioctl2, /* V4L2 ioctl handler */
7769eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.mmap		= timblogiw_mmap,
7779eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.read		= timblogiw_read,
7789eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.poll		= timblogiw_poll,
7799eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors};
7809eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
78149aefd2bcda80d33497f0f26702c67e372cacef3Stephen Rothwellstatic __devinitconst struct video_device timblogiw_template = {
7829eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.name		= TIMBLOGIWIN_NAME,
7839eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.fops		= &timblogiw_fops,
7849eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.ioctl_ops	= &timblogiw_ioctl_ops,
7859eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.release	= video_device_release_empty,
7869eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.minor		= -1,
7879eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.tvnorms	= V4L2_STD_PAL | V4L2_STD_NTSC
7889eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors};
7899eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7909eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int __devinit timblogiw_probe(struct platform_device *pdev)
7919eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
7929eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	int err;
7939eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw *lw = NULL;
7949eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timb_video_platform_data *pdata = pdev->dev.platform_data;
7959eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
7969eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (!pdata) {
7979eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		dev_err(&pdev->dev, "No platform data\n");
7989eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		err = -EINVAL;
7999eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		goto err;
8009eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	}
8019eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8029eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (!pdata->encoder.module_name)
8039eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		dev_info(&pdev->dev, "Running without decoder\n");
8049eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8059eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	lw = kzalloc(sizeof(*lw), GFP_KERNEL);
8069eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (!lw) {
8079eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		err = -ENOMEM;
8089eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		goto err;
8099eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	}
8109eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8119eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (pdev->dev.parent)
8129eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		lw->dev = pdev->dev.parent;
8139eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	else
8149eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		lw->dev = &pdev->dev;
8159eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8169eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	memcpy(&lw->pdata, pdata, sizeof(lw->pdata));
8179eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8189eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	mutex_init(&lw->lock);
8199eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8209eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	lw->video_dev = timblogiw_template;
8219eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8229eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	strlcpy(lw->v4l2_dev.name, DRIVER_NAME, sizeof(lw->v4l2_dev.name));
8239eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	err = v4l2_device_register(NULL, &lw->v4l2_dev);
8249eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (err)
8259eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		goto err_register;
8269eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8279eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	lw->video_dev.v4l2_dev = &lw->v4l2_dev;
8289eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8299eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	platform_set_drvdata(pdev, lw);
8309eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	video_set_drvdata(&lw->video_dev, lw);
8319eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8329eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	err = video_register_device(&lw->video_dev, VFL_TYPE_GRABBER, 0);
8339eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	if (err) {
8349eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		dev_err(&pdev->dev, "Error reg video: %d\n", err);
8359eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		goto err_request;
8369eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	}
8379eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8389eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8399eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return 0;
8409eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8419eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforserr_request:
8429eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	platform_set_drvdata(pdev, NULL);
8439eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	v4l2_device_unregister(&lw->v4l2_dev);
8449eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforserr_register:
8459eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	kfree(lw);
8469eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforserr:
8479eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	dev_err(&pdev->dev, "Failed to register: %d\n", err);
8489eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8499eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return err;
8509eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
8519eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8529eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int __devexit timblogiw_remove(struct platform_device *pdev)
8539eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
8549eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	struct timblogiw *lw = platform_get_drvdata(pdev);
8559eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8569eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	video_unregister_device(&lw->video_dev);
8579eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8589eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	v4l2_device_unregister(&lw->v4l2_dev);
8599eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8609eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	kfree(lw);
8619eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8629eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	platform_set_drvdata(pdev, NULL);
8639eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8649eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return 0;
8659eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
8669eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8679eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic struct platform_driver timblogiw_platform_driver = {
8689eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.driver = {
8699eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		.name	= DRIVER_NAME,
8709eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors		.owner	= THIS_MODULE,
8719eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	},
8729eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.probe		= timblogiw_probe,
8739eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	.remove		= __devexit_p(timblogiw_remove),
8749eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors};
8759eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8769eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors/* Module functions */
8779eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8789eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic int __init timblogiw_init(void)
8799eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
8809eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	return platform_driver_register(&timblogiw_platform_driver);
8819eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
8829eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8839eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsstatic void __exit timblogiw_exit(void)
8849eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors{
8859eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors	platform_driver_unregister(&timblogiw_platform_driver);
8869eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors}
8879eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8889eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsmodule_init(timblogiw_init);
8899eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjforsmodule_exit(timblogiw_exit);
8909eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard Röjfors
8919eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard RöjforsMODULE_DESCRIPTION(TIMBLOGIWIN_NAME);
8929eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard RöjforsMODULE_AUTHOR("Pelagicore AB <info@pelagicore.com>");
8939eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard RöjforsMODULE_LICENSE("GPL v2");
8949eae42e5a216059a146b3fbbe24b4fdc0b10c723Richard RöjforsMODULE_ALIAS("platform:"DRIVER_NAME);
895