0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/pci.h>
0010 #include <linux/delay.h>
0011 #include <sound/control.h>
0012 #include <sound/core.h>
0013 #include <sound/info.h>
0014 #include <sound/pcm.h>
0015 #include <sound/tlv.h>
0016 #include "oxygen.h"
0017 #include "xonar_dg.h"
0018 #include "cs4245.h"
0019
0020
0021
0022 static int output_select_apply(struct oxygen *chip)
0023 {
0024 struct dg *data = chip->model_data;
0025
0026 data->cs4245_shadow[CS4245_SIGNAL_SEL] &= ~CS4245_A_OUT_SEL_MASK;
0027 if (data->output_sel == PLAYBACK_DST_HP) {
0028
0029 oxygen_set_bits8(chip, OXYGEN_GPIO_DATA, GPIO_HP_REAR);
0030 } else if (data->output_sel == PLAYBACK_DST_HP_FP) {
0031
0032
0033
0034
0035 oxygen_clear_bits8(chip, OXYGEN_GPIO_DATA, GPIO_HP_REAR);
0036 data->cs4245_shadow[CS4245_SIGNAL_SEL] |= CS4245_A_OUT_SEL_DAC;
0037 } else {
0038
0039
0040
0041
0042 oxygen_clear_bits8(chip, OXYGEN_GPIO_DATA, GPIO_HP_REAR);
0043 }
0044 return cs4245_write_spi(chip, CS4245_SIGNAL_SEL);
0045 }
0046
0047 static int output_select_info(struct snd_kcontrol *ctl,
0048 struct snd_ctl_elem_info *info)
0049 {
0050 static const char *const names[3] = {
0051 "Stereo Headphones",
0052 "Stereo Headphones FP",
0053 "Multichannel",
0054 };
0055
0056 return snd_ctl_enum_info(info, 1, 3, names);
0057 }
0058
0059 static int output_select_get(struct snd_kcontrol *ctl,
0060 struct snd_ctl_elem_value *value)
0061 {
0062 struct oxygen *chip = ctl->private_data;
0063 struct dg *data = chip->model_data;
0064
0065 mutex_lock(&chip->mutex);
0066 value->value.enumerated.item[0] = data->output_sel;
0067 mutex_unlock(&chip->mutex);
0068 return 0;
0069 }
0070
0071 static int output_select_put(struct snd_kcontrol *ctl,
0072 struct snd_ctl_elem_value *value)
0073 {
0074 struct oxygen *chip = ctl->private_data;
0075 struct dg *data = chip->model_data;
0076 unsigned int new = value->value.enumerated.item[0];
0077 int changed = 0;
0078 int ret;
0079
0080 mutex_lock(&chip->mutex);
0081 if (data->output_sel != new) {
0082 data->output_sel = new;
0083 ret = output_select_apply(chip);
0084 changed = ret >= 0 ? 1 : ret;
0085 oxygen_update_dac_routing(chip);
0086 }
0087 mutex_unlock(&chip->mutex);
0088
0089 return changed;
0090 }
0091
0092
0093
0094 static int hp_stereo_volume_info(struct snd_kcontrol *ctl,
0095 struct snd_ctl_elem_info *info)
0096 {
0097 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0098 info->count = 2;
0099 info->value.integer.min = 0;
0100 info->value.integer.max = 255;
0101 return 0;
0102 }
0103
0104 static int hp_stereo_volume_get(struct snd_kcontrol *ctl,
0105 struct snd_ctl_elem_value *val)
0106 {
0107 struct oxygen *chip = ctl->private_data;
0108 struct dg *data = chip->model_data;
0109 unsigned int tmp;
0110
0111 mutex_lock(&chip->mutex);
0112 tmp = (~data->cs4245_shadow[CS4245_DAC_A_CTRL]) & 255;
0113 val->value.integer.value[0] = tmp;
0114 tmp = (~data->cs4245_shadow[CS4245_DAC_B_CTRL]) & 255;
0115 val->value.integer.value[1] = tmp;
0116 mutex_unlock(&chip->mutex);
0117 return 0;
0118 }
0119
0120 static int hp_stereo_volume_put(struct snd_kcontrol *ctl,
0121 struct snd_ctl_elem_value *val)
0122 {
0123 struct oxygen *chip = ctl->private_data;
0124 struct dg *data = chip->model_data;
0125 int ret;
0126 int changed = 0;
0127 long new1 = val->value.integer.value[0];
0128 long new2 = val->value.integer.value[1];
0129
0130 if ((new1 > 255) || (new1 < 0) || (new2 > 255) || (new2 < 0))
0131 return -EINVAL;
0132
0133 mutex_lock(&chip->mutex);
0134 if ((data->cs4245_shadow[CS4245_DAC_A_CTRL] != ~new1) ||
0135 (data->cs4245_shadow[CS4245_DAC_B_CTRL] != ~new2)) {
0136 data->cs4245_shadow[CS4245_DAC_A_CTRL] = ~new1;
0137 data->cs4245_shadow[CS4245_DAC_B_CTRL] = ~new2;
0138 ret = cs4245_write_spi(chip, CS4245_DAC_A_CTRL);
0139 if (ret >= 0)
0140 ret = cs4245_write_spi(chip, CS4245_DAC_B_CTRL);
0141 changed = ret >= 0 ? 1 : ret;
0142 }
0143 mutex_unlock(&chip->mutex);
0144
0145 return changed;
0146 }
0147
0148
0149
0150 static int hp_mute_get(struct snd_kcontrol *ctl,
0151 struct snd_ctl_elem_value *val)
0152 {
0153 struct oxygen *chip = ctl->private_data;
0154 struct dg *data = chip->model_data;
0155
0156 mutex_lock(&chip->mutex);
0157 val->value.integer.value[0] =
0158 !(data->cs4245_shadow[CS4245_DAC_CTRL_1] & CS4245_MUTE_DAC);
0159 mutex_unlock(&chip->mutex);
0160 return 0;
0161 }
0162
0163 static int hp_mute_put(struct snd_kcontrol *ctl,
0164 struct snd_ctl_elem_value *val)
0165 {
0166 struct oxygen *chip = ctl->private_data;
0167 struct dg *data = chip->model_data;
0168 int ret;
0169 int changed;
0170
0171 if (val->value.integer.value[0] > 1)
0172 return -EINVAL;
0173 mutex_lock(&chip->mutex);
0174 data->cs4245_shadow[CS4245_DAC_CTRL_1] &= ~CS4245_MUTE_DAC;
0175 data->cs4245_shadow[CS4245_DAC_CTRL_1] |=
0176 (~val->value.integer.value[0] << 2) & CS4245_MUTE_DAC;
0177 ret = cs4245_write_spi(chip, CS4245_DAC_CTRL_1);
0178 changed = ret >= 0 ? 1 : ret;
0179 mutex_unlock(&chip->mutex);
0180 return changed;
0181 }
0182
0183
0184
0185 static int input_volume_apply(struct oxygen *chip, char left, char right)
0186 {
0187 struct dg *data = chip->model_data;
0188 int ret;
0189
0190 data->cs4245_shadow[CS4245_PGA_A_CTRL] = left;
0191 data->cs4245_shadow[CS4245_PGA_B_CTRL] = right;
0192 ret = cs4245_write_spi(chip, CS4245_PGA_A_CTRL);
0193 if (ret < 0)
0194 return ret;
0195 return cs4245_write_spi(chip, CS4245_PGA_B_CTRL);
0196 }
0197
0198 static int input_vol_info(struct snd_kcontrol *ctl,
0199 struct snd_ctl_elem_info *info)
0200 {
0201 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0202 info->count = 2;
0203 info->value.integer.min = 2 * -12;
0204 info->value.integer.max = 2 * 12;
0205 return 0;
0206 }
0207
0208 static int input_vol_get(struct snd_kcontrol *ctl,
0209 struct snd_ctl_elem_value *value)
0210 {
0211 struct oxygen *chip = ctl->private_data;
0212 struct dg *data = chip->model_data;
0213 unsigned int idx = ctl->private_value;
0214
0215 mutex_lock(&chip->mutex);
0216 value->value.integer.value[0] = data->input_vol[idx][0];
0217 value->value.integer.value[1] = data->input_vol[idx][1];
0218 mutex_unlock(&chip->mutex);
0219 return 0;
0220 }
0221
0222 static int input_vol_put(struct snd_kcontrol *ctl,
0223 struct snd_ctl_elem_value *value)
0224 {
0225 struct oxygen *chip = ctl->private_data;
0226 struct dg *data = chip->model_data;
0227 unsigned int idx = ctl->private_value;
0228 int changed = 0;
0229 int ret = 0;
0230
0231 if (value->value.integer.value[0] < 2 * -12 ||
0232 value->value.integer.value[0] > 2 * 12 ||
0233 value->value.integer.value[1] < 2 * -12 ||
0234 value->value.integer.value[1] > 2 * 12)
0235 return -EINVAL;
0236 mutex_lock(&chip->mutex);
0237 changed = data->input_vol[idx][0] != value->value.integer.value[0] ||
0238 data->input_vol[idx][1] != value->value.integer.value[1];
0239 if (changed) {
0240 data->input_vol[idx][0] = value->value.integer.value[0];
0241 data->input_vol[idx][1] = value->value.integer.value[1];
0242 if (idx == data->input_sel) {
0243 ret = input_volume_apply(chip,
0244 data->input_vol[idx][0],
0245 data->input_vol[idx][1]);
0246 }
0247 changed = ret >= 0 ? 1 : ret;
0248 }
0249 mutex_unlock(&chip->mutex);
0250 return changed;
0251 }
0252
0253
0254
0255 static int input_source_apply(struct oxygen *chip)
0256 {
0257 struct dg *data = chip->model_data;
0258
0259 data->cs4245_shadow[CS4245_ANALOG_IN] &= ~CS4245_SEL_MASK;
0260 if (data->input_sel == CAPTURE_SRC_FP_MIC)
0261 data->cs4245_shadow[CS4245_ANALOG_IN] |= CS4245_SEL_INPUT_2;
0262 else if (data->input_sel == CAPTURE_SRC_LINE)
0263 data->cs4245_shadow[CS4245_ANALOG_IN] |= CS4245_SEL_INPUT_4;
0264 else if (data->input_sel != CAPTURE_SRC_MIC)
0265 data->cs4245_shadow[CS4245_ANALOG_IN] |= CS4245_SEL_INPUT_1;
0266 return cs4245_write_spi(chip, CS4245_ANALOG_IN);
0267 }
0268
0269 static int input_sel_info(struct snd_kcontrol *ctl,
0270 struct snd_ctl_elem_info *info)
0271 {
0272 static const char *const names[4] = {
0273 "Mic", "Front Mic", "Line", "Aux"
0274 };
0275
0276 return snd_ctl_enum_info(info, 1, 4, names);
0277 }
0278
0279 static int input_sel_get(struct snd_kcontrol *ctl,
0280 struct snd_ctl_elem_value *value)
0281 {
0282 struct oxygen *chip = ctl->private_data;
0283 struct dg *data = chip->model_data;
0284
0285 mutex_lock(&chip->mutex);
0286 value->value.enumerated.item[0] = data->input_sel;
0287 mutex_unlock(&chip->mutex);
0288 return 0;
0289 }
0290
0291 static int input_sel_put(struct snd_kcontrol *ctl,
0292 struct snd_ctl_elem_value *value)
0293 {
0294 struct oxygen *chip = ctl->private_data;
0295 struct dg *data = chip->model_data;
0296 int changed;
0297 int ret;
0298
0299 if (value->value.enumerated.item[0] > 3)
0300 return -EINVAL;
0301
0302 mutex_lock(&chip->mutex);
0303 changed = value->value.enumerated.item[0] != data->input_sel;
0304 if (changed) {
0305 data->input_sel = value->value.enumerated.item[0];
0306
0307 ret = input_source_apply(chip);
0308 if (ret >= 0)
0309 ret = input_volume_apply(chip,
0310 data->input_vol[data->input_sel][0],
0311 data->input_vol[data->input_sel][1]);
0312 changed = ret >= 0 ? 1 : ret;
0313 }
0314 mutex_unlock(&chip->mutex);
0315 return changed;
0316 }
0317
0318
0319
0320 static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)
0321 {
0322 static const char *const names[2] = { "Active", "Frozen" };
0323
0324 return snd_ctl_enum_info(info, 1, 2, names);
0325 }
0326
0327 static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
0328 {
0329 struct oxygen *chip = ctl->private_data;
0330 struct dg *data = chip->model_data;
0331
0332 value->value.enumerated.item[0] =
0333 !!(data->cs4245_shadow[CS4245_ADC_CTRL] & CS4245_HPF_FREEZE);
0334 return 0;
0335 }
0336
0337 static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
0338 {
0339 struct oxygen *chip = ctl->private_data;
0340 struct dg *data = chip->model_data;
0341 u8 reg;
0342 int changed;
0343
0344 mutex_lock(&chip->mutex);
0345 reg = data->cs4245_shadow[CS4245_ADC_CTRL] & ~CS4245_HPF_FREEZE;
0346 if (value->value.enumerated.item[0])
0347 reg |= CS4245_HPF_FREEZE;
0348 changed = reg != data->cs4245_shadow[CS4245_ADC_CTRL];
0349 if (changed) {
0350 data->cs4245_shadow[CS4245_ADC_CTRL] = reg;
0351 cs4245_write_spi(chip, CS4245_ADC_CTRL);
0352 }
0353 mutex_unlock(&chip->mutex);
0354 return changed;
0355 }
0356
0357 #define INPUT_VOLUME(xname, index) { \
0358 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
0359 .name = xname, \
0360 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
0361 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
0362 .info = input_vol_info, \
0363 .get = input_vol_get, \
0364 .put = input_vol_put, \
0365 .tlv = { .p = pga_db_scale }, \
0366 .private_value = index, \
0367 }
0368 static const DECLARE_TLV_DB_MINMAX(hp_db_scale, -12550, 0);
0369 static const DECLARE_TLV_DB_MINMAX(pga_db_scale, -1200, 1200);
0370 static const struct snd_kcontrol_new dg_controls[] = {
0371 {
0372 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0373 .name = "Analog Output Playback Enum",
0374 .info = output_select_info,
0375 .get = output_select_get,
0376 .put = output_select_put,
0377 },
0378 {
0379 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0380 .name = "Headphone Playback Volume",
0381 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
0382 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
0383 .info = hp_stereo_volume_info,
0384 .get = hp_stereo_volume_get,
0385 .put = hp_stereo_volume_put,
0386 .tlv = { .p = hp_db_scale, },
0387 },
0388 {
0389 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0390 .name = "Headphone Playback Switch",
0391 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
0392 .info = snd_ctl_boolean_mono_info,
0393 .get = hp_mute_get,
0394 .put = hp_mute_put,
0395 },
0396 INPUT_VOLUME("Mic Capture Volume", CAPTURE_SRC_MIC),
0397 INPUT_VOLUME("Front Mic Capture Volume", CAPTURE_SRC_FP_MIC),
0398 INPUT_VOLUME("Line Capture Volume", CAPTURE_SRC_LINE),
0399 INPUT_VOLUME("Aux Capture Volume", CAPTURE_SRC_AUX),
0400 {
0401 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0402 .name = "Capture Source",
0403 .info = input_sel_info,
0404 .get = input_sel_get,
0405 .put = input_sel_put,
0406 },
0407 {
0408 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0409 .name = "ADC High-pass Filter Capture Enum",
0410 .info = hpf_info,
0411 .get = hpf_get,
0412 .put = hpf_put,
0413 },
0414 };
0415
0416 static int dg_control_filter(struct snd_kcontrol_new *template)
0417 {
0418 if (!strncmp(template->name, "Master Playback ", 16))
0419 return 1;
0420 return 0;
0421 }
0422
0423 static int dg_mixer_init(struct oxygen *chip)
0424 {
0425 unsigned int i;
0426 int err;
0427
0428 output_select_apply(chip);
0429 input_source_apply(chip);
0430 oxygen_update_dac_routing(chip);
0431
0432 for (i = 0; i < ARRAY_SIZE(dg_controls); ++i) {
0433 err = snd_ctl_add(chip->card,
0434 snd_ctl_new1(&dg_controls[i], chip));
0435 if (err < 0)
0436 return err;
0437 }
0438
0439 return 0;
0440 }
0441
0442 const struct oxygen_model model_xonar_dg = {
0443 .longname = "C-Media Oxygen HD Audio",
0444 .chip = "CMI8786",
0445 .init = dg_init,
0446 .control_filter = dg_control_filter,
0447 .mixer_init = dg_mixer_init,
0448 .cleanup = dg_cleanup,
0449 .suspend = dg_suspend,
0450 .resume = dg_resume,
0451 .set_dac_params = set_cs4245_dac_params,
0452 .set_adc_params = set_cs4245_adc_params,
0453 .adjust_dac_routing = adjust_dg_dac_routing,
0454 .dump_registers = dump_cs4245_registers,
0455 .model_data_size = sizeof(struct dg),
0456 .device_config = PLAYBACK_0_TO_I2S |
0457 PLAYBACK_1_TO_SPDIF |
0458 CAPTURE_0_FROM_I2S_1 |
0459 CAPTURE_1_FROM_SPDIF,
0460 .dac_channels_pcm = 6,
0461 .dac_channels_mixer = 0,
0462 .function_flags = OXYGEN_FUNCTION_SPI,
0463 .dac_mclks = OXYGEN_MCLKS(256, 128, 128),
0464 .adc_mclks = OXYGEN_MCLKS(256, 128, 128),
0465 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
0466 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
0467 };