/*
* Media Vision Pro Movie Studio
* or
* "all you need is an I2C bus some RAM and a prayer"
*
* This draws heavily on code
*
* (c) Wolfgang Koehler, wolf@first.gmd.de, Dec. 1994
* Kiefernring 15
* 14478 Potsdam, Germany
*
* Most of this code is directly derived from his userspace driver.
* His driver works so send any reports to alan@lxorguk.ukuu.org.uk
* unless the userspace driver also doesn't work for you...
*
* Changes:
* 25-11-2009 Hans Verkuil <hverkuil@xs4all.nl>
* - converted to version 2 of the V4L API.
* 08/07/2003 Daniele Bellucci <bellucda@tiscali.it>
* - pms_capture: report back -EFAULT
*/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/version.h>
#include <linux/mutex.h>
#include <linux/uaccess.h>
#include <asm/io.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-device.h>
MODULE_LICENSE("GPL");
#define MOTOROLA 1
#define PHILIPS2 2 /* SAA7191 */
#define PHILIPS1 3
#define MVVMEMORYWIDTH 0x40 /* 512 bytes */
struct i2c_info {
u8 slave;
u8 sub;
u8 data;
u8 hits;
};
struct pms {
struct v4l2_device v4l2_dev;
struct video_device vdev;
int height;
int width;
int depth;
int input;
s32 brightness, saturation, hue, contrast;
struct mutex lock;
int i2c_count;
struct i2c_info i2cinfo[64];
int decoder;
int standard; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */
v4l2_std_id std;
int io;
int data;
void __iomem *mem;
};
static struct pms pms_card;
/*
* I/O ports and Shared Memory
*/
static int io_port = 0x250;
module_param(io_port, int, 0);
static int mem_base = 0xc8000;
module_param(mem_base, int, 0);
static int video_nr = -1;
module_param(video_nr, int, 0);
static inline void mvv_write(struct pms *dev, u8 index, u8 value)
{
outw(index | (value << 8), dev->io);
}
static inline u8 mvv_read(struct pms *dev, u8 index)
{
outb(index, dev->io);
return inb(dev->data);
}
static int pms_i2c_stat(struct pms *dev, u8 slave)
{
int counter = 0;
int i;
outb(0x28, dev->io);
while ((inb(dev->data) & 0x01) == 0)
if (counter++ == 256)
break;
while ((inb(dev->data) & 0x01) != 0)
if (counter++ == 256)
break;
outb(slave, dev->io);
counter = 0;
while ((inb(dev->data) & 0x01) == 0)
if (counter++ == 256)
break;
while ((inb(dev->data) & 0x01) != 0)
if (counter++ == 256)
break;
for (i = 0; i < 12; i++) {
char st = inb(dev->data);
if ((st & 2) != 0)
return -1;
if ((st & 1) == 0)