diff options
Diffstat (limited to 'sound/pci/oxygen')
-rw-r--r-- | sound/pci/oxygen/oxygen.c | 4 | ||||
-rw-r--r-- | sound/pci/oxygen/oxygen.h | 1 | ||||
-rw-r--r-- | sound/pci/oxygen/oxygen_lib.c | 55 | ||||
-rw-r--r-- | sound/pci/oxygen/oxygen_mixer.c | 5 | ||||
-rw-r--r-- | sound/pci/oxygen/oxygen_pcm.c | 12 | ||||
-rw-r--r-- | sound/pci/oxygen/oxygen_regs.h | 10 | ||||
-rw-r--r-- | sound/pci/oxygen/virtuoso.c | 5 | ||||
-rw-r--r-- | sound/pci/oxygen/xonar_cs43xx.c | 8 | ||||
-rw-r--r-- | sound/pci/oxygen/xonar_pcm179x.c | 29 | ||||
-rw-r--r-- | sound/pci/oxygen/xonar_wm87x6.c | 121 |
10 files changed, 173 insertions, 77 deletions
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c index 6c0a11adb2a8..98a8eb3c92f7 100644 --- a/sound/pci/oxygen/oxygen.c +++ b/sound/pci/oxygen/oxygen.c | |||
@@ -79,6 +79,7 @@ static DEFINE_PCI_DEVICE_TABLE(oxygen_ids) = { | |||
79 | { OXYGEN_PCI_SUBID(0x13f6, 0x0001), .driver_data = MODEL_CMEDIA_REF }, | 79 | { OXYGEN_PCI_SUBID(0x13f6, 0x0001), .driver_data = MODEL_CMEDIA_REF }, |
80 | { OXYGEN_PCI_SUBID(0x13f6, 0x0010), .driver_data = MODEL_CMEDIA_REF }, | 80 | { OXYGEN_PCI_SUBID(0x13f6, 0x0010), .driver_data = MODEL_CMEDIA_REF }, |
81 | { OXYGEN_PCI_SUBID(0x13f6, 0x8788), .driver_data = MODEL_CMEDIA_REF }, | 81 | { OXYGEN_PCI_SUBID(0x13f6, 0x8788), .driver_data = MODEL_CMEDIA_REF }, |
82 | { OXYGEN_PCI_SUBID(0x13f6, 0xffff), .driver_data = MODEL_CMEDIA_REF }, | ||
82 | { OXYGEN_PCI_SUBID(0x147a, 0xa017), .driver_data = MODEL_CMEDIA_REF }, | 83 | { OXYGEN_PCI_SUBID(0x147a, 0xa017), .driver_data = MODEL_CMEDIA_REF }, |
83 | { OXYGEN_PCI_SUBID(0x1a58, 0x0910), .driver_data = MODEL_CMEDIA_REF }, | 84 | { OXYGEN_PCI_SUBID(0x1a58, 0x0910), .driver_data = MODEL_CMEDIA_REF }, |
84 | { OXYGEN_PCI_SUBID(0x415a, 0x5431), .driver_data = MODEL_MERIDIAN }, | 85 | { OXYGEN_PCI_SUBID(0x415a, 0x5431), .driver_data = MODEL_MERIDIAN }, |
@@ -505,7 +506,8 @@ static const struct oxygen_model model_generic = { | |||
505 | PLAYBACK_2_TO_AC97_1 | | 506 | PLAYBACK_2_TO_AC97_1 | |
506 | CAPTURE_0_FROM_I2S_1 | | 507 | CAPTURE_0_FROM_I2S_1 | |
507 | CAPTURE_1_FROM_SPDIF | | 508 | CAPTURE_1_FROM_SPDIF | |
508 | CAPTURE_2_FROM_AC97_1, | 509 | CAPTURE_2_FROM_AC97_1 | |
510 | AC97_CD_INPUT, | ||
509 | .dac_channels = 8, | 511 | .dac_channels = 8, |
510 | .dac_volume_min = 0, | 512 | .dac_volume_min = 0, |
511 | .dac_volume_max = 255, | 513 | .dac_volume_max = 255, |
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h index a3409edcfb50..7d5222caa0a9 100644 --- a/sound/pci/oxygen/oxygen.h +++ b/sound/pci/oxygen/oxygen.h | |||
@@ -34,6 +34,7 @@ | |||
34 | /* CAPTURE_3_FROM_I2S_3 not implemented */ | 34 | /* CAPTURE_3_FROM_I2S_3 not implemented */ |
35 | #define MIDI_OUTPUT 0x0800 | 35 | #define MIDI_OUTPUT 0x0800 |
36 | #define MIDI_INPUT 0x1000 | 36 | #define MIDI_INPUT 0x1000 |
37 | #define AC97_CD_INPUT 0x2000 | ||
37 | 38 | ||
38 | enum { | 39 | enum { |
39 | CONTROL_SPDIF_PCM, | 40 | CONTROL_SPDIF_PCM, |
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index 7e93cf884437..e5ebe56fb0c5 100644 --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c | |||
@@ -308,25 +308,46 @@ static void oxygen_restore_eeprom(struct oxygen *chip, | |||
308 | } | 308 | } |
309 | } | 309 | } |
310 | 310 | ||
311 | static void pci_bridge_magic(void) | 311 | static void configure_pcie_bridge(struct pci_dev *pci) |
312 | { | 312 | { |
313 | struct pci_dev *pci = NULL; | 313 | enum { PEX811X, PI7C9X110 }; |
314 | static const struct pci_device_id bridge_ids[] = { | ||
315 | { PCI_VDEVICE(PLX, 0x8111), .driver_data = PEX811X }, | ||
316 | { PCI_VDEVICE(PLX, 0x8112), .driver_data = PEX811X }, | ||
317 | { PCI_DEVICE(0x12d8, 0xe110), .driver_data = PI7C9X110 }, | ||
318 | { } | ||
319 | }; | ||
320 | struct pci_dev *bridge; | ||
321 | const struct pci_device_id *id; | ||
314 | u32 tmp; | 322 | u32 tmp; |
315 | 323 | ||
316 | for (;;) { | 324 | if (!pci->bus || !pci->bus->self) |
317 | /* If there is any Pericom PI7C9X110 PCI-E/PCI bridge ... */ | 325 | return; |
318 | pci = pci_get_device(0x12d8, 0xe110, pci); | 326 | bridge = pci->bus->self; |
319 | if (!pci) | 327 | |
320 | break; | 328 | id = pci_match_id(bridge_ids, bridge); |
321 | /* | 329 | if (!id) |
322 | * ... configure its secondary internal arbiter to park to | 330 | return; |
323 | * the secondary port, instead of to the last master. | 331 | |
324 | */ | 332 | switch (id->driver_data) { |
325 | if (!pci_read_config_dword(pci, 0x40, &tmp)) { | 333 | case PEX811X: /* PLX PEX8111/PEX8112 PCIe/PCI bridge */ |
326 | tmp |= 1; | 334 | pci_read_config_dword(bridge, 0x48, &tmp); |
327 | pci_write_config_dword(pci, 0x40, tmp); | 335 | tmp |= 1; /* enable blind prefetching */ |
328 | } | 336 | tmp |= 1 << 11; /* enable beacon generation */ |
329 | /* Why? Try asking C-Media. */ | 337 | pci_write_config_dword(bridge, 0x48, tmp); |
338 | |||
339 | pci_write_config_dword(bridge, 0x84, 0x0c); | ||
340 | pci_read_config_dword(bridge, 0x88, &tmp); | ||
341 | tmp &= ~(7 << 27); | ||
342 | tmp |= 2 << 27; /* set prefetch size to 128 bytes */ | ||
343 | pci_write_config_dword(bridge, 0x88, tmp); | ||
344 | break; | ||
345 | |||
346 | case PI7C9X110: /* Pericom PI7C9X110 PCIe/PCI bridge */ | ||
347 | pci_read_config_dword(bridge, 0x40, &tmp); | ||
348 | tmp |= 1; /* park the PCI arbiter to the sound chip */ | ||
349 | pci_write_config_dword(bridge, 0x40, tmp); | ||
350 | break; | ||
330 | } | 351 | } |
331 | } | 352 | } |
332 | 353 | ||
@@ -613,7 +634,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | |||
613 | snd_card_set_dev(card, &pci->dev); | 634 | snd_card_set_dev(card, &pci->dev); |
614 | card->private_free = oxygen_card_free; | 635 | card->private_free = oxygen_card_free; |
615 | 636 | ||
616 | pci_bridge_magic(); | 637 | configure_pcie_bridge(pci); |
617 | oxygen_init(chip); | 638 | oxygen_init(chip); |
618 | chip->model.init(chip); | 639 | chip->model.init(chip); |
619 | 640 | ||
diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c index f375b8a27862..2849b36f5f7e 100644 --- a/sound/pci/oxygen/oxygen_mixer.c +++ b/sound/pci/oxygen/oxygen_mixer.c | |||
@@ -708,7 +708,7 @@ static int ac97_fp_rec_volume_put(struct snd_kcontrol *ctl, | |||
708 | .private_value = ((codec) << 24) | ((stereo) << 16) | (index), \ | 708 | .private_value = ((codec) << 24) | ((stereo) << 16) | (index), \ |
709 | } | 709 | } |
710 | 710 | ||
711 | static DECLARE_TLV_DB_SCALE(monitor_db_scale, -1000, 1000, 0); | 711 | static DECLARE_TLV_DB_SCALE(monitor_db_scale, -600, 600, 0); |
712 | static DECLARE_TLV_DB_SCALE(ac97_db_scale, -3450, 150, 0); | 712 | static DECLARE_TLV_DB_SCALE(ac97_db_scale, -3450, 150, 0); |
713 | static DECLARE_TLV_DB_SCALE(ac97_rec_db_scale, 0, 150, 0); | 713 | static DECLARE_TLV_DB_SCALE(ac97_rec_db_scale, 0, 150, 0); |
714 | 714 | ||
@@ -972,6 +972,9 @@ static int add_controls(struct oxygen *chip, | |||
972 | if (!strcmp(template.name, "Stereo Upmixing") && | 972 | if (!strcmp(template.name, "Stereo Upmixing") && |
973 | chip->model.dac_channels == 2) | 973 | chip->model.dac_channels == 2) |
974 | continue; | 974 | continue; |
975 | if (!strncmp(template.name, "CD Capture ", 11) && | ||
976 | !(chip->model.device_config & AC97_CD_INPUT)) | ||
977 | continue; | ||
975 | if (!strcmp(template.name, "Master Playback Volume") && | 978 | if (!strcmp(template.name, "Master Playback Volume") && |
976 | chip->model.dac_tlv) { | 979 | chip->model.dac_tlv) { |
977 | template.tlv.p = chip->model.dac_tlv; | 980 | template.tlv.p = chip->model.dac_tlv; |
diff --git a/sound/pci/oxygen/oxygen_pcm.c b/sound/pci/oxygen/oxygen_pcm.c index 9dff6954c397..814667442eb0 100644 --- a/sound/pci/oxygen/oxygen_pcm.c +++ b/sound/pci/oxygen/oxygen_pcm.c | |||
@@ -56,8 +56,8 @@ static const struct snd_pcm_hardware oxygen_stereo_hardware = { | |||
56 | .channels_max = 2, | 56 | .channels_max = 2, |
57 | .buffer_bytes_max = BUFFER_BYTES_MAX, | 57 | .buffer_bytes_max = BUFFER_BYTES_MAX, |
58 | .period_bytes_min = PERIOD_BYTES_MIN, | 58 | .period_bytes_min = PERIOD_BYTES_MIN, |
59 | .period_bytes_max = BUFFER_BYTES_MAX / 2, | 59 | .period_bytes_max = BUFFER_BYTES_MAX, |
60 | .periods_min = 2, | 60 | .periods_min = 1, |
61 | .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN, | 61 | .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN, |
62 | }; | 62 | }; |
63 | static const struct snd_pcm_hardware oxygen_multichannel_hardware = { | 63 | static const struct snd_pcm_hardware oxygen_multichannel_hardware = { |
@@ -82,8 +82,8 @@ static const struct snd_pcm_hardware oxygen_multichannel_hardware = { | |||
82 | .channels_max = 8, | 82 | .channels_max = 8, |
83 | .buffer_bytes_max = BUFFER_BYTES_MAX_MULTICH, | 83 | .buffer_bytes_max = BUFFER_BYTES_MAX_MULTICH, |
84 | .period_bytes_min = PERIOD_BYTES_MIN, | 84 | .period_bytes_min = PERIOD_BYTES_MIN, |
85 | .period_bytes_max = BUFFER_BYTES_MAX_MULTICH / 2, | 85 | .period_bytes_max = BUFFER_BYTES_MAX_MULTICH, |
86 | .periods_min = 2, | 86 | .periods_min = 1, |
87 | .periods_max = BUFFER_BYTES_MAX_MULTICH / PERIOD_BYTES_MIN, | 87 | .periods_max = BUFFER_BYTES_MAX_MULTICH / PERIOD_BYTES_MIN, |
88 | }; | 88 | }; |
89 | static const struct snd_pcm_hardware oxygen_ac97_hardware = { | 89 | static const struct snd_pcm_hardware oxygen_ac97_hardware = { |
@@ -100,8 +100,8 @@ static const struct snd_pcm_hardware oxygen_ac97_hardware = { | |||
100 | .channels_max = 2, | 100 | .channels_max = 2, |
101 | .buffer_bytes_max = BUFFER_BYTES_MAX, | 101 | .buffer_bytes_max = BUFFER_BYTES_MAX, |
102 | .period_bytes_min = PERIOD_BYTES_MIN, | 102 | .period_bytes_min = PERIOD_BYTES_MIN, |
103 | .period_bytes_max = BUFFER_BYTES_MAX / 2, | 103 | .period_bytes_max = BUFFER_BYTES_MAX, |
104 | .periods_min = 2, | 104 | .periods_min = 1, |
105 | .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN, | 105 | .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN, |
106 | }; | 106 | }; |
107 | 107 | ||
diff --git a/sound/pci/oxygen/oxygen_regs.h b/sound/pci/oxygen/oxygen_regs.h index 72de159d4567..4dcd41b78258 100644 --- a/sound/pci/oxygen/oxygen_regs.h +++ b/sound/pci/oxygen/oxygen_regs.h | |||
@@ -436,13 +436,15 @@ | |||
436 | /* OXYGEN_CHANNEL_* */ | 436 | /* OXYGEN_CHANNEL_* */ |
437 | 437 | ||
438 | #define OXYGEN_CODEC_VERSION 0xe4 | 438 | #define OXYGEN_CODEC_VERSION 0xe4 |
439 | #define OXYGEN_XCID_MASK 0x07 | 439 | #define OXYGEN_CODEC_ID_MASK 0x07 |
440 | 440 | ||
441 | #define OXYGEN_REVISION 0xe6 | 441 | #define OXYGEN_REVISION 0xe6 |
442 | #define OXYGEN_REVISION_XPKGID_MASK 0x0007 | 442 | #define OXYGEN_PACKAGE_ID_MASK 0x0007 |
443 | #define OXYGEN_PACKAGE_ID_8786 0x0004 | ||
444 | #define OXYGEN_PACKAGE_ID_8787 0x0006 | ||
445 | #define OXYGEN_PACKAGE_ID_8788 0x0007 | ||
443 | #define OXYGEN_REVISION_MASK 0xfff8 | 446 | #define OXYGEN_REVISION_MASK 0xfff8 |
444 | #define OXYGEN_REVISION_2 0x0008 /* bit flag */ | 447 | #define OXYGEN_REVISION_2 0x0008 |
445 | #define OXYGEN_REVISION_8787 0x0014 /* 8 bits */ | ||
446 | 448 | ||
447 | #define OXYGEN_OFFSIN_48K 0xe8 | 449 | #define OXYGEN_OFFSIN_48K 0xe8 |
448 | #define OXYGEN_OFFSBASE_48K 0xe9 | 450 | #define OXYGEN_OFFSBASE_48K 0xe9 |
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c index 06c863e86e3d..469010a8b849 100644 --- a/sound/pci/oxygen/virtuoso.c +++ b/sound/pci/oxygen/virtuoso.c | |||
@@ -25,9 +25,9 @@ | |||
25 | #include "xonar.h" | 25 | #include "xonar.h" |
26 | 26 | ||
27 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); | 27 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); |
28 | MODULE_DESCRIPTION("Asus AVx00 driver"); | 28 | MODULE_DESCRIPTION("Asus Virtuoso driver"); |
29 | MODULE_LICENSE("GPL v2"); | 29 | MODULE_LICENSE("GPL v2"); |
30 | MODULE_SUPPORTED_DEVICE("{{Asus,AV100},{Asus,AV200}}"); | 30 | MODULE_SUPPORTED_DEVICE("{{Asus,AV66},{Asus,AV100},{Asus,AV200}}"); |
31 | 31 | ||
32 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; | 32 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; |
33 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; | 33 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; |
@@ -49,6 +49,7 @@ static DEFINE_PCI_DEVICE_TABLE(xonar_ids) = { | |||
49 | { OXYGEN_PCI_SUBID(0x1043, 0x834f) }, | 49 | { OXYGEN_PCI_SUBID(0x1043, 0x834f) }, |
50 | { OXYGEN_PCI_SUBID(0x1043, 0x835c) }, | 50 | { OXYGEN_PCI_SUBID(0x1043, 0x835c) }, |
51 | { OXYGEN_PCI_SUBID(0x1043, 0x835d) }, | 51 | { OXYGEN_PCI_SUBID(0x1043, 0x835d) }, |
52 | { OXYGEN_PCI_SUBID(0x1043, 0x835e) }, | ||
52 | { OXYGEN_PCI_SUBID(0x1043, 0x838e) }, | 53 | { OXYGEN_PCI_SUBID(0x1043, 0x838e) }, |
53 | { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, | 54 | { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, |
54 | { } | 55 | { } |
diff --git a/sound/pci/oxygen/xonar_cs43xx.c b/sound/pci/oxygen/xonar_cs43xx.c index 7c4986b27f2b..aa27c31049af 100644 --- a/sound/pci/oxygen/xonar_cs43xx.c +++ b/sound/pci/oxygen/xonar_cs43xx.c | |||
@@ -367,13 +367,6 @@ static void xonar_d1_line_mic_ac97_switch(struct oxygen *chip, | |||
367 | 367 | ||
368 | static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -6000, 100, 0); | 368 | static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -6000, 100, 0); |
369 | 369 | ||
370 | static int xonar_d1_control_filter(struct snd_kcontrol_new *template) | ||
371 | { | ||
372 | if (!strncmp(template->name, "CD Capture ", 11)) | ||
373 | return 1; /* no CD input */ | ||
374 | return 0; | ||
375 | } | ||
376 | |||
377 | static int xonar_d1_mixer_init(struct oxygen *chip) | 370 | static int xonar_d1_mixer_init(struct oxygen *chip) |
378 | { | 371 | { |
379 | int err; | 372 | int err; |
@@ -391,7 +384,6 @@ static const struct oxygen_model model_xonar_d1 = { | |||
391 | .longname = "Asus Virtuoso 100", | 384 | .longname = "Asus Virtuoso 100", |
392 | .chip = "AV200", | 385 | .chip = "AV200", |
393 | .init = xonar_d1_init, | 386 | .init = xonar_d1_init, |
394 | .control_filter = xonar_d1_control_filter, | ||
395 | .mixer_init = xonar_d1_mixer_init, | 387 | .mixer_init = xonar_d1_mixer_init, |
396 | .cleanup = xonar_d1_cleanup, | 388 | .cleanup = xonar_d1_cleanup, |
397 | .suspend = xonar_d1_suspend, | 389 | .suspend = xonar_d1_suspend, |
diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c index ba18fb546b4f..d491fd6c0be2 100644 --- a/sound/pci/oxygen/xonar_pcm179x.c +++ b/sound/pci/oxygen/xonar_pcm179x.c | |||
@@ -132,6 +132,18 @@ | |||
132 | * GPIO 5 <- 0 | 132 | * GPIO 5 <- 0 |
133 | */ | 133 | */ |
134 | 134 | ||
135 | /* | ||
136 | * Xonar HDAV1.3 Slim | ||
137 | * ------------------ | ||
138 | * | ||
139 | * CMI8788: | ||
140 | * | ||
141 | * GPIO 1 -> enable output | ||
142 | * | ||
143 | * TXD -> HDMI controller | ||
144 | * RXD <- HDMI controller | ||
145 | */ | ||
146 | |||
135 | #include <linux/pci.h> | 147 | #include <linux/pci.h> |
136 | #include <linux/delay.h> | 148 | #include <linux/delay.h> |
137 | #include <linux/mutex.h> | 149 | #include <linux/mutex.h> |
@@ -362,7 +374,6 @@ static void xonar_st_init_common(struct oxygen *chip) | |||
362 | { | 374 | { |
363 | struct xonar_pcm179x *data = chip->model_data; | 375 | struct xonar_pcm179x *data = chip->model_data; |
364 | 376 | ||
365 | data->generic.anti_pop_delay = 100; | ||
366 | data->generic.output_enable_bit = GPIO_ST_OUTPUT_ENABLE; | 377 | data->generic.output_enable_bit = GPIO_ST_OUTPUT_ENABLE; |
367 | data->dacs = chip->model.private_data ? 4 : 1; | 378 | data->dacs = chip->model.private_data ? 4 : 1; |
368 | data->hp_gain_offset = 2*-18; | 379 | data->hp_gain_offset = 2*-18; |
@@ -408,6 +419,7 @@ static void xonar_st_init(struct oxygen *chip) | |||
408 | { | 419 | { |
409 | struct xonar_pcm179x *data = chip->model_data; | 420 | struct xonar_pcm179x *data = chip->model_data; |
410 | 421 | ||
422 | data->generic.anti_pop_delay = 100; | ||
411 | data->has_cs2000 = 1; | 423 | data->has_cs2000 = 1; |
412 | data->cs2000_fun_cfg_1 = CS2000_REF_CLK_DIV_1; | 424 | data->cs2000_fun_cfg_1 = CS2000_REF_CLK_DIV_1; |
413 | 425 | ||
@@ -428,6 +440,7 @@ static void xonar_stx_init(struct oxygen *chip) | |||
428 | struct xonar_pcm179x *data = chip->model_data; | 440 | struct xonar_pcm179x *data = chip->model_data; |
429 | 441 | ||
430 | xonar_st_init_i2c(chip); | 442 | xonar_st_init_i2c(chip); |
443 | data->generic.anti_pop_delay = 800; | ||
431 | data->generic.ext_power_reg = OXYGEN_GPI_DATA; | 444 | data->generic.ext_power_reg = OXYGEN_GPI_DATA; |
432 | data->generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; | 445 | data->generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; |
433 | data->generic.ext_power_bit = GPI_EXT_POWER; | 446 | data->generic.ext_power_bit = GPI_EXT_POWER; |
@@ -915,13 +928,6 @@ static int xonar_d2_control_filter(struct snd_kcontrol_new *template) | |||
915 | return 0; | 928 | return 0; |
916 | } | 929 | } |
917 | 930 | ||
918 | static int xonar_st_control_filter(struct snd_kcontrol_new *template) | ||
919 | { | ||
920 | if (!strncmp(template->name, "CD Capture ", 11)) | ||
921 | return 1; /* no CD input */ | ||
922 | return 0; | ||
923 | } | ||
924 | |||
925 | static int add_pcm1796_controls(struct oxygen *chip) | 931 | static int add_pcm1796_controls(struct oxygen *chip) |
926 | { | 932 | { |
927 | int err; | 933 | int err; |
@@ -991,7 +997,8 @@ static const struct oxygen_model model_xonar_d2 = { | |||
991 | CAPTURE_0_FROM_I2S_2 | | 997 | CAPTURE_0_FROM_I2S_2 | |
992 | CAPTURE_1_FROM_SPDIF | | 998 | CAPTURE_1_FROM_SPDIF | |
993 | MIDI_OUTPUT | | 999 | MIDI_OUTPUT | |
994 | MIDI_INPUT, | 1000 | MIDI_INPUT | |
1001 | AC97_CD_INPUT, | ||
995 | .dac_channels = 8, | 1002 | .dac_channels = 8, |
996 | .dac_volume_min = 255 - 2*60, | 1003 | .dac_volume_min = 255 - 2*60, |
997 | .dac_volume_max = 255, | 1004 | .dac_volume_max = 255, |
@@ -1037,7 +1044,6 @@ static const struct oxygen_model model_xonar_st = { | |||
1037 | .longname = "Asus Virtuoso 100", | 1044 | .longname = "Asus Virtuoso 100", |
1038 | .chip = "AV200", | 1045 | .chip = "AV200", |
1039 | .init = xonar_st_init, | 1046 | .init = xonar_st_init, |
1040 | .control_filter = xonar_st_control_filter, | ||
1041 | .mixer_init = xonar_st_mixer_init, | 1047 | .mixer_init = xonar_st_mixer_init, |
1042 | .cleanup = xonar_st_cleanup, | 1048 | .cleanup = xonar_st_cleanup, |
1043 | .suspend = xonar_st_suspend, | 1049 | .suspend = xonar_st_suspend, |
@@ -1108,6 +1114,9 @@ int __devinit get_xonar_pcm179x_model(struct oxygen *chip, | |||
1108 | chip->model.resume = xonar_stx_resume; | 1114 | chip->model.resume = xonar_stx_resume; |
1109 | chip->model.set_dac_params = set_pcm1796_params; | 1115 | chip->model.set_dac_params = set_pcm1796_params; |
1110 | break; | 1116 | break; |
1117 | case 0x835e: | ||
1118 | snd_printk(KERN_ERR "the HDAV1.3 Slim is not supported\n"); | ||
1119 | return -ENODEV; | ||
1111 | default: | 1120 | default: |
1112 | return -EINVAL; | 1121 | return -EINVAL; |
1113 | } | 1122 | } |
diff --git a/sound/pci/oxygen/xonar_wm87x6.c b/sound/pci/oxygen/xonar_wm87x6.c index b82c1cfa96f5..200f7601276f 100644 --- a/sound/pci/oxygen/xonar_wm87x6.c +++ b/sound/pci/oxygen/xonar_wm87x6.c | |||
@@ -25,16 +25,24 @@ | |||
25 | * SPI 0 -> WM8766 (surround, center/LFE, back) | 25 | * SPI 0 -> WM8766 (surround, center/LFE, back) |
26 | * SPI 1 -> WM8776 (front, input) | 26 | * SPI 1 -> WM8776 (front, input) |
27 | * | 27 | * |
28 | * GPIO 4 <- headphone detect | 28 | * GPIO 4 <- headphone detect, 0 = plugged |
29 | * GPIO 6 -> route input jack to input 1/2 (1/0) | 29 | * GPIO 6 -> route input jack to mic-in (0) or line-in (1) |
30 | * GPIO 7 -> enable output to speakers | 30 | * GPIO 7 -> enable output to front L/R speaker channels |
31 | * GPIO 8 -> enable output to speakers | 31 | * GPIO 8 -> enable output to other speaker channels and front panel headphone |
32 | * | ||
33 | * WM8766: | ||
34 | * | ||
35 | * input 1 <- line | ||
36 | * input 2 <- mic | ||
37 | * input 3 <- front mic | ||
38 | * input 4 <- aux | ||
32 | */ | 39 | */ |
33 | 40 | ||
34 | #include <linux/pci.h> | 41 | #include <linux/pci.h> |
35 | #include <linux/delay.h> | 42 | #include <linux/delay.h> |
36 | #include <sound/control.h> | 43 | #include <sound/control.h> |
37 | #include <sound/core.h> | 44 | #include <sound/core.h> |
45 | #include <sound/jack.h> | ||
38 | #include <sound/pcm.h> | 46 | #include <sound/pcm.h> |
39 | #include <sound/pcm_params.h> | 47 | #include <sound/pcm_params.h> |
40 | #include <sound/tlv.h> | 48 | #include <sound/tlv.h> |
@@ -44,7 +52,8 @@ | |||
44 | 52 | ||
45 | #define GPIO_DS_HP_DETECT 0x0010 | 53 | #define GPIO_DS_HP_DETECT 0x0010 |
46 | #define GPIO_DS_INPUT_ROUTE 0x0040 | 54 | #define GPIO_DS_INPUT_ROUTE 0x0040 |
47 | #define GPIO_DS_OUTPUT_ENABLE 0x0180 | 55 | #define GPIO_DS_OUTPUT_FRONTLR 0x0080 |
56 | #define GPIO_DS_OUTPUT_ENABLE 0x0100 | ||
48 | 57 | ||
49 | #define LC_CONTROL_LIMITER 0x40000000 | 58 | #define LC_CONTROL_LIMITER 0x40000000 |
50 | #define LC_CONTROL_ALC 0x20000000 | 59 | #define LC_CONTROL_ALC 0x20000000 |
@@ -56,6 +65,7 @@ struct xonar_wm87x6 { | |||
56 | struct snd_kcontrol *line_adcmux_control; | 65 | struct snd_kcontrol *line_adcmux_control; |
57 | struct snd_kcontrol *mic_adcmux_control; | 66 | struct snd_kcontrol *mic_adcmux_control; |
58 | struct snd_kcontrol *lc_controls[13]; | 67 | struct snd_kcontrol *lc_controls[13]; |
68 | struct snd_jack *hp_jack; | ||
59 | }; | 69 | }; |
60 | 70 | ||
61 | static void wm8776_write(struct oxygen *chip, | 71 | static void wm8776_write(struct oxygen *chip, |
@@ -97,8 +107,12 @@ static void wm8766_write(struct oxygen *chip, | |||
97 | (0 << OXYGEN_SPI_CODEC_SHIFT) | | 107 | (0 << OXYGEN_SPI_CODEC_SHIFT) | |
98 | OXYGEN_SPI_CEN_LATCH_CLOCK_LO, | 108 | OXYGEN_SPI_CEN_LATCH_CLOCK_LO, |
99 | (reg << 9) | value); | 109 | (reg << 9) | value); |
100 | if (reg < ARRAY_SIZE(data->wm8766_regs)) | 110 | if (reg < ARRAY_SIZE(data->wm8766_regs)) { |
111 | if ((reg >= WM8766_LDA1 && reg <= WM8766_RDA1) || | ||
112 | (reg >= WM8766_LDA2 && reg <= WM8766_MASTDA)) | ||
113 | value &= ~WM8766_UPDATE; | ||
101 | data->wm8766_regs[reg] = value; | 114 | data->wm8766_regs[reg] = value; |
115 | } | ||
102 | } | 116 | } |
103 | 117 | ||
104 | static void wm8766_write_cached(struct oxygen *chip, | 118 | static void wm8766_write_cached(struct oxygen *chip, |
@@ -107,12 +121,8 @@ static void wm8766_write_cached(struct oxygen *chip, | |||
107 | struct xonar_wm87x6 *data = chip->model_data; | 121 | struct xonar_wm87x6 *data = chip->model_data; |
108 | 122 | ||
109 | if (reg >= ARRAY_SIZE(data->wm8766_regs) || | 123 | if (reg >= ARRAY_SIZE(data->wm8766_regs) || |
110 | value != data->wm8766_regs[reg]) { | 124 | value != data->wm8766_regs[reg]) |
111 | if ((reg >= WM8766_LDA1 && reg <= WM8766_RDA1) || | ||
112 | (reg >= WM8766_LDA2 && reg <= WM8766_MASTDA)) | ||
113 | value &= ~WM8766_UPDATE; | ||
114 | wm8766_write(chip, reg, value); | 125 | wm8766_write(chip, reg, value); |
115 | } | ||
116 | } | 126 | } |
117 | 127 | ||
118 | static void wm8776_registers_init(struct oxygen *chip) | 128 | static void wm8776_registers_init(struct oxygen *chip) |
@@ -141,7 +151,10 @@ static void wm8776_registers_init(struct oxygen *chip) | |||
141 | 151 | ||
142 | static void wm8766_registers_init(struct oxygen *chip) | 152 | static void wm8766_registers_init(struct oxygen *chip) |
143 | { | 153 | { |
154 | struct xonar_wm87x6 *data = chip->model_data; | ||
155 | |||
144 | wm8766_write(chip, WM8766_RESET, 0); | 156 | wm8766_write(chip, WM8766_RESET, 0); |
157 | wm8766_write(chip, WM8766_DAC_CTRL, data->wm8766_regs[WM8766_DAC_CTRL]); | ||
145 | wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24); | 158 | wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24); |
146 | wm8766_write(chip, WM8766_DAC_CTRL2, | 159 | wm8766_write(chip, WM8766_DAC_CTRL2, |
147 | WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0)); | 160 | WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0)); |
@@ -170,6 +183,40 @@ static void wm8776_init(struct oxygen *chip) | |||
170 | wm8776_registers_init(chip); | 183 | wm8776_registers_init(chip); |
171 | } | 184 | } |
172 | 185 | ||
186 | static void wm8766_init(struct oxygen *chip) | ||
187 | { | ||
188 | struct xonar_wm87x6 *data = chip->model_data; | ||
189 | |||
190 | data->wm8766_regs[WM8766_DAC_CTRL] = | ||
191 | WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT; | ||
192 | wm8766_registers_init(chip); | ||
193 | } | ||
194 | |||
195 | static void xonar_ds_handle_hp_jack(struct oxygen *chip) | ||
196 | { | ||
197 | struct xonar_wm87x6 *data = chip->model_data; | ||
198 | bool hp_plugged; | ||
199 | unsigned int reg; | ||
200 | |||
201 | mutex_lock(&chip->mutex); | ||
202 | |||
203 | hp_plugged = !(oxygen_read16(chip, OXYGEN_GPIO_DATA) & | ||
204 | GPIO_DS_HP_DETECT); | ||
205 | |||
206 | oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, | ||
207 | hp_plugged ? 0 : GPIO_DS_OUTPUT_FRONTLR, | ||
208 | GPIO_DS_OUTPUT_FRONTLR); | ||
209 | |||
210 | reg = data->wm8766_regs[WM8766_DAC_CTRL] & ~WM8766_MUTEALL; | ||
211 | if (hp_plugged) | ||
212 | reg |= WM8766_MUTEALL; | ||
213 | wm8766_write_cached(chip, WM8766_DAC_CTRL, reg); | ||
214 | |||
215 | snd_jack_report(data->hp_jack, hp_plugged ? SND_JACK_HEADPHONE : 0); | ||
216 | |||
217 | mutex_unlock(&chip->mutex); | ||
218 | } | ||
219 | |||
173 | static void xonar_ds_init(struct oxygen *chip) | 220 | static void xonar_ds_init(struct oxygen *chip) |
174 | { | 221 | { |
175 | struct xonar_wm87x6 *data = chip->model_data; | 222 | struct xonar_wm87x6 *data = chip->model_data; |
@@ -178,16 +225,22 @@ static void xonar_ds_init(struct oxygen *chip) | |||
178 | data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE; | 225 | data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE; |
179 | 226 | ||
180 | wm8776_init(chip); | 227 | wm8776_init(chip); |
181 | wm8766_registers_init(chip); | 228 | wm8766_init(chip); |
182 | 229 | ||
183 | oxygen_write16_masked(chip, OXYGEN_GPIO_CONTROL, GPIO_DS_INPUT_ROUTE, | 230 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, |
184 | GPIO_DS_HP_DETECT | GPIO_DS_INPUT_ROUTE); | 231 | GPIO_DS_INPUT_ROUTE | GPIO_DS_OUTPUT_FRONTLR); |
232 | oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, | ||
233 | GPIO_DS_HP_DETECT); | ||
185 | oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE); | 234 | oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE); |
186 | oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT); | 235 | oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT); |
187 | chip->interrupt_mask |= OXYGEN_INT_GPIO; | 236 | chip->interrupt_mask |= OXYGEN_INT_GPIO; |
188 | 237 | ||
189 | xonar_enable_output(chip); | 238 | xonar_enable_output(chip); |
190 | 239 | ||
240 | snd_jack_new(chip->card, "Headphone", | ||
241 | SND_JACK_HEADPHONE, &data->hp_jack); | ||
242 | xonar_ds_handle_hp_jack(chip); | ||
243 | |||
191 | snd_component_add(chip->card, "WM8776"); | 244 | snd_component_add(chip->card, "WM8776"); |
192 | snd_component_add(chip->card, "WM8766"); | 245 | snd_component_add(chip->card, "WM8766"); |
193 | } | 246 | } |
@@ -208,6 +261,7 @@ static void xonar_ds_resume(struct oxygen *chip) | |||
208 | wm8776_registers_init(chip); | 261 | wm8776_registers_init(chip); |
209 | wm8766_registers_init(chip); | 262 | wm8766_registers_init(chip); |
210 | xonar_enable_output(chip); | 263 | xonar_enable_output(chip); |
264 | xonar_ds_handle_hp_jack(chip); | ||
211 | } | 265 | } |
212 | 266 | ||
213 | static void wm8776_adc_hardware_filter(unsigned int channel, | 267 | static void wm8776_adc_hardware_filter(unsigned int channel, |
@@ -323,12 +377,27 @@ static void update_wm87x6_mute(struct oxygen *chip) | |||
323 | (chip->dac_mute ? WM8766_DMUTE_MASK : 0)); | 377 | (chip->dac_mute ? WM8766_DMUTE_MASK : 0)); |
324 | } | 378 | } |
325 | 379 | ||
326 | static void xonar_ds_gpio_changed(struct oxygen *chip) | 380 | static void update_wm8766_center_lfe_mix(struct oxygen *chip, bool mixed) |
327 | { | 381 | { |
328 | u16 bits; | 382 | struct xonar_wm87x6 *data = chip->model_data; |
383 | unsigned int reg; | ||
329 | 384 | ||
330 | bits = oxygen_read16(chip, OXYGEN_GPIO_DATA); | 385 | /* |
331 | snd_printk(KERN_INFO "HP detect: %d\n", !!(bits & GPIO_DS_HP_DETECT)); | 386 | * The WM8766 can mix left and right channels, but this setting |
387 | * applies to all three stereo pairs. | ||
388 | */ | ||
389 | reg = data->wm8766_regs[WM8766_DAC_CTRL] & | ||
390 | ~(WM8766_PL_LEFT_MASK | WM8766_PL_RIGHT_MASK); | ||
391 | if (mixed) | ||
392 | reg |= WM8766_PL_LEFT_LRMIX | WM8766_PL_RIGHT_LRMIX; | ||
393 | else | ||
394 | reg |= WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT; | ||
395 | wm8766_write_cached(chip, WM8766_DAC_CTRL, reg); | ||
396 | } | ||
397 | |||
398 | static void xonar_ds_gpio_changed(struct oxygen *chip) | ||
399 | { | ||
400 | xonar_ds_handle_hp_jack(chip); | ||
332 | } | 401 | } |
333 | 402 | ||
334 | static int wm8776_bit_switch_get(struct snd_kcontrol *ctl, | 403 | static int wm8776_bit_switch_get(struct snd_kcontrol *ctl, |
@@ -896,7 +965,10 @@ static const struct snd_kcontrol_new ds_controls[] = { | |||
896 | .put = wm8776_input_mux_put, | 965 | .put = wm8776_input_mux_put, |
897 | .private_value = 1 << 1, | 966 | .private_value = 1 << 1, |
898 | }, | 967 | }, |
899 | WM8776_BIT_SWITCH("Aux", WM8776_ADCMUX, 1 << 2, 0, 0), | 968 | WM8776_BIT_SWITCH("Front Mic Capture Switch", |
969 | WM8776_ADCMUX, 1 << 2, 0, 0), | ||
970 | WM8776_BIT_SWITCH("Aux Capture Switch", | ||
971 | WM8776_ADCMUX, 1 << 3, 0, 0), | ||
900 | { | 972 | { |
901 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 973 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
902 | .name = "ADC Filter Capture Enum", | 974 | .name = "ADC Filter Capture Enum", |
@@ -956,13 +1028,6 @@ static const struct snd_kcontrol_new lc_controls[] = { | |||
956 | LC_CONTROL_ALC, wm8776_ngth_db_scale), | 1028 | LC_CONTROL_ALC, wm8776_ngth_db_scale), |
957 | }; | 1029 | }; |
958 | 1030 | ||
959 | static int xonar_ds_control_filter(struct snd_kcontrol_new *template) | ||
960 | { | ||
961 | if (!strncmp(template->name, "CD Capture ", 11)) | ||
962 | return 1; /* no CD input */ | ||
963 | return 0; | ||
964 | } | ||
965 | |||
966 | static int xonar_ds_mixer_init(struct oxygen *chip) | 1031 | static int xonar_ds_mixer_init(struct oxygen *chip) |
967 | { | 1032 | { |
968 | struct xonar_wm87x6 *data = chip->model_data; | 1033 | struct xonar_wm87x6 *data = chip->model_data; |
@@ -999,10 +1064,9 @@ static int xonar_ds_mixer_init(struct oxygen *chip) | |||
999 | 1064 | ||
1000 | static const struct oxygen_model model_xonar_ds = { | 1065 | static const struct oxygen_model model_xonar_ds = { |
1001 | .shortname = "Xonar DS", | 1066 | .shortname = "Xonar DS", |
1002 | .longname = "Asus Virtuoso 200", | 1067 | .longname = "Asus Virtuoso 66", |
1003 | .chip = "AV200", | 1068 | .chip = "AV200", |
1004 | .init = xonar_ds_init, | 1069 | .init = xonar_ds_init, |
1005 | .control_filter = xonar_ds_control_filter, | ||
1006 | .mixer_init = xonar_ds_mixer_init, | 1070 | .mixer_init = xonar_ds_mixer_init, |
1007 | .cleanup = xonar_ds_cleanup, | 1071 | .cleanup = xonar_ds_cleanup, |
1008 | .suspend = xonar_ds_suspend, | 1072 | .suspend = xonar_ds_suspend, |
@@ -1013,6 +1077,7 @@ static const struct oxygen_model model_xonar_ds = { | |||
1013 | .set_adc_params = set_wm8776_adc_params, | 1077 | .set_adc_params = set_wm8776_adc_params, |
1014 | .update_dac_volume = update_wm87x6_volume, | 1078 | .update_dac_volume = update_wm87x6_volume, |
1015 | .update_dac_mute = update_wm87x6_mute, | 1079 | .update_dac_mute = update_wm87x6_mute, |
1080 | .update_center_lfe_mix = update_wm8766_center_lfe_mix, | ||
1016 | .gpio_changed = xonar_ds_gpio_changed, | 1081 | .gpio_changed = xonar_ds_gpio_changed, |
1017 | .dac_tlv = wm87x6_dac_db_scale, | 1082 | .dac_tlv = wm87x6_dac_db_scale, |
1018 | .model_data_size = sizeof(struct xonar_wm87x6), | 1083 | .model_data_size = sizeof(struct xonar_wm87x6), |