Loading sound/pci/oxygen/xonar_pcm179x.c +157 −25 Original line number Diff line number Diff line Loading @@ -173,8 +173,11 @@ struct xonar_pcm179x { struct xonar_generic generic; unsigned int dacs; u8 pcm1796_regs[4][5]; unsigned int current_rate; bool os_128; bool hp_active; s8 hp_gain_offset; bool has_cs2000; u8 cs2000_fun_cfg_1; }; Loading Loading @@ -277,6 +280,7 @@ static void pcm1796_init(struct oxygen *chip) PCM1796_DMF_DISABLED | PCM1796_FMT_24_LJUST | PCM1796_ATLD; data->pcm1796_regs[0][20 - PCM1796_REG_BASE] = PCM1796_OS_64; pcm1796_registers_init(chip); data->current_rate = 48000; } static void xonar_d2_init(struct oxygen *chip) Loading Loading @@ -401,6 +405,7 @@ static void xonar_st_init(struct oxygen *chip) { struct xonar_pcm179x *data = chip->model_data; data->has_cs2000 = 1; data->cs2000_fun_cfg_1 = CS2000_REF_CLK_DIV_1; oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, Loading Loading @@ -486,18 +491,57 @@ static void xonar_st_resume(struct oxygen *chip) xonar_stx_resume(chip); } static void set_pcm1796_params(struct oxygen *chip, static unsigned int mclk_from_rate(struct oxygen *chip, unsigned int rate) { struct xonar_pcm179x *data = chip->model_data; if (rate <= 32000) return OXYGEN_I2S_MCLK_512; else if (rate <= 48000 && data->os_128) return OXYGEN_I2S_MCLK_512; else if (rate <= 96000) return OXYGEN_I2S_MCLK_256; else return OXYGEN_I2S_MCLK_128; } static unsigned int get_pcm1796_i2s_mclk(struct oxygen *chip, unsigned int channel, struct snd_pcm_hw_params *params) { if (channel == PCM_MULTICH) return mclk_from_rate(chip, params_rate(params)); else return oxygen_default_i2s_mclk(chip, channel, params); } static void update_pcm1796_oversampling(struct oxygen *chip) { struct xonar_pcm179x *data = chip->model_data; unsigned int i; u8 reg; reg = params_rate(params) >= 96000 ? PCM1796_OS_32 : PCM1796_OS_64; if (data->current_rate <= 32000) reg = PCM1796_OS_128; else if (data->current_rate <= 48000 && data->os_128) reg = PCM1796_OS_128; else if (data->current_rate <= 96000 || data->os_128) reg = PCM1796_OS_64; else reg = PCM1796_OS_32; for (i = 0; i < data->dacs; ++i) pcm1796_write_cached(chip, i, 20, reg); } static void set_pcm1796_params(struct oxygen *chip, struct snd_pcm_hw_params *params) { struct xonar_pcm179x *data = chip->model_data; data->current_rate = params_rate(params); update_pcm1796_oversampling(chip); } static void update_pcm1796_volume(struct oxygen *chip) { struct xonar_pcm179x *data = chip->model_data; Loading Loading @@ -526,26 +570,44 @@ static void update_pcm1796_mute(struct oxygen *chip) pcm1796_write_cached(chip, i, 18, value); } static void set_cs2000_params(struct oxygen *chip, struct snd_pcm_hw_params *params) static void update_cs2000_rate(struct oxygen *chip, unsigned int rate) { /* XXX Why is the I2S A MCLK half the actual I2S multich MCLK? */ static const u8 rate_mclks[] = { [OXYGEN_RATE_32000] = OXYGEN_RATE_32000 | OXYGEN_I2S_MCLK_128, [OXYGEN_RATE_44100] = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_128, [OXYGEN_RATE_48000] = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_128, [OXYGEN_RATE_64000] = OXYGEN_RATE_32000 | OXYGEN_I2S_MCLK_256, [OXYGEN_RATE_88200] = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_256, [OXYGEN_RATE_96000] = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_256, [OXYGEN_RATE_176400] = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_256, [OXYGEN_RATE_192000] = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_256, }; unsigned int rate_index; struct xonar_pcm179x *data = chip->model_data; u8 rate_mclk, reg; rate_index = oxygen_read16(chip, OXYGEN_I2S_MULTICH_FORMAT) & OXYGEN_I2S_RATE_MASK; rate_mclk = rate_mclks[rate_index]; switch (rate) { /* XXX Why is the I2S A MCLK half the actual I2S MCLK? */ case 32000: rate_mclk = OXYGEN_RATE_32000 | OXYGEN_I2S_MCLK_256; break; case 44100: if (data->os_128) rate_mclk = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_256; else rate_mclk = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_128; break; default: /* 48000 */ if (data->os_128) rate_mclk = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_256; else rate_mclk = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_128; break; case 64000: rate_mclk = OXYGEN_RATE_32000 | OXYGEN_I2S_MCLK_256; break; case 88200: rate_mclk = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_256; break; case 96000: rate_mclk = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_256; break; case 176400: rate_mclk = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_256; break; case 192000: rate_mclk = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_256; break; } oxygen_write16_masked(chip, OXYGEN_I2S_A_FORMAT, rate_mclk, OXYGEN_I2S_RATE_MASK | OXYGEN_I2S_MCLK_MASK); if ((rate_mclk & OXYGEN_I2S_MCLK_MASK) <= OXYGEN_I2S_MCLK_128) Loading @@ -558,7 +620,7 @@ static void set_cs2000_params(struct oxygen *chip, static void set_st_params(struct oxygen *chip, struct snd_pcm_hw_params *params) { set_cs2000_params(chip, params); update_cs2000_rate(chip, params_rate(params)); set_pcm1796_params(chip, params); } Loading @@ -580,6 +642,59 @@ static const struct snd_kcontrol_new alt_switch = { .private_value = GPIO_D2_ALT, }; static int os_128_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) { static const char *const names[2] = { "64x", "128x" }; info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; info->count = 1; info->value.enumerated.items = 2; if (info->value.enumerated.item >= 2) info->value.enumerated.item = 1; strcpy(info->value.enumerated.name, names[info->value.enumerated.item]); return 0; } static int os_128_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) { struct oxygen *chip = ctl->private_data; struct xonar_pcm179x *data = chip->model_data; value->value.enumerated.item[0] = data->os_128; return 0; } static int os_128_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) { struct oxygen *chip = ctl->private_data; struct xonar_pcm179x *data = chip->model_data; int changed; mutex_lock(&chip->mutex); changed = value->value.enumerated.item[0] != data->os_128; if (changed) { data->os_128 = value->value.enumerated.item[0]; if (data->has_cs2000) update_cs2000_rate(chip, data->current_rate); oxygen_write16_masked(chip, OXYGEN_I2S_MULTICH_FORMAT, mclk_from_rate(chip, data->current_rate), OXYGEN_I2S_MCLK_MASK); update_pcm1796_oversampling(chip); } mutex_unlock(&chip->mutex); return changed; } static const struct snd_kcontrol_new os_128_control = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "DAC Oversampling Playback Enum", .info = os_128_info, .get = os_128_get, .put = os_128_put, }; static int st_output_switch_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) { Loading Loading @@ -745,7 +860,20 @@ static int xonar_st_control_filter(struct snd_kcontrol_new *template) static int xonar_d2_mixer_init(struct oxygen *chip) { return snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip)); int err; err = snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip)); if (err < 0) return err; err = snd_ctl_add(chip->card, snd_ctl_new1(&os_128_control, chip)); if (err < 0) return err; return 0; } static int xonar_hdav_mixer_init(struct oxygen *chip) { return snd_ctl_add(chip->card, snd_ctl_new1(&os_128_control, chip)); } static int xonar_st_mixer_init(struct oxygen *chip) Loading @@ -759,6 +887,9 @@ static int xonar_st_mixer_init(struct oxygen *chip) if (err < 0) return err; } err = snd_ctl_add(chip->card, snd_ctl_new1(&os_128_control, chip)); if (err < 0) return err; return 0; } Loading @@ -771,7 +902,7 @@ static const struct oxygen_model model_xonar_d2 = { .cleanup = xonar_d2_cleanup, .suspend = xonar_d2_suspend, .resume = xonar_d2_resume, .get_i2s_mclk = oxygen_default_i2s_mclk, .get_i2s_mclk = get_pcm1796_i2s_mclk, .set_dac_params = set_pcm1796_params, .set_adc_params = xonar_set_cs53x1_params, .update_dac_volume = update_pcm1796_volume, Loading @@ -798,11 +929,12 @@ static const struct oxygen_model model_xonar_hdav = { .longname = "Asus Virtuoso 200", .chip = "AV200", .init = xonar_hdav_init, .mixer_init = xonar_hdav_mixer_init, .cleanup = xonar_hdav_cleanup, .suspend = xonar_hdav_suspend, .resume = xonar_hdav_resume, .pcm_hardware_filter = xonar_hdmi_pcm_hardware_filter, .get_i2s_mclk = oxygen_default_i2s_mclk, .get_i2s_mclk = get_pcm1796_i2s_mclk, .set_dac_params = set_hdav_params, .set_adc_params = xonar_set_cs53x1_params, .update_dac_volume = update_pcm1796_volume, Loading Loading @@ -833,7 +965,7 @@ static const struct oxygen_model model_xonar_st = { .cleanup = xonar_st_cleanup, .suspend = xonar_st_suspend, .resume = xonar_st_resume, .get_i2s_mclk = oxygen_default_i2s_mclk, .get_i2s_mclk = get_pcm1796_i2s_mclk, .set_dac_params = set_st_params, .set_adc_params = xonar_set_cs53x1_params, .update_dac_volume = update_pcm1796_volume, Loading Loading
sound/pci/oxygen/xonar_pcm179x.c +157 −25 Original line number Diff line number Diff line Loading @@ -173,8 +173,11 @@ struct xonar_pcm179x { struct xonar_generic generic; unsigned int dacs; u8 pcm1796_regs[4][5]; unsigned int current_rate; bool os_128; bool hp_active; s8 hp_gain_offset; bool has_cs2000; u8 cs2000_fun_cfg_1; }; Loading Loading @@ -277,6 +280,7 @@ static void pcm1796_init(struct oxygen *chip) PCM1796_DMF_DISABLED | PCM1796_FMT_24_LJUST | PCM1796_ATLD; data->pcm1796_regs[0][20 - PCM1796_REG_BASE] = PCM1796_OS_64; pcm1796_registers_init(chip); data->current_rate = 48000; } static void xonar_d2_init(struct oxygen *chip) Loading Loading @@ -401,6 +405,7 @@ static void xonar_st_init(struct oxygen *chip) { struct xonar_pcm179x *data = chip->model_data; data->has_cs2000 = 1; data->cs2000_fun_cfg_1 = CS2000_REF_CLK_DIV_1; oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, Loading Loading @@ -486,18 +491,57 @@ static void xonar_st_resume(struct oxygen *chip) xonar_stx_resume(chip); } static void set_pcm1796_params(struct oxygen *chip, static unsigned int mclk_from_rate(struct oxygen *chip, unsigned int rate) { struct xonar_pcm179x *data = chip->model_data; if (rate <= 32000) return OXYGEN_I2S_MCLK_512; else if (rate <= 48000 && data->os_128) return OXYGEN_I2S_MCLK_512; else if (rate <= 96000) return OXYGEN_I2S_MCLK_256; else return OXYGEN_I2S_MCLK_128; } static unsigned int get_pcm1796_i2s_mclk(struct oxygen *chip, unsigned int channel, struct snd_pcm_hw_params *params) { if (channel == PCM_MULTICH) return mclk_from_rate(chip, params_rate(params)); else return oxygen_default_i2s_mclk(chip, channel, params); } static void update_pcm1796_oversampling(struct oxygen *chip) { struct xonar_pcm179x *data = chip->model_data; unsigned int i; u8 reg; reg = params_rate(params) >= 96000 ? PCM1796_OS_32 : PCM1796_OS_64; if (data->current_rate <= 32000) reg = PCM1796_OS_128; else if (data->current_rate <= 48000 && data->os_128) reg = PCM1796_OS_128; else if (data->current_rate <= 96000 || data->os_128) reg = PCM1796_OS_64; else reg = PCM1796_OS_32; for (i = 0; i < data->dacs; ++i) pcm1796_write_cached(chip, i, 20, reg); } static void set_pcm1796_params(struct oxygen *chip, struct snd_pcm_hw_params *params) { struct xonar_pcm179x *data = chip->model_data; data->current_rate = params_rate(params); update_pcm1796_oversampling(chip); } static void update_pcm1796_volume(struct oxygen *chip) { struct xonar_pcm179x *data = chip->model_data; Loading Loading @@ -526,26 +570,44 @@ static void update_pcm1796_mute(struct oxygen *chip) pcm1796_write_cached(chip, i, 18, value); } static void set_cs2000_params(struct oxygen *chip, struct snd_pcm_hw_params *params) static void update_cs2000_rate(struct oxygen *chip, unsigned int rate) { /* XXX Why is the I2S A MCLK half the actual I2S multich MCLK? */ static const u8 rate_mclks[] = { [OXYGEN_RATE_32000] = OXYGEN_RATE_32000 | OXYGEN_I2S_MCLK_128, [OXYGEN_RATE_44100] = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_128, [OXYGEN_RATE_48000] = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_128, [OXYGEN_RATE_64000] = OXYGEN_RATE_32000 | OXYGEN_I2S_MCLK_256, [OXYGEN_RATE_88200] = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_256, [OXYGEN_RATE_96000] = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_256, [OXYGEN_RATE_176400] = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_256, [OXYGEN_RATE_192000] = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_256, }; unsigned int rate_index; struct xonar_pcm179x *data = chip->model_data; u8 rate_mclk, reg; rate_index = oxygen_read16(chip, OXYGEN_I2S_MULTICH_FORMAT) & OXYGEN_I2S_RATE_MASK; rate_mclk = rate_mclks[rate_index]; switch (rate) { /* XXX Why is the I2S A MCLK half the actual I2S MCLK? */ case 32000: rate_mclk = OXYGEN_RATE_32000 | OXYGEN_I2S_MCLK_256; break; case 44100: if (data->os_128) rate_mclk = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_256; else rate_mclk = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_128; break; default: /* 48000 */ if (data->os_128) rate_mclk = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_256; else rate_mclk = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_128; break; case 64000: rate_mclk = OXYGEN_RATE_32000 | OXYGEN_I2S_MCLK_256; break; case 88200: rate_mclk = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_256; break; case 96000: rate_mclk = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_256; break; case 176400: rate_mclk = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_256; break; case 192000: rate_mclk = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_256; break; } oxygen_write16_masked(chip, OXYGEN_I2S_A_FORMAT, rate_mclk, OXYGEN_I2S_RATE_MASK | OXYGEN_I2S_MCLK_MASK); if ((rate_mclk & OXYGEN_I2S_MCLK_MASK) <= OXYGEN_I2S_MCLK_128) Loading @@ -558,7 +620,7 @@ static void set_cs2000_params(struct oxygen *chip, static void set_st_params(struct oxygen *chip, struct snd_pcm_hw_params *params) { set_cs2000_params(chip, params); update_cs2000_rate(chip, params_rate(params)); set_pcm1796_params(chip, params); } Loading @@ -580,6 +642,59 @@ static const struct snd_kcontrol_new alt_switch = { .private_value = GPIO_D2_ALT, }; static int os_128_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) { static const char *const names[2] = { "64x", "128x" }; info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; info->count = 1; info->value.enumerated.items = 2; if (info->value.enumerated.item >= 2) info->value.enumerated.item = 1; strcpy(info->value.enumerated.name, names[info->value.enumerated.item]); return 0; } static int os_128_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) { struct oxygen *chip = ctl->private_data; struct xonar_pcm179x *data = chip->model_data; value->value.enumerated.item[0] = data->os_128; return 0; } static int os_128_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) { struct oxygen *chip = ctl->private_data; struct xonar_pcm179x *data = chip->model_data; int changed; mutex_lock(&chip->mutex); changed = value->value.enumerated.item[0] != data->os_128; if (changed) { data->os_128 = value->value.enumerated.item[0]; if (data->has_cs2000) update_cs2000_rate(chip, data->current_rate); oxygen_write16_masked(chip, OXYGEN_I2S_MULTICH_FORMAT, mclk_from_rate(chip, data->current_rate), OXYGEN_I2S_MCLK_MASK); update_pcm1796_oversampling(chip); } mutex_unlock(&chip->mutex); return changed; } static const struct snd_kcontrol_new os_128_control = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "DAC Oversampling Playback Enum", .info = os_128_info, .get = os_128_get, .put = os_128_put, }; static int st_output_switch_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) { Loading Loading @@ -745,7 +860,20 @@ static int xonar_st_control_filter(struct snd_kcontrol_new *template) static int xonar_d2_mixer_init(struct oxygen *chip) { return snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip)); int err; err = snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip)); if (err < 0) return err; err = snd_ctl_add(chip->card, snd_ctl_new1(&os_128_control, chip)); if (err < 0) return err; return 0; } static int xonar_hdav_mixer_init(struct oxygen *chip) { return snd_ctl_add(chip->card, snd_ctl_new1(&os_128_control, chip)); } static int xonar_st_mixer_init(struct oxygen *chip) Loading @@ -759,6 +887,9 @@ static int xonar_st_mixer_init(struct oxygen *chip) if (err < 0) return err; } err = snd_ctl_add(chip->card, snd_ctl_new1(&os_128_control, chip)); if (err < 0) return err; return 0; } Loading @@ -771,7 +902,7 @@ static const struct oxygen_model model_xonar_d2 = { .cleanup = xonar_d2_cleanup, .suspend = xonar_d2_suspend, .resume = xonar_d2_resume, .get_i2s_mclk = oxygen_default_i2s_mclk, .get_i2s_mclk = get_pcm1796_i2s_mclk, .set_dac_params = set_pcm1796_params, .set_adc_params = xonar_set_cs53x1_params, .update_dac_volume = update_pcm1796_volume, Loading @@ -798,11 +929,12 @@ static const struct oxygen_model model_xonar_hdav = { .longname = "Asus Virtuoso 200", .chip = "AV200", .init = xonar_hdav_init, .mixer_init = xonar_hdav_mixer_init, .cleanup = xonar_hdav_cleanup, .suspend = xonar_hdav_suspend, .resume = xonar_hdav_resume, .pcm_hardware_filter = xonar_hdmi_pcm_hardware_filter, .get_i2s_mclk = oxygen_default_i2s_mclk, .get_i2s_mclk = get_pcm1796_i2s_mclk, .set_dac_params = set_hdav_params, .set_adc_params = xonar_set_cs53x1_params, .update_dac_volume = update_pcm1796_volume, Loading Loading @@ -833,7 +965,7 @@ static const struct oxygen_model model_xonar_st = { .cleanup = xonar_st_cleanup, .suspend = xonar_st_suspend, .resume = xonar_st_resume, .get_i2s_mclk = oxygen_default_i2s_mclk, .get_i2s_mclk = get_pcm1796_i2s_mclk, .set_dac_params = set_st_params, .set_adc_params = xonar_set_cs53x1_params, .update_dac_volume = update_pcm1796_volume, Loading