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

📄 uda1341.c

📁 基于linux kernel 2.6.20的UDA1341声音芯片的声卡驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
	struct uda1341_ctl *ctl = (struct uda1341_ctl *)kc->private_value;	unsigned int val = ev->value.integer.value[0] & ctl->mask;	pr_debug(">>> %s\n", __FUNCTION__);	if (ctl->min > ctl->max)		val = ctl->mask - val;	spin_lock(&uda->lock);	uda->regs.data0[REGEXT4] &= ~3;		uda->regs.data0[REGEXT4] |= val & 3;	uda->regs.data0[REGEXT5] |= (val >> 2) & 31;	uda->regs.dirty[REGEXT4] = 1;	uda->regs.dirty[REGEXT5] = 1;	spin_unlock(&uda->lock);	return 0;}static snd_kcontrol_new_t uda1341_ctl_simple = {	.iface	= SNDRV_CTL_ELEM_IFACE_MIXER,	.access	= SNDRV_CTL_ELEM_ACCESS_READWRITE,	.info	= uda1341_ctl_simple_info,	.get	= uda1341_ctl_simple_get,	.put	= uda1341_ctl_simple_put,};static snd_kcontrol_new_t uda1341_ctl_stat1 = {	.iface	= SNDRV_CTL_ELEM_IFACE_MIXER,	.access	= SNDRV_CTL_ELEM_ACCESS_READWRITE,	.info	= uda1341_ctl_simple_info,	.get	= uda1341_ctl_stat1_get,	.put	= uda1341_ctl_stat1_put,};static snd_kcontrol_new_t uda1341_ctl_ch2ig = {	.iface	= SNDRV_CTL_ELEM_IFACE_MIXER,	.access	= SNDRV_CTL_ELEM_ACCESS_READWRITE,	.info	= uda1341_ctl_simple_info,	.get	= uda1341_ctl_ch2ig_get,	.put	= uda1341_ctl_ch2ig_put,};static struct uda1341_ctl uda1341_controls[] = {	{		.name	= "Master Playback Volume",		.ctl	= &uda1341_ctl_simple,		.min	= 62,		.max	= 1,		.def	= 1,		.reg	= REGDIR0,		.mask	= 63,		.off	= 0,	},	{		.name	= "Master Playback Mute",		.ctl	= &uda1341_ctl_simple,		.min	= 0,		.max	= 1,		.def	= 0,		.reg	= REGDIR2,		.mask	= 1,		.off	= 2,	},	{		.name	= "Tone Control - Bass",		.ctl	= &uda1341_ctl_simple,		.min	= 0,		.max	= 14,		.def	= 0,		.reg	= REGDIR1,		.mask	= 15,		.off	= 2,	},	{		.name	= "Tone Control - Treble",		.ctl	= &uda1341_ctl_simple,		.min	= 0,		.max	= 3,		.def	= 0,		.reg	= REGDIR1,		.mask	= 3,		.off	= 0,	},	{		.name	= "Line Capture Volume",		.ctl	= &uda1341_ctl_simple,		.min	= 31,		.max	= 0,		.def	= 31,		.reg	= REGEXT0,		.mask	= 31,		.off	= 0,	},	{		.name	= "Mic Capture Volume",		.ctl	= &uda1341_ctl_simple,		.min	= 31,		.max	= 0,		.def	= 31,		.reg	= REGEXT1,		.mask	= 31,		.off	= 0,	},	{		.name	= "Output 6DB gain switch",		.ctl	= &uda1341_ctl_stat1,		.min	= 0,		.max	= 1,		.def	= 1,		.reg	= 0xff,		.mask	= 1,		.off	= 6,	},	{		.name	= "Input 6DB gain switch",		.ctl	= &uda1341_ctl_stat1,		.min	= 0,		.max	= 1,		.def	= 1,		.reg	= 0xff,		.mask	= 1,		.off	= 5,	},	{		.name	= "ADC polarity",		.ctl	= &uda1341_ctl_stat1,		.min	= 0,		.max	= 1,		.def	= 0,		.reg	= 0xff,		.mask	= 1,		.off	= 4,	},	{		.name	= "DAC polarity",		.ctl	= &uda1341_ctl_stat1,		.min	= 0,		.max	= 1,		.def	= 0,		.reg	= 0xff,		.mask	= 1,		.off	= 3,	},	{		.name	= "Mode filter",		.ctl	= &uda1341_ctl_simple,		.min	= 0,		.max	= 3,		.def	= 3,		.reg	= REGDIR2,		.mask	= 3,		.off	= 0,	},	{		.name	= "De-emphasis",		.ctl	= &uda1341_ctl_simple,		.min	= 0,		.max	= 3,		.def	= 0,		.reg	= REGDIR2,		.mask	= 3,		.off	= 3,	},	{		.name	= "Mic Sensivity",		.ctl	= &uda1341_ctl_simple,		.min	= 0,		.max	= 6,		.def	= 4,		.reg	= REGEXT2,		.mask	= 7,		.off	= 2,	},	{		.name	= "Mixer mode",		.ctl	= &uda1341_ctl_simple,		.min	= 0,		.max	= 3,		.def	= 0,		.reg	= REGEXT2,		.mask	= 3,		.off	= 0,	},	{		.name	= "AGC switch",		.ctl	= &uda1341_ctl_simple,		.min	= 0,		.max	= 1,		.def	= 1,		.reg	= REGEXT4,		.mask	= 4,		.off	= 0,	},	{		.name	= "CH2 input gain",		.ctl	= &uda1341_ctl_ch2ig,		.min	= 0,		.max	= 127,		.def	= 0,		.reg	= 0xff,		.mask	= 10,		.off	= 0,	},	{		.name	= "AGC output level",		.ctl	= &uda1341_ctl_simple,		.min	= 3,		.max	= 0,		.def	= 0,		.reg	= REGEXT6,		.mask	= 3,		.off	= 0,	},	{		.name	= "AGC time constant",		.ctl	= &uda1341_ctl_simple,		.min	= 0,		.max	= 7,		.def	= 3,		.reg	= REGEXT6,		.mask	= 7,		.off	= 2,	},};static int uda1341_add_ctl(snd_card_t *card, struct uda1341 *uda, struct uda1341_ctl *udactl){	snd_kcontrol_t *ctl;	int ret = -ENOMEM;	pr_debug("--- %s\n", __FUNCTION__);	ctl = snd_ctl_new1(udactl->ctl, uda);	if (ctl) {		strlcpy(ctl->id.name, udactl->name, sizeof(ctl->id.name));		ctl->private_value = (unsigned long)udactl;		if (udactl->reg != 0xff) {		  uda->regs.data0[udactl->reg] &= ~(udactl->mask << udactl->off);		  uda->regs.data0[udactl->reg] |= udactl->def << udactl->off;		}		ret = snd_ctl_add(card, ctl);		if (ret < 0)			snd_ctl_free_one(ctl);	}	return ret;}static int uda1341_free(snd_device_t *dev){	struct uda1341 *uda = dev->device_data;	pr_debug("--- %s\n", __FUNCTION__);	l3_put_adapter(uda->l3_bus);	kfree(uda);	return 0;}static snd_device_ops_t uda1341_ops = {	.dev_free = uda1341_free,};struct uda1341 *uda1341_create(snd_card_t *card, const char *adapter){	struct uda1341 *uda;	int i, ret;	unsigned char buf[2];	pr_debug("--- %s\n", __FUNCTION__);	uda = kmalloc(sizeof(*uda), GFP_KERNEL);	if (!uda)		return ERR_PTR(-ENOMEM);	memset(uda, 0, sizeof(*uda));	ret = snd_device_new(card, SNDRV_DEV_LOWLEVEL, uda, &uda1341_ops);	if (ret)		goto err;	uda->regs.stat0 = STAT0_SC_384FS | STAT0_IF_LSB16;	uda->regs.stat1 = STAT1_DAC_GAIN | STAT1_ADC_GAIN; /* | STAT1_ADC_ON | STAT1_DAC_ON; */	uda->regs.data0[REGDIR0] = 0;	uda->regs.data0[REGDIR1] = 0;	uda->regs.data0[REGDIR2] = DATA2_PEAKAFTER | DATA2_DEEMP_NONE |			    DATA2_FILTER_MAX;	uda->regs.data0[REGEXT0] = 0;	uda->regs.data0[REGEXT1] = 0;	uda->regs.data0[REGEXT2] = EXT2_MIXMODE_CH1 | EXT2_MIC_GAIN(4);	uda->regs.data0[REGEXT4] = EXT4_AGC_ENABLE | EXT4_INPUT_GAIN(0);	uda->regs.data0[REGEXT5] = EXT5_INPUT_GAIN(0);	uda->regs.data0[REGEXT6] = EXT6_AGC_CONSTANT(3) | EXT6_AGC_LEVEL(0);	uda->l3_bus = l3_get_adapter(adapter);	if (!uda->l3_bus) {		kfree(uda);		return ERR_PTR(-ENOENT);	}	strlcpy(card->mixername, "Philips UDA1341", sizeof(card->mixername));	for (i = 0; i < ARRAY_SIZE(uda1341_controls); i++) {		ret = uda1341_add_ctl(card, uda, &uda1341_controls[i]);		if (ret)			goto err;	}	uda->regs.dirty0 = uda->regs.dirty1 = 1;	for(i=REGDIR0; i<=REGEXT6; i++)		uda->regs.dirty[i] = 1;	/* reset UDA */	buf[0] = uda->regs.stat0 | STAT0_RST;	buf[1] = uda->regs.stat1;	l3_write(uda->l3_bus, UDA1341_STATUS, buf, 2);	return uda; err:	kfree(uda);	return ERR_PTR(ret);}int uda1341_open(struct uda1341 *uda){	uda->active = 1;	pr_debug("--- %s\n", __FUNCTION__);	uda1341_sync(uda);	return 0;}void uda1341_close(struct uda1341 *uda, struct uda1341_cfg *conf){	unsigned char buf = uda->regs.stat1 | STAT1;	pr_debug("--- %s\n", __FUNCTION__);	if (conf->record) {		buf &= ~STAT1_ADC_ON;	}	if (conf->play) {		buf &= ~STAT1_DAC_ON;	}	l3_write(uda->l3_bus, UDA1341_STATUS, &buf, 1);	uda->active = 0;}void uda1341_suspend(struct uda1341 *uda){	unsigned char buf = uda->regs.stat1 & ~(STAT1_ADC_ON | STAT1_DAC_ON);	pr_debug("--- %s\n", __FUNCTION__);	if (uda->active)		l3_write(uda->l3_bus, UDA1341_STATUS, &buf, 1);}void uda1341_resume(struct uda1341 *uda){	unsigned char buf[2];	int i;	pr_debug("--- %s\n", __FUNCTION__);	if (uda->active) {		buf[0] = uda->regs.stat0 | STAT0_RST;		buf[1] = uda->regs.stat0;		l3_write(uda->l3_bus, UDA1341_STATUS, buf, 2);		/* resend all parameters */		uda->regs.dirty0 = uda->regs.dirty1 = 1;		for(i=REGDIR0; i<=REGEXT6; i++)			uda->regs.dirty[i] = 1;		uda1341_sync(uda);	}}MODULE_AUTHOR("Nicolas Pitre");MODULE_DESCRIPTION("Philips UDA1341 CODEC driver");MODULE_LICENSE("GPL");EXPORT_SYMBOL(uda1341_create);EXPORT_SYMBOL(uda1341_open);EXPORT_SYMBOL(uda1341_close);EXPORT_SYMBOL(uda1341_suspend);EXPORT_SYMBOL(uda1341_resume);

⌨️ 快捷键说明

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