11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Colour AR M64278(VGA) driver for Video4Linux
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2003	Takeo Takahashi <takahashi.takeo@renesas.com>
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * modify it under the terms of the GNU General Public License
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * as published by the Free Software Foundation; either version
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2 of the License, or (at your option) any later version.
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Some code is taken from AR driver sample program for M3T-M32700UT.
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * AR driver sample (M32R SDK):
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     Copyright (c) 2003 RENESAS TECHNOROGY CORPORATION
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     AND RENESAS SOLUTIONS CORPORATION
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     All Rights Reserved.
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2003-09-01:	Support w3cam by Takeo Takahashi
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h>
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fs.h>
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h>
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h>
30b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil#include <linux/videodev2.h>
315e87efa3b29c105f81fea785babafb098e4e046dMauro Carvalho Chehab#include <media/v4l2-common.h>
32b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil#include <media/v4l2-device.h>
33dfb9aff025c4c874f9169e2fd690ce6fee2309feAdrian Bunk#include <media/v4l2-ioctl.h>
343593cab5d62c4c7abced1076710f9bc2d8847433Ingo Molnar#include <linux/mutex.h>
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h>
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/m32r.h>
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/dma.h>
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/byteorder.h>
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0
4388f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil#define DEBUG(n, args...) printk(KERN_INFO args)
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CHECK_LOST	1
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DEBUG(n, args...)
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CHECK_LOST	0
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * USE_INT is always 0, interrupt mode is not available
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * on linux due to lack of speed
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define USE_INT		0	/* Don't modify */
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
561990d50b58bef127a647005fdcada6d07081d3efMauro Carvalho Chehab#define VERSION	"0.0.5"
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ar_inl(addr) 		inl((unsigned long)(addr))
5988f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil#define ar_outl(val, addr)	outl((unsigned long)(val), (unsigned long)(addr))
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern struct cpuinfo_m32r	boot_cpu_data;
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * CCD pixel size
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Note that M32700UT does not support CIF mode, but QVGA is
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	supported by M32700UT hardware using VGA mode of AR LSI.
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 	Supported: VGA  (Normal mode, Interlace mode)
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		   QVGA (Always Interlace mode of VGA)
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define AR_WIDTH_VGA		640
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define AR_HEIGHT_VGA		480
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define AR_WIDTH_QVGA		320
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define AR_HEIGHT_QVGA		240
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MIN_AR_WIDTH		AR_WIDTH_QVGA
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MIN_AR_HEIGHT		AR_HEIGHT_QVGA
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MAX_AR_WIDTH		AR_WIDTH_VGA
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MAX_AR_HEIGHT		AR_HEIGHT_VGA
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* bits & bytes per pixel */
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define AR_BITS_PER_PIXEL	16
83b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil#define AR_BYTES_PER_PIXEL	(AR_BITS_PER_PIXEL / 8)
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* line buffer size */
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define AR_LINE_BYTES_VGA	(AR_WIDTH_VGA * AR_BYTES_PER_PIXEL)
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define AR_LINE_BYTES_QVGA	(AR_WIDTH_QVGA * AR_BYTES_PER_PIXEL)
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MAX_AR_LINE_BYTES	AR_LINE_BYTES_VGA
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* frame size & type */
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define AR_FRAME_BYTES_VGA \
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(AR_WIDTH_VGA * AR_HEIGHT_VGA * AR_BYTES_PER_PIXEL)
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define AR_FRAME_BYTES_QVGA \
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(AR_WIDTH_QVGA * AR_HEIGHT_QVGA * AR_BYTES_PER_PIXEL)
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MAX_AR_FRAME_BYTES \
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(MAX_AR_WIDTH * MAX_AR_HEIGHT * AR_BYTES_PER_PIXEL)
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define AR_MAX_FRAME		15
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* capture size */
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define AR_SIZE_VGA		0
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define AR_SIZE_QVGA		1
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* capture mode */
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define AR_MODE_INTERLACE	0
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define AR_MODE_NORMAL		1
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
108b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuilstruct ar {
109b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	struct v4l2_device v4l2_dev;
110b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	struct video_device vdev;
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int start_capture;	/* duaring capture in INT. mode. */
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if USE_INT
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char *line_buff;	/* DMA line buffer */
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char *frame[MAX_AR_HEIGHT];	/* frame data */
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	short size;			/* capture size */
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	short mode;			/* capture mode */
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int width, height;
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int frame_bytes, line_bytes;
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wait_queue_head_t wait;
1213593cab5d62c4c7abced1076710f9bc2d8847433Ingo Molnar	struct mutex lock;
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
124b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuilstatic struct ar ardev;
125b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int video_nr = -1;	/* video device number (first free) */
127b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuilstatic unsigned char yuv[MAX_AR_FRAME_BYTES];
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* module parameters */
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* default frequency */
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DEFAULT_FREQ	50	/* 50 or 75 (MHz) is available as BCLK */
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int freq = DEFAULT_FREQ;	/* BCLK: available 50 or 70 (MHz) */
133ff699e6bd02eb1c6d02c7c2b576c2ee6caab201cDouglas Schilling Landgrafstatic int vga;			/* default mode(0:QVGA mode, other:VGA mode) */
134ff699e6bd02eb1c6d02c7c2b576c2ee6caab201cDouglas Schilling Landgrafstatic int vga_interlace;	/* 0 is normal mode for, else interlace mode */
1359b565eb794eec1ccd9edcc7263ebe5b3245a1e65Eric Sesterhenn / snakebytemodule_param(freq, int, 0);
1369b565eb794eec1ccd9edcc7263ebe5b3245a1e65Eric Sesterhenn / snakebytemodule_param(vga, int, 0);
1379b565eb794eec1ccd9edcc7263ebe5b3245a1e65Eric Sesterhenn / snakebytemodule_param(vga_interlace, int, 0);
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
139b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuilstatic void wait_for_vsync(void)
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (ar_inl(ARVCR0) & ARVCR0_VDS)	/* wait for VSYNC */
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cpu_relax();
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (!(ar_inl(ARVCR0) & ARVCR0_VDS))	/* wait for VSYNC */
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cpu_relax();
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
147b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuilstatic void wait_acknowledge(void)
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 1000; i++)
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cpu_relax();
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (ar_inl(PLDI2CSTS) & PLDI2CSTS_NOACK)
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cpu_relax();
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*******************************************************************
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * I2C functions
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *******************************************************************/
160b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuilstatic void iic(int n, unsigned long addr, unsigned long data1, unsigned long data2,
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 unsigned long data3)
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
165d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab	/* Slave Address */
166d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab	ar_outl(addr, PLDI2CDATA);
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wait_for_vsync();
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
169d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab	/* Start */
170d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab	ar_outl(1, PLDI2CCND);
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wait_acknowledge();
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Transfer data 1 */
174d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab	ar_outl(data1, PLDI2CDATA);
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wait_for_vsync();
176d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab	ar_outl(PLDI2CSTEN_STEN, PLDI2CSTEN);
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wait_acknowledge();
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Transfer data 2 */
180d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab	ar_outl(data2, PLDI2CDATA);
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wait_for_vsync();
182d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab	ar_outl(PLDI2CSTEN_STEN, PLDI2CSTEN);
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wait_acknowledge();
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (n == 3) {
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Transfer data 3 */
187d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab		ar_outl(data3, PLDI2CDATA);
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		wait_for_vsync();
189d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab		ar_outl(PLDI2CSTEN_STEN, PLDI2CSTEN);
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		wait_acknowledge();
191d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab	}
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
193d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab	/* Stop */
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 100; i++)
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cpu_relax();
196d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab	ar_outl(2, PLDI2CCND);
197d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab	ar_outl(2, PLDI2CCND);
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (ar_inl(PLDI2CSTS) & PLDI2CSTS_BB)
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cpu_relax();
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
204b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuilstatic void init_iic(void)
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DEBUG(1, "init_iic:\n");
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
208d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab	/*
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * ICU Setting (iic)
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
211d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab	/* I2C Setting */
212d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab	ar_outl(0x0, PLDI2CCR);      	/* I2CCR Disable                   */
213d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab	ar_outl(0x0300, PLDI2CMOD); 	/* I2CMOD ACK/8b-data/7b-addr/auto */
214d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab	ar_outl(0x1, PLDI2CACK);	/* I2CACK ACK                      */
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
216657de3cd32285831a56f9f96deb85c64205c42fcTrent Piepho	/* I2C CLK */
217d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab	/* 50MH-100k */
21888f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	if (freq == 75)
219d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab		ar_outl(369, PLDI2CFREQ);	/* BCLK = 75MHz */
22088f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	else if (freq == 50)
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ar_outl(244, PLDI2CFREQ);	/* BCLK = 50MHz */
22288f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	else
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ar_outl(244, PLDI2CFREQ);	/* default: BCLK = 50MHz */
224d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab	ar_outl(0x1, PLDI2CCR); 	/* I2CCR Enable */
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**************************************************************************
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Video4Linux Interface functions
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds **************************************************************************/
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void disable_dma(void)
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar_outl(0x8000, M32R_DMAEN_PORTL);	/* disable DMA0 */
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void enable_dma(void)
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar_outl(0x8080, M32R_DMAEN_PORTL);	/* enable DMA0 */
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void clear_dma_status(void)
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar_outl(0x8000, M32R_DMAEDET_PORTL);	/* clear status */
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
248b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuilstatic void wait_for_vertical_sync(struct ar *ar, int exp_line)
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if CHECK_LOST
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int tmout = 10000;	/* FIXME */
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int l;
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * check HCOUNT because we cannot check vertical sync.
256d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab	 */
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (; tmout >= 0; tmout--) {
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		l = ar_inl(ARVHCOUNT);
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (l == exp_line)
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tmout < 0)
263b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		v4l2_err(&ar->v4l2_dev, "lost %d -> %d\n", exp_line, l);
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (ar_inl(ARVHCOUNT) != exp_line)
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cpu_relax();
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos)
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
272b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	struct ar *ar = video_drvdata(file);
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long ret = ar->frame_bytes;		/* return read bytes */
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long arvcr1 = 0;
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char *p;
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int h, w;
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char *py, *pu, *pv;
27988f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil#if !USE_INT
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int l;
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DEBUG(1, "ar_read()\n");
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ar->size == AR_SIZE_QVGA)
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		arvcr1 |= ARVCR1_QVGA;
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ar->mode == AR_MODE_NORMAL)
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		arvcr1 |= ARVCR1_NORMAL;
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2903593cab5d62c4c7abced1076710f9bc2d8847433Ingo Molnar	mutex_lock(&ar->lock);
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if USE_INT
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	local_irq_save(flags);
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	disable_dma();
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar_outl(0xa1871300, M32R_DMA0CR0_PORTL);
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar_outl(0x01000000, M32R_DMA0CR1_PORTL);
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* set AR FIFO address as source(BSEL5) */
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar_outl(ARDATA32, M32R_DMA0CSA_PORTL);
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar_outl(ARDATA32, M32R_DMA0RSA_PORTL);
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar_outl(ar->line_buff, M32R_DMA0CDA_PORTL);	/* destination addr. */
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar_outl(ar->line_buff, M32R_DMA0RDA_PORTL); 	/* reload address */
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar_outl(ar->line_bytes, M32R_DMA0CBCUT_PORTL); 	/* byte count (bytes) */
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar_outl(ar->line_bytes, M32R_DMA0RBCUT_PORTL); 	/* reload count (bytes) */
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
307b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	 * Okay, kick AR LSI to invoke an interrupt
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar->start_capture = 0;
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar_outl(arvcr1 | ARVCR1_HIEN, ARVCR1);
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	local_irq_restore(flags);
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* .... AR interrupts .... */
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	interruptible_sleep_on(&ar->wait);
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (signal_pending(current)) {
31588f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil		printk(KERN_ERR "arv: interrupted while get frame data.\n");
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -EINTR;
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_up;
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else	/* ! USE_INT */
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* polling */
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar_outl(arvcr1, ARVCR1);
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	disable_dma();
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar_outl(0x8000, M32R_DMAEDET_PORTL);
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar_outl(0xa0861300, M32R_DMA0CR0_PORTL);
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar_outl(0x01000000, M32R_DMA0CR1_PORTL);
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar_outl(ARDATA32, M32R_DMA0CSA_PORTL);
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar_outl(ARDATA32, M32R_DMA0RSA_PORTL);
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar_outl(ar->line_bytes, M32R_DMA0CBCUT_PORTL);
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar_outl(ar->line_bytes, M32R_DMA0RBCUT_PORTL);
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	local_irq_save(flags);
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (ar_inl(ARVHCOUNT) != 0)		/* wait for 0 */
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cpu_relax();
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ar->mode == AR_MODE_INTERLACE && ar->size == AR_SIZE_VGA) {
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (h = 0; h < ar->height; h++) {
336b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil			wait_for_vertical_sync(ar, h);
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (h < (AR_HEIGHT_VGA/2))
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				l = h << 1;
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				l = (((h - (AR_HEIGHT_VGA/2)) << 1) + 1);
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ar_outl(virt_to_phys(ar->frame[l]), M32R_DMA0CDA_PORTL);
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			enable_dma();
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			while (!(ar_inl(M32R_DMAEDET_PORTL) & 0x8000))
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				cpu_relax();
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			disable_dma();
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			clear_dma_status();
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ar_outl(0xa0861300, M32R_DMA0CR0_PORTL);
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (h = 0; h < ar->height; h++) {
351b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil			wait_for_vertical_sync(ar, h);
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ar_outl(virt_to_phys(ar->frame[h]), M32R_DMA0CDA_PORTL);
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			enable_dma();
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			while (!(ar_inl(M32R_DMAEDET_PORTL) & 0x8000))
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				cpu_relax();
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			disable_dma();
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			clear_dma_status();
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ar_outl(0xa0861300, M32R_DMA0CR0_PORTL);
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	local_irq_restore(flags);
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif	/* ! USE_INT */
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * convert YUV422 to YUV422P
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * 	+--------------------+
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	|  Y0,Y1,...	     |
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	|  ..............Yn  |
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	+--------------------+
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	|  U0,U1,........Un  |
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	+--------------------+
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	|  V0,V1,........Vn  |
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *	+--------------------+
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	py = yuv;
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pu = py + (ar->frame_bytes / 2);
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pv = pu + (ar->frame_bytes / 4);
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (h = 0; h < ar->height; h++) {
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p = ar->frame[h];
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (w = 0; w < ar->line_bytes; w += 4) {
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*py++ = *p++;
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*pu++ = *p++;
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*py++ = *p++;
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*pv++ = *p++;
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (copy_to_user(buf, yuv, ar->frame_bytes)) {
388b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		v4l2_err(&ar->v4l2_dev, "failed while copy_to_user yuv.\n");
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -EFAULT;
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_up;
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DEBUG(1, "ret = %d\n", ret);
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_up:
3943593cab5d62c4c7abced1076710f9bc2d8847433Ingo Molnar	mutex_unlock(&ar->lock);
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
398b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuilstatic int ar_querycap(struct file *file, void  *priv,
399b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil					struct v4l2_capability *vcap)
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
401b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	struct ar *ar = video_drvdata(file);
402b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil
403b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	strlcpy(vcap->driver, ar->vdev.name, sizeof(vcap->driver));
404b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	strlcpy(vcap->card, "Colour AR VGA", sizeof(vcap->card));
405b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	strlcpy(vcap->bus_info, "Platform", sizeof(vcap->bus_info));
406b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	vcap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
407b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	return 0;
408b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil}
409b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil
410b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuilstatic int ar_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
411b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil{
412b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	if (vin->index > 0)
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
414b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	strlcpy(vin->name, "Camera", sizeof(vin->name));
415b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	vin->type = V4L2_INPUT_TYPE_CAMERA;
416b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	vin->audioset = 0;
417b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	vin->tuner = 0;
418b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	vin->std = V4L2_STD_ALL;
419b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	vin->status = 0;
420b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	return 0;
421b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil}
422b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil
423b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuilstatic int ar_g_input(struct file *file, void *fh, unsigned int *inp)
424b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil{
425b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	*inp = 0;
426b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	return 0;
427b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil}
428b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil
429b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuilstatic int ar_s_input(struct file *file, void *fh, unsigned int inp)
430b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil{
431b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	return inp ? -EINVAL : 0;
432b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil}
433b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil
434b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuilstatic int ar_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
435b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil{
436b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	struct ar *ar = video_drvdata(file);
437b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	struct v4l2_pix_format *pix = &fmt->fmt.pix;
438b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil
439b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	pix->width = ar->width;
440b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	pix->height = ar->height;
441b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	pix->pixelformat = V4L2_PIX_FMT_YUV422P;
442b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	pix->field = (ar->mode == AR_MODE_NORMAL) ? V4L2_FIELD_NONE : V4L2_FIELD_INTERLACED;
443b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	pix->bytesperline = ar->width;
444b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	pix->sizeimage = 2 * ar->width * ar->height;
445b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	/* Just a guess */
446b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
447b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	return 0;
448b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil}
449b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil
450b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuilstatic int ar_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
451b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil{
452b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	struct ar *ar = video_drvdata(file);
453b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	struct v4l2_pix_format *pix = &fmt->fmt.pix;
454b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil
455b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	if (pix->height <= AR_HEIGHT_QVGA || pix->width <= AR_WIDTH_QVGA) {
456b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		pix->height = AR_HEIGHT_QVGA;
457b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		pix->width = AR_WIDTH_QVGA;
458b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		pix->field = V4L2_FIELD_INTERLACED;
459b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	} else {
460b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		pix->height = AR_HEIGHT_VGA;
461b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		pix->width = AR_WIDTH_VGA;
462b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		pix->field = vga_interlace ? V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE;
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
464b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	pix->pixelformat = V4L2_PIX_FMT_YUV422P;
465b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	pix->bytesperline = ar->width;
466b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	pix->sizeimage = 2 * ar->width * ar->height;
467b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	/* Just a guess */
468b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
469b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	return 0;
470b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil}
471b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil
472b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuilstatic int ar_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
473b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil{
474b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	struct ar *ar = video_drvdata(file);
475b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	struct v4l2_pix_format *pix = &fmt->fmt.pix;
476b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	int ret = ar_try_fmt_vid_cap(file, fh, fmt);
477b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil
478b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	if (ret)
479b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		return ret;
480b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	mutex_lock(&ar->lock);
481b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	ar->width = pix->width;
482b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	ar->height = pix->height;
483b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	if (ar->width == AR_WIDTH_VGA) {
484b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		ar->size = AR_SIZE_VGA;
485b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		ar->frame_bytes = AR_FRAME_BYTES_VGA;
486b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		ar->line_bytes = AR_LINE_BYTES_VGA;
487b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		if (vga_interlace)
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ar->mode = AR_MODE_INTERLACE;
489b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		else
490b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil			ar->mode = AR_MODE_NORMAL;
491b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	} else {
492b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		ar->size = AR_SIZE_QVGA;
493b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		ar->frame_bytes = AR_FRAME_BYTES_QVGA;
494b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		ar->line_bytes = AR_LINE_BYTES_QVGA;
495b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		ar->mode = AR_MODE_INTERLACE;
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
497b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	/* Ok we figured out what to use from our wide choice */
498b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	mutex_unlock(&ar->lock);
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
502b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuilstatic int ar_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
504b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	static struct v4l2_fmtdesc formats[] = {
505b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		{ 0, 0, 0,
506b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		  "YUV 4:2:2 Planar", V4L2_PIX_FMT_YUV422P,
507b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		  { 0, 0, 0, 0 }
508b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		},
509b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	};
510b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	enum v4l2_buf_type type = fmt->type;
511b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil
512b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	if (fmt->index > 0)
513b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		return -EINVAL;
514b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil
515b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	*fmt = formats[fmt->index];
516b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	fmt->type = type;
517b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	return 0;
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if USE_INT
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Interrupt handler
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5247d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void ar_interrupt(int irq, void *dev)
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
526b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	struct ar *ar = dev;
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int line_count;
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int line_number;
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int arvcr1;
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	line_count = ar_inl(ARVHCOUNT);			/* line number */
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ar->mode == AR_MODE_INTERLACE && ar->size == AR_SIZE_VGA) {
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* operations for interlace mode */
53488f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil		if (line_count < (AR_HEIGHT_VGA / 2)) 	/* even line */
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			line_number = (line_count << 1);
536d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab		else 					/* odd line */
537d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab			line_number =
53888f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil			(((line_count - (AR_HEIGHT_VGA / 2)) << 1) + 1);
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		line_number = line_count;
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (line_number == 0) {
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * It is an interrupt for line 0.
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * we have to start capture.
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		disable_dma();
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ar_outl(ar->line_buff, M32R_DMA0CDA_PORTL);	/* needless? */
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy(ar->frame[0], ar->line_buff, ar->line_bytes);
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ar_outl(0xa1861300, M32R_DMA0CR0_PORTL);
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		enable_dma();
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ar->start_capture = 1;			/* during capture */
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ar->start_capture == 1 && line_number <= (ar->height - 1)) {
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		disable_dma();
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy(ar->frame[line_number], ar->line_buff, ar->line_bytes);
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * if captured all line of a frame, disable AR interrupt
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * and wake a process up.
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (line_number == (ar->height - 1)) { 	/* end  of line */
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ar->start_capture = 0;
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* disable AR interrupt request */
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			arvcr1 = ar_inl(ARVCR1);
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			arvcr1 &= ~ARVCR1_HIEN;		/* clear int. flag */
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ar_outl(arvcr1, ARVCR1);	/* disable */
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			wake_up_interruptible(&ar->wait);
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ar_outl(ar->line_buff, M32R_DMA0CDA_PORTL);
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ar_outl(0xa1861300, M32R_DMA0CR0_PORTL);
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			enable_dma();
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ar_initialize()
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 	ar_initialize() is called by video_register_device() and
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	initializes AR LSI and peripherals.
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	-1 is returned in all failures.
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	0 is returned in success.
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
598b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuilstatic int ar_initialize(struct ar *ar)
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long cr = 0;
60188f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	int i, found = 0;
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DEBUG(1, "ar_initialize:\n");
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * initialize AR LSI
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar_outl(0, ARVCR0);		/* assert reset of AR LSI */
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 0x18; i++)	/* wait for over 10 cycles @ 27MHz */
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cpu_relax();
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar_outl(ARVCR0_RST, ARVCR0);	/* negate reset of AR LSI (enable) */
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 0x40d; i++)	/* wait for over 420 cycles @ 27MHz */
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cpu_relax();
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* AR uses INT3 of CPU as interrupt pin. */
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar_outl(ARINTSEL_INT3, ARINTSEL);
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ar->size == AR_SIZE_QVGA)
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cr |= ARVCR1_QVGA;
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ar->mode == AR_MODE_NORMAL)
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cr |= ARVCR1_NORMAL;
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar_outl(cr, ARVCR1);
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
624d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab	/*
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Initialize IIC so that CPU can communicate with AR LSI,
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * and send boot commands to AR LSI.
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_iic();
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 0x100000; i++) {	/* > 0xa1d10,  56ms */
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((ar_inl(ARVCR0) & ARVCR0_VDS)) {	/* VSYNC */
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			found = 1;
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (found == 0)
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
640b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	v4l2_info(&ar->v4l2_dev, "Initializing ");
64188f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil
64288f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(2, 0x78, 0x11, 0x01, 0x00);	/* start */
64388f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(3, 0x78, 0x12, 0x00, 0x06);
64488f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(3, 0x78, 0x12, 0x12, 0x30);
64588f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(3, 0x78, 0x12, 0x15, 0x58);
64688f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(3, 0x78, 0x12, 0x17, 0x30);
64788f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	printk(KERN_CONT ".");
64888f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(3, 0x78, 0x12, 0x1a, 0x97);
64988f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(3, 0x78, 0x12, 0x1b, 0xff);
65088f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(3, 0x78, 0x12, 0x1c, 0xff);
65188f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(3, 0x78, 0x12, 0x26, 0x10);
65288f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(3, 0x78, 0x12, 0x27, 0x00);
65388f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	printk(KERN_CONT ".");
65488f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(2, 0x78, 0x34, 0x02, 0x00);
65588f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(2, 0x78, 0x7a, 0x10, 0x00);
65688f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(2, 0x78, 0x80, 0x39, 0x00);
65788f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(2, 0x78, 0x81, 0xe6, 0x00);
65888f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(2, 0x78, 0x8d, 0x00, 0x00);
65988f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	printk(KERN_CONT ".");
66088f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(2, 0x78, 0x8e, 0x0c, 0x00);
66188f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(2, 0x78, 0x8f, 0x00, 0x00);
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0
66388f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(2, 0x78, 0x90, 0x00, 0x00);	/* AWB on=1 off=0 */
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
66588f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(2, 0x78, 0x93, 0x01, 0x00);
66688f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(2, 0x78, 0x94, 0xcd, 0x00);
66788f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(2, 0x78, 0x95, 0x00, 0x00);
66888f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	printk(KERN_CONT ".");
66988f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(2, 0x78, 0x96, 0xa0, 0x00);
67088f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(2, 0x78, 0x97, 0x00, 0x00);
67188f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(2, 0x78, 0x98, 0x60, 0x00);
67288f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(2, 0x78, 0x99, 0x01, 0x00);
67388f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(2, 0x78, 0x9a, 0x19, 0x00);
67488f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	printk(KERN_CONT ".");
67588f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(2, 0x78, 0x9b, 0x02, 0x00);
67688f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(2, 0x78, 0x9c, 0xe8, 0x00);
67788f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(2, 0x78, 0x9d, 0x02, 0x00);
67888f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(2, 0x78, 0x9e, 0x2e, 0x00);
67988f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(2, 0x78, 0xb8, 0x78, 0x00);
68088f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(2, 0x78, 0xba, 0x05, 0x00);
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0
68288f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(2, 0x78, 0x83, 0x8c, 0x00);	/* brightness */
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
68488f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	printk(KERN_CONT ".");
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* color correction */
68788f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(3, 0x78, 0x49, 0x00, 0x95);	/* a		*/
68888f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(3, 0x78, 0x49, 0x01, 0x96);	/* b		*/
68988f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(3, 0x78, 0x49, 0x03, 0x85);	/* c		*/
69088f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(3, 0x78, 0x49, 0x04, 0x97);	/* d		*/
69188f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(3, 0x78, 0x49, 0x02, 0x7e);	/* e(Lo)	*/
69288f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(3, 0x78, 0x49, 0x05, 0xa4);	/* f(Lo)	*/
69388f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(3, 0x78, 0x49, 0x06, 0x04);	/* e(Hi)	*/
69488f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(3, 0x78, 0x49, 0x07, 0x04);	/* e(Hi)	*/
69588f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(2, 0x78, 0x48, 0x01, 0x00);	/* on=1 off=0	*/
69688f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil
69788f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	printk(KERN_CONT ".");
69888f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	iic(2, 0x78, 0x11, 0x00, 0x00);	/* end */
69988f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	printk(KERN_CONT " done\n");
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************************************
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Video4Linux Module functions
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ****************************************************************************/
7097d43cd53c851e3cf04d73108d4e7e25a1104c6f5Hans Verkuil
710bec43661b1dc0075b7445223ba775674133b164dHans Verkuilstatic const struct v4l2_file_operations ar_fops = {
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.owner		= THIS_MODULE,
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.read		= ar_read,
71361df3c9b3fe6a7e47d25b27ae4df0ecdb07b8fbdHans Verkuil	.unlocked_ioctl	= video_ioctl2,
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
716b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuilstatic const struct v4l2_ioctl_ops ar_ioctl_ops = {
717b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	.vidioc_querycap    		    = ar_querycap,
718b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	.vidioc_g_input      		    = ar_g_input,
719b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	.vidioc_s_input      		    = ar_s_input,
720b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	.vidioc_enum_input   		    = ar_enum_input,
721b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	.vidioc_enum_fmt_vid_cap 	    = ar_enum_fmt_vid_cap,
722b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	.vidioc_g_fmt_vid_cap 		    = ar_g_fmt_vid_cap,
723b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	.vidioc_s_fmt_vid_cap  		    = ar_s_fmt_vid_cap,
724b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	.vidioc_try_fmt_vid_cap  	    = ar_try_fmt_vid_cap,
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ALIGN4(x)	((((int)(x)) & 0x3) == 0)
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init ar_init(void)
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
731b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	struct ar *ar;
732b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	struct v4l2_device *v4l2_dev;
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar = &ardev;
737b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	v4l2_dev = &ar->v4l2_dev;
738b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	strlcpy(v4l2_dev->name, "arv", sizeof(v4l2_dev->name));
739b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	v4l2_info(v4l2_dev, "Colour AR VGA driver %s\n", VERSION);
740b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil
741b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	ret = v4l2_device_register(NULL, v4l2_dev);
742b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	if (ret < 0) {
743b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
744b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		return ret;
745b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	}
746b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	ret = -EIO;
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if USE_INT
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* allocate a DMA buffer for 1 line.  */
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar->line_buff = kmalloc(MAX_AR_LINE_BYTES, GFP_KERNEL | GFP_DMA);
75188f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	if (ar->line_buff == NULL || !ALIGN4(ar->line_buff)) {
752b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		v4l2_err(v4l2_dev, "buffer allocation failed for DMA.\n");
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -ENOMEM;
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_end;
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* allocate buffers for a frame */
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MAX_AR_HEIGHT; i++) {
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ar->frame[i] = kmalloc(MAX_AR_LINE_BYTES, GFP_KERNEL);
76088f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil		if (ar->frame[i] == NULL || !ALIGN4(ar->frame[i])) {
761b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil			v4l2_err(v4l2_dev, "buffer allocation failed for frame.\n");
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ret = -ENOMEM;
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto out_line_buff;
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
767b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	strlcpy(ar->vdev.name, "Colour AR VGA", sizeof(ar->vdev.name));
768b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	ar->vdev.v4l2_dev = v4l2_dev;
769b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	ar->vdev.fops = &ar_fops;
770b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	ar->vdev.ioctl_ops = &ar_ioctl_ops;
771b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	ar->vdev.release = video_device_release_empty;
772b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	video_set_drvdata(&ar->vdev, ar);
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (vga) {
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ar->width 	= AR_WIDTH_VGA;
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ar->height 	= AR_HEIGHT_VGA;
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ar->size 	= AR_SIZE_VGA;
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ar->frame_bytes = AR_FRAME_BYTES_VGA;
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ar->line_bytes	= AR_LINE_BYTES_VGA;
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (vga_interlace)
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ar->mode = AR_MODE_INTERLACE;
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ar->mode = AR_MODE_NORMAL;
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ar->width 	= AR_WIDTH_QVGA;
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ar->height 	= AR_HEIGHT_QVGA;
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ar->size 	= AR_SIZE_QVGA;
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ar->frame_bytes = AR_FRAME_BYTES_QVGA;
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ar->line_bytes	= AR_LINE_BYTES_QVGA;
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ar->mode	= AR_MODE_INTERLACE;
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7923593cab5d62c4c7abced1076710f9bc2d8847433Ingo Molnar	mutex_init(&ar->lock);
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_waitqueue_head(&ar->wait);
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if USE_INT
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (request_irq(M32R_IRQ_INT3, ar_interrupt, 0, "arv", ar)) {
797b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		v4l2_err("request_irq(%d) failed.\n", M32R_IRQ_INT3);
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -EIO;
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_irq;
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
803b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	if (ar_initialize(ar) != 0) {
804b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		v4l2_err(v4l2_dev, "M64278 not found.\n");
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -ENODEV;
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_dev;
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * ok, we can initialize h/w according to parameters,
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * so register video device as a frame grabber type.
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * device is named "video[0-64]".
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * video_register_device() initializes h/w using ar_initialize().
814d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab	 */
815b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	if (video_register_device(&ar->vdev, VFL_TYPE_GRABBER, video_nr) != 0) {
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* return -1, -ENFILE(full) or others */
817b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		v4l2_err(v4l2_dev, "register video (Colour AR) failed.\n");
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -ENODEV;
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_dev;
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
822b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	v4l2_info(v4l2_dev, "%s: Found M64278 VGA (IRQ %d, Freq %dMHz).\n",
823b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil		video_device_node_name(&ar->vdev), M32R_IRQ_INT3, freq);
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_dev:
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if USE_INT
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	free_irq(M32R_IRQ_INT3, ar);
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_irq:
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
8332ea7533060e361810c21b2f5ee02151c4dfb85d8Jesper Juhl	for (i = 0; i < MAX_AR_HEIGHT; i++)
8342ea7533060e361810c21b2f5ee02151c4dfb85d8Jesper Juhl		kfree(ar->frame[i]);
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_line_buff:
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if USE_INT
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(ar->line_buff);
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_end:
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
842b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	v4l2_device_unregister(&ar->v4l2_dev);
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init ar_init_module(void)
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	freq = (boot_cpu_data.bus_clock / 1000000);
85088f4423454a23375f07bb4ff3a80d209930560d0Hans Verkuil	printk(KERN_INFO "arv: Bus clock %d\n", freq);
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (freq != 50 && freq != 75)
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		freq = DEFAULT_FREQ;
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ar_init();
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit ar_cleanup_module(void)
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
858b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	struct ar *ar;
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ar = &ardev;
862b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	video_unregister_device(&ar->vdev);
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if USE_INT
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	free_irq(M32R_IRQ_INT3, ar);
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
8662ea7533060e361810c21b2f5ee02151c4dfb85d8Jesper Juhl	for (i = 0; i < MAX_AR_HEIGHT; i++)
8672ea7533060e361810c21b2f5ee02151c4dfb85d8Jesper Juhl		kfree(ar->frame[i]);
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if USE_INT
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(ar->line_buff);
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
871b8e56b6f6e5b6c55d4d375cc9ebd79151b44db58Hans Verkuil	v4l2_device_unregister(&ar->v4l2_dev);
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(ar_init_module);
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(ar_cleanup_module);
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Takeo Takahashi <takahashi.takeo@renesas.com>");
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Colour AR M64278(VGA) for Video4Linux");
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
8801990d50b58bef127a647005fdcada6d07081d3efMauro Carvalho ChehabMODULE_VERSION(VERSION);
881