diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-13 13:32:54 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-13 13:32:54 -0500 |
| commit | 66dc918d42eaaa9afe42a47d07526765162017a9 (patch) | |
| tree | 947411841773dfb076f1aa78bc5be868bc4281a6 /sound/pci | |
| parent | b2034d474b7e1e8578bd5c2977024b51693269d9 (diff) | |
| parent | 6db9a0f326d3144d790d9479309df480a8f562e4 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6: (348 commits)
ALSA: hda - Fix NULL-derefence with a single mic in STAC auto-mic detection
ALSA: hda - Add missing NID 0x19 fixup for Sony VAIO
ALSA: hda - Fix ALC275 enable hardware EQ for SONY VAIO
ALSA: oxygen: fix Xonar DG input
ALSA: hda - Fix EAPD on Lenovo NB ALC269 to low
ALSA: hda - Fix missing EAPD for Acer 4930G
ALSA: hda: Disable 4/6 channels on some NVIDIA GPUs.
ALSA: hda - Add static_hdmi_pcm option to HDMI codec parser
ALSA: hda - Don't refer ELD when unplugged
ASoC: tpa6130a2: Fix compiler warning
ASoC: tlv320dac33: Add DAPM selection for LOM invert
ASoC: DMIC codec: Adding a generic DMIC codec
ALSA: snd-usb-us122l: Fix missing NULL checks
ALSA: snd-usb-us122l: Fix MIDI output
ASoC: soc-cache: Fix invalid memory access during snd_soc_lzo_cache_sync()
ASoC: Fix section mismatch in wm8995.c
ALSA: oxygen: add S/PDIF source selection for Claro cards
ALSA: oxygen: fix CD/MIDI for X-Meridian (2G)
ASoC: fix migor audio build
ALSA: include delay.h for msleep in Xonar DG support
...
Diffstat (limited to 'sound/pci')
35 files changed, 3105 insertions, 1427 deletions
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index 12e34653b8a8..9823d59d7ad7 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig | |||
| @@ -209,7 +209,7 @@ config SND_OXYGEN_LIB | |||
| 209 | tristate | 209 | tristate |
| 210 | 210 | ||
| 211 | config SND_OXYGEN | 211 | config SND_OXYGEN |
| 212 | tristate "C-Media 8788 (Oxygen)" | 212 | tristate "C-Media 8786, 8787, 8788 (Oxygen)" |
| 213 | select SND_OXYGEN_LIB | 213 | select SND_OXYGEN_LIB |
| 214 | select SND_PCM | 214 | select SND_PCM |
| 215 | select SND_MPU401_UART | 215 | select SND_MPU401_UART |
| @@ -217,13 +217,18 @@ config SND_OXYGEN | |||
| 217 | Say Y here to include support for sound cards based on the | 217 | Say Y here to include support for sound cards based on the |
| 218 | C-Media CMI8788 (Oxygen HD Audio) chip: | 218 | C-Media CMI8788 (Oxygen HD Audio) chip: |
| 219 | * Asound A-8788 | 219 | * Asound A-8788 |
| 220 | * Asus Xonar DG | ||
| 220 | * AuzenTech X-Meridian | 221 | * AuzenTech X-Meridian |
| 222 | * AuzenTech X-Meridian 2G | ||
| 221 | * Bgears b-Enspirer | 223 | * Bgears b-Enspirer |
| 222 | * Club3D Theatron DTS | 224 | * Club3D Theatron DTS |
| 223 | * HT-Omega Claro (plus) | 225 | * HT-Omega Claro (plus) |
| 224 | * HT-Omega Claro halo (XT) | 226 | * HT-Omega Claro halo (XT) |
| 227 | * Kuroutoshikou CMI8787-HG2PCI | ||
| 225 | * Razer Barracuda AC-1 | 228 | * Razer Barracuda AC-1 |
| 226 | * Sondigo Inferno | 229 | * Sondigo Inferno |
| 230 | * TempoTec/MediaTek HiFier Fantasia | ||
| 231 | * TempoTec/MediaTek HiFier Serenade | ||
| 227 | 232 | ||
| 228 | To compile this driver as a module, choose M here: the module | 233 | To compile this driver as a module, choose M here: the module |
| 229 | will be called snd-oxygen. | 234 | will be called snd-oxygen. |
| @@ -578,18 +583,6 @@ config SND_HDSPM | |||
| 578 | To compile this driver as a module, choose M here: the module | 583 | To compile this driver as a module, choose M here: the module |
| 579 | will be called snd-hdspm. | 584 | will be called snd-hdspm. |
| 580 | 585 | ||
| 581 | config SND_HIFIER | ||
| 582 | tristate "TempoTec HiFier Fantasia" | ||
| 583 | select SND_OXYGEN_LIB | ||
| 584 | select SND_PCM | ||
| 585 | select SND_MPU401_UART | ||
| 586 | help | ||
| 587 | Say Y here to include support for the MediaTek/TempoTec HiFier | ||
| 588 | Fantasia sound card. | ||
| 589 | |||
| 590 | To compile this driver as a module, choose M here: the module | ||
| 591 | will be called snd-hifier. | ||
| 592 | |||
| 593 | config SND_ICE1712 | 586 | config SND_ICE1712 |
| 594 | tristate "ICEnsemble ICE1712 (Envy24)" | 587 | tristate "ICEnsemble ICE1712 (Envy24)" |
| 595 | select SND_MPU401_UART | 588 | select SND_MPU401_UART |
| @@ -826,8 +819,8 @@ config SND_VIRTUOSO | |||
| 826 | Say Y here to include support for sound cards based on the | 819 | Say Y here to include support for sound cards based on the |
| 827 | Asus AV66/AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, DS, | 820 | Asus AV66/AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, DS, |
| 828 | Essence ST (Deluxe), and Essence STX. | 821 | Essence ST (Deluxe), and Essence STX. |
| 829 | Support for the HDAV1.3 (Deluxe) is incomplete; for the | 822 | Support for the HDAV1.3 (Deluxe) and HDAV1.3 Slim is experimental; |
| 830 | HDAV1.3 Slim and Xense, missing. | 823 | for the Xense, missing. |
| 831 | 824 | ||
| 832 | To compile this driver as a module, choose M here: the module | 825 | To compile this driver as a module, choose M here: the module |
| 833 | will be called snd-virtuoso. | 826 | will be called snd-virtuoso. |
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index a7630e9edf8a..0fc614ce16c1 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c | |||
| @@ -1014,8 +1014,7 @@ static int snd_ac97_free(struct snd_ac97 *ac97) | |||
| 1014 | { | 1014 | { |
| 1015 | if (ac97) { | 1015 | if (ac97) { |
| 1016 | #ifdef CONFIG_SND_AC97_POWER_SAVE | 1016 | #ifdef CONFIG_SND_AC97_POWER_SAVE |
| 1017 | cancel_delayed_work(&ac97->power_work); | 1017 | cancel_delayed_work_sync(&ac97->power_work); |
| 1018 | flush_scheduled_work(); | ||
| 1019 | #endif | 1018 | #endif |
| 1020 | snd_ac97_proc_done(ac97); | 1019 | snd_ac97_proc_done(ac97); |
| 1021 | if (ac97->bus) | 1020 | if (ac97->bus) |
| @@ -2456,8 +2455,7 @@ void snd_ac97_suspend(struct snd_ac97 *ac97) | |||
| 2456 | if (ac97->build_ops->suspend) | 2455 | if (ac97->build_ops->suspend) |
| 2457 | ac97->build_ops->suspend(ac97); | 2456 | ac97->build_ops->suspend(ac97); |
| 2458 | #ifdef CONFIG_SND_AC97_POWER_SAVE | 2457 | #ifdef CONFIG_SND_AC97_POWER_SAVE |
| 2459 | cancel_delayed_work(&ac97->power_work); | 2458 | cancel_delayed_work_sync(&ac97->power_work); |
| 2460 | flush_scheduled_work(); | ||
| 2461 | #endif | 2459 | #endif |
| 2462 | snd_ac97_powerdown(ac97); | 2460 | snd_ac97_powerdown(ac97); |
| 2463 | } | 2461 | } |
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 2f3cacbd5528..6117595fc075 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * azt3328.c - driver for Aztech AZF3328 based soundcards (e.g. PCI168). | 2 | * azt3328.c - driver for Aztech AZF3328 based soundcards (e.g. PCI168). |
| 3 | * Copyright (C) 2002, 2005 - 2009 by Andreas Mohr <andi AT lisas.de> | 3 | * Copyright (C) 2002, 2005 - 2010 by Andreas Mohr <andi AT lisas.de> |
| 4 | * | 4 | * |
| 5 | * Framework borrowed from Bart Hartgers's als4000.c. | 5 | * Framework borrowed from Bart Hartgers's als4000.c. |
| 6 | * Driver developed on PCI168 AP(W) version (PCI rev. 10, subsystem ID 1801), | 6 | * Driver developed on PCI168 AP(W) version (PCI rev. 10, subsystem ID 1801), |
| @@ -175,6 +175,7 @@ | |||
| 175 | 175 | ||
| 176 | #include <asm/io.h> | 176 | #include <asm/io.h> |
| 177 | #include <linux/init.h> | 177 | #include <linux/init.h> |
| 178 | #include <linux/bug.h> /* WARN_ONCE */ | ||
| 178 | #include <linux/pci.h> | 179 | #include <linux/pci.h> |
| 179 | #include <linux/delay.h> | 180 | #include <linux/delay.h> |
| 180 | #include <linux/slab.h> | 181 | #include <linux/slab.h> |
| @@ -201,14 +202,15 @@ MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}"); | |||
| 201 | 202 | ||
| 202 | /* === Debug settings === | 203 | /* === Debug settings === |
| 203 | Further diagnostic functionality than the settings below | 204 | Further diagnostic functionality than the settings below |
| 204 | does not need to be provided, since one can easily write a bash script | 205 | does not need to be provided, since one can easily write a POSIX shell script |
| 205 | to dump the card's I/O ports (those listed in lspci -v -v): | 206 | to dump the card's I/O ports (those listed in lspci -v -v): |
| 206 | function dump() | 207 | dump() |
| 207 | { | 208 | { |
| 208 | local descr=$1; local addr=$2; local count=$3 | 209 | local descr=$1; local addr=$2; local count=$3 |
| 209 | 210 | ||
| 210 | echo "${descr}: ${count} @ ${addr}:" | 211 | echo "${descr}: ${count} @ ${addr}:" |
| 211 | dd if=/dev/port skip=$[${addr}] count=${count} bs=1 2>/dev/null| hexdump -C | 212 | dd if=/dev/port skip=`printf %d ${addr}` count=${count} bs=1 \ |
| 213 | 2>/dev/null| hexdump -C | ||
| 212 | } | 214 | } |
| 213 | and then use something like | 215 | and then use something like |
| 214 | "dump joy200 0x200 8", "dump mpu388 0x388 4", "dump joy 0xb400 8", | 216 | "dump joy200 0x200 8", "dump mpu388 0x388 4", "dump joy 0xb400 8", |
| @@ -216,14 +218,14 @@ MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}"); | |||
| 216 | possibly within a "while true; do ... sleep 1; done" loop. | 218 | possibly within a "while true; do ... sleep 1; done" loop. |
| 217 | Tweaking ports could be done using | 219 | Tweaking ports could be done using |
| 218 | VALSTRING="`printf "%02x" $value`" | 220 | VALSTRING="`printf "%02x" $value`" |
| 219 | printf "\x""$VALSTRING"|dd of=/dev/port seek=$[${addr}] bs=1 2>/dev/null | 221 | printf "\x""$VALSTRING"|dd of=/dev/port seek=`printf %d ${addr}` bs=1 \ |
| 222 | 2>/dev/null | ||
| 220 | */ | 223 | */ |
| 221 | 224 | ||
| 222 | #define DEBUG_MISC 0 | 225 | #define DEBUG_MISC 0 |
| 223 | #define DEBUG_CALLS 0 | 226 | #define DEBUG_CALLS 0 |
| 224 | #define DEBUG_MIXER 0 | 227 | #define DEBUG_MIXER 0 |
| 225 | #define DEBUG_CODEC 0 | 228 | #define DEBUG_CODEC 0 |
| 226 | #define DEBUG_IO 0 | ||
| 227 | #define DEBUG_TIMER 0 | 229 | #define DEBUG_TIMER 0 |
| 228 | #define DEBUG_GAME 0 | 230 | #define DEBUG_GAME 0 |
| 229 | #define DEBUG_PM 0 | 231 | #define DEBUG_PM 0 |
| @@ -291,19 +293,23 @@ static int seqtimer_scaling = 128; | |||
| 291 | module_param(seqtimer_scaling, int, 0444); | 293 | module_param(seqtimer_scaling, int, 0444); |
| 292 | MODULE_PARM_DESC(seqtimer_scaling, "Set 1024000Hz sequencer timer scale factor (lockup danger!). Default 128."); | 294 | MODULE_PARM_DESC(seqtimer_scaling, "Set 1024000Hz sequencer timer scale factor (lockup danger!). Default 128."); |
| 293 | 295 | ||
| 294 | struct snd_azf3328_codec_data { | ||
| 295 | unsigned long io_base; | ||
| 296 | struct snd_pcm_substream *substream; | ||
| 297 | bool running; | ||
| 298 | const char *name; | ||
| 299 | }; | ||
| 300 | |||
| 301 | enum snd_azf3328_codec_type { | 296 | enum snd_azf3328_codec_type { |
| 297 | /* warning: fixed indices (also used for bitmask checks!) */ | ||
| 302 | AZF_CODEC_PLAYBACK = 0, | 298 | AZF_CODEC_PLAYBACK = 0, |
| 303 | AZF_CODEC_CAPTURE = 1, | 299 | AZF_CODEC_CAPTURE = 1, |
| 304 | AZF_CODEC_I2S_OUT = 2, | 300 | AZF_CODEC_I2S_OUT = 2, |
| 305 | }; | 301 | }; |
| 306 | 302 | ||
| 303 | struct snd_azf3328_codec_data { | ||
| 304 | unsigned long io_base; /* keep first! (avoid offset calc) */ | ||
| 305 | unsigned int dma_base; /* helper to avoid an indirection in hotpath */ | ||
| 306 | spinlock_t *lock; /* TODO: convert to our own per-codec lock member */ | ||
| 307 | struct snd_pcm_substream *substream; | ||
| 308 | bool running; | ||
| 309 | enum snd_azf3328_codec_type type; | ||
| 310 | const char *name; | ||
| 311 | }; | ||
| 312 | |||
| 307 | struct snd_azf3328 { | 313 | struct snd_azf3328 { |
| 308 | /* often-used fields towards beginning, then grouped */ | 314 | /* often-used fields towards beginning, then grouped */ |
| 309 | 315 | ||
| @@ -362,6 +368,9 @@ MODULE_DEVICE_TABLE(pci, snd_azf3328_ids); | |||
| 362 | static int | 368 | static int |
| 363 | snd_azf3328_io_reg_setb(unsigned reg, u8 mask, bool do_set) | 369 | snd_azf3328_io_reg_setb(unsigned reg, u8 mask, bool do_set) |
| 364 | { | 370 | { |
| 371 | /* Well, strictly spoken, the inb/outb sequence isn't atomic | ||
| 372 | and would need locking. However we currently don't care | ||
| 373 | since it potentially complicates matters. */ | ||
| 365 | u8 prev = inb(reg), new; | 374 | u8 prev = inb(reg), new; |
| 366 | 375 | ||
| 367 | new = (do_set) ? (prev|mask) : (prev & ~mask); | 376 | new = (do_set) ? (prev|mask) : (prev & ~mask); |
| @@ -413,6 +422,21 @@ snd_azf3328_codec_outl(const struct snd_azf3328_codec_data *codec, | |||
| 413 | outl(value, codec->io_base + reg); | 422 | outl(value, codec->io_base + reg); |
| 414 | } | 423 | } |
| 415 | 424 | ||
| 425 | static inline void | ||
| 426 | snd_azf3328_codec_outl_multi(const struct snd_azf3328_codec_data *codec, | ||
| 427 | unsigned reg, const void *buffer, int count | ||
| 428 | ) | ||
| 429 | { | ||
| 430 | unsigned long addr = codec->io_base + reg; | ||
| 431 | if (count) { | ||
| 432 | const u32 *buf = buffer; | ||
| 433 | do { | ||
| 434 | outl(*buf++, addr); | ||
| 435 | addr += 4; | ||
| 436 | } while (--count); | ||
| 437 | } | ||
| 438 | } | ||
| 439 | |||
| 416 | static inline u32 | 440 | static inline u32 |
| 417 | snd_azf3328_codec_inl(const struct snd_azf3328_codec_data *codec, unsigned reg) | 441 | snd_azf3328_codec_inl(const struct snd_azf3328_codec_data *codec, unsigned reg) |
| 418 | { | 442 | { |
| @@ -943,38 +967,43 @@ snd_azf3328_hw_free(struct snd_pcm_substream *substream) | |||
| 943 | } | 967 | } |
| 944 | 968 | ||
| 945 | static void | 969 | static void |
| 946 | snd_azf3328_codec_setfmt(struct snd_azf3328 *chip, | 970 | snd_azf3328_codec_setfmt(struct snd_azf3328_codec_data *codec, |
| 947 | enum snd_azf3328_codec_type codec_type, | ||
| 948 | enum azf_freq_t bitrate, | 971 | enum azf_freq_t bitrate, |
| 949 | unsigned int format_width, | 972 | unsigned int format_width, |
| 950 | unsigned int channels | 973 | unsigned int channels |
| 951 | ) | 974 | ) |
| 952 | { | 975 | { |
| 953 | unsigned long flags; | 976 | unsigned long flags; |
| 954 | const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type]; | ||
| 955 | u16 val = 0xff00; | 977 | u16 val = 0xff00; |
| 978 | u8 freq = 0; | ||
| 956 | 979 | ||
| 957 | snd_azf3328_dbgcallenter(); | 980 | snd_azf3328_dbgcallenter(); |
| 958 | switch (bitrate) { | 981 | switch (bitrate) { |
| 959 | case AZF_FREQ_4000: val |= SOUNDFORMAT_FREQ_SUSPECTED_4000; break; | 982 | #define AZF_FMT_XLATE(in_freq, out_bits) \ |
| 960 | case AZF_FREQ_4800: val |= SOUNDFORMAT_FREQ_SUSPECTED_4800; break; | 983 | do { \ |
| 961 | case AZF_FREQ_5512: | 984 | case AZF_FREQ_ ## in_freq: \ |
| 962 | /* the AZF3328 names it "5510" for some strange reason */ | 985 | freq = SOUNDFORMAT_FREQ_ ## out_bits; \ |
| 963 | val |= SOUNDFORMAT_FREQ_5510; break; | 986 | break; \ |
| 964 | case AZF_FREQ_6620: val |= SOUNDFORMAT_FREQ_6620; break; | 987 | } while (0); |
| 965 | case AZF_FREQ_8000: val |= SOUNDFORMAT_FREQ_8000; break; | 988 | AZF_FMT_XLATE(4000, SUSPECTED_4000) |
| 966 | case AZF_FREQ_9600: val |= SOUNDFORMAT_FREQ_9600; break; | 989 | AZF_FMT_XLATE(4800, SUSPECTED_4800) |
| 967 | case AZF_FREQ_11025: val |= SOUNDFORMAT_FREQ_11025; break; | 990 | /* the AZF3328 names it "5510" for some strange reason: */ |
| 968 | case AZF_FREQ_13240: val |= SOUNDFORMAT_FREQ_SUSPECTED_13240; break; | 991 | AZF_FMT_XLATE(5512, 5510) |
| 969 | case AZF_FREQ_16000: val |= SOUNDFORMAT_FREQ_16000; break; | 992 | AZF_FMT_XLATE(6620, 6620) |
| 970 | case AZF_FREQ_22050: val |= SOUNDFORMAT_FREQ_22050; break; | 993 | AZF_FMT_XLATE(8000, 8000) |
| 971 | case AZF_FREQ_32000: val |= SOUNDFORMAT_FREQ_32000; break; | 994 | AZF_FMT_XLATE(9600, 9600) |
| 995 | AZF_FMT_XLATE(11025, 11025) | ||
| 996 | AZF_FMT_XLATE(13240, SUSPECTED_13240) | ||
| 997 | AZF_FMT_XLATE(16000, 16000) | ||
| 998 | AZF_FMT_XLATE(22050, 22050) | ||
| 999 | AZF_FMT_XLATE(32000, 32000) | ||
| 972 | default: | 1000 | default: |
| 973 | snd_printk(KERN_WARNING "unknown bitrate %d, assuming 44.1kHz!\n", bitrate); | 1001 | snd_printk(KERN_WARNING "unknown bitrate %d, assuming 44.1kHz!\n", bitrate); |
| 974 | /* fall-through */ | 1002 | /* fall-through */ |
| 975 | case AZF_FREQ_44100: val |= SOUNDFORMAT_FREQ_44100; break; | 1003 | AZF_FMT_XLATE(44100, 44100) |
| 976 | case AZF_FREQ_48000: val |= SOUNDFORMAT_FREQ_48000; break; | 1004 | AZF_FMT_XLATE(48000, 48000) |
| 977 | case AZF_FREQ_66200: val |= SOUNDFORMAT_FREQ_SUSPECTED_66200; break; | 1005 | AZF_FMT_XLATE(66200, SUSPECTED_66200) |
| 1006 | #undef AZF_FMT_XLATE | ||
| 978 | } | 1007 | } |
| 979 | /* val = 0xff07; 3m27.993s (65301Hz; -> 64000Hz???) hmm, 66120, 65967, 66123 */ | 1008 | /* val = 0xff07; 3m27.993s (65301Hz; -> 64000Hz???) hmm, 66120, 65967, 66123 */ |
| 980 | /* val = 0xff09; 17m15.098s (13123,478Hz; -> 12000Hz???) hmm, 13237.2Hz? */ | 1009 | /* val = 0xff09; 17m15.098s (13123,478Hz; -> 12000Hz???) hmm, 13237.2Hz? */ |
| @@ -986,13 +1015,15 @@ snd_azf3328_codec_setfmt(struct snd_azf3328 *chip, | |||
| 986 | /* val = 0xff0d; 41m23.135s (5523,600Hz; -> 5512Hz???) */ | 1015 | /* val = 0xff0d; 41m23.135s (5523,600Hz; -> 5512Hz???) */ |
| 987 | /* val = 0xff0e; 28m30.777s (8017Hz; -> 8000Hz???) */ | 1016 | /* val = 0xff0e; 28m30.777s (8017Hz; -> 8000Hz???) */ |
| 988 | 1017 | ||
| 1018 | val |= freq; | ||
| 1019 | |||
| 989 | if (channels == 2) | 1020 | if (channels == 2) |
| 990 | val |= SOUNDFORMAT_FLAG_2CHANNELS; | 1021 | val |= SOUNDFORMAT_FLAG_2CHANNELS; |
| 991 | 1022 | ||
| 992 | if (format_width == 16) | 1023 | if (format_width == 16) |
| 993 | val |= SOUNDFORMAT_FLAG_16BIT; | 1024 | val |= SOUNDFORMAT_FLAG_16BIT; |
| 994 | 1025 | ||
| 995 | spin_lock_irqsave(&chip->reg_lock, flags); | 1026 | spin_lock_irqsave(codec->lock, flags); |
| 996 | 1027 | ||
| 997 | /* set bitrate/format */ | 1028 | /* set bitrate/format */ |
| 998 | snd_azf3328_codec_outw(codec, IDX_IO_CODEC_SOUNDFORMAT, val); | 1029 | snd_azf3328_codec_outw(codec, IDX_IO_CODEC_SOUNDFORMAT, val); |
| @@ -1004,7 +1035,8 @@ snd_azf3328_codec_setfmt(struct snd_azf3328 *chip, | |||
| 1004 | * (FIXME: yes, it works, but what exactly am I doing here?? :) | 1035 | * (FIXME: yes, it works, but what exactly am I doing here?? :) |
| 1005 | * FIXME: does this have some side effects for full-duplex | 1036 | * FIXME: does this have some side effects for full-duplex |
| 1006 | * or other dramatic side effects? */ | 1037 | * or other dramatic side effects? */ |
| 1007 | if (codec_type == AZF_CODEC_PLAYBACK) /* only do it for playback */ | 1038 | /* do it for non-capture codecs only */ |
| 1039 | if (codec->type != AZF_CODEC_CAPTURE) | ||
| 1008 | snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, | 1040 | snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, |
| 1009 | snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS) | | 1041 | snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS) | |
| 1010 | DMA_RUN_SOMETHING1 | | 1042 | DMA_RUN_SOMETHING1 | |
| @@ -1014,20 +1046,19 @@ snd_azf3328_codec_setfmt(struct snd_azf3328 *chip, | |||
| 1014 | DMA_SOMETHING_ELSE | 1046 | DMA_SOMETHING_ELSE |
| 1015 | ); | 1047 | ); |
| 1016 | 1048 | ||
| 1017 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 1049 | spin_unlock_irqrestore(codec->lock, flags); |
| 1018 | snd_azf3328_dbgcallleave(); | 1050 | snd_azf3328_dbgcallleave(); |
| 1019 | } | 1051 | } |
| 1020 | 1052 | ||
| 1021 | static inline void | 1053 | static inline void |
| 1022 | snd_azf3328_codec_setfmt_lowpower(struct snd_azf3328 *chip, | 1054 | snd_azf3328_codec_setfmt_lowpower(struct snd_azf3328_codec_data *codec |
| 1023 | enum snd_azf3328_codec_type codec_type | ||
| 1024 | ) | 1055 | ) |
| 1025 | { | 1056 | { |
| 1026 | /* choose lowest frequency for low power consumption. | 1057 | /* choose lowest frequency for low power consumption. |
| 1027 | * While this will cause louder noise due to rather coarse frequency, | 1058 | * While this will cause louder noise due to rather coarse frequency, |
| 1028 | * it should never matter since output should always | 1059 | * it should never matter since output should always |
| 1029 | * get disabled properly when idle anyway. */ | 1060 | * get disabled properly when idle anyway. */ |
| 1030 | snd_azf3328_codec_setfmt(chip, codec_type, AZF_FREQ_4000, 8, 1); | 1061 | snd_azf3328_codec_setfmt(codec, AZF_FREQ_4000, 8, 1); |
| 1031 | } | 1062 | } |
| 1032 | 1063 | ||
| 1033 | static void | 1064 | static void |
| @@ -1101,69 +1132,87 @@ snd_azf3328_ctrl_codec_activity(struct snd_azf3328 *chip, | |||
| 1101 | /* ...and adjust clock, too | 1132 | /* ...and adjust clock, too |
| 1102 | * (reduce noise and power consumption) */ | 1133 | * (reduce noise and power consumption) */ |
| 1103 | if (!enable) | 1134 | if (!enable) |
| 1104 | snd_azf3328_codec_setfmt_lowpower( | 1135 | snd_azf3328_codec_setfmt_lowpower(codec); |
| 1105 | chip, | ||
| 1106 | codec_type | ||
| 1107 | ); | ||
| 1108 | codec->running = enable; | 1136 | codec->running = enable; |
| 1109 | } | 1137 | } |
| 1110 | } | 1138 | } |
| 1111 | 1139 | ||
| 1112 | static void | 1140 | static void |
| 1113 | snd_azf3328_codec_setdmaa(struct snd_azf3328 *chip, | 1141 | snd_azf3328_codec_setdmaa(struct snd_azf3328_codec_data *codec, |
| 1114 | enum snd_azf3328_codec_type codec_type, | ||
| 1115 | unsigned long addr, | 1142 | unsigned long addr, |
| 1116 | unsigned int count, | 1143 | unsigned int period_bytes, |
| 1117 | unsigned int size | 1144 | unsigned int buffer_bytes |
| 1118 | ) | 1145 | ) |
| 1119 | { | 1146 | { |
| 1120 | const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type]; | ||
| 1121 | snd_azf3328_dbgcallenter(); | 1147 | snd_azf3328_dbgcallenter(); |
| 1148 | WARN_ONCE(period_bytes & 1, "odd period length!?\n"); | ||
| 1149 | WARN_ONCE(buffer_bytes != 2 * period_bytes, | ||
| 1150 | "missed our input expectations! %u vs. %u\n", | ||
| 1151 | buffer_bytes, period_bytes); | ||
| 1122 | if (!codec->running) { | 1152 | if (!codec->running) { |
| 1123 | /* AZF3328 uses a two buffer pointer DMA transfer approach */ | 1153 | /* AZF3328 uses a two buffer pointer DMA transfer approach */ |
| 1124 | 1154 | ||
| 1125 | unsigned long flags, addr_area2; | 1155 | unsigned long flags; |
| 1126 | 1156 | ||
| 1127 | /* width 32bit (prevent overflow): */ | 1157 | /* width 32bit (prevent overflow): */ |
| 1128 | u32 count_areas, lengths; | 1158 | u32 area_length; |
| 1159 | struct codec_setup_io { | ||
| 1160 | u32 dma_start_1; | ||
| 1161 | u32 dma_start_2; | ||
| 1162 | u32 dma_lengths; | ||
| 1163 | } __attribute__((packed)) setup_io; | ||
| 1164 | |||
| 1165 | area_length = buffer_bytes/2; | ||
| 1166 | |||
| 1167 | setup_io.dma_start_1 = addr; | ||
| 1168 | setup_io.dma_start_2 = addr+area_length; | ||
| 1129 | 1169 | ||
| 1130 | count_areas = size/2; | 1170 | snd_azf3328_dbgcodec( |
| 1131 | addr_area2 = addr+count_areas; | 1171 | "setdma: buffers %08x[%u] / %08x[%u], %u, %u\n", |
| 1132 | snd_azf3328_dbgcodec("setdma: buffers %08lx[%u] / %08lx[%u]\n", | 1172 | setup_io.dma_start_1, area_length, |
| 1133 | addr, count_areas, addr_area2, count_areas); | 1173 | setup_io.dma_start_2, area_length, |
| 1174 | period_bytes, buffer_bytes); | ||
| 1134 | 1175 | ||
| 1135 | count_areas--; /* max. index */ | 1176 | /* Hmm, are we really supposed to decrement this by 1?? |
| 1177 | Most definitely certainly not: configuring full length does | ||
| 1178 | work properly (i.e. likely better), and BTW we | ||
| 1179 | violated possibly differing frame sizes with this... | ||
| 1180 | |||
| 1181 | area_length--; |* max. index *| | ||
| 1182 | */ | ||
| 1136 | 1183 | ||
| 1137 | /* build combined I/O buffer length word */ | 1184 | /* build combined I/O buffer length word */ |
| 1138 | lengths = (count_areas << 16) | (count_areas); | 1185 | setup_io.dma_lengths = (area_length << 16) | (area_length); |
| 1139 | spin_lock_irqsave(&chip->reg_lock, flags); | 1186 | |
| 1140 | snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_START_1, addr); | 1187 | spin_lock_irqsave(codec->lock, flags); |
| 1141 | snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_START_2, | 1188 | snd_azf3328_codec_outl_multi( |
| 1142 | addr_area2); | 1189 | codec, IDX_IO_CODEC_DMA_START_1, &setup_io, 3 |
| 1143 | snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_LENGTHS, | 1190 | ); |
| 1144 | lengths); | 1191 | spin_unlock_irqrestore(codec->lock, flags); |
| 1145 | spin_unlock_irqrestore(&chip->reg_lock, flags); | ||
| 1146 | } | 1192 | } |
| 1147 | snd_azf3328_dbgcallleave(); | 1193 | snd_azf3328_dbgcallleave(); |
| 1148 | } | 1194 | } |
| 1149 | 1195 | ||
| 1150 | static int | 1196 | static int |
| 1151 | snd_azf3328_codec_prepare(struct snd_pcm_substream *substream) | 1197 | snd_azf3328_pcm_prepare(struct snd_pcm_substream *substream) |
| 1152 | { | 1198 | { |
| 1153 | #if 0 | ||
| 1154 | struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); | ||
| 1155 | struct snd_pcm_runtime *runtime = substream->runtime; | 1199 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 1200 | struct snd_azf3328_codec_data *codec = runtime->private_data; | ||
| 1201 | #if 0 | ||
| 1156 | unsigned int size = snd_pcm_lib_buffer_bytes(substream); | 1202 | unsigned int size = snd_pcm_lib_buffer_bytes(substream); |
| 1157 | unsigned int count = snd_pcm_lib_period_bytes(substream); | 1203 | unsigned int count = snd_pcm_lib_period_bytes(substream); |
| 1158 | #endif | 1204 | #endif |
| 1159 | 1205 | ||
| 1160 | snd_azf3328_dbgcallenter(); | 1206 | snd_azf3328_dbgcallenter(); |
| 1207 | |||
| 1208 | codec->dma_base = runtime->dma_addr; | ||
| 1209 | |||
| 1161 | #if 0 | 1210 | #if 0 |
| 1162 | snd_azf3328_codec_setfmt(chip, AZF_CODEC_..., | 1211 | snd_azf3328_codec_setfmt(codec, |
| 1163 | runtime->rate, | 1212 | runtime->rate, |
| 1164 | snd_pcm_format_width(runtime->format), | 1213 | snd_pcm_format_width(runtime->format), |
| 1165 | runtime->channels); | 1214 | runtime->channels); |
| 1166 | snd_azf3328_codec_setdmaa(chip, AZF_CODEC_..., | 1215 | snd_azf3328_codec_setdmaa(codec, |
| 1167 | runtime->dma_addr, count, size); | 1216 | runtime->dma_addr, count, size); |
| 1168 | #endif | 1217 | #endif |
| 1169 | snd_azf3328_dbgcallleave(); | 1218 | snd_azf3328_dbgcallleave(); |
| @@ -1171,24 +1220,23 @@ snd_azf3328_codec_prepare(struct snd_pcm_substream *substream) | |||
| 1171 | } | 1220 | } |
| 1172 | 1221 | ||
| 1173 | static int | 1222 | static int |
| 1174 | snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type, | 1223 | snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd) |
| 1175 | struct snd_pcm_substream *substream, int cmd) | ||
| 1176 | { | 1224 | { |
| 1177 | struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); | 1225 | struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); |
| 1178 | const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type]; | ||
| 1179 | struct snd_pcm_runtime *runtime = substream->runtime; | 1226 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 1227 | struct snd_azf3328_codec_data *codec = runtime->private_data; | ||
| 1180 | int result = 0; | 1228 | int result = 0; |
| 1181 | u16 flags1; | 1229 | u16 flags1; |
| 1182 | bool previously_muted = 0; | 1230 | bool previously_muted = 0; |
| 1183 | bool is_playback_codec = (AZF_CODEC_PLAYBACK == codec_type); | 1231 | bool is_main_mixer_playback_codec = (AZF_CODEC_PLAYBACK == codec->type); |
| 1184 | 1232 | ||
| 1185 | snd_azf3328_dbgcalls("snd_azf3328_codec_trigger cmd %d\n", cmd); | 1233 | snd_azf3328_dbgcalls("snd_azf3328_pcm_trigger cmd %d\n", cmd); |
| 1186 | 1234 | ||
| 1187 | switch (cmd) { | 1235 | switch (cmd) { |
| 1188 | case SNDRV_PCM_TRIGGER_START: | 1236 | case SNDRV_PCM_TRIGGER_START: |
| 1189 | snd_azf3328_dbgcodec("START %s\n", codec->name); | 1237 | snd_azf3328_dbgcodec("START %s\n", codec->name); |
| 1190 | 1238 | ||
| 1191 | if (is_playback_codec) { | 1239 | if (is_main_mixer_playback_codec) { |
| 1192 | /* mute WaveOut (avoid clicking during setup) */ | 1240 | /* mute WaveOut (avoid clicking during setup) */ |
| 1193 | previously_muted = | 1241 | previously_muted = |
| 1194 | snd_azf3328_mixer_set_mute( | 1242 | snd_azf3328_mixer_set_mute( |
| @@ -1196,12 +1244,12 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type, | |||
| 1196 | ); | 1244 | ); |
| 1197 | } | 1245 | } |
| 1198 | 1246 | ||
| 1199 | snd_azf3328_codec_setfmt(chip, codec_type, | 1247 | snd_azf3328_codec_setfmt(codec, |
| 1200 | runtime->rate, | 1248 | runtime->rate, |
| 1201 | snd_pcm_format_width(runtime->format), | 1249 | snd_pcm_format_width(runtime->format), |
| 1202 | runtime->channels); | 1250 | runtime->channels); |
| 1203 | 1251 | ||
| 1204 | spin_lock(&chip->reg_lock); | 1252 | spin_lock(codec->lock); |
| 1205 | /* first, remember current value: */ | 1253 | /* first, remember current value: */ |
| 1206 | flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS); | 1254 | flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS); |
| 1207 | 1255 | ||
| @@ -1211,14 +1259,14 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type, | |||
| 1211 | 1259 | ||
| 1212 | /* FIXME: clear interrupts or what??? */ | 1260 | /* FIXME: clear interrupts or what??? */ |
| 1213 | snd_azf3328_codec_outw(codec, IDX_IO_CODEC_IRQTYPE, 0xffff); | 1261 | snd_azf3328_codec_outw(codec, IDX_IO_CODEC_IRQTYPE, 0xffff); |
| 1214 | spin_unlock(&chip->reg_lock); | 1262 | spin_unlock(codec->lock); |
| 1215 | 1263 | ||
| 1216 | snd_azf3328_codec_setdmaa(chip, codec_type, runtime->dma_addr, | 1264 | snd_azf3328_codec_setdmaa(codec, runtime->dma_addr, |
| 1217 | snd_pcm_lib_period_bytes(substream), | 1265 | snd_pcm_lib_period_bytes(substream), |
| 1218 | snd_pcm_lib_buffer_bytes(substream) | 1266 | snd_pcm_lib_buffer_bytes(substream) |
| 1219 | ); | 1267 | ); |
| 1220 | 1268 | ||
| 1221 | spin_lock(&chip->reg_lock); | 1269 | spin_lock(codec->lock); |
| 1222 | #ifdef WIN9X | 1270 | #ifdef WIN9X |
| 1223 | /* FIXME: enable playback/recording??? */ | 1271 | /* FIXME: enable playback/recording??? */ |
| 1224 | flags1 |= DMA_RUN_SOMETHING1 | DMA_RUN_SOMETHING2; | 1272 | flags1 |= DMA_RUN_SOMETHING1 | DMA_RUN_SOMETHING2; |
| @@ -1242,10 +1290,10 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type, | |||
| 1242 | DMA_EPILOGUE_SOMETHING | | 1290 | DMA_EPILOGUE_SOMETHING | |
| 1243 | DMA_SOMETHING_ELSE); | 1291 | DMA_SOMETHING_ELSE); |
| 1244 | #endif | 1292 | #endif |
| 1245 | spin_unlock(&chip->reg_lock); | 1293 | spin_unlock(codec->lock); |
| 1246 | snd_azf3328_ctrl_codec_activity(chip, codec_type, 1); | 1294 | snd_azf3328_ctrl_codec_activity(chip, codec->type, 1); |
| 1247 | 1295 | ||
| 1248 | if (is_playback_codec) { | 1296 | if (is_main_mixer_playback_codec) { |
| 1249 | /* now unmute WaveOut */ | 1297 | /* now unmute WaveOut */ |
| 1250 | if (!previously_muted) | 1298 | if (!previously_muted) |
| 1251 | snd_azf3328_mixer_set_mute( | 1299 | snd_azf3328_mixer_set_mute( |
| @@ -1258,19 +1306,19 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type, | |||
| 1258 | case SNDRV_PCM_TRIGGER_RESUME: | 1306 | case SNDRV_PCM_TRIGGER_RESUME: |
| 1259 | snd_azf3328_dbgcodec("RESUME %s\n", codec->name); | 1307 | snd_azf3328_dbgcodec("RESUME %s\n", codec->name); |
| 1260 | /* resume codec if we were active */ | 1308 | /* resume codec if we were active */ |
| 1261 | spin_lock(&chip->reg_lock); | 1309 | spin_lock(codec->lock); |
| 1262 | if (codec->running) | 1310 | if (codec->running) |
| 1263 | snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, | 1311 | snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, |
| 1264 | snd_azf3328_codec_inw( | 1312 | snd_azf3328_codec_inw( |
| 1265 | codec, IDX_IO_CODEC_DMA_FLAGS | 1313 | codec, IDX_IO_CODEC_DMA_FLAGS |
| 1266 | ) | DMA_RESUME | 1314 | ) | DMA_RESUME |
| 1267 | ); | 1315 | ); |
| 1268 | spin_unlock(&chip->reg_lock); | 1316 | spin_unlock(codec->lock); |
| 1269 | break; | 1317 | break; |
| 1270 | case SNDRV_PCM_TRIGGER_STOP: | 1318 | case SNDRV_PCM_TRIGGER_STOP: |
| 1271 | snd_azf3328_dbgcodec("STOP %s\n", codec->name); | 1319 | snd_azf3328_dbgcodec("STOP %s\n", codec->name); |
| 1272 | 1320 | ||
| 1273 | if (is_playback_codec) { | 1321 | if (is_main_mixer_playback_codec) { |
| 1274 | /* mute WaveOut (avoid clicking during setup) */ | 1322 | /* mute WaveOut (avoid clicking during setup) */ |
| 1275 | previously_muted = | 1323 | previously_muted = |
| 1276 | snd_azf3328_mixer_set_mute( | 1324 | snd_azf3328_mixer_set_mute( |
| @@ -1278,7 +1326,7 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type, | |||
| 1278 | ); | 1326 | ); |
| 1279 | } | 1327 | } |
| 1280 | 1328 | ||
| 1281 | spin_lock(&chip->reg_lock); | 1329 | spin_lock(codec->lock); |
| 1282 | /* first, remember current value: */ | 1330 | /* first, remember current value: */ |
| 1283 | flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS); | 1331 | flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS); |
| 1284 | 1332 | ||
| @@ -1293,10 +1341,10 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type, | |||
| 1293 | 1341 | ||
| 1294 | flags1 &= ~DMA_RUN_SOMETHING1; | 1342 | flags1 &= ~DMA_RUN_SOMETHING1; |
| 1295 | snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); | 1343 | snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); |
| 1296 | spin_unlock(&chip->reg_lock); | 1344 | spin_unlock(codec->lock); |
| 1297 | snd_azf3328_ctrl_codec_activity(chip, codec_type, 0); | 1345 | snd_azf3328_ctrl_codec_activity(chip, codec->type, 0); |
| 1298 | 1346 | ||
| 1299 | if (is_playback_codec) { | 1347 | if (is_main_mixer_playback_codec) { |
| 1300 | /* now unmute WaveOut */ | 1348 | /* now unmute WaveOut */ |
| 1301 | if (!previously_muted) | 1349 | if (!previously_muted) |
| 1302 | snd_azf3328_mixer_set_mute( | 1350 | snd_azf3328_mixer_set_mute( |
| @@ -1330,67 +1378,29 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type, | |||
| 1330 | return result; | 1378 | return result; |
| 1331 | } | 1379 | } |
| 1332 | 1380 | ||
| 1333 | static int | ||
| 1334 | snd_azf3328_codec_playback_trigger(struct snd_pcm_substream *substream, int cmd) | ||
| 1335 | { | ||
| 1336 | return snd_azf3328_codec_trigger(AZF_CODEC_PLAYBACK, substream, cmd); | ||
| 1337 | } | ||
| 1338 | |||
| 1339 | static int | ||
| 1340 | snd_azf3328_codec_capture_trigger(struct snd_pcm_substream *substream, int cmd) | ||
| 1341 | { | ||
| 1342 | return snd_azf3328_codec_trigger(AZF_CODEC_CAPTURE, substream, cmd); | ||
| 1343 | } | ||
| 1344 | |||
| 1345 | static int | ||
| 1346 | snd_azf3328_codec_i2s_out_trigger(struct snd_pcm_substream *substream, int cmd) | ||
| 1347 | { | ||
| 1348 | return snd_azf3328_codec_trigger(AZF_CODEC_I2S_OUT, substream, cmd); | ||
| 1349 | } | ||
| 1350 | |||
| 1351 | static snd_pcm_uframes_t | 1381 | static snd_pcm_uframes_t |
| 1352 | snd_azf3328_codec_pointer(struct snd_pcm_substream *substream, | 1382 | snd_azf3328_pcm_pointer(struct snd_pcm_substream *substream |
| 1353 | enum snd_azf3328_codec_type codec_type | ||
| 1354 | ) | 1383 | ) |
| 1355 | { | 1384 | { |
| 1356 | const struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); | 1385 | const struct snd_azf3328_codec_data *codec = |
| 1357 | const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type]; | 1386 | substream->runtime->private_data; |
| 1358 | unsigned long bufptr, result; | 1387 | unsigned long result; |
| 1359 | snd_pcm_uframes_t frmres; | 1388 | snd_pcm_uframes_t frmres; |
| 1360 | 1389 | ||
| 1361 | #ifdef QUERY_HARDWARE | ||
| 1362 | bufptr = snd_azf3328_codec_inl(codec, IDX_IO_CODEC_DMA_START_1); | ||
| 1363 | #else | ||
| 1364 | bufptr = substream->runtime->dma_addr; | ||
| 1365 | #endif | ||
| 1366 | result = snd_azf3328_codec_inl(codec, IDX_IO_CODEC_DMA_CURRPOS); | 1390 | result = snd_azf3328_codec_inl(codec, IDX_IO_CODEC_DMA_CURRPOS); |
| 1367 | 1391 | ||
| 1368 | /* calculate offset */ | 1392 | /* calculate offset */ |
| 1369 | result -= bufptr; | 1393 | #ifdef QUERY_HARDWARE |
| 1394 | result -= snd_azf3328_codec_inl(codec, IDX_IO_CODEC_DMA_START_1); | ||
| 1395 | #else | ||
| 1396 | result -= codec->dma_base; | ||
| 1397 | #endif | ||
| 1370 | frmres = bytes_to_frames( substream->runtime, result); | 1398 | frmres = bytes_to_frames( substream->runtime, result); |
| 1371 | snd_azf3328_dbgcodec("%s @ 0x%8lx, frames %8ld\n", | 1399 | snd_azf3328_dbgcodec("%08li %s @ 0x%8lx, frames %8ld\n", |
| 1372 | codec->name, result, frmres); | 1400 | jiffies, codec->name, result, frmres); |
| 1373 | return frmres; | 1401 | return frmres; |
| 1374 | } | 1402 | } |
| 1375 | 1403 | ||
| 1376 | static snd_pcm_uframes_t | ||
| 1377 | snd_azf3328_codec_playback_pointer(struct snd_pcm_substream *substream) | ||
| 1378 | { | ||
| 1379 | return snd_azf3328_codec_pointer(substream, AZF_CODEC_PLAYBACK); | ||
| 1380 | } | ||
| 1381 | |||
| 1382 | static snd_pcm_uframes_t | ||
| 1383 | snd_azf3328_codec_capture_pointer(struct snd_pcm_substream *substream) | ||
| 1384 | { | ||
| 1385 | return snd_azf3328_codec_pointer(substream, AZF_CODEC_CAPTURE); | ||
| 1386 | } | ||
| 1387 | |||
| 1388 | static snd_pcm_uframes_t | ||
| 1389 | snd_azf3328_codec_i2s_out_pointer(struct snd_pcm_substream *substream) | ||
| 1390 | { | ||
| 1391 | return snd_azf3328_codec_pointer(substream, AZF_CODEC_I2S_OUT); | ||
| 1392 | } | ||
| 1393 | |||
| 1394 | /******************************************************************/ | 1404 | /******************************************************************/ |
| 1395 | 1405 | ||
| 1396 | #ifdef SUPPORT_GAMEPORT | 1406 | #ifdef SUPPORT_GAMEPORT |
| @@ -1532,7 +1542,7 @@ snd_azf3328_gameport_cooked_read(struct gameport *gameport, | |||
| 1532 | } | 1542 | } |
| 1533 | } | 1543 | } |
| 1534 | 1544 | ||
| 1535 | /* trigger next axes sampling, to be evaluated the next time we | 1545 | /* trigger next sampling of axes, to be evaluated the next time we |
| 1536 | * enter this function */ | 1546 | * enter this function */ |
| 1537 | 1547 | ||
| 1538 | /* for some very, very strange reason we cannot enable | 1548 | /* for some very, very strange reason we cannot enable |
| @@ -1624,29 +1634,29 @@ snd_azf3328_irq_log_unknown_type(u8 which) | |||
| 1624 | } | 1634 | } |
| 1625 | 1635 | ||
| 1626 | static inline void | 1636 | static inline void |
| 1627 | snd_azf3328_codec_interrupt(struct snd_azf3328 *chip, u8 status) | 1637 | snd_azf3328_pcm_interrupt(const struct snd_azf3328_codec_data *first_codec, |
| 1638 | u8 status | ||
| 1639 | ) | ||
| 1628 | { | 1640 | { |
| 1629 | u8 which; | 1641 | u8 which; |
| 1630 | enum snd_azf3328_codec_type codec_type; | 1642 | enum snd_azf3328_codec_type codec_type; |
| 1631 | const struct snd_azf3328_codec_data *codec; | 1643 | const struct snd_azf3328_codec_data *codec = first_codec; |
| 1632 | 1644 | ||
| 1633 | for (codec_type = AZF_CODEC_PLAYBACK; | 1645 | for (codec_type = AZF_CODEC_PLAYBACK; |
| 1634 | codec_type <= AZF_CODEC_I2S_OUT; | 1646 | codec_type <= AZF_CODEC_I2S_OUT; |
| 1635 | ++codec_type) { | 1647 | ++codec_type, ++codec) { |
| 1636 | 1648 | ||
| 1637 | /* skip codec if there's no interrupt for it */ | 1649 | /* skip codec if there's no interrupt for it */ |
| 1638 | if (!(status & (1 << codec_type))) | 1650 | if (!(status & (1 << codec_type))) |
| 1639 | continue; | 1651 | continue; |
| 1640 | 1652 | ||
| 1641 | codec = &chip->codecs[codec_type]; | 1653 | spin_lock(codec->lock); |
| 1642 | |||
| 1643 | spin_lock(&chip->reg_lock); | ||
| 1644 | which = snd_azf3328_codec_inb(codec, IDX_IO_CODEC_IRQTYPE); | 1654 | which = snd_azf3328_codec_inb(codec, IDX_IO_CODEC_IRQTYPE); |
| 1645 | /* ack all IRQ types immediately */ | 1655 | /* ack all IRQ types immediately */ |
| 1646 | snd_azf3328_codec_outb(codec, IDX_IO_CODEC_IRQTYPE, which); | 1656 | snd_azf3328_codec_outb(codec, IDX_IO_CODEC_IRQTYPE, which); |
| 1647 | spin_unlock(&chip->reg_lock); | 1657 | spin_unlock(codec->lock); |
| 1648 | 1658 | ||
| 1649 | if ((chip->pcm[codec_type]) && (codec->substream)) { | 1659 | if (codec->substream) { |
| 1650 | snd_pcm_period_elapsed(codec->substream); | 1660 | snd_pcm_period_elapsed(codec->substream); |
| 1651 | snd_azf3328_dbgcodec("%s period done (#%x), @ %x\n", | 1661 | snd_azf3328_dbgcodec("%s period done (#%x), @ %x\n", |
| 1652 | codec->name, | 1662 | codec->name, |
| @@ -1701,7 +1711,7 @@ snd_azf3328_interrupt(int irq, void *dev_id) | |||
| 1701 | } | 1711 | } |
| 1702 | 1712 | ||
| 1703 | if (status & (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_I2S_OUT)) | 1713 | if (status & (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_I2S_OUT)) |
| 1704 | snd_azf3328_codec_interrupt(chip, status); | 1714 | snd_azf3328_pcm_interrupt(chip->codecs, status); |
| 1705 | 1715 | ||
| 1706 | if (status & IRQ_GAMEPORT) | 1716 | if (status & IRQ_GAMEPORT) |
| 1707 | snd_azf3328_gameport_interrupt(chip); | 1717 | snd_azf3328_gameport_interrupt(chip); |
| @@ -1789,101 +1799,85 @@ snd_azf3328_pcm_open(struct snd_pcm_substream *substream, | |||
| 1789 | { | 1799 | { |
| 1790 | struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); | 1800 | struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); |
| 1791 | struct snd_pcm_runtime *runtime = substream->runtime; | 1801 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 1802 | struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type]; | ||
| 1792 | 1803 | ||
| 1793 | snd_azf3328_dbgcallenter(); | 1804 | snd_azf3328_dbgcallenter(); |
| 1794 | chip->codecs[codec_type].substream = substream; | 1805 | codec->substream = substream; |
| 1795 | 1806 | ||
| 1796 | /* same parameters for all our codecs - at least we think so... */ | 1807 | /* same parameters for all our codecs - at least we think so... */ |
| 1797 | runtime->hw = snd_azf3328_hardware; | 1808 | runtime->hw = snd_azf3328_hardware; |
| 1798 | 1809 | ||
| 1799 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | 1810 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, |
| 1800 | &snd_azf3328_hw_constraints_rates); | 1811 | &snd_azf3328_hw_constraints_rates); |
| 1812 | runtime->private_data = codec; | ||
| 1801 | snd_azf3328_dbgcallleave(); | 1813 | snd_azf3328_dbgcallleave(); |
| 1802 | return 0; | 1814 | return 0; |
| 1803 | } | 1815 | } |
| 1804 | 1816 | ||
| 1805 | static int | 1817 | static int |
| 1806 | snd_azf3328_playback_open(struct snd_pcm_substream *substream) | 1818 | snd_azf3328_pcm_playback_open(struct snd_pcm_substream *substream) |
| 1807 | { | 1819 | { |
| 1808 | return snd_azf3328_pcm_open(substream, AZF_CODEC_PLAYBACK); | 1820 | return snd_azf3328_pcm_open(substream, AZF_CODEC_PLAYBACK); |
| 1809 | } | 1821 | } |
| 1810 | 1822 | ||
| 1811 | static int | 1823 | static int |
| 1812 | snd_azf3328_capture_open(struct snd_pcm_substream *substream) | 1824 | snd_azf3328_pcm_capture_open(struct snd_pcm_substream *substream) |
| 1813 | { | 1825 | { |
| 1814 | return snd_azf3328_pcm_open(substream, AZF_CODEC_CAPTURE); | 1826 | return snd_azf3328_pcm_open(substream, AZF_CODEC_CAPTURE); |
| 1815 | } | 1827 | } |
| 1816 | 1828 | ||
| 1817 | static int | 1829 | static int |
| 1818 | snd_azf3328_i2s_out_open(struct snd_pcm_substream *substream) | 1830 | snd_azf3328_pcm_i2s_out_open(struct snd_pcm_substream *substream) |
| 1819 | { | 1831 | { |
| 1820 | return snd_azf3328_pcm_open(substream, AZF_CODEC_I2S_OUT); | 1832 | return snd_azf3328_pcm_open(substream, AZF_CODEC_I2S_OUT); |
| 1821 | } | 1833 | } |
| 1822 | 1834 | ||
| 1823 | static int | 1835 | static int |
| 1824 | snd_azf3328_pcm_close(struct snd_pcm_substream *substream, | 1836 | snd_azf3328_pcm_close(struct snd_pcm_substream *substream |
| 1825 | enum snd_azf3328_codec_type codec_type | ||
| 1826 | ) | 1837 | ) |
| 1827 | { | 1838 | { |
| 1828 | struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); | 1839 | struct snd_azf3328_codec_data *codec = |
| 1840 | substream->runtime->private_data; | ||
| 1829 | 1841 | ||
| 1830 | snd_azf3328_dbgcallenter(); | 1842 | snd_azf3328_dbgcallenter(); |
| 1831 | chip->codecs[codec_type].substream = NULL; | 1843 | codec->substream = NULL; |
| 1832 | snd_azf3328_dbgcallleave(); | 1844 | snd_azf3328_dbgcallleave(); |
| 1833 | return 0; | 1845 | return 0; |
| 1834 | } | 1846 | } |
| 1835 | 1847 | ||
| 1836 | static int | ||
| 1837 | snd_azf3328_playback_close(struct snd_pcm_substream *substream) | ||
| 1838 | { | ||
| 1839 | return snd_azf3328_pcm_close(substream, AZF_CODEC_PLAYBACK); | ||
| 1840 | } | ||
| 1841 | |||
| 1842 | static int | ||
| 1843 | snd_azf3328_capture_close(struct snd_pcm_substream *substream) | ||
| 1844 | { | ||
| 1845 | return snd_azf3328_pcm_close(substream, AZF_CODEC_CAPTURE); | ||
| 1846 | } | ||
| 1847 | |||
| 1848 | static int | ||
| 1849 | snd_azf3328_i2s_out_close(struct snd_pcm_substream *substream) | ||
| 1850 | { | ||
| 1851 | return snd_azf3328_pcm_close(substream, AZF_CODEC_I2S_OUT); | ||
| 1852 | } | ||
| 1853 | |||
| 1854 | /******************************************************************/ | 1848 | /******************************************************************/ |
| 1855 | 1849 | ||
| 1856 | static struct snd_pcm_ops snd_azf3328_playback_ops = { | 1850 | static struct snd_pcm_ops snd_azf3328_playback_ops = { |
| 1857 | .open = snd_azf3328_playback_open, | 1851 | .open = snd_azf3328_pcm_playback_open, |
| 1858 | .close = snd_azf3328_playback_close, | 1852 | .close = snd_azf3328_pcm_close, |
| 1859 | .ioctl = snd_pcm_lib_ioctl, | 1853 | .ioctl = snd_pcm_lib_ioctl, |
| 1860 | .hw_params = snd_azf3328_hw_params, | 1854 | .hw_params = snd_azf3328_hw_params, |
| 1861 | .hw_free = snd_azf3328_hw_free, | 1855 | .hw_free = snd_azf3328_hw_free, |
| 1862 | .prepare = snd_azf3328_codec_prepare, | 1856 | .prepare = snd_azf3328_pcm_prepare, |
| 1863 | .trigger = snd_azf3328_codec_playback_trigger, | 1857 | .trigger = snd_azf3328_pcm_trigger, |
| 1864 | .pointer = snd_azf3328_codec_playback_pointer | 1858 | .pointer = snd_azf3328_pcm_pointer |
| 1865 | }; | 1859 | }; |
| 1866 | 1860 | ||
| 1867 | static struct snd_pcm_ops snd_azf3328_capture_ops = { | 1861 | static struct snd_pcm_ops snd_azf3328_capture_ops = { |
| 1868 | .open = snd_azf3328_capture_open, | 1862 | .open = snd_azf3328_pcm_capture_open, |
| 1869 | .close = snd_azf3328_capture_close, | 1863 | .close = snd_azf3328_pcm_close, |
| 1870 | .ioctl = snd_pcm_lib_ioctl, | 1864 | .ioctl = snd_pcm_lib_ioctl, |
| 1871 | .hw_params = snd_azf3328_hw_params, | 1865 | .hw_params = snd_azf3328_hw_params, |
| 1872 | .hw_free = snd_azf3328_hw_free, | 1866 | .hw_free = snd_azf3328_hw_free, |
| 1873 | .prepare = snd_azf3328_codec_prepare, | 1867 | .prepare = snd_azf3328_pcm_prepare, |
| 1874 | .trigger = snd_azf3328_codec_capture_trigger, | 1868 | .trigger = snd_azf3328_pcm_trigger, |
| 1875 | .pointer = snd_azf3328_codec_capture_pointer | 1869 | .pointer = snd_azf3328_pcm_pointer |
| 1876 | }; | 1870 | }; |
| 1877 | 1871 | ||
| 1878 | static struct snd_pcm_ops snd_azf3328_i2s_out_ops = { | 1872 | static struct snd_pcm_ops snd_azf3328_i2s_out_ops = { |
| 1879 | .open = snd_azf3328_i2s_out_open, | 1873 | .open = snd_azf3328_pcm_i2s_out_open, |
| 1880 | .close = snd_azf3328_i2s_out_close, | 1874 | .close = snd_azf3328_pcm_close, |
| 1881 | .ioctl = snd_pcm_lib_ioctl, | 1875 | .ioctl = snd_pcm_lib_ioctl, |
| 1882 | .hw_params = snd_azf3328_hw_params, | 1876 | .hw_params = snd_azf3328_hw_params, |
| 1883 | .hw_free = snd_azf3328_hw_free, | 1877 | .hw_free = snd_azf3328_hw_free, |
| 1884 | .prepare = snd_azf3328_codec_prepare, | 1878 | .prepare = snd_azf3328_pcm_prepare, |
| 1885 | .trigger = snd_azf3328_codec_i2s_out_trigger, | 1879 | .trigger = snd_azf3328_pcm_trigger, |
| 1886 | .pointer = snd_azf3328_codec_i2s_out_pointer | 1880 | .pointer = snd_azf3328_pcm_pointer |
| 1887 | }; | 1881 | }; |
| 1888 | 1882 | ||
| 1889 | static int __devinit | 1883 | static int __devinit |
| @@ -1966,7 +1960,7 @@ snd_azf3328_timer_start(struct snd_timer *timer) | |||
| 1966 | snd_azf3328_dbgtimer("delay was too low (%d)!\n", delay); | 1960 | snd_azf3328_dbgtimer("delay was too low (%d)!\n", delay); |
| 1967 | delay = 49; /* minimum time is 49 ticks */ | 1961 | delay = 49; /* minimum time is 49 ticks */ |
| 1968 | } | 1962 | } |
| 1969 | snd_azf3328_dbgtimer("setting timer countdown value %d, add COUNTDOWN|IRQ\n", delay); | 1963 | snd_azf3328_dbgtimer("setting timer countdown value %d\n", delay); |
| 1970 | delay |= TIMER_COUNTDOWN_ENABLE | TIMER_IRQ_ENABLE; | 1964 | delay |= TIMER_COUNTDOWN_ENABLE | TIMER_IRQ_ENABLE; |
| 1971 | spin_lock_irqsave(&chip->reg_lock, flags); | 1965 | spin_lock_irqsave(&chip->reg_lock, flags); |
| 1972 | snd_azf3328_ctrl_outl(chip, IDX_IO_TIMER_VALUE, delay); | 1966 | snd_azf3328_ctrl_outl(chip, IDX_IO_TIMER_VALUE, delay); |
| @@ -2180,6 +2174,7 @@ snd_azf3328_create(struct snd_card *card, | |||
| 2180 | }; | 2174 | }; |
| 2181 | u8 dma_init; | 2175 | u8 dma_init; |
| 2182 | enum snd_azf3328_codec_type codec_type; | 2176 | enum snd_azf3328_codec_type codec_type; |
| 2177 | struct snd_azf3328_codec_data *codec_setup; | ||
| 2183 | 2178 | ||
| 2184 | *rchip = NULL; | 2179 | *rchip = NULL; |
| 2185 | 2180 | ||
| @@ -2217,15 +2212,23 @@ snd_azf3328_create(struct snd_card *card, | |||
| 2217 | chip->opl3_io = pci_resource_start(pci, 3); | 2212 | chip->opl3_io = pci_resource_start(pci, 3); |
| 2218 | chip->mixer_io = pci_resource_start(pci, 4); | 2213 | chip->mixer_io = pci_resource_start(pci, 4); |
| 2219 | 2214 | ||
| 2220 | chip->codecs[AZF_CODEC_PLAYBACK].io_base = | 2215 | codec_setup = &chip->codecs[AZF_CODEC_PLAYBACK]; |
| 2221 | chip->ctrl_io + AZF_IO_OFFS_CODEC_PLAYBACK; | 2216 | codec_setup->io_base = chip->ctrl_io + AZF_IO_OFFS_CODEC_PLAYBACK; |
| 2222 | chip->codecs[AZF_CODEC_PLAYBACK].name = "PLAYBACK"; | 2217 | codec_setup->lock = &chip->reg_lock; |
| 2223 | chip->codecs[AZF_CODEC_CAPTURE].io_base = | 2218 | codec_setup->type = AZF_CODEC_PLAYBACK; |
| 2224 | chip->ctrl_io + AZF_IO_OFFS_CODEC_CAPTURE; | 2219 | codec_setup->name = "PLAYBACK"; |
| 2225 | chip->codecs[AZF_CODEC_CAPTURE].name = "CAPTURE"; | 2220 | |
| 2226 | chip->codecs[AZF_CODEC_I2S_OUT].io_base = | 2221 | codec_setup = &chip->codecs[AZF_CODEC_CAPTURE]; |
| 2227 | chip->ctrl_io + AZF_IO_OFFS_CODEC_I2S_OUT; | 2222 | codec_setup->io_base = chip->ctrl_io + AZF_IO_OFFS_CODEC_CAPTURE; |
| 2228 | chip->codecs[AZF_CODEC_I2S_OUT].name = "I2S_OUT"; | 2223 | codec_setup->lock = &chip->reg_lock; |
| 2224 | codec_setup->type = AZF_CODEC_CAPTURE; | ||
| 2225 | codec_setup->name = "CAPTURE"; | ||
| 2226 | |||
| 2227 | codec_setup = &chip->codecs[AZF_CODEC_I2S_OUT]; | ||
| 2228 | codec_setup->io_base = chip->ctrl_io + AZF_IO_OFFS_CODEC_I2S_OUT; | ||
| 2229 | codec_setup->lock = &chip->reg_lock; | ||
| 2230 | codec_setup->type = AZF_CODEC_I2S_OUT; | ||
| 2231 | codec_setup->name = "I2S_OUT"; | ||
| 2229 | 2232 | ||
| 2230 | if (request_irq(pci->irq, snd_azf3328_interrupt, | 2233 | if (request_irq(pci->irq, snd_azf3328_interrupt, |
| 2231 | IRQF_SHARED, card->shortname, chip)) { | 2234 | IRQF_SHARED, card->shortname, chip)) { |
| @@ -2257,15 +2260,15 @@ snd_azf3328_create(struct snd_card *card, | |||
| 2257 | struct snd_azf3328_codec_data *codec = | 2260 | struct snd_azf3328_codec_data *codec = |
| 2258 | &chip->codecs[codec_type]; | 2261 | &chip->codecs[codec_type]; |
| 2259 | 2262 | ||
| 2260 | /* shutdown codecs to save power */ | 2263 | /* shutdown codecs to reduce power / noise */ |
| 2261 | /* have ...ctrl_codec_activity() act properly */ | 2264 | /* have ...ctrl_codec_activity() act properly */ |
| 2262 | codec->running = 1; | 2265 | codec->running = 1; |
| 2263 | snd_azf3328_ctrl_codec_activity(chip, codec_type, 0); | 2266 | snd_azf3328_ctrl_codec_activity(chip, codec_type, 0); |
| 2264 | 2267 | ||
| 2265 | spin_lock_irq(&chip->reg_lock); | 2268 | spin_lock_irq(codec->lock); |
| 2266 | snd_azf3328_codec_outb(codec, IDX_IO_CODEC_DMA_FLAGS, | 2269 | snd_azf3328_codec_outb(codec, IDX_IO_CODEC_DMA_FLAGS, |
| 2267 | dma_init); | 2270 | dma_init); |
| 2268 | spin_unlock_irq(&chip->reg_lock); | 2271 | spin_unlock_irq(codec->lock); |
| 2269 | } | 2272 | } |
| 2270 | 2273 | ||
| 2271 | snd_card_set_dev(card, &pci->dev); | 2274 | snd_card_set_dev(card, &pci->dev); |
| @@ -2419,6 +2422,7 @@ snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state) | |||
| 2419 | 2422 | ||
| 2420 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 2423 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
| 2421 | 2424 | ||
| 2425 | /* same pcm object for playback/capture */ | ||
| 2422 | snd_pcm_suspend_all(chip->pcm[AZF_CODEC_PLAYBACK]); | 2426 | snd_pcm_suspend_all(chip->pcm[AZF_CODEC_PLAYBACK]); |
| 2423 | snd_pcm_suspend_all(chip->pcm[AZF_CODEC_I2S_OUT]); | 2427 | snd_pcm_suspend_all(chip->pcm[AZF_CODEC_I2S_OUT]); |
| 2424 | 2428 | ||
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 37e1b5df5ab8..2958a05b5293 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c | |||
| @@ -637,15 +637,9 @@ static struct snd_kcontrol_new snd_bt87x_capture_boost = { | |||
| 637 | static int snd_bt87x_capture_source_info(struct snd_kcontrol *kcontrol, | 637 | static int snd_bt87x_capture_source_info(struct snd_kcontrol *kcontrol, |
| 638 | struct snd_ctl_elem_info *info) | 638 | struct snd_ctl_elem_info *info) |
| 639 | { | 639 | { |
| 640 | static char *texts[3] = {"TV Tuner", "FM", "Mic/Line"}; | 640 | static const char *const texts[3] = {"TV Tuner", "FM", "Mic/Line"}; |
| 641 | 641 | ||
| 642 | info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 642 | return snd_ctl_enum_info(info, 1, 3, texts); |
| 643 | info->count = 1; | ||
| 644 | info->value.enumerated.items = 3; | ||
| 645 | if (info->value.enumerated.item > 2) | ||
| 646 | info->value.enumerated.item = 2; | ||
| 647 | strcpy(info->value.enumerated.name, texts[info->value.enumerated.item]); | ||
| 648 | return 0; | ||
| 649 | } | 643 | } |
| 650 | 644 | ||
| 651 | static int snd_bt87x_capture_source_get(struct snd_kcontrol *kcontrol, | 645 | static int snd_bt87x_capture_source_get(struct snd_kcontrol *kcontrol, |
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 329968edca9b..b5bb036ef73c 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c | |||
| @@ -2507,14 +2507,12 @@ static int snd_cmipci_line_in_mode_info(struct snd_kcontrol *kcontrol, | |||
| 2507 | struct snd_ctl_elem_info *uinfo) | 2507 | struct snd_ctl_elem_info *uinfo) |
| 2508 | { | 2508 | { |
| 2509 | struct cmipci *cm = snd_kcontrol_chip(kcontrol); | 2509 | struct cmipci *cm = snd_kcontrol_chip(kcontrol); |
| 2510 | static char *texts[3] = { "Line-In", "Rear Output", "Bass Output" }; | 2510 | static const char *const texts[3] = { |
| 2511 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 2511 | "Line-In", "Rear Output", "Bass Output" |
| 2512 | uinfo->count = 1; | 2512 | }; |
| 2513 | uinfo->value.enumerated.items = cm->chip_version >= 39 ? 3 : 2; | 2513 | |
| 2514 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | 2514 | return snd_ctl_enum_info(uinfo, 1, |
| 2515 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; | 2515 | cm->chip_version >= 39 ? 3 : 2, texts); |
| 2516 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
| 2517 | return 0; | ||
| 2518 | } | 2516 | } |
| 2519 | 2517 | ||
| 2520 | static inline unsigned int get_line_in_mode(struct cmipci *cm) | 2518 | static inline unsigned int get_line_in_mode(struct cmipci *cm) |
| @@ -2564,14 +2562,9 @@ static int snd_cmipci_line_in_mode_put(struct snd_kcontrol *kcontrol, | |||
| 2564 | static int snd_cmipci_mic_in_mode_info(struct snd_kcontrol *kcontrol, | 2562 | static int snd_cmipci_mic_in_mode_info(struct snd_kcontrol *kcontrol, |
| 2565 | struct snd_ctl_elem_info *uinfo) | 2563 | struct snd_ctl_elem_info *uinfo) |
| 2566 | { | 2564 | { |
| 2567 | static char *texts[2] = { "Mic-In", "Center/LFE Output" }; | 2565 | static const char *const texts[2] = { "Mic-In", "Center/LFE Output" }; |
| 2568 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 2566 | |
| 2569 | uinfo->count = 1; | 2567 | return snd_ctl_enum_info(uinfo, 1, 2, texts); |
| 2570 | uinfo->value.enumerated.items = 2; | ||
| 2571 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
| 2572 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; | ||
| 2573 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
| 2574 | return 0; | ||
| 2575 | } | 2568 | } |
| 2576 | 2569 | ||
| 2577 | static int snd_cmipci_mic_in_mode_get(struct snd_kcontrol *kcontrol, | 2570 | static int snd_cmipci_mic_in_mode_get(struct snd_kcontrol *kcontrol, |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 98b6d02a36c9..05e5ec88c2d9 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
| @@ -4571,6 +4571,9 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
| 4571 | } | 4571 | } |
| 4572 | memset(cfg->hp_pins + cfg->hp_outs, 0, | 4572 | memset(cfg->hp_pins + cfg->hp_outs, 0, |
| 4573 | sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - cfg->hp_outs)); | 4573 | sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - cfg->hp_outs)); |
| 4574 | if (!cfg->hp_outs) | ||
| 4575 | cfg->line_out_type = AUTO_PIN_HP_OUT; | ||
| 4576 | |||
| 4574 | } | 4577 | } |
| 4575 | 4578 | ||
| 4576 | /* sort by sequence */ | 4579 | /* sort by sequence */ |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index a1c4008af891..d3d18be483e1 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
| @@ -1235,7 +1235,8 @@ static int azx_setup_periods(struct azx *chip, | |||
| 1235 | pos_adj = 0; | 1235 | pos_adj = 0; |
| 1236 | } else { | 1236 | } else { |
| 1237 | ofs = setup_bdle(substream, azx_dev, | 1237 | ofs = setup_bdle(substream, azx_dev, |
| 1238 | &bdl, ofs, pos_adj, 1); | 1238 | &bdl, ofs, pos_adj, |
| 1239 | !substream->runtime->no_period_wakeup); | ||
| 1239 | if (ofs < 0) | 1240 | if (ofs < 0) |
| 1240 | goto error; | 1241 | goto error; |
| 1241 | } | 1242 | } |
| @@ -1247,7 +1248,8 @@ static int azx_setup_periods(struct azx *chip, | |||
| 1247 | period_bytes - pos_adj, 0); | 1248 | period_bytes - pos_adj, 0); |
| 1248 | else | 1249 | else |
| 1249 | ofs = setup_bdle(substream, azx_dev, &bdl, ofs, | 1250 | ofs = setup_bdle(substream, azx_dev, &bdl, ofs, |
| 1250 | period_bytes, 1); | 1251 | period_bytes, |
| 1252 | !substream->runtime->no_period_wakeup); | ||
| 1251 | if (ofs < 0) | 1253 | if (ofs < 0) |
| 1252 | goto error; | 1254 | goto error; |
| 1253 | } | 1255 | } |
| @@ -1515,7 +1517,8 @@ static struct snd_pcm_hardware azx_pcm_hw = { | |||
| 1515 | /* No full-resume yet implemented */ | 1517 | /* No full-resume yet implemented */ |
| 1516 | /* SNDRV_PCM_INFO_RESUME |*/ | 1518 | /* SNDRV_PCM_INFO_RESUME |*/ |
| 1517 | SNDRV_PCM_INFO_PAUSE | | 1519 | SNDRV_PCM_INFO_PAUSE | |
| 1518 | SNDRV_PCM_INFO_SYNC_START), | 1520 | SNDRV_PCM_INFO_SYNC_START | |
| 1521 | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP), | ||
| 1519 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 1522 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
| 1520 | .rates = SNDRV_PCM_RATE_48000, | 1523 | .rates = SNDRV_PCM_RATE_48000, |
| 1521 | .rate_min = 48000, | 1524 | .rate_min = 48000, |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index f7ff3f7ccb8e..46780670162b 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
| @@ -666,7 +666,7 @@ static struct snd_kcontrol_new ad1986a_mixers[] = { | |||
| 666 | HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT), | 666 | HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT), |
| 667 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), | 667 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), |
| 668 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), | 668 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), |
| 669 | HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), | 669 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT), |
| 670 | HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT), | 670 | HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT), |
| 671 | HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), | 671 | HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), |
| 672 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), | 672 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), |
| @@ -729,7 +729,7 @@ static struct snd_kcontrol_new ad1986a_laptop_mixers[] = { | |||
| 729 | HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT), | 729 | HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT), |
| 730 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), | 730 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), |
| 731 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), | 731 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), |
| 732 | HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), | 732 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT), |
| 733 | /* | 733 | /* |
| 734 | HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT), | 734 | HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT), |
| 735 | HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */ | 735 | HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */ |
| @@ -775,7 +775,7 @@ static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { | |||
| 775 | HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), | 775 | HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), |
| 776 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), | 776 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), |
| 777 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), | 777 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), |
| 778 | HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), | 778 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT), |
| 779 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), | 779 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), |
| 780 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), | 780 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), |
| 781 | { | 781 | { |
| @@ -1358,7 +1358,7 @@ static struct snd_kcontrol_new ad1983_mixers[] = { | |||
| 1358 | HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), | 1358 | HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), |
| 1359 | HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT), | 1359 | HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT), |
| 1360 | HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT), | 1360 | HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT), |
| 1361 | HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT), | 1361 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x0c, 0x0, HDA_OUTPUT), |
| 1362 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), | 1362 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), |
| 1363 | HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), | 1363 | HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), |
| 1364 | { | 1364 | { |
| @@ -1515,8 +1515,8 @@ static struct snd_kcontrol_new ad1981_mixers[] = { | |||
| 1515 | HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT), | 1515 | HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT), |
| 1516 | HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), | 1516 | HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), |
| 1517 | HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), | 1517 | HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), |
| 1518 | HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT), | 1518 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x08, 0x0, HDA_INPUT), |
| 1519 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT), | 1519 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x0, HDA_INPUT), |
| 1520 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), | 1520 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), |
| 1521 | HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), | 1521 | HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), |
| 1522 | { | 1522 | { |
| @@ -1726,8 +1726,8 @@ static struct snd_kcontrol_new ad1981_hp_mixers[] = { | |||
| 1726 | HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), | 1726 | HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), |
| 1727 | HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), | 1727 | HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), |
| 1728 | #endif | 1728 | #endif |
| 1729 | HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT), | 1729 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x08, 0x0, HDA_INPUT), |
| 1730 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x18, 0x0, HDA_INPUT), | 1730 | HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x18, 0x0, HDA_INPUT), |
| 1731 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), | 1731 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), |
| 1732 | HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), | 1732 | HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), |
| 1733 | { | 1733 | { |
| @@ -1774,7 +1774,7 @@ static struct snd_kcontrol_new ad1981_thinkpad_mixers[] = { | |||
| 1774 | HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), | 1774 | HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), |
| 1775 | HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), | 1775 | HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), |
| 1776 | HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), | 1776 | HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), |
| 1777 | HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT), | 1777 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x08, 0x0, HDA_INPUT), |
| 1778 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), | 1778 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), |
| 1779 | HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), | 1779 | HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), |
| 1780 | { | 1780 | { |
| @@ -2160,8 +2160,8 @@ static struct snd_kcontrol_new ad1988_6stack_mixers2[] = { | |||
| 2160 | HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), | 2160 | HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), |
| 2161 | HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), | 2161 | HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), |
| 2162 | 2162 | ||
| 2163 | HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT), | 2163 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT), |
| 2164 | HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT), | 2164 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT), |
| 2165 | 2165 | ||
| 2166 | { } /* end */ | 2166 | { } /* end */ |
| 2167 | }; | 2167 | }; |
| @@ -2203,8 +2203,8 @@ static struct snd_kcontrol_new ad1988_3stack_mixers2[] = { | |||
| 2203 | HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), | 2203 | HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), |
| 2204 | HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), | 2204 | HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), |
| 2205 | 2205 | ||
| 2206 | HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT), | 2206 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT), |
| 2207 | HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT), | 2207 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT), |
| 2208 | { | 2208 | { |
| 2209 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2209 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
| 2210 | .name = "Channel Mode", | 2210 | .name = "Channel Mode", |
| @@ -2232,7 +2232,7 @@ static struct snd_kcontrol_new ad1988_laptop_mixers[] = { | |||
| 2232 | HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), | 2232 | HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), |
| 2233 | HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), | 2233 | HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), |
| 2234 | 2234 | ||
| 2235 | HDA_CODEC_VOLUME("Mic Boost", 0x39, 0x0, HDA_OUTPUT), | 2235 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT), |
| 2236 | 2236 | ||
| 2237 | { | 2237 | { |
| 2238 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2238 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
| @@ -2902,7 +2902,7 @@ static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin, | |||
| 2902 | idx = ad1988_pin_idx(pin); | 2902 | idx = ad1988_pin_idx(pin); |
| 2903 | bnid = ad1988_boost_nids[idx]; | 2903 | bnid = ad1988_boost_nids[idx]; |
| 2904 | if (bnid) { | 2904 | if (bnid) { |
| 2905 | sprintf(name, "%s Boost", ctlname); | 2905 | sprintf(name, "%s Boost Volume", ctlname); |
| 2906 | return add_control(spec, AD_CTL_WIDGET_VOL, name, | 2906 | return add_control(spec, AD_CTL_WIDGET_VOL, name, |
| 2907 | HDA_COMPOSE_AMP_VAL(bnid, 3, idx, HDA_OUTPUT)); | 2907 | HDA_COMPOSE_AMP_VAL(bnid, 3, idx, HDA_OUTPUT)); |
| 2908 | 2908 | ||
| @@ -3300,8 +3300,8 @@ static struct snd_kcontrol_new ad1884_base_mixers[] = { | |||
| 3300 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT), | 3300 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT), |
| 3301 | HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT), | 3301 | HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT), |
| 3302 | HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT), | 3302 | HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT), |
| 3303 | HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT), | 3303 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT), |
| 3304 | HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT), | 3304 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT), |
| 3305 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), | 3305 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), |
| 3306 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), | 3306 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), |
| 3307 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), | 3307 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), |
| @@ -3499,9 +3499,9 @@ static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = { | |||
| 3499 | HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), | 3499 | HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), |
| 3500 | HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT), | 3500 | HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT), |
| 3501 | HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT), | 3501 | HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT), |
| 3502 | HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), | 3502 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT), |
| 3503 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT), | 3503 | HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT), |
| 3504 | HDA_CODEC_VOLUME("Docking Mic Boost", 0x25, 0x0, HDA_OUTPUT), | 3504 | HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT), |
| 3505 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), | 3505 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), |
| 3506 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), | 3506 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), |
| 3507 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), | 3507 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), |
| @@ -3560,8 +3560,8 @@ static struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = { | |||
| 3560 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), | 3560 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), |
| 3561 | HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT), | 3561 | HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT), |
| 3562 | HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT), | 3562 | HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT), |
| 3563 | HDA_CODEC_VOLUME("Line-In Boost", 0x15, 0x0, HDA_INPUT), | 3563 | HDA_CODEC_VOLUME("Line-In Boost Volume", 0x15, 0x0, HDA_INPUT), |
| 3564 | HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT), | 3564 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT), |
| 3565 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), | 3565 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), |
| 3566 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), | 3566 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), |
| 3567 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), | 3567 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), |
| @@ -3745,9 +3745,9 @@ static struct snd_kcontrol_new ad1884a_base_mixers[] = { | |||
| 3745 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT), | 3745 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT), |
| 3746 | HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT), | 3746 | HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT), |
| 3747 | HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT), | 3747 | HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT), |
| 3748 | HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT), | 3748 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT), |
| 3749 | HDA_CODEC_VOLUME("Line Boost", 0x15, 0x0, HDA_INPUT), | 3749 | HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x0, HDA_INPUT), |
| 3750 | HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT), | 3750 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT), |
| 3751 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), | 3751 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), |
| 3752 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), | 3752 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), |
| 3753 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), | 3753 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), |
| @@ -3888,9 +3888,9 @@ static struct snd_kcontrol_new ad1884a_laptop_mixers[] = { | |||
| 3888 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT), | 3888 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT), |
| 3889 | HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT), | 3889 | HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT), |
| 3890 | HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT), | 3890 | HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT), |
| 3891 | HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), | 3891 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT), |
| 3892 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT), | 3892 | HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT), |
| 3893 | HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT), | 3893 | HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT), |
| 3894 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), | 3894 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), |
| 3895 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), | 3895 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), |
| 3896 | { } /* end */ | 3896 | { } /* end */ |
| @@ -4126,8 +4126,8 @@ static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = { | |||
| 4126 | HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), | 4126 | HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), |
| 4127 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT), | 4127 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT), |
| 4128 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), | 4128 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), |
| 4129 | HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), | 4129 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT), |
| 4130 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT), | 4130 | HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT), |
| 4131 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), | 4131 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), |
| 4132 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), | 4132 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), |
| 4133 | { | 4133 | { |
| @@ -4255,8 +4255,8 @@ static struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = { | |||
| 4255 | HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), | 4255 | HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), |
| 4256 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), | 4256 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), |
| 4257 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), | 4257 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), |
| 4258 | HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT), | 4258 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT), |
| 4259 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT), | 4259 | HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT), |
| 4260 | { } /* end */ | 4260 | { } /* end */ |
| 4261 | }; | 4261 | }; |
| 4262 | 4262 | ||
| @@ -4494,9 +4494,9 @@ static struct snd_kcontrol_new ad1882_base_mixers[] = { | |||
| 4494 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT), | 4494 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT), |
| 4495 | HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT), | 4495 | HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT), |
| 4496 | 4496 | ||
| 4497 | HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT), | 4497 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT), |
| 4498 | HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT), | 4498 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT), |
| 4499 | HDA_CODEC_VOLUME("Line-In Boost", 0x3a, 0x0, HDA_OUTPUT), | 4499 | HDA_CODEC_VOLUME("Line-In Boost Volume", 0x3a, 0x0, HDA_OUTPUT), |
| 4500 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), | 4500 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), |
| 4501 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), | 4501 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), |
| 4502 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), | 4502 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), |
| @@ -4547,7 +4547,7 @@ static struct snd_kcontrol_new ad1882a_loopback_mixers[] = { | |||
| 4547 | HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT), | 4547 | HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT), |
| 4548 | HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT), | 4548 | HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT), |
| 4549 | HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT), | 4549 | HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT), |
| 4550 | HDA_CODEC_VOLUME("Digital Mic Boost", 0x1f, 0x0, HDA_INPUT), | 4550 | HDA_CODEC_VOLUME("Digital Mic Boost Volume", 0x1f, 0x0, HDA_INPUT), |
| 4551 | { } /* end */ | 4551 | { } /* end */ |
| 4552 | }; | 4552 | }; |
| 4553 | 4553 | ||
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 76bd58a0e2b6..e96581fcdbdb 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
| @@ -869,16 +869,16 @@ static void cxt5045_hp_unsol_event(struct hda_codec *codec, | |||
| 869 | } | 869 | } |
| 870 | 870 | ||
| 871 | static struct snd_kcontrol_new cxt5045_mixers[] = { | 871 | static struct snd_kcontrol_new cxt5045_mixers[] = { |
| 872 | HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x01, HDA_INPUT), | 872 | HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x1a, 0x01, HDA_INPUT), |
| 873 | HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x01, HDA_INPUT), | 873 | HDA_CODEC_MUTE("Internal Mic Capture Switch", 0x1a, 0x01, HDA_INPUT), |
| 874 | HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x02, HDA_INPUT), | 874 | HDA_CODEC_VOLUME("Mic Capture Volume", 0x1a, 0x02, HDA_INPUT), |
| 875 | HDA_CODEC_MUTE("Ext Mic Capture Switch", 0x1a, 0x02, HDA_INPUT), | 875 | HDA_CODEC_MUTE("Mic Capture Switch", 0x1a, 0x02, HDA_INPUT), |
| 876 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT), | 876 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT), |
| 877 | HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT), | 877 | HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT), |
| 878 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x17, 0x1, HDA_INPUT), | 878 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x1, HDA_INPUT), |
| 879 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x17, 0x1, HDA_INPUT), | 879 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x1, HDA_INPUT), |
| 880 | HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x17, 0x2, HDA_INPUT), | 880 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x17, 0x2, HDA_INPUT), |
| 881 | HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x17, 0x2, HDA_INPUT), | 881 | HDA_CODEC_MUTE("Mic Playback Switch", 0x17, 0x2, HDA_INPUT), |
| 882 | HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol), | 882 | HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol), |
| 883 | { | 883 | { |
| 884 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 884 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
| @@ -910,16 +910,16 @@ static struct snd_kcontrol_new cxt5045_benq_mixers[] = { | |||
| 910 | }; | 910 | }; |
| 911 | 911 | ||
| 912 | static struct snd_kcontrol_new cxt5045_mixers_hp530[] = { | 912 | static struct snd_kcontrol_new cxt5045_mixers_hp530[] = { |
| 913 | HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x02, HDA_INPUT), | 913 | HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x1a, 0x02, HDA_INPUT), |
| 914 | HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x02, HDA_INPUT), | 914 | HDA_CODEC_MUTE("Internal Mic Capture Switch", 0x1a, 0x02, HDA_INPUT), |
| 915 | HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x01, HDA_INPUT), | 915 | HDA_CODEC_VOLUME("Mic Capture Volume", 0x1a, 0x01, HDA_INPUT), |
| 916 | HDA_CODEC_MUTE("Ext Mic Capture Switch", 0x1a, 0x01, HDA_INPUT), | 916 | HDA_CODEC_MUTE("Mic Capture Switch", 0x1a, 0x01, HDA_INPUT), |
| 917 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT), | 917 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT), |
| 918 | HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT), | 918 | HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT), |
| 919 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x17, 0x2, HDA_INPUT), | 919 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x2, HDA_INPUT), |
| 920 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x17, 0x2, HDA_INPUT), | 920 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x2, HDA_INPUT), |
| 921 | HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x17, 0x1, HDA_INPUT), | 921 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x17, 0x1, HDA_INPUT), |
| 922 | HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x17, 0x1, HDA_INPUT), | 922 | HDA_CODEC_MUTE("Mic Playback Switch", 0x17, 0x1, HDA_INPUT), |
| 923 | HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol), | 923 | HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol), |
| 924 | { | 924 | { |
| 925 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 925 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
| @@ -947,7 +947,7 @@ static struct hda_verb cxt5045_init_verbs[] = { | |||
| 947 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | 947 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
| 948 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | 948 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
| 949 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | 949 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
| 950 | /* Record selector: Int mic */ | 950 | /* Record selector: Internal mic */ |
| 951 | {0x1a, AC_VERB_SET_CONNECT_SEL,0x1}, | 951 | {0x1a, AC_VERB_SET_CONNECT_SEL,0x1}, |
| 952 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, | 952 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, |
| 953 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, | 953 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, |
| @@ -960,7 +960,7 @@ static struct hda_verb cxt5045_init_verbs[] = { | |||
| 960 | }; | 960 | }; |
| 961 | 961 | ||
| 962 | static struct hda_verb cxt5045_benq_init_verbs[] = { | 962 | static struct hda_verb cxt5045_benq_init_verbs[] = { |
| 963 | /* Int Mic, Mic */ | 963 | /* Internal Mic, Mic */ |
| 964 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, | 964 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, |
| 965 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, | 965 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, |
| 966 | /* Line In,HP, Amp */ | 966 | /* Line In,HP, Amp */ |
| @@ -973,7 +973,7 @@ static struct hda_verb cxt5045_benq_init_verbs[] = { | |||
| 973 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | 973 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
| 974 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | 974 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
| 975 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | 975 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
| 976 | /* Record selector: Int mic */ | 976 | /* Record selector: Internal mic */ |
| 977 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x1}, | 977 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x1}, |
| 978 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, | 978 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, |
| 979 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, | 979 | AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, |
| @@ -1376,7 +1376,7 @@ static void cxt5047_hp_unsol_event(struct hda_codec *codec, | |||
| 1376 | static struct snd_kcontrol_new cxt5047_base_mixers[] = { | 1376 | static struct snd_kcontrol_new cxt5047_base_mixers[] = { |
| 1377 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x19, 0x02, HDA_INPUT), | 1377 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x19, 0x02, HDA_INPUT), |
| 1378 | HDA_CODEC_MUTE("Mic Playback Switch", 0x19, 0x02, HDA_INPUT), | 1378 | HDA_CODEC_MUTE("Mic Playback Switch", 0x19, 0x02, HDA_INPUT), |
| 1379 | HDA_CODEC_VOLUME("Mic Boost", 0x1a, 0x0, HDA_OUTPUT), | 1379 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x1a, 0x0, HDA_OUTPUT), |
| 1380 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), | 1380 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), |
| 1381 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), | 1381 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), |
| 1382 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), | 1382 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), |
| @@ -1796,8 +1796,8 @@ static struct snd_kcontrol_new cxt5051_playback_mixers[] = { | |||
| 1796 | static struct snd_kcontrol_new cxt5051_capture_mixers[] = { | 1796 | static struct snd_kcontrol_new cxt5051_capture_mixers[] = { |
| 1797 | HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), | 1797 | HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), |
| 1798 | HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), | 1798 | HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), |
| 1799 | HDA_CODEC_VOLUME("External Mic Volume", 0x14, 0x01, HDA_INPUT), | 1799 | HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT), |
| 1800 | HDA_CODEC_MUTE("External Mic Switch", 0x14, 0x01, HDA_INPUT), | 1800 | HDA_CODEC_MUTE("Mic Switch", 0x14, 0x01, HDA_INPUT), |
| 1801 | HDA_CODEC_VOLUME("Docking Mic Volume", 0x15, 0x00, HDA_INPUT), | 1801 | HDA_CODEC_VOLUME("Docking Mic Volume", 0x15, 0x00, HDA_INPUT), |
| 1802 | HDA_CODEC_MUTE("Docking Mic Switch", 0x15, 0x00, HDA_INPUT), | 1802 | HDA_CODEC_MUTE("Docking Mic Switch", 0x15, 0x00, HDA_INPUT), |
| 1803 | {} | 1803 | {} |
| @@ -1806,8 +1806,8 @@ static struct snd_kcontrol_new cxt5051_capture_mixers[] = { | |||
| 1806 | static struct snd_kcontrol_new cxt5051_hp_mixers[] = { | 1806 | static struct snd_kcontrol_new cxt5051_hp_mixers[] = { |
| 1807 | HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), | 1807 | HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), |
| 1808 | HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), | 1808 | HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), |
| 1809 | HDA_CODEC_VOLUME("External Mic Volume", 0x15, 0x00, HDA_INPUT), | 1809 | HDA_CODEC_VOLUME("Mic Volume", 0x15, 0x00, HDA_INPUT), |
| 1810 | HDA_CODEC_MUTE("External Mic Switch", 0x15, 0x00, HDA_INPUT), | 1810 | HDA_CODEC_MUTE("Mic Switch", 0x15, 0x00, HDA_INPUT), |
| 1811 | {} | 1811 | {} |
| 1812 | }; | 1812 | }; |
| 1813 | 1813 | ||
| @@ -1826,8 +1826,8 @@ static struct snd_kcontrol_new cxt5051_f700_mixers[] = { | |||
| 1826 | static struct snd_kcontrol_new cxt5051_toshiba_mixers[] = { | 1826 | static struct snd_kcontrol_new cxt5051_toshiba_mixers[] = { |
| 1827 | HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), | 1827 | HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), |
| 1828 | HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), | 1828 | HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), |
| 1829 | HDA_CODEC_VOLUME("External Mic Volume", 0x14, 0x01, HDA_INPUT), | 1829 | HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT), |
| 1830 | HDA_CODEC_MUTE("External Mic Switch", 0x14, 0x01, HDA_INPUT), | 1830 | HDA_CODEC_MUTE("Mic Switch", 0x14, 0x01, HDA_INPUT), |
| 1831 | {} | 1831 | {} |
| 1832 | }; | 1832 | }; |
| 1833 | 1833 | ||
| @@ -1847,7 +1847,7 @@ static struct hda_verb cxt5051_init_verbs[] = { | |||
| 1847 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, | 1847 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, |
| 1848 | /* DAC1 */ | 1848 | /* DAC1 */ |
| 1849 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 1849 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
| 1850 | /* Record selector: Int mic */ | 1850 | /* Record selector: Internal mic */ |
| 1851 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, | 1851 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, |
| 1852 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, | 1852 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, |
| 1853 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, | 1853 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, |
| @@ -1874,7 +1874,7 @@ static struct hda_verb cxt5051_hp_dv6736_init_verbs[] = { | |||
| 1874 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, | 1874 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, |
| 1875 | /* DAC1 */ | 1875 | /* DAC1 */ |
| 1876 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 1876 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
| 1877 | /* Record selector: Int mic */ | 1877 | /* Record selector: Internal mic */ |
| 1878 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, | 1878 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, |
| 1879 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x1}, | 1879 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x1}, |
| 1880 | /* SPDIF route: PCM */ | 1880 | /* SPDIF route: PCM */ |
| @@ -1904,7 +1904,7 @@ static struct hda_verb cxt5051_lenovo_x200_init_verbs[] = { | |||
| 1904 | {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, | 1904 | {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, |
| 1905 | /* DAC1 */ | 1905 | /* DAC1 */ |
| 1906 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 1906 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
| 1907 | /* Record selector: Int mic */ | 1907 | /* Record selector: Internal mic */ |
| 1908 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, | 1908 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, |
| 1909 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, | 1909 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, |
| 1910 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, | 1910 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, |
| @@ -1932,7 +1932,7 @@ static struct hda_verb cxt5051_f700_init_verbs[] = { | |||
| 1932 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, | 1932 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, |
| 1933 | /* DAC1 */ | 1933 | /* DAC1 */ |
| 1934 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 1934 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
| 1935 | /* Record selector: Int mic */ | 1935 | /* Record selector: Internal mic */ |
| 1936 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, | 1936 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, |
| 1937 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x1}, | 1937 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x1}, |
| 1938 | /* SPDIF route: PCM */ | 1938 | /* SPDIF route: PCM */ |
| @@ -2111,6 +2111,11 @@ static struct hda_channel_mode cxt5066_modes[1] = { | |||
| 2111 | { 2, NULL }, | 2111 | { 2, NULL }, |
| 2112 | }; | 2112 | }; |
| 2113 | 2113 | ||
| 2114 | #define HP_PRESENT_PORT_A (1 << 0) | ||
| 2115 | #define HP_PRESENT_PORT_D (1 << 1) | ||
| 2116 | #define hp_port_a_present(spec) ((spec)->hp_present & HP_PRESENT_PORT_A) | ||
| 2117 | #define hp_port_d_present(spec) ((spec)->hp_present & HP_PRESENT_PORT_D) | ||
| 2118 | |||
| 2114 | static void cxt5066_update_speaker(struct hda_codec *codec) | 2119 | static void cxt5066_update_speaker(struct hda_codec *codec) |
| 2115 | { | 2120 | { |
| 2116 | struct conexant_spec *spec = codec->spec; | 2121 | struct conexant_spec *spec = codec->spec; |
| @@ -2120,24 +2125,20 @@ static void cxt5066_update_speaker(struct hda_codec *codec) | |||
| 2120 | spec->hp_present, spec->cur_eapd); | 2125 | spec->hp_present, spec->cur_eapd); |
| 2121 | 2126 | ||
| 2122 | /* Port A (HP) */ | 2127 | /* Port A (HP) */ |
| 2123 | pinctl = ((spec->hp_present & 1) && spec->cur_eapd) ? PIN_HP : 0; | 2128 | pinctl = (hp_port_a_present(spec) && spec->cur_eapd) ? PIN_HP : 0; |
| 2124 | snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 2129 | snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, |
| 2125 | pinctl); | 2130 | pinctl); |
| 2126 | 2131 | ||
| 2127 | /* Port D (HP/LO) */ | 2132 | /* Port D (HP/LO) */ |
| 2128 | if (spec->dell_automute) { | 2133 | pinctl = spec->cur_eapd ? spec->port_d_mode : 0; |
| 2129 | /* DELL AIO Port Rule: PortA> PortD> IntSpk */ | 2134 | if (spec->dell_automute || spec->thinkpad) { |
| 2130 | pinctl = (!(spec->hp_present & 1) && spec->cur_eapd) | 2135 | /* Mute if Port A is connected */ |
| 2131 | ? PIN_OUT : 0; | 2136 | if (hp_port_a_present(spec)) |
| 2132 | } else if (spec->thinkpad) { | ||
| 2133 | if (spec->cur_eapd) | ||
| 2134 | pinctl = spec->port_d_mode; | ||
| 2135 | /* Mute dock line-out if Port A (laptop HP) is present */ | ||
| 2136 | if (spec->hp_present& 1) | ||
| 2137 | pinctl = 0; | 2137 | pinctl = 0; |
| 2138 | } else { | 2138 | } else { |
| 2139 | pinctl = ((spec->hp_present & 2) && spec->cur_eapd) | 2139 | /* Thinkpad/Dell doesn't give pin-D status */ |
| 2140 | ? spec->port_d_mode : 0; | 2140 | if (!hp_port_d_present(spec)) |
| 2141 | pinctl = 0; | ||
| 2141 | } | 2142 | } |
| 2142 | snd_hda_codec_write(codec, 0x1c, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 2143 | snd_hda_codec_write(codec, 0x1c, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, |
| 2143 | pinctl); | 2144 | pinctl); |
| @@ -2379,8 +2380,8 @@ static void cxt5066_hp_automute(struct hda_codec *codec) | |||
| 2379 | /* Port D */ | 2380 | /* Port D */ |
| 2380 | portD = snd_hda_jack_detect(codec, 0x1c); | 2381 | portD = snd_hda_jack_detect(codec, 0x1c); |
| 2381 | 2382 | ||
| 2382 | spec->hp_present = !!(portA); | 2383 | spec->hp_present = portA ? HP_PRESENT_PORT_A : 0; |
| 2383 | spec->hp_present |= portD ? 2 : 0; | 2384 | spec->hp_present |= portD ? HP_PRESENT_PORT_D : 0; |
| 2384 | snd_printdd("CXT5066: hp automute portA=%x portD=%x present=%d\n", | 2385 | snd_printdd("CXT5066: hp automute portA=%x portD=%x present=%d\n", |
| 2385 | portA, portD, spec->hp_present); | 2386 | portA, portD, spec->hp_present); |
| 2386 | cxt5066_update_speaker(codec); | 2387 | cxt5066_update_speaker(codec); |
| @@ -2728,7 +2729,7 @@ static struct snd_kcontrol_new cxt5066_mixers[] = { | |||
| 2728 | static struct snd_kcontrol_new cxt5066_vostro_mixers[] = { | 2729 | static struct snd_kcontrol_new cxt5066_vostro_mixers[] = { |
| 2729 | { | 2730 | { |
| 2730 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2731 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
| 2731 | .name = "Int Mic Boost Capture Enum", | 2732 | .name = "Internal Mic Boost Capture Enum", |
| 2732 | .info = cxt5066_mic_boost_mux_enum_info, | 2733 | .info = cxt5066_mic_boost_mux_enum_info, |
| 2733 | .get = cxt5066_mic_boost_mux_enum_get, | 2734 | .get = cxt5066_mic_boost_mux_enum_get, |
| 2734 | .put = cxt5066_mic_boost_mux_enum_put, | 2735 | .put = cxt5066_mic_boost_mux_enum_put, |
| @@ -2954,7 +2955,7 @@ static struct hda_verb cxt5066_init_verbs_ideapad[] = { | |||
| 2954 | {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 2955 | {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
| 2955 | 2956 | ||
| 2956 | /* internal microphone */ | 2957 | /* internal microphone */ |
| 2957 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable int mic */ | 2958 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable internal mic */ |
| 2958 | 2959 | ||
| 2959 | /* EAPD */ | 2960 | /* EAPD */ |
| 2960 | {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | 2961 | {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ |
| @@ -3009,7 +3010,7 @@ static struct hda_verb cxt5066_init_verbs_thinkpad[] = { | |||
| 3009 | {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 3010 | {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
| 3010 | 3011 | ||
| 3011 | /* internal microphone */ | 3012 | /* internal microphone */ |
| 3012 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable int mic */ | 3013 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable internal mic */ |
| 3013 | 3014 | ||
| 3014 | /* EAPD */ | 3015 | /* EAPD */ |
| 3015 | {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ | 3016 | {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ |
| @@ -3097,6 +3098,7 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = { | |||
| 3097 | SND_PCI_QUIRK_MASK(0x1025, 0xff00, 0x0400, "Acer", CXT5066_IDEAPAD), | 3098 | SND_PCI_QUIRK_MASK(0x1025, 0xff00, 0x0400, "Acer", CXT5066_IDEAPAD), |
| 3098 | SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO), | 3099 | SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO), |
| 3099 | SND_PCI_QUIRK(0x1028, 0x02f5, "Dell Vostro 320", CXT5066_IDEAPAD), | 3100 | SND_PCI_QUIRK(0x1028, 0x02f5, "Dell Vostro 320", CXT5066_IDEAPAD), |
| 3101 | SND_PCI_QUIRK(0x1028, 0x0401, "Dell Vostro 1014", CXT5066_DELL_VOSTRO), | ||
| 3100 | SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTRO), | 3102 | SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTRO), |
| 3101 | SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), | 3103 | SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), |
| 3102 | SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP), | 3104 | SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP), |
| @@ -3108,16 +3110,9 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = { | |||
| 3108 | CXT5066_LAPTOP), | 3110 | CXT5066_LAPTOP), |
| 3109 | SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), | 3111 | SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), |
| 3110 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), | 3112 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), |
| 3111 | SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD), | ||
| 3112 | SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD), | 3113 | SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD), |
| 3113 | SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD), | ||
| 3114 | SND_PCI_QUIRK(0x17aa, 0x21b4, "Thinkpad Edge", CXT5066_IDEAPAD), | ||
| 3115 | SND_PCI_QUIRK(0x17aa, 0x21c8, "Thinkpad Edge 11", CXT5066_IDEAPAD), | ||
| 3116 | SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD), | 3114 | SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD), |
| 3117 | SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G series", CXT5066_IDEAPAD), | 3115 | SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", CXT5066_IDEAPAD), /* Fallback for Lenovos without dock mic */ |
| 3118 | SND_PCI_QUIRK(0x17aa, 0x390a, "Lenovo S10-3t", CXT5066_IDEAPAD), | ||
| 3119 | SND_PCI_QUIRK(0x17aa, 0x3938, "Lenovo G series (AMD)", CXT5066_IDEAPAD), | ||
| 3120 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "ideapad", CXT5066_IDEAPAD), | ||
| 3121 | {} | 3116 | {} |
| 3122 | }; | 3117 | }; |
| 3123 | 3118 | ||
| @@ -3422,6 +3417,9 @@ static void cx_auto_hp_automute(struct hda_codec *codec) | |||
| 3422 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 3417 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
| 3423 | present ? 0 : PIN_OUT); | 3418 | present ? 0 : PIN_OUT); |
| 3424 | } | 3419 | } |
| 3420 | for (i = 0; !present && i < cfg->line_outs; i++) | ||
| 3421 | if (snd_hda_jack_detect(codec, cfg->line_out_pins[i])) | ||
| 3422 | present = 1; | ||
| 3425 | for (i = 0; i < cfg->speaker_outs; i++) { | 3423 | for (i = 0; i < cfg->speaker_outs; i++) { |
| 3426 | snd_hda_codec_write(codec, cfg->speaker_pins[i], 0, | 3424 | snd_hda_codec_write(codec, cfg->speaker_pins[i], 0, |
| 3427 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 3425 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 31df7747990d..f29b97b5de8f 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
| @@ -31,10 +31,15 @@ | |||
| 31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
| 32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
| 33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
| 34 | #include <linux/moduleparam.h> | ||
| 34 | #include <sound/core.h> | 35 | #include <sound/core.h> |
| 35 | #include "hda_codec.h" | 36 | #include "hda_codec.h" |
| 36 | #include "hda_local.h" | 37 | #include "hda_local.h" |
| 37 | 38 | ||
| 39 | static bool static_hdmi_pcm; | ||
| 40 | module_param(static_hdmi_pcm, bool, 0644); | ||
| 41 | MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info"); | ||
| 42 | |||
| 38 | /* | 43 | /* |
| 39 | * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device | 44 | * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device |
| 40 | * could support two independent pipes, each of them can be connected to one or | 45 | * could support two independent pipes, each of them can be connected to one or |
| @@ -827,7 +832,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, | |||
| 827 | *codec_pars = *hinfo; | 832 | *codec_pars = *hinfo; |
| 828 | 833 | ||
| 829 | eld = &spec->sink_eld[idx]; | 834 | eld = &spec->sink_eld[idx]; |
| 830 | if (eld->sad_count > 0) { | 835 | if (!static_hdmi_pcm && eld->eld_valid && eld->sad_count > 0) { |
| 831 | hdmi_eld_update_pcm_info(eld, hinfo, codec_pars); | 836 | hdmi_eld_update_pcm_info(eld, hinfo, codec_pars); |
| 832 | if (hinfo->channels_min > hinfo->channels_max || | 837 | if (hinfo->channels_min > hinfo->channels_max || |
| 833 | !hinfo->rates || !hinfo->formats) | 838 | !hinfo->rates || !hinfo->formats) |
| @@ -904,23 +909,28 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) | |||
| 904 | spec->pin[spec->num_pins] = pin_nid; | 909 | spec->pin[spec->num_pins] = pin_nid; |
| 905 | spec->num_pins++; | 910 | spec->num_pins++; |
| 906 | 911 | ||
| 907 | /* | ||
| 908 | * It is assumed that converter nodes come first in the node list and | ||
| 909 | * hence have been registered and usable now. | ||
| 910 | */ | ||
| 911 | return hdmi_read_pin_conn(codec, pin_nid); | 912 | return hdmi_read_pin_conn(codec, pin_nid); |
| 912 | } | 913 | } |
| 913 | 914 | ||
| 914 | static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid) | 915 | static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid) |
| 915 | { | 916 | { |
| 917 | int i, found_pin = 0; | ||
| 916 | struct hdmi_spec *spec = codec->spec; | 918 | struct hdmi_spec *spec = codec->spec; |
| 917 | 919 | ||
| 918 | if (spec->num_cvts >= MAX_HDMI_CVTS) { | 920 | for (i = 0; i < spec->num_pins; i++) |
| 919 | snd_printk(KERN_WARNING | 921 | if (nid == spec->pin_cvt[i]) { |
| 920 | "HDMI: no space for converter %d\n", nid); | 922 | found_pin = 1; |
| 921 | return -E2BIG; | 923 | break; |
| 924 | } | ||
| 925 | |||
| 926 | if (!found_pin) { | ||
| 927 | snd_printdd("HDMI: Skipping node %d (no connection)\n", nid); | ||
| 928 | return -EINVAL; | ||
| 922 | } | 929 | } |
| 923 | 930 | ||
| 931 | if (snd_BUG_ON(spec->num_cvts >= MAX_HDMI_CVTS)) | ||
| 932 | return -E2BIG; | ||
| 933 | |||
| 924 | spec->cvt[spec->num_cvts] = nid; | 934 | spec->cvt[spec->num_cvts] = nid; |
| 925 | spec->num_cvts++; | 935 | spec->num_cvts++; |
| 926 | 936 | ||
| @@ -931,6 +941,8 @@ static int hdmi_parse_codec(struct hda_codec *codec) | |||
| 931 | { | 941 | { |
| 932 | hda_nid_t nid; | 942 | hda_nid_t nid; |
| 933 | int i, nodes; | 943 | int i, nodes; |
| 944 | int num_tmp_cvts = 0; | ||
| 945 | hda_nid_t tmp_cvt[MAX_HDMI_CVTS]; | ||
| 934 | 946 | ||
| 935 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); | 947 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); |
| 936 | if (!nid || nodes < 0) { | 948 | if (!nid || nodes < 0) { |
| @@ -941,6 +953,7 @@ static int hdmi_parse_codec(struct hda_codec *codec) | |||
| 941 | for (i = 0; i < nodes; i++, nid++) { | 953 | for (i = 0; i < nodes; i++, nid++) { |
| 942 | unsigned int caps; | 954 | unsigned int caps; |
| 943 | unsigned int type; | 955 | unsigned int type; |
| 956 | unsigned int config; | ||
| 944 | 957 | ||
| 945 | caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); | 958 | caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); |
| 946 | type = get_wcaps_type(caps); | 959 | type = get_wcaps_type(caps); |
| @@ -950,17 +963,32 @@ static int hdmi_parse_codec(struct hda_codec *codec) | |||
| 950 | 963 | ||
| 951 | switch (type) { | 964 | switch (type) { |
| 952 | case AC_WID_AUD_OUT: | 965 | case AC_WID_AUD_OUT: |
| 953 | hdmi_add_cvt(codec, nid); | 966 | if (num_tmp_cvts >= MAX_HDMI_CVTS) { |
| 967 | snd_printk(KERN_WARNING | ||
| 968 | "HDMI: no space for converter %d\n", nid); | ||
| 969 | continue; | ||
| 970 | } | ||
| 971 | tmp_cvt[num_tmp_cvts] = nid; | ||
| 972 | num_tmp_cvts++; | ||
| 954 | break; | 973 | break; |
| 955 | case AC_WID_PIN: | 974 | case AC_WID_PIN: |
| 956 | caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | 975 | caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); |
| 957 | if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) | 976 | if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) |
| 958 | continue; | 977 | continue; |
| 978 | |||
| 979 | config = snd_hda_codec_read(codec, nid, 0, | ||
| 980 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
| 981 | if (get_defcfg_connect(config) == AC_JACK_PORT_NONE) | ||
| 982 | continue; | ||
| 983 | |||
| 959 | hdmi_add_pin(codec, nid); | 984 | hdmi_add_pin(codec, nid); |
| 960 | break; | 985 | break; |
| 961 | } | 986 | } |
| 962 | } | 987 | } |
| 963 | 988 | ||
| 989 | for (i = 0; i < num_tmp_cvts; i++) | ||
| 990 | hdmi_add_cvt(codec, tmp_cvt[i]); | ||
| 991 | |||
| 964 | /* | 992 | /* |
| 965 | * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event | 993 | * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event |
| 966 | * can be lost and presence sense verb will become inaccurate if the | 994 | * can be lost and presence sense verb will become inaccurate if the |
| @@ -1165,11 +1193,53 @@ static int nvhdmi_7x_init(struct hda_codec *codec) | |||
| 1165 | return 0; | 1193 | return 0; |
| 1166 | } | 1194 | } |
| 1167 | 1195 | ||
| 1196 | static unsigned int channels_2_6_8[] = { | ||
| 1197 | 2, 6, 8 | ||
| 1198 | }; | ||
| 1199 | |||
| 1200 | static unsigned int channels_2_8[] = { | ||
| 1201 | 2, 8 | ||
| 1202 | }; | ||
| 1203 | |||
| 1204 | static struct snd_pcm_hw_constraint_list hw_constraints_2_6_8_channels = { | ||
| 1205 | .count = ARRAY_SIZE(channels_2_6_8), | ||
| 1206 | .list = channels_2_6_8, | ||
| 1207 | .mask = 0, | ||
| 1208 | }; | ||
| 1209 | |||
| 1210 | static struct snd_pcm_hw_constraint_list hw_constraints_2_8_channels = { | ||
| 1211 | .count = ARRAY_SIZE(channels_2_8), | ||
| 1212 | .list = channels_2_8, | ||
| 1213 | .mask = 0, | ||
| 1214 | }; | ||
| 1215 | |||
| 1168 | static int simple_playback_pcm_open(struct hda_pcm_stream *hinfo, | 1216 | static int simple_playback_pcm_open(struct hda_pcm_stream *hinfo, |
| 1169 | struct hda_codec *codec, | 1217 | struct hda_codec *codec, |
| 1170 | struct snd_pcm_substream *substream) | 1218 | struct snd_pcm_substream *substream) |
| 1171 | { | 1219 | { |
| 1172 | struct hdmi_spec *spec = codec->spec; | 1220 | struct hdmi_spec *spec = codec->spec; |
| 1221 | struct snd_pcm_hw_constraint_list *hw_constraints_channels = NULL; | ||
| 1222 | |||
| 1223 | switch (codec->preset->id) { | ||
| 1224 | case 0x10de0002: | ||
| 1225 | case 0x10de0003: | ||
| 1226 | case 0x10de0005: | ||
| 1227 | case 0x10de0006: | ||
| 1228 | hw_constraints_channels = &hw_constraints_2_8_channels; | ||
| 1229 | break; | ||
| 1230 | case 0x10de0007: | ||
| 1231 | hw_constraints_channels = &hw_constraints_2_6_8_channels; | ||
| 1232 | break; | ||
| 1233 | default: | ||
| 1234 | break; | ||
| 1235 | } | ||
| 1236 | |||
| 1237 | if (hw_constraints_channels != NULL) { | ||
| 1238 | snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
| 1239 | SNDRV_PCM_HW_PARAM_CHANNELS, | ||
| 1240 | hw_constraints_channels); | ||
| 1241 | } | ||
| 1242 | |||
| 1173 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | 1243 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); |
| 1174 | } | 1244 | } |
| 1175 | 1245 | ||
| @@ -1532,7 +1602,7 @@ static struct hda_codec_preset snd_hda_preset_hdmi[] = { | |||
| 1532 | { .id = 0x1002793c, .name = "RS600 HDMI", .patch = patch_atihdmi }, | 1602 | { .id = 0x1002793c, .name = "RS600 HDMI", .patch = patch_atihdmi }, |
| 1533 | { .id = 0x10027919, .name = "RS600 HDMI", .patch = patch_atihdmi }, | 1603 | { .id = 0x10027919, .name = "RS600 HDMI", .patch = patch_atihdmi }, |
| 1534 | { .id = 0x1002791a, .name = "RS690/780 HDMI", .patch = patch_atihdmi }, | 1604 | { .id = 0x1002791a, .name = "RS690/780 HDMI", .patch = patch_atihdmi }, |
| 1535 | { .id = 0x1002aa01, .name = "R6xx HDMI", .patch = patch_atihdmi }, | 1605 | { .id = 0x1002aa01, .name = "R6xx HDMI", .patch = patch_generic_hdmi }, |
| 1536 | { .id = 0x10951390, .name = "SiI1390 HDMI", .patch = patch_generic_hdmi }, | 1606 | { .id = 0x10951390, .name = "SiI1390 HDMI", .patch = patch_generic_hdmi }, |
| 1537 | { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_generic_hdmi }, | 1607 | { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_generic_hdmi }, |
| 1538 | { .id = 0x17e80047, .name = "Chrontel HDMI", .patch = patch_generic_hdmi }, | 1608 | { .id = 0x17e80047, .name = "Chrontel HDMI", .patch = patch_generic_hdmi }, |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 552a09e9211f..51c08edd7563 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
| @@ -231,7 +231,6 @@ enum { | |||
| 231 | ALC888_ACER_ASPIRE_8930G, | 231 | ALC888_ACER_ASPIRE_8930G, |
| 232 | ALC888_ACER_ASPIRE_7730G, | 232 | ALC888_ACER_ASPIRE_7730G, |
| 233 | ALC883_MEDION, | 233 | ALC883_MEDION, |
| 234 | ALC883_MEDION_MD2, | ||
| 235 | ALC883_MEDION_WIM2160, | 234 | ALC883_MEDION_WIM2160, |
| 236 | ALC883_LAPTOP_EAPD, | 235 | ALC883_LAPTOP_EAPD, |
| 237 | ALC883_LENOVO_101E_2ch, | 236 | ALC883_LENOVO_101E_2ch, |
| @@ -1678,29 +1677,32 @@ struct alc_pincfg { | |||
| 1678 | u32 val; | 1677 | u32 val; |
| 1679 | }; | 1678 | }; |
| 1680 | 1679 | ||
| 1680 | struct alc_model_fixup { | ||
| 1681 | const int id; | ||
| 1682 | const char *name; | ||
| 1683 | }; | ||
| 1684 | |||
| 1681 | struct alc_fixup { | 1685 | struct alc_fixup { |
| 1682 | unsigned int sku; | 1686 | unsigned int sku; |
| 1683 | const struct alc_pincfg *pins; | 1687 | const struct alc_pincfg *pins; |
| 1684 | const struct hda_verb *verbs; | 1688 | const struct hda_verb *verbs; |
| 1689 | void (*func)(struct hda_codec *codec, const struct alc_fixup *fix, | ||
| 1690 | int pre_init); | ||
| 1685 | }; | 1691 | }; |
| 1686 | 1692 | ||
| 1687 | static void alc_pick_fixup(struct hda_codec *codec, | 1693 | static void __alc_pick_fixup(struct hda_codec *codec, |
| 1688 | const struct snd_pci_quirk *quirk, | 1694 | const struct alc_fixup *fix, |
| 1689 | const struct alc_fixup *fix, | 1695 | const char *modelname, |
| 1690 | int pre_init) | 1696 | int pre_init) |
| 1691 | { | 1697 | { |
| 1692 | const struct alc_pincfg *cfg; | 1698 | const struct alc_pincfg *cfg; |
| 1693 | struct alc_spec *spec; | 1699 | struct alc_spec *spec; |
| 1694 | 1700 | ||
| 1695 | quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk); | ||
| 1696 | if (!quirk) | ||
| 1697 | return; | ||
| 1698 | fix += quirk->value; | ||
| 1699 | cfg = fix->pins; | 1701 | cfg = fix->pins; |
| 1700 | if (pre_init && fix->sku) { | 1702 | if (pre_init && fix->sku) { |
| 1701 | #ifdef CONFIG_SND_DEBUG_VERBOSE | 1703 | #ifdef CONFIG_SND_DEBUG_VERBOSE |
| 1702 | snd_printdd(KERN_INFO "hda_codec: %s: Apply sku override for %s\n", | 1704 | snd_printdd(KERN_INFO "hda_codec: %s: Apply sku override for %s\n", |
| 1703 | codec->chip_name, quirk->name); | 1705 | codec->chip_name, modelname); |
| 1704 | #endif | 1706 | #endif |
| 1705 | spec = codec->spec; | 1707 | spec = codec->spec; |
| 1706 | spec->cdefine.sku_cfg = fix->sku; | 1708 | spec->cdefine.sku_cfg = fix->sku; |
| @@ -1709,7 +1711,7 @@ static void alc_pick_fixup(struct hda_codec *codec, | |||
| 1709 | if (pre_init && cfg) { | 1711 | if (pre_init && cfg) { |
| 1710 | #ifdef CONFIG_SND_DEBUG_VERBOSE | 1712 | #ifdef CONFIG_SND_DEBUG_VERBOSE |
| 1711 | snd_printdd(KERN_INFO "hda_codec: %s: Apply pincfg for %s\n", | 1713 | snd_printdd(KERN_INFO "hda_codec: %s: Apply pincfg for %s\n", |
| 1712 | codec->chip_name, quirk->name); | 1714 | codec->chip_name, modelname); |
| 1713 | #endif | 1715 | #endif |
| 1714 | for (; cfg->nid; cfg++) | 1716 | for (; cfg->nid; cfg++) |
| 1715 | snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val); | 1717 | snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val); |
| @@ -1717,10 +1719,53 @@ static void alc_pick_fixup(struct hda_codec *codec, | |||
| 1717 | if (!pre_init && fix->verbs) { | 1719 | if (!pre_init && fix->verbs) { |
| 1718 | #ifdef CONFIG_SND_DEBUG_VERBOSE | 1720 | #ifdef CONFIG_SND_DEBUG_VERBOSE |
| 1719 | snd_printdd(KERN_INFO "hda_codec: %s: Apply fix-verbs for %s\n", | 1721 | snd_printdd(KERN_INFO "hda_codec: %s: Apply fix-verbs for %s\n", |
| 1720 | codec->chip_name, quirk->name); | 1722 | codec->chip_name, modelname); |
| 1721 | #endif | 1723 | #endif |
| 1722 | add_verb(codec->spec, fix->verbs); | 1724 | add_verb(codec->spec, fix->verbs); |
| 1723 | } | 1725 | } |
| 1726 | if (fix->func) { | ||
| 1727 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
| 1728 | snd_printdd(KERN_INFO "hda_codec: %s: Apply fix-func for %s\n", | ||
| 1729 | codec->chip_name, modelname); | ||
| 1730 | #endif | ||
| 1731 | fix->func(codec, fix, pre_init); | ||
| 1732 | } | ||
| 1733 | } | ||
| 1734 | |||
| 1735 | static void alc_pick_fixup(struct hda_codec *codec, | ||
| 1736 | const struct snd_pci_quirk *quirk, | ||
| 1737 | const struct alc_fixup *fix, | ||
| 1738 | int pre_init) | ||
| 1739 | { | ||
| 1740 | quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk); | ||
| 1741 | if (quirk) { | ||
| 1742 | fix += quirk->value; | ||
| 1743 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
| 1744 | __alc_pick_fixup(codec, fix, quirk->name, pre_init); | ||
| 1745 | #else | ||
| 1746 | __alc_pick_fixup(codec, fix, NULL, pre_init); | ||
| 1747 | #endif | ||
| 1748 | } | ||
| 1749 | } | ||
| 1750 | |||
| 1751 | static void alc_pick_fixup_model(struct hda_codec *codec, | ||
| 1752 | const struct alc_model_fixup *models, | ||
| 1753 | const struct snd_pci_quirk *quirk, | ||
| 1754 | const struct alc_fixup *fix, | ||
| 1755 | int pre_init) | ||
| 1756 | { | ||
| 1757 | if (codec->modelname && models) { | ||
| 1758 | while (models->name) { | ||
| 1759 | if (!strcmp(codec->modelname, models->name)) { | ||
| 1760 | fix += models->id; | ||
| 1761 | break; | ||
| 1762 | } | ||
| 1763 | models++; | ||
| 1764 | } | ||
| 1765 | __alc_pick_fixup(codec, fix, codec->modelname, pre_init); | ||
| 1766 | } else { | ||
| 1767 | alc_pick_fixup(codec, quirk, fix, pre_init); | ||
| 1768 | } | ||
| 1724 | } | 1769 | } |
| 1725 | 1770 | ||
| 1726 | static int alc_read_coef_idx(struct hda_codec *codec, | 1771 | static int alc_read_coef_idx(struct hda_codec *codec, |
| @@ -1981,6 +2026,7 @@ static struct hda_verb alc888_acer_aspire_4930g_verbs[] = { | |||
| 1981 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 2026 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
| 1982 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 2027 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
| 1983 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, | 2028 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, |
| 2029 | {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2}, | ||
| 1984 | { } | 2030 | { } |
| 1985 | }; | 2031 | }; |
| 1986 | 2032 | ||
| @@ -2120,17 +2166,17 @@ static struct hda_input_mux alc888_acer_aspire_6530_sources[2] = { | |||
| 2120 | { | 2166 | { |
| 2121 | .num_items = 5, | 2167 | .num_items = 5, |
| 2122 | .items = { | 2168 | .items = { |
| 2123 | { "Ext Mic", 0x0 }, | 2169 | { "Mic", 0x0 }, |
| 2124 | { "Line In", 0x2 }, | 2170 | { "Line In", 0x2 }, |
| 2125 | { "CD", 0x4 }, | 2171 | { "CD", 0x4 }, |
| 2126 | { "Input Mix", 0xa }, | 2172 | { "Input Mix", 0xa }, |
| 2127 | { "Int Mic", 0xb }, | 2173 | { "Internal Mic", 0xb }, |
| 2128 | }, | 2174 | }, |
| 2129 | }, | 2175 | }, |
| 2130 | { | 2176 | { |
| 2131 | .num_items = 4, | 2177 | .num_items = 4, |
| 2132 | .items = { | 2178 | .items = { |
| 2133 | { "Ext Mic", 0x0 }, | 2179 | { "Mic", 0x0 }, |
| 2134 | { "Line In", 0x2 }, | 2180 | { "Line In", 0x2 }, |
| 2135 | { "CD", 0x4 }, | 2181 | { "CD", 0x4 }, |
| 2136 | { "Input Mix", 0xa }, | 2182 | { "Input Mix", 0xa }, |
| @@ -2187,7 +2233,7 @@ static struct snd_kcontrol_new alc888_base_mixer[] = { | |||
| 2187 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | 2233 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), |
| 2188 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 2234 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
| 2189 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 2235 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 2190 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 2236 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 2191 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 2237 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 2192 | { } /* end */ | 2238 | { } /* end */ |
| 2193 | }; | 2239 | }; |
| @@ -2205,7 +2251,7 @@ static struct snd_kcontrol_new alc889_acer_aspire_8930g_mixer[] = { | |||
| 2205 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | 2251 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), |
| 2206 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 2252 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
| 2207 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 2253 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 2208 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 2254 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 2209 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 2255 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 2210 | { } /* end */ | 2256 | { } /* end */ |
| 2211 | }; | 2257 | }; |
| @@ -2796,10 +2842,10 @@ static struct snd_kcontrol_new alc880_fujitsu_mixer[] = { | |||
| 2796 | HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT), | 2842 | HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT), |
| 2797 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 2843 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
| 2798 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 2844 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
| 2799 | HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 2845 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 2800 | HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 2846 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 2801 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 2847 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 2802 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 2848 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 2803 | { } /* end */ | 2849 | { } /* end */ |
| 2804 | }; | 2850 | }; |
| 2805 | 2851 | ||
| @@ -3307,7 +3353,7 @@ static struct hda_verb alc880_beep_init_verbs[] = { | |||
| 3307 | }; | 3353 | }; |
| 3308 | 3354 | ||
| 3309 | /* auto-toggle front mic */ | 3355 | /* auto-toggle front mic */ |
| 3310 | static void alc880_uniwill_mic_automute(struct hda_codec *codec) | 3356 | static void alc88x_simple_mic_automute(struct hda_codec *codec) |
| 3311 | { | 3357 | { |
| 3312 | unsigned int present; | 3358 | unsigned int present; |
| 3313 | unsigned char bits; | 3359 | unsigned char bits; |
| @@ -3329,7 +3375,7 @@ static void alc880_uniwill_setup(struct hda_codec *codec) | |||
| 3329 | static void alc880_uniwill_init_hook(struct hda_codec *codec) | 3375 | static void alc880_uniwill_init_hook(struct hda_codec *codec) |
| 3330 | { | 3376 | { |
| 3331 | alc_automute_amp(codec); | 3377 | alc_automute_amp(codec); |
| 3332 | alc880_uniwill_mic_automute(codec); | 3378 | alc88x_simple_mic_automute(codec); |
| 3333 | } | 3379 | } |
| 3334 | 3380 | ||
| 3335 | static void alc880_uniwill_unsol_event(struct hda_codec *codec, | 3381 | static void alc880_uniwill_unsol_event(struct hda_codec *codec, |
| @@ -3340,7 +3386,7 @@ static void alc880_uniwill_unsol_event(struct hda_codec *codec, | |||
| 3340 | */ | 3386 | */ |
| 3341 | switch (res >> 28) { | 3387 | switch (res >> 28) { |
| 3342 | case ALC880_MIC_EVENT: | 3388 | case ALC880_MIC_EVENT: |
| 3343 | alc880_uniwill_mic_automute(codec); | 3389 | alc88x_simple_mic_automute(codec); |
| 3344 | break; | 3390 | break; |
| 3345 | default: | 3391 | default: |
| 3346 | alc_automute_amp_unsol_event(codec, res); | 3392 | alc_automute_amp_unsol_event(codec, res); |
| @@ -5023,6 +5069,25 @@ static int alc880_auto_fill_dac_nids(struct alc_spec *spec, | |||
| 5023 | return 0; | 5069 | return 0; |
| 5024 | } | 5070 | } |
| 5025 | 5071 | ||
| 5072 | static const char *alc_get_line_out_pfx(const struct auto_pin_cfg *cfg, | ||
| 5073 | bool can_be_master) | ||
| 5074 | { | ||
| 5075 | if (!cfg->hp_outs && !cfg->speaker_outs && can_be_master) | ||
| 5076 | return "Master"; | ||
| 5077 | |||
| 5078 | switch (cfg->line_out_type) { | ||
| 5079 | case AUTO_PIN_SPEAKER_OUT: | ||
| 5080 | return "Speaker"; | ||
| 5081 | case AUTO_PIN_HP_OUT: | ||
| 5082 | return "Headphone"; | ||
| 5083 | default: | ||
| 5084 | if (cfg->line_outs == 1) | ||
| 5085 | return "PCM"; | ||
| 5086 | break; | ||
| 5087 | } | ||
| 5088 | return NULL; | ||
| 5089 | } | ||
| 5090 | |||
| 5026 | /* add playback controls from the parsed DAC table */ | 5091 | /* add playback controls from the parsed DAC table */ |
| 5027 | static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, | 5092 | static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, |
| 5028 | const struct auto_pin_cfg *cfg) | 5093 | const struct auto_pin_cfg *cfg) |
| @@ -5030,6 +5095,7 @@ static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
| 5030 | static const char *chname[4] = { | 5095 | static const char *chname[4] = { |
| 5031 | "Front", "Surround", NULL /*CLFE*/, "Side" | 5096 | "Front", "Surround", NULL /*CLFE*/, "Side" |
| 5032 | }; | 5097 | }; |
| 5098 | const char *pfx = alc_get_line_out_pfx(cfg, false); | ||
| 5033 | hda_nid_t nid; | 5099 | hda_nid_t nid; |
| 5034 | int i, err; | 5100 | int i, err; |
| 5035 | 5101 | ||
| @@ -5037,7 +5103,7 @@ static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
| 5037 | if (!spec->multiout.dac_nids[i]) | 5103 | if (!spec->multiout.dac_nids[i]) |
| 5038 | continue; | 5104 | continue; |
| 5039 | nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i])); | 5105 | nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i])); |
| 5040 | if (i == 2) { | 5106 | if (!pfx && i == 2) { |
| 5041 | /* Center/LFE */ | 5107 | /* Center/LFE */ |
| 5042 | err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, | 5108 | err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, |
| 5043 | "Center", | 5109 | "Center", |
| @@ -5064,18 +5130,17 @@ static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
| 5064 | if (err < 0) | 5130 | if (err < 0) |
| 5065 | return err; | 5131 | return err; |
| 5066 | } else { | 5132 | } else { |
| 5067 | const char *pfx; | 5133 | const char *name = pfx; |
| 5068 | if (cfg->line_outs == 1 && | 5134 | if (!name) |
| 5069 | cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) | 5135 | name = chname[i]; |
| 5070 | pfx = "Speaker"; | 5136 | err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, |
| 5071 | else | 5137 | name, i, |
| 5072 | pfx = chname[i]; | ||
| 5073 | err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, | ||
| 5074 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, | 5138 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, |
| 5075 | HDA_OUTPUT)); | 5139 | HDA_OUTPUT)); |
| 5076 | if (err < 0) | 5140 | if (err < 0) |
| 5077 | return err; | 5141 | return err; |
| 5078 | err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx, | 5142 | err = __add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, |
| 5143 | name, i, | ||
| 5079 | HDA_COMPOSE_AMP_VAL(nid, 3, 2, | 5144 | HDA_COMPOSE_AMP_VAL(nid, 3, 2, |
| 5080 | HDA_INPUT)); | 5145 | HDA_INPUT)); |
| 5081 | if (err < 0) | 5146 | if (err < 0) |
| @@ -5155,7 +5220,8 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec, | |||
| 5155 | { | 5220 | { |
| 5156 | struct alc_spec *spec = codec->spec; | 5221 | struct alc_spec *spec = codec->spec; |
| 5157 | struct hda_input_mux *imux = &spec->private_imux[0]; | 5222 | struct hda_input_mux *imux = &spec->private_imux[0]; |
| 5158 | int i, err, idx, type, type_idx = 0; | 5223 | int i, err, idx, type_idx = 0; |
| 5224 | const char *prev_label = NULL; | ||
| 5159 | 5225 | ||
| 5160 | for (i = 0; i < cfg->num_inputs; i++) { | 5226 | for (i = 0; i < cfg->num_inputs; i++) { |
| 5161 | hda_nid_t pin; | 5227 | hda_nid_t pin; |
| @@ -5165,12 +5231,13 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec, | |||
| 5165 | if (!alc_is_input_pin(codec, pin)) | 5231 | if (!alc_is_input_pin(codec, pin)) |
| 5166 | continue; | 5232 | continue; |
| 5167 | 5233 | ||
| 5168 | type = cfg->inputs[i].type; | 5234 | label = hda_get_autocfg_input_label(codec, cfg, i); |
| 5169 | if (i > 0 && type == cfg->inputs[i - 1].type) | 5235 | if (prev_label && !strcmp(label, prev_label)) |
| 5170 | type_idx++; | 5236 | type_idx++; |
| 5171 | else | 5237 | else |
| 5172 | type_idx = 0; | 5238 | type_idx = 0; |
| 5173 | label = hda_get_autocfg_input_label(codec, cfg, i); | 5239 | prev_label = label; |
| 5240 | |||
| 5174 | if (mixer) { | 5241 | if (mixer) { |
| 5175 | idx = get_connection_index(codec, mixer, pin); | 5242 | idx = get_connection_index(codec, mixer, pin); |
| 5176 | if (idx >= 0) { | 5243 | if (idx >= 0) { |
| @@ -7406,7 +7473,7 @@ static struct hda_input_mux alc883_lenovo_nb0763_capture_source = { | |||
| 7406 | .num_items = 4, | 7473 | .num_items = 4, |
| 7407 | .items = { | 7474 | .items = { |
| 7408 | { "Mic", 0x0 }, | 7475 | { "Mic", 0x0 }, |
| 7409 | { "Int Mic", 0x1 }, | 7476 | { "Internal Mic", 0x1 }, |
| 7410 | { "Line", 0x2 }, | 7477 | { "Line", 0x2 }, |
| 7411 | { "CD", 0x4 }, | 7478 | { "CD", 0x4 }, |
| 7412 | }, | 7479 | }, |
| @@ -7416,7 +7483,7 @@ static struct hda_input_mux alc883_fujitsu_pi2515_capture_source = { | |||
| 7416 | .num_items = 2, | 7483 | .num_items = 2, |
| 7417 | .items = { | 7484 | .items = { |
| 7418 | { "Mic", 0x0 }, | 7485 | { "Mic", 0x0 }, |
| 7419 | { "Int Mic", 0x1 }, | 7486 | { "Internal Mic", 0x1 }, |
| 7420 | }, | 7487 | }, |
| 7421 | }; | 7488 | }; |
| 7422 | 7489 | ||
| @@ -7851,10 +7918,10 @@ static struct snd_kcontrol_new alc882_base_mixer[] = { | |||
| 7851 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | 7918 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), |
| 7852 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 7919 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
| 7853 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 7920 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 7854 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 7921 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 7855 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 7922 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 7856 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 7923 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 7857 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 7924 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 7858 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 7925 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 7859 | { } /* end */ | 7926 | { } /* end */ |
| 7860 | }; | 7927 | }; |
| @@ -7878,8 +7945,8 @@ static struct snd_kcontrol_new alc885_mbp3_mixer[] = { | |||
| 7878 | HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 7945 | HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
| 7879 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT), | 7946 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT), |
| 7880 | HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT), | 7947 | HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT), |
| 7881 | HDA_CODEC_VOLUME("Line Boost", 0x1a, 0x00, HDA_INPUT), | 7948 | HDA_CODEC_VOLUME("Line Boost Volume", 0x1a, 0x00, HDA_INPUT), |
| 7882 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x00, HDA_INPUT), | 7949 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x00, HDA_INPUT), |
| 7883 | { } /* end */ | 7950 | { } /* end */ |
| 7884 | }; | 7951 | }; |
| 7885 | 7952 | ||
| @@ -7896,8 +7963,8 @@ static struct snd_kcontrol_new alc885_mb5_mixer[] = { | |||
| 7896 | HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT), | 7963 | HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT), |
| 7897 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | 7964 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), |
| 7898 | HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | 7965 | HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), |
| 7899 | HDA_CODEC_VOLUME("Line Boost", 0x15, 0x00, HDA_INPUT), | 7966 | HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x00, HDA_INPUT), |
| 7900 | HDA_CODEC_VOLUME("Mic Boost", 0x19, 0x00, HDA_INPUT), | 7967 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0x00, HDA_INPUT), |
| 7901 | { } /* end */ | 7968 | { } /* end */ |
| 7902 | }; | 7969 | }; |
| 7903 | 7970 | ||
| @@ -7912,7 +7979,7 @@ static struct snd_kcontrol_new alc885_macmini3_mixer[] = { | |||
| 7912 | HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT), | 7979 | HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT), |
| 7913 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT), | 7980 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT), |
| 7914 | HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT), | 7981 | HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT), |
| 7915 | HDA_CODEC_VOLUME("Line Boost", 0x15, 0x00, HDA_INPUT), | 7982 | HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x00, HDA_INPUT), |
| 7916 | { } /* end */ | 7983 | { } /* end */ |
| 7917 | }; | 7984 | }; |
| 7918 | 7985 | ||
| @@ -7931,7 +7998,7 @@ static struct snd_kcontrol_new alc882_w2jc_mixer[] = { | |||
| 7931 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | 7998 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), |
| 7932 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 7999 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
| 7933 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 8000 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 7934 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 8001 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 7935 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 8002 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 7936 | { } /* end */ | 8003 | { } /* end */ |
| 7937 | }; | 8004 | }; |
| @@ -7946,10 +8013,10 @@ static struct snd_kcontrol_new alc882_targa_mixer[] = { | |||
| 7946 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 8013 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
| 7947 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 8014 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 7948 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 8015 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 7949 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 8016 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 7950 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 8017 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 7951 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 8018 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 7952 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 8019 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 7953 | { } /* end */ | 8020 | { } /* end */ |
| 7954 | }; | 8021 | }; |
| 7955 | 8022 | ||
| @@ -7969,7 +8036,7 @@ static struct snd_kcontrol_new alc882_asus_a7j_mixer[] = { | |||
| 7969 | HDA_CODEC_MUTE("Mobile Line Playback Switch", 0x0b, 0x03, HDA_INPUT), | 8036 | HDA_CODEC_MUTE("Mobile Line Playback Switch", 0x0b, 0x03, HDA_INPUT), |
| 7970 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 8037 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 7971 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 8038 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 7972 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 8039 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 7973 | { } /* end */ | 8040 | { } /* end */ |
| 7974 | }; | 8041 | }; |
| 7975 | 8042 | ||
| @@ -7982,7 +8049,7 @@ static struct snd_kcontrol_new alc882_asus_a7m_mixer[] = { | |||
| 7982 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | 8049 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), |
| 7983 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 8050 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
| 7984 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 8051 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 7985 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 8052 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 7986 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 8053 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 7987 | { } /* end */ | 8054 | { } /* end */ |
| 7988 | }; | 8055 | }; |
| @@ -8763,10 +8830,10 @@ static struct snd_kcontrol_new alc883_mitac_mixer[] = { | |||
| 8763 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), | 8830 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), |
| 8764 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), | 8831 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), |
| 8765 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 8832 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 8766 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 8833 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 8767 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 8834 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 8768 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 8835 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 8769 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 8836 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 8770 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 8837 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 8771 | { } /* end */ | 8838 | { } /* end */ |
| 8772 | }; | 8839 | }; |
| @@ -8777,11 +8844,11 @@ static struct snd_kcontrol_new alc883_clevo_m720_mixer[] = { | |||
| 8777 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | 8844 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), |
| 8778 | HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT), | 8845 | HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT), |
| 8779 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 8846 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 8780 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 8847 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 8781 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 8848 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 8782 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 8849 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 8783 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), | 8850 | HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 8784 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 8851 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 8785 | { } /* end */ | 8852 | { } /* end */ |
| 8786 | }; | 8853 | }; |
| 8787 | 8854 | ||
| @@ -8791,11 +8858,11 @@ static struct snd_kcontrol_new alc883_2ch_fujitsu_pi2515_mixer[] = { | |||
| 8791 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | 8858 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), |
| 8792 | HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT), | 8859 | HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT), |
| 8793 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 8860 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 8794 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 8861 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 8795 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 8862 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 8796 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 8863 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 8797 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), | 8864 | HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 8798 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 8865 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 8799 | { } /* end */ | 8866 | { } /* end */ |
| 8800 | }; | 8867 | }; |
| 8801 | 8868 | ||
| @@ -8808,10 +8875,10 @@ static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = { | |||
| 8808 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | 8875 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), |
| 8809 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 8876 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
| 8810 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 8877 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 8811 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 8878 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 8812 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 8879 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 8813 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 8880 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 8814 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 8881 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 8815 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 8882 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 8816 | { } /* end */ | 8883 | { } /* end */ |
| 8817 | }; | 8884 | }; |
| @@ -8831,10 +8898,10 @@ static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = { | |||
| 8831 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | 8898 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), |
| 8832 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 8899 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
| 8833 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 8900 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 8834 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 8901 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 8835 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 8902 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 8836 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 8903 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 8837 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 8904 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 8838 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 8905 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 8839 | { } /* end */ | 8906 | { } /* end */ |
| 8840 | }; | 8907 | }; |
| @@ -8855,10 +8922,10 @@ static struct snd_kcontrol_new alc883_3ST_6ch_intel_mixer[] = { | |||
| 8855 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | 8922 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), |
| 8856 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 8923 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
| 8857 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 8924 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 8858 | HDA_CODEC_VOLUME("Mic Boost", 0x19, 0, HDA_INPUT), | 8925 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 8859 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 8926 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 8860 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 8927 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 8861 | HDA_CODEC_VOLUME("Front Mic Boost", 0x18, 0, HDA_INPUT), | 8928 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 8862 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 8929 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 8863 | { } /* end */ | 8930 | { } /* end */ |
| 8864 | }; | 8931 | }; |
| @@ -8879,10 +8946,10 @@ static struct snd_kcontrol_new alc885_8ch_intel_mixer[] = { | |||
| 8879 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | 8946 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), |
| 8880 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 8947 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
| 8881 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x3, HDA_INPUT), | 8948 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x3, HDA_INPUT), |
| 8882 | HDA_CODEC_VOLUME("Mic Boost", 0x1b, 0, HDA_INPUT), | 8949 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x1b, 0, HDA_INPUT), |
| 8883 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x3, HDA_INPUT), | 8950 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x3, HDA_INPUT), |
| 8884 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 8951 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 8885 | HDA_CODEC_VOLUME("Front Mic Boost", 0x18, 0, HDA_INPUT), | 8952 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 8886 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 8953 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 8887 | { } /* end */ | 8954 | { } /* end */ |
| 8888 | }; | 8955 | }; |
| @@ -8902,10 +8969,10 @@ static struct snd_kcontrol_new alc883_fivestack_mixer[] = { | |||
| 8902 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | 8969 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), |
| 8903 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 8970 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
| 8904 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 8971 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 8905 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 8972 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 8906 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 8973 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 8907 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 8974 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 8908 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 8975 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 8909 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 8976 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 8910 | { } /* end */ | 8977 | { } /* end */ |
| 8911 | }; | 8978 | }; |
| @@ -8926,7 +8993,7 @@ static struct snd_kcontrol_new alc883_targa_mixer[] = { | |||
| 8926 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | 8993 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), |
| 8927 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 8994 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
| 8928 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 8995 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 8929 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 8996 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 8930 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 8997 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 8931 | { } /* end */ | 8998 | { } /* end */ |
| 8932 | }; | 8999 | }; |
| @@ -8939,20 +9006,20 @@ static struct snd_kcontrol_new alc883_targa_2ch_mixer[] = { | |||
| 8939 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 9006 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
| 8940 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 9007 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
| 8941 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 9008 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 8942 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 9009 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 8943 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 9010 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 8944 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 9011 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 8945 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), | 9012 | HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 8946 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 9013 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 8947 | { } /* end */ | 9014 | { } /* end */ |
| 8948 | }; | 9015 | }; |
| 8949 | 9016 | ||
| 8950 | static struct snd_kcontrol_new alc883_targa_8ch_mixer[] = { | 9017 | static struct snd_kcontrol_new alc883_targa_8ch_mixer[] = { |
| 8951 | HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), | 9018 | HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), |
| 8952 | HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), | 9019 | HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), |
| 8953 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 9020 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 8954 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), | 9021 | HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 8955 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 9022 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 8956 | { } /* end */ | 9023 | { } /* end */ |
| 8957 | }; | 9024 | }; |
| 8958 | 9025 | ||
| @@ -8963,7 +9030,7 @@ static struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = { | |||
| 8963 | HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT), | 9030 | HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT), |
| 8964 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | 9031 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), |
| 8965 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 9032 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 8966 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 9033 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 8967 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 9034 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 8968 | { } /* end */ | 9035 | { } /* end */ |
| 8969 | }; | 9036 | }; |
| @@ -8976,21 +9043,8 @@ static struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = { | |||
| 8976 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 9043 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
| 8977 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 9044 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 8978 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 9045 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 8979 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 9046 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 8980 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 9047 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 8981 | { } /* end */ | ||
| 8982 | }; | ||
| 8983 | |||
| 8984 | static struct snd_kcontrol_new alc883_medion_md2_mixer[] = { | ||
| 8985 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
| 8986 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), | ||
| 8987 | HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT), | ||
| 8988 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
| 8989 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
| 8990 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
| 8991 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
| 8992 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
| 8993 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
| 8994 | { } /* end */ | 9048 | { } /* end */ |
| 8995 | }; | 9049 | }; |
| 8996 | 9050 | ||
| @@ -9037,7 +9091,7 @@ static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = { | |||
| 9037 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | 9091 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), |
| 9038 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 9092 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
| 9039 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 9093 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 9040 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 9094 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 9041 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 9095 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 9042 | { } /* end */ | 9096 | { } /* end */ |
| 9043 | }; | 9097 | }; |
| @@ -9050,7 +9104,7 @@ static struct snd_kcontrol_new alc888_acer_aspire_6530_mixer[] = { | |||
| 9050 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 9104 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
| 9051 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 9105 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
| 9052 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 9106 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 9053 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 9107 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 9054 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 9108 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 9055 | { } /* end */ | 9109 | { } /* end */ |
| 9056 | }; | 9110 | }; |
| @@ -9072,10 +9126,10 @@ static struct snd_kcontrol_new alc888_lenovo_sky_mixer[] = { | |||
| 9072 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | 9126 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), |
| 9073 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 9127 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
| 9074 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 9128 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 9075 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 9129 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 9076 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 9130 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 9077 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 9131 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 9078 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 9132 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 9079 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 9133 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 9080 | { } /* end */ | 9134 | { } /* end */ |
| 9081 | }; | 9135 | }; |
| @@ -9096,8 +9150,8 @@ static struct snd_kcontrol_new alc889A_mb31_mixer[] = { | |||
| 9096 | HDA_CODEC_MUTE("Enable Headphones", 0x15, 0x00, HDA_OUTPUT), | 9150 | HDA_CODEC_MUTE("Enable Headphones", 0x15, 0x00, HDA_OUTPUT), |
| 9097 | HDA_CODEC_MUTE_MONO("Enable LFE", 0x16, 2, 0x00, HDA_OUTPUT), | 9151 | HDA_CODEC_MUTE_MONO("Enable LFE", 0x16, 2, 0x00, HDA_OUTPUT), |
| 9098 | /* Boost mixers */ | 9152 | /* Boost mixers */ |
| 9099 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x00, HDA_INPUT), | 9153 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x00, HDA_INPUT), |
| 9100 | HDA_CODEC_VOLUME("Line Boost", 0x1a, 0x00, HDA_INPUT), | 9154 | HDA_CODEC_VOLUME("Line Boost Volume", 0x1a, 0x00, HDA_INPUT), |
| 9101 | /* Input mixers */ | 9155 | /* Input mixers */ |
| 9102 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT), | 9156 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT), |
| 9103 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT), | 9157 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT), |
| @@ -9111,7 +9165,7 @@ static struct snd_kcontrol_new alc883_vaiott_mixer[] = { | |||
| 9111 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | 9165 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), |
| 9112 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), | 9166 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), |
| 9113 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 9167 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 9114 | HDA_CODEC_VOLUME("Mic Boost", 0x19, 0, HDA_INPUT), | 9168 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 9115 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 9169 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 9116 | { } /* end */ | 9170 | { } /* end */ |
| 9117 | }; | 9171 | }; |
| @@ -9141,7 +9195,7 @@ static struct snd_kcontrol_new alc883_asus_eee1601_mixer[] = { | |||
| 9141 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | 9195 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), |
| 9142 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 9196 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
| 9143 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 9197 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 9144 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 9198 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 9145 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 9199 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 9146 | { } /* end */ | 9200 | { } /* end */ |
| 9147 | }; | 9201 | }; |
| @@ -9182,16 +9236,6 @@ static void alc883_mitac_setup(struct hda_codec *codec) | |||
| 9182 | spec->autocfg.speaker_pins[1] = 0x17; | 9236 | spec->autocfg.speaker_pins[1] = 0x17; |
| 9183 | } | 9237 | } |
| 9184 | 9238 | ||
| 9185 | /* auto-toggle front mic */ | ||
| 9186 | /* | ||
| 9187 | static void alc883_mitac_mic_automute(struct hda_codec *codec) | ||
| 9188 | { | ||
| 9189 | unsigned char bits = snd_hda_jack_detect(codec, 0x18) ? HDA_AMP_MUTE : 0; | ||
| 9190 | |||
| 9191 | snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits); | ||
| 9192 | } | ||
| 9193 | */ | ||
| 9194 | |||
| 9195 | static struct hda_verb alc883_mitac_verbs[] = { | 9239 | static struct hda_verb alc883_mitac_verbs[] = { |
| 9196 | /* HP */ | 9240 | /* HP */ |
| 9197 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, | 9241 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, |
| @@ -9435,18 +9479,8 @@ static void alc883_lenovo_ms7195_unsol_event(struct hda_codec *codec, | |||
| 9435 | alc888_lenovo_ms7195_rca_automute(codec); | 9479 | alc888_lenovo_ms7195_rca_automute(codec); |
| 9436 | } | 9480 | } |
| 9437 | 9481 | ||
| 9438 | static struct hda_verb alc883_medion_md2_verbs[] = { | ||
| 9439 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
| 9440 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
| 9441 | |||
| 9442 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
| 9443 | |||
| 9444 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | ||
| 9445 | { } /* end */ | ||
| 9446 | }; | ||
| 9447 | |||
| 9448 | /* toggle speaker-output according to the hp-jack state */ | 9482 | /* toggle speaker-output according to the hp-jack state */ |
| 9449 | static void alc883_medion_md2_setup(struct hda_codec *codec) | 9483 | static void alc883_lenovo_nb0763_setup(struct hda_codec *codec) |
| 9450 | { | 9484 | { |
| 9451 | struct alc_spec *spec = codec->spec; | 9485 | struct alc_spec *spec = codec->spec; |
| 9452 | 9486 | ||
| @@ -9458,15 +9492,6 @@ static void alc883_medion_md2_setup(struct hda_codec *codec) | |||
| 9458 | #define alc883_targa_init_hook alc882_targa_init_hook | 9492 | #define alc883_targa_init_hook alc882_targa_init_hook |
| 9459 | #define alc883_targa_unsol_event alc882_targa_unsol_event | 9493 | #define alc883_targa_unsol_event alc882_targa_unsol_event |
| 9460 | 9494 | ||
| 9461 | static void alc883_clevo_m720_mic_automute(struct hda_codec *codec) | ||
| 9462 | { | ||
| 9463 | unsigned int present; | ||
| 9464 | |||
| 9465 | present = snd_hda_jack_detect(codec, 0x18); | ||
| 9466 | snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, | ||
| 9467 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); | ||
| 9468 | } | ||
| 9469 | |||
| 9470 | static void alc883_clevo_m720_setup(struct hda_codec *codec) | 9495 | static void alc883_clevo_m720_setup(struct hda_codec *codec) |
| 9471 | { | 9496 | { |
| 9472 | struct alc_spec *spec = codec->spec; | 9497 | struct alc_spec *spec = codec->spec; |
| @@ -9478,7 +9503,7 @@ static void alc883_clevo_m720_setup(struct hda_codec *codec) | |||
| 9478 | static void alc883_clevo_m720_init_hook(struct hda_codec *codec) | 9503 | static void alc883_clevo_m720_init_hook(struct hda_codec *codec) |
| 9479 | { | 9504 | { |
| 9480 | alc_automute_amp(codec); | 9505 | alc_automute_amp(codec); |
| 9481 | alc883_clevo_m720_mic_automute(codec); | 9506 | alc88x_simple_mic_automute(codec); |
| 9482 | } | 9507 | } |
| 9483 | 9508 | ||
| 9484 | static void alc883_clevo_m720_unsol_event(struct hda_codec *codec, | 9509 | static void alc883_clevo_m720_unsol_event(struct hda_codec *codec, |
| @@ -9486,7 +9511,7 @@ static void alc883_clevo_m720_unsol_event(struct hda_codec *codec, | |||
| 9486 | { | 9511 | { |
| 9487 | switch (res >> 26) { | 9512 | switch (res >> 26) { |
| 9488 | case ALC880_MIC_EVENT: | 9513 | case ALC880_MIC_EVENT: |
| 9489 | alc883_clevo_m720_mic_automute(codec); | 9514 | alc88x_simple_mic_automute(codec); |
| 9490 | break; | 9515 | break; |
| 9491 | default: | 9516 | default: |
| 9492 | alc_automute_amp_unsol_event(codec, res); | 9517 | alc_automute_amp_unsol_event(codec, res); |
| @@ -9731,7 +9756,6 @@ static const char *alc882_models[ALC882_MODEL_LAST] = { | |||
| 9731 | [ALC888_ACER_ASPIRE_8930G] = "acer-aspire-8930g", | 9756 | [ALC888_ACER_ASPIRE_8930G] = "acer-aspire-8930g", |
| 9732 | [ALC888_ACER_ASPIRE_7730G] = "acer-aspire-7730g", | 9757 | [ALC888_ACER_ASPIRE_7730G] = "acer-aspire-7730g", |
| 9733 | [ALC883_MEDION] = "medion", | 9758 | [ALC883_MEDION] = "medion", |
| 9734 | [ALC883_MEDION_MD2] = "medion-md2", | ||
| 9735 | [ALC883_MEDION_WIM2160] = "medion-wim2160", | 9759 | [ALC883_MEDION_WIM2160] = "medion-wim2160", |
| 9736 | [ALC883_LAPTOP_EAPD] = "laptop-eapd", | 9760 | [ALC883_LAPTOP_EAPD] = "laptop-eapd", |
| 9737 | [ALC883_LENOVO_101E_2ch] = "lenovo-101e", | 9761 | [ALC883_LENOVO_101E_2ch] = "lenovo-101e", |
| @@ -10379,19 +10403,6 @@ static struct alc_config_preset alc882_presets[] = { | |||
| 10379 | .channel_mode = alc883_sixstack_modes, | 10403 | .channel_mode = alc883_sixstack_modes, |
| 10380 | .input_mux = &alc883_capture_source, | 10404 | .input_mux = &alc883_capture_source, |
| 10381 | }, | 10405 | }, |
| 10382 | [ALC883_MEDION_MD2] = { | ||
| 10383 | .mixers = { alc883_medion_md2_mixer}, | ||
| 10384 | .init_verbs = { alc883_init_verbs, alc883_medion_md2_verbs}, | ||
| 10385 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | ||
| 10386 | .dac_nids = alc883_dac_nids, | ||
| 10387 | .dig_out_nid = ALC883_DIGOUT_NID, | ||
| 10388 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), | ||
| 10389 | .channel_mode = alc883_3ST_2ch_modes, | ||
| 10390 | .input_mux = &alc883_capture_source, | ||
| 10391 | .unsol_event = alc_automute_amp_unsol_event, | ||
| 10392 | .setup = alc883_medion_md2_setup, | ||
| 10393 | .init_hook = alc_automute_amp, | ||
| 10394 | }, | ||
| 10395 | [ALC883_MEDION_WIM2160] = { | 10406 | [ALC883_MEDION_WIM2160] = { |
| 10396 | .mixers = { alc883_medion_wim2160_mixer }, | 10407 | .mixers = { alc883_medion_wim2160_mixer }, |
| 10397 | .init_verbs = { alc883_init_verbs, alc883_medion_wim2160_verbs }, | 10408 | .init_verbs = { alc883_init_verbs, alc883_medion_wim2160_verbs }, |
| @@ -10468,7 +10479,7 @@ static struct alc_config_preset alc882_presets[] = { | |||
| 10468 | .need_dac_fix = 1, | 10479 | .need_dac_fix = 1, |
| 10469 | .input_mux = &alc883_lenovo_nb0763_capture_source, | 10480 | .input_mux = &alc883_lenovo_nb0763_capture_source, |
| 10470 | .unsol_event = alc_automute_amp_unsol_event, | 10481 | .unsol_event = alc_automute_amp_unsol_event, |
| 10471 | .setup = alc883_medion_md2_setup, | 10482 | .setup = alc883_lenovo_nb0763_setup, |
| 10472 | .init_hook = alc_automute_amp, | 10483 | .init_hook = alc_automute_amp, |
| 10473 | }, | 10484 | }, |
| 10474 | [ALC888_LENOVO_MS7195_DIG] = { | 10485 | [ALC888_LENOVO_MS7195_DIG] = { |
| @@ -10830,25 +10841,30 @@ static int alc_auto_add_mic_boost(struct hda_codec *codec) | |||
| 10830 | { | 10841 | { |
| 10831 | struct alc_spec *spec = codec->spec; | 10842 | struct alc_spec *spec = codec->spec; |
| 10832 | struct auto_pin_cfg *cfg = &spec->autocfg; | 10843 | struct auto_pin_cfg *cfg = &spec->autocfg; |
| 10833 | int i, err, type; | 10844 | int i, err; |
| 10834 | int type_idx = 0; | 10845 | int type_idx = 0; |
| 10835 | hda_nid_t nid; | 10846 | hda_nid_t nid; |
| 10847 | const char *prev_label = NULL; | ||
| 10836 | 10848 | ||
| 10837 | for (i = 0; i < cfg->num_inputs; i++) { | 10849 | for (i = 0; i < cfg->num_inputs; i++) { |
| 10838 | if (cfg->inputs[i].type > AUTO_PIN_MIC) | 10850 | if (cfg->inputs[i].type > AUTO_PIN_MIC) |
| 10839 | break; | 10851 | break; |
| 10840 | nid = cfg->inputs[i].pin; | 10852 | nid = cfg->inputs[i].pin; |
| 10841 | if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) { | 10853 | if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) { |
| 10842 | char label[32]; | 10854 | const char *label; |
| 10843 | type = cfg->inputs[i].type; | 10855 | char boost_label[32]; |
| 10844 | if (i > 0 && type == cfg->inputs[i - 1].type) | 10856 | |
| 10857 | label = hda_get_autocfg_input_label(codec, cfg, i); | ||
| 10858 | if (prev_label && !strcmp(label, prev_label)) | ||
| 10845 | type_idx++; | 10859 | type_idx++; |
| 10846 | else | 10860 | else |
| 10847 | type_idx = 0; | 10861 | type_idx = 0; |
| 10848 | snprintf(label, sizeof(label), "%s Boost", | 10862 | prev_label = label; |
| 10849 | hda_get_autocfg_input_label(codec, cfg, i)); | 10863 | |
| 10850 | err = add_control(spec, ALC_CTL_WIDGET_VOL, label, | 10864 | snprintf(boost_label, sizeof(boost_label), |
| 10851 | type_idx, | 10865 | "%s Boost Volume", label); |
| 10866 | err = add_control(spec, ALC_CTL_WIDGET_VOL, | ||
| 10867 | boost_label, type_idx, | ||
| 10852 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); | 10868 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); |
| 10853 | if (err < 0) | 10869 | if (err < 0) |
| 10854 | return err; | 10870 | return err; |
| @@ -10857,6 +10873,9 @@ static int alc_auto_add_mic_boost(struct hda_codec *codec) | |||
| 10857 | return 0; | 10873 | return 0; |
| 10858 | } | 10874 | } |
| 10859 | 10875 | ||
| 10876 | static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec, | ||
| 10877 | const struct auto_pin_cfg *cfg); | ||
| 10878 | |||
| 10860 | /* almost identical with ALC880 parser... */ | 10879 | /* almost identical with ALC880 parser... */ |
| 10861 | static int alc882_parse_auto_config(struct hda_codec *codec) | 10880 | static int alc882_parse_auto_config(struct hda_codec *codec) |
| 10862 | { | 10881 | { |
| @@ -10874,7 +10893,10 @@ static int alc882_parse_auto_config(struct hda_codec *codec) | |||
| 10874 | err = alc880_auto_fill_dac_nids(spec, &spec->autocfg); | 10893 | err = alc880_auto_fill_dac_nids(spec, &spec->autocfg); |
| 10875 | if (err < 0) | 10894 | if (err < 0) |
| 10876 | return err; | 10895 | return err; |
| 10877 | err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg); | 10896 | if (codec->vendor_id == 0x10ec0887) |
| 10897 | err = alc861vd_auto_create_multi_out_ctls(spec, &spec->autocfg); | ||
| 10898 | else | ||
| 10899 | err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg); | ||
| 10878 | if (err < 0) | 10900 | if (err < 0) |
| 10879 | return err; | 10901 | return err; |
| 10880 | err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0], | 10902 | err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0], |
| @@ -11090,10 +11112,10 @@ static struct snd_kcontrol_new alc262_base_mixer[] = { | |||
| 11090 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 11112 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
| 11091 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 11113 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 11092 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 11114 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 11093 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 11115 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 11094 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | 11116 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), |
| 11095 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | 11117 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), |
| 11096 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 11118 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 11097 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT), | 11119 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT), |
| 11098 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), | 11120 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), |
| 11099 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | 11121 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), |
| @@ -11194,10 +11216,10 @@ static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = { | |||
| 11194 | HDA_OUTPUT), | 11216 | HDA_OUTPUT), |
| 11195 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 11217 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 11196 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 11218 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 11197 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 11219 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 11198 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | 11220 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), |
| 11199 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | 11221 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), |
| 11200 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 11222 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 11201 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | 11223 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), |
| 11202 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 11224 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
| 11203 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 11225 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
| @@ -11219,7 +11241,7 @@ static struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = { | |||
| 11219 | HDA_OUTPUT), | 11241 | HDA_OUTPUT), |
| 11220 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x02, HDA_INPUT), | 11242 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x02, HDA_INPUT), |
| 11221 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x02, HDA_INPUT), | 11243 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x02, HDA_INPUT), |
| 11222 | HDA_CODEC_VOLUME("Front Mic Boost", 0x1a, 0, HDA_INPUT), | 11244 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x1a, 0, HDA_INPUT), |
| 11223 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT), | 11245 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT), |
| 11224 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT), | 11246 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT), |
| 11225 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 11247 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
| @@ -11230,7 +11252,7 @@ static struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = { | |||
| 11230 | static struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = { | 11252 | static struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = { |
| 11231 | HDA_CODEC_VOLUME("Rear Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 11253 | HDA_CODEC_VOLUME("Rear Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 11232 | HDA_CODEC_MUTE("Rear Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 11254 | HDA_CODEC_MUTE("Rear Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 11233 | HDA_CODEC_VOLUME("Rear Mic Boost", 0x18, 0, HDA_INPUT), | 11255 | HDA_CODEC_VOLUME("Rear Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 11234 | { } /* end */ | 11256 | { } /* end */ |
| 11235 | }; | 11257 | }; |
| 11236 | 11258 | ||
| @@ -11250,7 +11272,7 @@ static struct snd_kcontrol_new alc262_hp_t5735_mixer[] = { | |||
| 11250 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), | 11272 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), |
| 11251 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 11273 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 11252 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 11274 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 11253 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 11275 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 11254 | { } /* end */ | 11276 | { } /* end */ |
| 11255 | }; | 11277 | }; |
| 11256 | 11278 | ||
| @@ -11357,10 +11379,10 @@ static struct snd_kcontrol_new alc262_hippo_mixer[] = { | |||
| 11357 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 11379 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
| 11358 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 11380 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 11359 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 11381 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 11360 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 11382 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 11361 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | 11383 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), |
| 11362 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | 11384 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), |
| 11363 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 11385 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 11364 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | 11386 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), |
| 11365 | { } /* end */ | 11387 | { } /* end */ |
| 11366 | }; | 11388 | }; |
| @@ -11374,10 +11396,10 @@ static struct snd_kcontrol_new alc262_hippo1_mixer[] = { | |||
| 11374 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 11396 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
| 11375 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 11397 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 11376 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 11398 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 11377 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 11399 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 11378 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | 11400 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), |
| 11379 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | 11401 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), |
| 11380 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 11402 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 11381 | { } /* end */ | 11403 | { } /* end */ |
| 11382 | }; | 11404 | }; |
| 11383 | 11405 | ||
| @@ -11445,10 +11467,10 @@ static struct snd_kcontrol_new alc262_tyan_mixer[] = { | |||
| 11445 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 11467 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
| 11446 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 11468 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 11447 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 11469 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 11448 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 11470 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 11449 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | 11471 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), |
| 11450 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | 11472 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), |
| 11451 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 11473 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 11452 | { } /* end */ | 11474 | { } /* end */ |
| 11453 | }; | 11475 | }; |
| 11454 | 11476 | ||
| @@ -11632,7 +11654,7 @@ static struct snd_kcontrol_new alc262_nec_mixer[] = { | |||
| 11632 | 11654 | ||
| 11633 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 11655 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 11634 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 11656 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 11635 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 11657 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 11636 | 11658 | ||
| 11637 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | 11659 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), |
| 11638 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), | 11660 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), |
| @@ -11687,7 +11709,7 @@ static struct hda_input_mux alc262_fujitsu_capture_source = { | |||
| 11687 | .num_items = 3, | 11709 | .num_items = 3, |
| 11688 | .items = { | 11710 | .items = { |
| 11689 | { "Mic", 0x0 }, | 11711 | { "Mic", 0x0 }, |
| 11690 | { "Int Mic", 0x1 }, | 11712 | { "Internal Mic", 0x1 }, |
| 11691 | { "CD", 0x4 }, | 11713 | { "CD", 0x4 }, |
| 11692 | }, | 11714 | }, |
| 11693 | }; | 11715 | }; |
| @@ -11839,12 +11861,12 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = { | |||
| 11839 | }, | 11861 | }, |
| 11840 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 11862 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
| 11841 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 11863 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
| 11842 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 11864 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 11843 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 11865 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 11844 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 11866 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 11845 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), | 11867 | HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 11846 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 11868 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 11847 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 11869 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 11848 | { } /* end */ | 11870 | { } /* end */ |
| 11849 | }; | 11871 | }; |
| 11850 | 11872 | ||
| @@ -11875,12 +11897,12 @@ static struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = { | |||
| 11875 | }, | 11897 | }, |
| 11876 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 11898 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
| 11877 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 11899 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
| 11878 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 11900 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 11879 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 11901 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 11880 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 11902 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 11881 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), | 11903 | HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 11882 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 11904 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 11883 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 11905 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 11884 | { } /* end */ | 11906 | { } /* end */ |
| 11885 | }; | 11907 | }; |
| 11886 | 11908 | ||
| @@ -11889,10 +11911,10 @@ static struct snd_kcontrol_new alc262_toshiba_rx1_mixer[] = { | |||
| 11889 | ALC262_HIPPO_MASTER_SWITCH, | 11911 | ALC262_HIPPO_MASTER_SWITCH, |
| 11890 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 11912 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 11891 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 11913 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 11892 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 11914 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 11893 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | 11915 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), |
| 11894 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | 11916 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), |
| 11895 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 11917 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 11896 | { } /* end */ | 11918 | { } /* end */ |
| 11897 | }; | 11919 | }; |
| 11898 | 11920 | ||
| @@ -11918,8 +11940,8 @@ static struct snd_kcontrol_new alc262_ultra_mixer[] = { | |||
| 11918 | HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT), | 11940 | HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT), |
| 11919 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | 11941 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), |
| 11920 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | 11942 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), |
| 11921 | HDA_CODEC_VOLUME("Mic Boost", 0x19, 0, HDA_INPUT), | 11943 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 11922 | HDA_CODEC_VOLUME("Headphone Mic Boost", 0x15, 0, HDA_INPUT), | 11944 | HDA_CODEC_VOLUME("Headphone Mic Boost Volume", 0x15, 0, HDA_INPUT), |
| 11923 | { } /* end */ | 11945 | { } /* end */ |
| 11924 | }; | 11946 | }; |
| 11925 | 11947 | ||
| @@ -12089,13 +12111,8 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
| 12089 | spec->multiout.dac_nids = spec->private_dac_nids; | 12111 | spec->multiout.dac_nids = spec->private_dac_nids; |
| 12090 | spec->multiout.dac_nids[0] = 2; | 12112 | spec->multiout.dac_nids[0] = 2; |
| 12091 | 12113 | ||
| 12092 | if (!cfg->speaker_pins[0] && !cfg->hp_pins[0]) | 12114 | pfx = alc_get_line_out_pfx(cfg, true); |
| 12093 | pfx = "Master"; | 12115 | if (!pfx) |
| 12094 | else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) | ||
| 12095 | pfx = "Speaker"; | ||
| 12096 | else if (cfg->line_out_type == AUTO_PIN_HP_OUT) | ||
| 12097 | pfx = "Headphone"; | ||
| 12098 | else | ||
| 12099 | pfx = "Front"; | 12116 | pfx = "Front"; |
| 12100 | for (i = 0; i < 2; i++) { | 12117 | for (i = 0; i < 2; i++) { |
| 12101 | err = alc262_add_out_sw_ctl(spec, cfg->line_out_pins[i], pfx, i); | 12118 | err = alc262_add_out_sw_ctl(spec, cfg->line_out_pins[i], pfx, i); |
| @@ -12996,9 +13013,9 @@ static struct snd_kcontrol_new alc268_base_mixer[] = { | |||
| 12996 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), | 13013 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), |
| 12997 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT), | 13014 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT), |
| 12998 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), | 13015 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), |
| 12999 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 13016 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 13000 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 13017 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 13001 | HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT), | 13018 | HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT), |
| 13002 | { } | 13019 | { } |
| 13003 | }; | 13020 | }; |
| 13004 | 13021 | ||
| @@ -13007,9 +13024,9 @@ static struct snd_kcontrol_new alc268_toshiba_mixer[] = { | |||
| 13007 | HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT), | 13024 | HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT), |
| 13008 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT), | 13025 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT), |
| 13009 | ALC262_HIPPO_MASTER_SWITCH, | 13026 | ALC262_HIPPO_MASTER_SWITCH, |
| 13010 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 13027 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 13011 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 13028 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 13012 | HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT), | 13029 | HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT), |
| 13013 | { } | 13030 | { } |
| 13014 | }; | 13031 | }; |
| 13015 | 13032 | ||
| @@ -13113,9 +13130,9 @@ static struct snd_kcontrol_new alc268_acer_mixer[] = { | |||
| 13113 | .put = alc268_acer_master_sw_put, | 13130 | .put = alc268_acer_master_sw_put, |
| 13114 | .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), | 13131 | .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), |
| 13115 | }, | 13132 | }, |
| 13116 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 13133 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 13117 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT), | 13134 | HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 13118 | HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT), | 13135 | HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT), |
| 13119 | { } | 13136 | { } |
| 13120 | }; | 13137 | }; |
| 13121 | 13138 | ||
| @@ -13131,8 +13148,8 @@ static struct snd_kcontrol_new alc268_acer_dmic_mixer[] = { | |||
| 13131 | .put = alc268_acer_master_sw_put, | 13148 | .put = alc268_acer_master_sw_put, |
| 13132 | .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), | 13149 | .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), |
| 13133 | }, | 13150 | }, |
| 13134 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 13151 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 13135 | HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT), | 13152 | HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT), |
| 13136 | { } | 13153 | { } |
| 13137 | }; | 13154 | }; |
| 13138 | 13155 | ||
| @@ -13224,8 +13241,8 @@ static struct snd_kcontrol_new alc268_dell_mixer[] = { | |||
| 13224 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT), | 13241 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT), |
| 13225 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), | 13242 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), |
| 13226 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), | 13243 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), |
| 13227 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 13244 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 13228 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT), | 13245 | HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 13229 | { } | 13246 | { } |
| 13230 | }; | 13247 | }; |
| 13231 | 13248 | ||
| @@ -13258,8 +13275,8 @@ static struct snd_kcontrol_new alc267_quanta_il1_mixer[] = { | |||
| 13258 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), | 13275 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), |
| 13259 | HDA_CODEC_VOLUME("Mic Capture Volume", 0x23, 0x0, HDA_OUTPUT), | 13276 | HDA_CODEC_VOLUME("Mic Capture Volume", 0x23, 0x0, HDA_OUTPUT), |
| 13260 | HDA_BIND_MUTE("Mic Capture Switch", 0x23, 2, HDA_OUTPUT), | 13277 | HDA_BIND_MUTE("Mic Capture Switch", 0x23, 2, HDA_OUTPUT), |
| 13261 | HDA_CODEC_VOLUME("Ext Mic Boost", 0x18, 0, HDA_INPUT), | 13278 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 13262 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), | 13279 | HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 13263 | { } | 13280 | { } |
| 13264 | }; | 13281 | }; |
| 13265 | 13282 | ||
| @@ -14082,10 +14099,10 @@ static struct snd_kcontrol_new alc269_base_mixer[] = { | |||
| 14082 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 14099 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
| 14083 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 14100 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 14084 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 14101 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 14085 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 14102 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 14086 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | 14103 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), |
| 14087 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | 14104 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), |
| 14088 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 14105 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 14089 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), | 14106 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), |
| 14090 | HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), | 14107 | HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), |
| 14091 | { } /* end */ | 14108 | { } /* end */ |
| @@ -14105,10 +14122,10 @@ static struct snd_kcontrol_new alc269_quanta_fl1_mixer[] = { | |||
| 14105 | }, | 14122 | }, |
| 14106 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 14123 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 14107 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 14124 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 14108 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 14125 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 14109 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | 14126 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), |
| 14110 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | 14127 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), |
| 14111 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT), | 14128 | HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 14112 | { } | 14129 | { } |
| 14113 | }; | 14130 | }; |
| 14114 | 14131 | ||
| @@ -14126,13 +14143,13 @@ static struct snd_kcontrol_new alc269_lifebook_mixer[] = { | |||
| 14126 | }, | 14143 | }, |
| 14127 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 14144 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 14128 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 14145 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 14129 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 14146 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 14130 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | 14147 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), |
| 14131 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | 14148 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), |
| 14132 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT), | 14149 | HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 14133 | HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x0b, 0x03, HDA_INPUT), | 14150 | HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x0b, 0x03, HDA_INPUT), |
| 14134 | HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x0b, 0x03, HDA_INPUT), | 14151 | HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x0b, 0x03, HDA_INPUT), |
| 14135 | HDA_CODEC_VOLUME("Dock Mic Boost", 0x1b, 0, HDA_INPUT), | 14152 | HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x1b, 0, HDA_INPUT), |
| 14136 | { } | 14153 | { } |
| 14137 | }; | 14154 | }; |
| 14138 | 14155 | ||
| @@ -14162,30 +14179,30 @@ static struct snd_kcontrol_new alc269_asus_mixer[] = { | |||
| 14162 | static struct snd_kcontrol_new alc269_laptop_analog_capture_mixer[] = { | 14179 | static struct snd_kcontrol_new alc269_laptop_analog_capture_mixer[] = { |
| 14163 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | 14180 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), |
| 14164 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | 14181 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), |
| 14165 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 14182 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 14166 | HDA_CODEC_VOLUME("IntMic Boost", 0x19, 0, HDA_INPUT), | 14183 | HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 14167 | { } /* end */ | 14184 | { } /* end */ |
| 14168 | }; | 14185 | }; |
| 14169 | 14186 | ||
| 14170 | static struct snd_kcontrol_new alc269_laptop_digital_capture_mixer[] = { | 14187 | static struct snd_kcontrol_new alc269_laptop_digital_capture_mixer[] = { |
| 14171 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | 14188 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), |
| 14172 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | 14189 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), |
| 14173 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 14190 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 14174 | { } /* end */ | 14191 | { } /* end */ |
| 14175 | }; | 14192 | }; |
| 14176 | 14193 | ||
| 14177 | static struct snd_kcontrol_new alc269vb_laptop_analog_capture_mixer[] = { | 14194 | static struct snd_kcontrol_new alc269vb_laptop_analog_capture_mixer[] = { |
| 14178 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), | 14195 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), |
| 14179 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), | 14196 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), |
| 14180 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 14197 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 14181 | HDA_CODEC_VOLUME("IntMic Boost", 0x19, 0, HDA_INPUT), | 14198 | HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 14182 | { } /* end */ | 14199 | { } /* end */ |
| 14183 | }; | 14200 | }; |
| 14184 | 14201 | ||
| 14185 | static struct snd_kcontrol_new alc269vb_laptop_digital_capture_mixer[] = { | 14202 | static struct snd_kcontrol_new alc269vb_laptop_digital_capture_mixer[] = { |
| 14186 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), | 14203 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), |
| 14187 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), | 14204 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), |
| 14188 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 14205 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 14189 | { } /* end */ | 14206 | { } /* end */ |
| 14190 | }; | 14207 | }; |
| 14191 | 14208 | ||
| @@ -14804,12 +14821,23 @@ static int alc269_resume(struct hda_codec *codec) | |||
| 14804 | } | 14821 | } |
| 14805 | #endif /* SND_HDA_NEEDS_RESUME */ | 14822 | #endif /* SND_HDA_NEEDS_RESUME */ |
| 14806 | 14823 | ||
| 14824 | static void alc269_fixup_hweq(struct hda_codec *codec, | ||
| 14825 | const struct alc_fixup *fix, int pre_init) | ||
| 14826 | { | ||
| 14827 | int coef; | ||
| 14828 | |||
| 14829 | coef = alc_read_coef_idx(codec, 0x1e); | ||
| 14830 | alc_write_coef_idx(codec, 0x1e, coef | 0x80); | ||
| 14831 | } | ||
| 14832 | |||
| 14807 | enum { | 14833 | enum { |
| 14808 | ALC269_FIXUP_SONY_VAIO, | 14834 | ALC269_FIXUP_SONY_VAIO, |
| 14809 | ALC275_FIX_SONY_VAIO_GPIO2, | 14835 | ALC275_FIX_SONY_VAIO_GPIO2, |
| 14810 | ALC269_FIXUP_DELL_M101Z, | 14836 | ALC269_FIXUP_DELL_M101Z, |
| 14811 | ALC269_FIXUP_SKU_IGNORE, | 14837 | ALC269_FIXUP_SKU_IGNORE, |
| 14812 | ALC269_FIXUP_ASUS_G73JW, | 14838 | ALC269_FIXUP_ASUS_G73JW, |
| 14839 | ALC269_FIXUP_LENOVO_EAPD, | ||
| 14840 | ALC275_FIXUP_SONY_HWEQ, | ||
| 14813 | }; | 14841 | }; |
| 14814 | 14842 | ||
| 14815 | static const struct alc_fixup alc269_fixups[] = { | 14843 | static const struct alc_fixup alc269_fixups[] = { |
| @@ -14824,6 +14852,7 @@ static const struct alc_fixup alc269_fixups[] = { | |||
| 14824 | {0x01, AC_VERB_SET_GPIO_MASK, 0x04}, | 14852 | {0x01, AC_VERB_SET_GPIO_MASK, 0x04}, |
| 14825 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04}, | 14853 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04}, |
| 14826 | {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, | 14854 | {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, |
| 14855 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD}, | ||
| 14827 | { } | 14856 | { } |
| 14828 | } | 14857 | } |
| 14829 | }, | 14858 | }, |
| @@ -14844,17 +14873,34 @@ static const struct alc_fixup alc269_fixups[] = { | |||
| 14844 | { } | 14873 | { } |
| 14845 | } | 14874 | } |
| 14846 | }, | 14875 | }, |
| 14876 | [ALC269_FIXUP_LENOVO_EAPD] = { | ||
| 14877 | .verbs = (const struct hda_verb[]) { | ||
| 14878 | {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0}, | ||
| 14879 | {} | ||
| 14880 | } | ||
| 14881 | }, | ||
| 14882 | [ALC275_FIXUP_SONY_HWEQ] = { | ||
| 14883 | .func = alc269_fixup_hweq, | ||
| 14884 | .verbs = (const struct hda_verb[]) { | ||
| 14885 | {0x01, AC_VERB_SET_GPIO_MASK, 0x04}, | ||
| 14886 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04}, | ||
| 14887 | {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, | ||
| 14888 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD}, | ||
| 14889 | { } | ||
| 14890 | } | ||
| 14891 | } | ||
| 14847 | }; | 14892 | }; |
| 14848 | 14893 | ||
| 14849 | static struct snd_pci_quirk alc269_fixup_tbl[] = { | 14894 | static struct snd_pci_quirk alc269_fixup_tbl[] = { |
| 14850 | SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIX_SONY_VAIO_GPIO2), | 14895 | SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIX_SONY_VAIO_GPIO2), |
| 14851 | SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIX_SONY_VAIO_GPIO2), | 14896 | SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), |
| 14852 | SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIX_SONY_VAIO_GPIO2), | 14897 | SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), |
| 14853 | SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), | 14898 | SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), |
| 14854 | SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), | 14899 | SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), |
| 14855 | SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE), | 14900 | SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE), |
| 14856 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), | 14901 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), |
| 14857 | SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), | 14902 | SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), |
| 14903 | SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), | ||
| 14858 | {} | 14904 | {} |
| 14859 | }; | 14905 | }; |
| 14860 | 14906 | ||
| @@ -15889,13 +15935,16 @@ static int alc861_auto_fill_dac_nids(struct hda_codec *codec, | |||
| 15889 | return 0; | 15935 | return 0; |
| 15890 | } | 15936 | } |
| 15891 | 15937 | ||
| 15892 | static int alc861_create_out_sw(struct hda_codec *codec, const char *pfx, | 15938 | static int __alc861_create_out_sw(struct hda_codec *codec, const char *pfx, |
| 15893 | hda_nid_t nid, unsigned int chs) | 15939 | hda_nid_t nid, int idx, unsigned int chs) |
| 15894 | { | 15940 | { |
| 15895 | return add_pb_sw_ctrl(codec->spec, ALC_CTL_WIDGET_MUTE, pfx, | 15941 | return __add_pb_sw_ctrl(codec->spec, ALC_CTL_WIDGET_MUTE, pfx, idx, |
| 15896 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); | 15942 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); |
| 15897 | } | 15943 | } |
| 15898 | 15944 | ||
| 15945 | #define alc861_create_out_sw(codec, pfx, nid, chs) \ | ||
| 15946 | __alc861_create_out_sw(codec, pfx, nid, 0, chs) | ||
| 15947 | |||
| 15899 | /* add playback controls from the parsed DAC table */ | 15948 | /* add playback controls from the parsed DAC table */ |
| 15900 | static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec, | 15949 | static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec, |
| 15901 | const struct auto_pin_cfg *cfg) | 15950 | const struct auto_pin_cfg *cfg) |
| @@ -15904,26 +15953,15 @@ static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
| 15904 | static const char *chname[4] = { | 15953 | static const char *chname[4] = { |
| 15905 | "Front", "Surround", NULL /*CLFE*/, "Side" | 15954 | "Front", "Surround", NULL /*CLFE*/, "Side" |
| 15906 | }; | 15955 | }; |
| 15956 | const char *pfx = alc_get_line_out_pfx(cfg, true); | ||
| 15907 | hda_nid_t nid; | 15957 | hda_nid_t nid; |
| 15908 | int i, err; | 15958 | int i, err; |
| 15909 | 15959 | ||
| 15910 | if (cfg->line_outs == 1) { | ||
| 15911 | const char *pfx = NULL; | ||
| 15912 | if (!cfg->hp_outs) | ||
| 15913 | pfx = "Master"; | ||
| 15914 | else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) | ||
| 15915 | pfx = "Speaker"; | ||
| 15916 | if (pfx) { | ||
| 15917 | nid = spec->multiout.dac_nids[0]; | ||
| 15918 | return alc861_create_out_sw(codec, pfx, nid, 3); | ||
| 15919 | } | ||
| 15920 | } | ||
| 15921 | |||
| 15922 | for (i = 0; i < cfg->line_outs; i++) { | 15960 | for (i = 0; i < cfg->line_outs; i++) { |
| 15923 | nid = spec->multiout.dac_nids[i]; | 15961 | nid = spec->multiout.dac_nids[i]; |
| 15924 | if (!nid) | 15962 | if (!nid) |
| 15925 | continue; | 15963 | continue; |
| 15926 | if (i == 2) { | 15964 | if (!pfx && i == 2) { |
| 15927 | /* Center/LFE */ | 15965 | /* Center/LFE */ |
| 15928 | err = alc861_create_out_sw(codec, "Center", nid, 1); | 15966 | err = alc861_create_out_sw(codec, "Center", nid, 1); |
| 15929 | if (err < 0) | 15967 | if (err < 0) |
| @@ -15932,7 +15970,10 @@ static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
| 15932 | if (err < 0) | 15970 | if (err < 0) |
| 15933 | return err; | 15971 | return err; |
| 15934 | } else { | 15972 | } else { |
| 15935 | err = alc861_create_out_sw(codec, chname[i], nid, 3); | 15973 | const char *name = pfx; |
| 15974 | if (!name) | ||
| 15975 | name = chname[i]; | ||
| 15976 | err = __alc861_create_out_sw(codec, name, nid, i, 3); | ||
| 15936 | if (err < 0) | 15977 | if (err < 0) |
| 15937 | return err; | 15978 | return err; |
| 15938 | } | 15979 | } |
| @@ -16404,8 +16445,8 @@ static struct hda_input_mux alc861vd_capture_source = { | |||
| 16404 | static struct hda_input_mux alc861vd_dallas_capture_source = { | 16445 | static struct hda_input_mux alc861vd_dallas_capture_source = { |
| 16405 | .num_items = 2, | 16446 | .num_items = 2, |
| 16406 | .items = { | 16447 | .items = { |
| 16407 | { "Ext Mic", 0x0 }, | 16448 | { "Mic", 0x0 }, |
| 16408 | { "Int Mic", 0x1 }, | 16449 | { "Internal Mic", 0x1 }, |
| 16409 | }, | 16450 | }, |
| 16410 | }; | 16451 | }; |
| 16411 | 16452 | ||
| @@ -16484,11 +16525,11 @@ static struct snd_kcontrol_new alc861vd_6st_mixer[] = { | |||
| 16484 | 16525 | ||
| 16485 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | 16526 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), |
| 16486 | 16527 | ||
| 16487 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 16528 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 16488 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 16529 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 16489 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 16530 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 16490 | 16531 | ||
| 16491 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 16532 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 16492 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 16533 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 16493 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 16534 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 16494 | 16535 | ||
| @@ -16507,11 +16548,11 @@ static struct snd_kcontrol_new alc861vd_3st_mixer[] = { | |||
| 16507 | 16548 | ||
| 16508 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | 16549 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), |
| 16509 | 16550 | ||
| 16510 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 16551 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 16511 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 16552 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 16512 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 16553 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 16513 | 16554 | ||
| 16514 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 16555 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 16515 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 16556 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 16516 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 16557 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 16517 | 16558 | ||
| @@ -16531,11 +16572,11 @@ static struct snd_kcontrol_new alc861vd_lenovo_mixer[] = { | |||
| 16531 | 16572 | ||
| 16532 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | 16573 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), |
| 16533 | 16574 | ||
| 16534 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 16575 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 16535 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 16576 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 16536 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 16577 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 16537 | 16578 | ||
| 16538 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | 16579 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 16539 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 16580 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 16540 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 16581 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 16541 | 16582 | ||
| @@ -16546,19 +16587,19 @@ static struct snd_kcontrol_new alc861vd_lenovo_mixer[] = { | |||
| 16546 | }; | 16587 | }; |
| 16547 | 16588 | ||
| 16548 | /* Pin assignment: Speaker=0x14, HP = 0x15, | 16589 | /* Pin assignment: Speaker=0x14, HP = 0x15, |
| 16549 | * Ext Mic=0x18, Int Mic = 0x19, CD = 0x1c, PC Beep = 0x1d | 16590 | * Mic=0x18, Internal Mic = 0x19, CD = 0x1c, PC Beep = 0x1d |
| 16550 | */ | 16591 | */ |
| 16551 | static struct snd_kcontrol_new alc861vd_dallas_mixer[] = { | 16592 | static struct snd_kcontrol_new alc861vd_dallas_mixer[] = { |
| 16552 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT), | 16593 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT), |
| 16553 | HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT), | 16594 | HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT), |
| 16554 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), | 16595 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), |
| 16555 | HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT), | 16596 | HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT), |
| 16556 | HDA_CODEC_VOLUME("Ext Mic Boost", 0x18, 0, HDA_INPUT), | 16597 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 16557 | HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 16598 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 16558 | HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 16599 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 16559 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), | 16600 | HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 16560 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 16601 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 16561 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 16602 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 16562 | { } /* end */ | 16603 | { } /* end */ |
| 16563 | }; | 16604 | }; |
| 16564 | 16605 | ||
| @@ -16723,18 +16764,6 @@ static struct hda_verb alc861vd_lenovo_unsol_verbs[] = { | |||
| 16723 | {} | 16764 | {} |
| 16724 | }; | 16765 | }; |
| 16725 | 16766 | ||
| 16726 | static void alc861vd_lenovo_mic_automute(struct hda_codec *codec) | ||
| 16727 | { | ||
| 16728 | unsigned int present; | ||
| 16729 | unsigned char bits; | ||
| 16730 | |||
| 16731 | present = snd_hda_jack_detect(codec, 0x18); | ||
| 16732 | bits = present ? HDA_AMP_MUTE : 0; | ||
| 16733 | |||
| 16734 | snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, | ||
| 16735 | HDA_AMP_MUTE, bits); | ||
| 16736 | } | ||
| 16737 | |||
| 16738 | static void alc861vd_lenovo_setup(struct hda_codec *codec) | 16767 | static void alc861vd_lenovo_setup(struct hda_codec *codec) |
| 16739 | { | 16768 | { |
| 16740 | struct alc_spec *spec = codec->spec; | 16769 | struct alc_spec *spec = codec->spec; |
| @@ -16745,7 +16774,7 @@ static void alc861vd_lenovo_setup(struct hda_codec *codec) | |||
| 16745 | static void alc861vd_lenovo_init_hook(struct hda_codec *codec) | 16774 | static void alc861vd_lenovo_init_hook(struct hda_codec *codec) |
| 16746 | { | 16775 | { |
| 16747 | alc_automute_amp(codec); | 16776 | alc_automute_amp(codec); |
| 16748 | alc861vd_lenovo_mic_automute(codec); | 16777 | alc88x_simple_mic_automute(codec); |
| 16749 | } | 16778 | } |
| 16750 | 16779 | ||
| 16751 | static void alc861vd_lenovo_unsol_event(struct hda_codec *codec, | 16780 | static void alc861vd_lenovo_unsol_event(struct hda_codec *codec, |
| @@ -16753,7 +16782,7 @@ static void alc861vd_lenovo_unsol_event(struct hda_codec *codec, | |||
| 16753 | { | 16782 | { |
| 16754 | switch (res >> 26) { | 16783 | switch (res >> 26) { |
| 16755 | case ALC880_MIC_EVENT: | 16784 | case ALC880_MIC_EVENT: |
| 16756 | alc861vd_lenovo_mic_automute(codec); | 16785 | alc88x_simple_mic_automute(codec); |
| 16757 | break; | 16786 | break; |
| 16758 | default: | 16787 | default: |
| 16759 | alc_automute_amp_unsol_event(codec, res); | 16788 | alc_automute_amp_unsol_event(codec, res); |
| @@ -17043,12 +17072,13 @@ static void alc861vd_auto_init_analog_input(struct hda_codec *codec) | |||
| 17043 | #define alc861vd_idx_to_mixer_switch(nid) ((nid) + 0x0c) | 17072 | #define alc861vd_idx_to_mixer_switch(nid) ((nid) + 0x0c) |
| 17044 | 17073 | ||
| 17045 | /* add playback controls from the parsed DAC table */ | 17074 | /* add playback controls from the parsed DAC table */ |
| 17046 | /* Based on ALC880 version. But ALC861VD has separate, | 17075 | /* Based on ALC880 version. But ALC861VD and ALC887 have separate, |
| 17047 | * different NIDs for mute/unmute switch and volume control */ | 17076 | * different NIDs for mute/unmute switch and volume control */ |
| 17048 | static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec, | 17077 | static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec, |
| 17049 | const struct auto_pin_cfg *cfg) | 17078 | const struct auto_pin_cfg *cfg) |
| 17050 | { | 17079 | { |
| 17051 | static const char *chname[4] = {"Front", "Surround", "CLFE", "Side"}; | 17080 | static const char *chname[4] = {"Front", "Surround", "CLFE", "Side"}; |
| 17081 | const char *pfx = alc_get_line_out_pfx(cfg, true); | ||
| 17052 | hda_nid_t nid_v, nid_s; | 17082 | hda_nid_t nid_v, nid_s; |
| 17053 | int i, err; | 17083 | int i, err; |
| 17054 | 17084 | ||
| @@ -17062,7 +17092,7 @@ static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
| 17062 | alc880_dac_to_idx( | 17092 | alc880_dac_to_idx( |
| 17063 | spec->multiout.dac_nids[i])); | 17093 | spec->multiout.dac_nids[i])); |
| 17064 | 17094 | ||
| 17065 | if (i == 2) { | 17095 | if (!pfx && i == 2) { |
| 17066 | /* Center/LFE */ | 17096 | /* Center/LFE */ |
| 17067 | err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, | 17097 | err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, |
| 17068 | "Center", | 17098 | "Center", |
| @@ -17089,24 +17119,17 @@ static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
| 17089 | if (err < 0) | 17119 | if (err < 0) |
| 17090 | return err; | 17120 | return err; |
| 17091 | } else { | 17121 | } else { |
| 17092 | const char *pfx; | 17122 | const char *name = pfx; |
| 17093 | if (cfg->line_outs == 1 && | 17123 | if (!name) |
| 17094 | cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) { | 17124 | name = chname[i]; |
| 17095 | if (!cfg->hp_pins) | 17125 | err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, |
| 17096 | pfx = "Speaker"; | 17126 | name, i, |
| 17097 | else | ||
| 17098 | pfx = "PCM"; | ||
| 17099 | } else | ||
| 17100 | pfx = chname[i]; | ||
| 17101 | err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, | ||
| 17102 | HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, | 17127 | HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, |
| 17103 | HDA_OUTPUT)); | 17128 | HDA_OUTPUT)); |
| 17104 | if (err < 0) | 17129 | if (err < 0) |
| 17105 | return err; | 17130 | return err; |
| 17106 | if (cfg->line_outs == 1 && | 17131 | err = __add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, |
| 17107 | cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) | 17132 | name, i, |
| 17108 | pfx = "Speaker"; | ||
| 17109 | err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx, | ||
| 17110 | HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, | 17133 | HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, |
| 17111 | HDA_INPUT)); | 17134 | HDA_INPUT)); |
| 17112 | if (err < 0) | 17135 | if (err < 0) |
| @@ -17570,13 +17593,13 @@ static struct snd_kcontrol_new alc662_eeepc_p701_mixer[] = { | |||
| 17570 | HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT), | 17593 | HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT), |
| 17571 | ALC262_HIPPO_MASTER_SWITCH, | 17594 | ALC262_HIPPO_MASTER_SWITCH, |
| 17572 | 17595 | ||
| 17573 | HDA_CODEC_VOLUME("e-Mic Boost", 0x18, 0, HDA_INPUT), | 17596 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 17574 | HDA_CODEC_VOLUME("e-Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 17597 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 17575 | HDA_CODEC_MUTE("e-Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 17598 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 17576 | 17599 | ||
| 17577 | HDA_CODEC_VOLUME("i-Mic Boost", 0x19, 0, HDA_INPUT), | 17600 | HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 17578 | HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 17601 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 17579 | HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 17602 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 17580 | { } /* end */ | 17603 | { } /* end */ |
| 17581 | }; | 17604 | }; |
| 17582 | 17605 | ||
| @@ -17720,8 +17743,8 @@ static struct snd_kcontrol_new alc663_g71v_mixer[] = { | |||
| 17720 | 17743 | ||
| 17721 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 17744 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 17722 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 17745 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 17723 | HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 17746 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 17724 | HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 17747 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 17725 | { } /* end */ | 17748 | { } /* end */ |
| 17726 | }; | 17749 | }; |
| 17727 | 17750 | ||
| @@ -17732,8 +17755,8 @@ static struct snd_kcontrol_new alc663_g50v_mixer[] = { | |||
| 17732 | 17755 | ||
| 17733 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 17756 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 17734 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 17757 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 17735 | HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 17758 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 17736 | HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 17759 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 17737 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | 17760 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), |
| 17738 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 17761 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
| 17739 | { } /* end */ | 17762 | { } /* end */ |
| @@ -18566,13 +18589,13 @@ static struct snd_kcontrol_new alc662_ecs_mixer[] = { | |||
| 18566 | HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT), | 18589 | HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT), |
| 18567 | ALC262_HIPPO_MASTER_SWITCH, | 18590 | ALC262_HIPPO_MASTER_SWITCH, |
| 18568 | 18591 | ||
| 18569 | HDA_CODEC_VOLUME("e-Mic/LineIn Boost", 0x18, 0, HDA_INPUT), | 18592 | HDA_CODEC_VOLUME("Mic/LineIn Boost Volume", 0x18, 0, HDA_INPUT), |
| 18570 | HDA_CODEC_VOLUME("e-Mic/LineIn Playback Volume", 0x0b, 0x0, HDA_INPUT), | 18593 | HDA_CODEC_VOLUME("Mic/LineIn Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 18571 | HDA_CODEC_MUTE("e-Mic/LineIn Playback Switch", 0x0b, 0x0, HDA_INPUT), | 18594 | HDA_CODEC_MUTE("Mic/LineIn Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 18572 | 18595 | ||
| 18573 | HDA_CODEC_VOLUME("i-Mic Boost", 0x19, 0, HDA_INPUT), | 18596 | HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 18574 | HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 18597 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 18575 | HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 18598 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 18576 | { } /* end */ | 18599 | { } /* end */ |
| 18577 | }; | 18600 | }; |
| 18578 | 18601 | ||
| @@ -18583,13 +18606,13 @@ static struct snd_kcontrol_new alc272_nc10_mixer[] = { | |||
| 18583 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), | 18606 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), |
| 18584 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT), | 18607 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT), |
| 18585 | 18608 | ||
| 18586 | HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 18609 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
| 18587 | HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 18610 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
| 18588 | HDA_CODEC_VOLUME("Ext Mic Boost", 0x18, 0, HDA_INPUT), | 18611 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 18589 | 18612 | ||
| 18590 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 18613 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
| 18591 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 18614 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
| 18592 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), | 18615 | HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT), |
| 18593 | { } /* end */ | 18616 | { } /* end */ |
| 18594 | }; | 18617 | }; |
| 18595 | 18618 | ||
| @@ -19094,20 +19117,24 @@ static int alc662_auto_fill_dac_nids(struct hda_codec *codec, | |||
| 19094 | return 0; | 19117 | return 0; |
| 19095 | } | 19118 | } |
| 19096 | 19119 | ||
| 19097 | static inline int alc662_add_vol_ctl(struct alc_spec *spec, const char *pfx, | 19120 | static inline int __alc662_add_vol_ctl(struct alc_spec *spec, const char *pfx, |
| 19098 | hda_nid_t nid, unsigned int chs) | 19121 | hda_nid_t nid, int idx, unsigned int chs) |
| 19099 | { | 19122 | { |
| 19100 | return add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, | 19123 | return __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, idx, |
| 19101 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); | 19124 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); |
| 19102 | } | 19125 | } |
| 19103 | 19126 | ||
| 19104 | static inline int alc662_add_sw_ctl(struct alc_spec *spec, const char *pfx, | 19127 | static inline int __alc662_add_sw_ctl(struct alc_spec *spec, const char *pfx, |
| 19105 | hda_nid_t nid, unsigned int chs) | 19128 | hda_nid_t nid, int idx, unsigned int chs) |
| 19106 | { | 19129 | { |
| 19107 | return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, | 19130 | return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, idx, |
| 19108 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT)); | 19131 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT)); |
| 19109 | } | 19132 | } |
| 19110 | 19133 | ||
| 19134 | #define alc662_add_vol_ctl(spec, pfx, nid, chs) \ | ||
| 19135 | __alc662_add_vol_ctl(spec, pfx, nid, 0, chs) | ||
| 19136 | #define alc662_add_sw_ctl(spec, pfx, nid, chs) \ | ||
| 19137 | __alc662_add_sw_ctl(spec, pfx, nid, 0, chs) | ||
| 19111 | #define alc662_add_stereo_vol(spec, pfx, nid) \ | 19138 | #define alc662_add_stereo_vol(spec, pfx, nid) \ |
| 19112 | alc662_add_vol_ctl(spec, pfx, nid, 3) | 19139 | alc662_add_vol_ctl(spec, pfx, nid, 3) |
| 19113 | #define alc662_add_stereo_sw(spec, pfx, nid) \ | 19140 | #define alc662_add_stereo_sw(spec, pfx, nid) \ |
| @@ -19121,6 +19148,7 @@ static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
| 19121 | static const char *chname[4] = { | 19148 | static const char *chname[4] = { |
| 19122 | "Front", "Surround", NULL /*CLFE*/, "Side" | 19149 | "Front", "Surround", NULL /*CLFE*/, "Side" |
| 19123 | }; | 19150 | }; |
| 19151 | const char *pfx = alc_get_line_out_pfx(cfg, true); | ||
| 19124 | hda_nid_t nid, mix; | 19152 | hda_nid_t nid, mix; |
| 19125 | int i, err; | 19153 | int i, err; |
| 19126 | 19154 | ||
| @@ -19131,7 +19159,7 @@ static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
| 19131 | mix = alc662_dac_to_mix(codec, cfg->line_out_pins[i], nid); | 19159 | mix = alc662_dac_to_mix(codec, cfg->line_out_pins[i], nid); |
| 19132 | if (!mix) | 19160 | if (!mix) |
| 19133 | continue; | 19161 | continue; |
| 19134 | if (i == 2) { | 19162 | if (!pfx && i == 2) { |
| 19135 | /* Center/LFE */ | 19163 | /* Center/LFE */ |
| 19136 | err = alc662_add_vol_ctl(spec, "Center", nid, 1); | 19164 | err = alc662_add_vol_ctl(spec, "Center", nid, 1); |
| 19137 | if (err < 0) | 19165 | if (err < 0) |
| @@ -19146,22 +19174,13 @@ static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
| 19146 | if (err < 0) | 19174 | if (err < 0) |
| 19147 | return err; | 19175 | return err; |
| 19148 | } else { | 19176 | } else { |
| 19149 | const char *pfx; | 19177 | const char *name = pfx; |
| 19150 | if (cfg->line_outs == 1 && | 19178 | if (!name) |
| 19151 | cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) { | 19179 | name = chname[i]; |
| 19152 | if (cfg->hp_outs) | 19180 | err = __alc662_add_vol_ctl(spec, name, nid, i, 3); |
| 19153 | pfx = "Speaker"; | ||
| 19154 | else | ||
| 19155 | pfx = "PCM"; | ||
| 19156 | } else | ||
| 19157 | pfx = chname[i]; | ||
| 19158 | err = alc662_add_vol_ctl(spec, pfx, nid, 3); | ||
| 19159 | if (err < 0) | 19181 | if (err < 0) |
| 19160 | return err; | 19182 | return err; |
| 19161 | if (cfg->line_outs == 1 && | 19183 | err = __alc662_add_sw_ctl(spec, name, mix, i, 3); |
| 19162 | cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) | ||
| 19163 | pfx = "Speaker"; | ||
| 19164 | err = alc662_add_sw_ctl(spec, pfx, mix, 3); | ||
| 19165 | if (err < 0) | 19184 | if (err < 0) |
| 19166 | return err; | 19185 | return err; |
| 19167 | } | 19186 | } |
| @@ -19358,9 +19377,21 @@ static void alc662_auto_init(struct hda_codec *codec) | |||
| 19358 | alc_inithook(codec); | 19377 | alc_inithook(codec); |
| 19359 | } | 19378 | } |
| 19360 | 19379 | ||
| 19380 | static void alc272_fixup_mario(struct hda_codec *codec, | ||
| 19381 | const struct alc_fixup *fix, int pre_init) { | ||
| 19382 | if (snd_hda_override_amp_caps(codec, 0x2, HDA_OUTPUT, | ||
| 19383 | (0x3b << AC_AMPCAP_OFFSET_SHIFT) | | ||
| 19384 | (0x3b << AC_AMPCAP_NUM_STEPS_SHIFT) | | ||
| 19385 | (0x03 << AC_AMPCAP_STEP_SIZE_SHIFT) | | ||
| 19386 | (0 << AC_AMPCAP_MUTE_SHIFT))) | ||
| 19387 | printk(KERN_WARNING | ||
| 19388 | "hda_codec: failed to override amp caps for NID 0x2\n"); | ||
| 19389 | } | ||
| 19390 | |||
| 19361 | enum { | 19391 | enum { |
| 19362 | ALC662_FIXUP_ASPIRE, | 19392 | ALC662_FIXUP_ASPIRE, |
| 19363 | ALC662_FIXUP_IDEAPAD, | 19393 | ALC662_FIXUP_IDEAPAD, |
| 19394 | ALC272_FIXUP_MARIO, | ||
| 19364 | }; | 19395 | }; |
| 19365 | 19396 | ||
| 19366 | static const struct alc_fixup alc662_fixups[] = { | 19397 | static const struct alc_fixup alc662_fixups[] = { |
| @@ -19376,6 +19407,9 @@ static const struct alc_fixup alc662_fixups[] = { | |||
| 19376 | { } | 19407 | { } |
| 19377 | } | 19408 | } |
| 19378 | }, | 19409 | }, |
| 19410 | [ALC272_FIXUP_MARIO] = { | ||
| 19411 | .func = alc272_fixup_mario, | ||
| 19412 | } | ||
| 19379 | }; | 19413 | }; |
| 19380 | 19414 | ||
| 19381 | static struct snd_pci_quirk alc662_fixup_tbl[] = { | 19415 | static struct snd_pci_quirk alc662_fixup_tbl[] = { |
| @@ -19386,6 +19420,10 @@ static struct snd_pci_quirk alc662_fixup_tbl[] = { | |||
| 19386 | {} | 19420 | {} |
| 19387 | }; | 19421 | }; |
| 19388 | 19422 | ||
| 19423 | static const struct alc_model_fixup alc662_fixup_models[] = { | ||
| 19424 | {.id = ALC272_FIXUP_MARIO, .name = "mario"}, | ||
| 19425 | {} | ||
| 19426 | }; | ||
| 19389 | 19427 | ||
| 19390 | 19428 | ||
| 19391 | static int patch_alc662(struct hda_codec *codec) | 19429 | static int patch_alc662(struct hda_codec *codec) |
| @@ -19485,7 +19523,8 @@ static int patch_alc662(struct hda_codec *codec) | |||
| 19485 | codec->patch_ops = alc_patch_ops; | 19523 | codec->patch_ops = alc_patch_ops; |
| 19486 | if (board_config == ALC662_AUTO) { | 19524 | if (board_config == ALC662_AUTO) { |
| 19487 | spec->init_hook = alc662_auto_init; | 19525 | spec->init_hook = alc662_auto_init; |
| 19488 | alc_pick_fixup(codec, alc662_fixup_tbl, alc662_fixups, 0); | 19526 | alc_pick_fixup_model(codec, alc662_fixup_models, |
| 19527 | alc662_fixup_tbl, alc662_fixups, 0); | ||
| 19489 | } | 19528 | } |
| 19490 | 19529 | ||
| 19491 | alc_init_jacks(codec); | 19530 | alc_init_jacks(codec); |
| @@ -19612,9 +19651,9 @@ static struct snd_kcontrol_new alc680_base_mixer[] = { | |||
| 19612 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), | 19651 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), |
| 19613 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x4, 0x0, HDA_OUTPUT), | 19652 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x4, 0x0, HDA_OUTPUT), |
| 19614 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x16, 0x0, HDA_OUTPUT), | 19653 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x16, 0x0, HDA_OUTPUT), |
| 19615 | HDA_CODEC_VOLUME("Int Mic Boost", 0x12, 0, HDA_INPUT), | 19654 | HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x12, 0, HDA_INPUT), |
| 19616 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 19655 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT), |
| 19617 | HDA_CODEC_VOLUME("Line In Boost", 0x19, 0, HDA_INPUT), | 19656 | HDA_CODEC_VOLUME("Line In Boost Volume", 0x19, 0, HDA_INPUT), |
| 19618 | { } | 19657 | { } |
| 19619 | }; | 19658 | }; |
| 19620 | 19659 | ||
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index f03b2ff90496..4ab019d0924e 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
| @@ -389,6 +389,9 @@ static hda_nid_t stac92hd83xxx_dmic_nids[STAC92HD83XXX_NUM_DMICS + 1] = { | |||
| 389 | 0x11, 0x20, 0 | 389 | 0x11, 0x20, 0 |
| 390 | }; | 390 | }; |
| 391 | 391 | ||
| 392 | #define STAC92HD88XXX_NUM_DMICS STAC92HD83XXX_NUM_DMICS | ||
| 393 | #define stac92hd88xxx_dmic_nids stac92hd83xxx_dmic_nids | ||
| 394 | |||
| 392 | #define STAC92HD87B_NUM_DMICS 1 | 395 | #define STAC92HD87B_NUM_DMICS 1 |
| 393 | static hda_nid_t stac92hd87b_dmic_nids[STAC92HD87B_NUM_DMICS + 1] = { | 396 | static hda_nid_t stac92hd87b_dmic_nids[STAC92HD87B_NUM_DMICS + 1] = { |
| 394 | 0x11, 0 | 397 | 0x11, 0 |
| @@ -3591,7 +3594,7 @@ static int stac_check_auto_mic(struct hda_codec *codec) | |||
| 3591 | if (check_mic_pin(codec, spec->dmic_nids[i], | 3594 | if (check_mic_pin(codec, spec->dmic_nids[i], |
| 3592 | &fixed, &ext, &dock)) | 3595 | &fixed, &ext, &dock)) |
| 3593 | return 0; | 3596 | return 0; |
| 3594 | if (!fixed && !ext && !dock) | 3597 | if (!fixed || (!ext && !dock)) |
| 3595 | return 0; /* no input to switch */ | 3598 | return 0; /* no input to switch */ |
| 3596 | if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP)) | 3599 | if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP)) |
| 3597 | return 0; /* no unsol support */ | 3600 | return 0; /* no unsol support */ |
| @@ -5422,7 +5425,7 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) | |||
| 5422 | snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7ED, 0); | 5425 | snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7ED, 0); |
| 5423 | codec->no_trigger_sense = 1; | 5426 | codec->no_trigger_sense = 1; |
| 5424 | codec->spec = spec; | 5427 | codec->spec = spec; |
| 5425 | spec->linear_tone_beep = 1; | 5428 | spec->linear_tone_beep = 0; |
| 5426 | codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs; | 5429 | codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs; |
| 5427 | spec->digbeep_nid = 0x21; | 5430 | spec->digbeep_nid = 0x21; |
| 5428 | spec->dmic_nids = stac92hd83xxx_dmic_nids; | 5431 | spec->dmic_nids = stac92hd83xxx_dmic_nids; |
| @@ -5462,15 +5465,21 @@ again: | |||
| 5462 | spec->num_dmics = stac92xx_connected_ports(codec, | 5465 | spec->num_dmics = stac92xx_connected_ports(codec, |
| 5463 | stac92hd87b_dmic_nids, | 5466 | stac92hd87b_dmic_nids, |
| 5464 | STAC92HD87B_NUM_DMICS); | 5467 | STAC92HD87B_NUM_DMICS); |
| 5465 | /* Fall through */ | 5468 | spec->num_pins = ARRAY_SIZE(stac92hd88xxx_pin_nids); |
| 5469 | spec->pin_nids = stac92hd88xxx_pin_nids; | ||
| 5470 | spec->mono_nid = 0; | ||
| 5471 | spec->num_pwrs = 0; | ||
| 5472 | break; | ||
| 5466 | case 0x111d7666: | 5473 | case 0x111d7666: |
| 5467 | case 0x111d7667: | 5474 | case 0x111d7667: |
| 5468 | case 0x111d7668: | 5475 | case 0x111d7668: |
| 5469 | case 0x111d7669: | 5476 | case 0x111d7669: |
| 5477 | spec->num_dmics = stac92xx_connected_ports(codec, | ||
| 5478 | stac92hd88xxx_dmic_nids, | ||
| 5479 | STAC92HD88XXX_NUM_DMICS); | ||
| 5470 | spec->num_pins = ARRAY_SIZE(stac92hd88xxx_pin_nids); | 5480 | spec->num_pins = ARRAY_SIZE(stac92hd88xxx_pin_nids); |
| 5471 | spec->pin_nids = stac92hd88xxx_pin_nids; | 5481 | spec->pin_nids = stac92hd88xxx_pin_nids; |
| 5472 | spec->mono_nid = 0; | 5482 | spec->mono_nid = 0; |
| 5473 | spec->digbeep_nid = 0; | ||
| 5474 | spec->num_pwrs = 0; | 5483 | spec->num_pwrs = 0; |
| 5475 | break; | 5484 | break; |
| 5476 | case 0x111d7604: | 5485 | case 0x111d7604: |
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index d1c3f8defc48..7f4852a478a1 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
| @@ -263,8 +263,7 @@ static void vt1708_stop_hp_work(struct via_spec *spec) | |||
| 263 | return; | 263 | return; |
| 264 | snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, | 264 | snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, |
| 265 | !spec->vt1708_jack_detectect); | 265 | !spec->vt1708_jack_detectect); |
| 266 | cancel_delayed_work(&spec->vt1708_hp_work); | 266 | cancel_delayed_work_sync(&spec->vt1708_hp_work); |
| 267 | flush_scheduled_work(); | ||
| 268 | } | 267 | } |
| 269 | 268 | ||
| 270 | 269 | ||
diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c index 712c1710f9a2..7b62de089fee 100644 --- a/sound/pci/ice1712/delta.c +++ b/sound/pci/ice1712/delta.c | |||
| @@ -96,6 +96,11 @@ static unsigned char ap_cs8427_codec_select(struct snd_ice1712 *ice) | |||
| 96 | tmp |= ICE1712_DELTA_AP_CCLK | ICE1712_DELTA_AP_CS_CODEC; | 96 | tmp |= ICE1712_DELTA_AP_CCLK | ICE1712_DELTA_AP_CS_CODEC; |
| 97 | tmp &= ~ICE1712_DELTA_AP_CS_DIGITAL; | 97 | tmp &= ~ICE1712_DELTA_AP_CS_DIGITAL; |
| 98 | break; | 98 | break; |
| 99 | case ICE1712_SUBDEVICE_DELTA66E: | ||
| 100 | tmp |= ICE1712_DELTA_66E_CCLK | ICE1712_DELTA_66E_CS_CHIP_A | | ||
| 101 | ICE1712_DELTA_66E_CS_CHIP_B; | ||
| 102 | tmp &= ~ICE1712_DELTA_66E_CS_CS8427; | ||
| 103 | break; | ||
| 99 | case ICE1712_SUBDEVICE_VX442: | 104 | case ICE1712_SUBDEVICE_VX442: |
| 100 | tmp |= ICE1712_VX442_CCLK | ICE1712_VX442_CODEC_CHIP_A | ICE1712_VX442_CODEC_CHIP_B; | 105 | tmp |= ICE1712_VX442_CCLK | ICE1712_VX442_CODEC_CHIP_A | ICE1712_VX442_CODEC_CHIP_B; |
| 101 | tmp &= ~ICE1712_VX442_CS_DIGITAL; | 106 | tmp &= ~ICE1712_VX442_CS_DIGITAL; |
| @@ -119,6 +124,9 @@ static void ap_cs8427_codec_deassert(struct snd_ice1712 *ice, unsigned char tmp) | |||
| 119 | case ICE1712_SUBDEVICE_DELTA410: | 124 | case ICE1712_SUBDEVICE_DELTA410: |
| 120 | tmp |= ICE1712_DELTA_AP_CS_DIGITAL; | 125 | tmp |= ICE1712_DELTA_AP_CS_DIGITAL; |
| 121 | break; | 126 | break; |
| 127 | case ICE1712_SUBDEVICE_DELTA66E: | ||
| 128 | tmp |= ICE1712_DELTA_66E_CS_CS8427; | ||
| 129 | break; | ||
| 122 | case ICE1712_SUBDEVICE_VX442: | 130 | case ICE1712_SUBDEVICE_VX442: |
| 123 | tmp |= ICE1712_VX442_CS_DIGITAL; | 131 | tmp |= ICE1712_VX442_CS_DIGITAL; |
| 124 | break; | 132 | break; |
| @@ -276,6 +284,20 @@ static void delta1010lt_ak4524_lock(struct snd_akm4xxx *ak, int chip) | |||
| 276 | } | 284 | } |
| 277 | 285 | ||
| 278 | /* | 286 | /* |
| 287 | * AK4524 on Delta66 rev E to choose the chip address | ||
| 288 | */ | ||
| 289 | static void delta66e_ak4524_lock(struct snd_akm4xxx *ak, int chip) | ||
| 290 | { | ||
| 291 | struct snd_ak4xxx_private *priv = (void *)ak->private_value[0]; | ||
| 292 | struct snd_ice1712 *ice = ak->private_data[0]; | ||
| 293 | |||
| 294 | snd_ice1712_save_gpio_status(ice); | ||
| 295 | priv->cs_mask = | ||
| 296 | priv->cs_addr = chip == 0 ? ICE1712_DELTA_66E_CS_CHIP_A : | ||
| 297 | ICE1712_DELTA_66E_CS_CHIP_B; | ||
| 298 | } | ||
| 299 | |||
| 300 | /* | ||
| 279 | * AK4528 on VX442 to choose the chip mask | 301 | * AK4528 on VX442 to choose the chip mask |
| 280 | */ | 302 | */ |
| 281 | static void vx442_ak4524_lock(struct snd_akm4xxx *ak, int chip) | 303 | static void vx442_ak4524_lock(struct snd_akm4xxx *ak, int chip) |
| @@ -487,6 +509,29 @@ static struct snd_ak4xxx_private akm_delta1010lt_priv __devinitdata = { | |||
| 487 | .mask_flags = 0, | 509 | .mask_flags = 0, |
| 488 | }; | 510 | }; |
| 489 | 511 | ||
| 512 | static struct snd_akm4xxx akm_delta66e __devinitdata = { | ||
| 513 | .type = SND_AK4524, | ||
| 514 | .num_adcs = 4, | ||
| 515 | .num_dacs = 4, | ||
| 516 | .ops = { | ||
| 517 | .lock = delta66e_ak4524_lock, | ||
| 518 | .set_rate_val = delta_ak4524_set_rate_val | ||
| 519 | } | ||
| 520 | }; | ||
| 521 | |||
| 522 | static struct snd_ak4xxx_private akm_delta66e_priv __devinitdata = { | ||
| 523 | .caddr = 2, | ||
| 524 | .cif = 0, /* the default level of the CIF pin from AK4524 */ | ||
| 525 | .data_mask = ICE1712_DELTA_66E_DOUT, | ||
| 526 | .clk_mask = ICE1712_DELTA_66E_CCLK, | ||
| 527 | .cs_mask = 0, | ||
| 528 | .cs_addr = 0, /* set later */ | ||
| 529 | .cs_none = 0, | ||
| 530 | .add_flags = 0, | ||
| 531 | .mask_flags = 0, | ||
| 532 | }; | ||
| 533 | |||
| 534 | |||
| 490 | static struct snd_akm4xxx akm_delta44 __devinitdata = { | 535 | static struct snd_akm4xxx akm_delta44 __devinitdata = { |
| 491 | .type = SND_AK4524, | 536 | .type = SND_AK4524, |
| 492 | .num_adcs = 4, | 537 | .num_adcs = 4, |
| @@ -644,9 +689,11 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice) | |||
| 644 | err = snd_ice1712_akm4xxx_init(ak, &akm_delta44, &akm_delta44_priv, ice); | 689 | err = snd_ice1712_akm4xxx_init(ak, &akm_delta44, &akm_delta44_priv, ice); |
| 645 | break; | 690 | break; |
| 646 | case ICE1712_SUBDEVICE_VX442: | 691 | case ICE1712_SUBDEVICE_VX442: |
| 647 | case ICE1712_SUBDEVICE_DELTA66E: | ||
| 648 | err = snd_ice1712_akm4xxx_init(ak, &akm_vx442, &akm_vx442_priv, ice); | 692 | err = snd_ice1712_akm4xxx_init(ak, &akm_vx442, &akm_vx442_priv, ice); |
| 649 | break; | 693 | break; |
| 694 | case ICE1712_SUBDEVICE_DELTA66E: | ||
| 695 | err = snd_ice1712_akm4xxx_init(ak, &akm_delta66e, &akm_delta66e_priv, ice); | ||
| 696 | break; | ||
| 650 | default: | 697 | default: |
| 651 | snd_BUG(); | 698 | snd_BUG(); |
| 652 | return -EINVAL; | 699 | return -EINVAL; |
diff --git a/sound/pci/ice1712/delta.h b/sound/pci/ice1712/delta.h index 1a0ac6cd6501..11a9c3a76507 100644 --- a/sound/pci/ice1712/delta.h +++ b/sound/pci/ice1712/delta.h | |||
| @@ -144,6 +144,17 @@ extern struct snd_ice1712_card_info snd_ice1712_delta_cards[]; | |||
| 144 | #define ICE1712_DELTA_1010LT_CS_NONE 0x50 /* nothing */ | 144 | #define ICE1712_DELTA_1010LT_CS_NONE 0x50 /* nothing */ |
| 145 | #define ICE1712_DELTA_1010LT_WORDCLOCK 0x80 /* sample clock source: 0 = Word Clock Input, 1 = S/PDIF Input ??? */ | 145 | #define ICE1712_DELTA_1010LT_WORDCLOCK 0x80 /* sample clock source: 0 = Word Clock Input, 1 = S/PDIF Input ??? */ |
| 146 | 146 | ||
| 147 | /* M-Audio Delta 66 rev. E definitions. | ||
| 148 | * Newer revisions of Delta 66 have CS8427 over SPI for | ||
| 149 | * S/PDIF transceiver instead of CS8404/CS8414. */ | ||
| 150 | /* 0x01 = DFS */ | ||
| 151 | #define ICE1712_DELTA_66E_CCLK 0x02 /* SPI clock */ | ||
| 152 | #define ICE1712_DELTA_66E_DIN 0x04 /* data input */ | ||
| 153 | #define ICE1712_DELTA_66E_DOUT 0x08 /* data output */ | ||
| 154 | #define ICE1712_DELTA_66E_CS_CS8427 0x10 /* chip select, low = CS8427 */ | ||
| 155 | #define ICE1712_DELTA_66E_CS_CHIP_A 0x20 /* AK4524 #0 */ | ||
| 156 | #define ICE1712_DELTA_66E_CS_CHIP_B 0x40 /* AK4524 #1 */ | ||
| 157 | |||
| 147 | /* Digigram VX442 definitions */ | 158 | /* Digigram VX442 definitions */ |
| 148 | #define ICE1712_VX442_CCLK 0x02 /* SPI clock */ | 159 | #define ICE1712_VX442_CCLK 0x02 /* SPI clock */ |
| 149 | #define ICE1712_VX442_DIN 0x04 /* data input */ | 160 | #define ICE1712_VX442_DIN 0x04 /* data input */ |
diff --git a/sound/pci/oxygen/Makefile b/sound/pci/oxygen/Makefile index acd8f15f7bff..0f8726551fde 100644 --- a/sound/pci/oxygen/Makefile +++ b/sound/pci/oxygen/Makefile | |||
| @@ -1,10 +1,8 @@ | |||
| 1 | snd-oxygen-lib-objs := oxygen_io.o oxygen_lib.o oxygen_mixer.o oxygen_pcm.o | 1 | snd-oxygen-lib-objs := oxygen_io.o oxygen_lib.o oxygen_mixer.o oxygen_pcm.o |
| 2 | snd-hifier-objs := hifier.o | 2 | snd-oxygen-objs := oxygen.o xonar_dg.o |
| 3 | snd-oxygen-objs := oxygen.o | ||
| 4 | snd-virtuoso-objs := virtuoso.o xonar_lib.o \ | 3 | snd-virtuoso-objs := virtuoso.o xonar_lib.o \ |
| 5 | xonar_pcm179x.o xonar_cs43xx.o xonar_wm87x6.o xonar_hdmi.o | 4 | xonar_pcm179x.o xonar_cs43xx.o xonar_wm87x6.o xonar_hdmi.o |
| 6 | 5 | ||
| 7 | obj-$(CONFIG_SND_OXYGEN_LIB) += snd-oxygen-lib.o | 6 | obj-$(CONFIG_SND_OXYGEN_LIB) += snd-oxygen-lib.o |
| 8 | obj-$(CONFIG_SND_HIFIER) += snd-hifier.o | ||
| 9 | obj-$(CONFIG_SND_OXYGEN) += snd-oxygen.o | 7 | obj-$(CONFIG_SND_OXYGEN) += snd-oxygen.o |
| 10 | obj-$(CONFIG_SND_VIRTUOSO) += snd-virtuoso.o | 8 | obj-$(CONFIG_SND_VIRTUOSO) += snd-virtuoso.o |
diff --git a/sound/pci/oxygen/cs4245.h b/sound/pci/oxygen/cs4245.h new file mode 100644 index 000000000000..5e0197e07dd1 --- /dev/null +++ b/sound/pci/oxygen/cs4245.h | |||
| @@ -0,0 +1,107 @@ | |||
| 1 | #define CS4245_CHIP_ID 0x01 | ||
| 2 | #define CS4245_POWER_CTRL 0x02 | ||
| 3 | #define CS4245_DAC_CTRL_1 0x03 | ||
| 4 | #define CS4245_ADC_CTRL 0x04 | ||
| 5 | #define CS4245_MCLK_FREQ 0x05 | ||
| 6 | #define CS4245_SIGNAL_SEL 0x06 | ||
| 7 | #define CS4245_PGA_B_CTRL 0x07 | ||
| 8 | #define CS4245_PGA_A_CTRL 0x08 | ||
| 9 | #define CS4245_ANALOG_IN 0x09 | ||
| 10 | #define CS4245_DAC_A_CTRL 0x0a | ||
| 11 | #define CS4245_DAC_B_CTRL 0x0b | ||
| 12 | #define CS4245_DAC_CTRL_2 0x0c | ||
| 13 | #define CS4245_INT_STATUS 0x0d | ||
| 14 | #define CS4245_INT_MASK 0x0e | ||
| 15 | #define CS4245_INT_MODE_MSB 0x0f | ||
| 16 | #define CS4245_INT_MODE_LSB 0x10 | ||
| 17 | |||
| 18 | /* Chip ID */ | ||
| 19 | #define CS4245_CHIP_PART_MASK 0xf0 | ||
| 20 | #define CS4245_CHIP_REV_MASK 0x0f | ||
| 21 | |||
| 22 | /* Power Control */ | ||
| 23 | #define CS4245_FREEZE 0x80 | ||
| 24 | #define CS4245_PDN_MIC 0x08 | ||
| 25 | #define CS4245_PDN_ADC 0x04 | ||
| 26 | #define CS4245_PDN_DAC 0x02 | ||
| 27 | #define CS4245_PDN 0x01 | ||
| 28 | |||
| 29 | /* DAC Control */ | ||
| 30 | #define CS4245_DAC_FM_MASK 0xc0 | ||
| 31 | #define CS4245_DAC_FM_SINGLE 0x00 | ||
| 32 | #define CS4245_DAC_FM_DOUBLE 0x40 | ||
| 33 | #define CS4245_DAC_FM_QUAD 0x80 | ||
| 34 | #define CS4245_DAC_DIF_MASK 0x30 | ||
| 35 | #define CS4245_DAC_DIF_LJUST 0x00 | ||
| 36 | #define CS4245_DAC_DIF_I2S 0x10 | ||
| 37 | #define CS4245_DAC_DIF_RJUST_16 0x20 | ||
| 38 | #define CS4245_DAC_DIF_RJUST_24 0x30 | ||
| 39 | #define CS4245_RESERVED_1 0x08 | ||
| 40 | #define CS4245_MUTE_DAC 0x04 | ||
| 41 | #define CS4245_DEEMPH 0x02 | ||
| 42 | #define CS4245_DAC_MASTER 0x01 | ||
| 43 | |||
| 44 | /* ADC Control */ | ||
| 45 | #define CS4245_ADC_FM_MASK 0xc0 | ||
| 46 | #define CS4245_ADC_FM_SINGLE 0x00 | ||
| 47 | #define CS4245_ADC_FM_DOUBLE 0x40 | ||
| 48 | #define CS4245_ADC_FM_QUAD 0x80 | ||
| 49 | #define CS4245_ADC_DIF_MASK 0x10 | ||
| 50 | #define CS4245_ADC_DIF_LJUST 0x00 | ||
| 51 | #define CS4245_ADC_DIF_I2S 0x10 | ||
| 52 | #define CS4245_MUTE_ADC 0x04 | ||
| 53 | #define CS4245_HPF_FREEZE 0x02 | ||
| 54 | #define CS4245_ADC_MASTER 0x01 | ||
| 55 | |||
| 56 | /* MCLK Frequency */ | ||
| 57 | #define CS4245_MCLK1_MASK 0x70 | ||
| 58 | #define CS4245_MCLK1_SHIFT 4 | ||
| 59 | #define CS4245_MCLK2_MASK 0x07 | ||
| 60 | #define CS4245_MCLK2_SHIFT 0 | ||
| 61 | #define CS4245_MCLK_1 0 | ||
| 62 | #define CS4245_MCLK_1_5 1 | ||
| 63 | #define CS4245_MCLK_2 2 | ||
| 64 | #define CS4245_MCLK_3 3 | ||
| 65 | #define CS4245_MCLK_4 4 | ||
| 66 | |||
| 67 | /* Signal Selection */ | ||
| 68 | #define CS4245_A_OUT_SEL_MASK 0x60 | ||
| 69 | #define CS4245_A_OUT_SEL_HIZ 0x00 | ||
| 70 | #define CS4245_A_OUT_SEL_DAC 0x20 | ||
| 71 | #define CS4245_A_OUT_SEL_PGA 0x40 | ||
| 72 | #define CS4245_LOOP 0x02 | ||
| 73 | #define CS4245_ASYNCH 0x01 | ||
| 74 | |||
| 75 | /* Channel B/A PGA Control */ | ||
| 76 | #define CS4245_PGA_GAIN_MASK 0x3f | ||
| 77 | |||
| 78 | /* ADC Input Control */ | ||
| 79 | #define CS4245_PGA_SOFT 0x10 | ||
| 80 | #define CS4245_PGA_ZERO 0x08 | ||
| 81 | #define CS4245_SEL_MASK 0x07 | ||
| 82 | #define CS4245_SEL_MIC 0x00 | ||
| 83 | #define CS4245_SEL_INPUT_1 0x01 | ||
| 84 | #define CS4245_SEL_INPUT_2 0x02 | ||
| 85 | #define CS4245_SEL_INPUT_3 0x03 | ||
| 86 | #define CS4245_SEL_INPUT_4 0x04 | ||
| 87 | #define CS4245_SEL_INPUT_5 0x05 | ||
| 88 | #define CS4245_SEL_INPUT_6 0x06 | ||
| 89 | |||
| 90 | /* DAC Channel A/B Volume Control */ | ||
| 91 | #define CS4245_VOL_MASK 0xff | ||
| 92 | |||
| 93 | /* DAC Control 2 */ | ||
| 94 | #define CS4245_DAC_SOFT 0x80 | ||
| 95 | #define CS4245_DAC_ZERO 0x40 | ||
| 96 | #define CS4245_INVERT_DAC 0x20 | ||
| 97 | #define CS4245_INT_ACTIVE_HIGH 0x01 | ||
| 98 | |||
| 99 | /* Interrupt Status/Mask/Mode */ | ||
| 100 | #define CS4245_ADC_CLK_ERR 0x08 | ||
| 101 | #define CS4245_DAC_CLK_ERR 0x04 | ||
| 102 | #define CS4245_ADC_OVFL 0x02 | ||
| 103 | #define CS4245_ADC_UNDRFL 0x01 | ||
| 104 | |||
| 105 | |||
| 106 | #define CS4245_SPI_ADDRESS (0x9e << 16) | ||
| 107 | #define CS4245_SPI_WRITE (0 << 16) | ||
diff --git a/sound/pci/oxygen/hifier.c b/sound/pci/oxygen/hifier.c deleted file mode 100644 index 5a87d683691f..000000000000 --- a/sound/pci/oxygen/hifier.c +++ /dev/null | |||
| @@ -1,239 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * C-Media CMI8788 driver for the MediaTek/TempoTec HiFier Fantasia | ||
| 3 | * | ||
| 4 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> | ||
| 5 | * | ||
| 6 | * | ||
| 7 | * This driver is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License, version 2. | ||
| 9 | * | ||
| 10 | * This driver is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this driver; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 18 | */ | ||
| 19 | |||
| 20 | /* | ||
| 21 | * CMI8788: | ||
| 22 | * | ||
| 23 | * SPI 0 -> AK4396 | ||
| 24 | */ | ||
| 25 | |||
| 26 | #include <linux/delay.h> | ||
| 27 | #include <linux/pci.h> | ||
| 28 | #include <sound/control.h> | ||
| 29 | #include <sound/core.h> | ||
| 30 | #include <sound/initval.h> | ||
| 31 | #include <sound/pcm.h> | ||
| 32 | #include <sound/tlv.h> | ||
| 33 | #include "oxygen.h" | ||
| 34 | #include "ak4396.h" | ||
| 35 | |||
| 36 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); | ||
| 37 | MODULE_DESCRIPTION("TempoTec HiFier driver"); | ||
| 38 | MODULE_LICENSE("GPL v2"); | ||
| 39 | |||
| 40 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; | ||
| 41 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; | ||
| 42 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; | ||
| 43 | |||
| 44 | module_param_array(index, int, NULL, 0444); | ||
| 45 | MODULE_PARM_DESC(index, "card index"); | ||
| 46 | module_param_array(id, charp, NULL, 0444); | ||
| 47 | MODULE_PARM_DESC(id, "ID string"); | ||
| 48 | module_param_array(enable, bool, NULL, 0444); | ||
| 49 | MODULE_PARM_DESC(enable, "enable card"); | ||
| 50 | |||
| 51 | static DEFINE_PCI_DEVICE_TABLE(hifier_ids) = { | ||
| 52 | { OXYGEN_PCI_SUBID(0x14c3, 0x1710) }, | ||
| 53 | { OXYGEN_PCI_SUBID(0x14c3, 0x1711) }, | ||
| 54 | { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, | ||
| 55 | { } | ||
| 56 | }; | ||
| 57 | MODULE_DEVICE_TABLE(pci, hifier_ids); | ||
| 58 | |||
| 59 | struct hifier_data { | ||
| 60 | u8 ak4396_regs[5]; | ||
| 61 | }; | ||
| 62 | |||
| 63 | static void ak4396_write(struct oxygen *chip, u8 reg, u8 value) | ||
| 64 | { | ||
| 65 | struct hifier_data *data = chip->model_data; | ||
| 66 | |||
| 67 | oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | | ||
| 68 | OXYGEN_SPI_DATA_LENGTH_2 | | ||
| 69 | OXYGEN_SPI_CLOCK_160 | | ||
| 70 | (0 << OXYGEN_SPI_CODEC_SHIFT) | | ||
| 71 | OXYGEN_SPI_CEN_LATCH_CLOCK_HI, | ||
| 72 | AK4396_WRITE | (reg << 8) | value); | ||
| 73 | data->ak4396_regs[reg] = value; | ||
| 74 | } | ||
| 75 | |||
| 76 | static void ak4396_write_cached(struct oxygen *chip, u8 reg, u8 value) | ||
| 77 | { | ||
| 78 | struct hifier_data *data = chip->model_data; | ||
| 79 | |||
| 80 | if (value != data->ak4396_regs[reg]) | ||
| 81 | ak4396_write(chip, reg, value); | ||
| 82 | } | ||
| 83 | |||
| 84 | static void hifier_registers_init(struct oxygen *chip) | ||
| 85 | { | ||
| 86 | struct hifier_data *data = chip->model_data; | ||
| 87 | |||
| 88 | ak4396_write(chip, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN); | ||
| 89 | ak4396_write(chip, AK4396_CONTROL_2, | ||
| 90 | data->ak4396_regs[AK4396_CONTROL_2]); | ||
| 91 | ak4396_write(chip, AK4396_CONTROL_3, AK4396_PCM); | ||
| 92 | ak4396_write(chip, AK4396_LCH_ATT, chip->dac_volume[0]); | ||
| 93 | ak4396_write(chip, AK4396_RCH_ATT, chip->dac_volume[1]); | ||
| 94 | } | ||
| 95 | |||
| 96 | static void hifier_init(struct oxygen *chip) | ||
| 97 | { | ||
| 98 | struct hifier_data *data = chip->model_data; | ||
| 99 | |||
| 100 | data->ak4396_regs[AK4396_CONTROL_2] = | ||
| 101 | AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL; | ||
| 102 | hifier_registers_init(chip); | ||
| 103 | |||
| 104 | snd_component_add(chip->card, "AK4396"); | ||
| 105 | snd_component_add(chip->card, "CS5340"); | ||
| 106 | } | ||
| 107 | |||
| 108 | static void hifier_cleanup(struct oxygen *chip) | ||
| 109 | { | ||
| 110 | } | ||
| 111 | |||
| 112 | static void hifier_resume(struct oxygen *chip) | ||
| 113 | { | ||
| 114 | hifier_registers_init(chip); | ||
| 115 | } | ||
| 116 | |||
| 117 | static void set_ak4396_params(struct oxygen *chip, | ||
| 118 | struct snd_pcm_hw_params *params) | ||
| 119 | { | ||
| 120 | struct hifier_data *data = chip->model_data; | ||
| 121 | u8 value; | ||
| 122 | |||
| 123 | value = data->ak4396_regs[AK4396_CONTROL_2] & ~AK4396_DFS_MASK; | ||
| 124 | if (params_rate(params) <= 54000) | ||
| 125 | value |= AK4396_DFS_NORMAL; | ||
| 126 | else if (params_rate(params) <= 108000) | ||
| 127 | value |= AK4396_DFS_DOUBLE; | ||
| 128 | else | ||
| 129 | value |= AK4396_DFS_QUAD; | ||
| 130 | |||
| 131 | msleep(1); /* wait for the new MCLK to become stable */ | ||
| 132 | |||
| 133 | if (value != data->ak4396_regs[AK4396_CONTROL_2]) { | ||
| 134 | ak4396_write(chip, AK4396_CONTROL_1, | ||
| 135 | AK4396_DIF_24_MSB); | ||
| 136 | ak4396_write(chip, AK4396_CONTROL_2, value); | ||
| 137 | ak4396_write(chip, AK4396_CONTROL_1, | ||
| 138 | AK4396_DIF_24_MSB | AK4396_RSTN); | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | static void update_ak4396_volume(struct oxygen *chip) | ||
| 143 | { | ||
| 144 | ak4396_write_cached(chip, AK4396_LCH_ATT, chip->dac_volume[0]); | ||
| 145 | ak4396_write_cached(chip, AK4396_RCH_ATT, chip->dac_volume[1]); | ||
| 146 | } | ||
| 147 | |||
| 148 | static void update_ak4396_mute(struct oxygen *chip) | ||
| 149 | { | ||
| 150 | struct hifier_data *data = chip->model_data; | ||
| 151 | u8 value; | ||
| 152 | |||
| 153 | value = data->ak4396_regs[AK4396_CONTROL_2] & ~AK4396_SMUTE; | ||
| 154 | if (chip->dac_mute) | ||
| 155 | value |= AK4396_SMUTE; | ||
| 156 | ak4396_write_cached(chip, AK4396_CONTROL_2, value); | ||
| 157 | } | ||
| 158 | |||
| 159 | static void set_cs5340_params(struct oxygen *chip, | ||
| 160 | struct snd_pcm_hw_params *params) | ||
| 161 | { | ||
| 162 | } | ||
| 163 | |||
| 164 | static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); | ||
| 165 | |||
| 166 | static const struct oxygen_model model_hifier = { | ||
| 167 | .shortname = "C-Media CMI8787", | ||
| 168 | .longname = "C-Media Oxygen HD Audio", | ||
| 169 | .chip = "CMI8788", | ||
| 170 | .init = hifier_init, | ||
| 171 | .cleanup = hifier_cleanup, | ||
| 172 | .resume = hifier_resume, | ||
| 173 | .get_i2s_mclk = oxygen_default_i2s_mclk, | ||
| 174 | .set_dac_params = set_ak4396_params, | ||
| 175 | .set_adc_params = set_cs5340_params, | ||
| 176 | .update_dac_volume = update_ak4396_volume, | ||
| 177 | .update_dac_mute = update_ak4396_mute, | ||
| 178 | .dac_tlv = ak4396_db_scale, | ||
| 179 | .model_data_size = sizeof(struct hifier_data), | ||
| 180 | .device_config = PLAYBACK_0_TO_I2S | | ||
| 181 | PLAYBACK_1_TO_SPDIF | | ||
| 182 | CAPTURE_0_FROM_I2S_1, | ||
| 183 | .dac_channels = 2, | ||
| 184 | .dac_volume_min = 0, | ||
| 185 | .dac_volume_max = 255, | ||
| 186 | .function_flags = OXYGEN_FUNCTION_SPI, | ||
| 187 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | ||
| 188 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | ||
| 189 | }; | ||
| 190 | |||
| 191 | static int __devinit get_hifier_model(struct oxygen *chip, | ||
| 192 | const struct pci_device_id *id) | ||
| 193 | { | ||
| 194 | chip->model = model_hifier; | ||
| 195 | return 0; | ||
| 196 | } | ||
| 197 | |||
| 198 | static int __devinit hifier_probe(struct pci_dev *pci, | ||
| 199 | const struct pci_device_id *pci_id) | ||
| 200 | { | ||
| 201 | static int dev; | ||
| 202 | int err; | ||
| 203 | |||
| 204 | if (dev >= SNDRV_CARDS) | ||
| 205 | return -ENODEV; | ||
| 206 | if (!enable[dev]) { | ||
| 207 | ++dev; | ||
| 208 | return -ENOENT; | ||
| 209 | } | ||
| 210 | err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE, | ||
| 211 | hifier_ids, get_hifier_model); | ||
| 212 | if (err >= 0) | ||
| 213 | ++dev; | ||
| 214 | return err; | ||
| 215 | } | ||
| 216 | |||
| 217 | static struct pci_driver hifier_driver = { | ||
| 218 | .name = "CMI8787HiFier", | ||
| 219 | .id_table = hifier_ids, | ||
| 220 | .probe = hifier_probe, | ||
| 221 | .remove = __devexit_p(oxygen_pci_remove), | ||
| 222 | #ifdef CONFIG_PM | ||
| 223 | .suspend = oxygen_pci_suspend, | ||
| 224 | .resume = oxygen_pci_resume, | ||
| 225 | #endif | ||
| 226 | }; | ||
| 227 | |||
| 228 | static int __init alsa_card_hifier_init(void) | ||
| 229 | { | ||
| 230 | return pci_register_driver(&hifier_driver); | ||
| 231 | } | ||
| 232 | |||
| 233 | static void __exit alsa_card_hifier_exit(void) | ||
| 234 | { | ||
| 235 | pci_unregister_driver(&hifier_driver); | ||
| 236 | } | ||
| 237 | |||
| 238 | module_init(alsa_card_hifier_init) | ||
| 239 | module_exit(alsa_card_hifier_exit) | ||
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 | ||
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h index 7d5222caa0a9..c2ae63d17cd2 100644 --- a/sound/pci/oxygen/oxygen.h +++ b/sound/pci/oxygen/oxygen.h | |||
| @@ -16,6 +16,10 @@ | |||
| 16 | #define PCM_AC97 5 | 16 | #define PCM_AC97 5 |
| 17 | #define PCM_COUNT 6 | 17 | #define PCM_COUNT 6 |
| 18 | 18 | ||
| 19 | #define OXYGEN_MCLKS(f_single, f_double, f_quad) ((MCLK_##f_single << 0) | \ | ||
| 20 | (MCLK_##f_double << 2) | \ | ||
| 21 | (MCLK_##f_quad << 4)) | ||
| 22 | |||
| 19 | #define OXYGEN_IO_SIZE 0x100 | 23 | #define OXYGEN_IO_SIZE 0x100 |
| 20 | 24 | ||
| 21 | #define OXYGEN_EEPROM_ID 0x434d /* "CM" */ | 25 | #define OXYGEN_EEPROM_ID 0x434d /* "CM" */ |
| @@ -35,6 +39,7 @@ | |||
| 35 | #define MIDI_OUTPUT 0x0800 | 39 | #define MIDI_OUTPUT 0x0800 |
| 36 | #define MIDI_INPUT 0x1000 | 40 | #define MIDI_INPUT 0x1000 |
| 37 | #define AC97_CD_INPUT 0x2000 | 41 | #define AC97_CD_INPUT 0x2000 |
| 42 | #define AC97_FMIC_SWITCH 0x4000 | ||
| 38 | 43 | ||
| 39 | enum { | 44 | enum { |
| 40 | CONTROL_SPDIF_PCM, | 45 | CONTROL_SPDIF_PCM, |
| @@ -65,6 +70,7 @@ struct snd_pcm_hardware; | |||
| 65 | struct snd_pcm_hw_params; | 70 | struct snd_pcm_hw_params; |
| 66 | struct snd_kcontrol_new; | 71 | struct snd_kcontrol_new; |
| 67 | struct snd_rawmidi; | 72 | struct snd_rawmidi; |
| 73 | struct snd_info_buffer; | ||
| 68 | struct oxygen; | 74 | struct oxygen; |
| 69 | 75 | ||
| 70 | struct oxygen_model { | 76 | struct oxygen_model { |
| @@ -79,8 +85,6 @@ struct oxygen_model { | |||
| 79 | void (*resume)(struct oxygen *chip); | 85 | void (*resume)(struct oxygen *chip); |
| 80 | void (*pcm_hardware_filter)(unsigned int channel, | 86 | void (*pcm_hardware_filter)(unsigned int channel, |
| 81 | struct snd_pcm_hardware *hardware); | 87 | struct snd_pcm_hardware *hardware); |
| 82 | unsigned int (*get_i2s_mclk)(struct oxygen *chip, unsigned int channel, | ||
| 83 | struct snd_pcm_hw_params *hw_params); | ||
| 84 | void (*set_dac_params)(struct oxygen *chip, | 88 | void (*set_dac_params)(struct oxygen *chip, |
| 85 | struct snd_pcm_hw_params *params); | 89 | struct snd_pcm_hw_params *params); |
| 86 | void (*set_adc_params)(struct oxygen *chip, | 90 | void (*set_adc_params)(struct oxygen *chip, |
| @@ -92,15 +96,19 @@ struct oxygen_model { | |||
| 92 | void (*uart_input)(struct oxygen *chip); | 96 | void (*uart_input)(struct oxygen *chip); |
| 93 | void (*ac97_switch)(struct oxygen *chip, | 97 | void (*ac97_switch)(struct oxygen *chip, |
| 94 | unsigned int reg, unsigned int mute); | 98 | unsigned int reg, unsigned int mute); |
| 99 | void (*dump_registers)(struct oxygen *chip, | ||
| 100 | struct snd_info_buffer *buffer); | ||
| 95 | const unsigned int *dac_tlv; | 101 | const unsigned int *dac_tlv; |
| 96 | unsigned long private_data; | ||
| 97 | size_t model_data_size; | 102 | size_t model_data_size; |
| 98 | unsigned int device_config; | 103 | unsigned int device_config; |
| 99 | u8 dac_channels; | 104 | u8 dac_channels_pcm; |
| 105 | u8 dac_channels_mixer; | ||
| 100 | u8 dac_volume_min; | 106 | u8 dac_volume_min; |
| 101 | u8 dac_volume_max; | 107 | u8 dac_volume_max; |
| 102 | u8 misc_flags; | 108 | u8 misc_flags; |
| 103 | u8 function_flags; | 109 | u8 function_flags; |
| 110 | u8 dac_mclks; | ||
| 111 | u8 adc_mclks; | ||
| 104 | u16 dac_i2s_format; | 112 | u16 dac_i2s_format; |
| 105 | u16 adc_i2s_format; | 113 | u16 adc_i2s_format; |
| 106 | }; | 114 | }; |
| @@ -121,7 +129,6 @@ struct oxygen { | |||
| 121 | u8 pcm_running; | 129 | u8 pcm_running; |
| 122 | u8 dac_routing; | 130 | u8 dac_routing; |
| 123 | u8 spdif_playback_enable; | 131 | u8 spdif_playback_enable; |
| 124 | u8 revision; | ||
| 125 | u8 has_ac97_0; | 132 | u8 has_ac97_0; |
| 126 | u8 has_ac97_1; | 133 | u8 has_ac97_1; |
| 127 | u32 spdif_bits; | 134 | u32 spdif_bits; |
| @@ -167,8 +174,6 @@ void oxygen_update_spdif_source(struct oxygen *chip); | |||
| 167 | /* oxygen_pcm.c */ | 174 | /* oxygen_pcm.c */ |
| 168 | 175 | ||
| 169 | int oxygen_pcm_init(struct oxygen *chip); | 176 | int oxygen_pcm_init(struct oxygen *chip); |
| 170 | unsigned int oxygen_default_i2s_mclk(struct oxygen *chip, unsigned int channel, | ||
| 171 | struct snd_pcm_hw_params *hw_params); | ||
| 172 | 177 | ||
| 173 | /* oxygen_io.c */ | 178 | /* oxygen_io.c */ |
| 174 | 179 | ||
diff --git a/sound/pci/oxygen/oxygen_io.c b/sound/pci/oxygen/oxygen_io.c index 09b2b2a36df5..f5164b1e1c80 100644 --- a/sound/pci/oxygen/oxygen_io.c +++ b/sound/pci/oxygen/oxygen_io.c | |||
| @@ -197,11 +197,11 @@ void oxygen_write_spi(struct oxygen *chip, u8 control, unsigned int data) | |||
| 197 | { | 197 | { |
| 198 | unsigned int count; | 198 | unsigned int count; |
| 199 | 199 | ||
| 200 | /* should not need more than 7.68 us (24 * 320 ns) */ | 200 | /* should not need more than 30.72 us (24 * 1.28 us) */ |
| 201 | count = 10; | 201 | count = 10; |
| 202 | while ((oxygen_read8(chip, OXYGEN_SPI_CONTROL) & OXYGEN_SPI_BUSY) | 202 | while ((oxygen_read8(chip, OXYGEN_SPI_CONTROL) & OXYGEN_SPI_BUSY) |
| 203 | && count > 0) { | 203 | && count > 0) { |
| 204 | udelay(1); | 204 | udelay(4); |
| 205 | --count; | 205 | --count; |
| 206 | } | 206 | } |
| 207 | 207 | ||
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index e5ebe56fb0c5..70b739816fcc 100644 --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c | |||
| @@ -202,7 +202,13 @@ static void oxygen_proc_read(struct snd_info_entry *entry, | |||
| 202 | struct oxygen *chip = entry->private_data; | 202 | struct oxygen *chip = entry->private_data; |
| 203 | int i, j; | 203 | int i, j; |
| 204 | 204 | ||
| 205 | snd_iprintf(buffer, "CMI8788\n\n"); | 205 | switch (oxygen_read8(chip, OXYGEN_REVISION) & OXYGEN_PACKAGE_ID_MASK) { |
| 206 | case OXYGEN_PACKAGE_ID_8786: i = '6'; break; | ||
| 207 | case OXYGEN_PACKAGE_ID_8787: i = '7'; break; | ||
| 208 | case OXYGEN_PACKAGE_ID_8788: i = '8'; break; | ||
| 209 | default: i = '?'; break; | ||
| 210 | } | ||
| 211 | snd_iprintf(buffer, "CMI878%c:\n", i); | ||
| 206 | for (i = 0; i < OXYGEN_IO_SIZE; i += 0x10) { | 212 | for (i = 0; i < OXYGEN_IO_SIZE; i += 0x10) { |
| 207 | snd_iprintf(buffer, "%02x:", i); | 213 | snd_iprintf(buffer, "%02x:", i); |
| 208 | for (j = 0; j < 0x10; ++j) | 214 | for (j = 0; j < 0x10; ++j) |
| @@ -212,7 +218,7 @@ static void oxygen_proc_read(struct snd_info_entry *entry, | |||
| 212 | if (mutex_lock_interruptible(&chip->mutex) < 0) | 218 | if (mutex_lock_interruptible(&chip->mutex) < 0) |
| 213 | return; | 219 | return; |
| 214 | if (chip->has_ac97_0) { | 220 | if (chip->has_ac97_0) { |
| 215 | snd_iprintf(buffer, "\nAC97\n"); | 221 | snd_iprintf(buffer, "\nAC97:\n"); |
| 216 | for (i = 0; i < 0x80; i += 0x10) { | 222 | for (i = 0; i < 0x80; i += 0x10) { |
| 217 | snd_iprintf(buffer, "%02x:", i); | 223 | snd_iprintf(buffer, "%02x:", i); |
| 218 | for (j = 0; j < 0x10; j += 2) | 224 | for (j = 0; j < 0x10; j += 2) |
| @@ -222,7 +228,7 @@ static void oxygen_proc_read(struct snd_info_entry *entry, | |||
| 222 | } | 228 | } |
| 223 | } | 229 | } |
| 224 | if (chip->has_ac97_1) { | 230 | if (chip->has_ac97_1) { |
| 225 | snd_iprintf(buffer, "\nAC97 2\n"); | 231 | snd_iprintf(buffer, "\nAC97 2:\n"); |
| 226 | for (i = 0; i < 0x80; i += 0x10) { | 232 | for (i = 0; i < 0x80; i += 0x10) { |
| 227 | snd_iprintf(buffer, "%02x:", i); | 233 | snd_iprintf(buffer, "%02x:", i); |
| 228 | for (j = 0; j < 0x10; j += 2) | 234 | for (j = 0; j < 0x10; j += 2) |
| @@ -232,13 +238,15 @@ static void oxygen_proc_read(struct snd_info_entry *entry, | |||
| 232 | } | 238 | } |
| 233 | } | 239 | } |
| 234 | mutex_unlock(&chip->mutex); | 240 | mutex_unlock(&chip->mutex); |
| 241 | if (chip->model.dump_registers) | ||
| 242 | chip->model.dump_registers(chip, buffer); | ||
| 235 | } | 243 | } |
| 236 | 244 | ||
| 237 | static void oxygen_proc_init(struct oxygen *chip) | 245 | static void oxygen_proc_init(struct oxygen *chip) |
| 238 | { | 246 | { |
| 239 | struct snd_info_entry *entry; | 247 | struct snd_info_entry *entry; |
| 240 | 248 | ||
| 241 | if (!snd_card_proc_new(chip->card, "cmi8788", &entry)) | 249 | if (!snd_card_proc_new(chip->card, "oxygen", &entry)) |
| 242 | snd_info_set_text_ops(entry, chip, oxygen_proc_read); | 250 | snd_info_set_text_ops(entry, chip, oxygen_proc_read); |
| 243 | } | 251 | } |
| 244 | #else | 252 | #else |
| @@ -262,7 +270,7 @@ oxygen_search_pci_id(struct oxygen *chip, const struct pci_device_id ids[]) | |||
| 262 | */ | 270 | */ |
| 263 | subdevice = oxygen_read_eeprom(chip, 2); | 271 | subdevice = oxygen_read_eeprom(chip, 2); |
| 264 | /* use default ID if EEPROM is missing */ | 272 | /* use default ID if EEPROM is missing */ |
| 265 | if (subdevice == 0xffff) | 273 | if (subdevice == 0xffff && oxygen_read_eeprom(chip, 1) == 0xffff) |
| 266 | subdevice = 0x8788; | 274 | subdevice = 0x8788; |
| 267 | /* | 275 | /* |
| 268 | * We use only the subsystem device ID for searching because it is | 276 | * We use only the subsystem device ID for searching because it is |
| @@ -364,12 +372,7 @@ static void oxygen_init(struct oxygen *chip) | |||
| 364 | (IEC958_AES1_CON_PCM_CODER << OXYGEN_SPDIF_CATEGORY_SHIFT); | 372 | (IEC958_AES1_CON_PCM_CODER << OXYGEN_SPDIF_CATEGORY_SHIFT); |
| 365 | chip->spdif_pcm_bits = chip->spdif_bits; | 373 | chip->spdif_pcm_bits = chip->spdif_bits; |
| 366 | 374 | ||
| 367 | if (oxygen_read8(chip, OXYGEN_REVISION) & OXYGEN_REVISION_2) | 375 | if (!(oxygen_read8(chip, OXYGEN_REVISION) & OXYGEN_REVISION_2)) |
| 368 | chip->revision = 2; | ||
| 369 | else | ||
| 370 | chip->revision = 1; | ||
| 371 | |||
| 372 | if (chip->revision == 1) | ||
| 373 | oxygen_set_bits8(chip, OXYGEN_MISC, | 376 | oxygen_set_bits8(chip, OXYGEN_MISC, |
| 374 | OXYGEN_MISC_PCI_MEM_W_1_CLOCK); | 377 | OXYGEN_MISC_PCI_MEM_W_1_CLOCK); |
| 375 | 378 | ||
| @@ -406,28 +409,40 @@ static void oxygen_init(struct oxygen *chip) | |||
| 406 | (OXYGEN_FORMAT_16 << OXYGEN_MULTICH_FORMAT_SHIFT)); | 409 | (OXYGEN_FORMAT_16 << OXYGEN_MULTICH_FORMAT_SHIFT)); |
| 407 | oxygen_write8(chip, OXYGEN_REC_CHANNELS, OXYGEN_REC_CHANNELS_2_2_2); | 410 | oxygen_write8(chip, OXYGEN_REC_CHANNELS, OXYGEN_REC_CHANNELS_2_2_2); |
| 408 | oxygen_write16(chip, OXYGEN_I2S_MULTICH_FORMAT, | 411 | oxygen_write16(chip, OXYGEN_I2S_MULTICH_FORMAT, |
| 409 | OXYGEN_RATE_48000 | chip->model.dac_i2s_format | | 412 | OXYGEN_RATE_48000 | |
| 410 | OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 | | 413 | chip->model.dac_i2s_format | |
| 411 | OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); | 414 | OXYGEN_I2S_MCLK(chip->model.dac_mclks) | |
| 415 | OXYGEN_I2S_BITS_16 | | ||
| 416 | OXYGEN_I2S_MASTER | | ||
| 417 | OXYGEN_I2S_BCLK_64); | ||
| 412 | if (chip->model.device_config & CAPTURE_0_FROM_I2S_1) | 418 | if (chip->model.device_config & CAPTURE_0_FROM_I2S_1) |
| 413 | oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, | 419 | oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, |
| 414 | OXYGEN_RATE_48000 | chip->model.adc_i2s_format | | 420 | OXYGEN_RATE_48000 | |
| 415 | OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 | | 421 | chip->model.adc_i2s_format | |
| 416 | OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); | 422 | OXYGEN_I2S_MCLK(chip->model.adc_mclks) | |
| 423 | OXYGEN_I2S_BITS_16 | | ||
| 424 | OXYGEN_I2S_MASTER | | ||
| 425 | OXYGEN_I2S_BCLK_64); | ||
| 417 | else | 426 | else |
| 418 | oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, | 427 | oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, |
| 419 | OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK); | 428 | OXYGEN_I2S_MASTER | |
| 429 | OXYGEN_I2S_MUTE_MCLK); | ||
| 420 | if (chip->model.device_config & (CAPTURE_0_FROM_I2S_2 | | 430 | if (chip->model.device_config & (CAPTURE_0_FROM_I2S_2 | |
| 421 | CAPTURE_2_FROM_I2S_2)) | 431 | CAPTURE_2_FROM_I2S_2)) |
| 422 | oxygen_write16(chip, OXYGEN_I2S_B_FORMAT, | 432 | oxygen_write16(chip, OXYGEN_I2S_B_FORMAT, |
| 423 | OXYGEN_RATE_48000 | chip->model.adc_i2s_format | | 433 | OXYGEN_RATE_48000 | |
| 424 | OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 | | 434 | chip->model.adc_i2s_format | |
| 425 | OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); | 435 | OXYGEN_I2S_MCLK(chip->model.adc_mclks) | |
| 436 | OXYGEN_I2S_BITS_16 | | ||
| 437 | OXYGEN_I2S_MASTER | | ||
| 438 | OXYGEN_I2S_BCLK_64); | ||
| 426 | else | 439 | else |
| 427 | oxygen_write16(chip, OXYGEN_I2S_B_FORMAT, | 440 | oxygen_write16(chip, OXYGEN_I2S_B_FORMAT, |
| 428 | OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK); | 441 | OXYGEN_I2S_MASTER | |
| 442 | OXYGEN_I2S_MUTE_MCLK); | ||
| 429 | oxygen_write16(chip, OXYGEN_I2S_C_FORMAT, | 443 | oxygen_write16(chip, OXYGEN_I2S_C_FORMAT, |
| 430 | OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK); | 444 | OXYGEN_I2S_MASTER | |
| 445 | OXYGEN_I2S_MUTE_MCLK); | ||
| 431 | oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL, | 446 | oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL, |
| 432 | OXYGEN_SPDIF_OUT_ENABLE | | 447 | OXYGEN_SPDIF_OUT_ENABLE | |
| 433 | OXYGEN_SPDIF_LOOPBACK); | 448 | OXYGEN_SPDIF_LOOPBACK); |
| @@ -557,7 +572,8 @@ static void oxygen_card_free(struct snd_card *card) | |||
| 557 | oxygen_shutdown(chip); | 572 | oxygen_shutdown(chip); |
| 558 | if (chip->irq >= 0) | 573 | if (chip->irq >= 0) |
| 559 | free_irq(chip->irq, chip); | 574 | free_irq(chip->irq, chip); |
| 560 | flush_scheduled_work(); | 575 | flush_work_sync(&chip->spdif_input_bits_work); |
| 576 | flush_work_sync(&chip->gpio_work); | ||
| 561 | chip->model.cleanup(chip); | 577 | chip->model.cleanup(chip); |
| 562 | kfree(chip->model_data); | 578 | kfree(chip->model_data); |
| 563 | mutex_destroy(&chip->mutex); | 579 | mutex_destroy(&chip->mutex); |
| @@ -648,8 +664,8 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | |||
| 648 | 664 | ||
| 649 | strcpy(card->driver, chip->model.chip); | 665 | strcpy(card->driver, chip->model.chip); |
| 650 | strcpy(card->shortname, chip->model.shortname); | 666 | strcpy(card->shortname, chip->model.shortname); |
| 651 | sprintf(card->longname, "%s (rev %u) at %#lx, irq %i", | 667 | sprintf(card->longname, "%s at %#lx, irq %i", |
| 652 | chip->model.longname, chip->revision, chip->addr, chip->irq); | 668 | chip->model.longname, chip->addr, chip->irq); |
| 653 | strcpy(card->mixername, chip->model.chip); | 669 | strcpy(card->mixername, chip->model.chip); |
| 654 | snd_component_add(card, chip->model.chip); | 670 | snd_component_add(card, chip->model.chip); |
| 655 | 671 | ||
| @@ -733,7 +749,8 @@ int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state) | |||
| 733 | spin_unlock_irq(&chip->reg_lock); | 749 | spin_unlock_irq(&chip->reg_lock); |
| 734 | 750 | ||
| 735 | synchronize_irq(chip->irq); | 751 | synchronize_irq(chip->irq); |
| 736 | flush_scheduled_work(); | 752 | flush_work_sync(&chip->spdif_input_bits_work); |
| 753 | flush_work_sync(&chip->gpio_work); | ||
| 737 | chip->interrupt_mask = saved_interrupt_mask; | 754 | chip->interrupt_mask = saved_interrupt_mask; |
| 738 | 755 | ||
| 739 | pci_disable_device(pci); | 756 | pci_disable_device(pci); |
diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c index 2849b36f5f7e..9bff14d5895d 100644 --- a/sound/pci/oxygen/oxygen_mixer.c +++ b/sound/pci/oxygen/oxygen_mixer.c | |||
| @@ -31,7 +31,7 @@ static int dac_volume_info(struct snd_kcontrol *ctl, | |||
| 31 | struct oxygen *chip = ctl->private_data; | 31 | struct oxygen *chip = ctl->private_data; |
| 32 | 32 | ||
| 33 | info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 33 | info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
| 34 | info->count = chip->model.dac_channels; | 34 | info->count = chip->model.dac_channels_mixer; |
| 35 | info->value.integer.min = chip->model.dac_volume_min; | 35 | info->value.integer.min = chip->model.dac_volume_min; |
| 36 | info->value.integer.max = chip->model.dac_volume_max; | 36 | info->value.integer.max = chip->model.dac_volume_max; |
| 37 | return 0; | 37 | return 0; |
| @@ -44,7 +44,7 @@ static int dac_volume_get(struct snd_kcontrol *ctl, | |||
| 44 | unsigned int i; | 44 | unsigned int i; |
| 45 | 45 | ||
| 46 | mutex_lock(&chip->mutex); | 46 | mutex_lock(&chip->mutex); |
| 47 | for (i = 0; i < chip->model.dac_channels; ++i) | 47 | for (i = 0; i < chip->model.dac_channels_mixer; ++i) |
| 48 | value->value.integer.value[i] = chip->dac_volume[i]; | 48 | value->value.integer.value[i] = chip->dac_volume[i]; |
| 49 | mutex_unlock(&chip->mutex); | 49 | mutex_unlock(&chip->mutex); |
| 50 | return 0; | 50 | return 0; |
| @@ -59,7 +59,7 @@ static int dac_volume_put(struct snd_kcontrol *ctl, | |||
| 59 | 59 | ||
| 60 | changed = 0; | 60 | changed = 0; |
| 61 | mutex_lock(&chip->mutex); | 61 | mutex_lock(&chip->mutex); |
| 62 | for (i = 0; i < chip->model.dac_channels; ++i) | 62 | for (i = 0; i < chip->model.dac_channels_mixer; ++i) |
| 63 | if (value->value.integer.value[i] != chip->dac_volume[i]) { | 63 | if (value->value.integer.value[i] != chip->dac_volume[i]) { |
| 64 | chip->dac_volume[i] = value->value.integer.value[i]; | 64 | chip->dac_volume[i] = value->value.integer.value[i]; |
| 65 | changed = 1; | 65 | changed = 1; |
| @@ -97,6 +97,16 @@ static int dac_mute_put(struct snd_kcontrol *ctl, | |||
| 97 | return changed; | 97 | return changed; |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | static unsigned int upmix_item_count(struct oxygen *chip) | ||
| 101 | { | ||
| 102 | if (chip->model.dac_channels_pcm < 8) | ||
| 103 | return 2; | ||
| 104 | else if (chip->model.update_center_lfe_mix) | ||
| 105 | return 5; | ||
| 106 | else | ||
| 107 | return 3; | ||
| 108 | } | ||
| 109 | |||
| 100 | static int upmix_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) | 110 | static int upmix_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) |
| 101 | { | 111 | { |
| 102 | static const char *const names[5] = { | 112 | static const char *const names[5] = { |
| @@ -107,15 +117,9 @@ static int upmix_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) | |||
| 107 | "Front+Surround+Center/LFE+Back", | 117 | "Front+Surround+Center/LFE+Back", |
| 108 | }; | 118 | }; |
| 109 | struct oxygen *chip = ctl->private_data; | 119 | struct oxygen *chip = ctl->private_data; |
| 110 | unsigned int count = chip->model.update_center_lfe_mix ? 5 : 3; | 120 | unsigned int count = upmix_item_count(chip); |
| 111 | 121 | ||
| 112 | info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 122 | return snd_ctl_enum_info(info, 1, count, names); |
| 113 | info->count = 1; | ||
| 114 | info->value.enumerated.items = count; | ||
| 115 | if (info->value.enumerated.item >= count) | ||
| 116 | info->value.enumerated.item = count - 1; | ||
| 117 | strcpy(info->value.enumerated.name, names[info->value.enumerated.item]); | ||
| 118 | return 0; | ||
| 119 | } | 123 | } |
| 120 | 124 | ||
| 121 | static int upmix_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) | 125 | static int upmix_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) |
| @@ -188,7 +192,7 @@ void oxygen_update_dac_routing(struct oxygen *chip) | |||
| 188 | static int upmix_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) | 192 | static int upmix_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) |
| 189 | { | 193 | { |
| 190 | struct oxygen *chip = ctl->private_data; | 194 | struct oxygen *chip = ctl->private_data; |
| 191 | unsigned int count = chip->model.update_center_lfe_mix ? 5 : 3; | 195 | unsigned int count = upmix_item_count(chip); |
| 192 | int changed; | 196 | int changed; |
| 193 | 197 | ||
| 194 | if (value->value.enumerated.item[0] >= count) | 198 | if (value->value.enumerated.item[0] >= count) |
| @@ -430,30 +434,31 @@ static int spdif_input_default_get(struct snd_kcontrol *ctl, | |||
| 430 | return 0; | 434 | return 0; |
| 431 | } | 435 | } |
| 432 | 436 | ||
| 433 | static int spdif_loopback_get(struct snd_kcontrol *ctl, | 437 | static int spdif_bit_switch_get(struct snd_kcontrol *ctl, |
| 434 | struct snd_ctl_elem_value *value) | 438 | struct snd_ctl_elem_value *value) |
| 435 | { | 439 | { |
| 436 | struct oxygen *chip = ctl->private_data; | 440 | struct oxygen *chip = ctl->private_data; |
| 441 | u32 bit = ctl->private_value; | ||
| 437 | 442 | ||
| 438 | value->value.integer.value[0] = | 443 | value->value.integer.value[0] = |
| 439 | !!(oxygen_read32(chip, OXYGEN_SPDIF_CONTROL) | 444 | !!(oxygen_read32(chip, OXYGEN_SPDIF_CONTROL) & bit); |
| 440 | & OXYGEN_SPDIF_LOOPBACK); | ||
| 441 | return 0; | 445 | return 0; |
| 442 | } | 446 | } |
| 443 | 447 | ||
| 444 | static int spdif_loopback_put(struct snd_kcontrol *ctl, | 448 | static int spdif_bit_switch_put(struct snd_kcontrol *ctl, |
| 445 | struct snd_ctl_elem_value *value) | 449 | struct snd_ctl_elem_value *value) |
| 446 | { | 450 | { |
| 447 | struct oxygen *chip = ctl->private_data; | 451 | struct oxygen *chip = ctl->private_data; |
| 452 | u32 bit = ctl->private_value; | ||
| 448 | u32 oldreg, newreg; | 453 | u32 oldreg, newreg; |
| 449 | int changed; | 454 | int changed; |
| 450 | 455 | ||
| 451 | spin_lock_irq(&chip->reg_lock); | 456 | spin_lock_irq(&chip->reg_lock); |
| 452 | oldreg = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL); | 457 | oldreg = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL); |
| 453 | if (value->value.integer.value[0]) | 458 | if (value->value.integer.value[0]) |
| 454 | newreg = oldreg | OXYGEN_SPDIF_LOOPBACK; | 459 | newreg = oldreg | bit; |
| 455 | else | 460 | else |
| 456 | newreg = oldreg & ~OXYGEN_SPDIF_LOOPBACK; | 461 | newreg = oldreg & ~bit; |
| 457 | changed = newreg != oldreg; | 462 | changed = newreg != oldreg; |
| 458 | if (changed) | 463 | if (changed) |
| 459 | oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, newreg); | 464 | oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, newreg); |
| @@ -644,6 +649,46 @@ static int ac97_volume_put(struct snd_kcontrol *ctl, | |||
| 644 | return change; | 649 | return change; |
| 645 | } | 650 | } |
| 646 | 651 | ||
| 652 | static int mic_fmic_source_info(struct snd_kcontrol *ctl, | ||
| 653 | struct snd_ctl_elem_info *info) | ||
| 654 | { | ||
| 655 | static const char *const names[] = { "Mic Jack", "Front Panel" }; | ||
| 656 | |||
| 657 | return snd_ctl_enum_info(info, 1, 2, names); | ||
| 658 | } | ||
| 659 | |||
| 660 | static int mic_fmic_source_get(struct snd_kcontrol *ctl, | ||
| 661 | struct snd_ctl_elem_value *value) | ||
| 662 | { | ||
| 663 | struct oxygen *chip = ctl->private_data; | ||
| 664 | |||
| 665 | mutex_lock(&chip->mutex); | ||
| 666 | value->value.enumerated.item[0] = | ||
| 667 | !!(oxygen_read_ac97(chip, 0, CM9780_JACK) & CM9780_FMIC2MIC); | ||
| 668 | mutex_unlock(&chip->mutex); | ||
| 669 | return 0; | ||
| 670 | } | ||
| 671 | |||
| 672 | static int mic_fmic_source_put(struct snd_kcontrol *ctl, | ||
| 673 | struct snd_ctl_elem_value *value) | ||
| 674 | { | ||
| 675 | struct oxygen *chip = ctl->private_data; | ||
| 676 | u16 oldreg, newreg; | ||
| 677 | int change; | ||
| 678 | |||
| 679 | mutex_lock(&chip->mutex); | ||
| 680 | oldreg = oxygen_read_ac97(chip, 0, CM9780_JACK); | ||
| 681 | if (value->value.enumerated.item[0]) | ||
| 682 | newreg = oldreg | CM9780_FMIC2MIC; | ||
| 683 | else | ||
| 684 | newreg = oldreg & ~CM9780_FMIC2MIC; | ||
| 685 | change = newreg != oldreg; | ||
| 686 | if (change) | ||
| 687 | oxygen_write_ac97(chip, 0, CM9780_JACK, newreg); | ||
| 688 | mutex_unlock(&chip->mutex); | ||
| 689 | return change; | ||
| 690 | } | ||
| 691 | |||
| 647 | static int ac97_fp_rec_volume_info(struct snd_kcontrol *ctl, | 692 | static int ac97_fp_rec_volume_info(struct snd_kcontrol *ctl, |
| 648 | struct snd_ctl_elem_info *info) | 693 | struct snd_ctl_elem_info *info) |
| 649 | { | 694 | { |
| @@ -791,8 +836,17 @@ static const struct snd_kcontrol_new spdif_input_controls[] = { | |||
| 791 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 836 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
| 792 | .name = SNDRV_CTL_NAME_IEC958("Loopback ", NONE, SWITCH), | 837 | .name = SNDRV_CTL_NAME_IEC958("Loopback ", NONE, SWITCH), |
| 793 | .info = snd_ctl_boolean_mono_info, | 838 | .info = snd_ctl_boolean_mono_info, |
| 794 | .get = spdif_loopback_get, | 839 | .get = spdif_bit_switch_get, |
| 795 | .put = spdif_loopback_put, | 840 | .put = spdif_bit_switch_put, |
| 841 | .private_value = OXYGEN_SPDIF_LOOPBACK, | ||
| 842 | }, | ||
| 843 | { | ||
| 844 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
| 845 | .name = SNDRV_CTL_NAME_IEC958("Validity Check ",CAPTURE,SWITCH), | ||
| 846 | .info = snd_ctl_boolean_mono_info, | ||
| 847 | .get = spdif_bit_switch_get, | ||
| 848 | .put = spdif_bit_switch_put, | ||
| 849 | .private_value = OXYGEN_SPDIF_SPDVALID, | ||
| 796 | }, | 850 | }, |
| 797 | }; | 851 | }; |
| 798 | 852 | ||
| @@ -908,6 +962,13 @@ static const struct snd_kcontrol_new ac97_controls[] = { | |||
| 908 | AC97_VOLUME("Mic Capture Volume", 0, AC97_MIC, 0), | 962 | AC97_VOLUME("Mic Capture Volume", 0, AC97_MIC, 0), |
| 909 | AC97_SWITCH("Mic Capture Switch", 0, AC97_MIC, 15, 1), | 963 | AC97_SWITCH("Mic Capture Switch", 0, AC97_MIC, 15, 1), |
| 910 | AC97_SWITCH("Mic Boost (+20dB)", 0, AC97_MIC, 6, 0), | 964 | AC97_SWITCH("Mic Boost (+20dB)", 0, AC97_MIC, 6, 0), |
| 965 | { | ||
| 966 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
| 967 | .name = "Mic Source Capture Enum", | ||
| 968 | .info = mic_fmic_source_info, | ||
| 969 | .get = mic_fmic_source_get, | ||
| 970 | .put = mic_fmic_source_put, | ||
| 971 | }, | ||
| 911 | AC97_SWITCH("Line Capture Switch", 0, AC97_LINE, 15, 1), | 972 | AC97_SWITCH("Line Capture Switch", 0, AC97_LINE, 15, 1), |
| 912 | AC97_VOLUME("CD Capture Volume", 0, AC97_CD, 1), | 973 | AC97_VOLUME("CD Capture Volume", 0, AC97_CD, 1), |
| 913 | AC97_SWITCH("CD Capture Switch", 0, AC97_CD, 15, 1), | 974 | AC97_SWITCH("CD Capture Switch", 0, AC97_CD, 15, 1), |
| @@ -970,7 +1031,10 @@ static int add_controls(struct oxygen *chip, | |||
| 970 | continue; | 1031 | continue; |
| 971 | } | 1032 | } |
| 972 | if (!strcmp(template.name, "Stereo Upmixing") && | 1033 | if (!strcmp(template.name, "Stereo Upmixing") && |
| 973 | chip->model.dac_channels == 2) | 1034 | chip->model.dac_channels_pcm == 2) |
| 1035 | continue; | ||
| 1036 | if (!strcmp(template.name, "Mic Source Capture Enum") && | ||
| 1037 | !(chip->model.device_config & AC97_FMIC_SWITCH)) | ||
| 974 | continue; | 1038 | continue; |
| 975 | if (!strncmp(template.name, "CD Capture ", 11) && | 1039 | if (!strncmp(template.name, "CD Capture ", 11) && |
| 976 | !(chip->model.device_config & AC97_CD_INPUT)) | 1040 | !(chip->model.device_config & AC97_CD_INPUT)) |
diff --git a/sound/pci/oxygen/oxygen_pcm.c b/sound/pci/oxygen/oxygen_pcm.c index 814667442eb0..d5533e34ece9 100644 --- a/sound/pci/oxygen/oxygen_pcm.c +++ b/sound/pci/oxygen/oxygen_pcm.c | |||
| @@ -39,7 +39,8 @@ static const struct snd_pcm_hardware oxygen_stereo_hardware = { | |||
| 39 | SNDRV_PCM_INFO_MMAP_VALID | | 39 | SNDRV_PCM_INFO_MMAP_VALID | |
| 40 | SNDRV_PCM_INFO_INTERLEAVED | | 40 | SNDRV_PCM_INFO_INTERLEAVED | |
| 41 | SNDRV_PCM_INFO_PAUSE | | 41 | SNDRV_PCM_INFO_PAUSE | |
| 42 | SNDRV_PCM_INFO_SYNC_START, | 42 | SNDRV_PCM_INFO_SYNC_START | |
| 43 | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, | ||
| 43 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | 44 | .formats = SNDRV_PCM_FMTBIT_S16_LE | |
| 44 | SNDRV_PCM_FMTBIT_S32_LE, | 45 | SNDRV_PCM_FMTBIT_S32_LE, |
| 45 | .rates = SNDRV_PCM_RATE_32000 | | 46 | .rates = SNDRV_PCM_RATE_32000 | |
| @@ -65,7 +66,8 @@ static const struct snd_pcm_hardware oxygen_multichannel_hardware = { | |||
| 65 | SNDRV_PCM_INFO_MMAP_VALID | | 66 | SNDRV_PCM_INFO_MMAP_VALID | |
| 66 | SNDRV_PCM_INFO_INTERLEAVED | | 67 | SNDRV_PCM_INFO_INTERLEAVED | |
| 67 | SNDRV_PCM_INFO_PAUSE | | 68 | SNDRV_PCM_INFO_PAUSE | |
| 68 | SNDRV_PCM_INFO_SYNC_START, | 69 | SNDRV_PCM_INFO_SYNC_START | |
| 70 | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, | ||
| 69 | .formats = SNDRV_PCM_FMTBIT_S16_LE | | 71 | .formats = SNDRV_PCM_FMTBIT_S16_LE | |
| 70 | SNDRV_PCM_FMTBIT_S32_LE, | 72 | SNDRV_PCM_FMTBIT_S32_LE, |
| 71 | .rates = SNDRV_PCM_RATE_32000 | | 73 | .rates = SNDRV_PCM_RATE_32000 | |
| @@ -91,7 +93,8 @@ static const struct snd_pcm_hardware oxygen_ac97_hardware = { | |||
| 91 | SNDRV_PCM_INFO_MMAP_VALID | | 93 | SNDRV_PCM_INFO_MMAP_VALID | |
| 92 | SNDRV_PCM_INFO_INTERLEAVED | | 94 | SNDRV_PCM_INFO_INTERLEAVED | |
| 93 | SNDRV_PCM_INFO_PAUSE | | 95 | SNDRV_PCM_INFO_PAUSE | |
| 94 | SNDRV_PCM_INFO_SYNC_START, | 96 | SNDRV_PCM_INFO_SYNC_START | |
| 97 | SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, | ||
| 95 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 98 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
| 96 | .rates = SNDRV_PCM_RATE_48000, | 99 | .rates = SNDRV_PCM_RATE_48000, |
| 97 | .rate_min = 48000, | 100 | .rate_min = 48000, |
| @@ -140,7 +143,7 @@ static int oxygen_open(struct snd_pcm_substream *substream, | |||
| 140 | runtime->hw.rate_min = 44100; | 143 | runtime->hw.rate_min = 44100; |
| 141 | break; | 144 | break; |
| 142 | case PCM_MULTICH: | 145 | case PCM_MULTICH: |
| 143 | runtime->hw.channels_max = chip->model.dac_channels; | 146 | runtime->hw.channels_max = chip->model.dac_channels_pcm; |
| 144 | break; | 147 | break; |
| 145 | } | 148 | } |
| 146 | if (chip->model.pcm_hardware_filter) | 149 | if (chip->model.pcm_hardware_filter) |
| @@ -271,17 +274,6 @@ static unsigned int oxygen_rate(struct snd_pcm_hw_params *hw_params) | |||
| 271 | } | 274 | } |
| 272 | } | 275 | } |
| 273 | 276 | ||
| 274 | unsigned int oxygen_default_i2s_mclk(struct oxygen *chip, | ||
| 275 | unsigned int channel, | ||
| 276 | struct snd_pcm_hw_params *hw_params) | ||
| 277 | { | ||
| 278 | if (params_rate(hw_params) <= 96000) | ||
| 279 | return OXYGEN_I2S_MCLK_256; | ||
| 280 | else | ||
| 281 | return OXYGEN_I2S_MCLK_128; | ||
| 282 | } | ||
| 283 | EXPORT_SYMBOL(oxygen_default_i2s_mclk); | ||
| 284 | |||
| 285 | static unsigned int oxygen_i2s_bits(struct snd_pcm_hw_params *hw_params) | 277 | static unsigned int oxygen_i2s_bits(struct snd_pcm_hw_params *hw_params) |
| 286 | { | 278 | { |
| 287 | if (params_format(hw_params) == SNDRV_PCM_FORMAT_S32_LE) | 279 | if (params_format(hw_params) == SNDRV_PCM_FORMAT_S32_LE) |
| @@ -341,6 +333,26 @@ static int oxygen_hw_params(struct snd_pcm_substream *substream, | |||
| 341 | return 0; | 333 | return 0; |
| 342 | } | 334 | } |
| 343 | 335 | ||
| 336 | static u16 get_mclk(struct oxygen *chip, unsigned int channel, | ||
| 337 | struct snd_pcm_hw_params *params) | ||
| 338 | { | ||
| 339 | unsigned int mclks, shift; | ||
| 340 | |||
| 341 | if (channel == PCM_MULTICH) | ||
| 342 | mclks = chip->model.dac_mclks; | ||
| 343 | else | ||
| 344 | mclks = chip->model.adc_mclks; | ||
| 345 | |||
| 346 | if (params_rate(params) <= 48000) | ||
| 347 | shift = 0; | ||
| 348 | else if (params_rate(params) <= 96000) | ||
| 349 | shift = 2; | ||
| 350 | else | ||
| 351 | shift = 4; | ||
| 352 | |||
| 353 | return OXYGEN_I2S_MCLK(mclks >> shift); | ||
| 354 | } | ||
| 355 | |||
| 344 | static int oxygen_rec_a_hw_params(struct snd_pcm_substream *substream, | 356 | static int oxygen_rec_a_hw_params(struct snd_pcm_substream *substream, |
| 345 | struct snd_pcm_hw_params *hw_params) | 357 | struct snd_pcm_hw_params *hw_params) |
| 346 | { | 358 | { |
| @@ -357,8 +369,8 @@ static int oxygen_rec_a_hw_params(struct snd_pcm_substream *substream, | |||
| 357 | OXYGEN_REC_FORMAT_A_MASK); | 369 | OXYGEN_REC_FORMAT_A_MASK); |
| 358 | oxygen_write16_masked(chip, OXYGEN_I2S_A_FORMAT, | 370 | oxygen_write16_masked(chip, OXYGEN_I2S_A_FORMAT, |
| 359 | oxygen_rate(hw_params) | | 371 | oxygen_rate(hw_params) | |
| 360 | chip->model.get_i2s_mclk(chip, PCM_A, hw_params) | | ||
| 361 | chip->model.adc_i2s_format | | 372 | chip->model.adc_i2s_format | |
| 373 | get_mclk(chip, PCM_A, hw_params) | | ||
| 362 | oxygen_i2s_bits(hw_params), | 374 | oxygen_i2s_bits(hw_params), |
| 363 | OXYGEN_I2S_RATE_MASK | | 375 | OXYGEN_I2S_RATE_MASK | |
| 364 | OXYGEN_I2S_FORMAT_MASK | | 376 | OXYGEN_I2S_FORMAT_MASK | |
| @@ -393,9 +405,8 @@ static int oxygen_rec_b_hw_params(struct snd_pcm_substream *substream, | |||
| 393 | if (!is_ac97) | 405 | if (!is_ac97) |
| 394 | oxygen_write16_masked(chip, OXYGEN_I2S_B_FORMAT, | 406 | oxygen_write16_masked(chip, OXYGEN_I2S_B_FORMAT, |
| 395 | oxygen_rate(hw_params) | | 407 | oxygen_rate(hw_params) | |
| 396 | chip->model.get_i2s_mclk(chip, PCM_B, | ||
| 397 | hw_params) | | ||
| 398 | chip->model.adc_i2s_format | | 408 | chip->model.adc_i2s_format | |
| 409 | get_mclk(chip, PCM_B, hw_params) | | ||
| 399 | oxygen_i2s_bits(hw_params), | 410 | oxygen_i2s_bits(hw_params), |
| 400 | OXYGEN_I2S_RATE_MASK | | 411 | OXYGEN_I2S_RATE_MASK | |
| 401 | OXYGEN_I2S_FORMAT_MASK | | 412 | OXYGEN_I2S_FORMAT_MASK | |
| @@ -476,8 +487,7 @@ static int oxygen_multich_hw_params(struct snd_pcm_substream *substream, | |||
| 476 | oxygen_write16_masked(chip, OXYGEN_I2S_MULTICH_FORMAT, | 487 | oxygen_write16_masked(chip, OXYGEN_I2S_MULTICH_FORMAT, |
| 477 | oxygen_rate(hw_params) | | 488 | oxygen_rate(hw_params) | |
| 478 | chip->model.dac_i2s_format | | 489 | chip->model.dac_i2s_format | |
| 479 | chip->model.get_i2s_mclk(chip, PCM_MULTICH, | 490 | get_mclk(chip, PCM_MULTICH, hw_params) | |
| 480 | hw_params) | | ||
| 481 | oxygen_i2s_bits(hw_params), | 491 | oxygen_i2s_bits(hw_params), |
| 482 | OXYGEN_I2S_RATE_MASK | | 492 | OXYGEN_I2S_RATE_MASK | |
| 483 | OXYGEN_I2S_FORMAT_MASK | | 493 | OXYGEN_I2S_FORMAT_MASK | |
| @@ -530,7 +540,10 @@ static int oxygen_prepare(struct snd_pcm_substream *substream) | |||
| 530 | oxygen_set_bits8(chip, OXYGEN_DMA_FLUSH, channel_mask); | 540 | oxygen_set_bits8(chip, OXYGEN_DMA_FLUSH, channel_mask); |
| 531 | oxygen_clear_bits8(chip, OXYGEN_DMA_FLUSH, channel_mask); | 541 | oxygen_clear_bits8(chip, OXYGEN_DMA_FLUSH, channel_mask); |
| 532 | 542 | ||
| 533 | chip->interrupt_mask |= channel_mask; | 543 | if (substream->runtime->no_period_wakeup) |
| 544 | chip->interrupt_mask &= ~channel_mask; | ||
| 545 | else | ||
| 546 | chip->interrupt_mask |= channel_mask; | ||
| 534 | oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask); | 547 | oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask); |
| 535 | spin_unlock_irq(&chip->reg_lock); | 548 | spin_unlock_irq(&chip->reg_lock); |
| 536 | return 0; | 549 | return 0; |
diff --git a/sound/pci/oxygen/oxygen_regs.h b/sound/pci/oxygen/oxygen_regs.h index 4dcd41b78258..63dc7a0ab555 100644 --- a/sound/pci/oxygen/oxygen_regs.h +++ b/sound/pci/oxygen/oxygen_regs.h | |||
| @@ -139,9 +139,11 @@ | |||
| 139 | #define OXYGEN_I2S_FORMAT_I2S 0x0000 | 139 | #define OXYGEN_I2S_FORMAT_I2S 0x0000 |
| 140 | #define OXYGEN_I2S_FORMAT_LJUST 0x0008 | 140 | #define OXYGEN_I2S_FORMAT_LJUST 0x0008 |
| 141 | #define OXYGEN_I2S_MCLK_MASK 0x0030 /* MCLK/LRCK */ | 141 | #define OXYGEN_I2S_MCLK_MASK 0x0030 /* MCLK/LRCK */ |
| 142 | #define OXYGEN_I2S_MCLK_128 0x0000 | 142 | #define OXYGEN_I2S_MCLK_SHIFT 4 |
| 143 | #define OXYGEN_I2S_MCLK_256 0x0010 | 143 | #define MCLK_128 0 |
| 144 | #define OXYGEN_I2S_MCLK_512 0x0020 | 144 | #define MCLK_256 1 |
| 145 | #define MCLK_512 2 | ||
| 146 | #define OXYGEN_I2S_MCLK(f) (((f) & 3) << OXYGEN_I2S_MCLK_SHIFT) | ||
| 145 | #define OXYGEN_I2S_BITS_MASK 0x00c0 | 147 | #define OXYGEN_I2S_BITS_MASK 0x00c0 |
| 146 | #define OXYGEN_I2S_BITS_16 0x0000 | 148 | #define OXYGEN_I2S_BITS_16 0x0000 |
| 147 | #define OXYGEN_I2S_BITS_20 0x0040 | 149 | #define OXYGEN_I2S_BITS_20 0x0040 |
| @@ -238,11 +240,11 @@ | |||
| 238 | #define OXYGEN_SPI_DATA_LENGTH_MASK 0x02 | 240 | #define OXYGEN_SPI_DATA_LENGTH_MASK 0x02 |
| 239 | #define OXYGEN_SPI_DATA_LENGTH_2 0x00 | 241 | #define OXYGEN_SPI_DATA_LENGTH_2 0x00 |
| 240 | #define OXYGEN_SPI_DATA_LENGTH_3 0x02 | 242 | #define OXYGEN_SPI_DATA_LENGTH_3 0x02 |
| 241 | #define OXYGEN_SPI_CLOCK_MASK 0xc0 | 243 | #define OXYGEN_SPI_CLOCK_MASK 0x0c |
| 242 | #define OXYGEN_SPI_CLOCK_160 0x00 /* ns */ | 244 | #define OXYGEN_SPI_CLOCK_160 0x00 /* ns */ |
| 243 | #define OXYGEN_SPI_CLOCK_320 0x40 | 245 | #define OXYGEN_SPI_CLOCK_320 0x04 |
| 244 | #define OXYGEN_SPI_CLOCK_640 0x80 | 246 | #define OXYGEN_SPI_CLOCK_640 0x08 |
| 245 | #define OXYGEN_SPI_CLOCK_1280 0xc0 | 247 | #define OXYGEN_SPI_CLOCK_1280 0x0c |
| 246 | #define OXYGEN_SPI_CODEC_MASK 0x70 /* 0..5 */ | 248 | #define OXYGEN_SPI_CODEC_MASK 0x70 /* 0..5 */ |
| 247 | #define OXYGEN_SPI_CODEC_SHIFT 4 | 249 | #define OXYGEN_SPI_CODEC_SHIFT 4 |
| 248 | #define OXYGEN_SPI_CEN_MASK 0x80 | 250 | #define OXYGEN_SPI_CEN_MASK 0x80 |
diff --git a/sound/pci/oxygen/xonar.h b/sound/pci/oxygen/xonar.h index b35343b0a9a5..0434c207e811 100644 --- a/sound/pci/oxygen/xonar.h +++ b/sound/pci/oxygen/xonar.h | |||
| @@ -24,6 +24,8 @@ void xonar_init_ext_power(struct oxygen *chip); | |||
| 24 | void xonar_init_cs53x1(struct oxygen *chip); | 24 | void xonar_init_cs53x1(struct oxygen *chip); |
| 25 | void xonar_set_cs53x1_params(struct oxygen *chip, | 25 | void xonar_set_cs53x1_params(struct oxygen *chip, |
| 26 | struct snd_pcm_hw_params *params); | 26 | struct snd_pcm_hw_params *params); |
| 27 | |||
| 28 | #define XONAR_GPIO_BIT_INVERT (1 << 16) | ||
| 27 | int xonar_gpio_bit_switch_get(struct snd_kcontrol *ctl, | 29 | int xonar_gpio_bit_switch_get(struct snd_kcontrol *ctl, |
| 28 | struct snd_ctl_elem_value *value); | 30 | struct snd_ctl_elem_value *value); |
| 29 | int xonar_gpio_bit_switch_put(struct snd_kcontrol *ctl, | 31 | int xonar_gpio_bit_switch_put(struct snd_kcontrol *ctl, |
diff --git a/sound/pci/oxygen/xonar_cs43xx.c b/sound/pci/oxygen/xonar_cs43xx.c index aa27c31049af..9f72d424969c 100644 --- a/sound/pci/oxygen/xonar_cs43xx.c +++ b/sound/pci/oxygen/xonar_cs43xx.c | |||
| @@ -22,29 +22,28 @@ | |||
| 22 | * | 22 | * |
| 23 | * CMI8788: | 23 | * CMI8788: |
| 24 | * | 24 | * |
| 25 | * I²C <-> CS4398 (front) | 25 | * I²C <-> CS4398 (addr 1001111) (front) |
| 26 | * <-> CS4362A (surround, center/LFE, back) | 26 | * <-> CS4362A (addr 0011000) (surround, center/LFE, back) |
| 27 | * | 27 | * |
| 28 | * GPI 0 <- external power present (DX only) | 28 | * GPI 0 <- external power present (DX only) |
| 29 | * | 29 | * |
| 30 | * GPIO 0 -> enable output to speakers | 30 | * GPIO 0 -> enable output to speakers |
| 31 | * GPIO 1 -> enable front panel I/O | 31 | * GPIO 1 -> route output to front panel |
| 32 | * GPIO 2 -> M0 of CS5361 | 32 | * GPIO 2 -> M0 of CS5361 |
| 33 | * GPIO 3 -> M1 of CS5361 | 33 | * GPIO 3 -> M1 of CS5361 |
| 34 | * GPIO 8 -> route input jack to line-in (0) or mic-in (1) | 34 | * GPIO 6 -> ? |
| 35 | * GPIO 7 -> ? | ||
| 36 | * GPIO 8 -> route input jack to line-in (0) or mic-in (1) | ||
| 35 | * | 37 | * |
| 36 | * CS4398: | 38 | * CM9780: |
| 37 | * | ||
| 38 | * AD0 <- 1 | ||
| 39 | * AD1 <- 1 | ||
| 40 | * | 39 | * |
| 41 | * CS4362A: | 40 | * LINE_OUT -> input of ADC |
| 42 | * | 41 | * |
| 43 | * AD0 <- 0 | 42 | * AUX_IN <- aux |
| 43 | * MIC_IN <- mic | ||
| 44 | * FMIC_IN <- front mic | ||
| 44 | * | 45 | * |
| 45 | * CM9780: | 46 | * GPO 0 -> route line-in (0) or AC97 output (1) to CS5361 input |
| 46 | * | ||
| 47 | * GPO 0 -> route line-in (0) or AC97 output (1) to CS5361 input | ||
| 48 | */ | 47 | */ |
| 49 | 48 | ||
| 50 | #include <linux/pci.h> | 49 | #include <linux/pci.h> |
| @@ -63,6 +62,7 @@ | |||
| 63 | #define GPI_EXT_POWER 0x01 | 62 | #define GPI_EXT_POWER 0x01 |
| 64 | #define GPIO_D1_OUTPUT_ENABLE 0x0001 | 63 | #define GPIO_D1_OUTPUT_ENABLE 0x0001 |
| 65 | #define GPIO_D1_FRONT_PANEL 0x0002 | 64 | #define GPIO_D1_FRONT_PANEL 0x0002 |
| 65 | #define GPIO_D1_MAGIC 0x00c0 | ||
| 66 | #define GPIO_D1_INPUT_ROUTE 0x0100 | 66 | #define GPIO_D1_INPUT_ROUTE 0x0100 |
| 67 | 67 | ||
| 68 | #define I2C_DEVICE_CS4398 0x9e /* 10011, AD1=1, AD0=1, /W=0 */ | 68 | #define I2C_DEVICE_CS4398 0x9e /* 10011, AD1=1, AD0=1, /W=0 */ |
| @@ -169,12 +169,12 @@ static void xonar_d1_init(struct oxygen *chip) | |||
| 169 | cs43xx_registers_init(chip); | 169 | cs43xx_registers_init(chip); |
| 170 | 170 | ||
| 171 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, | 171 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, |
| 172 | GPIO_D1_FRONT_PANEL | GPIO_D1_INPUT_ROUTE); | 172 | GPIO_D1_FRONT_PANEL | |
| 173 | GPIO_D1_MAGIC | | ||
| 174 | GPIO_D1_INPUT_ROUTE); | ||
| 173 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, | 175 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, |
| 174 | GPIO_D1_FRONT_PANEL | GPIO_D1_INPUT_ROUTE); | 176 | GPIO_D1_FRONT_PANEL | GPIO_D1_INPUT_ROUTE); |
| 175 | 177 | ||
| 176 | oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC); | ||
| 177 | |||
| 178 | xonar_init_cs53x1(chip); | 178 | xonar_init_cs53x1(chip); |
| 179 | xonar_enable_output(chip); | 179 | xonar_enable_output(chip); |
| 180 | 180 | ||
| @@ -284,7 +284,7 @@ static void update_cs43xx_center_lfe_mix(struct oxygen *chip, bool mixed) | |||
| 284 | 284 | ||
| 285 | static const struct snd_kcontrol_new front_panel_switch = { | 285 | static const struct snd_kcontrol_new front_panel_switch = { |
| 286 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 286 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
| 287 | .name = "Front Panel Switch", | 287 | .name = "Front Panel Playback Switch", |
| 288 | .info = snd_ctl_boolean_mono_info, | 288 | .info = snd_ctl_boolean_mono_info, |
| 289 | .get = xonar_gpio_bit_switch_get, | 289 | .get = xonar_gpio_bit_switch_get, |
| 290 | .put = xonar_gpio_bit_switch_put, | 290 | .put = xonar_gpio_bit_switch_put, |
| @@ -298,13 +298,7 @@ static int rolloff_info(struct snd_kcontrol *ctl, | |||
| 298 | "Fast Roll-off", "Slow Roll-off" | 298 | "Fast Roll-off", "Slow Roll-off" |
| 299 | }; | 299 | }; |
| 300 | 300 | ||
| 301 | info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 301 | return snd_ctl_enum_info(info, 1, 2, names); |
| 302 | info->count = 1; | ||
| 303 | info->value.enumerated.items = 2; | ||
| 304 | if (info->value.enumerated.item >= 2) | ||
| 305 | info->value.enumerated.item = 1; | ||
| 306 | strcpy(info->value.enumerated.name, names[info->value.enumerated.item]); | ||
| 307 | return 0; | ||
| 308 | } | 302 | } |
| 309 | 303 | ||
| 310 | static int rolloff_get(struct snd_kcontrol *ctl, | 304 | static int rolloff_get(struct snd_kcontrol *ctl, |
| @@ -380,6 +374,30 @@ static int xonar_d1_mixer_init(struct oxygen *chip) | |||
| 380 | return 0; | 374 | return 0; |
| 381 | } | 375 | } |
| 382 | 376 | ||
| 377 | static void dump_cs4362a_registers(struct xonar_cs43xx *data, | ||
| 378 | struct snd_info_buffer *buffer) | ||
| 379 | { | ||
| 380 | unsigned int i; | ||
| 381 | |||
| 382 | snd_iprintf(buffer, "\nCS4362A:"); | ||
| 383 | for (i = 1; i <= 14; ++i) | ||
| 384 | snd_iprintf(buffer, " %02x", data->cs4362a_regs[i]); | ||
| 385 | snd_iprintf(buffer, "\n"); | ||
| 386 | } | ||
| 387 | |||
| 388 | static void dump_d1_registers(struct oxygen *chip, | ||
| 389 | struct snd_info_buffer *buffer) | ||
| 390 | { | ||
| 391 | struct xonar_cs43xx *data = chip->model_data; | ||
| 392 | unsigned int i; | ||
| 393 | |||
| 394 | snd_iprintf(buffer, "\nCS4398: 7?"); | ||
| 395 | for (i = 2; i <= 8; ++i) | ||
| 396 | snd_iprintf(buffer, " %02x", data->cs4398_regs[i]); | ||
| 397 | snd_iprintf(buffer, "\n"); | ||
| 398 | dump_cs4362a_registers(data, buffer); | ||
| 399 | } | ||
| 400 | |||
| 383 | static const struct oxygen_model model_xonar_d1 = { | 401 | static const struct oxygen_model model_xonar_d1 = { |
| 384 | .longname = "Asus Virtuoso 100", | 402 | .longname = "Asus Virtuoso 100", |
| 385 | .chip = "AV200", | 403 | .chip = "AV200", |
| @@ -388,22 +406,26 @@ static const struct oxygen_model model_xonar_d1 = { | |||
| 388 | .cleanup = xonar_d1_cleanup, | 406 | .cleanup = xonar_d1_cleanup, |
| 389 | .suspend = xonar_d1_suspend, | 407 | .suspend = xonar_d1_suspend, |
| 390 | .resume = xonar_d1_resume, | 408 | .resume = xonar_d1_resume, |
| 391 | .get_i2s_mclk = oxygen_default_i2s_mclk, | ||
| 392 | .set_dac_params = set_cs43xx_params, | 409 | .set_dac_params = set_cs43xx_params, |
| 393 | .set_adc_params = xonar_set_cs53x1_params, | 410 | .set_adc_params = xonar_set_cs53x1_params, |
| 394 | .update_dac_volume = update_cs43xx_volume, | 411 | .update_dac_volume = update_cs43xx_volume, |
| 395 | .update_dac_mute = update_cs43xx_mute, | 412 | .update_dac_mute = update_cs43xx_mute, |
| 396 | .update_center_lfe_mix = update_cs43xx_center_lfe_mix, | 413 | .update_center_lfe_mix = update_cs43xx_center_lfe_mix, |
| 397 | .ac97_switch = xonar_d1_line_mic_ac97_switch, | 414 | .ac97_switch = xonar_d1_line_mic_ac97_switch, |
| 415 | .dump_registers = dump_d1_registers, | ||
| 398 | .dac_tlv = cs4362a_db_scale, | 416 | .dac_tlv = cs4362a_db_scale, |
| 399 | .model_data_size = sizeof(struct xonar_cs43xx), | 417 | .model_data_size = sizeof(struct xonar_cs43xx), |
| 400 | .device_config = PLAYBACK_0_TO_I2S | | 418 | .device_config = PLAYBACK_0_TO_I2S | |
| 401 | PLAYBACK_1_TO_SPDIF | | 419 | PLAYBACK_1_TO_SPDIF | |
| 402 | CAPTURE_0_FROM_I2S_2, | 420 | CAPTURE_0_FROM_I2S_2 | |
| 403 | .dac_channels = 8, | 421 | AC97_FMIC_SWITCH, |
| 422 | .dac_channels_pcm = 8, | ||
| 423 | .dac_channels_mixer = 8, | ||
| 404 | .dac_volume_min = 127 - 60, | 424 | .dac_volume_min = 127 - 60, |
| 405 | .dac_volume_max = 127, | 425 | .dac_volume_max = 127, |
| 406 | .function_flags = OXYGEN_FUNCTION_2WIRE, | 426 | .function_flags = OXYGEN_FUNCTION_2WIRE, |
| 427 | .dac_mclks = OXYGEN_MCLKS(256, 128, 128), | ||
| 428 | .adc_mclks = OXYGEN_MCLKS(256, 128, 128), | ||
| 407 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 429 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
| 408 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 430 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
| 409 | }; | 431 | }; |
diff --git a/sound/pci/oxygen/xonar_dg.c b/sound/pci/oxygen/xonar_dg.c new file mode 100644 index 000000000000..e4de0b8d087a --- /dev/null +++ b/sound/pci/oxygen/xonar_dg.c | |||
| @@ -0,0 +1,572 @@ | |||
| 1 | /* | ||
| 2 | * card driver for the Xonar DG | ||
| 3 | * | ||
| 4 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> | ||
| 5 | * | ||
| 6 | * | ||
| 7 | * This driver is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License, version 2. | ||
| 9 | * | ||
| 10 | * This driver is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this driver; if not, see <http://www.gnu.org/licenses/>. | ||
| 17 | */ | ||
| 18 | |||
| 19 | /* | ||
| 20 | * Xonar DG | ||
| 21 | * -------- | ||
| 22 | * | ||
| 23 | * CMI8788: | ||
| 24 | * | ||
| 25 | * SPI 0 -> CS4245 | ||
| 26 | * | ||
| 27 | * GPIO 3 <- ? | ||
| 28 | * GPIO 4 <- headphone detect | ||
| 29 | * GPIO 5 -> route input jack to line-in (0) or mic-in (1) | ||
| 30 | * GPIO 6 -> route input jack to line-in (0) or mic-in (1) | ||
| 31 | * GPIO 7 -> enable rear headphone amp | ||
| 32 | * GPIO 8 -> enable output to speakers | ||
| 33 | * | ||
| 34 | * CS4245: | ||
| 35 | * | ||
| 36 | * input 1 <- aux | ||
| 37 | * input 2 <- front mic | ||
| 38 | * input 4 <- line/mic | ||
| 39 | * aux out -> front panel headphones | ||
| 40 | */ | ||
| 41 | |||
| 42 | #include <linux/pci.h> | ||
| 43 | #include <linux/delay.h> | ||
| 44 | #include <sound/control.h> | ||
| 45 | #include <sound/core.h> | ||
| 46 | #include <sound/info.h> | ||
| 47 | #include <sound/pcm.h> | ||
| 48 | #include <sound/tlv.h> | ||
| 49 | #include "oxygen.h" | ||
| 50 | #include "xonar_dg.h" | ||
| 51 | #include "cs4245.h" | ||
| 52 | |||
| 53 | #define GPIO_MAGIC 0x0008 | ||
| 54 | #define GPIO_HP_DETECT 0x0010 | ||
| 55 | #define GPIO_INPUT_ROUTE 0x0060 | ||
| 56 | #define GPIO_HP_REAR 0x0080 | ||
| 57 | #define GPIO_OUTPUT_ENABLE 0x0100 | ||
| 58 | |||
| 59 | struct dg { | ||
| 60 | unsigned int output_sel; | ||
| 61 | s8 input_vol[4][2]; | ||
| 62 | unsigned int input_sel; | ||
| 63 | u8 hp_vol_att; | ||
| 64 | u8 cs4245_regs[0x11]; | ||
| 65 | }; | ||
| 66 | |||
| 67 | static void cs4245_write(struct oxygen *chip, unsigned int reg, u8 value) | ||
| 68 | { | ||
| 69 | struct dg *data = chip->model_data; | ||
| 70 | |||
| 71 | oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | | ||
| 72 | OXYGEN_SPI_DATA_LENGTH_3 | | ||
| 73 | OXYGEN_SPI_CLOCK_1280 | | ||
| 74 | (0 << OXYGEN_SPI_CODEC_SHIFT) | | ||
| 75 | OXYGEN_SPI_CEN_LATCH_CLOCK_HI, | ||
| 76 | CS4245_SPI_ADDRESS | | ||
| 77 | CS4245_SPI_WRITE | | ||
| 78 | (value << 8) | reg); | ||
| 79 | data->cs4245_regs[reg] = value; | ||
| 80 | } | ||
| 81 | |||
| 82 | static void cs4245_write_cached(struct oxygen *chip, unsigned int reg, u8 value) | ||
| 83 | { | ||
| 84 | struct dg *data = chip->model_data; | ||
| 85 | |||
| 86 | if (value != data->cs4245_regs[reg]) | ||
| 87 | cs4245_write(chip, reg, value); | ||
| 88 | } | ||
| 89 | |||
| 90 | static void cs4245_registers_init(struct oxygen *chip) | ||
| 91 | { | ||
| 92 | struct dg *data = chip->model_data; | ||
| 93 | |||
| 94 | cs4245_write(chip, CS4245_POWER_CTRL, CS4245_PDN); | ||
| 95 | cs4245_write(chip, CS4245_DAC_CTRL_1, | ||
| 96 | data->cs4245_regs[CS4245_DAC_CTRL_1]); | ||
| 97 | cs4245_write(chip, CS4245_ADC_CTRL, | ||
| 98 | data->cs4245_regs[CS4245_ADC_CTRL]); | ||
| 99 | cs4245_write(chip, CS4245_SIGNAL_SEL, | ||
| 100 | data->cs4245_regs[CS4245_SIGNAL_SEL]); | ||
| 101 | cs4245_write(chip, CS4245_PGA_B_CTRL, | ||
| 102 | data->cs4245_regs[CS4245_PGA_B_CTRL]); | ||
| 103 | cs4245_write(chip, CS4245_PGA_A_CTRL, | ||
| 104 | data->cs4245_regs[CS4245_PGA_A_CTRL]); | ||
| 105 | cs4245_write(chip, CS4245_ANALOG_IN, | ||
| 106 | data->cs4245_regs[CS4245_ANALOG_IN]); | ||
| 107 | cs4245_write(chip, CS4245_DAC_A_CTRL, | ||
| 108 | data->cs4245_regs[CS4245_DAC_A_CTRL]); | ||
| 109 | cs4245_write(chip, CS4245_DAC_B_CTRL, | ||
| 110 | data->cs4245_regs[CS4245_DAC_B_CTRL]); | ||
| 111 | cs4245_write(chip, CS4245_DAC_CTRL_2, | ||
| 112 | CS4245_DAC_SOFT | CS4245_DAC_ZERO | CS4245_INVERT_DAC); | ||
| 113 | cs4245_write(chip, CS4245_INT_MASK, 0); | ||
| 114 | cs4245_write(chip, CS4245_POWER_CTRL, 0); | ||
| 115 | } | ||
| 116 | |||
| 117 | static void cs4245_init(struct oxygen *chip) | ||
| 118 | { | ||
| 119 | struct dg *data = chip->model_data; | ||
| 120 | |||
| 121 | data->cs4245_regs[CS4245_DAC_CTRL_1] = | ||
| 122 | CS4245_DAC_FM_SINGLE | CS4245_DAC_DIF_LJUST; | ||
| 123 | data->cs4245_regs[CS4245_ADC_CTRL] = | ||
| 124 | CS4245_ADC_FM_SINGLE | CS4245_ADC_DIF_LJUST; | ||
| 125 | data->cs4245_regs[CS4245_SIGNAL_SEL] = | ||
| 126 | CS4245_A_OUT_SEL_HIZ | CS4245_ASYNCH; | ||
| 127 | data->cs4245_regs[CS4245_PGA_B_CTRL] = 0; | ||
| 128 | data->cs4245_regs[CS4245_PGA_A_CTRL] = 0; | ||
| 129 | data->cs4245_regs[CS4245_ANALOG_IN] = | ||
| 130 | CS4245_PGA_SOFT | CS4245_PGA_ZERO | CS4245_SEL_INPUT_4; | ||
| 131 | data->cs4245_regs[CS4245_DAC_A_CTRL] = 0; | ||
| 132 | data->cs4245_regs[CS4245_DAC_B_CTRL] = 0; | ||
| 133 | cs4245_registers_init(chip); | ||
| 134 | snd_component_add(chip->card, "CS4245"); | ||
| 135 | } | ||
| 136 | |||
| 137 | static void dg_output_enable(struct oxygen *chip) | ||
| 138 | { | ||
| 139 | msleep(2500); | ||
| 140 | oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE); | ||
| 141 | } | ||
| 142 | |||
| 143 | static void dg_init(struct oxygen *chip) | ||
| 144 | { | ||
| 145 | struct dg *data = chip->model_data; | ||
| 146 | |||
| 147 | data->output_sel = 0; | ||
| 148 | data->input_sel = 3; | ||
| 149 | data->hp_vol_att = 2 * 16; | ||
| 150 | |||
| 151 | cs4245_init(chip); | ||
| 152 | |||
| 153 | oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, | ||
| 154 | GPIO_MAGIC | GPIO_HP_DETECT); | ||
| 155 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, | ||
| 156 | GPIO_INPUT_ROUTE | GPIO_HP_REAR | GPIO_OUTPUT_ENABLE); | ||
| 157 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, | ||
| 158 | GPIO_INPUT_ROUTE | GPIO_HP_REAR); | ||
| 159 | dg_output_enable(chip); | ||
| 160 | } | ||
| 161 | |||
| 162 | static void dg_cleanup(struct oxygen *chip) | ||
| 163 | { | ||
| 164 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE); | ||
| 165 | } | ||
| 166 | |||
| 167 | static void dg_suspend(struct oxygen *chip) | ||
| 168 | { | ||
| 169 | dg_cleanup(chip); | ||
| 170 | } | ||
| 171 | |||
| 172 | static void dg_resume(struct oxygen *chip) | ||
| 173 | { | ||
| 174 | cs4245_registers_init(chip); | ||
| 175 | dg_output_enable(chip); | ||
| 176 | } | ||
| 177 | |||
| 178 | static void set_cs4245_dac_params(struct oxygen *chip, | ||
| 179 | struct snd_pcm_hw_params *params) | ||
| 180 | { | ||
| 181 | struct dg *data = chip->model_data; | ||
| 182 | u8 value; | ||
| 183 | |||
| 184 | value = data->cs4245_regs[CS4245_DAC_CTRL_1] & ~CS4245_DAC_FM_MASK; | ||
| 185 | if (params_rate(params) <= 50000) | ||
| 186 | value |= CS4245_DAC_FM_SINGLE; | ||
| 187 | else if (params_rate(params) <= 100000) | ||
| 188 | value |= CS4245_DAC_FM_DOUBLE; | ||
| 189 | else | ||
| 190 | value |= CS4245_DAC_FM_QUAD; | ||
| 191 | cs4245_write_cached(chip, CS4245_DAC_CTRL_1, value); | ||
| 192 | } | ||
| 193 | |||
| 194 | static void set_cs4245_adc_params(struct oxygen *chip, | ||
| 195 | struct snd_pcm_hw_params *params) | ||
| 196 | { | ||
| 197 | struct dg *data = chip->model_data; | ||
| 198 | u8 value; | ||
| 199 | |||
| 200 | value = data->cs4245_regs[CS4245_ADC_CTRL] & ~CS4245_ADC_FM_MASK; | ||
| 201 | if (params_rate(params) <= 50000) | ||
| 202 | value |= CS4245_ADC_FM_SINGLE; | ||
| 203 | else if (params_rate(params) <= 100000) | ||
| 204 | value |= CS4245_ADC_FM_DOUBLE; | ||
| 205 | else | ||
| 206 | value |= CS4245_ADC_FM_QUAD; | ||
| 207 | cs4245_write_cached(chip, CS4245_ADC_CTRL, value); | ||
| 208 | } | ||
| 209 | |||
| 210 | static int output_switch_info(struct snd_kcontrol *ctl, | ||
| 211 | struct snd_ctl_elem_info *info) | ||
| 212 | { | ||
| 213 | static const char *const names[3] = { | ||
| 214 | "Speakers", "Headphones", "FP Headphones" | ||
| 215 | }; | ||
| 216 | |||
| 217 | return snd_ctl_enum_info(info, 1, 3, names); | ||
| 218 | } | ||
| 219 | |||
| 220 | static int output_switch_get(struct snd_kcontrol *ctl, | ||
| 221 | struct snd_ctl_elem_value *value) | ||
| 222 | { | ||
| 223 | struct oxygen *chip = ctl->private_data; | ||
| 224 | struct dg *data = chip->model_data; | ||
| 225 | |||
| 226 | mutex_lock(&chip->mutex); | ||
| 227 | value->value.enumerated.item[0] = data->output_sel; | ||
| 228 | mutex_unlock(&chip->mutex); | ||
| 229 | return 0; | ||
| 230 | } | ||
| 231 | |||
| 232 | static int output_switch_put(struct snd_kcontrol *ctl, | ||
| 233 | struct snd_ctl_elem_value *value) | ||
| 234 | { | ||
| 235 | struct oxygen *chip = ctl->private_data; | ||
| 236 | struct dg *data = chip->model_data; | ||
| 237 | u8 reg; | ||
| 238 | int changed; | ||
| 239 | |||
| 240 | if (value->value.enumerated.item[0] > 2) | ||
| 241 | return -EINVAL; | ||
| 242 | |||
| 243 | mutex_lock(&chip->mutex); | ||
| 244 | changed = value->value.enumerated.item[0] != data->output_sel; | ||
| 245 | if (changed) { | ||
| 246 | data->output_sel = value->value.enumerated.item[0]; | ||
| 247 | |||
| 248 | reg = data->cs4245_regs[CS4245_SIGNAL_SEL] & | ||
| 249 | ~CS4245_A_OUT_SEL_MASK; | ||
| 250 | reg |= data->output_sel == 2 ? | ||
| 251 | CS4245_A_OUT_SEL_DAC : CS4245_A_OUT_SEL_HIZ; | ||
| 252 | cs4245_write_cached(chip, CS4245_SIGNAL_SEL, reg); | ||
| 253 | |||
| 254 | cs4245_write_cached(chip, CS4245_DAC_A_CTRL, | ||
| 255 | data->output_sel ? data->hp_vol_att : 0); | ||
| 256 | cs4245_write_cached(chip, CS4245_DAC_B_CTRL, | ||
| 257 | data->output_sel ? data->hp_vol_att : 0); | ||
| 258 | |||
| 259 | oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, | ||
| 260 | data->output_sel == 1 ? GPIO_HP_REAR : 0, | ||
| 261 | GPIO_HP_REAR); | ||
| 262 | } | ||
| 263 | mutex_unlock(&chip->mutex); | ||
| 264 | return changed; | ||
| 265 | } | ||
| 266 | |||
| 267 | static int hp_volume_offset_info(struct snd_kcontrol *ctl, | ||
| 268 | struct snd_ctl_elem_info *info) | ||
| 269 | { | ||
| 270 | static const char *const names[3] = { | ||
| 271 | "< 64 ohms", "64-150 ohms", "150-300 ohms" | ||
| 272 | }; | ||
| 273 | |||
| 274 | return snd_ctl_enum_info(info, 1, 3, names); | ||
| 275 | } | ||
| 276 | |||
| 277 | static int hp_volume_offset_get(struct snd_kcontrol *ctl, | ||
| 278 | struct snd_ctl_elem_value *value) | ||
| 279 | { | ||
| 280 | struct oxygen *chip = ctl->private_data; | ||
| 281 | struct dg *data = chip->model_data; | ||
| 282 | |||
| 283 | mutex_lock(&chip->mutex); | ||
| 284 | if (data->hp_vol_att > 2 * 7) | ||
| 285 | value->value.enumerated.item[0] = 0; | ||
| 286 | else if (data->hp_vol_att > 0) | ||
| 287 | value->value.enumerated.item[0] = 1; | ||
| 288 | else | ||
| 289 | value->value.enumerated.item[0] = 2; | ||
| 290 | mutex_unlock(&chip->mutex); | ||
| 291 | return 0; | ||
| 292 | } | ||
| 293 | |||
| 294 | static int hp_volume_offset_put(struct snd_kcontrol *ctl, | ||
| 295 | struct snd_ctl_elem_value *value) | ||
| 296 | { | ||
| 297 | static const s8 atts[3] = { 2 * 16, 2 * 7, 0 }; | ||
| 298 | struct oxygen *chip = ctl->private_data; | ||
| 299 | struct dg *data = chip->model_data; | ||
| 300 | s8 att; | ||
| 301 | int changed; | ||
| 302 | |||
| 303 | if (value->value.enumerated.item[0] > 2) | ||
| 304 | return -EINVAL; | ||
| 305 | att = atts[value->value.enumerated.item[0]]; | ||
| 306 | mutex_lock(&chip->mutex); | ||
| 307 | changed = att != data->hp_vol_att; | ||
| 308 | if (changed) { | ||
| 309 | data->hp_vol_att = att; | ||
| 310 | if (data->output_sel) { | ||
| 311 | cs4245_write_cached(chip, CS4245_DAC_A_CTRL, att); | ||
| 312 | cs4245_write_cached(chip, CS4245_DAC_B_CTRL, att); | ||
| 313 | } | ||
| 314 | } | ||
| 315 | mutex_unlock(&chip->mutex); | ||
| 316 | return changed; | ||
| 317 | } | ||
| 318 | |||
| 319 | static int input_vol_info(struct snd_kcontrol *ctl, | ||
| 320 | struct snd_ctl_elem_info *info) | ||
| 321 | { | ||
| 322 | info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
| 323 | info->count = 2; | ||
| 324 | info->value.integer.min = 2 * -12; | ||
| 325 | info->value.integer.max = 2 * 12; | ||
| 326 | return 0; | ||
| 327 | } | ||
| 328 | |||
| 329 | static int input_vol_get(struct snd_kcontrol *ctl, | ||
| 330 | struct snd_ctl_elem_value *value) | ||
| 331 | { | ||
| 332 | struct oxygen *chip = ctl->private_data; | ||
| 333 | struct dg *data = chip->model_data; | ||
| 334 | unsigned int idx = ctl->private_value; | ||
| 335 | |||
| 336 | mutex_lock(&chip->mutex); | ||
| 337 | value->value.integer.value[0] = data->input_vol[idx][0]; | ||
| 338 | value->value.integer.value[1] = data->input_vol[idx][1]; | ||
| 339 | mutex_unlock(&chip->mutex); | ||
| 340 | return 0; | ||
| 341 | } | ||
| 342 | |||
| 343 | static int input_vol_put(struct snd_kcontrol *ctl, | ||
| 344 | struct snd_ctl_elem_value *value) | ||
| 345 | { | ||
| 346 | struct oxygen *chip = ctl->private_data; | ||
| 347 | struct dg *data = chip->model_data; | ||
| 348 | unsigned int idx = ctl->private_value; | ||
| 349 | int changed = 0; | ||
| 350 | |||
| 351 | if (value->value.integer.value[0] < 2 * -12 || | ||
| 352 | value->value.integer.value[0] > 2 * 12 || | ||
| 353 | value->value.integer.value[1] < 2 * -12 || | ||
| 354 | value->value.integer.value[1] > 2 * 12) | ||
| 355 | return -EINVAL; | ||
| 356 | mutex_lock(&chip->mutex); | ||
| 357 | changed = data->input_vol[idx][0] != value->value.integer.value[0] || | ||
| 358 | data->input_vol[idx][1] != value->value.integer.value[1]; | ||
| 359 | if (changed) { | ||
| 360 | data->input_vol[idx][0] = value->value.integer.value[0]; | ||
| 361 | data->input_vol[idx][1] = value->value.integer.value[1]; | ||
| 362 | if (idx == data->input_sel) { | ||
| 363 | cs4245_write_cached(chip, CS4245_PGA_A_CTRL, | ||
| 364 | data->input_vol[idx][0]); | ||
| 365 | cs4245_write_cached(chip, CS4245_PGA_B_CTRL, | ||
| 366 | data->input_vol[idx][1]); | ||
| 367 | } | ||
| 368 | } | ||
| 369 | mutex_unlock(&chip->mutex); | ||
| 370 | return changed; | ||
| 371 | } | ||
| 372 | |||
| 373 | static DECLARE_TLV_DB_SCALE(cs4245_pga_db_scale, -1200, 50, 0); | ||
| 374 | |||
| 375 | static int input_sel_info(struct snd_kcontrol *ctl, | ||
| 376 | struct snd_ctl_elem_info *info) | ||
| 377 | { | ||
| 378 | static const char *const names[4] = { | ||
| 379 | "Mic", "Aux", "Front Mic", "Line" | ||
| 380 | }; | ||
| 381 | |||
| 382 | return snd_ctl_enum_info(info, 1, 4, names); | ||
| 383 | } | ||
| 384 | |||
| 385 | static int input_sel_get(struct snd_kcontrol *ctl, | ||
| 386 | struct snd_ctl_elem_value *value) | ||
| 387 | { | ||
| 388 | struct oxygen *chip = ctl->private_data; | ||
| 389 | struct dg *data = chip->model_data; | ||
| 390 | |||
| 391 | mutex_lock(&chip->mutex); | ||
| 392 | value->value.enumerated.item[0] = data->input_sel; | ||
| 393 | mutex_unlock(&chip->mutex); | ||
| 394 | return 0; | ||
| 395 | } | ||
| 396 | |||
| 397 | static int input_sel_put(struct snd_kcontrol *ctl, | ||
| 398 | struct snd_ctl_elem_value *value) | ||
| 399 | { | ||
| 400 | static const u8 sel_values[4] = { | ||
| 401 | CS4245_SEL_MIC, | ||
| 402 | CS4245_SEL_INPUT_1, | ||
| 403 | CS4245_SEL_INPUT_2, | ||
| 404 | CS4245_SEL_INPUT_4 | ||
| 405 | }; | ||
| 406 | struct oxygen *chip = ctl->private_data; | ||
| 407 | struct dg *data = chip->model_data; | ||
| 408 | int changed; | ||
| 409 | |||
| 410 | if (value->value.enumerated.item[0] > 3) | ||
| 411 | return -EINVAL; | ||
| 412 | |||
| 413 | mutex_lock(&chip->mutex); | ||
| 414 | changed = value->value.enumerated.item[0] != data->input_sel; | ||
| 415 | if (changed) { | ||
| 416 | data->input_sel = value->value.enumerated.item[0]; | ||
| 417 | |||
| 418 | cs4245_write(chip, CS4245_ANALOG_IN, | ||
| 419 | (data->cs4245_regs[CS4245_ANALOG_IN] & | ||
| 420 | ~CS4245_SEL_MASK) | | ||
| 421 | sel_values[data->input_sel]); | ||
| 422 | |||
| 423 | cs4245_write_cached(chip, CS4245_PGA_A_CTRL, | ||
| 424 | data->input_vol[data->input_sel][0]); | ||
| 425 | cs4245_write_cached(chip, CS4245_PGA_B_CTRL, | ||
| 426 | data->input_vol[data->input_sel][1]); | ||
| 427 | |||
| 428 | oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, | ||
| 429 | data->input_sel ? 0 : GPIO_INPUT_ROUTE, | ||
| 430 | GPIO_INPUT_ROUTE); | ||
| 431 | } | ||
| 432 | mutex_unlock(&chip->mutex); | ||
| 433 | return changed; | ||
| 434 | } | ||
| 435 | |||
| 436 | static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) | ||
| 437 | { | ||
| 438 | static const char *const names[2] = { "Active", "Frozen" }; | ||
| 439 | |||
| 440 | return snd_ctl_enum_info(info, 1, 2, names); | ||
| 441 | } | ||
| 442 | |||
| 443 | static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) | ||
| 444 | { | ||
| 445 | struct oxygen *chip = ctl->private_data; | ||
| 446 | struct dg *data = chip->model_data; | ||
| 447 | |||
| 448 | value->value.enumerated.item[0] = | ||
| 449 | !!(data->cs4245_regs[CS4245_ADC_CTRL] & CS4245_HPF_FREEZE); | ||
| 450 | return 0; | ||
| 451 | } | ||
| 452 | |||
| 453 | static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) | ||
| 454 | { | ||
| 455 | struct oxygen *chip = ctl->private_data; | ||
| 456 | struct dg *data = chip->model_data; | ||
| 457 | u8 reg; | ||
| 458 | int changed; | ||
| 459 | |||
| 460 | mutex_lock(&chip->mutex); | ||
| 461 | reg = data->cs4245_regs[CS4245_ADC_CTRL] & ~CS4245_HPF_FREEZE; | ||
| 462 | if (value->value.enumerated.item[0]) | ||
| 463 | reg |= CS4245_HPF_FREEZE; | ||
| 464 | changed = reg != data->cs4245_regs[CS4245_ADC_CTRL]; | ||
| 465 | if (changed) | ||
| 466 | cs4245_write(chip, CS4245_ADC_CTRL, reg); | ||
| 467 | mutex_unlock(&chip->mutex); | ||
| 468 | return changed; | ||
| 469 | } | ||
| 470 | |||
| 471 | #define INPUT_VOLUME(xname, index) { \ | ||
| 472 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
| 473 | .name = xname, \ | ||
| 474 | .info = input_vol_info, \ | ||
| 475 | .get = input_vol_get, \ | ||
| 476 | .put = input_vol_put, \ | ||
| 477 | .tlv = { .p = cs4245_pga_db_scale }, \ | ||
| 478 | .private_value = index, \ | ||
| 479 | } | ||
| 480 | static const struct snd_kcontrol_new dg_controls[] = { | ||
| 481 | { | ||
| 482 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
| 483 | .name = "Analog Output Playback Enum", | ||
| 484 | .info = output_switch_info, | ||
| 485 | .get = output_switch_get, | ||
| 486 | .put = output_switch_put, | ||
| 487 | }, | ||
| 488 | { | ||
| 489 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
| 490 | .name = "Headphones Impedance Playback Enum", | ||
| 491 | .info = hp_volume_offset_info, | ||
| 492 | .get = hp_volume_offset_get, | ||
| 493 | .put = hp_volume_offset_put, | ||
| 494 | }, | ||
| 495 | INPUT_VOLUME("Mic Capture Volume", 0), | ||
| 496 | INPUT_VOLUME("Aux Capture Volume", 1), | ||
| 497 | INPUT_VOLUME("Front Mic Capture Volume", 2), | ||
| 498 | INPUT_VOLUME("Line Capture Volume", 3), | ||
| 499 | { | ||
| 500 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
| 501 | .name = "Capture Source", | ||
| 502 | .info = input_sel_info, | ||
| 503 | .get = input_sel_get, | ||
| 504 | .put = input_sel_put, | ||
| 505 | }, | ||
| 506 | { | ||
| 507 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
| 508 | .name = "ADC High-pass Filter Capture Enum", | ||
| 509 | .info = hpf_info, | ||
| 510 | .get = hpf_get, | ||
| 511 | .put = hpf_put, | ||
| 512 | }, | ||
| 513 | }; | ||
| 514 | |||
| 515 | static int dg_control_filter(struct snd_kcontrol_new *template) | ||
| 516 | { | ||
| 517 | if (!strncmp(template->name, "Master Playback ", 16)) | ||
| 518 | return 1; | ||
| 519 | return 0; | ||
| 520 | } | ||
| 521 | |||
| 522 | static int dg_mixer_init(struct oxygen *chip) | ||
| 523 | { | ||
| 524 | unsigned int i; | ||
| 525 | int err; | ||
| 526 | |||
| 527 | for (i = 0; i < ARRAY_SIZE(dg_controls); ++i) { | ||
| 528 | err = snd_ctl_add(chip->card, | ||
| 529 | snd_ctl_new1(&dg_controls[i], chip)); | ||
| 530 | if (err < 0) | ||
| 531 | return err; | ||
| 532 | } | ||
| 533 | return 0; | ||
| 534 | } | ||
| 535 | |||
| 536 | static void dump_cs4245_registers(struct oxygen *chip, | ||
| 537 | struct snd_info_buffer *buffer) | ||
| 538 | { | ||
| 539 | struct dg *data = chip->model_data; | ||
| 540 | unsigned int i; | ||
| 541 | |||
| 542 | snd_iprintf(buffer, "\nCS4245:"); | ||
| 543 | for (i = 1; i <= 0x10; ++i) | ||
| 544 | snd_iprintf(buffer, " %02x", data->cs4245_regs[i]); | ||
| 545 | snd_iprintf(buffer, "\n"); | ||
| 546 | } | ||
| 547 | |||
| 548 | struct oxygen_model model_xonar_dg = { | ||
| 549 | .shortname = "Xonar DG", | ||
| 550 | .longname = "C-Media Oxygen HD Audio", | ||
| 551 | .chip = "CMI8786", | ||
| 552 | .init = dg_init, | ||
| 553 | .control_filter = dg_control_filter, | ||
| 554 | .mixer_init = dg_mixer_init, | ||
| 555 | .cleanup = dg_cleanup, | ||
| 556 | .suspend = dg_suspend, | ||
| 557 | .resume = dg_resume, | ||
| 558 | .set_dac_params = set_cs4245_dac_params, | ||
| 559 | .set_adc_params = set_cs4245_adc_params, | ||
| 560 | .dump_registers = dump_cs4245_registers, | ||
| 561 | .model_data_size = sizeof(struct dg), | ||
| 562 | .device_config = PLAYBACK_0_TO_I2S | | ||
| 563 | PLAYBACK_1_TO_SPDIF | | ||
| 564 | CAPTURE_0_FROM_I2S_2, | ||
| 565 | .dac_channels_pcm = 6, | ||
| 566 | .dac_channels_mixer = 0, | ||
| 567 | .function_flags = OXYGEN_FUNCTION_SPI, | ||
| 568 | .dac_mclks = OXYGEN_MCLKS(256, 128, 128), | ||
| 569 | .adc_mclks = OXYGEN_MCLKS(256, 128, 128), | ||
| 570 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | ||
| 571 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | ||
| 572 | }; | ||
diff --git a/sound/pci/oxygen/xonar_dg.h b/sound/pci/oxygen/xonar_dg.h new file mode 100644 index 000000000000..5688d78609a9 --- /dev/null +++ b/sound/pci/oxygen/xonar_dg.h | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | #ifndef XONAR_DG_H_INCLUDED | ||
| 2 | #define XONAR_DG_H_INCLUDED | ||
| 3 | |||
| 4 | #include "oxygen.h" | ||
| 5 | |||
| 6 | extern struct oxygen_model model_xonar_dg; | ||
| 7 | |||
| 8 | #endif | ||
diff --git a/sound/pci/oxygen/xonar_hdmi.c b/sound/pci/oxygen/xonar_hdmi.c index b12db1f1cea9..136dac6a3964 100644 --- a/sound/pci/oxygen/xonar_hdmi.c +++ b/sound/pci/oxygen/xonar_hdmi.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * helper functions for HDMI models (Xonar HDAV1.3) | 2 | * helper functions for HDMI models (Xonar HDAV1.3/HDAV1.3 Slim) |
| 3 | * | 3 | * |
| 4 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> | 4 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> |
| 5 | * | 5 | * |
diff --git a/sound/pci/oxygen/xonar_lib.c b/sound/pci/oxygen/xonar_lib.c index b3ff71316653..0ebe7f5916f9 100644 --- a/sound/pci/oxygen/xonar_lib.c +++ b/sound/pci/oxygen/xonar_lib.c | |||
| @@ -104,9 +104,10 @@ int xonar_gpio_bit_switch_get(struct snd_kcontrol *ctl, | |||
| 104 | { | 104 | { |
| 105 | struct oxygen *chip = ctl->private_data; | 105 | struct oxygen *chip = ctl->private_data; |
| 106 | u16 bit = ctl->private_value; | 106 | u16 bit = ctl->private_value; |
| 107 | bool invert = ctl->private_value & XONAR_GPIO_BIT_INVERT; | ||
| 107 | 108 | ||
| 108 | value->value.integer.value[0] = | 109 | value->value.integer.value[0] = |
| 109 | !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & bit); | 110 | !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & bit) ^ invert; |
| 110 | return 0; | 111 | return 0; |
| 111 | } | 112 | } |
| 112 | 113 | ||
| @@ -115,12 +116,13 @@ int xonar_gpio_bit_switch_put(struct snd_kcontrol *ctl, | |||
| 115 | { | 116 | { |
| 116 | struct oxygen *chip = ctl->private_data; | 117 | struct oxygen *chip = ctl->private_data; |
| 117 | u16 bit = ctl->private_value; | 118 | u16 bit = ctl->private_value; |
| 119 | bool invert = ctl->private_value & XONAR_GPIO_BIT_INVERT; | ||
| 118 | u16 old_bits, new_bits; | 120 | u16 old_bits, new_bits; |
| 119 | int changed; | 121 | int changed; |
| 120 | 122 | ||
| 121 | spin_lock_irq(&chip->reg_lock); | 123 | spin_lock_irq(&chip->reg_lock); |
| 122 | old_bits = oxygen_read16(chip, OXYGEN_GPIO_DATA); | 124 | old_bits = oxygen_read16(chip, OXYGEN_GPIO_DATA); |
| 123 | if (value->value.integer.value[0]) | 125 | if (!!value->value.integer.value[0] ^ invert) |
| 124 | new_bits = old_bits | bit; | 126 | new_bits = old_bits | bit; |
| 125 | else | 127 | else |
| 126 | new_bits = old_bits & ~bit; | 128 | new_bits = old_bits & ~bit; |
diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c index d491fd6c0be2..54cad38ec30a 100644 --- a/sound/pci/oxygen/xonar_pcm179x.c +++ b/sound/pci/oxygen/xonar_pcm179x.c | |||
| @@ -22,20 +22,26 @@ | |||
| 22 | * | 22 | * |
| 23 | * CMI8788: | 23 | * CMI8788: |
| 24 | * | 24 | * |
| 25 | * SPI 0 -> 1st PCM1796 (front) | 25 | * SPI 0 -> 1st PCM1796 (front) |
| 26 | * SPI 1 -> 2nd PCM1796 (surround) | 26 | * SPI 1 -> 2nd PCM1796 (surround) |
| 27 | * SPI 2 -> 3rd PCM1796 (center/LFE) | 27 | * SPI 2 -> 3rd PCM1796 (center/LFE) |
| 28 | * SPI 4 -> 4th PCM1796 (back) | 28 | * SPI 4 -> 4th PCM1796 (back) |
| 29 | * | 29 | * |
| 30 | * GPIO 2 -> M0 of CS5381 | 30 | * GPIO 2 -> M0 of CS5381 |
| 31 | * GPIO 3 -> M1 of CS5381 | 31 | * GPIO 3 -> M1 of CS5381 |
| 32 | * GPIO 5 <- external power present (D2X only) | 32 | * GPIO 5 <- external power present (D2X only) |
| 33 | * GPIO 7 -> ALT | 33 | * GPIO 7 -> ALT |
| 34 | * GPIO 8 -> enable output to speakers | 34 | * GPIO 8 -> enable output to speakers |
| 35 | * | 35 | * |
| 36 | * CM9780: | 36 | * CM9780: |
| 37 | * | 37 | * |
| 38 | * GPO 0 -> route line-in (0) or AC97 output (1) to CS5381 input | 38 | * LINE_OUT -> input of ADC |
| 39 | * | ||
| 40 | * AUX_IN <- aux | ||
| 41 | * VIDEO_IN <- CD | ||
| 42 | * FMIC_IN <- mic | ||
| 43 | * | ||
| 44 | * GPO 0 -> route line-in (0) or AC97 output (1) to CS5381 input | ||
| 39 | */ | 45 | */ |
| 40 | 46 | ||
| 41 | /* | 47 | /* |
| @@ -44,52 +50,53 @@ | |||
| 44 | * | 50 | * |
| 45 | * CMI8788: | 51 | * CMI8788: |
| 46 | * | 52 | * |
| 47 | * I²C <-> PCM1796 (front) | 53 | * I²C <-> PCM1796 (addr 1001100) (front) |
| 48 | * | 54 | * |
| 49 | * GPI 0 <- external power present | 55 | * GPI 0 <- external power present |
| 50 | * | 56 | * |
| 51 | * GPIO 0 -> enable output to speakers | 57 | * GPIO 0 -> enable HDMI (0) or speaker (1) output |
| 52 | * GPIO 2 -> M0 of CS5381 | 58 | * GPIO 2 -> M0 of CS5381 |
| 53 | * GPIO 3 -> M1 of CS5381 | 59 | * GPIO 3 -> M1 of CS5381 |
| 54 | * GPIO 8 -> route input jack to line-in (0) or mic-in (1) | 60 | * GPIO 4 <- daughterboard detection |
| 61 | * GPIO 5 <- daughterboard detection | ||
| 62 | * GPIO 6 -> ? | ||
| 63 | * GPIO 7 -> ? | ||
| 64 | * GPIO 8 -> route input jack to line-in (0) or mic-in (1) | ||
| 55 | * | 65 | * |
| 56 | * TXD -> HDMI controller | 66 | * UART <-> HDMI controller |
| 57 | * RXD <- HDMI controller | ||
| 58 | * | ||
| 59 | * PCM1796 front: AD1,0 <- 0,0 | ||
| 60 | * | 67 | * |
| 61 | * CM9780: | 68 | * CM9780: |
| 62 | * | 69 | * |
| 63 | * GPO 0 -> route line-in (0) or AC97 output (1) to CS5381 input | 70 | * LINE_OUT -> input of ADC |
| 71 | * | ||
| 72 | * AUX_IN <- aux | ||
| 73 | * CD_IN <- CD | ||
| 74 | * MIC_IN <- mic | ||
| 75 | * | ||
| 76 | * GPO 0 -> route line-in (0) or AC97 output (1) to CS5381 input | ||
| 64 | * | 77 | * |
| 65 | * no daughterboard | 78 | * no daughterboard |
| 66 | * ---------------- | 79 | * ---------------- |
| 67 | * | 80 | * |
| 68 | * GPIO 4 <- 1 | 81 | * GPIO 4 <- 1 |
| 69 | * | 82 | * |
| 70 | * H6 daughterboard | 83 | * H6 daughterboard |
| 71 | * ---------------- | 84 | * ---------------- |
| 72 | * | 85 | * |
| 73 | * GPIO 4 <- 0 | 86 | * GPIO 4 <- 0 |
| 74 | * GPIO 5 <- 0 | 87 | * GPIO 5 <- 0 |
| 75 | * | ||
| 76 | * I²C <-> PCM1796 (surround) | ||
| 77 | * <-> PCM1796 (center/LFE) | ||
| 78 | * <-> PCM1796 (back) | ||
| 79 | * | 88 | * |
| 80 | * PCM1796 surround: AD1,0 <- 0,1 | 89 | * I²C <-> PCM1796 (addr 1001101) (surround) |
| 81 | * PCM1796 center/LFE: AD1,0 <- 1,0 | 90 | * <-> PCM1796 (addr 1001110) (center/LFE) |
| 82 | * PCM1796 back: AD1,0 <- 1,1 | 91 | * <-> PCM1796 (addr 1001111) (back) |
| 83 | * | 92 | * |
| 84 | * unknown daughterboard | 93 | * unknown daughterboard |
| 85 | * --------------------- | 94 | * --------------------- |
| 86 | * | 95 | * |
| 87 | * GPIO 4 <- 0 | 96 | * GPIO 4 <- 0 |
| 88 | * GPIO 5 <- 1 | 97 | * GPIO 5 <- 1 |
| 89 | * | ||
| 90 | * I²C <-> CS4362A (surround, center/LFE, back) | ||
| 91 | * | 98 | * |
| 92 | * CS4362A: AD0 <- 0 | 99 | * I²C <-> CS4362A (addr 0011000) (surround, center/LFE, back) |
| 93 | */ | 100 | */ |
| 94 | 101 | ||
| 95 | /* | 102 | /* |
| @@ -98,32 +105,35 @@ | |||
| 98 | * | 105 | * |
| 99 | * CMI8788: | 106 | * CMI8788: |
| 100 | * | 107 | * |
| 101 | * I²C <-> PCM1792A | 108 | * I²C <-> PCM1792A (addr 1001100) |
| 102 | * <-> CS2000 (ST only) | 109 | * <-> CS2000 (addr 1001110) (ST only) |
| 103 | * | 110 | * |
| 104 | * ADC1 MCLK -> REF_CLK of CS2000 (ST only) | 111 | * ADC1 MCLK -> REF_CLK of CS2000 (ST only) |
| 105 | * | 112 | * |
| 106 | * GPI 0 <- external power present (STX only) | 113 | * GPI 0 <- external power present (STX only) |
| 107 | * | 114 | * |
| 108 | * GPIO 0 -> enable output to speakers | 115 | * GPIO 0 -> enable output to speakers |
| 109 | * GPIO 1 -> route HP to front panel (0) or rear jack (1) | 116 | * GPIO 1 -> route HP to front panel (0) or rear jack (1) |
| 110 | * GPIO 2 -> M0 of CS5381 | 117 | * GPIO 2 -> M0 of CS5381 |
| 111 | * GPIO 3 -> M1 of CS5381 | 118 | * GPIO 3 -> M1 of CS5381 |
| 112 | * GPIO 7 -> route output to speaker jacks (0) or HP (1) | 119 | * GPIO 4 <- daughterboard detection |
| 113 | * GPIO 8 -> route input jack to line-in (0) or mic-in (1) | 120 | * GPIO 5 <- daughterboard detection |
| 121 | * GPIO 6 -> ? | ||
| 122 | * GPIO 7 -> route output to speaker jacks (0) or HP (1) | ||
| 123 | * GPIO 8 -> route input jack to line-in (0) or mic-in (1) | ||
| 114 | * | 124 | * |
| 115 | * PCM1792A: | 125 | * PCM1792A: |
| 116 | * | 126 | * |
| 117 | * AD1,0 <- 0,0 | 127 | * SCK <- CLK_OUT of CS2000 (ST only) |
| 118 | * SCK <- CLK_OUT of CS2000 (ST only) | ||
| 119 | * | 128 | * |
| 120 | * CS2000: | 129 | * CM9780: |
| 121 | * | 130 | * |
| 122 | * AD0 <- 0 | 131 | * LINE_OUT -> input of ADC |
| 123 | * | 132 | * |
| 124 | * CM9780: | 133 | * AUX_IN <- aux |
| 134 | * MIC_IN <- mic | ||
| 125 | * | 135 | * |
| 126 | * GPO 0 -> route line-in (0) or AC97 output (1) to CS5381 input | 136 | * GPO 0 -> route line-in (0) or AC97 output (1) to CS5381 input |
| 127 | * | 137 | * |
| 128 | * H6 daughterboard | 138 | * H6 daughterboard |
| 129 | * ---------------- | 139 | * ---------------- |
| @@ -133,15 +143,39 @@ | |||
| 133 | */ | 143 | */ |
| 134 | 144 | ||
| 135 | /* | 145 | /* |
| 136 | * Xonar HDAV1.3 Slim | 146 | * Xonar Xense |
| 137 | * ------------------ | 147 | * ----------- |
| 138 | * | 148 | * |
| 139 | * CMI8788: | 149 | * CMI8788: |
| 140 | * | 150 | * |
| 141 | * GPIO 1 -> enable output | 151 | * I²C <-> PCM1796 (addr 1001100) (front) |
| 152 | * <-> CS4362A (addr 0011000) (surround, center/LFE, back) | ||
| 153 | * <-> CS2000 (addr 1001110) | ||
| 154 | * | ||
| 155 | * ADC1 MCLK -> REF_CLK of CS2000 | ||
| 156 | * | ||
| 157 | * GPI 0 <- external power present | ||
| 158 | * | ||
| 159 | * GPIO 0 -> enable output | ||
| 160 | * GPIO 1 -> route HP to front panel (0) or rear jack (1) | ||
| 161 | * GPIO 2 -> M0 of CS5381 | ||
| 162 | * GPIO 3 -> M1 of CS5381 | ||
| 163 | * GPIO 4 -> enable output | ||
| 164 | * GPIO 5 -> enable output | ||
| 165 | * GPIO 6 -> ? | ||
| 166 | * GPIO 7 -> route output to HP (0) or speaker (1) | ||
| 167 | * GPIO 8 -> route input jack to mic-in (0) or line-in (1) | ||
| 142 | * | 168 | * |
| 143 | * TXD -> HDMI controller | 169 | * CM9780: |
| 144 | * RXD <- HDMI controller | 170 | * |
| 171 | * LINE_OUT -> input of ADC | ||
| 172 | * | ||
| 173 | * AUX_IN <- aux | ||
| 174 | * VIDEO_IN <- ? | ||
| 175 | * FMIC_IN <- mic | ||
| 176 | * | ||
| 177 | * GPO 0 -> route line-in (0) or AC97 output (1) to CS5381 input | ||
| 178 | * GPO 1 -> route mic-in from input jack (0) or front panel header (1) | ||
| 145 | */ | 179 | */ |
| 146 | 180 | ||
| 147 | #include <linux/pci.h> | 181 | #include <linux/pci.h> |
| @@ -150,6 +184,7 @@ | |||
| 150 | #include <sound/ac97_codec.h> | 184 | #include <sound/ac97_codec.h> |
| 151 | #include <sound/control.h> | 185 | #include <sound/control.h> |
| 152 | #include <sound/core.h> | 186 | #include <sound/core.h> |
| 187 | #include <sound/info.h> | ||
| 153 | #include <sound/pcm.h> | 188 | #include <sound/pcm.h> |
| 154 | #include <sound/pcm_params.h> | 189 | #include <sound/pcm_params.h> |
| 155 | #include <sound/tlv.h> | 190 | #include <sound/tlv.h> |
| @@ -167,12 +202,14 @@ | |||
| 167 | #define GPIO_INPUT_ROUTE 0x0100 | 202 | #define GPIO_INPUT_ROUTE 0x0100 |
| 168 | 203 | ||
| 169 | #define GPIO_HDAV_OUTPUT_ENABLE 0x0001 | 204 | #define GPIO_HDAV_OUTPUT_ENABLE 0x0001 |
| 205 | #define GPIO_HDAV_MAGIC 0x00c0 | ||
| 170 | 206 | ||
| 171 | #define GPIO_DB_MASK 0x0030 | 207 | #define GPIO_DB_MASK 0x0030 |
| 172 | #define GPIO_DB_H6 0x0000 | 208 | #define GPIO_DB_H6 0x0000 |
| 173 | 209 | ||
| 174 | #define GPIO_ST_OUTPUT_ENABLE 0x0001 | 210 | #define GPIO_ST_OUTPUT_ENABLE 0x0001 |
| 175 | #define GPIO_ST_HP_REAR 0x0002 | 211 | #define GPIO_ST_HP_REAR 0x0002 |
| 212 | #define GPIO_ST_MAGIC 0x0040 | ||
| 176 | #define GPIO_ST_HP 0x0080 | 213 | #define GPIO_ST_HP 0x0080 |
| 177 | 214 | ||
| 178 | #define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ii, /W=0 */ | 215 | #define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ii, /W=0 */ |
| @@ -186,11 +223,12 @@ struct xonar_pcm179x { | |||
| 186 | unsigned int dacs; | 223 | unsigned int dacs; |
| 187 | u8 pcm1796_regs[4][5]; | 224 | u8 pcm1796_regs[4][5]; |
| 188 | unsigned int current_rate; | 225 | unsigned int current_rate; |
| 189 | bool os_128; | 226 | bool h6; |
| 190 | bool hp_active; | 227 | bool hp_active; |
| 191 | s8 hp_gain_offset; | 228 | s8 hp_gain_offset; |
| 192 | bool has_cs2000; | 229 | bool has_cs2000; |
| 193 | u8 cs2000_fun_cfg_1; | 230 | u8 cs2000_regs[0x1f]; |
| 231 | bool broken_i2c; | ||
| 194 | }; | 232 | }; |
| 195 | 233 | ||
| 196 | struct xonar_hdav { | 234 | struct xonar_hdav { |
| @@ -249,16 +287,14 @@ static void cs2000_write(struct oxygen *chip, u8 reg, u8 value) | |||
| 249 | struct xonar_pcm179x *data = chip->model_data; | 287 | struct xonar_pcm179x *data = chip->model_data; |
| 250 | 288 | ||
| 251 | oxygen_write_i2c(chip, I2C_DEVICE_CS2000, reg, value); | 289 | oxygen_write_i2c(chip, I2C_DEVICE_CS2000, reg, value); |
| 252 | if (reg == CS2000_FUN_CFG_1) | 290 | data->cs2000_regs[reg] = value; |
| 253 | data->cs2000_fun_cfg_1 = value; | ||
| 254 | } | 291 | } |
| 255 | 292 | ||
| 256 | static void cs2000_write_cached(struct oxygen *chip, u8 reg, u8 value) | 293 | static void cs2000_write_cached(struct oxygen *chip, u8 reg, u8 value) |
| 257 | { | 294 | { |
| 258 | struct xonar_pcm179x *data = chip->model_data; | 295 | struct xonar_pcm179x *data = chip->model_data; |
| 259 | 296 | ||
| 260 | if (reg != CS2000_FUN_CFG_1 || | 297 | if (value != data->cs2000_regs[reg]) |
| 261 | value != data->cs2000_fun_cfg_1) | ||
| 262 | cs2000_write(chip, reg, value); | 298 | cs2000_write(chip, reg, value); |
| 263 | } | 299 | } |
| 264 | 300 | ||
| @@ -268,6 +304,7 @@ static void pcm1796_registers_init(struct oxygen *chip) | |||
| 268 | unsigned int i; | 304 | unsigned int i; |
| 269 | s8 gain_offset; | 305 | s8 gain_offset; |
| 270 | 306 | ||
| 307 | msleep(1); | ||
| 271 | gain_offset = data->hp_active ? data->hp_gain_offset : 0; | 308 | gain_offset = data->hp_active ? data->hp_gain_offset : 0; |
| 272 | for (i = 0; i < data->dacs; ++i) { | 309 | for (i = 0; i < data->dacs; ++i) { |
| 273 | /* set ATLD before ATL/ATR */ | 310 | /* set ATLD before ATL/ATR */ |
| @@ -282,6 +319,7 @@ static void pcm1796_registers_init(struct oxygen *chip) | |||
| 282 | pcm1796_write(chip, i, 20, | 319 | pcm1796_write(chip, i, 20, |
| 283 | data->pcm1796_regs[0][20 - PCM1796_REG_BASE]); | 320 | data->pcm1796_regs[0][20 - PCM1796_REG_BASE]); |
| 284 | pcm1796_write(chip, i, 21, 0); | 321 | pcm1796_write(chip, i, 21, 0); |
| 322 | gain_offset = 0; | ||
| 285 | } | 323 | } |
| 286 | } | 324 | } |
| 287 | 325 | ||
| @@ -290,10 +328,11 @@ static void pcm1796_init(struct oxygen *chip) | |||
| 290 | struct xonar_pcm179x *data = chip->model_data; | 328 | struct xonar_pcm179x *data = chip->model_data; |
| 291 | 329 | ||
| 292 | data->pcm1796_regs[0][18 - PCM1796_REG_BASE] = PCM1796_MUTE | | 330 | data->pcm1796_regs[0][18 - PCM1796_REG_BASE] = PCM1796_MUTE | |
| 293 | PCM1796_DMF_DISABLED | PCM1796_FMT_24_LJUST | PCM1796_ATLD; | 331 | PCM1796_DMF_DISABLED | PCM1796_FMT_24_I2S | PCM1796_ATLD; |
| 294 | data->pcm1796_regs[0][19 - PCM1796_REG_BASE] = | 332 | data->pcm1796_regs[0][19 - PCM1796_REG_BASE] = |
| 295 | PCM1796_FLT_SHARP | PCM1796_ATS_1; | 333 | PCM1796_FLT_SHARP | PCM1796_ATS_1; |
| 296 | data->pcm1796_regs[0][20 - PCM1796_REG_BASE] = PCM1796_OS_64; | 334 | data->pcm1796_regs[0][20 - PCM1796_REG_BASE] = |
| 335 | data->h6 ? PCM1796_OS_64 : PCM1796_OS_128; | ||
| 297 | pcm1796_registers_init(chip); | 336 | pcm1796_registers_init(chip); |
| 298 | data->current_rate = 48000; | 337 | data->current_rate = 48000; |
| 299 | } | 338 | } |
| @@ -339,18 +378,20 @@ static void xonar_hdav_init(struct oxygen *chip) | |||
| 339 | oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS, | 378 | oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS, |
| 340 | OXYGEN_2WIRE_LENGTH_8 | | 379 | OXYGEN_2WIRE_LENGTH_8 | |
| 341 | OXYGEN_2WIRE_INTERRUPT_MASK | | 380 | OXYGEN_2WIRE_INTERRUPT_MASK | |
| 342 | OXYGEN_2WIRE_SPEED_FAST); | 381 | OXYGEN_2WIRE_SPEED_STANDARD); |
| 343 | 382 | ||
| 344 | data->pcm179x.generic.anti_pop_delay = 100; | 383 | data->pcm179x.generic.anti_pop_delay = 100; |
| 345 | data->pcm179x.generic.output_enable_bit = GPIO_HDAV_OUTPUT_ENABLE; | 384 | data->pcm179x.generic.output_enable_bit = GPIO_HDAV_OUTPUT_ENABLE; |
| 346 | data->pcm179x.generic.ext_power_reg = OXYGEN_GPI_DATA; | 385 | data->pcm179x.generic.ext_power_reg = OXYGEN_GPI_DATA; |
| 347 | data->pcm179x.generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; | 386 | data->pcm179x.generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; |
| 348 | data->pcm179x.generic.ext_power_bit = GPI_EXT_POWER; | 387 | data->pcm179x.generic.ext_power_bit = GPI_EXT_POWER; |
| 349 | data->pcm179x.dacs = chip->model.private_data ? 4 : 1; | 388 | data->pcm179x.dacs = chip->model.dac_channels_mixer / 2; |
| 389 | data->pcm179x.h6 = chip->model.dac_channels_mixer > 2; | ||
| 350 | 390 | ||
| 351 | pcm1796_init(chip); | 391 | pcm1796_init(chip); |
| 352 | 392 | ||
| 353 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_INPUT_ROUTE); | 393 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, |
| 394 | GPIO_HDAV_MAGIC | GPIO_INPUT_ROUTE); | ||
| 354 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_INPUT_ROUTE); | 395 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_INPUT_ROUTE); |
| 355 | 396 | ||
| 356 | xonar_init_cs53x1(chip); | 397 | xonar_init_cs53x1(chip); |
| @@ -367,7 +408,7 @@ static void xonar_st_init_i2c(struct oxygen *chip) | |||
| 367 | oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS, | 408 | oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS, |
| 368 | OXYGEN_2WIRE_LENGTH_8 | | 409 | OXYGEN_2WIRE_LENGTH_8 | |
| 369 | OXYGEN_2WIRE_INTERRUPT_MASK | | 410 | OXYGEN_2WIRE_INTERRUPT_MASK | |
| 370 | OXYGEN_2WIRE_SPEED_FAST); | 411 | OXYGEN_2WIRE_SPEED_STANDARD); |
| 371 | } | 412 | } |
| 372 | 413 | ||
| 373 | static void xonar_st_init_common(struct oxygen *chip) | 414 | static void xonar_st_init_common(struct oxygen *chip) |
| @@ -375,13 +416,14 @@ static void xonar_st_init_common(struct oxygen *chip) | |||
| 375 | struct xonar_pcm179x *data = chip->model_data; | 416 | struct xonar_pcm179x *data = chip->model_data; |
| 376 | 417 | ||
| 377 | data->generic.output_enable_bit = GPIO_ST_OUTPUT_ENABLE; | 418 | data->generic.output_enable_bit = GPIO_ST_OUTPUT_ENABLE; |
| 378 | data->dacs = chip->model.private_data ? 4 : 1; | 419 | data->dacs = chip->model.dac_channels_mixer / 2; |
| 379 | data->hp_gain_offset = 2*-18; | 420 | data->hp_gain_offset = 2*-18; |
| 380 | 421 | ||
| 381 | pcm1796_init(chip); | 422 | pcm1796_init(chip); |
| 382 | 423 | ||
| 383 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, | 424 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, |
| 384 | GPIO_INPUT_ROUTE | GPIO_ST_HP_REAR | GPIO_ST_HP); | 425 | GPIO_INPUT_ROUTE | GPIO_ST_HP_REAR | |
| 426 | GPIO_ST_MAGIC | GPIO_ST_HP); | ||
| 385 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, | 427 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, |
| 386 | GPIO_INPUT_ROUTE | GPIO_ST_HP_REAR | GPIO_ST_HP); | 428 | GPIO_INPUT_ROUTE | GPIO_ST_HP_REAR | GPIO_ST_HP); |
| 387 | 429 | ||
| @@ -410,9 +452,11 @@ static void cs2000_registers_init(struct oxygen *chip) | |||
| 410 | cs2000_write(chip, CS2000_RATIO_0 + 1, 0x10); | 452 | cs2000_write(chip, CS2000_RATIO_0 + 1, 0x10); |
| 411 | cs2000_write(chip, CS2000_RATIO_0 + 2, 0x00); | 453 | cs2000_write(chip, CS2000_RATIO_0 + 2, 0x00); |
| 412 | cs2000_write(chip, CS2000_RATIO_0 + 3, 0x00); | 454 | cs2000_write(chip, CS2000_RATIO_0 + 3, 0x00); |
| 413 | cs2000_write(chip, CS2000_FUN_CFG_1, data->cs2000_fun_cfg_1); | 455 | cs2000_write(chip, CS2000_FUN_CFG_1, |
| 456 | data->cs2000_regs[CS2000_FUN_CFG_1]); | ||
| 414 | cs2000_write(chip, CS2000_FUN_CFG_2, 0); | 457 | cs2000_write(chip, CS2000_FUN_CFG_2, 0); |
| 415 | cs2000_write(chip, CS2000_GLOBAL_CFG, CS2000_EN_DEV_CFG_2); | 458 | cs2000_write(chip, CS2000_GLOBAL_CFG, CS2000_EN_DEV_CFG_2); |
| 459 | msleep(3); /* PLL lock delay */ | ||
| 416 | } | 460 | } |
| 417 | 461 | ||
| 418 | static void xonar_st_init(struct oxygen *chip) | 462 | static void xonar_st_init(struct oxygen *chip) |
| @@ -420,13 +464,18 @@ static void xonar_st_init(struct oxygen *chip) | |||
| 420 | struct xonar_pcm179x *data = chip->model_data; | 464 | struct xonar_pcm179x *data = chip->model_data; |
| 421 | 465 | ||
| 422 | data->generic.anti_pop_delay = 100; | 466 | data->generic.anti_pop_delay = 100; |
| 467 | data->h6 = chip->model.dac_channels_mixer > 2; | ||
| 423 | data->has_cs2000 = 1; | 468 | data->has_cs2000 = 1; |
| 424 | data->cs2000_fun_cfg_1 = CS2000_REF_CLK_DIV_1; | 469 | data->cs2000_regs[CS2000_FUN_CFG_1] = CS2000_REF_CLK_DIV_1; |
| 470 | data->broken_i2c = true; | ||
| 425 | 471 | ||
| 426 | oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, | 472 | oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, |
| 427 | OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_I2S | | 473 | OXYGEN_RATE_48000 | |
| 428 | OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 | | 474 | OXYGEN_I2S_FORMAT_I2S | |
| 429 | OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); | 475 | OXYGEN_I2S_MCLK(data->h6 ? MCLK_256 : MCLK_512) | |
| 476 | OXYGEN_I2S_BITS_16 | | ||
| 477 | OXYGEN_I2S_MASTER | | ||
| 478 | OXYGEN_I2S_BCLK_64); | ||
| 430 | 479 | ||
| 431 | xonar_st_init_i2c(chip); | 480 | xonar_st_init_i2c(chip); |
| 432 | cs2000_registers_init(chip); | 481 | cs2000_registers_init(chip); |
| @@ -507,44 +556,16 @@ static void xonar_st_resume(struct oxygen *chip) | |||
| 507 | xonar_stx_resume(chip); | 556 | xonar_stx_resume(chip); |
| 508 | } | 557 | } |
| 509 | 558 | ||
| 510 | static unsigned int mclk_from_rate(struct oxygen *chip, unsigned int rate) | ||
| 511 | { | ||
| 512 | struct xonar_pcm179x *data = chip->model_data; | ||
| 513 | |||
| 514 | if (rate <= 32000) | ||
| 515 | return OXYGEN_I2S_MCLK_512; | ||
| 516 | else if (rate <= 48000 && data->os_128) | ||
| 517 | return OXYGEN_I2S_MCLK_512; | ||
| 518 | else if (rate <= 96000) | ||
| 519 | return OXYGEN_I2S_MCLK_256; | ||
| 520 | else | ||
| 521 | return OXYGEN_I2S_MCLK_128; | ||
| 522 | } | ||
| 523 | |||
| 524 | static unsigned int get_pcm1796_i2s_mclk(struct oxygen *chip, | ||
| 525 | unsigned int channel, | ||
| 526 | struct snd_pcm_hw_params *params) | ||
| 527 | { | ||
| 528 | if (channel == PCM_MULTICH) | ||
| 529 | return mclk_from_rate(chip, params_rate(params)); | ||
| 530 | else | ||
| 531 | return oxygen_default_i2s_mclk(chip, channel, params); | ||
| 532 | } | ||
| 533 | |||
| 534 | static void update_pcm1796_oversampling(struct oxygen *chip) | 559 | static void update_pcm1796_oversampling(struct oxygen *chip) |
| 535 | { | 560 | { |
| 536 | struct xonar_pcm179x *data = chip->model_data; | 561 | struct xonar_pcm179x *data = chip->model_data; |
| 537 | unsigned int i; | 562 | unsigned int i; |
| 538 | u8 reg; | 563 | u8 reg; |
| 539 | 564 | ||
| 540 | if (data->current_rate <= 32000) | 565 | if (data->current_rate <= 48000 && !data->h6) |
| 541 | reg = PCM1796_OS_128; | 566 | reg = PCM1796_OS_128; |
| 542 | else if (data->current_rate <= 48000 && data->os_128) | ||
| 543 | reg = PCM1796_OS_128; | ||
| 544 | else if (data->current_rate <= 96000 || data->os_128) | ||
| 545 | reg = PCM1796_OS_64; | ||
| 546 | else | 567 | else |
| 547 | reg = PCM1796_OS_32; | 568 | reg = PCM1796_OS_64; |
| 548 | for (i = 0; i < data->dacs; ++i) | 569 | for (i = 0; i < data->dacs; ++i) |
| 549 | pcm1796_write_cached(chip, i, 20, reg); | 570 | pcm1796_write_cached(chip, i, 20, reg); |
| 550 | } | 571 | } |
| @@ -554,6 +575,7 @@ static void set_pcm1796_params(struct oxygen *chip, | |||
| 554 | { | 575 | { |
| 555 | struct xonar_pcm179x *data = chip->model_data; | 576 | struct xonar_pcm179x *data = chip->model_data; |
| 556 | 577 | ||
| 578 | msleep(1); | ||
| 557 | data->current_rate = params_rate(params); | 579 | data->current_rate = params_rate(params); |
| 558 | update_pcm1796_oversampling(chip); | 580 | update_pcm1796_oversampling(chip); |
| 559 | } | 581 | } |
| @@ -570,6 +592,7 @@ static void update_pcm1796_volume(struct oxygen *chip) | |||
| 570 | + gain_offset); | 592 | + gain_offset); |
| 571 | pcm1796_write_cached(chip, i, 17, chip->dac_volume[i * 2 + 1] | 593 | pcm1796_write_cached(chip, i, 17, chip->dac_volume[i * 2 + 1] |
| 572 | + gain_offset); | 594 | + gain_offset); |
| 595 | gain_offset = 0; | ||
| 573 | } | 596 | } |
| 574 | } | 597 | } |
| 575 | 598 | ||
| @@ -579,7 +602,7 @@ static void update_pcm1796_mute(struct oxygen *chip) | |||
| 579 | unsigned int i; | 602 | unsigned int i; |
| 580 | u8 value; | 603 | u8 value; |
| 581 | 604 | ||
| 582 | value = PCM1796_DMF_DISABLED | PCM1796_FMT_24_LJUST | PCM1796_ATLD; | 605 | value = PCM1796_DMF_DISABLED | PCM1796_FMT_24_I2S | PCM1796_ATLD; |
| 583 | if (chip->dac_mute) | 606 | if (chip->dac_mute) |
| 584 | value |= PCM1796_MUTE; | 607 | value |= PCM1796_MUTE; |
| 585 | for (i = 0; i < data->dacs; ++i) | 608 | for (i = 0; i < data->dacs; ++i) |
| @@ -592,45 +615,35 @@ static void update_cs2000_rate(struct oxygen *chip, unsigned int rate) | |||
| 592 | u8 rate_mclk, reg; | 615 | u8 rate_mclk, reg; |
| 593 | 616 | ||
| 594 | switch (rate) { | 617 | switch (rate) { |
| 595 | /* XXX Why is the I2S A MCLK half the actual I2S MCLK? */ | ||
| 596 | case 32000: | 618 | case 32000: |
| 597 | rate_mclk = OXYGEN_RATE_32000 | OXYGEN_I2S_MCLK_256; | ||
| 598 | break; | ||
| 599 | case 44100: | ||
| 600 | if (data->os_128) | ||
| 601 | rate_mclk = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_256; | ||
| 602 | else | ||
| 603 | rate_mclk = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_128; | ||
| 604 | break; | ||
| 605 | default: /* 48000 */ | ||
| 606 | if (data->os_128) | ||
| 607 | rate_mclk = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_256; | ||
| 608 | else | ||
| 609 | rate_mclk = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_128; | ||
| 610 | break; | ||
| 611 | case 64000: | 619 | case 64000: |
| 612 | rate_mclk = OXYGEN_RATE_32000 | OXYGEN_I2S_MCLK_256; | 620 | rate_mclk = OXYGEN_RATE_32000; |
| 613 | break; | 621 | break; |
| 622 | case 44100: | ||
| 614 | case 88200: | 623 | case 88200: |
| 615 | rate_mclk = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_256; | ||
| 616 | break; | ||
| 617 | case 96000: | ||
| 618 | rate_mclk = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_256; | ||
| 619 | break; | ||
| 620 | case 176400: | 624 | case 176400: |
| 621 | rate_mclk = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_256; | 625 | rate_mclk = OXYGEN_RATE_44100; |
| 622 | break; | 626 | break; |
| 627 | default: | ||
| 628 | case 48000: | ||
| 629 | case 96000: | ||
| 623 | case 192000: | 630 | case 192000: |
| 624 | rate_mclk = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_256; | 631 | rate_mclk = OXYGEN_RATE_48000; |
| 625 | break; | 632 | break; |
| 626 | } | 633 | } |
| 627 | oxygen_write16_masked(chip, OXYGEN_I2S_A_FORMAT, rate_mclk, | 634 | |
| 628 | OXYGEN_I2S_RATE_MASK | OXYGEN_I2S_MCLK_MASK); | 635 | if (rate <= 96000 && (rate > 48000 || data->h6)) { |
| 629 | if ((rate_mclk & OXYGEN_I2S_MCLK_MASK) <= OXYGEN_I2S_MCLK_128) | 636 | rate_mclk |= OXYGEN_I2S_MCLK(MCLK_256); |
| 630 | reg = CS2000_REF_CLK_DIV_1; | 637 | reg = CS2000_REF_CLK_DIV_1; |
| 631 | else | 638 | } else { |
| 639 | rate_mclk |= OXYGEN_I2S_MCLK(MCLK_512); | ||
| 632 | reg = CS2000_REF_CLK_DIV_2; | 640 | reg = CS2000_REF_CLK_DIV_2; |
| 641 | } | ||
| 642 | |||
| 643 | oxygen_write16_masked(chip, OXYGEN_I2S_A_FORMAT, rate_mclk, | ||
| 644 | OXYGEN_I2S_RATE_MASK | OXYGEN_I2S_MCLK_MASK); | ||
| 633 | cs2000_write_cached(chip, CS2000_FUN_CFG_1, reg); | 645 | cs2000_write_cached(chip, CS2000_FUN_CFG_1, reg); |
| 646 | msleep(3); /* PLL lock delay */ | ||
| 634 | } | 647 | } |
| 635 | 648 | ||
| 636 | static void set_st_params(struct oxygen *chip, | 649 | static void set_st_params(struct oxygen *chip, |
| @@ -665,13 +678,7 @@ static int rolloff_info(struct snd_kcontrol *ctl, | |||
| 665 | "Sharp Roll-off", "Slow Roll-off" | 678 | "Sharp Roll-off", "Slow Roll-off" |
| 666 | }; | 679 | }; |
| 667 | 680 | ||
| 668 | info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 681 | return snd_ctl_enum_info(info, 1, 2, names); |
| 669 | info->count = 1; | ||
| 670 | info->value.enumerated.items = 2; | ||
| 671 | if (info->value.enumerated.item >= 2) | ||
| 672 | info->value.enumerated.item = 1; | ||
| 673 | strcpy(info->value.enumerated.name, names[info->value.enumerated.item]); | ||
| 674 | return 0; | ||
| 675 | } | 682 | } |
| 676 | 683 | ||
| 677 | static int rolloff_get(struct snd_kcontrol *ctl, | 684 | static int rolloff_get(struct snd_kcontrol *ctl, |
| @@ -719,57 +726,13 @@ static const struct snd_kcontrol_new rolloff_control = { | |||
| 719 | .put = rolloff_put, | 726 | .put = rolloff_put, |
| 720 | }; | 727 | }; |
| 721 | 728 | ||
| 722 | static int os_128_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) | 729 | static const struct snd_kcontrol_new hdav_hdmi_control = { |
| 723 | { | ||
| 724 | static const char *const names[2] = { "64x", "128x" }; | ||
| 725 | |||
| 726 | info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
| 727 | info->count = 1; | ||
| 728 | info->value.enumerated.items = 2; | ||
| 729 | if (info->value.enumerated.item >= 2) | ||
| 730 | info->value.enumerated.item = 1; | ||
| 731 | strcpy(info->value.enumerated.name, names[info->value.enumerated.item]); | ||
| 732 | return 0; | ||
| 733 | } | ||
| 734 | |||
| 735 | static int os_128_get(struct snd_kcontrol *ctl, | ||
| 736 | struct snd_ctl_elem_value *value) | ||
| 737 | { | ||
| 738 | struct oxygen *chip = ctl->private_data; | ||
| 739 | struct xonar_pcm179x *data = chip->model_data; | ||
| 740 | |||
| 741 | value->value.enumerated.item[0] = data->os_128; | ||
| 742 | return 0; | ||
| 743 | } | ||
| 744 | |||
| 745 | static int os_128_put(struct snd_kcontrol *ctl, | ||
| 746 | struct snd_ctl_elem_value *value) | ||
| 747 | { | ||
| 748 | struct oxygen *chip = ctl->private_data; | ||
| 749 | struct xonar_pcm179x *data = chip->model_data; | ||
| 750 | int changed; | ||
| 751 | |||
| 752 | mutex_lock(&chip->mutex); | ||
| 753 | changed = value->value.enumerated.item[0] != data->os_128; | ||
| 754 | if (changed) { | ||
| 755 | data->os_128 = value->value.enumerated.item[0]; | ||
| 756 | if (data->has_cs2000) | ||
| 757 | update_cs2000_rate(chip, data->current_rate); | ||
| 758 | oxygen_write16_masked(chip, OXYGEN_I2S_MULTICH_FORMAT, | ||
| 759 | mclk_from_rate(chip, data->current_rate), | ||
| 760 | OXYGEN_I2S_MCLK_MASK); | ||
| 761 | update_pcm1796_oversampling(chip); | ||
| 762 | } | ||
| 763 | mutex_unlock(&chip->mutex); | ||
| 764 | return changed; | ||
| 765 | } | ||
| 766 | |||
| 767 | static const struct snd_kcontrol_new os_128_control = { | ||
| 768 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 730 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
| 769 | .name = "DAC Oversampling Playback Enum", | 731 | .name = "HDMI Playback Switch", |
| 770 | .info = os_128_info, | 732 | .info = snd_ctl_boolean_mono_info, |
| 771 | .get = os_128_get, | 733 | .get = xonar_gpio_bit_switch_get, |
| 772 | .put = os_128_put, | 734 | .put = xonar_gpio_bit_switch_put, |
| 735 | .private_value = GPIO_HDAV_OUTPUT_ENABLE | XONAR_GPIO_BIT_INVERT, | ||
| 773 | }; | 736 | }; |
| 774 | 737 | ||
| 775 | static int st_output_switch_info(struct snd_kcontrol *ctl, | 738 | static int st_output_switch_info(struct snd_kcontrol *ctl, |
| @@ -779,13 +742,7 @@ static int st_output_switch_info(struct snd_kcontrol *ctl, | |||
| 779 | "Speakers", "Headphones", "FP Headphones" | 742 | "Speakers", "Headphones", "FP Headphones" |
| 780 | }; | 743 | }; |
| 781 | 744 | ||
| 782 | info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 745 | return snd_ctl_enum_info(info, 1, 3, names); |
| 783 | info->count = 1; | ||
| 784 | info->value.enumerated.items = 3; | ||
| 785 | if (info->value.enumerated.item >= 3) | ||
| 786 | info->value.enumerated.item = 2; | ||
| 787 | strcpy(info->value.enumerated.name, names[info->value.enumerated.item]); | ||
| 788 | return 0; | ||
| 789 | } | 746 | } |
| 790 | 747 | ||
| 791 | static int st_output_switch_get(struct snd_kcontrol *ctl, | 748 | static int st_output_switch_get(struct snd_kcontrol *ctl, |
| @@ -840,13 +797,7 @@ static int st_hp_volume_offset_info(struct snd_kcontrol *ctl, | |||
| 840 | "< 64 ohms", "64-300 ohms", "300-600 ohms" | 797 | "< 64 ohms", "64-300 ohms", "300-600 ohms" |
| 841 | }; | 798 | }; |
| 842 | 799 | ||
| 843 | info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 800 | return snd_ctl_enum_info(info, 1, 3, names); |
| 844 | info->count = 1; | ||
| 845 | info->value.enumerated.items = 3; | ||
| 846 | if (info->value.enumerated.item > 2) | ||
| 847 | info->value.enumerated.item = 2; | ||
| 848 | strcpy(info->value.enumerated.name, names[info->value.enumerated.item]); | ||
| 849 | return 0; | ||
| 850 | } | 801 | } |
| 851 | 802 | ||
| 852 | static int st_hp_volume_offset_get(struct snd_kcontrol *ctl, | 803 | static int st_hp_volume_offset_get(struct snd_kcontrol *ctl, |
| @@ -928,16 +879,25 @@ static int xonar_d2_control_filter(struct snd_kcontrol_new *template) | |||
| 928 | return 0; | 879 | return 0; |
| 929 | } | 880 | } |
| 930 | 881 | ||
| 882 | static int xonar_st_h6_control_filter(struct snd_kcontrol_new *template) | ||
| 883 | { | ||
| 884 | if (!strncmp(template->name, "Master Playback ", 16)) | ||
| 885 | /* no volume/mute, as I²C to the third DAC does not work */ | ||
| 886 | return 1; | ||
| 887 | return 0; | ||
| 888 | } | ||
| 889 | |||
| 931 | static int add_pcm1796_controls(struct oxygen *chip) | 890 | static int add_pcm1796_controls(struct oxygen *chip) |
| 932 | { | 891 | { |
| 892 | struct xonar_pcm179x *data = chip->model_data; | ||
| 933 | int err; | 893 | int err; |
| 934 | 894 | ||
| 935 | err = snd_ctl_add(chip->card, snd_ctl_new1(&rolloff_control, chip)); | 895 | if (!data->broken_i2c) { |
| 936 | if (err < 0) | 896 | err = snd_ctl_add(chip->card, |
| 937 | return err; | 897 | snd_ctl_new1(&rolloff_control, chip)); |
| 938 | err = snd_ctl_add(chip->card, snd_ctl_new1(&os_128_control, chip)); | 898 | if (err < 0) |
| 939 | if (err < 0) | 899 | return err; |
| 940 | return err; | 900 | } |
| 941 | return 0; | 901 | return 0; |
| 942 | } | 902 | } |
| 943 | 903 | ||
| @@ -956,7 +916,15 @@ static int xonar_d2_mixer_init(struct oxygen *chip) | |||
| 956 | 916 | ||
| 957 | static int xonar_hdav_mixer_init(struct oxygen *chip) | 917 | static int xonar_hdav_mixer_init(struct oxygen *chip) |
| 958 | { | 918 | { |
| 959 | return add_pcm1796_controls(chip); | 919 | int err; |
| 920 | |||
| 921 | err = snd_ctl_add(chip->card, snd_ctl_new1(&hdav_hdmi_control, chip)); | ||
| 922 | if (err < 0) | ||
| 923 | return err; | ||
| 924 | err = add_pcm1796_controls(chip); | ||
| 925 | if (err < 0) | ||
| 926 | return err; | ||
| 927 | return 0; | ||
| 960 | } | 928 | } |
| 961 | 929 | ||
| 962 | static int xonar_st_mixer_init(struct oxygen *chip) | 930 | static int xonar_st_mixer_init(struct oxygen *chip) |
| @@ -976,6 +944,45 @@ static int xonar_st_mixer_init(struct oxygen *chip) | |||
| 976 | return 0; | 944 | return 0; |
| 977 | } | 945 | } |
| 978 | 946 | ||
| 947 | static void dump_pcm1796_registers(struct oxygen *chip, | ||
| 948 | struct snd_info_buffer *buffer) | ||
| 949 | { | ||
| 950 | struct xonar_pcm179x *data = chip->model_data; | ||
| 951 | unsigned int dac, i; | ||
| 952 | |||
| 953 | for (dac = 0; dac < data->dacs; ++dac) { | ||
| 954 | snd_iprintf(buffer, "\nPCM1796 %u:", dac + 1); | ||
| 955 | for (i = 0; i < 5; ++i) | ||
| 956 | snd_iprintf(buffer, " %02x", | ||
| 957 | data->pcm1796_regs[dac][i]); | ||
| 958 | } | ||
| 959 | snd_iprintf(buffer, "\n"); | ||
| 960 | } | ||
| 961 | |||
| 962 | static void dump_cs2000_registers(struct oxygen *chip, | ||
| 963 | struct snd_info_buffer *buffer) | ||
| 964 | { | ||
| 965 | struct xonar_pcm179x *data = chip->model_data; | ||
| 966 | unsigned int i; | ||
| 967 | |||
| 968 | if (data->has_cs2000) { | ||
| 969 | snd_iprintf(buffer, "\nCS2000:\n00: "); | ||
| 970 | for (i = 1; i < 0x10; ++i) | ||
| 971 | snd_iprintf(buffer, " %02x", data->cs2000_regs[i]); | ||
| 972 | snd_iprintf(buffer, "\n10:"); | ||
| 973 | for (i = 0x10; i < 0x1f; ++i) | ||
| 974 | snd_iprintf(buffer, " %02x", data->cs2000_regs[i]); | ||
| 975 | snd_iprintf(buffer, "\n"); | ||
| 976 | } | ||
| 977 | } | ||
| 978 | |||
| 979 | static void dump_st_registers(struct oxygen *chip, | ||
| 980 | struct snd_info_buffer *buffer) | ||
| 981 | { | ||
| 982 | dump_pcm1796_registers(chip, buffer); | ||
| 983 | dump_cs2000_registers(chip, buffer); | ||
| 984 | } | ||
| 985 | |||
| 979 | static const struct oxygen_model model_xonar_d2 = { | 986 | static const struct oxygen_model model_xonar_d2 = { |
| 980 | .longname = "Asus Virtuoso 200", | 987 | .longname = "Asus Virtuoso 200", |
| 981 | .chip = "AV200", | 988 | .chip = "AV200", |
| @@ -985,11 +992,11 @@ static const struct oxygen_model model_xonar_d2 = { | |||
| 985 | .cleanup = xonar_d2_cleanup, | 992 | .cleanup = xonar_d2_cleanup, |
| 986 | .suspend = xonar_d2_suspend, | 993 | .suspend = xonar_d2_suspend, |
| 987 | .resume = xonar_d2_resume, | 994 | .resume = xonar_d2_resume, |
| 988 | .get_i2s_mclk = get_pcm1796_i2s_mclk, | ||
| 989 | .set_dac_params = set_pcm1796_params, | 995 | .set_dac_params = set_pcm1796_params, |
| 990 | .set_adc_params = xonar_set_cs53x1_params, | 996 | .set_adc_params = xonar_set_cs53x1_params, |
| 991 | .update_dac_volume = update_pcm1796_volume, | 997 | .update_dac_volume = update_pcm1796_volume, |
| 992 | .update_dac_mute = update_pcm1796_mute, | 998 | .update_dac_mute = update_pcm1796_mute, |
| 999 | .dump_registers = dump_pcm1796_registers, | ||
| 993 | .dac_tlv = pcm1796_db_scale, | 1000 | .dac_tlv = pcm1796_db_scale, |
| 994 | .model_data_size = sizeof(struct xonar_pcm179x), | 1001 | .model_data_size = sizeof(struct xonar_pcm179x), |
| 995 | .device_config = PLAYBACK_0_TO_I2S | | 1002 | .device_config = PLAYBACK_0_TO_I2S | |
| @@ -999,13 +1006,16 @@ static const struct oxygen_model model_xonar_d2 = { | |||
| 999 | MIDI_OUTPUT | | 1006 | MIDI_OUTPUT | |
| 1000 | MIDI_INPUT | | 1007 | MIDI_INPUT | |
| 1001 | AC97_CD_INPUT, | 1008 | AC97_CD_INPUT, |
| 1002 | .dac_channels = 8, | 1009 | .dac_channels_pcm = 8, |
| 1010 | .dac_channels_mixer = 8, | ||
| 1003 | .dac_volume_min = 255 - 2*60, | 1011 | .dac_volume_min = 255 - 2*60, |
| 1004 | .dac_volume_max = 255, | 1012 | .dac_volume_max = 255, |
| 1005 | .misc_flags = OXYGEN_MISC_MIDI, | 1013 | .misc_flags = OXYGEN_MISC_MIDI, |
| 1006 | .function_flags = OXYGEN_FUNCTION_SPI | | 1014 | .function_flags = OXYGEN_FUNCTION_SPI | |
| 1007 | OXYGEN_FUNCTION_ENABLE_SPI_4_5, | 1015 | OXYGEN_FUNCTION_ENABLE_SPI_4_5, |
| 1008 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 1016 | .dac_mclks = OXYGEN_MCLKS(512, 128, 128), |
| 1017 | .adc_mclks = OXYGEN_MCLKS(256, 128, 128), | ||
| 1018 | .dac_i2s_format = OXYGEN_I2S_FORMAT_I2S, | ||
| 1009 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 1019 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
| 1010 | }; | 1020 | }; |
| 1011 | 1021 | ||
| @@ -1018,25 +1028,28 @@ static const struct oxygen_model model_xonar_hdav = { | |||
| 1018 | .suspend = xonar_hdav_suspend, | 1028 | .suspend = xonar_hdav_suspend, |
| 1019 | .resume = xonar_hdav_resume, | 1029 | .resume = xonar_hdav_resume, |
| 1020 | .pcm_hardware_filter = xonar_hdmi_pcm_hardware_filter, | 1030 | .pcm_hardware_filter = xonar_hdmi_pcm_hardware_filter, |
| 1021 | .get_i2s_mclk = get_pcm1796_i2s_mclk, | ||
| 1022 | .set_dac_params = set_hdav_params, | 1031 | .set_dac_params = set_hdav_params, |
| 1023 | .set_adc_params = xonar_set_cs53x1_params, | 1032 | .set_adc_params = xonar_set_cs53x1_params, |
| 1024 | .update_dac_volume = update_pcm1796_volume, | 1033 | .update_dac_volume = update_pcm1796_volume, |
| 1025 | .update_dac_mute = update_pcm1796_mute, | 1034 | .update_dac_mute = update_pcm1796_mute, |
| 1026 | .uart_input = xonar_hdmi_uart_input, | 1035 | .uart_input = xonar_hdmi_uart_input, |
| 1027 | .ac97_switch = xonar_line_mic_ac97_switch, | 1036 | .ac97_switch = xonar_line_mic_ac97_switch, |
| 1037 | .dump_registers = dump_pcm1796_registers, | ||
| 1028 | .dac_tlv = pcm1796_db_scale, | 1038 | .dac_tlv = pcm1796_db_scale, |
| 1029 | .model_data_size = sizeof(struct xonar_hdav), | 1039 | .model_data_size = sizeof(struct xonar_hdav), |
| 1030 | .device_config = PLAYBACK_0_TO_I2S | | 1040 | .device_config = PLAYBACK_0_TO_I2S | |
| 1031 | PLAYBACK_1_TO_SPDIF | | 1041 | PLAYBACK_1_TO_SPDIF | |
| 1032 | CAPTURE_0_FROM_I2S_2 | | 1042 | CAPTURE_0_FROM_I2S_2 | |
| 1033 | CAPTURE_1_FROM_SPDIF, | 1043 | CAPTURE_1_FROM_SPDIF, |
| 1034 | .dac_channels = 8, | 1044 | .dac_channels_pcm = 8, |
| 1045 | .dac_channels_mixer = 2, | ||
| 1035 | .dac_volume_min = 255 - 2*60, | 1046 | .dac_volume_min = 255 - 2*60, |
| 1036 | .dac_volume_max = 255, | 1047 | .dac_volume_max = 255, |
| 1037 | .misc_flags = OXYGEN_MISC_MIDI, | 1048 | .misc_flags = OXYGEN_MISC_MIDI, |
| 1038 | .function_flags = OXYGEN_FUNCTION_2WIRE, | 1049 | .function_flags = OXYGEN_FUNCTION_2WIRE, |
| 1039 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 1050 | .dac_mclks = OXYGEN_MCLKS(512, 128, 128), |
| 1051 | .adc_mclks = OXYGEN_MCLKS(256, 128, 128), | ||
| 1052 | .dac_i2s_format = OXYGEN_I2S_FORMAT_I2S, | ||
| 1040 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 1053 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
| 1041 | }; | 1054 | }; |
| 1042 | 1055 | ||
| @@ -1048,22 +1061,26 @@ static const struct oxygen_model model_xonar_st = { | |||
| 1048 | .cleanup = xonar_st_cleanup, | 1061 | .cleanup = xonar_st_cleanup, |
| 1049 | .suspend = xonar_st_suspend, | 1062 | .suspend = xonar_st_suspend, |
| 1050 | .resume = xonar_st_resume, | 1063 | .resume = xonar_st_resume, |
| 1051 | .get_i2s_mclk = get_pcm1796_i2s_mclk, | ||
| 1052 | .set_dac_params = set_st_params, | 1064 | .set_dac_params = set_st_params, |
| 1053 | .set_adc_params = xonar_set_cs53x1_params, | 1065 | .set_adc_params = xonar_set_cs53x1_params, |
| 1054 | .update_dac_volume = update_pcm1796_volume, | 1066 | .update_dac_volume = update_pcm1796_volume, |
| 1055 | .update_dac_mute = update_pcm1796_mute, | 1067 | .update_dac_mute = update_pcm1796_mute, |
| 1056 | .ac97_switch = xonar_line_mic_ac97_switch, | 1068 | .ac97_switch = xonar_line_mic_ac97_switch, |
| 1069 | .dump_registers = dump_st_registers, | ||
| 1057 | .dac_tlv = pcm1796_db_scale, | 1070 | .dac_tlv = pcm1796_db_scale, |
| 1058 | .model_data_size = sizeof(struct xonar_pcm179x), | 1071 | .model_data_size = sizeof(struct xonar_pcm179x), |
| 1059 | .device_config = PLAYBACK_0_TO_I2S | | 1072 | .device_config = PLAYBACK_0_TO_I2S | |
| 1060 | PLAYBACK_1_TO_SPDIF | | 1073 | PLAYBACK_1_TO_SPDIF | |
| 1061 | CAPTURE_0_FROM_I2S_2, | 1074 | CAPTURE_0_FROM_I2S_2 | |
| 1062 | .dac_channels = 2, | 1075 | AC97_FMIC_SWITCH, |
| 1076 | .dac_channels_pcm = 2, | ||
| 1077 | .dac_channels_mixer = 2, | ||
| 1063 | .dac_volume_min = 255 - 2*60, | 1078 | .dac_volume_min = 255 - 2*60, |
| 1064 | .dac_volume_max = 255, | 1079 | .dac_volume_max = 255, |
| 1065 | .function_flags = OXYGEN_FUNCTION_2WIRE, | 1080 | .function_flags = OXYGEN_FUNCTION_2WIRE, |
| 1066 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 1081 | .dac_mclks = OXYGEN_MCLKS(512, 128, 128), |
| 1082 | .adc_mclks = OXYGEN_MCLKS(256, 128, 128), | ||
| 1083 | .dac_i2s_format = OXYGEN_I2S_FORMAT_I2S, | ||
| 1067 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 1084 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
| 1068 | }; | 1085 | }; |
| 1069 | 1086 | ||
| @@ -1089,7 +1106,8 @@ int __devinit get_xonar_pcm179x_model(struct oxygen *chip, | |||
| 1089 | break; | 1106 | break; |
| 1090 | case GPIO_DB_H6: | 1107 | case GPIO_DB_H6: |
| 1091 | chip->model.shortname = "Xonar HDAV1.3+H6"; | 1108 | chip->model.shortname = "Xonar HDAV1.3+H6"; |
| 1092 | chip->model.private_data = 1; | 1109 | chip->model.dac_channels_mixer = 8; |
| 1110 | chip->model.dac_mclks = OXYGEN_MCLKS(256, 128, 128); | ||
| 1093 | break; | 1111 | break; |
| 1094 | } | 1112 | } |
| 1095 | break; | 1113 | break; |
| @@ -1102,8 +1120,10 @@ int __devinit get_xonar_pcm179x_model(struct oxygen *chip, | |||
| 1102 | break; | 1120 | break; |
| 1103 | case GPIO_DB_H6: | 1121 | case GPIO_DB_H6: |
| 1104 | chip->model.shortname = "Xonar ST+H6"; | 1122 | chip->model.shortname = "Xonar ST+H6"; |
| 1105 | chip->model.dac_channels = 8; | 1123 | chip->model.control_filter = xonar_st_h6_control_filter; |
| 1106 | chip->model.private_data = 1; | 1124 | chip->model.dac_channels_pcm = 8; |
| 1125 | chip->model.dac_channels_mixer = 8; | ||
| 1126 | chip->model.dac_mclks = OXYGEN_MCLKS(256, 128, 128); | ||
| 1107 | break; | 1127 | break; |
| 1108 | } | 1128 | } |
| 1109 | break; | 1129 | break; |
| @@ -1114,9 +1134,6 @@ int __devinit get_xonar_pcm179x_model(struct oxygen *chip, | |||
| 1114 | chip->model.resume = xonar_stx_resume; | 1134 | chip->model.resume = xonar_stx_resume; |
| 1115 | chip->model.set_dac_params = set_pcm1796_params; | 1135 | chip->model.set_dac_params = set_pcm1796_params; |
| 1116 | break; | 1136 | break; |
| 1117 | case 0x835e: | ||
| 1118 | snd_printk(KERN_ERR "the HDAV1.3 Slim is not supported\n"); | ||
| 1119 | return -ENODEV; | ||
| 1120 | default: | 1137 | default: |
| 1121 | return -EINVAL; | 1138 | return -EINVAL; |
| 1122 | } | 1139 | } |
diff --git a/sound/pci/oxygen/xonar_wm87x6.c b/sound/pci/oxygen/xonar_wm87x6.c index 200f7601276f..42d1ab136217 100644 --- a/sound/pci/oxygen/xonar_wm87x6.c +++ b/sound/pci/oxygen/xonar_wm87x6.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * card driver for models with WM8776/WM8766 DACs (Xonar DS) | 2 | * card driver for models with WM8776/WM8766 DACs (Xonar DS/HDAV1.3 Slim) |
| 3 | * | 3 | * |
| 4 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> | 4 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> |
| 5 | * | 5 | * |
| @@ -22,26 +22,48 @@ | |||
| 22 | * | 22 | * |
| 23 | * CMI8788: | 23 | * CMI8788: |
| 24 | * | 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, 0 = plugged | 28 | * GPIO 4 <- headphone detect, 0 = plugged |
| 29 | * GPIO 6 -> route input jack to mic-in (0) or line-in (1) | 29 | * GPIO 6 -> route input jack to mic-in (0) or line-in (1) |
| 30 | * GPIO 7 -> enable output to front L/R speaker channels | 30 | * GPIO 7 -> enable output to front L/R speaker channels |
| 31 | * GPIO 8 -> enable output to other speaker channels and front panel headphone | 31 | * GPIO 8 -> enable output to other speaker channels and front panel headphone |
| 32 | * | 32 | * |
| 33 | * WM8766: | 33 | * WM8776: |
| 34 | * | 34 | * |
| 35 | * input 1 <- line | 35 | * input 1 <- line |
| 36 | * input 2 <- mic | 36 | * input 2 <- mic |
| 37 | * input 3 <- front mic | 37 | * input 3 <- front mic |
| 38 | * input 4 <- aux | 38 | * input 4 <- aux |
| 39 | */ | ||
| 40 | |||
| 41 | /* | ||
| 42 | * Xonar HDAV1.3 Slim | ||
| 43 | * ------------------ | ||
| 44 | * | ||
| 45 | * CMI8788: | ||
| 46 | * | ||
| 47 | * I²C <-> WM8776 (addr 0011010) | ||
| 48 | * | ||
| 49 | * GPIO 0 -> disable HDMI output | ||
| 50 | * GPIO 1 -> enable HP output | ||
| 51 | * GPIO 6 -> firmware EEPROM I²C clock | ||
| 52 | * GPIO 7 <-> firmware EEPROM I²C data | ||
| 53 | * | ||
| 54 | * UART <-> HDMI controller | ||
| 55 | * | ||
| 56 | * WM8776: | ||
| 57 | * | ||
| 58 | * input 1 <- mic | ||
| 59 | * input 2 <- aux | ||
| 39 | */ | 60 | */ |
| 40 | 61 | ||
| 41 | #include <linux/pci.h> | 62 | #include <linux/pci.h> |
| 42 | #include <linux/delay.h> | 63 | #include <linux/delay.h> |
| 43 | #include <sound/control.h> | 64 | #include <sound/control.h> |
| 44 | #include <sound/core.h> | 65 | #include <sound/core.h> |
| 66 | #include <sound/info.h> | ||
| 45 | #include <sound/jack.h> | 67 | #include <sound/jack.h> |
| 46 | #include <sound/pcm.h> | 68 | #include <sound/pcm.h> |
| 47 | #include <sound/pcm_params.h> | 69 | #include <sound/pcm_params.h> |
| @@ -55,6 +77,13 @@ | |||
| 55 | #define GPIO_DS_OUTPUT_FRONTLR 0x0080 | 77 | #define GPIO_DS_OUTPUT_FRONTLR 0x0080 |
| 56 | #define GPIO_DS_OUTPUT_ENABLE 0x0100 | 78 | #define GPIO_DS_OUTPUT_ENABLE 0x0100 |
| 57 | 79 | ||
| 80 | #define GPIO_SLIM_HDMI_DISABLE 0x0001 | ||
| 81 | #define GPIO_SLIM_OUTPUT_ENABLE 0x0002 | ||
| 82 | #define GPIO_SLIM_FIRMWARE_CLK 0x0040 | ||
| 83 | #define GPIO_SLIM_FIRMWARE_DATA 0x0080 | ||
| 84 | |||
| 85 | #define I2C_DEVICE_WM8776 0x34 /* 001101, 0, /W=0 */ | ||
| 86 | |||
| 58 | #define LC_CONTROL_LIMITER 0x40000000 | 87 | #define LC_CONTROL_LIMITER 0x40000000 |
| 59 | #define LC_CONTROL_ALC 0x20000000 | 88 | #define LC_CONTROL_ALC 0x20000000 |
| 60 | 89 | ||
| @@ -66,19 +95,37 @@ struct xonar_wm87x6 { | |||
| 66 | struct snd_kcontrol *mic_adcmux_control; | 95 | struct snd_kcontrol *mic_adcmux_control; |
| 67 | struct snd_kcontrol *lc_controls[13]; | 96 | struct snd_kcontrol *lc_controls[13]; |
| 68 | struct snd_jack *hp_jack; | 97 | struct snd_jack *hp_jack; |
| 98 | struct xonar_hdmi hdmi; | ||
| 69 | }; | 99 | }; |
| 70 | 100 | ||
| 71 | static void wm8776_write(struct oxygen *chip, | 101 | static void wm8776_write_spi(struct oxygen *chip, |
| 72 | unsigned int reg, unsigned int value) | 102 | unsigned int reg, unsigned int value) |
| 73 | { | 103 | { |
| 74 | struct xonar_wm87x6 *data = chip->model_data; | ||
| 75 | |||
| 76 | oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | | 104 | oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | |
| 77 | OXYGEN_SPI_DATA_LENGTH_2 | | 105 | OXYGEN_SPI_DATA_LENGTH_2 | |
| 78 | OXYGEN_SPI_CLOCK_160 | | 106 | OXYGEN_SPI_CLOCK_160 | |
| 79 | (1 << OXYGEN_SPI_CODEC_SHIFT) | | 107 | (1 << OXYGEN_SPI_CODEC_SHIFT) | |
| 80 | OXYGEN_SPI_CEN_LATCH_CLOCK_LO, | 108 | OXYGEN_SPI_CEN_LATCH_CLOCK_LO, |
| 81 | (reg << 9) | value); | 109 | (reg << 9) | value); |
| 110 | } | ||
| 111 | |||
| 112 | static void wm8776_write_i2c(struct oxygen *chip, | ||
| 113 | unsigned int reg, unsigned int value) | ||
| 114 | { | ||
| 115 | oxygen_write_i2c(chip, I2C_DEVICE_WM8776, | ||
| 116 | (reg << 1) | (value >> 8), value); | ||
| 117 | } | ||
| 118 | |||
| 119 | static void wm8776_write(struct oxygen *chip, | ||
| 120 | unsigned int reg, unsigned int value) | ||
| 121 | { | ||
| 122 | struct xonar_wm87x6 *data = chip->model_data; | ||
| 123 | |||
| 124 | if ((chip->model.function_flags & OXYGEN_FUNCTION_2WIRE_SPI_MASK) == | ||
| 125 | OXYGEN_FUNCTION_SPI) | ||
| 126 | wm8776_write_spi(chip, reg, value); | ||
| 127 | else | ||
| 128 | wm8776_write_i2c(chip, reg, value); | ||
| 82 | if (reg < ARRAY_SIZE(data->wm8776_regs)) { | 129 | if (reg < ARRAY_SIZE(data->wm8776_regs)) { |
| 83 | if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER) | 130 | if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER) |
| 84 | value &= ~WM8776_UPDATE; | 131 | value &= ~WM8776_UPDATE; |
| @@ -245,17 +292,50 @@ static void xonar_ds_init(struct oxygen *chip) | |||
| 245 | snd_component_add(chip->card, "WM8766"); | 292 | snd_component_add(chip->card, "WM8766"); |
| 246 | } | 293 | } |
| 247 | 294 | ||
| 295 | static void xonar_hdav_slim_init(struct oxygen *chip) | ||
| 296 | { | ||
| 297 | struct xonar_wm87x6 *data = chip->model_data; | ||
| 298 | |||
| 299 | data->generic.anti_pop_delay = 300; | ||
| 300 | data->generic.output_enable_bit = GPIO_SLIM_OUTPUT_ENABLE; | ||
| 301 | |||
| 302 | wm8776_init(chip); | ||
| 303 | |||
| 304 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, | ||
| 305 | GPIO_SLIM_HDMI_DISABLE | | ||
| 306 | GPIO_SLIM_FIRMWARE_CLK | | ||
| 307 | GPIO_SLIM_FIRMWARE_DATA); | ||
| 308 | |||
| 309 | xonar_hdmi_init(chip, &data->hdmi); | ||
| 310 | xonar_enable_output(chip); | ||
| 311 | |||
| 312 | snd_component_add(chip->card, "WM8776"); | ||
| 313 | } | ||
| 314 | |||
| 248 | static void xonar_ds_cleanup(struct oxygen *chip) | 315 | static void xonar_ds_cleanup(struct oxygen *chip) |
| 249 | { | 316 | { |
| 250 | xonar_disable_output(chip); | 317 | xonar_disable_output(chip); |
| 251 | wm8776_write(chip, WM8776_RESET, 0); | 318 | wm8776_write(chip, WM8776_RESET, 0); |
| 252 | } | 319 | } |
| 253 | 320 | ||
| 321 | static void xonar_hdav_slim_cleanup(struct oxygen *chip) | ||
| 322 | { | ||
| 323 | xonar_hdmi_cleanup(chip); | ||
| 324 | xonar_disable_output(chip); | ||
| 325 | wm8776_write(chip, WM8776_RESET, 0); | ||
| 326 | msleep(2); | ||
| 327 | } | ||
| 328 | |||
| 254 | static void xonar_ds_suspend(struct oxygen *chip) | 329 | static void xonar_ds_suspend(struct oxygen *chip) |
| 255 | { | 330 | { |
| 256 | xonar_ds_cleanup(chip); | 331 | xonar_ds_cleanup(chip); |
| 257 | } | 332 | } |
| 258 | 333 | ||
| 334 | static void xonar_hdav_slim_suspend(struct oxygen *chip) | ||
| 335 | { | ||
| 336 | xonar_hdav_slim_cleanup(chip); | ||
| 337 | } | ||
| 338 | |||
| 259 | static void xonar_ds_resume(struct oxygen *chip) | 339 | static void xonar_ds_resume(struct oxygen *chip) |
| 260 | { | 340 | { |
| 261 | wm8776_registers_init(chip); | 341 | wm8776_registers_init(chip); |
| @@ -264,6 +344,15 @@ static void xonar_ds_resume(struct oxygen *chip) | |||
| 264 | xonar_ds_handle_hp_jack(chip); | 344 | xonar_ds_handle_hp_jack(chip); |
| 265 | } | 345 | } |
| 266 | 346 | ||
| 347 | static void xonar_hdav_slim_resume(struct oxygen *chip) | ||
| 348 | { | ||
| 349 | struct xonar_wm87x6 *data = chip->model_data; | ||
| 350 | |||
| 351 | wm8776_registers_init(chip); | ||
| 352 | xonar_hdmi_resume(chip, &data->hdmi); | ||
| 353 | xonar_enable_output(chip); | ||
| 354 | } | ||
| 355 | |||
| 267 | static void wm8776_adc_hardware_filter(unsigned int channel, | 356 | static void wm8776_adc_hardware_filter(unsigned int channel, |
| 268 | struct snd_pcm_hardware *hardware) | 357 | struct snd_pcm_hardware *hardware) |
| 269 | { | 358 | { |
| @@ -278,6 +367,13 @@ static void wm8776_adc_hardware_filter(unsigned int channel, | |||
| 278 | } | 367 | } |
| 279 | } | 368 | } |
| 280 | 369 | ||
| 370 | static void xonar_hdav_slim_hardware_filter(unsigned int channel, | ||
| 371 | struct snd_pcm_hardware *hardware) | ||
| 372 | { | ||
| 373 | wm8776_adc_hardware_filter(channel, hardware); | ||
| 374 | xonar_hdmi_pcm_hardware_filter(channel, hardware); | ||
| 375 | } | ||
| 376 | |||
| 281 | static void set_wm87x6_dac_params(struct oxygen *chip, | 377 | static void set_wm87x6_dac_params(struct oxygen *chip, |
| 282 | struct snd_pcm_hw_params *params) | 378 | struct snd_pcm_hw_params *params) |
| 283 | { | 379 | { |
| @@ -294,6 +390,14 @@ static void set_wm8776_adc_params(struct oxygen *chip, | |||
| 294 | wm8776_write_cached(chip, WM8776_MSTRCTRL, reg); | 390 | wm8776_write_cached(chip, WM8776_MSTRCTRL, reg); |
| 295 | } | 391 | } |
| 296 | 392 | ||
| 393 | static void set_hdav_slim_dac_params(struct oxygen *chip, | ||
| 394 | struct snd_pcm_hw_params *params) | ||
| 395 | { | ||
| 396 | struct xonar_wm87x6 *data = chip->model_data; | ||
| 397 | |||
| 398 | xonar_set_hdmi_params(chip, &data->hdmi, params); | ||
| 399 | } | ||
| 400 | |||
| 297 | static void update_wm8776_volume(struct oxygen *chip) | 401 | static void update_wm8776_volume(struct oxygen *chip) |
| 298 | { | 402 | { |
| 299 | struct xonar_wm87x6 *data = chip->model_data; | 403 | struct xonar_wm87x6 *data = chip->model_data; |
| @@ -473,11 +577,6 @@ static int wm8776_field_enum_info(struct snd_kcontrol *ctl, | |||
| 473 | const char *const *names; | 577 | const char *const *names; |
| 474 | 578 | ||
| 475 | max = (ctl->private_value >> 12) & 0xf; | 579 | max = (ctl->private_value >> 12) & 0xf; |
| 476 | info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
| 477 | info->count = 1; | ||
| 478 | info->value.enumerated.items = max + 1; | ||
| 479 | if (info->value.enumerated.item > max) | ||
| 480 | info->value.enumerated.item = max; | ||
| 481 | switch ((ctl->private_value >> 24) & 0x1f) { | 580 | switch ((ctl->private_value >> 24) & 0x1f) { |
| 482 | case WM8776_ALCCTRL2: | 581 | case WM8776_ALCCTRL2: |
| 483 | names = hld; | 582 | names = hld; |
| @@ -501,8 +600,7 @@ static int wm8776_field_enum_info(struct snd_kcontrol *ctl, | |||
| 501 | default: | 600 | default: |
| 502 | return -ENXIO; | 601 | return -ENXIO; |
| 503 | } | 602 | } |
| 504 | strcpy(info->value.enumerated.name, names[info->value.enumerated.item]); | 603 | return snd_ctl_enum_info(info, 1, max + 1, names); |
| 505 | return 0; | ||
| 506 | } | 604 | } |
| 507 | 605 | ||
| 508 | static int wm8776_field_volume_info(struct snd_kcontrol *ctl, | 606 | static int wm8776_field_volume_info(struct snd_kcontrol *ctl, |
| @@ -759,13 +857,8 @@ static int wm8776_level_control_info(struct snd_kcontrol *ctl, | |||
| 759 | static const char *const names[3] = { | 857 | static const char *const names[3] = { |
| 760 | "None", "Peak Limiter", "Automatic Level Control" | 858 | "None", "Peak Limiter", "Automatic Level Control" |
| 761 | }; | 859 | }; |
| 762 | info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 860 | |
| 763 | info->count = 1; | 861 | return snd_ctl_enum_info(info, 1, 3, names); |
| 764 | info->value.enumerated.items = 3; | ||
| 765 | if (info->value.enumerated.item >= 3) | ||
| 766 | info->value.enumerated.item = 2; | ||
| 767 | strcpy(info->value.enumerated.name, names[info->value.enumerated.item]); | ||
| 768 | return 0; | ||
| 769 | } | 862 | } |
| 770 | 863 | ||
| 771 | static int wm8776_level_control_get(struct snd_kcontrol *ctl, | 864 | static int wm8776_level_control_get(struct snd_kcontrol *ctl, |
| @@ -851,13 +944,7 @@ static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) | |||
| 851 | "None", "High-pass Filter" | 944 | "None", "High-pass Filter" |
| 852 | }; | 945 | }; |
| 853 | 946 | ||
| 854 | info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 947 | return snd_ctl_enum_info(info, 1, 2, names); |
| 855 | info->count = 1; | ||
| 856 | info->value.enumerated.items = 2; | ||
| 857 | if (info->value.enumerated.item >= 2) | ||
| 858 | info->value.enumerated.item = 1; | ||
| 859 | strcpy(info->value.enumerated.name, names[info->value.enumerated.item]); | ||
| 860 | return 0; | ||
| 861 | } | 948 | } |
| 862 | 949 | ||
| 863 | static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) | 950 | static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) |
| @@ -985,6 +1072,53 @@ static const struct snd_kcontrol_new ds_controls[] = { | |||
| 985 | .private_value = 0, | 1072 | .private_value = 0, |
| 986 | }, | 1073 | }, |
| 987 | }; | 1074 | }; |
| 1075 | static const struct snd_kcontrol_new hdav_slim_controls[] = { | ||
| 1076 | { | ||
| 1077 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
| 1078 | .name = "HDMI Playback Switch", | ||
| 1079 | .info = snd_ctl_boolean_mono_info, | ||
| 1080 | .get = xonar_gpio_bit_switch_get, | ||
| 1081 | .put = xonar_gpio_bit_switch_put, | ||
| 1082 | .private_value = GPIO_SLIM_HDMI_DISABLE | XONAR_GPIO_BIT_INVERT, | ||
| 1083 | }, | ||
| 1084 | { | ||
| 1085 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
| 1086 | .name = "Headphone Playback Volume", | ||
| 1087 | .info = wm8776_hp_vol_info, | ||
| 1088 | .get = wm8776_hp_vol_get, | ||
| 1089 | .put = wm8776_hp_vol_put, | ||
| 1090 | .tlv = { .p = wm8776_hp_db_scale }, | ||
| 1091 | }, | ||
| 1092 | WM8776_BIT_SWITCH("Headphone Playback Switch", | ||
| 1093 | WM8776_PWRDOWN, WM8776_HPPD, 1, 0), | ||
| 1094 | { | ||
| 1095 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
| 1096 | .name = "Input Capture Volume", | ||
| 1097 | .info = wm8776_input_vol_info, | ||
| 1098 | .get = wm8776_input_vol_get, | ||
| 1099 | .put = wm8776_input_vol_put, | ||
| 1100 | .tlv = { .p = wm8776_adc_db_scale }, | ||
| 1101 | }, | ||
| 1102 | WM8776_BIT_SWITCH("Mic Capture Switch", | ||
| 1103 | WM8776_ADCMUX, 1 << 0, 0, 0), | ||
| 1104 | WM8776_BIT_SWITCH("Aux Capture Switch", | ||
| 1105 | WM8776_ADCMUX, 1 << 1, 0, 0), | ||
| 1106 | { | ||
| 1107 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
| 1108 | .name = "ADC Filter Capture Enum", | ||
| 1109 | .info = hpf_info, | ||
| 1110 | .get = hpf_get, | ||
| 1111 | .put = hpf_put, | ||
| 1112 | }, | ||
| 1113 | { | ||
| 1114 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
| 1115 | .name = "Level Control Capture Enum", | ||
| 1116 | .info = wm8776_level_control_info, | ||
| 1117 | .get = wm8776_level_control_get, | ||
| 1118 | .put = wm8776_level_control_put, | ||
| 1119 | .private_value = 0, | ||
| 1120 | }, | ||
| 1121 | }; | ||
| 988 | static const struct snd_kcontrol_new lc_controls[] = { | 1122 | static const struct snd_kcontrol_new lc_controls[] = { |
| 989 | WM8776_FIELD_CTL_VOLUME("Limiter Threshold", | 1123 | WM8776_FIELD_CTL_VOLUME("Limiter Threshold", |
| 990 | WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf, | 1124 | WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf, |
| @@ -1028,6 +1162,26 @@ static const struct snd_kcontrol_new lc_controls[] = { | |||
| 1028 | LC_CONTROL_ALC, wm8776_ngth_db_scale), | 1162 | LC_CONTROL_ALC, wm8776_ngth_db_scale), |
| 1029 | }; | 1163 | }; |
| 1030 | 1164 | ||
| 1165 | static int add_lc_controls(struct oxygen *chip) | ||
| 1166 | { | ||
| 1167 | struct xonar_wm87x6 *data = chip->model_data; | ||
| 1168 | unsigned int i; | ||
| 1169 | struct snd_kcontrol *ctl; | ||
| 1170 | int err; | ||
| 1171 | |||
| 1172 | BUILD_BUG_ON(ARRAY_SIZE(lc_controls) != ARRAY_SIZE(data->lc_controls)); | ||
| 1173 | for (i = 0; i < ARRAY_SIZE(lc_controls); ++i) { | ||
| 1174 | ctl = snd_ctl_new1(&lc_controls[i], chip); | ||
| 1175 | if (!ctl) | ||
| 1176 | return -ENOMEM; | ||
| 1177 | err = snd_ctl_add(chip->card, ctl); | ||
| 1178 | if (err < 0) | ||
| 1179 | return err; | ||
| 1180 | data->lc_controls[i] = ctl; | ||
| 1181 | } | ||
| 1182 | return 0; | ||
| 1183 | } | ||
| 1184 | |||
| 1031 | static int xonar_ds_mixer_init(struct oxygen *chip) | 1185 | static int xonar_ds_mixer_init(struct oxygen *chip) |
| 1032 | { | 1186 | { |
| 1033 | struct xonar_wm87x6 *data = chip->model_data; | 1187 | struct xonar_wm87x6 *data = chip->model_data; |
| @@ -1049,17 +1203,54 @@ static int xonar_ds_mixer_init(struct oxygen *chip) | |||
| 1049 | } | 1203 | } |
| 1050 | if (!data->line_adcmux_control || !data->mic_adcmux_control) | 1204 | if (!data->line_adcmux_control || !data->mic_adcmux_control) |
| 1051 | return -ENXIO; | 1205 | return -ENXIO; |
| 1052 | BUILD_BUG_ON(ARRAY_SIZE(lc_controls) != ARRAY_SIZE(data->lc_controls)); | 1206 | |
| 1053 | for (i = 0; i < ARRAY_SIZE(lc_controls); ++i) { | 1207 | return add_lc_controls(chip); |
| 1054 | ctl = snd_ctl_new1(&lc_controls[i], chip); | 1208 | } |
| 1209 | |||
| 1210 | static int xonar_hdav_slim_mixer_init(struct oxygen *chip) | ||
| 1211 | { | ||
| 1212 | unsigned int i; | ||
| 1213 | struct snd_kcontrol *ctl; | ||
| 1214 | int err; | ||
| 1215 | |||
| 1216 | for (i = 0; i < ARRAY_SIZE(hdav_slim_controls); ++i) { | ||
| 1217 | ctl = snd_ctl_new1(&hdav_slim_controls[i], chip); | ||
| 1055 | if (!ctl) | 1218 | if (!ctl) |
| 1056 | return -ENOMEM; | 1219 | return -ENOMEM; |
| 1057 | err = snd_ctl_add(chip->card, ctl); | 1220 | err = snd_ctl_add(chip->card, ctl); |
| 1058 | if (err < 0) | 1221 | if (err < 0) |
| 1059 | return err; | 1222 | return err; |
| 1060 | data->lc_controls[i] = ctl; | ||
| 1061 | } | 1223 | } |
| 1062 | return 0; | 1224 | |
| 1225 | return add_lc_controls(chip); | ||
| 1226 | } | ||
| 1227 | |||
| 1228 | static void dump_wm8776_registers(struct oxygen *chip, | ||
| 1229 | struct snd_info_buffer *buffer) | ||
| 1230 | { | ||
| 1231 | struct xonar_wm87x6 *data = chip->model_data; | ||
| 1232 | unsigned int i; | ||
| 1233 | |||
| 1234 | snd_iprintf(buffer, "\nWM8776:\n00:"); | ||
| 1235 | for (i = 0; i < 0x10; ++i) | ||
| 1236 | snd_iprintf(buffer, " %03x", data->wm8776_regs[i]); | ||
| 1237 | snd_iprintf(buffer, "\n10:"); | ||
| 1238 | for (i = 0x10; i < 0x17; ++i) | ||
| 1239 | snd_iprintf(buffer, " %03x", data->wm8776_regs[i]); | ||
| 1240 | snd_iprintf(buffer, "\n"); | ||
| 1241 | } | ||
| 1242 | |||
| 1243 | static void dump_wm87x6_registers(struct oxygen *chip, | ||
| 1244 | struct snd_info_buffer *buffer) | ||
| 1245 | { | ||
| 1246 | struct xonar_wm87x6 *data = chip->model_data; | ||
| 1247 | unsigned int i; | ||
| 1248 | |||
| 1249 | dump_wm8776_registers(chip, buffer); | ||
| 1250 | snd_iprintf(buffer, "\nWM8766:\n00:"); | ||
| 1251 | for (i = 0; i < 0x10; ++i) | ||
| 1252 | snd_iprintf(buffer, " %03x", data->wm8766_regs[i]); | ||
| 1253 | snd_iprintf(buffer, "\n"); | ||
| 1063 | } | 1254 | } |
| 1064 | 1255 | ||
| 1065 | static const struct oxygen_model model_xonar_ds = { | 1256 | static const struct oxygen_model model_xonar_ds = { |
| @@ -1072,22 +1263,57 @@ static const struct oxygen_model model_xonar_ds = { | |||
| 1072 | .suspend = xonar_ds_suspend, | 1263 | .suspend = xonar_ds_suspend, |
| 1073 | .resume = xonar_ds_resume, | 1264 | .resume = xonar_ds_resume, |
| 1074 | .pcm_hardware_filter = wm8776_adc_hardware_filter, | 1265 | .pcm_hardware_filter = wm8776_adc_hardware_filter, |
| 1075 | .get_i2s_mclk = oxygen_default_i2s_mclk, | ||
| 1076 | .set_dac_params = set_wm87x6_dac_params, | 1266 | .set_dac_params = set_wm87x6_dac_params, |
| 1077 | .set_adc_params = set_wm8776_adc_params, | 1267 | .set_adc_params = set_wm8776_adc_params, |
| 1078 | .update_dac_volume = update_wm87x6_volume, | 1268 | .update_dac_volume = update_wm87x6_volume, |
| 1079 | .update_dac_mute = update_wm87x6_mute, | 1269 | .update_dac_mute = update_wm87x6_mute, |
| 1080 | .update_center_lfe_mix = update_wm8766_center_lfe_mix, | 1270 | .update_center_lfe_mix = update_wm8766_center_lfe_mix, |
| 1081 | .gpio_changed = xonar_ds_gpio_changed, | 1271 | .gpio_changed = xonar_ds_gpio_changed, |
| 1272 | .dump_registers = dump_wm87x6_registers, | ||
| 1082 | .dac_tlv = wm87x6_dac_db_scale, | 1273 | .dac_tlv = wm87x6_dac_db_scale, |
| 1083 | .model_data_size = sizeof(struct xonar_wm87x6), | 1274 | .model_data_size = sizeof(struct xonar_wm87x6), |
| 1084 | .device_config = PLAYBACK_0_TO_I2S | | 1275 | .device_config = PLAYBACK_0_TO_I2S | |
| 1085 | PLAYBACK_1_TO_SPDIF | | 1276 | PLAYBACK_1_TO_SPDIF | |
| 1086 | CAPTURE_0_FROM_I2S_1, | 1277 | CAPTURE_0_FROM_I2S_1, |
| 1087 | .dac_channels = 8, | 1278 | .dac_channels_pcm = 8, |
| 1279 | .dac_channels_mixer = 8, | ||
| 1088 | .dac_volume_min = 255 - 2*60, | 1280 | .dac_volume_min = 255 - 2*60, |
| 1089 | .dac_volume_max = 255, | 1281 | .dac_volume_max = 255, |
| 1090 | .function_flags = OXYGEN_FUNCTION_SPI, | 1282 | .function_flags = OXYGEN_FUNCTION_SPI, |
| 1283 | .dac_mclks = OXYGEN_MCLKS(256, 256, 128), | ||
| 1284 | .adc_mclks = OXYGEN_MCLKS(256, 256, 128), | ||
| 1285 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | ||
| 1286 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | ||
| 1287 | }; | ||
| 1288 | |||
| 1289 | static const struct oxygen_model model_xonar_hdav_slim = { | ||
| 1290 | .shortname = "Xonar HDAV1.3 Slim", | ||
| 1291 | .longname = "Asus Virtuoso 200", | ||
| 1292 | .chip = "AV200", | ||
| 1293 | .init = xonar_hdav_slim_init, | ||
| 1294 | .mixer_init = xonar_hdav_slim_mixer_init, | ||
| 1295 | .cleanup = xonar_hdav_slim_cleanup, | ||
| 1296 | .suspend = xonar_hdav_slim_suspend, | ||
| 1297 | .resume = xonar_hdav_slim_resume, | ||
| 1298 | .pcm_hardware_filter = xonar_hdav_slim_hardware_filter, | ||
| 1299 | .set_dac_params = set_hdav_slim_dac_params, | ||
| 1300 | .set_adc_params = set_wm8776_adc_params, | ||
| 1301 | .update_dac_volume = update_wm8776_volume, | ||
| 1302 | .update_dac_mute = update_wm8776_mute, | ||
| 1303 | .uart_input = xonar_hdmi_uart_input, | ||
| 1304 | .dump_registers = dump_wm8776_registers, | ||
| 1305 | .dac_tlv = wm87x6_dac_db_scale, | ||
| 1306 | .model_data_size = sizeof(struct xonar_wm87x6), | ||
| 1307 | .device_config = PLAYBACK_0_TO_I2S | | ||
| 1308 | PLAYBACK_1_TO_SPDIF | | ||
| 1309 | CAPTURE_0_FROM_I2S_1, | ||
| 1310 | .dac_channels_pcm = 8, | ||
| 1311 | .dac_channels_mixer = 2, | ||
| 1312 | .dac_volume_min = 255 - 2*60, | ||
| 1313 | .dac_volume_max = 255, | ||
| 1314 | .function_flags = OXYGEN_FUNCTION_2WIRE, | ||
| 1315 | .dac_mclks = OXYGEN_MCLKS(256, 256, 128), | ||
| 1316 | .adc_mclks = OXYGEN_MCLKS(256, 256, 128), | ||
| 1091 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 1317 | .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
| 1092 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, | 1318 | .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, |
| 1093 | }; | 1319 | }; |
| @@ -1099,6 +1325,9 @@ int __devinit get_xonar_wm87x6_model(struct oxygen *chip, | |||
| 1099 | case 0x838e: | 1325 | case 0x838e: |
| 1100 | chip->model = model_xonar_ds; | 1326 | chip->model = model_xonar_ds; |
| 1101 | break; | 1327 | break; |
| 1328 | case 0x835e: | ||
| 1329 | chip->model = model_xonar_hdav_slim; | ||
| 1330 | break; | ||
| 1102 | default: | 1331 | default: |
| 1103 | return -EINVAL; | 1332 | return -EINVAL; |
| 1104 | } | 1333 | } |
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 0b720cf7783e..2d8332416c83 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c | |||
| @@ -60,6 +60,7 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," | |||
| 60 | "{RME HDSP-9652}," | 60 | "{RME HDSP-9652}," |
| 61 | "{RME HDSP-9632}}"); | 61 | "{RME HDSP-9632}}"); |
| 62 | #ifdef HDSP_FW_LOADER | 62 | #ifdef HDSP_FW_LOADER |
| 63 | MODULE_FIRMWARE("rpm_firmware.bin"); | ||
| 63 | MODULE_FIRMWARE("multiface_firmware.bin"); | 64 | MODULE_FIRMWARE("multiface_firmware.bin"); |
| 64 | MODULE_FIRMWARE("multiface_firmware_rev11.bin"); | 65 | MODULE_FIRMWARE("multiface_firmware_rev11.bin"); |
| 65 | MODULE_FIRMWARE("digiface_firmware.bin"); | 66 | MODULE_FIRMWARE("digiface_firmware.bin"); |
| @@ -81,6 +82,7 @@ MODULE_FIRMWARE("digiface_firmware_rev11.bin"); | |||
| 81 | #define H9632_SS_CHANNELS 12 | 82 | #define H9632_SS_CHANNELS 12 |
| 82 | #define H9632_DS_CHANNELS 8 | 83 | #define H9632_DS_CHANNELS 8 |
| 83 | #define H9632_QS_CHANNELS 4 | 84 | #define H9632_QS_CHANNELS 4 |
| 85 | #define RPM_CHANNELS 6 | ||
| 84 | 86 | ||
| 85 | /* Write registers. These are defined as byte-offsets from the iobase value. | 87 | /* Write registers. These are defined as byte-offsets from the iobase value. |
| 86 | */ | 88 | */ |
| @@ -191,6 +193,25 @@ MODULE_FIRMWARE("digiface_firmware_rev11.bin"); | |||
| 191 | #define HDSP_PhoneGain1 (1<<30) | 193 | #define HDSP_PhoneGain1 (1<<30) |
| 192 | #define HDSP_QuadSpeed (1<<31) | 194 | #define HDSP_QuadSpeed (1<<31) |
| 193 | 195 | ||
| 196 | /* RPM uses some of the registers for special purposes */ | ||
| 197 | #define HDSP_RPM_Inp12 0x04A00 | ||
| 198 | #define HDSP_RPM_Inp12_Phon_6dB 0x00800 /* Dolby */ | ||
| 199 | #define HDSP_RPM_Inp12_Phon_0dB 0x00000 /* .. */ | ||
| 200 | #define HDSP_RPM_Inp12_Phon_n6dB 0x04000 /* inp_0 */ | ||
| 201 | #define HDSP_RPM_Inp12_Line_0dB 0x04200 /* Dolby+PRO */ | ||
| 202 | #define HDSP_RPM_Inp12_Line_n6dB 0x00200 /* PRO */ | ||
| 203 | |||
| 204 | #define HDSP_RPM_Inp34 0x32000 | ||
| 205 | #define HDSP_RPM_Inp34_Phon_6dB 0x20000 /* SyncRef1 */ | ||
| 206 | #define HDSP_RPM_Inp34_Phon_0dB 0x00000 /* .. */ | ||
| 207 | #define HDSP_RPM_Inp34_Phon_n6dB 0x02000 /* SyncRef2 */ | ||
| 208 | #define HDSP_RPM_Inp34_Line_0dB 0x30000 /* SyncRef1+SyncRef0 */ | ||
| 209 | #define HDSP_RPM_Inp34_Line_n6dB 0x10000 /* SyncRef0 */ | ||
| 210 | |||
| 211 | #define HDSP_RPM_Bypass 0x01000 | ||
| 212 | |||
| 213 | #define HDSP_RPM_Disconnect 0x00001 | ||
| 214 | |||
| 194 | #define HDSP_ADGainMask (HDSP_ADGain0|HDSP_ADGain1) | 215 | #define HDSP_ADGainMask (HDSP_ADGain0|HDSP_ADGain1) |
| 195 | #define HDSP_ADGainMinus10dBV HDSP_ADGainMask | 216 | #define HDSP_ADGainMinus10dBV HDSP_ADGainMask |
| 196 | #define HDSP_ADGainPlus4dBu (HDSP_ADGain0) | 217 | #define HDSP_ADGainPlus4dBu (HDSP_ADGain0) |
| @@ -450,7 +471,7 @@ struct hdsp { | |||
| 450 | u32 creg_spdif; | 471 | u32 creg_spdif; |
| 451 | u32 creg_spdif_stream; | 472 | u32 creg_spdif_stream; |
| 452 | int clock_source_locked; | 473 | int clock_source_locked; |
| 453 | char *card_name; /* digiface/multiface */ | 474 | char *card_name; /* digiface/multiface/rpm */ |
| 454 | enum HDSP_IO_Type io_type; /* ditto, but for code use */ | 475 | enum HDSP_IO_Type io_type; /* ditto, but for code use */ |
| 455 | unsigned short firmware_rev; | 476 | unsigned short firmware_rev; |
| 456 | unsigned short state; /* stores state bits */ | 477 | unsigned short state; /* stores state bits */ |
| @@ -612,6 +633,7 @@ static int hdsp_playback_to_output_key (struct hdsp *hdsp, int in, int out) | |||
| 612 | switch (hdsp->io_type) { | 633 | switch (hdsp->io_type) { |
| 613 | case Multiface: | 634 | case Multiface: |
| 614 | case Digiface: | 635 | case Digiface: |
| 636 | case RPM: | ||
| 615 | default: | 637 | default: |
| 616 | if (hdsp->firmware_rev == 0xa) | 638 | if (hdsp->firmware_rev == 0xa) |
| 617 | return (64 * out) + (32 + (in)); | 639 | return (64 * out) + (32 + (in)); |
| @@ -629,6 +651,7 @@ static int hdsp_input_to_output_key (struct hdsp *hdsp, int in, int out) | |||
| 629 | switch (hdsp->io_type) { | 651 | switch (hdsp->io_type) { |
| 630 | case Multiface: | 652 | case Multiface: |
| 631 | case Digiface: | 653 | case Digiface: |
| 654 | case RPM: | ||
| 632 | default: | 655 | default: |
| 633 | if (hdsp->firmware_rev == 0xa) | 656 | if (hdsp->firmware_rev == 0xa) |
| 634 | return (64 * out) + in; | 657 | return (64 * out) + in; |
| @@ -655,7 +678,7 @@ static int hdsp_check_for_iobox (struct hdsp *hdsp) | |||
| 655 | { | 678 | { |
| 656 | if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0; | 679 | if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0; |
| 657 | if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_ConfigError) { | 680 | if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_ConfigError) { |
| 658 | snd_printk ("Hammerfall-DSP: no Digiface or Multiface connected!\n"); | 681 | snd_printk("Hammerfall-DSP: no IO box connected!\n"); |
| 659 | hdsp->state &= ~HDSP_FirmwareLoaded; | 682 | hdsp->state &= ~HDSP_FirmwareLoaded; |
| 660 | return -EIO; | 683 | return -EIO; |
| 661 | } | 684 | } |
| @@ -680,7 +703,7 @@ static int hdsp_wait_for_iobox(struct hdsp *hdsp, unsigned int loops, | |||
| 680 | } | 703 | } |
| 681 | } | 704 | } |
| 682 | 705 | ||
| 683 | snd_printk("Hammerfall-DSP: no Digiface or Multiface connected!\n"); | 706 | snd_printk("Hammerfall-DSP: no IO box connected!\n"); |
| 684 | hdsp->state &= ~HDSP_FirmwareLoaded; | 707 | hdsp->state &= ~HDSP_FirmwareLoaded; |
| 685 | return -EIO; | 708 | return -EIO; |
| 686 | } | 709 | } |
| @@ -752,17 +775,21 @@ static int hdsp_get_iobox_version (struct hdsp *hdsp) | |||
| 752 | hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD); | 775 | hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD); |
| 753 | hdsp_write (hdsp, HDSP_fifoData, 0); | 776 | hdsp_write (hdsp, HDSP_fifoData, 0); |
| 754 | 777 | ||
| 755 | if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT)) { | 778 | if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT)) { |
| 756 | hdsp->io_type = Multiface; | 779 | hdsp_write(hdsp, HDSP_control2Reg, HDSP_VERSION_BIT); |
| 757 | hdsp_write (hdsp, HDSP_control2Reg, HDSP_VERSION_BIT); | 780 | hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD); |
| 758 | hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD); | 781 | if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT)) |
| 759 | hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT); | 782 | hdsp->io_type = RPM; |
| 783 | else | ||
| 784 | hdsp->io_type = Multiface; | ||
| 760 | } else { | 785 | } else { |
| 761 | hdsp->io_type = Digiface; | 786 | hdsp->io_type = Digiface; |
| 762 | } | 787 | } |
| 763 | } else { | 788 | } else { |
| 764 | /* firmware was already loaded, get iobox type */ | 789 | /* firmware was already loaded, get iobox type */ |
| 765 | if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) | 790 | if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version2) |
| 791 | hdsp->io_type = RPM; | ||
| 792 | else if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) | ||
| 766 | hdsp->io_type = Multiface; | 793 | hdsp->io_type = Multiface; |
| 767 | else | 794 | else |
| 768 | hdsp->io_type = Digiface; | 795 | hdsp->io_type = Digiface; |
| @@ -1184,6 +1211,7 @@ static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally) | |||
| 1184 | hdsp->channel_map = channel_map_ds; | 1211 | hdsp->channel_map = channel_map_ds; |
| 1185 | } else { | 1212 | } else { |
| 1186 | switch (hdsp->io_type) { | 1213 | switch (hdsp->io_type) { |
| 1214 | case RPM: | ||
| 1187 | case Multiface: | 1215 | case Multiface: |
| 1188 | hdsp->channel_map = channel_map_mf_ss; | 1216 | hdsp->channel_map = channel_map_mf_ss; |
| 1189 | break; | 1217 | break; |
| @@ -3231,6 +3259,318 @@ HDSP_PRECISE_POINTER("Precise Pointer", 0), | |||
| 3231 | HDSP_USE_MIDI_TASKLET("Use Midi Tasklet", 0), | 3259 | HDSP_USE_MIDI_TASKLET("Use Midi Tasklet", 0), |
| 3232 | }; | 3260 | }; |
| 3233 | 3261 | ||
| 3262 | |||
| 3263 | static int hdsp_rpm_input12(struct hdsp *hdsp) | ||
| 3264 | { | ||
| 3265 | switch (hdsp->control_register & HDSP_RPM_Inp12) { | ||
| 3266 | case HDSP_RPM_Inp12_Phon_6dB: | ||
| 3267 | return 0; | ||
| 3268 | case HDSP_RPM_Inp12_Phon_n6dB: | ||
| 3269 | return 2; | ||
| 3270 | case HDSP_RPM_Inp12_Line_0dB: | ||
| 3271 | return 3; | ||
| 3272 | case HDSP_RPM_Inp12_Line_n6dB: | ||
| 3273 | return 4; | ||
| 3274 | } | ||
| 3275 | return 1; | ||
| 3276 | } | ||
| 3277 | |||
| 3278 | |||
| 3279 | static int snd_hdsp_get_rpm_input12(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
| 3280 | { | ||
| 3281 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | ||
| 3282 | |||
| 3283 | ucontrol->value.enumerated.item[0] = hdsp_rpm_input12(hdsp); | ||
| 3284 | return 0; | ||
| 3285 | } | ||
| 3286 | |||
| 3287 | |||
| 3288 | static int hdsp_set_rpm_input12(struct hdsp *hdsp, int mode) | ||
| 3289 | { | ||
| 3290 | hdsp->control_register &= ~HDSP_RPM_Inp12; | ||
| 3291 | switch (mode) { | ||
| 3292 | case 0: | ||
| 3293 | hdsp->control_register |= HDSP_RPM_Inp12_Phon_6dB; | ||
| 3294 | break; | ||
| 3295 | case 1: | ||
| 3296 | break; | ||
| 3297 | case 2: | ||
| 3298 | hdsp->control_register |= HDSP_RPM_Inp12_Phon_n6dB; | ||
| 3299 | break; | ||
| 3300 | case 3: | ||
| 3301 | hdsp->control_register |= HDSP_RPM_Inp12_Line_0dB; | ||
| 3302 | break; | ||
| 3303 | case 4: | ||
| 3304 | hdsp->control_register |= HDSP_RPM_Inp12_Line_n6dB; | ||
| 3305 | break; | ||
| 3306 | default: | ||
| 3307 | return -1; | ||
| 3308 | } | ||
| 3309 | |||
| 3310 | hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); | ||
| 3311 | return 0; | ||
| 3312 | } | ||
| 3313 | |||
| 3314 | |||
| 3315 | static int snd_hdsp_put_rpm_input12(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
| 3316 | { | ||
| 3317 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | ||
| 3318 | int change; | ||
| 3319 | int val; | ||
| 3320 | |||
| 3321 | if (!snd_hdsp_use_is_exclusive(hdsp)) | ||
| 3322 | return -EBUSY; | ||
| 3323 | val = ucontrol->value.enumerated.item[0]; | ||
| 3324 | if (val < 0) | ||
| 3325 | val = 0; | ||
| 3326 | if (val > 4) | ||
| 3327 | val = 4; | ||
| 3328 | spin_lock_irq(&hdsp->lock); | ||
| 3329 | if (val != hdsp_rpm_input12(hdsp)) | ||
| 3330 | change = (hdsp_set_rpm_input12(hdsp, val) == 0) ? 1 : 0; | ||
| 3331 | else | ||
| 3332 | change = 0; | ||
| 3333 | spin_unlock_irq(&hdsp->lock); | ||
| 3334 | return change; | ||
| 3335 | } | ||
| 3336 | |||
| 3337 | |||
| 3338 | static int snd_hdsp_info_rpm_input(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | ||
| 3339 | { | ||
| 3340 | static char *texts[] = {"Phono +6dB", "Phono 0dB", "Phono -6dB", "Line 0dB", "Line -6dB"}; | ||
| 3341 | |||
| 3342 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
| 3343 | uinfo->count = 1; | ||
| 3344 | uinfo->value.enumerated.items = 5; | ||
| 3345 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
| 3346 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; | ||
| 3347 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
| 3348 | return 0; | ||
| 3349 | } | ||
| 3350 | |||
| 3351 | |||
| 3352 | static int hdsp_rpm_input34(struct hdsp *hdsp) | ||
| 3353 | { | ||
| 3354 | switch (hdsp->control_register & HDSP_RPM_Inp34) { | ||
| 3355 | case HDSP_RPM_Inp34_Phon_6dB: | ||
| 3356 | return 0; | ||
| 3357 | case HDSP_RPM_Inp34_Phon_n6dB: | ||
| 3358 | return 2; | ||
| 3359 | case HDSP_RPM_Inp34_Line_0dB: | ||
| 3360 | return 3; | ||
| 3361 | case HDSP_RPM_Inp34_Line_n6dB: | ||
| 3362 | return 4; | ||
| 3363 | } | ||
| 3364 | return 1; | ||
| 3365 | } | ||
| 3366 | |||
| 3367 | |||
| 3368 | static int snd_hdsp_get_rpm_input34(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
| 3369 | { | ||
| 3370 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | ||
| 3371 | |||
| 3372 | ucontrol->value.enumerated.item[0] = hdsp_rpm_input34(hdsp); | ||
| 3373 | return 0; | ||
| 3374 | } | ||
| 3375 | |||
| 3376 | |||
| 3377 | static int hdsp_set_rpm_input34(struct hdsp *hdsp, int mode) | ||
| 3378 | { | ||
| 3379 | hdsp->control_register &= ~HDSP_RPM_Inp34; | ||
| 3380 | switch (mode) { | ||
| 3381 | case 0: | ||
| 3382 | hdsp->control_register |= HDSP_RPM_Inp34_Phon_6dB; | ||
| 3383 | break; | ||
| 3384 | case 1: | ||
| 3385 | break; | ||
| 3386 | case 2: | ||
| 3387 | hdsp->control_register |= HDSP_RPM_Inp34_Phon_n6dB; | ||
| 3388 | break; | ||
| 3389 | case 3: | ||
| 3390 | hdsp->control_register |= HDSP_RPM_Inp34_Line_0dB; | ||
| 3391 | break; | ||
| 3392 | case 4: | ||
| 3393 | hdsp->control_register |= HDSP_RPM_Inp34_Line_n6dB; | ||
| 3394 | break; | ||
| 3395 | default: | ||
| 3396 | return -1; | ||
| 3397 | } | ||
| 3398 | |||
| 3399 | hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); | ||
| 3400 | return 0; | ||
| 3401 | } | ||
| 3402 | |||
| 3403 | |||
| 3404 | static int snd_hdsp_put_rpm_input34(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
| 3405 | { | ||
| 3406 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | ||
| 3407 | int change; | ||
| 3408 | int val; | ||
| 3409 | |||
| 3410 | if (!snd_hdsp_use_is_exclusive(hdsp)) | ||
| 3411 | return -EBUSY; | ||
| 3412 | val = ucontrol->value.enumerated.item[0]; | ||
| 3413 | if (val < 0) | ||
| 3414 | val = 0; | ||
| 3415 | if (val > 4) | ||
| 3416 | val = 4; | ||
| 3417 | spin_lock_irq(&hdsp->lock); | ||
| 3418 | if (val != hdsp_rpm_input34(hdsp)) | ||
| 3419 | change = (hdsp_set_rpm_input34(hdsp, val) == 0) ? 1 : 0; | ||
| 3420 | else | ||
| 3421 | change = 0; | ||
| 3422 | spin_unlock_irq(&hdsp->lock); | ||
| 3423 | return change; | ||
| 3424 | } | ||
| 3425 | |||
| 3426 | |||
| 3427 | /* RPM Bypass switch */ | ||
| 3428 | static int hdsp_rpm_bypass(struct hdsp *hdsp) | ||
| 3429 | { | ||
| 3430 | return (hdsp->control_register & HDSP_RPM_Bypass) ? 1 : 0; | ||
| 3431 | } | ||
| 3432 | |||
| 3433 | |||
| 3434 | static int snd_hdsp_get_rpm_bypass(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
| 3435 | { | ||
| 3436 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | ||
| 3437 | |||
| 3438 | ucontrol->value.integer.value[0] = hdsp_rpm_bypass(hdsp); | ||
| 3439 | return 0; | ||
| 3440 | } | ||
| 3441 | |||
| 3442 | |||
| 3443 | static int hdsp_set_rpm_bypass(struct hdsp *hdsp, int on) | ||
| 3444 | { | ||
| 3445 | if (on) | ||
| 3446 | hdsp->control_register |= HDSP_RPM_Bypass; | ||
| 3447 | else | ||
| 3448 | hdsp->control_register &= ~HDSP_RPM_Bypass; | ||
| 3449 | hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); | ||
| 3450 | return 0; | ||
| 3451 | } | ||
| 3452 | |||
| 3453 | |||
| 3454 | static int snd_hdsp_put_rpm_bypass(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
| 3455 | { | ||
| 3456 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | ||
| 3457 | int change; | ||
| 3458 | unsigned int val; | ||
| 3459 | |||
| 3460 | if (!snd_hdsp_use_is_exclusive(hdsp)) | ||
| 3461 | return -EBUSY; | ||
| 3462 | val = ucontrol->value.integer.value[0] & 1; | ||
| 3463 | spin_lock_irq(&hdsp->lock); | ||
| 3464 | change = (int)val != hdsp_rpm_bypass(hdsp); | ||
| 3465 | hdsp_set_rpm_bypass(hdsp, val); | ||
| 3466 | spin_unlock_irq(&hdsp->lock); | ||
| 3467 | return change; | ||
| 3468 | } | ||
| 3469 | |||
| 3470 | |||
| 3471 | static int snd_hdsp_info_rpm_bypass(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | ||
| 3472 | { | ||
| 3473 | static char *texts[] = {"On", "Off"}; | ||
| 3474 | |||
| 3475 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
| 3476 | uinfo->count = 1; | ||
| 3477 | uinfo->value.enumerated.items = 2; | ||
| 3478 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
| 3479 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; | ||
| 3480 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
| 3481 | return 0; | ||
| 3482 | } | ||
| 3483 | |||
| 3484 | |||
| 3485 | /* RPM Disconnect switch */ | ||
| 3486 | static int hdsp_rpm_disconnect(struct hdsp *hdsp) | ||
| 3487 | { | ||
| 3488 | return (hdsp->control_register & HDSP_RPM_Disconnect) ? 1 : 0; | ||
| 3489 | } | ||
| 3490 | |||
| 3491 | |||
| 3492 | static int snd_hdsp_get_rpm_disconnect(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
| 3493 | { | ||
| 3494 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | ||
| 3495 | |||
| 3496 | ucontrol->value.integer.value[0] = hdsp_rpm_disconnect(hdsp); | ||
| 3497 | return 0; | ||
| 3498 | } | ||
| 3499 | |||
| 3500 | |||
| 3501 | static int hdsp_set_rpm_disconnect(struct hdsp *hdsp, int on) | ||
| 3502 | { | ||
| 3503 | if (on) | ||
| 3504 | hdsp->control_register |= HDSP_RPM_Disconnect; | ||
| 3505 | else | ||
| 3506 | hdsp->control_register &= ~HDSP_RPM_Disconnect; | ||
| 3507 | hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); | ||
| 3508 | return 0; | ||
| 3509 | } | ||
| 3510 | |||
| 3511 | |||
| 3512 | static int snd_hdsp_put_rpm_disconnect(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
| 3513 | { | ||
| 3514 | struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); | ||
| 3515 | int change; | ||
| 3516 | unsigned int val; | ||
| 3517 | |||
| 3518 | if (!snd_hdsp_use_is_exclusive(hdsp)) | ||
| 3519 | return -EBUSY; | ||
| 3520 | val = ucontrol->value.integer.value[0] & 1; | ||
| 3521 | spin_lock_irq(&hdsp->lock); | ||
| 3522 | change = (int)val != hdsp_rpm_disconnect(hdsp); | ||
| 3523 | hdsp_set_rpm_disconnect(hdsp, val); | ||
| 3524 | spin_unlock_irq(&hdsp->lock); | ||
| 3525 | return change; | ||
| 3526 | } | ||
| 3527 | |||
| 3528 | static int snd_hdsp_info_rpm_disconnect(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | ||
| 3529 | { | ||
| 3530 | static char *texts[] = {"On", "Off"}; | ||
| 3531 | |||
| 3532 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
| 3533 | uinfo->count = 1; | ||
| 3534 | uinfo->value.enumerated.items = 2; | ||
| 3535 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
| 3536 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; | ||
| 3537 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
| 3538 | return 0; | ||
| 3539 | } | ||
| 3540 | |||
| 3541 | static struct snd_kcontrol_new snd_hdsp_rpm_controls[] = { | ||
| 3542 | { | ||
| 3543 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
| 3544 | .name = "RPM Bypass", | ||
| 3545 | .get = snd_hdsp_get_rpm_bypass, | ||
| 3546 | .put = snd_hdsp_put_rpm_bypass, | ||
| 3547 | .info = snd_hdsp_info_rpm_bypass | ||
| 3548 | }, | ||
| 3549 | { | ||
| 3550 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
| 3551 | .name = "RPM Disconnect", | ||
| 3552 | .get = snd_hdsp_get_rpm_disconnect, | ||
| 3553 | .put = snd_hdsp_put_rpm_disconnect, | ||
| 3554 | .info = snd_hdsp_info_rpm_disconnect | ||
| 3555 | }, | ||
| 3556 | { | ||
| 3557 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
| 3558 | .name = "Input 1/2", | ||
| 3559 | .get = snd_hdsp_get_rpm_input12, | ||
| 3560 | .put = snd_hdsp_put_rpm_input12, | ||
| 3561 | .info = snd_hdsp_info_rpm_input | ||
| 3562 | }, | ||
| 3563 | { | ||
| 3564 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
| 3565 | .name = "Input 3/4", | ||
| 3566 | .get = snd_hdsp_get_rpm_input34, | ||
| 3567 | .put = snd_hdsp_put_rpm_input34, | ||
| 3568 | .info = snd_hdsp_info_rpm_input | ||
| 3569 | }, | ||
| 3570 | HDSP_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), | ||
| 3571 | HDSP_MIXER("Mixer", 0) | ||
| 3572 | }; | ||
| 3573 | |||
| 3234 | static struct snd_kcontrol_new snd_hdsp_96xx_aeb = HDSP_AEB("Analog Extension Board", 0); | 3574 | static struct snd_kcontrol_new snd_hdsp_96xx_aeb = HDSP_AEB("Analog Extension Board", 0); |
| 3235 | static struct snd_kcontrol_new snd_hdsp_adat_sync_check = HDSP_ADAT_SYNC_CHECK; | 3575 | static struct snd_kcontrol_new snd_hdsp_adat_sync_check = HDSP_ADAT_SYNC_CHECK; |
| 3236 | 3576 | ||
| @@ -3240,6 +3580,16 @@ static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp) | |||
| 3240 | int err; | 3580 | int err; |
| 3241 | struct snd_kcontrol *kctl; | 3581 | struct snd_kcontrol *kctl; |
| 3242 | 3582 | ||
| 3583 | if (hdsp->io_type == RPM) { | ||
| 3584 | /* RPM Bypass, Disconnect and Input switches */ | ||
| 3585 | for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_rpm_controls); idx++) { | ||
| 3586 | err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_rpm_controls[idx], hdsp)); | ||
| 3587 | if (err < 0) | ||
| 3588 | return err; | ||
| 3589 | } | ||
| 3590 | return 0; | ||
| 3591 | } | ||
| 3592 | |||
| 3243 | for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_controls); idx++) { | 3593 | for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_controls); idx++) { |
| 3244 | if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_controls[idx], hdsp))) < 0) | 3594 | if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_controls[idx], hdsp))) < 0) |
| 3245 | return err; | 3595 | return err; |
| @@ -3459,48 +3809,102 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | |||
| 3459 | 3809 | ||
| 3460 | snd_iprintf(buffer, "\n"); | 3810 | snd_iprintf(buffer, "\n"); |
| 3461 | 3811 | ||
| 3462 | switch (hdsp_spdif_in(hdsp)) { | 3812 | if (hdsp->io_type != RPM) { |
| 3463 | case HDSP_SPDIFIN_OPTICAL: | 3813 | switch (hdsp_spdif_in(hdsp)) { |
| 3464 | snd_iprintf(buffer, "IEC958 input: Optical\n"); | 3814 | case HDSP_SPDIFIN_OPTICAL: |
| 3465 | break; | 3815 | snd_iprintf(buffer, "IEC958 input: Optical\n"); |
| 3466 | case HDSP_SPDIFIN_COAXIAL: | 3816 | break; |
| 3467 | snd_iprintf(buffer, "IEC958 input: Coaxial\n"); | 3817 | case HDSP_SPDIFIN_COAXIAL: |
| 3468 | break; | 3818 | snd_iprintf(buffer, "IEC958 input: Coaxial\n"); |
| 3469 | case HDSP_SPDIFIN_INTERNAL: | 3819 | break; |
| 3470 | snd_iprintf(buffer, "IEC958 input: Internal\n"); | 3820 | case HDSP_SPDIFIN_INTERNAL: |
| 3471 | break; | 3821 | snd_iprintf(buffer, "IEC958 input: Internal\n"); |
| 3472 | case HDSP_SPDIFIN_AES: | 3822 | break; |
| 3473 | snd_iprintf(buffer, "IEC958 input: AES\n"); | 3823 | case HDSP_SPDIFIN_AES: |
| 3474 | break; | 3824 | snd_iprintf(buffer, "IEC958 input: AES\n"); |
| 3475 | default: | 3825 | break; |
| 3476 | snd_iprintf(buffer, "IEC958 input: ???\n"); | 3826 | default: |
| 3477 | break; | 3827 | snd_iprintf(buffer, "IEC958 input: ???\n"); |
| 3828 | break; | ||
| 3829 | } | ||
| 3478 | } | 3830 | } |
| 3479 | 3831 | ||
| 3480 | if (hdsp->control_register & HDSP_SPDIFOpticalOut) | 3832 | if (RPM == hdsp->io_type) { |
| 3481 | snd_iprintf(buffer, "IEC958 output: Coaxial & ADAT1\n"); | 3833 | if (hdsp->control_register & HDSP_RPM_Bypass) |
| 3482 | else | 3834 | snd_iprintf(buffer, "RPM Bypass: disabled\n"); |
| 3483 | snd_iprintf(buffer, "IEC958 output: Coaxial only\n"); | 3835 | else |
| 3836 | snd_iprintf(buffer, "RPM Bypass: enabled\n"); | ||
| 3837 | if (hdsp->control_register & HDSP_RPM_Disconnect) | ||
| 3838 | snd_iprintf(buffer, "RPM disconnected\n"); | ||
| 3839 | else | ||
| 3840 | snd_iprintf(buffer, "RPM connected\n"); | ||
| 3484 | 3841 | ||
| 3485 | if (hdsp->control_register & HDSP_SPDIFProfessional) | 3842 | switch (hdsp->control_register & HDSP_RPM_Inp12) { |
| 3486 | snd_iprintf(buffer, "IEC958 quality: Professional\n"); | 3843 | case HDSP_RPM_Inp12_Phon_6dB: |
| 3487 | else | 3844 | snd_iprintf(buffer, "Input 1/2: Phono, 6dB\n"); |
| 3488 | snd_iprintf(buffer, "IEC958 quality: Consumer\n"); | 3845 | break; |
| 3846 | case HDSP_RPM_Inp12_Phon_0dB: | ||
| 3847 | snd_iprintf(buffer, "Input 1/2: Phono, 0dB\n"); | ||
| 3848 | break; | ||
| 3849 | case HDSP_RPM_Inp12_Phon_n6dB: | ||
| 3850 | snd_iprintf(buffer, "Input 1/2: Phono, -6dB\n"); | ||
| 3851 | break; | ||
| 3852 | case HDSP_RPM_Inp12_Line_0dB: | ||
| 3853 | snd_iprintf(buffer, "Input 1/2: Line, 0dB\n"); | ||
| 3854 | break; | ||
| 3855 | case HDSP_RPM_Inp12_Line_n6dB: | ||
| 3856 | snd_iprintf(buffer, "Input 1/2: Line, -6dB\n"); | ||
| 3857 | break; | ||
| 3858 | default: | ||
| 3859 | snd_iprintf(buffer, "Input 1/2: ???\n"); | ||
| 3860 | } | ||
| 3489 | 3861 | ||
| 3490 | if (hdsp->control_register & HDSP_SPDIFEmphasis) | 3862 | switch (hdsp->control_register & HDSP_RPM_Inp34) { |
| 3491 | snd_iprintf(buffer, "IEC958 emphasis: on\n"); | 3863 | case HDSP_RPM_Inp34_Phon_6dB: |
| 3492 | else | 3864 | snd_iprintf(buffer, "Input 3/4: Phono, 6dB\n"); |
| 3493 | snd_iprintf(buffer, "IEC958 emphasis: off\n"); | 3865 | break; |
| 3866 | case HDSP_RPM_Inp34_Phon_0dB: | ||
| 3867 | snd_iprintf(buffer, "Input 3/4: Phono, 0dB\n"); | ||
| 3868 | break; | ||
| 3869 | case HDSP_RPM_Inp34_Phon_n6dB: | ||
| 3870 | snd_iprintf(buffer, "Input 3/4: Phono, -6dB\n"); | ||
| 3871 | break; | ||
| 3872 | case HDSP_RPM_Inp34_Line_0dB: | ||
| 3873 | snd_iprintf(buffer, "Input 3/4: Line, 0dB\n"); | ||
| 3874 | break; | ||
| 3875 | case HDSP_RPM_Inp34_Line_n6dB: | ||
| 3876 | snd_iprintf(buffer, "Input 3/4: Line, -6dB\n"); | ||
| 3877 | break; | ||
| 3878 | default: | ||
| 3879 | snd_iprintf(buffer, "Input 3/4: ???\n"); | ||
| 3880 | } | ||
| 3494 | 3881 | ||
| 3495 | if (hdsp->control_register & HDSP_SPDIFNonAudio) | 3882 | } else { |
| 3496 | snd_iprintf(buffer, "IEC958 NonAudio: on\n"); | 3883 | if (hdsp->control_register & HDSP_SPDIFOpticalOut) |
| 3497 | else | 3884 | snd_iprintf(buffer, "IEC958 output: Coaxial & ADAT1\n"); |
| 3498 | snd_iprintf(buffer, "IEC958 NonAudio: off\n"); | 3885 | else |
| 3499 | if ((x = hdsp_spdif_sample_rate (hdsp)) != 0) | 3886 | snd_iprintf(buffer, "IEC958 output: Coaxial only\n"); |
| 3500 | snd_iprintf (buffer, "IEC958 sample rate: %d\n", x); | 3887 | |
| 3501 | else | 3888 | if (hdsp->control_register & HDSP_SPDIFProfessional) |
| 3502 | snd_iprintf (buffer, "IEC958 sample rate: Error flag set\n"); | 3889 | snd_iprintf(buffer, "IEC958 quality: Professional\n"); |
| 3890 | else | ||
| 3891 | snd_iprintf(buffer, "IEC958 quality: Consumer\n"); | ||
| 3892 | |||
| 3893 | if (hdsp->control_register & HDSP_SPDIFEmphasis) | ||
| 3894 | snd_iprintf(buffer, "IEC958 emphasis: on\n"); | ||
| 3895 | else | ||
| 3896 | snd_iprintf(buffer, "IEC958 emphasis: off\n"); | ||
| 3503 | 3897 | ||
| 3898 | if (hdsp->control_register & HDSP_SPDIFNonAudio) | ||
| 3899 | snd_iprintf(buffer, "IEC958 NonAudio: on\n"); | ||
| 3900 | else | ||
| 3901 | snd_iprintf(buffer, "IEC958 NonAudio: off\n"); | ||
| 3902 | x = hdsp_spdif_sample_rate(hdsp); | ||
| 3903 | if (x != 0) | ||
| 3904 | snd_iprintf(buffer, "IEC958 sample rate: %d\n", x); | ||
| 3905 | else | ||
| 3906 | snd_iprintf(buffer, "IEC958 sample rate: Error flag set\n"); | ||
| 3907 | } | ||
| 3504 | snd_iprintf(buffer, "\n"); | 3908 | snd_iprintf(buffer, "\n"); |
| 3505 | 3909 | ||
| 3506 | /* Sync Check */ | 3910 | /* Sync Check */ |
| @@ -3765,7 +4169,7 @@ static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id) | |||
| 3765 | snd_hdsp_midi_input_read (&hdsp->midi[0]); | 4169 | snd_hdsp_midi_input_read (&hdsp->midi[0]); |
| 3766 | } | 4170 | } |
| 3767 | } | 4171 | } |
| 3768 | if (hdsp->io_type != Multiface && hdsp->io_type != H9632 && midi1 && midi1status) { | 4172 | if (hdsp->io_type != Multiface && hdsp->io_type != RPM && hdsp->io_type != H9632 && midi1 && midi1status) { |
| 3769 | if (hdsp->use_midi_tasklet) { | 4173 | if (hdsp->use_midi_tasklet) { |
| 3770 | /* we disable interrupts for this input until processing is done */ | 4174 | /* we disable interrupts for this input until processing is done */ |
| 3771 | hdsp->control_register &= ~HDSP_Midi1InterruptEnable; | 4175 | hdsp->control_register &= ~HDSP_Midi1InterruptEnable; |
| @@ -4093,7 +4497,7 @@ static struct snd_pcm_hardware snd_hdsp_playback_subinfo = | |||
| 4093 | SNDRV_PCM_RATE_96000), | 4497 | SNDRV_PCM_RATE_96000), |
| 4094 | .rate_min = 32000, | 4498 | .rate_min = 32000, |
| 4095 | .rate_max = 96000, | 4499 | .rate_max = 96000, |
| 4096 | .channels_min = 14, | 4500 | .channels_min = 6, |
| 4097 | .channels_max = HDSP_MAX_CHANNELS, | 4501 | .channels_max = HDSP_MAX_CHANNELS, |
| 4098 | .buffer_bytes_max = HDSP_CHANNEL_BUFFER_BYTES * HDSP_MAX_CHANNELS, | 4502 | .buffer_bytes_max = HDSP_CHANNEL_BUFFER_BYTES * HDSP_MAX_CHANNELS, |
| 4099 | .period_bytes_min = (64 * 4) * 10, | 4503 | .period_bytes_min = (64 * 4) * 10, |
| @@ -4122,7 +4526,7 @@ static struct snd_pcm_hardware snd_hdsp_capture_subinfo = | |||
| 4122 | SNDRV_PCM_RATE_96000), | 4526 | SNDRV_PCM_RATE_96000), |
| 4123 | .rate_min = 32000, | 4527 | .rate_min = 32000, |
| 4124 | .rate_max = 96000, | 4528 | .rate_max = 96000, |
| 4125 | .channels_min = 14, | 4529 | .channels_min = 5, |
| 4126 | .channels_max = HDSP_MAX_CHANNELS, | 4530 | .channels_max = HDSP_MAX_CHANNELS, |
| 4127 | .buffer_bytes_max = HDSP_CHANNEL_BUFFER_BYTES * HDSP_MAX_CHANNELS, | 4531 | .buffer_bytes_max = HDSP_CHANNEL_BUFFER_BYTES * HDSP_MAX_CHANNELS, |
| 4128 | .period_bytes_min = (64 * 4) * 10, | 4532 | .period_bytes_min = (64 * 4) * 10, |
| @@ -4357,10 +4761,12 @@ static int snd_hdsp_playback_open(struct snd_pcm_substream *substream) | |||
| 4357 | snd_hdsp_hw_rule_rate_out_channels, hdsp, | 4761 | snd_hdsp_hw_rule_rate_out_channels, hdsp, |
| 4358 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | 4762 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); |
| 4359 | 4763 | ||
| 4360 | hdsp->creg_spdif_stream = hdsp->creg_spdif; | 4764 | if (RPM != hdsp->io_type) { |
| 4361 | hdsp->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; | 4765 | hdsp->creg_spdif_stream = hdsp->creg_spdif; |
| 4362 | snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE | | 4766 | hdsp->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; |
| 4363 | SNDRV_CTL_EVENT_MASK_INFO, &hdsp->spdif_ctl->id); | 4767 | snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE | |
| 4768 | SNDRV_CTL_EVENT_MASK_INFO, &hdsp->spdif_ctl->id); | ||
| 4769 | } | ||
| 4364 | return 0; | 4770 | return 0; |
| 4365 | } | 4771 | } |
| 4366 | 4772 | ||
| @@ -4375,9 +4781,11 @@ static int snd_hdsp_playback_release(struct snd_pcm_substream *substream) | |||
| 4375 | 4781 | ||
| 4376 | spin_unlock_irq(&hdsp->lock); | 4782 | spin_unlock_irq(&hdsp->lock); |
| 4377 | 4783 | ||
| 4378 | hdsp->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; | 4784 | if (RPM != hdsp->io_type) { |
| 4379 | snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE | | 4785 | hdsp->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; |
| 4380 | SNDRV_CTL_EVENT_MASK_INFO, &hdsp->spdif_ctl->id); | 4786 | snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE | |
| 4787 | SNDRV_CTL_EVENT_MASK_INFO, &hdsp->spdif_ctl->id); | ||
| 4788 | } | ||
| 4381 | return 0; | 4789 | return 0; |
| 4382 | } | 4790 | } |
| 4383 | 4791 | ||
| @@ -4616,7 +5024,7 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne | |||
| 4616 | if (hdsp->io_type != H9632) | 5024 | if (hdsp->io_type != H9632) |
| 4617 | info.adatsync_sync_check = (unsigned char)hdsp_adatsync_sync_check(hdsp); | 5025 | info.adatsync_sync_check = (unsigned char)hdsp_adatsync_sync_check(hdsp); |
| 4618 | info.spdif_sync_check = (unsigned char)hdsp_spdif_sync_check(hdsp); | 5026 | info.spdif_sync_check = (unsigned char)hdsp_spdif_sync_check(hdsp); |
| 4619 | for (i = 0; i < ((hdsp->io_type != Multiface && hdsp->io_type != H9632) ? 3 : 1); ++i) | 5027 | for (i = 0; i < ((hdsp->io_type != Multiface && hdsp->io_type != RPM && hdsp->io_type != H9632) ? 3 : 1); ++i) |
| 4620 | info.adat_sync_check[i] = (unsigned char)hdsp_adat_sync_check(hdsp, i); | 5028 | info.adat_sync_check[i] = (unsigned char)hdsp_adat_sync_check(hdsp, i); |
| 4621 | info.spdif_in = (unsigned char)hdsp_spdif_in(hdsp); | 5029 | info.spdif_in = (unsigned char)hdsp_spdif_in(hdsp); |
| 4622 | info.spdif_out = (unsigned char)hdsp_spdif_out(hdsp); | 5030 | info.spdif_out = (unsigned char)hdsp_spdif_out(hdsp); |
| @@ -4636,6 +5044,9 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne | |||
| 4636 | info.phone_gain = (unsigned char)hdsp_phone_gain(hdsp); | 5044 | info.phone_gain = (unsigned char)hdsp_phone_gain(hdsp); |
| 4637 | info.xlr_breakout_cable = (unsigned char)hdsp_xlr_breakout_cable(hdsp); | 5045 | info.xlr_breakout_cable = (unsigned char)hdsp_xlr_breakout_cable(hdsp); |
| 4638 | 5046 | ||
| 5047 | } else if (hdsp->io_type == RPM) { | ||
| 5048 | info.da_gain = (unsigned char) hdsp_rpm_input12(hdsp); | ||
| 5049 | info.ad_gain = (unsigned char) hdsp_rpm_input34(hdsp); | ||
| 4639 | } | 5050 | } |
| 4640 | if (hdsp->io_type == H9632 || hdsp->io_type == H9652) | 5051 | if (hdsp->io_type == H9632 || hdsp->io_type == H9652) |
| 4641 | info.analog_extension_board = (unsigned char)hdsp_aeb(hdsp); | 5052 | info.analog_extension_board = (unsigned char)hdsp_aeb(hdsp); |
| @@ -4844,6 +5255,14 @@ static void snd_hdsp_initialize_channels(struct hdsp *hdsp) | |||
| 4844 | hdsp->ds_in_channels = hdsp->ds_out_channels = MULTIFACE_DS_CHANNELS; | 5255 | hdsp->ds_in_channels = hdsp->ds_out_channels = MULTIFACE_DS_CHANNELS; |
| 4845 | break; | 5256 | break; |
| 4846 | 5257 | ||
| 5258 | case RPM: | ||
| 5259 | hdsp->card_name = "RME Hammerfall DSP + RPM"; | ||
| 5260 | hdsp->ss_in_channels = RPM_CHANNELS-1; | ||
| 5261 | hdsp->ss_out_channels = RPM_CHANNELS; | ||
| 5262 | hdsp->ds_in_channels = RPM_CHANNELS-1; | ||
| 5263 | hdsp->ds_out_channels = RPM_CHANNELS; | ||
| 5264 | break; | ||
| 5265 | |||
| 4847 | default: | 5266 | default: |
| 4848 | /* should never get here */ | 5267 | /* should never get here */ |
| 4849 | break; | 5268 | break; |
| @@ -4930,6 +5349,9 @@ static int hdsp_request_fw_loader(struct hdsp *hdsp) | |||
| 4930 | 5349 | ||
| 4931 | /* caution: max length of firmware filename is 30! */ | 5350 | /* caution: max length of firmware filename is 30! */ |
| 4932 | switch (hdsp->io_type) { | 5351 | switch (hdsp->io_type) { |
| 5352 | case RPM: | ||
| 5353 | fwfile = "rpm_firmware.bin"; | ||
| 5354 | break; | ||
| 4933 | case Multiface: | 5355 | case Multiface: |
| 4934 | if (hdsp->firmware_rev == 0xa) | 5356 | if (hdsp->firmware_rev == 0xa) |
| 4935 | fwfile = "multiface_firmware.bin"; | 5357 | fwfile = "multiface_firmware.bin"; |
| @@ -5100,7 +5522,9 @@ static int __devinit snd_hdsp_create(struct snd_card *card, | |||
| 5100 | return 0; | 5522 | return 0; |
| 5101 | } else { | 5523 | } else { |
| 5102 | snd_printk(KERN_INFO "Hammerfall-DSP: Firmware already present, initializing card.\n"); | 5524 | snd_printk(KERN_INFO "Hammerfall-DSP: Firmware already present, initializing card.\n"); |
| 5103 | if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) | 5525 | if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version2) |
| 5526 | hdsp->io_type = RPM; | ||
| 5527 | else if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) | ||
| 5104 | hdsp->io_type = Multiface; | 5528 | hdsp->io_type = Multiface; |
| 5105 | else | 5529 | else |
| 5106 | hdsp->io_type = Digiface; | 5530 | hdsp->io_type = Digiface; |
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index 5518371db13f..c94c051ad0c8 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c | |||
| @@ -1389,15 +1389,9 @@ static struct snd_kcontrol_new snd_ymfpci_spdif_stream __devinitdata = | |||
| 1389 | 1389 | ||
| 1390 | static int snd_ymfpci_drec_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *info) | 1390 | static int snd_ymfpci_drec_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *info) |
| 1391 | { | 1391 | { |
| 1392 | static char *texts[3] = {"AC'97", "IEC958", "ZV Port"}; | 1392 | static const char *const texts[3] = {"AC'97", "IEC958", "ZV Port"}; |
| 1393 | 1393 | ||
| 1394 | info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 1394 | return snd_ctl_enum_info(info, 1, 3, texts); |
| 1395 | info->count = 1; | ||
| 1396 | info->value.enumerated.items = 3; | ||
| 1397 | if (info->value.enumerated.item > 2) | ||
| 1398 | info->value.enumerated.item = 2; | ||
| 1399 | strcpy(info->value.enumerated.name, texts[info->value.enumerated.item]); | ||
| 1400 | return 0; | ||
| 1401 | } | 1395 | } |
| 1402 | 1396 | ||
| 1403 | static int snd_ymfpci_drec_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *value) | 1397 | static int snd_ymfpci_drec_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *value) |
