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) |