diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-03 12:10:23 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-03 12:10:23 -0400 |
commit | 9992ba72327fa0d8bdc9fb624e80f5cce338a711 (patch) | |
tree | e0bf31ae53cb19c44674df7e0d0343a26037ad34 /sound/pci | |
parent | 00fdffb5131125dce0702bf61e24a806ec3aed80 (diff) | |
parent | 4ca231b2e6ed171107c5b21f9e92d1965fd6fd9e (diff) |
Merge tag 'sound-3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai:
"Mostly many small changes spread as seen in diffstat in sound/*
directory by this update. A significant change in the subsystem level
is the introduction of snd_soc_component, which will help more generic
handling of SoC and off-SoC components.
Also, snd_BUG_ON() macro is enabled unconditionally now due to its
misuses, so people might hit kernel warnings (it's a good thing for
us).
- compress-offload: support for capture by Charles Keepax
- HD-audio: codec delay support by Dylan Reid
- HD-audio: improvements/fixes in generic parser: better headphone
mic and headset mic support, jack_modes hint consolidation, proper
beep attach/detachment, generalized power filter controls by David
Henningsson, et al
- HD-audio: Improved management of HDMI codec pins/converters
- HD-audio: Better pin/DAC assignment for VIA codecs
- HD-audio: Haswell HDMI workarounds
- HD-audio: ALC268 codec support, a few new quirks for Chromebooks
- USB: regression fixes: USB-MIDI autopm fix, the recent ISO latency
fix by Clemens Ladisch
- USB: support for DSD formats by Daniel Mack
- USB: A few UAC2 device endian/cock fixes by Eldad Zack
- USB: quirks for Emu 192kHz support, Novation Twitch DJ controller,
Yamaha THRxx devices
- HDSPM: updates for TCO controls by Adrian Knoth
- ASoC: Add a snd_soc_component object type for generic handling of
SoC and off-SoC components by Kuninori Morimoto,
- dmaengine: a large set of cleanups and conversions by Lars-Peter
Clausen
- ASoC DAPM: performance optimizations from Ryo Tsutsui
- ASoC DAPM: support for mixer control sharing by Stephen Warren
- ASoC: multiplatform ARM cleanups from Arnd Bergmann
- ASoC: new codec drivers for AK5385 and TAS5086 from Daniel Mack"
* tag 'sound-3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (315 commits)
ALSA: usb-audio: caiaq: fix endianness bug in snd_usb_caiaq_maschine_dispatch
ALSA: asihpi: add format support check in snd_card_asihpi_capture_formats
ALSA: pcm_format_to_bits strong-typed conversion
ALSA: compress: fix the states to check for allowing read
ALSA: hda - Move Thinkpad X220 to use auto parser
ALSA: USB: adjust for changed 3.8 USB API
ALSA: usb - Avoid unnecessary sample rate changes on USB 2.0 clock sources
sound: oss/dmabuf: use dma_map_single
ALSA: ali5451: use mdelay instead of large udelay constants
ALSA: hda - Add the support for ALC286 codec
ALSA: usb-audio: USB quirk for Yamaha THR10C
ALSA: usb-audio: USB quirk for Yamaha THR5A
ALSA: usb-audio: USB quirk for Yamaha THR10
ALSA: usb-audio: Fix autopm error during probing
ALSA: snd-usb: try harder to find USB_DT_CS_ENDPOINT
ALSA: sound kconfig typo
ALSA: emu10k1: Fix dock firmware loading
ASoC: ux500: forward declare msp_i2s_platform_data
ASoC: davinci-mcasp: Add Support BCLK-to-LRCLK ratio for TDM modes
ASoC: davinci-pcm, davinci-mcasp: Clean up active_serializers
...
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/ac97/ac97_codec.c | 16 | ||||
-rw-r--r-- | sound/pci/ac97/ac97_pcm.c | 10 | ||||
-rw-r--r-- | sound/pci/ali5451/ali5451.c | 8 | ||||
-rw-r--r-- | sound/pci/asihpi/asihpi.c | 6 | ||||
-rw-r--r-- | sound/pci/emu10k1/emu10k1_main.c | 39 | ||||
-rw-r--r-- | sound/pci/hda/hda_auto_parser.c | 68 | ||||
-rw-r--r-- | sound/pci/hda/hda_auto_parser.h | 29 | ||||
-rw-r--r-- | sound/pci/hda/hda_beep.c | 39 | ||||
-rw-r--r-- | sound/pci/hda/hda_beep.h | 1 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 28 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 3 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.c | 433 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.h | 30 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 39 | ||||
-rw-r--r-- | sound/pci/hda/hda_jack.c | 43 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 4 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 33 | ||||
-rw-r--r-- | sound/pci/hda/patch_ca0132.c | 82 | ||||
-rw-r--r-- | sound/pci/hda/patch_cirrus.c | 19 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 21 | ||||
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 236 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 715 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 39 | ||||
-rw-r--r-- | sound/pci/hda/patch_via.c | 20 | ||||
-rw-r--r-- | sound/pci/rme9652/hdspm.c | 382 |
25 files changed, 1791 insertions, 552 deletions
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 8b0f99688303..d37c683cfd7a 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c | |||
@@ -299,7 +299,7 @@ EXPORT_SYMBOL(snd_ac97_write); | |||
299 | * Reads a value from the given register. This will invoke the read | 299 | * Reads a value from the given register. This will invoke the read |
300 | * callback directly after the register check. | 300 | * callback directly after the register check. |
301 | * | 301 | * |
302 | * Returns the read value. | 302 | * Return: The read value. |
303 | */ | 303 | */ |
304 | unsigned short snd_ac97_read(struct snd_ac97 *ac97, unsigned short reg) | 304 | unsigned short snd_ac97_read(struct snd_ac97 *ac97, unsigned short reg) |
305 | { | 305 | { |
@@ -352,7 +352,7 @@ EXPORT_SYMBOL(snd_ac97_write_cache); | |||
352 | * Compares the value with the register cache and updates the value | 352 | * Compares the value with the register cache and updates the value |
353 | * only when the value is changed. | 353 | * only when the value is changed. |
354 | * | 354 | * |
355 | * Returns 1 if the value is changed, 0 if no change, or a negative | 355 | * Return: 1 if the value is changed, 0 if no change, or a negative |
356 | * code on failure. | 356 | * code on failure. |
357 | */ | 357 | */ |
358 | int snd_ac97_update(struct snd_ac97 *ac97, unsigned short reg, unsigned short value) | 358 | int snd_ac97_update(struct snd_ac97 *ac97, unsigned short reg, unsigned short value) |
@@ -384,7 +384,7 @@ EXPORT_SYMBOL(snd_ac97_update); | |||
384 | * Updates the masked-bits on the given register only when the value | 384 | * Updates the masked-bits on the given register only when the value |
385 | * is changed. | 385 | * is changed. |
386 | * | 386 | * |
387 | * Returns 1 if the bits are changed, 0 if no change, or a negative | 387 | * Return: 1 if the bits are changed, 0 if no change, or a negative |
388 | * code on failure. | 388 | * code on failure. |
389 | */ | 389 | */ |
390 | int snd_ac97_update_bits(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value) | 390 | int snd_ac97_update_bits(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value) |
@@ -1836,7 +1836,7 @@ void snd_ac97_get_name(struct snd_ac97 *ac97, unsigned int id, char *name, int m | |||
1836 | * snd_ac97_get_short_name - retrieve codec name | 1836 | * snd_ac97_get_short_name - retrieve codec name |
1837 | * @ac97: the codec instance | 1837 | * @ac97: the codec instance |
1838 | * | 1838 | * |
1839 | * Returns the short identifying name of the codec. | 1839 | * Return: The short identifying name of the codec. |
1840 | */ | 1840 | */ |
1841 | const char *snd_ac97_get_short_name(struct snd_ac97 *ac97) | 1841 | const char *snd_ac97_get_short_name(struct snd_ac97 *ac97) |
1842 | { | 1842 | { |
@@ -1910,7 +1910,7 @@ static int ac97_reset_wait(struct snd_ac97 *ac97, int timeout, int with_modem) | |||
1910 | * The AC97 bus instance is registered as a low-level device, so you don't | 1910 | * The AC97 bus instance is registered as a low-level device, so you don't |
1911 | * have to release it manually. | 1911 | * have to release it manually. |
1912 | * | 1912 | * |
1913 | * Returns zero if successful, or a negative error code on failure. | 1913 | * Return: Zero if successful, or a negative error code on failure. |
1914 | */ | 1914 | */ |
1915 | int snd_ac97_bus(struct snd_card *card, int num, struct snd_ac97_bus_ops *ops, | 1915 | int snd_ac97_bus(struct snd_card *card, int num, struct snd_ac97_bus_ops *ops, |
1916 | void *private_data, struct snd_ac97_bus **rbus) | 1916 | void *private_data, struct snd_ac97_bus **rbus) |
@@ -2006,7 +2006,7 @@ static void do_update_power(struct work_struct *work) | |||
2006 | * The ac97 instance is registered as a low-level device, so you don't | 2006 | * The ac97 instance is registered as a low-level device, so you don't |
2007 | * have to release it manually. | 2007 | * have to release it manually. |
2008 | * | 2008 | * |
2009 | * Returns zero if successful, or a negative error code on failure. | 2009 | * Return: Zero if successful, or a negative error code on failure. |
2010 | */ | 2010 | */ |
2011 | int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, struct snd_ac97 **rac97) | 2011 | int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, struct snd_ac97 **rac97) |
2012 | { | 2012 | { |
@@ -2373,6 +2373,8 @@ static struct ac97_power_reg power_regs[PWIDX_SIZE] = { | |||
2373 | * @powerup: non-zero when power up the part | 2373 | * @powerup: non-zero when power up the part |
2374 | * | 2374 | * |
2375 | * Update the AC97 powerdown register bits of the given part. | 2375 | * Update the AC97 powerdown register bits of the given part. |
2376 | * | ||
2377 | * Return: Zero. | ||
2376 | */ | 2378 | */ |
2377 | int snd_ac97_update_power(struct snd_ac97 *ac97, int reg, int powerup) | 2379 | int snd_ac97_update_power(struct snd_ac97 *ac97, int reg, int powerup) |
2378 | { | 2380 | { |
@@ -2885,7 +2887,7 @@ static int apply_quirk_str(struct snd_ac97 *ac97, const char *typestr) | |||
2885 | * headphone (true line-out) control as "Master". | 2887 | * headphone (true line-out) control as "Master". |
2886 | * The quirk-list must be terminated with a zero-filled entry. | 2888 | * The quirk-list must be terminated with a zero-filled entry. |
2887 | * | 2889 | * |
2888 | * Returns zero if successful, or a negative error code on failure. | 2890 | * Return: Zero if successful, or a negative error code on failure. |
2889 | */ | 2891 | */ |
2890 | 2892 | ||
2891 | int snd_ac97_tune_hardware(struct snd_ac97 *ac97, struct ac97_quirk *quirk, const char *override) | 2893 | int snd_ac97_tune_hardware(struct snd_ac97 *ac97, struct ac97_quirk *quirk, const char *override) |
diff --git a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c index f1488fc176d5..eab0fc9ff2e0 100644 --- a/sound/pci/ac97/ac97_pcm.c +++ b/sound/pci/ac97/ac97_pcm.c | |||
@@ -253,7 +253,7 @@ static int set_spdif_rate(struct snd_ac97 *ac97, unsigned short rate) | |||
253 | * AC97_SPDIF is accepted as a pseudo register to modify the SPDIF | 253 | * AC97_SPDIF is accepted as a pseudo register to modify the SPDIF |
254 | * status bits. | 254 | * status bits. |
255 | * | 255 | * |
256 | * Returns zero if successful, or a negative error code on failure. | 256 | * Return: Zero if successful, or a negative error code on failure. |
257 | */ | 257 | */ |
258 | int snd_ac97_set_rate(struct snd_ac97 *ac97, int reg, unsigned int rate) | 258 | int snd_ac97_set_rate(struct snd_ac97 *ac97, int reg, unsigned int rate) |
259 | { | 259 | { |
@@ -440,6 +440,8 @@ static unsigned int get_rates(struct ac97_pcm *pcm, unsigned int cidx, unsigned | |||
440 | * It assigns available AC97 slots for given PCMs. If none or only | 440 | * It assigns available AC97 slots for given PCMs. If none or only |
441 | * some slots are available, pcm->xxx.slots and pcm->xxx.rslots[] members | 441 | * some slots are available, pcm->xxx.slots and pcm->xxx.rslots[] members |
442 | * are reduced and might be zero. | 442 | * are reduced and might be zero. |
443 | * | ||
444 | * Return: Zero if successful, or a negative error code on failure. | ||
443 | */ | 445 | */ |
444 | int snd_ac97_pcm_assign(struct snd_ac97_bus *bus, | 446 | int snd_ac97_pcm_assign(struct snd_ac97_bus *bus, |
445 | unsigned short pcms_count, | 447 | unsigned short pcms_count, |
@@ -562,6 +564,8 @@ EXPORT_SYMBOL(snd_ac97_pcm_assign); | |||
562 | * @slots: a subset of allocated slots (snd_ac97_pcm_assign) for this pcm | 564 | * @slots: a subset of allocated slots (snd_ac97_pcm_assign) for this pcm |
563 | * | 565 | * |
564 | * It locks the specified slots and sets the given rate to AC97 registers. | 566 | * It locks the specified slots and sets the given rate to AC97 registers. |
567 | * | ||
568 | * Return: Zero if successful, or a negative error code on failure. | ||
565 | */ | 569 | */ |
566 | int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate, | 570 | int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate, |
567 | enum ac97_pcm_cfg cfg, unsigned short slots) | 571 | enum ac97_pcm_cfg cfg, unsigned short slots) |
@@ -644,6 +648,8 @@ EXPORT_SYMBOL(snd_ac97_pcm_open); | |||
644 | * @pcm: the ac97 pcm instance | 648 | * @pcm: the ac97 pcm instance |
645 | * | 649 | * |
646 | * It frees the locked AC97 slots. | 650 | * It frees the locked AC97 slots. |
651 | * | ||
652 | * Return: Zero. | ||
647 | */ | 653 | */ |
648 | int snd_ac97_pcm_close(struct ac97_pcm *pcm) | 654 | int snd_ac97_pcm_close(struct ac97_pcm *pcm) |
649 | { | 655 | { |
@@ -718,6 +724,8 @@ static int double_rate_hw_constraint_channels(struct snd_pcm_hw_params *params, | |||
718 | * | 724 | * |
719 | * Installs the hardware constraint rules to prevent using double rates and | 725 | * Installs the hardware constraint rules to prevent using double rates and |
720 | * more than two channels at the same time. | 726 | * more than two channels at the same time. |
727 | * | ||
728 | * Return: Zero if successful, or a negative error code on failure. | ||
721 | */ | 729 | */ |
722 | int snd_ac97_pcm_double_rate_rules(struct snd_pcm_runtime *runtime) | 730 | int snd_ac97_pcm_double_rate_rules(struct snd_pcm_runtime *runtime) |
723 | { | 731 | { |
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index e760af9d1fb6..53754f5edeb1 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c | |||
@@ -451,10 +451,10 @@ static int snd_ali_reset_5451(struct snd_ali *codec) | |||
451 | if (pci_dev) { | 451 | if (pci_dev) { |
452 | pci_read_config_dword(pci_dev, 0x7c, &dwVal); | 452 | pci_read_config_dword(pci_dev, 0x7c, &dwVal); |
453 | pci_write_config_dword(pci_dev, 0x7c, dwVal | 0x08000000); | 453 | pci_write_config_dword(pci_dev, 0x7c, dwVal | 0x08000000); |
454 | udelay(5000); | 454 | mdelay(5); |
455 | pci_read_config_dword(pci_dev, 0x7c, &dwVal); | 455 | pci_read_config_dword(pci_dev, 0x7c, &dwVal); |
456 | pci_write_config_dword(pci_dev, 0x7c, dwVal & 0xf7ffffff); | 456 | pci_write_config_dword(pci_dev, 0x7c, dwVal & 0xf7ffffff); |
457 | udelay(5000); | 457 | mdelay(5); |
458 | } | 458 | } |
459 | 459 | ||
460 | pci_dev = codec->pci; | 460 | pci_dev = codec->pci; |
@@ -463,14 +463,14 @@ static int snd_ali_reset_5451(struct snd_ali *codec) | |||
463 | udelay(500); | 463 | udelay(500); |
464 | pci_read_config_dword(pci_dev, 0x44, &dwVal); | 464 | pci_read_config_dword(pci_dev, 0x44, &dwVal); |
465 | pci_write_config_dword(pci_dev, 0x44, dwVal & 0xfffbffff); | 465 | pci_write_config_dword(pci_dev, 0x44, dwVal & 0xfffbffff); |
466 | udelay(5000); | 466 | mdelay(5); |
467 | 467 | ||
468 | wCount = 200; | 468 | wCount = 200; |
469 | while(wCount--) { | 469 | while(wCount--) { |
470 | wReg = snd_ali_codec_peek(codec, 0, AC97_POWERDOWN); | 470 | wReg = snd_ali_codec_peek(codec, 0, AC97_POWERDOWN); |
471 | if ((wReg & 0x000f) == 0x000f) | 471 | if ((wReg & 0x000f) == 0x000f) |
472 | return 0; | 472 | return 0; |
473 | udelay(5000); | 473 | mdelay(5); |
474 | } | 474 | } |
475 | 475 | ||
476 | /* non-fatal if you have a non PM capable codec */ | 476 | /* non-fatal if you have a non PM capable codec */ |
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index 0aabfedeecba..fbc17203613c 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c | |||
@@ -966,7 +966,7 @@ static u64 snd_card_asihpi_playback_formats(struct snd_card_asihpi *asihpi, | |||
966 | if (!err) | 966 | if (!err) |
967 | err = hpi_outstream_query_format(h_stream, &hpi_format); | 967 | err = hpi_outstream_query_format(h_stream, &hpi_format); |
968 | if (!err && (hpi_to_alsa_formats[format] != -1)) | 968 | if (!err && (hpi_to_alsa_formats[format] != -1)) |
969 | formats |= (1ULL << hpi_to_alsa_formats[format]); | 969 | formats |= pcm_format_to_bits(hpi_to_alsa_formats[format]); |
970 | } | 970 | } |
971 | return formats; | 971 | return formats; |
972 | } | 972 | } |
@@ -1141,8 +1141,8 @@ static u64 snd_card_asihpi_capture_formats(struct snd_card_asihpi *asihpi, | |||
1141 | format, sample_rate, 128000, 0); | 1141 | format, sample_rate, 128000, 0); |
1142 | if (!err) | 1142 | if (!err) |
1143 | err = hpi_instream_query_format(h_stream, &hpi_format); | 1143 | err = hpi_instream_query_format(h_stream, &hpi_format); |
1144 | if (!err) | 1144 | if (!err && (hpi_to_alsa_formats[format] != -1)) |
1145 | formats |= (1ULL << hpi_to_alsa_formats[format]); | 1145 | formats |= pcm_format_to_bits(hpi_to_alsa_formats[format]); |
1146 | } | 1146 | } |
1147 | return formats; | 1147 | return formats; |
1148 | } | 1148 | } |
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index e6b016693240..bdd888ec9a84 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c | |||
@@ -657,14 +657,14 @@ static int snd_emu10k1_cardbus_init(struct snd_emu10k1 *emu) | |||
657 | return 0; | 657 | return 0; |
658 | } | 658 | } |
659 | 659 | ||
660 | static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu) | 660 | static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, |
661 | const struct firmware *fw_entry) | ||
661 | { | 662 | { |
662 | int n, i; | 663 | int n, i; |
663 | int reg; | 664 | int reg; |
664 | int value; | 665 | int value; |
665 | unsigned int write_post; | 666 | unsigned int write_post; |
666 | unsigned long flags; | 667 | unsigned long flags; |
667 | const struct firmware *fw_entry = emu->firmware; | ||
668 | 668 | ||
669 | if (!fw_entry) | 669 | if (!fw_entry) |
670 | return -EIO; | 670 | return -EIO; |
@@ -725,9 +725,34 @@ static int emu1010_firmware_thread(void *data) | |||
725 | /* Return to Audio Dock programming mode */ | 725 | /* Return to Audio Dock programming mode */ |
726 | snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n"); | 726 | snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n"); |
727 | snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK); | 727 | snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK); |
728 | err = snd_emu1010_load_firmware(emu); | 728 | |
729 | if (err != 0) | 729 | if (!emu->dock_fw) { |
730 | continue; | 730 | const char *filename = NULL; |
731 | switch (emu->card_capabilities->emu_model) { | ||
732 | case EMU_MODEL_EMU1010: | ||
733 | filename = DOCK_FILENAME; | ||
734 | break; | ||
735 | case EMU_MODEL_EMU1010B: | ||
736 | filename = MICRO_DOCK_FILENAME; | ||
737 | break; | ||
738 | case EMU_MODEL_EMU1616: | ||
739 | filename = MICRO_DOCK_FILENAME; | ||
740 | break; | ||
741 | } | ||
742 | if (filename) { | ||
743 | err = request_firmware(&emu->dock_fw, | ||
744 | filename, | ||
745 | &emu->pci->dev); | ||
746 | if (err) | ||
747 | continue; | ||
748 | } | ||
749 | } | ||
750 | |||
751 | if (emu->dock_fw) { | ||
752 | err = snd_emu1010_load_firmware(emu, emu->dock_fw); | ||
753 | if (err) | ||
754 | continue; | ||
755 | } | ||
731 | 756 | ||
732 | snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0); | 757 | snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0); |
733 | snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, ®); | 758 | snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, ®); |
@@ -862,7 +887,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) | |||
862 | filename, emu->firmware->size); | 887 | filename, emu->firmware->size); |
863 | } | 888 | } |
864 | 889 | ||
865 | err = snd_emu1010_load_firmware(emu); | 890 | err = snd_emu1010_load_firmware(emu, emu->firmware); |
866 | if (err != 0) { | 891 | if (err != 0) { |
867 | snd_printk(KERN_INFO "emu1010: Loading Firmware failed\n"); | 892 | snd_printk(KERN_INFO "emu1010: Loading Firmware failed\n"); |
868 | return err; | 893 | return err; |
@@ -1253,6 +1278,8 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu) | |||
1253 | kthread_stop(emu->emu1010.firmware_thread); | 1278 | kthread_stop(emu->emu1010.firmware_thread); |
1254 | if (emu->firmware) | 1279 | if (emu->firmware) |
1255 | release_firmware(emu->firmware); | 1280 | release_firmware(emu->firmware); |
1281 | if (emu->dock_fw) | ||
1282 | release_firmware(emu->dock_fw); | ||
1256 | if (emu->irq >= 0) | 1283 | if (emu->irq >= 0) |
1257 | free_irq(emu->irq, emu); | 1284 | free_irq(emu->irq, emu); |
1258 | /* remove reserved page */ | 1285 | /* remove reserved page */ |
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c index a3ea76a4c9d2..7c11d46b84d3 100644 --- a/sound/pci/hda/hda_auto_parser.c +++ b/sound/pci/hda/hda_auto_parser.c | |||
@@ -119,6 +119,32 @@ static bool check_pincap_validity(struct hda_codec *codec, hda_nid_t pin, | |||
119 | } | 119 | } |
120 | } | 120 | } |
121 | 121 | ||
122 | static bool can_be_headset_mic(struct hda_codec *codec, | ||
123 | struct auto_pin_cfg_item *item, | ||
124 | int seq_number) | ||
125 | { | ||
126 | int attr; | ||
127 | unsigned int def_conf; | ||
128 | if (item->type != AUTO_PIN_MIC) | ||
129 | return false; | ||
130 | |||
131 | if (item->is_headset_mic || item->is_headphone_mic) | ||
132 | return false; /* Already assigned */ | ||
133 | |||
134 | def_conf = snd_hda_codec_get_pincfg(codec, item->pin); | ||
135 | attr = snd_hda_get_input_pin_attr(def_conf); | ||
136 | if (attr <= INPUT_PIN_ATTR_DOCK) | ||
137 | return false; | ||
138 | |||
139 | if (seq_number >= 0) { | ||
140 | int seq = get_defcfg_sequence(def_conf); | ||
141 | if (seq != seq_number) | ||
142 | return false; | ||
143 | } | ||
144 | |||
145 | return true; | ||
146 | } | ||
147 | |||
122 | /* | 148 | /* |
123 | * Parse all pin widgets and store the useful pin nids to cfg | 149 | * Parse all pin widgets and store the useful pin nids to cfg |
124 | * | 150 | * |
@@ -260,6 +286,38 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, | |||
260 | } | 286 | } |
261 | } | 287 | } |
262 | 288 | ||
289 | /* Find a pin that could be a headset or headphone mic */ | ||
290 | if (cond_flags & HDA_PINCFG_HEADSET_MIC || cond_flags & HDA_PINCFG_HEADPHONE_MIC) { | ||
291 | bool hsmic = !!(cond_flags & HDA_PINCFG_HEADSET_MIC); | ||
292 | bool hpmic = !!(cond_flags & HDA_PINCFG_HEADPHONE_MIC); | ||
293 | for (i = 0; (hsmic || hpmic) && (i < cfg->num_inputs); i++) | ||
294 | if (hsmic && can_be_headset_mic(codec, &cfg->inputs[i], 0xc)) { | ||
295 | cfg->inputs[i].is_headset_mic = 1; | ||
296 | hsmic = false; | ||
297 | } else if (hpmic && can_be_headset_mic(codec, &cfg->inputs[i], 0xd)) { | ||
298 | cfg->inputs[i].is_headphone_mic = 1; | ||
299 | hpmic = false; | ||
300 | } | ||
301 | |||
302 | /* If we didn't find our sequence number mark, fall back to any sequence number */ | ||
303 | for (i = 0; (hsmic || hpmic) && (i < cfg->num_inputs); i++) { | ||
304 | if (!can_be_headset_mic(codec, &cfg->inputs[i], -1)) | ||
305 | continue; | ||
306 | if (hsmic) { | ||
307 | cfg->inputs[i].is_headset_mic = 1; | ||
308 | hsmic = false; | ||
309 | } else if (hpmic) { | ||
310 | cfg->inputs[i].is_headphone_mic = 1; | ||
311 | hpmic = false; | ||
312 | } | ||
313 | } | ||
314 | |||
315 | if (hsmic) | ||
316 | snd_printdd("Told to look for a headset mic, but didn't find any.\n"); | ||
317 | if (hpmic) | ||
318 | snd_printdd("Told to look for a headphone mic, but didn't find any.\n"); | ||
319 | } | ||
320 | |||
263 | /* FIX-UP: | 321 | /* FIX-UP: |
264 | * If no line-out is defined but multiple HPs are found, | 322 | * If no line-out is defined but multiple HPs are found, |
265 | * some of them might be the real line-outs. | 323 | * some of them might be the real line-outs. |
@@ -388,6 +446,7 @@ EXPORT_SYMBOL_HDA(snd_hda_get_input_pin_attr); | |||
388 | */ | 446 | */ |
389 | 447 | ||
390 | static const char *hda_get_input_pin_label(struct hda_codec *codec, | 448 | static const char *hda_get_input_pin_label(struct hda_codec *codec, |
449 | const struct auto_pin_cfg_item *item, | ||
391 | hda_nid_t pin, bool check_location) | 450 | hda_nid_t pin, bool check_location) |
392 | { | 451 | { |
393 | unsigned int def_conf; | 452 | unsigned int def_conf; |
@@ -400,6 +459,10 @@ static const char *hda_get_input_pin_label(struct hda_codec *codec, | |||
400 | 459 | ||
401 | switch (get_defcfg_device(def_conf)) { | 460 | switch (get_defcfg_device(def_conf)) { |
402 | case AC_JACK_MIC_IN: | 461 | case AC_JACK_MIC_IN: |
462 | if (item && item->is_headset_mic) | ||
463 | return "Headset Mic"; | ||
464 | if (item && item->is_headphone_mic) | ||
465 | return "Headphone Mic"; | ||
403 | if (!check_location) | 466 | if (!check_location) |
404 | return "Mic"; | 467 | return "Mic"; |
405 | attr = snd_hda_get_input_pin_attr(def_conf); | 468 | attr = snd_hda_get_input_pin_attr(def_conf); |
@@ -480,7 +543,8 @@ const char *hda_get_autocfg_input_label(struct hda_codec *codec, | |||
480 | has_multiple_pins = 1; | 543 | has_multiple_pins = 1; |
481 | if (has_multiple_pins && type == AUTO_PIN_MIC) | 544 | if (has_multiple_pins && type == AUTO_PIN_MIC) |
482 | has_multiple_pins &= check_mic_location_need(codec, cfg, input); | 545 | has_multiple_pins &= check_mic_location_need(codec, cfg, input); |
483 | return hda_get_input_pin_label(codec, cfg->inputs[input].pin, | 546 | return hda_get_input_pin_label(codec, &cfg->inputs[input], |
547 | cfg->inputs[input].pin, | ||
484 | has_multiple_pins); | 548 | has_multiple_pins); |
485 | } | 549 | } |
486 | EXPORT_SYMBOL_HDA(hda_get_autocfg_input_label); | 550 | EXPORT_SYMBOL_HDA(hda_get_autocfg_input_label); |
@@ -649,7 +713,7 @@ int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid, | |||
649 | } | 713 | } |
650 | } | 714 | } |
651 | if (!name) | 715 | if (!name) |
652 | name = hda_get_input_pin_label(codec, nid, true); | 716 | name = hda_get_input_pin_label(codec, NULL, nid, true); |
653 | break; | 717 | break; |
654 | } | 718 | } |
655 | if (!name) | 719 | if (!name) |
diff --git a/sound/pci/hda/hda_auto_parser.h b/sound/pci/hda/hda_auto_parser.h index f74807138b49..e941f604f5e5 100644 --- a/sound/pci/hda/hda_auto_parser.h +++ b/sound/pci/hda/hda_auto_parser.h | |||
@@ -36,6 +36,8 @@ enum { | |||
36 | struct auto_pin_cfg_item { | 36 | struct auto_pin_cfg_item { |
37 | hda_nid_t pin; | 37 | hda_nid_t pin; |
38 | int type; | 38 | int type; |
39 | unsigned int is_headset_mic:1; | ||
40 | unsigned int is_headphone_mic:1; /* Mic-only in headphone jack */ | ||
39 | }; | 41 | }; |
40 | 42 | ||
41 | struct auto_pin_cfg; | 43 | struct auto_pin_cfg; |
@@ -78,8 +80,10 @@ struct auto_pin_cfg { | |||
78 | }; | 80 | }; |
79 | 81 | ||
80 | /* bit-flags for snd_hda_parse_pin_def_config() behavior */ | 82 | /* bit-flags for snd_hda_parse_pin_def_config() behavior */ |
81 | #define HDA_PINCFG_NO_HP_FIXUP (1 << 0) /* no HP-split */ | 83 | #define HDA_PINCFG_NO_HP_FIXUP (1 << 0) /* no HP-split */ |
82 | #define HDA_PINCFG_NO_LO_FIXUP (1 << 1) /* don't take other outs as LO */ | 84 | #define HDA_PINCFG_NO_LO_FIXUP (1 << 1) /* don't take other outs as LO */ |
85 | #define HDA_PINCFG_HEADSET_MIC (1 << 2) /* Try to find headset mic; mark seq number as 0xc to trigger */ | ||
86 | #define HDA_PINCFG_HEADPHONE_MIC (1 << 3) /* Try to find headphone mic; mark seq number as 0xd to trigger */ | ||
83 | 87 | ||
84 | int snd_hda_parse_pin_defcfg(struct hda_codec *codec, | 88 | int snd_hda_parse_pin_defcfg(struct hda_codec *codec, |
85 | struct auto_pin_cfg *cfg, | 89 | struct auto_pin_cfg *cfg, |
@@ -90,4 +94,25 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, | |||
90 | #define snd_hda_parse_pin_def_config(codec, cfg, ignore) \ | 94 | #define snd_hda_parse_pin_def_config(codec, cfg, ignore) \ |
91 | snd_hda_parse_pin_defcfg(codec, cfg, ignore, 0) | 95 | snd_hda_parse_pin_defcfg(codec, cfg, ignore, 0) |
92 | 96 | ||
97 | static inline int auto_cfg_hp_outs(const struct auto_pin_cfg *cfg) | ||
98 | { | ||
99 | return (cfg->line_out_type == AUTO_PIN_HP_OUT) ? | ||
100 | cfg->line_outs : cfg->hp_outs; | ||
101 | } | ||
102 | static inline const hda_nid_t *auto_cfg_hp_pins(const struct auto_pin_cfg *cfg) | ||
103 | { | ||
104 | return (cfg->line_out_type == AUTO_PIN_HP_OUT) ? | ||
105 | cfg->line_out_pins : cfg->hp_pins; | ||
106 | } | ||
107 | static inline int auto_cfg_speaker_outs(const struct auto_pin_cfg *cfg) | ||
108 | { | ||
109 | return (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) ? | ||
110 | cfg->line_outs : cfg->speaker_outs; | ||
111 | } | ||
112 | static inline const hda_nid_t *auto_cfg_speaker_pins(const struct auto_pin_cfg *cfg) | ||
113 | { | ||
114 | return (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) ? | ||
115 | cfg->line_out_pins : cfg->speaker_pins; | ||
116 | } | ||
117 | |||
93 | #endif /* __SOUND_HDA_AUTO_PARSER_H */ | 118 | #endif /* __SOUND_HDA_AUTO_PARSER_H */ |
diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index 0849aac449f2..63c99090a4ec 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c | |||
@@ -39,13 +39,23 @@ static void snd_hda_generate_beep(struct work_struct *work) | |||
39 | struct hda_beep *beep = | 39 | struct hda_beep *beep = |
40 | container_of(work, struct hda_beep, beep_work); | 40 | container_of(work, struct hda_beep, beep_work); |
41 | struct hda_codec *codec = beep->codec; | 41 | struct hda_codec *codec = beep->codec; |
42 | int tone; | ||
42 | 43 | ||
43 | if (!beep->enabled) | 44 | if (!beep->enabled) |
44 | return; | 45 | return; |
45 | 46 | ||
47 | tone = beep->tone; | ||
48 | if (tone && !beep->playing) { | ||
49 | snd_hda_power_up(codec); | ||
50 | beep->playing = 1; | ||
51 | } | ||
46 | /* generate tone */ | 52 | /* generate tone */ |
47 | snd_hda_codec_write(codec, beep->nid, 0, | 53 | snd_hda_codec_write(codec, beep->nid, 0, |
48 | AC_VERB_SET_BEEP_CONTROL, beep->tone); | 54 | AC_VERB_SET_BEEP_CONTROL, tone); |
55 | if (!tone && beep->playing) { | ||
56 | beep->playing = 0; | ||
57 | snd_hda_power_down(codec); | ||
58 | } | ||
49 | } | 59 | } |
50 | 60 | ||
51 | /* (non-standard) Linear beep tone calculation for IDT/STAC codecs | 61 | /* (non-standard) Linear beep tone calculation for IDT/STAC codecs |
@@ -115,14 +125,23 @@ static int snd_hda_beep_event(struct input_dev *dev, unsigned int type, | |||
115 | return 0; | 125 | return 0; |
116 | } | 126 | } |
117 | 127 | ||
128 | static void turn_off_beep(struct hda_beep *beep) | ||
129 | { | ||
130 | cancel_work_sync(&beep->beep_work); | ||
131 | if (beep->playing) { | ||
132 | /* turn off beep */ | ||
133 | snd_hda_codec_write(beep->codec, beep->nid, 0, | ||
134 | AC_VERB_SET_BEEP_CONTROL, 0); | ||
135 | beep->playing = 0; | ||
136 | snd_hda_power_down(beep->codec); | ||
137 | } | ||
138 | } | ||
139 | |||
118 | static void snd_hda_do_detach(struct hda_beep *beep) | 140 | static void snd_hda_do_detach(struct hda_beep *beep) |
119 | { | 141 | { |
120 | input_unregister_device(beep->dev); | 142 | input_unregister_device(beep->dev); |
121 | beep->dev = NULL; | 143 | beep->dev = NULL; |
122 | cancel_work_sync(&beep->beep_work); | 144 | turn_off_beep(beep); |
123 | /* turn off beep for sure */ | ||
124 | snd_hda_codec_write(beep->codec, beep->nid, 0, | ||
125 | AC_VERB_SET_BEEP_CONTROL, 0); | ||
126 | } | 145 | } |
127 | 146 | ||
128 | static int snd_hda_do_attach(struct hda_beep *beep) | 147 | static int snd_hda_do_attach(struct hda_beep *beep) |
@@ -170,12 +189,8 @@ int snd_hda_enable_beep_device(struct hda_codec *codec, int enable) | |||
170 | enable = !!enable; | 189 | enable = !!enable; |
171 | if (beep->enabled != enable) { | 190 | if (beep->enabled != enable) { |
172 | beep->enabled = enable; | 191 | beep->enabled = enable; |
173 | if (!enable) { | 192 | if (!enable) |
174 | cancel_work_sync(&beep->beep_work); | 193 | turn_off_beep(beep); |
175 | /* turn off beep */ | ||
176 | snd_hda_codec_write(beep->codec, beep->nid, 0, | ||
177 | AC_VERB_SET_BEEP_CONTROL, 0); | ||
178 | } | ||
179 | return 1; | 194 | return 1; |
180 | } | 195 | } |
181 | return 0; | 196 | return 0; |
@@ -198,7 +213,7 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) | |||
198 | snprintf(beep->phys, sizeof(beep->phys), | 213 | snprintf(beep->phys, sizeof(beep->phys), |
199 | "card%d/codec#%d/beep0", codec->bus->card->number, codec->addr); | 214 | "card%d/codec#%d/beep0", codec->bus->card->number, codec->addr); |
200 | /* enable linear scale */ | 215 | /* enable linear scale */ |
201 | snd_hda_codec_write(codec, nid, 0, | 216 | snd_hda_codec_write_cache(codec, nid, 0, |
202 | AC_VERB_SET_DIGI_CONVERT_2, 0x01); | 217 | AC_VERB_SET_DIGI_CONVERT_2, 0x01); |
203 | 218 | ||
204 | beep->nid = nid; | 219 | beep->nid = nid; |
diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h index 4dc6933bc655..cb88464676b6 100644 --- a/sound/pci/hda/hda_beep.h +++ b/sound/pci/hda/hda_beep.h | |||
@@ -36,6 +36,7 @@ struct hda_beep { | |||
36 | hda_nid_t nid; | 36 | hda_nid_t nid; |
37 | unsigned int enabled:1; | 37 | unsigned int enabled:1; |
38 | unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */ | 38 | unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */ |
39 | unsigned int playing:1; | ||
39 | struct work_struct beep_work; /* scheduled task for beep event */ | 40 | struct work_struct beep_work; /* scheduled task for beep event */ |
40 | struct mutex mutex; | 41 | struct mutex mutex; |
41 | }; | 42 | }; |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 4aba7646dd9c..6f9b64700f6e 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -1065,8 +1065,14 @@ int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list, | |||
1065 | { | 1065 | { |
1066 | struct hda_pincfg *pin; | 1066 | struct hda_pincfg *pin; |
1067 | 1067 | ||
1068 | /* the check below may be invalid when pins are added by a fixup | ||
1069 | * dynamically (e.g. via snd_hda_codec_update_widgets()), so disabled | ||
1070 | * for now | ||
1071 | */ | ||
1072 | /* | ||
1068 | if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN) | 1073 | if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN) |
1069 | return -EINVAL; | 1074 | return -EINVAL; |
1075 | */ | ||
1070 | 1076 | ||
1071 | pin = look_up_pincfg(codec, list, nid); | 1077 | pin = look_up_pincfg(codec, list, nid); |
1072 | if (!pin) { | 1078 | if (!pin) { |
@@ -1300,8 +1306,6 @@ static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec, | |||
1300 | 1306 | ||
1301 | static unsigned int hda_set_power_state(struct hda_codec *codec, | 1307 | static unsigned int hda_set_power_state(struct hda_codec *codec, |
1302 | unsigned int power_state); | 1308 | unsigned int power_state); |
1303 | static unsigned int default_power_filter(struct hda_codec *codec, hda_nid_t nid, | ||
1304 | unsigned int power_state); | ||
1305 | 1309 | ||
1306 | /** | 1310 | /** |
1307 | * snd_hda_codec_new - create a HDA codec | 1311 | * snd_hda_codec_new - create a HDA codec |
@@ -1422,7 +1426,6 @@ int snd_hda_codec_new(struct hda_bus *bus, | |||
1422 | #endif | 1426 | #endif |
1423 | codec->epss = snd_hda_codec_get_supported_ps(codec, fg, | 1427 | codec->epss = snd_hda_codec_get_supported_ps(codec, fg, |
1424 | AC_PWRST_EPSS); | 1428 | AC_PWRST_EPSS); |
1425 | codec->power_filter = default_power_filter; | ||
1426 | 1429 | ||
1427 | /* power-up all before initialization */ | 1430 | /* power-up all before initialization */ |
1428 | hda_set_power_state(codec, AC_PWRST_D0); | 1431 | hda_set_power_state(codec, AC_PWRST_D0); |
@@ -2787,6 +2790,11 @@ void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook) | |||
2787 | { | 2790 | { |
2788 | if (!hook->hook || !hook->codec) | 2791 | if (!hook->hook || !hook->codec) |
2789 | return; | 2792 | return; |
2793 | /* don't call vmaster hook in the destructor since it might have | ||
2794 | * been already destroyed | ||
2795 | */ | ||
2796 | if (hook->codec->bus->shutdown) | ||
2797 | return; | ||
2790 | switch (hook->mute_mode) { | 2798 | switch (hook->mute_mode) { |
2791 | case HDA_VMUTE_FOLLOW_MASTER: | 2799 | case HDA_VMUTE_FOLLOW_MASTER: |
2792 | snd_ctl_sync_vmaster_hook(hook->sw_kctl); | 2800 | snd_ctl_sync_vmaster_hook(hook->sw_kctl); |
@@ -3770,8 +3778,9 @@ static unsigned int hda_sync_power_state(struct hda_codec *codec, | |||
3770 | } | 3778 | } |
3771 | 3779 | ||
3772 | /* don't power down the widget if it controls eapd and EAPD_BTLENABLE is set */ | 3780 | /* don't power down the widget if it controls eapd and EAPD_BTLENABLE is set */ |
3773 | static unsigned int default_power_filter(struct hda_codec *codec, hda_nid_t nid, | 3781 | unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec, |
3774 | unsigned int power_state) | 3782 | hda_nid_t nid, |
3783 | unsigned int power_state) | ||
3775 | { | 3784 | { |
3776 | if (power_state == AC_PWRST_D3 && | 3785 | if (power_state == AC_PWRST_D3 && |
3777 | get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_PIN && | 3786 | get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_PIN && |
@@ -3783,6 +3792,7 @@ static unsigned int default_power_filter(struct hda_codec *codec, hda_nid_t nid, | |||
3783 | } | 3792 | } |
3784 | return power_state; | 3793 | return power_state; |
3785 | } | 3794 | } |
3795 | EXPORT_SYMBOL_HDA(snd_hda_codec_eapd_power_filter); | ||
3786 | 3796 | ||
3787 | /* | 3797 | /* |
3788 | * set power state of the codec, and return the power state | 3798 | * set power state of the codec, and return the power state |
@@ -3827,8 +3837,8 @@ static void sync_power_up_states(struct hda_codec *codec) | |||
3827 | hda_nid_t nid = codec->start_nid; | 3837 | hda_nid_t nid = codec->start_nid; |
3828 | int i; | 3838 | int i; |
3829 | 3839 | ||
3830 | /* don't care if no or standard filter is used */ | 3840 | /* don't care if no filter is used */ |
3831 | if (!codec->power_filter || codec->power_filter == default_power_filter) | 3841 | if (!codec->power_filter) |
3832 | return; | 3842 | return; |
3833 | 3843 | ||
3834 | for (i = 0; i < codec->num_nodes; i++, nid++) { | 3844 | for (i = 0; i < codec->num_nodes; i++, nid++) { |
@@ -5546,14 +5556,12 @@ void *snd_array_new(struct snd_array *array) | |||
5546 | if (array->used >= array->alloced) { | 5556 | if (array->used >= array->alloced) { |
5547 | int num = array->alloced + array->alloc_align; | 5557 | int num = array->alloced + array->alloc_align; |
5548 | int size = (num + 1) * array->elem_size; | 5558 | int size = (num + 1) * array->elem_size; |
5549 | int oldsize = array->alloced * array->elem_size; | ||
5550 | void *nlist; | 5559 | void *nlist; |
5551 | if (snd_BUG_ON(num >= 4096)) | 5560 | if (snd_BUG_ON(num >= 4096)) |
5552 | return NULL; | 5561 | return NULL; |
5553 | nlist = krealloc(array->list, size, GFP_KERNEL); | 5562 | nlist = krealloc(array->list, size, GFP_KERNEL | __GFP_ZERO); |
5554 | if (!nlist) | 5563 | if (!nlist) |
5555 | return NULL; | 5564 | return NULL; |
5556 | memset(nlist + oldsize, 0, size - oldsize); | ||
5557 | array->list = nlist; | 5565 | array->list = nlist; |
5558 | array->alloced = num; | 5566 | array->alloced = num; |
5559 | } | 5567 | } |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 23ca1722aff1..c93f9021f452 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -757,6 +757,9 @@ struct hda_pcm_ops { | |||
757 | struct snd_pcm_substream *substream); | 757 | struct snd_pcm_substream *substream); |
758 | int (*cleanup)(struct hda_pcm_stream *info, struct hda_codec *codec, | 758 | int (*cleanup)(struct hda_pcm_stream *info, struct hda_codec *codec, |
759 | struct snd_pcm_substream *substream); | 759 | struct snd_pcm_substream *substream); |
760 | unsigned int (*get_delay)(struct hda_pcm_stream *info, | ||
761 | struct hda_codec *codec, | ||
762 | struct snd_pcm_substream *substream); | ||
760 | }; | 763 | }; |
761 | 764 | ||
762 | /* PCM information for each substream */ | 765 | /* PCM information for each substream */ |
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 2dbe767be16b..ac079f93c535 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include "hda_local.h" | 34 | #include "hda_local.h" |
35 | #include "hda_auto_parser.h" | 35 | #include "hda_auto_parser.h" |
36 | #include "hda_jack.h" | 36 | #include "hda_jack.h" |
37 | #include "hda_beep.h" | ||
37 | #include "hda_generic.h" | 38 | #include "hda_generic.h" |
38 | 39 | ||
39 | 40 | ||
@@ -150,15 +151,25 @@ static void parse_user_hints(struct hda_codec *codec) | |||
150 | val = snd_hda_get_bool_hint(codec, "add_stereo_mix_input"); | 151 | val = snd_hda_get_bool_hint(codec, "add_stereo_mix_input"); |
151 | if (val >= 0) | 152 | if (val >= 0) |
152 | spec->add_stereo_mix_input = !!val; | 153 | spec->add_stereo_mix_input = !!val; |
154 | /* the following two are just for compatibility */ | ||
153 | val = snd_hda_get_bool_hint(codec, "add_out_jack_modes"); | 155 | val = snd_hda_get_bool_hint(codec, "add_out_jack_modes"); |
154 | if (val >= 0) | 156 | if (val >= 0) |
155 | spec->add_out_jack_modes = !!val; | 157 | spec->add_jack_modes = !!val; |
156 | val = snd_hda_get_bool_hint(codec, "add_in_jack_modes"); | 158 | val = snd_hda_get_bool_hint(codec, "add_in_jack_modes"); |
157 | if (val >= 0) | 159 | if (val >= 0) |
158 | spec->add_in_jack_modes = !!val; | 160 | spec->add_jack_modes = !!val; |
161 | val = snd_hda_get_bool_hint(codec, "add_jack_modes"); | ||
162 | if (val >= 0) | ||
163 | spec->add_jack_modes = !!val; | ||
159 | val = snd_hda_get_bool_hint(codec, "power_down_unused"); | 164 | val = snd_hda_get_bool_hint(codec, "power_down_unused"); |
160 | if (val >= 0) | 165 | if (val >= 0) |
161 | spec->power_down_unused = !!val; | 166 | spec->power_down_unused = !!val; |
167 | val = snd_hda_get_bool_hint(codec, "add_hp_mic"); | ||
168 | if (val >= 0) | ||
169 | spec->hp_mic = !!val; | ||
170 | val = snd_hda_get_bool_hint(codec, "hp_mic_detect"); | ||
171 | if (val >= 0) | ||
172 | spec->suppress_hp_mic_detect = !val; | ||
162 | 173 | ||
163 | if (!snd_hda_get_int_hint(codec, "mixer_nid", &val)) | 174 | if (!snd_hda_get_int_hint(codec, "mixer_nid", &val)) |
164 | spec->mixer_nid = val; | 175 | spec->mixer_nid = val; |
@@ -996,7 +1007,7 @@ enum { | |||
996 | /* Primary DAC shared with main surrounds */ | 1007 | /* Primary DAC shared with main surrounds */ |
997 | BAD_SHARED_SURROUND = 0x100, | 1008 | BAD_SHARED_SURROUND = 0x100, |
998 | /* No independent HP possible */ | 1009 | /* No independent HP possible */ |
999 | BAD_NO_INDEP_HP = 0x40, | 1010 | BAD_NO_INDEP_HP = 0x10, |
1000 | /* Primary DAC shared with main CLFE */ | 1011 | /* Primary DAC shared with main CLFE */ |
1001 | BAD_SHARED_CLFE = 0x10, | 1012 | BAD_SHARED_CLFE = 0x10, |
1002 | /* Primary DAC shared with extra surrounds */ | 1013 | /* Primary DAC shared with extra surrounds */ |
@@ -1051,16 +1062,7 @@ static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path) | |||
1051 | return badness; | 1062 | return badness; |
1052 | } | 1063 | } |
1053 | 1064 | ||
1054 | struct badness_table { | 1065 | const struct badness_table hda_main_out_badness = { |
1055 | int no_primary_dac; /* no primary DAC */ | ||
1056 | int no_dac; /* no secondary DACs */ | ||
1057 | int shared_primary; /* primary DAC is shared with main output */ | ||
1058 | int shared_surr; /* secondary DAC shared with main or primary */ | ||
1059 | int shared_clfe; /* third DAC shared with main or primary */ | ||
1060 | int shared_surr_main; /* secondary DAC sahred with main/DAC0 */ | ||
1061 | }; | ||
1062 | |||
1063 | static struct badness_table main_out_badness = { | ||
1064 | .no_primary_dac = BAD_NO_PRIMARY_DAC, | 1066 | .no_primary_dac = BAD_NO_PRIMARY_DAC, |
1065 | .no_dac = BAD_NO_DAC, | 1067 | .no_dac = BAD_NO_DAC, |
1066 | .shared_primary = BAD_NO_PRIMARY_DAC, | 1068 | .shared_primary = BAD_NO_PRIMARY_DAC, |
@@ -1068,8 +1070,9 @@ static struct badness_table main_out_badness = { | |||
1068 | .shared_clfe = BAD_SHARED_CLFE, | 1070 | .shared_clfe = BAD_SHARED_CLFE, |
1069 | .shared_surr_main = BAD_SHARED_SURROUND, | 1071 | .shared_surr_main = BAD_SHARED_SURROUND, |
1070 | }; | 1072 | }; |
1073 | EXPORT_SYMBOL_HDA(hda_main_out_badness); | ||
1071 | 1074 | ||
1072 | static struct badness_table extra_out_badness = { | 1075 | const struct badness_table hda_extra_out_badness = { |
1073 | .no_primary_dac = BAD_NO_DAC, | 1076 | .no_primary_dac = BAD_NO_DAC, |
1074 | .no_dac = BAD_NO_DAC, | 1077 | .no_dac = BAD_NO_DAC, |
1075 | .shared_primary = BAD_NO_EXTRA_DAC, | 1078 | .shared_primary = BAD_NO_EXTRA_DAC, |
@@ -1077,6 +1080,7 @@ static struct badness_table extra_out_badness = { | |||
1077 | .shared_clfe = BAD_SHARED_EXTRA_SURROUND, | 1080 | .shared_clfe = BAD_SHARED_EXTRA_SURROUND, |
1078 | .shared_surr_main = BAD_NO_EXTRA_SURR_DAC, | 1081 | .shared_surr_main = BAD_NO_EXTRA_SURR_DAC, |
1079 | }; | 1082 | }; |
1083 | EXPORT_SYMBOL_HDA(hda_extra_out_badness); | ||
1080 | 1084 | ||
1081 | /* get the DAC of the primary output corresponding to the given array index */ | 1085 | /* get the DAC of the primary output corresponding to the given array index */ |
1082 | static hda_nid_t get_primary_out(struct hda_codec *codec, int idx) | 1086 | static hda_nid_t get_primary_out(struct hda_codec *codec, int idx) |
@@ -1367,22 +1371,25 @@ static int check_aamix_out_path(struct hda_codec *codec, int path_idx) | |||
1367 | { | 1371 | { |
1368 | struct hda_gen_spec *spec = codec->spec; | 1372 | struct hda_gen_spec *spec = codec->spec; |
1369 | struct nid_path *path; | 1373 | struct nid_path *path; |
1370 | hda_nid_t dac, pin; | 1374 | hda_nid_t path_dac, dac, pin; |
1371 | 1375 | ||
1372 | path = snd_hda_get_path_from_idx(codec, path_idx); | 1376 | path = snd_hda_get_path_from_idx(codec, path_idx); |
1373 | if (!path || !path->depth || | 1377 | if (!path || !path->depth || |
1374 | is_nid_contained(path, spec->mixer_nid)) | 1378 | is_nid_contained(path, spec->mixer_nid)) |
1375 | return 0; | 1379 | return 0; |
1376 | dac = path->path[0]; | 1380 | path_dac = path->path[0]; |
1381 | dac = spec->private_dac_nids[0]; | ||
1377 | pin = path->path[path->depth - 1]; | 1382 | pin = path->path[path->depth - 1]; |
1378 | path = snd_hda_add_new_path(codec, dac, pin, spec->mixer_nid); | 1383 | path = snd_hda_add_new_path(codec, dac, pin, spec->mixer_nid); |
1379 | if (!path) { | 1384 | if (!path) { |
1380 | if (dac != spec->multiout.dac_nids[0]) | 1385 | if (dac != path_dac) |
1381 | dac = spec->multiout.dac_nids[0]; | 1386 | dac = path_dac; |
1382 | else if (spec->multiout.hp_out_nid[0]) | 1387 | else if (spec->multiout.hp_out_nid[0]) |
1383 | dac = spec->multiout.hp_out_nid[0]; | 1388 | dac = spec->multiout.hp_out_nid[0]; |
1384 | else if (spec->multiout.extra_out_nid[0]) | 1389 | else if (spec->multiout.extra_out_nid[0]) |
1385 | dac = spec->multiout.extra_out_nid[0]; | 1390 | dac = spec->multiout.extra_out_nid[0]; |
1391 | else | ||
1392 | dac = 0; | ||
1386 | if (dac) | 1393 | if (dac) |
1387 | path = snd_hda_add_new_path(codec, dac, pin, | 1394 | path = snd_hda_add_new_path(codec, dac, pin, |
1388 | spec->mixer_nid); | 1395 | spec->mixer_nid); |
@@ -1507,7 +1514,7 @@ static int fill_and_eval_dacs(struct hda_codec *codec, | |||
1507 | 1514 | ||
1508 | badness += try_assign_dacs(codec, cfg->line_outs, cfg->line_out_pins, | 1515 | badness += try_assign_dacs(codec, cfg->line_outs, cfg->line_out_pins, |
1509 | spec->private_dac_nids, spec->out_paths, | 1516 | spec->private_dac_nids, spec->out_paths, |
1510 | &main_out_badness); | 1517 | spec->main_out_badness); |
1511 | 1518 | ||
1512 | if (fill_mio_first && | 1519 | if (fill_mio_first && |
1513 | cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { | 1520 | cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { |
@@ -1522,7 +1529,7 @@ static int fill_and_eval_dacs(struct hda_codec *codec, | |||
1522 | err = try_assign_dacs(codec, cfg->hp_outs, cfg->hp_pins, | 1529 | err = try_assign_dacs(codec, cfg->hp_outs, cfg->hp_pins, |
1523 | spec->multiout.hp_out_nid, | 1530 | spec->multiout.hp_out_nid, |
1524 | spec->hp_paths, | 1531 | spec->hp_paths, |
1525 | &extra_out_badness); | 1532 | spec->extra_out_badness); |
1526 | if (err < 0) | 1533 | if (err < 0) |
1527 | return err; | 1534 | return err; |
1528 | badness += err; | 1535 | badness += err; |
@@ -1532,7 +1539,7 @@ static int fill_and_eval_dacs(struct hda_codec *codec, | |||
1532 | cfg->speaker_pins, | 1539 | cfg->speaker_pins, |
1533 | spec->multiout.extra_out_nid, | 1540 | spec->multiout.extra_out_nid, |
1534 | spec->speaker_paths, | 1541 | spec->speaker_paths, |
1535 | &extra_out_badness); | 1542 | spec->extra_out_badness); |
1536 | if (err < 0) | 1543 | if (err < 0) |
1537 | return err; | 1544 | return err; |
1538 | badness += err; | 1545 | badness += err; |
@@ -1926,6 +1933,17 @@ static int create_speaker_out_ctls(struct hda_codec *codec) | |||
1926 | * independent HP controls | 1933 | * independent HP controls |
1927 | */ | 1934 | */ |
1928 | 1935 | ||
1936 | /* update HP auto-mute state too */ | ||
1937 | static void update_hp_automute_hook(struct hda_codec *codec) | ||
1938 | { | ||
1939 | struct hda_gen_spec *spec = codec->spec; | ||
1940 | |||
1941 | if (spec->hp_automute_hook) | ||
1942 | spec->hp_automute_hook(codec, NULL); | ||
1943 | else | ||
1944 | snd_hda_gen_hp_automute(codec, NULL); | ||
1945 | } | ||
1946 | |||
1929 | static int indep_hp_info(struct snd_kcontrol *kcontrol, | 1947 | static int indep_hp_info(struct snd_kcontrol *kcontrol, |
1930 | struct snd_ctl_elem_info *uinfo) | 1948 | struct snd_ctl_elem_info *uinfo) |
1931 | { | 1949 | { |
@@ -1986,12 +2004,7 @@ static int indep_hp_put(struct snd_kcontrol *kcontrol, | |||
1986 | else | 2004 | else |
1987 | *dacp = spec->alt_dac_nid; | 2005 | *dacp = spec->alt_dac_nid; |
1988 | 2006 | ||
1989 | /* update HP auto-mute state too */ | 2007 | update_hp_automute_hook(codec); |
1990 | if (spec->hp_automute_hook) | ||
1991 | spec->hp_automute_hook(codec, NULL); | ||
1992 | else | ||
1993 | snd_hda_gen_hp_automute(codec, NULL); | ||
1994 | |||
1995 | ret = 1; | 2008 | ret = 1; |
1996 | } | 2009 | } |
1997 | unlock: | 2010 | unlock: |
@@ -2072,6 +2085,14 @@ get_multiio_path(struct hda_codec *codec, int idx) | |||
2072 | 2085 | ||
2073 | static void update_automute_all(struct hda_codec *codec); | 2086 | static void update_automute_all(struct hda_codec *codec); |
2074 | 2087 | ||
2088 | /* Default value to be passed as aamix argument for snd_hda_activate_path(); | ||
2089 | * used for output paths | ||
2090 | */ | ||
2091 | static bool aamix_default(struct hda_gen_spec *spec) | ||
2092 | { | ||
2093 | return !spec->have_aamix_ctl || spec->aamix_mode; | ||
2094 | } | ||
2095 | |||
2075 | static int set_multi_io(struct hda_codec *codec, int idx, bool output) | 2096 | static int set_multi_io(struct hda_codec *codec, int idx, bool output) |
2076 | { | 2097 | { |
2077 | struct hda_gen_spec *spec = codec->spec; | 2098 | struct hda_gen_spec *spec = codec->spec; |
@@ -2087,11 +2108,11 @@ static int set_multi_io(struct hda_codec *codec, int idx, bool output) | |||
2087 | 2108 | ||
2088 | if (output) { | 2109 | if (output) { |
2089 | set_pin_target(codec, nid, PIN_OUT, true); | 2110 | set_pin_target(codec, nid, PIN_OUT, true); |
2090 | snd_hda_activate_path(codec, path, true, true); | 2111 | snd_hda_activate_path(codec, path, true, aamix_default(spec)); |
2091 | set_pin_eapd(codec, nid, true); | 2112 | set_pin_eapd(codec, nid, true); |
2092 | } else { | 2113 | } else { |
2093 | set_pin_eapd(codec, nid, false); | 2114 | set_pin_eapd(codec, nid, false); |
2094 | snd_hda_activate_path(codec, path, false, true); | 2115 | snd_hda_activate_path(codec, path, false, aamix_default(spec)); |
2095 | set_pin_target(codec, nid, spec->multi_io[idx].ctl_in, true); | 2116 | set_pin_target(codec, nid, spec->multi_io[idx].ctl_in, true); |
2096 | path_power_down_sync(codec, path); | 2117 | path_power_down_sync(codec, path); |
2097 | } | 2118 | } |
@@ -2182,8 +2203,8 @@ static void update_aamix_paths(struct hda_codec *codec, bool do_mix, | |||
2182 | snd_hda_activate_path(codec, mix_path, true, true); | 2203 | snd_hda_activate_path(codec, mix_path, true, true); |
2183 | path_power_down_sync(codec, nomix_path); | 2204 | path_power_down_sync(codec, nomix_path); |
2184 | } else { | 2205 | } else { |
2185 | snd_hda_activate_path(codec, mix_path, false, true); | 2206 | snd_hda_activate_path(codec, mix_path, false, false); |
2186 | snd_hda_activate_path(codec, nomix_path, true, true); | 2207 | snd_hda_activate_path(codec, nomix_path, true, false); |
2187 | path_power_down_sync(codec, mix_path); | 2208 | path_power_down_sync(codec, mix_path); |
2188 | } | 2209 | } |
2189 | } | 2210 | } |
@@ -2240,63 +2261,95 @@ static int create_loopback_mixing_ctl(struct hda_codec *codec) | |||
2240 | static void call_update_outputs(struct hda_codec *codec); | 2261 | static void call_update_outputs(struct hda_codec *codec); |
2241 | 2262 | ||
2242 | /* for shared I/O, change the pin-control accordingly */ | 2263 | /* for shared I/O, change the pin-control accordingly */ |
2243 | static void update_shared_mic_hp(struct hda_codec *codec, bool set_as_mic) | 2264 | static void update_hp_mic(struct hda_codec *codec, int adc_mux, bool force) |
2244 | { | 2265 | { |
2245 | struct hda_gen_spec *spec = codec->spec; | 2266 | struct hda_gen_spec *spec = codec->spec; |
2267 | bool as_mic; | ||
2246 | unsigned int val; | 2268 | unsigned int val; |
2247 | hda_nid_t pin = spec->autocfg.inputs[1].pin; | 2269 | hda_nid_t pin; |
2248 | /* NOTE: this assumes that there are only two inputs, the | ||
2249 | * first is the real internal mic and the second is HP/mic jack. | ||
2250 | */ | ||
2251 | 2270 | ||
2252 | val = snd_hda_get_default_vref(codec, pin); | 2271 | pin = spec->hp_mic_pin; |
2272 | as_mic = spec->cur_mux[adc_mux] == spec->hp_mic_mux_idx; | ||
2273 | |||
2274 | if (!force) { | ||
2275 | val = snd_hda_codec_get_pin_target(codec, pin); | ||
2276 | if (as_mic) { | ||
2277 | if (val & PIN_IN) | ||
2278 | return; | ||
2279 | } else { | ||
2280 | if (val & PIN_OUT) | ||
2281 | return; | ||
2282 | } | ||
2283 | } | ||
2253 | 2284 | ||
2254 | /* This pin does not have vref caps - let's enable vref on pin 0x18 | 2285 | val = snd_hda_get_default_vref(codec, pin); |
2255 | instead, as suggested by Realtek */ | 2286 | /* if the HP pin doesn't support VREF and the codec driver gives an |
2287 | * alternative pin, set up the VREF on that pin instead | ||
2288 | */ | ||
2256 | if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) { | 2289 | if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) { |
2257 | const hda_nid_t vref_pin = spec->shared_mic_vref_pin; | 2290 | const hda_nid_t vref_pin = spec->shared_mic_vref_pin; |
2258 | unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin); | 2291 | unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin); |
2259 | if (vref_val != AC_PINCTL_VREF_HIZ) | 2292 | if (vref_val != AC_PINCTL_VREF_HIZ) |
2260 | snd_hda_set_pin_ctl_cache(codec, vref_pin, | 2293 | snd_hda_set_pin_ctl_cache(codec, vref_pin, |
2261 | PIN_IN | (set_as_mic ? vref_val : 0)); | 2294 | PIN_IN | (as_mic ? vref_val : 0)); |
2262 | } | 2295 | } |
2263 | 2296 | ||
2264 | val = set_as_mic ? val | PIN_IN : PIN_HP; | 2297 | if (!spec->hp_mic_jack_modes) { |
2265 | set_pin_target(codec, pin, val, true); | 2298 | if (as_mic) |
2266 | 2299 | val |= PIN_IN; | |
2267 | spec->automute_speaker = !set_as_mic; | 2300 | else |
2268 | call_update_outputs(codec); | 2301 | val = PIN_HP; |
2302 | set_pin_target(codec, pin, val, true); | ||
2303 | update_hp_automute_hook(codec); | ||
2304 | } | ||
2269 | } | 2305 | } |
2270 | 2306 | ||
2271 | /* create a shared input with the headphone out */ | 2307 | /* create a shared input with the headphone out */ |
2272 | static int create_shared_input(struct hda_codec *codec) | 2308 | static int create_hp_mic(struct hda_codec *codec) |
2273 | { | 2309 | { |
2274 | struct hda_gen_spec *spec = codec->spec; | 2310 | struct hda_gen_spec *spec = codec->spec; |
2275 | struct auto_pin_cfg *cfg = &spec->autocfg; | 2311 | struct auto_pin_cfg *cfg = &spec->autocfg; |
2276 | unsigned int defcfg; | 2312 | unsigned int defcfg; |
2277 | hda_nid_t nid; | 2313 | hda_nid_t nid; |
2278 | 2314 | ||
2279 | /* only one internal input pin? */ | 2315 | if (!spec->hp_mic) { |
2280 | if (cfg->num_inputs != 1) | 2316 | if (spec->suppress_hp_mic_detect) |
2281 | return 0; | 2317 | return 0; |
2282 | defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin); | 2318 | /* automatic detection: only if no input or a single internal |
2283 | if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT) | 2319 | * input pin is found, try to detect the shared hp/mic |
2320 | */ | ||
2321 | if (cfg->num_inputs > 1) | ||
2322 | return 0; | ||
2323 | else if (cfg->num_inputs == 1) { | ||
2324 | defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin); | ||
2325 | if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT) | ||
2326 | return 0; | ||
2327 | } | ||
2328 | } | ||
2329 | |||
2330 | spec->hp_mic = 0; /* clear once */ | ||
2331 | if (cfg->num_inputs >= AUTO_CFG_MAX_INS) | ||
2284 | return 0; | 2332 | return 0; |
2285 | 2333 | ||
2286 | if (cfg->hp_outs == 1 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) | 2334 | nid = 0; |
2287 | nid = cfg->hp_pins[0]; /* OK, we have a single HP-out */ | 2335 | if (cfg->line_out_type == AUTO_PIN_HP_OUT && cfg->line_outs > 0) |
2288 | else if (cfg->line_outs == 1 && cfg->line_out_type == AUTO_PIN_HP_OUT) | 2336 | nid = cfg->line_out_pins[0]; |
2289 | nid = cfg->line_out_pins[0]; /* OK, we have a single line-out */ | 2337 | else if (cfg->hp_outs > 0) |
2290 | else | 2338 | nid = cfg->hp_pins[0]; |
2291 | return 0; /* both not available */ | 2339 | if (!nid) |
2340 | return 0; | ||
2292 | 2341 | ||
2293 | if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN)) | 2342 | if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN)) |
2294 | return 0; /* no input */ | 2343 | return 0; /* no input */ |
2295 | 2344 | ||
2296 | cfg->inputs[1].pin = nid; | 2345 | cfg->inputs[cfg->num_inputs].pin = nid; |
2297 | cfg->inputs[1].type = AUTO_PIN_MIC; | 2346 | cfg->inputs[cfg->num_inputs].type = AUTO_PIN_MIC; |
2298 | cfg->num_inputs = 2; | 2347 | cfg->inputs[cfg->num_inputs].is_headphone_mic = 1; |
2299 | spec->shared_mic_hp = 1; | 2348 | cfg->num_inputs++; |
2349 | spec->hp_mic = 1; | ||
2350 | spec->hp_mic_pin = nid; | ||
2351 | /* we can't handle auto-mic together with HP-mic */ | ||
2352 | spec->suppress_auto_mic = 1; | ||
2300 | snd_printdd("hda-codec: Enable shared I/O jack on NID 0x%x\n", nid); | 2353 | snd_printdd("hda-codec: Enable shared I/O jack on NID 0x%x\n", nid); |
2301 | return 0; | 2354 | return 0; |
2302 | } | 2355 | } |
@@ -2304,13 +2357,17 @@ static int create_shared_input(struct hda_codec *codec) | |||
2304 | /* | 2357 | /* |
2305 | * output jack mode | 2358 | * output jack mode |
2306 | */ | 2359 | */ |
2360 | |||
2361 | static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin); | ||
2362 | |||
2363 | static const char * const out_jack_texts[] = { | ||
2364 | "Line Out", "Headphone Out", | ||
2365 | }; | ||
2366 | |||
2307 | static int out_jack_mode_info(struct snd_kcontrol *kcontrol, | 2367 | static int out_jack_mode_info(struct snd_kcontrol *kcontrol, |
2308 | struct snd_ctl_elem_info *uinfo) | 2368 | struct snd_ctl_elem_info *uinfo) |
2309 | { | 2369 | { |
2310 | static const char * const texts[] = { | 2370 | return snd_hda_enum_helper_info(kcontrol, uinfo, 2, out_jack_texts); |
2311 | "Line Out", "Headphone Out", | ||
2312 | }; | ||
2313 | return snd_hda_enum_helper_info(kcontrol, uinfo, 2, texts); | ||
2314 | } | 2371 | } |
2315 | 2372 | ||
2316 | static int out_jack_mode_get(struct snd_kcontrol *kcontrol, | 2373 | static int out_jack_mode_get(struct snd_kcontrol *kcontrol, |
@@ -2372,6 +2429,17 @@ static void get_jack_mode_name(struct hda_codec *codec, hda_nid_t pin, | |||
2372 | ; | 2429 | ; |
2373 | } | 2430 | } |
2374 | 2431 | ||
2432 | static int get_out_jack_num_items(struct hda_codec *codec, hda_nid_t pin) | ||
2433 | { | ||
2434 | struct hda_gen_spec *spec = codec->spec; | ||
2435 | if (spec->add_jack_modes) { | ||
2436 | unsigned int pincap = snd_hda_query_pin_caps(codec, pin); | ||
2437 | if ((pincap & AC_PINCAP_OUT) && (pincap & AC_PINCAP_HP_DRV)) | ||
2438 | return 2; | ||
2439 | } | ||
2440 | return 1; | ||
2441 | } | ||
2442 | |||
2375 | static int create_out_jack_modes(struct hda_codec *codec, int num_pins, | 2443 | static int create_out_jack_modes(struct hda_codec *codec, int num_pins, |
2376 | hda_nid_t *pins) | 2444 | hda_nid_t *pins) |
2377 | { | 2445 | { |
@@ -2380,8 +2448,13 @@ static int create_out_jack_modes(struct hda_codec *codec, int num_pins, | |||
2380 | 2448 | ||
2381 | for (i = 0; i < num_pins; i++) { | 2449 | for (i = 0; i < num_pins; i++) { |
2382 | hda_nid_t pin = pins[i]; | 2450 | hda_nid_t pin = pins[i]; |
2383 | unsigned int pincap = snd_hda_query_pin_caps(codec, pin); | 2451 | if (pin == spec->hp_mic_pin) { |
2384 | if ((pincap & AC_PINCAP_OUT) && (pincap & AC_PINCAP_HP_DRV)) { | 2452 | int ret = create_hp_mic_jack_mode(codec, pin); |
2453 | if (ret < 0) | ||
2454 | return ret; | ||
2455 | continue; | ||
2456 | } | ||
2457 | if (get_out_jack_num_items(codec, pin) > 1) { | ||
2385 | struct snd_kcontrol_new *knew; | 2458 | struct snd_kcontrol_new *knew; |
2386 | char name[44]; | 2459 | char name[44]; |
2387 | get_jack_mode_name(codec, pin, name, sizeof(name)); | 2460 | get_jack_mode_name(codec, pin, name, sizeof(name)); |
@@ -2502,12 +2575,24 @@ static const struct snd_kcontrol_new in_jack_mode_enum = { | |||
2502 | .put = in_jack_mode_put, | 2575 | .put = in_jack_mode_put, |
2503 | }; | 2576 | }; |
2504 | 2577 | ||
2578 | static int get_in_jack_num_items(struct hda_codec *codec, hda_nid_t pin) | ||
2579 | { | ||
2580 | struct hda_gen_spec *spec = codec->spec; | ||
2581 | int nitems = 0; | ||
2582 | if (spec->add_jack_modes) | ||
2583 | nitems = hweight32(get_vref_caps(codec, pin)); | ||
2584 | return nitems ? nitems : 1; | ||
2585 | } | ||
2586 | |||
2505 | static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin) | 2587 | static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin) |
2506 | { | 2588 | { |
2507 | struct hda_gen_spec *spec = codec->spec; | 2589 | struct hda_gen_spec *spec = codec->spec; |
2508 | unsigned int defcfg; | ||
2509 | struct snd_kcontrol_new *knew; | 2590 | struct snd_kcontrol_new *knew; |
2510 | char name[44]; | 2591 | char name[44]; |
2592 | unsigned int defcfg; | ||
2593 | |||
2594 | if (pin == spec->hp_mic_pin) | ||
2595 | return 0; /* already done in create_out_jack_mode() */ | ||
2511 | 2596 | ||
2512 | /* no jack mode for fixed pins */ | 2597 | /* no jack mode for fixed pins */ |
2513 | defcfg = snd_hda_codec_get_pincfg(codec, pin); | 2598 | defcfg = snd_hda_codec_get_pincfg(codec, pin); |
@@ -2515,7 +2600,7 @@ static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin) | |||
2515 | return 0; | 2600 | return 0; |
2516 | 2601 | ||
2517 | /* no multiple vref caps? */ | 2602 | /* no multiple vref caps? */ |
2518 | if (hweight32(get_vref_caps(codec, pin)) <= 1) | 2603 | if (get_in_jack_num_items(codec, pin) <= 1) |
2519 | return 0; | 2604 | return 0; |
2520 | 2605 | ||
2521 | get_jack_mode_name(codec, pin, name, sizeof(name)); | 2606 | get_jack_mode_name(codec, pin, name, sizeof(name)); |
@@ -2526,6 +2611,132 @@ static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin) | |||
2526 | return 0; | 2611 | return 0; |
2527 | } | 2612 | } |
2528 | 2613 | ||
2614 | /* | ||
2615 | * HP/mic shared jack mode | ||
2616 | */ | ||
2617 | static int hp_mic_jack_mode_info(struct snd_kcontrol *kcontrol, | ||
2618 | struct snd_ctl_elem_info *uinfo) | ||
2619 | { | ||
2620 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2621 | hda_nid_t nid = kcontrol->private_value; | ||
2622 | int out_jacks = get_out_jack_num_items(codec, nid); | ||
2623 | int in_jacks = get_in_jack_num_items(codec, nid); | ||
2624 | const char *text = NULL; | ||
2625 | int idx; | ||
2626 | |||
2627 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
2628 | uinfo->count = 1; | ||
2629 | uinfo->value.enumerated.items = out_jacks + in_jacks; | ||
2630 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
2631 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; | ||
2632 | idx = uinfo->value.enumerated.item; | ||
2633 | if (idx < out_jacks) { | ||
2634 | if (out_jacks > 1) | ||
2635 | text = out_jack_texts[idx]; | ||
2636 | else | ||
2637 | text = "Headphone Out"; | ||
2638 | } else { | ||
2639 | idx -= out_jacks; | ||
2640 | if (in_jacks > 1) { | ||
2641 | unsigned int vref_caps = get_vref_caps(codec, nid); | ||
2642 | text = vref_texts[get_vref_idx(vref_caps, idx)]; | ||
2643 | } else | ||
2644 | text = "Mic In"; | ||
2645 | } | ||
2646 | |||
2647 | strcpy(uinfo->value.enumerated.name, text); | ||
2648 | return 0; | ||
2649 | } | ||
2650 | |||
2651 | static int get_cur_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t nid) | ||
2652 | { | ||
2653 | int out_jacks = get_out_jack_num_items(codec, nid); | ||
2654 | int in_jacks = get_in_jack_num_items(codec, nid); | ||
2655 | unsigned int val = snd_hda_codec_get_pin_target(codec, nid); | ||
2656 | int idx = 0; | ||
2657 | |||
2658 | if (val & PIN_OUT) { | ||
2659 | if (out_jacks > 1 && val == PIN_HP) | ||
2660 | idx = 1; | ||
2661 | } else if (val & PIN_IN) { | ||
2662 | idx = out_jacks; | ||
2663 | if (in_jacks > 1) { | ||
2664 | unsigned int vref_caps = get_vref_caps(codec, nid); | ||
2665 | val &= AC_PINCTL_VREFEN; | ||
2666 | idx += cvt_from_vref_idx(vref_caps, val); | ||
2667 | } | ||
2668 | } | ||
2669 | return idx; | ||
2670 | } | ||
2671 | |||
2672 | static int hp_mic_jack_mode_get(struct snd_kcontrol *kcontrol, | ||
2673 | struct snd_ctl_elem_value *ucontrol) | ||
2674 | { | ||
2675 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2676 | hda_nid_t nid = kcontrol->private_value; | ||
2677 | ucontrol->value.enumerated.item[0] = | ||
2678 | get_cur_hp_mic_jack_mode(codec, nid); | ||
2679 | return 0; | ||
2680 | } | ||
2681 | |||
2682 | static int hp_mic_jack_mode_put(struct snd_kcontrol *kcontrol, | ||
2683 | struct snd_ctl_elem_value *ucontrol) | ||
2684 | { | ||
2685 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2686 | hda_nid_t nid = kcontrol->private_value; | ||
2687 | int out_jacks = get_out_jack_num_items(codec, nid); | ||
2688 | int in_jacks = get_in_jack_num_items(codec, nid); | ||
2689 | unsigned int val, oldval, idx; | ||
2690 | |||
2691 | oldval = get_cur_hp_mic_jack_mode(codec, nid); | ||
2692 | idx = ucontrol->value.enumerated.item[0]; | ||
2693 | if (oldval == idx) | ||
2694 | return 0; | ||
2695 | |||
2696 | if (idx < out_jacks) { | ||
2697 | if (out_jacks > 1) | ||
2698 | val = idx ? PIN_HP : PIN_OUT; | ||
2699 | else | ||
2700 | val = PIN_HP; | ||
2701 | } else { | ||
2702 | idx -= out_jacks; | ||
2703 | if (in_jacks > 1) { | ||
2704 | unsigned int vref_caps = get_vref_caps(codec, nid); | ||
2705 | val = snd_hda_codec_get_pin_target(codec, nid); | ||
2706 | val &= ~(AC_PINCTL_VREFEN | PIN_HP); | ||
2707 | val |= get_vref_idx(vref_caps, idx) | PIN_IN; | ||
2708 | } else | ||
2709 | val = snd_hda_get_default_vref(codec, nid); | ||
2710 | } | ||
2711 | snd_hda_set_pin_ctl_cache(codec, nid, val); | ||
2712 | update_hp_automute_hook(codec); | ||
2713 | |||
2714 | return 1; | ||
2715 | } | ||
2716 | |||
2717 | static const struct snd_kcontrol_new hp_mic_jack_mode_enum = { | ||
2718 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2719 | .info = hp_mic_jack_mode_info, | ||
2720 | .get = hp_mic_jack_mode_get, | ||
2721 | .put = hp_mic_jack_mode_put, | ||
2722 | }; | ||
2723 | |||
2724 | static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin) | ||
2725 | { | ||
2726 | struct hda_gen_spec *spec = codec->spec; | ||
2727 | struct snd_kcontrol_new *knew; | ||
2728 | |||
2729 | if (get_out_jack_num_items(codec, pin) <= 1 && | ||
2730 | get_in_jack_num_items(codec, pin) <= 1) | ||
2731 | return 0; /* no need */ | ||
2732 | knew = snd_hda_gen_add_kctl(spec, "Headphone Mic Jack Mode", | ||
2733 | &hp_mic_jack_mode_enum); | ||
2734 | if (!knew) | ||
2735 | return -ENOMEM; | ||
2736 | knew->private_value = pin; | ||
2737 | spec->hp_mic_jack_modes = 1; | ||
2738 | return 0; | ||
2739 | } | ||
2529 | 2740 | ||
2530 | /* | 2741 | /* |
2531 | * Parse input paths | 2742 | * Parse input paths |
@@ -2648,7 +2859,6 @@ static int check_dyn_adc_switch(struct hda_codec *codec) | |||
2648 | unsigned int ok_bits; | 2859 | unsigned int ok_bits; |
2649 | int i, n, nums; | 2860 | int i, n, nums; |
2650 | 2861 | ||
2651 | again: | ||
2652 | nums = 0; | 2862 | nums = 0; |
2653 | ok_bits = 0; | 2863 | ok_bits = 0; |
2654 | for (n = 0; n < spec->num_adc_nids; n++) { | 2864 | for (n = 0; n < spec->num_adc_nids; n++) { |
@@ -2663,12 +2873,6 @@ static int check_dyn_adc_switch(struct hda_codec *codec) | |||
2663 | } | 2873 | } |
2664 | 2874 | ||
2665 | if (!ok_bits) { | 2875 | if (!ok_bits) { |
2666 | if (spec->shared_mic_hp) { | ||
2667 | spec->shared_mic_hp = 0; | ||
2668 | imux->num_items = 1; | ||
2669 | goto again; | ||
2670 | } | ||
2671 | |||
2672 | /* check whether ADC-switch is possible */ | 2876 | /* check whether ADC-switch is possible */ |
2673 | for (i = 0; i < imux->num_items; i++) { | 2877 | for (i = 0; i < imux->num_items; i++) { |
2674 | for (n = 0; n < spec->num_adc_nids; n++) { | 2878 | for (n = 0; n < spec->num_adc_nids; n++) { |
@@ -2701,7 +2905,8 @@ static int check_dyn_adc_switch(struct hda_codec *codec) | |||
2701 | spec->num_adc_nids = nums; | 2905 | spec->num_adc_nids = nums; |
2702 | } | 2906 | } |
2703 | 2907 | ||
2704 | if (imux->num_items == 1 || spec->shared_mic_hp) { | 2908 | if (imux->num_items == 1 || |
2909 | (imux->num_items == 2 && spec->hp_mic)) { | ||
2705 | snd_printdd("hda-codec: reducing to a single ADC\n"); | 2910 | snd_printdd("hda-codec: reducing to a single ADC\n"); |
2706 | spec->num_adc_nids = 1; /* reduce to a single ADC */ | 2911 | spec->num_adc_nids = 1; /* reduce to a single ADC */ |
2707 | } | 2912 | } |
@@ -2738,6 +2943,8 @@ static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin, | |||
2738 | snd_hda_get_path_idx(codec, path); | 2943 | snd_hda_get_path_idx(codec, path); |
2739 | 2944 | ||
2740 | if (!imux_added) { | 2945 | if (!imux_added) { |
2946 | if (spec->hp_mic_pin == pin) | ||
2947 | spec->hp_mic_mux_idx = imux->num_items; | ||
2741 | spec->imux_pins[imux->num_items] = pin; | 2948 | spec->imux_pins[imux->num_items] = pin; |
2742 | snd_hda_add_imux_item(imux, label, cfg_idx, NULL); | 2949 | snd_hda_add_imux_item(imux, label, cfg_idx, NULL); |
2743 | imux_added = true; | 2950 | imux_added = true; |
@@ -2812,7 +3019,8 @@ static int create_input_ctls(struct hda_codec *codec) | |||
2812 | val = PIN_IN; | 3019 | val = PIN_IN; |
2813 | if (cfg->inputs[i].type == AUTO_PIN_MIC) | 3020 | if (cfg->inputs[i].type == AUTO_PIN_MIC) |
2814 | val |= snd_hda_get_default_vref(codec, pin); | 3021 | val |= snd_hda_get_default_vref(codec, pin); |
2815 | set_pin_target(codec, pin, val, false); | 3022 | if (pin != spec->hp_mic_pin) |
3023 | set_pin_target(codec, pin, val, false); | ||
2816 | 3024 | ||
2817 | if (mixer) { | 3025 | if (mixer) { |
2818 | if (is_reachable_path(codec, pin, mixer)) { | 3026 | if (is_reachable_path(codec, pin, mixer)) { |
@@ -2830,7 +3038,7 @@ static int create_input_ctls(struct hda_codec *codec) | |||
2830 | if (err < 0) | 3038 | if (err < 0) |
2831 | return err; | 3039 | return err; |
2832 | 3040 | ||
2833 | if (spec->add_in_jack_modes) { | 3041 | if (spec->add_jack_modes) { |
2834 | err = create_in_jack_mode(codec, pin); | 3042 | err = create_in_jack_mode(codec, pin); |
2835 | if (err < 0) | 3043 | if (err < 0) |
2836 | return err; | 3044 | return err; |
@@ -3462,8 +3670,8 @@ static int mux_select(struct hda_codec *codec, unsigned int adc_idx, | |||
3462 | 3670 | ||
3463 | spec->cur_mux[adc_idx] = idx; | 3671 | spec->cur_mux[adc_idx] = idx; |
3464 | 3672 | ||
3465 | if (spec->shared_mic_hp) | 3673 | if (spec->hp_mic) |
3466 | update_shared_mic_hp(codec, spec->cur_mux[adc_idx]); | 3674 | update_hp_mic(codec, adc_idx, false); |
3467 | 3675 | ||
3468 | if (spec->dyn_adc_switch) | 3676 | if (spec->dyn_adc_switch) |
3469 | dyn_adc_pcm_resetup(codec, idx); | 3677 | dyn_adc_pcm_resetup(codec, idx); |
@@ -3511,18 +3719,21 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins, | |||
3511 | 3719 | ||
3512 | for (i = 0; i < num_pins; i++) { | 3720 | for (i = 0; i < num_pins; i++) { |
3513 | hda_nid_t nid = pins[i]; | 3721 | hda_nid_t nid = pins[i]; |
3514 | unsigned int val; | 3722 | unsigned int val, oldval; |
3515 | if (!nid) | 3723 | if (!nid) |
3516 | break; | 3724 | break; |
3725 | oldval = snd_hda_codec_get_pin_target(codec, nid); | ||
3726 | if (oldval & PIN_IN) | ||
3727 | continue; /* no mute for inputs */ | ||
3517 | /* don't reset VREF value in case it's controlling | 3728 | /* don't reset VREF value in case it's controlling |
3518 | * the amp (see alc861_fixup_asus_amp_vref_0f()) | 3729 | * the amp (see alc861_fixup_asus_amp_vref_0f()) |
3519 | */ | 3730 | */ |
3520 | if (spec->keep_vref_in_automute) | 3731 | if (spec->keep_vref_in_automute) |
3521 | val = snd_hda_codec_get_pin_target(codec, nid) & ~PIN_HP; | 3732 | val = oldval & ~PIN_HP; |
3522 | else | 3733 | else |
3523 | val = 0; | 3734 | val = 0; |
3524 | if (!mute) | 3735 | if (!mute) |
3525 | val |= snd_hda_codec_get_pin_target(codec, nid); | 3736 | val |= oldval; |
3526 | /* here we call update_pin_ctl() so that the pinctl is changed | 3737 | /* here we call update_pin_ctl() so that the pinctl is changed |
3527 | * without changing the pinctl target value; | 3738 | * without changing the pinctl target value; |
3528 | * the original target value will be still referred at the | 3739 | * the original target value will be still referred at the |
@@ -3543,8 +3754,7 @@ void snd_hda_gen_update_outputs(struct hda_codec *codec) | |||
3543 | * in general, HP pins/amps control should be enabled in all cases, | 3754 | * in general, HP pins/amps control should be enabled in all cases, |
3544 | * but currently set only for master_mute, just to be safe | 3755 | * but currently set only for master_mute, just to be safe |
3545 | */ | 3756 | */ |
3546 | if (!spec->shared_mic_hp) /* don't change HP-pin when shared with mic */ | 3757 | do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins), |
3547 | do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins), | ||
3548 | spec->autocfg.hp_pins, spec->master_mute); | 3758 | spec->autocfg.hp_pins, spec->master_mute); |
3549 | 3759 | ||
3550 | if (!spec->automute_speaker) | 3760 | if (!spec->automute_speaker) |
@@ -3649,10 +3859,7 @@ static void update_automute_all(struct hda_codec *codec) | |||
3649 | { | 3859 | { |
3650 | struct hda_gen_spec *spec = codec->spec; | 3860 | struct hda_gen_spec *spec = codec->spec; |
3651 | 3861 | ||
3652 | if (spec->hp_automute_hook) | 3862 | update_hp_automute_hook(codec); |
3653 | spec->hp_automute_hook(codec, NULL); | ||
3654 | else | ||
3655 | snd_hda_gen_hp_automute(codec, NULL); | ||
3656 | if (spec->line_automute_hook) | 3863 | if (spec->line_automute_hook) |
3657 | spec->line_automute_hook(codec, NULL); | 3864 | spec->line_automute_hook(codec, NULL); |
3658 | else | 3865 | else |
@@ -3978,6 +4185,11 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec, | |||
3978 | cfg = &spec->autocfg; | 4185 | cfg = &spec->autocfg; |
3979 | } | 4186 | } |
3980 | 4187 | ||
4188 | if (!spec->main_out_badness) | ||
4189 | spec->main_out_badness = &hda_main_out_badness; | ||
4190 | if (!spec->extra_out_badness) | ||
4191 | spec->extra_out_badness = &hda_extra_out_badness; | ||
4192 | |||
3981 | fill_all_dac_nids(codec); | 4193 | fill_all_dac_nids(codec); |
3982 | 4194 | ||
3983 | if (!cfg->line_outs) { | 4195 | if (!cfg->line_outs) { |
@@ -4024,7 +4236,7 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec, | |||
4024 | err = create_loopback_mixing_ctl(codec); | 4236 | err = create_loopback_mixing_ctl(codec); |
4025 | if (err < 0) | 4237 | if (err < 0) |
4026 | return err; | 4238 | return err; |
4027 | err = create_shared_input(codec); | 4239 | err = create_hp_mic(codec); |
4028 | if (err < 0) | 4240 | if (err < 0) |
4029 | return err; | 4241 | return err; |
4030 | err = create_input_ctls(codec); | 4242 | err = create_input_ctls(codec); |
@@ -4050,11 +4262,9 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec, | |||
4050 | if (err < 0) | 4262 | if (err < 0) |
4051 | return err; | 4263 | return err; |
4052 | 4264 | ||
4053 | if (!spec->shared_mic_hp) { | 4265 | err = check_auto_mic_availability(codec); |
4054 | err = check_auto_mic_availability(codec); | 4266 | if (err < 0) |
4055 | if (err < 0) | 4267 | return err; |
4056 | return err; | ||
4057 | } | ||
4058 | 4268 | ||
4059 | err = create_capture_mixers(codec); | 4269 | err = create_capture_mixers(codec); |
4060 | if (err < 0) | 4270 | if (err < 0) |
@@ -4064,7 +4274,7 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec, | |||
4064 | if (err < 0) | 4274 | if (err < 0) |
4065 | return err; | 4275 | return err; |
4066 | 4276 | ||
4067 | if (spec->add_out_jack_modes) { | 4277 | if (spec->add_jack_modes) { |
4068 | if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { | 4278 | if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { |
4069 | err = create_out_jack_modes(codec, cfg->line_outs, | 4279 | err = create_out_jack_modes(codec, cfg->line_outs, |
4070 | cfg->line_out_pins); | 4280 | cfg->line_out_pins); |
@@ -4085,6 +4295,12 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec, | |||
4085 | if (spec->power_down_unused) | 4295 | if (spec->power_down_unused) |
4086 | codec->power_filter = snd_hda_gen_path_power_filter; | 4296 | codec->power_filter = snd_hda_gen_path_power_filter; |
4087 | 4297 | ||
4298 | if (!spec->no_analog && spec->beep_nid) { | ||
4299 | err = snd_hda_attach_beep_device(codec, spec->beep_nid); | ||
4300 | if (err < 0) | ||
4301 | return err; | ||
4302 | } | ||
4303 | |||
4088 | return 1; | 4304 | return 1; |
4089 | } | 4305 | } |
4090 | EXPORT_SYMBOL_HDA(snd_hda_gen_parse_auto_config); | 4306 | EXPORT_SYMBOL_HDA(snd_hda_gen_parse_auto_config); |
@@ -4161,17 +4377,6 @@ int snd_hda_gen_build_controls(struct hda_codec *codec) | |||
4161 | 4377 | ||
4162 | free_kctls(spec); /* no longer needed */ | 4378 | free_kctls(spec); /* no longer needed */ |
4163 | 4379 | ||
4164 | if (spec->shared_mic_hp) { | ||
4165 | int err; | ||
4166 | int nid = spec->autocfg.inputs[1].pin; | ||
4167 | err = snd_hda_jack_add_kctl(codec, nid, "Headphone Mic", 0); | ||
4168 | if (err < 0) | ||
4169 | return err; | ||
4170 | err = snd_hda_jack_detect_enable(codec, nid, 0); | ||
4171 | if (err < 0) | ||
4172 | return err; | ||
4173 | } | ||
4174 | |||
4175 | err = snd_hda_jack_add_kctls(codec, &spec->autocfg); | 4380 | err = snd_hda_jack_add_kctls(codec, &spec->autocfg); |
4176 | if (err < 0) | 4381 | if (err < 0) |
4177 | return err; | 4382 | return err; |
@@ -4729,7 +4934,8 @@ static void set_output_and_unmute(struct hda_codec *codec, int path_idx) | |||
4729 | return; | 4934 | return; |
4730 | pin = path->path[path->depth - 1]; | 4935 | pin = path->path[path->depth - 1]; |
4731 | restore_pin_ctl(codec, pin); | 4936 | restore_pin_ctl(codec, pin); |
4732 | snd_hda_activate_path(codec, path, path->active, true); | 4937 | snd_hda_activate_path(codec, path, path->active, |
4938 | aamix_default(codec->spec)); | ||
4733 | set_pin_eapd(codec, pin, path->active); | 4939 | set_pin_eapd(codec, pin, path->active); |
4734 | } | 4940 | } |
4735 | 4941 | ||
@@ -4779,7 +4985,8 @@ static void init_multi_io(struct hda_codec *codec) | |||
4779 | if (!spec->multi_io[i].ctl_in) | 4985 | if (!spec->multi_io[i].ctl_in) |
4780 | spec->multi_io[i].ctl_in = | 4986 | spec->multi_io[i].ctl_in = |
4781 | snd_hda_codec_get_pin_target(codec, pin); | 4987 | snd_hda_codec_get_pin_target(codec, pin); |
4782 | snd_hda_activate_path(codec, path, path->active, true); | 4988 | snd_hda_activate_path(codec, path, path->active, |
4989 | aamix_default(spec)); | ||
4783 | } | 4990 | } |
4784 | } | 4991 | } |
4785 | 4992 | ||
@@ -4826,11 +5033,10 @@ static void init_input_src(struct hda_codec *codec) | |||
4826 | snd_hda_activate_path(codec, path, active, false); | 5033 | snd_hda_activate_path(codec, path, active, false); |
4827 | } | 5034 | } |
4828 | } | 5035 | } |
5036 | if (spec->hp_mic) | ||
5037 | update_hp_mic(codec, c, true); | ||
4829 | } | 5038 | } |
4830 | 5039 | ||
4831 | if (spec->shared_mic_hp) | ||
4832 | update_shared_mic_hp(codec, spec->cur_mux[0]); | ||
4833 | |||
4834 | if (spec->cap_sync_hook) | 5040 | if (spec->cap_sync_hook) |
4835 | spec->cap_sync_hook(codec, NULL); | 5041 | spec->cap_sync_hook(codec, NULL); |
4836 | } | 5042 | } |
@@ -4911,6 +5117,7 @@ EXPORT_SYMBOL_HDA(snd_hda_gen_init); | |||
4911 | */ | 5117 | */ |
4912 | void snd_hda_gen_free(struct hda_codec *codec) | 5118 | void snd_hda_gen_free(struct hda_codec *codec) |
4913 | { | 5119 | { |
5120 | snd_hda_detach_beep_device(codec); | ||
4914 | snd_hda_gen_spec_free(codec->spec); | 5121 | snd_hda_gen_spec_free(codec->spec); |
4915 | kfree(codec->spec); | 5122 | kfree(codec->spec); |
4916 | codec->spec = NULL; | 5123 | codec->spec = NULL; |
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h index 009b57be96d3..54e665160379 100644 --- a/sound/pci/hda/hda_generic.h +++ b/sound/pci/hda/hda_generic.h | |||
@@ -76,6 +76,19 @@ enum { | |||
76 | HDA_GEN_PCM_ACT_CLOSE, | 76 | HDA_GEN_PCM_ACT_CLOSE, |
77 | }; | 77 | }; |
78 | 78 | ||
79 | /* DAC assignment badness table */ | ||
80 | struct badness_table { | ||
81 | int no_primary_dac; /* no primary DAC */ | ||
82 | int no_dac; /* no secondary DACs */ | ||
83 | int shared_primary; /* primary DAC is shared with main output */ | ||
84 | int shared_surr; /* secondary DAC shared with main or primary */ | ||
85 | int shared_clfe; /* third DAC shared with main or primary */ | ||
86 | int shared_surr_main; /* secondary DAC sahred with main/DAC0 */ | ||
87 | }; | ||
88 | |||
89 | extern const struct badness_table hda_main_out_badness; | ||
90 | extern const struct badness_table hda_extra_out_badness; | ||
91 | |||
79 | struct hda_gen_spec { | 92 | struct hda_gen_spec { |
80 | char stream_name_analog[32]; /* analog PCM stream */ | 93 | char stream_name_analog[32]; /* analog PCM stream */ |
81 | const struct hda_pcm_stream *stream_analog_playback; | 94 | const struct hda_pcm_stream *stream_analog_playback; |
@@ -145,7 +158,10 @@ struct hda_gen_spec { | |||
145 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; | 158 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; |
146 | hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS]; | 159 | hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS]; |
147 | unsigned int dyn_adc_idx[HDA_MAX_NUM_INPUTS]; | 160 | unsigned int dyn_adc_idx[HDA_MAX_NUM_INPUTS]; |
161 | /* shared hp/mic */ | ||
148 | hda_nid_t shared_mic_vref_pin; | 162 | hda_nid_t shared_mic_vref_pin; |
163 | hda_nid_t hp_mic_pin; | ||
164 | int hp_mic_mux_idx; | ||
149 | 165 | ||
150 | /* DAC/ADC lists */ | 166 | /* DAC/ADC lists */ |
151 | int num_all_dacs; | 167 | int num_all_dacs; |
@@ -200,7 +216,8 @@ struct hda_gen_spec { | |||
200 | 216 | ||
201 | /* other parse behavior flags */ | 217 | /* other parse behavior flags */ |
202 | unsigned int need_dac_fix:1; /* need to limit DACs for multi channels */ | 218 | unsigned int need_dac_fix:1; /* need to limit DACs for multi channels */ |
203 | unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */ | 219 | unsigned int hp_mic:1; /* Allow HP as a mic-in */ |
220 | unsigned int suppress_hp_mic_detect:1; /* Don't detect HP/mic */ | ||
204 | unsigned int no_primary_hp:1; /* Don't prefer HP pins to speaker pins */ | 221 | unsigned int no_primary_hp:1; /* Don't prefer HP pins to speaker pins */ |
205 | unsigned int multi_cap_vol:1; /* allow multiple capture xxx volumes */ | 222 | unsigned int multi_cap_vol:1; /* allow multiple capture xxx volumes */ |
206 | unsigned int inv_dmic_split:1; /* inverted dmic w/a for conexant */ | 223 | unsigned int inv_dmic_split:1; /* inverted dmic w/a for conexant */ |
@@ -209,8 +226,7 @@ struct hda_gen_spec { | |||
209 | unsigned int indep_hp:1; /* independent HP supported */ | 226 | unsigned int indep_hp:1; /* independent HP supported */ |
210 | unsigned int prefer_hp_amp:1; /* enable HP amp for speaker if any */ | 227 | unsigned int prefer_hp_amp:1; /* enable HP amp for speaker if any */ |
211 | unsigned int add_stereo_mix_input:1; /* add aamix as a capture src */ | 228 | unsigned int add_stereo_mix_input:1; /* add aamix as a capture src */ |
212 | unsigned int add_out_jack_modes:1; /* add output jack mode enum ctls */ | 229 | unsigned int add_jack_modes:1; /* add i/o jack mode enum ctls */ |
213 | unsigned int add_in_jack_modes:1; /* add input jack mode enum ctls */ | ||
214 | unsigned int power_down_unused:1; /* power down unused widgets */ | 230 | unsigned int power_down_unused:1; /* power down unused widgets */ |
215 | 231 | ||
216 | /* other internal flags */ | 232 | /* other internal flags */ |
@@ -218,10 +234,18 @@ struct hda_gen_spec { | |||
218 | unsigned int dyn_adc_switch:1; /* switch ADCs (for ALC275) */ | 234 | unsigned int dyn_adc_switch:1; /* switch ADCs (for ALC275) */ |
219 | unsigned int indep_hp_enabled:1; /* independent HP enabled */ | 235 | unsigned int indep_hp_enabled:1; /* independent HP enabled */ |
220 | unsigned int have_aamix_ctl:1; | 236 | unsigned int have_aamix_ctl:1; |
237 | unsigned int hp_mic_jack_modes:1; | ||
238 | |||
239 | /* badness tables for output path evaluations */ | ||
240 | const struct badness_table *main_out_badness; | ||
241 | const struct badness_table *extra_out_badness; | ||
221 | 242 | ||
222 | /* loopback mixing mode */ | 243 | /* loopback mixing mode */ |
223 | bool aamix_mode; | 244 | bool aamix_mode; |
224 | 245 | ||
246 | /* digital beep */ | ||
247 | hda_nid_t beep_nid; | ||
248 | |||
225 | /* for virtual master */ | 249 | /* for virtual master */ |
226 | hda_nid_t vmaster_nid; | 250 | hda_nid_t vmaster_nid; |
227 | unsigned int vmaster_tlv[4]; | 251 | unsigned int vmaster_tlv[4]; |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index bcd40ee488e3..7b213d589ef6 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -1889,6 +1889,26 @@ static void azx_timecounter_init(struct snd_pcm_substream *substream, | |||
1889 | tc->cycle_last = last; | 1889 | tc->cycle_last = last; |
1890 | } | 1890 | } |
1891 | 1891 | ||
1892 | static u64 azx_adjust_codec_delay(struct snd_pcm_substream *substream, | ||
1893 | u64 nsec) | ||
1894 | { | ||
1895 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); | ||
1896 | struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; | ||
1897 | u64 codec_frames, codec_nsecs; | ||
1898 | |||
1899 | if (!hinfo->ops.get_delay) | ||
1900 | return nsec; | ||
1901 | |||
1902 | codec_frames = hinfo->ops.get_delay(hinfo, apcm->codec, substream); | ||
1903 | codec_nsecs = div_u64(codec_frames * 1000000000LL, | ||
1904 | substream->runtime->rate); | ||
1905 | |||
1906 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
1907 | return nsec + codec_nsecs; | ||
1908 | |||
1909 | return (nsec > codec_nsecs) ? nsec - codec_nsecs : 0; | ||
1910 | } | ||
1911 | |||
1892 | static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream, | 1912 | static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream, |
1893 | struct timespec *ts) | 1913 | struct timespec *ts) |
1894 | { | 1914 | { |
@@ -1897,6 +1917,7 @@ static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream, | |||
1897 | 1917 | ||
1898 | nsec = timecounter_read(&azx_dev->azx_tc); | 1918 | nsec = timecounter_read(&azx_dev->azx_tc); |
1899 | nsec = div_u64(nsec, 3); /* can be optimized */ | 1919 | nsec = div_u64(nsec, 3); /* can be optimized */ |
1920 | nsec = azx_adjust_codec_delay(substream, nsec); | ||
1900 | 1921 | ||
1901 | *ts = ns_to_timespec(nsec); | 1922 | *ts = ns_to_timespec(nsec); |
1902 | 1923 | ||
@@ -2349,8 +2370,11 @@ static unsigned int azx_get_position(struct azx *chip, | |||
2349 | struct azx_dev *azx_dev, | 2370 | struct azx_dev *azx_dev, |
2350 | bool with_check) | 2371 | bool with_check) |
2351 | { | 2372 | { |
2373 | struct snd_pcm_substream *substream = azx_dev->substream; | ||
2374 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); | ||
2352 | unsigned int pos; | 2375 | unsigned int pos; |
2353 | int stream = azx_dev->substream->stream; | 2376 | int stream = substream->stream; |
2377 | struct hda_pcm_stream *hinfo = apcm->hinfo[stream]; | ||
2354 | int delay = 0; | 2378 | int delay = 0; |
2355 | 2379 | ||
2356 | switch (chip->position_fix[stream]) { | 2380 | switch (chip->position_fix[stream]) { |
@@ -2381,7 +2405,7 @@ static unsigned int azx_get_position(struct azx *chip, | |||
2381 | pos = 0; | 2405 | pos = 0; |
2382 | 2406 | ||
2383 | /* calculate runtime delay from LPIB */ | 2407 | /* calculate runtime delay from LPIB */ |
2384 | if (azx_dev->substream->runtime && | 2408 | if (substream->runtime && |
2385 | chip->position_fix[stream] == POS_FIX_POSBUF && | 2409 | chip->position_fix[stream] == POS_FIX_POSBUF && |
2386 | (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) { | 2410 | (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) { |
2387 | unsigned int lpib_pos = azx_sd_readl(azx_dev, SD_LPIB); | 2411 | unsigned int lpib_pos = azx_sd_readl(azx_dev, SD_LPIB); |
@@ -2399,9 +2423,16 @@ static unsigned int azx_get_position(struct azx *chip, | |||
2399 | delay = 0; | 2423 | delay = 0; |
2400 | chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY; | 2424 | chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY; |
2401 | } | 2425 | } |
2402 | azx_dev->substream->runtime->delay = | 2426 | delay = bytes_to_frames(substream->runtime, delay); |
2403 | bytes_to_frames(azx_dev->substream->runtime, delay); | ||
2404 | } | 2427 | } |
2428 | |||
2429 | if (substream->runtime) { | ||
2430 | if (hinfo->ops.get_delay) | ||
2431 | delay += hinfo->ops.get_delay(hinfo, apcm->codec, | ||
2432 | substream); | ||
2433 | substream->runtime->delay = delay; | ||
2434 | } | ||
2435 | |||
2405 | trace_azx_get_position(chip, azx_dev, pos, delay); | 2436 | trace_azx_get_position(chip, azx_dev, pos, delay); |
2406 | return pos; | 2437 | return pos; |
2407 | } | 2438 | } |
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index 1d035efeff4f..9e0a95288f46 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c | |||
@@ -394,7 +394,8 @@ static int get_unique_index(struct hda_codec *codec, const char *name, int idx) | |||
394 | } | 394 | } |
395 | 395 | ||
396 | static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, | 396 | static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, |
397 | const struct auto_pin_cfg *cfg) | 397 | const struct auto_pin_cfg *cfg, |
398 | const char *base_name) | ||
398 | { | 399 | { |
399 | unsigned int def_conf, conn; | 400 | unsigned int def_conf, conn; |
400 | char name[44]; | 401 | char name[44]; |
@@ -410,7 +411,11 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, | |||
410 | phantom_jack = (conn != AC_JACK_PORT_COMPLEX) || | 411 | phantom_jack = (conn != AC_JACK_PORT_COMPLEX) || |
411 | !is_jack_detectable(codec, nid); | 412 | !is_jack_detectable(codec, nid); |
412 | 413 | ||
413 | snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx); | 414 | if (base_name) { |
415 | strlcpy(name, base_name, sizeof(name)); | ||
416 | idx = 0; | ||
417 | } else | ||
418 | snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx); | ||
414 | if (phantom_jack) | 419 | if (phantom_jack) |
415 | /* Example final name: "Internal Mic Phantom Jack" */ | 420 | /* Example final name: "Internal Mic Phantom Jack" */ |
416 | strncat(name, " Phantom", sizeof(name) - strlen(name) - 1); | 421 | strncat(name, " Phantom", sizeof(name) - strlen(name) - 1); |
@@ -433,39 +438,51 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec, | |||
433 | const hda_nid_t *p; | 438 | const hda_nid_t *p; |
434 | int i, err; | 439 | int i, err; |
435 | 440 | ||
441 | for (i = 0; i < cfg->num_inputs; i++) { | ||
442 | /* If we have headphone mics; make sure they get the right name | ||
443 | before grabbed by output pins */ | ||
444 | if (cfg->inputs[i].is_headphone_mic) { | ||
445 | if (auto_cfg_hp_outs(cfg) == 1) | ||
446 | err = add_jack_kctl(codec, auto_cfg_hp_pins(cfg)[0], | ||
447 | cfg, "Headphone Mic"); | ||
448 | else | ||
449 | err = add_jack_kctl(codec, cfg->inputs[i].pin, | ||
450 | cfg, "Headphone Mic"); | ||
451 | } else | ||
452 | err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg, | ||
453 | NULL); | ||
454 | if (err < 0) | ||
455 | return err; | ||
456 | } | ||
457 | |||
436 | for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) { | 458 | for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) { |
437 | err = add_jack_kctl(codec, *p, cfg); | 459 | err = add_jack_kctl(codec, *p, cfg, NULL); |
438 | if (err < 0) | 460 | if (err < 0) |
439 | return err; | 461 | return err; |
440 | } | 462 | } |
441 | for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) { | 463 | for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) { |
442 | if (*p == *cfg->line_out_pins) /* might be duplicated */ | 464 | if (*p == *cfg->line_out_pins) /* might be duplicated */ |
443 | break; | 465 | break; |
444 | err = add_jack_kctl(codec, *p, cfg); | 466 | err = add_jack_kctl(codec, *p, cfg, NULL); |
445 | if (err < 0) | 467 | if (err < 0) |
446 | return err; | 468 | return err; |
447 | } | 469 | } |
448 | for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) { | 470 | for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) { |
449 | if (*p == *cfg->line_out_pins) /* might be duplicated */ | 471 | if (*p == *cfg->line_out_pins) /* might be duplicated */ |
450 | break; | 472 | break; |
451 | err = add_jack_kctl(codec, *p, cfg); | 473 | err = add_jack_kctl(codec, *p, cfg, NULL); |
452 | if (err < 0) | ||
453 | return err; | ||
454 | } | ||
455 | for (i = 0; i < cfg->num_inputs; i++) { | ||
456 | err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg); | ||
457 | if (err < 0) | 474 | if (err < 0) |
458 | return err; | 475 | return err; |
459 | } | 476 | } |
460 | for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) { | 477 | for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) { |
461 | err = add_jack_kctl(codec, *p, cfg); | 478 | err = add_jack_kctl(codec, *p, cfg, NULL); |
462 | if (err < 0) | 479 | if (err < 0) |
463 | return err; | 480 | return err; |
464 | } | 481 | } |
465 | err = add_jack_kctl(codec, cfg->dig_in_pin, cfg); | 482 | err = add_jack_kctl(codec, cfg->dig_in_pin, cfg, NULL); |
466 | if (err < 0) | 483 | if (err < 0) |
467 | return err; | 484 | return err; |
468 | err = add_jack_kctl(codec, cfg->mono_out_pin, cfg); | 485 | err = add_jack_kctl(codec, cfg->mono_out_pin, cfg, NULL); |
469 | if (err < 0) | 486 | if (err < 0) |
470 | return err; | 487 | return err; |
471 | return 0; | 488 | return 0; |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 83b7486c8eff..e0bf7534fa1f 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -670,6 +670,10 @@ snd_hda_check_power_state(struct hda_codec *codec, hda_nid_t nid, | |||
670 | return (state != target_state); | 670 | return (state != target_state); |
671 | } | 671 | } |
672 | 672 | ||
673 | unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec, | ||
674 | hda_nid_t nid, | ||
675 | unsigned int power_state); | ||
676 | |||
673 | /* | 677 | /* |
674 | * AMP control callbacks | 678 | * AMP control callbacks |
675 | */ | 679 | */ |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index df8014b27596..977b0d878dae 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -43,7 +43,6 @@ struct ad198x_spec { | |||
43 | hda_nid_t eapd_nid; | 43 | hda_nid_t eapd_nid; |
44 | 44 | ||
45 | unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */ | 45 | unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */ |
46 | hda_nid_t beep_dev_nid; | ||
47 | 46 | ||
48 | #ifdef ENABLE_AD_STATIC_QUIRKS | 47 | #ifdef ENABLE_AD_STATIC_QUIRKS |
49 | const struct snd_kcontrol_new *mixers[6]; | 48 | const struct snd_kcontrol_new *mixers[6]; |
@@ -609,7 +608,7 @@ static const struct hda_codec_ops ad198x_auto_patch_ops = { | |||
609 | .build_controls = ad198x_auto_build_controls, | 608 | .build_controls = ad198x_auto_build_controls, |
610 | .build_pcms = snd_hda_gen_build_pcms, | 609 | .build_pcms = snd_hda_gen_build_pcms, |
611 | .init = snd_hda_gen_init, | 610 | .init = snd_hda_gen_init, |
612 | .free = ad198x_free, | 611 | .free = snd_hda_gen_free, |
613 | .unsol_event = snd_hda_jack_unsol_event, | 612 | .unsol_event = snd_hda_jack_unsol_event, |
614 | #ifdef CONFIG_PM | 613 | #ifdef CONFIG_PM |
615 | .check_power_status = snd_hda_gen_check_power_status, | 614 | .check_power_status = snd_hda_gen_check_power_status, |
@@ -638,12 +637,6 @@ static int ad198x_parse_auto_config(struct hda_codec *codec) | |||
638 | if (err < 0) | 637 | if (err < 0) |
639 | return err; | 638 | return err; |
640 | 639 | ||
641 | if (spec->beep_dev_nid) { | ||
642 | err = snd_hda_attach_beep_device(codec, spec->beep_dev_nid); | ||
643 | if (err < 0) | ||
644 | return err; | ||
645 | } | ||
646 | |||
647 | codec->patch_ops = ad198x_auto_patch_ops; | 640 | codec->patch_ops = ad198x_auto_patch_ops; |
648 | 641 | ||
649 | return 0; | 642 | return 0; |
@@ -1240,7 +1233,7 @@ static int ad1986a_parse_auto_config(struct hda_codec *codec) | |||
1240 | codec->inv_eapd = 1; | 1233 | codec->inv_eapd = 1; |
1241 | 1234 | ||
1242 | spec->gen.mixer_nid = 0x07; | 1235 | spec->gen.mixer_nid = 0x07; |
1243 | spec->beep_dev_nid = 0x19; | 1236 | spec->gen.beep_nid = 0x19; |
1244 | set_beep_amp(spec, 0x18, 0, HDA_OUTPUT); | 1237 | set_beep_amp(spec, 0x18, 0, HDA_OUTPUT); |
1245 | 1238 | ||
1246 | /* AD1986A has a hardware problem that it can't share a stream | 1239 | /* AD1986A has a hardware problem that it can't share a stream |
@@ -1256,7 +1249,7 @@ static int ad1986a_parse_auto_config(struct hda_codec *codec) | |||
1256 | 1249 | ||
1257 | err = ad198x_parse_auto_config(codec); | 1250 | err = ad198x_parse_auto_config(codec); |
1258 | if (err < 0) { | 1251 | if (err < 0) { |
1259 | ad198x_free(codec); | 1252 | snd_hda_gen_free(codec); |
1260 | return err; | 1253 | return err; |
1261 | } | 1254 | } |
1262 | 1255 | ||
@@ -1673,7 +1666,7 @@ static int ad1983_parse_auto_config(struct hda_codec *codec) | |||
1673 | return err; | 1666 | return err; |
1674 | spec = codec->spec; | 1667 | spec = codec->spec; |
1675 | 1668 | ||
1676 | spec->beep_dev_nid = 0x10; | 1669 | spec->gen.beep_nid = 0x10; |
1677 | set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); | 1670 | set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); |
1678 | err = ad198x_parse_auto_config(codec); | 1671 | err = ad198x_parse_auto_config(codec); |
1679 | if (err < 0) | 1672 | if (err < 0) |
@@ -1684,7 +1677,7 @@ static int ad1983_parse_auto_config(struct hda_codec *codec) | |||
1684 | return 0; | 1677 | return 0; |
1685 | 1678 | ||
1686 | error: | 1679 | error: |
1687 | ad198x_free(codec); | 1680 | snd_hda_gen_free(codec); |
1688 | return err; | 1681 | return err; |
1689 | } | 1682 | } |
1690 | 1683 | ||
@@ -2187,7 +2180,7 @@ static int ad1981_parse_auto_config(struct hda_codec *codec) | |||
2187 | spec = codec->spec; | 2180 | spec = codec->spec; |
2188 | 2181 | ||
2189 | spec->gen.mixer_nid = 0x0e; | 2182 | spec->gen.mixer_nid = 0x0e; |
2190 | spec->beep_dev_nid = 0x10; | 2183 | spec->gen.beep_nid = 0x10; |
2191 | set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT); | 2184 | set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT); |
2192 | 2185 | ||
2193 | snd_hda_pick_fixup(codec, NULL, ad1981_fixup_tbl, ad1981_fixups); | 2186 | snd_hda_pick_fixup(codec, NULL, ad1981_fixup_tbl, ad1981_fixups); |
@@ -2205,7 +2198,7 @@ static int ad1981_parse_auto_config(struct hda_codec *codec) | |||
2205 | return 0; | 2198 | return 0; |
2206 | 2199 | ||
2207 | error: | 2200 | error: |
2208 | ad198x_free(codec); | 2201 | snd_hda_gen_free(codec); |
2209 | return err; | 2202 | return err; |
2210 | } | 2203 | } |
2211 | 2204 | ||
@@ -3236,7 +3229,7 @@ static int ad1988_parse_auto_config(struct hda_codec *codec) | |||
3236 | 3229 | ||
3237 | spec->gen.mixer_nid = 0x20; | 3230 | spec->gen.mixer_nid = 0x20; |
3238 | spec->gen.mixer_merge_nid = 0x21; | 3231 | spec->gen.mixer_merge_nid = 0x21; |
3239 | spec->beep_dev_nid = 0x10; | 3232 | spec->gen.beep_nid = 0x10; |
3240 | set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); | 3233 | set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); |
3241 | err = ad198x_parse_auto_config(codec); | 3234 | err = ad198x_parse_auto_config(codec); |
3242 | if (err < 0) | 3235 | if (err < 0) |
@@ -3247,7 +3240,7 @@ static int ad1988_parse_auto_config(struct hda_codec *codec) | |||
3247 | return 0; | 3240 | return 0; |
3248 | 3241 | ||
3249 | error: | 3242 | error: |
3250 | ad198x_free(codec); | 3243 | snd_hda_gen_free(codec); |
3251 | return err; | 3244 | return err; |
3252 | } | 3245 | } |
3253 | 3246 | ||
@@ -3653,7 +3646,7 @@ static int ad1884_parse_auto_config(struct hda_codec *codec) | |||
3653 | spec = codec->spec; | 3646 | spec = codec->spec; |
3654 | 3647 | ||
3655 | spec->gen.mixer_nid = 0x20; | 3648 | spec->gen.mixer_nid = 0x20; |
3656 | spec->beep_dev_nid = 0x10; | 3649 | spec->gen.beep_nid = 0x10; |
3657 | set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); | 3650 | set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); |
3658 | 3651 | ||
3659 | snd_hda_pick_fixup(codec, NULL, ad1884_fixup_tbl, ad1884_fixups); | 3652 | snd_hda_pick_fixup(codec, NULL, ad1884_fixup_tbl, ad1884_fixups); |
@@ -3671,7 +3664,7 @@ static int ad1884_parse_auto_config(struct hda_codec *codec) | |||
3671 | return 0; | 3664 | return 0; |
3672 | 3665 | ||
3673 | error: | 3666 | error: |
3674 | ad198x_free(codec); | 3667 | snd_hda_gen_free(codec); |
3675 | return err; | 3668 | return err; |
3676 | } | 3669 | } |
3677 | 3670 | ||
@@ -5155,7 +5148,7 @@ static int ad1882_parse_auto_config(struct hda_codec *codec) | |||
5155 | 5148 | ||
5156 | spec->gen.mixer_nid = 0x20; | 5149 | spec->gen.mixer_nid = 0x20; |
5157 | spec->gen.mixer_merge_nid = 0x21; | 5150 | spec->gen.mixer_merge_nid = 0x21; |
5158 | spec->beep_dev_nid = 0x10; | 5151 | spec->gen.beep_nid = 0x10; |
5159 | set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); | 5152 | set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); |
5160 | err = ad198x_parse_auto_config(codec); | 5153 | err = ad198x_parse_auto_config(codec); |
5161 | if (err < 0) | 5154 | if (err < 0) |
@@ -5166,7 +5159,7 @@ static int ad1882_parse_auto_config(struct hda_codec *codec) | |||
5166 | return 0; | 5159 | return 0; |
5167 | 5160 | ||
5168 | error: | 5161 | error: |
5169 | ad198x_free(codec); | 5162 | snd_hda_gen_free(codec); |
5170 | return err; | 5163 | return err; |
5171 | } | 5164 | } |
5172 | 5165 | ||
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 0792b5725f9c..90ff7a3f72df 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c | |||
@@ -131,6 +131,13 @@ enum { | |||
131 | /* Effects values size*/ | 131 | /* Effects values size*/ |
132 | #define EFFECT_VALS_MAX_COUNT 12 | 132 | #define EFFECT_VALS_MAX_COUNT 12 |
133 | 133 | ||
134 | /* Latency introduced by DSP blocks in milliseconds. */ | ||
135 | #define DSP_CAPTURE_INIT_LATENCY 0 | ||
136 | #define DSP_CRYSTAL_VOICE_LATENCY 124 | ||
137 | #define DSP_PLAYBACK_INIT_LATENCY 13 | ||
138 | #define DSP_PLAY_ENHANCEMENT_LATENCY 30 | ||
139 | #define DSP_SPEAKER_OUT_LATENCY 7 | ||
140 | |||
134 | struct ct_effect { | 141 | struct ct_effect { |
135 | char name[44]; | 142 | char name[44]; |
136 | hda_nid_t nid; | 143 | hda_nid_t nid; |
@@ -741,6 +748,9 @@ struct ca0132_spec { | |||
741 | long voicefx_val; | 748 | long voicefx_val; |
742 | long cur_mic_boost; | 749 | long cur_mic_boost; |
743 | 750 | ||
751 | struct hda_codec *codec; | ||
752 | struct delayed_work unsol_hp_work; | ||
753 | |||
744 | #ifdef ENABLE_TUNING_CONTROLS | 754 | #ifdef ENABLE_TUNING_CONTROLS |
745 | long cur_ctl_vals[TUNING_CTLS_COUNT]; | 755 | long cur_ctl_vals[TUNING_CTLS_COUNT]; |
746 | #endif | 756 | #endif |
@@ -2740,6 +2750,31 @@ static int ca0132_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | |||
2740 | return 0; | 2750 | return 0; |
2741 | } | 2751 | } |
2742 | 2752 | ||
2753 | static unsigned int ca0132_playback_pcm_delay(struct hda_pcm_stream *info, | ||
2754 | struct hda_codec *codec, | ||
2755 | struct snd_pcm_substream *substream) | ||
2756 | { | ||
2757 | struct ca0132_spec *spec = codec->spec; | ||
2758 | unsigned int latency = DSP_PLAYBACK_INIT_LATENCY; | ||
2759 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
2760 | |||
2761 | if (spec->dsp_state != DSP_DOWNLOADED) | ||
2762 | return 0; | ||
2763 | |||
2764 | /* Add latency if playback enhancement and either effect is enabled. */ | ||
2765 | if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]) { | ||
2766 | if ((spec->effects_switch[SURROUND - EFFECT_START_NID]) || | ||
2767 | (spec->effects_switch[DIALOG_PLUS - EFFECT_START_NID])) | ||
2768 | latency += DSP_PLAY_ENHANCEMENT_LATENCY; | ||
2769 | } | ||
2770 | |||
2771 | /* Applying Speaker EQ adds latency as well. */ | ||
2772 | if (spec->cur_out_type == SPEAKER_OUT) | ||
2773 | latency += DSP_SPEAKER_OUT_LATENCY; | ||
2774 | |||
2775 | return (latency * runtime->rate) / 1000; | ||
2776 | } | ||
2777 | |||
2743 | /* | 2778 | /* |
2744 | * Digital out | 2779 | * Digital out |
2745 | */ | 2780 | */ |
@@ -2808,6 +2843,23 @@ static int ca0132_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | |||
2808 | return 0; | 2843 | return 0; |
2809 | } | 2844 | } |
2810 | 2845 | ||
2846 | static unsigned int ca0132_capture_pcm_delay(struct hda_pcm_stream *info, | ||
2847 | struct hda_codec *codec, | ||
2848 | struct snd_pcm_substream *substream) | ||
2849 | { | ||
2850 | struct ca0132_spec *spec = codec->spec; | ||
2851 | unsigned int latency = DSP_CAPTURE_INIT_LATENCY; | ||
2852 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
2853 | |||
2854 | if (spec->dsp_state != DSP_DOWNLOADED) | ||
2855 | return 0; | ||
2856 | |||
2857 | if (spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID]) | ||
2858 | latency += DSP_CRYSTAL_VOICE_LATENCY; | ||
2859 | |||
2860 | return (latency * runtime->rate) / 1000; | ||
2861 | } | ||
2862 | |||
2811 | /* | 2863 | /* |
2812 | * Controls stuffs. | 2864 | * Controls stuffs. |
2813 | */ | 2865 | */ |
@@ -3227,6 +3279,14 @@ exit: | |||
3227 | return err < 0 ? err : 0; | 3279 | return err < 0 ? err : 0; |
3228 | } | 3280 | } |
3229 | 3281 | ||
3282 | static void ca0132_unsol_hp_delayed(struct work_struct *work) | ||
3283 | { | ||
3284 | struct ca0132_spec *spec = container_of( | ||
3285 | to_delayed_work(work), struct ca0132_spec, unsol_hp_work); | ||
3286 | ca0132_select_out(spec->codec); | ||
3287 | snd_hda_jack_report_sync(spec->codec); | ||
3288 | } | ||
3289 | |||
3230 | static void ca0132_set_dmic(struct hda_codec *codec, int enable); | 3290 | static void ca0132_set_dmic(struct hda_codec *codec, int enable); |
3231 | static int ca0132_mic_boost_set(struct hda_codec *codec, long val); | 3291 | static int ca0132_mic_boost_set(struct hda_codec *codec, long val); |
3232 | static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val); | 3292 | static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val); |
@@ -3991,7 +4051,8 @@ static struct hda_pcm_stream ca0132_pcm_analog_playback = { | |||
3991 | .channels_max = 6, | 4051 | .channels_max = 6, |
3992 | .ops = { | 4052 | .ops = { |
3993 | .prepare = ca0132_playback_pcm_prepare, | 4053 | .prepare = ca0132_playback_pcm_prepare, |
3994 | .cleanup = ca0132_playback_pcm_cleanup | 4054 | .cleanup = ca0132_playback_pcm_cleanup, |
4055 | .get_delay = ca0132_playback_pcm_delay, | ||
3995 | }, | 4056 | }, |
3996 | }; | 4057 | }; |
3997 | 4058 | ||
@@ -4001,7 +4062,8 @@ static struct hda_pcm_stream ca0132_pcm_analog_capture = { | |||
4001 | .channels_max = 2, | 4062 | .channels_max = 2, |
4002 | .ops = { | 4063 | .ops = { |
4003 | .prepare = ca0132_capture_pcm_prepare, | 4064 | .prepare = ca0132_capture_pcm_prepare, |
4004 | .cleanup = ca0132_capture_pcm_cleanup | 4065 | .cleanup = ca0132_capture_pcm_cleanup, |
4066 | .get_delay = ca0132_capture_pcm_delay, | ||
4005 | }, | 4067 | }, |
4006 | }; | 4068 | }; |
4007 | 4069 | ||
@@ -4399,8 +4461,7 @@ static void ca0132_process_dsp_response(struct hda_codec *codec) | |||
4399 | 4461 | ||
4400 | static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res) | 4462 | static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res) |
4401 | { | 4463 | { |
4402 | snd_printdd(KERN_INFO "ca0132_unsol_event: 0x%x\n", res); | 4464 | struct ca0132_spec *spec = codec->spec; |
4403 | |||
4404 | 4465 | ||
4405 | if (((res >> AC_UNSOL_RES_TAG_SHIFT) & 0x3f) == UNSOL_TAG_DSP) { | 4466 | if (((res >> AC_UNSOL_RES_TAG_SHIFT) & 0x3f) == UNSOL_TAG_DSP) { |
4406 | ca0132_process_dsp_response(codec); | 4467 | ca0132_process_dsp_response(codec); |
@@ -4412,8 +4473,13 @@ static void ca0132_unsol_event(struct hda_codec *codec, unsigned int res) | |||
4412 | 4473 | ||
4413 | switch (res) { | 4474 | switch (res) { |
4414 | case UNSOL_TAG_HP: | 4475 | case UNSOL_TAG_HP: |
4415 | ca0132_select_out(codec); | 4476 | /* Delay enabling the HP amp, to let the mic-detection |
4416 | snd_hda_jack_report_sync(codec); | 4477 | * state machine run. |
4478 | */ | ||
4479 | cancel_delayed_work_sync(&spec->unsol_hp_work); | ||
4480 | queue_delayed_work(codec->bus->workq, | ||
4481 | &spec->unsol_hp_work, | ||
4482 | msecs_to_jiffies(500)); | ||
4417 | break; | 4483 | break; |
4418 | case UNSOL_TAG_AMIC1: | 4484 | case UNSOL_TAG_AMIC1: |
4419 | ca0132_select_mic(codec); | 4485 | ca0132_select_mic(codec); |
@@ -4588,6 +4654,7 @@ static void ca0132_free(struct hda_codec *codec) | |||
4588 | { | 4654 | { |
4589 | struct ca0132_spec *spec = codec->spec; | 4655 | struct ca0132_spec *spec = codec->spec; |
4590 | 4656 | ||
4657 | cancel_delayed_work_sync(&spec->unsol_hp_work); | ||
4591 | snd_hda_power_up(codec); | 4658 | snd_hda_power_up(codec); |
4592 | snd_hda_sequence_write(codec, spec->base_exit_verbs); | 4659 | snd_hda_sequence_write(codec, spec->base_exit_verbs); |
4593 | ca0132_exit_chip(codec); | 4660 | ca0132_exit_chip(codec); |
@@ -4653,6 +4720,7 @@ static int patch_ca0132(struct hda_codec *codec) | |||
4653 | if (!spec) | 4720 | if (!spec) |
4654 | return -ENOMEM; | 4721 | return -ENOMEM; |
4655 | codec->spec = spec; | 4722 | codec->spec = spec; |
4723 | spec->codec = codec; | ||
4656 | 4724 | ||
4657 | spec->num_mixers = 1; | 4725 | spec->num_mixers = 1; |
4658 | spec->mixers[0] = ca0132_mixer; | 4726 | spec->mixers[0] = ca0132_mixer; |
@@ -4663,6 +4731,8 @@ static int patch_ca0132(struct hda_codec *codec) | |||
4663 | spec->init_verbs[1] = ca0132_init_verbs1; | 4731 | spec->init_verbs[1] = ca0132_init_verbs1; |
4664 | spec->num_init_verbs = 2; | 4732 | spec->num_init_verbs = 2; |
4665 | 4733 | ||
4734 | INIT_DELAYED_WORK(&spec->unsol_hp_work, ca0132_unsol_hp_delayed); | ||
4735 | |||
4666 | ca0132_init_chip(codec); | 4736 | ca0132_init_chip(codec); |
4667 | 4737 | ||
4668 | ca0132_config(codec); | 4738 | ca0132_config(codec); |
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 0d9c58f13560..bd8d46cca2b3 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c | |||
@@ -68,6 +68,7 @@ enum { | |||
68 | enum { | 68 | enum { |
69 | CS421X_CDB4210, | 69 | CS421X_CDB4210, |
70 | CS421X_SENSE_B, | 70 | CS421X_SENSE_B, |
71 | CS421X_STUMPY, | ||
71 | }; | 72 | }; |
72 | 73 | ||
73 | /* Vendor-specific processing widget */ | 74 | /* Vendor-specific processing widget */ |
@@ -538,6 +539,7 @@ static int patch_cs420x(struct hda_codec *codec) | |||
538 | /* CS4210 board names */ | 539 | /* CS4210 board names */ |
539 | static const struct hda_model_fixup cs421x_models[] = { | 540 | static const struct hda_model_fixup cs421x_models[] = { |
540 | { .id = CS421X_CDB4210, .name = "cdb4210" }, | 541 | { .id = CS421X_CDB4210, .name = "cdb4210" }, |
542 | { .id = CS421X_STUMPY, .name = "stumpy" }, | ||
541 | {} | 543 | {} |
542 | }; | 544 | }; |
543 | 545 | ||
@@ -559,6 +561,17 @@ static const struct hda_pintbl cdb4210_pincfgs[] = { | |||
559 | {} /* terminator */ | 561 | {} /* terminator */ |
560 | }; | 562 | }; |
561 | 563 | ||
564 | /* Stumpy ChromeBox */ | ||
565 | static const struct hda_pintbl stumpy_pincfgs[] = { | ||
566 | { 0x05, 0x022120f0 }, | ||
567 | { 0x06, 0x901700f0 }, | ||
568 | { 0x07, 0x02a120f0 }, | ||
569 | { 0x08, 0x77a70037 }, | ||
570 | { 0x09, 0x77a6003e }, | ||
571 | { 0x0a, 0x434510f0 }, | ||
572 | {} /* terminator */ | ||
573 | }; | ||
574 | |||
562 | /* Setup GPIO/SENSE for each board (if used) */ | 575 | /* Setup GPIO/SENSE for each board (if used) */ |
563 | static void cs421x_fixup_sense_b(struct hda_codec *codec, | 576 | static void cs421x_fixup_sense_b(struct hda_codec *codec, |
564 | const struct hda_fixup *fix, int action) | 577 | const struct hda_fixup *fix, int action) |
@@ -578,7 +591,11 @@ static const struct hda_fixup cs421x_fixups[] = { | |||
578 | [CS421X_SENSE_B] = { | 591 | [CS421X_SENSE_B] = { |
579 | .type = HDA_FIXUP_FUNC, | 592 | .type = HDA_FIXUP_FUNC, |
580 | .v.func = cs421x_fixup_sense_b, | 593 | .v.func = cs421x_fixup_sense_b, |
581 | } | 594 | }, |
595 | [CS421X_STUMPY] = { | ||
596 | .type = HDA_FIXUP_PINS, | ||
597 | .v.pins = stumpy_pincfgs, | ||
598 | }, | ||
582 | }; | 599 | }; |
583 | 600 | ||
584 | static const struct hda_verb cs421x_coef_init_verbs[] = { | 601 | static const struct hda_verb cs421x_coef_init_verbs[] = { |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 2a89d1eefeb6..84b81c874a4a 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -139,8 +139,12 @@ struct conexant_spec { | |||
139 | 139 | ||
140 | 140 | ||
141 | #ifdef CONFIG_SND_HDA_INPUT_BEEP | 141 | #ifdef CONFIG_SND_HDA_INPUT_BEEP |
142 | #define set_beep_amp(spec, nid, idx, dir) \ | 142 | static inline void set_beep_amp(struct conexant_spec *spec, hda_nid_t nid, |
143 | ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) | 143 | int idx, int dir) |
144 | { | ||
145 | spec->gen.beep_nid = nid; | ||
146 | spec->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir); | ||
147 | } | ||
144 | /* additional beep mixers; the actual parameters are overwritten at build */ | 148 | /* additional beep mixers; the actual parameters are overwritten at build */ |
145 | static const struct snd_kcontrol_new cxt_beep_mixer[] = { | 149 | static const struct snd_kcontrol_new cxt_beep_mixer[] = { |
146 | HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT), | 150 | HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT), |
@@ -2942,7 +2946,6 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { | |||
2942 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), | 2946 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), |
2943 | SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD), | 2947 | SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD), |
2944 | SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS), | 2948 | SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS), |
2945 | SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT5066_THINKPAD), | ||
2946 | SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT5066_THINKPAD), | 2949 | SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT5066_THINKPAD), |
2947 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS), | 2950 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS), |
2948 | SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS), | 2951 | SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS), |
@@ -3191,17 +3194,11 @@ static int cx_auto_build_controls(struct hda_codec *codec) | |||
3191 | return 0; | 3194 | return 0; |
3192 | } | 3195 | } |
3193 | 3196 | ||
3194 | static void cx_auto_free(struct hda_codec *codec) | ||
3195 | { | ||
3196 | snd_hda_detach_beep_device(codec); | ||
3197 | snd_hda_gen_free(codec); | ||
3198 | } | ||
3199 | |||
3200 | static const struct hda_codec_ops cx_auto_patch_ops = { | 3197 | static const struct hda_codec_ops cx_auto_patch_ops = { |
3201 | .build_controls = cx_auto_build_controls, | 3198 | .build_controls = cx_auto_build_controls, |
3202 | .build_pcms = snd_hda_gen_build_pcms, | 3199 | .build_pcms = snd_hda_gen_build_pcms, |
3203 | .init = snd_hda_gen_init, | 3200 | .init = snd_hda_gen_init, |
3204 | .free = cx_auto_free, | 3201 | .free = snd_hda_gen_free, |
3205 | .unsol_event = snd_hda_jack_unsol_event, | 3202 | .unsol_event = snd_hda_jack_unsol_event, |
3206 | #ifdef CONFIG_PM | 3203 | #ifdef CONFIG_PM |
3207 | .check_power_status = snd_hda_gen_check_power_status, | 3204 | .check_power_status = snd_hda_gen_check_power_status, |
@@ -3310,6 +3307,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = { | |||
3310 | SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410), | 3307 | SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410), |
3311 | SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410), | 3308 | SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410), |
3312 | SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410), | 3309 | SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410), |
3310 | SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT_PINCFG_LENOVO_TP410), | ||
3313 | SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC), | 3311 | SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC), |
3314 | SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC), | 3312 | SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC), |
3315 | SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC), | 3313 | SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC), |
@@ -3356,7 +3354,6 @@ static int patch_conexant_auto(struct hda_codec *codec) | |||
3356 | switch (codec->vendor_id) { | 3354 | switch (codec->vendor_id) { |
3357 | case 0x14f15045: | 3355 | case 0x14f15045: |
3358 | codec->single_adc_amp = 1; | 3356 | codec->single_adc_amp = 1; |
3359 | codec->power_filter = NULL; /* Needs speaker amp to D3 to avoid click */ | ||
3360 | break; | 3357 | break; |
3361 | case 0x14f15047: | 3358 | case 0x14f15047: |
3362 | codec->pin_amp_workaround = 1; | 3359 | codec->pin_amp_workaround = 1; |
@@ -3396,8 +3393,6 @@ static int patch_conexant_auto(struct hda_codec *codec) | |||
3396 | goto error; | 3393 | goto error; |
3397 | 3394 | ||
3398 | codec->patch_ops = cx_auto_patch_ops; | 3395 | codec->patch_ops = cx_auto_patch_ops; |
3399 | if (spec->beep_amp) | ||
3400 | snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp)); | ||
3401 | 3396 | ||
3402 | /* Some laptops with Conexant chips show stalls in S3 resume, | 3397 | /* Some laptops with Conexant chips show stalls in S3 resume, |
3403 | * which falls into the single-cmd mode. | 3398 | * which falls into the single-cmd mode. |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index de8ac5c07fd0..32930e668854 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -44,16 +44,6 @@ static bool static_hdmi_pcm; | |||
44 | module_param(static_hdmi_pcm, bool, 0644); | 44 | module_param(static_hdmi_pcm, bool, 0644); |
45 | MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info"); | 45 | MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info"); |
46 | 46 | ||
47 | /* | ||
48 | * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device | ||
49 | * could support N independent pipes, each of them can be connected to one or | ||
50 | * more ports (DVI, HDMI or DisplayPort). | ||
51 | * | ||
52 | * The HDA correspondence of pipes/ports are converter/pin nodes. | ||
53 | */ | ||
54 | #define MAX_HDMI_CVTS 8 | ||
55 | #define MAX_HDMI_PINS 8 | ||
56 | |||
57 | struct hdmi_spec_per_cvt { | 47 | struct hdmi_spec_per_cvt { |
58 | hda_nid_t cvt_nid; | 48 | hda_nid_t cvt_nid; |
59 | int assigned; | 49 | int assigned; |
@@ -80,16 +70,17 @@ struct hdmi_spec_per_pin { | |||
80 | bool non_pcm; | 70 | bool non_pcm; |
81 | bool chmap_set; /* channel-map override by ALSA API? */ | 71 | bool chmap_set; /* channel-map override by ALSA API? */ |
82 | unsigned char chmap[8]; /* ALSA API channel-map */ | 72 | unsigned char chmap[8]; /* ALSA API channel-map */ |
73 | char pcm_name[8]; /* filled in build_pcm callbacks */ | ||
83 | }; | 74 | }; |
84 | 75 | ||
85 | struct hdmi_spec { | 76 | struct hdmi_spec { |
86 | int num_cvts; | 77 | int num_cvts; |
87 | struct hdmi_spec_per_cvt cvts[MAX_HDMI_CVTS]; | 78 | struct snd_array cvts; /* struct hdmi_spec_per_cvt */ |
88 | hda_nid_t cvt_nids[MAX_HDMI_CVTS]; | 79 | hda_nid_t cvt_nids[4]; /* only for haswell fix */ |
89 | 80 | ||
90 | int num_pins; | 81 | int num_pins; |
91 | struct hdmi_spec_per_pin pins[MAX_HDMI_PINS]; | 82 | struct snd_array pins; /* struct hdmi_spec_per_pin */ |
92 | struct hda_pcm pcm_rec[MAX_HDMI_PINS]; | 83 | struct snd_array pcm_rec; /* struct hda_pcm */ |
93 | unsigned int channels_max; /* max over all cvts */ | 84 | unsigned int channels_max; /* max over all cvts */ |
94 | 85 | ||
95 | struct hdmi_eld temp_eld; | 86 | struct hdmi_eld temp_eld; |
@@ -304,12 +295,19 @@ static struct cea_channel_speaker_allocation channel_allocations[] = { | |||
304 | * HDMI routines | 295 | * HDMI routines |
305 | */ | 296 | */ |
306 | 297 | ||
298 | #define get_pin(spec, idx) \ | ||
299 | ((struct hdmi_spec_per_pin *)snd_array_elem(&spec->pins, idx)) | ||
300 | #define get_cvt(spec, idx) \ | ||
301 | ((struct hdmi_spec_per_cvt *)snd_array_elem(&spec->cvts, idx)) | ||
302 | #define get_pcm_rec(spec, idx) \ | ||
303 | ((struct hda_pcm *)snd_array_elem(&spec->pcm_rec, idx)) | ||
304 | |||
307 | static int pin_nid_to_pin_index(struct hdmi_spec *spec, hda_nid_t pin_nid) | 305 | static int pin_nid_to_pin_index(struct hdmi_spec *spec, hda_nid_t pin_nid) |
308 | { | 306 | { |
309 | int pin_idx; | 307 | int pin_idx; |
310 | 308 | ||
311 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) | 309 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) |
312 | if (spec->pins[pin_idx].pin_nid == pin_nid) | 310 | if (get_pin(spec, pin_idx)->pin_nid == pin_nid) |
313 | return pin_idx; | 311 | return pin_idx; |
314 | 312 | ||
315 | snd_printk(KERN_WARNING "HDMI: pin nid %d not registered\n", pin_nid); | 313 | snd_printk(KERN_WARNING "HDMI: pin nid %d not registered\n", pin_nid); |
@@ -322,7 +320,7 @@ static int hinfo_to_pin_index(struct hdmi_spec *spec, | |||
322 | int pin_idx; | 320 | int pin_idx; |
323 | 321 | ||
324 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) | 322 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) |
325 | if (&spec->pcm_rec[pin_idx].stream[0] == hinfo) | 323 | if (get_pcm_rec(spec, pin_idx)->stream == hinfo) |
326 | return pin_idx; | 324 | return pin_idx; |
327 | 325 | ||
328 | snd_printk(KERN_WARNING "HDMI: hinfo %p not registered\n", hinfo); | 326 | snd_printk(KERN_WARNING "HDMI: hinfo %p not registered\n", hinfo); |
@@ -334,7 +332,7 @@ static int cvt_nid_to_cvt_index(struct hdmi_spec *spec, hda_nid_t cvt_nid) | |||
334 | int cvt_idx; | 332 | int cvt_idx; |
335 | 333 | ||
336 | for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) | 334 | for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) |
337 | if (spec->cvts[cvt_idx].cvt_nid == cvt_nid) | 335 | if (get_cvt(spec, cvt_idx)->cvt_nid == cvt_nid) |
338 | return cvt_idx; | 336 | return cvt_idx; |
339 | 337 | ||
340 | snd_printk(KERN_WARNING "HDMI: cvt nid %d not registered\n", cvt_nid); | 338 | snd_printk(KERN_WARNING "HDMI: cvt nid %d not registered\n", cvt_nid); |
@@ -352,7 +350,7 @@ static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol, | |||
352 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; | 350 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; |
353 | 351 | ||
354 | pin_idx = kcontrol->private_value; | 352 | pin_idx = kcontrol->private_value; |
355 | eld = &spec->pins[pin_idx].sink_eld; | 353 | eld = &get_pin(spec, pin_idx)->sink_eld; |
356 | 354 | ||
357 | mutex_lock(&eld->lock); | 355 | mutex_lock(&eld->lock); |
358 | uinfo->count = eld->eld_valid ? eld->eld_size : 0; | 356 | uinfo->count = eld->eld_valid ? eld->eld_size : 0; |
@@ -370,7 +368,7 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol, | |||
370 | int pin_idx; | 368 | int pin_idx; |
371 | 369 | ||
372 | pin_idx = kcontrol->private_value; | 370 | pin_idx = kcontrol->private_value; |
373 | eld = &spec->pins[pin_idx].sink_eld; | 371 | eld = &get_pin(spec, pin_idx)->sink_eld; |
374 | 372 | ||
375 | mutex_lock(&eld->lock); | 373 | mutex_lock(&eld->lock); |
376 | if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data)) { | 374 | if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data)) { |
@@ -410,11 +408,11 @@ static int hdmi_create_eld_ctl(struct hda_codec *codec, int pin_idx, | |||
410 | kctl->private_value = pin_idx; | 408 | kctl->private_value = pin_idx; |
411 | kctl->id.device = device; | 409 | kctl->id.device = device; |
412 | 410 | ||
413 | err = snd_hda_ctl_add(codec, spec->pins[pin_idx].pin_nid, kctl); | 411 | err = snd_hda_ctl_add(codec, get_pin(spec, pin_idx)->pin_nid, kctl); |
414 | if (err < 0) | 412 | if (err < 0) |
415 | return err; | 413 | return err; |
416 | 414 | ||
417 | spec->pins[pin_idx].eld_ctl = kctl; | 415 | get_pin(spec, pin_idx)->eld_ctl = kctl; |
418 | return 0; | 416 | return 0; |
419 | } | 417 | } |
420 | 418 | ||
@@ -875,14 +873,14 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx, | |||
875 | struct snd_pcm_substream *substream) | 873 | struct snd_pcm_substream *substream) |
876 | { | 874 | { |
877 | struct hdmi_spec *spec = codec->spec; | 875 | struct hdmi_spec *spec = codec->spec; |
878 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | 876 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); |
879 | hda_nid_t pin_nid = per_pin->pin_nid; | 877 | hda_nid_t pin_nid = per_pin->pin_nid; |
880 | int channels = substream->runtime->channels; | 878 | int channels = substream->runtime->channels; |
881 | struct hdmi_eld *eld; | 879 | struct hdmi_eld *eld; |
882 | int ca; | 880 | int ca; |
883 | union audio_infoframe ai; | 881 | union audio_infoframe ai; |
884 | 882 | ||
885 | eld = &spec->pins[pin_idx].sink_eld; | 883 | eld = &per_pin->sink_eld; |
886 | if (!eld->monitor_present) | 884 | if (!eld->monitor_present) |
887 | return; | 885 | return; |
888 | 886 | ||
@@ -977,7 +975,7 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) | |||
977 | if (pin_idx < 0) | 975 | if (pin_idx < 0) |
978 | return; | 976 | return; |
979 | 977 | ||
980 | hdmi_present_sense(&spec->pins[pin_idx], 1); | 978 | hdmi_present_sense(get_pin(spec, pin_idx), 1); |
981 | snd_hda_jack_report_sync(codec); | 979 | snd_hda_jack_report_sync(codec); |
982 | } | 980 | } |
983 | 981 | ||
@@ -1020,6 +1018,41 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res) | |||
1020 | hdmi_non_intrinsic_event(codec, res); | 1018 | hdmi_non_intrinsic_event(codec, res); |
1021 | } | 1019 | } |
1022 | 1020 | ||
1021 | static void haswell_verify_pin_D0(struct hda_codec *codec, hda_nid_t nid) | ||
1022 | { | ||
1023 | int pwr, lamp, ramp; | ||
1024 | |||
1025 | pwr = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0); | ||
1026 | pwr = (pwr & AC_PWRST_ACTUAL) >> AC_PWRST_ACTUAL_SHIFT; | ||
1027 | if (pwr != AC_PWRST_D0) { | ||
1028 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, | ||
1029 | AC_PWRST_D0); | ||
1030 | msleep(40); | ||
1031 | pwr = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0); | ||
1032 | pwr = (pwr & AC_PWRST_ACTUAL) >> AC_PWRST_ACTUAL_SHIFT; | ||
1033 | snd_printd("Haswell HDMI audio: Power for pin 0x%x is now D%d\n", nid, pwr); | ||
1034 | } | ||
1035 | |||
1036 | lamp = snd_hda_codec_read(codec, nid, 0, | ||
1037 | AC_VERB_GET_AMP_GAIN_MUTE, | ||
1038 | AC_AMP_GET_LEFT | AC_AMP_GET_OUTPUT); | ||
1039 | ramp = snd_hda_codec_read(codec, nid, 0, | ||
1040 | AC_VERB_GET_AMP_GAIN_MUTE, | ||
1041 | AC_AMP_GET_RIGHT | AC_AMP_GET_OUTPUT); | ||
1042 | if (lamp != ramp) { | ||
1043 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1044 | AC_AMP_SET_RIGHT | AC_AMP_SET_OUTPUT | lamp); | ||
1045 | |||
1046 | lamp = snd_hda_codec_read(codec, nid, 0, | ||
1047 | AC_VERB_GET_AMP_GAIN_MUTE, | ||
1048 | AC_AMP_GET_LEFT | AC_AMP_GET_OUTPUT); | ||
1049 | ramp = snd_hda_codec_read(codec, nid, 0, | ||
1050 | AC_VERB_GET_AMP_GAIN_MUTE, | ||
1051 | AC_AMP_GET_RIGHT | AC_AMP_GET_OUTPUT); | ||
1052 | snd_printd("Haswell HDMI audio: Mute after set on pin 0x%x: [0x%x 0x%x]\n", nid, lamp, ramp); | ||
1053 | } | ||
1054 | } | ||
1055 | |||
1023 | /* | 1056 | /* |
1024 | * Callbacks | 1057 | * Callbacks |
1025 | */ | 1058 | */ |
@@ -1034,6 +1067,9 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, | |||
1034 | int pinctl; | 1067 | int pinctl; |
1035 | int new_pinctl = 0; | 1068 | int new_pinctl = 0; |
1036 | 1069 | ||
1070 | if (codec->vendor_id == 0x80862807) | ||
1071 | haswell_verify_pin_D0(codec, pin_nid); | ||
1072 | |||
1037 | if (snd_hda_query_pin_caps(codec, pin_nid) & AC_PINCAP_HBR) { | 1073 | if (snd_hda_query_pin_caps(codec, pin_nid) & AC_PINCAP_HBR) { |
1038 | pinctl = snd_hda_codec_read(codec, pin_nid, 0, | 1074 | pinctl = snd_hda_codec_read(codec, pin_nid, 0, |
1039 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 1075 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
@@ -1083,12 +1119,12 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, | |||
1083 | pin_idx = hinfo_to_pin_index(spec, hinfo); | 1119 | pin_idx = hinfo_to_pin_index(spec, hinfo); |
1084 | if (snd_BUG_ON(pin_idx < 0)) | 1120 | if (snd_BUG_ON(pin_idx < 0)) |
1085 | return -EINVAL; | 1121 | return -EINVAL; |
1086 | per_pin = &spec->pins[pin_idx]; | 1122 | per_pin = get_pin(spec, pin_idx); |
1087 | eld = &per_pin->sink_eld; | 1123 | eld = &per_pin->sink_eld; |
1088 | 1124 | ||
1089 | /* Dynamically assign converter to stream */ | 1125 | /* Dynamically assign converter to stream */ |
1090 | for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) { | 1126 | for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) { |
1091 | per_cvt = &spec->cvts[cvt_idx]; | 1127 | per_cvt = get_cvt(spec, cvt_idx); |
1092 | 1128 | ||
1093 | /* Must not already be assigned */ | 1129 | /* Must not already be assigned */ |
1094 | if (per_cvt->assigned) | 1130 | if (per_cvt->assigned) |
@@ -1151,7 +1187,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, | |||
1151 | static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx) | 1187 | static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx) |
1152 | { | 1188 | { |
1153 | struct hdmi_spec *spec = codec->spec; | 1189 | struct hdmi_spec *spec = codec->spec; |
1154 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | 1190 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); |
1155 | hda_nid_t pin_nid = per_pin->pin_nid; | 1191 | hda_nid_t pin_nid = per_pin->pin_nid; |
1156 | 1192 | ||
1157 | if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) { | 1193 | if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) { |
@@ -1275,14 +1311,13 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) | |||
1275 | if (get_defcfg_connect(config) == AC_JACK_PORT_NONE) | 1311 | if (get_defcfg_connect(config) == AC_JACK_PORT_NONE) |
1276 | return 0; | 1312 | return 0; |
1277 | 1313 | ||
1278 | if (snd_BUG_ON(spec->num_pins >= MAX_HDMI_PINS)) | ||
1279 | return -E2BIG; | ||
1280 | |||
1281 | if (codec->vendor_id == 0x80862807) | 1314 | if (codec->vendor_id == 0x80862807) |
1282 | intel_haswell_fixup_connect_list(codec, pin_nid); | 1315 | intel_haswell_fixup_connect_list(codec, pin_nid); |
1283 | 1316 | ||
1284 | pin_idx = spec->num_pins; | 1317 | pin_idx = spec->num_pins; |
1285 | per_pin = &spec->pins[pin_idx]; | 1318 | per_pin = snd_array_new(&spec->pins); |
1319 | if (!per_pin) | ||
1320 | return -ENOMEM; | ||
1286 | 1321 | ||
1287 | per_pin->pin_nid = pin_nid; | 1322 | per_pin->pin_nid = pin_nid; |
1288 | per_pin->non_pcm = false; | 1323 | per_pin->non_pcm = false; |
@@ -1299,19 +1334,16 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) | |||
1299 | static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) | 1334 | static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) |
1300 | { | 1335 | { |
1301 | struct hdmi_spec *spec = codec->spec; | 1336 | struct hdmi_spec *spec = codec->spec; |
1302 | int cvt_idx; | ||
1303 | struct hdmi_spec_per_cvt *per_cvt; | 1337 | struct hdmi_spec_per_cvt *per_cvt; |
1304 | unsigned int chans; | 1338 | unsigned int chans; |
1305 | int err; | 1339 | int err; |
1306 | 1340 | ||
1307 | if (snd_BUG_ON(spec->num_cvts >= MAX_HDMI_CVTS)) | ||
1308 | return -E2BIG; | ||
1309 | |||
1310 | chans = get_wcaps(codec, cvt_nid); | 1341 | chans = get_wcaps(codec, cvt_nid); |
1311 | chans = get_wcaps_channels(chans); | 1342 | chans = get_wcaps_channels(chans); |
1312 | 1343 | ||
1313 | cvt_idx = spec->num_cvts; | 1344 | per_cvt = snd_array_new(&spec->cvts); |
1314 | per_cvt = &spec->cvts[cvt_idx]; | 1345 | if (!per_cvt) |
1346 | return -ENOMEM; | ||
1315 | 1347 | ||
1316 | per_cvt->cvt_nid = cvt_nid; | 1348 | per_cvt->cvt_nid = cvt_nid; |
1317 | per_cvt->channels_min = 2; | 1349 | per_cvt->channels_min = 2; |
@@ -1328,7 +1360,9 @@ static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) | |||
1328 | if (err < 0) | 1360 | if (err < 0) |
1329 | return err; | 1361 | return err; |
1330 | 1362 | ||
1331 | spec->cvt_nids[spec->num_cvts++] = cvt_nid; | 1363 | if (spec->num_cvts < ARRAY_SIZE(spec->cvt_nids)) |
1364 | spec->cvt_nids[spec->num_cvts] = cvt_nid; | ||
1365 | spec->num_cvts++; | ||
1332 | 1366 | ||
1333 | return 0; | 1367 | return 0; |
1334 | } | 1368 | } |
@@ -1384,13 +1418,6 @@ static int hdmi_parse_codec(struct hda_codec *codec) | |||
1384 | 1418 | ||
1385 | /* | 1419 | /* |
1386 | */ | 1420 | */ |
1387 | static char *get_hdmi_pcm_name(int idx) | ||
1388 | { | ||
1389 | static char names[MAX_HDMI_PINS][8]; | ||
1390 | sprintf(&names[idx][0], "HDMI %d", idx); | ||
1391 | return &names[idx][0]; | ||
1392 | } | ||
1393 | |||
1394 | static bool check_non_pcm_per_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) | 1421 | static bool check_non_pcm_per_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) |
1395 | { | 1422 | { |
1396 | struct hda_spdif_out *spdif; | 1423 | struct hda_spdif_out *spdif; |
@@ -1417,7 +1444,7 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
1417 | hda_nid_t cvt_nid = hinfo->nid; | 1444 | hda_nid_t cvt_nid = hinfo->nid; |
1418 | struct hdmi_spec *spec = codec->spec; | 1445 | struct hdmi_spec *spec = codec->spec; |
1419 | int pin_idx = hinfo_to_pin_index(spec, hinfo); | 1446 | int pin_idx = hinfo_to_pin_index(spec, hinfo); |
1420 | hda_nid_t pin_nid = spec->pins[pin_idx].pin_nid; | 1447 | hda_nid_t pin_nid = get_pin(spec, pin_idx)->pin_nid; |
1421 | bool non_pcm; | 1448 | bool non_pcm; |
1422 | 1449 | ||
1423 | non_pcm = check_non_pcm_per_cvt(codec, cvt_nid); | 1450 | non_pcm = check_non_pcm_per_cvt(codec, cvt_nid); |
@@ -1450,7 +1477,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, | |||
1450 | cvt_idx = cvt_nid_to_cvt_index(spec, hinfo->nid); | 1477 | cvt_idx = cvt_nid_to_cvt_index(spec, hinfo->nid); |
1451 | if (snd_BUG_ON(cvt_idx < 0)) | 1478 | if (snd_BUG_ON(cvt_idx < 0)) |
1452 | return -EINVAL; | 1479 | return -EINVAL; |
1453 | per_cvt = &spec->cvts[cvt_idx]; | 1480 | per_cvt = get_cvt(spec, cvt_idx); |
1454 | 1481 | ||
1455 | snd_BUG_ON(!per_cvt->assigned); | 1482 | snd_BUG_ON(!per_cvt->assigned); |
1456 | per_cvt->assigned = 0; | 1483 | per_cvt->assigned = 0; |
@@ -1459,7 +1486,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, | |||
1459 | pin_idx = hinfo_to_pin_index(spec, hinfo); | 1486 | pin_idx = hinfo_to_pin_index(spec, hinfo); |
1460 | if (snd_BUG_ON(pin_idx < 0)) | 1487 | if (snd_BUG_ON(pin_idx < 0)) |
1461 | return -EINVAL; | 1488 | return -EINVAL; |
1462 | per_pin = &spec->pins[pin_idx]; | 1489 | per_pin = get_pin(spec, pin_idx); |
1463 | 1490 | ||
1464 | snd_hda_spdif_ctls_unassign(codec, pin_idx); | 1491 | snd_hda_spdif_ctls_unassign(codec, pin_idx); |
1465 | per_pin->chmap_set = false; | 1492 | per_pin->chmap_set = false; |
@@ -1553,7 +1580,7 @@ static int hdmi_chmap_ctl_get(struct snd_kcontrol *kcontrol, | |||
1553 | struct hda_codec *codec = info->private_data; | 1580 | struct hda_codec *codec = info->private_data; |
1554 | struct hdmi_spec *spec = codec->spec; | 1581 | struct hdmi_spec *spec = codec->spec; |
1555 | int pin_idx = kcontrol->private_value; | 1582 | int pin_idx = kcontrol->private_value; |
1556 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | 1583 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); |
1557 | int i; | 1584 | int i; |
1558 | 1585 | ||
1559 | for (i = 0; i < ARRAY_SIZE(per_pin->chmap); i++) | 1586 | for (i = 0; i < ARRAY_SIZE(per_pin->chmap); i++) |
@@ -1568,7 +1595,7 @@ static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol, | |||
1568 | struct hda_codec *codec = info->private_data; | 1595 | struct hda_codec *codec = info->private_data; |
1569 | struct hdmi_spec *spec = codec->spec; | 1596 | struct hdmi_spec *spec = codec->spec; |
1570 | int pin_idx = kcontrol->private_value; | 1597 | int pin_idx = kcontrol->private_value; |
1571 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | 1598 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); |
1572 | unsigned int ctl_idx; | 1599 | unsigned int ctl_idx; |
1573 | struct snd_pcm_substream *substream; | 1600 | struct snd_pcm_substream *substream; |
1574 | unsigned char chmap[8]; | 1601 | unsigned char chmap[8]; |
@@ -1613,9 +1640,14 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec) | |||
1613 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | 1640 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { |
1614 | struct hda_pcm *info; | 1641 | struct hda_pcm *info; |
1615 | struct hda_pcm_stream *pstr; | 1642 | struct hda_pcm_stream *pstr; |
1616 | 1643 | struct hdmi_spec_per_pin *per_pin; | |
1617 | info = &spec->pcm_rec[pin_idx]; | 1644 | |
1618 | info->name = get_hdmi_pcm_name(pin_idx); | 1645 | per_pin = get_pin(spec, pin_idx); |
1646 | sprintf(per_pin->pcm_name, "HDMI %d", pin_idx); | ||
1647 | info = snd_array_new(&spec->pcm_rec); | ||
1648 | if (!info) | ||
1649 | return -ENOMEM; | ||
1650 | info->name = per_pin->pcm_name; | ||
1619 | info->pcm_type = HDA_PCM_TYPE_HDMI; | 1651 | info->pcm_type = HDA_PCM_TYPE_HDMI; |
1620 | info->own_chmap = true; | 1652 | info->own_chmap = true; |
1621 | 1653 | ||
@@ -1626,7 +1658,7 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec) | |||
1626 | } | 1658 | } |
1627 | 1659 | ||
1628 | codec->num_pcms = spec->num_pins; | 1660 | codec->num_pcms = spec->num_pins; |
1629 | codec->pcm_info = spec->pcm_rec; | 1661 | codec->pcm_info = spec->pcm_rec.list; |
1630 | 1662 | ||
1631 | return 0; | 1663 | return 0; |
1632 | } | 1664 | } |
@@ -1635,8 +1667,8 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx) | |||
1635 | { | 1667 | { |
1636 | char hdmi_str[32] = "HDMI/DP"; | 1668 | char hdmi_str[32] = "HDMI/DP"; |
1637 | struct hdmi_spec *spec = codec->spec; | 1669 | struct hdmi_spec *spec = codec->spec; |
1638 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | 1670 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); |
1639 | int pcmdev = spec->pcm_rec[pin_idx].device; | 1671 | int pcmdev = get_pcm_rec(spec, pin_idx)->device; |
1640 | 1672 | ||
1641 | if (pcmdev > 0) | 1673 | if (pcmdev > 0) |
1642 | sprintf(hdmi_str + strlen(hdmi_str), ",pcm=%d", pcmdev); | 1674 | sprintf(hdmi_str + strlen(hdmi_str), ",pcm=%d", pcmdev); |
@@ -1654,7 +1686,7 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) | |||
1654 | int pin_idx; | 1686 | int pin_idx; |
1655 | 1687 | ||
1656 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | 1688 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { |
1657 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | 1689 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); |
1658 | 1690 | ||
1659 | err = generic_hdmi_build_jack(codec, pin_idx); | 1691 | err = generic_hdmi_build_jack(codec, pin_idx); |
1660 | if (err < 0) | 1692 | if (err < 0) |
@@ -1669,9 +1701,8 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) | |||
1669 | snd_hda_spdif_ctls_unassign(codec, pin_idx); | 1701 | snd_hda_spdif_ctls_unassign(codec, pin_idx); |
1670 | 1702 | ||
1671 | /* add control for ELD Bytes */ | 1703 | /* add control for ELD Bytes */ |
1672 | err = hdmi_create_eld_ctl(codec, | 1704 | err = hdmi_create_eld_ctl(codec, pin_idx, |
1673 | pin_idx, | 1705 | get_pcm_rec(spec, pin_idx)->device); |
1674 | spec->pcm_rec[pin_idx].device); | ||
1675 | 1706 | ||
1676 | if (err < 0) | 1707 | if (err < 0) |
1677 | return err; | 1708 | return err; |
@@ -1709,7 +1740,7 @@ static int generic_hdmi_init_per_pins(struct hda_codec *codec) | |||
1709 | int pin_idx; | 1740 | int pin_idx; |
1710 | 1741 | ||
1711 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | 1742 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { |
1712 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | 1743 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); |
1713 | struct hdmi_eld *eld = &per_pin->sink_eld; | 1744 | struct hdmi_eld *eld = &per_pin->sink_eld; |
1714 | 1745 | ||
1715 | per_pin->codec = codec; | 1746 | per_pin->codec = codec; |
@@ -1726,7 +1757,7 @@ static int generic_hdmi_init(struct hda_codec *codec) | |||
1726 | int pin_idx; | 1757 | int pin_idx; |
1727 | 1758 | ||
1728 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | 1759 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { |
1729 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | 1760 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); |
1730 | hda_nid_t pin_nid = per_pin->pin_nid; | 1761 | hda_nid_t pin_nid = per_pin->pin_nid; |
1731 | 1762 | ||
1732 | hdmi_init_pin(codec, pin_nid); | 1763 | hdmi_init_pin(codec, pin_nid); |
@@ -1735,13 +1766,27 @@ static int generic_hdmi_init(struct hda_codec *codec) | |||
1735 | return 0; | 1766 | return 0; |
1736 | } | 1767 | } |
1737 | 1768 | ||
1769 | static void hdmi_array_init(struct hdmi_spec *spec, int nums) | ||
1770 | { | ||
1771 | snd_array_init(&spec->pins, sizeof(struct hdmi_spec_per_pin), nums); | ||
1772 | snd_array_init(&spec->cvts, sizeof(struct hdmi_spec_per_cvt), nums); | ||
1773 | snd_array_init(&spec->pcm_rec, sizeof(struct hda_pcm), nums); | ||
1774 | } | ||
1775 | |||
1776 | static void hdmi_array_free(struct hdmi_spec *spec) | ||
1777 | { | ||
1778 | snd_array_free(&spec->pins); | ||
1779 | snd_array_free(&spec->cvts); | ||
1780 | snd_array_free(&spec->pcm_rec); | ||
1781 | } | ||
1782 | |||
1738 | static void generic_hdmi_free(struct hda_codec *codec) | 1783 | static void generic_hdmi_free(struct hda_codec *codec) |
1739 | { | 1784 | { |
1740 | struct hdmi_spec *spec = codec->spec; | 1785 | struct hdmi_spec *spec = codec->spec; |
1741 | int pin_idx; | 1786 | int pin_idx; |
1742 | 1787 | ||
1743 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | 1788 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { |
1744 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | 1789 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); |
1745 | struct hdmi_eld *eld = &per_pin->sink_eld; | 1790 | struct hdmi_eld *eld = &per_pin->sink_eld; |
1746 | 1791 | ||
1747 | cancel_delayed_work(&per_pin->work); | 1792 | cancel_delayed_work(&per_pin->work); |
@@ -1749,6 +1794,7 @@ static void generic_hdmi_free(struct hda_codec *codec) | |||
1749 | } | 1794 | } |
1750 | 1795 | ||
1751 | flush_workqueue(codec->bus->workq); | 1796 | flush_workqueue(codec->bus->workq); |
1797 | hdmi_array_free(spec); | ||
1752 | kfree(spec); | 1798 | kfree(spec); |
1753 | } | 1799 | } |
1754 | 1800 | ||
@@ -1775,6 +1821,7 @@ static void intel_haswell_fixup_connect_list(struct hda_codec *codec, | |||
1775 | 1821 | ||
1776 | /* override pins connection list */ | 1822 | /* override pins connection list */ |
1777 | snd_printdd("hdmi: haswell: override pin connection 0x%x\n", nid); | 1823 | snd_printdd("hdmi: haswell: override pin connection 0x%x\n", nid); |
1824 | nconns = max(spec->num_cvts, 4); | ||
1778 | snd_hda_override_conn_list(codec, nid, spec->num_cvts, spec->cvt_nids); | 1825 | snd_hda_override_conn_list(codec, nid, spec->num_cvts, spec->cvt_nids); |
1779 | } | 1826 | } |
1780 | 1827 | ||
@@ -1855,6 +1902,7 @@ static int patch_generic_hdmi(struct hda_codec *codec) | |||
1855 | return -ENOMEM; | 1902 | return -ENOMEM; |
1856 | 1903 | ||
1857 | codec->spec = spec; | 1904 | codec->spec = spec; |
1905 | hdmi_array_init(spec, 4); | ||
1858 | 1906 | ||
1859 | snd_hda_pick_fixup(codec, hdmi_models, hdmi_fixup_tbl, hdmi_fixups); | 1907 | snd_hda_pick_fixup(codec, hdmi_models, hdmi_fixup_tbl, hdmi_fixups); |
1860 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 1908 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
@@ -1882,24 +1930,30 @@ static int patch_generic_hdmi(struct hda_codec *codec) | |||
1882 | static int simple_playback_build_pcms(struct hda_codec *codec) | 1930 | static int simple_playback_build_pcms(struct hda_codec *codec) |
1883 | { | 1931 | { |
1884 | struct hdmi_spec *spec = codec->spec; | 1932 | struct hdmi_spec *spec = codec->spec; |
1885 | struct hda_pcm *info = spec->pcm_rec; | 1933 | struct hda_pcm *info; |
1886 | unsigned int chans; | 1934 | unsigned int chans; |
1887 | struct hda_pcm_stream *pstr; | 1935 | struct hda_pcm_stream *pstr; |
1936 | struct hdmi_spec_per_cvt *per_cvt; | ||
1888 | 1937 | ||
1889 | codec->num_pcms = 1; | 1938 | per_cvt = get_cvt(spec, 0); |
1890 | codec->pcm_info = info; | 1939 | chans = get_wcaps(codec, per_cvt->cvt_nid); |
1891 | |||
1892 | chans = get_wcaps(codec, spec->cvts[0].cvt_nid); | ||
1893 | chans = get_wcaps_channels(chans); | 1940 | chans = get_wcaps_channels(chans); |
1894 | 1941 | ||
1895 | info->name = get_hdmi_pcm_name(0); | 1942 | info = snd_array_new(&spec->pcm_rec); |
1943 | if (!info) | ||
1944 | return -ENOMEM; | ||
1945 | info->name = get_pin(spec, 0)->pcm_name; | ||
1946 | sprintf(info->name, "HDMI 0"); | ||
1896 | info->pcm_type = HDA_PCM_TYPE_HDMI; | 1947 | info->pcm_type = HDA_PCM_TYPE_HDMI; |
1897 | pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; | 1948 | pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; |
1898 | *pstr = spec->pcm_playback; | 1949 | *pstr = spec->pcm_playback; |
1899 | pstr->nid = spec->cvts[0].cvt_nid; | 1950 | pstr->nid = per_cvt->cvt_nid; |
1900 | if (pstr->channels_max <= 2 && chans && chans <= 16) | 1951 | if (pstr->channels_max <= 2 && chans && chans <= 16) |
1901 | pstr->channels_max = chans; | 1952 | pstr->channels_max = chans; |
1902 | 1953 | ||
1954 | codec->num_pcms = 1; | ||
1955 | codec->pcm_info = info; | ||
1956 | |||
1903 | return 0; | 1957 | return 0; |
1904 | } | 1958 | } |
1905 | 1959 | ||
@@ -1919,11 +1973,12 @@ static void simple_hdmi_unsol_event(struct hda_codec *codec, | |||
1919 | static int simple_playback_build_controls(struct hda_codec *codec) | 1973 | static int simple_playback_build_controls(struct hda_codec *codec) |
1920 | { | 1974 | { |
1921 | struct hdmi_spec *spec = codec->spec; | 1975 | struct hdmi_spec *spec = codec->spec; |
1976 | struct hdmi_spec_per_cvt *per_cvt; | ||
1922 | int err; | 1977 | int err; |
1923 | 1978 | ||
1924 | err = snd_hda_create_spdif_out_ctls(codec, | 1979 | per_cvt = get_cvt(spec, 0); |
1925 | spec->cvts[0].cvt_nid, | 1980 | err = snd_hda_create_spdif_out_ctls(codec, per_cvt->cvt_nid, |
1926 | spec->cvts[0].cvt_nid); | 1981 | per_cvt->cvt_nid); |
1927 | if (err < 0) | 1982 | if (err < 0) |
1928 | return err; | 1983 | return err; |
1929 | return simple_hdmi_build_jack(codec, 0); | 1984 | return simple_hdmi_build_jack(codec, 0); |
@@ -1932,7 +1987,8 @@ static int simple_playback_build_controls(struct hda_codec *codec) | |||
1932 | static int simple_playback_init(struct hda_codec *codec) | 1987 | static int simple_playback_init(struct hda_codec *codec) |
1933 | { | 1988 | { |
1934 | struct hdmi_spec *spec = codec->spec; | 1989 | struct hdmi_spec *spec = codec->spec; |
1935 | hda_nid_t pin = spec->pins[0].pin_nid; | 1990 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, 0); |
1991 | hda_nid_t pin = per_pin->pin_nid; | ||
1936 | 1992 | ||
1937 | snd_hda_codec_write(codec, pin, 0, | 1993 | snd_hda_codec_write(codec, pin, 0, |
1938 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | 1994 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); |
@@ -1948,6 +2004,7 @@ static void simple_playback_free(struct hda_codec *codec) | |||
1948 | { | 2004 | { |
1949 | struct hdmi_spec *spec = codec->spec; | 2005 | struct hdmi_spec *spec = codec->spec; |
1950 | 2006 | ||
2007 | hdmi_array_free(spec); | ||
1951 | kfree(spec); | 2008 | kfree(spec); |
1952 | } | 2009 | } |
1953 | 2010 | ||
@@ -2111,20 +2168,29 @@ static int patch_simple_hdmi(struct hda_codec *codec, | |||
2111 | hda_nid_t cvt_nid, hda_nid_t pin_nid) | 2168 | hda_nid_t cvt_nid, hda_nid_t pin_nid) |
2112 | { | 2169 | { |
2113 | struct hdmi_spec *spec; | 2170 | struct hdmi_spec *spec; |
2171 | struct hdmi_spec_per_cvt *per_cvt; | ||
2172 | struct hdmi_spec_per_pin *per_pin; | ||
2114 | 2173 | ||
2115 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 2174 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
2116 | if (!spec) | 2175 | if (!spec) |
2117 | return -ENOMEM; | 2176 | return -ENOMEM; |
2118 | 2177 | ||
2119 | codec->spec = spec; | 2178 | codec->spec = spec; |
2179 | hdmi_array_init(spec, 1); | ||
2120 | 2180 | ||
2121 | spec->multiout.num_dacs = 0; /* no analog */ | 2181 | spec->multiout.num_dacs = 0; /* no analog */ |
2122 | spec->multiout.max_channels = 2; | 2182 | spec->multiout.max_channels = 2; |
2123 | spec->multiout.dig_out_nid = cvt_nid; | 2183 | spec->multiout.dig_out_nid = cvt_nid; |
2124 | spec->num_cvts = 1; | 2184 | spec->num_cvts = 1; |
2125 | spec->num_pins = 1; | 2185 | spec->num_pins = 1; |
2126 | spec->cvts[0].cvt_nid = cvt_nid; | 2186 | per_pin = snd_array_new(&spec->pins); |
2127 | spec->pins[0].pin_nid = pin_nid; | 2187 | per_cvt = snd_array_new(&spec->cvts); |
2188 | if (!per_pin || !per_cvt) { | ||
2189 | simple_playback_free(codec); | ||
2190 | return -ENOMEM; | ||
2191 | } | ||
2192 | per_cvt->cvt_nid = cvt_nid; | ||
2193 | per_pin->pin_nid = pin_nid; | ||
2128 | spec->pcm_playback = simple_pcm_playback; | 2194 | spec->pcm_playback = simple_pcm_playback; |
2129 | 2195 | ||
2130 | codec->patch_ops = simple_hdmi_patch_ops; | 2196 | codec->patch_ops = simple_hdmi_patch_ops; |
@@ -2201,9 +2267,11 @@ static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
2201 | int i; | 2267 | int i; |
2202 | struct hdmi_spec *spec = codec->spec; | 2268 | struct hdmi_spec *spec = codec->spec; |
2203 | struct hda_spdif_out *spdif; | 2269 | struct hda_spdif_out *spdif; |
2270 | struct hdmi_spec_per_cvt *per_cvt; | ||
2204 | 2271 | ||
2205 | mutex_lock(&codec->spdif_mutex); | 2272 | mutex_lock(&codec->spdif_mutex); |
2206 | spdif = snd_hda_spdif_out_of_nid(codec, spec->cvts[0].cvt_nid); | 2273 | per_cvt = get_cvt(spec, 0); |
2274 | spdif = snd_hda_spdif_out_of_nid(codec, per_cvt->cvt_nid); | ||
2207 | 2275 | ||
2208 | chs = substream->runtime->channels; | 2276 | chs = substream->runtime->channels; |
2209 | 2277 | ||
@@ -2325,13 +2393,17 @@ static int nvhdmi_7x_8ch_build_pcms(struct hda_codec *codec) | |||
2325 | { | 2393 | { |
2326 | struct hdmi_spec *spec = codec->spec; | 2394 | struct hdmi_spec *spec = codec->spec; |
2327 | int err = simple_playback_build_pcms(codec); | 2395 | int err = simple_playback_build_pcms(codec); |
2328 | spec->pcm_rec[0].own_chmap = true; | 2396 | if (!err) { |
2397 | struct hda_pcm *info = get_pcm_rec(spec, 0); | ||
2398 | info->own_chmap = true; | ||
2399 | } | ||
2329 | return err; | 2400 | return err; |
2330 | } | 2401 | } |
2331 | 2402 | ||
2332 | static int nvhdmi_7x_8ch_build_controls(struct hda_codec *codec) | 2403 | static int nvhdmi_7x_8ch_build_controls(struct hda_codec *codec) |
2333 | { | 2404 | { |
2334 | struct hdmi_spec *spec = codec->spec; | 2405 | struct hdmi_spec *spec = codec->spec; |
2406 | struct hda_pcm *info; | ||
2335 | struct snd_pcm_chmap *chmap; | 2407 | struct snd_pcm_chmap *chmap; |
2336 | int err; | 2408 | int err; |
2337 | 2409 | ||
@@ -2340,7 +2412,8 @@ static int nvhdmi_7x_8ch_build_controls(struct hda_codec *codec) | |||
2340 | return err; | 2412 | return err; |
2341 | 2413 | ||
2342 | /* add channel maps */ | 2414 | /* add channel maps */ |
2343 | err = snd_pcm_add_chmap_ctls(spec->pcm_rec[0].pcm, | 2415 | info = get_pcm_rec(spec, 0); |
2416 | err = snd_pcm_add_chmap_ctls(info->pcm, | ||
2344 | SNDRV_PCM_STREAM_PLAYBACK, | 2417 | SNDRV_PCM_STREAM_PLAYBACK, |
2345 | snd_pcm_alt_chmaps, 8, 0, &chmap); | 2418 | snd_pcm_alt_chmaps, 8, 0, &chmap); |
2346 | if (err < 0) | 2419 | if (err < 0) |
@@ -2395,6 +2468,7 @@ static int atihdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
2395 | struct snd_pcm_substream *substream) | 2468 | struct snd_pcm_substream *substream) |
2396 | { | 2469 | { |
2397 | struct hdmi_spec *spec = codec->spec; | 2470 | struct hdmi_spec *spec = codec->spec; |
2471 | struct hdmi_spec_per_cvt *per_cvt = get_cvt(spec, 0); | ||
2398 | int chans = substream->runtime->channels; | 2472 | int chans = substream->runtime->channels; |
2399 | int i, err; | 2473 | int i, err; |
2400 | 2474 | ||
@@ -2402,11 +2476,11 @@ static int atihdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
2402 | substream); | 2476 | substream); |
2403 | if (err < 0) | 2477 | if (err < 0) |
2404 | return err; | 2478 | return err; |
2405 | snd_hda_codec_write(codec, spec->cvts[0].cvt_nid, 0, | 2479 | snd_hda_codec_write(codec, per_cvt->cvt_nid, 0, |
2406 | AC_VERB_SET_CVT_CHAN_COUNT, chans - 1); | 2480 | AC_VERB_SET_CVT_CHAN_COUNT, chans - 1); |
2407 | /* FIXME: XXX */ | 2481 | /* FIXME: XXX */ |
2408 | for (i = 0; i < chans; i++) { | 2482 | for (i = 0; i < chans; i++) { |
2409 | snd_hda_codec_write(codec, spec->cvts[0].cvt_nid, 0, | 2483 | snd_hda_codec_write(codec, per_cvt->cvt_nid, 0, |
2410 | AC_VERB_SET_HDMI_CHAN_SLOT, | 2484 | AC_VERB_SET_HDMI_CHAN_SLOT, |
2411 | (i << 4) | i); | 2485 | (i << 4) | i); |
2412 | } | 2486 | } |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index f15c36bde540..6bf47f7326ad 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include "hda_codec.h" | 34 | #include "hda_codec.h" |
35 | #include "hda_local.h" | 35 | #include "hda_local.h" |
36 | #include "hda_auto_parser.h" | 36 | #include "hda_auto_parser.h" |
37 | #include "hda_beep.h" | ||
38 | #include "hda_jack.h" | 37 | #include "hda_jack.h" |
39 | #include "hda_generic.h" | 38 | #include "hda_generic.h" |
40 | 39 | ||
@@ -53,6 +52,20 @@ enum { | |||
53 | ALC_INIT_GPIO3, | 52 | ALC_INIT_GPIO3, |
54 | }; | 53 | }; |
55 | 54 | ||
55 | enum { | ||
56 | ALC_HEADSET_MODE_UNKNOWN, | ||
57 | ALC_HEADSET_MODE_UNPLUGGED, | ||
58 | ALC_HEADSET_MODE_HEADSET, | ||
59 | ALC_HEADSET_MODE_MIC, | ||
60 | ALC_HEADSET_MODE_HEADPHONE, | ||
61 | }; | ||
62 | |||
63 | enum { | ||
64 | ALC_HEADSET_TYPE_UNKNOWN, | ||
65 | ALC_HEADSET_TYPE_CTIA, | ||
66 | ALC_HEADSET_TYPE_OMTP, | ||
67 | }; | ||
68 | |||
56 | struct alc_customize_define { | 69 | struct alc_customize_define { |
57 | unsigned int sku_cfg; | 70 | unsigned int sku_cfg; |
58 | unsigned char port_connectivity; | 71 | unsigned char port_connectivity; |
@@ -86,6 +99,13 @@ struct alc_spec { | |||
86 | int mute_led_polarity; | 99 | int mute_led_polarity; |
87 | hda_nid_t mute_led_nid; | 100 | hda_nid_t mute_led_nid; |
88 | 101 | ||
102 | unsigned int gpio_led; /* used for alc269_fixup_hp_gpio_led() */ | ||
103 | |||
104 | hda_nid_t headset_mic_pin; | ||
105 | hda_nid_t headphone_mic_pin; | ||
106 | int current_headset_mode; | ||
107 | int current_headset_type; | ||
108 | |||
89 | /* hooks */ | 109 | /* hooks */ |
90 | void (*init_hook)(struct hda_codec *codec); | 110 | void (*init_hook)(struct hda_codec *codec); |
91 | #ifdef CONFIG_PM | 111 | #ifdef CONFIG_PM |
@@ -805,17 +825,7 @@ static inline void alc_shutup(struct hda_codec *codec) | |||
805 | snd_hda_shutup_pins(codec); | 825 | snd_hda_shutup_pins(codec); |
806 | } | 826 | } |
807 | 827 | ||
808 | static void alc_free(struct hda_codec *codec) | 828 | #define alc_free snd_hda_gen_free |
809 | { | ||
810 | struct alc_spec *spec = codec->spec; | ||
811 | |||
812 | if (!spec) | ||
813 | return; | ||
814 | |||
815 | snd_hda_gen_spec_free(&spec->gen); | ||
816 | snd_hda_detach_beep_device(codec); | ||
817 | kfree(spec); | ||
818 | } | ||
819 | 829 | ||
820 | #ifdef CONFIG_PM | 830 | #ifdef CONFIG_PM |
821 | static void alc_power_eapd(struct hda_codec *codec) | 831 | static void alc_power_eapd(struct hda_codec *codec) |
@@ -1401,6 +1411,7 @@ static int patch_alc880(struct hda_codec *codec) | |||
1401 | 1411 | ||
1402 | spec = codec->spec; | 1412 | spec = codec->spec; |
1403 | spec->gen.need_dac_fix = 1; | 1413 | spec->gen.need_dac_fix = 1; |
1414 | spec->gen.beep_nid = 0x01; | ||
1404 | 1415 | ||
1405 | snd_hda_pick_fixup(codec, alc880_fixup_models, alc880_fixup_tbl, | 1416 | snd_hda_pick_fixup(codec, alc880_fixup_models, alc880_fixup_tbl, |
1406 | alc880_fixups); | 1417 | alc880_fixups); |
@@ -1411,12 +1422,8 @@ static int patch_alc880(struct hda_codec *codec) | |||
1411 | if (err < 0) | 1422 | if (err < 0) |
1412 | goto error; | 1423 | goto error; |
1413 | 1424 | ||
1414 | if (!spec->gen.no_analog) { | 1425 | if (!spec->gen.no_analog) |
1415 | err = snd_hda_attach_beep_device(codec, 0x1); | ||
1416 | if (err < 0) | ||
1417 | goto error; | ||
1418 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 1426 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
1419 | } | ||
1420 | 1427 | ||
1421 | codec->patch_ops = alc_patch_ops; | 1428 | codec->patch_ops = alc_patch_ops; |
1422 | codec->patch_ops.unsol_event = alc880_unsol_event; | 1429 | codec->patch_ops.unsol_event = alc880_unsol_event; |
@@ -1455,6 +1462,7 @@ enum { | |||
1455 | ALC260_FIXUP_HP_B1900, | 1462 | ALC260_FIXUP_HP_B1900, |
1456 | ALC260_FIXUP_KN1, | 1463 | ALC260_FIXUP_KN1, |
1457 | ALC260_FIXUP_FSC_S7020, | 1464 | ALC260_FIXUP_FSC_S7020, |
1465 | ALC260_FIXUP_FSC_S7020_JWSE, | ||
1458 | }; | 1466 | }; |
1459 | 1467 | ||
1460 | static void alc260_gpio1_automute(struct hda_codec *codec) | 1468 | static void alc260_gpio1_automute(struct hda_codec *codec) |
@@ -1516,14 +1524,17 @@ static void alc260_fixup_fsc_s7020(struct hda_codec *codec, | |||
1516 | const struct hda_fixup *fix, int action) | 1524 | const struct hda_fixup *fix, int action) |
1517 | { | 1525 | { |
1518 | struct alc_spec *spec = codec->spec; | 1526 | struct alc_spec *spec = codec->spec; |
1519 | 1527 | if (action == HDA_FIXUP_ACT_PROBE) | |
1520 | switch (action) { | ||
1521 | case HDA_FIXUP_ACT_PRE_PROBE: | ||
1522 | spec->gen.add_out_jack_modes = 1; | ||
1523 | break; | ||
1524 | case HDA_FIXUP_ACT_PROBE: | ||
1525 | spec->init_amp = ALC_INIT_NONE; | 1528 | spec->init_amp = ALC_INIT_NONE; |
1526 | break; | 1529 | } |
1530 | |||
1531 | static void alc260_fixup_fsc_s7020_jwse(struct hda_codec *codec, | ||
1532 | const struct hda_fixup *fix, int action) | ||
1533 | { | ||
1534 | struct alc_spec *spec = codec->spec; | ||
1535 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | ||
1536 | spec->gen.add_jack_modes = 1; | ||
1537 | spec->gen.hp_mic = 1; | ||
1527 | } | 1538 | } |
1528 | } | 1539 | } |
1529 | 1540 | ||
@@ -1586,6 +1597,12 @@ static const struct hda_fixup alc260_fixups[] = { | |||
1586 | .type = HDA_FIXUP_FUNC, | 1597 | .type = HDA_FIXUP_FUNC, |
1587 | .v.func = alc260_fixup_fsc_s7020, | 1598 | .v.func = alc260_fixup_fsc_s7020, |
1588 | }, | 1599 | }, |
1600 | [ALC260_FIXUP_FSC_S7020_JWSE] = { | ||
1601 | .type = HDA_FIXUP_FUNC, | ||
1602 | .v.func = alc260_fixup_fsc_s7020_jwse, | ||
1603 | .chained = true, | ||
1604 | .chain_id = ALC260_FIXUP_FSC_S7020, | ||
1605 | }, | ||
1589 | }; | 1606 | }; |
1590 | 1607 | ||
1591 | static const struct snd_pci_quirk alc260_fixup_tbl[] = { | 1608 | static const struct snd_pci_quirk alc260_fixup_tbl[] = { |
@@ -1602,6 +1619,14 @@ static const struct snd_pci_quirk alc260_fixup_tbl[] = { | |||
1602 | {} | 1619 | {} |
1603 | }; | 1620 | }; |
1604 | 1621 | ||
1622 | static const struct hda_model_fixup alc260_fixup_models[] = { | ||
1623 | {.id = ALC260_FIXUP_GPIO1, .name = "gpio1"}, | ||
1624 | {.id = ALC260_FIXUP_COEF, .name = "coef"}, | ||
1625 | {.id = ALC260_FIXUP_FSC_S7020, .name = "fujitsu"}, | ||
1626 | {.id = ALC260_FIXUP_FSC_S7020_JWSE, .name = "fujitsu-jwse"}, | ||
1627 | {} | ||
1628 | }; | ||
1629 | |||
1605 | /* | 1630 | /* |
1606 | */ | 1631 | */ |
1607 | static int patch_alc260(struct hda_codec *codec) | 1632 | static int patch_alc260(struct hda_codec *codec) |
@@ -1619,8 +1644,10 @@ static int patch_alc260(struct hda_codec *codec) | |||
1619 | * it's almost harmless. | 1644 | * it's almost harmless. |
1620 | */ | 1645 | */ |
1621 | spec->gen.prefer_hp_amp = 1; | 1646 | spec->gen.prefer_hp_amp = 1; |
1647 | spec->gen.beep_nid = 0x01; | ||
1622 | 1648 | ||
1623 | snd_hda_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups); | 1649 | snd_hda_pick_fixup(codec, alc260_fixup_models, alc260_fixup_tbl, |
1650 | alc260_fixups); | ||
1624 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 1651 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
1625 | 1652 | ||
1626 | /* automatic parse from the BIOS config */ | 1653 | /* automatic parse from the BIOS config */ |
@@ -1628,12 +1655,8 @@ static int patch_alc260(struct hda_codec *codec) | |||
1628 | if (err < 0) | 1655 | if (err < 0) |
1629 | goto error; | 1656 | goto error; |
1630 | 1657 | ||
1631 | if (!spec->gen.no_analog) { | 1658 | if (!spec->gen.no_analog) |
1632 | err = snd_hda_attach_beep_device(codec, 0x1); | ||
1633 | if (err < 0) | ||
1634 | goto error; | ||
1635 | set_beep_amp(spec, 0x07, 0x05, HDA_INPUT); | 1659 | set_beep_amp(spec, 0x07, 0x05, HDA_INPUT); |
1636 | } | ||
1637 | 1660 | ||
1638 | codec->patch_ops = alc_patch_ops; | 1661 | codec->patch_ops = alc_patch_ops; |
1639 | spec->shutup = alc_eapd_shutup; | 1662 | spec->shutup = alc_eapd_shutup; |
@@ -2132,17 +2155,16 @@ static int patch_alc882(struct hda_codec *codec) | |||
2132 | 2155 | ||
2133 | alc_auto_parse_customize_define(codec); | 2156 | alc_auto_parse_customize_define(codec); |
2134 | 2157 | ||
2158 | if (has_cdefine_beep(codec)) | ||
2159 | spec->gen.beep_nid = 0x01; | ||
2160 | |||
2135 | /* automatic parse from the BIOS config */ | 2161 | /* automatic parse from the BIOS config */ |
2136 | err = alc882_parse_auto_config(codec); | 2162 | err = alc882_parse_auto_config(codec); |
2137 | if (err < 0) | 2163 | if (err < 0) |
2138 | goto error; | 2164 | goto error; |
2139 | 2165 | ||
2140 | if (!spec->gen.no_analog && has_cdefine_beep(codec)) { | 2166 | if (!spec->gen.no_analog && spec->gen.beep_nid) |
2141 | err = snd_hda_attach_beep_device(codec, 0x1); | ||
2142 | if (err < 0) | ||
2143 | goto error; | ||
2144 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 2167 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
2145 | } | ||
2146 | 2168 | ||
2147 | codec->patch_ops = alc_patch_ops; | 2169 | codec->patch_ops = alc_patch_ops; |
2148 | 2170 | ||
@@ -2295,17 +2317,16 @@ static int patch_alc262(struct hda_codec *codec) | |||
2295 | 2317 | ||
2296 | alc_auto_parse_customize_define(codec); | 2318 | alc_auto_parse_customize_define(codec); |
2297 | 2319 | ||
2320 | if (has_cdefine_beep(codec)) | ||
2321 | spec->gen.beep_nid = 0x01; | ||
2322 | |||
2298 | /* automatic parse from the BIOS config */ | 2323 | /* automatic parse from the BIOS config */ |
2299 | err = alc262_parse_auto_config(codec); | 2324 | err = alc262_parse_auto_config(codec); |
2300 | if (err < 0) | 2325 | if (err < 0) |
2301 | goto error; | 2326 | goto error; |
2302 | 2327 | ||
2303 | if (!spec->gen.no_analog && has_cdefine_beep(codec)) { | 2328 | if (!spec->gen.no_analog && spec->gen.beep_nid) |
2304 | err = snd_hda_attach_beep_device(codec, 0x1); | ||
2305 | if (err < 0) | ||
2306 | goto error; | ||
2307 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 2329 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
2308 | } | ||
2309 | 2330 | ||
2310 | codec->patch_ops = alc_patch_ops; | 2331 | codec->patch_ops = alc_patch_ops; |
2311 | spec->shutup = alc_eapd_shutup; | 2332 | spec->shutup = alc_eapd_shutup; |
@@ -2386,16 +2407,7 @@ static const struct snd_pci_quirk alc268_fixup_tbl[] = { | |||
2386 | static int alc268_parse_auto_config(struct hda_codec *codec) | 2407 | static int alc268_parse_auto_config(struct hda_codec *codec) |
2387 | { | 2408 | { |
2388 | static const hda_nid_t alc268_ssids[] = { 0x15, 0x1b, 0x14, 0 }; | 2409 | static const hda_nid_t alc268_ssids[] = { 0x15, 0x1b, 0x14, 0 }; |
2389 | struct alc_spec *spec = codec->spec; | 2410 | return alc_parse_auto_config(codec, NULL, alc268_ssids); |
2390 | int err = alc_parse_auto_config(codec, NULL, alc268_ssids); | ||
2391 | if (err > 0) { | ||
2392 | if (!spec->gen.no_analog && | ||
2393 | spec->gen.autocfg.speaker_pins[0] != 0x1d) { | ||
2394 | add_mixer(spec, alc268_beep_mixer); | ||
2395 | snd_hda_add_verbs(codec, alc268_beep_init_verbs); | ||
2396 | } | ||
2397 | } | ||
2398 | return err; | ||
2399 | } | 2411 | } |
2400 | 2412 | ||
2401 | /* | 2413 | /* |
@@ -2403,7 +2415,7 @@ static int alc268_parse_auto_config(struct hda_codec *codec) | |||
2403 | static int patch_alc268(struct hda_codec *codec) | 2415 | static int patch_alc268(struct hda_codec *codec) |
2404 | { | 2416 | { |
2405 | struct alc_spec *spec; | 2417 | struct alc_spec *spec; |
2406 | int i, has_beep, err; | 2418 | int err; |
2407 | 2419 | ||
2408 | /* ALC268 has no aa-loopback mixer */ | 2420 | /* ALC268 has no aa-loopback mixer */ |
2409 | err = alc_alloc_spec(codec, 0); | 2421 | err = alc_alloc_spec(codec, 0); |
@@ -2411,6 +2423,7 @@ static int patch_alc268(struct hda_codec *codec) | |||
2411 | return err; | 2423 | return err; |
2412 | 2424 | ||
2413 | spec = codec->spec; | 2425 | spec = codec->spec; |
2426 | spec->gen.beep_nid = 0x01; | ||
2414 | 2427 | ||
2415 | snd_hda_pick_fixup(codec, alc268_fixup_models, alc268_fixup_tbl, alc268_fixups); | 2428 | snd_hda_pick_fixup(codec, alc268_fixup_models, alc268_fixup_tbl, alc268_fixups); |
2416 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 2429 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
@@ -2420,18 +2433,10 @@ static int patch_alc268(struct hda_codec *codec) | |||
2420 | if (err < 0) | 2433 | if (err < 0) |
2421 | goto error; | 2434 | goto error; |
2422 | 2435 | ||
2423 | has_beep = 0; | 2436 | if (err > 0 && !spec->gen.no_analog && |
2424 | for (i = 0; i < spec->num_mixers; i++) { | 2437 | spec->gen.autocfg.speaker_pins[0] != 0x1d) { |
2425 | if (spec->mixers[i] == alc268_beep_mixer) { | 2438 | add_mixer(spec, alc268_beep_mixer); |
2426 | has_beep = 1; | 2439 | snd_hda_add_verbs(codec, alc268_beep_init_verbs); |
2427 | break; | ||
2428 | } | ||
2429 | } | ||
2430 | |||
2431 | if (has_beep) { | ||
2432 | err = snd_hda_attach_beep_device(codec, 0x1); | ||
2433 | if (err < 0) | ||
2434 | goto error; | ||
2435 | if (!query_amp_caps(codec, 0x1d, HDA_INPUT)) | 2440 | if (!query_amp_caps(codec, 0x1d, HDA_INPUT)) |
2436 | /* override the amp caps for beep generator */ | 2441 | /* override the amp caps for beep generator */ |
2437 | snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT, | 2442 | snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT, |
@@ -2515,6 +2520,7 @@ enum { | |||
2515 | ALC269_TYPE_ALC280, | 2520 | ALC269_TYPE_ALC280, |
2516 | ALC269_TYPE_ALC282, | 2521 | ALC269_TYPE_ALC282, |
2517 | ALC269_TYPE_ALC284, | 2522 | ALC269_TYPE_ALC284, |
2523 | ALC269_TYPE_ALC286, | ||
2518 | }; | 2524 | }; |
2519 | 2525 | ||
2520 | /* | 2526 | /* |
@@ -2538,6 +2544,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
2538 | case ALC269_TYPE_ALC269VB: | 2544 | case ALC269_TYPE_ALC269VB: |
2539 | case ALC269_TYPE_ALC269VD: | 2545 | case ALC269_TYPE_ALC269VD: |
2540 | case ALC269_TYPE_ALC282: | 2546 | case ALC269_TYPE_ALC282: |
2547 | case ALC269_TYPE_ALC286: | ||
2541 | ssids = alc269_ssids; | 2548 | ssids = alc269_ssids; |
2542 | break; | 2549 | break; |
2543 | default: | 2550 | default: |
@@ -2631,7 +2638,8 @@ static void alc271_fixup_dmic(struct hda_codec *codec, | |||
2631 | }; | 2638 | }; |
2632 | unsigned int cfg; | 2639 | unsigned int cfg; |
2633 | 2640 | ||
2634 | if (strcmp(codec->chip_name, "ALC271X")) | 2641 | if (strcmp(codec->chip_name, "ALC271X") && |
2642 | strcmp(codec->chip_name, "ALC269VB")) | ||
2635 | return; | 2643 | return; |
2636 | cfg = snd_hda_codec_get_pincfg(codec, 0x12); | 2644 | cfg = snd_hda_codec_get_pincfg(codec, 0x12); |
2637 | if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED) | 2645 | if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED) |
@@ -2693,6 +2701,34 @@ static void alc269_fixup_quanta_mute(struct hda_codec *codec, | |||
2693 | spec->gen.automute_hook = alc269_quanta_automute; | 2701 | spec->gen.automute_hook = alc269_quanta_automute; |
2694 | } | 2702 | } |
2695 | 2703 | ||
2704 | static void alc269_x101_hp_automute_hook(struct hda_codec *codec, | ||
2705 | struct hda_jack_tbl *jack) | ||
2706 | { | ||
2707 | struct alc_spec *spec = codec->spec; | ||
2708 | int vref; | ||
2709 | msleep(200); | ||
2710 | snd_hda_gen_hp_automute(codec, jack); | ||
2711 | |||
2712 | vref = spec->gen.hp_jack_present ? PIN_VREF80 : 0; | ||
2713 | msleep(100); | ||
2714 | snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
2715 | vref); | ||
2716 | msleep(500); | ||
2717 | snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
2718 | vref); | ||
2719 | } | ||
2720 | |||
2721 | static void alc269_fixup_x101_headset_mic(struct hda_codec *codec, | ||
2722 | const struct hda_fixup *fix, int action) | ||
2723 | { | ||
2724 | struct alc_spec *spec = codec->spec; | ||
2725 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | ||
2726 | spec->parse_flags |= HDA_PINCFG_HEADSET_MIC; | ||
2727 | spec->gen.hp_automute_hook = alc269_x101_hp_automute_hook; | ||
2728 | } | ||
2729 | } | ||
2730 | |||
2731 | |||
2696 | /* update mute-LED according to the speaker mute state via mic VREF pin */ | 2732 | /* update mute-LED according to the speaker mute state via mic VREF pin */ |
2697 | static void alc269_fixup_mic_mute_hook(void *private_data, int enabled) | 2733 | static void alc269_fixup_mic_mute_hook(void *private_data, int enabled) |
2698 | { | 2734 | { |
@@ -2757,6 +2793,356 @@ static void alc269_fixup_hp_mute_led_mic2(struct hda_codec *codec, | |||
2757 | } | 2793 | } |
2758 | } | 2794 | } |
2759 | 2795 | ||
2796 | /* turn on/off mute LED per vmaster hook */ | ||
2797 | static void alc269_fixup_hp_gpio_mute_hook(void *private_data, int enabled) | ||
2798 | { | ||
2799 | struct hda_codec *codec = private_data; | ||
2800 | struct alc_spec *spec = codec->spec; | ||
2801 | unsigned int oldval = spec->gpio_led; | ||
2802 | |||
2803 | if (enabled) | ||
2804 | spec->gpio_led &= ~0x08; | ||
2805 | else | ||
2806 | spec->gpio_led |= 0x08; | ||
2807 | if (spec->gpio_led != oldval) | ||
2808 | snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, | ||
2809 | spec->gpio_led); | ||
2810 | } | ||
2811 | |||
2812 | /* turn on/off mic-mute LED per capture hook */ | ||
2813 | static void alc269_fixup_hp_gpio_mic_mute_hook(struct hda_codec *codec, | ||
2814 | struct snd_ctl_elem_value *ucontrol) | ||
2815 | { | ||
2816 | struct alc_spec *spec = codec->spec; | ||
2817 | unsigned int oldval = spec->gpio_led; | ||
2818 | |||
2819 | if (!ucontrol) | ||
2820 | return; | ||
2821 | |||
2822 | if (ucontrol->value.integer.value[0] || | ||
2823 | ucontrol->value.integer.value[1]) | ||
2824 | spec->gpio_led &= ~0x10; | ||
2825 | else | ||
2826 | spec->gpio_led |= 0x10; | ||
2827 | if (spec->gpio_led != oldval) | ||
2828 | snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, | ||
2829 | spec->gpio_led); | ||
2830 | } | ||
2831 | |||
2832 | static void alc269_fixup_hp_gpio_led(struct hda_codec *codec, | ||
2833 | const struct hda_fixup *fix, int action) | ||
2834 | { | ||
2835 | struct alc_spec *spec = codec->spec; | ||
2836 | static const struct hda_verb gpio_init[] = { | ||
2837 | { 0x01, AC_VERB_SET_GPIO_MASK, 0x18 }, | ||
2838 | { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x18 }, | ||
2839 | {} | ||
2840 | }; | ||
2841 | |||
2842 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | ||
2843 | spec->gen.vmaster_mute.hook = alc269_fixup_hp_gpio_mute_hook; | ||
2844 | spec->gen.cap_sync_hook = alc269_fixup_hp_gpio_mic_mute_hook; | ||
2845 | spec->gpio_led = 0; | ||
2846 | snd_hda_add_verbs(codec, gpio_init); | ||
2847 | } | ||
2848 | } | ||
2849 | |||
2850 | static void alc_headset_mode_unplugged(struct hda_codec *codec) | ||
2851 | { | ||
2852 | int val; | ||
2853 | |||
2854 | switch (codec->vendor_id) { | ||
2855 | case 0x10ec0283: | ||
2856 | alc_write_coef_idx(codec, 0x1b, 0x0c0b); | ||
2857 | alc_write_coef_idx(codec, 0x45, 0xc429); | ||
2858 | val = alc_read_coef_idx(codec, 0x35); | ||
2859 | alc_write_coef_idx(codec, 0x35, val & 0xbfff); | ||
2860 | alc_write_coef_idx(codec, 0x06, 0x2104); | ||
2861 | alc_write_coef_idx(codec, 0x1a, 0x0001); | ||
2862 | alc_write_coef_idx(codec, 0x26, 0x0004); | ||
2863 | alc_write_coef_idx(codec, 0x32, 0x42a3); | ||
2864 | break; | ||
2865 | case 0x10ec0292: | ||
2866 | alc_write_coef_idx(codec, 0x76, 0x000e); | ||
2867 | alc_write_coef_idx(codec, 0x6c, 0x2400); | ||
2868 | alc_write_coef_idx(codec, 0x18, 0x7308); | ||
2869 | alc_write_coef_idx(codec, 0x6b, 0xc429); | ||
2870 | break; | ||
2871 | case 0x10ec0668: | ||
2872 | alc_write_coef_idx(codec, 0x15, 0x0d40); | ||
2873 | alc_write_coef_idx(codec, 0xb7, 0x802b); | ||
2874 | break; | ||
2875 | } | ||
2876 | snd_printdd("Headset jack set to unplugged mode.\n"); | ||
2877 | } | ||
2878 | |||
2879 | |||
2880 | static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, | ||
2881 | hda_nid_t mic_pin) | ||
2882 | { | ||
2883 | int val; | ||
2884 | |||
2885 | switch (codec->vendor_id) { | ||
2886 | case 0x10ec0283: | ||
2887 | alc_write_coef_idx(codec, 0x45, 0xc429); | ||
2888 | snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); | ||
2889 | val = alc_read_coef_idx(codec, 0x35); | ||
2890 | alc_write_coef_idx(codec, 0x35, val | 1<<14); | ||
2891 | alc_write_coef_idx(codec, 0x06, 0x2100); | ||
2892 | alc_write_coef_idx(codec, 0x1a, 0x0021); | ||
2893 | alc_write_coef_idx(codec, 0x26, 0x008c); | ||
2894 | snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); | ||
2895 | break; | ||
2896 | case 0x10ec0292: | ||
2897 | snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); | ||
2898 | alc_write_coef_idx(codec, 0x19, 0xa208); | ||
2899 | alc_write_coef_idx(codec, 0x2e, 0xacf0); | ||
2900 | break; | ||
2901 | case 0x10ec0668: | ||
2902 | alc_write_coef_idx(codec, 0x11, 0x0001); | ||
2903 | snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); | ||
2904 | alc_write_coef_idx(codec, 0xb7, 0x802b); | ||
2905 | alc_write_coef_idx(codec, 0xb5, 0x1040); | ||
2906 | val = alc_read_coef_idx(codec, 0xc3); | ||
2907 | alc_write_coef_idx(codec, 0xc3, val | 1<<12); | ||
2908 | snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); | ||
2909 | break; | ||
2910 | } | ||
2911 | snd_printdd("Headset jack set to mic-in mode.\n"); | ||
2912 | } | ||
2913 | |||
2914 | static void alc_headset_mode_default(struct hda_codec *codec) | ||
2915 | { | ||
2916 | switch (codec->vendor_id) { | ||
2917 | case 0x10ec0283: | ||
2918 | alc_write_coef_idx(codec, 0x06, 0x2100); | ||
2919 | alc_write_coef_idx(codec, 0x32, 0x4ea3); | ||
2920 | break; | ||
2921 | case 0x10ec0292: | ||
2922 | alc_write_coef_idx(codec, 0x76, 0x000e); | ||
2923 | alc_write_coef_idx(codec, 0x6c, 0x2400); | ||
2924 | alc_write_coef_idx(codec, 0x6b, 0xc429); | ||
2925 | alc_write_coef_idx(codec, 0x18, 0x7308); | ||
2926 | break; | ||
2927 | case 0x10ec0668: | ||
2928 | alc_write_coef_idx(codec, 0x11, 0x0041); | ||
2929 | alc_write_coef_idx(codec, 0x15, 0x0d40); | ||
2930 | alc_write_coef_idx(codec, 0xb7, 0x802b); | ||
2931 | break; | ||
2932 | } | ||
2933 | snd_printdd("Headset jack set to headphone (default) mode.\n"); | ||
2934 | } | ||
2935 | |||
2936 | /* Iphone type */ | ||
2937 | static void alc_headset_mode_ctia(struct hda_codec *codec) | ||
2938 | { | ||
2939 | switch (codec->vendor_id) { | ||
2940 | case 0x10ec0283: | ||
2941 | alc_write_coef_idx(codec, 0x45, 0xd429); | ||
2942 | alc_write_coef_idx(codec, 0x1b, 0x0c2b); | ||
2943 | alc_write_coef_idx(codec, 0x32, 0x4ea3); | ||
2944 | break; | ||
2945 | case 0x10ec0292: | ||
2946 | alc_write_coef_idx(codec, 0x6b, 0xd429); | ||
2947 | alc_write_coef_idx(codec, 0x76, 0x0008); | ||
2948 | alc_write_coef_idx(codec, 0x18, 0x7388); | ||
2949 | break; | ||
2950 | case 0x10ec0668: | ||
2951 | alc_write_coef_idx(codec, 0x15, 0x0d60); | ||
2952 | alc_write_coef_idx(codec, 0xc3, 0x0000); | ||
2953 | break; | ||
2954 | } | ||
2955 | snd_printdd("Headset jack set to iPhone-style headset mode.\n"); | ||
2956 | } | ||
2957 | |||
2958 | /* Nokia type */ | ||
2959 | static void alc_headset_mode_omtp(struct hda_codec *codec) | ||
2960 | { | ||
2961 | switch (codec->vendor_id) { | ||
2962 | case 0x10ec0283: | ||
2963 | alc_write_coef_idx(codec, 0x45, 0xe429); | ||
2964 | alc_write_coef_idx(codec, 0x1b, 0x0c2b); | ||
2965 | alc_write_coef_idx(codec, 0x32, 0x4ea3); | ||
2966 | break; | ||
2967 | case 0x10ec0292: | ||
2968 | alc_write_coef_idx(codec, 0x6b, 0xe429); | ||
2969 | alc_write_coef_idx(codec, 0x76, 0x0008); | ||
2970 | alc_write_coef_idx(codec, 0x18, 0x7388); | ||
2971 | break; | ||
2972 | case 0x10ec0668: | ||
2973 | alc_write_coef_idx(codec, 0x15, 0x0d50); | ||
2974 | alc_write_coef_idx(codec, 0xc3, 0x0000); | ||
2975 | break; | ||
2976 | } | ||
2977 | snd_printdd("Headset jack set to Nokia-style headset mode.\n"); | ||
2978 | } | ||
2979 | |||
2980 | static void alc_determine_headset_type(struct hda_codec *codec) | ||
2981 | { | ||
2982 | int val; | ||
2983 | bool is_ctia = false; | ||
2984 | struct alc_spec *spec = codec->spec; | ||
2985 | |||
2986 | switch (codec->vendor_id) { | ||
2987 | case 0x10ec0283: | ||
2988 | alc_write_coef_idx(codec, 0x45, 0xd029); | ||
2989 | msleep(300); | ||
2990 | val = alc_read_coef_idx(codec, 0x46); | ||
2991 | is_ctia = (val & 0x0070) == 0x0070; | ||
2992 | break; | ||
2993 | case 0x10ec0292: | ||
2994 | alc_write_coef_idx(codec, 0x6b, 0xd429); | ||
2995 | msleep(300); | ||
2996 | val = alc_read_coef_idx(codec, 0x6c); | ||
2997 | is_ctia = (val & 0x001c) == 0x001c; | ||
2998 | break; | ||
2999 | case 0x10ec0668: | ||
3000 | alc_write_coef_idx(codec, 0x11, 0x0001); | ||
3001 | alc_write_coef_idx(codec, 0xb7, 0x802b); | ||
3002 | alc_write_coef_idx(codec, 0x15, 0x0d60); | ||
3003 | alc_write_coef_idx(codec, 0xc3, 0x0c00); | ||
3004 | msleep(300); | ||
3005 | val = alc_read_coef_idx(codec, 0xbe); | ||
3006 | is_ctia = (val & 0x1c02) == 0x1c02; | ||
3007 | break; | ||
3008 | } | ||
3009 | |||
3010 | snd_printdd("Headset jack detected iPhone-style headset: %s\n", | ||
3011 | is_ctia ? "yes" : "no"); | ||
3012 | spec->current_headset_type = is_ctia ? ALC_HEADSET_TYPE_CTIA : ALC_HEADSET_TYPE_OMTP; | ||
3013 | } | ||
3014 | |||
3015 | static void alc_update_headset_mode(struct hda_codec *codec) | ||
3016 | { | ||
3017 | struct alc_spec *spec = codec->spec; | ||
3018 | |||
3019 | hda_nid_t mux_pin = spec->gen.imux_pins[spec->gen.cur_mux[0]]; | ||
3020 | hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; | ||
3021 | |||
3022 | int new_headset_mode; | ||
3023 | |||
3024 | if (!snd_hda_jack_detect(codec, hp_pin)) | ||
3025 | new_headset_mode = ALC_HEADSET_MODE_UNPLUGGED; | ||
3026 | else if (mux_pin == spec->headset_mic_pin) | ||
3027 | new_headset_mode = ALC_HEADSET_MODE_HEADSET; | ||
3028 | else if (mux_pin == spec->headphone_mic_pin) | ||
3029 | new_headset_mode = ALC_HEADSET_MODE_MIC; | ||
3030 | else | ||
3031 | new_headset_mode = ALC_HEADSET_MODE_HEADPHONE; | ||
3032 | |||
3033 | if (new_headset_mode == spec->current_headset_mode) | ||
3034 | return; | ||
3035 | |||
3036 | switch (new_headset_mode) { | ||
3037 | case ALC_HEADSET_MODE_UNPLUGGED: | ||
3038 | alc_headset_mode_unplugged(codec); | ||
3039 | spec->gen.hp_jack_present = false; | ||
3040 | break; | ||
3041 | case ALC_HEADSET_MODE_HEADSET: | ||
3042 | if (spec->current_headset_type == ALC_HEADSET_TYPE_UNKNOWN) | ||
3043 | alc_determine_headset_type(codec); | ||
3044 | if (spec->current_headset_type == ALC_HEADSET_TYPE_CTIA) | ||
3045 | alc_headset_mode_ctia(codec); | ||
3046 | else if (spec->current_headset_type == ALC_HEADSET_TYPE_OMTP) | ||
3047 | alc_headset_mode_omtp(codec); | ||
3048 | spec->gen.hp_jack_present = true; | ||
3049 | break; | ||
3050 | case ALC_HEADSET_MODE_MIC: | ||
3051 | alc_headset_mode_mic_in(codec, hp_pin, spec->headphone_mic_pin); | ||
3052 | spec->gen.hp_jack_present = false; | ||
3053 | break; | ||
3054 | case ALC_HEADSET_MODE_HEADPHONE: | ||
3055 | alc_headset_mode_default(codec); | ||
3056 | spec->gen.hp_jack_present = true; | ||
3057 | break; | ||
3058 | } | ||
3059 | if (new_headset_mode != ALC_HEADSET_MODE_MIC) { | ||
3060 | snd_hda_set_pin_ctl_cache(codec, hp_pin, | ||
3061 | AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN); | ||
3062 | if (spec->headphone_mic_pin) | ||
3063 | snd_hda_set_pin_ctl_cache(codec, spec->headphone_mic_pin, | ||
3064 | PIN_VREFHIZ); | ||
3065 | } | ||
3066 | spec->current_headset_mode = new_headset_mode; | ||
3067 | |||
3068 | snd_hda_gen_update_outputs(codec); | ||
3069 | } | ||
3070 | |||
3071 | static void alc_update_headset_mode_hook(struct hda_codec *codec, | ||
3072 | struct snd_ctl_elem_value *ucontrol) | ||
3073 | { | ||
3074 | alc_update_headset_mode(codec); | ||
3075 | } | ||
3076 | |||
3077 | static void alc_update_headset_jack_cb(struct hda_codec *codec, struct hda_jack_tbl *jack) | ||
3078 | { | ||
3079 | struct alc_spec *spec = codec->spec; | ||
3080 | spec->current_headset_type = ALC_HEADSET_MODE_UNKNOWN; | ||
3081 | snd_hda_gen_hp_automute(codec, jack); | ||
3082 | } | ||
3083 | |||
3084 | static void alc_probe_headset_mode(struct hda_codec *codec) | ||
3085 | { | ||
3086 | int i; | ||
3087 | struct alc_spec *spec = codec->spec; | ||
3088 | struct auto_pin_cfg *cfg = &spec->gen.autocfg; | ||
3089 | |||
3090 | /* Find mic pins */ | ||
3091 | for (i = 0; i < cfg->num_inputs; i++) { | ||
3092 | if (cfg->inputs[i].is_headset_mic && !spec->headset_mic_pin) | ||
3093 | spec->headset_mic_pin = cfg->inputs[i].pin; | ||
3094 | if (cfg->inputs[i].is_headphone_mic && !spec->headphone_mic_pin) | ||
3095 | spec->headphone_mic_pin = cfg->inputs[i].pin; | ||
3096 | } | ||
3097 | |||
3098 | spec->gen.cap_sync_hook = alc_update_headset_mode_hook; | ||
3099 | spec->gen.automute_hook = alc_update_headset_mode; | ||
3100 | spec->gen.hp_automute_hook = alc_update_headset_jack_cb; | ||
3101 | } | ||
3102 | |||
3103 | static void alc_fixup_headset_mode(struct hda_codec *codec, | ||
3104 | const struct hda_fixup *fix, int action) | ||
3105 | { | ||
3106 | struct alc_spec *spec = codec->spec; | ||
3107 | |||
3108 | switch (action) { | ||
3109 | case HDA_FIXUP_ACT_PRE_PROBE: | ||
3110 | spec->parse_flags |= HDA_PINCFG_HEADSET_MIC | HDA_PINCFG_HEADPHONE_MIC; | ||
3111 | break; | ||
3112 | case HDA_FIXUP_ACT_PROBE: | ||
3113 | alc_probe_headset_mode(codec); | ||
3114 | break; | ||
3115 | case HDA_FIXUP_ACT_INIT: | ||
3116 | spec->current_headset_mode = 0; | ||
3117 | alc_update_headset_mode(codec); | ||
3118 | break; | ||
3119 | } | ||
3120 | } | ||
3121 | |||
3122 | static void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec, | ||
3123 | const struct hda_fixup *fix, int action) | ||
3124 | { | ||
3125 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | ||
3126 | struct alc_spec *spec = codec->spec; | ||
3127 | spec->parse_flags |= HDA_PINCFG_HEADSET_MIC; | ||
3128 | } | ||
3129 | else | ||
3130 | alc_fixup_headset_mode(codec, fix, action); | ||
3131 | } | ||
3132 | |||
3133 | static void alc_fixup_headset_mode_alc668(struct hda_codec *codec, | ||
3134 | const struct hda_fixup *fix, int action) | ||
3135 | { | ||
3136 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | ||
3137 | int val; | ||
3138 | alc_write_coef_idx(codec, 0xc4, 0x8000); | ||
3139 | val = alc_read_coef_idx(codec, 0xc2); | ||
3140 | alc_write_coef_idx(codec, 0xc2, val & 0xfe); | ||
3141 | snd_hda_set_pin_ctl_cache(codec, 0x18, 0); | ||
3142 | } | ||
3143 | alc_fixup_headset_mode(codec, fix, action); | ||
3144 | } | ||
3145 | |||
2760 | static void alc271_hp_gate_mic_jack(struct hda_codec *codec, | 3146 | static void alc271_hp_gate_mic_jack(struct hda_codec *codec, |
2761 | const struct hda_fixup *fix, | 3147 | const struct hda_fixup *fix, |
2762 | int action) | 3148 | int action) |
@@ -2772,6 +3158,38 @@ static void alc271_hp_gate_mic_jack(struct hda_codec *codec, | |||
2772 | } | 3158 | } |
2773 | } | 3159 | } |
2774 | 3160 | ||
3161 | static void alc269_fixup_limit_int_mic_boost(struct hda_codec *codec, | ||
3162 | const struct hda_fixup *fix, | ||
3163 | int action) | ||
3164 | { | ||
3165 | struct alc_spec *spec = codec->spec; | ||
3166 | struct auto_pin_cfg *cfg = &spec->gen.autocfg; | ||
3167 | int i; | ||
3168 | |||
3169 | /* The mic boosts on level 2 and 3 are too noisy | ||
3170 | on the internal mic input. | ||
3171 | Therefore limit the boost to 0 or 1. */ | ||
3172 | |||
3173 | if (action != HDA_FIXUP_ACT_PROBE) | ||
3174 | return; | ||
3175 | |||
3176 | for (i = 0; i < cfg->num_inputs; i++) { | ||
3177 | hda_nid_t nid = cfg->inputs[i].pin; | ||
3178 | unsigned int defcfg; | ||
3179 | if (cfg->inputs[i].type != AUTO_PIN_MIC) | ||
3180 | continue; | ||
3181 | defcfg = snd_hda_codec_get_pincfg(codec, nid); | ||
3182 | if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT) | ||
3183 | continue; | ||
3184 | |||
3185 | snd_hda_override_amp_caps(codec, nid, HDA_INPUT, | ||
3186 | (0x00 << AC_AMPCAP_OFFSET_SHIFT) | | ||
3187 | (0x01 << AC_AMPCAP_NUM_STEPS_SHIFT) | | ||
3188 | (0x2f << AC_AMPCAP_STEP_SIZE_SHIFT) | | ||
3189 | (0 << AC_AMPCAP_MUTE_SHIFT)); | ||
3190 | } | ||
3191 | } | ||
3192 | |||
2775 | enum { | 3193 | enum { |
2776 | ALC269_FIXUP_SONY_VAIO, | 3194 | ALC269_FIXUP_SONY_VAIO, |
2777 | ALC275_FIXUP_SONY_VAIO_GPIO2, | 3195 | ALC275_FIXUP_SONY_VAIO_GPIO2, |
@@ -2792,11 +3210,21 @@ enum { | |||
2792 | ALC269_FIXUP_HP_MUTE_LED, | 3210 | ALC269_FIXUP_HP_MUTE_LED, |
2793 | ALC269_FIXUP_HP_MUTE_LED_MIC1, | 3211 | ALC269_FIXUP_HP_MUTE_LED_MIC1, |
2794 | ALC269_FIXUP_HP_MUTE_LED_MIC2, | 3212 | ALC269_FIXUP_HP_MUTE_LED_MIC2, |
3213 | ALC269_FIXUP_HP_GPIO_LED, | ||
2795 | ALC269_FIXUP_INV_DMIC, | 3214 | ALC269_FIXUP_INV_DMIC, |
2796 | ALC269_FIXUP_LENOVO_DOCK, | 3215 | ALC269_FIXUP_LENOVO_DOCK, |
2797 | ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT, | 3216 | ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT, |
3217 | ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, | ||
3218 | ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, | ||
3219 | ALC269_FIXUP_HEADSET_MODE, | ||
3220 | ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC, | ||
3221 | ALC269_FIXUP_ASUS_X101_FUNC, | ||
3222 | ALC269_FIXUP_ASUS_X101_VERB, | ||
3223 | ALC269_FIXUP_ASUS_X101, | ||
2798 | ALC271_FIXUP_AMIC_MIC2, | 3224 | ALC271_FIXUP_AMIC_MIC2, |
2799 | ALC271_FIXUP_HP_GATE_MIC_JACK, | 3225 | ALC271_FIXUP_HP_GATE_MIC_JACK, |
3226 | ALC269_FIXUP_ACER_AC700, | ||
3227 | ALC269_FIXUP_LIMIT_INT_MIC_BOOST, | ||
2800 | }; | 3228 | }; |
2801 | 3229 | ||
2802 | static const struct hda_fixup alc269_fixups[] = { | 3230 | static const struct hda_fixup alc269_fixups[] = { |
@@ -2931,6 +3359,10 @@ static const struct hda_fixup alc269_fixups[] = { | |||
2931 | .type = HDA_FIXUP_FUNC, | 3359 | .type = HDA_FIXUP_FUNC, |
2932 | .v.func = alc269_fixup_hp_mute_led_mic2, | 3360 | .v.func = alc269_fixup_hp_mute_led_mic2, |
2933 | }, | 3361 | }, |
3362 | [ALC269_FIXUP_HP_GPIO_LED] = { | ||
3363 | .type = HDA_FIXUP_FUNC, | ||
3364 | .v.func = alc269_fixup_hp_gpio_led, | ||
3365 | }, | ||
2934 | [ALC269_FIXUP_INV_DMIC] = { | 3366 | [ALC269_FIXUP_INV_DMIC] = { |
2935 | .type = HDA_FIXUP_FUNC, | 3367 | .type = HDA_FIXUP_FUNC, |
2936 | .v.func = alc_fixup_inv_dmic_0x12, | 3368 | .v.func = alc_fixup_inv_dmic_0x12, |
@@ -2949,6 +3381,59 @@ static const struct hda_fixup alc269_fixups[] = { | |||
2949 | .type = HDA_FIXUP_FUNC, | 3381 | .type = HDA_FIXUP_FUNC, |
2950 | .v.func = alc269_fixup_pincfg_no_hp_to_lineout, | 3382 | .v.func = alc269_fixup_pincfg_no_hp_to_lineout, |
2951 | }, | 3383 | }, |
3384 | [ALC269_FIXUP_DELL1_MIC_NO_PRESENCE] = { | ||
3385 | .type = HDA_FIXUP_PINS, | ||
3386 | .v.pins = (const struct hda_pintbl[]) { | ||
3387 | { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */ | ||
3388 | { 0x1a, 0x01a1913d }, /* use as headphone mic, without its own jack detect */ | ||
3389 | { } | ||
3390 | }, | ||
3391 | .chained = true, | ||
3392 | .chain_id = ALC269_FIXUP_HEADSET_MODE | ||
3393 | }, | ||
3394 | [ALC269_FIXUP_DELL2_MIC_NO_PRESENCE] = { | ||
3395 | .type = HDA_FIXUP_PINS, | ||
3396 | .v.pins = (const struct hda_pintbl[]) { | ||
3397 | { 0x16, 0x21014020 }, /* dock line out */ | ||
3398 | { 0x19, 0x21a19030 }, /* dock mic */ | ||
3399 | { 0x1a, 0x01a1913c }, /* use as headset mic, without its own jack detect */ | ||
3400 | { } | ||
3401 | }, | ||
3402 | .chained = true, | ||
3403 | .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC | ||
3404 | }, | ||
3405 | [ALC269_FIXUP_HEADSET_MODE] = { | ||
3406 | .type = HDA_FIXUP_FUNC, | ||
3407 | .v.func = alc_fixup_headset_mode, | ||
3408 | }, | ||
3409 | [ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC] = { | ||
3410 | .type = HDA_FIXUP_FUNC, | ||
3411 | .v.func = alc_fixup_headset_mode_no_hp_mic, | ||
3412 | }, | ||
3413 | [ALC269_FIXUP_ASUS_X101_FUNC] = { | ||
3414 | .type = HDA_FIXUP_FUNC, | ||
3415 | .v.func = alc269_fixup_x101_headset_mic, | ||
3416 | }, | ||
3417 | [ALC269_FIXUP_ASUS_X101_VERB] = { | ||
3418 | .type = HDA_FIXUP_VERBS, | ||
3419 | .v.verbs = (const struct hda_verb[]) { | ||
3420 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, | ||
3421 | {0x20, AC_VERB_SET_COEF_INDEX, 0x08}, | ||
3422 | {0x20, AC_VERB_SET_PROC_COEF, 0x0310}, | ||
3423 | { } | ||
3424 | }, | ||
3425 | .chained = true, | ||
3426 | .chain_id = ALC269_FIXUP_ASUS_X101_FUNC | ||
3427 | }, | ||
3428 | [ALC269_FIXUP_ASUS_X101] = { | ||
3429 | .type = HDA_FIXUP_PINS, | ||
3430 | .v.pins = (const struct hda_pintbl[]) { | ||
3431 | { 0x18, 0x04a1182c }, /* Headset mic */ | ||
3432 | { } | ||
3433 | }, | ||
3434 | .chained = true, | ||
3435 | .chain_id = ALC269_FIXUP_ASUS_X101_VERB | ||
3436 | }, | ||
2952 | [ALC271_FIXUP_AMIC_MIC2] = { | 3437 | [ALC271_FIXUP_AMIC_MIC2] = { |
2953 | .type = HDA_FIXUP_PINS, | 3438 | .type = HDA_FIXUP_PINS, |
2954 | .v.pins = (const struct hda_pintbl[]) { | 3439 | .v.pins = (const struct hda_pintbl[]) { |
@@ -2965,29 +3450,72 @@ static const struct hda_fixup alc269_fixups[] = { | |||
2965 | .chained = true, | 3450 | .chained = true, |
2966 | .chain_id = ALC271_FIXUP_AMIC_MIC2, | 3451 | .chain_id = ALC271_FIXUP_AMIC_MIC2, |
2967 | }, | 3452 | }, |
3453 | [ALC269_FIXUP_ACER_AC700] = { | ||
3454 | .type = HDA_FIXUP_PINS, | ||
3455 | .v.pins = (const struct hda_pintbl[]) { | ||
3456 | { 0x12, 0x99a3092f }, /* int-mic */ | ||
3457 | { 0x14, 0x99130110 }, /* speaker */ | ||
3458 | { 0x18, 0x03a11c20 }, /* mic */ | ||
3459 | { 0x1e, 0x0346101e }, /* SPDIF1 */ | ||
3460 | { 0x21, 0x0321101f }, /* HP out */ | ||
3461 | { } | ||
3462 | }, | ||
3463 | .chained = true, | ||
3464 | .chain_id = ALC271_FIXUP_DMIC, | ||
3465 | }, | ||
3466 | [ALC269_FIXUP_LIMIT_INT_MIC_BOOST] = { | ||
3467 | .type = HDA_FIXUP_FUNC, | ||
3468 | .v.func = alc269_fixup_limit_int_mic_boost, | ||
3469 | }, | ||
2968 | }; | 3470 | }; |
2969 | 3471 | ||
2970 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { | 3472 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { |
2971 | SND_PCI_QUIRK(0x1025, 0x029b, "Acer 1810TZ", ALC269_FIXUP_INV_DMIC), | 3473 | SND_PCI_QUIRK(0x1025, 0x029b, "Acer 1810TZ", ALC269_FIXUP_INV_DMIC), |
2972 | SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC), | 3474 | SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC), |
3475 | SND_PCI_QUIRK(0x1028, 0x05bd, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), | ||
3476 | SND_PCI_QUIRK(0x1028, 0x05be, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), | ||
3477 | SND_PCI_QUIRK(0x1028, 0x05c4, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
3478 | SND_PCI_QUIRK(0x1028, 0x05c5, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
3479 | SND_PCI_QUIRK(0x1028, 0x05c6, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
3480 | SND_PCI_QUIRK(0x1028, 0x05c7, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
3481 | SND_PCI_QUIRK(0x1028, 0x05c8, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
3482 | SND_PCI_QUIRK(0x1028, 0x05c9, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
3483 | SND_PCI_QUIRK(0x1028, 0x05ca, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), | ||
3484 | SND_PCI_QUIRK(0x1028, 0x05cb, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), | ||
3485 | SND_PCI_QUIRK(0x1028, 0x05e9, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
3486 | SND_PCI_QUIRK(0x1028, 0x05ea, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
3487 | SND_PCI_QUIRK(0x1028, 0x05eb, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
3488 | SND_PCI_QUIRK(0x1028, 0x05ec, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
3489 | SND_PCI_QUIRK(0x1028, 0x05ed, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
3490 | SND_PCI_QUIRK(0x1028, 0x05ee, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
3491 | SND_PCI_QUIRK(0x1028, 0x05f3, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
3492 | SND_PCI_QUIRK(0x1028, 0x05f4, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
3493 | SND_PCI_QUIRK(0x1028, 0x05f5, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
3494 | SND_PCI_QUIRK(0x1028, 0x05f6, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
2973 | SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), | 3495 | SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), |
3496 | SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED), | ||
2974 | SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 3497 | SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
2975 | SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 3498 | SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
2976 | SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED), | 3499 | SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED), |
3500 | SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | ||
3501 | SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | ||
2977 | SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_DMIC), | 3502 | SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_DMIC), |
2978 | SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_DMIC), | 3503 | SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_DMIC), |
3504 | SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), | ||
2979 | SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), | 3505 | SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), |
2980 | SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC), | 3506 | SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC), |
2981 | SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), | 3507 | SND_PCI_QUIRK(0x1043, 0x1c23, "Asus X55U", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
2982 | SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), | 3508 | SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), |
2983 | SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC), | 3509 | SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC), |
2984 | SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC), | 3510 | SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC), |
2985 | SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC), | 3511 | SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC), |
3512 | SND_PCI_QUIRK(0x1043, 0x8516, "ASUS X101CH", ALC269_FIXUP_ASUS_X101), | ||
2986 | SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2), | 3513 | SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2), |
2987 | SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), | 3514 | SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), |
2988 | SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), | 3515 | SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), |
2989 | SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), | 3516 | SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), |
2990 | SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), | 3517 | SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), |
3518 | SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700), | ||
2991 | SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK), | 3519 | SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK), |
2992 | SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK), | 3520 | SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK), |
2993 | SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC), | 3521 | SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC), |
@@ -3063,6 +3591,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = { | |||
3063 | {.id = ALC271_FIXUP_DMIC, .name = "alc271-dmic"}, | 3591 | {.id = ALC271_FIXUP_DMIC, .name = "alc271-dmic"}, |
3064 | {.id = ALC269_FIXUP_INV_DMIC, .name = "inv-dmic"}, | 3592 | {.id = ALC269_FIXUP_INV_DMIC, .name = "inv-dmic"}, |
3065 | {.id = ALC269_FIXUP_LENOVO_DOCK, .name = "lenovo-dock"}, | 3593 | {.id = ALC269_FIXUP_LENOVO_DOCK, .name = "lenovo-dock"}, |
3594 | {.id = ALC269_FIXUP_HP_GPIO_LED, .name = "hp-gpio-led"}, | ||
3066 | {} | 3595 | {} |
3067 | }; | 3596 | }; |
3068 | 3597 | ||
@@ -3131,6 +3660,9 @@ static int patch_alc269(struct hda_codec *codec) | |||
3131 | 3660 | ||
3132 | alc_auto_parse_customize_define(codec); | 3661 | alc_auto_parse_customize_define(codec); |
3133 | 3662 | ||
3663 | if (has_cdefine_beep(codec)) | ||
3664 | spec->gen.beep_nid = 0x01; | ||
3665 | |||
3134 | switch (codec->vendor_id) { | 3666 | switch (codec->vendor_id) { |
3135 | case 0x10ec0269: | 3667 | case 0x10ec0269: |
3136 | spec->codec_variant = ALC269_TYPE_ALC269VA; | 3668 | spec->codec_variant = ALC269_TYPE_ALC269VA; |
@@ -3172,6 +3704,9 @@ static int patch_alc269(struct hda_codec *codec) | |||
3172 | case 0x10ec0292: | 3704 | case 0x10ec0292: |
3173 | spec->codec_variant = ALC269_TYPE_ALC284; | 3705 | spec->codec_variant = ALC269_TYPE_ALC284; |
3174 | break; | 3706 | break; |
3707 | case 0x10ec0286: | ||
3708 | spec->codec_variant = ALC269_TYPE_ALC286; | ||
3709 | break; | ||
3175 | } | 3710 | } |
3176 | 3711 | ||
3177 | /* automatic parse from the BIOS config */ | 3712 | /* automatic parse from the BIOS config */ |
@@ -3179,12 +3714,8 @@ static int patch_alc269(struct hda_codec *codec) | |||
3179 | if (err < 0) | 3714 | if (err < 0) |
3180 | goto error; | 3715 | goto error; |
3181 | 3716 | ||
3182 | if (!spec->gen.no_analog && has_cdefine_beep(codec)) { | 3717 | if (!spec->gen.no_analog && spec->gen.beep_nid) |
3183 | err = snd_hda_attach_beep_device(codec, 0x1); | ||
3184 | if (err < 0) | ||
3185 | goto error; | ||
3186 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); | 3718 | set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); |
3187 | } | ||
3188 | 3719 | ||
3189 | codec->patch_ops = alc_patch_ops; | 3720 | codec->patch_ops = alc_patch_ops; |
3190 | #ifdef CONFIG_PM | 3721 | #ifdef CONFIG_PM |
@@ -3292,6 +3823,7 @@ static int patch_alc861(struct hda_codec *codec) | |||
3292 | return err; | 3823 | return err; |
3293 | 3824 | ||
3294 | spec = codec->spec; | 3825 | spec = codec->spec; |
3826 | spec->gen.beep_nid = 0x23; | ||
3295 | 3827 | ||
3296 | snd_hda_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups); | 3828 | snd_hda_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups); |
3297 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 3829 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
@@ -3301,12 +3833,8 @@ static int patch_alc861(struct hda_codec *codec) | |||
3301 | if (err < 0) | 3833 | if (err < 0) |
3302 | goto error; | 3834 | goto error; |
3303 | 3835 | ||
3304 | if (!spec->gen.no_analog) { | 3836 | if (!spec->gen.no_analog) |
3305 | err = snd_hda_attach_beep_device(codec, 0x23); | ||
3306 | if (err < 0) | ||
3307 | goto error; | ||
3308 | set_beep_amp(spec, 0x23, 0, HDA_OUTPUT); | 3837 | set_beep_amp(spec, 0x23, 0, HDA_OUTPUT); |
3309 | } | ||
3310 | 3838 | ||
3311 | codec->patch_ops = alc_patch_ops; | 3839 | codec->patch_ops = alc_patch_ops; |
3312 | #ifdef CONFIG_PM | 3840 | #ifdef CONFIG_PM |
@@ -3387,6 +3915,7 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
3387 | return err; | 3915 | return err; |
3388 | 3916 | ||
3389 | spec = codec->spec; | 3917 | spec = codec->spec; |
3918 | spec->gen.beep_nid = 0x23; | ||
3390 | 3919 | ||
3391 | snd_hda_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups); | 3920 | snd_hda_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups); |
3392 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | 3921 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
@@ -3396,12 +3925,8 @@ static int patch_alc861vd(struct hda_codec *codec) | |||
3396 | if (err < 0) | 3925 | if (err < 0) |
3397 | goto error; | 3926 | goto error; |
3398 | 3927 | ||
3399 | if (!spec->gen.no_analog) { | 3928 | if (!spec->gen.no_analog) |
3400 | err = snd_hda_attach_beep_device(codec, 0x23); | ||
3401 | if (err < 0) | ||
3402 | goto error; | ||
3403 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 3929 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
3404 | } | ||
3405 | 3930 | ||
3406 | codec->patch_ops = alc_patch_ops; | 3931 | codec->patch_ops = alc_patch_ops; |
3407 | 3932 | ||
@@ -3480,6 +4005,8 @@ enum { | |||
3480 | ALC662_FIXUP_NO_JACK_DETECT, | 4005 | ALC662_FIXUP_NO_JACK_DETECT, |
3481 | ALC662_FIXUP_ZOTAC_Z68, | 4006 | ALC662_FIXUP_ZOTAC_Z68, |
3482 | ALC662_FIXUP_INV_DMIC, | 4007 | ALC662_FIXUP_INV_DMIC, |
4008 | ALC668_FIXUP_DELL_MIC_NO_PRESENCE, | ||
4009 | ALC668_FIXUP_HEADSET_MODE, | ||
3483 | }; | 4010 | }; |
3484 | 4011 | ||
3485 | static const struct hda_fixup alc662_fixups[] = { | 4012 | static const struct hda_fixup alc662_fixups[] = { |
@@ -3640,6 +4167,20 @@ static const struct hda_fixup alc662_fixups[] = { | |||
3640 | .type = HDA_FIXUP_FUNC, | 4167 | .type = HDA_FIXUP_FUNC, |
3641 | .v.func = alc_fixup_inv_dmic_0x12, | 4168 | .v.func = alc_fixup_inv_dmic_0x12, |
3642 | }, | 4169 | }, |
4170 | [ALC668_FIXUP_DELL_MIC_NO_PRESENCE] = { | ||
4171 | .type = HDA_FIXUP_PINS, | ||
4172 | .v.pins = (const struct hda_pintbl[]) { | ||
4173 | { 0x19, 0x03a1913d }, /* use as headphone mic, without its own jack detect */ | ||
4174 | { 0x1b, 0x03a1113c }, /* use as headset mic, without its own jack detect */ | ||
4175 | { } | ||
4176 | }, | ||
4177 | .chained = true, | ||
4178 | .chain_id = ALC668_FIXUP_HEADSET_MODE | ||
4179 | }, | ||
4180 | [ALC668_FIXUP_HEADSET_MODE] = { | ||
4181 | .type = HDA_FIXUP_FUNC, | ||
4182 | .v.func = alc_fixup_headset_mode_alc668, | ||
4183 | }, | ||
3643 | }; | 4184 | }; |
3644 | 4185 | ||
3645 | static const struct snd_pci_quirk alc662_fixup_tbl[] = { | 4186 | static const struct snd_pci_quirk alc662_fixup_tbl[] = { |
@@ -3648,6 +4189,8 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { | |||
3648 | SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE), | 4189 | SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE), |
3649 | SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC), | 4190 | SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC), |
3650 | SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), | 4191 | SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), |
4192 | SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | ||
4193 | SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | ||
3651 | SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), | 4194 | SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), |
3652 | SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT), | 4195 | SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT), |
3653 | SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2), | 4196 | SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2), |
@@ -3784,10 +4327,14 @@ static int patch_alc662(struct hda_codec *codec) | |||
3784 | 4327 | ||
3785 | alc_auto_parse_customize_define(codec); | 4328 | alc_auto_parse_customize_define(codec); |
3786 | 4329 | ||
4330 | if (has_cdefine_beep(codec)) | ||
4331 | spec->gen.beep_nid = 0x01; | ||
4332 | |||
3787 | if ((alc_get_coef0(codec) & (1 << 14)) && | 4333 | if ((alc_get_coef0(codec) & (1 << 14)) && |
3788 | codec->bus->pci->subsystem_vendor == 0x1025 && | 4334 | codec->bus->pci->subsystem_vendor == 0x1025 && |
3789 | spec->cdefine.platform_type == 1) { | 4335 | spec->cdefine.platform_type == 1) { |
3790 | if (alc_codec_rename(codec, "ALC272X") < 0) | 4336 | err = alc_codec_rename(codec, "ALC272X"); |
4337 | if (err < 0) | ||
3791 | goto error; | 4338 | goto error; |
3792 | } | 4339 | } |
3793 | 4340 | ||
@@ -3796,10 +4343,7 @@ static int patch_alc662(struct hda_codec *codec) | |||
3796 | if (err < 0) | 4343 | if (err < 0) |
3797 | goto error; | 4344 | goto error; |
3798 | 4345 | ||
3799 | if (!spec->gen.no_analog && has_cdefine_beep(codec)) { | 4346 | if (!spec->gen.no_analog && spec->gen.beep_nid) { |
3800 | err = snd_hda_attach_beep_device(codec, 0x1); | ||
3801 | if (err < 0) | ||
3802 | goto error; | ||
3803 | switch (codec->vendor_id) { | 4347 | switch (codec->vendor_id) { |
3804 | case 0x10ec0662: | 4348 | case 0x10ec0662: |
3805 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 4349 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
@@ -3878,6 +4422,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { | |||
3878 | { .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 }, | 4422 | { .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 }, |
3879 | { .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 }, | 4423 | { .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 }, |
3880 | { .id = 0x10ec0284, .name = "ALC284", .patch = patch_alc269 }, | 4424 | { .id = 0x10ec0284, .name = "ALC284", .patch = patch_alc269 }, |
4425 | { .id = 0x10ec0286, .name = "ALC286", .patch = patch_alc269 }, | ||
3881 | { .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 }, | 4426 | { .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 }, |
3882 | { .id = 0x10ec0292, .name = "ALC292", .patch = patch_alc269 }, | 4427 | { .id = 0x10ec0292, .name = "ALC292", .patch = patch_alc269 }, |
3883 | { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", | 4428 | { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index dafe04ae8c72..1d9d6427e0bf 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -211,7 +211,6 @@ struct sigmatel_spec { | |||
211 | 211 | ||
212 | /* beep widgets */ | 212 | /* beep widgets */ |
213 | hda_nid_t anabeep_nid; | 213 | hda_nid_t anabeep_nid; |
214 | hda_nid_t digbeep_nid; | ||
215 | 214 | ||
216 | /* SPDIF-out mux */ | 215 | /* SPDIF-out mux */ |
217 | const char * const *spdif_labels; | 216 | const char * const *spdif_labels; |
@@ -3529,8 +3528,12 @@ static int stac_parse_auto_config(struct hda_codec *codec) | |||
3529 | { | 3528 | { |
3530 | struct sigmatel_spec *spec = codec->spec; | 3529 | struct sigmatel_spec *spec = codec->spec; |
3531 | int err; | 3530 | int err; |
3531 | int flags = 0; | ||
3532 | 3532 | ||
3533 | err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0); | 3533 | if (spec->headset_jack) |
3534 | flags |= HDA_PINCFG_HEADSET_MIC; | ||
3535 | |||
3536 | err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, flags); | ||
3534 | if (err < 0) | 3537 | if (err < 0) |
3535 | return err; | 3538 | return err; |
3536 | 3539 | ||
@@ -3560,16 +3563,13 @@ static int stac_parse_auto_config(struct hda_codec *codec) | |||
3560 | 3563 | ||
3561 | /* setup digital beep controls and input device */ | 3564 | /* setup digital beep controls and input device */ |
3562 | #ifdef CONFIG_SND_HDA_INPUT_BEEP | 3565 | #ifdef CONFIG_SND_HDA_INPUT_BEEP |
3563 | if (spec->digbeep_nid > 0) { | 3566 | if (spec->gen.beep_nid) { |
3564 | hda_nid_t nid = spec->digbeep_nid; | 3567 | hda_nid_t nid = spec->gen.beep_nid; |
3565 | unsigned int caps; | 3568 | unsigned int caps; |
3566 | 3569 | ||
3567 | err = stac_auto_create_beep_ctls(codec, nid); | 3570 | err = stac_auto_create_beep_ctls(codec, nid); |
3568 | if (err < 0) | 3571 | if (err < 0) |
3569 | return err; | 3572 | return err; |
3570 | err = snd_hda_attach_beep_device(codec, nid); | ||
3571 | if (err < 0) | ||
3572 | return err; | ||
3573 | if (codec->beep) { | 3573 | if (codec->beep) { |
3574 | /* IDT/STAC codecs have linear beep tone parameter */ | 3574 | /* IDT/STAC codecs have linear beep tone parameter */ |
3575 | codec->beep->linear_tone = spec->linear_tone_beep; | 3575 | codec->beep->linear_tone = spec->linear_tone_beep; |
@@ -3657,17 +3657,7 @@ static void stac_shutup(struct hda_codec *codec) | |||
3657 | ~spec->eapd_mask); | 3657 | ~spec->eapd_mask); |
3658 | } | 3658 | } |
3659 | 3659 | ||
3660 | static void stac_free(struct hda_codec *codec) | 3660 | #define stac_free snd_hda_gen_free |
3661 | { | ||
3662 | struct sigmatel_spec *spec = codec->spec; | ||
3663 | |||
3664 | if (!spec) | ||
3665 | return; | ||
3666 | |||
3667 | snd_hda_gen_spec_free(&spec->gen); | ||
3668 | kfree(spec); | ||
3669 | snd_hda_detach_beep_device(codec); | ||
3670 | } | ||
3671 | 3661 | ||
3672 | #ifdef CONFIG_PROC_FS | 3662 | #ifdef CONFIG_PROC_FS |
3673 | static void stac92hd_proc_hook(struct snd_info_buffer *buffer, | 3663 | static void stac92hd_proc_hook(struct snd_info_buffer *buffer, |
@@ -3797,6 +3787,7 @@ static int patch_stac9200(struct hda_codec *codec) | |||
3797 | spec->gen.own_eapd_ctl = 1; | 3787 | spec->gen.own_eapd_ctl = 1; |
3798 | 3788 | ||
3799 | codec->patch_ops = stac_patch_ops; | 3789 | codec->patch_ops = stac_patch_ops; |
3790 | codec->power_filter = snd_hda_codec_eapd_power_filter; | ||
3800 | 3791 | ||
3801 | snd_hda_add_verbs(codec, stac9200_eapd_init); | 3792 | snd_hda_add_verbs(codec, stac9200_eapd_init); |
3802 | 3793 | ||
@@ -3884,7 +3875,7 @@ static int patch_stac92hd73xx(struct hda_codec *codec) | |||
3884 | spec->aloopback_mask = 0x01; | 3875 | spec->aloopback_mask = 0x01; |
3885 | spec->aloopback_shift = 8; | 3876 | spec->aloopback_shift = 8; |
3886 | 3877 | ||
3887 | spec->digbeep_nid = 0x1c; | 3878 | spec->gen.beep_nid = 0x1c; /* digital beep */ |
3888 | 3879 | ||
3889 | /* GPIO0 High = Enable EAPD */ | 3880 | /* GPIO0 High = Enable EAPD */ |
3890 | spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1; | 3881 | spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1; |
@@ -3968,7 +3959,7 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) | |||
3968 | spec->gen.power_down_unused = 1; | 3959 | spec->gen.power_down_unused = 1; |
3969 | spec->gen.mixer_nid = 0x1b; | 3960 | spec->gen.mixer_nid = 0x1b; |
3970 | 3961 | ||
3971 | spec->digbeep_nid = 0x21; | 3962 | spec->gen.beep_nid = 0x21; /* digital beep */ |
3972 | spec->pwr_nids = stac92hd83xxx_pwr_nids; | 3963 | spec->pwr_nids = stac92hd83xxx_pwr_nids; |
3973 | spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids); | 3964 | spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids); |
3974 | spec->default_polarity = -1; /* no default cfg */ | 3965 | spec->default_polarity = -1; /* no default cfg */ |
@@ -4016,7 +4007,7 @@ static int patch_stac92hd95(struct hda_codec *codec) | |||
4016 | spec->gen.own_eapd_ctl = 1; | 4007 | spec->gen.own_eapd_ctl = 1; |
4017 | spec->gen.power_down_unused = 1; | 4008 | spec->gen.power_down_unused = 1; |
4018 | 4009 | ||
4019 | spec->digbeep_nid = 0x19; | 4010 | spec->gen.beep_nid = 0x19; /* digital beep */ |
4020 | spec->pwr_nids = stac92hd95_pwr_nids; | 4011 | spec->pwr_nids = stac92hd95_pwr_nids; |
4021 | spec->num_pwrs = ARRAY_SIZE(stac92hd95_pwr_nids); | 4012 | spec->num_pwrs = ARRAY_SIZE(stac92hd95_pwr_nids); |
4022 | spec->default_polarity = -1; /* no default cfg */ | 4013 | spec->default_polarity = -1; /* no default cfg */ |
@@ -4091,7 +4082,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) | |||
4091 | spec->aloopback_shift = 0; | 4082 | spec->aloopback_shift = 0; |
4092 | 4083 | ||
4093 | spec->powerdown_adcs = 1; | 4084 | spec->powerdown_adcs = 1; |
4094 | spec->digbeep_nid = 0x26; | 4085 | spec->gen.beep_nid = 0x26; /* digital beep */ |
4095 | spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids); | 4086 | spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids); |
4096 | spec->pwr_nids = stac92hd71bxx_pwr_nids; | 4087 | spec->pwr_nids = stac92hd71bxx_pwr_nids; |
4097 | 4088 | ||
@@ -4173,7 +4164,7 @@ static int patch_stac927x(struct hda_codec *codec) | |||
4173 | spec->have_spdif_mux = 1; | 4164 | spec->have_spdif_mux = 1; |
4174 | spec->spdif_labels = stac927x_spdif_labels; | 4165 | spec->spdif_labels = stac927x_spdif_labels; |
4175 | 4166 | ||
4176 | spec->digbeep_nid = 0x23; | 4167 | spec->gen.beep_nid = 0x23; /* digital beep */ |
4177 | 4168 | ||
4178 | /* GPIO0 High = Enable EAPD */ | 4169 | /* GPIO0 High = Enable EAPD */ |
4179 | spec->eapd_mask = spec->gpio_mask = 0x01; | 4170 | spec->eapd_mask = spec->gpio_mask = 0x01; |
@@ -4232,7 +4223,7 @@ static int patch_stac9205(struct hda_codec *codec) | |||
4232 | spec->gen.own_eapd_ctl = 1; | 4223 | spec->gen.own_eapd_ctl = 1; |
4233 | spec->have_spdif_mux = 1; | 4224 | spec->have_spdif_mux = 1; |
4234 | 4225 | ||
4235 | spec->digbeep_nid = 0x23; | 4226 | spec->gen.beep_nid = 0x23; /* digital beep */ |
4236 | 4227 | ||
4237 | snd_hda_add_verbs(codec, stac9205_core_init); | 4228 | snd_hda_add_verbs(codec, stac9205_core_init); |
4238 | spec->aloopback_ctl = &stac9205_loopback; | 4229 | spec->aloopback_ctl = &stac9205_loopback; |
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index c35338a8771d..e0dadcf2030d 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -626,11 +626,31 @@ static void via_set_jack_unsol_events(struct hda_codec *codec) | |||
626 | } | 626 | } |
627 | } | 627 | } |
628 | 628 | ||
629 | static const struct badness_table via_main_out_badness = { | ||
630 | .no_primary_dac = 0x10000, | ||
631 | .no_dac = 0x4000, | ||
632 | .shared_primary = 0x10000, | ||
633 | .shared_surr = 0x20, | ||
634 | .shared_clfe = 0x20, | ||
635 | .shared_surr_main = 0x20, | ||
636 | }; | ||
637 | static const struct badness_table via_extra_out_badness = { | ||
638 | .no_primary_dac = 0x4000, | ||
639 | .no_dac = 0x4000, | ||
640 | .shared_primary = 0x12, | ||
641 | .shared_surr = 0x20, | ||
642 | .shared_clfe = 0x20, | ||
643 | .shared_surr_main = 0x10, | ||
644 | }; | ||
645 | |||
629 | static int via_parse_auto_config(struct hda_codec *codec) | 646 | static int via_parse_auto_config(struct hda_codec *codec) |
630 | { | 647 | { |
631 | struct via_spec *spec = codec->spec; | 648 | struct via_spec *spec = codec->spec; |
632 | int err; | 649 | int err; |
633 | 650 | ||
651 | spec->gen.main_out_badness = &via_main_out_badness; | ||
652 | spec->gen.extra_out_badness = &via_extra_out_badness; | ||
653 | |||
634 | err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0); | 654 | err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0); |
635 | if (err < 0) | 655 | if (err < 0) |
636 | return err; | 656 | return err; |
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 223c3d9cc69e..9ea05e956474 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c | |||
@@ -969,6 +969,7 @@ static int snd_hdspm_create_pcm(struct snd_card *card, | |||
969 | struct hdspm *hdspm); | 969 | struct hdspm *hdspm); |
970 | 970 | ||
971 | static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm); | 971 | static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm); |
972 | static inline int hdspm_get_pll_freq(struct hdspm *hdspm); | ||
972 | static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm); | 973 | static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm); |
973 | static int hdspm_autosync_ref(struct hdspm *hdspm); | 974 | static int hdspm_autosync_ref(struct hdspm *hdspm); |
974 | static int snd_hdspm_set_defaults(struct hdspm *hdspm); | 975 | static int snd_hdspm_set_defaults(struct hdspm *hdspm); |
@@ -1075,6 +1076,20 @@ static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm) | |||
1075 | return ret; | 1076 | return ret; |
1076 | } | 1077 | } |
1077 | 1078 | ||
1079 | /* round arbitary sample rates to commonly known rates */ | ||
1080 | static int hdspm_round_frequency(int rate) | ||
1081 | { | ||
1082 | if (rate < 38050) | ||
1083 | return 32000; | ||
1084 | if (rate < 46008) | ||
1085 | return 44100; | ||
1086 | else | ||
1087 | return 48000; | ||
1088 | } | ||
1089 | |||
1090 | static int hdspm_tco_sync_check(struct hdspm *hdspm); | ||
1091 | static int hdspm_sync_in_sync_check(struct hdspm *hdspm); | ||
1092 | |||
1078 | /* check for external sample rate */ | 1093 | /* check for external sample rate */ |
1079 | static int hdspm_external_sample_rate(struct hdspm *hdspm) | 1094 | static int hdspm_external_sample_rate(struct hdspm *hdspm) |
1080 | { | 1095 | { |
@@ -1216,22 +1231,45 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm) | |||
1216 | break; | 1231 | break; |
1217 | } | 1232 | } |
1218 | 1233 | ||
1219 | /* QS and DS rates normally can not be detected | 1234 | } /* endif HDSPM_madiLock */ |
1220 | * automatically by the card. Only exception is MADI | 1235 | |
1221 | * in 96k frame mode. | 1236 | /* check sample rate from TCO or SYNC_IN */ |
1222 | * | 1237 | { |
1223 | * So if we read SS values (32 .. 48k), check for | 1238 | bool is_valid_input = 0; |
1224 | * user-provided DS/QS bits in the control register | 1239 | bool has_sync = 0; |
1225 | * and multiply the base frequency accordingly. | 1240 | |
1226 | */ | 1241 | syncref = hdspm_autosync_ref(hdspm); |
1227 | if (rate <= 48000) { | 1242 | if (HDSPM_AUTOSYNC_FROM_TCO == syncref) { |
1228 | if (hdspm->control_register & HDSPM_QuadSpeed) | 1243 | is_valid_input = 1; |
1229 | rate *= 4; | 1244 | has_sync = (HDSPM_SYNC_CHECK_SYNC == |
1230 | else if (hdspm->control_register & | 1245 | hdspm_tco_sync_check(hdspm)); |
1231 | HDSPM_DoubleSpeed) | 1246 | } else if (HDSPM_AUTOSYNC_FROM_SYNC_IN == syncref) { |
1232 | rate *= 2; | 1247 | is_valid_input = 1; |
1248 | has_sync = (HDSPM_SYNC_CHECK_SYNC == | ||
1249 | hdspm_sync_in_sync_check(hdspm)); | ||
1250 | } | ||
1251 | |||
1252 | if (is_valid_input && has_sync) { | ||
1253 | rate = hdspm_round_frequency( | ||
1254 | hdspm_get_pll_freq(hdspm)); | ||
1233 | } | 1255 | } |
1234 | } | 1256 | } |
1257 | |||
1258 | /* QS and DS rates normally can not be detected | ||
1259 | * automatically by the card. Only exception is MADI | ||
1260 | * in 96k frame mode. | ||
1261 | * | ||
1262 | * So if we read SS values (32 .. 48k), check for | ||
1263 | * user-provided DS/QS bits in the control register | ||
1264 | * and multiply the base frequency accordingly. | ||
1265 | */ | ||
1266 | if (rate <= 48000) { | ||
1267 | if (hdspm->control_register & HDSPM_QuadSpeed) | ||
1268 | rate *= 4; | ||
1269 | else if (hdspm->control_register & | ||
1270 | HDSPM_DoubleSpeed) | ||
1271 | rate *= 2; | ||
1272 | } | ||
1235 | break; | 1273 | break; |
1236 | } | 1274 | } |
1237 | 1275 | ||
@@ -1979,16 +2017,25 @@ static void hdspm_midi_tasklet(unsigned long arg) | |||
1979 | /* get the system sample rate which is set */ | 2017 | /* get the system sample rate which is set */ |
1980 | 2018 | ||
1981 | 2019 | ||
2020 | static inline int hdspm_get_pll_freq(struct hdspm *hdspm) | ||
2021 | { | ||
2022 | unsigned int period, rate; | ||
2023 | |||
2024 | period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ); | ||
2025 | rate = hdspm_calc_dds_value(hdspm, period); | ||
2026 | |||
2027 | return rate; | ||
2028 | } | ||
2029 | |||
1982 | /** | 2030 | /** |
1983 | * Calculate the real sample rate from the | 2031 | * Calculate the real sample rate from the |
1984 | * current DDS value. | 2032 | * current DDS value. |
1985 | **/ | 2033 | **/ |
1986 | static int hdspm_get_system_sample_rate(struct hdspm *hdspm) | 2034 | static int hdspm_get_system_sample_rate(struct hdspm *hdspm) |
1987 | { | 2035 | { |
1988 | unsigned int period, rate; | 2036 | unsigned int rate; |
1989 | 2037 | ||
1990 | period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ); | 2038 | rate = hdspm_get_pll_freq(hdspm); |
1991 | rate = hdspm_calc_dds_value(hdspm, period); | ||
1992 | 2039 | ||
1993 | if (rate > 207000) { | 2040 | if (rate > 207000) { |
1994 | /* Unreasonable high sample rate as seen on PCI MADI cards. */ | 2041 | /* Unreasonable high sample rate as seen on PCI MADI cards. */ |
@@ -2128,6 +2175,16 @@ static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx) | |||
2128 | return (status >> (idx*4)) & 0xF; | 2175 | return (status >> (idx*4)) & 0xF; |
2129 | } | 2176 | } |
2130 | 2177 | ||
2178 | #define ENUMERATED_CTL_INFO(info, texts) \ | ||
2179 | { \ | ||
2180 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; \ | ||
2181 | uinfo->count = 1; \ | ||
2182 | uinfo->value.enumerated.items = ARRAY_SIZE(texts); \ | ||
2183 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) \ | ||
2184 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; \ | ||
2185 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); \ | ||
2186 | } | ||
2187 | |||
2131 | 2188 | ||
2132 | 2189 | ||
2133 | #define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \ | 2190 | #define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \ |
@@ -2143,14 +2200,7 @@ static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx) | |||
2143 | static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol, | 2200 | static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol, |
2144 | struct snd_ctl_elem_info *uinfo) | 2201 | struct snd_ctl_elem_info *uinfo) |
2145 | { | 2202 | { |
2146 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 2203 | ENUMERATED_CTL_INFO(uinfo, texts_freq); |
2147 | uinfo->count = 1; | ||
2148 | uinfo->value.enumerated.items = 10; | ||
2149 | |||
2150 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
2151 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; | ||
2152 | strcpy(uinfo->value.enumerated.name, | ||
2153 | texts_freq[uinfo->value.enumerated.item]); | ||
2154 | return 0; | 2204 | return 0; |
2155 | } | 2205 | } |
2156 | 2206 | ||
@@ -2316,15 +2366,7 @@ static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol, | |||
2316 | struct snd_ctl_elem_info *uinfo) | 2366 | struct snd_ctl_elem_info *uinfo) |
2317 | { | 2367 | { |
2318 | static char *texts[] = { "Master", "AutoSync" }; | 2368 | static char *texts[] = { "Master", "AutoSync" }; |
2319 | 2369 | ENUMERATED_CTL_INFO(uinfo, texts); | |
2320 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
2321 | uinfo->count = 1; | ||
2322 | uinfo->value.enumerated.items = 2; | ||
2323 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
2324 | uinfo->value.enumerated.item = | ||
2325 | uinfo->value.enumerated.items - 1; | ||
2326 | strcpy(uinfo->value.enumerated.name, | ||
2327 | texts[uinfo->value.enumerated.item]); | ||
2328 | return 0; | 2370 | return 0; |
2329 | } | 2371 | } |
2330 | 2372 | ||
@@ -2888,6 +2930,112 @@ static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol, | |||
2888 | return 0; | 2930 | return 0; |
2889 | } | 2931 | } |
2890 | 2932 | ||
2933 | |||
2934 | |||
2935 | #define HDSPM_TCO_VIDEO_INPUT_FORMAT(xname, xindex) \ | ||
2936 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
2937 | .name = xname, \ | ||
2938 | .access = SNDRV_CTL_ELEM_ACCESS_READ |\ | ||
2939 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
2940 | .info = snd_hdspm_info_tco_video_input_format, \ | ||
2941 | .get = snd_hdspm_get_tco_video_input_format, \ | ||
2942 | } | ||
2943 | |||
2944 | static int snd_hdspm_info_tco_video_input_format(struct snd_kcontrol *kcontrol, | ||
2945 | struct snd_ctl_elem_info *uinfo) | ||
2946 | { | ||
2947 | static char *texts[] = {"No video", "NTSC", "PAL"}; | ||
2948 | ENUMERATED_CTL_INFO(uinfo, texts); | ||
2949 | return 0; | ||
2950 | } | ||
2951 | |||
2952 | static int snd_hdspm_get_tco_video_input_format(struct snd_kcontrol *kcontrol, | ||
2953 | struct snd_ctl_elem_value *ucontrol) | ||
2954 | { | ||
2955 | u32 status; | ||
2956 | int ret = 0; | ||
2957 | |||
2958 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
2959 | status = hdspm_read(hdspm, HDSPM_RD_TCO + 4); | ||
2960 | switch (status & (HDSPM_TCO1_Video_Input_Format_NTSC | | ||
2961 | HDSPM_TCO1_Video_Input_Format_PAL)) { | ||
2962 | case HDSPM_TCO1_Video_Input_Format_NTSC: | ||
2963 | /* ntsc */ | ||
2964 | ret = 1; | ||
2965 | break; | ||
2966 | case HDSPM_TCO1_Video_Input_Format_PAL: | ||
2967 | /* pal */ | ||
2968 | ret = 2; | ||
2969 | break; | ||
2970 | default: | ||
2971 | /* no video */ | ||
2972 | ret = 0; | ||
2973 | break; | ||
2974 | } | ||
2975 | ucontrol->value.enumerated.item[0] = ret; | ||
2976 | return 0; | ||
2977 | } | ||
2978 | |||
2979 | |||
2980 | |||
2981 | #define HDSPM_TCO_LTC_FRAMES(xname, xindex) \ | ||
2982 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
2983 | .name = xname, \ | ||
2984 | .access = SNDRV_CTL_ELEM_ACCESS_READ |\ | ||
2985 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
2986 | .info = snd_hdspm_info_tco_ltc_frames, \ | ||
2987 | .get = snd_hdspm_get_tco_ltc_frames, \ | ||
2988 | } | ||
2989 | |||
2990 | static int snd_hdspm_info_tco_ltc_frames(struct snd_kcontrol *kcontrol, | ||
2991 | struct snd_ctl_elem_info *uinfo) | ||
2992 | { | ||
2993 | static char *texts[] = {"No lock", "24 fps", "25 fps", "29.97 fps", | ||
2994 | "30 fps"}; | ||
2995 | ENUMERATED_CTL_INFO(uinfo, texts); | ||
2996 | return 0; | ||
2997 | } | ||
2998 | |||
2999 | static int hdspm_tco_ltc_frames(struct hdspm *hdspm) | ||
3000 | { | ||
3001 | u32 status; | ||
3002 | int ret = 0; | ||
3003 | |||
3004 | status = hdspm_read(hdspm, HDSPM_RD_TCO + 4); | ||
3005 | if (status & HDSPM_TCO1_LTC_Input_valid) { | ||
3006 | switch (status & (HDSPM_TCO1_LTC_Format_LSB | | ||
3007 | HDSPM_TCO1_LTC_Format_MSB)) { | ||
3008 | case 0: | ||
3009 | /* 24 fps */ | ||
3010 | ret = 1; | ||
3011 | break; | ||
3012 | case HDSPM_TCO1_LTC_Format_LSB: | ||
3013 | /* 25 fps */ | ||
3014 | ret = 2; | ||
3015 | break; | ||
3016 | case HDSPM_TCO1_LTC_Format_MSB: | ||
3017 | /* 25 fps */ | ||
3018 | ret = 3; | ||
3019 | break; | ||
3020 | default: | ||
3021 | /* 30 fps */ | ||
3022 | ret = 4; | ||
3023 | break; | ||
3024 | } | ||
3025 | } | ||
3026 | |||
3027 | return ret; | ||
3028 | } | ||
3029 | |||
3030 | static int snd_hdspm_get_tco_ltc_frames(struct snd_kcontrol *kcontrol, | ||
3031 | struct snd_ctl_elem_value *ucontrol) | ||
3032 | { | ||
3033 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
3034 | |||
3035 | ucontrol->value.enumerated.item[0] = hdspm_tco_ltc_frames(hdspm); | ||
3036 | return 0; | ||
3037 | } | ||
3038 | |||
2891 | #define HDSPM_TOGGLE_SETTING(xname, xindex) \ | 3039 | #define HDSPM_TOGGLE_SETTING(xname, xindex) \ |
2892 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3040 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
2893 | .name = xname, \ | 3041 | .name = xname, \ |
@@ -2974,17 +3122,7 @@ static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol, | |||
2974 | struct snd_ctl_elem_info *uinfo) | 3122 | struct snd_ctl_elem_info *uinfo) |
2975 | { | 3123 | { |
2976 | static char *texts[] = { "optical", "coaxial" }; | 3124 | static char *texts[] = { "optical", "coaxial" }; |
2977 | 3125 | ENUMERATED_CTL_INFO(uinfo, texts); | |
2978 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
2979 | uinfo->count = 1; | ||
2980 | uinfo->value.enumerated.items = 2; | ||
2981 | |||
2982 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
2983 | uinfo->value.enumerated.item = | ||
2984 | uinfo->value.enumerated.items - 1; | ||
2985 | strcpy(uinfo->value.enumerated.name, | ||
2986 | texts[uinfo->value.enumerated.item]); | ||
2987 | |||
2988 | return 0; | 3126 | return 0; |
2989 | } | 3127 | } |
2990 | 3128 | ||
@@ -3046,17 +3184,7 @@ static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol, | |||
3046 | struct snd_ctl_elem_info *uinfo) | 3184 | struct snd_ctl_elem_info *uinfo) |
3047 | { | 3185 | { |
3048 | static char *texts[] = { "Single", "Double" }; | 3186 | static char *texts[] = { "Single", "Double" }; |
3049 | 3187 | ENUMERATED_CTL_INFO(uinfo, texts); | |
3050 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
3051 | uinfo->count = 1; | ||
3052 | uinfo->value.enumerated.items = 2; | ||
3053 | |||
3054 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
3055 | uinfo->value.enumerated.item = | ||
3056 | uinfo->value.enumerated.items - 1; | ||
3057 | strcpy(uinfo->value.enumerated.name, | ||
3058 | texts[uinfo->value.enumerated.item]); | ||
3059 | |||
3060 | return 0; | 3188 | return 0; |
3061 | } | 3189 | } |
3062 | 3190 | ||
@@ -3129,17 +3257,7 @@ static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol, | |||
3129 | struct snd_ctl_elem_info *uinfo) | 3257 | struct snd_ctl_elem_info *uinfo) |
3130 | { | 3258 | { |
3131 | static char *texts[] = { "Single", "Double", "Quad" }; | 3259 | static char *texts[] = { "Single", "Double", "Quad" }; |
3132 | 3260 | ENUMERATED_CTL_INFO(uinfo, texts); | |
3133 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
3134 | uinfo->count = 1; | ||
3135 | uinfo->value.enumerated.items = 3; | ||
3136 | |||
3137 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
3138 | uinfo->value.enumerated.item = | ||
3139 | uinfo->value.enumerated.items - 1; | ||
3140 | strcpy(uinfo->value.enumerated.name, | ||
3141 | texts[uinfo->value.enumerated.item]); | ||
3142 | |||
3143 | return 0; | 3261 | return 0; |
3144 | } | 3262 | } |
3145 | 3263 | ||
@@ -3215,17 +3333,7 @@ static int snd_hdspm_info_madi_speedmode(struct snd_kcontrol *kcontrol, | |||
3215 | struct snd_ctl_elem_info *uinfo) | 3333 | struct snd_ctl_elem_info *uinfo) |
3216 | { | 3334 | { |
3217 | static char *texts[] = { "Single", "Double", "Quad" }; | 3335 | static char *texts[] = { "Single", "Double", "Quad" }; |
3218 | 3336 | ENUMERATED_CTL_INFO(uinfo, texts); | |
3219 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
3220 | uinfo->count = 1; | ||
3221 | uinfo->value.enumerated.items = 3; | ||
3222 | |||
3223 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
3224 | uinfo->value.enumerated.item = | ||
3225 | uinfo->value.enumerated.items - 1; | ||
3226 | strcpy(uinfo->value.enumerated.name, | ||
3227 | texts[uinfo->value.enumerated.item]); | ||
3228 | |||
3229 | return 0; | 3337 | return 0; |
3230 | } | 3338 | } |
3231 | 3339 | ||
@@ -3445,19 +3553,30 @@ static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol, | |||
3445 | .get = snd_hdspm_get_sync_check \ | 3553 | .get = snd_hdspm_get_sync_check \ |
3446 | } | 3554 | } |
3447 | 3555 | ||
3556 | #define HDSPM_TCO_LOCK_CHECK(xname, xindex) \ | ||
3557 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
3558 | .name = xname, \ | ||
3559 | .private_value = xindex, \ | ||
3560 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
3561 | .info = snd_hdspm_tco_info_lock_check, \ | ||
3562 | .get = snd_hdspm_get_sync_check \ | ||
3563 | } | ||
3564 | |||
3565 | |||
3448 | 3566 | ||
3449 | static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol, | 3567 | static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol, |
3450 | struct snd_ctl_elem_info *uinfo) | 3568 | struct snd_ctl_elem_info *uinfo) |
3451 | { | 3569 | { |
3452 | static char *texts[] = { "No Lock", "Lock", "Sync", "N/A" }; | 3570 | static char *texts[] = { "No Lock", "Lock", "Sync", "N/A" }; |
3453 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 3571 | ENUMERATED_CTL_INFO(uinfo, texts); |
3454 | uinfo->count = 1; | 3572 | return 0; |
3455 | uinfo->value.enumerated.items = 4; | 3573 | } |
3456 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | 3574 | |
3457 | uinfo->value.enumerated.item = | 3575 | static int snd_hdspm_tco_info_lock_check(struct snd_kcontrol *kcontrol, |
3458 | uinfo->value.enumerated.items - 1; | 3576 | struct snd_ctl_elem_info *uinfo) |
3459 | strcpy(uinfo->value.enumerated.name, | 3577 | { |
3460 | texts[uinfo->value.enumerated.item]); | 3578 | static char *texts[] = { "No Lock", "Lock" }; |
3579 | ENUMERATED_CTL_INFO(uinfo, texts); | ||
3461 | return 0; | 3580 | return 0; |
3462 | } | 3581 | } |
3463 | 3582 | ||
@@ -3590,6 +3709,14 @@ static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx) | |||
3590 | return 0; | 3709 | return 0; |
3591 | } | 3710 | } |
3592 | 3711 | ||
3712 | static int hdspm_tco_input_check(struct hdspm *hdspm, u32 mask) | ||
3713 | { | ||
3714 | u32 status; | ||
3715 | status = hdspm_read(hdspm, HDSPM_RD_TCO + 4); | ||
3716 | |||
3717 | return (status & mask) ? 1 : 0; | ||
3718 | } | ||
3719 | |||
3593 | 3720 | ||
3594 | static int hdspm_tco_sync_check(struct hdspm *hdspm) | 3721 | static int hdspm_tco_sync_check(struct hdspm *hdspm) |
3595 | { | 3722 | { |
@@ -3697,6 +3824,22 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol, | |||
3697 | 3824 | ||
3698 | } | 3825 | } |
3699 | 3826 | ||
3827 | if (hdspm->tco) { | ||
3828 | switch (kcontrol->private_value) { | ||
3829 | case 11: | ||
3830 | /* Check TCO for lock state of its current input */ | ||
3831 | val = hdspm_tco_input_check(hdspm, HDSPM_TCO1_TCO_lock); | ||
3832 | break; | ||
3833 | case 12: | ||
3834 | /* Check TCO for valid time code on LTC input. */ | ||
3835 | val = hdspm_tco_input_check(hdspm, | ||
3836 | HDSPM_TCO1_LTC_Input_valid); | ||
3837 | break; | ||
3838 | default: | ||
3839 | break; | ||
3840 | } | ||
3841 | } | ||
3842 | |||
3700 | if (-1 == val) | 3843 | if (-1 == val) |
3701 | val = 3; | 3844 | val = 3; |
3702 | 3845 | ||
@@ -3813,17 +3956,7 @@ static int snd_hdspm_info_tco_sample_rate(struct snd_kcontrol *kcontrol, | |||
3813 | struct snd_ctl_elem_info *uinfo) | 3956 | struct snd_ctl_elem_info *uinfo) |
3814 | { | 3957 | { |
3815 | static char *texts[] = { "44.1 kHz", "48 kHz" }; | 3958 | static char *texts[] = { "44.1 kHz", "48 kHz" }; |
3816 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 3959 | ENUMERATED_CTL_INFO(uinfo, texts); |
3817 | uinfo->count = 1; | ||
3818 | uinfo->value.enumerated.items = 2; | ||
3819 | |||
3820 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
3821 | uinfo->value.enumerated.item = | ||
3822 | uinfo->value.enumerated.items - 1; | ||
3823 | |||
3824 | strcpy(uinfo->value.enumerated.name, | ||
3825 | texts[uinfo->value.enumerated.item]); | ||
3826 | |||
3827 | return 0; | 3960 | return 0; |
3828 | } | 3961 | } |
3829 | 3962 | ||
@@ -3869,17 +4002,7 @@ static int snd_hdspm_info_tco_pull(struct snd_kcontrol *kcontrol, | |||
3869 | struct snd_ctl_elem_info *uinfo) | 4002 | struct snd_ctl_elem_info *uinfo) |
3870 | { | 4003 | { |
3871 | static char *texts[] = { "0", "+ 0.1 %", "- 0.1 %", "+ 4 %", "- 4 %" }; | 4004 | static char *texts[] = { "0", "+ 0.1 %", "- 0.1 %", "+ 4 %", "- 4 %" }; |
3872 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 4005 | ENUMERATED_CTL_INFO(uinfo, texts); |
3873 | uinfo->count = 1; | ||
3874 | uinfo->value.enumerated.items = 5; | ||
3875 | |||
3876 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
3877 | uinfo->value.enumerated.item = | ||
3878 | uinfo->value.enumerated.items - 1; | ||
3879 | |||
3880 | strcpy(uinfo->value.enumerated.name, | ||
3881 | texts[uinfo->value.enumerated.item]); | ||
3882 | |||
3883 | return 0; | 4006 | return 0; |
3884 | } | 4007 | } |
3885 | 4008 | ||
@@ -3924,17 +4047,7 @@ static int snd_hdspm_info_tco_wck_conversion(struct snd_kcontrol *kcontrol, | |||
3924 | struct snd_ctl_elem_info *uinfo) | 4047 | struct snd_ctl_elem_info *uinfo) |
3925 | { | 4048 | { |
3926 | static char *texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" }; | 4049 | static char *texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" }; |
3927 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 4050 | ENUMERATED_CTL_INFO(uinfo, texts); |
3928 | uinfo->count = 1; | ||
3929 | uinfo->value.enumerated.items = 3; | ||
3930 | |||
3931 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
3932 | uinfo->value.enumerated.item = | ||
3933 | uinfo->value.enumerated.items - 1; | ||
3934 | |||
3935 | strcpy(uinfo->value.enumerated.name, | ||
3936 | texts[uinfo->value.enumerated.item]); | ||
3937 | |||
3938 | return 0; | 4051 | return 0; |
3939 | } | 4052 | } |
3940 | 4053 | ||
@@ -3981,17 +4094,7 @@ static int snd_hdspm_info_tco_frame_rate(struct snd_kcontrol *kcontrol, | |||
3981 | { | 4094 | { |
3982 | static char *texts[] = { "24 fps", "25 fps", "29.97fps", | 4095 | static char *texts[] = { "24 fps", "25 fps", "29.97fps", |
3983 | "29.97 dfps", "30 fps", "30 dfps" }; | 4096 | "29.97 dfps", "30 fps", "30 dfps" }; |
3984 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 4097 | ENUMERATED_CTL_INFO(uinfo, texts); |
3985 | uinfo->count = 1; | ||
3986 | uinfo->value.enumerated.items = 6; | ||
3987 | |||
3988 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
3989 | uinfo->value.enumerated.item = | ||
3990 | uinfo->value.enumerated.items - 1; | ||
3991 | |||
3992 | strcpy(uinfo->value.enumerated.name, | ||
3993 | texts[uinfo->value.enumerated.item]); | ||
3994 | |||
3995 | return 0; | 4098 | return 0; |
3996 | } | 4099 | } |
3997 | 4100 | ||
@@ -4037,17 +4140,7 @@ static int snd_hdspm_info_tco_sync_source(struct snd_kcontrol *kcontrol, | |||
4037 | struct snd_ctl_elem_info *uinfo) | 4140 | struct snd_ctl_elem_info *uinfo) |
4038 | { | 4141 | { |
4039 | static char *texts[] = { "LTC", "Video", "WCK" }; | 4142 | static char *texts[] = { "LTC", "Video", "WCK" }; |
4040 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 4143 | ENUMERATED_CTL_INFO(uinfo, texts); |
4041 | uinfo->count = 1; | ||
4042 | uinfo->value.enumerated.items = 3; | ||
4043 | |||
4044 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
4045 | uinfo->value.enumerated.item = | ||
4046 | uinfo->value.enumerated.items - 1; | ||
4047 | |||
4048 | strcpy(uinfo->value.enumerated.name, | ||
4049 | texts[uinfo->value.enumerated.item]); | ||
4050 | |||
4051 | return 0; | 4144 | return 0; |
4052 | } | 4145 | } |
4053 | 4146 | ||
@@ -4145,6 +4238,7 @@ static struct snd_kcontrol_new snd_hdspm_controls_madi[] = { | |||
4145 | HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3), | 4238 | HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3), |
4146 | HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut), | 4239 | HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut), |
4147 | HDSPM_TOGGLE_SETTING("TX 64 channels mode", HDSPM_TX_64ch), | 4240 | HDSPM_TOGGLE_SETTING("TX 64 channels mode", HDSPM_TX_64ch), |
4241 | HDSPM_TOGGLE_SETTING("Disable 96K frames", HDSPM_SMUX), | ||
4148 | HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms), | 4242 | HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms), |
4149 | HDSPM_TOGGLE_SETTING("Safe Mode", HDSPM_AutoInp), | 4243 | HDSPM_TOGGLE_SETTING("Safe Mode", HDSPM_AutoInp), |
4150 | HDSPM_INPUT_SELECT("Input Select", 0), | 4244 | HDSPM_INPUT_SELECT("Input Select", 0), |
@@ -4272,7 +4366,11 @@ static struct snd_kcontrol_new snd_hdspm_controls_tco[] = { | |||
4272 | HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0), | 4366 | HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0), |
4273 | HDSPM_TCO_FRAME_RATE("TCO Frame Rate", 0), | 4367 | HDSPM_TCO_FRAME_RATE("TCO Frame Rate", 0), |
4274 | HDSPM_TCO_SYNC_SOURCE("TCO Sync Source", 0), | 4368 | HDSPM_TCO_SYNC_SOURCE("TCO Sync Source", 0), |
4275 | HDSPM_TCO_WORD_TERM("TCO Word Term", 0) | 4369 | HDSPM_TCO_WORD_TERM("TCO Word Term", 0), |
4370 | HDSPM_TCO_LOCK_CHECK("TCO Input Check", 11), | ||
4371 | HDSPM_TCO_LOCK_CHECK("TCO LTC Valid", 12), | ||
4372 | HDSPM_TCO_LTC_FRAMES("TCO Detected Frame Rate", 0), | ||
4373 | HDSPM_TCO_VIDEO_INPUT_FORMAT("Video Input Format", 0) | ||
4276 | }; | 4374 | }; |
4277 | 4375 | ||
4278 | 4376 | ||