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

📄 uda1341_c.txt

📁 2410uda1341的测试代码
💻 TXT
📖 第 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 + -