📄 uda1341.c
字号:
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 + -