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

📄 tvaudio.c

📁 saa7134-0.2.9.tar.gz 电视卡驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
		.checkit    = tda9874a_checkit,		.initialize = tda9874a_initialize,		.insmodopt  = &tda9874a,		.addr_lo    = I2C_TDA9874 >> 1,		.addr_hi    = I2C_TDA9874 >> 1,		.getmode    = tda9874a_getmode,		.setmode    = tda9874a_setmode,		.checkmode  = generic_checkmode,	},	{		.name       = "tda9850",		.id         = I2C_DRIVERID_TDA9850,		.insmodopt  = &tda9850,		.addr_lo    = I2C_TDA985x_L >> 1,		.addr_hi    = I2C_TDA985x_H >> 1,		.registers  = 11,		.getmode    = tda985x_getmode,		.setmode    = tda985x_setmode,		.init       = { 8, { TDA9850_C4, 0x08, 0x08, TDA985x_STEREO, 0x07, 0x10, 0x10, 0x03 } }	},	{		.name       = "tda9855",		.id         = I2C_DRIVERID_TDA9855,		.insmodopt  = &tda9855,		.addr_lo    = I2C_TDA985x_L >> 1,		.addr_hi    = I2C_TDA985x_H >> 1,		.registers  = 11,		.flags      = CHIP_HAS_VOLUME | CHIP_HAS_BASSTREBLE,		.leftreg    = TDA9855_VL,		.rightreg   = TDA9855_VR,		.bassreg    = TDA9855_BA,		.treblereg  = TDA9855_TR,		.volfunc    = tda9855_volume,		.bassfunc   = tda9855_bass,		.treblefunc = tda9855_treble,		.getmode    = tda985x_getmode,		.setmode    = tda985x_setmode,		.init       = { 12, { 0, 0x6f, 0x6f, 0x0e, 0x07<<1, 0x8<<2,				    TDA9855_MUTE | TDA9855_AVL | TDA9855_LOUD | TDA9855_INT,				    TDA985x_STEREO | TDA9855_LINEAR | TDA9855_TZCM | TDA9855_VZCM,				    0x07, 0x10, 0x10, 0x03 }}	},	{		.name       = "tea6300",		.id         = I2C_DRIVERID_TEA6300,		.insmodopt  = &tea6300,		.addr_lo    = I2C_TEA6300 >> 1,		.addr_hi    = I2C_TEA6300 >> 1,		.registers  = 6,		.flags      = CHIP_HAS_VOLUME | CHIP_HAS_BASSTREBLE | CHIP_HAS_INPUTSEL,		.leftreg    = TEA6300_VR,		.rightreg   = TEA6300_VL,		.bassreg    = TEA6300_BA,		.treblereg  = TEA6300_TR,		.volfunc    = tea6300_shift10,		.bassfunc   = tea6300_shift12,		.treblefunc = tea6300_shift12,		.inputreg   = TEA6300_S,		.inputmap   = { TEA6300_S_SA, TEA6300_S_SB, TEA6300_S_SC },		.inputmute  = TEA6300_S_GMU,	},	{		.name       = "tea6420",		.id         = I2C_DRIVERID_TEA6420,		.insmodopt  = &tea6420,		.addr_lo    = I2C_TEA6420 >> 1,		.addr_hi    = I2C_TEA6420 >> 1,		.registers  = 1,		.flags      = CHIP_HAS_INPUTSEL,		.inputreg   = -1,		.inputmap   = { TEA6420_S_SA, TEA6420_S_SB, TEA6420_S_SC },		.inputmute  = TEA6300_S_GMU,	},	{		.name       = "tda8425",		.id         = I2C_DRIVERID_TDA8425,		.insmodopt  = &tda8425,		.addr_lo    = I2C_TDA8425 >> 1,		.addr_hi    = I2C_TDA8425 >> 1,		.registers  = 9,		.flags      = CHIP_HAS_VOLUME | CHIP_HAS_BASSTREBLE | CHIP_HAS_INPUTSEL,		.leftreg    = TDA8425_VL,		.rightreg   = TDA8425_VR,		.bassreg    = TDA8425_BA,		.treblereg  = TDA8425_TR,		.volfunc    = tda8425_shift10,		.bassfunc   = tda8425_shift12,		.treblefunc = tda8425_shift12,		.inputreg   = TDA8425_S1,		.inputmap   = { TDA8425_S1_CH1, TDA8425_S1_CH1, TDA8425_S1_CH1 },		.inputmute  = TDA8425_S1_OFF,		.setmode    = tda8425_setmode,		.initialize = tda8425_initialize,	},	{		.name       = "pic16c54 (PV951)",		.id         = I2C_DRIVERID_PIC16C54_PV951,		.insmodopt  = &pic16c54,		.addr_lo    = I2C_PIC16C54 >> 1,		.addr_hi    = I2C_PIC16C54>> 1,		.registers  = 2,		.flags      = CHIP_HAS_INPUTSEL,		.inputreg   = PIC16C54_REG_MISC,		.inputmap   = {PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_TUNER,			     PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_LINE,			     PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_LINE,			     PIC16C54_MISC_SND_MUTE,PIC16C54_MISC_SND_MUTE,			     PIC16C54_MISC_SND_NOTMUTE},		.inputmute  = PIC16C54_MISC_SND_MUTE,	},	{		.name       = "ta8874z",		.id         = -1,		//.id         = I2C_DRIVERID_TA8874Z,		.checkit    = ta8874z_checkit,		.insmodopt  = &ta8874z,		.addr_lo    = I2C_TDA9840 >> 1,		.addr_hi    = I2C_TDA9840 >> 1,		.registers  = 2,		.getmode    = ta8874z_getmode,		.setmode    = ta8874z_setmode,		.checkmode  = generic_checkmode,	        .init       = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}},	},	{ .name = NULL } /* EOF */};/* ---------------------------------------------------------------------- *//* i2c registration                                                       */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)static int chip_attach(struct i2c_adapter *adap, int addr, int kind)#elsestatic int chip_attach(struct i2c_adapter *adap, int addr,		       unsigned short flags, int kind)#endif{	struct CHIPSTATE *chip;	struct CHIPDESC  *desc;	int rc;	chip = kmalloc(sizeof(*chip),GFP_KERNEL);	if (!chip)		return -ENOMEM;	memset(chip,0,sizeof(*chip));	memcpy(&chip->c,&client_template,sizeof(struct i2c_client));        chip->c.adapter = adap;        chip->c.addr = addr;	i2c_set_clientdata(&chip->c, chip);	/* find description for the chip */	dprintk("tvaudio: chip found @ i2c-addr=0x%x\n", addr<<1);	for (desc = chiplist; desc->name != NULL; desc++) {		if (0 == *(desc->insmodopt))			continue;		if (addr < desc->addr_lo ||		    addr > desc->addr_hi)			continue;		if (desc->checkit && !desc->checkit(chip))			continue;		break;	}	if (desc->name == NULL) {		dprintk("tvaudio: no matching chip description found\n");		return -EIO;	}	printk("tvaudio: found %s @ 0x%x\n", desc->name, addr<<1);	dprintk("tvaudio: matches:%s%s%s.\n",		(desc->flags & CHIP_HAS_VOLUME)     ? " volume"      : "",		(desc->flags & CHIP_HAS_BASSTREBLE) ? " bass/treble" : "",		(desc->flags & CHIP_HAS_INPUTSEL)   ? " audiomux"    : "");	/* fill required data structures */	strcpy(i2c_clientname(&chip->c),desc->name);	chip->type = desc-chiplist;	chip->shadow.count = desc->registers+1;        chip->prevmode = -1;	/* register */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	MOD_INC_USE_COUNT;#endif	i2c_attach_client(&chip->c);	/* initialization  */	if (desc->initialize != NULL)		desc->initialize(chip);	else		chip_cmd(chip,"init",&desc->init);	if (desc->flags & CHIP_HAS_VOLUME) {		chip->left   = desc->leftinit   ? desc->leftinit   : 65535;		chip->right  = desc->rightinit  ? desc->rightinit  : 65535;		chip_write(chip,desc->leftreg,desc->volfunc(chip->left));		chip_write(chip,desc->rightreg,desc->volfunc(chip->right));	}	if (desc->flags & CHIP_HAS_BASSTREBLE) {		chip->treble = desc->trebleinit ? desc->trebleinit : 32768;		chip->bass   = desc->bassinit   ? desc->bassinit   : 32768;		chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass));		chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble));	}	if (desc->checkmode) {		/* start async thread */		DECLARE_MUTEX_LOCKED(sem);		chip->notify = &sem;		init_timer(&chip->wt);		chip->wt.function = chip_thread_wake;		chip->wt.data     = (unsigned long)chip;		init_waitqueue_head(&chip->wq);		rc = kernel_thread(chip_thread,(void *)chip,0);		if (rc < 0)			printk(KERN_WARNING "%s: kernel_thread() failed\n",			       i2c_clientname(&chip->c));		else			down(&sem);		chip->notify = NULL;		wake_up_interruptible(&chip->wq);	}	return 0;}static int chip_probe(struct i2c_adapter *adap){#ifdef I2C_ADAP_CLASS_TV_ANALOG	if (adap->class & I2C_ADAP_CLASS_TV_ANALOG)		return i2c_probe(adap, &addr_data, chip_attach);#else	switch (adap->id) {	case I2C_ALGO_BIT | I2C_HW_B_BT848:	case I2C_ALGO_BIT | I2C_HW_B_RIVA:	case I2C_ALGO_SAA7134:		return i2c_probe(adap, &addr_data, chip_attach);	}#endif	return 0;}static int chip_detach(struct i2c_client *client){	struct CHIPSTATE *chip = i2c_get_clientdata(client);	del_timer(&chip->wt);	if (NULL != chip->thread) {		/* shutdown async thread */		DECLARE_MUTEX_LOCKED(sem);		chip->notify = &sem;		chip->done = 1;		wake_up_interruptible(&chip->wq);		down(&sem);		chip->notify = NULL;	}		i2c_detach_client(&chip->c);	kfree(chip);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	MOD_DEC_USE_COUNT;#endif	return 0;}/* ---------------------------------------------------------------------- *//* video4linux interface                                                  */static int chip_command(struct i2c_client *client,			unsigned int cmd, void *arg){        __u16 *sarg = arg;	struct CHIPSTATE *chip = i2c_get_clientdata(client);	struct CHIPDESC  *desc = chiplist + chip->type;	dprintk("%s: chip_command 0x%x\n",i2c_clientname(&chip->c),cmd);	switch (cmd) {	case AUDC_SET_INPUT:		if (desc->flags & CHIP_HAS_INPUTSEL) {			if (*sarg & 0x80)				chip_write_masked(chip,desc->inputreg,desc->inputmute,desc->inputmask);			else				chip_write_masked(chip,desc->inputreg,desc->inputmap[*sarg],desc->inputmask);		}		break;	case AUDC_SET_RADIO:		dprintk(KERN_DEBUG "tvaudio: AUDC_SET_RADIO\n");		chip->norm = VIDEO_MODE_RADIO;		chip->watch_stereo = 0;		/* del_timer(&chip->wt); */		break;	/* --- v4l ioctls --- */	/* take care: bttv does userspace copying, we'll get a	   kernel pointer here... */	case VIDIOCGAUDIO:	{		struct video_audio *va = arg;		if (desc->flags & CHIP_HAS_VOLUME) {			va->flags  |= VIDEO_AUDIO_VOLUME;			va->volume  = max(chip->left,chip->right);			va->balance = (32768*min(chip->left,chip->right))/				(va->volume ? va->volume : 1);		}		if (desc->flags & CHIP_HAS_BASSTREBLE) {			va->flags |= VIDEO_AUDIO_BASS | VIDEO_AUDIO_TREBLE;			va->bass   = chip->bass;			va->treble = chip->treble;		}		if (chip->norm != VIDEO_MODE_RADIO) {			if (desc->getmode)				va->mode = desc->getmode(chip);			else				va->mode = VIDEO_SOUND_MONO;		}		break;	}	case VIDIOCSAUDIO:	{		struct video_audio *va = arg;				if (desc->flags & CHIP_HAS_VOLUME) {			chip->left = (min(65536 - va->balance,32768) *				      va->volume) / 32768;			chip->right = (min(va->balance,(__u16)32768) *				       va->volume) / 32768;			chip_write(chip,desc->leftreg,desc->volfunc(chip->left));			chip_write(chip,desc->rightreg,desc->volfunc(chip->right));		}		if (desc->flags & CHIP_HAS_BASSTREBLE) {			chip->bass = va->bass;			chip->treble = va->treble;			chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass));			chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble));		}		if (desc->setmode && va->mode) {			chip->watch_stereo = 0;			/* del_timer(&chip->wt); */			chip->mode = va->mode;			desc->setmode(chip,va->mode);		}		break;	}	case VIDIOCSCHAN:	{		struct video_channel *vc = arg;				dprintk(KERN_DEBUG "tvaudio: VIDIOCSCHAN\n");		chip->norm = vc->norm;		break;	}	case VIDIOCSFREQ:	{	    	chip->mode = 0; /* automatic */		if (desc->checkmode) {			desc->setmode(chip,VIDEO_SOUND_MONO);		    	if (chip->prevmode != VIDEO_SOUND_MONO)		    		chip->prevmode = -1; /* reset previous mode */			mod_timer(&chip->wt, jiffies+2*HZ);			/* the thread will call checkmode() later */		}	}	}	return 0;}static struct i2c_driver driver = {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,54)	.owner           = THIS_MODULE,#endif        .name            = "generic i2c audio driver",        .id              = I2C_DRIVERID_TVAUDIO,        .flags           = I2C_DF_NOTIFY,        .attach_adapter  = chip_probe,        .detach_client   = chip_detach,        .command         = chip_command,};static struct i2c_client client_template ={	I2C_DEVNAME("(unset)"),	.flags      = I2C_CLIENT_ALLOW_USE,        .driver     = &driver,};static int audiochip_init_module(void){	struct CHIPDESC  *desc;	printk(KERN_INFO "tvaudio: TV audio decoder + audio/video mux driver\n");	printk(KERN_INFO "tvaudio: known chips: ");	for (desc = chiplist; desc->name != NULL; desc++)		printk("%s%s", (desc == chiplist) ? "" : ",",desc->name);	printk("\n");	i2c_add_driver(&driver);	return 0;}static void audiochip_cleanup_module(void){	i2c_del_driver(&driver);}module_init(audiochip_init_module);module_exit(audiochip_cleanup_module);/* * Local variables: * c-basic-offset: 8 * End: */

⌨️ 快捷键说明

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