static int __devinit snd_vt1724_amp_init(struct snd_ice1712 *ice) { static const unsigned short wm_inits[] = { WM_ATTEN_L, 0x0000, /* 0 db */ WM_ATTEN_R, 0x0000, /* 0 db */ WM_DAC_CTRL, 0x0008, /* 24bit I2S */ WM_INT_CTRL, 0x0001, /* 24bit I2S */ }; unsigned int i; /* only use basic functionality for now */ /* VT1616 6ch codec connected to PSDOUT0 using packed mode */ ice->num_total_dacs = 6; ice->num_total_adcs = 2; /* Chaintech AV-710 has another WM8728 codec connected to PSDOUT4 (shared with the SPDIF output). Mixer control for this codec is not yet supported. */ if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AV710) { for (i = 0; i < ARRAY_SIZE(wm_inits); i += 2) wm_put(ice, wm_inits[i], wm_inits[i+1]); } return 0; }
static int __devinit snd_vt1724_amp_init(struct snd_ice1712 *ice) { static unsigned short wm_inits[] = { WM_ATTEN_L, 0x0000, /* 0 db */ WM_ATTEN_R, 0x0000, /* 0 db */ WM_DAC_CTRL, 0x0008, /* 24bit I2S */ WM_INT_CTRL, 0x0001, /* 24bit I2S */ }; unsigned int i; /* only use basic functionality for now */ ice->num_total_dacs = 2; /* only PSDOUT0 is connected */ ice->num_total_adcs = 2; /* Chaintech AV-710 has another codecs, which need initialization */ /* initialize WM8728 codec */ if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AV710) { for (i = 0; i < ARRAY_SIZE(wm_inits); i += 2) wm_put(ice, wm_inits[i], wm_inits[i+1]); } return 0; }
static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned short vol, unsigned short master) { unsigned char nvol; if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE)) nvol = 0; else nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX]; wm_put(ice, index, nvol); wm_put_nocache(ice, index, 0x180 | nvol); }
/* * 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); }
/* * WM codec registers */ static void wm_proc_regs_write(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { struct snd_ice1712 *ice = entry->private_data; char line[64]; unsigned int reg, val; mutex_lock(&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); } mutex_unlock(&ice->gpio_mutex); }
static int phase28_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); int temp, temp2; temp2 = temp = wm_get(ice, WM_DAC_CTRL2); if (ucontrol->value.integer.value[0]) temp |= 0xf; else temp &= ~0xf; if (temp != temp2) { wm_put(ice, WM_DAC_CTRL2, temp); return 1; } return 0; }
static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); unsigned short nval, oval; int change; snd_ice1712_save_gpio_status(ice); oval = wm_get(ice, WM_MUTE); nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10); if ((change = (nval != oval))) wm_put(ice, WM_MUTE, nval); snd_ice1712_restore_gpio_status(ice); return change; }
static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned short vol, unsigned short master) { unsigned char nvol; if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE)) nvol = 0; else { nvol = (((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 128) & WM_VOL_MAX; nvol = (nvol ? (nvol + DAC_MIN) : 0) & 0xff; } wm_put(ice, index, nvol); wm_put_nocache(ice, index, 0x100 | nvol); }
static int wm_adc_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); unsigned short oval, nval; int change = 0; mutex_lock(&ice->gpio_mutex); oval = wm_get(ice, WM_ADC_MUX); nval = (oval & 0xe0) | ucontrol->value.integer.value[0]; if (nval != oval) { wm_put(ice, WM_ADC_MUX, nval); change = 1; } mutex_unlock(&ice->gpio_mutex); return change; }
static int phase28_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { int temp, temp2; struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); temp2 = temp = wm_get(ice, WM_MASTER); if (ucontrol->value.enumerated.item[0]) temp |= 0x8; else temp &= ~0x8; if (temp != temp2) { wm_put(ice, WM_MASTER, temp); return 1; } return 0; }
static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); unsigned short ovol, nvol; int change = 0; snd_ice1712_save_gpio_status(ice); nvol = ucontrol->value.integer.value[0]; nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff; ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff; if (ovol != nvol) { wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */ wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */ change = 1; } snd_ice1712_restore_gpio_status(ice); return change; }
static int wm_bypass_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); unsigned short val, oval; int change = 0; mutex_lock(&ice->gpio_mutex); val = oval = wm_get(ice, WM_OUT_MUX); if (ucontrol->value.integer.value[0]) val |= 0x04; else val &= ~0x04; if (val != oval) { wm_put(ice, WM_OUT_MUX, val); change = 1; } mutex_unlock(&ice->gpio_mutex); return change; }
static int wm_bypass_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol) { ice1712_t *ice = snd_kcontrol_chip(kcontrol); unsigned short val, oval; int change = 0; down(&ice->gpio_mutex); val = oval = wm_get(ice, WM_OUT_MUX); if (ucontrol->value.integer.value[0]) val |= 0x04; else val &= ~0x04; if (val != oval) { wm_put(ice, WM_OUT_MUX, val); change = 1; } up(&ice->gpio_mutex); return change; }
static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); int bit = kcontrol->private_value; unsigned short oval, nval; int change; mutex_lock(&ice->gpio_mutex); nval = oval = wm_get(ice, WM_ADC_MUX); if (ucontrol->value.integer.value[0]) nval |= (1 << bit); else nval &= ~(1 << bit); change = nval != oval; if (change) { wm_put(ice, WM_ADC_MUX, nval); } mutex_unlock(&ice->gpio_mutex); return change; }
static int wm_adc_mux_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol) { ice1712_t *ice = snd_kcontrol_chip(kcontrol); int bit = kcontrol->private_value; unsigned short oval, nval; int change; down(&ice->gpio_mutex); nval = oval = wm_get(ice, WM_ADC_MUX); if (ucontrol->value.integer.value[0]) nval |= (1 << bit); else nval &= ~(1 << bit); change = nval != oval; if (change) { wm_put(ice, WM_ADC_MUX, nval); } up(&ice->gpio_mutex); return 0; }
static int wm_adc_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) { ice1712_t *ice = snd_kcontrol_chip(kcontrol); unsigned short ovol, nvol; int i, idx, change = 0; down(&ice->gpio_mutex); for (i = 0; i < 2; i++) { nvol = ucontrol->value.integer.value[i]; nvol = nvol ? (nvol + ADC_MIN) : 0; idx = WM_ADC_ATTEN_L + i; ovol = wm_get(ice, idx) & 0xff; if (ovol != nvol) { wm_put(ice, idx, nvol); change = 1; } } up(&ice->gpio_mutex); return change; }
static int wm_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); unsigned short oval, nval; int i, idx, change = 0; mutex_lock(&ice->gpio_mutex); for (i = 0; i < 2; i++) { nval = ucontrol->value.integer.value[i]; nval = (nval ? (nval + DAC_MIN) : 0) & 0xff; idx = WM_DAC_ATTEN_L + i; oval = wm_get(ice, idx) & 0xff; if (oval != nval) { wm_put(ice, idx, nval); wm_put_nocache(ice, idx, nval | 0x100); change = 1; } } mutex_unlock(&ice->gpio_mutex); return change; }
static int wm_chswap_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol) { ice1712_t *ice = snd_kcontrol_chip(kcontrol); unsigned short val, oval; int change = 0; down(&ice->gpio_mutex); oval = wm_get(ice, WM_DAC_CTRL1); val = oval & 0x0f; if (ucontrol->value.integer.value[0]) val |= 0x60; else val |= 0x90; if (val != oval) { wm_put(ice, WM_DAC_CTRL1, val); wm_put_nocache(ice, WM_DAC_CTRL1, val); change = 1; } up(&ice->gpio_mutex); return change; }
static int __devinit prodigy_hifi_init(struct snd_ice1712 *ice) { static unsigned short wm_inits[] = { WM_ADC_MUX, 0x0003, WM_DAC_MUTE, 0x0001, WM_DAC_CTRL1, 0x0000, WM_POWERDOWN, 0x0008, WM_RESET, 0x0000, }; static unsigned short wm_inits2[] = { WM_MASTER_CTRL, 0x0022, WM_DAC_INT, 0x0022, WM_ADC_INT, 0x0022, WM_DAC_CTRL1, 0x0090, WM_OUT_MUX, 0x0001, WM_HP_ATTEN_L, 0x0179, WM_HP_ATTEN_R, 0x0179, WM_DAC_ATTEN_L, 0x0000, WM_DAC_ATTEN_L, 0x0100, WM_DAC_ATTEN_R, 0x0000, WM_DAC_ATTEN_R, 0x0100, WM_PHASE_SWAP, 0x0000, #if 0 WM_DAC_MASTER, 0x0100, #endif WM_DAC_CTRL2, 0x0000, WM_ADC_ATTEN_L, 0x0000, WM_ADC_ATTEN_R, 0x0000, #if 1 WM_ALC_CTRL1, 0x007b, WM_ALC_CTRL2, 0x0000, WM_ALC_CTRL3, 0x0000, WM_NOISE_GATE, 0x0000, #endif WM_DAC_MUTE, 0x0000, WM_ADC_MUX, 0x0003, }; static unsigned short wm8766_inits[] = { WM8766_RESET, 0x0000, WM8766_DAC_CTRL, 0x0120, WM8766_INT_CTRL, 0x0022, WM8766_DAC_CTRL2, 0x0001, WM8766_DAC_CTRL3, 0x0080, WM8766_LDA1, 0x0100, WM8766_LDA2, 0x0100, WM8766_LDA3, 0x0100, WM8766_RDA1, 0x0100, WM8766_RDA2, 0x0100, WM8766_RDA3, 0x0100, WM8766_MUTE1, 0x0000, WM8766_MUTE2, 0x0000, }; struct prodigy_hifi_spec *spec; unsigned int i; ice->vt1720 = 0; ice->vt1724 = 1; ice->num_total_dacs = 8; ice->num_total_adcs = 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; ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); if (! ice->akm) return -ENOMEM; ice->akm_codecs = 1; spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (!spec) return -ENOMEM; ice->spec = spec; 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]); for (i = 0; i < ARRAY_SIZE(wm8766_inits); i += 2) wm8766_spi_write(ice, wm8766_inits[i], wm8766_inits[i+1]); return 0; }
static int __devinit phase28_init(struct snd_ice1712 *ice) { static const unsigned short wm_inits_phase28[] = { /* These come first to reduce init pop noise */ 0x1b, 0x044, /* ADC Mux (AC'97 source) */ 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */ 0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */ 0x18, 0x000, /* All power-up */ 0x16, 0x122, /* I2S, normal polarity, 24bit */ 0x17, 0x022, /* 256fs, slave mode */ 0x00, 0, /* DAC1 analog mute */ 0x01, 0, /* DAC2 analog mute */ 0x02, 0, /* DAC3 analog mute */ 0x03, 0, /* DAC4 analog mute */ 0x04, 0, /* DAC5 analog mute */ 0x05, 0, /* DAC6 analog mute */ 0x06, 0, /* DAC7 analog mute */ 0x07, 0, /* DAC8 analog mute */ 0x08, 0x100, /* master analog mute */ 0x09, 0xff, /* DAC1 digital full */ 0x0a, 0xff, /* DAC2 digital full */ 0x0b, 0xff, /* DAC3 digital full */ 0x0c, 0xff, /* DAC4 digital full */ 0x0d, 0xff, /* DAC5 digital full */ 0x0e, 0xff, /* DAC6 digital full */ 0x0f, 0xff, /* DAC7 digital full */ 0x10, 0xff, /* DAC8 digital full */ 0x11, 0x1ff, /* master digital full */ 0x12, 0x000, /* phase normal */ 0x13, 0x090, /* unmute DAC L/R */ 0x14, 0x000, /* all unmute */ 0x15, 0x000, /* no deemphasis, no ZFLG */ 0x19, 0x000, /* -12dB ADC/L */ 0x1a, 0x000, /* -12dB ADC/R */ (unsigned short)-1 }; unsigned int tmp; struct snd_akm4xxx *ak; const unsigned short *p; int i; ice->num_total_dacs = 8; ice->num_total_adcs = 2; // Initialize analog chips ak = ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); if (!ak) return -ENOMEM; ice->akm_codecs = 1; snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */ /* reset the wm codec as the SPI mode */ snd_ice1712_save_gpio_status(ice); snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RESET|PHASE28_WM_CS|PHASE28_HP_SEL)); tmp = snd_ice1712_gpio_read(ice); tmp &= ~PHASE28_WM_RESET; snd_ice1712_gpio_write(ice, tmp); udelay(1); tmp |= PHASE28_WM_CS; snd_ice1712_gpio_write(ice, tmp); udelay(1); tmp |= PHASE28_WM_RESET; snd_ice1712_gpio_write(ice, tmp); udelay(1); p = wm_inits_phase28; for (; *p != (unsigned short)-1; p += 2) wm_put(ice, p[0], p[1]); snd_ice1712_restore_gpio_status(ice); ice->spec.phase28.master[0] = WM_VOL_MUTE; ice->spec.phase28.master[1] = WM_VOL_MUTE; for (i = 0; i < ice->num_total_dacs; i++) { ice->spec.phase28.vol[i] = WM_VOL_MUTE; wm_set_vol(ice, i, ice->spec.phase28.vol[i], ice->spec.phase28.master[i % 2]); } 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; }