📄 uda1341_c.txt
字号:
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 + -