⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 saa7110.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * saa7110 - Philips SAA7110(A) video decoder driver * * Copyright (C) 1998 Pauline Middelink <middelin@polyware.nl> * * Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net> * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx> *    - some corrections for Pinnacle Systems Inc. DC10plus card. * * 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/init.h>#include <linux/types.h>#include <linux/delay.h>#include <linux/slab.h>#include <linux/wait.h>#include <asm/io.h>#include <asm/uaccess.h>MODULE_DESCRIPTION("Philips SAA7110 video decoder driver");MODULE_AUTHOR("Pauline Middelink");MODULE_LICENSE("GPL");#include <linux/i2c.h>#include <linux/i2c-dev.h>#define I2C_NAME(s) (s)->name#include <linux/videodev.h>#include <linux/video_decoder.h>static int debug = 0;module_param(debug, int, 0);MODULE_PARM_DESC(debug, "Debug level (0-1)");#define dprintk(num, format, args...) \	do { \		if (debug >= num) \			printk(format, ##args); \	} while (0)#define SAA7110_MAX_INPUT	9	/* 6 CVBS, 3 SVHS */#define SAA7110_MAX_OUTPUT	0	/* its a decoder only */#define	I2C_SAA7110		0x9C	/* or 0x9E */#define SAA7110_NR_REG		0x35struct saa7110 {	u8 reg[SAA7110_NR_REG];	int norm;	int input;	int enable;	int bright;	int contrast;	int hue;	int sat;	wait_queue_head_t wq;};/* ----------------------------------------------------------------------- *//* I2C support functions						   *//* ----------------------------------------------------------------------- */static intsaa7110_write (struct i2c_client *client,	       u8                 reg,	       u8                 value){	struct saa7110 *decoder = i2c_get_clientdata(client);	decoder->reg[reg] = value;	return i2c_smbus_write_byte_data(client, reg, value);}static intsaa7110_write_block (struct i2c_client *client,		     const u8          *data,		     unsigned int       len){	int ret = -1;	u8 reg = *data;		/* first register to write to */	/* Sanity check */	if (reg + (len - 1) > SAA7110_NR_REG)		return ret;	/* the saa7110 has an autoincrement function, use it if	 * the adapter understands raw I2C */	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {		struct saa7110 *decoder = i2c_get_clientdata(client);		struct i2c_msg msg;		msg.len = len;		msg.buf = (char *) data;		msg.addr = client->addr;		msg.flags = 0;		ret = i2c_transfer(client->adapter, &msg, 1);		/* Cache the written data */		memcpy(decoder->reg + reg, data + 1, len - 1);	} else {		for (++data, --len; len; len--) {			if ((ret = saa7110_write(client, reg++,						 *data++)) < 0)				break;		}	}	return ret;}static inline intsaa7110_read (struct i2c_client *client){	return i2c_smbus_read_byte(client);}/* ----------------------------------------------------------------------- *//* SAA7110 functions							   *//* ----------------------------------------------------------------------- */#define FRESP_06H_COMPST 0x03	//0x13#define FRESP_06H_SVIDEO 0x83	//0xC0static intsaa7110_selmux (struct i2c_client *client,	        int                chan){	static const unsigned char modes[9][8] = {		/* mode 0 */		{FRESP_06H_COMPST, 0xD9, 0x17, 0x40, 0x03,			      0x44, 0x75, 0x16},		/* mode 1 */		{FRESP_06H_COMPST, 0xD8, 0x17, 0x40, 0x03,			      0x44, 0x75, 0x16},		/* mode 2 */		{FRESP_06H_COMPST, 0xBA, 0x07, 0x91, 0x03,			      0x60, 0xB5, 0x05},		/* mode 3 */		{FRESP_06H_COMPST, 0xB8, 0x07, 0x91, 0x03,			      0x60, 0xB5, 0x05},		/* mode 4 */		{FRESP_06H_COMPST, 0x7C, 0x07, 0xD2, 0x83,			      0x60, 0xB5, 0x03},		/* mode 5 */		{FRESP_06H_COMPST, 0x78, 0x07, 0xD2, 0x83,			      0x60, 0xB5, 0x03},		/* mode 6 */		{FRESP_06H_SVIDEO, 0x59, 0x17, 0x42, 0xA3,			      0x44, 0x75, 0x12},		/* mode 7 */		{FRESP_06H_SVIDEO, 0x9A, 0x17, 0xB1, 0x13,			      0x60, 0xB5, 0x14},		/* mode 8 */		{FRESP_06H_SVIDEO, 0x3C, 0x27, 0xC1, 0x23,			      0x44, 0x75, 0x21}	};	struct saa7110 *decoder = i2c_get_clientdata(client);	const unsigned char *ptr = modes[chan];	saa7110_write(client, 0x06, ptr[0]);	/* Luminance control    */	saa7110_write(client, 0x20, ptr[1]);	/* Analog Control #1    */	saa7110_write(client, 0x21, ptr[2]);	/* Analog Control #2    */	saa7110_write(client, 0x22, ptr[3]);	/* Mixer Control #1     */	saa7110_write(client, 0x2C, ptr[4]);	/* Mixer Control #2     */	saa7110_write(client, 0x30, ptr[5]);	/* ADCs gain control    */	saa7110_write(client, 0x31, ptr[6]);	/* Mixer Control #3     */	saa7110_write(client, 0x21, ptr[7]);	/* Analog Control #2    */	decoder->input = chan;	return 0;}static const unsigned char initseq[1 + SAA7110_NR_REG] = {	0, 0x4C, 0x3C, 0x0D, 0xEF, 0xBD, 0xF2, 0x03, 0x00,	/* 0x08 */ 0xF8, 0xF8, 0x60, 0x60, 0x00, 0x86, 0x18, 0x90,	/* 0x10 */ 0x00, 0x59, 0x40, 0x46, 0x42, 0x1A, 0xFF, 0xDA,	/* 0x18 */ 0xF2, 0x8B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 0x20 */ 0xD9, 0x16, 0x40, 0x41, 0x80, 0x41, 0x80, 0x4F,	/* 0x28 */ 0xFE, 0x01, 0xCF, 0x0F, 0x03, 0x01, 0x03, 0x0C,	/* 0x30 */ 0x44, 0x71, 0x02, 0x8C, 0x02};static intdetermine_norm (struct i2c_client *client){	DEFINE_WAIT(wait);	struct saa7110 *decoder = i2c_get_clientdata(client);	int status;	/* mode changed, start automatic detection */	saa7110_write_block(client, initseq, sizeof(initseq));	saa7110_selmux(client, decoder->input);	prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE);	schedule_timeout(HZ/4);	finish_wait(&decoder->wq, &wait);	status = saa7110_read(client);	if (status & 0x40) {		dprintk(1, KERN_INFO "%s: status=0x%02x (no signal)\n",			I2C_NAME(client), status);		return decoder->norm;	// no change	}	if ((status & 3) == 0) {		saa7110_write(client, 0x06, 0x83);		if (status & 0x20) {			dprintk(1,				KERN_INFO				"%s: status=0x%02x (NTSC/no color)\n",				I2C_NAME(client), status);			//saa7110_write(client,0x2E,0x81);			return VIDEO_MODE_NTSC;		}		dprintk(1, KERN_INFO "%s: status=0x%02x (PAL/no color)\n",			I2C_NAME(client), status);		//saa7110_write(client,0x2E,0x9A);		return VIDEO_MODE_PAL;	}	//saa7110_write(client,0x06,0x03);	if (status & 0x20) {	/* 60Hz */		dprintk(1, KERN_INFO "%s: status=0x%02x (NTSC)\n",			I2C_NAME(client), status);		saa7110_write(client, 0x0D, 0x86);		saa7110_write(client, 0x0F, 0x50);		saa7110_write(client, 0x11, 0x2C);		//saa7110_write(client,0x2E,0x81);		return VIDEO_MODE_NTSC;	}	/* 50Hz -> PAL/SECAM */	saa7110_write(client, 0x0D, 0x86);	saa7110_write(client, 0x0F, 0x10);	saa7110_write(client, 0x11, 0x59);	//saa7110_write(client,0x2E,0x9A);	prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE);	schedule_timeout(HZ/4);	finish_wait(&decoder->wq, &wait);	status = saa7110_read(client);	if ((status & 0x03) == 0x01) {		dprintk(1, KERN_INFO "%s: status=0x%02x (SECAM)\n",			I2C_NAME(client), status);		saa7110_write(client, 0x0D, 0x87);		return VIDEO_MODE_SECAM;	}	dprintk(1, KERN_INFO "%s: status=0x%02x (PAL)\n", I2C_NAME(client),		status);	return VIDEO_MODE_PAL;}static intsaa7110_command (struct i2c_client *client,		 unsigned int       cmd,		 void              *arg){	struct saa7110 *decoder = i2c_get_clientdata(client);	int v;	switch (cmd) {	case 0:		//saa7110_write_block(client, initseq, sizeof(initseq));		break;	case DECODER_GET_CAPABILITIES:	{		struct video_decoder_capability *dc = arg;		dc->flags =		    VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC |		    VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO;		dc->inputs = SAA7110_MAX_INPUT;		dc->outputs = SAA7110_MAX_OUTPUT;	}		break;	case DECODER_GET_STATUS:	{		int status;		int res = 0;		status = saa7110_read(client);		dprintk(1, KERN_INFO "%s: status=0x%02x norm=%d\n",			I2C_NAME(client), status, decoder->norm);		if (!(status & 0x40))			res |= DECODER_STATUS_GOOD;		if (status & 0x03)			res |= DECODER_STATUS_COLOR;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -