📄 pontis.c
字号:
}/* * SPDIF input source */static int cs_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo){ static char *texts[] = { "Coax", /* RXP0 */ "Optical", /* RXP1 */ "CD", /* RXP2 */ }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = 3; if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); return 0;}static int cs_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); down(&ice->gpio_mutex); ucontrol->value.enumerated.item[0] = ice->gpio.saved[0]; up(&ice->gpio_mutex); return 0;}static int cs_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); unsigned char val; int change = 0; down(&ice->gpio_mutex); if (ucontrol->value.enumerated.item[0] != ice->gpio.saved[0]) { ice->gpio.saved[0] = ucontrol->value.enumerated.item[0] & 3; val = 0x80 | (ice->gpio.saved[0] << 3); spi_write(ice, CS_DEV, 0x04, val); change = 1; } up(&ice->gpio_mutex); return 0;}/* * GPIO controls */static int pontis_gpio_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = 0xffff; /* 16bit */ return 0;}static int pontis_gpio_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); down(&ice->gpio_mutex); /* 4-7 reserved */ ucontrol->value.integer.value[0] = (~ice->gpio.write_mask & 0xffff) | 0x00f0; up(&ice->gpio_mutex); return 0;} static int pontis_gpio_mask_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); unsigned int val; int changed; down(&ice->gpio_mutex); /* 4-7 reserved */ val = (~ucontrol->value.integer.value[0] & 0xffff) | 0x00f0; changed = val != ice->gpio.write_mask; ice->gpio.write_mask = val; up(&ice->gpio_mutex); return changed;}static int pontis_gpio_dir_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); down(&ice->gpio_mutex); /* 4-7 reserved */ ucontrol->value.integer.value[0] = ice->gpio.direction & 0xff0f; up(&ice->gpio_mutex); return 0;} static int pontis_gpio_dir_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); unsigned int val; int changed; down(&ice->gpio_mutex); /* 4-7 reserved */ val = ucontrol->value.integer.value[0] & 0xff0f; changed = (val != ice->gpio.direction); ice->gpio.direction = val; up(&ice->gpio_mutex); return changed;}static int pontis_gpio_data_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); down(&ice->gpio_mutex); snd_ice1712_gpio_set_dir(ice, ice->gpio.direction); snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask); ucontrol->value.integer.value[0] = snd_ice1712_gpio_read(ice) & 0xffff; up(&ice->gpio_mutex); return 0;}static int pontis_gpio_data_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ ice1712_t *ice = snd_kcontrol_chip(kcontrol); unsigned int val, nval; int changed = 0; down(&ice->gpio_mutex); snd_ice1712_gpio_set_dir(ice, ice->gpio.direction); snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask); val = snd_ice1712_gpio_read(ice) & 0xffff; nval = ucontrol->value.integer.value[0] & 0xffff; if (val != nval) { snd_ice1712_gpio_write(ice, nval); changed = 1; } up(&ice->gpio_mutex); return changed;}/* * mixers */static snd_kcontrol_new_t pontis_controls[] __devinitdata = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "PCM Playback Volume", .info = wm_dac_vol_info, .get = wm_dac_vol_get, .put = wm_dac_vol_put, }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Capture Volume", .info = wm_adc_vol_info, .get = wm_adc_vol_get, .put = wm_adc_vol_put, }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "CD Capture Switch", .info = wm_adc_mux_info, .get = wm_adc_mux_get, .put = wm_adc_mux_put, .private_value = 0, }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Line Capture Switch", .info = wm_adc_mux_info, .get = wm_adc_mux_get, .put = wm_adc_mux_put, .private_value = 1, }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Analog Bypass Switch", .info = wm_bypass_info, .get = wm_bypass_get, .put = wm_bypass_put, }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Swap Output Channels", .info = wm_chswap_info, .get = wm_chswap_get, .put = wm_chswap_put, }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "IEC958 Input Source", .info = cs_source_info, .get = cs_source_get, .put = cs_source_put, }, /* FIXME: which interface? */ { .iface = SNDRV_CTL_ELEM_IFACE_CARD, .name = "GPIO Mask", .info = pontis_gpio_mask_info, .get = pontis_gpio_mask_get, .put = pontis_gpio_mask_put, }, { .iface = SNDRV_CTL_ELEM_IFACE_CARD, .name = "GPIO Direction", .info = pontis_gpio_mask_info, .get = pontis_gpio_dir_get, .put = pontis_gpio_dir_put, }, { .iface = SNDRV_CTL_ELEM_IFACE_CARD, .name = "GPIO Data", .info = pontis_gpio_mask_info, .get = pontis_gpio_data_get, .put = pontis_gpio_data_put, },};/* * WM codec registers */static void wm_proc_regs_write(snd_info_entry_t *entry, snd_info_buffer_t *buffer){ ice1712_t *ice = (ice1712_t *)entry->private_data; char line[64]; unsigned int reg, val; down(&ice->gpio_mutex); while (!snd_info_get_line(buffer, line, sizeof(line))) { if (sscanf(line, "%x %x", ®, &val) != 2) continue; if (reg <= 0x17 && val <= 0xffff) wm_put(ice, reg, val); } up(&ice->gpio_mutex);}static void wm_proc_regs_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer){ ice1712_t *ice = (ice1712_t *)entry->private_data; int reg, val; down(&ice->gpio_mutex); for (reg = 0; reg <= 0x17; reg++) { val = wm_get(ice, reg); snd_iprintf(buffer, "%02x = %04x\n", reg, val); } up(&ice->gpio_mutex);}static void wm_proc_init(ice1712_t *ice){ snd_info_entry_t *entry; if (! snd_card_proc_new(ice->card, "wm_codec", &entry)) { snd_info_set_text_ops(entry, ice, 1024, wm_proc_regs_read); entry->mode |= S_IWUSR; entry->c.text.write_size = 1024; entry->c.text.write = wm_proc_regs_write; }}static void cs_proc_regs_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer){ ice1712_t *ice = (ice1712_t *)entry->private_data; int reg, val; down(&ice->gpio_mutex); for (reg = 0; reg <= 0x26; reg++) { val = spi_read(ice, CS_DEV, reg); snd_iprintf(buffer, "%02x = %02x\n", reg, val); } val = spi_read(ice, CS_DEV, 0x7f); snd_iprintf(buffer, "%02x = %02x\n", 0x7f, val); up(&ice->gpio_mutex);}static void cs_proc_init(ice1712_t *ice){ snd_info_entry_t *entry; if (! snd_card_proc_new(ice->card, "cs_codec", &entry)) { snd_info_set_text_ops(entry, ice, 1024, cs_proc_regs_read); }}static int __devinit pontis_add_controls(ice1712_t *ice){ unsigned int i; int err; for (i = 0; i < ARRAY_SIZE(pontis_controls); i++) { err = snd_ctl_add(ice->card, snd_ctl_new1(&pontis_controls[i], ice)); if (err < 0) return err; } wm_proc_init(ice); cs_proc_init(ice); return 0;}/* * initialize the chip */static int __devinit pontis_init(ice1712_t *ice){ static unsigned short wm_inits[] = { /* These come first to reduce init pop noise */ WM_ADC_MUX, 0x00c0, /* ADC mute */ WM_DAC_MUTE, 0x0001, /* DAC softmute */ WM_DAC_CTRL1, 0x0000, /* DAC mute */ WM_POWERDOWN, 0x0008, /* All power-up except HP */ WM_RESET, 0x0000, /* reset */ }; static unsigned short wm_inits2[] = { WM_MASTER_CTRL, 0x0022, /* 256fs, slave mode */ WM_DAC_INT, 0x0022, /* I2S, normal polarity, 24bit */ WM_ADC_INT, 0x0022, /* I2S, normal polarity, 24bit */ WM_DAC_CTRL1, 0x0090, /* DAC L/R */ WM_OUT_MUX, 0x0001, /* OUT DAC */ WM_HP_ATTEN_L, 0x0179, /* HP 0dB */ WM_HP_ATTEN_R, 0x0179, /* HP 0dB */ WM_DAC_ATTEN_L, 0x0000, /* DAC 0dB */ WM_DAC_ATTEN_L, 0x0100, /* DAC 0dB */ WM_DAC_ATTEN_R, 0x0000, /* DAC 0dB */ WM_DAC_ATTEN_R, 0x0100, /* DAC 0dB */ // WM_DAC_MASTER, 0x0100, /* DAC master muted */ WM_PHASE_SWAP, 0x0000, /* phase normal */ WM_DAC_CTRL2, 0x0000, /* no deemphasis, no ZFLG */ WM_ADC_ATTEN_L, 0x0000, /* ADC muted */ WM_ADC_ATTEN_R, 0x0000, /* ADC muted */#if 0 WM_ALC_CTRL1, 0x007b, /* */ WM_ALC_CTRL2, 0x0000, /* */ WM_ALC_CTRL3, 0x0000, /* */ WM_NOISE_GATE, 0x0000, /* */#endif WM_DAC_MUTE, 0x0000, /* DAC unmute */ WM_ADC_MUX, 0x0003, /* ADC unmute, both CD/Line On */ }; static unsigned char cs_inits[] = { 0x04, 0x80, /* RUN, RXP0 */ 0x05, 0x05, /* slave, 24bit */ 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, }; unsigned int i; ice->vt1720 = 1; ice->num_total_dacs = 2; ice->num_total_adcs = 2; /* to remeber the register values */ ice->akm = kzalloc(sizeof(akm4xxx_t), GFP_KERNEL); if (! ice->akm) return -ENOMEM; ice->akm_codecs = 1; /* HACK - use this as the SPDIF source. * don't call snd_ice1712_gpio_get/put(), otherwise it's overwritten */ ice->gpio.saved[0] = 0; /* initialize WM8776 codec */ for (i = 0; i < ARRAY_SIZE(wm_inits); i += 2) wm_put(ice, wm_inits[i], wm_inits[i+1]); schedule_timeout_uninterruptible(1); for (i = 0; i < ARRAY_SIZE(wm_inits2); i += 2) wm_put(ice, wm_inits2[i], wm_inits2[i+1]); /* initialize CS8416 codec */ /* assert PRST#; MT05 bit 7 */ outb(inb(ICEMT1724(ice, AC97_CMD)) | 0x80, ICEMT1724(ice, AC97_CMD)); mdelay(5); /* deassert PRST# */ outb(inb(ICEMT1724(ice, AC97_CMD)) & ~0x80, ICEMT1724(ice, AC97_CMD)); for (i = 0; i < ARRAY_SIZE(cs_inits); i += 2) spi_write(ice, CS_DEV, cs_inits[i], cs_inits[i+1]); return 0;}/* * Pontis boards don't provide the EEPROM data at all. * hence the driver needs to sets up it properly. */static unsigned char pontis_eeprom[] __devinitdata = { 0x08, /* SYSCONF: clock 256, mpu401, spdif-in/ADC, 1DAC */ 0x80, /* ACLINK: I2S */ 0xf8, /* I2S: vol, 96k, 24bit, 192k */ 0xc3, /* SPDIF: out-en, out-int, spdif-in */ 0x07, /* GPIO_DIR */ 0x00, /* GPIO_DIR1 */ 0x00, /* GPIO_DIR2 (ignored) */ 0x0f, /* GPIO_MASK (4-7 reserved for CS8416) */ 0xff, /* GPIO_MASK1 */ 0x00, /* GPIO_MASK2 (ignored) */ 0x06, /* GPIO_STATE (0-low, 1-high, 2-high) */ 0x00, /* GPIO_STATE1 */ 0x00, /* GPIO_STATE2 (ignored) */};/* entry point */struct snd_ice1712_card_info snd_vt1720_pontis_cards[] __devinitdata = { { .subvendor = VT1720_SUBDEVICE_PONTIS_MS300, .name = "Pontis MS300", .model = "ms300", .chip_init = pontis_init, .build_controls = pontis_add_controls, .eeprom_size = sizeof(pontis_eeprom), .eeprom_data = pontis_eeprom, }, { } /* terminator */};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -