diff options
Diffstat (limited to 'sound/pci')
124 files changed, 5820 insertions, 3356 deletions
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index c6b44102aa5b..356bf21a1506 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig | |||
@@ -170,14 +170,14 @@ config SND_CA0106 | |||
170 | will be called snd-ca0106. | 170 | will be called snd-ca0106. |
171 | 171 | ||
172 | config SND_CMIPCI | 172 | config SND_CMIPCI |
173 | tristate "C-Media 8738, 8338" | 173 | tristate "C-Media 8338, 8738, 8768, 8770" |
174 | depends on SND | 174 | depends on SND |
175 | select SND_OPL3_LIB | 175 | select SND_OPL3_LIB |
176 | select SND_MPU401_UART | 176 | select SND_MPU401_UART |
177 | select SND_PCM | 177 | select SND_PCM |
178 | help | 178 | help |
179 | If you want to use soundcards based on C-Media CMI8338 or CMI8738 | 179 | If you want to use soundcards based on C-Media CMI8338, CMI8738, |
180 | chips, say Y here and read | 180 | CMI8768 or CMI8770 chips, say Y here and read |
181 | <file:Documentation/sound/alsa/CMIPCI.txt>. | 181 | <file:Documentation/sound/alsa/CMIPCI.txt>. |
182 | 182 | ||
183 | To compile this driver as a module, choose M here: the module | 183 | To compile this driver as a module, choose M here: the module |
@@ -500,6 +500,103 @@ config SND_HDA_INTEL | |||
500 | To compile this driver as a module, choose M here: the module | 500 | To compile this driver as a module, choose M here: the module |
501 | will be called snd-hda-intel. | 501 | will be called snd-hda-intel. |
502 | 502 | ||
503 | config SND_HDA_HWDEP | ||
504 | bool "Build hwdep interface for HD-audio driver" | ||
505 | depends on SND_HDA_INTEL | ||
506 | select SND_HWDEP | ||
507 | help | ||
508 | Say Y here to build a hwdep interface for HD-audio driver. | ||
509 | This interface can be used for out-of-band communication | ||
510 | with codecs for debugging purposes. | ||
511 | |||
512 | config SND_HDA_CODEC_REALTEK | ||
513 | bool "Build Realtek HD-audio codec support" | ||
514 | depends on SND_HDA_INTEL | ||
515 | default y | ||
516 | help | ||
517 | Say Y here to include Realtek HD-audio codec support in | ||
518 | snd-hda-intel driver, such as ALC880. | ||
519 | |||
520 | config SND_HDA_CODEC_ANALOG | ||
521 | bool "Build Analog Device HD-audio codec support" | ||
522 | depends on SND_HDA_INTEL | ||
523 | default y | ||
524 | help | ||
525 | Say Y here to include Analog Device HD-audio codec support in | ||
526 | snd-hda-intel driver, such as AD1986A. | ||
527 | |||
528 | config SND_HDA_CODEC_SIGMATEL | ||
529 | bool "Build IDT/Sigmatel HD-audio codec support" | ||
530 | depends on SND_HDA_INTEL | ||
531 | default y | ||
532 | help | ||
533 | Say Y here to include IDT (Sigmatel) HD-audio codec support in | ||
534 | snd-hda-intel driver, such as STAC9200. | ||
535 | |||
536 | config SND_HDA_CODEC_VIA | ||
537 | bool "Build VIA HD-audio codec support" | ||
538 | depends on SND_HDA_INTEL | ||
539 | default y | ||
540 | help | ||
541 | Say Y here to include VIA HD-audio codec support in | ||
542 | snd-hda-intel driver, such as VT1708. | ||
543 | |||
544 | config SND_HDA_CODEC_ATIHDMI | ||
545 | bool "Build ATI HDMI HD-audio codec support" | ||
546 | depends on SND_HDA_INTEL | ||
547 | default y | ||
548 | help | ||
549 | Say Y here to include ATI HDMI HD-audio codec support in | ||
550 | snd-hda-intel driver, such as ATI RS600 HDMI. | ||
551 | |||
552 | config SND_HDA_CODEC_CONEXANT | ||
553 | bool "Build Conexant HD-audio codec support" | ||
554 | depends on SND_HDA_INTEL | ||
555 | default y | ||
556 | help | ||
557 | Say Y here to include Conexant HD-audio codec support in | ||
558 | snd-hda-intel driver, such as CX20549. | ||
559 | |||
560 | config SND_HDA_CODEC_CMEDIA | ||
561 | bool "Build C-Media HD-audio codec support" | ||
562 | depends on SND_HDA_INTEL | ||
563 | default y | ||
564 | help | ||
565 | Say Y here to include C-Media HD-audio codec support in | ||
566 | snd-hda-intel driver, such as CMI9880. | ||
567 | |||
568 | config SND_HDA_CODEC_SI3054 | ||
569 | bool "Build Silicon Labs 3054 HD-modem codec support" | ||
570 | depends on SND_HDA_INTEL | ||
571 | default y | ||
572 | help | ||
573 | Say Y here to include Silicon Labs 3054 HD-modem codec | ||
574 | (and compatibles) support in snd-hda-intel driver. | ||
575 | |||
576 | config SND_HDA_GENERIC | ||
577 | bool "Enable generic HD-audio codec parser" | ||
578 | depends on SND_HDA_INTEL | ||
579 | default y | ||
580 | help | ||
581 | Say Y here to enable the generic HD-audio codec parser | ||
582 | in snd-hda-intel driver. | ||
583 | |||
584 | config SND_HDA_POWER_SAVE | ||
585 | bool "Aggressive power-saving on HD-audio" | ||
586 | depends on SND_HDA_INTEL && EXPERIMENTAL | ||
587 | help | ||
588 | Say Y here to enable more aggressive power-saving mode on | ||
589 | HD-audio driver. The power-saving timeout can be configured | ||
590 | via power_save option or over sysfs on-the-fly. | ||
591 | |||
592 | config SND_HDA_POWER_SAVE_DEFAULT | ||
593 | int "Default time-out for HD-audio power-save mode" | ||
594 | depends on SND_HDA_POWER_SAVE | ||
595 | default 0 | ||
596 | help | ||
597 | The default time-out value in seconds for HD-audio automatic | ||
598 | power-save mode. 0 means to disable the power-save mode. | ||
599 | |||
503 | config SND_HDSP | 600 | config SND_HDSP |
504 | tristate "RME Hammerfall DSP Audio" | 601 | tristate "RME Hammerfall DSP Audio" |
505 | depends on SND | 602 | depends on SND |
@@ -799,4 +896,12 @@ config SND_AC97_POWER_SAVE | |||
799 | snd-ac97-codec driver. You can toggle it dynamically over | 896 | snd-ac97-codec driver. You can toggle it dynamically over |
800 | sysfs, too. | 897 | sysfs, too. |
801 | 898 | ||
899 | config SND_AC97_POWER_SAVE_DEFAULT | ||
900 | int "Default time-out for AC97 power-save mode" | ||
901 | depends on SND_AC97_POWER_SAVE | ||
902 | default 0 | ||
903 | help | ||
904 | The default time-out value in seconds for AC97 automatic | ||
905 | power-save mode. 0 means to disable the power-save mode. | ||
906 | |||
802 | endmenu | 907 | endmenu |
diff --git a/sound/pci/Makefile b/sound/pci/Makefile index cd76e0293d06..09ddc82eeca2 100644 --- a/sound/pci/Makefile +++ b/sound/pci/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-ad1889-objs := ad1889.o | 6 | snd-ad1889-objs := ad1889.o |
diff --git a/sound/pci/ac97/Makefile b/sound/pci/ac97/Makefile index f5d471896b95..0be48b1a22d0 100644 --- a/sound/pci/ac97/Makefile +++ b/sound/pci/ac97/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-ac97-codec-objs := ac97_codec.o ac97_pcm.o | 6 | snd-ac97-codec-objs := ac97_codec.o ac97_pcm.o |
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index bbed644bf9c5..6a9966df0cc9 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Universal interface for Audio Codec '97 | 3 | * Universal interface for Audio Codec '97 |
4 | * | 4 | * |
5 | * For more details look to AC '97 component specification revision 2.2 | 5 | * For more details look to AC '97 component specification revision 2.2 |
@@ -39,7 +39,7 @@ | |||
39 | 39 | ||
40 | #include "ac97_patch.c" | 40 | #include "ac97_patch.c" |
41 | 41 | ||
42 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 42 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
43 | MODULE_DESCRIPTION("Universal interface for Audio Codec '97"); | 43 | MODULE_DESCRIPTION("Universal interface for Audio Codec '97"); |
44 | MODULE_LICENSE("GPL"); | 44 | MODULE_LICENSE("GPL"); |
45 | 45 | ||
@@ -49,7 +49,7 @@ module_param(enable_loopback, bool, 0444); | |||
49 | MODULE_PARM_DESC(enable_loopback, "Enable AC97 ADC/DAC Loopback Control"); | 49 | MODULE_PARM_DESC(enable_loopback, "Enable AC97 ADC/DAC Loopback Control"); |
50 | 50 | ||
51 | #ifdef CONFIG_SND_AC97_POWER_SAVE | 51 | #ifdef CONFIG_SND_AC97_POWER_SAVE |
52 | static int power_save; | 52 | static int power_save = CONFIG_SND_AC97_POWER_SAVE_DEFAULT; |
53 | module_param(power_save, bool, 0644); | 53 | module_param(power_save, bool, 0644); |
54 | MODULE_PARM_DESC(power_save, "Enable AC97 power-saving control"); | 54 | MODULE_PARM_DESC(power_save, "Enable AC97 power-saving control"); |
55 | #endif | 55 | #endif |
@@ -176,7 +176,7 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = { | |||
176 | { 0x574d4C09, 0xffffffff, "WM9709", NULL, NULL}, | 176 | { 0x574d4C09, 0xffffffff, "WM9709", NULL, NULL}, |
177 | { 0x574d4C12, 0xffffffff, "WM9711,WM9712", patch_wolfson11, NULL}, | 177 | { 0x574d4C12, 0xffffffff, "WM9711,WM9712", patch_wolfson11, NULL}, |
178 | { 0x574d4c13, 0xffffffff, "WM9713,WM9714", patch_wolfson13, NULL, AC97_DEFAULT_POWER_OFF}, | 178 | { 0x574d4c13, 0xffffffff, "WM9713,WM9714", patch_wolfson13, NULL, AC97_DEFAULT_POWER_OFF}, |
179 | { 0x594d4800, 0xffffffff, "YMF743", NULL, NULL }, | 179 | { 0x594d4800, 0xffffffff, "YMF743", patch_yamaha_ymf743, NULL }, |
180 | { 0x594d4802, 0xffffffff, "YMF752", NULL, NULL }, | 180 | { 0x594d4802, 0xffffffff, "YMF752", NULL, NULL }, |
181 | { 0x594d4803, 0xffffffff, "YMF753", patch_yamaha_ymf753, NULL }, | 181 | { 0x594d4803, 0xffffffff, "YMF753", patch_yamaha_ymf753, NULL }, |
182 | { 0x83847600, 0xffffffff, "STAC9700,83,84", patch_sigmatel_stac9700, NULL }, | 182 | { 0x83847600, 0xffffffff, "STAC9700,83,84", patch_sigmatel_stac9700, NULL }, |
@@ -779,6 +779,12 @@ static int snd_ac97_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_ | |||
779 | change |= snd_ac97_update_bits_nolock(ac97, AC97_CXR_AUDIO_MISC, | 779 | change |= snd_ac97_update_bits_nolock(ac97, AC97_CXR_AUDIO_MISC, |
780 | AC97_CXR_SPDIF_MASK | AC97_CXR_COPYRGT, | 780 | AC97_CXR_SPDIF_MASK | AC97_CXR_COPYRGT, |
781 | v); | 781 | v); |
782 | } else if (ac97->id == AC97_ID_YMF743) { | ||
783 | change |= snd_ac97_update_bits_nolock(ac97, | ||
784 | AC97_YMF7X3_DIT_CTRL, | ||
785 | 0xff38, | ||
786 | ((val << 4) & 0xff00) | | ||
787 | ((val << 2) & 0x0038)); | ||
782 | } else { | 788 | } else { |
783 | unsigned short extst = snd_ac97_read_cache(ac97, AC97_EXTENDED_STATUS); | 789 | unsigned short extst = snd_ac97_read_cache(ac97, AC97_EXTENDED_STATUS); |
784 | snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); /* turn off */ | 790 | snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); /* turn off */ |
@@ -1375,7 +1381,8 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1375 | for (idx = 0; idx < 2; idx++) { | 1381 | for (idx = 0; idx < 2; idx++) { |
1376 | if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_tone[idx], ac97))) < 0) | 1382 | if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_tone[idx], ac97))) < 0) |
1377 | return err; | 1383 | return err; |
1378 | if (ac97->id == AC97_ID_YMF753) { | 1384 | if (ac97->id == AC97_ID_YMF743 || |
1385 | ac97->id == AC97_ID_YMF753) { | ||
1379 | kctl->private_value &= ~(0xff << 16); | 1386 | kctl->private_value &= ~(0xff << 16); |
1380 | kctl->private_value |= 7 << 16; | 1387 | kctl->private_value |= 7 << 16; |
1381 | } | 1388 | } |
@@ -2036,11 +2043,12 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, | |||
2036 | else { | 2043 | else { |
2037 | udelay(50); | 2044 | udelay(50); |
2038 | if (ac97->scaps & AC97_SCAP_SKIP_AUDIO) | 2045 | if (ac97->scaps & AC97_SCAP_SKIP_AUDIO) |
2039 | err = ac97_reset_wait(ac97, HZ/2, 1); | 2046 | err = ac97_reset_wait(ac97, msecs_to_jiffies(500), 1); |
2040 | else { | 2047 | else { |
2041 | err = ac97_reset_wait(ac97, HZ/2, 0); | 2048 | err = ac97_reset_wait(ac97, msecs_to_jiffies(500), 0); |
2042 | if (err < 0) | 2049 | if (err < 0) |
2043 | err = ac97_reset_wait(ac97, HZ/2, 1); | 2050 | err = ac97_reset_wait(ac97, |
2051 | msecs_to_jiffies(500), 1); | ||
2044 | } | 2052 | } |
2045 | if (err < 0) { | 2053 | if (err < 0) { |
2046 | snd_printk(KERN_WARNING "AC'97 %d does not respond - RESET\n", ac97->num); | 2054 | snd_printk(KERN_WARNING "AC'97 %d does not respond - RESET\n", ac97->num); |
@@ -2104,7 +2112,7 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, | |||
2104 | } | 2112 | } |
2105 | /* nothing should be in powerdown mode */ | 2113 | /* nothing should be in powerdown mode */ |
2106 | snd_ac97_write_cache(ac97, AC97_GENERAL_PURPOSE, 0); | 2114 | snd_ac97_write_cache(ac97, AC97_GENERAL_PURPOSE, 0); |
2107 | end_time = jiffies + (HZ / 10); | 2115 | end_time = jiffies + msecs_to_jiffies(100); |
2108 | do { | 2116 | do { |
2109 | if ((snd_ac97_read(ac97, AC97_POWERDOWN) & 0x0f) == 0x0f) | 2117 | if ((snd_ac97_read(ac97, AC97_POWERDOWN) & 0x0f) == 0x0f) |
2110 | goto __ready_ok; | 2118 | goto __ready_ok; |
@@ -2136,7 +2144,7 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, | |||
2136 | udelay(100); | 2144 | udelay(100); |
2137 | /* nothing should be in powerdown mode */ | 2145 | /* nothing should be in powerdown mode */ |
2138 | snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0); | 2146 | snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0); |
2139 | end_time = jiffies + (HZ / 10); | 2147 | end_time = jiffies + msecs_to_jiffies(100); |
2140 | do { | 2148 | do { |
2141 | if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp) | 2149 | if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp) |
2142 | goto __ready_ok; | 2150 | goto __ready_ok; |
@@ -2354,7 +2362,8 @@ int snd_ac97_update_power(struct snd_ac97 *ac97, int reg, int powerup) | |||
2354 | * (for avoiding loud click noises for many (OSS) apps | 2362 | * (for avoiding loud click noises for many (OSS) apps |
2355 | * that open/close frequently) | 2363 | * that open/close frequently) |
2356 | */ | 2364 | */ |
2357 | schedule_delayed_work(&ac97->power_work, HZ*2); | 2365 | schedule_delayed_work(&ac97->power_work, |
2366 | msecs_to_jiffies(2000)); | ||
2358 | else { | 2367 | else { |
2359 | cancel_delayed_work(&ac97->power_work); | 2368 | cancel_delayed_work(&ac97->power_work); |
2360 | update_power_regs(ac97); | 2369 | update_power_regs(ac97); |
@@ -2436,7 +2445,7 @@ EXPORT_SYMBOL(snd_ac97_suspend); | |||
2436 | /* | 2445 | /* |
2437 | * restore ac97 status | 2446 | * restore ac97 status |
2438 | */ | 2447 | */ |
2439 | void snd_ac97_restore_status(struct snd_ac97 *ac97) | 2448 | static void snd_ac97_restore_status(struct snd_ac97 *ac97) |
2440 | { | 2449 | { |
2441 | int i; | 2450 | int i; |
2442 | 2451 | ||
@@ -2457,7 +2466,7 @@ void snd_ac97_restore_status(struct snd_ac97 *ac97) | |||
2457 | /* | 2466 | /* |
2458 | * restore IEC958 status | 2467 | * restore IEC958 status |
2459 | */ | 2468 | */ |
2460 | void snd_ac97_restore_iec958(struct snd_ac97 *ac97) | 2469 | static void snd_ac97_restore_iec958(struct snd_ac97 *ac97) |
2461 | { | 2470 | { |
2462 | if (ac97->ext_id & AC97_EI_SPDIF) { | 2471 | if (ac97->ext_id & AC97_EI_SPDIF) { |
2463 | if (ac97->regs[AC97_EXTENDED_STATUS] & AC97_EA_SPDIF) { | 2472 | if (ac97->regs[AC97_EXTENDED_STATUS] & AC97_EA_SPDIF) { |
@@ -2494,7 +2503,10 @@ void snd_ac97_resume(struct snd_ac97 *ac97) | |||
2494 | 2503 | ||
2495 | snd_ac97_write(ac97, AC97_POWERDOWN, 0); | 2504 | snd_ac97_write(ac97, AC97_POWERDOWN, 0); |
2496 | if (! (ac97->flags & AC97_DEFAULT_POWER_OFF)) { | 2505 | if (! (ac97->flags & AC97_DEFAULT_POWER_OFF)) { |
2497 | snd_ac97_write(ac97, AC97_RESET, 0); | 2506 | if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO)) |
2507 | snd_ac97_write(ac97, AC97_RESET, 0); | ||
2508 | else if (!(ac97->scaps & AC97_SCAP_SKIP_MODEM)) | ||
2509 | snd_ac97_write(ac97, AC97_EXTENDED_MID, 0); | ||
2498 | udelay(100); | 2510 | udelay(100); |
2499 | snd_ac97_write(ac97, AC97_POWERDOWN, 0); | 2511 | snd_ac97_write(ac97, AC97_POWERDOWN, 0); |
2500 | } | 2512 | } |
diff --git a/sound/pci/ac97/ac97_id.h b/sound/pci/ac97/ac97_id.h index 6d73514dc49e..c129492c82b3 100644 --- a/sound/pci/ac97/ac97_id.h +++ b/sound/pci/ac97/ac97_id.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Universal interface for Audio Codec '97 | 3 | * Universal interface for Audio Codec '97 |
4 | * | 4 | * |
5 | * For more details look to AC '97 component specification revision 2.2 | 5 | * For more details look to AC '97 component specification revision 2.2 |
@@ -54,6 +54,7 @@ | |||
54 | #define AC97_ID_ALC658 0x414c4780 | 54 | #define AC97_ID_ALC658 0x414c4780 |
55 | #define AC97_ID_ALC658D 0x414c4781 | 55 | #define AC97_ID_ALC658D 0x414c4781 |
56 | #define AC97_ID_ALC850 0x414c4790 | 56 | #define AC97_ID_ALC850 0x414c4790 |
57 | #define AC97_ID_YMF743 0x594d4800 | ||
57 | #define AC97_ID_YMF753 0x594d4803 | 58 | #define AC97_ID_YMF753 0x594d4803 |
58 | #define AC97_ID_VT1616 0x49434551 | 59 | #define AC97_ID_VT1616 0x49434551 |
59 | #define AC97_ID_CM9738 0x434d4941 | 60 | #define AC97_ID_CM9738 0x434d4941 |
diff --git a/sound/pci/ac97/ac97_local.h b/sound/pci/ac97/ac97_local.h index 78745c5c6df8..c276a5e3f7ac 100644 --- a/sound/pci/ac97/ac97_local.h +++ b/sound/pci/ac97/ac97_local.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Universal interface for Audio Codec '97 | 3 | * Universal interface for Audio Codec '97 |
4 | * | 4 | * |
5 | * For more details look to AC '97 component specification revision 2.2 | 5 | * For more details look to AC '97 component specification revision 2.2 |
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 581ebba4d1a7..98c8b727b62b 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Universal interface for Audio Codec '97 | 3 | * Universal interface for Audio Codec '97 |
4 | * | 4 | * |
5 | * For more details look to AC '97 component specification revision 2.2 | 5 | * For more details look to AC '97 component specification revision 2.2 |
@@ -204,9 +204,13 @@ static inline int is_shared_micin(struct snd_ac97 *ac97) | |||
204 | 204 | ||
205 | 205 | ||
206 | /* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */ | 206 | /* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */ |
207 | /* Modified for YMF743 by Keita Maehara <maehara@debian.org> */ | ||
207 | 208 | ||
208 | /* It is possible to indicate to the Yamaha YMF753 the type of speakers being used. */ | 209 | /* It is possible to indicate to the Yamaha YMF7x3 the type of |
209 | static int snd_ac97_ymf753_info_speaker(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 210 | speakers being used. */ |
211 | |||
212 | static int snd_ac97_ymf7x3_info_speaker(struct snd_kcontrol *kcontrol, | ||
213 | struct snd_ctl_elem_info *uinfo) | ||
210 | { | 214 | { |
211 | static char *texts[3] = { | 215 | static char *texts[3] = { |
212 | "Standard", "Small", "Smaller" | 216 | "Standard", "Small", "Smaller" |
@@ -221,12 +225,13 @@ static int snd_ac97_ymf753_info_speaker(struct snd_kcontrol *kcontrol, struct sn | |||
221 | return 0; | 225 | return 0; |
222 | } | 226 | } |
223 | 227 | ||
224 | static int snd_ac97_ymf753_get_speaker(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 228 | static int snd_ac97_ymf7x3_get_speaker(struct snd_kcontrol *kcontrol, |
229 | struct snd_ctl_elem_value *ucontrol) | ||
225 | { | 230 | { |
226 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); | 231 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); |
227 | unsigned short val; | 232 | unsigned short val; |
228 | 233 | ||
229 | val = ac97->regs[AC97_YMF753_3D_MODE_SEL]; | 234 | val = ac97->regs[AC97_YMF7X3_3D_MODE_SEL]; |
230 | val = (val >> 10) & 3; | 235 | val = (val >> 10) & 3; |
231 | if (val > 0) /* 0 = invalid */ | 236 | if (val > 0) /* 0 = invalid */ |
232 | val--; | 237 | val--; |
@@ -234,7 +239,8 @@ static int snd_ac97_ymf753_get_speaker(struct snd_kcontrol *kcontrol, struct snd | |||
234 | return 0; | 239 | return 0; |
235 | } | 240 | } |
236 | 241 | ||
237 | static int snd_ac97_ymf753_put_speaker(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 242 | static int snd_ac97_ymf7x3_put_speaker(struct snd_kcontrol *kcontrol, |
243 | struct snd_ctl_elem_value *ucontrol) | ||
238 | { | 244 | { |
239 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); | 245 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); |
240 | unsigned short val; | 246 | unsigned short val; |
@@ -242,20 +248,22 @@ static int snd_ac97_ymf753_put_speaker(struct snd_kcontrol *kcontrol, struct snd | |||
242 | if (ucontrol->value.enumerated.item[0] > 2) | 248 | if (ucontrol->value.enumerated.item[0] > 2) |
243 | return -EINVAL; | 249 | return -EINVAL; |
244 | val = (ucontrol->value.enumerated.item[0] + 1) << 10; | 250 | val = (ucontrol->value.enumerated.item[0] + 1) << 10; |
245 | return snd_ac97_update(ac97, AC97_YMF753_3D_MODE_SEL, val); | 251 | return snd_ac97_update(ac97, AC97_YMF7X3_3D_MODE_SEL, val); |
246 | } | 252 | } |
247 | 253 | ||
248 | static const struct snd_kcontrol_new snd_ac97_ymf753_controls_speaker = | 254 | static const struct snd_kcontrol_new snd_ac97_ymf7x3_controls_speaker = |
249 | { | 255 | { |
250 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 256 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
251 | .name = "3D Control - Speaker", | 257 | .name = "3D Control - Speaker", |
252 | .info = snd_ac97_ymf753_info_speaker, | 258 | .info = snd_ac97_ymf7x3_info_speaker, |
253 | .get = snd_ac97_ymf753_get_speaker, | 259 | .get = snd_ac97_ymf7x3_get_speaker, |
254 | .put = snd_ac97_ymf753_put_speaker, | 260 | .put = snd_ac97_ymf7x3_put_speaker, |
255 | }; | 261 | }; |
256 | 262 | ||
257 | /* It is possible to indicate to the Yamaha YMF753 the source to direct to the S/PDIF output. */ | 263 | /* It is possible to indicate to the Yamaha YMF7x3 the source to |
258 | static int snd_ac97_ymf753_spdif_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 264 | direct to the S/PDIF output. */ |
265 | static int snd_ac97_ymf7x3_spdif_source_info(struct snd_kcontrol *kcontrol, | ||
266 | struct snd_ctl_elem_info *uinfo) | ||
259 | { | 267 | { |
260 | static char *texts[2] = { "AC-Link", "A/D Converter" }; | 268 | static char *texts[2] = { "AC-Link", "A/D Converter" }; |
261 | 269 | ||
@@ -268,17 +276,19 @@ static int snd_ac97_ymf753_spdif_source_info(struct snd_kcontrol *kcontrol, stru | |||
268 | return 0; | 276 | return 0; |
269 | } | 277 | } |
270 | 278 | ||
271 | static int snd_ac97_ymf753_spdif_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 279 | static int snd_ac97_ymf7x3_spdif_source_get(struct snd_kcontrol *kcontrol, |
280 | struct snd_ctl_elem_value *ucontrol) | ||
272 | { | 281 | { |
273 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); | 282 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); |
274 | unsigned short val; | 283 | unsigned short val; |
275 | 284 | ||
276 | val = ac97->regs[AC97_YMF753_DIT_CTRL2]; | 285 | val = ac97->regs[AC97_YMF7X3_DIT_CTRL]; |
277 | ucontrol->value.enumerated.item[0] = (val >> 1) & 1; | 286 | ucontrol->value.enumerated.item[0] = (val >> 1) & 1; |
278 | return 0; | 287 | return 0; |
279 | } | 288 | } |
280 | 289 | ||
281 | static int snd_ac97_ymf753_spdif_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 290 | static int snd_ac97_ymf7x3_spdif_source_put(struct snd_kcontrol *kcontrol, |
291 | struct snd_ctl_elem_value *ucontrol) | ||
282 | { | 292 | { |
283 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); | 293 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); |
284 | unsigned short val; | 294 | unsigned short val; |
@@ -286,7 +296,75 @@ static int snd_ac97_ymf753_spdif_source_put(struct snd_kcontrol *kcontrol, struc | |||
286 | if (ucontrol->value.enumerated.item[0] > 1) | 296 | if (ucontrol->value.enumerated.item[0] > 1) |
287 | return -EINVAL; | 297 | return -EINVAL; |
288 | val = ucontrol->value.enumerated.item[0] << 1; | 298 | val = ucontrol->value.enumerated.item[0] << 1; |
289 | return snd_ac97_update_bits(ac97, AC97_YMF753_DIT_CTRL2, 0x0002, val); | 299 | return snd_ac97_update_bits(ac97, AC97_YMF7X3_DIT_CTRL, 0x0002, val); |
300 | } | ||
301 | |||
302 | static int patch_yamaha_ymf7x3_3d(struct snd_ac97 *ac97) | ||
303 | { | ||
304 | struct snd_kcontrol *kctl; | ||
305 | int err; | ||
306 | |||
307 | kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97); | ||
308 | err = snd_ctl_add(ac97->bus->card, kctl); | ||
309 | if (err < 0) | ||
310 | return err; | ||
311 | strcpy(kctl->id.name, "3D Control - Wide"); | ||
312 | kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 9, 7, 0); | ||
313 | snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000); | ||
314 | err = snd_ctl_add(ac97->bus->card, | ||
315 | snd_ac97_cnew(&snd_ac97_ymf7x3_controls_speaker, | ||
316 | ac97)); | ||
317 | if (err < 0) | ||
318 | return err; | ||
319 | snd_ac97_write_cache(ac97, AC97_YMF7X3_3D_MODE_SEL, 0x0c00); | ||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | static const struct snd_kcontrol_new snd_ac97_yamaha_ymf743_controls_spdif[3] = | ||
324 | { | ||
325 | AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH), | ||
326 | AC97_YMF7X3_DIT_CTRL, 0, 1, 0), | ||
327 | { | ||
328 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
329 | .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, NONE) "Source", | ||
330 | .info = snd_ac97_ymf7x3_spdif_source_info, | ||
331 | .get = snd_ac97_ymf7x3_spdif_source_get, | ||
332 | .put = snd_ac97_ymf7x3_spdif_source_put, | ||
333 | }, | ||
334 | AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", NONE, NONE) "Mute", | ||
335 | AC97_YMF7X3_DIT_CTRL, 2, 1, 1) | ||
336 | }; | ||
337 | |||
338 | static int patch_yamaha_ymf743_build_spdif(struct snd_ac97 *ac97) | ||
339 | { | ||
340 | int err; | ||
341 | |||
342 | err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3); | ||
343 | if (err < 0) | ||
344 | return err; | ||
345 | err = patch_build_controls(ac97, | ||
346 | snd_ac97_yamaha_ymf743_controls_spdif, 3); | ||
347 | if (err < 0) | ||
348 | return err; | ||
349 | /* set default PCM S/PDIF params */ | ||
350 | /* PCM audio,no copyright,no preemphasis,PCM coder,original */ | ||
351 | snd_ac97_write_cache(ac97, AC97_YMF7X3_DIT_CTRL, 0xa201); | ||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static struct snd_ac97_build_ops patch_yamaha_ymf743_ops = { | ||
356 | .build_spdif = patch_yamaha_ymf743_build_spdif, | ||
357 | .build_3d = patch_yamaha_ymf7x3_3d, | ||
358 | }; | ||
359 | |||
360 | static int patch_yamaha_ymf743(struct snd_ac97 *ac97) | ||
361 | { | ||
362 | ac97->build_ops = &patch_yamaha_ymf743_ops; | ||
363 | ac97->caps |= AC97_BC_BASS_TREBLE; | ||
364 | ac97->caps |= 0x04 << 10; /* Yamaha 3D enhancement */ | ||
365 | ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */ | ||
366 | ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */ | ||
367 | return 0; | ||
290 | } | 368 | } |
291 | 369 | ||
292 | /* The AC'97 spec states that the S/PDIF signal is to be output at pin 48. | 370 | /* The AC'97 spec states that the S/PDIF signal is to be output at pin 48. |
@@ -311,7 +389,7 @@ static int snd_ac97_ymf753_spdif_output_pin_get(struct snd_kcontrol *kcontrol, s | |||
311 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); | 389 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); |
312 | unsigned short val; | 390 | unsigned short val; |
313 | 391 | ||
314 | val = ac97->regs[AC97_YMF753_DIT_CTRL2]; | 392 | val = ac97->regs[AC97_YMF7X3_DIT_CTRL]; |
315 | ucontrol->value.enumerated.item[0] = (val & 0x0008) ? 2 : (val & 0x0020) ? 1 : 0; | 393 | ucontrol->value.enumerated.item[0] = (val & 0x0008) ? 2 : (val & 0x0020) ? 1 : 0; |
316 | return 0; | 394 | return 0; |
317 | } | 395 | } |
@@ -325,7 +403,7 @@ static int snd_ac97_ymf753_spdif_output_pin_put(struct snd_kcontrol *kcontrol, s | |||
325 | return -EINVAL; | 403 | return -EINVAL; |
326 | val = (ucontrol->value.enumerated.item[0] == 2) ? 0x0008 : | 404 | val = (ucontrol->value.enumerated.item[0] == 2) ? 0x0008 : |
327 | (ucontrol->value.enumerated.item[0] == 1) ? 0x0020 : 0; | 405 | (ucontrol->value.enumerated.item[0] == 1) ? 0x0020 : 0; |
328 | return snd_ac97_update_bits(ac97, AC97_YMF753_DIT_CTRL2, 0x0028, val); | 406 | return snd_ac97_update_bits(ac97, AC97_YMF7X3_DIT_CTRL, 0x0028, val); |
329 | /* The following can be used to direct S/PDIF output to pin 47 (EAPD). | 407 | /* The following can be used to direct S/PDIF output to pin 47 (EAPD). |
330 | snd_ac97_write_cache(ac97, 0x62, snd_ac97_read(ac97, 0x62) | 0x0008); */ | 408 | snd_ac97_write_cache(ac97, 0x62, snd_ac97_read(ac97, 0x62) | 0x0008); */ |
331 | } | 409 | } |
@@ -334,9 +412,9 @@ static const struct snd_kcontrol_new snd_ac97_ymf753_controls_spdif[3] = { | |||
334 | { | 412 | { |
335 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 413 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
336 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", | 414 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", |
337 | .info = snd_ac97_ymf753_spdif_source_info, | 415 | .info = snd_ac97_ymf7x3_spdif_source_info, |
338 | .get = snd_ac97_ymf753_spdif_source_get, | 416 | .get = snd_ac97_ymf7x3_spdif_source_get, |
339 | .put = snd_ac97_ymf753_spdif_source_put, | 417 | .put = snd_ac97_ymf7x3_spdif_source_put, |
340 | }, | 418 | }, |
341 | { | 419 | { |
342 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 420 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -345,25 +423,10 @@ static const struct snd_kcontrol_new snd_ac97_ymf753_controls_spdif[3] = { | |||
345 | .get = snd_ac97_ymf753_spdif_output_pin_get, | 423 | .get = snd_ac97_ymf753_spdif_output_pin_get, |
346 | .put = snd_ac97_ymf753_spdif_output_pin_put, | 424 | .put = snd_ac97_ymf753_spdif_output_pin_put, |
347 | }, | 425 | }, |
348 | AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",NONE,NONE) "Mute", AC97_YMF753_DIT_CTRL2, 2, 1, 1) | 426 | AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", NONE, NONE) "Mute", |
427 | AC97_YMF7X3_DIT_CTRL, 2, 1, 1) | ||
349 | }; | 428 | }; |
350 | 429 | ||
351 | static int patch_yamaha_ymf753_3d(struct snd_ac97 * ac97) | ||
352 | { | ||
353 | struct snd_kcontrol *kctl; | ||
354 | int err; | ||
355 | |||
356 | if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0) | ||
357 | return err; | ||
358 | strcpy(kctl->id.name, "3D Control - Wide"); | ||
359 | kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 9, 7, 0); | ||
360 | snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000); | ||
361 | if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&snd_ac97_ymf753_controls_speaker, ac97))) < 0) | ||
362 | return err; | ||
363 | snd_ac97_write_cache(ac97, AC97_YMF753_3D_MODE_SEL, 0x0c00); | ||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | static int patch_yamaha_ymf753_post_spdif(struct snd_ac97 * ac97) | 430 | static int patch_yamaha_ymf753_post_spdif(struct snd_ac97 * ac97) |
368 | { | 431 | { |
369 | int err; | 432 | int err; |
@@ -374,7 +437,7 @@ static int patch_yamaha_ymf753_post_spdif(struct snd_ac97 * ac97) | |||
374 | } | 437 | } |
375 | 438 | ||
376 | static struct snd_ac97_build_ops patch_yamaha_ymf753_ops = { | 439 | static struct snd_ac97_build_ops patch_yamaha_ymf753_ops = { |
377 | .build_3d = patch_yamaha_ymf753_3d, | 440 | .build_3d = patch_yamaha_ymf7x3_3d, |
378 | .build_post_spdif = patch_yamaha_ymf753_post_spdif | 441 | .build_post_spdif = patch_yamaha_ymf753_post_spdif |
379 | }; | 442 | }; |
380 | 443 | ||
@@ -1880,14 +1943,7 @@ static int patch_ad1981b(struct snd_ac97 *ac97) | |||
1880 | return 0; | 1943 | return 0; |
1881 | } | 1944 | } |
1882 | 1945 | ||
1883 | static int snd_ac97_ad1888_lohpsel_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1946 | #define snd_ac97_ad1888_lohpsel_info snd_ctl_boolean_mono_info |
1884 | { | ||
1885 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1886 | uinfo->count = 1; | ||
1887 | uinfo->value.integer.min = 0; | ||
1888 | uinfo->value.integer.max = 1; | ||
1889 | return 0; | ||
1890 | } | ||
1891 | 1947 | ||
1892 | static int snd_ac97_ad1888_lohpsel_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1948 | static int snd_ac97_ad1888_lohpsel_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1893 | { | 1949 | { |
@@ -2186,15 +2242,7 @@ static int patch_ad1985(struct snd_ac97 * ac97) | |||
2186 | return 0; | 2242 | return 0; |
2187 | } | 2243 | } |
2188 | 2244 | ||
2189 | static int snd_ac97_ad1986_bool_info(struct snd_kcontrol *kcontrol, | 2245 | #define snd_ac97_ad1986_bool_info snd_ctl_boolean_mono_info |
2190 | struct snd_ctl_elem_info *uinfo) | ||
2191 | { | ||
2192 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2193 | uinfo->count = 1; | ||
2194 | uinfo->value.integer.min = 0; | ||
2195 | uinfo->value.integer.max = 1; | ||
2196 | return 0; | ||
2197 | } | ||
2198 | 2246 | ||
2199 | static int snd_ac97_ad1986_lososel_get(struct snd_kcontrol *kcontrol, | 2247 | static int snd_ac97_ad1986_lososel_get(struct snd_kcontrol *kcontrol, |
2200 | struct snd_ctl_elem_value *ucontrol) | 2248 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/ac97/ac97_patch.h b/sound/pci/ac97/ac97_patch.h index fd341ce63762..9cccc27ea1b5 100644 --- a/sound/pci/ac97/ac97_patch.h +++ b/sound/pci/ac97/ac97_patch.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Universal interface for Audio Codec '97 | 3 | * Universal interface for Audio Codec '97 |
4 | * | 4 | * |
5 | * For more details look to AC '97 component specification revision 2.2 | 5 | * For more details look to AC '97 component specification revision 2.2 |
diff --git a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c index 4281e6d0c5b6..8cbc03332b01 100644 --- a/sound/pci/ac97/ac97_pcm.c +++ b/sound/pci/ac97/ac97_pcm.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Universal interface for Audio Codec '97 | 3 | * Universal interface for Audio Codec '97 |
4 | * | 4 | * |
5 | * For more details look to AC '97 component specification revision 2.2 | 5 | * For more details look to AC '97 component specification revision 2.2 |
diff --git a/sound/pci/ac97/ac97_proc.c b/sound/pci/ac97/ac97_proc.c index a3fdd7da911c..fed4a2c3d8a1 100644 --- a/sound/pci/ac97/ac97_proc.c +++ b/sound/pci/ac97/ac97_proc.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Universal interface for Audio Codec '97 | 3 | * Universal interface for Audio Codec '97 |
4 | * | 4 | * |
5 | * For more details look to AC '97 component specification revision 2.2 | 5 | * For more details look to AC '97 component specification revision 2.2 |
@@ -236,10 +236,14 @@ static void snd_ac97_proc_read_main(struct snd_ac97 *ac97, struct snd_info_buffe | |||
236 | val = snd_ac97_read(ac97, AC97_PCM_MIC_ADC_RATE); | 236 | val = snd_ac97_read(ac97, AC97_PCM_MIC_ADC_RATE); |
237 | snd_iprintf(buffer, "PCM MIC ADC : %iHz\n", val); | 237 | snd_iprintf(buffer, "PCM MIC ADC : %iHz\n", val); |
238 | } | 238 | } |
239 | if ((ext & AC97_EI_SPDIF) || (ac97->flags & AC97_CS_SPDIF)) { | 239 | if ((ext & AC97_EI_SPDIF) || (ac97->flags & AC97_CS_SPDIF) || |
240 | (ac97->id == AC97_ID_YMF743)) { | ||
240 | if (ac97->flags & AC97_CS_SPDIF) | 241 | if (ac97->flags & AC97_CS_SPDIF) |
241 | val = snd_ac97_read(ac97, AC97_CSR_SPDIF); | 242 | val = snd_ac97_read(ac97, AC97_CSR_SPDIF); |
242 | else | 243 | else if (ac97->id == AC97_ID_YMF743) { |
244 | val = snd_ac97_read(ac97, AC97_YMF7X3_DIT_CTRL); | ||
245 | val = 0x2000 | (val & 0xff00) >> 4 | (val & 0x38) >> 2; | ||
246 | } else | ||
243 | val = snd_ac97_read(ac97, AC97_SPDIF); | 247 | val = snd_ac97_read(ac97, AC97_SPDIF); |
244 | 248 | ||
245 | snd_iprintf(buffer, "SPDIF Control :%s%s%s%s Category=0x%x Generation=%i%s%s%s\n", | 249 | snd_iprintf(buffer, "SPDIF Control :%s%s%s%s Category=0x%x Generation=%i%s%s%s\n", |
diff --git a/sound/pci/ac97/ak4531_codec.c b/sound/pci/ac97/ak4531_codec.c index dc26820a03a5..722de451d15f 100644 --- a/sound/pci/ac97/ak4531_codec.c +++ b/sound/pci/ac97/ak4531_codec.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Universal routines for AK4531 codec | 3 | * Universal routines for AK4531 codec |
4 | * | 4 | * |
5 | * | 5 | * |
@@ -29,7 +29,7 @@ | |||
29 | #include <sound/ak4531_codec.h> | 29 | #include <sound/ak4531_codec.h> |
30 | #include <sound/tlv.h> | 30 | #include <sound/tlv.h> |
31 | 31 | ||
32 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 32 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
33 | MODULE_DESCRIPTION("Universal routines for AK4531 codec"); | 33 | MODULE_DESCRIPTION("Universal routines for AK4531 codec"); |
34 | MODULE_LICENSE("GPL"); | 34 | MODULE_LICENSE("GPL"); |
35 | 35 | ||
diff --git a/sound/pci/ali5451/Makefile b/sound/pci/ali5451/Makefile index 2e1831597474..713459c12d22 100644 --- a/sound/pci/ali5451/Makefile +++ b/sound/pci/ali5451/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-ali5451-objs := ali5451.o | 6 | snd-ali5451-objs := ali5451.o |
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index 05b4c8696941..4c2bd7adf674 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c | |||
@@ -1804,15 +1804,7 @@ static int __devinit snd_ali_build_pcms(struct snd_ali *codec) | |||
1804 | .info = snd_ali5451_spdif_info, .get = snd_ali5451_spdif_get, \ | 1804 | .info = snd_ali5451_spdif_info, .get = snd_ali5451_spdif_get, \ |
1805 | .put = snd_ali5451_spdif_put, .private_value = value} | 1805 | .put = snd_ali5451_spdif_put, .private_value = value} |
1806 | 1806 | ||
1807 | static int snd_ali5451_spdif_info(struct snd_kcontrol *kcontrol, | 1807 | #define snd_ali5451_spdif_info snd_ctl_boolean_mono_info |
1808 | struct snd_ctl_elem_info *uinfo) | ||
1809 | { | ||
1810 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1811 | uinfo->count = 1; | ||
1812 | uinfo->value.integer.min = 0; | ||
1813 | uinfo->value.integer.max = 1; | ||
1814 | return 0; | ||
1815 | } | ||
1816 | 1808 | ||
1817 | static int snd_ali5451_spdif_get(struct snd_kcontrol *kcontrol, | 1809 | static int snd_ali5451_spdif_get(struct snd_kcontrol *kcontrol, |
1818 | struct snd_ctl_elem_value *ucontrol) | 1810 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index 8fb55d3b454b..1190ef366a41 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * card-als4000.c - driver for Avance Logic ALS4000 based soundcards. | 2 | * card-als4000.c - driver for Avance Logic ALS4000 based soundcards. |
3 | * Copyright (C) 2000 by Bart Hartgers <bart@etpmod.phys.tue.nl>, | 3 | * Copyright (C) 2000 by Bart Hartgers <bart@etpmod.phys.tue.nl>, |
4 | * Jaroslav Kysela <perex@suse.cz> | 4 | * Jaroslav Kysela <perex@perex.cz> |
5 | * Copyright (C) 2002 by Andreas Mohr <hw7oshyuv3001@sneakemail.com> | 5 | * Copyright (C) 2002 by Andreas Mohr <hw7oshyuv3001@sneakemail.com> |
6 | * | 6 | * |
7 | * Framework borrowed from Massimo Piccioni's card-als100.c. | 7 | * Framework borrowed from Massimo Piccioni's card-als100.c. |
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c index 5ec1b6fcd548..f70286a7364a 100644 --- a/sound/pci/au88x0/au88x0.c +++ b/sound/pci/au88x0/au88x0.c | |||
@@ -232,6 +232,7 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip) | |||
232 | pci_disable_device(chip->pci_dev); | 232 | pci_disable_device(chip->pci_dev); |
233 | //FIXME: this not the right place to unregister the gameport | 233 | //FIXME: this not the right place to unregister the gameport |
234 | vortex_gameport_unregister(chip); | 234 | vortex_gameport_unregister(chip); |
235 | kfree(chip); | ||
235 | return err; | 236 | return err; |
236 | } | 237 | } |
237 | 238 | ||
diff --git a/sound/pci/au88x0/au88x0_eq.c b/sound/pci/au88x0/au88x0_eq.c index 0c86a31c4336..38602b85874d 100644 --- a/sound/pci/au88x0/au88x0_eq.c +++ b/sound/pci/au88x0/au88x0_eq.c | |||
@@ -728,15 +728,7 @@ static void vortex_Eqlzr_shutdown(vortex_t * vortex) | |||
728 | /* ALSA interface */ | 728 | /* ALSA interface */ |
729 | 729 | ||
730 | /* Control interface */ | 730 | /* Control interface */ |
731 | static int | 731 | #define snd_vortex_eqtoggle_info snd_ctl_boolean_mono_info |
732 | snd_vortex_eqtoggle_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | ||
733 | { | ||
734 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
735 | uinfo->count = 1; | ||
736 | uinfo->value.integer.min = 0; | ||
737 | uinfo->value.integer.max = 1; | ||
738 | return 0; | ||
739 | } | ||
740 | 732 | ||
741 | static int | 733 | static int |
742 | snd_vortex_eqtoggle_get(struct snd_kcontrol *kcontrol, | 734 | snd_vortex_eqtoggle_get(struct snd_kcontrol *kcontrol, |
diff --git a/sound/pci/au88x0/au88x0_mpu401.c b/sound/pci/au88x0/au88x0_mpu401.c index c75d368ea087..8db3d3e6f7bb 100644 --- a/sound/pci/au88x0/au88x0_mpu401.c +++ b/sound/pci/au88x0/au88x0_mpu401.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for control of MPU-401 in UART mode | 3 | * Routines for control of MPU-401 in UART mode |
4 | * | 4 | * |
5 | * Modified for the Aureal Vortex based Soundcards | 5 | * Modified for the Aureal Vortex based Soundcards |
diff --git a/sound/pci/au88x0/au88x0_synth.c b/sound/pci/au88x0/au88x0_synth.c index d3e662a1285d..978b856f5621 100644 --- a/sound/pci/au88x0/au88x0_synth.c +++ b/sound/pci/au88x0/au88x0_synth.c | |||
@@ -370,8 +370,8 @@ static void vortex_wt_SetFrequency(vortex_t * vortex, int wt, unsigned int sr) | |||
370 | while ((edx & 0x80000000) == 0) { | 370 | while ((edx & 0x80000000) == 0) { |
371 | edx <<= 1; | 371 | edx <<= 1; |
372 | eax--; | 372 | eax--; |
373 | if (eax == 0) ; | 373 | if (eax == 0) |
374 | break; | 374 | break; |
375 | } | 375 | } |
376 | if (eax) | 376 | if (eax) |
377 | edx <<= 1; | 377 | edx <<= 1; |
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 131952f55857..91f9e6a112ff 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c | |||
@@ -147,15 +147,56 @@ MODULE_PARM_DESC(load_all, "Allow to load the non-whitelisted cards"); | |||
147 | /* SYNC, one WRITE per line, one extra WRITE per page boundary, SYNC, JUMP */ | 147 | /* SYNC, one WRITE per line, one extra WRITE per page boundary, SYNC, JUMP */ |
148 | #define MAX_RISC_SIZE ((1 + 255 + (PAGE_ALIGN(255 * 4092) / PAGE_SIZE - 1) + 1 + 1) * 8) | 148 | #define MAX_RISC_SIZE ((1 + 255 + (PAGE_ALIGN(255 * 4092) / PAGE_SIZE - 1) + 1 + 1) * 8) |
149 | 149 | ||
150 | /* Cards with configuration information */ | ||
151 | enum snd_bt87x_boardid { | ||
152 | SND_BT87X_BOARD_UNKNOWN, | ||
153 | SND_BT87X_BOARD_GENERIC, /* both an & dig interfaces, 32kHz */ | ||
154 | SND_BT87X_BOARD_ANALOG, /* board with no external A/D */ | ||
155 | SND_BT87X_BOARD_OSPREY2x0, | ||
156 | SND_BT87X_BOARD_OSPREY440, | ||
157 | SND_BT87X_BOARD_AVPHONE98, | ||
158 | }; | ||
159 | |||
160 | /* Card configuration */ | ||
161 | struct snd_bt87x_board { | ||
162 | int dig_rate; /* Digital input sampling rate */ | ||
163 | u32 digital_fmt; /* Register settings for digital input */ | ||
164 | unsigned no_analog:1; /* No analog input */ | ||
165 | unsigned no_digital:1; /* No digital input */ | ||
166 | }; | ||
167 | |||
168 | static const __devinitdata struct snd_bt87x_board snd_bt87x_boards[] = { | ||
169 | [SND_BT87X_BOARD_UNKNOWN] = { | ||
170 | .dig_rate = 32000, /* just a guess */ | ||
171 | }, | ||
172 | [SND_BT87X_BOARD_GENERIC] = { | ||
173 | .dig_rate = 32000, | ||
174 | }, | ||
175 | [SND_BT87X_BOARD_ANALOG] = { | ||
176 | .no_digital = 1, | ||
177 | }, | ||
178 | [SND_BT87X_BOARD_OSPREY2x0] = { | ||
179 | .dig_rate = 44100, | ||
180 | .digital_fmt = CTL_DA_LRI | (1 << CTL_DA_LRD_SHIFT), | ||
181 | }, | ||
182 | [SND_BT87X_BOARD_OSPREY440] = { | ||
183 | .dig_rate = 32000, | ||
184 | .digital_fmt = CTL_DA_LRI | (1 << CTL_DA_LRD_SHIFT), | ||
185 | .no_analog = 1, | ||
186 | }, | ||
187 | [SND_BT87X_BOARD_AVPHONE98] = { | ||
188 | .dig_rate = 48000, | ||
189 | }, | ||
190 | }; | ||
191 | |||
150 | struct snd_bt87x { | 192 | struct snd_bt87x { |
151 | struct snd_card *card; | 193 | struct snd_card *card; |
152 | struct pci_dev *pci; | 194 | struct pci_dev *pci; |
195 | struct snd_bt87x_board board; | ||
153 | 196 | ||
154 | void __iomem *mmio; | 197 | void __iomem *mmio; |
155 | int irq; | 198 | int irq; |
156 | 199 | ||
157 | int dig_rate; | ||
158 | |||
159 | spinlock_t reg_lock; | 200 | spinlock_t reg_lock; |
160 | unsigned long opened; | 201 | unsigned long opened; |
161 | struct snd_pcm_substream *substream; | 202 | struct snd_pcm_substream *substream; |
@@ -340,30 +381,11 @@ static struct snd_pcm_hardware snd_bt87x_analog_hw = { | |||
340 | 381 | ||
341 | static int snd_bt87x_set_digital_hw(struct snd_bt87x *chip, struct snd_pcm_runtime *runtime) | 382 | static int snd_bt87x_set_digital_hw(struct snd_bt87x *chip, struct snd_pcm_runtime *runtime) |
342 | { | 383 | { |
343 | static struct { | 384 | chip->reg_control |= CTL_DA_IOM_DA | CTL_A_PWRDN; |
344 | int rate; | ||
345 | unsigned int bit; | ||
346 | } ratebits[] = { | ||
347 | {8000, SNDRV_PCM_RATE_8000}, | ||
348 | {11025, SNDRV_PCM_RATE_11025}, | ||
349 | {16000, SNDRV_PCM_RATE_16000}, | ||
350 | {22050, SNDRV_PCM_RATE_22050}, | ||
351 | {32000, SNDRV_PCM_RATE_32000}, | ||
352 | {44100, SNDRV_PCM_RATE_44100}, | ||
353 | {48000, SNDRV_PCM_RATE_48000} | ||
354 | }; | ||
355 | int i; | ||
356 | |||
357 | chip->reg_control |= CTL_DA_IOM_DA; | ||
358 | runtime->hw = snd_bt87x_digital_hw; | 385 | runtime->hw = snd_bt87x_digital_hw; |
359 | runtime->hw.rates = SNDRV_PCM_RATE_KNOT; | 386 | runtime->hw.rates = snd_pcm_rate_to_rate_bit(chip->board.dig_rate); |
360 | for (i = 0; i < ARRAY_SIZE(ratebits); ++i) | 387 | runtime->hw.rate_min = chip->board.dig_rate; |
361 | if (chip->dig_rate == ratebits[i].rate) { | 388 | runtime->hw.rate_max = chip->board.dig_rate; |
362 | runtime->hw.rates = ratebits[i].bit; | ||
363 | break; | ||
364 | } | ||
365 | runtime->hw.rate_min = chip->dig_rate; | ||
366 | runtime->hw.rate_max = chip->dig_rate; | ||
367 | return 0; | 389 | return 0; |
368 | } | 390 | } |
369 | 391 | ||
@@ -380,7 +402,7 @@ static int snd_bt87x_set_analog_hw(struct snd_bt87x *chip, struct snd_pcm_runtim | |||
380 | .rats = &analog_clock | 402 | .rats = &analog_clock |
381 | }; | 403 | }; |
382 | 404 | ||
383 | chip->reg_control &= ~CTL_DA_IOM_DA; | 405 | chip->reg_control &= ~(CTL_DA_IOM_DA | CTL_A_PWRDN); |
384 | runtime->hw = snd_bt87x_analog_hw; | 406 | runtime->hw = snd_bt87x_analog_hw; |
385 | return snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | 407 | return snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, |
386 | &constraint_rates); | 408 | &constraint_rates); |
@@ -419,6 +441,11 @@ static int snd_bt87x_close(struct snd_pcm_substream *substream) | |||
419 | { | 441 | { |
420 | struct snd_bt87x *chip = snd_pcm_substream_chip(substream); | 442 | struct snd_bt87x *chip = snd_pcm_substream_chip(substream); |
421 | 443 | ||
444 | spin_lock_irq(&chip->reg_lock); | ||
445 | chip->reg_control |= CTL_A_PWRDN; | ||
446 | snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); | ||
447 | spin_unlock_irq(&chip->reg_lock); | ||
448 | |||
422 | chip->substream = NULL; | 449 | chip->substream = NULL; |
423 | clear_bit(0, &chip->opened); | 450 | clear_bit(0, &chip->opened); |
424 | smp_mb__after_clear_bit(); | 451 | smp_mb__after_clear_bit(); |
@@ -569,15 +596,7 @@ static struct snd_kcontrol_new snd_bt87x_capture_volume = { | |||
569 | .put = snd_bt87x_capture_volume_put, | 596 | .put = snd_bt87x_capture_volume_put, |
570 | }; | 597 | }; |
571 | 598 | ||
572 | static int snd_bt87x_capture_boost_info(struct snd_kcontrol *kcontrol, | 599 | #define snd_bt87x_capture_boost_info snd_ctl_boolean_mono_info |
573 | struct snd_ctl_elem_info *info) | ||
574 | { | ||
575 | info->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
576 | info->count = 1; | ||
577 | info->value.integer.min = 0; | ||
578 | info->value.integer.max = 1; | ||
579 | return 0; | ||
580 | } | ||
581 | 600 | ||
582 | static int snd_bt87x_capture_boost_get(struct snd_kcontrol *kcontrol, | 601 | static int snd_bt87x_capture_boost_get(struct snd_kcontrol *kcontrol, |
583 | struct snd_ctl_elem_value *value) | 602 | struct snd_ctl_elem_value *value) |
@@ -736,61 +755,69 @@ static int __devinit snd_bt87x_create(struct snd_card *card, | |||
736 | chip->mmio = ioremap_nocache(pci_resource_start(pci, 0), | 755 | chip->mmio = ioremap_nocache(pci_resource_start(pci, 0), |
737 | pci_resource_len(pci, 0)); | 756 | pci_resource_len(pci, 0)); |
738 | if (!chip->mmio) { | 757 | if (!chip->mmio) { |
739 | snd_bt87x_free(chip); | ||
740 | snd_printk(KERN_ERR "cannot remap io memory\n"); | 758 | snd_printk(KERN_ERR "cannot remap io memory\n"); |
741 | return -ENOMEM; | 759 | err = -ENOMEM; |
760 | goto fail; | ||
742 | } | 761 | } |
743 | 762 | ||
744 | chip->reg_control = CTL_DA_ES2 | CTL_PKTP_16 | (15 << CTL_DA_SDR_SHIFT); | 763 | chip->reg_control = CTL_A_PWRDN | CTL_DA_ES2 | |
764 | CTL_PKTP_16 | (15 << CTL_DA_SDR_SHIFT); | ||
745 | chip->interrupt_mask = MY_INTERRUPTS; | 765 | chip->interrupt_mask = MY_INTERRUPTS; |
746 | snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); | 766 | snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); |
747 | snd_bt87x_writel(chip, REG_INT_MASK, 0); | 767 | snd_bt87x_writel(chip, REG_INT_MASK, 0); |
748 | snd_bt87x_writel(chip, REG_INT_STAT, MY_INTERRUPTS); | 768 | snd_bt87x_writel(chip, REG_INT_STAT, MY_INTERRUPTS); |
749 | 769 | ||
750 | if (request_irq(pci->irq, snd_bt87x_interrupt, IRQF_SHARED, | 770 | err = request_irq(pci->irq, snd_bt87x_interrupt, IRQF_SHARED, |
751 | "Bt87x audio", chip)) { | 771 | "Bt87x audio", chip); |
752 | snd_bt87x_free(chip); | 772 | if (err < 0) { |
753 | snd_printk(KERN_ERR "cannot grab irq\n"); | 773 | snd_printk(KERN_ERR "cannot grab irq %d\n", pci->irq); |
754 | return -EBUSY; | 774 | goto fail; |
755 | } | 775 | } |
756 | chip->irq = pci->irq; | 776 | chip->irq = pci->irq; |
757 | pci_set_master(pci); | 777 | pci_set_master(pci); |
758 | synchronize_irq(chip->irq); | 778 | synchronize_irq(chip->irq); |
759 | 779 | ||
760 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); | 780 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); |
761 | if (err < 0) { | 781 | if (err < 0) |
762 | snd_bt87x_free(chip); | 782 | goto fail; |
763 | return err; | 783 | |
764 | } | ||
765 | snd_card_set_dev(card, &pci->dev); | 784 | snd_card_set_dev(card, &pci->dev); |
766 | *rchip = chip; | 785 | *rchip = chip; |
767 | return 0; | 786 | return 0; |
787 | |||
788 | fail: | ||
789 | snd_bt87x_free(chip); | ||
790 | return err; | ||
768 | } | 791 | } |
769 | 792 | ||
770 | #define BT_DEVICE(chip, subvend, subdev, rate) \ | 793 | #define BT_DEVICE(chip, subvend, subdev, id) \ |
771 | { .vendor = PCI_VENDOR_ID_BROOKTREE, \ | 794 | { .vendor = PCI_VENDOR_ID_BROOKTREE, \ |
772 | .device = chip, \ | 795 | .device = chip, \ |
773 | .subvendor = subvend, .subdevice = subdev, \ | 796 | .subvendor = subvend, .subdevice = subdev, \ |
774 | .driver_data = rate } | 797 | .driver_data = SND_BT87X_BOARD_ ## id } |
798 | /* driver_data is the card id for that device */ | ||
775 | 799 | ||
776 | /* driver_data is the default digital_rate value for that device */ | ||
777 | static struct pci_device_id snd_bt87x_ids[] = { | 800 | static struct pci_device_id snd_bt87x_ids[] = { |
778 | /* Hauppauge WinTV series */ | 801 | /* Hauppauge WinTV series */ |
779 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0x13eb, 32000), | 802 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0x13eb, GENERIC), |
780 | /* Hauppauge WinTV series */ | 803 | /* Hauppauge WinTV series */ |
781 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, 0x0070, 0x13eb, 32000), | 804 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, 0x0070, 0x13eb, GENERIC), |
782 | /* Viewcast Osprey 200 */ | 805 | /* Viewcast Osprey 200 */ |
783 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff01, 44100), | 806 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff01, OSPREY2x0), |
784 | /* Viewcast Osprey 440 (rate is configurable via gpio) */ | 807 | /* Viewcast Osprey 440 (rate is configurable via gpio) */ |
785 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff07, 32000), | 808 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff07, OSPREY440), |
786 | /* ATI TV-Wonder */ | 809 | /* ATI TV-Wonder */ |
787 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1002, 0x0001, 32000), | 810 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1002, 0x0001, GENERIC), |
788 | /* Leadtek Winfast tv 2000xp delux */ | 811 | /* Leadtek Winfast tv 2000xp delux */ |
789 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x107d, 0x6606, 32000), | 812 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x107d, 0x6606, GENERIC), |
790 | /* Voodoo TV 200 */ | 813 | /* Voodoo TV 200 */ |
791 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x121a, 0x3000, 32000), | 814 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x121a, 0x3000, GENERIC), |
792 | /* AVerMedia Studio No. 103, 203, ...? */ | 815 | /* AVerMedia Studio No. 103, 203, ...? */ |
793 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1461, 0x0003, 48000), | 816 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1461, 0x0003, AVPHONE98), |
817 | /* Prolink PixelView PV-M4900 */ | ||
818 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1554, 0x4011, GENERIC), | ||
819 | /* Pinnacle Studio PCTV rave */ | ||
820 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0xbd11, 0x1200, GENERIC), | ||
794 | { } | 821 | { } |
795 | }; | 822 | }; |
796 | MODULE_DEVICE_TABLE(pci, snd_bt87x_ids); | 823 | MODULE_DEVICE_TABLE(pci, snd_bt87x_ids); |
@@ -815,7 +842,7 @@ static struct { | |||
815 | 842 | ||
816 | static struct pci_driver driver; | 843 | static struct pci_driver driver; |
817 | 844 | ||
818 | /* return the rate of the card, or a negative value if it's blacklisted */ | 845 | /* return the id of the card, or a negative value if it's blacklisted */ |
819 | static int __devinit snd_bt87x_detect_card(struct pci_dev *pci) | 846 | static int __devinit snd_bt87x_detect_card(struct pci_dev *pci) |
820 | { | 847 | { |
821 | int i; | 848 | int i; |
@@ -833,12 +860,12 @@ static int __devinit snd_bt87x_detect_card(struct pci_dev *pci) | |||
833 | return -EBUSY; | 860 | return -EBUSY; |
834 | } | 861 | } |
835 | 862 | ||
836 | snd_printk(KERN_INFO "unknown card %#04x-%#04x:%#04x, using default rate 32000\n", | 863 | snd_printk(KERN_INFO "unknown card %#04x-%#04x:%#04x\n", |
837 | pci->device, pci->subsystem_vendor, pci->subsystem_device); | 864 | pci->device, pci->subsystem_vendor, pci->subsystem_device); |
838 | snd_printk(KERN_DEBUG "please mail id, board name, and, " | 865 | snd_printk(KERN_DEBUG "please mail id, board name, and, " |
839 | "if it works, the correct digital_rate option to " | 866 | "if it works, the correct digital_rate option to " |
840 | "<alsa-devel@alsa-project.org>\n"); | 867 | "<alsa-devel@alsa-project.org>\n"); |
841 | return 32000; /* default rate */ | 868 | return SND_BT87X_BOARD_UNKNOWN; |
842 | } | 869 | } |
843 | 870 | ||
844 | static int __devinit snd_bt87x_probe(struct pci_dev *pci, | 871 | static int __devinit snd_bt87x_probe(struct pci_dev *pci, |
@@ -847,12 +874,16 @@ static int __devinit snd_bt87x_probe(struct pci_dev *pci, | |||
847 | static int dev; | 874 | static int dev; |
848 | struct snd_card *card; | 875 | struct snd_card *card; |
849 | struct snd_bt87x *chip; | 876 | struct snd_bt87x *chip; |
850 | int err, rate; | 877 | int err; |
878 | enum snd_bt87x_boardid boardid; | ||
851 | 879 | ||
852 | rate = pci_id->driver_data; | 880 | if (!pci_id->driver_data) { |
853 | if (! rate) | 881 | err = snd_bt87x_detect_card(pci); |
854 | if ((rate = snd_bt87x_detect_card(pci)) <= 0) | 882 | if (err < 0) |
855 | return -ENODEV; | 883 | return -ENODEV; |
884 | boardid = err; | ||
885 | } else | ||
886 | boardid = pci_id->driver_data; | ||
856 | 887 | ||
857 | if (dev >= SNDRV_CARDS) | 888 | if (dev >= SNDRV_CARDS) |
858 | return -ENODEV; | 889 | return -ENODEV; |
@@ -869,27 +900,39 @@ static int __devinit snd_bt87x_probe(struct pci_dev *pci, | |||
869 | if (err < 0) | 900 | if (err < 0) |
870 | goto _error; | 901 | goto _error; |
871 | 902 | ||
872 | if (digital_rate[dev] > 0) | 903 | memcpy(&chip->board, &snd_bt87x_boards[boardid], sizeof(chip->board)); |
873 | chip->dig_rate = digital_rate[dev]; | ||
874 | else | ||
875 | chip->dig_rate = rate; | ||
876 | 904 | ||
877 | err = snd_bt87x_pcm(chip, DEVICE_DIGITAL, "Bt87x Digital"); | 905 | if (!chip->board.no_digital) { |
878 | if (err < 0) | 906 | if (digital_rate[dev] > 0) |
879 | goto _error; | 907 | chip->board.dig_rate = digital_rate[dev]; |
880 | err = snd_bt87x_pcm(chip, DEVICE_ANALOG, "Bt87x Analog"); | ||
881 | if (err < 0) | ||
882 | goto _error; | ||
883 | 908 | ||
884 | err = snd_ctl_add(card, snd_ctl_new1(&snd_bt87x_capture_volume, chip)); | 909 | chip->reg_control |= chip->board.digital_fmt; |
885 | if (err < 0) | 910 | |
886 | goto _error; | 911 | err = snd_bt87x_pcm(chip, DEVICE_DIGITAL, "Bt87x Digital"); |
887 | err = snd_ctl_add(card, snd_ctl_new1(&snd_bt87x_capture_boost, chip)); | 912 | if (err < 0) |
888 | if (err < 0) | 913 | goto _error; |
889 | goto _error; | 914 | } |
890 | err = snd_ctl_add(card, snd_ctl_new1(&snd_bt87x_capture_source, chip)); | 915 | if (!chip->board.no_analog) { |
891 | if (err < 0) | 916 | err = snd_bt87x_pcm(chip, DEVICE_ANALOG, "Bt87x Analog"); |
892 | goto _error; | 917 | if (err < 0) |
918 | goto _error; | ||
919 | err = snd_ctl_add(card, snd_ctl_new1( | ||
920 | &snd_bt87x_capture_volume, chip)); | ||
921 | if (err < 0) | ||
922 | goto _error; | ||
923 | err = snd_ctl_add(card, snd_ctl_new1( | ||
924 | &snd_bt87x_capture_boost, chip)); | ||
925 | if (err < 0) | ||
926 | goto _error; | ||
927 | err = snd_ctl_add(card, snd_ctl_new1( | ||
928 | &snd_bt87x_capture_source, chip)); | ||
929 | if (err < 0) | ||
930 | goto _error; | ||
931 | } | ||
932 | snd_printk(KERN_INFO "bt87x%d: Using board %d, %sanalog, %sdigital " | ||
933 | "(rate %d Hz)\n", dev, boardid, | ||
934 | chip->board.no_analog ? "no " : "", | ||
935 | chip->board.no_digital ? "no " : "", chip->board.dig_rate); | ||
893 | 936 | ||
894 | strcpy(card->driver, "Bt87x"); | 937 | strcpy(card->driver, "Bt87x"); |
895 | sprintf(card->shortname, "Brooktree Bt%x", pci->device); | 938 | sprintf(card->shortname, "Brooktree Bt%x", pci->device); |
@@ -920,8 +963,8 @@ static void __devexit snd_bt87x_remove(struct pci_dev *pci) | |||
920 | /* default entries for all Bt87x cards - it's not exported */ | 963 | /* default entries for all Bt87x cards - it's not exported */ |
921 | /* driver_data is set to 0 to call detection */ | 964 | /* driver_data is set to 0 to call detection */ |
922 | static struct pci_device_id snd_bt87x_default_ids[] __devinitdata = { | 965 | static struct pci_device_id snd_bt87x_default_ids[] __devinitdata = { |
923 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, PCI_ANY_ID, PCI_ANY_ID, 0), | 966 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, PCI_ANY_ID, PCI_ANY_ID, UNKNOWN), |
924 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, PCI_ANY_ID, PCI_ANY_ID, 0), | 967 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, PCI_ANY_ID, PCI_ANY_ID, UNKNOWN), |
925 | { } | 968 | { } |
926 | }; | 969 | }; |
927 | 970 | ||
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h index a0420bc63f0b..75da1746e758 100644 --- a/sound/pci/ca0106/ca0106.h +++ b/sound/pci/ca0106/ca0106.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> | 2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> |
3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit | 3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit |
4 | * Version: 0.0.21 | 4 | * Version: 0.0.22 |
5 | * | 5 | * |
6 | * FEATURES currently supported: | 6 | * FEATURES currently supported: |
7 | * See ca0106_main.c for features. | 7 | * See ca0106_main.c for features. |
@@ -47,6 +47,8 @@ | |||
47 | * Added GPIO info for SB Live 24bit. | 47 | * Added GPIO info for SB Live 24bit. |
48 | * 0.0.21 | 48 | * 0.0.21 |
49 | * Implement support for Line-in capture on SB Live 24bit. | 49 | * Implement support for Line-in capture on SB Live 24bit. |
50 | * 0.0.22 | ||
51 | * Add support for mute control on SB Live 24bit (cards w/ SPI DAC) | ||
50 | * | 52 | * |
51 | * | 53 | * |
52 | * This code was initally based on code from ALSA's emu10k1x.c which is: | 54 | * This code was initally based on code from ALSA's emu10k1x.c which is: |
@@ -552,6 +554,95 @@ | |||
552 | #define CONTROL_CENTER_LFE_CHANNEL 1 | 554 | #define CONTROL_CENTER_LFE_CHANNEL 1 |
553 | #define CONTROL_UNKNOWN_CHANNEL 2 | 555 | #define CONTROL_UNKNOWN_CHANNEL 2 |
554 | 556 | ||
557 | |||
558 | /* Based on WM8768 Datasheet Rev 4.2 page 32 */ | ||
559 | #define SPI_REG_MASK 0x1ff /* 16-bit SPI writes have a 7-bit address */ | ||
560 | #define SPI_REG_SHIFT 9 /* followed by 9 bits of data */ | ||
561 | |||
562 | #define SPI_LDA1_REG 0 /* digital attenuation */ | ||
563 | #define SPI_RDA1_REG 1 | ||
564 | #define SPI_LDA2_REG 4 | ||
565 | #define SPI_RDA2_REG 5 | ||
566 | #define SPI_LDA3_REG 6 | ||
567 | #define SPI_RDA3_REG 7 | ||
568 | #define SPI_LDA4_REG 13 | ||
569 | #define SPI_RDA4_REG 14 | ||
570 | #define SPI_MASTDA_REG 8 | ||
571 | |||
572 | #define SPI_DA_BIT_UPDATE (1<<8) /* update attenuation values */ | ||
573 | #define SPI_DA_BIT_0dB 0xff /* 0 dB */ | ||
574 | #define SPI_DA_BIT_infdB 0x00 /* inf dB attenuation (mute) */ | ||
575 | |||
576 | #define SPI_PL_REG 2 | ||
577 | #define SPI_PL_BIT_L_M (0<<5) /* left channel = mute */ | ||
578 | #define SPI_PL_BIT_L_L (1<<5) /* left channel = left */ | ||
579 | #define SPI_PL_BIT_L_R (2<<5) /* left channel = right */ | ||
580 | #define SPI_PL_BIT_L_C (3<<5) /* left channel = (L+R)/2 */ | ||
581 | #define SPI_PL_BIT_R_M (0<<7) /* right channel = mute */ | ||
582 | #define SPI_PL_BIT_R_L (1<<7) /* right channel = left */ | ||
583 | #define SPI_PL_BIT_R_R (2<<7) /* right channel = right */ | ||
584 | #define SPI_PL_BIT_R_C (3<<7) /* right channel = (L+R)/2 */ | ||
585 | #define SPI_IZD_REG 2 | ||
586 | #define SPI_IZD_BIT (1<<4) /* infinite zero detect */ | ||
587 | |||
588 | #define SPI_FMT_REG 3 | ||
589 | #define SPI_FMT_BIT_RJ (0<<0) /* right justified mode */ | ||
590 | #define SPI_FMT_BIT_LJ (1<<0) /* left justified mode */ | ||
591 | #define SPI_FMT_BIT_I2S (2<<0) /* I2S mode */ | ||
592 | #define SPI_FMT_BIT_DSP (3<<0) /* DSP Modes A or B */ | ||
593 | #define SPI_LRP_REG 3 | ||
594 | #define SPI_LRP_BIT (1<<2) /* invert LRCLK polarity */ | ||
595 | #define SPI_BCP_REG 3 | ||
596 | #define SPI_BCP_BIT (1<<3) /* invert BCLK polarity */ | ||
597 | #define SPI_IWL_REG 3 | ||
598 | #define SPI_IWL_BIT_16 (0<<4) /* 16-bit world length */ | ||
599 | #define SPI_IWL_BIT_20 (1<<4) /* 20-bit world length */ | ||
600 | #define SPI_IWL_BIT_24 (2<<4) /* 24-bit world length */ | ||
601 | #define SPI_IWL_BIT_32 (3<<4) /* 32-bit world length */ | ||
602 | |||
603 | #define SPI_MS_REG 10 | ||
604 | #define SPI_MS_BIT (1<<5) /* master mode */ | ||
605 | #define SPI_RATE_REG 10 /* only applies in master mode */ | ||
606 | #define SPI_RATE_BIT_128 (0<<6) /* MCLK = LRCLK * 128 */ | ||
607 | #define SPI_RATE_BIT_192 (1<<6) | ||
608 | #define SPI_RATE_BIT_256 (2<<6) | ||
609 | #define SPI_RATE_BIT_384 (3<<6) | ||
610 | #define SPI_RATE_BIT_512 (4<<6) | ||
611 | #define SPI_RATE_BIT_768 (5<<6) | ||
612 | |||
613 | /* They really do label the bit for the 4th channel "4" and not "3" */ | ||
614 | #define SPI_DMUTE0_REG 9 | ||
615 | #define SPI_DMUTE1_REG 9 | ||
616 | #define SPI_DMUTE2_REG 9 | ||
617 | #define SPI_DMUTE4_REG 15 | ||
618 | #define SPI_DMUTE0_BIT (1<<3) | ||
619 | #define SPI_DMUTE1_BIT (1<<4) | ||
620 | #define SPI_DMUTE2_BIT (1<<5) | ||
621 | #define SPI_DMUTE4_BIT (1<<2) | ||
622 | |||
623 | #define SPI_PHASE0_REG 3 | ||
624 | #define SPI_PHASE1_REG 3 | ||
625 | #define SPI_PHASE2_REG 3 | ||
626 | #define SPI_PHASE4_REG 15 | ||
627 | #define SPI_PHASE0_BIT (1<<6) | ||
628 | #define SPI_PHASE1_BIT (1<<7) | ||
629 | #define SPI_PHASE2_BIT (1<<8) | ||
630 | #define SPI_PHASE4_BIT (1<<3) | ||
631 | |||
632 | #define SPI_PDWN_REG 2 /* power down all DACs */ | ||
633 | #define SPI_PDWN_BIT (1<<2) | ||
634 | #define SPI_DACD0_REG 10 /* power down individual DACs */ | ||
635 | #define SPI_DACD1_REG 10 | ||
636 | #define SPI_DACD2_REG 10 | ||
637 | #define SPI_DACD4_REG 15 | ||
638 | #define SPI_DACD0_BIT (1<<1) | ||
639 | #define SPI_DACD1_BIT (1<<2) | ||
640 | #define SPI_DACD2_BIT (1<<3) | ||
641 | #define SPI_DACD4_BIT (1<<0) /* datasheet error says it's 1 */ | ||
642 | |||
643 | #define SPI_PWRDNALL_REG 10 /* power down everything */ | ||
644 | #define SPI_PWRDNALL_BIT (1<<4) | ||
645 | |||
555 | #include "ca_midi.h" | 646 | #include "ca_midi.h" |
556 | 647 | ||
557 | struct snd_ca0106; | 648 | struct snd_ca0106; |
@@ -611,6 +702,8 @@ struct snd_ca0106 { | |||
611 | 702 | ||
612 | struct snd_ca_midi midi; | 703 | struct snd_ca_midi midi; |
613 | struct snd_ca_midi midi2; | 704 | struct snd_ca_midi midi2; |
705 | |||
706 | u16 spi_dac_reg[16]; | ||
614 | }; | 707 | }; |
615 | 708 | ||
616 | int snd_ca0106_mixer(struct snd_ca0106 *emu); | 709 | int snd_ca0106_mixer(struct snd_ca0106 *emu); |
@@ -627,4 +720,5 @@ void snd_ca0106_ptr_write(struct snd_ca0106 *emu, | |||
627 | 720 | ||
628 | int snd_ca0106_i2c_write(struct snd_ca0106 *emu, u32 reg, u32 value); | 721 | int snd_ca0106_i2c_write(struct snd_ca0106 *emu, u32 reg, u32 value); |
629 | 722 | ||
630 | 723 | int snd_ca0106_spi_write(struct snd_ca0106 * emu, | |
724 | unsigned int data); | ||
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index fcab8fb97e38..31d8db9f7a4c 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> | 2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> |
3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit | 3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit |
4 | * Version: 0.0.23 | 4 | * Version: 0.0.25 |
5 | * | 5 | * |
6 | * FEATURES currently supported: | 6 | * FEATURES currently supported: |
7 | * Front, Rear and Center/LFE. | 7 | * Front, Rear and Center/LFE. |
@@ -79,6 +79,10 @@ | |||
79 | * Add support for MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97. From kiksen, bug #901 | 79 | * Add support for MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97. From kiksen, bug #901 |
80 | * 0.0.23 | 80 | * 0.0.23 |
81 | * Implement support for Line-in capture on SB Live 24bit. | 81 | * Implement support for Line-in capture on SB Live 24bit. |
82 | * 0.0.24 | ||
83 | * Add support for mute control on SB Live 24bit (cards w/ SPI DAC) | ||
84 | * 0.0.25 | ||
85 | * Powerdown SPI DAC channels when not in use | ||
82 | * | 86 | * |
83 | * BUGS: | 87 | * BUGS: |
84 | * Some stability problems when unloading the snd-ca0106 kernel module. | 88 | * Some stability problems when unloading the snd-ca0106 kernel module. |
@@ -170,6 +174,15 @@ MODULE_PARM_DESC(subsystem, "Force card subsystem model."); | |||
170 | static struct snd_ca0106_details ca0106_chip_details[] = { | 174 | static struct snd_ca0106_details ca0106_chip_details[] = { |
171 | /* Sound Blaster X-Fi Extreme Audio. This does not have an AC97. 53SB079000000 */ | 175 | /* Sound Blaster X-Fi Extreme Audio. This does not have an AC97. 53SB079000000 */ |
172 | /* It is really just a normal SB Live 24bit. */ | 176 | /* It is really just a normal SB Live 24bit. */ |
177 | /* Tested: | ||
178 | * See ALSA bug#3251 | ||
179 | */ | ||
180 | { .serial = 0x10131102, | ||
181 | .name = "X-Fi Extreme Audio [SBxxxx]", | ||
182 | .gpio_type = 1, | ||
183 | .i2c_adc = 1 } , | ||
184 | /* Sound Blaster X-Fi Extreme Audio. This does not have an AC97. 53SB079000000 */ | ||
185 | /* It is really just a normal SB Live 24bit. */ | ||
173 | /* | 186 | /* |
174 | * CTRL:CA0111-WTLF | 187 | * CTRL:CA0111-WTLF |
175 | * ADC: WM8775SEDS | 188 | * ADC: WM8775SEDS |
@@ -261,10 +274,11 @@ static struct snd_ca0106_details ca0106_chip_details[] = { | |||
261 | 274 | ||
262 | /* hardware definition */ | 275 | /* hardware definition */ |
263 | static struct snd_pcm_hardware snd_ca0106_playback_hw = { | 276 | static struct snd_pcm_hardware snd_ca0106_playback_hw = { |
264 | .info = (SNDRV_PCM_INFO_MMAP | | 277 | .info = SNDRV_PCM_INFO_MMAP | |
265 | SNDRV_PCM_INFO_INTERLEAVED | | 278 | SNDRV_PCM_INFO_INTERLEAVED | |
266 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 279 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
267 | SNDRV_PCM_INFO_MMAP_VALID), | 280 | SNDRV_PCM_INFO_MMAP_VALID | |
281 | SNDRV_PCM_INFO_SYNC_START, | ||
268 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, | 282 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, |
269 | .rates = (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | | 283 | .rates = (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | |
270 | SNDRV_PCM_RATE_192000), | 284 | SNDRV_PCM_RATE_192000), |
@@ -447,6 +461,19 @@ static void snd_ca0106_pcm_free_substream(struct snd_pcm_runtime *runtime) | |||
447 | kfree(runtime->private_data); | 461 | kfree(runtime->private_data); |
448 | } | 462 | } |
449 | 463 | ||
464 | static const int spi_dacd_reg[] = { | ||
465 | [PCM_FRONT_CHANNEL] = SPI_DACD4_REG, | ||
466 | [PCM_REAR_CHANNEL] = SPI_DACD0_REG, | ||
467 | [PCM_CENTER_LFE_CHANNEL]= SPI_DACD2_REG, | ||
468 | [PCM_UNKNOWN_CHANNEL] = SPI_DACD1_REG, | ||
469 | }; | ||
470 | static const int spi_dacd_bit[] = { | ||
471 | [PCM_FRONT_CHANNEL] = SPI_DACD4_BIT, | ||
472 | [PCM_REAR_CHANNEL] = SPI_DACD0_BIT, | ||
473 | [PCM_CENTER_LFE_CHANNEL]= SPI_DACD2_BIT, | ||
474 | [PCM_UNKNOWN_CHANNEL] = SPI_DACD1_BIT, | ||
475 | }; | ||
476 | |||
450 | /* open_playback callback */ | 477 | /* open_playback callback */ |
451 | static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream, | 478 | static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream, |
452 | int channel_id) | 479 | int channel_id) |
@@ -481,6 +508,17 @@ static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substr | |||
481 | return err; | 508 | return err; |
482 | if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0) | 509 | if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0) |
483 | return err; | 510 | return err; |
511 | snd_pcm_set_sync(substream); | ||
512 | |||
513 | if (chip->details->spi_dac && channel_id != PCM_FRONT_CHANNEL) { | ||
514 | const int reg = spi_dacd_reg[channel_id]; | ||
515 | |||
516 | /* Power up dac */ | ||
517 | chip->spi_dac_reg[reg] &= ~spi_dacd_bit[channel_id]; | ||
518 | err = snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]); | ||
519 | if (err < 0) | ||
520 | return err; | ||
521 | } | ||
484 | return 0; | 522 | return 0; |
485 | } | 523 | } |
486 | 524 | ||
@@ -491,6 +529,14 @@ static int snd_ca0106_pcm_close_playback(struct snd_pcm_substream *substream) | |||
491 | struct snd_pcm_runtime *runtime = substream->runtime; | 529 | struct snd_pcm_runtime *runtime = substream->runtime; |
492 | struct snd_ca0106_pcm *epcm = runtime->private_data; | 530 | struct snd_ca0106_pcm *epcm = runtime->private_data; |
493 | chip->playback_channels[epcm->channel_id].use = 0; | 531 | chip->playback_channels[epcm->channel_id].use = 0; |
532 | |||
533 | if (chip->details->spi_dac && epcm->channel_id != PCM_FRONT_CHANNEL) { | ||
534 | const int reg = spi_dacd_reg[epcm->channel_id]; | ||
535 | |||
536 | /* Power down DAC */ | ||
537 | chip->spi_dac_reg[reg] |= spi_dacd_bit[epcm->channel_id]; | ||
538 | snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]); | ||
539 | } | ||
494 | /* FIXME: maybe zero others */ | 540 | /* FIXME: maybe zero others */ |
495 | return 0; | 541 | return 0; |
496 | } | 542 | } |
@@ -809,6 +855,9 @@ static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream, | |||
809 | break; | 855 | break; |
810 | } | 856 | } |
811 | snd_pcm_group_for_each_entry(s, substream) { | 857 | snd_pcm_group_for_each_entry(s, substream) { |
858 | if (snd_pcm_substream_chip(s) != emu || | ||
859 | s->stream != SNDRV_PCM_STREAM_PLAYBACK) | ||
860 | continue; | ||
812 | runtime = s->runtime; | 861 | runtime = s->runtime; |
813 | epcm = runtime->private_data; | 862 | epcm = runtime->private_data; |
814 | channel = epcm->channel_id; | 863 | channel = epcm->channel_id; |
@@ -1214,28 +1263,23 @@ static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device, struct s | |||
1214 | return 0; | 1263 | return 0; |
1215 | } | 1264 | } |
1216 | 1265 | ||
1266 | #define SPI_REG(reg, value) (((reg) << SPI_REG_SHIFT) | (value)) | ||
1217 | static unsigned int spi_dac_init[] = { | 1267 | static unsigned int spi_dac_init[] = { |
1218 | 0x00ff, | 1268 | SPI_REG(SPI_LDA1_REG, SPI_DA_BIT_0dB), /* 0dB dig. attenuation */ |
1219 | 0x02ff, | 1269 | SPI_REG(SPI_RDA1_REG, SPI_DA_BIT_0dB), |
1220 | 0x0400, | 1270 | SPI_REG(SPI_PL_REG, SPI_PL_BIT_L_L | SPI_PL_BIT_R_R | SPI_IZD_BIT), |
1221 | 0x0520, | 1271 | SPI_REG(SPI_FMT_REG, SPI_FMT_BIT_I2S | SPI_IWL_BIT_24), |
1222 | 0x0620, /* Set 24 bit. Was 0x0600 */ | 1272 | SPI_REG(SPI_LDA2_REG, SPI_DA_BIT_0dB), |
1223 | 0x08ff, | 1273 | SPI_REG(SPI_RDA2_REG, SPI_DA_BIT_0dB), |
1224 | 0x0aff, | 1274 | SPI_REG(SPI_LDA3_REG, SPI_DA_BIT_0dB), |
1225 | 0x0cff, | 1275 | SPI_REG(SPI_RDA3_REG, SPI_DA_BIT_0dB), |
1226 | 0x0eff, | 1276 | SPI_REG(SPI_MASTDA_REG, SPI_DA_BIT_0dB), |
1227 | 0x10ff, | 1277 | SPI_REG(9, 0x00), |
1228 | 0x1200, | 1278 | SPI_REG(SPI_MS_REG, SPI_DACD0_BIT | SPI_DACD1_BIT | SPI_DACD2_BIT), |
1229 | 0x1400, | 1279 | SPI_REG(12, 0x00), |
1230 | 0x1480, | 1280 | SPI_REG(SPI_LDA4_REG, SPI_DA_BIT_0dB), |
1231 | 0x1800, | 1281 | SPI_REG(SPI_RDA4_REG, SPI_DA_BIT_0dB | SPI_DA_BIT_UPDATE), |
1232 | 0x1aff, | 1282 | SPI_REG(SPI_DACD4_REG, 0x00), |
1233 | 0x1cff, | ||
1234 | 0x1e00, | ||
1235 | 0x0530, | ||
1236 | 0x0602, | ||
1237 | 0x0622, | ||
1238 | 0x1400, | ||
1239 | }; | 1283 | }; |
1240 | 1284 | ||
1241 | static unsigned int i2c_adc_init[][2] = { | 1285 | static unsigned int i2c_adc_init[][2] = { |
@@ -1475,8 +1519,13 @@ static int __devinit snd_ca0106_create(int dev, struct snd_card *card, | |||
1475 | int size, n; | 1519 | int size, n; |
1476 | 1520 | ||
1477 | size = ARRAY_SIZE(spi_dac_init); | 1521 | size = ARRAY_SIZE(spi_dac_init); |
1478 | for (n=0; n < size; n++) | 1522 | for (n = 0; n < size; n++) { |
1523 | int reg = spi_dac_init[n] >> SPI_REG_SHIFT; | ||
1524 | |||
1479 | snd_ca0106_spi_write(chip, spi_dac_init[n]); | 1525 | snd_ca0106_spi_write(chip, spi_dac_init[n]); |
1526 | if (reg < ARRAY_SIZE(chip->spi_dac_reg)) | ||
1527 | chip->spi_dac_reg[reg] = spi_dac_init[n]; | ||
1528 | } | ||
1480 | } | 1529 | } |
1481 | 1530 | ||
1482 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, | 1531 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, |
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index 9c3a9c8d1dc2..be519a17dfa5 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> | 2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> |
3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit | 3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit |
4 | * Version: 0.0.17 | 4 | * Version: 0.0.18 |
5 | * | 5 | * |
6 | * FEATURES currently supported: | 6 | * FEATURES currently supported: |
7 | * See ca0106_main.c for features. | 7 | * See ca0106_main.c for features. |
@@ -39,6 +39,8 @@ | |||
39 | * Modified Copyright message. | 39 | * Modified Copyright message. |
40 | * 0.0.17 | 40 | * 0.0.17 |
41 | * Implement Mic and Line in Capture. | 41 | * Implement Mic and Line in Capture. |
42 | * 0.0.18 | ||
43 | * Add support for mute control on SB Live 24bit (cards w/ SPI DAC) | ||
42 | * | 44 | * |
43 | * This code was initally based on code from ALSA's emu10k1x.c which is: | 45 | * This code was initally based on code from ALSA's emu10k1x.c which is: |
44 | * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com> | 46 | * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com> |
@@ -77,15 +79,7 @@ | |||
77 | static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1); | 79 | static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1); |
78 | static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1); | 80 | static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1); |
79 | 81 | ||
80 | static int snd_ca0106_shared_spdif_info(struct snd_kcontrol *kcontrol, | 82 | #define snd_ca0106_shared_spdif_info snd_ctl_boolean_mono_info |
81 | struct snd_ctl_elem_info *uinfo) | ||
82 | { | ||
83 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
84 | uinfo->count = 1; | ||
85 | uinfo->value.integer.min = 0; | ||
86 | uinfo->value.integer.max = 1; | ||
87 | return 0; | ||
88 | } | ||
89 | 83 | ||
90 | static int snd_ca0106_shared_spdif_get(struct snd_kcontrol *kcontrol, | 84 | static int snd_ca0106_shared_spdif_get(struct snd_kcontrol *kcontrol, |
91 | struct snd_ctl_elem_value *ucontrol) | 85 | struct snd_ctl_elem_value *ucontrol) |
@@ -470,6 +464,42 @@ static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol, | |||
470 | return change; | 464 | return change; |
471 | } | 465 | } |
472 | 466 | ||
467 | #define spi_mute_info snd_ctl_boolean_mono_info | ||
468 | |||
469 | static int spi_mute_get(struct snd_kcontrol *kcontrol, | ||
470 | struct snd_ctl_elem_value *ucontrol) | ||
471 | { | ||
472 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); | ||
473 | unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT; | ||
474 | unsigned int bit = kcontrol->private_value & SPI_REG_MASK; | ||
475 | |||
476 | ucontrol->value.integer.value[0] = !(emu->spi_dac_reg[reg] & bit); | ||
477 | return 0; | ||
478 | } | ||
479 | |||
480 | static int spi_mute_put(struct snd_kcontrol *kcontrol, | ||
481 | struct snd_ctl_elem_value *ucontrol) | ||
482 | { | ||
483 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); | ||
484 | unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT; | ||
485 | unsigned int bit = kcontrol->private_value & SPI_REG_MASK; | ||
486 | int ret; | ||
487 | |||
488 | ret = emu->spi_dac_reg[reg] & bit; | ||
489 | if (ucontrol->value.integer.value[0]) { | ||
490 | if (!ret) /* bit already cleared, do nothing */ | ||
491 | return 0; | ||
492 | emu->spi_dac_reg[reg] &= ~bit; | ||
493 | } else { | ||
494 | if (ret) /* bit already set, do nothing */ | ||
495 | return 0; | ||
496 | emu->spi_dac_reg[reg] |= bit; | ||
497 | } | ||
498 | |||
499 | ret = snd_ca0106_spi_write(emu, emu->spi_dac_reg[reg]); | ||
500 | return ret ? -1 : 1; | ||
501 | } | ||
502 | |||
473 | #define CA_VOLUME(xname,chid,reg) \ | 503 | #define CA_VOLUME(xname,chid,reg) \ |
474 | { \ | 504 | { \ |
475 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 505 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
@@ -562,6 +592,28 @@ static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] __devinitdata = | |||
562 | I2C_VOLUME("Aux Capture Volume", 3), | 592 | I2C_VOLUME("Aux Capture Volume", 3), |
563 | }; | 593 | }; |
564 | 594 | ||
595 | #define SPI_SWITCH(xname,reg,bit) \ | ||
596 | { \ | ||
597 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
598 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ | ||
599 | .info = spi_mute_info, \ | ||
600 | .get = spi_mute_get, \ | ||
601 | .put = spi_mute_put, \ | ||
602 | .private_value = (reg<<SPI_REG_SHIFT) | (bit) \ | ||
603 | } | ||
604 | |||
605 | static struct snd_kcontrol_new snd_ca0106_volume_spi_dac_ctls[] | ||
606 | __devinitdata = { | ||
607 | SPI_SWITCH("Analog Front Playback Switch", | ||
608 | SPI_DMUTE4_REG, SPI_DMUTE4_BIT), | ||
609 | SPI_SWITCH("Analog Rear Playback Switch", | ||
610 | SPI_DMUTE0_REG, SPI_DMUTE0_BIT), | ||
611 | SPI_SWITCH("Analog Center/LFE Playback Switch", | ||
612 | SPI_DMUTE2_REG, SPI_DMUTE2_BIT), | ||
613 | SPI_SWITCH("Analog Side Playback Switch", | ||
614 | SPI_DMUTE1_REG, SPI_DMUTE1_BIT), | ||
615 | }; | ||
616 | |||
565 | static int __devinit remove_ctl(struct snd_card *card, const char *name) | 617 | static int __devinit remove_ctl(struct snd_card *card, const char *name) |
566 | { | 618 | { |
567 | struct snd_ctl_elem_id id; | 619 | struct snd_ctl_elem_id id; |
@@ -591,9 +643,19 @@ static int __devinit rename_ctl(struct snd_card *card, const char *src, const ch | |||
591 | return -ENOENT; | 643 | return -ENOENT; |
592 | } | 644 | } |
593 | 645 | ||
646 | #define ADD_CTLS(emu, ctls) \ | ||
647 | do { \ | ||
648 | int i, err; \ | ||
649 | for (i = 0; i < ARRAY_SIZE(ctls); i++) { \ | ||
650 | err = snd_ctl_add(card, snd_ctl_new1(&ctls[i], emu)); \ | ||
651 | if (err < 0) \ | ||
652 | return err; \ | ||
653 | } \ | ||
654 | } while (0) | ||
655 | |||
594 | int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu) | 656 | int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu) |
595 | { | 657 | { |
596 | int i, err; | 658 | int err; |
597 | struct snd_card *card = emu->card; | 659 | struct snd_card *card = emu->card; |
598 | char **c; | 660 | char **c; |
599 | static char *ca0106_remove_ctls[] = { | 661 | static char *ca0106_remove_ctls[] = { |
@@ -640,17 +702,9 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu) | |||
640 | rename_ctl(card, c[0], c[1]); | 702 | rename_ctl(card, c[0], c[1]); |
641 | #endif | 703 | #endif |
642 | 704 | ||
643 | for (i = 0; i < ARRAY_SIZE(snd_ca0106_volume_ctls); i++) { | 705 | ADD_CTLS(emu, snd_ca0106_volume_ctls); |
644 | err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_volume_ctls[i], emu)); | ||
645 | if (err < 0) | ||
646 | return err; | ||
647 | } | ||
648 | if (emu->details->i2c_adc == 1) { | 706 | if (emu->details->i2c_adc == 1) { |
649 | for (i = 0; i < ARRAY_SIZE(snd_ca0106_volume_i2c_adc_ctls); i++) { | 707 | ADD_CTLS(emu, snd_ca0106_volume_i2c_adc_ctls); |
650 | err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_volume_i2c_adc_ctls[i], emu)); | ||
651 | if (err < 0) | ||
652 | return err; | ||
653 | } | ||
654 | if (emu->details->gpio_type == 1) | 708 | if (emu->details->gpio_type == 1) |
655 | err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu)); | 709 | err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu)); |
656 | else /* gpio_type == 2 */ | 710 | else /* gpio_type == 2 */ |
@@ -658,6 +712,8 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu) | |||
658 | if (err < 0) | 712 | if (err < 0) |
659 | return err; | 713 | return err; |
660 | } | 714 | } |
715 | if (emu->details->spi_dac == 1) | ||
716 | ADD_CTLS(emu, snd_ca0106_volume_spi_dac_ctls); | ||
661 | return 0; | 717 | return 0; |
662 | } | 718 | } |
663 | 719 | ||
diff --git a/sound/pci/ca0106/ca_midi.c b/sound/pci/ca0106/ca_midi.c index 2e6eab1f1189..ad32eff2713f 100644 --- a/sound/pci/ca0106/ca_midi.c +++ b/sound/pci/ca0106/ca_midi.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * Changelog: | 6 | * Changelog: |
7 | * Implementation is based on mpu401 and emu10k1x and | 7 | * Implementation is based on mpu401 and emu10k1x and |
8 | * tested with ca0106. | 8 | * tested with ca0106. |
9 | * mpu401: Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 9 | * mpu401: Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
10 | * emu10k1x: Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com> | 10 | * emu10k1x: Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com> |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/pci/ca0106/ca_midi.h b/sound/pci/ca0106/ca_midi.h index b72c0933bd22..922ed3e3731e 100644 --- a/sound/pci/ca0106/ca_midi.h +++ b/sound/pci/ca0106/ca_midi.h | |||
@@ -22,9 +22,9 @@ | |||
22 | * | 22 | * |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include<linux/spinlock.h> | 25 | #include <linux/spinlock.h> |
26 | #include<sound/rawmidi.h> | 26 | #include <sound/rawmidi.h> |
27 | #include<sound/mpu401.h> | 27 | #include <sound/mpu401.h> |
28 | 28 | ||
29 | #define CA_MIDI_MODE_INPUT MPU401_MODE_INPUT | 29 | #define CA_MIDI_MODE_INPUT MPU401_MODE_INPUT |
30 | #define CA_MIDI_MODE_OUTPUT MPU401_MODE_OUTPUT | 30 | #define CA_MIDI_MODE_OUTPUT MPU401_MODE_OUTPUT |
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 7d3c5ee0005c..6832649879ce 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c | |||
@@ -95,30 +95,34 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); | |||
95 | #define CM_CHADC0 0x00000001 /* ch0, 0:playback, 1:record */ | 95 | #define CM_CHADC0 0x00000001 /* ch0, 0:playback, 1:record */ |
96 | 96 | ||
97 | #define CM_REG_FUNCTRL1 0x04 | 97 | #define CM_REG_FUNCTRL1 0x04 |
98 | #define CM_ASFC_MASK 0x0000E000 /* ADC sampling frequency */ | 98 | #define CM_DSFC_MASK 0x0000E000 /* channel 1 (DAC?) sampling frequency */ |
99 | #define CM_ASFC_SHIFT 13 | 99 | #define CM_DSFC_SHIFT 13 |
100 | #define CM_DSFC_MASK 0x00001C00 /* DAC sampling frequency */ | 100 | #define CM_ASFC_MASK 0x00001C00 /* channel 0 (ADC?) sampling frequency */ |
101 | #define CM_DSFC_SHIFT 10 | 101 | #define CM_ASFC_SHIFT 10 |
102 | #define CM_SPDF_1 0x00000200 /* SPDIF IN/OUT at channel B */ | 102 | #define CM_SPDF_1 0x00000200 /* SPDIF IN/OUT at channel B */ |
103 | #define CM_SPDF_0 0x00000100 /* SPDIF OUT only channel A */ | 103 | #define CM_SPDF_0 0x00000100 /* SPDIF OUT only channel A */ |
104 | #define CM_SPDFLOOP 0x00000080 /* ext. SPDIIF/OUT -> IN loopback */ | 104 | #define CM_SPDFLOOP 0x00000080 /* ext. SPDIIF/IN -> OUT loopback */ |
105 | #define CM_SPDO2DAC 0x00000040 /* SPDIF/OUT can be heard from internal DAC */ | 105 | #define CM_SPDO2DAC 0x00000040 /* SPDIF/OUT can be heard from internal DAC */ |
106 | #define CM_INTRM 0x00000020 /* master control block (MCB) interrupt enabled */ | 106 | #define CM_INTRM 0x00000020 /* master control block (MCB) interrupt enabled */ |
107 | #define CM_BREQ 0x00000010 /* bus master enabled */ | 107 | #define CM_BREQ 0x00000010 /* bus master enabled */ |
108 | #define CM_VOICE_EN 0x00000008 /* legacy voice (SB16,FM) */ | 108 | #define CM_VOICE_EN 0x00000008 /* legacy voice (SB16,FM) */ |
109 | #define CM_UART_EN 0x00000004 /* UART */ | 109 | #define CM_UART_EN 0x00000004 /* legacy UART */ |
110 | #define CM_JYSTK_EN 0x00000002 /* joy stick */ | 110 | #define CM_JYSTK_EN 0x00000002 /* legacy joystick */ |
111 | #define CM_ZVPORT 0x00000001 /* ZVPORT */ | ||
111 | 112 | ||
112 | #define CM_REG_CHFORMAT 0x08 | 113 | #define CM_REG_CHFORMAT 0x08 |
113 | 114 | ||
114 | #define CM_CHB3D5C 0x80000000 /* 5,6 channels */ | 115 | #define CM_CHB3D5C 0x80000000 /* 5,6 channels */ |
116 | #define CM_FMOFFSET2 0x40000000 /* initial FM PCM offset 2 when Fmute=1 */ | ||
115 | #define CM_CHB3D 0x20000000 /* 4 channels */ | 117 | #define CM_CHB3D 0x20000000 /* 4 channels */ |
116 | 118 | ||
117 | #define CM_CHIP_MASK1 0x1f000000 | 119 | #define CM_CHIP_MASK1 0x1f000000 |
118 | #define CM_CHIP_037 0x01000000 | 120 | #define CM_CHIP_037 0x01000000 |
119 | 121 | #define CM_SETLAT48 0x00800000 /* set latency timer 48h */ | |
120 | #define CM_SPDIF_SELECT1 0x00080000 /* for model <= 037 ? */ | 122 | #define CM_EDGEIRQ 0x00400000 /* emulated edge trigger legacy IRQ */ |
123 | #define CM_SPD24SEL39 0x00200000 /* 24-bit spdif: model 039 */ | ||
121 | #define CM_AC3EN1 0x00100000 /* enable AC3: model 037 */ | 124 | #define CM_AC3EN1 0x00100000 /* enable AC3: model 037 */ |
125 | #define CM_SPDIF_SELECT1 0x00080000 /* for model <= 037 ? */ | ||
122 | #define CM_SPD24SEL 0x00020000 /* 24bit spdif: model 037 */ | 126 | #define CM_SPD24SEL 0x00020000 /* 24bit spdif: model 037 */ |
123 | /* #define CM_SPDIF_INVERSE 0x00010000 */ /* ??? */ | 127 | /* #define CM_SPDIF_INVERSE 0x00010000 */ /* ??? */ |
124 | 128 | ||
@@ -128,35 +132,45 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); | |||
128 | #define CM_ADCBITLEN_14 0x00008000 | 132 | #define CM_ADCBITLEN_14 0x00008000 |
129 | #define CM_ADCBITLEN_13 0x0000C000 | 133 | #define CM_ADCBITLEN_13 0x0000C000 |
130 | 134 | ||
131 | #define CM_ADCDACLEN_MASK 0x00003000 | 135 | #define CM_ADCDACLEN_MASK 0x00003000 /* model 037 */ |
132 | #define CM_ADCDACLEN_060 0x00000000 | 136 | #define CM_ADCDACLEN_060 0x00000000 |
133 | #define CM_ADCDACLEN_066 0x00001000 | 137 | #define CM_ADCDACLEN_066 0x00001000 |
134 | #define CM_ADCDACLEN_130 0x00002000 | 138 | #define CM_ADCDACLEN_130 0x00002000 |
135 | #define CM_ADCDACLEN_280 0x00003000 | 139 | #define CM_ADCDACLEN_280 0x00003000 |
136 | 140 | ||
141 | #define CM_ADCDLEN_MASK 0x00003000 /* model 039 */ | ||
142 | #define CM_ADCDLEN_ORIGINAL 0x00000000 | ||
143 | #define CM_ADCDLEN_EXTRA 0x00001000 | ||
144 | #define CM_ADCDLEN_24K 0x00002000 | ||
145 | #define CM_ADCDLEN_WEIGHT 0x00003000 | ||
146 | |||
137 | #define CM_CH1_SRATE_176K 0x00000800 | 147 | #define CM_CH1_SRATE_176K 0x00000800 |
148 | #define CM_CH1_SRATE_96K 0x00000800 /* model 055? */ | ||
138 | #define CM_CH1_SRATE_88K 0x00000400 | 149 | #define CM_CH1_SRATE_88K 0x00000400 |
139 | #define CM_CH0_SRATE_176K 0x00000200 | 150 | #define CM_CH0_SRATE_176K 0x00000200 |
151 | #define CM_CH0_SRATE_96K 0x00000200 /* model 055? */ | ||
140 | #define CM_CH0_SRATE_88K 0x00000100 | 152 | #define CM_CH0_SRATE_88K 0x00000100 |
141 | 153 | ||
142 | #define CM_SPDIF_INVERSE2 0x00000080 /* model 055? */ | 154 | #define CM_SPDIF_INVERSE2 0x00000080 /* model 055? */ |
155 | #define CM_DBLSPDS 0x00000040 /* double SPDIF sample rate 88.2/96 */ | ||
156 | #define CM_POLVALID 0x00000020 /* inverse SPDIF/IN valid bit */ | ||
157 | #define CM_SPDLOCKED 0x00000010 | ||
143 | 158 | ||
144 | #define CM_CH1FMT_MASK 0x0000000C | 159 | #define CM_CH1FMT_MASK 0x0000000C /* bit 3: 16 bits, bit 2: stereo */ |
145 | #define CM_CH1FMT_SHIFT 2 | 160 | #define CM_CH1FMT_SHIFT 2 |
146 | #define CM_CH0FMT_MASK 0x00000003 | 161 | #define CM_CH0FMT_MASK 0x00000003 /* bit 1: 16 bits, bit 0: stereo */ |
147 | #define CM_CH0FMT_SHIFT 0 | 162 | #define CM_CH0FMT_SHIFT 0 |
148 | 163 | ||
149 | #define CM_REG_INT_HLDCLR 0x0C | 164 | #define CM_REG_INT_HLDCLR 0x0C |
150 | #define CM_CHIP_MASK2 0xff000000 | 165 | #define CM_CHIP_MASK2 0xff000000 |
166 | #define CM_CHIP_8768 0x20000000 | ||
167 | #define CM_CHIP_055 0x08000000 | ||
151 | #define CM_CHIP_039 0x04000000 | 168 | #define CM_CHIP_039 0x04000000 |
152 | #define CM_CHIP_039_6CH 0x01000000 | 169 | #define CM_CHIP_039_6CH 0x01000000 |
153 | #define CM_CHIP_055 0x08000000 | 170 | #define CM_UNKNOWN_INT_EN 0x00080000 /* ? */ |
154 | #define CM_CHIP_8768 0x20000000 | ||
155 | #define CM_TDMA_INT_EN 0x00040000 | 171 | #define CM_TDMA_INT_EN 0x00040000 |
156 | #define CM_CH1_INT_EN 0x00020000 | 172 | #define CM_CH1_INT_EN 0x00020000 |
157 | #define CM_CH0_INT_EN 0x00010000 | 173 | #define CM_CH0_INT_EN 0x00010000 |
158 | #define CM_INT_HOLD 0x00000002 | ||
159 | #define CM_INT_CLEAR 0x00000001 | ||
160 | 174 | ||
161 | #define CM_REG_INT_STATUS 0x10 | 175 | #define CM_REG_INT_STATUS 0x10 |
162 | #define CM_INTR 0x80000000 | 176 | #define CM_INTR 0x80000000 |
@@ -175,12 +189,13 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); | |||
175 | #define CM_CHINT0 0x00000001 | 189 | #define CM_CHINT0 0x00000001 |
176 | 190 | ||
177 | #define CM_REG_LEGACY_CTRL 0x14 | 191 | #define CM_REG_LEGACY_CTRL 0x14 |
178 | #define CM_NXCHG 0x80000000 /* h/w multi channels? */ | 192 | #define CM_NXCHG 0x80000000 /* don't map base reg dword->sample */ |
179 | #define CM_VMPU_MASK 0x60000000 /* MPU401 i/o port address */ | 193 | #define CM_VMPU_MASK 0x60000000 /* MPU401 i/o port address */ |
180 | #define CM_VMPU_330 0x00000000 | 194 | #define CM_VMPU_330 0x00000000 |
181 | #define CM_VMPU_320 0x20000000 | 195 | #define CM_VMPU_320 0x20000000 |
182 | #define CM_VMPU_310 0x40000000 | 196 | #define CM_VMPU_310 0x40000000 |
183 | #define CM_VMPU_300 0x60000000 | 197 | #define CM_VMPU_300 0x60000000 |
198 | #define CM_ENWR8237 0x10000000 /* enable bus master to write 8237 base reg */ | ||
184 | #define CM_VSBSEL_MASK 0x0C000000 /* SB16 base address */ | 199 | #define CM_VSBSEL_MASK 0x0C000000 /* SB16 base address */ |
185 | #define CM_VSBSEL_220 0x00000000 | 200 | #define CM_VSBSEL_220 0x00000000 |
186 | #define CM_VSBSEL_240 0x04000000 | 201 | #define CM_VSBSEL_240 0x04000000 |
@@ -191,44 +206,74 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); | |||
191 | #define CM_FMSEL_3C8 0x01000000 | 206 | #define CM_FMSEL_3C8 0x01000000 |
192 | #define CM_FMSEL_3E0 0x02000000 | 207 | #define CM_FMSEL_3E0 0x02000000 |
193 | #define CM_FMSEL_3E8 0x03000000 | 208 | #define CM_FMSEL_3E8 0x03000000 |
194 | #define CM_ENSPDOUT 0x00800000 /* enable XPDIF/OUT to I/O interface */ | 209 | #define CM_ENSPDOUT 0x00800000 /* enable XSPDIF/OUT to I/O interface */ |
195 | #define CM_SPDCOPYRHT 0x00400000 /* set copyright spdif in/out */ | 210 | #define CM_SPDCOPYRHT 0x00400000 /* spdif in/out copyright bit */ |
196 | #define CM_DAC2SPDO 0x00200000 /* enable wave+fm_midi -> SPDIF/OUT */ | 211 | #define CM_DAC2SPDO 0x00200000 /* enable wave+fm_midi -> SPDIF/OUT */ |
197 | #define CM_SETRETRY 0x00010000 /* 0: legacy i/o wait (default), 1: legacy i/o bus retry */ | 212 | #define CM_INVIDWEN 0x00100000 /* internal vendor ID write enable, model 039? */ |
213 | #define CM_SETRETRY 0x00100000 /* 0: legacy i/o wait (default), 1: legacy i/o bus retry */ | ||
214 | #define CM_C_EEACCESS 0x00080000 /* direct programming eeprom regs */ | ||
215 | #define CM_C_EECS 0x00040000 | ||
216 | #define CM_C_EEDI46 0x00020000 | ||
217 | #define CM_C_EECK46 0x00010000 | ||
198 | #define CM_CHB3D6C 0x00008000 /* 5.1 channels support */ | 218 | #define CM_CHB3D6C 0x00008000 /* 5.1 channels support */ |
199 | #define CM_LINE_AS_BASS 0x00006000 /* use line-in as bass */ | 219 | #define CM_CENTR2LIN 0x00004000 /* line-in as center out */ |
220 | #define CM_BASE2LIN 0x00002000 /* line-in as bass out */ | ||
221 | #define CM_EXBASEN 0x00001000 /* external bass input enable */ | ||
200 | 222 | ||
201 | #define CM_REG_MISC_CTRL 0x18 | 223 | #define CM_REG_MISC_CTRL 0x18 |
202 | #define CM_PWD 0x80000000 | 224 | #define CM_PWD 0x80000000 /* power down */ |
203 | #define CM_RESET 0x40000000 | 225 | #define CM_RESET 0x40000000 |
204 | #define CM_SFIL_MASK 0x30000000 | 226 | #define CM_SFIL_MASK 0x30000000 /* filter control at front end DAC, model 037? */ |
205 | #define CM_TXVX 0x08000000 | 227 | #define CM_VMGAIN 0x10000000 /* analog master amp +6dB, model 039? */ |
206 | #define CM_N4SPK3D 0x04000000 /* 4ch output */ | 228 | #define CM_TXVX 0x08000000 /* model 037? */ |
229 | #define CM_N4SPK3D 0x04000000 /* copy front to rear */ | ||
207 | #define CM_SPDO5V 0x02000000 /* 5V spdif output (1 = 0.5v (coax)) */ | 230 | #define CM_SPDO5V 0x02000000 /* 5V spdif output (1 = 0.5v (coax)) */ |
208 | #define CM_SPDIF48K 0x01000000 /* write */ | 231 | #define CM_SPDIF48K 0x01000000 /* write */ |
209 | #define CM_SPATUS48K 0x01000000 /* read */ | 232 | #define CM_SPATUS48K 0x01000000 /* read */ |
210 | #define CM_ENDBDAC 0x00800000 /* enable dual dac */ | 233 | #define CM_ENDBDAC 0x00800000 /* enable double dac */ |
211 | #define CM_XCHGDAC 0x00400000 /* 0: front=ch0, 1: front=ch1 */ | 234 | #define CM_XCHGDAC 0x00400000 /* 0: front=ch0, 1: front=ch1 */ |
212 | #define CM_SPD32SEL 0x00200000 /* 0: 16bit SPDIF, 1: 32bit */ | 235 | #define CM_SPD32SEL 0x00200000 /* 0: 16bit SPDIF, 1: 32bit */ |
213 | #define CM_SPDFLOOPI 0x00100000 /* int. SPDIF-IN -> int. OUT */ | 236 | #define CM_SPDFLOOPI 0x00100000 /* int. SPDIF-OUT -> int. IN */ |
214 | #define CM_FM_EN 0x00080000 /* enalbe FM */ | 237 | #define CM_FM_EN 0x00080000 /* enable legacy FM */ |
215 | #define CM_AC3EN2 0x00040000 /* enable AC3: model 039 */ | 238 | #define CM_AC3EN2 0x00040000 /* enable AC3: model 039 */ |
216 | #define CM_VIDWPDSB 0x00010000 | 239 | #define CM_ENWRASID 0x00010000 /* choose writable internal SUBID (audio) */ |
240 | #define CM_VIDWPDSB 0x00010000 /* model 037? */ | ||
217 | #define CM_SPDF_AC97 0x00008000 /* 0: SPDIF/OUT 44.1K, 1: 48K */ | 241 | #define CM_SPDF_AC97 0x00008000 /* 0: SPDIF/OUT 44.1K, 1: 48K */ |
218 | #define CM_MASK_EN 0x00004000 | 242 | #define CM_MASK_EN 0x00004000 /* activate channel mask on legacy DMA */ |
219 | #define CM_VIDWPPRT 0x00002000 | 243 | #define CM_ENWRMSID 0x00002000 /* choose writable internal SUBID (modem) */ |
220 | #define CM_SFILENB 0x00001000 | 244 | #define CM_VIDWPPRT 0x00002000 /* model 037? */ |
221 | #define CM_MMODE_MASK 0x00000E00 | 245 | #define CM_SFILENB 0x00001000 /* filter stepping at front end DAC, model 037? */ |
246 | #define CM_MMODE_MASK 0x00000E00 /* model DAA interface mode */ | ||
222 | #define CM_SPDIF_SELECT2 0x00000100 /* for model > 039 ? */ | 247 | #define CM_SPDIF_SELECT2 0x00000100 /* for model > 039 ? */ |
223 | #define CM_ENCENTER 0x00000080 | 248 | #define CM_ENCENTER 0x00000080 |
224 | #define CM_FLINKON 0x00000040 | 249 | #define CM_FLINKON 0x00000080 /* force modem link detection on, model 037 */ |
225 | #define CM_FLINKOFF 0x00000020 | 250 | #define CM_MUTECH1 0x00000040 /* mute PCI ch1 to DAC */ |
226 | #define CM_MIDSMP 0x00000010 | 251 | #define CM_FLINKOFF 0x00000040 /* force modem link detection off, model 037 */ |
227 | #define CM_UPDDMA_MASK 0x0000000C | 252 | #define CM_UNKNOWN_18_5 0x00000020 /* ? */ |
228 | #define CM_TWAIT_MASK 0x00000003 | 253 | #define CM_MIDSMP 0x00000010 /* 1/2 interpolation at front end DAC */ |
254 | #define CM_UPDDMA_MASK 0x0000000C /* TDMA position update notification */ | ||
255 | #define CM_UPDDMA_2048 0x00000000 | ||
256 | #define CM_UPDDMA_1024 0x00000004 | ||
257 | #define CM_UPDDMA_512 0x00000008 | ||
258 | #define CM_UPDDMA_256 0x0000000C | ||
259 | #define CM_TWAIT_MASK 0x00000003 /* model 037 */ | ||
260 | #define CM_TWAIT1 0x00000002 /* FM i/o cycle, 0: 48, 1: 64 PCICLKs */ | ||
261 | #define CM_TWAIT0 0x00000001 /* i/o cycle, 0: 4, 1: 6 PCICLKs */ | ||
262 | |||
263 | #define CM_REG_TDMA_POSITION 0x1C | ||
264 | #define CM_TDMA_CNT_MASK 0xFFFF0000 /* current byte/word count */ | ||
265 | #define CM_TDMA_ADR_MASK 0x0000FFFF /* current address */ | ||
229 | 266 | ||
230 | /* byte */ | 267 | /* byte */ |
231 | #define CM_REG_MIXER0 0x20 | 268 | #define CM_REG_MIXER0 0x20 |
269 | #define CM_REG_SBVR 0x20 /* write: sb16 version */ | ||
270 | #define CM_REG_DEV 0x20 /* read: hardware device version */ | ||
271 | |||
272 | #define CM_REG_MIXER21 0x21 | ||
273 | #define CM_UNKNOWN_21_MASK 0x78 /* ? */ | ||
274 | #define CM_X_ADPCM 0x04 /* SB16 ADPCM enable */ | ||
275 | #define CM_PROINV 0x02 /* SBPro left/right channel switching */ | ||
276 | #define CM_X_SB16 0x01 /* SB16 compatible */ | ||
232 | 277 | ||
233 | #define CM_REG_SB16_DATA 0x22 | 278 | #define CM_REG_SB16_DATA 0x22 |
234 | #define CM_REG_SB16_ADDR 0x23 | 279 | #define CM_REG_SB16_ADDR 0x23 |
@@ -243,8 +288,8 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); | |||
243 | #define CM_FMMUTE_SHIFT 7 | 288 | #define CM_FMMUTE_SHIFT 7 |
244 | #define CM_WSMUTE 0x40 /* mute PCM */ | 289 | #define CM_WSMUTE 0x40 /* mute PCM */ |
245 | #define CM_WSMUTE_SHIFT 6 | 290 | #define CM_WSMUTE_SHIFT 6 |
246 | #define CM_SPK4 0x20 /* lin-in -> rear line out */ | 291 | #define CM_REAR2LIN 0x20 /* lin-in -> rear line out */ |
247 | #define CM_SPK4_SHIFT 5 | 292 | #define CM_REAR2LIN_SHIFT 5 |
248 | #define CM_REAR2FRONT 0x10 /* exchange rear/front */ | 293 | #define CM_REAR2FRONT 0x10 /* exchange rear/front */ |
249 | #define CM_REAR2FRONT_SHIFT 4 | 294 | #define CM_REAR2FRONT_SHIFT 4 |
250 | #define CM_WAVEINL 0x08 /* digital wave rec. left chan */ | 295 | #define CM_WAVEINL 0x08 /* digital wave rec. left chan */ |
@@ -276,12 +321,13 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); | |||
276 | #define CM_VAUXR_MASK 0x0f | 321 | #define CM_VAUXR_MASK 0x0f |
277 | 322 | ||
278 | #define CM_REG_MISC 0x27 | 323 | #define CM_REG_MISC 0x27 |
324 | #define CM_UNKNOWN_27_MASK 0xd8 /* ? */ | ||
279 | #define CM_XGPO1 0x20 | 325 | #define CM_XGPO1 0x20 |
280 | // #define CM_XGPBIO 0x04 | 326 | // #define CM_XGPBIO 0x04 |
281 | #define CM_MIC_CENTER_LFE 0x04 /* mic as center/lfe out? (model 039 or later?) */ | 327 | #define CM_MIC_CENTER_LFE 0x04 /* mic as center/lfe out? (model 039 or later?) */ |
282 | #define CM_SPDIF_INVERSE 0x04 /* spdif input phase inverse (model 037) */ | 328 | #define CM_SPDIF_INVERSE 0x04 /* spdif input phase inverse (model 037) */ |
283 | #define CM_SPDVALID 0x02 /* spdif input valid check */ | 329 | #define CM_SPDVALID 0x02 /* spdif input valid check */ |
284 | #define CM_DMAUTO 0x01 | 330 | #define CM_DMAUTO 0x01 /* SB16 DMA auto detect */ |
285 | 331 | ||
286 | #define CM_REG_AC97 0x28 /* hmmm.. do we have ac97 link? */ | 332 | #define CM_REG_AC97 0x28 /* hmmm.. do we have ac97 link? */ |
287 | /* | 333 | /* |
@@ -322,18 +368,20 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); | |||
322 | /* | 368 | /* |
323 | * extended registers | 369 | * extended registers |
324 | */ | 370 | */ |
325 | #define CM_REG_CH0_FRAME1 0x80 /* base address */ | 371 | #define CM_REG_CH0_FRAME1 0x80 /* write: base address */ |
326 | #define CM_REG_CH0_FRAME2 0x84 | 372 | #define CM_REG_CH0_FRAME2 0x84 /* read: current address */ |
327 | #define CM_REG_CH1_FRAME1 0x88 /* 0-15: count of samples at bus master; buffer size */ | 373 | #define CM_REG_CH1_FRAME1 0x88 /* 0-15: count of samples at bus master; buffer size */ |
328 | #define CM_REG_CH1_FRAME2 0x8C /* 16-31: count of samples at codec; fragment size */ | 374 | #define CM_REG_CH1_FRAME2 0x8C /* 16-31: count of samples at codec; fragment size */ |
375 | |||
329 | #define CM_REG_EXT_MISC 0x90 | 376 | #define CM_REG_EXT_MISC 0x90 |
330 | #define CM_REG_MISC_CTRL_8768 0x92 /* reg. name the same as 0x18 */ | 377 | #define CM_ADC48K44K 0x10000000 /* ADC parameters group, 0: 44k, 1: 48k */ |
331 | #define CM_CHB3D8C 0x20 /* 7.1 channels support */ | 378 | #define CM_CHB3D8C 0x00200000 /* 7.1 channels support */ |
332 | #define CM_SPD32FMT 0x10 /* SPDIF/IN 32k */ | 379 | #define CM_SPD32FMT 0x00100000 /* SPDIF/IN 32k sample rate */ |
333 | #define CM_ADC2SPDIF 0x08 /* ADC output to SPDIF/OUT */ | 380 | #define CM_ADC2SPDIF 0x00080000 /* ADC output to SPDIF/OUT */ |
334 | #define CM_SHAREADC 0x04 /* DAC in ADC as Center/LFE */ | 381 | #define CM_SHAREADC 0x00040000 /* DAC in ADC as Center/LFE */ |
335 | #define CM_REALTCMP 0x02 /* monitor the CMPL/CMPR of ADC */ | 382 | #define CM_REALTCMP 0x00020000 /* monitor the CMPL/CMPR of ADC */ |
336 | #define CM_INVLRCK 0x01 /* invert ZVPORT's LRCK */ | 383 | #define CM_INVLRCK 0x00010000 /* invert ZVPORT's LRCK */ |
384 | #define CM_UNKNOWN_90_MASK 0x0000FFFF /* ? */ | ||
337 | 385 | ||
338 | /* | 386 | /* |
339 | * size of i/o region | 387 | * size of i/o region |
@@ -383,15 +431,14 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); | |||
383 | 431 | ||
384 | struct cmipci_pcm { | 432 | struct cmipci_pcm { |
385 | struct snd_pcm_substream *substream; | 433 | struct snd_pcm_substream *substream; |
386 | int running; /* dac/adc running? */ | 434 | u8 running; /* dac/adc running? */ |
435 | u8 fmt; /* format bits */ | ||
436 | u8 is_dac; | ||
437 | u8 needs_silencing; | ||
387 | unsigned int dma_size; /* in frames */ | 438 | unsigned int dma_size; /* in frames */ |
388 | unsigned int period_size; /* in frames */ | 439 | unsigned int shift; |
440 | unsigned int ch; /* channel (0/1) */ | ||
389 | unsigned int offset; /* physical address of the buffer */ | 441 | unsigned int offset; /* physical address of the buffer */ |
390 | unsigned int fmt; /* format bits */ | ||
391 | int ch; /* channel (0/1) */ | ||
392 | unsigned int is_dac; /* is dac? */ | ||
393 | int bytes_per_frame; | ||
394 | int shift; | ||
395 | }; | 442 | }; |
396 | 443 | ||
397 | /* mixer elements toggled/resumed during ac3 playback */ | 444 | /* mixer elements toggled/resumed during ac3 playback */ |
@@ -424,7 +471,6 @@ struct cmipci { | |||
424 | 471 | ||
425 | int chip_version; | 472 | int chip_version; |
426 | int max_channels; | 473 | int max_channels; |
427 | unsigned int has_dual_dac: 1; | ||
428 | unsigned int can_ac3_sw: 1; | 474 | unsigned int can_ac3_sw: 1; |
429 | unsigned int can_ac3_hw: 1; | 475 | unsigned int can_ac3_hw: 1; |
430 | unsigned int can_multi_ch: 1; | 476 | unsigned int can_multi_ch: 1; |
@@ -557,6 +603,9 @@ static unsigned int rates[] = { 5512, 11025, 22050, 44100, 8000, 16000, 32000, 4 | |||
557 | static unsigned int snd_cmipci_rate_freq(unsigned int rate) | 603 | static unsigned int snd_cmipci_rate_freq(unsigned int rate) |
558 | { | 604 | { |
559 | unsigned int i; | 605 | unsigned int i; |
606 | |||
607 | if (rate > 48000) | ||
608 | rate /= 2; | ||
560 | for (i = 0; i < ARRAY_SIZE(rates); i++) { | 609 | for (i = 0; i < ARRAY_SIZE(rates); i++) { |
561 | if (rates[i] == rate) | 610 | if (rates[i] == rate) |
562 | return i; | 611 | return i; |
@@ -671,19 +720,19 @@ static int snd_cmipci_hw_free(struct snd_pcm_substream *substream) | |||
671 | /* | 720 | /* |
672 | */ | 721 | */ |
673 | 722 | ||
674 | static unsigned int hw_channels[] = {1, 2, 4, 5, 6, 8}; | 723 | static unsigned int hw_channels[] = {1, 2, 4, 6, 8}; |
675 | static struct snd_pcm_hw_constraint_list hw_constraints_channels_4 = { | 724 | static struct snd_pcm_hw_constraint_list hw_constraints_channels_4 = { |
676 | .count = 3, | 725 | .count = 3, |
677 | .list = hw_channels, | 726 | .list = hw_channels, |
678 | .mask = 0, | 727 | .mask = 0, |
679 | }; | 728 | }; |
680 | static struct snd_pcm_hw_constraint_list hw_constraints_channels_6 = { | 729 | static struct snd_pcm_hw_constraint_list hw_constraints_channels_6 = { |
681 | .count = 5, | 730 | .count = 4, |
682 | .list = hw_channels, | 731 | .list = hw_channels, |
683 | .mask = 0, | 732 | .mask = 0, |
684 | }; | 733 | }; |
685 | static struct snd_pcm_hw_constraint_list hw_constraints_channels_8 = { | 734 | static struct snd_pcm_hw_constraint_list hw_constraints_channels_8 = { |
686 | .count = 6, | 735 | .count = 5, |
687 | .list = hw_channels, | 736 | .list = hw_channels, |
688 | .mask = 0, | 737 | .mask = 0, |
689 | }; | 738 | }; |
@@ -691,48 +740,37 @@ static struct snd_pcm_hw_constraint_list hw_constraints_channels_8 = { | |||
691 | static int set_dac_channels(struct cmipci *cm, struct cmipci_pcm *rec, int channels) | 740 | static int set_dac_channels(struct cmipci *cm, struct cmipci_pcm *rec, int channels) |
692 | { | 741 | { |
693 | if (channels > 2) { | 742 | if (channels > 2) { |
694 | if (! cm->can_multi_ch) | 743 | if (!cm->can_multi_ch || !rec->ch) |
695 | return -EINVAL; | 744 | return -EINVAL; |
696 | if (rec->fmt != 0x03) /* stereo 16bit only */ | 745 | if (rec->fmt != 0x03) /* stereo 16bit only */ |
697 | return -EINVAL; | 746 | return -EINVAL; |
747 | } | ||
698 | 748 | ||
749 | if (cm->can_multi_ch) { | ||
699 | spin_lock_irq(&cm->reg_lock); | 750 | spin_lock_irq(&cm->reg_lock); |
700 | snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_NXCHG); | 751 | if (channels > 2) { |
701 | snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC); | 752 | snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_NXCHG); |
702 | if (channels > 4) { | 753 | snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC); |
703 | snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D); | ||
704 | snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C); | ||
705 | } else { | 754 | } else { |
706 | snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C); | 755 | snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_NXCHG); |
707 | snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_CHB3D); | 756 | snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC); |
708 | } | 757 | } |
709 | if (channels >= 6) { | 758 | if (channels == 8) |
759 | snd_cmipci_set_bit(cm, CM_REG_EXT_MISC, CM_CHB3D8C); | ||
760 | else | ||
761 | snd_cmipci_clear_bit(cm, CM_REG_EXT_MISC, CM_CHB3D8C); | ||
762 | if (channels == 6) { | ||
763 | snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C); | ||
710 | snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C); | 764 | snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C); |
711 | snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_ENCENTER); | ||
712 | } else { | 765 | } else { |
713 | snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C); | ||
714 | snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_ENCENTER); | ||
715 | } | ||
716 | if (cm->chip_version == 68) { | ||
717 | if (channels == 8) { | ||
718 | snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL_8768, CM_CHB3D8C); | ||
719 | } else { | ||
720 | snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL_8768, CM_CHB3D8C); | ||
721 | } | ||
722 | } | ||
723 | spin_unlock_irq(&cm->reg_lock); | ||
724 | |||
725 | } else { | ||
726 | if (cm->can_multi_ch) { | ||
727 | spin_lock_irq(&cm->reg_lock); | ||
728 | snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_NXCHG); | ||
729 | snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D); | ||
730 | snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C); | 766 | snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C); |
731 | snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C); | 767 | snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C); |
732 | snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_ENCENTER); | ||
733 | snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC); | ||
734 | spin_unlock_irq(&cm->reg_lock); | ||
735 | } | 768 | } |
769 | if (channels == 4) | ||
770 | snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_CHB3D); | ||
771 | else | ||
772 | snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D); | ||
773 | spin_unlock_irq(&cm->reg_lock); | ||
736 | } | 774 | } |
737 | return 0; | 775 | return 0; |
738 | } | 776 | } |
@@ -746,6 +784,7 @@ static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec, | |||
746 | struct snd_pcm_substream *substream) | 784 | struct snd_pcm_substream *substream) |
747 | { | 785 | { |
748 | unsigned int reg, freq, val; | 786 | unsigned int reg, freq, val; |
787 | unsigned int period_size; | ||
749 | struct snd_pcm_runtime *runtime = substream->runtime; | 788 | struct snd_pcm_runtime *runtime = substream->runtime; |
750 | 789 | ||
751 | rec->fmt = 0; | 790 | rec->fmt = 0; |
@@ -765,11 +804,11 @@ static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec, | |||
765 | rec->offset = runtime->dma_addr; | 804 | rec->offset = runtime->dma_addr; |
766 | /* buffer and period sizes in frame */ | 805 | /* buffer and period sizes in frame */ |
767 | rec->dma_size = runtime->buffer_size << rec->shift; | 806 | rec->dma_size = runtime->buffer_size << rec->shift; |
768 | rec->period_size = runtime->period_size << rec->shift; | 807 | period_size = runtime->period_size << rec->shift; |
769 | if (runtime->channels > 2) { | 808 | if (runtime->channels > 2) { |
770 | /* multi-channels */ | 809 | /* multi-channels */ |
771 | rec->dma_size = (rec->dma_size * runtime->channels) / 2; | 810 | rec->dma_size = (rec->dma_size * runtime->channels) / 2; |
772 | rec->period_size = (rec->period_size * runtime->channels) / 2; | 811 | period_size = (period_size * runtime->channels) / 2; |
773 | } | 812 | } |
774 | 813 | ||
775 | spin_lock_irq(&cm->reg_lock); | 814 | spin_lock_irq(&cm->reg_lock); |
@@ -780,7 +819,7 @@ static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec, | |||
780 | /* program sample counts */ | 819 | /* program sample counts */ |
781 | reg = rec->ch ? CM_REG_CH1_FRAME2 : CM_REG_CH0_FRAME2; | 820 | reg = rec->ch ? CM_REG_CH1_FRAME2 : CM_REG_CH0_FRAME2; |
782 | snd_cmipci_write_w(cm, reg, rec->dma_size - 1); | 821 | snd_cmipci_write_w(cm, reg, rec->dma_size - 1); |
783 | snd_cmipci_write_w(cm, reg + 2, rec->period_size - 1); | 822 | snd_cmipci_write_w(cm, reg + 2, period_size - 1); |
784 | 823 | ||
785 | /* set adc/dac flag */ | 824 | /* set adc/dac flag */ |
786 | val = rec->ch ? CM_CHADC1 : CM_CHADC0; | 825 | val = rec->ch ? CM_CHADC1 : CM_CHADC0; |
@@ -795,11 +834,11 @@ static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec, | |||
795 | freq = snd_cmipci_rate_freq(runtime->rate); | 834 | freq = snd_cmipci_rate_freq(runtime->rate); |
796 | val = snd_cmipci_read(cm, CM_REG_FUNCTRL1); | 835 | val = snd_cmipci_read(cm, CM_REG_FUNCTRL1); |
797 | if (rec->ch) { | 836 | if (rec->ch) { |
798 | val &= ~CM_ASFC_MASK; | ||
799 | val |= (freq << CM_ASFC_SHIFT) & CM_ASFC_MASK; | ||
800 | } else { | ||
801 | val &= ~CM_DSFC_MASK; | 837 | val &= ~CM_DSFC_MASK; |
802 | val |= (freq << CM_DSFC_SHIFT) & CM_DSFC_MASK; | 838 | val |= (freq << CM_DSFC_SHIFT) & CM_DSFC_MASK; |
839 | } else { | ||
840 | val &= ~CM_ASFC_MASK; | ||
841 | val |= (freq << CM_ASFC_SHIFT) & CM_ASFC_MASK; | ||
803 | } | 842 | } |
804 | snd_cmipci_write(cm, CM_REG_FUNCTRL1, val); | 843 | snd_cmipci_write(cm, CM_REG_FUNCTRL1, val); |
805 | //snd_printd("cmipci: functrl1 = %08x\n", val); | 844 | //snd_printd("cmipci: functrl1 = %08x\n", val); |
@@ -813,6 +852,16 @@ static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec, | |||
813 | val &= ~CM_CH0FMT_MASK; | 852 | val &= ~CM_CH0FMT_MASK; |
814 | val |= rec->fmt << CM_CH0FMT_SHIFT; | 853 | val |= rec->fmt << CM_CH0FMT_SHIFT; |
815 | } | 854 | } |
855 | if (cm->chip_version == 68) { | ||
856 | if (runtime->rate == 88200) | ||
857 | val |= CM_CH0_SRATE_88K << (rec->ch * 2); | ||
858 | else | ||
859 | val &= ~(CM_CH0_SRATE_88K << (rec->ch * 2)); | ||
860 | if (runtime->rate == 96000) | ||
861 | val |= CM_CH0_SRATE_96K << (rec->ch * 2); | ||
862 | else | ||
863 | val &= ~(CM_CH0_SRATE_96K << (rec->ch * 2)); | ||
864 | } | ||
816 | snd_cmipci_write(cm, CM_REG_CHFORMAT, val); | 865 | snd_cmipci_write(cm, CM_REG_CHFORMAT, val); |
817 | //snd_printd("cmipci: chformat = %08x\n", val); | 866 | //snd_printd("cmipci: chformat = %08x\n", val); |
818 | 867 | ||
@@ -826,7 +875,7 @@ static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec, | |||
826 | * PCM trigger/stop | 875 | * PCM trigger/stop |
827 | */ | 876 | */ |
828 | static int snd_cmipci_pcm_trigger(struct cmipci *cm, struct cmipci_pcm *rec, | 877 | static int snd_cmipci_pcm_trigger(struct cmipci *cm, struct cmipci_pcm *rec, |
829 | struct snd_pcm_substream *substream, int cmd) | 878 | int cmd) |
830 | { | 879 | { |
831 | unsigned int inthld, chen, reset, pause; | 880 | unsigned int inthld, chen, reset, pause; |
832 | int result = 0; | 881 | int result = 0; |
@@ -855,6 +904,7 @@ static int snd_cmipci_pcm_trigger(struct cmipci *cm, struct cmipci_pcm *rec, | |||
855 | cm->ctrl &= ~chen; | 904 | cm->ctrl &= ~chen; |
856 | snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl | reset); | 905 | snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl | reset); |
857 | snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl & ~reset); | 906 | snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl & ~reset); |
907 | rec->needs_silencing = rec->is_dac; | ||
858 | break; | 908 | break; |
859 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 909 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
860 | case SNDRV_PCM_TRIGGER_SUSPEND: | 910 | case SNDRV_PCM_TRIGGER_SUSPEND: |
@@ -906,7 +956,7 @@ static int snd_cmipci_playback_trigger(struct snd_pcm_substream *substream, | |||
906 | int cmd) | 956 | int cmd) |
907 | { | 957 | { |
908 | struct cmipci *cm = snd_pcm_substream_chip(substream); | 958 | struct cmipci *cm = snd_pcm_substream_chip(substream); |
909 | return snd_cmipci_pcm_trigger(cm, &cm->channel[CM_CH_PLAY], substream, cmd); | 959 | return snd_cmipci_pcm_trigger(cm, &cm->channel[CM_CH_PLAY], cmd); |
910 | } | 960 | } |
911 | 961 | ||
912 | static snd_pcm_uframes_t snd_cmipci_playback_pointer(struct snd_pcm_substream *substream) | 962 | static snd_pcm_uframes_t snd_cmipci_playback_pointer(struct snd_pcm_substream *substream) |
@@ -925,7 +975,7 @@ static int snd_cmipci_capture_trigger(struct snd_pcm_substream *substream, | |||
925 | int cmd) | 975 | int cmd) |
926 | { | 976 | { |
927 | struct cmipci *cm = snd_pcm_substream_chip(substream); | 977 | struct cmipci *cm = snd_pcm_substream_chip(substream); |
928 | return snd_cmipci_pcm_trigger(cm, &cm->channel[CM_CH_CAPT], substream, cmd); | 978 | return snd_cmipci_pcm_trigger(cm, &cm->channel[CM_CH_CAPT], cmd); |
929 | } | 979 | } |
930 | 980 | ||
931 | static snd_pcm_uframes_t snd_cmipci_capture_pointer(struct snd_pcm_substream *substream) | 981 | static snd_pcm_uframes_t snd_cmipci_capture_pointer(struct snd_pcm_substream *substream) |
@@ -1199,15 +1249,19 @@ static int setup_spdif_playback(struct cmipci *cm, struct snd_pcm_substream *sub | |||
1199 | snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_PLAYBACK_SPDF); | 1249 | snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_PLAYBACK_SPDF); |
1200 | setup_ac3(cm, subs, do_ac3, rate); | 1250 | setup_ac3(cm, subs, do_ac3, rate); |
1201 | 1251 | ||
1202 | if (rate == 48000) | 1252 | if (rate == 48000 || rate == 96000) |
1203 | snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_SPDIF48K | CM_SPDF_AC97); | 1253 | snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_SPDIF48K | CM_SPDF_AC97); |
1204 | else | 1254 | else |
1205 | snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_SPDIF48K | CM_SPDF_AC97); | 1255 | snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_SPDIF48K | CM_SPDF_AC97); |
1206 | 1256 | if (rate > 48000) | |
1257 | snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_DBLSPDS); | ||
1258 | else | ||
1259 | snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_DBLSPDS); | ||
1207 | } else { | 1260 | } else { |
1208 | /* they are controlled via "IEC958 Output Switch" */ | 1261 | /* they are controlled via "IEC958 Output Switch" */ |
1209 | /* snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_ENSPDOUT); */ | 1262 | /* snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_ENSPDOUT); */ |
1210 | /* snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_SPDO2DAC); */ | 1263 | /* snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_SPDO2DAC); */ |
1264 | snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_DBLSPDS); | ||
1211 | snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_PLAYBACK_SPDF); | 1265 | snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_PLAYBACK_SPDF); |
1212 | setup_ac3(cm, subs, 0, 0); | 1266 | setup_ac3(cm, subs, 0, 0); |
1213 | } | 1267 | } |
@@ -1227,7 +1281,7 @@ static int snd_cmipci_playback_prepare(struct snd_pcm_substream *substream) | |||
1227 | int rate = substream->runtime->rate; | 1281 | int rate = substream->runtime->rate; |
1228 | int err, do_spdif, do_ac3 = 0; | 1282 | int err, do_spdif, do_ac3 = 0; |
1229 | 1283 | ||
1230 | do_spdif = ((rate == 44100 || rate == 48000) && | 1284 | do_spdif = (rate >= 44100 && |
1231 | substream->runtime->format == SNDRV_PCM_FORMAT_S16_LE && | 1285 | substream->runtime->format == SNDRV_PCM_FORMAT_S16_LE && |
1232 | substream->runtime->channels == 2); | 1286 | substream->runtime->channels == 2); |
1233 | if (do_spdif && cm->can_ac3_hw) | 1287 | if (do_spdif && cm->can_ac3_hw) |
@@ -1252,11 +1306,75 @@ static int snd_cmipci_playback_spdif_prepare(struct snd_pcm_substream *substream | |||
1252 | return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_PLAY], substream); | 1306 | return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_PLAY], substream); |
1253 | } | 1307 | } |
1254 | 1308 | ||
1309 | /* | ||
1310 | * Apparently, the samples last played on channel A stay in some buffer, even | ||
1311 | * after the channel is reset, and get added to the data for the rear DACs when | ||
1312 | * playing a multichannel stream on channel B. This is likely to generate | ||
1313 | * wraparounds and thus distortions. | ||
1314 | * To avoid this, we play at least one zero sample after the actual stream has | ||
1315 | * stopped. | ||
1316 | */ | ||
1317 | static void snd_cmipci_silence_hack(struct cmipci *cm, struct cmipci_pcm *rec) | ||
1318 | { | ||
1319 | struct snd_pcm_runtime *runtime = rec->substream->runtime; | ||
1320 | unsigned int reg, val; | ||
1321 | |||
1322 | if (rec->needs_silencing && runtime && runtime->dma_area) { | ||
1323 | /* set up a small silence buffer */ | ||
1324 | memset(runtime->dma_area, 0, PAGE_SIZE); | ||
1325 | reg = rec->ch ? CM_REG_CH1_FRAME2 : CM_REG_CH0_FRAME2; | ||
1326 | val = ((PAGE_SIZE / 4) - 1) | (((PAGE_SIZE / 4) / 2 - 1) << 16); | ||
1327 | snd_cmipci_write(cm, reg, val); | ||
1328 | |||
1329 | /* configure for 16 bits, 2 channels, 8 kHz */ | ||
1330 | if (runtime->channels > 2) | ||
1331 | set_dac_channels(cm, rec, 2); | ||
1332 | spin_lock_irq(&cm->reg_lock); | ||
1333 | val = snd_cmipci_read(cm, CM_REG_FUNCTRL1); | ||
1334 | val &= ~(CM_ASFC_MASK << (rec->ch * 3)); | ||
1335 | val |= (4 << CM_ASFC_SHIFT) << (rec->ch * 3); | ||
1336 | snd_cmipci_write(cm, CM_REG_FUNCTRL1, val); | ||
1337 | val = snd_cmipci_read(cm, CM_REG_CHFORMAT); | ||
1338 | val &= ~(CM_CH0FMT_MASK << (rec->ch * 2)); | ||
1339 | val |= (3 << CM_CH0FMT_SHIFT) << (rec->ch * 2); | ||
1340 | if (cm->chip_version == 68) { | ||
1341 | val &= ~(CM_CH0_SRATE_88K << (rec->ch * 2)); | ||
1342 | val &= ~(CM_CH0_SRATE_96K << (rec->ch * 2)); | ||
1343 | } | ||
1344 | snd_cmipci_write(cm, CM_REG_CHFORMAT, val); | ||
1345 | |||
1346 | /* start stream (we don't need interrupts) */ | ||
1347 | cm->ctrl |= CM_CHEN0 << rec->ch; | ||
1348 | snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl); | ||
1349 | spin_unlock_irq(&cm->reg_lock); | ||
1350 | |||
1351 | msleep(1); | ||
1352 | |||
1353 | /* stop and reset stream */ | ||
1354 | spin_lock_irq(&cm->reg_lock); | ||
1355 | cm->ctrl &= ~(CM_CHEN0 << rec->ch); | ||
1356 | val = CM_RST_CH0 << rec->ch; | ||
1357 | snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl | val); | ||
1358 | snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl & ~val); | ||
1359 | spin_unlock_irq(&cm->reg_lock); | ||
1360 | |||
1361 | rec->needs_silencing = 0; | ||
1362 | } | ||
1363 | } | ||
1364 | |||
1255 | static int snd_cmipci_playback_hw_free(struct snd_pcm_substream *substream) | 1365 | static int snd_cmipci_playback_hw_free(struct snd_pcm_substream *substream) |
1256 | { | 1366 | { |
1257 | struct cmipci *cm = snd_pcm_substream_chip(substream); | 1367 | struct cmipci *cm = snd_pcm_substream_chip(substream); |
1258 | setup_spdif_playback(cm, substream, 0, 0); | 1368 | setup_spdif_playback(cm, substream, 0, 0); |
1259 | restore_mixer_state(cm); | 1369 | restore_mixer_state(cm); |
1370 | snd_cmipci_silence_hack(cm, &cm->channel[0]); | ||
1371 | return snd_cmipci_hw_free(substream); | ||
1372 | } | ||
1373 | |||
1374 | static int snd_cmipci_playback2_hw_free(struct snd_pcm_substream *substream) | ||
1375 | { | ||
1376 | struct cmipci *cm = snd_pcm_substream_chip(substream); | ||
1377 | snd_cmipci_silence_hack(cm, &cm->channel[1]); | ||
1260 | return snd_cmipci_hw_free(substream); | 1378 | return snd_cmipci_hw_free(substream); |
1261 | } | 1379 | } |
1262 | 1380 | ||
@@ -1515,7 +1633,11 @@ static int snd_cmipci_playback_open(struct snd_pcm_substream *substream) | |||
1515 | if ((err = open_device_check(cm, CM_OPEN_PLAYBACK, substream)) < 0) | 1633 | if ((err = open_device_check(cm, CM_OPEN_PLAYBACK, substream)) < 0) |
1516 | return err; | 1634 | return err; |
1517 | runtime->hw = snd_cmipci_playback; | 1635 | runtime->hw = snd_cmipci_playback; |
1518 | runtime->hw.channels_max = cm->max_channels; | 1636 | if (cm->chip_version == 68) { |
1637 | runtime->hw.rates |= SNDRV_PCM_RATE_88200 | | ||
1638 | SNDRV_PCM_RATE_96000; | ||
1639 | runtime->hw.rate_max = 96000; | ||
1640 | } | ||
1519 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); | 1641 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); |
1520 | cm->dig_pcm_status = cm->dig_status; | 1642 | cm->dig_pcm_status = cm->dig_status; |
1521 | return 0; | 1643 | return 0; |
@@ -1558,9 +1680,14 @@ static int snd_cmipci_playback2_open(struct snd_pcm_substream *substream) | |||
1558 | else if (cm->max_channels == 8) | 1680 | else if (cm->max_channels == 8) |
1559 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels_8); | 1681 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels_8); |
1560 | } | 1682 | } |
1561 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); | ||
1562 | } | 1683 | } |
1563 | mutex_unlock(&cm->open_mutex); | 1684 | mutex_unlock(&cm->open_mutex); |
1685 | if (cm->chip_version == 68) { | ||
1686 | runtime->hw.rates |= SNDRV_PCM_RATE_88200 | | ||
1687 | SNDRV_PCM_RATE_96000; | ||
1688 | runtime->hw.rate_max = 96000; | ||
1689 | } | ||
1690 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); | ||
1564 | return 0; | 1691 | return 0; |
1565 | } | 1692 | } |
1566 | 1693 | ||
@@ -1574,8 +1701,15 @@ static int snd_cmipci_playback_spdif_open(struct snd_pcm_substream *substream) | |||
1574 | return err; | 1701 | return err; |
1575 | if (cm->can_ac3_hw) { | 1702 | if (cm->can_ac3_hw) { |
1576 | runtime->hw = snd_cmipci_playback_spdif; | 1703 | runtime->hw = snd_cmipci_playback_spdif; |
1577 | if (cm->chip_version >= 37) | 1704 | if (cm->chip_version >= 37) { |
1578 | runtime->hw.formats |= SNDRV_PCM_FMTBIT_S32_LE; | 1705 | runtime->hw.formats |= SNDRV_PCM_FMTBIT_S32_LE; |
1706 | snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); | ||
1707 | } | ||
1708 | if (cm->chip_version == 68) { | ||
1709 | runtime->hw.rates |= SNDRV_PCM_RATE_88200 | | ||
1710 | SNDRV_PCM_RATE_96000; | ||
1711 | runtime->hw.rate_max = 96000; | ||
1712 | } | ||
1579 | } else { | 1713 | } else { |
1580 | runtime->hw = snd_cmipci_playback_iec958_subframe; | 1714 | runtime->hw = snd_cmipci_playback_iec958_subframe; |
1581 | } | 1715 | } |
@@ -1668,7 +1802,7 @@ static struct snd_pcm_ops snd_cmipci_playback2_ops = { | |||
1668 | .close = snd_cmipci_playback2_close, | 1802 | .close = snd_cmipci_playback2_close, |
1669 | .ioctl = snd_pcm_lib_ioctl, | 1803 | .ioctl = snd_pcm_lib_ioctl, |
1670 | .hw_params = snd_cmipci_playback2_hw_params, | 1804 | .hw_params = snd_cmipci_playback2_hw_params, |
1671 | .hw_free = snd_cmipci_hw_free, | 1805 | .hw_free = snd_cmipci_playback2_hw_free, |
1672 | .prepare = snd_cmipci_capture_prepare, /* channel B */ | 1806 | .prepare = snd_cmipci_capture_prepare, /* channel B */ |
1673 | .trigger = snd_cmipci_capture_trigger, /* channel B */ | 1807 | .trigger = snd_cmipci_capture_trigger, /* channel B */ |
1674 | .pointer = snd_cmipci_capture_pointer, /* channel B */ | 1808 | .pointer = snd_cmipci_capture_pointer, /* channel B */ |
@@ -2139,15 +2273,7 @@ struct cmipci_switch_args { | |||
2139 | */ | 2273 | */ |
2140 | }; | 2274 | }; |
2141 | 2275 | ||
2142 | static int snd_cmipci_uswitch_info(struct snd_kcontrol *kcontrol, | 2276 | #define snd_cmipci_uswitch_info snd_ctl_boolean_mono_info |
2143 | struct snd_ctl_elem_info *uinfo) | ||
2144 | { | ||
2145 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2146 | uinfo->count = 1; | ||
2147 | uinfo->value.integer.min = 0; | ||
2148 | uinfo->value.integer.max = 1; | ||
2149 | return 0; | ||
2150 | } | ||
2151 | 2277 | ||
2152 | static int _snd_cmipci_uswitch_get(struct snd_kcontrol *kcontrol, | 2278 | static int _snd_cmipci_uswitch_get(struct snd_kcontrol *kcontrol, |
2153 | struct snd_ctl_elem_value *ucontrol, | 2279 | struct snd_ctl_elem_value *ucontrol, |
@@ -2260,8 +2386,8 @@ DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, 0, 0, 0); /* rever | |||
2260 | DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, CM_XCHGDAC, 0, 0); | 2386 | DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, CM_XCHGDAC, 0, 0); |
2261 | #endif | 2387 | #endif |
2262 | DEFINE_BIT_SWITCH_ARG(fourch, CM_REG_MISC_CTRL, CM_N4SPK3D, 0, 0); | 2388 | DEFINE_BIT_SWITCH_ARG(fourch, CM_REG_MISC_CTRL, CM_N4SPK3D, 0, 0); |
2263 | // DEFINE_BIT_SWITCH_ARG(line_rear, CM_REG_MIXER1, CM_SPK4, 1, 0); | 2389 | // DEFINE_BIT_SWITCH_ARG(line_rear, CM_REG_MIXER1, CM_REAR2LIN, 1, 0); |
2264 | // DEFINE_BIT_SWITCH_ARG(line_bass, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS, 0, 0); | 2390 | // DEFINE_BIT_SWITCH_ARG(line_bass, CM_REG_LEGACY_CTRL, CM_CENTR2LIN|CM_BASE2LIN, 0, 0); |
2265 | // DEFINE_BIT_SWITCH_ARG(joystick, CM_REG_FUNCTRL1, CM_JYSTK_EN, 0, 0); /* now module option */ | 2391 | // DEFINE_BIT_SWITCH_ARG(joystick, CM_REG_FUNCTRL1, CM_JYSTK_EN, 0, 0); /* now module option */ |
2266 | DEFINE_SWITCH_ARG(modem, CM_REG_MISC_CTRL, CM_FLINKON|CM_FLINKOFF, CM_FLINKON, 0, 0); | 2392 | DEFINE_SWITCH_ARG(modem, CM_REG_MISC_CTRL, CM_FLINKON|CM_FLINKOFF, CM_FLINKON, 0, 0); |
2267 | 2393 | ||
@@ -2331,11 +2457,11 @@ static inline unsigned int get_line_in_mode(struct cmipci *cm) | |||
2331 | unsigned int val; | 2457 | unsigned int val; |
2332 | if (cm->chip_version >= 39) { | 2458 | if (cm->chip_version >= 39) { |
2333 | val = snd_cmipci_read(cm, CM_REG_LEGACY_CTRL); | 2459 | val = snd_cmipci_read(cm, CM_REG_LEGACY_CTRL); |
2334 | if (val & CM_LINE_AS_BASS) | 2460 | if (val & (CM_CENTR2LIN | CM_BASE2LIN)) |
2335 | return 2; | 2461 | return 2; |
2336 | } | 2462 | } |
2337 | val = snd_cmipci_read_b(cm, CM_REG_MIXER1); | 2463 | val = snd_cmipci_read_b(cm, CM_REG_MIXER1); |
2338 | if (val & CM_SPK4) | 2464 | if (val & CM_REAR2LIN) |
2339 | return 1; | 2465 | return 1; |
2340 | return 0; | 2466 | return 0; |
2341 | } | 2467 | } |
@@ -2359,13 +2485,13 @@ static int snd_cmipci_line_in_mode_put(struct snd_kcontrol *kcontrol, | |||
2359 | 2485 | ||
2360 | spin_lock_irq(&cm->reg_lock); | 2486 | spin_lock_irq(&cm->reg_lock); |
2361 | if (ucontrol->value.enumerated.item[0] == 2) | 2487 | if (ucontrol->value.enumerated.item[0] == 2) |
2362 | change = snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS); | 2488 | change = snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_CENTR2LIN | CM_BASE2LIN); |
2363 | else | 2489 | else |
2364 | change = snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS); | 2490 | change = snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_CENTR2LIN | CM_BASE2LIN); |
2365 | if (ucontrol->value.enumerated.item[0] == 1) | 2491 | if (ucontrol->value.enumerated.item[0] == 1) |
2366 | change |= snd_cmipci_set_bit_b(cm, CM_REG_MIXER1, CM_SPK4); | 2492 | change |= snd_cmipci_set_bit_b(cm, CM_REG_MIXER1, CM_REAR2LIN); |
2367 | else | 2493 | else |
2368 | change |= snd_cmipci_clear_bit_b(cm, CM_REG_MIXER1, CM_SPK4); | 2494 | change |= snd_cmipci_clear_bit_b(cm, CM_REG_MIXER1, CM_REAR2LIN); |
2369 | spin_unlock_irq(&cm->reg_lock); | 2495 | spin_unlock_irq(&cm->reg_lock); |
2370 | return change; | 2496 | return change; |
2371 | } | 2497 | } |
@@ -2583,19 +2709,18 @@ static void snd_cmipci_proc_read(struct snd_info_entry *entry, | |||
2583 | struct snd_info_buffer *buffer) | 2709 | struct snd_info_buffer *buffer) |
2584 | { | 2710 | { |
2585 | struct cmipci *cm = entry->private_data; | 2711 | struct cmipci *cm = entry->private_data; |
2586 | int i; | 2712 | int i, v; |
2587 | 2713 | ||
2588 | snd_iprintf(buffer, "%s\n\n", cm->card->longname); | 2714 | snd_iprintf(buffer, "%s\n", cm->card->longname); |
2589 | for (i = 0; i < 0x40; i++) { | 2715 | for (i = 0; i < 0x94; i++) { |
2590 | int v = inb(cm->iobase + i); | 2716 | if (i == 0x28) |
2717 | i = 0x90; | ||
2718 | v = inb(cm->iobase + i); | ||
2591 | if (i % 4 == 0) | 2719 | if (i % 4 == 0) |
2592 | snd_iprintf(buffer, "%02x: ", i); | 2720 | snd_iprintf(buffer, "\n%02x:", i); |
2593 | snd_iprintf(buffer, "%02x", v); | 2721 | snd_iprintf(buffer, " %02x", v); |
2594 | if (i % 4 == 3) | ||
2595 | snd_iprintf(buffer, "\n"); | ||
2596 | else | ||
2597 | snd_iprintf(buffer, " "); | ||
2598 | } | 2722 | } |
2723 | snd_iprintf(buffer, "\n"); | ||
2599 | } | 2724 | } |
2600 | 2725 | ||
2601 | static void __devinit snd_cmipci_proc_init(struct cmipci *cm) | 2726 | static void __devinit snd_cmipci_proc_init(struct cmipci *cm) |
@@ -2633,46 +2758,40 @@ static void __devinit query_chip(struct cmipci *cm) | |||
2633 | if (! detect) { | 2758 | if (! detect) { |
2634 | /* check reg 08h, bit 24-28 */ | 2759 | /* check reg 08h, bit 24-28 */ |
2635 | detect = snd_cmipci_read(cm, CM_REG_CHFORMAT) & CM_CHIP_MASK1; | 2760 | detect = snd_cmipci_read(cm, CM_REG_CHFORMAT) & CM_CHIP_MASK1; |
2636 | if (! detect) { | 2761 | switch (detect) { |
2762 | case 0: | ||
2637 | cm->chip_version = 33; | 2763 | cm->chip_version = 33; |
2638 | cm->max_channels = 2; | ||
2639 | if (cm->do_soft_ac3) | 2764 | if (cm->do_soft_ac3) |
2640 | cm->can_ac3_sw = 1; | 2765 | cm->can_ac3_sw = 1; |
2641 | else | 2766 | else |
2642 | cm->can_ac3_hw = 1; | 2767 | cm->can_ac3_hw = 1; |
2643 | cm->has_dual_dac = 1; | 2768 | break; |
2644 | } else { | 2769 | case CM_CHIP_037: |
2645 | cm->chip_version = 37; | 2770 | cm->chip_version = 37; |
2646 | cm->max_channels = 2; | ||
2647 | cm->can_ac3_hw = 1; | 2771 | cm->can_ac3_hw = 1; |
2648 | cm->has_dual_dac = 1; | 2772 | break; |
2773 | default: | ||
2774 | cm->chip_version = 39; | ||
2775 | cm->can_ac3_hw = 1; | ||
2776 | break; | ||
2649 | } | 2777 | } |
2778 | cm->max_channels = 2; | ||
2650 | } else { | 2779 | } else { |
2651 | /* check reg 0Ch, bit 26 */ | 2780 | if (detect & CM_CHIP_039) { |
2652 | if (detect & CM_CHIP_8768) { | ||
2653 | cm->chip_version = 68; | ||
2654 | cm->max_channels = 8; | ||
2655 | cm->can_ac3_hw = 1; | ||
2656 | cm->has_dual_dac = 1; | ||
2657 | cm->can_multi_ch = 1; | ||
2658 | } else if (detect & CM_CHIP_055) { | ||
2659 | cm->chip_version = 55; | ||
2660 | cm->max_channels = 6; | ||
2661 | cm->can_ac3_hw = 1; | ||
2662 | cm->has_dual_dac = 1; | ||
2663 | cm->can_multi_ch = 1; | ||
2664 | } else if (detect & CM_CHIP_039) { | ||
2665 | cm->chip_version = 39; | 2781 | cm->chip_version = 39; |
2666 | if (detect & CM_CHIP_039_6CH) /* 4 or 6 channels */ | 2782 | if (detect & CM_CHIP_039_6CH) /* 4 or 6 channels */ |
2667 | cm->max_channels = 6; | 2783 | cm->max_channels = 6; |
2668 | else | 2784 | else |
2669 | cm->max_channels = 4; | 2785 | cm->max_channels = 4; |
2670 | cm->can_ac3_hw = 1; | 2786 | } else if (detect & CM_CHIP_8768) { |
2671 | cm->has_dual_dac = 1; | 2787 | cm->chip_version = 68; |
2672 | cm->can_multi_ch = 1; | 2788 | cm->max_channels = 8; |
2673 | } else { | 2789 | } else { |
2674 | printk(KERN_ERR "chip %x version not supported\n", detect); | 2790 | cm->chip_version = 55; |
2791 | cm->max_channels = 6; | ||
2675 | } | 2792 | } |
2793 | cm->can_ac3_hw = 1; | ||
2794 | cm->can_multi_ch = 1; | ||
2676 | } | 2795 | } |
2677 | } | 2796 | } |
2678 | 2797 | ||
@@ -2782,10 +2901,14 @@ static int __devinit snd_cmipci_create_fm(struct cmipci *cm, long fm_port) | |||
2782 | if (!fm_port) | 2901 | if (!fm_port) |
2783 | goto disable_fm; | 2902 | goto disable_fm; |
2784 | 2903 | ||
2785 | /* first try FM regs in PCI port range */ | 2904 | if (cm->chip_version >= 39) { |
2786 | iosynth = cm->iobase + CM_REG_FM_PCI; | 2905 | /* first try FM regs in PCI port range */ |
2787 | err = snd_opl3_create(cm->card, iosynth, iosynth + 2, | 2906 | iosynth = cm->iobase + CM_REG_FM_PCI; |
2788 | OPL3_HW_OPL3, 1, &opl3); | 2907 | err = snd_opl3_create(cm->card, iosynth, iosynth + 2, |
2908 | OPL3_HW_OPL3, 1, &opl3); | ||
2909 | } else { | ||
2910 | err = -EIO; | ||
2911 | } | ||
2789 | if (err < 0) { | 2912 | if (err < 0) { |
2790 | /* then try legacy ports */ | 2913 | /* then try legacy ports */ |
2791 | val = snd_cmipci_read(cm, CM_REG_LEGACY_CTRL) & ~CM_FMSEL_MASK; | 2914 | val = snd_cmipci_read(cm, CM_REG_LEGACY_CTRL) & ~CM_FMSEL_MASK; |
@@ -2829,9 +2952,10 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc | |||
2829 | static struct snd_device_ops ops = { | 2952 | static struct snd_device_ops ops = { |
2830 | .dev_free = snd_cmipci_dev_free, | 2953 | .dev_free = snd_cmipci_dev_free, |
2831 | }; | 2954 | }; |
2832 | unsigned int val = 0; | 2955 | unsigned int val; |
2833 | long iomidi; | 2956 | long iomidi; |
2834 | int integrated_midi; | 2957 | int integrated_midi = 0; |
2958 | char modelstr[16]; | ||
2835 | int pcm_index, pcm_spdif_index; | 2959 | int pcm_index, pcm_spdif_index; |
2836 | static struct pci_device_id intel_82437vx[] = { | 2960 | static struct pci_device_id intel_82437vx[] = { |
2837 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437VX) }, | 2961 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437VX) }, |
@@ -2904,6 +3028,8 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc | |||
2904 | #endif | 3028 | #endif |
2905 | 3029 | ||
2906 | /* initialize codec registers */ | 3030 | /* initialize codec registers */ |
3031 | snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_RESET); | ||
3032 | snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_RESET); | ||
2907 | snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0); /* disable ints */ | 3033 | snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0); /* disable ints */ |
2908 | snd_cmipci_ch_reset(cm, CM_CH_PLAY); | 3034 | snd_cmipci_ch_reset(cm, CM_CH_PLAY); |
2909 | snd_cmipci_ch_reset(cm, CM_CH_CAPT); | 3035 | snd_cmipci_ch_reset(cm, CM_CH_CAPT); |
@@ -2917,6 +3043,10 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc | |||
2917 | #else | 3043 | #else |
2918 | snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC); | 3044 | snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC); |
2919 | #endif | 3045 | #endif |
3046 | if (cm->chip_version) { | ||
3047 | snd_cmipci_write_b(cm, CM_REG_EXT_MISC, 0x20); /* magic */ | ||
3048 | snd_cmipci_write_b(cm, CM_REG_EXT_MISC + 1, 0x09); /* more magic */ | ||
3049 | } | ||
2920 | /* Set Bus Master Request */ | 3050 | /* Set Bus Master Request */ |
2921 | snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_BREQ); | 3051 | snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_BREQ); |
2922 | 3052 | ||
@@ -2931,15 +3061,55 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc | |||
2931 | break; | 3061 | break; |
2932 | } | 3062 | } |
2933 | 3063 | ||
3064 | if (cm->chip_version < 68) { | ||
3065 | val = pci->device < 0x110 ? 8338 : 8738; | ||
3066 | } else { | ||
3067 | switch (snd_cmipci_read_b(cm, CM_REG_INT_HLDCLR + 3) & 0x03) { | ||
3068 | case 0: | ||
3069 | val = 8769; | ||
3070 | break; | ||
3071 | case 2: | ||
3072 | val = 8762; | ||
3073 | break; | ||
3074 | default: | ||
3075 | switch ((pci->subsystem_vendor << 16) | | ||
3076 | pci->subsystem_device) { | ||
3077 | case 0x13f69761: | ||
3078 | case 0x584d3741: | ||
3079 | case 0x584d3751: | ||
3080 | case 0x584d3761: | ||
3081 | case 0x584d3771: | ||
3082 | case 0x72848384: | ||
3083 | val = 8770; | ||
3084 | break; | ||
3085 | default: | ||
3086 | val = 8768; | ||
3087 | break; | ||
3088 | } | ||
3089 | } | ||
3090 | } | ||
3091 | sprintf(card->shortname, "C-Media CMI%d", val); | ||
3092 | if (cm->chip_version < 68) | ||
3093 | sprintf(modelstr, " (model %d)", cm->chip_version); | ||
3094 | else | ||
3095 | modelstr[0] = '\0'; | ||
3096 | sprintf(card->longname, "%s%s at %#lx, irq %i", | ||
3097 | card->shortname, modelstr, cm->iobase, cm->irq); | ||
3098 | |||
2934 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, cm, &ops)) < 0) { | 3099 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, cm, &ops)) < 0) { |
2935 | snd_cmipci_free(cm); | 3100 | snd_cmipci_free(cm); |
2936 | return err; | 3101 | return err; |
2937 | } | 3102 | } |
2938 | 3103 | ||
2939 | integrated_midi = snd_cmipci_read_b(cm, CM_REG_MPU_PCI) != 0xff; | 3104 | if (cm->chip_version >= 39) { |
2940 | if (integrated_midi && mpu_port[dev] == 1) | 3105 | val = snd_cmipci_read_b(cm, CM_REG_MPU_PCI + 1); |
2941 | iomidi = cm->iobase + CM_REG_MPU_PCI; | 3106 | if (val != 0x00 && val != 0xff) { |
2942 | else { | 3107 | iomidi = cm->iobase + CM_REG_MPU_PCI; |
3108 | integrated_midi = 1; | ||
3109 | } | ||
3110 | } | ||
3111 | if (!integrated_midi) { | ||
3112 | val = 0; | ||
2943 | iomidi = mpu_port[dev]; | 3113 | iomidi = mpu_port[dev]; |
2944 | switch (iomidi) { | 3114 | switch (iomidi) { |
2945 | case 0x320: val = CM_VMPU_320; break; | 3115 | case 0x320: val = CM_VMPU_320; break; |
@@ -2953,11 +3123,21 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc | |||
2953 | snd_cmipci_write(cm, CM_REG_LEGACY_CTRL, val); | 3123 | snd_cmipci_write(cm, CM_REG_LEGACY_CTRL, val); |
2954 | /* enable UART */ | 3124 | /* enable UART */ |
2955 | snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_UART_EN); | 3125 | snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_UART_EN); |
3126 | if (inb(iomidi + 1) == 0xff) { | ||
3127 | snd_printk(KERN_ERR "cannot enable MPU-401 port" | ||
3128 | " at %#lx\n", iomidi); | ||
3129 | snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, | ||
3130 | CM_UART_EN); | ||
3131 | iomidi = 0; | ||
3132 | } | ||
2956 | } | 3133 | } |
2957 | } | 3134 | } |
2958 | 3135 | ||
2959 | if ((err = snd_cmipci_create_fm(cm, fm_port[dev])) < 0) | 3136 | if (cm->chip_version < 68) { |
2960 | return err; | 3137 | err = snd_cmipci_create_fm(cm, fm_port[dev]); |
3138 | if (err < 0) | ||
3139 | return err; | ||
3140 | } | ||
2961 | 3141 | ||
2962 | /* reset mixer */ | 3142 | /* reset mixer */ |
2963 | snd_cmipci_mixer_write(cm, 0, 0); | 3143 | snd_cmipci_mixer_write(cm, 0, 0); |
@@ -2969,11 +3149,9 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc | |||
2969 | if ((err = snd_cmipci_pcm_new(cm, pcm_index)) < 0) | 3149 | if ((err = snd_cmipci_pcm_new(cm, pcm_index)) < 0) |
2970 | return err; | 3150 | return err; |
2971 | pcm_index++; | 3151 | pcm_index++; |
2972 | if (cm->has_dual_dac) { | 3152 | if ((err = snd_cmipci_pcm2_new(cm, pcm_index)) < 0) |
2973 | if ((err = snd_cmipci_pcm2_new(cm, pcm_index)) < 0) | 3153 | return err; |
2974 | return err; | 3154 | pcm_index++; |
2975 | pcm_index++; | ||
2976 | } | ||
2977 | if (cm->can_ac3_hw || cm->can_ac3_sw) { | 3155 | if (cm->can_ac3_hw || cm->can_ac3_sw) { |
2978 | pcm_spdif_index = pcm_index; | 3156 | pcm_spdif_index = pcm_index; |
2979 | if ((err = snd_cmipci_pcm_spdif_new(cm, pcm_index)) < 0) | 3157 | if ((err = snd_cmipci_pcm_spdif_new(cm, pcm_index)) < 0) |
@@ -3057,15 +3235,6 @@ static int __devinit snd_cmipci_probe(struct pci_dev *pci, | |||
3057 | } | 3235 | } |
3058 | card->private_data = cm; | 3236 | card->private_data = cm; |
3059 | 3237 | ||
3060 | sprintf(card->shortname, "C-Media PCI %s", card->driver); | ||
3061 | sprintf(card->longname, "%s (model %d) at 0x%lx, irq %i", | ||
3062 | card->shortname, | ||
3063 | cm->chip_version, | ||
3064 | cm->iobase, | ||
3065 | cm->irq); | ||
3066 | |||
3067 | //snd_printd("%s is detected\n", card->longname); | ||
3068 | |||
3069 | if ((err = snd_card_register(card)) < 0) { | 3238 | if ((err = snd_card_register(card)) < 0) { |
3070 | snd_card_free(card); | 3239 | snd_card_free(card); |
3071 | return err; | 3240 | return err; |
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index 44cf54607647..9a55f4a9739b 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for Cirrus Logic CS4281 based PCI soundcard | 2 | * Driver for Cirrus Logic CS4281 based PCI soundcard |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz>, | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz>, |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -38,7 +38,7 @@ | |||
38 | #include <sound/initval.h> | 38 | #include <sound/initval.h> |
39 | 39 | ||
40 | 40 | ||
41 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 41 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
42 | MODULE_DESCRIPTION("Cirrus Logic CS4281"); | 42 | MODULE_DESCRIPTION("Cirrus Logic CS4281"); |
43 | MODULE_LICENSE("GPL"); | 43 | MODULE_LICENSE("GPL"); |
44 | MODULE_SUPPORTED_DEVICE("{{Cirrus Logic,CS4281}}"); | 44 | MODULE_SUPPORTED_DEVICE("{{Cirrus Logic,CS4281}}"); |
@@ -842,12 +842,11 @@ static snd_pcm_uframes_t snd_cs4281_pointer(struct snd_pcm_substream *substream) | |||
842 | 842 | ||
843 | static struct snd_pcm_hardware snd_cs4281_playback = | 843 | static struct snd_pcm_hardware snd_cs4281_playback = |
844 | { | 844 | { |
845 | .info = (SNDRV_PCM_INFO_MMAP | | 845 | .info = SNDRV_PCM_INFO_MMAP | |
846 | SNDRV_PCM_INFO_INTERLEAVED | | 846 | SNDRV_PCM_INFO_INTERLEAVED | |
847 | SNDRV_PCM_INFO_MMAP_VALID | | 847 | SNDRV_PCM_INFO_MMAP_VALID | |
848 | SNDRV_PCM_INFO_PAUSE | | 848 | SNDRV_PCM_INFO_PAUSE | |
849 | SNDRV_PCM_INFO_RESUME | | 849 | SNDRV_PCM_INFO_RESUME, |
850 | SNDRV_PCM_INFO_SYNC_START), | ||
851 | .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | | 850 | .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | |
852 | SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_S16_LE | | 851 | SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_S16_LE | |
853 | SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE | | 852 | SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE | |
@@ -868,12 +867,11 @@ static struct snd_pcm_hardware snd_cs4281_playback = | |||
868 | 867 | ||
869 | static struct snd_pcm_hardware snd_cs4281_capture = | 868 | static struct snd_pcm_hardware snd_cs4281_capture = |
870 | { | 869 | { |
871 | .info = (SNDRV_PCM_INFO_MMAP | | 870 | .info = SNDRV_PCM_INFO_MMAP | |
872 | SNDRV_PCM_INFO_INTERLEAVED | | 871 | SNDRV_PCM_INFO_INTERLEAVED | |
873 | SNDRV_PCM_INFO_MMAP_VALID | | 872 | SNDRV_PCM_INFO_MMAP_VALID | |
874 | SNDRV_PCM_INFO_PAUSE | | 873 | SNDRV_PCM_INFO_PAUSE | |
875 | SNDRV_PCM_INFO_RESUME | | 874 | SNDRV_PCM_INFO_RESUME, |
876 | SNDRV_PCM_INFO_SYNC_START), | ||
877 | .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | | 875 | .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | |
878 | SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_S16_LE | | 876 | SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_S16_LE | |
879 | SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE | | 877 | SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE | |
@@ -904,7 +902,6 @@ static int snd_cs4281_playback_open(struct snd_pcm_substream *substream) | |||
904 | dma->right_slot = 1; | 902 | dma->right_slot = 1; |
905 | runtime->private_data = dma; | 903 | runtime->private_data = dma; |
906 | runtime->hw = snd_cs4281_playback; | 904 | runtime->hw = snd_cs4281_playback; |
907 | snd_pcm_set_sync(substream); | ||
908 | /* should be detected from the AC'97 layer, but it seems | 905 | /* should be detected from the AC'97 layer, but it seems |
909 | that although CS4297A rev B reports 18-bit ADC resolution, | 906 | that although CS4297A rev B reports 18-bit ADC resolution, |
910 | samples are 20-bit */ | 907 | samples are 20-bit */ |
@@ -924,7 +921,6 @@ static int snd_cs4281_capture_open(struct snd_pcm_substream *substream) | |||
924 | dma->right_slot = 11; | 921 | dma->right_slot = 11; |
925 | runtime->private_data = dma; | 922 | runtime->private_data = dma; |
926 | runtime->hw = snd_cs4281_capture; | 923 | runtime->hw = snd_cs4281_capture; |
927 | snd_pcm_set_sync(substream); | ||
928 | /* should be detected from the AC'97 layer, but it seems | 924 | /* should be detected from the AC'97 layer, but it seems |
929 | that although CS4297A rev B reports 18-bit ADC resolution, | 925 | that although CS4297A rev B reports 18-bit ADC resolution, |
930 | samples are 20-bit */ | 926 | samples are 20-bit */ |
diff --git a/sound/pci/cs46xx/Makefile b/sound/pci/cs46xx/Makefile index d8b77b89aec4..67e811ec8539 100644 --- a/sound/pci/cs46xx/Makefile +++ b/sound/pci/cs46xx/Makefile | |||
@@ -1,12 +1,10 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-cs46xx-objs := cs46xx.o cs46xx_lib.o | 6 | snd-cs46xx-y := cs46xx.o cs46xx_lib.o |
7 | ifeq ($(CONFIG_SND_CS46XX_NEW_DSP),y) | 7 | snd-cs46xx-$(CONFIG_SND_CS46XX_NEW_DSP) += dsp_spos.o dsp_spos_scb_lib.o |
8 | snd-cs46xx-objs += dsp_spos.o dsp_spos_scb_lib.o | ||
9 | endif | ||
10 | 8 | ||
11 | # Toplevel Module Dependency | 9 | # Toplevel Module Dependency |
12 | obj-$(CONFIG_SND_CS46XX) += snd-cs46xx.o | 10 | obj-$(CONFIG_SND_CS46XX) += snd-cs46xx.o |
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c index 8b6cd144d101..2699cb6c2cd6 100644 --- a/sound/pci/cs46xx/cs46xx.c +++ b/sound/pci/cs46xx/cs46xx.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards | 2 | * The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -34,7 +34,7 @@ | |||
34 | #include <sound/cs46xx.h> | 34 | #include <sound/cs46xx.h> |
35 | #include <sound/initval.h> | 35 | #include <sound/initval.h> |
36 | 36 | ||
37 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 37 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
38 | MODULE_DESCRIPTION("Cirrus Logic Sound Fusion CS46XX"); | 38 | MODULE_DESCRIPTION("Cirrus Logic Sound Fusion CS46XX"); |
39 | MODULE_LICENSE("GPL"); | 39 | MODULE_LICENSE("GPL"); |
40 | MODULE_SUPPORTED_DEVICE("{{Cirrus Logic,Sound Fusion (CS4280)}," | 40 | MODULE_SUPPORTED_DEVICE("{{Cirrus Logic,Sound Fusion (CS4280)}," |
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 71d7aab9d869..2c7bfc9fef61 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Abramo Bagnara <abramo@alsa-project.org> | 3 | * Abramo Bagnara <abramo@alsa-project.org> |
4 | * Cirrus Logic, Inc. | 4 | * Cirrus Logic, Inc. |
5 | * Routines for control of Cirrus Logic CS461x chips | 5 | * Routines for control of Cirrus Logic CS461x chips |
@@ -1818,15 +1818,7 @@ static int snd_cs46xx_vol_iec958_put(struct snd_kcontrol *kcontrol, struct snd_c | |||
1818 | } | 1818 | } |
1819 | #endif | 1819 | #endif |
1820 | 1820 | ||
1821 | static int snd_mixer_boolean_info(struct snd_kcontrol *kcontrol, | 1821 | #define snd_mixer_boolean_info snd_ctl_boolean_mono_info |
1822 | struct snd_ctl_elem_info *uinfo) | ||
1823 | { | ||
1824 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1825 | uinfo->count = 1; | ||
1826 | uinfo->value.integer.min = 0; | ||
1827 | uinfo->value.integer.max = 1; | ||
1828 | return 0; | ||
1829 | } | ||
1830 | 1822 | ||
1831 | static int snd_cs46xx_iec958_get(struct snd_kcontrol *kcontrol, | 1823 | static int snd_cs46xx_iec958_get(struct snd_kcontrol *kcontrol, |
1832 | struct snd_ctl_elem_value *ucontrol) | 1824 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/cs46xx/cs46xx_lib.h b/sound/pci/cs46xx/cs46xx_lib.h index 20dcd72f06c1..018a7de56017 100644 --- a/sound/pci/cs46xx/cs46xx_lib.h +++ b/sound/pci/cs46xx/cs46xx_lib.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards | 2 | * The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/pci/cs46xx/dsp_spos.h b/sound/pci/cs46xx/dsp_spos.h index 0d246bca4184..f9e169d33c03 100644 --- a/sound/pci/cs46xx/dsp_spos.h +++ b/sound/pci/cs46xx/dsp_spos.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards | 2 | * The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c index 57e357de1500..eded4dfeba12 100644 --- a/sound/pci/cs46xx/dsp_spos_scb_lib.c +++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c | |||
@@ -1480,7 +1480,7 @@ void cs46xx_dsp_destroy_pcm_channel (struct snd_cs46xx * chip, | |||
1480 | if (!pcm_channel->src_scb->ref_count) { | 1480 | if (!pcm_channel->src_scb->ref_count) { |
1481 | cs46xx_dsp_remove_scb(chip,pcm_channel->src_scb); | 1481 | cs46xx_dsp_remove_scb(chip,pcm_channel->src_scb); |
1482 | 1482 | ||
1483 | snd_assert (pcm_channel->src_slot >= 0 && pcm_channel->src_slot <= DSP_MAX_SRC_NR, | 1483 | snd_assert (pcm_channel->src_slot >= 0 && pcm_channel->src_slot < DSP_MAX_SRC_NR, |
1484 | return ); | 1484 | return ); |
1485 | 1485 | ||
1486 | ins->src_scb_slots[pcm_channel->src_slot] = 0; | 1486 | ins->src_scb_slots[pcm_channel->src_slot] = 0; |
diff --git a/sound/pci/cs5535audio/Makefile b/sound/pci/cs5535audio/Makefile index ad947b4c04cc..bb3d57e6a3cb 100644 --- a/sound/pci/cs5535audio/Makefile +++ b/sound/pci/cs5535audio/Makefile | |||
@@ -2,11 +2,8 @@ | |||
2 | # Makefile for cs5535audio | 2 | # Makefile for cs5535audio |
3 | # | 3 | # |
4 | 4 | ||
5 | snd-cs5535audio-objs := cs5535audio.o cs5535audio_pcm.o | 5 | snd-cs5535audio-y := cs5535audio.o cs5535audio_pcm.o |
6 | 6 | snd-cs5535audio-$(CONFIG_PM) += cs5535audio_pm.o | |
7 | ifeq ($(CONFIG_PM),y) | ||
8 | snd-cs5535audio-objs += cs5535audio_pm.o | ||
9 | endif | ||
10 | 7 | ||
11 | # Toplevel Module Dependency | 8 | # Toplevel Module Dependency |
12 | obj-$(CONFIG_SND_CS5535AUDIO) += snd-cs5535audio.o | 9 | obj-$(CONFIG_SND_CS5535AUDIO) += snd-cs5535audio.o |
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index b8e75ef9c1e6..2b35889787be 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c | |||
@@ -206,7 +206,6 @@ static void process_bm1_irq(struct cs5535audio *cs5535au) | |||
206 | static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id) | 206 | static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id) |
207 | { | 207 | { |
208 | u16 acc_irq_stat; | 208 | u16 acc_irq_stat; |
209 | u8 bm_stat; | ||
210 | unsigned char count; | 209 | unsigned char count; |
211 | struct cs5535audio *cs5535au = dev_id; | 210 | struct cs5535audio *cs5535au = dev_id; |
212 | 211 | ||
@@ -217,7 +216,7 @@ static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id) | |||
217 | 216 | ||
218 | if (!acc_irq_stat) | 217 | if (!acc_irq_stat) |
219 | return IRQ_NONE; | 218 | return IRQ_NONE; |
220 | for (count = 0; count < 10; count++) { | 219 | for (count = 0; count < 4; count++) { |
221 | if (acc_irq_stat & (1 << count)) { | 220 | if (acc_irq_stat & (1 << count)) { |
222 | switch (count) { | 221 | switch (count) { |
223 | case IRQ_STS: | 222 | case IRQ_STS: |
@@ -232,26 +231,9 @@ static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id) | |||
232 | case BM1_IRQ_STS: | 231 | case BM1_IRQ_STS: |
233 | process_bm1_irq(cs5535au); | 232 | process_bm1_irq(cs5535au); |
234 | break; | 233 | break; |
235 | case BM2_IRQ_STS: | ||
236 | bm_stat = cs_readb(cs5535au, ACC_BM2_STATUS); | ||
237 | break; | ||
238 | case BM3_IRQ_STS: | ||
239 | bm_stat = cs_readb(cs5535au, ACC_BM3_STATUS); | ||
240 | break; | ||
241 | case BM4_IRQ_STS: | ||
242 | bm_stat = cs_readb(cs5535au, ACC_BM4_STATUS); | ||
243 | break; | ||
244 | case BM5_IRQ_STS: | ||
245 | bm_stat = cs_readb(cs5535au, ACC_BM5_STATUS); | ||
246 | break; | ||
247 | case BM6_IRQ_STS: | ||
248 | bm_stat = cs_readb(cs5535au, ACC_BM6_STATUS); | ||
249 | break; | ||
250 | case BM7_IRQ_STS: | ||
251 | bm_stat = cs_readb(cs5535au, ACC_BM7_STATUS); | ||
252 | break; | ||
253 | default: | 234 | default: |
254 | snd_printk(KERN_ERR "Unexpected irq src\n"); | 235 | snd_printk(KERN_ERR "Unexpected irq src: " |
236 | "0x%x\n", acc_irq_stat); | ||
255 | break; | 237 | break; |
256 | } | 238 | } |
257 | } | 239 | } |
diff --git a/sound/pci/cs5535audio/cs5535audio.h b/sound/pci/cs5535audio/cs5535audio.h index 4fd1f31a6cf9..66bae7664193 100644 --- a/sound/pci/cs5535audio/cs5535audio.h +++ b/sound/pci/cs5535audio/cs5535audio.h | |||
@@ -16,57 +16,28 @@ | |||
16 | #define ACC_IRQ_STATUS 0x12 | 16 | #define ACC_IRQ_STATUS 0x12 |
17 | #define ACC_BM0_CMD 0x20 | 17 | #define ACC_BM0_CMD 0x20 |
18 | #define ACC_BM1_CMD 0x28 | 18 | #define ACC_BM1_CMD 0x28 |
19 | #define ACC_BM2_CMD 0x30 | ||
20 | #define ACC_BM3_CMD 0x38 | ||
21 | #define ACC_BM4_CMD 0x40 | ||
22 | #define ACC_BM5_CMD 0x48 | ||
23 | #define ACC_BM6_CMD 0x50 | ||
24 | #define ACC_BM7_CMD 0x58 | ||
25 | #define ACC_BM0_PRD 0x24 | 19 | #define ACC_BM0_PRD 0x24 |
26 | #define ACC_BM1_PRD 0x2C | 20 | #define ACC_BM1_PRD 0x2C |
27 | #define ACC_BM2_PRD 0x34 | ||
28 | #define ACC_BM3_PRD 0x3C | ||
29 | #define ACC_BM4_PRD 0x44 | ||
30 | #define ACC_BM5_PRD 0x4C | ||
31 | #define ACC_BM6_PRD 0x54 | ||
32 | #define ACC_BM7_PRD 0x5C | ||
33 | #define ACC_BM0_STATUS 0x21 | 21 | #define ACC_BM0_STATUS 0x21 |
34 | #define ACC_BM1_STATUS 0x29 | 22 | #define ACC_BM1_STATUS 0x29 |
35 | #define ACC_BM2_STATUS 0x31 | ||
36 | #define ACC_BM3_STATUS 0x39 | ||
37 | #define ACC_BM4_STATUS 0x41 | ||
38 | #define ACC_BM5_STATUS 0x49 | ||
39 | #define ACC_BM6_STATUS 0x51 | ||
40 | #define ACC_BM7_STATUS 0x59 | ||
41 | #define ACC_BM0_PNTR 0x60 | 23 | #define ACC_BM0_PNTR 0x60 |
42 | #define ACC_BM1_PNTR 0x64 | 24 | #define ACC_BM1_PNTR 0x64 |
43 | #define ACC_BM2_PNTR 0x68 | 25 | |
44 | #define ACC_BM3_PNTR 0x6C | ||
45 | #define ACC_BM4_PNTR 0x70 | ||
46 | #define ACC_BM5_PNTR 0x74 | ||
47 | #define ACC_BM6_PNTR 0x78 | ||
48 | #define ACC_BM7_PNTR 0x7C | ||
49 | /* acc_codec bar0 reg bits */ | 26 | /* acc_codec bar0 reg bits */ |
50 | /* ACC_IRQ_STATUS */ | 27 | /* ACC_IRQ_STATUS */ |
51 | #define IRQ_STS 0 | 28 | #define IRQ_STS 0 |
52 | #define WU_IRQ_STS 1 | 29 | #define WU_IRQ_STS 1 |
53 | #define BM0_IRQ_STS 2 | 30 | #define BM0_IRQ_STS 2 |
54 | #define BM1_IRQ_STS 3 | 31 | #define BM1_IRQ_STS 3 |
55 | #define BM2_IRQ_STS 4 | ||
56 | #define BM3_IRQ_STS 5 | ||
57 | #define BM4_IRQ_STS 6 | ||
58 | #define BM5_IRQ_STS 7 | ||
59 | #define BM6_IRQ_STS 8 | ||
60 | #define BM7_IRQ_STS 9 | ||
61 | /* ACC_BMX_STATUS */ | 32 | /* ACC_BMX_STATUS */ |
62 | #define EOP (1<<0) | 33 | #define EOP (1<<0) |
63 | #define BM_EOP_ERR (1<<1) | 34 | #define BM_EOP_ERR (1<<1) |
64 | /* ACC_BMX_CTL */ | 35 | /* ACC_BMX_CTL */ |
65 | #define BM_CTL_EN 0x00000001 | 36 | #define BM_CTL_EN 0x01 |
66 | #define BM_CTL_PAUSE 0x00000011 | 37 | #define BM_CTL_PAUSE 0x03 |
67 | #define BM_CTL_DIS 0x00000000 | 38 | #define BM_CTL_DIS 0x00 |
68 | #define BM_CTL_BYTE_ORD_LE 0x00000000 | 39 | #define BM_CTL_BYTE_ORD_LE 0x00 |
69 | #define BM_CTL_BYTE_ORD_BE 0x00000100 | 40 | #define BM_CTL_BYTE_ORD_BE 0x04 |
70 | /* cs5535 specific ac97 codec register defines */ | 41 | /* cs5535 specific ac97 codec register defines */ |
71 | #define CMD_MASK 0xFF00FFFF | 42 | #define CMD_MASK 0xFF00FFFF |
72 | #define CMD_NEW 0x00010000 | 43 | #define CMD_NEW 0x00010000 |
@@ -106,7 +77,6 @@ struct cs5535audio_dma { | |||
106 | struct snd_pcm_substream *substream; | 77 | struct snd_pcm_substream *substream; |
107 | unsigned int buf_addr, buf_bytes; | 78 | unsigned int buf_addr, buf_bytes; |
108 | unsigned int period_bytes, periods; | 79 | unsigned int period_bytes, periods; |
109 | int suspended; | ||
110 | u32 saved_prd; | 80 | u32 saved_prd; |
111 | }; | 81 | }; |
112 | 82 | ||
diff --git a/sound/pci/cs5535audio/cs5535audio_pcm.c b/sound/pci/cs5535audio/cs5535audio_pcm.c index 5450a9e8f133..21df0634af32 100644 --- a/sound/pci/cs5535audio/cs5535audio_pcm.c +++ b/sound/pci/cs5535audio/cs5535audio_pcm.c | |||
@@ -43,7 +43,6 @@ static struct snd_pcm_hardware snd_cs5535audio_playback = | |||
43 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 43 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
44 | SNDRV_PCM_INFO_MMAP_VALID | | 44 | SNDRV_PCM_INFO_MMAP_VALID | |
45 | SNDRV_PCM_INFO_PAUSE | | 45 | SNDRV_PCM_INFO_PAUSE | |
46 | SNDRV_PCM_INFO_SYNC_START | | ||
47 | SNDRV_PCM_INFO_RESUME | 46 | SNDRV_PCM_INFO_RESUME |
48 | ), | 47 | ), |
49 | .formats = ( | 48 | .formats = ( |
@@ -71,8 +70,7 @@ static struct snd_pcm_hardware snd_cs5535audio_capture = | |||
71 | SNDRV_PCM_INFO_MMAP | | 70 | SNDRV_PCM_INFO_MMAP | |
72 | SNDRV_PCM_INFO_INTERLEAVED | | 71 | SNDRV_PCM_INFO_INTERLEAVED | |
73 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 72 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
74 | SNDRV_PCM_INFO_MMAP_VALID | | 73 | SNDRV_PCM_INFO_MMAP_VALID |
75 | SNDRV_PCM_INFO_SYNC_START | ||
76 | ), | 74 | ), |
77 | .formats = ( | 75 | .formats = ( |
78 | SNDRV_PCM_FMTBIT_S16_LE | 76 | SNDRV_PCM_FMTBIT_S16_LE |
@@ -102,7 +100,6 @@ static int snd_cs5535audio_playback_open(struct snd_pcm_substream *substream) | |||
102 | runtime->hw = snd_cs5535audio_playback; | 100 | runtime->hw = snd_cs5535audio_playback; |
103 | cs5535au->playback_substream = substream; | 101 | cs5535au->playback_substream = substream; |
104 | runtime->private_data = &(cs5535au->dmas[CS5535AUDIO_DMA_PLAYBACK]); | 102 | runtime->private_data = &(cs5535au->dmas[CS5535AUDIO_DMA_PLAYBACK]); |
105 | snd_pcm_set_sync(substream); | ||
106 | if ((err = snd_pcm_hw_constraint_integer(runtime, | 103 | if ((err = snd_pcm_hw_constraint_integer(runtime, |
107 | SNDRV_PCM_HW_PARAM_PERIODS)) < 0) | 104 | SNDRV_PCM_HW_PARAM_PERIODS)) < 0) |
108 | return err; | 105 | return err; |
@@ -164,6 +161,7 @@ static int cs5535audio_build_dma_packets(struct cs5535audio *cs5535au, | |||
164 | jmpprd_addr = cpu_to_le32(lastdesc->addr + | 161 | jmpprd_addr = cpu_to_le32(lastdesc->addr + |
165 | (sizeof(struct cs5535audio_dma_desc)*periods)); | 162 | (sizeof(struct cs5535audio_dma_desc)*periods)); |
166 | 163 | ||
164 | dma->substream = substream; | ||
167 | dma->period_bytes = period_bytes; | 165 | dma->period_bytes = period_bytes; |
168 | dma->periods = periods; | 166 | dma->periods = periods; |
169 | spin_lock_irq(&cs5535au->reg_lock); | 167 | spin_lock_irq(&cs5535au->reg_lock); |
@@ -241,6 +239,7 @@ static void cs5535audio_clear_dma_packets(struct cs5535audio *cs5535au, | |||
241 | { | 239 | { |
242 | snd_dma_free_pages(&dma->desc_buf); | 240 | snd_dma_free_pages(&dma->desc_buf); |
243 | dma->desc_buf.area = NULL; | 241 | dma->desc_buf.area = NULL; |
242 | dma->substream = NULL; | ||
244 | } | 243 | } |
245 | 244 | ||
246 | static int snd_cs5535audio_hw_params(struct snd_pcm_substream *substream, | 245 | static int snd_cs5535audio_hw_params(struct snd_pcm_substream *substream, |
@@ -298,14 +297,12 @@ static int snd_cs5535audio_trigger(struct snd_pcm_substream *substream, int cmd) | |||
298 | break; | 297 | break; |
299 | case SNDRV_PCM_TRIGGER_RESUME: | 298 | case SNDRV_PCM_TRIGGER_RESUME: |
300 | dma->ops->enable_dma(cs5535au); | 299 | dma->ops->enable_dma(cs5535au); |
301 | dma->suspended = 0; | ||
302 | break; | 300 | break; |
303 | case SNDRV_PCM_TRIGGER_STOP: | 301 | case SNDRV_PCM_TRIGGER_STOP: |
304 | dma->ops->disable_dma(cs5535au); | 302 | dma->ops->disable_dma(cs5535au); |
305 | break; | 303 | break; |
306 | case SNDRV_PCM_TRIGGER_SUSPEND: | 304 | case SNDRV_PCM_TRIGGER_SUSPEND: |
307 | dma->ops->disable_dma(cs5535au); | 305 | dma->ops->disable_dma(cs5535au); |
308 | dma->suspended = 1; | ||
309 | break; | 306 | break; |
310 | default: | 307 | default: |
311 | snd_printk(KERN_ERR "unhandled trigger\n"); | 308 | snd_printk(KERN_ERR "unhandled trigger\n"); |
@@ -348,7 +345,6 @@ static int snd_cs5535audio_capture_open(struct snd_pcm_substream *substream) | |||
348 | runtime->hw = snd_cs5535audio_capture; | 345 | runtime->hw = snd_cs5535audio_capture; |
349 | cs5535au->capture_substream = substream; | 346 | cs5535au->capture_substream = substream; |
350 | runtime->private_data = &(cs5535au->dmas[CS5535AUDIO_DMA_CAPTURE]); | 347 | runtime->private_data = &(cs5535au->dmas[CS5535AUDIO_DMA_CAPTURE]); |
351 | snd_pcm_set_sync(substream); | ||
352 | if ((err = snd_pcm_hw_constraint_integer(runtime, | 348 | if ((err = snd_pcm_hw_constraint_integer(runtime, |
353 | SNDRV_PCM_HW_PARAM_PERIODS)) < 0) | 349 | SNDRV_PCM_HW_PARAM_PERIODS)) < 0) |
354 | return err; | 350 | return err; |
diff --git a/sound/pci/cs5535audio/cs5535audio_pm.c b/sound/pci/cs5535audio/cs5535audio_pm.c index 3e4d198a4502..838708f6d45e 100644 --- a/sound/pci/cs5535audio/cs5535audio_pm.c +++ b/sound/pci/cs5535audio/cs5535audio_pm.c | |||
@@ -64,18 +64,21 @@ int snd_cs5535audio_suspend(struct pci_dev *pci, pm_message_t state) | |||
64 | int i; | 64 | int i; |
65 | 65 | ||
66 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 66 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
67 | snd_pcm_suspend_all(cs5535au->pcm); | ||
68 | snd_ac97_suspend(cs5535au->ac97); | ||
67 | for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) { | 69 | for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) { |
68 | struct cs5535audio_dma *dma = &cs5535au->dmas[i]; | 70 | struct cs5535audio_dma *dma = &cs5535au->dmas[i]; |
69 | if (dma && dma->substream && !dma->suspended) | 71 | if (dma && dma->substream) |
70 | dma->saved_prd = dma->ops->read_prd(cs5535au); | 72 | dma->saved_prd = dma->ops->read_prd(cs5535au); |
71 | } | 73 | } |
72 | snd_pcm_suspend_all(cs5535au->pcm); | ||
73 | snd_ac97_suspend(cs5535au->ac97); | ||
74 | /* save important regs, then disable aclink in hw */ | 74 | /* save important regs, then disable aclink in hw */ |
75 | snd_cs5535audio_stop_hardware(cs5535au); | 75 | snd_cs5535audio_stop_hardware(cs5535au); |
76 | 76 | ||
77 | if (pci_save_state(pci)) { | ||
78 | printk(KERN_ERR "cs5535audio: pci_save_state failed!\n"); | ||
79 | return -EIO; | ||
80 | } | ||
77 | pci_disable_device(pci); | 81 | pci_disable_device(pci); |
78 | pci_save_state(pci); | ||
79 | pci_set_power_state(pci, pci_choose_state(pci, state)); | 82 | pci_set_power_state(pci, pci_choose_state(pci, state)); |
80 | return 0; | 83 | return 0; |
81 | } | 84 | } |
@@ -89,7 +92,12 @@ int snd_cs5535audio_resume(struct pci_dev *pci) | |||
89 | int i; | 92 | int i; |
90 | 93 | ||
91 | pci_set_power_state(pci, PCI_D0); | 94 | pci_set_power_state(pci, PCI_D0); |
92 | pci_restore_state(pci); | 95 | if (pci_restore_state(pci) < 0) { |
96 | printk(KERN_ERR "cs5535audio: pci_restore_state failed, " | ||
97 | "disabling device\n"); | ||
98 | snd_card_disconnect(card); | ||
99 | return -EIO; | ||
100 | } | ||
93 | if (pci_enable_device(pci) < 0) { | 101 | if (pci_enable_device(pci) < 0) { |
94 | printk(KERN_ERR "cs5535audio: pci_enable_device failed, " | 102 | printk(KERN_ERR "cs5535audio: pci_enable_device failed, " |
95 | "disabling device\n"); | 103 | "disabling device\n"); |
@@ -112,17 +120,17 @@ int snd_cs5535audio_resume(struct pci_dev *pci) | |||
112 | if (!timeout) | 120 | if (!timeout) |
113 | snd_printk(KERN_ERR "Failure getting AC Link ready\n"); | 121 | snd_printk(KERN_ERR "Failure getting AC Link ready\n"); |
114 | 122 | ||
115 | /* we depend on ac97 to perform the codec power up */ | ||
116 | snd_ac97_resume(cs5535au->ac97); | ||
117 | /* set up rate regs, dma. actual initiation is done in trig */ | 123 | /* set up rate regs, dma. actual initiation is done in trig */ |
118 | for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) { | 124 | for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) { |
119 | struct cs5535audio_dma *dma = &cs5535au->dmas[i]; | 125 | struct cs5535audio_dma *dma = &cs5535au->dmas[i]; |
120 | if (dma && dma->substream && dma->suspended) { | 126 | if (dma && dma->substream) { |
121 | dma->substream->ops->prepare(dma->substream); | 127 | dma->substream->ops->prepare(dma->substream); |
122 | dma->ops->setup_prd(cs5535au, dma->saved_prd); | 128 | dma->ops->setup_prd(cs5535au, dma->saved_prd); |
123 | } | 129 | } |
124 | } | 130 | } |
125 | 131 | ||
132 | /* we depend on ac97 to perform the codec power up */ | ||
133 | snd_ac97_resume(cs5535au->ac97); | ||
126 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 134 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
127 | 135 | ||
128 | return 0; | 136 | return 0; |
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index f27b6a733b96..499ee1a5319d 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c | |||
@@ -1595,15 +1595,7 @@ static struct snd_kcontrol_new snd_echo_clock_source_switch __devinitdata = { | |||
1595 | #ifdef ECHOCARD_HAS_PHANTOM_POWER | 1595 | #ifdef ECHOCARD_HAS_PHANTOM_POWER |
1596 | 1596 | ||
1597 | /******************* Phantom power switch *******************/ | 1597 | /******************* Phantom power switch *******************/ |
1598 | static int snd_echo_phantom_power_info(struct snd_kcontrol *kcontrol, | 1598 | #define snd_echo_phantom_power_info snd_ctl_boolean_mono_info |
1599 | struct snd_ctl_elem_info *uinfo) | ||
1600 | { | ||
1601 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1602 | uinfo->count = 1; | ||
1603 | uinfo->value.integer.min = 0; | ||
1604 | uinfo->value.integer.max = 1; | ||
1605 | return 0; | ||
1606 | } | ||
1607 | 1599 | ||
1608 | static int snd_echo_phantom_power_get(struct snd_kcontrol *kcontrol, | 1600 | static int snd_echo_phantom_power_get(struct snd_kcontrol *kcontrol, |
1609 | struct snd_ctl_elem_value *ucontrol) | 1601 | struct snd_ctl_elem_value *ucontrol) |
@@ -1646,15 +1638,7 @@ static struct snd_kcontrol_new snd_echo_phantom_power_switch __devinitdata = { | |||
1646 | #ifdef ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE | 1638 | #ifdef ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE |
1647 | 1639 | ||
1648 | /******************* Digital input automute switch *******************/ | 1640 | /******************* Digital input automute switch *******************/ |
1649 | static int snd_echo_automute_info(struct snd_kcontrol *kcontrol, | 1641 | #define snd_echo_automute_info snd_ctl_boolean_mono_info |
1650 | struct snd_ctl_elem_info *uinfo) | ||
1651 | { | ||
1652 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1653 | uinfo->count = 1; | ||
1654 | uinfo->value.integer.min = 0; | ||
1655 | uinfo->value.integer.max = 1; | ||
1656 | return 0; | ||
1657 | } | ||
1658 | 1642 | ||
1659 | static int snd_echo_automute_get(struct snd_kcontrol *kcontrol, | 1643 | static int snd_echo_automute_get(struct snd_kcontrol *kcontrol, |
1660 | struct snd_ctl_elem_value *ucontrol) | 1644 | struct snd_ctl_elem_value *ucontrol) |
@@ -1695,18 +1679,7 @@ static struct snd_kcontrol_new snd_echo_automute_switch __devinitdata = { | |||
1695 | 1679 | ||
1696 | 1680 | ||
1697 | /******************* VU-meters switch *******************/ | 1681 | /******************* VU-meters switch *******************/ |
1698 | static int snd_echo_vumeters_switch_info(struct snd_kcontrol *kcontrol, | 1682 | #define snd_echo_vumeters_switch_info snd_ctl_boolean_mono_info |
1699 | struct snd_ctl_elem_info *uinfo) | ||
1700 | { | ||
1701 | struct echoaudio *chip; | ||
1702 | |||
1703 | chip = snd_kcontrol_chip(kcontrol); | ||
1704 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1705 | uinfo->count = 1; | ||
1706 | uinfo->value.integer.min = 0; | ||
1707 | uinfo->value.integer.max = 1; | ||
1708 | return 0; | ||
1709 | } | ||
1710 | 1683 | ||
1711 | static int snd_echo_vumeters_switch_put(struct snd_kcontrol *kcontrol, | 1684 | static int snd_echo_vumeters_switch_put(struct snd_kcontrol *kcontrol, |
1712 | struct snd_ctl_elem_value *ucontrol) | 1685 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/echoaudio/echoaudio_dsp.c b/sound/pci/echoaudio/echoaudio_dsp.c index 42afa837d9b4..e6c100770392 100644 --- a/sound/pci/echoaudio/echoaudio_dsp.c +++ b/sound/pci/echoaudio/echoaudio_dsp.c | |||
@@ -43,11 +43,11 @@ static int wait_handshake(struct echoaudio *chip) | |||
43 | { | 43 | { |
44 | int i; | 44 | int i; |
45 | 45 | ||
46 | /* Wait up to 10ms for the handshake from the DSP */ | 46 | /* Wait up to 20ms for the handshake from the DSP */ |
47 | for (i = 0; i < HANDSHAKE_TIMEOUT; i++) { | 47 | for (i = 0; i < HANDSHAKE_TIMEOUT; i++) { |
48 | /* Look for the handshake value */ | 48 | /* Look for the handshake value */ |
49 | barrier(); | ||
49 | if (chip->comm_page->handshake) { | 50 | if (chip->comm_page->handshake) { |
50 | /*if (i) DE_ACT(("Handshake time: %d\n", i));*/ | ||
51 | return 0; | 51 | return 0; |
52 | } | 52 | } |
53 | udelay(1); | 53 | udelay(1); |
diff --git a/sound/pci/echoaudio/echoaudio_dsp.h b/sound/pci/echoaudio/echoaudio_dsp.h index e55ee00991ac..e352f3ae292c 100644 --- a/sound/pci/echoaudio/echoaudio_dsp.h +++ b/sound/pci/echoaudio/echoaudio_dsp.h | |||
@@ -642,18 +642,18 @@ struct comm_page { /* Base Length*/ | |||
642 | u32 flags; /* See Appendix A below 0x004 4 */ | 642 | u32 flags; /* See Appendix A below 0x004 4 */ |
643 | u32 unused; /* Unused entry 0x008 4 */ | 643 | u32 unused; /* Unused entry 0x008 4 */ |
644 | u32 sample_rate; /* Card sample rate in Hz 0x00c 4 */ | 644 | u32 sample_rate; /* Card sample rate in Hz 0x00c 4 */ |
645 | volatile u32 handshake; /* DSP command handshake 0x010 4 */ | 645 | u32 handshake; /* DSP command handshake 0x010 4 */ |
646 | u32 cmd_start; /* Chs. to start mask 0x014 4 */ | 646 | u32 cmd_start; /* Chs. to start mask 0x014 4 */ |
647 | u32 cmd_stop; /* Chs. to stop mask 0x018 4 */ | 647 | u32 cmd_stop; /* Chs. to stop mask 0x018 4 */ |
648 | u32 cmd_reset; /* Chs. to reset mask 0x01c 4 */ | 648 | u32 cmd_reset; /* Chs. to reset mask 0x01c 4 */ |
649 | u16 audio_format[DSP_MAXPIPES]; /* Chs. audio format 0x020 32*2 */ | 649 | u16 audio_format[DSP_MAXPIPES]; /* Chs. audio format 0x020 32*2 */ |
650 | struct sg_entry sglist_addr[DSP_MAXPIPES]; | 650 | struct sg_entry sglist_addr[DSP_MAXPIPES]; |
651 | /* Chs. Physical sglist addrs 0x060 32*8 */ | 651 | /* Chs. Physical sglist addrs 0x060 32*8 */ |
652 | volatile u32 position[DSP_MAXPIPES]; | 652 | u32 position[DSP_MAXPIPES]; |
653 | /* Positions for ea. ch. 0x160 32*4 */ | 653 | /* Positions for ea. ch. 0x160 32*4 */ |
654 | volatile s8 vu_meter[DSP_MAXPIPES]; | 654 | s8 vu_meter[DSP_MAXPIPES]; |
655 | /* VU meters 0x1e0 32*1 */ | 655 | /* VU meters 0x1e0 32*1 */ |
656 | volatile s8 peak_meter[DSP_MAXPIPES]; | 656 | s8 peak_meter[DSP_MAXPIPES]; |
657 | /* Peak meters 0x200 32*1 */ | 657 | /* Peak meters 0x200 32*1 */ |
658 | s8 line_out_level[DSP_MAXAUDIOOUTPUTS]; | 658 | s8 line_out_level[DSP_MAXAUDIOOUTPUTS]; |
659 | /* Output gain 0x220 16*1 */ | 659 | /* Output gain 0x220 16*1 */ |
@@ -665,7 +665,7 @@ struct comm_page { /* Base Length*/ | |||
665 | /* Gina/Darla play filters - obsolete 0x3c0 168*4 */ | 665 | /* Gina/Darla play filters - obsolete 0x3c0 168*4 */ |
666 | u32 rec_coeff[MAX_REC_TAPS]; | 666 | u32 rec_coeff[MAX_REC_TAPS]; |
667 | /* Gina/Darla record filters - obsolete 0x660 192*4 */ | 667 | /* Gina/Darla record filters - obsolete 0x660 192*4 */ |
668 | volatile u16 midi_input[MIDI_IN_BUFFER_SIZE]; | 668 | u16 midi_input[MIDI_IN_BUFFER_SIZE]; |
669 | /* MIDI input data transfer buffer 0x960 256*2 */ | 669 | /* MIDI input data transfer buffer 0x960 256*2 */ |
670 | u8 gd_clock_state; /* Chg Gina/Darla clock state 0xb60 1 */ | 670 | u8 gd_clock_state; /* Chg Gina/Darla clock state 0xb60 1 */ |
671 | u8 gd_spdif_status; /* Chg. Gina/Darla S/PDIF state 0xb61 1 */ | 671 | u8 gd_spdif_status; /* Chg. Gina/Darla S/PDIF state 0xb61 1 */ |
@@ -674,11 +674,10 @@ struct comm_page { /* Base Length*/ | |||
674 | u32 nominal_level_mask; /* -10 level enable mask 0xb64 4 */ | 674 | u32 nominal_level_mask; /* -10 level enable mask 0xb64 4 */ |
675 | u16 input_clock; /* Chg. Input clock state 0xb68 2 */ | 675 | u16 input_clock; /* Chg. Input clock state 0xb68 2 */ |
676 | u16 output_clock; /* Chg. Output clock state 0xb6a 2 */ | 676 | u16 output_clock; /* Chg. Output clock state 0xb6a 2 */ |
677 | volatile u32 status_clocks; | 677 | u32 status_clocks; /* Current Input clock state 0xb6c 4 */ |
678 | /* Current Input clock state 0xb6c 4 */ | ||
679 | u32 ext_box_status; /* External box status 0xb70 4 */ | 678 | u32 ext_box_status; /* External box status 0xb70 4 */ |
680 | u32 cmd_add_buffer; /* Pipes to add (obsolete) 0xb74 4 */ | 679 | u32 cmd_add_buffer; /* Pipes to add (obsolete) 0xb74 4 */ |
681 | volatile u32 midi_out_free_count; | 680 | u32 midi_out_free_count; |
682 | /* # of bytes free in MIDI output FIFO 0xb78 4 */ | 681 | /* # of bytes free in MIDI output FIFO 0xb78 4 */ |
683 | u32 unused2; /* Cyclic pipes 0xb7c 4 */ | 682 | u32 unused2; /* Cyclic pipes 0xb7c 4 */ |
684 | u32 control_register; | 683 | u32 control_register; |
diff --git a/sound/pci/emu10k1/Makefile b/sound/pci/emu10k1/Makefile index e521c38cef45..cf2d5636d8be 100644 --- a/sound/pci/emu10k1/Makefile +++ b/sound/pci/emu10k1/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-emu10k1-objs := emu10k1.o emu10k1_main.o \ | 6 | snd-emu10k1-objs := emu10k1.o emu10k1_main.o \ |
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 55caf341933a..9680caff90c8 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * The driver for the EMU10K1 (SB Live!) based soundcards | 2 | * The driver for the EMU10K1 (SB Live!) based soundcards |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk> | 5 | * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk> |
6 | * Added support for Audigy 2 Value. | 6 | * Added support for Audigy 2 Value. |
@@ -32,7 +32,7 @@ | |||
32 | #include <sound/emu10k1.h> | 32 | #include <sound/emu10k1.h> |
33 | #include <sound/initval.h> | 33 | #include <sound/initval.h> |
34 | 34 | ||
35 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 35 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
36 | MODULE_DESCRIPTION("EMU10K1"); | 36 | MODULE_DESCRIPTION("EMU10K1"); |
37 | MODULE_LICENSE("GPL"); | 37 | MODULE_LICENSE("GPL"); |
38 | MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB Live!/PCI512/E-mu APS}," | 38 | MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB Live!/PCI512/E-mu APS}," |
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 404ae1be0a4b..97c41d72a255 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Creative Labs, Inc. | 3 | * Creative Labs, Inc. |
4 | * Routines for control of EMU10K1 chips | 4 | * Routines for control of EMU10K1 chips |
5 | * | 5 | * |
@@ -31,6 +31,8 @@ | |||
31 | * | 31 | * |
32 | */ | 32 | */ |
33 | 33 | ||
34 | #include <linux/sched.h> | ||
35 | #include <linux/kthread.h> | ||
34 | #include <sound/driver.h> | 36 | #include <sound/driver.h> |
35 | #include <linux/delay.h> | 37 | #include <linux/delay.h> |
36 | #include <linux/init.h> | 38 | #include <linux/init.h> |
@@ -702,6 +704,65 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * file | |||
702 | return 0; | 704 | return 0; |
703 | } | 705 | } |
704 | 706 | ||
707 | int emu1010_firmware_thread(void *data) { | ||
708 | struct snd_emu10k1 * emu = data; | ||
709 | int tmp,tmp2; | ||
710 | int reg; | ||
711 | int err; | ||
712 | |||
713 | for (;;) { | ||
714 | /* Delay to allow Audio Dock to settle */ | ||
715 | msleep(1000); | ||
716 | if (kthread_should_stop()) | ||
717 | break; | ||
718 | snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp ); /* IRQ Status */ | ||
719 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ® ); /* OPTIONS: Which cards are attached to the EMU */ | ||
720 | if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) { | ||
721 | /* Audio Dock attached */ | ||
722 | /* Return to Audio Dock programming mode */ | ||
723 | snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n"); | ||
724 | snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK ); | ||
725 | if (emu->card_capabilities->emu1010 == 1) { | ||
726 | if ((err = snd_emu1010_load_firmware(emu, DOCK_FILENAME)) != 0) { | ||
727 | return err; | ||
728 | } | ||
729 | } else if (emu->card_capabilities->emu1010 == 2) { | ||
730 | if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) { | ||
731 | return err; | ||
732 | } | ||
733 | } else if (emu->card_capabilities->emu1010 == 3) { | ||
734 | if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) { | ||
735 | return err; | ||
736 | } | ||
737 | } | ||
738 | |||
739 | snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0 ); | ||
740 | snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, ® ); | ||
741 | snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_IRQ_STATUS=0x%x\n",reg); | ||
742 | /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ | ||
743 | snd_emu1010_fpga_read(emu, EMU_HANA_ID, ® ); | ||
744 | snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_ID=0x%x\n",reg); | ||
745 | if ((reg & 0x1f) != 0x15) { | ||
746 | /* FPGA failed to be programmed */ | ||
747 | snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware file failed, reg=0x%x\n", reg); | ||
748 | return 0; | ||
749 | return -ENODEV; | ||
750 | } | ||
751 | snd_printk(KERN_INFO "emu1010: Audio Dock Firmware loaded\n"); | ||
752 | snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp ); | ||
753 | snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2 ); | ||
754 | snd_printk("Audio Dock ver:%d.%d\n",tmp ,tmp2); | ||
755 | /* Sync clocking between 1010 and Dock */ | ||
756 | /* Allow DLL to settle */ | ||
757 | msleep(10); | ||
758 | /* Unmute all. Default is muted after a firmware load */ | ||
759 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); | ||
760 | break; | ||
761 | } | ||
762 | } | ||
763 | return 0; | ||
764 | } | ||
765 | |||
705 | /* | 766 | /* |
706 | * EMU-1010 - details found out from this driver, official MS Win drivers, | 767 | * EMU-1010 - details found out from this driver, official MS Win drivers, |
707 | * testing the card: | 768 | * testing the card: |
@@ -817,8 +878,16 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) | |||
817 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ® ); | 878 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ® ); |
818 | snd_printk(KERN_INFO "emu1010: Card options=0x%x\n",reg); | 879 | snd_printk(KERN_INFO "emu1010: Card options=0x%x\n",reg); |
819 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTICAL_TYPE, &tmp ); | 880 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTICAL_TYPE, &tmp ); |
820 | /* ADAT input. */ | 881 | /* Optical -> ADAT I/O */ |
821 | snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x01 ); | 882 | /* 0 : SPDIF |
883 | * 1 : ADAT | ||
884 | */ | ||
885 | emu->emu1010.optical_in = 1; /* IN_ADAT */ | ||
886 | emu->emu1010.optical_out = 1; /* IN_ADAT */ | ||
887 | tmp = 0; | ||
888 | tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : 0) | | ||
889 | (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : 0); | ||
890 | snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp ); | ||
822 | snd_emu1010_fpga_read(emu, EMU_HANA_ADC_PADS, &tmp ); | 891 | snd_emu1010_fpga_read(emu, EMU_HANA_ADC_PADS, &tmp ); |
823 | /* Set no attenuation on Audio Dock pads. */ | 892 | /* Set no attenuation on Audio Dock pads. */ |
824 | snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, 0x00 ); | 893 | snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, 0x00 ); |
@@ -1004,49 +1073,12 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) | |||
1004 | snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp ); | 1073 | snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp ); |
1005 | snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10 ); /* SPDIF Format spdif (or 0x11 for aes/ebu) */ | 1074 | snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10 ); /* SPDIF Format spdif (or 0x11 for aes/ebu) */ |
1006 | 1075 | ||
1007 | /* Delay to allow Audio Dock to settle */ | 1076 | /* Start Micro/Audio Dock firmware loader thread */ |
1008 | msleep(100); | 1077 | emu->emu1010.firmware_thread = kthread_create(&emu1010_firmware_thread, |
1009 | snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp ); /* IRQ Status */ | 1078 | emu, |
1010 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ® ); /* OPTIONS: Which cards are attached to the EMU */ | 1079 | "emu1010_firmware"); |
1011 | /* FIXME: The loading of this should be able to happen any time, | 1080 | wake_up_process(emu->emu1010.firmware_thread); |
1012 | * as the user can plug/unplug it at any time | ||
1013 | */ | ||
1014 | if (reg & (EMU_HANA_OPTION_DOCK_ONLINE | EMU_HANA_OPTION_DOCK_OFFLINE) ) { | ||
1015 | /* Audio Dock attached */ | ||
1016 | /* Return to Audio Dock programming mode */ | ||
1017 | snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n"); | ||
1018 | snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK ); | ||
1019 | if (emu->card_capabilities->emu1010 == 1) { | ||
1020 | if ((err = snd_emu1010_load_firmware(emu, DOCK_FILENAME)) != 0) { | ||
1021 | return err; | ||
1022 | } | ||
1023 | } else if (emu->card_capabilities->emu1010 == 2) { | ||
1024 | if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) { | ||
1025 | return err; | ||
1026 | } | ||
1027 | } else if (emu->card_capabilities->emu1010 == 3) { | ||
1028 | if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) { | ||
1029 | return err; | ||
1030 | } | ||
1031 | } | ||
1032 | 1081 | ||
1033 | snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0 ); | ||
1034 | snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, ® ); | ||
1035 | snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_IRQ_STATUS=0x%x\n",reg); | ||
1036 | /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ | ||
1037 | snd_emu1010_fpga_read(emu, EMU_HANA_ID, ® ); | ||
1038 | snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_ID=0x%x\n",reg); | ||
1039 | if ((reg & 0x3f) != 0x15) { | ||
1040 | /* FPGA failed to be programmed */ | ||
1041 | snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware file failed, reg=0x%x\n", reg); | ||
1042 | return 0; | ||
1043 | return -ENODEV; | ||
1044 | } | ||
1045 | snd_printk(KERN_INFO "emu1010: Audio Dock Firmware loaded\n"); | ||
1046 | snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp ); | ||
1047 | snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2 ); | ||
1048 | snd_printk("Audio Dock ver:%d.%d\n",tmp ,tmp2); | ||
1049 | } | ||
1050 | #if 0 | 1082 | #if 0 |
1051 | snd_emu1010_fpga_link_dst_src_write(emu, | 1083 | snd_emu1010_fpga_link_dst_src_write(emu, |
1052 | EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32B + 2); /* ALICE2 bus 0xa2 */ | 1084 | EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32B + 2); /* ALICE2 bus 0xa2 */ |
@@ -1132,7 +1164,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) | |||
1132 | emu->emu1010.output_source[23] = 28; | 1164 | emu->emu1010.output_source[23] = 28; |
1133 | 1165 | ||
1134 | /* TEMP: Select SPDIF in/out */ | 1166 | /* TEMP: Select SPDIF in/out */ |
1135 | snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x0); /* Output spdif */ | 1167 | //snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x0); /* Output spdif */ |
1136 | 1168 | ||
1137 | /* TEMP: Select 48kHz SPDIF out */ | 1169 | /* TEMP: Select 48kHz SPDIF out */ |
1138 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x0); /* Mute all */ | 1170 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x0); /* Mute all */ |
@@ -1173,6 +1205,7 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu) | |||
1173 | if (emu->card_capabilities->emu1010) { | 1205 | if (emu->card_capabilities->emu1010) { |
1174 | /* Disable 48Volt power to Audio Dock */ | 1206 | /* Disable 48Volt power to Audio Dock */ |
1175 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0 ); | 1207 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0 ); |
1208 | kthread_stop(emu->emu1010.firmware_thread); | ||
1176 | } | 1209 | } |
1177 | if (emu->memhdr) | 1210 | if (emu->memhdr) |
1178 | snd_util_memhdr_free(emu->memhdr); | 1211 | snd_util_memhdr_free(emu->memhdr); |
@@ -1722,8 +1755,9 @@ int __devinit snd_emu10k1_create(struct snd_card *card, | |||
1722 | goto error; | 1755 | goto error; |
1723 | } | 1756 | } |
1724 | 1757 | ||
1725 | emu->page_ptr_table = (void **)vmalloc(emu->max_cache_pages * sizeof(void*)); | 1758 | emu->page_ptr_table = vmalloc(emu->max_cache_pages * sizeof(void *)); |
1726 | emu->page_addr_table = (unsigned long*)vmalloc(emu->max_cache_pages * sizeof(unsigned long)); | 1759 | emu->page_addr_table = vmalloc(emu->max_cache_pages * |
1760 | sizeof(unsigned long)); | ||
1727 | if (emu->page_ptr_table == NULL || emu->page_addr_table == NULL) { | 1761 | if (emu->page_ptr_table == NULL || emu->page_addr_table == NULL) { |
1728 | err = -ENOMEM; | 1762 | err = -ENOMEM; |
1729 | goto error; | 1763 | goto error; |
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index e4af7a9b808c..1ec7ebaff9e9 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c | |||
@@ -1062,14 +1062,7 @@ static int __devinit snd_emu10k1x_proc_init(struct emu10k1x * emu) | |||
1062 | return 0; | 1062 | return 0; |
1063 | } | 1063 | } |
1064 | 1064 | ||
1065 | static int snd_emu10k1x_shared_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1065 | #define snd_emu10k1x_shared_spdif_info snd_ctl_boolean_mono_info |
1066 | { | ||
1067 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1068 | uinfo->count = 1; | ||
1069 | uinfo->value.integer.min = 0; | ||
1070 | uinfo->value.integer.max = 1; | ||
1071 | return 0; | ||
1072 | } | ||
1073 | 1066 | ||
1074 | static int snd_emu10k1x_shared_spdif_get(struct snd_kcontrol *kcontrol, | 1067 | static int snd_emu10k1x_shared_spdif_get(struct snd_kcontrol *kcontrol, |
1075 | struct snd_ctl_elem_value *ucontrol) | 1068 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index 7206c0fa06f2..9bf1cd592199 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Creative Labs, Inc. | 3 | * Creative Labs, Inc. |
4 | * Routines for effect processor FX8010 | 4 | * Routines for effect processor FX8010 |
5 | * | 5 | * |
@@ -642,10 +642,8 @@ snd_emu10k1_look_for_ctl(struct snd_emu10k1 *emu, struct snd_ctl_elem_id *id) | |||
642 | { | 642 | { |
643 | struct snd_emu10k1_fx8010_ctl *ctl; | 643 | struct snd_emu10k1_fx8010_ctl *ctl; |
644 | struct snd_kcontrol *kcontrol; | 644 | struct snd_kcontrol *kcontrol; |
645 | struct list_head *list; | 645 | |
646 | 646 | list_for_each_entry(ctl, &emu->fx8010.gpr_ctl, list) { | |
647 | list_for_each(list, &emu->fx8010.gpr_ctl) { | ||
648 | ctl = emu10k1_gpr_ctl(list); | ||
649 | kcontrol = ctl->kcontrol; | 647 | kcontrol = ctl->kcontrol; |
650 | if (kcontrol->id.iface == id->iface && | 648 | if (kcontrol->id.iface == id->iface && |
651 | !strcmp(kcontrol->id.name, id->name) && | 649 | !strcmp(kcontrol->id.name, id->name) && |
@@ -895,14 +893,12 @@ static int snd_emu10k1_list_controls(struct snd_emu10k1 *emu, | |||
895 | struct snd_emu10k1_fx8010_control_gpr *gctl; | 893 | struct snd_emu10k1_fx8010_control_gpr *gctl; |
896 | struct snd_emu10k1_fx8010_ctl *ctl; | 894 | struct snd_emu10k1_fx8010_ctl *ctl; |
897 | struct snd_ctl_elem_id *id; | 895 | struct snd_ctl_elem_id *id; |
898 | struct list_head *list; | ||
899 | 896 | ||
900 | gctl = kmalloc(sizeof(*gctl), GFP_KERNEL); | 897 | gctl = kmalloc(sizeof(*gctl), GFP_KERNEL); |
901 | if (! gctl) | 898 | if (! gctl) |
902 | return -ENOMEM; | 899 | return -ENOMEM; |
903 | 900 | ||
904 | list_for_each(list, &emu->fx8010.gpr_ctl) { | 901 | list_for_each_entry(ctl, &emu->fx8010.gpr_ctl, list) { |
905 | ctl = emu10k1_gpr_ctl(list); | ||
906 | total++; | 902 | total++; |
907 | if (icode->gpr_list_controls && | 903 | if (icode->gpr_list_controls && |
908 | i < icode->gpr_list_control_count) { | 904 | i < icode->gpr_list_control_count) { |
@@ -1207,7 +1203,7 @@ static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) | |||
1207 | A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT)); | 1203 | A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT)); |
1208 | snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Front Playback Volume", gpr, 100); | 1204 | snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Front Playback Volume", gpr, 100); |
1209 | gpr += 2; | 1205 | gpr += 2; |
1210 | 1206 | ||
1211 | /* PCM Surround Playback (independent from stereo mix) */ | 1207 | /* PCM Surround Playback (independent from stereo mix) */ |
1212 | A_OP(icode, &ptr, iMAC0, A_GPR(playback+2), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_REAR)); | 1208 | A_OP(icode, &ptr, iMAC0, A_GPR(playback+2), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_REAR)); |
1213 | A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_REAR)); | 1209 | A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_REAR)); |
@@ -1267,8 +1263,16 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) | |||
1267 | 1263 | ||
1268 | /* emu1212 DSP 0 and DSP 1 Capture */ | 1264 | /* emu1212 DSP 0 and DSP 1 Capture */ |
1269 | if (emu->card_capabilities->emu1010) { | 1265 | if (emu->card_capabilities->emu1010) { |
1270 | A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_P16VIN(0x0)); | 1266 | if (emu->card_capabilities->ca0108_chip) { |
1271 | A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_P16VIN(0x1)); | 1267 | /* Note:JCD:No longer bit shift lower 16bits to upper 16bits of 32bit value. */ |
1268 | A_OP(icode, &ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A3_EMU32IN(0x0), A_C_00000001); | ||
1269 | A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_GPR(tmp)); | ||
1270 | A_OP(icode, &ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A3_EMU32IN(0x1), A_C_00000001); | ||
1271 | A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr), A_GPR(tmp)); | ||
1272 | } else { | ||
1273 | A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_P16VIN(0x0)); | ||
1274 | A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_P16VIN(0x1)); | ||
1275 | } | ||
1272 | snd_emu10k1_init_stereo_control(&controls[nctl++], "EMU Capture Volume", gpr, 0); | 1276 | snd_emu10k1_init_stereo_control(&controls[nctl++], "EMU Capture Volume", gpr, 0); |
1273 | gpr += 2; | 1277 | gpr += 2; |
1274 | } | 1278 | } |
@@ -1516,7 +1520,11 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) | |||
1516 | /* EMU1010 Outputs from PCM Front, Rear, Center, LFE, Side */ | 1520 | /* EMU1010 Outputs from PCM Front, Rear, Center, LFE, Side */ |
1517 | snd_printk("EMU outputs on\n"); | 1521 | snd_printk("EMU outputs on\n"); |
1518 | for (z = 0; z < 8; z++) { | 1522 | for (z = 0; z < 8; z++) { |
1519 | A_OP(icode, &ptr, iACC3, A_EMU32OUTL(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000); | 1523 | if (emu->card_capabilities->ca0108_chip) { |
1524 | A_OP(icode, &ptr, iACC3, A3_EMU32OUT(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000); | ||
1525 | } else { | ||
1526 | A_OP(icode, &ptr, iACC3, A_EMU32OUTL(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000); | ||
1527 | } | ||
1520 | } | 1528 | } |
1521 | } | 1529 | } |
1522 | 1530 | ||
@@ -1557,106 +1565,116 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) | |||
1557 | #endif | 1565 | #endif |
1558 | 1566 | ||
1559 | if (emu->card_capabilities->emu1010) { | 1567 | if (emu->card_capabilities->emu1010) { |
1560 | snd_printk("EMU inputs on\n"); | 1568 | if (emu->card_capabilities->ca0108_chip) { |
1561 | /* Capture 16 (originally 8) channels of S32_LE sound */ | 1569 | snd_printk("EMU2 inputs on\n"); |
1562 | 1570 | for (z = 0; z < 0x10; z++) { | |
1563 | /* printk("emufx.c: gpr=0x%x, tmp=0x%x\n",gpr, tmp); */ | 1571 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, |
1564 | /* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */ | 1572 | bit_shifter16, |
1565 | /* A_P16VIN(0) is delayed by one sample, | 1573 | A3_EMU32IN(z), |
1566 | * so all other A_P16VIN channels will need to also be delayed | 1574 | A_FXBUS2(z*2) ); |
1567 | */ | 1575 | } |
1568 | /* Left ADC in. 1 of 2 */ | 1576 | } else { |
1569 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_P16VIN(0x0), A_FXBUS2(0) ); | 1577 | snd_printk("EMU inputs on\n"); |
1570 | /* Right ADC in 1 of 2 */ | 1578 | /* Capture 16 (originally 8) channels of S32_LE sound */ |
1571 | gpr_map[gpr++] = 0x00000000; | 1579 | |
1572 | /* Delaying by one sample: instead of copying the input | 1580 | /* printk("emufx.c: gpr=0x%x, tmp=0x%x\n",gpr, tmp); */ |
1573 | * value A_P16VIN to output A_FXBUS2 as in the first channel, | 1581 | /* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */ |
1574 | * we use an auxiliary register, delaying the value by one | 1582 | /* A_P16VIN(0) is delayed by one sample, |
1575 | * sample | 1583 | * so all other A_P16VIN channels will need to also be delayed |
1576 | */ | 1584 | */ |
1577 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(2) ); | 1585 | /* Left ADC in. 1 of 2 */ |
1578 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x1), A_C_00000000, A_C_00000000); | 1586 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_P16VIN(0x0), A_FXBUS2(0) ); |
1579 | gpr_map[gpr++] = 0x00000000; | 1587 | /* Right ADC in 1 of 2 */ |
1580 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(4) ); | 1588 | gpr_map[gpr++] = 0x00000000; |
1581 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x2), A_C_00000000, A_C_00000000); | 1589 | /* Delaying by one sample: instead of copying the input |
1582 | gpr_map[gpr++] = 0x00000000; | 1590 | * value A_P16VIN to output A_FXBUS2 as in the first channel, |
1583 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(6) ); | 1591 | * we use an auxiliary register, delaying the value by one |
1584 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x3), A_C_00000000, A_C_00000000); | 1592 | * sample |
1585 | /* For 96kHz mode */ | 1593 | */ |
1586 | /* Left ADC in. 2 of 2 */ | 1594 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(2) ); |
1587 | gpr_map[gpr++] = 0x00000000; | 1595 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x1), A_C_00000000, A_C_00000000); |
1588 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0x8) ); | 1596 | gpr_map[gpr++] = 0x00000000; |
1589 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x4), A_C_00000000, A_C_00000000); | 1597 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(4) ); |
1590 | /* Right ADC in 2 of 2 */ | 1598 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x2), A_C_00000000, A_C_00000000); |
1591 | gpr_map[gpr++] = 0x00000000; | 1599 | gpr_map[gpr++] = 0x00000000; |
1592 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xa) ); | 1600 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(6) ); |
1593 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x5), A_C_00000000, A_C_00000000); | 1601 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x3), A_C_00000000, A_C_00000000); |
1594 | gpr_map[gpr++] = 0x00000000; | 1602 | /* For 96kHz mode */ |
1595 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xc) ); | 1603 | /* Left ADC in. 2 of 2 */ |
1596 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x6), A_C_00000000, A_C_00000000); | 1604 | gpr_map[gpr++] = 0x00000000; |
1597 | gpr_map[gpr++] = 0x00000000; | 1605 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0x8) ); |
1598 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xe) ); | 1606 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x4), A_C_00000000, A_C_00000000); |
1599 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x7), A_C_00000000, A_C_00000000); | 1607 | /* Right ADC in 2 of 2 */ |
1600 | /* Pavel Hofman - we still have voices, A_FXBUS2s, and | 1608 | gpr_map[gpr++] = 0x00000000; |
1601 | * A_P16VINs available - | 1609 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xa) ); |
1602 | * let's add 8 more capture channels - total of 16 | 1610 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x5), A_C_00000000, A_C_00000000); |
1603 | */ | 1611 | gpr_map[gpr++] = 0x00000000; |
1604 | gpr_map[gpr++] = 0x00000000; | 1612 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xc) ); |
1605 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, | 1613 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x6), A_C_00000000, A_C_00000000); |
1606 | bit_shifter16, | 1614 | gpr_map[gpr++] = 0x00000000; |
1607 | A_GPR(gpr - 1), | 1615 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xe) ); |
1608 | A_FXBUS2(0x10)); | 1616 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x7), A_C_00000000, A_C_00000000); |
1609 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x8), | 1617 | /* Pavel Hofman - we still have voices, A_FXBUS2s, and |
1610 | A_C_00000000, A_C_00000000); | 1618 | * A_P16VINs available - |
1611 | gpr_map[gpr++] = 0x00000000; | 1619 | * let's add 8 more capture channels - total of 16 |
1612 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, | 1620 | */ |
1613 | bit_shifter16, | 1621 | gpr_map[gpr++] = 0x00000000; |
1614 | A_GPR(gpr - 1), | 1622 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, |
1615 | A_FXBUS2(0x12)); | 1623 | bit_shifter16, |
1616 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x9), | 1624 | A_GPR(gpr - 1), |
1617 | A_C_00000000, A_C_00000000); | 1625 | A_FXBUS2(0x10)); |
1618 | gpr_map[gpr++] = 0x00000000; | 1626 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x8), |
1619 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, | 1627 | A_C_00000000, A_C_00000000); |
1620 | bit_shifter16, | 1628 | gpr_map[gpr++] = 0x00000000; |
1621 | A_GPR(gpr - 1), | 1629 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, |
1622 | A_FXBUS2(0x14)); | 1630 | bit_shifter16, |
1623 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xa), | 1631 | A_GPR(gpr - 1), |
1624 | A_C_00000000, A_C_00000000); | 1632 | A_FXBUS2(0x12)); |
1625 | gpr_map[gpr++] = 0x00000000; | 1633 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x9), |
1626 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, | 1634 | A_C_00000000, A_C_00000000); |
1627 | bit_shifter16, | 1635 | gpr_map[gpr++] = 0x00000000; |
1628 | A_GPR(gpr - 1), | 1636 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, |
1629 | A_FXBUS2(0x16)); | 1637 | bit_shifter16, |
1630 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xb), | 1638 | A_GPR(gpr - 1), |
1631 | A_C_00000000, A_C_00000000); | 1639 | A_FXBUS2(0x14)); |
1632 | gpr_map[gpr++] = 0x00000000; | 1640 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xa), |
1633 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, | 1641 | A_C_00000000, A_C_00000000); |
1634 | bit_shifter16, | 1642 | gpr_map[gpr++] = 0x00000000; |
1635 | A_GPR(gpr - 1), | 1643 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, |
1636 | A_FXBUS2(0x18)); | 1644 | bit_shifter16, |
1637 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xc), | 1645 | A_GPR(gpr - 1), |
1638 | A_C_00000000, A_C_00000000); | 1646 | A_FXBUS2(0x16)); |
1639 | gpr_map[gpr++] = 0x00000000; | 1647 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xb), |
1640 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, | 1648 | A_C_00000000, A_C_00000000); |
1641 | bit_shifter16, | 1649 | gpr_map[gpr++] = 0x00000000; |
1642 | A_GPR(gpr - 1), | 1650 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, |
1643 | A_FXBUS2(0x1a)); | 1651 | bit_shifter16, |
1644 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xd), | 1652 | A_GPR(gpr - 1), |
1645 | A_C_00000000, A_C_00000000); | 1653 | A_FXBUS2(0x18)); |
1646 | gpr_map[gpr++] = 0x00000000; | 1654 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xc), |
1647 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, | 1655 | A_C_00000000, A_C_00000000); |
1648 | bit_shifter16, | 1656 | gpr_map[gpr++] = 0x00000000; |
1649 | A_GPR(gpr - 1), | 1657 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, |
1650 | A_FXBUS2(0x1c)); | 1658 | bit_shifter16, |
1651 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xe), | 1659 | A_GPR(gpr - 1), |
1652 | A_C_00000000, A_C_00000000); | 1660 | A_FXBUS2(0x1a)); |
1653 | gpr_map[gpr++] = 0x00000000; | 1661 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xd), |
1654 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, | 1662 | A_C_00000000, A_C_00000000); |
1655 | bit_shifter16, | 1663 | gpr_map[gpr++] = 0x00000000; |
1656 | A_GPR(gpr - 1), | 1664 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, |
1657 | A_FXBUS2(0x1e)); | 1665 | bit_shifter16, |
1658 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xf), | 1666 | A_GPR(gpr - 1), |
1659 | A_C_00000000, A_C_00000000); | 1667 | A_FXBUS2(0x1c)); |
1668 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xe), | ||
1669 | A_C_00000000, A_C_00000000); | ||
1670 | gpr_map[gpr++] = 0x00000000; | ||
1671 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, | ||
1672 | bit_shifter16, | ||
1673 | A_GPR(gpr - 1), | ||
1674 | A_FXBUS2(0x1e)); | ||
1675 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xf), | ||
1676 | A_C_00000000, A_C_00000000); | ||
1677 | } | ||
1660 | 1678 | ||
1661 | #if 0 | 1679 | #if 0 |
1662 | for (z = 4; z < 8; z++) { | 1680 | for (z = 4; z < 8; z++) { |
@@ -2418,14 +2436,13 @@ static void copy_string(char *dst, char *src, char *null, int idx) | |||
2418 | strcpy(dst, src); | 2436 | strcpy(dst, src); |
2419 | } | 2437 | } |
2420 | 2438 | ||
2421 | static int snd_emu10k1_fx8010_info(struct snd_emu10k1 *emu, | 2439 | static void snd_emu10k1_fx8010_info(struct snd_emu10k1 *emu, |
2422 | struct snd_emu10k1_fx8010_info *info) | 2440 | struct snd_emu10k1_fx8010_info *info) |
2423 | { | 2441 | { |
2424 | char **fxbus, **extin, **extout; | 2442 | char **fxbus, **extin, **extout; |
2425 | unsigned short fxbus_mask, extin_mask, extout_mask; | 2443 | unsigned short fxbus_mask, extin_mask, extout_mask; |
2426 | int res; | 2444 | int res; |
2427 | 2445 | ||
2428 | memset(info, 0, sizeof(info)); | ||
2429 | info->internal_tram_size = emu->fx8010.itram_size; | 2446 | info->internal_tram_size = emu->fx8010.itram_size; |
2430 | info->external_tram_size = emu->fx8010.etram_pages.bytes / 2; | 2447 | info->external_tram_size = emu->fx8010.etram_pages.bytes / 2; |
2431 | fxbus = fxbuses; | 2448 | fxbus = fxbuses; |
@@ -2442,7 +2459,6 @@ static int snd_emu10k1_fx8010_info(struct snd_emu10k1 *emu, | |||
2442 | for (res = 16; res < 32; res++, extout++) | 2459 | for (res = 16; res < 32; res++, extout++) |
2443 | copy_string(info->extout_names[res], extout_mask & (1 << res) ? *extout : NULL, "Unused", res); | 2460 | copy_string(info->extout_names[res], extout_mask & (1 << res) ? *extout : NULL, "Unused", res); |
2444 | info->gpr_controls = emu->fx8010.gpr_count; | 2461 | info->gpr_controls = emu->fx8010.gpr_count; |
2445 | return 0; | ||
2446 | } | 2462 | } |
2447 | 2463 | ||
2448 | static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, unsigned int cmd, unsigned long arg) | 2464 | static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, unsigned int cmd, unsigned long arg) |
@@ -2463,10 +2479,7 @@ static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, un | |||
2463 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 2479 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
2464 | if (!info) | 2480 | if (!info) |
2465 | return -ENOMEM; | 2481 | return -ENOMEM; |
2466 | if ((res = snd_emu10k1_fx8010_info(emu, info)) < 0) { | 2482 | snd_emu10k1_fx8010_info(emu, info); |
2467 | kfree(info); | ||
2468 | return res; | ||
2469 | } | ||
2470 | if (copy_to_user(argp, info, sizeof(*info))) { | 2483 | if (copy_to_user(argp, info, sizeof(*info))) { |
2471 | kfree(info); | 2484 | kfree(info); |
2472 | return -EFAULT; | 2485 | return -EFAULT; |
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c index 7b2c1dcc5337..54a2034d8edd 100644 --- a/sound/pci/emu10k1/emumixer.c +++ b/sound/pci/emu10k1/emumixer.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz>, | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz>, |
3 | * Takashi Iwai <tiwai@suse.de> | 3 | * Takashi Iwai <tiwai@suse.de> |
4 | * Creative Labs, Inc. | 4 | * Creative Labs, Inc. |
5 | * Routines for control of EMU10K1 chips / mixer routines | 5 | * Routines for control of EMU10K1 chips / mixer routines |
@@ -400,15 +400,7 @@ static struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] __devinitdata = { | |||
400 | 400 | ||
401 | 401 | ||
402 | 402 | ||
403 | 403 | #define snd_emu1010_adc_pads_info snd_ctl_boolean_mono_info | |
404 | static int snd_emu1010_adc_pads_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | ||
405 | { | ||
406 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
407 | uinfo->count = 1; | ||
408 | uinfo->value.integer.min = 0; | ||
409 | uinfo->value.integer.max = 1; | ||
410 | return 0; | ||
411 | } | ||
412 | 404 | ||
413 | static int snd_emu1010_adc_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 405 | static int snd_emu1010_adc_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
414 | { | 406 | { |
@@ -456,14 +448,7 @@ static struct snd_kcontrol_new snd_emu1010_adc_pads[] __devinitdata = { | |||
456 | EMU1010_ADC_PADS("ADC1 14dB PAD 0202 Capture Switch", EMU_HANA_0202_ADC_PAD1), | 448 | EMU1010_ADC_PADS("ADC1 14dB PAD 0202 Capture Switch", EMU_HANA_0202_ADC_PAD1), |
457 | }; | 449 | }; |
458 | 450 | ||
459 | static int snd_emu1010_dac_pads_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 451 | #define snd_emu1010_dac_pads_info snd_ctl_boolean_mono_info |
460 | { | ||
461 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
462 | uinfo->count = 1; | ||
463 | uinfo->value.integer.min = 0; | ||
464 | uinfo->value.integer.max = 1; | ||
465 | return 0; | ||
466 | } | ||
467 | 452 | ||
468 | static int snd_emu1010_dac_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 453 | static int snd_emu1010_dac_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
469 | { | 454 | { |
@@ -516,17 +501,19 @@ static struct snd_kcontrol_new snd_emu1010_dac_pads[] __devinitdata = { | |||
516 | static int snd_emu1010_internal_clock_info(struct snd_kcontrol *kcontrol, | 501 | static int snd_emu1010_internal_clock_info(struct snd_kcontrol *kcontrol, |
517 | struct snd_ctl_elem_info *uinfo) | 502 | struct snd_ctl_elem_info *uinfo) |
518 | { | 503 | { |
519 | static char *texts[2] = { | 504 | static char *texts[4] = { |
520 | "44100", "48000" | 505 | "44100", "48000", "SPDIF", "ADAT" |
521 | }; | 506 | }; |
522 | 507 | ||
523 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 508 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
524 | uinfo->count = 1; | 509 | uinfo->count = 1; |
525 | uinfo->value.enumerated.items = 2; | 510 | uinfo->value.enumerated.items = 4; |
526 | if (uinfo->value.enumerated.item > 1) | 511 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) |
527 | uinfo->value.enumerated.item = 1; | 512 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; |
528 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | 513 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); |
529 | return 0; | 514 | return 0; |
515 | |||
516 | |||
530 | } | 517 | } |
531 | 518 | ||
532 | static int snd_emu1010_internal_clock_get(struct snd_kcontrol *kcontrol, | 519 | static int snd_emu1010_internal_clock_get(struct snd_kcontrol *kcontrol, |
@@ -584,6 +571,44 @@ static int snd_emu1010_internal_clock_put(struct snd_kcontrol *kcontrol, | |||
584 | /* Unmute all */ | 571 | /* Unmute all */ |
585 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); | 572 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); |
586 | break; | 573 | break; |
574 | |||
575 | case 2: /* Take clock from S/PDIF IN */ | ||
576 | /* Mute all */ | ||
577 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE ); | ||
578 | /* Default fallback clock 48kHz */ | ||
579 | snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K ); | ||
580 | /* Word Clock source, sync to S/PDIF input */ | ||
581 | snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, | ||
582 | EMU_HANA_WCLOCK_HANA_SPDIF_IN | EMU_HANA_WCLOCK_1X ); | ||
583 | /* Set LEDs on Audio Dock */ | ||
584 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, | ||
585 | EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_LOCK ); | ||
586 | /* FIXME: We should set EMU_HANA_DOCK_LEDS_2_LOCK only when clock signal is present and valid */ | ||
587 | /* Allow DLL to settle */ | ||
588 | msleep(10); | ||
589 | /* Unmute all */ | ||
590 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); | ||
591 | break; | ||
592 | |||
593 | case 3: | ||
594 | /* Take clock from ADAT IN */ | ||
595 | /* Mute all */ | ||
596 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE ); | ||
597 | /* Default fallback clock 48kHz */ | ||
598 | snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K ); | ||
599 | /* Word Clock source, sync to ADAT input */ | ||
600 | snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, | ||
601 | EMU_HANA_WCLOCK_HANA_ADAT_IN | EMU_HANA_WCLOCK_1X ); | ||
602 | /* Set LEDs on Audio Dock */ | ||
603 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_LOCK ); | ||
604 | /* FIXME: We should set EMU_HANA_DOCK_LEDS_2_LOCK only when clock signal is present and valid */ | ||
605 | /* Allow DLL to settle */ | ||
606 | msleep(10); | ||
607 | /* Unmute all */ | ||
608 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); | ||
609 | |||
610 | |||
611 | break; | ||
587 | } | 612 | } |
588 | } | 613 | } |
589 | return change; | 614 | return change; |
@@ -871,7 +896,7 @@ static struct snd_kcontrol_new snd_emu10k1_spdif_mask_control = | |||
871 | .access = SNDRV_CTL_ELEM_ACCESS_READ, | 896 | .access = SNDRV_CTL_ELEM_ACCESS_READ, |
872 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 897 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
873 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), | 898 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), |
874 | .count = 4, | 899 | .count = 3, |
875 | .info = snd_emu10k1_spdif_info, | 900 | .info = snd_emu10k1_spdif_info, |
876 | .get = snd_emu10k1_spdif_get_mask | 901 | .get = snd_emu10k1_spdif_get_mask |
877 | }; | 902 | }; |
@@ -880,7 +905,7 @@ static struct snd_kcontrol_new snd_emu10k1_spdif_control = | |||
880 | { | 905 | { |
881 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 906 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
882 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), | 907 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), |
883 | .count = 4, | 908 | .count = 3, |
884 | .info = snd_emu10k1_spdif_info, | 909 | .info = snd_emu10k1_spdif_info, |
885 | .get = snd_emu10k1_spdif_get, | 910 | .get = snd_emu10k1_spdif_get, |
886 | .put = snd_emu10k1_spdif_put | 911 | .put = snd_emu10k1_spdif_put |
@@ -1326,14 +1351,7 @@ static struct snd_kcontrol_new snd_emu10k1_efx_attn_control = | |||
1326 | .put = snd_emu10k1_efx_attn_put | 1351 | .put = snd_emu10k1_efx_attn_put |
1327 | }; | 1352 | }; |
1328 | 1353 | ||
1329 | static int snd_emu10k1_shared_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1354 | #define snd_emu10k1_shared_spdif_info snd_ctl_boolean_mono_info |
1330 | { | ||
1331 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1332 | uinfo->count = 1; | ||
1333 | uinfo->value.integer.min = 0; | ||
1334 | uinfo->value.integer.max = 1; | ||
1335 | return 0; | ||
1336 | } | ||
1337 | 1355 | ||
1338 | static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol, | 1356 | static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol, |
1339 | struct snd_ctl_elem_value *ucontrol) | 1357 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/emu10k1/emumpu401.c b/sound/pci/emu10k1/emumpu401.c index 950c6bcd6b7d..04c7cf703531 100644 --- a/sound/pci/emu10k1/emumpu401.c +++ b/sound/pci/emu10k1/emumpu401.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for control of EMU10K1 MPU-401 in UART mode | 3 | * Routines for control of EMU10K1 MPU-401 in UART mode |
4 | * | 4 | * |
5 | * | 5 | * |
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index eda5cb373ded..5ce5befc701b 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Creative Labs, Inc. | 3 | * Creative Labs, Inc. |
4 | * Routines for control of EMU10K1 chips / PCM routines | 4 | * Routines for control of EMU10K1 chips / PCM routines |
5 | * Multichannel PCM support Copyright (c) Lee Revell <rlrevell@joe-job.com> | 5 | * Multichannel PCM support Copyright (c) Lee Revell <rlrevell@joe-job.com> |
diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c index 2c1585991bc8..c3fb10e81c9e 100644 --- a/sound/pci/emu10k1/emuproc.c +++ b/sound/pci/emu10k1/emuproc.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Creative Labs, Inc. | 3 | * Creative Labs, Inc. |
4 | * Routines for control of EMU10K1 chips / proc interface routines | 4 | * Routines for control of EMU10K1 chips / proc interface routines |
5 | * | 5 | * |
@@ -240,8 +240,42 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry, | |||
240 | struct snd_info_buffer *buffer) | 240 | struct snd_info_buffer *buffer) |
241 | { | 241 | { |
242 | struct snd_emu10k1 *emu = entry->private_data; | 242 | struct snd_emu10k1 *emu = entry->private_data; |
243 | snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF In", CDCS, CDSRCS); | 243 | u32 value; |
244 | snd_emu10k1_proc_spdif_status(emu, buffer, "Optical or Coax S/PDIF In", GPSCS, GPSRCS); | 244 | u32 value2; |
245 | unsigned long flags; | ||
246 | u32 rate; | ||
247 | |||
248 | if (emu->card_capabilities->emu1010) { | ||
249 | spin_lock_irqsave(&emu->emu_lock, flags); | ||
250 | snd_emu1010_fpga_read(emu, 0x38, &value); | ||
251 | spin_unlock_irqrestore(&emu->emu_lock, flags); | ||
252 | if ((value & 0x1) == 0) { | ||
253 | spin_lock_irqsave(&emu->emu_lock, flags); | ||
254 | snd_emu1010_fpga_read(emu, 0x2a, &value); | ||
255 | snd_emu1010_fpga_read(emu, 0x2b, &value2); | ||
256 | spin_unlock_irqrestore(&emu->emu_lock, flags); | ||
257 | rate = 0x1770000 / (((value << 5) | value2)+1); | ||
258 | snd_iprintf(buffer, "ADAT Locked : %u\n", rate); | ||
259 | } else { | ||
260 | snd_iprintf(buffer, "ADAT Unlocked\n"); | ||
261 | } | ||
262 | spin_lock_irqsave(&emu->emu_lock, flags); | ||
263 | snd_emu1010_fpga_read(emu, 0x20, &value); | ||
264 | spin_unlock_irqrestore(&emu->emu_lock, flags); | ||
265 | if ((value & 0x4) == 0) { | ||
266 | spin_lock_irqsave(&emu->emu_lock, flags); | ||
267 | snd_emu1010_fpga_read(emu, 0x28, &value); | ||
268 | snd_emu1010_fpga_read(emu, 0x29, &value2); | ||
269 | spin_unlock_irqrestore(&emu->emu_lock, flags); | ||
270 | rate = 0x1770000 / (((value << 5) | value2)+1); | ||
271 | snd_iprintf(buffer, "SPDIF Locked : %d\n", rate); | ||
272 | } else { | ||
273 | snd_iprintf(buffer, "SPDIF Unlocked\n"); | ||
274 | } | ||
275 | } else { | ||
276 | snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF In", CDCS, CDSRCS); | ||
277 | snd_emu10k1_proc_spdif_status(emu, buffer, "Optical or Coax S/PDIF In", GPSCS, GPSRCS); | ||
278 | } | ||
245 | #if 0 | 279 | #if 0 |
246 | val = snd_emu10k1_ptr_read(emu, ZVSRCS, 0); | 280 | val = snd_emu10k1_ptr_read(emu, ZVSRCS, 0); |
247 | snd_iprintf(buffer, "\nZoomed Video\n"); | 281 | snd_iprintf(buffer, "\nZoomed Video\n"); |
@@ -379,20 +413,16 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry, | |||
379 | struct snd_info_buffer *buffer) | 413 | struct snd_info_buffer *buffer) |
380 | { | 414 | { |
381 | struct snd_emu10k1 *emu = entry->private_data; | 415 | struct snd_emu10k1 *emu = entry->private_data; |
382 | unsigned long value; | 416 | int value; |
383 | unsigned long flags; | 417 | unsigned long flags; |
384 | unsigned long regs; | ||
385 | int i; | 418 | int i; |
386 | snd_iprintf(buffer, "EMU1010 Registers:\n\n"); | 419 | snd_iprintf(buffer, "EMU1010 Registers:\n\n"); |
387 | 420 | ||
388 | for(i = 0; i < 0x30; i+=1) { | 421 | for(i = 0; i < 0x40; i+=1) { |
389 | spin_lock_irqsave(&emu->emu_lock, flags); | 422 | spin_lock_irqsave(&emu->emu_lock, flags); |
390 | regs=i+0x40; /* 0x40 upwards are registers. */ | 423 | snd_emu1010_fpga_read(emu, i, &value); |
391 | outl(regs, emu->port + A_IOCFG); | ||
392 | outl(regs | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */ | ||
393 | value = inl(emu->port + A_IOCFG); | ||
394 | spin_unlock_irqrestore(&emu->emu_lock, flags); | 424 | spin_unlock_irqrestore(&emu->emu_lock, flags); |
395 | snd_iprintf(buffer, "%02X: %08lX, %02lX\n", i, value, (value >> 8) & 0x7f); | 425 | snd_iprintf(buffer, "%02X: %08X, %02X\n", i, value, (value >> 8) & 0x7f); |
396 | } | 426 | } |
397 | } | 427 | } |
398 | 428 | ||
@@ -555,9 +585,9 @@ int __devinit snd_emu10k1_proc_init(struct snd_emu10k1 * emu) | |||
555 | { | 585 | { |
556 | struct snd_info_entry *entry; | 586 | struct snd_info_entry *entry; |
557 | #ifdef CONFIG_SND_DEBUG | 587 | #ifdef CONFIG_SND_DEBUG |
558 | if ((emu->card_capabilities->emu1010) && | 588 | if (emu->card_capabilities->emu1010) { |
559 | snd_card_proc_new(emu->card, "emu1010_regs", &entry)) { | 589 | if (! snd_card_proc_new(emu->card, "emu1010_regs", &entry)) |
560 | snd_info_set_text_ops(entry, emu, snd_emu_proc_emu1010_reg_read); | 590 | snd_info_set_text_ops(entry, emu, snd_emu_proc_emu1010_reg_read); |
561 | } | 591 | } |
562 | if (! snd_card_proc_new(emu->card, "io_regs", &entry)) { | 592 | if (! snd_card_proc_new(emu->card, "io_regs", &entry)) { |
563 | snd_info_set_text_ops(entry, emu, snd_emu_proc_io_reg_read); | 593 | snd_info_set_text_ops(entry, emu, snd_emu_proc_io_reg_read); |
diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c index 116e1c8d9361..6702c15fefa3 100644 --- a/sound/pci/emu10k1/io.c +++ b/sound/pci/emu10k1/io.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Creative Labs, Inc. | 3 | * Creative Labs, Inc. |
4 | * Routines for control of EMU10K1 chips | 4 | * Routines for control of EMU10K1 chips |
5 | * | 5 | * |
@@ -226,9 +226,9 @@ int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, | |||
226 | return 0; | 226 | return 0; |
227 | } | 227 | } |
228 | 228 | ||
229 | int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, int reg, int value) | 229 | int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, u32 reg, u32 value) |
230 | { | 230 | { |
231 | if (reg < 0 || reg > 0x3f) | 231 | if (reg > 0x3f) |
232 | return 1; | 232 | return 1; |
233 | reg += 0x40; /* 0x40 upwards are registers. */ | 233 | reg += 0x40; /* 0x40 upwards are registers. */ |
234 | if (value < 0 || value > 0x3f) /* 0 to 0x3f are values */ | 234 | if (value < 0 || value > 0x3f) /* 0 to 0x3f are values */ |
@@ -244,9 +244,9 @@ int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, int reg, int value) | |||
244 | return 0; | 244 | return 0; |
245 | } | 245 | } |
246 | 246 | ||
247 | int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, int reg, int *value) | 247 | int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, u32 reg, u32 *value) |
248 | { | 248 | { |
249 | if (reg < 0 || reg > 0x3f) | 249 | if (reg > 0x3f) |
250 | return 1; | 250 | return 1; |
251 | reg += 0x40; /* 0x40 upwards are registers. */ | 251 | reg += 0x40; /* 0x40 upwards are registers. */ |
252 | outl(reg, emu->port + A_IOCFG); | 252 | outl(reg, emu->port + A_IOCFG); |
@@ -261,7 +261,7 @@ int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, int reg, int *value) | |||
261 | /* Each Destination has one and only one Source, | 261 | /* Each Destination has one and only one Source, |
262 | * but one Source can feed any number of Destinations simultaneously. | 262 | * but one Source can feed any number of Destinations simultaneously. |
263 | */ | 263 | */ |
264 | int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 * emu, int dst, int src) | 264 | int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 * emu, u32 dst, u32 src) |
265 | { | 265 | { |
266 | snd_emu1010_fpga_write(emu, 0x00, ((dst >> 8) & 0x3f) ); | 266 | snd_emu1010_fpga_write(emu, 0x00, ((dst >> 8) & 0x3f) ); |
267 | snd_emu1010_fpga_write(emu, 0x01, (dst & 0x3f) ); | 267 | snd_emu1010_fpga_write(emu, 0x01, (dst & 0x3f) ); |
diff --git a/sound/pci/emu10k1/irq.c b/sound/pci/emu10k1/irq.c index 4f18f7e8bcfb..3c114b45e0b2 100644 --- a/sound/pci/emu10k1/irq.c +++ b/sound/pci/emu10k1/irq.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Creative Labs, Inc. | 3 | * Creative Labs, Inc. |
4 | * Routines for IRQ control of EMU10K1 chips | 4 | * Routines for IRQ control of EMU10K1 chips |
5 | * | 5 | * |
diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index 4fcaefe5a3c5..48097c6bb15c 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Copyright (c) by Takashi Iwai <tiwai@suse.de> | 3 | * Copyright (c) by Takashi Iwai <tiwai@suse.de> |
4 | * | 4 | * |
5 | * EMU10K1 memory page allocation (PTB area) | 5 | * EMU10K1 memory page allocation (PTB area) |
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c index 7ee19c63c2c8..d619a3842cdd 100644 --- a/sound/pci/emu10k1/p16v.c +++ b/sound/pci/emu10k1/p16v.c | |||
@@ -124,11 +124,12 @@ | |||
124 | 124 | ||
125 | /* hardware definition */ | 125 | /* hardware definition */ |
126 | static struct snd_pcm_hardware snd_p16v_playback_hw = { | 126 | static struct snd_pcm_hardware snd_p16v_playback_hw = { |
127 | .info = (SNDRV_PCM_INFO_MMAP | | 127 | .info = SNDRV_PCM_INFO_MMAP | |
128 | SNDRV_PCM_INFO_INTERLEAVED | | 128 | SNDRV_PCM_INFO_INTERLEAVED | |
129 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 129 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
130 | SNDRV_PCM_INFO_RESUME | | 130 | SNDRV_PCM_INFO_RESUME | |
131 | SNDRV_PCM_INFO_MMAP_VALID), | 131 | SNDRV_PCM_INFO_MMAP_VALID | |
132 | SNDRV_PCM_INFO_SYNC_START, | ||
132 | .formats = SNDRV_PCM_FMTBIT_S32_LE, /* Only supports 24-bit samples padded to 32 bits. */ | 133 | .formats = SNDRV_PCM_FMTBIT_S32_LE, /* Only supports 24-bit samples padded to 32 bits. */ |
133 | .rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, | 134 | .rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, |
134 | .rate_min = 44100, | 135 | .rate_min = 44100, |
@@ -207,6 +208,11 @@ static int snd_p16v_pcm_open_playback_channel(struct snd_pcm_substream *substrea | |||
207 | if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) | 208 | if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) |
208 | return err; | 209 | return err; |
209 | 210 | ||
211 | runtime->sync.id32[0] = substream->pcm->card->number; | ||
212 | runtime->sync.id32[1] = 'P'; | ||
213 | runtime->sync.id32[2] = 16; | ||
214 | runtime->sync.id32[3] = 'V'; | ||
215 | |||
210 | return 0; | 216 | return 0; |
211 | } | 217 | } |
212 | /* open_capture callback */ | 218 | /* open_capture callback */ |
@@ -448,6 +454,9 @@ static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream, | |||
448 | break; | 454 | break; |
449 | } | 455 | } |
450 | snd_pcm_group_for_each_entry(s, substream) { | 456 | snd_pcm_group_for_each_entry(s, substream) { |
457 | if (snd_pcm_substream_chip(s) != emu || | ||
458 | s->stream != SNDRV_PCM_STREAM_PLAYBACK) | ||
459 | continue; | ||
451 | runtime = s->runtime; | 460 | runtime = s->runtime; |
452 | epcm = runtime->private_data; | 461 | epcm = runtime->private_data; |
453 | channel = substream->pcm->device-emu->p16v_device_offset; | 462 | channel = substream->pcm->device-emu->p16v_device_offset; |
diff --git a/sound/pci/emu10k1/voice.c b/sound/pci/emu10k1/voice.c index 1db50fe61475..04fa8492abb0 100644 --- a/sound/pci/emu10k1/voice.c +++ b/sound/pci/emu10k1/voice.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Creative Labs, Inc. | 3 | * Creative Labs, Inc. |
4 | * Lee Revell <rlrevell@joe-job.com> | 4 | * Lee Revell <rlrevell@joe-job.com> |
5 | * Routines for control of EMU10K1 chips - voice manager | 5 | * Routines for control of EMU10K1 chips - voice manager |
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 21cb4268a59b..b958f869cb13 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for Ensoniq ES1370/ES1371 AudioPCI soundcard | 2 | * Driver for Ensoniq ES1370/ES1371 AudioPCI soundcard |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz>, | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz>, |
4 | * Thomas Sailer <sailer@ife.ee.ethz.ch> | 4 | * Thomas Sailer <sailer@ife.ee.ethz.ch> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -61,7 +61,7 @@ | |||
61 | #endif | 61 | #endif |
62 | 62 | ||
63 | 63 | ||
64 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Thomas Sailer <sailer@ife.ee.ethz.ch>"); | 64 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Thomas Sailer <sailer@ife.ee.ethz.ch>"); |
65 | MODULE_LICENSE("GPL"); | 65 | MODULE_LICENSE("GPL"); |
66 | #ifdef CHIP1370 | 66 | #ifdef CHIP1370 |
67 | MODULE_DESCRIPTION("Ensoniq AudioPCI ES1370"); | 67 | MODULE_DESCRIPTION("Ensoniq AudioPCI ES1370"); |
@@ -1419,15 +1419,7 @@ static int snd_ens1373_spdif_stream_put(struct snd_kcontrol *kcontrol, | |||
1419 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_es1371_spdif_info, \ | 1419 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_es1371_spdif_info, \ |
1420 | .get = snd_es1371_spdif_get, .put = snd_es1371_spdif_put } | 1420 | .get = snd_es1371_spdif_get, .put = snd_es1371_spdif_put } |
1421 | 1421 | ||
1422 | static int snd_es1371_spdif_info(struct snd_kcontrol *kcontrol, | 1422 | #define snd_es1371_spdif_info snd_ctl_boolean_mono_info |
1423 | struct snd_ctl_elem_info *uinfo) | ||
1424 | { | ||
1425 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1426 | uinfo->count = 1; | ||
1427 | uinfo->value.integer.min = 0; | ||
1428 | uinfo->value.integer.max = 1; | ||
1429 | return 0; | ||
1430 | } | ||
1431 | 1423 | ||
1432 | static int snd_es1371_spdif_get(struct snd_kcontrol *kcontrol, | 1424 | static int snd_es1371_spdif_get(struct snd_kcontrol *kcontrol, |
1433 | struct snd_ctl_elem_value *ucontrol) | 1425 | struct snd_ctl_elem_value *ucontrol) |
@@ -1489,15 +1481,7 @@ static struct snd_kcontrol_new snd_es1371_mixer_spdif[] __devinitdata = { | |||
1489 | }; | 1481 | }; |
1490 | 1482 | ||
1491 | 1483 | ||
1492 | static int snd_es1373_rear_info(struct snd_kcontrol *kcontrol, | 1484 | #define snd_es1373_rear_info snd_ctl_boolean_mono_info |
1493 | struct snd_ctl_elem_info *uinfo) | ||
1494 | { | ||
1495 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1496 | uinfo->count = 1; | ||
1497 | uinfo->value.integer.min = 0; | ||
1498 | uinfo->value.integer.max = 1; | ||
1499 | return 0; | ||
1500 | } | ||
1501 | 1485 | ||
1502 | static int snd_es1373_rear_get(struct snd_kcontrol *kcontrol, | 1486 | static int snd_es1373_rear_get(struct snd_kcontrol *kcontrol, |
1503 | struct snd_ctl_elem_value *ucontrol) | 1487 | struct snd_ctl_elem_value *ucontrol) |
@@ -1542,15 +1526,7 @@ static struct snd_kcontrol_new snd_ens1373_rear __devinitdata = | |||
1542 | .put = snd_es1373_rear_put, | 1526 | .put = snd_es1373_rear_put, |
1543 | }; | 1527 | }; |
1544 | 1528 | ||
1545 | static int snd_es1373_line_info(struct snd_kcontrol *kcontrol, | 1529 | #define snd_es1373_line_info snd_ctl_boolean_mono_info |
1546 | struct snd_ctl_elem_info *uinfo) | ||
1547 | { | ||
1548 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1549 | uinfo->count = 1; | ||
1550 | uinfo->value.integer.min = 0; | ||
1551 | uinfo->value.integer.max = 1; | ||
1552 | return 0; | ||
1553 | } | ||
1554 | 1530 | ||
1555 | static int snd_es1373_line_get(struct snd_kcontrol *kcontrol, | 1531 | static int snd_es1373_line_get(struct snd_kcontrol *kcontrol, |
1556 | struct snd_ctl_elem_value *ucontrol) | 1532 | struct snd_ctl_elem_value *ucontrol) |
@@ -1707,15 +1683,7 @@ static int __devinit snd_ensoniq_1371_mixer(struct ensoniq *ensoniq, | |||
1707 | .get = snd_ensoniq_control_get, .put = snd_ensoniq_control_put, \ | 1683 | .get = snd_ensoniq_control_get, .put = snd_ensoniq_control_put, \ |
1708 | .private_value = mask } | 1684 | .private_value = mask } |
1709 | 1685 | ||
1710 | static int snd_ensoniq_control_info(struct snd_kcontrol *kcontrol, | 1686 | #define snd_ensoniq_control_info snd_ctl_boolean_mono_info |
1711 | struct snd_ctl_elem_info *uinfo) | ||
1712 | { | ||
1713 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1714 | uinfo->count = 1; | ||
1715 | uinfo->value.integer.min = 0; | ||
1716 | uinfo->value.integer.max = 1; | ||
1717 | return 0; | ||
1718 | } | ||
1719 | 1687 | ||
1720 | static int snd_ensoniq_control_get(struct snd_kcontrol *kcontrol, | 1688 | static int snd_ensoniq_control_get(struct snd_kcontrol *kcontrol, |
1721 | struct snd_ctl_elem_value *ucontrol) | 1689 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index fec29a108945..fb25abe68a02 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for ESS Solo-1 (ES1938, ES1946, ES1969) soundcard | 2 | * Driver for ESS Solo-1 (ES1938, ES1946, ES1969) soundcard |
3 | * Copyright (c) by Jaromir Koutek <miri@punknet.cz>, | 3 | * Copyright (c) by Jaromir Koutek <miri@punknet.cz>, |
4 | * Jaroslav Kysela <perex@suse.cz>, | 4 | * Jaroslav Kysela <perex@perex.cz>, |
5 | * Thomas Sailer <sailer@ife.ee.ethz.ch>, | 5 | * Thomas Sailer <sailer@ife.ee.ethz.ch>, |
6 | * Abramo Bagnara <abramo@alsa-project.org>, | 6 | * Abramo Bagnara <abramo@alsa-project.org>, |
7 | * Markus Gruber <gruber@eikon.tum.de> | 7 | * Markus Gruber <gruber@eikon.tum.de> |
@@ -1066,15 +1066,7 @@ static int snd_es1938_put_mux(struct snd_kcontrol *kcontrol, | |||
1066 | return snd_es1938_mixer_bits(chip, 0x1c, 0x07, val) != val; | 1066 | return snd_es1938_mixer_bits(chip, 0x1c, 0x07, val) != val; |
1067 | } | 1067 | } |
1068 | 1068 | ||
1069 | static int snd_es1938_info_spatializer_enable(struct snd_kcontrol *kcontrol, | 1069 | #define snd_es1938_info_spatializer_enable snd_ctl_boolean_mono_info |
1070 | struct snd_ctl_elem_info *uinfo) | ||
1071 | { | ||
1072 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1073 | uinfo->count = 1; | ||
1074 | uinfo->value.integer.min = 0; | ||
1075 | uinfo->value.integer.max = 1; | ||
1076 | return 0; | ||
1077 | } | ||
1078 | 1070 | ||
1079 | static int snd_es1938_get_spatializer_enable(struct snd_kcontrol *kcontrol, | 1071 | static int snd_es1938_get_spatializer_enable(struct snd_kcontrol *kcontrol, |
1080 | struct snd_ctl_elem_value *ucontrol) | 1072 | struct snd_ctl_elem_value *ucontrol) |
@@ -1120,15 +1112,7 @@ static int snd_es1938_get_hw_volume(struct snd_kcontrol *kcontrol, | |||
1120 | return 0; | 1112 | return 0; |
1121 | } | 1113 | } |
1122 | 1114 | ||
1123 | static int snd_es1938_info_hw_switch(struct snd_kcontrol *kcontrol, | 1115 | #define snd_es1938_info_hw_switch snd_ctl_boolean_stereo_info |
1124 | struct snd_ctl_elem_info *uinfo) | ||
1125 | { | ||
1126 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1127 | uinfo->count = 2; | ||
1128 | uinfo->value.integer.min = 0; | ||
1129 | uinfo->value.integer.max = 1; | ||
1130 | return 0; | ||
1131 | } | ||
1132 | 1116 | ||
1133 | static int snd_es1938_get_hw_switch(struct snd_kcontrol *kcontrol, | 1117 | static int snd_es1938_get_hw_switch(struct snd_kcontrol *kcontrol, |
1134 | struct snd_ctl_elem_value *ucontrol) | 1118 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 2faf009076bb..d69b11d1f993 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c | |||
@@ -843,10 +843,9 @@ static void snd_es1968_bob_dec(struct es1968 *chip) | |||
843 | snd_es1968_bob_stop(chip); | 843 | snd_es1968_bob_stop(chip); |
844 | else if (chip->bob_freq > ESM_BOB_FREQ) { | 844 | else if (chip->bob_freq > ESM_BOB_FREQ) { |
845 | /* check reduction of timer frequency */ | 845 | /* check reduction of timer frequency */ |
846 | struct list_head *p; | ||
847 | int max_freq = ESM_BOB_FREQ; | 846 | int max_freq = ESM_BOB_FREQ; |
848 | list_for_each(p, &chip->substream_list) { | 847 | struct esschan *es; |
849 | struct esschan *es = list_entry(p, struct esschan, list); | 848 | list_for_each_entry(es, &chip->substream_list, list) { |
850 | if (max_freq < es->bob_freq) | 849 | if (max_freq < es->bob_freq) |
851 | max_freq = es->bob_freq; | 850 | max_freq = es->bob_freq; |
852 | } | 851 | } |
@@ -1316,12 +1315,11 @@ static struct snd_pcm_hardware snd_es1968_capture = { | |||
1316 | 1315 | ||
1317 | static int calc_available_memory_size(struct es1968 *chip) | 1316 | static int calc_available_memory_size(struct es1968 *chip) |
1318 | { | 1317 | { |
1319 | struct list_head *p; | ||
1320 | int max_size = 0; | 1318 | int max_size = 0; |
1321 | 1319 | struct esm_memory *buf; | |
1320 | |||
1322 | mutex_lock(&chip->memory_mutex); | 1321 | mutex_lock(&chip->memory_mutex); |
1323 | list_for_each(p, &chip->buf_list) { | 1322 | list_for_each_entry(buf, &chip->buf_list, list) { |
1324 | struct esm_memory *buf = list_entry(p, struct esm_memory, list); | ||
1325 | if (buf->empty && buf->buf.bytes > max_size) | 1323 | if (buf->empty && buf->buf.bytes > max_size) |
1326 | max_size = buf->buf.bytes; | 1324 | max_size = buf->buf.bytes; |
1327 | } | 1325 | } |
@@ -1335,12 +1333,10 @@ static int calc_available_memory_size(struct es1968 *chip) | |||
1335 | static struct esm_memory *snd_es1968_new_memory(struct es1968 *chip, int size) | 1333 | static struct esm_memory *snd_es1968_new_memory(struct es1968 *chip, int size) |
1336 | { | 1334 | { |
1337 | struct esm_memory *buf; | 1335 | struct esm_memory *buf; |
1338 | struct list_head *p; | 1336 | |
1339 | |||
1340 | size = ALIGN(size, ESM_MEM_ALIGN); | 1337 | size = ALIGN(size, ESM_MEM_ALIGN); |
1341 | mutex_lock(&chip->memory_mutex); | 1338 | mutex_lock(&chip->memory_mutex); |
1342 | list_for_each(p, &chip->buf_list) { | 1339 | list_for_each_entry(buf, &chip->buf_list, list) { |
1343 | buf = list_entry(p, struct esm_memory, list); | ||
1344 | if (buf->empty && buf->buf.bytes >= size) | 1340 | if (buf->empty && buf->buf.bytes >= size) |
1345 | goto __found; | 1341 | goto __found; |
1346 | } | 1342 | } |
@@ -1938,10 +1934,9 @@ static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id) | |||
1938 | } | 1934 | } |
1939 | 1935 | ||
1940 | if (event & ESM_SOUND_IRQ) { | 1936 | if (event & ESM_SOUND_IRQ) { |
1941 | struct list_head *p; | 1937 | struct esschan *es; |
1942 | spin_lock(&chip->substream_lock); | 1938 | spin_lock(&chip->substream_lock); |
1943 | list_for_each(p, &chip->substream_list) { | 1939 | list_for_each_entry(es, &chip->substream_list, list) { |
1944 | struct esschan *es = list_entry(p, struct esschan, list); | ||
1945 | if (es->running) | 1940 | if (es->running) |
1946 | snd_es1968_update_pcm(chip, es); | 1941 | snd_es1968_update_pcm(chip, es); |
1947 | } | 1942 | } |
@@ -2345,7 +2340,7 @@ static int es1968_resume(struct pci_dev *pci) | |||
2345 | { | 2340 | { |
2346 | struct snd_card *card = pci_get_drvdata(pci); | 2341 | struct snd_card *card = pci_get_drvdata(pci); |
2347 | struct es1968 *chip = card->private_data; | 2342 | struct es1968 *chip = card->private_data; |
2348 | struct list_head *p; | 2343 | struct esschan *es; |
2349 | 2344 | ||
2350 | if (! chip->do_pm) | 2345 | if (! chip->do_pm) |
2351 | return 0; | 2346 | return 0; |
@@ -2374,8 +2369,7 @@ static int es1968_resume(struct pci_dev *pci) | |||
2374 | /* restore ac97 state */ | 2369 | /* restore ac97 state */ |
2375 | snd_ac97_resume(chip->ac97); | 2370 | snd_ac97_resume(chip->ac97); |
2376 | 2371 | ||
2377 | list_for_each(p, &chip->substream_list) { | 2372 | list_for_each_entry(es, &chip->substream_list, list) { |
2378 | struct esschan *es = list_entry(p, struct esschan, list); | ||
2379 | switch (es->mode) { | 2373 | switch (es->mode) { |
2380 | case ESM_MODE_PLAY: | 2374 | case ESM_MODE_PLAY: |
2381 | snd_es1968_playback_setup(chip, es, es->substream->runtime); | 2375 | snd_es1968_playback_setup(chip, es, es->substream->runtime); |
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 11015178e207..9939109f05a2 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * The driver for the ForteMedia FM801 based soundcards | 2 | * The driver for the ForteMedia FM801 based soundcards |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * Support FM only card by Andy Shevchenko <andy@smile.org.ua> | 5 | * Support FM only card by Andy Shevchenko <andy@smile.org.ua> |
6 | * | 6 | * |
@@ -42,7 +42,7 @@ | |||
42 | #define TEA575X_RADIO 1 | 42 | #define TEA575X_RADIO 1 |
43 | #endif | 43 | #endif |
44 | 44 | ||
45 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 45 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
46 | MODULE_DESCRIPTION("ForteMedia FM801"); | 46 | MODULE_DESCRIPTION("ForteMedia FM801"); |
47 | MODULE_LICENSE("GPL"); | 47 | MODULE_LICENSE("GPL"); |
48 | MODULE_SUPPORTED_DEVICE("{{ForteMedia,FM801}," | 48 | MODULE_SUPPORTED_DEVICE("{{ForteMedia,FM801}," |
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index b2484bbdcc1d..ab0c726d648e 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile | |||
@@ -1,19 +1,18 @@ | |||
1 | snd-hda-intel-objs := hda_intel.o | 1 | snd-hda-intel-y := hda_intel.o |
2 | # since snd-hda-intel is the only driver using hda-codec, | 2 | # since snd-hda-intel is the only driver using hda-codec, |
3 | # merge it into a single module although it was originally | 3 | # merge it into a single module although it was originally |
4 | # designed to be individual modules | 4 | # designed to be individual modules |
5 | snd-hda-intel-objs += hda_codec.o \ | 5 | snd-hda-intel-y += hda_codec.o |
6 | hda_generic.o \ | 6 | snd-hda-intel-$(CONFIG_PROC_FS) += hda_proc.o |
7 | patch_realtek.o \ | 7 | snd-hda-intel-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o |
8 | patch_cmedia.o \ | 8 | snd-hda-intel-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o |
9 | patch_analog.o \ | 9 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_REALTEK) += patch_realtek.o |
10 | patch_sigmatel.o \ | 10 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_CMEDIA) += patch_cmedia.o |
11 | patch_si3054.o \ | 11 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_ANALOG) += patch_analog.o |
12 | patch_atihdmi.o \ | 12 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_SIGMATEL) += patch_sigmatel.o |
13 | patch_conexant.o \ | 13 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_SI3054) += patch_si3054.o |
14 | patch_via.o | 14 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_ATIHDMI) += patch_atihdmi.o |
15 | ifdef CONFIG_PROC_FS | 15 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_CONEXANT) += patch_conexant.o |
16 | snd-hda-intel-objs += hda_proc.o | 16 | snd-hda-intel-$(CONFIG_SND_HDA_CODEC_VIA) += patch_via.o |
17 | endif | ||
18 | 17 | ||
19 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o | 18 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index f87f8f088956..187533e477c6 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -31,7 +31,15 @@ | |||
31 | #include <sound/tlv.h> | 31 | #include <sound/tlv.h> |
32 | #include <sound/initval.h> | 32 | #include <sound/initval.h> |
33 | #include "hda_local.h" | 33 | #include "hda_local.h" |
34 | 34 | #include <sound/hda_hwdep.h> | |
35 | |||
36 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
37 | /* define this option here to hide as static */ | ||
38 | static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT; | ||
39 | module_param(power_save, int, 0644); | ||
40 | MODULE_PARM_DESC(power_save, "Automatic power-saving timeout " | ||
41 | "(in second, 0 = disable)."); | ||
42 | #endif | ||
35 | 43 | ||
36 | /* | 44 | /* |
37 | * vendor / preset table | 45 | * vendor / preset table |
@@ -59,6 +67,13 @@ static struct hda_vendor_id hda_vendor_ids[] = { | |||
59 | #include "hda_patch.h" | 67 | #include "hda_patch.h" |
60 | 68 | ||
61 | 69 | ||
70 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
71 | static void hda_power_work(struct work_struct *work); | ||
72 | static void hda_keep_power_on(struct hda_codec *codec); | ||
73 | #else | ||
74 | static inline void hda_keep_power_on(struct hda_codec *codec) {} | ||
75 | #endif | ||
76 | |||
62 | /** | 77 | /** |
63 | * snd_hda_codec_read - send a command and get the response | 78 | * snd_hda_codec_read - send a command and get the response |
64 | * @codec: the HDA codec | 79 | * @codec: the HDA codec |
@@ -76,12 +91,14 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, | |||
76 | unsigned int verb, unsigned int parm) | 91 | unsigned int verb, unsigned int parm) |
77 | { | 92 | { |
78 | unsigned int res; | 93 | unsigned int res; |
94 | snd_hda_power_up(codec); | ||
79 | mutex_lock(&codec->bus->cmd_mutex); | 95 | mutex_lock(&codec->bus->cmd_mutex); |
80 | if (!codec->bus->ops.command(codec, nid, direct, verb, parm)) | 96 | if (!codec->bus->ops.command(codec, nid, direct, verb, parm)) |
81 | res = codec->bus->ops.get_response(codec); | 97 | res = codec->bus->ops.get_response(codec); |
82 | else | 98 | else |
83 | res = (unsigned int)-1; | 99 | res = (unsigned int)-1; |
84 | mutex_unlock(&codec->bus->cmd_mutex); | 100 | mutex_unlock(&codec->bus->cmd_mutex); |
101 | snd_hda_power_down(codec); | ||
85 | return res; | 102 | return res; |
86 | } | 103 | } |
87 | 104 | ||
@@ -101,9 +118,11 @@ int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, | |||
101 | unsigned int verb, unsigned int parm) | 118 | unsigned int verb, unsigned int parm) |
102 | { | 119 | { |
103 | int err; | 120 | int err; |
121 | snd_hda_power_up(codec); | ||
104 | mutex_lock(&codec->bus->cmd_mutex); | 122 | mutex_lock(&codec->bus->cmd_mutex); |
105 | err = codec->bus->ops.command(codec, nid, direct, verb, parm); | 123 | err = codec->bus->ops.command(codec, nid, direct, verb, parm); |
106 | mutex_unlock(&codec->bus->cmd_mutex); | 124 | mutex_unlock(&codec->bus->cmd_mutex); |
125 | snd_hda_power_down(codec); | ||
107 | return err; | 126 | return err; |
108 | } | 127 | } |
109 | 128 | ||
@@ -136,6 +155,8 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, | |||
136 | unsigned int parm; | 155 | unsigned int parm; |
137 | 156 | ||
138 | parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT); | 157 | parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT); |
158 | if (parm == -1) | ||
159 | return 0; | ||
139 | *start_id = (parm >> 16) & 0x7fff; | 160 | *start_id = (parm >> 16) & 0x7fff; |
140 | return (int)(parm & 0x7fff); | 161 | return (int)(parm & 0x7fff); |
141 | } | 162 | } |
@@ -387,6 +408,13 @@ int __devinit snd_hda_bus_new(struct snd_card *card, | |||
387 | return 0; | 408 | return 0; |
388 | } | 409 | } |
389 | 410 | ||
411 | #ifdef CONFIG_SND_HDA_GENERIC | ||
412 | #define is_generic_config(codec) \ | ||
413 | (codec->bus->modelname && !strcmp(codec->bus->modelname, "generic")) | ||
414 | #else | ||
415 | #define is_generic_config(codec) 0 | ||
416 | #endif | ||
417 | |||
390 | /* | 418 | /* |
391 | * find a matching codec preset | 419 | * find a matching codec preset |
392 | */ | 420 | */ |
@@ -395,7 +423,7 @@ find_codec_preset(struct hda_codec *codec) | |||
395 | { | 423 | { |
396 | const struct hda_codec_preset **tbl, *preset; | 424 | const struct hda_codec_preset **tbl, *preset; |
397 | 425 | ||
398 | if (codec->bus->modelname && !strcmp(codec->bus->modelname, "generic")) | 426 | if (is_generic_config(codec)) |
399 | return NULL; /* use the generic parser */ | 427 | return NULL; /* use the generic parser */ |
400 | 428 | ||
401 | for (tbl = hda_preset_tables; *tbl; tbl++) { | 429 | for (tbl = hda_preset_tables; *tbl; tbl++) { |
@@ -486,6 +514,10 @@ static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node) | |||
486 | } | 514 | } |
487 | 515 | ||
488 | 516 | ||
517 | static void init_hda_cache(struct hda_cache_rec *cache, | ||
518 | unsigned int record_size); | ||
519 | static void free_hda_cache(struct hda_cache_rec *cache); | ||
520 | |||
489 | /* | 521 | /* |
490 | * codec destructor | 522 | * codec destructor |
491 | */ | 523 | */ |
@@ -493,17 +525,20 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
493 | { | 525 | { |
494 | if (!codec) | 526 | if (!codec) |
495 | return; | 527 | return; |
528 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
529 | cancel_delayed_work(&codec->power_work); | ||
530 | flush_scheduled_work(); | ||
531 | #endif | ||
496 | list_del(&codec->list); | 532 | list_del(&codec->list); |
497 | codec->bus->caddr_tbl[codec->addr] = NULL; | 533 | codec->bus->caddr_tbl[codec->addr] = NULL; |
498 | if (codec->patch_ops.free) | 534 | if (codec->patch_ops.free) |
499 | codec->patch_ops.free(codec); | 535 | codec->patch_ops.free(codec); |
500 | kfree(codec->amp_info); | 536 | free_hda_cache(&codec->amp_cache); |
537 | free_hda_cache(&codec->cmd_cache); | ||
501 | kfree(codec->wcaps); | 538 | kfree(codec->wcaps); |
502 | kfree(codec); | 539 | kfree(codec); |
503 | } | 540 | } |
504 | 541 | ||
505 | static void init_amp_hash(struct hda_codec *codec); | ||
506 | |||
507 | /** | 542 | /** |
508 | * snd_hda_codec_new - create a HDA codec | 543 | * snd_hda_codec_new - create a HDA codec |
509 | * @bus: the bus to assign | 544 | * @bus: the bus to assign |
@@ -537,7 +572,17 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
537 | codec->bus = bus; | 572 | codec->bus = bus; |
538 | codec->addr = codec_addr; | 573 | codec->addr = codec_addr; |
539 | mutex_init(&codec->spdif_mutex); | 574 | mutex_init(&codec->spdif_mutex); |
540 | init_amp_hash(codec); | 575 | init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); |
576 | init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); | ||
577 | |||
578 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
579 | INIT_DELAYED_WORK(&codec->power_work, hda_power_work); | ||
580 | /* snd_hda_codec_new() marks the codec as power-up, and leave it as is. | ||
581 | * the caller has to power down appropriatley after initialization | ||
582 | * phase. | ||
583 | */ | ||
584 | hda_keep_power_on(codec); | ||
585 | #endif | ||
541 | 586 | ||
542 | list_add_tail(&codec->list, &bus->codec_list); | 587 | list_add_tail(&codec->list, &bus->codec_list); |
543 | bus->caddr_tbl[codec_addr] = codec; | 588 | bus->caddr_tbl[codec_addr] = codec; |
@@ -581,10 +626,26 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
581 | snd_hda_get_codec_name(codec, bus->card->mixername, | 626 | snd_hda_get_codec_name(codec, bus->card->mixername, |
582 | sizeof(bus->card->mixername)); | 627 | sizeof(bus->card->mixername)); |
583 | 628 | ||
584 | if (codec->preset && codec->preset->patch) | 629 | #ifdef CONFIG_SND_HDA_GENERIC |
585 | err = codec->preset->patch(codec); | 630 | if (is_generic_config(codec)) { |
586 | else | ||
587 | err = snd_hda_parse_generic_codec(codec); | 631 | err = snd_hda_parse_generic_codec(codec); |
632 | goto patched; | ||
633 | } | ||
634 | #endif | ||
635 | if (codec->preset && codec->preset->patch) { | ||
636 | err = codec->preset->patch(codec); | ||
637 | goto patched; | ||
638 | } | ||
639 | |||
640 | /* call the default parser */ | ||
641 | #ifdef CONFIG_SND_HDA_GENERIC | ||
642 | err = snd_hda_parse_generic_codec(codec); | ||
643 | #else | ||
644 | printk(KERN_ERR "hda-codec: No codec parser is available\n"); | ||
645 | err = -ENODEV; | ||
646 | #endif | ||
647 | |||
648 | patched: | ||
588 | if (err < 0) { | 649 | if (err < 0) { |
589 | snd_hda_codec_free(codec); | 650 | snd_hda_codec_free(codec); |
590 | return err; | 651 | return err; |
@@ -594,6 +655,9 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
594 | init_unsol_queue(bus); | 655 | init_unsol_queue(bus); |
595 | 656 | ||
596 | snd_hda_codec_proc_new(codec); | 657 | snd_hda_codec_proc_new(codec); |
658 | #ifdef CONFIG_SND_HDA_HWDEP | ||
659 | snd_hda_create_hwdep(codec); | ||
660 | #endif | ||
597 | 661 | ||
598 | sprintf(component, "HDA:%08x", codec->vendor_id); | 662 | sprintf(component, "HDA:%08x", codec->vendor_id); |
599 | snd_component_add(codec->bus->card, component); | 663 | snd_component_add(codec->bus->card, component); |
@@ -637,59 +701,72 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, | |||
637 | #define INFO_AMP_VOL(ch) (1 << (1 + (ch))) | 701 | #define INFO_AMP_VOL(ch) (1 << (1 + (ch))) |
638 | 702 | ||
639 | /* initialize the hash table */ | 703 | /* initialize the hash table */ |
640 | static void __devinit init_amp_hash(struct hda_codec *codec) | 704 | static void __devinit init_hda_cache(struct hda_cache_rec *cache, |
705 | unsigned int record_size) | ||
706 | { | ||
707 | memset(cache, 0, sizeof(*cache)); | ||
708 | memset(cache->hash, 0xff, sizeof(cache->hash)); | ||
709 | cache->record_size = record_size; | ||
710 | } | ||
711 | |||
712 | static void free_hda_cache(struct hda_cache_rec *cache) | ||
641 | { | 713 | { |
642 | memset(codec->amp_hash, 0xff, sizeof(codec->amp_hash)); | 714 | kfree(cache->buffer); |
643 | codec->num_amp_entries = 0; | ||
644 | codec->amp_info_size = 0; | ||
645 | codec->amp_info = NULL; | ||
646 | } | 715 | } |
647 | 716 | ||
648 | /* query the hash. allocate an entry if not found. */ | 717 | /* query the hash. allocate an entry if not found. */ |
649 | static struct hda_amp_info *get_alloc_amp_hash(struct hda_codec *codec, u32 key) | 718 | static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, |
719 | u32 key) | ||
650 | { | 720 | { |
651 | u16 idx = key % (u16)ARRAY_SIZE(codec->amp_hash); | 721 | u16 idx = key % (u16)ARRAY_SIZE(cache->hash); |
652 | u16 cur = codec->amp_hash[idx]; | 722 | u16 cur = cache->hash[idx]; |
653 | struct hda_amp_info *info; | 723 | struct hda_cache_head *info; |
654 | 724 | ||
655 | while (cur != 0xffff) { | 725 | while (cur != 0xffff) { |
656 | info = &codec->amp_info[cur]; | 726 | info = (struct hda_cache_head *)(cache->buffer + |
727 | cur * cache->record_size); | ||
657 | if (info->key == key) | 728 | if (info->key == key) |
658 | return info; | 729 | return info; |
659 | cur = info->next; | 730 | cur = info->next; |
660 | } | 731 | } |
661 | 732 | ||
662 | /* add a new hash entry */ | 733 | /* add a new hash entry */ |
663 | if (codec->num_amp_entries >= codec->amp_info_size) { | 734 | if (cache->num_entries >= cache->size) { |
664 | /* reallocate the array */ | 735 | /* reallocate the array */ |
665 | int new_size = codec->amp_info_size + 64; | 736 | unsigned int new_size = cache->size + 64; |
666 | struct hda_amp_info *new_info; | 737 | void *new_buffer; |
667 | new_info = kcalloc(new_size, sizeof(struct hda_amp_info), | 738 | new_buffer = kcalloc(new_size, cache->record_size, GFP_KERNEL); |
668 | GFP_KERNEL); | 739 | if (!new_buffer) { |
669 | if (!new_info) { | ||
670 | snd_printk(KERN_ERR "hda_codec: " | 740 | snd_printk(KERN_ERR "hda_codec: " |
671 | "can't malloc amp_info\n"); | 741 | "can't malloc amp_info\n"); |
672 | return NULL; | 742 | return NULL; |
673 | } | 743 | } |
674 | if (codec->amp_info) { | 744 | if (cache->buffer) { |
675 | memcpy(new_info, codec->amp_info, | 745 | memcpy(new_buffer, cache->buffer, |
676 | codec->amp_info_size * | 746 | cache->size * cache->record_size); |
677 | sizeof(struct hda_amp_info)); | 747 | kfree(cache->buffer); |
678 | kfree(codec->amp_info); | ||
679 | } | 748 | } |
680 | codec->amp_info_size = new_size; | 749 | cache->size = new_size; |
681 | codec->amp_info = new_info; | 750 | cache->buffer = new_buffer; |
682 | } | 751 | } |
683 | cur = codec->num_amp_entries++; | 752 | cur = cache->num_entries++; |
684 | info = &codec->amp_info[cur]; | 753 | info = (struct hda_cache_head *)(cache->buffer + |
754 | cur * cache->record_size); | ||
685 | info->key = key; | 755 | info->key = key; |
686 | info->status = 0; /* not initialized yet */ | 756 | info->val = 0; |
687 | info->next = codec->amp_hash[idx]; | 757 | info->next = cache->hash[idx]; |
688 | codec->amp_hash[idx] = cur; | 758 | cache->hash[idx] = cur; |
689 | 759 | ||
690 | return info; | 760 | return info; |
691 | } | 761 | } |
692 | 762 | ||
763 | /* query and allocate an amp hash entry */ | ||
764 | static inline struct hda_amp_info * | ||
765 | get_alloc_amp_hash(struct hda_codec *codec, u32 key) | ||
766 | { | ||
767 | return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key); | ||
768 | } | ||
769 | |||
693 | /* | 770 | /* |
694 | * query AMP capabilities for the given widget and direction | 771 | * query AMP capabilities for the given widget and direction |
695 | */ | 772 | */ |
@@ -700,7 +777,7 @@ static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction) | |||
700 | info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0)); | 777 | info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0)); |
701 | if (!info) | 778 | if (!info) |
702 | return 0; | 779 | return 0; |
703 | if (!(info->status & INFO_AMP_CAPS)) { | 780 | if (!(info->head.val & INFO_AMP_CAPS)) { |
704 | if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD)) | 781 | if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD)) |
705 | nid = codec->afg; | 782 | nid = codec->afg; |
706 | info->amp_caps = snd_hda_param_read(codec, nid, | 783 | info->amp_caps = snd_hda_param_read(codec, nid, |
@@ -708,7 +785,7 @@ static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction) | |||
708 | AC_PAR_AMP_OUT_CAP : | 785 | AC_PAR_AMP_OUT_CAP : |
709 | AC_PAR_AMP_IN_CAP); | 786 | AC_PAR_AMP_IN_CAP); |
710 | if (info->amp_caps) | 787 | if (info->amp_caps) |
711 | info->status |= INFO_AMP_CAPS; | 788 | info->head.val |= INFO_AMP_CAPS; |
712 | } | 789 | } |
713 | return info->amp_caps; | 790 | return info->amp_caps; |
714 | } | 791 | } |
@@ -722,7 +799,7 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, | |||
722 | if (!info) | 799 | if (!info) |
723 | return -EINVAL; | 800 | return -EINVAL; |
724 | info->amp_caps = caps; | 801 | info->amp_caps = caps; |
725 | info->status |= INFO_AMP_CAPS; | 802 | info->head.val |= INFO_AMP_CAPS; |
726 | return 0; | 803 | return 0; |
727 | } | 804 | } |
728 | 805 | ||
@@ -736,7 +813,7 @@ static unsigned int get_vol_mute(struct hda_codec *codec, | |||
736 | { | 813 | { |
737 | u32 val, parm; | 814 | u32 val, parm; |
738 | 815 | ||
739 | if (info->status & INFO_AMP_VOL(ch)) | 816 | if (info->head.val & INFO_AMP_VOL(ch)) |
740 | return info->vol[ch]; | 817 | return info->vol[ch]; |
741 | 818 | ||
742 | parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT; | 819 | parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT; |
@@ -745,7 +822,7 @@ static unsigned int get_vol_mute(struct hda_codec *codec, | |||
745 | val = snd_hda_codec_read(codec, nid, 0, | 822 | val = snd_hda_codec_read(codec, nid, 0, |
746 | AC_VERB_GET_AMP_GAIN_MUTE, parm); | 823 | AC_VERB_GET_AMP_GAIN_MUTE, parm); |
747 | info->vol[ch] = val & 0xff; | 824 | info->vol[ch] = val & 0xff; |
748 | info->status |= INFO_AMP_VOL(ch); | 825 | info->head.val |= INFO_AMP_VOL(ch); |
749 | return info->vol[ch]; | 826 | return info->vol[ch]; |
750 | } | 827 | } |
751 | 828 | ||
@@ -792,12 +869,50 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, | |||
792 | return 0; | 869 | return 0; |
793 | val &= mask; | 870 | val &= mask; |
794 | val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask; | 871 | val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask; |
795 | if (info->vol[ch] == val && !codec->in_resume) | 872 | if (info->vol[ch] == val) |
796 | return 0; | 873 | return 0; |
797 | put_vol_mute(codec, info, nid, ch, direction, idx, val); | 874 | put_vol_mute(codec, info, nid, ch, direction, idx, val); |
798 | return 1; | 875 | return 1; |
799 | } | 876 | } |
800 | 877 | ||
878 | /* | ||
879 | * update the AMP stereo with the same mask and value | ||
880 | */ | ||
881 | int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, | ||
882 | int direction, int idx, int mask, int val) | ||
883 | { | ||
884 | int ch, ret = 0; | ||
885 | for (ch = 0; ch < 2; ch++) | ||
886 | ret |= snd_hda_codec_amp_update(codec, nid, ch, direction, | ||
887 | idx, mask, val); | ||
888 | return ret; | ||
889 | } | ||
890 | |||
891 | #ifdef SND_HDA_NEEDS_RESUME | ||
892 | /* resume the all amp commands from the cache */ | ||
893 | void snd_hda_codec_resume_amp(struct hda_codec *codec) | ||
894 | { | ||
895 | struct hda_amp_info *buffer = codec->amp_cache.buffer; | ||
896 | int i; | ||
897 | |||
898 | for (i = 0; i < codec->amp_cache.size; i++, buffer++) { | ||
899 | u32 key = buffer->head.key; | ||
900 | hda_nid_t nid; | ||
901 | unsigned int idx, dir, ch; | ||
902 | if (!key) | ||
903 | continue; | ||
904 | nid = key & 0xff; | ||
905 | idx = (key >> 16) & 0xff; | ||
906 | dir = (key >> 24) & 0xff; | ||
907 | for (ch = 0; ch < 2; ch++) { | ||
908 | if (!(buffer->head.val & INFO_AMP_VOL(ch))) | ||
909 | continue; | ||
910 | put_vol_mute(codec, buffer, nid, ch, dir, idx, | ||
911 | buffer->vol[ch]); | ||
912 | } | ||
913 | } | ||
914 | } | ||
915 | #endif /* SND_HDA_NEEDS_RESUME */ | ||
801 | 916 | ||
802 | /* | 917 | /* |
803 | * AMP control callbacks | 918 | * AMP control callbacks |
@@ -844,9 +959,11 @@ int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, | |||
844 | long *valp = ucontrol->value.integer.value; | 959 | long *valp = ucontrol->value.integer.value; |
845 | 960 | ||
846 | if (chs & 1) | 961 | if (chs & 1) |
847 | *valp++ = snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x7f; | 962 | *valp++ = snd_hda_codec_amp_read(codec, nid, 0, dir, idx) |
963 | & HDA_AMP_VOLMASK; | ||
848 | if (chs & 2) | 964 | if (chs & 2) |
849 | *valp = snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x7f; | 965 | *valp = snd_hda_codec_amp_read(codec, nid, 1, dir, idx) |
966 | & HDA_AMP_VOLMASK; | ||
850 | return 0; | 967 | return 0; |
851 | } | 968 | } |
852 | 969 | ||
@@ -861,6 +978,7 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, | |||
861 | long *valp = ucontrol->value.integer.value; | 978 | long *valp = ucontrol->value.integer.value; |
862 | int change = 0; | 979 | int change = 0; |
863 | 980 | ||
981 | snd_hda_power_up(codec); | ||
864 | if (chs & 1) { | 982 | if (chs & 1) { |
865 | change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, | 983 | change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, |
866 | 0x7f, *valp); | 984 | 0x7f, *valp); |
@@ -869,6 +987,7 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, | |||
869 | if (chs & 2) | 987 | if (chs & 2) |
870 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, | 988 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, |
871 | 0x7f, *valp); | 989 | 0x7f, *valp); |
990 | snd_hda_power_down(codec); | ||
872 | return change; | 991 | return change; |
873 | } | 992 | } |
874 | 993 | ||
@@ -923,10 +1042,10 @@ int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, | |||
923 | 1042 | ||
924 | if (chs & 1) | 1043 | if (chs & 1) |
925 | *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & | 1044 | *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & |
926 | 0x80) ? 0 : 1; | 1045 | HDA_AMP_MUTE) ? 0 : 1; |
927 | if (chs & 2) | 1046 | if (chs & 2) |
928 | *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & | 1047 | *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & |
929 | 0x80) ? 0 : 1; | 1048 | HDA_AMP_MUTE) ? 0 : 1; |
930 | return 0; | 1049 | return 0; |
931 | } | 1050 | } |
932 | 1051 | ||
@@ -941,15 +1060,22 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, | |||
941 | long *valp = ucontrol->value.integer.value; | 1060 | long *valp = ucontrol->value.integer.value; |
942 | int change = 0; | 1061 | int change = 0; |
943 | 1062 | ||
1063 | snd_hda_power_up(codec); | ||
944 | if (chs & 1) { | 1064 | if (chs & 1) { |
945 | change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, | 1065 | change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, |
946 | 0x80, *valp ? 0 : 0x80); | 1066 | HDA_AMP_MUTE, |
1067 | *valp ? 0 : HDA_AMP_MUTE); | ||
947 | valp++; | 1068 | valp++; |
948 | } | 1069 | } |
949 | if (chs & 2) | 1070 | if (chs & 2) |
950 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, | 1071 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, |
951 | 0x80, *valp ? 0 : 0x80); | 1072 | HDA_AMP_MUTE, |
952 | 1073 | *valp ? 0 : HDA_AMP_MUTE); | |
1074 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1075 | if (codec->patch_ops.check_power_status) | ||
1076 | codec->patch_ops.check_power_status(codec, nid); | ||
1077 | #endif | ||
1078 | snd_hda_power_down(codec); | ||
953 | return change; | 1079 | return change; |
954 | } | 1080 | } |
955 | 1081 | ||
@@ -1002,6 +1128,93 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, | |||
1002 | } | 1128 | } |
1003 | 1129 | ||
1004 | /* | 1130 | /* |
1131 | * generic bound volume/swtich controls | ||
1132 | */ | ||
1133 | int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol, | ||
1134 | struct snd_ctl_elem_info *uinfo) | ||
1135 | { | ||
1136 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1137 | struct hda_bind_ctls *c; | ||
1138 | int err; | ||
1139 | |||
1140 | c = (struct hda_bind_ctls *)kcontrol->private_value; | ||
1141 | mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ | ||
1142 | kcontrol->private_value = *c->values; | ||
1143 | err = c->ops->info(kcontrol, uinfo); | ||
1144 | kcontrol->private_value = (long)c; | ||
1145 | mutex_unlock(&codec->spdif_mutex); | ||
1146 | return err; | ||
1147 | } | ||
1148 | |||
1149 | int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol, | ||
1150 | struct snd_ctl_elem_value *ucontrol) | ||
1151 | { | ||
1152 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1153 | struct hda_bind_ctls *c; | ||
1154 | int err; | ||
1155 | |||
1156 | c = (struct hda_bind_ctls *)kcontrol->private_value; | ||
1157 | mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ | ||
1158 | kcontrol->private_value = *c->values; | ||
1159 | err = c->ops->get(kcontrol, ucontrol); | ||
1160 | kcontrol->private_value = (long)c; | ||
1161 | mutex_unlock(&codec->spdif_mutex); | ||
1162 | return err; | ||
1163 | } | ||
1164 | |||
1165 | int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol, | ||
1166 | struct snd_ctl_elem_value *ucontrol) | ||
1167 | { | ||
1168 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1169 | struct hda_bind_ctls *c; | ||
1170 | unsigned long *vals; | ||
1171 | int err = 0, change = 0; | ||
1172 | |||
1173 | c = (struct hda_bind_ctls *)kcontrol->private_value; | ||
1174 | mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ | ||
1175 | for (vals = c->values; *vals; vals++) { | ||
1176 | kcontrol->private_value = *vals; | ||
1177 | err = c->ops->put(kcontrol, ucontrol); | ||
1178 | if (err < 0) | ||
1179 | break; | ||
1180 | change |= err; | ||
1181 | } | ||
1182 | kcontrol->private_value = (long)c; | ||
1183 | mutex_unlock(&codec->spdif_mutex); | ||
1184 | return err < 0 ? err : change; | ||
1185 | } | ||
1186 | |||
1187 | int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag, | ||
1188 | unsigned int size, unsigned int __user *tlv) | ||
1189 | { | ||
1190 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1191 | struct hda_bind_ctls *c; | ||
1192 | int err; | ||
1193 | |||
1194 | c = (struct hda_bind_ctls *)kcontrol->private_value; | ||
1195 | mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ | ||
1196 | kcontrol->private_value = *c->values; | ||
1197 | err = c->ops->tlv(kcontrol, op_flag, size, tlv); | ||
1198 | kcontrol->private_value = (long)c; | ||
1199 | mutex_unlock(&codec->spdif_mutex); | ||
1200 | return err; | ||
1201 | } | ||
1202 | |||
1203 | struct hda_ctl_ops snd_hda_bind_vol = { | ||
1204 | .info = snd_hda_mixer_amp_volume_info, | ||
1205 | .get = snd_hda_mixer_amp_volume_get, | ||
1206 | .put = snd_hda_mixer_amp_volume_put, | ||
1207 | .tlv = snd_hda_mixer_amp_tlv | ||
1208 | }; | ||
1209 | |||
1210 | struct hda_ctl_ops snd_hda_bind_sw = { | ||
1211 | .info = snd_hda_mixer_amp_switch_info, | ||
1212 | .get = snd_hda_mixer_amp_switch_get, | ||
1213 | .put = snd_hda_mixer_amp_switch_put, | ||
1214 | .tlv = snd_hda_mixer_amp_tlv | ||
1215 | }; | ||
1216 | |||
1217 | /* | ||
1005 | * SPDIF out controls | 1218 | * SPDIF out controls |
1006 | */ | 1219 | */ |
1007 | 1220 | ||
@@ -1118,26 +1331,20 @@ static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, | |||
1118 | change = codec->spdif_ctls != val; | 1331 | change = codec->spdif_ctls != val; |
1119 | codec->spdif_ctls = val; | 1332 | codec->spdif_ctls = val; |
1120 | 1333 | ||
1121 | if (change || codec->in_resume) { | 1334 | if (change) { |
1122 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, | 1335 | snd_hda_codec_write_cache(codec, nid, 0, |
1123 | val & 0xff); | 1336 | AC_VERB_SET_DIGI_CONVERT_1, |
1124 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_2, | 1337 | val & 0xff); |
1125 | val >> 8); | 1338 | snd_hda_codec_write_cache(codec, nid, 0, |
1339 | AC_VERB_SET_DIGI_CONVERT_2, | ||
1340 | val >> 8); | ||
1126 | } | 1341 | } |
1127 | 1342 | ||
1128 | mutex_unlock(&codec->spdif_mutex); | 1343 | mutex_unlock(&codec->spdif_mutex); |
1129 | return change; | 1344 | return change; |
1130 | } | 1345 | } |
1131 | 1346 | ||
1132 | static int snd_hda_spdif_out_switch_info(struct snd_kcontrol *kcontrol, | 1347 | #define snd_hda_spdif_out_switch_info snd_ctl_boolean_mono_info |
1133 | struct snd_ctl_elem_info *uinfo) | ||
1134 | { | ||
1135 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1136 | uinfo->count = 1; | ||
1137 | uinfo->value.integer.min = 0; | ||
1138 | uinfo->value.integer.max = 1; | ||
1139 | return 0; | ||
1140 | } | ||
1141 | 1348 | ||
1142 | static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol, | 1349 | static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol, |
1143 | struct snd_ctl_elem_value *ucontrol) | 1350 | struct snd_ctl_elem_value *ucontrol) |
@@ -1161,17 +1368,16 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol, | |||
1161 | if (ucontrol->value.integer.value[0]) | 1368 | if (ucontrol->value.integer.value[0]) |
1162 | val |= AC_DIG1_ENABLE; | 1369 | val |= AC_DIG1_ENABLE; |
1163 | change = codec->spdif_ctls != val; | 1370 | change = codec->spdif_ctls != val; |
1164 | if (change || codec->in_resume) { | 1371 | if (change) { |
1165 | codec->spdif_ctls = val; | 1372 | codec->spdif_ctls = val; |
1166 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, | 1373 | snd_hda_codec_write_cache(codec, nid, 0, |
1167 | val & 0xff); | 1374 | AC_VERB_SET_DIGI_CONVERT_1, |
1375 | val & 0xff); | ||
1168 | /* unmute amp switch (if any) */ | 1376 | /* unmute amp switch (if any) */ |
1169 | if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) && | 1377 | if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) && |
1170 | (val & AC_DIG1_ENABLE)) | 1378 | (val & AC_DIG1_ENABLE)) |
1171 | snd_hda_codec_write(codec, nid, 0, | 1379 | snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, |
1172 | AC_VERB_SET_AMP_GAIN_MUTE, | 1380 | HDA_AMP_MUTE, 0); |
1173 | AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | | ||
1174 | AC_AMP_SET_OUTPUT); | ||
1175 | } | 1381 | } |
1176 | mutex_unlock(&codec->spdif_mutex); | 1382 | mutex_unlock(&codec->spdif_mutex); |
1177 | return change; | 1383 | return change; |
@@ -1219,8 +1425,7 @@ static struct snd_kcontrol_new dig_mixes[] = { | |||
1219 | * | 1425 | * |
1220 | * Returns 0 if successful, or a negative error code. | 1426 | * Returns 0 if successful, or a negative error code. |
1221 | */ | 1427 | */ |
1222 | int __devinit snd_hda_create_spdif_out_ctls(struct hda_codec *codec, | 1428 | int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid) |
1223 | hda_nid_t nid) | ||
1224 | { | 1429 | { |
1225 | int err; | 1430 | int err; |
1226 | struct snd_kcontrol *kctl; | 1431 | struct snd_kcontrol *kctl; |
@@ -1264,10 +1469,10 @@ static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol, | |||
1264 | 1469 | ||
1265 | mutex_lock(&codec->spdif_mutex); | 1470 | mutex_lock(&codec->spdif_mutex); |
1266 | change = codec->spdif_in_enable != val; | 1471 | change = codec->spdif_in_enable != val; |
1267 | if (change || codec->in_resume) { | 1472 | if (change) { |
1268 | codec->spdif_in_enable = val; | 1473 | codec->spdif_in_enable = val; |
1269 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, | 1474 | snd_hda_codec_write_cache(codec, nid, 0, |
1270 | val); | 1475 | AC_VERB_SET_DIGI_CONVERT_1, val); |
1271 | } | 1476 | } |
1272 | mutex_unlock(&codec->spdif_mutex); | 1477 | mutex_unlock(&codec->spdif_mutex); |
1273 | return change; | 1478 | return change; |
@@ -1318,8 +1523,7 @@ static struct snd_kcontrol_new dig_in_ctls[] = { | |||
1318 | * | 1523 | * |
1319 | * Returns 0 if successful, or a negative error code. | 1524 | * Returns 0 if successful, or a negative error code. |
1320 | */ | 1525 | */ |
1321 | int __devinit snd_hda_create_spdif_in_ctls(struct hda_codec *codec, | 1526 | int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) |
1322 | hda_nid_t nid) | ||
1323 | { | 1527 | { |
1324 | int err; | 1528 | int err; |
1325 | struct snd_kcontrol *kctl; | 1529 | struct snd_kcontrol *kctl; |
@@ -1338,6 +1542,79 @@ int __devinit snd_hda_create_spdif_in_ctls(struct hda_codec *codec, | |||
1338 | return 0; | 1542 | return 0; |
1339 | } | 1543 | } |
1340 | 1544 | ||
1545 | #ifdef SND_HDA_NEEDS_RESUME | ||
1546 | /* | ||
1547 | * command cache | ||
1548 | */ | ||
1549 | |||
1550 | /* build a 32bit cache key with the widget id and the command parameter */ | ||
1551 | #define build_cmd_cache_key(nid, verb) ((verb << 8) | nid) | ||
1552 | #define get_cmd_cache_nid(key) ((key) & 0xff) | ||
1553 | #define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff) | ||
1554 | |||
1555 | /** | ||
1556 | * snd_hda_codec_write_cache - send a single command with caching | ||
1557 | * @codec: the HDA codec | ||
1558 | * @nid: NID to send the command | ||
1559 | * @direct: direct flag | ||
1560 | * @verb: the verb to send | ||
1561 | * @parm: the parameter for the verb | ||
1562 | * | ||
1563 | * Send a single command without waiting for response. | ||
1564 | * | ||
1565 | * Returns 0 if successful, or a negative error code. | ||
1566 | */ | ||
1567 | int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, | ||
1568 | int direct, unsigned int verb, unsigned int parm) | ||
1569 | { | ||
1570 | int err; | ||
1571 | snd_hda_power_up(codec); | ||
1572 | mutex_lock(&codec->bus->cmd_mutex); | ||
1573 | err = codec->bus->ops.command(codec, nid, direct, verb, parm); | ||
1574 | if (!err) { | ||
1575 | struct hda_cache_head *c; | ||
1576 | u32 key = build_cmd_cache_key(nid, verb); | ||
1577 | c = get_alloc_hash(&codec->cmd_cache, key); | ||
1578 | if (c) | ||
1579 | c->val = parm; | ||
1580 | } | ||
1581 | mutex_unlock(&codec->bus->cmd_mutex); | ||
1582 | snd_hda_power_down(codec); | ||
1583 | return err; | ||
1584 | } | ||
1585 | |||
1586 | /* resume the all commands from the cache */ | ||
1587 | void snd_hda_codec_resume_cache(struct hda_codec *codec) | ||
1588 | { | ||
1589 | struct hda_cache_head *buffer = codec->cmd_cache.buffer; | ||
1590 | int i; | ||
1591 | |||
1592 | for (i = 0; i < codec->cmd_cache.size; i++, buffer++) { | ||
1593 | u32 key = buffer->key; | ||
1594 | if (!key) | ||
1595 | continue; | ||
1596 | snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0, | ||
1597 | get_cmd_cache_cmd(key), buffer->val); | ||
1598 | } | ||
1599 | } | ||
1600 | |||
1601 | /** | ||
1602 | * snd_hda_sequence_write_cache - sequence writes with caching | ||
1603 | * @codec: the HDA codec | ||
1604 | * @seq: VERB array to send | ||
1605 | * | ||
1606 | * Send the commands sequentially from the given array. | ||
1607 | * Thte commands are recorded on cache for power-save and resume. | ||
1608 | * The array must be terminated with NID=0. | ||
1609 | */ | ||
1610 | void snd_hda_sequence_write_cache(struct hda_codec *codec, | ||
1611 | const struct hda_verb *seq) | ||
1612 | { | ||
1613 | for (; seq->nid; seq++) | ||
1614 | snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb, | ||
1615 | seq->param); | ||
1616 | } | ||
1617 | #endif /* SND_HDA_NEEDS_RESUME */ | ||
1341 | 1618 | ||
1342 | /* | 1619 | /* |
1343 | * set power state of the codec | 1620 | * set power state of the codec |
@@ -1345,23 +1622,86 @@ int __devinit snd_hda_create_spdif_in_ctls(struct hda_codec *codec, | |||
1345 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | 1622 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, |
1346 | unsigned int power_state) | 1623 | unsigned int power_state) |
1347 | { | 1624 | { |
1348 | hda_nid_t nid, nid_start; | 1625 | hda_nid_t nid; |
1349 | int nodes; | 1626 | int i; |
1350 | 1627 | ||
1351 | snd_hda_codec_write(codec, fg, 0, AC_VERB_SET_POWER_STATE, | 1628 | snd_hda_codec_write(codec, fg, 0, AC_VERB_SET_POWER_STATE, |
1352 | power_state); | 1629 | power_state); |
1353 | 1630 | ||
1354 | nodes = snd_hda_get_sub_nodes(codec, fg, &nid_start); | 1631 | nid = codec->start_nid; |
1355 | for (nid = nid_start; nid < nodes + nid_start; nid++) { | 1632 | for (i = 0; i < codec->num_nodes; i++, nid++) { |
1356 | if (get_wcaps(codec, nid) & AC_WCAP_POWER) | 1633 | if (get_wcaps(codec, nid) & AC_WCAP_POWER) { |
1634 | unsigned int pincap; | ||
1635 | /* | ||
1636 | * don't power down the widget if it controls eapd | ||
1637 | * and EAPD_BTLENABLE is set. | ||
1638 | */ | ||
1639 | pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | ||
1640 | if (pincap & AC_PINCAP_EAPD) { | ||
1641 | int eapd = snd_hda_codec_read(codec, nid, | ||
1642 | 0, AC_VERB_GET_EAPD_BTLENABLE, 0); | ||
1643 | eapd &= 0x02; | ||
1644 | if (power_state == AC_PWRST_D3 && eapd) | ||
1645 | continue; | ||
1646 | } | ||
1357 | snd_hda_codec_write(codec, nid, 0, | 1647 | snd_hda_codec_write(codec, nid, 0, |
1358 | AC_VERB_SET_POWER_STATE, | 1648 | AC_VERB_SET_POWER_STATE, |
1359 | power_state); | 1649 | power_state); |
1650 | } | ||
1360 | } | 1651 | } |
1361 | 1652 | ||
1362 | if (power_state == AC_PWRST_D0) | 1653 | if (power_state == AC_PWRST_D0) { |
1654 | unsigned long end_time; | ||
1655 | int state; | ||
1363 | msleep(10); | 1656 | msleep(10); |
1657 | /* wait until the codec reachs to D0 */ | ||
1658 | end_time = jiffies + msecs_to_jiffies(500); | ||
1659 | do { | ||
1660 | state = snd_hda_codec_read(codec, fg, 0, | ||
1661 | AC_VERB_GET_POWER_STATE, 0); | ||
1662 | if (state == power_state) | ||
1663 | break; | ||
1664 | msleep(1); | ||
1665 | } while (time_after_eq(end_time, jiffies)); | ||
1666 | } | ||
1667 | } | ||
1668 | |||
1669 | #ifdef SND_HDA_NEEDS_RESUME | ||
1670 | /* | ||
1671 | * call suspend and power-down; used both from PM and power-save | ||
1672 | */ | ||
1673 | static void hda_call_codec_suspend(struct hda_codec *codec) | ||
1674 | { | ||
1675 | if (codec->patch_ops.suspend) | ||
1676 | codec->patch_ops.suspend(codec, PMSG_SUSPEND); | ||
1677 | hda_set_power_state(codec, | ||
1678 | codec->afg ? codec->afg : codec->mfg, | ||
1679 | AC_PWRST_D3); | ||
1680 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1681 | cancel_delayed_work(&codec->power_work); | ||
1682 | codec->power_on = 0; | ||
1683 | codec->power_transition = 0; | ||
1684 | #endif | ||
1685 | } | ||
1686 | |||
1687 | /* | ||
1688 | * kick up codec; used both from PM and power-save | ||
1689 | */ | ||
1690 | static void hda_call_codec_resume(struct hda_codec *codec) | ||
1691 | { | ||
1692 | hda_set_power_state(codec, | ||
1693 | codec->afg ? codec->afg : codec->mfg, | ||
1694 | AC_PWRST_D0); | ||
1695 | if (codec->patch_ops.resume) | ||
1696 | codec->patch_ops.resume(codec); | ||
1697 | else { | ||
1698 | if (codec->patch_ops.init) | ||
1699 | codec->patch_ops.init(codec); | ||
1700 | snd_hda_codec_resume_amp(codec); | ||
1701 | snd_hda_codec_resume_cache(codec); | ||
1702 | } | ||
1364 | } | 1703 | } |
1704 | #endif /* SND_HDA_NEEDS_RESUME */ | ||
1365 | 1705 | ||
1366 | 1706 | ||
1367 | /** | 1707 | /** |
@@ -1376,28 +1716,24 @@ int __devinit snd_hda_build_controls(struct hda_bus *bus) | |||
1376 | { | 1716 | { |
1377 | struct hda_codec *codec; | 1717 | struct hda_codec *codec; |
1378 | 1718 | ||
1379 | /* build controls */ | ||
1380 | list_for_each_entry(codec, &bus->codec_list, list) { | 1719 | list_for_each_entry(codec, &bus->codec_list, list) { |
1381 | int err; | 1720 | int err = 0; |
1382 | if (!codec->patch_ops.build_controls) | 1721 | /* fake as if already powered-on */ |
1383 | continue; | 1722 | hda_keep_power_on(codec); |
1384 | err = codec->patch_ops.build_controls(codec); | 1723 | /* then fire up */ |
1385 | if (err < 0) | ||
1386 | return err; | ||
1387 | } | ||
1388 | |||
1389 | /* initialize */ | ||
1390 | list_for_each_entry(codec, &bus->codec_list, list) { | ||
1391 | int err; | ||
1392 | hda_set_power_state(codec, | 1724 | hda_set_power_state(codec, |
1393 | codec->afg ? codec->afg : codec->mfg, | 1725 | codec->afg ? codec->afg : codec->mfg, |
1394 | AC_PWRST_D0); | 1726 | AC_PWRST_D0); |
1395 | if (!codec->patch_ops.init) | 1727 | /* continue to initialize... */ |
1396 | continue; | 1728 | if (codec->patch_ops.init) |
1397 | err = codec->patch_ops.init(codec); | 1729 | err = codec->patch_ops.init(codec); |
1730 | if (!err && codec->patch_ops.build_controls) | ||
1731 | err = codec->patch_ops.build_controls(codec); | ||
1732 | snd_hda_power_down(codec); | ||
1398 | if (err < 0) | 1733 | if (err < 0) |
1399 | return err; | 1734 | return err; |
1400 | } | 1735 | } |
1736 | |||
1401 | return 0; | 1737 | return 0; |
1402 | } | 1738 | } |
1403 | 1739 | ||
@@ -1789,9 +2125,9 @@ int __devinit snd_hda_build_pcms(struct hda_bus *bus) | |||
1789 | * | 2125 | * |
1790 | * If no entries are matching, the function returns a negative value. | 2126 | * If no entries are matching, the function returns a negative value. |
1791 | */ | 2127 | */ |
1792 | int __devinit snd_hda_check_board_config(struct hda_codec *codec, | 2128 | int snd_hda_check_board_config(struct hda_codec *codec, |
1793 | int num_configs, const char **models, | 2129 | int num_configs, const char **models, |
1794 | const struct snd_pci_quirk *tbl) | 2130 | const struct snd_pci_quirk *tbl) |
1795 | { | 2131 | { |
1796 | if (codec->bus->modelname && models) { | 2132 | if (codec->bus->modelname && models) { |
1797 | int i; | 2133 | int i; |
@@ -1841,10 +2177,9 @@ int __devinit snd_hda_check_board_config(struct hda_codec *codec, | |||
1841 | * | 2177 | * |
1842 | * Returns 0 if successful, or a negative error code. | 2178 | * Returns 0 if successful, or a negative error code. |
1843 | */ | 2179 | */ |
1844 | int __devinit snd_hda_add_new_ctls(struct hda_codec *codec, | 2180 | int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) |
1845 | struct snd_kcontrol_new *knew) | ||
1846 | { | 2181 | { |
1847 | int err; | 2182 | int err; |
1848 | 2183 | ||
1849 | for (; knew->name; knew++) { | 2184 | for (; knew->name; knew++) { |
1850 | struct snd_kcontrol *kctl; | 2185 | struct snd_kcontrol *kctl; |
@@ -1867,6 +2202,93 @@ int __devinit snd_hda_add_new_ctls(struct hda_codec *codec, | |||
1867 | return 0; | 2202 | return 0; |
1868 | } | 2203 | } |
1869 | 2204 | ||
2205 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
2206 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | ||
2207 | unsigned int power_state); | ||
2208 | |||
2209 | static void hda_power_work(struct work_struct *work) | ||
2210 | { | ||
2211 | struct hda_codec *codec = | ||
2212 | container_of(work, struct hda_codec, power_work.work); | ||
2213 | |||
2214 | if (!codec->power_on || codec->power_count) { | ||
2215 | codec->power_transition = 0; | ||
2216 | return; | ||
2217 | } | ||
2218 | |||
2219 | hda_call_codec_suspend(codec); | ||
2220 | if (codec->bus->ops.pm_notify) | ||
2221 | codec->bus->ops.pm_notify(codec); | ||
2222 | } | ||
2223 | |||
2224 | static void hda_keep_power_on(struct hda_codec *codec) | ||
2225 | { | ||
2226 | codec->power_count++; | ||
2227 | codec->power_on = 1; | ||
2228 | } | ||
2229 | |||
2230 | void snd_hda_power_up(struct hda_codec *codec) | ||
2231 | { | ||
2232 | codec->power_count++; | ||
2233 | if (codec->power_on || codec->power_transition) | ||
2234 | return; | ||
2235 | |||
2236 | codec->power_on = 1; | ||
2237 | if (codec->bus->ops.pm_notify) | ||
2238 | codec->bus->ops.pm_notify(codec); | ||
2239 | hda_call_codec_resume(codec); | ||
2240 | cancel_delayed_work(&codec->power_work); | ||
2241 | codec->power_transition = 0; | ||
2242 | } | ||
2243 | |||
2244 | void snd_hda_power_down(struct hda_codec *codec) | ||
2245 | { | ||
2246 | --codec->power_count; | ||
2247 | if (!codec->power_on || codec->power_count || codec->power_transition) | ||
2248 | return; | ||
2249 | if (power_save) { | ||
2250 | codec->power_transition = 1; /* avoid reentrance */ | ||
2251 | schedule_delayed_work(&codec->power_work, | ||
2252 | msecs_to_jiffies(power_save * 1000)); | ||
2253 | } | ||
2254 | } | ||
2255 | |||
2256 | int snd_hda_check_amp_list_power(struct hda_codec *codec, | ||
2257 | struct hda_loopback_check *check, | ||
2258 | hda_nid_t nid) | ||
2259 | { | ||
2260 | struct hda_amp_list *p; | ||
2261 | int ch, v; | ||
2262 | |||
2263 | if (!check->amplist) | ||
2264 | return 0; | ||
2265 | for (p = check->amplist; p->nid; p++) { | ||
2266 | if (p->nid == nid) | ||
2267 | break; | ||
2268 | } | ||
2269 | if (!p->nid) | ||
2270 | return 0; /* nothing changed */ | ||
2271 | |||
2272 | for (p = check->amplist; p->nid; p++) { | ||
2273 | for (ch = 0; ch < 2; ch++) { | ||
2274 | v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir, | ||
2275 | p->idx); | ||
2276 | if (!(v & HDA_AMP_MUTE) && v > 0) { | ||
2277 | if (!check->power_on) { | ||
2278 | check->power_on = 1; | ||
2279 | snd_hda_power_up(codec); | ||
2280 | } | ||
2281 | return 1; | ||
2282 | } | ||
2283 | } | ||
2284 | } | ||
2285 | if (check->power_on) { | ||
2286 | check->power_on = 0; | ||
2287 | snd_hda_power_down(codec); | ||
2288 | } | ||
2289 | return 0; | ||
2290 | } | ||
2291 | #endif | ||
1870 | 2292 | ||
1871 | /* | 2293 | /* |
1872 | * Channel mode helper | 2294 | * Channel mode helper |
@@ -1913,12 +2335,12 @@ int snd_hda_ch_mode_put(struct hda_codec *codec, | |||
1913 | 2335 | ||
1914 | mode = ucontrol->value.enumerated.item[0]; | 2336 | mode = ucontrol->value.enumerated.item[0]; |
1915 | snd_assert(mode < num_chmodes, return -EINVAL); | 2337 | snd_assert(mode < num_chmodes, return -EINVAL); |
1916 | if (*max_channelsp == chmode[mode].channels && !codec->in_resume) | 2338 | if (*max_channelsp == chmode[mode].channels) |
1917 | return 0; | 2339 | return 0; |
1918 | /* change the current channel setting */ | 2340 | /* change the current channel setting */ |
1919 | *max_channelsp = chmode[mode].channels; | 2341 | *max_channelsp = chmode[mode].channels; |
1920 | if (chmode[mode].sequence) | 2342 | if (chmode[mode].sequence) |
1921 | snd_hda_sequence_write(codec, chmode[mode].sequence); | 2343 | snd_hda_sequence_write_cache(codec, chmode[mode].sequence); |
1922 | return 1; | 2344 | return 1; |
1923 | } | 2345 | } |
1924 | 2346 | ||
@@ -1933,6 +2355,8 @@ int snd_hda_input_mux_info(const struct hda_input_mux *imux, | |||
1933 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 2355 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1934 | uinfo->count = 1; | 2356 | uinfo->count = 1; |
1935 | uinfo->value.enumerated.items = imux->num_items; | 2357 | uinfo->value.enumerated.items = imux->num_items; |
2358 | if (!imux->num_items) | ||
2359 | return 0; | ||
1936 | index = uinfo->value.enumerated.item; | 2360 | index = uinfo->value.enumerated.item; |
1937 | if (index >= imux->num_items) | 2361 | if (index >= imux->num_items) |
1938 | index = imux->num_items - 1; | 2362 | index = imux->num_items - 1; |
@@ -1948,13 +2372,15 @@ int snd_hda_input_mux_put(struct hda_codec *codec, | |||
1948 | { | 2372 | { |
1949 | unsigned int idx; | 2373 | unsigned int idx; |
1950 | 2374 | ||
2375 | if (!imux->num_items) | ||
2376 | return 0; | ||
1951 | idx = ucontrol->value.enumerated.item[0]; | 2377 | idx = ucontrol->value.enumerated.item[0]; |
1952 | if (idx >= imux->num_items) | 2378 | if (idx >= imux->num_items) |
1953 | idx = imux->num_items - 1; | 2379 | idx = imux->num_items - 1; |
1954 | if (*cur_val == idx && !codec->in_resume) | 2380 | if (*cur_val == idx) |
1955 | return 0; | 2381 | return 0; |
1956 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, | 2382 | snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, |
1957 | imux->items[idx].index); | 2383 | imux->items[idx].index); |
1958 | *cur_val = idx; | 2384 | *cur_val = idx; |
1959 | return 1; | 2385 | return 1; |
1960 | } | 2386 | } |
@@ -2118,7 +2544,7 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, | |||
2118 | * Helper for automatic ping configuration | 2544 | * Helper for automatic ping configuration |
2119 | */ | 2545 | */ |
2120 | 2546 | ||
2121 | static int __devinit is_in_nid_list(hda_nid_t nid, hda_nid_t *list) | 2547 | static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) |
2122 | { | 2548 | { |
2123 | for (; *list; list++) | 2549 | for (; *list; list++) |
2124 | if (*list == nid) | 2550 | if (*list == nid) |
@@ -2169,9 +2595,9 @@ static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences, | |||
2169 | * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, | 2595 | * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, |
2170 | * respectively. | 2596 | * respectively. |
2171 | */ | 2597 | */ |
2172 | int __devinit snd_hda_parse_pin_def_config(struct hda_codec *codec, | 2598 | int snd_hda_parse_pin_def_config(struct hda_codec *codec, |
2173 | struct auto_pin_cfg *cfg, | 2599 | struct auto_pin_cfg *cfg, |
2174 | hda_nid_t *ignore_nids) | 2600 | hda_nid_t *ignore_nids) |
2175 | { | 2601 | { |
2176 | hda_nid_t nid, nid_start; | 2602 | hda_nid_t nid, nid_start; |
2177 | int nodes; | 2603 | int nodes; |
@@ -2371,13 +2797,12 @@ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state) | |||
2371 | { | 2797 | { |
2372 | struct hda_codec *codec; | 2798 | struct hda_codec *codec; |
2373 | 2799 | ||
2374 | /* FIXME: should handle power widget capabilities */ | ||
2375 | list_for_each_entry(codec, &bus->codec_list, list) { | 2800 | list_for_each_entry(codec, &bus->codec_list, list) { |
2376 | if (codec->patch_ops.suspend) | 2801 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
2377 | codec->patch_ops.suspend(codec, state); | 2802 | if (!codec->power_on) |
2378 | hda_set_power_state(codec, | 2803 | continue; |
2379 | codec->afg ? codec->afg : codec->mfg, | 2804 | #endif |
2380 | AC_PWRST_D3); | 2805 | hda_call_codec_suspend(codec); |
2381 | } | 2806 | } |
2382 | return 0; | 2807 | return 0; |
2383 | } | 2808 | } |
@@ -2388,76 +2813,30 @@ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state) | |||
2388 | * @state: resume state | 2813 | * @state: resume state |
2389 | * | 2814 | * |
2390 | * Returns 0 if successful. | 2815 | * Returns 0 if successful. |
2816 | * | ||
2817 | * This fucntion is defined only when POWER_SAVE isn't set. | ||
2818 | * In the power-save mode, the codec is resumed dynamically. | ||
2391 | */ | 2819 | */ |
2392 | int snd_hda_resume(struct hda_bus *bus) | 2820 | int snd_hda_resume(struct hda_bus *bus) |
2393 | { | 2821 | { |
2394 | struct hda_codec *codec; | 2822 | struct hda_codec *codec; |
2395 | 2823 | ||
2396 | list_for_each_entry(codec, &bus->codec_list, list) { | 2824 | list_for_each_entry(codec, &bus->codec_list, list) { |
2397 | hda_set_power_state(codec, | 2825 | if (snd_hda_codec_needs_resume(codec)) |
2398 | codec->afg ? codec->afg : codec->mfg, | 2826 | hda_call_codec_resume(codec); |
2399 | AC_PWRST_D0); | ||
2400 | if (codec->patch_ops.resume) | ||
2401 | codec->patch_ops.resume(codec); | ||
2402 | } | 2827 | } |
2403 | return 0; | 2828 | return 0; |
2404 | } | 2829 | } |
2405 | 2830 | #ifdef CONFIG_SND_HDA_POWER_SAVE | |
2406 | /** | 2831 | int snd_hda_codecs_inuse(struct hda_bus *bus) |
2407 | * snd_hda_resume_ctls - resume controls in the new control list | ||
2408 | * @codec: the HDA codec | ||
2409 | * @knew: the array of struct snd_kcontrol_new | ||
2410 | * | ||
2411 | * This function resumes the mixer controls in the struct snd_kcontrol_new array, | ||
2412 | * originally for snd_hda_add_new_ctls(). | ||
2413 | * The array must be terminated with an empty entry as terminator. | ||
2414 | */ | ||
2415 | int snd_hda_resume_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) | ||
2416 | { | 2832 | { |
2417 | struct snd_ctl_elem_value *val; | 2833 | struct hda_codec *codec; |
2418 | 2834 | ||
2419 | val = kmalloc(sizeof(*val), GFP_KERNEL); | 2835 | list_for_each_entry(codec, &bus->codec_list, list) { |
2420 | if (!val) | 2836 | if (snd_hda_codec_needs_resume(codec)) |
2421 | return -ENOMEM; | 2837 | return 1; |
2422 | codec->in_resume = 1; | ||
2423 | for (; knew->name; knew++) { | ||
2424 | int i, count; | ||
2425 | count = knew->count ? knew->count : 1; | ||
2426 | for (i = 0; i < count; i++) { | ||
2427 | memset(val, 0, sizeof(*val)); | ||
2428 | val->id.iface = knew->iface; | ||
2429 | val->id.device = knew->device; | ||
2430 | val->id.subdevice = knew->subdevice; | ||
2431 | strcpy(val->id.name, knew->name); | ||
2432 | val->id.index = knew->index ? knew->index : i; | ||
2433 | /* Assume that get callback reads only from cache, | ||
2434 | * not accessing to the real hardware | ||
2435 | */ | ||
2436 | if (snd_ctl_elem_read(codec->bus->card, val) < 0) | ||
2437 | continue; | ||
2438 | snd_ctl_elem_write(codec->bus->card, NULL, val); | ||
2439 | } | ||
2440 | } | 2838 | } |
2441 | codec->in_resume = 0; | ||
2442 | kfree(val); | ||
2443 | return 0; | 2839 | return 0; |
2444 | } | 2840 | } |
2445 | 2841 | #endif | |
2446 | /** | ||
2447 | * snd_hda_resume_spdif_out - resume the digital out | ||
2448 | * @codec: the HDA codec | ||
2449 | */ | ||
2450 | int snd_hda_resume_spdif_out(struct hda_codec *codec) | ||
2451 | { | ||
2452 | return snd_hda_resume_ctls(codec, dig_mixes); | ||
2453 | } | ||
2454 | |||
2455 | /** | ||
2456 | * snd_hda_resume_spdif_in - resume the digital in | ||
2457 | * @codec: the HDA codec | ||
2458 | */ | ||
2459 | int snd_hda_resume_spdif_in(struct hda_codec *codec) | ||
2460 | { | ||
2461 | return snd_hda_resume_ctls(codec, dig_in_ctls); | ||
2462 | } | ||
2463 | #endif | 2842 | #endif |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 56c26e7ccdf1..2bce925d84ef 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -24,6 +24,11 @@ | |||
24 | #include <sound/info.h> | 24 | #include <sound/info.h> |
25 | #include <sound/control.h> | 25 | #include <sound/control.h> |
26 | #include <sound/pcm.h> | 26 | #include <sound/pcm.h> |
27 | #include <sound/hwdep.h> | ||
28 | |||
29 | #if defined(CONFIG_PM) || defined(CONFIG_SND_HDA_POWER_SAVE) | ||
30 | #define SND_HDA_NEEDS_RESUME /* resume control code is required */ | ||
31 | #endif | ||
27 | 32 | ||
28 | /* | 33 | /* |
29 | * nodes | 34 | * nodes |
@@ -199,7 +204,9 @@ enum { | |||
199 | #define AC_AMPCAP_OFFSET_SHIFT 0 | 204 | #define AC_AMPCAP_OFFSET_SHIFT 0 |
200 | #define AC_AMPCAP_NUM_STEPS (0x7f<<8) /* number of steps */ | 205 | #define AC_AMPCAP_NUM_STEPS (0x7f<<8) /* number of steps */ |
201 | #define AC_AMPCAP_NUM_STEPS_SHIFT 8 | 206 | #define AC_AMPCAP_NUM_STEPS_SHIFT 8 |
202 | #define AC_AMPCAP_STEP_SIZE (0x7f<<16) /* step size 0-32dB in 0.25dB */ | 207 | #define AC_AMPCAP_STEP_SIZE (0x7f<<16) /* step size 0-32dB |
208 | * in 0.25dB | ||
209 | */ | ||
203 | #define AC_AMPCAP_STEP_SIZE_SHIFT 16 | 210 | #define AC_AMPCAP_STEP_SIZE_SHIFT 16 |
204 | #define AC_AMPCAP_MUTE (1<<31) /* mute capable */ | 211 | #define AC_AMPCAP_MUTE (1<<31) /* mute capable */ |
205 | #define AC_AMPCAP_MUTE_SHIFT 31 | 212 | #define AC_AMPCAP_MUTE_SHIFT 31 |
@@ -409,6 +416,10 @@ struct hda_bus_ops { | |||
409 | unsigned int (*get_response)(struct hda_codec *codec); | 416 | unsigned int (*get_response)(struct hda_codec *codec); |
410 | /* free the private data */ | 417 | /* free the private data */ |
411 | void (*private_free)(struct hda_bus *); | 418 | void (*private_free)(struct hda_bus *); |
419 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
420 | /* notify power-up/down from codec to contoller */ | ||
421 | void (*pm_notify)(struct hda_codec *codec); | ||
422 | #endif | ||
412 | }; | 423 | }; |
413 | 424 | ||
414 | /* template to pass to the bus constructor */ | 425 | /* template to pass to the bus constructor */ |
@@ -436,7 +447,8 @@ struct hda_bus { | |||
436 | 447 | ||
437 | /* codec linked list */ | 448 | /* codec linked list */ |
438 | struct list_head codec_list; | 449 | struct list_head codec_list; |
439 | struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1]; /* caddr -> codec */ | 450 | /* link caddr -> codec */ |
451 | struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1]; | ||
440 | 452 | ||
441 | struct mutex cmd_mutex; | 453 | struct mutex cmd_mutex; |
442 | 454 | ||
@@ -469,19 +481,34 @@ struct hda_codec_ops { | |||
469 | int (*init)(struct hda_codec *codec); | 481 | int (*init)(struct hda_codec *codec); |
470 | void (*free)(struct hda_codec *codec); | 482 | void (*free)(struct hda_codec *codec); |
471 | void (*unsol_event)(struct hda_codec *codec, unsigned int res); | 483 | void (*unsol_event)(struct hda_codec *codec, unsigned int res); |
472 | #ifdef CONFIG_PM | 484 | #ifdef SND_HDA_NEEDS_RESUME |
473 | int (*suspend)(struct hda_codec *codec, pm_message_t state); | 485 | int (*suspend)(struct hda_codec *codec, pm_message_t state); |
474 | int (*resume)(struct hda_codec *codec); | 486 | int (*resume)(struct hda_codec *codec); |
475 | #endif | 487 | #endif |
488 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
489 | int (*check_power_status)(struct hda_codec *codec, hda_nid_t nid); | ||
490 | #endif | ||
476 | }; | 491 | }; |
477 | 492 | ||
478 | /* record for amp information cache */ | 493 | /* record for amp information cache */ |
479 | struct hda_amp_info { | 494 | struct hda_cache_head { |
480 | u32 key; /* hash key */ | 495 | u32 key; /* hash key */ |
496 | u16 val; /* assigned value */ | ||
497 | u16 next; /* next link; -1 = terminal */ | ||
498 | }; | ||
499 | |||
500 | struct hda_amp_info { | ||
501 | struct hda_cache_head head; | ||
481 | u32 amp_caps; /* amp capabilities */ | 502 | u32 amp_caps; /* amp capabilities */ |
482 | u16 vol[2]; /* current volume & mute */ | 503 | u16 vol[2]; /* current volume & mute */ |
483 | u16 status; /* update flag */ | 504 | }; |
484 | u16 next; /* next link */ | 505 | |
506 | struct hda_cache_rec { | ||
507 | u16 hash[64]; /* hash table for index */ | ||
508 | unsigned int num_entries; /* number of assigned entries */ | ||
509 | unsigned int size; /* allocated size */ | ||
510 | unsigned int record_size; /* record size (including header) */ | ||
511 | void *buffer; /* hash table entries */ | ||
485 | }; | 512 | }; |
486 | 513 | ||
487 | /* PCM callbacks */ | 514 | /* PCM callbacks */ |
@@ -499,7 +526,7 @@ struct hda_pcm_ops { | |||
499 | 526 | ||
500 | /* PCM information for each substream */ | 527 | /* PCM information for each substream */ |
501 | struct hda_pcm_stream { | 528 | struct hda_pcm_stream { |
502 | unsigned int substreams; /* number of substreams, 0 = not exist */ | 529 | unsigned int substreams; /* number of substreams, 0 = not exist*/ |
503 | unsigned int channels_min; /* min. number of channels */ | 530 | unsigned int channels_min; /* min. number of channels */ |
504 | unsigned int channels_max; /* max. number of channels */ | 531 | unsigned int channels_max; /* max. number of channels */ |
505 | hda_nid_t nid; /* default NID to query rates/formats/bps, or set up */ | 532 | hda_nid_t nid; /* default NID to query rates/formats/bps, or set up */ |
@@ -536,11 +563,6 @@ struct hda_codec { | |||
536 | /* set by patch */ | 563 | /* set by patch */ |
537 | struct hda_codec_ops patch_ops; | 564 | struct hda_codec_ops patch_ops; |
538 | 565 | ||
539 | /* resume phase - all controls should update even if | ||
540 | * the values are not changed | ||
541 | */ | ||
542 | unsigned int in_resume; | ||
543 | |||
544 | /* PCM to create, set by patch_ops.build_pcms callback */ | 566 | /* PCM to create, set by patch_ops.build_pcms callback */ |
545 | unsigned int num_pcms; | 567 | unsigned int num_pcms; |
546 | struct hda_pcm *pcm_info; | 568 | struct hda_pcm *pcm_info; |
@@ -553,16 +575,22 @@ struct hda_codec { | |||
553 | hda_nid_t start_nid; | 575 | hda_nid_t start_nid; |
554 | u32 *wcaps; | 576 | u32 *wcaps; |
555 | 577 | ||
556 | /* hash for amp access */ | 578 | struct hda_cache_rec amp_cache; /* cache for amp access */ |
557 | u16 amp_hash[32]; | 579 | struct hda_cache_rec cmd_cache; /* cache for other commands */ |
558 | int num_amp_entries; | ||
559 | int amp_info_size; | ||
560 | struct hda_amp_info *amp_info; | ||
561 | 580 | ||
562 | struct mutex spdif_mutex; | 581 | struct mutex spdif_mutex; |
563 | unsigned int spdif_status; /* IEC958 status bits */ | 582 | unsigned int spdif_status; /* IEC958 status bits */ |
564 | unsigned short spdif_ctls; /* SPDIF control bits */ | 583 | unsigned short spdif_ctls; /* SPDIF control bits */ |
565 | unsigned int spdif_in_enable; /* SPDIF input enable? */ | 584 | unsigned int spdif_in_enable; /* SPDIF input enable? */ |
585 | |||
586 | struct snd_hwdep *hwdep; /* assigned hwdep device */ | ||
587 | |||
588 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
589 | unsigned int power_on :1; /* current (global) power-state */ | ||
590 | unsigned int power_transition :1; /* power-state in transition */ | ||
591 | int power_count; /* current (global) power refcount */ | ||
592 | struct delayed_work power_work; /* delayed task for powerdown */ | ||
593 | #endif | ||
566 | }; | 594 | }; |
567 | 595 | ||
568 | /* direction */ | 596 | /* direction */ |
@@ -582,13 +610,17 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
582 | /* | 610 | /* |
583 | * low level functions | 611 | * low level functions |
584 | */ | 612 | */ |
585 | unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, int direct, | 613 | unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, |
614 | int direct, | ||
586 | unsigned int verb, unsigned int parm); | 615 | unsigned int verb, unsigned int parm); |
587 | int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, | 616 | int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, |
588 | unsigned int verb, unsigned int parm); | 617 | unsigned int verb, unsigned int parm); |
589 | #define snd_hda_param_read(codec, nid, param) snd_hda_codec_read(codec, nid, 0, AC_VERB_PARAMETERS, param) | 618 | #define snd_hda_param_read(codec, nid, param) \ |
590 | int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, hda_nid_t *start_id); | 619 | snd_hda_codec_read(codec, nid, 0, AC_VERB_PARAMETERS, param) |
591 | int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, hda_nid_t *conn_list, int max_conns); | 620 | int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, |
621 | hda_nid_t *start_id); | ||
622 | int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, | ||
623 | hda_nid_t *conn_list, int max_conns); | ||
592 | 624 | ||
593 | struct hda_verb { | 625 | struct hda_verb { |
594 | hda_nid_t nid; | 626 | hda_nid_t nid; |
@@ -596,11 +628,24 @@ struct hda_verb { | |||
596 | u32 param; | 628 | u32 param; |
597 | }; | 629 | }; |
598 | 630 | ||
599 | void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq); | 631 | void snd_hda_sequence_write(struct hda_codec *codec, |
632 | const struct hda_verb *seq); | ||
600 | 633 | ||
601 | /* unsolicited event */ | 634 | /* unsolicited event */ |
602 | int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex); | 635 | int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex); |
603 | 636 | ||
637 | /* cached write */ | ||
638 | #ifdef SND_HDA_NEEDS_RESUME | ||
639 | int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, | ||
640 | int direct, unsigned int verb, unsigned int parm); | ||
641 | void snd_hda_sequence_write_cache(struct hda_codec *codec, | ||
642 | const struct hda_verb *seq); | ||
643 | void snd_hda_codec_resume_cache(struct hda_codec *codec); | ||
644 | #else | ||
645 | #define snd_hda_codec_write_cache snd_hda_codec_write | ||
646 | #define snd_hda_sequence_write_cache snd_hda_sequence_write | ||
647 | #endif | ||
648 | |||
604 | /* | 649 | /* |
605 | * Mixer | 650 | * Mixer |
606 | */ | 651 | */ |
@@ -610,10 +655,13 @@ int snd_hda_build_controls(struct hda_bus *bus); | |||
610 | * PCM | 655 | * PCM |
611 | */ | 656 | */ |
612 | int snd_hda_build_pcms(struct hda_bus *bus); | 657 | int snd_hda_build_pcms(struct hda_bus *bus); |
613 | void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stream_tag, | 658 | void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, |
659 | u32 stream_tag, | ||
614 | int channel_id, int format); | 660 | int channel_id, int format); |
615 | unsigned int snd_hda_calc_stream_format(unsigned int rate, unsigned int channels, | 661 | unsigned int snd_hda_calc_stream_format(unsigned int rate, |
616 | unsigned int format, unsigned int maxbps); | 662 | unsigned int channels, |
663 | unsigned int format, | ||
664 | unsigned int maxbps); | ||
617 | int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | 665 | int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, |
618 | u32 *ratesp, u64 *formatsp, unsigned int *bpsp); | 666 | u32 *ratesp, u64 *formatsp, unsigned int *bpsp); |
619 | int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid, | 667 | int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid, |
@@ -632,4 +680,19 @@ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state); | |||
632 | int snd_hda_resume(struct hda_bus *bus); | 680 | int snd_hda_resume(struct hda_bus *bus); |
633 | #endif | 681 | #endif |
634 | 682 | ||
683 | /* | ||
684 | * power saving | ||
685 | */ | ||
686 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
687 | void snd_hda_power_up(struct hda_codec *codec); | ||
688 | void snd_hda_power_down(struct hda_codec *codec); | ||
689 | #define snd_hda_codec_needs_resume(codec) codec->power_count | ||
690 | int snd_hda_codecs_inuse(struct hda_bus *bus); | ||
691 | #else | ||
692 | static inline void snd_hda_power_up(struct hda_codec *codec) {} | ||
693 | static inline void snd_hda_power_down(struct hda_codec *codec) {} | ||
694 | #define snd_hda_codec_needs_resume(codec) 1 | ||
695 | #define snd_hda_codecs_inuse(bus) 1 | ||
696 | #endif | ||
697 | |||
635 | #endif /* __SOUND_HDA_CODEC_H */ | 698 | #endif /* __SOUND_HDA_CODEC_H */ |
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 000287f7da43..c957eb58de5c 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -70,6 +70,13 @@ struct hda_gspec { | |||
70 | struct hda_pcm pcm_rec; /* PCM information */ | 70 | struct hda_pcm pcm_rec; /* PCM information */ |
71 | 71 | ||
72 | struct list_head nid_list; /* list of widgets */ | 72 | struct list_head nid_list; /* list of widgets */ |
73 | |||
74 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
75 | #define MAX_LOOPBACK_AMPS 7 | ||
76 | struct hda_loopback_check loopback; | ||
77 | int num_loopbacks; | ||
78 | struct hda_amp_list loopback_list[MAX_LOOPBACK_AMPS + 1]; | ||
79 | #endif | ||
73 | }; | 80 | }; |
74 | 81 | ||
75 | /* | 82 | /* |
@@ -88,13 +95,12 @@ struct hda_gspec { | |||
88 | static void snd_hda_generic_free(struct hda_codec *codec) | 95 | static void snd_hda_generic_free(struct hda_codec *codec) |
89 | { | 96 | { |
90 | struct hda_gspec *spec = codec->spec; | 97 | struct hda_gspec *spec = codec->spec; |
91 | struct list_head *p, *n; | 98 | struct hda_gnode *node, *n; |
92 | 99 | ||
93 | if (! spec) | 100 | if (! spec) |
94 | return; | 101 | return; |
95 | /* free all widgets */ | 102 | /* free all widgets */ |
96 | list_for_each_safe(p, n, &spec->nid_list) { | 103 | list_for_each_entry_safe(node, n, &spec->nid_list, list) { |
97 | struct hda_gnode *node = list_entry(p, struct hda_gnode, list); | ||
98 | if (node->conn_list != node->slist) | 104 | if (node->conn_list != node->slist) |
99 | kfree(node->conn_list); | 105 | kfree(node->conn_list); |
100 | kfree(node); | 106 | kfree(node); |
@@ -196,11 +202,9 @@ static int build_afg_tree(struct hda_codec *codec) | |||
196 | /* FIXME: should avoid the braindead linear search */ | 202 | /* FIXME: should avoid the braindead linear search */ |
197 | static struct hda_gnode *hda_get_node(struct hda_gspec *spec, hda_nid_t nid) | 203 | static struct hda_gnode *hda_get_node(struct hda_gspec *spec, hda_nid_t nid) |
198 | { | 204 | { |
199 | struct list_head *p; | ||
200 | struct hda_gnode *node; | 205 | struct hda_gnode *node; |
201 | 206 | ||
202 | list_for_each(p, &spec->nid_list) { | 207 | list_for_each_entry(node, &spec->nid_list, list) { |
203 | node = list_entry(p, struct hda_gnode, list); | ||
204 | if (node->nid == nid) | 208 | if (node->nid == nid) |
205 | return node; | 209 | return node; |
206 | } | 210 | } |
@@ -218,9 +222,8 @@ static int unmute_output(struct hda_codec *codec, struct hda_gnode *node) | |||
218 | ofs = (node->amp_out_caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT; | 222 | ofs = (node->amp_out_caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT; |
219 | if (val >= ofs) | 223 | if (val >= ofs) |
220 | val -= ofs; | 224 | val -= ofs; |
221 | val |= AC_AMP_SET_LEFT | AC_AMP_SET_RIGHT; | 225 | snd_hda_codec_amp_stereo(codec, node->nid, HDA_OUTPUT, 0, 0xff, val); |
222 | val |= AC_AMP_SET_OUTPUT; | 226 | return 0; |
223 | return snd_hda_codec_write(codec, node->nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, val); | ||
224 | } | 227 | } |
225 | 228 | ||
226 | /* | 229 | /* |
@@ -234,11 +237,8 @@ static int unmute_input(struct hda_codec *codec, struct hda_gnode *node, unsigne | |||
234 | ofs = (node->amp_in_caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT; | 237 | ofs = (node->amp_in_caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT; |
235 | if (val >= ofs) | 238 | if (val >= ofs) |
236 | val -= ofs; | 239 | val -= ofs; |
237 | val |= AC_AMP_SET_LEFT | AC_AMP_SET_RIGHT; | 240 | snd_hda_codec_amp_stereo(codec, node->nid, HDA_INPUT, index, 0xff, val); |
238 | val |= AC_AMP_SET_INPUT; | 241 | return 0; |
239 | // awk added - fixed to allow unmuting of indexed amps | ||
240 | val |= index << AC_AMP_SET_INDEX_SHIFT; | ||
241 | return snd_hda_codec_write(codec, node->nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, val); | ||
242 | } | 242 | } |
243 | 243 | ||
244 | /* | 244 | /* |
@@ -248,7 +248,8 @@ static int select_input_connection(struct hda_codec *codec, struct hda_gnode *no | |||
248 | unsigned int index) | 248 | unsigned int index) |
249 | { | 249 | { |
250 | snd_printdd("CONNECT: NID=0x%x IDX=0x%x\n", node->nid, index); | 250 | snd_printdd("CONNECT: NID=0x%x IDX=0x%x\n", node->nid, index); |
251 | return snd_hda_codec_write(codec, node->nid, 0, AC_VERB_SET_CONNECT_SEL, index); | 251 | return snd_hda_codec_write_cache(codec, node->nid, 0, |
252 | AC_VERB_SET_CONNECT_SEL, index); | ||
252 | } | 253 | } |
253 | 254 | ||
254 | /* | 255 | /* |
@@ -256,11 +257,9 @@ static int select_input_connection(struct hda_codec *codec, struct hda_gnode *no | |||
256 | */ | 257 | */ |
257 | static void clear_check_flags(struct hda_gspec *spec) | 258 | static void clear_check_flags(struct hda_gspec *spec) |
258 | { | 259 | { |
259 | struct list_head *p; | ||
260 | struct hda_gnode *node; | 260 | struct hda_gnode *node; |
261 | 261 | ||
262 | list_for_each(p, &spec->nid_list) { | 262 | list_for_each_entry(node, &spec->nid_list, list) { |
263 | node = list_entry(p, struct hda_gnode, list); | ||
264 | node->checked = 0; | 263 | node->checked = 0; |
265 | } | 264 | } |
266 | } | 265 | } |
@@ -343,12 +342,10 @@ static struct hda_gnode *parse_output_jack(struct hda_codec *codec, | |||
343 | struct hda_gspec *spec, | 342 | struct hda_gspec *spec, |
344 | int jack_type) | 343 | int jack_type) |
345 | { | 344 | { |
346 | struct list_head *p; | ||
347 | struct hda_gnode *node; | 345 | struct hda_gnode *node; |
348 | int err; | 346 | int err; |
349 | 347 | ||
350 | list_for_each(p, &spec->nid_list) { | 348 | list_for_each_entry(node, &spec->nid_list, list) { |
351 | node = list_entry(p, struct hda_gnode, list); | ||
352 | if (node->type != AC_WID_PIN) | 349 | if (node->type != AC_WID_PIN) |
353 | continue; | 350 | continue; |
354 | /* output capable? */ | 351 | /* output capable? */ |
@@ -379,7 +376,7 @@ static struct hda_gnode *parse_output_jack(struct hda_codec *codec, | |||
379 | /* unmute the PIN output */ | 376 | /* unmute the PIN output */ |
380 | unmute_output(codec, node); | 377 | unmute_output(codec, node); |
381 | /* set PIN-Out enable */ | 378 | /* set PIN-Out enable */ |
382 | snd_hda_codec_write(codec, node->nid, 0, | 379 | snd_hda_codec_write_cache(codec, node->nid, 0, |
383 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 380 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
384 | AC_PINCTL_OUT_EN | | 381 | AC_PINCTL_OUT_EN | |
385 | ((node->pin_caps & AC_PINCAP_HP_DRV) ? | 382 | ((node->pin_caps & AC_PINCAP_HP_DRV) ? |
@@ -570,7 +567,8 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec, | |||
570 | /* unmute the PIN external input */ | 567 | /* unmute the PIN external input */ |
571 | unmute_input(codec, node, 0); /* index = 0? */ | 568 | unmute_input(codec, node, 0); /* index = 0? */ |
572 | /* set PIN-In enable */ | 569 | /* set PIN-In enable */ |
573 | snd_hda_codec_write(codec, node->nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl); | 570 | snd_hda_codec_write_cache(codec, node->nid, 0, |
571 | AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl); | ||
574 | 572 | ||
575 | return 1; /* found */ | 573 | return 1; /* found */ |
576 | } | 574 | } |
@@ -659,7 +657,6 @@ static int parse_input_path(struct hda_codec *codec, struct hda_gnode *adc_node) | |||
659 | static int parse_input(struct hda_codec *codec) | 657 | static int parse_input(struct hda_codec *codec) |
660 | { | 658 | { |
661 | struct hda_gspec *spec = codec->spec; | 659 | struct hda_gspec *spec = codec->spec; |
662 | struct list_head *p; | ||
663 | struct hda_gnode *node; | 660 | struct hda_gnode *node; |
664 | int err; | 661 | int err; |
665 | 662 | ||
@@ -668,8 +665,7 @@ static int parse_input(struct hda_codec *codec) | |||
668 | * If it reaches to certain input PINs, we take it as the | 665 | * If it reaches to certain input PINs, we take it as the |
669 | * input path. | 666 | * input path. |
670 | */ | 667 | */ |
671 | list_for_each(p, &spec->nid_list) { | 668 | list_for_each_entry(node, &spec->nid_list, list) { |
672 | node = list_entry(p, struct hda_gnode, list); | ||
673 | if (node->wid_caps & AC_WCAP_DIGITAL) | 669 | if (node->wid_caps & AC_WCAP_DIGITAL) |
674 | continue; /* skip SPDIF */ | 670 | continue; /* skip SPDIF */ |
675 | if (node->type == AC_WID_AUD_IN) { | 671 | if (node->type == AC_WID_AUD_IN) { |
@@ -684,11 +680,33 @@ static int parse_input(struct hda_codec *codec) | |||
684 | return 0; | 680 | return 0; |
685 | } | 681 | } |
686 | 682 | ||
683 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
684 | static void add_input_loopback(struct hda_codec *codec, hda_nid_t nid, | ||
685 | int dir, int idx) | ||
686 | { | ||
687 | struct hda_gspec *spec = codec->spec; | ||
688 | struct hda_amp_list *p; | ||
689 | |||
690 | if (spec->num_loopbacks >= MAX_LOOPBACK_AMPS) { | ||
691 | snd_printk(KERN_ERR "hda_generic: Too many loopback ctls\n"); | ||
692 | return; | ||
693 | } | ||
694 | p = &spec->loopback_list[spec->num_loopbacks++]; | ||
695 | p->nid = nid; | ||
696 | p->dir = dir; | ||
697 | p->idx = idx; | ||
698 | spec->loopback.amplist = spec->loopback_list; | ||
699 | } | ||
700 | #else | ||
701 | #define add_input_loopback(codec,nid,dir,idx) | ||
702 | #endif | ||
703 | |||
687 | /* | 704 | /* |
688 | * create mixer controls if possible | 705 | * create mixer controls if possible |
689 | */ | 706 | */ |
690 | static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, | 707 | static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, |
691 | unsigned int index, const char *type, const char *dir_sfx) | 708 | unsigned int index, const char *type, |
709 | const char *dir_sfx, int is_loopback) | ||
692 | { | 710 | { |
693 | char name[32]; | 711 | char name[32]; |
694 | int err; | 712 | int err; |
@@ -702,6 +720,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, | |||
702 | if ((node->wid_caps & AC_WCAP_IN_AMP) && | 720 | if ((node->wid_caps & AC_WCAP_IN_AMP) && |
703 | (node->amp_in_caps & AC_AMPCAP_MUTE)) { | 721 | (node->amp_in_caps & AC_AMPCAP_MUTE)) { |
704 | knew = (struct snd_kcontrol_new)HDA_CODEC_MUTE(name, node->nid, index, HDA_INPUT); | 722 | knew = (struct snd_kcontrol_new)HDA_CODEC_MUTE(name, node->nid, index, HDA_INPUT); |
723 | if (is_loopback) | ||
724 | add_input_loopback(codec, node->nid, HDA_INPUT, index); | ||
705 | snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index); | 725 | snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index); |
706 | if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) | 726 | if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) |
707 | return err; | 727 | return err; |
@@ -709,6 +729,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, | |||
709 | } else if ((node->wid_caps & AC_WCAP_OUT_AMP) && | 729 | } else if ((node->wid_caps & AC_WCAP_OUT_AMP) && |
710 | (node->amp_out_caps & AC_AMPCAP_MUTE)) { | 730 | (node->amp_out_caps & AC_AMPCAP_MUTE)) { |
711 | knew = (struct snd_kcontrol_new)HDA_CODEC_MUTE(name, node->nid, 0, HDA_OUTPUT); | 731 | knew = (struct snd_kcontrol_new)HDA_CODEC_MUTE(name, node->nid, 0, HDA_OUTPUT); |
732 | if (is_loopback) | ||
733 | add_input_loopback(codec, node->nid, HDA_OUTPUT, 0); | ||
712 | snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid); | 734 | snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid); |
713 | if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) | 735 | if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0) |
714 | return err; | 736 | return err; |
@@ -767,7 +789,7 @@ static int create_output_mixers(struct hda_codec *codec, const char **names) | |||
767 | for (i = 0; i < spec->pcm_vol_nodes; i++) { | 789 | for (i = 0; i < spec->pcm_vol_nodes; i++) { |
768 | err = create_mixer(codec, spec->pcm_vol[i].node, | 790 | err = create_mixer(codec, spec->pcm_vol[i].node, |
769 | spec->pcm_vol[i].index, | 791 | spec->pcm_vol[i].index, |
770 | names[i], "Playback"); | 792 | names[i], "Playback", 0); |
771 | if (err < 0) | 793 | if (err < 0) |
772 | return err; | 794 | return err; |
773 | } | 795 | } |
@@ -784,7 +806,7 @@ static int build_output_controls(struct hda_codec *codec) | |||
784 | case 1: | 806 | case 1: |
785 | return create_mixer(codec, spec->pcm_vol[0].node, | 807 | return create_mixer(codec, spec->pcm_vol[0].node, |
786 | spec->pcm_vol[0].index, | 808 | spec->pcm_vol[0].index, |
787 | "Master", "Playback"); | 809 | "Master", "Playback", 0); |
788 | case 2: | 810 | case 2: |
789 | if (defcfg_type(spec->out_pin_node[0]) == AC_JACK_SPEAKER) | 811 | if (defcfg_type(spec->out_pin_node[0]) == AC_JACK_SPEAKER) |
790 | return create_output_mixers(codec, types_speaker); | 812 | return create_output_mixers(codec, types_speaker); |
@@ -820,7 +842,7 @@ static int build_input_controls(struct hda_codec *codec) | |||
820 | if (spec->input_mux.num_items == 1) { | 842 | if (spec->input_mux.num_items == 1) { |
821 | err = create_mixer(codec, adc_node, | 843 | err = create_mixer(codec, adc_node, |
822 | spec->input_mux.items[0].index, | 844 | spec->input_mux.items[0].index, |
823 | NULL, "Capture"); | 845 | NULL, "Capture", 0); |
824 | if (err < 0) | 846 | if (err < 0) |
825 | return err; | 847 | return err; |
826 | return 0; | 848 | return 0; |
@@ -886,7 +908,8 @@ static int parse_loopback_path(struct hda_codec *codec, struct hda_gspec *spec, | |||
886 | return err; | 908 | return err; |
887 | else if (err >= 1) { | 909 | else if (err >= 1) { |
888 | if (err == 1) { | 910 | if (err == 1) { |
889 | err = create_mixer(codec, node, i, type, "Playback"); | 911 | err = create_mixer(codec, node, i, type, |
912 | "Playback", 1); | ||
890 | if (err < 0) | 913 | if (err < 0) |
891 | return err; | 914 | return err; |
892 | if (err > 0) | 915 | if (err > 0) |
@@ -911,7 +934,6 @@ static int parse_loopback_path(struct hda_codec *codec, struct hda_gspec *spec, | |||
911 | static int build_loopback_controls(struct hda_codec *codec) | 934 | static int build_loopback_controls(struct hda_codec *codec) |
912 | { | 935 | { |
913 | struct hda_gspec *spec = codec->spec; | 936 | struct hda_gspec *spec = codec->spec; |
914 | struct list_head *p; | ||
915 | struct hda_gnode *node; | 937 | struct hda_gnode *node; |
916 | int err; | 938 | int err; |
917 | const char *type; | 939 | const char *type; |
@@ -919,8 +941,7 @@ static int build_loopback_controls(struct hda_codec *codec) | |||
919 | if (! spec->out_pin_node[0]) | 941 | if (! spec->out_pin_node[0]) |
920 | return 0; | 942 | return 0; |
921 | 943 | ||
922 | list_for_each(p, &spec->nid_list) { | 944 | list_for_each_entry(node, &spec->nid_list, list) { |
923 | node = list_entry(p, struct hda_gnode, list); | ||
924 | if (node->type != AC_WID_PIN) | 945 | if (node->type != AC_WID_PIN) |
925 | continue; | 946 | continue; |
926 | /* input capable? */ | 947 | /* input capable? */ |
@@ -1022,6 +1043,14 @@ static int build_generic_pcms(struct hda_codec *codec) | |||
1022 | return 0; | 1043 | return 0; |
1023 | } | 1044 | } |
1024 | 1045 | ||
1046 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1047 | static int generic_check_power_status(struct hda_codec *codec, hda_nid_t nid) | ||
1048 | { | ||
1049 | struct hda_gspec *spec = codec->spec; | ||
1050 | return snd_hda_check_amp_list_power(codec, &spec->loopback, nid); | ||
1051 | } | ||
1052 | #endif | ||
1053 | |||
1025 | 1054 | ||
1026 | /* | 1055 | /* |
1027 | */ | 1056 | */ |
@@ -1029,6 +1058,9 @@ static struct hda_codec_ops generic_patch_ops = { | |||
1029 | .build_controls = build_generic_controls, | 1058 | .build_controls = build_generic_controls, |
1030 | .build_pcms = build_generic_pcms, | 1059 | .build_pcms = build_generic_pcms, |
1031 | .free = snd_hda_generic_free, | 1060 | .free = snd_hda_generic_free, |
1061 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1062 | .check_power_status = generic_check_power_status, | ||
1063 | #endif | ||
1032 | }; | 1064 | }; |
1033 | 1065 | ||
1034 | /* | 1066 | /* |
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c new file mode 100644 index 000000000000..bafb7b01f5a1 --- /dev/null +++ b/sound/pci/hda/hda_hwdep.c | |||
@@ -0,0 +1,122 @@ | |||
1 | /* | ||
2 | * HWDEP Interface for HD-audio codec | ||
3 | * | ||
4 | * Copyright (c) 2007 Takashi Iwai <tiwai@suse.de> | ||
5 | * | ||
6 | * This driver is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This driver is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <sound/driver.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/pci.h> | ||
25 | #include <linux/compat.h> | ||
26 | #include <linux/mutex.h> | ||
27 | #include <sound/core.h> | ||
28 | #include "hda_codec.h" | ||
29 | #include "hda_local.h" | ||
30 | #include <sound/hda_hwdep.h> | ||
31 | |||
32 | /* | ||
33 | * write/read an out-of-bound verb | ||
34 | */ | ||
35 | static int verb_write_ioctl(struct hda_codec *codec, | ||
36 | struct hda_verb_ioctl __user *arg) | ||
37 | { | ||
38 | u32 verb, res; | ||
39 | |||
40 | if (get_user(verb, &arg->verb)) | ||
41 | return -EFAULT; | ||
42 | res = snd_hda_codec_read(codec, verb >> 24, 0, | ||
43 | (verb >> 8) & 0xffff, verb & 0xff); | ||
44 | if (put_user(res, &arg->res)) | ||
45 | return -EFAULT; | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | static int get_wcap_ioctl(struct hda_codec *codec, | ||
50 | struct hda_verb_ioctl __user *arg) | ||
51 | { | ||
52 | u32 verb, res; | ||
53 | |||
54 | if (get_user(verb, &arg->verb)) | ||
55 | return -EFAULT; | ||
56 | res = get_wcaps(codec, verb >> 24); | ||
57 | if (put_user(res, &arg->res)) | ||
58 | return -EFAULT; | ||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | |||
63 | /* | ||
64 | */ | ||
65 | static int hda_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, | ||
66 | unsigned int cmd, unsigned long arg) | ||
67 | { | ||
68 | struct hda_codec *codec = hw->private_data; | ||
69 | void __user *argp = (void __user *)arg; | ||
70 | |||
71 | switch (cmd) { | ||
72 | case HDA_IOCTL_PVERSION: | ||
73 | return put_user(HDA_HWDEP_VERSION, (int __user *)argp); | ||
74 | case HDA_IOCTL_VERB_WRITE: | ||
75 | return verb_write_ioctl(codec, argp); | ||
76 | case HDA_IOCTL_GET_WCAP: | ||
77 | return get_wcap_ioctl(codec, argp); | ||
78 | } | ||
79 | return -ENOIOCTLCMD; | ||
80 | } | ||
81 | |||
82 | #ifdef CONFIG_COMPAT | ||
83 | static int hda_hwdep_ioctl_compat(struct snd_hwdep *hw, struct file *file, | ||
84 | unsigned int cmd, unsigned long arg) | ||
85 | { | ||
86 | return hda_hwdep_ioctl(hw, file, cmd, (unsigned long)compat_ptr(arg)); | ||
87 | } | ||
88 | #endif | ||
89 | |||
90 | static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file) | ||
91 | { | ||
92 | #ifndef CONFIG_SND_DEBUG_DETECT | ||
93 | if (!capable(CAP_SYS_RAWIO)) | ||
94 | return -EACCES; | ||
95 | #endif | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | int __devinit snd_hda_create_hwdep(struct hda_codec *codec) | ||
100 | { | ||
101 | char hwname[16]; | ||
102 | struct snd_hwdep *hwdep; | ||
103 | int err; | ||
104 | |||
105 | sprintf(hwname, "HDA Codec %d", codec->addr); | ||
106 | err = snd_hwdep_new(codec->bus->card, hwname, codec->addr, &hwdep); | ||
107 | if (err < 0) | ||
108 | return err; | ||
109 | codec->hwdep = hwdep; | ||
110 | sprintf(hwdep->name, "HDA Codec %d", codec->addr); | ||
111 | hwdep->iface = SNDRV_HWDEP_IFACE_HDA; | ||
112 | hwdep->private_data = codec; | ||
113 | hwdep->exclusive = 1; | ||
114 | |||
115 | hwdep->ops.open = hda_hwdep_open; | ||
116 | hwdep->ops.ioctl = hda_hwdep_ioctl; | ||
117 | #ifdef CONFIG_COMPAT | ||
118 | hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat; | ||
119 | #endif | ||
120 | |||
121 | return 0; | ||
122 | } | ||
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 92bc8b3fa2a0..3fa0f9704909 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * | 2 | * |
3 | * hda_intel.c - Implementation of primary alsa driver code base for Intel HD Audio. | 3 | * hda_intel.c - Implementation of primary alsa driver code base |
4 | * for Intel HD Audio. | ||
4 | * | 5 | * |
5 | * Copyright(c) 2004 Intel Corporation. All rights reserved. | 6 | * Copyright(c) 2004 Intel Corporation. All rights reserved. |
6 | * | 7 | * |
@@ -64,14 +65,27 @@ MODULE_PARM_DESC(id, "ID string for Intel HD audio interface."); | |||
64 | module_param(model, charp, 0444); | 65 | module_param(model, charp, 0444); |
65 | MODULE_PARM_DESC(model, "Use the given board model."); | 66 | MODULE_PARM_DESC(model, "Use the given board model."); |
66 | module_param(position_fix, int, 0444); | 67 | module_param(position_fix, int, 0444); |
67 | MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size)."); | 68 | MODULE_PARM_DESC(position_fix, "Fix DMA pointer " |
69 | "(0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size)."); | ||
68 | module_param(probe_mask, int, 0444); | 70 | module_param(probe_mask, int, 0444); |
69 | MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1)."); | 71 | MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1)."); |
70 | module_param(single_cmd, bool, 0444); | 72 | module_param(single_cmd, bool, 0444); |
71 | MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs (for debugging only)."); | 73 | MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs " |
74 | "(for debugging only)."); | ||
72 | module_param(enable_msi, int, 0); | 75 | module_param(enable_msi, int, 0); |
73 | MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)"); | 76 | MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)"); |
74 | 77 | ||
78 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
79 | /* power_save option is defined in hda_codec.c */ | ||
80 | |||
81 | /* reset the HD-audio controller in power save mode. | ||
82 | * this may give more power-saving, but will take longer time to | ||
83 | * wake up. | ||
84 | */ | ||
85 | static int power_save_controller = 1; | ||
86 | module_param(power_save_controller, bool, 0644); | ||
87 | MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode."); | ||
88 | #endif | ||
75 | 89 | ||
76 | /* just for backward compatibility */ | 90 | /* just for backward compatibility */ |
77 | static int enable; | 91 | static int enable; |
@@ -98,6 +112,7 @@ MODULE_DESCRIPTION("Intel HDA driver"); | |||
98 | 112 | ||
99 | #define SFX "hda-intel: " | 113 | #define SFX "hda-intel: " |
100 | 114 | ||
115 | |||
101 | /* | 116 | /* |
102 | * registers | 117 | * registers |
103 | */ | 118 | */ |
@@ -213,15 +228,16 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
213 | #define SD_INT_DESC_ERR 0x10 /* descriptor error interrupt */ | 228 | #define SD_INT_DESC_ERR 0x10 /* descriptor error interrupt */ |
214 | #define SD_INT_FIFO_ERR 0x08 /* FIFO error interrupt */ | 229 | #define SD_INT_FIFO_ERR 0x08 /* FIFO error interrupt */ |
215 | #define SD_INT_COMPLETE 0x04 /* completion interrupt */ | 230 | #define SD_INT_COMPLETE 0x04 /* completion interrupt */ |
216 | #define SD_INT_MASK (SD_INT_DESC_ERR|SD_INT_FIFO_ERR|SD_INT_COMPLETE) | 231 | #define SD_INT_MASK (SD_INT_DESC_ERR|SD_INT_FIFO_ERR|\ |
232 | SD_INT_COMPLETE) | ||
217 | 233 | ||
218 | /* SD_STS */ | 234 | /* SD_STS */ |
219 | #define SD_STS_FIFO_READY 0x20 /* FIFO ready */ | 235 | #define SD_STS_FIFO_READY 0x20 /* FIFO ready */ |
220 | 236 | ||
221 | /* INTCTL and INTSTS */ | 237 | /* INTCTL and INTSTS */ |
222 | #define ICH6_INT_ALL_STREAM 0xff /* all stream interrupts */ | 238 | #define ICH6_INT_ALL_STREAM 0xff /* all stream interrupts */ |
223 | #define ICH6_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */ | 239 | #define ICH6_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */ |
224 | #define ICH6_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */ | 240 | #define ICH6_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */ |
225 | 241 | ||
226 | /* GCTL unsolicited response enable bit */ | 242 | /* GCTL unsolicited response enable bit */ |
227 | #define ICH6_GCTL_UREN (1<<8) | 243 | #define ICH6_GCTL_UREN (1<<8) |
@@ -257,22 +273,26 @@ enum { | |||
257 | */ | 273 | */ |
258 | 274 | ||
259 | struct azx_dev { | 275 | struct azx_dev { |
260 | u32 *bdl; /* virtual address of the BDL */ | 276 | u32 *bdl; /* virtual address of the BDL */ |
261 | dma_addr_t bdl_addr; /* physical address of the BDL */ | 277 | dma_addr_t bdl_addr; /* physical address of the BDL */ |
262 | u32 *posbuf; /* position buffer pointer */ | 278 | u32 *posbuf; /* position buffer pointer */ |
263 | 279 | ||
264 | unsigned int bufsize; /* size of the play buffer in bytes */ | 280 | unsigned int bufsize; /* size of the play buffer in bytes */ |
265 | unsigned int fragsize; /* size of each period in bytes */ | 281 | unsigned int fragsize; /* size of each period in bytes */ |
266 | unsigned int frags; /* number for period in the play buffer */ | 282 | unsigned int frags; /* number for period in the play buffer */ |
267 | unsigned int fifo_size; /* FIFO size */ | 283 | unsigned int fifo_size; /* FIFO size */ |
268 | 284 | ||
269 | void __iomem *sd_addr; /* stream descriptor pointer */ | 285 | void __iomem *sd_addr; /* stream descriptor pointer */ |
270 | 286 | ||
271 | u32 sd_int_sta_mask; /* stream int status mask */ | 287 | u32 sd_int_sta_mask; /* stream int status mask */ |
272 | 288 | ||
273 | /* pcm support */ | 289 | /* pcm support */ |
274 | struct snd_pcm_substream *substream; /* assigned substream, set in PCM open */ | 290 | struct snd_pcm_substream *substream; /* assigned substream, |
275 | unsigned int format_val; /* format value to be set in the controller and the codec */ | 291 | * set in PCM open |
292 | */ | ||
293 | unsigned int format_val; /* format value to be set in the | ||
294 | * controller and the codec | ||
295 | */ | ||
276 | unsigned char stream_tag; /* assigned stream */ | 296 | unsigned char stream_tag; /* assigned stream */ |
277 | unsigned char index; /* stream index */ | 297 | unsigned char index; /* stream index */ |
278 | /* for sanity check of position buffer */ | 298 | /* for sanity check of position buffer */ |
@@ -337,6 +357,7 @@ struct azx { | |||
337 | 357 | ||
338 | /* flags */ | 358 | /* flags */ |
339 | int position_fix; | 359 | int position_fix; |
360 | unsigned int running :1; | ||
340 | unsigned int initialized :1; | 361 | unsigned int initialized :1; |
341 | unsigned int single_cmd :1; | 362 | unsigned int single_cmd :1; |
342 | unsigned int polling_mode :1; | 363 | unsigned int polling_mode :1; |
@@ -418,7 +439,8 @@ static int azx_alloc_cmd_io(struct azx *chip) | |||
418 | int err; | 439 | int err; |
419 | 440 | ||
420 | /* single page (at least 4096 bytes) must suffice for both ringbuffes */ | 441 | /* single page (at least 4096 bytes) must suffice for both ringbuffes */ |
421 | err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), | 442 | err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, |
443 | snd_dma_pci_data(chip->pci), | ||
422 | PAGE_SIZE, &chip->rb); | 444 | PAGE_SIZE, &chip->rb); |
423 | if (err < 0) { | 445 | if (err < 0) { |
424 | snd_printk(KERN_ERR SFX "cannot allocate CORB/RIRB\n"); | 446 | snd_printk(KERN_ERR SFX "cannot allocate CORB/RIRB\n"); |
@@ -531,9 +553,9 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec) | |||
531 | azx_update_rirb(chip); | 553 | azx_update_rirb(chip); |
532 | spin_unlock_irq(&chip->reg_lock); | 554 | spin_unlock_irq(&chip->reg_lock); |
533 | } | 555 | } |
534 | if (! chip->rirb.cmds) | 556 | if (!chip->rirb.cmds) |
535 | return chip->rirb.res; /* the last value */ | 557 | return chip->rirb.res; /* the last value */ |
536 | schedule_timeout(1); | 558 | schedule_timeout_uninterruptible(1); |
537 | } while (time_after_eq(timeout, jiffies)); | 559 | } while (time_after_eq(timeout, jiffies)); |
538 | 560 | ||
539 | if (chip->msi) { | 561 | if (chip->msi) { |
@@ -585,16 +607,19 @@ static int azx_single_send_cmd(struct hda_codec *codec, u32 val) | |||
585 | 607 | ||
586 | while (timeout--) { | 608 | while (timeout--) { |
587 | /* check ICB busy bit */ | 609 | /* check ICB busy bit */ |
588 | if (! (azx_readw(chip, IRS) & ICH6_IRS_BUSY)) { | 610 | if (!((azx_readw(chip, IRS) & ICH6_IRS_BUSY))) { |
589 | /* Clear IRV valid bit */ | 611 | /* Clear IRV valid bit */ |
590 | azx_writew(chip, IRS, azx_readw(chip, IRS) | ICH6_IRS_VALID); | 612 | azx_writew(chip, IRS, azx_readw(chip, IRS) | |
613 | ICH6_IRS_VALID); | ||
591 | azx_writel(chip, IC, val); | 614 | azx_writel(chip, IC, val); |
592 | azx_writew(chip, IRS, azx_readw(chip, IRS) | ICH6_IRS_BUSY); | 615 | azx_writew(chip, IRS, azx_readw(chip, IRS) | |
616 | ICH6_IRS_BUSY); | ||
593 | return 0; | 617 | return 0; |
594 | } | 618 | } |
595 | udelay(1); | 619 | udelay(1); |
596 | } | 620 | } |
597 | snd_printd(SFX "send_cmd timeout: IRS=0x%x, val=0x%x\n", azx_readw(chip, IRS), val); | 621 | snd_printd(SFX "send_cmd timeout: IRS=0x%x, val=0x%x\n", |
622 | azx_readw(chip, IRS), val); | ||
598 | return -EIO; | 623 | return -EIO; |
599 | } | 624 | } |
600 | 625 | ||
@@ -610,7 +635,8 @@ static unsigned int azx_single_get_response(struct hda_codec *codec) | |||
610 | return azx_readl(chip, IR); | 635 | return azx_readl(chip, IR); |
611 | udelay(1); | 636 | udelay(1); |
612 | } | 637 | } |
613 | snd_printd(SFX "get_response timeout: IRS=0x%x\n", azx_readw(chip, IRS)); | 638 | snd_printd(SFX "get_response timeout: IRS=0x%x\n", |
639 | azx_readw(chip, IRS)); | ||
614 | return (unsigned int)-1; | 640 | return (unsigned int)-1; |
615 | } | 641 | } |
616 | 642 | ||
@@ -652,12 +678,18 @@ static unsigned int azx_get_response(struct hda_codec *codec) | |||
652 | return azx_rirb_get_response(codec); | 678 | return azx_rirb_get_response(codec); |
653 | } | 679 | } |
654 | 680 | ||
681 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
682 | static void azx_power_notify(struct hda_codec *codec); | ||
683 | #endif | ||
655 | 684 | ||
656 | /* reset codec link */ | 685 | /* reset codec link */ |
657 | static int azx_reset(struct azx *chip) | 686 | static int azx_reset(struct azx *chip) |
658 | { | 687 | { |
659 | int count; | 688 | int count; |
660 | 689 | ||
690 | /* clear STATESTS */ | ||
691 | azx_writeb(chip, STATESTS, STATESTS_INT_MASK); | ||
692 | |||
661 | /* reset controller */ | 693 | /* reset controller */ |
662 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_RESET); | 694 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_RESET); |
663 | 695 | ||
@@ -777,18 +809,12 @@ static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev) | |||
777 | 809 | ||
778 | 810 | ||
779 | /* | 811 | /* |
780 | * initialize the chip | 812 | * reset and start the controller registers |
781 | */ | 813 | */ |
782 | static void azx_init_chip(struct azx *chip) | 814 | static void azx_init_chip(struct azx *chip) |
783 | { | 815 | { |
784 | unsigned char reg; | 816 | if (chip->initialized) |
785 | 817 | return; | |
786 | /* Clear bits 0-2 of PCI register TCSEL (at offset 0x44) | ||
787 | * TCSEL == Traffic Class Select Register, which sets PCI express QOS | ||
788 | * Ensuring these bits are 0 clears playback static on some HD Audio codecs | ||
789 | */ | ||
790 | pci_read_config_byte (chip->pci, ICH6_PCIREG_TCSEL, ®); | ||
791 | pci_write_config_byte(chip->pci, ICH6_PCIREG_TCSEL, reg & 0xf8); | ||
792 | 818 | ||
793 | /* reset controller */ | 819 | /* reset controller */ |
794 | azx_reset(chip); | 820 | azx_reset(chip); |
@@ -805,19 +831,45 @@ static void azx_init_chip(struct azx *chip) | |||
805 | azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); | 831 | azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); |
806 | azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr)); | 832 | azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr)); |
807 | 833 | ||
834 | chip->initialized = 1; | ||
835 | } | ||
836 | |||
837 | /* | ||
838 | * initialize the PCI registers | ||
839 | */ | ||
840 | /* update bits in a PCI register byte */ | ||
841 | static void update_pci_byte(struct pci_dev *pci, unsigned int reg, | ||
842 | unsigned char mask, unsigned char val) | ||
843 | { | ||
844 | unsigned char data; | ||
845 | |||
846 | pci_read_config_byte(pci, reg, &data); | ||
847 | data &= ~mask; | ||
848 | data |= (val & mask); | ||
849 | pci_write_config_byte(pci, reg, data); | ||
850 | } | ||
851 | |||
852 | static void azx_init_pci(struct azx *chip) | ||
853 | { | ||
854 | /* Clear bits 0-2 of PCI register TCSEL (at offset 0x44) | ||
855 | * TCSEL == Traffic Class Select Register, which sets PCI express QOS | ||
856 | * Ensuring these bits are 0 clears playback static on some HD Audio | ||
857 | * codecs | ||
858 | */ | ||
859 | update_pci_byte(chip->pci, ICH6_PCIREG_TCSEL, 0x07, 0); | ||
860 | |||
808 | switch (chip->driver_type) { | 861 | switch (chip->driver_type) { |
809 | case AZX_DRIVER_ATI: | 862 | case AZX_DRIVER_ATI: |
810 | /* For ATI SB450 azalia HD audio, we need to enable snoop */ | 863 | /* For ATI SB450 azalia HD audio, we need to enable snoop */ |
811 | pci_read_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, | 864 | update_pci_byte(chip->pci, |
812 | ®); | 865 | ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, |
813 | pci_write_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, | 866 | 0x07, ATI_SB450_HDAUDIO_ENABLE_SNOOP); |
814 | (reg & 0xf8) | ATI_SB450_HDAUDIO_ENABLE_SNOOP); | ||
815 | break; | 867 | break; |
816 | case AZX_DRIVER_NVIDIA: | 868 | case AZX_DRIVER_NVIDIA: |
817 | /* For NVIDIA HDA, enable snoop */ | 869 | /* For NVIDIA HDA, enable snoop */ |
818 | pci_read_config_byte(chip->pci,NVIDIA_HDA_TRANSREG_ADDR, ®); | 870 | update_pci_byte(chip->pci, |
819 | pci_write_config_byte(chip->pci,NVIDIA_HDA_TRANSREG_ADDR, | 871 | NVIDIA_HDA_TRANSREG_ADDR, |
820 | (reg & 0xf0) | NVIDIA_HDA_ENABLE_COHBITS); | 872 | 0x0f, NVIDIA_HDA_ENABLE_COHBITS); |
821 | break; | 873 | break; |
822 | } | 874 | } |
823 | } | 875 | } |
@@ -857,7 +909,7 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id) | |||
857 | /* clear rirb int */ | 909 | /* clear rirb int */ |
858 | status = azx_readb(chip, RIRBSTS); | 910 | status = azx_readb(chip, RIRBSTS); |
859 | if (status & RIRB_INT_MASK) { | 911 | if (status & RIRB_INT_MASK) { |
860 | if (! chip->single_cmd && (status & RIRB_INT_RESPONSE)) | 912 | if (!chip->single_cmd && (status & RIRB_INT_RESPONSE)) |
861 | azx_update_rirb(chip); | 913 | azx_update_rirb(chip); |
862 | azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); | 914 | azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); |
863 | } | 915 | } |
@@ -911,9 +963,11 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | |||
911 | int timeout; | 963 | int timeout; |
912 | 964 | ||
913 | /* make sure the run bit is zero for SD */ | 965 | /* make sure the run bit is zero for SD */ |
914 | azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) & ~SD_CTL_DMA_START); | 966 | azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) & |
967 | ~SD_CTL_DMA_START); | ||
915 | /* reset stream */ | 968 | /* reset stream */ |
916 | azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) | SD_CTL_STREAM_RESET); | 969 | azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) | |
970 | SD_CTL_STREAM_RESET); | ||
917 | udelay(3); | 971 | udelay(3); |
918 | timeout = 300; | 972 | timeout = 300; |
919 | while (!((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) && | 973 | while (!((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) && |
@@ -931,7 +985,7 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | |||
931 | 985 | ||
932 | /* program the stream_tag */ | 986 | /* program the stream_tag */ |
933 | azx_sd_writel(azx_dev, SD_CTL, | 987 | azx_sd_writel(azx_dev, SD_CTL, |
934 | (azx_sd_readl(azx_dev, SD_CTL) & ~SD_CTL_STREAM_TAG_MASK) | | 988 | (azx_sd_readl(azx_dev, SD_CTL) & ~SD_CTL_STREAM_TAG_MASK)| |
935 | (azx_dev->stream_tag << SD_CTL_STREAM_TAG_SHIFT)); | 989 | (azx_dev->stream_tag << SD_CTL_STREAM_TAG_SHIFT)); |
936 | 990 | ||
937 | /* program the length of samples in cyclic buffer */ | 991 | /* program the length of samples in cyclic buffer */ |
@@ -951,11 +1005,13 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | |||
951 | azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr)); | 1005 | azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr)); |
952 | 1006 | ||
953 | /* enable the position buffer */ | 1007 | /* enable the position buffer */ |
954 | if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) | 1008 | if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) |
955 | azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE); | 1009 | azx_writel(chip, DPLBASE, |
1010 | (u32)chip->posbuf.addr |ICH6_DPLBASE_ENABLE); | ||
956 | 1011 | ||
957 | /* set the interrupt enable bits in the descriptor control register */ | 1012 | /* set the interrupt enable bits in the descriptor control register */ |
958 | azx_sd_writel(azx_dev, SD_CTL, azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK); | 1013 | azx_sd_writel(azx_dev, SD_CTL, |
1014 | azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK); | ||
959 | 1015 | ||
960 | return 0; | 1016 | return 0; |
961 | } | 1017 | } |
@@ -986,8 +1042,12 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model) | |||
986 | bus_temp.pci = chip->pci; | 1042 | bus_temp.pci = chip->pci; |
987 | bus_temp.ops.command = azx_send_cmd; | 1043 | bus_temp.ops.command = azx_send_cmd; |
988 | bus_temp.ops.get_response = azx_get_response; | 1044 | bus_temp.ops.get_response = azx_get_response; |
1045 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1046 | bus_temp.ops.pm_notify = azx_power_notify; | ||
1047 | #endif | ||
989 | 1048 | ||
990 | if ((err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus)) < 0) | 1049 | err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus); |
1050 | if (err < 0) | ||
991 | return err; | 1051 | return err; |
992 | 1052 | ||
993 | codecs = audio_codecs = 0; | 1053 | codecs = audio_codecs = 0; |
@@ -1038,7 +1098,7 @@ static inline struct azx_dev *azx_assign_device(struct azx *chip, int stream) | |||
1038 | nums = chip->capture_streams; | 1098 | nums = chip->capture_streams; |
1039 | } | 1099 | } |
1040 | for (i = 0; i < nums; i++, dev++) | 1100 | for (i = 0; i < nums; i++, dev++) |
1041 | if (! chip->azx_dev[dev].opened) { | 1101 | if (!chip->azx_dev[dev].opened) { |
1042 | chip->azx_dev[dev].opened = 1; | 1102 | chip->azx_dev[dev].opened = 1; |
1043 | return &chip->azx_dev[dev]; | 1103 | return &chip->azx_dev[dev]; |
1044 | } | 1104 | } |
@@ -1052,7 +1112,8 @@ static inline void azx_release_device(struct azx_dev *azx_dev) | |||
1052 | } | 1112 | } |
1053 | 1113 | ||
1054 | static struct snd_pcm_hardware azx_pcm_hw = { | 1114 | static struct snd_pcm_hardware azx_pcm_hw = { |
1055 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | | 1115 | .info = (SNDRV_PCM_INFO_MMAP | |
1116 | SNDRV_PCM_INFO_INTERLEAVED | | ||
1056 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 1117 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
1057 | SNDRV_PCM_INFO_MMAP_VALID | | 1118 | SNDRV_PCM_INFO_MMAP_VALID | |
1058 | /* No full-resume yet implemented */ | 1119 | /* No full-resume yet implemented */ |
@@ -1105,8 +1166,11 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) | |||
1105 | 128); | 1166 | 128); |
1106 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, | 1167 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, |
1107 | 128); | 1168 | 128); |
1108 | if ((err = hinfo->ops.open(hinfo, apcm->codec, substream)) < 0) { | 1169 | snd_hda_power_up(apcm->codec); |
1170 | err = hinfo->ops.open(hinfo, apcm->codec, substream); | ||
1171 | if (err < 0) { | ||
1109 | azx_release_device(azx_dev); | 1172 | azx_release_device(azx_dev); |
1173 | snd_hda_power_down(apcm->codec); | ||
1110 | mutex_unlock(&chip->open_mutex); | 1174 | mutex_unlock(&chip->open_mutex); |
1111 | return err; | 1175 | return err; |
1112 | } | 1176 | } |
@@ -1135,13 +1199,16 @@ static int azx_pcm_close(struct snd_pcm_substream *substream) | |||
1135 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 1199 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
1136 | azx_release_device(azx_dev); | 1200 | azx_release_device(azx_dev); |
1137 | hinfo->ops.close(hinfo, apcm->codec, substream); | 1201 | hinfo->ops.close(hinfo, apcm->codec, substream); |
1202 | snd_hda_power_down(apcm->codec); | ||
1138 | mutex_unlock(&chip->open_mutex); | 1203 | mutex_unlock(&chip->open_mutex); |
1139 | return 0; | 1204 | return 0; |
1140 | } | 1205 | } |
1141 | 1206 | ||
1142 | static int azx_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) | 1207 | static int azx_pcm_hw_params(struct snd_pcm_substream *substream, |
1208 | struct snd_pcm_hw_params *hw_params) | ||
1143 | { | 1209 | { |
1144 | return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); | 1210 | return snd_pcm_lib_malloc_pages(substream, |
1211 | params_buffer_bytes(hw_params)); | ||
1145 | } | 1212 | } |
1146 | 1213 | ||
1147 | static int azx_pcm_hw_free(struct snd_pcm_substream *substream) | 1214 | static int azx_pcm_hw_free(struct snd_pcm_substream *substream) |
@@ -1175,13 +1242,15 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
1175 | runtime->channels, | 1242 | runtime->channels, |
1176 | runtime->format, | 1243 | runtime->format, |
1177 | hinfo->maxbps); | 1244 | hinfo->maxbps); |
1178 | if (! azx_dev->format_val) { | 1245 | if (!azx_dev->format_val) { |
1179 | snd_printk(KERN_ERR SFX "invalid format_val, rate=%d, ch=%d, format=%d\n", | 1246 | snd_printk(KERN_ERR SFX |
1247 | "invalid format_val, rate=%d, ch=%d, format=%d\n", | ||
1180 | runtime->rate, runtime->channels, runtime->format); | 1248 | runtime->rate, runtime->channels, runtime->format); |
1181 | return -EINVAL; | 1249 | return -EINVAL; |
1182 | } | 1250 | } |
1183 | 1251 | ||
1184 | snd_printdd("azx_pcm_prepare: bufsize=0x%x, fragsize=0x%x, format=0x%x\n", | 1252 | snd_printdd("azx_pcm_prepare: bufsize=0x%x, fragsize=0x%x, " |
1253 | "format=0x%x\n", | ||
1185 | azx_dev->bufsize, azx_dev->fragsize, azx_dev->format_val); | 1254 | azx_dev->bufsize, azx_dev->fragsize, azx_dev->format_val); |
1186 | azx_setup_periods(azx_dev); | 1255 | azx_setup_periods(azx_dev); |
1187 | azx_setup_controller(chip, azx_dev); | 1256 | azx_setup_controller(chip, azx_dev); |
@@ -1223,7 +1292,8 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
1223 | cmd == SNDRV_PCM_TRIGGER_SUSPEND || | 1292 | cmd == SNDRV_PCM_TRIGGER_SUSPEND || |
1224 | cmd == SNDRV_PCM_TRIGGER_STOP) { | 1293 | cmd == SNDRV_PCM_TRIGGER_STOP) { |
1225 | int timeout = 5000; | 1294 | int timeout = 5000; |
1226 | while (azx_sd_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START && --timeout) | 1295 | while ((azx_sd_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START) && |
1296 | --timeout) | ||
1227 | ; | 1297 | ; |
1228 | } | 1298 | } |
1229 | return err; | 1299 | return err; |
@@ -1241,7 +1311,7 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream) | |||
1241 | /* use the position buffer */ | 1311 | /* use the position buffer */ |
1242 | pos = le32_to_cpu(*azx_dev->posbuf); | 1312 | pos = le32_to_cpu(*azx_dev->posbuf); |
1243 | if (chip->position_fix == POS_FIX_AUTO && | 1313 | if (chip->position_fix == POS_FIX_AUTO && |
1244 | azx_dev->period_intr == 1 && ! pos) { | 1314 | azx_dev->period_intr == 1 && !pos) { |
1245 | printk(KERN_WARNING | 1315 | printk(KERN_WARNING |
1246 | "hda-intel: Invalid position buffer, " | 1316 | "hda-intel: Invalid position buffer, " |
1247 | "using LPIB read method instead.\n"); | 1317 | "using LPIB read method instead.\n"); |
@@ -1292,7 +1362,8 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec, | |||
1292 | snd_assert(cpcm->name, return -EINVAL); | 1362 | snd_assert(cpcm->name, return -EINVAL); |
1293 | 1363 | ||
1294 | err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, | 1364 | err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, |
1295 | cpcm->stream[0].substreams, cpcm->stream[1].substreams, | 1365 | cpcm->stream[0].substreams, |
1366 | cpcm->stream[1].substreams, | ||
1296 | &pcm); | 1367 | &pcm); |
1297 | if (err < 0) | 1368 | if (err < 0) |
1298 | return err; | 1369 | return err; |
@@ -1322,26 +1393,27 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec, | |||
1322 | 1393 | ||
1323 | static int __devinit azx_pcm_create(struct azx *chip) | 1394 | static int __devinit azx_pcm_create(struct azx *chip) |
1324 | { | 1395 | { |
1325 | struct list_head *p; | ||
1326 | struct hda_codec *codec; | 1396 | struct hda_codec *codec; |
1327 | int c, err; | 1397 | int c, err; |
1328 | int pcm_dev; | 1398 | int pcm_dev; |
1329 | 1399 | ||
1330 | if ((err = snd_hda_build_pcms(chip->bus)) < 0) | 1400 | err = snd_hda_build_pcms(chip->bus); |
1401 | if (err < 0) | ||
1331 | return err; | 1402 | return err; |
1332 | 1403 | ||
1333 | /* create audio PCMs */ | 1404 | /* create audio PCMs */ |
1334 | pcm_dev = 0; | 1405 | pcm_dev = 0; |
1335 | list_for_each(p, &chip->bus->codec_list) { | 1406 | list_for_each_entry(codec, &chip->bus->codec_list, list) { |
1336 | codec = list_entry(p, struct hda_codec, list); | ||
1337 | for (c = 0; c < codec->num_pcms; c++) { | 1407 | for (c = 0; c < codec->num_pcms; c++) { |
1338 | if (codec->pcm_info[c].is_modem) | 1408 | if (codec->pcm_info[c].is_modem) |
1339 | continue; /* create later */ | 1409 | continue; /* create later */ |
1340 | if (pcm_dev >= AZX_MAX_AUDIO_PCMS) { | 1410 | if (pcm_dev >= AZX_MAX_AUDIO_PCMS) { |
1341 | snd_printk(KERN_ERR SFX "Too many audio PCMs\n"); | 1411 | snd_printk(KERN_ERR SFX |
1412 | "Too many audio PCMs\n"); | ||
1342 | return -EINVAL; | 1413 | return -EINVAL; |
1343 | } | 1414 | } |
1344 | err = create_codec_pcm(chip, codec, &codec->pcm_info[c], pcm_dev); | 1415 | err = create_codec_pcm(chip, codec, |
1416 | &codec->pcm_info[c], pcm_dev); | ||
1345 | if (err < 0) | 1417 | if (err < 0) |
1346 | return err; | 1418 | return err; |
1347 | pcm_dev++; | 1419 | pcm_dev++; |
@@ -1350,16 +1422,17 @@ static int __devinit azx_pcm_create(struct azx *chip) | |||
1350 | 1422 | ||
1351 | /* create modem PCMs */ | 1423 | /* create modem PCMs */ |
1352 | pcm_dev = AZX_MAX_AUDIO_PCMS; | 1424 | pcm_dev = AZX_MAX_AUDIO_PCMS; |
1353 | list_for_each(p, &chip->bus->codec_list) { | 1425 | list_for_each_entry(codec, &chip->bus->codec_list, list) { |
1354 | codec = list_entry(p, struct hda_codec, list); | ||
1355 | for (c = 0; c < codec->num_pcms; c++) { | 1426 | for (c = 0; c < codec->num_pcms; c++) { |
1356 | if (! codec->pcm_info[c].is_modem) | 1427 | if (!codec->pcm_info[c].is_modem) |
1357 | continue; /* already created */ | 1428 | continue; /* already created */ |
1358 | if (pcm_dev >= AZX_MAX_PCMS) { | 1429 | if (pcm_dev >= AZX_MAX_PCMS) { |
1359 | snd_printk(KERN_ERR SFX "Too many modem PCMs\n"); | 1430 | snd_printk(KERN_ERR SFX |
1431 | "Too many modem PCMs\n"); | ||
1360 | return -EINVAL; | 1432 | return -EINVAL; |
1361 | } | 1433 | } |
1362 | err = create_codec_pcm(chip, codec, &codec->pcm_info[c], pcm_dev); | 1434 | err = create_codec_pcm(chip, codec, |
1435 | &codec->pcm_info[c], pcm_dev); | ||
1363 | if (err < 0) | 1436 | if (err < 0) |
1364 | return err; | 1437 | return err; |
1365 | chip->pcm[pcm_dev]->dev_class = SNDRV_PCM_CLASS_MODEM; | 1438 | chip->pcm[pcm_dev]->dev_class = SNDRV_PCM_CLASS_MODEM; |
@@ -1386,7 +1459,8 @@ static int __devinit azx_init_stream(struct azx *chip) | |||
1386 | int i; | 1459 | int i; |
1387 | 1460 | ||
1388 | /* initialize each stream (aka device) | 1461 | /* initialize each stream (aka device) |
1389 | * assign the starting bdl address to each stream (device) and initialize | 1462 | * assign the starting bdl address to each stream (device) |
1463 | * and initialize | ||
1390 | */ | 1464 | */ |
1391 | for (i = 0; i < chip->num_streams; i++) { | 1465 | for (i = 0; i < chip->num_streams; i++) { |
1392 | unsigned int off = sizeof(u32) * (i * AZX_MAX_FRAG * 4); | 1466 | unsigned int off = sizeof(u32) * (i * AZX_MAX_FRAG * 4); |
@@ -1423,6 +1497,46 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect) | |||
1423 | } | 1497 | } |
1424 | 1498 | ||
1425 | 1499 | ||
1500 | static void azx_stop_chip(struct azx *chip) | ||
1501 | { | ||
1502 | if (!chip->initialized) | ||
1503 | return; | ||
1504 | |||
1505 | /* disable interrupts */ | ||
1506 | azx_int_disable(chip); | ||
1507 | azx_int_clear(chip); | ||
1508 | |||
1509 | /* disable CORB/RIRB */ | ||
1510 | azx_free_cmd_io(chip); | ||
1511 | |||
1512 | /* disable position buffer */ | ||
1513 | azx_writel(chip, DPLBASE, 0); | ||
1514 | azx_writel(chip, DPUBASE, 0); | ||
1515 | |||
1516 | chip->initialized = 0; | ||
1517 | } | ||
1518 | |||
1519 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1520 | /* power-up/down the controller */ | ||
1521 | static void azx_power_notify(struct hda_codec *codec) | ||
1522 | { | ||
1523 | struct azx *chip = codec->bus->private_data; | ||
1524 | struct hda_codec *c; | ||
1525 | int power_on = 0; | ||
1526 | |||
1527 | list_for_each_entry(c, &codec->bus->codec_list, list) { | ||
1528 | if (c->power_on) { | ||
1529 | power_on = 1; | ||
1530 | break; | ||
1531 | } | ||
1532 | } | ||
1533 | if (power_on) | ||
1534 | azx_init_chip(chip); | ||
1535 | else if (chip->running && power_save_controller) | ||
1536 | azx_stop_chip(chip); | ||
1537 | } | ||
1538 | #endif /* CONFIG_SND_HDA_POWER_SAVE */ | ||
1539 | |||
1426 | #ifdef CONFIG_PM | 1540 | #ifdef CONFIG_PM |
1427 | /* | 1541 | /* |
1428 | * power management | 1542 | * power management |
@@ -1436,8 +1550,9 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state) | |||
1436 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 1550 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
1437 | for (i = 0; i < chip->pcm_devs; i++) | 1551 | for (i = 0; i < chip->pcm_devs; i++) |
1438 | snd_pcm_suspend_all(chip->pcm[i]); | 1552 | snd_pcm_suspend_all(chip->pcm[i]); |
1439 | snd_hda_suspend(chip->bus, state); | 1553 | if (chip->initialized) |
1440 | azx_free_cmd_io(chip); | 1554 | snd_hda_suspend(chip->bus, state); |
1555 | azx_stop_chip(chip); | ||
1441 | if (chip->irq >= 0) { | 1556 | if (chip->irq >= 0) { |
1442 | synchronize_irq(chip->irq); | 1557 | synchronize_irq(chip->irq); |
1443 | free_irq(chip->irq, chip); | 1558 | free_irq(chip->irq, chip); |
@@ -1470,7 +1585,11 @@ static int azx_resume(struct pci_dev *pci) | |||
1470 | chip->msi = 0; | 1585 | chip->msi = 0; |
1471 | if (azx_acquire_irq(chip, 1) < 0) | 1586 | if (azx_acquire_irq(chip, 1) < 0) |
1472 | return -EIO; | 1587 | return -EIO; |
1473 | azx_init_chip(chip); | 1588 | azx_init_pci(chip); |
1589 | |||
1590 | if (snd_hda_codecs_inuse(chip->bus)) | ||
1591 | azx_init_chip(chip); | ||
1592 | |||
1474 | snd_hda_resume(chip->bus); | 1593 | snd_hda_resume(chip->bus); |
1475 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 1594 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
1476 | return 0; | 1595 | return 0; |
@@ -1485,20 +1604,9 @@ static int azx_free(struct azx *chip) | |||
1485 | { | 1604 | { |
1486 | if (chip->initialized) { | 1605 | if (chip->initialized) { |
1487 | int i; | 1606 | int i; |
1488 | |||
1489 | for (i = 0; i < chip->num_streams; i++) | 1607 | for (i = 0; i < chip->num_streams; i++) |
1490 | azx_stream_stop(chip, &chip->azx_dev[i]); | 1608 | azx_stream_stop(chip, &chip->azx_dev[i]); |
1491 | 1609 | azx_stop_chip(chip); | |
1492 | /* disable interrupts */ | ||
1493 | azx_int_disable(chip); | ||
1494 | azx_int_clear(chip); | ||
1495 | |||
1496 | /* disable CORB/RIRB */ | ||
1497 | azx_free_cmd_io(chip); | ||
1498 | |||
1499 | /* disable position buffer */ | ||
1500 | azx_writel(chip, DPLBASE, 0); | ||
1501 | azx_writel(chip, DPUBASE, 0); | ||
1502 | } | 1610 | } |
1503 | 1611 | ||
1504 | if (chip->irq >= 0) { | 1612 | if (chip->irq >= 0) { |
@@ -1534,6 +1642,7 @@ static int azx_dev_free(struct snd_device *device) | |||
1534 | */ | 1642 | */ |
1535 | static struct snd_pci_quirk position_fix_list[] __devinitdata = { | 1643 | static struct snd_pci_quirk position_fix_list[] __devinitdata = { |
1536 | SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_NONE), | 1644 | SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_NONE), |
1645 | SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_NONE), | ||
1537 | {} | 1646 | {} |
1538 | }; | 1647 | }; |
1539 | 1648 | ||
@@ -1544,7 +1653,7 @@ static int __devinit check_position_fix(struct azx *chip, int fix) | |||
1544 | if (fix == POS_FIX_AUTO) { | 1653 | if (fix == POS_FIX_AUTO) { |
1545 | q = snd_pci_quirk_lookup(chip->pci, position_fix_list); | 1654 | q = snd_pci_quirk_lookup(chip->pci, position_fix_list); |
1546 | if (q) { | 1655 | if (q) { |
1547 | snd_printdd(KERN_INFO | 1656 | printk(KERN_INFO |
1548 | "hda_intel: position_fix set to %d " | 1657 | "hda_intel: position_fix set to %d " |
1549 | "for device %04x:%04x\n", | 1658 | "for device %04x:%04x\n", |
1550 | q->value, q->subvendor, q->subdevice); | 1659 | q->value, q->subvendor, q->subdevice); |
@@ -1555,6 +1664,36 @@ static int __devinit check_position_fix(struct azx *chip, int fix) | |||
1555 | } | 1664 | } |
1556 | 1665 | ||
1557 | /* | 1666 | /* |
1667 | * black-lists for probe_mask | ||
1668 | */ | ||
1669 | static struct snd_pci_quirk probe_mask_list[] __devinitdata = { | ||
1670 | /* Thinkpad often breaks the controller communication when accessing | ||
1671 | * to the non-working (or non-existing) modem codec slot. | ||
1672 | */ | ||
1673 | SND_PCI_QUIRK(0x1014, 0x05b7, "Thinkpad Z60", 0x01), | ||
1674 | SND_PCI_QUIRK(0x17aa, 0x2010, "Thinkpad X/T/R60", 0x01), | ||
1675 | SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X/T/R61", 0x01), | ||
1676 | {} | ||
1677 | }; | ||
1678 | |||
1679 | static void __devinit check_probe_mask(struct azx *chip) | ||
1680 | { | ||
1681 | const struct snd_pci_quirk *q; | ||
1682 | |||
1683 | if (probe_mask == -1) { | ||
1684 | q = snd_pci_quirk_lookup(chip->pci, probe_mask_list); | ||
1685 | if (q) { | ||
1686 | printk(KERN_INFO | ||
1687 | "hda_intel: probe_mask set to 0x%x " | ||
1688 | "for device %04x:%04x\n", | ||
1689 | q->value, q->subvendor, q->subdevice); | ||
1690 | probe_mask = q->value; | ||
1691 | } | ||
1692 | } | ||
1693 | } | ||
1694 | |||
1695 | |||
1696 | /* | ||
1558 | * constructor | 1697 | * constructor |
1559 | */ | 1698 | */ |
1560 | static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | 1699 | static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, |
@@ -1589,6 +1728,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1589 | chip->msi = enable_msi; | 1728 | chip->msi = enable_msi; |
1590 | 1729 | ||
1591 | chip->position_fix = check_position_fix(chip, position_fix); | 1730 | chip->position_fix = check_position_fix(chip, position_fix); |
1731 | check_probe_mask(chip); | ||
1592 | 1732 | ||
1593 | chip->single_cmd = single_cmd; | 1733 | chip->single_cmd = single_cmd; |
1594 | 1734 | ||
@@ -1650,37 +1790,43 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1650 | break; | 1790 | break; |
1651 | } | 1791 | } |
1652 | chip->num_streams = chip->playback_streams + chip->capture_streams; | 1792 | chip->num_streams = chip->playback_streams + chip->capture_streams; |
1653 | chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev), GFP_KERNEL); | 1793 | chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev), |
1794 | GFP_KERNEL); | ||
1654 | if (!chip->azx_dev) { | 1795 | if (!chip->azx_dev) { |
1655 | snd_printk(KERN_ERR "cannot malloc azx_dev\n"); | 1796 | snd_printk(KERN_ERR "cannot malloc azx_dev\n"); |
1656 | goto errout; | 1797 | goto errout; |
1657 | } | 1798 | } |
1658 | 1799 | ||
1659 | /* allocate memory for the BDL for each stream */ | 1800 | /* allocate memory for the BDL for each stream */ |
1660 | if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), | 1801 | err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, |
1661 | BDL_SIZE, &chip->bdl)) < 0) { | 1802 | snd_dma_pci_data(chip->pci), |
1803 | BDL_SIZE, &chip->bdl); | ||
1804 | if (err < 0) { | ||
1662 | snd_printk(KERN_ERR SFX "cannot allocate BDL\n"); | 1805 | snd_printk(KERN_ERR SFX "cannot allocate BDL\n"); |
1663 | goto errout; | 1806 | goto errout; |
1664 | } | 1807 | } |
1665 | /* allocate memory for the position buffer */ | 1808 | /* allocate memory for the position buffer */ |
1666 | if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), | 1809 | err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, |
1667 | chip->num_streams * 8, &chip->posbuf)) < 0) { | 1810 | snd_dma_pci_data(chip->pci), |
1811 | chip->num_streams * 8, &chip->posbuf); | ||
1812 | if (err < 0) { | ||
1668 | snd_printk(KERN_ERR SFX "cannot allocate posbuf\n"); | 1813 | snd_printk(KERN_ERR SFX "cannot allocate posbuf\n"); |
1669 | goto errout; | 1814 | goto errout; |
1670 | } | 1815 | } |
1671 | /* allocate CORB/RIRB */ | 1816 | /* allocate CORB/RIRB */ |
1672 | if (! chip->single_cmd) | 1817 | if (!chip->single_cmd) { |
1673 | if ((err = azx_alloc_cmd_io(chip)) < 0) | 1818 | err = azx_alloc_cmd_io(chip); |
1819 | if (err < 0) | ||
1674 | goto errout; | 1820 | goto errout; |
1821 | } | ||
1675 | 1822 | ||
1676 | /* initialize streams */ | 1823 | /* initialize streams */ |
1677 | azx_init_stream(chip); | 1824 | azx_init_stream(chip); |
1678 | 1825 | ||
1679 | /* initialize chip */ | 1826 | /* initialize chip */ |
1827 | azx_init_pci(chip); | ||
1680 | azx_init_chip(chip); | 1828 | azx_init_chip(chip); |
1681 | 1829 | ||
1682 | chip->initialized = 1; | ||
1683 | |||
1684 | /* codec detection */ | 1830 | /* codec detection */ |
1685 | if (!chip->codec_mask) { | 1831 | if (!chip->codec_mask) { |
1686 | snd_printk(KERN_ERR SFX "no codecs found!\n"); | 1832 | snd_printk(KERN_ERR SFX "no codecs found!\n"); |
@@ -1688,14 +1834,16 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1688 | goto errout; | 1834 | goto errout; |
1689 | } | 1835 | } |
1690 | 1836 | ||
1691 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) <0) { | 1837 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); |
1838 | if (err <0) { | ||
1692 | snd_printk(KERN_ERR SFX "Error creating device [card]!\n"); | 1839 | snd_printk(KERN_ERR SFX "Error creating device [card]!\n"); |
1693 | goto errout; | 1840 | goto errout; |
1694 | } | 1841 | } |
1695 | 1842 | ||
1696 | strcpy(card->driver, "HDA-Intel"); | 1843 | strcpy(card->driver, "HDA-Intel"); |
1697 | strcpy(card->shortname, driver_short_names[chip->driver_type]); | 1844 | strcpy(card->shortname, driver_short_names[chip->driver_type]); |
1698 | sprintf(card->longname, "%s at 0x%lx irq %i", card->shortname, chip->addr, chip->irq); | 1845 | sprintf(card->longname, "%s at 0x%lx irq %i", |
1846 | card->shortname, chip->addr, chip->irq); | ||
1699 | 1847 | ||
1700 | *rchip = chip; | 1848 | *rchip = chip; |
1701 | return 0; | 1849 | return 0; |
@@ -1705,7 +1853,21 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1705 | return err; | 1853 | return err; |
1706 | } | 1854 | } |
1707 | 1855 | ||
1708 | static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | 1856 | static void power_down_all_codecs(struct azx *chip) |
1857 | { | ||
1858 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1859 | /* The codecs were powered up in snd_hda_codec_new(). | ||
1860 | * Now all initialization done, so turn them down if possible | ||
1861 | */ | ||
1862 | struct hda_codec *codec; | ||
1863 | list_for_each_entry(codec, &chip->bus->codec_list, list) { | ||
1864 | snd_hda_power_down(codec); | ||
1865 | } | ||
1866 | #endif | ||
1867 | } | ||
1868 | |||
1869 | static int __devinit azx_probe(struct pci_dev *pci, | ||
1870 | const struct pci_device_id *pci_id) | ||
1709 | { | 1871 | { |
1710 | struct snd_card *card; | 1872 | struct snd_card *card; |
1711 | struct azx *chip; | 1873 | struct azx *chip; |
@@ -1725,31 +1887,37 @@ static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id * | |||
1725 | card->private_data = chip; | 1887 | card->private_data = chip; |
1726 | 1888 | ||
1727 | /* create codec instances */ | 1889 | /* create codec instances */ |
1728 | if ((err = azx_codec_create(chip, model)) < 0) { | 1890 | err = azx_codec_create(chip, model); |
1891 | if (err < 0) { | ||
1729 | snd_card_free(card); | 1892 | snd_card_free(card); |
1730 | return err; | 1893 | return err; |
1731 | } | 1894 | } |
1732 | 1895 | ||
1733 | /* create PCM streams */ | 1896 | /* create PCM streams */ |
1734 | if ((err = azx_pcm_create(chip)) < 0) { | 1897 | err = azx_pcm_create(chip); |
1898 | if (err < 0) { | ||
1735 | snd_card_free(card); | 1899 | snd_card_free(card); |
1736 | return err; | 1900 | return err; |
1737 | } | 1901 | } |
1738 | 1902 | ||
1739 | /* create mixer controls */ | 1903 | /* create mixer controls */ |
1740 | if ((err = azx_mixer_create(chip)) < 0) { | 1904 | err = azx_mixer_create(chip); |
1905 | if (err < 0) { | ||
1741 | snd_card_free(card); | 1906 | snd_card_free(card); |
1742 | return err; | 1907 | return err; |
1743 | } | 1908 | } |
1744 | 1909 | ||
1745 | snd_card_set_dev(card, &pci->dev); | 1910 | snd_card_set_dev(card, &pci->dev); |
1746 | 1911 | ||
1747 | if ((err = snd_card_register(card)) < 0) { | 1912 | err = snd_card_register(card); |
1913 | if (err < 0) { | ||
1748 | snd_card_free(card); | 1914 | snd_card_free(card); |
1749 | return err; | 1915 | return err; |
1750 | } | 1916 | } |
1751 | 1917 | ||
1752 | pci_set_drvdata(pci, card); | 1918 | pci_set_drvdata(pci, card); |
1919 | chip->running = 1; | ||
1920 | power_down_all_codecs(chip); | ||
1753 | 1921 | ||
1754 | return err; | 1922 | return err; |
1755 | } | 1923 | } |
@@ -1791,6 +1959,10 @@ static struct pci_device_id azx_ids[] = { | |||
1791 | { 0x10de, 0x0775, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */ | 1959 | { 0x10de, 0x0775, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */ |
1792 | { 0x10de, 0x0776, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */ | 1960 | { 0x10de, 0x0776, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */ |
1793 | { 0x10de, 0x0777, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */ | 1961 | { 0x10de, 0x0777, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */ |
1962 | { 0x10de, 0x0ac0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */ | ||
1963 | { 0x10de, 0x0ac1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */ | ||
1964 | { 0x10de, 0x0ac2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */ | ||
1965 | { 0x10de, 0x0ac3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */ | ||
1794 | { 0, } | 1966 | { 0, } |
1795 | }; | 1967 | }; |
1796 | MODULE_DEVICE_TABLE(pci, azx_ids); | 1968 | MODULE_DEVICE_TABLE(pci, azx_ids); |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index f91ea5ec9f6d..a79d0ed5469c 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -26,7 +26,8 @@ | |||
26 | /* | 26 | /* |
27 | * for mixer controls | 27 | * for mixer controls |
28 | */ | 28 | */ |
29 | #define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19)) | 29 | #define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \ |
30 | ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19)) | ||
30 | /* mono volume with index (index=0,1,...) (channel=1,2) */ | 31 | /* mono volume with index (index=0,1,...) (channel=1,2) */ |
31 | #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ | 32 | #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ |
32 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ | 33 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ |
@@ -64,18 +65,35 @@ | |||
64 | #define HDA_CODEC_MUTE(xname, nid, xindex, direction) \ | 65 | #define HDA_CODEC_MUTE(xname, nid, xindex, direction) \ |
65 | HDA_CODEC_MUTE_MONO(xname, nid, 3, xindex, direction) | 66 | HDA_CODEC_MUTE_MONO(xname, nid, 3, xindex, direction) |
66 | 67 | ||
67 | int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); | 68 | int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, |
68 | int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 69 | struct snd_ctl_elem_info *uinfo); |
69 | int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 70 | int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, |
70 | int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, unsigned int size, unsigned int __user *tlv); | 71 | struct snd_ctl_elem_value *ucontrol); |
71 | int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); | 72 | int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, |
72 | int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 73 | struct snd_ctl_elem_value *ucontrol); |
73 | int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 74 | int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, |
75 | unsigned int size, unsigned int __user *tlv); | ||
76 | int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, | ||
77 | struct snd_ctl_elem_info *uinfo); | ||
78 | int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, | ||
79 | struct snd_ctl_elem_value *ucontrol); | ||
80 | int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, | ||
81 | struct snd_ctl_elem_value *ucontrol); | ||
74 | /* lowlevel accessor with caching; use carefully */ | 82 | /* lowlevel accessor with caching; use carefully */ |
75 | int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, | 83 | int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, |
76 | int direction, int index); | 84 | int direction, int index); |
77 | int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, | 85 | int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, |
78 | int direction, int idx, int mask, int val); | 86 | int direction, int idx, int mask, int val); |
87 | int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, | ||
88 | int dir, int idx, int mask, int val); | ||
89 | #ifdef SND_HDA_NEEDS_RESUME | ||
90 | void snd_hda_codec_resume_amp(struct hda_codec *codec); | ||
91 | #endif | ||
92 | |||
93 | /* amp value bits */ | ||
94 | #define HDA_AMP_MUTE 0x80 | ||
95 | #define HDA_AMP_UNMUTE 0x00 | ||
96 | #define HDA_AMP_VOLMASK 0x7f | ||
79 | 97 | ||
80 | /* mono switch binding multiple inputs */ | 98 | /* mono switch binding multiple inputs */ |
81 | #define HDA_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \ | 99 | #define HDA_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \ |
@@ -86,11 +104,61 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, | |||
86 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, indices, direction) } | 104 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, indices, direction) } |
87 | 105 | ||
88 | /* stereo switch binding multiple inputs */ | 106 | /* stereo switch binding multiple inputs */ |
89 | #define HDA_BIND_MUTE(xname,nid,indices,dir) HDA_BIND_MUTE_MONO(xname,nid,3,indices,dir) | 107 | #define HDA_BIND_MUTE(xname,nid,indices,dir) \ |
108 | HDA_BIND_MUTE_MONO(xname,nid,3,indices,dir) | ||
109 | |||
110 | int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, | ||
111 | struct snd_ctl_elem_value *ucontrol); | ||
112 | int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, | ||
113 | struct snd_ctl_elem_value *ucontrol); | ||
114 | |||
115 | /* more generic bound controls */ | ||
116 | struct hda_ctl_ops { | ||
117 | snd_kcontrol_info_t *info; | ||
118 | snd_kcontrol_get_t *get; | ||
119 | snd_kcontrol_put_t *put; | ||
120 | snd_kcontrol_tlv_rw_t *tlv; | ||
121 | }; | ||
90 | 122 | ||
91 | int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 123 | extern struct hda_ctl_ops snd_hda_bind_vol; /* for bind-volume with TLV */ |
92 | int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 124 | extern struct hda_ctl_ops snd_hda_bind_sw; /* for bind-switch */ |
93 | 125 | ||
126 | struct hda_bind_ctls { | ||
127 | struct hda_ctl_ops *ops; | ||
128 | long values[]; | ||
129 | }; | ||
130 | |||
131 | int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol, | ||
132 | struct snd_ctl_elem_info *uinfo); | ||
133 | int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol, | ||
134 | struct snd_ctl_elem_value *ucontrol); | ||
135 | int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol, | ||
136 | struct snd_ctl_elem_value *ucontrol); | ||
137 | int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag, | ||
138 | unsigned int size, unsigned int __user *tlv); | ||
139 | |||
140 | #define HDA_BIND_VOL(xname, bindrec) \ | ||
141 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
142 | .name = xname, \ | ||
143 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ | ||
144 | SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | ||
145 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK,\ | ||
146 | .info = snd_hda_mixer_bind_ctls_info,\ | ||
147 | .get = snd_hda_mixer_bind_ctls_get,\ | ||
148 | .put = snd_hda_mixer_bind_ctls_put,\ | ||
149 | .tlv = { .c = snd_hda_mixer_bind_tlv },\ | ||
150 | .private_value = (long) (bindrec) } | ||
151 | #define HDA_BIND_SW(xname, bindrec) \ | ||
152 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,\ | ||
153 | .name = xname, \ | ||
154 | .info = snd_hda_mixer_bind_ctls_info,\ | ||
155 | .get = snd_hda_mixer_bind_ctls_get,\ | ||
156 | .put = snd_hda_mixer_bind_ctls_put,\ | ||
157 | .private_value = (long) (bindrec) } | ||
158 | |||
159 | /* | ||
160 | * SPDIF I/O | ||
161 | */ | ||
94 | int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid); | 162 | int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid); |
95 | int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid); | 163 | int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid); |
96 | 164 | ||
@@ -107,8 +175,10 @@ struct hda_input_mux { | |||
107 | struct hda_input_mux_item items[HDA_MAX_NUM_INPUTS]; | 175 | struct hda_input_mux_item items[HDA_MAX_NUM_INPUTS]; |
108 | }; | 176 | }; |
109 | 177 | ||
110 | int snd_hda_input_mux_info(const struct hda_input_mux *imux, struct snd_ctl_elem_info *uinfo); | 178 | int snd_hda_input_mux_info(const struct hda_input_mux *imux, |
111 | int snd_hda_input_mux_put(struct hda_codec *codec, const struct hda_input_mux *imux, | 179 | struct snd_ctl_elem_info *uinfo); |
180 | int snd_hda_input_mux_put(struct hda_codec *codec, | ||
181 | const struct hda_input_mux *imux, | ||
112 | struct snd_ctl_elem_value *ucontrol, hda_nid_t nid, | 182 | struct snd_ctl_elem_value *ucontrol, hda_nid_t nid, |
113 | unsigned int *cur_val); | 183 | unsigned int *cur_val); |
114 | 184 | ||
@@ -120,13 +190,19 @@ struct hda_channel_mode { | |||
120 | const struct hda_verb *sequence; | 190 | const struct hda_verb *sequence; |
121 | }; | 191 | }; |
122 | 192 | ||
123 | int snd_hda_ch_mode_info(struct hda_codec *codec, struct snd_ctl_elem_info *uinfo, | 193 | int snd_hda_ch_mode_info(struct hda_codec *codec, |
124 | const struct hda_channel_mode *chmode, int num_chmodes); | 194 | struct snd_ctl_elem_info *uinfo, |
125 | int snd_hda_ch_mode_get(struct hda_codec *codec, struct snd_ctl_elem_value *ucontrol, | 195 | const struct hda_channel_mode *chmode, |
126 | const struct hda_channel_mode *chmode, int num_chmodes, | 196 | int num_chmodes); |
197 | int snd_hda_ch_mode_get(struct hda_codec *codec, | ||
198 | struct snd_ctl_elem_value *ucontrol, | ||
199 | const struct hda_channel_mode *chmode, | ||
200 | int num_chmodes, | ||
127 | int max_channels); | 201 | int max_channels); |
128 | int snd_hda_ch_mode_put(struct hda_codec *codec, struct snd_ctl_elem_value *ucontrol, | 202 | int snd_hda_ch_mode_put(struct hda_codec *codec, |
129 | const struct hda_channel_mode *chmode, int num_chmodes, | 203 | struct snd_ctl_elem_value *ucontrol, |
204 | const struct hda_channel_mode *chmode, | ||
205 | int num_chmodes, | ||
130 | int *max_channelsp); | 206 | int *max_channelsp); |
131 | 207 | ||
132 | /* | 208 | /* |
@@ -146,20 +222,25 @@ struct hda_multi_out { | |||
146 | int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */ | 222 | int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */ |
147 | }; | 223 | }; |
148 | 224 | ||
149 | int snd_hda_multi_out_dig_open(struct hda_codec *codec, struct hda_multi_out *mout); | 225 | int snd_hda_multi_out_dig_open(struct hda_codec *codec, |
150 | int snd_hda_multi_out_dig_close(struct hda_codec *codec, struct hda_multi_out *mout); | 226 | struct hda_multi_out *mout); |
227 | int snd_hda_multi_out_dig_close(struct hda_codec *codec, | ||
228 | struct hda_multi_out *mout); | ||
151 | int snd_hda_multi_out_dig_prepare(struct hda_codec *codec, | 229 | int snd_hda_multi_out_dig_prepare(struct hda_codec *codec, |
152 | struct hda_multi_out *mout, | 230 | struct hda_multi_out *mout, |
153 | unsigned int stream_tag, | 231 | unsigned int stream_tag, |
154 | unsigned int format, | 232 | unsigned int format, |
155 | struct snd_pcm_substream *substream); | 233 | struct snd_pcm_substream *substream); |
156 | int snd_hda_multi_out_analog_open(struct hda_codec *codec, struct hda_multi_out *mout, | 234 | int snd_hda_multi_out_analog_open(struct hda_codec *codec, |
235 | struct hda_multi_out *mout, | ||
157 | struct snd_pcm_substream *substream); | 236 | struct snd_pcm_substream *substream); |
158 | int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_out *mout, | 237 | int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, |
238 | struct hda_multi_out *mout, | ||
159 | unsigned int stream_tag, | 239 | unsigned int stream_tag, |
160 | unsigned int format, | 240 | unsigned int format, |
161 | struct snd_pcm_substream *substream); | 241 | struct snd_pcm_substream *substream); |
162 | int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_out *mout); | 242 | int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, |
243 | struct hda_multi_out *mout); | ||
163 | 244 | ||
164 | /* | 245 | /* |
165 | * generic codec parser | 246 | * generic codec parser |
@@ -181,16 +262,8 @@ static inline int snd_hda_codec_proc_new(struct hda_codec *codec) { return 0; } | |||
181 | int snd_hda_check_board_config(struct hda_codec *codec, int num_configs, | 262 | int snd_hda_check_board_config(struct hda_codec *codec, int num_configs, |
182 | const char **modelnames, | 263 | const char **modelnames, |
183 | const struct snd_pci_quirk *pci_list); | 264 | const struct snd_pci_quirk *pci_list); |
184 | int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew); | 265 | int snd_hda_add_new_ctls(struct hda_codec *codec, |
185 | 266 | struct snd_kcontrol_new *knew); | |
186 | /* | ||
187 | * power management | ||
188 | */ | ||
189 | #ifdef CONFIG_PM | ||
190 | int snd_hda_resume_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew); | ||
191 | int snd_hda_resume_spdif_out(struct hda_codec *codec); | ||
192 | int snd_hda_resume_spdif_in(struct hda_codec *codec); | ||
193 | #endif | ||
194 | 267 | ||
195 | /* | 268 | /* |
196 | * unsolicited event handler | 269 | * unsolicited event handler |
@@ -232,7 +305,9 @@ extern const char *auto_pin_cfg_labels[AUTO_PIN_LAST]; | |||
232 | 305 | ||
233 | struct auto_pin_cfg { | 306 | struct auto_pin_cfg { |
234 | int line_outs; | 307 | int line_outs; |
235 | hda_nid_t line_out_pins[5]; /* sorted in the order of Front/Surr/CLFE/Side */ | 308 | hda_nid_t line_out_pins[5]; /* sorted in the order of |
309 | * Front/Surr/CLFE/Side | ||
310 | */ | ||
236 | int speaker_outs; | 311 | int speaker_outs; |
237 | hda_nid_t speaker_pins[5]; | 312 | hda_nid_t speaker_pins[5]; |
238 | int hp_outs; | 313 | int hp_outs; |
@@ -243,13 +318,19 @@ struct auto_pin_cfg { | |||
243 | hda_nid_t dig_in_pin; | 318 | hda_nid_t dig_in_pin; |
244 | }; | 319 | }; |
245 | 320 | ||
246 | #define get_defcfg_connect(cfg) ((cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT) | 321 | #define get_defcfg_connect(cfg) \ |
247 | #define get_defcfg_association(cfg) ((cfg & AC_DEFCFG_DEF_ASSOC) >> AC_DEFCFG_ASSOC_SHIFT) | 322 | ((cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT) |
248 | #define get_defcfg_location(cfg) ((cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT) | 323 | #define get_defcfg_association(cfg) \ |
249 | #define get_defcfg_sequence(cfg) (cfg & AC_DEFCFG_SEQUENCE) | 324 | ((cfg & AC_DEFCFG_DEF_ASSOC) >> AC_DEFCFG_ASSOC_SHIFT) |
250 | #define get_defcfg_device(cfg) ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT) | 325 | #define get_defcfg_location(cfg) \ |
251 | 326 | ((cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT) | |
252 | int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg, | 327 | #define get_defcfg_sequence(cfg) \ |
328 | (cfg & AC_DEFCFG_SEQUENCE) | ||
329 | #define get_defcfg_device(cfg) \ | ||
330 | ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT) | ||
331 | |||
332 | int snd_hda_parse_pin_def_config(struct hda_codec *codec, | ||
333 | struct auto_pin_cfg *cfg, | ||
253 | hda_nid_t *ignore_nids); | 334 | hda_nid_t *ignore_nids); |
254 | 335 | ||
255 | /* amp values */ | 336 | /* amp values */ |
@@ -280,4 +361,32 @@ static inline u32 get_wcaps(struct hda_codec *codec, hda_nid_t nid) | |||
280 | int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, | 361 | int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, |
281 | unsigned int caps); | 362 | unsigned int caps); |
282 | 363 | ||
364 | /* | ||
365 | * hwdep interface | ||
366 | */ | ||
367 | int snd_hda_create_hwdep(struct hda_codec *codec); | ||
368 | |||
369 | /* | ||
370 | * power-management | ||
371 | */ | ||
372 | |||
373 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
374 | void snd_hda_schedule_power_save(struct hda_codec *codec); | ||
375 | |||
376 | struct hda_amp_list { | ||
377 | hda_nid_t nid; | ||
378 | unsigned char dir; | ||
379 | unsigned char idx; | ||
380 | }; | ||
381 | |||
382 | struct hda_loopback_check { | ||
383 | struct hda_amp_list *amplist; | ||
384 | int power_on; | ||
385 | }; | ||
386 | |||
387 | int snd_hda_check_amp_list_power(struct hda_codec *codec, | ||
388 | struct hda_loopback_check *check, | ||
389 | hda_nid_t nid); | ||
390 | #endif /* CONFIG_SND_HDA_POWER_SAVE */ | ||
391 | |||
283 | #endif /* __SOUND_HDA_LOCAL_H */ | 392 | #endif /* __SOUND_HDA_LOCAL_H */ |
diff --git a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h index 9f9e9ae44a9d..f5c23bb16d7e 100644 --- a/sound/pci/hda/hda_patch.h +++ b/sound/pci/hda/hda_patch.h | |||
@@ -20,13 +20,29 @@ extern struct hda_codec_preset snd_hda_preset_conexant[]; | |||
20 | extern struct hda_codec_preset snd_hda_preset_via[]; | 20 | extern struct hda_codec_preset snd_hda_preset_via[]; |
21 | 21 | ||
22 | static const struct hda_codec_preset *hda_preset_tables[] = { | 22 | static const struct hda_codec_preset *hda_preset_tables[] = { |
23 | #ifdef CONFIG_SND_HDA_CODEC_REALTEK | ||
23 | snd_hda_preset_realtek, | 24 | snd_hda_preset_realtek, |
25 | #endif | ||
26 | #ifdef CONFIG_SND_HDA_CODEC_CMEDIA | ||
24 | snd_hda_preset_cmedia, | 27 | snd_hda_preset_cmedia, |
28 | #endif | ||
29 | #ifdef CONFIG_SND_HDA_CODEC_ANALOG | ||
25 | snd_hda_preset_analog, | 30 | snd_hda_preset_analog, |
31 | #endif | ||
32 | #ifdef CONFIG_SND_HDA_CODEC_SIGMATEL | ||
26 | snd_hda_preset_sigmatel, | 33 | snd_hda_preset_sigmatel, |
34 | #endif | ||
35 | #ifdef CONFIG_SND_HDA_CODEC_SI3054 | ||
27 | snd_hda_preset_si3054, | 36 | snd_hda_preset_si3054, |
37 | #endif | ||
38 | #ifdef CONFIG_SND_HDA_CODEC_ATIHDMI | ||
28 | snd_hda_preset_atihdmi, | 39 | snd_hda_preset_atihdmi, |
40 | #endif | ||
41 | #ifdef CONFIG_SND_HDA_CODEC_CONEXANT | ||
29 | snd_hda_preset_conexant, | 42 | snd_hda_preset_conexant, |
43 | #endif | ||
44 | #ifdef CONFIG_SND_HDA_CODEC_VIA | ||
30 | snd_hda_preset_via, | 45 | snd_hda_preset_via, |
46 | #endif | ||
31 | NULL | 47 | NULL |
32 | }; | 48 | }; |
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index ac15066fd300..e94944f34ffd 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c | |||
@@ -58,7 +58,8 @@ static void print_amp_caps(struct snd_info_buffer *buffer, | |||
58 | snd_iprintf(buffer, "N/A\n"); | 58 | snd_iprintf(buffer, "N/A\n"); |
59 | return; | 59 | return; |
60 | } | 60 | } |
61 | snd_iprintf(buffer, "ofs=0x%02x, nsteps=0x%02x, stepsize=0x%02x, mute=%x\n", | 61 | snd_iprintf(buffer, "ofs=0x%02x, nsteps=0x%02x, stepsize=0x%02x, " |
62 | "mute=%x\n", | ||
62 | caps & AC_AMPCAP_OFFSET, | 63 | caps & AC_AMPCAP_OFFSET, |
63 | (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT, | 64 | (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT, |
64 | (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT, | 65 | (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT, |
@@ -76,11 +77,13 @@ static void print_amp_vals(struct snd_info_buffer *buffer, | |||
76 | for (i = 0; i < indices; i++) { | 77 | for (i = 0; i < indices; i++) { |
77 | snd_iprintf(buffer, " ["); | 78 | snd_iprintf(buffer, " ["); |
78 | if (stereo) { | 79 | if (stereo) { |
79 | val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, | 80 | val = snd_hda_codec_read(codec, nid, 0, |
81 | AC_VERB_GET_AMP_GAIN_MUTE, | ||
80 | AC_AMP_GET_LEFT | dir | i); | 82 | AC_AMP_GET_LEFT | dir | i); |
81 | snd_iprintf(buffer, "0x%02x ", val); | 83 | snd_iprintf(buffer, "0x%02x ", val); |
82 | } | 84 | } |
83 | val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, | 85 | val = snd_hda_codec_read(codec, nid, 0, |
86 | AC_VERB_GET_AMP_GAIN_MUTE, | ||
84 | AC_AMP_GET_RIGHT | dir | i); | 87 | AC_AMP_GET_RIGHT | dir | i); |
85 | snd_iprintf(buffer, "0x%02x]", val); | 88 | snd_iprintf(buffer, "0x%02x]", val); |
86 | } | 89 | } |
@@ -237,7 +240,8 @@ static void print_pin_caps(struct snd_info_buffer *buffer, | |||
237 | } | 240 | } |
238 | 241 | ||
239 | 242 | ||
240 | static void print_codec_info(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | 243 | static void print_codec_info(struct snd_info_entry *entry, |
244 | struct snd_info_buffer *buffer) | ||
241 | { | 245 | { |
242 | struct hda_codec *codec = entry->private_data; | 246 | struct hda_codec *codec = entry->private_data; |
243 | char buf[32]; | 247 | char buf[32]; |
@@ -258,6 +262,7 @@ static void print_codec_info(struct snd_info_entry *entry, struct snd_info_buffe | |||
258 | 262 | ||
259 | if (! codec->afg) | 263 | if (! codec->afg) |
260 | return; | 264 | return; |
265 | snd_hda_power_up(codec); | ||
261 | snd_iprintf(buffer, "Default PCM:\n"); | 266 | snd_iprintf(buffer, "Default PCM:\n"); |
262 | print_pcm_caps(buffer, codec, codec->afg); | 267 | print_pcm_caps(buffer, codec, codec->afg); |
263 | snd_iprintf(buffer, "Default Amp-In caps: "); | 268 | snd_iprintf(buffer, "Default Amp-In caps: "); |
@@ -268,12 +273,15 @@ static void print_codec_info(struct snd_info_entry *entry, struct snd_info_buffe | |||
268 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); | 273 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); |
269 | if (! nid || nodes < 0) { | 274 | if (! nid || nodes < 0) { |
270 | snd_iprintf(buffer, "Invalid AFG subtree\n"); | 275 | snd_iprintf(buffer, "Invalid AFG subtree\n"); |
276 | snd_hda_power_down(codec); | ||
271 | return; | 277 | return; |
272 | } | 278 | } |
273 | for (i = 0; i < nodes; i++, nid++) { | 279 | for (i = 0; i < nodes; i++, nid++) { |
274 | unsigned int wid_caps = snd_hda_param_read(codec, nid, | 280 | unsigned int wid_caps = |
275 | AC_PAR_AUDIO_WIDGET_CAP); | 281 | snd_hda_param_read(codec, nid, |
276 | unsigned int wid_type = (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | 282 | AC_PAR_AUDIO_WIDGET_CAP); |
283 | unsigned int wid_type = | ||
284 | (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | ||
277 | int conn_len = 0; | 285 | int conn_len = 0; |
278 | hda_nid_t conn[HDA_MAX_CONNECTIONS]; | 286 | hda_nid_t conn[HDA_MAX_CONNECTIONS]; |
279 | 287 | ||
@@ -313,7 +321,9 @@ static void print_codec_info(struct snd_info_entry *entry, struct snd_info_buffe | |||
313 | if (wid_type == AC_WID_PIN) { | 321 | if (wid_type == AC_WID_PIN) { |
314 | unsigned int pinctls; | 322 | unsigned int pinctls; |
315 | print_pin_caps(buffer, codec, nid); | 323 | print_pin_caps(buffer, codec, nid); |
316 | pinctls = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 324 | pinctls = snd_hda_codec_read(codec, nid, 0, |
325 | AC_VERB_GET_PIN_WIDGET_CONTROL, | ||
326 | 0); | ||
317 | snd_iprintf(buffer, " Pin-ctls: 0x%02x:", pinctls); | 327 | snd_iprintf(buffer, " Pin-ctls: 0x%02x:", pinctls); |
318 | if (pinctls & AC_PINCTL_IN_EN) | 328 | if (pinctls & AC_PINCTL_IN_EN) |
319 | snd_iprintf(buffer, " IN"); | 329 | snd_iprintf(buffer, " IN"); |
@@ -333,7 +343,8 @@ static void print_codec_info(struct snd_info_entry *entry, struct snd_info_buffe | |||
333 | if (wid_caps & AC_WCAP_POWER) | 343 | if (wid_caps & AC_WCAP_POWER) |
334 | snd_iprintf(buffer, " Power: 0x%x\n", | 344 | snd_iprintf(buffer, " Power: 0x%x\n", |
335 | snd_hda_codec_read(codec, nid, 0, | 345 | snd_hda_codec_read(codec, nid, 0, |
336 | AC_VERB_GET_POWER_STATE, 0)); | 346 | AC_VERB_GET_POWER_STATE, |
347 | 0)); | ||
337 | 348 | ||
338 | if (wid_caps & AC_WCAP_CONN_LIST) { | 349 | if (wid_caps & AC_WCAP_CONN_LIST) { |
339 | int c, curr = -1; | 350 | int c, curr = -1; |
@@ -350,6 +361,7 @@ static void print_codec_info(struct snd_info_entry *entry, struct snd_info_buffe | |||
350 | snd_iprintf(buffer, "\n"); | 361 | snd_iprintf(buffer, "\n"); |
351 | } | 362 | } |
352 | } | 363 | } |
364 | snd_hda_power_down(codec); | ||
353 | } | 365 | } |
354 | 366 | ||
355 | /* | 367 | /* |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 4d7f8d11ad75..54cfd4526d20 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -73,6 +73,12 @@ struct ad198x_spec { | |||
73 | struct snd_kcontrol_new *kctl_alloc; | 73 | struct snd_kcontrol_new *kctl_alloc; |
74 | struct hda_input_mux private_imux; | 74 | struct hda_input_mux private_imux; |
75 | hda_nid_t private_dac_nids[4]; | 75 | hda_nid_t private_dac_nids[4]; |
76 | |||
77 | unsigned int jack_present :1; | ||
78 | |||
79 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
80 | struct hda_loopback_check loopback; | ||
81 | #endif | ||
76 | }; | 82 | }; |
77 | 83 | ||
78 | /* | 84 | /* |
@@ -144,6 +150,14 @@ static int ad198x_build_controls(struct hda_codec *codec) | |||
144 | return 0; | 150 | return 0; |
145 | } | 151 | } |
146 | 152 | ||
153 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
154 | static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid) | ||
155 | { | ||
156 | struct ad198x_spec *spec = codec->spec; | ||
157 | return snd_hda_check_amp_list_power(codec, &spec->loopback, nid); | ||
158 | } | ||
159 | #endif | ||
160 | |||
147 | /* | 161 | /* |
148 | * Analog playback callbacks | 162 | * Analog playback callbacks |
149 | */ | 163 | */ |
@@ -318,30 +332,13 @@ static void ad198x_free(struct hda_codec *codec) | |||
318 | kfree(codec->spec); | 332 | kfree(codec->spec); |
319 | } | 333 | } |
320 | 334 | ||
321 | #ifdef CONFIG_PM | ||
322 | static int ad198x_resume(struct hda_codec *codec) | ||
323 | { | ||
324 | struct ad198x_spec *spec = codec->spec; | ||
325 | int i; | ||
326 | |||
327 | codec->patch_ops.init(codec); | ||
328 | for (i = 0; i < spec->num_mixers; i++) | ||
329 | snd_hda_resume_ctls(codec, spec->mixers[i]); | ||
330 | if (spec->multiout.dig_out_nid) | ||
331 | snd_hda_resume_spdif_out(codec); | ||
332 | if (spec->dig_in_nid) | ||
333 | snd_hda_resume_spdif_in(codec); | ||
334 | return 0; | ||
335 | } | ||
336 | #endif | ||
337 | |||
338 | static struct hda_codec_ops ad198x_patch_ops = { | 335 | static struct hda_codec_ops ad198x_patch_ops = { |
339 | .build_controls = ad198x_build_controls, | 336 | .build_controls = ad198x_build_controls, |
340 | .build_pcms = ad198x_build_pcms, | 337 | .build_pcms = ad198x_build_pcms, |
341 | .init = ad198x_init, | 338 | .init = ad198x_init, |
342 | .free = ad198x_free, | 339 | .free = ad198x_free, |
343 | #ifdef CONFIG_PM | 340 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
344 | .resume = ad198x_resume, | 341 | .check_power_status = ad198x_check_power_status, |
345 | #endif | 342 | #endif |
346 | }; | 343 | }; |
347 | 344 | ||
@@ -350,15 +347,7 @@ static struct hda_codec_ops ad198x_patch_ops = { | |||
350 | * EAPD control | 347 | * EAPD control |
351 | * the private value = nid | (invert << 8) | 348 | * the private value = nid | (invert << 8) |
352 | */ | 349 | */ |
353 | static int ad198x_eapd_info(struct snd_kcontrol *kcontrol, | 350 | #define ad198x_eapd_info snd_ctl_boolean_mono_info |
354 | struct snd_ctl_elem_info *uinfo) | ||
355 | { | ||
356 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
357 | uinfo->count = 1; | ||
358 | uinfo->value.integer.min = 0; | ||
359 | uinfo->value.integer.max = 1; | ||
360 | return 0; | ||
361 | } | ||
362 | 351 | ||
363 | static int ad198x_eapd_get(struct snd_kcontrol *kcontrol, | 352 | static int ad198x_eapd_get(struct snd_kcontrol *kcontrol, |
364 | struct snd_ctl_elem_value *ucontrol) | 353 | struct snd_ctl_elem_value *ucontrol) |
@@ -384,12 +373,12 @@ static int ad198x_eapd_put(struct snd_kcontrol *kcontrol, | |||
384 | eapd = ucontrol->value.integer.value[0]; | 373 | eapd = ucontrol->value.integer.value[0]; |
385 | if (invert) | 374 | if (invert) |
386 | eapd = !eapd; | 375 | eapd = !eapd; |
387 | if (eapd == spec->cur_eapd && ! codec->in_resume) | 376 | if (eapd == spec->cur_eapd) |
388 | return 0; | 377 | return 0; |
389 | spec->cur_eapd = eapd; | 378 | spec->cur_eapd = eapd; |
390 | snd_hda_codec_write(codec, nid, | 379 | snd_hda_codec_write_cache(codec, nid, |
391 | 0, AC_VERB_SET_EAPD_BTLENABLE, | 380 | 0, AC_VERB_SET_EAPD_BTLENABLE, |
392 | eapd ? 0x02 : 0x00); | 381 | eapd ? 0x02 : 0x00); |
393 | return 1; | 382 | return 1; |
394 | } | 383 | } |
395 | 384 | ||
@@ -430,94 +419,36 @@ static struct hda_input_mux ad1986a_capture_source = { | |||
430 | }, | 419 | }, |
431 | }; | 420 | }; |
432 | 421 | ||
433 | /* | ||
434 | * PCM control | ||
435 | * | ||
436 | * bind volumes/mutes of 3 DACs as a single PCM control for simplicity | ||
437 | */ | ||
438 | |||
439 | #define ad1986a_pcm_amp_vol_info snd_hda_mixer_amp_volume_info | ||
440 | |||
441 | static int ad1986a_pcm_amp_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
442 | { | ||
443 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
444 | struct ad198x_spec *ad = codec->spec; | ||
445 | |||
446 | mutex_lock(&ad->amp_mutex); | ||
447 | snd_hda_mixer_amp_volume_get(kcontrol, ucontrol); | ||
448 | mutex_unlock(&ad->amp_mutex); | ||
449 | return 0; | ||
450 | } | ||
451 | |||
452 | static int ad1986a_pcm_amp_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
453 | { | ||
454 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
455 | struct ad198x_spec *ad = codec->spec; | ||
456 | int i, change = 0; | ||
457 | |||
458 | mutex_lock(&ad->amp_mutex); | ||
459 | for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) { | ||
460 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT); | ||
461 | change |= snd_hda_mixer_amp_volume_put(kcontrol, ucontrol); | ||
462 | } | ||
463 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT); | ||
464 | mutex_unlock(&ad->amp_mutex); | ||
465 | return change; | ||
466 | } | ||
467 | |||
468 | #define ad1986a_pcm_amp_sw_info snd_hda_mixer_amp_switch_info | ||
469 | 422 | ||
470 | static int ad1986a_pcm_amp_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 423 | static struct hda_bind_ctls ad1986a_bind_pcm_vol = { |
471 | { | 424 | .ops = &snd_hda_bind_vol, |
472 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 425 | .values = { |
473 | struct ad198x_spec *ad = codec->spec; | 426 | HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT), |
474 | 427 | HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT), | |
475 | mutex_lock(&ad->amp_mutex); | 428 | HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT), |
476 | snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); | 429 | 0 |
477 | mutex_unlock(&ad->amp_mutex); | 430 | }, |
478 | return 0; | 431 | }; |
479 | } | ||
480 | |||
481 | static int ad1986a_pcm_amp_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
482 | { | ||
483 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
484 | struct ad198x_spec *ad = codec->spec; | ||
485 | int i, change = 0; | ||
486 | 432 | ||
487 | mutex_lock(&ad->amp_mutex); | 433 | static struct hda_bind_ctls ad1986a_bind_pcm_sw = { |
488 | for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) { | 434 | .ops = &snd_hda_bind_sw, |
489 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT); | 435 | .values = { |
490 | change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); | 436 | HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT), |
491 | } | 437 | HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT), |
492 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT); | 438 | HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT), |
493 | mutex_unlock(&ad->amp_mutex); | 439 | 0 |
494 | return change; | 440 | }, |
495 | } | 441 | }; |
496 | 442 | ||
497 | /* | 443 | /* |
498 | * mixers | 444 | * mixers |
499 | */ | 445 | */ |
500 | static struct snd_kcontrol_new ad1986a_mixers[] = { | 446 | static struct snd_kcontrol_new ad1986a_mixers[] = { |
501 | { | 447 | /* |
502 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 448 | * bind volumes/mutes of 3 DACs as a single PCM control for simplicity |
503 | .name = "PCM Playback Volume", | 449 | */ |
504 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | 450 | HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol), |
505 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | | 451 | HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw), |
506 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, | ||
507 | .info = ad1986a_pcm_amp_vol_info, | ||
508 | .get = ad1986a_pcm_amp_vol_get, | ||
509 | .put = ad1986a_pcm_amp_vol_put, | ||
510 | .tlv = { .c = snd_hda_mixer_amp_tlv }, | ||
511 | .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT) | ||
512 | }, | ||
513 | { | ||
514 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
515 | .name = "PCM Playback Switch", | ||
516 | .info = ad1986a_pcm_amp_sw_info, | ||
517 | .get = ad1986a_pcm_amp_sw_get, | ||
518 | .put = ad1986a_pcm_amp_sw_put, | ||
519 | .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT) | ||
520 | }, | ||
521 | HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT), | 452 | HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT), |
522 | HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | 453 | HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), |
523 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT), | 454 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT), |
@@ -569,13 +500,30 @@ static struct snd_kcontrol_new ad1986a_3st_mixers[] = { | |||
569 | /* laptop model - 2ch only */ | 500 | /* laptop model - 2ch only */ |
570 | static hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC }; | 501 | static hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC }; |
571 | 502 | ||
503 | /* master controls both pins 0x1a and 0x1b */ | ||
504 | static struct hda_bind_ctls ad1986a_laptop_master_vol = { | ||
505 | .ops = &snd_hda_bind_vol, | ||
506 | .values = { | ||
507 | HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), | ||
508 | HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT), | ||
509 | 0, | ||
510 | }, | ||
511 | }; | ||
512 | |||
513 | static struct hda_bind_ctls ad1986a_laptop_master_sw = { | ||
514 | .ops = &snd_hda_bind_sw, | ||
515 | .values = { | ||
516 | HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), | ||
517 | HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT), | ||
518 | 0, | ||
519 | }, | ||
520 | }; | ||
521 | |||
572 | static struct snd_kcontrol_new ad1986a_laptop_mixers[] = { | 522 | static struct snd_kcontrol_new ad1986a_laptop_mixers[] = { |
573 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), | 523 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), |
574 | HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), | 524 | HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), |
575 | HDA_CODEC_VOLUME("Master Playback Volume", 0x1b, 0x0, HDA_OUTPUT), | 525 | HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), |
576 | HDA_CODEC_MUTE("Master Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | 526 | HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw), |
577 | /* HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT), | ||
578 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT), */ | ||
579 | HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT), | 527 | HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT), |
580 | HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT), | 528 | HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT), |
581 | HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT), | 529 | HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT), |
@@ -603,68 +551,114 @@ static struct snd_kcontrol_new ad1986a_laptop_mixers[] = { | |||
603 | 551 | ||
604 | /* laptop-eapd model - 2ch only */ | 552 | /* laptop-eapd model - 2ch only */ |
605 | 553 | ||
606 | /* master controls both pins 0x1a and 0x1b */ | 554 | static struct hda_input_mux ad1986a_laptop_eapd_capture_source = { |
607 | static int ad1986a_laptop_master_vol_put(struct snd_kcontrol *kcontrol, | 555 | .num_items = 3, |
608 | struct snd_ctl_elem_value *ucontrol) | 556 | .items = { |
557 | { "Mic", 0x0 }, | ||
558 | { "Internal Mic", 0x4 }, | ||
559 | { "Mix", 0x5 }, | ||
560 | }, | ||
561 | }; | ||
562 | |||
563 | static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { | ||
564 | HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), | ||
565 | HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw), | ||
566 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), | ||
567 | HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), | ||
568 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x0, HDA_OUTPUT), | ||
569 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x0, HDA_OUTPUT), | ||
570 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), | ||
571 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), | ||
572 | HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), | ||
573 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), | ||
574 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), | ||
575 | { | ||
576 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
577 | .name = "Capture Source", | ||
578 | .info = ad198x_mux_enum_info, | ||
579 | .get = ad198x_mux_enum_get, | ||
580 | .put = ad198x_mux_enum_put, | ||
581 | }, | ||
582 | { | ||
583 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
584 | .name = "External Amplifier", | ||
585 | .info = ad198x_eapd_info, | ||
586 | .get = ad198x_eapd_get, | ||
587 | .put = ad198x_eapd_put, | ||
588 | .private_value = 0x1b | (1 << 8), /* port-D, inversed */ | ||
589 | }, | ||
590 | { } /* end */ | ||
591 | }; | ||
592 | |||
593 | /* laptop-automute - 2ch only */ | ||
594 | |||
595 | static void ad1986a_update_hp(struct hda_codec *codec) | ||
609 | { | 596 | { |
610 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 597 | struct ad198x_spec *spec = codec->spec; |
611 | long *valp = ucontrol->value.integer.value; | 598 | unsigned int mute; |
612 | int change; | ||
613 | 599 | ||
614 | change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0, | 600 | if (spec->jack_present) |
615 | 0x7f, valp[0] & 0x7f); | 601 | mute = HDA_AMP_MUTE; /* mute internal speaker */ |
616 | change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0, | 602 | else |
617 | 0x7f, valp[1] & 0x7f); | 603 | /* unmute internal speaker if necessary */ |
618 | snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0, | 604 | mute = snd_hda_codec_amp_read(codec, 0x1a, 0, HDA_OUTPUT, 0); |
619 | 0x7f, valp[0] & 0x7f); | 605 | snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0, |
620 | snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0, | 606 | HDA_AMP_MUTE, mute); |
621 | 0x7f, valp[1] & 0x7f); | ||
622 | return change; | ||
623 | } | 607 | } |
624 | 608 | ||
625 | static int ad1986a_laptop_master_sw_put(struct snd_kcontrol *kcontrol, | 609 | static void ad1986a_hp_automute(struct hda_codec *codec) |
626 | struct snd_ctl_elem_value *ucontrol) | 610 | { |
611 | struct ad198x_spec *spec = codec->spec; | ||
612 | unsigned int present; | ||
613 | |||
614 | present = snd_hda_codec_read(codec, 0x1a, 0, AC_VERB_GET_PIN_SENSE, 0); | ||
615 | spec->jack_present = (present & 0x80000000) != 0; | ||
616 | ad1986a_update_hp(codec); | ||
617 | } | ||
618 | |||
619 | #define AD1986A_HP_EVENT 0x37 | ||
620 | |||
621 | static void ad1986a_hp_unsol_event(struct hda_codec *codec, unsigned int res) | ||
622 | { | ||
623 | if ((res >> 26) != AD1986A_HP_EVENT) | ||
624 | return; | ||
625 | ad1986a_hp_automute(codec); | ||
626 | } | ||
627 | |||
628 | static int ad1986a_hp_init(struct hda_codec *codec) | ||
629 | { | ||
630 | ad198x_init(codec); | ||
631 | ad1986a_hp_automute(codec); | ||
632 | return 0; | ||
633 | } | ||
634 | |||
635 | /* bind hp and internal speaker mute (with plug check) */ | ||
636 | static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol, | ||
637 | struct snd_ctl_elem_value *ucontrol) | ||
627 | { | 638 | { |
628 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 639 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
629 | long *valp = ucontrol->value.integer.value; | 640 | long *valp = ucontrol->value.integer.value; |
630 | int change; | 641 | int change; |
631 | 642 | ||
632 | change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0, | 643 | change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0, |
633 | 0x80, valp[0] ? 0 : 0x80); | 644 | HDA_AMP_MUTE, |
645 | valp[0] ? 0 : HDA_AMP_MUTE); | ||
634 | change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0, | 646 | change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0, |
635 | 0x80, valp[1] ? 0 : 0x80); | 647 | HDA_AMP_MUTE, |
636 | snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0, | 648 | valp[1] ? 0 : HDA_AMP_MUTE); |
637 | 0x80, valp[0] ? 0 : 0x80); | 649 | if (change) |
638 | snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0, | 650 | ad1986a_update_hp(codec); |
639 | 0x80, valp[1] ? 0 : 0x80); | ||
640 | return change; | 651 | return change; |
641 | } | 652 | } |
642 | 653 | ||
643 | static struct hda_input_mux ad1986a_laptop_eapd_capture_source = { | 654 | static struct snd_kcontrol_new ad1986a_laptop_automute_mixers[] = { |
644 | .num_items = 3, | 655 | HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), |
645 | .items = { | ||
646 | { "Mic", 0x0 }, | ||
647 | { "Internal Mic", 0x4 }, | ||
648 | { "Mix", 0x5 }, | ||
649 | }, | ||
650 | }; | ||
651 | |||
652 | static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { | ||
653 | { | ||
654 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
655 | .name = "Master Playback Volume", | ||
656 | .info = snd_hda_mixer_amp_volume_info, | ||
657 | .get = snd_hda_mixer_amp_volume_get, | ||
658 | .put = ad1986a_laptop_master_vol_put, | ||
659 | .tlv = { .c = snd_hda_mixer_amp_tlv }, | ||
660 | .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), | ||
661 | }, | ||
662 | { | 656 | { |
663 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 657 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
664 | .name = "Master Playback Switch", | 658 | .name = "Master Playback Switch", |
665 | .info = snd_hda_mixer_amp_switch_info, | 659 | .info = snd_hda_mixer_amp_switch_info, |
666 | .get = snd_hda_mixer_amp_switch_get, | 660 | .get = snd_hda_mixer_amp_switch_get, |
667 | .put = ad1986a_laptop_master_sw_put, | 661 | .put = ad1986a_hp_master_sw_put, |
668 | .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), | 662 | .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), |
669 | }, | 663 | }, |
670 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), | 664 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), |
@@ -674,6 +668,8 @@ static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { | |||
674 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), | 668 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), |
675 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), | 669 | HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), |
676 | HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), | 670 | HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT), |
671 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x18, 0x0, HDA_OUTPUT), | ||
672 | HDA_CODEC_MUTE("Beep Playback Switch", 0x18, 0x0, HDA_OUTPUT), | ||
677 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), | 673 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), |
678 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), | 674 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), |
679 | { | 675 | { |
@@ -807,12 +803,20 @@ static struct hda_verb ad1986a_ultra_init[] = { | |||
807 | { } /* end */ | 803 | { } /* end */ |
808 | }; | 804 | }; |
809 | 805 | ||
806 | /* pin sensing on HP jack */ | ||
807 | static struct hda_verb ad1986a_hp_init_verbs[] = { | ||
808 | {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_HP_EVENT}, | ||
809 | {} | ||
810 | }; | ||
811 | |||
812 | |||
810 | /* models */ | 813 | /* models */ |
811 | enum { | 814 | enum { |
812 | AD1986A_6STACK, | 815 | AD1986A_6STACK, |
813 | AD1986A_3STACK, | 816 | AD1986A_3STACK, |
814 | AD1986A_LAPTOP, | 817 | AD1986A_LAPTOP, |
815 | AD1986A_LAPTOP_EAPD, | 818 | AD1986A_LAPTOP_EAPD, |
819 | AD1986A_LAPTOP_AUTOMUTE, | ||
816 | AD1986A_ULTRA, | 820 | AD1986A_ULTRA, |
817 | AD1986A_MODELS | 821 | AD1986A_MODELS |
818 | }; | 822 | }; |
@@ -822,6 +826,7 @@ static const char *ad1986a_models[AD1986A_MODELS] = { | |||
822 | [AD1986A_3STACK] = "3stack", | 826 | [AD1986A_3STACK] = "3stack", |
823 | [AD1986A_LAPTOP] = "laptop", | 827 | [AD1986A_LAPTOP] = "laptop", |
824 | [AD1986A_LAPTOP_EAPD] = "laptop-eapd", | 828 | [AD1986A_LAPTOP_EAPD] = "laptop-eapd", |
829 | [AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute", | ||
825 | [AD1986A_ULTRA] = "ultra", | 830 | [AD1986A_ULTRA] = "ultra", |
826 | }; | 831 | }; |
827 | 832 | ||
@@ -850,11 +855,22 @@ static struct snd_pci_quirk ad1986a_cfg_tbl[] = { | |||
850 | SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA), | 855 | SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA), |
851 | SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP), | 856 | SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP), |
852 | SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK), | 857 | SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK), |
853 | SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_EAPD), | 858 | SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE), |
854 | SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP), | 859 | SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP), |
855 | {} | 860 | {} |
856 | }; | 861 | }; |
857 | 862 | ||
863 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
864 | static struct hda_amp_list ad1986a_loopbacks[] = { | ||
865 | { 0x13, HDA_OUTPUT, 0 }, /* Mic */ | ||
866 | { 0x14, HDA_OUTPUT, 0 }, /* Phone */ | ||
867 | { 0x15, HDA_OUTPUT, 0 }, /* CD */ | ||
868 | { 0x16, HDA_OUTPUT, 0 }, /* Aux */ | ||
869 | { 0x17, HDA_OUTPUT, 0 }, /* Line */ | ||
870 | { } /* end */ | ||
871 | }; | ||
872 | #endif | ||
873 | |||
858 | static int patch_ad1986a(struct hda_codec *codec) | 874 | static int patch_ad1986a(struct hda_codec *codec) |
859 | { | 875 | { |
860 | struct ad198x_spec *spec; | 876 | struct ad198x_spec *spec; |
@@ -864,7 +880,6 @@ static int patch_ad1986a(struct hda_codec *codec) | |||
864 | if (spec == NULL) | 880 | if (spec == NULL) |
865 | return -ENOMEM; | 881 | return -ENOMEM; |
866 | 882 | ||
867 | mutex_init(&spec->amp_mutex); | ||
868 | codec->spec = spec; | 883 | codec->spec = spec; |
869 | 884 | ||
870 | spec->multiout.max_channels = 6; | 885 | spec->multiout.max_channels = 6; |
@@ -879,6 +894,9 @@ static int patch_ad1986a(struct hda_codec *codec) | |||
879 | spec->mixers[0] = ad1986a_mixers; | 894 | spec->mixers[0] = ad1986a_mixers; |
880 | spec->num_init_verbs = 1; | 895 | spec->num_init_verbs = 1; |
881 | spec->init_verbs[0] = ad1986a_init_verbs; | 896 | spec->init_verbs[0] = ad1986a_init_verbs; |
897 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
898 | spec->loopback.amplist = ad1986a_loopbacks; | ||
899 | #endif | ||
882 | 900 | ||
883 | codec->patch_ops = ad198x_patch_ops; | 901 | codec->patch_ops = ad198x_patch_ops; |
884 | 902 | ||
@@ -914,6 +932,19 @@ static int patch_ad1986a(struct hda_codec *codec) | |||
914 | spec->multiout.dig_out_nid = 0; | 932 | spec->multiout.dig_out_nid = 0; |
915 | spec->input_mux = &ad1986a_laptop_eapd_capture_source; | 933 | spec->input_mux = &ad1986a_laptop_eapd_capture_source; |
916 | break; | 934 | break; |
935 | case AD1986A_LAPTOP_AUTOMUTE: | ||
936 | spec->mixers[0] = ad1986a_laptop_automute_mixers; | ||
937 | spec->num_init_verbs = 3; | ||
938 | spec->init_verbs[1] = ad1986a_eapd_init_verbs; | ||
939 | spec->init_verbs[2] = ad1986a_hp_init_verbs; | ||
940 | spec->multiout.max_channels = 2; | ||
941 | spec->multiout.num_dacs = 1; | ||
942 | spec->multiout.dac_nids = ad1986a_laptop_dac_nids; | ||
943 | spec->multiout.dig_out_nid = 0; | ||
944 | spec->input_mux = &ad1986a_laptop_eapd_capture_source; | ||
945 | codec->patch_ops.unsol_event = ad1986a_hp_unsol_event; | ||
946 | codec->patch_ops.init = ad1986a_hp_init; | ||
947 | break; | ||
917 | case AD1986A_ULTRA: | 948 | case AD1986A_ULTRA: |
918 | spec->mixers[0] = ad1986a_laptop_eapd_mixers; | 949 | spec->mixers[0] = ad1986a_laptop_eapd_mixers; |
919 | spec->num_init_verbs = 2; | 950 | spec->num_init_verbs = 2; |
@@ -982,8 +1013,9 @@ static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
982 | 1013 | ||
983 | if (spec->spdif_route != ucontrol->value.enumerated.item[0]) { | 1014 | if (spec->spdif_route != ucontrol->value.enumerated.item[0]) { |
984 | spec->spdif_route = ucontrol->value.enumerated.item[0]; | 1015 | spec->spdif_route = ucontrol->value.enumerated.item[0]; |
985 | snd_hda_codec_write(codec, spec->multiout.dig_out_nid, 0, | 1016 | snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0, |
986 | AC_VERB_SET_CONNECT_SEL, spec->spdif_route); | 1017 | AC_VERB_SET_CONNECT_SEL, |
1018 | spec->spdif_route); | ||
987 | return 1; | 1019 | return 1; |
988 | } | 1020 | } |
989 | return 0; | 1021 | return 0; |
@@ -1063,6 +1095,13 @@ static struct hda_verb ad1983_init_verbs[] = { | |||
1063 | { } /* end */ | 1095 | { } /* end */ |
1064 | }; | 1096 | }; |
1065 | 1097 | ||
1098 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1099 | static struct hda_amp_list ad1983_loopbacks[] = { | ||
1100 | { 0x12, HDA_OUTPUT, 0 }, /* Mic */ | ||
1101 | { 0x13, HDA_OUTPUT, 0 }, /* Line */ | ||
1102 | { } /* end */ | ||
1103 | }; | ||
1104 | #endif | ||
1066 | 1105 | ||
1067 | static int patch_ad1983(struct hda_codec *codec) | 1106 | static int patch_ad1983(struct hda_codec *codec) |
1068 | { | 1107 | { |
@@ -1072,7 +1111,6 @@ static int patch_ad1983(struct hda_codec *codec) | |||
1072 | if (spec == NULL) | 1111 | if (spec == NULL) |
1073 | return -ENOMEM; | 1112 | return -ENOMEM; |
1074 | 1113 | ||
1075 | mutex_init(&spec->amp_mutex); | ||
1076 | codec->spec = spec; | 1114 | codec->spec = spec; |
1077 | 1115 | ||
1078 | spec->multiout.max_channels = 2; | 1116 | spec->multiout.max_channels = 2; |
@@ -1088,6 +1126,9 @@ static int patch_ad1983(struct hda_codec *codec) | |||
1088 | spec->num_init_verbs = 1; | 1126 | spec->num_init_verbs = 1; |
1089 | spec->init_verbs[0] = ad1983_init_verbs; | 1127 | spec->init_verbs[0] = ad1983_init_verbs; |
1090 | spec->spdif_route = 0; | 1128 | spec->spdif_route = 0; |
1129 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1130 | spec->loopback.amplist = ad1983_loopbacks; | ||
1131 | #endif | ||
1091 | 1132 | ||
1092 | codec->patch_ops = ad198x_patch_ops; | 1133 | codec->patch_ops = ad198x_patch_ops; |
1093 | 1134 | ||
@@ -1211,6 +1252,17 @@ static struct hda_verb ad1981_init_verbs[] = { | |||
1211 | { } /* end */ | 1252 | { } /* end */ |
1212 | }; | 1253 | }; |
1213 | 1254 | ||
1255 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1256 | static struct hda_amp_list ad1981_loopbacks[] = { | ||
1257 | { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */ | ||
1258 | { 0x13, HDA_OUTPUT, 0 }, /* Line */ | ||
1259 | { 0x1b, HDA_OUTPUT, 0 }, /* Aux */ | ||
1260 | { 0x1c, HDA_OUTPUT, 0 }, /* Mic */ | ||
1261 | { 0x1d, HDA_OUTPUT, 0 }, /* CD */ | ||
1262 | { } /* end */ | ||
1263 | }; | ||
1264 | #endif | ||
1265 | |||
1214 | /* | 1266 | /* |
1215 | * Patch for HP nx6320 | 1267 | * Patch for HP nx6320 |
1216 | * | 1268 | * |
@@ -1240,31 +1292,21 @@ static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol, | |||
1240 | return 0; | 1292 | return 0; |
1241 | 1293 | ||
1242 | /* toggle HP mute appropriately */ | 1294 | /* toggle HP mute appropriately */ |
1243 | snd_hda_codec_amp_update(codec, 0x06, 0, HDA_OUTPUT, 0, | 1295 | snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0, |
1244 | 0x80, spec->cur_eapd ? 0 : 0x80); | 1296 | HDA_AMP_MUTE, |
1245 | snd_hda_codec_amp_update(codec, 0x06, 1, HDA_OUTPUT, 0, | 1297 | spec->cur_eapd ? 0 : HDA_AMP_MUTE); |
1246 | 0x80, spec->cur_eapd ? 0 : 0x80); | ||
1247 | return 1; | 1298 | return 1; |
1248 | } | 1299 | } |
1249 | 1300 | ||
1250 | /* bind volumes of both NID 0x05 and 0x06 */ | 1301 | /* bind volumes of both NID 0x05 and 0x06 */ |
1251 | static int ad1981_hp_master_vol_put(struct snd_kcontrol *kcontrol, | 1302 | static struct hda_bind_ctls ad1981_hp_bind_master_vol = { |
1252 | struct snd_ctl_elem_value *ucontrol) | 1303 | .ops = &snd_hda_bind_vol, |
1253 | { | 1304 | .values = { |
1254 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1305 | HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT), |
1255 | long *valp = ucontrol->value.integer.value; | 1306 | HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT), |
1256 | int change; | 1307 | 0 |
1257 | 1308 | }, | |
1258 | change = snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0, | 1309 | }; |
1259 | 0x7f, valp[0] & 0x7f); | ||
1260 | change |= snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0, | ||
1261 | 0x7f, valp[1] & 0x7f); | ||
1262 | snd_hda_codec_amp_update(codec, 0x06, 0, HDA_OUTPUT, 0, | ||
1263 | 0x7f, valp[0] & 0x7f); | ||
1264 | snd_hda_codec_amp_update(codec, 0x06, 1, HDA_OUTPUT, 0, | ||
1265 | 0x7f, valp[1] & 0x7f); | ||
1266 | return change; | ||
1267 | } | ||
1268 | 1310 | ||
1269 | /* mute internal speaker if HP is plugged */ | 1311 | /* mute internal speaker if HP is plugged */ |
1270 | static void ad1981_hp_automute(struct hda_codec *codec) | 1312 | static void ad1981_hp_automute(struct hda_codec *codec) |
@@ -1273,10 +1315,8 @@ static void ad1981_hp_automute(struct hda_codec *codec) | |||
1273 | 1315 | ||
1274 | present = snd_hda_codec_read(codec, 0x06, 0, | 1316 | present = snd_hda_codec_read(codec, 0x06, 0, |
1275 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 1317 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
1276 | snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0, | 1318 | snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0, |
1277 | 0x80, present ? 0x80 : 0); | 1319 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); |
1278 | snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0, | ||
1279 | 0x80, present ? 0x80 : 0); | ||
1280 | } | 1320 | } |
1281 | 1321 | ||
1282 | /* toggle input of built-in and mic jack appropriately */ | 1322 | /* toggle input of built-in and mic jack appropriately */ |
@@ -1327,14 +1367,7 @@ static struct hda_input_mux ad1981_hp_capture_source = { | |||
1327 | }; | 1367 | }; |
1328 | 1368 | ||
1329 | static struct snd_kcontrol_new ad1981_hp_mixers[] = { | 1369 | static struct snd_kcontrol_new ad1981_hp_mixers[] = { |
1330 | { | 1370 | HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol), |
1331 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1332 | .name = "Master Playback Volume", | ||
1333 | .info = snd_hda_mixer_amp_volume_info, | ||
1334 | .get = snd_hda_mixer_amp_volume_get, | ||
1335 | .put = ad1981_hp_master_vol_put, | ||
1336 | .private_value = HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT), | ||
1337 | }, | ||
1338 | { | 1371 | { |
1339 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1372 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1340 | .name = "Master Playback Switch", | 1373 | .name = "Master Playback Switch", |
@@ -1474,7 +1507,6 @@ static int patch_ad1981(struct hda_codec *codec) | |||
1474 | if (spec == NULL) | 1507 | if (spec == NULL) |
1475 | return -ENOMEM; | 1508 | return -ENOMEM; |
1476 | 1509 | ||
1477 | mutex_init(&spec->amp_mutex); | ||
1478 | codec->spec = spec; | 1510 | codec->spec = spec; |
1479 | 1511 | ||
1480 | spec->multiout.max_channels = 2; | 1512 | spec->multiout.max_channels = 2; |
@@ -1490,6 +1522,9 @@ static int patch_ad1981(struct hda_codec *codec) | |||
1490 | spec->num_init_verbs = 1; | 1522 | spec->num_init_verbs = 1; |
1491 | spec->init_verbs[0] = ad1981_init_verbs; | 1523 | spec->init_verbs[0] = ad1981_init_verbs; |
1492 | spec->spdif_route = 0; | 1524 | spec->spdif_route = 0; |
1525 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1526 | spec->loopback.amplist = ad1981_loopbacks; | ||
1527 | #endif | ||
1493 | 1528 | ||
1494 | codec->patch_ops = ad198x_patch_ops; | 1529 | codec->patch_ops = ad198x_patch_ops; |
1495 | 1530 | ||
@@ -1897,16 +1932,19 @@ static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol, | |||
1897 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1932 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1898 | unsigned int sel; | 1933 | unsigned int sel; |
1899 | 1934 | ||
1900 | sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0); | 1935 | sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE, |
1901 | if (sel > 0) { | 1936 | AC_AMP_GET_INPUT); |
1937 | if (!(sel & 0x80)) | ||
1938 | ucontrol->value.enumerated.item[0] = 0; | ||
1939 | else { | ||
1902 | sel = snd_hda_codec_read(codec, 0x0b, 0, | 1940 | sel = snd_hda_codec_read(codec, 0x0b, 0, |
1903 | AC_VERB_GET_CONNECT_SEL, 0); | 1941 | AC_VERB_GET_CONNECT_SEL, 0); |
1904 | if (sel < 3) | 1942 | if (sel < 3) |
1905 | sel++; | 1943 | sel++; |
1906 | else | 1944 | else |
1907 | sel = 0; | 1945 | sel = 0; |
1946 | ucontrol->value.enumerated.item[0] = sel; | ||
1908 | } | 1947 | } |
1909 | ucontrol->value.enumerated.item[0] = sel; | ||
1910 | return 0; | 1948 | return 0; |
1911 | } | 1949 | } |
1912 | 1950 | ||
@@ -1918,23 +1956,39 @@ static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol, | |||
1918 | int change; | 1956 | int change; |
1919 | 1957 | ||
1920 | val = ucontrol->value.enumerated.item[0]; | 1958 | val = ucontrol->value.enumerated.item[0]; |
1921 | sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0); | ||
1922 | if (!val) { | 1959 | if (!val) { |
1923 | change = sel != 0; | 1960 | sel = snd_hda_codec_read(codec, 0x1d, 0, |
1924 | if (change || codec->in_resume) | 1961 | AC_VERB_GET_AMP_GAIN_MUTE, |
1925 | snd_hda_codec_write(codec, 0x02, 0, | 1962 | AC_AMP_GET_INPUT); |
1926 | AC_VERB_SET_CONNECT_SEL, 0); | 1963 | change = sel & 0x80; |
1964 | if (change) { | ||
1965 | snd_hda_codec_write_cache(codec, 0x1d, 0, | ||
1966 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
1967 | AMP_IN_UNMUTE(0)); | ||
1968 | snd_hda_codec_write_cache(codec, 0x1d, 0, | ||
1969 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
1970 | AMP_IN_MUTE(1)); | ||
1971 | } | ||
1927 | } else { | 1972 | } else { |
1928 | change = sel == 0; | 1973 | sel = snd_hda_codec_read(codec, 0x1d, 0, |
1929 | if (change || codec->in_resume) | 1974 | AC_VERB_GET_AMP_GAIN_MUTE, |
1930 | snd_hda_codec_write(codec, 0x02, 0, | 1975 | AC_AMP_GET_INPUT | 0x01); |
1931 | AC_VERB_SET_CONNECT_SEL, 1); | 1976 | change = sel & 0x80; |
1977 | if (change) { | ||
1978 | snd_hda_codec_write_cache(codec, 0x1d, 0, | ||
1979 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
1980 | AMP_IN_MUTE(0)); | ||
1981 | snd_hda_codec_write_cache(codec, 0x1d, 0, | ||
1982 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
1983 | AMP_IN_UNMUTE(1)); | ||
1984 | } | ||
1932 | sel = snd_hda_codec_read(codec, 0x0b, 0, | 1985 | sel = snd_hda_codec_read(codec, 0x0b, 0, |
1933 | AC_VERB_GET_CONNECT_SEL, 0) + 1; | 1986 | AC_VERB_GET_CONNECT_SEL, 0) + 1; |
1934 | change |= sel != val; | 1987 | change |= sel != val; |
1935 | if (change || codec->in_resume) | 1988 | if (change) |
1936 | snd_hda_codec_write(codec, 0x0b, 0, | 1989 | snd_hda_codec_write_cache(codec, 0x0b, 0, |
1937 | AC_VERB_SET_CONNECT_SEL, val - 1); | 1990 | AC_VERB_SET_CONNECT_SEL, |
1991 | val - 1); | ||
1938 | } | 1992 | } |
1939 | return change; | 1993 | return change; |
1940 | } | 1994 | } |
@@ -2047,10 +2101,9 @@ static struct hda_verb ad1988_spdif_init_verbs[] = { | |||
2047 | {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */ | 2101 | {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */ |
2048 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */ | 2102 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */ |
2049 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 2103 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
2050 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 2104 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
2051 | /* SPDIF out pin */ | 2105 | /* SPDIF out pin */ |
2052 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ | 2106 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ |
2053 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x17}, /* 0dB */ | ||
2054 | 2107 | ||
2055 | { } | 2108 | { } |
2056 | }; | 2109 | }; |
@@ -2225,6 +2278,15 @@ static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res) | |||
2225 | snd_hda_sequence_write(codec, ad1988_laptop_hp_off); | 2278 | snd_hda_sequence_write(codec, ad1988_laptop_hp_off); |
2226 | } | 2279 | } |
2227 | 2280 | ||
2281 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
2282 | static struct hda_amp_list ad1988_loopbacks[] = { | ||
2283 | { 0x20, HDA_INPUT, 0 }, /* Front Mic */ | ||
2284 | { 0x20, HDA_INPUT, 1 }, /* Line */ | ||
2285 | { 0x20, HDA_INPUT, 4 }, /* Mic */ | ||
2286 | { 0x20, HDA_INPUT, 6 }, /* CD */ | ||
2287 | { } /* end */ | ||
2288 | }; | ||
2289 | #endif | ||
2228 | 2290 | ||
2229 | /* | 2291 | /* |
2230 | * Automatic parse of I/O pins from the BIOS configuration | 2292 | * Automatic parse of I/O pins from the BIOS configuration |
@@ -2663,7 +2725,6 @@ static int patch_ad1988(struct hda_codec *codec) | |||
2663 | if (spec == NULL) | 2725 | if (spec == NULL) |
2664 | return -ENOMEM; | 2726 | return -ENOMEM; |
2665 | 2727 | ||
2666 | mutex_init(&spec->amp_mutex); | ||
2667 | codec->spec = spec; | 2728 | codec->spec = spec; |
2668 | 2729 | ||
2669 | if (is_rev2(codec)) | 2730 | if (is_rev2(codec)) |
@@ -2770,6 +2831,9 @@ static int patch_ad1988(struct hda_codec *codec) | |||
2770 | codec->patch_ops.unsol_event = ad1988_laptop_unsol_event; | 2831 | codec->patch_ops.unsol_event = ad1988_laptop_unsol_event; |
2771 | break; | 2832 | break; |
2772 | } | 2833 | } |
2834 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
2835 | spec->loopback.amplist = ad1988_loopbacks; | ||
2836 | #endif | ||
2773 | 2837 | ||
2774 | return 0; | 2838 | return 0; |
2775 | } | 2839 | } |
@@ -2926,6 +2990,16 @@ static struct hda_verb ad1884_init_verbs[] = { | |||
2926 | { } /* end */ | 2990 | { } /* end */ |
2927 | }; | 2991 | }; |
2928 | 2992 | ||
2993 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
2994 | static struct hda_amp_list ad1884_loopbacks[] = { | ||
2995 | { 0x20, HDA_INPUT, 0 }, /* Front Mic */ | ||
2996 | { 0x20, HDA_INPUT, 1 }, /* Mic */ | ||
2997 | { 0x20, HDA_INPUT, 2 }, /* CD */ | ||
2998 | { 0x20, HDA_INPUT, 4 }, /* Docking */ | ||
2999 | { } /* end */ | ||
3000 | }; | ||
3001 | #endif | ||
3002 | |||
2929 | static int patch_ad1884(struct hda_codec *codec) | 3003 | static int patch_ad1884(struct hda_codec *codec) |
2930 | { | 3004 | { |
2931 | struct ad198x_spec *spec; | 3005 | struct ad198x_spec *spec; |
@@ -2950,6 +3024,9 @@ static int patch_ad1884(struct hda_codec *codec) | |||
2950 | spec->num_init_verbs = 1; | 3024 | spec->num_init_verbs = 1; |
2951 | spec->init_verbs[0] = ad1884_init_verbs; | 3025 | spec->init_verbs[0] = ad1884_init_verbs; |
2952 | spec->spdif_route = 0; | 3026 | spec->spdif_route = 0; |
3027 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
3028 | spec->loopback.amplist = ad1884_loopbacks; | ||
3029 | #endif | ||
2953 | 3030 | ||
2954 | codec->patch_ops = ad198x_patch_ops; | 3031 | codec->patch_ops = ad198x_patch_ops; |
2955 | 3032 | ||
@@ -3331,6 +3408,16 @@ static struct hda_verb ad1882_init_verbs[] = { | |||
3331 | { } /* end */ | 3408 | { } /* end */ |
3332 | }; | 3409 | }; |
3333 | 3410 | ||
3411 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
3412 | static struct hda_amp_list ad1882_loopbacks[] = { | ||
3413 | { 0x20, HDA_INPUT, 0 }, /* Front Mic */ | ||
3414 | { 0x20, HDA_INPUT, 1 }, /* Mic */ | ||
3415 | { 0x20, HDA_INPUT, 4 }, /* Line */ | ||
3416 | { 0x20, HDA_INPUT, 6 }, /* CD */ | ||
3417 | { } /* end */ | ||
3418 | }; | ||
3419 | #endif | ||
3420 | |||
3334 | /* models */ | 3421 | /* models */ |
3335 | enum { | 3422 | enum { |
3336 | AD1882_3STACK, | 3423 | AD1882_3STACK, |
@@ -3369,6 +3456,9 @@ static int patch_ad1882(struct hda_codec *codec) | |||
3369 | spec->num_init_verbs = 1; | 3456 | spec->num_init_verbs = 1; |
3370 | spec->init_verbs[0] = ad1882_init_verbs; | 3457 | spec->init_verbs[0] = ad1882_init_verbs; |
3371 | spec->spdif_route = 0; | 3458 | spec->spdif_route = 0; |
3459 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
3460 | spec->loopback.amplist = ad1882_loopbacks; | ||
3461 | #endif | ||
3372 | 3462 | ||
3373 | codec->patch_ops = ad198x_patch_ops; | 3463 | codec->patch_ops = ad198x_patch_ops; |
3374 | 3464 | ||
diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c index 72d3ab9751ac..fbb8969dc559 100644 --- a/sound/pci/hda/patch_atihdmi.c +++ b/sound/pci/hda/patch_atihdmi.c | |||
@@ -62,19 +62,6 @@ static int atihdmi_init(struct hda_codec *codec) | |||
62 | return 0; | 62 | return 0; |
63 | } | 63 | } |
64 | 64 | ||
65 | #ifdef CONFIG_PM | ||
66 | /* | ||
67 | * resume | ||
68 | */ | ||
69 | static int atihdmi_resume(struct hda_codec *codec) | ||
70 | { | ||
71 | atihdmi_init(codec); | ||
72 | snd_hda_resume_spdif_out(codec); | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | #endif | ||
77 | |||
78 | /* | 65 | /* |
79 | * Digital out | 66 | * Digital out |
80 | */ | 67 | */ |
@@ -141,9 +128,6 @@ static struct hda_codec_ops atihdmi_patch_ops = { | |||
141 | .build_pcms = atihdmi_build_pcms, | 128 | .build_pcms = atihdmi_build_pcms, |
142 | .init = atihdmi_init, | 129 | .init = atihdmi_init, |
143 | .free = atihdmi_free, | 130 | .free = atihdmi_free, |
144 | #ifdef CONFIG_PM | ||
145 | .resume = atihdmi_resume, | ||
146 | #endif | ||
147 | }; | 131 | }; |
148 | 132 | ||
149 | static int patch_atihdmi(struct hda_codec *codec) | 133 | static int patch_atihdmi(struct hda_codec *codec) |
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c index 3c722e667bc8..2468f3171222 100644 --- a/sound/pci/hda/patch_cmedia.c +++ b/sound/pci/hda/patch_cmedia.c | |||
@@ -427,27 +427,6 @@ static int cmi9880_init(struct hda_codec *codec) | |||
427 | return 0; | 427 | return 0; |
428 | } | 428 | } |
429 | 429 | ||
430 | #ifdef CONFIG_PM | ||
431 | /* | ||
432 | * resume | ||
433 | */ | ||
434 | static int cmi9880_resume(struct hda_codec *codec) | ||
435 | { | ||
436 | struct cmi_spec *spec = codec->spec; | ||
437 | |||
438 | cmi9880_init(codec); | ||
439 | snd_hda_resume_ctls(codec, cmi9880_basic_mixer); | ||
440 | if (spec->channel_modes) | ||
441 | snd_hda_resume_ctls(codec, cmi9880_ch_mode_mixer); | ||
442 | if (spec->multiout.dig_out_nid) | ||
443 | snd_hda_resume_spdif_out(codec); | ||
444 | if (spec->dig_in_nid) | ||
445 | snd_hda_resume_spdif_in(codec); | ||
446 | |||
447 | return 0; | ||
448 | } | ||
449 | #endif | ||
450 | |||
451 | /* | 430 | /* |
452 | * Analog playback callbacks | 431 | * Analog playback callbacks |
453 | */ | 432 | */ |
@@ -635,9 +614,6 @@ static struct hda_codec_ops cmi9880_patch_ops = { | |||
635 | .build_pcms = cmi9880_build_pcms, | 614 | .build_pcms = cmi9880_build_pcms, |
636 | .init = cmi9880_init, | 615 | .init = cmi9880_init, |
637 | .free = cmi9880_free, | 616 | .free = cmi9880_free, |
638 | #ifdef CONFIG_PM | ||
639 | .resume = cmi9880_resume, | ||
640 | #endif | ||
641 | }; | 617 | }; |
642 | 618 | ||
643 | static int patch_cmi9880(struct hda_codec *codec) | 619 | static int patch_cmi9880(struct hda_codec *codec) |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 4d8e8af5c819..080e3001d9c5 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -311,23 +311,6 @@ static void conexant_free(struct hda_codec *codec) | |||
311 | kfree(codec->spec); | 311 | kfree(codec->spec); |
312 | } | 312 | } |
313 | 313 | ||
314 | #ifdef CONFIG_PM | ||
315 | static int conexant_resume(struct hda_codec *codec) | ||
316 | { | ||
317 | struct conexant_spec *spec = codec->spec; | ||
318 | int i; | ||
319 | |||
320 | codec->patch_ops.init(codec); | ||
321 | for (i = 0; i < spec->num_mixers; i++) | ||
322 | snd_hda_resume_ctls(codec, spec->mixers[i]); | ||
323 | if (spec->multiout.dig_out_nid) | ||
324 | snd_hda_resume_spdif_out(codec); | ||
325 | if (spec->dig_in_nid) | ||
326 | snd_hda_resume_spdif_in(codec); | ||
327 | return 0; | ||
328 | } | ||
329 | #endif | ||
330 | |||
331 | static int conexant_build_controls(struct hda_codec *codec) | 314 | static int conexant_build_controls(struct hda_codec *codec) |
332 | { | 315 | { |
333 | struct conexant_spec *spec = codec->spec; | 316 | struct conexant_spec *spec = codec->spec; |
@@ -358,9 +341,6 @@ static struct hda_codec_ops conexant_patch_ops = { | |||
358 | .build_pcms = conexant_build_pcms, | 341 | .build_pcms = conexant_build_pcms, |
359 | .init = conexant_init, | 342 | .init = conexant_init, |
360 | .free = conexant_free, | 343 | .free = conexant_free, |
361 | #ifdef CONFIG_PM | ||
362 | .resume = conexant_resume, | ||
363 | #endif | ||
364 | }; | 344 | }; |
365 | 345 | ||
366 | /* | 346 | /* |
@@ -368,15 +348,7 @@ static struct hda_codec_ops conexant_patch_ops = { | |||
368 | * the private value = nid | (invert << 8) | 348 | * the private value = nid | (invert << 8) |
369 | */ | 349 | */ |
370 | 350 | ||
371 | static int cxt_eapd_info(struct snd_kcontrol *kcontrol, | 351 | #define cxt_eapd_info snd_ctl_boolean_mono_info |
372 | struct snd_ctl_elem_info *uinfo) | ||
373 | { | ||
374 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
375 | uinfo->count = 1; | ||
376 | uinfo->value.integer.min = 0; | ||
377 | uinfo->value.integer.max = 1; | ||
378 | return 0; | ||
379 | } | ||
380 | 352 | ||
381 | static int cxt_eapd_get(struct snd_kcontrol *kcontrol, | 353 | static int cxt_eapd_get(struct snd_kcontrol *kcontrol, |
382 | struct snd_ctl_elem_value *ucontrol) | 354 | struct snd_ctl_elem_value *ucontrol) |
@@ -404,13 +376,13 @@ static int cxt_eapd_put(struct snd_kcontrol *kcontrol, | |||
404 | eapd = ucontrol->value.integer.value[0]; | 376 | eapd = ucontrol->value.integer.value[0]; |
405 | if (invert) | 377 | if (invert) |
406 | eapd = !eapd; | 378 | eapd = !eapd; |
407 | if (eapd == spec->cur_eapd && !codec->in_resume) | 379 | if (eapd == spec->cur_eapd) |
408 | return 0; | 380 | return 0; |
409 | 381 | ||
410 | spec->cur_eapd = eapd; | 382 | spec->cur_eapd = eapd; |
411 | snd_hda_codec_write(codec, nid, | 383 | snd_hda_codec_write_cache(codec, nid, |
412 | 0, AC_VERB_SET_EAPD_BTLENABLE, | 384 | 0, AC_VERB_SET_EAPD_BTLENABLE, |
413 | eapd ? 0x02 : 0x00); | 385 | eapd ? 0x02 : 0x00); |
414 | return 1; | 386 | return 1; |
415 | } | 387 | } |
416 | 388 | ||
@@ -500,34 +472,25 @@ static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol, | |||
500 | /* toggle internal speakers mute depending of presence of | 472 | /* toggle internal speakers mute depending of presence of |
501 | * the headphone jack | 473 | * the headphone jack |
502 | */ | 474 | */ |
503 | bits = (!spec->hp_present && spec->cur_eapd) ? 0 : 0x80; | 475 | bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE; |
504 | snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits); | 476 | snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0, |
505 | snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits); | 477 | HDA_AMP_MUTE, bits); |
506 | 478 | ||
507 | bits = spec->cur_eapd ? 0 : 0x80; | 479 | bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE; |
508 | snd_hda_codec_amp_update(codec, 0x11, 0, HDA_OUTPUT, 0, 0x80, bits); | 480 | snd_hda_codec_amp_stereo(codec, 0x11, HDA_OUTPUT, 0, |
509 | snd_hda_codec_amp_update(codec, 0x11, 1, HDA_OUTPUT, 0, 0x80, bits); | 481 | HDA_AMP_MUTE, bits); |
510 | return 1; | 482 | return 1; |
511 | } | 483 | } |
512 | 484 | ||
513 | /* bind volumes of both NID 0x10 and 0x11 */ | 485 | /* bind volumes of both NID 0x10 and 0x11 */ |
514 | static int cxt5045_hp_master_vol_put(struct snd_kcontrol *kcontrol, | 486 | static struct hda_bind_ctls cxt5045_hp_bind_master_vol = { |
515 | struct snd_ctl_elem_value *ucontrol) | 487 | .ops = &snd_hda_bind_vol, |
516 | { | 488 | .values = { |
517 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 489 | HDA_COMPOSE_AMP_VAL(0x10, 3, 0, HDA_OUTPUT), |
518 | long *valp = ucontrol->value.integer.value; | 490 | HDA_COMPOSE_AMP_VAL(0x11, 3, 0, HDA_OUTPUT), |
519 | int change; | 491 | 0 |
520 | 492 | }, | |
521 | change = snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, | 493 | }; |
522 | 0x7f, valp[0] & 0x7f); | ||
523 | change |= snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, | ||
524 | 0x7f, valp[1] & 0x7f); | ||
525 | snd_hda_codec_amp_update(codec, 0x11, 0, HDA_OUTPUT, 0, | ||
526 | 0x7f, valp[0] & 0x7f); | ||
527 | snd_hda_codec_amp_update(codec, 0x11, 1, HDA_OUTPUT, 0, | ||
528 | 0x7f, valp[1] & 0x7f); | ||
529 | return change; | ||
530 | } | ||
531 | 494 | ||
532 | /* toggle input of built-in and mic jack appropriately */ | 495 | /* toggle input of built-in and mic jack appropriately */ |
533 | static void cxt5045_hp_automic(struct hda_codec *codec) | 496 | static void cxt5045_hp_automic(struct hda_codec *codec) |
@@ -562,9 +525,9 @@ static void cxt5045_hp_automute(struct hda_codec *codec) | |||
562 | spec->hp_present = snd_hda_codec_read(codec, 0x11, 0, | 525 | spec->hp_present = snd_hda_codec_read(codec, 0x11, 0, |
563 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 526 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
564 | 527 | ||
565 | bits = (spec->hp_present || !spec->cur_eapd) ? 0x80 : 0; | 528 | bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; |
566 | snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits); | 529 | snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0, |
567 | snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits); | 530 | HDA_AMP_MUTE, bits); |
568 | } | 531 | } |
569 | 532 | ||
570 | /* unsolicited event for HP jack sensing */ | 533 | /* unsolicited event for HP jack sensing */ |
@@ -595,14 +558,7 @@ static struct snd_kcontrol_new cxt5045_mixers[] = { | |||
595 | HDA_CODEC_MUTE("Int Mic Switch", 0x1a, 0x01, HDA_INPUT), | 558 | HDA_CODEC_MUTE("Int Mic Switch", 0x1a, 0x01, HDA_INPUT), |
596 | HDA_CODEC_VOLUME("Ext Mic Volume", 0x1a, 0x02, HDA_INPUT), | 559 | HDA_CODEC_VOLUME("Ext Mic Volume", 0x1a, 0x02, HDA_INPUT), |
597 | HDA_CODEC_MUTE("Ext Mic Switch", 0x1a, 0x02, HDA_INPUT), | 560 | HDA_CODEC_MUTE("Ext Mic Switch", 0x1a, 0x02, HDA_INPUT), |
598 | { | 561 | HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol), |
599 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
600 | .name = "Master Playback Volume", | ||
601 | .info = snd_hda_mixer_amp_volume_info, | ||
602 | .get = snd_hda_mixer_amp_volume_get, | ||
603 | .put = cxt5045_hp_master_vol_put, | ||
604 | .private_value = HDA_COMPOSE_AMP_VAL(0x10, 3, 0, HDA_OUTPUT), | ||
605 | }, | ||
606 | { | 562 | { |
607 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 563 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
608 | .name = "Master Playback Switch", | 564 | .name = "Master Playback Switch", |
@@ -915,33 +871,24 @@ static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol, | |||
915 | /* toggle internal speakers mute depending of presence of | 871 | /* toggle internal speakers mute depending of presence of |
916 | * the headphone jack | 872 | * the headphone jack |
917 | */ | 873 | */ |
918 | bits = (!spec->hp_present && spec->cur_eapd) ? 0 : 0x80; | 874 | bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE; |
919 | snd_hda_codec_amp_update(codec, 0x1d, 0, HDA_OUTPUT, 0, 0x80, bits); | 875 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0, |
920 | snd_hda_codec_amp_update(codec, 0x1d, 1, HDA_OUTPUT, 0, 0x80, bits); | 876 | HDA_AMP_MUTE, bits); |
921 | bits = spec->cur_eapd ? 0 : 0x80; | 877 | bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE; |
922 | snd_hda_codec_amp_update(codec, 0x13, 0, HDA_OUTPUT, 0, 0x80, bits); | 878 | snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0, |
923 | snd_hda_codec_amp_update(codec, 0x13, 1, HDA_OUTPUT, 0, 0x80, bits); | 879 | HDA_AMP_MUTE, bits); |
924 | return 1; | 880 | return 1; |
925 | } | 881 | } |
926 | 882 | ||
927 | /* bind volumes of both NID 0x13 (Headphones) and 0x1d (Speakers) */ | 883 | /* bind volumes of both NID 0x13 (Headphones) and 0x1d (Speakers) */ |
928 | static int cxt5047_hp_master_vol_put(struct snd_kcontrol *kcontrol, | 884 | static struct hda_bind_ctls cxt5047_bind_master_vol = { |
929 | struct snd_ctl_elem_value *ucontrol) | 885 | .ops = &snd_hda_bind_vol, |
930 | { | 886 | .values = { |
931 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 887 | HDA_COMPOSE_AMP_VAL(0x13, 3, 0, HDA_OUTPUT), |
932 | long *valp = ucontrol->value.integer.value; | 888 | HDA_COMPOSE_AMP_VAL(0x1d, 3, 0, HDA_OUTPUT), |
933 | int change; | 889 | 0 |
934 | 890 | }, | |
935 | change = snd_hda_codec_amp_update(codec, 0x1d, 0, HDA_OUTPUT, 0, | 891 | }; |
936 | 0x7f, valp[0] & 0x7f); | ||
937 | change |= snd_hda_codec_amp_update(codec, 0x1d, 1, HDA_OUTPUT, 0, | ||
938 | 0x7f, valp[1] & 0x7f); | ||
939 | snd_hda_codec_amp_update(codec, 0x13, 0, HDA_OUTPUT, 0, | ||
940 | 0x7f, valp[0] & 0x7f); | ||
941 | snd_hda_codec_amp_update(codec, 0x13, 1, HDA_OUTPUT, 0, | ||
942 | 0x7f, valp[1] & 0x7f); | ||
943 | return change; | ||
944 | } | ||
945 | 892 | ||
946 | /* mute internal speaker if HP is plugged */ | 893 | /* mute internal speaker if HP is plugged */ |
947 | static void cxt5047_hp_automute(struct hda_codec *codec) | 894 | static void cxt5047_hp_automute(struct hda_codec *codec) |
@@ -952,12 +899,12 @@ static void cxt5047_hp_automute(struct hda_codec *codec) | |||
952 | spec->hp_present = snd_hda_codec_read(codec, 0x13, 0, | 899 | spec->hp_present = snd_hda_codec_read(codec, 0x13, 0, |
953 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 900 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
954 | 901 | ||
955 | bits = (spec->hp_present || !spec->cur_eapd) ? 0x80 : 0; | 902 | bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; |
956 | snd_hda_codec_amp_update(codec, 0x1d, 0, HDA_OUTPUT, 0, 0x80, bits); | 903 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0, |
957 | snd_hda_codec_amp_update(codec, 0x1d, 1, HDA_OUTPUT, 0, 0x80, bits); | 904 | HDA_AMP_MUTE, bits); |
958 | /* Mute/Unmute PCM 2 for good measure - some systems need this */ | 905 | /* Mute/Unmute PCM 2 for good measure - some systems need this */ |
959 | snd_hda_codec_amp_update(codec, 0x1c, 0, HDA_OUTPUT, 0, 0x80, bits); | 906 | snd_hda_codec_amp_stereo(codec, 0x1c, HDA_OUTPUT, 0, |
960 | snd_hda_codec_amp_update(codec, 0x1c, 1, HDA_OUTPUT, 0, 0x80, bits); | 907 | HDA_AMP_MUTE, bits); |
961 | } | 908 | } |
962 | 909 | ||
963 | /* mute internal speaker if HP is plugged */ | 910 | /* mute internal speaker if HP is plugged */ |
@@ -969,12 +916,12 @@ static void cxt5047_hp2_automute(struct hda_codec *codec) | |||
969 | spec->hp_present = snd_hda_codec_read(codec, 0x13, 0, | 916 | spec->hp_present = snd_hda_codec_read(codec, 0x13, 0, |
970 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 917 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
971 | 918 | ||
972 | bits = spec->hp_present ? 0x80 : 0; | 919 | bits = spec->hp_present ? HDA_AMP_MUTE : 0; |
973 | snd_hda_codec_amp_update(codec, 0x1d, 0, HDA_OUTPUT, 0, 0x80, bits); | 920 | snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0, |
974 | snd_hda_codec_amp_update(codec, 0x1d, 1, HDA_OUTPUT, 0, 0x80, bits); | 921 | HDA_AMP_MUTE, bits); |
975 | /* Mute/Unmute PCM 2 for good measure - some systems need this */ | 922 | /* Mute/Unmute PCM 2 for good measure - some systems need this */ |
976 | snd_hda_codec_amp_update(codec, 0x1c, 0, HDA_OUTPUT, 0, 0x80, bits); | 923 | snd_hda_codec_amp_stereo(codec, 0x1c, HDA_OUTPUT, 0, |
977 | snd_hda_codec_amp_update(codec, 0x1c, 1, HDA_OUTPUT, 0, 0x80, bits); | 924 | HDA_AMP_MUTE, bits); |
978 | } | 925 | } |
979 | 926 | ||
980 | /* toggle input of built-in and mic jack appropriately */ | 927 | /* toggle input of built-in and mic jack appropriately */ |
@@ -1063,14 +1010,7 @@ static struct snd_kcontrol_new cxt5047_toshiba_mixers[] = { | |||
1063 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), | 1010 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), |
1064 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), | 1011 | HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), |
1065 | HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), | 1012 | HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), |
1066 | { | 1013 | HDA_BIND_VOL("Master Playback Volume", &cxt5047_bind_master_vol), |
1067 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1068 | .name = "Master Playback Volume", | ||
1069 | .info = snd_hda_mixer_amp_volume_info, | ||
1070 | .get = snd_hda_mixer_amp_volume_get, | ||
1071 | .put = cxt5047_hp_master_vol_put, | ||
1072 | .private_value = HDA_COMPOSE_AMP_VAL(0x13, 3, 0, HDA_OUTPUT), | ||
1073 | }, | ||
1074 | { | 1014 | { |
1075 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1015 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1076 | .name = "Master Playback Switch", | 1016 | .name = "Master Playback Switch", |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 9a47eec5a27b..53b0428abfc2 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -102,6 +102,8 @@ enum { | |||
102 | /* ALC268 models */ | 102 | /* ALC268 models */ |
103 | enum { | 103 | enum { |
104 | ALC268_3ST, | 104 | ALC268_3ST, |
105 | ALC268_TOSHIBA, | ||
106 | ALC268_ACER, | ||
105 | ALC268_AUTO, | 107 | ALC268_AUTO, |
106 | ALC268_MODEL_LAST /* last tag */ | 108 | ALC268_MODEL_LAST /* last tag */ |
107 | }; | 109 | }; |
@@ -129,6 +131,7 @@ enum { | |||
129 | ALC861VD_6ST_DIG, | 131 | ALC861VD_6ST_DIG, |
130 | ALC861VD_LENOVO, | 132 | ALC861VD_LENOVO, |
131 | ALC861VD_DALLAS, | 133 | ALC861VD_DALLAS, |
134 | ALC861VD_HP, | ||
132 | ALC861VD_AUTO, | 135 | ALC861VD_AUTO, |
133 | ALC861VD_MODEL_LAST, | 136 | ALC861VD_MODEL_LAST, |
134 | }; | 137 | }; |
@@ -140,6 +143,7 @@ enum { | |||
140 | ALC662_3ST_6ch, | 143 | ALC662_3ST_6ch, |
141 | ALC662_5ST_DIG, | 144 | ALC662_5ST_DIG, |
142 | ALC662_LENOVO_101E, | 145 | ALC662_LENOVO_101E, |
146 | ALC662_ASUS_EEEPC_P701, | ||
143 | ALC662_AUTO, | 147 | ALC662_AUTO, |
144 | ALC662_MODEL_LAST, | 148 | ALC662_MODEL_LAST, |
145 | }; | 149 | }; |
@@ -152,7 +156,9 @@ enum { | |||
152 | ALC882_W2JC, | 156 | ALC882_W2JC, |
153 | ALC882_TARGA, | 157 | ALC882_TARGA, |
154 | ALC882_ASUS_A7J, | 158 | ALC882_ASUS_A7J, |
159 | ALC882_ASUS_A7M, | ||
155 | ALC885_MACPRO, | 160 | ALC885_MACPRO, |
161 | ALC885_MBP3, | ||
156 | ALC885_IMAC24, | 162 | ALC885_IMAC24, |
157 | ALC882_AUTO, | 163 | ALC882_AUTO, |
158 | ALC882_MODEL_LAST, | 164 | ALC882_MODEL_LAST, |
@@ -167,12 +173,14 @@ enum { | |||
167 | ALC883_TARGA_DIG, | 173 | ALC883_TARGA_DIG, |
168 | ALC883_TARGA_2ch_DIG, | 174 | ALC883_TARGA_2ch_DIG, |
169 | ALC883_ACER, | 175 | ALC883_ACER, |
176 | ALC883_ACER_ASPIRE, | ||
170 | ALC883_MEDION, | 177 | ALC883_MEDION, |
171 | ALC883_MEDION_MD2, | 178 | ALC883_MEDION_MD2, |
172 | ALC883_LAPTOP_EAPD, | 179 | ALC883_LAPTOP_EAPD, |
173 | ALC883_LENOVO_101E_2ch, | 180 | ALC883_LENOVO_101E_2ch, |
174 | ALC883_LENOVO_NB0763, | 181 | ALC883_LENOVO_NB0763, |
175 | ALC888_LENOVO_MS7195_DIG, | 182 | ALC888_LENOVO_MS7195_DIG, |
183 | ALC883_HAIER_W66, | ||
176 | ALC888_6ST_HP, | 184 | ALC888_6ST_HP, |
177 | ALC888_3ST_HP, | 185 | ALC888_3ST_HP, |
178 | ALC883_AUTO, | 186 | ALC883_AUTO, |
@@ -239,6 +247,10 @@ struct alc_spec { | |||
239 | /* for pin sensing */ | 247 | /* for pin sensing */ |
240 | unsigned int sense_updated: 1; | 248 | unsigned int sense_updated: 1; |
241 | unsigned int jack_present: 1; | 249 | unsigned int jack_present: 1; |
250 | |||
251 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
252 | struct hda_loopback_check loopback; | ||
253 | #endif | ||
242 | }; | 254 | }; |
243 | 255 | ||
244 | /* | 256 | /* |
@@ -263,6 +275,9 @@ struct alc_config_preset { | |||
263 | const struct hda_input_mux *input_mux; | 275 | const struct hda_input_mux *input_mux; |
264 | void (*unsol_event)(struct hda_codec *, unsigned int); | 276 | void (*unsol_event)(struct hda_codec *, unsigned int); |
265 | void (*init_hook)(struct hda_codec *); | 277 | void (*init_hook)(struct hda_codec *); |
278 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
279 | struct hda_amp_list *loopbacks; | ||
280 | #endif | ||
266 | }; | 281 | }; |
267 | 282 | ||
268 | 283 | ||
@@ -441,8 +456,9 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, | |||
441 | change = pinctl != alc_pin_mode_values[val]; | 456 | change = pinctl != alc_pin_mode_values[val]; |
442 | if (change) { | 457 | if (change) { |
443 | /* Set pin mode to that requested */ | 458 | /* Set pin mode to that requested */ |
444 | snd_hda_codec_write(codec,nid,0,AC_VERB_SET_PIN_WIDGET_CONTROL, | 459 | snd_hda_codec_write_cache(codec, nid, 0, |
445 | alc_pin_mode_values[val]); | 460 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
461 | alc_pin_mode_values[val]); | ||
446 | 462 | ||
447 | /* Also enable the retasking pin's input/output as required | 463 | /* Also enable the retasking pin's input/output as required |
448 | * for the requested pin mode. Enum values of 2 or less are | 464 | * for the requested pin mode. Enum values of 2 or less are |
@@ -455,19 +471,15 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, | |||
455 | * this turns out to be necessary in the future. | 471 | * this turns out to be necessary in the future. |
456 | */ | 472 | */ |
457 | if (val <= 2) { | 473 | if (val <= 2) { |
458 | snd_hda_codec_write(codec, nid, 0, | 474 | snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, |
459 | AC_VERB_SET_AMP_GAIN_MUTE, | 475 | HDA_AMP_MUTE, HDA_AMP_MUTE); |
460 | AMP_OUT_MUTE); | 476 | snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0, |
461 | snd_hda_codec_write(codec, nid, 0, | 477 | HDA_AMP_MUTE, 0); |
462 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
463 | AMP_IN_UNMUTE(0)); | ||
464 | } else { | 478 | } else { |
465 | snd_hda_codec_write(codec, nid, 0, | 479 | snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0, |
466 | AC_VERB_SET_AMP_GAIN_MUTE, | 480 | HDA_AMP_MUTE, HDA_AMP_MUTE); |
467 | AMP_IN_MUTE(0)); | 481 | snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, |
468 | snd_hda_codec_write(codec, nid, 0, | 482 | HDA_AMP_MUTE, 0); |
469 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
470 | AMP_OUT_UNMUTE); | ||
471 | } | 483 | } |
472 | } | 484 | } |
473 | return change; | 485 | return change; |
@@ -486,15 +498,7 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, | |||
486 | * needed for any "production" models. | 498 | * needed for any "production" models. |
487 | */ | 499 | */ |
488 | #ifdef CONFIG_SND_DEBUG | 500 | #ifdef CONFIG_SND_DEBUG |
489 | static int alc_gpio_data_info(struct snd_kcontrol *kcontrol, | 501 | #define alc_gpio_data_info snd_ctl_boolean_mono_info |
490 | struct snd_ctl_elem_info *uinfo) | ||
491 | { | ||
492 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
493 | uinfo->count = 1; | ||
494 | uinfo->value.integer.min = 0; | ||
495 | uinfo->value.integer.max = 1; | ||
496 | return 0; | ||
497 | } | ||
498 | 502 | ||
499 | static int alc_gpio_data_get(struct snd_kcontrol *kcontrol, | 503 | static int alc_gpio_data_get(struct snd_kcontrol *kcontrol, |
500 | struct snd_ctl_elem_value *ucontrol) | 504 | struct snd_ctl_elem_value *ucontrol) |
@@ -527,7 +531,8 @@ static int alc_gpio_data_put(struct snd_kcontrol *kcontrol, | |||
527 | gpio_data &= ~mask; | 531 | gpio_data &= ~mask; |
528 | else | 532 | else |
529 | gpio_data |= mask; | 533 | gpio_data |= mask; |
530 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_GPIO_DATA, gpio_data); | 534 | snd_hda_codec_write_cache(codec, nid, 0, |
535 | AC_VERB_SET_GPIO_DATA, gpio_data); | ||
531 | 536 | ||
532 | return change; | 537 | return change; |
533 | } | 538 | } |
@@ -547,15 +552,7 @@ static int alc_gpio_data_put(struct snd_kcontrol *kcontrol, | |||
547 | * necessary. | 552 | * necessary. |
548 | */ | 553 | */ |
549 | #ifdef CONFIG_SND_DEBUG | 554 | #ifdef CONFIG_SND_DEBUG |
550 | static int alc_spdif_ctrl_info(struct snd_kcontrol *kcontrol, | 555 | #define alc_spdif_ctrl_info snd_ctl_boolean_mono_info |
551 | struct snd_ctl_elem_info *uinfo) | ||
552 | { | ||
553 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
554 | uinfo->count = 1; | ||
555 | uinfo->value.integer.min = 0; | ||
556 | uinfo->value.integer.max = 1; | ||
557 | return 0; | ||
558 | } | ||
559 | 556 | ||
560 | static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol, | 557 | static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol, |
561 | struct snd_ctl_elem_value *ucontrol) | 558 | struct snd_ctl_elem_value *ucontrol) |
@@ -588,8 +585,8 @@ static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol, | |||
588 | ctrl_data &= ~mask; | 585 | ctrl_data &= ~mask; |
589 | else | 586 | else |
590 | ctrl_data |= mask; | 587 | ctrl_data |= mask; |
591 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, | 588 | snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, |
592 | ctrl_data); | 589 | ctrl_data); |
593 | 590 | ||
594 | return change; | 591 | return change; |
595 | } | 592 | } |
@@ -638,6 +635,9 @@ static void setup_preset(struct alc_spec *spec, | |||
638 | 635 | ||
639 | spec->unsol_event = preset->unsol_event; | 636 | spec->unsol_event = preset->unsol_event; |
640 | spec->init_hook = preset->init_hook; | 637 | spec->init_hook = preset->init_hook; |
638 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
639 | spec->loopback.amplist = preset->loopbacks; | ||
640 | #endif | ||
641 | } | 641 | } |
642 | 642 | ||
643 | /* Enable GPIO mask and set output */ | 643 | /* Enable GPIO mask and set output */ |
@@ -662,6 +662,44 @@ static struct hda_verb alc_gpio3_init_verbs[] = { | |||
662 | { } | 662 | { } |
663 | }; | 663 | }; |
664 | 664 | ||
665 | static void alc_sku_automute(struct hda_codec *codec) | ||
666 | { | ||
667 | struct alc_spec *spec = codec->spec; | ||
668 | unsigned int mute; | ||
669 | unsigned int present; | ||
670 | unsigned int hp_nid = spec->autocfg.hp_pins[0]; | ||
671 | unsigned int sp_nid = spec->autocfg.speaker_pins[0]; | ||
672 | |||
673 | /* need to execute and sync at first */ | ||
674 | snd_hda_codec_read(codec, hp_nid, 0, AC_VERB_SET_PIN_SENSE, 0); | ||
675 | present = snd_hda_codec_read(codec, hp_nid, 0, | ||
676 | AC_VERB_GET_PIN_SENSE, 0); | ||
677 | spec->jack_present = (present & 0x80000000) != 0; | ||
678 | if (spec->jack_present) { | ||
679 | /* mute internal speaker */ | ||
680 | snd_hda_codec_amp_stereo(codec, sp_nid, HDA_OUTPUT, 0, | ||
681 | HDA_AMP_MUTE, HDA_AMP_MUTE); | ||
682 | } else { | ||
683 | /* unmute internal speaker if necessary */ | ||
684 | mute = snd_hda_codec_amp_read(codec, hp_nid, 0, HDA_OUTPUT, 0); | ||
685 | snd_hda_codec_amp_stereo(codec, sp_nid, HDA_OUTPUT, 0, | ||
686 | HDA_AMP_MUTE, mute); | ||
687 | } | ||
688 | } | ||
689 | |||
690 | /* unsolicited event for HP jack sensing */ | ||
691 | static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res) | ||
692 | { | ||
693 | if (codec->vendor_id == 0x10ec0880) | ||
694 | res >>= 28; | ||
695 | else | ||
696 | res >>= 26; | ||
697 | if (res != ALC880_HP_EVENT) | ||
698 | return; | ||
699 | |||
700 | alc_sku_automute(codec); | ||
701 | } | ||
702 | |||
665 | /* 32-bit subsystem ID for BIOS loading in HD Audio codec. | 703 | /* 32-bit subsystem ID for BIOS loading in HD Audio codec. |
666 | * 31 ~ 16 : Manufacture ID | 704 | * 31 ~ 16 : Manufacture ID |
667 | * 15 ~ 8 : SKU ID | 705 | * 15 ~ 8 : SKU ID |
@@ -672,13 +710,48 @@ static void alc_subsystem_id(struct hda_codec *codec, | |||
672 | unsigned int porta, unsigned int porte, | 710 | unsigned int porta, unsigned int porte, |
673 | unsigned int portd) | 711 | unsigned int portd) |
674 | { | 712 | { |
675 | unsigned int ass, tmp; | 713 | unsigned int ass, tmp, i; |
714 | unsigned nid; | ||
715 | struct alc_spec *spec = codec->spec; | ||
676 | 716 | ||
677 | ass = codec->subsystem_id; | 717 | ass = codec->subsystem_id & 0xffff; |
678 | if (!(ass & 1)) | 718 | if ((ass != codec->bus->pci->subsystem_device) && (ass & 1)) |
719 | goto do_sku; | ||
720 | |||
721 | /* | ||
722 | * 31~30 : port conetcivity | ||
723 | * 29~21 : reserve | ||
724 | * 20 : PCBEEP input | ||
725 | * 19~16 : Check sum (15:1) | ||
726 | * 15~1 : Custom | ||
727 | * 0 : override | ||
728 | */ | ||
729 | nid = 0x1d; | ||
730 | if (codec->vendor_id == 0x10ec0260) | ||
731 | nid = 0x17; | ||
732 | ass = snd_hda_codec_read(codec, nid, 0, | ||
733 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
734 | if (!(ass & 1) && !(ass & 0x100000)) | ||
735 | return; | ||
736 | if ((ass >> 30) != 1) /* no physical connection */ | ||
679 | return; | 737 | return; |
680 | 738 | ||
681 | /* Override */ | 739 | /* check sum */ |
740 | tmp = 0; | ||
741 | for (i = 1; i < 16; i++) { | ||
742 | if ((ass >> i) && 1) | ||
743 | tmp++; | ||
744 | } | ||
745 | if (((ass >> 16) & 0xf) != tmp) | ||
746 | return; | ||
747 | do_sku: | ||
748 | /* | ||
749 | * 0 : override | ||
750 | * 1 : Swap Jack | ||
751 | * 2 : 0 --> Desktop, 1 --> Laptop | ||
752 | * 3~5 : External Amplifier control | ||
753 | * 7~6 : Reserved | ||
754 | */ | ||
682 | tmp = (ass & 0x38) >> 3; /* external Amp control */ | 755 | tmp = (ass & 0x38) >> 3; /* external Amp control */ |
683 | switch (tmp) { | 756 | switch (tmp) { |
684 | case 1: | 757 | case 1: |
@@ -690,38 +763,108 @@ static void alc_subsystem_id(struct hda_codec *codec, | |||
690 | case 7: | 763 | case 7: |
691 | snd_hda_sequence_write(codec, alc_gpio3_init_verbs); | 764 | snd_hda_sequence_write(codec, alc_gpio3_init_verbs); |
692 | break; | 765 | break; |
693 | case 5: | 766 | case 5: /* set EAPD output high */ |
694 | switch (codec->vendor_id) { | 767 | switch (codec->vendor_id) { |
695 | case 0x10ec0862: | 768 | case 0x10ec0260: |
696 | case 0x10ec0660: | 769 | snd_hda_codec_write(codec, 0x0f, 0, |
697 | case 0x10ec0662: | 770 | AC_VERB_SET_EAPD_BTLENABLE, 2); |
771 | snd_hda_codec_write(codec, 0x10, 0, | ||
772 | AC_VERB_SET_EAPD_BTLENABLE, 2); | ||
773 | break; | ||
774 | case 0x10ec0262: | ||
698 | case 0x10ec0267: | 775 | case 0x10ec0267: |
699 | case 0x10ec0268: | 776 | case 0x10ec0268: |
777 | case 0x10ec0269: | ||
778 | case 0x10ec0862: | ||
779 | case 0x10ec0662: | ||
700 | snd_hda_codec_write(codec, 0x14, 0, | 780 | snd_hda_codec_write(codec, 0x14, 0, |
701 | AC_VERB_SET_EAPD_BTLENABLE, 2); | 781 | AC_VERB_SET_EAPD_BTLENABLE, 2); |
702 | snd_hda_codec_write(codec, 0x15, 0, | 782 | snd_hda_codec_write(codec, 0x15, 0, |
703 | AC_VERB_SET_EAPD_BTLENABLE, 2); | 783 | AC_VERB_SET_EAPD_BTLENABLE, 2); |
704 | return; | 784 | break; |
705 | } | 785 | } |
706 | case 6: | 786 | switch (codec->vendor_id) { |
707 | if (ass & 4) { /* bit 2 : 0 = Desktop, 1 = Laptop */ | 787 | case 0x10ec0260: |
708 | hda_nid_t port = 0; | 788 | snd_hda_codec_write(codec, 0x1a, 0, |
709 | tmp = (ass & 0x1800) >> 11; | 789 | AC_VERB_SET_COEF_INDEX, 7); |
710 | switch (tmp) { | 790 | tmp = snd_hda_codec_read(codec, 0x1a, 0, |
711 | case 0: port = porta; break; | 791 | AC_VERB_GET_PROC_COEF, 0); |
712 | case 1: port = porte; break; | 792 | snd_hda_codec_write(codec, 0x1a, 0, |
713 | case 2: port = portd; break; | 793 | AC_VERB_SET_COEF_INDEX, 7); |
714 | } | 794 | snd_hda_codec_write(codec, 0x1a, 0, |
715 | if (port) | 795 | AC_VERB_SET_PROC_COEF, |
716 | snd_hda_codec_write(codec, port, 0, | 796 | tmp | 0x2010); |
717 | AC_VERB_SET_EAPD_BTLENABLE, | 797 | break; |
718 | 2); | 798 | case 0x10ec0262: |
799 | case 0x10ec0880: | ||
800 | case 0x10ec0882: | ||
801 | case 0x10ec0883: | ||
802 | case 0x10ec0885: | ||
803 | case 0x10ec0888: | ||
804 | snd_hda_codec_write(codec, 0x20, 0, | ||
805 | AC_VERB_SET_COEF_INDEX, 7); | ||
806 | tmp = snd_hda_codec_read(codec, 0x20, 0, | ||
807 | AC_VERB_GET_PROC_COEF, 0); | ||
808 | snd_hda_codec_write(codec, 0x20, 0, | ||
809 | AC_VERB_SET_COEF_INDEX, 7); | ||
810 | snd_hda_codec_write(codec, 0x20, 0, | ||
811 | AC_VERB_SET_PROC_COEF, | ||
812 | tmp | 0x2010); | ||
813 | break; | ||
814 | case 0x10ec0267: | ||
815 | case 0x10ec0268: | ||
816 | snd_hda_codec_write(codec, 0x20, 0, | ||
817 | AC_VERB_SET_COEF_INDEX, 7); | ||
818 | tmp = snd_hda_codec_read(codec, 0x20, 0, | ||
819 | AC_VERB_GET_PROC_COEF, 0); | ||
820 | snd_hda_codec_write(codec, 0x20, 0, | ||
821 | AC_VERB_SET_COEF_INDEX, 7); | ||
822 | snd_hda_codec_write(codec, 0x20, 0, | ||
823 | AC_VERB_SET_PROC_COEF, | ||
824 | tmp | 0x3000); | ||
825 | break; | ||
719 | } | 826 | } |
720 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7); | 827 | default: |
721 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, | ||
722 | (tmp == 5 ? 0x3040 : 0x3050)); | ||
723 | break; | 828 | break; |
724 | } | 829 | } |
830 | |||
831 | /* is laptop and enable the function "Mute internal speaker | ||
832 | * when the external headphone out jack is plugged" | ||
833 | */ | ||
834 | if (!(ass & 0x4) || !(ass & 0x8000)) | ||
835 | return; | ||
836 | /* | ||
837 | * 10~8 : Jack location | ||
838 | * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered | ||
839 | * 14~13: Resvered | ||
840 | * 15 : 1 --> enable the function "Mute internal speaker | ||
841 | * when the external headphone out jack is plugged" | ||
842 | */ | ||
843 | if (!spec->autocfg.speaker_pins[0]) { | ||
844 | if (spec->multiout.dac_nids[0]) | ||
845 | spec->autocfg.speaker_pins[0] = | ||
846 | spec->multiout.dac_nids[0]; | ||
847 | else | ||
848 | return; | ||
849 | } | ||
850 | |||
851 | if (!spec->autocfg.hp_pins[0]) { | ||
852 | tmp = (ass >> 11) & 0x3; /* HP to chassis */ | ||
853 | if (tmp == 0) | ||
854 | spec->autocfg.hp_pins[0] = porta; | ||
855 | else if (tmp == 1) | ||
856 | spec->autocfg.hp_pins[0] = porte; | ||
857 | else if (tmp == 2) | ||
858 | spec->autocfg.hp_pins[0] = portd; | ||
859 | else | ||
860 | return; | ||
861 | } | ||
862 | |||
863 | snd_hda_codec_write(codec, spec->autocfg.hp_pins[0], 0, | ||
864 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
865 | AC_USRSP_EN | ALC880_HP_EVENT); | ||
866 | spec->unsol_event = alc_sku_unsol_event; | ||
867 | spec->init_hook = alc_sku_automute; | ||
725 | } | 868 | } |
726 | 869 | ||
727 | /* | 870 | /* |
@@ -1304,11 +1447,13 @@ static struct hda_verb alc880_volume_init_verbs[] = { | |||
1304 | * panel mic (mic 2) | 1447 | * panel mic (mic 2) |
1305 | */ | 1448 | */ |
1306 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 1449 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
1307 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 1450 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
1308 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 1451 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
1309 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 1452 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
1310 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 1453 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
1311 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 1454 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
1455 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, | ||
1456 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, | ||
1312 | 1457 | ||
1313 | /* | 1458 | /* |
1314 | * Set up output mixers (0x0c - 0x0f) | 1459 | * Set up output mixers (0x0c - 0x0f) |
@@ -1568,15 +1713,11 @@ static void alc880_uniwill_hp_automute(struct hda_codec *codec) | |||
1568 | 1713 | ||
1569 | present = snd_hda_codec_read(codec, 0x14, 0, | 1714 | present = snd_hda_codec_read(codec, 0x14, 0, |
1570 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 1715 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
1571 | bits = present ? 0x80 : 0; | 1716 | bits = present ? HDA_AMP_MUTE : 0; |
1572 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | 1717 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, |
1573 | 0x80, bits); | 1718 | HDA_AMP_MUTE, bits); |
1574 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | 1719 | snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, |
1575 | 0x80, bits); | 1720 | HDA_AMP_MUTE, bits); |
1576 | snd_hda_codec_amp_update(codec, 0x16, 0, HDA_OUTPUT, 0, | ||
1577 | 0x80, bits); | ||
1578 | snd_hda_codec_amp_update(codec, 0x16, 1, HDA_OUTPUT, 0, | ||
1579 | 0x80, bits); | ||
1580 | } | 1721 | } |
1581 | 1722 | ||
1582 | /* auto-toggle front mic */ | 1723 | /* auto-toggle front mic */ |
@@ -1587,11 +1728,8 @@ static void alc880_uniwill_mic_automute(struct hda_codec *codec) | |||
1587 | 1728 | ||
1588 | present = snd_hda_codec_read(codec, 0x18, 0, | 1729 | present = snd_hda_codec_read(codec, 0x18, 0, |
1589 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 1730 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
1590 | bits = present ? 0x80 : 0; | 1731 | bits = present ? HDA_AMP_MUTE : 0; |
1591 | snd_hda_codec_amp_update(codec, 0x0b, 0, HDA_INPUT, 1, | 1732 | snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits); |
1592 | 0x80, bits); | ||
1593 | snd_hda_codec_amp_update(codec, 0x0b, 1, HDA_INPUT, 1, | ||
1594 | 0x80, bits); | ||
1595 | } | 1733 | } |
1596 | 1734 | ||
1597 | static void alc880_uniwill_automute(struct hda_codec *codec) | 1735 | static void alc880_uniwill_automute(struct hda_codec *codec) |
@@ -1623,11 +1761,8 @@ static void alc880_uniwill_p53_hp_automute(struct hda_codec *codec) | |||
1623 | 1761 | ||
1624 | present = snd_hda_codec_read(codec, 0x14, 0, | 1762 | present = snd_hda_codec_read(codec, 0x14, 0, |
1625 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 1763 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
1626 | bits = present ? 0x80 : 0; | 1764 | bits = present ? HDA_AMP_MUTE : 0; |
1627 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_INPUT, 0, | 1765 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_INPUT, 0, HDA_AMP_MUTE, bits); |
1628 | 0x80, bits); | ||
1629 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_INPUT, 0, | ||
1630 | 0x80, bits); | ||
1631 | } | 1766 | } |
1632 | 1767 | ||
1633 | static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec) | 1768 | static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec) |
@@ -1635,19 +1770,14 @@ static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec) | |||
1635 | unsigned int present; | 1770 | unsigned int present; |
1636 | 1771 | ||
1637 | present = snd_hda_codec_read(codec, 0x21, 0, | 1772 | present = snd_hda_codec_read(codec, 0x21, 0, |
1638 | AC_VERB_GET_VOLUME_KNOB_CONTROL, 0) & 0x7f; | 1773 | AC_VERB_GET_VOLUME_KNOB_CONTROL, 0); |
1639 | 1774 | present &= HDA_AMP_VOLMASK; | |
1640 | snd_hda_codec_amp_update(codec, 0x0c, 0, HDA_OUTPUT, 0, | 1775 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_OUTPUT, 0, |
1641 | 0x7f, present); | 1776 | HDA_AMP_VOLMASK, present); |
1642 | snd_hda_codec_amp_update(codec, 0x0c, 1, HDA_OUTPUT, 0, | 1777 | snd_hda_codec_amp_stereo(codec, 0x0d, HDA_OUTPUT, 0, |
1643 | 0x7f, present); | 1778 | HDA_AMP_VOLMASK, present); |
1644 | |||
1645 | snd_hda_codec_amp_update(codec, 0x0d, 0, HDA_OUTPUT, 0, | ||
1646 | 0x7f, present); | ||
1647 | snd_hda_codec_amp_update(codec, 0x0d, 1, HDA_OUTPUT, 0, | ||
1648 | 0x7f, present); | ||
1649 | |||
1650 | } | 1779 | } |
1780 | |||
1651 | static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec, | 1781 | static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec, |
1652 | unsigned int res) | 1782 | unsigned int res) |
1653 | { | 1783 | { |
@@ -1868,8 +1998,8 @@ static struct hda_verb alc880_lg_init_verbs[] = { | |||
1868 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 1998 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
1869 | /* mute all amp mixer inputs */ | 1999 | /* mute all amp mixer inputs */ |
1870 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, | 2000 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, |
1871 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)}, | 2001 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, |
1872 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)}, | 2002 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, |
1873 | /* line-in to input */ | 2003 | /* line-in to input */ |
1874 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | 2004 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
1875 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 2005 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
@@ -1900,11 +2030,9 @@ static void alc880_lg_automute(struct hda_codec *codec) | |||
1900 | 2030 | ||
1901 | present = snd_hda_codec_read(codec, 0x1b, 0, | 2031 | present = snd_hda_codec_read(codec, 0x1b, 0, |
1902 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 2032 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
1903 | bits = present ? 0x80 : 0; | 2033 | bits = present ? HDA_AMP_MUTE : 0; |
1904 | snd_hda_codec_amp_update(codec, 0x17, 0, HDA_OUTPUT, 0, | 2034 | snd_hda_codec_amp_stereo(codec, 0x17, HDA_OUTPUT, 0, |
1905 | 0x80, bits); | 2035 | HDA_AMP_MUTE, bits); |
1906 | snd_hda_codec_amp_update(codec, 0x17, 1, HDA_OUTPUT, 0, | ||
1907 | 0x80, bits); | ||
1908 | } | 2036 | } |
1909 | 2037 | ||
1910 | static void alc880_lg_unsol_event(struct hda_codec *codec, unsigned int res) | 2038 | static void alc880_lg_unsol_event(struct hda_codec *codec, unsigned int res) |
@@ -1973,7 +2101,7 @@ static struct hda_verb alc880_lg_lw_init_verbs[] = { | |||
1973 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 2101 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1974 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 2102 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1975 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 2103 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1976 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)}, | 2104 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, |
1977 | /* speaker-out */ | 2105 | /* speaker-out */ |
1978 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | 2106 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, |
1979 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 2107 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
@@ -1999,11 +2127,9 @@ static void alc880_lg_lw_automute(struct hda_codec *codec) | |||
1999 | 2127 | ||
2000 | present = snd_hda_codec_read(codec, 0x1b, 0, | 2128 | present = snd_hda_codec_read(codec, 0x1b, 0, |
2001 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 2129 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
2002 | bits = present ? 0x80 : 0; | 2130 | bits = present ? HDA_AMP_MUTE : 0; |
2003 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | 2131 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, |
2004 | 0x80, bits); | 2132 | HDA_AMP_MUTE, bits); |
2005 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
2006 | 0x80, bits); | ||
2007 | } | 2133 | } |
2008 | 2134 | ||
2009 | static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res) | 2135 | static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res) |
@@ -2015,6 +2141,24 @@ static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res) | |||
2015 | alc880_lg_lw_automute(codec); | 2141 | alc880_lg_lw_automute(codec); |
2016 | } | 2142 | } |
2017 | 2143 | ||
2144 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
2145 | static struct hda_amp_list alc880_loopbacks[] = { | ||
2146 | { 0x0b, HDA_INPUT, 0 }, | ||
2147 | { 0x0b, HDA_INPUT, 1 }, | ||
2148 | { 0x0b, HDA_INPUT, 2 }, | ||
2149 | { 0x0b, HDA_INPUT, 3 }, | ||
2150 | { 0x0b, HDA_INPUT, 4 }, | ||
2151 | { } /* end */ | ||
2152 | }; | ||
2153 | |||
2154 | static struct hda_amp_list alc880_lg_loopbacks[] = { | ||
2155 | { 0x0b, HDA_INPUT, 1 }, | ||
2156 | { 0x0b, HDA_INPUT, 6 }, | ||
2157 | { 0x0b, HDA_INPUT, 7 }, | ||
2158 | { } /* end */ | ||
2159 | }; | ||
2160 | #endif | ||
2161 | |||
2018 | /* | 2162 | /* |
2019 | * Common callbacks | 2163 | * Common callbacks |
2020 | */ | 2164 | */ |
@@ -2041,24 +2185,11 @@ static void alc_unsol_event(struct hda_codec *codec, unsigned int res) | |||
2041 | spec->unsol_event(codec, res); | 2185 | spec->unsol_event(codec, res); |
2042 | } | 2186 | } |
2043 | 2187 | ||
2044 | #ifdef CONFIG_PM | 2188 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
2045 | /* | 2189 | static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid) |
2046 | * resume | ||
2047 | */ | ||
2048 | static int alc_resume(struct hda_codec *codec) | ||
2049 | { | 2190 | { |
2050 | struct alc_spec *spec = codec->spec; | 2191 | struct alc_spec *spec = codec->spec; |
2051 | int i; | 2192 | return snd_hda_check_amp_list_power(codec, &spec->loopback, nid); |
2052 | |||
2053 | alc_init(codec); | ||
2054 | for (i = 0; i < spec->num_mixers; i++) | ||
2055 | snd_hda_resume_ctls(codec, spec->mixers[i]); | ||
2056 | if (spec->multiout.dig_out_nid) | ||
2057 | snd_hda_resume_spdif_out(codec); | ||
2058 | if (spec->dig_in_nid) | ||
2059 | snd_hda_resume_spdif_in(codec); | ||
2060 | |||
2061 | return 0; | ||
2062 | } | 2193 | } |
2063 | #endif | 2194 | #endif |
2064 | 2195 | ||
@@ -2293,8 +2424,8 @@ static struct hda_codec_ops alc_patch_ops = { | |||
2293 | .init = alc_init, | 2424 | .init = alc_init, |
2294 | .free = alc_free, | 2425 | .free = alc_free, |
2295 | .unsol_event = alc_unsol_event, | 2426 | .unsol_event = alc_unsol_event, |
2296 | #ifdef CONFIG_PM | 2427 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
2297 | .resume = alc_resume, | 2428 | .check_power_status = alc_check_power_status, |
2298 | #endif | 2429 | #endif |
2299 | }; | 2430 | }; |
2300 | 2431 | ||
@@ -2392,11 +2523,14 @@ static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol, | |||
2392 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 2523 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
2393 | new_ctl = ctls[ucontrol->value.enumerated.item[0]]; | 2524 | new_ctl = ctls[ucontrol->value.enumerated.item[0]]; |
2394 | if (old_ctl != new_ctl) { | 2525 | if (old_ctl != new_ctl) { |
2395 | snd_hda_codec_write(codec, nid, 0, | 2526 | int val; |
2396 | AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl); | 2527 | snd_hda_codec_write_cache(codec, nid, 0, |
2397 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 2528 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
2398 | (ucontrol->value.enumerated.item[0] >= 3 ? | 2529 | new_ctl); |
2399 | 0xb080 : 0xb000)); | 2530 | val = ucontrol->value.enumerated.item[0] >= 3 ? |
2531 | HDA_AMP_MUTE : 0; | ||
2532 | snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, | ||
2533 | HDA_AMP_MUTE, val); | ||
2400 | return 1; | 2534 | return 1; |
2401 | } | 2535 | } |
2402 | return 0; | 2536 | return 0; |
@@ -2439,7 +2573,8 @@ static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol, | |||
2439 | sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3; | 2573 | sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3; |
2440 | if (ucontrol->value.enumerated.item[0] != sel) { | 2574 | if (ucontrol->value.enumerated.item[0] != sel) { |
2441 | sel = ucontrol->value.enumerated.item[0] & 3; | 2575 | sel = ucontrol->value.enumerated.item[0] & 3; |
2442 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, sel); | 2576 | snd_hda_codec_write_cache(codec, nid, 0, |
2577 | AC_VERB_SET_CONNECT_SEL, sel); | ||
2443 | return 1; | 2578 | return 1; |
2444 | } | 2579 | } |
2445 | return 0; | 2580 | return 0; |
@@ -2885,6 +3020,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
2885 | alc880_beep_init_verbs }, | 3020 | alc880_beep_init_verbs }, |
2886 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | 3021 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), |
2887 | .dac_nids = alc880_dac_nids, | 3022 | .dac_nids = alc880_dac_nids, |
3023 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
2888 | .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), | 3024 | .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), |
2889 | .channel_mode = alc880_2_jack_modes, | 3025 | .channel_mode = alc880_2_jack_modes, |
2890 | .input_mux = &alc880_capture_source, | 3026 | .input_mux = &alc880_capture_source, |
@@ -2916,6 +3052,9 @@ static struct alc_config_preset alc880_presets[] = { | |||
2916 | .input_mux = &alc880_lg_capture_source, | 3052 | .input_mux = &alc880_lg_capture_source, |
2917 | .unsol_event = alc880_lg_unsol_event, | 3053 | .unsol_event = alc880_lg_unsol_event, |
2918 | .init_hook = alc880_lg_automute, | 3054 | .init_hook = alc880_lg_automute, |
3055 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
3056 | .loopbacks = alc880_lg_loopbacks, | ||
3057 | #endif | ||
2919 | }, | 3058 | }, |
2920 | [ALC880_LG_LW] = { | 3059 | [ALC880_LG_LW] = { |
2921 | .mixers = { alc880_lg_lw_mixer }, | 3060 | .mixers = { alc880_lg_lw_mixer }, |
@@ -3399,6 +3538,10 @@ static int patch_alc880(struct hda_codec *codec) | |||
3399 | codec->patch_ops = alc_patch_ops; | 3538 | codec->patch_ops = alc_patch_ops; |
3400 | if (board_config == ALC880_AUTO) | 3539 | if (board_config == ALC880_AUTO) |
3401 | spec->init_hook = alc880_auto_init; | 3540 | spec->init_hook = alc880_auto_init; |
3541 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
3542 | if (!spec->loopback.amplist) | ||
3543 | spec->loopback.amplist = alc880_loopbacks; | ||
3544 | #endif | ||
3402 | 3545 | ||
3403 | return 0; | 3546 | return 0; |
3404 | } | 3547 | } |
@@ -3747,12 +3890,12 @@ static struct hda_verb alc260_init_verbs[] = { | |||
3747 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & | 3890 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & |
3748 | * Line In 2 = 0x03 | 3891 | * Line In 2 = 0x03 |
3749 | */ | 3892 | */ |
3750 | /* mute CD */ | 3893 | /* mute analog inputs */ |
3751 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 3894 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
3752 | /* mute Line In */ | 3895 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
3753 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 3896 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
3754 | /* mute Mic */ | 3897 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
3755 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 3898 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
3756 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ | 3899 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ |
3757 | /* mute Front out path */ | 3900 | /* mute Front out path */ |
3758 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 3901 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
@@ -3797,12 +3940,12 @@ static struct hda_verb alc260_hp_init_verbs[] = { | |||
3797 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & | 3940 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & |
3798 | * Line In 2 = 0x03 | 3941 | * Line In 2 = 0x03 |
3799 | */ | 3942 | */ |
3800 | /* unmute CD */ | 3943 | /* mute analog inputs */ |
3801 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, | 3944 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
3802 | /* unmute Line In */ | 3945 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
3803 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, | 3946 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
3804 | /* unmute Mic */ | 3947 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
3805 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 3948 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
3806 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ | 3949 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ |
3807 | /* Unmute Front out path */ | 3950 | /* Unmute Front out path */ |
3808 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 3951 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, |
@@ -3847,12 +3990,12 @@ static struct hda_verb alc260_hp_3013_init_verbs[] = { | |||
3847 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & | 3990 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & |
3848 | * Line In 2 = 0x03 | 3991 | * Line In 2 = 0x03 |
3849 | */ | 3992 | */ |
3850 | /* unmute CD */ | 3993 | /* mute analog inputs */ |
3851 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, | 3994 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
3852 | /* unmute Line In */ | 3995 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
3853 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, | 3996 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
3854 | /* unmute Mic */ | 3997 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
3855 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 3998 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
3856 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ | 3999 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ |
3857 | /* Unmute Front out path */ | 4000 | /* Unmute Front out path */ |
3858 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 4001 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, |
@@ -4069,13 +4212,17 @@ static void alc260_replacer_672v_automute(struct hda_codec *codec) | |||
4069 | present = snd_hda_codec_read(codec, 0x0f, 0, | 4212 | present = snd_hda_codec_read(codec, 0x0f, 0, |
4070 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 4213 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
4071 | if (present) { | 4214 | if (present) { |
4072 | snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 1); | 4215 | snd_hda_codec_write_cache(codec, 0x01, 0, |
4073 | snd_hda_codec_write(codec, 0x0f, 0, | 4216 | AC_VERB_SET_GPIO_DATA, 1); |
4074 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP); | 4217 | snd_hda_codec_write_cache(codec, 0x0f, 0, |
4218 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
4219 | PIN_HP); | ||
4075 | } else { | 4220 | } else { |
4076 | snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0); | 4221 | snd_hda_codec_write_cache(codec, 0x01, 0, |
4077 | snd_hda_codec_write(codec, 0x0f, 0, | 4222 | AC_VERB_SET_GPIO_DATA, 0); |
4078 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | 4223 | snd_hda_codec_write_cache(codec, 0x0f, 0, |
4224 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
4225 | PIN_OUT); | ||
4079 | } | 4226 | } |
4080 | } | 4227 | } |
4081 | 4228 | ||
@@ -4470,11 +4617,12 @@ static struct hda_verb alc260_volume_init_verbs[] = { | |||
4470 | * front panel mic (mic 2) | 4617 | * front panel mic (mic 2) |
4471 | */ | 4618 | */ |
4472 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 4619 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
4473 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 4620 | /* mute analog inputs */ |
4474 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 4621 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
4475 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 4622 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
4476 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 4623 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
4477 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 4624 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
4625 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
4478 | 4626 | ||
4479 | /* | 4627 | /* |
4480 | * Set up output mixers (0x08 - 0x0a) | 4628 | * Set up output mixers (0x08 - 0x0a) |
@@ -4551,6 +4699,17 @@ static void alc260_auto_init(struct hda_codec *codec) | |||
4551 | alc260_auto_init_analog_input(codec); | 4699 | alc260_auto_init_analog_input(codec); |
4552 | } | 4700 | } |
4553 | 4701 | ||
4702 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4703 | static struct hda_amp_list alc260_loopbacks[] = { | ||
4704 | { 0x07, HDA_INPUT, 0 }, | ||
4705 | { 0x07, HDA_INPUT, 1 }, | ||
4706 | { 0x07, HDA_INPUT, 2 }, | ||
4707 | { 0x07, HDA_INPUT, 3 }, | ||
4708 | { 0x07, HDA_INPUT, 4 }, | ||
4709 | { } /* end */ | ||
4710 | }; | ||
4711 | #endif | ||
4712 | |||
4554 | /* | 4713 | /* |
4555 | * ALC260 configurations | 4714 | * ALC260 configurations |
4556 | */ | 4715 | */ |
@@ -4750,6 +4909,10 @@ static int patch_alc260(struct hda_codec *codec) | |||
4750 | codec->patch_ops = alc_patch_ops; | 4909 | codec->patch_ops = alc_patch_ops; |
4751 | if (board_config == ALC260_AUTO) | 4910 | if (board_config == ALC260_AUTO) |
4752 | spec->init_hook = alc260_auto_init; | 4911 | spec->init_hook = alc260_auto_init; |
4912 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4913 | if (!spec->loopback.amplist) | ||
4914 | spec->loopback.amplist = alc260_loopbacks; | ||
4915 | #endif | ||
4753 | 4916 | ||
4754 | return 0; | 4917 | return 0; |
4755 | } | 4918 | } |
@@ -4812,12 +4975,13 @@ static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
4812 | idx = ucontrol->value.enumerated.item[0]; | 4975 | idx = ucontrol->value.enumerated.item[0]; |
4813 | if (idx >= imux->num_items) | 4976 | if (idx >= imux->num_items) |
4814 | idx = imux->num_items - 1; | 4977 | idx = imux->num_items - 1; |
4815 | if (*cur_val == idx && !codec->in_resume) | 4978 | if (*cur_val == idx) |
4816 | return 0; | 4979 | return 0; |
4817 | for (i = 0; i < imux->num_items; i++) { | 4980 | for (i = 0; i < imux->num_items; i++) { |
4818 | unsigned int v = (i == idx) ? 0x7000 : 0x7080; | 4981 | unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE; |
4819 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 4982 | snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, |
4820 | v | (imux->items[i].index << 8)); | 4983 | imux->items[i].index, |
4984 | HDA_AMP_MUTE, v); | ||
4821 | } | 4985 | } |
4822 | *cur_val = idx; | 4986 | *cur_val = idx; |
4823 | return 1; | 4987 | return 1; |
@@ -4879,6 +5043,38 @@ static struct hda_channel_mode alc882_sixstack_modes[2] = { | |||
4879 | { 8, alc882_sixstack_ch8_init }, | 5043 | { 8, alc882_sixstack_ch8_init }, |
4880 | }; | 5044 | }; |
4881 | 5045 | ||
5046 | /* | ||
5047 | * macbook pro ALC885 can switch LineIn to LineOut without loosing Mic | ||
5048 | */ | ||
5049 | |||
5050 | /* | ||
5051 | * 2ch mode | ||
5052 | */ | ||
5053 | static struct hda_verb alc885_mbp_ch2_init[] = { | ||
5054 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
5055 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5056 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
5057 | { } /* end */ | ||
5058 | }; | ||
5059 | |||
5060 | /* | ||
5061 | * 6ch mode | ||
5062 | */ | ||
5063 | static struct hda_verb alc885_mbp_ch6_init[] = { | ||
5064 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
5065 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
5066 | { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, | ||
5067 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
5068 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
5069 | { } /* end */ | ||
5070 | }; | ||
5071 | |||
5072 | static struct hda_channel_mode alc885_mbp_6ch_modes[2] = { | ||
5073 | { 2, alc885_mbp_ch2_init }, | ||
5074 | { 6, alc885_mbp_ch6_init }, | ||
5075 | }; | ||
5076 | |||
5077 | |||
4882 | /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 | 5078 | /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 |
4883 | * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b | 5079 | * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b |
4884 | */ | 5080 | */ |
@@ -4909,6 +5105,19 @@ static struct snd_kcontrol_new alc882_base_mixer[] = { | |||
4909 | { } /* end */ | 5105 | { } /* end */ |
4910 | }; | 5106 | }; |
4911 | 5107 | ||
5108 | static struct snd_kcontrol_new alc885_mbp3_mixer[] = { | ||
5109 | HDA_CODEC_VOLUME("Master Volume", 0x0c, 0x00, HDA_OUTPUT), | ||
5110 | HDA_BIND_MUTE ("Master Switch", 0x0c, 0x02, HDA_INPUT), | ||
5111 | HDA_CODEC_MUTE ("Speaker Switch", 0x14, 0x00, HDA_OUTPUT), | ||
5112 | HDA_CODEC_VOLUME("Line Out Volume", 0x0d,0x00, HDA_OUTPUT), | ||
5113 | HDA_CODEC_VOLUME("Line In Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
5114 | HDA_CODEC_MUTE ("Line In Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
5115 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT), | ||
5116 | HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT), | ||
5117 | HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0x00, HDA_INPUT), | ||
5118 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x00, HDA_INPUT), | ||
5119 | { } /* end */ | ||
5120 | }; | ||
4912 | static struct snd_kcontrol_new alc882_w2jc_mixer[] = { | 5121 | static struct snd_kcontrol_new alc882_w2jc_mixer[] = { |
4913 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 5122 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
4914 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | 5123 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), |
@@ -4934,8 +5143,10 @@ static struct snd_kcontrol_new alc882_targa_mixer[] = { | |||
4934 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 5143 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
4935 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 5144 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
4936 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 5145 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
5146 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
4937 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 5147 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
4938 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 5148 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
5149 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | ||
4939 | { } /* end */ | 5150 | { } /* end */ |
4940 | }; | 5151 | }; |
4941 | 5152 | ||
@@ -4955,6 +5166,23 @@ static struct snd_kcontrol_new alc882_asus_a7j_mixer[] = { | |||
4955 | HDA_CODEC_MUTE("Mobile Line Playback Switch", 0x0b, 0x03, HDA_INPUT), | 5166 | HDA_CODEC_MUTE("Mobile Line Playback Switch", 0x0b, 0x03, HDA_INPUT), |
4956 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 5167 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
4957 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 5168 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
5169 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
5170 | { } /* end */ | ||
5171 | }; | ||
5172 | |||
5173 | static struct snd_kcontrol_new alc882_asus_a7m_mixer[] = { | ||
5174 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
5175 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
5176 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), | ||
5177 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
5178 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
5179 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
5180 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
5181 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
5182 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
5183 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
5184 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
5185 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
4958 | { } /* end */ | 5186 | { } /* end */ |
4959 | }; | 5187 | }; |
4960 | 5188 | ||
@@ -5119,6 +5347,66 @@ static struct hda_verb alc882_macpro_init_verbs[] = { | |||
5119 | { } | 5347 | { } |
5120 | }; | 5348 | }; |
5121 | 5349 | ||
5350 | /* Macbook Pro rev3 */ | ||
5351 | static struct hda_verb alc885_mbp3_init_verbs[] = { | ||
5352 | /* Front mixer: unmute input/output amp left and right (volume = 0) */ | ||
5353 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
5354 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5355 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
5356 | /* Rear mixer */ | ||
5357 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
5358 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5359 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
5360 | /* Front Pin: output 0 (0x0c) */ | ||
5361 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
5362 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
5363 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
5364 | /* HP Pin: output 0 (0x0d) */ | ||
5365 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4}, | ||
5366 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
5367 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
5368 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | ||
5369 | /* Mic (rear) pin: input vref at 80% */ | ||
5370 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
5371 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
5372 | /* Front Mic pin: input vref at 80% */ | ||
5373 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
5374 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
5375 | /* Line In pin: use output 1 when in LineOut mode */ | ||
5376 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
5377 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
5378 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
5379 | |||
5380 | /* FIXME: use matrix-type input source selection */ | ||
5381 | /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ | ||
5382 | /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ | ||
5383 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
5384 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
5385 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
5386 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
5387 | /* Input mixer2 */ | ||
5388 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
5389 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
5390 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
5391 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
5392 | /* Input mixer3 */ | ||
5393 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
5394 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
5395 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
5396 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
5397 | /* ADC1: mute amp left and right */ | ||
5398 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5399 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
5400 | /* ADC2: mute amp left and right */ | ||
5401 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5402 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
5403 | /* ADC3: mute amp left and right */ | ||
5404 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5405 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
5406 | |||
5407 | { } | ||
5408 | }; | ||
5409 | |||
5122 | /* iMac 24 mixer. */ | 5410 | /* iMac 24 mixer. */ |
5123 | static struct snd_kcontrol_new alc885_imac24_mixer[] = { | 5411 | static struct snd_kcontrol_new alc885_imac24_mixer[] = { |
5124 | HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x00, HDA_OUTPUT), | 5412 | HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x00, HDA_OUTPUT), |
@@ -5154,14 +5442,10 @@ static void alc885_imac24_automute(struct hda_codec *codec) | |||
5154 | 5442 | ||
5155 | present = snd_hda_codec_read(codec, 0x14, 0, | 5443 | present = snd_hda_codec_read(codec, 0x14, 0, |
5156 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 5444 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
5157 | snd_hda_codec_amp_update(codec, 0x18, 0, HDA_OUTPUT, 0, | 5445 | snd_hda_codec_amp_stereo(codec, 0x18, HDA_OUTPUT, 0, |
5158 | 0x80, present ? 0x80 : 0); | 5446 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); |
5159 | snd_hda_codec_amp_update(codec, 0x18, 1, HDA_OUTPUT, 0, | 5447 | snd_hda_codec_amp_stereo(codec, 0x1a, HDA_OUTPUT, 0, |
5160 | 0x80, present ? 0x80 : 0); | 5448 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); |
5161 | snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0, | ||
5162 | 0x80, present ? 0x80 : 0); | ||
5163 | snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0, | ||
5164 | 0x80, present ? 0x80 : 0); | ||
5165 | } | 5449 | } |
5166 | 5450 | ||
5167 | /* Processes unsolicited events. */ | 5451 | /* Processes unsolicited events. */ |
@@ -5173,6 +5457,27 @@ static void alc885_imac24_unsol_event(struct hda_codec *codec, | |||
5173 | alc885_imac24_automute(codec); | 5457 | alc885_imac24_automute(codec); |
5174 | } | 5458 | } |
5175 | 5459 | ||
5460 | static void alc885_mbp3_automute(struct hda_codec *codec) | ||
5461 | { | ||
5462 | unsigned int present; | ||
5463 | |||
5464 | present = snd_hda_codec_read(codec, 0x15, 0, | ||
5465 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
5466 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, | ||
5467 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); | ||
5468 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, | ||
5469 | HDA_AMP_MUTE, present ? 0 : HDA_AMP_MUTE); | ||
5470 | |||
5471 | } | ||
5472 | static void alc885_mbp3_unsol_event(struct hda_codec *codec, | ||
5473 | unsigned int res) | ||
5474 | { | ||
5475 | /* Headphone insertion or removal. */ | ||
5476 | if ((res >> 26) == ALC880_HP_EVENT) | ||
5477 | alc885_mbp3_automute(codec); | ||
5478 | } | ||
5479 | |||
5480 | |||
5176 | static struct hda_verb alc882_targa_verbs[] = { | 5481 | static struct hda_verb alc882_targa_verbs[] = { |
5177 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 5482 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
5178 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 5483 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
@@ -5198,11 +5503,10 @@ static void alc882_targa_automute(struct hda_codec *codec) | |||
5198 | 5503 | ||
5199 | present = snd_hda_codec_read(codec, 0x14, 0, | 5504 | present = snd_hda_codec_read(codec, 0x14, 0, |
5200 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 5505 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
5201 | snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0, | 5506 | snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0, |
5202 | 0x80, present ? 0x80 : 0); | 5507 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); |
5203 | snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0, | 5508 | snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA, |
5204 | 0x80, present ? 0x80 : 0); | 5509 | present ? 1 : 3); |
5205 | snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA, present ? 1 : 3); | ||
5206 | } | 5510 | } |
5207 | 5511 | ||
5208 | static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res) | 5512 | static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res) |
@@ -5233,6 +5537,24 @@ static struct hda_verb alc882_asus_a7j_verbs[] = { | |||
5233 | { } /* end */ | 5537 | { } /* end */ |
5234 | }; | 5538 | }; |
5235 | 5539 | ||
5540 | static struct hda_verb alc882_asus_a7m_verbs[] = { | ||
5541 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
5542 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
5543 | |||
5544 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
5545 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
5546 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
5547 | |||
5548 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */ | ||
5549 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ | ||
5550 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */ | ||
5551 | |||
5552 | {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ | ||
5553 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */ | ||
5554 | {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ | ||
5555 | { } /* end */ | ||
5556 | }; | ||
5557 | |||
5236 | static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted) | 5558 | static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted) |
5237 | { | 5559 | { |
5238 | unsigned int gpiostate, gpiomask, gpiodir; | 5560 | unsigned int gpiostate, gpiomask, gpiodir; |
@@ -5265,6 +5587,20 @@ static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted) | |||
5265 | AC_VERB_SET_GPIO_DATA, gpiostate); | 5587 | AC_VERB_SET_GPIO_DATA, gpiostate); |
5266 | } | 5588 | } |
5267 | 5589 | ||
5590 | /* set up GPIO at initialization */ | ||
5591 | static void alc885_macpro_init_hook(struct hda_codec *codec) | ||
5592 | { | ||
5593 | alc882_gpio_mute(codec, 0, 0); | ||
5594 | alc882_gpio_mute(codec, 1, 0); | ||
5595 | } | ||
5596 | |||
5597 | /* set up GPIO and update auto-muting at initialization */ | ||
5598 | static void alc885_imac24_init_hook(struct hda_codec *codec) | ||
5599 | { | ||
5600 | alc885_macpro_init_hook(codec); | ||
5601 | alc885_imac24_automute(codec); | ||
5602 | } | ||
5603 | |||
5268 | /* | 5604 | /* |
5269 | * generic initialization of ADC, input mixers and output mixers | 5605 | * generic initialization of ADC, input mixers and output mixers |
5270 | */ | 5606 | */ |
@@ -5279,17 +5615,17 @@ static struct hda_verb alc882_auto_init_verbs[] = { | |||
5279 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | 5615 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
5280 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 5616 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
5281 | 5617 | ||
5282 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 5618 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
5283 | * mixer widget | 5619 | * mixer widget |
5284 | * Note: PASD motherboards uses the Line In 2 as the input for | 5620 | * Note: PASD motherboards uses the Line In 2 as the input for |
5285 | * front panel mic (mic 2) | 5621 | * front panel mic (mic 2) |
5286 | */ | 5622 | */ |
5287 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 5623 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
5288 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 5624 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
5289 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 5625 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
5290 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 5626 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
5291 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 5627 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
5292 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 5628 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
5293 | 5629 | ||
5294 | /* | 5630 | /* |
5295 | * Set up output mixers (0x0c - 0x0f) | 5631 | * Set up output mixers (0x0c - 0x0f) |
@@ -5378,6 +5714,10 @@ static struct snd_kcontrol_new alc882_capture_mixer[] = { | |||
5378 | { } /* end */ | 5714 | { } /* end */ |
5379 | }; | 5715 | }; |
5380 | 5716 | ||
5717 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
5718 | #define alc882_loopbacks alc880_loopbacks | ||
5719 | #endif | ||
5720 | |||
5381 | /* pcm configuration: identiacal with ALC880 */ | 5721 | /* pcm configuration: identiacal with ALC880 */ |
5382 | #define alc882_pcm_analog_playback alc880_pcm_analog_playback | 5722 | #define alc882_pcm_analog_playback alc880_pcm_analog_playback |
5383 | #define alc882_pcm_analog_capture alc880_pcm_analog_capture | 5723 | #define alc882_pcm_analog_capture alc880_pcm_analog_capture |
@@ -5392,7 +5732,11 @@ static const char *alc882_models[ALC882_MODEL_LAST] = { | |||
5392 | [ALC882_6ST_DIG] = "6stack-dig", | 5732 | [ALC882_6ST_DIG] = "6stack-dig", |
5393 | [ALC882_ARIMA] = "arima", | 5733 | [ALC882_ARIMA] = "arima", |
5394 | [ALC882_W2JC] = "w2jc", | 5734 | [ALC882_W2JC] = "w2jc", |
5735 | [ALC882_TARGA] = "targa", | ||
5736 | [ALC882_ASUS_A7J] = "asus-a7j", | ||
5737 | [ALC882_ASUS_A7M] = "asus-a7m", | ||
5395 | [ALC885_MACPRO] = "macpro", | 5738 | [ALC885_MACPRO] = "macpro", |
5739 | [ALC885_MBP3] = "mbp3", | ||
5396 | [ALC885_IMAC24] = "imac24", | 5740 | [ALC885_IMAC24] = "imac24", |
5397 | [ALC882_AUTO] = "auto", | 5741 | [ALC882_AUTO] = "auto", |
5398 | }; | 5742 | }; |
@@ -5404,6 +5748,8 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = { | |||
5404 | SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */ | 5748 | SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */ |
5405 | SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA), | 5749 | SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA), |
5406 | SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J), | 5750 | SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J), |
5751 | SND_PCI_QUIRK(0x1043, 0x1243, "Asus A7J", ALC882_ASUS_A7J), | ||
5752 | SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_ASUS_A7M), | ||
5407 | SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG), | 5753 | SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG), |
5408 | SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG), | 5754 | SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG), |
5409 | SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC), | 5755 | SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC), |
@@ -5455,6 +5801,20 @@ static struct alc_config_preset alc882_presets[] = { | |||
5455 | .input_mux = &alc882_capture_source, | 5801 | .input_mux = &alc882_capture_source, |
5456 | .dig_out_nid = ALC882_DIGOUT_NID, | 5802 | .dig_out_nid = ALC882_DIGOUT_NID, |
5457 | }, | 5803 | }, |
5804 | [ALC885_MBP3] = { | ||
5805 | .mixers = { alc885_mbp3_mixer, alc882_chmode_mixer }, | ||
5806 | .init_verbs = { alc885_mbp3_init_verbs, | ||
5807 | alc880_gpio1_init_verbs }, | ||
5808 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), | ||
5809 | .dac_nids = alc882_dac_nids, | ||
5810 | .channel_mode = alc885_mbp_6ch_modes, | ||
5811 | .num_channel_mode = ARRAY_SIZE(alc885_mbp_6ch_modes), | ||
5812 | .input_mux = &alc882_capture_source, | ||
5813 | .dig_out_nid = ALC882_DIGOUT_NID, | ||
5814 | .dig_in_nid = ALC882_DIGIN_NID, | ||
5815 | .unsol_event = alc885_mbp3_unsol_event, | ||
5816 | .init_hook = alc885_mbp3_automute, | ||
5817 | }, | ||
5458 | [ALC885_MACPRO] = { | 5818 | [ALC885_MACPRO] = { |
5459 | .mixers = { alc882_macpro_mixer }, | 5819 | .mixers = { alc882_macpro_mixer }, |
5460 | .init_verbs = { alc882_macpro_init_verbs }, | 5820 | .init_verbs = { alc882_macpro_init_verbs }, |
@@ -5465,6 +5825,7 @@ static struct alc_config_preset alc882_presets[] = { | |||
5465 | .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), | 5825 | .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), |
5466 | .channel_mode = alc882_ch_modes, | 5826 | .channel_mode = alc882_ch_modes, |
5467 | .input_mux = &alc882_capture_source, | 5827 | .input_mux = &alc882_capture_source, |
5828 | .init_hook = alc885_macpro_init_hook, | ||
5468 | }, | 5829 | }, |
5469 | [ALC885_IMAC24] = { | 5830 | [ALC885_IMAC24] = { |
5470 | .mixers = { alc885_imac24_mixer }, | 5831 | .mixers = { alc885_imac24_mixer }, |
@@ -5477,7 +5838,7 @@ static struct alc_config_preset alc882_presets[] = { | |||
5477 | .channel_mode = alc882_ch_modes, | 5838 | .channel_mode = alc882_ch_modes, |
5478 | .input_mux = &alc882_capture_source, | 5839 | .input_mux = &alc882_capture_source, |
5479 | .unsol_event = alc885_imac24_unsol_event, | 5840 | .unsol_event = alc885_imac24_unsol_event, |
5480 | .init_hook = alc885_imac24_automute, | 5841 | .init_hook = alc885_imac24_init_hook, |
5481 | }, | 5842 | }, |
5482 | [ALC882_TARGA] = { | 5843 | [ALC882_TARGA] = { |
5483 | .mixers = { alc882_targa_mixer, alc882_chmode_mixer, | 5844 | .mixers = { alc882_targa_mixer, alc882_chmode_mixer, |
@@ -5509,6 +5870,19 @@ static struct alc_config_preset alc882_presets[] = { | |||
5509 | .need_dac_fix = 1, | 5870 | .need_dac_fix = 1, |
5510 | .input_mux = &alc882_capture_source, | 5871 | .input_mux = &alc882_capture_source, |
5511 | }, | 5872 | }, |
5873 | [ALC882_ASUS_A7M] = { | ||
5874 | .mixers = { alc882_asus_a7m_mixer, alc882_chmode_mixer }, | ||
5875 | .init_verbs = { alc882_init_verbs, alc882_eapd_verbs, | ||
5876 | alc880_gpio1_init_verbs, | ||
5877 | alc882_asus_a7m_verbs }, | ||
5878 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), | ||
5879 | .dac_nids = alc882_dac_nids, | ||
5880 | .dig_out_nid = ALC882_DIGOUT_NID, | ||
5881 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), | ||
5882 | .channel_mode = alc880_threestack_modes, | ||
5883 | .need_dac_fix = 1, | ||
5884 | .input_mux = &alc882_capture_source, | ||
5885 | }, | ||
5512 | }; | 5886 | }; |
5513 | 5887 | ||
5514 | 5888 | ||
@@ -5608,6 +5982,32 @@ static void alc882_auto_init_analog_input(struct hda_codec *codec) | |||
5608 | } | 5982 | } |
5609 | } | 5983 | } |
5610 | 5984 | ||
5985 | /* add mic boosts if needed */ | ||
5986 | static int alc_auto_add_mic_boost(struct hda_codec *codec) | ||
5987 | { | ||
5988 | struct alc_spec *spec = codec->spec; | ||
5989 | int err; | ||
5990 | hda_nid_t nid; | ||
5991 | |||
5992 | nid = spec->autocfg.input_pins[AUTO_PIN_MIC]; | ||
5993 | if (nid) { | ||
5994 | err = add_control(spec, ALC_CTL_WIDGET_VOL, | ||
5995 | "Mic Boost", | ||
5996 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); | ||
5997 | if (err < 0) | ||
5998 | return err; | ||
5999 | } | ||
6000 | nid = spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC]; | ||
6001 | if (nid) { | ||
6002 | err = add_control(spec, ALC_CTL_WIDGET_VOL, | ||
6003 | "Front Mic Boost", | ||
6004 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); | ||
6005 | if (err < 0) | ||
6006 | return err; | ||
6007 | } | ||
6008 | return 0; | ||
6009 | } | ||
6010 | |||
5611 | /* almost identical with ALC880 parser... */ | 6011 | /* almost identical with ALC880 parser... */ |
5612 | static int alc882_parse_auto_config(struct hda_codec *codec) | 6012 | static int alc882_parse_auto_config(struct hda_codec *codec) |
5613 | { | 6013 | { |
@@ -5616,10 +6016,17 @@ static int alc882_parse_auto_config(struct hda_codec *codec) | |||
5616 | 6016 | ||
5617 | if (err < 0) | 6017 | if (err < 0) |
5618 | return err; | 6018 | return err; |
5619 | else if (err > 0) | 6019 | else if (!err) |
5620 | /* hack - override the init verbs */ | 6020 | return 0; /* no config found */ |
5621 | spec->init_verbs[0] = alc882_auto_init_verbs; | 6021 | |
5622 | return err; | 6022 | err = alc_auto_add_mic_boost(codec); |
6023 | if (err < 0) | ||
6024 | return err; | ||
6025 | |||
6026 | /* hack - override the init verbs */ | ||
6027 | spec->init_verbs[0] = alc882_auto_init_verbs; | ||
6028 | |||
6029 | return 1; /* config found */ | ||
5623 | } | 6030 | } |
5624 | 6031 | ||
5625 | /* additional initialization for auto-configuration model */ | 6032 | /* additional initialization for auto-configuration model */ |
@@ -5654,6 +6061,9 @@ static int patch_alc882(struct hda_codec *codec) | |||
5654 | case 0x106b1000: /* iMac 24 */ | 6061 | case 0x106b1000: /* iMac 24 */ |
5655 | board_config = ALC885_IMAC24; | 6062 | board_config = ALC885_IMAC24; |
5656 | break; | 6063 | break; |
6064 | case 0x106b2c00: /* Macbook Pro rev3 */ | ||
6065 | board_config = ALC885_MBP3; | ||
6066 | break; | ||
5657 | default: | 6067 | default: |
5658 | printk(KERN_INFO "hda_codec: Unknown model for ALC882, " | 6068 | printk(KERN_INFO "hda_codec: Unknown model for ALC882, " |
5659 | "trying auto-probe from BIOS...\n"); | 6069 | "trying auto-probe from BIOS...\n"); |
@@ -5680,11 +6090,6 @@ static int patch_alc882(struct hda_codec *codec) | |||
5680 | if (board_config != ALC882_AUTO) | 6090 | if (board_config != ALC882_AUTO) |
5681 | setup_preset(spec, &alc882_presets[board_config]); | 6091 | setup_preset(spec, &alc882_presets[board_config]); |
5682 | 6092 | ||
5683 | if (board_config == ALC885_MACPRO || board_config == ALC885_IMAC24) { | ||
5684 | alc882_gpio_mute(codec, 0, 0); | ||
5685 | alc882_gpio_mute(codec, 1, 0); | ||
5686 | } | ||
5687 | |||
5688 | spec->stream_name_analog = "ALC882 Analog"; | 6093 | spec->stream_name_analog = "ALC882 Analog"; |
5689 | spec->stream_analog_playback = &alc882_pcm_analog_playback; | 6094 | spec->stream_analog_playback = &alc882_pcm_analog_playback; |
5690 | spec->stream_analog_capture = &alc882_pcm_analog_capture; | 6095 | spec->stream_analog_capture = &alc882_pcm_analog_capture; |
@@ -5715,6 +6120,10 @@ static int patch_alc882(struct hda_codec *codec) | |||
5715 | codec->patch_ops = alc_patch_ops; | 6120 | codec->patch_ops = alc_patch_ops; |
5716 | if (board_config == ALC882_AUTO) | 6121 | if (board_config == ALC882_AUTO) |
5717 | spec->init_hook = alc882_auto_init; | 6122 | spec->init_hook = alc882_auto_init; |
6123 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
6124 | if (!spec->loopback.amplist) | ||
6125 | spec->loopback.amplist = alc882_loopbacks; | ||
6126 | #endif | ||
5718 | 6127 | ||
5719 | return 0; | 6128 | return 0; |
5720 | } | 6129 | } |
@@ -5792,12 +6201,13 @@ static int alc883_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
5792 | idx = ucontrol->value.enumerated.item[0]; | 6201 | idx = ucontrol->value.enumerated.item[0]; |
5793 | if (idx >= imux->num_items) | 6202 | if (idx >= imux->num_items) |
5794 | idx = imux->num_items - 1; | 6203 | idx = imux->num_items - 1; |
5795 | if (*cur_val == idx && !codec->in_resume) | 6204 | if (*cur_val == idx) |
5796 | return 0; | 6205 | return 0; |
5797 | for (i = 0; i < imux->num_items; i++) { | 6206 | for (i = 0; i < imux->num_items; i++) { |
5798 | unsigned int v = (i == idx) ? 0x7000 : 0x7080; | 6207 | unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE; |
5799 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 6208 | snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, |
5800 | v | (imux->items[i].index << 8)); | 6209 | imux->items[i].index, |
6210 | HDA_AMP_MUTE, v); | ||
5801 | } | 6211 | } |
5802 | *cur_val = idx; | 6212 | *cur_val = idx; |
5803 | return 1; | 6213 | return 1; |
@@ -5822,6 +6232,18 @@ static struct hda_verb alc883_3ST_ch2_init[] = { | |||
5822 | }; | 6232 | }; |
5823 | 6233 | ||
5824 | /* | 6234 | /* |
6235 | * 4ch mode | ||
6236 | */ | ||
6237 | static struct hda_verb alc883_3ST_ch4_init[] = { | ||
6238 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
6239 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
6240 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
6241 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
6242 | { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, | ||
6243 | { } /* end */ | ||
6244 | }; | ||
6245 | |||
6246 | /* | ||
5825 | * 6ch mode | 6247 | * 6ch mode |
5826 | */ | 6248 | */ |
5827 | static struct hda_verb alc883_3ST_ch6_init[] = { | 6249 | static struct hda_verb alc883_3ST_ch6_init[] = { |
@@ -5834,8 +6256,9 @@ static struct hda_verb alc883_3ST_ch6_init[] = { | |||
5834 | { } /* end */ | 6256 | { } /* end */ |
5835 | }; | 6257 | }; |
5836 | 6258 | ||
5837 | static struct hda_channel_mode alc883_3ST_6ch_modes[2] = { | 6259 | static struct hda_channel_mode alc883_3ST_6ch_modes[3] = { |
5838 | { 2, alc883_3ST_ch2_init }, | 6260 | { 2, alc883_3ST_ch2_init }, |
6261 | { 4, alc883_3ST_ch4_init }, | ||
5839 | { 6, alc883_3ST_ch6_init }, | 6262 | { 6, alc883_3ST_ch6_init }, |
5840 | }; | 6263 | }; |
5841 | 6264 | ||
@@ -6235,6 +6658,31 @@ static struct snd_kcontrol_new alc888_3st_hp_mixer[] = { | |||
6235 | { } /* end */ | 6658 | { } /* end */ |
6236 | }; | 6659 | }; |
6237 | 6660 | ||
6661 | static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = { | ||
6662 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
6663 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
6664 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), | ||
6665 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
6666 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
6667 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
6668 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
6669 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
6670 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
6671 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
6672 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | ||
6673 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
6674 | { | ||
6675 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
6676 | /* .name = "Capture Source", */ | ||
6677 | .name = "Input Source", | ||
6678 | .count = 2, | ||
6679 | .info = alc883_mux_enum_info, | ||
6680 | .get = alc883_mux_enum_get, | ||
6681 | .put = alc883_mux_enum_put, | ||
6682 | }, | ||
6683 | { } /* end */ | ||
6684 | }; | ||
6685 | |||
6238 | static struct snd_kcontrol_new alc883_chmode_mixer[] = { | 6686 | static struct snd_kcontrol_new alc883_chmode_mixer[] = { |
6239 | { | 6687 | { |
6240 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 6688 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -6270,11 +6718,12 @@ static struct hda_verb alc883_init_verbs[] = { | |||
6270 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 6718 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
6271 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | 6719 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
6272 | 6720 | ||
6273 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 6721 | /* mute analog input loopbacks */ |
6274 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 6722 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
6275 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 6723 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
6276 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 6724 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
6277 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 6725 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
6726 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
6278 | 6727 | ||
6279 | /* Front Pin: output 0 (0x0c) */ | 6728 | /* Front Pin: output 0 (0x0c) */ |
6280 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 6729 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
@@ -6366,6 +6815,19 @@ static struct hda_verb alc888_lenovo_ms7195_verbs[] = { | |||
6366 | { } /* end */ | 6815 | { } /* end */ |
6367 | }; | 6816 | }; |
6368 | 6817 | ||
6818 | static struct hda_verb alc883_haier_w66_verbs[] = { | ||
6819 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
6820 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
6821 | |||
6822 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
6823 | |||
6824 | {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
6825 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
6826 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | ||
6827 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
6828 | { } /* end */ | ||
6829 | }; | ||
6830 | |||
6369 | static struct hda_verb alc888_6st_hp_verbs[] = { | 6831 | static struct hda_verb alc888_6st_hp_verbs[] = { |
6370 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */ | 6832 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */ |
6371 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x02}, /* Rear : output 2 (0x0e) */ | 6833 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x02}, /* Rear : output 2 (0x0e) */ |
@@ -6409,15 +6871,10 @@ static void alc888_lenovo_ms7195_front_automute(struct hda_codec *codec) | |||
6409 | 6871 | ||
6410 | present = snd_hda_codec_read(codec, 0x1b, 0, | 6872 | present = snd_hda_codec_read(codec, 0x1b, 0, |
6411 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 6873 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
6412 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | 6874 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, |
6413 | 0x80, present ? 0x80 : 0); | 6875 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); |
6414 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | 6876 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, |
6415 | 0x80, present ? 0x80 : 0); | 6877 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); |
6416 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | ||
6417 | 0x80, present ? 0x80 : 0); | ||
6418 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | ||
6419 | 0x80, present ? 0x80 : 0); | ||
6420 | |||
6421 | } | 6878 | } |
6422 | 6879 | ||
6423 | /* toggle RCA according to the front-jack state */ | 6880 | /* toggle RCA according to the front-jack state */ |
@@ -6427,12 +6884,10 @@ static void alc888_lenovo_ms7195_rca_automute(struct hda_codec *codec) | |||
6427 | 6884 | ||
6428 | present = snd_hda_codec_read(codec, 0x14, 0, | 6885 | present = snd_hda_codec_read(codec, 0x14, 0, |
6429 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 6886 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
6430 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | 6887 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, |
6431 | 0x80, present ? 0x80 : 0); | 6888 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); |
6432 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | ||
6433 | 0x80, present ? 0x80 : 0); | ||
6434 | |||
6435 | } | 6889 | } |
6890 | |||
6436 | static void alc883_lenovo_ms7195_unsol_event(struct hda_codec *codec, | 6891 | static void alc883_lenovo_ms7195_unsol_event(struct hda_codec *codec, |
6437 | unsigned int res) | 6892 | unsigned int res) |
6438 | { | 6893 | { |
@@ -6459,10 +6914,8 @@ static void alc883_medion_md2_automute(struct hda_codec *codec) | |||
6459 | 6914 | ||
6460 | present = snd_hda_codec_read(codec, 0x14, 0, | 6915 | present = snd_hda_codec_read(codec, 0x14, 0, |
6461 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 6916 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
6462 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | 6917 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, |
6463 | 0x80, present ? 0x80 : 0); | 6918 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); |
6464 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | ||
6465 | 0x80, present ? 0x80 : 0); | ||
6466 | } | 6919 | } |
6467 | 6920 | ||
6468 | static void alc883_medion_md2_unsol_event(struct hda_codec *codec, | 6921 | static void alc883_medion_md2_unsol_event(struct hda_codec *codec, |
@@ -6480,13 +6933,11 @@ static void alc883_tagra_automute(struct hda_codec *codec) | |||
6480 | 6933 | ||
6481 | present = snd_hda_codec_read(codec, 0x14, 0, | 6934 | present = snd_hda_codec_read(codec, 0x14, 0, |
6482 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 6935 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
6483 | bits = present ? 0x80 : 0; | 6936 | bits = present ? HDA_AMP_MUTE : 0; |
6484 | snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0, | 6937 | snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0, |
6485 | 0x80, bits); | 6938 | HDA_AMP_MUTE, bits); |
6486 | snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0, | 6939 | snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA, |
6487 | 0x80, bits); | 6940 | present ? 1 : 3); |
6488 | snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA, | ||
6489 | present ? 1 : 3); | ||
6490 | } | 6941 | } |
6491 | 6942 | ||
6492 | static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res) | 6943 | static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res) |
@@ -6495,6 +6946,25 @@ static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res) | |||
6495 | alc883_tagra_automute(codec); | 6946 | alc883_tagra_automute(codec); |
6496 | } | 6947 | } |
6497 | 6948 | ||
6949 | static void alc883_haier_w66_automute(struct hda_codec *codec) | ||
6950 | { | ||
6951 | unsigned int present; | ||
6952 | unsigned char bits; | ||
6953 | |||
6954 | present = snd_hda_codec_read(codec, 0x1b, 0, | ||
6955 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
6956 | bits = present ? 0x80 : 0; | ||
6957 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, | ||
6958 | 0x80, bits); | ||
6959 | } | ||
6960 | |||
6961 | static void alc883_haier_w66_unsol_event(struct hda_codec *codec, | ||
6962 | unsigned int res) | ||
6963 | { | ||
6964 | if ((res >> 26) == ALC880_HP_EVENT) | ||
6965 | alc883_haier_w66_automute(codec); | ||
6966 | } | ||
6967 | |||
6498 | static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec) | 6968 | static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec) |
6499 | { | 6969 | { |
6500 | unsigned int present; | 6970 | unsigned int present; |
@@ -6502,11 +6972,9 @@ static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec) | |||
6502 | 6972 | ||
6503 | present = snd_hda_codec_read(codec, 0x14, 0, | 6973 | present = snd_hda_codec_read(codec, 0x14, 0, |
6504 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 6974 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
6505 | bits = present ? 0x80 : 0; | 6975 | bits = present ? HDA_AMP_MUTE : 0; |
6506 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | 6976 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, |
6507 | 0x80, bits); | 6977 | HDA_AMP_MUTE, bits); |
6508 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | ||
6509 | 0x80, bits); | ||
6510 | } | 6978 | } |
6511 | 6979 | ||
6512 | static void alc883_lenovo_101e_all_automute(struct hda_codec *codec) | 6980 | static void alc883_lenovo_101e_all_automute(struct hda_codec *codec) |
@@ -6516,15 +6984,11 @@ static void alc883_lenovo_101e_all_automute(struct hda_codec *codec) | |||
6516 | 6984 | ||
6517 | present = snd_hda_codec_read(codec, 0x1b, 0, | 6985 | present = snd_hda_codec_read(codec, 0x1b, 0, |
6518 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 6986 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
6519 | bits = present ? 0x80 : 0; | 6987 | bits = present ? HDA_AMP_MUTE : 0; |
6520 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | 6988 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, |
6521 | 0x80, bits); | 6989 | HDA_AMP_MUTE, bits); |
6522 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | 6990 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, |
6523 | 0x80, bits); | 6991 | HDA_AMP_MUTE, bits); |
6524 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | ||
6525 | 0x80, bits); | ||
6526 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
6527 | 0x80, bits); | ||
6528 | } | 6992 | } |
6529 | 6993 | ||
6530 | static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec, | 6994 | static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec, |
@@ -6536,6 +7000,44 @@ static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec, | |||
6536 | alc883_lenovo_101e_ispeaker_automute(codec); | 7000 | alc883_lenovo_101e_ispeaker_automute(codec); |
6537 | } | 7001 | } |
6538 | 7002 | ||
7003 | /* toggle speaker-output according to the hp-jack state */ | ||
7004 | static void alc883_acer_aspire_automute(struct hda_codec *codec) | ||
7005 | { | ||
7006 | unsigned int present; | ||
7007 | |||
7008 | present = snd_hda_codec_read(codec, 0x14, 0, | ||
7009 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
7010 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, | ||
7011 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); | ||
7012 | snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, | ||
7013 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); | ||
7014 | } | ||
7015 | |||
7016 | static void alc883_acer_aspire_unsol_event(struct hda_codec *codec, | ||
7017 | unsigned int res) | ||
7018 | { | ||
7019 | if ((res >> 26) == ALC880_HP_EVENT) | ||
7020 | alc883_acer_aspire_automute(codec); | ||
7021 | } | ||
7022 | |||
7023 | static struct hda_verb alc883_acer_eapd_verbs[] = { | ||
7024 | /* HP Pin: output 0 (0x0c) */ | ||
7025 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
7026 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
7027 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
7028 | /* Front Pin: output 0 (0x0c) */ | ||
7029 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
7030 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
7031 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
7032 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
7033 | /* eanable EAPD on medion laptop */ | ||
7034 | {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, | ||
7035 | {0x20, AC_VERB_SET_PROC_COEF, 0x3050}, | ||
7036 | /* enable unsolicited event */ | ||
7037 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | ||
7038 | { } | ||
7039 | }; | ||
7040 | |||
6539 | /* | 7041 | /* |
6540 | * generic initialization of ADC, input mixers and output mixers | 7042 | * generic initialization of ADC, input mixers and output mixers |
6541 | */ | 7043 | */ |
@@ -6548,17 +7050,17 @@ static struct hda_verb alc883_auto_init_verbs[] = { | |||
6548 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | 7050 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
6549 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7051 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
6550 | 7052 | ||
6551 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 7053 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
6552 | * mixer widget | 7054 | * mixer widget |
6553 | * Note: PASD motherboards uses the Line In 2 as the input for | 7055 | * Note: PASD motherboards uses the Line In 2 as the input for |
6554 | * front panel mic (mic 2) | 7056 | * front panel mic (mic 2) |
6555 | */ | 7057 | */ |
6556 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 7058 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
6557 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7059 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
6558 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 7060 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
6559 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 7061 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
6560 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 7062 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
6561 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 7063 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
6562 | 7064 | ||
6563 | /* | 7065 | /* |
6564 | * Set up output mixers (0x0c - 0x0f) | 7066 | * Set up output mixers (0x0c - 0x0f) |
@@ -6621,6 +7123,10 @@ static struct snd_kcontrol_new alc883_capture_mixer[] = { | |||
6621 | { } /* end */ | 7123 | { } /* end */ |
6622 | }; | 7124 | }; |
6623 | 7125 | ||
7126 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
7127 | #define alc883_loopbacks alc880_loopbacks | ||
7128 | #endif | ||
7129 | |||
6624 | /* pcm configuration: identiacal with ALC880 */ | 7130 | /* pcm configuration: identiacal with ALC880 */ |
6625 | #define alc883_pcm_analog_playback alc880_pcm_analog_playback | 7131 | #define alc883_pcm_analog_playback alc880_pcm_analog_playback |
6626 | #define alc883_pcm_analog_capture alc880_pcm_analog_capture | 7132 | #define alc883_pcm_analog_capture alc880_pcm_analog_capture |
@@ -6638,12 +7144,14 @@ static const char *alc883_models[ALC883_MODEL_LAST] = { | |||
6638 | [ALC883_TARGA_DIG] = "targa-dig", | 7144 | [ALC883_TARGA_DIG] = "targa-dig", |
6639 | [ALC883_TARGA_2ch_DIG] = "targa-2ch-dig", | 7145 | [ALC883_TARGA_2ch_DIG] = "targa-2ch-dig", |
6640 | [ALC883_ACER] = "acer", | 7146 | [ALC883_ACER] = "acer", |
7147 | [ALC883_ACER_ASPIRE] = "acer-aspire", | ||
6641 | [ALC883_MEDION] = "medion", | 7148 | [ALC883_MEDION] = "medion", |
6642 | [ALC883_MEDION_MD2] = "medion-md2", | 7149 | [ALC883_MEDION_MD2] = "medion-md2", |
6643 | [ALC883_LAPTOP_EAPD] = "laptop-eapd", | 7150 | [ALC883_LAPTOP_EAPD] = "laptop-eapd", |
6644 | [ALC883_LENOVO_101E_2ch] = "lenovo-101e", | 7151 | [ALC883_LENOVO_101E_2ch] = "lenovo-101e", |
6645 | [ALC883_LENOVO_NB0763] = "lenovo-nb0763", | 7152 | [ALC883_LENOVO_NB0763] = "lenovo-nb0763", |
6646 | [ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig", | 7153 | [ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig", |
7154 | [ALC883_HAIER_W66] = "haier-w66", | ||
6647 | [ALC888_6ST_HP] = "6stack-hp", | 7155 | [ALC888_6ST_HP] = "6stack-hp", |
6648 | [ALC888_3ST_HP] = "3stack-hp", | 7156 | [ALC888_3ST_HP] = "3stack-hp", |
6649 | [ALC883_AUTO] = "auto", | 7157 | [ALC883_AUTO] = "auto", |
@@ -6669,10 +7177,14 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { | |||
6669 | SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG), | 7177 | SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG), |
6670 | SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG), | 7178 | SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG), |
6671 | SND_PCI_QUIRK(0x1462, 0x3fc3, "MSI", ALC883_TARGA_DIG), | 7179 | SND_PCI_QUIRK(0x1462, 0x3fc3, "MSI", ALC883_TARGA_DIG), |
7180 | SND_PCI_QUIRK(0x1462, 0x3fdf, "MSI", ALC883_TARGA_DIG), | ||
6672 | SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG), | 7181 | SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG), |
6673 | SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG), | 7182 | SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG), |
6674 | SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG), | 7183 | SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG), |
6675 | SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG), | 7184 | SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG), |
7185 | SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE), | ||
7186 | SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE), | ||
7187 | SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE), | ||
6676 | SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER), | 7188 | SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER), |
6677 | SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch), | 7189 | SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch), |
6678 | SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION), | 7190 | SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION), |
@@ -6685,6 +7197,10 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { | |||
6685 | SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP), | 7197 | SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP), |
6686 | SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP), | 7198 | SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP), |
6687 | SND_PCI_QUIRK(0x17c0, 0x4071, "MEDION MD2", ALC883_MEDION_MD2), | 7199 | SND_PCI_QUIRK(0x17c0, 0x4071, "MEDION MD2", ALC883_MEDION_MD2), |
7200 | SND_PCI_QUIRK(0x1991, 0x5625, "Haier W66", ALC883_HAIER_W66), | ||
7201 | SND_PCI_QUIRK(0x17aa, 0x3bfc, "Lenovo NB0763", ALC883_LENOVO_NB0763), | ||
7202 | SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG), | ||
7203 | SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG), | ||
6688 | {} | 7204 | {} |
6689 | }; | 7205 | }; |
6690 | 7206 | ||
@@ -6771,8 +7287,7 @@ static struct alc_config_preset alc883_presets[] = { | |||
6771 | .init_hook = alc883_tagra_automute, | 7287 | .init_hook = alc883_tagra_automute, |
6772 | }, | 7288 | }, |
6773 | [ALC883_ACER] = { | 7289 | [ALC883_ACER] = { |
6774 | .mixers = { alc883_base_mixer, | 7290 | .mixers = { alc883_base_mixer }, |
6775 | alc883_chmode_mixer }, | ||
6776 | /* On TravelMate laptops, GPIO 0 enables the internal speaker | 7291 | /* On TravelMate laptops, GPIO 0 enables the internal speaker |
6777 | * and the headphone jack. Turn this on and rely on the | 7292 | * and the headphone jack. Turn this on and rely on the |
6778 | * standard mute methods whenever the user wants to turn | 7293 | * standard mute methods whenever the user wants to turn |
@@ -6787,6 +7302,20 @@ static struct alc_config_preset alc883_presets[] = { | |||
6787 | .channel_mode = alc883_3ST_2ch_modes, | 7302 | .channel_mode = alc883_3ST_2ch_modes, |
6788 | .input_mux = &alc883_capture_source, | 7303 | .input_mux = &alc883_capture_source, |
6789 | }, | 7304 | }, |
7305 | [ALC883_ACER_ASPIRE] = { | ||
7306 | .mixers = { alc883_acer_aspire_mixer }, | ||
7307 | .init_verbs = { alc883_init_verbs, alc883_acer_eapd_verbs }, | ||
7308 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | ||
7309 | .dac_nids = alc883_dac_nids, | ||
7310 | .dig_out_nid = ALC883_DIGOUT_NID, | ||
7311 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), | ||
7312 | .adc_nids = alc883_adc_nids, | ||
7313 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), | ||
7314 | .channel_mode = alc883_3ST_2ch_modes, | ||
7315 | .input_mux = &alc883_capture_source, | ||
7316 | .unsol_event = alc883_acer_aspire_unsol_event, | ||
7317 | .init_hook = alc883_acer_aspire_automute, | ||
7318 | }, | ||
6790 | [ALC883_MEDION] = { | 7319 | [ALC883_MEDION] = { |
6791 | .mixers = { alc883_fivestack_mixer, | 7320 | .mixers = { alc883_fivestack_mixer, |
6792 | alc883_chmode_mixer }, | 7321 | alc883_chmode_mixer }, |
@@ -6815,8 +7344,7 @@ static struct alc_config_preset alc883_presets[] = { | |||
6815 | .init_hook = alc883_medion_md2_automute, | 7344 | .init_hook = alc883_medion_md2_automute, |
6816 | }, | 7345 | }, |
6817 | [ALC883_LAPTOP_EAPD] = { | 7346 | [ALC883_LAPTOP_EAPD] = { |
6818 | .mixers = { alc883_base_mixer, | 7347 | .mixers = { alc883_base_mixer }, |
6819 | alc883_chmode_mixer }, | ||
6820 | .init_verbs = { alc883_init_verbs, alc882_eapd_verbs }, | 7348 | .init_verbs = { alc883_init_verbs, alc882_eapd_verbs }, |
6821 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | 7349 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), |
6822 | .dac_nids = alc883_dac_nids, | 7350 | .dac_nids = alc883_dac_nids, |
@@ -6867,6 +7395,20 @@ static struct alc_config_preset alc883_presets[] = { | |||
6867 | .input_mux = &alc883_capture_source, | 7395 | .input_mux = &alc883_capture_source, |
6868 | .unsol_event = alc883_lenovo_ms7195_unsol_event, | 7396 | .unsol_event = alc883_lenovo_ms7195_unsol_event, |
6869 | .init_hook = alc888_lenovo_ms7195_front_automute, | 7397 | .init_hook = alc888_lenovo_ms7195_front_automute, |
7398 | }, | ||
7399 | [ALC883_HAIER_W66] = { | ||
7400 | .mixers = { alc883_tagra_2ch_mixer}, | ||
7401 | .init_verbs = { alc883_init_verbs, alc883_haier_w66_verbs}, | ||
7402 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | ||
7403 | .dac_nids = alc883_dac_nids, | ||
7404 | .dig_out_nid = ALC883_DIGOUT_NID, | ||
7405 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), | ||
7406 | .adc_nids = alc883_adc_nids, | ||
7407 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), | ||
7408 | .channel_mode = alc883_3ST_2ch_modes, | ||
7409 | .input_mux = &alc883_capture_source, | ||
7410 | .unsol_event = alc883_haier_w66_unsol_event, | ||
7411 | .init_hook = alc883_haier_w66_automute, | ||
6870 | }, | 7412 | }, |
6871 | [ALC888_6ST_HP] = { | 7413 | [ALC888_6ST_HP] = { |
6872 | .mixers = { alc888_6st_hp_mixer, alc883_chmode_mixer }, | 7414 | .mixers = { alc888_6st_hp_mixer, alc883_chmode_mixer }, |
@@ -6977,12 +7519,19 @@ static int alc883_parse_auto_config(struct hda_codec *codec) | |||
6977 | 7519 | ||
6978 | if (err < 0) | 7520 | if (err < 0) |
6979 | return err; | 7521 | return err; |
6980 | else if (err > 0) | 7522 | else if (!err) |
6981 | /* hack - override the init verbs */ | 7523 | return 0; /* no config found */ |
6982 | spec->init_verbs[0] = alc883_auto_init_verbs; | 7524 | |
7525 | err = alc_auto_add_mic_boost(codec); | ||
7526 | if (err < 0) | ||
7527 | return err; | ||
7528 | |||
7529 | /* hack - override the init verbs */ | ||
7530 | spec->init_verbs[0] = alc883_auto_init_verbs; | ||
6983 | spec->mixers[spec->num_mixers] = alc883_capture_mixer; | 7531 | spec->mixers[spec->num_mixers] = alc883_capture_mixer; |
6984 | spec->num_mixers++; | 7532 | spec->num_mixers++; |
6985 | return err; | 7533 | |
7534 | return 1; /* config found */ | ||
6986 | } | 7535 | } |
6987 | 7536 | ||
6988 | /* additional initialization for auto-configuration model */ | 7537 | /* additional initialization for auto-configuration model */ |
@@ -7046,6 +7595,10 @@ static int patch_alc883(struct hda_codec *codec) | |||
7046 | codec->patch_ops = alc_patch_ops; | 7595 | codec->patch_ops = alc_patch_ops; |
7047 | if (board_config == ALC883_AUTO) | 7596 | if (board_config == ALC883_AUTO) |
7048 | spec->init_hook = alc883_auto_init; | 7597 | spec->init_hook = alc883_auto_init; |
7598 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
7599 | if (!spec->loopback.amplist) | ||
7600 | spec->loopback.amplist = alc883_loopbacks; | ||
7601 | #endif | ||
7049 | 7602 | ||
7050 | return 0; | 7603 | return 0; |
7051 | } | 7604 | } |
@@ -7156,9 +7709,46 @@ static struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = { | |||
7156 | { } /* end */ | 7709 | { } /* end */ |
7157 | }; | 7710 | }; |
7158 | 7711 | ||
7712 | /* bind hp and internal speaker mute (with plug check) */ | ||
7713 | static int alc262_sony_master_sw_put(struct snd_kcontrol *kcontrol, | ||
7714 | struct snd_ctl_elem_value *ucontrol) | ||
7715 | { | ||
7716 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
7717 | long *valp = ucontrol->value.integer.value; | ||
7718 | int change; | ||
7719 | |||
7720 | /* change hp mute */ | ||
7721 | change = snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | ||
7722 | HDA_AMP_MUTE, | ||
7723 | valp[0] ? 0 : HDA_AMP_MUTE); | ||
7724 | change |= snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | ||
7725 | HDA_AMP_MUTE, | ||
7726 | valp[1] ? 0 : HDA_AMP_MUTE); | ||
7727 | if (change) { | ||
7728 | /* change speaker according to HP jack state */ | ||
7729 | struct alc_spec *spec = codec->spec; | ||
7730 | unsigned int mute; | ||
7731 | if (spec->jack_present) | ||
7732 | mute = HDA_AMP_MUTE; | ||
7733 | else | ||
7734 | mute = snd_hda_codec_amp_read(codec, 0x15, 0, | ||
7735 | HDA_OUTPUT, 0); | ||
7736 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, | ||
7737 | HDA_AMP_MUTE, mute); | ||
7738 | } | ||
7739 | return change; | ||
7740 | } | ||
7741 | |||
7159 | static struct snd_kcontrol_new alc262_sony_mixer[] = { | 7742 | static struct snd_kcontrol_new alc262_sony_mixer[] = { |
7160 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 7743 | HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
7161 | HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT), | 7744 | { |
7745 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
7746 | .name = "Master Playback Switch", | ||
7747 | .info = snd_hda_mixer_amp_switch_info, | ||
7748 | .get = snd_hda_mixer_amp_switch_get, | ||
7749 | .put = alc262_sony_master_sw_put, | ||
7750 | .private_value = HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT), | ||
7751 | }, | ||
7162 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 7752 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
7163 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 7753 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
7164 | HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | 7754 | HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), |
@@ -7194,17 +7784,17 @@ static struct hda_verb alc262_init_verbs[] = { | |||
7194 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | 7784 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
7195 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7785 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7196 | 7786 | ||
7197 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 7787 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
7198 | * mixer widget | 7788 | * mixer widget |
7199 | * Note: PASD motherboards uses the Line In 2 as the input for | 7789 | * Note: PASD motherboards uses the Line In 2 as the input for |
7200 | * front panel mic (mic 2) | 7790 | * front panel mic (mic 2) |
7201 | */ | 7791 | */ |
7202 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 7792 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
7203 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 7793 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
7204 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 7794 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
7205 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 7795 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
7206 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 7796 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
7207 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 7797 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
7208 | 7798 | ||
7209 | /* | 7799 | /* |
7210 | * Set up output mixers (0x0c - 0x0e) | 7800 | * Set up output mixers (0x0c - 0x0e) |
@@ -7285,34 +7875,26 @@ static struct hda_verb alc262_sony_unsol_verbs[] = { | |||
7285 | }; | 7875 | }; |
7286 | 7876 | ||
7287 | /* mute/unmute internal speaker according to the hp jack and mute state */ | 7877 | /* mute/unmute internal speaker according to the hp jack and mute state */ |
7288 | static void alc262_hippo_automute(struct hda_codec *codec, int force) | 7878 | static void alc262_hippo_automute(struct hda_codec *codec) |
7289 | { | 7879 | { |
7290 | struct alc_spec *spec = codec->spec; | 7880 | struct alc_spec *spec = codec->spec; |
7291 | unsigned int mute; | 7881 | unsigned int mute; |
7882 | unsigned int present; | ||
7292 | 7883 | ||
7293 | if (force || !spec->sense_updated) { | 7884 | /* need to execute and sync at first */ |
7294 | unsigned int present; | 7885 | snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0); |
7295 | /* need to execute and sync at first */ | 7886 | present = snd_hda_codec_read(codec, 0x15, 0, |
7296 | snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0); | 7887 | AC_VERB_GET_PIN_SENSE, 0); |
7297 | present = snd_hda_codec_read(codec, 0x15, 0, | 7888 | spec->jack_present = (present & 0x80000000) != 0; |
7298 | AC_VERB_GET_PIN_SENSE, 0); | ||
7299 | spec->jack_present = (present & 0x80000000) != 0; | ||
7300 | spec->sense_updated = 1; | ||
7301 | } | ||
7302 | if (spec->jack_present) { | 7889 | if (spec->jack_present) { |
7303 | /* mute internal speaker */ | 7890 | /* mute internal speaker */ |
7304 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | 7891 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, |
7305 | 0x80, 0x80); | 7892 | HDA_AMP_MUTE, HDA_AMP_MUTE); |
7306 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
7307 | 0x80, 0x80); | ||
7308 | } else { | 7893 | } else { |
7309 | /* unmute internal speaker if necessary */ | 7894 | /* unmute internal speaker if necessary */ |
7310 | mute = snd_hda_codec_amp_read(codec, 0x15, 0, HDA_OUTPUT, 0); | 7895 | mute = snd_hda_codec_amp_read(codec, 0x15, 0, HDA_OUTPUT, 0); |
7311 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | 7896 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, |
7312 | 0x80, mute & 0x80); | 7897 | HDA_AMP_MUTE, mute); |
7313 | mute = snd_hda_codec_amp_read(codec, 0x15, 1, HDA_OUTPUT, 0); | ||
7314 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
7315 | 0x80, mute & 0x80); | ||
7316 | } | 7898 | } |
7317 | } | 7899 | } |
7318 | 7900 | ||
@@ -7322,37 +7904,27 @@ static void alc262_hippo_unsol_event(struct hda_codec *codec, | |||
7322 | { | 7904 | { |
7323 | if ((res >> 26) != ALC880_HP_EVENT) | 7905 | if ((res >> 26) != ALC880_HP_EVENT) |
7324 | return; | 7906 | return; |
7325 | alc262_hippo_automute(codec, 1); | 7907 | alc262_hippo_automute(codec); |
7326 | } | 7908 | } |
7327 | 7909 | ||
7328 | static void alc262_hippo1_automute(struct hda_codec *codec, int force) | 7910 | static void alc262_hippo1_automute(struct hda_codec *codec) |
7329 | { | 7911 | { |
7330 | struct alc_spec *spec = codec->spec; | ||
7331 | unsigned int mute; | 7912 | unsigned int mute; |
7913 | unsigned int present; | ||
7332 | 7914 | ||
7333 | if (force || !spec->sense_updated) { | 7915 | snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0); |
7334 | unsigned int present; | 7916 | present = snd_hda_codec_read(codec, 0x1b, 0, |
7335 | /* need to execute and sync at first */ | 7917 | AC_VERB_GET_PIN_SENSE, 0); |
7336 | snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0); | 7918 | present = (present & 0x80000000) != 0; |
7337 | present = snd_hda_codec_read(codec, 0x1b, 0, | 7919 | if (present) { |
7338 | AC_VERB_GET_PIN_SENSE, 0); | ||
7339 | spec->jack_present = (present & 0x80000000) != 0; | ||
7340 | spec->sense_updated = 1; | ||
7341 | } | ||
7342 | if (spec->jack_present) { | ||
7343 | /* mute internal speaker */ | 7920 | /* mute internal speaker */ |
7344 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | 7921 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, |
7345 | 0x80, 0x80); | 7922 | HDA_AMP_MUTE, HDA_AMP_MUTE); |
7346 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
7347 | 0x80, 0x80); | ||
7348 | } else { | 7923 | } else { |
7349 | /* unmute internal speaker if necessary */ | 7924 | /* unmute internal speaker if necessary */ |
7350 | mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0); | 7925 | mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0); |
7351 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | 7926 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, |
7352 | 0x80, mute & 0x80); | 7927 | HDA_AMP_MUTE, mute); |
7353 | mute = snd_hda_codec_amp_read(codec, 0x1b, 1, HDA_OUTPUT, 0); | ||
7354 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
7355 | 0x80, mute & 0x80); | ||
7356 | } | 7928 | } |
7357 | } | 7929 | } |
7358 | 7930 | ||
@@ -7362,7 +7934,7 @@ static void alc262_hippo1_unsol_event(struct hda_codec *codec, | |||
7362 | { | 7934 | { |
7363 | if ((res >> 26) != ALC880_HP_EVENT) | 7935 | if ((res >> 26) != ALC880_HP_EVENT) |
7364 | return; | 7936 | return; |
7365 | alc262_hippo1_automute(codec, 1); | 7937 | alc262_hippo1_automute(codec); |
7366 | } | 7938 | } |
7367 | 7939 | ||
7368 | /* | 7940 | /* |
@@ -7379,9 +7951,10 @@ static struct hda_verb alc262_fujitsu_unsol_verbs[] = { | |||
7379 | }; | 7951 | }; |
7380 | 7952 | ||
7381 | static struct hda_input_mux alc262_fujitsu_capture_source = { | 7953 | static struct hda_input_mux alc262_fujitsu_capture_source = { |
7382 | .num_items = 2, | 7954 | .num_items = 3, |
7383 | .items = { | 7955 | .items = { |
7384 | { "Mic", 0x0 }, | 7956 | { "Mic", 0x0 }, |
7957 | { "Int Mic", 0x1 }, | ||
7385 | { "CD", 0x4 }, | 7958 | { "CD", 0x4 }, |
7386 | }, | 7959 | }, |
7387 | }; | 7960 | }; |
@@ -7390,13 +7963,23 @@ static struct hda_input_mux alc262_HP_capture_source = { | |||
7390 | .num_items = 5, | 7963 | .num_items = 5, |
7391 | .items = { | 7964 | .items = { |
7392 | { "Mic", 0x0 }, | 7965 | { "Mic", 0x0 }, |
7393 | { "Front Mic", 0x3 }, | 7966 | { "Front Mic", 0x1 }, |
7394 | { "Line", 0x2 }, | 7967 | { "Line", 0x2 }, |
7395 | { "CD", 0x4 }, | 7968 | { "CD", 0x4 }, |
7396 | { "AUX IN", 0x6 }, | 7969 | { "AUX IN", 0x6 }, |
7397 | }, | 7970 | }, |
7398 | }; | 7971 | }; |
7399 | 7972 | ||
7973 | static struct hda_input_mux alc262_HP_D7000_capture_source = { | ||
7974 | .num_items = 4, | ||
7975 | .items = { | ||
7976 | { "Mic", 0x0 }, | ||
7977 | { "Front Mic", 0x2 }, | ||
7978 | { "Line", 0x1 }, | ||
7979 | { "CD", 0x4 }, | ||
7980 | }, | ||
7981 | }; | ||
7982 | |||
7400 | /* mute/unmute internal speaker according to the hp jack and mute state */ | 7983 | /* mute/unmute internal speaker according to the hp jack and mute state */ |
7401 | static void alc262_fujitsu_automute(struct hda_codec *codec, int force) | 7984 | static void alc262_fujitsu_automute(struct hda_codec *codec, int force) |
7402 | { | 7985 | { |
@@ -7414,18 +7997,13 @@ static void alc262_fujitsu_automute(struct hda_codec *codec, int force) | |||
7414 | } | 7997 | } |
7415 | if (spec->jack_present) { | 7998 | if (spec->jack_present) { |
7416 | /* mute internal speaker */ | 7999 | /* mute internal speaker */ |
7417 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | 8000 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, |
7418 | 0x80, 0x80); | 8001 | HDA_AMP_MUTE, HDA_AMP_MUTE); |
7419 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | ||
7420 | 0x80, 0x80); | ||
7421 | } else { | 8002 | } else { |
7422 | /* unmute internal speaker if necessary */ | 8003 | /* unmute internal speaker if necessary */ |
7423 | mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0); | 8004 | mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0); |
7424 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | 8005 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, |
7425 | 0x80, mute & 0x80); | 8006 | HDA_AMP_MUTE, mute); |
7426 | mute = snd_hda_codec_amp_read(codec, 0x14, 1, HDA_OUTPUT, 0); | ||
7427 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | ||
7428 | 0x80, mute & 0x80); | ||
7429 | } | 8007 | } |
7430 | } | 8008 | } |
7431 | 8009 | ||
@@ -7439,23 +8017,14 @@ static void alc262_fujitsu_unsol_event(struct hda_codec *codec, | |||
7439 | } | 8017 | } |
7440 | 8018 | ||
7441 | /* bind volumes of both NID 0x0c and 0x0d */ | 8019 | /* bind volumes of both NID 0x0c and 0x0d */ |
7442 | static int alc262_fujitsu_master_vol_put(struct snd_kcontrol *kcontrol, | 8020 | static struct hda_bind_ctls alc262_fujitsu_bind_master_vol = { |
7443 | struct snd_ctl_elem_value *ucontrol) | 8021 | .ops = &snd_hda_bind_vol, |
7444 | { | 8022 | .values = { |
7445 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 8023 | HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT), |
7446 | long *valp = ucontrol->value.integer.value; | 8024 | HDA_COMPOSE_AMP_VAL(0x0d, 3, 0, HDA_OUTPUT), |
7447 | int change; | 8025 | 0 |
7448 | 8026 | }, | |
7449 | change = snd_hda_codec_amp_update(codec, 0x0c, 0, HDA_OUTPUT, 0, | 8027 | }; |
7450 | 0x7f, valp[0] & 0x7f); | ||
7451 | change |= snd_hda_codec_amp_update(codec, 0x0c, 1, HDA_OUTPUT, 0, | ||
7452 | 0x7f, valp[1] & 0x7f); | ||
7453 | snd_hda_codec_amp_update(codec, 0x0d, 0, HDA_OUTPUT, 0, | ||
7454 | 0x7f, valp[0] & 0x7f); | ||
7455 | snd_hda_codec_amp_update(codec, 0x0d, 1, HDA_OUTPUT, 0, | ||
7456 | 0x7f, valp[1] & 0x7f); | ||
7457 | return change; | ||
7458 | } | ||
7459 | 8028 | ||
7460 | /* bind hp and internal speaker mute (with plug check) */ | 8029 | /* bind hp and internal speaker mute (with plug check) */ |
7461 | static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol, | 8030 | static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol, |
@@ -7466,24 +8035,18 @@ static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol, | |||
7466 | int change; | 8035 | int change; |
7467 | 8036 | ||
7468 | change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | 8037 | change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, |
7469 | 0x80, valp[0] ? 0 : 0x80); | 8038 | HDA_AMP_MUTE, |
8039 | valp[0] ? 0 : HDA_AMP_MUTE); | ||
7470 | change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | 8040 | change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, |
7471 | 0x80, valp[1] ? 0 : 0x80); | 8041 | HDA_AMP_MUTE, |
7472 | if (change || codec->in_resume) | 8042 | valp[1] ? 0 : HDA_AMP_MUTE); |
7473 | alc262_fujitsu_automute(codec, codec->in_resume); | 8043 | if (change) |
8044 | alc262_fujitsu_automute(codec, 0); | ||
7474 | return change; | 8045 | return change; |
7475 | } | 8046 | } |
7476 | 8047 | ||
7477 | static struct snd_kcontrol_new alc262_fujitsu_mixer[] = { | 8048 | static struct snd_kcontrol_new alc262_fujitsu_mixer[] = { |
7478 | { | 8049 | HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol), |
7479 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
7480 | .name = "Master Playback Volume", | ||
7481 | .info = snd_hda_mixer_amp_volume_info, | ||
7482 | .get = snd_hda_mixer_amp_volume_get, | ||
7483 | .put = alc262_fujitsu_master_vol_put, | ||
7484 | .tlv = { .c = snd_hda_mixer_amp_tlv }, | ||
7485 | .private_value = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT), | ||
7486 | }, | ||
7487 | { | 8050 | { |
7488 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 8051 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
7489 | .name = "Master Playback Switch", | 8052 | .name = "Master Playback Switch", |
@@ -7497,6 +8060,9 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = { | |||
7497 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 8060 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), |
7498 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 8061 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
7499 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 8062 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
8063 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), | ||
8064 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
8065 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
7500 | { } /* end */ | 8066 | { } /* end */ |
7501 | }; | 8067 | }; |
7502 | 8068 | ||
@@ -7611,17 +8177,17 @@ static struct hda_verb alc262_volume_init_verbs[] = { | |||
7611 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | 8177 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
7612 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 8178 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7613 | 8179 | ||
7614 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 8180 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
7615 | * mixer widget | 8181 | * mixer widget |
7616 | * Note: PASD motherboards uses the Line In 2 as the input for | 8182 | * Note: PASD motherboards uses the Line In 2 as the input for |
7617 | * front panel mic (mic 2) | 8183 | * front panel mic (mic 2) |
7618 | */ | 8184 | */ |
7619 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 8185 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
7620 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 8186 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
7621 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 8187 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
7622 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 8188 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
7623 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 8189 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
7624 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 8190 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
7625 | 8191 | ||
7626 | /* | 8192 | /* |
7627 | * Set up output mixers (0x0c - 0x0f) | 8193 | * Set up output mixers (0x0c - 0x0f) |
@@ -7672,19 +8238,19 @@ static struct hda_verb alc262_HP_BPC_init_verbs[] = { | |||
7672 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | 8238 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
7673 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 8239 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7674 | 8240 | ||
7675 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 8241 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
7676 | * mixer widget | 8242 | * mixer widget |
7677 | * Note: PASD motherboards uses the Line In 2 as the input for | 8243 | * Note: PASD motherboards uses the Line In 2 as the input for |
7678 | * front panel mic (mic 2) | 8244 | * front panel mic (mic 2) |
7679 | */ | 8245 | */ |
7680 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 8246 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
7681 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 8247 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
7682 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 8248 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
7683 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 8249 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
7684 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 8250 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
7685 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 8251 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
7686 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, | 8252 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, |
7687 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)}, | 8253 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, |
7688 | 8254 | ||
7689 | /* | 8255 | /* |
7690 | * Set up output mixers (0x0c - 0x0e) | 8256 | * Set up output mixers (0x0c - 0x0e) |
@@ -7759,20 +8325,20 @@ static struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = { | |||
7759 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | 8325 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
7760 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 8326 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
7761 | 8327 | ||
7762 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 8328 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
7763 | * mixer widget | 8329 | * mixer widget |
7764 | * Note: PASD motherboards uses the Line In 2 as the input for front | 8330 | * Note: PASD motherboards uses the Line In 2 as the input for front |
7765 | * panel mic (mic 2) | 8331 | * panel mic (mic 2) |
7766 | */ | 8332 | */ |
7767 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 8333 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
7768 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 8334 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
7769 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 8335 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
7770 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 8336 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
7771 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 8337 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
7772 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 8338 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
7773 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, | 8339 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, |
7774 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)}, | 8340 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, |
7775 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)}, | 8341 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, |
7776 | /* | 8342 | /* |
7777 | * Set up output mixers (0x0c - 0x0e) | 8343 | * Set up output mixers (0x0c - 0x0e) |
7778 | */ | 8344 | */ |
@@ -7842,6 +8408,10 @@ static struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = { | |||
7842 | { } | 8408 | { } |
7843 | }; | 8409 | }; |
7844 | 8410 | ||
8411 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
8412 | #define alc262_loopbacks alc880_loopbacks | ||
8413 | #endif | ||
8414 | |||
7845 | /* pcm configuration: identiacal with ALC880 */ | 8415 | /* pcm configuration: identiacal with ALC880 */ |
7846 | #define alc262_pcm_analog_playback alc880_pcm_analog_playback | 8416 | #define alc262_pcm_analog_playback alc880_pcm_analog_playback |
7847 | #define alc262_pcm_analog_capture alc880_pcm_analog_capture | 8417 | #define alc262_pcm_analog_capture alc880_pcm_analog_capture |
@@ -7884,6 +8454,10 @@ static int alc262_parse_auto_config(struct hda_codec *codec) | |||
7884 | spec->num_mux_defs = 1; | 8454 | spec->num_mux_defs = 1; |
7885 | spec->input_mux = &spec->private_imux; | 8455 | spec->input_mux = &spec->private_imux; |
7886 | 8456 | ||
8457 | err = alc_auto_add_mic_boost(codec); | ||
8458 | if (err < 0) | ||
8459 | return err; | ||
8460 | |||
7887 | return 1; | 8461 | return 1; |
7888 | } | 8462 | } |
7889 | 8463 | ||
@@ -7939,6 +8513,7 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = { | |||
7939 | SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1), | 8513 | SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1), |
7940 | SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8), | 8514 | SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8), |
7941 | SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31), | 8515 | SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31), |
8516 | SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD), | ||
7942 | SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD), | 8517 | SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD), |
7943 | SND_PCI_QUIRK(0x104d, 0x900e, "Sony ASSAMD", ALC262_SONY_ASSAMD), | 8518 | SND_PCI_QUIRK(0x104d, 0x900e, "Sony ASSAMD", ALC262_SONY_ASSAMD), |
7944 | SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD), | 8519 | SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD), |
@@ -7967,6 +8542,7 @@ static struct alc_config_preset alc262_presets[] = { | |||
7967 | .channel_mode = alc262_modes, | 8542 | .channel_mode = alc262_modes, |
7968 | .input_mux = &alc262_capture_source, | 8543 | .input_mux = &alc262_capture_source, |
7969 | .unsol_event = alc262_hippo_unsol_event, | 8544 | .unsol_event = alc262_hippo_unsol_event, |
8545 | .init_hook = alc262_hippo_automute, | ||
7970 | }, | 8546 | }, |
7971 | [ALC262_HIPPO_1] = { | 8547 | [ALC262_HIPPO_1] = { |
7972 | .mixers = { alc262_hippo1_mixer }, | 8548 | .mixers = { alc262_hippo1_mixer }, |
@@ -7979,10 +8555,12 @@ static struct alc_config_preset alc262_presets[] = { | |||
7979 | .channel_mode = alc262_modes, | 8555 | .channel_mode = alc262_modes, |
7980 | .input_mux = &alc262_capture_source, | 8556 | .input_mux = &alc262_capture_source, |
7981 | .unsol_event = alc262_hippo1_unsol_event, | 8557 | .unsol_event = alc262_hippo1_unsol_event, |
8558 | .init_hook = alc262_hippo1_automute, | ||
7982 | }, | 8559 | }, |
7983 | [ALC262_FUJITSU] = { | 8560 | [ALC262_FUJITSU] = { |
7984 | .mixers = { alc262_fujitsu_mixer }, | 8561 | .mixers = { alc262_fujitsu_mixer }, |
7985 | .init_verbs = { alc262_init_verbs, alc262_fujitsu_unsol_verbs }, | 8562 | .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs, |
8563 | alc262_fujitsu_unsol_verbs }, | ||
7986 | .num_dacs = ARRAY_SIZE(alc262_dac_nids), | 8564 | .num_dacs = ARRAY_SIZE(alc262_dac_nids), |
7987 | .dac_nids = alc262_dac_nids, | 8565 | .dac_nids = alc262_dac_nids, |
7988 | .hp_nid = 0x03, | 8566 | .hp_nid = 0x03, |
@@ -8010,7 +8588,7 @@ static struct alc_config_preset alc262_presets[] = { | |||
8010 | .hp_nid = 0x03, | 8588 | .hp_nid = 0x03, |
8011 | .num_channel_mode = ARRAY_SIZE(alc262_modes), | 8589 | .num_channel_mode = ARRAY_SIZE(alc262_modes), |
8012 | .channel_mode = alc262_modes, | 8590 | .channel_mode = alc262_modes, |
8013 | .input_mux = &alc262_HP_capture_source, | 8591 | .input_mux = &alc262_HP_D7000_capture_source, |
8014 | }, | 8592 | }, |
8015 | [ALC262_HP_BPC_D7000_WL] = { | 8593 | [ALC262_HP_BPC_D7000_WL] = { |
8016 | .mixers = { alc262_HP_BPC_WildWest_mixer, | 8594 | .mixers = { alc262_HP_BPC_WildWest_mixer, |
@@ -8021,7 +8599,7 @@ static struct alc_config_preset alc262_presets[] = { | |||
8021 | .hp_nid = 0x03, | 8599 | .hp_nid = 0x03, |
8022 | .num_channel_mode = ARRAY_SIZE(alc262_modes), | 8600 | .num_channel_mode = ARRAY_SIZE(alc262_modes), |
8023 | .channel_mode = alc262_modes, | 8601 | .channel_mode = alc262_modes, |
8024 | .input_mux = &alc262_HP_capture_source, | 8602 | .input_mux = &alc262_HP_D7000_capture_source, |
8025 | }, | 8603 | }, |
8026 | [ALC262_BENQ_ED8] = { | 8604 | [ALC262_BENQ_ED8] = { |
8027 | .mixers = { alc262_base_mixer }, | 8605 | .mixers = { alc262_base_mixer }, |
@@ -8043,6 +8621,7 @@ static struct alc_config_preset alc262_presets[] = { | |||
8043 | .channel_mode = alc262_modes, | 8621 | .channel_mode = alc262_modes, |
8044 | .input_mux = &alc262_capture_source, | 8622 | .input_mux = &alc262_capture_source, |
8045 | .unsol_event = alc262_hippo_unsol_event, | 8623 | .unsol_event = alc262_hippo_unsol_event, |
8624 | .init_hook = alc262_hippo_automute, | ||
8046 | }, | 8625 | }, |
8047 | [ALC262_BENQ_T31] = { | 8626 | [ALC262_BENQ_T31] = { |
8048 | .mixers = { alc262_benq_t31_mixer }, | 8627 | .mixers = { alc262_benq_t31_mixer }, |
@@ -8054,6 +8633,7 @@ static struct alc_config_preset alc262_presets[] = { | |||
8054 | .channel_mode = alc262_modes, | 8633 | .channel_mode = alc262_modes, |
8055 | .input_mux = &alc262_capture_source, | 8634 | .input_mux = &alc262_capture_source, |
8056 | .unsol_event = alc262_hippo_unsol_event, | 8635 | .unsol_event = alc262_hippo_unsol_event, |
8636 | .init_hook = alc262_hippo_automute, | ||
8057 | }, | 8637 | }, |
8058 | }; | 8638 | }; |
8059 | 8639 | ||
@@ -8139,6 +8719,10 @@ static int patch_alc262(struct hda_codec *codec) | |||
8139 | codec->patch_ops = alc_patch_ops; | 8719 | codec->patch_ops = alc_patch_ops; |
8140 | if (board_config == ALC262_AUTO) | 8720 | if (board_config == ALC262_AUTO) |
8141 | spec->init_hook = alc262_auto_init; | 8721 | spec->init_hook = alc262_auto_init; |
8722 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
8723 | if (!spec->loopback.amplist) | ||
8724 | spec->loopback.amplist = alc262_loopbacks; | ||
8725 | #endif | ||
8142 | 8726 | ||
8143 | return 0; | 8727 | return 0; |
8144 | } | 8728 | } |
@@ -8170,9 +8754,125 @@ static struct snd_kcontrol_new alc268_base_mixer[] = { | |||
8170 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), | 8754 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), |
8171 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT), | 8755 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT), |
8172 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), | 8756 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), |
8757 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
8758 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | ||
8759 | HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT), | ||
8760 | { } | ||
8761 | }; | ||
8762 | |||
8763 | static struct hda_verb alc268_eapd_verbs[] = { | ||
8764 | {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2}, | ||
8765 | {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2}, | ||
8766 | { } | ||
8767 | }; | ||
8768 | |||
8769 | /* Toshiba specific */ | ||
8770 | #define alc268_toshiba_automute alc262_hippo_automute | ||
8771 | |||
8772 | static struct hda_verb alc268_toshiba_verbs[] = { | ||
8773 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | ||
8774 | { } /* end */ | ||
8775 | }; | ||
8776 | |||
8777 | /* Acer specific */ | ||
8778 | /* bind volumes of both NID 0x02 and 0x03 */ | ||
8779 | static struct hda_bind_ctls alc268_acer_bind_master_vol = { | ||
8780 | .ops = &snd_hda_bind_vol, | ||
8781 | .values = { | ||
8782 | HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), | ||
8783 | HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT), | ||
8784 | 0 | ||
8785 | }, | ||
8786 | }; | ||
8787 | |||
8788 | /* mute/unmute internal speaker according to the hp jack and mute state */ | ||
8789 | static void alc268_acer_automute(struct hda_codec *codec, int force) | ||
8790 | { | ||
8791 | struct alc_spec *spec = codec->spec; | ||
8792 | unsigned int mute; | ||
8793 | |||
8794 | if (force || !spec->sense_updated) { | ||
8795 | unsigned int present; | ||
8796 | present = snd_hda_codec_read(codec, 0x14, 0, | ||
8797 | AC_VERB_GET_PIN_SENSE, 0); | ||
8798 | spec->jack_present = (present & 0x80000000) != 0; | ||
8799 | spec->sense_updated = 1; | ||
8800 | } | ||
8801 | if (spec->jack_present) | ||
8802 | mute = HDA_AMP_MUTE; /* mute internal speaker */ | ||
8803 | else /* unmute internal speaker if necessary */ | ||
8804 | mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0); | ||
8805 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, | ||
8806 | HDA_AMP_MUTE, mute); | ||
8807 | } | ||
8808 | |||
8809 | |||
8810 | /* bind hp and internal speaker mute (with plug check) */ | ||
8811 | static int alc268_acer_master_sw_put(struct snd_kcontrol *kcontrol, | ||
8812 | struct snd_ctl_elem_value *ucontrol) | ||
8813 | { | ||
8814 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
8815 | long *valp = ucontrol->value.integer.value; | ||
8816 | int change; | ||
8817 | |||
8818 | change = snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | ||
8819 | HDA_AMP_MUTE, | ||
8820 | valp[0] ? 0 : HDA_AMP_MUTE); | ||
8821 | change |= snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
8822 | HDA_AMP_MUTE, | ||
8823 | valp[1] ? 0 : HDA_AMP_MUTE); | ||
8824 | if (change) | ||
8825 | alc268_acer_automute(codec, 0); | ||
8826 | return change; | ||
8827 | } | ||
8828 | |||
8829 | static struct snd_kcontrol_new alc268_acer_mixer[] = { | ||
8830 | /* output mixer control */ | ||
8831 | HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol), | ||
8832 | { | ||
8833 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
8834 | .name = "Master Playback Switch", | ||
8835 | .info = snd_hda_mixer_amp_switch_info, | ||
8836 | .get = snd_hda_mixer_amp_switch_get, | ||
8837 | .put = alc268_acer_master_sw_put, | ||
8838 | .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), | ||
8839 | }, | ||
8840 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
8841 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT), | ||
8842 | HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT), | ||
8173 | { } | 8843 | { } |
8174 | }; | 8844 | }; |
8175 | 8845 | ||
8846 | static struct hda_verb alc268_acer_verbs[] = { | ||
8847 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
8848 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
8849 | |||
8850 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | ||
8851 | { } | ||
8852 | }; | ||
8853 | |||
8854 | /* unsolicited event for HP jack sensing */ | ||
8855 | static void alc268_toshiba_unsol_event(struct hda_codec *codec, | ||
8856 | unsigned int res) | ||
8857 | { | ||
8858 | if ((res >> 26) != ALC880_HP_EVENT) | ||
8859 | return; | ||
8860 | alc268_toshiba_automute(codec); | ||
8861 | } | ||
8862 | |||
8863 | static void alc268_acer_unsol_event(struct hda_codec *codec, | ||
8864 | unsigned int res) | ||
8865 | { | ||
8866 | if ((res >> 26) != ALC880_HP_EVENT) | ||
8867 | return; | ||
8868 | alc268_acer_automute(codec, 1); | ||
8869 | } | ||
8870 | |||
8871 | static void alc268_acer_init_hook(struct hda_codec *codec) | ||
8872 | { | ||
8873 | alc268_acer_automute(codec, 1); | ||
8874 | } | ||
8875 | |||
8176 | /* | 8876 | /* |
8177 | * generic initialization of ADC, input mixers and output mixers | 8877 | * generic initialization of ADC, input mixers and output mixers |
8178 | */ | 8878 | */ |
@@ -8282,14 +8982,16 @@ static int alc268_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
8282 | idx = ucontrol->value.enumerated.item[0]; | 8982 | idx = ucontrol->value.enumerated.item[0]; |
8283 | if (idx >= imux->num_items) | 8983 | if (idx >= imux->num_items) |
8284 | idx = imux->num_items - 1; | 8984 | idx = imux->num_items - 1; |
8285 | if (*cur_val == idx && !codec->in_resume) | 8985 | if (*cur_val == idx) |
8286 | return 0; | 8986 | return 0; |
8287 | for (i = 0; i < imux->num_items; i++) { | 8987 | for (i = 0; i < imux->num_items; i++) { |
8288 | unsigned int v = (i == idx) ? 0x7000 : 0x7080; | 8988 | unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE; |
8289 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 8989 | snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, |
8290 | v | (imux->items[i].index << 8)); | 8990 | imux->items[i].index, |
8291 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, | 8991 | HDA_AMP_MUTE, v); |
8292 | idx ); | 8992 | snd_hda_codec_write_cache(codec, nid, 0, |
8993 | AC_VERB_SET_CONNECT_SEL, | ||
8994 | idx ); | ||
8293 | } | 8995 | } |
8294 | *cur_val = idx; | 8996 | *cur_val = idx; |
8295 | return 1; | 8997 | return 1; |
@@ -8530,6 +9232,10 @@ static int alc268_parse_auto_config(struct hda_codec *codec) | |||
8530 | spec->num_mux_defs = 1; | 9232 | spec->num_mux_defs = 1; |
8531 | spec->input_mux = &spec->private_imux; | 9233 | spec->input_mux = &spec->private_imux; |
8532 | 9234 | ||
9235 | err = alc_auto_add_mic_boost(codec); | ||
9236 | if (err < 0) | ||
9237 | return err; | ||
9238 | |||
8533 | return 1; | 9239 | return 1; |
8534 | } | 9240 | } |
8535 | 9241 | ||
@@ -8551,11 +9257,19 @@ static void alc268_auto_init(struct hda_codec *codec) | |||
8551 | */ | 9257 | */ |
8552 | static const char *alc268_models[ALC268_MODEL_LAST] = { | 9258 | static const char *alc268_models[ALC268_MODEL_LAST] = { |
8553 | [ALC268_3ST] = "3stack", | 9259 | [ALC268_3ST] = "3stack", |
9260 | [ALC268_TOSHIBA] = "toshiba", | ||
9261 | [ALC268_ACER] = "acer", | ||
8554 | [ALC268_AUTO] = "auto", | 9262 | [ALC268_AUTO] = "auto", |
8555 | }; | 9263 | }; |
8556 | 9264 | ||
8557 | static struct snd_pci_quirk alc268_cfg_tbl[] = { | 9265 | static struct snd_pci_quirk alc268_cfg_tbl[] = { |
8558 | SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST), | 9266 | SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST), |
9267 | SND_PCI_QUIRK(0x1179, 0xff10, "TOSHIBA A205", ALC268_TOSHIBA), | ||
9268 | SND_PCI_QUIRK(0x1179, 0xff50, "TOSHIBA A305", ALC268_TOSHIBA), | ||
9269 | SND_PCI_QUIRK(0x103c, 0x30cc, "TOSHIBA", ALC268_TOSHIBA), | ||
9270 | SND_PCI_QUIRK(0x1025, 0x0126, "Acer", ALC268_ACER), | ||
9271 | SND_PCI_QUIRK(0x1025, 0x0130, "Acer Extensa 5210", ALC268_ACER), | ||
9272 | SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER), | ||
8559 | {} | 9273 | {} |
8560 | }; | 9274 | }; |
8561 | 9275 | ||
@@ -8573,6 +9287,37 @@ static struct alc_config_preset alc268_presets[] = { | |||
8573 | .channel_mode = alc268_modes, | 9287 | .channel_mode = alc268_modes, |
8574 | .input_mux = &alc268_capture_source, | 9288 | .input_mux = &alc268_capture_source, |
8575 | }, | 9289 | }, |
9290 | [ALC268_TOSHIBA] = { | ||
9291 | .mixers = { alc268_base_mixer, alc268_capture_alt_mixer }, | ||
9292 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, | ||
9293 | alc268_toshiba_verbs }, | ||
9294 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), | ||
9295 | .dac_nids = alc268_dac_nids, | ||
9296 | .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt), | ||
9297 | .adc_nids = alc268_adc_nids_alt, | ||
9298 | .hp_nid = 0x03, | ||
9299 | .num_channel_mode = ARRAY_SIZE(alc268_modes), | ||
9300 | .channel_mode = alc268_modes, | ||
9301 | .input_mux = &alc268_capture_source, | ||
9302 | .input_mux = &alc268_capture_source, | ||
9303 | .unsol_event = alc268_toshiba_unsol_event, | ||
9304 | .init_hook = alc268_toshiba_automute, | ||
9305 | }, | ||
9306 | [ALC268_ACER] = { | ||
9307 | .mixers = { alc268_acer_mixer, alc268_capture_alt_mixer }, | ||
9308 | .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, | ||
9309 | alc268_acer_verbs }, | ||
9310 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), | ||
9311 | .dac_nids = alc268_dac_nids, | ||
9312 | .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt), | ||
9313 | .adc_nids = alc268_adc_nids_alt, | ||
9314 | .hp_nid = 0x02, | ||
9315 | .num_channel_mode = ARRAY_SIZE(alc268_modes), | ||
9316 | .channel_mode = alc268_modes, | ||
9317 | .input_mux = &alc268_capture_source, | ||
9318 | .unsol_event = alc268_acer_unsol_event, | ||
9319 | .init_hook = alc268_acer_init_hook, | ||
9320 | }, | ||
8576 | }; | 9321 | }; |
8577 | 9322 | ||
8578 | static int patch_alc268(struct hda_codec *codec) | 9323 | static int patch_alc268(struct hda_codec *codec) |
@@ -9279,14 +10024,10 @@ static void alc861_toshiba_automute(struct hda_codec *codec) | |||
9279 | 10024 | ||
9280 | present = snd_hda_codec_read(codec, 0x0f, 0, | 10025 | present = snd_hda_codec_read(codec, 0x0f, 0, |
9281 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 10026 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
9282 | snd_hda_codec_amp_update(codec, 0x16, 0, HDA_INPUT, 0, | 10027 | snd_hda_codec_amp_stereo(codec, 0x16, HDA_INPUT, 0, |
9283 | 0x80, present ? 0x80 : 0); | 10028 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); |
9284 | snd_hda_codec_amp_update(codec, 0x16, 1, HDA_INPUT, 0, | 10029 | snd_hda_codec_amp_stereo(codec, 0x1a, HDA_INPUT, 3, |
9285 | 0x80, present ? 0x80 : 0); | 10030 | HDA_AMP_MUTE, present ? 0 : HDA_AMP_MUTE); |
9286 | snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_INPUT, 3, | ||
9287 | 0x80, present ? 0 : 0x80); | ||
9288 | snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_INPUT, 3, | ||
9289 | 0x80, present ? 0 : 0x80); | ||
9290 | } | 10031 | } |
9291 | 10032 | ||
9292 | static void alc861_toshiba_unsol_event(struct hda_codec *codec, | 10033 | static void alc861_toshiba_unsol_event(struct hda_codec *codec, |
@@ -9599,6 +10340,16 @@ static void alc861_auto_init(struct hda_codec *codec) | |||
9599 | alc861_auto_init_analog_input(codec); | 10340 | alc861_auto_init_analog_input(codec); |
9600 | } | 10341 | } |
9601 | 10342 | ||
10343 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
10344 | static struct hda_amp_list alc861_loopbacks[] = { | ||
10345 | { 0x15, HDA_INPUT, 0 }, | ||
10346 | { 0x15, HDA_INPUT, 1 }, | ||
10347 | { 0x15, HDA_INPUT, 2 }, | ||
10348 | { 0x15, HDA_INPUT, 3 }, | ||
10349 | { } /* end */ | ||
10350 | }; | ||
10351 | #endif | ||
10352 | |||
9602 | 10353 | ||
9603 | /* | 10354 | /* |
9604 | * configuration and preset | 10355 | * configuration and preset |
@@ -9796,6 +10547,10 @@ static int patch_alc861(struct hda_codec *codec) | |||
9796 | codec->patch_ops = alc_patch_ops; | 10547 | codec->patch_ops = alc_patch_ops; |
9797 | if (board_config == ALC861_AUTO) | 10548 | if (board_config == ALC861_AUTO) |
9798 | spec->init_hook = alc861_auto_init; | 10549 | spec->init_hook = alc861_auto_init; |
10550 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
10551 | if (!spec->loopback.amplist) | ||
10552 | spec->loopback.amplist = alc861_loopbacks; | ||
10553 | #endif | ||
9799 | 10554 | ||
9800 | return 0; | 10555 | return 0; |
9801 | } | 10556 | } |
@@ -9852,6 +10607,14 @@ static struct hda_input_mux alc861vd_dallas_capture_source = { | |||
9852 | }, | 10607 | }, |
9853 | }; | 10608 | }; |
9854 | 10609 | ||
10610 | static struct hda_input_mux alc861vd_hp_capture_source = { | ||
10611 | .num_items = 2, | ||
10612 | .items = { | ||
10613 | { "Front Mic", 0x0 }, | ||
10614 | { "ATAPI Mic", 0x1 }, | ||
10615 | }, | ||
10616 | }; | ||
10617 | |||
9855 | #define alc861vd_mux_enum_info alc_mux_enum_info | 10618 | #define alc861vd_mux_enum_info alc_mux_enum_info |
9856 | #define alc861vd_mux_enum_get alc_mux_enum_get | 10619 | #define alc861vd_mux_enum_get alc_mux_enum_get |
9857 | 10620 | ||
@@ -9870,12 +10633,13 @@ static int alc861vd_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
9870 | idx = ucontrol->value.enumerated.item[0]; | 10633 | idx = ucontrol->value.enumerated.item[0]; |
9871 | if (idx >= imux->num_items) | 10634 | if (idx >= imux->num_items) |
9872 | idx = imux->num_items - 1; | 10635 | idx = imux->num_items - 1; |
9873 | if (*cur_val == idx && !codec->in_resume) | 10636 | if (*cur_val == idx) |
9874 | return 0; | 10637 | return 0; |
9875 | for (i = 0; i < imux->num_items; i++) { | 10638 | for (i = 0; i < imux->num_items; i++) { |
9876 | unsigned int v = (i == idx) ? 0x7000 : 0x7080; | 10639 | unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE; |
9877 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 10640 | snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, |
9878 | v | (imux->items[i].index << 8)); | 10641 | imux->items[i].index, |
10642 | HDA_AMP_MUTE, v); | ||
9879 | } | 10643 | } |
9880 | *cur_val = idx; | 10644 | *cur_val = idx; |
9881 | return 1; | 10645 | return 1; |
@@ -10049,17 +10813,22 @@ static struct snd_kcontrol_new alc861vd_dallas_mixer[] = { | |||
10049 | HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 10813 | HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
10050 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x05, HDA_INPUT), | 10814 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x05, HDA_INPUT), |
10051 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x05, HDA_INPUT), | 10815 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x05, HDA_INPUT), |
10052 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), | 10816 | { } /* end */ |
10053 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), | 10817 | }; |
10054 | { | 10818 | |
10055 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 10819 | /* Pin assignment: Speaker=0x14, Line-out = 0x15, |
10056 | /* .name = "Capture Source", */ | 10820 | * Front Mic=0x18, ATAPI Mic = 0x19, |
10057 | .name = "Input Source", | 10821 | */ |
10058 | .count = 1, | 10822 | static struct snd_kcontrol_new alc861vd_hp_mixer[] = { |
10059 | .info = alc882_mux_enum_info, | 10823 | HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT), |
10060 | .get = alc882_mux_enum_get, | 10824 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), |
10061 | .put = alc882_mux_enum_put, | 10825 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), |
10062 | }, | 10826 | HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT), |
10827 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
10828 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
10829 | HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
10830 | HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
10831 | |||
10063 | { } /* end */ | 10832 | { } /* end */ |
10064 | }; | 10833 | }; |
10065 | 10834 | ||
@@ -10077,11 +10846,11 @@ static struct hda_verb alc861vd_volume_init_verbs[] = { | |||
10077 | * the analog-loopback mixer widget | 10846 | * the analog-loopback mixer widget |
10078 | */ | 10847 | */ |
10079 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 10848 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
10080 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 10849 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
10081 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 10850 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
10082 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 10851 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
10083 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 10852 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
10084 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 10853 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
10085 | 10854 | ||
10086 | /* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */ | 10855 | /* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */ |
10087 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 10856 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
@@ -10210,11 +10979,9 @@ static void alc861vd_lenovo_hp_automute(struct hda_codec *codec) | |||
10210 | 10979 | ||
10211 | present = snd_hda_codec_read(codec, 0x1b, 0, | 10980 | present = snd_hda_codec_read(codec, 0x1b, 0, |
10212 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 10981 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
10213 | bits = present ? 0x80 : 0; | 10982 | bits = present ? HDA_AMP_MUTE : 0; |
10214 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | 10983 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, |
10215 | 0x80, bits); | 10984 | HDA_AMP_MUTE, bits); |
10216 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
10217 | 0x80, bits); | ||
10218 | } | 10985 | } |
10219 | 10986 | ||
10220 | static void alc861vd_lenovo_mic_automute(struct hda_codec *codec) | 10987 | static void alc861vd_lenovo_mic_automute(struct hda_codec *codec) |
@@ -10224,11 +10991,9 @@ static void alc861vd_lenovo_mic_automute(struct hda_codec *codec) | |||
10224 | 10991 | ||
10225 | present = snd_hda_codec_read(codec, 0x18, 0, | 10992 | present = snd_hda_codec_read(codec, 0x18, 0, |
10226 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 10993 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
10227 | bits = present ? 0x80 : 0; | 10994 | bits = present ? HDA_AMP_MUTE : 0; |
10228 | snd_hda_codec_amp_update(codec, 0x0b, 0, HDA_INPUT, 1, | 10995 | snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, |
10229 | 0x80, bits); | 10996 | HDA_AMP_MUTE, bits); |
10230 | snd_hda_codec_amp_update(codec, 0x0b, 1, HDA_INPUT, 1, | ||
10231 | 0x80, bits); | ||
10232 | } | 10997 | } |
10233 | 10998 | ||
10234 | static void alc861vd_lenovo_automute(struct hda_codec *codec) | 10999 | static void alc861vd_lenovo_automute(struct hda_codec *codec) |
@@ -10302,10 +11067,8 @@ static void alc861vd_dallas_automute(struct hda_codec *codec) | |||
10302 | 11067 | ||
10303 | present = snd_hda_codec_read(codec, 0x15, 0, | 11068 | present = snd_hda_codec_read(codec, 0x15, 0, |
10304 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 11069 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
10305 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | 11070 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, |
10306 | 0x80, present ? 0x80 : 0); | 11071 | HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); |
10307 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
10308 | 0x80, present ? 0x80 : 0); | ||
10309 | } | 11072 | } |
10310 | 11073 | ||
10311 | static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int res) | 11074 | static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int res) |
@@ -10314,6 +11077,10 @@ static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int re | |||
10314 | alc861vd_dallas_automute(codec); | 11077 | alc861vd_dallas_automute(codec); |
10315 | } | 11078 | } |
10316 | 11079 | ||
11080 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
11081 | #define alc861vd_loopbacks alc880_loopbacks | ||
11082 | #endif | ||
11083 | |||
10317 | /* pcm configuration: identiacal with ALC880 */ | 11084 | /* pcm configuration: identiacal with ALC880 */ |
10318 | #define alc861vd_pcm_analog_playback alc880_pcm_analog_playback | 11085 | #define alc861vd_pcm_analog_playback alc880_pcm_analog_playback |
10319 | #define alc861vd_pcm_analog_capture alc880_pcm_analog_capture | 11086 | #define alc861vd_pcm_analog_capture alc880_pcm_analog_capture |
@@ -10325,12 +11092,13 @@ static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int re | |||
10325 | */ | 11092 | */ |
10326 | static const char *alc861vd_models[ALC861VD_MODEL_LAST] = { | 11093 | static const char *alc861vd_models[ALC861VD_MODEL_LAST] = { |
10327 | [ALC660VD_3ST] = "3stack-660", | 11094 | [ALC660VD_3ST] = "3stack-660", |
10328 | [ALC660VD_3ST_DIG]= "3stack-660-digout", | 11095 | [ALC660VD_3ST_DIG] = "3stack-660-digout", |
10329 | [ALC861VD_3ST] = "3stack", | 11096 | [ALC861VD_3ST] = "3stack", |
10330 | [ALC861VD_3ST_DIG] = "3stack-digout", | 11097 | [ALC861VD_3ST_DIG] = "3stack-digout", |
10331 | [ALC861VD_6ST_DIG] = "6stack-digout", | 11098 | [ALC861VD_6ST_DIG] = "6stack-digout", |
10332 | [ALC861VD_LENOVO] = "lenovo", | 11099 | [ALC861VD_LENOVO] = "lenovo", |
10333 | [ALC861VD_DALLAS] = "dallas", | 11100 | [ALC861VD_DALLAS] = "dallas", |
11101 | [ALC861VD_HP] = "hp", | ||
10334 | [ALC861VD_AUTO] = "auto", | 11102 | [ALC861VD_AUTO] = "auto", |
10335 | }; | 11103 | }; |
10336 | 11104 | ||
@@ -10341,11 +11109,15 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = { | |||
10341 | SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST), | 11109 | SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST), |
10342 | SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST), | 11110 | SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST), |
10343 | 11111 | ||
10344 | SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS), | 11112 | /*SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS),*/ /*lenovo*/ |
10345 | SND_PCI_QUIRK(0x1179, 0xff01, "DALLAS", ALC861VD_DALLAS), | 11113 | SND_PCI_QUIRK(0x1179, 0xff01, "DALLAS", ALC861VD_DALLAS), |
10346 | SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO), | 11114 | SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO), |
10347 | SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO), | 11115 | SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO), |
10348 | SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO), | 11116 | SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO), |
11117 | SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO), | ||
11118 | SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG), | ||
11119 | SND_PCI_QUIRK(0x1849, 0x0862, "ASRock K8NF6G-VSTA", ALC861VD_6ST_DIG), | ||
11120 | SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_HP), | ||
10349 | {} | 11121 | {} |
10350 | }; | 11122 | }; |
10351 | 11123 | ||
@@ -10435,7 +11207,21 @@ static struct alc_config_preset alc861vd_presets[] = { | |||
10435 | .input_mux = &alc861vd_dallas_capture_source, | 11207 | .input_mux = &alc861vd_dallas_capture_source, |
10436 | .unsol_event = alc861vd_dallas_unsol_event, | 11208 | .unsol_event = alc861vd_dallas_unsol_event, |
10437 | .init_hook = alc861vd_dallas_automute, | 11209 | .init_hook = alc861vd_dallas_automute, |
10438 | }, | 11210 | }, |
11211 | [ALC861VD_HP] = { | ||
11212 | .mixers = { alc861vd_hp_mixer }, | ||
11213 | .init_verbs = { alc861vd_dallas_verbs, alc861vd_eapd_verbs }, | ||
11214 | .num_dacs = ARRAY_SIZE(alc861vd_dac_nids), | ||
11215 | .dac_nids = alc861vd_dac_nids, | ||
11216 | .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids), | ||
11217 | .dig_out_nid = ALC861VD_DIGOUT_NID, | ||
11218 | .adc_nids = alc861vd_adc_nids, | ||
11219 | .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), | ||
11220 | .channel_mode = alc861vd_3stack_2ch_modes, | ||
11221 | .input_mux = &alc861vd_hp_capture_source, | ||
11222 | .unsol_event = alc861vd_dallas_unsol_event, | ||
11223 | .init_hook = alc861vd_dallas_automute, | ||
11224 | }, | ||
10439 | }; | 11225 | }; |
10440 | 11226 | ||
10441 | /* | 11227 | /* |
@@ -10668,6 +11454,10 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec) | |||
10668 | spec->num_mux_defs = 1; | 11454 | spec->num_mux_defs = 1; |
10669 | spec->input_mux = &spec->private_imux; | 11455 | spec->input_mux = &spec->private_imux; |
10670 | 11456 | ||
11457 | err = alc_auto_add_mic_boost(codec); | ||
11458 | if (err < 0) | ||
11459 | return err; | ||
11460 | |||
10671 | return 1; | 11461 | return 1; |
10672 | } | 11462 | } |
10673 | 11463 | ||
@@ -10735,6 +11525,10 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
10735 | 11525 | ||
10736 | if (board_config == ALC861VD_AUTO) | 11526 | if (board_config == ALC861VD_AUTO) |
10737 | spec->init_hook = alc861vd_auto_init; | 11527 | spec->init_hook = alc861vd_auto_init; |
11528 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
11529 | if (!spec->loopback.amplist) | ||
11530 | spec->loopback.amplist = alc861vd_loopbacks; | ||
11531 | #endif | ||
10738 | 11532 | ||
10739 | return 0; | 11533 | return 0; |
10740 | } | 11534 | } |
@@ -10782,6 +11576,15 @@ static struct hda_input_mux alc662_lenovo_101e_capture_source = { | |||
10782 | { "Line", 0x2 }, | 11576 | { "Line", 0x2 }, |
10783 | }, | 11577 | }, |
10784 | }; | 11578 | }; |
11579 | |||
11580 | static struct hda_input_mux alc662_eeepc_capture_source = { | ||
11581 | .num_items = 2, | ||
11582 | .items = { | ||
11583 | { "i-Mic", 0x1 }, | ||
11584 | { "e-Mic", 0x0 }, | ||
11585 | }, | ||
11586 | }; | ||
11587 | |||
10785 | #define alc662_mux_enum_info alc_mux_enum_info | 11588 | #define alc662_mux_enum_info alc_mux_enum_info |
10786 | #define alc662_mux_enum_get alc_mux_enum_get | 11589 | #define alc662_mux_enum_get alc_mux_enum_get |
10787 | 11590 | ||
@@ -10792,7 +11595,7 @@ static int alc662_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
10792 | struct alc_spec *spec = codec->spec; | 11595 | struct alc_spec *spec = codec->spec; |
10793 | const struct hda_input_mux *imux = spec->input_mux; | 11596 | const struct hda_input_mux *imux = spec->input_mux; |
10794 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 11597 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
10795 | static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 }; | 11598 | static hda_nid_t capture_mixers[2] = { 0x23, 0x22 }; |
10796 | hda_nid_t nid = capture_mixers[adc_idx]; | 11599 | hda_nid_t nid = capture_mixers[adc_idx]; |
10797 | unsigned int *cur_val = &spec->cur_mux[adc_idx]; | 11600 | unsigned int *cur_val = &spec->cur_mux[adc_idx]; |
10798 | unsigned int i, idx; | 11601 | unsigned int i, idx; |
@@ -10800,12 +11603,13 @@ static int alc662_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
10800 | idx = ucontrol->value.enumerated.item[0]; | 11603 | idx = ucontrol->value.enumerated.item[0]; |
10801 | if (idx >= imux->num_items) | 11604 | if (idx >= imux->num_items) |
10802 | idx = imux->num_items - 1; | 11605 | idx = imux->num_items - 1; |
10803 | if (*cur_val == idx && !codec->in_resume) | 11606 | if (*cur_val == idx) |
10804 | return 0; | 11607 | return 0; |
10805 | for (i = 0; i < imux->num_items; i++) { | 11608 | for (i = 0; i < imux->num_items; i++) { |
10806 | unsigned int v = (i == idx) ? 0x7000 : 0x7080; | 11609 | unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE; |
10807 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 11610 | snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, |
10808 | v | (imux->items[i].index << 8)); | 11611 | imux->items[i].index, |
11612 | HDA_AMP_MUTE, v); | ||
10809 | } | 11613 | } |
10810 | *cur_val = idx; | 11614 | *cur_val = idx; |
10811 | return 1; | 11615 | return 1; |
@@ -10997,6 +11801,22 @@ static struct snd_kcontrol_new alc662_lenovo_101e_mixer[] = { | |||
10997 | { } /* end */ | 11801 | { } /* end */ |
10998 | }; | 11802 | }; |
10999 | 11803 | ||
11804 | static struct snd_kcontrol_new alc662_eeepc_p701_mixer[] = { | ||
11805 | HDA_CODEC_MUTE("iSpeaker Playback Switch", 0x14, 0x0, HDA_OUTPUT), | ||
11806 | |||
11807 | HDA_CODEC_VOLUME("LineOut Playback Volume", 0x02, 0x0, HDA_OUTPUT), | ||
11808 | HDA_CODEC_MUTE("LineOut Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
11809 | |||
11810 | HDA_CODEC_VOLUME("e-Mic Boost", 0x18, 0, HDA_INPUT), | ||
11811 | HDA_CODEC_VOLUME("e-Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
11812 | HDA_CODEC_MUTE("e-Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
11813 | |||
11814 | HDA_CODEC_VOLUME("i-Mic Boost", 0x19, 0, HDA_INPUT), | ||
11815 | HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
11816 | HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
11817 | { } /* end */ | ||
11818 | }; | ||
11819 | |||
11000 | static struct snd_kcontrol_new alc662_chmode_mixer[] = { | 11820 | static struct snd_kcontrol_new alc662_chmode_mixer[] = { |
11001 | { | 11821 | { |
11002 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 11822 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -11014,18 +11834,18 @@ static struct hda_verb alc662_init_verbs[] = { | |||
11014 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | 11834 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
11015 | /* Front mixer: unmute input/output amp left and right (volume = 0) */ | 11835 | /* Front mixer: unmute input/output amp left and right (volume = 0) */ |
11016 | 11836 | ||
11017 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11837 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
11018 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 11838 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
11019 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 11839 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
11020 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 11840 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
11021 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 11841 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
11022 | 11842 | ||
11023 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11843 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
11024 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 11844 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
11025 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11845 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
11026 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 11846 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
11027 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11847 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
11028 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 11848 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
11029 | 11849 | ||
11030 | /* Front Pin: output 0 (0x0c) */ | 11850 | /* Front Pin: output 0 (0x0c) */ |
11031 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 11851 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
@@ -11062,13 +11882,24 @@ static struct hda_verb alc662_init_verbs[] = { | |||
11062 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 11882 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
11063 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 11883 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, |
11064 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 11884 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, |
11885 | |||
11886 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
11887 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
11888 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | ||
11889 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | ||
11065 | { } | 11890 | { } |
11066 | }; | 11891 | }; |
11067 | 11892 | ||
11068 | static struct hda_verb alc662_sue_init_verbs[] = { | 11893 | static struct hda_verb alc662_sue_init_verbs[] = { |
11069 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT}, | 11894 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT}, |
11070 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT}, | 11895 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT}, |
11071 | {} | 11896 | {} |
11897 | }; | ||
11898 | |||
11899 | static struct hda_verb alc662_eeepc_sue_init_verbs[] = { | ||
11900 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, | ||
11901 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, | ||
11902 | {} | ||
11072 | }; | 11903 | }; |
11073 | 11904 | ||
11074 | /* | 11905 | /* |
@@ -11087,11 +11918,11 @@ static struct hda_verb alc662_auto_init_verbs[] = { | |||
11087 | * panel mic (mic 2) | 11918 | * panel mic (mic 2) |
11088 | */ | 11919 | */ |
11089 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ | 11920 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
11090 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11921 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
11091 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 11922 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
11092 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 11923 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
11093 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 11924 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
11094 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 11925 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
11095 | 11926 | ||
11096 | /* | 11927 | /* |
11097 | * Set up output mixers (0x0c - 0x0f) | 11928 | * Set up output mixers (0x0c - 0x0f) |
@@ -11103,23 +11934,19 @@ static struct hda_verb alc662_auto_init_verbs[] = { | |||
11103 | 11934 | ||
11104 | /* set up input amps for analog loopback */ | 11935 | /* set up input amps for analog loopback */ |
11105 | /* Amp Indices: DAC = 0, mixer = 1 */ | 11936 | /* Amp Indices: DAC = 0, mixer = 1 */ |
11106 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11937 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
11107 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 11938 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
11108 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11939 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
11109 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 11940 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
11110 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11941 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
11111 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 11942 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
11112 | 11943 | ||
11113 | 11944 | ||
11114 | /* FIXME: use matrix-type input source selection */ | 11945 | /* FIXME: use matrix-type input source selection */ |
11115 | /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ | 11946 | /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ |
11116 | /* Input mixer */ | 11947 | /* Input mixer */ |
11117 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11948 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
11118 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 11949 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
11119 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | ||
11120 | /*{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},*/ | ||
11121 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | ||
11122 | |||
11123 | { } | 11950 | { } |
11124 | }; | 11951 | }; |
11125 | 11952 | ||
@@ -11150,11 +11977,9 @@ static void alc662_lenovo_101e_ispeaker_automute(struct hda_codec *codec) | |||
11150 | 11977 | ||
11151 | present = snd_hda_codec_read(codec, 0x14, 0, | 11978 | present = snd_hda_codec_read(codec, 0x14, 0, |
11152 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 11979 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
11153 | bits = present ? 0x80 : 0; | 11980 | bits = present ? HDA_AMP_MUTE : 0; |
11154 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | 11981 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, |
11155 | 0x80, bits); | 11982 | HDA_AMP_MUTE, bits); |
11156 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | ||
11157 | 0x80, bits); | ||
11158 | } | 11983 | } |
11159 | 11984 | ||
11160 | static void alc662_lenovo_101e_all_automute(struct hda_codec *codec) | 11985 | static void alc662_lenovo_101e_all_automute(struct hda_codec *codec) |
@@ -11164,15 +11989,11 @@ static void alc662_lenovo_101e_all_automute(struct hda_codec *codec) | |||
11164 | 11989 | ||
11165 | present = snd_hda_codec_read(codec, 0x1b, 0, | 11990 | present = snd_hda_codec_read(codec, 0x1b, 0, |
11166 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | 11991 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; |
11167 | bits = present ? 0x80 : 0; | 11992 | bits = present ? HDA_AMP_MUTE : 0; |
11168 | snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0, | 11993 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, |
11169 | 0x80, bits); | 11994 | HDA_AMP_MUTE, bits); |
11170 | snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0, | 11995 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, |
11171 | 0x80, bits); | 11996 | HDA_AMP_MUTE, bits); |
11172 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | ||
11173 | 0x80, bits); | ||
11174 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
11175 | 0x80, bits); | ||
11176 | } | 11997 | } |
11177 | 11998 | ||
11178 | static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec, | 11999 | static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec, |
@@ -11184,6 +12005,43 @@ static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec, | |||
11184 | alc662_lenovo_101e_ispeaker_automute(codec); | 12005 | alc662_lenovo_101e_ispeaker_automute(codec); |
11185 | } | 12006 | } |
11186 | 12007 | ||
12008 | static void alc662_eeepc_mic_automute(struct hda_codec *codec) | ||
12009 | { | ||
12010 | unsigned int present; | ||
12011 | |||
12012 | present = snd_hda_codec_read(codec, 0x18, 0, | ||
12013 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
12014 | snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
12015 | 0x7000 | (0x00 << 8) | (present ? 0 : 0x80)); | ||
12016 | snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
12017 | 0x7000 | (0x00 << 8) | (present ? 0 : 0x80)); | ||
12018 | snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
12019 | 0x7000 | (0x01 << 8) | (present ? 0x80 : 0)); | ||
12020 | snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
12021 | 0x7000 | (0x01 << 8) | (present ? 0x80 : 0)); | ||
12022 | } | ||
12023 | |||
12024 | /* unsolicited event for HP jack sensing */ | ||
12025 | static void alc662_eeepc_unsol_event(struct hda_codec *codec, | ||
12026 | unsigned int res) | ||
12027 | { | ||
12028 | if ((res >> 26) == ALC880_HP_EVENT) | ||
12029 | alc262_hippo1_automute( codec ); | ||
12030 | |||
12031 | if ((res >> 26) == ALC880_MIC_EVENT) | ||
12032 | alc662_eeepc_mic_automute(codec); | ||
12033 | } | ||
12034 | |||
12035 | static void alc662_eeepc_inithook(struct hda_codec *codec) | ||
12036 | { | ||
12037 | alc262_hippo1_automute( codec ); | ||
12038 | alc662_eeepc_mic_automute(codec); | ||
12039 | } | ||
12040 | |||
12041 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
12042 | #define alc662_loopbacks alc880_loopbacks | ||
12043 | #endif | ||
12044 | |||
11187 | 12045 | ||
11188 | /* pcm configuration: identiacal with ALC880 */ | 12046 | /* pcm configuration: identiacal with ALC880 */ |
11189 | #define alc662_pcm_analog_playback alc880_pcm_analog_playback | 12047 | #define alc662_pcm_analog_playback alc880_pcm_analog_playback |
@@ -11205,12 +12063,13 @@ static const char *alc662_models[ALC662_MODEL_LAST] = { | |||
11205 | 12063 | ||
11206 | static struct snd_pci_quirk alc662_cfg_tbl[] = { | 12064 | static struct snd_pci_quirk alc662_cfg_tbl[] = { |
11207 | SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E), | 12065 | SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E), |
12066 | SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701), | ||
11208 | {} | 12067 | {} |
11209 | }; | 12068 | }; |
11210 | 12069 | ||
11211 | static struct alc_config_preset alc662_presets[] = { | 12070 | static struct alc_config_preset alc662_presets[] = { |
11212 | [ALC662_3ST_2ch_DIG] = { | 12071 | [ALC662_3ST_2ch_DIG] = { |
11213 | .mixers = { alc662_3ST_2ch_mixer }, | 12072 | .mixers = { alc662_3ST_2ch_mixer, alc662_capture_mixer }, |
11214 | .init_verbs = { alc662_init_verbs }, | 12073 | .init_verbs = { alc662_init_verbs }, |
11215 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 12074 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
11216 | .dac_nids = alc662_dac_nids, | 12075 | .dac_nids = alc662_dac_nids, |
@@ -11223,7 +12082,8 @@ static struct alc_config_preset alc662_presets[] = { | |||
11223 | .input_mux = &alc662_capture_source, | 12082 | .input_mux = &alc662_capture_source, |
11224 | }, | 12083 | }, |
11225 | [ALC662_3ST_6ch_DIG] = { | 12084 | [ALC662_3ST_6ch_DIG] = { |
11226 | .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer }, | 12085 | .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer, |
12086 | alc662_capture_mixer }, | ||
11227 | .init_verbs = { alc662_init_verbs }, | 12087 | .init_verbs = { alc662_init_verbs }, |
11228 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 12088 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
11229 | .dac_nids = alc662_dac_nids, | 12089 | .dac_nids = alc662_dac_nids, |
@@ -11237,7 +12097,8 @@ static struct alc_config_preset alc662_presets[] = { | |||
11237 | .input_mux = &alc662_capture_source, | 12097 | .input_mux = &alc662_capture_source, |
11238 | }, | 12098 | }, |
11239 | [ALC662_3ST_6ch] = { | 12099 | [ALC662_3ST_6ch] = { |
11240 | .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer }, | 12100 | .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer, |
12101 | alc662_capture_mixer }, | ||
11241 | .init_verbs = { alc662_init_verbs }, | 12102 | .init_verbs = { alc662_init_verbs }, |
11242 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 12103 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
11243 | .dac_nids = alc662_dac_nids, | 12104 | .dac_nids = alc662_dac_nids, |
@@ -11249,7 +12110,8 @@ static struct alc_config_preset alc662_presets[] = { | |||
11249 | .input_mux = &alc662_capture_source, | 12110 | .input_mux = &alc662_capture_source, |
11250 | }, | 12111 | }, |
11251 | [ALC662_5ST_DIG] = { | 12112 | [ALC662_5ST_DIG] = { |
11252 | .mixers = { alc662_base_mixer, alc662_chmode_mixer }, | 12113 | .mixers = { alc662_base_mixer, alc662_chmode_mixer, |
12114 | alc662_capture_mixer }, | ||
11253 | .init_verbs = { alc662_init_verbs }, | 12115 | .init_verbs = { alc662_init_verbs }, |
11254 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 12116 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
11255 | .dac_nids = alc662_dac_nids, | 12117 | .dac_nids = alc662_dac_nids, |
@@ -11262,7 +12124,7 @@ static struct alc_config_preset alc662_presets[] = { | |||
11262 | .input_mux = &alc662_capture_source, | 12124 | .input_mux = &alc662_capture_source, |
11263 | }, | 12125 | }, |
11264 | [ALC662_LENOVO_101E] = { | 12126 | [ALC662_LENOVO_101E] = { |
11265 | .mixers = { alc662_lenovo_101e_mixer }, | 12127 | .mixers = { alc662_lenovo_101e_mixer, alc662_capture_mixer }, |
11266 | .init_verbs = { alc662_init_verbs, alc662_sue_init_verbs }, | 12128 | .init_verbs = { alc662_init_verbs, alc662_sue_init_verbs }, |
11267 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | 12129 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), |
11268 | .dac_nids = alc662_dac_nids, | 12130 | .dac_nids = alc662_dac_nids, |
@@ -11274,6 +12136,20 @@ static struct alc_config_preset alc662_presets[] = { | |||
11274 | .unsol_event = alc662_lenovo_101e_unsol_event, | 12136 | .unsol_event = alc662_lenovo_101e_unsol_event, |
11275 | .init_hook = alc662_lenovo_101e_all_automute, | 12137 | .init_hook = alc662_lenovo_101e_all_automute, |
11276 | }, | 12138 | }, |
12139 | [ALC662_ASUS_EEEPC_P701] = { | ||
12140 | .mixers = { alc662_eeepc_p701_mixer, alc662_capture_mixer }, | ||
12141 | .init_verbs = { alc662_init_verbs, | ||
12142 | alc662_eeepc_sue_init_verbs }, | ||
12143 | .num_dacs = ARRAY_SIZE(alc662_dac_nids), | ||
12144 | .dac_nids = alc662_dac_nids, | ||
12145 | .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids), | ||
12146 | .adc_nids = alc662_adc_nids, | ||
12147 | .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes), | ||
12148 | .channel_mode = alc662_3ST_2ch_modes, | ||
12149 | .input_mux = &alc662_eeepc_capture_source, | ||
12150 | .unsol_event = alc662_eeepc_unsol_event, | ||
12151 | .init_hook = alc662_eeepc_inithook, | ||
12152 | }, | ||
11277 | 12153 | ||
11278 | }; | 12154 | }; |
11279 | 12155 | ||
@@ -11296,7 +12172,7 @@ static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
11296 | for (i = 0; i < cfg->line_outs; i++) { | 12172 | for (i = 0; i < cfg->line_outs; i++) { |
11297 | if (!spec->multiout.dac_nids[i]) | 12173 | if (!spec->multiout.dac_nids[i]) |
11298 | continue; | 12174 | continue; |
11299 | nid = alc880_idx_to_mixer(i); | 12175 | nid = alc880_idx_to_dac(i); |
11300 | if (i == 2) { | 12176 | if (i == 2) { |
11301 | /* Center/LFE */ | 12177 | /* Center/LFE */ |
11302 | err = add_control(spec, ALC_CTL_WIDGET_VOL, | 12178 | err = add_control(spec, ALC_CTL_WIDGET_VOL, |
@@ -11586,6 +12462,10 @@ static int patch_alc662(struct hda_codec *codec) | |||
11586 | codec->patch_ops = alc_patch_ops; | 12462 | codec->patch_ops = alc_patch_ops; |
11587 | if (board_config == ALC662_AUTO) | 12463 | if (board_config == ALC662_AUTO) |
11588 | spec->init_hook = alc662_auto_init; | 12464 | spec->init_hook = alc662_auto_init; |
12465 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
12466 | if (!spec->loopback.amplist) | ||
12467 | spec->loopback.amplist = alc662_loopbacks; | ||
12468 | #endif | ||
11589 | 12469 | ||
11590 | return 0; | 12470 | return 0; |
11591 | } | 12471 | } |
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c index 6d2ecc38905c..2a4b9609aa5c 100644 --- a/sound/pci/hda/patch_si3054.c +++ b/sound/pci/hda/patch_si3054.c | |||
@@ -78,6 +78,8 @@ | |||
78 | /* si3054 codec registers (nodes) access macros */ | 78 | /* si3054 codec registers (nodes) access macros */ |
79 | #define GET_REG(codec,reg) (snd_hda_codec_read(codec,reg,0,SI3054_VERB_READ_NODE,0)) | 79 | #define GET_REG(codec,reg) (snd_hda_codec_read(codec,reg,0,SI3054_VERB_READ_NODE,0)) |
80 | #define SET_REG(codec,reg,val) (snd_hda_codec_write(codec,reg,0,SI3054_VERB_WRITE_NODE,val)) | 80 | #define SET_REG(codec,reg,val) (snd_hda_codec_write(codec,reg,0,SI3054_VERB_WRITE_NODE,val)) |
81 | #define SET_REG_CACHE(codec,reg,val) \ | ||
82 | snd_hda_codec_write_cache(codec,reg,0,SI3054_VERB_WRITE_NODE,val) | ||
81 | 83 | ||
82 | 84 | ||
83 | struct si3054_spec { | 85 | struct si3054_spec { |
@@ -94,15 +96,7 @@ struct si3054_spec { | |||
94 | #define PRIVATE_REG(val) ((val>>16)&0xffff) | 96 | #define PRIVATE_REG(val) ((val>>16)&0xffff) |
95 | #define PRIVATE_MASK(val) (val&0xffff) | 97 | #define PRIVATE_MASK(val) (val&0xffff) |
96 | 98 | ||
97 | static int si3054_switch_info(struct snd_kcontrol *kcontrol, | 99 | #define si3054_switch_info snd_ctl_boolean_mono_info |
98 | struct snd_ctl_elem_info *uinfo) | ||
99 | { | ||
100 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
101 | uinfo->count = 1; | ||
102 | uinfo->value.integer.min = 0; | ||
103 | uinfo->value.integer.max = 1; | ||
104 | return 0; | ||
105 | } | ||
106 | 100 | ||
107 | static int si3054_switch_get(struct snd_kcontrol *kcontrol, | 101 | static int si3054_switch_get(struct snd_kcontrol *kcontrol, |
108 | struct snd_ctl_elem_value *uvalue) | 102 | struct snd_ctl_elem_value *uvalue) |
@@ -121,9 +115,9 @@ static int si3054_switch_put(struct snd_kcontrol *kcontrol, | |||
121 | u16 reg = PRIVATE_REG(kcontrol->private_value); | 115 | u16 reg = PRIVATE_REG(kcontrol->private_value); |
122 | u16 mask = PRIVATE_MASK(kcontrol->private_value); | 116 | u16 mask = PRIVATE_MASK(kcontrol->private_value); |
123 | if (uvalue->value.integer.value[0]) | 117 | if (uvalue->value.integer.value[0]) |
124 | SET_REG(codec, reg, (GET_REG(codec, reg)) | mask); | 118 | SET_REG_CACHE(codec, reg, (GET_REG(codec, reg)) | mask); |
125 | else | 119 | else |
126 | SET_REG(codec, reg, (GET_REG(codec, reg)) & ~mask); | 120 | SET_REG_CACHE(codec, reg, (GET_REG(codec, reg)) & ~mask); |
127 | return 0; | 121 | return 0; |
128 | } | 122 | } |
129 | 123 | ||
@@ -275,10 +269,6 @@ static struct hda_codec_ops si3054_patch_ops = { | |||
275 | .build_pcms = si3054_build_pcms, | 269 | .build_pcms = si3054_build_pcms, |
276 | .init = si3054_init, | 270 | .init = si3054_init, |
277 | .free = si3054_free, | 271 | .free = si3054_free, |
278 | #ifdef CONFIG_PM | ||
279 | //.suspend = si3054_suspend, | ||
280 | .resume = si3054_init, | ||
281 | #endif | ||
282 | }; | 272 | }; |
283 | 273 | ||
284 | static int patch_si3054(struct hda_codec *codec) | 274 | static int patch_si3054(struct hda_codec *codec) |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 3f25de72966b..bf950195107c 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -39,12 +39,25 @@ | |||
39 | 39 | ||
40 | enum { | 40 | enum { |
41 | STAC_REF, | 41 | STAC_REF, |
42 | STAC_9200_DELL_D21, | ||
43 | STAC_9200_DELL_D22, | ||
44 | STAC_9200_DELL_D23, | ||
45 | STAC_9200_DELL_M21, | ||
46 | STAC_9200_DELL_M22, | ||
47 | STAC_9200_DELL_M23, | ||
48 | STAC_9200_DELL_M24, | ||
49 | STAC_9200_DELL_M25, | ||
50 | STAC_9200_DELL_M26, | ||
51 | STAC_9200_DELL_M27, | ||
52 | STAC_9200_GATEWAY, | ||
42 | STAC_9200_MODELS | 53 | STAC_9200_MODELS |
43 | }; | 54 | }; |
44 | 55 | ||
45 | enum { | 56 | enum { |
46 | STAC_9205_REF, | 57 | STAC_9205_REF, |
47 | STAC_M43xx, | 58 | STAC_9205_DELL_M42, |
59 | STAC_9205_DELL_M43, | ||
60 | STAC_9205_DELL_M44, | ||
48 | STAC_9205_MODELS | 61 | STAC_9205_MODELS |
49 | }; | 62 | }; |
50 | 63 | ||
@@ -60,19 +73,22 @@ enum { | |||
60 | STAC_D945_REF, | 73 | STAC_D945_REF, |
61 | STAC_D945GTP3, | 74 | STAC_D945GTP3, |
62 | STAC_D945GTP5, | 75 | STAC_D945GTP5, |
63 | STAC_922X_DELL, | ||
64 | STAC_INTEL_MAC_V1, | 76 | STAC_INTEL_MAC_V1, |
65 | STAC_INTEL_MAC_V2, | 77 | STAC_INTEL_MAC_V2, |
66 | STAC_INTEL_MAC_V3, | 78 | STAC_INTEL_MAC_V3, |
67 | STAC_INTEL_MAC_V4, | 79 | STAC_INTEL_MAC_V4, |
68 | STAC_INTEL_MAC_V5, | 80 | STAC_INTEL_MAC_V5, |
69 | /* for backward compitability */ | 81 | /* for backward compatibility */ |
70 | STAC_MACMINI, | 82 | STAC_MACMINI, |
71 | STAC_MACBOOK, | 83 | STAC_MACBOOK, |
72 | STAC_MACBOOK_PRO_V1, | 84 | STAC_MACBOOK_PRO_V1, |
73 | STAC_MACBOOK_PRO_V2, | 85 | STAC_MACBOOK_PRO_V2, |
74 | STAC_IMAC_INTEL, | 86 | STAC_IMAC_INTEL, |
75 | STAC_IMAC_INTEL_20, | 87 | STAC_IMAC_INTEL_20, |
88 | STAC_922X_DELL_D81, | ||
89 | STAC_922X_DELL_D82, | ||
90 | STAC_922X_DELL_M81, | ||
91 | STAC_922X_DELL_M82, | ||
76 | STAC_922X_MODELS | 92 | STAC_922X_MODELS |
77 | }; | 93 | }; |
78 | 94 | ||
@@ -80,6 +96,7 @@ enum { | |||
80 | STAC_D965_REF, | 96 | STAC_D965_REF, |
81 | STAC_D965_3ST, | 97 | STAC_D965_3ST, |
82 | STAC_D965_5ST, | 98 | STAC_D965_5ST, |
99 | STAC_DELL_3ST, | ||
83 | STAC_927X_MODELS | 100 | STAC_927X_MODELS |
84 | }; | 101 | }; |
85 | 102 | ||
@@ -95,6 +112,8 @@ struct sigmatel_spec { | |||
95 | unsigned int hp_detect: 1; | 112 | unsigned int hp_detect: 1; |
96 | unsigned int gpio_mute: 1; | 113 | unsigned int gpio_mute: 1; |
97 | 114 | ||
115 | unsigned int gpio_mask, gpio_data; | ||
116 | |||
98 | /* playback */ | 117 | /* playback */ |
99 | struct hda_multi_out multiout; | 118 | struct hda_multi_out multiout; |
100 | hda_nid_t dac_nids[5]; | 119 | hda_nid_t dac_nids[5]; |
@@ -127,6 +146,8 @@ struct sigmatel_spec { | |||
127 | 146 | ||
128 | /* i/o switches */ | 147 | /* i/o switches */ |
129 | unsigned int io_switch[2]; | 148 | unsigned int io_switch[2]; |
149 | unsigned int clfe_swap; | ||
150 | unsigned int aloopback; | ||
130 | 151 | ||
131 | struct hda_pcm pcm_rec[2]; /* PCM information */ | 152 | struct hda_pcm pcm_rec[2]; /* PCM information */ |
132 | 153 | ||
@@ -162,8 +183,9 @@ static hda_nid_t stac925x_dac_nids[1] = { | |||
162 | 0x02, | 183 | 0x02, |
163 | }; | 184 | }; |
164 | 185 | ||
165 | static hda_nid_t stac925x_dmic_nids[1] = { | 186 | #define STAC925X_NUM_DMICS 1 |
166 | 0x15, | 187 | static hda_nid_t stac925x_dmic_nids[STAC925X_NUM_DMICS + 1] = { |
188 | 0x15, 0 | ||
167 | }; | 189 | }; |
168 | 190 | ||
169 | static hda_nid_t stac922x_adc_nids[2] = { | 191 | static hda_nid_t stac922x_adc_nids[2] = { |
@@ -190,8 +212,9 @@ static hda_nid_t stac9205_mux_nids[2] = { | |||
190 | 0x19, 0x1a | 212 | 0x19, 0x1a |
191 | }; | 213 | }; |
192 | 214 | ||
193 | static hda_nid_t stac9205_dmic_nids[2] = { | 215 | #define STAC9205_NUM_DMICS 2 |
194 | 0x17, 0x18, | 216 | static hda_nid_t stac9205_dmic_nids[STAC9205_NUM_DMICS + 1] = { |
217 | 0x17, 0x18, 0 | ||
195 | }; | 218 | }; |
196 | 219 | ||
197 | static hda_nid_t stac9200_pin_nids[8] = { | 220 | static hda_nid_t stac9200_pin_nids[8] = { |
@@ -276,12 +299,97 @@ static int stac92xx_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
276 | spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]); | 299 | spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]); |
277 | } | 300 | } |
278 | 301 | ||
302 | #define stac92xx_aloopback_info snd_ctl_boolean_mono_info | ||
303 | |||
304 | static int stac92xx_aloopback_get(struct snd_kcontrol *kcontrol, | ||
305 | struct snd_ctl_elem_value *ucontrol) | ||
306 | { | ||
307 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
308 | struct sigmatel_spec *spec = codec->spec; | ||
309 | |||
310 | ucontrol->value.integer.value[0] = spec->aloopback; | ||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | static int stac92xx_aloopback_put(struct snd_kcontrol *kcontrol, | ||
315 | struct snd_ctl_elem_value *ucontrol) | ||
316 | { | ||
317 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
318 | struct sigmatel_spec *spec = codec->spec; | ||
319 | unsigned int dac_mode; | ||
320 | |||
321 | if (spec->aloopback == ucontrol->value.integer.value[0]) | ||
322 | return 0; | ||
323 | |||
324 | spec->aloopback = ucontrol->value.integer.value[0]; | ||
325 | |||
326 | |||
327 | dac_mode = snd_hda_codec_read(codec, codec->afg, 0, | ||
328 | kcontrol->private_value & 0xFFFF, 0x0); | ||
329 | |||
330 | if (spec->aloopback) { | ||
331 | snd_hda_power_up(codec); | ||
332 | dac_mode |= 0x40; | ||
333 | } else { | ||
334 | snd_hda_power_down(codec); | ||
335 | dac_mode &= ~0x40; | ||
336 | } | ||
337 | |||
338 | snd_hda_codec_write_cache(codec, codec->afg, 0, | ||
339 | kcontrol->private_value >> 16, dac_mode); | ||
340 | |||
341 | return 1; | ||
342 | } | ||
343 | |||
344 | static int stac92xx_volknob_info(struct snd_kcontrol *kcontrol, | ||
345 | struct snd_ctl_elem_info *uinfo) | ||
346 | { | ||
347 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
348 | uinfo->count = 1; | ||
349 | uinfo->value.integer.min = 0; | ||
350 | uinfo->value.integer.max = 127; | ||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | static int stac92xx_volknob_get(struct snd_kcontrol *kcontrol, | ||
355 | struct snd_ctl_elem_value *ucontrol) | ||
356 | { | ||
357 | ucontrol->value.integer.value[0] = kcontrol->private_value & 0xff; | ||
358 | return 0; | ||
359 | } | ||
360 | |||
361 | static int stac92xx_volknob_put(struct snd_kcontrol *kcontrol, | ||
362 | struct snd_ctl_elem_value *ucontrol) | ||
363 | { | ||
364 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
365 | unsigned int val = kcontrol->private_value & 0xff; | ||
366 | |||
367 | if (val == ucontrol->value.integer.value[0]) | ||
368 | return 0; | ||
369 | |||
370 | val = ucontrol->value.integer.value[0]; | ||
371 | kcontrol->private_value &= ~0xff; | ||
372 | kcontrol->private_value |= val; | ||
373 | |||
374 | snd_hda_codec_write_cache(codec, kcontrol->private_value >> 16, 0, | ||
375 | AC_VERB_SET_VOLUME_KNOB_CONTROL, val | 0x80); | ||
376 | return 1; | ||
377 | } | ||
378 | |||
379 | |||
279 | static struct hda_verb stac9200_core_init[] = { | 380 | static struct hda_verb stac9200_core_init[] = { |
280 | /* set dac0mux for dac converter */ | 381 | /* set dac0mux for dac converter */ |
281 | { 0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | 382 | { 0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, |
282 | {} | 383 | {} |
283 | }; | 384 | }; |
284 | 385 | ||
386 | static struct hda_verb stac9200_eapd_init[] = { | ||
387 | /* set dac0mux for dac converter */ | ||
388 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
389 | {0x08, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, | ||
390 | {} | ||
391 | }; | ||
392 | |||
285 | static struct hda_verb stac925x_core_init[] = { | 393 | static struct hda_verb stac925x_core_init[] = { |
286 | /* set dac0mux for dac converter */ | 394 | /* set dac0mux for dac converter */ |
287 | { 0x06, AC_VERB_SET_CONNECT_SEL, 0x00}, | 395 | { 0x06, AC_VERB_SET_CONNECT_SEL, 0x00}, |
@@ -316,17 +424,43 @@ static struct hda_verb stac9205_core_init[] = { | |||
316 | {} | 424 | {} |
317 | }; | 425 | }; |
318 | 426 | ||
427 | #define STAC_INPUT_SOURCE(cnt) \ | ||
428 | { \ | ||
429 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
430 | .name = "Input Source", \ | ||
431 | .count = cnt, \ | ||
432 | .info = stac92xx_mux_enum_info, \ | ||
433 | .get = stac92xx_mux_enum_get, \ | ||
434 | .put = stac92xx_mux_enum_put, \ | ||
435 | } | ||
436 | |||
437 | #define STAC_ANALOG_LOOPBACK(verb_read,verb_write) \ | ||
438 | { \ | ||
439 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
440 | .name = "Analog Loopback", \ | ||
441 | .count = 1, \ | ||
442 | .info = stac92xx_aloopback_info, \ | ||
443 | .get = stac92xx_aloopback_get, \ | ||
444 | .put = stac92xx_aloopback_put, \ | ||
445 | .private_value = verb_read | (verb_write << 16), \ | ||
446 | } | ||
447 | |||
448 | #define STAC_VOLKNOB(knob_nid) \ | ||
449 | { \ | ||
450 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
451 | .name = "Master Playback Volume", \ | ||
452 | .count = 1, \ | ||
453 | .info = stac92xx_volknob_info, \ | ||
454 | .get = stac92xx_volknob_get, \ | ||
455 | .put = stac92xx_volknob_put, \ | ||
456 | .private_value = 127 | (knob_nid << 16), \ | ||
457 | } | ||
458 | |||
459 | |||
319 | static struct snd_kcontrol_new stac9200_mixer[] = { | 460 | static struct snd_kcontrol_new stac9200_mixer[] = { |
320 | HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), | 461 | HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), |
321 | HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), | 462 | HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), |
322 | { | 463 | STAC_INPUT_SOURCE(1), |
323 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
324 | .name = "Input Source", | ||
325 | .count = 1, | ||
326 | .info = stac92xx_mux_enum_info, | ||
327 | .get = stac92xx_mux_enum_get, | ||
328 | .put = stac92xx_mux_enum_put, | ||
329 | }, | ||
330 | HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), | 464 | HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), |
331 | HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), | 465 | HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), |
332 | HDA_CODEC_VOLUME("Capture Mux Volume", 0x0c, 0, HDA_OUTPUT), | 466 | HDA_CODEC_VOLUME("Capture Mux Volume", 0x0c, 0, HDA_OUTPUT), |
@@ -334,86 +468,68 @@ static struct snd_kcontrol_new stac9200_mixer[] = { | |||
334 | }; | 468 | }; |
335 | 469 | ||
336 | static struct snd_kcontrol_new stac925x_mixer[] = { | 470 | static struct snd_kcontrol_new stac925x_mixer[] = { |
337 | { | 471 | STAC_INPUT_SOURCE(1), |
338 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
339 | .name = "Input Source", | ||
340 | .count = 1, | ||
341 | .info = stac92xx_mux_enum_info, | ||
342 | .get = stac92xx_mux_enum_get, | ||
343 | .put = stac92xx_mux_enum_put, | ||
344 | }, | ||
345 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT), | 472 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT), |
346 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_OUTPUT), | 473 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_OUTPUT), |
347 | HDA_CODEC_VOLUME("Capture Mux Volume", 0x0f, 0, HDA_OUTPUT), | 474 | HDA_CODEC_VOLUME("Capture Mux Volume", 0x0f, 0, HDA_OUTPUT), |
348 | { } /* end */ | 475 | { } /* end */ |
349 | }; | 476 | }; |
350 | 477 | ||
351 | /* This needs to be generated dynamically based on sequence */ | 478 | static struct snd_kcontrol_new stac9205_mixer[] = { |
352 | static struct snd_kcontrol_new stac922x_mixer[] = { | ||
353 | { | 479 | { |
354 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 480 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
355 | .name = "Input Source", | 481 | .name = "Digital Input Source", |
356 | .count = 1, | 482 | .count = 1, |
357 | .info = stac92xx_mux_enum_info, | 483 | .info = stac92xx_dmux_enum_info, |
358 | .get = stac92xx_mux_enum_get, | 484 | .get = stac92xx_dmux_enum_get, |
359 | .put = stac92xx_mux_enum_put, | 485 | .put = stac92xx_dmux_enum_put, |
360 | }, | 486 | }, |
361 | HDA_CODEC_VOLUME("Capture Volume", 0x17, 0x0, HDA_INPUT), | 487 | STAC_INPUT_SOURCE(2), |
362 | HDA_CODEC_MUTE("Capture Switch", 0x17, 0x0, HDA_INPUT), | 488 | STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0), |
363 | HDA_CODEC_VOLUME("Mux Capture Volume", 0x12, 0x0, HDA_OUTPUT), | 489 | STAC_VOLKNOB(0x24), |
490 | |||
491 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1b, 0x0, HDA_INPUT), | ||
492 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1d, 0x0, HDA_OUTPUT), | ||
493 | HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x0, 0x19, 0x0, HDA_OUTPUT), | ||
494 | |||
495 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x1c, 0x0, HDA_INPUT), | ||
496 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1e, 0x0, HDA_OUTPUT), | ||
497 | HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x1, 0x1A, 0x0, HDA_OUTPUT), | ||
498 | |||
364 | { } /* end */ | 499 | { } /* end */ |
365 | }; | 500 | }; |
366 | 501 | ||
367 | /* This needs to be generated dynamically based on sequence */ | 502 | /* This needs to be generated dynamically based on sequence */ |
368 | static struct snd_kcontrol_new stac9227_mixer[] = { | 503 | static struct snd_kcontrol_new stac922x_mixer[] = { |
369 | { | 504 | STAC_INPUT_SOURCE(2), |
370 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 505 | STAC_VOLKNOB(0x16), |
371 | .name = "Input Source", | 506 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_INPUT), |
372 | .count = 1, | 507 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x17, 0x0, HDA_INPUT), |
373 | .info = stac92xx_mux_enum_info, | 508 | HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x0, 0x12, 0x0, HDA_OUTPUT), |
374 | .get = stac92xx_mux_enum_get, | 509 | |
375 | .put = stac92xx_mux_enum_put, | 510 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x18, 0x0, HDA_INPUT), |
376 | }, | 511 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x18, 0x0, HDA_INPUT), |
377 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), | 512 | HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x1, 0x13, 0x0, HDA_OUTPUT), |
378 | HDA_CODEC_MUTE("Capture Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
379 | { } /* end */ | 513 | { } /* end */ |
380 | }; | 514 | }; |
381 | 515 | ||
516 | |||
382 | static struct snd_kcontrol_new stac927x_mixer[] = { | 517 | static struct snd_kcontrol_new stac927x_mixer[] = { |
383 | { | 518 | STAC_INPUT_SOURCE(3), |
384 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 519 | STAC_VOLKNOB(0x24), |
385 | .name = "Input Source", | 520 | STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB), |
386 | .count = 1, | ||
387 | .info = stac92xx_mux_enum_info, | ||
388 | .get = stac92xx_mux_enum_get, | ||
389 | .put = stac92xx_mux_enum_put, | ||
390 | }, | ||
391 | HDA_CODEC_VOLUME("InMux Capture Volume", 0x15, 0x0, HDA_OUTPUT), | ||
392 | HDA_CODEC_VOLUME("InVol Capture Volume", 0x18, 0x0, HDA_INPUT), | ||
393 | HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
394 | { } /* end */ | ||
395 | }; | ||
396 | 521 | ||
397 | static struct snd_kcontrol_new stac9205_mixer[] = { | 522 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x18, 0x0, HDA_INPUT), |
398 | { | 523 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1b, 0x0, HDA_OUTPUT), |
399 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 524 | HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x0, 0x15, 0x0, HDA_OUTPUT), |
400 | .name = "Digital Input Source", | 525 | |
401 | .count = 1, | 526 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x19, 0x0, HDA_INPUT), |
402 | .info = stac92xx_dmux_enum_info, | 527 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1c, 0x0, HDA_OUTPUT), |
403 | .get = stac92xx_dmux_enum_get, | 528 | HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x1, 0x16, 0x0, HDA_OUTPUT), |
404 | .put = stac92xx_dmux_enum_put, | 529 | |
405 | }, | 530 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x2, 0x1A, 0x0, HDA_INPUT), |
406 | { | 531 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x2, 0x1d, 0x0, HDA_OUTPUT), |
407 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 532 | HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x2, 0x17, 0x0, HDA_OUTPUT), |
408 | .name = "Input Source", | ||
409 | .count = 1, | ||
410 | .info = stac92xx_mux_enum_info, | ||
411 | .get = stac92xx_mux_enum_get, | ||
412 | .put = stac92xx_mux_enum_put, | ||
413 | }, | ||
414 | HDA_CODEC_VOLUME("InMux Capture Volume", 0x19, 0x0, HDA_OUTPUT), | ||
415 | HDA_CODEC_VOLUME("InVol Capture Volume", 0x1b, 0x0, HDA_INPUT), | ||
416 | HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1d, 0x0, HDA_OUTPUT), | ||
417 | { } /* end */ | 533 | { } /* end */ |
418 | }; | 534 | }; |
419 | 535 | ||
@@ -451,12 +567,145 @@ static unsigned int ref9200_pin_configs[8] = { | |||
451 | 0x02a19020, 0x01a19021, 0x90100140, 0x01813122, | 567 | 0x02a19020, 0x01a19021, 0x90100140, 0x01813122, |
452 | }; | 568 | }; |
453 | 569 | ||
570 | /* | ||
571 | STAC 9200 pin configs for | ||
572 | 102801A8 | ||
573 | 102801DE | ||
574 | 102801E8 | ||
575 | */ | ||
576 | static unsigned int dell9200_d21_pin_configs[8] = { | ||
577 | 0x400001f0, 0x400001f1, 0x02214030, 0x01014010, | ||
578 | 0x02a19020, 0x01a19021, 0x90100140, 0x01813122, | ||
579 | }; | ||
580 | |||
581 | /* | ||
582 | STAC 9200 pin configs for | ||
583 | 102801C0 | ||
584 | 102801C1 | ||
585 | */ | ||
586 | static unsigned int dell9200_d22_pin_configs[8] = { | ||
587 | 0x400001f0, 0x400001f1, 0x0221401f, 0x01014010, | ||
588 | 0x01813020, 0x02a19021, 0x90100140, 0x400001f2, | ||
589 | }; | ||
590 | |||
591 | /* | ||
592 | STAC 9200 pin configs for | ||
593 | 102801C4 (Dell Dimension E310) | ||
594 | 102801C5 | ||
595 | 102801C7 | ||
596 | 102801D9 | ||
597 | 102801DA | ||
598 | 102801E3 | ||
599 | */ | ||
600 | static unsigned int dell9200_d23_pin_configs[8] = { | ||
601 | 0x400001f0, 0x400001f1, 0x0221401f, 0x01014010, | ||
602 | 0x01813020, 0x01a19021, 0x90100140, 0x400001f2, | ||
603 | }; | ||
604 | |||
605 | |||
606 | /* | ||
607 | STAC 9200-32 pin configs for | ||
608 | 102801B5 (Dell Inspiron 630m) | ||
609 | 102801D8 (Dell Inspiron 640m) | ||
610 | */ | ||
611 | static unsigned int dell9200_m21_pin_configs[8] = { | ||
612 | 0x40c003fa, 0x03441340, 0x0321121f, 0x90170310, | ||
613 | 0x408003fb, 0x03a11020, 0x401003fc, 0x403003fd, | ||
614 | }; | ||
615 | |||
616 | /* | ||
617 | STAC 9200-32 pin configs for | ||
618 | 102801C2 (Dell Latitude D620) | ||
619 | 102801C8 | ||
620 | 102801CC (Dell Latitude D820) | ||
621 | 102801D4 | ||
622 | 102801D6 | ||
623 | */ | ||
624 | static unsigned int dell9200_m22_pin_configs[8] = { | ||
625 | 0x40c003fa, 0x0144131f, 0x0321121f, 0x90170310, | ||
626 | 0x90a70321, 0x03a11020, 0x401003fb, 0x40f000fc, | ||
627 | }; | ||
628 | |||
629 | /* | ||
630 | STAC 9200-32 pin configs for | ||
631 | 102801CE (Dell XPS M1710) | ||
632 | 102801CF (Dell Precision M90) | ||
633 | */ | ||
634 | static unsigned int dell9200_m23_pin_configs[8] = { | ||
635 | 0x40c003fa, 0x01441340, 0x0421421f, 0x90170310, | ||
636 | 0x408003fb, 0x04a1102e, 0x90170311, 0x403003fc, | ||
637 | }; | ||
638 | |||
639 | /* | ||
640 | STAC 9200-32 pin configs for | ||
641 | 102801C9 | ||
642 | 102801CA | ||
643 | 102801CB (Dell Latitude 120L) | ||
644 | 102801D3 | ||
645 | */ | ||
646 | static unsigned int dell9200_m24_pin_configs[8] = { | ||
647 | 0x40c003fa, 0x404003fb, 0x0321121f, 0x90170310, | ||
648 | 0x408003fc, 0x03a11020, 0x401003fd, 0x403003fe, | ||
649 | }; | ||
650 | |||
651 | /* | ||
652 | STAC 9200-32 pin configs for | ||
653 | 102801BD (Dell Inspiron E1505n) | ||
654 | 102801EE | ||
655 | 102801EF | ||
656 | */ | ||
657 | static unsigned int dell9200_m25_pin_configs[8] = { | ||
658 | 0x40c003fa, 0x01441340, 0x0421121f, 0x90170310, | ||
659 | 0x408003fb, 0x04a11020, 0x401003fc, 0x403003fd, | ||
660 | }; | ||
661 | |||
662 | /* | ||
663 | STAC 9200-32 pin configs for | ||
664 | 102801F5 (Dell Inspiron 1501) | ||
665 | 102801F6 | ||
666 | */ | ||
667 | static unsigned int dell9200_m26_pin_configs[8] = { | ||
668 | 0x40c003fa, 0x404003fb, 0x0421121f, 0x90170310, | ||
669 | 0x408003fc, 0x04a11020, 0x401003fd, 0x403003fe, | ||
670 | }; | ||
671 | |||
672 | /* | ||
673 | STAC 9200-32 | ||
674 | 102801CD (Dell Inspiron E1705/9400) | ||
675 | */ | ||
676 | static unsigned int dell9200_m27_pin_configs[8] = { | ||
677 | 0x40c003fa, 0x01441340, 0x0421121f, 0x90170310, | ||
678 | 0x90170310, 0x04a11020, 0x90170310, 0x40f003fc, | ||
679 | }; | ||
680 | |||
681 | |||
454 | static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = { | 682 | static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = { |
455 | [STAC_REF] = ref9200_pin_configs, | 683 | [STAC_REF] = ref9200_pin_configs, |
684 | [STAC_9200_DELL_D21] = dell9200_d21_pin_configs, | ||
685 | [STAC_9200_DELL_D22] = dell9200_d22_pin_configs, | ||
686 | [STAC_9200_DELL_D23] = dell9200_d23_pin_configs, | ||
687 | [STAC_9200_DELL_M21] = dell9200_m21_pin_configs, | ||
688 | [STAC_9200_DELL_M22] = dell9200_m22_pin_configs, | ||
689 | [STAC_9200_DELL_M23] = dell9200_m23_pin_configs, | ||
690 | [STAC_9200_DELL_M24] = dell9200_m24_pin_configs, | ||
691 | [STAC_9200_DELL_M25] = dell9200_m25_pin_configs, | ||
692 | [STAC_9200_DELL_M26] = dell9200_m26_pin_configs, | ||
693 | [STAC_9200_DELL_M27] = dell9200_m27_pin_configs, | ||
456 | }; | 694 | }; |
457 | 695 | ||
458 | static const char *stac9200_models[STAC_9200_MODELS] = { | 696 | static const char *stac9200_models[STAC_9200_MODELS] = { |
459 | [STAC_REF] = "ref", | 697 | [STAC_REF] = "ref", |
698 | [STAC_9200_DELL_D21] = "dell-d21", | ||
699 | [STAC_9200_DELL_D22] = "dell-d22", | ||
700 | [STAC_9200_DELL_D23] = "dell-d23", | ||
701 | [STAC_9200_DELL_M21] = "dell-m21", | ||
702 | [STAC_9200_DELL_M22] = "dell-m22", | ||
703 | [STAC_9200_DELL_M23] = "dell-m23", | ||
704 | [STAC_9200_DELL_M24] = "dell-m24", | ||
705 | [STAC_9200_DELL_M25] = "dell-m25", | ||
706 | [STAC_9200_DELL_M26] = "dell-m26", | ||
707 | [STAC_9200_DELL_M27] = "dell-m27", | ||
708 | [STAC_9200_GATEWAY] = "gateway", | ||
460 | }; | 709 | }; |
461 | 710 | ||
462 | static struct snd_pci_quirk stac9200_cfg_tbl[] = { | 711 | static struct snd_pci_quirk stac9200_cfg_tbl[] = { |
@@ -464,30 +713,72 @@ static struct snd_pci_quirk stac9200_cfg_tbl[] = { | |||
464 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 713 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
465 | "DFI LanParty", STAC_REF), | 714 | "DFI LanParty", STAC_REF), |
466 | /* Dell laptops have BIOS problem */ | 715 | /* Dell laptops have BIOS problem */ |
716 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a8, | ||
717 | "unknown Dell", STAC_9200_DELL_D21), | ||
467 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01b5, | 718 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01b5, |
468 | "Dell Inspiron 630m", STAC_REF), | 719 | "Dell Inspiron 630m", STAC_9200_DELL_M21), |
720 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01bd, | ||
721 | "Dell Inspiron E1505n", STAC_9200_DELL_M25), | ||
722 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c0, | ||
723 | "unknown Dell", STAC_9200_DELL_D22), | ||
724 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c1, | ||
725 | "unknown Dell", STAC_9200_DELL_D22), | ||
469 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c2, | 726 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c2, |
470 | "Dell Latitude D620", STAC_REF), | 727 | "Dell Latitude D620", STAC_9200_DELL_M22), |
728 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c5, | ||
729 | "unknown Dell", STAC_9200_DELL_D23), | ||
730 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c7, | ||
731 | "unknown Dell", STAC_9200_DELL_D23), | ||
732 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c8, | ||
733 | "unknown Dell", STAC_9200_DELL_M22), | ||
734 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c9, | ||
735 | "unknown Dell", STAC_9200_DELL_M24), | ||
736 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ca, | ||
737 | "unknown Dell", STAC_9200_DELL_M24), | ||
471 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cb, | 738 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cb, |
472 | "Dell Latitude 120L", STAC_REF), | 739 | "Dell Latitude 120L", STAC_9200_DELL_M24), |
473 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cc, | 740 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cc, |
474 | "Dell Latitude D820", STAC_REF), | 741 | "Dell Latitude D820", STAC_9200_DELL_M22), |
475 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cd, | 742 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cd, |
476 | "Dell Inspiron E1705/9400", STAC_REF), | 743 | "Dell Inspiron E1705/9400", STAC_9200_DELL_M27), |
477 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ce, | 744 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ce, |
478 | "Dell XPS M1710", STAC_REF), | 745 | "Dell XPS M1710", STAC_9200_DELL_M23), |
479 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cf, | 746 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cf, |
480 | "Dell Precision M90", STAC_REF), | 747 | "Dell Precision M90", STAC_9200_DELL_M23), |
748 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d3, | ||
749 | "unknown Dell", STAC_9200_DELL_M22), | ||
750 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d4, | ||
751 | "unknown Dell", STAC_9200_DELL_M22), | ||
481 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d6, | 752 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d6, |
482 | "unknown Dell", STAC_REF), | 753 | "unknown Dell", STAC_9200_DELL_M22), |
483 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d8, | 754 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d8, |
484 | "Dell Inspiron 640m", STAC_REF), | 755 | "Dell Inspiron 640m", STAC_9200_DELL_M21), |
756 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d9, | ||
757 | "unknown Dell", STAC_9200_DELL_D23), | ||
758 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01da, | ||
759 | "unknown Dell", STAC_9200_DELL_D23), | ||
760 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01de, | ||
761 | "unknown Dell", STAC_9200_DELL_D21), | ||
762 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01e3, | ||
763 | "unknown Dell", STAC_9200_DELL_D23), | ||
764 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01e8, | ||
765 | "unknown Dell", STAC_9200_DELL_D21), | ||
766 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ee, | ||
767 | "unknown Dell", STAC_9200_DELL_M25), | ||
768 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ef, | ||
769 | "unknown Dell", STAC_9200_DELL_M25), | ||
485 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f5, | 770 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f5, |
486 | "Dell Inspiron 1501", STAC_REF), | 771 | "Dell Inspiron 1501", STAC_9200_DELL_M26), |
487 | 772 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f6, | |
773 | "unknown Dell", STAC_9200_DELL_M26), | ||
488 | /* Panasonic */ | 774 | /* Panasonic */ |
489 | SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_REF), | 775 | SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_REF), |
490 | 776 | /* Gateway machines needs EAPD to be set on resume */ | |
777 | SND_PCI_QUIRK(0x107b, 0x0205, "Gateway S-7110M", STAC_9200_GATEWAY), | ||
778 | SND_PCI_QUIRK(0x107b, 0x0317, "Gateway MT3423, MX341*", | ||
779 | STAC_9200_GATEWAY), | ||
780 | SND_PCI_QUIRK(0x107b, 0x0318, "Gateway ML3019, MT3707", | ||
781 | STAC_9200_GATEWAY), | ||
491 | {} /* terminator */ | 782 | {} /* terminator */ |
492 | }; | 783 | }; |
493 | 784 | ||
@@ -543,6 +834,51 @@ static unsigned int ref922x_pin_configs[10] = { | |||
543 | 0x40000100, 0x40000100, | 834 | 0x40000100, 0x40000100, |
544 | }; | 835 | }; |
545 | 836 | ||
837 | /* | ||
838 | STAC 922X pin configs for | ||
839 | 102801A7 | ||
840 | 102801AB | ||
841 | 102801A9 | ||
842 | 102801D1 | ||
843 | 102801D2 | ||
844 | */ | ||
845 | static unsigned int dell_922x_d81_pin_configs[10] = { | ||
846 | 0x02214030, 0x01a19021, 0x01111012, 0x01114010, | ||
847 | 0x02a19020, 0x01117011, 0x400001f0, 0x400001f1, | ||
848 | 0x01813122, 0x400001f2, | ||
849 | }; | ||
850 | |||
851 | /* | ||
852 | STAC 922X pin configs for | ||
853 | 102801AC | ||
854 | 102801D0 | ||
855 | */ | ||
856 | static unsigned int dell_922x_d82_pin_configs[10] = { | ||
857 | 0x02214030, 0x01a19021, 0x01111012, 0x01114010, | ||
858 | 0x02a19020, 0x01117011, 0x01451140, 0x400001f0, | ||
859 | 0x01813122, 0x400001f1, | ||
860 | }; | ||
861 | |||
862 | /* | ||
863 | STAC 922X pin configs for | ||
864 | 102801BF | ||
865 | */ | ||
866 | static unsigned int dell_922x_m81_pin_configs[10] = { | ||
867 | 0x0321101f, 0x01112024, 0x01111222, 0x91174220, | ||
868 | 0x03a11050, 0x01116221, 0x90a70330, 0x01452340, | ||
869 | 0x40C003f1, 0x405003f0, | ||
870 | }; | ||
871 | |||
872 | /* | ||
873 | STAC 9221 A1 pin configs for | ||
874 | 102801D7 (Dell XPS M1210) | ||
875 | */ | ||
876 | static unsigned int dell_922x_m82_pin_configs[10] = { | ||
877 | 0x0221121f, 0x408103ff, 0x02111212, 0x90100310, | ||
878 | 0x408003f1, 0x02111211, 0x03451340, 0x40c003f2, | ||
879 | 0x508003f3, 0x405003f4, | ||
880 | }; | ||
881 | |||
546 | static unsigned int d945gtp3_pin_configs[10] = { | 882 | static unsigned int d945gtp3_pin_configs[10] = { |
547 | 0x0221401f, 0x01a19022, 0x01813021, 0x01014010, | 883 | 0x0221401f, 0x01a19022, 0x01813021, 0x01014010, |
548 | 0x40000100, 0x40000100, 0x40000100, 0x40000100, | 884 | 0x40000100, 0x40000100, 0x40000100, 0x40000100, |
@@ -585,48 +921,49 @@ static unsigned int intel_mac_v5_pin_configs[10] = { | |||
585 | 0x400000fc, 0x400000fb, | 921 | 0x400000fc, 0x400000fb, |
586 | }; | 922 | }; |
587 | 923 | ||
588 | static unsigned int stac922x_dell_pin_configs[10] = { | ||
589 | 0x0221121e, 0x408103ff, 0x02a1123e, 0x90100310, | ||
590 | 0x408003f1, 0x0221122f, 0x03451340, 0x40c003f2, | ||
591 | 0x50a003f3, 0x405003f4 | ||
592 | }; | ||
593 | 924 | ||
594 | static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = { | 925 | static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = { |
595 | [STAC_D945_REF] = ref922x_pin_configs, | 926 | [STAC_D945_REF] = ref922x_pin_configs, |
596 | [STAC_D945GTP3] = d945gtp3_pin_configs, | 927 | [STAC_D945GTP3] = d945gtp3_pin_configs, |
597 | [STAC_D945GTP5] = d945gtp5_pin_configs, | 928 | [STAC_D945GTP5] = d945gtp5_pin_configs, |
598 | [STAC_922X_DELL] = stac922x_dell_pin_configs, | ||
599 | [STAC_INTEL_MAC_V1] = intel_mac_v1_pin_configs, | 929 | [STAC_INTEL_MAC_V1] = intel_mac_v1_pin_configs, |
600 | [STAC_INTEL_MAC_V2] = intel_mac_v2_pin_configs, | 930 | [STAC_INTEL_MAC_V2] = intel_mac_v2_pin_configs, |
601 | [STAC_INTEL_MAC_V3] = intel_mac_v3_pin_configs, | 931 | [STAC_INTEL_MAC_V3] = intel_mac_v3_pin_configs, |
602 | [STAC_INTEL_MAC_V4] = intel_mac_v4_pin_configs, | 932 | [STAC_INTEL_MAC_V4] = intel_mac_v4_pin_configs, |
603 | [STAC_INTEL_MAC_V5] = intel_mac_v5_pin_configs, | 933 | [STAC_INTEL_MAC_V5] = intel_mac_v5_pin_configs, |
604 | /* for backward compitability */ | 934 | /* for backward compatibility */ |
605 | [STAC_MACMINI] = intel_mac_v3_pin_configs, | 935 | [STAC_MACMINI] = intel_mac_v3_pin_configs, |
606 | [STAC_MACBOOK] = intel_mac_v5_pin_configs, | 936 | [STAC_MACBOOK] = intel_mac_v5_pin_configs, |
607 | [STAC_MACBOOK_PRO_V1] = intel_mac_v3_pin_configs, | 937 | [STAC_MACBOOK_PRO_V1] = intel_mac_v3_pin_configs, |
608 | [STAC_MACBOOK_PRO_V2] = intel_mac_v3_pin_configs, | 938 | [STAC_MACBOOK_PRO_V2] = intel_mac_v3_pin_configs, |
609 | [STAC_IMAC_INTEL] = intel_mac_v2_pin_configs, | 939 | [STAC_IMAC_INTEL] = intel_mac_v2_pin_configs, |
610 | [STAC_IMAC_INTEL_20] = intel_mac_v3_pin_configs, | 940 | [STAC_IMAC_INTEL_20] = intel_mac_v3_pin_configs, |
941 | [STAC_922X_DELL_D81] = dell_922x_d81_pin_configs, | ||
942 | [STAC_922X_DELL_D82] = dell_922x_d82_pin_configs, | ||
943 | [STAC_922X_DELL_M81] = dell_922x_m81_pin_configs, | ||
944 | [STAC_922X_DELL_M82] = dell_922x_m82_pin_configs, | ||
611 | }; | 945 | }; |
612 | 946 | ||
613 | static const char *stac922x_models[STAC_922X_MODELS] = { | 947 | static const char *stac922x_models[STAC_922X_MODELS] = { |
614 | [STAC_D945_REF] = "ref", | 948 | [STAC_D945_REF] = "ref", |
615 | [STAC_D945GTP5] = "5stack", | 949 | [STAC_D945GTP5] = "5stack", |
616 | [STAC_D945GTP3] = "3stack", | 950 | [STAC_D945GTP3] = "3stack", |
617 | [STAC_922X_DELL] = "dell", | ||
618 | [STAC_INTEL_MAC_V1] = "intel-mac-v1", | 951 | [STAC_INTEL_MAC_V1] = "intel-mac-v1", |
619 | [STAC_INTEL_MAC_V2] = "intel-mac-v2", | 952 | [STAC_INTEL_MAC_V2] = "intel-mac-v2", |
620 | [STAC_INTEL_MAC_V3] = "intel-mac-v3", | 953 | [STAC_INTEL_MAC_V3] = "intel-mac-v3", |
621 | [STAC_INTEL_MAC_V4] = "intel-mac-v4", | 954 | [STAC_INTEL_MAC_V4] = "intel-mac-v4", |
622 | [STAC_INTEL_MAC_V5] = "intel-mac-v5", | 955 | [STAC_INTEL_MAC_V5] = "intel-mac-v5", |
623 | /* for backward compitability */ | 956 | /* for backward compatibility */ |
624 | [STAC_MACMINI] = "macmini", | 957 | [STAC_MACMINI] = "macmini", |
625 | [STAC_MACBOOK] = "macbook", | 958 | [STAC_MACBOOK] = "macbook", |
626 | [STAC_MACBOOK_PRO_V1] = "macbook-pro-v1", | 959 | [STAC_MACBOOK_PRO_V1] = "macbook-pro-v1", |
627 | [STAC_MACBOOK_PRO_V2] = "macbook-pro", | 960 | [STAC_MACBOOK_PRO_V2] = "macbook-pro", |
628 | [STAC_IMAC_INTEL] = "imac-intel", | 961 | [STAC_IMAC_INTEL] = "imac-intel", |
629 | [STAC_IMAC_INTEL_20] = "imac-intel-20", | 962 | [STAC_IMAC_INTEL_20] = "imac-intel-20", |
963 | [STAC_922X_DELL_D81] = "dell-d81", | ||
964 | [STAC_922X_DELL_D82] = "dell-d82", | ||
965 | [STAC_922X_DELL_M81] = "dell-m81", | ||
966 | [STAC_922X_DELL_M82] = "dell-m82", | ||
630 | }; | 967 | }; |
631 | 968 | ||
632 | static struct snd_pci_quirk stac922x_cfg_tbl[] = { | 969 | static struct snd_pci_quirk stac922x_cfg_tbl[] = { |
@@ -690,9 +1027,25 @@ static struct snd_pci_quirk stac922x_cfg_tbl[] = { | |||
690 | /* Apple Mac Mini (early 2006) */ | 1027 | /* Apple Mac Mini (early 2006) */ |
691 | SND_PCI_QUIRK(0x8384, 0x7680, | 1028 | SND_PCI_QUIRK(0x8384, 0x7680, |
692 | "Mac Mini", STAC_INTEL_MAC_V3), | 1029 | "Mac Mini", STAC_INTEL_MAC_V3), |
693 | /* Dell */ | 1030 | /* Dell systems */ |
694 | SND_PCI_QUIRK(0x1028, 0x01d7, "Dell XPS M1210", STAC_922X_DELL), | 1031 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a7, |
695 | 1032 | "unknown Dell", STAC_922X_DELL_D81), | |
1033 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a9, | ||
1034 | "unknown Dell", STAC_922X_DELL_D81), | ||
1035 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ab, | ||
1036 | "unknown Dell", STAC_922X_DELL_D81), | ||
1037 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ac, | ||
1038 | "unknown Dell", STAC_922X_DELL_D82), | ||
1039 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01bf, | ||
1040 | "unknown Dell", STAC_922X_DELL_M81), | ||
1041 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d0, | ||
1042 | "unknown Dell", STAC_922X_DELL_D82), | ||
1043 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d1, | ||
1044 | "unknown Dell", STAC_922X_DELL_D81), | ||
1045 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d2, | ||
1046 | "unknown Dell", STAC_922X_DELL_D81), | ||
1047 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d7, | ||
1048 | "Dell XPS M1210", STAC_922X_DELL_M82), | ||
696 | {} /* terminator */ | 1049 | {} /* terminator */ |
697 | }; | 1050 | }; |
698 | 1051 | ||
@@ -717,16 +1070,25 @@ static unsigned int d965_5st_pin_configs[14] = { | |||
717 | 0x40000100, 0x40000100 | 1070 | 0x40000100, 0x40000100 |
718 | }; | 1071 | }; |
719 | 1072 | ||
1073 | static unsigned int dell_3st_pin_configs[14] = { | ||
1074 | 0x02211230, 0x02a11220, 0x01a19040, 0x01114210, | ||
1075 | 0x01111212, 0x01116211, 0x01813050, 0x01112214, | ||
1076 | 0x403003fa, 0x40000100, 0x40000100, 0x404003fb, | ||
1077 | 0x40c003fc, 0x40000100 | ||
1078 | }; | ||
1079 | |||
720 | static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = { | 1080 | static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = { |
721 | [STAC_D965_REF] = ref927x_pin_configs, | 1081 | [STAC_D965_REF] = ref927x_pin_configs, |
722 | [STAC_D965_3ST] = d965_3st_pin_configs, | 1082 | [STAC_D965_3ST] = d965_3st_pin_configs, |
723 | [STAC_D965_5ST] = d965_5st_pin_configs, | 1083 | [STAC_D965_5ST] = d965_5st_pin_configs, |
1084 | [STAC_DELL_3ST] = dell_3st_pin_configs, | ||
724 | }; | 1085 | }; |
725 | 1086 | ||
726 | static const char *stac927x_models[STAC_927X_MODELS] = { | 1087 | static const char *stac927x_models[STAC_927X_MODELS] = { |
727 | [STAC_D965_REF] = "ref", | 1088 | [STAC_D965_REF] = "ref", |
728 | [STAC_D965_3ST] = "3stack", | 1089 | [STAC_D965_3ST] = "3stack", |
729 | [STAC_D965_5ST] = "5stack", | 1090 | [STAC_D965_5ST] = "5stack", |
1091 | [STAC_DELL_3ST] = "dell-3stack", | ||
730 | }; | 1092 | }; |
731 | 1093 | ||
732 | static struct snd_pci_quirk stac927x_cfg_tbl[] = { | 1094 | static struct snd_pci_quirk stac927x_cfg_tbl[] = { |
@@ -753,7 +1115,13 @@ static struct snd_pci_quirk stac927x_cfg_tbl[] = { | |||
753 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2003, "Intel D965", STAC_D965_3ST), | 1115 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2003, "Intel D965", STAC_D965_3ST), |
754 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2002, "Intel D965", STAC_D965_3ST), | 1116 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2002, "Intel D965", STAC_D965_3ST), |
755 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2001, "Intel D965", STAC_D965_3ST), | 1117 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2001, "Intel D965", STAC_D965_3ST), |
1118 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f3, "Dell Inspiron 1420", STAC_D965_3ST), | ||
1119 | /* Dell 3 stack systems */ | ||
1120 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01dd, "Dell Dimension E520", STAC_DELL_3ST), | ||
1121 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ed, "Dell ", STAC_DELL_3ST), | ||
1122 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f4, "Dell ", STAC_DELL_3ST), | ||
756 | /* 965 based 5 stack systems */ | 1123 | /* 965 based 5 stack systems */ |
1124 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0209, "Dell XPS 1330", STAC_D965_5ST), | ||
757 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2301, "Intel D965", STAC_D965_5ST), | 1125 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2301, "Intel D965", STAC_D965_5ST), |
758 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2302, "Intel D965", STAC_D965_5ST), | 1126 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2302, "Intel D965", STAC_D965_5ST), |
759 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2303, "Intel D965", STAC_D965_5ST), | 1127 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2303, "Intel D965", STAC_D965_5ST), |
@@ -772,23 +1140,97 @@ static unsigned int ref9205_pin_configs[12] = { | |||
772 | 0x90a000f0, 0x90a000f0, 0x01441030, 0x01c41030 | 1140 | 0x90a000f0, 0x90a000f0, 0x01441030, 0x01c41030 |
773 | }; | 1141 | }; |
774 | 1142 | ||
1143 | /* | ||
1144 | STAC 9205 pin configs for | ||
1145 | 102801F1 | ||
1146 | 102801F2 | ||
1147 | 102801FC | ||
1148 | 102801FD | ||
1149 | 10280204 | ||
1150 | 1028021F | ||
1151 | */ | ||
1152 | static unsigned int dell_9205_m42_pin_configs[12] = { | ||
1153 | 0x0321101F, 0x03A11020, 0x400003FA, 0x90170310, | ||
1154 | 0x400003FB, 0x400003FC, 0x400003FD, 0x40F000F9, | ||
1155 | 0x90A60330, 0x400003FF, 0x0144131F, 0x40C003FE, | ||
1156 | }; | ||
1157 | |||
1158 | /* | ||
1159 | STAC 9205 pin configs for | ||
1160 | 102801F9 | ||
1161 | 102801FA | ||
1162 | 102801FE | ||
1163 | 102801FF (Dell Precision M4300) | ||
1164 | 10280206 | ||
1165 | 10280200 | ||
1166 | 10280201 | ||
1167 | */ | ||
1168 | static unsigned int dell_9205_m43_pin_configs[12] = { | ||
1169 | 0x0321101f, 0x03a11020, 0x90a70330, 0x90170310, | ||
1170 | 0x400000fe, 0x400000ff, 0x400000fd, 0x40f000f9, | ||
1171 | 0x400000fa, 0x400000fc, 0x0144131f, 0x40c003f8, | ||
1172 | }; | ||
1173 | |||
1174 | static unsigned int dell_9205_m44_pin_configs[12] = { | ||
1175 | 0x0421101f, 0x04a11020, 0x400003fa, 0x90170310, | ||
1176 | 0x400003fb, 0x400003fc, 0x400003fd, 0x400003f9, | ||
1177 | 0x90a60330, 0x400003ff, 0x01441340, 0x40c003fe, | ||
1178 | }; | ||
1179 | |||
775 | static unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = { | 1180 | static unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = { |
776 | [STAC_REF] = ref9205_pin_configs, | 1181 | [STAC_9205_REF] = ref9205_pin_configs, |
777 | [STAC_M43xx] = NULL, | 1182 | [STAC_9205_DELL_M42] = dell_9205_m42_pin_configs, |
1183 | [STAC_9205_DELL_M43] = dell_9205_m43_pin_configs, | ||
1184 | [STAC_9205_DELL_M44] = dell_9205_m44_pin_configs, | ||
778 | }; | 1185 | }; |
779 | 1186 | ||
780 | static const char *stac9205_models[STAC_9205_MODELS] = { | 1187 | static const char *stac9205_models[STAC_9205_MODELS] = { |
781 | [STAC_9205_REF] = "ref", | 1188 | [STAC_9205_REF] = "ref", |
1189 | [STAC_9205_DELL_M42] = "dell-m42", | ||
1190 | [STAC_9205_DELL_M43] = "dell-m43", | ||
1191 | [STAC_9205_DELL_M44] = "dell-m44", | ||
782 | }; | 1192 | }; |
783 | 1193 | ||
784 | static struct snd_pci_quirk stac9205_cfg_tbl[] = { | 1194 | static struct snd_pci_quirk stac9205_cfg_tbl[] = { |
785 | /* SigmaTel reference board */ | 1195 | /* SigmaTel reference board */ |
786 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 1196 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
787 | "DFI LanParty", STAC_9205_REF), | 1197 | "DFI LanParty", STAC_9205_REF), |
788 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x01f8, | 1198 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f1, |
789 | "Dell Precision", STAC_M43xx), | 1199 | "unknown Dell", STAC_9205_DELL_M42), |
790 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x01ff, | 1200 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f2, |
791 | "Dell Precision", STAC_M43xx), | 1201 | "unknown Dell", STAC_9205_DELL_M42), |
1202 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f8, | ||
1203 | "Dell Precision", STAC_9205_DELL_M43), | ||
1204 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021c, | ||
1205 | "Dell Precision", STAC_9205_DELL_M43), | ||
1206 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f9, | ||
1207 | "Dell Precision", STAC_9205_DELL_M43), | ||
1208 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021b, | ||
1209 | "Dell Precision", STAC_9205_DELL_M43), | ||
1210 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fa, | ||
1211 | "Dell Precision", STAC_9205_DELL_M43), | ||
1212 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fc, | ||
1213 | "unknown Dell", STAC_9205_DELL_M42), | ||
1214 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fd, | ||
1215 | "unknown Dell", STAC_9205_DELL_M42), | ||
1216 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fe, | ||
1217 | "Dell Precision", STAC_9205_DELL_M43), | ||
1218 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ff, | ||
1219 | "Dell Precision M4300", STAC_9205_DELL_M43), | ||
1220 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0206, | ||
1221 | "Dell Precision", STAC_9205_DELL_M43), | ||
1222 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f1, | ||
1223 | "Dell Inspiron", STAC_9205_DELL_M44), | ||
1224 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f2, | ||
1225 | "Dell Inspiron", STAC_9205_DELL_M44), | ||
1226 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fc, | ||
1227 | "Dell Inspiron", STAC_9205_DELL_M44), | ||
1228 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fd, | ||
1229 | "Dell Inspiron", STAC_9205_DELL_M44), | ||
1230 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0204, | ||
1231 | "unknown Dell", STAC_9205_DELL_M42), | ||
1232 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021f, | ||
1233 | "Dell Inspiron", STAC_9205_DELL_M44), | ||
792 | {} /* terminator */ | 1234 | {} /* terminator */ |
793 | }; | 1235 | }; |
794 | 1236 | ||
@@ -854,20 +1296,20 @@ static void stac92xx_set_config_regs(struct hda_codec *codec) | |||
854 | spec->pin_configs[i]); | 1296 | spec->pin_configs[i]); |
855 | } | 1297 | } |
856 | 1298 | ||
857 | static void stac92xx_enable_gpio_mask(struct hda_codec *codec, | 1299 | static void stac92xx_enable_gpio_mask(struct hda_codec *codec) |
858 | int gpio_mask, int gpio_data) | ||
859 | { | 1300 | { |
1301 | struct sigmatel_spec *spec = codec->spec; | ||
860 | /* Configure GPIOx as output */ | 1302 | /* Configure GPIOx as output */ |
861 | snd_hda_codec_write(codec, codec->afg, 0, | 1303 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
862 | AC_VERB_SET_GPIO_DIRECTION, gpio_mask); | 1304 | AC_VERB_SET_GPIO_DIRECTION, spec->gpio_mask); |
863 | /* Configure GPIOx as CMOS */ | 1305 | /* Configure GPIOx as CMOS */ |
864 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0x00000000); | 1306 | snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7e7, 0x00000000); |
865 | /* Assert GPIOx */ | 1307 | /* Assert GPIOx */ |
866 | snd_hda_codec_write(codec, codec->afg, 0, | 1308 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
867 | AC_VERB_SET_GPIO_DATA, gpio_data); | 1309 | AC_VERB_SET_GPIO_DATA, spec->gpio_data); |
868 | /* Enable GPIOx */ | 1310 | /* Enable GPIOx */ |
869 | snd_hda_codec_write(codec, codec->afg, 0, | 1311 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
870 | AC_VERB_SET_GPIO_MASK, gpio_mask); | 1312 | AC_VERB_SET_GPIO_MASK, spec->gpio_mask); |
871 | } | 1313 | } |
872 | 1314 | ||
873 | /* | 1315 | /* |
@@ -1000,10 +1442,9 @@ static struct hda_pcm_stream stac92xx_pcm_analog_alt_playback = { | |||
1000 | }; | 1442 | }; |
1001 | 1443 | ||
1002 | static struct hda_pcm_stream stac92xx_pcm_analog_capture = { | 1444 | static struct hda_pcm_stream stac92xx_pcm_analog_capture = { |
1003 | .substreams = 2, | ||
1004 | .channels_min = 2, | 1445 | .channels_min = 2, |
1005 | .channels_max = 2, | 1446 | .channels_max = 2, |
1006 | /* NID is set in stac92xx_build_pcms */ | 1447 | /* NID + .substreams is set in stac92xx_build_pcms */ |
1007 | .ops = { | 1448 | .ops = { |
1008 | .prepare = stac92xx_capture_pcm_prepare, | 1449 | .prepare = stac92xx_capture_pcm_prepare, |
1009 | .cleanup = stac92xx_capture_pcm_cleanup | 1450 | .cleanup = stac92xx_capture_pcm_cleanup |
@@ -1022,6 +1463,7 @@ static int stac92xx_build_pcms(struct hda_codec *codec) | |||
1022 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback; | 1463 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback; |
1023 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture; | 1464 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture; |
1024 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; | 1465 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; |
1466 | info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adcs; | ||
1025 | 1467 | ||
1026 | if (spec->alt_switch) { | 1468 | if (spec->alt_switch) { |
1027 | codec->num_pcms++; | 1469 | codec->num_pcms++; |
@@ -1066,17 +1508,11 @@ static unsigned int stac92xx_get_vref(struct hda_codec *codec, hda_nid_t nid) | |||
1066 | static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int pin_type) | 1508 | static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int pin_type) |
1067 | 1509 | ||
1068 | { | 1510 | { |
1069 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); | 1511 | snd_hda_codec_write_cache(codec, nid, 0, |
1512 | AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); | ||
1070 | } | 1513 | } |
1071 | 1514 | ||
1072 | static int stac92xx_io_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1515 | #define stac92xx_io_switch_info snd_ctl_boolean_mono_info |
1073 | { | ||
1074 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1075 | uinfo->count = 1; | ||
1076 | uinfo->value.integer.min = 0; | ||
1077 | uinfo->value.integer.max = 1; | ||
1078 | return 0; | ||
1079 | } | ||
1080 | 1516 | ||
1081 | static int stac92xx_io_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1517 | static int stac92xx_io_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1082 | { | 1518 | { |
@@ -1109,6 +1545,36 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
1109 | return 1; | 1545 | return 1; |
1110 | } | 1546 | } |
1111 | 1547 | ||
1548 | #define stac92xx_clfe_switch_info snd_ctl_boolean_mono_info | ||
1549 | |||
1550 | static int stac92xx_clfe_switch_get(struct snd_kcontrol *kcontrol, | ||
1551 | struct snd_ctl_elem_value *ucontrol) | ||
1552 | { | ||
1553 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1554 | struct sigmatel_spec *spec = codec->spec; | ||
1555 | |||
1556 | ucontrol->value.integer.value[0] = spec->clfe_swap; | ||
1557 | return 0; | ||
1558 | } | ||
1559 | |||
1560 | static int stac92xx_clfe_switch_put(struct snd_kcontrol *kcontrol, | ||
1561 | struct snd_ctl_elem_value *ucontrol) | ||
1562 | { | ||
1563 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1564 | struct sigmatel_spec *spec = codec->spec; | ||
1565 | hda_nid_t nid = kcontrol->private_value & 0xff; | ||
1566 | |||
1567 | if (spec->clfe_swap == ucontrol->value.integer.value[0]) | ||
1568 | return 0; | ||
1569 | |||
1570 | spec->clfe_swap = ucontrol->value.integer.value[0]; | ||
1571 | |||
1572 | snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE, | ||
1573 | spec->clfe_swap ? 0x4 : 0x0); | ||
1574 | |||
1575 | return 1; | ||
1576 | } | ||
1577 | |||
1112 | #define STAC_CODEC_IO_SWITCH(xname, xpval) \ | 1578 | #define STAC_CODEC_IO_SWITCH(xname, xpval) \ |
1113 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 1579 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
1114 | .name = xname, \ | 1580 | .name = xname, \ |
@@ -1119,17 +1585,28 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
1119 | .private_value = xpval, \ | 1585 | .private_value = xpval, \ |
1120 | } | 1586 | } |
1121 | 1587 | ||
1588 | #define STAC_CODEC_CLFE_SWITCH(xname, xpval) \ | ||
1589 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1590 | .name = xname, \ | ||
1591 | .index = 0, \ | ||
1592 | .info = stac92xx_clfe_switch_info, \ | ||
1593 | .get = stac92xx_clfe_switch_get, \ | ||
1594 | .put = stac92xx_clfe_switch_put, \ | ||
1595 | .private_value = xpval, \ | ||
1596 | } | ||
1122 | 1597 | ||
1123 | enum { | 1598 | enum { |
1124 | STAC_CTL_WIDGET_VOL, | 1599 | STAC_CTL_WIDGET_VOL, |
1125 | STAC_CTL_WIDGET_MUTE, | 1600 | STAC_CTL_WIDGET_MUTE, |
1126 | STAC_CTL_WIDGET_IO_SWITCH, | 1601 | STAC_CTL_WIDGET_IO_SWITCH, |
1602 | STAC_CTL_WIDGET_CLFE_SWITCH | ||
1127 | }; | 1603 | }; |
1128 | 1604 | ||
1129 | static struct snd_kcontrol_new stac92xx_control_templates[] = { | 1605 | static struct snd_kcontrol_new stac92xx_control_templates[] = { |
1130 | HDA_CODEC_VOLUME(NULL, 0, 0, 0), | 1606 | HDA_CODEC_VOLUME(NULL, 0, 0, 0), |
1131 | HDA_CODEC_MUTE(NULL, 0, 0, 0), | 1607 | HDA_CODEC_MUTE(NULL, 0, 0, 0), |
1132 | STAC_CODEC_IO_SWITCH(NULL, 0), | 1608 | STAC_CODEC_IO_SWITCH(NULL, 0), |
1609 | STAC_CODEC_CLFE_SWITCH(NULL, 0), | ||
1133 | }; | 1610 | }; |
1134 | 1611 | ||
1135 | /* add dynamic controls */ | 1612 | /* add dynamic controls */ |
@@ -1182,7 +1659,8 @@ static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cf | |||
1182 | case 3: | 1659 | case 3: |
1183 | /* add line-in as side */ | 1660 | /* add line-in as side */ |
1184 | if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 3) { | 1661 | if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 3) { |
1185 | cfg->line_out_pins[3] = cfg->input_pins[AUTO_PIN_LINE]; | 1662 | cfg->line_out_pins[cfg->line_outs] = |
1663 | cfg->input_pins[AUTO_PIN_LINE]; | ||
1186 | spec->line_switch = 1; | 1664 | spec->line_switch = 1; |
1187 | cfg->line_outs++; | 1665 | cfg->line_outs++; |
1188 | } | 1666 | } |
@@ -1190,12 +1668,14 @@ static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cf | |||
1190 | case 2: | 1668 | case 2: |
1191 | /* add line-in as clfe and mic as side */ | 1669 | /* add line-in as clfe and mic as side */ |
1192 | if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 2) { | 1670 | if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 2) { |
1193 | cfg->line_out_pins[2] = cfg->input_pins[AUTO_PIN_LINE]; | 1671 | cfg->line_out_pins[cfg->line_outs] = |
1672 | cfg->input_pins[AUTO_PIN_LINE]; | ||
1194 | spec->line_switch = 1; | 1673 | spec->line_switch = 1; |
1195 | cfg->line_outs++; | 1674 | cfg->line_outs++; |
1196 | } | 1675 | } |
1197 | if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 3) { | 1676 | if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 3) { |
1198 | cfg->line_out_pins[3] = cfg->input_pins[AUTO_PIN_MIC]; | 1677 | cfg->line_out_pins[cfg->line_outs] = |
1678 | cfg->input_pins[AUTO_PIN_MIC]; | ||
1199 | spec->mic_switch = 1; | 1679 | spec->mic_switch = 1; |
1200 | cfg->line_outs++; | 1680 | cfg->line_outs++; |
1201 | } | 1681 | } |
@@ -1203,12 +1683,14 @@ static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cf | |||
1203 | case 1: | 1683 | case 1: |
1204 | /* add line-in as surr and mic as clfe */ | 1684 | /* add line-in as surr and mic as clfe */ |
1205 | if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 1) { | 1685 | if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 1) { |
1206 | cfg->line_out_pins[1] = cfg->input_pins[AUTO_PIN_LINE]; | 1686 | cfg->line_out_pins[cfg->line_outs] = |
1687 | cfg->input_pins[AUTO_PIN_LINE]; | ||
1207 | spec->line_switch = 1; | 1688 | spec->line_switch = 1; |
1208 | cfg->line_outs++; | 1689 | cfg->line_outs++; |
1209 | } | 1690 | } |
1210 | if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 2) { | 1691 | if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 2) { |
1211 | cfg->line_out_pins[2] = cfg->input_pins[AUTO_PIN_MIC]; | 1692 | cfg->line_out_pins[cfg->line_outs] = |
1693 | cfg->input_pins[AUTO_PIN_MIC]; | ||
1212 | spec->mic_switch = 1; | 1694 | spec->mic_switch = 1; |
1213 | cfg->line_outs++; | 1695 | cfg->line_outs++; |
1214 | } | 1696 | } |
@@ -1282,8 +1764,8 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, | |||
1282 | spec->multiout.num_dacs++; | 1764 | spec->multiout.num_dacs++; |
1283 | if (conn_len > 1) { | 1765 | if (conn_len > 1) { |
1284 | /* select this DAC in the pin's input mux */ | 1766 | /* select this DAC in the pin's input mux */ |
1285 | snd_hda_codec_write(codec, nid, 0, | 1767 | snd_hda_codec_write_cache(codec, nid, 0, |
1286 | AC_VERB_SET_CONNECT_SEL, j); | 1768 | AC_VERB_SET_CONNECT_SEL, j); |
1287 | 1769 | ||
1288 | } | 1770 | } |
1289 | } | 1771 | } |
@@ -1318,7 +1800,7 @@ static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_ | |||
1318 | } | 1800 | } |
1319 | 1801 | ||
1320 | /* add playback controls from the parsed DAC table */ | 1802 | /* add playback controls from the parsed DAC table */ |
1321 | static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, | 1803 | static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, |
1322 | const struct auto_pin_cfg *cfg) | 1804 | const struct auto_pin_cfg *cfg) |
1323 | { | 1805 | { |
1324 | static const char *chname[4] = { | 1806 | static const char *chname[4] = { |
@@ -1327,6 +1809,10 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, | |||
1327 | hda_nid_t nid; | 1809 | hda_nid_t nid; |
1328 | int i, err; | 1810 | int i, err; |
1329 | 1811 | ||
1812 | struct sigmatel_spec *spec = codec->spec; | ||
1813 | unsigned int wid_caps; | ||
1814 | |||
1815 | |||
1330 | for (i = 0; i < cfg->line_outs; i++) { | 1816 | for (i = 0; i < cfg->line_outs; i++) { |
1331 | if (!spec->multiout.dac_nids[i]) | 1817 | if (!spec->multiout.dac_nids[i]) |
1332 | continue; | 1818 | continue; |
@@ -1341,6 +1827,18 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, | |||
1341 | err = create_controls(spec, "LFE", nid, 2); | 1827 | err = create_controls(spec, "LFE", nid, 2); |
1342 | if (err < 0) | 1828 | if (err < 0) |
1343 | return err; | 1829 | return err; |
1830 | |||
1831 | wid_caps = get_wcaps(codec, nid); | ||
1832 | |||
1833 | if (wid_caps & AC_WCAP_LR_SWAP) { | ||
1834 | err = stac92xx_add_control(spec, | ||
1835 | STAC_CTL_WIDGET_CLFE_SWITCH, | ||
1836 | "Swap Center/LFE Playback Switch", nid); | ||
1837 | |||
1838 | if (err < 0) | ||
1839 | return err; | ||
1840 | } | ||
1841 | |||
1344 | } else { | 1842 | } else { |
1345 | err = create_controls(spec, chname[i], nid, 3); | 1843 | err = create_controls(spec, chname[i], nid, 3); |
1346 | if (err < 0) | 1844 | if (err < 0) |
@@ -1536,9 +2034,9 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const | |||
1536 | * NID lists. Hopefully this won't get confused. | 2034 | * NID lists. Hopefully this won't get confused. |
1537 | */ | 2035 | */ |
1538 | for (i = 0; i < spec->num_muxes; i++) { | 2036 | for (i = 0; i < spec->num_muxes; i++) { |
1539 | snd_hda_codec_write(codec, spec->mux_nids[i], 0, | 2037 | snd_hda_codec_write_cache(codec, spec->mux_nids[i], 0, |
1540 | AC_VERB_SET_CONNECT_SEL, | 2038 | AC_VERB_SET_CONNECT_SEL, |
1541 | imux->items[0].index); | 2039 | imux->items[0].index); |
1542 | } | 2040 | } |
1543 | } | 2041 | } |
1544 | 2042 | ||
@@ -1593,9 +2091,19 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
1593 | if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) | 2091 | if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) |
1594 | return err; | 2092 | return err; |
1595 | 2093 | ||
1596 | if ((err = stac92xx_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || | 2094 | err = stac92xx_auto_create_multi_out_ctls(codec, &spec->autocfg); |
1597 | (err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg)) < 0 || | 2095 | |
1598 | (err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0) | 2096 | if (err < 0) |
2097 | return err; | ||
2098 | |||
2099 | err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg); | ||
2100 | |||
2101 | if (err < 0) | ||
2102 | return err; | ||
2103 | |||
2104 | err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg); | ||
2105 | |||
2106 | if (err < 0) | ||
1599 | return err; | 2107 | return err; |
1600 | 2108 | ||
1601 | if (spec->num_dmics > 0) | 2109 | if (spec->num_dmics > 0) |
@@ -1764,9 +2272,9 @@ static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, | |||
1764 | unsigned int event) | 2272 | unsigned int event) |
1765 | { | 2273 | { |
1766 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) | 2274 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) |
1767 | snd_hda_codec_write(codec, nid, 0, | 2275 | snd_hda_codec_write_cache(codec, nid, 0, |
1768 | AC_VERB_SET_UNSOLICITED_ENABLE, | 2276 | AC_VERB_SET_UNSOLICITED_ENABLE, |
1769 | (AC_USRSP_EN | event)); | 2277 | (AC_USRSP_EN | event)); |
1770 | } | 2278 | } |
1771 | 2279 | ||
1772 | static int stac92xx_init(struct hda_codec *codec) | 2280 | static int stac92xx_init(struct hda_codec *codec) |
@@ -1870,7 +2378,7 @@ static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, | |||
1870 | if (flag & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)) | 2378 | if (flag & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)) |
1871 | pin_ctl &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); | 2379 | pin_ctl &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); |
1872 | 2380 | ||
1873 | snd_hda_codec_write(codec, nid, 0, | 2381 | snd_hda_codec_write_cache(codec, nid, 0, |
1874 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 2382 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
1875 | pin_ctl | flag); | 2383 | pin_ctl | flag); |
1876 | } | 2384 | } |
@@ -1880,7 +2388,7 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, | |||
1880 | { | 2388 | { |
1881 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, | 2389 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, |
1882 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); | 2390 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); |
1883 | snd_hda_codec_write(codec, nid, 0, | 2391 | snd_hda_codec_write_cache(codec, nid, 0, |
1884 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 2392 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
1885 | pin_ctl & ~flag); | 2393 | pin_ctl & ~flag); |
1886 | } | 2394 | } |
@@ -1936,22 +2444,22 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | |||
1936 | } | 2444 | } |
1937 | } | 2445 | } |
1938 | 2446 | ||
1939 | #ifdef CONFIG_PM | 2447 | #ifdef SND_HDA_NEEDS_RESUME |
1940 | static int stac92xx_resume(struct hda_codec *codec) | 2448 | static int stac92xx_resume(struct hda_codec *codec) |
1941 | { | 2449 | { |
1942 | struct sigmatel_spec *spec = codec->spec; | 2450 | struct sigmatel_spec *spec = codec->spec; |
1943 | int i; | ||
1944 | 2451 | ||
1945 | stac92xx_init(codec); | ||
1946 | stac92xx_set_config_regs(codec); | 2452 | stac92xx_set_config_regs(codec); |
1947 | snd_hda_resume_ctls(codec, spec->mixer); | 2453 | snd_hda_sequence_write(codec, spec->init); |
1948 | for (i = 0; i < spec->num_mixers; i++) | 2454 | if (spec->gpio_mute) { |
1949 | snd_hda_resume_ctls(codec, spec->mixers[i]); | 2455 | stac922x_gpio_mute(codec, 0, 0); |
1950 | if (spec->multiout.dig_out_nid) | 2456 | stac922x_gpio_mute(codec, 1, 0); |
1951 | snd_hda_resume_spdif_out(codec); | 2457 | } |
1952 | if (spec->dig_in_nid) | 2458 | snd_hda_codec_resume_amp(codec); |
1953 | snd_hda_resume_spdif_in(codec); | 2459 | snd_hda_codec_resume_cache(codec); |
1954 | 2460 | /* invoke unsolicited event to reset the HP state */ | |
2461 | if (spec->hp_detect) | ||
2462 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | ||
1955 | return 0; | 2463 | return 0; |
1956 | } | 2464 | } |
1957 | #endif | 2465 | #endif |
@@ -1962,7 +2470,7 @@ static struct hda_codec_ops stac92xx_patch_ops = { | |||
1962 | .init = stac92xx_init, | 2470 | .init = stac92xx_init, |
1963 | .free = stac92xx_free, | 2471 | .free = stac92xx_free, |
1964 | .unsol_event = stac92xx_unsol_event, | 2472 | .unsol_event = stac92xx_unsol_event, |
1965 | #ifdef CONFIG_PM | 2473 | #ifdef SND_HDA_NEEDS_RESUME |
1966 | .resume = stac92xx_resume, | 2474 | .resume = stac92xx_resume, |
1967 | #endif | 2475 | #endif |
1968 | }; | 2476 | }; |
@@ -2002,8 +2510,12 @@ static int patch_stac9200(struct hda_codec *codec) | |||
2002 | spec->mux_nids = stac9200_mux_nids; | 2510 | spec->mux_nids = stac9200_mux_nids; |
2003 | spec->num_muxes = 1; | 2511 | spec->num_muxes = 1; |
2004 | spec->num_dmics = 0; | 2512 | spec->num_dmics = 0; |
2513 | spec->num_adcs = 1; | ||
2005 | 2514 | ||
2006 | spec->init = stac9200_core_init; | 2515 | if (spec->board_config == STAC_9200_GATEWAY) |
2516 | spec->init = stac9200_eapd_init; | ||
2517 | else | ||
2518 | spec->init = stac9200_core_init; | ||
2007 | spec->mixer = stac9200_mixer; | 2519 | spec->mixer = stac9200_mixer; |
2008 | 2520 | ||
2009 | err = stac9200_parse_auto_config(codec); | 2521 | err = stac9200_parse_auto_config(codec); |
@@ -2053,12 +2565,13 @@ static int patch_stac925x(struct hda_codec *codec) | |||
2053 | spec->adc_nids = stac925x_adc_nids; | 2565 | spec->adc_nids = stac925x_adc_nids; |
2054 | spec->mux_nids = stac925x_mux_nids; | 2566 | spec->mux_nids = stac925x_mux_nids; |
2055 | spec->num_muxes = 1; | 2567 | spec->num_muxes = 1; |
2568 | spec->num_adcs = 1; | ||
2056 | switch (codec->vendor_id) { | 2569 | switch (codec->vendor_id) { |
2057 | case 0x83847632: /* STAC9202 */ | 2570 | case 0x83847632: /* STAC9202 */ |
2058 | case 0x83847633: /* STAC9202D */ | 2571 | case 0x83847633: /* STAC9202D */ |
2059 | case 0x83847636: /* STAC9251 */ | 2572 | case 0x83847636: /* STAC9251 */ |
2060 | case 0x83847637: /* STAC9251D */ | 2573 | case 0x83847637: /* STAC9251D */ |
2061 | spec->num_dmics = 1; | 2574 | spec->num_dmics = STAC925X_NUM_DMICS; |
2062 | spec->dmic_nids = stac925x_dmic_nids; | 2575 | spec->dmic_nids = stac925x_dmic_nids; |
2063 | break; | 2576 | break; |
2064 | default: | 2577 | default: |
@@ -2156,6 +2669,7 @@ static int patch_stac922x(struct hda_codec *codec) | |||
2156 | spec->adc_nids = stac922x_adc_nids; | 2669 | spec->adc_nids = stac922x_adc_nids; |
2157 | spec->mux_nids = stac922x_mux_nids; | 2670 | spec->mux_nids = stac922x_mux_nids; |
2158 | spec->num_muxes = ARRAY_SIZE(stac922x_mux_nids); | 2671 | spec->num_muxes = ARRAY_SIZE(stac922x_mux_nids); |
2672 | spec->num_adcs = ARRAY_SIZE(stac922x_adc_nids); | ||
2159 | spec->num_dmics = 0; | 2673 | spec->num_dmics = 0; |
2160 | 2674 | ||
2161 | spec->init = stac922x_core_init; | 2675 | spec->init = stac922x_core_init; |
@@ -2224,22 +2738,25 @@ static int patch_stac927x(struct hda_codec *codec) | |||
2224 | spec->adc_nids = stac927x_adc_nids; | 2738 | spec->adc_nids = stac927x_adc_nids; |
2225 | spec->mux_nids = stac927x_mux_nids; | 2739 | spec->mux_nids = stac927x_mux_nids; |
2226 | spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); | 2740 | spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); |
2741 | spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids); | ||
2227 | spec->num_dmics = 0; | 2742 | spec->num_dmics = 0; |
2228 | spec->init = d965_core_init; | 2743 | spec->init = d965_core_init; |
2229 | spec->mixer = stac9227_mixer; | 2744 | spec->mixer = stac927x_mixer; |
2230 | break; | 2745 | break; |
2231 | case STAC_D965_5ST: | 2746 | case STAC_D965_5ST: |
2232 | spec->adc_nids = stac927x_adc_nids; | 2747 | spec->adc_nids = stac927x_adc_nids; |
2233 | spec->mux_nids = stac927x_mux_nids; | 2748 | spec->mux_nids = stac927x_mux_nids; |
2234 | spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); | 2749 | spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); |
2750 | spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids); | ||
2235 | spec->num_dmics = 0; | 2751 | spec->num_dmics = 0; |
2236 | spec->init = d965_core_init; | 2752 | spec->init = d965_core_init; |
2237 | spec->mixer = stac9227_mixer; | 2753 | spec->mixer = stac927x_mixer; |
2238 | break; | 2754 | break; |
2239 | default: | 2755 | default: |
2240 | spec->adc_nids = stac927x_adc_nids; | 2756 | spec->adc_nids = stac927x_adc_nids; |
2241 | spec->mux_nids = stac927x_mux_nids; | 2757 | spec->mux_nids = stac927x_mux_nids; |
2242 | spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); | 2758 | spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); |
2759 | spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids); | ||
2243 | spec->num_dmics = 0; | 2760 | spec->num_dmics = 0; |
2244 | spec->init = stac927x_core_init; | 2761 | spec->init = stac927x_core_init; |
2245 | spec->mixer = stac927x_mixer; | 2762 | spec->mixer = stac927x_mixer; |
@@ -2247,7 +2764,8 @@ static int patch_stac927x(struct hda_codec *codec) | |||
2247 | 2764 | ||
2248 | spec->multiout.dac_nids = spec->dac_nids; | 2765 | spec->multiout.dac_nids = spec->dac_nids; |
2249 | /* GPIO0 High = Enable EAPD */ | 2766 | /* GPIO0 High = Enable EAPD */ |
2250 | stac92xx_enable_gpio_mask(codec, 0x00000001, 0x00000001); | 2767 | spec->gpio_mask = spec->gpio_data = 0x00000001; |
2768 | stac92xx_enable_gpio_mask(codec); | ||
2251 | 2769 | ||
2252 | err = stac92xx_parse_auto_config(codec, 0x1e, 0x20); | 2770 | err = stac92xx_parse_auto_config(codec, 0x1e, 0x20); |
2253 | if (!err) { | 2771 | if (!err) { |
@@ -2272,7 +2790,7 @@ static int patch_stac927x(struct hda_codec *codec) | |||
2272 | static int patch_stac9205(struct hda_codec *codec) | 2790 | static int patch_stac9205(struct hda_codec *codec) |
2273 | { | 2791 | { |
2274 | struct sigmatel_spec *spec; | 2792 | struct sigmatel_spec *spec; |
2275 | int err, gpio_mask, gpio_data; | 2793 | int err; |
2276 | 2794 | ||
2277 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 2795 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
2278 | if (spec == NULL) | 2796 | if (spec == NULL) |
@@ -2299,10 +2817,11 @@ static int patch_stac9205(struct hda_codec *codec) | |||
2299 | } | 2817 | } |
2300 | 2818 | ||
2301 | spec->adc_nids = stac9205_adc_nids; | 2819 | spec->adc_nids = stac9205_adc_nids; |
2820 | spec->num_adcs = ARRAY_SIZE(stac9205_adc_nids); | ||
2302 | spec->mux_nids = stac9205_mux_nids; | 2821 | spec->mux_nids = stac9205_mux_nids; |
2303 | spec->num_muxes = ARRAY_SIZE(stac9205_mux_nids); | 2822 | spec->num_muxes = ARRAY_SIZE(stac9205_mux_nids); |
2304 | spec->dmic_nids = stac9205_dmic_nids; | 2823 | spec->dmic_nids = stac9205_dmic_nids; |
2305 | spec->num_dmics = ARRAY_SIZE(stac9205_dmic_nids); | 2824 | spec->num_dmics = STAC9205_NUM_DMICS; |
2306 | spec->dmux_nid = 0x1d; | 2825 | spec->dmux_nid = 0x1d; |
2307 | 2826 | ||
2308 | spec->init = stac9205_core_init; | 2827 | spec->init = stac9205_core_init; |
@@ -2310,20 +2829,25 @@ static int patch_stac9205(struct hda_codec *codec) | |||
2310 | 2829 | ||
2311 | spec->multiout.dac_nids = spec->dac_nids; | 2830 | spec->multiout.dac_nids = spec->dac_nids; |
2312 | 2831 | ||
2313 | if (spec->board_config == STAC_M43xx) { | 2832 | switch (spec->board_config){ |
2833 | case STAC_9205_DELL_M43: | ||
2314 | /* Enable SPDIF in/out */ | 2834 | /* Enable SPDIF in/out */ |
2315 | stac92xx_set_config_reg(codec, 0x1f, 0x01441030); | 2835 | stac92xx_set_config_reg(codec, 0x1f, 0x01441030); |
2316 | stac92xx_set_config_reg(codec, 0x20, 0x1c410030); | 2836 | stac92xx_set_config_reg(codec, 0x20, 0x1c410030); |
2317 | 2837 | ||
2318 | gpio_mask = 0x00000007; /* GPIO0-2 */ | 2838 | spec->gpio_mask = 0x00000007; /* GPIO0-2 */ |
2319 | /* GPIO0 High = EAPD, GPIO1 Low = DRM, | 2839 | /* GPIO0 High = EAPD, GPIO1 Low = DRM, |
2320 | * GPIO2 High = Headphone Mute | 2840 | * GPIO2 High = Headphone Mute |
2321 | */ | 2841 | */ |
2322 | gpio_data = 0x00000005; | 2842 | spec->gpio_data = 0x00000005; |
2323 | } else | 2843 | break; |
2324 | gpio_mask = gpio_data = 0x00000001; /* GPIO0 High = EAPD */ | 2844 | default: |
2845 | /* GPIO0 High = EAPD */ | ||
2846 | spec->gpio_mask = spec->gpio_data = 0x00000001; | ||
2847 | break; | ||
2848 | } | ||
2325 | 2849 | ||
2326 | stac92xx_enable_gpio_mask(codec, gpio_mask, gpio_data); | 2850 | stac92xx_enable_gpio_mask(codec); |
2327 | err = stac92xx_parse_auto_config(codec, 0x1f, 0x20); | 2851 | err = stac92xx_parse_auto_config(codec, 0x1f, 0x20); |
2328 | if (!err) { | 2852 | if (!err) { |
2329 | if (spec->board_config < 0) { | 2853 | if (spec->board_config < 0) { |
@@ -2355,7 +2879,7 @@ static hda_nid_t vaio_adcs[] = { 0x8 /*,0x6*/ }; | |||
2355 | static hda_nid_t vaio_mux_nids[] = { 0x15 }; | 2879 | static hda_nid_t vaio_mux_nids[] = { 0x15 }; |
2356 | 2880 | ||
2357 | static struct hda_input_mux vaio_mux = { | 2881 | static struct hda_input_mux vaio_mux = { |
2358 | .num_items = 2, | 2882 | .num_items = 3, |
2359 | .items = { | 2883 | .items = { |
2360 | /* { "HP", 0x0 }, */ | 2884 | /* { "HP", 0x0 }, */ |
2361 | { "Mic Jack", 0x1 }, | 2885 | { "Mic Jack", 0x1 }, |
@@ -2366,6 +2890,7 @@ static struct hda_input_mux vaio_mux = { | |||
2366 | 2890 | ||
2367 | static struct hda_verb vaio_init[] = { | 2891 | static struct hda_verb vaio_init[] = { |
2368 | {0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */ | 2892 | {0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */ |
2893 | {0x0a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | STAC_HP_EVENT}, | ||
2369 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */ | 2894 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */ |
2370 | {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */ | 2895 | {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */ |
2371 | {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */ | 2896 | {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */ |
@@ -2397,61 +2922,28 @@ static struct hda_verb vaio_ar_init[] = { | |||
2397 | }; | 2922 | }; |
2398 | 2923 | ||
2399 | /* bind volumes of both NID 0x02 and 0x05 */ | 2924 | /* bind volumes of both NID 0x02 and 0x05 */ |
2400 | static int vaio_master_vol_put(struct snd_kcontrol *kcontrol, | 2925 | static struct hda_bind_ctls vaio_bind_master_vol = { |
2401 | struct snd_ctl_elem_value *ucontrol) | 2926 | .ops = &snd_hda_bind_vol, |
2402 | { | 2927 | .values = { |
2403 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 2928 | HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), |
2404 | long *valp = ucontrol->value.integer.value; | 2929 | HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT), |
2405 | int change; | 2930 | 0 |
2406 | 2931 | }, | |
2407 | change = snd_hda_codec_amp_update(codec, 0x02, 0, HDA_OUTPUT, 0, | 2932 | }; |
2408 | 0x7f, valp[0] & 0x7f); | ||
2409 | change |= snd_hda_codec_amp_update(codec, 0x02, 1, HDA_OUTPUT, 0, | ||
2410 | 0x7f, valp[1] & 0x7f); | ||
2411 | snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0, | ||
2412 | 0x7f, valp[0] & 0x7f); | ||
2413 | snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0, | ||
2414 | 0x7f, valp[1] & 0x7f); | ||
2415 | return change; | ||
2416 | } | ||
2417 | 2933 | ||
2418 | /* bind volumes of both NID 0x02 and 0x05 */ | 2934 | /* bind volumes of both NID 0x02 and 0x05 */ |
2419 | static int vaio_master_sw_put(struct snd_kcontrol *kcontrol, | 2935 | static struct hda_bind_ctls vaio_bind_master_sw = { |
2420 | struct snd_ctl_elem_value *ucontrol) | 2936 | .ops = &snd_hda_bind_sw, |
2421 | { | 2937 | .values = { |
2422 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 2938 | HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), |
2423 | long *valp = ucontrol->value.integer.value; | 2939 | HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT), |
2424 | int change; | 2940 | 0, |
2425 | 2941 | }, | |
2426 | change = snd_hda_codec_amp_update(codec, 0x02, 0, HDA_OUTPUT, 0, | 2942 | }; |
2427 | 0x80, (valp[0] ? 0 : 0x80)); | ||
2428 | change |= snd_hda_codec_amp_update(codec, 0x02, 1, HDA_OUTPUT, 0, | ||
2429 | 0x80, (valp[1] ? 0 : 0x80)); | ||
2430 | snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0, | ||
2431 | 0x80, (valp[0] ? 0 : 0x80)); | ||
2432 | snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0, | ||
2433 | 0x80, (valp[1] ? 0 : 0x80)); | ||
2434 | return change; | ||
2435 | } | ||
2436 | 2943 | ||
2437 | static struct snd_kcontrol_new vaio_mixer[] = { | 2944 | static struct snd_kcontrol_new vaio_mixer[] = { |
2438 | { | 2945 | HDA_BIND_VOL("Master Playback Volume", &vaio_bind_master_vol), |
2439 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2946 | HDA_BIND_SW("Master Playback Switch", &vaio_bind_master_sw), |
2440 | .name = "Master Playback Volume", | ||
2441 | .info = snd_hda_mixer_amp_volume_info, | ||
2442 | .get = snd_hda_mixer_amp_volume_get, | ||
2443 | .put = vaio_master_vol_put, | ||
2444 | .tlv = { .c = snd_hda_mixer_amp_tlv }, | ||
2445 | .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), | ||
2446 | }, | ||
2447 | { | ||
2448 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2449 | .name = "Master Playback Switch", | ||
2450 | .info = snd_hda_mixer_amp_switch_info, | ||
2451 | .get = snd_hda_mixer_amp_switch_get, | ||
2452 | .put = vaio_master_sw_put, | ||
2453 | .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), | ||
2454 | }, | ||
2455 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ | 2947 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ |
2456 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), | 2948 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), |
2457 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), | 2949 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), |
@@ -2467,22 +2959,8 @@ static struct snd_kcontrol_new vaio_mixer[] = { | |||
2467 | }; | 2959 | }; |
2468 | 2960 | ||
2469 | static struct snd_kcontrol_new vaio_ar_mixer[] = { | 2961 | static struct snd_kcontrol_new vaio_ar_mixer[] = { |
2470 | { | 2962 | HDA_BIND_VOL("Master Playback Volume", &vaio_bind_master_vol), |
2471 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2963 | HDA_BIND_SW("Master Playback Switch", &vaio_bind_master_sw), |
2472 | .name = "Master Playback Volume", | ||
2473 | .info = snd_hda_mixer_amp_volume_info, | ||
2474 | .get = snd_hda_mixer_amp_volume_get, | ||
2475 | .put = vaio_master_vol_put, | ||
2476 | .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), | ||
2477 | }, | ||
2478 | { | ||
2479 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2480 | .name = "Master Playback Switch", | ||
2481 | .info = snd_hda_mixer_amp_switch_info, | ||
2482 | .get = snd_hda_mixer_amp_switch_get, | ||
2483 | .put = vaio_master_sw_put, | ||
2484 | .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), | ||
2485 | }, | ||
2486 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ | 2964 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ |
2487 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), | 2965 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), |
2488 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), | 2966 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), |
@@ -2504,6 +2982,49 @@ static struct hda_codec_ops stac9872_patch_ops = { | |||
2504 | .build_pcms = stac92xx_build_pcms, | 2982 | .build_pcms = stac92xx_build_pcms, |
2505 | .init = stac92xx_init, | 2983 | .init = stac92xx_init, |
2506 | .free = stac92xx_free, | 2984 | .free = stac92xx_free, |
2985 | #ifdef SND_HDA_NEEDS_RESUME | ||
2986 | .resume = stac92xx_resume, | ||
2987 | #endif | ||
2988 | }; | ||
2989 | |||
2990 | static int stac9872_vaio_init(struct hda_codec *codec) | ||
2991 | { | ||
2992 | int err; | ||
2993 | |||
2994 | err = stac92xx_init(codec); | ||
2995 | if (err < 0) | ||
2996 | return err; | ||
2997 | if (codec->patch_ops.unsol_event) | ||
2998 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | ||
2999 | return 0; | ||
3000 | } | ||
3001 | |||
3002 | static void stac9872_vaio_hp_detect(struct hda_codec *codec, unsigned int res) | ||
3003 | { | ||
3004 | if (get_pin_presence(codec, 0x0a)) { | ||
3005 | stac92xx_reset_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN); | ||
3006 | stac92xx_set_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN); | ||
3007 | } else { | ||
3008 | stac92xx_reset_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN); | ||
3009 | stac92xx_set_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN); | ||
3010 | } | ||
3011 | } | ||
3012 | |||
3013 | static void stac9872_vaio_unsol_event(struct hda_codec *codec, unsigned int res) | ||
3014 | { | ||
3015 | switch (res >> 26) { | ||
3016 | case STAC_HP_EVENT: | ||
3017 | stac9872_vaio_hp_detect(codec, res); | ||
3018 | break; | ||
3019 | } | ||
3020 | } | ||
3021 | |||
3022 | static struct hda_codec_ops stac9872_vaio_patch_ops = { | ||
3023 | .build_controls = stac92xx_build_controls, | ||
3024 | .build_pcms = stac92xx_build_pcms, | ||
3025 | .init = stac9872_vaio_init, | ||
3026 | .free = stac92xx_free, | ||
3027 | .unsol_event = stac9872_vaio_unsol_event, | ||
2507 | #ifdef CONFIG_PM | 3028 | #ifdef CONFIG_PM |
2508 | .resume = stac92xx_resume, | 3029 | .resume = stac92xx_resume, |
2509 | #endif | 3030 | #endif |
@@ -2564,6 +3085,7 @@ static int patch_stac9872(struct hda_codec *codec) | |||
2564 | spec->adc_nids = vaio_adcs; | 3085 | spec->adc_nids = vaio_adcs; |
2565 | spec->input_mux = &vaio_mux; | 3086 | spec->input_mux = &vaio_mux; |
2566 | spec->mux_nids = vaio_mux_nids; | 3087 | spec->mux_nids = vaio_mux_nids; |
3088 | codec->patch_ops = stac9872_vaio_patch_ops; | ||
2567 | break; | 3089 | break; |
2568 | 3090 | ||
2569 | case CXD9872AKD_VAIO: | 3091 | case CXD9872AKD_VAIO: |
@@ -2577,10 +3099,10 @@ static int patch_stac9872(struct hda_codec *codec) | |||
2577 | spec->adc_nids = vaio_adcs; | 3099 | spec->adc_nids = vaio_adcs; |
2578 | spec->input_mux = &vaio_mux; | 3100 | spec->input_mux = &vaio_mux; |
2579 | spec->mux_nids = vaio_mux_nids; | 3101 | spec->mux_nids = vaio_mux_nids; |
3102 | codec->patch_ops = stac9872_patch_ops; | ||
2580 | break; | 3103 | break; |
2581 | } | 3104 | } |
2582 | 3105 | ||
2583 | codec->patch_ops = stac9872_patch_ops; | ||
2584 | return 0; | 3106 | return 0; |
2585 | } | 3107 | } |
2586 | 3108 | ||
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index ba32d1e52cb8..33b5e1ffa817 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -115,6 +115,10 @@ struct via_spec { | |||
115 | struct snd_kcontrol_new *kctl_alloc; | 115 | struct snd_kcontrol_new *kctl_alloc; |
116 | struct hda_input_mux private_imux; | 116 | struct hda_input_mux private_imux; |
117 | hda_nid_t private_dac_nids[4]; | 117 | hda_nid_t private_dac_nids[4]; |
118 | |||
119 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
120 | struct hda_loopback_check loopback; | ||
121 | #endif | ||
118 | }; | 122 | }; |
119 | 123 | ||
120 | static hda_nid_t vt1708_adc_nids[2] = { | 124 | static hda_nid_t vt1708_adc_nids[2] = { |
@@ -305,15 +309,15 @@ static struct hda_verb vt1708_volume_init_verbs[] = { | |||
305 | {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 309 | {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
306 | 310 | ||
307 | 311 | ||
308 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 312 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
309 | * mixer widget | 313 | * mixer widget |
310 | */ | 314 | */ |
311 | /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */ | 315 | /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */ |
312 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 316 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* master */ |
313 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 317 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
314 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 318 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
315 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 319 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
316 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 320 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
317 | 321 | ||
318 | /* | 322 | /* |
319 | * Set up output mixers (0x19 - 0x1b) | 323 | * Set up output mixers (0x19 - 0x1b) |
@@ -543,24 +547,11 @@ static int via_init(struct hda_codec *codec) | |||
543 | return 0; | 547 | return 0; |
544 | } | 548 | } |
545 | 549 | ||
546 | #ifdef CONFIG_PM | 550 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
547 | /* | 551 | static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid) |
548 | * resume | ||
549 | */ | ||
550 | static int via_resume(struct hda_codec *codec) | ||
551 | { | 552 | { |
552 | struct via_spec *spec = codec->spec; | 553 | struct via_spec *spec = codec->spec; |
553 | int i; | 554 | return snd_hda_check_amp_list_power(codec, &spec->loopback, nid); |
554 | |||
555 | via_init(codec); | ||
556 | for (i = 0; i < spec->num_mixers; i++) | ||
557 | snd_hda_resume_ctls(codec, spec->mixers[i]); | ||
558 | if (spec->multiout.dig_out_nid) | ||
559 | snd_hda_resume_spdif_out(codec); | ||
560 | if (spec->dig_in_nid) | ||
561 | snd_hda_resume_spdif_in(codec); | ||
562 | |||
563 | return 0; | ||
564 | } | 555 | } |
565 | #endif | 556 | #endif |
566 | 557 | ||
@@ -571,8 +562,8 @@ static struct hda_codec_ops via_patch_ops = { | |||
571 | .build_pcms = via_build_pcms, | 562 | .build_pcms = via_build_pcms, |
572 | .init = via_init, | 563 | .init = via_init, |
573 | .free = via_free, | 564 | .free = via_free, |
574 | #ifdef CONFIG_PM | 565 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
575 | .resume = via_resume, | 566 | .check_power_status = via_check_power_status, |
576 | #endif | 567 | #endif |
577 | }; | 568 | }; |
578 | 569 | ||
@@ -762,6 +753,16 @@ static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec, | |||
762 | return 0; | 753 | return 0; |
763 | } | 754 | } |
764 | 755 | ||
756 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
757 | static struct hda_amp_list vt1708_loopbacks[] = { | ||
758 | { 0x17, HDA_INPUT, 1 }, | ||
759 | { 0x17, HDA_INPUT, 2 }, | ||
760 | { 0x17, HDA_INPUT, 3 }, | ||
761 | { 0x17, HDA_INPUT, 4 }, | ||
762 | { } /* end */ | ||
763 | }; | ||
764 | #endif | ||
765 | |||
765 | static int vt1708_parse_auto_config(struct hda_codec *codec) | 766 | static int vt1708_parse_auto_config(struct hda_codec *codec) |
766 | { | 767 | { |
767 | struct via_spec *spec = codec->spec; | 768 | struct via_spec *spec = codec->spec; |
@@ -855,6 +856,9 @@ static int patch_vt1708(struct hda_codec *codec) | |||
855 | codec->patch_ops = via_patch_ops; | 856 | codec->patch_ops = via_patch_ops; |
856 | 857 | ||
857 | codec->patch_ops.init = via_auto_init; | 858 | codec->patch_ops.init = via_auto_init; |
859 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
860 | spec->loopback.amplist = vt1708_loopbacks; | ||
861 | #endif | ||
858 | 862 | ||
859 | return 0; | 863 | return 0; |
860 | } | 864 | } |
@@ -895,15 +899,15 @@ static struct hda_verb vt1709_10ch_volume_init_verbs[] = { | |||
895 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 899 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
896 | 900 | ||
897 | 901 | ||
898 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 902 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
899 | * mixer widget | 903 | * mixer widget |
900 | */ | 904 | */ |
901 | /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */ | 905 | /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */ |
902 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 906 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* unmute master */ |
903 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 907 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
904 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 908 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
905 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 909 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
906 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, | 910 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
907 | 911 | ||
908 | /* | 912 | /* |
909 | * Set up output selector (0x1a, 0x1b, 0x29) | 913 | * Set up output selector (0x1a, 0x1b, 0x29) |
@@ -1251,6 +1255,16 @@ static int vt1709_parse_auto_config(struct hda_codec *codec) | |||
1251 | return 1; | 1255 | return 1; |
1252 | } | 1256 | } |
1253 | 1257 | ||
1258 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1259 | static struct hda_amp_list vt1709_loopbacks[] = { | ||
1260 | { 0x18, HDA_INPUT, 1 }, | ||
1261 | { 0x18, HDA_INPUT, 2 }, | ||
1262 | { 0x18, HDA_INPUT, 3 }, | ||
1263 | { 0x18, HDA_INPUT, 4 }, | ||
1264 | { } /* end */ | ||
1265 | }; | ||
1266 | #endif | ||
1267 | |||
1254 | static int patch_vt1709_10ch(struct hda_codec *codec) | 1268 | static int patch_vt1709_10ch(struct hda_codec *codec) |
1255 | { | 1269 | { |
1256 | struct via_spec *spec; | 1270 | struct via_spec *spec; |
@@ -1293,6 +1307,9 @@ static int patch_vt1709_10ch(struct hda_codec *codec) | |||
1293 | codec->patch_ops = via_patch_ops; | 1307 | codec->patch_ops = via_patch_ops; |
1294 | 1308 | ||
1295 | codec->patch_ops.init = via_auto_init; | 1309 | codec->patch_ops.init = via_auto_init; |
1310 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1311 | spec->loopback.amplist = vt1709_loopbacks; | ||
1312 | #endif | ||
1296 | 1313 | ||
1297 | return 0; | 1314 | return 0; |
1298 | } | 1315 | } |
@@ -1383,6 +1400,9 @@ static int patch_vt1709_6ch(struct hda_codec *codec) | |||
1383 | codec->patch_ops = via_patch_ops; | 1400 | codec->patch_ops = via_patch_ops; |
1384 | 1401 | ||
1385 | codec->patch_ops.init = via_auto_init; | 1402 | codec->patch_ops.init = via_auto_init; |
1403 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
1404 | spec->loopback.amplist = vt1709_loopbacks; | ||
1405 | #endif | ||
1386 | 1406 | ||
1387 | return 0; | 1407 | return 0; |
1388 | } | 1408 | } |
diff --git a/sound/pci/ice1712/Makefile b/sound/pci/ice1712/Makefile index 6efdd62f6837..65ce66adba5a 100644 --- a/sound/pci/ice1712/Makefile +++ b/sound/pci/ice1712/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-ice17xx-ak4xxx-objs := ak4xxx.o | 6 | snd-ice17xx-ak4xxx-objs := ak4xxx.o |
diff --git a/sound/pci/ice1712/ak4xxx.c b/sound/pci/ice1712/ak4xxx.c index ab00cce2c39f..a1aba0d7d0e4 100644 --- a/sound/pci/ice1712/ak4xxx.c +++ b/sound/pci/ice1712/ak4xxx.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * AK4524 / AK4528 / AK4529 / AK4355 / AK4381 interface | 4 | * AK4524 / AK4528 / AK4529 / AK4355 / AK4381 interface |
5 | * | 5 | * |
6 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 6 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
@@ -30,7 +30,7 @@ | |||
30 | #include <sound/initval.h> | 30 | #include <sound/initval.h> |
31 | #include "ice1712.h" | 31 | #include "ice1712.h" |
32 | 32 | ||
33 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 33 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
34 | MODULE_DESCRIPTION("ICEnsemble ICE17xx <-> AK4xxx AD/DA chip interface"); | 34 | MODULE_DESCRIPTION("ICEnsemble ICE17xx <-> AK4xxx AD/DA chip interface"); |
35 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
36 | 36 | ||
diff --git a/sound/pci/ice1712/amp.c b/sound/pci/ice1712/amp.c index 44bbb630b949..6e13d758bb5d 100644 --- a/sound/pci/ice1712/amp.c +++ b/sound/pci/ice1712/amp.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Lowlevel functions for Advanced Micro Peripherals Ltd AUDIO2000 | 4 | * Lowlevel functions for Advanced Micro Peripherals Ltd AUDIO2000 |
5 | * | 5 | * |
6 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 6 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
diff --git a/sound/pci/ice1712/amp.h b/sound/pci/ice1712/amp.h index a0fc89b48122..bf81d30d9150 100644 --- a/sound/pci/ice1712/amp.h +++ b/sound/pci/ice1712/amp.h | |||
@@ -6,7 +6,7 @@ | |||
6 | * | 6 | * |
7 | * Lowlevel functions for Advanced Micro Peripherals Ltd AUDIO2000 | 7 | * Lowlevel functions for Advanced Micro Peripherals Ltd AUDIO2000 |
8 | * | 8 | * |
9 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 9 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License as published by | 12 | * it under the terms of the GNU General Public License as published by |
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c index 66bacde1ead3..ec0699c89952 100644 --- a/sound/pci/ice1712/aureon.c +++ b/sound/pci/ice1712/aureon.c | |||
@@ -394,7 +394,7 @@ static int aureon_ac97_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ele | |||
394 | /* | 394 | /* |
395 | * AC'97 mute controls | 395 | * AC'97 mute controls |
396 | */ | 396 | */ |
397 | #define aureon_ac97_mute_info aureon_mono_bool_info | 397 | #define aureon_ac97_mute_info snd_ctl_boolean_mono_info |
398 | 398 | ||
399 | static int aureon_ac97_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 399 | static int aureon_ac97_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
400 | { | 400 | { |
@@ -430,7 +430,7 @@ static int aureon_ac97_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el | |||
430 | /* | 430 | /* |
431 | * AC'97 mute controls | 431 | * AC'97 mute controls |
432 | */ | 432 | */ |
433 | #define aureon_ac97_micboost_info aureon_mono_bool_info | 433 | #define aureon_ac97_micboost_info snd_ctl_boolean_mono_info |
434 | 434 | ||
435 | static int aureon_ac97_micboost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 435 | static int aureon_ac97_micboost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
436 | { | 436 | { |
@@ -621,19 +621,12 @@ static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val) | |||
621 | 621 | ||
622 | /* | 622 | /* |
623 | */ | 623 | */ |
624 | static int aureon_mono_bool_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo) | 624 | #define aureon_mono_bool_info snd_ctl_boolean_mono_info |
625 | { | ||
626 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
627 | uinfo->count = 1; | ||
628 | uinfo->value.integer.min = 0; | ||
629 | uinfo->value.integer.max = 1; | ||
630 | return 0; | ||
631 | } | ||
632 | 625 | ||
633 | /* | 626 | /* |
634 | * AC'97 master playback mute controls (Mute on WM8770 chip) | 627 | * AC'97 master playback mute controls (Mute on WM8770 chip) |
635 | */ | 628 | */ |
636 | #define aureon_ac97_mmute_info aureon_mono_bool_info | 629 | #define aureon_ac97_mmute_info snd_ctl_boolean_mono_info |
637 | 630 | ||
638 | static int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 631 | static int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
639 | { | 632 | { |
@@ -708,7 +701,7 @@ static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned sho | |||
708 | /* | 701 | /* |
709 | * DAC mute control | 702 | * DAC mute control |
710 | */ | 703 | */ |
711 | #define wm_pcm_mute_info aureon_mono_bool_info | 704 | #define wm_pcm_mute_info snd_ctl_boolean_mono_info |
712 | 705 | ||
713 | static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 706 | static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
714 | { | 707 | { |
@@ -879,13 +872,7 @@ static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value | |||
879 | /* | 872 | /* |
880 | * WM8770 master mute control | 873 | * WM8770 master mute control |
881 | */ | 874 | */ |
882 | static int wm_master_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { | 875 | #define wm_master_mute_info snd_ctl_boolean_stereo_info |
883 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
884 | uinfo->count = 2; | ||
885 | uinfo->value.integer.min = 0; | ||
886 | uinfo->value.integer.max = 1; | ||
887 | return 0; | ||
888 | } | ||
889 | 876 | ||
890 | static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 877 | static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
891 | { | 878 | { |
@@ -969,14 +956,7 @@ static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val | |||
969 | /* | 956 | /* |
970 | * ADC mute control | 957 | * ADC mute control |
971 | */ | 958 | */ |
972 | static int wm_adc_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 959 | #define wm_adc_mute_info snd_ctl_boolean_stereo_info |
973 | { | ||
974 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
975 | uinfo->count = 2; | ||
976 | uinfo->value.integer.min = 0; | ||
977 | uinfo->value.integer.max = 1; | ||
978 | return 0; | ||
979 | } | ||
980 | 960 | ||
981 | static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 961 | static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
982 | { | 962 | { |
@@ -1210,12 +1190,7 @@ static int aureon_cs8415_rate_get (struct snd_kcontrol *kcontrol, struct snd_ctl | |||
1210 | /* | 1190 | /* |
1211 | * CS8415A Mute | 1191 | * CS8415A Mute |
1212 | */ | 1192 | */ |
1213 | static int aureon_cs8415_mute_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1193 | #define aureon_cs8415_mute_info snd_ctl_boolean_mono_info |
1214 | { | ||
1215 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1216 | uinfo->count = 1; | ||
1217 | return 0; | ||
1218 | } | ||
1219 | 1194 | ||
1220 | static int aureon_cs8415_mute_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1195 | static int aureon_cs8415_mute_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1221 | { | 1196 | { |
@@ -1316,7 +1291,7 @@ static int aureon_get_headphone_amp(struct snd_ice1712 *ice) | |||
1316 | return ( tmp & AUREON_HP_SEL )!= 0; | 1291 | return ( tmp & AUREON_HP_SEL )!= 0; |
1317 | } | 1292 | } |
1318 | 1293 | ||
1319 | #define aureon_hpamp_info aureon_mono_bool_info | 1294 | #define aureon_hpamp_info snd_ctl_boolean_mono_info |
1320 | 1295 | ||
1321 | static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1296 | static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1322 | { | 1297 | { |
@@ -1338,7 +1313,7 @@ static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v | |||
1338 | * Deemphasis | 1313 | * Deemphasis |
1339 | */ | 1314 | */ |
1340 | 1315 | ||
1341 | #define aureon_deemp_info aureon_mono_bool_info | 1316 | #define aureon_deemp_info snd_ctl_boolean_mono_info |
1342 | 1317 | ||
1343 | static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1318 | static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1344 | { | 1319 | { |
diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c index af659800c9b0..371f78461db4 100644 --- a/sound/pci/ice1712/delta.c +++ b/sound/pci/ice1712/delta.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Lowlevel functions for M-Audio Delta 1010, 44, 66, Dio2496, Audiophile | 4 | * Lowlevel functions for M-Audio Delta 1010, 44, 66, Dio2496, Audiophile |
5 | * Digigram VX442 | 5 | * Digigram VX442 |
6 | * | 6 | * |
7 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 7 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by | 10 | * it under the terms of the GNU General Public License as published by |
@@ -393,15 +393,8 @@ static void delta_setup_spdif(struct snd_ice1712 *ice, int rate) | |||
393 | snd_ice1712_delta_cs8403_spdif_write(ice, tmp); | 393 | snd_ice1712_delta_cs8403_spdif_write(ice, tmp); |
394 | } | 394 | } |
395 | 395 | ||
396 | static int snd_ice1712_delta1010lt_wordclock_status_info(struct snd_kcontrol *kcontrol, | 396 | #define snd_ice1712_delta1010lt_wordclock_status_info \ |
397 | struct snd_ctl_elem_info *uinfo) | 397 | snd_ctl_boolean_mono_info |
398 | { | ||
399 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
400 | uinfo->count = 1; | ||
401 | uinfo->value.integer.min = 0; | ||
402 | uinfo->value.integer.max = 1; | ||
403 | return 0; | ||
404 | } | ||
405 | 398 | ||
406 | static int snd_ice1712_delta1010lt_wordclock_status_get(struct snd_kcontrol *kcontrol, | 399 | static int snd_ice1712_delta1010lt_wordclock_status_get(struct snd_kcontrol *kcontrol, |
407 | struct snd_ctl_elem_value *ucontrol) | 400 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/ice1712/delta.h b/sound/pci/ice1712/delta.h index 2697156607e4..26ea05a32f56 100644 --- a/sound/pci/ice1712/delta.h +++ b/sound/pci/ice1712/delta.h | |||
@@ -7,7 +7,7 @@ | |||
7 | * Lowlevel functions for M-Audio Delta 1010, 44, 66, Dio2496, Audiophile | 7 | * Lowlevel functions for M-Audio Delta 1010, 44, 66, Dio2496, Audiophile |
8 | * Digigram VX442 | 8 | * Digigram VX442 |
9 | * | 9 | * |
10 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 10 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
13 | * it under the terms of the GNU General Public License as published by | 13 | * it under the terms of the GNU General Public License as published by |
diff --git a/sound/pci/ice1712/envy24ht.h b/sound/pci/ice1712/envy24ht.h index b58afcda9ed6..43b9e3e858be 100644 --- a/sound/pci/ice1712/envy24ht.h +++ b/sound/pci/ice1712/envy24ht.h | |||
@@ -4,7 +4,7 @@ | |||
4 | /* | 4 | /* |
5 | * ALSA driver for ICEnsemble VT1724 (Envy24) | 5 | * ALSA driver for ICEnsemble VT1724 (Envy24) |
6 | * | 6 | * |
7 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 7 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by | 10 | * it under the terms of the GNU General Public License as published by |
diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c index b135389fec6c..75e4e5e0f1e4 100644 --- a/sound/pci/ice1712/ews.c +++ b/sound/pci/ice1712/ews.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Lowlevel functions for Terratec EWS88MT/D, EWX24/96, DMX 6Fire | 4 | * Lowlevel functions for Terratec EWS88MT/D, EWX24/96, DMX 6Fire |
5 | * | 5 | * |
6 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 6 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
7 | * 2002 Takashi Iwai <tiwai@suse.de> | 7 | * 2002 Takashi Iwai <tiwai@suse.de> |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
@@ -700,14 +700,7 @@ static struct snd_kcontrol_new snd_ice1712_ews88mt_output_sense __devinitdata = | |||
700 | * EWS88D specific controls | 700 | * EWS88D specific controls |
701 | */ | 701 | */ |
702 | 702 | ||
703 | static int snd_ice1712_ews88d_control_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 703 | #define snd_ice1712_ews88d_control_info snd_ctl_boolean_mono_info |
704 | { | ||
705 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
706 | uinfo->count = 1; | ||
707 | uinfo->value.integer.min = 0; | ||
708 | uinfo->value.integer.max = 1; | ||
709 | return 0; | ||
710 | } | ||
711 | 704 | ||
712 | static int snd_ice1712_ews88d_control_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 705 | static int snd_ice1712_ews88d_control_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
713 | { | 706 | { |
@@ -812,14 +805,7 @@ static int snd_ice1712_6fire_write_pca(struct snd_ice1712 *ice, unsigned char re | |||
812 | return 0; | 805 | return 0; |
813 | } | 806 | } |
814 | 807 | ||
815 | static int snd_ice1712_6fire_control_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 808 | #define snd_ice1712_6fire_control_info snd_ctl_boolean_mono_info |
816 | { | ||
817 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
818 | uinfo->count = 1; | ||
819 | uinfo->value.integer.min = 0; | ||
820 | uinfo->value.integer.max = 1; | ||
821 | return 0; | ||
822 | } | ||
823 | 809 | ||
824 | static int snd_ice1712_6fire_control_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 810 | static int snd_ice1712_6fire_control_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
825 | { | 811 | { |
diff --git a/sound/pci/ice1712/ews.h b/sound/pci/ice1712/ews.h index a12a0b053558..e4ed1b475b08 100644 --- a/sound/pci/ice1712/ews.h +++ b/sound/pci/ice1712/ews.h | |||
@@ -6,7 +6,7 @@ | |||
6 | * | 6 | * |
7 | * Lowlevel functions for Terratec EWS88MT/D, EWX24/96, DMX 6Fire | 7 | * Lowlevel functions for Terratec EWS88MT/D, EWX24/96, DMX 6Fire |
8 | * | 8 | * |
9 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 9 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
10 | * 2002 Takashi Iwai <tiwai@suse.de> | 10 | * 2002 Takashi Iwai <tiwai@suse.de> |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
diff --git a/sound/pci/ice1712/hoontech.c b/sound/pci/ice1712/hoontech.c index 8203562ef7e7..abcfd1da6587 100644 --- a/sound/pci/ice1712/hoontech.c +++ b/sound/pci/ice1712/hoontech.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Lowlevel functions for Hoontech STDSP24 | 4 | * Lowlevel functions for Hoontech STDSP24 |
5 | * | 5 | * |
6 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 6 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
diff --git a/sound/pci/ice1712/hoontech.h b/sound/pci/ice1712/hoontech.h index 1ee538b20fbf..cc1da1e69ad1 100644 --- a/sound/pci/ice1712/hoontech.h +++ b/sound/pci/ice1712/hoontech.h | |||
@@ -6,7 +6,7 @@ | |||
6 | * | 6 | * |
7 | * Lowlevel functions for Hoontech STDSP24 | 7 | * Lowlevel functions for Hoontech STDSP24 |
8 | * | 8 | * |
9 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 9 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License as published by | 12 | * it under the terms of the GNU General Public License as published by |
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 6630a0ae9527..052fc3cb3272 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * ALSA driver for ICEnsemble ICE1712 (Envy24) | 2 | * ALSA driver for ICEnsemble ICE1712 (Envy24) |
3 | * | 3 | * |
4 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 4 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
@@ -73,7 +73,7 @@ | |||
73 | #include "ews.h" | 73 | #include "ews.h" |
74 | #include "hoontech.h" | 74 | #include "hoontech.h" |
75 | 75 | ||
76 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 76 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
77 | MODULE_DESCRIPTION("ICEnsemble ICE1712 (Envy24)"); | 77 | MODULE_DESCRIPTION("ICEnsemble ICE1712 (Envy24)"); |
78 | MODULE_LICENSE("GPL"); | 78 | MODULE_LICENSE("GPL"); |
79 | MODULE_SUPPORTED_DEVICE("{" | 79 | MODULE_SUPPORTED_DEVICE("{" |
@@ -256,14 +256,7 @@ static unsigned short snd_ice1712_pro_ac97_read(struct snd_ac97 *ac97, | |||
256 | /* | 256 | /* |
257 | * consumer ac97 digital mix | 257 | * consumer ac97 digital mix |
258 | */ | 258 | */ |
259 | static int snd_ice1712_digmix_route_ac97_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 259 | #define snd_ice1712_digmix_route_ac97_info snd_ctl_boolean_mono_info |
260 | { | ||
261 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
262 | uinfo->count = 1; | ||
263 | uinfo->value.integer.min = 0; | ||
264 | uinfo->value.integer.max = 1; | ||
265 | return 0; | ||
266 | } | ||
267 | 260 | ||
268 | static int snd_ice1712_digmix_route_ac97_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 261 | static int snd_ice1712_digmix_route_ac97_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
269 | { | 262 | { |
@@ -1300,14 +1293,7 @@ static void snd_ice1712_update_volume(struct snd_ice1712 *ice, int index) | |||
1300 | outw(val, ICEMT(ice, MONITOR_VOLUME)); | 1293 | outw(val, ICEMT(ice, MONITOR_VOLUME)); |
1301 | } | 1294 | } |
1302 | 1295 | ||
1303 | static int snd_ice1712_pro_mixer_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1296 | #define snd_ice1712_pro_mixer_switch_info snd_ctl_boolean_stereo_info |
1304 | { | ||
1305 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1306 | uinfo->count = 2; | ||
1307 | uinfo->value.integer.min = 0; | ||
1308 | uinfo->value.integer.max = 1; | ||
1309 | return 0; | ||
1310 | } | ||
1311 | 1297 | ||
1312 | static int snd_ice1712_pro_mixer_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1298 | static int snd_ice1712_pro_mixer_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1313 | { | 1299 | { |
@@ -1759,16 +1745,6 @@ static struct snd_kcontrol_new snd_ice1712_spdif_stream __devinitdata = | |||
1759 | .put = snd_ice1712_spdif_stream_put | 1745 | .put = snd_ice1712_spdif_stream_put |
1760 | }; | 1746 | }; |
1761 | 1747 | ||
1762 | int snd_ice1712_gpio_info(struct snd_kcontrol *kcontrol, | ||
1763 | struct snd_ctl_elem_info *uinfo) | ||
1764 | { | ||
1765 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1766 | uinfo->count = 1; | ||
1767 | uinfo->value.integer.min = 0; | ||
1768 | uinfo->value.integer.max = 1; | ||
1769 | return 0; | ||
1770 | } | ||
1771 | |||
1772 | int snd_ice1712_gpio_get(struct snd_kcontrol *kcontrol, | 1748 | int snd_ice1712_gpio_get(struct snd_kcontrol *kcontrol, |
1773 | struct snd_ctl_elem_value *ucontrol) | 1749 | struct snd_ctl_elem_value *ucontrol) |
1774 | { | 1750 | { |
@@ -1968,15 +1944,7 @@ static struct snd_kcontrol_new snd_ice1712_pro_internal_clock_default __devinitd | |||
1968 | .put = snd_ice1712_pro_internal_clock_default_put | 1944 | .put = snd_ice1712_pro_internal_clock_default_put |
1969 | }; | 1945 | }; |
1970 | 1946 | ||
1971 | static int snd_ice1712_pro_rate_locking_info(struct snd_kcontrol *kcontrol, | 1947 | #define snd_ice1712_pro_rate_locking_info snd_ctl_boolean_mono_info |
1972 | struct snd_ctl_elem_info *uinfo) | ||
1973 | { | ||
1974 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1975 | uinfo->count = 1; | ||
1976 | uinfo->value.integer.min = 0; | ||
1977 | uinfo->value.integer.max = 1; | ||
1978 | return 0; | ||
1979 | } | ||
1980 | 1948 | ||
1981 | static int snd_ice1712_pro_rate_locking_get(struct snd_kcontrol *kcontrol, | 1949 | static int snd_ice1712_pro_rate_locking_get(struct snd_kcontrol *kcontrol, |
1982 | struct snd_ctl_elem_value *ucontrol) | 1950 | struct snd_ctl_elem_value *ucontrol) |
@@ -2007,15 +1975,7 @@ static struct snd_kcontrol_new snd_ice1712_pro_rate_locking __devinitdata = { | |||
2007 | .put = snd_ice1712_pro_rate_locking_put | 1975 | .put = snd_ice1712_pro_rate_locking_put |
2008 | }; | 1976 | }; |
2009 | 1977 | ||
2010 | static int snd_ice1712_pro_rate_reset_info(struct snd_kcontrol *kcontrol, | 1978 | #define snd_ice1712_pro_rate_reset_info snd_ctl_boolean_mono_info |
2011 | struct snd_ctl_elem_info *uinfo) | ||
2012 | { | ||
2013 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2014 | uinfo->count = 1; | ||
2015 | uinfo->value.integer.min = 0; | ||
2016 | uinfo->value.integer.max = 1; | ||
2017 | return 0; | ||
2018 | } | ||
2019 | 1979 | ||
2020 | static int snd_ice1712_pro_rate_reset_get(struct snd_kcontrol *kcontrol, | 1980 | static int snd_ice1712_pro_rate_reset_get(struct snd_kcontrol *kcontrol, |
2021 | struct snd_ctl_elem_value *ucontrol) | 1981 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h index 6ac486d9c138..58640afa5404 100644 --- a/sound/pci/ice1712/ice1712.h +++ b/sound/pci/ice1712/ice1712.h | |||
@@ -4,7 +4,7 @@ | |||
4 | /* | 4 | /* |
5 | * ALSA driver for ICEnsemble ICE1712 (Envy24) | 5 | * ALSA driver for ICEnsemble ICE1712 (Envy24) |
6 | * | 6 | * |
7 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 7 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by | 10 | * it under the terms of the GNU General Public License as published by |
@@ -451,11 +451,10 @@ static inline void snd_ice1712_restore_gpio_status(struct snd_ice1712 *ice) | |||
451 | 451 | ||
452 | /* for bit controls */ | 452 | /* for bit controls */ |
453 | #define ICE1712_GPIO(xiface, xname, xindex, mask, invert, xaccess) \ | 453 | #define ICE1712_GPIO(xiface, xname, xindex, mask, invert, xaccess) \ |
454 | { .iface = xiface, .name = xname, .access = xaccess, .info = snd_ice1712_gpio_info, \ | 454 | { .iface = xiface, .name = xname, .access = xaccess, .info = snd_ctl_boolean_mono_info, \ |
455 | .get = snd_ice1712_gpio_get, .put = snd_ice1712_gpio_put, \ | 455 | .get = snd_ice1712_gpio_get, .put = snd_ice1712_gpio_put, \ |
456 | .private_value = mask | (invert << 24) } | 456 | .private_value = mask | (invert << 24) } |
457 | 457 | ||
458 | int snd_ice1712_gpio_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); | ||
459 | int snd_ice1712_gpio_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 458 | int snd_ice1712_gpio_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); |
460 | int snd_ice1712_gpio_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); | 459 | int snd_ice1712_gpio_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); |
461 | 460 | ||
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index ee620dea7ef3..0b0bbb0d96b9 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * ALSA driver for VT1724 ICEnsemble ICE1724 / VIA VT1724 (Envy24HT) | 2 | * ALSA driver for VT1724 ICEnsemble ICE1724 / VIA VT1724 (Envy24HT) |
3 | * VIA VT1720 (Envy24PT) | 3 | * VIA VT1720 (Envy24PT) |
4 | * | 4 | * |
5 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 5 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
6 | * 2002 James Stafford <jstafford@ampltd.com> | 6 | * 2002 James Stafford <jstafford@ampltd.com> |
7 | * 2003 Takashi Iwai <tiwai@suse.de> | 7 | * 2003 Takashi Iwai <tiwai@suse.de> |
8 | * | 8 | * |
@@ -52,7 +52,7 @@ | |||
52 | #include "phase.h" | 52 | #include "phase.h" |
53 | #include "wtm.h" | 53 | #include "wtm.h" |
54 | 54 | ||
55 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 55 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
56 | MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)"); | 56 | MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)"); |
57 | MODULE_LICENSE("GPL"); | 57 | MODULE_LICENSE("GPL"); |
58 | MODULE_SUPPORTED_DEVICE("{" | 58 | MODULE_SUPPORTED_DEVICE("{" |
@@ -341,10 +341,12 @@ static int snd_vt1724_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
341 | 341 | ||
342 | what = 0; | 342 | what = 0; |
343 | snd_pcm_group_for_each_entry(s, substream) { | 343 | snd_pcm_group_for_each_entry(s, substream) { |
344 | const struct vt1724_pcm_reg *reg; | 344 | if (snd_pcm_substream_chip(s) == ice) { |
345 | reg = s->runtime->private_data; | 345 | const struct vt1724_pcm_reg *reg; |
346 | what |= reg->start; | 346 | reg = s->runtime->private_data; |
347 | snd_pcm_trigger_done(s, substream); | 347 | what |= reg->start; |
348 | snd_pcm_trigger_done(s, substream); | ||
349 | } | ||
348 | } | 350 | } |
349 | 351 | ||
350 | switch (cmd) { | 352 | switch (cmd) { |
@@ -1479,15 +1481,7 @@ static struct snd_kcontrol_new snd_vt1724_spdif_maskp __devinitdata = | |||
1479 | .get = snd_vt1724_spdif_maskp_get, | 1481 | .get = snd_vt1724_spdif_maskp_get, |
1480 | }; | 1482 | }; |
1481 | 1483 | ||
1482 | static int snd_vt1724_spdif_sw_info(struct snd_kcontrol *kcontrol, | 1484 | #define snd_vt1724_spdif_sw_info snd_ctl_boolean_mono_info |
1483 | struct snd_ctl_elem_info *uinfo) | ||
1484 | { | ||
1485 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1486 | uinfo->count = 1; | ||
1487 | uinfo->value.integer.min = 0; | ||
1488 | uinfo->value.integer.max = 1; | ||
1489 | return 0; | ||
1490 | } | ||
1491 | 1485 | ||
1492 | static int snd_vt1724_spdif_sw_get(struct snd_kcontrol *kcontrol, | 1486 | static int snd_vt1724_spdif_sw_get(struct snd_kcontrol *kcontrol, |
1493 | struct snd_ctl_elem_value *ucontrol) | 1487 | struct snd_ctl_elem_value *ucontrol) |
@@ -1532,15 +1526,7 @@ static struct snd_kcontrol_new snd_vt1724_spdif_switch __devinitdata = | |||
1532 | * GPIO access from extern | 1526 | * GPIO access from extern |
1533 | */ | 1527 | */ |
1534 | 1528 | ||
1535 | int snd_vt1724_gpio_info(struct snd_kcontrol *kcontrol, | 1529 | #define snd_vt1724_gpio_info snd_ctl_boolean_mono_info |
1536 | struct snd_ctl_elem_info *uinfo) | ||
1537 | { | ||
1538 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1539 | uinfo->count = 1; | ||
1540 | uinfo->value.integer.min = 0; | ||
1541 | uinfo->value.integer.max = 1; | ||
1542 | return 0; | ||
1543 | } | ||
1544 | 1530 | ||
1545 | int snd_vt1724_gpio_get(struct snd_kcontrol *kcontrol, | 1531 | int snd_vt1724_gpio_get(struct snd_kcontrol *kcontrol, |
1546 | struct snd_ctl_elem_value *ucontrol) | 1532 | struct snd_ctl_elem_value *ucontrol) |
@@ -1706,15 +1692,7 @@ static struct snd_kcontrol_new snd_vt1724_pro_internal_clock __devinitdata = { | |||
1706 | .put = snd_vt1724_pro_internal_clock_put | 1692 | .put = snd_vt1724_pro_internal_clock_put |
1707 | }; | 1693 | }; |
1708 | 1694 | ||
1709 | static int snd_vt1724_pro_rate_locking_info(struct snd_kcontrol *kcontrol, | 1695 | #define snd_vt1724_pro_rate_locking_info snd_ctl_boolean_mono_info |
1710 | struct snd_ctl_elem_info *uinfo) | ||
1711 | { | ||
1712 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1713 | uinfo->count = 1; | ||
1714 | uinfo->value.integer.min = 0; | ||
1715 | uinfo->value.integer.max = 1; | ||
1716 | return 0; | ||
1717 | } | ||
1718 | 1696 | ||
1719 | static int snd_vt1724_pro_rate_locking_get(struct snd_kcontrol *kcontrol, | 1697 | static int snd_vt1724_pro_rate_locking_get(struct snd_kcontrol *kcontrol, |
1720 | struct snd_ctl_elem_value *ucontrol) | 1698 | struct snd_ctl_elem_value *ucontrol) |
@@ -1745,15 +1723,7 @@ static struct snd_kcontrol_new snd_vt1724_pro_rate_locking __devinitdata = { | |||
1745 | .put = snd_vt1724_pro_rate_locking_put | 1723 | .put = snd_vt1724_pro_rate_locking_put |
1746 | }; | 1724 | }; |
1747 | 1725 | ||
1748 | static int snd_vt1724_pro_rate_reset_info(struct snd_kcontrol *kcontrol, | 1726 | #define snd_vt1724_pro_rate_reset_info snd_ctl_boolean_mono_info |
1749 | struct snd_ctl_elem_info *uinfo) | ||
1750 | { | ||
1751 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1752 | uinfo->count = 1; | ||
1753 | uinfo->value.integer.min = 0; | ||
1754 | uinfo->value.integer.max = 1; | ||
1755 | return 0; | ||
1756 | } | ||
1757 | 1727 | ||
1758 | static int snd_vt1724_pro_rate_reset_get(struct snd_kcontrol *kcontrol, | 1728 | static int snd_vt1724_pro_rate_reset_get(struct snd_kcontrol *kcontrol, |
1759 | struct snd_ctl_elem_value *ucontrol) | 1729 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c index 3d8e74e493d7..1fbe3ef8e60a 100644 --- a/sound/pci/ice1712/juli.c +++ b/sound/pci/ice1712/juli.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Lowlevel functions for ESI Juli@ cards | 4 | * Lowlevel functions for ESI Juli@ cards |
5 | * | 5 | * |
6 | * Copyright (c) 2004 Jaroslav Kysela <perex@suse.cz> | 6 | * Copyright (c) 2004 Jaroslav Kysela <perex@perex.cz> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
diff --git a/sound/pci/ice1712/phase.c b/sound/pci/ice1712/phase.c index 40a9098af777..3ac25058bb58 100644 --- a/sound/pci/ice1712/phase.c +++ b/sound/pci/ice1712/phase.c | |||
@@ -270,7 +270,7 @@ static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned sho | |||
270 | /* | 270 | /* |
271 | * DAC mute control | 271 | * DAC mute control |
272 | */ | 272 | */ |
273 | #define wm_pcm_mute_info phase28_mono_bool_info | 273 | #define wm_pcm_mute_info snd_ctl_boolean_mono_info |
274 | 274 | ||
275 | static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 275 | static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
276 | { | 276 | { |
@@ -527,13 +527,7 @@ static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value | |||
527 | /* | 527 | /* |
528 | * WM8770 master mute control | 528 | * WM8770 master mute control |
529 | */ | 529 | */ |
530 | static int wm_master_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { | 530 | #define wm_master_mute_info snd_ctl_boolean_stereo_info |
531 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
532 | uinfo->count = 2; | ||
533 | uinfo->value.integer.min = 0; | ||
534 | uinfo->value.integer.max = 1; | ||
535 | return 0; | ||
536 | } | ||
537 | 531 | ||
538 | static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 532 | static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
539 | { | 533 | { |
@@ -615,20 +609,9 @@ static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val | |||
615 | } | 609 | } |
616 | 610 | ||
617 | /* | 611 | /* |
618 | */ | ||
619 | static int phase28_mono_bool_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo) | ||
620 | { | ||
621 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
622 | uinfo->count = 1; | ||
623 | uinfo->value.integer.min = 0; | ||
624 | uinfo->value.integer.max = 1; | ||
625 | return 0; | ||
626 | } | ||
627 | |||
628 | /* | ||
629 | * Deemphasis | 612 | * Deemphasis |
630 | */ | 613 | */ |
631 | #define phase28_deemp_info phase28_mono_bool_info | 614 | #define phase28_deemp_info snd_ctl_boolean_mono_info |
632 | 615 | ||
633 | static int phase28_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 616 | static int phase28_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
634 | { | 617 | { |
diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c index 01c69453ddeb..faefd52c1b80 100644 --- a/sound/pci/ice1712/pontis.c +++ b/sound/pci/ice1712/pontis.c | |||
@@ -216,14 +216,7 @@ static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val | |||
216 | /* | 216 | /* |
217 | * ADC input mux mixer control | 217 | * ADC input mux mixer control |
218 | */ | 218 | */ |
219 | static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 219 | #define wm_adc_mux_info snd_ctl_boolean_mono_info |
220 | { | ||
221 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
222 | uinfo->count = 1; | ||
223 | uinfo->value.integer.min = 0; | ||
224 | uinfo->value.integer.max = 1; | ||
225 | return 0; | ||
226 | } | ||
227 | 220 | ||
228 | static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 221 | static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
229 | { | 222 | { |
@@ -260,14 +253,7 @@ static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val | |||
260 | /* | 253 | /* |
261 | * Analog bypass (In -> Out) | 254 | * Analog bypass (In -> Out) |
262 | */ | 255 | */ |
263 | static int wm_bypass_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 256 | #define wm_bypass_info snd_ctl_boolean_mono_info |
264 | { | ||
265 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
266 | uinfo->count = 1; | ||
267 | uinfo->value.integer.min = 0; | ||
268 | uinfo->value.integer.max = 1; | ||
269 | return 0; | ||
270 | } | ||
271 | 257 | ||
272 | static int wm_bypass_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 258 | static int wm_bypass_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
273 | { | 259 | { |
@@ -302,14 +288,7 @@ static int wm_bypass_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu | |||
302 | /* | 288 | /* |
303 | * Left/Right swap | 289 | * Left/Right swap |
304 | */ | 290 | */ |
305 | static int wm_chswap_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 291 | #define wm_chswap_info snd_ctl_boolean_mono_info |
306 | { | ||
307 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
308 | uinfo->count = 1; | ||
309 | uinfo->value.integer.min = 0; | ||
310 | uinfo->value.integer.max = 1; | ||
311 | return 0; | ||
312 | } | ||
313 | 292 | ||
314 | static int wm_chswap_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 293 | static int wm_chswap_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
315 | { | 294 | { |
diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c index 4bae7305a79b..4180f9739ecb 100644 --- a/sound/pci/ice1712/prodigy192.c +++ b/sound/pci/ice1712/prodigy192.c | |||
@@ -81,14 +81,7 @@ static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg) | |||
81 | /* | 81 | /* |
82 | * DAC mute control | 82 | * DAC mute control |
83 | */ | 83 | */ |
84 | static int stac9460_dac_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 84 | #define stac9460_dac_mute_info snd_ctl_boolean_mono_info |
85 | { | ||
86 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
87 | uinfo->count = 1; | ||
88 | uinfo->value.integer.min = 0; | ||
89 | uinfo->value.integer.max = 1; | ||
90 | return 0; | ||
91 | } | ||
92 | 85 | ||
93 | static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 86 | static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
94 | { | 87 | { |
@@ -177,14 +170,7 @@ static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el | |||
177 | /* | 170 | /* |
178 | * ADC mute control | 171 | * ADC mute control |
179 | */ | 172 | */ |
180 | static int stac9460_adc_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 173 | #define stac9460_adc_mute_info snd_ctl_boolean_stereo_info |
181 | { | ||
182 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
183 | uinfo->count = 2; | ||
184 | uinfo->value.integer.min = 0; | ||
185 | uinfo->value.integer.max = 1; | ||
186 | return 0; | ||
187 | } | ||
188 | 174 | ||
189 | static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 175 | static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
190 | { | 176 | { |
@@ -292,14 +278,7 @@ static int aureon_get_headphone_amp(struct snd_ice1712 *ice) | |||
292 | return ( tmp & AUREON_HP_SEL )!= 0; | 278 | return ( tmp & AUREON_HP_SEL )!= 0; |
293 | } | 279 | } |
294 | 280 | ||
295 | static int aureon_bool_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo) | 281 | #define aureon_bool_info snd_ctl_boolean_mono_info |
296 | { | ||
297 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
298 | uinfo->count = 1; | ||
299 | uinfo->value.integer.min = 0; | ||
300 | uinfo->value.integer.max = 1; | ||
301 | return 0; | ||
302 | } | ||
303 | 282 | ||
304 | static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 283 | static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
305 | { | 284 | { |
diff --git a/sound/pci/ice1712/wtm.c b/sound/pci/ice1712/wtm.c index 04e535c8542b..7fcce0a506d6 100644 --- a/sound/pci/ice1712/wtm.c +++ b/sound/pci/ice1712/wtm.c | |||
@@ -71,14 +71,7 @@ static inline unsigned char stac9460_2_get(struct snd_ice1712 *ice, int reg) | |||
71 | /* | 71 | /* |
72 | * DAC mute control | 72 | * DAC mute control |
73 | */ | 73 | */ |
74 | static int stac9460_dac_mute_info(struct snd_kcontrol *kcontrol, | 74 | #define stac9460_dac_mute_info snd_ctl_boolean_mono_info |
75 | struct snd_ctl_elem_info *uinfo) | ||
76 | { | ||
77 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
78 | uinfo->count = 1; | ||
79 | uinfo->value.integer.min = 0; | ||
80 | return 0; | ||
81 | } | ||
82 | 75 | ||
83 | static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, | 76 | static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, |
84 | struct snd_ctl_elem_value *ucontrol) | 77 | struct snd_ctl_elem_value *ucontrol) |
@@ -218,15 +211,7 @@ static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol, | |||
218 | /* | 211 | /* |
219 | * ADC mute control | 212 | * ADC mute control |
220 | */ | 213 | */ |
221 | static int stac9460_adc_mute_info(struct snd_kcontrol *kcontrol, | 214 | #define stac9460_adc_mute_info snd_ctl_boolean_stereo_info |
222 | struct snd_ctl_elem_info *uinfo) | ||
223 | { | ||
224 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
225 | uinfo->count = 2; | ||
226 | uinfo->value.integer.min = 0; | ||
227 | uinfo->value.integer.max = 1; | ||
228 | return 0; | ||
229 | } | ||
230 | 215 | ||
231 | static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol, | 216 | static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol, |
232 | struct snd_ctl_elem_value *ucontrol) | 217 | struct snd_ctl_elem_value *ucontrol) |
@@ -357,15 +342,7 @@ static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol, | |||
357 | * MIC / LINE switch fonction | 342 | * MIC / LINE switch fonction |
358 | */ | 343 | */ |
359 | 344 | ||
360 | static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol, | 345 | #define stac9460_mic_sw_info snd_ctl_boolean_mono_info |
361 | struct snd_ctl_elem_info *uinfo) | ||
362 | { | ||
363 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
364 | uinfo->count = 1; | ||
365 | uinfo->value.integer.min = 0; | ||
366 | uinfo->value.integer.max = 1; | ||
367 | return 0; | ||
368 | } | ||
369 | 346 | ||
370 | static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol, | 347 | static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol, |
371 | struct snd_ctl_elem_value *ucontrol) | 348 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index da9734073dba..b4a38a3d855b 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * ALSA driver for Intel ICH (i8x0) chipsets | 2 | * ALSA driver for Intel ICH (i8x0) chipsets |
3 | * | 3 | * |
4 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 4 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
5 | * | 5 | * |
6 | * | 6 | * |
7 | * This code also contains alpha support for SiS 735 chipsets provided | 7 | * This code also contains alpha support for SiS 735 chipsets provided |
@@ -43,7 +43,7 @@ | |||
43 | #include <asm/pgtable.h> | 43 | #include <asm/pgtable.h> |
44 | #include <asm/cacheflush.h> | 44 | #include <asm/cacheflush.h> |
45 | 45 | ||
46 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 46 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
47 | MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7012; Ali 5455"); | 47 | MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7012; Ali 5455"); |
48 | MODULE_LICENSE("GPL"); | 48 | MODULE_LICENSE("GPL"); |
49 | MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH}," | 49 | MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH}," |
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index c155e1f3a0e5..fad806e60f36 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * ALSA modem driver for Intel ICH (i8x0) chipsets | 2 | * ALSA modem driver for Intel ICH (i8x0) chipsets |
3 | * | 3 | * |
4 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 4 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
5 | * | 5 | * |
6 | * This is modified (by Sasha Khapyorsky <sashak@alsa-project.org>) version | 6 | * This is modified (by Sasha Khapyorsky <sashak@alsa-project.org>) version |
7 | * of ALSA ICH sound driver intel8x0.c . | 7 | * of ALSA ICH sound driver intel8x0.c . |
@@ -37,7 +37,7 @@ | |||
37 | #include <sound/info.h> | 37 | #include <sound/info.h> |
38 | #include <sound/initval.h> | 38 | #include <sound/initval.h> |
39 | 39 | ||
40 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 40 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
41 | MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; " | 41 | MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; " |
42 | "SiS 7013; NVidia MCP/2/2S/3 modems"); | 42 | "SiS 7013; NVidia MCP/2/2S/3 modems"); |
43 | MODULE_LICENSE("GPL"); | 43 | MODULE_LICENSE("GPL"); |
diff --git a/sound/pci/korg1212/Makefile b/sound/pci/korg1212/Makefile index 78c9dc6eeb2d..f11ce1b1b3d4 100644 --- a/sound/pci/korg1212/Makefile +++ b/sound/pci/korg1212/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-korg1212-objs := korg1212.o | 6 | snd-korg1212-objs := korg1212.o |
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 5338243fb035..c4af57fb5af1 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c | |||
@@ -1391,8 +1391,6 @@ static int snd_korg1212_playback_open(struct snd_pcm_substream *substream) | |||
1391 | K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_open [%s]\n", | 1391 | K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_open [%s]\n", |
1392 | stateName[korg1212->cardState]); | 1392 | stateName[korg1212->cardState]); |
1393 | 1393 | ||
1394 | snd_pcm_set_sync(substream); // ??? | ||
1395 | |||
1396 | snd_korg1212_OpenCard(korg1212); | 1394 | snd_korg1212_OpenCard(korg1212); |
1397 | 1395 | ||
1398 | runtime->hw = snd_korg1212_playback_info; | 1396 | runtime->hw = snd_korg1212_playback_info; |
@@ -1422,8 +1420,6 @@ static int snd_korg1212_capture_open(struct snd_pcm_substream *substream) | |||
1422 | K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_open [%s]\n", | 1420 | K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_open [%s]\n", |
1423 | stateName[korg1212->cardState]); | 1421 | stateName[korg1212->cardState]); |
1424 | 1422 | ||
1425 | snd_pcm_set_sync(substream); | ||
1426 | |||
1427 | snd_korg1212_OpenCard(korg1212); | 1423 | snd_korg1212_OpenCard(korg1212); |
1428 | 1424 | ||
1429 | runtime->hw = snd_korg1212_capture_info; | 1425 | runtime->hw = snd_korg1212_capture_info; |
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 8a5ff1cb5362..32245770595e 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c | |||
@@ -1821,7 +1821,6 @@ snd_m3_playback_open(struct snd_pcm_substream *subs) | |||
1821 | return err; | 1821 | return err; |
1822 | 1822 | ||
1823 | runtime->hw = snd_m3_playback; | 1823 | runtime->hw = snd_m3_playback; |
1824 | snd_pcm_set_sync(subs); | ||
1825 | 1824 | ||
1826 | return 0; | 1825 | return 0; |
1827 | } | 1826 | } |
@@ -1846,7 +1845,6 @@ snd_m3_capture_open(struct snd_pcm_substream *subs) | |||
1846 | return err; | 1845 | return err; |
1847 | 1846 | ||
1848 | runtime->hw = snd_m3_capture; | 1847 | runtime->hw = snd_m3_capture; |
1849 | snd_pcm_set_sync(subs); | ||
1850 | 1848 | ||
1851 | return 0; | 1849 | return 0; |
1852 | } | 1850 | } |
diff --git a/sound/pci/mixart/Makefile b/sound/pci/mixart/Makefile index fe6ba0c4b567..cce159ec5624 100644 --- a/sound/pci/mixart/Makefile +++ b/sound/pci/mixart/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-mixart-objs := mixart.o mixart_core.o mixart_hwdep.o mixart_mixer.o | 6 | snd-mixart-objs := mixart.o mixart_core.o mixart_hwdep.o mixart_mixer.o |
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index ac007cec0879..880b824e24cd 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c | |||
@@ -652,7 +652,7 @@ static int snd_mixart_hw_free(struct snd_pcm_substream *subs) | |||
652 | static struct snd_pcm_hardware snd_mixart_analog_caps = | 652 | static struct snd_pcm_hardware snd_mixart_analog_caps = |
653 | { | 653 | { |
654 | .info = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | | 654 | .info = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | |
655 | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START | | 655 | SNDRV_PCM_INFO_MMAP_VALID | |
656 | SNDRV_PCM_INFO_PAUSE), | 656 | SNDRV_PCM_INFO_PAUSE), |
657 | .formats = ( SNDRV_PCM_FMTBIT_U8 | | 657 | .formats = ( SNDRV_PCM_FMTBIT_U8 | |
658 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | | 658 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | |
@@ -673,7 +673,7 @@ static struct snd_pcm_hardware snd_mixart_analog_caps = | |||
673 | static struct snd_pcm_hardware snd_mixart_digital_caps = | 673 | static struct snd_pcm_hardware snd_mixart_digital_caps = |
674 | { | 674 | { |
675 | .info = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | | 675 | .info = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | |
676 | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START | | 676 | SNDRV_PCM_INFO_MMAP_VALID | |
677 | SNDRV_PCM_INFO_PAUSE), | 677 | SNDRV_PCM_INFO_PAUSE), |
678 | .formats = ( SNDRV_PCM_FMTBIT_U8 | | 678 | .formats = ( SNDRV_PCM_FMTBIT_U8 | |
679 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | | 679 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | |
@@ -1317,6 +1317,12 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci, | |||
1317 | mgr->mem[i].phys = pci_resource_start(pci, i); | 1317 | mgr->mem[i].phys = pci_resource_start(pci, i); |
1318 | mgr->mem[i].virt = ioremap_nocache(mgr->mem[i].phys, | 1318 | mgr->mem[i].virt = ioremap_nocache(mgr->mem[i].phys, |
1319 | pci_resource_len(pci, i)); | 1319 | pci_resource_len(pci, i)); |
1320 | if (!mgr->mem[i].virt) { | ||
1321 | printk(KERN_ERR "unable to remap resource 0x%lx\n", | ||
1322 | mgr->mem[i].phys); | ||
1323 | snd_mixart_free(mgr); | ||
1324 | return -EBUSY; | ||
1325 | } | ||
1320 | } | 1326 | } |
1321 | 1327 | ||
1322 | if (request_irq(pci->irq, snd_mixart_interrupt, IRQF_SHARED, | 1328 | if (request_irq(pci->irq, snd_mixart_interrupt, IRQF_SHARED, |
diff --git a/sound/pci/mixart/mixart_mixer.c b/sound/pci/mixart/mixart_mixer.c index d7d15c036e02..0e16512d25f7 100644 --- a/sound/pci/mixart/mixart_mixer.c +++ b/sound/pci/mixart/mixart_mixer.c | |||
@@ -403,14 +403,7 @@ static struct snd_kcontrol_new mixart_control_analog_level = { | |||
403 | }; | 403 | }; |
404 | 404 | ||
405 | /* shared */ | 405 | /* shared */ |
406 | static int mixart_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 406 | #define mixart_sw_info snd_ctl_boolean_stereo_info |
407 | { | ||
408 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
409 | uinfo->count = 2; | ||
410 | uinfo->value.integer.min = 0; | ||
411 | uinfo->value.integer.max = 1; | ||
412 | return 0; | ||
413 | } | ||
414 | 407 | ||
415 | static int mixart_audio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 408 | static int mixart_audio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
416 | { | 409 | { |
diff --git a/sound/pci/nm256/Makefile b/sound/pci/nm256/Makefile index d91d8c519212..a1bd44ff850e 100644 --- a/sound/pci/nm256/Makefile +++ b/sound/pci/nm256/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-nm256-objs := nm256.o | 6 | snd-nm256-objs := nm256.o |
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index c7621bd770a6..276c5763f0e5 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c | |||
@@ -842,7 +842,6 @@ static void snd_nm256_setup_stream(struct nm256 *chip, struct nm256_stream *s, | |||
842 | runtime->private_data = s; | 842 | runtime->private_data = s; |
843 | s->substream = substream; | 843 | s->substream = substream; |
844 | 844 | ||
845 | snd_pcm_set_sync(substream); | ||
846 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | 845 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, |
847 | &constraints_rates); | 846 | &constraints_rates); |
848 | } | 847 | } |
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index f7f6a687f033..2d618bd7e62b 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c | |||
@@ -646,6 +646,8 @@ static int pcxhr_trigger(struct snd_pcm_substream *subs, int cmd) | |||
646 | if (snd_pcm_stream_linked(subs)) { | 646 | if (snd_pcm_stream_linked(subs)) { |
647 | struct snd_pcxhr *chip = snd_pcm_substream_chip(subs); | 647 | struct snd_pcxhr *chip = snd_pcm_substream_chip(subs); |
648 | snd_pcm_group_for_each_entry(s, subs) { | 648 | snd_pcm_group_for_each_entry(s, subs) { |
649 | if (snd_pcm_substream_chip(s) != chip) | ||
650 | continue; | ||
649 | stream = s->runtime->private_data; | 651 | stream = s->runtime->private_data; |
650 | stream->status = | 652 | stream->status = |
651 | PCXHR_STREAM_STATUS_SCHEDULE_RUN; | 653 | PCXHR_STREAM_STATUS_SCHEDULE_RUN; |
@@ -662,6 +664,7 @@ static int pcxhr_trigger(struct snd_pcm_substream *subs, int cmd) | |||
662 | if (pcxhr_update_r_buffer(stream)) | 664 | if (pcxhr_update_r_buffer(stream)) |
663 | return -EINVAL; | 665 | return -EINVAL; |
664 | 666 | ||
667 | stream->status = PCXHR_STREAM_STATUS_SCHEDULE_RUN; | ||
665 | if (pcxhr_set_stream_state(stream)) | 668 | if (pcxhr_set_stream_state(stream)) |
666 | return -EINVAL; | 669 | return -EINVAL; |
667 | stream->status = PCXHR_STREAM_STATUS_RUNNING; | 670 | stream->status = PCXHR_STREAM_STATUS_RUNNING; |
@@ -902,6 +905,8 @@ static int pcxhr_open(struct snd_pcm_substream *subs) | |||
902 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4); | 905 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4); |
903 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4); | 906 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4); |
904 | 907 | ||
908 | snd_pcm_set_sync(subs); | ||
909 | |||
905 | mgr->ref_count_rate++; | 910 | mgr->ref_count_rate++; |
906 | 911 | ||
907 | mutex_unlock(&mgr->setup_mutex); | 912 | mutex_unlock(&mgr->setup_mutex); |
diff --git a/sound/pci/pcxhr/pcxhr_mixer.c b/sound/pci/pcxhr/pcxhr_mixer.c index d9cc8d2beb6d..5f8d42633b04 100644 --- a/sound/pci/pcxhr/pcxhr_mixer.c +++ b/sound/pci/pcxhr/pcxhr_mixer.c | |||
@@ -44,8 +44,8 @@ | |||
44 | #define PCXHR_ANALOG_PLAYBACK_LEVEL_MAX 128 /* 0.0 dB */ | 44 | #define PCXHR_ANALOG_PLAYBACK_LEVEL_MAX 128 /* 0.0 dB */ |
45 | #define PCXHR_ANALOG_PLAYBACK_ZERO_LEVEL 104 /* -24.0 dB ( 0.0 dB - fix level +24.0 dB ) */ | 45 | #define PCXHR_ANALOG_PLAYBACK_ZERO_LEVEL 104 /* -24.0 dB ( 0.0 dB - fix level +24.0 dB ) */ |
46 | 46 | ||
47 | static const DECLARE_TLV_DB_SCALE(db_scale_analog_capture, -9600, 50, 0); | 47 | static const DECLARE_TLV_DB_SCALE(db_scale_analog_capture, -9600, 50, 3150); |
48 | static const DECLARE_TLV_DB_SCALE(db_scale_analog_playback, -12800, 100, 0); | 48 | static const DECLARE_TLV_DB_SCALE(db_scale_analog_playback, -10400, 100, 2400); |
49 | 49 | ||
50 | static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip, int is_capture, int channel) | 50 | static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip, int is_capture, int channel) |
51 | { | 51 | { |
@@ -144,14 +144,7 @@ static struct snd_kcontrol_new pcxhr_control_analog_level = { | |||
144 | }; | 144 | }; |
145 | 145 | ||
146 | /* shared */ | 146 | /* shared */ |
147 | static int pcxhr_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 147 | #define pcxhr_sw_info snd_ctl_boolean_stereo_info |
148 | { | ||
149 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
150 | uinfo->count = 2; | ||
151 | uinfo->value.integer.min = 0; | ||
152 | uinfo->value.integer.max = 1; | ||
153 | return 0; | ||
154 | } | ||
155 | 148 | ||
156 | static int pcxhr_audio_sw_get(struct snd_kcontrol *kcontrol, | 149 | static int pcxhr_audio_sw_get(struct snd_kcontrol *kcontrol, |
157 | struct snd_ctl_elem_value *ucontrol) | 150 | struct snd_ctl_elem_value *ucontrol) |
@@ -195,7 +188,7 @@ static struct snd_kcontrol_new pcxhr_control_output_switch = { | |||
195 | #define PCXHR_DIGITAL_LEVEL_MAX 0x1ff /* +18 dB */ | 188 | #define PCXHR_DIGITAL_LEVEL_MAX 0x1ff /* +18 dB */ |
196 | #define PCXHR_DIGITAL_ZERO_LEVEL 0x1b7 /* 0 dB */ | 189 | #define PCXHR_DIGITAL_ZERO_LEVEL 0x1b7 /* 0 dB */ |
197 | 190 | ||
198 | static const DECLARE_TLV_DB_SCALE(db_scale_digital, -10950, 50, 0); | 191 | static const DECLARE_TLV_DB_SCALE(db_scale_digital, -10975, 25, 1800); |
199 | 192 | ||
200 | #define MORE_THAN_ONE_STREAM_LEVEL 0x000001 | 193 | #define MORE_THAN_ONE_STREAM_LEVEL 0x000001 |
201 | #define VALID_STREAM_PAN_LEVEL_MASK 0x800000 | 194 | #define VALID_STREAM_PAN_LEVEL_MASK 0x800000 |
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index 618653e22561..1475912588e9 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c | |||
@@ -258,19 +258,6 @@ static inline unsigned int snd_rme32_pcm_byteptr(struct rme32 * rme32) | |||
258 | & RME32_RCR_AUDIO_ADDR_MASK); | 258 | & RME32_RCR_AUDIO_ADDR_MASK); |
259 | } | 259 | } |
260 | 260 | ||
261 | static int snd_rme32_ratecode(int rate) | ||
262 | { | ||
263 | switch (rate) { | ||
264 | case 32000: return SNDRV_PCM_RATE_32000; | ||
265 | case 44100: return SNDRV_PCM_RATE_44100; | ||
266 | case 48000: return SNDRV_PCM_RATE_48000; | ||
267 | case 64000: return SNDRV_PCM_RATE_64000; | ||
268 | case 88200: return SNDRV_PCM_RATE_88200; | ||
269 | case 96000: return SNDRV_PCM_RATE_96000; | ||
270 | } | ||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | /* silence callback for halfduplex mode */ | 261 | /* silence callback for halfduplex mode */ |
275 | static int snd_rme32_playback_silence(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */ | 262 | static int snd_rme32_playback_silence(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */ |
276 | snd_pcm_uframes_t pos, | 263 | snd_pcm_uframes_t pos, |
@@ -887,7 +874,7 @@ static int snd_rme32_playback_spdif_open(struct snd_pcm_substream *substream) | |||
887 | if ((rme32->rcreg & RME32_RCR_KMODE) && | 874 | if ((rme32->rcreg & RME32_RCR_KMODE) && |
888 | (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) { | 875 | (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) { |
889 | /* AutoSync */ | 876 | /* AutoSync */ |
890 | runtime->hw.rates = snd_rme32_ratecode(rate); | 877 | runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); |
891 | runtime->hw.rate_min = rate; | 878 | runtime->hw.rate_min = rate; |
892 | runtime->hw.rate_max = rate; | 879 | runtime->hw.rate_max = rate; |
893 | } | 880 | } |
@@ -929,7 +916,7 @@ static int snd_rme32_capture_spdif_open(struct snd_pcm_substream *substream) | |||
929 | if (isadat) { | 916 | if (isadat) { |
930 | return -EIO; | 917 | return -EIO; |
931 | } | 918 | } |
932 | runtime->hw.rates = snd_rme32_ratecode(rate); | 919 | runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); |
933 | runtime->hw.rate_min = rate; | 920 | runtime->hw.rate_min = rate; |
934 | runtime->hw.rate_max = rate; | 921 | runtime->hw.rate_max = rate; |
935 | } | 922 | } |
@@ -965,7 +952,7 @@ snd_rme32_playback_adat_open(struct snd_pcm_substream *substream) | |||
965 | if ((rme32->rcreg & RME32_RCR_KMODE) && | 952 | if ((rme32->rcreg & RME32_RCR_KMODE) && |
966 | (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) { | 953 | (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) { |
967 | /* AutoSync */ | 954 | /* AutoSync */ |
968 | runtime->hw.rates = snd_rme32_ratecode(rate); | 955 | runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); |
969 | runtime->hw.rate_min = rate; | 956 | runtime->hw.rate_min = rate; |
970 | runtime->hw.rate_max = rate; | 957 | runtime->hw.rate_max = rate; |
971 | } | 958 | } |
@@ -989,7 +976,7 @@ snd_rme32_capture_adat_open(struct snd_pcm_substream *substream) | |||
989 | if (!isadat) { | 976 | if (!isadat) { |
990 | return -EIO; | 977 | return -EIO; |
991 | } | 978 | } |
992 | runtime->hw.rates = snd_rme32_ratecode(rate); | 979 | runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); |
993 | runtime->hw.rate_min = rate; | 980 | runtime->hw.rate_min = rate; |
994 | runtime->hw.rate_max = rate; | 981 | runtime->hw.rate_max = rate; |
995 | } | 982 | } |
@@ -1582,16 +1569,8 @@ static void __devinit snd_rme32_proc_init(struct rme32 * rme32) | |||
1582 | * control interface | 1569 | * control interface |
1583 | */ | 1570 | */ |
1584 | 1571 | ||
1585 | static int | 1572 | #define snd_rme32_info_loopback_control snd_ctl_boolean_mono_info |
1586 | snd_rme32_info_loopback_control(struct snd_kcontrol *kcontrol, | 1573 | |
1587 | struct snd_ctl_elem_info *uinfo) | ||
1588 | { | ||
1589 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1590 | uinfo->count = 1; | ||
1591 | uinfo->value.integer.min = 0; | ||
1592 | uinfo->value.integer.max = 1; | ||
1593 | return 0; | ||
1594 | } | ||
1595 | static int | 1574 | static int |
1596 | snd_rme32_get_loopback_control(struct snd_kcontrol *kcontrol, | 1575 | snd_rme32_get_loopback_control(struct snd_kcontrol *kcontrol, |
1597 | struct snd_ctl_elem_value *ucontrol) | 1576 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index e3304b7ccbcb..0b3c532c4014 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c | |||
@@ -301,20 +301,6 @@ snd_rme96_capture_ptr(struct rme96 *rme96) | |||
301 | } | 301 | } |
302 | 302 | ||
303 | static int | 303 | static int |
304 | snd_rme96_ratecode(int rate) | ||
305 | { | ||
306 | switch (rate) { | ||
307 | case 32000: return SNDRV_PCM_RATE_32000; | ||
308 | case 44100: return SNDRV_PCM_RATE_44100; | ||
309 | case 48000: return SNDRV_PCM_RATE_48000; | ||
310 | case 64000: return SNDRV_PCM_RATE_64000; | ||
311 | case 88200: return SNDRV_PCM_RATE_88200; | ||
312 | case 96000: return SNDRV_PCM_RATE_96000; | ||
313 | } | ||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | static int | ||
318 | snd_rme96_playback_silence(struct snd_pcm_substream *substream, | 304 | snd_rme96_playback_silence(struct snd_pcm_substream *substream, |
319 | int channel, /* not used (interleaved data) */ | 305 | int channel, /* not used (interleaved data) */ |
320 | snd_pcm_uframes_t pos, | 306 | snd_pcm_uframes_t pos, |
@@ -1176,8 +1162,6 @@ snd_rme96_playback_spdif_open(struct snd_pcm_substream *substream) | |||
1176 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); | 1162 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); |
1177 | struct snd_pcm_runtime *runtime = substream->runtime; | 1163 | struct snd_pcm_runtime *runtime = substream->runtime; |
1178 | 1164 | ||
1179 | snd_pcm_set_sync(substream); | ||
1180 | |||
1181 | spin_lock_irq(&rme96->lock); | 1165 | spin_lock_irq(&rme96->lock); |
1182 | if (rme96->playback_substream != NULL) { | 1166 | if (rme96->playback_substream != NULL) { |
1183 | spin_unlock_irq(&rme96->lock); | 1167 | spin_unlock_irq(&rme96->lock); |
@@ -1194,7 +1178,7 @@ snd_rme96_playback_spdif_open(struct snd_pcm_substream *substream) | |||
1194 | (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0) | 1178 | (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0) |
1195 | { | 1179 | { |
1196 | /* slave clock */ | 1180 | /* slave clock */ |
1197 | runtime->hw.rates = snd_rme96_ratecode(rate); | 1181 | runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); |
1198 | runtime->hw.rate_min = rate; | 1182 | runtime->hw.rate_min = rate; |
1199 | runtime->hw.rate_max = rate; | 1183 | runtime->hw.rate_max = rate; |
1200 | } | 1184 | } |
@@ -1214,8 +1198,6 @@ snd_rme96_capture_spdif_open(struct snd_pcm_substream *substream) | |||
1214 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); | 1198 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); |
1215 | struct snd_pcm_runtime *runtime = substream->runtime; | 1199 | struct snd_pcm_runtime *runtime = substream->runtime; |
1216 | 1200 | ||
1217 | snd_pcm_set_sync(substream); | ||
1218 | |||
1219 | runtime->hw = snd_rme96_capture_spdif_info; | 1201 | runtime->hw = snd_rme96_capture_spdif_info; |
1220 | if (snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG && | 1202 | if (snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG && |
1221 | (rate = snd_rme96_capture_getrate(rme96, &isadat)) > 0) | 1203 | (rate = snd_rme96_capture_getrate(rme96, &isadat)) > 0) |
@@ -1223,7 +1205,7 @@ snd_rme96_capture_spdif_open(struct snd_pcm_substream *substream) | |||
1223 | if (isadat) { | 1205 | if (isadat) { |
1224 | return -EIO; | 1206 | return -EIO; |
1225 | } | 1207 | } |
1226 | runtime->hw.rates = snd_rme96_ratecode(rate); | 1208 | runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); |
1227 | runtime->hw.rate_min = rate; | 1209 | runtime->hw.rate_min = rate; |
1228 | runtime->hw.rate_max = rate; | 1210 | runtime->hw.rate_max = rate; |
1229 | } | 1211 | } |
@@ -1247,8 +1229,6 @@ snd_rme96_playback_adat_open(struct snd_pcm_substream *substream) | |||
1247 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); | 1229 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); |
1248 | struct snd_pcm_runtime *runtime = substream->runtime; | 1230 | struct snd_pcm_runtime *runtime = substream->runtime; |
1249 | 1231 | ||
1250 | snd_pcm_set_sync(substream); | ||
1251 | |||
1252 | spin_lock_irq(&rme96->lock); | 1232 | spin_lock_irq(&rme96->lock); |
1253 | if (rme96->playback_substream != NULL) { | 1233 | if (rme96->playback_substream != NULL) { |
1254 | spin_unlock_irq(&rme96->lock); | 1234 | spin_unlock_irq(&rme96->lock); |
@@ -1265,7 +1245,7 @@ snd_rme96_playback_adat_open(struct snd_pcm_substream *substream) | |||
1265 | (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0) | 1245 | (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0) |
1266 | { | 1246 | { |
1267 | /* slave clock */ | 1247 | /* slave clock */ |
1268 | runtime->hw.rates = snd_rme96_ratecode(rate); | 1248 | runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); |
1269 | runtime->hw.rate_min = rate; | 1249 | runtime->hw.rate_min = rate; |
1270 | runtime->hw.rate_max = rate; | 1250 | runtime->hw.rate_max = rate; |
1271 | } | 1251 | } |
@@ -1280,8 +1260,6 @@ snd_rme96_capture_adat_open(struct snd_pcm_substream *substream) | |||
1280 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); | 1260 | struct rme96 *rme96 = snd_pcm_substream_chip(substream); |
1281 | struct snd_pcm_runtime *runtime = substream->runtime; | 1261 | struct snd_pcm_runtime *runtime = substream->runtime; |
1282 | 1262 | ||
1283 | snd_pcm_set_sync(substream); | ||
1284 | |||
1285 | runtime->hw = snd_rme96_capture_adat_info; | 1263 | runtime->hw = snd_rme96_capture_adat_info; |
1286 | if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) { | 1264 | if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) { |
1287 | /* makes no sense to use analog input. Note that analog | 1265 | /* makes no sense to use analog input. Note that analog |
@@ -1292,7 +1270,7 @@ snd_rme96_capture_adat_open(struct snd_pcm_substream *substream) | |||
1292 | if (!isadat) { | 1270 | if (!isadat) { |
1293 | return -EIO; | 1271 | return -EIO; |
1294 | } | 1272 | } |
1295 | runtime->hw.rates = snd_rme96_ratecode(rate); | 1273 | runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); |
1296 | runtime->hw.rate_min = rate; | 1274 | runtime->hw.rate_min = rate; |
1297 | runtime->hw.rate_max = rate; | 1275 | runtime->hw.rate_max = rate; |
1298 | } | 1276 | } |
@@ -1826,15 +1804,8 @@ snd_rme96_proc_init(struct rme96 *rme96) | |||
1826 | * control interface | 1804 | * control interface |
1827 | */ | 1805 | */ |
1828 | 1806 | ||
1829 | static int | 1807 | #define snd_rme96_info_loopback_control snd_ctl_boolean_mono_info |
1830 | snd_rme96_info_loopback_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1808 | |
1831 | { | ||
1832 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1833 | uinfo->count = 1; | ||
1834 | uinfo->value.integer.min = 0; | ||
1835 | uinfo->value.integer.max = 1; | ||
1836 | return 0; | ||
1837 | } | ||
1838 | static int | 1809 | static int |
1839 | snd_rme96_get_loopback_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1810 | snd_rme96_get_loopback_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1840 | { | 1811 | { |
diff --git a/sound/pci/rme9652/Makefile b/sound/pci/rme9652/Makefile index d2c294e136f9..dcba56040205 100644 --- a/sound/pci/rme9652/Makefile +++ b/sound/pci/rme9652/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-rme9652-objs := rme9652.o | 6 | snd-rme9652-objs := rme9652.o |
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 3b3ef657f73e..ff26a3672d40 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c | |||
@@ -606,28 +606,28 @@ static void snd_hdsp_9652_enable_mixer (struct hdsp *hdsp); | |||
606 | 606 | ||
607 | static int hdsp_playback_to_output_key (struct hdsp *hdsp, int in, int out) | 607 | static int hdsp_playback_to_output_key (struct hdsp *hdsp, int in, int out) |
608 | { | 608 | { |
609 | switch (hdsp->firmware_rev) { | 609 | switch (hdsp->io_type) { |
610 | case 0xa: | 610 | case Multiface: |
611 | case Digiface: | ||
612 | default: | ||
611 | return (64 * out) + (32 + (in)); | 613 | return (64 * out) + (32 + (in)); |
612 | case 0x96: | 614 | case H9632: |
613 | case 0x97: | ||
614 | case 0x98: | ||
615 | return (32 * out) + (16 + (in)); | 615 | return (32 * out) + (16 + (in)); |
616 | default: | 616 | case H9652: |
617 | return (52 * out) + (26 + (in)); | 617 | return (52 * out) + (26 + (in)); |
618 | } | 618 | } |
619 | } | 619 | } |
620 | 620 | ||
621 | static int hdsp_input_to_output_key (struct hdsp *hdsp, int in, int out) | 621 | static int hdsp_input_to_output_key (struct hdsp *hdsp, int in, int out) |
622 | { | 622 | { |
623 | switch (hdsp->firmware_rev) { | 623 | switch (hdsp->io_type) { |
624 | case 0xa: | 624 | case Multiface: |
625 | case Digiface: | ||
626 | default: | ||
625 | return (64 * out) + in; | 627 | return (64 * out) + in; |
626 | case 0x96: | 628 | case H9632: |
627 | case 0x97: | ||
628 | case 0x98: | ||
629 | return (32 * out) + in; | 629 | return (32 * out) + in; |
630 | default: | 630 | case H9652: |
631 | return (52 * out) + in; | 631 | return (52 * out) + in; |
632 | } | 632 | } |
633 | } | 633 | } |
@@ -1623,14 +1623,7 @@ static int hdsp_set_spdif_output(struct hdsp *hdsp, int out) | |||
1623 | return 0; | 1623 | return 0; |
1624 | } | 1624 | } |
1625 | 1625 | ||
1626 | static int snd_hdsp_info_spdif_bits(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1626 | #define snd_hdsp_info_spdif_bits snd_ctl_boolean_mono_info |
1627 | { | ||
1628 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1629 | uinfo->count = 1; | ||
1630 | uinfo->value.integer.min = 0; | ||
1631 | uinfo->value.integer.max = 1; | ||
1632 | return 0; | ||
1633 | } | ||
1634 | 1627 | ||
1635 | static int snd_hdsp_get_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1628 | static int snd_hdsp_get_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1636 | { | 1629 | { |
@@ -2111,14 +2104,7 @@ static int snd_hdsp_put_clock_source(struct snd_kcontrol *kcontrol, struct snd_c | |||
2111 | return change; | 2104 | return change; |
2112 | } | 2105 | } |
2113 | 2106 | ||
2114 | static int snd_hdsp_info_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 2107 | #define snd_hdsp_info_clock_source_lock snd_ctl_boolean_mono_info |
2115 | { | ||
2116 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2117 | uinfo->count = 1; | ||
2118 | uinfo->value.integer.min = 0; | ||
2119 | uinfo->value.integer.max = 1; | ||
2120 | return 0; | ||
2121 | } | ||
2122 | 2108 | ||
2123 | static int snd_hdsp_get_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2109 | static int snd_hdsp_get_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
2124 | { | 2110 | { |
@@ -2420,14 +2406,7 @@ static int hdsp_set_xlr_breakout_cable(struct hdsp *hdsp, int mode) | |||
2420 | return 0; | 2406 | return 0; |
2421 | } | 2407 | } |
2422 | 2408 | ||
2423 | static int snd_hdsp_info_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 2409 | #define snd_hdsp_info_xlr_breakout_cable snd_ctl_boolean_mono_info |
2424 | { | ||
2425 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2426 | uinfo->count = 1; | ||
2427 | uinfo->value.integer.min = 0; | ||
2428 | uinfo->value.integer.max = 1; | ||
2429 | return 0; | ||
2430 | } | ||
2431 | 2410 | ||
2432 | static int snd_hdsp_get_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2411 | static int snd_hdsp_get_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
2433 | { | 2412 | { |
@@ -2483,14 +2462,7 @@ static int hdsp_set_aeb(struct hdsp *hdsp, int mode) | |||
2483 | return 0; | 2462 | return 0; |
2484 | } | 2463 | } |
2485 | 2464 | ||
2486 | static int snd_hdsp_info_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 2465 | #define snd_hdsp_info_aeb snd_ctl_boolean_mono_info |
2487 | { | ||
2488 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2489 | uinfo->count = 1; | ||
2490 | uinfo->value.integer.min = 0; | ||
2491 | uinfo->value.integer.max = 1; | ||
2492 | return 0; | ||
2493 | } | ||
2494 | 2466 | ||
2495 | static int snd_hdsp_get_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2467 | static int snd_hdsp_get_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
2496 | { | 2468 | { |
@@ -2729,14 +2701,7 @@ static int hdsp_set_line_output(struct hdsp *hdsp, int out) | |||
2729 | return 0; | 2701 | return 0; |
2730 | } | 2702 | } |
2731 | 2703 | ||
2732 | static int snd_hdsp_info_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 2704 | #define snd_hdsp_info_line_out snd_ctl_boolean_mono_info |
2733 | { | ||
2734 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2735 | uinfo->count = 1; | ||
2736 | uinfo->value.integer.min = 0; | ||
2737 | uinfo->value.integer.max = 1; | ||
2738 | return 0; | ||
2739 | } | ||
2740 | 2705 | ||
2741 | static int snd_hdsp_get_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2706 | static int snd_hdsp_get_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
2742 | { | 2707 | { |
@@ -2782,14 +2747,7 @@ static int hdsp_set_precise_pointer(struct hdsp *hdsp, int precise) | |||
2782 | return 0; | 2747 | return 0; |
2783 | } | 2748 | } |
2784 | 2749 | ||
2785 | static int snd_hdsp_info_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 2750 | #define snd_hdsp_info_precise_pointer snd_ctl_boolean_mono_info |
2786 | { | ||
2787 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2788 | uinfo->count = 1; | ||
2789 | uinfo->value.integer.min = 0; | ||
2790 | uinfo->value.integer.max = 1; | ||
2791 | return 0; | ||
2792 | } | ||
2793 | 2751 | ||
2794 | static int snd_hdsp_get_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2752 | static int snd_hdsp_get_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
2795 | { | 2753 | { |
@@ -2835,14 +2793,7 @@ static int hdsp_set_use_midi_tasklet(struct hdsp *hdsp, int use_tasklet) | |||
2835 | return 0; | 2793 | return 0; |
2836 | } | 2794 | } |
2837 | 2795 | ||
2838 | static int snd_hdsp_info_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 2796 | #define snd_hdsp_info_use_midi_tasklet snd_ctl_boolean_mono_info |
2839 | { | ||
2840 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2841 | uinfo->count = 1; | ||
2842 | uinfo->value.integer.min = 0; | ||
2843 | uinfo->value.integer.max = 1; | ||
2844 | return 0; | ||
2845 | } | ||
2846 | 2797 | ||
2847 | static int snd_hdsp_get_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2798 | static int snd_hdsp_get_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
2848 | { | 2799 | { |
@@ -3108,6 +3059,9 @@ static int hdsp_dds_offset(struct hdsp *hdsp) | |||
3108 | unsigned int dds_value = hdsp->dds_value; | 3059 | unsigned int dds_value = hdsp->dds_value; |
3109 | int system_sample_rate = hdsp->system_sample_rate; | 3060 | int system_sample_rate = hdsp->system_sample_rate; |
3110 | 3061 | ||
3062 | if (!dds_value) | ||
3063 | return 0; | ||
3064 | |||
3111 | n = DDS_NUMERATOR; | 3065 | n = DDS_NUMERATOR; |
3112 | /* | 3066 | /* |
3113 | * dds_value = n / rate | 3067 | * dds_value = n / rate |
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 143185e7e4dc..f1bdda6cbcff 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* -*- linux-c -*- | 1 | /* |
2 | * | ||
3 | * ALSA driver for RME Hammerfall DSP MADI audio interface(s) | 2 | * ALSA driver for RME Hammerfall DSP MADI audio interface(s) |
4 | * | 3 | * |
5 | * Copyright (c) 2003 Winfried Ritsch (IEM) | 4 | * Copyright (c) 2003 Winfried Ritsch (IEM) |
@@ -78,7 +77,8 @@ MODULE_PARM_DESC(enable_monitor, | |||
78 | "Enable Analog Out on Channel 63/64 by default."); | 77 | "Enable Analog Out on Channel 63/64 by default."); |
79 | 78 | ||
80 | MODULE_AUTHOR | 79 | MODULE_AUTHOR |
81 | ("Winfried Ritsch <ritsch_AT_iem.at>, Paul Davis <paul@linuxaudiosystems.com>, " | 80 | ("Winfried Ritsch <ritsch_AT_iem.at>, " |
81 | "Paul Davis <paul@linuxaudiosystems.com>, " | ||
82 | "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, " | 82 | "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, " |
83 | "Remy Bruno <remy.bruno@trinnov.com>"); | 83 | "Remy Bruno <remy.bruno@trinnov.com>"); |
84 | MODULE_DESCRIPTION("RME HDSPM"); | 84 | MODULE_DESCRIPTION("RME HDSPM"); |
@@ -161,7 +161,9 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
161 | 0=off, 1=on */ /* MADI ONLY */ | 161 | 0=off, 1=on */ /* MADI ONLY */ |
162 | #define HDSPM_Dolby (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */ | 162 | #define HDSPM_Dolby (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */ |
163 | 163 | ||
164 | #define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax */ /* MADI ONLY*/ | 164 | #define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax |
165 | * -- MADI ONLY | ||
166 | */ | ||
165 | #define HDSPM_InputSelect1 (1<<15) /* should be 0 */ | 167 | #define HDSPM_InputSelect1 (1<<15) /* should be 0 */ |
166 | 168 | ||
167 | #define HDSPM_SyncRef0 (1<<16) /* 0=WOrd, 1=MADI */ | 169 | #define HDSPM_SyncRef0 (1<<16) /* 0=WOrd, 1=MADI */ |
@@ -189,11 +191,13 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
189 | 191 | ||
190 | /* --- bit helper defines */ | 192 | /* --- bit helper defines */ |
191 | #define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2) | 193 | #define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2) |
192 | #define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1|HDSPM_DoubleSpeed|HDSPM_QuadSpeed) | 194 | #define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1|\ |
195 | HDSPM_DoubleSpeed|HDSPM_QuadSpeed) | ||
193 | #define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1) | 196 | #define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1) |
194 | #define HDSPM_InputOptical 0 | 197 | #define HDSPM_InputOptical 0 |
195 | #define HDSPM_InputCoaxial (HDSPM_InputSelect0) | 198 | #define HDSPM_InputCoaxial (HDSPM_InputSelect0) |
196 | #define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|HDSPM_SyncRef2|HDSPM_SyncRef3) | 199 | #define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|\ |
200 | HDSPM_SyncRef2|HDSPM_SyncRef3) | ||
197 | #define HDSPM_SyncRef_Word 0 | 201 | #define HDSPM_SyncRef_Word 0 |
198 | #define HDSPM_SyncRef_MADI (HDSPM_SyncRef0) | 202 | #define HDSPM_SyncRef_MADI (HDSPM_SyncRef0) |
199 | 203 | ||
@@ -205,10 +209,12 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
205 | #define HDSPM_Frequency48KHz (HDSPM_Frequency1|HDSPM_Frequency0) | 209 | #define HDSPM_Frequency48KHz (HDSPM_Frequency1|HDSPM_Frequency0) |
206 | #define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0) | 210 | #define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0) |
207 | #define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1) | 211 | #define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1) |
208 | #define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|HDSPM_Frequency0) | 212 | #define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|\ |
213 | HDSPM_Frequency0) | ||
209 | #define HDSPM_Frequency128KHz (HDSPM_QuadSpeed|HDSPM_Frequency0) | 214 | #define HDSPM_Frequency128KHz (HDSPM_QuadSpeed|HDSPM_Frequency0) |
210 | #define HDSPM_Frequency176_4KHz (HDSPM_QuadSpeed|HDSPM_Frequency1) | 215 | #define HDSPM_Frequency176_4KHz (HDSPM_QuadSpeed|HDSPM_Frequency1) |
211 | #define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|HDSPM_Frequency0) | 216 | #define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|\ |
217 | HDSPM_Frequency0) | ||
212 | 218 | ||
213 | /* --- for internal discrimination */ | 219 | /* --- for internal discrimination */ |
214 | #define HDSPM_CLOCK_SOURCE_AUTOSYNC 0 /* Sample Clock Sources */ | 220 | #define HDSPM_CLOCK_SOURCE_AUTOSYNC 0 /* Sample Clock Sources */ |
@@ -256,10 +262,14 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
256 | #define HDSPM_RD_MULTIPLE (1<<10) | 262 | #define HDSPM_RD_MULTIPLE (1<<10) |
257 | 263 | ||
258 | /* --- Status Register bits --- */ /* MADI ONLY */ /* Bits defined here and | 264 | /* --- Status Register bits --- */ /* MADI ONLY */ /* Bits defined here and |
259 | that do not conflict with specific bits for AES32 seem to be valid also for the AES32 */ | 265 | that do not conflict with specific bits for AES32 seem to be valid also |
266 | for the AES32 | ||
267 | */ | ||
260 | #define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */ | 268 | #define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */ |
261 | #define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn. MODE=0 */ | 269 | #define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn MODE=0 */ |
262 | #define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1 (like inp0) */ | 270 | #define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1 |
271 | * (like inp0) | ||
272 | */ | ||
263 | #define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */ | 273 | #define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */ |
264 | 274 | ||
265 | #define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */ | 275 | #define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */ |
@@ -274,12 +284,15 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
274 | #define HDSPM_madiFreq2 (1<<24) /* 4=64, 5=88.2 6=96 */ | 284 | #define HDSPM_madiFreq2 (1<<24) /* 4=64, 5=88.2 6=96 */ |
275 | #define HDSPM_madiFreq3 (1<<25) /* 7=128, 8=176.4 9=192 */ | 285 | #define HDSPM_madiFreq3 (1<<25) /* 7=128, 8=176.4 9=192 */ |
276 | 286 | ||
277 | #define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with Interrupt */ | 287 | #define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with |
288 | * Interrupt | ||
289 | */ | ||
278 | #define HDSPM_midi0IRQPending (1<<30) /* MIDI IRQ is pending */ | 290 | #define HDSPM_midi0IRQPending (1<<30) /* MIDI IRQ is pending */ |
279 | #define HDSPM_midi1IRQPending (1<<31) /* and aktiv */ | 291 | #define HDSPM_midi1IRQPending (1<<31) /* and aktiv */ |
280 | 292 | ||
281 | /* --- status bit helpers */ | 293 | /* --- status bit helpers */ |
282 | #define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2|HDSPM_madiFreq3) | 294 | #define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|\ |
295 | HDSPM_madiFreq2|HDSPM_madiFreq3) | ||
283 | #define HDSPM_madiFreq32 (HDSPM_madiFreq0) | 296 | #define HDSPM_madiFreq32 (HDSPM_madiFreq0) |
284 | #define HDSPM_madiFreq44_1 (HDSPM_madiFreq1) | 297 | #define HDSPM_madiFreq44_1 (HDSPM_madiFreq1) |
285 | #define HDSPM_madiFreq48 (HDSPM_madiFreq0|HDSPM_madiFreq1) | 298 | #define HDSPM_madiFreq48 (HDSPM_madiFreq0|HDSPM_madiFreq1) |
@@ -319,10 +332,12 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
319 | #define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2) | 332 | #define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2) |
320 | 333 | ||
321 | 334 | ||
322 | #define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2) | 335 | #define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\ |
336 | HDSPM_SelSyncRef2) | ||
323 | #define HDSPM_SelSyncRef_WORD 0 | 337 | #define HDSPM_SelSyncRef_WORD 0 |
324 | #define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0) | 338 | #define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0) |
325 | #define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2) | 339 | #define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\ |
340 | HDSPM_SelSyncRef2) | ||
326 | 341 | ||
327 | /* | 342 | /* |
328 | For AES32, bits for status, status2 and timecode are different | 343 | For AES32, bits for status, status2 and timecode are different |
@@ -344,7 +359,7 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
344 | #define HDSPM_AES32_AUTOSYNC_FROM_AES6 6 | 359 | #define HDSPM_AES32_AUTOSYNC_FROM_AES6 6 |
345 | #define HDSPM_AES32_AUTOSYNC_FROM_AES7 7 | 360 | #define HDSPM_AES32_AUTOSYNC_FROM_AES7 7 |
346 | #define HDSPM_AES32_AUTOSYNC_FROM_AES8 8 | 361 | #define HDSPM_AES32_AUTOSYNC_FROM_AES8 8 |
347 | #define HDSPM_AES32_AUTOSYNC_FROM_NONE -1 | 362 | #define HDSPM_AES32_AUTOSYNC_FROM_NONE 9 |
348 | 363 | ||
349 | /* status2 */ | 364 | /* status2 */ |
350 | /* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */ | 365 | /* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */ |
@@ -398,6 +413,13 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
398 | /* revisions >= 230 indicate AES32 card */ | 413 | /* revisions >= 230 indicate AES32 card */ |
399 | #define HDSPM_AESREVISION 230 | 414 | #define HDSPM_AESREVISION 230 |
400 | 415 | ||
416 | /* speed factor modes */ | ||
417 | #define HDSPM_SPEED_SINGLE 0 | ||
418 | #define HDSPM_SPEED_DOUBLE 1 | ||
419 | #define HDSPM_SPEED_QUAD 2 | ||
420 | /* names for speed modes */ | ||
421 | static char *hdspm_speed_names[] = { "single", "double", "quad" }; | ||
422 | |||
401 | struct hdspm_midi { | 423 | struct hdspm_midi { |
402 | struct hdspm *hdspm; | 424 | struct hdspm *hdspm; |
403 | int id; | 425 | int id; |
@@ -412,8 +434,9 @@ struct hdspm_midi { | |||
412 | 434 | ||
413 | struct hdspm { | 435 | struct hdspm { |
414 | spinlock_t lock; | 436 | spinlock_t lock; |
415 | struct snd_pcm_substream *capture_substream; /* only one playback */ | 437 | /* only one playback and/or capture stream */ |
416 | struct snd_pcm_substream *playback_substream; /* and/or capture stream */ | 438 | struct snd_pcm_substream *capture_substream; |
439 | struct snd_pcm_substream *playback_substream; | ||
417 | 440 | ||
418 | char *card_name; /* for procinfo */ | 441 | char *card_name; /* for procinfo */ |
419 | unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/ | 442 | unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/ |
@@ -460,9 +483,12 @@ struct hdspm { | |||
460 | struct pci_dev *pci; /* and an pci info */ | 483 | struct pci_dev *pci; /* and an pci info */ |
461 | 484 | ||
462 | /* Mixer vars */ | 485 | /* Mixer vars */ |
463 | struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS]; /* fast alsa mixer */ | 486 | /* fast alsa mixer */ |
464 | struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS]; /* but input to much, so not used */ | 487 | struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS]; |
465 | struct hdspm_mixer *mixer; /* full mixer accessable over mixer ioctl or hwdep-device */ | 488 | /* but input to much, so not used */ |
489 | struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS]; | ||
490 | /* full mixer accessable over mixer ioctl or hwdep-device */ | ||
491 | struct hdspm_mixer *mixer; | ||
466 | 492 | ||
467 | }; | 493 | }; |
468 | 494 | ||
@@ -616,13 +642,15 @@ static inline int hdspm_external_sample_rate(struct hdspm * hdspm) | |||
616 | if (hdspm->is_aes32) { | 642 | if (hdspm->is_aes32) { |
617 | unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | 643 | unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); |
618 | unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); | 644 | unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); |
619 | unsigned int timecode = hdspm_read(hdspm, HDSPM_timecodeRegister); | 645 | unsigned int timecode = |
646 | hdspm_read(hdspm, HDSPM_timecodeRegister); | ||
620 | 647 | ||
621 | int syncref = hdspm_autosync_ref(hdspm); | 648 | int syncref = hdspm_autosync_ref(hdspm); |
622 | 649 | ||
623 | if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD && | 650 | if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD && |
624 | status & HDSPM_AES32_wcLock) | 651 | status & HDSPM_AES32_wcLock) |
625 | return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF); | 652 | return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) |
653 | & 0xF); | ||
626 | if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 && | 654 | if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 && |
627 | syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 && | 655 | syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 && |
628 | status2 & (HDSPM_LockAES >> | 656 | status2 & (HDSPM_LockAES >> |
@@ -668,7 +696,9 @@ static inline int hdspm_external_sample_rate(struct hdspm * hdspm) | |||
668 | } | 696 | } |
669 | } | 697 | } |
670 | 698 | ||
671 | /* if rate detected and Syncref is Word than have it, word has priority to MADI */ | 699 | /* if rate detected and Syncref is Word than have it, |
700 | * word has priority to MADI | ||
701 | */ | ||
672 | if (rate != 0 && | 702 | if (rate != 0 && |
673 | (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD) | 703 | (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD) |
674 | return rate; | 704 | return rate; |
@@ -727,12 +757,12 @@ static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm * hdspm) | |||
727 | 757 | ||
728 | position = hdspm_read(hdspm, HDSPM_statusRegister); | 758 | position = hdspm_read(hdspm, HDSPM_statusRegister); |
729 | 759 | ||
730 | if (!hdspm->precise_ptr) { | 760 | if (!hdspm->precise_ptr) |
731 | return (position & HDSPM_BufferID) ? (hdspm->period_bytes / | 761 | return (position & HDSPM_BufferID) ? |
732 | 4) : 0; | 762 | (hdspm->period_bytes / 4) : 0; |
733 | } | ||
734 | 763 | ||
735 | /* hwpointer comes in bytes and is 64Bytes accurate (by docu since PCI Burst) | 764 | /* hwpointer comes in bytes and is 64Bytes accurate (by docu since |
765 | PCI Burst) | ||
736 | i have experimented that it is at most 64 Byte to much for playing | 766 | i have experimented that it is at most 64 Byte to much for playing |
737 | so substraction of 64 byte should be ok for ALSA, but use it only | 767 | so substraction of 64 byte should be ok for ALSA, but use it only |
738 | for application where you know what you do since if you come to | 768 | for application where you know what you do since if you come to |
@@ -811,7 +841,7 @@ static void hdspm_set_dds_value(struct hdspm *hdspm, int rate) | |||
811 | // return 104857600000000 / rate; // 100 MHz | 841 | // return 104857600000000 / rate; // 100 MHz |
812 | return 110100480000000 / rate; // 105 MHz | 842 | return 110100480000000 / rate; // 105 MHz |
813 | */ | 843 | */ |
814 | //n = 104857600000000ULL; /* = 2^20 * 10^8 */ | 844 | /* n = 104857600000000ULL; */ /* = 2^20 * 10^8 */ |
815 | n = 110100480000000ULL; /* Value checked for AES32 and MADI */ | 845 | n = 110100480000000ULL; /* Value checked for AES32 and MADI */ |
816 | div64_32(&n, rate, &r); | 846 | div64_32(&n, rate, &r); |
817 | /* n should be less than 2^32 for being written to FREQ register */ | 847 | /* n should be less than 2^32 for being written to FREQ register */ |
@@ -822,11 +852,10 @@ static void hdspm_set_dds_value(struct hdspm *hdspm, int rate) | |||
822 | /* dummy set rate lets see what happens */ | 852 | /* dummy set rate lets see what happens */ |
823 | static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) | 853 | static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) |
824 | { | 854 | { |
825 | int reject_if_open = 0; | ||
826 | int current_rate; | 855 | int current_rate; |
827 | int rate_bits; | 856 | int rate_bits; |
828 | int not_set = 0; | 857 | int not_set = 0; |
829 | int is_single, is_double, is_quad; | 858 | int current_speed, target_speed; |
830 | 859 | ||
831 | /* ASSUMPTION: hdspm->lock is either set, or there is no need for | 860 | /* ASSUMPTION: hdspm->lock is either set, or there is no need for |
832 | it (e.g. during module initialization). | 861 | it (e.g. during module initialization). |
@@ -841,8 +870,9 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) | |||
841 | just make a warning an remember setting | 870 | just make a warning an remember setting |
842 | for future master mode switching */ | 871 | for future master mode switching */ |
843 | 872 | ||
844 | snd_printk | 873 | snd_printk(KERN_WARNING "HDSPM: " |
845 | (KERN_WARNING "HDSPM: Warning: device is not running as a clock master.\n"); | 874 | "Warning: device is not running " |
875 | "as a clock master.\n"); | ||
846 | not_set = 1; | 876 | not_set = 1; |
847 | } else { | 877 | } else { |
848 | 878 | ||
@@ -850,16 +880,18 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) | |||
850 | int external_freq = | 880 | int external_freq = |
851 | hdspm_external_sample_rate(hdspm); | 881 | hdspm_external_sample_rate(hdspm); |
852 | 882 | ||
853 | if ((hdspm_autosync_ref(hdspm) == | 883 | if (hdspm_autosync_ref(hdspm) == |
854 | HDSPM_AUTOSYNC_FROM_NONE)) { | 884 | HDSPM_AUTOSYNC_FROM_NONE) { |
855 | 885 | ||
856 | snd_printk(KERN_WARNING "HDSPM: Detected no Externel Sync \n"); | 886 | snd_printk(KERN_WARNING "HDSPM: " |
887 | "Detected no Externel Sync \n"); | ||
857 | not_set = 1; | 888 | not_set = 1; |
858 | 889 | ||
859 | } else if (rate != external_freq) { | 890 | } else if (rate != external_freq) { |
860 | 891 | ||
861 | snd_printk | 892 | snd_printk(KERN_WARNING "HDSPM: " |
862 | (KERN_WARNING "HDSPM: Warning: No AutoSync source for requested rate\n"); | 893 | "Warning: No AutoSync source for " |
894 | "requested rate\n"); | ||
863 | not_set = 1; | 895 | not_set = 1; |
864 | } | 896 | } |
865 | } | 897 | } |
@@ -877,64 +909,60 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) | |||
877 | changes in the read/write routines. | 909 | changes in the read/write routines. |
878 | */ | 910 | */ |
879 | 911 | ||
880 | is_single = (current_rate <= 48000); | 912 | if (current_rate <= 48000) |
881 | is_double = (current_rate > 48000 && current_rate <= 96000); | 913 | current_speed = HDSPM_SPEED_SINGLE; |
882 | is_quad = (current_rate > 96000); | 914 | else if (current_rate <= 96000) |
915 | current_speed = HDSPM_SPEED_DOUBLE; | ||
916 | else | ||
917 | current_speed = HDSPM_SPEED_QUAD; | ||
918 | |||
919 | if (rate <= 48000) | ||
920 | target_speed = HDSPM_SPEED_SINGLE; | ||
921 | else if (rate <= 96000) | ||
922 | target_speed = HDSPM_SPEED_DOUBLE; | ||
923 | else | ||
924 | target_speed = HDSPM_SPEED_QUAD; | ||
883 | 925 | ||
884 | switch (rate) { | 926 | switch (rate) { |
885 | case 32000: | 927 | case 32000: |
886 | if (!is_single) | ||
887 | reject_if_open = 1; | ||
888 | rate_bits = HDSPM_Frequency32KHz; | 928 | rate_bits = HDSPM_Frequency32KHz; |
889 | break; | 929 | break; |
890 | case 44100: | 930 | case 44100: |
891 | if (!is_single) | ||
892 | reject_if_open = 1; | ||
893 | rate_bits = HDSPM_Frequency44_1KHz; | 931 | rate_bits = HDSPM_Frequency44_1KHz; |
894 | break; | 932 | break; |
895 | case 48000: | 933 | case 48000: |
896 | if (!is_single) | ||
897 | reject_if_open = 1; | ||
898 | rate_bits = HDSPM_Frequency48KHz; | 934 | rate_bits = HDSPM_Frequency48KHz; |
899 | break; | 935 | break; |
900 | case 64000: | 936 | case 64000: |
901 | if (!is_double) | ||
902 | reject_if_open = 1; | ||
903 | rate_bits = HDSPM_Frequency64KHz; | 937 | rate_bits = HDSPM_Frequency64KHz; |
904 | break; | 938 | break; |
905 | case 88200: | 939 | case 88200: |
906 | if (!is_double) | ||
907 | reject_if_open = 1; | ||
908 | rate_bits = HDSPM_Frequency88_2KHz; | 940 | rate_bits = HDSPM_Frequency88_2KHz; |
909 | break; | 941 | break; |
910 | case 96000: | 942 | case 96000: |
911 | if (!is_double) | ||
912 | reject_if_open = 1; | ||
913 | rate_bits = HDSPM_Frequency96KHz; | 943 | rate_bits = HDSPM_Frequency96KHz; |
914 | break; | 944 | break; |
915 | case 128000: | 945 | case 128000: |
916 | if (!is_quad) | ||
917 | reject_if_open = 1; | ||
918 | rate_bits = HDSPM_Frequency128KHz; | 946 | rate_bits = HDSPM_Frequency128KHz; |
919 | break; | 947 | break; |
920 | case 176400: | 948 | case 176400: |
921 | if (!is_quad) | ||
922 | reject_if_open = 1; | ||
923 | rate_bits = HDSPM_Frequency176_4KHz; | 949 | rate_bits = HDSPM_Frequency176_4KHz; |
924 | break; | 950 | break; |
925 | case 192000: | 951 | case 192000: |
926 | if (!is_quad) | ||
927 | reject_if_open = 1; | ||
928 | rate_bits = HDSPM_Frequency192KHz; | 952 | rate_bits = HDSPM_Frequency192KHz; |
929 | break; | 953 | break; |
930 | default: | 954 | default: |
931 | return -EINVAL; | 955 | return -EINVAL; |
932 | } | 956 | } |
933 | 957 | ||
934 | if (reject_if_open | 958 | if (current_speed != target_speed |
935 | && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) { | 959 | && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) { |
936 | snd_printk | 960 | snd_printk |
937 | (KERN_ERR "HDSPM: cannot change between single- and double-speed mode (capture PID = %d, playback PID = %d)\n", | 961 | (KERN_ERR "HDSPM: " |
962 | "cannot change from %s speed to %s speed mode " | ||
963 | "(capture PID = %d, playback PID = %d)\n", | ||
964 | hdspm_speed_names[current_speed], | ||
965 | hdspm_speed_names[target_speed], | ||
938 | hdspm->capture_pid, hdspm->playback_pid); | 966 | hdspm->capture_pid, hdspm->playback_pid); |
939 | return -EBUSY; | 967 | return -EBUSY; |
940 | } | 968 | } |
@@ -966,8 +994,14 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) | |||
966 | static void all_in_all_mixer(struct hdspm * hdspm, int sgain) | 994 | static void all_in_all_mixer(struct hdspm * hdspm, int sgain) |
967 | { | 995 | { |
968 | int i, j; | 996 | int i, j; |
969 | unsigned int gain = | 997 | unsigned int gain; |
970 | (sgain > UNITY_GAIN) ? UNITY_GAIN : (sgain < 0) ? 0 : sgain; | 998 | |
999 | if (sgain > UNITY_GAIN) | ||
1000 | gain = UNITY_GAIN; | ||
1001 | else if (sgain < 0) | ||
1002 | gain = 0; | ||
1003 | else | ||
1004 | gain = sgain; | ||
971 | 1005 | ||
972 | for (i = 0; i < HDSPM_MIXER_CHANNELS; i++) | 1006 | for (i = 0; i < HDSPM_MIXER_CHANNELS; i++) |
973 | for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) { | 1007 | for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) { |
@@ -980,7 +1014,8 @@ static void all_in_all_mixer(struct hdspm * hdspm, int sgain) | |||
980 | MIDI | 1014 | MIDI |
981 | ----------------------------------------------------------------------------*/ | 1015 | ----------------------------------------------------------------------------*/ |
982 | 1016 | ||
983 | static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm, int id) | 1017 | static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm, |
1018 | int id) | ||
984 | { | 1019 | { |
985 | /* the hardware already does the relevant bit-mask with 0xff */ | 1020 | /* the hardware already does the relevant bit-mask with 0xff */ |
986 | if (id) | 1021 | if (id) |
@@ -989,7 +1024,8 @@ static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm, int i | |||
989 | return hdspm_read(hdspm, HDSPM_midiDataIn0); | 1024 | return hdspm_read(hdspm, HDSPM_midiDataIn0); |
990 | } | 1025 | } |
991 | 1026 | ||
992 | static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id, int val) | 1027 | static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id, |
1028 | int val) | ||
993 | { | 1029 | { |
994 | /* the hardware already does the relevant bit-mask with 0xff */ | 1030 | /* the hardware already does the relevant bit-mask with 0xff */ |
995 | if (id) | 1031 | if (id) |
@@ -1011,9 +1047,10 @@ static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id) | |||
1011 | int fifo_bytes_used; | 1047 | int fifo_bytes_used; |
1012 | 1048 | ||
1013 | if (id) | 1049 | if (id) |
1014 | fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xff; | 1050 | fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut1); |
1015 | else | 1051 | else |
1016 | fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xff; | 1052 | fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut0); |
1053 | fifo_bytes_used &= 0xff; | ||
1017 | 1054 | ||
1018 | if (fifo_bytes_used < 128) | 1055 | if (fifo_bytes_used < 128) |
1019 | return 128 - fifo_bytes_used; | 1056 | return 128 - fifo_bytes_used; |
@@ -1038,16 +1075,21 @@ static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi) | |||
1038 | /* Output is not interrupt driven */ | 1075 | /* Output is not interrupt driven */ |
1039 | 1076 | ||
1040 | spin_lock_irqsave (&hmidi->lock, flags); | 1077 | spin_lock_irqsave (&hmidi->lock, flags); |
1041 | if (hmidi->output) { | 1078 | if (hmidi->output && |
1042 | if (!snd_rawmidi_transmit_empty (hmidi->output)) { | 1079 | !snd_rawmidi_transmit_empty (hmidi->output)) { |
1043 | if ((n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm, hmidi->id)) > 0) { | 1080 | n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm, |
1044 | if (n_pending > (int)sizeof (buf)) | 1081 | hmidi->id); |
1045 | n_pending = sizeof (buf); | 1082 | if (n_pending > 0) { |
1046 | 1083 | if (n_pending > (int)sizeof (buf)) | |
1047 | if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) { | 1084 | n_pending = sizeof (buf); |
1048 | for (i = 0; i < to_write; ++i) | 1085 | |
1049 | snd_hdspm_midi_write_byte (hmidi->hdspm, hmidi->id, buf[i]); | 1086 | to_write = snd_rawmidi_transmit (hmidi->output, buf, |
1050 | } | 1087 | n_pending); |
1088 | if (to_write > 0) { | ||
1089 | for (i = 0; i < to_write; ++i) | ||
1090 | snd_hdspm_midi_write_byte (hmidi->hdspm, | ||
1091 | hmidi->id, | ||
1092 | buf[i]); | ||
1051 | } | 1093 | } |
1052 | } | 1094 | } |
1053 | } | 1095 | } |
@@ -1057,51 +1099,55 @@ static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi) | |||
1057 | 1099 | ||
1058 | static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi) | 1100 | static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi) |
1059 | { | 1101 | { |
1060 | unsigned char buf[128]; /* this buffer is designed to match the MIDI input FIFO size */ | 1102 | unsigned char buf[128]; /* this buffer is designed to match the MIDI |
1103 | * input FIFO size | ||
1104 | */ | ||
1061 | unsigned long flags; | 1105 | unsigned long flags; |
1062 | int n_pending; | 1106 | int n_pending; |
1063 | int i; | 1107 | int i; |
1064 | 1108 | ||
1065 | spin_lock_irqsave (&hmidi->lock, flags); | 1109 | spin_lock_irqsave (&hmidi->lock, flags); |
1066 | if ((n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id)) > 0) { | 1110 | n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id); |
1111 | if (n_pending > 0) { | ||
1067 | if (hmidi->input) { | 1112 | if (hmidi->input) { |
1068 | if (n_pending > (int)sizeof (buf)) { | 1113 | if (n_pending > (int)sizeof (buf)) |
1069 | n_pending = sizeof (buf); | 1114 | n_pending = sizeof (buf); |
1070 | } | 1115 | for (i = 0; i < n_pending; ++i) |
1071 | for (i = 0; i < n_pending; ++i) { | 1116 | buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm, |
1072 | buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm, hmidi->id); | 1117 | hmidi->id); |
1073 | } | 1118 | if (n_pending) |
1074 | if (n_pending) { | 1119 | snd_rawmidi_receive (hmidi->input, buf, |
1075 | snd_rawmidi_receive (hmidi->input, buf, n_pending); | 1120 | n_pending); |
1076 | } | ||
1077 | } else { | 1121 | } else { |
1078 | /* flush the MIDI input FIFO */ | 1122 | /* flush the MIDI input FIFO */ |
1079 | while (n_pending--) { | 1123 | while (n_pending--) |
1080 | snd_hdspm_midi_read_byte (hmidi->hdspm, hmidi->id); | 1124 | snd_hdspm_midi_read_byte (hmidi->hdspm, |
1081 | } | 1125 | hmidi->id); |
1082 | } | 1126 | } |
1083 | } | 1127 | } |
1084 | hmidi->pending = 0; | 1128 | hmidi->pending = 0; |
1085 | if (hmidi->id) { | 1129 | if (hmidi->id) |
1086 | hmidi->hdspm->control_register |= HDSPM_Midi1InterruptEnable; | 1130 | hmidi->hdspm->control_register |= HDSPM_Midi1InterruptEnable; |
1087 | } else { | 1131 | else |
1088 | hmidi->hdspm->control_register |= HDSPM_Midi0InterruptEnable; | 1132 | hmidi->hdspm->control_register |= HDSPM_Midi0InterruptEnable; |
1089 | } | 1133 | hdspm_write(hmidi->hdspm, HDSPM_controlRegister, |
1090 | hdspm_write(hmidi->hdspm, HDSPM_controlRegister, hmidi->hdspm->control_register); | 1134 | hmidi->hdspm->control_register); |
1091 | spin_unlock_irqrestore (&hmidi->lock, flags); | 1135 | spin_unlock_irqrestore (&hmidi->lock, flags); |
1092 | return snd_hdspm_midi_output_write (hmidi); | 1136 | return snd_hdspm_midi_output_write (hmidi); |
1093 | } | 1137 | } |
1094 | 1138 | ||
1095 | static void snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) | 1139 | static void |
1140 | snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) | ||
1096 | { | 1141 | { |
1097 | struct hdspm *hdspm; | 1142 | struct hdspm *hdspm; |
1098 | struct hdspm_midi *hmidi; | 1143 | struct hdspm_midi *hmidi; |
1099 | unsigned long flags; | 1144 | unsigned long flags; |
1100 | u32 ie; | 1145 | u32 ie; |
1101 | 1146 | ||
1102 | hmidi = (struct hdspm_midi *) substream->rmidi->private_data; | 1147 | hmidi = substream->rmidi->private_data; |
1103 | hdspm = hmidi->hdspm; | 1148 | hdspm = hmidi->hdspm; |
1104 | ie = hmidi->id ? HDSPM_Midi1InterruptEnable : HDSPM_Midi0InterruptEnable; | 1149 | ie = hmidi->id ? |
1150 | HDSPM_Midi1InterruptEnable : HDSPM_Midi0InterruptEnable; | ||
1105 | spin_lock_irqsave (&hdspm->lock, flags); | 1151 | spin_lock_irqsave (&hdspm->lock, flags); |
1106 | if (up) { | 1152 | if (up) { |
1107 | if (!(hdspm->control_register & ie)) { | 1153 | if (!(hdspm->control_register & ie)) { |
@@ -1138,12 +1184,13 @@ static void snd_hdspm_midi_output_timer(unsigned long data) | |||
1138 | spin_unlock_irqrestore (&hmidi->lock, flags); | 1184 | spin_unlock_irqrestore (&hmidi->lock, flags); |
1139 | } | 1185 | } |
1140 | 1186 | ||
1141 | static void snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) | 1187 | static void |
1188 | snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) | ||
1142 | { | 1189 | { |
1143 | struct hdspm_midi *hmidi; | 1190 | struct hdspm_midi *hmidi; |
1144 | unsigned long flags; | 1191 | unsigned long flags; |
1145 | 1192 | ||
1146 | hmidi = (struct hdspm_midi *) substream->rmidi->private_data; | 1193 | hmidi = substream->rmidi->private_data; |
1147 | spin_lock_irqsave (&hmidi->lock, flags); | 1194 | spin_lock_irqsave (&hmidi->lock, flags); |
1148 | if (up) { | 1195 | if (up) { |
1149 | if (!hmidi->istimer) { | 1196 | if (!hmidi->istimer) { |
@@ -1155,9 +1202,8 @@ static void snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substrea | |||
1155 | hmidi->istimer++; | 1202 | hmidi->istimer++; |
1156 | } | 1203 | } |
1157 | } else { | 1204 | } else { |
1158 | if (hmidi->istimer && --hmidi->istimer <= 0) { | 1205 | if (hmidi->istimer && --hmidi->istimer <= 0) |
1159 | del_timer (&hmidi->timer); | 1206 | del_timer (&hmidi->timer); |
1160 | } | ||
1161 | } | 1207 | } |
1162 | spin_unlock_irqrestore (&hmidi->lock, flags); | 1208 | spin_unlock_irqrestore (&hmidi->lock, flags); |
1163 | if (up) | 1209 | if (up) |
@@ -1168,7 +1214,7 @@ static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream) | |||
1168 | { | 1214 | { |
1169 | struct hdspm_midi *hmidi; | 1215 | struct hdspm_midi *hmidi; |
1170 | 1216 | ||
1171 | hmidi = (struct hdspm_midi *) substream->rmidi->private_data; | 1217 | hmidi = substream->rmidi->private_data; |
1172 | spin_lock_irq (&hmidi->lock); | 1218 | spin_lock_irq (&hmidi->lock); |
1173 | snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id); | 1219 | snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id); |
1174 | hmidi->input = substream; | 1220 | hmidi->input = substream; |
@@ -1181,7 +1227,7 @@ static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream) | |||
1181 | { | 1227 | { |
1182 | struct hdspm_midi *hmidi; | 1228 | struct hdspm_midi *hmidi; |
1183 | 1229 | ||
1184 | hmidi = (struct hdspm_midi *) substream->rmidi->private_data; | 1230 | hmidi = substream->rmidi->private_data; |
1185 | spin_lock_irq (&hmidi->lock); | 1231 | spin_lock_irq (&hmidi->lock); |
1186 | hmidi->output = substream; | 1232 | hmidi->output = substream; |
1187 | spin_unlock_irq (&hmidi->lock); | 1233 | spin_unlock_irq (&hmidi->lock); |
@@ -1195,7 +1241,7 @@ static int snd_hdspm_midi_input_close(struct snd_rawmidi_substream *substream) | |||
1195 | 1241 | ||
1196 | snd_hdspm_midi_input_trigger (substream, 0); | 1242 | snd_hdspm_midi_input_trigger (substream, 0); |
1197 | 1243 | ||
1198 | hmidi = (struct hdspm_midi *) substream->rmidi->private_data; | 1244 | hmidi = substream->rmidi->private_data; |
1199 | spin_lock_irq (&hmidi->lock); | 1245 | spin_lock_irq (&hmidi->lock); |
1200 | hmidi->input = NULL; | 1246 | hmidi->input = NULL; |
1201 | spin_unlock_irq (&hmidi->lock); | 1247 | spin_unlock_irq (&hmidi->lock); |
@@ -1209,7 +1255,7 @@ static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream) | |||
1209 | 1255 | ||
1210 | snd_hdspm_midi_output_trigger (substream, 0); | 1256 | snd_hdspm_midi_output_trigger (substream, 0); |
1211 | 1257 | ||
1212 | hmidi = (struct hdspm_midi *) substream->rmidi->private_data; | 1258 | hmidi = substream->rmidi->private_data; |
1213 | spin_lock_irq (&hmidi->lock); | 1259 | spin_lock_irq (&hmidi->lock); |
1214 | hmidi->output = NULL; | 1260 | hmidi->output = NULL; |
1215 | spin_unlock_irq (&hmidi->lock); | 1261 | spin_unlock_irq (&hmidi->lock); |
@@ -1231,29 +1277,28 @@ static struct snd_rawmidi_ops snd_hdspm_midi_input = | |||
1231 | .trigger = snd_hdspm_midi_input_trigger, | 1277 | .trigger = snd_hdspm_midi_input_trigger, |
1232 | }; | 1278 | }; |
1233 | 1279 | ||
1234 | static int __devinit snd_hdspm_create_midi (struct snd_card *card, struct hdspm *hdspm, int id) | 1280 | static int __devinit snd_hdspm_create_midi (struct snd_card *card, |
1281 | struct hdspm *hdspm, int id) | ||
1235 | { | 1282 | { |
1236 | int err; | 1283 | int err; |
1237 | char buf[32]; | 1284 | char buf[32]; |
1238 | 1285 | ||
1239 | hdspm->midi[id].id = id; | 1286 | hdspm->midi[id].id = id; |
1240 | hdspm->midi[id].rmidi = NULL; | ||
1241 | hdspm->midi[id].input = NULL; | ||
1242 | hdspm->midi[id].output = NULL; | ||
1243 | hdspm->midi[id].hdspm = hdspm; | 1287 | hdspm->midi[id].hdspm = hdspm; |
1244 | hdspm->midi[id].istimer = 0; | ||
1245 | hdspm->midi[id].pending = 0; | ||
1246 | spin_lock_init (&hdspm->midi[id].lock); | 1288 | spin_lock_init (&hdspm->midi[id].lock); |
1247 | 1289 | ||
1248 | sprintf (buf, "%s MIDI %d", card->shortname, id+1); | 1290 | sprintf (buf, "%s MIDI %d", card->shortname, id+1); |
1249 | if ((err = snd_rawmidi_new (card, buf, id, 1, 1, &hdspm->midi[id].rmidi)) < 0) | 1291 | err = snd_rawmidi_new (card, buf, id, 1, 1, &hdspm->midi[id].rmidi); |
1292 | if (err < 0) | ||
1250 | return err; | 1293 | return err; |
1251 | 1294 | ||
1252 | sprintf (hdspm->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1); | 1295 | sprintf (hdspm->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1); |
1253 | hdspm->midi[id].rmidi->private_data = &hdspm->midi[id]; | 1296 | hdspm->midi[id].rmidi->private_data = &hdspm->midi[id]; |
1254 | 1297 | ||
1255 | snd_rawmidi_set_ops (hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_hdspm_midi_output); | 1298 | snd_rawmidi_set_ops(hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, |
1256 | snd_rawmidi_set_ops (hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_hdspm_midi_input); | 1299 | &snd_hdspm_midi_output); |
1300 | snd_rawmidi_set_ops(hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT, | ||
1301 | &snd_hdspm_midi_input); | ||
1257 | 1302 | ||
1258 | hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | | 1303 | hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | |
1259 | SNDRV_RAWMIDI_INFO_INPUT | | 1304 | SNDRV_RAWMIDI_INFO_INPUT | |
@@ -1558,8 +1603,8 @@ static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol, | |||
1558 | val = ucontrol->value.enumerated.item[0]; | 1603 | val = ucontrol->value.enumerated.item[0]; |
1559 | if (val < 0) | 1604 | if (val < 0) |
1560 | val = 0; | 1605 | val = 0; |
1561 | if (val > 6) | 1606 | if (val > 9) |
1562 | val = 6; | 1607 | val = 9; |
1563 | spin_lock_irq(&hdspm->lock); | 1608 | spin_lock_irq(&hdspm->lock); |
1564 | if (val != hdspm_clock_source(hdspm)) | 1609 | if (val != hdspm_clock_source(hdspm)) |
1565 | change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0; | 1610 | change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0; |
@@ -1637,7 +1682,8 @@ static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref) | |||
1637 | hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef1; | 1682 | hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef1; |
1638 | break; | 1683 | break; |
1639 | case 7: | 1684 | case 7: |
1640 | hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0; | 1685 | hdspm->control_register |= |
1686 | HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0; | ||
1641 | break; | 1687 | break; |
1642 | case 8: | 1688 | case 8: |
1643 | hdspm->control_register |= HDSPM_SyncRef3; | 1689 | hdspm->control_register |= HDSPM_SyncRef3; |
@@ -1675,7 +1721,8 @@ static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol, | |||
1675 | 1721 | ||
1676 | uinfo->value.enumerated.items = 9; | 1722 | uinfo->value.enumerated.items = 9; |
1677 | 1723 | ||
1678 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | 1724 | if (uinfo->value.enumerated.item >= |
1725 | uinfo->value.enumerated.items) | ||
1679 | uinfo->value.enumerated.item = | 1726 | uinfo->value.enumerated.item = |
1680 | uinfo->value.enumerated.items - 1; | 1727 | uinfo->value.enumerated.items - 1; |
1681 | strcpy(uinfo->value.enumerated.name, | 1728 | strcpy(uinfo->value.enumerated.name, |
@@ -1688,7 +1735,8 @@ static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol, | |||
1688 | 1735 | ||
1689 | uinfo->value.enumerated.items = 2; | 1736 | uinfo->value.enumerated.items = 2; |
1690 | 1737 | ||
1691 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | 1738 | if (uinfo->value.enumerated.item >= |
1739 | uinfo->value.enumerated.items) | ||
1692 | uinfo->value.enumerated.item = | 1740 | uinfo->value.enumerated.item = |
1693 | uinfo->value.enumerated.items - 1; | 1741 | uinfo->value.enumerated.items - 1; |
1694 | strcpy(uinfo->value.enumerated.name, | 1742 | strcpy(uinfo->value.enumerated.name, |
@@ -1740,7 +1788,8 @@ static int hdspm_autosync_ref(struct hdspm * hdspm) | |||
1740 | { | 1788 | { |
1741 | if (hdspm->is_aes32) { | 1789 | if (hdspm->is_aes32) { |
1742 | unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); | 1790 | unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); |
1743 | unsigned int syncref = (status >> HDSPM_AES32_syncref_bit) & 0xF; | 1791 | unsigned int syncref = (status >> HDSPM_AES32_syncref_bit) & |
1792 | 0xF; | ||
1744 | if (syncref == 0) | 1793 | if (syncref == 0) |
1745 | return HDSPM_AES32_AUTOSYNC_FROM_WORD; | 1794 | return HDSPM_AES32_AUTOSYNC_FROM_WORD; |
1746 | if (syncref <= 8) | 1795 | if (syncref <= 8) |
@@ -1777,20 +1826,20 @@ static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol, | |||
1777 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 1826 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1778 | uinfo->count = 1; | 1827 | uinfo->count = 1; |
1779 | uinfo->value.enumerated.items = 10; | 1828 | uinfo->value.enumerated.items = 10; |
1780 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | 1829 | if (uinfo->value.enumerated.item >= |
1830 | uinfo->value.enumerated.items) | ||
1781 | uinfo->value.enumerated.item = | 1831 | uinfo->value.enumerated.item = |
1782 | uinfo->value.enumerated.items - 1; | 1832 | uinfo->value.enumerated.items - 1; |
1783 | strcpy(uinfo->value.enumerated.name, | 1833 | strcpy(uinfo->value.enumerated.name, |
1784 | texts[uinfo->value.enumerated.item]); | 1834 | texts[uinfo->value.enumerated.item]); |
1785 | } | 1835 | } else { |
1786 | else | ||
1787 | { | ||
1788 | static char *texts[] = { "WordClock", "MADI", "None" }; | 1836 | static char *texts[] = { "WordClock", "MADI", "None" }; |
1789 | 1837 | ||
1790 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 1838 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1791 | uinfo->count = 1; | 1839 | uinfo->count = 1; |
1792 | uinfo->value.enumerated.items = 3; | 1840 | uinfo->value.enumerated.items = 3; |
1793 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | 1841 | if (uinfo->value.enumerated.item >= |
1842 | uinfo->value.enumerated.items) | ||
1794 | uinfo->value.enumerated.item = | 1843 | uinfo->value.enumerated.item = |
1795 | uinfo->value.enumerated.items - 1; | 1844 | uinfo->value.enumerated.items - 1; |
1796 | strcpy(uinfo->value.enumerated.name, | 1845 | strcpy(uinfo->value.enumerated.name, |
@@ -1804,7 +1853,7 @@ static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol, | |||
1804 | { | 1853 | { |
1805 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 1854 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
1806 | 1855 | ||
1807 | ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm); | 1856 | ucontrol->value.enumerated.item[0] = hdspm_autosync_ref(hdspm); |
1808 | return 0; | 1857 | return 0; |
1809 | } | 1858 | } |
1810 | 1859 | ||
@@ -1834,15 +1883,7 @@ static int hdspm_set_line_output(struct hdspm * hdspm, int out) | |||
1834 | return 0; | 1883 | return 0; |
1835 | } | 1884 | } |
1836 | 1885 | ||
1837 | static int snd_hdspm_info_line_out(struct snd_kcontrol *kcontrol, | 1886 | #define snd_hdspm_info_line_out snd_ctl_boolean_mono_info |
1838 | struct snd_ctl_elem_info *uinfo) | ||
1839 | { | ||
1840 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1841 | uinfo->count = 1; | ||
1842 | uinfo->value.integer.min = 0; | ||
1843 | uinfo->value.integer.max = 1; | ||
1844 | return 0; | ||
1845 | } | ||
1846 | 1887 | ||
1847 | static int snd_hdspm_get_line_out(struct snd_kcontrol *kcontrol, | 1888 | static int snd_hdspm_get_line_out(struct snd_kcontrol *kcontrol, |
1848 | struct snd_ctl_elem_value *ucontrol) | 1889 | struct snd_ctl_elem_value *ucontrol) |
@@ -1897,15 +1938,7 @@ static int hdspm_set_tx_64(struct hdspm * hdspm, int out) | |||
1897 | return 0; | 1938 | return 0; |
1898 | } | 1939 | } |
1899 | 1940 | ||
1900 | static int snd_hdspm_info_tx_64(struct snd_kcontrol *kcontrol, | 1941 | #define snd_hdspm_info_tx_64 snd_ctl_boolean_mono_info |
1901 | struct snd_ctl_elem_info *uinfo) | ||
1902 | { | ||
1903 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1904 | uinfo->count = 1; | ||
1905 | uinfo->value.integer.min = 0; | ||
1906 | uinfo->value.integer.max = 1; | ||
1907 | return 0; | ||
1908 | } | ||
1909 | 1942 | ||
1910 | static int snd_hdspm_get_tx_64(struct snd_kcontrol *kcontrol, | 1943 | static int snd_hdspm_get_tx_64(struct snd_kcontrol *kcontrol, |
1911 | struct snd_ctl_elem_value *ucontrol) | 1944 | struct snd_ctl_elem_value *ucontrol) |
@@ -1960,15 +1993,7 @@ static int hdspm_set_c_tms(struct hdspm * hdspm, int out) | |||
1960 | return 0; | 1993 | return 0; |
1961 | } | 1994 | } |
1962 | 1995 | ||
1963 | static int snd_hdspm_info_c_tms(struct snd_kcontrol *kcontrol, | 1996 | #define snd_hdspm_info_c_tms snd_ctl_boolean_mono_info |
1964 | struct snd_ctl_elem_info *uinfo) | ||
1965 | { | ||
1966 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1967 | uinfo->count = 1; | ||
1968 | uinfo->value.integer.min = 0; | ||
1969 | uinfo->value.integer.max = 1; | ||
1970 | return 0; | ||
1971 | } | ||
1972 | 1997 | ||
1973 | static int snd_hdspm_get_c_tms(struct snd_kcontrol *kcontrol, | 1998 | static int snd_hdspm_get_c_tms(struct snd_kcontrol *kcontrol, |
1974 | struct snd_ctl_elem_value *ucontrol) | 1999 | struct snd_ctl_elem_value *ucontrol) |
@@ -2023,15 +2048,7 @@ static int hdspm_set_safe_mode(struct hdspm * hdspm, int out) | |||
2023 | return 0; | 2048 | return 0; |
2024 | } | 2049 | } |
2025 | 2050 | ||
2026 | static int snd_hdspm_info_safe_mode(struct snd_kcontrol *kcontrol, | 2051 | #define snd_hdspm_info_safe_mode snd_ctl_boolean_mono_info |
2027 | struct snd_ctl_elem_info *uinfo) | ||
2028 | { | ||
2029 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2030 | uinfo->count = 1; | ||
2031 | uinfo->value.integer.min = 0; | ||
2032 | uinfo->value.integer.max = 1; | ||
2033 | return 0; | ||
2034 | } | ||
2035 | 2052 | ||
2036 | static int snd_hdspm_get_safe_mode(struct snd_kcontrol *kcontrol, | 2053 | static int snd_hdspm_get_safe_mode(struct snd_kcontrol *kcontrol, |
2037 | struct snd_ctl_elem_value *ucontrol) | 2054 | struct snd_ctl_elem_value *ucontrol) |
@@ -2086,15 +2103,7 @@ static int hdspm_set_emphasis(struct hdspm * hdspm, int emp) | |||
2086 | return 0; | 2103 | return 0; |
2087 | } | 2104 | } |
2088 | 2105 | ||
2089 | static int snd_hdspm_info_emphasis(struct snd_kcontrol *kcontrol, | 2106 | #define snd_hdspm_info_emphasis snd_ctl_boolean_mono_info |
2090 | struct snd_ctl_elem_info *uinfo) | ||
2091 | { | ||
2092 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2093 | uinfo->count = 1; | ||
2094 | uinfo->value.integer.min = 0; | ||
2095 | uinfo->value.integer.max = 1; | ||
2096 | return 0; | ||
2097 | } | ||
2098 | 2107 | ||
2099 | static int snd_hdspm_get_emphasis(struct snd_kcontrol *kcontrol, | 2108 | static int snd_hdspm_get_emphasis(struct snd_kcontrol *kcontrol, |
2100 | struct snd_ctl_elem_value *ucontrol) | 2109 | struct snd_ctl_elem_value *ucontrol) |
@@ -2149,15 +2158,7 @@ static int hdspm_set_dolby(struct hdspm * hdspm, int dol) | |||
2149 | return 0; | 2158 | return 0; |
2150 | } | 2159 | } |
2151 | 2160 | ||
2152 | static int snd_hdspm_info_dolby(struct snd_kcontrol *kcontrol, | 2161 | #define snd_hdspm_info_dolby snd_ctl_boolean_mono_info |
2153 | struct snd_ctl_elem_info *uinfo) | ||
2154 | { | ||
2155 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2156 | uinfo->count = 1; | ||
2157 | uinfo->value.integer.min = 0; | ||
2158 | uinfo->value.integer.max = 1; | ||
2159 | return 0; | ||
2160 | } | ||
2161 | 2162 | ||
2162 | static int snd_hdspm_get_dolby(struct snd_kcontrol *kcontrol, | 2163 | static int snd_hdspm_get_dolby(struct snd_kcontrol *kcontrol, |
2163 | struct snd_ctl_elem_value *ucontrol) | 2164 | struct snd_ctl_elem_value *ucontrol) |
@@ -2212,15 +2213,7 @@ static int hdspm_set_professional(struct hdspm * hdspm, int dol) | |||
2212 | return 0; | 2213 | return 0; |
2213 | } | 2214 | } |
2214 | 2215 | ||
2215 | static int snd_hdspm_info_professional(struct snd_kcontrol *kcontrol, | 2216 | #define snd_hdspm_info_professional snd_ctl_boolean_mono_info |
2216 | struct snd_ctl_elem_info *uinfo) | ||
2217 | { | ||
2218 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2219 | uinfo->count = 1; | ||
2220 | uinfo->value.integer.min = 0; | ||
2221 | uinfo->value.integer.max = 1; | ||
2222 | return 0; | ||
2223 | } | ||
2224 | 2217 | ||
2225 | static int snd_hdspm_get_professional(struct snd_kcontrol *kcontrol, | 2218 | static int snd_hdspm_get_professional(struct snd_kcontrol *kcontrol, |
2226 | struct snd_ctl_elem_value *ucontrol) | 2219 | struct snd_ctl_elem_value *ucontrol) |
@@ -2472,7 +2465,7 @@ static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol, | |||
2472 | if (val > 2) | 2465 | if (val > 2) |
2473 | val = 2; | 2466 | val = 2; |
2474 | spin_lock_irq(&hdspm->lock); | 2467 | spin_lock_irq(&hdspm->lock); |
2475 | change = (int) val != hdspm_qs_wire(hdspm); | 2468 | change = val != hdspm_qs_wire(hdspm); |
2476 | hdspm_set_qs_wire(hdspm, val); | 2469 | hdspm_set_qs_wire(hdspm, val); |
2477 | spin_unlock_irq(&hdspm->lock); | 2470 | spin_unlock_irq(&hdspm->lock); |
2478 | return change; | 2471 | return change; |
@@ -2573,8 +2566,8 @@ static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol, | |||
2573 | source - | 2566 | source - |
2574 | HDSPM_MAX_CHANNELS); | 2567 | HDSPM_MAX_CHANNELS); |
2575 | else | 2568 | else |
2576 | change = | 2569 | change = gain != hdspm_read_in_gain(hdspm, destination, |
2577 | gain != hdspm_read_in_gain(hdspm, destination, source); | 2570 | source); |
2578 | 2571 | ||
2579 | if (change) { | 2572 | if (change) { |
2580 | if (source >= HDSPM_MAX_CHANNELS) | 2573 | if (source >= HDSPM_MAX_CHANNELS) |
@@ -2627,7 +2620,8 @@ static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol, | |||
2627 | snd_assert(channel >= 0 | 2620 | snd_assert(channel >= 0 |
2628 | || channel < HDSPM_MAX_CHANNELS, return -EINVAL); | 2621 | || channel < HDSPM_MAX_CHANNELS, return -EINVAL); |
2629 | 2622 | ||
2630 | if ((mapped_channel = hdspm->channel_map[channel]) < 0) | 2623 | mapped_channel = hdspm->channel_map[channel]; |
2624 | if (mapped_channel < 0) | ||
2631 | return -EINVAL; | 2625 | return -EINVAL; |
2632 | 2626 | ||
2633 | spin_lock_irq(&hdspm->lock); | 2627 | spin_lock_irq(&hdspm->lock); |
@@ -2635,10 +2629,12 @@ static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol, | |||
2635 | hdspm_read_pb_gain(hdspm, mapped_channel, mapped_channel); | 2629 | hdspm_read_pb_gain(hdspm, mapped_channel, mapped_channel); |
2636 | spin_unlock_irq(&hdspm->lock); | 2630 | spin_unlock_irq(&hdspm->lock); |
2637 | 2631 | ||
2638 | /* snd_printdd("get pb mixer index %d, channel %d, mapped_channel %d, value %d\n", | 2632 | /* |
2639 | ucontrol->id.index, channel, mapped_channel, ucontrol->value.integer.value[0]); | 2633 | snd_printdd("get pb mixer index %d, channel %d, mapped_channel %d, " |
2640 | */ | 2634 | "value %d\n", |
2641 | 2635 | ucontrol->id.index, channel, mapped_channel, | |
2636 | ucontrol->value.integer.value[0]); | ||
2637 | */ | ||
2642 | return 0; | 2638 | return 0; |
2643 | } | 2639 | } |
2644 | 2640 | ||
@@ -2659,7 +2655,8 @@ static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol, | |||
2659 | snd_assert(channel >= 0 | 2655 | snd_assert(channel >= 0 |
2660 | || channel < HDSPM_MAX_CHANNELS, return -EINVAL); | 2656 | || channel < HDSPM_MAX_CHANNELS, return -EINVAL); |
2661 | 2657 | ||
2662 | if ((mapped_channel = hdspm->channel_map[channel]) < 0) | 2658 | mapped_channel = hdspm->channel_map[channel]; |
2659 | if (mapped_channel < 0) | ||
2663 | return -EINVAL; | 2660 | return -EINVAL; |
2664 | 2661 | ||
2665 | gain = ucontrol->value.integer.value[0]; | 2662 | gain = ucontrol->value.integer.value[0]; |
@@ -2909,28 +2906,26 @@ static int snd_hdspm_create_controls(struct snd_card *card, struct hdspm * hdspm | |||
2909 | } | 2906 | } |
2910 | 2907 | ||
2911 | /* Channel playback mixer as default control | 2908 | /* Channel playback mixer as default control |
2912 | Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats too big for any alsamixer | 2909 | Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, |
2913 | they are accesible via special IOCTL on hwdep | 2910 | thats too * big for any alsamixer they are accesible via special |
2914 | and the mixer 2dimensional mixer control */ | 2911 | IOCTL on hwdep and the mixer 2dimensional mixer control |
2912 | */ | ||
2915 | 2913 | ||
2916 | snd_hdspm_playback_mixer.name = "Chn"; | 2914 | snd_hdspm_playback_mixer.name = "Chn"; |
2917 | limit = HDSPM_MAX_CHANNELS; | 2915 | limit = HDSPM_MAX_CHANNELS; |
2918 | 2916 | ||
2919 | /* The index values are one greater than the channel ID so that alsamixer | 2917 | /* The index values are one greater than the channel ID so that |
2920 | will display them correctly. We want to use the index for fast lookup | 2918 | * alsamixer will display them correctly. We want to use the index |
2921 | of the relevant channel, but if we use it at all, most ALSA software | 2919 | * for fast lookup of the relevant channel, but if we use it at all, |
2922 | does the wrong thing with it ... | 2920 | * most ALSA software does the wrong thing with it ... |
2923 | */ | 2921 | */ |
2924 | 2922 | ||
2925 | for (idx = 0; idx < limit; ++idx) { | 2923 | for (idx = 0; idx < limit; ++idx) { |
2926 | snd_hdspm_playback_mixer.index = idx + 1; | 2924 | snd_hdspm_playback_mixer.index = idx + 1; |
2927 | if ((err = snd_ctl_add(card, | 2925 | kctl = snd_ctl_new1(&snd_hdspm_playback_mixer, hdspm); |
2928 | kctl = | 2926 | err = snd_ctl_add(card, kctl); |
2929 | snd_ctl_new1 | 2927 | if (err < 0) |
2930 | (&snd_hdspm_playback_mixer, | ||
2931 | hdspm)))) { | ||
2932 | return err; | 2928 | return err; |
2933 | } | ||
2934 | hdspm->playback_mixer_ctls[idx] = kctl; | 2929 | hdspm->playback_mixer_ctls[idx] = kctl; |
2935 | } | 2930 | } |
2936 | 2931 | ||
@@ -2945,7 +2940,7 @@ static void | |||
2945 | snd_hdspm_proc_read_madi(struct snd_info_entry * entry, | 2940 | snd_hdspm_proc_read_madi(struct snd_info_entry * entry, |
2946 | struct snd_info_buffer *buffer) | 2941 | struct snd_info_buffer *buffer) |
2947 | { | 2942 | { |
2948 | struct hdspm *hdspm = (struct hdspm *) entry->private_data; | 2943 | struct hdspm *hdspm = entry->private_data; |
2949 | unsigned int status; | 2944 | unsigned int status; |
2950 | unsigned int status2; | 2945 | unsigned int status2; |
2951 | char *pref_sync_ref; | 2946 | char *pref_sync_ref; |
@@ -2978,14 +2973,14 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry, | |||
2978 | (status & HDSPM_midi1IRQPending) ? 1 : 0, | 2973 | (status & HDSPM_midi1IRQPending) ? 1 : 0, |
2979 | hdspm->irq_count); | 2974 | hdspm->irq_count); |
2980 | snd_iprintf(buffer, | 2975 | snd_iprintf(buffer, |
2981 | "HW pointer: id = %d, rawptr = %d (%d->%d) estimated= %ld (bytes)\n", | 2976 | "HW pointer: id = %d, rawptr = %d (%d->%d) " |
2977 | "estimated= %ld (bytes)\n", | ||
2982 | ((status & HDSPM_BufferID) ? 1 : 0), | 2978 | ((status & HDSPM_BufferID) ? 1 : 0), |
2983 | (status & HDSPM_BufferPositionMask), | 2979 | (status & HDSPM_BufferPositionMask), |
2984 | (status & HDSPM_BufferPositionMask) % (2 * | 2980 | (status & HDSPM_BufferPositionMask) % |
2985 | (int)hdspm-> | 2981 | (2 * (int)hdspm->period_bytes), |
2986 | period_bytes), | 2982 | ((status & HDSPM_BufferPositionMask) - 64) % |
2987 | ((status & HDSPM_BufferPositionMask) - | 2983 | (2 * (int)hdspm->period_bytes), |
2988 | 64) % (2 * (int)hdspm->period_bytes), | ||
2989 | (long) hdspm_hw_pointer(hdspm) * 4); | 2984 | (long) hdspm_hw_pointer(hdspm) * 4); |
2990 | 2985 | ||
2991 | snd_iprintf(buffer, | 2986 | snd_iprintf(buffer, |
@@ -2995,24 +2990,22 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry, | |||
2995 | hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF, | 2990 | hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF, |
2996 | hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF); | 2991 | hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF); |
2997 | snd_iprintf(buffer, | 2992 | snd_iprintf(buffer, |
2998 | "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, status2=0x%x\n", | 2993 | "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, " |
2994 | "status2=0x%x\n", | ||
2999 | hdspm->control_register, hdspm->control2_register, | 2995 | hdspm->control_register, hdspm->control2_register, |
3000 | status, status2); | 2996 | status, status2); |
3001 | 2997 | ||
3002 | snd_iprintf(buffer, "--- Settings ---\n"); | 2998 | snd_iprintf(buffer, "--- Settings ---\n"); |
3003 | 2999 | ||
3004 | x = 1 << (6 + | 3000 | x = 1 << (6 + hdspm_decode_latency(hdspm->control_register & |
3005 | hdspm_decode_latency(hdspm-> | 3001 | HDSPM_LatencyMask)); |
3006 | control_register & | ||
3007 | HDSPM_LatencyMask)); | ||
3008 | 3002 | ||
3009 | snd_iprintf(buffer, | 3003 | snd_iprintf(buffer, |
3010 | "Size (Latency): %d samples (2 periods of %lu bytes)\n", | 3004 | "Size (Latency): %d samples (2 periods of %lu bytes)\n", |
3011 | x, (unsigned long) hdspm->period_bytes); | 3005 | x, (unsigned long) hdspm->period_bytes); |
3012 | 3006 | ||
3013 | snd_iprintf(buffer, "Line out: %s, Precise Pointer: %s\n", | 3007 | snd_iprintf(buffer, "Line out: %s, Precise Pointer: %s\n", |
3014 | (hdspm-> | 3008 | (hdspm->control_register & HDSPM_LineOut) ? "on " : "off", |
3015 | control_register & HDSPM_LineOut) ? "on " : "off", | ||
3016 | (hdspm->precise_ptr) ? "on" : "off"); | 3009 | (hdspm->precise_ptr) ? "on" : "off"); |
3017 | 3010 | ||
3018 | switch (hdspm->control_register & HDSPM_InputMask) { | 3011 | switch (hdspm->control_register & HDSPM_InputMask) { |
@@ -3040,7 +3033,8 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry, | |||
3040 | syncref); | 3033 | syncref); |
3041 | 3034 | ||
3042 | snd_iprintf(buffer, | 3035 | snd_iprintf(buffer, |
3043 | "ClearTrackMarker = %s, Transmit in %s Channel Mode, Auto Input %s\n", | 3036 | "ClearTrackMarker = %s, Transmit in %s Channel Mode, " |
3037 | "Auto Input %s\n", | ||
3044 | (hdspm-> | 3038 | (hdspm-> |
3045 | control_register & HDSPM_clr_tms) ? "on" : "off", | 3039 | control_register & HDSPM_clr_tms) ? "on" : "off", |
3046 | (hdspm-> | 3040 | (hdspm-> |
@@ -3141,7 +3135,7 @@ static void | |||
3141 | snd_hdspm_proc_read_aes32(struct snd_info_entry * entry, | 3135 | snd_hdspm_proc_read_aes32(struct snd_info_entry * entry, |
3142 | struct snd_info_buffer *buffer) | 3136 | struct snd_info_buffer *buffer) |
3143 | { | 3137 | { |
3144 | struct hdspm *hdspm = (struct hdspm *) entry->private_data; | 3138 | struct hdspm *hdspm = entry->private_data; |
3145 | unsigned int status; | 3139 | unsigned int status; |
3146 | unsigned int status2; | 3140 | unsigned int status2; |
3147 | unsigned int timecode; | 3141 | unsigned int timecode; |
@@ -3171,14 +3165,14 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry, | |||
3171 | (status & HDSPM_midi1IRQPending) ? 1 : 0, | 3165 | (status & HDSPM_midi1IRQPending) ? 1 : 0, |
3172 | hdspm->irq_count); | 3166 | hdspm->irq_count); |
3173 | snd_iprintf(buffer, | 3167 | snd_iprintf(buffer, |
3174 | "HW pointer: id = %d, rawptr = %d (%d->%d) estimated= %ld (bytes)\n", | 3168 | "HW pointer: id = %d, rawptr = %d (%d->%d) " |
3169 | "estimated= %ld (bytes)\n", | ||
3175 | ((status & HDSPM_BufferID) ? 1 : 0), | 3170 | ((status & HDSPM_BufferID) ? 1 : 0), |
3176 | (status & HDSPM_BufferPositionMask), | 3171 | (status & HDSPM_BufferPositionMask), |
3177 | (status & HDSPM_BufferPositionMask) % (2 * | 3172 | (status & HDSPM_BufferPositionMask) % |
3178 | (int)hdspm-> | 3173 | (2 * (int)hdspm->period_bytes), |
3179 | period_bytes), | 3174 | ((status & HDSPM_BufferPositionMask) - 64) % |
3180 | ((status & HDSPM_BufferPositionMask) - | 3175 | (2 * (int)hdspm->period_bytes), |
3181 | 64) % (2 * (int)hdspm->period_bytes), | ||
3182 | (long) hdspm_hw_pointer(hdspm) * 4); | 3176 | (long) hdspm_hw_pointer(hdspm) * 4); |
3183 | 3177 | ||
3184 | snd_iprintf(buffer, | 3178 | snd_iprintf(buffer, |
@@ -3188,16 +3182,15 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry, | |||
3188 | hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF, | 3182 | hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF, |
3189 | hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF); | 3183 | hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF); |
3190 | snd_iprintf(buffer, | 3184 | snd_iprintf(buffer, |
3191 | "Register: ctrl1=0x%x, status1=0x%x, status2=0x%x, timecode=0x%x\n", | 3185 | "Register: ctrl1=0x%x, status1=0x%x, status2=0x%x, " |
3186 | "timecode=0x%x\n", | ||
3192 | hdspm->control_register, | 3187 | hdspm->control_register, |
3193 | status, status2, timecode); | 3188 | status, status2, timecode); |
3194 | 3189 | ||
3195 | snd_iprintf(buffer, "--- Settings ---\n"); | 3190 | snd_iprintf(buffer, "--- Settings ---\n"); |
3196 | 3191 | ||
3197 | x = 1 << (6 + | 3192 | x = 1 << (6 + hdspm_decode_latency(hdspm->control_register & |
3198 | hdspm_decode_latency(hdspm-> | 3193 | HDSPM_LatencyMask)); |
3199 | control_register & | ||
3200 | HDSPM_LatencyMask)); | ||
3201 | 3194 | ||
3202 | snd_iprintf(buffer, | 3195 | snd_iprintf(buffer, |
3203 | "Size (Latency): %d samples (2 periods of %lu bytes)\n", | 3196 | "Size (Latency): %d samples (2 periods of %lu bytes)\n", |
@@ -3280,14 +3273,15 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry, | |||
3280 | snd_iprintf(buffer, "--- Status:\n"); | 3273 | snd_iprintf(buffer, "--- Status:\n"); |
3281 | 3274 | ||
3282 | snd_iprintf(buffer, "Word: %s Frequency: %d\n", | 3275 | snd_iprintf(buffer, "Word: %s Frequency: %d\n", |
3283 | (status & HDSPM_AES32_wcLock)? "Sync " : "No Lock", | 3276 | (status & HDSPM_AES32_wcLock)? "Sync " : "No Lock", |
3284 | HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF)); | 3277 | HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF)); |
3285 | 3278 | ||
3286 | for (x = 0; x < 8; x++) { | 3279 | for (x = 0; x < 8; x++) { |
3287 | snd_iprintf(buffer, "AES%d: %s Frequency: %d\n", | 3280 | snd_iprintf(buffer, "AES%d: %s Frequency: %d\n", |
3288 | x+1, | 3281 | x+1, |
3289 | (status2 & (HDSPM_LockAES >> x))? "Sync ": "No Lock", | 3282 | (status2 & (HDSPM_LockAES >> x)) ? |
3290 | HDSPM_bit2freq((timecode >> (4*x)) & 0xF)); | 3283 | "Sync ": "No Lock", |
3284 | HDSPM_bit2freq((timecode >> (4*x)) & 0xF)); | ||
3291 | } | 3285 | } |
3292 | 3286 | ||
3293 | switch (hdspm_autosync_ref(hdspm)) { | 3287 | switch (hdspm_autosync_ref(hdspm)) { |
@@ -3313,12 +3307,11 @@ static void | |||
3313 | snd_hdspm_proc_read_debug(struct snd_info_entry * entry, | 3307 | snd_hdspm_proc_read_debug(struct snd_info_entry * entry, |
3314 | struct snd_info_buffer *buffer) | 3308 | struct snd_info_buffer *buffer) |
3315 | { | 3309 | { |
3316 | struct hdspm *hdspm = (struct hdspm *)entry->private_data; | 3310 | struct hdspm *hdspm = entry->private_data; |
3317 | 3311 | ||
3318 | int j,i; | 3312 | int j,i; |
3319 | 3313 | ||
3320 | for (i = 0; i < 256 /* 1024*64 */; i += j) | 3314 | for (i = 0; i < 256 /* 1024*64 */; i += j) { |
3321 | { | ||
3322 | snd_iprintf(buffer, "0x%08X: ", i); | 3315 | snd_iprintf(buffer, "0x%08X: ", i); |
3323 | for (j = 0; j < 16; j += 4) | 3316 | for (j = 0; j < 16; j += 4) |
3324 | snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j)); | 3317 | snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j)); |
@@ -3361,14 +3354,20 @@ static int snd_hdspm_set_defaults(struct hdspm * hdspm) | |||
3361 | /* set defaults: */ | 3354 | /* set defaults: */ |
3362 | 3355 | ||
3363 | if (hdspm->is_aes32) | 3356 | if (hdspm->is_aes32) |
3364 | hdspm->control_register = HDSPM_ClockModeMaster | /* Master Cloack Mode on */ | 3357 | hdspm->control_register = |
3365 | hdspm_encode_latency(7) | /* latency maximum = 8192 samples */ | 3358 | HDSPM_ClockModeMaster | /* Master Cloack Mode on */ |
3359 | hdspm_encode_latency(7) | /* latency maximum = | ||
3360 | * 8192 samples | ||
3361 | */ | ||
3366 | HDSPM_SyncRef0 | /* AES1 is syncclock */ | 3362 | HDSPM_SyncRef0 | /* AES1 is syncclock */ |
3367 | HDSPM_LineOut | /* Analog output in */ | 3363 | HDSPM_LineOut | /* Analog output in */ |
3368 | HDSPM_Professional; /* Professional mode */ | 3364 | HDSPM_Professional; /* Professional mode */ |
3369 | else | 3365 | else |
3370 | hdspm->control_register = HDSPM_ClockModeMaster | /* Master Cloack Mode on */ | 3366 | hdspm->control_register = |
3371 | hdspm_encode_latency(7) | /* latency maximum = 8192 samples */ | 3367 | HDSPM_ClockModeMaster | /* Master Cloack Mode on */ |
3368 | hdspm_encode_latency(7) | /* latency maximum = | ||
3369 | * 8192 samples | ||
3370 | */ | ||
3372 | HDSPM_InputCoaxial | /* Input Coax not Optical */ | 3371 | HDSPM_InputCoaxial | /* Input Coax not Optical */ |
3373 | HDSPM_SyncRef_MADI | /* Madi is syncclock */ | 3372 | HDSPM_SyncRef_MADI | /* Madi is syncclock */ |
3374 | HDSPM_LineOut | /* Analog output in */ | 3373 | HDSPM_LineOut | /* Analog output in */ |
@@ -3399,7 +3398,8 @@ static int snd_hdspm_set_defaults(struct hdspm * hdspm) | |||
3399 | 3398 | ||
3400 | if (line_outs_monitor[hdspm->dev]) { | 3399 | if (line_outs_monitor[hdspm->dev]) { |
3401 | 3400 | ||
3402 | snd_printk(KERN_INFO "HDSPM: sending all playback streams to line outs.\n"); | 3401 | snd_printk(KERN_INFO "HDSPM: " |
3402 | "sending all playback streams to line outs.\n"); | ||
3403 | 3403 | ||
3404 | for (i = 0; i < HDSPM_MIXER_CHANNELS; i++) { | 3404 | for (i = 0; i < HDSPM_MIXER_CHANNELS; i++) { |
3405 | if (hdspm_write_pb_gain(hdspm, i, i, UNITY_GAIN)) | 3405 | if (hdspm_write_pb_gain(hdspm, i, i, UNITY_GAIN)) |
@@ -3448,20 +3448,16 @@ static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id) | |||
3448 | if (audio) { | 3448 | if (audio) { |
3449 | 3449 | ||
3450 | if (hdspm->capture_substream) | 3450 | if (hdspm->capture_substream) |
3451 | snd_pcm_period_elapsed(hdspm->pcm-> | 3451 | snd_pcm_period_elapsed(hdspm->capture_substream); |
3452 | streams | ||
3453 | [SNDRV_PCM_STREAM_CAPTURE]. | ||
3454 | substream); | ||
3455 | 3452 | ||
3456 | if (hdspm->playback_substream) | 3453 | if (hdspm->playback_substream) |
3457 | snd_pcm_period_elapsed(hdspm->pcm-> | 3454 | snd_pcm_period_elapsed(hdspm->playback_substream); |
3458 | streams | ||
3459 | [SNDRV_PCM_STREAM_PLAYBACK]. | ||
3460 | substream); | ||
3461 | } | 3455 | } |
3462 | 3456 | ||
3463 | if (midi0 && midi0status) { | 3457 | if (midi0 && midi0status) { |
3464 | /* we disable interrupts for this input until processing is done */ | 3458 | /* we disable interrupts for this input until processing |
3459 | * is done | ||
3460 | */ | ||
3465 | hdspm->control_register &= ~HDSPM_Midi0InterruptEnable; | 3461 | hdspm->control_register &= ~HDSPM_Midi0InterruptEnable; |
3466 | hdspm_write(hdspm, HDSPM_controlRegister, | 3462 | hdspm_write(hdspm, HDSPM_controlRegister, |
3467 | hdspm->control_register); | 3463 | hdspm->control_register); |
@@ -3469,7 +3465,9 @@ static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id) | |||
3469 | schedule = 1; | 3465 | schedule = 1; |
3470 | } | 3466 | } |
3471 | if (midi1 && midi1status) { | 3467 | if (midi1 && midi1status) { |
3472 | /* we disable interrupts for this input until processing is done */ | 3468 | /* we disable interrupts for this input until processing |
3469 | * is done | ||
3470 | */ | ||
3473 | hdspm->control_register &= ~HDSPM_Midi1InterruptEnable; | 3471 | hdspm->control_register &= ~HDSPM_Midi1InterruptEnable; |
3474 | hdspm_write(hdspm, HDSPM_controlRegister, | 3472 | hdspm_write(hdspm, HDSPM_controlRegister, |
3475 | hdspm->control_register); | 3473 | hdspm->control_register); |
@@ -3501,16 +3499,16 @@ static char *hdspm_channel_buffer_location(struct hdspm * hdspm, | |||
3501 | snd_assert(channel >= 0 | 3499 | snd_assert(channel >= 0 |
3502 | || channel < HDSPM_MAX_CHANNELS, return NULL); | 3500 | || channel < HDSPM_MAX_CHANNELS, return NULL); |
3503 | 3501 | ||
3504 | if ((mapped_channel = hdspm->channel_map[channel]) < 0) | 3502 | mapped_channel = hdspm->channel_map[channel]; |
3503 | if (mapped_channel < 0) | ||
3505 | return NULL; | 3504 | return NULL; |
3506 | 3505 | ||
3507 | if (stream == SNDRV_PCM_STREAM_CAPTURE) { | 3506 | if (stream == SNDRV_PCM_STREAM_CAPTURE) |
3508 | return hdspm->capture_buffer + | 3507 | return hdspm->capture_buffer + |
3509 | mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES; | 3508 | mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES; |
3510 | } else { | 3509 | else |
3511 | return hdspm->playback_buffer + | 3510 | return hdspm->playback_buffer + |
3512 | mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES; | 3511 | mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES; |
3513 | } | ||
3514 | } | 3512 | } |
3515 | 3513 | ||
3516 | 3514 | ||
@@ -3525,9 +3523,9 @@ static int snd_hdspm_playback_copy(struct snd_pcm_substream *substream, | |||
3525 | snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4, | 3523 | snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4, |
3526 | return -EINVAL); | 3524 | return -EINVAL); |
3527 | 3525 | ||
3528 | channel_buf = hdspm_channel_buffer_location(hdspm, | 3526 | channel_buf = |
3529 | substream->pstr-> | 3527 | hdspm_channel_buffer_location(hdspm, substream->pstr->stream, |
3530 | stream, channel); | 3528 | channel); |
3531 | 3529 | ||
3532 | snd_assert(channel_buf != NULL, return -EIO); | 3530 | snd_assert(channel_buf != NULL, return -EIO); |
3533 | 3531 | ||
@@ -3544,9 +3542,9 @@ static int snd_hdspm_capture_copy(struct snd_pcm_substream *substream, | |||
3544 | snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4, | 3542 | snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4, |
3545 | return -EINVAL); | 3543 | return -EINVAL); |
3546 | 3544 | ||
3547 | channel_buf = hdspm_channel_buffer_location(hdspm, | 3545 | channel_buf = |
3548 | substream->pstr-> | 3546 | hdspm_channel_buffer_location(hdspm, substream->pstr->stream, |
3549 | stream, channel); | 3547 | channel); |
3550 | snd_assert(channel_buf != NULL, return -EIO); | 3548 | snd_assert(channel_buf != NULL, return -EIO); |
3551 | return copy_to_user(dst, channel_buf + pos * 4, count * 4); | 3549 | return copy_to_user(dst, channel_buf + pos * 4, count * 4); |
3552 | } | 3550 | } |
@@ -3559,8 +3557,8 @@ static int snd_hdspm_hw_silence(struct snd_pcm_substream *substream, | |||
3559 | char *channel_buf; | 3557 | char *channel_buf; |
3560 | 3558 | ||
3561 | channel_buf = | 3559 | channel_buf = |
3562 | hdspm_channel_buffer_location(hdspm, substream->pstr->stream, | 3560 | hdspm_channel_buffer_location(hdspm, substream->pstr->stream, |
3563 | channel); | 3561 | channel); |
3564 | snd_assert(channel_buf != NULL, return -EIO); | 3562 | snd_assert(channel_buf != NULL, return -EIO); |
3565 | memset(channel_buf + pos * 4, 0, count * 4); | 3563 | memset(channel_buf + pos * 4, 0, count * 4); |
3566 | return 0; | 3564 | return 0; |
@@ -3616,7 +3614,7 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, | |||
3616 | other_pid = hdspm->playback_pid; | 3614 | other_pid = hdspm->playback_pid; |
3617 | } | 3615 | } |
3618 | 3616 | ||
3619 | if ((other_pid > 0) && (this_pid != other_pid)) { | 3617 | if (other_pid > 0 && this_pid != other_pid) { |
3620 | 3618 | ||
3621 | /* The other stream is open, and not by the same | 3619 | /* The other stream is open, and not by the same |
3622 | task as this one. Make sure that the parameters | 3620 | task as this one. Make sure that the parameters |
@@ -3633,7 +3631,7 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, | |||
3633 | if (params_period_size(params) != hdspm->period_bytes / 4) { | 3631 | if (params_period_size(params) != hdspm->period_bytes / 4) { |
3634 | spin_unlock_irq(&hdspm->lock); | 3632 | spin_unlock_irq(&hdspm->lock); |
3635 | _snd_pcm_hw_param_setempty(params, | 3633 | _snd_pcm_hw_param_setempty(params, |
3636 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE); | 3634 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE); |
3637 | return -EBUSY; | 3635 | return -EBUSY; |
3638 | } | 3636 | } |
3639 | 3637 | ||
@@ -3644,7 +3642,8 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, | |||
3644 | /* how to make sure that the rate matches an externally-set one ? */ | 3642 | /* how to make sure that the rate matches an externally-set one ? */ |
3645 | 3643 | ||
3646 | spin_lock_irq(&hdspm->lock); | 3644 | spin_lock_irq(&hdspm->lock); |
3647 | if ((err = hdspm_set_rate(hdspm, params_rate(params), 0)) < 0) { | 3645 | err = hdspm_set_rate(hdspm, params_rate(params), 0); |
3646 | if (err < 0) { | ||
3648 | spin_unlock_irq(&hdspm->lock); | 3647 | spin_unlock_irq(&hdspm->lock); |
3649 | _snd_pcm_hw_param_setempty(params, | 3648 | _snd_pcm_hw_param_setempty(params, |
3650 | SNDRV_PCM_HW_PARAM_RATE); | 3649 | SNDRV_PCM_HW_PARAM_RATE); |
@@ -3652,16 +3651,17 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, | |||
3652 | } | 3651 | } |
3653 | spin_unlock_irq(&hdspm->lock); | 3652 | spin_unlock_irq(&hdspm->lock); |
3654 | 3653 | ||
3655 | if ((err = | 3654 | err = hdspm_set_interrupt_interval(hdspm, |
3656 | hdspm_set_interrupt_interval(hdspm, | 3655 | params_period_size(params)); |
3657 | params_period_size(params))) < | 3656 | if (err < 0) { |
3658 | 0) { | ||
3659 | _snd_pcm_hw_param_setempty(params, | 3657 | _snd_pcm_hw_param_setempty(params, |
3660 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE); | 3658 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE); |
3661 | return err; | 3659 | return err; |
3662 | } | 3660 | } |
3663 | 3661 | ||
3664 | /* Memory allocation, takashi's method, dont know if we should spinlock */ | 3662 | /* Memory allocation, takashi's method, dont know if we should |
3663 | * spinlock | ||
3664 | */ | ||
3665 | /* malloc all buffer even if not enabled to get sure */ | 3665 | /* malloc all buffer even if not enabled to get sure */ |
3666 | /* Update for MADI rev 204: we need to allocate for all channels, | 3666 | /* Update for MADI rev 204: we need to allocate for all channels, |
3667 | * otherwise it doesn't work at 96kHz */ | 3667 | * otherwise it doesn't work at 96kHz */ |
@@ -3746,7 +3746,8 @@ static int snd_hdspm_channel_info(struct snd_pcm_substream *substream, | |||
3746 | 3746 | ||
3747 | snd_assert(info->channel < HDSPM_MAX_CHANNELS, return -EINVAL); | 3747 | snd_assert(info->channel < HDSPM_MAX_CHANNELS, return -EINVAL); |
3748 | 3748 | ||
3749 | if ((mapped_channel = hdspm->channel_map[info->channel]) < 0) | 3749 | mapped_channel = hdspm->channel_map[info->channel]; |
3750 | if (mapped_channel < 0) | ||
3750 | return -EINVAL; | 3751 | return -EINVAL; |
3751 | 3752 | ||
3752 | info->offset = mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES; | 3753 | info->offset = mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES; |
@@ -3760,15 +3761,13 @@ static int snd_hdspm_ioctl(struct snd_pcm_substream *substream, | |||
3760 | { | 3761 | { |
3761 | switch (cmd) { | 3762 | switch (cmd) { |
3762 | case SNDRV_PCM_IOCTL1_RESET: | 3763 | case SNDRV_PCM_IOCTL1_RESET: |
3763 | { | 3764 | return snd_hdspm_reset(substream); |
3764 | return snd_hdspm_reset(substream); | ||
3765 | } | ||
3766 | 3765 | ||
3767 | case SNDRV_PCM_IOCTL1_CHANNEL_INFO: | 3766 | case SNDRV_PCM_IOCTL1_CHANNEL_INFO: |
3768 | { | 3767 | { |
3769 | struct snd_pcm_channel_info *info = arg; | 3768 | struct snd_pcm_channel_info *info = arg; |
3770 | return snd_hdspm_channel_info(substream, info); | 3769 | return snd_hdspm_channel_info(substream, info); |
3771 | } | 3770 | } |
3772 | default: | 3771 | default: |
3773 | break; | 3772 | break; |
3774 | } | 3773 | } |
@@ -3979,9 +3978,12 @@ static int snd_hdspm_hw_rule_channels(struct snd_pcm_hw_params *params, | |||
3979 | } | 3978 | } |
3980 | 3979 | ||
3981 | 3980 | ||
3982 | static unsigned int hdspm_aes32_sample_rates[] = { 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 }; | 3981 | static unsigned int hdspm_aes32_sample_rates[] = { |
3982 | 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 | ||
3983 | }; | ||
3983 | 3984 | ||
3984 | static struct snd_pcm_hw_constraint_list hdspm_hw_constraints_aes32_sample_rates = { | 3985 | static struct snd_pcm_hw_constraint_list |
3986 | hdspm_hw_constraints_aes32_sample_rates = { | ||
3985 | .count = ARRAY_SIZE(hdspm_aes32_sample_rates), | 3987 | .count = ARRAY_SIZE(hdspm_aes32_sample_rates), |
3986 | .list = hdspm_aes32_sample_rates, | 3988 | .list = hdspm_aes32_sample_rates, |
3987 | .mask = 0 | 3989 | .mask = 0 |
@@ -4107,7 +4109,7 @@ static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep * hw, struct file *file) | |||
4107 | static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file, | 4109 | static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file, |
4108 | unsigned int cmd, unsigned long arg) | 4110 | unsigned int cmd, unsigned long arg) |
4109 | { | 4111 | { |
4110 | struct hdspm *hdspm = (struct hdspm *) hw->private_data; | 4112 | struct hdspm *hdspm = hw->private_data; |
4111 | struct hdspm_mixer_ioctl mixer; | 4113 | struct hdspm_mixer_ioctl mixer; |
4112 | struct hdspm_config_info info; | 4114 | struct hdspm_config_info info; |
4113 | struct hdspm_version hdspm_version; | 4115 | struct hdspm_version hdspm_version; |
@@ -4115,11 +4117,12 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file, | |||
4115 | 4117 | ||
4116 | switch (cmd) { | 4118 | switch (cmd) { |
4117 | 4119 | ||
4118 | |||
4119 | case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS: | 4120 | case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS: |
4120 | if (copy_from_user(&rms, (void __user *)arg, sizeof(rms))) | 4121 | if (copy_from_user(&rms, (void __user *)arg, sizeof(rms))) |
4121 | return -EFAULT; | 4122 | return -EFAULT; |
4122 | /* maybe there is a chance to memorymap in future so dont touch just copy */ | 4123 | /* maybe there is a chance to memorymap in future |
4124 | * so dont touch just copy | ||
4125 | */ | ||
4123 | if(copy_to_user_fromio((void __user *)rms.peak, | 4126 | if(copy_to_user_fromio((void __user *)rms.peak, |
4124 | hdspm->iobase+HDSPM_MADI_peakrmsbase, | 4127 | hdspm->iobase+HDSPM_MADI_peakrmsbase, |
4125 | sizeof(struct hdspm_peak_rms)) != 0 ) | 4128 | sizeof(struct hdspm_peak_rms)) != 0 ) |
@@ -4131,21 +4134,16 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file, | |||
4131 | case SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO: | 4134 | case SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO: |
4132 | 4135 | ||
4133 | spin_lock_irq(&hdspm->lock); | 4136 | spin_lock_irq(&hdspm->lock); |
4134 | info.pref_sync_ref = | 4137 | info.pref_sync_ref = hdspm_pref_sync_ref(hdspm); |
4135 | (unsigned char) hdspm_pref_sync_ref(hdspm); | 4138 | info.wordclock_sync_check = hdspm_wc_sync_check(hdspm); |
4136 | info.wordclock_sync_check = | ||
4137 | (unsigned char) hdspm_wc_sync_check(hdspm); | ||
4138 | 4139 | ||
4139 | info.system_sample_rate = hdspm->system_sample_rate; | 4140 | info.system_sample_rate = hdspm->system_sample_rate; |
4140 | info.autosync_sample_rate = | 4141 | info.autosync_sample_rate = |
4141 | hdspm_external_sample_rate(hdspm); | 4142 | hdspm_external_sample_rate(hdspm); |
4142 | info.system_clock_mode = | 4143 | info.system_clock_mode = hdspm_system_clock_mode(hdspm); |
4143 | (unsigned char) hdspm_system_clock_mode(hdspm); | 4144 | info.clock_source = hdspm_clock_source(hdspm); |
4144 | info.clock_source = | 4145 | info.autosync_ref = hdspm_autosync_ref(hdspm); |
4145 | (unsigned char) hdspm_clock_source(hdspm); | 4146 | info.line_out = hdspm_line_out(hdspm); |
4146 | info.autosync_ref = | ||
4147 | (unsigned char) hdspm_autosync_ref(hdspm); | ||
4148 | info.line_out = (unsigned char) hdspm_line_out(hdspm); | ||
4149 | info.passthru = 0; | 4147 | info.passthru = 0; |
4150 | spin_unlock_irq(&hdspm->lock); | 4148 | spin_unlock_irq(&hdspm->lock); |
4151 | if (copy_to_user((void __user *) arg, &info, sizeof(info))) | 4149 | if (copy_to_user((void __user *) arg, &info, sizeof(info))) |
@@ -4162,8 +4160,8 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file, | |||
4162 | case SNDRV_HDSPM_IOCTL_GET_MIXER: | 4160 | case SNDRV_HDSPM_IOCTL_GET_MIXER: |
4163 | if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer))) | 4161 | if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer))) |
4164 | return -EFAULT; | 4162 | return -EFAULT; |
4165 | if (copy_to_user | 4163 | if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer, |
4166 | ((void __user *)mixer.mixer, hdspm->mixer, sizeof(struct hdspm_mixer))) | 4164 | sizeof(struct hdspm_mixer))) |
4167 | return -EFAULT; | 4165 | return -EFAULT; |
4168 | break; | 4166 | break; |
4169 | 4167 | ||
@@ -4206,7 +4204,8 @@ static int __devinit snd_hdspm_create_hwdep(struct snd_card *card, | |||
4206 | struct snd_hwdep *hw; | 4204 | struct snd_hwdep *hw; |
4207 | int err; | 4205 | int err; |
4208 | 4206 | ||
4209 | if ((err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw)) < 0) | 4207 | err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw); |
4208 | if (err < 0) | ||
4210 | return err; | 4209 | return err; |
4211 | 4210 | ||
4212 | hdspm->hwdep = hw; | 4211 | hdspm->hwdep = hw; |
@@ -4232,15 +4231,15 @@ static int __devinit snd_hdspm_preallocate_memory(struct hdspm * hdspm) | |||
4232 | 4231 | ||
4233 | pcm = hdspm->pcm; | 4232 | pcm = hdspm->pcm; |
4234 | 4233 | ||
4235 | /* wanted = HDSPM_DMA_AREA_BYTES + 4096;*/ /* dont know why, but it works */ | ||
4236 | wanted = HDSPM_DMA_AREA_BYTES; | 4234 | wanted = HDSPM_DMA_AREA_BYTES; |
4237 | 4235 | ||
4238 | if ((err = | 4236 | err = |
4239 | snd_pcm_lib_preallocate_pages_for_all(pcm, | 4237 | snd_pcm_lib_preallocate_pages_for_all(pcm, |
4240 | SNDRV_DMA_TYPE_DEV_SG, | 4238 | SNDRV_DMA_TYPE_DEV_SG, |
4241 | snd_dma_pci_data(hdspm->pci), | 4239 | snd_dma_pci_data(hdspm->pci), |
4242 | wanted, | 4240 | wanted, |
4243 | wanted)) < 0) { | 4241 | wanted); |
4242 | if (err < 0) { | ||
4244 | snd_printdd("Could not preallocate %zd Bytes\n", wanted); | 4243 | snd_printdd("Could not preallocate %zd Bytes\n", wanted); |
4245 | 4244 | ||
4246 | return err; | 4245 | return err; |
@@ -4256,8 +4255,7 @@ static void hdspm_set_sgbuf(struct hdspm * hdspm, struct snd_sg_buf *sgbuf, | |||
4256 | int i; | 4255 | int i; |
4257 | for (i = 0; i < (channels * 16); i++) | 4256 | for (i = 0; i < (channels * 16); i++) |
4258 | hdspm_write(hdspm, reg + 4 * i, | 4257 | hdspm_write(hdspm, reg + 4 * i, |
4259 | snd_pcm_sgbuf_get_addr(sgbuf, | 4258 | snd_pcm_sgbuf_get_addr(sgbuf, (size_t) 4096 * i)); |
4260 | (size_t) 4096 * i)); | ||
4261 | } | 4259 | } |
4262 | 4260 | ||
4263 | /* ------------- ALSA Devices ---------------------------- */ | 4261 | /* ------------- ALSA Devices ---------------------------- */ |
@@ -4267,7 +4265,8 @@ static int __devinit snd_hdspm_create_pcm(struct snd_card *card, | |||
4267 | struct snd_pcm *pcm; | 4265 | struct snd_pcm *pcm; |
4268 | int err; | 4266 | int err; |
4269 | 4267 | ||
4270 | if ((err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm)) < 0) | 4268 | err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm); |
4269 | if (err < 0) | ||
4271 | return err; | 4270 | return err; |
4272 | 4271 | ||
4273 | hdspm->pcm = pcm; | 4272 | hdspm->pcm = pcm; |
@@ -4281,7 +4280,8 @@ static int __devinit snd_hdspm_create_pcm(struct snd_card *card, | |||
4281 | 4280 | ||
4282 | pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; | 4281 | pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; |
4283 | 4282 | ||
4284 | if ((err = snd_hdspm_preallocate_memory(hdspm)) < 0) | 4283 | err = snd_hdspm_preallocate_memory(hdspm); |
4284 | if (err < 0) | ||
4285 | return err; | 4285 | return err; |
4286 | 4286 | ||
4287 | return 0; | 4287 | return 0; |
@@ -4299,19 +4299,24 @@ static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card, | |||
4299 | int err; | 4299 | int err; |
4300 | 4300 | ||
4301 | snd_printdd("Create card...\n"); | 4301 | snd_printdd("Create card...\n"); |
4302 | if ((err = snd_hdspm_create_pcm(card, hdspm)) < 0) | 4302 | err = snd_hdspm_create_pcm(card, hdspm); |
4303 | if (err < 0) | ||
4303 | return err; | 4304 | return err; |
4304 | 4305 | ||
4305 | if ((err = snd_hdspm_create_midi(card, hdspm, 0)) < 0) | 4306 | err = snd_hdspm_create_midi(card, hdspm, 0); |
4307 | if (err < 0) | ||
4306 | return err; | 4308 | return err; |
4307 | 4309 | ||
4308 | if ((err = snd_hdspm_create_midi(card, hdspm, 1)) < 0) | 4310 | err = snd_hdspm_create_midi(card, hdspm, 1); |
4311 | if (err < 0) | ||
4309 | return err; | 4312 | return err; |
4310 | 4313 | ||
4311 | if ((err = snd_hdspm_create_controls(card, hdspm)) < 0) | 4314 | err = snd_hdspm_create_controls(card, hdspm); |
4315 | if (err < 0) | ||
4312 | return err; | 4316 | return err; |
4313 | 4317 | ||
4314 | if ((err = snd_hdspm_create_hwdep(card, hdspm)) < 0) | 4318 | err = snd_hdspm_create_hwdep(card, hdspm); |
4319 | if (err < 0) | ||
4315 | return err; | 4320 | return err; |
4316 | 4321 | ||
4317 | snd_printdd("proc init...\n"); | 4322 | snd_printdd("proc init...\n"); |
@@ -4326,7 +4331,8 @@ static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card, | |||
4326 | hdspm->playback_substream = NULL; | 4331 | hdspm->playback_substream = NULL; |
4327 | 4332 | ||
4328 | snd_printdd("Set defaults...\n"); | 4333 | snd_printdd("Set defaults...\n"); |
4329 | if ((err = snd_hdspm_set_defaults(hdspm)) < 0) | 4334 | err = snd_hdspm_set_defaults(hdspm); |
4335 | if (err < 0) | ||
4330 | return err; | 4336 | return err; |
4331 | 4337 | ||
4332 | snd_printdd("Update mixer controls...\n"); | 4338 | snd_printdd("Update mixer controls...\n"); |
@@ -4334,7 +4340,8 @@ static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card, | |||
4334 | 4340 | ||
4335 | snd_printdd("Initializeing complete ???\n"); | 4341 | snd_printdd("Initializeing complete ???\n"); |
4336 | 4342 | ||
4337 | if ((err = snd_card_register(card)) < 0) { | 4343 | err = snd_card_register(card); |
4344 | if (err < 0) { | ||
4338 | snd_printk(KERN_ERR "HDSPM: error registering card\n"); | 4345 | snd_printk(KERN_ERR "HDSPM: error registering card\n"); |
4339 | return err; | 4346 | return err; |
4340 | } | 4347 | } |
@@ -4344,36 +4351,18 @@ static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card, | |||
4344 | return 0; | 4351 | return 0; |
4345 | } | 4352 | } |
4346 | 4353 | ||
4347 | static int __devinit snd_hdspm_create(struct snd_card *card, struct hdspm * hdspm, | 4354 | static int __devinit snd_hdspm_create(struct snd_card *card, |
4355 | struct hdspm *hdspm, | ||
4348 | int precise_ptr, int enable_monitor) | 4356 | int precise_ptr, int enable_monitor) |
4349 | { | 4357 | { |
4350 | struct pci_dev *pci = hdspm->pci; | 4358 | struct pci_dev *pci = hdspm->pci; |
4351 | int err; | 4359 | int err; |
4352 | int i; | ||
4353 | |||
4354 | unsigned long io_extent; | 4360 | unsigned long io_extent; |
4355 | 4361 | ||
4356 | hdspm->irq = -1; | 4362 | hdspm->irq = -1; |
4357 | hdspm->irq_count = 0; | 4363 | |
4358 | |||
4359 | hdspm->midi[0].rmidi = NULL; | ||
4360 | hdspm->midi[1].rmidi = NULL; | ||
4361 | hdspm->midi[0].input = NULL; | ||
4362 | hdspm->midi[1].input = NULL; | ||
4363 | hdspm->midi[0].output = NULL; | ||
4364 | hdspm->midi[1].output = NULL; | ||
4365 | spin_lock_init(&hdspm->midi[0].lock); | 4364 | spin_lock_init(&hdspm->midi[0].lock); |
4366 | spin_lock_init(&hdspm->midi[1].lock); | 4365 | spin_lock_init(&hdspm->midi[1].lock); |
4367 | hdspm->iobase = NULL; | ||
4368 | hdspm->control_register = 0; | ||
4369 | hdspm->control2_register = 0; | ||
4370 | |||
4371 | hdspm->playback_buffer = NULL; | ||
4372 | hdspm->capture_buffer = NULL; | ||
4373 | |||
4374 | for (i = 0; i < HDSPM_MAX_CHANNELS; ++i) | ||
4375 | hdspm->playback_mixer_ctls[i] = NULL; | ||
4376 | hdspm->mixer = NULL; | ||
4377 | 4366 | ||
4378 | hdspm->card = card; | 4367 | hdspm->card = card; |
4379 | 4368 | ||
@@ -4396,12 +4385,14 @@ static int __devinit snd_hdspm_create(struct snd_card *card, struct hdspm * hdsp | |||
4396 | hdspm->card_name = "RME HDSPM MADI"; | 4385 | hdspm->card_name = "RME HDSPM MADI"; |
4397 | } | 4386 | } |
4398 | 4387 | ||
4399 | if ((err = pci_enable_device(pci)) < 0) | 4388 | err = pci_enable_device(pci); |
4389 | if (err < 0) | ||
4400 | return err; | 4390 | return err; |
4401 | 4391 | ||
4402 | pci_set_master(hdspm->pci); | 4392 | pci_set_master(hdspm->pci); |
4403 | 4393 | ||
4404 | if ((err = pci_request_regions(pci, "hdspm")) < 0) | 4394 | err = pci_request_regions(pci, "hdspm"); |
4395 | if (err < 0) | ||
4405 | return err; | 4396 | return err; |
4406 | 4397 | ||
4407 | hdspm->port = pci_resource_start(pci, 0); | 4398 | hdspm->port = pci_resource_start(pci, 0); |
@@ -4411,8 +4402,10 @@ static int __devinit snd_hdspm_create(struct snd_card *card, struct hdspm * hdsp | |||
4411 | hdspm->port, hdspm->port + io_extent - 1); | 4402 | hdspm->port, hdspm->port + io_extent - 1); |
4412 | 4403 | ||
4413 | 4404 | ||
4414 | if ((hdspm->iobase = ioremap_nocache(hdspm->port, io_extent)) == NULL) { | 4405 | hdspm->iobase = ioremap_nocache(hdspm->port, io_extent); |
4415 | snd_printk(KERN_ERR "HDSPM: unable to remap region 0x%lx-0x%lx\n", | 4406 | if (!hdspm->iobase) { |
4407 | snd_printk(KERN_ERR "HDSPM: " | ||
4408 | "unable to remap region 0x%lx-0x%lx\n", | ||
4416 | hdspm->port, hdspm->port + io_extent - 1); | 4409 | hdspm->port, hdspm->port + io_extent - 1); |
4417 | return -EBUSY; | 4410 | return -EBUSY; |
4418 | } | 4411 | } |
@@ -4435,9 +4428,10 @@ static int __devinit snd_hdspm_create(struct snd_card *card, struct hdspm * hdsp | |||
4435 | 4428 | ||
4436 | snd_printdd("kmalloc Mixer memory of %zd Bytes\n", | 4429 | snd_printdd("kmalloc Mixer memory of %zd Bytes\n", |
4437 | sizeof(struct hdspm_mixer)); | 4430 | sizeof(struct hdspm_mixer)); |
4438 | if ((hdspm->mixer = kmalloc(sizeof(struct hdspm_mixer), GFP_KERNEL)) | 4431 | hdspm->mixer = kzalloc(sizeof(struct hdspm_mixer), GFP_KERNEL); |
4439 | == NULL) { | 4432 | if (!hdspm->mixer) { |
4440 | snd_printk(KERN_ERR "HDSPM: unable to kmalloc Mixer memory of %d Bytes\n", | 4433 | snd_printk(KERN_ERR "HDSPM: " |
4434 | "unable to kmalloc Mixer memory of %d Bytes\n", | ||
4441 | (int)sizeof(struct hdspm_mixer)); | 4435 | (int)sizeof(struct hdspm_mixer)); |
4442 | return err; | 4436 | return err; |
4443 | } | 4437 | } |
@@ -4447,7 +4441,8 @@ static int __devinit snd_hdspm_create(struct snd_card *card, struct hdspm * hdsp | |||
4447 | hdspm->qs_channels = MADI_QS_CHANNELS; | 4441 | hdspm->qs_channels = MADI_QS_CHANNELS; |
4448 | 4442 | ||
4449 | snd_printdd("create alsa devices.\n"); | 4443 | snd_printdd("create alsa devices.\n"); |
4450 | if ((err = snd_hdspm_create_alsa_devices(card, hdspm)) < 0) | 4444 | err = snd_hdspm_create_alsa_devices(card, hdspm); |
4445 | if (err < 0) | ||
4451 | return err; | 4446 | return err; |
4452 | 4447 | ||
4453 | snd_hdspm_initialize_midi_flush(hdspm); | 4448 | snd_hdspm_initialize_midi_flush(hdspm); |
@@ -4462,9 +4457,8 @@ static int snd_hdspm_free(struct hdspm * hdspm) | |||
4462 | 4457 | ||
4463 | /* stop th audio, and cancel all interrupts */ | 4458 | /* stop th audio, and cancel all interrupts */ |
4464 | hdspm->control_register &= | 4459 | hdspm->control_register &= |
4465 | ~(HDSPM_Start | HDSPM_AudioInterruptEnable | 4460 | ~(HDSPM_Start | HDSPM_AudioInterruptEnable | |
4466 | | HDSPM_Midi0InterruptEnable | | 4461 | HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable); |
4467 | HDSPM_Midi1InterruptEnable); | ||
4468 | hdspm_write(hdspm, HDSPM_controlRegister, | 4462 | hdspm_write(hdspm, HDSPM_controlRegister, |
4469 | hdspm->control_register); | 4463 | hdspm->control_register); |
4470 | } | 4464 | } |
@@ -4472,7 +4466,6 @@ static int snd_hdspm_free(struct hdspm * hdspm) | |||
4472 | if (hdspm->irq >= 0) | 4466 | if (hdspm->irq >= 0) |
4473 | free_irq(hdspm->irq, (void *) hdspm); | 4467 | free_irq(hdspm->irq, (void *) hdspm); |
4474 | 4468 | ||
4475 | |||
4476 | kfree(hdspm->mixer); | 4469 | kfree(hdspm->mixer); |
4477 | 4470 | ||
4478 | if (hdspm->iobase) | 4471 | if (hdspm->iobase) |
@@ -4487,7 +4480,7 @@ static int snd_hdspm_free(struct hdspm * hdspm) | |||
4487 | 4480 | ||
4488 | static void snd_hdspm_card_free(struct snd_card *card) | 4481 | static void snd_hdspm_card_free(struct snd_card *card) |
4489 | { | 4482 | { |
4490 | struct hdspm *hdspm = (struct hdspm *) card->private_data; | 4483 | struct hdspm *hdspm = card->private_data; |
4491 | 4484 | ||
4492 | if (hdspm) | 4485 | if (hdspm) |
4493 | snd_hdspm_free(hdspm); | 4486 | snd_hdspm_free(hdspm); |
@@ -4508,20 +4501,21 @@ static int __devinit snd_hdspm_probe(struct pci_dev *pci, | |||
4508 | return -ENOENT; | 4501 | return -ENOENT; |
4509 | } | 4502 | } |
4510 | 4503 | ||
4511 | if (!(card = snd_card_new(index[dev], id[dev], | 4504 | card = snd_card_new(index[dev], id[dev], |
4512 | THIS_MODULE, sizeof(struct hdspm)))) | 4505 | THIS_MODULE, sizeof(struct hdspm)); |
4506 | if (!card) | ||
4513 | return -ENOMEM; | 4507 | return -ENOMEM; |
4514 | 4508 | ||
4515 | hdspm = (struct hdspm *) card->private_data; | 4509 | hdspm = card->private_data; |
4516 | card->private_free = snd_hdspm_card_free; | 4510 | card->private_free = snd_hdspm_card_free; |
4517 | hdspm->dev = dev; | 4511 | hdspm->dev = dev; |
4518 | hdspm->pci = pci; | 4512 | hdspm->pci = pci; |
4519 | 4513 | ||
4520 | snd_card_set_dev(card, &pci->dev); | 4514 | snd_card_set_dev(card, &pci->dev); |
4521 | 4515 | ||
4522 | if ((err = | 4516 | err = snd_hdspm_create(card, hdspm, precise_ptr[dev], |
4523 | snd_hdspm_create(card, hdspm, precise_ptr[dev], | 4517 | enable_monitor[dev]); |
4524 | enable_monitor[dev])) < 0) { | 4518 | if (err < 0) { |
4525 | snd_card_free(card); | 4519 | snd_card_free(card); |
4526 | return err; | 4520 | return err; |
4527 | } | 4521 | } |
@@ -4530,7 +4524,8 @@ static int __devinit snd_hdspm_probe(struct pci_dev *pci, | |||
4530 | sprintf(card->longname, "%s at 0x%lx, irq %d", hdspm->card_name, | 4524 | sprintf(card->longname, "%s at 0x%lx, irq %d", hdspm->card_name, |
4531 | hdspm->port, hdspm->irq); | 4525 | hdspm->port, hdspm->irq); |
4532 | 4526 | ||
4533 | if ((err = snd_card_register(card)) < 0) { | 4527 | err = snd_card_register(card); |
4528 | if (err < 0) { | ||
4534 | snd_card_free(card); | 4529 | snd_card_free(card); |
4535 | return err; | 4530 | return err; |
4536 | } | 4531 | } |
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index 2de27405a0bd..34f96f12e5bf 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c | |||
@@ -1067,14 +1067,7 @@ static int rme9652_set_spdif_output(struct snd_rme9652 *rme9652, int out) | |||
1067 | return 0; | 1067 | return 0; |
1068 | } | 1068 | } |
1069 | 1069 | ||
1070 | static int snd_rme9652_info_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1070 | #define snd_rme9652_info_spdif_out snd_ctl_boolean_mono_info |
1071 | { | ||
1072 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1073 | uinfo->count = 1; | ||
1074 | uinfo->value.integer.min = 0; | ||
1075 | uinfo->value.integer.max = 1; | ||
1076 | return 0; | ||
1077 | } | ||
1078 | 1071 | ||
1079 | static int snd_rme9652_get_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1072 | static int snd_rme9652_get_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1080 | { | 1073 | { |
@@ -1338,14 +1331,7 @@ static int snd_rme9652_put_thru(struct snd_kcontrol *kcontrol, struct snd_ctl_el | |||
1338 | .put = snd_rme9652_put_passthru, \ | 1331 | .put = snd_rme9652_put_passthru, \ |
1339 | .get = snd_rme9652_get_passthru } | 1332 | .get = snd_rme9652_get_passthru } |
1340 | 1333 | ||
1341 | static int snd_rme9652_info_passthru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1334 | #define snd_rme9652_info_passthru snd_ctl_boolean_mono_info |
1342 | { | ||
1343 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1344 | uinfo->count = 1; | ||
1345 | uinfo->value.integer.min = 0; | ||
1346 | uinfo->value.integer.max = 1; | ||
1347 | return 0; | ||
1348 | } | ||
1349 | 1335 | ||
1350 | static int snd_rme9652_get_passthru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1336 | static int snd_rme9652_get_passthru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1351 | { | 1337 | { |
@@ -1445,14 +1431,7 @@ static int snd_rme9652_get_adat_sync(struct snd_kcontrol *kcontrol, struct snd_c | |||
1445 | .info = snd_rme9652_info_tc_valid, \ | 1431 | .info = snd_rme9652_info_tc_valid, \ |
1446 | .get = snd_rme9652_get_tc_valid } | 1432 | .get = snd_rme9652_get_tc_valid } |
1447 | 1433 | ||
1448 | static int snd_rme9652_info_tc_valid(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1434 | #define snd_rme9652_info_tc_valid snd_ctl_boolean_mono_info |
1449 | { | ||
1450 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1451 | uinfo->count = 1; | ||
1452 | uinfo->value.integer.min = 0; | ||
1453 | uinfo->value.integer.max = 1; | ||
1454 | return 0; | ||
1455 | } | ||
1456 | 1435 | ||
1457 | static int snd_rme9652_get_tc_valid(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1436 | static int snd_rme9652_get_tc_valid(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1458 | { | 1437 | { |
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 9f25d93cbec2..44a7f5fad573 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for S3 SonicVibes soundcard | 2 | * Driver for S3 SonicVibes soundcard |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * BUGS: | 5 | * BUGS: |
6 | * It looks like 86c617 rev 3 doesn't supports DDMA buffers above 16MB? | 6 | * It looks like 86c617 rev 3 doesn't supports DDMA buffers above 16MB? |
@@ -42,7 +42,7 @@ | |||
42 | 42 | ||
43 | #include <asm/io.h> | 43 | #include <asm/io.h> |
44 | 44 | ||
45 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 45 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
46 | MODULE_DESCRIPTION("S3 SonicVibes PCI"); | 46 | MODULE_DESCRIPTION("S3 SonicVibes PCI"); |
47 | MODULE_LICENSE("GPL"); | 47 | MODULE_LICENSE("GPL"); |
48 | MODULE_SUPPORTED_DEVICE("{{S3,SonicVibes PCI}}"); | 48 | MODULE_SUPPORTED_DEVICE("{{S3,SonicVibes PCI}}"); |
diff --git a/sound/pci/trident/Makefile b/sound/pci/trident/Makefile index 65bc5b703239..65f2c218324c 100644 --- a/sound/pci/trident/Makefile +++ b/sound/pci/trident/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-trident-objs := trident.o trident_main.o trident_memory.o | 6 | snd-trident-objs := trident.o trident_main.o trident_memory.o |
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index 9145f7c57fb0..84884567df6a 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <sound/trident.h> | 30 | #include <sound/trident.h> |
31 | #include <sound/initval.h> | 31 | #include <sound/initval.h> |
32 | 32 | ||
33 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, <audio@tridentmicro.com>"); | 33 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, <audio@tridentmicro.com>"); |
34 | MODULE_DESCRIPTION("Trident 4D-WaveDX/NX & SiS SI7018"); | 34 | MODULE_DESCRIPTION("Trident 4D-WaveDX/NX & SiS SI7018"); |
35 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
36 | MODULE_SUPPORTED_DEVICE("{{Trident,4DWave DX}," | 36 | MODULE_SUPPORTED_DEVICE("{{Trident,4DWave DX}," |
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 7ca606272460..a235e034a690 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Maintained by Jaroslav Kysela <perex@suse.cz> | 2 | * Maintained by Jaroslav Kysela <perex@perex.cz> |
3 | * Originated by audio@tridentmicro.com | 3 | * Originated by audio@tridentmicro.com |
4 | * Fri Feb 19 15:55:28 MST 1999 | 4 | * Fri Feb 19 15:55:28 MST 1999 |
5 | * Routines for control of Trident 4DWave (DX and NX) chip | 5 | * Routines for control of Trident 4DWave (DX and NX) chip |
@@ -2317,15 +2317,7 @@ int __devinit snd_trident_spdif_pcm(struct snd_trident * trident, | |||
2317 | Description: enable/disable S/PDIF out from ac97 mixer | 2317 | Description: enable/disable S/PDIF out from ac97 mixer |
2318 | ---------------------------------------------------------------------------*/ | 2318 | ---------------------------------------------------------------------------*/ |
2319 | 2319 | ||
2320 | static int snd_trident_spdif_control_info(struct snd_kcontrol *kcontrol, | 2320 | #define snd_trident_spdif_control_info snd_ctl_boolean_mono_info |
2321 | struct snd_ctl_elem_info *uinfo) | ||
2322 | { | ||
2323 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2324 | uinfo->count = 1; | ||
2325 | uinfo->value.integer.min = 0; | ||
2326 | uinfo->value.integer.max = 1; | ||
2327 | return 0; | ||
2328 | } | ||
2329 | 2321 | ||
2330 | static int snd_trident_spdif_control_get(struct snd_kcontrol *kcontrol, | 2322 | static int snd_trident_spdif_control_get(struct snd_kcontrol *kcontrol, |
2331 | struct snd_ctl_elem_value *ucontrol) | 2323 | struct snd_ctl_elem_value *ucontrol) |
@@ -2545,15 +2537,7 @@ static struct snd_kcontrol_new snd_trident_spdif_stream __devinitdata = | |||
2545 | Description: enable/disable rear path for ac97 | 2537 | Description: enable/disable rear path for ac97 |
2546 | ---------------------------------------------------------------------------*/ | 2538 | ---------------------------------------------------------------------------*/ |
2547 | 2539 | ||
2548 | static int snd_trident_ac97_control_info(struct snd_kcontrol *kcontrol, | 2540 | #define snd_trident_ac97_control_info snd_ctl_boolean_mono_info |
2549 | struct snd_ctl_elem_info *uinfo) | ||
2550 | { | ||
2551 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2552 | uinfo->count = 1; | ||
2553 | uinfo->value.integer.min = 0; | ||
2554 | uinfo->value.integer.max = 1; | ||
2555 | return 0; | ||
2556 | } | ||
2557 | 2541 | ||
2558 | static int snd_trident_ac97_control_get(struct snd_kcontrol *kcontrol, | 2542 | static int snd_trident_ac97_control_get(struct snd_kcontrol *kcontrol, |
2559 | struct snd_ctl_elem_value *ucontrol) | 2543 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c index aff3f874131c..847b8c6d5c0a 100644 --- a/sound/pci/trident/trident_memory.c +++ b/sound/pci/trident/trident_memory.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Copyright (c) by Takashi Iwai <tiwai@suse.de> | 3 | * Copyright (c) by Takashi Iwai <tiwai@suse.de> |
4 | * Copyright (c) by Scott McNab <sdm@fractalgraphics.com.au> | 4 | * Copyright (c) by Scott McNab <sdm@fractalgraphics.com.au> |
5 | * | 5 | * |
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 6ea09df0c73a..cf62d2ab8d7c 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * VT82C686A/B/C, VT8233A/C, VT8235 | 4 | * VT82C686A/B/C, VT8233A/C, VT8235 |
5 | * | 5 | * |
6 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 6 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
7 | * Tjeerd.Mulder <Tjeerd.Mulder@fujitsu-siemens.com> | 7 | * Tjeerd.Mulder <Tjeerd.Mulder@fujitsu-siemens.com> |
8 | * 2002 Takashi Iwai <tiwai@suse.de> | 8 | * 2002 Takashi Iwai <tiwai@suse.de> |
9 | * | 9 | * |
@@ -68,7 +68,7 @@ | |||
68 | #define POINTER_DEBUG | 68 | #define POINTER_DEBUG |
69 | #endif | 69 | #endif |
70 | 70 | ||
71 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 71 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
72 | MODULE_DESCRIPTION("VIA VT82xx audio"); | 72 | MODULE_DESCRIPTION("VIA VT82xx audio"); |
73 | MODULE_LICENSE("GPL"); | 73 | MODULE_LICENSE("GPL"); |
74 | MODULE_SUPPORTED_DEVICE("{{VIA,VT82C686A/B/C,pci},{VIA,VT8233A/C,8235}}"); | 74 | MODULE_SUPPORTED_DEVICE("{{VIA,VT82C686A/B/C,pci},{VIA,VT8233A/C,8235}}"); |
@@ -1572,15 +1572,7 @@ static struct snd_kcontrol_new snd_via8233_capture_source __devinitdata = { | |||
1572 | .put = snd_via8233_capture_source_put, | 1572 | .put = snd_via8233_capture_source_put, |
1573 | }; | 1573 | }; |
1574 | 1574 | ||
1575 | static int snd_via8233_dxs3_spdif_info(struct snd_kcontrol *kcontrol, | 1575 | #define snd_via8233_dxs3_spdif_info snd_ctl_boolean_mono_info |
1576 | struct snd_ctl_elem_info *uinfo) | ||
1577 | { | ||
1578 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1579 | uinfo->count = 1; | ||
1580 | uinfo->value.integer.min = 0; | ||
1581 | uinfo->value.integer.max = 1; | ||
1582 | return 0; | ||
1583 | } | ||
1584 | 1576 | ||
1585 | static int snd_via8233_dxs3_spdif_get(struct snd_kcontrol *kcontrol, | 1577 | static int snd_via8233_dxs3_spdif_get(struct snd_kcontrol *kcontrol, |
1586 | struct snd_ctl_elem_value *ucontrol) | 1578 | struct snd_ctl_elem_value *ucontrol) |
@@ -2098,7 +2090,7 @@ static int snd_via82xx_chip_init(struct via82xx *chip) | |||
2098 | pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); | 2090 | pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); |
2099 | if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ | 2091 | if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ |
2100 | break; | 2092 | break; |
2101 | schedule_timeout(1); | 2093 | schedule_timeout_uninterruptible(1); |
2102 | } while (time_before(jiffies, end_time)); | 2094 | } while (time_before(jiffies, end_time)); |
2103 | 2095 | ||
2104 | if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) | 2096 | if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) |
@@ -2117,7 +2109,7 @@ static int snd_via82xx_chip_init(struct via82xx *chip) | |||
2117 | chip->ac97_secondary = 1; | 2109 | chip->ac97_secondary = 1; |
2118 | goto __ac97_ok2; | 2110 | goto __ac97_ok2; |
2119 | } | 2111 | } |
2120 | schedule_timeout(1); | 2112 | schedule_timeout_uninterruptible(1); |
2121 | } while (time_before(jiffies, end_time)); | 2113 | } while (time_before(jiffies, end_time)); |
2122 | /* This is ok, the most of motherboards have only one codec */ | 2114 | /* This is ok, the most of motherboards have only one codec */ |
2123 | 2115 | ||
@@ -2371,6 +2363,7 @@ static struct snd_pci_quirk dxs_whitelist[] __devinitdata = { | |||
2371 | SND_PCI_QUIRK(0x1071, 0, "Diverse Notebook", VIA_DXS_NO_VRA), | 2363 | SND_PCI_QUIRK(0x1071, 0, "Diverse Notebook", VIA_DXS_NO_VRA), |
2372 | SND_PCI_QUIRK(0x10cf, 0x118e, "FSC Laptop", VIA_DXS_ENABLE), | 2364 | SND_PCI_QUIRK(0x10cf, 0x118e, "FSC Laptop", VIA_DXS_ENABLE), |
2373 | SND_PCI_QUIRK(0x1106, 0, "ASRock", VIA_DXS_SRC), | 2365 | SND_PCI_QUIRK(0x1106, 0, "ASRock", VIA_DXS_SRC), |
2366 | SND_PCI_QUIRK(0x1297, 0xa231, "Shuttle AK31v2", VIA_DXS_SRC), | ||
2374 | SND_PCI_QUIRK(0x1297, 0xa232, "Shuttle", VIA_DXS_ENABLE), | 2367 | SND_PCI_QUIRK(0x1297, 0xa232, "Shuttle", VIA_DXS_ENABLE), |
2375 | SND_PCI_QUIRK(0x1297, 0xc160, "Shuttle Sk41G", VIA_DXS_ENABLE), | 2368 | SND_PCI_QUIRK(0x1297, 0xc160, "Shuttle Sk41G", VIA_DXS_ENABLE), |
2376 | SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte GA-7VAXP", VIA_DXS_ENABLE), | 2369 | SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte GA-7VAXP", VIA_DXS_ENABLE), |
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 72425e73abae..57fb9ae22f93 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * VT82C686A/B/C, VT8233A/C, VT8235 | 4 | * VT82C686A/B/C, VT8233A/C, VT8235 |
5 | * | 5 | * |
6 | * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> | 6 | * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> |
7 | * Tjeerd.Mulder <Tjeerd.Mulder@fujitsu-siemens.com> | 7 | * Tjeerd.Mulder <Tjeerd.Mulder@fujitsu-siemens.com> |
8 | * 2002 Takashi Iwai <tiwai@suse.de> | 8 | * 2002 Takashi Iwai <tiwai@suse.de> |
9 | * | 9 | * |
@@ -50,7 +50,7 @@ | |||
50 | #define POINTER_DEBUG | 50 | #define POINTER_DEBUG |
51 | #endif | 51 | #endif |
52 | 52 | ||
53 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 53 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
54 | MODULE_DESCRIPTION("VIA VT82xx modem"); | 54 | MODULE_DESCRIPTION("VIA VT82xx modem"); |
55 | MODULE_LICENSE("GPL"); | 55 | MODULE_LICENSE("GPL"); |
56 | MODULE_SUPPORTED_DEVICE("{{VIA,VT82C686A/B/C modem,pci}}"); | 56 | MODULE_SUPPORTED_DEVICE("{{VIA,VT82C686A/B/C modem,pci}}"); |
@@ -983,7 +983,7 @@ static int snd_via82xx_chip_init(struct via82xx_modem *chip) | |||
983 | pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); | 983 | pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); |
984 | if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ | 984 | if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ |
985 | break; | 985 | break; |
986 | schedule_timeout(1); | 986 | schedule_timeout_uninterruptible(1); |
987 | } while (time_before(jiffies, end_time)); | 987 | } while (time_before(jiffies, end_time)); |
988 | 988 | ||
989 | if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) | 989 | if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) |
@@ -1001,7 +1001,7 @@ static int snd_via82xx_chip_init(struct via82xx_modem *chip) | |||
1001 | chip->ac97_secondary = 1; | 1001 | chip->ac97_secondary = 1; |
1002 | goto __ac97_ok2; | 1002 | goto __ac97_ok2; |
1003 | } | 1003 | } |
1004 | schedule_timeout(1); | 1004 | schedule_timeout_uninterruptible(1); |
1005 | } while (time_before(jiffies, end_time)); | 1005 | } while (time_before(jiffies, end_time)); |
1006 | /* This is ok, the most of motherboards have only one codec */ | 1006 | /* This is ok, the most of motherboards have only one codec */ |
1007 | 1007 | ||
diff --git a/sound/pci/vx222/Makefile b/sound/pci/vx222/Makefile index 058c8bff7c11..a4d08d4de354 100644 --- a/sound/pci/vx222/Makefile +++ b/sound/pci/vx222/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-vx222-objs := vx222.o vx222_ops.o | 6 | snd-vx222-objs := vx222.o vx222_ops.o |
diff --git a/sound/pci/ymfpci/Makefile b/sound/pci/ymfpci/Makefile index 8790c5f3ed02..bd3d514ed76b 100644 --- a/sound/pci/ymfpci/Makefile +++ b/sound/pci/ymfpci/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for ALSA | 2 | # Makefile for ALSA |
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-ymfpci-objs := ymfpci.o ymfpci_main.o | 6 | snd-ymfpci-objs := ymfpci.o ymfpci_main.o |
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index fd9b7b83a884..5c4256a4d4b9 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * The driver for the Yamaha's DS1/DS1E cards | 2 | * The driver for the Yamaha's DS1/DS1E cards |
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
4 | * | 4 | * |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
@@ -30,7 +30,7 @@ | |||
30 | #include <sound/opl3.h> | 30 | #include <sound/opl3.h> |
31 | #include <sound/initval.h> | 31 | #include <sound/initval.h> |
32 | 32 | ||
33 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 33 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
34 | MODULE_DESCRIPTION("Yamaha DS-1 PCI"); | 34 | MODULE_DESCRIPTION("Yamaha DS-1 PCI"); |
35 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
36 | MODULE_SUPPORTED_DEVICE("{{Yamaha,YMF724}," | 36 | MODULE_SUPPORTED_DEVICE("{{Yamaha,YMF724}," |
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index ab7a81c35705..1fe39ed28765 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | 2 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
3 | * Routines for control of YMF724/740/744/754 chips | 3 | * Routines for control of YMF724/740/744/754 chips |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
@@ -84,7 +84,6 @@ static int snd_ymfpci_codec_ready(struct snd_ymfpci *chip, int secondary) | |||
84 | do { | 84 | do { |
85 | if ((snd_ymfpci_readw(chip, reg) & 0x8000) == 0) | 85 | if ((snd_ymfpci_readw(chip, reg) & 0x8000) == 0) |
86 | return 0; | 86 | return 0; |
87 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
88 | schedule_timeout_uninterruptible(1); | 87 | schedule_timeout_uninterruptible(1); |
89 | } while (time_before(jiffies, end_time)); | 88 | } while (time_before(jiffies, end_time)); |
90 | snd_printk(KERN_ERR "codec_ready: codec %i is not ready [0x%x]\n", secondary, snd_ymfpci_readw(chip, reg)); | 89 | snd_printk(KERN_ERR "codec_ready: codec %i is not ready [0x%x]\n", secondary, snd_ymfpci_readw(chip, reg)); |
@@ -171,17 +170,6 @@ static u32 snd_ymfpci_calc_lpfQ(u32 rate) | |||
171 | return val[0]; | 170 | return val[0]; |
172 | } | 171 | } |
173 | 172 | ||
174 | static void snd_ymfpci_pcm_441_volume_set(struct snd_ymfpci_pcm *ypcm) | ||
175 | { | ||
176 | unsigned int value; | ||
177 | struct snd_ymfpci_pcm_mixer *mixer; | ||
178 | |||
179 | mixer = &ypcm->chip->pcm_mixer[ypcm->substream->number]; | ||
180 | value = min_t(unsigned int, mixer->left, 0x7fff) >> 1; | ||
181 | value |= (min_t(unsigned int, mixer->right, 0x7fff) >> 1) << 16; | ||
182 | snd_ymfpci_writel(ypcm->chip, YDSXGR_BUF441OUTVOL, value); | ||
183 | } | ||
184 | |||
185 | /* | 173 | /* |
186 | * Hardware start management | 174 | * Hardware start management |
187 | */ | 175 | */ |
@@ -389,6 +377,7 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream, | |||
389 | { | 377 | { |
390 | struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); | 378 | struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); |
391 | struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; | 379 | struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; |
380 | struct snd_kcontrol *kctl = NULL; | ||
392 | int result = 0; | 381 | int result = 0; |
393 | 382 | ||
394 | spin_lock(&chip->reg_lock); | 383 | spin_lock(&chip->reg_lock); |
@@ -406,6 +395,11 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream, | |||
406 | ypcm->running = 1; | 395 | ypcm->running = 1; |
407 | break; | 396 | break; |
408 | case SNDRV_PCM_TRIGGER_STOP: | 397 | case SNDRV_PCM_TRIGGER_STOP: |
398 | if (substream->pcm == chip->pcm && !ypcm->use_441_slot) { | ||
399 | kctl = chip->pcm_mixer[substream->number].ctl; | ||
400 | kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; | ||
401 | } | ||
402 | /* fall through */ | ||
409 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 403 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
410 | case SNDRV_PCM_TRIGGER_SUSPEND: | 404 | case SNDRV_PCM_TRIGGER_SUSPEND: |
411 | chip->ctrl_playback[ypcm->voices[0]->number + 1] = 0; | 405 | chip->ctrl_playback[ypcm->voices[0]->number + 1] = 0; |
@@ -419,6 +413,8 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream, | |||
419 | } | 413 | } |
420 | __unlock: | 414 | __unlock: |
421 | spin_unlock(&chip->reg_lock); | 415 | spin_unlock(&chip->reg_lock); |
416 | if (kctl) | ||
417 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id); | ||
422 | return result; | 418 | return result; |
423 | } | 419 | } |
424 | static int snd_ymfpci_capture_trigger(struct snd_pcm_substream *substream, | 420 | static int snd_ymfpci_capture_trigger(struct snd_pcm_substream *substream, |
@@ -526,7 +522,6 @@ static void snd_ymfpci_pcm_init_voice(struct snd_ymfpci_pcm *ypcm, unsigned int | |||
526 | ypcm->chip->src441_used = voice->number; | 522 | ypcm->chip->src441_used = voice->number; |
527 | ypcm->use_441_slot = 1; | 523 | ypcm->use_441_slot = 1; |
528 | format |= 0x10000000; | 524 | format |= 0x10000000; |
529 | snd_ymfpci_pcm_441_volume_set(ypcm); | ||
530 | } | 525 | } |
531 | if (ypcm->chip->src441_used == voice->number && | 526 | if (ypcm->chip->src441_used == voice->number && |
532 | (format & 0x10000000) == 0) { | 527 | (format & 0x10000000) == 0) { |
@@ -667,6 +662,7 @@ static int snd_ymfpci_playback_prepare(struct snd_pcm_substream *substream) | |||
667 | struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); | 662 | struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); |
668 | struct snd_pcm_runtime *runtime = substream->runtime; | 663 | struct snd_pcm_runtime *runtime = substream->runtime; |
669 | struct snd_ymfpci_pcm *ypcm = runtime->private_data; | 664 | struct snd_ymfpci_pcm *ypcm = runtime->private_data; |
665 | struct snd_kcontrol *kctl; | ||
670 | unsigned int nvoice; | 666 | unsigned int nvoice; |
671 | 667 | ||
672 | ypcm->period_size = runtime->period_size; | 668 | ypcm->period_size = runtime->period_size; |
@@ -676,6 +672,12 @@ static int snd_ymfpci_playback_prepare(struct snd_pcm_substream *substream) | |||
676 | for (nvoice = 0; nvoice < runtime->channels; nvoice++) | 672 | for (nvoice = 0; nvoice < runtime->channels; nvoice++) |
677 | snd_ymfpci_pcm_init_voice(ypcm, nvoice, runtime, | 673 | snd_ymfpci_pcm_init_voice(ypcm, nvoice, runtime, |
678 | substream->pcm == chip->pcm); | 674 | substream->pcm == chip->pcm); |
675 | |||
676 | if (substream->pcm == chip->pcm && !ypcm->use_441_slot) { | ||
677 | kctl = chip->pcm_mixer[substream->number].ctl; | ||
678 | kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; | ||
679 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id); | ||
680 | } | ||
679 | return 0; | 681 | return 0; |
680 | } | 682 | } |
681 | 683 | ||
@@ -926,7 +928,6 @@ static int snd_ymfpci_playback_open(struct snd_pcm_substream *substream) | |||
926 | struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); | 928 | struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); |
927 | struct snd_pcm_runtime *runtime = substream->runtime; | 929 | struct snd_pcm_runtime *runtime = substream->runtime; |
928 | struct snd_ymfpci_pcm *ypcm; | 930 | struct snd_ymfpci_pcm *ypcm; |
929 | struct snd_kcontrol *kctl; | ||
930 | int err; | 931 | int err; |
931 | 932 | ||
932 | if ((err = snd_ymfpci_playback_open_1(substream)) < 0) | 933 | if ((err = snd_ymfpci_playback_open_1(substream)) < 0) |
@@ -941,10 +942,6 @@ static int snd_ymfpci_playback_open(struct snd_pcm_substream *substream) | |||
941 | chip->rear_opened++; | 942 | chip->rear_opened++; |
942 | } | 943 | } |
943 | spin_unlock_irq(&chip->reg_lock); | 944 | spin_unlock_irq(&chip->reg_lock); |
944 | |||
945 | kctl = chip->pcm_mixer[substream->number].ctl; | ||
946 | kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; | ||
947 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id); | ||
948 | return 0; | 945 | return 0; |
949 | } | 946 | } |
950 | 947 | ||
@@ -1039,7 +1036,6 @@ static int snd_ymfpci_playback_close(struct snd_pcm_substream *substream) | |||
1039 | { | 1036 | { |
1040 | struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); | 1037 | struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); |
1041 | struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; | 1038 | struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; |
1042 | struct snd_kcontrol *kctl; | ||
1043 | 1039 | ||
1044 | spin_lock_irq(&chip->reg_lock); | 1040 | spin_lock_irq(&chip->reg_lock); |
1045 | if (ypcm->output_rear && chip->rear_opened > 0) { | 1041 | if (ypcm->output_rear && chip->rear_opened > 0) { |
@@ -1047,9 +1043,6 @@ static int snd_ymfpci_playback_close(struct snd_pcm_substream *substream) | |||
1047 | ymfpci_close_extension(chip); | 1043 | ymfpci_close_extension(chip); |
1048 | } | 1044 | } |
1049 | spin_unlock_irq(&chip->reg_lock); | 1045 | spin_unlock_irq(&chip->reg_lock); |
1050 | kctl = chip->pcm_mixer[substream->number].ctl; | ||
1051 | kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; | ||
1052 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id); | ||
1053 | return snd_ymfpci_playback_close_1(substream); | 1046 | return snd_ymfpci_playback_close_1(substream); |
1054 | } | 1047 | } |
1055 | 1048 | ||
@@ -1443,22 +1436,7 @@ static struct snd_kcontrol_new snd_ymfpci_drec_source __devinitdata = { | |||
1443 | .get = snd_ymfpci_get_single, .put = snd_ymfpci_put_single, \ | 1436 | .get = snd_ymfpci_get_single, .put = snd_ymfpci_put_single, \ |
1444 | .private_value = ((reg) | ((shift) << 16)) } | 1437 | .private_value = ((reg) | ((shift) << 16)) } |
1445 | 1438 | ||
1446 | static int snd_ymfpci_info_single(struct snd_kcontrol *kcontrol, | 1439 | #define snd_ymfpci_info_single snd_ctl_boolean_mono_info |
1447 | struct snd_ctl_elem_info *uinfo) | ||
1448 | { | ||
1449 | int reg = kcontrol->private_value & 0xffff; | ||
1450 | |||
1451 | switch (reg) { | ||
1452 | case YDSXGR_SPDIFOUTCTRL: break; | ||
1453 | case YDSXGR_SPDIFINCTRL: break; | ||
1454 | default: return -EINVAL; | ||
1455 | } | ||
1456 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1457 | uinfo->count = 1; | ||
1458 | uinfo->value.integer.min = 0; | ||
1459 | uinfo->value.integer.max = 1; | ||
1460 | return 0; | ||
1461 | } | ||
1462 | 1440 | ||
1463 | static int snd_ymfpci_get_single(struct snd_kcontrol *kcontrol, | 1441 | static int snd_ymfpci_get_single(struct snd_kcontrol *kcontrol, |
1464 | struct snd_ctl_elem_value *ucontrol) | 1442 | struct snd_ctl_elem_value *ucontrol) |
@@ -1567,17 +1545,30 @@ static int snd_ymfpci_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
1567 | return change; | 1545 | return change; |
1568 | } | 1546 | } |
1569 | 1547 | ||
1548 | static int snd_ymfpci_put_nativedacvol(struct snd_kcontrol *kcontrol, | ||
1549 | struct snd_ctl_elem_value *ucontrol) | ||
1550 | { | ||
1551 | struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol); | ||
1552 | unsigned int reg = YDSXGR_NATIVEDACOUTVOL; | ||
1553 | unsigned int reg2 = YDSXGR_BUF441OUTVOL; | ||
1554 | int change; | ||
1555 | unsigned int value, oval; | ||
1556 | |||
1557 | value = ucontrol->value.integer.value[0] & 0x3fff; | ||
1558 | value |= (ucontrol->value.integer.value[1] & 0x3fff) << 16; | ||
1559 | spin_lock_irq(&chip->reg_lock); | ||
1560 | oval = snd_ymfpci_readl(chip, reg); | ||
1561 | change = value != oval; | ||
1562 | snd_ymfpci_writel(chip, reg, value); | ||
1563 | snd_ymfpci_writel(chip, reg2, value); | ||
1564 | spin_unlock_irq(&chip->reg_lock); | ||
1565 | return change; | ||
1566 | } | ||
1567 | |||
1570 | /* | 1568 | /* |
1571 | * 4ch duplication | 1569 | * 4ch duplication |
1572 | */ | 1570 | */ |
1573 | static int snd_ymfpci_info_dup4ch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1571 | #define snd_ymfpci_info_dup4ch snd_ctl_boolean_mono_info |
1574 | { | ||
1575 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1576 | uinfo->count = 1; | ||
1577 | uinfo->value.integer.min = 0; | ||
1578 | uinfo->value.integer.max = 1; | ||
1579 | return 0; | ||
1580 | } | ||
1581 | 1572 | ||
1582 | static int snd_ymfpci_get_dup4ch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1573 | static int snd_ymfpci_get_dup4ch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1583 | { | 1574 | { |
@@ -1598,7 +1589,17 @@ static int snd_ymfpci_put_dup4ch(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
1598 | 1589 | ||
1599 | 1590 | ||
1600 | static struct snd_kcontrol_new snd_ymfpci_controls[] __devinitdata = { | 1591 | static struct snd_kcontrol_new snd_ymfpci_controls[] __devinitdata = { |
1601 | YMFPCI_DOUBLE("Wave Playback Volume", 0, YDSXGR_NATIVEDACOUTVOL), | 1592 | { |
1593 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1594 | .name = "Wave Playback Volume", | ||
1595 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
1596 | SNDRV_CTL_ELEM_ACCESS_TLV_READ, | ||
1597 | .info = snd_ymfpci_info_double, | ||
1598 | .get = snd_ymfpci_get_double, | ||
1599 | .put = snd_ymfpci_put_nativedacvol, | ||
1600 | .private_value = YDSXGR_NATIVEDACOUTVOL, | ||
1601 | .tlv = { .p = db_scale_native }, | ||
1602 | }, | ||
1602 | YMFPCI_DOUBLE("Wave Capture Volume", 0, YDSXGR_NATIVEDACLOOPVOL), | 1603 | YMFPCI_DOUBLE("Wave Capture Volume", 0, YDSXGR_NATIVEDACLOOPVOL), |
1603 | YMFPCI_DOUBLE("Digital Capture Volume", 0, YDSXGR_NATIVEDACINVOL), | 1604 | YMFPCI_DOUBLE("Digital Capture Volume", 0, YDSXGR_NATIVEDACINVOL), |
1604 | YMFPCI_DOUBLE("Digital Capture Volume", 1, YDSXGR_NATIVEADCINVOL), | 1605 | YMFPCI_DOUBLE("Digital Capture Volume", 1, YDSXGR_NATIVEADCINVOL), |
@@ -1665,14 +1666,7 @@ static int snd_ymfpci_set_gpio_out(struct snd_ymfpci *chip, int pin, int enable) | |||
1665 | return 0; | 1666 | return 0; |
1666 | } | 1667 | } |
1667 | 1668 | ||
1668 | static int snd_ymfpci_gpio_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1669 | #define snd_ymfpci_gpio_sw_info snd_ctl_boolean_mono_info |
1669 | { | ||
1670 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1671 | uinfo->count = 1; | ||
1672 | uinfo->value.integer.min = 0; | ||
1673 | uinfo->value.integer.max = 1; | ||
1674 | return 0; | ||
1675 | } | ||
1676 | 1670 | ||
1677 | static int snd_ymfpci_gpio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 1671 | static int snd_ymfpci_gpio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
1678 | { | 1672 | { |
@@ -1748,8 +1742,6 @@ static int snd_ymfpci_pcm_vol_put(struct snd_kcontrol *kcontrol, | |||
1748 | struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; | 1742 | struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; |
1749 | if (!ypcm->use_441_slot) | 1743 | if (!ypcm->use_441_slot) |
1750 | ypcm->update_pcm_vol = 2; | 1744 | ypcm->update_pcm_vol = 2; |
1751 | else | ||
1752 | snd_ymfpci_pcm_441_volume_set(ypcm); | ||
1753 | } | 1745 | } |
1754 | spin_unlock_irqrestore(&chip->voice_lock, flags); | 1746 | spin_unlock_irqrestore(&chip->voice_lock, flags); |
1755 | return 1; | 1747 | return 1; |