diff options
Diffstat (limited to 'sound/pci/oxygen/oxygen.c')
-rw-r--r-- | sound/pci/oxygen/oxygen.c | 356 |
1 files changed, 318 insertions, 38 deletions
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c index 98a8eb3c92f7..d7e8ddd9a67b 100644 --- a/sound/pci/oxygen/oxygen.c +++ b/sound/pci/oxygen/oxygen.c | |||
@@ -20,19 +20,32 @@ | |||
20 | /* | 20 | /* |
21 | * CMI8788: | 21 | * CMI8788: |
22 | * | 22 | * |
23 | * SPI 0 -> 1st AK4396 (front) | 23 | * SPI 0 -> 1st AK4396 (front) |
24 | * SPI 1 -> 2nd AK4396 (surround) | 24 | * SPI 1 -> 2nd AK4396 (surround) |
25 | * SPI 2 -> 3rd AK4396 (center/LFE) | 25 | * SPI 2 -> 3rd AK4396 (center/LFE) |
26 | * SPI 3 -> WM8785 | 26 | * SPI 3 -> WM8785 |
27 | * SPI 4 -> 4th AK4396 (back) | 27 | * SPI 4 -> 4th AK4396 (back) |
28 | * | 28 | * |
29 | * GPIO 0 -> DFS0 of AK5385 | 29 | * GPIO 0 -> DFS0 of AK5385 |
30 | * GPIO 1 -> DFS1 of AK5385 | 30 | * GPIO 1 -> DFS1 of AK5385 |
31 | * GPIO 8 -> enable headphone amplifier on HT-Omega models | 31 | * |
32 | * X-Meridian models: | ||
33 | * GPIO 4 -> enable extension S/PDIF input | ||
34 | * GPIO 6 -> enable on-board S/PDIF input | ||
35 | * | ||
36 | * Claro models: | ||
37 | * GPIO 6 -> S/PDIF from optical (0) or coaxial (1) input | ||
38 | * GPIO 8 -> enable headphone amplifier | ||
32 | * | 39 | * |
33 | * CM9780: | 40 | * CM9780: |
34 | * | 41 | * |
35 | * GPO 0 -> route line-in (0) or AC97 output (1) to ADC input | 42 | * LINE_OUT -> input of ADC |
43 | * | ||
44 | * AUX_IN <- aux | ||
45 | * CD_IN <- CD | ||
46 | * MIC_IN <- mic | ||
47 | * | ||
48 | * GPO 0 -> route line-in (0) or AC97 output (1) to ADC input | ||
36 | */ | 49 | */ |
37 | 50 | ||
38 | #include <linux/delay.h> | 51 | #include <linux/delay.h> |
@@ -41,18 +54,22 @@ | |||
41 | #include <sound/ac97_codec.h> | 54 | #include <sound/ac97_codec.h> |
42 | #include <sound/control.h> | 55 | #include <sound/control.h> |
43 | #include <sound/core.h> | 56 | #include <sound/core.h> |
57 | #include <sound/info.h> | ||
44 | #include <sound/initval.h> | 58 | #include <sound/initval.h> |
45 | #include <sound/pcm.h> | 59 | #include <sound/pcm.h> |
46 | #include <sound/pcm_params.h> | 60 | #include <sound/pcm_params.h> |
47 | #include <sound/tlv.h> | 61 | #include <sound/tlv.h> |
48 | #include "oxygen.h" | 62 | #include "oxygen.h" |
63 | #include "xonar_dg.h" | ||
49 | #include "ak4396.h" | 64 | #include "ak4396.h" |
50 | #include "wm8785.h" | 65 | #include "wm8785.h" |
51 | 66 | ||
52 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); | 67 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); |
53 | MODULE_DESCRIPTION("C-Media CMI8788 driver"); | 68 | MODULE_DESCRIPTION("C-Media CMI8788 driver"); |
54 | MODULE_LICENSE("GPL v2"); | 69 | MODULE_LICENSE("GPL v2"); |
55 | MODULE_SUPPORTED_DEVICE("{{C-Media,CMI8788}}"); | 70 | MODULE_SUPPORTED_DEVICE("{{C-Media,CMI8786}" |
71 | ",{C-Media,CMI8787}" | ||
72 | ",{C-Media,CMI8788}}"); | ||
56 | 73 | ||
57 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; | 74 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; |
58 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; | 75 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; |
@@ -66,24 +83,46 @@ module_param_array(enable, bool, NULL, 0444); | |||
66 | MODULE_PARM_DESC(enable, "enable card"); | 83 | MODULE_PARM_DESC(enable, "enable card"); |
67 | 84 | ||
68 | enum { | 85 | enum { |
69 | MODEL_CMEDIA_REF, /* C-Media's reference design */ | 86 | MODEL_CMEDIA_REF, |
70 | MODEL_MERIDIAN, /* AuzenTech X-Meridian */ | 87 | MODEL_MERIDIAN, |
71 | MODEL_CLARO, /* HT-Omega Claro */ | 88 | MODEL_MERIDIAN_2G, |
72 | MODEL_CLARO_HALO, /* HT-Omega Claro halo */ | 89 | MODEL_CLARO, |
90 | MODEL_CLARO_HALO, | ||
91 | MODEL_FANTASIA, | ||
92 | MODEL_SERENADE, | ||
93 | MODEL_2CH_OUTPUT, | ||
94 | MODEL_HG2PCI, | ||
95 | MODEL_XONAR_DG, | ||
73 | }; | 96 | }; |
74 | 97 | ||
75 | static DEFINE_PCI_DEVICE_TABLE(oxygen_ids) = { | 98 | static DEFINE_PCI_DEVICE_TABLE(oxygen_ids) = { |
99 | /* C-Media's reference design */ | ||
76 | { OXYGEN_PCI_SUBID(0x10b0, 0x0216), .driver_data = MODEL_CMEDIA_REF }, | 100 | { OXYGEN_PCI_SUBID(0x10b0, 0x0216), .driver_data = MODEL_CMEDIA_REF }, |
101 | { OXYGEN_PCI_SUBID(0x10b0, 0x0217), .driver_data = MODEL_CMEDIA_REF }, | ||
77 | { OXYGEN_PCI_SUBID(0x10b0, 0x0218), .driver_data = MODEL_CMEDIA_REF }, | 102 | { OXYGEN_PCI_SUBID(0x10b0, 0x0218), .driver_data = MODEL_CMEDIA_REF }, |
78 | { OXYGEN_PCI_SUBID(0x10b0, 0x0219), .driver_data = MODEL_CMEDIA_REF }, | 103 | { OXYGEN_PCI_SUBID(0x10b0, 0x0219), .driver_data = MODEL_CMEDIA_REF }, |
79 | { OXYGEN_PCI_SUBID(0x13f6, 0x0001), .driver_data = MODEL_CMEDIA_REF }, | 104 | { OXYGEN_PCI_SUBID(0x13f6, 0x0001), .driver_data = MODEL_CMEDIA_REF }, |
80 | { OXYGEN_PCI_SUBID(0x13f6, 0x0010), .driver_data = MODEL_CMEDIA_REF }, | 105 | { OXYGEN_PCI_SUBID(0x13f6, 0x0010), .driver_data = MODEL_CMEDIA_REF }, |
81 | { OXYGEN_PCI_SUBID(0x13f6, 0x8788), .driver_data = MODEL_CMEDIA_REF }, | 106 | { OXYGEN_PCI_SUBID(0x13f6, 0x8788), .driver_data = MODEL_CMEDIA_REF }, |
82 | { OXYGEN_PCI_SUBID(0x13f6, 0xffff), .driver_data = MODEL_CMEDIA_REF }, | ||
83 | { OXYGEN_PCI_SUBID(0x147a, 0xa017), .driver_data = MODEL_CMEDIA_REF }, | 107 | { OXYGEN_PCI_SUBID(0x147a, 0xa017), .driver_data = MODEL_CMEDIA_REF }, |
84 | { OXYGEN_PCI_SUBID(0x1a58, 0x0910), .driver_data = MODEL_CMEDIA_REF }, | 108 | { OXYGEN_PCI_SUBID(0x1a58, 0x0910), .driver_data = MODEL_CMEDIA_REF }, |
109 | /* Asus Xonar DG */ | ||
110 | { OXYGEN_PCI_SUBID(0x1043, 0x8467), .driver_data = MODEL_XONAR_DG }, | ||
111 | /* PCI 2.0 HD Audio */ | ||
112 | { OXYGEN_PCI_SUBID(0x13f6, 0x8782), .driver_data = MODEL_2CH_OUTPUT }, | ||
113 | /* Kuroutoshikou CMI8787-HG2PCI */ | ||
114 | { OXYGEN_PCI_SUBID(0x13f6, 0xffff), .driver_data = MODEL_HG2PCI }, | ||
115 | /* TempoTec HiFier Fantasia */ | ||
116 | { OXYGEN_PCI_SUBID(0x14c3, 0x1710), .driver_data = MODEL_FANTASIA }, | ||
117 | /* TempoTec HiFier Serenade */ | ||
118 | { OXYGEN_PCI_SUBID(0x14c3, 0x1711), .driver_data = MODEL_SERENADE }, | ||
119 | /* AuzenTech X-Meridian */ | ||
85 | { OXYGEN_PCI_SUBID(0x415a, 0x5431), .driver_data = MODEL_MERIDIAN }, | 120 | { OXYGEN_PCI_SUBID(0x415a, 0x5431), .driver_data = MODEL_MERIDIAN }, |
121 | /* AuzenTech X-Meridian 2G */ | ||
122 | { OXYGEN_PCI_SUBID(0x5431, 0x017a), .driver_data = MODEL_MERIDIAN_2G }, | ||
123 | /* HT-Omega Claro */ | ||
86 | { OXYGEN_PCI_SUBID(0x7284, 0x9761), .driver_data = MODEL_CLARO }, | 124 | { OXYGEN_PCI_SUBID(0x7284, 0x9761), .driver_data = MODEL_CLARO }, |
125 | /* HT-Omega Claro halo */ | ||
87 | { OXYGEN_PCI_SUBID(0x7284, 0x9781), .driver_data = MODEL_CLARO_HALO }, | 126 | { OXYGEN_PCI_SUBID(0x7284, 0x9781), .driver_data = MODEL_CLARO_HALO }, |
88 | { } | 127 | { } |
89 | }; | 128 | }; |
@@ -95,9 +134,15 @@ MODULE_DEVICE_TABLE(pci, oxygen_ids); | |||
95 | #define GPIO_AK5385_DFS_DOUBLE 0x0001 | 134 | #define GPIO_AK5385_DFS_DOUBLE 0x0001 |
96 | #define GPIO_AK5385_DFS_QUAD 0x0002 | 135 | #define GPIO_AK5385_DFS_QUAD 0x0002 |
97 | 136 | ||
137 | #define GPIO_MERIDIAN_DIG_MASK 0x0050 | ||
138 | #define GPIO_MERIDIAN_DIG_EXT 0x0010 | ||
139 | #define GPIO_MERIDIAN_DIG_BOARD 0x0040 | ||
140 | |||
141 | #define GPIO_CLARO_DIG_COAX 0x0040 | ||
98 | #define GPIO_CLARO_HP 0x0100 | 142 | #define GPIO_CLARO_HP 0x0100 |
99 | 143 | ||
100 | struct generic_data { | 144 | struct generic_data { |
145 | unsigned int dacs; | ||
101 | u8 ak4396_regs[4][5]; | 146 | u8 ak4396_regs[4][5]; |
102 | u16 wm8785_regs[3]; | 147 | u16 wm8785_regs[3]; |
103 | }; | 148 | }; |
@@ -148,7 +193,7 @@ static void ak4396_registers_init(struct oxygen *chip) | |||
148 | struct generic_data *data = chip->model_data; | 193 | struct generic_data *data = chip->model_data; |
149 | unsigned int i; | 194 | unsigned int i; |
150 | 195 | ||
151 | for (i = 0; i < 4; ++i) { | 196 | for (i = 0; i < data->dacs; ++i) { |
152 | ak4396_write(chip, i, AK4396_CONTROL_1, | 197 | ak4396_write(chip, i, AK4396_CONTROL_1, |
153 | AK4396_DIF_24_MSB | AK4396_RSTN); | 198 | AK4396_DIF_24_MSB | AK4396_RSTN); |
154 | ak4396_write(chip, i, AK4396_CONTROL_2, | 199 | ak4396_write(chip, i, AK4396_CONTROL_2, |
@@ -166,6 +211,7 @@ static void ak4396_init(struct oxygen *chip) | |||
166 | { | 211 | { |
167 | struct generic_data *data = chip->model_data; | 212 | struct generic_data *data = chip->model_data; |
168 | 213 | ||
214 | data->dacs = chip->model.dac_channels_pcm / 2; | ||
169 | data->ak4396_regs[0][AK4396_CONTROL_2] = | 215 | data->ak4396_regs[0][AK4396_CONTROL_2] = |
170 | AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL; | 216 | AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL; |
171 | ak4396_registers_init(chip); | 217 | ak4396_registers_init(chip); |
@@ -207,6 +253,10 @@ static void generic_init(struct oxygen *chip) | |||
207 | 253 | ||
208 | static void meridian_init(struct oxygen *chip) | 254 | static void meridian_init(struct oxygen *chip) |
209 | { | 255 | { |
256 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, | ||
257 | GPIO_MERIDIAN_DIG_MASK); | ||
258 | oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, | ||
259 | GPIO_MERIDIAN_DIG_BOARD, GPIO_MERIDIAN_DIG_MASK); | ||
210 | ak4396_init(chip); | 260 | ak4396_init(chip); |
211 | ak5385_init(chip); | 261 | ak5385_init(chip); |
212 | } | 262 | } |
@@ -220,6 +270,8 @@ static void claro_enable_hp(struct oxygen *chip) | |||
220 | 270 | ||
221 | static void claro_init(struct oxygen *chip) | 271 | static void claro_init(struct oxygen *chip) |
222 | { | 272 | { |
273 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CLARO_DIG_COAX); | ||
274 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_DIG_COAX); | ||
223 | ak4396_init(chip); | 275 | ak4396_init(chip); |
224 | wm8785_init(chip); | 276 | wm8785_init(chip); |
225 | claro_enable_hp(chip); | 277 | claro_enable_hp(chip); |
@@ -227,11 +279,24 @@ static void claro_init(struct oxygen *chip) | |||
227 | 279 | ||
228 | static void claro_halo_init(struct oxygen *chip) | 280 | static void claro_halo_init(struct oxygen *chip) |
229 | { | 281 | { |
282 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CLARO_DIG_COAX); | ||
283 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_DIG_COAX); | ||
230 | ak4396_init(chip); | 284 | ak4396_init(chip); |
231 | ak5385_init(chip); | 285 | ak5385_init(chip); |
232 | claro_enable_hp(chip); | 286 | claro_enable_hp(chip); |
233 | } | 287 | } |
234 | 288 | ||
289 | static void fantasia_init(struct oxygen *chip) | ||
290 | { | ||
291 | ak4396_init(chip); | ||
292 | snd_component_add(chip->card, "CS5340"); | ||
293 | } | ||
294 | |||
295 | static void stereo_output_init(struct oxygen *chip) | ||
296 | { | ||
297 | ak4396_init(chip); | ||
298 | } | ||
299 | |||
235 | static void generic_cleanup(struct oxygen *chip) | 300 | static void generic_cleanup(struct oxygen *chip) |
236 | { | 301 | { |
237 | } | 302 | } |
@@ -268,6 +333,11 @@ static void claro_resume(struct oxygen *chip) | |||
268 | claro_enable_hp(chip); | 333 | claro_enable_hp(chip); |
269 | } | 334 | } |
270 | 335 | ||
336 | static void stereo_resume(struct oxygen *chip) | ||
337 | { | ||
338 | ak4396_registers_init(chip); | ||
339 | } | ||
340 | |||
271 | static void set_ak4396_params(struct oxygen *chip, | 341 | static void set_ak4396_params(struct oxygen *chip, |
272 | struct snd_pcm_hw_params *params) | 342 | struct snd_pcm_hw_params *params) |
273 | { | 343 | { |
@@ -286,7 +356,7 @@ static void set_ak4396_params(struct oxygen *chip, | |||
286 | msleep(1); /* wait for the new MCLK to become stable */ | 356 | msleep(1); /* wait for the new MCLK to become stable */ |
287 | 357 | ||
288 | if (value != data->ak4396_regs[0][AK4396_CONTROL_2]) { | 358 | if (value != data->ak4396_regs[0][AK4396_CONTROL_2]) { |
289 | for (i = 0; i < 4; ++i) { | 359 | for (i = 0; i < data->dacs; ++i) { |
290 | ak4396_write(chip, i, AK4396_CONTROL_1, | 360 | ak4396_write(chip, i, AK4396_CONTROL_1, |
291 | AK4396_DIF_24_MSB); | 361 | AK4396_DIF_24_MSB); |
292 | ak4396_write(chip, i, AK4396_CONTROL_2, value); | 362 | ak4396_write(chip, i, AK4396_CONTROL_2, value); |
@@ -298,9 +368,10 @@ static void set_ak4396_params(struct oxygen *chip, | |||
298 | 368 | ||
299 | static void update_ak4396_volume(struct oxygen *chip) | 369 | static void update_ak4396_volume(struct oxygen *chip) |
300 | { | 370 | { |
371 | struct generic_data *data = chip->model_data; | ||
301 | unsigned int i; | 372 | unsigned int i; |
302 | 373 | ||
303 | for (i = 0; i < 4; ++i) { | 374 | for (i = 0; i < data->dacs; ++i) { |
304 | ak4396_write_cached(chip, i, AK4396_LCH_ATT, | 375 | ak4396_write_cached(chip, i, AK4396_LCH_ATT, |
305 | chip->dac_volume[i * 2]); | 376 | chip->dac_volume[i * 2]); |
306 | ak4396_write_cached(chip, i, AK4396_RCH_ATT, | 377 | ak4396_write_cached(chip, i, AK4396_RCH_ATT, |
@@ -317,7 +388,7 @@ static void update_ak4396_mute(struct oxygen *chip) | |||
317 | value = data->ak4396_regs[0][AK4396_CONTROL_2] & ~AK4396_SMUTE; | 388 | value = data->ak4396_regs[0][AK4396_CONTROL_2] & ~AK4396_SMUTE; |
318 | if (chip->dac_mute) | 389 | if (chip->dac_mute) |
319 | value |= AK4396_SMUTE; | 390 | value |= AK4396_SMUTE; |
320 | for (i = 0; i < 4; ++i) | 391 | for (i = 0; i < data->dacs; ++i) |
321 | ak4396_write_cached(chip, i, AK4396_CONTROL_2, value); | 392 | ak4396_write_cached(chip, i, AK4396_CONTROL_2, value); |
322 | } | 393 | } |
323 | 394 | ||
@@ -356,6 +427,10 @@ static void set_ak5385_params(struct oxygen *chip, | |||
356 | value, GPIO_AK5385_DFS_MASK); | 427 | value, GPIO_AK5385_DFS_MASK); |
357 | } | 428 | } |
358 | 429 | ||
430 | static void set_no_params(struct oxygen *chip, struct snd_pcm_hw_params *params) | ||
431 | { | ||
432 | } | ||
433 | |||
359 | static int rolloff_info(struct snd_kcontrol *ctl, | 434 | static int rolloff_info(struct snd_kcontrol *ctl, |
360 | struct snd_ctl_elem_info *info) | 435 | struct snd_ctl_elem_info *info) |
361 | { | 436 | { |
@@ -363,13 +438,7 @@ static int rolloff_info(struct snd_kcontrol *ctl, | |||
363 | "Sharp Roll-off", "Slow Roll-off" | 438 | "Sharp Roll-off", "Slow Roll-off" |
364 | }; | 439 | }; |
365 | 440 | ||
366 | info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 441 | return snd_ctl_enum_info(info, 1, 2, names); |
367 | info->count = 1; | ||
368 | info->value.enumerated.items = 2; | ||
369 | if (info->value.enumerated.item >= 2) | ||
370 | info->value.enumerated.item = 1; | ||
371 | strcpy(info->value.enumerated.name, names[info->value.enumerated.item]); | ||
372 | return 0; | ||
373 | } | 442 | } |
374 | 443 | ||
375 | static int rolloff_get(struct snd_kcontrol *ctl, | 444 | static int rolloff_get(struct snd_kcontrol *ctl, |
@@ -400,7 +469,7 @@ static int rolloff_put(struct snd_kcontrol *ctl, | |||
400 | reg &= ~AK4396_SLOW; | 469 | reg &= ~AK4396_SLOW; |
401 | changed = reg != data->ak4396_regs[0][AK4396_CONTROL_2]; | 470 | changed = reg != data->ak4396_regs[0][AK4396_CONTROL_2]; |
402 | if (changed) { | 471 | if (changed) { |
403 | for (i = 0; i < 4; ++i) | 472 | for (i = 0; i < data->dacs; ++i) |
404 | ak4396_write(chip, i, AK4396_CONTROL_2, reg); | 473 | ak4396_write(chip, i, AK4396_CONTROL_2, reg); |
405 | } | 474 | } |
406 | mutex_unlock(&chip->mutex); | 475 | mutex_unlock(&chip->mutex); |
@@ -421,13 +490,7 @@ static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) | |||
421 | "None", "High-pass Filter" | 490 | "None", "High-pass Filter" |
422 | }; | 491 | }; |
423 | 492 | ||
424 | info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 493 | return snd_ctl_enum_info(info, 1, 2, names); |
425 | info->count = 1; | ||
426 | info->value.enumerated.items = 2; | ||
427 | if (info->value.enumerated.item >= 2) | ||
428 | info->value.enumerated.item = 1; | ||
429 | strcpy(info->value.enumerated.name, names[info->value.enumerated.item]); | ||
430 | return 0; | ||
431 | } | 494 | } |
432 | 495 | ||
433 | static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) | 496 | static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) |
@@ -466,6 +529,100 @@ static const struct snd_kcontrol_new hpf_control = { | |||
466 | .put = hpf_put, | 529 | .put = hpf_put, |
467 | }; | 530 | }; |
468 | 531 | ||
532 | static int meridian_dig_source_info(struct snd_kcontrol *ctl, | ||
533 | struct snd_ctl_elem_info *info) | ||
534 | { | ||
535 | static const char *const names[2] = { "On-board", "Extension" }; | ||
536 | |||
537 | return snd_ctl_enum_info(info, 1, 2, names); | ||
538 | } | ||
539 | |||
540 | static int claro_dig_source_info(struct snd_kcontrol *ctl, | ||
541 | struct snd_ctl_elem_info *info) | ||
542 | { | ||
543 | static const char *const names[2] = { "Optical", "Coaxial" }; | ||
544 | |||
545 | return snd_ctl_enum_info(info, 1, 2, names); | ||
546 | } | ||
547 | |||
548 | static int meridian_dig_source_get(struct snd_kcontrol *ctl, | ||
549 | struct snd_ctl_elem_value *value) | ||
550 | { | ||
551 | struct oxygen *chip = ctl->private_data; | ||
552 | |||
553 | value->value.enumerated.item[0] = | ||
554 | !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & | ||
555 | GPIO_MERIDIAN_DIG_EXT); | ||
556 | return 0; | ||
557 | } | ||
558 | |||
559 | static int claro_dig_source_get(struct snd_kcontrol *ctl, | ||
560 | struct snd_ctl_elem_value *value) | ||
561 | { | ||
562 | struct oxygen *chip = ctl->private_data; | ||
563 | |||
564 | value->value.enumerated.item[0] = | ||
565 | !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & | ||
566 | GPIO_CLARO_DIG_COAX); | ||
567 | return 0; | ||
568 | } | ||
569 | |||
570 | static int meridian_dig_source_put(struct snd_kcontrol *ctl, | ||
571 | struct snd_ctl_elem_value *value) | ||
572 | { | ||
573 | struct oxygen *chip = ctl->private_data; | ||
574 | u16 old_reg, new_reg; | ||
575 | int changed; | ||
576 | |||
577 | mutex_lock(&chip->mutex); | ||
578 | old_reg = oxygen_read16(chip, OXYGEN_GPIO_DATA); | ||
579 | new_reg = old_reg & ~GPIO_MERIDIAN_DIG_MASK; | ||
580 | if (value->value.enumerated.item[0] == 0) | ||
581 | new_reg |= GPIO_MERIDIAN_DIG_BOARD; | ||
582 | else | ||
583 | new_reg |= GPIO_MERIDIAN_DIG_EXT; | ||
584 | changed = new_reg != old_reg; | ||
585 | if (changed) | ||
586 | oxygen_write16(chip, OXYGEN_GPIO_DATA, new_reg); | ||
587 | mutex_unlock(&chip->mutex); | ||
588 | return changed; | ||
589 | } | ||
590 | |||
591 | static int claro_dig_source_put(struct snd_kcontrol *ctl, | ||
592 | struct snd_ctl_elem_value *value) | ||
593 | { | ||
594 | struct oxygen *chip = ctl->private_data; | ||
595 | u16 old_reg, new_reg; | ||
596 | int changed; | ||
597 | |||
598 | mutex_lock(&chip->mutex); | ||
599 | old_reg = oxygen_read16(chip, OXYGEN_GPIO_DATA); | ||
600 | new_reg = old_reg & ~GPIO_CLARO_DIG_COAX; | ||
601 | if (value->value.enumerated.item[0]) | ||
602 | new_reg |= GPIO_CLARO_DIG_COAX; | ||
603 | changed = new_reg != old_reg; | ||
604 | if (changed) | ||
605 | oxygen_write16(chip, OXYGEN_GPIO_DATA, new_reg); | ||
606 | mutex_unlock(&chip->mutex); | ||
607 | return changed; | ||
608 | } | ||
609 | |||
610 | static const struct snd_kcontrol_new meridian_dig_source_control = { | ||
611 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
612 | .name = "IEC958 Source Capture Enum", | ||
613 | .info = meridian_dig_source_info, | ||
614 | .get = meridian_dig_source_get, | ||
615 | .put = meridian_dig_source_put, | ||
616 | }; | ||
617 | |||
618 | static const struct snd_kcontrol_new claro_dig_source_control = { | ||
619 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
620 | .name = "IEC958 Source Capture Enum", | ||
621 | .info = claro_dig_source_info, | ||
622 | .get = claro_dig_source_get, | ||
623 | .put = claro_dig_source_put, | ||
624 | }; | ||
625 | |||
469 | static int generic_mixer_init(struct oxygen *chip) | 626 | static int generic_mixer_init(struct oxygen *chip) |
470 | { | 627 | { |
471 | return snd_ctl_add(chip->card, snd_ctl_new1(&rolloff_control, chip)); | 628 | return snd_ctl_add(chip->card, snd_ctl_new1(&rolloff_control, chip)); |
@@ -484,6 +641,81 @@ static int generic_wm8785_mixer_init(struct oxygen *chip) | |||
484 | return 0; | 641 | return 0; |
485 | } | 642 | } |
486 | 643 | ||
644 | static int meridian_mixer_init(struct oxygen *chip) | ||
645 | { | ||
646 | int err; | ||
647 | |||
648 | err = generic_mixer_init(chip); | ||
649 | if (err < 0) | ||
650 | return err; | ||
651 | err = snd_ctl_add(chip->card, | ||
652 | snd_ctl_new1(&meridian_dig_source_control, chip)); | ||
653 | if (err < 0) | ||
654 | return err; | ||
655 | return 0; | ||
656 | } | ||
657 | |||
658 | static int claro_mixer_init(struct oxygen *chip) | ||
659 | { | ||
660 | int err; | ||
661 | |||
662 | err = generic_wm8785_mixer_init(chip); | ||
663 | if (err < 0) | ||
664 | return err; | ||
665 | err = snd_ctl_add(chip->card, | ||
666 | snd_ctl_new1(&claro_dig_source_control, chip)); | ||
667 | if (err < 0) | ||
668 | return err; | ||
669 | return 0; | ||
670 | } | ||
671 | |||
672 | static int claro_halo_mixer_init(struct oxygen *chip) | ||
673 | { | ||
674 | int err; | ||
675 | |||
676 | err = generic_mixer_init(chip); | ||
677 | if (err < 0) | ||
678 | return err; | ||
679 | err = snd_ctl_add(chip->card, | ||
680 | snd_ctl_new1(&claro_dig_source_control, chip)); | ||
681 | if (err < 0) | ||
682 | return err; | ||
683 | return 0; | ||
684 | } | ||
685 | |||
686 | static void dump_ak4396_registers(struct oxygen *chip, | ||
687 | struct snd_info_buffer *buffer) | ||
688 | { | ||
689 | struct generic_data *data = chip->model_data; | ||
690 | unsigned int dac, i; | ||
691 | |||
692 | for (dac = 0; dac < data->dacs; ++dac) { | ||
693 | snd_iprintf(buffer, "\nAK4396 %u:", dac + 1); | ||
694 | for (i = 0; i < 5; ++i) | ||
695 | snd_iprintf(buffer, " %02x", data->ak4396_regs[dac][i]); | ||
696 | } | ||
697 | snd_iprintf(buffer, "\n"); | ||
698 | } | ||
699 | |||
700 | static void dump_wm8785_registers(struct oxygen *chip, | ||
701 | struct snd_info_buffer *buffer) | ||
702 | { | ||
703 | struct generic_data *data = chip->model_data; | ||
704 | unsigned int i; | ||
705 | |||
706 | snd_iprintf(buffer, "\nWM8785:"); | ||
707 | for (i = 0; i < 3; ++i) | ||
708 | snd_iprintf(buffer, " %03x", data->wm8785_regs[i]); | ||
709 | snd_iprintf(buffer, "\n"); | ||
710 | } | ||
711 | |||
712 | static void dump_oxygen_registers(struct oxygen *chip, | ||
713 | struct snd_info_buffer *buffer) | ||
714 | { | ||
715 | dump_ak4396_registers(chip, buffer); | ||
716 | dump_wm8785_registers(chip, buffer); | ||
717 | } | ||
718 | |||
487 | static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); | 719 | static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); |
488 | 720 | ||
489 | static const struct oxygen_model model_generic = { | 721 | static const struct oxygen_model model_generic = { |
@@ -494,11 +726,11 @@ static const struct oxygen_model model_generic = { | |||
494 | .mixer_init = generic_wm8785_mixer_init, | 726 | .mixer_init = generic_wm8785_mixer_init, |
495 | .cleanup = generic_cleanup, | 727 | .cleanup = generic_cleanup, |
496 | .resume = generic_resume, | 728 | .resume = generic_resume, |
497 | .get_i2s_mclk = oxygen_default_i2s_mclk, | ||
498 | .set_dac_params = set_ak4396_params, | 729 | .set_dac_params = set_ak4396_params, |
499 | .set_adc_params = set_wm8785_params, | 730 | .set_adc_params = set_wm8785_params, |
500 | .update_dac_volume = update_ak4396_volume, | 731 | .update_dac_volume = update_ak4396_volume, |
501 | .update_dac_mute = update_ak4396_mute, | 732 | .update_dac_mute = update_ak4396_mute, |
733 | .dump_registers = dump_oxygen_registers, | ||
502 | .dac_tlv = ak4396_db_scale, | 734 | .dac_tlv = ak4396_db_scale, |
503 | .model_data_size = sizeof(struct generic_data), | 735 | .model_data_size = sizeof(struct generic_data), |
504 | .device_config = PLAYBACK_0_TO_I2S | | 736 | .device_config = PLAYBACK_0_TO_I2S | |
@@ -508,11 +740,14 @@ static const struct oxygen_model model_generic = { | |||
508 | CAPTURE_1_FROM_SPDIF | | 740 | CAPTURE_1_FROM_SPDIF | |
509 | CAPTURE_2_FROM_AC97_1 | | 741 | CAPTURE_2_FROM_AC97_1 | |
510 | AC97_CD_INPUT, | 742 | AC97_CD_INPUT, |
511 | .dac_channels = 8, | 743 | .dac_channels_pcm = 8, |
744 | .dac_channels_mixer = 8, | ||
512 | .dac_volume_min = 0, | 745 | .dac_volume_min = 0, |
513 | .dac_volume_max = 255, | 746 | .dac_volume_max = 255, |
514 | .function_flags = OXYGEN_FUNCTION_SPI | | 747 | .function_flags = OXYGEN_FUNCTION_SPI | |
515 | OXYGEN_FUNCTION_ENABLE_SPI_4_5, | 748 | OXYGEN_FUNCTION_ENABLE_SPI_4_5, |
749 | .dac_mclks = OXYGEN_MCLKS(256, 128, 128), | ||
750 | .adc_mclks = OXYGEN_MCLKS(256, 256, 128), | ||
516 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 751 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
517 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 752 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
518 | }; | 753 | }; |
@@ -520,42 +755,87 @@ static const struct oxygen_model model_generic = { | |||
520 | static int __devinit get_oxygen_model(struct oxygen *chip, | 755 | static int __devinit get_oxygen_model(struct oxygen *chip, |
521 | const struct pci_device_id *id) | 756 | const struct pci_device_id *id) |
522 | { | 757 | { |
758 | static const char *const names[] = { | ||
759 | [MODEL_MERIDIAN] = "AuzenTech X-Meridian", | ||
760 | [MODEL_MERIDIAN_2G] = "AuzenTech X-Meridian 2G", | ||
761 | [MODEL_CLARO] = "HT-Omega Claro", | ||
762 | [MODEL_CLARO_HALO] = "HT-Omega Claro halo", | ||
763 | [MODEL_FANTASIA] = "TempoTec HiFier Fantasia", | ||
764 | [MODEL_SERENADE] = "TempoTec HiFier Serenade", | ||
765 | [MODEL_HG2PCI] = "CMI8787-HG2PCI", | ||
766 | }; | ||
767 | |||
523 | chip->model = model_generic; | 768 | chip->model = model_generic; |
524 | switch (id->driver_data) { | 769 | switch (id->driver_data) { |
525 | case MODEL_MERIDIAN: | 770 | case MODEL_MERIDIAN: |
771 | case MODEL_MERIDIAN_2G: | ||
526 | chip->model.init = meridian_init; | 772 | chip->model.init = meridian_init; |
527 | chip->model.mixer_init = generic_mixer_init; | 773 | chip->model.mixer_init = meridian_mixer_init; |
528 | chip->model.resume = meridian_resume; | 774 | chip->model.resume = meridian_resume; |
529 | chip->model.set_adc_params = set_ak5385_params; | 775 | chip->model.set_adc_params = set_ak5385_params; |
776 | chip->model.dump_registers = dump_ak4396_registers; | ||
530 | chip->model.device_config = PLAYBACK_0_TO_I2S | | 777 | chip->model.device_config = PLAYBACK_0_TO_I2S | |
531 | PLAYBACK_1_TO_SPDIF | | 778 | PLAYBACK_1_TO_SPDIF | |
532 | CAPTURE_0_FROM_I2S_2 | | 779 | CAPTURE_0_FROM_I2S_2 | |
533 | CAPTURE_1_FROM_SPDIF; | 780 | CAPTURE_1_FROM_SPDIF; |
781 | if (id->driver_data == MODEL_MERIDIAN) | ||
782 | chip->model.device_config |= AC97_CD_INPUT; | ||
534 | break; | 783 | break; |
535 | case MODEL_CLARO: | 784 | case MODEL_CLARO: |
536 | chip->model.init = claro_init; | 785 | chip->model.init = claro_init; |
786 | chip->model.mixer_init = claro_mixer_init; | ||
537 | chip->model.cleanup = claro_cleanup; | 787 | chip->model.cleanup = claro_cleanup; |
538 | chip->model.suspend = claro_suspend; | 788 | chip->model.suspend = claro_suspend; |
539 | chip->model.resume = claro_resume; | 789 | chip->model.resume = claro_resume; |
540 | break; | 790 | break; |
541 | case MODEL_CLARO_HALO: | 791 | case MODEL_CLARO_HALO: |
542 | chip->model.init = claro_halo_init; | 792 | chip->model.init = claro_halo_init; |
543 | chip->model.mixer_init = generic_mixer_init; | 793 | chip->model.mixer_init = claro_halo_mixer_init; |
544 | chip->model.cleanup = claro_cleanup; | 794 | chip->model.cleanup = claro_cleanup; |
545 | chip->model.suspend = claro_suspend; | 795 | chip->model.suspend = claro_suspend; |
546 | chip->model.resume = claro_resume; | 796 | chip->model.resume = claro_resume; |
547 | chip->model.set_adc_params = set_ak5385_params; | 797 | chip->model.set_adc_params = set_ak5385_params; |
798 | chip->model.dump_registers = dump_ak4396_registers; | ||
548 | chip->model.device_config = PLAYBACK_0_TO_I2S | | 799 | chip->model.device_config = PLAYBACK_0_TO_I2S | |
549 | PLAYBACK_1_TO_SPDIF | | 800 | PLAYBACK_1_TO_SPDIF | |
550 | CAPTURE_0_FROM_I2S_2 | | 801 | CAPTURE_0_FROM_I2S_2 | |
551 | CAPTURE_1_FROM_SPDIF; | 802 | CAPTURE_1_FROM_SPDIF; |
552 | break; | 803 | break; |
804 | case MODEL_FANTASIA: | ||
805 | case MODEL_SERENADE: | ||
806 | case MODEL_2CH_OUTPUT: | ||
807 | case MODEL_HG2PCI: | ||
808 | chip->model.shortname = "C-Media CMI8787"; | ||
809 | chip->model.chip = "CMI8787"; | ||
810 | if (id->driver_data == MODEL_FANTASIA) | ||
811 | chip->model.init = fantasia_init; | ||
812 | else | ||
813 | chip->model.init = stereo_output_init; | ||
814 | chip->model.resume = stereo_resume; | ||
815 | chip->model.mixer_init = generic_mixer_init; | ||
816 | chip->model.set_adc_params = set_no_params; | ||
817 | chip->model.dump_registers = dump_ak4396_registers; | ||
818 | chip->model.device_config = PLAYBACK_0_TO_I2S | | ||
819 | PLAYBACK_1_TO_SPDIF; | ||
820 | if (id->driver_data == MODEL_FANTASIA) { | ||
821 | chip->model.device_config |= CAPTURE_0_FROM_I2S_1; | ||
822 | chip->model.adc_mclks = OXYGEN_MCLKS(256, 128, 128); | ||
823 | } | ||
824 | chip->model.dac_channels_pcm = 2; | ||
825 | chip->model.dac_channels_mixer = 2; | ||
826 | break; | ||
827 | case MODEL_XONAR_DG: | ||
828 | chip->model = model_xonar_dg; | ||
829 | break; | ||
553 | } | 830 | } |
554 | if (id->driver_data == MODEL_MERIDIAN || | 831 | if (id->driver_data == MODEL_MERIDIAN || |
832 | id->driver_data == MODEL_MERIDIAN_2G || | ||
555 | id->driver_data == MODEL_CLARO_HALO) { | 833 | id->driver_data == MODEL_CLARO_HALO) { |
556 | chip->model.misc_flags = OXYGEN_MISC_MIDI; | 834 | chip->model.misc_flags = OXYGEN_MISC_MIDI; |
557 | chip->model.device_config |= MIDI_OUTPUT | MIDI_INPUT; | 835 | chip->model.device_config |= MIDI_OUTPUT | MIDI_INPUT; |
558 | } | 836 | } |
837 | if (id->driver_data < ARRAY_SIZE(names) && names[id->driver_data]) | ||
838 | chip->model.shortname = names[id->driver_data]; | ||
559 | return 0; | 839 | return 0; |
560 | } | 840 | } |
561 | 841 | ||