11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Motion Eye video4linux driver for Sony Vaio PictureBook
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2001-2004 Stelian Pop <stelian@popies.net>
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
696de0e252cedffad61b3cb5e05662c591898e69aJan Engelhardt * Copyright (C) 2001-2002 Alcôve <www.alcove.com>
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com>
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Earlier work by Werner Almesberger, Paul `Rusty' Russell and Paul Mackerras.
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Some parts borrowed from various video4linux drivers, especially
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * bttv-driver.c and zoran.c, see original files for credits.
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (at your option) any later version.
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful,
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GNU General Public License for more details.
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; if not, write to the Free Software
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h>
31d43c36dc6b357fa1806800f18aa30123c747a6d1Alexey Dobriyan#include <linux/sched.h>
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
335a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/gfp.h>
3451270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil#include <linux/videodev2.h>
355e87efa3b29c105f81fea785babafb098e4e046dMauro Carvalho Chehab#include <media/v4l2-common.h>
3651270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil#include <media/v4l2-device.h>
3735ea11ff84719b1bfab2909903a9640a86552fd1Hans Verkuil#include <media/v4l2-ioctl.h>
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h>
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h>
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h>
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/vmalloc.h>
43d013a068a5675ecd8e71f585a44e7af0798a4307Tobias Klauser#include <linux/dma-mapping.h>
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "meye.h"
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/meye.h>
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Stelian Pop <stelian@popies.net>");
496ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling LandgrafMODULE_DESCRIPTION("v4l2 driver for the MotionEye camera");
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_VERSION(MEYE_DRIVER_VERSION);
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* number of grab buffers */
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int gbuffers = 2;
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(gbuffers, int, 0444);
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(gbuffers, "number of capture buffers, default is 2 (32 max)");
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* size of a grab buffer */
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int gbufsize = MEYE_MAX_BUFSIZE;
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(gbufsize, int, 0444);
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(gbufsize, "size of the capture buffers, default is 614400"
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 " (will be rounded up to a page multiple)");
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* /dev/videoX registration number */
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int video_nr = -1;
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(video_nr, int, 0444);
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(video_nr, "video device to register (0=/dev/video0, etc)");
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* driver structure - only one possible */
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct meye meye;
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************************************/
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Memory allocation routines (stolen from bttv-driver.c)                   */
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************************************/
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void *rvmalloc(unsigned long size)
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *mem;
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long adr;
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	size = PAGE_ALIGN(size);
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mem = vmalloc_32(size);
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mem) {
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memset(mem, 0, size);
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adr = (unsigned long) mem;
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while (size > 0) {
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			SetPageReserved(vmalloc_to_page((void *)adr));
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			adr += PAGE_SIZE;
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			size -= PAGE_SIZE;
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return mem;
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void rvfree(void * mem, unsigned long size)
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long adr;
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mem) {
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adr = (unsigned long) mem;
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while ((long) size > 0) {
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ClearPageReserved(vmalloc_to_page((void *)adr));
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			adr += PAGE_SIZE;
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			size -= PAGE_SIZE;
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vfree(mem);
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return a page table pointing to N pages of locked memory
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NOTE: The meye device expects DMA addresses on 32 bits, we build
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * a table of 1024 entries = 4 bytes * 1024 = 4096 bytes.
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ptable_alloc(void)
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 *pt;
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(meye.mchip_ptable, 0, sizeof(meye.mchip_ptable));
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* give only 32 bit DMA addresses */
123284901a90a9e0b812ca3f5f852cbbfb60d10249dYang Hongyang	if (dma_set_mask(&meye.mchip_dev->dev, DMA_BIT_MASK(32)))
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	meye.mchip_ptable_toc = dma_alloc_coherent(&meye.mchip_dev->dev,
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						   PAGE_SIZE,
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						   &meye.mchip_dmahandle,
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						   GFP_KERNEL);
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!meye.mchip_ptable_toc) {
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		meye.mchip_dmahandle = 0;
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pt = meye.mchip_ptable_toc;
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MCHIP_NB_PAGES; i++) {
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dma_addr_t dma;
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		meye.mchip_ptable[i] = dma_alloc_coherent(&meye.mchip_dev->dev,
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							  PAGE_SIZE,
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							  &dma,
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							  GFP_KERNEL);
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!meye.mchip_ptable[i]) {
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			int j;
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pt = meye.mchip_ptable_toc;
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (j = 0; j < i; ++j) {
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				dma = (dma_addr_t) *pt;
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				dma_free_coherent(&meye.mchip_dev->dev,
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						  PAGE_SIZE,
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						  meye.mchip_ptable[j], dma);
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pt++;
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dma_free_coherent(&meye.mchip_dev->dev,
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					  PAGE_SIZE,
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					  meye.mchip_ptable_toc,
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					  meye.mchip_dmahandle);
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			meye.mchip_ptable_toc = NULL;
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			meye.mchip_dmahandle = 0;
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -1;
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*pt = (u32) dma;
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pt++;
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ptable_free(void)
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 *pt;
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pt = meye.mchip_ptable_toc;
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MCHIP_NB_PAGES; i++) {
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dma_addr_t dma = (dma_addr_t) *pt;
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (meye.mchip_ptable[i])
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dma_free_coherent(&meye.mchip_dev->dev,
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					  PAGE_SIZE,
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					  meye.mchip_ptable[i], dma);
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pt++;
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (meye.mchip_ptable_toc)
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dma_free_coherent(&meye.mchip_dev->dev,
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  PAGE_SIZE,
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  meye.mchip_ptable_toc,
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  meye.mchip_dmahandle);
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(meye.mchip_ptable, 0, sizeof(meye.mchip_ptable));
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	meye.mchip_ptable_toc = NULL;
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	meye.mchip_dmahandle = 0;
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* copy data from ptable into buf */
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ptable_copy(u8 *buf, int start, int size, int pt_pages)
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < (size / PAGE_SIZE) * PAGE_SIZE; i += PAGE_SIZE) {
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy(buf + i, meye.mchip_ptable[start++], PAGE_SIZE);
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (start >= pt_pages)
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			start = 0;
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(buf + i, meye.mchip_ptable[start], size % PAGE_SIZE);
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************************************/
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* JPEG tables at different qualities to load into the VRJ chip             */
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************************************/
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* return a set of quantisation tables based on a quality from 1 to 10 */
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 *jpeg_quantisation_tables(int *length, int quality)
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	static u16 jpeg_tables[][70] = { {
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xdbff, 0x4300, 0xff00, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xffff, 0xffff, 0xffff,
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xdbff, 0x4300, 0xff01, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xffff, 0xffff, 0xffff,
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xdbff, 0x4300, 0x5000, 0x3c37, 0x3c46, 0x5032, 0x4146, 0x5a46,
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x5055, 0x785f, 0x82c8, 0x6e78, 0x786e, 0xaff5, 0x91b9, 0xffc8,
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xffff, 0xffff, 0xffff,
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xdbff, 0x4300, 0x5501, 0x5a5a, 0x6978, 0xeb78, 0x8282, 0xffeb,
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xffff, 0xffff, 0xffff,
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xdbff, 0x4300, 0x2800, 0x1e1c, 0x1e23, 0x2819, 0x2123, 0x2d23,
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x282b, 0x3c30, 0x4164, 0x373c, 0x3c37, 0x587b, 0x495d, 0x9164,
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x9980, 0x8f96, 0x8c80, 0xa08a, 0xe6b4, 0xa0c3, 0xdaaa, 0x8aad,
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xc88c, 0xcbff, 0xeeda, 0xfff5, 0xffff, 0xc19b, 0xffff, 0xfaff,
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xe6ff, 0xfffd, 0xfff8,
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xdbff, 0x4300, 0x2b01, 0x2d2d, 0x353c, 0x763c, 0x4141, 0xf876,
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x8ca5, 0xf8a5, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8,
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8,
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8,
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xf8f8, 0xf8f8, 0xfff8,
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xdbff, 0x4300, 0x1b00, 0x1412, 0x1417, 0x1b11, 0x1617, 0x1e17,
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x1b1c, 0x2820, 0x2b42, 0x2528, 0x2825, 0x3a51, 0x303d, 0x6042,
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x6555, 0x5f64, 0x5d55, 0x6a5b, 0x9978, 0x6a81, 0x9071, 0x5b73,
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x855d, 0x86b5, 0x9e90, 0xaba3, 0xabad, 0x8067, 0xc9bc, 0xa6ba,
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x99c7, 0xaba8, 0xffa4,
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xdbff, 0x4300, 0x1c01, 0x1e1e, 0x2328, 0x4e28, 0x2b2b, 0xa44e,
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x5d6e, 0xa46e, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xa4a4, 0xa4a4, 0xffa4,
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xdbff, 0x4300, 0x1400, 0x0f0e, 0x0f12, 0x140d, 0x1012, 0x1712,
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x1415, 0x1e18, 0x2132, 0x1c1e, 0x1e1c, 0x2c3d, 0x242e, 0x4932,
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x4c40, 0x474b, 0x4640, 0x5045, 0x735a, 0x5062, 0x6d55, 0x4556,
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x6446, 0x6588, 0x776d, 0x817b, 0x8182, 0x604e, 0x978d, 0x7d8c,
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x7396, 0x817e, 0xff7c,
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xdbff, 0x4300, 0x1501, 0x1717, 0x1a1e, 0x3b1e, 0x2121, 0x7c3b,
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x4653, 0x7c53, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c,
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c,
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c,
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x7c7c, 0x7c7c, 0xff7c,
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xdbff, 0x4300, 0x1000, 0x0c0b, 0x0c0e, 0x100a, 0x0d0e, 0x120e,
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x1011, 0x1813, 0x1a28, 0x1618, 0x1816, 0x2331, 0x1d25, 0x3a28,
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x3d33, 0x393c, 0x3833, 0x4037, 0x5c48, 0x404e, 0x5744, 0x3745,
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x5038, 0x516d, 0x5f57, 0x6762, 0x6768, 0x4d3e, 0x7971, 0x6470,
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x5c78, 0x6765, 0xff63,
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xdbff, 0x4300, 0x1101, 0x1212, 0x1518, 0x2f18, 0x1a1a, 0x632f,
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x3842, 0x6342, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363,
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363,
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363,
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x6363, 0x6363, 0xff63,
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xdbff, 0x4300, 0x0d00, 0x0a09, 0x0a0b, 0x0d08, 0x0a0b, 0x0e0b,
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x0d0e, 0x130f, 0x1520, 0x1213, 0x1312, 0x1c27, 0x171e, 0x2e20,
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x3129, 0x2e30, 0x2d29, 0x332c, 0x4a3a, 0x333e, 0x4636, 0x2c37,
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x402d, 0x4157, 0x4c46, 0x524e, 0x5253, 0x3e32, 0x615a, 0x505a,
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x4a60, 0x5251, 0xff4f,
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xdbff, 0x4300, 0x0e01, 0x0e0e, 0x1113, 0x2613, 0x1515, 0x4f26,
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x2d35, 0x4f35, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f,
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f,
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f,
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x4f4f, 0x4f4f, 0xff4f,
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xdbff, 0x4300, 0x0a00, 0x0707, 0x0708, 0x0a06, 0x0808, 0x0b08,
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x0a0a, 0x0e0b, 0x1018, 0x0d0e, 0x0e0d, 0x151d, 0x1116, 0x2318,
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x251f, 0x2224, 0x221f, 0x2621, 0x372b, 0x262f, 0x3429, 0x2129,
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x3022, 0x3141, 0x3934, 0x3e3b, 0x3e3e, 0x2e25, 0x4944, 0x3c43,
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x3748, 0x3e3d, 0xff3b,
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xdbff, 0x4300, 0x0a01, 0x0b0b, 0x0d0e, 0x1c0e, 0x1010, 0x3b1c,
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x2228, 0x3b28, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b,
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b,
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b,
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x3b3b, 0x3b3b, 0xff3b,
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xdbff, 0x4300, 0x0600, 0x0504, 0x0506, 0x0604, 0x0506, 0x0706,
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x0607, 0x0a08, 0x0a10, 0x090a, 0x0a09, 0x0e14, 0x0c0f, 0x1710,
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x1814, 0x1718, 0x1614, 0x1a16, 0x251d, 0x1a1f, 0x231b, 0x161c,
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x2016, 0x202c, 0x2623, 0x2927, 0x292a, 0x1f19, 0x302d, 0x282d,
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x2530, 0x2928, 0xff28,
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xdbff, 0x4300, 0x0701, 0x0707, 0x080a, 0x130a, 0x0a0a, 0x2813,
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x161a, 0x281a, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828,
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828,
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828,
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x2828, 0x2828, 0xff28,
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xdbff, 0x4300, 0x0300, 0x0202, 0x0203, 0x0302, 0x0303, 0x0403,
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x0303, 0x0504, 0x0508, 0x0405, 0x0504, 0x070a, 0x0607, 0x0c08,
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x0c0a, 0x0b0c, 0x0b0a, 0x0d0b, 0x120e, 0x0d10, 0x110e, 0x0b0e,
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x100b, 0x1016, 0x1311, 0x1514, 0x1515, 0x0f0c, 0x1817, 0x1416,
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x1218, 0x1514, 0xff14,
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xdbff, 0x4300, 0x0301, 0x0404, 0x0405, 0x0905, 0x0505, 0x1409,
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x0b0d, 0x140d, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414,
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414,
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414,
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x1414, 0x1414, 0xff14,
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xdbff, 0x4300, 0x0100, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x0101, 0x0101, 0xff01,
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xdbff, 0x4300, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x0101, 0x0101, 0xff01,
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} };
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (quality < 0 || quality > 10) {
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       "meye: invalid quality level %d - using 8\n", quality);
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		quality = 8;
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*length = ARRAY_SIZE(jpeg_tables[quality]);
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return jpeg_tables[quality];
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* return a generic set of huffman tables */
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 *jpeg_huffman_tables(int *length)
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	static u16 tables[] = {
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xC4FF, 0xB500, 0x0010, 0x0102, 0x0303, 0x0402, 0x0503, 0x0405,
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x0004, 0x0100, 0x017D, 0x0302, 0x0400, 0x0511, 0x2112, 0x4131,
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x1306, 0x6151, 0x2207, 0x1471, 0x8132, 0xA191, 0x2308, 0xB142,
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x15C1, 0xD152, 0x24F0, 0x6233, 0x8272, 0x0A09, 0x1716, 0x1918,
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x251A, 0x2726, 0x2928, 0x342A, 0x3635, 0x3837, 0x3A39, 0x4443,
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x4645, 0x4847, 0x4A49, 0x5453, 0x5655, 0x5857, 0x5A59, 0x6463,
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x6665, 0x6867, 0x6A69, 0x7473, 0x7675, 0x7877, 0x7A79, 0x8483,
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x8685, 0x8887, 0x8A89, 0x9392, 0x9594, 0x9796, 0x9998, 0xA29A,
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xA4A3, 0xA6A5, 0xA8A7, 0xAAA9, 0xB3B2, 0xB5B4, 0xB7B6, 0xB9B8,
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xC2BA, 0xC4C3, 0xC6C5, 0xC8C7, 0xCAC9, 0xD3D2, 0xD5D4, 0xD7D6,
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xD9D8, 0xE1DA, 0xE3E2, 0xE5E4, 0xE7E6, 0xE9E8, 0xF1EA, 0xF3F2,
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xF5F4, 0xF7F6, 0xF9F8, 0xFFFA,
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xC4FF, 0xB500, 0x0011, 0x0102, 0x0402, 0x0304, 0x0704, 0x0405,
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x0004, 0x0201, 0x0077, 0x0201, 0x1103, 0x0504, 0x3121, 0x1206,
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x5141, 0x6107, 0x1371, 0x3222, 0x0881, 0x4214, 0xA191, 0xC1B1,
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x2309, 0x5233, 0x15F0, 0x7262, 0x0AD1, 0x2416, 0xE134, 0xF125,
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x1817, 0x1A19, 0x2726, 0x2928, 0x352A, 0x3736, 0x3938, 0x433A,
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x4544, 0x4746, 0x4948, 0x534A, 0x5554, 0x5756, 0x5958, 0x635A,
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x6564, 0x6766, 0x6968, 0x736A, 0x7574, 0x7776, 0x7978, 0x827A,
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x8483, 0x8685, 0x8887, 0x8A89, 0x9392, 0x9594, 0x9796, 0x9998,
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xA29A, 0xA4A3, 0xA6A5, 0xA8A7, 0xAAA9, 0xB3B2, 0xB5B4, 0xB7B6,
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xB9B8, 0xC2BA, 0xC4C3, 0xC6C5, 0xC8C7, 0xCAC9, 0xD3D2, 0xD5D4,
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xD7D6, 0xD9D8, 0xE2DA, 0xE4E3, 0xE6E5, 0xE8E7, 0xEAE9, 0xF3F2,
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xF5F4, 0xF7F6, 0xF9F8, 0xFFFA,
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xC4FF, 0x1F00, 0x0000, 0x0501, 0x0101, 0x0101, 0x0101, 0x0000,
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x0000, 0x0000, 0x0000, 0x0201, 0x0403, 0x0605, 0x0807, 0x0A09,
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xFF0B,
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xC4FF, 0x1F00, 0x0001, 0x0103, 0x0101, 0x0101, 0x0101, 0x0101,
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x0000, 0x0000, 0x0000, 0x0201, 0x0403, 0x0605, 0x0807, 0x0A09,
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0xFF0B
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	};
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*length = ARRAY_SIZE(tables);
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return tables;
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************************************/
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* MCHIP low-level functions                                                */
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************************************/
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* returns the horizontal capture size */
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int mchip_hsize(void)
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return meye.params.subsample ? 320 : 640;
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* returns the vertical capture size */
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int mchip_vsize(void)
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return meye.params.subsample ? 240 : 480;
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* waits for a register to be available */
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mchip_sync(int reg)
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 status;
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (reg == MCHIP_MM_FIFO_DATA) {
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < MCHIP_REG_TIMEOUT; i++) {
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			status = readl(meye.mchip_mmregs +
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       MCHIP_MM_FIFO_STATUS);
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(status & MCHIP_MM_FIFO_WAIT)) {
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				printk(KERN_WARNING "meye: fifo not ready\n");
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return;
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (status & MCHIP_MM_FIFO_READY)
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return;
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			udelay(1);
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (reg > 0x80) {
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u32 mask = (reg < 0x100) ? MCHIP_HIC_STATUS_MCC_RDY
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 : MCHIP_HIC_STATUS_VRJ_RDY;
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < MCHIP_REG_TIMEOUT; i++) {
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			status = readl(meye.mchip_mmregs + MCHIP_HIC_STATUS);
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (status & mask)
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return;
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			udelay(1);
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_WARNING
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       "meye: mchip_sync() timeout on reg 0x%x status=0x%x\n",
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       reg, status);
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* sets a value into the register */
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void mchip_set(int reg, u32 v)
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_sync(reg);
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writel(v, meye.mchip_mmregs + reg);
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* get the register value */
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline u32 mchip_read(int reg)
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_sync(reg);
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return readl(meye.mchip_mmregs + reg);
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* wait for a register to become a particular value */
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int mchip_delay(u32 reg, u32 v)
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int n = 10;
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (--n && mchip_read(reg) != v)
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(1);
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return n;
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* setup subsampling */
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mchip_subsample(void)
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_MCC_R_SAMPLING, meye.params.subsample);
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_MCC_R_XRANGE, mchip_hsize());
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_MCC_R_YRANGE, mchip_vsize());
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_MCC_B_XRANGE, mchip_hsize());
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_MCC_B_YRANGE, mchip_vsize());
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE);
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* set the framerate into the mchip */
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mchip_set_framerate(void)
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_HIC_S_RATE, meye.params.framerate);
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* load some huffman and quantisation tables into the VRJ chip ready
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   for JPEG compression */
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mchip_load_tables(void)
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int length;
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 *tables;
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tables = jpeg_huffman_tables(&length);
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < length; i++)
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writel(tables[i], meye.mchip_mmregs + MCHIP_VRJ_TABLE_DATA);
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tables = jpeg_quantisation_tables(&length, meye.params.quality);
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < length; i++)
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writel(tables[i], meye.mchip_mmregs + MCHIP_VRJ_TABLE_DATA);
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* setup the VRJ parameters in the chip */
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mchip_vrj_setup(u8 mode)
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_VRJ_BUS_MODE, 5);
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_VRJ_SIGNAL_ACTIVE_LEVEL, 0x1f);
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_VRJ_PDAT_USE, 1);
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_VRJ_IRQ_FLAG, 0xa0);
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_VRJ_MODE_SPECIFY, mode);
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_VRJ_NUM_LINES, mchip_vsize());
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_VRJ_NUM_PIXELS, mchip_hsize());
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_VRJ_NUM_COMPONENTS, 0x1b);
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_VRJ_LIMIT_COMPRESSED_LO, 0xFFFF);
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_VRJ_LIMIT_COMPRESSED_HI, 0xFFFF);
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_VRJ_COMP_DATA_FORMAT, 0xC);
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_VRJ_RESTART_INTERVAL, 0);
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_VRJ_SOF1, 0x601);
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_VRJ_SOF2, 0x1502);
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_VRJ_SOF3, 0x1503);
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_VRJ_SOF4, 0x1596);
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_VRJ_SOS, 0x0ed0);
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_load_tables();
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* sets the DMA parameters into the chip */
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mchip_dma_setup(dma_addr_t dma_addr)
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_MM_PT_ADDR, (u32)dma_addr);
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 4; i++)
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mchip_set(MCHIP_MM_FIR(i), 0);
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	meye.mchip_fnum = 0;
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* setup for DMA transfers - also zeros the framebuffer */
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mchip_dma_alloc(void)
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!meye.mchip_dmahandle)
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ptable_alloc())
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -1;
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* frees the DMA buffer */
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mchip_dma_free(void)
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (meye.mchip_dmahandle) {
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mchip_dma_setup(0);
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ptable_free();
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* stop any existing HIC action and wait for any dma to complete then
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   reset the dma engine */
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mchip_hic_stop(void)
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, j;
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	meye.mchip_mode = MCHIP_HIC_MODE_NOOP;
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(mchip_read(MCHIP_HIC_STATUS) & MCHIP_HIC_STATUS_BUSY))
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 20; ++i) {
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_STOP);
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mchip_delay(MCHIP_HIC_CMD, 0);
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (j = 0; j < 100; ++j) {
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (mchip_delay(MCHIP_HIC_STATUS,
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					MCHIP_HIC_STATUS_IDLE))
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return;
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			msleep(1);
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "meye: need to reset HIC!\n");
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mchip_set(MCHIP_HIC_CTL, MCHIP_HIC_CTL_SOFT_RESET);
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		msleep(250);
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_ERR "meye: resetting HIC hanged!\n");
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************************************/
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* MCHIP frame processing functions                                         */
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************************************/
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* get the next ready frame from the dma engine */
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u32 mchip_get_frame(void)
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 v;
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	v = mchip_read(MCHIP_MM_FIR(meye.mchip_fnum));
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return v;
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* frees the current frame from the dma engine */
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mchip_free_frame(void)
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_MM_FIR(meye.mchip_fnum), 0);
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	meye.mchip_fnum++;
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	meye.mchip_fnum %= 4;
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* read one frame from the framebuffer assuming it was captured using
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   a uncompressed transfer */
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mchip_cont_read_frame(u32 v, u8 *buf, int size)
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int pt_id;
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pt_id = (v >> 17) & 0x3FF;
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ptable_copy(buf, pt_id, size, MCHIP_NB_PAGES);
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* read a compressed frame from the framebuffer */
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mchip_comp_read_frame(u32 v, u8 *buf, int size)
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int pt_start, pt_end, trailer;
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int fsize;
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pt_start = (v >> 19) & 0xFF;
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pt_end = (v >> 11) & 0xFF;
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	trailer = (v >> 1) & 0x3FF;
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pt_end < pt_start)
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fsize = (MCHIP_NB_PAGES_MJPEG - pt_start) * PAGE_SIZE +
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pt_end * PAGE_SIZE + trailer * 4;
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fsize = (pt_end - pt_start) * PAGE_SIZE + trailer * 4;
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fsize > size) {
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING "meye: oversized compressed frame %d\n",
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       fsize);
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ptable_copy(buf, pt_start, fsize, MCHIP_NB_PAGES_MJPEG);
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef MEYE_JPEG_CORRECTION
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Some mchip generated jpeg frames are incorrect. In most
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * (all ?) of those cases, the final EOI (0xff 0xd9) marker
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * is not present at the end of the frame.
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Since adding the final marker is not enough to restore
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * the jpeg integrity, we drop the frame.
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = fsize - 1; i > 0 && buf[i] == 0xff; i--) ;
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (i < 2 || buf[i - 1] != 0xff || buf[i] != 0xd9)
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return fsize;
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* take a picture into SDRAM */
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mchip_take_picture(void)
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_hic_stop();
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_subsample();
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_dma_setup(meye.mchip_dmahandle);
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_CAP);
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_delay(MCHIP_HIC_CMD, 0);
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 100; ++i) {
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE))
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		msleep(1);
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* dma a previously taken picture into a buffer */
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mchip_get_picture(u8 *buf, int bufsize)
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 v;
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_OUT);
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_delay(MCHIP_HIC_CMD, 0);
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 100; ++i) {
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE))
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		msleep(1);
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 4; ++i) {
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		v = mchip_get_frame();
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (v & MCHIP_MM_FIR_RDY) {
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mchip_cont_read_frame(v, buf, bufsize);
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mchip_free_frame();
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* start continuous dma capture */
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mchip_continuous_start(void)
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_hic_stop();
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_subsample();
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set_framerate();
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_dma_setup(meye.mchip_dmahandle);
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT;
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_CONT_OUT);
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_delay(MCHIP_HIC_CMD, 0);
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* compress one frame into a buffer */
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mchip_compress_frame(u8 *buf, int bufsize)
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 v;
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int len = -1, i;
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_vrj_setup(0x3f);
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(50);
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_COMP);
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_delay(MCHIP_HIC_CMD, 0);
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 100; ++i) {
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE))
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		msleep(1);
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 4; ++i) {
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		v = mchip_get_frame();
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (v & MCHIP_MM_FIR_RDY) {
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			len = mchip_comp_read_frame(v, buf, bufsize);
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mchip_free_frame();
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return len;
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* uncompress one image into a buffer */
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mchip_uncompress_frame(u8 *img, int imgsize, u8 *buf, int bufsize)
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_vrj_setup(0x3f);
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(50);
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_DECOMP);
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_delay(MCHIP_HIC_CMD, 0);
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return mchip_comp_read_frame(buf, bufsize);
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* start continuous compressed capture */
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mchip_cont_compression_start(void)
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_hic_stop();
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_vrj_setup(0x3f);
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_subsample();
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set_framerate();
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_dma_setup(meye.mchip_dmahandle);
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP;
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_CONT_COMP);
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_delay(MCHIP_HIC_CMD, 0);
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************************************/
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Interrupt handling                                                       */
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************************************/
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7877d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t meye_irq(int irq, void *dev_id)
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 v;
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int reqnr;
791ff699e6bd02eb1c6d02c7c2b576c2ee6caab201cDouglas Schilling Landgraf	static int sequence;
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	v = mchip_read(MCHIP_MM_INTA);
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_OUT &&
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP)
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return IRQ_NONE;
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsagain:
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	v = mchip_get_frame();
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(v & MCHIP_MM_FIR_RDY))
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return IRQ_HANDLED;
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (meye.mchip_mode == MCHIP_HIC_MODE_CONT_OUT) {
8057acd72eb85f1c7a15e8b5eb554994949241737f1Stefani Seibold		if (kfifo_out_locked(&meye.grabq, (unsigned char *)&reqnr,
806c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold			      sizeof(int), &meye.grabq_lock) != sizeof(int)) {
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mchip_free_frame();
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return IRQ_HANDLED;
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mchip_cont_read_frame(v, meye.grab_fbuffer + gbufsize * reqnr,
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				      mchip_hsize() * mchip_vsize() * 2);
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		meye.grab_buffer[reqnr].size = mchip_hsize() * mchip_vsize() * 2;
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		meye.grab_buffer[reqnr].state = MEYE_BUF_DONE;
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		do_gettimeofday(&meye.grab_buffer[reqnr].timestamp);
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		meye.grab_buffer[reqnr].sequence = sequence++;
8167acd72eb85f1c7a15e8b5eb554994949241737f1Stefani Seibold		kfifo_in_locked(&meye.doneq, (unsigned char *)&reqnr,
817c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold				sizeof(int), &meye.doneq_lock);
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		wake_up_interruptible(&meye.proc_list);
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int size;
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		size = mchip_comp_read_frame(v, meye.grab_temp, gbufsize);
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (size == -1) {
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mchip_free_frame();
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto again;
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8267acd72eb85f1c7a15e8b5eb554994949241737f1Stefani Seibold		if (kfifo_out_locked(&meye.grabq, (unsigned char *)&reqnr,
827c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold			      sizeof(int), &meye.grabq_lock) != sizeof(int)) {
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mchip_free_frame();
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto again;
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy(meye.grab_fbuffer + gbufsize * reqnr, meye.grab_temp,
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       size);
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		meye.grab_buffer[reqnr].size = size;
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		meye.grab_buffer[reqnr].state = MEYE_BUF_DONE;
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		do_gettimeofday(&meye.grab_buffer[reqnr].timestamp);
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		meye.grab_buffer[reqnr].sequence = sequence++;
8377acd72eb85f1c7a15e8b5eb554994949241737f1Stefani Seibold		kfifo_in_locked(&meye.doneq, (unsigned char *)&reqnr,
838c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold				sizeof(int), &meye.doneq_lock);
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		wake_up_interruptible(&meye.proc_list);
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_free_frame();
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	goto again;
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************************************/
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* video4linux integration                                                  */
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************************************/
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
849bec43661b1dc0075b7445223ba775674133b164dHans Verkuilstatic int meye_open(struct file *file)
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8517d43cd53c851e3cf04d73108d4e7e25a1104c6f5Hans Verkuil	int i;
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8537d43cd53c851e3cf04d73108d4e7e25a1104c6f5Hans Verkuil	if (test_and_set_bit(0, &meye.in_use))
8547d43cd53c851e3cf04d73108d4e7e25a1104c6f5Hans Verkuil		return -EBUSY;
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_hic_stop();
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mchip_dma_alloc()) {
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "meye: mchip framebuffer allocation failed\n");
8607d43cd53c851e3cf04d73108d4e7e25a1104c6f5Hans Verkuil		clear_bit(0, &meye.in_use);
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOBUFS;
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MEYE_MAX_BUFNBRS; i++)
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		meye.grab_buffer[i].state = MEYE_BUF_UNUSED;
86645465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seibold	kfifo_reset(&meye.grabq);
86745465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seibold	kfifo_reset(&meye.doneq);
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
871bec43661b1dc0075b7445223ba775674133b164dHans Verkuilstatic int meye_release(struct file *file)
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_hic_stop();
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_dma_free();
8757d43cd53c851e3cf04d73108d4e7e25a1104c6f5Hans Verkuil	clear_bit(0, &meye.in_use);
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8796ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgrafstatic int meyeioc_g_params(struct meye_params *p)
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8816ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	*p = meye.params;
8826ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	return 0;
8836ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf}
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8856ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgrafstatic int meyeioc_s_params(struct meye_params *jp)
8866ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf{
8876ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (jp->subsample > 1)
8886ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8906ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (jp->quality > 10)
8916ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8936ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (jp->sharpness > 63 || jp->agc > 63 || jp->picture > 63)
8946ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8966ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (jp->framerate > 31)
8976ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8996ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mutex_lock(&meye.lock);
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9016ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (meye.params.subsample != jp->subsample ||
9026ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	    meye.params.quality != jp->quality)
9036ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		mchip_hic_stop();	/* need restart */
9046ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
9056ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	meye.params = *jp;
9066ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS,
9076ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf			      meye.params.sharpness);
9086ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC,
9096ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf			      meye.params.agc);
9106ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE,
9116ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf			      meye.params.picture);
9126ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mutex_unlock(&meye.lock);
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9146ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	return 0;
9156ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf}
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9176ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgrafstatic int meyeioc_qbuf_capt(int *nb)
9186ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf{
9196ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (!meye.grab_fbuffer)
9206ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9226ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (*nb >= gbuffers)
9236ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9256ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (*nb < 0) {
9266ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		/* stop capture */
9276ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		mchip_hic_stop();
9286ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return 0;
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9316ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (meye.grab_buffer[*nb].state != MEYE_BUF_UNUSED)
9326ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EBUSY;
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9346ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mutex_lock(&meye.lock);
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9366ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP)
9376ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		mchip_cont_compression_start();
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9396ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	meye.grab_buffer[*nb].state = MEYE_BUF_USING;
9407acd72eb85f1c7a15e8b5eb554994949241737f1Stefani Seibold	kfifo_in_locked(&meye.grabq, (unsigned char *)nb, sizeof(int),
941c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold			 &meye.grabq_lock);
9426ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mutex_unlock(&meye.lock);
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9446ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	return 0;
9456ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf}
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9476ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgrafstatic int meyeioc_sync(struct file *file, void *fh, int *i)
9486ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf{
9496ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	int unused;
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9516ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (*i < 0 || *i >= gbuffers)
9526ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
9536ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
9546ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mutex_lock(&meye.lock);
9556ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	switch (meye.grab_buffer[*i].state) {
9566ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
9576ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case MEYE_BUF_UNUSED:
9583593cab5d62c4c7abced1076710f9bc2d8847433Ingo Molnar		mutex_unlock(&meye.lock);
9596ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
9606ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case MEYE_BUF_USING:
9616ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		if (file->f_flags & O_NONBLOCK) {
9626ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf			mutex_unlock(&meye.lock);
9636ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf			return -EAGAIN;
9646ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		}
9656ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		if (wait_event_interruptible(meye.proc_list,
9666ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf			(meye.grab_buffer[*i].state != MEYE_BUF_USING))) {
9676ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf			mutex_unlock(&meye.lock);
9686ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf			return -EINTR;
9696ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		}
9706ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		/* fall through */
9716ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case MEYE_BUF_DONE:
9726ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		meye.grab_buffer[*i].state = MEYE_BUF_UNUSED;
9739842c38e917636fa7dc6b88aff17a8f1fd7f0cc0Stefani Seibold		if (kfifo_out_locked(&meye.doneq, (unsigned char *)&unused,
9749842c38e917636fa7dc6b88aff17a8f1fd7f0cc0Stefani Seibold				sizeof(int), &meye.doneq_lock) != sizeof(int))
9759842c38e917636fa7dc6b88aff17a8f1fd7f0cc0Stefani Seibold					break;
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9776ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	*i = meye.grab_buffer[*i].size;
9786ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mutex_unlock(&meye.lock);
9796ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	return 0;
9806ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf}
9816ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
9826ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgrafstatic int meyeioc_stillcapt(void)
9836ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf{
9846ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (!meye.grab_fbuffer)
9856ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9876ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
9886ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EBUSY;
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9906ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mutex_lock(&meye.lock);
9916ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	meye.grab_buffer[0].state = MEYE_BUF_USING;
9926ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mchip_take_picture();
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9946ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mchip_get_picture(meye.grab_fbuffer,
9956ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf			mchip_hsize() * mchip_vsize() * 2);
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9976ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	meye.grab_buffer[0].state = MEYE_BUF_DONE;
9986ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mutex_unlock(&meye.lock);
9996ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
10006ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	return 0;
10016ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf}
10026ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
10036ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgrafstatic int meyeioc_stilljcapt(int *len)
10046ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf{
10056ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (!meye.grab_fbuffer)
10066ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
10076ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
10086ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
10096ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EBUSY;
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10116ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mutex_lock(&meye.lock);
10126ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	meye.grab_buffer[0].state = MEYE_BUF_USING;
10136ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	*len = -1;
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10156ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	while (*len == -1) {
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mchip_take_picture();
10176ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		*len = mchip_compress_frame(meye.grab_fbuffer, gbufsize);
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10206ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	meye.grab_buffer[0].state = MEYE_BUF_DONE;
10216ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mutex_unlock(&meye.lock);
10226ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	return 0;
10236ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf}
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10256ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgrafstatic int vidioc_querycap(struct file *file, void *fh,
10266ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf				struct v4l2_capability *cap)
10276ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf{
10286ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	strcpy(cap->driver, "meye");
10296ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	strcpy(cap->card, "meye");
10306ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	sprintf(cap->bus_info, "PCI:%s", pci_name(meye.mchip_dev));
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10326ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	cap->version = (MEYE_DRIVER_MAJORVERSION << 8) +
10336ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		       MEYE_DRIVER_MINORVERSION;
10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10356ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
10366ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf			    V4L2_CAP_STREAMING;
10376ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
10386ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	return 0;
10396ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf}
10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10416ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgrafstatic int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
10426ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf{
10436ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (i->index != 0)
10446ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
10456ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
10466ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	strcpy(i->name, "Camera");
10476ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	i->type = V4L2_INPUT_TYPE_CAMERA;
10486ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
10496ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	return 0;
10506ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf}
10516ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
10526ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgrafstatic int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
10536ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf{
10546ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	*i = 0;
10556ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	return 0;
10566ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf}
10576ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
10586ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgrafstatic int vidioc_s_input(struct file *file, void *fh, unsigned int i)
10596ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf{
10606ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (i != 0)
10616ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10636ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	return 0;
10646ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf}
10656ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
10666ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgrafstatic int vidioc_queryctrl(struct file *file, void *fh,
10676ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf				struct v4l2_queryctrl *c)
10686ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf{
10696ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	switch (c->id) {
10706ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
10716ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_BRIGHTNESS:
10726ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->type = V4L2_CTRL_TYPE_INTEGER;
10736ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		strcpy(c->name, "Brightness");
10746ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->minimum = 0;
10756ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->maximum = 63;
10766ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->step = 1;
10776ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->default_value = 32;
10786ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->flags = 0;
10796ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
10806ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_HUE:
10816ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->type = V4L2_CTRL_TYPE_INTEGER;
10826ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		strcpy(c->name, "Hue");
10836ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->minimum = 0;
10846ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->maximum = 63;
10856ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->step = 1;
10866ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->default_value = 32;
10876ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->flags = 0;
10886ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
10896ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_CONTRAST:
10906ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->type = V4L2_CTRL_TYPE_INTEGER;
10916ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		strcpy(c->name, "Contrast");
10926ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->minimum = 0;
10936ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->maximum = 63;
10946ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->step = 1;
10956ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->default_value = 32;
10966ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->flags = 0;
10976ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
10986ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_SATURATION:
10996ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->type = V4L2_CTRL_TYPE_INTEGER;
11006ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		strcpy(c->name, "Saturation");
11016ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->minimum = 0;
11026ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->maximum = 63;
11036ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->step = 1;
11046ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->default_value = 32;
11056ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->flags = 0;
11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
11076ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_AGC:
11086ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->type = V4L2_CTRL_TYPE_INTEGER;
11096ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		strcpy(c->name, "Agc");
11106ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->minimum = 0;
11116ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->maximum = 63;
11126ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->step = 1;
11136ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->default_value = 48;
11146ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->flags = 0;
11156ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
11166ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_MEYE_SHARPNESS:
11176ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_SHARPNESS:
11186ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->type = V4L2_CTRL_TYPE_INTEGER;
11196ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		strcpy(c->name, "Sharpness");
11206ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->minimum = 0;
11216ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->maximum = 63;
11226ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->step = 1;
11236ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->default_value = 32;
11246ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
11256ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		/* Continue to report legacy private SHARPNESS ctrl but
11266ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		 * say it is disabled in preference to ctrl in the spec
11276ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		 */
11286ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->flags = (c->id == V4L2_CID_SHARPNESS) ? 0 :
11296ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf						V4L2_CTRL_FLAG_DISABLED;
11306ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
11316ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_PICTURE:
11326ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->type = V4L2_CTRL_TYPE_INTEGER;
11336ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		strcpy(c->name, "Picture");
11346ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->minimum = 0;
11356ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->maximum = 63;
11366ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->step = 1;
11376ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->default_value = 0;
11386ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->flags = 0;
11396ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
11406ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_JPEGQUAL:
11416ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->type = V4L2_CTRL_TYPE_INTEGER;
11426ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		strcpy(c->name, "JPEG quality");
11436ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->minimum = 0;
11446ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->maximum = 10;
11456ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->step = 1;
11466ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->default_value = 8;
11476ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->flags = 0;
11486ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
11496ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_FRAMERATE:
11506ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->type = V4L2_CTRL_TYPE_INTEGER;
11516ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		strcpy(c->name, "Framerate");
11526ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->minimum = 0;
11536ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->maximum = 31;
11546ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->step = 1;
11556ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->default_value = 0;
11566ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->flags = 0;
11576ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
11586ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	default:
11596ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11626ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	return 0;
11636ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf}
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11656ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgrafstatic int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c)
11666ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf{
11676ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mutex_lock(&meye.lock);
11686ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	switch (c->id) {
11696ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_BRIGHTNESS:
11706ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		sony_pic_camera_command(
11716ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf			SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, c->value);
117251270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil		meye.brightness = c->value << 10;
11736ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
11746ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_HUE:
11756ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		sony_pic_camera_command(
11766ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf			SONY_PIC_COMMAND_SETCAMERAHUE, c->value);
117751270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil		meye.hue = c->value << 10;
11786ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
11796ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_CONTRAST:
11806ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		sony_pic_camera_command(
11816ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf			SONY_PIC_COMMAND_SETCAMERACONTRAST, c->value);
118251270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil		meye.contrast = c->value << 10;
11836ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
11846ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_SATURATION:
11856ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		sony_pic_camera_command(
11866ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf			SONY_PIC_COMMAND_SETCAMERACOLOR, c->value);
118751270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil		meye.colour = c->value << 10;
11886ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
11896ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_AGC:
11906ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		sony_pic_camera_command(
11916ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf			SONY_PIC_COMMAND_SETCAMERAAGC, c->value);
11926ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		meye.params.agc = c->value;
11936ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
11946ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_SHARPNESS:
11956ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_MEYE_SHARPNESS:
11966ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		sony_pic_camera_command(
11976ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf			SONY_PIC_COMMAND_SETCAMERASHARPNESS, c->value);
11986ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		meye.params.sharpness = c->value;
11996ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
12006ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_PICTURE:
12016ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		sony_pic_camera_command(
12026ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf			SONY_PIC_COMMAND_SETCAMERAPICTURE, c->value);
12036ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		meye.params.picture = c->value;
12046ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
12056ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_JPEGQUAL:
12066ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		meye.params.quality = c->value;
12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
12086ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_FRAMERATE:
12096ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		meye.params.framerate = c->value;
12106ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
12116ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	default:
12126ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		mutex_unlock(&meye.lock);
12136ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12156ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mutex_unlock(&meye.lock);
12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12176ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	return 0;
12186ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf}
12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12206ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgrafstatic int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c)
12216ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf{
12226ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mutex_lock(&meye.lock);
12236ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	switch (c->id) {
12246ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_BRIGHTNESS:
122551270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil		c->value = meye.brightness >> 10;
12266ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
12276ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_HUE:
122851270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil		c->value = meye.hue >> 10;
12296ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
12306ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_CONTRAST:
123151270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil		c->value = meye.contrast >> 10;
12326ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
12336ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_SATURATION:
123451270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil		c->value = meye.colour >> 10;
12356ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
12366ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_AGC:
12376ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->value = meye.params.agc;
12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
12396ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_SHARPNESS:
12406ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_MEYE_SHARPNESS:
12416ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->value = meye.params.sharpness;
12426ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
12436ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_PICTURE:
12446ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->value = meye.params.picture;
12456ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
12466ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_JPEGQUAL:
12476ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->value = meye.params.quality;
12486ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
12496ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_CID_FRAMERATE:
12506ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		c->value = meye.params.framerate;
12516ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
12526ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	default:
12536ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		mutex_unlock(&meye.lock);
12546ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12566ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mutex_unlock(&meye.lock);
12576ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
12586ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	return 0;
12596ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf}
12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
126178b526a43561d7e5e702ba27948e422dfbc4bea1Hans Verkuilstatic int vidioc_enum_fmt_vid_cap(struct file *file, void *fh,
12626ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf				struct v4l2_fmtdesc *f)
12636ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf{
12646ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (f->index > 1)
12656ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12676ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (f->index == 0) {
12686ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		/* standard YUV 422 capture */
12696ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		f->flags = 0;
12706ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		strcpy(f->description, "YUV422");
12716ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		f->pixelformat = V4L2_PIX_FMT_YUYV;
12726ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	} else {
12736ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		/* compressed MJPEG capture */
12746ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		f->flags = V4L2_FMT_FLAG_COMPRESSED;
12756ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		strcpy(f->description, "MJPEG");
12766ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		f->pixelformat = V4L2_PIX_FMT_MJPEG;
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12796ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	return 0;
12806ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf}
12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
128278b526a43561d7e5e702ba27948e422dfbc4bea1Hans Verkuilstatic int vidioc_try_fmt_vid_cap(struct file *file, void *fh,
12836ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf				struct v4l2_format *f)
12846ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf{
12856ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
12866ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	    f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
12876ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
12886ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
12896ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (f->fmt.pix.field != V4L2_FIELD_ANY &&
12906ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	    f->fmt.pix.field != V4L2_FIELD_NONE)
12916ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
12926ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
12936ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	f->fmt.pix.field = V4L2_FIELD_NONE;
12946ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
12956ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (f->fmt.pix.width <= 320) {
12966ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		f->fmt.pix.width = 320;
12976ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		f->fmt.pix.height = 240;
12986ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	} else {
12996ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		f->fmt.pix.width = 640;
13006ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		f->fmt.pix.height = 480;
13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13036ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
13046ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	f->fmt.pix.sizeimage = f->fmt.pix.height *
13056ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf			       f->fmt.pix.bytesperline;
13066ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	f->fmt.pix.colorspace = 0;
13076ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	f->fmt.pix.priv = 0;
13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13096ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	return 0;
13106ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf}
13116ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
131278b526a43561d7e5e702ba27948e422dfbc4bea1Hans Verkuilstatic int vidioc_g_fmt_vid_cap(struct file *file, void *fh,
131378b526a43561d7e5e702ba27948e422dfbc4bea1Hans Verkuil				    struct v4l2_format *f)
13146ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf{
13156ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	switch (meye.mchip_mode) {
13166ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case MCHIP_HIC_MODE_CONT_OUT:
13176ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	default:
13186ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
13196ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
13206ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case MCHIP_HIC_MODE_CONT_COMP:
13216ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		f->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13256ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	f->fmt.pix.field = V4L2_FIELD_NONE;
13266ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	f->fmt.pix.width = mchip_hsize();
13276ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	f->fmt.pix.height = mchip_vsize();
13286ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
13296ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	f->fmt.pix.sizeimage = f->fmt.pix.height *
13306ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf			       f->fmt.pix.bytesperline;
13316ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
13326ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	return 0;
13336ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf}
13346ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
133578b526a43561d7e5e702ba27948e422dfbc4bea1Hans Verkuilstatic int vidioc_s_fmt_vid_cap(struct file *file, void *fh,
133678b526a43561d7e5e702ba27948e422dfbc4bea1Hans Verkuil				    struct v4l2_format *f)
13376ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf{
13386ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
13396ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	    f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
13406ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
13416ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
13426ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (f->fmt.pix.field != V4L2_FIELD_ANY &&
13436ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	    f->fmt.pix.field != V4L2_FIELD_NONE)
13446ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
13456ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
13466ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	f->fmt.pix.field = V4L2_FIELD_NONE;
13476ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mutex_lock(&meye.lock);
13486ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
13496ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (f->fmt.pix.width <= 320) {
13506ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		f->fmt.pix.width = 320;
13516ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		f->fmt.pix.height = 240;
13526ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		meye.params.subsample = 1;
13536ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	} else {
13546ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		f->fmt.pix.width = 640;
13556ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		f->fmt.pix.height = 480;
13566ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		meye.params.subsample = 0;
13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13596ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	switch (f->fmt.pix.pixelformat) {
13606ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_PIX_FMT_YUYV:
13616ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT;
13626ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
13636ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case V4L2_PIX_FMT_MJPEG:
13646ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP;
13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13686ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mutex_unlock(&meye.lock);
13696ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
13706ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	f->fmt.pix.sizeimage = f->fmt.pix.height *
13716ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf			       f->fmt.pix.bytesperline;
13726ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	f->fmt.pix.colorspace = 0;
13736ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	f->fmt.pix.priv = 0;
13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13756ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	return 0;
13766ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf}
13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13786ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgrafstatic int vidioc_reqbufs(struct file *file, void *fh,
13796ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf				struct v4l2_requestbuffers *req)
13806ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf{
13816ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	int i;
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13836ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (req->memory != V4L2_MEMORY_MMAP)
13846ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13866ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (meye.grab_fbuffer && req->count == gbuffers) {
13876ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		/* already allocated, no modifications */
13886ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return 0;
13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13916ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mutex_lock(&meye.lock);
13926ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (meye.grab_fbuffer) {
13936ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		for (i = 0; i < gbuffers; i++)
13946ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf			if (meye.vma_use_count[i]) {
13956ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf				mutex_unlock(&meye.lock);
13966ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf				return -EINVAL;
13976ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf			}
13986ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		rvfree(meye.grab_fbuffer, gbuffers * gbufsize);
13996ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		meye.grab_fbuffer = NULL;
14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14026ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	gbuffers = max(2, min((int)req->count, MEYE_MAX_BUFNBRS));
14036ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	req->count = gbuffers;
14046ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	meye.grab_fbuffer = rvmalloc(gbuffers * gbufsize);
14056ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
14066ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (!meye.grab_fbuffer) {
14076ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		printk(KERN_ERR "meye: v4l framebuffer allocation"
14086ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf				" failed\n");
14093593cab5d62c4c7abced1076710f9bc2d8847433Ingo Molnar		mutex_unlock(&meye.lock);
14106ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -ENOMEM;
14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14136ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	for (i = 0; i < gbuffers; i++)
14146ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		meye.vma_use_count[i] = 0;
14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14166ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mutex_unlock(&meye.lock);
14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14186ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	return 0;
14196ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf}
14206ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
14216ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgrafstatic int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf)
14226ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf{
14236174523c5948f8a36f778f0abdfc648a5d73bf46Trent Piepho	unsigned int index = buf->index;
14246ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
14256174523c5948f8a36f778f0abdfc648a5d73bf46Trent Piepho	if (index >= gbuffers)
14266ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
14276ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
14286ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	buf->bytesused = meye.grab_buffer[index].size;
14296ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	buf->flags = V4L2_BUF_FLAG_MAPPED;
14306ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
14316ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (meye.grab_buffer[index].state == MEYE_BUF_USING)
14326ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		buf->flags |= V4L2_BUF_FLAG_QUEUED;
14336ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
14346ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (meye.grab_buffer[index].state == MEYE_BUF_DONE)
14356ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		buf->flags |= V4L2_BUF_FLAG_DONE;
14366ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
14376ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	buf->field = V4L2_FIELD_NONE;
14386ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	buf->timestamp = meye.grab_buffer[index].timestamp;
14396ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	buf->sequence = meye.grab_buffer[index].sequence;
14406ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	buf->memory = V4L2_MEMORY_MMAP;
14416ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	buf->m.offset = index * gbufsize;
14426ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	buf->length = gbufsize;
14436ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
14446ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	return 0;
14456ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf}
14466ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
14476ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgrafstatic int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
14486ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf{
14496ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (buf->memory != V4L2_MEMORY_MMAP)
14506ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
14516ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
14526174523c5948f8a36f778f0abdfc648a5d73bf46Trent Piepho	if (buf->index >= gbuffers)
14536ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
14546ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
14556ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (meye.grab_buffer[buf->index].state != MEYE_BUF_UNUSED)
14566ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
14576ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
14586ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mutex_lock(&meye.lock);
14596ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	buf->flags |= V4L2_BUF_FLAG_QUEUED;
14606ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	buf->flags &= ~V4L2_BUF_FLAG_DONE;
14616ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	meye.grab_buffer[buf->index].state = MEYE_BUF_USING;
14627acd72eb85f1c7a15e8b5eb554994949241737f1Stefani Seibold	kfifo_in_locked(&meye.grabq, (unsigned char *)&buf->index,
1463c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold			sizeof(int), &meye.grabq_lock);
14646ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mutex_unlock(&meye.lock);
14656ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
14666ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	return 0;
14676ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf}
14686ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
14696ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgrafstatic int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
14706ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf{
14716ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	int reqnr;
14726ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
14736ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (buf->memory != V4L2_MEMORY_MMAP)
14746ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
14756ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
14766ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mutex_lock(&meye.lock);
14776ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
147845465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seibold	if (kfifo_len(&meye.doneq) == 0 && file->f_flags & O_NONBLOCK) {
14793593cab5d62c4c7abced1076710f9bc2d8847433Ingo Molnar		mutex_unlock(&meye.lock);
14806ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EAGAIN;
14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14836ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (wait_event_interruptible(meye.proc_list,
148445465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seibold				     kfifo_len(&meye.doneq) != 0) < 0) {
14853593cab5d62c4c7abced1076710f9bc2d8847433Ingo Molnar		mutex_unlock(&meye.lock);
14866ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINTR;
14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14897acd72eb85f1c7a15e8b5eb554994949241737f1Stefani Seibold	if (!kfifo_out_locked(&meye.doneq, (unsigned char *)&reqnr,
1490c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold		       sizeof(int), &meye.doneq_lock)) {
14916ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		mutex_unlock(&meye.lock);
14926ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EBUSY;
14936ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	}
14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14956ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	if (meye.grab_buffer[reqnr].state != MEYE_BUF_DONE) {
14963593cab5d62c4c7abced1076710f9bc2d8847433Ingo Molnar		mutex_unlock(&meye.lock);
14976ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15006ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	buf->index = reqnr;
15016ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	buf->bytesused = meye.grab_buffer[reqnr].size;
15026ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	buf->flags = V4L2_BUF_FLAG_MAPPED;
15036ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	buf->field = V4L2_FIELD_NONE;
15046ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	buf->timestamp = meye.grab_buffer[reqnr].timestamp;
15056ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	buf->sequence = meye.grab_buffer[reqnr].sequence;
15066ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	buf->memory = V4L2_MEMORY_MMAP;
15076ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	buf->m.offset = reqnr * gbufsize;
15086ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	buf->length = gbufsize;
15096ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	meye.grab_buffer[reqnr].state = MEYE_BUF_UNUSED;
15106ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mutex_unlock(&meye.lock);
15116ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
15126ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	return 0;
15136ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf}
15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15156ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgrafstatic int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
15166ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf{
15176ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mutex_lock(&meye.lock);
15186ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
15196ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	switch (meye.mchip_mode) {
15206ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case MCHIP_HIC_MODE_CONT_OUT:
15216ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		mchip_continuous_start();
15226ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
15236ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case MCHIP_HIC_MODE_CONT_COMP:
15246ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		mchip_cont_compression_start();
15256ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		break;
15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
15276ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		mutex_unlock(&meye.lock);
15286ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15316ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mutex_unlock(&meye.lock);
15326ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15366ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgrafstatic int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15386ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mutex_lock(&meye.lock);
15396ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mchip_hic_stop();
154045465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seibold	kfifo_reset(&meye.grabq);
154145465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seibold	kfifo_reset(&meye.doneq);
15426ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
15436ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	for (i = 0; i < MEYE_MAX_BUFNBRS; i++)
15446ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		meye.grab_buffer[i].state = MEYE_BUF_UNUSED;
15456ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
15466ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	mutex_unlock(&meye.lock);
15476ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	return 0;
15486ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf}
15496ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
155099cd47bc733436da282016e629eef6baa0f6047cHans Verkuilstatic long vidioc_default(struct file *file, void *fh, bool valid_prio,
155199cd47bc733436da282016e629eef6baa0f6047cHans Verkuil						int cmd, void *arg)
15526ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf{
15536ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	switch (cmd) {
15546ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case MEYEIOC_G_PARAMS:
15556ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return meyeioc_g_params((struct meye_params *) arg);
15566ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
15576ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case MEYEIOC_S_PARAMS:
15586ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return meyeioc_s_params((struct meye_params *) arg);
15596ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
15606ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case MEYEIOC_QBUF_CAPT:
15616ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return meyeioc_qbuf_capt((int *) arg);
15626ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
15636ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case MEYEIOC_SYNC:
15646ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return meyeioc_sync(file, fh, (int *) arg);
15656ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
15666ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case MEYEIOC_STILLCAPT:
15676ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return meyeioc_stillcapt();
15686ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
15696ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	case MEYEIOC_STILLJCAPT:
15706ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return meyeioc_stilljcapt((int *) arg);
15716ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
15726ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	default:
15736ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf		return -EINVAL;
15746ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	}
15756ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf
15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int meye_poll(struct file *file, poll_table *wait)
15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int res = 0;
15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15823593cab5d62c4c7abced1076710f9bc2d8847433Ingo Molnar	mutex_lock(&meye.lock);
15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	poll_wait(file, &meye.proc_list, wait);
158445465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seibold	if (kfifo_len(&meye.doneq))
15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		res = POLLIN | POLLRDNORM;
15863593cab5d62c4c7abced1076710f9bc2d8847433Ingo Molnar	mutex_unlock(&meye.lock);
15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;
15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void meye_vm_open(struct vm_area_struct *vma)
15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1592d6144028af6b151018c50c160e794a4d7f686333Mauro Carvalho Chehab	long idx = (long)vma->vm_private_data;
15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	meye.vma_use_count[idx]++;
15941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void meye_vm_close(struct vm_area_struct *vma)
15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1598d6144028af6b151018c50c160e794a4d7f686333Mauro Carvalho Chehab	long idx = (long)vma->vm_private_data;
15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	meye.vma_use_count[idx]--;
16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1602f0f37e2f77731b3473fa6bd5ee53255d9a9cdb40Alexey Dobriyanstatic const struct vm_operations_struct meye_vm_ops = {
16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.open		= meye_vm_open,
16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.close		= meye_vm_close,
16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int meye_mmap(struct file *file, struct vm_area_struct *vma)
16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long start = vma->vm_start;
16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long size = vma->vm_end - vma->vm_start;
16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long page, pos;
16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16143593cab5d62c4c7abced1076710f9bc2d8847433Ingo Molnar	mutex_lock(&meye.lock);
16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (size > gbuffers * gbufsize) {
16163593cab5d62c4c7abced1076710f9bc2d8847433Ingo Molnar		mutex_unlock(&meye.lock);
16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!meye.grab_fbuffer) {
16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int i;
16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* lazy allocation */
16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		meye.grab_fbuffer = rvmalloc(gbuffers*gbufsize);
16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!meye.grab_fbuffer) {
16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk(KERN_ERR "meye: v4l framebuffer allocation failed\n");
16263593cab5d62c4c7abced1076710f9bc2d8847433Ingo Molnar			mutex_unlock(&meye.lock);
16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -ENOMEM;
16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < gbuffers; i++)
16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			meye.vma_use_count[i] = 0;
16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pos = (unsigned long)meye.grab_fbuffer + offset;
16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (size > 0) {
16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		page = vmalloc_to_pfn((void *)pos);
16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
16373593cab5d62c4c7abced1076710f9bc2d8847433Ingo Molnar			mutex_unlock(&meye.lock);
16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EAGAIN;
16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		start += PAGE_SIZE;
16411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pos += PAGE_SIZE;
16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (size > PAGE_SIZE)
16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			size -= PAGE_SIZE;
16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			size = 0;
16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vma->vm_ops = &meye_vm_ops;
16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vma->vm_flags &= ~VM_IO;	/* not I/O memory */
16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vma->vm_flags |= VM_RESERVED;	/* avoid to swap out this VMA */
16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vma->vm_private_data = (void *) (offset / gbufsize);
16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	meye_vm_open(vma);
16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16543593cab5d62c4c7abced1076710f9bc2d8847433Ingo Molnar	mutex_unlock(&meye.lock);
16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1658bec43661b1dc0075b7445223ba775674133b164dHans Verkuilstatic const struct v4l2_file_operations meye_fops = {
16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.owner		= THIS_MODULE,
16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.open		= meye_open,
16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.release	= meye_release,
16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.mmap		= meye_mmap,
166361df3c9b3fe6a7e47d25b27ae4df0ecdb07b8fbdHans Verkuil	.unlocked_ioctl	= video_ioctl2,
16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.poll		= meye_poll,
16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1667a399810ca69d9d4bd30ab8c1678c7439e567f90bHans Verkuilstatic const struct v4l2_ioctl_ops meye_ioctl_ops = {
16686ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	.vidioc_querycap	= vidioc_querycap,
16696ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	.vidioc_enum_input	= vidioc_enum_input,
16706ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	.vidioc_g_input		= vidioc_g_input,
16716ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	.vidioc_s_input		= vidioc_s_input,
16726ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	.vidioc_queryctrl	= vidioc_queryctrl,
16736ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	.vidioc_s_ctrl		= vidioc_s_ctrl,
16746ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	.vidioc_g_ctrl		= vidioc_g_ctrl,
167578b526a43561d7e5e702ba27948e422dfbc4bea1Hans Verkuil	.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
167678b526a43561d7e5e702ba27948e422dfbc4bea1Hans Verkuil	.vidioc_try_fmt_vid_cap	= vidioc_try_fmt_vid_cap,
167778b526a43561d7e5e702ba27948e422dfbc4bea1Hans Verkuil	.vidioc_g_fmt_vid_cap	= vidioc_g_fmt_vid_cap,
167878b526a43561d7e5e702ba27948e422dfbc4bea1Hans Verkuil	.vidioc_s_fmt_vid_cap	= vidioc_s_fmt_vid_cap,
16796ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	.vidioc_reqbufs		= vidioc_reqbufs,
16806ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	.vidioc_querybuf	= vidioc_querybuf,
16816ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	.vidioc_qbuf		= vidioc_qbuf,
16826ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	.vidioc_dqbuf		= vidioc_dqbuf,
16836ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	.vidioc_streamon	= vidioc_streamon,
16846ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	.vidioc_streamoff	= vidioc_streamoff,
16856ec6e0ced1bb9d85e29302e76f5340e3e49bd0b9Douglas Schilling Landgraf	.vidioc_default		= vidioc_default,
16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1688a399810ca69d9d4bd30ab8c1678c7439e567f90bHans Verkuilstatic struct video_device meye_template = {
1689a399810ca69d9d4bd30ab8c1678c7439e567f90bHans Verkuil	.name		= "meye",
1690a399810ca69d9d4bd30ab8c1678c7439e567f90bHans Verkuil	.fops		= &meye_fops,
1691a399810ca69d9d4bd30ab8c1678c7439e567f90bHans Verkuil	.ioctl_ops 	= &meye_ioctl_ops,
1692a399810ca69d9d4bd30ab8c1678c7439e567f90bHans Verkuil	.release	= video_device_release,
1693a399810ca69d9d4bd30ab8c1678c7439e567f90bHans Verkuil};
1694a399810ca69d9d4bd30ab8c1678c7439e567f90bHans Verkuil
16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PM
1696a291068991c4d0cc4c2bd533094422bf417c86ddPavel Machekstatic int meye_suspend(struct pci_dev *pdev, pm_message_t state)
16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_save_state(pdev);
16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	meye.pm_mchip_mode = meye.mchip_mode;
17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_hic_stop();
17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_MM_INTA, 0x0);
17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int meye_resume(struct pci_dev *pdev)
17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_restore_state(pdev);
17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_write_config_word(meye.mchip_dev, MCHIP_PCI_SOFTRESET_SET, 1);
17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_delay(MCHIP_HIC_CMD, 0);
17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE);
17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	msleep(1);
17131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_VRJ_SOFT_RESET, 1);
17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	msleep(1);
17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_MM_PCI_MODE, 5);
17161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	msleep(1);
17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_MM_INTA, MCHIP_MM_INTA_HIC_1_MASK);
17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (meye.pm_mchip_mode) {
17201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MCHIP_HIC_MODE_CONT_OUT:
17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mchip_continuous_start();
17221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MCHIP_HIC_MODE_CONT_COMP:
17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mchip_cont_compression_start();
17251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
17281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
17301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __devinit meye_probe(struct pci_dev *pcidev,
17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				const struct pci_device_id *ent)
17331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
173451270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil	struct v4l2_device *v4l2_dev = &meye.v4l2_dev;
17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = -EBUSY;
17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long mchip_adr;
17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (meye.mchip_dev != NULL) {
17391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "meye: only one device allowed!\n");
17401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto outnotdev;
17411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
174351270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil	ret = v4l2_device_register(&pcidev->dev, v4l2_dev);
174451270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil	if (ret < 0) {
174551270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
174651270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil		return ret;
174751270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil	}
1748ef0e3c26efe9c52de62b96fdad94de3ed70489d0Henrik Kretzschmar	ret = -ENOMEM;
17491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	meye.mchip_dev = pcidev;
175051270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil	meye.vdev = video_device_alloc();
175151270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil	if (!meye.vdev) {
175251270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil		v4l2_err(v4l2_dev, "video_device_alloc() failed!\n");
17531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto outnotdev;
17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	meye.grab_temp = vmalloc(MCHIP_NB_PAGES_MJPEG * PAGE_SIZE);
17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!meye.grab_temp) {
175851270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil		v4l2_err(v4l2_dev, "grab buffer allocation failed\n");
17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto outvmalloc;
17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(&meye.grabq_lock);
1763c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold	if (kfifo_alloc(&meye.grabq, sizeof(int) * MEYE_MAX_BUFNBRS,
1764c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold				GFP_KERNEL)) {
176551270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil		v4l2_err(v4l2_dev, "fifo allocation failed\n");
17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto outkfifoalloc1;
17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(&meye.doneq_lock);
1769c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold	if (kfifo_alloc(&meye.doneq, sizeof(int) * MEYE_MAX_BUFNBRS,
1770c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold				GFP_KERNEL)) {
177151270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil		v4l2_err(v4l2_dev, "fifo allocation failed\n");
17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto outkfifoalloc2;
17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
177551270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil	memcpy(meye.vdev, &meye_template, sizeof(meye_template));
177651270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil	meye.vdev->v4l2_dev = &meye.v4l2_dev;
17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17785b5aff83a549c8f1e425e06d46ec951eae950b37Mauro Carvalho Chehab	ret = -EIO;
1779cbefb762b67fa6d3eb2a48ae3380358a940e8c9dmalattia@linux.it	if ((ret = sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 1))) {
178051270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil		v4l2_err(v4l2_dev, "meye: unable to power on the camera\n");
178151270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil		v4l2_err(v4l2_dev, "meye: did you enable the camera in "
17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"sonypi using the module options ?\n");
17831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto outsonypienable;
17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((ret = pci_enable_device(meye.mchip_dev))) {
178751270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil		v4l2_err(v4l2_dev, "meye: pci_enable_device failed\n");
17881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto outenabledev;
17891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_adr = pci_resource_start(meye.mchip_dev,0);
17921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!mchip_adr) {
179351270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil		v4l2_err(v4l2_dev, "meye: mchip has no device base address\n");
17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto outregions;
17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!request_mem_region(pci_resource_start(meye.mchip_dev, 0),
17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pci_resource_len(meye.mchip_dev, 0),
17981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"meye")) {
179951270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil		v4l2_err(v4l2_dev, "meye: request_mem_region failed\n");
18001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto outregions;
18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	meye.mchip_mmregs = ioremap(mchip_adr, MCHIP_MM_REGS);
18031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!meye.mchip_mmregs) {
180451270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil		v4l2_err(v4l2_dev, "meye: ioremap failed\n");
18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto outremap;
18061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
18071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	meye.mchip_irq = pcidev->irq;
18091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (request_irq(meye.mchip_irq, meye_irq,
18108076fe32a7db9a6628589ffa372808e4ba25d222Thomas Gleixner			IRQF_DISABLED | IRQF_SHARED, "meye", meye_irq)) {
181151270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil		v4l2_err(v4l2_dev, "request_irq failed\n");
18121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto outreqirq;
18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_write_config_byte(meye.mchip_dev, PCI_CACHE_LINE_SIZE, 8);
18161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_write_config_byte(meye.mchip_dev, PCI_LATENCY_TIMER, 64);
18171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_set_master(meye.mchip_dev);
18191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Ask the camera to perform a soft reset. */
18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_write_config_word(meye.mchip_dev, MCHIP_PCI_SOFTRESET_SET, 1);
18221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_delay(MCHIP_HIC_CMD, 0);
18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE);
18251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	msleep(1);
18271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_VRJ_SOFT_RESET, 1);
18281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	msleep(1);
18301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_MM_PCI_MODE, 5);
18311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	msleep(1);
18331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_MM_INTA, MCHIP_MM_INTA_HIC_1_MASK);
18341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18353593cab5d62c4c7abced1076710f9bc2d8847433Ingo Molnar	mutex_init(&meye.lock);
18361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_waitqueue_head(&meye.proc_list);
183751270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil	meye.brightness = 32 << 10;
183851270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil	meye.hue = 32 << 10;
183951270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil	meye.colour = 32 << 10;
184051270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil	meye.contrast = 32 << 10;
18411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	meye.params.subsample = 0;
18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	meye.params.quality = 8;
18431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	meye.params.sharpness = 32;
18441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	meye.params.agc = 48;
18451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	meye.params.picture = 0;
18461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	meye.params.framerate = 0;
18471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1848cbefb762b67fa6d3eb2a48ae3380358a940e8c9dmalattia@linux.it	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, 32);
1849cbefb762b67fa6d3eb2a48ae3380358a940e8c9dmalattia@linux.it	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAHUE, 32);
1850cbefb762b67fa6d3eb2a48ae3380358a940e8c9dmalattia@linux.it	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACOLOR, 32);
1851cbefb762b67fa6d3eb2a48ae3380358a940e8c9dmalattia@linux.it	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACONTRAST, 32);
1852cbefb762b67fa6d3eb2a48ae3380358a940e8c9dmalattia@linux.it	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS, 32);
1853cbefb762b67fa6d3eb2a48ae3380358a940e8c9dmalattia@linux.it	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE, 0);
1854cbefb762b67fa6d3eb2a48ae3380358a940e8c9dmalattia@linux.it	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC, 48);
18551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
185661df3c9b3fe6a7e47d25b27ae4df0ecdb07b8fbdHans Verkuil	if (video_register_device(meye.vdev, VFL_TYPE_GRABBER,
185761df3c9b3fe6a7e47d25b27ae4df0ecdb07b8fbdHans Verkuil				  video_nr) < 0) {
185861df3c9b3fe6a7e47d25b27ae4df0ecdb07b8fbdHans Verkuil		v4l2_err(v4l2_dev, "video_register_device failed\n");
185961df3c9b3fe6a7e47d25b27ae4df0ecdb07b8fbdHans Verkuil		goto outvideoreg;
186061df3c9b3fe6a7e47d25b27ae4df0ecdb07b8fbdHans Verkuil	}
186161df3c9b3fe6a7e47d25b27ae4df0ecdb07b8fbdHans Verkuil
186251270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil	v4l2_info(v4l2_dev, "Motion Eye Camera Driver v%s.\n",
18631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       MEYE_DRIVER_VERSION);
186451270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil	v4l2_info(v4l2_dev, "mchip KL5A72002 rev. %d, base %lx, irq %d\n",
186544c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok	       meye.mchip_dev->revision, mchip_adr, meye.mchip_irq);
18661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
18681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsoutvideoreg:
18701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	free_irq(meye.mchip_irq, meye_irq);
18711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsoutreqirq:
18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iounmap(meye.mchip_mmregs);
18731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsoutremap:
18741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	release_mem_region(pci_resource_start(meye.mchip_dev, 0),
18751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   pci_resource_len(meye.mchip_dev, 0));
18761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsoutregions:
18771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_disable_device(meye.mchip_dev);
18781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsoutenabledev:
1879cbefb762b67fa6d3eb2a48ae3380358a940e8c9dmalattia@linux.it	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0);
18801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsoutsonypienable:
188145465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seibold	kfifo_free(&meye.doneq);
18821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsoutkfifoalloc2:
188345465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seibold	kfifo_free(&meye.grabq);
18841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsoutkfifoalloc1:
18851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vfree(meye.grab_temp);
18861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsoutvmalloc:
188751270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil	video_device_release(meye.vdev);
18881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsoutnotdev:
18891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
18901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __devexit meye_remove(struct pci_dev *pcidev)
18931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
189451270617a52793c423ef68ddd3f18745e9abd15bHans Verkuil	video_unregister_device(meye.vdev);
18951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_hic_stop();
18971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_dma_free();
18991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* disable interrupts */
19011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchip_set(MCHIP_MM_INTA, 0x0);
19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	free_irq(meye.mchip_irq, meye_irq);
19041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iounmap(meye.mchip_mmregs);
19061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	release_mem_region(pci_resource_start(meye.mchip_dev, 0),
19081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   pci_resource_len(meye.mchip_dev, 0));
19091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_disable_device(meye.mchip_dev);
19111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1912cbefb762b67fa6d3eb2a48ae3380358a940e8c9dmalattia@linux.it	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0);
19131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
191445465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seibold	kfifo_free(&meye.doneq);
191545465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seibold	kfifo_free(&meye.grabq);
19161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vfree(meye.grab_temp);
19181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (meye.grab_fbuffer) {
19201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rvfree(meye.grab_fbuffer, gbuffers*gbufsize);
19211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		meye.grab_fbuffer = NULL;
19221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
19231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_INFO "meye: removed\n");
19251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
19261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_device_id meye_pci_tbl[] = {
192876e9741d1d7deb332abbbc3d8fc4c55154e2c180Joe Perches	{ PCI_VDEVICE(KAWASAKI, PCI_DEVICE_ID_MCHIP_KL5A72002), 0 },
19291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ }
19301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
19311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(pci, meye_pci_tbl);
19331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_driver meye_driver = {
19351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "meye",
19361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.id_table	= meye_pci_tbl,
19371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.probe		= meye_probe,
19381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.remove		= __devexit_p(meye_remove),
19391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PM
19401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.suspend	= meye_suspend,
19411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.resume		= meye_resume,
19421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
19431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
19441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init meye_init(void)
19461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
19471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	gbuffers = max(2, min((int)gbuffers, MEYE_MAX_BUFNBRS));
19481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (gbufsize < 0 || gbufsize > MEYE_MAX_BUFSIZE)
19491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		gbufsize = MEYE_MAX_BUFSIZE;
19501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	gbufsize = PAGE_ALIGN(gbufsize);
1951ac9bb7f5167d53207893a783a2f722cd6e6ed78fJoe Perches	printk(KERN_INFO "meye: using %d buffers with %dk (%dk total) "
19521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 "for capture\n",
19531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 gbuffers,
19541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 gbufsize / 1024, gbuffers * gbufsize / 1024);
19551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return pci_register_driver(&meye_driver);
19561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
19571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit meye_exit(void)
19591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
19601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_unregister_driver(&meye_driver);
19611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
19621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(meye_init);
19641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(meye_exit);
1965