From fc084e0b930d546872ab23667052499f7daf0fed Mon Sep 17 00:00:00 2001 From: David Dillow Date: Thu, 1 Dec 2011 23:26:53 -0500 Subject: [PATCH 01/14] ALSA: sis7019 - give slow codecs more time to reset There are some AC97 codec and board combinations that have been observed to take a very long time to respond after the cold reset has completed. In one case, more than 350 ms was required. To allow users to have sound on those platforms, we'll wait up to 500ms for the codec to become ready. As a board may have multiple codecs, with some faster than others to reset, we add a module parameter to inform the driver which codecs should be present. Reported-by: KotCzarny Signed-off-by: David Dillow Cc: Signed-off-by: Takashi Iwai --- sound/pci/sis7019.c | 66 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c index a391e622a192..28dfafb56dd1 100644 --- a/sound/pci/sis7019.c +++ b/sound/pci/sis7019.c @@ -41,6 +41,7 @@ MODULE_SUPPORTED_DEVICE("{{SiS,SiS7019 Audio Accelerator}}"); static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ static int enable = 1; +static int codecs = 1; module_param(index, int, 0444); MODULE_PARM_DESC(index, "Index value for SiS7019 Audio Accelerator."); @@ -48,6 +49,8 @@ module_param(id, charp, 0444); MODULE_PARM_DESC(id, "ID string for SiS7019 Audio Accelerator."); module_param(enable, bool, 0444); MODULE_PARM_DESC(enable, "Enable SiS7019 Audio Accelerator."); +module_param(codecs, int, 0444); +MODULE_PARM_DESC(codecs, "Set bit to indicate that codec number is expected to be present (default 1)"); static DEFINE_PCI_DEVICE_TABLE(snd_sis7019_ids) = { { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x7019) }, @@ -140,6 +143,9 @@ struct sis7019 { dma_addr_t silence_dma_addr; }; +/* These values are also used by the module param 'codecs' to indicate + * which codecs should be present. + */ #define SIS_PRIMARY_CODEC_PRESENT 0x0001 #define SIS_SECONDARY_CODEC_PRESENT 0x0002 #define SIS_TERTIARY_CODEC_PRESENT 0x0004 @@ -1078,6 +1084,7 @@ static int sis_chip_init(struct sis7019 *sis) { unsigned long io = sis->ioport; void __iomem *ioaddr = sis->ioaddr; + unsigned long timeout; u16 status; int count; int i; @@ -1104,22 +1111,46 @@ static int sis_chip_init(struct sis7019 *sis) while ((inw(io + SIS_AC97_STATUS) & SIS_AC97_STATUS_BUSY) && --count) udelay(1); - /* Now that we've finished the reset, find out what's attached. - */ - status = inl(io + SIS_AC97_STATUS); - if (status & SIS_AC97_STATUS_CODEC_READY) - sis->codecs_present |= SIS_PRIMARY_CODEC_PRESENT; - if (status & SIS_AC97_STATUS_CODEC2_READY) - sis->codecs_present |= SIS_SECONDARY_CODEC_PRESENT; - if (status & SIS_AC97_STATUS_CODEC3_READY) - sis->codecs_present |= SIS_TERTIARY_CODEC_PRESENT; - - /* All done, let go of the semaphore, and check for errors + /* Command complete, we can let go of the semaphore now. */ outl(SIS_AC97_SEMA_RELEASE, io + SIS_AC97_SEMA); - if (!sis->codecs_present || !count) + if (!count) return -EIO; + /* Now that we've finished the reset, find out what's attached. + * There are some codec/board combinations that take an extremely + * long time to come up. 350+ ms has been observed in the field, + * so we'll give them up to 500ms. + */ + sis->codecs_present = 0; + timeout = msecs_to_jiffies(500) + jiffies; + while (time_before_eq(jiffies, timeout)) { + status = inl(io + SIS_AC97_STATUS); + if (status & SIS_AC97_STATUS_CODEC_READY) + sis->codecs_present |= SIS_PRIMARY_CODEC_PRESENT; + if (status & SIS_AC97_STATUS_CODEC2_READY) + sis->codecs_present |= SIS_SECONDARY_CODEC_PRESENT; + if (status & SIS_AC97_STATUS_CODEC3_READY) + sis->codecs_present |= SIS_TERTIARY_CODEC_PRESENT; + + if (sis->codecs_present == codecs) + break; + + msleep(1); + } + + /* All done, check for errors. + */ + if (!sis->codecs_present) { + printk(KERN_ERR "sis7019: could not find any codecs\n"); + return -EIO; + } + + if (sis->codecs_present != codecs) { + printk(KERN_WARNING "sis7019: missing codecs, found %0x, expected %0x\n", + sis->codecs_present, codecs); + } + /* Let the hardware know that the audio driver is alive, * and enable PCM slots on the AC-link for L/R playback (3 & 4) and * record channels. We're going to want to use Variable Rate Audio @@ -1390,6 +1421,17 @@ static int __devinit snd_sis7019_probe(struct pci_dev *pci, if (!enable) goto error_out; + /* The user can specify which codecs should be present so that we + * can wait for them to show up if they are slow to recover from + * the AC97 cold reset. We default to a single codec, the primary. + * + * We assume that SIS_PRIMARY_*_PRESENT matches bits 0-2. + */ + codecs &= SIS_PRIMARY_CODEC_PRESENT | SIS_SECONDARY_CODEC_PRESENT | + SIS_TERTIARY_CODEC_PRESENT; + if (!codecs) + codecs = SIS_PRIMARY_CODEC_PRESENT; + rc = snd_card_create(index, id, THIS_MODULE, sizeof(*sis), &card); if (rc < 0) goto error_out; From cce4aa378a049f4275416ee6302dd24f37b289df Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 2 Dec 2011 15:29:12 +0100 Subject: [PATCH 02/14] ALSA: hda/realtek - Fix Oops in alc_mux_select() When no imux is available (e.g. a single capture source), alc_auto_init_input_src() may trigger an Oops due to the access to -1. Add a proper zero-check to avoid it. Cc: Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index cbde019d3d52..a7d1bc4e0d09 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -297,6 +297,8 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, imux = &spec->input_mux[mux_idx]; if (!imux->num_items && mux_idx > 0) imux = &spec->input_mux[0]; + if (!imux->num_items) + return 0; if (idx >= imux->num_items) idx = imux->num_items - 1; From 87b86ade8bb07473596e2551de7bb64c1f44bbe4 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 14 Aug 2011 13:39:20 +0900 Subject: [PATCH 03/14] ASoC: Mark WM8994 ADC muxes as virtual Since they don't actually have power bits but do have events associated with them it's important that we bootstrap their state properly which making them virtual does. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 6c2988549003..d0c545b73d78 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -1325,15 +1325,15 @@ SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 0, 0), }; static const struct snd_soc_dapm_widget wm8994_adc_revd_widgets[] = { -SND_SOC_DAPM_MUX_E("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux, - adc_mux_ev, SND_SOC_DAPM_PRE_PMU), -SND_SOC_DAPM_MUX_E("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux, - adc_mux_ev, SND_SOC_DAPM_PRE_PMU), +SND_SOC_DAPM_VIRT_MUX_E("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux, + adc_mux_ev, SND_SOC_DAPM_PRE_PMU), +SND_SOC_DAPM_VIRT_MUX_E("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux, + adc_mux_ev, SND_SOC_DAPM_PRE_PMU), }; static const struct snd_soc_dapm_widget wm8994_adc_widgets[] = { -SND_SOC_DAPM_MUX("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux), -SND_SOC_DAPM_MUX("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux), +SND_SOC_DAPM_VIRT_MUX("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux), +SND_SOC_DAPM_VIRT_MUX("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux), }; static const struct snd_soc_dapm_widget wm8994_dapm_widgets[] = { From 36d54dc0c893b143748bcf13a1e3b7a00696115d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 3 Dec 2011 18:38:25 +0800 Subject: [PATCH 04/14] ASoC: kirkwood: Make SND_KIRKWOOD_SOC_OPENRD and SND_KIRKWOOD_SOC_T5325 depend on I2C SND_KIRKWOOD_SOC_T5325 selects SND_SOC_ALC5623, but SND_SOC_ALC5623 needs CONFIG_I2C. So we need to make SND_KIRKWOOD_SOC_T5325 depend on I2C, otherwise I got below build error if CONFIG_I2C is not selected. CC sound/soc/codecs/alc5623.o sound/soc/codecs/alc5623.c: In function 'alc5623_i2c_probe': sound/soc/codecs/alc5623.c:1002: error: implicit declaration of function 'i2c_smbus_read_word_data' sound/soc/codecs/alc5623.c:1009: error: implicit declaration of function 'i2c_smbus_read_byte_data' sound/soc/codecs/alc5623.c: In function 'alc5623_modinit': sound/soc/codecs/alc5623.c:1096: error: implicit declaration of function 'i2c_add_driver' sound/soc/codecs/alc5623.c: In function 'alc5623_modexit': sound/soc/codecs/alc5623.c:1108: error: implicit declaration of function 'i2c_del_driver' make[3]: *** [sound/soc/codecs/alc5623.o] Error 1 make[2]: *** [sound/soc/codecs] Error 2 make[1]: *** [sound/soc] Error 2 make: *** [sound] Error 2 Also fix the same issue for SND_KIRKWOOD_SOC_OPENRD. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- sound/soc/kirkwood/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/kirkwood/Kconfig b/sound/soc/kirkwood/Kconfig index 8f49e165f4d1..c62d715235e2 100644 --- a/sound/soc/kirkwood/Kconfig +++ b/sound/soc/kirkwood/Kconfig @@ -12,6 +12,7 @@ config SND_KIRKWOOD_SOC_I2S config SND_KIRKWOOD_SOC_OPENRD tristate "SoC Audio support for Kirkwood Openrd Client" depends on SND_KIRKWOOD_SOC && (MACH_OPENRD_CLIENT || MACH_OPENRD_ULTIMATE) + depends on I2C select SND_KIRKWOOD_SOC_I2S select SND_SOC_CS42L51 help @@ -20,7 +21,7 @@ config SND_KIRKWOOD_SOC_OPENRD config SND_KIRKWOOD_SOC_T5325 tristate "SoC Audio support for HP t5325" - depends on SND_KIRKWOOD_SOC && MACH_T5325 + depends on SND_KIRKWOOD_SOC && MACH_T5325 && I2C select SND_KIRKWOOD_SOC_I2S select SND_SOC_ALC5623 help From ef1497707c69f3805bbca97c5d10c2913b6d2fa1 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 4 Dec 2011 19:35:20 +0800 Subject: [PATCH 05/14] ASoC: uda1380: Return proper error in uda1380_modinit failure path Return proper error for uda1380_modinit if i2c_add_driver() fails. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- sound/soc/codecs/uda1380.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index c5ca8cfea60f..0441893e270e 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -863,13 +863,13 @@ static struct i2c_driver uda1380_i2c_driver = { static int __init uda1380_modinit(void) { - int ret; + int ret = 0; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) ret = i2c_add_driver(&uda1380_i2c_driver); if (ret != 0) pr_err("Failed to register UDA1380 I2C driver: %d\n", ret); #endif - return 0; + return ret; } module_init(uda1380_modinit); From b971c370a4d265848d9df0793b2f7fcc5b16b378 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 4 Dec 2011 16:30:18 +0800 Subject: [PATCH 06/14] ASoC: Fix dependency for SND_SOC_RAUMFELD and SND_PXA2XX_SOC_HX4700 SND_SOC_RAUMFELD selects SND_SOC_CS4270 which needs CONFIG_I2C, and also selects SND_SOC_AK4104 which needs SPI_MASTER. Thus make SND_SOC_RAUMFELD depend on I2C && SPI_MASTER. Add depend on SPI_MASTER to fix below build error if CONFIG_SPI_MASTER is not selected. LD .tmp_vmlinux1 sound/built-in.o: In function `ak4104_spi_write': last.c:(.text+0x290cc): undefined reference to `spi_sync' sound/built-in.o: In function `ak4104_probe': last.c:(.text+0x292a0): undefined reference to `spi_write_then_read' sound/built-in.o: In function `ak4104_spi_probe': last.c:(.text+0x29398): undefined reference to `spi_setup' sound/built-in.o: In function `ak4104_init': last.c:(.init.text+0x4ec): undefined reference to `spi_register_driver' make: *** [.tmp_vmlinux1] Error 1 Add depend on I2C to fix below build error if CONFIG_I2C is not selected: CC sound/soc/codecs/cs4270.o sound/soc/codecs/cs4270.c: In function 'cs4270_i2c_probe': sound/soc/codecs/cs4270.c:657: error: implicit declaration of function 'i2c_smbus_read_byte_data' sound/soc/codecs/cs4270.c: In function 'cs4270_init': sound/soc/codecs/cs4270.c:730: error: implicit declaration of function 'i2c_add_driver' sound/soc/codecs/cs4270.c: In function 'cs4270_exit': sound/soc/codecs/cs4270.c:736: error: implicit declaration of function 'i2c_del_driver' make[3]: *** [sound/soc/codecs/cs4270.o] Error 1 make[2]: *** [sound/soc/codecs] Error 2 make[1]: *** [sound/soc] Error 2 make: *** [sound] Error 2 SND_PXA2XX_SOC_HX4700 selects SND_SOC_AK4641 which needs CONFIG_I2C. Thus make SND_PXA2XX_SOC_HX4700 depend on I2C. Add depend on I2C to fix below build error if CONFIG_I2C is not selected: CC sound/soc/codecs/ak4641.o sound/soc/codecs/ak4641.c: In function 'ak4641_modinit': sound/soc/codecs/ak4641.c:646: error: implicit declaration of function 'i2c_add_driver' sound/soc/codecs/ak4641.c: In function 'ak4641_exit': sound/soc/codecs/ak4641.c:656: error: implicit declaration of function 'i2c_del_driver' make[3]: *** [sound/soc/codecs/ak4641.o] Error 1 make[2]: *** [sound/soc/codecs] Error 2 make[1]: *** [sound/soc] Error 2 make: *** [sound] Error 2 Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- sound/soc/pxa/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index ffd2242e305f..a0f7d3cfa470 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -151,6 +151,7 @@ config SND_SOC_ZYLONITE config SND_SOC_RAUMFELD tristate "SoC Audio support Raumfeld audio adapter" depends on SND_PXA2XX_SOC && (MACH_RAUMFELD_SPEAKER || MACH_RAUMFELD_CONNECTOR) + depends on I2C && SPI_MASTER select SND_PXA_SOC_SSP select SND_SOC_CS4270 select SND_SOC_AK4104 @@ -159,7 +160,7 @@ config SND_SOC_RAUMFELD config SND_PXA2XX_SOC_HX4700 tristate "SoC Audio support for HP iPAQ hx4700" - depends on SND_PXA2XX_SOC && MACH_H4700 + depends on SND_PXA2XX_SOC && MACH_H4700 && I2C select SND_PXA2XX_SOC_I2S select SND_SOC_AK4641 help From 570a2429e964f8d63338b3450ba801a263b29b3a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 4 Dec 2011 16:11:16 +0800 Subject: [PATCH 07/14] ASoC: Make SND_SOC_MX27VIS_AIC32X4 depend on I2C SND_SOC_MX27VIS_AIC32X4 selects SND_SOC_TLV320AIC32X4, but SND_SOC_TLV320AIC32X4 needs CONFIG_I2C. So we need to make SND_SOC_MX27VIS_AIC32X4 depend on I2C. otherwise I got below build error if CONFIG_I2C is not selected. CC sound/soc/codecs/tlv320aic32x4.o sound/soc/codecs/tlv320aic32x4.c: In function 'aic32x4_read': sound/soc/codecs/tlv320aic32x4.c:323: error: implicit declaration of function 'i2c_smbus_read_byte_data' sound/soc/codecs/tlv320aic32x4.c: In function 'aic32x4_probe': sound/soc/codecs/tlv320aic32x4.c:641: error: 'i2c_master_send' undeclared (first use in this function) sound/soc/codecs/tlv320aic32x4.c:641: error: (Each undeclared identifier is reported only once sound/soc/codecs/tlv320aic32x4.c:641: error: for each function it appears in.) sound/soc/codecs/tlv320aic32x4.c: In function 'aic32x4_modinit': sound/soc/codecs/tlv320aic32x4.c:763: error: implicit declaration of function 'i2c_add_driver' sound/soc/codecs/tlv320aic32x4.c: In function 'aic32x4_exit': sound/soc/codecs/tlv320aic32x4.c:774: error: implicit declaration of function 'i2c_del_driver' make[3]: *** [sound/soc/codecs/tlv320aic32x4.o] Error 1 make[2]: *** [sound/soc/codecs] Error 2 make[1]: *** [sound/soc] Error 2 make: *** [sound] Error 2 Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- sound/soc/imx/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig index b133bfcc5848..738391757f2c 100644 --- a/sound/soc/imx/Kconfig +++ b/sound/soc/imx/Kconfig @@ -28,7 +28,7 @@ config SND_MXC_SOC_WM1133_EV1 config SND_SOC_MX27VIS_AIC32X4 tristate "SoC audio support for Visstrim M10 boards" - depends on MACH_IMX27_VISSTRIM_M10 + depends on MACH_IMX27_VISSTRIM_M10 && I2C select SND_SOC_TLV320AIC32X4 select SND_MXC_SOC_MX2 help From 145294c359a690b35c62d27dcff28fe892d02aca Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 5 Dec 2011 18:27:25 +0000 Subject: [PATCH 08/14] ASoC: Remove references to corgi and spitz from machine driver document They're not currently actively worked on, the hardware being rather obsolete by now. Signed-off-by: Mark Brown --- Documentation/sound/alsa/soc/machine.txt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Documentation/sound/alsa/soc/machine.txt b/Documentation/sound/alsa/soc/machine.txt index 3e2ec9cbf397..d50c14df3411 100644 --- a/Documentation/sound/alsa/soc/machine.txt +++ b/Documentation/sound/alsa/soc/machine.txt @@ -50,8 +50,7 @@ Machine DAI Configuration The machine DAI configuration glues all the codec and CPU DAIs together. It can also be used to set up the DAI system clock and for any machine related DAI initialisation e.g. the machine audio map can be connected to the codec audio -map, unconnected codec pins can be set as such. Please see corgi.c, spitz.c -for examples. +map, unconnected codec pins can be set as such. struct snd_soc_dai_link is used to set up each DAI in your machine. e.g. @@ -83,8 +82,7 @@ Machine Power Map The machine driver can optionally extend the codec power map and to become an audio power map of the audio subsystem. This allows for automatic power up/down of speaker/HP amplifiers, etc. Codec pins can be connected to the machines jack -sockets in the machine init function. See soc/pxa/spitz.c and dapm.txt for -details. +sockets in the machine init function. Machine Controls From cefcc03ffc9527dde56807339edb1719c8dbae5f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 5 Dec 2011 20:50:45 +0000 Subject: [PATCH 09/14] ASoC: Provide a more complete DMA driver stub Allow userspace applications to do more parameter setting by providing a more complete stub DMA driver specifying a wildcard set of formats and channels and essentially random values for the DMA parameters. This is required for useful runtime operation of the dummy DMA driver until we are able to figure out how to power up links and do hw_params() from DAPM. Sending to stable as without this the dummy driver is not terribly useful. Reported-by: Kyung-Kwee Ryu Tested-by: Kyung-Kwee Ryu Signed-off-by: Mark Brown Cc: stable@kernel.org --- sound/soc/soc-utils.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index 0c12b98484bd..4220bb0f2730 100644 --- a/sound/soc/soc-utils.c +++ b/sound/soc/soc-utils.c @@ -58,7 +58,36 @@ int snd_soc_params_to_bclk(struct snd_pcm_hw_params *params) } EXPORT_SYMBOL_GPL(snd_soc_params_to_bclk); -static struct snd_soc_platform_driver dummy_platform; +static const struct snd_pcm_hardware dummy_dma_hardware = { + .formats = 0xffffffff, + .channels_min = 1, + .channels_max = UINT_MAX, + + /* Random values to keep userspace happy when checking constraints */ + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER, + .buffer_bytes_max = 128*1024, + .period_bytes_min = PAGE_SIZE, + .period_bytes_max = PAGE_SIZE*2, + .periods_min = 2, + .periods_max = 128, +}; + +static int dummy_dma_open(struct snd_pcm_substream *substream) +{ + snd_soc_set_runtime_hwparams(substream, &dummy_dma_hardware); + + return 0; +} + +static struct snd_pcm_ops dummy_dma_ops = { + .open = dummy_dma_open, + .ioctl = snd_pcm_lib_ioctl, +}; + +static struct snd_soc_platform_driver dummy_platform = { + .ops = &dummy_dma_ops, +}; static __devinit int snd_soc_dummy_probe(struct platform_device *pdev) { From f1a73746c6664442082e3d53e1804f46e1910436 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 4 Dec 2011 13:44:06 +0100 Subject: [PATCH 10/14] ALSA: hda - Fix GPIO LED setup for IDT 92HD75 codecs Some HP laptops with IDT 92HD75 codecs may use a GPIO > 4 for the mute LED, but currently the driver doesn't check this properly, and confuses the mute LED behavior. This ended up with the silent output on some HP laptops due to having another GPIO used as external amp control. This patch fixes the problem by checking the max GPIO count and comparing with the given value from DMI entry instead of magic fixed value 4 and 8, and adding a new field to indicate the VREF mute-LED behavior. Reported-and-tested-by: Vitaliy Kulikov Cc: [v3.1] Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 45 ++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index f3658658548e..e035cf6de278 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -215,6 +215,7 @@ struct sigmatel_spec { unsigned int gpio_mute; unsigned int gpio_led; unsigned int gpio_led_polarity; + unsigned int vref_mute_led_nid; /* pin NID for mute-LED vref control */ unsigned int vref_led; /* stream */ @@ -4318,12 +4319,10 @@ static void stac_store_hints(struct hda_codec *codec) spec->eapd_switch = val; get_int_hint(codec, "gpio_led_polarity", &spec->gpio_led_polarity); if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) { - if (spec->gpio_led <= 8) { - spec->gpio_mask |= spec->gpio_led; - spec->gpio_dir |= spec->gpio_led; - if (spec->gpio_led_polarity) - spec->gpio_data |= spec->gpio_led; - } + spec->gpio_mask |= spec->gpio_led; + spec->gpio_dir |= spec->gpio_led; + if (spec->gpio_led_polarity) + spec->gpio_data |= spec->gpio_led; } } @@ -4913,8 +4912,14 @@ static int find_mute_led_gpio(struct hda_codec *codec, int default_polarity) if (sscanf(dev->name, "HP_Mute_LED_%d_%x", &spec->gpio_led_polarity, &spec->gpio_led) == 2) { - if (spec->gpio_led < 4) + unsigned int max_gpio; + max_gpio = snd_hda_param_read(codec, codec->afg, + AC_PAR_GPIO_CAP); + max_gpio &= AC_GPIO_IO_COUNT; + if (spec->gpio_led < max_gpio) spec->gpio_led = 1 << spec->gpio_led; + else + spec->vref_mute_led_nid = spec->gpio_led; return 1; } if (sscanf(dev->name, "HP_Mute_LED_%d", @@ -5043,15 +5048,12 @@ static int stac92xx_pre_resume(struct hda_codec *codec) struct sigmatel_spec *spec = codec->spec; /* sync mute LED */ - if (spec->gpio_led) { - if (spec->gpio_led <= 8) { - stac_gpio_set(codec, spec->gpio_mask, - spec->gpio_dir, spec->gpio_data); - } else { - stac_vrefout_set(codec, - spec->gpio_led, spec->vref_led); - } - } + if (spec->vref_mute_led_nid) + stac_vrefout_set(codec, spec->vref_mute_led_nid, + spec->vref_led); + else if (spec->gpio_led) + stac_gpio_set(codec, spec->gpio_mask, + spec->gpio_dir, spec->gpio_data); return 0; } @@ -5076,7 +5078,7 @@ static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg, struct sigmatel_spec *spec = codec->spec; if (power_state == AC_PWRST_D3) { - if (spec->gpio_led > 8) { + if (spec->vref_mute_led_nid) { /* with vref-out pin used for mute led control * codec AFG is prevented from D3 state */ @@ -5129,7 +5131,7 @@ static int stac92xx_update_led_status(struct hda_codec *codec) } } /*polarity defines *not* muted state level*/ - if (spec->gpio_led <= 8) { + if (!spec->vref_mute_led_nid) { if (muted) spec->gpio_data &= ~spec->gpio_led; /* orange */ else @@ -5147,7 +5149,8 @@ static int stac92xx_update_led_status(struct hda_codec *codec) muted_lvl = spec->gpio_led_polarity ? AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_HIZ; spec->vref_led = muted ? muted_lvl : notmtd_lvl; - stac_vrefout_set(codec, spec->gpio_led, spec->vref_led); + stac_vrefout_set(codec, spec->vref_mute_led_nid, + spec->vref_led); } return 0; } @@ -5661,7 +5664,7 @@ again: #ifdef CONFIG_SND_HDA_POWER_SAVE if (spec->gpio_led) { - if (spec->gpio_led <= 8) { + if (!spec->vref_mute_led_nid) { spec->gpio_mask |= spec->gpio_led; spec->gpio_dir |= spec->gpio_led; spec->gpio_data |= spec->gpio_led; @@ -5976,7 +5979,7 @@ again: #ifdef CONFIG_SND_HDA_POWER_SAVE if (spec->gpio_led) { - if (spec->gpio_led <= 8) { + if (!spec->vref_mute_led_nid) { spec->gpio_mask |= spec->gpio_led; spec->gpio_dir |= spec->gpio_led; spec->gpio_data |= spec->gpio_led; From a020428364485751b607105c8f5a608f9b1fd38b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 6 Dec 2011 13:17:23 +0100 Subject: [PATCH 11/14] ALSA: hda - Fix remaining VREF mute-LED NID check in post-3.1 changes Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index ea1f157ca38b..eeb25d529e30 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -4442,7 +4442,7 @@ static int stac92xx_init(struct hda_codec *codec) /* power on when no jack detection is available */ /* or when the VREF is used for controlling LED */ if (!spec->hp_detect || - (spec->gpio_led > 8 && spec->gpio_led == nid)) { + spec->vref_mute_led_nid == nid) { stac_toggle_power_map(codec, nid, 1); continue; } From 766ddee68bf1e4cc2cdcf73b34d243cf6e6f8ab0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Dec 2011 16:55:19 +0100 Subject: [PATCH 12/14] ALSA: hda/realtek - Don't create extra controls with channel suffix The multiple headphone or speaker pins are usually provided to output the same stream unlike line-out jacks (which are supposed to be multi-channel surrounds). Thus giving a mixer name like "Headphone Surround" is rather confusing. Instead, when multiple headphone volumes are available, use index with the same "Headphone" name. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a7d1bc4e0d09..96f5da9db5cf 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3173,7 +3173,8 @@ static int alc_auto_create_multi_out_ctls(struct hda_codec *codec, } static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, - hda_nid_t dac, const char *pfx) + hda_nid_t dac, const char *pfx, + int cidx) { struct alc_spec *spec = codec->spec; hda_nid_t sw, vol; @@ -3189,15 +3190,15 @@ static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, if (is_ctl_used(spec->sw_ctls, val)) return 0; /* already created */ mark_ctl_usage(spec->sw_ctls, val); - return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, val); + return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, cidx, val); } sw = alc_look_for_out_mute_nid(codec, pin, dac); vol = alc_look_for_out_vol_nid(codec, pin, dac); - err = alc_auto_add_stereo_vol(codec, pfx, 0, vol); + err = alc_auto_add_stereo_vol(codec, pfx, cidx, vol); if (err < 0) return err; - err = alc_auto_add_stereo_sw(codec, pfx, 0, sw); + err = alc_auto_add_stereo_sw(codec, pfx, cidx, sw); if (err < 0) return err; return 0; @@ -3238,16 +3239,21 @@ static int alc_auto_create_extra_outs(struct hda_codec *codec, int num_pins, hda_nid_t dac = *dacs; if (!dac) dac = spec->multiout.dac_nids[0]; - return alc_auto_create_extra_out(codec, *pins, dac, pfx); + return alc_auto_create_extra_out(codec, *pins, dac, pfx, 0); } if (dacs[num_pins - 1]) { /* OK, we have a multi-output system with individual volumes */ for (i = 0; i < num_pins; i++) { - snprintf(name, sizeof(name), "%s %s", - pfx, channel_name[i]); - err = alc_auto_create_extra_out(codec, pins[i], dacs[i], - name); + if (num_pins >= 3) { + snprintf(name, sizeof(name), "%s %s", + pfx, channel_name[i]); + err = alc_auto_create_extra_out(codec, pins[i], dacs[i], + name, 0); + } else { + err = alc_auto_create_extra_out(codec, pins[i], dacs[i], + pfx, i); + } if (err < 0) return err; } From fbabc24619f7298626265a3f973786b471b8c29d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Dec 2011 17:14:20 +0100 Subject: [PATCH 13/14] ALSA: hda/realtek - Create "Bass Speaker" for two speaker pins On systems with two speaker pins, the secondary speaker pin is mostly assigned to a bass speaker instead of a surround. Thus it makes more sense to rename the control properly. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 96f5da9db5cf..214d4f91d6af 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2631,6 +2631,8 @@ static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch, case AUTO_PIN_SPEAKER_OUT: if (cfg->line_outs == 1) return "Speaker"; + if (cfg->line_outs == 2) + return ch ? "Bass Speaker" : "Speaker"; break; case AUTO_PIN_HP_OUT: /* for multi-io case, only the primary out */ From 0a34b42b6245ccc710be6759cded5b7fe41ea1f9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 7 Dec 2011 17:20:30 +0100 Subject: [PATCH 14/14] ALSA: hda/realtek - Fix lost speaker volume controls When there are the same or more number of HP pins are available, HP pins are used as the primary outputs instead of the speaker pins. But, in some cases (especially with ALC663 & co), some DACs are available only with a later pin and it's assigned to a speaker, and since the driver parses the pins from the lower NID, such a DAC was skipped eventually without assignments. This resulted in a regression, the missing speaker volume control in the new parser. As a workaround for this, now the driver retries the pin->DAC mapping again after restoring the speaker-pins as primary. This is still an ad hoc fix, but it works so far for most of Realtek codecs. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 37 ++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 214d4f91d6af..1d07e8fa2433 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2906,7 +2906,7 @@ static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin) if (!nid) continue; if (found_in_nid_list(nid, spec->multiout.dac_nids, - spec->multiout.num_dacs)) + ARRAY_SIZE(spec->private_dac_nids))) continue; if (found_in_nid_list(nid, spec->multiout.hp_out_nid, ARRAY_SIZE(spec->multiout.hp_out_nid))) @@ -2927,6 +2927,7 @@ static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin) return 0; } +/* return 0 if no possible DAC is found, 1 if one or more found */ static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs, const hda_nid_t *pins, hda_nid_t *dacs) { @@ -2944,7 +2945,7 @@ static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs, if (!dacs[i]) dacs[i] = alc_auto_look_for_dac(codec, pins[i]); } - return 0; + return 1; } static int alc_auto_fill_multi_ios(struct hda_codec *codec, @@ -2954,7 +2955,7 @@ static int alc_auto_fill_multi_ios(struct hda_codec *codec, static int alc_auto_fill_dac_nids(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - const struct auto_pin_cfg *cfg = &spec->autocfg; + struct auto_pin_cfg *cfg = &spec->autocfg; bool redone = false; int i; @@ -2965,6 +2966,7 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) spec->multiout.extra_out_nid[0] = 0; memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids)); spec->multiout.dac_nids = spec->private_dac_nids; + spec->multi_ios = 0; /* fill hard-wired DACs first */ if (!redone) { @@ -2998,10 +3000,12 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) for (i = 0; i < cfg->line_outs; i++) { if (spec->private_dac_nids[i]) spec->multiout.num_dacs++; - else + else { memmove(spec->private_dac_nids + i, spec->private_dac_nids + i + 1, sizeof(hda_nid_t) * (cfg->line_outs - i - 1)); + spec->private_dac_nids[cfg->line_outs - 1] = 0; + } } if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { @@ -3023,9 +3027,28 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) if (cfg->line_out_type != AUTO_PIN_HP_OUT) alc_auto_fill_extra_dacs(codec, cfg->hp_outs, cfg->hp_pins, spec->multiout.hp_out_nid); - if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) - alc_auto_fill_extra_dacs(codec, cfg->speaker_outs, cfg->speaker_pins, - spec->multiout.extra_out_nid); + if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { + int err = alc_auto_fill_extra_dacs(codec, cfg->speaker_outs, + cfg->speaker_pins, + spec->multiout.extra_out_nid); + /* if no speaker volume is assigned, try again as the primary + * output + */ + if (!err && cfg->speaker_outs > 0 && + cfg->line_out_type == AUTO_PIN_HP_OUT) { + cfg->hp_outs = cfg->line_outs; + memcpy(cfg->hp_pins, cfg->line_out_pins, + sizeof(cfg->hp_pins)); + cfg->line_outs = cfg->speaker_outs; + memcpy(cfg->line_out_pins, cfg->speaker_pins, + sizeof(cfg->speaker_pins)); + cfg->speaker_outs = 0; + memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); + cfg->line_out_type = AUTO_PIN_SPEAKER_OUT; + redone = false; + goto again; + } + } return 0; }