diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-25 11:32:05 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-25 11:32:05 -0400 |
commit | 33081adf8b89d5a716d7e1c60171768d39795b39 (patch) | |
tree | 275de58bbbb5f7ddffcdc087844cfc7fbe4315be /sound/pci | |
parent | c55960499f810357a29659b32d6ea594abee9237 (diff) | |
parent | 506ecbca71d07fa327dd986be1682e90885678ee (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6: (365 commits)
ALSA: hda - Disable sticky PCM stream assignment for AD codecs
ALSA: usb - Creative USB X-Fi volume knob support
ALSA: ca0106: Use card specific dac id for mute controls.
ALSA: ca0106: Allow different sound cards to use different SPI channel mappings.
ALSA: ca0106: Create a nice spot for mapping channels to dacs.
ALSA: ca0106: Move enabling of front dac out of hardcoded setup sequence.
ALSA: ca0106: Pull out dac powering routine into separate function.
ALSA: ca0106 - add Sound Blaster 5.1vx info.
ASoC: tlv320dac33: Use usleep_range for delays
ALSA: usb-audio: add Novation Launchpad support
ALSA: hda - Add workarounds for CT-IBG controllers
ALSA: hda - Fix wrong TLV mute bit for STAC/IDT codecs
ASoC: tpa6130a2: Error handling for broken chip
ASoC: max98088: Staticise m98088_eq_band
ASoC: soc-core: Fix codec->name memory leak
ALSA: hda - Apply ideapad quirk to Acer laptops with Cxt5066
ALSA: hda - Add some workarounds for Creative IBG
ALSA: hda - Fix wrong SPDIF NID assignment for CA0110
ALSA: hda - Fix codec rename rules for ALC662-compatible codecs
ALSA: hda - Add alc_init_jacks() call to other codecs
...
Diffstat (limited to 'sound/pci')
41 files changed, 3206 insertions, 2401 deletions
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index e7a8cd058efb..12e34653b8a8 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig | |||
@@ -207,12 +207,12 @@ config SND_CMIPCI | |||
207 | 207 | ||
208 | config SND_OXYGEN_LIB | 208 | config SND_OXYGEN_LIB |
209 | tristate | 209 | tristate |
210 | select SND_PCM | ||
211 | select SND_MPU401_UART | ||
212 | 210 | ||
213 | config SND_OXYGEN | 211 | config SND_OXYGEN |
214 | tristate "C-Media 8788 (Oxygen)" | 212 | tristate "C-Media 8788 (Oxygen)" |
215 | select SND_OXYGEN_LIB | 213 | select SND_OXYGEN_LIB |
214 | select SND_PCM | ||
215 | select SND_MPU401_UART | ||
216 | help | 216 | help |
217 | Say Y here to include support for sound cards based on the | 217 | Say Y here to include support for sound cards based on the |
218 | C-Media CMI8788 (Oxygen HD Audio) chip: | 218 | C-Media CMI8788 (Oxygen HD Audio) chip: |
@@ -581,6 +581,8 @@ config SND_HDSPM | |||
581 | config SND_HIFIER | 581 | config SND_HIFIER |
582 | tristate "TempoTec HiFier Fantasia" | 582 | tristate "TempoTec HiFier Fantasia" |
583 | select SND_OXYGEN_LIB | 583 | select SND_OXYGEN_LIB |
584 | select SND_PCM | ||
585 | select SND_MPU401_UART | ||
584 | help | 586 | help |
585 | Say Y here to include support for the MediaTek/TempoTec HiFier | 587 | Say Y here to include support for the MediaTek/TempoTec HiFier |
586 | Fantasia sound card. | 588 | Fantasia sound card. |
@@ -815,14 +817,17 @@ config SND_VIA82XX_MODEM | |||
815 | will be called snd-via82xx-modem. | 817 | will be called snd-via82xx-modem. |
816 | 818 | ||
817 | config SND_VIRTUOSO | 819 | config SND_VIRTUOSO |
818 | tristate "Asus Virtuoso 100/200 (Xonar)" | 820 | tristate "Asus Virtuoso 66/100/200 (Xonar)" |
819 | select SND_OXYGEN_LIB | 821 | select SND_OXYGEN_LIB |
822 | select SND_PCM | ||
823 | select SND_MPU401_UART | ||
824 | select SND_JACK if INPUT=y || INPUT=SND | ||
820 | help | 825 | help |
821 | Say Y here to include support for sound cards based on the | 826 | Say Y here to include support for sound cards based on the |
822 | Asus AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, | 827 | Asus AV66/AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, DS, |
823 | Essence ST (Deluxe), and Essence STX. | 828 | Essence ST (Deluxe), and Essence STX. |
824 | Support for the DS is experimental. | 829 | Support for the HDAV1.3 (Deluxe) is incomplete; for the |
825 | Support for the HDAV1.3 (Deluxe) is very experimental. | 830 | HDAV1.3 Slim and Xense, missing. |
826 | 831 | ||
827 | To compile this driver as a module, choose M here: the module | 832 | To compile this driver as a module, choose M here: the module |
828 | will be called snd-virtuoso. | 833 | will be called snd-virtuoso. |
diff --git a/sound/pci/au88x0/au88x0_mixer.c b/sound/pci/au88x0/au88x0_mixer.c index c92f493d341e..557c782ae4fc 100644 --- a/sound/pci/au88x0/au88x0_mixer.c +++ b/sound/pci/au88x0/au88x0_mixer.c | |||
@@ -23,7 +23,7 @@ static int __devinit snd_vortex_mixer(vortex_t * vortex) | |||
23 | if ((err = snd_ac97_bus(vortex->card, 0, &ops, NULL, &pbus)) < 0) | 23 | if ((err = snd_ac97_bus(vortex->card, 0, &ops, NULL, &pbus)) < 0) |
24 | return err; | 24 | return err; |
25 | memset(&ac97, 0, sizeof(ac97)); | 25 | memset(&ac97, 0, sizeof(ac97)); |
26 | // Intialize AC97 codec stuff. | 26 | // Initialize AC97 codec stuff. |
27 | ac97.private_data = vortex; | 27 | ac97.private_data = vortex; |
28 | ac97.scaps = AC97_SCAP_NO_SPDIF; | 28 | ac97.scaps = AC97_SCAP_NO_SPDIF; |
29 | err = snd_ac97_mixer(pbus, &ac97, &vortex->codec); | 29 | err = snd_ac97_mixer(pbus, &ac97, &vortex->codec); |
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h index 14b8d9a91aae..f19c11077255 100644 --- a/sound/pci/ca0106/ca0106.h +++ b/sound/pci/ca0106/ca0106.h | |||
@@ -670,8 +670,9 @@ struct snd_ca0106_details { | |||
670 | gpio_type = 2 -> shared side-out/line-in. */ | 670 | gpio_type = 2 -> shared side-out/line-in. */ |
671 | int i2c_adc; /* with i2c_adc=1, the driver adds some capture volume | 671 | int i2c_adc; /* with i2c_adc=1, the driver adds some capture volume |
672 | controls, phone, mic, line-in and aux. */ | 672 | controls, phone, mic, line-in and aux. */ |
673 | int spi_dac; /* spi_dac=1 adds the mute switch for each analog | 673 | u16 spi_dac; /* spi_dac = 0 -> no spi interface for DACs |
674 | output, front, rear, etc. */ | 674 | spi_dac = 0x<front><rear><center-lfe><side> |
675 | -> specifies DAC id for each channel pair. */ | ||
675 | }; | 676 | }; |
676 | 677 | ||
677 | // definition of the chip-specific record | 678 | // definition of the chip-specific record |
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 0a3d3d6e77b4..d2d12c08f937 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c | |||
@@ -227,7 +227,7 @@ static struct snd_ca0106_details ca0106_chip_details[] = { | |||
227 | .name = "Audigy SE [SB0570]", | 227 | .name = "Audigy SE [SB0570]", |
228 | .gpio_type = 1, | 228 | .gpio_type = 1, |
229 | .i2c_adc = 1, | 229 | .i2c_adc = 1, |
230 | .spi_dac = 1 } , | 230 | .spi_dac = 0x4021 } , |
231 | /* New Audigy LS. Has a different DAC. */ | 231 | /* New Audigy LS. Has a different DAC. */ |
232 | /* SB0570: | 232 | /* SB0570: |
233 | * CTRL:CA0106-DAT | 233 | * CTRL:CA0106-DAT |
@@ -238,7 +238,17 @@ static struct snd_ca0106_details ca0106_chip_details[] = { | |||
238 | .name = "Audigy SE OEM [SB0570a]", | 238 | .name = "Audigy SE OEM [SB0570a]", |
239 | .gpio_type = 1, | 239 | .gpio_type = 1, |
240 | .i2c_adc = 1, | 240 | .i2c_adc = 1, |
241 | .spi_dac = 1 } , | 241 | .spi_dac = 0x4021 } , |
242 | /* Sound Blaster 5.1vx | ||
243 | * Tested: Playback on front, rear, center/lfe speakers | ||
244 | * Not-Tested: Capture | ||
245 | */ | ||
246 | { .serial = 0x10041102, | ||
247 | .name = "Sound Blaster 5.1vx [SB1070]", | ||
248 | .gpio_type = 1, | ||
249 | .i2c_adc = 0, | ||
250 | .spi_dac = 0x0124 | ||
251 | } , | ||
242 | /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */ | 252 | /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */ |
243 | /* SB0438 | 253 | /* SB0438 |
244 | * CTRL:CA0106-DAT | 254 | * CTRL:CA0106-DAT |
@@ -254,7 +264,7 @@ static struct snd_ca0106_details ca0106_chip_details[] = { | |||
254 | .name = "MSI K8N Diamond MB", | 264 | .name = "MSI K8N Diamond MB", |
255 | .gpio_type = 2, | 265 | .gpio_type = 2, |
256 | .i2c_adc = 1, | 266 | .i2c_adc = 1, |
257 | .spi_dac = 1 } , | 267 | .spi_dac = 0x4021 } , |
258 | /* Giga-byte GA-G1975X mobo | 268 | /* Giga-byte GA-G1975X mobo |
259 | * Novell bnc#395807 | 269 | * Novell bnc#395807 |
260 | */ | 270 | */ |
@@ -483,16 +493,18 @@ static void snd_ca0106_pcm_free_substream(struct snd_pcm_runtime *runtime) | |||
483 | } | 493 | } |
484 | 494 | ||
485 | static const int spi_dacd_reg[] = { | 495 | static const int spi_dacd_reg[] = { |
486 | [PCM_FRONT_CHANNEL] = SPI_DACD4_REG, | 496 | SPI_DACD0_REG, |
487 | [PCM_REAR_CHANNEL] = SPI_DACD0_REG, | 497 | SPI_DACD1_REG, |
488 | [PCM_CENTER_LFE_CHANNEL]= SPI_DACD2_REG, | 498 | SPI_DACD2_REG, |
489 | [PCM_UNKNOWN_CHANNEL] = SPI_DACD1_REG, | 499 | 0, |
500 | SPI_DACD4_REG, | ||
490 | }; | 501 | }; |
491 | static const int spi_dacd_bit[] = { | 502 | static const int spi_dacd_bit[] = { |
492 | [PCM_FRONT_CHANNEL] = SPI_DACD4_BIT, | 503 | SPI_DACD0_BIT, |
493 | [PCM_REAR_CHANNEL] = SPI_DACD0_BIT, | 504 | SPI_DACD1_BIT, |
494 | [PCM_CENTER_LFE_CHANNEL]= SPI_DACD2_BIT, | 505 | SPI_DACD2_BIT, |
495 | [PCM_UNKNOWN_CHANNEL] = SPI_DACD1_BIT, | 506 | 0, |
507 | SPI_DACD4_BIT, | ||
496 | }; | 508 | }; |
497 | 509 | ||
498 | static void restore_spdif_bits(struct snd_ca0106 *chip, int idx) | 510 | static void restore_spdif_bits(struct snd_ca0106 *chip, int idx) |
@@ -504,6 +516,45 @@ static void restore_spdif_bits(struct snd_ca0106 *chip, int idx) | |||
504 | } | 516 | } |
505 | } | 517 | } |
506 | 518 | ||
519 | static int snd_ca0106_channel_dac(struct snd_ca0106_details *details, | ||
520 | int channel_id) | ||
521 | { | ||
522 | switch (channel_id) { | ||
523 | case PCM_FRONT_CHANNEL: | ||
524 | return (details->spi_dac & 0xf000) >> (4 * 3); | ||
525 | case PCM_REAR_CHANNEL: | ||
526 | return (details->spi_dac & 0x0f00) >> (4 * 2); | ||
527 | case PCM_CENTER_LFE_CHANNEL: | ||
528 | return (details->spi_dac & 0x00f0) >> (4 * 1); | ||
529 | case PCM_UNKNOWN_CHANNEL: | ||
530 | return (details->spi_dac & 0x000f) >> (4 * 0); | ||
531 | default: | ||
532 | snd_printk(KERN_DEBUG "ca0106: unknown channel_id %d\n", | ||
533 | channel_id); | ||
534 | } | ||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | static int snd_ca0106_pcm_power_dac(struct snd_ca0106 *chip, int channel_id, | ||
539 | int power) | ||
540 | { | ||
541 | if (chip->details->spi_dac) { | ||
542 | const int dac = snd_ca0106_channel_dac(chip->details, | ||
543 | channel_id); | ||
544 | const int reg = spi_dacd_reg[dac]; | ||
545 | const int bit = spi_dacd_bit[dac]; | ||
546 | |||
547 | if (power) | ||
548 | /* Power up */ | ||
549 | chip->spi_dac_reg[reg] &= ~bit; | ||
550 | else | ||
551 | /* Power down */ | ||
552 | chip->spi_dac_reg[reg] |= bit; | ||
553 | return snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]); | ||
554 | } | ||
555 | return 0; | ||
556 | } | ||
557 | |||
507 | /* open_playback callback */ | 558 | /* open_playback callback */ |
508 | static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream, | 559 | static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream, |
509 | int channel_id) | 560 | int channel_id) |
@@ -543,12 +594,9 @@ static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substr | |||
543 | return err; | 594 | return err; |
544 | snd_pcm_set_sync(substream); | 595 | snd_pcm_set_sync(substream); |
545 | 596 | ||
546 | if (chip->details->spi_dac && channel_id != PCM_FRONT_CHANNEL) { | 597 | /* Front channel dac should already be on */ |
547 | const int reg = spi_dacd_reg[channel_id]; | 598 | if (channel_id != PCM_FRONT_CHANNEL) { |
548 | 599 | err = snd_ca0106_pcm_power_dac(chip, channel_id, 1); | |
549 | /* Power up dac */ | ||
550 | chip->spi_dac_reg[reg] &= ~spi_dacd_bit[channel_id]; | ||
551 | err = snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]); | ||
552 | if (err < 0) | 600 | if (err < 0) |
553 | return err; | 601 | return err; |
554 | } | 602 | } |
@@ -568,13 +616,14 @@ static int snd_ca0106_pcm_close_playback(struct snd_pcm_substream *substream) | |||
568 | 616 | ||
569 | restore_spdif_bits(chip, epcm->channel_id); | 617 | restore_spdif_bits(chip, epcm->channel_id); |
570 | 618 | ||
571 | if (chip->details->spi_dac && epcm->channel_id != PCM_FRONT_CHANNEL) { | 619 | /* Front channel dac should stay on */ |
572 | const int reg = spi_dacd_reg[epcm->channel_id]; | 620 | if (epcm->channel_id != PCM_FRONT_CHANNEL) { |
573 | 621 | int err; | |
574 | /* Power down DAC */ | 622 | err = snd_ca0106_pcm_power_dac(chip, epcm->channel_id, 0); |
575 | chip->spi_dac_reg[reg] |= spi_dacd_bit[epcm->channel_id]; | 623 | if (err < 0) |
576 | snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]); | 624 | return err; |
577 | } | 625 | } |
626 | |||
578 | /* FIXME: maybe zero others */ | 627 | /* FIXME: maybe zero others */ |
579 | return 0; | 628 | return 0; |
580 | } | 629 | } |
@@ -1002,29 +1051,27 @@ snd_ca0106_pcm_pointer_playback(struct snd_pcm_substream *substream) | |||
1002 | struct snd_ca0106 *emu = snd_pcm_substream_chip(substream); | 1051 | struct snd_ca0106 *emu = snd_pcm_substream_chip(substream); |
1003 | struct snd_pcm_runtime *runtime = substream->runtime; | 1052 | struct snd_pcm_runtime *runtime = substream->runtime; |
1004 | struct snd_ca0106_pcm *epcm = runtime->private_data; | 1053 | struct snd_ca0106_pcm *epcm = runtime->private_data; |
1005 | snd_pcm_uframes_t ptr, ptr1, ptr2,ptr3,ptr4 = 0; | 1054 | unsigned int ptr, prev_ptr; |
1006 | int channel = epcm->channel_id; | 1055 | int channel = epcm->channel_id; |
1056 | int timeout = 10; | ||
1007 | 1057 | ||
1008 | if (!epcm->running) | 1058 | if (!epcm->running) |
1009 | return 0; | 1059 | return 0; |
1010 | 1060 | ||
1011 | ptr3 = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel); | 1061 | prev_ptr = -1; |
1012 | ptr1 = snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel); | 1062 | do { |
1013 | ptr4 = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel); | 1063 | ptr = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel); |
1014 | if (ptr3 != ptr4) ptr1 = snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel); | 1064 | ptr = (ptr >> 3) * runtime->period_size; |
1015 | ptr2 = bytes_to_frames(runtime, ptr1); | 1065 | ptr += bytes_to_frames(runtime, |
1016 | ptr2+= (ptr4 >> 3) * runtime->period_size; | 1066 | snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel)); |
1017 | ptr=ptr2; | 1067 | if (ptr >= runtime->buffer_size) |
1018 | if (ptr >= runtime->buffer_size) | 1068 | ptr -= runtime->buffer_size; |
1019 | ptr -= runtime->buffer_size; | 1069 | if (prev_ptr == ptr) |
1020 | /* | 1070 | return ptr; |
1021 | printk(KERN_DEBUG "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, " | 1071 | prev_ptr = ptr; |
1022 | "buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", | 1072 | } while (--timeout); |
1023 | ptr1, ptr2, ptr, (int)runtime->buffer_size, | 1073 | snd_printk(KERN_WARNING "ca0106: unstable DMA pointer!\n"); |
1024 | (int)runtime->period_size, (int)runtime->frame_bits, | 1074 | return 0; |
1025 | (int)runtime->rate); | ||
1026 | */ | ||
1027 | return ptr; | ||
1028 | } | 1075 | } |
1029 | 1076 | ||
1030 | /* pointer_capture callback */ | 1077 | /* pointer_capture callback */ |
@@ -1362,7 +1409,7 @@ static unsigned int spi_dac_init[] = { | |||
1362 | SPI_REG(12, 0x00), | 1409 | SPI_REG(12, 0x00), |
1363 | SPI_REG(SPI_LDA4_REG, SPI_DA_BIT_0dB), | 1410 | SPI_REG(SPI_LDA4_REG, SPI_DA_BIT_0dB), |
1364 | SPI_REG(SPI_RDA4_REG, SPI_DA_BIT_0dB | SPI_DA_BIT_UPDATE), | 1411 | SPI_REG(SPI_RDA4_REG, SPI_DA_BIT_0dB | SPI_DA_BIT_UPDATE), |
1365 | SPI_REG(SPI_DACD4_REG, 0x00), | 1412 | SPI_REG(SPI_DACD4_REG, SPI_DACD4_BIT), |
1366 | }; | 1413 | }; |
1367 | 1414 | ||
1368 | static unsigned int i2c_adc_init[][2] = { | 1415 | static unsigned int i2c_adc_init[][2] = { |
@@ -1541,7 +1588,7 @@ static void ca0106_init_chip(struct snd_ca0106 *chip, int resume) | |||
1541 | /* snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); */ | 1588 | /* snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); */ |
1542 | } | 1589 | } |
1543 | 1590 | ||
1544 | if (chip->details->spi_dac == 1) { | 1591 | if (chip->details->spi_dac) { |
1545 | /* The SB0570 use SPI to control DAC. */ | 1592 | /* The SB0570 use SPI to control DAC. */ |
1546 | int size, n; | 1593 | int size, n; |
1547 | 1594 | ||
@@ -1553,6 +1600,9 @@ static void ca0106_init_chip(struct snd_ca0106 *chip, int resume) | |||
1553 | if (reg < ARRAY_SIZE(chip->spi_dac_reg)) | 1600 | if (reg < ARRAY_SIZE(chip->spi_dac_reg)) |
1554 | chip->spi_dac_reg[reg] = spi_dac_init[n]; | 1601 | chip->spi_dac_reg[reg] = spi_dac_init[n]; |
1555 | } | 1602 | } |
1603 | |||
1604 | /* Enable front dac only */ | ||
1605 | snd_ca0106_pcm_power_dac(chip, PCM_FRONT_CHANNEL, 1); | ||
1556 | } | 1606 | } |
1557 | } | 1607 | } |
1558 | 1608 | ||
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index 85fd315d9999..630aa4998189 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c | |||
@@ -676,28 +676,65 @@ static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] __devinitdata = | |||
676 | I2C_VOLUME("Aux Capture Volume", 3), | 676 | I2C_VOLUME("Aux Capture Volume", 3), |
677 | }; | 677 | }; |
678 | 678 | ||
679 | #define SPI_SWITCH(xname,reg,bit) \ | 679 | static const int spi_dmute_reg[] = { |
680 | { \ | 680 | SPI_DMUTE0_REG, |
681 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 681 | SPI_DMUTE1_REG, |
682 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ | 682 | SPI_DMUTE2_REG, |
683 | .info = spi_mute_info, \ | 683 | 0, |
684 | .get = spi_mute_get, \ | 684 | SPI_DMUTE4_REG, |
685 | .put = spi_mute_put, \ | 685 | }; |
686 | .private_value = (reg<<SPI_REG_SHIFT) | (bit) \ | 686 | static const int spi_dmute_bit[] = { |
687 | } | 687 | SPI_DMUTE0_BIT, |
688 | 688 | SPI_DMUTE1_BIT, | |
689 | static struct snd_kcontrol_new snd_ca0106_volume_spi_dac_ctls[] | 689 | SPI_DMUTE2_BIT, |
690 | __devinitdata = { | 690 | 0, |
691 | SPI_SWITCH("Analog Front Playback Switch", | 691 | SPI_DMUTE4_BIT, |
692 | SPI_DMUTE4_REG, SPI_DMUTE4_BIT), | ||
693 | SPI_SWITCH("Analog Rear Playback Switch", | ||
694 | SPI_DMUTE0_REG, SPI_DMUTE0_BIT), | ||
695 | SPI_SWITCH("Analog Center/LFE Playback Switch", | ||
696 | SPI_DMUTE2_REG, SPI_DMUTE2_BIT), | ||
697 | SPI_SWITCH("Analog Side Playback Switch", | ||
698 | SPI_DMUTE1_REG, SPI_DMUTE1_BIT), | ||
699 | }; | 692 | }; |
700 | 693 | ||
694 | static struct snd_kcontrol_new __devinit | ||
695 | snd_ca0106_volume_spi_dac_ctl(struct snd_ca0106_details *details, | ||
696 | int channel_id) | ||
697 | { | ||
698 | struct snd_kcontrol_new spi_switch = {0}; | ||
699 | int reg, bit; | ||
700 | int dac_id; | ||
701 | |||
702 | spi_switch.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
703 | spi_switch.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; | ||
704 | spi_switch.info = spi_mute_info; | ||
705 | spi_switch.get = spi_mute_get; | ||
706 | spi_switch.put = spi_mute_put; | ||
707 | |||
708 | switch (channel_id) { | ||
709 | case PCM_FRONT_CHANNEL: | ||
710 | spi_switch.name = "Analog Front Playback Switch"; | ||
711 | dac_id = (details->spi_dac & 0xf000) >> (4 * 3); | ||
712 | break; | ||
713 | case PCM_REAR_CHANNEL: | ||
714 | spi_switch.name = "Analog Rear Playback Switch"; | ||
715 | dac_id = (details->spi_dac & 0x0f00) >> (4 * 2); | ||
716 | break; | ||
717 | case PCM_CENTER_LFE_CHANNEL: | ||
718 | spi_switch.name = "Analog Center/LFE Playback Switch"; | ||
719 | dac_id = (details->spi_dac & 0x00f0) >> (4 * 1); | ||
720 | break; | ||
721 | case PCM_UNKNOWN_CHANNEL: | ||
722 | spi_switch.name = "Analog Side Playback Switch"; | ||
723 | dac_id = (details->spi_dac & 0x000f) >> (4 * 0); | ||
724 | break; | ||
725 | default: | ||
726 | /* Unused channel */ | ||
727 | spi_switch.name = NULL; | ||
728 | dac_id = 0; | ||
729 | } | ||
730 | reg = spi_dmute_reg[dac_id]; | ||
731 | bit = spi_dmute_bit[dac_id]; | ||
732 | |||
733 | spi_switch.private_value = (reg << SPI_REG_SHIFT) | bit; | ||
734 | |||
735 | return spi_switch; | ||
736 | } | ||
737 | |||
701 | static int __devinit remove_ctl(struct snd_card *card, const char *name) | 738 | static int __devinit remove_ctl(struct snd_card *card, const char *name) |
702 | { | 739 | { |
703 | struct snd_ctl_elem_id id; | 740 | struct snd_ctl_elem_id id; |
@@ -832,8 +869,18 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu) | |||
832 | if (err < 0) | 869 | if (err < 0) |
833 | return err; | 870 | return err; |
834 | } | 871 | } |
835 | if (emu->details->spi_dac == 1) | 872 | if (emu->details->spi_dac) { |
836 | ADD_CTLS(emu, snd_ca0106_volume_spi_dac_ctls); | 873 | int i; |
874 | for (i = 0;; i++) { | ||
875 | struct snd_kcontrol_new ctl; | ||
876 | ctl = snd_ca0106_volume_spi_dac_ctl(emu->details, i); | ||
877 | if (!ctl.name) | ||
878 | break; | ||
879 | err = snd_ctl_add(card, snd_ctl_new1(&ctl, emu)); | ||
880 | if (err < 0) | ||
881 | return err; | ||
882 | } | ||
883 | } | ||
837 | 884 | ||
838 | /* Create virtual master controls */ | 885 | /* Create virtual master controls */ |
839 | vmaster = snd_ctl_make_virtual_master("Master Playback Volume", | 886 | vmaster = snd_ctl_make_virtual_master("Master Playback Volume", |
@@ -845,7 +892,7 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu) | |||
845 | return err; | 892 | return err; |
846 | add_slaves(card, vmaster, slave_vols); | 893 | add_slaves(card, vmaster, slave_vols); |
847 | 894 | ||
848 | if (emu->details->spi_dac == 1) { | 895 | if (emu->details->spi_dac) { |
849 | vmaster = snd_ctl_make_virtual_master("Master Playback Switch", | 896 | vmaster = snd_ctl_make_virtual_master("Master Playback Switch", |
850 | NULL); | 897 | NULL); |
851 | if (!vmaster) | 898 | if (!vmaster) |
diff --git a/sound/pci/emu10k1/emumpu401.c b/sound/pci/emu10k1/emumpu401.c index 8578c70c61f2..bab564824efe 100644 --- a/sound/pci/emu10k1/emumpu401.c +++ b/sound/pci/emu10k1/emumpu401.c | |||
@@ -321,7 +321,7 @@ static struct snd_rawmidi_ops snd_emu10k1_midi_input = | |||
321 | 321 | ||
322 | static void snd_emu10k1_midi_free(struct snd_rawmidi *rmidi) | 322 | static void snd_emu10k1_midi_free(struct snd_rawmidi *rmidi) |
323 | { | 323 | { |
324 | struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)rmidi->private_data; | 324 | struct snd_emu10k1_midi *midi = rmidi->private_data; |
325 | midi->interrupt = NULL; | 325 | midi->interrupt = NULL; |
326 | midi->rmidi = NULL; | 326 | midi->rmidi = NULL; |
327 | } | 327 | } |
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index 9194c3c1d04a..0ea5cc60ac78 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig | |||
@@ -119,47 +119,20 @@ config SND_HDA_CODEC_VIA | |||
119 | snd-hda-codec-via. | 119 | snd-hda-codec-via. |
120 | This module is automatically loaded at probing. | 120 | This module is automatically loaded at probing. |
121 | 121 | ||
122 | config SND_HDA_CODEC_ATIHDMI | 122 | config SND_HDA_CODEC_HDMI |
123 | bool "Build ATI HDMI HD-audio codec support" | 123 | bool "Build HDMI/DisplayPort HD-audio codec support" |
124 | default y | ||
125 | help | ||
126 | Say Y here to include ATI HDMI HD-audio codec support in | ||
127 | snd-hda-intel driver, such as ATI RS600 HDMI. | ||
128 | |||
129 | When the HD-audio driver is built as a module, the codec | ||
130 | support code is also built as another module, | ||
131 | snd-hda-codec-atihdmi. | ||
132 | This module is automatically loaded at probing. | ||
133 | |||
134 | config SND_HDA_CODEC_NVHDMI | ||
135 | bool "Build NVIDIA HDMI HD-audio codec support" | ||
136 | default y | ||
137 | help | ||
138 | Say Y here to include NVIDIA HDMI HD-audio codec support in | ||
139 | snd-hda-intel driver, such as NVIDIA MCP78 HDMI. | ||
140 | |||
141 | When the HD-audio driver is built as a module, the codec | ||
142 | support code is also built as another module, | ||
143 | snd-hda-codec-nvhdmi. | ||
144 | This module is automatically loaded at probing. | ||
145 | |||
146 | config SND_HDA_CODEC_INTELHDMI | ||
147 | bool "Build INTEL HDMI HD-audio codec support" | ||
148 | select SND_DYNAMIC_MINORS | 124 | select SND_DYNAMIC_MINORS |
149 | default y | 125 | default y |
150 | help | 126 | help |
151 | Say Y here to include INTEL HDMI HD-audio codec support in | 127 | Say Y here to include HDMI and DisplayPort HD-audio codec |
152 | snd-hda-intel driver, such as Eaglelake integrated HDMI. | 128 | support in snd-hda-intel driver. This includes all AMD/ATI, |
129 | Intel and Nvidia HDMI/DisplayPort codecs. | ||
153 | 130 | ||
154 | When the HD-audio driver is built as a module, the codec | 131 | When the HD-audio driver is built as a module, the codec |
155 | support code is also built as another module, | 132 | support code is also built as another module, |
156 | snd-hda-codec-intelhdmi. | 133 | snd-hda-codec-hdmi. |
157 | This module is automatically loaded at probing. | 134 | This module is automatically loaded at probing. |
158 | 135 | ||
159 | config SND_HDA_ELD | ||
160 | def_bool y | ||
161 | depends on SND_HDA_CODEC_INTELHDMI || SND_HDA_CODEC_NVHDMI | ||
162 | |||
163 | config SND_HDA_CODEC_CIRRUS | 136 | config SND_HDA_CODEC_CIRRUS |
164 | bool "Build Cirrus Logic codec support" | 137 | bool "Build Cirrus Logic codec support" |
165 | depends on SND_HDA_INTEL | 138 | depends on SND_HDA_INTEL |
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index 24bc195b02da..17ef3658f34b 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile | |||
@@ -3,7 +3,6 @@ snd-hda-intel-objs := hda_intel.o | |||
3 | snd-hda-codec-y := hda_codec.o | 3 | snd-hda-codec-y := hda_codec.o |
4 | snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o | 4 | snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o |
5 | snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o | 5 | snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o |
6 | snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o | ||
7 | snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o | 6 | snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o |
8 | snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o | 7 | snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o |
9 | 8 | ||
@@ -12,13 +11,11 @@ snd-hda-codec-cmedia-objs := patch_cmedia.o | |||
12 | snd-hda-codec-analog-objs := patch_analog.o | 11 | snd-hda-codec-analog-objs := patch_analog.o |
13 | snd-hda-codec-idt-objs := patch_sigmatel.o | 12 | snd-hda-codec-idt-objs := patch_sigmatel.o |
14 | snd-hda-codec-si3054-objs := patch_si3054.o | 13 | snd-hda-codec-si3054-objs := patch_si3054.o |
15 | snd-hda-codec-atihdmi-objs := patch_atihdmi.o | ||
16 | snd-hda-codec-cirrus-objs := patch_cirrus.o | 14 | snd-hda-codec-cirrus-objs := patch_cirrus.o |
17 | snd-hda-codec-ca0110-objs := patch_ca0110.o | 15 | snd-hda-codec-ca0110-objs := patch_ca0110.o |
18 | snd-hda-codec-conexant-objs := patch_conexant.o | 16 | snd-hda-codec-conexant-objs := patch_conexant.o |
19 | snd-hda-codec-via-objs := patch_via.o | 17 | snd-hda-codec-via-objs := patch_via.o |
20 | snd-hda-codec-nvhdmi-objs := patch_nvhdmi.o | 18 | snd-hda-codec-hdmi-objs := patch_hdmi.o hda_eld.o |
21 | snd-hda-codec-intelhdmi-objs := patch_intelhdmi.o | ||
22 | 19 | ||
23 | # common driver | 20 | # common driver |
24 | obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o | 21 | obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o |
@@ -39,9 +36,6 @@ endif | |||
39 | ifdef CONFIG_SND_HDA_CODEC_SI3054 | 36 | ifdef CONFIG_SND_HDA_CODEC_SI3054 |
40 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-si3054.o | 37 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-si3054.o |
41 | endif | 38 | endif |
42 | ifdef CONFIG_SND_HDA_CODEC_ATIHDMI | ||
43 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-atihdmi.o | ||
44 | endif | ||
45 | ifdef CONFIG_SND_HDA_CODEC_CIRRUS | 39 | ifdef CONFIG_SND_HDA_CODEC_CIRRUS |
46 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-cirrus.o | 40 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-cirrus.o |
47 | endif | 41 | endif |
@@ -54,11 +48,8 @@ endif | |||
54 | ifdef CONFIG_SND_HDA_CODEC_VIA | 48 | ifdef CONFIG_SND_HDA_CODEC_VIA |
55 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-via.o | 49 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-via.o |
56 | endif | 50 | endif |
57 | ifdef CONFIG_SND_HDA_CODEC_NVHDMI | 51 | ifdef CONFIG_SND_HDA_CODEC_HDMI |
58 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-nvhdmi.o | 52 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-hdmi.o |
59 | endif | ||
60 | ifdef CONFIG_SND_HDA_CODEC_INTELHDMI | ||
61 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-intelhdmi.o | ||
62 | endif | 53 | endif |
63 | 54 | ||
64 | # this must be the last entry after codec drivers; | 55 | # this must be the last entry after codec drivers; |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 14829210ef0b..644e3f14f8ca 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -1216,6 +1216,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, | |||
1216 | struct hda_codec *c; | 1216 | struct hda_codec *c; |
1217 | struct hda_cvt_setup *p; | 1217 | struct hda_cvt_setup *p; |
1218 | unsigned int oldval, newval; | 1218 | unsigned int oldval, newval; |
1219 | int type; | ||
1219 | int i; | 1220 | int i; |
1220 | 1221 | ||
1221 | if (!nid) | 1222 | if (!nid) |
@@ -1254,10 +1255,12 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, | |||
1254 | p->dirty = 0; | 1255 | p->dirty = 0; |
1255 | 1256 | ||
1256 | /* make other inactive cvts with the same stream-tag dirty */ | 1257 | /* make other inactive cvts with the same stream-tag dirty */ |
1258 | type = get_wcaps_type(get_wcaps(codec, nid)); | ||
1257 | list_for_each_entry(c, &codec->bus->codec_list, list) { | 1259 | list_for_each_entry(c, &codec->bus->codec_list, list) { |
1258 | for (i = 0; i < c->cvt_setups.used; i++) { | 1260 | for (i = 0; i < c->cvt_setups.used; i++) { |
1259 | p = snd_array_elem(&c->cvt_setups, i); | 1261 | p = snd_array_elem(&c->cvt_setups, i); |
1260 | if (!p->active && p->stream_tag == stream_tag) | 1262 | if (!p->active && p->stream_tag == stream_tag && |
1263 | get_wcaps_type(get_wcaps(codec, p->nid)) == type) | ||
1261 | p->dirty = 1; | 1264 | p->dirty = 1; |
1262 | } | 1265 | } |
1263 | } | 1266 | } |
@@ -1281,6 +1284,9 @@ void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid, | |||
1281 | if (!nid) | 1284 | if (!nid) |
1282 | return; | 1285 | return; |
1283 | 1286 | ||
1287 | if (codec->no_sticky_stream) | ||
1288 | do_now = 1; | ||
1289 | |||
1284 | snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid); | 1290 | snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid); |
1285 | p = get_hda_cvt_setup(codec, nid); | 1291 | p = get_hda_cvt_setup(codec, nid); |
1286 | if (p) { | 1292 | if (p) { |
@@ -1831,6 +1837,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, | |||
1831 | hda_nid_t nid = get_amp_nid(kcontrol); | 1837 | hda_nid_t nid = get_amp_nid(kcontrol); |
1832 | int dir = get_amp_direction(kcontrol); | 1838 | int dir = get_amp_direction(kcontrol); |
1833 | unsigned int ofs = get_amp_offset(kcontrol); | 1839 | unsigned int ofs = get_amp_offset(kcontrol); |
1840 | bool min_mute = get_amp_min_mute(kcontrol); | ||
1834 | u32 caps, val1, val2; | 1841 | u32 caps, val1, val2; |
1835 | 1842 | ||
1836 | if (size < 4 * sizeof(unsigned int)) | 1843 | if (size < 4 * sizeof(unsigned int)) |
@@ -1841,6 +1848,8 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, | |||
1841 | val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); | 1848 | val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); |
1842 | val1 += ofs; | 1849 | val1 += ofs; |
1843 | val1 = ((int)val1) * ((int)val2); | 1850 | val1 = ((int)val1) * ((int)val2); |
1851 | if (min_mute) | ||
1852 | val2 |= TLV_DB_SCALE_MUTE; | ||
1844 | if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) | 1853 | if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) |
1845 | return -EFAULT; | 1854 | return -EFAULT; |
1846 | if (put_user(2 * sizeof(unsigned int), _tlv + 1)) | 1855 | if (put_user(2 * sizeof(unsigned int), _tlv + 1)) |
@@ -2228,10 +2237,7 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, | |||
2228 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, | 2237 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, |
2229 | HDA_AMP_MUTE, | 2238 | HDA_AMP_MUTE, |
2230 | *valp ? 0 : HDA_AMP_MUTE); | 2239 | *valp ? 0 : HDA_AMP_MUTE); |
2231 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 2240 | hda_call_check_power_status(codec, nid); |
2232 | if (codec->patch_ops.check_power_status) | ||
2233 | codec->patch_ops.check_power_status(codec, nid); | ||
2234 | #endif | ||
2235 | snd_hda_power_down(codec); | 2241 | snd_hda_power_down(codec); |
2236 | return change; | 2242 | return change; |
2237 | } | 2243 | } |
@@ -4372,6 +4378,34 @@ static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences, | |||
4372 | } | 4378 | } |
4373 | 4379 | ||
4374 | 4380 | ||
4381 | /* add the found input-pin to the cfg->inputs[] table */ | ||
4382 | static void add_auto_cfg_input_pin(struct auto_pin_cfg *cfg, hda_nid_t nid, | ||
4383 | int type) | ||
4384 | { | ||
4385 | if (cfg->num_inputs < AUTO_CFG_MAX_INS) { | ||
4386 | cfg->inputs[cfg->num_inputs].pin = nid; | ||
4387 | cfg->inputs[cfg->num_inputs].type = type; | ||
4388 | cfg->num_inputs++; | ||
4389 | } | ||
4390 | } | ||
4391 | |||
4392 | /* sort inputs in the order of AUTO_PIN_* type */ | ||
4393 | static void sort_autocfg_input_pins(struct auto_pin_cfg *cfg) | ||
4394 | { | ||
4395 | int i, j; | ||
4396 | |||
4397 | for (i = 0; i < cfg->num_inputs; i++) { | ||
4398 | for (j = i + 1; j < cfg->num_inputs; j++) { | ||
4399 | if (cfg->inputs[i].type > cfg->inputs[j].type) { | ||
4400 | struct auto_pin_cfg_item tmp; | ||
4401 | tmp = cfg->inputs[i]; | ||
4402 | cfg->inputs[i] = cfg->inputs[j]; | ||
4403 | cfg->inputs[j] = tmp; | ||
4404 | } | ||
4405 | } | ||
4406 | } | ||
4407 | } | ||
4408 | |||
4375 | /* | 4409 | /* |
4376 | * Parse all pin widgets and store the useful pin nids to cfg | 4410 | * Parse all pin widgets and store the useful pin nids to cfg |
4377 | * | 4411 | * |
@@ -4385,7 +4419,7 @@ static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences, | |||
4385 | * output, i.e. to line_out_pins[0]. So, line_outs is always positive | 4419 | * output, i.e. to line_out_pins[0]. So, line_outs is always positive |
4386 | * if any analog output exists. | 4420 | * if any analog output exists. |
4387 | * | 4421 | * |
4388 | * The analog input pins are assigned to input_pins array. | 4422 | * The analog input pins are assigned to inputs array. |
4389 | * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, | 4423 | * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, |
4390 | * respectively. | 4424 | * respectively. |
4391 | */ | 4425 | */ |
@@ -4398,6 +4432,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4398 | short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)]; | 4432 | short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)]; |
4399 | short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)]; | 4433 | short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)]; |
4400 | short sequences_hp[ARRAY_SIZE(cfg->hp_pins)]; | 4434 | short sequences_hp[ARRAY_SIZE(cfg->hp_pins)]; |
4435 | int i; | ||
4401 | 4436 | ||
4402 | memset(cfg, 0, sizeof(*cfg)); | 4437 | memset(cfg, 0, sizeof(*cfg)); |
4403 | 4438 | ||
@@ -4468,33 +4503,17 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4468 | sequences_hp[cfg->hp_outs] = (assoc << 4) | seq; | 4503 | sequences_hp[cfg->hp_outs] = (assoc << 4) | seq; |
4469 | cfg->hp_outs++; | 4504 | cfg->hp_outs++; |
4470 | break; | 4505 | break; |
4471 | case AC_JACK_MIC_IN: { | 4506 | case AC_JACK_MIC_IN: |
4472 | int preferred, alt; | 4507 | add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_MIC); |
4473 | if (loc == AC_JACK_LOC_FRONT || | ||
4474 | (loc & 0x30) == AC_JACK_LOC_INTERNAL) { | ||
4475 | preferred = AUTO_PIN_FRONT_MIC; | ||
4476 | alt = AUTO_PIN_MIC; | ||
4477 | } else { | ||
4478 | preferred = AUTO_PIN_MIC; | ||
4479 | alt = AUTO_PIN_FRONT_MIC; | ||
4480 | } | ||
4481 | if (!cfg->input_pins[preferred]) | ||
4482 | cfg->input_pins[preferred] = nid; | ||
4483 | else if (!cfg->input_pins[alt]) | ||
4484 | cfg->input_pins[alt] = nid; | ||
4485 | break; | 4508 | break; |
4486 | } | ||
4487 | case AC_JACK_LINE_IN: | 4509 | case AC_JACK_LINE_IN: |
4488 | if (loc == AC_JACK_LOC_FRONT) | 4510 | add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_LINE_IN); |
4489 | cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid; | ||
4490 | else | ||
4491 | cfg->input_pins[AUTO_PIN_LINE] = nid; | ||
4492 | break; | 4511 | break; |
4493 | case AC_JACK_CD: | 4512 | case AC_JACK_CD: |
4494 | cfg->input_pins[AUTO_PIN_CD] = nid; | 4513 | add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_CD); |
4495 | break; | 4514 | break; |
4496 | case AC_JACK_AUX: | 4515 | case AC_JACK_AUX: |
4497 | cfg->input_pins[AUTO_PIN_AUX] = nid; | 4516 | add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_AUX); |
4498 | break; | 4517 | break; |
4499 | case AC_JACK_SPDIF_OUT: | 4518 | case AC_JACK_SPDIF_OUT: |
4500 | case AC_JACK_DIG_OTHER_OUT: | 4519 | case AC_JACK_DIG_OTHER_OUT: |
@@ -4539,6 +4558,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4539 | memmove(sequences_hp + i, sequences_hp + i + 1, | 4558 | memmove(sequences_hp + i, sequences_hp + i + 1, |
4540 | sizeof(sequences_hp[0]) * (cfg->hp_outs - i)); | 4559 | sizeof(sequences_hp[0]) * (cfg->hp_outs - i)); |
4541 | } | 4560 | } |
4561 | memset(cfg->hp_pins + cfg->hp_outs, 0, | ||
4562 | sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - cfg->hp_outs)); | ||
4542 | } | 4563 | } |
4543 | 4564 | ||
4544 | /* sort by sequence */ | 4565 | /* sort by sequence */ |
@@ -4549,21 +4570,6 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4549 | sort_pins_by_sequence(cfg->hp_pins, sequences_hp, | 4570 | sort_pins_by_sequence(cfg->hp_pins, sequences_hp, |
4550 | cfg->hp_outs); | 4571 | cfg->hp_outs); |
4551 | 4572 | ||
4552 | /* if we have only one mic, make it AUTO_PIN_MIC */ | ||
4553 | if (!cfg->input_pins[AUTO_PIN_MIC] && | ||
4554 | cfg->input_pins[AUTO_PIN_FRONT_MIC]) { | ||
4555 | cfg->input_pins[AUTO_PIN_MIC] = | ||
4556 | cfg->input_pins[AUTO_PIN_FRONT_MIC]; | ||
4557 | cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0; | ||
4558 | } | ||
4559 | /* ditto for line-in */ | ||
4560 | if (!cfg->input_pins[AUTO_PIN_LINE] && | ||
4561 | cfg->input_pins[AUTO_PIN_FRONT_LINE]) { | ||
4562 | cfg->input_pins[AUTO_PIN_LINE] = | ||
4563 | cfg->input_pins[AUTO_PIN_FRONT_LINE]; | ||
4564 | cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0; | ||
4565 | } | ||
4566 | |||
4567 | /* | 4573 | /* |
4568 | * FIX-UP: if no line-outs are detected, try to use speaker or HP pin | 4574 | * FIX-UP: if no line-outs are detected, try to use speaker or HP pin |
4569 | * as a primary output | 4575 | * as a primary output |
@@ -4602,6 +4608,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4602 | break; | 4608 | break; |
4603 | } | 4609 | } |
4604 | 4610 | ||
4611 | sort_autocfg_input_pins(cfg); | ||
4612 | |||
4605 | /* | 4613 | /* |
4606 | * debug prints of the parsed results | 4614 | * debug prints of the parsed results |
4607 | */ | 4615 | */ |
@@ -4621,14 +4629,13 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4621 | if (cfg->dig_outs) | 4629 | if (cfg->dig_outs) |
4622 | snd_printd(" dig-out=0x%x/0x%x\n", | 4630 | snd_printd(" dig-out=0x%x/0x%x\n", |
4623 | cfg->dig_out_pins[0], cfg->dig_out_pins[1]); | 4631 | cfg->dig_out_pins[0], cfg->dig_out_pins[1]); |
4624 | snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x," | 4632 | snd_printd(" inputs:"); |
4625 | " cd=0x%x, aux=0x%x\n", | 4633 | for (i = 0; i < cfg->num_inputs; i++) { |
4626 | cfg->input_pins[AUTO_PIN_MIC], | 4634 | snd_printdd(" %s=0x%x", |
4627 | cfg->input_pins[AUTO_PIN_FRONT_MIC], | 4635 | hda_get_autocfg_input_label(codec, cfg, i), |
4628 | cfg->input_pins[AUTO_PIN_LINE], | 4636 | cfg->inputs[i].pin); |
4629 | cfg->input_pins[AUTO_PIN_FRONT_LINE], | 4637 | } |
4630 | cfg->input_pins[AUTO_PIN_CD], | 4638 | snd_printd("\n"); |
4631 | cfg->input_pins[AUTO_PIN_AUX]); | ||
4632 | if (cfg->dig_in_pin) | 4639 | if (cfg->dig_in_pin) |
4633 | snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin); | 4640 | snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin); |
4634 | 4641 | ||
@@ -4636,11 +4643,165 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4636 | } | 4643 | } |
4637 | EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config); | 4644 | EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config); |
4638 | 4645 | ||
4639 | /* labels for input pins */ | 4646 | int snd_hda_get_input_pin_attr(unsigned int def_conf) |
4640 | const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = { | 4647 | { |
4641 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux" | 4648 | unsigned int loc = get_defcfg_location(def_conf); |
4642 | }; | 4649 | unsigned int conn = get_defcfg_connect(def_conf); |
4643 | EXPORT_SYMBOL_HDA(auto_pin_cfg_labels); | 4650 | if (conn == AC_JACK_PORT_NONE) |
4651 | return INPUT_PIN_ATTR_UNUSED; | ||
4652 | /* Windows may claim the internal mic to be BOTH, too */ | ||
4653 | if (conn == AC_JACK_PORT_FIXED || conn == AC_JACK_PORT_BOTH) | ||
4654 | return INPUT_PIN_ATTR_INT; | ||
4655 | if ((loc & 0x30) == AC_JACK_LOC_INTERNAL) | ||
4656 | return INPUT_PIN_ATTR_INT; | ||
4657 | if ((loc & 0x30) == AC_JACK_LOC_SEPARATE) | ||
4658 | return INPUT_PIN_ATTR_DOCK; | ||
4659 | if (loc == AC_JACK_LOC_REAR) | ||
4660 | return INPUT_PIN_ATTR_REAR; | ||
4661 | if (loc == AC_JACK_LOC_FRONT) | ||
4662 | return INPUT_PIN_ATTR_FRONT; | ||
4663 | return INPUT_PIN_ATTR_NORMAL; | ||
4664 | } | ||
4665 | EXPORT_SYMBOL_HDA(snd_hda_get_input_pin_attr); | ||
4666 | |||
4667 | /** | ||
4668 | * hda_get_input_pin_label - Give a label for the given input pin | ||
4669 | * | ||
4670 | * When check_location is true, the function checks the pin location | ||
4671 | * for mic and line-in pins, and set an appropriate prefix like "Front", | ||
4672 | * "Rear", "Internal". | ||
4673 | */ | ||
4674 | |||
4675 | const char *hda_get_input_pin_label(struct hda_codec *codec, hda_nid_t pin, | ||
4676 | int check_location) | ||
4677 | { | ||
4678 | unsigned int def_conf; | ||
4679 | static const char *mic_names[] = { | ||
4680 | "Internal Mic", "Dock Mic", "Mic", "Front Mic", "Rear Mic", | ||
4681 | }; | ||
4682 | int attr; | ||
4683 | |||
4684 | def_conf = snd_hda_codec_get_pincfg(codec, pin); | ||
4685 | |||
4686 | switch (get_defcfg_device(def_conf)) { | ||
4687 | case AC_JACK_MIC_IN: | ||
4688 | if (!check_location) | ||
4689 | return "Mic"; | ||
4690 | attr = snd_hda_get_input_pin_attr(def_conf); | ||
4691 | if (!attr) | ||
4692 | return "None"; | ||
4693 | return mic_names[attr - 1]; | ||
4694 | case AC_JACK_LINE_IN: | ||
4695 | if (!check_location) | ||
4696 | return "Line"; | ||
4697 | attr = snd_hda_get_input_pin_attr(def_conf); | ||
4698 | if (!attr) | ||
4699 | return "None"; | ||
4700 | if (attr == INPUT_PIN_ATTR_DOCK) | ||
4701 | return "Dock Line"; | ||
4702 | return "Line"; | ||
4703 | case AC_JACK_AUX: | ||
4704 | return "Aux"; | ||
4705 | case AC_JACK_CD: | ||
4706 | return "CD"; | ||
4707 | case AC_JACK_SPDIF_IN: | ||
4708 | return "SPDIF In"; | ||
4709 | case AC_JACK_DIG_OTHER_IN: | ||
4710 | return "Digital In"; | ||
4711 | default: | ||
4712 | return "Misc"; | ||
4713 | } | ||
4714 | } | ||
4715 | EXPORT_SYMBOL_HDA(hda_get_input_pin_label); | ||
4716 | |||
4717 | /* Check whether the location prefix needs to be added to the label. | ||
4718 | * If all mic-jacks are in the same location (e.g. rear panel), we don't | ||
4719 | * have to put "Front" prefix to each label. In such a case, returns false. | ||
4720 | */ | ||
4721 | static int check_mic_location_need(struct hda_codec *codec, | ||
4722 | const struct auto_pin_cfg *cfg, | ||
4723 | int input) | ||
4724 | { | ||
4725 | unsigned int defc; | ||
4726 | int i, attr, attr2; | ||
4727 | |||
4728 | defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[input].pin); | ||
4729 | attr = snd_hda_get_input_pin_attr(defc); | ||
4730 | /* for internal or docking mics, we need locations */ | ||
4731 | if (attr <= INPUT_PIN_ATTR_NORMAL) | ||
4732 | return 1; | ||
4733 | |||
4734 | attr = 0; | ||
4735 | for (i = 0; i < cfg->num_inputs; i++) { | ||
4736 | defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[i].pin); | ||
4737 | attr2 = snd_hda_get_input_pin_attr(defc); | ||
4738 | if (attr2 >= INPUT_PIN_ATTR_NORMAL) { | ||
4739 | if (attr && attr != attr2) | ||
4740 | return 1; /* different locations found */ | ||
4741 | attr = attr2; | ||
4742 | } | ||
4743 | } | ||
4744 | return 0; | ||
4745 | } | ||
4746 | |||
4747 | /** | ||
4748 | * hda_get_autocfg_input_label - Get a label for the given input | ||
4749 | * | ||
4750 | * Get a label for the given input pin defined by the autocfg item. | ||
4751 | * Unlike hda_get_input_pin_label(), this function checks all inputs | ||
4752 | * defined in autocfg and avoids the redundant mic/line prefix as much as | ||
4753 | * possible. | ||
4754 | */ | ||
4755 | const char *hda_get_autocfg_input_label(struct hda_codec *codec, | ||
4756 | const struct auto_pin_cfg *cfg, | ||
4757 | int input) | ||
4758 | { | ||
4759 | int type = cfg->inputs[input].type; | ||
4760 | int has_multiple_pins = 0; | ||
4761 | |||
4762 | if ((input > 0 && cfg->inputs[input - 1].type == type) || | ||
4763 | (input < cfg->num_inputs - 1 && cfg->inputs[input + 1].type == type)) | ||
4764 | has_multiple_pins = 1; | ||
4765 | if (has_multiple_pins && type == AUTO_PIN_MIC) | ||
4766 | has_multiple_pins &= check_mic_location_need(codec, cfg, input); | ||
4767 | return hda_get_input_pin_label(codec, cfg->inputs[input].pin, | ||
4768 | has_multiple_pins); | ||
4769 | } | ||
4770 | EXPORT_SYMBOL_HDA(hda_get_autocfg_input_label); | ||
4771 | |||
4772 | /** | ||
4773 | * snd_hda_add_imux_item - Add an item to input_mux | ||
4774 | * | ||
4775 | * When the same label is used already in the existing items, the number | ||
4776 | * suffix is appended to the label. This label index number is stored | ||
4777 | * to type_idx when non-NULL pointer is given. | ||
4778 | */ | ||
4779 | int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label, | ||
4780 | int index, int *type_idx) | ||
4781 | { | ||
4782 | int i, label_idx = 0; | ||
4783 | if (imux->num_items >= HDA_MAX_NUM_INPUTS) { | ||
4784 | snd_printd(KERN_ERR "hda_codec: Too many imux items!\n"); | ||
4785 | return -EINVAL; | ||
4786 | } | ||
4787 | for (i = 0; i < imux->num_items; i++) { | ||
4788 | if (!strncmp(label, imux->items[i].label, strlen(label))) | ||
4789 | label_idx++; | ||
4790 | } | ||
4791 | if (type_idx) | ||
4792 | *type_idx = label_idx; | ||
4793 | if (label_idx > 0) | ||
4794 | snprintf(imux->items[imux->num_items].label, | ||
4795 | sizeof(imux->items[imux->num_items].label), | ||
4796 | "%s %d", label, label_idx); | ||
4797 | else | ||
4798 | strlcpy(imux->items[imux->num_items].label, label, | ||
4799 | sizeof(imux->items[imux->num_items].label)); | ||
4800 | imux->items[imux->num_items].index = index; | ||
4801 | imux->num_items++; | ||
4802 | return 0; | ||
4803 | } | ||
4804 | EXPORT_SYMBOL_HDA(snd_hda_add_imux_item); | ||
4644 | 4805 | ||
4645 | 4806 | ||
4646 | #ifdef CONFIG_PM | 4807 | #ifdef CONFIG_PM |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 62c702240108..fdf8d44f8b6b 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -850,6 +850,7 @@ struct hda_codec { | |||
850 | unsigned int pin_amp_workaround:1; /* pin out-amp takes index | 850 | unsigned int pin_amp_workaround:1; /* pin out-amp takes index |
851 | * (e.g. Conexant codecs) | 851 | * (e.g. Conexant codecs) |
852 | */ | 852 | */ |
853 | unsigned int no_sticky_stream:1; /* no sticky-PCM stream assignment */ | ||
853 | unsigned int pins_shutup:1; /* pins are shut up */ | 854 | unsigned int pins_shutup:1; /* pins are shut up */ |
854 | unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */ | 855 | unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */ |
855 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 856 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
@@ -989,6 +990,18 @@ int snd_hda_suspend(struct hda_bus *bus); | |||
989 | int snd_hda_resume(struct hda_bus *bus); | 990 | int snd_hda_resume(struct hda_bus *bus); |
990 | #endif | 991 | #endif |
991 | 992 | ||
993 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
994 | static inline | ||
995 | int hda_call_check_power_status(struct hda_codec *codec, hda_nid_t nid) | ||
996 | { | ||
997 | if (codec->patch_ops.check_power_status) | ||
998 | return codec->patch_ops.check_power_status(codec, nid); | ||
999 | return 0; | ||
1000 | } | ||
1001 | #else | ||
1002 | #define hda_call_check_power_status(codec, nid) 0 | ||
1003 | #endif | ||
1004 | |||
992 | /* | 1005 | /* |
993 | * get widget information | 1006 | * get widget information |
994 | */ | 1007 | */ |
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 26c3ade73583..cb0c23a6b473 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c | |||
@@ -332,7 +332,6 @@ int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid) | |||
332 | return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE, | 332 | return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE, |
333 | AC_DIPSIZE_ELD_BUF); | 333 | AC_DIPSIZE_ELD_BUF); |
334 | } | 334 | } |
335 | EXPORT_SYMBOL_HDA(snd_hdmi_get_eld_size); | ||
336 | 335 | ||
337 | int snd_hdmi_get_eld(struct hdmi_eld *eld, | 336 | int snd_hdmi_get_eld(struct hdmi_eld *eld, |
338 | struct hda_codec *codec, hda_nid_t nid) | 337 | struct hda_codec *codec, hda_nid_t nid) |
@@ -368,7 +367,6 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld, | |||
368 | kfree(buf); | 367 | kfree(buf); |
369 | return ret; | 368 | return ret; |
370 | } | 369 | } |
371 | EXPORT_SYMBOL_HDA(snd_hdmi_get_eld); | ||
372 | 370 | ||
373 | static void hdmi_show_short_audio_desc(struct cea_sad *a) | 371 | static void hdmi_show_short_audio_desc(struct cea_sad *a) |
374 | { | 372 | { |
@@ -407,7 +405,6 @@ void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen) | |||
407 | } | 405 | } |
408 | buf[j] = '\0'; /* necessary when j == 0 */ | 406 | buf[j] = '\0'; /* necessary when j == 0 */ |
409 | } | 407 | } |
410 | EXPORT_SYMBOL_HDA(snd_print_channel_allocation); | ||
411 | 408 | ||
412 | void snd_hdmi_show_eld(struct hdmi_eld *e) | 409 | void snd_hdmi_show_eld(struct hdmi_eld *e) |
413 | { | 410 | { |
@@ -426,7 +423,6 @@ void snd_hdmi_show_eld(struct hdmi_eld *e) | |||
426 | for (i = 0; i < e->sad_count; i++) | 423 | for (i = 0; i < e->sad_count; i++) |
427 | hdmi_show_short_audio_desc(e->sad + i); | 424 | hdmi_show_short_audio_desc(e->sad + i); |
428 | } | 425 | } |
429 | EXPORT_SYMBOL_HDA(snd_hdmi_show_eld); | ||
430 | 426 | ||
431 | #ifdef CONFIG_PROC_FS | 427 | #ifdef CONFIG_PROC_FS |
432 | 428 | ||
@@ -585,7 +581,6 @@ int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld, | |||
585 | 581 | ||
586 | return 0; | 582 | return 0; |
587 | } | 583 | } |
588 | EXPORT_SYMBOL_HDA(snd_hda_eld_proc_new); | ||
589 | 584 | ||
590 | void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld) | 585 | void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld) |
591 | { | 586 | { |
@@ -594,7 +589,6 @@ void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld) | |||
594 | eld->proc_entry = NULL; | 589 | eld->proc_entry = NULL; |
595 | } | 590 | } |
596 | } | 591 | } |
597 | EXPORT_SYMBOL_HDA(snd_hda_eld_proc_free); | ||
598 | 592 | ||
599 | #endif /* CONFIG_PROC_FS */ | 593 | #endif /* CONFIG_PROC_FS */ |
600 | 594 | ||
@@ -645,4 +639,3 @@ void hdmi_eld_update_pcm_info(struct hdmi_eld *eld, struct hda_pcm_stream *pcm, | |||
645 | pcm->channels_max = min(pcm->channels_max, codec_pars->channels_max); | 639 | pcm->channels_max = min(pcm->channels_max, codec_pars->channels_max); |
646 | pcm->maxbps = min(pcm->maxbps, codec_pars->maxbps); | 640 | pcm->maxbps = min(pcm->maxbps, codec_pars->maxbps); |
647 | } | 641 | } |
648 | EXPORT_SYMBOL_HDA(hdmi_eld_update_pcm_info); | ||
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 5ea21285ee1f..fb0582f8d725 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -61,7 +61,6 @@ struct hda_gspec { | |||
61 | struct hda_gnode *cap_vol_node; /* Node for capture volume */ | 61 | struct hda_gnode *cap_vol_node; /* Node for capture volume */ |
62 | unsigned int cur_cap_src; /* current capture source */ | 62 | unsigned int cur_cap_src; /* current capture source */ |
63 | struct hda_input_mux input_mux; | 63 | struct hda_input_mux input_mux; |
64 | char cap_labels[HDA_MAX_NUM_INPUTS][16]; | ||
65 | 64 | ||
66 | unsigned int def_amp_in_caps; | 65 | unsigned int def_amp_in_caps; |
67 | unsigned int def_amp_out_caps; | 66 | unsigned int def_amp_out_caps; |
@@ -506,11 +505,10 @@ static const char *get_input_type(struct hda_gnode *node, unsigned int *pinctl) | |||
506 | * returns 0 if not found, 1 if found, or a negative error code. | 505 | * returns 0 if not found, 1 if found, or a negative error code. |
507 | */ | 506 | */ |
508 | static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec, | 507 | static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec, |
509 | struct hda_gnode *node) | 508 | struct hda_gnode *node, int idx) |
510 | { | 509 | { |
511 | int i, err; | 510 | int i, err; |
512 | unsigned int pinctl; | 511 | unsigned int pinctl; |
513 | char *label; | ||
514 | const char *type; | 512 | const char *type; |
515 | 513 | ||
516 | if (node->checked) | 514 | if (node->checked) |
@@ -523,7 +521,7 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec, | |||
523 | child = hda_get_node(spec, node->conn_list[i]); | 521 | child = hda_get_node(spec, node->conn_list[i]); |
524 | if (! child) | 522 | if (! child) |
525 | continue; | 523 | continue; |
526 | err = parse_adc_sub_nodes(codec, spec, child); | 524 | err = parse_adc_sub_nodes(codec, spec, child, idx); |
527 | if (err < 0) | 525 | if (err < 0) |
528 | return err; | 526 | return err; |
529 | if (err > 0) { | 527 | if (err > 0) { |
@@ -564,9 +562,7 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec, | |||
564 | return 0; | 562 | return 0; |
565 | type = "Input"; | 563 | type = "Input"; |
566 | } | 564 | } |
567 | label = spec->cap_labels[spec->input_mux.num_items]; | 565 | snd_hda_add_imux_item(&spec->input_mux, type, idx, NULL); |
568 | strcpy(label, type); | ||
569 | spec->input_mux.items[spec->input_mux.num_items].label = label; | ||
570 | 566 | ||
571 | /* unmute the PIN external input */ | 567 | /* unmute the PIN external input */ |
572 | unmute_input(codec, node, 0); /* index = 0? */ | 568 | unmute_input(codec, node, 0); /* index = 0? */ |
@@ -577,29 +573,6 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec, | |||
577 | return 1; /* found */ | 573 | return 1; /* found */ |
578 | } | 574 | } |
579 | 575 | ||
580 | /* add a capture source element */ | ||
581 | static void add_cap_src(struct hda_gspec *spec, int idx) | ||
582 | { | ||
583 | struct hda_input_mux_item *csrc; | ||
584 | char *buf; | ||
585 | int num, ocap; | ||
586 | |||
587 | num = spec->input_mux.num_items; | ||
588 | csrc = &spec->input_mux.items[num]; | ||
589 | buf = spec->cap_labels[num]; | ||
590 | for (ocap = 0; ocap < num; ocap++) { | ||
591 | if (! strcmp(buf, spec->cap_labels[ocap])) { | ||
592 | /* same label already exists, | ||
593 | * put the index number to be unique | ||
594 | */ | ||
595 | sprintf(buf, "%s %d", spec->cap_labels[ocap], num); | ||
596 | break; | ||
597 | } | ||
598 | } | ||
599 | csrc->index = idx; | ||
600 | spec->input_mux.num_items++; | ||
601 | } | ||
602 | |||
603 | /* | 576 | /* |
604 | * parse input | 577 | * parse input |
605 | */ | 578 | */ |
@@ -624,22 +597,18 @@ static int parse_input_path(struct hda_codec *codec, struct hda_gnode *adc_node) | |||
624 | for (i = 0; i < adc_node->nconns; i++) { | 597 | for (i = 0; i < adc_node->nconns; i++) { |
625 | node = hda_get_node(spec, adc_node->conn_list[i]); | 598 | node = hda_get_node(spec, adc_node->conn_list[i]); |
626 | if (node && node->type == AC_WID_PIN) { | 599 | if (node && node->type == AC_WID_PIN) { |
627 | err = parse_adc_sub_nodes(codec, spec, node); | 600 | err = parse_adc_sub_nodes(codec, spec, node, i); |
628 | if (err < 0) | 601 | if (err < 0) |
629 | return err; | 602 | return err; |
630 | else if (err > 0) | ||
631 | add_cap_src(spec, i); | ||
632 | } | 603 | } |
633 | } | 604 | } |
634 | /* ... then check the rests, more complicated connections */ | 605 | /* ... then check the rests, more complicated connections */ |
635 | for (i = 0; i < adc_node->nconns; i++) { | 606 | for (i = 0; i < adc_node->nconns; i++) { |
636 | node = hda_get_node(spec, adc_node->conn_list[i]); | 607 | node = hda_get_node(spec, adc_node->conn_list[i]); |
637 | if (node && node->type != AC_WID_PIN) { | 608 | if (node && node->type != AC_WID_PIN) { |
638 | err = parse_adc_sub_nodes(codec, spec, node); | 609 | err = parse_adc_sub_nodes(codec, spec, node, i); |
639 | if (err < 0) | 610 | if (err < 0) |
640 | return err; | 611 | return err; |
641 | else if (err > 0) | ||
642 | add_cap_src(spec, i); | ||
643 | } | 612 | } |
644 | } | 613 | } |
645 | 614 | ||
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 34940a079051..21aa9b0e28f6 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -78,8 +78,8 @@ MODULE_PARM_DESC(enable, "Enable Intel HD audio interface."); | |||
78 | module_param_array(model, charp, NULL, 0444); | 78 | module_param_array(model, charp, NULL, 0444); |
79 | MODULE_PARM_DESC(model, "Use the given board model."); | 79 | MODULE_PARM_DESC(model, "Use the given board model."); |
80 | module_param_array(position_fix, int, NULL, 0444); | 80 | module_param_array(position_fix, int, NULL, 0444); |
81 | MODULE_PARM_DESC(position_fix, "Fix DMA pointer " | 81 | MODULE_PARM_DESC(position_fix, "DMA pointer read method." |
82 | "(0 = auto, 1 = none, 2 = POSBUF)."); | 82 | "(0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO)."); |
83 | module_param_array(bdl_pos_adj, int, NULL, 0644); | 83 | module_param_array(bdl_pos_adj, int, NULL, 0644); |
84 | MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset."); | 84 | MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset."); |
85 | module_param_array(probe_mask, int, NULL, 0444); | 85 | module_param_array(probe_mask, int, NULL, 0444); |
@@ -305,6 +305,7 @@ enum { | |||
305 | POS_FIX_AUTO, | 305 | POS_FIX_AUTO, |
306 | POS_FIX_LPIB, | 306 | POS_FIX_LPIB, |
307 | POS_FIX_POSBUF, | 307 | POS_FIX_POSBUF, |
308 | POS_FIX_VIACOMBO, | ||
308 | }; | 309 | }; |
309 | 310 | ||
310 | /* Defines for ATI HD Audio support in SB450 south bridge */ | 311 | /* Defines for ATI HD Audio support in SB450 south bridge */ |
@@ -433,7 +434,6 @@ struct azx { | |||
433 | unsigned int polling_mode :1; | 434 | unsigned int polling_mode :1; |
434 | unsigned int msi :1; | 435 | unsigned int msi :1; |
435 | unsigned int irq_pending_warned :1; | 436 | unsigned int irq_pending_warned :1; |
436 | unsigned int via_dmapos_patch :1; /* enable DMA-position fix for VIA */ | ||
437 | unsigned int probing :1; /* codec probing phase */ | 437 | unsigned int probing :1; /* codec probing phase */ |
438 | 438 | ||
439 | /* for debugging */ | 439 | /* for debugging */ |
@@ -458,6 +458,7 @@ enum { | |||
458 | AZX_DRIVER_ULI, | 458 | AZX_DRIVER_ULI, |
459 | AZX_DRIVER_NVIDIA, | 459 | AZX_DRIVER_NVIDIA, |
460 | AZX_DRIVER_TERA, | 460 | AZX_DRIVER_TERA, |
461 | AZX_DRIVER_CTX, | ||
461 | AZX_DRIVER_GENERIC, | 462 | AZX_DRIVER_GENERIC, |
462 | AZX_NUM_DRIVERS, /* keep this as last entry */ | 463 | AZX_NUM_DRIVERS, /* keep this as last entry */ |
463 | }; | 464 | }; |
@@ -473,6 +474,7 @@ static char *driver_short_names[] __devinitdata = { | |||
473 | [AZX_DRIVER_ULI] = "HDA ULI M5461", | 474 | [AZX_DRIVER_ULI] = "HDA ULI M5461", |
474 | [AZX_DRIVER_NVIDIA] = "HDA NVidia", | 475 | [AZX_DRIVER_NVIDIA] = "HDA NVidia", |
475 | [AZX_DRIVER_TERA] = "HDA Teradici", | 476 | [AZX_DRIVER_TERA] = "HDA Teradici", |
477 | [AZX_DRIVER_CTX] = "HDA Creative", | ||
476 | [AZX_DRIVER_GENERIC] = "HD-Audio Generic", | 478 | [AZX_DRIVER_GENERIC] = "HD-Audio Generic", |
477 | }; | 479 | }; |
478 | 480 | ||
@@ -563,7 +565,10 @@ static void azx_init_cmd_io(struct azx *chip) | |||
563 | /* reset the rirb hw write pointer */ | 565 | /* reset the rirb hw write pointer */ |
564 | azx_writew(chip, RIRBWP, ICH6_RIRBWP_RST); | 566 | azx_writew(chip, RIRBWP, ICH6_RIRBWP_RST); |
565 | /* set N=1, get RIRB response interrupt for new entry */ | 567 | /* set N=1, get RIRB response interrupt for new entry */ |
566 | azx_writew(chip, RINTCNT, 1); | 568 | if (chip->driver_type == AZX_DRIVER_CTX) |
569 | azx_writew(chip, RINTCNT, 0xc0); | ||
570 | else | ||
571 | azx_writew(chip, RINTCNT, 1); | ||
567 | /* enable rirb dma and response irq */ | 572 | /* enable rirb dma and response irq */ |
568 | azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN); | 573 | azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN); |
569 | spin_unlock_irq(&chip->reg_lock); | 574 | spin_unlock_irq(&chip->reg_lock); |
@@ -1136,8 +1141,11 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id) | |||
1136 | /* clear rirb int */ | 1141 | /* clear rirb int */ |
1137 | status = azx_readb(chip, RIRBSTS); | 1142 | status = azx_readb(chip, RIRBSTS); |
1138 | if (status & RIRB_INT_MASK) { | 1143 | if (status & RIRB_INT_MASK) { |
1139 | if (status & RIRB_INT_RESPONSE) | 1144 | if (status & RIRB_INT_RESPONSE) { |
1145 | if (chip->driver_type == AZX_DRIVER_CTX) | ||
1146 | udelay(80); | ||
1140 | azx_update_rirb(chip); | 1147 | azx_update_rirb(chip); |
1148 | } | ||
1141 | azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); | 1149 | azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); |
1142 | } | 1150 | } |
1143 | 1151 | ||
@@ -1309,11 +1317,8 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | |||
1309 | azx_sd_writel(azx_dev, SD_BDLPU, upper_32_bits(azx_dev->bdl.addr)); | 1317 | azx_sd_writel(azx_dev, SD_BDLPU, upper_32_bits(azx_dev->bdl.addr)); |
1310 | 1318 | ||
1311 | /* enable the position buffer */ | 1319 | /* enable the position buffer */ |
1312 | if (chip->position_fix[0] == POS_FIX_POSBUF || | 1320 | if (chip->position_fix[0] != POS_FIX_LPIB || |
1313 | chip->position_fix[0] == POS_FIX_AUTO || | 1321 | chip->position_fix[1] != POS_FIX_LPIB) { |
1314 | chip->position_fix[1] == POS_FIX_POSBUF || | ||
1315 | chip->position_fix[1] == POS_FIX_AUTO || | ||
1316 | chip->via_dmapos_patch) { | ||
1317 | if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) | 1322 | if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) |
1318 | azx_writel(chip, DPLBASE, | 1323 | azx_writel(chip, DPLBASE, |
1319 | (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE); | 1324 | (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE); |
@@ -1647,7 +1652,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
1647 | struct azx_dev *azx_dev = get_azx_dev(substream); | 1652 | struct azx_dev *azx_dev = get_azx_dev(substream); |
1648 | struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; | 1653 | struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; |
1649 | struct snd_pcm_runtime *runtime = substream->runtime; | 1654 | struct snd_pcm_runtime *runtime = substream->runtime; |
1650 | unsigned int bufsize, period_bytes, format_val; | 1655 | unsigned int bufsize, period_bytes, format_val, stream_tag; |
1651 | int err; | 1656 | int err; |
1652 | 1657 | ||
1653 | azx_stream_reset(chip, azx_dev); | 1658 | azx_stream_reset(chip, azx_dev); |
@@ -1689,7 +1694,12 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
1689 | else | 1694 | else |
1690 | azx_dev->fifo_size = 0; | 1695 | azx_dev->fifo_size = 0; |
1691 | 1696 | ||
1692 | return snd_hda_codec_prepare(apcm->codec, hinfo, azx_dev->stream_tag, | 1697 | stream_tag = azx_dev->stream_tag; |
1698 | /* CA-IBG chips need the playback stream starting from 1 */ | ||
1699 | if (chip->driver_type == AZX_DRIVER_CTX && | ||
1700 | stream_tag > chip->capture_streams) | ||
1701 | stream_tag -= chip->capture_streams; | ||
1702 | return snd_hda_codec_prepare(apcm->codec, hinfo, stream_tag, | ||
1693 | azx_dev->format_val, substream); | 1703 | azx_dev->format_val, substream); |
1694 | } | 1704 | } |
1695 | 1705 | ||
@@ -1852,20 +1862,21 @@ static unsigned int azx_get_position(struct azx *chip, | |||
1852 | struct azx_dev *azx_dev) | 1862 | struct azx_dev *azx_dev) |
1853 | { | 1863 | { |
1854 | unsigned int pos; | 1864 | unsigned int pos; |
1865 | int stream = azx_dev->substream->stream; | ||
1855 | 1866 | ||
1856 | if (chip->via_dmapos_patch) | 1867 | switch (chip->position_fix[stream]) { |
1868 | case POS_FIX_LPIB: | ||
1869 | /* read LPIB */ | ||
1870 | pos = azx_sd_readl(azx_dev, SD_LPIB); | ||
1871 | break; | ||
1872 | case POS_FIX_VIACOMBO: | ||
1857 | pos = azx_via_get_position(chip, azx_dev); | 1873 | pos = azx_via_get_position(chip, azx_dev); |
1858 | else { | 1874 | break; |
1859 | int stream = azx_dev->substream->stream; | 1875 | default: |
1860 | if (chip->position_fix[stream] == POS_FIX_POSBUF || | 1876 | /* use the position buffer */ |
1861 | chip->position_fix[stream] == POS_FIX_AUTO) { | 1877 | pos = le32_to_cpu(*azx_dev->posbuf); |
1862 | /* use the position buffer */ | ||
1863 | pos = le32_to_cpu(*azx_dev->posbuf); | ||
1864 | } else { | ||
1865 | /* read LPIB */ | ||
1866 | pos = azx_sd_readl(azx_dev, SD_LPIB); | ||
1867 | } | ||
1868 | } | 1878 | } |
1879 | |||
1869 | if (pos >= azx_dev->bufsize) | 1880 | if (pos >= azx_dev->bufsize) |
1870 | pos = 0; | 1881 | pos = 0; |
1871 | return pos; | 1882 | return pos; |
@@ -2313,19 +2324,10 @@ static int __devinit check_position_fix(struct azx *chip, int fix) | |||
2313 | switch (fix) { | 2324 | switch (fix) { |
2314 | case POS_FIX_LPIB: | 2325 | case POS_FIX_LPIB: |
2315 | case POS_FIX_POSBUF: | 2326 | case POS_FIX_POSBUF: |
2327 | case POS_FIX_VIACOMBO: | ||
2316 | return fix; | 2328 | return fix; |
2317 | } | 2329 | } |
2318 | 2330 | ||
2319 | /* Check VIA/ATI HD Audio Controller exist */ | ||
2320 | switch (chip->driver_type) { | ||
2321 | case AZX_DRIVER_VIA: | ||
2322 | case AZX_DRIVER_ATI: | ||
2323 | chip->via_dmapos_patch = 1; | ||
2324 | /* Use link position directly, avoid any transfer problem. */ | ||
2325 | return POS_FIX_LPIB; | ||
2326 | } | ||
2327 | chip->via_dmapos_patch = 0; | ||
2328 | |||
2329 | q = snd_pci_quirk_lookup(chip->pci, position_fix_list); | 2331 | q = snd_pci_quirk_lookup(chip->pci, position_fix_list); |
2330 | if (q) { | 2332 | if (q) { |
2331 | printk(KERN_INFO | 2333 | printk(KERN_INFO |
@@ -2334,6 +2336,15 @@ static int __devinit check_position_fix(struct azx *chip, int fix) | |||
2334 | q->value, q->subvendor, q->subdevice); | 2336 | q->value, q->subvendor, q->subdevice); |
2335 | return q->value; | 2337 | return q->value; |
2336 | } | 2338 | } |
2339 | |||
2340 | /* Check VIA/ATI HD Audio Controller exist */ | ||
2341 | switch (chip->driver_type) { | ||
2342 | case AZX_DRIVER_VIA: | ||
2343 | case AZX_DRIVER_ATI: | ||
2344 | /* Use link position directly, avoid any transfer problem. */ | ||
2345 | return POS_FIX_VIACOMBO; | ||
2346 | } | ||
2347 | |||
2337 | return POS_FIX_AUTO; | 2348 | return POS_FIX_AUTO; |
2338 | } | 2349 | } |
2339 | 2350 | ||
@@ -2735,25 +2746,17 @@ static void __devexit azx_remove(struct pci_dev *pci) | |||
2735 | 2746 | ||
2736 | /* PCI IDs */ | 2747 | /* PCI IDs */ |
2737 | static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { | 2748 | static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { |
2738 | /* ICH 6..10 */ | ||
2739 | { PCI_DEVICE(0x8086, 0x2668), .driver_data = AZX_DRIVER_ICH }, | ||
2740 | { PCI_DEVICE(0x8086, 0x27d8), .driver_data = AZX_DRIVER_ICH }, | ||
2741 | { PCI_DEVICE(0x8086, 0x269a), .driver_data = AZX_DRIVER_ICH }, | ||
2742 | { PCI_DEVICE(0x8086, 0x284b), .driver_data = AZX_DRIVER_ICH }, | ||
2743 | { PCI_DEVICE(0x8086, 0x2911), .driver_data = AZX_DRIVER_ICH }, | ||
2744 | { PCI_DEVICE(0x8086, 0x293e), .driver_data = AZX_DRIVER_ICH }, | ||
2745 | { PCI_DEVICE(0x8086, 0x293f), .driver_data = AZX_DRIVER_ICH }, | ||
2746 | { PCI_DEVICE(0x8086, 0x3a3e), .driver_data = AZX_DRIVER_ICH }, | ||
2747 | { PCI_DEVICE(0x8086, 0x3a6e), .driver_data = AZX_DRIVER_ICH }, | ||
2748 | /* PCH */ | ||
2749 | { PCI_DEVICE(0x8086, 0x3b56), .driver_data = AZX_DRIVER_ICH }, | ||
2750 | { PCI_DEVICE(0x8086, 0x3b57), .driver_data = AZX_DRIVER_ICH }, | ||
2751 | /* CPT */ | 2749 | /* CPT */ |
2752 | { PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH }, | 2750 | { PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH }, |
2753 | /* PBG */ | 2751 | /* PBG */ |
2754 | { PCI_DEVICE(0x8086, 0x1d20), .driver_data = AZX_DRIVER_PCH }, | 2752 | { PCI_DEVICE(0x8086, 0x1d20), .driver_data = AZX_DRIVER_PCH }, |
2755 | /* SCH */ | 2753 | /* SCH */ |
2756 | { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH }, | 2754 | { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH }, |
2755 | /* Generic Intel */ | ||
2756 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_ANY_ID), | ||
2757 | .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, | ||
2758 | .class_mask = 0xffffff, | ||
2759 | .driver_data = AZX_DRIVER_ICH }, | ||
2757 | /* ATI SB 450/600 */ | 2760 | /* ATI SB 450/600 */ |
2758 | { PCI_DEVICE(0x1002, 0x437b), .driver_data = AZX_DRIVER_ATI }, | 2761 | { PCI_DEVICE(0x1002, 0x437b), .driver_data = AZX_DRIVER_ATI }, |
2759 | { PCI_DEVICE(0x1002, 0x4383), .driver_data = AZX_DRIVER_ATI }, | 2762 | { PCI_DEVICE(0x1002, 0x4383), .driver_data = AZX_DRIVER_ATI }, |
@@ -2794,11 +2797,13 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { | |||
2794 | { PCI_DEVICE(PCI_VENDOR_ID_CREATIVE, PCI_ANY_ID), | 2797 | { PCI_DEVICE(PCI_VENDOR_ID_CREATIVE, PCI_ANY_ID), |
2795 | .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, | 2798 | .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, |
2796 | .class_mask = 0xffffff, | 2799 | .class_mask = 0xffffff, |
2797 | .driver_data = AZX_DRIVER_GENERIC }, | 2800 | .driver_data = AZX_DRIVER_CTX }, |
2798 | #else | 2801 | #else |
2799 | /* this entry seems still valid -- i.e. without emu20kx chip */ | 2802 | /* this entry seems still valid -- i.e. without emu20kx chip */ |
2800 | { PCI_DEVICE(0x1102, 0x0009), .driver_data = AZX_DRIVER_GENERIC }, | 2803 | { PCI_DEVICE(0x1102, 0x0009), .driver_data = AZX_DRIVER_CTX }, |
2801 | #endif | 2804 | #endif |
2805 | /* Vortex86MX */ | ||
2806 | { PCI_DEVICE(0x17f3, 0x3010), .driver_data = AZX_DRIVER_GENERIC }, | ||
2802 | /* AMD/ATI Generic, PCI class code and Vendor ID for HD Audio */ | 2807 | /* AMD/ATI Generic, PCI class code and Vendor ID for HD Audio */ |
2803 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_ANY_ID), | 2808 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_ANY_ID), |
2804 | .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, | 2809 | .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 28ab4aead48f..46bbefe2e4a9 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -38,10 +38,11 @@ | |||
38 | */ | 38 | */ |
39 | #define HDA_COMPOSE_AMP_VAL_OFS(nid,chs,idx,dir,ofs) \ | 39 | #define HDA_COMPOSE_AMP_VAL_OFS(nid,chs,idx,dir,ofs) \ |
40 | ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19) | ((ofs)<<23)) | 40 | ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19) | ((ofs)<<23)) |
41 | #define HDA_AMP_VAL_MIN_MUTE (1<<29) | ||
41 | #define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \ | 42 | #define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \ |
42 | HDA_COMPOSE_AMP_VAL_OFS(nid, chs, idx, dir, 0) | 43 | HDA_COMPOSE_AMP_VAL_OFS(nid, chs, idx, dir, 0) |
43 | /* mono volume with index (index=0,1,...) (channel=1,2) */ | 44 | /* mono volume with index (index=0,1,...) (channel=1,2) */ |
44 | #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ | 45 | #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, dir, flags) \ |
45 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ | 46 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ |
46 | .subdevice = HDA_SUBDEV_AMP_FLAG, \ | 47 | .subdevice = HDA_SUBDEV_AMP_FLAG, \ |
47 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ | 48 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ |
@@ -51,16 +52,20 @@ | |||
51 | .get = snd_hda_mixer_amp_volume_get, \ | 52 | .get = snd_hda_mixer_amp_volume_get, \ |
52 | .put = snd_hda_mixer_amp_volume_put, \ | 53 | .put = snd_hda_mixer_amp_volume_put, \ |
53 | .tlv = { .c = snd_hda_mixer_amp_tlv }, \ | 54 | .tlv = { .c = snd_hda_mixer_amp_tlv }, \ |
54 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) } | 55 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, dir) | flags } |
55 | /* stereo volume with index */ | 56 | /* stereo volume with index */ |
56 | #define HDA_CODEC_VOLUME_IDX(xname, xcidx, nid, xindex, direction) \ | 57 | #define HDA_CODEC_VOLUME_IDX(xname, xcidx, nid, xindex, direction) \ |
57 | HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, 3, xindex, direction) | 58 | HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, 3, xindex, direction, 0) |
58 | /* mono volume */ | 59 | /* mono volume */ |
59 | #define HDA_CODEC_VOLUME_MONO(xname, nid, channel, xindex, direction) \ | 60 | #define HDA_CODEC_VOLUME_MONO(xname, nid, channel, xindex, direction) \ |
60 | HDA_CODEC_VOLUME_MONO_IDX(xname, 0, nid, channel, xindex, direction) | 61 | HDA_CODEC_VOLUME_MONO_IDX(xname, 0, nid, channel, xindex, direction, 0) |
61 | /* stereo volume */ | 62 | /* stereo volume */ |
62 | #define HDA_CODEC_VOLUME(xname, nid, xindex, direction) \ | 63 | #define HDA_CODEC_VOLUME(xname, nid, xindex, direction) \ |
63 | HDA_CODEC_VOLUME_MONO(xname, nid, 3, xindex, direction) | 64 | HDA_CODEC_VOLUME_MONO(xname, nid, 3, xindex, direction) |
65 | /* stereo volume with min=mute */ | ||
66 | #define HDA_CODEC_VOLUME_MIN_MUTE(xname, nid, xindex, direction) \ | ||
67 | HDA_CODEC_VOLUME_MONO_IDX(xname, 0, nid, 3, xindex, direction, \ | ||
68 | HDA_AMP_VAL_MIN_MUTE) | ||
64 | /* mono mute switch with index (index=0,1,...) (channel=1,2) */ | 69 | /* mono mute switch with index (index=0,1,...) (channel=1,2) */ |
65 | #define HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ | 70 | #define HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ |
66 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ | 71 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ |
@@ -215,7 +220,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid); | |||
215 | */ | 220 | */ |
216 | #define HDA_MAX_NUM_INPUTS 16 | 221 | #define HDA_MAX_NUM_INPUTS 16 |
217 | struct hda_input_mux_item { | 222 | struct hda_input_mux_item { |
218 | const char *label; | 223 | char label[32]; |
219 | unsigned int index; | 224 | unsigned int index; |
220 | }; | 225 | }; |
221 | struct hda_input_mux { | 226 | struct hda_input_mux { |
@@ -366,9 +371,7 @@ struct hda_bus_unsolicited { | |||
366 | 371 | ||
367 | enum { | 372 | enum { |
368 | AUTO_PIN_MIC, | 373 | AUTO_PIN_MIC, |
369 | AUTO_PIN_FRONT_MIC, | 374 | AUTO_PIN_LINE_IN, |
370 | AUTO_PIN_LINE, | ||
371 | AUTO_PIN_FRONT_LINE, | ||
372 | AUTO_PIN_CD, | 375 | AUTO_PIN_CD, |
373 | AUTO_PIN_AUX, | 376 | AUTO_PIN_AUX, |
374 | AUTO_PIN_LAST | 377 | AUTO_PIN_LAST |
@@ -380,9 +383,33 @@ enum { | |||
380 | AUTO_PIN_HP_OUT | 383 | AUTO_PIN_HP_OUT |
381 | }; | 384 | }; |
382 | 385 | ||
383 | extern const char *auto_pin_cfg_labels[AUTO_PIN_LAST]; | ||
384 | |||
385 | #define AUTO_CFG_MAX_OUTS 5 | 386 | #define AUTO_CFG_MAX_OUTS 5 |
387 | #define AUTO_CFG_MAX_INS 8 | ||
388 | |||
389 | struct auto_pin_cfg_item { | ||
390 | hda_nid_t pin; | ||
391 | int type; | ||
392 | }; | ||
393 | |||
394 | struct auto_pin_cfg; | ||
395 | const char *hda_get_input_pin_label(struct hda_codec *codec, hda_nid_t pin, | ||
396 | int check_location); | ||
397 | const char *hda_get_autocfg_input_label(struct hda_codec *codec, | ||
398 | const struct auto_pin_cfg *cfg, | ||
399 | int input); | ||
400 | int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label, | ||
401 | int index, int *type_index_ret); | ||
402 | |||
403 | enum { | ||
404 | INPUT_PIN_ATTR_UNUSED, /* pin not connected */ | ||
405 | INPUT_PIN_ATTR_INT, /* internal mic/line-in */ | ||
406 | INPUT_PIN_ATTR_DOCK, /* docking mic/line-in */ | ||
407 | INPUT_PIN_ATTR_NORMAL, /* mic/line-in jack */ | ||
408 | INPUT_PIN_ATTR_FRONT, /* mic/line-in jack in front */ | ||
409 | INPUT_PIN_ATTR_REAR, /* mic/line-in jack in rear */ | ||
410 | }; | ||
411 | |||
412 | int snd_hda_get_input_pin_attr(unsigned int def_conf); | ||
386 | 413 | ||
387 | struct auto_pin_cfg { | 414 | struct auto_pin_cfg { |
388 | int line_outs; | 415 | int line_outs; |
@@ -393,7 +420,8 @@ struct auto_pin_cfg { | |||
393 | int hp_outs; | 420 | int hp_outs; |
394 | int line_out_type; /* AUTO_PIN_XXX_OUT */ | 421 | int line_out_type; /* AUTO_PIN_XXX_OUT */ |
395 | hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS]; | 422 | hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS]; |
396 | hda_nid_t input_pins[AUTO_PIN_LAST]; | 423 | int num_inputs; |
424 | struct auto_pin_cfg_item inputs[AUTO_CFG_MAX_INS]; | ||
397 | int dig_outs; | 425 | int dig_outs; |
398 | hda_nid_t dig_out_pins[2]; | 426 | hda_nid_t dig_out_pins[2]; |
399 | hda_nid_t dig_in_pin; | 427 | hda_nid_t dig_in_pin; |
@@ -558,6 +586,7 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec, | |||
558 | #define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1) | 586 | #define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1) |
559 | #define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) | 587 | #define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) |
560 | #define get_amp_offset(kc) (((kc)->private_value >> 23) & 0x3f) | 588 | #define get_amp_offset(kc) (((kc)->private_value >> 23) & 0x3f) |
589 | #define get_amp_min_mute(kc) (((kc)->private_value >> 29) & 0x1) | ||
561 | 590 | ||
562 | /* | 591 | /* |
563 | * CEA Short Audio Descriptor data | 592 | * CEA Short Audio Descriptor data |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 10bbbaf6ebc3..f7ff3f7ccb8e 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -1276,6 +1276,7 @@ static int patch_ad1986a(struct hda_codec *codec) | |||
1276 | spec->multiout.no_share_stream = 1; | 1276 | spec->multiout.no_share_stream = 1; |
1277 | 1277 | ||
1278 | codec->no_trigger_sense = 1; | 1278 | codec->no_trigger_sense = 1; |
1279 | codec->no_sticky_stream = 1; | ||
1279 | 1280 | ||
1280 | return 0; | 1281 | return 0; |
1281 | } | 1282 | } |
@@ -1463,6 +1464,7 @@ static int patch_ad1983(struct hda_codec *codec) | |||
1463 | codec->patch_ops = ad198x_patch_ops; | 1464 | codec->patch_ops = ad198x_patch_ops; |
1464 | 1465 | ||
1465 | codec->no_trigger_sense = 1; | 1466 | codec->no_trigger_sense = 1; |
1467 | codec->no_sticky_stream = 1; | ||
1466 | 1468 | ||
1467 | return 0; | 1469 | return 0; |
1468 | } | 1470 | } |
@@ -1917,6 +1919,7 @@ static int patch_ad1981(struct hda_codec *codec) | |||
1917 | } | 1919 | } |
1918 | 1920 | ||
1919 | codec->no_trigger_sense = 1; | 1921 | codec->no_trigger_sense = 1; |
1922 | codec->no_sticky_stream = 1; | ||
1920 | 1923 | ||
1921 | return 0; | 1924 | return 0; |
1922 | } | 1925 | } |
@@ -2880,7 +2883,7 @@ static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, | |||
2880 | 2883 | ||
2881 | /* create input playback/capture controls for the given pin */ | 2884 | /* create input playback/capture controls for the given pin */ |
2882 | static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin, | 2885 | static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin, |
2883 | const char *ctlname, int boost) | 2886 | const char *ctlname, int ctlidx, int boost) |
2884 | { | 2887 | { |
2885 | char name[32]; | 2888 | char name[32]; |
2886 | int err, idx; | 2889 | int err, idx; |
@@ -2909,25 +2912,27 @@ static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin, | |||
2909 | } | 2912 | } |
2910 | 2913 | ||
2911 | /* create playback/capture controls for input pins */ | 2914 | /* create playback/capture controls for input pins */ |
2912 | static int ad1988_auto_create_analog_input_ctls(struct ad198x_spec *spec, | 2915 | static int ad1988_auto_create_analog_input_ctls(struct hda_codec *codec, |
2913 | const struct auto_pin_cfg *cfg) | 2916 | const struct auto_pin_cfg *cfg) |
2914 | { | 2917 | { |
2918 | struct ad198x_spec *spec = codec->spec; | ||
2915 | struct hda_input_mux *imux = &spec->private_imux; | 2919 | struct hda_input_mux *imux = &spec->private_imux; |
2916 | int i, err; | 2920 | int i, err, type, type_idx; |
2917 | 2921 | ||
2918 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 2922 | for (i = 0; i < cfg->num_inputs; i++) { |
2919 | err = new_analog_input(spec, cfg->input_pins[i], | 2923 | const char *label; |
2920 | auto_pin_cfg_labels[i], | 2924 | type = cfg->inputs[i].type; |
2921 | i <= AUTO_PIN_FRONT_MIC); | 2925 | label = hda_get_autocfg_input_label(codec, cfg, i); |
2926 | snd_hda_add_imux_item(imux, label, | ||
2927 | ad1988_pin_to_adc_idx(cfg->inputs[i].pin), | ||
2928 | &type_idx); | ||
2929 | err = new_analog_input(spec, cfg->inputs[i].pin, | ||
2930 | label, type_idx, | ||
2931 | type == AUTO_PIN_MIC); | ||
2922 | if (err < 0) | 2932 | if (err < 0) |
2923 | return err; | 2933 | return err; |
2924 | imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; | ||
2925 | imux->items[imux->num_items].index = ad1988_pin_to_adc_idx(cfg->input_pins[i]); | ||
2926 | imux->num_items++; | ||
2927 | } | 2934 | } |
2928 | imux->items[imux->num_items].label = "Mix"; | 2935 | snd_hda_add_imux_item(imux, "Mix", 9, NULL); |
2929 | imux->items[imux->num_items].index = 9; | ||
2930 | imux->num_items++; | ||
2931 | 2936 | ||
2932 | if ((err = add_control(spec, AD_CTL_WIDGET_VOL, | 2937 | if ((err = add_control(spec, AD_CTL_WIDGET_VOL, |
2933 | "Analog Mix Playback Volume", | 2938 | "Analog Mix Playback Volume", |
@@ -2994,12 +2999,11 @@ static void ad1988_auto_init_extra_out(struct hda_codec *codec) | |||
2994 | static void ad1988_auto_init_analog_input(struct hda_codec *codec) | 2999 | static void ad1988_auto_init_analog_input(struct hda_codec *codec) |
2995 | { | 3000 | { |
2996 | struct ad198x_spec *spec = codec->spec; | 3001 | struct ad198x_spec *spec = codec->spec; |
3002 | const struct auto_pin_cfg *cfg = &spec->autocfg; | ||
2997 | int i, idx; | 3003 | int i, idx; |
2998 | 3004 | ||
2999 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 3005 | for (i = 0; i < cfg->num_inputs; i++) { |
3000 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 3006 | hda_nid_t nid = cfg->inputs[i].pin; |
3001 | if (! nid) | ||
3002 | continue; | ||
3003 | switch (nid) { | 3007 | switch (nid) { |
3004 | case 0x15: /* port-C */ | 3008 | case 0x15: /* port-C */ |
3005 | snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0); | 3009 | snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0); |
@@ -3009,7 +3013,7 @@ static void ad1988_auto_init_analog_input(struct hda_codec *codec) | |||
3009 | break; | 3013 | break; |
3010 | } | 3014 | } |
3011 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 3015 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, |
3012 | i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN); | 3016 | i == AUTO_PIN_MIC ? PIN_VREF80 : PIN_IN); |
3013 | if (nid != AD1988_PIN_CD_NID) | 3017 | if (nid != AD1988_PIN_CD_NID) |
3014 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 3018 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, |
3015 | AMP_OUT_MUTE); | 3019 | AMP_OUT_MUTE); |
@@ -3040,7 +3044,7 @@ static int ad1988_parse_auto_config(struct hda_codec *codec) | |||
3040 | "Speaker")) < 0 || | 3044 | "Speaker")) < 0 || |
3041 | (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0], | 3045 | (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0], |
3042 | "Headphone")) < 0 || | 3046 | "Headphone")) < 0 || |
3043 | (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) | 3047 | (err = ad1988_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0) |
3044 | return err; | 3048 | return err; |
3045 | 3049 | ||
3046 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 3050 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
@@ -3235,6 +3239,7 @@ static int patch_ad1988(struct hda_codec *codec) | |||
3235 | spec->vmaster_nid = 0x04; | 3239 | spec->vmaster_nid = 0x04; |
3236 | 3240 | ||
3237 | codec->no_trigger_sense = 1; | 3241 | codec->no_trigger_sense = 1; |
3242 | codec->no_sticky_stream = 1; | ||
3238 | 3243 | ||
3239 | return 0; | 3244 | return 0; |
3240 | } | 3245 | } |
@@ -3449,6 +3454,7 @@ static int patch_ad1884(struct hda_codec *codec) | |||
3449 | codec->patch_ops = ad198x_patch_ops; | 3454 | codec->patch_ops = ad198x_patch_ops; |
3450 | 3455 | ||
3451 | codec->no_trigger_sense = 1; | 3456 | codec->no_trigger_sense = 1; |
3457 | codec->no_sticky_stream = 1; | ||
3452 | 3458 | ||
3453 | return 0; | 3459 | return 0; |
3454 | } | 3460 | } |
@@ -4422,6 +4428,7 @@ static int patch_ad1884a(struct hda_codec *codec) | |||
4422 | } | 4428 | } |
4423 | 4429 | ||
4424 | codec->no_trigger_sense = 1; | 4430 | codec->no_trigger_sense = 1; |
4431 | codec->no_sticky_stream = 1; | ||
4425 | 4432 | ||
4426 | return 0; | 4433 | return 0; |
4427 | } | 4434 | } |
@@ -4761,6 +4768,7 @@ static int patch_ad1882(struct hda_codec *codec) | |||
4761 | } | 4768 | } |
4762 | 4769 | ||
4763 | codec->no_trigger_sense = 1; | 4770 | codec->no_trigger_sense = 1; |
4771 | codec->no_sticky_stream = 1; | ||
4764 | 4772 | ||
4765 | return 0; | 4773 | return 0; |
4766 | } | 4774 | } |
diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c deleted file mode 100644 index fb684f00156b..000000000000 --- a/sound/pci/hda/patch_atihdmi.c +++ /dev/null | |||
@@ -1,224 +0,0 @@ | |||
1 | /* | ||
2 | * Universal Interface for Intel High Definition Audio Codec | ||
3 | * | ||
4 | * HD audio interface patch for ATI HDMI codecs | ||
5 | * | ||
6 | * Copyright (c) 2006 ATI Technologies Inc. | ||
7 | * | ||
8 | * | ||
9 | * This driver is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This driver is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | */ | ||
23 | |||
24 | #include <linux/init.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <sound/core.h> | ||
28 | #include "hda_codec.h" | ||
29 | #include "hda_local.h" | ||
30 | |||
31 | struct atihdmi_spec { | ||
32 | struct hda_multi_out multiout; | ||
33 | |||
34 | struct hda_pcm pcm_rec; | ||
35 | }; | ||
36 | |||
37 | #define CVT_NID 0x02 /* audio converter */ | ||
38 | #define PIN_NID 0x03 /* HDMI output pin */ | ||
39 | |||
40 | static struct hda_verb atihdmi_basic_init[] = { | ||
41 | /* enable digital output on pin widget */ | ||
42 | { 0x03, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
43 | {} /* terminator */ | ||
44 | }; | ||
45 | |||
46 | /* | ||
47 | * Controls | ||
48 | */ | ||
49 | static int atihdmi_build_controls(struct hda_codec *codec) | ||
50 | { | ||
51 | struct atihdmi_spec *spec = codec->spec; | ||
52 | int err; | ||
53 | |||
54 | err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); | ||
55 | if (err < 0) | ||
56 | return err; | ||
57 | |||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | static int atihdmi_init(struct hda_codec *codec) | ||
62 | { | ||
63 | snd_hda_sequence_write(codec, atihdmi_basic_init); | ||
64 | /* SI codec requires to unmute the pin */ | ||
65 | if (get_wcaps(codec, PIN_NID) & AC_WCAP_OUT_AMP) | ||
66 | snd_hda_codec_write(codec, PIN_NID, 0, | ||
67 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
68 | AMP_OUT_UNMUTE); | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | /* | ||
73 | * Digital out | ||
74 | */ | ||
75 | static int atihdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
76 | struct hda_codec *codec, | ||
77 | struct snd_pcm_substream *substream) | ||
78 | { | ||
79 | struct atihdmi_spec *spec = codec->spec; | ||
80 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | ||
81 | } | ||
82 | |||
83 | static int atihdmi_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | ||
84 | struct hda_codec *codec, | ||
85 | struct snd_pcm_substream *substream) | ||
86 | { | ||
87 | struct atihdmi_spec *spec = codec->spec; | ||
88 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
89 | } | ||
90 | |||
91 | static int atihdmi_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
92 | struct hda_codec *codec, | ||
93 | unsigned int stream_tag, | ||
94 | unsigned int format, | ||
95 | struct snd_pcm_substream *substream) | ||
96 | { | ||
97 | struct atihdmi_spec *spec = codec->spec; | ||
98 | int chans = substream->runtime->channels; | ||
99 | int i, err; | ||
100 | |||
101 | err = snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, | ||
102 | format, substream); | ||
103 | if (err < 0) | ||
104 | return err; | ||
105 | snd_hda_codec_write(codec, CVT_NID, 0, AC_VERB_SET_CVT_CHAN_COUNT, | ||
106 | chans - 1); | ||
107 | /* FIXME: XXX */ | ||
108 | for (i = 0; i < chans; i++) { | ||
109 | snd_hda_codec_write(codec, CVT_NID, 0, | ||
110 | AC_VERB_SET_HDMI_CHAN_SLOT, | ||
111 | (i << 4) | i); | ||
112 | } | ||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static struct hda_pcm_stream atihdmi_pcm_digital_playback = { | ||
117 | .substreams = 1, | ||
118 | .channels_min = 2, | ||
119 | .channels_max = 2, | ||
120 | .nid = CVT_NID, /* NID to query formats and rates and setup streams */ | ||
121 | .ops = { | ||
122 | .open = atihdmi_dig_playback_pcm_open, | ||
123 | .close = atihdmi_dig_playback_pcm_close, | ||
124 | .prepare = atihdmi_dig_playback_pcm_prepare | ||
125 | }, | ||
126 | }; | ||
127 | |||
128 | static int atihdmi_build_pcms(struct hda_codec *codec) | ||
129 | { | ||
130 | struct atihdmi_spec *spec = codec->spec; | ||
131 | struct hda_pcm *info = &spec->pcm_rec; | ||
132 | unsigned int chans; | ||
133 | |||
134 | codec->num_pcms = 1; | ||
135 | codec->pcm_info = info; | ||
136 | |||
137 | info->name = "ATI HDMI"; | ||
138 | info->pcm_type = HDA_PCM_TYPE_HDMI; | ||
139 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = atihdmi_pcm_digital_playback; | ||
140 | |||
141 | /* FIXME: we must check ELD and change the PCM parameters dynamically | ||
142 | */ | ||
143 | chans = get_wcaps(codec, CVT_NID); | ||
144 | chans = get_wcaps_channels(chans); | ||
145 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans; | ||
146 | |||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | static void atihdmi_free(struct hda_codec *codec) | ||
151 | { | ||
152 | kfree(codec->spec); | ||
153 | } | ||
154 | |||
155 | static struct hda_codec_ops atihdmi_patch_ops = { | ||
156 | .build_controls = atihdmi_build_controls, | ||
157 | .build_pcms = atihdmi_build_pcms, | ||
158 | .init = atihdmi_init, | ||
159 | .free = atihdmi_free, | ||
160 | }; | ||
161 | |||
162 | static int patch_atihdmi(struct hda_codec *codec) | ||
163 | { | ||
164 | struct atihdmi_spec *spec; | ||
165 | |||
166 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
167 | if (spec == NULL) | ||
168 | return -ENOMEM; | ||
169 | |||
170 | codec->spec = spec; | ||
171 | |||
172 | spec->multiout.num_dacs = 0; /* no analog */ | ||
173 | spec->multiout.max_channels = 2; | ||
174 | /* NID for copying analog to digital, | ||
175 | * seems to be unused in pure-digital | ||
176 | * case. | ||
177 | */ | ||
178 | spec->multiout.dig_out_nid = CVT_NID; | ||
179 | |||
180 | codec->patch_ops = atihdmi_patch_ops; | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | /* | ||
186 | * patch entries | ||
187 | */ | ||
188 | static struct hda_codec_preset snd_hda_preset_atihdmi[] = { | ||
189 | { .id = 0x1002793c, .name = "RS600 HDMI", .patch = patch_atihdmi }, | ||
190 | { .id = 0x10027919, .name = "RS600 HDMI", .patch = patch_atihdmi }, | ||
191 | { .id = 0x1002791a, .name = "RS690/780 HDMI", .patch = patch_atihdmi }, | ||
192 | { .id = 0x1002aa01, .name = "R6xx HDMI", .patch = patch_atihdmi }, | ||
193 | { .id = 0x10951390, .name = "SiI1390 HDMI", .patch = patch_atihdmi }, | ||
194 | { .id = 0x17e80047, .name = "Chrontel HDMI", .patch = patch_atihdmi }, | ||
195 | {} /* terminator */ | ||
196 | }; | ||
197 | |||
198 | MODULE_ALIAS("snd-hda-codec-id:1002793c"); | ||
199 | MODULE_ALIAS("snd-hda-codec-id:10027919"); | ||
200 | MODULE_ALIAS("snd-hda-codec-id:1002791a"); | ||
201 | MODULE_ALIAS("snd-hda-codec-id:1002aa01"); | ||
202 | MODULE_ALIAS("snd-hda-codec-id:10951390"); | ||
203 | MODULE_ALIAS("snd-hda-codec-id:17e80047"); | ||
204 | |||
205 | MODULE_LICENSE("GPL"); | ||
206 | MODULE_DESCRIPTION("ATI HDMI HD-audio codec"); | ||
207 | |||
208 | static struct hda_codec_preset_list atihdmi_list = { | ||
209 | .preset = snd_hda_preset_atihdmi, | ||
210 | .owner = THIS_MODULE, | ||
211 | }; | ||
212 | |||
213 | static int __init patch_atihdmi_init(void) | ||
214 | { | ||
215 | return snd_hda_add_codec_preset(&atihdmi_list); | ||
216 | } | ||
217 | |||
218 | static void __exit patch_atihdmi_exit(void) | ||
219 | { | ||
220 | snd_hda_delete_codec_preset(&atihdmi_list); | ||
221 | } | ||
222 | |||
223 | module_init(patch_atihdmi_init) | ||
224 | module_exit(patch_atihdmi_exit) | ||
diff --git a/sound/pci/hda/patch_ca0110.c b/sound/pci/hda/patch_ca0110.c index af478019088e..46c8bf48c31f 100644 --- a/sound/pci/hda/patch_ca0110.c +++ b/sound/pci/hda/patch_ca0110.c | |||
@@ -468,13 +468,13 @@ static void parse_input(struct hda_codec *codec) | |||
468 | spec->dig_in = nid; | 468 | spec->dig_in = nid; |
469 | continue; | 469 | continue; |
470 | } | 470 | } |
471 | for (j = 0; j < AUTO_PIN_LAST; j++) | 471 | for (j = 0; j < cfg->num_inputs; j++) |
472 | if (cfg->input_pins[j] == pin) | 472 | if (cfg->inputs[j].pin == pin) |
473 | break; | 473 | break; |
474 | if (j >= AUTO_PIN_LAST) | 474 | if (j >= cfg->num_inputs) |
475 | continue; | 475 | continue; |
476 | spec->input_pins[n] = pin; | 476 | spec->input_pins[n] = pin; |
477 | spec->input_labels[n] = auto_pin_cfg_labels[j]; | 477 | spec->input_labels[n] = hda_get_input_pin_label(codec, pin, 1); |
478 | spec->adcs[n] = nid; | 478 | spec->adcs[n] = nid; |
479 | n++; | 479 | n++; |
480 | } | 480 | } |
@@ -489,7 +489,7 @@ static void parse_digital(struct hda_codec *codec) | |||
489 | if (cfg->dig_outs && | 489 | if (cfg->dig_outs && |
490 | snd_hda_get_connections(codec, cfg->dig_out_pins[0], | 490 | snd_hda_get_connections(codec, cfg->dig_out_pins[0], |
491 | &spec->dig_out, 1) == 1) | 491 | &spec->dig_out, 1) == 1) |
492 | spec->multiout.dig_out_nid = cfg->dig_out_pins[0]; | 492 | spec->multiout.dig_out_nid = spec->dig_out; |
493 | } | 493 | } |
494 | 494 | ||
495 | static int ca0110_parse_auto_config(struct hda_codec *codec) | 495 | static int ca0110_parse_auto_config(struct hda_codec *codec) |
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 488fd9ade1ba..460fb2ef7e39 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c | |||
@@ -65,6 +65,7 @@ struct cs_spec { | |||
65 | 65 | ||
66 | /* available models */ | 66 | /* available models */ |
67 | enum { | 67 | enum { |
68 | CS420X_MBP53, | ||
68 | CS420X_MBP55, | 69 | CS420X_MBP55, |
69 | CS420X_IMAC27, | 70 | CS420X_IMAC27, |
70 | CS420X_AUTO, | 71 | CS420X_AUTO, |
@@ -329,12 +330,12 @@ static int is_ext_mic(struct hda_codec *codec, unsigned int idx) | |||
329 | { | 330 | { |
330 | struct cs_spec *spec = codec->spec; | 331 | struct cs_spec *spec = codec->spec; |
331 | struct auto_pin_cfg *cfg = &spec->autocfg; | 332 | struct auto_pin_cfg *cfg = &spec->autocfg; |
332 | hda_nid_t pin = cfg->input_pins[idx]; | 333 | hda_nid_t pin = cfg->inputs[idx].pin; |
333 | unsigned int val = snd_hda_query_pin_caps(codec, pin); | 334 | unsigned int val = snd_hda_query_pin_caps(codec, pin); |
334 | if (!(val & AC_PINCAP_PRES_DETECT)) | 335 | if (!(val & AC_PINCAP_PRES_DETECT)) |
335 | return 0; | 336 | return 0; |
336 | val = snd_hda_codec_get_pincfg(codec, pin); | 337 | val = snd_hda_codec_get_pincfg(codec, pin); |
337 | return (get_defcfg_connect(val) == AC_JACK_PORT_COMPLEX); | 338 | return (snd_hda_get_input_pin_attr(val) != INPUT_PIN_ATTR_INT); |
338 | } | 339 | } |
339 | 340 | ||
340 | static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin, | 341 | static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin, |
@@ -424,10 +425,8 @@ static int parse_input(struct hda_codec *codec) | |||
424 | struct auto_pin_cfg *cfg = &spec->autocfg; | 425 | struct auto_pin_cfg *cfg = &spec->autocfg; |
425 | int i; | 426 | int i; |
426 | 427 | ||
427 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 428 | for (i = 0; i < cfg->num_inputs; i++) { |
428 | hda_nid_t pin = cfg->input_pins[i]; | 429 | hda_nid_t pin = cfg->inputs[i].pin; |
429 | if (!pin) | ||
430 | continue; | ||
431 | spec->input_idx[spec->num_inputs] = i; | 430 | spec->input_idx[spec->num_inputs] = i; |
432 | spec->capsrc_idx[i] = spec->num_inputs++; | 431 | spec->capsrc_idx[i] = spec->num_inputs++; |
433 | spec->cur_input = i; | 432 | spec->cur_input = i; |
@@ -438,16 +437,17 @@ static int parse_input(struct hda_codec *codec) | |||
438 | 437 | ||
439 | /* check whether the automatic mic switch is available */ | 438 | /* check whether the automatic mic switch is available */ |
440 | if (spec->num_inputs == 2 && | 439 | if (spec->num_inputs == 2 && |
441 | spec->adc_nid[AUTO_PIN_MIC] && spec->adc_nid[AUTO_PIN_FRONT_MIC]) { | 440 | cfg->inputs[0].type == AUTO_PIN_MIC && |
442 | if (is_ext_mic(codec, cfg->input_pins[AUTO_PIN_FRONT_MIC])) { | 441 | cfg->inputs[1].type == AUTO_PIN_MIC) { |
443 | if (!is_ext_mic(codec, cfg->input_pins[AUTO_PIN_MIC])) { | 442 | if (is_ext_mic(codec, cfg->inputs[0].pin)) { |
443 | if (!is_ext_mic(codec, cfg->inputs[1].pin)) { | ||
444 | spec->mic_detect = 1; | 444 | spec->mic_detect = 1; |
445 | spec->automic_idx = AUTO_PIN_FRONT_MIC; | 445 | spec->automic_idx = 0; |
446 | } | 446 | } |
447 | } else { | 447 | } else { |
448 | if (is_ext_mic(codec, cfg->input_pins[AUTO_PIN_MIC])) { | 448 | if (is_ext_mic(codec, cfg->inputs[1].pin)) { |
449 | spec->mic_detect = 1; | 449 | spec->mic_detect = 1; |
450 | spec->automic_idx = AUTO_PIN_MIC; | 450 | spec->automic_idx = 1; |
451 | } | 451 | } |
452 | } | 452 | } |
453 | } | 453 | } |
@@ -674,6 +674,7 @@ static int cs_capture_source_info(struct snd_kcontrol *kcontrol, | |||
674 | { | 674 | { |
675 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 675 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
676 | struct cs_spec *spec = codec->spec; | 676 | struct cs_spec *spec = codec->spec; |
677 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
677 | unsigned int idx; | 678 | unsigned int idx; |
678 | 679 | ||
679 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 680 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
@@ -682,7 +683,8 @@ static int cs_capture_source_info(struct snd_kcontrol *kcontrol, | |||
682 | if (uinfo->value.enumerated.item >= spec->num_inputs) | 683 | if (uinfo->value.enumerated.item >= spec->num_inputs) |
683 | uinfo->value.enumerated.item = spec->num_inputs - 1; | 684 | uinfo->value.enumerated.item = spec->num_inputs - 1; |
684 | idx = spec->input_idx[uinfo->value.enumerated.item]; | 685 | idx = spec->input_idx[uinfo->value.enumerated.item]; |
685 | strcpy(uinfo->value.enumerated.name, auto_pin_cfg_labels[idx]); | 686 | strcpy(uinfo->value.enumerated.name, |
687 | hda_get_input_pin_label(codec, cfg->inputs[idx].pin, 1)); | ||
686 | return 0; | 688 | return 0; |
687 | } | 689 | } |
688 | 690 | ||
@@ -740,6 +742,27 @@ static struct hda_bind_ctls *make_bind_capture(struct hda_codec *codec, | |||
740 | return bind; | 742 | return bind; |
741 | } | 743 | } |
742 | 744 | ||
745 | /* add a (input-boost) volume control to the given input pin */ | ||
746 | static int add_input_volume_control(struct hda_codec *codec, | ||
747 | struct auto_pin_cfg *cfg, | ||
748 | int item) | ||
749 | { | ||
750 | hda_nid_t pin = cfg->inputs[item].pin; | ||
751 | u32 caps; | ||
752 | const char *label; | ||
753 | struct snd_kcontrol *kctl; | ||
754 | |||
755 | if (!(get_wcaps(codec, pin) & AC_WCAP_IN_AMP)) | ||
756 | return 0; | ||
757 | caps = query_amp_caps(codec, pin, HDA_INPUT); | ||
758 | caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; | ||
759 | if (caps <= 1) | ||
760 | return 0; | ||
761 | label = hda_get_autocfg_input_label(codec, cfg, item); | ||
762 | return add_volume(codec, label, 0, | ||
763 | HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_INPUT), 1, &kctl); | ||
764 | } | ||
765 | |||
743 | static int build_input(struct hda_codec *codec) | 766 | static int build_input(struct hda_codec *codec) |
744 | { | 767 | { |
745 | struct cs_spec *spec = codec->spec; | 768 | struct cs_spec *spec = codec->spec; |
@@ -779,6 +802,12 @@ static int build_input(struct hda_codec *codec) | |||
779 | return err; | 802 | return err; |
780 | } | 803 | } |
781 | 804 | ||
805 | for (i = 0; i < spec->num_inputs; i++) { | ||
806 | err = add_input_volume_control(codec, &spec->autocfg, i); | ||
807 | if (err < 0) | ||
808 | return err; | ||
809 | } | ||
810 | |||
782 | return 0; | 811 | return 0; |
783 | } | 812 | } |
784 | 813 | ||
@@ -838,7 +867,8 @@ static void cs_automute(struct hda_codec *codec) | |||
838 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 867 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
839 | hp_present ? 0 : PIN_OUT); | 868 | hp_present ? 0 : PIN_OUT); |
840 | } | 869 | } |
841 | if (spec->board_config == CS420X_MBP55 || | 870 | if (spec->board_config == CS420X_MBP53 || |
871 | spec->board_config == CS420X_MBP55 || | ||
842 | spec->board_config == CS420X_IMAC27) { | 872 | spec->board_config == CS420X_IMAC27) { |
843 | unsigned int gpio = hp_present ? 0x02 : 0x08; | 873 | unsigned int gpio = hp_present ? 0x02 : 0x08; |
844 | snd_hda_codec_write(codec, 0x01, 0, | 874 | snd_hda_codec_write(codec, 0x01, 0, |
@@ -853,15 +883,12 @@ static void cs_automic(struct hda_codec *codec) | |||
853 | hda_nid_t nid; | 883 | hda_nid_t nid; |
854 | unsigned int present; | 884 | unsigned int present; |
855 | 885 | ||
856 | nid = cfg->input_pins[spec->automic_idx]; | 886 | nid = cfg->inputs[spec->automic_idx].pin; |
857 | present = snd_hda_jack_detect(codec, nid); | 887 | present = snd_hda_jack_detect(codec, nid); |
858 | if (present) | 888 | if (present) |
859 | change_cur_input(codec, spec->automic_idx, 0); | 889 | change_cur_input(codec, spec->automic_idx, 0); |
860 | else { | 890 | else |
861 | unsigned int imic = (spec->automic_idx == AUTO_PIN_MIC) ? | 891 | change_cur_input(codec, !spec->automic_idx, 0); |
862 | AUTO_PIN_FRONT_MIC : AUTO_PIN_MIC; | ||
863 | change_cur_input(codec, imic, 0); | ||
864 | } | ||
865 | } | 892 | } |
866 | 893 | ||
867 | /* | 894 | /* |
@@ -918,14 +945,14 @@ static void init_input(struct hda_codec *codec) | |||
918 | unsigned int coef; | 945 | unsigned int coef; |
919 | int i; | 946 | int i; |
920 | 947 | ||
921 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 948 | for (i = 0; i < cfg->num_inputs; i++) { |
922 | unsigned int ctl; | 949 | unsigned int ctl; |
923 | hda_nid_t pin = cfg->input_pins[i]; | 950 | hda_nid_t pin = cfg->inputs[i].pin; |
924 | if (!pin || !spec->adc_nid[i]) | 951 | if (!spec->adc_nid[i]) |
925 | continue; | 952 | continue; |
926 | /* set appropriate pin control and mute first */ | 953 | /* set appropriate pin control and mute first */ |
927 | ctl = PIN_IN; | 954 | ctl = PIN_IN; |
928 | if (i <= AUTO_PIN_FRONT_MIC) { | 955 | if (cfg->inputs[i].type == AUTO_PIN_MIC) { |
929 | unsigned int caps = snd_hda_query_pin_caps(codec, pin); | 956 | unsigned int caps = snd_hda_query_pin_caps(codec, pin); |
930 | caps >>= AC_PINCAP_VREF_SHIFT; | 957 | caps >>= AC_PINCAP_VREF_SHIFT; |
931 | if (caps & AC_PINCAP_VREF_80) | 958 | if (caps & AC_PINCAP_VREF_80) |
@@ -1130,6 +1157,7 @@ static int cs_parse_auto_config(struct hda_codec *codec) | |||
1130 | } | 1157 | } |
1131 | 1158 | ||
1132 | static const char *cs420x_models[CS420X_MODELS] = { | 1159 | static const char *cs420x_models[CS420X_MODELS] = { |
1160 | [CS420X_MBP53] = "mbp53", | ||
1133 | [CS420X_MBP55] = "mbp55", | 1161 | [CS420X_MBP55] = "mbp55", |
1134 | [CS420X_IMAC27] = "imac27", | 1162 | [CS420X_IMAC27] = "imac27", |
1135 | [CS420X_AUTO] = "auto", | 1163 | [CS420X_AUTO] = "auto", |
@@ -1137,7 +1165,9 @@ static const char *cs420x_models[CS420X_MODELS] = { | |||
1137 | 1165 | ||
1138 | 1166 | ||
1139 | static struct snd_pci_quirk cs420x_cfg_tbl[] = { | 1167 | static struct snd_pci_quirk cs420x_cfg_tbl[] = { |
1168 | SND_PCI_QUIRK(0x10de, 0x0ac0, "MacBookPro 5,3", CS420X_MBP53), | ||
1140 | SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55), | 1169 | SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55), |
1170 | SND_PCI_QUIRK(0x10de, 0xcb89, "MacBookPro 7,1", CS420X_MBP55), | ||
1141 | SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27), | 1171 | SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27), |
1142 | {} /* terminator */ | 1172 | {} /* terminator */ |
1143 | }; | 1173 | }; |
@@ -1147,6 +1177,20 @@ struct cs_pincfg { | |||
1147 | u32 val; | 1177 | u32 val; |
1148 | }; | 1178 | }; |
1149 | 1179 | ||
1180 | static struct cs_pincfg mbp53_pincfgs[] = { | ||
1181 | { 0x09, 0x012b4050 }, | ||
1182 | { 0x0a, 0x90100141 }, | ||
1183 | { 0x0b, 0x90100140 }, | ||
1184 | { 0x0c, 0x018b3020 }, | ||
1185 | { 0x0d, 0x90a00110 }, | ||
1186 | { 0x0e, 0x400000f0 }, | ||
1187 | { 0x0f, 0x01cbe030 }, | ||
1188 | { 0x10, 0x014be060 }, | ||
1189 | { 0x12, 0x400000f0 }, | ||
1190 | { 0x15, 0x400000f0 }, | ||
1191 | {} /* terminator */ | ||
1192 | }; | ||
1193 | |||
1150 | static struct cs_pincfg mbp55_pincfgs[] = { | 1194 | static struct cs_pincfg mbp55_pincfgs[] = { |
1151 | { 0x09, 0x012b4030 }, | 1195 | { 0x09, 0x012b4030 }, |
1152 | { 0x0a, 0x90100121 }, | 1196 | { 0x0a, 0x90100121 }, |
@@ -1176,6 +1220,7 @@ static struct cs_pincfg imac27_pincfgs[] = { | |||
1176 | }; | 1220 | }; |
1177 | 1221 | ||
1178 | static struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = { | 1222 | static struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = { |
1223 | [CS420X_MBP53] = mbp53_pincfgs, | ||
1179 | [CS420X_MBP55] = mbp55_pincfgs, | 1224 | [CS420X_MBP55] = mbp55_pincfgs, |
1180 | [CS420X_IMAC27] = imac27_pincfgs, | 1225 | [CS420X_IMAC27] = imac27_pincfgs, |
1181 | }; | 1226 | }; |
@@ -1208,6 +1253,7 @@ static int patch_cs420x(struct hda_codec *codec) | |||
1208 | 1253 | ||
1209 | switch (spec->board_config) { | 1254 | switch (spec->board_config) { |
1210 | case CS420X_IMAC27: | 1255 | case CS420X_IMAC27: |
1256 | case CS420X_MBP53: | ||
1211 | case CS420X_MBP55: | 1257 | case CS420X_MBP55: |
1212 | /* GPIO1 = headphones */ | 1258 | /* GPIO1 = headphones */ |
1213 | /* GPIO3 = speakers */ | 1259 | /* GPIO3 = speakers */ |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 972e7c453b3d..6361f752b5f3 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -57,6 +57,12 @@ struct conexant_jack { | |||
57 | 57 | ||
58 | }; | 58 | }; |
59 | 59 | ||
60 | struct pin_dac_pair { | ||
61 | hda_nid_t pin; | ||
62 | hda_nid_t dac; | ||
63 | int type; | ||
64 | }; | ||
65 | |||
60 | struct conexant_spec { | 66 | struct conexant_spec { |
61 | 67 | ||
62 | struct snd_kcontrol_new *mixers[5]; | 68 | struct snd_kcontrol_new *mixers[5]; |
@@ -77,6 +83,7 @@ struct conexant_spec { | |||
77 | unsigned int cur_eapd; | 83 | unsigned int cur_eapd; |
78 | unsigned int hp_present; | 84 | unsigned int hp_present; |
79 | unsigned int auto_mic; | 85 | unsigned int auto_mic; |
86 | int auto_mic_ext; /* autocfg.inputs[] index for ext mic */ | ||
80 | unsigned int need_dac_fix; | 87 | unsigned int need_dac_fix; |
81 | 88 | ||
82 | /* capture */ | 89 | /* capture */ |
@@ -110,9 +117,12 @@ struct conexant_spec { | |||
110 | struct auto_pin_cfg autocfg; | 117 | struct auto_pin_cfg autocfg; |
111 | struct hda_input_mux private_imux; | 118 | struct hda_input_mux private_imux; |
112 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; | 119 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; |
120 | struct pin_dac_pair dac_info[8]; | ||
121 | int dac_info_filled; | ||
113 | 122 | ||
114 | unsigned int dell_automute; | ||
115 | unsigned int port_d_mode; | 123 | unsigned int port_d_mode; |
124 | unsigned int auto_mute:1; /* used in auto-parser */ | ||
125 | unsigned int dell_automute:1; | ||
116 | unsigned int dell_vostro:1; | 126 | unsigned int dell_vostro:1; |
117 | unsigned int ideapad:1; | 127 | unsigned int ideapad:1; |
118 | unsigned int thinkpad:1; | 128 | unsigned int thinkpad:1; |
@@ -3065,7 +3075,7 @@ enum { | |||
3065 | CXT5066_LAPTOP, /* Laptops w/ EAPD support */ | 3075 | CXT5066_LAPTOP, /* Laptops w/ EAPD support */ |
3066 | CXT5066_DELL_LAPTOP, /* Dell Laptop */ | 3076 | CXT5066_DELL_LAPTOP, /* Dell Laptop */ |
3067 | CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */ | 3077 | CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */ |
3068 | CXT5066_DELL_VOSTO, /* Dell Vostro 1015i */ | 3078 | CXT5066_DELL_VOSTRO, /* Dell Vostro 1015i */ |
3069 | CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */ | 3079 | CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */ |
3070 | CXT5066_THINKPAD, /* Lenovo ThinkPad T410s, others? */ | 3080 | CXT5066_THINKPAD, /* Lenovo ThinkPad T410s, others? */ |
3071 | CXT5066_HP_LAPTOP, /* HP Laptop */ | 3081 | CXT5066_HP_LAPTOP, /* HP Laptop */ |
@@ -3076,25 +3086,26 @@ static const char *cxt5066_models[CXT5066_MODELS] = { | |||
3076 | [CXT5066_LAPTOP] = "laptop", | 3086 | [CXT5066_LAPTOP] = "laptop", |
3077 | [CXT5066_DELL_LAPTOP] = "dell-laptop", | 3087 | [CXT5066_DELL_LAPTOP] = "dell-laptop", |
3078 | [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5", | 3088 | [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5", |
3079 | [CXT5066_DELL_VOSTO] = "dell-vostro", | 3089 | [CXT5066_DELL_VOSTRO] = "dell-vostro", |
3080 | [CXT5066_IDEAPAD] = "ideapad", | 3090 | [CXT5066_IDEAPAD] = "ideapad", |
3081 | [CXT5066_THINKPAD] = "thinkpad", | 3091 | [CXT5066_THINKPAD] = "thinkpad", |
3082 | [CXT5066_HP_LAPTOP] = "hp-laptop", | 3092 | [CXT5066_HP_LAPTOP] = "hp-laptop", |
3083 | }; | 3093 | }; |
3084 | 3094 | ||
3085 | static struct snd_pci_quirk cxt5066_cfg_tbl[] = { | 3095 | static struct snd_pci_quirk cxt5066_cfg_tbl[] = { |
3086 | SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", | 3096 | SND_PCI_QUIRK_MASK(0x1025, 0xff00, 0x0400, "Acer", CXT5066_IDEAPAD), |
3087 | CXT5066_LAPTOP), | 3097 | SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO), |
3088 | SND_PCI_QUIRK(0x1028, 0x02f5, "Dell", | 3098 | SND_PCI_QUIRK(0x1028, 0x02f5, "Dell", |
3089 | CXT5066_DELL_LAPTOP), | 3099 | CXT5066_DELL_LAPTOP), |
3090 | SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), | 3100 | SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTRO), |
3091 | SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTO), | ||
3092 | SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO), | ||
3093 | SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), | 3101 | SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), |
3094 | SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP), | 3102 | SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP), |
3095 | SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD), | 3103 | SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD), |
3096 | SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), | 3104 | SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), |
3097 | SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5), | 3105 | SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5), |
3106 | SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", | ||
3107 | CXT5066_LAPTOP), | ||
3108 | SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), | ||
3098 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), | 3109 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), |
3099 | SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD), | 3110 | SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD), |
3100 | SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD), | 3111 | SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD), |
@@ -3196,7 +3207,7 @@ static int patch_cxt5066(struct hda_codec *codec) | |||
3196 | spec->capture_prepare = cxt5066_olpc_capture_prepare; | 3207 | spec->capture_prepare = cxt5066_olpc_capture_prepare; |
3197 | spec->capture_cleanup = cxt5066_olpc_capture_cleanup; | 3208 | spec->capture_cleanup = cxt5066_olpc_capture_cleanup; |
3198 | break; | 3209 | break; |
3199 | case CXT5066_DELL_VOSTO: | 3210 | case CXT5066_DELL_VOSTRO: |
3200 | codec->patch_ops.init = cxt5066_init; | 3211 | codec->patch_ops.init = cxt5066_init; |
3201 | codec->patch_ops.unsol_event = cxt5066_vostro_event; | 3212 | codec->patch_ops.unsol_event = cxt5066_vostro_event; |
3202 | spec->init_verbs[0] = cxt5066_init_verbs_vostro; | 3213 | spec->init_verbs[0] = cxt5066_init_verbs_vostro; |
@@ -3254,6 +3265,604 @@ static int patch_cxt5066(struct hda_codec *codec) | |||
3254 | } | 3265 | } |
3255 | 3266 | ||
3256 | /* | 3267 | /* |
3268 | * Automatic parser for CX20641 & co | ||
3269 | */ | ||
3270 | |||
3271 | static hda_nid_t cx_auto_adc_nids[] = { 0x14 }; | ||
3272 | |||
3273 | /* get the connection index of @nid in the widget @mux */ | ||
3274 | static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, | ||
3275 | hda_nid_t nid) | ||
3276 | { | ||
3277 | hda_nid_t conn[HDA_MAX_NUM_INPUTS]; | ||
3278 | int i, nums; | ||
3279 | |||
3280 | nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn)); | ||
3281 | for (i = 0; i < nums; i++) | ||
3282 | if (conn[i] == nid) | ||
3283 | return i; | ||
3284 | return -1; | ||
3285 | } | ||
3286 | |||
3287 | /* get an unassigned DAC from the given list. | ||
3288 | * Return the nid if found and reduce the DAC list, or return zero if | ||
3289 | * not found | ||
3290 | */ | ||
3291 | static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t pin, | ||
3292 | hda_nid_t *dacs, int *num_dacs) | ||
3293 | { | ||
3294 | int i, nums = *num_dacs; | ||
3295 | hda_nid_t ret = 0; | ||
3296 | |||
3297 | for (i = 0; i < nums; i++) { | ||
3298 | if (get_connection_index(codec, pin, dacs[i]) >= 0) { | ||
3299 | ret = dacs[i]; | ||
3300 | break; | ||
3301 | } | ||
3302 | } | ||
3303 | if (!ret) | ||
3304 | return 0; | ||
3305 | if (--nums > 0) | ||
3306 | memmove(dacs, dacs + 1, nums * sizeof(hda_nid_t)); | ||
3307 | *num_dacs = nums; | ||
3308 | return ret; | ||
3309 | } | ||
3310 | |||
3311 | #define MAX_AUTO_DACS 5 | ||
3312 | |||
3313 | /* fill analog DAC list from the widget tree */ | ||
3314 | static int fill_cx_auto_dacs(struct hda_codec *codec, hda_nid_t *dacs) | ||
3315 | { | ||
3316 | hda_nid_t nid, end_nid; | ||
3317 | int nums = 0; | ||
3318 | |||
3319 | end_nid = codec->start_nid + codec->num_nodes; | ||
3320 | for (nid = codec->start_nid; nid < end_nid; nid++) { | ||
3321 | unsigned int wcaps = get_wcaps(codec, nid); | ||
3322 | unsigned int type = get_wcaps_type(wcaps); | ||
3323 | if (type == AC_WID_AUD_OUT && !(wcaps & AC_WCAP_DIGITAL)) { | ||
3324 | dacs[nums++] = nid; | ||
3325 | if (nums >= MAX_AUTO_DACS) | ||
3326 | break; | ||
3327 | } | ||
3328 | } | ||
3329 | return nums; | ||
3330 | } | ||
3331 | |||
3332 | /* fill pin_dac_pair list from the pin and dac list */ | ||
3333 | static int fill_dacs_for_pins(struct hda_codec *codec, hda_nid_t *pins, | ||
3334 | int num_pins, hda_nid_t *dacs, int *rest, | ||
3335 | struct pin_dac_pair *filled, int type) | ||
3336 | { | ||
3337 | int i, nums; | ||
3338 | |||
3339 | nums = 0; | ||
3340 | for (i = 0; i < num_pins; i++) { | ||
3341 | filled[nums].pin = pins[i]; | ||
3342 | filled[nums].type = type; | ||
3343 | filled[nums].dac = get_unassigned_dac(codec, pins[i], dacs, rest); | ||
3344 | nums++; | ||
3345 | } | ||
3346 | return nums; | ||
3347 | } | ||
3348 | |||
3349 | /* parse analog output paths */ | ||
3350 | static void cx_auto_parse_output(struct hda_codec *codec) | ||
3351 | { | ||
3352 | struct conexant_spec *spec = codec->spec; | ||
3353 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
3354 | hda_nid_t dacs[MAX_AUTO_DACS]; | ||
3355 | int i, j, nums, rest; | ||
3356 | |||
3357 | rest = fill_cx_auto_dacs(codec, dacs); | ||
3358 | /* parse all analog output pins */ | ||
3359 | nums = fill_dacs_for_pins(codec, cfg->line_out_pins, cfg->line_outs, | ||
3360 | dacs, &rest, spec->dac_info, | ||
3361 | AUTO_PIN_LINE_OUT); | ||
3362 | nums += fill_dacs_for_pins(codec, cfg->hp_pins, cfg->hp_outs, | ||
3363 | dacs, &rest, spec->dac_info + nums, | ||
3364 | AUTO_PIN_HP_OUT); | ||
3365 | nums += fill_dacs_for_pins(codec, cfg->speaker_pins, cfg->speaker_outs, | ||
3366 | dacs, &rest, spec->dac_info + nums, | ||
3367 | AUTO_PIN_SPEAKER_OUT); | ||
3368 | spec->dac_info_filled = nums; | ||
3369 | /* fill multiout struct */ | ||
3370 | for (i = 0; i < nums; i++) { | ||
3371 | hda_nid_t dac = spec->dac_info[i].dac; | ||
3372 | if (!dac) | ||
3373 | continue; | ||
3374 | switch (spec->dac_info[i].type) { | ||
3375 | case AUTO_PIN_LINE_OUT: | ||
3376 | spec->private_dac_nids[spec->multiout.num_dacs] = dac; | ||
3377 | spec->multiout.num_dacs++; | ||
3378 | break; | ||
3379 | case AUTO_PIN_HP_OUT: | ||
3380 | case AUTO_PIN_SPEAKER_OUT: | ||
3381 | if (!spec->multiout.hp_nid) { | ||
3382 | spec->multiout.hp_nid = dac; | ||
3383 | break; | ||
3384 | } | ||
3385 | for (j = 0; j < ARRAY_SIZE(spec->multiout.extra_out_nid); j++) | ||
3386 | if (!spec->multiout.extra_out_nid[j]) { | ||
3387 | spec->multiout.extra_out_nid[j] = dac; | ||
3388 | break; | ||
3389 | } | ||
3390 | break; | ||
3391 | } | ||
3392 | } | ||
3393 | spec->multiout.dac_nids = spec->private_dac_nids; | ||
3394 | spec->multiout.max_channels = nums * 2; | ||
3395 | |||
3396 | if (cfg->hp_outs > 0) | ||
3397 | spec->auto_mute = 1; | ||
3398 | spec->vmaster_nid = spec->private_dac_nids[0]; | ||
3399 | } | ||
3400 | |||
3401 | /* auto-mute/unmute speaker and line outs according to headphone jack */ | ||
3402 | static void cx_auto_hp_automute(struct hda_codec *codec) | ||
3403 | { | ||
3404 | struct conexant_spec *spec = codec->spec; | ||
3405 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
3406 | int i, present; | ||
3407 | |||
3408 | if (!spec->auto_mute) | ||
3409 | return; | ||
3410 | present = 0; | ||
3411 | for (i = 0; i < cfg->hp_outs; i++) { | ||
3412 | if (snd_hda_jack_detect(codec, cfg->hp_pins[i])) { | ||
3413 | present = 1; | ||
3414 | break; | ||
3415 | } | ||
3416 | } | ||
3417 | for (i = 0; i < cfg->line_outs; i++) { | ||
3418 | snd_hda_codec_write(codec, cfg->line_out_pins[i], 0, | ||
3419 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
3420 | present ? 0 : PIN_OUT); | ||
3421 | } | ||
3422 | for (i = 0; i < cfg->speaker_outs; i++) { | ||
3423 | snd_hda_codec_write(codec, cfg->speaker_pins[i], 0, | ||
3424 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
3425 | present ? 0 : PIN_OUT); | ||
3426 | } | ||
3427 | } | ||
3428 | |||
3429 | /* automatic switch internal and external mic */ | ||
3430 | static void cx_auto_automic(struct hda_codec *codec) | ||
3431 | { | ||
3432 | struct conexant_spec *spec = codec->spec; | ||
3433 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
3434 | struct hda_input_mux *imux = &spec->private_imux; | ||
3435 | int ext_idx = spec->auto_mic_ext; | ||
3436 | |||
3437 | if (!spec->auto_mic) | ||
3438 | return; | ||
3439 | if (snd_hda_jack_detect(codec, cfg->inputs[ext_idx].pin)) { | ||
3440 | snd_hda_codec_write(codec, spec->adc_nids[0], 0, | ||
3441 | AC_VERB_SET_CONNECT_SEL, | ||
3442 | imux->items[ext_idx].index); | ||
3443 | } else { | ||
3444 | snd_hda_codec_write(codec, spec->adc_nids[0], 0, | ||
3445 | AC_VERB_SET_CONNECT_SEL, | ||
3446 | imux->items[!ext_idx].index); | ||
3447 | } | ||
3448 | } | ||
3449 | |||
3450 | static void cx_auto_unsol_event(struct hda_codec *codec, unsigned int res) | ||
3451 | { | ||
3452 | int nid = (res & AC_UNSOL_RES_SUBTAG) >> 20; | ||
3453 | switch (res >> 26) { | ||
3454 | case CONEXANT_HP_EVENT: | ||
3455 | cx_auto_hp_automute(codec); | ||
3456 | conexant_report_jack(codec, nid); | ||
3457 | break; | ||
3458 | case CONEXANT_MIC_EVENT: | ||
3459 | cx_auto_automic(codec); | ||
3460 | conexant_report_jack(codec, nid); | ||
3461 | break; | ||
3462 | } | ||
3463 | } | ||
3464 | |||
3465 | /* return true if it's an internal-mic pin */ | ||
3466 | static int is_int_mic(struct hda_codec *codec, hda_nid_t pin) | ||
3467 | { | ||
3468 | unsigned int def_conf = snd_hda_codec_get_pincfg(codec, pin); | ||
3469 | return get_defcfg_device(def_conf) == AC_JACK_MIC_IN && | ||
3470 | snd_hda_get_input_pin_attr(def_conf) == INPUT_PIN_ATTR_INT; | ||
3471 | } | ||
3472 | |||
3473 | /* return true if it's an external-mic pin */ | ||
3474 | static int is_ext_mic(struct hda_codec *codec, hda_nid_t pin) | ||
3475 | { | ||
3476 | unsigned int def_conf = snd_hda_codec_get_pincfg(codec, pin); | ||
3477 | return get_defcfg_device(def_conf) == AC_JACK_MIC_IN && | ||
3478 | snd_hda_get_input_pin_attr(def_conf) >= INPUT_PIN_ATTR_NORMAL && | ||
3479 | (snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_PRES_DETECT); | ||
3480 | } | ||
3481 | |||
3482 | /* check whether the pin config is suitable for auto-mic switching; | ||
3483 | * auto-mic is enabled only when one int-mic and one-ext mic exist | ||
3484 | */ | ||
3485 | static void cx_auto_check_auto_mic(struct hda_codec *codec) | ||
3486 | { | ||
3487 | struct conexant_spec *spec = codec->spec; | ||
3488 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
3489 | |||
3490 | if (is_ext_mic(codec, cfg->inputs[0].pin) && | ||
3491 | is_int_mic(codec, cfg->inputs[1].pin)) { | ||
3492 | spec->auto_mic = 1; | ||
3493 | spec->auto_mic_ext = 1; | ||
3494 | return; | ||
3495 | } | ||
3496 | if (is_int_mic(codec, cfg->inputs[1].pin) && | ||
3497 | is_ext_mic(codec, cfg->inputs[0].pin)) { | ||
3498 | spec->auto_mic = 1; | ||
3499 | spec->auto_mic_ext = 0; | ||
3500 | return; | ||
3501 | } | ||
3502 | } | ||
3503 | |||
3504 | static void cx_auto_parse_input(struct hda_codec *codec) | ||
3505 | { | ||
3506 | struct conexant_spec *spec = codec->spec; | ||
3507 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
3508 | struct hda_input_mux *imux; | ||
3509 | int i; | ||
3510 | |||
3511 | imux = &spec->private_imux; | ||
3512 | for (i = 0; i < cfg->num_inputs; i++) { | ||
3513 | int idx = get_connection_index(codec, spec->adc_nids[0], | ||
3514 | cfg->inputs[i].pin); | ||
3515 | if (idx >= 0) { | ||
3516 | const char *label; | ||
3517 | label = hda_get_autocfg_input_label(codec, cfg, i); | ||
3518 | snd_hda_add_imux_item(imux, label, idx, NULL); | ||
3519 | } | ||
3520 | } | ||
3521 | if (imux->num_items == 2 && cfg->num_inputs == 2) | ||
3522 | cx_auto_check_auto_mic(codec); | ||
3523 | if (imux->num_items > 1 && !spec->auto_mic) | ||
3524 | spec->input_mux = imux; | ||
3525 | } | ||
3526 | |||
3527 | /* get digital-input audio widget corresponding to the given pin */ | ||
3528 | static hda_nid_t cx_auto_get_dig_in(struct hda_codec *codec, hda_nid_t pin) | ||
3529 | { | ||
3530 | hda_nid_t nid, end_nid; | ||
3531 | |||
3532 | end_nid = codec->start_nid + codec->num_nodes; | ||
3533 | for (nid = codec->start_nid; nid < end_nid; nid++) { | ||
3534 | unsigned int wcaps = get_wcaps(codec, nid); | ||
3535 | unsigned int type = get_wcaps_type(wcaps); | ||
3536 | if (type == AC_WID_AUD_IN && (wcaps & AC_WCAP_DIGITAL)) { | ||
3537 | if (get_connection_index(codec, nid, pin) >= 0) | ||
3538 | return nid; | ||
3539 | } | ||
3540 | } | ||
3541 | return 0; | ||
3542 | } | ||
3543 | |||
3544 | static void cx_auto_parse_digital(struct hda_codec *codec) | ||
3545 | { | ||
3546 | struct conexant_spec *spec = codec->spec; | ||
3547 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
3548 | hda_nid_t nid; | ||
3549 | |||
3550 | if (cfg->dig_outs && | ||
3551 | snd_hda_get_connections(codec, cfg->dig_out_pins[0], &nid, 1) == 1) | ||
3552 | spec->multiout.dig_out_nid = nid; | ||
3553 | if (cfg->dig_in_pin) | ||
3554 | spec->dig_in_nid = cx_auto_get_dig_in(codec, cfg->dig_in_pin); | ||
3555 | } | ||
3556 | |||
3557 | #ifdef CONFIG_SND_HDA_INPUT_BEEP | ||
3558 | static void cx_auto_parse_beep(struct hda_codec *codec) | ||
3559 | { | ||
3560 | struct conexant_spec *spec = codec->spec; | ||
3561 | hda_nid_t nid, end_nid; | ||
3562 | |||
3563 | end_nid = codec->start_nid + codec->num_nodes; | ||
3564 | for (nid = codec->start_nid; nid < end_nid; nid++) | ||
3565 | if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP) { | ||
3566 | set_beep_amp(spec, nid, 0, HDA_OUTPUT); | ||
3567 | break; | ||
3568 | } | ||
3569 | } | ||
3570 | #else | ||
3571 | #define cx_auto_parse_beep(codec) | ||
3572 | #endif | ||
3573 | |||
3574 | static int cx_auto_parse_auto_config(struct hda_codec *codec) | ||
3575 | { | ||
3576 | struct conexant_spec *spec = codec->spec; | ||
3577 | int err; | ||
3578 | |||
3579 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL); | ||
3580 | if (err < 0) | ||
3581 | return err; | ||
3582 | |||
3583 | cx_auto_parse_output(codec); | ||
3584 | cx_auto_parse_input(codec); | ||
3585 | cx_auto_parse_digital(codec); | ||
3586 | cx_auto_parse_beep(codec); | ||
3587 | return 0; | ||
3588 | } | ||
3589 | |||
3590 | static void cx_auto_turn_on_eapd(struct hda_codec *codec, int num_pins, | ||
3591 | hda_nid_t *pins) | ||
3592 | { | ||
3593 | int i; | ||
3594 | for (i = 0; i < num_pins; i++) { | ||
3595 | if (snd_hda_query_pin_caps(codec, pins[i]) & AC_PINCAP_EAPD) | ||
3596 | snd_hda_codec_write(codec, pins[i], 0, | ||
3597 | AC_VERB_SET_EAPD_BTLENABLE, 0x02); | ||
3598 | } | ||
3599 | } | ||
3600 | |||
3601 | static void select_connection(struct hda_codec *codec, hda_nid_t pin, | ||
3602 | hda_nid_t src) | ||
3603 | { | ||
3604 | int idx = get_connection_index(codec, pin, src); | ||
3605 | if (idx >= 0) | ||
3606 | snd_hda_codec_write(codec, pin, 0, | ||
3607 | AC_VERB_SET_CONNECT_SEL, idx); | ||
3608 | } | ||
3609 | |||
3610 | static void cx_auto_init_output(struct hda_codec *codec) | ||
3611 | { | ||
3612 | struct conexant_spec *spec = codec->spec; | ||
3613 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
3614 | hda_nid_t nid; | ||
3615 | int i; | ||
3616 | |||
3617 | for (i = 0; i < spec->multiout.num_dacs; i++) | ||
3618 | snd_hda_codec_write(codec, spec->multiout.dac_nids[i], 0, | ||
3619 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); | ||
3620 | |||
3621 | for (i = 0; i < cfg->hp_outs; i++) | ||
3622 | snd_hda_codec_write(codec, cfg->hp_pins[i], 0, | ||
3623 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP); | ||
3624 | if (spec->auto_mute) { | ||
3625 | for (i = 0; i < cfg->hp_outs; i++) { | ||
3626 | snd_hda_codec_write(codec, cfg->hp_pins[i], 0, | ||
3627 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
3628 | AC_USRSP_EN | CONEXANT_HP_EVENT); | ||
3629 | } | ||
3630 | cx_auto_hp_automute(codec); | ||
3631 | } else { | ||
3632 | for (i = 0; i < cfg->line_outs; i++) | ||
3633 | snd_hda_codec_write(codec, cfg->line_out_pins[i], 0, | ||
3634 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | ||
3635 | for (i = 0; i < cfg->speaker_outs; i++) | ||
3636 | snd_hda_codec_write(codec, cfg->speaker_pins[i], 0, | ||
3637 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | ||
3638 | } | ||
3639 | |||
3640 | for (i = 0; i < spec->dac_info_filled; i++) { | ||
3641 | nid = spec->dac_info[i].dac; | ||
3642 | if (!nid) | ||
3643 | nid = spec->multiout.dac_nids[0]; | ||
3644 | select_connection(codec, spec->dac_info[i].pin, nid); | ||
3645 | } | ||
3646 | |||
3647 | /* turn on EAPD */ | ||
3648 | cx_auto_turn_on_eapd(codec, cfg->line_outs, cfg->line_out_pins); | ||
3649 | cx_auto_turn_on_eapd(codec, cfg->hp_outs, cfg->hp_pins); | ||
3650 | cx_auto_turn_on_eapd(codec, cfg->speaker_outs, cfg->speaker_pins); | ||
3651 | } | ||
3652 | |||
3653 | static void cx_auto_init_input(struct hda_codec *codec) | ||
3654 | { | ||
3655 | struct conexant_spec *spec = codec->spec; | ||
3656 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
3657 | int i; | ||
3658 | |||
3659 | for (i = 0; i < spec->num_adc_nids; i++) | ||
3660 | snd_hda_codec_write(codec, spec->adc_nids[i], 0, | ||
3661 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)); | ||
3662 | |||
3663 | for (i = 0; i < cfg->num_inputs; i++) { | ||
3664 | unsigned int type; | ||
3665 | if (cfg->inputs[i].type == AUTO_PIN_MIC) | ||
3666 | type = PIN_VREF80; | ||
3667 | else | ||
3668 | type = PIN_IN; | ||
3669 | snd_hda_codec_write(codec, cfg->inputs[i].pin, 0, | ||
3670 | AC_VERB_SET_PIN_WIDGET_CONTROL, type); | ||
3671 | } | ||
3672 | |||
3673 | if (spec->auto_mic) { | ||
3674 | int ext_idx = spec->auto_mic_ext; | ||
3675 | snd_hda_codec_write(codec, cfg->inputs[ext_idx].pin, 0, | ||
3676 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
3677 | AC_USRSP_EN | CONEXANT_MIC_EVENT); | ||
3678 | cx_auto_automic(codec); | ||
3679 | } else { | ||
3680 | for (i = 0; i < spec->num_adc_nids; i++) { | ||
3681 | snd_hda_codec_write(codec, spec->adc_nids[i], 0, | ||
3682 | AC_VERB_SET_CONNECT_SEL, | ||
3683 | spec->private_imux.items[0].index); | ||
3684 | } | ||
3685 | } | ||
3686 | } | ||
3687 | |||
3688 | static void cx_auto_init_digital(struct hda_codec *codec) | ||
3689 | { | ||
3690 | struct conexant_spec *spec = codec->spec; | ||
3691 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
3692 | |||
3693 | if (spec->multiout.dig_out_nid) | ||
3694 | snd_hda_codec_write(codec, cfg->dig_out_pins[0], 0, | ||
3695 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | ||
3696 | if (spec->dig_in_nid) | ||
3697 | snd_hda_codec_write(codec, cfg->dig_in_pin, 0, | ||
3698 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN); | ||
3699 | } | ||
3700 | |||
3701 | static int cx_auto_init(struct hda_codec *codec) | ||
3702 | { | ||
3703 | /*snd_hda_sequence_write(codec, cx_auto_init_verbs);*/ | ||
3704 | cx_auto_init_output(codec); | ||
3705 | cx_auto_init_input(codec); | ||
3706 | cx_auto_init_digital(codec); | ||
3707 | return 0; | ||
3708 | } | ||
3709 | |||
3710 | static int cx_auto_add_volume(struct hda_codec *codec, const char *basename, | ||
3711 | const char *dir, int cidx, | ||
3712 | hda_nid_t nid, int hda_dir) | ||
3713 | { | ||
3714 | static char name[32]; | ||
3715 | static struct snd_kcontrol_new knew[] = { | ||
3716 | HDA_CODEC_VOLUME(name, 0, 0, 0), | ||
3717 | HDA_CODEC_MUTE(name, 0, 0, 0), | ||
3718 | }; | ||
3719 | static char *sfx[2] = { "Volume", "Switch" }; | ||
3720 | int i, err; | ||
3721 | |||
3722 | for (i = 0; i < 2; i++) { | ||
3723 | struct snd_kcontrol *kctl; | ||
3724 | knew[i].private_value = HDA_COMPOSE_AMP_VAL(nid, 3, 0, hda_dir); | ||
3725 | knew[i].subdevice = HDA_SUBDEV_AMP_FLAG; | ||
3726 | knew[i].index = cidx; | ||
3727 | snprintf(name, sizeof(name), "%s%s %s", basename, dir, sfx[i]); | ||
3728 | kctl = snd_ctl_new1(&knew[i], codec); | ||
3729 | if (!kctl) | ||
3730 | return -ENOMEM; | ||
3731 | err = snd_hda_ctl_add(codec, nid, kctl); | ||
3732 | if (err < 0) | ||
3733 | return err; | ||
3734 | if (!(query_amp_caps(codec, nid, hda_dir) & AC_AMPCAP_MUTE)) | ||
3735 | break; | ||
3736 | } | ||
3737 | return 0; | ||
3738 | } | ||
3739 | |||
3740 | #define cx_auto_add_pb_volume(codec, nid, str, idx) \ | ||
3741 | cx_auto_add_volume(codec, str, " Playback", idx, nid, HDA_OUTPUT) | ||
3742 | |||
3743 | static int cx_auto_build_output_controls(struct hda_codec *codec) | ||
3744 | { | ||
3745 | struct conexant_spec *spec = codec->spec; | ||
3746 | int i, err; | ||
3747 | int num_line = 0, num_hp = 0, num_spk = 0; | ||
3748 | static const char *texts[3] = { "Front", "Surround", "CLFE" }; | ||
3749 | |||
3750 | if (spec->dac_info_filled == 1) | ||
3751 | return cx_auto_add_pb_volume(codec, spec->dac_info[0].dac, | ||
3752 | "Master", 0); | ||
3753 | for (i = 0; i < spec->dac_info_filled; i++) { | ||
3754 | const char *label; | ||
3755 | int idx, type; | ||
3756 | if (!spec->dac_info[i].dac) | ||
3757 | continue; | ||
3758 | type = spec->dac_info[i].type; | ||
3759 | if (type == AUTO_PIN_LINE_OUT) | ||
3760 | type = spec->autocfg.line_out_type; | ||
3761 | switch (type) { | ||
3762 | case AUTO_PIN_LINE_OUT: | ||
3763 | default: | ||
3764 | label = texts[num_line++]; | ||
3765 | idx = 0; | ||
3766 | break; | ||
3767 | case AUTO_PIN_HP_OUT: | ||
3768 | label = "Headphone"; | ||
3769 | idx = num_hp++; | ||
3770 | break; | ||
3771 | case AUTO_PIN_SPEAKER_OUT: | ||
3772 | label = "Speaker"; | ||
3773 | idx = num_spk++; | ||
3774 | break; | ||
3775 | } | ||
3776 | err = cx_auto_add_pb_volume(codec, spec->dac_info[i].dac, | ||
3777 | label, idx); | ||
3778 | if (err < 0) | ||
3779 | return err; | ||
3780 | } | ||
3781 | return 0; | ||
3782 | } | ||
3783 | |||
3784 | static int cx_auto_build_input_controls(struct hda_codec *codec) | ||
3785 | { | ||
3786 | struct conexant_spec *spec = codec->spec; | ||
3787 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
3788 | static const char *prev_label; | ||
3789 | int i, err, cidx; | ||
3790 | |||
3791 | err = cx_auto_add_volume(codec, "Capture", "", 0, spec->adc_nids[0], | ||
3792 | HDA_INPUT); | ||
3793 | if (err < 0) | ||
3794 | return err; | ||
3795 | prev_label = NULL; | ||
3796 | cidx = 0; | ||
3797 | for (i = 0; i < cfg->num_inputs; i++) { | ||
3798 | hda_nid_t nid = cfg->inputs[i].pin; | ||
3799 | const char *label; | ||
3800 | if (!(get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) | ||
3801 | continue; | ||
3802 | label = hda_get_autocfg_input_label(codec, cfg, i); | ||
3803 | if (label == prev_label) | ||
3804 | cidx++; | ||
3805 | else | ||
3806 | cidx = 0; | ||
3807 | prev_label = label; | ||
3808 | err = cx_auto_add_volume(codec, label, " Capture", cidx, | ||
3809 | nid, HDA_INPUT); | ||
3810 | if (err < 0) | ||
3811 | return err; | ||
3812 | } | ||
3813 | return 0; | ||
3814 | } | ||
3815 | |||
3816 | static int cx_auto_build_controls(struct hda_codec *codec) | ||
3817 | { | ||
3818 | int err; | ||
3819 | |||
3820 | err = cx_auto_build_output_controls(codec); | ||
3821 | if (err < 0) | ||
3822 | return err; | ||
3823 | err = cx_auto_build_input_controls(codec); | ||
3824 | if (err < 0) | ||
3825 | return err; | ||
3826 | return conexant_build_controls(codec); | ||
3827 | } | ||
3828 | |||
3829 | static struct hda_codec_ops cx_auto_patch_ops = { | ||
3830 | .build_controls = cx_auto_build_controls, | ||
3831 | .build_pcms = conexant_build_pcms, | ||
3832 | .init = cx_auto_init, | ||
3833 | .free = conexant_free, | ||
3834 | .unsol_event = cx_auto_unsol_event, | ||
3835 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
3836 | .suspend = conexant_suspend, | ||
3837 | #endif | ||
3838 | .reboot_notify = snd_hda_shutup_pins, | ||
3839 | }; | ||
3840 | |||
3841 | static int patch_conexant_auto(struct hda_codec *codec) | ||
3842 | { | ||
3843 | struct conexant_spec *spec; | ||
3844 | int err; | ||
3845 | |||
3846 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
3847 | if (!spec) | ||
3848 | return -ENOMEM; | ||
3849 | codec->spec = spec; | ||
3850 | spec->adc_nids = cx_auto_adc_nids; | ||
3851 | spec->num_adc_nids = ARRAY_SIZE(cx_auto_adc_nids); | ||
3852 | spec->capsrc_nids = spec->adc_nids; | ||
3853 | err = cx_auto_parse_auto_config(codec); | ||
3854 | if (err < 0) { | ||
3855 | kfree(codec->spec); | ||
3856 | codec->spec = NULL; | ||
3857 | return err; | ||
3858 | } | ||
3859 | codec->patch_ops = cx_auto_patch_ops; | ||
3860 | if (spec->beep_amp) | ||
3861 | snd_hda_attach_beep_device(codec, spec->beep_amp); | ||
3862 | return 0; | ||
3863 | } | ||
3864 | |||
3865 | /* | ||
3257 | */ | 3866 | */ |
3258 | 3867 | ||
3259 | static struct hda_codec_preset snd_hda_preset_conexant[] = { | 3868 | static struct hda_codec_preset snd_hda_preset_conexant[] = { |
@@ -3271,6 +3880,22 @@ static struct hda_codec_preset snd_hda_preset_conexant[] = { | |||
3271 | .patch = patch_cxt5066 }, | 3880 | .patch = patch_cxt5066 }, |
3272 | { .id = 0x14f15069, .name = "CX20585", | 3881 | { .id = 0x14f15069, .name = "CX20585", |
3273 | .patch = patch_cxt5066 }, | 3882 | .patch = patch_cxt5066 }, |
3883 | { .id = 0x14f15097, .name = "CX20631", | ||
3884 | .patch = patch_conexant_auto }, | ||
3885 | { .id = 0x14f15098, .name = "CX20632", | ||
3886 | .patch = patch_conexant_auto }, | ||
3887 | { .id = 0x14f150a1, .name = "CX20641", | ||
3888 | .patch = patch_conexant_auto }, | ||
3889 | { .id = 0x14f150a2, .name = "CX20642", | ||
3890 | .patch = patch_conexant_auto }, | ||
3891 | { .id = 0x14f150ab, .name = "CX20651", | ||
3892 | .patch = patch_conexant_auto }, | ||
3893 | { .id = 0x14f150ac, .name = "CX20652", | ||
3894 | .patch = patch_conexant_auto }, | ||
3895 | { .id = 0x14f150b8, .name = "CX20664", | ||
3896 | .patch = patch_conexant_auto }, | ||
3897 | { .id = 0x14f150b9, .name = "CX20665", | ||
3898 | .patch = patch_conexant_auto }, | ||
3274 | {} /* terminator */ | 3899 | {} /* terminator */ |
3275 | }; | 3900 | }; |
3276 | 3901 | ||
@@ -3281,6 +3906,14 @@ MODULE_ALIAS("snd-hda-codec-id:14f15066"); | |||
3281 | MODULE_ALIAS("snd-hda-codec-id:14f15067"); | 3906 | MODULE_ALIAS("snd-hda-codec-id:14f15067"); |
3282 | MODULE_ALIAS("snd-hda-codec-id:14f15068"); | 3907 | MODULE_ALIAS("snd-hda-codec-id:14f15068"); |
3283 | MODULE_ALIAS("snd-hda-codec-id:14f15069"); | 3908 | MODULE_ALIAS("snd-hda-codec-id:14f15069"); |
3909 | MODULE_ALIAS("snd-hda-codec-id:14f15097"); | ||
3910 | MODULE_ALIAS("snd-hda-codec-id:14f15098"); | ||
3911 | MODULE_ALIAS("snd-hda-codec-id:14f150a1"); | ||
3912 | MODULE_ALIAS("snd-hda-codec-id:14f150a2"); | ||
3913 | MODULE_ALIAS("snd-hda-codec-id:14f150ab"); | ||
3914 | MODULE_ALIAS("snd-hda-codec-id:14f150ac"); | ||
3915 | MODULE_ALIAS("snd-hda-codec-id:14f150b8"); | ||
3916 | MODULE_ALIAS("snd-hda-codec-id:14f150b9"); | ||
3284 | 3917 | ||
3285 | MODULE_LICENSE("GPL"); | 3918 | MODULE_LICENSE("GPL"); |
3286 | MODULE_DESCRIPTION("Conexant HD-audio codec"); | 3919 | MODULE_DESCRIPTION("Conexant HD-audio codec"); |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index afd6022a96a7..d3e49aa5b9ec 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -3,6 +3,9 @@ | |||
3 | * patch_hdmi.c - routines for HDMI/DisplayPort codecs | 3 | * patch_hdmi.c - routines for HDMI/DisplayPort codecs |
4 | * | 4 | * |
5 | * Copyright(c) 2008-2010 Intel Corporation. All rights reserved. | 5 | * Copyright(c) 2008-2010 Intel Corporation. All rights reserved. |
6 | * Copyright (c) 2006 ATI Technologies Inc. | ||
7 | * Copyright (c) 2008 NVIDIA Corp. All rights reserved. | ||
8 | * Copyright (c) 2008 Wei Ni <wni@nvidia.com> | ||
6 | * | 9 | * |
7 | * Authors: | 10 | * Authors: |
8 | * Wu Fengguang <wfg@linux.intel.com> | 11 | * Wu Fengguang <wfg@linux.intel.com> |
@@ -25,6 +28,22 @@ | |||
25 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 28 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
26 | */ | 29 | */ |
27 | 30 | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/slab.h> | ||
34 | #include <sound/core.h> | ||
35 | #include "hda_codec.h" | ||
36 | #include "hda_local.h" | ||
37 | |||
38 | /* | ||
39 | * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device | ||
40 | * could support two independent pipes, each of them can be connected to one or | ||
41 | * more ports (DVI, HDMI or DisplayPort). | ||
42 | * | ||
43 | * The HDA correspondence of pipes/ports are converter/pin nodes. | ||
44 | */ | ||
45 | #define MAX_HDMI_CVTS 3 | ||
46 | #define MAX_HDMI_PINS 3 | ||
28 | 47 | ||
29 | struct hdmi_spec { | 48 | struct hdmi_spec { |
30 | int num_cvts; | 49 | int num_cvts; |
@@ -49,10 +68,10 @@ struct hdmi_spec { | |||
49 | struct hda_pcm_stream codec_pcm_pars[MAX_HDMI_CVTS]; | 68 | struct hda_pcm_stream codec_pcm_pars[MAX_HDMI_CVTS]; |
50 | 69 | ||
51 | /* | 70 | /* |
52 | * nvhdmi specific | 71 | * ati/nvhdmi specific |
53 | */ | 72 | */ |
54 | struct hda_multi_out multiout; | 73 | struct hda_multi_out multiout; |
55 | unsigned int codec_type; | 74 | struct hda_pcm_stream *pcm_playback; |
56 | 75 | ||
57 | /* misc flags */ | 76 | /* misc flags */ |
58 | /* PD bit indicates only the update, not the current state */ | 77 | /* PD bit indicates only the update, not the current state */ |
@@ -65,13 +84,25 @@ struct hdmi_audio_infoframe { | |||
65 | u8 ver; /* 0x01 */ | 84 | u8 ver; /* 0x01 */ |
66 | u8 len; /* 0x0a */ | 85 | u8 len; /* 0x0a */ |
67 | 86 | ||
68 | u8 checksum; /* PB0 */ | 87 | u8 checksum; |
88 | |||
69 | u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ | 89 | u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ |
70 | u8 SS01_SF24; | 90 | u8 SS01_SF24; |
71 | u8 CXT04; | 91 | u8 CXT04; |
72 | u8 CA; | 92 | u8 CA; |
73 | u8 LFEPBL01_LSV36_DM_INH7; | 93 | u8 LFEPBL01_LSV36_DM_INH7; |
74 | u8 reserved[5]; /* PB6 - PB10 */ | 94 | }; |
95 | |||
96 | struct dp_audio_infoframe { | ||
97 | u8 type; /* 0x84 */ | ||
98 | u8 len; /* 0x1b */ | ||
99 | u8 ver; /* 0x11 << 2 */ | ||
100 | |||
101 | u8 CC02_CT47; /* match with HDMI infoframe from this on */ | ||
102 | u8 SS01_SF24; | ||
103 | u8 CXT04; | ||
104 | u8 CA; | ||
105 | u8 LFEPBL01_LSV36_DM_INH7; | ||
75 | }; | 106 | }; |
76 | 107 | ||
77 | /* | 108 | /* |
@@ -162,7 +193,7 @@ static int hdmi_channel_mapping[0x32][8] = { | |||
162 | /* 4ch */ | 193 | /* 4ch */ |
163 | [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, | 194 | [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, |
164 | /* surround41 */ | 195 | /* surround41 */ |
165 | [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 }, | 196 | [0x09] = { 0x00, 0x11, 0x24, 0x35, 0x42, 0xf3, 0xf6, 0xf7 }, |
166 | /* surround50 */ | 197 | /* surround50 */ |
167 | [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, | 198 | [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, |
168 | /* surround51 */ | 199 | /* surround51 */ |
@@ -175,7 +206,7 @@ static int hdmi_channel_mapping[0x32][8] = { | |||
175 | * This is an ordered list! | 206 | * This is an ordered list! |
176 | * | 207 | * |
177 | * The preceding ones have better chances to be selected by | 208 | * The preceding ones have better chances to be selected by |
178 | * hdmi_setup_channel_allocation(). | 209 | * hdmi_channel_allocation(). |
179 | */ | 210 | */ |
180 | static struct cea_channel_speaker_allocation channel_allocations[] = { | 211 | static struct cea_channel_speaker_allocation channel_allocations[] = { |
181 | /* channel: 7 6 5 4 3 2 1 0 */ | 212 | /* channel: 7 6 5 4 3 2 1 0 */ |
@@ -352,14 +383,14 @@ static void init_channel_allocations(void) | |||
352 | * | 383 | * |
353 | * TODO: it could select the wrong CA from multiple candidates. | 384 | * TODO: it could select the wrong CA from multiple candidates. |
354 | */ | 385 | */ |
355 | static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, | 386 | static int hdmi_channel_allocation(struct hda_codec *codec, hda_nid_t nid, |
356 | struct hdmi_audio_infoframe *ai) | 387 | int channels) |
357 | { | 388 | { |
358 | struct hdmi_spec *spec = codec->spec; | 389 | struct hdmi_spec *spec = codec->spec; |
359 | struct hdmi_eld *eld; | 390 | struct hdmi_eld *eld; |
360 | int i; | 391 | int i; |
392 | int ca = 0; | ||
361 | int spk_mask = 0; | 393 | int spk_mask = 0; |
362 | int channels = 1 + (ai->CC02_CT47 & 0x7); | ||
363 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; | 394 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; |
364 | 395 | ||
365 | /* | 396 | /* |
@@ -397,16 +428,16 @@ static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, | |||
397 | if (channels == channel_allocations[i].channels && | 428 | if (channels == channel_allocations[i].channels && |
398 | (spk_mask & channel_allocations[i].spk_mask) == | 429 | (spk_mask & channel_allocations[i].spk_mask) == |
399 | channel_allocations[i].spk_mask) { | 430 | channel_allocations[i].spk_mask) { |
400 | ai->CA = channel_allocations[i].ca_index; | 431 | ca = channel_allocations[i].ca_index; |
401 | break; | 432 | break; |
402 | } | 433 | } |
403 | } | 434 | } |
404 | 435 | ||
405 | snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); | 436 | snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); |
406 | snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", | 437 | snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", |
407 | ai->CA, channels, buf); | 438 | ca, channels, buf); |
408 | 439 | ||
409 | return ai->CA; | 440 | return ca; |
410 | } | 441 | } |
411 | 442 | ||
412 | static void hdmi_debug_channel_mapping(struct hda_codec *codec, | 443 | static void hdmi_debug_channel_mapping(struct hda_codec *codec, |
@@ -428,10 +459,9 @@ static void hdmi_debug_channel_mapping(struct hda_codec *codec, | |||
428 | 459 | ||
429 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, | 460 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, |
430 | hda_nid_t pin_nid, | 461 | hda_nid_t pin_nid, |
431 | struct hdmi_audio_infoframe *ai) | 462 | int ca) |
432 | { | 463 | { |
433 | int i; | 464 | int i; |
434 | int ca = ai->CA; | ||
435 | int err; | 465 | int err; |
436 | 466 | ||
437 | if (hdmi_channel_mapping[ca][1] == 0) { | 467 | if (hdmi_channel_mapping[ca][1] == 0) { |
@@ -528,41 +558,37 @@ static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid) | |||
528 | #endif | 558 | #endif |
529 | } | 559 | } |
530 | 560 | ||
531 | static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai) | 561 | static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *hdmi_ai) |
532 | { | 562 | { |
533 | u8 *bytes = (u8 *)ai; | 563 | u8 *bytes = (u8 *)hdmi_ai; |
534 | u8 sum = 0; | 564 | u8 sum = 0; |
535 | int i; | 565 | int i; |
536 | 566 | ||
537 | ai->checksum = 0; | 567 | hdmi_ai->checksum = 0; |
538 | 568 | ||
539 | for (i = 0; i < sizeof(*ai); i++) | 569 | for (i = 0; i < sizeof(*hdmi_ai); i++) |
540 | sum += bytes[i]; | 570 | sum += bytes[i]; |
541 | 571 | ||
542 | ai->checksum = -sum; | 572 | hdmi_ai->checksum = -sum; |
543 | } | 573 | } |
544 | 574 | ||
545 | static void hdmi_fill_audio_infoframe(struct hda_codec *codec, | 575 | static void hdmi_fill_audio_infoframe(struct hda_codec *codec, |
546 | hda_nid_t pin_nid, | 576 | hda_nid_t pin_nid, |
547 | struct hdmi_audio_infoframe *ai) | 577 | u8 *dip, int size) |
548 | { | 578 | { |
549 | u8 *bytes = (u8 *)ai; | ||
550 | int i; | 579 | int i; |
551 | 580 | ||
552 | hdmi_debug_dip_size(codec, pin_nid); | 581 | hdmi_debug_dip_size(codec, pin_nid); |
553 | hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ | 582 | hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ |
554 | 583 | ||
555 | hdmi_checksum_audio_infoframe(ai); | ||
556 | |||
557 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | 584 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); |
558 | for (i = 0; i < sizeof(*ai); i++) | 585 | for (i = 0; i < size; i++) |
559 | hdmi_write_dip_byte(codec, pin_nid, bytes[i]); | 586 | hdmi_write_dip_byte(codec, pin_nid, dip[i]); |
560 | } | 587 | } |
561 | 588 | ||
562 | static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, | 589 | static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, |
563 | struct hdmi_audio_infoframe *ai) | 590 | u8 *dip, int size) |
564 | { | 591 | { |
565 | u8 *bytes = (u8 *)ai; | ||
566 | u8 val; | 592 | u8 val; |
567 | int i; | 593 | int i; |
568 | 594 | ||
@@ -571,10 +597,10 @@ static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, | |||
571 | return false; | 597 | return false; |
572 | 598 | ||
573 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | 599 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); |
574 | for (i = 0; i < sizeof(*ai); i++) { | 600 | for (i = 0; i < size; i++) { |
575 | val = snd_hda_codec_read(codec, pin_nid, 0, | 601 | val = snd_hda_codec_read(codec, pin_nid, 0, |
576 | AC_VERB_GET_HDMI_DIP_DATA, 0); | 602 | AC_VERB_GET_HDMI_DIP_DATA, 0); |
577 | if (val != bytes[i]) | 603 | if (val != dip[i]) |
578 | return false; | 604 | return false; |
579 | } | 605 | } |
580 | 606 | ||
@@ -586,15 +612,13 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, | |||
586 | { | 612 | { |
587 | struct hdmi_spec *spec = codec->spec; | 613 | struct hdmi_spec *spec = codec->spec; |
588 | hda_nid_t pin_nid; | 614 | hda_nid_t pin_nid; |
615 | int channels = substream->runtime->channels; | ||
616 | int ca; | ||
589 | int i; | 617 | int i; |
590 | struct hdmi_audio_infoframe ai = { | 618 | u8 ai[max(sizeof(struct hdmi_audio_infoframe), |
591 | .type = 0x84, | 619 | sizeof(struct dp_audio_infoframe))]; |
592 | .ver = 0x01, | ||
593 | .len = 0x0a, | ||
594 | .CC02_CT47 = substream->runtime->channels - 1, | ||
595 | }; | ||
596 | 620 | ||
597 | hdmi_setup_channel_allocation(codec, nid, &ai); | 621 | ca = hdmi_channel_allocation(codec, nid, channels); |
598 | 622 | ||
599 | for (i = 0; i < spec->num_pins; i++) { | 623 | for (i = 0; i < spec->num_pins; i++) { |
600 | if (spec->pin_cvt[i] != nid) | 624 | if (spec->pin_cvt[i] != nid) |
@@ -603,14 +627,45 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, | |||
603 | continue; | 627 | continue; |
604 | 628 | ||
605 | pin_nid = spec->pin[i]; | 629 | pin_nid = spec->pin[i]; |
606 | if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) { | 630 | |
631 | memset(ai, 0, sizeof(ai)); | ||
632 | if (spec->sink_eld[i].conn_type == 0) { /* HDMI */ | ||
633 | struct hdmi_audio_infoframe *hdmi_ai; | ||
634 | |||
635 | hdmi_ai = (struct hdmi_audio_infoframe *)ai; | ||
636 | hdmi_ai->type = 0x84; | ||
637 | hdmi_ai->ver = 0x01; | ||
638 | hdmi_ai->len = 0x0a; | ||
639 | hdmi_ai->CC02_CT47 = channels - 1; | ||
640 | hdmi_checksum_audio_infoframe(hdmi_ai); | ||
641 | } else if (spec->sink_eld[i].conn_type == 1) { /* DisplayPort */ | ||
642 | struct dp_audio_infoframe *dp_ai; | ||
643 | |||
644 | dp_ai = (struct dp_audio_infoframe *)ai; | ||
645 | dp_ai->type = 0x84; | ||
646 | dp_ai->len = 0x1b; | ||
647 | dp_ai->ver = 0x11 << 2; | ||
648 | dp_ai->CC02_CT47 = channels - 1; | ||
649 | } else { | ||
650 | snd_printd("HDMI: unknown connection type at pin %d\n", | ||
651 | pin_nid); | ||
652 | continue; | ||
653 | } | ||
654 | |||
655 | /* | ||
656 | * sizeof(ai) is used instead of sizeof(*hdmi_ai) or | ||
657 | * sizeof(*dp_ai) to avoid partial match/update problems when | ||
658 | * the user switches between HDMI/DP monitors. | ||
659 | */ | ||
660 | if (!hdmi_infoframe_uptodate(codec, pin_nid, ai, sizeof(ai))) { | ||
607 | snd_printdd("hdmi_setup_audio_infoframe: " | 661 | snd_printdd("hdmi_setup_audio_infoframe: " |
608 | "cvt=%d pin=%d channels=%d\n", | 662 | "cvt=%d pin=%d channels=%d\n", |
609 | nid, pin_nid, | 663 | nid, pin_nid, |
610 | substream->runtime->channels); | 664 | channels); |
611 | hdmi_setup_channel_mapping(codec, pin_nid, &ai); | 665 | hdmi_setup_channel_mapping(codec, pin_nid, ca); |
612 | hdmi_stop_infoframe_trans(codec, pin_nid); | 666 | hdmi_stop_infoframe_trans(codec, pin_nid); |
613 | hdmi_fill_audio_infoframe(codec, pin_nid, &ai); | 667 | hdmi_fill_audio_infoframe(codec, pin_nid, |
668 | ai, sizeof(ai)); | ||
614 | hdmi_start_infoframe_trans(codec, pin_nid); | 669 | hdmi_start_infoframe_trans(codec, pin_nid); |
615 | } | 670 | } |
616 | } | 671 | } |
@@ -791,7 +846,6 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, | |||
791 | /* | 846 | /* |
792 | * HDA/HDMI auto parsing | 847 | * HDA/HDMI auto parsing |
793 | */ | 848 | */ |
794 | |||
795 | static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid) | 849 | static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid) |
796 | { | 850 | { |
797 | struct hdmi_spec *spec = codec->spec; | 851 | struct hdmi_spec *spec = codec->spec; |
@@ -922,3 +976,664 @@ static int hdmi_parse_codec(struct hda_codec *codec) | |||
922 | return 0; | 976 | return 0; |
923 | } | 977 | } |
924 | 978 | ||
979 | /* | ||
980 | */ | ||
981 | static char *generic_hdmi_pcm_names[MAX_HDMI_CVTS] = { | ||
982 | "HDMI 0", | ||
983 | "HDMI 1", | ||
984 | "HDMI 2", | ||
985 | }; | ||
986 | |||
987 | /* | ||
988 | * HDMI callbacks | ||
989 | */ | ||
990 | |||
991 | static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
992 | struct hda_codec *codec, | ||
993 | unsigned int stream_tag, | ||
994 | unsigned int format, | ||
995 | struct snd_pcm_substream *substream) | ||
996 | { | ||
997 | hdmi_set_channel_count(codec, hinfo->nid, | ||
998 | substream->runtime->channels); | ||
999 | |||
1000 | hdmi_setup_audio_infoframe(codec, hinfo->nid, substream); | ||
1001 | |||
1002 | return hdmi_setup_stream(codec, hinfo->nid, stream_tag, format); | ||
1003 | } | ||
1004 | |||
1005 | static struct hda_pcm_stream generic_hdmi_pcm_playback = { | ||
1006 | .substreams = 1, | ||
1007 | .channels_min = 2, | ||
1008 | .ops = { | ||
1009 | .open = hdmi_pcm_open, | ||
1010 | .prepare = generic_hdmi_playback_pcm_prepare, | ||
1011 | }, | ||
1012 | }; | ||
1013 | |||
1014 | static int generic_hdmi_build_pcms(struct hda_codec *codec) | ||
1015 | { | ||
1016 | struct hdmi_spec *spec = codec->spec; | ||
1017 | struct hda_pcm *info = spec->pcm_rec; | ||
1018 | int i; | ||
1019 | |||
1020 | codec->num_pcms = spec->num_cvts; | ||
1021 | codec->pcm_info = info; | ||
1022 | |||
1023 | for (i = 0; i < codec->num_pcms; i++, info++) { | ||
1024 | unsigned int chans; | ||
1025 | struct hda_pcm_stream *pstr; | ||
1026 | |||
1027 | chans = get_wcaps(codec, spec->cvt[i]); | ||
1028 | chans = get_wcaps_channels(chans); | ||
1029 | |||
1030 | info->name = generic_hdmi_pcm_names[i]; | ||
1031 | info->pcm_type = HDA_PCM_TYPE_HDMI; | ||
1032 | pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; | ||
1033 | if (spec->pcm_playback) | ||
1034 | *pstr = *spec->pcm_playback; | ||
1035 | else | ||
1036 | *pstr = generic_hdmi_pcm_playback; | ||
1037 | pstr->nid = spec->cvt[i]; | ||
1038 | if (pstr->channels_max <= 2 && chans && chans <= 16) | ||
1039 | pstr->channels_max = chans; | ||
1040 | } | ||
1041 | |||
1042 | return 0; | ||
1043 | } | ||
1044 | |||
1045 | static int generic_hdmi_build_controls(struct hda_codec *codec) | ||
1046 | { | ||
1047 | struct hdmi_spec *spec = codec->spec; | ||
1048 | int err; | ||
1049 | int i; | ||
1050 | |||
1051 | for (i = 0; i < codec->num_pcms; i++) { | ||
1052 | err = snd_hda_create_spdif_out_ctls(codec, spec->cvt[i]); | ||
1053 | if (err < 0) | ||
1054 | return err; | ||
1055 | } | ||
1056 | |||
1057 | return 0; | ||
1058 | } | ||
1059 | |||
1060 | static int generic_hdmi_init(struct hda_codec *codec) | ||
1061 | { | ||
1062 | struct hdmi_spec *spec = codec->spec; | ||
1063 | int i; | ||
1064 | |||
1065 | for (i = 0; spec->pin[i]; i++) { | ||
1066 | hdmi_enable_output(codec, spec->pin[i]); | ||
1067 | snd_hda_codec_write(codec, spec->pin[i], 0, | ||
1068 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
1069 | AC_USRSP_EN | spec->pin[i]); | ||
1070 | } | ||
1071 | return 0; | ||
1072 | } | ||
1073 | |||
1074 | static void generic_hdmi_free(struct hda_codec *codec) | ||
1075 | { | ||
1076 | struct hdmi_spec *spec = codec->spec; | ||
1077 | int i; | ||
1078 | |||
1079 | for (i = 0; i < spec->num_pins; i++) | ||
1080 | snd_hda_eld_proc_free(codec, &spec->sink_eld[i]); | ||
1081 | |||
1082 | kfree(spec); | ||
1083 | } | ||
1084 | |||
1085 | static struct hda_codec_ops generic_hdmi_patch_ops = { | ||
1086 | .init = generic_hdmi_init, | ||
1087 | .free = generic_hdmi_free, | ||
1088 | .build_pcms = generic_hdmi_build_pcms, | ||
1089 | .build_controls = generic_hdmi_build_controls, | ||
1090 | .unsol_event = hdmi_unsol_event, | ||
1091 | }; | ||
1092 | |||
1093 | static int patch_generic_hdmi(struct hda_codec *codec) | ||
1094 | { | ||
1095 | struct hdmi_spec *spec; | ||
1096 | int i; | ||
1097 | |||
1098 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1099 | if (spec == NULL) | ||
1100 | return -ENOMEM; | ||
1101 | |||
1102 | codec->spec = spec; | ||
1103 | if (hdmi_parse_codec(codec) < 0) { | ||
1104 | codec->spec = NULL; | ||
1105 | kfree(spec); | ||
1106 | return -EINVAL; | ||
1107 | } | ||
1108 | codec->patch_ops = generic_hdmi_patch_ops; | ||
1109 | |||
1110 | for (i = 0; i < spec->num_pins; i++) | ||
1111 | snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i); | ||
1112 | |||
1113 | init_channel_allocations(); | ||
1114 | |||
1115 | return 0; | ||
1116 | } | ||
1117 | |||
1118 | /* | ||
1119 | * Nvidia specific implementations | ||
1120 | */ | ||
1121 | |||
1122 | #define Nv_VERB_SET_Channel_Allocation 0xF79 | ||
1123 | #define Nv_VERB_SET_Info_Frame_Checksum 0xF7A | ||
1124 | #define Nv_VERB_SET_Audio_Protection_On 0xF98 | ||
1125 | #define Nv_VERB_SET_Audio_Protection_Off 0xF99 | ||
1126 | |||
1127 | #define nvhdmi_master_con_nid_7x 0x04 | ||
1128 | #define nvhdmi_master_pin_nid_7x 0x05 | ||
1129 | |||
1130 | static hda_nid_t nvhdmi_con_nids_7x[4] = { | ||
1131 | /*front, rear, clfe, rear_surr */ | ||
1132 | 0x6, 0x8, 0xa, 0xc, | ||
1133 | }; | ||
1134 | |||
1135 | static struct hda_verb nvhdmi_basic_init_7x[] = { | ||
1136 | /* set audio protect on */ | ||
1137 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, | ||
1138 | /* enable digital output on pin widget */ | ||
1139 | { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
1140 | { 0x7, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
1141 | { 0x9, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
1142 | { 0xb, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
1143 | { 0xd, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
1144 | {} /* terminator */ | ||
1145 | }; | ||
1146 | |||
1147 | #ifdef LIMITED_RATE_FMT_SUPPORT | ||
1148 | /* support only the safe format and rate */ | ||
1149 | #define SUPPORTED_RATES SNDRV_PCM_RATE_48000 | ||
1150 | #define SUPPORTED_MAXBPS 16 | ||
1151 | #define SUPPORTED_FORMATS SNDRV_PCM_FMTBIT_S16_LE | ||
1152 | #else | ||
1153 | /* support all rates and formats */ | ||
1154 | #define SUPPORTED_RATES \ | ||
1155 | (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ | ||
1156 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\ | ||
1157 | SNDRV_PCM_RATE_192000) | ||
1158 | #define SUPPORTED_MAXBPS 24 | ||
1159 | #define SUPPORTED_FORMATS \ | ||
1160 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
1161 | #endif | ||
1162 | |||
1163 | static int nvhdmi_7x_init(struct hda_codec *codec) | ||
1164 | { | ||
1165 | snd_hda_sequence_write(codec, nvhdmi_basic_init_7x); | ||
1166 | return 0; | ||
1167 | } | ||
1168 | |||
1169 | static int simple_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
1170 | struct hda_codec *codec, | ||
1171 | struct snd_pcm_substream *substream) | ||
1172 | { | ||
1173 | struct hdmi_spec *spec = codec->spec; | ||
1174 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | ||
1175 | } | ||
1176 | |||
1177 | static int simple_playback_pcm_close(struct hda_pcm_stream *hinfo, | ||
1178 | struct hda_codec *codec, | ||
1179 | struct snd_pcm_substream *substream) | ||
1180 | { | ||
1181 | struct hdmi_spec *spec = codec->spec; | ||
1182 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
1183 | } | ||
1184 | |||
1185 | static int simple_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
1186 | struct hda_codec *codec, | ||
1187 | unsigned int stream_tag, | ||
1188 | unsigned int format, | ||
1189 | struct snd_pcm_substream *substream) | ||
1190 | { | ||
1191 | struct hdmi_spec *spec = codec->spec; | ||
1192 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, | ||
1193 | stream_tag, format, substream); | ||
1194 | } | ||
1195 | |||
1196 | static int nvhdmi_8ch_7x_pcm_close(struct hda_pcm_stream *hinfo, | ||
1197 | struct hda_codec *codec, | ||
1198 | struct snd_pcm_substream *substream) | ||
1199 | { | ||
1200 | struct hdmi_spec *spec = codec->spec; | ||
1201 | int i; | ||
1202 | |||
1203 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, | ||
1204 | 0, AC_VERB_SET_CHANNEL_STREAMID, 0); | ||
1205 | for (i = 0; i < 4; i++) { | ||
1206 | /* set the stream id */ | ||
1207 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, | ||
1208 | AC_VERB_SET_CHANNEL_STREAMID, 0); | ||
1209 | /* set the stream format */ | ||
1210 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, | ||
1211 | AC_VERB_SET_STREAM_FORMAT, 0); | ||
1212 | } | ||
1213 | |||
1214 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
1215 | } | ||
1216 | |||
1217 | static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
1218 | struct hda_codec *codec, | ||
1219 | unsigned int stream_tag, | ||
1220 | unsigned int format, | ||
1221 | struct snd_pcm_substream *substream) | ||
1222 | { | ||
1223 | int chs; | ||
1224 | unsigned int dataDCC1, dataDCC2, chan, chanmask, channel_id; | ||
1225 | int i; | ||
1226 | |||
1227 | mutex_lock(&codec->spdif_mutex); | ||
1228 | |||
1229 | chs = substream->runtime->channels; | ||
1230 | chan = chs ? (chs - 1) : 1; | ||
1231 | |||
1232 | switch (chs) { | ||
1233 | default: | ||
1234 | case 0: | ||
1235 | case 2: | ||
1236 | chanmask = 0x00; | ||
1237 | break; | ||
1238 | case 4: | ||
1239 | chanmask = 0x08; | ||
1240 | break; | ||
1241 | case 6: | ||
1242 | chanmask = 0x0b; | ||
1243 | break; | ||
1244 | case 8: | ||
1245 | chanmask = 0x13; | ||
1246 | break; | ||
1247 | } | ||
1248 | dataDCC1 = AC_DIG1_ENABLE | AC_DIG1_COPYRIGHT; | ||
1249 | dataDCC2 = 0x2; | ||
1250 | |||
1251 | /* set the Audio InforFrame Channel Allocation */ | ||
1252 | snd_hda_codec_write(codec, 0x1, 0, | ||
1253 | Nv_VERB_SET_Channel_Allocation, chanmask); | ||
1254 | |||
1255 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ | ||
1256 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) | ||
1257 | snd_hda_codec_write(codec, | ||
1258 | nvhdmi_master_con_nid_7x, | ||
1259 | 0, | ||
1260 | AC_VERB_SET_DIGI_CONVERT_1, | ||
1261 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); | ||
1262 | |||
1263 | /* set the stream id */ | ||
1264 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, | ||
1265 | AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0); | ||
1266 | |||
1267 | /* set the stream format */ | ||
1268 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, | ||
1269 | AC_VERB_SET_STREAM_FORMAT, format); | ||
1270 | |||
1271 | /* turn on again (if needed) */ | ||
1272 | /* enable and set the channel status audio/data flag */ | ||
1273 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) { | ||
1274 | snd_hda_codec_write(codec, | ||
1275 | nvhdmi_master_con_nid_7x, | ||
1276 | 0, | ||
1277 | AC_VERB_SET_DIGI_CONVERT_1, | ||
1278 | codec->spdif_ctls & 0xff); | ||
1279 | snd_hda_codec_write(codec, | ||
1280 | nvhdmi_master_con_nid_7x, | ||
1281 | 0, | ||
1282 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); | ||
1283 | } | ||
1284 | |||
1285 | for (i = 0; i < 4; i++) { | ||
1286 | if (chs == 2) | ||
1287 | channel_id = 0; | ||
1288 | else | ||
1289 | channel_id = i * 2; | ||
1290 | |||
1291 | /* turn off SPDIF once; | ||
1292 | *otherwise the IEC958 bits won't be updated | ||
1293 | */ | ||
1294 | if (codec->spdif_status_reset && | ||
1295 | (codec->spdif_ctls & AC_DIG1_ENABLE)) | ||
1296 | snd_hda_codec_write(codec, | ||
1297 | nvhdmi_con_nids_7x[i], | ||
1298 | 0, | ||
1299 | AC_VERB_SET_DIGI_CONVERT_1, | ||
1300 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); | ||
1301 | /* set the stream id */ | ||
1302 | snd_hda_codec_write(codec, | ||
1303 | nvhdmi_con_nids_7x[i], | ||
1304 | 0, | ||
1305 | AC_VERB_SET_CHANNEL_STREAMID, | ||
1306 | (stream_tag << 4) | channel_id); | ||
1307 | /* set the stream format */ | ||
1308 | snd_hda_codec_write(codec, | ||
1309 | nvhdmi_con_nids_7x[i], | ||
1310 | 0, | ||
1311 | AC_VERB_SET_STREAM_FORMAT, | ||
1312 | format); | ||
1313 | /* turn on again (if needed) */ | ||
1314 | /* enable and set the channel status audio/data flag */ | ||
1315 | if (codec->spdif_status_reset && | ||
1316 | (codec->spdif_ctls & AC_DIG1_ENABLE)) { | ||
1317 | snd_hda_codec_write(codec, | ||
1318 | nvhdmi_con_nids_7x[i], | ||
1319 | 0, | ||
1320 | AC_VERB_SET_DIGI_CONVERT_1, | ||
1321 | codec->spdif_ctls & 0xff); | ||
1322 | snd_hda_codec_write(codec, | ||
1323 | nvhdmi_con_nids_7x[i], | ||
1324 | 0, | ||
1325 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); | ||
1326 | } | ||
1327 | } | ||
1328 | |||
1329 | /* set the Audio Info Frame Checksum */ | ||
1330 | snd_hda_codec_write(codec, 0x1, 0, | ||
1331 | Nv_VERB_SET_Info_Frame_Checksum, | ||
1332 | (0x71 - chan - chanmask)); | ||
1333 | |||
1334 | mutex_unlock(&codec->spdif_mutex); | ||
1335 | return 0; | ||
1336 | } | ||
1337 | |||
1338 | static struct hda_pcm_stream nvhdmi_pcm_playback_8ch_7x = { | ||
1339 | .substreams = 1, | ||
1340 | .channels_min = 2, | ||
1341 | .channels_max = 8, | ||
1342 | .nid = nvhdmi_master_con_nid_7x, | ||
1343 | .rates = SUPPORTED_RATES, | ||
1344 | .maxbps = SUPPORTED_MAXBPS, | ||
1345 | .formats = SUPPORTED_FORMATS, | ||
1346 | .ops = { | ||
1347 | .open = simple_playback_pcm_open, | ||
1348 | .close = nvhdmi_8ch_7x_pcm_close, | ||
1349 | .prepare = nvhdmi_8ch_7x_pcm_prepare | ||
1350 | }, | ||
1351 | }; | ||
1352 | |||
1353 | static struct hda_pcm_stream nvhdmi_pcm_playback_2ch = { | ||
1354 | .substreams = 1, | ||
1355 | .channels_min = 2, | ||
1356 | .channels_max = 2, | ||
1357 | .nid = nvhdmi_master_con_nid_7x, | ||
1358 | .rates = SUPPORTED_RATES, | ||
1359 | .maxbps = SUPPORTED_MAXBPS, | ||
1360 | .formats = SUPPORTED_FORMATS, | ||
1361 | .ops = { | ||
1362 | .open = simple_playback_pcm_open, | ||
1363 | .close = simple_playback_pcm_close, | ||
1364 | .prepare = simple_playback_pcm_prepare | ||
1365 | }, | ||
1366 | }; | ||
1367 | |||
1368 | static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = { | ||
1369 | .build_controls = generic_hdmi_build_controls, | ||
1370 | .build_pcms = generic_hdmi_build_pcms, | ||
1371 | .init = nvhdmi_7x_init, | ||
1372 | .free = generic_hdmi_free, | ||
1373 | }; | ||
1374 | |||
1375 | static struct hda_codec_ops nvhdmi_patch_ops_2ch = { | ||
1376 | .build_controls = generic_hdmi_build_controls, | ||
1377 | .build_pcms = generic_hdmi_build_pcms, | ||
1378 | .init = nvhdmi_7x_init, | ||
1379 | .free = generic_hdmi_free, | ||
1380 | }; | ||
1381 | |||
1382 | static int patch_nvhdmi_8ch_89(struct hda_codec *codec) | ||
1383 | { | ||
1384 | struct hdmi_spec *spec; | ||
1385 | int err = patch_generic_hdmi(codec); | ||
1386 | |||
1387 | if (err < 0) | ||
1388 | return err; | ||
1389 | spec = codec->spec; | ||
1390 | spec->old_pin_detect = 1; | ||
1391 | return 0; | ||
1392 | } | ||
1393 | |||
1394 | static int patch_nvhdmi_2ch(struct hda_codec *codec) | ||
1395 | { | ||
1396 | struct hdmi_spec *spec; | ||
1397 | |||
1398 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1399 | if (spec == NULL) | ||
1400 | return -ENOMEM; | ||
1401 | |||
1402 | codec->spec = spec; | ||
1403 | |||
1404 | spec->multiout.num_dacs = 0; /* no analog */ | ||
1405 | spec->multiout.max_channels = 2; | ||
1406 | spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; | ||
1407 | spec->old_pin_detect = 1; | ||
1408 | spec->num_cvts = 1; | ||
1409 | spec->cvt[0] = nvhdmi_master_con_nid_7x; | ||
1410 | spec->pcm_playback = &nvhdmi_pcm_playback_2ch; | ||
1411 | |||
1412 | codec->patch_ops = nvhdmi_patch_ops_2ch; | ||
1413 | |||
1414 | return 0; | ||
1415 | } | ||
1416 | |||
1417 | static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) | ||
1418 | { | ||
1419 | struct hdmi_spec *spec; | ||
1420 | int err = patch_nvhdmi_2ch(codec); | ||
1421 | |||
1422 | if (err < 0) | ||
1423 | return err; | ||
1424 | spec = codec->spec; | ||
1425 | spec->multiout.max_channels = 8; | ||
1426 | spec->pcm_playback = &nvhdmi_pcm_playback_8ch_7x; | ||
1427 | codec->patch_ops = nvhdmi_patch_ops_8ch_7x; | ||
1428 | return 0; | ||
1429 | } | ||
1430 | |||
1431 | /* | ||
1432 | * ATI-specific implementations | ||
1433 | * | ||
1434 | * FIXME: we may omit the whole this and use the generic code once after | ||
1435 | * it's confirmed to work. | ||
1436 | */ | ||
1437 | |||
1438 | #define ATIHDMI_CVT_NID 0x02 /* audio converter */ | ||
1439 | #define ATIHDMI_PIN_NID 0x03 /* HDMI output pin */ | ||
1440 | |||
1441 | static int atihdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
1442 | struct hda_codec *codec, | ||
1443 | unsigned int stream_tag, | ||
1444 | unsigned int format, | ||
1445 | struct snd_pcm_substream *substream) | ||
1446 | { | ||
1447 | struct hdmi_spec *spec = codec->spec; | ||
1448 | int chans = substream->runtime->channels; | ||
1449 | int i, err; | ||
1450 | |||
1451 | err = simple_playback_pcm_prepare(hinfo, codec, stream_tag, format, | ||
1452 | substream); | ||
1453 | if (err < 0) | ||
1454 | return err; | ||
1455 | snd_hda_codec_write(codec, spec->cvt[0], 0, AC_VERB_SET_CVT_CHAN_COUNT, | ||
1456 | chans - 1); | ||
1457 | /* FIXME: XXX */ | ||
1458 | for (i = 0; i < chans; i++) { | ||
1459 | snd_hda_codec_write(codec, spec->cvt[0], 0, | ||
1460 | AC_VERB_SET_HDMI_CHAN_SLOT, | ||
1461 | (i << 4) | i); | ||
1462 | } | ||
1463 | return 0; | ||
1464 | } | ||
1465 | |||
1466 | static struct hda_pcm_stream atihdmi_pcm_digital_playback = { | ||
1467 | .substreams = 1, | ||
1468 | .channels_min = 2, | ||
1469 | .channels_max = 2, | ||
1470 | .nid = ATIHDMI_CVT_NID, | ||
1471 | .ops = { | ||
1472 | .open = simple_playback_pcm_open, | ||
1473 | .close = simple_playback_pcm_close, | ||
1474 | .prepare = atihdmi_playback_pcm_prepare | ||
1475 | }, | ||
1476 | }; | ||
1477 | |||
1478 | static struct hda_verb atihdmi_basic_init[] = { | ||
1479 | /* enable digital output on pin widget */ | ||
1480 | { 0x03, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
1481 | {} /* terminator */ | ||
1482 | }; | ||
1483 | |||
1484 | static int atihdmi_init(struct hda_codec *codec) | ||
1485 | { | ||
1486 | struct hdmi_spec *spec = codec->spec; | ||
1487 | |||
1488 | snd_hda_sequence_write(codec, atihdmi_basic_init); | ||
1489 | /* SI codec requires to unmute the pin */ | ||
1490 | if (get_wcaps(codec, spec->pin[0]) & AC_WCAP_OUT_AMP) | ||
1491 | snd_hda_codec_write(codec, spec->pin[0], 0, | ||
1492 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
1493 | AMP_OUT_UNMUTE); | ||
1494 | return 0; | ||
1495 | } | ||
1496 | |||
1497 | static struct hda_codec_ops atihdmi_patch_ops = { | ||
1498 | .build_controls = generic_hdmi_build_controls, | ||
1499 | .build_pcms = generic_hdmi_build_pcms, | ||
1500 | .init = atihdmi_init, | ||
1501 | .free = generic_hdmi_free, | ||
1502 | }; | ||
1503 | |||
1504 | |||
1505 | static int patch_atihdmi(struct hda_codec *codec) | ||
1506 | { | ||
1507 | struct hdmi_spec *spec; | ||
1508 | |||
1509 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1510 | if (spec == NULL) | ||
1511 | return -ENOMEM; | ||
1512 | |||
1513 | codec->spec = spec; | ||
1514 | |||
1515 | spec->multiout.num_dacs = 0; /* no analog */ | ||
1516 | spec->multiout.max_channels = 2; | ||
1517 | spec->multiout.dig_out_nid = ATIHDMI_CVT_NID; | ||
1518 | spec->num_cvts = 1; | ||
1519 | spec->cvt[0] = ATIHDMI_CVT_NID; | ||
1520 | spec->pin[0] = ATIHDMI_PIN_NID; | ||
1521 | spec->pcm_playback = &atihdmi_pcm_digital_playback; | ||
1522 | |||
1523 | codec->patch_ops = atihdmi_patch_ops; | ||
1524 | |||
1525 | return 0; | ||
1526 | } | ||
1527 | |||
1528 | |||
1529 | /* | ||
1530 | * patch entries | ||
1531 | */ | ||
1532 | static struct hda_codec_preset snd_hda_preset_hdmi[] = { | ||
1533 | { .id = 0x1002793c, .name = "RS600 HDMI", .patch = patch_atihdmi }, | ||
1534 | { .id = 0x10027919, .name = "RS600 HDMI", .patch = patch_atihdmi }, | ||
1535 | { .id = 0x1002791a, .name = "RS690/780 HDMI", .patch = patch_atihdmi }, | ||
1536 | { .id = 0x1002aa01, .name = "R6xx HDMI", .patch = patch_atihdmi }, | ||
1537 | { .id = 0x10951390, .name = "SiI1390 HDMI", .patch = patch_generic_hdmi }, | ||
1538 | { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_generic_hdmi }, | ||
1539 | { .id = 0x17e80047, .name = "Chrontel HDMI", .patch = patch_generic_hdmi }, | ||
1540 | { .id = 0x10de0002, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
1541 | { .id = 0x10de0003, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
1542 | { .id = 0x10de0005, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
1543 | { .id = 0x10de0006, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
1544 | { .id = 0x10de0007, .name = "MCP79/7A HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
1545 | { .id = 0x10de000a, .name = "GPU 0a HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1546 | { .id = 0x10de000b, .name = "GPU 0b HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1547 | { .id = 0x10de000c, .name = "MCP89 HDMI", .patch = patch_nvhdmi_8ch_89 }, | ||
1548 | { .id = 0x10de000d, .name = "GPU 0d HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1549 | { .id = 0x10de0010, .name = "GPU 10 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1550 | { .id = 0x10de0011, .name = "GPU 11 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1551 | { .id = 0x10de0012, .name = "GPU 12 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1552 | { .id = 0x10de0013, .name = "GPU 13 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1553 | { .id = 0x10de0014, .name = "GPU 14 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1554 | { .id = 0x10de0018, .name = "GPU 18 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1555 | { .id = 0x10de0019, .name = "GPU 19 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1556 | { .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1557 | { .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1558 | { .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1559 | { .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1560 | { .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1561 | { .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1562 | { .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1563 | { .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
1564 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, | ||
1565 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, | ||
1566 | { .id = 0x80860054, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, | ||
1567 | { .id = 0x80862801, .name = "Bearlake HDMI", .patch = patch_generic_hdmi }, | ||
1568 | { .id = 0x80862802, .name = "Cantiga HDMI", .patch = patch_generic_hdmi }, | ||
1569 | { .id = 0x80862803, .name = "Eaglelake HDMI", .patch = patch_generic_hdmi }, | ||
1570 | { .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, | ||
1571 | { .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_generic_hdmi }, | ||
1572 | { .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi }, | ||
1573 | {} /* terminator */ | ||
1574 | }; | ||
1575 | |||
1576 | MODULE_ALIAS("snd-hda-codec-id:1002793c"); | ||
1577 | MODULE_ALIAS("snd-hda-codec-id:10027919"); | ||
1578 | MODULE_ALIAS("snd-hda-codec-id:1002791a"); | ||
1579 | MODULE_ALIAS("snd-hda-codec-id:1002aa01"); | ||
1580 | MODULE_ALIAS("snd-hda-codec-id:10951390"); | ||
1581 | MODULE_ALIAS("snd-hda-codec-id:10951392"); | ||
1582 | MODULE_ALIAS("snd-hda-codec-id:10de0002"); | ||
1583 | MODULE_ALIAS("snd-hda-codec-id:10de0003"); | ||
1584 | MODULE_ALIAS("snd-hda-codec-id:10de0005"); | ||
1585 | MODULE_ALIAS("snd-hda-codec-id:10de0006"); | ||
1586 | MODULE_ALIAS("snd-hda-codec-id:10de0007"); | ||
1587 | MODULE_ALIAS("snd-hda-codec-id:10de000a"); | ||
1588 | MODULE_ALIAS("snd-hda-codec-id:10de000b"); | ||
1589 | MODULE_ALIAS("snd-hda-codec-id:10de000c"); | ||
1590 | MODULE_ALIAS("snd-hda-codec-id:10de000d"); | ||
1591 | MODULE_ALIAS("snd-hda-codec-id:10de0010"); | ||
1592 | MODULE_ALIAS("snd-hda-codec-id:10de0011"); | ||
1593 | MODULE_ALIAS("snd-hda-codec-id:10de0012"); | ||
1594 | MODULE_ALIAS("snd-hda-codec-id:10de0013"); | ||
1595 | MODULE_ALIAS("snd-hda-codec-id:10de0014"); | ||
1596 | MODULE_ALIAS("snd-hda-codec-id:10de0018"); | ||
1597 | MODULE_ALIAS("snd-hda-codec-id:10de0019"); | ||
1598 | MODULE_ALIAS("snd-hda-codec-id:10de001a"); | ||
1599 | MODULE_ALIAS("snd-hda-codec-id:10de001b"); | ||
1600 | MODULE_ALIAS("snd-hda-codec-id:10de001c"); | ||
1601 | MODULE_ALIAS("snd-hda-codec-id:10de0040"); | ||
1602 | MODULE_ALIAS("snd-hda-codec-id:10de0041"); | ||
1603 | MODULE_ALIAS("snd-hda-codec-id:10de0042"); | ||
1604 | MODULE_ALIAS("snd-hda-codec-id:10de0043"); | ||
1605 | MODULE_ALIAS("snd-hda-codec-id:10de0044"); | ||
1606 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); | ||
1607 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); | ||
1608 | MODULE_ALIAS("snd-hda-codec-id:17e80047"); | ||
1609 | MODULE_ALIAS("snd-hda-codec-id:80860054"); | ||
1610 | MODULE_ALIAS("snd-hda-codec-id:80862801"); | ||
1611 | MODULE_ALIAS("snd-hda-codec-id:80862802"); | ||
1612 | MODULE_ALIAS("snd-hda-codec-id:80862803"); | ||
1613 | MODULE_ALIAS("snd-hda-codec-id:80862804"); | ||
1614 | MODULE_ALIAS("snd-hda-codec-id:80862805"); | ||
1615 | MODULE_ALIAS("snd-hda-codec-id:808629fb"); | ||
1616 | |||
1617 | MODULE_LICENSE("GPL"); | ||
1618 | MODULE_DESCRIPTION("HDMI HD-audio codec"); | ||
1619 | MODULE_ALIAS("snd-hda-codec-intelhdmi"); | ||
1620 | MODULE_ALIAS("snd-hda-codec-nvhdmi"); | ||
1621 | MODULE_ALIAS("snd-hda-codec-atihdmi"); | ||
1622 | |||
1623 | static struct hda_codec_preset_list intel_list = { | ||
1624 | .preset = snd_hda_preset_hdmi, | ||
1625 | .owner = THIS_MODULE, | ||
1626 | }; | ||
1627 | |||
1628 | static int __init patch_hdmi_init(void) | ||
1629 | { | ||
1630 | return snd_hda_add_codec_preset(&intel_list); | ||
1631 | } | ||
1632 | |||
1633 | static void __exit patch_hdmi_exit(void) | ||
1634 | { | ||
1635 | snd_hda_delete_codec_preset(&intel_list); | ||
1636 | } | ||
1637 | |||
1638 | module_init(patch_hdmi_init) | ||
1639 | module_exit(patch_hdmi_exit) | ||
diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c deleted file mode 100644 index 36a9b83a6174..000000000000 --- a/sound/pci/hda/patch_intelhdmi.c +++ /dev/null | |||
@@ -1,220 +0,0 @@ | |||
1 | /* | ||
2 | * | ||
3 | * patch_intelhdmi.c - Patch for Intel HDMI codecs | ||
4 | * | ||
5 | * Copyright(c) 2008 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * Authors: | ||
8 | * Jiang Zhe <zhe.jiang@intel.com> | ||
9 | * Wu Fengguang <wfg@linux.intel.com> | ||
10 | * | ||
11 | * Maintained by: | ||
12 | * Wu Fengguang <wfg@linux.intel.com> | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify it | ||
15 | * under the terms of the GNU General Public License as published by the Free | ||
16 | * Software Foundation; either version 2 of the License, or (at your option) | ||
17 | * any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, but | ||
20 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
21 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
22 | * for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software Foundation, | ||
26 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
27 | */ | ||
28 | |||
29 | #include <linux/init.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <sound/core.h> | ||
33 | #include "hda_codec.h" | ||
34 | #include "hda_local.h" | ||
35 | |||
36 | /* | ||
37 | * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device | ||
38 | * could support two independent pipes, each of them can be connected to one or | ||
39 | * more ports (DVI, HDMI or DisplayPort). | ||
40 | * | ||
41 | * The HDA correspondence of pipes/ports are converter/pin nodes. | ||
42 | */ | ||
43 | #define MAX_HDMI_CVTS 3 | ||
44 | #define MAX_HDMI_PINS 3 | ||
45 | |||
46 | #include "patch_hdmi.c" | ||
47 | |||
48 | static char *intel_hdmi_pcm_names[MAX_HDMI_CVTS] = { | ||
49 | "INTEL HDMI 0", | ||
50 | "INTEL HDMI 1", | ||
51 | "INTEL HDMI 2", | ||
52 | }; | ||
53 | |||
54 | /* | ||
55 | * HDMI callbacks | ||
56 | */ | ||
57 | |||
58 | static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
59 | struct hda_codec *codec, | ||
60 | unsigned int stream_tag, | ||
61 | unsigned int format, | ||
62 | struct snd_pcm_substream *substream) | ||
63 | { | ||
64 | hdmi_set_channel_count(codec, hinfo->nid, | ||
65 | substream->runtime->channels); | ||
66 | |||
67 | hdmi_setup_audio_infoframe(codec, hinfo->nid, substream); | ||
68 | |||
69 | return hdmi_setup_stream(codec, hinfo->nid, stream_tag, format); | ||
70 | } | ||
71 | |||
72 | static struct hda_pcm_stream intel_hdmi_pcm_playback = { | ||
73 | .substreams = 1, | ||
74 | .channels_min = 2, | ||
75 | .ops = { | ||
76 | .open = hdmi_pcm_open, | ||
77 | .prepare = intel_hdmi_playback_pcm_prepare, | ||
78 | }, | ||
79 | }; | ||
80 | |||
81 | static int intel_hdmi_build_pcms(struct hda_codec *codec) | ||
82 | { | ||
83 | struct hdmi_spec *spec = codec->spec; | ||
84 | struct hda_pcm *info = spec->pcm_rec; | ||
85 | int i; | ||
86 | |||
87 | codec->num_pcms = spec->num_cvts; | ||
88 | codec->pcm_info = info; | ||
89 | |||
90 | for (i = 0; i < codec->num_pcms; i++, info++) { | ||
91 | unsigned int chans; | ||
92 | |||
93 | chans = get_wcaps(codec, spec->cvt[i]); | ||
94 | chans = get_wcaps_channels(chans); | ||
95 | |||
96 | info->name = intel_hdmi_pcm_names[i]; | ||
97 | info->pcm_type = HDA_PCM_TYPE_HDMI; | ||
98 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = | ||
99 | intel_hdmi_pcm_playback; | ||
100 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->cvt[i]; | ||
101 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans; | ||
102 | } | ||
103 | |||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static int intel_hdmi_build_controls(struct hda_codec *codec) | ||
108 | { | ||
109 | struct hdmi_spec *spec = codec->spec; | ||
110 | int err; | ||
111 | int i; | ||
112 | |||
113 | for (i = 0; i < codec->num_pcms; i++) { | ||
114 | err = snd_hda_create_spdif_out_ctls(codec, spec->cvt[i]); | ||
115 | if (err < 0) | ||
116 | return err; | ||
117 | } | ||
118 | |||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static int intel_hdmi_init(struct hda_codec *codec) | ||
123 | { | ||
124 | struct hdmi_spec *spec = codec->spec; | ||
125 | int i; | ||
126 | |||
127 | for (i = 0; spec->pin[i]; i++) { | ||
128 | hdmi_enable_output(codec, spec->pin[i]); | ||
129 | snd_hda_codec_write(codec, spec->pin[i], 0, | ||
130 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
131 | AC_USRSP_EN | spec->pin[i]); | ||
132 | } | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static void intel_hdmi_free(struct hda_codec *codec) | ||
137 | { | ||
138 | struct hdmi_spec *spec = codec->spec; | ||
139 | int i; | ||
140 | |||
141 | for (i = 0; i < spec->num_pins; i++) | ||
142 | snd_hda_eld_proc_free(codec, &spec->sink_eld[i]); | ||
143 | |||
144 | kfree(spec); | ||
145 | } | ||
146 | |||
147 | static struct hda_codec_ops intel_hdmi_patch_ops = { | ||
148 | .init = intel_hdmi_init, | ||
149 | .free = intel_hdmi_free, | ||
150 | .build_pcms = intel_hdmi_build_pcms, | ||
151 | .build_controls = intel_hdmi_build_controls, | ||
152 | .unsol_event = hdmi_unsol_event, | ||
153 | }; | ||
154 | |||
155 | static int patch_intel_hdmi(struct hda_codec *codec) | ||
156 | { | ||
157 | struct hdmi_spec *spec; | ||
158 | int i; | ||
159 | |||
160 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
161 | if (spec == NULL) | ||
162 | return -ENOMEM; | ||
163 | |||
164 | codec->spec = spec; | ||
165 | if (hdmi_parse_codec(codec) < 0) { | ||
166 | codec->spec = NULL; | ||
167 | kfree(spec); | ||
168 | return -EINVAL; | ||
169 | } | ||
170 | codec->patch_ops = intel_hdmi_patch_ops; | ||
171 | |||
172 | for (i = 0; i < spec->num_pins; i++) | ||
173 | snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i); | ||
174 | |||
175 | init_channel_allocations(); | ||
176 | |||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static struct hda_codec_preset snd_hda_preset_intelhdmi[] = { | ||
181 | { .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_intel_hdmi }, | ||
182 | { .id = 0x80862801, .name = "Bearlake HDMI", .patch = patch_intel_hdmi }, | ||
183 | { .id = 0x80862802, .name = "Cantiga HDMI", .patch = patch_intel_hdmi }, | ||
184 | { .id = 0x80862803, .name = "Eaglelake HDMI", .patch = patch_intel_hdmi }, | ||
185 | { .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_intel_hdmi }, | ||
186 | { .id = 0x80860054, .name = "IbexPeak HDMI", .patch = patch_intel_hdmi }, | ||
187 | { .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_intel_hdmi }, | ||
188 | { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_intel_hdmi }, | ||
189 | {} /* terminator */ | ||
190 | }; | ||
191 | |||
192 | MODULE_ALIAS("snd-hda-codec-id:808629fb"); | ||
193 | MODULE_ALIAS("snd-hda-codec-id:80862801"); | ||
194 | MODULE_ALIAS("snd-hda-codec-id:80862802"); | ||
195 | MODULE_ALIAS("snd-hda-codec-id:80862803"); | ||
196 | MODULE_ALIAS("snd-hda-codec-id:80862804"); | ||
197 | MODULE_ALIAS("snd-hda-codec-id:80862805"); | ||
198 | MODULE_ALIAS("snd-hda-codec-id:80860054"); | ||
199 | MODULE_ALIAS("snd-hda-codec-id:10951392"); | ||
200 | |||
201 | MODULE_LICENSE("GPL"); | ||
202 | MODULE_DESCRIPTION("Intel HDMI HD-audio codec"); | ||
203 | |||
204 | static struct hda_codec_preset_list intel_list = { | ||
205 | .preset = snd_hda_preset_intelhdmi, | ||
206 | .owner = THIS_MODULE, | ||
207 | }; | ||
208 | |||
209 | static int __init patch_intelhdmi_init(void) | ||
210 | { | ||
211 | return snd_hda_add_codec_preset(&intel_list); | ||
212 | } | ||
213 | |||
214 | static void __exit patch_intelhdmi_exit(void) | ||
215 | { | ||
216 | snd_hda_delete_codec_preset(&intel_list); | ||
217 | } | ||
218 | |||
219 | module_init(patch_intelhdmi_init) | ||
220 | module_exit(patch_intelhdmi_exit) | ||
diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c deleted file mode 100644 index baa108b9d6aa..000000000000 --- a/sound/pci/hda/patch_nvhdmi.c +++ /dev/null | |||
@@ -1,608 +0,0 @@ | |||
1 | /* | ||
2 | * Universal Interface for Intel High Definition Audio Codec | ||
3 | * | ||
4 | * HD audio interface patch for NVIDIA HDMI codecs | ||
5 | * | ||
6 | * Copyright (c) 2008 NVIDIA Corp. All rights reserved. | ||
7 | * Copyright (c) 2008 Wei Ni <wni@nvidia.com> | ||
8 | * | ||
9 | * | ||
10 | * This driver is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This driver is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | */ | ||
24 | |||
25 | #include <linux/init.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <sound/core.h> | ||
29 | #include "hda_codec.h" | ||
30 | #include "hda_local.h" | ||
31 | |||
32 | #define MAX_HDMI_CVTS 1 | ||
33 | #define MAX_HDMI_PINS 1 | ||
34 | |||
35 | #include "patch_hdmi.c" | ||
36 | |||
37 | static char *nvhdmi_pcm_names[MAX_HDMI_CVTS] = { | ||
38 | "NVIDIA HDMI", | ||
39 | }; | ||
40 | |||
41 | /* define below to restrict the supported rates and formats */ | ||
42 | /* #define LIMITED_RATE_FMT_SUPPORT */ | ||
43 | |||
44 | enum HDACodec { | ||
45 | HDA_CODEC_NVIDIA_MCP7X, | ||
46 | HDA_CODEC_NVIDIA_MCP89, | ||
47 | HDA_CODEC_NVIDIA_GT21X, | ||
48 | HDA_CODEC_INVALID | ||
49 | }; | ||
50 | |||
51 | #define Nv_VERB_SET_Channel_Allocation 0xF79 | ||
52 | #define Nv_VERB_SET_Info_Frame_Checksum 0xF7A | ||
53 | #define Nv_VERB_SET_Audio_Protection_On 0xF98 | ||
54 | #define Nv_VERB_SET_Audio_Protection_Off 0xF99 | ||
55 | |||
56 | #define nvhdmi_master_con_nid_7x 0x04 | ||
57 | #define nvhdmi_master_pin_nid_7x 0x05 | ||
58 | |||
59 | #define nvhdmi_master_con_nid_89 0x04 | ||
60 | #define nvhdmi_master_pin_nid_89 0x05 | ||
61 | |||
62 | static hda_nid_t nvhdmi_con_nids_7x[4] = { | ||
63 | /*front, rear, clfe, rear_surr */ | ||
64 | 0x6, 0x8, 0xa, 0xc, | ||
65 | }; | ||
66 | |||
67 | static struct hda_verb nvhdmi_basic_init_7x[] = { | ||
68 | /* set audio protect on */ | ||
69 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, | ||
70 | /* enable digital output on pin widget */ | ||
71 | { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
72 | { 0x7, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
73 | { 0x9, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
74 | { 0xb, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
75 | { 0xd, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
76 | {} /* terminator */ | ||
77 | }; | ||
78 | |||
79 | #ifdef LIMITED_RATE_FMT_SUPPORT | ||
80 | /* support only the safe format and rate */ | ||
81 | #define SUPPORTED_RATES SNDRV_PCM_RATE_48000 | ||
82 | #define SUPPORTED_MAXBPS 16 | ||
83 | #define SUPPORTED_FORMATS SNDRV_PCM_FMTBIT_S16_LE | ||
84 | #else | ||
85 | /* support all rates and formats */ | ||
86 | #define SUPPORTED_RATES \ | ||
87 | (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ | ||
88 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\ | ||
89 | SNDRV_PCM_RATE_192000) | ||
90 | #define SUPPORTED_MAXBPS 24 | ||
91 | #define SUPPORTED_FORMATS \ | ||
92 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
93 | #endif | ||
94 | |||
95 | /* | ||
96 | * Controls | ||
97 | */ | ||
98 | static int nvhdmi_build_controls(struct hda_codec *codec) | ||
99 | { | ||
100 | struct hdmi_spec *spec = codec->spec; | ||
101 | int err; | ||
102 | int i; | ||
103 | |||
104 | if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) | ||
105 | || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { | ||
106 | for (i = 0; i < codec->num_pcms; i++) { | ||
107 | err = snd_hda_create_spdif_out_ctls(codec, | ||
108 | spec->cvt[i]); | ||
109 | if (err < 0) | ||
110 | return err; | ||
111 | } | ||
112 | } else { | ||
113 | err = snd_hda_create_spdif_out_ctls(codec, | ||
114 | spec->multiout.dig_out_nid); | ||
115 | if (err < 0) | ||
116 | return err; | ||
117 | } | ||
118 | |||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static int nvhdmi_init(struct hda_codec *codec) | ||
123 | { | ||
124 | struct hdmi_spec *spec = codec->spec; | ||
125 | int i; | ||
126 | if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) | ||
127 | || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { | ||
128 | for (i = 0; spec->pin[i]; i++) { | ||
129 | hdmi_enable_output(codec, spec->pin[i]); | ||
130 | snd_hda_codec_write(codec, spec->pin[i], 0, | ||
131 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
132 | AC_USRSP_EN | spec->pin[i]); | ||
133 | } | ||
134 | } else { | ||
135 | snd_hda_sequence_write(codec, nvhdmi_basic_init_7x); | ||
136 | } | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | static void nvhdmi_free(struct hda_codec *codec) | ||
141 | { | ||
142 | struct hdmi_spec *spec = codec->spec; | ||
143 | int i; | ||
144 | |||
145 | if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) | ||
146 | || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { | ||
147 | for (i = 0; i < spec->num_pins; i++) | ||
148 | snd_hda_eld_proc_free(codec, &spec->sink_eld[i]); | ||
149 | } | ||
150 | |||
151 | kfree(spec); | ||
152 | } | ||
153 | |||
154 | /* | ||
155 | * Digital out | ||
156 | */ | ||
157 | static int nvhdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
158 | struct hda_codec *codec, | ||
159 | struct snd_pcm_substream *substream) | ||
160 | { | ||
161 | struct hdmi_spec *spec = codec->spec; | ||
162 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | ||
163 | } | ||
164 | |||
165 | static int nvhdmi_dig_playback_pcm_close_8ch_7x(struct hda_pcm_stream *hinfo, | ||
166 | struct hda_codec *codec, | ||
167 | struct snd_pcm_substream *substream) | ||
168 | { | ||
169 | struct hdmi_spec *spec = codec->spec; | ||
170 | int i; | ||
171 | |||
172 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, | ||
173 | 0, AC_VERB_SET_CHANNEL_STREAMID, 0); | ||
174 | for (i = 0; i < 4; i++) { | ||
175 | /* set the stream id */ | ||
176 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, | ||
177 | AC_VERB_SET_CHANNEL_STREAMID, 0); | ||
178 | /* set the stream format */ | ||
179 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, | ||
180 | AC_VERB_SET_STREAM_FORMAT, 0); | ||
181 | } | ||
182 | |||
183 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
184 | } | ||
185 | |||
186 | static int nvhdmi_dig_playback_pcm_close_2ch(struct hda_pcm_stream *hinfo, | ||
187 | struct hda_codec *codec, | ||
188 | struct snd_pcm_substream *substream) | ||
189 | { | ||
190 | struct hdmi_spec *spec = codec->spec; | ||
191 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
192 | } | ||
193 | |||
194 | static int nvhdmi_dig_playback_pcm_prepare_8ch_89(struct hda_pcm_stream *hinfo, | ||
195 | struct hda_codec *codec, | ||
196 | unsigned int stream_tag, | ||
197 | unsigned int format, | ||
198 | struct snd_pcm_substream *substream) | ||
199 | { | ||
200 | hdmi_set_channel_count(codec, hinfo->nid, | ||
201 | substream->runtime->channels); | ||
202 | |||
203 | hdmi_setup_audio_infoframe(codec, hinfo->nid, substream); | ||
204 | |||
205 | return hdmi_setup_stream(codec, hinfo->nid, stream_tag, format); | ||
206 | } | ||
207 | |||
208 | static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, | ||
209 | struct hda_codec *codec, | ||
210 | unsigned int stream_tag, | ||
211 | unsigned int format, | ||
212 | struct snd_pcm_substream *substream) | ||
213 | { | ||
214 | int chs; | ||
215 | unsigned int dataDCC1, dataDCC2, chan, chanmask, channel_id; | ||
216 | int i; | ||
217 | |||
218 | mutex_lock(&codec->spdif_mutex); | ||
219 | |||
220 | chs = substream->runtime->channels; | ||
221 | chan = chs ? (chs - 1) : 1; | ||
222 | |||
223 | switch (chs) { | ||
224 | default: | ||
225 | case 0: | ||
226 | case 2: | ||
227 | chanmask = 0x00; | ||
228 | break; | ||
229 | case 4: | ||
230 | chanmask = 0x08; | ||
231 | break; | ||
232 | case 6: | ||
233 | chanmask = 0x0b; | ||
234 | break; | ||
235 | case 8: | ||
236 | chanmask = 0x13; | ||
237 | break; | ||
238 | } | ||
239 | dataDCC1 = AC_DIG1_ENABLE | AC_DIG1_COPYRIGHT; | ||
240 | dataDCC2 = 0x2; | ||
241 | |||
242 | /* set the Audio InforFrame Channel Allocation */ | ||
243 | snd_hda_codec_write(codec, 0x1, 0, | ||
244 | Nv_VERB_SET_Channel_Allocation, chanmask); | ||
245 | |||
246 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ | ||
247 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) | ||
248 | snd_hda_codec_write(codec, | ||
249 | nvhdmi_master_con_nid_7x, | ||
250 | 0, | ||
251 | AC_VERB_SET_DIGI_CONVERT_1, | ||
252 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); | ||
253 | |||
254 | /* set the stream id */ | ||
255 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, | ||
256 | AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0); | ||
257 | |||
258 | /* set the stream format */ | ||
259 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, | ||
260 | AC_VERB_SET_STREAM_FORMAT, format); | ||
261 | |||
262 | /* turn on again (if needed) */ | ||
263 | /* enable and set the channel status audio/data flag */ | ||
264 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) { | ||
265 | snd_hda_codec_write(codec, | ||
266 | nvhdmi_master_con_nid_7x, | ||
267 | 0, | ||
268 | AC_VERB_SET_DIGI_CONVERT_1, | ||
269 | codec->spdif_ctls & 0xff); | ||
270 | snd_hda_codec_write(codec, | ||
271 | nvhdmi_master_con_nid_7x, | ||
272 | 0, | ||
273 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); | ||
274 | } | ||
275 | |||
276 | for (i = 0; i < 4; i++) { | ||
277 | if (chs == 2) | ||
278 | channel_id = 0; | ||
279 | else | ||
280 | channel_id = i * 2; | ||
281 | |||
282 | /* turn off SPDIF once; | ||
283 | *otherwise the IEC958 bits won't be updated | ||
284 | */ | ||
285 | if (codec->spdif_status_reset && | ||
286 | (codec->spdif_ctls & AC_DIG1_ENABLE)) | ||
287 | snd_hda_codec_write(codec, | ||
288 | nvhdmi_con_nids_7x[i], | ||
289 | 0, | ||
290 | AC_VERB_SET_DIGI_CONVERT_1, | ||
291 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); | ||
292 | /* set the stream id */ | ||
293 | snd_hda_codec_write(codec, | ||
294 | nvhdmi_con_nids_7x[i], | ||
295 | 0, | ||
296 | AC_VERB_SET_CHANNEL_STREAMID, | ||
297 | (stream_tag << 4) | channel_id); | ||
298 | /* set the stream format */ | ||
299 | snd_hda_codec_write(codec, | ||
300 | nvhdmi_con_nids_7x[i], | ||
301 | 0, | ||
302 | AC_VERB_SET_STREAM_FORMAT, | ||
303 | format); | ||
304 | /* turn on again (if needed) */ | ||
305 | /* enable and set the channel status audio/data flag */ | ||
306 | if (codec->spdif_status_reset && | ||
307 | (codec->spdif_ctls & AC_DIG1_ENABLE)) { | ||
308 | snd_hda_codec_write(codec, | ||
309 | nvhdmi_con_nids_7x[i], | ||
310 | 0, | ||
311 | AC_VERB_SET_DIGI_CONVERT_1, | ||
312 | codec->spdif_ctls & 0xff); | ||
313 | snd_hda_codec_write(codec, | ||
314 | nvhdmi_con_nids_7x[i], | ||
315 | 0, | ||
316 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); | ||
317 | } | ||
318 | } | ||
319 | |||
320 | /* set the Audio Info Frame Checksum */ | ||
321 | snd_hda_codec_write(codec, 0x1, 0, | ||
322 | Nv_VERB_SET_Info_Frame_Checksum, | ||
323 | (0x71 - chan - chanmask)); | ||
324 | |||
325 | mutex_unlock(&codec->spdif_mutex); | ||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo, | ||
330 | struct hda_codec *codec, | ||
331 | unsigned int stream_tag, | ||
332 | unsigned int format, | ||
333 | struct snd_pcm_substream *substream) | ||
334 | { | ||
335 | struct hdmi_spec *spec = codec->spec; | ||
336 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, | ||
337 | format, substream); | ||
338 | } | ||
339 | |||
340 | static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_89 = { | ||
341 | .substreams = 1, | ||
342 | .channels_min = 2, | ||
343 | .ops = { | ||
344 | .open = hdmi_pcm_open, | ||
345 | .prepare = nvhdmi_dig_playback_pcm_prepare_8ch_89, | ||
346 | }, | ||
347 | }; | ||
348 | |||
349 | static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_7x = { | ||
350 | .substreams = 1, | ||
351 | .channels_min = 2, | ||
352 | .channels_max = 8, | ||
353 | .nid = nvhdmi_master_con_nid_7x, | ||
354 | .rates = SUPPORTED_RATES, | ||
355 | .maxbps = SUPPORTED_MAXBPS, | ||
356 | .formats = SUPPORTED_FORMATS, | ||
357 | .ops = { | ||
358 | .open = nvhdmi_dig_playback_pcm_open, | ||
359 | .close = nvhdmi_dig_playback_pcm_close_8ch_7x, | ||
360 | .prepare = nvhdmi_dig_playback_pcm_prepare_8ch | ||
361 | }, | ||
362 | }; | ||
363 | |||
364 | static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = { | ||
365 | .substreams = 1, | ||
366 | .channels_min = 2, | ||
367 | .channels_max = 2, | ||
368 | .nid = nvhdmi_master_con_nid_7x, | ||
369 | .rates = SUPPORTED_RATES, | ||
370 | .maxbps = SUPPORTED_MAXBPS, | ||
371 | .formats = SUPPORTED_FORMATS, | ||
372 | .ops = { | ||
373 | .open = nvhdmi_dig_playback_pcm_open, | ||
374 | .close = nvhdmi_dig_playback_pcm_close_2ch, | ||
375 | .prepare = nvhdmi_dig_playback_pcm_prepare_2ch | ||
376 | }, | ||
377 | }; | ||
378 | |||
379 | static int nvhdmi_build_pcms_8ch_89(struct hda_codec *codec) | ||
380 | { | ||
381 | struct hdmi_spec *spec = codec->spec; | ||
382 | struct hda_pcm *info = spec->pcm_rec; | ||
383 | int i; | ||
384 | |||
385 | codec->num_pcms = spec->num_cvts; | ||
386 | codec->pcm_info = info; | ||
387 | |||
388 | for (i = 0; i < codec->num_pcms; i++, info++) { | ||
389 | unsigned int chans; | ||
390 | |||
391 | chans = get_wcaps(codec, spec->cvt[i]); | ||
392 | chans = get_wcaps_channels(chans); | ||
393 | |||
394 | info->name = nvhdmi_pcm_names[i]; | ||
395 | info->pcm_type = HDA_PCM_TYPE_HDMI; | ||
396 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] | ||
397 | = nvhdmi_pcm_digital_playback_8ch_89; | ||
398 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->cvt[i]; | ||
399 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans; | ||
400 | } | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | static int nvhdmi_build_pcms_8ch_7x(struct hda_codec *codec) | ||
406 | { | ||
407 | struct hdmi_spec *spec = codec->spec; | ||
408 | struct hda_pcm *info = spec->pcm_rec; | ||
409 | |||
410 | codec->num_pcms = 1; | ||
411 | codec->pcm_info = info; | ||
412 | |||
413 | info->name = "NVIDIA HDMI"; | ||
414 | info->pcm_type = HDA_PCM_TYPE_HDMI; | ||
415 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] | ||
416 | = nvhdmi_pcm_digital_playback_8ch_7x; | ||
417 | |||
418 | return 0; | ||
419 | } | ||
420 | |||
421 | static int nvhdmi_build_pcms_2ch(struct hda_codec *codec) | ||
422 | { | ||
423 | struct hdmi_spec *spec = codec->spec; | ||
424 | struct hda_pcm *info = spec->pcm_rec; | ||
425 | |||
426 | codec->num_pcms = 1; | ||
427 | codec->pcm_info = info; | ||
428 | |||
429 | info->name = "NVIDIA HDMI"; | ||
430 | info->pcm_type = HDA_PCM_TYPE_HDMI; | ||
431 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] | ||
432 | = nvhdmi_pcm_digital_playback_2ch; | ||
433 | |||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | static struct hda_codec_ops nvhdmi_patch_ops_8ch_89 = { | ||
438 | .build_controls = nvhdmi_build_controls, | ||
439 | .build_pcms = nvhdmi_build_pcms_8ch_89, | ||
440 | .init = nvhdmi_init, | ||
441 | .free = nvhdmi_free, | ||
442 | .unsol_event = hdmi_unsol_event, | ||
443 | }; | ||
444 | |||
445 | static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = { | ||
446 | .build_controls = nvhdmi_build_controls, | ||
447 | .build_pcms = nvhdmi_build_pcms_8ch_7x, | ||
448 | .init = nvhdmi_init, | ||
449 | .free = nvhdmi_free, | ||
450 | }; | ||
451 | |||
452 | static struct hda_codec_ops nvhdmi_patch_ops_2ch = { | ||
453 | .build_controls = nvhdmi_build_controls, | ||
454 | .build_pcms = nvhdmi_build_pcms_2ch, | ||
455 | .init = nvhdmi_init, | ||
456 | .free = nvhdmi_free, | ||
457 | }; | ||
458 | |||
459 | static int patch_nvhdmi_8ch_89(struct hda_codec *codec) | ||
460 | { | ||
461 | struct hdmi_spec *spec; | ||
462 | int i; | ||
463 | |||
464 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
465 | if (spec == NULL) | ||
466 | return -ENOMEM; | ||
467 | |||
468 | codec->spec = spec; | ||
469 | spec->codec_type = HDA_CODEC_NVIDIA_MCP89; | ||
470 | spec->old_pin_detect = 1; | ||
471 | |||
472 | if (hdmi_parse_codec(codec) < 0) { | ||
473 | codec->spec = NULL; | ||
474 | kfree(spec); | ||
475 | return -EINVAL; | ||
476 | } | ||
477 | codec->patch_ops = nvhdmi_patch_ops_8ch_89; | ||
478 | |||
479 | for (i = 0; i < spec->num_pins; i++) | ||
480 | snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i); | ||
481 | |||
482 | init_channel_allocations(); | ||
483 | |||
484 | return 0; | ||
485 | } | ||
486 | |||
487 | static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) | ||
488 | { | ||
489 | struct hdmi_spec *spec; | ||
490 | |||
491 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
492 | if (spec == NULL) | ||
493 | return -ENOMEM; | ||
494 | |||
495 | codec->spec = spec; | ||
496 | |||
497 | spec->multiout.num_dacs = 0; /* no analog */ | ||
498 | spec->multiout.max_channels = 8; | ||
499 | spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; | ||
500 | spec->codec_type = HDA_CODEC_NVIDIA_MCP7X; | ||
501 | spec->old_pin_detect = 1; | ||
502 | |||
503 | codec->patch_ops = nvhdmi_patch_ops_8ch_7x; | ||
504 | |||
505 | return 0; | ||
506 | } | ||
507 | |||
508 | static int patch_nvhdmi_2ch(struct hda_codec *codec) | ||
509 | { | ||
510 | struct hdmi_spec *spec; | ||
511 | |||
512 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
513 | if (spec == NULL) | ||
514 | return -ENOMEM; | ||
515 | |||
516 | codec->spec = spec; | ||
517 | |||
518 | spec->multiout.num_dacs = 0; /* no analog */ | ||
519 | spec->multiout.max_channels = 2; | ||
520 | spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; | ||
521 | spec->codec_type = HDA_CODEC_NVIDIA_MCP7X; | ||
522 | spec->old_pin_detect = 1; | ||
523 | |||
524 | codec->patch_ops = nvhdmi_patch_ops_2ch; | ||
525 | |||
526 | return 0; | ||
527 | } | ||
528 | |||
529 | /* | ||
530 | * patch entries | ||
531 | */ | ||
532 | static struct hda_codec_preset snd_hda_preset_nvhdmi[] = { | ||
533 | { .id = 0x10de0002, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
534 | { .id = 0x10de0003, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
535 | { .id = 0x10de0005, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
536 | { .id = 0x10de0006, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
537 | { .id = 0x10de0007, .name = "MCP79/7A HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
538 | { .id = 0x10de000a, .name = "GPU 0a HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
539 | { .id = 0x10de000b, .name = "GPU 0b HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
540 | { .id = 0x10de000c, .name = "MCP89 HDMI", .patch = patch_nvhdmi_8ch_89 }, | ||
541 | { .id = 0x10de000d, .name = "GPU 0d HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
542 | { .id = 0x10de0010, .name = "GPU 10 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
543 | { .id = 0x10de0011, .name = "GPU 11 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
544 | { .id = 0x10de0012, .name = "GPU 12 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
545 | { .id = 0x10de0013, .name = "GPU 13 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
546 | { .id = 0x10de0014, .name = "GPU 14 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
547 | { .id = 0x10de0018, .name = "GPU 18 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
548 | { .id = 0x10de0019, .name = "GPU 19 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
549 | { .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
550 | { .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
551 | { .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
552 | { .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
553 | { .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
554 | { .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
555 | { .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
556 | { .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
557 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, | ||
558 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, | ||
559 | {} /* terminator */ | ||
560 | }; | ||
561 | |||
562 | MODULE_ALIAS("snd-hda-codec-id:10de0002"); | ||
563 | MODULE_ALIAS("snd-hda-codec-id:10de0003"); | ||
564 | MODULE_ALIAS("snd-hda-codec-id:10de0005"); | ||
565 | MODULE_ALIAS("snd-hda-codec-id:10de0006"); | ||
566 | MODULE_ALIAS("snd-hda-codec-id:10de0007"); | ||
567 | MODULE_ALIAS("snd-hda-codec-id:10de000a"); | ||
568 | MODULE_ALIAS("snd-hda-codec-id:10de000b"); | ||
569 | MODULE_ALIAS("snd-hda-codec-id:10de000c"); | ||
570 | MODULE_ALIAS("snd-hda-codec-id:10de000d"); | ||
571 | MODULE_ALIAS("snd-hda-codec-id:10de0010"); | ||
572 | MODULE_ALIAS("snd-hda-codec-id:10de0011"); | ||
573 | MODULE_ALIAS("snd-hda-codec-id:10de0012"); | ||
574 | MODULE_ALIAS("snd-hda-codec-id:10de0013"); | ||
575 | MODULE_ALIAS("snd-hda-codec-id:10de0014"); | ||
576 | MODULE_ALIAS("snd-hda-codec-id:10de0018"); | ||
577 | MODULE_ALIAS("snd-hda-codec-id:10de0019"); | ||
578 | MODULE_ALIAS("snd-hda-codec-id:10de001a"); | ||
579 | MODULE_ALIAS("snd-hda-codec-id:10de001b"); | ||
580 | MODULE_ALIAS("snd-hda-codec-id:10de001c"); | ||
581 | MODULE_ALIAS("snd-hda-codec-id:10de0040"); | ||
582 | MODULE_ALIAS("snd-hda-codec-id:10de0041"); | ||
583 | MODULE_ALIAS("snd-hda-codec-id:10de0042"); | ||
584 | MODULE_ALIAS("snd-hda-codec-id:10de0043"); | ||
585 | MODULE_ALIAS("snd-hda-codec-id:10de0044"); | ||
586 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); | ||
587 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); | ||
588 | |||
589 | MODULE_LICENSE("GPL"); | ||
590 | MODULE_DESCRIPTION("NVIDIA HDMI HD-audio codec"); | ||
591 | |||
592 | static struct hda_codec_preset_list nvhdmi_list = { | ||
593 | .preset = snd_hda_preset_nvhdmi, | ||
594 | .owner = THIS_MODULE, | ||
595 | }; | ||
596 | |||
597 | static int __init patch_nvhdmi_init(void) | ||
598 | { | ||
599 | return snd_hda_add_codec_preset(&nvhdmi_list); | ||
600 | } | ||
601 | |||
602 | static void __exit patch_nvhdmi_exit(void) | ||
603 | { | ||
604 | snd_hda_delete_codec_preset(&nvhdmi_list); | ||
605 | } | ||
606 | |||
607 | module_init(patch_nvhdmi_init) | ||
608 | module_exit(patch_nvhdmi_exit) | ||
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a432e6efd19b..5f00589cb791 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/pci.h> | 29 | #include <linux/pci.h> |
30 | #include <sound/core.h> | 30 | #include <sound/core.h> |
31 | #include <sound/jack.h> | ||
31 | #include "hda_codec.h" | 32 | #include "hda_codec.h" |
32 | #include "hda_local.h" | 33 | #include "hda_local.h" |
33 | #include "hda_beep.h" | 34 | #include "hda_beep.h" |
@@ -282,6 +283,12 @@ struct alc_mic_route { | |||
282 | unsigned char amix_idx; | 283 | unsigned char amix_idx; |
283 | }; | 284 | }; |
284 | 285 | ||
286 | struct alc_jack { | ||
287 | hda_nid_t nid; | ||
288 | int type; | ||
289 | struct snd_jack *jack; | ||
290 | }; | ||
291 | |||
285 | #define MUX_IDX_UNDEF ((unsigned char)-1) | 292 | #define MUX_IDX_UNDEF ((unsigned char)-1) |
286 | 293 | ||
287 | struct alc_customize_define { | 294 | struct alc_customize_define { |
@@ -294,6 +301,7 @@ struct alc_customize_define { | |||
294 | unsigned int platform_type:1; | 301 | unsigned int platform_type:1; |
295 | unsigned int swap:1; | 302 | unsigned int swap:1; |
296 | unsigned int override:1; | 303 | unsigned int override:1; |
304 | unsigned int fixup:1; /* Means that this sku is set by driver, not read from hw */ | ||
297 | }; | 305 | }; |
298 | 306 | ||
299 | struct alc_spec { | 307 | struct alc_spec { |
@@ -357,6 +365,9 @@ struct alc_spec { | |||
357 | /* PCM information */ | 365 | /* PCM information */ |
358 | struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ | 366 | struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ |
359 | 367 | ||
368 | /* jack detection */ | ||
369 | struct snd_array jacks; | ||
370 | |||
360 | /* dynamic controls, init_verbs and input_mux */ | 371 | /* dynamic controls, init_verbs and input_mux */ |
361 | struct auto_pin_cfg autocfg; | 372 | struct auto_pin_cfg autocfg; |
362 | struct alc_customize_define cdefine; | 373 | struct alc_customize_define cdefine; |
@@ -383,6 +394,7 @@ struct alc_spec { | |||
383 | unsigned int no_analog :1; /* digital I/O only */ | 394 | unsigned int no_analog :1; /* digital I/O only */ |
384 | unsigned int dual_adc_switch:1; /* switch ADCs (for ALC275) */ | 395 | unsigned int dual_adc_switch:1; /* switch ADCs (for ALC275) */ |
385 | int init_amp; | 396 | int init_amp; |
397 | int codec_variant; /* flag for other variants */ | ||
386 | 398 | ||
387 | /* for virtual master */ | 399 | /* for virtual master */ |
388 | hda_nid_t vmaster_nid; | 400 | hda_nid_t vmaster_nid; |
@@ -846,7 +858,7 @@ static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid, | |||
846 | { | 858 | { |
847 | unsigned int val = PIN_IN; | 859 | unsigned int val = PIN_IN; |
848 | 860 | ||
849 | if (auto_pin_type <= AUTO_PIN_FRONT_MIC) { | 861 | if (auto_pin_type == AUTO_PIN_MIC) { |
850 | unsigned int pincap; | 862 | unsigned int pincap; |
851 | unsigned int oldval; | 863 | unsigned int oldval; |
852 | oldval = snd_hda_codec_read(codec, nid, 0, | 864 | oldval = snd_hda_codec_read(codec, nid, 0, |
@@ -866,6 +878,28 @@ static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid, | |||
866 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val); | 878 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val); |
867 | } | 879 | } |
868 | 880 | ||
881 | static void alc_fixup_autocfg_pin_nums(struct hda_codec *codec) | ||
882 | { | ||
883 | struct alc_spec *spec = codec->spec; | ||
884 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
885 | |||
886 | if (!cfg->line_outs) { | ||
887 | while (cfg->line_outs < AUTO_CFG_MAX_OUTS && | ||
888 | cfg->line_out_pins[cfg->line_outs]) | ||
889 | cfg->line_outs++; | ||
890 | } | ||
891 | if (!cfg->speaker_outs) { | ||
892 | while (cfg->speaker_outs < AUTO_CFG_MAX_OUTS && | ||
893 | cfg->speaker_pins[cfg->speaker_outs]) | ||
894 | cfg->speaker_outs++; | ||
895 | } | ||
896 | if (!cfg->hp_outs) { | ||
897 | while (cfg->hp_outs < AUTO_CFG_MAX_OUTS && | ||
898 | cfg->hp_pins[cfg->hp_outs]) | ||
899 | cfg->hp_outs++; | ||
900 | } | ||
901 | } | ||
902 | |||
869 | /* | 903 | /* |
870 | */ | 904 | */ |
871 | static void add_mixer(struct alc_spec *spec, struct snd_kcontrol_new *mix) | 905 | static void add_mixer(struct alc_spec *spec, struct snd_kcontrol_new *mix) |
@@ -934,6 +968,8 @@ static void setup_preset(struct hda_codec *codec, | |||
934 | 968 | ||
935 | if (preset->setup) | 969 | if (preset->setup) |
936 | preset->setup(codec); | 970 | preset->setup(codec); |
971 | |||
972 | alc_fixup_autocfg_pin_nums(codec); | ||
937 | } | 973 | } |
938 | 974 | ||
939 | /* Enable GPIO mask and set output */ | 975 | /* Enable GPIO mask and set output */ |
@@ -990,25 +1026,136 @@ static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid, | |||
990 | alc_fix_pll(codec); | 1026 | alc_fix_pll(codec); |
991 | } | 1027 | } |
992 | 1028 | ||
993 | static void alc_automute_pin(struct hda_codec *codec) | 1029 | #ifdef CONFIG_SND_HDA_INPUT_JACK |
1030 | static void alc_free_jack_priv(struct snd_jack *jack) | ||
1031 | { | ||
1032 | struct alc_jack *jacks = jack->private_data; | ||
1033 | jacks->nid = 0; | ||
1034 | jacks->jack = NULL; | ||
1035 | } | ||
1036 | |||
1037 | static int alc_add_jack(struct hda_codec *codec, | ||
1038 | hda_nid_t nid, int type) | ||
1039 | { | ||
1040 | struct alc_spec *spec; | ||
1041 | struct alc_jack *jack; | ||
1042 | const char *name; | ||
1043 | int err; | ||
1044 | |||
1045 | spec = codec->spec; | ||
1046 | snd_array_init(&spec->jacks, sizeof(*jack), 32); | ||
1047 | jack = snd_array_new(&spec->jacks); | ||
1048 | if (!jack) | ||
1049 | return -ENOMEM; | ||
1050 | |||
1051 | jack->nid = nid; | ||
1052 | jack->type = type; | ||
1053 | name = (type == SND_JACK_HEADPHONE) ? "Headphone" : "Mic" ; | ||
1054 | |||
1055 | err = snd_jack_new(codec->bus->card, name, type, &jack->jack); | ||
1056 | if (err < 0) | ||
1057 | return err; | ||
1058 | jack->jack->private_data = jack; | ||
1059 | jack->jack->private_free = alc_free_jack_priv; | ||
1060 | return 0; | ||
1061 | } | ||
1062 | |||
1063 | static void alc_report_jack(struct hda_codec *codec, hda_nid_t nid) | ||
994 | { | 1064 | { |
995 | struct alc_spec *spec = codec->spec; | 1065 | struct alc_spec *spec = codec->spec; |
996 | unsigned int nid = spec->autocfg.hp_pins[0]; | 1066 | struct alc_jack *jacks = spec->jacks.list; |
1067 | |||
1068 | if (jacks) { | ||
1069 | int i; | ||
1070 | for (i = 0; i < spec->jacks.used; i++) { | ||
1071 | if (jacks->nid == nid) { | ||
1072 | unsigned int present; | ||
1073 | present = snd_hda_jack_detect(codec, nid); | ||
1074 | |||
1075 | present = (present) ? jacks->type : 0; | ||
1076 | |||
1077 | snd_jack_report(jacks->jack, present); | ||
1078 | } | ||
1079 | jacks++; | ||
1080 | } | ||
1081 | } | ||
1082 | } | ||
1083 | |||
1084 | static int alc_init_jacks(struct hda_codec *codec) | ||
1085 | { | ||
1086 | struct alc_spec *spec = codec->spec; | ||
1087 | int err; | ||
1088 | unsigned int hp_nid = spec->autocfg.hp_pins[0]; | ||
1089 | unsigned int mic_nid = spec->ext_mic.pin; | ||
1090 | |||
1091 | if (hp_nid) { | ||
1092 | err = alc_add_jack(codec, hp_nid, SND_JACK_HEADPHONE); | ||
1093 | if (err < 0) | ||
1094 | return err; | ||
1095 | alc_report_jack(codec, hp_nid); | ||
1096 | } | ||
1097 | |||
1098 | if (mic_nid) { | ||
1099 | err = alc_add_jack(codec, mic_nid, SND_JACK_MICROPHONE); | ||
1100 | if (err < 0) | ||
1101 | return err; | ||
1102 | alc_report_jack(codec, mic_nid); | ||
1103 | } | ||
1104 | |||
1105 | return 0; | ||
1106 | } | ||
1107 | #else | ||
1108 | static inline void alc_report_jack(struct hda_codec *codec, hda_nid_t nid) | ||
1109 | { | ||
1110 | } | ||
1111 | |||
1112 | static inline int alc_init_jacks(struct hda_codec *codec) | ||
1113 | { | ||
1114 | return 0; | ||
1115 | } | ||
1116 | #endif | ||
1117 | |||
1118 | static void alc_automute_speaker(struct hda_codec *codec, int pinctl) | ||
1119 | { | ||
1120 | struct alc_spec *spec = codec->spec; | ||
1121 | unsigned int mute; | ||
1122 | hda_nid_t nid; | ||
997 | int i; | 1123 | int i; |
998 | 1124 | ||
999 | if (!nid) | 1125 | spec->jack_present = 0; |
1000 | return; | 1126 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) { |
1001 | spec->jack_present = snd_hda_jack_detect(codec, nid); | 1127 | nid = spec->autocfg.hp_pins[i]; |
1128 | if (!nid) | ||
1129 | break; | ||
1130 | if (snd_hda_jack_detect(codec, nid)) { | ||
1131 | spec->jack_present = 1; | ||
1132 | break; | ||
1133 | } | ||
1134 | alc_report_jack(codec, spec->autocfg.hp_pins[i]); | ||
1135 | } | ||
1136 | |||
1137 | mute = spec->jack_present ? HDA_AMP_MUTE : 0; | ||
1138 | /* Toggle internal speakers muting */ | ||
1002 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) { | 1139 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) { |
1003 | nid = spec->autocfg.speaker_pins[i]; | 1140 | nid = spec->autocfg.speaker_pins[i]; |
1004 | if (!nid) | 1141 | if (!nid) |
1005 | break; | 1142 | break; |
1006 | snd_hda_codec_write(codec, nid, 0, | 1143 | if (pinctl) { |
1144 | snd_hda_codec_write(codec, nid, 0, | ||
1007 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 1145 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
1008 | spec->jack_present ? 0 : PIN_OUT); | 1146 | spec->jack_present ? 0 : PIN_OUT); |
1147 | } else { | ||
1148 | snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, | ||
1149 | HDA_AMP_MUTE, mute); | ||
1150 | } | ||
1009 | } | 1151 | } |
1010 | } | 1152 | } |
1011 | 1153 | ||
1154 | static void alc_automute_pin(struct hda_codec *codec) | ||
1155 | { | ||
1156 | alc_automute_speaker(codec, 1); | ||
1157 | } | ||
1158 | |||
1012 | static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, | 1159 | static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, |
1013 | hda_nid_t nid) | 1160 | hda_nid_t nid) |
1014 | { | 1161 | { |
@@ -1090,6 +1237,7 @@ static void alc_mic_automute(struct hda_codec *codec) | |||
1090 | AC_VERB_SET_CONNECT_SEL, | 1237 | AC_VERB_SET_CONNECT_SEL, |
1091 | alive->mux_idx); | 1238 | alive->mux_idx); |
1092 | } | 1239 | } |
1240 | alc_report_jack(codec, spec->ext_mic.pin); | ||
1093 | 1241 | ||
1094 | /* FIXME: analog mixer */ | 1242 | /* FIXME: analog mixer */ |
1095 | } | 1243 | } |
@@ -1236,24 +1384,35 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type) | |||
1236 | static void alc_init_auto_hp(struct hda_codec *codec) | 1384 | static void alc_init_auto_hp(struct hda_codec *codec) |
1237 | { | 1385 | { |
1238 | struct alc_spec *spec = codec->spec; | 1386 | struct alc_spec *spec = codec->spec; |
1387 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
1388 | int i; | ||
1239 | 1389 | ||
1240 | if (!spec->autocfg.hp_pins[0]) | 1390 | if (!cfg->hp_pins[0]) { |
1241 | return; | 1391 | if (cfg->line_out_type != AUTO_PIN_HP_OUT) |
1392 | return; | ||
1393 | } | ||
1242 | 1394 | ||
1243 | if (!spec->autocfg.speaker_pins[0]) { | 1395 | if (!cfg->speaker_pins[0]) { |
1244 | if (spec->autocfg.line_out_pins[0] && | 1396 | if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) |
1245 | spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT) | ||
1246 | spec->autocfg.speaker_pins[0] = | ||
1247 | spec->autocfg.line_out_pins[0]; | ||
1248 | else | ||
1249 | return; | 1397 | return; |
1398 | memcpy(cfg->speaker_pins, cfg->line_out_pins, | ||
1399 | sizeof(cfg->speaker_pins)); | ||
1400 | cfg->speaker_outs = cfg->line_outs; | ||
1250 | } | 1401 | } |
1251 | 1402 | ||
1252 | snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n", | 1403 | if (!cfg->hp_pins[0]) { |
1253 | spec->autocfg.hp_pins[0]); | 1404 | memcpy(cfg->hp_pins, cfg->line_out_pins, |
1254 | snd_hda_codec_write_cache(codec, spec->autocfg.hp_pins[0], 0, | 1405 | sizeof(cfg->hp_pins)); |
1406 | cfg->hp_outs = cfg->line_outs; | ||
1407 | } | ||
1408 | |||
1409 | for (i = 0; i < cfg->hp_outs; i++) { | ||
1410 | snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n", | ||
1411 | cfg->hp_pins[i]); | ||
1412 | snd_hda_codec_write_cache(codec, cfg->hp_pins[i], 0, | ||
1255 | AC_VERB_SET_UNSOLICITED_ENABLE, | 1413 | AC_VERB_SET_UNSOLICITED_ENABLE, |
1256 | AC_USRSP_EN | ALC880_HP_EVENT); | 1414 | AC_USRSP_EN | ALC880_HP_EVENT); |
1415 | } | ||
1257 | spec->unsol_event = alc_sku_unsol_event; | 1416 | spec->unsol_event = alc_sku_unsol_event; |
1258 | } | 1417 | } |
1259 | 1418 | ||
@@ -1265,30 +1424,28 @@ static void alc_init_auto_mic(struct hda_codec *codec) | |||
1265 | int i; | 1424 | int i; |
1266 | 1425 | ||
1267 | /* there must be only two mic inputs exclusively */ | 1426 | /* there must be only two mic inputs exclusively */ |
1268 | for (i = AUTO_PIN_LINE; i < AUTO_PIN_LAST; i++) | 1427 | for (i = 0; i < cfg->num_inputs; i++) |
1269 | if (cfg->input_pins[i]) | 1428 | if (cfg->inputs[i].type >= AUTO_PIN_LINE_IN) |
1270 | return; | 1429 | return; |
1271 | 1430 | ||
1272 | fixed = ext = 0; | 1431 | fixed = ext = 0; |
1273 | for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++) { | 1432 | for (i = 0; i < cfg->num_inputs; i++) { |
1274 | hda_nid_t nid = cfg->input_pins[i]; | 1433 | hda_nid_t nid = cfg->inputs[i].pin; |
1275 | unsigned int defcfg; | 1434 | unsigned int defcfg; |
1276 | if (!nid) | ||
1277 | return; | ||
1278 | defcfg = snd_hda_codec_get_pincfg(codec, nid); | 1435 | defcfg = snd_hda_codec_get_pincfg(codec, nid); |
1279 | switch (get_defcfg_connect(defcfg)) { | 1436 | switch (snd_hda_get_input_pin_attr(defcfg)) { |
1280 | case AC_JACK_PORT_FIXED: | 1437 | case INPUT_PIN_ATTR_INT: |
1281 | if (fixed) | 1438 | if (fixed) |
1282 | return; /* already occupied */ | 1439 | return; /* already occupied */ |
1283 | fixed = nid; | 1440 | fixed = nid; |
1284 | break; | 1441 | break; |
1285 | case AC_JACK_PORT_COMPLEX: | 1442 | case INPUT_PIN_ATTR_UNUSED: |
1443 | return; /* invalid entry */ | ||
1444 | default: | ||
1286 | if (ext) | 1445 | if (ext) |
1287 | return; /* already occupied */ | 1446 | return; /* already occupied */ |
1288 | ext = nid; | 1447 | ext = nid; |
1289 | break; | 1448 | break; |
1290 | default: | ||
1291 | return; /* invalid entry */ | ||
1292 | } | 1449 | } |
1293 | } | 1450 | } |
1294 | if (!ext || !fixed) | 1451 | if (!ext || !fixed) |
@@ -1308,6 +1465,11 @@ static void alc_init_auto_mic(struct hda_codec *codec) | |||
1308 | spec->unsol_event = alc_sku_unsol_event; | 1465 | spec->unsol_event = alc_sku_unsol_event; |
1309 | } | 1466 | } |
1310 | 1467 | ||
1468 | /* Could be any non-zero and even value. When used as fixup, tells | ||
1469 | * the driver to ignore any present sku defines. | ||
1470 | */ | ||
1471 | #define ALC_FIXUP_SKU_IGNORE (2) | ||
1472 | |||
1311 | static int alc_auto_parse_customize_define(struct hda_codec *codec) | 1473 | static int alc_auto_parse_customize_define(struct hda_codec *codec) |
1312 | { | 1474 | { |
1313 | unsigned int ass, tmp, i; | 1475 | unsigned int ass, tmp, i; |
@@ -1316,6 +1478,13 @@ static int alc_auto_parse_customize_define(struct hda_codec *codec) | |||
1316 | 1478 | ||
1317 | spec->cdefine.enable_pcbeep = 1; /* assume always enabled */ | 1479 | spec->cdefine.enable_pcbeep = 1; /* assume always enabled */ |
1318 | 1480 | ||
1481 | if (spec->cdefine.fixup) { | ||
1482 | ass = spec->cdefine.sku_cfg; | ||
1483 | if (ass == ALC_FIXUP_SKU_IGNORE) | ||
1484 | return -1; | ||
1485 | goto do_sku; | ||
1486 | } | ||
1487 | |||
1319 | ass = codec->subsystem_id & 0xffff; | 1488 | ass = codec->subsystem_id & 0xffff; |
1320 | if (ass != codec->bus->pci->subsystem_device && (ass & 1)) | 1489 | if (ass != codec->bus->pci->subsystem_device && (ass & 1)) |
1321 | goto do_sku; | 1490 | goto do_sku; |
@@ -1383,6 +1552,13 @@ static int alc_subsystem_id(struct hda_codec *codec, | |||
1383 | unsigned nid; | 1552 | unsigned nid; |
1384 | struct alc_spec *spec = codec->spec; | 1553 | struct alc_spec *spec = codec->spec; |
1385 | 1554 | ||
1555 | if (spec->cdefine.fixup) { | ||
1556 | ass = spec->cdefine.sku_cfg; | ||
1557 | if (ass == ALC_FIXUP_SKU_IGNORE) | ||
1558 | return 0; | ||
1559 | goto do_sku; | ||
1560 | } | ||
1561 | |||
1386 | ass = codec->subsystem_id & 0xffff; | 1562 | ass = codec->subsystem_id & 0xffff; |
1387 | if ((ass != codec->bus->pci->subsystem_device) && (ass & 1)) | 1563 | if ((ass != codec->bus->pci->subsystem_device) && (ass & 1)) |
1388 | goto do_sku; | 1564 | goto do_sku; |
@@ -1502,6 +1678,7 @@ struct alc_pincfg { | |||
1502 | }; | 1678 | }; |
1503 | 1679 | ||
1504 | struct alc_fixup { | 1680 | struct alc_fixup { |
1681 | unsigned int sku; | ||
1505 | const struct alc_pincfg *pins; | 1682 | const struct alc_pincfg *pins; |
1506 | const struct hda_verb *verbs; | 1683 | const struct hda_verb *verbs; |
1507 | }; | 1684 | }; |
@@ -1512,12 +1689,22 @@ static void alc_pick_fixup(struct hda_codec *codec, | |||
1512 | int pre_init) | 1689 | int pre_init) |
1513 | { | 1690 | { |
1514 | const struct alc_pincfg *cfg; | 1691 | const struct alc_pincfg *cfg; |
1692 | struct alc_spec *spec; | ||
1515 | 1693 | ||
1516 | quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk); | 1694 | quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk); |
1517 | if (!quirk) | 1695 | if (!quirk) |
1518 | return; | 1696 | return; |
1519 | fix += quirk->value; | 1697 | fix += quirk->value; |
1520 | cfg = fix->pins; | 1698 | cfg = fix->pins; |
1699 | if (pre_init && fix->sku) { | ||
1700 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
1701 | snd_printdd(KERN_INFO "hda_codec: %s: Apply sku override for %s\n", | ||
1702 | codec->chip_name, quirk->name); | ||
1703 | #endif | ||
1704 | spec = codec->spec; | ||
1705 | spec->cdefine.sku_cfg = fix->sku; | ||
1706 | spec->cdefine.fixup = 1; | ||
1707 | } | ||
1521 | if (pre_init && cfg) { | 1708 | if (pre_init && cfg) { |
1522 | #ifdef CONFIG_SND_DEBUG_VERBOSE | 1709 | #ifdef CONFIG_SND_DEBUG_VERBOSE |
1523 | snd_printdd(KERN_INFO "hda_codec: %s: Apply pincfg for %s\n", | 1710 | snd_printdd(KERN_INFO "hda_codec: %s: Apply pincfg for %s\n", |
@@ -1546,6 +1733,15 @@ static int alc_read_coef_idx(struct hda_codec *codec, | |||
1546 | return val; | 1733 | return val; |
1547 | } | 1734 | } |
1548 | 1735 | ||
1736 | static void alc_write_coef_idx(struct hda_codec *codec, unsigned int coef_idx, | ||
1737 | unsigned int coef_val) | ||
1738 | { | ||
1739 | snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, | ||
1740 | coef_idx); | ||
1741 | snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, | ||
1742 | coef_val); | ||
1743 | } | ||
1744 | |||
1549 | /* set right pin controls for digital I/O */ | 1745 | /* set right pin controls for digital I/O */ |
1550 | static void alc_auto_init_digital(struct hda_codec *codec) | 1746 | static void alc_auto_init_digital(struct hda_codec *codec) |
1551 | { | 1747 | { |
@@ -1723,31 +1919,7 @@ static struct hda_verb alc888_fujitsu_xa3530_verbs[] = { | |||
1723 | 1919 | ||
1724 | static void alc_automute_amp(struct hda_codec *codec) | 1920 | static void alc_automute_amp(struct hda_codec *codec) |
1725 | { | 1921 | { |
1726 | struct alc_spec *spec = codec->spec; | 1922 | alc_automute_speaker(codec, 0); |
1727 | unsigned int mute; | ||
1728 | hda_nid_t nid; | ||
1729 | int i; | ||
1730 | |||
1731 | spec->jack_present = 0; | ||
1732 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) { | ||
1733 | nid = spec->autocfg.hp_pins[i]; | ||
1734 | if (!nid) | ||
1735 | break; | ||
1736 | if (snd_hda_jack_detect(codec, nid)) { | ||
1737 | spec->jack_present = 1; | ||
1738 | break; | ||
1739 | } | ||
1740 | } | ||
1741 | |||
1742 | mute = spec->jack_present ? HDA_AMP_MUTE : 0; | ||
1743 | /* Toggle internal speakers muting */ | ||
1744 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) { | ||
1745 | nid = spec->autocfg.speaker_pins[i]; | ||
1746 | if (!nid) | ||
1747 | break; | ||
1748 | snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, | ||
1749 | HDA_AMP_MUTE, mute); | ||
1750 | } | ||
1751 | } | 1923 | } |
1752 | 1924 | ||
1753 | static void alc_automute_amp_unsol_event(struct hda_codec *codec, | 1925 | static void alc_automute_amp_unsol_event(struct hda_codec *codec, |
@@ -3602,10 +3774,7 @@ static int alc_init(struct hda_codec *codec) | |||
3602 | if (spec->init_hook) | 3774 | if (spec->init_hook) |
3603 | spec->init_hook(codec); | 3775 | spec->init_hook(codec); |
3604 | 3776 | ||
3605 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 3777 | hda_call_check_power_status(codec, 0x01); |
3606 | if (codec->patch_ops.check_power_status) | ||
3607 | codec->patch_ops.check_power_status(codec, 0x01); | ||
3608 | #endif | ||
3609 | return 0; | 3778 | return 0; |
3610 | } | 3779 | } |
3611 | 3780 | ||
@@ -4001,10 +4170,7 @@ static int alc_resume(struct hda_codec *codec) | |||
4001 | codec->patch_ops.init(codec); | 4170 | codec->patch_ops.init(codec); |
4002 | snd_hda_codec_resume_amp(codec); | 4171 | snd_hda_codec_resume_amp(codec); |
4003 | snd_hda_codec_resume_cache(codec); | 4172 | snd_hda_codec_resume_cache(codec); |
4004 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 4173 | hda_call_check_power_status(codec, 0x01); |
4005 | if (codec->patch_ops.check_power_status) | ||
4006 | codec->patch_ops.check_power_status(codec, 0x01); | ||
4007 | #endif | ||
4008 | return 0; | 4174 | return 0; |
4009 | } | 4175 | } |
4010 | #endif | 4176 | #endif |
@@ -4729,7 +4895,7 @@ static struct snd_kcontrol_new alc880_control_templates[] = { | |||
4729 | 4895 | ||
4730 | /* add dynamic controls */ | 4896 | /* add dynamic controls */ |
4731 | static int add_control(struct alc_spec *spec, int type, const char *name, | 4897 | static int add_control(struct alc_spec *spec, int type, const char *name, |
4732 | unsigned long val) | 4898 | int cidx, unsigned long val) |
4733 | { | 4899 | { |
4734 | struct snd_kcontrol_new *knew; | 4900 | struct snd_kcontrol_new *knew; |
4735 | 4901 | ||
@@ -4741,6 +4907,7 @@ static int add_control(struct alc_spec *spec, int type, const char *name, | |||
4741 | knew->name = kstrdup(name, GFP_KERNEL); | 4907 | knew->name = kstrdup(name, GFP_KERNEL); |
4742 | if (!knew->name) | 4908 | if (!knew->name) |
4743 | return -ENOMEM; | 4909 | return -ENOMEM; |
4910 | knew->index = cidx; | ||
4744 | if (get_amp_nid_(val)) | 4911 | if (get_amp_nid_(val)) |
4745 | knew->subdevice = HDA_SUBDEV_AMP_FLAG; | 4912 | knew->subdevice = HDA_SUBDEV_AMP_FLAG; |
4746 | knew->private_value = val; | 4913 | knew->private_value = val; |
@@ -4749,17 +4916,21 @@ static int add_control(struct alc_spec *spec, int type, const char *name, | |||
4749 | 4916 | ||
4750 | static int add_control_with_pfx(struct alc_spec *spec, int type, | 4917 | static int add_control_with_pfx(struct alc_spec *spec, int type, |
4751 | const char *pfx, const char *dir, | 4918 | const char *pfx, const char *dir, |
4752 | const char *sfx, unsigned long val) | 4919 | const char *sfx, int cidx, unsigned long val) |
4753 | { | 4920 | { |
4754 | char name[32]; | 4921 | char name[32]; |
4755 | snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx); | 4922 | snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx); |
4756 | return add_control(spec, type, name, val); | 4923 | return add_control(spec, type, name, cidx, val); |
4757 | } | 4924 | } |
4758 | 4925 | ||
4759 | #define add_pb_vol_ctrl(spec, type, pfx, val) \ | 4926 | #define add_pb_vol_ctrl(spec, type, pfx, val) \ |
4760 | add_control_with_pfx(spec, type, pfx, "Playback", "Volume", val) | 4927 | add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val) |
4761 | #define add_pb_sw_ctrl(spec, type, pfx, val) \ | 4928 | #define add_pb_sw_ctrl(spec, type, pfx, val) \ |
4762 | add_control_with_pfx(spec, type, pfx, "Playback", "Switch", val) | 4929 | add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val) |
4930 | #define __add_pb_vol_ctrl(spec, type, pfx, cidx, val) \ | ||
4931 | add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val) | ||
4932 | #define __add_pb_sw_ctrl(spec, type, pfx, cidx, val) \ | ||
4933 | add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val) | ||
4763 | 4934 | ||
4764 | #define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17) | 4935 | #define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17) |
4765 | #define alc880_fixed_pin_idx(nid) ((nid) - 0x14) | 4936 | #define alc880_fixed_pin_idx(nid) ((nid) - 0x14) |
@@ -4912,16 +5083,16 @@ static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, | |||
4912 | 5083 | ||
4913 | /* create input playback/capture controls for the given pin */ | 5084 | /* create input playback/capture controls for the given pin */ |
4914 | static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, | 5085 | static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, |
4915 | const char *ctlname, | 5086 | const char *ctlname, int ctlidx, |
4916 | int idx, hda_nid_t mix_nid) | 5087 | int idx, hda_nid_t mix_nid) |
4917 | { | 5088 | { |
4918 | int err; | 5089 | int err; |
4919 | 5090 | ||
4920 | err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, | 5091 | err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, ctlidx, |
4921 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); | 5092 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); |
4922 | if (err < 0) | 5093 | if (err < 0) |
4923 | return err; | 5094 | return err; |
4924 | err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, | 5095 | err = __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, ctlidx, |
4925 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); | 5096 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); |
4926 | if (err < 0) | 5097 | if (err < 0) |
4927 | return err; | 5098 | return err; |
@@ -4942,20 +5113,27 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec, | |||
4942 | { | 5113 | { |
4943 | struct alc_spec *spec = codec->spec; | 5114 | struct alc_spec *spec = codec->spec; |
4944 | struct hda_input_mux *imux = &spec->private_imux[0]; | 5115 | struct hda_input_mux *imux = &spec->private_imux[0]; |
4945 | int i, err, idx; | 5116 | int i, err, idx, type, type_idx = 0; |
4946 | 5117 | ||
4947 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 5118 | for (i = 0; i < cfg->num_inputs; i++) { |
4948 | hda_nid_t pin; | 5119 | hda_nid_t pin; |
5120 | const char *label; | ||
4949 | 5121 | ||
4950 | pin = cfg->input_pins[i]; | 5122 | pin = cfg->inputs[i].pin; |
4951 | if (!alc_is_input_pin(codec, pin)) | 5123 | if (!alc_is_input_pin(codec, pin)) |
4952 | continue; | 5124 | continue; |
4953 | 5125 | ||
5126 | type = cfg->inputs[i].type; | ||
5127 | if (i > 0 && type == cfg->inputs[i - 1].type) | ||
5128 | type_idx++; | ||
5129 | else | ||
5130 | type_idx = 0; | ||
5131 | label = hda_get_autocfg_input_label(codec, cfg, i); | ||
4954 | if (mixer) { | 5132 | if (mixer) { |
4955 | idx = get_connection_index(codec, mixer, pin); | 5133 | idx = get_connection_index(codec, mixer, pin); |
4956 | if (idx >= 0) { | 5134 | if (idx >= 0) { |
4957 | err = new_analog_input(spec, pin, | 5135 | err = new_analog_input(spec, pin, |
4958 | auto_pin_cfg_labels[i], | 5136 | label, type_idx, |
4959 | idx, mixer); | 5137 | idx, mixer); |
4960 | if (err < 0) | 5138 | if (err < 0) |
4961 | return err; | 5139 | return err; |
@@ -4967,12 +5145,8 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec, | |||
4967 | idx = get_connection_index(codec, cap1, pin); | 5145 | idx = get_connection_index(codec, cap1, pin); |
4968 | if (idx < 0 && cap2) | 5146 | if (idx < 0 && cap2) |
4969 | idx = get_connection_index(codec, cap2, pin); | 5147 | idx = get_connection_index(codec, cap2, pin); |
4970 | if (idx >= 0) { | 5148 | if (idx >= 0) |
4971 | imux->items[imux->num_items].label = | 5149 | snd_hda_add_imux_item(imux, label, idx, NULL); |
4972 | auto_pin_cfg_labels[i]; | ||
4973 | imux->items[imux->num_items].index = idx; | ||
4974 | imux->num_items++; | ||
4975 | } | ||
4976 | } | 5150 | } |
4977 | return 0; | 5151 | return 0; |
4978 | } | 5152 | } |
@@ -5044,12 +5218,13 @@ static void alc880_auto_init_extra_out(struct hda_codec *codec) | |||
5044 | static void alc880_auto_init_analog_input(struct hda_codec *codec) | 5218 | static void alc880_auto_init_analog_input(struct hda_codec *codec) |
5045 | { | 5219 | { |
5046 | struct alc_spec *spec = codec->spec; | 5220 | struct alc_spec *spec = codec->spec; |
5221 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
5047 | int i; | 5222 | int i; |
5048 | 5223 | ||
5049 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 5224 | for (i = 0; i < cfg->num_inputs; i++) { |
5050 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 5225 | hda_nid_t nid = cfg->inputs[i].pin; |
5051 | if (alc_is_input_pin(codec, nid)) { | 5226 | if (alc_is_input_pin(codec, nid)) { |
5052 | alc_set_input_pin(codec, nid, i); | 5227 | alc_set_input_pin(codec, nid, cfg->inputs[i].type); |
5053 | if (nid != ALC880_PIN_CD_NID && | 5228 | if (nid != ALC880_PIN_CD_NID && |
5054 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) | 5229 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) |
5055 | snd_hda_codec_write(codec, nid, 0, | 5230 | snd_hda_codec_write(codec, nid, 0, |
@@ -5214,19 +5389,13 @@ static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin) | |||
5214 | static void fixup_single_adc(struct hda_codec *codec) | 5389 | static void fixup_single_adc(struct hda_codec *codec) |
5215 | { | 5390 | { |
5216 | struct alc_spec *spec = codec->spec; | 5391 | struct alc_spec *spec = codec->spec; |
5217 | hda_nid_t pin = 0; | 5392 | struct auto_pin_cfg *cfg = &spec->autocfg; |
5218 | int i; | 5393 | int i; |
5219 | 5394 | ||
5220 | /* search for the input pin; there must be only one */ | 5395 | /* search for the input pin; there must be only one */ |
5221 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 5396 | if (cfg->num_inputs != 1) |
5222 | if (spec->autocfg.input_pins[i]) { | ||
5223 | pin = spec->autocfg.input_pins[i]; | ||
5224 | break; | ||
5225 | } | ||
5226 | } | ||
5227 | if (!pin) | ||
5228 | return; | 5397 | return; |
5229 | i = init_capsrc_for_pin(codec, pin); | 5398 | i = init_capsrc_for_pin(codec, cfg->inputs[0].pin); |
5230 | if (i >= 0) { | 5399 | if (i >= 0) { |
5231 | /* use only this ADC */ | 5400 | /* use only this ADC */ |
5232 | if (spec->capsrc_nids) | 5401 | if (spec->capsrc_nids) |
@@ -5279,6 +5448,7 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids, | |||
5279 | int num_nids) | 5448 | int num_nids) |
5280 | { | 5449 | { |
5281 | struct alc_spec *spec = codec->spec; | 5450 | struct alc_spec *spec = codec->spec; |
5451 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
5282 | int n; | 5452 | int n; |
5283 | hda_nid_t fallback_adc = 0, fallback_cap = 0; | 5453 | hda_nid_t fallback_adc = 0, fallback_cap = 0; |
5284 | 5454 | ||
@@ -5304,10 +5474,8 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids, | |||
5304 | fallback_adc = adc; | 5474 | fallback_adc = adc; |
5305 | fallback_cap = cap; | 5475 | fallback_cap = cap; |
5306 | } | 5476 | } |
5307 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 5477 | for (i = 0; i < cfg->num_inputs; i++) { |
5308 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 5478 | hda_nid_t nid = cfg->inputs[i].pin; |
5309 | if (!nid) | ||
5310 | continue; | ||
5311 | for (j = 0; j < nconns; j++) { | 5479 | for (j = 0; j < nconns; j++) { |
5312 | if (conn[j] == nid) | 5480 | if (conn[j] == nid) |
5313 | break; | 5481 | break; |
@@ -5315,7 +5483,7 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids, | |||
5315 | if (j >= nconns) | 5483 | if (j >= nconns) |
5316 | break; | 5484 | break; |
5317 | } | 5485 | } |
5318 | if (i >= AUTO_PIN_LAST) { | 5486 | if (i >= cfg->num_inputs) { |
5319 | int num_adcs = spec->num_adc_nids; | 5487 | int num_adcs = spec->num_adc_nids; |
5320 | spec->private_adc_nids[num_adcs] = adc; | 5488 | spec->private_adc_nids[num_adcs] = adc; |
5321 | spec->private_capsrc_nids[num_adcs] = cap; | 5489 | spec->private_capsrc_nids[num_adcs] = cap; |
@@ -6683,12 +6851,13 @@ static void alc260_auto_init_multi_out(struct hda_codec *codec) | |||
6683 | static void alc260_auto_init_analog_input(struct hda_codec *codec) | 6851 | static void alc260_auto_init_analog_input(struct hda_codec *codec) |
6684 | { | 6852 | { |
6685 | struct alc_spec *spec = codec->spec; | 6853 | struct alc_spec *spec = codec->spec; |
6854 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
6686 | int i; | 6855 | int i; |
6687 | 6856 | ||
6688 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 6857 | for (i = 0; i < cfg->num_inputs; i++) { |
6689 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 6858 | hda_nid_t nid = cfg->inputs[i].pin; |
6690 | if (nid >= 0x12) { | 6859 | if (nid >= 0x12) { |
6691 | alc_set_input_pin(codec, nid, i); | 6860 | alc_set_input_pin(codec, nid, cfg->inputs[i].type); |
6692 | if (nid != ALC260_PIN_CD_NID && | 6861 | if (nid != ALC260_PIN_CD_NID && |
6693 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) | 6862 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) |
6694 | snd_hda_codec_write(codec, nid, 0, | 6863 | snd_hda_codec_write(codec, nid, 0, |
@@ -6810,14 +6979,12 @@ enum { | |||
6810 | PINFIX_HP_DC5750, | 6979 | PINFIX_HP_DC5750, |
6811 | }; | 6980 | }; |
6812 | 6981 | ||
6813 | static struct alc_pincfg alc260_hp_dc5750_pinfix[] = { | ||
6814 | { 0x11, 0x90130110 }, /* speaker */ | ||
6815 | { } | ||
6816 | }; | ||
6817 | |||
6818 | static const struct alc_fixup alc260_fixups[] = { | 6982 | static const struct alc_fixup alc260_fixups[] = { |
6819 | [PINFIX_HP_DC5750] = { | 6983 | [PINFIX_HP_DC5750] = { |
6820 | .pins = alc260_hp_dc5750_pinfix | 6984 | .pins = (const struct alc_pincfg[]) { |
6985 | { 0x11, 0x90130110 }, /* speaker */ | ||
6986 | { } | ||
6987 | } | ||
6821 | }, | 6988 | }, |
6822 | }; | 6989 | }; |
6823 | 6990 | ||
@@ -10461,32 +10628,33 @@ static struct alc_config_preset alc882_presets[] = { | |||
10461 | enum { | 10628 | enum { |
10462 | PINFIX_ABIT_AW9D_MAX, | 10629 | PINFIX_ABIT_AW9D_MAX, |
10463 | PINFIX_PB_M5210, | 10630 | PINFIX_PB_M5210, |
10464 | }; | 10631 | PINFIX_ACER_ASPIRE_7736, |
10465 | |||
10466 | static struct alc_pincfg alc882_abit_aw9d_pinfix[] = { | ||
10467 | { 0x15, 0x01080104 }, /* side */ | ||
10468 | { 0x16, 0x01011012 }, /* rear */ | ||
10469 | { 0x17, 0x01016011 }, /* clfe */ | ||
10470 | { } | ||
10471 | }; | ||
10472 | |||
10473 | static const struct hda_verb pb_m5210_verbs[] = { | ||
10474 | { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 }, | ||
10475 | {} | ||
10476 | }; | 10632 | }; |
10477 | 10633 | ||
10478 | static const struct alc_fixup alc882_fixups[] = { | 10634 | static const struct alc_fixup alc882_fixups[] = { |
10479 | [PINFIX_ABIT_AW9D_MAX] = { | 10635 | [PINFIX_ABIT_AW9D_MAX] = { |
10480 | .pins = alc882_abit_aw9d_pinfix | 10636 | .pins = (const struct alc_pincfg[]) { |
10637 | { 0x15, 0x01080104 }, /* side */ | ||
10638 | { 0x16, 0x01011012 }, /* rear */ | ||
10639 | { 0x17, 0x01016011 }, /* clfe */ | ||
10640 | { } | ||
10641 | } | ||
10481 | }, | 10642 | }, |
10482 | [PINFIX_PB_M5210] = { | 10643 | [PINFIX_PB_M5210] = { |
10483 | .verbs = pb_m5210_verbs | 10644 | .verbs = (const struct hda_verb[]) { |
10645 | { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 }, | ||
10646 | {} | ||
10647 | } | ||
10648 | }, | ||
10649 | [PINFIX_ACER_ASPIRE_7736] = { | ||
10650 | .sku = ALC_FIXUP_SKU_IGNORE, | ||
10484 | }, | 10651 | }, |
10485 | }; | 10652 | }; |
10486 | 10653 | ||
10487 | static struct snd_pci_quirk alc882_fixup_tbl[] = { | 10654 | static struct snd_pci_quirk alc882_fixup_tbl[] = { |
10488 | SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210), | 10655 | SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210), |
10489 | SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX), | 10656 | SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX), |
10657 | SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736), | ||
10490 | {} | 10658 | {} |
10491 | }; | 10659 | }; |
10492 | 10660 | ||
@@ -10535,16 +10703,21 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec) | |||
10535 | { | 10703 | { |
10536 | struct alc_spec *spec = codec->spec; | 10704 | struct alc_spec *spec = codec->spec; |
10537 | hda_nid_t pin, dac; | 10705 | hda_nid_t pin, dac; |
10706 | int i; | ||
10538 | 10707 | ||
10539 | pin = spec->autocfg.hp_pins[0]; | 10708 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) { |
10540 | if (pin) { | 10709 | pin = spec->autocfg.hp_pins[i]; |
10710 | if (!pin) | ||
10711 | break; | ||
10541 | dac = spec->multiout.hp_nid; | 10712 | dac = spec->multiout.hp_nid; |
10542 | if (!dac) | 10713 | if (!dac) |
10543 | dac = spec->multiout.dac_nids[0]; /* to front */ | 10714 | dac = spec->multiout.dac_nids[0]; /* to front */ |
10544 | alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac); | 10715 | alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac); |
10545 | } | 10716 | } |
10546 | pin = spec->autocfg.speaker_pins[0]; | 10717 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) { |
10547 | if (pin) { | 10718 | pin = spec->autocfg.speaker_pins[i]; |
10719 | if (!pin) | ||
10720 | break; | ||
10548 | dac = spec->multiout.extra_out_nid[0]; | 10721 | dac = spec->multiout.extra_out_nid[0]; |
10549 | if (!dac) | 10722 | if (!dac) |
10550 | dac = spec->multiout.dac_nids[0]; /* to front */ | 10723 | dac = spec->multiout.dac_nids[0]; /* to front */ |
@@ -10555,13 +10728,12 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec) | |||
10555 | static void alc882_auto_init_analog_input(struct hda_codec *codec) | 10728 | static void alc882_auto_init_analog_input(struct hda_codec *codec) |
10556 | { | 10729 | { |
10557 | struct alc_spec *spec = codec->spec; | 10730 | struct alc_spec *spec = codec->spec; |
10731 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
10558 | int i; | 10732 | int i; |
10559 | 10733 | ||
10560 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 10734 | for (i = 0; i < cfg->num_inputs; i++) { |
10561 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 10735 | hda_nid_t nid = cfg->inputs[i].pin; |
10562 | if (!nid) | 10736 | alc_set_input_pin(codec, nid, cfg->inputs[i].type); |
10563 | continue; | ||
10564 | alc_set_input_pin(codec, nid, i); | ||
10565 | if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) | 10737 | if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) |
10566 | snd_hda_codec_write(codec, nid, 0, | 10738 | snd_hda_codec_write(codec, nid, 0, |
10567 | AC_VERB_SET_AMP_GAIN_MUTE, | 10739 | AC_VERB_SET_AMP_GAIN_MUTE, |
@@ -10623,24 +10795,23 @@ static void alc882_auto_init_input_src(struct hda_codec *codec) | |||
10623 | static int alc_auto_add_mic_boost(struct hda_codec *codec) | 10795 | static int alc_auto_add_mic_boost(struct hda_codec *codec) |
10624 | { | 10796 | { |
10625 | struct alc_spec *spec = codec->spec; | 10797 | struct alc_spec *spec = codec->spec; |
10626 | int err; | 10798 | struct auto_pin_cfg *cfg = &spec->autocfg; |
10799 | int i, err; | ||
10627 | hda_nid_t nid; | 10800 | hda_nid_t nid; |
10628 | 10801 | ||
10629 | nid = spec->autocfg.input_pins[AUTO_PIN_MIC]; | 10802 | for (i = 0; i < cfg->num_inputs; i++) { |
10630 | if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) { | 10803 | if (cfg->inputs[i].type > AUTO_PIN_MIC) |
10631 | err = add_control(spec, ALC_CTL_WIDGET_VOL, | 10804 | break; |
10632 | "Mic Boost", | 10805 | nid = cfg->inputs[i].pin; |
10633 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); | 10806 | if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) { |
10634 | if (err < 0) | 10807 | char label[32]; |
10635 | return err; | 10808 | snprintf(label, sizeof(label), "%s Boost", |
10636 | } | 10809 | hda_get_autocfg_input_label(codec, cfg, i)); |
10637 | nid = spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC]; | 10810 | err = add_control(spec, ALC_CTL_WIDGET_VOL, label, 0, |
10638 | if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) { | ||
10639 | err = add_control(spec, ALC_CTL_WIDGET_VOL, | ||
10640 | "Front Mic Boost", | ||
10641 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); | 10811 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); |
10642 | if (err < 0) | 10812 | if (err < 0) |
10643 | return err; | 10813 | return err; |
10814 | } | ||
10644 | } | 10815 | } |
10645 | return 0; | 10816 | return 0; |
10646 | } | 10817 | } |
@@ -10726,8 +10897,6 @@ static int patch_alc882(struct hda_codec *codec) | |||
10726 | 10897 | ||
10727 | codec->spec = spec; | 10898 | codec->spec = spec; |
10728 | 10899 | ||
10729 | alc_auto_parse_customize_define(codec); | ||
10730 | |||
10731 | switch (codec->vendor_id) { | 10900 | switch (codec->vendor_id) { |
10732 | case 0x10ec0882: | 10901 | case 0x10ec0882: |
10733 | case 0x10ec0885: | 10902 | case 0x10ec0885: |
@@ -10755,6 +10924,8 @@ static int patch_alc882(struct hda_codec *codec) | |||
10755 | if (board_config == ALC882_AUTO) | 10924 | if (board_config == ALC882_AUTO) |
10756 | alc_pick_fixup(codec, alc882_fixup_tbl, alc882_fixups, 1); | 10925 | alc_pick_fixup(codec, alc882_fixup_tbl, alc882_fixups, 1); |
10757 | 10926 | ||
10927 | alc_auto_parse_customize_define(codec); | ||
10928 | |||
10758 | if (board_config == ALC882_AUTO) { | 10929 | if (board_config == ALC882_AUTO) { |
10759 | /* automatic parse from the BIOS config */ | 10930 | /* automatic parse from the BIOS config */ |
10760 | err = alc882_parse_auto_config(codec); | 10931 | err = alc882_parse_auto_config(codec); |
@@ -10835,6 +11006,8 @@ static int patch_alc882(struct hda_codec *codec) | |||
10835 | codec->patch_ops = alc_patch_ops; | 11006 | codec->patch_ops = alc_patch_ops; |
10836 | if (board_config == ALC882_AUTO) | 11007 | if (board_config == ALC882_AUTO) |
10837 | spec->init_hook = alc882_auto_init; | 11008 | spec->init_hook = alc882_auto_init; |
11009 | |||
11010 | alc_init_jacks(codec); | ||
10838 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 11011 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
10839 | if (!spec->loopback.amplist) | 11012 | if (!spec->loopback.amplist) |
10840 | spec->loopback.amplist = alc882_loopbacks; | 11013 | spec->loopback.amplist = alc882_loopbacks; |
@@ -11831,7 +12004,7 @@ static int alc262_check_volbit(hda_nid_t nid) | |||
11831 | } | 12004 | } |
11832 | 12005 | ||
11833 | static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid, | 12006 | static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid, |
11834 | const char *pfx, int *vbits) | 12007 | const char *pfx, int *vbits, int idx) |
11835 | { | 12008 | { |
11836 | unsigned long val; | 12009 | unsigned long val; |
11837 | int vbit; | 12010 | int vbit; |
@@ -11846,11 +12019,11 @@ static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid, | |||
11846 | val = HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT); | 12019 | val = HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT); |
11847 | else | 12020 | else |
11848 | val = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT); | 12021 | val = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT); |
11849 | return add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, val); | 12022 | return __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, idx, val); |
11850 | } | 12023 | } |
11851 | 12024 | ||
11852 | static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid, | 12025 | static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid, |
11853 | const char *pfx) | 12026 | const char *pfx, int idx) |
11854 | { | 12027 | { |
11855 | unsigned long val; | 12028 | unsigned long val; |
11856 | 12029 | ||
@@ -11860,7 +12033,7 @@ static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid, | |||
11860 | val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT); | 12033 | val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT); |
11861 | else | 12034 | else |
11862 | val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); | 12035 | val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); |
11863 | return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, val); | 12036 | return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, idx, val); |
11864 | } | 12037 | } |
11865 | 12038 | ||
11866 | /* add playback controls from the parsed DAC table */ | 12039 | /* add playback controls from the parsed DAC table */ |
@@ -11869,7 +12042,7 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
11869 | { | 12042 | { |
11870 | const char *pfx; | 12043 | const char *pfx; |
11871 | int vbits; | 12044 | int vbits; |
11872 | int err; | 12045 | int i, err; |
11873 | 12046 | ||
11874 | spec->multiout.num_dacs = 1; /* only use one dac */ | 12047 | spec->multiout.num_dacs = 1; /* only use one dac */ |
11875 | spec->multiout.dac_nids = spec->private_dac_nids; | 12048 | spec->multiout.dac_nids = spec->private_dac_nids; |
@@ -11879,39 +12052,52 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
11879 | pfx = "Master"; | 12052 | pfx = "Master"; |
11880 | else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) | 12053 | else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) |
11881 | pfx = "Speaker"; | 12054 | pfx = "Speaker"; |
12055 | else if (cfg->line_out_type == AUTO_PIN_HP_OUT) | ||
12056 | pfx = "Headphone"; | ||
11882 | else | 12057 | else |
11883 | pfx = "Front"; | 12058 | pfx = "Front"; |
11884 | err = alc262_add_out_sw_ctl(spec, cfg->line_out_pins[0], pfx); | 12059 | for (i = 0; i < 2; i++) { |
11885 | if (err < 0) | 12060 | err = alc262_add_out_sw_ctl(spec, cfg->line_out_pins[i], pfx, i); |
11886 | return err; | 12061 | if (err < 0) |
11887 | err = alc262_add_out_sw_ctl(spec, cfg->speaker_pins[0], "Speaker"); | 12062 | return err; |
11888 | if (err < 0) | 12063 | if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { |
11889 | return err; | 12064 | err = alc262_add_out_sw_ctl(spec, cfg->speaker_pins[i], |
11890 | err = alc262_add_out_sw_ctl(spec, cfg->hp_pins[0], "Headphone"); | 12065 | "Speaker", i); |
11891 | if (err < 0) | 12066 | if (err < 0) |
11892 | return err; | 12067 | return err; |
12068 | } | ||
12069 | if (cfg->line_out_type != AUTO_PIN_HP_OUT) { | ||
12070 | err = alc262_add_out_sw_ctl(spec, cfg->hp_pins[i], | ||
12071 | "Headphone", i); | ||
12072 | if (err < 0) | ||
12073 | return err; | ||
12074 | } | ||
12075 | } | ||
11893 | 12076 | ||
11894 | vbits = alc262_check_volbit(cfg->line_out_pins[0]) | | 12077 | vbits = alc262_check_volbit(cfg->line_out_pins[0]) | |
11895 | alc262_check_volbit(cfg->speaker_pins[0]) | | 12078 | alc262_check_volbit(cfg->speaker_pins[0]) | |
11896 | alc262_check_volbit(cfg->hp_pins[0]); | 12079 | alc262_check_volbit(cfg->hp_pins[0]); |
11897 | if (vbits == 1 || vbits == 2) | 12080 | if (vbits == 1 || vbits == 2) |
11898 | pfx = "Master"; /* only one mixer is used */ | 12081 | pfx = "Master"; /* only one mixer is used */ |
11899 | else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) | ||
11900 | pfx = "Speaker"; | ||
11901 | else | ||
11902 | pfx = "Front"; | ||
11903 | vbits = 0; | 12082 | vbits = 0; |
11904 | err = alc262_add_out_vol_ctl(spec, cfg->line_out_pins[0], pfx, &vbits); | 12083 | for (i = 0; i < 2; i++) { |
11905 | if (err < 0) | 12084 | err = alc262_add_out_vol_ctl(spec, cfg->line_out_pins[i], pfx, |
11906 | return err; | 12085 | &vbits, i); |
11907 | err = alc262_add_out_vol_ctl(spec, cfg->speaker_pins[0], "Speaker", | 12086 | if (err < 0) |
11908 | &vbits); | 12087 | return err; |
11909 | if (err < 0) | 12088 | if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { |
11910 | return err; | 12089 | err = alc262_add_out_vol_ctl(spec, cfg->speaker_pins[i], |
11911 | err = alc262_add_out_vol_ctl(spec, cfg->hp_pins[0], "Headphone", | 12090 | "Speaker", &vbits, i); |
11912 | &vbits); | 12091 | if (err < 0) |
11913 | if (err < 0) | 12092 | return err; |
11914 | return err; | 12093 | } |
12094 | if (cfg->line_out_type != AUTO_PIN_HP_OUT) { | ||
12095 | err = alc262_add_out_vol_ctl(spec, cfg->hp_pins[i], | ||
12096 | "Headphone", &vbits, i); | ||
12097 | if (err < 0) | ||
12098 | return err; | ||
12099 | } | ||
12100 | } | ||
11915 | return 0; | 12101 | return 0; |
11916 | } | 12102 | } |
11917 | 12103 | ||
@@ -12199,6 +12385,35 @@ static struct hda_verb alc262_toshiba_rx1_unsol_verbs[] = { | |||
12199 | {} | 12385 | {} |
12200 | }; | 12386 | }; |
12201 | 12387 | ||
12388 | /* | ||
12389 | * Pin config fixes | ||
12390 | */ | ||
12391 | enum { | ||
12392 | PINFIX_FSC_H270, | ||
12393 | }; | ||
12394 | |||
12395 | static const struct alc_fixup alc262_fixups[] = { | ||
12396 | [PINFIX_FSC_H270] = { | ||
12397 | .pins = (const struct alc_pincfg[]) { | ||
12398 | { 0x14, 0x99130110 }, /* speaker */ | ||
12399 | { 0x15, 0x0221142f }, /* front HP */ | ||
12400 | { 0x1b, 0x0121141f }, /* rear HP */ | ||
12401 | { } | ||
12402 | } | ||
12403 | }, | ||
12404 | [PINFIX_PB_M5210] = { | ||
12405 | .verbs = (const struct hda_verb[]) { | ||
12406 | { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 }, | ||
12407 | {} | ||
12408 | } | ||
12409 | }, | ||
12410 | }; | ||
12411 | |||
12412 | static struct snd_pci_quirk alc262_fixup_tbl[] = { | ||
12413 | SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", PINFIX_FSC_H270), | ||
12414 | {} | ||
12415 | }; | ||
12416 | |||
12202 | 12417 | ||
12203 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 12418 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
12204 | #define alc262_loopbacks alc880_loopbacks | 12419 | #define alc262_loopbacks alc880_loopbacks |
@@ -12622,6 +12837,9 @@ static int patch_alc262(struct hda_codec *codec) | |||
12622 | board_config = ALC262_AUTO; | 12837 | board_config = ALC262_AUTO; |
12623 | } | 12838 | } |
12624 | 12839 | ||
12840 | if (board_config == ALC262_AUTO) | ||
12841 | alc_pick_fixup(codec, alc262_fixup_tbl, alc262_fixups, 1); | ||
12842 | |||
12625 | if (board_config == ALC262_AUTO) { | 12843 | if (board_config == ALC262_AUTO) { |
12626 | /* automatic parse from the BIOS config */ | 12844 | /* automatic parse from the BIOS config */ |
12627 | err = alc262_parse_auto_config(codec); | 12845 | err = alc262_parse_auto_config(codec); |
@@ -12690,11 +12908,16 @@ static int patch_alc262(struct hda_codec *codec) | |||
12690 | if (!spec->no_analog && has_cdefine_beep(codec)) | 12908 | if (!spec->no_analog && has_cdefine_beep(codec)) |
12691 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 12909 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
12692 | 12910 | ||
12911 | if (board_config == ALC262_AUTO) | ||
12912 | alc_pick_fixup(codec, alc262_fixup_tbl, alc262_fixups, 0); | ||
12913 | |||
12693 | spec->vmaster_nid = 0x0c; | 12914 | spec->vmaster_nid = 0x0c; |
12694 | 12915 | ||
12695 | codec->patch_ops = alc_patch_ops; | 12916 | codec->patch_ops = alc_patch_ops; |
12696 | if (board_config == ALC262_AUTO) | 12917 | if (board_config == ALC262_AUTO) |
12697 | spec->init_hook = alc262_auto_init; | 12918 | spec->init_hook = alc262_auto_init; |
12919 | |||
12920 | alc_init_jacks(codec); | ||
12698 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 12921 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
12699 | if (!spec->loopback.amplist) | 12922 | if (!spec->loopback.amplist) |
12700 | spec->loopback.amplist = alc262_loopbacks; | 12923 | spec->loopback.amplist = alc262_loopbacks; |
@@ -13310,8 +13533,10 @@ static void alc268_auto_set_output_and_unmute(struct hda_codec *codec, | |||
13310 | static void alc268_auto_init_multi_out(struct hda_codec *codec) | 13533 | static void alc268_auto_init_multi_out(struct hda_codec *codec) |
13311 | { | 13534 | { |
13312 | struct alc_spec *spec = codec->spec; | 13535 | struct alc_spec *spec = codec->spec; |
13313 | hda_nid_t nid = spec->autocfg.line_out_pins[0]; | 13536 | int i; |
13314 | if (nid) { | 13537 | |
13538 | for (i = 0; i < spec->autocfg.line_outs; i++) { | ||
13539 | hda_nid_t nid = spec->autocfg.line_out_pins[i]; | ||
13315 | int pin_type = get_pin_type(spec->autocfg.line_out_type); | 13540 | int pin_type = get_pin_type(spec->autocfg.line_out_type); |
13316 | alc268_auto_set_output_and_unmute(codec, nid, pin_type); | 13541 | alc268_auto_set_output_and_unmute(codec, nid, pin_type); |
13317 | } | 13542 | } |
@@ -13321,13 +13546,19 @@ static void alc268_auto_init_hp_out(struct hda_codec *codec) | |||
13321 | { | 13546 | { |
13322 | struct alc_spec *spec = codec->spec; | 13547 | struct alc_spec *spec = codec->spec; |
13323 | hda_nid_t pin; | 13548 | hda_nid_t pin; |
13549 | int i; | ||
13324 | 13550 | ||
13325 | pin = spec->autocfg.hp_pins[0]; | 13551 | for (i = 0; i < spec->autocfg.hp_outs; i++) { |
13326 | if (pin) | 13552 | pin = spec->autocfg.hp_pins[i]; |
13327 | alc268_auto_set_output_and_unmute(codec, pin, PIN_HP); | 13553 | alc268_auto_set_output_and_unmute(codec, pin, PIN_HP); |
13328 | pin = spec->autocfg.speaker_pins[0]; | 13554 | } |
13329 | if (pin) | 13555 | for (i = 0; i < spec->autocfg.speaker_outs; i++) { |
13556 | pin = spec->autocfg.speaker_pins[i]; | ||
13330 | alc268_auto_set_output_and_unmute(codec, pin, PIN_OUT); | 13557 | alc268_auto_set_output_and_unmute(codec, pin, PIN_OUT); |
13558 | } | ||
13559 | if (spec->autocfg.mono_out_pin) | ||
13560 | snd_hda_codec_write(codec, spec->autocfg.mono_out_pin, 0, | ||
13561 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | ||
13331 | } | 13562 | } |
13332 | 13563 | ||
13333 | static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec) | 13564 | static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec) |
@@ -13766,6 +13997,8 @@ static int patch_alc268(struct hda_codec *codec) | |||
13766 | if (board_config == ALC268_AUTO) | 13997 | if (board_config == ALC268_AUTO) |
13767 | spec->init_hook = alc268_auto_init; | 13998 | spec->init_hook = alc268_auto_init; |
13768 | 13999 | ||
14000 | alc_init_jacks(codec); | ||
14001 | |||
13769 | return 0; | 14002 | return 0; |
13770 | } | 14003 | } |
13771 | 14004 | ||
@@ -14132,6 +14365,7 @@ static void alc269_speaker_automute(struct hda_codec *codec) | |||
14132 | HDA_AMP_MUTE, bits); | 14365 | HDA_AMP_MUTE, bits); |
14133 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, | 14366 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, |
14134 | HDA_AMP_MUTE, bits); | 14367 | HDA_AMP_MUTE, bits); |
14368 | alc_report_jack(codec, nid); | ||
14135 | } | 14369 | } |
14136 | 14370 | ||
14137 | /* unsolicited event for HP jack sensing */ | 14371 | /* unsolicited event for HP jack sensing */ |
@@ -14386,6 +14620,13 @@ static int alc275_setup_dual_adc(struct hda_codec *codec) | |||
14386 | return 0; | 14620 | return 0; |
14387 | } | 14621 | } |
14388 | 14622 | ||
14623 | /* different alc269-variants */ | ||
14624 | enum { | ||
14625 | ALC269_TYPE_NORMAL, | ||
14626 | ALC269_TYPE_ALC259, | ||
14627 | ALC269_TYPE_ALC271X, | ||
14628 | }; | ||
14629 | |||
14389 | /* | 14630 | /* |
14390 | * BIOS auto configuration | 14631 | * BIOS auto configuration |
14391 | */ | 14632 | */ |
@@ -14403,7 +14644,11 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
14403 | err = alc269_auto_create_multi_out_ctls(spec, &spec->autocfg); | 14644 | err = alc269_auto_create_multi_out_ctls(spec, &spec->autocfg); |
14404 | if (err < 0) | 14645 | if (err < 0) |
14405 | return err; | 14646 | return err; |
14406 | err = alc269_auto_create_input_ctls(codec, &spec->autocfg); | 14647 | if (spec->codec_variant == ALC269_TYPE_NORMAL) |
14648 | err = alc269_auto_create_input_ctls(codec, &spec->autocfg); | ||
14649 | else | ||
14650 | err = alc_auto_create_input_ctls(codec, &spec->autocfg, 0, | ||
14651 | 0x22, 0); | ||
14407 | if (err < 0) | 14652 | if (err < 0) |
14408 | return err; | 14653 | return err; |
14409 | 14654 | ||
@@ -14414,7 +14659,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
14414 | if (spec->kctls.list) | 14659 | if (spec->kctls.list) |
14415 | add_mixer(spec, spec->kctls.list); | 14660 | add_mixer(spec, spec->kctls.list); |
14416 | 14661 | ||
14417 | if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010) { | 14662 | if (spec->codec_variant != ALC269_TYPE_NORMAL) { |
14418 | add_verb(spec, alc269vb_init_verbs); | 14663 | add_verb(spec, alc269vb_init_verbs); |
14419 | alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21); | 14664 | alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21); |
14420 | } else { | 14665 | } else { |
@@ -14461,19 +14706,71 @@ static void alc269_auto_init(struct hda_codec *codec) | |||
14461 | alc_inithook(codec); | 14706 | alc_inithook(codec); |
14462 | } | 14707 | } |
14463 | 14708 | ||
14709 | #ifdef SND_HDA_NEEDS_RESUME | ||
14710 | static void alc269_toggle_power_output(struct hda_codec *codec, int power_up) | ||
14711 | { | ||
14712 | int val = alc_read_coef_idx(codec, 0x04); | ||
14713 | if (power_up) | ||
14714 | val |= 1 << 11; | ||
14715 | else | ||
14716 | val &= ~(1 << 11); | ||
14717 | alc_write_coef_idx(codec, 0x04, val); | ||
14718 | } | ||
14719 | |||
14720 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
14721 | static int alc269_suspend(struct hda_codec *codec, pm_message_t state) | ||
14722 | { | ||
14723 | struct alc_spec *spec = codec->spec; | ||
14724 | |||
14725 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) | ||
14726 | alc269_toggle_power_output(codec, 0); | ||
14727 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) { | ||
14728 | alc269_toggle_power_output(codec, 0); | ||
14729 | msleep(150); | ||
14730 | } | ||
14731 | |||
14732 | alc_shutup(codec); | ||
14733 | if (spec && spec->power_hook) | ||
14734 | spec->power_hook(codec); | ||
14735 | return 0; | ||
14736 | } | ||
14737 | #endif /* CONFIG_SND_HDA_POWER_SAVE */ | ||
14738 | |||
14739 | static int alc269_resume(struct hda_codec *codec) | ||
14740 | { | ||
14741 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) { | ||
14742 | alc269_toggle_power_output(codec, 0); | ||
14743 | msleep(150); | ||
14744 | } | ||
14745 | |||
14746 | codec->patch_ops.init(codec); | ||
14747 | |||
14748 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) { | ||
14749 | alc269_toggle_power_output(codec, 1); | ||
14750 | msleep(200); | ||
14751 | } | ||
14752 | |||
14753 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) | ||
14754 | alc269_toggle_power_output(codec, 1); | ||
14755 | |||
14756 | snd_hda_codec_resume_amp(codec); | ||
14757 | snd_hda_codec_resume_cache(codec); | ||
14758 | hda_call_check_power_status(codec, 0x01); | ||
14759 | return 0; | ||
14760 | } | ||
14761 | #endif /* SND_HDA_NEEDS_RESUME */ | ||
14762 | |||
14464 | enum { | 14763 | enum { |
14465 | ALC269_FIXUP_SONY_VAIO, | 14764 | ALC269_FIXUP_SONY_VAIO, |
14466 | ALC269_FIXUP_DELL_M101Z, | 14765 | ALC269_FIXUP_DELL_M101Z, |
14467 | }; | 14766 | }; |
14468 | 14767 | ||
14469 | static const struct hda_verb alc269_sony_vaio_fixup_verbs[] = { | ||
14470 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD}, | ||
14471 | {} | ||
14472 | }; | ||
14473 | |||
14474 | static const struct alc_fixup alc269_fixups[] = { | 14768 | static const struct alc_fixup alc269_fixups[] = { |
14475 | [ALC269_FIXUP_SONY_VAIO] = { | 14769 | [ALC269_FIXUP_SONY_VAIO] = { |
14476 | .verbs = alc269_sony_vaio_fixup_verbs | 14770 | .verbs = (const struct hda_verb[]) { |
14771 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD}, | ||
14772 | {} | ||
14773 | } | ||
14477 | }, | 14774 | }, |
14478 | [ALC269_FIXUP_DELL_M101Z] = { | 14775 | [ALC269_FIXUP_DELL_M101Z] = { |
14479 | .verbs = (const struct hda_verb[]) { | 14776 | .verbs = (const struct hda_verb[]) { |
@@ -14486,8 +14783,7 @@ static const struct alc_fixup alc269_fixups[] = { | |||
14486 | }; | 14783 | }; |
14487 | 14784 | ||
14488 | static struct snd_pci_quirk alc269_fixup_tbl[] = { | 14785 | static struct snd_pci_quirk alc269_fixup_tbl[] = { |
14489 | SND_PCI_QUIRK(0x104d, 0x9071, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), | 14786 | SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), |
14490 | SND_PCI_QUIRK(0x104d, 0x9077, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), | ||
14491 | SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), | 14787 | SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), |
14492 | {} | 14788 | {} |
14493 | }; | 14789 | }; |
@@ -14689,12 +14985,46 @@ static struct alc_config_preset alc269_presets[] = { | |||
14689 | }, | 14985 | }, |
14690 | }; | 14986 | }; |
14691 | 14987 | ||
14988 | static int alc269_fill_coef(struct hda_codec *codec) | ||
14989 | { | ||
14990 | int val; | ||
14991 | |||
14992 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) < 0x015) { | ||
14993 | alc_write_coef_idx(codec, 0xf, 0x960b); | ||
14994 | alc_write_coef_idx(codec, 0xe, 0x8817); | ||
14995 | } | ||
14996 | |||
14997 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x016) { | ||
14998 | alc_write_coef_idx(codec, 0xf, 0x960b); | ||
14999 | alc_write_coef_idx(codec, 0xe, 0x8814); | ||
15000 | } | ||
15001 | |||
15002 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) { | ||
15003 | val = alc_read_coef_idx(codec, 0x04); | ||
15004 | /* Power up output pin */ | ||
15005 | alc_write_coef_idx(codec, 0x04, val | (1<<11)); | ||
15006 | } | ||
15007 | |||
15008 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) { | ||
15009 | val = alc_read_coef_idx(codec, 0xd); | ||
15010 | if ((val & 0x0c00) >> 10 != 0x1) { | ||
15011 | /* Capless ramp up clock control */ | ||
15012 | alc_write_coef_idx(codec, 0xd, val | 1<<10); | ||
15013 | } | ||
15014 | val = alc_read_coef_idx(codec, 0x17); | ||
15015 | if ((val & 0x01c0) >> 6 != 0x4) { | ||
15016 | /* Class D power on reset */ | ||
15017 | alc_write_coef_idx(codec, 0x17, val | 1<<7); | ||
15018 | } | ||
15019 | } | ||
15020 | return 0; | ||
15021 | } | ||
15022 | |||
14692 | static int patch_alc269(struct hda_codec *codec) | 15023 | static int patch_alc269(struct hda_codec *codec) |
14693 | { | 15024 | { |
14694 | struct alc_spec *spec; | 15025 | struct alc_spec *spec; |
14695 | int board_config; | 15026 | int board_config; |
14696 | int err; | 15027 | int err; |
14697 | int is_alc269vb = 0; | ||
14698 | 15028 | ||
14699 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 15029 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
14700 | if (spec == NULL) | 15030 | if (spec == NULL) |
@@ -14706,14 +15036,18 @@ static int patch_alc269(struct hda_codec *codec) | |||
14706 | 15036 | ||
14707 | if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010){ | 15037 | if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010){ |
14708 | if (codec->bus->pci->subsystem_vendor == 0x1025 && | 15038 | if (codec->bus->pci->subsystem_vendor == 0x1025 && |
14709 | spec->cdefine.platform_type == 1) | 15039 | spec->cdefine.platform_type == 1) { |
14710 | alc_codec_rename(codec, "ALC271X"); | 15040 | alc_codec_rename(codec, "ALC271X"); |
14711 | else | 15041 | spec->codec_variant = ALC269_TYPE_ALC271X; |
15042 | } else { | ||
14712 | alc_codec_rename(codec, "ALC259"); | 15043 | alc_codec_rename(codec, "ALC259"); |
14713 | is_alc269vb = 1; | 15044 | spec->codec_variant = ALC269_TYPE_ALC259; |
15045 | } | ||
14714 | } else | 15046 | } else |
14715 | alc_fix_pll_init(codec, 0x20, 0x04, 15); | 15047 | alc_fix_pll_init(codec, 0x20, 0x04, 15); |
14716 | 15048 | ||
15049 | alc269_fill_coef(codec); | ||
15050 | |||
14717 | board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST, | 15051 | board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST, |
14718 | alc269_models, | 15052 | alc269_models, |
14719 | alc269_cfg_tbl); | 15053 | alc269_cfg_tbl); |
@@ -14770,7 +15104,7 @@ static int patch_alc269(struct hda_codec *codec) | |||
14770 | spec->stream_digital_capture = &alc269_pcm_digital_capture; | 15104 | spec->stream_digital_capture = &alc269_pcm_digital_capture; |
14771 | 15105 | ||
14772 | if (!spec->adc_nids) { /* wasn't filled automatically? use default */ | 15106 | if (!spec->adc_nids) { /* wasn't filled automatically? use default */ |
14773 | if (!is_alc269vb) { | 15107 | if (spec->codec_variant != ALC269_TYPE_NORMAL) { |
14774 | spec->adc_nids = alc269_adc_nids; | 15108 | spec->adc_nids = alc269_adc_nids; |
14775 | spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids); | 15109 | spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids); |
14776 | spec->capsrc_nids = alc269_capsrc_nids; | 15110 | spec->capsrc_nids = alc269_capsrc_nids; |
@@ -14792,8 +15126,16 @@ static int patch_alc269(struct hda_codec *codec) | |||
14792 | spec->vmaster_nid = 0x02; | 15126 | spec->vmaster_nid = 0x02; |
14793 | 15127 | ||
14794 | codec->patch_ops = alc_patch_ops; | 15128 | codec->patch_ops = alc_patch_ops; |
15129 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
15130 | codec->patch_ops.suspend = alc269_suspend; | ||
15131 | #endif | ||
15132 | #ifdef SND_HDA_NEEDS_RESUME | ||
15133 | codec->patch_ops.resume = alc269_resume; | ||
15134 | #endif | ||
14795 | if (board_config == ALC269_AUTO) | 15135 | if (board_config == ALC269_AUTO) |
14796 | spec->init_hook = alc269_auto_init; | 15136 | spec->init_hook = alc269_auto_init; |
15137 | |||
15138 | alc_init_jacks(codec); | ||
14797 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 15139 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
14798 | if (!spec->loopback.amplist) | 15140 | if (!spec->loopback.amplist) |
14799 | spec->loopback.amplist = alc269_loopbacks; | 15141 | spec->loopback.amplist = alc269_loopbacks; |
@@ -15606,12 +15948,13 @@ static void alc861_auto_init_hp_out(struct hda_codec *codec) | |||
15606 | static void alc861_auto_init_analog_input(struct hda_codec *codec) | 15948 | static void alc861_auto_init_analog_input(struct hda_codec *codec) |
15607 | { | 15949 | { |
15608 | struct alc_spec *spec = codec->spec; | 15950 | struct alc_spec *spec = codec->spec; |
15951 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
15609 | int i; | 15952 | int i; |
15610 | 15953 | ||
15611 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 15954 | for (i = 0; i < cfg->num_inputs; i++) { |
15612 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 15955 | hda_nid_t nid = cfg->inputs[i].pin; |
15613 | if (nid >= 0x0c && nid <= 0x11) | 15956 | if (nid >= 0x0c && nid <= 0x11) |
15614 | alc_set_input_pin(codec, nid, i); | 15957 | alc_set_input_pin(codec, nid, cfg->inputs[i].type); |
15615 | } | 15958 | } |
15616 | } | 15959 | } |
15617 | 15960 | ||
@@ -15840,15 +16183,13 @@ enum { | |||
15840 | PINFIX_FSC_AMILO_PI1505, | 16183 | PINFIX_FSC_AMILO_PI1505, |
15841 | }; | 16184 | }; |
15842 | 16185 | ||
15843 | static struct alc_pincfg alc861_fsc_amilo_pi1505_pinfix[] = { | ||
15844 | { 0x0b, 0x0221101f }, /* HP */ | ||
15845 | { 0x0f, 0x90170310 }, /* speaker */ | ||
15846 | { } | ||
15847 | }; | ||
15848 | |||
15849 | static const struct alc_fixup alc861_fixups[] = { | 16186 | static const struct alc_fixup alc861_fixups[] = { |
15850 | [PINFIX_FSC_AMILO_PI1505] = { | 16187 | [PINFIX_FSC_AMILO_PI1505] = { |
15851 | .pins = alc861_fsc_amilo_pi1505_pinfix | 16188 | .pins = (const struct alc_pincfg[]) { |
16189 | { 0x0b, 0x0221101f }, /* HP */ | ||
16190 | { 0x0f, 0x90170310 }, /* speaker */ | ||
16191 | { } | ||
16192 | } | ||
15852 | }, | 16193 | }, |
15853 | }; | 16194 | }; |
15854 | 16195 | ||
@@ -16600,12 +16941,13 @@ static void alc861vd_auto_init_hp_out(struct hda_codec *codec) | |||
16600 | static void alc861vd_auto_init_analog_input(struct hda_codec *codec) | 16941 | static void alc861vd_auto_init_analog_input(struct hda_codec *codec) |
16601 | { | 16942 | { |
16602 | struct alc_spec *spec = codec->spec; | 16943 | struct alc_spec *spec = codec->spec; |
16944 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
16603 | int i; | 16945 | int i; |
16604 | 16946 | ||
16605 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 16947 | for (i = 0; i < cfg->num_inputs; i++) { |
16606 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 16948 | hda_nid_t nid = cfg->inputs[i].pin; |
16607 | if (alc_is_input_pin(codec, nid)) { | 16949 | if (alc_is_input_pin(codec, nid)) { |
16608 | alc_set_input_pin(codec, nid, i); | 16950 | alc_set_input_pin(codec, nid, cfg->inputs[i].type); |
16609 | if (nid != ALC861VD_PIN_CD_NID && | 16951 | if (nid != ALC861VD_PIN_CD_NID && |
16610 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) | 16952 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) |
16611 | snd_hda_codec_write(codec, nid, 0, | 16953 | snd_hda_codec_write(codec, nid, 0, |
@@ -16815,16 +17157,14 @@ enum { | |||
16815 | }; | 17157 | }; |
16816 | 17158 | ||
16817 | /* reset GPIO1 */ | 17159 | /* reset GPIO1 */ |
16818 | static const struct hda_verb alc660vd_fix_asus_gpio1_verbs[] = { | ||
16819 | {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, | ||
16820 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, | ||
16821 | {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, | ||
16822 | { } | ||
16823 | }; | ||
16824 | |||
16825 | static const struct alc_fixup alc861vd_fixups[] = { | 17160 | static const struct alc_fixup alc861vd_fixups[] = { |
16826 | [ALC660VD_FIX_ASUS_GPIO1] = { | 17161 | [ALC660VD_FIX_ASUS_GPIO1] = { |
16827 | .verbs = alc660vd_fix_asus_gpio1_verbs, | 17162 | .verbs = (const struct hda_verb[]) { |
17163 | {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, | ||
17164 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, | ||
17165 | {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, | ||
17166 | { } | ||
17167 | } | ||
16828 | }, | 17168 | }, |
16829 | }; | 17169 | }; |
16830 | 17170 | ||
@@ -18838,12 +19178,13 @@ static void alc662_auto_init_hp_out(struct hda_codec *codec) | |||
18838 | static void alc662_auto_init_analog_input(struct hda_codec *codec) | 19178 | static void alc662_auto_init_analog_input(struct hda_codec *codec) |
18839 | { | 19179 | { |
18840 | struct alc_spec *spec = codec->spec; | 19180 | struct alc_spec *spec = codec->spec; |
19181 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
18841 | int i; | 19182 | int i; |
18842 | 19183 | ||
18843 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 19184 | for (i = 0; i < cfg->num_inputs; i++) { |
18844 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 19185 | hda_nid_t nid = cfg->inputs[i].pin; |
18845 | if (alc_is_input_pin(codec, nid)) { | 19186 | if (alc_is_input_pin(codec, nid)) { |
18846 | alc_set_input_pin(codec, nid, i); | 19187 | alc_set_input_pin(codec, nid, cfg->inputs[i].type); |
18847 | if (nid != ALC662_PIN_CD_NID && | 19188 | if (nid != ALC662_PIN_CD_NID && |
18848 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) | 19189 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) |
18849 | snd_hda_codec_write(codec, nid, 0, | 19190 | snd_hda_codec_write(codec, nid, 0, |
@@ -18935,10 +19276,40 @@ static void alc662_auto_init(struct hda_codec *codec) | |||
18935 | alc_inithook(codec); | 19276 | alc_inithook(codec); |
18936 | } | 19277 | } |
18937 | 19278 | ||
19279 | enum { | ||
19280 | ALC662_FIXUP_ASPIRE, | ||
19281 | ALC662_FIXUP_IDEAPAD, | ||
19282 | }; | ||
19283 | |||
19284 | static const struct alc_fixup alc662_fixups[] = { | ||
19285 | [ALC662_FIXUP_ASPIRE] = { | ||
19286 | .pins = (const struct alc_pincfg[]) { | ||
19287 | { 0x15, 0x99130112 }, /* subwoofer */ | ||
19288 | { } | ||
19289 | } | ||
19290 | }, | ||
19291 | [ALC662_FIXUP_IDEAPAD] = { | ||
19292 | .pins = (const struct alc_pincfg[]) { | ||
19293 | { 0x17, 0x99130112 }, /* subwoofer */ | ||
19294 | { } | ||
19295 | } | ||
19296 | }, | ||
19297 | }; | ||
19298 | |||
19299 | static struct snd_pci_quirk alc662_fixup_tbl[] = { | ||
19300 | SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), | ||
19301 | SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD), | ||
19302 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD), | ||
19303 | {} | ||
19304 | }; | ||
19305 | |||
19306 | |||
19307 | |||
18938 | static int patch_alc662(struct hda_codec *codec) | 19308 | static int patch_alc662(struct hda_codec *codec) |
18939 | { | 19309 | { |
18940 | struct alc_spec *spec; | 19310 | struct alc_spec *spec; |
18941 | int err, board_config; | 19311 | int err, board_config; |
19312 | int coef; | ||
18942 | 19313 | ||
18943 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 19314 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
18944 | if (!spec) | 19315 | if (!spec) |
@@ -18950,12 +19321,15 @@ static int patch_alc662(struct hda_codec *codec) | |||
18950 | 19321 | ||
18951 | alc_fix_pll_init(codec, 0x20, 0x04, 15); | 19322 | alc_fix_pll_init(codec, 0x20, 0x04, 15); |
18952 | 19323 | ||
18953 | if (alc_read_coef_idx(codec, 0) == 0x8020) | 19324 | coef = alc_read_coef_idx(codec, 0); |
19325 | if (coef == 0x8020 || coef == 0x8011) | ||
18954 | alc_codec_rename(codec, "ALC661"); | 19326 | alc_codec_rename(codec, "ALC661"); |
18955 | else if ((alc_read_coef_idx(codec, 0) & (1 << 14)) && | 19327 | else if (coef & (1 << 14) && |
18956 | codec->bus->pci->subsystem_vendor == 0x1025 && | 19328 | codec->bus->pci->subsystem_vendor == 0x1025 && |
18957 | spec->cdefine.platform_type == 1) | 19329 | spec->cdefine.platform_type == 1) |
18958 | alc_codec_rename(codec, "ALC272X"); | 19330 | alc_codec_rename(codec, "ALC272X"); |
19331 | else if (coef == 0x4011) | ||
19332 | alc_codec_rename(codec, "ALC656"); | ||
18959 | 19333 | ||
18960 | board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST, | 19334 | board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST, |
18961 | alc662_models, | 19335 | alc662_models, |
@@ -18967,6 +19341,7 @@ static int patch_alc662(struct hda_codec *codec) | |||
18967 | } | 19341 | } |
18968 | 19342 | ||
18969 | if (board_config == ALC662_AUTO) { | 19343 | if (board_config == ALC662_AUTO) { |
19344 | alc_pick_fixup(codec, alc662_fixup_tbl, alc662_fixups, 1); | ||
18970 | /* automatic parse from the BIOS config */ | 19345 | /* automatic parse from the BIOS config */ |
18971 | err = alc662_parse_auto_config(codec); | 19346 | err = alc662_parse_auto_config(codec); |
18972 | if (err < 0) { | 19347 | if (err < 0) { |
@@ -19025,8 +19400,13 @@ static int patch_alc662(struct hda_codec *codec) | |||
19025 | spec->vmaster_nid = 0x02; | 19400 | spec->vmaster_nid = 0x02; |
19026 | 19401 | ||
19027 | codec->patch_ops = alc_patch_ops; | 19402 | codec->patch_ops = alc_patch_ops; |
19028 | if (board_config == ALC662_AUTO) | 19403 | if (board_config == ALC662_AUTO) { |
19029 | spec->init_hook = alc662_auto_init; | 19404 | spec->init_hook = alc662_auto_init; |
19405 | alc_pick_fixup(codec, alc662_fixup_tbl, alc662_fixups, 0); | ||
19406 | } | ||
19407 | |||
19408 | alc_init_jacks(codec); | ||
19409 | |||
19030 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 19410 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
19031 | if (!spec->loopback.amplist) | 19411 | if (!spec->loopback.amplist) |
19032 | spec->loopback.amplist = alc662_loopbacks; | 19412 | spec->loopback.amplist = alc662_loopbacks; |
@@ -19070,6 +19450,39 @@ static hda_nid_t alc680_adc_nids[3] = { | |||
19070 | /* | 19450 | /* |
19071 | * Analog capture ADC cgange | 19451 | * Analog capture ADC cgange |
19072 | */ | 19452 | */ |
19453 | static void alc680_rec_autoswitch(struct hda_codec *codec) | ||
19454 | { | ||
19455 | struct alc_spec *spec = codec->spec; | ||
19456 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
19457 | int pin_found = 0; | ||
19458 | int type_found = AUTO_PIN_LAST; | ||
19459 | hda_nid_t nid; | ||
19460 | int i; | ||
19461 | |||
19462 | for (i = 0; i < cfg->num_inputs; i++) { | ||
19463 | nid = cfg->inputs[i].pin; | ||
19464 | if (!(snd_hda_query_pin_caps(codec, nid) & | ||
19465 | AC_PINCAP_PRES_DETECT)) | ||
19466 | continue; | ||
19467 | if (snd_hda_jack_detect(codec, nid)) { | ||
19468 | if (cfg->inputs[i].type < type_found) { | ||
19469 | type_found = cfg->inputs[i].type; | ||
19470 | pin_found = nid; | ||
19471 | } | ||
19472 | } | ||
19473 | } | ||
19474 | |||
19475 | nid = 0x07; | ||
19476 | if (pin_found) | ||
19477 | snd_hda_get_connections(codec, pin_found, &nid, 1); | ||
19478 | |||
19479 | if (nid != spec->cur_adc) | ||
19480 | __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1); | ||
19481 | spec->cur_adc = nid; | ||
19482 | snd_hda_codec_setup_stream(codec, nid, spec->cur_adc_stream_tag, 0, | ||
19483 | spec->cur_adc_format); | ||
19484 | } | ||
19485 | |||
19073 | static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | 19486 | static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo, |
19074 | struct hda_codec *codec, | 19487 | struct hda_codec *codec, |
19075 | unsigned int stream_tag, | 19488 | unsigned int stream_tag, |
@@ -19077,24 +19490,12 @@ static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
19077 | struct snd_pcm_substream *substream) | 19490 | struct snd_pcm_substream *substream) |
19078 | { | 19491 | { |
19079 | struct alc_spec *spec = codec->spec; | 19492 | struct alc_spec *spec = codec->spec; |
19080 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
19081 | unsigned int pre_mic, pre_line; | ||
19082 | |||
19083 | pre_mic = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_MIC]); | ||
19084 | pre_line = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_LINE]); | ||
19085 | 19493 | ||
19494 | spec->cur_adc = 0x07; | ||
19086 | spec->cur_adc_stream_tag = stream_tag; | 19495 | spec->cur_adc_stream_tag = stream_tag; |
19087 | spec->cur_adc_format = format; | 19496 | spec->cur_adc_format = format; |
19088 | 19497 | ||
19089 | if (pre_mic || pre_line) { | 19498 | alc680_rec_autoswitch(codec); |
19090 | if (pre_mic) | ||
19091 | snd_hda_codec_setup_stream(codec, 0x08, stream_tag, 0, | ||
19092 | format); | ||
19093 | else | ||
19094 | snd_hda_codec_setup_stream(codec, 0x09, stream_tag, 0, | ||
19095 | format); | ||
19096 | } else | ||
19097 | snd_hda_codec_setup_stream(codec, 0x07, stream_tag, 0, format); | ||
19098 | return 0; | 19499 | return 0; |
19099 | } | 19500 | } |
19100 | 19501 | ||
@@ -19180,6 +19581,7 @@ static struct hda_verb alc680_init_verbs[] = { | |||
19180 | 19581 | ||
19181 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | 19582 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, |
19182 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN}, | 19583 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN}, |
19584 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN}, | ||
19183 | 19585 | ||
19184 | { } | 19586 | { } |
19185 | }; | 19587 | }; |
@@ -19192,25 +19594,11 @@ static void alc680_base_setup(struct hda_codec *codec) | |||
19192 | spec->autocfg.hp_pins[0] = 0x16; | 19594 | spec->autocfg.hp_pins[0] = 0x16; |
19193 | spec->autocfg.speaker_pins[0] = 0x14; | 19595 | spec->autocfg.speaker_pins[0] = 0x14; |
19194 | spec->autocfg.speaker_pins[1] = 0x15; | 19596 | spec->autocfg.speaker_pins[1] = 0x15; |
19195 | spec->autocfg.input_pins[AUTO_PIN_MIC] = 0x18; | 19597 | spec->autocfg.num_inputs = 2; |
19196 | spec->autocfg.input_pins[AUTO_PIN_LINE] = 0x19; | 19598 | spec->autocfg.inputs[0].pin = 0x18; |
19197 | } | 19599 | spec->autocfg.inputs[0].type = AUTO_PIN_MIC; |
19198 | 19600 | spec->autocfg.inputs[1].pin = 0x19; | |
19199 | static void alc680_rec_autoswitch(struct hda_codec *codec) | 19601 | spec->autocfg.inputs[1].type = AUTO_PIN_LINE_IN; |
19200 | { | ||
19201 | struct alc_spec *spec = codec->spec; | ||
19202 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
19203 | unsigned int present; | ||
19204 | hda_nid_t new_adc; | ||
19205 | |||
19206 | present = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_MIC]); | ||
19207 | |||
19208 | new_adc = present ? 0x8 : 0x7; | ||
19209 | __snd_hda_codec_cleanup_stream(codec, !present ? 0x8 : 0x7, 1); | ||
19210 | snd_hda_codec_setup_stream(codec, new_adc, | ||
19211 | spec->cur_adc_stream_tag, 0, | ||
19212 | spec->cur_adc_format); | ||
19213 | |||
19214 | } | 19602 | } |
19215 | 19603 | ||
19216 | static void alc680_unsol_event(struct hda_codec *codec, | 19604 | static void alc680_unsol_event(struct hda_codec *codec, |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index c16c5ba0fda0..82ebeb9544fe 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <sound/core.h> | 32 | #include <sound/core.h> |
33 | #include <sound/asoundef.h> | 33 | #include <sound/asoundef.h> |
34 | #include <sound/jack.h> | 34 | #include <sound/jack.h> |
35 | #include <sound/tlv.h> | ||
35 | #include "hda_codec.h" | 36 | #include "hda_codec.h" |
36 | #include "hda_local.h" | 37 | #include "hda_local.h" |
37 | #include "hda_beep.h" | 38 | #include "hda_beep.h" |
@@ -263,6 +264,7 @@ struct sigmatel_spec { | |||
263 | 264 | ||
264 | struct sigmatel_mic_route ext_mic; | 265 | struct sigmatel_mic_route ext_mic; |
265 | struct sigmatel_mic_route int_mic; | 266 | struct sigmatel_mic_route int_mic; |
267 | struct sigmatel_mic_route dock_mic; | ||
266 | 268 | ||
267 | const char **spdif_labels; | 269 | const char **spdif_labels; |
268 | 270 | ||
@@ -382,6 +384,11 @@ static unsigned int stac92hd83xxx_pwr_mapping[4] = { | |||
382 | 0x03, 0x0c, 0x20, 0x40, | 384 | 0x03, 0x0c, 0x20, 0x40, |
383 | }; | 385 | }; |
384 | 386 | ||
387 | #define STAC92HD83XXX_NUM_DMICS 2 | ||
388 | static hda_nid_t stac92hd83xxx_dmic_nids[STAC92HD83XXX_NUM_DMICS + 1] = { | ||
389 | 0x11, 0x20, 0 | ||
390 | }; | ||
391 | |||
385 | #define STAC92HD83XXX_NUM_CAPS 2 | 392 | #define STAC92HD83XXX_NUM_CAPS 2 |
386 | static unsigned long stac92hd83xxx_capvols[] = { | 393 | static unsigned long stac92hd83xxx_capvols[] = { |
387 | HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT), | 394 | HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT), |
@@ -986,7 +993,7 @@ static struct hda_verb stac9205_core_init[] = { | |||
986 | } | 993 | } |
987 | 994 | ||
988 | static struct snd_kcontrol_new stac9200_mixer[] = { | 995 | static struct snd_kcontrol_new stac9200_mixer[] = { |
989 | HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), | 996 | HDA_CODEC_VOLUME_MIN_MUTE("Master Playback Volume", 0xb, 0, HDA_OUTPUT), |
990 | HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), | 997 | HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), |
991 | HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), | 998 | HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), |
992 | HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), | 999 | HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), |
@@ -1014,7 +1021,7 @@ static struct snd_kcontrol_new stac92hd71bxx_loopback[] = { | |||
1014 | }; | 1021 | }; |
1015 | 1022 | ||
1016 | static struct snd_kcontrol_new stac925x_mixer[] = { | 1023 | static struct snd_kcontrol_new stac925x_mixer[] = { |
1017 | HDA_CODEC_VOLUME("Master Playback Volume", 0x0e, 0, HDA_OUTPUT), | 1024 | HDA_CODEC_VOLUME_MIN_MUTE("Master Playback Volume", 0xe, 0, HDA_OUTPUT), |
1018 | HDA_CODEC_MUTE("Master Playback Switch", 0x0e, 0, HDA_OUTPUT), | 1025 | HDA_CODEC_MUTE("Master Playback Switch", 0x0e, 0, HDA_OUTPUT), |
1019 | { } /* end */ | 1026 | { } /* end */ |
1020 | }; | 1027 | }; |
@@ -1105,9 +1112,7 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1105 | struct hda_input_mux *smux = &spec->private_smux; | 1112 | struct hda_input_mux *smux = &spec->private_smux; |
1106 | /* check for mute support on SPDIF out */ | 1113 | /* check for mute support on SPDIF out */ |
1107 | if (wcaps & AC_WCAP_OUT_AMP) { | 1114 | if (wcaps & AC_WCAP_OUT_AMP) { |
1108 | smux->items[smux->num_items].label = "Off"; | 1115 | snd_hda_add_imux_item(smux, "Off", 0, NULL); |
1109 | smux->items[smux->num_items].index = 0; | ||
1110 | smux->num_items++; | ||
1111 | spec->spdif_mute = 1; | 1116 | spec->spdif_mute = 1; |
1112 | } | 1117 | } |
1113 | stac_smux_mixer.count = spec->num_smuxes; | 1118 | stac_smux_mixer.count = spec->num_smuxes; |
@@ -1140,6 +1145,8 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1140 | HDA_OUTPUT, vmaster_tlv); | 1145 | HDA_OUTPUT, vmaster_tlv); |
1141 | /* correct volume offset */ | 1146 | /* correct volume offset */ |
1142 | vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset; | 1147 | vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset; |
1148 | /* minimum value is actually mute */ | ||
1149 | vmaster_tlv[3] |= TLV_DB_SCALE_MUTE; | ||
1143 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", | 1150 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", |
1144 | vmaster_tlv, slave_vols); | 1151 | vmaster_tlv, slave_vols); |
1145 | if (err < 0) | 1152 | if (err < 0) |
@@ -1180,14 +1187,11 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1180 | if (err < 0) | 1187 | if (err < 0) |
1181 | return err; | 1188 | return err; |
1182 | } | 1189 | } |
1183 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 1190 | for (i = 0; i < cfg->num_inputs; i++) { |
1184 | nid = cfg->input_pins[i]; | 1191 | nid = cfg->inputs[i].pin; |
1185 | if (nid) { | 1192 | err = stac92xx_add_jack(codec, nid, SND_JACK_MICROPHONE); |
1186 | err = stac92xx_add_jack(codec, nid, | 1193 | if (err < 0) |
1187 | SND_JACK_MICROPHONE); | 1194 | return err; |
1188 | if (err < 0) | ||
1189 | return err; | ||
1190 | } | ||
1191 | } | 1195 | } |
1192 | 1196 | ||
1193 | return 0; | 1197 | return 0; |
@@ -2779,7 +2783,7 @@ static inline int stac92xx_add_jack_mode_control(struct hda_codec *codec, | |||
2779 | struct sigmatel_spec *spec = codec->spec; | 2783 | struct sigmatel_spec *spec = codec->spec; |
2780 | char name[22]; | 2784 | char name[22]; |
2781 | 2785 | ||
2782 | if (!((get_defcfg_connect(def_conf)) & AC_JACK_PORT_FIXED)) { | 2786 | if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT) { |
2783 | if (stac92xx_get_default_vref(codec, nid) == AC_PINCTL_VREF_GRD | 2787 | if (stac92xx_get_default_vref(codec, nid) == AC_PINCTL_VREF_GRD |
2784 | && nid == spec->line_switch) | 2788 | && nid == spec->line_switch) |
2785 | control = STAC_CTL_WIDGET_IO_SWITCH; | 2789 | control = STAC_CTL_WIDGET_IO_SWITCH; |
@@ -2791,7 +2795,7 @@ static inline int stac92xx_add_jack_mode_control(struct hda_codec *codec, | |||
2791 | } | 2795 | } |
2792 | 2796 | ||
2793 | if (control) { | 2797 | if (control) { |
2794 | strcpy(name, auto_pin_cfg_labels[idx]); | 2798 | strcpy(name, hda_get_input_pin_label(codec, nid, 1)); |
2795 | return stac92xx_add_control(codec->spec, control, | 2799 | return stac92xx_add_control(codec->spec, control, |
2796 | strcat(name, " Jack Mode"), nid); | 2800 | strcat(name, " Jack Mode"), nid); |
2797 | } | 2801 | } |
@@ -2823,41 +2827,49 @@ static hda_nid_t check_line_out_switch(struct hda_codec *codec) | |||
2823 | struct auto_pin_cfg *cfg = &spec->autocfg; | 2827 | struct auto_pin_cfg *cfg = &spec->autocfg; |
2824 | hda_nid_t nid; | 2828 | hda_nid_t nid; |
2825 | unsigned int pincap; | 2829 | unsigned int pincap; |
2830 | int i; | ||
2826 | 2831 | ||
2827 | if (cfg->line_out_type != AUTO_PIN_LINE_OUT) | 2832 | if (cfg->line_out_type != AUTO_PIN_LINE_OUT) |
2828 | return 0; | 2833 | return 0; |
2829 | nid = cfg->input_pins[AUTO_PIN_LINE]; | 2834 | for (i = 0; i < cfg->num_inputs; i++) { |
2830 | pincap = snd_hda_query_pin_caps(codec, nid); | 2835 | if (cfg->inputs[i].type == AUTO_PIN_LINE_IN) { |
2831 | if (pincap & AC_PINCAP_OUT) | 2836 | nid = cfg->inputs[i].pin; |
2832 | return nid; | 2837 | pincap = snd_hda_query_pin_caps(codec, nid); |
2838 | if (pincap & AC_PINCAP_OUT) | ||
2839 | return nid; | ||
2840 | } | ||
2841 | } | ||
2833 | return 0; | 2842 | return 0; |
2834 | } | 2843 | } |
2835 | 2844 | ||
2845 | static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid); | ||
2846 | |||
2836 | /* check whether the mic-input can be used as line-out */ | 2847 | /* check whether the mic-input can be used as line-out */ |
2837 | static hda_nid_t check_mic_out_switch(struct hda_codec *codec) | 2848 | static hda_nid_t check_mic_out_switch(struct hda_codec *codec, hda_nid_t *dac) |
2838 | { | 2849 | { |
2839 | struct sigmatel_spec *spec = codec->spec; | 2850 | struct sigmatel_spec *spec = codec->spec; |
2840 | struct auto_pin_cfg *cfg = &spec->autocfg; | 2851 | struct auto_pin_cfg *cfg = &spec->autocfg; |
2841 | unsigned int def_conf, pincap; | 2852 | unsigned int def_conf, pincap; |
2842 | unsigned int mic_pin; | 2853 | int i; |
2843 | 2854 | ||
2855 | *dac = 0; | ||
2844 | if (cfg->line_out_type != AUTO_PIN_LINE_OUT) | 2856 | if (cfg->line_out_type != AUTO_PIN_LINE_OUT) |
2845 | return 0; | 2857 | return 0; |
2846 | mic_pin = AUTO_PIN_MIC; | 2858 | for (i = 0; i < cfg->num_inputs; i++) { |
2847 | for (;;) { | 2859 | hda_nid_t nid = cfg->inputs[i].pin; |
2848 | hda_nid_t nid = cfg->input_pins[mic_pin]; | 2860 | if (cfg->inputs[i].type != AUTO_PIN_MIC) |
2861 | continue; | ||
2849 | def_conf = snd_hda_codec_get_pincfg(codec, nid); | 2862 | def_conf = snd_hda_codec_get_pincfg(codec, nid); |
2850 | /* some laptops have an internal analog microphone | 2863 | /* some laptops have an internal analog microphone |
2851 | * which can't be used as a output */ | 2864 | * which can't be used as a output */ |
2852 | if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) { | 2865 | if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT) { |
2853 | pincap = snd_hda_query_pin_caps(codec, nid); | 2866 | pincap = snd_hda_query_pin_caps(codec, nid); |
2854 | if (pincap & AC_PINCAP_OUT) | 2867 | if (pincap & AC_PINCAP_OUT) { |
2855 | return nid; | 2868 | *dac = get_unassigned_dac(codec, nid); |
2869 | if (*dac) | ||
2870 | return nid; | ||
2871 | } | ||
2856 | } | 2872 | } |
2857 | if (mic_pin == AUTO_PIN_MIC) | ||
2858 | mic_pin = AUTO_PIN_FRONT_MIC; | ||
2859 | else | ||
2860 | break; | ||
2861 | } | 2873 | } |
2862 | return 0; | 2874 | return 0; |
2863 | } | 2875 | } |
@@ -3004,17 +3016,14 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec) | |||
3004 | } | 3016 | } |
3005 | } | 3017 | } |
3006 | /* add mic as output */ | 3018 | /* add mic as output */ |
3007 | nid = check_mic_out_switch(codec); | 3019 | nid = check_mic_out_switch(codec, &dac); |
3008 | if (nid) { | 3020 | if (nid && dac) { |
3009 | dac = get_unassigned_dac(codec, nid); | 3021 | snd_printdd("STAC: Add mic-in 0x%x as output %d\n", |
3010 | if (dac) { | 3022 | nid, cfg->line_outs); |
3011 | snd_printdd("STAC: Add mic-in 0x%x as output %d\n", | 3023 | cfg->line_out_pins[cfg->line_outs] = nid; |
3012 | nid, cfg->line_outs); | 3024 | cfg->line_outs++; |
3013 | cfg->line_out_pins[cfg->line_outs] = nid; | 3025 | spec->mic_switch = nid; |
3014 | cfg->line_outs++; | 3026 | add_spec_dacs(spec, dac); |
3015 | spec->mic_switch = nid; | ||
3016 | add_spec_dacs(spec, dac); | ||
3017 | } | ||
3018 | } | 3027 | } |
3019 | 3028 | ||
3020 | snd_printd("stac92xx: dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", | 3029 | snd_printd("stac92xx: dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", |
@@ -3204,13 +3213,13 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
3204 | return err; | 3213 | return err; |
3205 | } | 3214 | } |
3206 | 3215 | ||
3207 | for (idx = AUTO_PIN_MIC; idx <= AUTO_PIN_FRONT_LINE; idx++) { | 3216 | for (idx = 0; idx < cfg->num_inputs; idx++) { |
3208 | nid = cfg->input_pins[idx]; | 3217 | if (cfg->inputs[idx].type > AUTO_PIN_LINE_IN) |
3209 | if (nid) { | 3218 | break; |
3210 | err = stac92xx_add_jack_mode_control(codec, nid, idx); | 3219 | nid = cfg->inputs[idx].pin; |
3211 | if (err < 0) | 3220 | err = stac92xx_add_jack_mode_control(codec, nid, idx); |
3212 | return err; | 3221 | if (err < 0) |
3213 | } | 3222 | return err; |
3214 | } | 3223 | } |
3215 | 3224 | ||
3216 | return 0; | 3225 | return 0; |
@@ -3256,12 +3265,9 @@ static int stac92xx_auto_create_mono_output_ctls(struct hda_codec *codec) | |||
3256 | if (num_cons <= 0 || num_cons > ARRAY_SIZE(stac92xx_mono_labels)) | 3265 | if (num_cons <= 0 || num_cons > ARRAY_SIZE(stac92xx_mono_labels)) |
3257 | return -EINVAL; | 3266 | return -EINVAL; |
3258 | 3267 | ||
3259 | for (i = 0; i < num_cons; i++) { | 3268 | for (i = 0; i < num_cons; i++) |
3260 | mono_mux->items[mono_mux->num_items].label = | 3269 | snd_hda_add_imux_item(mono_mux, stac92xx_mono_labels[i], i, |
3261 | stac92xx_mono_labels[i]; | 3270 | NULL); |
3262 | mono_mux->items[mono_mux->num_items].index = i; | ||
3263 | mono_mux->num_items++; | ||
3264 | } | ||
3265 | 3271 | ||
3266 | return stac92xx_add_control(spec, STAC_CTL_WIDGET_MONO_MUX, | 3272 | return stac92xx_add_control(spec, STAC_CTL_WIDGET_MONO_MUX, |
3267 | "Mono Mux", spec->mono_nid); | 3273 | "Mono Mux", spec->mono_nid); |
@@ -3386,11 +3392,8 @@ static int stac92xx_auto_create_spdif_mux_ctls(struct hda_codec *codec) | |||
3386 | if (!labels) | 3392 | if (!labels) |
3387 | labels = stac92xx_spdif_labels; | 3393 | labels = stac92xx_spdif_labels; |
3388 | 3394 | ||
3389 | for (i = 0; i < num_cons; i++) { | 3395 | for (i = 0; i < num_cons; i++) |
3390 | spdif_mux->items[spdif_mux->num_items].label = labels[i]; | 3396 | snd_hda_add_imux_item(spdif_mux, labels[i], i, NULL); |
3391 | spdif_mux->items[spdif_mux->num_items].index = i; | ||
3392 | spdif_mux->num_items++; | ||
3393 | } | ||
3394 | 3397 | ||
3395 | return 0; | 3398 | return 0; |
3396 | } | 3399 | } |
@@ -3417,7 +3420,7 @@ static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, | |||
3417 | /* create a volume assigned to the given pin (only if supported) */ | 3420 | /* create a volume assigned to the given pin (only if supported) */ |
3418 | /* return 1 if the volume control is created */ | 3421 | /* return 1 if the volume control is created */ |
3419 | static int create_elem_capture_vol(struct hda_codec *codec, hda_nid_t nid, | 3422 | static int create_elem_capture_vol(struct hda_codec *codec, hda_nid_t nid, |
3420 | const char *label, int direction) | 3423 | const char *label, int idx, int direction) |
3421 | { | 3424 | { |
3422 | unsigned int caps, nums; | 3425 | unsigned int caps, nums; |
3423 | char name[32]; | 3426 | char name[32]; |
@@ -3434,8 +3437,8 @@ static int create_elem_capture_vol(struct hda_codec *codec, hda_nid_t nid, | |||
3434 | if (!nums) | 3437 | if (!nums) |
3435 | return 0; | 3438 | return 0; |
3436 | snprintf(name, sizeof(name), "%s Capture Volume", label); | 3439 | snprintf(name, sizeof(name), "%s Capture Volume", label); |
3437 | err = stac92xx_add_control(codec->spec, STAC_CTL_WIDGET_VOL, name, | 3440 | err = stac92xx_add_control_idx(codec->spec, STAC_CTL_WIDGET_VOL, idx, name, |
3438 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, direction)); | 3441 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, direction)); |
3439 | if (err < 0) | 3442 | if (err < 0) |
3440 | return err; | 3443 | return err; |
3441 | return 1; | 3444 | return 1; |
@@ -3448,27 +3451,14 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, | |||
3448 | struct sigmatel_spec *spec = codec->spec; | 3451 | struct sigmatel_spec *spec = codec->spec; |
3449 | struct hda_input_mux *imux = &spec->private_imux; | 3452 | struct hda_input_mux *imux = &spec->private_imux; |
3450 | struct hda_input_mux *dimux = &spec->private_dimux; | 3453 | struct hda_input_mux *dimux = &spec->private_dimux; |
3451 | int err, i, active_mics; | 3454 | int err, i; |
3452 | unsigned int def_conf; | 3455 | unsigned int def_conf; |
3453 | 3456 | ||
3454 | dimux->items[dimux->num_items].label = stac92xx_dmic_labels[0]; | 3457 | snd_hda_add_imux_item(dimux, stac92xx_dmic_labels[0], 0, NULL); |
3455 | dimux->items[dimux->num_items].index = 0; | ||
3456 | dimux->num_items++; | ||
3457 | |||
3458 | active_mics = 0; | ||
3459 | for (i = 0; i < spec->num_dmics; i++) { | ||
3460 | /* check the validity: sometimes it's a dead vendor-spec node */ | ||
3461 | if (get_wcaps_type(get_wcaps(codec, spec->dmic_nids[i])) | ||
3462 | != AC_WID_PIN) | ||
3463 | continue; | ||
3464 | def_conf = snd_hda_codec_get_pincfg(codec, spec->dmic_nids[i]); | ||
3465 | if (get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE) | ||
3466 | active_mics++; | ||
3467 | } | ||
3468 | 3458 | ||
3469 | for (i = 0; i < spec->num_dmics; i++) { | 3459 | for (i = 0; i < spec->num_dmics; i++) { |
3470 | hda_nid_t nid; | 3460 | hda_nid_t nid; |
3471 | int index; | 3461 | int index, type_idx; |
3472 | const char *label; | 3462 | const char *label; |
3473 | 3463 | ||
3474 | nid = spec->dmic_nids[i]; | 3464 | nid = spec->dmic_nids[i]; |
@@ -3482,28 +3472,23 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, | |||
3482 | if (index < 0) | 3472 | if (index < 0) |
3483 | continue; | 3473 | continue; |
3484 | 3474 | ||
3485 | if (active_mics == 1) | 3475 | label = hda_get_input_pin_label(codec, nid, 1); |
3486 | label = "Digital Mic"; | 3476 | snd_hda_add_imux_item(dimux, label, index, &type_idx); |
3487 | else | ||
3488 | label = stac92xx_dmic_labels[dimux->num_items]; | ||
3489 | 3477 | ||
3490 | err = create_elem_capture_vol(codec, nid, label, HDA_INPUT); | 3478 | err = create_elem_capture_vol(codec, nid, label, type_idx, |
3479 | HDA_INPUT); | ||
3491 | if (err < 0) | 3480 | if (err < 0) |
3492 | return err; | 3481 | return err; |
3493 | if (!err) { | 3482 | if (!err) { |
3494 | err = create_elem_capture_vol(codec, nid, label, | 3483 | err = create_elem_capture_vol(codec, nid, label, |
3495 | HDA_OUTPUT); | 3484 | type_idx, HDA_OUTPUT); |
3496 | if (err < 0) | 3485 | if (err < 0) |
3497 | return err; | 3486 | return err; |
3498 | } | 3487 | } |
3499 | 3488 | ||
3500 | dimux->items[dimux->num_items].label = label; | ||
3501 | dimux->items[dimux->num_items].index = index; | ||
3502 | dimux->num_items++; | ||
3503 | if (snd_hda_get_bool_hint(codec, "separate_dmux") != 1) { | 3489 | if (snd_hda_get_bool_hint(codec, "separate_dmux") != 1) { |
3504 | imux->items[imux->num_items].label = label; | 3490 | snd_hda_add_imux_item(imux, label, index, NULL); |
3505 | imux->items[imux->num_items].index = index; | 3491 | spec->num_analog_muxes++; |
3506 | imux->num_items++; | ||
3507 | } | 3492 | } |
3508 | } | 3493 | } |
3509 | 3494 | ||
@@ -3511,20 +3496,27 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, | |||
3511 | } | 3496 | } |
3512 | 3497 | ||
3513 | static int check_mic_pin(struct hda_codec *codec, hda_nid_t nid, | 3498 | static int check_mic_pin(struct hda_codec *codec, hda_nid_t nid, |
3514 | hda_nid_t *fixed, hda_nid_t *ext) | 3499 | hda_nid_t *fixed, hda_nid_t *ext, hda_nid_t *dock) |
3515 | { | 3500 | { |
3516 | unsigned int cfg; | 3501 | unsigned int cfg; |
3517 | 3502 | ||
3518 | if (!nid) | 3503 | if (!nid) |
3519 | return 0; | 3504 | return 0; |
3520 | cfg = snd_hda_codec_get_pincfg(codec, nid); | 3505 | cfg = snd_hda_codec_get_pincfg(codec, nid); |
3521 | switch (get_defcfg_connect(cfg)) { | 3506 | switch (snd_hda_get_input_pin_attr(cfg)) { |
3522 | case AC_JACK_PORT_FIXED: | 3507 | case INPUT_PIN_ATTR_INT: |
3523 | if (*fixed) | 3508 | if (*fixed) |
3524 | return 1; /* already occupied */ | 3509 | return 1; /* already occupied */ |
3525 | *fixed = nid; | 3510 | *fixed = nid; |
3526 | break; | 3511 | break; |
3527 | case AC_JACK_PORT_COMPLEX: | 3512 | case INPUT_PIN_ATTR_UNUSED: |
3513 | break; | ||
3514 | case INPUT_PIN_ATTR_DOCK: | ||
3515 | if (*dock) | ||
3516 | return 1; /* already occupied */ | ||
3517 | *dock = nid; | ||
3518 | break; | ||
3519 | default: | ||
3528 | if (*ext) | 3520 | if (*ext) |
3529 | return 1; /* already occupied */ | 3521 | return 1; /* already occupied */ |
3530 | *ext = nid; | 3522 | *ext = nid; |
@@ -3542,10 +3534,13 @@ static int set_mic_route(struct hda_codec *codec, | |||
3542 | int i; | 3534 | int i; |
3543 | 3535 | ||
3544 | mic->pin = pin; | 3536 | mic->pin = pin; |
3545 | for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++) | 3537 | if (pin == 0) |
3546 | if (pin == cfg->input_pins[i]) | 3538 | return 0; |
3539 | for (i = 0; i < cfg->num_inputs; i++) { | ||
3540 | if (pin == cfg->inputs[i].pin) | ||
3547 | break; | 3541 | break; |
3548 | if (i <= AUTO_PIN_FRONT_MIC) { | 3542 | } |
3543 | if (i < cfg->num_inputs && cfg->inputs[i].type == AUTO_PIN_MIC) { | ||
3549 | /* analog pin */ | 3544 | /* analog pin */ |
3550 | i = get_connection_index(codec, spec->mux_nids[0], pin); | 3545 | i = get_connection_index(codec, spec->mux_nids[0], pin); |
3551 | if (i < 0) | 3546 | if (i < 0) |
@@ -3576,26 +3571,29 @@ static int stac_check_auto_mic(struct hda_codec *codec) | |||
3576 | { | 3571 | { |
3577 | struct sigmatel_spec *spec = codec->spec; | 3572 | struct sigmatel_spec *spec = codec->spec; |
3578 | struct auto_pin_cfg *cfg = &spec->autocfg; | 3573 | struct auto_pin_cfg *cfg = &spec->autocfg; |
3579 | hda_nid_t fixed, ext; | 3574 | hda_nid_t fixed, ext, dock; |
3580 | int i; | 3575 | int i; |
3581 | 3576 | ||
3582 | for (i = AUTO_PIN_LINE; i < AUTO_PIN_LAST; i++) { | 3577 | for (i = 0; i < cfg->num_inputs; i++) { |
3583 | if (cfg->input_pins[i]) | 3578 | if (cfg->inputs[i].type >= AUTO_PIN_LINE_IN) |
3584 | return 0; /* must be exclusively mics */ | 3579 | return 0; /* must be exclusively mics */ |
3585 | } | 3580 | } |
3586 | fixed = ext = 0; | 3581 | fixed = ext = dock = 0; |
3587 | for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++) | 3582 | for (i = 0; i < cfg->num_inputs; i++) |
3588 | if (check_mic_pin(codec, cfg->input_pins[i], &fixed, &ext)) | 3583 | if (check_mic_pin(codec, cfg->inputs[i].pin, |
3584 | &fixed, &ext, &dock)) | ||
3589 | return 0; | 3585 | return 0; |
3590 | for (i = 0; i < spec->num_dmics; i++) | 3586 | for (i = 0; i < spec->num_dmics; i++) |
3591 | if (check_mic_pin(codec, spec->dmic_nids[i], &fixed, &ext)) | 3587 | if (check_mic_pin(codec, spec->dmic_nids[i], |
3588 | &fixed, &ext, &dock)) | ||
3592 | return 0; | 3589 | return 0; |
3593 | if (!fixed || !ext) | 3590 | if (!fixed && !ext && !dock) |
3594 | return 0; | 3591 | return 0; /* no input to switch */ |
3595 | if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP)) | 3592 | if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP)) |
3596 | return 0; /* no unsol support */ | 3593 | return 0; /* no unsol support */ |
3597 | if (set_mic_route(codec, &spec->ext_mic, ext) || | 3594 | if (set_mic_route(codec, &spec->ext_mic, ext) || |
3598 | set_mic_route(codec, &spec->int_mic, fixed)) | 3595 | set_mic_route(codec, &spec->int_mic, fixed) || |
3596 | set_mic_route(codec, &spec->dock_mic, dock)) | ||
3599 | return 0; /* something is wrong */ | 3597 | return 0; /* something is wrong */ |
3600 | return 1; | 3598 | return 1; |
3601 | } | 3599 | } |
@@ -3606,13 +3604,12 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const | |||
3606 | struct sigmatel_spec *spec = codec->spec; | 3604 | struct sigmatel_spec *spec = codec->spec; |
3607 | struct hda_input_mux *imux = &spec->private_imux; | 3605 | struct hda_input_mux *imux = &spec->private_imux; |
3608 | int i, j; | 3606 | int i, j; |
3607 | const char *label; | ||
3609 | 3608 | ||
3610 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 3609 | for (i = 0; i < cfg->num_inputs; i++) { |
3611 | hda_nid_t nid = cfg->input_pins[i]; | 3610 | hda_nid_t nid = cfg->inputs[i].pin; |
3612 | int index, err; | 3611 | int index, err, type_idx; |
3613 | 3612 | ||
3614 | if (!nid) | ||
3615 | continue; | ||
3616 | index = -1; | 3613 | index = -1; |
3617 | for (j = 0; j < spec->num_muxes; j++) { | 3614 | for (j = 0; j < spec->num_muxes; j++) { |
3618 | index = get_connection_index(codec, spec->mux_nids[j], | 3615 | index = get_connection_index(codec, spec->mux_nids[j], |
@@ -3623,15 +3620,14 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const | |||
3623 | if (index < 0) | 3620 | if (index < 0) |
3624 | continue; | 3621 | continue; |
3625 | 3622 | ||
3623 | label = hda_get_autocfg_input_label(codec, cfg, i); | ||
3624 | snd_hda_add_imux_item(imux, label, index, &type_idx); | ||
3625 | |||
3626 | err = create_elem_capture_vol(codec, nid, | 3626 | err = create_elem_capture_vol(codec, nid, |
3627 | auto_pin_cfg_labels[i], | 3627 | label, type_idx, |
3628 | HDA_INPUT); | 3628 | HDA_INPUT); |
3629 | if (err < 0) | 3629 | if (err < 0) |
3630 | return err; | 3630 | return err; |
3631 | |||
3632 | imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; | ||
3633 | imux->items[imux->num_items].index = index; | ||
3634 | imux->num_items++; | ||
3635 | } | 3631 | } |
3636 | spec->num_analog_muxes = imux->num_items; | 3632 | spec->num_analog_muxes = imux->num_items; |
3637 | 3633 | ||
@@ -4305,38 +4301,38 @@ static int stac92xx_init(struct hda_codec *codec) | |||
4305 | AC_VERB_SET_CONNECT_SEL, 0); | 4301 | AC_VERB_SET_CONNECT_SEL, 0); |
4306 | if (enable_pin_detect(codec, spec->ext_mic.pin, STAC_MIC_EVENT)) | 4302 | if (enable_pin_detect(codec, spec->ext_mic.pin, STAC_MIC_EVENT)) |
4307 | stac_issue_unsol_event(codec, spec->ext_mic.pin); | 4303 | stac_issue_unsol_event(codec, spec->ext_mic.pin); |
4308 | } | 4304 | if (enable_pin_detect(codec, spec->dock_mic.pin, |
4309 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 4305 | STAC_MIC_EVENT)) |
4310 | hda_nid_t nid = cfg->input_pins[i]; | 4306 | stac_issue_unsol_event(codec, spec->dock_mic.pin); |
4311 | if (nid) { | 4307 | } |
4312 | unsigned int pinctl, conf; | 4308 | for (i = 0; i < cfg->num_inputs; i++) { |
4313 | if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) { | 4309 | hda_nid_t nid = cfg->inputs[i].pin; |
4314 | /* for mic pins, force to initialize */ | 4310 | int type = cfg->inputs[i].type; |
4315 | pinctl = stac92xx_get_default_vref(codec, nid); | 4311 | unsigned int pinctl, conf; |
4312 | if (type == AUTO_PIN_MIC) { | ||
4313 | /* for mic pins, force to initialize */ | ||
4314 | pinctl = stac92xx_get_default_vref(codec, nid); | ||
4315 | pinctl |= AC_PINCTL_IN_EN; | ||
4316 | stac92xx_auto_set_pinctl(codec, nid, pinctl); | ||
4317 | } else { | ||
4318 | pinctl = snd_hda_codec_read(codec, nid, 0, | ||
4319 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
4320 | /* if PINCTL already set then skip */ | ||
4321 | /* Also, if both INPUT and OUTPUT are set, | ||
4322 | * it must be a BIOS bug; need to override, too | ||
4323 | */ | ||
4324 | if (!(pinctl & AC_PINCTL_IN_EN) || | ||
4325 | (pinctl & AC_PINCTL_OUT_EN)) { | ||
4326 | pinctl &= ~AC_PINCTL_OUT_EN; | ||
4316 | pinctl |= AC_PINCTL_IN_EN; | 4327 | pinctl |= AC_PINCTL_IN_EN; |
4317 | stac92xx_auto_set_pinctl(codec, nid, pinctl); | 4328 | stac92xx_auto_set_pinctl(codec, nid, pinctl); |
4318 | } else { | ||
4319 | pinctl = snd_hda_codec_read(codec, nid, 0, | ||
4320 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
4321 | /* if PINCTL already set then skip */ | ||
4322 | /* Also, if both INPUT and OUTPUT are set, | ||
4323 | * it must be a BIOS bug; need to override, too | ||
4324 | */ | ||
4325 | if (!(pinctl & AC_PINCTL_IN_EN) || | ||
4326 | (pinctl & AC_PINCTL_OUT_EN)) { | ||
4327 | pinctl &= ~AC_PINCTL_OUT_EN; | ||
4328 | pinctl |= AC_PINCTL_IN_EN; | ||
4329 | stac92xx_auto_set_pinctl(codec, nid, | ||
4330 | pinctl); | ||
4331 | } | ||
4332 | } | ||
4333 | conf = snd_hda_codec_get_pincfg(codec, nid); | ||
4334 | if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) { | ||
4335 | if (enable_pin_detect(codec, nid, | ||
4336 | STAC_INSERT_EVENT)) | ||
4337 | stac_issue_unsol_event(codec, nid); | ||
4338 | } | 4329 | } |
4339 | } | 4330 | } |
4331 | conf = snd_hda_codec_get_pincfg(codec, nid); | ||
4332 | if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) { | ||
4333 | if (enable_pin_detect(codec, nid, STAC_INSERT_EVENT)) | ||
4334 | stac_issue_unsol_event(codec, nid); | ||
4335 | } | ||
4340 | } | 4336 | } |
4341 | for (i = 0; i < spec->num_dmics; i++) | 4337 | for (i = 0; i < spec->num_dmics; i++) |
4342 | stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i], | 4338 | stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i], |
@@ -4383,11 +4379,9 @@ static int stac92xx_init(struct hda_codec *codec) | |||
4383 | stac_issue_unsol_event(codec, nid); | 4379 | stac_issue_unsol_event(codec, nid); |
4384 | } | 4380 | } |
4385 | 4381 | ||
4386 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4387 | /* sync mute LED */ | 4382 | /* sync mute LED */ |
4388 | if (spec->gpio_led && codec->patch_ops.check_power_status) | 4383 | if (spec->gpio_led) |
4389 | codec->patch_ops.check_power_status(codec, 0x01); | 4384 | hda_call_check_power_status(codec, 0x01); |
4390 | #endif | ||
4391 | if (spec->dac_list) | 4385 | if (spec->dac_list) |
4392 | stac92xx_power_down(codec); | 4386 | stac92xx_power_down(codec); |
4393 | return 0; | 4387 | return 0; |
@@ -4688,6 +4682,36 @@ static void stac92xx_report_jack(struct hda_codec *codec, hda_nid_t nid) | |||
4688 | } | 4682 | } |
4689 | } | 4683 | } |
4690 | 4684 | ||
4685 | /* get the pin connection (fixed, none, etc) */ | ||
4686 | static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx) | ||
4687 | { | ||
4688 | struct sigmatel_spec *spec = codec->spec; | ||
4689 | unsigned int cfg; | ||
4690 | |||
4691 | cfg = snd_hda_codec_get_pincfg(codec, spec->pin_nids[idx]); | ||
4692 | return get_defcfg_connect(cfg); | ||
4693 | } | ||
4694 | |||
4695 | static int stac92xx_connected_ports(struct hda_codec *codec, | ||
4696 | hda_nid_t *nids, int num_nids) | ||
4697 | { | ||
4698 | struct sigmatel_spec *spec = codec->spec; | ||
4699 | int idx, num; | ||
4700 | unsigned int def_conf; | ||
4701 | |||
4702 | for (num = 0; num < num_nids; num++) { | ||
4703 | for (idx = 0; idx < spec->num_pins; idx++) | ||
4704 | if (spec->pin_nids[idx] == nids[num]) | ||
4705 | break; | ||
4706 | if (idx >= spec->num_pins) | ||
4707 | break; | ||
4708 | def_conf = stac_get_defcfg_connect(codec, idx); | ||
4709 | if (def_conf == AC_JACK_PORT_NONE) | ||
4710 | break; | ||
4711 | } | ||
4712 | return num; | ||
4713 | } | ||
4714 | |||
4691 | static void stac92xx_mic_detect(struct hda_codec *codec) | 4715 | static void stac92xx_mic_detect(struct hda_codec *codec) |
4692 | { | 4716 | { |
4693 | struct sigmatel_spec *spec = codec->spec; | 4717 | struct sigmatel_spec *spec = codec->spec; |
@@ -4695,6 +4719,8 @@ static void stac92xx_mic_detect(struct hda_codec *codec) | |||
4695 | 4719 | ||
4696 | if (get_pin_presence(codec, spec->ext_mic.pin)) | 4720 | if (get_pin_presence(codec, spec->ext_mic.pin)) |
4697 | mic = &spec->ext_mic; | 4721 | mic = &spec->ext_mic; |
4722 | else if (get_pin_presence(codec, spec->dock_mic.pin)) | ||
4723 | mic = &spec->dock_mic; | ||
4698 | else | 4724 | else |
4699 | mic = &spec->int_mic; | 4725 | mic = &spec->int_mic; |
4700 | if (mic->dmux_idx >= 0) | 4726 | if (mic->dmux_idx >= 0) |
@@ -4937,11 +4963,9 @@ static int stac92xx_resume(struct hda_codec *codec) | |||
4937 | stac_issue_unsol_event(codec, | 4963 | stac_issue_unsol_event(codec, |
4938 | spec->autocfg.line_out_pins[0]); | 4964 | spec->autocfg.line_out_pins[0]); |
4939 | } | 4965 | } |
4940 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4941 | /* sync mute LED */ | 4966 | /* sync mute LED */ |
4942 | if (spec->gpio_led && codec->patch_ops.check_power_status) | 4967 | if (spec->gpio_led) |
4943 | codec->patch_ops.check_power_status(codec, 0x01); | 4968 | hda_call_check_power_status(codec, 0x01); |
4944 | #endif | ||
4945 | return 0; | 4969 | return 0; |
4946 | } | 4970 | } |
4947 | 4971 | ||
@@ -5313,11 +5337,16 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) | |||
5313 | if (spec == NULL) | 5337 | if (spec == NULL) |
5314 | return -ENOMEM; | 5338 | return -ENOMEM; |
5315 | 5339 | ||
5340 | /* reset pin power-down; Windows may leave these bits after reboot */ | ||
5341 | snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7EC, 0); | ||
5342 | snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7ED, 0); | ||
5316 | codec->no_trigger_sense = 1; | 5343 | codec->no_trigger_sense = 1; |
5317 | codec->spec = spec; | 5344 | codec->spec = spec; |
5318 | spec->linear_tone_beep = 1; | 5345 | spec->linear_tone_beep = 1; |
5319 | codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs; | 5346 | codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs; |
5320 | spec->digbeep_nid = 0x21; | 5347 | spec->digbeep_nid = 0x21; |
5348 | spec->dmic_nids = stac92hd83xxx_dmic_nids; | ||
5349 | spec->dmux_nids = stac92hd83xxx_mux_nids; | ||
5321 | spec->mux_nids = stac92hd83xxx_mux_nids; | 5350 | spec->mux_nids = stac92hd83xxx_mux_nids; |
5322 | spec->num_muxes = ARRAY_SIZE(stac92hd83xxx_mux_nids); | 5351 | spec->num_muxes = ARRAY_SIZE(stac92hd83xxx_mux_nids); |
5323 | spec->adc_nids = stac92hd83xxx_adc_nids; | 5352 | spec->adc_nids = stac92hd83xxx_adc_nids; |
@@ -5363,9 +5392,13 @@ again: | |||
5363 | case 0x111d76d4: | 5392 | case 0x111d76d4: |
5364 | case 0x111d7605: | 5393 | case 0x111d7605: |
5365 | case 0x111d76d5: | 5394 | case 0x111d76d5: |
5395 | case 0x111d76e7: | ||
5366 | if (spec->board_config == STAC_92HD83XXX_PWR_REF) | 5396 | if (spec->board_config == STAC_92HD83XXX_PWR_REF) |
5367 | break; | 5397 | break; |
5368 | spec->num_pwrs = 0; | 5398 | spec->num_pwrs = 0; |
5399 | spec->num_dmics = stac92xx_connected_ports(codec, | ||
5400 | stac92hd83xxx_dmic_nids, | ||
5401 | STAC92HD83XXX_NUM_DMICS); | ||
5369 | break; | 5402 | break; |
5370 | } | 5403 | } |
5371 | 5404 | ||
@@ -5424,36 +5457,6 @@ again: | |||
5424 | return 0; | 5457 | return 0; |
5425 | } | 5458 | } |
5426 | 5459 | ||
5427 | /* get the pin connection (fixed, none, etc) */ | ||
5428 | static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx) | ||
5429 | { | ||
5430 | struct sigmatel_spec *spec = codec->spec; | ||
5431 | unsigned int cfg; | ||
5432 | |||
5433 | cfg = snd_hda_codec_get_pincfg(codec, spec->pin_nids[idx]); | ||
5434 | return get_defcfg_connect(cfg); | ||
5435 | } | ||
5436 | |||
5437 | static int stac92hd71bxx_connected_ports(struct hda_codec *codec, | ||
5438 | hda_nid_t *nids, int num_nids) | ||
5439 | { | ||
5440 | struct sigmatel_spec *spec = codec->spec; | ||
5441 | int idx, num; | ||
5442 | unsigned int def_conf; | ||
5443 | |||
5444 | for (num = 0; num < num_nids; num++) { | ||
5445 | for (idx = 0; idx < spec->num_pins; idx++) | ||
5446 | if (spec->pin_nids[idx] == nids[num]) | ||
5447 | break; | ||
5448 | if (idx >= spec->num_pins) | ||
5449 | break; | ||
5450 | def_conf = stac_get_defcfg_connect(codec, idx); | ||
5451 | if (def_conf == AC_JACK_PORT_NONE) | ||
5452 | break; | ||
5453 | } | ||
5454 | return num; | ||
5455 | } | ||
5456 | |||
5457 | static int stac92hd71bxx_connected_smuxes(struct hda_codec *codec, | 5460 | static int stac92hd71bxx_connected_smuxes(struct hda_codec *codec, |
5458 | hda_nid_t dig0pin) | 5461 | hda_nid_t dig0pin) |
5459 | { | 5462 | { |
@@ -5592,7 +5595,7 @@ again: | |||
5592 | case 0x111d76b5: | 5595 | case 0x111d76b5: |
5593 | spec->init = stac92hd71bxx_core_init; | 5596 | spec->init = stac92hd71bxx_core_init; |
5594 | codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; | 5597 | codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; |
5595 | spec->num_dmics = stac92hd71bxx_connected_ports(codec, | 5598 | spec->num_dmics = stac92xx_connected_ports(codec, |
5596 | stac92hd71bxx_dmic_nids, | 5599 | stac92hd71bxx_dmic_nids, |
5597 | STAC92HD71BXX_NUM_DMICS); | 5600 | STAC92HD71BXX_NUM_DMICS); |
5598 | break; | 5601 | break; |
@@ -5624,7 +5627,7 @@ again: | |||
5624 | snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0); | 5627 | snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0); |
5625 | snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3); | 5628 | snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3); |
5626 | stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS - 1] = 0; | 5629 | stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS - 1] = 0; |
5627 | spec->num_dmics = stac92hd71bxx_connected_ports(codec, | 5630 | spec->num_dmics = stac92xx_connected_ports(codec, |
5628 | stac92hd71bxx_dmic_nids, | 5631 | stac92hd71bxx_dmic_nids, |
5629 | STAC92HD71BXX_NUM_DMICS - 1); | 5632 | STAC92HD71BXX_NUM_DMICS - 1); |
5630 | break; | 5633 | break; |
@@ -5638,7 +5641,7 @@ again: | |||
5638 | default: | 5641 | default: |
5639 | spec->init = stac92hd71bxx_core_init; | 5642 | spec->init = stac92hd71bxx_core_init; |
5640 | codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; | 5643 | codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; |
5641 | spec->num_dmics = stac92hd71bxx_connected_ports(codec, | 5644 | spec->num_dmics = stac92xx_connected_ports(codec, |
5642 | stac92hd71bxx_dmic_nids, | 5645 | stac92hd71bxx_dmic_nids, |
5643 | STAC92HD71BXX_NUM_DMICS); | 5646 | STAC92HD71BXX_NUM_DMICS); |
5644 | break; | 5647 | break; |
@@ -6320,6 +6323,8 @@ static struct hda_codec_preset snd_hda_preset_sigmatel[] = { | |||
6320 | { .id = 0x111d76cc, .name = "92HD89F3", .patch = patch_stac92hd73xx }, | 6323 | { .id = 0x111d76cc, .name = "92HD89F3", .patch = patch_stac92hd73xx }, |
6321 | { .id = 0x111d76cd, .name = "92HD89F2", .patch = patch_stac92hd73xx }, | 6324 | { .id = 0x111d76cd, .name = "92HD89F2", .patch = patch_stac92hd73xx }, |
6322 | { .id = 0x111d76ce, .name = "92HD89F1", .patch = patch_stac92hd73xx }, | 6325 | { .id = 0x111d76ce, .name = "92HD89F1", .patch = patch_stac92hd73xx }, |
6326 | { .id = 0x111d76e0, .name = "92HD91BXX", .patch = patch_stac92hd83xxx}, | ||
6327 | { .id = 0x111d76e7, .name = "92HD90BXX", .patch = patch_stac92hd83xxx}, | ||
6323 | {} /* terminator */ | 6328 | {} /* terminator */ |
6324 | }; | 6329 | }; |
6325 | 6330 | ||
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index ae3acb2b42d1..d1c3f8defc48 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -444,8 +444,8 @@ static hda_nid_t vt1812_adc_nids[2] = { | |||
444 | 444 | ||
445 | 445 | ||
446 | /* add dynamic controls */ | 446 | /* add dynamic controls */ |
447 | static int via_add_control(struct via_spec *spec, int type, const char *name, | 447 | static int __via_add_control(struct via_spec *spec, int type, const char *name, |
448 | unsigned long val) | 448 | int idx, unsigned long val) |
449 | { | 449 | { |
450 | struct snd_kcontrol_new *knew; | 450 | struct snd_kcontrol_new *knew; |
451 | 451 | ||
@@ -463,6 +463,9 @@ static int via_add_control(struct via_spec *spec, int type, const char *name, | |||
463 | return 0; | 463 | return 0; |
464 | } | 464 | } |
465 | 465 | ||
466 | #define via_add_control(spec, type, name, val) \ | ||
467 | __via_add_control(spec, type, name, 0, val) | ||
468 | |||
466 | static struct snd_kcontrol_new *via_clone_control(struct via_spec *spec, | 469 | static struct snd_kcontrol_new *via_clone_control(struct via_spec *spec, |
467 | struct snd_kcontrol_new *tmpl) | 470 | struct snd_kcontrol_new *tmpl) |
468 | { | 471 | { |
@@ -494,18 +497,18 @@ static void via_free_kctls(struct hda_codec *codec) | |||
494 | 497 | ||
495 | /* create input playback/capture controls for the given pin */ | 498 | /* create input playback/capture controls for the given pin */ |
496 | static int via_new_analog_input(struct via_spec *spec, const char *ctlname, | 499 | static int via_new_analog_input(struct via_spec *spec, const char *ctlname, |
497 | int idx, int mix_nid) | 500 | int type_idx, int idx, int mix_nid) |
498 | { | 501 | { |
499 | char name[32]; | 502 | char name[32]; |
500 | int err; | 503 | int err; |
501 | 504 | ||
502 | sprintf(name, "%s Playback Volume", ctlname); | 505 | sprintf(name, "%s Playback Volume", ctlname); |
503 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, | 506 | err = __via_add_control(spec, VIA_CTL_WIDGET_VOL, name, type_idx, |
504 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); | 507 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); |
505 | if (err < 0) | 508 | if (err < 0) |
506 | return err; | 509 | return err; |
507 | sprintf(name, "%s Playback Switch", ctlname); | 510 | sprintf(name, "%s Playback Switch", ctlname); |
508 | err = via_add_control(spec, VIA_CTL_WIDGET_ANALOG_MUTE, name, | 511 | err = __via_add_control(spec, VIA_CTL_WIDGET_ANALOG_MUTE, name, type_idx, |
509 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); | 512 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); |
510 | if (err < 0) | 513 | if (err < 0) |
511 | return err; | 514 | return err; |
@@ -557,17 +560,15 @@ static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin); | |||
557 | static void via_auto_init_analog_input(struct hda_codec *codec) | 560 | static void via_auto_init_analog_input(struct hda_codec *codec) |
558 | { | 561 | { |
559 | struct via_spec *spec = codec->spec; | 562 | struct via_spec *spec = codec->spec; |
563 | const struct auto_pin_cfg *cfg = &spec->autocfg; | ||
560 | unsigned int ctl; | 564 | unsigned int ctl; |
561 | int i; | 565 | int i; |
562 | 566 | ||
563 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 567 | for (i = 0; i < cfg->num_inputs; i++) { |
564 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 568 | hda_nid_t nid = cfg->inputs[i].pin; |
565 | if (!nid) | ||
566 | continue; | ||
567 | |||
568 | if (spec->smart51_enabled && is_smart51_pins(spec, nid)) | 569 | if (spec->smart51_enabled && is_smart51_pins(spec, nid)) |
569 | ctl = PIN_OUT; | 570 | ctl = PIN_OUT; |
570 | else if (i <= AUTO_PIN_FRONT_MIC) | 571 | else if (i == AUTO_PIN_MIC) |
571 | ctl = PIN_VREF50; | 572 | ctl = PIN_VREF50; |
572 | else | 573 | else |
573 | ctl = PIN_IN; | 574 | ctl = PIN_IN; |
@@ -1322,15 +1323,14 @@ static void mute_aa_path(struct hda_codec *codec, int mute) | |||
1322 | } | 1323 | } |
1323 | static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin) | 1324 | static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin) |
1324 | { | 1325 | { |
1325 | int res = 0; | 1326 | const struct auto_pin_cfg *cfg = &spec->autocfg; |
1326 | int index; | 1327 | int i; |
1327 | for (index = AUTO_PIN_MIC; index < AUTO_PIN_FRONT_LINE; index++) { | 1328 | |
1328 | if (pin == spec->autocfg.input_pins[index]) { | 1329 | for (i = 0; i < cfg->num_inputs; i++) { |
1329 | res = 1; | 1330 | if (pin == cfg->inputs[i].pin) |
1330 | break; | 1331 | return cfg->inputs[i].type <= AUTO_PIN_LINE_IN; |
1331 | } | ||
1332 | } | 1332 | } |
1333 | return res; | 1333 | return 0; |
1334 | } | 1334 | } |
1335 | 1335 | ||
1336 | static int via_smart51_info(struct snd_kcontrol *kcontrol, | 1336 | static int via_smart51_info(struct snd_kcontrol *kcontrol, |
@@ -1348,25 +1348,21 @@ static int via_smart51_get(struct snd_kcontrol *kcontrol, | |||
1348 | { | 1348 | { |
1349 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1349 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1350 | struct via_spec *spec = codec->spec; | 1350 | struct via_spec *spec = codec->spec; |
1351 | int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE }; | 1351 | const struct auto_pin_cfg *cfg = &spec->autocfg; |
1352 | int on = 1; | 1352 | int on = 1; |
1353 | int i; | 1353 | int i; |
1354 | 1354 | ||
1355 | for (i = 0; i < ARRAY_SIZE(index); i++) { | 1355 | for (i = 0; i < cfg->num_inputs; i++) { |
1356 | hda_nid_t nid = spec->autocfg.input_pins[index[i]]; | 1356 | hda_nid_t nid = cfg->inputs[i].pin; |
1357 | if (nid) { | 1357 | int ctl = snd_hda_codec_read(codec, nid, 0, |
1358 | int ctl = | 1358 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
1359 | snd_hda_codec_read(codec, nid, 0, | 1359 | if (cfg->inputs[i].type > AUTO_PIN_LINE_IN) |
1360 | AC_VERB_GET_PIN_WIDGET_CONTROL, | 1360 | continue; |
1361 | 0); | 1361 | if (cfg->inputs[i].type == AUTO_PIN_MIC && |
1362 | if (i == AUTO_PIN_FRONT_MIC | 1362 | spec->hp_independent_mode && spec->codec_type != VT1718S) |
1363 | && spec->hp_independent_mode | 1363 | continue; /* ignore FMic for independent HP */ |
1364 | && spec->codec_type != VT1718S) | 1364 | if ((ctl & AC_PINCTL_IN_EN) && !(ctl & AC_PINCTL_OUT_EN)) |
1365 | continue; /* ignore FMic for independent HP */ | 1365 | on = 0; |
1366 | if (ctl & AC_PINCTL_IN_EN | ||
1367 | && !(ctl & AC_PINCTL_OUT_EN)) | ||
1368 | on = 0; | ||
1369 | } | ||
1370 | } | 1366 | } |
1371 | *ucontrol->value.integer.value = on; | 1367 | *ucontrol->value.integer.value = on; |
1372 | return 0; | 1368 | return 0; |
@@ -1377,36 +1373,38 @@ static int via_smart51_put(struct snd_kcontrol *kcontrol, | |||
1377 | { | 1373 | { |
1378 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1374 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1379 | struct via_spec *spec = codec->spec; | 1375 | struct via_spec *spec = codec->spec; |
1376 | const struct auto_pin_cfg *cfg = &spec->autocfg; | ||
1380 | int out_in = *ucontrol->value.integer.value | 1377 | int out_in = *ucontrol->value.integer.value |
1381 | ? AC_PINCTL_OUT_EN : AC_PINCTL_IN_EN; | 1378 | ? AC_PINCTL_OUT_EN : AC_PINCTL_IN_EN; |
1382 | int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE }; | ||
1383 | int i; | 1379 | int i; |
1384 | 1380 | ||
1385 | for (i = 0; i < ARRAY_SIZE(index); i++) { | 1381 | for (i = 0; i < cfg->num_inputs; i++) { |
1386 | hda_nid_t nid = spec->autocfg.input_pins[index[i]]; | 1382 | hda_nid_t nid = cfg->inputs[i].pin; |
1387 | if (i == AUTO_PIN_FRONT_MIC | 1383 | unsigned int parm; |
1388 | && spec->hp_independent_mode | 1384 | |
1389 | && spec->codec_type != VT1718S) | 1385 | if (cfg->inputs[i].type > AUTO_PIN_LINE_IN) |
1386 | continue; | ||
1387 | if (cfg->inputs[i].type == AUTO_PIN_MIC && | ||
1388 | spec->hp_independent_mode && spec->codec_type != VT1718S) | ||
1390 | continue; /* don't retask FMic for independent HP */ | 1389 | continue; /* don't retask FMic for independent HP */ |
1391 | if (nid) { | 1390 | |
1392 | unsigned int parm = snd_hda_codec_read( | 1391 | parm = snd_hda_codec_read(codec, nid, 0, |
1393 | codec, nid, 0, | 1392 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
1394 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 1393 | parm &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); |
1395 | parm &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); | 1394 | parm |= out_in; |
1396 | parm |= out_in; | 1395 | snd_hda_codec_write(codec, nid, 0, |
1397 | snd_hda_codec_write(codec, nid, 0, | 1396 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
1398 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 1397 | parm); |
1399 | parm); | 1398 | if (out_in == AC_PINCTL_OUT_EN) { |
1400 | if (out_in == AC_PINCTL_OUT_EN) { | 1399 | mute_aa_path(codec, 1); |
1401 | mute_aa_path(codec, 1); | 1400 | notify_aa_path_ctls(codec); |
1402 | notify_aa_path_ctls(codec); | 1401 | } |
1403 | } | 1402 | if (spec->codec_type == VT1718S) { |
1404 | if (spec->codec_type == VT1718S) | 1403 | snd_hda_codec_amp_stereo( |
1405 | snd_hda_codec_amp_stereo( | ||
1406 | codec, nid, HDA_OUTPUT, 0, HDA_AMP_MUTE, | 1404 | codec, nid, HDA_OUTPUT, 0, HDA_AMP_MUTE, |
1407 | HDA_AMP_UNMUTE); | 1405 | HDA_AMP_UNMUTE); |
1408 | } | 1406 | } |
1409 | if (i == AUTO_PIN_FRONT_MIC) { | 1407 | if (cfg->inputs[i].type == AUTO_PIN_MIC) { |
1410 | if (spec->codec_type == VT1708S | 1408 | if (spec->codec_type == VT1708S |
1411 | || spec->codec_type == VT1716S) { | 1409 | || spec->codec_type == VT1716S) { |
1412 | /* input = index 1 (AOW3) */ | 1410 | /* input = index 1 (AOW3) */ |
@@ -1442,7 +1440,7 @@ static struct snd_kcontrol_new via_smart51_mixer[2] = { | |||
1442 | static int via_smart51_build(struct via_spec *spec) | 1440 | static int via_smart51_build(struct via_spec *spec) |
1443 | { | 1441 | { |
1444 | struct snd_kcontrol_new *knew; | 1442 | struct snd_kcontrol_new *knew; |
1445 | int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE }; | 1443 | const struct auto_pin_cfg *cfg = &spec->autocfg; |
1446 | hda_nid_t nid; | 1444 | hda_nid_t nid; |
1447 | int i; | 1445 | int i; |
1448 | 1446 | ||
@@ -1450,13 +1448,14 @@ static int via_smart51_build(struct via_spec *spec) | |||
1450 | if (knew == NULL) | 1448 | if (knew == NULL) |
1451 | return -ENOMEM; | 1449 | return -ENOMEM; |
1452 | 1450 | ||
1453 | for (i = 0; i < ARRAY_SIZE(index); i++) { | 1451 | for (i = 0; i < cfg->num_inputs; i++) { |
1454 | nid = spec->autocfg.input_pins[index[i]]; | 1452 | nid = cfg->inputs[i].pin; |
1455 | if (nid) { | 1453 | if (cfg->inputs[i].type <= AUTO_PIN_LINE_IN) { |
1456 | knew = via_clone_control(spec, &via_smart51_mixer[1]); | 1454 | knew = via_clone_control(spec, &via_smart51_mixer[1]); |
1457 | if (knew == NULL) | 1455 | if (knew == NULL) |
1458 | return -ENOMEM; | 1456 | return -ENOMEM; |
1459 | knew->subdevice = nid; | 1457 | knew->subdevice = nid; |
1458 | break; | ||
1460 | } | 1459 | } |
1461 | } | 1460 | } |
1462 | 1461 | ||
@@ -2375,13 +2374,8 @@ static void create_hp_imux(struct via_spec *spec) | |||
2375 | static const char *texts[] = { "OFF", "ON", NULL}; | 2374 | static const char *texts[] = { "OFF", "ON", NULL}; |
2376 | 2375 | ||
2377 | /* for hp mode select */ | 2376 | /* for hp mode select */ |
2378 | i = 0; | 2377 | for (i = 0; texts[i]; i++) |
2379 | while (texts[i] != NULL) { | 2378 | snd_hda_add_imux_item(imux, texts[i], i, NULL); |
2380 | imux->items[imux->num_items].label = texts[i]; | ||
2381 | imux->items[imux->num_items].index = i; | ||
2382 | imux->num_items++; | ||
2383 | i++; | ||
2384 | } | ||
2385 | 2379 | ||
2386 | spec->hp_mux = &spec->private_imux[1]; | 2380 | spec->hp_mux = &spec->private_imux[1]; |
2387 | } | 2381 | } |
@@ -2413,51 +2407,53 @@ static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
2413 | } | 2407 | } |
2414 | 2408 | ||
2415 | /* create playback/capture controls for input pins */ | 2409 | /* create playback/capture controls for input pins */ |
2416 | static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec, | 2410 | static int vt_auto_create_analog_input_ctls(struct hda_codec *codec, |
2417 | const struct auto_pin_cfg *cfg) | 2411 | const struct auto_pin_cfg *cfg, |
2412 | hda_nid_t cap_nid, | ||
2413 | hda_nid_t pin_idxs[], int num_idxs) | ||
2418 | { | 2414 | { |
2419 | static char *labels[] = { | 2415 | struct via_spec *spec = codec->spec; |
2420 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | ||
2421 | }; | ||
2422 | struct hda_input_mux *imux = &spec->private_imux[0]; | 2416 | struct hda_input_mux *imux = &spec->private_imux[0]; |
2423 | int i, err, idx = 0; | 2417 | int i, err, idx, type, type_idx = 0; |
2424 | 2418 | ||
2425 | /* for internal loopback recording select */ | 2419 | /* for internal loopback recording select */ |
2426 | imux->items[imux->num_items].label = "Stereo Mixer"; | 2420 | for (idx = 0; idx < num_idxs; idx++) { |
2427 | imux->items[imux->num_items].index = idx; | 2421 | if (pin_idxs[idx] == 0xff) { |
2428 | imux->num_items++; | 2422 | snd_hda_add_imux_item(imux, "Stereo Mixer", idx, NULL); |
2429 | |||
2430 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
2431 | if (!cfg->input_pins[i]) | ||
2432 | continue; | ||
2433 | |||
2434 | switch (cfg->input_pins[i]) { | ||
2435 | case 0x1d: /* Mic */ | ||
2436 | idx = 2; | ||
2437 | break; | ||
2438 | |||
2439 | case 0x1e: /* Line In */ | ||
2440 | idx = 3; | ||
2441 | break; | ||
2442 | |||
2443 | case 0x21: /* Front Mic */ | ||
2444 | idx = 4; | ||
2445 | break; | ||
2446 | |||
2447 | case 0x24: /* CD */ | ||
2448 | idx = 1; | ||
2449 | break; | 2423 | break; |
2450 | } | 2424 | } |
2451 | err = via_new_analog_input(spec, labels[i], idx, 0x17); | 2425 | } |
2426 | |||
2427 | for (i = 0; i < cfg->num_inputs; i++) { | ||
2428 | const char *label; | ||
2429 | type = cfg->inputs[i].type; | ||
2430 | for (idx = 0; idx < num_idxs; idx++) | ||
2431 | if (pin_idxs[idx] == cfg->inputs[i].pin) | ||
2432 | break; | ||
2433 | if (idx >= num_idxs) | ||
2434 | continue; | ||
2435 | if (i > 0 && type == cfg->inputs[i - 1].type) | ||
2436 | type_idx++; | ||
2437 | else | ||
2438 | type_idx = 0; | ||
2439 | label = hda_get_autocfg_input_label(codec, cfg, i); | ||
2440 | err = via_new_analog_input(spec, label, type_idx, idx, cap_nid); | ||
2452 | if (err < 0) | 2441 | if (err < 0) |
2453 | return err; | 2442 | return err; |
2454 | imux->items[imux->num_items].label = labels[i]; | 2443 | snd_hda_add_imux_item(imux, label, idx, NULL); |
2455 | imux->items[imux->num_items].index = idx; | ||
2456 | imux->num_items++; | ||
2457 | } | 2444 | } |
2458 | return 0; | 2445 | return 0; |
2459 | } | 2446 | } |
2460 | 2447 | ||
2448 | /* create playback/capture controls for input pins */ | ||
2449 | static int vt1708_auto_create_analog_input_ctls(struct hda_codec *codec, | ||
2450 | const struct auto_pin_cfg *cfg) | ||
2451 | { | ||
2452 | static hda_nid_t pin_idxs[] = { 0xff, 0x24, 0x1d, 0x1e, 0x21 }; | ||
2453 | return vt_auto_create_analog_input_ctls(codec, cfg, 0x17, pin_idxs, | ||
2454 | ARRAY_SIZE(pin_idxs)); | ||
2455 | } | ||
2456 | |||
2461 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 2457 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
2462 | static struct hda_amp_list vt1708_loopbacks[] = { | 2458 | static struct hda_amp_list vt1708_loopbacks[] = { |
2463 | { 0x17, HDA_INPUT, 1 }, | 2459 | { 0x17, HDA_INPUT, 1 }, |
@@ -2554,7 +2550,7 @@ static int vt1708_parse_auto_config(struct hda_codec *codec) | |||
2554 | err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | 2550 | err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); |
2555 | if (err < 0) | 2551 | if (err < 0) |
2556 | return err; | 2552 | return err; |
2557 | err = vt1708_auto_create_analog_input_ctls(spec, &spec->autocfg); | 2553 | err = vt1708_auto_create_analog_input_ctls(codec, &spec->autocfg); |
2558 | if (err < 0) | 2554 | if (err < 0) |
2559 | return err; | 2555 | return err; |
2560 | /* add jack detect on/off control */ | 2556 | /* add jack detect on/off control */ |
@@ -3021,49 +3017,12 @@ static int vt1709_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
3021 | } | 3017 | } |
3022 | 3018 | ||
3023 | /* create playback/capture controls for input pins */ | 3019 | /* create playback/capture controls for input pins */ |
3024 | static int vt1709_auto_create_analog_input_ctls(struct via_spec *spec, | 3020 | static int vt1709_auto_create_analog_input_ctls(struct hda_codec *codec, |
3025 | const struct auto_pin_cfg *cfg) | 3021 | const struct auto_pin_cfg *cfg) |
3026 | { | 3022 | { |
3027 | static char *labels[] = { | 3023 | static hda_nid_t pin_idxs[] = { 0xff, 0x23, 0x1d, 0x1e, 0x21 }; |
3028 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | 3024 | return vt_auto_create_analog_input_ctls(codec, cfg, 0x18, pin_idxs, |
3029 | }; | 3025 | ARRAY_SIZE(pin_idxs)); |
3030 | struct hda_input_mux *imux = &spec->private_imux[0]; | ||
3031 | int i, err, idx = 0; | ||
3032 | |||
3033 | /* for internal loopback recording select */ | ||
3034 | imux->items[imux->num_items].label = "Stereo Mixer"; | ||
3035 | imux->items[imux->num_items].index = idx; | ||
3036 | imux->num_items++; | ||
3037 | |||
3038 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
3039 | if (!cfg->input_pins[i]) | ||
3040 | continue; | ||
3041 | |||
3042 | switch (cfg->input_pins[i]) { | ||
3043 | case 0x1d: /* Mic */ | ||
3044 | idx = 2; | ||
3045 | break; | ||
3046 | |||
3047 | case 0x1e: /* Line In */ | ||
3048 | idx = 3; | ||
3049 | break; | ||
3050 | |||
3051 | case 0x21: /* Front Mic */ | ||
3052 | idx = 4; | ||
3053 | break; | ||
3054 | |||
3055 | case 0x23: /* CD */ | ||
3056 | idx = 1; | ||
3057 | break; | ||
3058 | } | ||
3059 | err = via_new_analog_input(spec, labels[i], idx, 0x18); | ||
3060 | if (err < 0) | ||
3061 | return err; | ||
3062 | imux->items[imux->num_items].label = labels[i]; | ||
3063 | imux->items[imux->num_items].index = idx; | ||
3064 | imux->num_items++; | ||
3065 | } | ||
3066 | return 0; | ||
3067 | } | 3026 | } |
3068 | 3027 | ||
3069 | static int vt1709_parse_auto_config(struct hda_codec *codec) | 3028 | static int vt1709_parse_auto_config(struct hda_codec *codec) |
@@ -3086,7 +3045,7 @@ static int vt1709_parse_auto_config(struct hda_codec *codec) | |||
3086 | err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | 3045 | err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); |
3087 | if (err < 0) | 3046 | if (err < 0) |
3088 | return err; | 3047 | return err; |
3089 | err = vt1709_auto_create_analog_input_ctls(spec, &spec->autocfg); | 3048 | err = vt1709_auto_create_analog_input_ctls(codec, &spec->autocfg); |
3090 | if (err < 0) | 3049 | if (err < 0) |
3091 | return err; | 3050 | return err; |
3092 | 3051 | ||
@@ -3588,49 +3547,12 @@ static int vt1708B_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
3588 | } | 3547 | } |
3589 | 3548 | ||
3590 | /* create playback/capture controls for input pins */ | 3549 | /* create playback/capture controls for input pins */ |
3591 | static int vt1708B_auto_create_analog_input_ctls(struct via_spec *spec, | 3550 | static int vt1708B_auto_create_analog_input_ctls(struct hda_codec *codec, |
3592 | const struct auto_pin_cfg *cfg) | 3551 | const struct auto_pin_cfg *cfg) |
3593 | { | 3552 | { |
3594 | static char *labels[] = { | 3553 | static hda_nid_t pin_idxs[] = { 0xff, 0x1f, 0x1a, 0x1b, 0x1e }; |
3595 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | 3554 | return vt_auto_create_analog_input_ctls(codec, cfg, 0x16, pin_idxs, |
3596 | }; | 3555 | ARRAY_SIZE(pin_idxs)); |
3597 | struct hda_input_mux *imux = &spec->private_imux[0]; | ||
3598 | int i, err, idx = 0; | ||
3599 | |||
3600 | /* for internal loopback recording select */ | ||
3601 | imux->items[imux->num_items].label = "Stereo Mixer"; | ||
3602 | imux->items[imux->num_items].index = idx; | ||
3603 | imux->num_items++; | ||
3604 | |||
3605 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
3606 | if (!cfg->input_pins[i]) | ||
3607 | continue; | ||
3608 | |||
3609 | switch (cfg->input_pins[i]) { | ||
3610 | case 0x1a: /* Mic */ | ||
3611 | idx = 2; | ||
3612 | break; | ||
3613 | |||
3614 | case 0x1b: /* Line In */ | ||
3615 | idx = 3; | ||
3616 | break; | ||
3617 | |||
3618 | case 0x1e: /* Front Mic */ | ||
3619 | idx = 4; | ||
3620 | break; | ||
3621 | |||
3622 | case 0x1f: /* CD */ | ||
3623 | idx = 1; | ||
3624 | break; | ||
3625 | } | ||
3626 | err = via_new_analog_input(spec, labels[i], idx, 0x16); | ||
3627 | if (err < 0) | ||
3628 | return err; | ||
3629 | imux->items[imux->num_items].label = labels[i]; | ||
3630 | imux->items[imux->num_items].index = idx; | ||
3631 | imux->num_items++; | ||
3632 | } | ||
3633 | return 0; | ||
3634 | } | 3556 | } |
3635 | 3557 | ||
3636 | static int vt1708B_parse_auto_config(struct hda_codec *codec) | 3558 | static int vt1708B_parse_auto_config(struct hda_codec *codec) |
@@ -3653,7 +3575,7 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec) | |||
3653 | err = vt1708B_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | 3575 | err = vt1708B_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); |
3654 | if (err < 0) | 3576 | if (err < 0) |
3655 | return err; | 3577 | return err; |
3656 | err = vt1708B_auto_create_analog_input_ctls(spec, &spec->autocfg); | 3578 | err = vt1708B_auto_create_analog_input_ctls(codec, &spec->autocfg); |
3657 | if (err < 0) | 3579 | if (err < 0) |
3658 | return err; | 3580 | return err; |
3659 | 3581 | ||
@@ -4061,49 +3983,12 @@ static int vt1708S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
4061 | } | 3983 | } |
4062 | 3984 | ||
4063 | /* create playback/capture controls for input pins */ | 3985 | /* create playback/capture controls for input pins */ |
4064 | static int vt1708S_auto_create_analog_input_ctls(struct via_spec *spec, | 3986 | static int vt1708S_auto_create_analog_input_ctls(struct hda_codec *codec, |
4065 | const struct auto_pin_cfg *cfg) | 3987 | const struct auto_pin_cfg *cfg) |
4066 | { | 3988 | { |
4067 | static char *labels[] = { | 3989 | static hda_nid_t pin_idxs[] = { 0x1f, 0x1a, 0x1b, 0x1e, 0, 0xff }; |
4068 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | 3990 | return vt_auto_create_analog_input_ctls(codec, cfg, 0x16, pin_idxs, |
4069 | }; | 3991 | ARRAY_SIZE(pin_idxs)); |
4070 | struct hda_input_mux *imux = &spec->private_imux[0]; | ||
4071 | int i, err, idx = 0; | ||
4072 | |||
4073 | /* for internal loopback recording select */ | ||
4074 | imux->items[imux->num_items].label = "Stereo Mixer"; | ||
4075 | imux->items[imux->num_items].index = 5; | ||
4076 | imux->num_items++; | ||
4077 | |||
4078 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
4079 | if (!cfg->input_pins[i]) | ||
4080 | continue; | ||
4081 | |||
4082 | switch (cfg->input_pins[i]) { | ||
4083 | case 0x1a: /* Mic */ | ||
4084 | idx = 2; | ||
4085 | break; | ||
4086 | |||
4087 | case 0x1b: /* Line In */ | ||
4088 | idx = 3; | ||
4089 | break; | ||
4090 | |||
4091 | case 0x1e: /* Front Mic */ | ||
4092 | idx = 4; | ||
4093 | break; | ||
4094 | |||
4095 | case 0x1f: /* CD */ | ||
4096 | idx = 1; | ||
4097 | break; | ||
4098 | } | ||
4099 | err = via_new_analog_input(spec, labels[i], idx, 0x16); | ||
4100 | if (err < 0) | ||
4101 | return err; | ||
4102 | imux->items[imux->num_items].label = labels[i]; | ||
4103 | imux->items[imux->num_items].index = idx-1; | ||
4104 | imux->num_items++; | ||
4105 | } | ||
4106 | return 0; | ||
4107 | } | 3992 | } |
4108 | 3993 | ||
4109 | /* fill out digital output widgets; one for master and one for slave outputs */ | 3994 | /* fill out digital output widgets; one for master and one for slave outputs */ |
@@ -4151,7 +4036,7 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec) | |||
4151 | err = vt1708S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | 4036 | err = vt1708S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); |
4152 | if (err < 0) | 4037 | if (err < 0) |
4153 | return err; | 4038 | return err; |
4154 | err = vt1708S_auto_create_analog_input_ctls(spec, &spec->autocfg); | 4039 | err = vt1708S_auto_create_analog_input_ctls(codec, &spec->autocfg); |
4155 | if (err < 0) | 4040 | if (err < 0) |
4156 | return err; | 4041 | return err; |
4157 | 4042 | ||
@@ -4441,58 +4326,20 @@ static int vt1702_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
4441 | imux = &spec->private_imux[1]; | 4326 | imux = &spec->private_imux[1]; |
4442 | 4327 | ||
4443 | /* for hp mode select */ | 4328 | /* for hp mode select */ |
4444 | i = 0; | 4329 | for (i = 0; texts[i]; i++) |
4445 | while (texts[i] != NULL) { | 4330 | snd_hda_add_imux_item(imux, texts[i], i, NULL); |
4446 | imux->items[imux->num_items].label = texts[i]; | ||
4447 | imux->items[imux->num_items].index = i; | ||
4448 | imux->num_items++; | ||
4449 | i++; | ||
4450 | } | ||
4451 | 4331 | ||
4452 | spec->hp_mux = &spec->private_imux[1]; | 4332 | spec->hp_mux = &spec->private_imux[1]; |
4453 | return 0; | 4333 | return 0; |
4454 | } | 4334 | } |
4455 | 4335 | ||
4456 | /* create playback/capture controls for input pins */ | 4336 | /* create playback/capture controls for input pins */ |
4457 | static int vt1702_auto_create_analog_input_ctls(struct via_spec *spec, | 4337 | static int vt1702_auto_create_analog_input_ctls(struct hda_codec *codec, |
4458 | const struct auto_pin_cfg *cfg) | 4338 | const struct auto_pin_cfg *cfg) |
4459 | { | 4339 | { |
4460 | static char *labels[] = { | 4340 | static hda_nid_t pin_idxs[] = { 0x14, 0x15, 0x18, 0xff }; |
4461 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | 4341 | return vt_auto_create_analog_input_ctls(codec, cfg, 0x1a, pin_idxs, |
4462 | }; | 4342 | ARRAY_SIZE(pin_idxs)); |
4463 | struct hda_input_mux *imux = &spec->private_imux[0]; | ||
4464 | int i, err, idx = 0; | ||
4465 | |||
4466 | /* for internal loopback recording select */ | ||
4467 | imux->items[imux->num_items].label = "Stereo Mixer"; | ||
4468 | imux->items[imux->num_items].index = 3; | ||
4469 | imux->num_items++; | ||
4470 | |||
4471 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
4472 | if (!cfg->input_pins[i]) | ||
4473 | continue; | ||
4474 | |||
4475 | switch (cfg->input_pins[i]) { | ||
4476 | case 0x14: /* Mic */ | ||
4477 | idx = 1; | ||
4478 | break; | ||
4479 | |||
4480 | case 0x15: /* Line In */ | ||
4481 | idx = 2; | ||
4482 | break; | ||
4483 | |||
4484 | case 0x18: /* Front Mic */ | ||
4485 | idx = 3; | ||
4486 | break; | ||
4487 | } | ||
4488 | err = via_new_analog_input(spec, labels[i], idx, 0x1A); | ||
4489 | if (err < 0) | ||
4490 | return err; | ||
4491 | imux->items[imux->num_items].label = labels[i]; | ||
4492 | imux->items[imux->num_items].index = idx-1; | ||
4493 | imux->num_items++; | ||
4494 | } | ||
4495 | return 0; | ||
4496 | } | 4343 | } |
4497 | 4344 | ||
4498 | static int vt1702_parse_auto_config(struct hda_codec *codec) | 4345 | static int vt1702_parse_auto_config(struct hda_codec *codec) |
@@ -4521,7 +4368,7 @@ static int vt1702_parse_auto_config(struct hda_codec *codec) | |||
4521 | (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | | 4368 | (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | |
4522 | (0x5 << AC_AMPCAP_STEP_SIZE_SHIFT) | | 4369 | (0x5 << AC_AMPCAP_STEP_SIZE_SHIFT) | |
4523 | (1 << AC_AMPCAP_MUTE_SHIFT)); | 4370 | (1 << AC_AMPCAP_MUTE_SHIFT)); |
4524 | err = vt1702_auto_create_analog_input_ctls(spec, &spec->autocfg); | 4371 | err = vt1702_auto_create_analog_input_ctls(codec, &spec->autocfg); |
4525 | if (err < 0) | 4372 | if (err < 0) |
4526 | return err; | 4373 | return err; |
4527 | 4374 | ||
@@ -4872,49 +4719,12 @@ static int vt1718S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
4872 | } | 4719 | } |
4873 | 4720 | ||
4874 | /* create playback/capture controls for input pins */ | 4721 | /* create playback/capture controls for input pins */ |
4875 | static int vt1718S_auto_create_analog_input_ctls(struct via_spec *spec, | 4722 | static int vt1718S_auto_create_analog_input_ctls(struct hda_codec *codec, |
4876 | const struct auto_pin_cfg *cfg) | 4723 | const struct auto_pin_cfg *cfg) |
4877 | { | 4724 | { |
4878 | static char *labels[] = { | 4725 | static hda_nid_t pin_idxs[] = { 0x2c, 0x2b, 0x2a, 0x29, 0, 0xff }; |
4879 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | 4726 | return vt_auto_create_analog_input_ctls(codec, cfg, 0x21, pin_idxs, |
4880 | }; | 4727 | ARRAY_SIZE(pin_idxs)); |
4881 | struct hda_input_mux *imux = &spec->private_imux[0]; | ||
4882 | int i, err, idx = 0; | ||
4883 | |||
4884 | /* for internal loopback recording select */ | ||
4885 | imux->items[imux->num_items].label = "Stereo Mixer"; | ||
4886 | imux->items[imux->num_items].index = 5; | ||
4887 | imux->num_items++; | ||
4888 | |||
4889 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
4890 | if (!cfg->input_pins[i]) | ||
4891 | continue; | ||
4892 | |||
4893 | switch (cfg->input_pins[i]) { | ||
4894 | case 0x2b: /* Mic */ | ||
4895 | idx = 1; | ||
4896 | break; | ||
4897 | |||
4898 | case 0x2a: /* Line In */ | ||
4899 | idx = 2; | ||
4900 | break; | ||
4901 | |||
4902 | case 0x29: /* Front Mic */ | ||
4903 | idx = 3; | ||
4904 | break; | ||
4905 | |||
4906 | case 0x2c: /* CD */ | ||
4907 | idx = 0; | ||
4908 | break; | ||
4909 | } | ||
4910 | err = via_new_analog_input(spec, labels[i], idx, 0x21); | ||
4911 | if (err < 0) | ||
4912 | return err; | ||
4913 | imux->items[imux->num_items].label = labels[i]; | ||
4914 | imux->items[imux->num_items].index = idx; | ||
4915 | imux->num_items++; | ||
4916 | } | ||
4917 | return 0; | ||
4918 | } | 4728 | } |
4919 | 4729 | ||
4920 | static int vt1718S_parse_auto_config(struct hda_codec *codec) | 4730 | static int vt1718S_parse_auto_config(struct hda_codec *codec) |
@@ -4938,7 +4748,7 @@ static int vt1718S_parse_auto_config(struct hda_codec *codec) | |||
4938 | err = vt1718S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | 4748 | err = vt1718S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); |
4939 | if (err < 0) | 4749 | if (err < 0) |
4940 | return err; | 4750 | return err; |
4941 | err = vt1718S_auto_create_analog_input_ctls(spec, &spec->autocfg); | 4751 | err = vt1718S_auto_create_analog_input_ctls(codec, &spec->autocfg); |
4942 | if (err < 0) | 4752 | if (err < 0) |
4943 | return err; | 4753 | return err; |
4944 | 4754 | ||
@@ -5371,49 +5181,12 @@ static int vt1716S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
5371 | } | 5181 | } |
5372 | 5182 | ||
5373 | /* create playback/capture controls for input pins */ | 5183 | /* create playback/capture controls for input pins */ |
5374 | static int vt1716S_auto_create_analog_input_ctls(struct via_spec *spec, | 5184 | static int vt1716S_auto_create_analog_input_ctls(struct hda_codec *codec, |
5375 | const struct auto_pin_cfg *cfg) | 5185 | const struct auto_pin_cfg *cfg) |
5376 | { | 5186 | { |
5377 | static char *labels[] = { | 5187 | static hda_nid_t pin_idxs[] = { 0x1f, 0x1a, 0x1b, 0x1e, 0, 0xff }; |
5378 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | 5188 | return vt_auto_create_analog_input_ctls(codec, cfg, 0x16, pin_idxs, |
5379 | }; | 5189 | ARRAY_SIZE(pin_idxs)); |
5380 | struct hda_input_mux *imux = &spec->private_imux[0]; | ||
5381 | int i, err, idx = 0; | ||
5382 | |||
5383 | /* for internal loopback recording select */ | ||
5384 | imux->items[imux->num_items].label = "Stereo Mixer"; | ||
5385 | imux->items[imux->num_items].index = 5; | ||
5386 | imux->num_items++; | ||
5387 | |||
5388 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
5389 | if (!cfg->input_pins[i]) | ||
5390 | continue; | ||
5391 | |||
5392 | switch (cfg->input_pins[i]) { | ||
5393 | case 0x1a: /* Mic */ | ||
5394 | idx = 2; | ||
5395 | break; | ||
5396 | |||
5397 | case 0x1b: /* Line In */ | ||
5398 | idx = 3; | ||
5399 | break; | ||
5400 | |||
5401 | case 0x1e: /* Front Mic */ | ||
5402 | idx = 4; | ||
5403 | break; | ||
5404 | |||
5405 | case 0x1f: /* CD */ | ||
5406 | idx = 1; | ||
5407 | break; | ||
5408 | } | ||
5409 | err = via_new_analog_input(spec, labels[i], idx, 0x16); | ||
5410 | if (err < 0) | ||
5411 | return err; | ||
5412 | imux->items[imux->num_items].label = labels[i]; | ||
5413 | imux->items[imux->num_items].index = idx-1; | ||
5414 | imux->num_items++; | ||
5415 | } | ||
5416 | return 0; | ||
5417 | } | 5190 | } |
5418 | 5191 | ||
5419 | static int vt1716S_parse_auto_config(struct hda_codec *codec) | 5192 | static int vt1716S_parse_auto_config(struct hda_codec *codec) |
@@ -5436,7 +5209,7 @@ static int vt1716S_parse_auto_config(struct hda_codec *codec) | |||
5436 | err = vt1716S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | 5209 | err = vt1716S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); |
5437 | if (err < 0) | 5210 | if (err < 0) |
5438 | return err; | 5211 | return err; |
5439 | err = vt1716S_auto_create_analog_input_ctls(spec, &spec->autocfg); | 5212 | err = vt1716S_auto_create_analog_input_ctls(codec, &spec->autocfg); |
5440 | if (err < 0) | 5213 | if (err < 0) |
5441 | return err; | 5214 | return err; |
5442 | 5215 | ||
@@ -5717,54 +5490,25 @@ static int vt2002P_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
5717 | } | 5490 | } |
5718 | 5491 | ||
5719 | /* create playback/capture controls for input pins */ | 5492 | /* create playback/capture controls for input pins */ |
5720 | static int vt2002P_auto_create_analog_input_ctls(struct via_spec *spec, | 5493 | static int vt2002P_auto_create_analog_input_ctls(struct hda_codec *codec, |
5721 | const struct auto_pin_cfg *cfg) | 5494 | const struct auto_pin_cfg *cfg) |
5722 | { | 5495 | { |
5723 | static char *labels[] = { | 5496 | struct via_spec *spec = codec->spec; |
5724 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | ||
5725 | }; | ||
5726 | struct hda_input_mux *imux = &spec->private_imux[0]; | 5497 | struct hda_input_mux *imux = &spec->private_imux[0]; |
5727 | int i, err, idx = 0; | 5498 | static hda_nid_t pin_idxs[] = { 0x2b, 0x2a, 0x29, 0xff }; |
5728 | 5499 | int err; | |
5729 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
5730 | if (!cfg->input_pins[i]) | ||
5731 | continue; | ||
5732 | |||
5733 | switch (cfg->input_pins[i]) { | ||
5734 | case 0x2b: /* Mic */ | ||
5735 | idx = 0; | ||
5736 | break; | ||
5737 | |||
5738 | case 0x2a: /* Line In */ | ||
5739 | idx = 1; | ||
5740 | break; | ||
5741 | |||
5742 | case 0x29: /* Front Mic */ | ||
5743 | idx = 2; | ||
5744 | break; | ||
5745 | } | ||
5746 | err = via_new_analog_input(spec, labels[i], idx, 0x21); | ||
5747 | if (err < 0) | ||
5748 | return err; | ||
5749 | imux->items[imux->num_items].label = labels[i]; | ||
5750 | imux->items[imux->num_items].index = idx; | ||
5751 | imux->num_items++; | ||
5752 | } | ||
5753 | 5500 | ||
5501 | err = vt_auto_create_analog_input_ctls(codec, cfg, 0x21, pin_idxs, | ||
5502 | ARRAY_SIZE(pin_idxs)); | ||
5503 | if (err < 0) | ||
5504 | return err; | ||
5754 | /* build volume/mute control of loopback */ | 5505 | /* build volume/mute control of loopback */ |
5755 | err = via_new_analog_input(spec, "Stereo Mixer", 3, 0x21); | 5506 | err = via_new_analog_input(spec, "Stereo Mixer", 0, 3, 0x21); |
5756 | if (err < 0) | 5507 | if (err < 0) |
5757 | return err; | 5508 | return err; |
5758 | 5509 | ||
5759 | /* for internal loopback recording select */ | ||
5760 | imux->items[imux->num_items].label = "Stereo Mixer"; | ||
5761 | imux->items[imux->num_items].index = 3; | ||
5762 | imux->num_items++; | ||
5763 | |||
5764 | /* for digital mic select */ | 5510 | /* for digital mic select */ |
5765 | imux->items[imux->num_items].label = "Digital Mic"; | 5511 | snd_hda_add_imux_item(imux, "Digital Mic", 4, NULL); |
5766 | imux->items[imux->num_items].index = 4; | ||
5767 | imux->num_items++; | ||
5768 | 5512 | ||
5769 | return 0; | 5513 | return 0; |
5770 | } | 5514 | } |
@@ -5792,7 +5536,7 @@ static int vt2002P_parse_auto_config(struct hda_codec *codec) | |||
5792 | err = vt2002P_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | 5536 | err = vt2002P_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); |
5793 | if (err < 0) | 5537 | if (err < 0) |
5794 | return err; | 5538 | return err; |
5795 | err = vt2002P_auto_create_analog_input_ctls(spec, &spec->autocfg); | 5539 | err = vt2002P_auto_create_analog_input_ctls(codec, &spec->autocfg); |
5796 | if (err < 0) | 5540 | if (err < 0) |
5797 | return err; | 5541 | return err; |
5798 | 5542 | ||
@@ -6067,53 +5811,26 @@ static int vt1812_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
6067 | } | 5811 | } |
6068 | 5812 | ||
6069 | /* create playback/capture controls for input pins */ | 5813 | /* create playback/capture controls for input pins */ |
6070 | static int vt1812_auto_create_analog_input_ctls(struct via_spec *spec, | 5814 | static int vt1812_auto_create_analog_input_ctls(struct hda_codec *codec, |
6071 | const struct auto_pin_cfg *cfg) | 5815 | const struct auto_pin_cfg *cfg) |
6072 | { | 5816 | { |
6073 | static char *labels[] = { | 5817 | struct via_spec *spec = codec->spec; |
6074 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | ||
6075 | }; | ||
6076 | struct hda_input_mux *imux = &spec->private_imux[0]; | 5818 | struct hda_input_mux *imux = &spec->private_imux[0]; |
6077 | int i, err, idx = 0; | 5819 | static hda_nid_t pin_idxs[] = { 0x2b, 0x2a, 0x29, 0, 0, 0xff }; |
6078 | 5820 | int err; | |
6079 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
6080 | if (!cfg->input_pins[i]) | ||
6081 | continue; | ||
6082 | |||
6083 | switch (cfg->input_pins[i]) { | ||
6084 | case 0x2b: /* Mic */ | ||
6085 | idx = 0; | ||
6086 | break; | ||
6087 | 5821 | ||
6088 | case 0x2a: /* Line In */ | 5822 | err = vt_auto_create_analog_input_ctls(codec, cfg, 0x21, pin_idxs, |
6089 | idx = 1; | 5823 | ARRAY_SIZE(pin_idxs)); |
6090 | break; | 5824 | if (err < 0) |
5825 | return err; | ||
6091 | 5826 | ||
6092 | case 0x29: /* Front Mic */ | ||
6093 | idx = 2; | ||
6094 | break; | ||
6095 | } | ||
6096 | err = via_new_analog_input(spec, labels[i], idx, 0x21); | ||
6097 | if (err < 0) | ||
6098 | return err; | ||
6099 | imux->items[imux->num_items].label = labels[i]; | ||
6100 | imux->items[imux->num_items].index = idx; | ||
6101 | imux->num_items++; | ||
6102 | } | ||
6103 | /* build volume/mute control of loopback */ | 5827 | /* build volume/mute control of loopback */ |
6104 | err = via_new_analog_input(spec, "Stereo Mixer", 5, 0x21); | 5828 | err = via_new_analog_input(spec, "Stereo Mixer", 0, 5, 0x21); |
6105 | if (err < 0) | 5829 | if (err < 0) |
6106 | return err; | 5830 | return err; |
6107 | 5831 | ||
6108 | /* for internal loopback recording select */ | ||
6109 | imux->items[imux->num_items].label = "Stereo Mixer"; | ||
6110 | imux->items[imux->num_items].index = 5; | ||
6111 | imux->num_items++; | ||
6112 | |||
6113 | /* for digital mic select */ | 5832 | /* for digital mic select */ |
6114 | imux->items[imux->num_items].label = "Digital Mic"; | 5833 | snd_hda_add_imux_item(imux, "Digital Mic", 6, NULL); |
6115 | imux->items[imux->num_items].index = 6; | ||
6116 | imux->num_items++; | ||
6117 | 5834 | ||
6118 | return 0; | 5835 | return 0; |
6119 | } | 5836 | } |
@@ -6141,7 +5858,7 @@ static int vt1812_parse_auto_config(struct hda_codec *codec) | |||
6141 | err = vt1812_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | 5858 | err = vt1812_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); |
6142 | if (err < 0) | 5859 | if (err < 0) |
6143 | return err; | 5860 | return err; |
6144 | err = vt1812_auto_create_analog_input_ctls(spec, &spec->autocfg); | 5861 | err = vt1812_auto_create_analog_input_ctls(codec, &spec->autocfg); |
6145 | if (err < 0) | 5862 | if (err < 0) |
6146 | return err; | 5863 | return err; |
6147 | 5864 | ||
diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c index d216362626d0..712c1710f9a2 100644 --- a/sound/pci/ice1712/delta.c +++ b/sound/pci/ice1712/delta.c | |||
@@ -563,6 +563,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice) | |||
563 | case ICE1712_SUBDEVICE_DELTA1010E: | 563 | case ICE1712_SUBDEVICE_DELTA1010E: |
564 | case ICE1712_SUBDEVICE_DELTA1010LT: | 564 | case ICE1712_SUBDEVICE_DELTA1010LT: |
565 | case ICE1712_SUBDEVICE_MEDIASTATION: | 565 | case ICE1712_SUBDEVICE_MEDIASTATION: |
566 | case ICE1712_SUBDEVICE_EDIROLDA2496: | ||
566 | ice->num_total_dacs = 8; | 567 | ice->num_total_dacs = 8; |
567 | ice->num_total_adcs = 8; | 568 | ice->num_total_adcs = 8; |
568 | break; | 569 | break; |
@@ -635,6 +636,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice) | |||
635 | err = snd_ice1712_akm4xxx_init(ak, &akm_delta410, &akm_delta410_priv, ice); | 636 | err = snd_ice1712_akm4xxx_init(ak, &akm_delta410, &akm_delta410_priv, ice); |
636 | break; | 637 | break; |
637 | case ICE1712_SUBDEVICE_DELTA1010LT: | 638 | case ICE1712_SUBDEVICE_DELTA1010LT: |
639 | case ICE1712_SUBDEVICE_EDIROLDA2496: | ||
638 | err = snd_ice1712_akm4xxx_init(ak, &akm_delta1010lt, &akm_delta1010lt_priv, ice); | 640 | err = snd_ice1712_akm4xxx_init(ak, &akm_delta1010lt, &akm_delta1010lt_priv, ice); |
639 | break; | 641 | break; |
640 | case ICE1712_SUBDEVICE_DELTA66: | 642 | case ICE1712_SUBDEVICE_DELTA66: |
@@ -734,6 +736,7 @@ static int __devinit snd_ice1712_delta_add_controls(struct snd_ice1712 *ice) | |||
734 | case ICE1712_SUBDEVICE_DELTA66: | 736 | case ICE1712_SUBDEVICE_DELTA66: |
735 | case ICE1712_SUBDEVICE_VX442: | 737 | case ICE1712_SUBDEVICE_VX442: |
736 | case ICE1712_SUBDEVICE_DELTA66E: | 738 | case ICE1712_SUBDEVICE_DELTA66E: |
739 | case ICE1712_SUBDEVICE_EDIROLDA2496: | ||
737 | err = snd_ice1712_akm4xxx_build_controls(ice); | 740 | err = snd_ice1712_akm4xxx_build_controls(ice); |
738 | if (err < 0) | 741 | if (err < 0) |
739 | return err; | 742 | return err; |
@@ -813,5 +816,12 @@ struct snd_ice1712_card_info snd_ice1712_delta_cards[] __devinitdata = { | |||
813 | .chip_init = snd_ice1712_delta_init, | 816 | .chip_init = snd_ice1712_delta_init, |
814 | .build_controls = snd_ice1712_delta_add_controls, | 817 | .build_controls = snd_ice1712_delta_add_controls, |
815 | }, | 818 | }, |
819 | { | ||
820 | .subvendor = ICE1712_SUBDEVICE_EDIROLDA2496, | ||
821 | .name = "Edirol DA2496", | ||
822 | .model = "da2496", | ||
823 | .chip_init = snd_ice1712_delta_init, | ||
824 | .build_controls = snd_ice1712_delta_add_controls, | ||
825 | }, | ||
816 | { } /* terminator */ | 826 | { } /* terminator */ |
817 | }; | 827 | }; |
diff --git a/sound/pci/ice1712/delta.h b/sound/pci/ice1712/delta.h index f7f14df81f26..1a0ac6cd6501 100644 --- a/sound/pci/ice1712/delta.h +++ b/sound/pci/ice1712/delta.h | |||
@@ -34,7 +34,8 @@ | |||
34 | "{MidiMan M Audio,Delta 410},"\ | 34 | "{MidiMan M Audio,Delta 410},"\ |
35 | "{MidiMan M Audio,Audiophile 24/96},"\ | 35 | "{MidiMan M Audio,Audiophile 24/96},"\ |
36 | "{Digigram,VX442},"\ | 36 | "{Digigram,VX442},"\ |
37 | "{Lionstracs,Mediastation}," | 37 | "{Lionstracs,Mediastation},"\ |
38 | "{Edirol,DA2496}," | ||
38 | 39 | ||
39 | #define ICE1712_SUBDEVICE_DELTA1010 0x121430d6 | 40 | #define ICE1712_SUBDEVICE_DELTA1010 0x121430d6 |
40 | #define ICE1712_SUBDEVICE_DELTA1010E 0xff1430d6 | 41 | #define ICE1712_SUBDEVICE_DELTA1010E 0xff1430d6 |
@@ -47,6 +48,7 @@ | |||
47 | #define ICE1712_SUBDEVICE_DELTA1010LT 0x12143bd6 | 48 | #define ICE1712_SUBDEVICE_DELTA1010LT 0x12143bd6 |
48 | #define ICE1712_SUBDEVICE_VX442 0x12143cd6 | 49 | #define ICE1712_SUBDEVICE_VX442 0x12143cd6 |
49 | #define ICE1712_SUBDEVICE_MEDIASTATION 0x694c0100 | 50 | #define ICE1712_SUBDEVICE_MEDIASTATION 0x694c0100 |
51 | #define ICE1712_SUBDEVICE_EDIROLDA2496 0xce164010 | ||
50 | 52 | ||
51 | /* entry point */ | 53 | /* entry point */ |
52 | extern struct snd_ice1712_card_info snd_ice1712_delta_cards[]; | 54 | extern struct snd_ice1712_card_info snd_ice1712_delta_cards[]; |
diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c index 6bc3f91b7281..cdb873f5da50 100644 --- a/sound/pci/ice1712/pontis.c +++ b/sound/pci/ice1712/pontis.c | |||
@@ -638,7 +638,7 @@ static struct snd_kcontrol_new pontis_controls[] __devinitdata = { | |||
638 | */ | 638 | */ |
639 | static void wm_proc_regs_write(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | 639 | static void wm_proc_regs_write(struct snd_info_entry *entry, struct snd_info_buffer *buffer) |
640 | { | 640 | { |
641 | struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data; | 641 | struct snd_ice1712 *ice = entry->private_data; |
642 | char line[64]; | 642 | char line[64]; |
643 | unsigned int reg, val; | 643 | unsigned int reg, val; |
644 | mutex_lock(&ice->gpio_mutex); | 644 | mutex_lock(&ice->gpio_mutex); |
@@ -653,7 +653,7 @@ static void wm_proc_regs_write(struct snd_info_entry *entry, struct snd_info_buf | |||
653 | 653 | ||
654 | static void wm_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | 654 | static void wm_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) |
655 | { | 655 | { |
656 | struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data; | 656 | struct snd_ice1712 *ice = entry->private_data; |
657 | int reg, val; | 657 | int reg, val; |
658 | 658 | ||
659 | mutex_lock(&ice->gpio_mutex); | 659 | mutex_lock(&ice->gpio_mutex); |
@@ -676,7 +676,7 @@ static void wm_proc_init(struct snd_ice1712 *ice) | |||
676 | 676 | ||
677 | static void cs_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | 677 | static void cs_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) |
678 | { | 678 | { |
679 | struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data; | 679 | struct snd_ice1712 *ice = entry->private_data; |
680 | int reg, val; | 680 | int reg, val; |
681 | 681 | ||
682 | mutex_lock(&ice->gpio_mutex); | 682 | mutex_lock(&ice->gpio_mutex); |
diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c index 2a8e5cd8f2d8..e36ddb94c382 100644 --- a/sound/pci/ice1712/prodigy192.c +++ b/sound/pci/ice1712/prodigy192.c | |||
@@ -654,7 +654,7 @@ static int prodigy192_ak4114_init(struct snd_ice1712 *ice) | |||
654 | static void stac9460_proc_regs_read(struct snd_info_entry *entry, | 654 | static void stac9460_proc_regs_read(struct snd_info_entry *entry, |
655 | struct snd_info_buffer *buffer) | 655 | struct snd_info_buffer *buffer) |
656 | { | 656 | { |
657 | struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data; | 657 | struct snd_ice1712 *ice = entry->private_data; |
658 | int reg, val; | 658 | int reg, val; |
659 | /* registers 0x0 - 0x14 */ | 659 | /* registers 0x0 - 0x14 */ |
660 | for (reg = 0; reg <= 0x15; reg++) { | 660 | for (reg = 0; reg <= 0x15; reg++) { |
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c index 6c0a11adb2a8..98a8eb3c92f7 100644 --- a/sound/pci/oxygen/oxygen.c +++ b/sound/pci/oxygen/oxygen.c | |||
@@ -79,6 +79,7 @@ static DEFINE_PCI_DEVICE_TABLE(oxygen_ids) = { | |||
79 | { OXYGEN_PCI_SUBID(0x13f6, 0x0001), .driver_data = MODEL_CMEDIA_REF }, | 79 | { OXYGEN_PCI_SUBID(0x13f6, 0x0001), .driver_data = MODEL_CMEDIA_REF }, |
80 | { OXYGEN_PCI_SUBID(0x13f6, 0x0010), .driver_data = MODEL_CMEDIA_REF }, | 80 | { OXYGEN_PCI_SUBID(0x13f6, 0x0010), .driver_data = MODEL_CMEDIA_REF }, |
81 | { OXYGEN_PCI_SUBID(0x13f6, 0x8788), .driver_data = MODEL_CMEDIA_REF }, | 81 | { OXYGEN_PCI_SUBID(0x13f6, 0x8788), .driver_data = MODEL_CMEDIA_REF }, |
82 | { OXYGEN_PCI_SUBID(0x13f6, 0xffff), .driver_data = MODEL_CMEDIA_REF }, | ||
82 | { OXYGEN_PCI_SUBID(0x147a, 0xa017), .driver_data = MODEL_CMEDIA_REF }, | 83 | { OXYGEN_PCI_SUBID(0x147a, 0xa017), .driver_data = MODEL_CMEDIA_REF }, |
83 | { OXYGEN_PCI_SUBID(0x1a58, 0x0910), .driver_data = MODEL_CMEDIA_REF }, | 84 | { OXYGEN_PCI_SUBID(0x1a58, 0x0910), .driver_data = MODEL_CMEDIA_REF }, |
84 | { OXYGEN_PCI_SUBID(0x415a, 0x5431), .driver_data = MODEL_MERIDIAN }, | 85 | { OXYGEN_PCI_SUBID(0x415a, 0x5431), .driver_data = MODEL_MERIDIAN }, |
@@ -505,7 +506,8 @@ static const struct oxygen_model model_generic = { | |||
505 | PLAYBACK_2_TO_AC97_1 | | 506 | PLAYBACK_2_TO_AC97_1 | |
506 | CAPTURE_0_FROM_I2S_1 | | 507 | CAPTURE_0_FROM_I2S_1 | |
507 | CAPTURE_1_FROM_SPDIF | | 508 | CAPTURE_1_FROM_SPDIF | |
508 | CAPTURE_2_FROM_AC97_1, | 509 | CAPTURE_2_FROM_AC97_1 | |
510 | AC97_CD_INPUT, | ||
509 | .dac_channels = 8, | 511 | .dac_channels = 8, |
510 | .dac_volume_min = 0, | 512 | .dac_volume_min = 0, |
511 | .dac_volume_max = 255, | 513 | .dac_volume_max = 255, |
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h index a3409edcfb50..7d5222caa0a9 100644 --- a/sound/pci/oxygen/oxygen.h +++ b/sound/pci/oxygen/oxygen.h | |||
@@ -34,6 +34,7 @@ | |||
34 | /* CAPTURE_3_FROM_I2S_3 not implemented */ | 34 | /* CAPTURE_3_FROM_I2S_3 not implemented */ |
35 | #define MIDI_OUTPUT 0x0800 | 35 | #define MIDI_OUTPUT 0x0800 |
36 | #define MIDI_INPUT 0x1000 | 36 | #define MIDI_INPUT 0x1000 |
37 | #define AC97_CD_INPUT 0x2000 | ||
37 | 38 | ||
38 | enum { | 39 | enum { |
39 | CONTROL_SPDIF_PCM, | 40 | CONTROL_SPDIF_PCM, |
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index 7e93cf884437..e5ebe56fb0c5 100644 --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c | |||
@@ -308,25 +308,46 @@ static void oxygen_restore_eeprom(struct oxygen *chip, | |||
308 | } | 308 | } |
309 | } | 309 | } |
310 | 310 | ||
311 | static void pci_bridge_magic(void) | 311 | static void configure_pcie_bridge(struct pci_dev *pci) |
312 | { | 312 | { |
313 | struct pci_dev *pci = NULL; | 313 | enum { PEX811X, PI7C9X110 }; |
314 | static const struct pci_device_id bridge_ids[] = { | ||
315 | { PCI_VDEVICE(PLX, 0x8111), .driver_data = PEX811X }, | ||
316 | { PCI_VDEVICE(PLX, 0x8112), .driver_data = PEX811X }, | ||
317 | { PCI_DEVICE(0x12d8, 0xe110), .driver_data = PI7C9X110 }, | ||
318 | { } | ||
319 | }; | ||
320 | struct pci_dev *bridge; | ||
321 | const struct pci_device_id *id; | ||
314 | u32 tmp; | 322 | u32 tmp; |
315 | 323 | ||
316 | for (;;) { | 324 | if (!pci->bus || !pci->bus->self) |
317 | /* If there is any Pericom PI7C9X110 PCI-E/PCI bridge ... */ | 325 | return; |
318 | pci = pci_get_device(0x12d8, 0xe110, pci); | 326 | bridge = pci->bus->self; |
319 | if (!pci) | 327 | |
320 | break; | 328 | id = pci_match_id(bridge_ids, bridge); |
321 | /* | 329 | if (!id) |
322 | * ... configure its secondary internal arbiter to park to | 330 | return; |
323 | * the secondary port, instead of to the last master. | 331 | |
324 | */ | 332 | switch (id->driver_data) { |
325 | if (!pci_read_config_dword(pci, 0x40, &tmp)) { | 333 | case PEX811X: /* PLX PEX8111/PEX8112 PCIe/PCI bridge */ |
326 | tmp |= 1; | 334 | pci_read_config_dword(bridge, 0x48, &tmp); |
327 | pci_write_config_dword(pci, 0x40, tmp); | 335 | tmp |= 1; /* enable blind prefetching */ |
328 | } | 336 | tmp |= 1 << 11; /* enable beacon generation */ |
329 | /* Why? Try asking C-Media. */ | 337 | pci_write_config_dword(bridge, 0x48, tmp); |
338 | |||
339 | pci_write_config_dword(bridge, 0x84, 0x0c); | ||
340 | pci_read_config_dword(bridge, 0x88, &tmp); | ||
341 | tmp &= ~(7 << 27); | ||
342 | tmp |= 2 << 27; /* set prefetch size to 128 bytes */ | ||
343 | pci_write_config_dword(bridge, 0x88, tmp); | ||
344 | break; | ||
345 | |||
346 | case PI7C9X110: /* Pericom PI7C9X110 PCIe/PCI bridge */ | ||
347 | pci_read_config_dword(bridge, 0x40, &tmp); | ||
348 | tmp |= 1; /* park the PCI arbiter to the sound chip */ | ||
349 | pci_write_config_dword(bridge, 0x40, tmp); | ||
350 | break; | ||
330 | } | 351 | } |
331 | } | 352 | } |
332 | 353 | ||
@@ -613,7 +634,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | |||
613 | snd_card_set_dev(card, &pci->dev); | 634 | snd_card_set_dev(card, &pci->dev); |
614 | card->private_free = oxygen_card_free; | 635 | card->private_free = oxygen_card_free; |
615 | 636 | ||
616 | pci_bridge_magic(); | 637 | configure_pcie_bridge(pci); |
617 | oxygen_init(chip); | 638 | oxygen_init(chip); |
618 | chip->model.init(chip); | 639 | chip->model.init(chip); |
619 | 640 | ||
diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c index f375b8a27862..2849b36f5f7e 100644 --- a/sound/pci/oxygen/oxygen_mixer.c +++ b/sound/pci/oxygen/oxygen_mixer.c | |||
@@ -708,7 +708,7 @@ static int ac97_fp_rec_volume_put(struct snd_kcontrol *ctl, | |||
708 | .private_value = ((codec) << 24) | ((stereo) << 16) | (index), \ | 708 | .private_value = ((codec) << 24) | ((stereo) << 16) | (index), \ |
709 | } | 709 | } |
710 | 710 | ||
711 | static DECLARE_TLV_DB_SCALE(monitor_db_scale, -1000, 1000, 0); | 711 | static DECLARE_TLV_DB_SCALE(monitor_db_scale, -600, 600, 0); |
712 | static DECLARE_TLV_DB_SCALE(ac97_db_scale, -3450, 150, 0); | 712 | static DECLARE_TLV_DB_SCALE(ac97_db_scale, -3450, 150, 0); |
713 | static DECLARE_TLV_DB_SCALE(ac97_rec_db_scale, 0, 150, 0); | 713 | static DECLARE_TLV_DB_SCALE(ac97_rec_db_scale, 0, 150, 0); |
714 | 714 | ||
@@ -972,6 +972,9 @@ static int add_controls(struct oxygen *chip, | |||
972 | if (!strcmp(template.name, "Stereo Upmixing") && | 972 | if (!strcmp(template.name, "Stereo Upmixing") && |
973 | chip->model.dac_channels == 2) | 973 | chip->model.dac_channels == 2) |
974 | continue; | 974 | continue; |
975 | if (!strncmp(template.name, "CD Capture ", 11) && | ||
976 | !(chip->model.device_config & AC97_CD_INPUT)) | ||
977 | continue; | ||
975 | if (!strcmp(template.name, "Master Playback Volume") && | 978 | if (!strcmp(template.name, "Master Playback Volume") && |
976 | chip->model.dac_tlv) { | 979 | chip->model.dac_tlv) { |
977 | template.tlv.p = chip->model.dac_tlv; | 980 | template.tlv.p = chip->model.dac_tlv; |
diff --git a/sound/pci/oxygen/oxygen_pcm.c b/sound/pci/oxygen/oxygen_pcm.c index 9dff6954c397..814667442eb0 100644 --- a/sound/pci/oxygen/oxygen_pcm.c +++ b/sound/pci/oxygen/oxygen_pcm.c | |||
@@ -56,8 +56,8 @@ static const struct snd_pcm_hardware oxygen_stereo_hardware = { | |||
56 | .channels_max = 2, | 56 | .channels_max = 2, |
57 | .buffer_bytes_max = BUFFER_BYTES_MAX, | 57 | .buffer_bytes_max = BUFFER_BYTES_MAX, |
58 | .period_bytes_min = PERIOD_BYTES_MIN, | 58 | .period_bytes_min = PERIOD_BYTES_MIN, |
59 | .period_bytes_max = BUFFER_BYTES_MAX / 2, | 59 | .period_bytes_max = BUFFER_BYTES_MAX, |
60 | .periods_min = 2, | 60 | .periods_min = 1, |
61 | .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN, | 61 | .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN, |
62 | }; | 62 | }; |
63 | static const struct snd_pcm_hardware oxygen_multichannel_hardware = { | 63 | static const struct snd_pcm_hardware oxygen_multichannel_hardware = { |
@@ -82,8 +82,8 @@ static const struct snd_pcm_hardware oxygen_multichannel_hardware = { | |||
82 | .channels_max = 8, | 82 | .channels_max = 8, |
83 | .buffer_bytes_max = BUFFER_BYTES_MAX_MULTICH, | 83 | .buffer_bytes_max = BUFFER_BYTES_MAX_MULTICH, |
84 | .period_bytes_min = PERIOD_BYTES_MIN, | 84 | .period_bytes_min = PERIOD_BYTES_MIN, |
85 | .period_bytes_max = BUFFER_BYTES_MAX_MULTICH / 2, | 85 | .period_bytes_max = BUFFER_BYTES_MAX_MULTICH, |
86 | .periods_min = 2, | 86 | .periods_min = 1, |
87 | .periods_max = BUFFER_BYTES_MAX_MULTICH / PERIOD_BYTES_MIN, | 87 | .periods_max = BUFFER_BYTES_MAX_MULTICH / PERIOD_BYTES_MIN, |
88 | }; | 88 | }; |
89 | static const struct snd_pcm_hardware oxygen_ac97_hardware = { | 89 | static const struct snd_pcm_hardware oxygen_ac97_hardware = { |
@@ -100,8 +100,8 @@ static const struct snd_pcm_hardware oxygen_ac97_hardware = { | |||
100 | .channels_max = 2, | 100 | .channels_max = 2, |
101 | .buffer_bytes_max = BUFFER_BYTES_MAX, | 101 | .buffer_bytes_max = BUFFER_BYTES_MAX, |
102 | .period_bytes_min = PERIOD_BYTES_MIN, | 102 | .period_bytes_min = PERIOD_BYTES_MIN, |
103 | .period_bytes_max = BUFFER_BYTES_MAX / 2, | 103 | .period_bytes_max = BUFFER_BYTES_MAX, |
104 | .periods_min = 2, | 104 | .periods_min = 1, |
105 | .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN, | 105 | .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN, |
106 | }; | 106 | }; |
107 | 107 | ||
diff --git a/sound/pci/oxygen/oxygen_regs.h b/sound/pci/oxygen/oxygen_regs.h index 72de159d4567..4dcd41b78258 100644 --- a/sound/pci/oxygen/oxygen_regs.h +++ b/sound/pci/oxygen/oxygen_regs.h | |||
@@ -436,13 +436,15 @@ | |||
436 | /* OXYGEN_CHANNEL_* */ | 436 | /* OXYGEN_CHANNEL_* */ |
437 | 437 | ||
438 | #define OXYGEN_CODEC_VERSION 0xe4 | 438 | #define OXYGEN_CODEC_VERSION 0xe4 |
439 | #define OXYGEN_XCID_MASK 0x07 | 439 | #define OXYGEN_CODEC_ID_MASK 0x07 |
440 | 440 | ||
441 | #define OXYGEN_REVISION 0xe6 | 441 | #define OXYGEN_REVISION 0xe6 |
442 | #define OXYGEN_REVISION_XPKGID_MASK 0x0007 | 442 | #define OXYGEN_PACKAGE_ID_MASK 0x0007 |
443 | #define OXYGEN_PACKAGE_ID_8786 0x0004 | ||
444 | #define OXYGEN_PACKAGE_ID_8787 0x0006 | ||
445 | #define OXYGEN_PACKAGE_ID_8788 0x0007 | ||
443 | #define OXYGEN_REVISION_MASK 0xfff8 | 446 | #define OXYGEN_REVISION_MASK 0xfff8 |
444 | #define OXYGEN_REVISION_2 0x0008 /* bit flag */ | 447 | #define OXYGEN_REVISION_2 0x0008 |
445 | #define OXYGEN_REVISION_8787 0x0014 /* 8 bits */ | ||
446 | 448 | ||
447 | #define OXYGEN_OFFSIN_48K 0xe8 | 449 | #define OXYGEN_OFFSIN_48K 0xe8 |
448 | #define OXYGEN_OFFSBASE_48K 0xe9 | 450 | #define OXYGEN_OFFSBASE_48K 0xe9 |
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c index 06c863e86e3d..469010a8b849 100644 --- a/sound/pci/oxygen/virtuoso.c +++ b/sound/pci/oxygen/virtuoso.c | |||
@@ -25,9 +25,9 @@ | |||
25 | #include "xonar.h" | 25 | #include "xonar.h" |
26 | 26 | ||
27 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); | 27 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); |
28 | MODULE_DESCRIPTION("Asus AVx00 driver"); | 28 | MODULE_DESCRIPTION("Asus Virtuoso driver"); |
29 | MODULE_LICENSE("GPL v2"); | 29 | MODULE_LICENSE("GPL v2"); |
30 | MODULE_SUPPORTED_DEVICE("{{Asus,AV100},{Asus,AV200}}"); | 30 | MODULE_SUPPORTED_DEVICE("{{Asus,AV66},{Asus,AV100},{Asus,AV200}}"); |
31 | 31 | ||
32 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; | 32 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; |
33 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; | 33 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; |
@@ -49,6 +49,7 @@ static DEFINE_PCI_DEVICE_TABLE(xonar_ids) = { | |||
49 | { OXYGEN_PCI_SUBID(0x1043, 0x834f) }, | 49 | { OXYGEN_PCI_SUBID(0x1043, 0x834f) }, |
50 | { OXYGEN_PCI_SUBID(0x1043, 0x835c) }, | 50 | { OXYGEN_PCI_SUBID(0x1043, 0x835c) }, |
51 | { OXYGEN_PCI_SUBID(0x1043, 0x835d) }, | 51 | { OXYGEN_PCI_SUBID(0x1043, 0x835d) }, |
52 | { OXYGEN_PCI_SUBID(0x1043, 0x835e) }, | ||
52 | { OXYGEN_PCI_SUBID(0x1043, 0x838e) }, | 53 | { OXYGEN_PCI_SUBID(0x1043, 0x838e) }, |
53 | { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, | 54 | { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, |
54 | { } | 55 | { } |
diff --git a/sound/pci/oxygen/xonar_cs43xx.c b/sound/pci/oxygen/xonar_cs43xx.c index 7c4986b27f2b..aa27c31049af 100644 --- a/sound/pci/oxygen/xonar_cs43xx.c +++ b/sound/pci/oxygen/xonar_cs43xx.c | |||
@@ -367,13 +367,6 @@ static void xonar_d1_line_mic_ac97_switch(struct oxygen *chip, | |||
367 | 367 | ||
368 | static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -6000, 100, 0); | 368 | static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -6000, 100, 0); |
369 | 369 | ||
370 | static int xonar_d1_control_filter(struct snd_kcontrol_new *template) | ||
371 | { | ||
372 | if (!strncmp(template->name, "CD Capture ", 11)) | ||
373 | return 1; /* no CD input */ | ||
374 | return 0; | ||
375 | } | ||
376 | |||
377 | static int xonar_d1_mixer_init(struct oxygen *chip) | 370 | static int xonar_d1_mixer_init(struct oxygen *chip) |
378 | { | 371 | { |
379 | int err; | 372 | int err; |
@@ -391,7 +384,6 @@ static const struct oxygen_model model_xonar_d1 = { | |||
391 | .longname = "Asus Virtuoso 100", | 384 | .longname = "Asus Virtuoso 100", |
392 | .chip = "AV200", | 385 | .chip = "AV200", |
393 | .init = xonar_d1_init, | 386 | .init = xonar_d1_init, |
394 | .control_filter = xonar_d1_control_filter, | ||
395 | .mixer_init = xonar_d1_mixer_init, | 387 | .mixer_init = xonar_d1_mixer_init, |
396 | .cleanup = xonar_d1_cleanup, | 388 | .cleanup = xonar_d1_cleanup, |
397 | .suspend = xonar_d1_suspend, | 389 | .suspend = xonar_d1_suspend, |
diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c index ba18fb546b4f..d491fd6c0be2 100644 --- a/sound/pci/oxygen/xonar_pcm179x.c +++ b/sound/pci/oxygen/xonar_pcm179x.c | |||
@@ -132,6 +132,18 @@ | |||
132 | * GPIO 5 <- 0 | 132 | * GPIO 5 <- 0 |
133 | */ | 133 | */ |
134 | 134 | ||
135 | /* | ||
136 | * Xonar HDAV1.3 Slim | ||
137 | * ------------------ | ||
138 | * | ||
139 | * CMI8788: | ||
140 | * | ||
141 | * GPIO 1 -> enable output | ||
142 | * | ||
143 | * TXD -> HDMI controller | ||
144 | * RXD <- HDMI controller | ||
145 | */ | ||
146 | |||
135 | #include <linux/pci.h> | 147 | #include <linux/pci.h> |
136 | #include <linux/delay.h> | 148 | #include <linux/delay.h> |
137 | #include <linux/mutex.h> | 149 | #include <linux/mutex.h> |
@@ -362,7 +374,6 @@ static void xonar_st_init_common(struct oxygen *chip) | |||
362 | { | 374 | { |
363 | struct xonar_pcm179x *data = chip->model_data; | 375 | struct xonar_pcm179x *data = chip->model_data; |
364 | 376 | ||
365 | data->generic.anti_pop_delay = 100; | ||
366 | data->generic.output_enable_bit = GPIO_ST_OUTPUT_ENABLE; | 377 | data->generic.output_enable_bit = GPIO_ST_OUTPUT_ENABLE; |
367 | data->dacs = chip->model.private_data ? 4 : 1; | 378 | data->dacs = chip->model.private_data ? 4 : 1; |
368 | data->hp_gain_offset = 2*-18; | 379 | data->hp_gain_offset = 2*-18; |
@@ -408,6 +419,7 @@ static void xonar_st_init(struct oxygen *chip) | |||
408 | { | 419 | { |
409 | struct xonar_pcm179x *data = chip->model_data; | 420 | struct xonar_pcm179x *data = chip->model_data; |
410 | 421 | ||
422 | data->generic.anti_pop_delay = 100; | ||
411 | data->has_cs2000 = 1; | 423 | data->has_cs2000 = 1; |
412 | data->cs2000_fun_cfg_1 = CS2000_REF_CLK_DIV_1; | 424 | data->cs2000_fun_cfg_1 = CS2000_REF_CLK_DIV_1; |
413 | 425 | ||
@@ -428,6 +440,7 @@ static void xonar_stx_init(struct oxygen *chip) | |||
428 | struct xonar_pcm179x *data = chip->model_data; | 440 | struct xonar_pcm179x *data = chip->model_data; |
429 | 441 | ||
430 | xonar_st_init_i2c(chip); | 442 | xonar_st_init_i2c(chip); |
443 | data->generic.anti_pop_delay = 800; | ||
431 | data->generic.ext_power_reg = OXYGEN_GPI_DATA; | 444 | data->generic.ext_power_reg = OXYGEN_GPI_DATA; |
432 | data->generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; | 445 | data->generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; |
433 | data->generic.ext_power_bit = GPI_EXT_POWER; | 446 | data->generic.ext_power_bit = GPI_EXT_POWER; |
@@ -915,13 +928,6 @@ static int xonar_d2_control_filter(struct snd_kcontrol_new *template) | |||
915 | return 0; | 928 | return 0; |
916 | } | 929 | } |
917 | 930 | ||
918 | static int xonar_st_control_filter(struct snd_kcontrol_new *template) | ||
919 | { | ||
920 | if (!strncmp(template->name, "CD Capture ", 11)) | ||
921 | return 1; /* no CD input */ | ||
922 | return 0; | ||
923 | } | ||
924 | |||
925 | static int add_pcm1796_controls(struct oxygen *chip) | 931 | static int add_pcm1796_controls(struct oxygen *chip) |
926 | { | 932 | { |
927 | int err; | 933 | int err; |
@@ -991,7 +997,8 @@ static const struct oxygen_model model_xonar_d2 = { | |||
991 | CAPTURE_0_FROM_I2S_2 | | 997 | CAPTURE_0_FROM_I2S_2 | |
992 | CAPTURE_1_FROM_SPDIF | | 998 | CAPTURE_1_FROM_SPDIF | |
993 | MIDI_OUTPUT | | 999 | MIDI_OUTPUT | |
994 | MIDI_INPUT, | 1000 | MIDI_INPUT | |
1001 | AC97_CD_INPUT, | ||
995 | .dac_channels = 8, | 1002 | .dac_channels = 8, |
996 | .dac_volume_min = 255 - 2*60, | 1003 | .dac_volume_min = 255 - 2*60, |
997 | .dac_volume_max = 255, | 1004 | .dac_volume_max = 255, |
@@ -1037,7 +1044,6 @@ static const struct oxygen_model model_xonar_st = { | |||
1037 | .longname = "Asus Virtuoso 100", | 1044 | .longname = "Asus Virtuoso 100", |
1038 | .chip = "AV200", | 1045 | .chip = "AV200", |
1039 | .init = xonar_st_init, | 1046 | .init = xonar_st_init, |
1040 | .control_filter = xonar_st_control_filter, | ||
1041 | .mixer_init = xonar_st_mixer_init, | 1047 | .mixer_init = xonar_st_mixer_init, |
1042 | .cleanup = xonar_st_cleanup, | 1048 | .cleanup = xonar_st_cleanup, |
1043 | .suspend = xonar_st_suspend, | 1049 | .suspend = xonar_st_suspend, |
@@ -1108,6 +1114,9 @@ int __devinit get_xonar_pcm179x_model(struct oxygen *chip, | |||
1108 | chip->model.resume = xonar_stx_resume; | 1114 | chip->model.resume = xonar_stx_resume; |
1109 | chip->model.set_dac_params = set_pcm1796_params; | 1115 | chip->model.set_dac_params = set_pcm1796_params; |
1110 | break; | 1116 | break; |
1117 | case 0x835e: | ||
1118 | snd_printk(KERN_ERR "the HDAV1.3 Slim is not supported\n"); | ||
1119 | return -ENODEV; | ||
1111 | default: | 1120 | default: |
1112 | return -EINVAL; | 1121 | return -EINVAL; |
1113 | } | 1122 | } |
diff --git a/sound/pci/oxygen/xonar_wm87x6.c b/sound/pci/oxygen/xonar_wm87x6.c index b82c1cfa96f5..200f7601276f 100644 --- a/sound/pci/oxygen/xonar_wm87x6.c +++ b/sound/pci/oxygen/xonar_wm87x6.c | |||
@@ -25,16 +25,24 @@ | |||
25 | * SPI 0 -> WM8766 (surround, center/LFE, back) | 25 | * SPI 0 -> WM8766 (surround, center/LFE, back) |
26 | * SPI 1 -> WM8776 (front, input) | 26 | * SPI 1 -> WM8776 (front, input) |
27 | * | 27 | * |
28 | * GPIO 4 <- headphone detect | 28 | * GPIO 4 <- headphone detect, 0 = plugged |
29 | * GPIO 6 -> route input jack to input 1/2 (1/0) | 29 | * GPIO 6 -> route input jack to mic-in (0) or line-in (1) |
30 | * GPIO 7 -> enable output to speakers | 30 | * GPIO 7 -> enable output to front L/R speaker channels |
31 | * GPIO 8 -> enable output to speakers | 31 | * GPIO 8 -> enable output to other speaker channels and front panel headphone |
32 | * | ||
33 | * WM8766: | ||
34 | * | ||
35 | * input 1 <- line | ||
36 | * input 2 <- mic | ||
37 | * input 3 <- front mic | ||
38 | * input 4 <- aux | ||
32 | */ | 39 | */ |
33 | 40 | ||
34 | #include <linux/pci.h> | 41 | #include <linux/pci.h> |
35 | #include <linux/delay.h> | 42 | #include <linux/delay.h> |
36 | #include <sound/control.h> | 43 | #include <sound/control.h> |
37 | #include <sound/core.h> | 44 | #include <sound/core.h> |
45 | #include <sound/jack.h> | ||
38 | #include <sound/pcm.h> | 46 | #include <sound/pcm.h> |
39 | #include <sound/pcm_params.h> | 47 | #include <sound/pcm_params.h> |
40 | #include <sound/tlv.h> | 48 | #include <sound/tlv.h> |
@@ -44,7 +52,8 @@ | |||
44 | 52 | ||
45 | #define GPIO_DS_HP_DETECT 0x0010 | 53 | #define GPIO_DS_HP_DETECT 0x0010 |
46 | #define GPIO_DS_INPUT_ROUTE 0x0040 | 54 | #define GPIO_DS_INPUT_ROUTE 0x0040 |
47 | #define GPIO_DS_OUTPUT_ENABLE 0x0180 | 55 | #define GPIO_DS_OUTPUT_FRONTLR 0x0080 |
56 | #define GPIO_DS_OUTPUT_ENABLE 0x0100 | ||
48 | 57 | ||
49 | #define LC_CONTROL_LIMITER 0x40000000 | 58 | #define LC_CONTROL_LIMITER 0x40000000 |
50 | #define LC_CONTROL_ALC 0x20000000 | 59 | #define LC_CONTROL_ALC 0x20000000 |
@@ -56,6 +65,7 @@ struct xonar_wm87x6 { | |||
56 | struct snd_kcontrol *line_adcmux_control; | 65 | struct snd_kcontrol *line_adcmux_control; |
57 | struct snd_kcontrol *mic_adcmux_control; | 66 | struct snd_kcontrol *mic_adcmux_control; |
58 | struct snd_kcontrol *lc_controls[13]; | 67 | struct snd_kcontrol *lc_controls[13]; |
68 | struct snd_jack *hp_jack; | ||
59 | }; | 69 | }; |
60 | 70 | ||
61 | static void wm8776_write(struct oxygen *chip, | 71 | static void wm8776_write(struct oxygen *chip, |
@@ -97,8 +107,12 @@ static void wm8766_write(struct oxygen *chip, | |||
97 | (0 << OXYGEN_SPI_CODEC_SHIFT) | | 107 | (0 << OXYGEN_SPI_CODEC_SHIFT) | |
98 | OXYGEN_SPI_CEN_LATCH_CLOCK_LO, | 108 | OXYGEN_SPI_CEN_LATCH_CLOCK_LO, |
99 | (reg << 9) | value); | 109 | (reg << 9) | value); |
100 | if (reg < ARRAY_SIZE(data->wm8766_regs)) | 110 | if (reg < ARRAY_SIZE(data->wm8766_regs)) { |
111 | if ((reg >= WM8766_LDA1 && reg <= WM8766_RDA1) || | ||
112 | (reg >= WM8766_LDA2 && reg <= WM8766_MASTDA)) | ||
113 | value &= ~WM8766_UPDATE; | ||
101 | data->wm8766_regs[reg] = value; | 114 | data->wm8766_regs[reg] = value; |
115 | } | ||
102 | } | 116 | } |
103 | 117 | ||
104 | static void wm8766_write_cached(struct oxygen *chip, | 118 | static void wm8766_write_cached(struct oxygen *chip, |
@@ -107,12 +121,8 @@ static void wm8766_write_cached(struct oxygen *chip, | |||
107 | struct xonar_wm87x6 *data = chip->model_data; | 121 | struct xonar_wm87x6 *data = chip->model_data; |
108 | 122 | ||
109 | if (reg >= ARRAY_SIZE(data->wm8766_regs) || | 123 | if (reg >= ARRAY_SIZE(data->wm8766_regs) || |
110 | value != data->wm8766_regs[reg]) { | 124 | value != data->wm8766_regs[reg]) |
111 | if ((reg >= WM8766_LDA1 && reg <= WM8766_RDA1) || | ||
112 | (reg >= WM8766_LDA2 && reg <= WM8766_MASTDA)) | ||
113 | value &= ~WM8766_UPDATE; | ||
114 | wm8766_write(chip, reg, value); | 125 | wm8766_write(chip, reg, value); |
115 | } | ||
116 | } | 126 | } |
117 | 127 | ||
118 | static void wm8776_registers_init(struct oxygen *chip) | 128 | static void wm8776_registers_init(struct oxygen *chip) |
@@ -141,7 +151,10 @@ static void wm8776_registers_init(struct oxygen *chip) | |||
141 | 151 | ||
142 | static void wm8766_registers_init(struct oxygen *chip) | 152 | static void wm8766_registers_init(struct oxygen *chip) |
143 | { | 153 | { |
154 | struct xonar_wm87x6 *data = chip->model_data; | ||
155 | |||
144 | wm8766_write(chip, WM8766_RESET, 0); | 156 | wm8766_write(chip, WM8766_RESET, 0); |
157 | wm8766_write(chip, WM8766_DAC_CTRL, data->wm8766_regs[WM8766_DAC_CTRL]); | ||
145 | wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24); | 158 | wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24); |
146 | wm8766_write(chip, WM8766_DAC_CTRL2, | 159 | wm8766_write(chip, WM8766_DAC_CTRL2, |
147 | WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0)); | 160 | WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0)); |
@@ -170,6 +183,40 @@ static void wm8776_init(struct oxygen *chip) | |||
170 | wm8776_registers_init(chip); | 183 | wm8776_registers_init(chip); |
171 | } | 184 | } |
172 | 185 | ||
186 | static void wm8766_init(struct oxygen *chip) | ||
187 | { | ||
188 | struct xonar_wm87x6 *data = chip->model_data; | ||
189 | |||
190 | data->wm8766_regs[WM8766_DAC_CTRL] = | ||
191 | WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT; | ||
192 | wm8766_registers_init(chip); | ||
193 | } | ||
194 | |||
195 | static void xonar_ds_handle_hp_jack(struct oxygen *chip) | ||
196 | { | ||
197 | struct xonar_wm87x6 *data = chip->model_data; | ||
198 | bool hp_plugged; | ||
199 | unsigned int reg; | ||
200 | |||
201 | mutex_lock(&chip->mutex); | ||
202 | |||
203 | hp_plugged = !(oxygen_read16(chip, OXYGEN_GPIO_DATA) & | ||
204 | GPIO_DS_HP_DETECT); | ||
205 | |||
206 | oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, | ||
207 | hp_plugged ? 0 : GPIO_DS_OUTPUT_FRONTLR, | ||
208 | GPIO_DS_OUTPUT_FRONTLR); | ||
209 | |||
210 | reg = data->wm8766_regs[WM8766_DAC_CTRL] & ~WM8766_MUTEALL; | ||
211 | if (hp_plugged) | ||
212 | reg |= WM8766_MUTEALL; | ||
213 | wm8766_write_cached(chip, WM8766_DAC_CTRL, reg); | ||
214 | |||
215 | snd_jack_report(data->hp_jack, hp_plugged ? SND_JACK_HEADPHONE : 0); | ||
216 | |||
217 | mutex_unlock(&chip->mutex); | ||
218 | } | ||
219 | |||
173 | static void xonar_ds_init(struct oxygen *chip) | 220 | static void xonar_ds_init(struct oxygen *chip) |
174 | { | 221 | { |
175 | struct xonar_wm87x6 *data = chip->model_data; | 222 | struct xonar_wm87x6 *data = chip->model_data; |
@@ -178,16 +225,22 @@ static void xonar_ds_init(struct oxygen *chip) | |||
178 | data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE; | 225 | data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE; |
179 | 226 | ||
180 | wm8776_init(chip); | 227 | wm8776_init(chip); |
181 | wm8766_registers_init(chip); | 228 | wm8766_init(chip); |
182 | 229 | ||
183 | oxygen_write16_masked(chip, OXYGEN_GPIO_CONTROL, GPIO_DS_INPUT_ROUTE, | 230 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, |
184 | GPIO_DS_HP_DETECT | GPIO_DS_INPUT_ROUTE); | 231 | GPIO_DS_INPUT_ROUTE | GPIO_DS_OUTPUT_FRONTLR); |
232 | oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, | ||
233 | GPIO_DS_HP_DETECT); | ||
185 | oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE); | 234 | oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE); |
186 | oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT); | 235 | oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT); |
187 | chip->interrupt_mask |= OXYGEN_INT_GPIO; | 236 | chip->interrupt_mask |= OXYGEN_INT_GPIO; |
188 | 237 | ||
189 | xonar_enable_output(chip); | 238 | xonar_enable_output(chip); |
190 | 239 | ||
240 | snd_jack_new(chip->card, "Headphone", | ||
241 | SND_JACK_HEADPHONE, &data->hp_jack); | ||
242 | xonar_ds_handle_hp_jack(chip); | ||
243 | |||
191 | snd_component_add(chip->card, "WM8776"); | 244 | snd_component_add(chip->card, "WM8776"); |
192 | snd_component_add(chip->card, "WM8766"); | 245 | snd_component_add(chip->card, "WM8766"); |
193 | } | 246 | } |
@@ -208,6 +261,7 @@ static void xonar_ds_resume(struct oxygen *chip) | |||
208 | wm8776_registers_init(chip); | 261 | wm8776_registers_init(chip); |
209 | wm8766_registers_init(chip); | 262 | wm8766_registers_init(chip); |
210 | xonar_enable_output(chip); | 263 | xonar_enable_output(chip); |
264 | xonar_ds_handle_hp_jack(chip); | ||
211 | } | 265 | } |
212 | 266 | ||
213 | static void wm8776_adc_hardware_filter(unsigned int channel, | 267 | static void wm8776_adc_hardware_filter(unsigned int channel, |
@@ -323,12 +377,27 @@ static void update_wm87x6_mute(struct oxygen *chip) | |||
323 | (chip->dac_mute ? WM8766_DMUTE_MASK : 0)); | 377 | (chip->dac_mute ? WM8766_DMUTE_MASK : 0)); |
324 | } | 378 | } |
325 | 379 | ||
326 | static void xonar_ds_gpio_changed(struct oxygen *chip) | 380 | static void update_wm8766_center_lfe_mix(struct oxygen *chip, bool mixed) |
327 | { | 381 | { |
328 | u16 bits; | 382 | struct xonar_wm87x6 *data = chip->model_data; |
383 | unsigned int reg; | ||
329 | 384 | ||
330 | bits = oxygen_read16(chip, OXYGEN_GPIO_DATA); | 385 | /* |
331 | snd_printk(KERN_INFO "HP detect: %d\n", !!(bits & GPIO_DS_HP_DETECT)); | 386 | * The WM8766 can mix left and right channels, but this setting |
387 | * applies to all three stereo pairs. | ||
388 | */ | ||
389 | reg = data->wm8766_regs[WM8766_DAC_CTRL] & | ||
390 | ~(WM8766_PL_LEFT_MASK | WM8766_PL_RIGHT_MASK); | ||
391 | if (mixed) | ||
392 | reg |= WM8766_PL_LEFT_LRMIX | WM8766_PL_RIGHT_LRMIX; | ||
393 | else | ||
394 | reg |= WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT; | ||
395 | wm8766_write_cached(chip, WM8766_DAC_CTRL, reg); | ||
396 | } | ||
397 | |||
398 | static void xonar_ds_gpio_changed(struct oxygen *chip) | ||
399 | { | ||
400 | xonar_ds_handle_hp_jack(chip); | ||
332 | } | 401 | } |
333 | 402 | ||
334 | static int wm8776_bit_switch_get(struct snd_kcontrol *ctl, | 403 | static int wm8776_bit_switch_get(struct snd_kcontrol *ctl, |
@@ -896,7 +965,10 @@ static const struct snd_kcontrol_new ds_controls[] = { | |||
896 | .put = wm8776_input_mux_put, | 965 | .put = wm8776_input_mux_put, |
897 | .private_value = 1 << 1, | 966 | .private_value = 1 << 1, |
898 | }, | 967 | }, |
899 | WM8776_BIT_SWITCH("Aux", WM8776_ADCMUX, 1 << 2, 0, 0), | 968 | WM8776_BIT_SWITCH("Front Mic Capture Switch", |
969 | WM8776_ADCMUX, 1 << 2, 0, 0), | ||
970 | WM8776_BIT_SWITCH("Aux Capture Switch", | ||
971 | WM8776_ADCMUX, 1 << 3, 0, 0), | ||
900 | { | 972 | { |
901 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 973 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
902 | .name = "ADC Filter Capture Enum", | 974 | .name = "ADC Filter Capture Enum", |
@@ -956,13 +1028,6 @@ static const struct snd_kcontrol_new lc_controls[] = { | |||
956 | LC_CONTROL_ALC, wm8776_ngth_db_scale), | 1028 | LC_CONTROL_ALC, wm8776_ngth_db_scale), |
957 | }; | 1029 | }; |
958 | 1030 | ||
959 | static int xonar_ds_control_filter(struct snd_kcontrol_new *template) | ||
960 | { | ||
961 | if (!strncmp(template->name, "CD Capture ", 11)) | ||
962 | return 1; /* no CD input */ | ||
963 | return 0; | ||
964 | } | ||
965 | |||
966 | static int xonar_ds_mixer_init(struct oxygen *chip) | 1031 | static int xonar_ds_mixer_init(struct oxygen *chip) |
967 | { | 1032 | { |
968 | struct xonar_wm87x6 *data = chip->model_data; | 1033 | struct xonar_wm87x6 *data = chip->model_data; |
@@ -999,10 +1064,9 @@ static int xonar_ds_mixer_init(struct oxygen *chip) | |||
999 | 1064 | ||
1000 | static const struct oxygen_model model_xonar_ds = { | 1065 | static const struct oxygen_model model_xonar_ds = { |
1001 | .shortname = "Xonar DS", | 1066 | .shortname = "Xonar DS", |
1002 | .longname = "Asus Virtuoso 200", | 1067 | .longname = "Asus Virtuoso 66", |
1003 | .chip = "AV200", | 1068 | .chip = "AV200", |
1004 | .init = xonar_ds_init, | 1069 | .init = xonar_ds_init, |
1005 | .control_filter = xonar_ds_control_filter, | ||
1006 | .mixer_init = xonar_ds_mixer_init, | 1070 | .mixer_init = xonar_ds_mixer_init, |
1007 | .cleanup = xonar_ds_cleanup, | 1071 | .cleanup = xonar_ds_cleanup, |
1008 | .suspend = xonar_ds_suspend, | 1072 | .suspend = xonar_ds_suspend, |
@@ -1013,6 +1077,7 @@ static const struct oxygen_model model_xonar_ds = { | |||
1013 | .set_adc_params = set_wm8776_adc_params, | 1077 | .set_adc_params = set_wm8776_adc_params, |
1014 | .update_dac_volume = update_wm87x6_volume, | 1078 | .update_dac_volume = update_wm87x6_volume, |
1015 | .update_dac_mute = update_wm87x6_mute, | 1079 | .update_dac_mute = update_wm87x6_mute, |
1080 | .update_center_lfe_mix = update_wm8766_center_lfe_mix, | ||
1016 | .gpio_changed = xonar_ds_gpio_changed, | 1081 | .gpio_changed = xonar_ds_gpio_changed, |
1017 | .dac_tlv = wm87x6_dac_db_scale, | 1082 | .dac_tlv = wm87x6_dac_db_scale, |
1018 | .model_data_size = sizeof(struct xonar_wm87x6), | 1083 | .model_data_size = sizeof(struct xonar_wm87x6), |
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index d19dc052c391..d5f5b440fc40 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c | |||
@@ -1527,14 +1527,14 @@ snd_rme96_free(void *private_data) | |||
1527 | static void | 1527 | static void |
1528 | snd_rme96_free_spdif_pcm(struct snd_pcm *pcm) | 1528 | snd_rme96_free_spdif_pcm(struct snd_pcm *pcm) |
1529 | { | 1529 | { |
1530 | struct rme96 *rme96 = (struct rme96 *) pcm->private_data; | 1530 | struct rme96 *rme96 = pcm->private_data; |
1531 | rme96->spdif_pcm = NULL; | 1531 | rme96->spdif_pcm = NULL; |
1532 | } | 1532 | } |
1533 | 1533 | ||
1534 | static void | 1534 | static void |
1535 | snd_rme96_free_adat_pcm(struct snd_pcm *pcm) | 1535 | snd_rme96_free_adat_pcm(struct snd_pcm *pcm) |
1536 | { | 1536 | { |
1537 | struct rme96 *rme96 = (struct rme96 *) pcm->private_data; | 1537 | struct rme96 *rme96 = pcm->private_data; |
1538 | rme96->adat_pcm = NULL; | 1538 | rme96->adat_pcm = NULL; |
1539 | } | 1539 | } |
1540 | 1540 | ||
@@ -1661,7 +1661,7 @@ static void | |||
1661 | snd_rme96_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | 1661 | snd_rme96_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) |
1662 | { | 1662 | { |
1663 | int n; | 1663 | int n; |
1664 | struct rme96 *rme96 = (struct rme96 *)entry->private_data; | 1664 | struct rme96 *rme96 = entry->private_data; |
1665 | 1665 | ||
1666 | rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); | 1666 | rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); |
1667 | 1667 | ||
@@ -2348,7 +2348,7 @@ snd_rme96_probe(struct pci_dev *pci, | |||
2348 | if (err < 0) | 2348 | if (err < 0) |
2349 | return err; | 2349 | return err; |
2350 | card->private_free = snd_rme96_card_free; | 2350 | card->private_free = snd_rme96_card_free; |
2351 | rme96 = (struct rme96 *)card->private_data; | 2351 | rme96 = card->private_data; |
2352 | rme96->card = card; | 2352 | rme96->card = card; |
2353 | rme96->pci = pci; | 2353 | rme96->pci = pci; |
2354 | snd_card_set_dev(card, &pci->dev); | 2354 | snd_card_set_dev(card, &pci->dev); |
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index d6fa7bfd9aa1..0b720cf7783e 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c | |||
@@ -3284,7 +3284,7 @@ static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp) | |||
3284 | static void | 3284 | static void |
3285 | snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | 3285 | snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) |
3286 | { | 3286 | { |
3287 | struct hdsp *hdsp = (struct hdsp *) entry->private_data; | 3287 | struct hdsp *hdsp = entry->private_data; |
3288 | unsigned int status; | 3288 | unsigned int status; |
3289 | unsigned int status2; | 3289 | unsigned int status2; |
3290 | char *pref_sync_ref; | 3290 | char *pref_sync_ref; |
@@ -4566,7 +4566,7 @@ static int hdsp_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rm | |||
4566 | 4566 | ||
4567 | static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg) | 4567 | static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg) |
4568 | { | 4568 | { |
4569 | struct hdsp *hdsp = (struct hdsp *)hw->private_data; | 4569 | struct hdsp *hdsp = hw->private_data; |
4570 | void __user *argp = (void __user *)arg; | 4570 | void __user *argp = (void __user *)arg; |
4571 | int err; | 4571 | int err; |
4572 | 4572 | ||
@@ -5156,7 +5156,7 @@ static int snd_hdsp_free(struct hdsp *hdsp) | |||
5156 | 5156 | ||
5157 | static void snd_hdsp_card_free(struct snd_card *card) | 5157 | static void snd_hdsp_card_free(struct snd_card *card) |
5158 | { | 5158 | { |
5159 | struct hdsp *hdsp = (struct hdsp *) card->private_data; | 5159 | struct hdsp *hdsp = card->private_data; |
5160 | 5160 | ||
5161 | if (hdsp) | 5161 | if (hdsp) |
5162 | snd_hdsp_free(hdsp); | 5162 | snd_hdsp_free(hdsp); |
@@ -5182,7 +5182,7 @@ static int __devinit snd_hdsp_probe(struct pci_dev *pci, | |||
5182 | if (err < 0) | 5182 | if (err < 0) |
5183 | return err; | 5183 | return err; |
5184 | 5184 | ||
5185 | hdsp = (struct hdsp *) card->private_data; | 5185 | hdsp = card->private_data; |
5186 | card->private_free = snd_hdsp_card_free; | 5186 | card->private_free = snd_hdsp_card_free; |
5187 | hdsp->dev = dev; | 5187 | hdsp->dev = dev; |
5188 | hdsp->pci = pci; | 5188 | hdsp->pci = pci; |