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

📄 mxb.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
/*    mxb - v4l2 driver for the Multimedia eXtension Board        Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de>    Visit http://www.mihu.de/linux/saa7146/mxb/    for further details about this card.        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.*/#define DEBUG_VARIABLE debug#include <media/saa7146_vv.h>#include <media/tuner.h>#include <linux/video_decoder.h>#include "mxb.h"#include "tea6415c.h"#include "tea6420.h"#include "tda9840.h"#define I2C_SAA7111 0x24#define MXB_BOARD_CAN_DO_VBI(dev)   (dev->revision != 0) /* global variable */static int mxb_num = 0;/* initial frequence the tuner will be tuned to.    in verden (lower saxony, germany) 4148 is a   channel called "phoenix" */static int freq = 4148;module_param(freq, int, 0644);MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup");static int debug = 0;module_param(debug, int, 0644);MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");#define MXB_INPUTS 4enum { TUNER, AUX1, AUX3, AUX3_YC };static struct v4l2_input mxb_inputs[MXB_INPUTS] = {	{ TUNER,	"Tuner",		V4L2_INPUT_TYPE_TUNER,	1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, 	{ AUX1,		"AUX1",			V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },	{ AUX3,		"AUX3 Composite",	V4L2_INPUT_TYPE_CAMERA,	4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },	{ AUX3_YC,	"AUX3 S-Video",		V4L2_INPUT_TYPE_CAMERA,	4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },};/* this array holds the information, which port of the saa7146 each   input actually uses. the mxb uses port 0 for every input */static struct {	int hps_source;	int hps_sync;} input_port_selection[MXB_INPUTS] = { 		{ SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },	{ SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },	{ SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },	{ SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },};/* this array holds the information of the audio source (mxb_audios),   which has to be switched corresponding to the video source (mxb_channels) */static int video_audio_connect[MXB_INPUTS] =	{ 0, 1, 3, 3 };/* these are the necessary input-output-pins for bringing one audio source(see above) to the CD-output */static struct tea6420_multiplex TEA6420_cd[MXB_AUDIOS+1][2] =		{ 		{{1,1,0},{1,1,0}},	/* Tuner */		{{5,1,0},{6,1,0}},	/* AUX 1 */		{{4,1,0},{6,1,0}},	/* AUX 2 */		{{3,1,0},{6,1,0}},	/* AUX 3 */		{{1,1,0},{3,1,0}},	/* Radio */		{{1,1,0},{2,1,0}},	/* CD-Rom */		{{6,1,0},{6,1,0}}	/* Mute */		};/* these are the necessary input-output-pins for bringing one audio source(see above) to the line-output */static struct tea6420_multiplex TEA6420_line[MXB_AUDIOS+1][2] =		{		{{2,3,0},{1,2,0}},		{{5,3,0},{6,2,0}},		{{4,3,0},{6,2,0}},		{{3,3,0},{6,2,0}},		{{2,3,0},{3,2,0}},		{{2,3,0},{2,2,0}},		{{6,3,0},{6,2,0}}	/* Mute */		};#define MAXCONTROLS	1static struct v4l2_queryctrl mxb_controls[] = {	{ V4L2_CID_AUDIO_MUTE, V4L2_CTRL_TYPE_BOOLEAN, "Mute", 0, 1, 1, 0, 0 },};static struct saa7146_extension_ioctls ioctls[] = {	{ VIDIOC_ENUMINPUT, 	SAA7146_EXCLUSIVE },	{ VIDIOC_G_INPUT,	SAA7146_EXCLUSIVE },	{ VIDIOC_S_INPUT,	SAA7146_EXCLUSIVE },	{ VIDIOC_QUERYCTRL, 	SAA7146_BEFORE },	{ VIDIOC_G_CTRL,	SAA7146_BEFORE },	{ VIDIOC_S_CTRL,	SAA7146_BEFORE },	{ VIDIOC_G_TUNER, 	SAA7146_EXCLUSIVE },	{ VIDIOC_S_TUNER, 	SAA7146_EXCLUSIVE },	{ VIDIOC_G_FREQUENCY,	SAA7146_EXCLUSIVE },	{ VIDIOC_S_FREQUENCY, 	SAA7146_EXCLUSIVE },	{ VIDIOC_G_AUDIO, 	SAA7146_EXCLUSIVE },	{ VIDIOC_S_AUDIO, 	SAA7146_EXCLUSIVE },	{ MXB_S_AUDIO_CD, 	SAA7146_EXCLUSIVE },	/* custom control */		{ MXB_S_AUDIO_LINE, 	SAA7146_EXCLUSIVE },	/* custom control */		{ 0,			0 }};struct mxb{	struct video_device	*video_dev;	struct video_device	*vbi_dev;	struct i2c_adapter	i2c_adapter;		struct i2c_client*	saa7111a;	struct i2c_client*	tda9840;	struct i2c_client*	tea6415c;	struct i2c_client*	tuner;	struct i2c_client*	tea6420_1;	struct i2c_client*	tea6420_2;	int	cur_mode;	/* current audio mode (mono, stereo, ...) */	int	cur_input;	/* current input */	int	cur_mute;	/* current mute status */	struct v4l2_frequency	cur_freq;	/* current frequency the tuner is tuned to */};static struct saa7146_extension extension;static int mxb_probe(struct saa7146_dev* dev){	struct mxb* mxb = NULL;	struct i2c_client *client;	struct list_head *item;	int result;	if ((result = request_module("saa7111")) < 0) {		printk("mxb: saa7111 i2c module not available.\n");		return -ENODEV;	}	if ((result = request_module("tuner")) < 0) {		printk("mxb: tuner i2c module not available.\n");		return -ENODEV;	}	if ((result = request_module("tea6420")) < 0) {		printk("mxb: tea6420 i2c module not available.\n");		return -ENODEV;	}	if ((result = request_module("tea6415c")) < 0) {		printk("mxb: tea6415c i2c module not available.\n");		return -ENODEV;	}	if ((result = request_module("tda9840")) < 0) {		printk("mxb: tda9840 i2c module not available.\n");		return -ENODEV;	}	mxb = (struct mxb*)kmalloc(sizeof(struct mxb), GFP_KERNEL);	if( NULL == mxb ) {		DEB_D(("not enough kernel memory.\n"));		return -ENOMEM;	}	memset(mxb, 0x0, sizeof(struct mxb));		mxb->i2c_adapter = (struct i2c_adapter) {		.class = I2C_CLASS_TV_ANALOG,		.name = "mxb",	};	saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);	if(i2c_add_adapter(&mxb->i2c_adapter) < 0) {		DEB_S(("cannot register i2c-device. skipping.\n"));		kfree(mxb);		return -EFAULT;	}	/* loop through all i2c-devices on the bus and look who is there */	list_for_each(item,&mxb->i2c_adapter.clients) {		client = list_entry(item, struct i2c_client, list);		if( I2C_TEA6420_1 == client->addr )			mxb->tea6420_1 = client;		if( I2C_TEA6420_2 == client->addr ) 			mxb->tea6420_2 = client;		if( I2C_TEA6415C_2 == client->addr ) 			mxb->tea6415c = client;		if( I2C_TDA9840 == client->addr ) 			mxb->tda9840 = client;		if( I2C_SAA7111 == client->addr )			mxb->saa7111a = client;		if( 0x60 == client->addr ) 			mxb->tuner = client;	}	/* check if all devices are present */	if(    0 == mxb->tea6420_1	|| 0 == mxb->tea6420_2	|| 0 == mxb->tea6415c	    || 0 == mxb->tda9840	|| 0 == mxb->saa7111a	|| 0 == mxb->tuner ) {		printk("mxb: did not find all i2c devices. aborting\n");		i2c_del_adapter(&mxb->i2c_adapter);		kfree(mxb);		return -ENODEV;	}	/* all devices are present, probe was successful */		/* we store the pointer in our private data field */	dev->ext_priv = mxb;	return 0;}/* some init data for the saa7740, the so-called 'sound arena module'.    there are no specs available, so we simply use some init values */static struct {	int	length;	char	data[9];} mxb_saa7740_init[] = {	{ 3, { 0x80, 0x00, 0x00 } },{ 3, { 0x80, 0x89, 0x00 } },	{ 3, { 0x80, 0xb0, 0x0a } },{ 3, { 0x00, 0x00, 0x00 } },	{ 3, { 0x49, 0x00, 0x00 } },{ 3, { 0x4a, 0x00, 0x00 } },	{ 3, { 0x4b, 0x00, 0x00 } },{ 3, { 0x4c, 0x00, 0x00 } },	{ 3, { 0x4d, 0x00, 0x00 } },{ 3, { 0x4e, 0x00, 0x00 } },	{ 3, { 0x4f, 0x00, 0x00 } },{ 3, { 0x50, 0x00, 0x00 } },	{ 3, { 0x51, 0x00, 0x00 } },{ 3, { 0x52, 0x00, 0x00 } },	{ 3, { 0x53, 0x00, 0x00 } },{ 3, { 0x54, 0x00, 0x00 } },	{ 3, { 0x55, 0x00, 0x00 } },{ 3, { 0x56, 0x00, 0x00 } },	{ 3, { 0x57, 0x00, 0x00 } },{ 3, { 0x58, 0x00, 0x00 } },	{ 3, { 0x59, 0x00, 0x00 } },{ 3, { 0x5a, 0x00, 0x00 } },	{ 3, { 0x5b, 0x00, 0x00 } },{ 3, { 0x5c, 0x00, 0x00 } },	{ 3, { 0x5d, 0x00, 0x00 } },{ 3, { 0x5e, 0x00, 0x00 } },	{ 3, { 0x5f, 0x00, 0x00 } },{ 3, { 0x60, 0x00, 0x00 } },	{ 3, { 0x61, 0x00, 0x00 } },{ 3, { 0x62, 0x00, 0x00 } },	{ 3, { 0x63, 0x00, 0x00 } },{ 3, { 0x64, 0x00, 0x00 } },	{ 3, { 0x65, 0x00, 0x00 } },{ 3, { 0x66, 0x00, 0x00 } },	{ 3, { 0x67, 0x00, 0x00 } },{ 3, { 0x68, 0x00, 0x00 } },	{ 3, { 0x69, 0x00, 0x00 } },{ 3, { 0x6a, 0x00, 0x00 } },	{ 3, { 0x6b, 0x00, 0x00 } },{ 3, { 0x6c, 0x00, 0x00 } },	{ 3, { 0x6d, 0x00, 0x00 } },{ 3, { 0x6e, 0x00, 0x00 } },	{ 3, { 0x6f, 0x00, 0x00 } },{ 3, { 0x70, 0x00, 0x00 } },	{ 3, { 0x71, 0x00, 0x00 } },{ 3, { 0x72, 0x00, 0x00 } },	{ 3, { 0x73, 0x00, 0x00 } },{ 3, { 0x74, 0x00, 0x00 } },	{ 3, { 0x75, 0x00, 0x00 } },{ 3, { 0x76, 0x00, 0x00 } },	{ 3, { 0x77, 0x00, 0x00 } },{ 3, { 0x41, 0x00, 0x42 } },	{ 3, { 0x42, 0x10, 0x42 } },{ 3, { 0x43, 0x20, 0x42 } },	{ 3, { 0x44, 0x30, 0x42 } },{ 3, { 0x45, 0x00, 0x01 } },	{ 3, { 0x46, 0x00, 0x01 } },{ 3, { 0x47, 0x00, 0x01 } },	{ 3, { 0x48, 0x00, 0x01 } },	{ 9, { 0x01, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },	{ 9, { 0x21, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },	{ 9, { 0x09, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },	{ 9, { 0x29, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },	{ 9, { 0x11, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },	{ 9, { 0x31, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },	{ 9, { 0x19, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },	{ 9, { 0x39, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },	{ 9, { 0x05, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },	{ 9, { 0x25, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },	{ 9, { 0x0d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },	{ 9, { 0x2d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },	{ 9, { 0x15, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },	{ 9, { 0x35, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },	{ 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },	{ 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },	{ 3, { 0x80, 0xb3, 0x0a } },	{-1, { 0} }};static const unsigned char mxb_saa7111_init[] = {	0x00, 0x00,	  /* 00 - ID byte */	0x01, 0x00,	  /* 01 - reserved */	/*front end */	0x02, 0xd8,	  /* 02 - FUSE=x, GUDL=x, MODE=x */	0x03, 0x23,	  /* 03 - HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */	0x04, 0x00,	  /* 04 - GAI1=256 */	0x05, 0x00,	  /* 05 - GAI2=256 */	/* decoder */	0x06, 0xf0,	  /* 06 - HSB at  xx(50Hz) /  xx(60Hz) pixels after end of last line */	0x07, 0x30,	  /* 07 - HSS at  xx(50Hz) /  xx(60Hz) pixels after end of last line */	0x08, 0xa8,	  /* 08 - AUFD=x, FSEL=x, EXFIL=x, VTRC=x, HPLL=x, VNOI=x */	0x09, 0x02,	  /* 09 - BYPS=x, PREF=x, BPSS=x, VBLB=x, UPTCV=x, APER=x */	0x0a, 0x80,	  /* 0a - BRIG=128 */	0x0b, 0x47,	  /* 0b - CONT=1.109 */	0x0c, 0x40,	  /* 0c - SATN=1.0 */	0x0d, 0x00,	  /* 0d - HUE=0 */	0x0e, 0x01,	  /* 0e - CDTO=0, CSTD=0, DCCF=0, FCTC=0, CHBW=1 */	0x0f, 0x00,	  /* 0f - reserved */	0x10, 0xd0,	  /* 10 - OFTS=x, HDEL=x, VRLN=x, YDEL=x */	0x11, 0x8c,	  /* 11 - GPSW=x, CM99=x, FECO=x, COMPO=x, OEYC=1, OEHV=1, VIPB=0, COLO=0 */	0x12, 0x80,	  /* 12 - xx output control 2 */	0x13, 0x30,	  /* 13 - xx output control 3 */	0x14, 0x00,	  /* 14 - reserved */	0x15, 0x15,	  /* 15 - VBI */	0x16, 0x04,	  /* 16 - VBI */	0x17, 0x00,	  /* 17 - VBI */};/* bring hardware to a sane state. this has to be done, just in case someone   wants to capture from this device before it has been properly initialized.   the capture engine would badly fail, because no valid signal arrives on the   saa7146, thus leading to timeouts and stuff. */static int mxb_init_done(struct saa7146_dev* dev){	struct mxb* mxb = (struct mxb*)dev->ext_priv;	struct video_decoder_init init;	struct i2c_msg msg;	struct tuner_setup tun_setup;	int i = 0, err = 0;	struct	tea6415c_multiplex vm;		/* select video mode in saa7111a */	i = VIDEO_MODE_PAL;	/* fixme: currently pointless: gets overwritten by configuration below */	mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_NORM, &i);	/* write configuration to saa7111a */	init.data = mxb_saa7111_init;	init.len = sizeof(mxb_saa7111_init);	mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_INIT, &init);

⌨️ 快捷键说明

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