.mixer_init = generic_wm8785_mixer_init,
.cleanup = generic_cleanup,
.resume = generic_resume,
- .get_i2s_mclk = oxygen_default_i2s_mclk,
.set_dac_params = set_ak4396_params,
.set_adc_params = set_wm8785_params,
.update_dac_volume = update_ak4396_volume,
.dac_volume_max = 255,
.function_flags = OXYGEN_FUNCTION_SPI |
OXYGEN_FUNCTION_ENABLE_SPI_4_5,
+ .dac_mclks = OXYGEN_MCLKS(256, 256, 128),
+ .adc_mclks = OXYGEN_MCLKS(256, 256, 128),
.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
};
#define PCM_AC97 5
#define PCM_COUNT 6
+#define OXYGEN_MCLKS(f_single, f_double, f_quad) ((MCLK_##f_single << 0) | \
+ (MCLK_##f_double << 2) | \
+ (MCLK_##f_quad << 4))
+
#define OXYGEN_IO_SIZE 0x100
#define OXYGEN_EEPROM_ID 0x434d /* "CM" */
void (*resume)(struct oxygen *chip);
void (*pcm_hardware_filter)(unsigned int channel,
struct snd_pcm_hardware *hardware);
- unsigned int (*get_i2s_mclk)(struct oxygen *chip, unsigned int channel,
- struct snd_pcm_hw_params *hw_params);
void (*set_dac_params)(struct oxygen *chip,
struct snd_pcm_hw_params *params);
void (*set_adc_params)(struct oxygen *chip,
u8 dac_volume_max;
u8 misc_flags;
u8 function_flags;
+ u8 dac_mclks;
+ u8 adc_mclks;
u16 dac_i2s_format;
u16 adc_i2s_format;
};
/* oxygen_pcm.c */
int oxygen_pcm_init(struct oxygen *chip);
-unsigned int oxygen_default_i2s_mclk(struct oxygen *chip, unsigned int channel,
- struct snd_pcm_hw_params *hw_params);
/* oxygen_io.c */
(OXYGEN_FORMAT_16 << OXYGEN_MULTICH_FORMAT_SHIFT));
oxygen_write8(chip, OXYGEN_REC_CHANNELS, OXYGEN_REC_CHANNELS_2_2_2);
oxygen_write16(chip, OXYGEN_I2S_MULTICH_FORMAT,
- OXYGEN_RATE_48000 | chip->model.dac_i2s_format |
- OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |
- OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
+ OXYGEN_RATE_48000 |
+ chip->model.dac_i2s_format |
+ OXYGEN_I2S_MCLK(chip->model.dac_mclks) |
+ OXYGEN_I2S_BITS_16 |
+ OXYGEN_I2S_MASTER |
+ OXYGEN_I2S_BCLK_64);
if (chip->model.device_config & CAPTURE_0_FROM_I2S_1)
oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,
- OXYGEN_RATE_48000 | chip->model.adc_i2s_format |
- OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |
- OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
+ OXYGEN_RATE_48000 |
+ chip->model.adc_i2s_format |
+ OXYGEN_I2S_MCLK(chip->model.adc_mclks) |
+ OXYGEN_I2S_BITS_16 |
+ OXYGEN_I2S_MASTER |
+ OXYGEN_I2S_BCLK_64);
else
oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,
- OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK);
+ OXYGEN_I2S_MASTER |
+ OXYGEN_I2S_MUTE_MCLK);
if (chip->model.device_config & (CAPTURE_0_FROM_I2S_2 |
CAPTURE_2_FROM_I2S_2))
oxygen_write16(chip, OXYGEN_I2S_B_FORMAT,
- OXYGEN_RATE_48000 | chip->model.adc_i2s_format |
- OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |
- OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);
+ OXYGEN_RATE_48000 |
+ chip->model.adc_i2s_format |
+ OXYGEN_I2S_MCLK(chip->model.adc_mclks) |
+ OXYGEN_I2S_BITS_16 |
+ OXYGEN_I2S_MASTER |
+ OXYGEN_I2S_BCLK_64);
else
oxygen_write16(chip, OXYGEN_I2S_B_FORMAT,
- OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK);
+ OXYGEN_I2S_MASTER |
+ OXYGEN_I2S_MUTE_MCLK);
oxygen_write16(chip, OXYGEN_I2S_C_FORMAT,
- OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK);
+ OXYGEN_I2S_MASTER |
+ OXYGEN_I2S_MUTE_MCLK);
oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL,
OXYGEN_SPDIF_OUT_ENABLE |
OXYGEN_SPDIF_LOOPBACK);
}
}
-unsigned int oxygen_default_i2s_mclk(struct oxygen *chip,
- unsigned int channel,
- struct snd_pcm_hw_params *hw_params)
-{
- if (params_rate(hw_params) <= 96000)
- return OXYGEN_I2S_MCLK_256;
- else
- return OXYGEN_I2S_MCLK_128;
-}
-EXPORT_SYMBOL(oxygen_default_i2s_mclk);
-
static unsigned int oxygen_i2s_bits(struct snd_pcm_hw_params *hw_params)
{
if (params_format(hw_params) == SNDRV_PCM_FORMAT_S32_LE)
return 0;
}
+static u16 get_mclk(struct oxygen *chip, unsigned int channel,
+ struct snd_pcm_hw_params *params)
+{
+ unsigned int mclks, shift;
+
+ if (channel == PCM_MULTICH)
+ mclks = chip->model.dac_mclks;
+ else
+ mclks = chip->model.adc_mclks;
+
+ if (params_rate(params) <= 48000)
+ shift = 0;
+ else if (params_rate(params) <= 96000)
+ shift = 2;
+ else
+ shift = 4;
+
+ return OXYGEN_I2S_MCLK(mclks >> shift);
+}
+
static int oxygen_rec_a_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
{
OXYGEN_REC_FORMAT_A_MASK);
oxygen_write16_masked(chip, OXYGEN_I2S_A_FORMAT,
oxygen_rate(hw_params) |
- chip->model.get_i2s_mclk(chip, PCM_A, 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 |
if (!is_ac97)
oxygen_write16_masked(chip, OXYGEN_I2S_B_FORMAT,
oxygen_rate(hw_params) |
- chip->model.get_i2s_mclk(chip, PCM_B,
- 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_write16_masked(chip, OXYGEN_I2S_MULTICH_FORMAT,
oxygen_rate(hw_params) |
chip->model.dac_i2s_format |
- chip->model.get_i2s_mclk(chip, PCM_MULTICH,
- hw_params) |
+ get_mclk(chip, PCM_MULTICH, hw_params) |
oxygen_i2s_bits(hw_params),
OXYGEN_I2S_RATE_MASK |
OXYGEN_I2S_FORMAT_MASK |
#define OXYGEN_I2S_FORMAT_I2S 0x0000
#define OXYGEN_I2S_FORMAT_LJUST 0x0008
#define OXYGEN_I2S_MCLK_MASK 0x0030 /* MCLK/LRCK */
-#define OXYGEN_I2S_MCLK_128 0x0000
-#define OXYGEN_I2S_MCLK_256 0x0010
-#define OXYGEN_I2S_MCLK_512 0x0020
+#define OXYGEN_I2S_MCLK_SHIFT 4
+#define MCLK_128 0
+#define MCLK_256 1
+#define MCLK_512 2
+#define OXYGEN_I2S_MCLK(f) (((f) & 3) << OXYGEN_I2S_MCLK_SHIFT)
#define OXYGEN_I2S_BITS_MASK 0x00c0
#define OXYGEN_I2S_BITS_16 0x0000
#define OXYGEN_I2S_BITS_20 0x0040
.cleanup = xonar_d1_cleanup,
.suspend = xonar_d1_suspend,
.resume = xonar_d1_resume,
- .get_i2s_mclk = oxygen_default_i2s_mclk,
.set_dac_params = set_cs43xx_params,
.set_adc_params = xonar_set_cs53x1_params,
.update_dac_volume = update_cs43xx_volume,
.dac_volume_min = 127 - 60,
.dac_volume_max = 127,
.function_flags = OXYGEN_FUNCTION_2WIRE,
+ .dac_mclks = OXYGEN_MCLKS(256, 256, 128),
+ .adc_mclks = OXYGEN_MCLKS(256, 256, 128),
.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
};
data->h6 ? PCM1796_OS_64 : PCM1796_OS_128;
pcm1796_registers_init(chip);
data->current_rate = 48000;
- if (!data->h6)
- oxygen_write16_masked(chip, OXYGEN_I2S_MULTICH_FORMAT,
- OXYGEN_I2S_MCLK_512,
- OXYGEN_I2S_MCLK_MASK);
}
static void xonar_d2_init(struct oxygen *chip)
oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,
OXYGEN_RATE_48000 |
OXYGEN_I2S_FORMAT_I2S |
- (data->h6 ? OXYGEN_I2S_MCLK_256 : OXYGEN_I2S_MCLK_512) |
+ OXYGEN_I2S_MCLK(data->h6 ? MCLK_256 : MCLK_512) |
OXYGEN_I2S_BITS_16 |
OXYGEN_I2S_MASTER |
OXYGEN_I2S_BCLK_64);
xonar_stx_resume(chip);
}
-static unsigned int mclk_from_rate(struct oxygen *chip, unsigned int rate)
-{
- struct xonar_pcm179x *data = chip->model_data;
-
- if (rate <= 48000)
- return data->h6 ? OXYGEN_I2S_MCLK_256 : OXYGEN_I2S_MCLK_512;
- 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;
switch (rate) {
case 32000:
- if (data->h6)
- rate_mclk = OXYGEN_RATE_32000 | OXYGEN_I2S_MCLK_256;
- else
- rate_mclk = OXYGEN_RATE_32000 | OXYGEN_I2S_MCLK_512;
- break;
- case 44100:
- if (data->h6)
- rate_mclk = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_256;
- else
- rate_mclk = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_512;
- break;
- default: /* 48000 */
- if (data->h6)
- rate_mclk = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_256;
- else
- rate_mclk = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_512;
- break;
case 64000:
- rate_mclk = OXYGEN_RATE_32000 | OXYGEN_I2S_MCLK_256;
+ rate_mclk = OXYGEN_RATE_32000;
break;
+ case 44100:
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_512;
+ rate_mclk = OXYGEN_RATE_44100;
break;
+ default:
+ case 48000:
+ case 96000:
case 192000:
- rate_mclk = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_512;
+ rate_mclk = OXYGEN_RATE_48000;
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_256)
+
+ if (rate <= 96000 && (rate > 48000 || data->h6)) {
+ rate_mclk |= OXYGEN_I2S_MCLK(MCLK_256);
reg = CS2000_REF_CLK_DIV_1;
- else
+ } 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 */
}
.cleanup = xonar_d2_cleanup,
.suspend = xonar_d2_suspend,
.resume = xonar_d2_resume,
- .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,
.misc_flags = OXYGEN_MISC_MIDI,
.function_flags = OXYGEN_FUNCTION_SPI |
OXYGEN_FUNCTION_ENABLE_SPI_4_5,
+ .dac_mclks = OXYGEN_MCLKS(512, 128, 128),
+ .adc_mclks = OXYGEN_MCLKS(256, 256, 128),
.dac_i2s_format = OXYGEN_I2S_FORMAT_I2S,
.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
};
.suspend = xonar_hdav_suspend,
.resume = xonar_hdav_resume,
.pcm_hardware_filter = xonar_hdmi_pcm_hardware_filter,
- .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,
.dac_volume_max = 255,
.misc_flags = OXYGEN_MISC_MIDI,
.function_flags = OXYGEN_FUNCTION_2WIRE,
+ .dac_mclks = OXYGEN_MCLKS(512, 128, 128),
+ .adc_mclks = OXYGEN_MCLKS(256, 256, 128),
.dac_i2s_format = OXYGEN_I2S_FORMAT_I2S,
.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
};
.cleanup = xonar_st_cleanup,
.suspend = xonar_st_suspend,
.resume = xonar_st_resume,
- .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,
.dac_volume_min = 255 - 2*60,
.dac_volume_max = 255,
.function_flags = OXYGEN_FUNCTION_2WIRE,
+ .dac_mclks = OXYGEN_MCLKS(512, 128, 128),
+ .adc_mclks = OXYGEN_MCLKS(256, 256, 128),
.dac_i2s_format = OXYGEN_I2S_FORMAT_I2S,
.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
};
case GPIO_DB_H6:
chip->model.shortname = "Xonar HDAV1.3+H6";
chip->model.dac_channels_mixer = 8;
+ chip->model.dac_mclks = OXYGEN_MCLKS(256, 128, 128);
break;
}
break;
chip->model.control_filter = xonar_st_h6_control_filter;
chip->model.dac_channels_pcm = 8;
chip->model.dac_channels_mixer = 8;
+ chip->model.dac_mclks = OXYGEN_MCLKS(256, 128, 128);
break;
}
break;
.suspend = xonar_ds_suspend,
.resume = xonar_ds_resume,
.pcm_hardware_filter = wm8776_adc_hardware_filter,
- .get_i2s_mclk = oxygen_default_i2s_mclk,
.set_dac_params = set_wm87x6_dac_params,
.set_adc_params = set_wm8776_adc_params,
.update_dac_volume = update_wm87x6_volume,
.dac_volume_min = 255 - 2*60,
.dac_volume_max = 255,
.function_flags = OXYGEN_FUNCTION_SPI,
+ .dac_mclks = OXYGEN_MCLKS(256, 256, 128),
+ .adc_mclks = OXYGEN_MCLKS(256, 256, 128),
.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
};