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

📄 tvaudio.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 3 页
字号:
/* ---------------------------------------------------------------------- *//* audio chip descriptions - defines+functions for tda8425                */#define TDA8425_VL         0x00  /* volume left */#define TDA8425_VR         0x01  /* volume right */#define TDA8425_BA         0x02  /* bass */#define TDA8425_TR         0x03  /* treble */#define TDA8425_S1         0x08  /* switch functions */                                 /* values for those registers: */#define TDA8425_S1_OFF     0xEE  /* audio off (mute on) */#define TDA8425_S1_ON      0xCE  /* audio on (mute off) - "linear stereo" mode */int tda8425_shift10(int val) { return val >> 10 | 0xc0; }int tda8425_shift12(int val) { return val >> 12 | 0xf0; }/* ---------------------------------------------------------------------- *//* audio chip descriptions - defines+functions for pic16c54 (PV951)       *//* the registers of 16C54, I2C sub address. */#define PIC16C54_REG_KEY_CODE     0x01	       /* Not use. */#define PIC16C54_REG_MISC         0x02/* bit definition of the RESET register, I2C data. */#define PIC16C54_MISC_RESET_REMOTE_CTL 0x01 /* bit 0, Reset to receive the key */                                            /*        code of remote controller */#define PIC16C54_MISC_MTS_MAIN         0x02 /* bit 1 */#define PIC16C54_MISC_MTS_SAP          0x04 /* bit 2 */#define PIC16C54_MISC_MTS_BOTH         0x08 /* bit 3 */#define PIC16C54_MISC_SND_MUTE         0x10 /* bit 4, Mute Audio(Line-in and Tuner) */#define PIC16C54_MISC_SND_NOTMUTE      0x20 /* bit 5 */#define PIC16C54_MISC_SWITCH_TUNER     0x40 /* bit 6	, Switch to Line-in */#define PIC16C54_MISC_SWITCH_LINE      0x80 /* bit 7	, Switch to Tuner *//* ---------------------------------------------------------------------- *//* audio chip descriptions - struct CHIPDESC                              *//* insmod options to enable/disable individual audio chips */int tda8425  = 1;int tda9840  = 1;int tda9850  = 1;int tda9855  = 1;int tda9873  = 1;int tda9874a = 1;int tea6300  = 0;int tea6420  = 1;int pic16c54 = 1;MODULE_PARM(tda8425,"i");MODULE_PARM(tda9840,"i");MODULE_PARM(tda9850,"i");MODULE_PARM(tda9855,"i");MODULE_PARM(tda9873,"i");MODULE_PARM(tda9874a,"i");MODULE_PARM(tea6300,"i");MODULE_PARM(tea6420,"i");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,		checkmode:  generic_checkmode,	        init:       { 2, { TDA9840_TEST, TDA9840_TEST_INT1SN				/* ,TDA9840_SW, TDA9840_MONO */} }	},	{		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,		flags:      CHIP_HAS_INPUTSEL,		getmode:    tda9873_getmode,		setmode:    tda9873_setmode,		checkmode:  generic_checkmode,		init:       { 4, { TDA9873_SW, 0xa4, 0x06, 0x03 } },		inputreg:   TDA9873_SW,		inputmute:  TDA9873_MUTE | TDA9873_AUTOMUTE,		inputmap:   {0xa0, 0xa2, 0xa0, 0xa0, 0xc0},		inputmask:  TDA9873_INP_MASK | TDA9873_MUTE | TDA9873_AUTOMUTE			},	{		name:       "tda9874a",		id:         I2C_DRIVERID_TDA9874A,		checkit:    tda9874a_checkit,		initialize: tda9874a_initialize,		insmodopt:  &tda9874a,		addr_lo:    I2C_TDA9874A >> 1,		addr_hi:    I2C_TDA9874A >> 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_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,			     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: 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;        chip->prevmode = -1;	/* register */	MOD_INC_USE_COUNT;	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   : 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;		chip->wt.function = chip_thread_wake;		chip->wt.data     = (unsigned long)chip;		init_waitqueue_head(&chip->wq);		kernel_thread(chip_thread,(void *)chip,0);		down(&sem);		chip->notify = NULL;		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;	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);	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_masked(chip,desc->inputreg,desc->inputmute,desc->inputmask);			else				chip_write_masked(chip,desc->inputreg,desc->inputmap[*sarg],desc->inputmask);		}		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) {			chip->mode = va->mode;			desc->setmode(chip,va->mode);		}		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 = {        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 + -