static int oxygen_multich_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct oxygen *chip = snd_pcm_substream_chip(substream); int err; err = oxygen_hw_params(substream, hw_params); if (err < 0) return err; mutex_lock(&chip->mutex); spin_lock_irq(&chip->reg_lock); oxygen_write8_masked(chip, OXYGEN_PLAY_CHANNELS, oxygen_play_channels(hw_params), OXYGEN_PLAY_CHANNELS_MASK); oxygen_write8_masked(chip, OXYGEN_PLAY_FORMAT, oxygen_format(hw_params) << OXYGEN_MULTICH_FORMAT_SHIFT, OXYGEN_MULTICH_FORMAT_MASK); oxygen_write16_masked(chip, OXYGEN_I2S_MULTICH_FORMAT, oxygen_rate(hw_params) | chip->model.dac_i2s_format | get_mclk(chip, PCM_MULTICH, hw_params) | oxygen_i2s_bits(hw_params), OXYGEN_I2S_RATE_MASK | OXYGEN_I2S_FORMAT_MASK | OXYGEN_I2S_MCLK_MASK | OXYGEN_I2S_BITS_MASK); oxygen_update_spdif_source(chip); spin_unlock_irq(&chip->reg_lock); chip->model.set_dac_params(chip, hw_params); oxygen_update_dac_routing(chip); mutex_unlock(&chip->mutex); return 0; }
static int oxygen_rec_a_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct oxygen *chip = snd_pcm_substream_chip(substream); int err; err = oxygen_hw_params(substream, hw_params); if (err < 0) return err; spin_lock_irq(&chip->reg_lock); oxygen_write8_masked(chip, OXYGEN_REC_FORMAT, oxygen_format(hw_params) << OXYGEN_REC_FORMAT_A_SHIFT, OXYGEN_REC_FORMAT_A_MASK); oxygen_write16_masked(chip, OXYGEN_I2S_A_FORMAT, oxygen_rate(hw_params) | chip->model.adc_i2s_format | get_mclk(chip, PCM_A, hw_params) | oxygen_i2s_bits(hw_params), OXYGEN_I2S_RATE_MASK | OXYGEN_I2S_FORMAT_MASK | OXYGEN_I2S_MCLK_MASK | OXYGEN_I2S_BITS_MASK); spin_unlock_irq(&chip->reg_lock); mutex_lock(&chip->mutex); chip->model.set_adc_params(chip, hw_params); mutex_unlock(&chip->mutex); return 0; }
static void meridian_init(struct oxygen *chip) { oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_MERIDIAN_DIG_MASK); oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, GPIO_MERIDIAN_DIG_BOARD, GPIO_MERIDIAN_DIG_MASK); ak4396_init(chip); ak5385_init(chip); }
static void xonar_d1_line_mic_ac97_switch(struct oxygen *chip, unsigned int reg, unsigned int mute) { if (reg == AC97_LINE) { spin_lock_irq(&chip->reg_lock); oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, mute ? GPIO_D1_INPUT_ROUTE : 0, GPIO_D1_INPUT_ROUTE); spin_unlock_irq(&chip->reg_lock); } }
static void set_cs53x1_params(struct oxygen *chip, struct snd_pcm_hw_params *params) { unsigned int value; if (params_rate(params) <= 54000) value = GPIO_CS53x1_M_SINGLE; else if (params_rate(params) <= 108000) value = GPIO_CS53x1_M_DOUBLE; else value = GPIO_CS53x1_M_QUAD; oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, value, GPIO_CS53x1_M_MASK); }
static void set_ak5385_params(struct oxygen *chip, struct snd_pcm_hw_params *params) { unsigned int value; if (params_rate(params) <= 54000) value = GPIO_AK5385_DFS_NORMAL; else if (params_rate(params) <= 108000) value = GPIO_AK5385_DFS_DOUBLE; else value = GPIO_AK5385_DFS_QUAD; oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, value, GPIO_AK5385_DFS_MASK); }
static void update_cs2000_rate(struct oxygen *chip, unsigned int rate) { struct xonar_pcm179x *data = chip->model_data; u8 rate_mclk, reg; switch (rate) { 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) reg = CS2000_REF_CLK_DIV_1; else reg = CS2000_REF_CLK_DIV_2; cs2000_write_cached(chip, CS2000_FUN_CFG_1, reg); }
static int output_switch_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) { struct oxygen *chip = ctl->private_data; struct dg *data = chip->model_data; u8 reg; int changed; if (value->value.enumerated.item[0] > 2) return -EINVAL; mutex_lock(&chip->mutex); changed = value->value.enumerated.item[0] != data->output_sel; if (changed) { data->output_sel = value->value.enumerated.item[0]; reg = data->cs4245_regs[CS4245_SIGNAL_SEL] & ~CS4245_A_OUT_SEL_MASK; reg |= data->output_sel == 2 ? CS4245_A_OUT_SEL_DAC : CS4245_A_OUT_SEL_HIZ; cs4245_write_cached(chip, CS4245_SIGNAL_SEL, reg); cs4245_write_cached(chip, CS4245_DAC_A_CTRL, data->output_sel ? data->hp_vol_att : 0); cs4245_write_cached(chip, CS4245_DAC_B_CTRL, data->output_sel ? data->hp_vol_att : 0); oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, data->output_sel == 1 ? GPIO_HP_REAR : 0, GPIO_HP_REAR); oxygen_write8_masked(chip, OXYGEN_PLAY_ROUTING, data->output_sel == 0 ? OXYGEN_PLAY_MUTE01 : OXYGEN_PLAY_MUTE23 | OXYGEN_PLAY_MUTE45 | OXYGEN_PLAY_MUTE67, OXYGEN_PLAY_MUTE01 | OXYGEN_PLAY_MUTE23 | OXYGEN_PLAY_MUTE45 | OXYGEN_PLAY_MUTE67); } mutex_unlock(&chip->mutex); return changed; }
static void xonar_common_init(struct oxygen *chip) { struct xonar_data *data = chip->model_data; if (data->ext_power_reg) { oxygen_set_bits8(chip, data->ext_power_int_reg, data->ext_power_bit); chip->interrupt_mask |= OXYGEN_INT_GPIO; chip->model.gpio_changed = xonar_gpio_changed; data->has_power = !!(oxygen_read8(chip, data->ext_power_reg) & data->ext_power_bit); } oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CS53x1_M_MASK | data->output_enable_bit); oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, GPIO_CS53x1_M_SINGLE, GPIO_CS53x1_M_MASK); oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC); xonar_enable_output(chip); }
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 int input_sel_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) { static const u8 sel_values[4] = { CS4245_SEL_MIC, CS4245_SEL_INPUT_1, CS4245_SEL_INPUT_2, CS4245_SEL_INPUT_4 }; struct oxygen *chip = ctl->private_data; struct dg *data = chip->model_data; int changed; if (value->value.enumerated.item[0] > 3) return -EINVAL; mutex_lock(&chip->mutex); changed = value->value.enumerated.item[0] != data->input_sel; if (changed) { data->input_sel = value->value.enumerated.item[0]; cs4245_write(chip, CS4245_ANALOG_IN, (data->cs4245_regs[CS4245_ANALOG_IN] & ~CS4245_SEL_MASK) | sel_values[data->input_sel]); cs4245_write_cached(chip, CS4245_PGA_A_CTRL, data->input_vol[data->input_sel][0]); cs4245_write_cached(chip, CS4245_PGA_B_CTRL, data->input_vol[data->input_sel][1]); oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, data->input_sel ? 0 : GPIO_INPUT_ROUTE, GPIO_INPUT_ROUTE); } mutex_unlock(&chip->mutex); return changed; }
static int oxygen_rec_b_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct oxygen *chip = snd_pcm_substream_chip(substream); int is_ac97; int err; err = oxygen_hw_params(substream, hw_params); if (err < 0) return err; is_ac97 = chip->has_ac97_1 && (chip->model.device_config & CAPTURE_2_FROM_AC97_1); spin_lock_irq(&chip->reg_lock); oxygen_write8_masked(chip, OXYGEN_REC_FORMAT, oxygen_format(hw_params) << OXYGEN_REC_FORMAT_B_SHIFT, OXYGEN_REC_FORMAT_B_MASK); if (!is_ac97) oxygen_write16_masked(chip, OXYGEN_I2S_B_FORMAT, oxygen_rate(hw_params) | chip->model.adc_i2s_format | get_mclk(chip, PCM_B, hw_params) | oxygen_i2s_bits(hw_params), OXYGEN_I2S_RATE_MASK | OXYGEN_I2S_FORMAT_MASK | OXYGEN_I2S_MCLK_MASK | OXYGEN_I2S_BITS_MASK); spin_unlock_irq(&chip->reg_lock); if (!is_ac97) { mutex_lock(&chip->mutex); chip->model.set_adc_params(chip, hw_params); mutex_unlock(&chip->mutex); } return 0; }
static void update_cs2000_rate(struct oxygen *chip, unsigned int rate) { struct xonar_pcm179x *data = chip->model_data; u8 rate_mclk, reg; switch (rate) { case 32000: case 64000: rate_mclk = OXYGEN_RATE_32000; break; case 44100: case 88200: case 176400: rate_mclk = OXYGEN_RATE_44100; break; default: case 48000: case 96000: case 192000: rate_mclk = OXYGEN_RATE_48000; break; } if (rate <= 96000 && (rate > 48000 || data->h6)) { rate_mclk |= OXYGEN_I2S_MCLK(MCLK_256); reg = CS2000_REF_CLK_DIV_1; } else { rate_mclk |= OXYGEN_I2S_MCLK(MCLK_512); reg = CS2000_REF_CLK_DIV_2; } oxygen_write16_masked(chip, OXYGEN_I2S_A_FORMAT, rate_mclk, OXYGEN_I2S_RATE_MASK | OXYGEN_I2S_MCLK_MASK); cs2000_write_cached(chip, CS2000_FUN_CFG_1, reg); msleep(3); /* PLL lock delay */ }
void xonar_init_cs53x1(struct oxygen *chip) { oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CS53x1_M_MASK); oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, GPIO_CS53x1_M_SINGLE, GPIO_CS53x1_M_MASK); }