0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 #include <linux/pci.h>
0047 #include <linux/delay.h>
0048 #include <sound/control.h>
0049 #include <sound/core.h>
0050 #include <sound/info.h>
0051 #include <sound/pcm.h>
0052 #include <sound/tlv.h>
0053 #include "oxygen.h"
0054 #include "xonar_dg.h"
0055 #include "cs4245.h"
0056
0057 int cs4245_write_spi(struct oxygen *chip, u8 reg)
0058 {
0059 struct dg *data = chip->model_data;
0060 unsigned int packet;
0061
0062 packet = reg << 8;
0063 packet |= (CS4245_SPI_ADDRESS | CS4245_SPI_WRITE) << 16;
0064 packet |= data->cs4245_shadow[reg];
0065
0066 return oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
0067 OXYGEN_SPI_DATA_LENGTH_3 |
0068 OXYGEN_SPI_CLOCK_1280 |
0069 (0 << OXYGEN_SPI_CODEC_SHIFT) |
0070 OXYGEN_SPI_CEN_LATCH_CLOCK_HI,
0071 packet);
0072 }
0073
0074 int cs4245_read_spi(struct oxygen *chip, u8 addr)
0075 {
0076 struct dg *data = chip->model_data;
0077 int ret;
0078
0079 ret = oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
0080 OXYGEN_SPI_DATA_LENGTH_2 |
0081 OXYGEN_SPI_CEN_LATCH_CLOCK_HI |
0082 OXYGEN_SPI_CLOCK_1280 | (0 << OXYGEN_SPI_CODEC_SHIFT),
0083 ((CS4245_SPI_ADDRESS | CS4245_SPI_WRITE) << 8) | addr);
0084 if (ret < 0)
0085 return ret;
0086
0087 ret = oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
0088 OXYGEN_SPI_DATA_LENGTH_2 |
0089 OXYGEN_SPI_CEN_LATCH_CLOCK_HI |
0090 OXYGEN_SPI_CLOCK_1280 | (0 << OXYGEN_SPI_CODEC_SHIFT),
0091 (CS4245_SPI_ADDRESS | CS4245_SPI_READ) << 8);
0092 if (ret < 0)
0093 return ret;
0094
0095 data->cs4245_shadow[addr] = oxygen_read8(chip, OXYGEN_SPI_DATA1);
0096
0097 return 0;
0098 }
0099
0100 int cs4245_shadow_control(struct oxygen *chip, enum cs4245_shadow_operation op)
0101 {
0102 struct dg *data = chip->model_data;
0103 unsigned char addr;
0104 int ret;
0105
0106 for (addr = 1; addr < ARRAY_SIZE(data->cs4245_shadow); addr++) {
0107 ret = (op == CS4245_SAVE_TO_SHADOW ?
0108 cs4245_read_spi(chip, addr) :
0109 cs4245_write_spi(chip, addr));
0110 if (ret < 0)
0111 return ret;
0112 }
0113 return 0;
0114 }
0115
0116 static void cs4245_init(struct oxygen *chip)
0117 {
0118 struct dg *data = chip->model_data;
0119
0120
0121 cs4245_shadow_control(chip, CS4245_SAVE_TO_SHADOW);
0122
0123
0124
0125
0126
0127
0128 data->cs4245_shadow[CS4245_POWER_CTRL] = 0;
0129 data->cs4245_shadow[CS4245_SIGNAL_SEL] =
0130 CS4245_A_OUT_SEL_DAC | CS4245_ASYNCH;
0131 data->cs4245_shadow[CS4245_DAC_CTRL_1] =
0132 CS4245_DAC_FM_SINGLE | CS4245_DAC_DIF_LJUST;
0133 data->cs4245_shadow[CS4245_DAC_CTRL_2] =
0134 CS4245_DAC_SOFT | CS4245_DAC_ZERO | CS4245_INVERT_DAC;
0135 data->cs4245_shadow[CS4245_ADC_CTRL] =
0136 CS4245_ADC_FM_SINGLE | CS4245_ADC_DIF_LJUST;
0137 data->cs4245_shadow[CS4245_ANALOG_IN] =
0138 CS4245_PGA_SOFT | CS4245_PGA_ZERO;
0139 data->cs4245_shadow[CS4245_PGA_B_CTRL] = 0;
0140 data->cs4245_shadow[CS4245_PGA_A_CTRL] = 0;
0141 data->cs4245_shadow[CS4245_DAC_A_CTRL] = 8;
0142 data->cs4245_shadow[CS4245_DAC_B_CTRL] = 8;
0143
0144 cs4245_shadow_control(chip, CS4245_LOAD_FROM_SHADOW);
0145 snd_component_add(chip->card, "CS4245");
0146 }
0147
0148 void dg_init(struct oxygen *chip)
0149 {
0150 struct dg *data = chip->model_data;
0151
0152 data->output_sel = PLAYBACK_DST_HP_FP;
0153 data->input_sel = CAPTURE_SRC_MIC;
0154
0155 cs4245_init(chip);
0156 oxygen_write16(chip, OXYGEN_GPIO_CONTROL,
0157 GPIO_OUTPUT_ENABLE | GPIO_HP_REAR | GPIO_INPUT_ROUTE);
0158
0159 msleep(2500);
0160 oxygen_write16(chip, OXYGEN_GPIO_DATA,
0161 GPIO_OUTPUT_ENABLE | GPIO_INPUT_ROUTE);
0162 }
0163
0164 void dg_cleanup(struct oxygen *chip)
0165 {
0166 oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE);
0167 }
0168
0169 void dg_suspend(struct oxygen *chip)
0170 {
0171 dg_cleanup(chip);
0172 }
0173
0174 void dg_resume(struct oxygen *chip)
0175 {
0176 cs4245_shadow_control(chip, CS4245_LOAD_FROM_SHADOW);
0177 msleep(2500);
0178 oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE);
0179 }
0180
0181 void set_cs4245_dac_params(struct oxygen *chip,
0182 struct snd_pcm_hw_params *params)
0183 {
0184 struct dg *data = chip->model_data;
0185 unsigned char dac_ctrl;
0186 unsigned char mclk_freq;
0187
0188 dac_ctrl = data->cs4245_shadow[CS4245_DAC_CTRL_1] & ~CS4245_DAC_FM_MASK;
0189 mclk_freq = data->cs4245_shadow[CS4245_MCLK_FREQ] & ~CS4245_MCLK1_MASK;
0190 if (params_rate(params) <= 50000) {
0191 dac_ctrl |= CS4245_DAC_FM_SINGLE;
0192 mclk_freq |= CS4245_MCLK_1 << CS4245_MCLK1_SHIFT;
0193 } else if (params_rate(params) <= 100000) {
0194 dac_ctrl |= CS4245_DAC_FM_DOUBLE;
0195 mclk_freq |= CS4245_MCLK_1 << CS4245_MCLK1_SHIFT;
0196 } else {
0197 dac_ctrl |= CS4245_DAC_FM_QUAD;
0198 mclk_freq |= CS4245_MCLK_2 << CS4245_MCLK1_SHIFT;
0199 }
0200 data->cs4245_shadow[CS4245_DAC_CTRL_1] = dac_ctrl;
0201 data->cs4245_shadow[CS4245_MCLK_FREQ] = mclk_freq;
0202 cs4245_write_spi(chip, CS4245_DAC_CTRL_1);
0203 cs4245_write_spi(chip, CS4245_MCLK_FREQ);
0204 }
0205
0206 void set_cs4245_adc_params(struct oxygen *chip,
0207 struct snd_pcm_hw_params *params)
0208 {
0209 struct dg *data = chip->model_data;
0210 unsigned char adc_ctrl;
0211 unsigned char mclk_freq;
0212
0213 adc_ctrl = data->cs4245_shadow[CS4245_ADC_CTRL] & ~CS4245_ADC_FM_MASK;
0214 mclk_freq = data->cs4245_shadow[CS4245_MCLK_FREQ] & ~CS4245_MCLK2_MASK;
0215 if (params_rate(params) <= 50000) {
0216 adc_ctrl |= CS4245_ADC_FM_SINGLE;
0217 mclk_freq |= CS4245_MCLK_1 << CS4245_MCLK2_SHIFT;
0218 } else if (params_rate(params) <= 100000) {
0219 adc_ctrl |= CS4245_ADC_FM_DOUBLE;
0220 mclk_freq |= CS4245_MCLK_1 << CS4245_MCLK2_SHIFT;
0221 } else {
0222 adc_ctrl |= CS4245_ADC_FM_QUAD;
0223 mclk_freq |= CS4245_MCLK_2 << CS4245_MCLK2_SHIFT;
0224 }
0225 data->cs4245_shadow[CS4245_ADC_CTRL] = adc_ctrl;
0226 data->cs4245_shadow[CS4245_MCLK_FREQ] = mclk_freq;
0227 cs4245_write_spi(chip, CS4245_ADC_CTRL);
0228 cs4245_write_spi(chip, CS4245_MCLK_FREQ);
0229 }
0230
0231 static inline unsigned int shift_bits(unsigned int value,
0232 unsigned int shift_from,
0233 unsigned int shift_to,
0234 unsigned int mask)
0235 {
0236 if (shift_from < shift_to)
0237 return (value << (shift_to - shift_from)) & mask;
0238 else
0239 return (value >> (shift_from - shift_to)) & mask;
0240 }
0241
0242 unsigned int adjust_dg_dac_routing(struct oxygen *chip,
0243 unsigned int play_routing)
0244 {
0245 struct dg *data = chip->model_data;
0246
0247 switch (data->output_sel) {
0248 case PLAYBACK_DST_HP:
0249 case PLAYBACK_DST_HP_FP:
0250 oxygen_write8_masked(chip, OXYGEN_PLAY_ROUTING,
0251 OXYGEN_PLAY_MUTE23 | OXYGEN_PLAY_MUTE45 |
0252 OXYGEN_PLAY_MUTE67, OXYGEN_PLAY_MUTE_MASK);
0253 break;
0254 case PLAYBACK_DST_MULTICH:
0255 oxygen_write8_masked(chip, OXYGEN_PLAY_ROUTING,
0256 OXYGEN_PLAY_MUTE01, OXYGEN_PLAY_MUTE_MASK);
0257 break;
0258 }
0259 return (play_routing & OXYGEN_PLAY_DAC0_SOURCE_MASK) |
0260 shift_bits(play_routing,
0261 OXYGEN_PLAY_DAC2_SOURCE_SHIFT,
0262 OXYGEN_PLAY_DAC1_SOURCE_SHIFT,
0263 OXYGEN_PLAY_DAC1_SOURCE_MASK) |
0264 shift_bits(play_routing,
0265 OXYGEN_PLAY_DAC1_SOURCE_SHIFT,
0266 OXYGEN_PLAY_DAC2_SOURCE_SHIFT,
0267 OXYGEN_PLAY_DAC2_SOURCE_MASK) |
0268 shift_bits(play_routing,
0269 OXYGEN_PLAY_DAC0_SOURCE_SHIFT,
0270 OXYGEN_PLAY_DAC3_SOURCE_SHIFT,
0271 OXYGEN_PLAY_DAC3_SOURCE_MASK);
0272 }
0273
0274 void dump_cs4245_registers(struct oxygen *chip,
0275 struct snd_info_buffer *buffer)
0276 {
0277 struct dg *data = chip->model_data;
0278 unsigned int addr;
0279
0280 snd_iprintf(buffer, "\nCS4245:");
0281 cs4245_read_spi(chip, CS4245_INT_STATUS);
0282 for (addr = 1; addr < ARRAY_SIZE(data->cs4245_shadow); addr++)
0283 snd_iprintf(buffer, " %02x", data->cs4245_shadow[addr]);
0284 snd_iprintf(buffer, "\n");
0285 }