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

📄 tvaudio.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
MODULE_PARM(pic16c54,"i");static struct CHIPDESC chiplist[] = {	{		name:       "tda9840",		id:         I2C_DRIVERID_TDA9840,		insmodopt:  &tda9840,		addr_lo:    I2C_TDA9840 >> 1,		addr_hi:    I2C_TDA9840 >> 1,		registers:  5,		getmode:    tda9840_getmode,		setmode:    tda9840_setmode,		init:       { 2, { TDA9840_SW, 0x2a } }	},	{		name:       "tda9873h",		id:         I2C_DRIVERID_TDA9873,		checkit:    tda9873_checkit,		insmodopt:  &tda9873,		addr_lo:    I2C_TDA985x_L >> 1,		addr_hi:    I2C_TDA985x_H >> 1,		registers:  3,		getmode:    tda9873_getmode,		setmode:    tda9873_setmode,		checkmode:  tda9873_checkmode,		init:       { 4, { TDA9873_SW, 0xa0, 0x06, 0x03 } }	},	{		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_VR,		rightreg:   TDA9855_VL,		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_VR,		rightreg:   TDA8425_VL,		bassreg:    TDA8425_BA,		treblereg:  TDA8425_TR,		volfunc:    tda8425_shift10,		bassfunc:   tda8425_shift12,		treblefunc: tda8425_shift12,		inputreg:   TDA8425_S1,		inputmap:   { TDA8425_S1_ON, TDA8425_S1_ON, TDA8425_S1_ON },		inputmute:  TDA8425_S1_OFF,	},	{		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},		inputmute:  PIC16C54_MISC_SND_MUTE,	},	{ name: NULL } /* EOF */};/* ---------------------------------------------------------------------- *//* i2c registration                                                       */static int chip_attach(struct i2c_adapter *adap, int addr,		       unsigned short flags, int kind){	struct CHIPSTATE *chip;	struct CHIPDESC  *desc;	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;	chip->c.data = chip;	/* find description for the chip */	dprintk("tvaudio: chip @ 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;	}	dprintk("tvaudio: %s matches:%s%s%s\n",desc->name,		(desc->flags & CHIP_HAS_VOLUME)     ? " volume"      : "",		(desc->flags & CHIP_HAS_BASSTREBLE) ? " bass/treble" : "",		(desc->flags & CHIP_HAS_INPUTSEL)   ? " audiomux"    : "");	/* fill required data structures */	strcpy(chip->c.name,desc->name);	chip->type = desc-chiplist;	chip->shadow.count = desc->registers+1;	/* register */	MOD_INC_USE_COUNT;	i2c_attach_client(&chip->c);	/* initialization  */	chip_cmd(chip,"init",&desc->init);	if (desc->flags & CHIP_HAS_VOLUME) {		chip->left   = desc->leftinit   ? desc->leftinit   : 65536;		chip->right  = desc->rightinit  ? desc->rightinit  : 65536;		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_waitqueue_head(&chip->wq);		kernel_thread(chip_thread,(void *)chip,0);		down(&sem);		chip->notify = NULL;		chip->wake++;		wake_up_interruptible(&chip->wq);	}	return 0;}static int chip_probe(struct i2c_adapter *adap){	if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))		return i2c_probe(adap, &addr_data, chip_attach);	return 0;}static int chip_detach(struct i2c_client *client){	struct CHIPSTATE *chip = client->data;	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);	MOD_DEC_USE_COUNT;	return 0;}/* ---------------------------------------------------------------------- *//* video4linux interface                                                  */static int chip_command(struct i2c_client *client,			unsigned int cmd, void *arg){        __u16 *sarg = arg;	struct CHIPSTATE *chip = client->data;	struct CHIPDESC  *desc = chiplist + chip->type;	dprintk("%s: chip_command 0x%x\n",chip->c.name,cmd);	switch (cmd) {	case AUDC_SET_INPUT:		if (desc->flags & CHIP_HAS_INPUTSEL) {			if (*sarg & 0x80)				chip_write(chip,desc->inputreg,desc->inputmute);			else				chip_write(chip,desc->inputreg,desc->inputmap[*sarg]);		}		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 (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,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)			desc->setmode(chip,va->mode);		break;	}	case VIDIOCSFREQ:	{		if (desc->checkmode) {			desc->setmode(chip,VIDEO_SOUND_MONO);			chip->wake++;			wake_up_interruptible(&chip->wq);			/* the thread will call checkmode() a second later */		}	}	}	return 0;}static struct i2c_driver driver = {        name:            "generic i2c audio driver",        id:              I2C_DRIVERID_TVAUDIO, /* FIXME */        flags:           I2C_DF_NOTIFY,        attach_adapter:  chip_probe,        detach_client:   chip_detach,        command:         chip_command,};static struct i2c_client client_template ={        name:   "(unset)",        driver: &driver,};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;}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 + -