/*
* saa7114 - Philips SAA7114H video decoder driver version 0.0.1
*
* Copyright (C) 2002 Maxim Yevtyushkin <max@linuxmedialabs.com>
*
* Based on saa7111 driver by Dave Perks
*
* Copyright (C) 1998 Dave Perks <dperks@ibm.net>
*
* Slight changes for video timing and attachment output by
* Wolfgang Scherr <scherr@net4you.net>
*
* Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
* - moved over to linux>=2.4.x i2c protocol (1/1/2003)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/ioctl.h>
#include <asm/uaccess.h>
#include <linux/i2c.h>
#include <linux/i2c-id.h>
#include <linux/videodev.h>
#include <linux/video_decoder.h>
#include <media/v4l2-common.h>
#include <media/v4l2-i2c-drv-legacy.h>
MODULE_DESCRIPTION("Philips SAA7114H video decoder driver");
MODULE_AUTHOR("Maxim Yevtyushkin");
MODULE_LICENSE("GPL");
static int debug;
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
/* ----------------------------------------------------------------------- */
struct saa7114 {
unsigned char reg[0xf0 * 2];
int norm;
int input;
int enable;
int bright;
int contrast;
int hue;
int sat;
int playback;
};
#define I2C_DELAY 10
//#define SAA_7114_NTSC_HSYNC_START (-3)
//#define SAA_7114_NTSC_HSYNC_STOP (-18)
#define SAA_7114_NTSC_HSYNC_START (-17)
#define SAA_7114_NTSC_HSYNC_STOP (-32)
//#define SAA_7114_NTSC_HOFFSET (5)
#define SAA_7114_NTSC_HOFFSET (6)
#define SAA_7114_NTSC_VOFFSET (10)
#define SAA_7114_NTSC_WIDTH (720)
#define SAA_7114_NTSC_HEIGHT (250)
#define SAA_7114_SECAM_HSYNC_START (-17)
#define SAA_7114_SECAM_HSYNC_STOP (-32)
#define SAA_7114_SECAM_HOFFSET (2)
#define SAA_7114_SECAM_VOFFSET (10)
#define SAA_7114_SECAM_WIDTH (720)
#define SAA_7114_SECAM_HEIGHT (300)
#define SAA_7114_PAL_HSYNC_START (-17)
#define SAA_7114_PAL_HSYNC_STOP (-32)
#define SAA_7114_PAL_HOFFSET (2)
#define SAA_7114_PAL_VOFFSET (10)
#define SAA_7114_PAL_WIDTH (720)
#define SAA_7114_PAL_HEIGHT (300)
#define SAA_7114_VERTICAL_CHROMA_OFFSET 0 //0x50504040
#define SAA_7114_VERTICAL_LUMA_OFFSET 0
#define REG_ADDR(x) (((x) << 1) + 1)
#define LOBYTE(x) ((unsigned char)((x) & 0xff))
#define HIBYTE(x) ((unsigned char)(((x) >> 8) & 0xff))
#define LOWORD(x) ((unsigned short int)((x) & 0xffff))
#define HIWORD(x) ((unsigned short int)(((x) >> 16) & 0xffff))
/* ----------------------------------------------------------------------- */
static inline int saa7114_write(struct i2c_client *client, u8 reg, u8 value)
{
return i2c_smbus_write_byte_data(client, reg, value);
}
static int saa7114_write_block(struct i2c_client *client, const u8 *data, unsigned int len)
{
int ret = -1;
u8 reg;
/* the saa7114 has an autoincrement function, use it if
* the adapter understands raw I2C */
if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
/* do raw I2C, not smbus compatible */
u8 block_data[32];
int block_len;
while (len >= 2) {
block_len = 0;
block_data[block_len++] = reg = data[0];
do {
block_data[block_len++] = data[1];
reg++;
len -= 2;
data += 2;
} while (len >= 2 && data[0] == reg && block_len < 32);
ret = i2c_master_send(client, block_data, block_len);
if (ret < 0)
break;
}
} else {
/* do some slow I2C emulation kind of thing */
while (len >= 2) {
reg = *data++;
ret = saa7114_write(client, reg, *data++);
if (ret < 0)
break;
len -= 2;
}
}
return ret;
}
static inline int saa7114_read(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_byte_data(client, reg);
}
/* ----------------------------------------------------------------------- */
// initially set NTSC, composite
static const unsigned char init[] = {
0x00, 0x00, /* 00 - ID byte , chip version,
* read only */
0x01, 0x08, /* 01 - X,X,X,X, IDEL3 to IDEL0 -
* horizontal increment delay,
* recommended position */
0x02, 0x00, /* 02 - FUSE=3, GUDL=2, MODE=0 ;
* input control */
0x03, 0x10, /* 03 - HLNRS=0, VBSL=1, WPOFF=0,
* HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */
0x04, 0x90, /* 04 - GAI1=256 */
0x05, 0x90, /* 05 - GAI2=256 */
0x06, SAA_7114_NTSC_HSYNC_START, /* 06 - HSB: hsync start,
* depends on the video standard */
0x07, SAA_7114_NTSC_HSYNC_STOP, /* 07 - HSS: hsync stop, depends
*on the video standard */
0x08, 0xb8, /* 08 - AUFD=1, FSEL=1, EXFIL=0, VTRC=1,
* HPLL: free running in playback, locked
* in capture, VNOI=0 */
0x09, 0x80,