diff options
author | Takashi Iwai <tiwai@suse.de> | 2022-07-04 14:14:04 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2022-07-04 14:14:04 +0200 |
commit | dd84cfff3cc3b79c9d616f85bd1178df135cbd1a (patch) | |
tree | cd02e30a78211bed4f1270877b705a079d4bd364 /sound | |
parent | ALSA: usb-audio: Add quirk for Fiero SC-01 (fw v1.0.0) (diff) | |
parent | ASoC: madera: Fix event generation for rate controls (diff) | |
download | linux-dd84cfff3cc3b79c9d616f85bd1178df135cbd1a.tar.xz linux-dd84cfff3cc3b79c9d616f85bd1178df135cbd1a.zip |
Merge tag 'asoc-fix-v5.19-rc3' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Fixes for v5.19
A collection of fixes for v5.19, quite large but nothing major - a good
chunk of it is more stuff that was identified by mixer-test regarding
event generation.
Diffstat (limited to 'sound')
64 files changed, 1015 insertions, 680 deletions
diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c index 58274b4a1f09..e55c0421718b 100644 --- a/sound/arm/pxa2xx-ac97-lib.c +++ b/sound/arm/pxa2xx-ac97-lib.c @@ -17,12 +17,13 @@ #include <linux/io.h> #include <linux/gpio.h> #include <linux/of_gpio.h> +#include <linux/soc/pxa/cpu.h> #include <sound/pxa2xx-lib.h> -#include <mach/irqs.h> -#include <mach/regs-ac97.h> -#include <mach/audio.h> +#include <linux/platform_data/asoc-pxa.h> + +#include "pxa2xx-ac97-regs.h" static DEFINE_MUTEX(car_mutex); static DECLARE_WAIT_QUEUE_HEAD(gsr_wq); @@ -30,6 +31,7 @@ static volatile long gsr_bits; static struct clk *ac97_clk; static struct clk *ac97conf_clk; static int reset_gpio; +static void __iomem *ac97_reg_base; extern void pxa27x_configure_ac97reset(int reset_gpio, bool to_gpio); @@ -46,7 +48,7 @@ extern void pxa27x_configure_ac97reset(int reset_gpio, bool to_gpio); int pxa2xx_ac97_read(int slot, unsigned short reg) { int val = -ENODEV; - volatile u32 *reg_addr; + u32 __iomem *reg_addr; if (slot > 0) return -ENODEV; @@ -55,31 +57,33 @@ int pxa2xx_ac97_read(int slot, unsigned short reg) /* set up primary or secondary codec space */ if (cpu_is_pxa25x() && reg == AC97_GPIO_STATUS) - reg_addr = slot ? &SMC_REG_BASE : &PMC_REG_BASE; + reg_addr = ac97_reg_base + + (slot ? SMC_REG_BASE : PMC_REG_BASE); else - reg_addr = slot ? &SAC_REG_BASE : &PAC_REG_BASE; + reg_addr = ac97_reg_base + + (slot ? SAC_REG_BASE : PAC_REG_BASE); reg_addr += (reg >> 1); /* start read access across the ac97 link */ - GSR = GSR_CDONE | GSR_SDONE; + writel(GSR_CDONE | GSR_SDONE, ac97_reg_base + GSR); gsr_bits = 0; - val = (*reg_addr & 0xffff); + val = (readl(reg_addr) & 0xffff); if (reg == AC97_GPIO_STATUS) goto out; - if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1) <= 0 && - !((GSR | gsr_bits) & GSR_SDONE)) { + if (wait_event_timeout(gsr_wq, (readl(ac97_reg_base + GSR) | gsr_bits) & GSR_SDONE, 1) <= 0 && + !((readl(ac97_reg_base + GSR) | gsr_bits) & GSR_SDONE)) { printk(KERN_ERR "%s: read error (ac97_reg=%d GSR=%#lx)\n", - __func__, reg, GSR | gsr_bits); + __func__, reg, readl(ac97_reg_base + GSR) | gsr_bits); val = -ETIMEDOUT; goto out; } /* valid data now */ - GSR = GSR_CDONE | GSR_SDONE; + writel(GSR_CDONE | GSR_SDONE, ac97_reg_base + GSR); gsr_bits = 0; - val = (*reg_addr & 0xffff); + val = (readl(reg_addr) & 0xffff); /* but we've just started another cycle... */ - wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1); + wait_event_timeout(gsr_wq, (readl(ac97_reg_base + GSR) | gsr_bits) & GSR_SDONE, 1); out: mutex_unlock(&car_mutex); return val; @@ -88,25 +92,27 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_read); int pxa2xx_ac97_write(int slot, unsigned short reg, unsigned short val) { - volatile u32 *reg_addr; + u32 __iomem *reg_addr; int ret = 0; mutex_lock(&car_mutex); /* set up primary or secondary codec space */ if (cpu_is_pxa25x() && reg == AC97_GPIO_STATUS) - reg_addr = slot ? &SMC_REG_BASE : &PMC_REG_BASE; + reg_addr = ac97_reg_base + + (slot ? SMC_REG_BASE : PMC_REG_BASE); else - reg_addr = slot ? &SAC_REG_BASE : &PAC_REG_BASE; + reg_addr = ac97_reg_base + + (slot ? SAC_REG_BASE : PAC_REG_BASE); reg_addr += (reg >> 1); - GSR = GSR_CDONE | GSR_SDONE; + writel(GSR_CDONE | GSR_SDONE, ac97_reg_base + GSR); gsr_bits = 0; - *reg_addr = val; - if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1) <= 0 && - !((GSR | gsr_bits) & GSR_CDONE)) { + writel(val, reg_addr); + if (wait_event_timeout(gsr_wq, (readl(ac97_reg_base + GSR) | gsr_bits) & GSR_CDONE, 1) <= 0 && + !((readl(ac97_reg_base + GSR) | gsr_bits) & GSR_CDONE)) { printk(KERN_ERR "%s: write error (ac97_reg=%d GSR=%#lx)\n", - __func__, reg, GSR | gsr_bits); + __func__, reg, readl(ac97_reg_base + GSR) | gsr_bits); ret = -EIO; } @@ -120,17 +126,17 @@ static inline void pxa_ac97_warm_pxa25x(void) { gsr_bits = 0; - GCR |= GCR_WARM_RST; + writel(readl(ac97_reg_base + GCR) | (GCR_WARM_RST), ac97_reg_base + GCR); } static inline void pxa_ac97_cold_pxa25x(void) { - GCR &= GCR_COLD_RST; /* clear everything but nCRST */ - GCR &= ~GCR_COLD_RST; /* then assert nCRST */ + writel(readl(ac97_reg_base + GCR) & ( GCR_COLD_RST), ac97_reg_base + GCR); /* clear everything but nCRST */ + writel(readl(ac97_reg_base + GCR) & (~GCR_COLD_RST), ac97_reg_base + GCR); /* then assert nCRST */ gsr_bits = 0; - GCR = GCR_COLD_RST; + writel(GCR_COLD_RST, ac97_reg_base + GCR); } #endif @@ -142,15 +148,15 @@ static inline void pxa_ac97_warm_pxa27x(void) /* warm reset broken on Bulverde, so manually keep AC97 reset high */ pxa27x_configure_ac97reset(reset_gpio, true); udelay(10); - GCR |= GCR_WARM_RST; + writel(readl(ac97_reg_base + GCR) | (GCR_WARM_RST), ac97_reg_base + GCR); pxa27x_configure_ac97reset(reset_gpio, false); udelay(500); } static inline void pxa_ac97_cold_pxa27x(void) { - GCR &= GCR_COLD_RST; /* clear everything but nCRST */ - GCR &= ~GCR_COLD_RST; /* then assert nCRST */ + writel(readl(ac97_reg_base + GCR) & ( GCR_COLD_RST), ac97_reg_base + GCR); /* clear everything but nCRST */ + writel(readl(ac97_reg_base + GCR) & (~GCR_COLD_RST), ac97_reg_base + GCR); /* then assert nCRST */ gsr_bits = 0; @@ -158,7 +164,7 @@ static inline void pxa_ac97_cold_pxa27x(void) clk_prepare_enable(ac97conf_clk); udelay(5); clk_disable_unprepare(ac97conf_clk); - GCR = GCR_COLD_RST | GCR_WARM_RST; + writel(GCR_COLD_RST | GCR_WARM_RST, ac97_reg_base + GCR); } #endif @@ -168,26 +174,26 @@ static inline void pxa_ac97_warm_pxa3xx(void) gsr_bits = 0; /* Can't use interrupts */ - GCR |= GCR_WARM_RST; + writel(readl(ac97_reg_base + GCR) | (GCR_WARM_RST), ac97_reg_base + GCR); } static inline void pxa_ac97_cold_pxa3xx(void) { /* Hold CLKBPB for 100us */ - GCR = 0; - GCR = GCR_CLKBPB; + writel(0, ac97_reg_base + GCR); + writel(GCR_CLKBPB, ac97_reg_base + GCR); udelay(100); - GCR = 0; + writel(0, ac97_reg_base + GCR); - GCR &= GCR_COLD_RST; /* clear everything but nCRST */ - GCR &= ~GCR_COLD_RST; /* then assert nCRST */ + writel(readl(ac97_reg_base + GCR) & ( GCR_COLD_RST), ac97_reg_base + GCR); /* clear everything but nCRST */ + writel(readl(ac97_reg_base + GCR) & (~GCR_COLD_RST), ac97_reg_base + GCR); /* then assert nCRST */ gsr_bits = 0; /* Can't use interrupts on PXA3xx */ - GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN); + writel(readl(ac97_reg_base + GCR) & (~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN)), ac97_reg_base + GCR); - GCR = GCR_WARM_RST | GCR_COLD_RST; + writel(GCR_WARM_RST | GCR_COLD_RST, ac97_reg_base + GCR); } #endif @@ -213,10 +219,10 @@ bool pxa2xx_ac97_try_warm_reset(void) #endif snd_BUG(); - while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--) + while (!((readl(ac97_reg_base + GSR) | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--) mdelay(1); - gsr = GSR | gsr_bits; + gsr = readl(ac97_reg_base + GSR) | gsr_bits; if (!(gsr & (GSR_PCR | GSR_SCR))) { printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n", __func__, gsr); @@ -250,10 +256,10 @@ bool pxa2xx_ac97_try_cold_reset(void) #endif snd_BUG(); - while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--) + while (!((readl(ac97_reg_base + GSR) | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--) mdelay(1); - gsr = GSR | gsr_bits; + gsr = readl(ac97_reg_base + GSR) | gsr_bits; if (!(gsr & (GSR_PCR | GSR_SCR))) { printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n", __func__, gsr); @@ -268,8 +274,10 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_try_cold_reset); void pxa2xx_ac97_finish_reset(void) { - GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN); - GCR |= GCR_SDONE_IE|GCR_CDONE_IE; + u32 gcr = readl(ac97_reg_base + GCR); + gcr &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN); + gcr |= GCR_SDONE_IE|GCR_CDONE_IE; + writel(gcr, ac97_reg_base + GCR); } EXPORT_SYMBOL_GPL(pxa2xx_ac97_finish_reset); @@ -277,9 +285,9 @@ static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id) { long status; - status = GSR; + status = readl(ac97_reg_base + GSR); if (status) { - GSR = status; + writel(status, ac97_reg_base + GSR); gsr_bits |= status; wake_up(&gsr_wq); @@ -287,9 +295,9 @@ static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id) since they tend to spuriously trigger when MMC is used (hardware bug? go figure)... */ if (cpu_is_pxa27x()) { - MISR = MISR_EOC; - PISR = PISR_EOC; - MCSR = MCSR_EOC; + writel(MISR_EOC, ac97_reg_base + MISR); + writel(PISR_EOC, ac97_reg_base + PISR); + writel(MCSR_EOC, ac97_reg_base + MCSR); } return IRQ_HANDLED; @@ -301,7 +309,7 @@ static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id) #ifdef CONFIG_PM int pxa2xx_ac97_hw_suspend(void) { - GCR |= GCR_ACLINK_OFF; + writel(readl(ac97_reg_base + GCR) | (GCR_ACLINK_OFF), ac97_reg_base + GCR); clk_disable_unprepare(ac97_clk); return 0; } @@ -318,8 +326,15 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_resume); int pxa2xx_ac97_hw_probe(struct platform_device *dev) { int ret; + int irq; pxa2xx_audio_ops_t *pdata = dev->dev.platform_data; + ac97_reg_base = devm_platform_ioremap_resource(dev, 0); + if (IS_ERR(ac97_reg_base)) { + dev_err(&dev->dev, "Missing MMIO resource\n"); + return PTR_ERR(ac97_reg_base); + } + if (pdata) { switch (pdata->reset_gpio) { case 95: @@ -386,14 +401,18 @@ int pxa2xx_ac97_hw_probe(struct platform_device *dev) if (ret) goto err_clk2; - ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, 0, "AC97", NULL); + irq = platform_get_irq(dev, 0); + if (!irq) + goto err_irq; + + ret = request_irq(irq, pxa2xx_ac97_irq, 0, "AC97", NULL); if (ret < 0) goto err_irq; return 0; err_irq: - GCR |= GCR_ACLINK_OFF; + writel(readl(ac97_reg_base + GCR) | (GCR_ACLINK_OFF), ac97_reg_base + GCR); err_clk2: clk_put(ac97_clk); ac97_clk = NULL; @@ -411,8 +430,8 @@ void pxa2xx_ac97_hw_remove(struct platform_device *dev) { if (cpu_is_pxa27x()) gpio_free(reset_gpio); - GCR |= GCR_ACLINK_OFF; - free_irq(IRQ_AC97, NULL); + writel(readl(ac97_reg_base + GCR) | (GCR_ACLINK_OFF), ac97_reg_base + GCR); + free_irq(platform_get_irq(dev, 0), NULL); if (ac97conf_clk) { clk_put(ac97conf_clk); ac97conf_clk = NULL; @@ -423,6 +442,24 @@ void pxa2xx_ac97_hw_remove(struct platform_device *dev) } EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_remove); +u32 pxa2xx_ac97_read_modr(void) +{ + if (!ac97_reg_base) + return 0; + + return readl(ac97_reg_base + MODR); +} +EXPORT_SYMBOL_GPL(pxa2xx_ac97_read_modr); + +u32 pxa2xx_ac97_read_misr(void) +{ + if (!ac97_reg_base) + return 0; + + return readl(ac97_reg_base + MISR); +} +EXPORT_SYMBOL_GPL(pxa2xx_ac97_read_misr); + MODULE_AUTHOR("Nicolas Pitre"); MODULE_DESCRIPTION("Intel/Marvell PXA sound library"); MODULE_LICENSE("GPL"); diff --git a/sound/arm/pxa2xx-ac97-regs.h b/sound/arm/pxa2xx-ac97-regs.h new file mode 100644 index 000000000000..ae638a1b919b --- /dev/null +++ b/sound/arm/pxa2xx-ac97-regs.h @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __ASM_ARCH_REGS_AC97_H +#define __ASM_ARCH_REGS_AC97_H + +/* + * AC97 Controller registers + */ + +#define POCR (0x0000) /* PCM Out Control Register */ +#define POCR_FEIE (1 << 3) /* FIFO Error Interrupt Enable */ +#define POCR_FSRIE (1 << 1) /* FIFO Service Request Interrupt Enable */ + +#define PICR (0x0004) /* PCM In Control Register */ +#define PICR_FEIE (1 << 3) /* FIFO Error Interrupt Enable */ +#define PICR_FSRIE (1 << 1) /* FIFO Service Request Interrupt Enable */ + +#define MCCR (0x0008) /* Mic In Control Register */ +#define MCCR_FEIE (1 << 3) /* FIFO Error Interrupt Enable */ +#define MCCR_FSRIE (1 << 1) /* FIFO Service Request Interrupt Enable */ + +#define GCR (0x000C) /* Global Control Register */ +#ifdef CONFIG_PXA3xx +#define GCR_CLKBPB (1 << 31) /* Internal clock enable */ +#endif +#define GCR_nDMAEN (1 << 24) /* non DMA Enable */ +#define GCR_CDONE_IE (1 << 19) /* Command Done Interrupt Enable */ +#define GCR_SDONE_IE (1 << 18) /* Status Done Interrupt Enable */ +#define GCR_SECRDY_IEN (1 << 9) /* Secondary Ready Interrupt Enable */ +#define GCR_PRIRDY_IEN (1 << 8) /* Primary Ready Interrupt Enable */ +#define GCR_SECRES_IEN (1 << 5) /* Secondary Resume Interrupt Enable */ +#define GCR_PRIRES_IEN (1 << 4) /* Primary Resume Interrupt Enable */ +#define GCR_ACLINK_OFF (1 << 3) /* AC-link Shut Off */ +#define GCR_WARM_RST (1 << 2) /* AC97 Warm Reset */ +#define GCR_COLD_RST (1 << 1) /* AC'97 Cold Reset (0 = active) */ +#define GCR_GIE (1 << 0) /* Codec GPI Interrupt Enable */ + +#define POSR (0x0010) /* PCM Out Status Register */ +#define POSR_FIFOE (1 << 4) /* FIFO error */ +#define POSR_FSR (1 << 2) /* FIFO Service Request */ + +#define PISR (0x0014) /* PCM In Status Register */ +#define PISR_FIFOE (1 << 4) /* FIFO error */ +#define PISR_EOC (1 << 3) /* DMA End-of-Chain (exclusive clear) */ +#define PISR_FSR (1 << 2) /* FIFO Service Request */ + +#define MCSR (0x0018) /* Mic In Status Register */ +#define MCSR_FIFOE (1 << 4) /* FIFO error */ +#define MCSR_EOC (1 << 3) /* DMA End-of-Chain (exclusive clear) */ +#define MCSR_FSR (1 << 2) /* FIFO Service Request */ + +#define GSR (0x001C) /* Global Status Register */ +#define GSR_CDONE (1 << 19) /* Command Done */ +#define GSR_SDONE (1 << 18) /* Status Done */ +#define GSR_RDCS (1 << 15) /* Read Completion Status */ +#define GSR_BIT3SLT12 (1 << 14) /* Bit 3 of slot 12 */ +#define GSR_BIT2SLT12 (1 << 13) /* Bit 2 of slot 12 */ +#define GSR_BIT1SLT12 (1 << 12) /* Bit 1 of slot 12 */ +#define GSR_SECRES (1 << 11) /* Secondary Resume Interrupt */ +#define GSR_PRIRES (1 << 10) /* Primary Resume Interrupt */ +#define GSR_SCR (1 << 9) /* Secondary Codec Ready */ +#define GSR_PCR (1 << 8) /* Primary Codec Ready */ +#define GSR_MCINT (1 << 7) /* Mic In Interrupt */ +#define GSR_POINT (1 << 6) /* PCM Out Interrupt */ +#define GSR_PIINT (1 << 5) /* PCM In Interrupt */ +#define GSR_ACOFFD (1 << 3) /* AC-link Shut Off Done */ +#define GSR_MOINT (1 << 2) /* Modem Out Interrupt */ +#define GSR_MIINT (1 << 1) /* Modem In Interrupt */ +#define GSR_GSCI (1 << 0) /* Codec GPI Status Change Interrupt */ + +#define CAR (0x0020) /* CODEC Access Register */ +#define CAR_CAIP (1 << 0) /* Codec Access In Progress */ + +#define PCDR (0x0040) /* PCM FIFO Data Register */ +#define MCDR (0x0060) /* Mic-in FIFO Data Register */ + +#define MOCR (0x0100) /* Modem Out Control Register */ +#define MOCR_FEIE (1 << 3) /* FIFO Error */ +#define MOCR_FSRIE (1 << 1) /* FIFO Service Request Interrupt Enable */ + +#define MICR (0x0108) /* Modem In Control Register */ +#define MICR_FEIE (1 << 3) /* FIFO Error */ +#define MICR_FSRIE (1 << 1) /* FIFO Service Request Interrupt Enable */ + +#define MOSR (0x0110) /* Modem Out Status Register */ +#define MOSR_FIFOE (1 << 4) /* FIFO error */ +#define MOSR_FSR (1 << 2) /* FIFO Service Request */ + +#define MISR (0x0118) /* Modem In Status Register */ +#define MISR_FIFOE (1 << 4) /* FIFO error */ +#define MISR_EOC (1 << 3) /* DMA End-of-Chain (exclusive clear) */ +#define MISR_FSR (1 << 2) /* FIFO Service Request */ + +#define MODR (0x0140) /* Modem FIFO Data Register */ + +#define PAC_REG_BASE (0x0200) /* Primary Audio Codec */ +#define SAC_REG_BASE (0x0300) /* Secondary Audio Codec */ +#define PMC_REG_BASE (0x0400) /* Primary Modem Codec */ +#define SMC_REG_BASE (0x0500) /* Secondary Modem Codec */ + +#endif /* __ASM_ARCH_REGS_AC97_H */ diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c index c17a19fe59ed..c162086455ad 100644 --- a/sound/arm/pxa2xx-ac97.c +++ b/sound/arm/pxa2xx-ac97.c @@ -21,8 +21,7 @@ #include <sound/pxa2xx-lib.h> #include <sound/dmaengine_pcm.h> -#include <mach/regs-ac97.h> -#include <mach/audio.h> +#include <linux/platform_data/asoc-pxa.h> static void pxa2xx_ac97_legacy_reset(struct snd_ac97 *ac97) { diff --git a/sound/core/Makefile b/sound/core/Makefile index 350d704ced98..2762f03d9b7b 100644 --- a/sound/core/Makefile +++ b/sound/core/Makefile @@ -9,9 +9,7 @@ ifneq ($(CONFIG_SND_PROC_FS),) snd-y += info.o snd-$(CONFIG_SND_OSSEMUL) += info_oss.o endif -ifneq ($(CONFIG_M68K),y) snd-$(CONFIG_ISA_DMA_API) += isadma.o -endif snd-$(CONFIG_SND_OSSEMUL) += sound_oss.o snd-$(CONFIG_SND_VMASTER) += vmaster.o snd-$(CONFIG_SND_JACK) += ctljack.o jack.o diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index 570b88e0b201..6ffa48dd5983 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig @@ -22,7 +22,7 @@ config SND_SB16_DSP menuconfig SND_ISA bool "ISA sound devices" depends on ISA || COMPILE_TEST - depends on ISA_DMA_API && !M68K + depends on ISA_DMA_API default y help Support for sound devices connected via the ISA bus. diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c index 55e773f92122..93606e5afd8f 100644 --- a/sound/soc/codecs/ak4613.c +++ b/sound/soc/codecs/ak4613.c @@ -868,10 +868,12 @@ static void ak4613_parse_of(struct ak4613_priv *priv, /* * connected STDI + * TDM support is assuming it is probed via Audio-Graph-Card style here. + * Default is SDTIx1 if it was probed via Simple-Audio-Card for now. */ sdti_num = of_graph_get_endpoint_count(np); - if (WARN_ON((sdti_num > 3) || (sdti_num < 1))) - return; + if ((sdti_num >= SDTx_MAX) || (sdti_num < 1)) + sdti_num = 1; AK4613_CONFIG_SDTI_set(priv, sdti_num); } diff --git a/sound/soc/codecs/cs35l41-lib.c b/sound/soc/codecs/cs35l41-lib.c index 6d3070ea9e06..198cfe54a46f 100644 --- a/sound/soc/codecs/cs35l41-lib.c +++ b/sound/soc/codecs/cs35l41-lib.c @@ -37,8 +37,8 @@ static const struct reg_default cs35l41_reg[] = { { CS35L41_DAC_PCM1_SRC, 0x00000008 }, { CS35L41_ASP_TX1_SRC, 0x00000018 }, { CS35L41_ASP_TX2_SRC, 0x00000019 }, - { CS35L41_ASP_TX3_SRC, 0x00000020 }, - { CS35L41_ASP_TX4_SRC, 0x00000021 }, + { CS35L41_ASP_TX3_SRC, 0x00000000 }, + { CS35L41_ASP_TX4_SRC, 0x00000000 }, { CS35L41_DSP1_RX1_SRC, 0x00000008 }, { CS35L41_DSP1_RX2_SRC, 0x00000009 }, { CS35L41_DSP1_RX3_SRC, 0x00000018 }, @@ -644,6 +644,8 @@ static const struct reg_sequence cs35l41_reva0_errata_patch[] = { { CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 }, { CS35L41_PWR_CTRL2, 0x00000000 }, { CS35L41_AMP_GAIN_CTRL, 0x00000000 }, + { CS35L41_ASP_TX3_SRC, 0x00000000 }, + { CS35L41_ASP_TX4_SRC, 0x00000000 }, }; static const struct reg_sequence cs35l41_revb0_errata_patch[] = { @@ -655,6 +657,8 @@ static const struct reg_sequence cs35l41_revb0_errata_patch[] = { { CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 }, { CS35L41_PWR_CTRL2, 0x00000000 }, { CS35L41_AMP_GAIN_CTRL, 0x00000000 }, + { CS35L41_ASP_TX3_SRC, 0x00000000 }, + { CS35L41_ASP_TX4_SRC, 0x00000000 }, }; static const struct reg_sequence cs35l41_revb2_errata_patch[] = { @@ -666,6 +670,8 @@ static const struct reg_sequence cs35l41_revb2_errata_patch[] = { { CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 }, { CS35L41_PWR_CTRL2, 0x00000000 }, { CS35L41_AMP_GAIN_CTRL, 0x00000000 }, + { CS35L41_ASP_TX3_SRC, 0x00000000 }, + { CS35L41_ASP_TX4_SRC, 0x00000000 }, }; static const struct reg_sequence cs35l41_fs_errata_patch[] = { diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c index 3e68a07a3c8e..71ab2a5d1c55 100644 --- a/sound/soc/codecs/cs35l41.c +++ b/sound/soc/codecs/cs35l41.c @@ -333,7 +333,7 @@ static const struct snd_kcontrol_new cs35l41_aud_controls[] = { SOC_SINGLE("HW Noise Gate Enable", CS35L41_NG_CFG, 8, 63, 0), SOC_SINGLE("HW Noise Gate Delay", CS35L41_NG_CFG, 4, 7, 0), SOC_SINGLE("HW Noise Gate Threshold", CS35L41_NG_CFG, 0, 7, 0), - SOC_SINGLE("Aux Noise Gate CH1 Enable", + SOC_SINGLE("Aux Noise Gate CH1 Switch", CS35L41_MIXER_NGATE_CH1_CFG, 16, 1, 0), SOC_SINGLE("Aux Noise Gate CH1 Entry Delay", CS35L41_MIXER_NGATE_CH1_CFG, 8, 15, 0), @@ -341,15 +341,15 @@ static const struct snd_kcontrol_new cs35l41_aud_controls[] = { CS35L41_MIXER_NGATE_CH1_CFG, 0, 7, 0), SOC_SINGLE("Aux Noise Gate CH2 Entry Delay", CS35L41_MIXER_NGATE_CH2_CFG, 8, 15, 0), - SOC_SINGLE("Aux Noise Gate CH2 Enable", + SOC_SINGLE("Aux Noise Gate CH2 Switch", CS35L41_MIXER_NGATE_CH2_CFG, 16, 1, 0), SOC_SINGLE("Aux Noise Gate CH2 Threshold", CS35L41_MIXER_NGATE_CH2_CFG, 0, 7, 0), - SOC_SINGLE("SCLK Force", CS35L41_SP_FORMAT, CS35L41_SCLK_FRC_SHIFT, 1, 0), - SOC_SINGLE("LRCLK Force", CS35L41_SP_FORMAT, CS35L41_LRCLK_FRC_SHIFT, 1, 0), - SOC_SINGLE("Invert Class D", CS35L41_AMP_DIG_VOL_CTRL, + SOC_SINGLE("SCLK Force Switch", CS35L41_SP_FORMAT, CS35L41_SCLK_FRC_SHIFT, 1, 0), + SOC_SINGLE("LRCLK Force Switch", CS35L41_SP_FORMAT, CS35L41_LRCLK_FRC_SHIFT, 1, 0), + SOC_SINGLE("Invert Class D Switch", CS35L41_AMP_DIG_VOL_CTRL, CS35L41_AMP_INV_PCM_SHIFT, 1, 0), - SOC_SINGLE("Amp Gain ZC", CS35L41_AMP_GAIN_CTRL, + SOC_SINGLE("Amp Gain ZC Switch", CS35L41_AMP_GAIN_CTRL, CS35L41_AMP_GAIN_ZC_SHIFT, 1, 0), WM_ADSP2_PRELOAD_SWITCH("DSP1", 1), WM_ADSP_FW_CONTROL("DSP1", 0), diff --git a/sound/soc/codecs/cs47l15.c b/sound/soc/codecs/cs47l15.c index 391fd7da331f..1c7d52bef893 100644 --- a/sound/soc/codecs/cs47l15.c +++ b/sound/soc/codecs/cs47l15.c @@ -122,6 +122,9 @@ static int cs47l15_in1_adc_put(struct snd_kcontrol *kcontrol, snd_soc_kcontrol_component(kcontrol); struct cs47l15 *cs47l15 = snd_soc_component_get_drvdata(component); + if (!!ucontrol->value.integer.value[0] == cs47l15->in1_lp_mode) + return 0; + switch (ucontrol->value.integer.value[0]) { case 0: /* Set IN1 to normal mode */ @@ -150,7 +153,7 @@ static int cs47l15_in1_adc_put(struct snd_kcontrol *kcontrol, break; } - return 0; + return 1; } static const struct snd_kcontrol_new cs47l15_snd_controls[] = { diff --git a/sound/soc/codecs/madera.c b/sound/soc/codecs/madera.c index 272041c6236a..b9f19fbd2911 100644 --- a/sound/soc/codecs/madera.c +++ b/sound/soc/codecs/madera.c @@ -618,7 +618,13 @@ int madera_out1_demux_put(struct snd_kcontrol *kcontrol, end: snd_soc_dapm_mutex_unlock(dapm); - return snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL); + ret = snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL); + if (ret < 0) { + dev_err(madera->dev, "Failed to update demux power state: %d\n", ret); + return ret; + } + + return change; } EXPORT_SYMBOL_GPL(madera_out1_demux_put); @@ -893,7 +899,7 @@ static int madera_adsp_rate_put(struct snd_kcontrol *kcontrol, struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; const int adsp_num = e->shift_l; const unsigned int item = ucontrol->value.enumerated.item[0]; - int ret; + int ret = 0; if (item >= e->items) return -EINVAL; @@ -910,10 +916,10 @@ static int madera_adsp_rate_put(struct snd_kcontrol *kcontrol, "Cannot change '%s' while in use by active audio paths\n", kcontrol->id.name); ret = -EBUSY; - } else { + } else if (priv->adsp_rate_cache[adsp_num] != e->values[item]) { /* Volatile register so defer until the codec is powered up */ priv->adsp_rate_cache[adsp_num] = e->values[item]; - ret = 0; + ret = 1; } mutex_unlock(&priv->rate_lock); diff --git a/sound/soc/codecs/max98373-sdw.c b/sound/soc/codecs/max98373-sdw.c index f47e956d4f55..97b64477dde6 100644 --- a/sound/soc/codecs/max98373-sdw.c +++ b/sound/soc/codecs/max98373-sdw.c @@ -862,6 +862,16 @@ static int max98373_sdw_probe(struct sdw_slave *slave, return max98373_init(slave, regmap); } +static int max98373_sdw_remove(struct sdw_slave *slave) +{ + struct max98373_priv *max98373 = dev_get_drvdata(&slave->dev); + + if (max98373->first_hw_init) + pm_runtime_disable(&slave->dev); + + return 0; +} + #if defined(CONFIG_OF) static const struct of_device_id max98373_of_match[] = { { .compatible = "maxim,max98373", }, @@ -893,7 +903,7 @@ static struct sdw_driver max98373_sdw_driver = { .pm = &max98373_pm, }, .probe = max98373_sdw_probe, - .remove = NULL, + .remove = max98373_sdw_remove, .ops = &max98373_slave_ops, .id_table = max98373_id, }; diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c index 1c11b42dd76e..72f673f278ee 100644 --- a/sound/soc/codecs/rt1308-sdw.c +++ b/sound/soc/codecs/rt1308-sdw.c @@ -691,6 +691,16 @@ static int rt1308_sdw_probe(struct sdw_slave *slave, return 0; } +static int rt1308_sdw_remove(struct sdw_slave *slave) +{ + struct rt1308_sdw_priv *rt1308 = dev_get_drvdata(&slave->dev); + + if (rt1308->first_hw_init) + pm_runtime_disable(&slave->dev); + + return 0; +} + static const struct sdw_device_id rt1308_id[] = { SDW_SLAVE_ENTRY_EXT(0x025d, 0x1308, 0x2, 0, 0), {}, @@ -750,6 +760,7 @@ static struct sdw_driver rt1308_sdw_driver = { .pm = &rt1308_pm, }, .probe = rt1308_sdw_probe, + .remove = rt1308_sdw_remove, .ops = &rt1308_slave_ops, .id_table = rt1308_id, }; diff --git a/sound/soc/codecs/rt1316-sdw.c b/sound/soc/codecs/rt1316-sdw.c index 60baa9ff1907..2d6b5f9d4d77 100644 --- a/sound/soc/codecs/rt1316-sdw.c +++ b/sound/soc/codecs/rt1316-sdw.c @@ -676,6 +676,16 @@ static int rt1316_sdw_probe(struct sdw_slave *slave, return rt1316_sdw_init(&slave->dev, regmap, slave); } +static int rt1316_sdw_remove(struct sdw_slave *slave) +{ + struct rt1316_sdw_priv *rt1316 = dev_get_drvdata(&slave->dev); + + if (rt1316->first_hw_init) + pm_runtime_disable(&slave->dev); + + return 0; +} + static const struct sdw_device_id rt1316_id[] = { SDW_SLAVE_ENTRY_EXT(0x025d, 0x1316, 0x3, 0x1, 0), {}, @@ -735,6 +745,7 @@ static struct sdw_driver rt1316_sdw_driver = { .pm = &rt1316_pm, }, .probe = rt1316_sdw_probe, + .remove = rt1316_sdw_remove, .ops = &rt1316_slave_ops, .id_table = rt1316_id, }; diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index 248257a2e4e0..f04e18c32489 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -719,9 +719,12 @@ static int rt5682_sdw_remove(struct sdw_slave *slave) { struct rt5682_priv *rt5682 = dev_get_drvdata(&slave->dev); - if (rt5682 && rt5682->hw_init) + if (rt5682->hw_init) cancel_delayed_work_sync(&rt5682->jack_detect_work); + if (rt5682->first_hw_init) + pm_runtime_disable(&slave->dev); + return 0; } diff --git a/sound/soc/codecs/rt700-sdw.c b/sound/soc/codecs/rt700-sdw.c index bda594899664..f7439e40ca8b 100644 --- a/sound/soc/codecs/rt700-sdw.c +++ b/sound/soc/codecs/rt700-sdw.c @@ -13,6 +13,7 @@ #include <linux/soundwire/sdw_type.h> #include <linux/soundwire/sdw_registers.h> #include <linux/module.h> +#include <linux/pm_runtime.h> #include <linux/regmap.h> #include <sound/soc.h> #include "rt700.h" @@ -463,11 +464,14 @@ static int rt700_sdw_remove(struct sdw_slave *slave) { struct rt700_priv *rt700 = dev_get_drvdata(&slave->dev); - if (rt700 && rt700->hw_init) { + if (rt700->hw_init) { cancel_delayed_work_sync(&rt700->jack_detect_work); cancel_delayed_work_sync(&rt700->jack_btn_check_work); } + if (rt700->first_hw_init) + pm_runtime_disable(&slave->dev); + return 0; } diff --git a/sound/soc/codecs/rt700.c b/sound/soc/codecs/rt700.c index af32295fa9b9..9bceeeb830b1 100644 --- a/sound/soc/codecs/rt700.c +++ b/sound/soc/codecs/rt700.c @@ -162,7 +162,7 @@ static void rt700_jack_detect_handler(struct work_struct *work) if (!rt700->hs_jack) return; - if (!rt700->component->card->instantiated) + if (!rt700->component->card || !rt700->component->card->instantiated) return; reg = RT700_VERB_GET_PIN_SENSE | RT700_HP_OUT; @@ -315,17 +315,27 @@ static int rt700_set_jack_detect(struct snd_soc_component *component, struct snd_soc_jack *hs_jack, void *data) { struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component); + int ret; rt700->hs_jack = hs_jack; - if (!rt700->hw_init) { - dev_dbg(&rt700->slave->dev, - "%s hw_init not ready yet\n", __func__); + ret = pm_runtime_resume_and_get(component->dev); + if (ret < 0) { + if (ret != -EACCES) { + dev_err(component->dev, "%s: failed to resume %d\n", __func__, ret); + return ret; + } + + /* pm_runtime not enabled yet */ + dev_dbg(component->dev, "%s: skipping jack init for now\n", __func__); return 0; } rt700_jack_init(rt700); + pm_runtime_mark_last_busy(component->dev); + pm_runtime_put_autosuspend(component->dev); + return 0; } @@ -1115,6 +1125,11 @@ int rt700_init(struct device *dev, struct regmap *sdw_regmap, mutex_init(&rt700->disable_irq_lock); + INIT_DELAYED_WORK(&rt700->jack_detect_work, + rt700_jack_detect_handler); + INIT_DELAYED_WORK(&rt700->jack_btn_check_work, + rt700_btn_check_handler); + /* * Mark hw_init to false * HW init will be performed when device reports present @@ -1209,13 +1224,6 @@ int rt700_io_init(struct device *dev, struct sdw_slave *slave) /* Finish Initial Settings, set power to D3 */ regmap_write(rt700->regmap, RT700_SET_AUDIO_POWER_STATE, AC_PWRST_D3); - if (!rt700->first_hw_init) { - INIT_DELAYED_WORK(&rt700->jack_detect_work, - rt700_jack_detect_handler); - INIT_DELAYED_WORK(&rt700->jack_btn_check_work, - rt700_btn_check_handler); - } - /* * if set_jack callback occurred early than io_init, * we set up the jack detection function now diff --git a/sound/soc/codecs/rt711-sdca-sdw.c b/sound/soc/codecs/rt711-sdca-sdw.c index aaf5af153d3f..a085b2f530aa 100644 --- a/sound/soc/codecs/rt711-sdca-sdw.c +++ b/sound/soc/codecs/rt711-sdca-sdw.c @@ -11,6 +11,7 @@ #include <linux/mod_devicetable.h> #include <linux/soundwire/sdw_registers.h> #include <linux/module.h> +#include <linux/pm_runtime.h> #include "rt711-sdca.h" #include "rt711-sdca-sdw.h" @@ -364,11 +365,17 @@ static int rt711_sdca_sdw_remove(struct sdw_slave *slave) { struct rt711_sdca_priv *rt711 = dev_get_drvdata(&slave->dev); - if (rt711 && rt711->hw_init) { + if (rt711->hw_init) { cancel_delayed_work_sync(&rt711->jack_detect_work); cancel_delayed_work_sync(&rt711->jack_btn_check_work); } + if (rt711->first_hw_init) + pm_runtime_disable(&slave->dev); + + mutex_destroy(&rt711->calibrate_mutex); + mutex_destroy(&rt711->disable_irq_lock); + return 0; } diff --git a/sound/soc/codecs/rt711-sdca.c b/sound/soc/codecs/rt711-sdca.c index 57629c18db38..5ad53bbc8528 100644 --- a/sound/soc/codecs/rt711-sdca.c +++ b/sound/soc/codecs/rt711-sdca.c @@ -34,7 +34,7 @@ static int rt711_sdca_index_write(struct rt711_sdca_priv *rt711, ret = regmap_write(regmap, addr, value); if (ret < 0) - dev_err(rt711->component->dev, + dev_err(&rt711->slave->dev, "Failed to set private value: %06x <= %04x ret=%d\n", addr, value, ret); @@ -50,7 +50,7 @@ static int rt711_sdca_index_read(struct rt711_sdca_priv *rt711, ret = regmap_read(regmap, addr, value); if (ret < 0) - dev_err(rt711->component->dev, + dev_err(&rt711->slave->dev, "Failed to get private value: %06x => %04x ret=%d\n", addr, *value, ret); @@ -294,7 +294,7 @@ static void rt711_sdca_jack_detect_handler(struct work_struct *work) if (!rt711->hs_jack) return; - if (!rt711->component->card->instantiated) + if (!rt711->component->card || !rt711->component->card->instantiated) return; /* SDW_SCP_SDCA_INT_SDCA_0 is used for jack detection */ @@ -487,16 +487,27 @@ static int rt711_sdca_set_jack_detect(struct snd_soc_component *component, struct snd_soc_jack *hs_jack, void *data) { struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); + int ret; rt711->hs_jack = hs_jack; - if (!rt711->hw_init) { - dev_dbg(&rt711->slave->dev, - "%s hw_init not ready yet\n", __func__); + ret = pm_runtime_resume_and_get(component->dev); + if (ret < 0) { + if (ret != -EACCES) { + dev_err(component->dev, "%s: failed to resume %d\n", __func__, ret); + return ret; + } + + /* pm_runtime not enabled yet */ + dev_dbg(component->dev, "%s: skipping jack init for now\n", __func__); return 0; } rt711_sdca_jack_init(rt711); + + pm_runtime_mark_last_busy(component->dev); + pm_runtime_put_autosuspend(component->dev); + return 0; } @@ -1190,14 +1201,6 @@ static int rt711_sdca_probe(struct snd_soc_component *component) return 0; } -static void rt711_sdca_remove(struct snd_soc_component *component) -{ - struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); - - regcache_cache_only(rt711->regmap, true); - regcache_cache_only(rt711->mbq_regmap, true); -} - static const struct snd_soc_component_driver soc_sdca_dev_rt711 = { .probe = rt711_sdca_probe, .controls = rt711_sdca_snd_controls, @@ -1207,7 +1210,6 @@ static const struct snd_soc_component_driver soc_sdca_dev_rt711 = { .dapm_routes = rt711_sdca_audio_map, .num_dapm_routes = ARRAY_SIZE(rt711_sdca_audio_map), .set_jack = rt711_sdca_set_jack_detect, - .remove = rt711_sdca_remove, .endianness = 1, }; @@ -1412,8 +1414,12 @@ int rt711_sdca_init(struct device *dev, struct regmap *regmap, rt711->regmap = regmap; rt711->mbq_regmap = mbq_regmap; + mutex_init(&rt711->calibrate_mutex); mutex_init(&rt711->disable_irq_lock); + INIT_DELAYED_WORK(&rt711->jack_detect_work, rt711_sdca_jack_detect_handler); + INIT_DELAYED_WORK(&rt711->jack_btn_check_work, rt711_sdca_btn_check_handler); + /* * Mark hw_init to false * HW init will be performed when device reports present @@ -1545,14 +1551,6 @@ int rt711_sdca_io_init(struct device *dev, struct sdw_slave *slave) rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, RT711_PUSH_BTN_INT_CTL0, 0x20, 0x00); - if (!rt711->first_hw_init) { - INIT_DELAYED_WORK(&rt711->jack_detect_work, - rt711_sdca_jack_detect_handler); - INIT_DELAYED_WORK(&rt711->jack_btn_check_work, - rt711_sdca_btn_check_handler); - mutex_init(&rt711->calibrate_mutex); - } - /* calibration */ ret = rt711_sdca_calibration(rt711); if (ret < 0) diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c index bda2cc9439c9..4fe68bcf2a7c 100644 --- a/sound/soc/codecs/rt711-sdw.c +++ b/sound/soc/codecs/rt711-sdw.c @@ -13,6 +13,7 @@ #include <linux/soundwire/sdw_type.h> #include <linux/soundwire/sdw_registers.h> #include <linux/module.h> +#include <linux/pm_runtime.h> #include <linux/regmap.h> #include <sound/soc.h> #include "rt711.h" @@ -464,12 +465,18 @@ static int rt711_sdw_remove(struct sdw_slave *slave) { struct rt711_priv *rt711 = dev_get_drvdata(&slave->dev); - if (rt711 && rt711->hw_init) { + if (rt711->hw_init) { cancel_delayed_work_sync(&rt711->jack_detect_work); cancel_delayed_work_sync(&rt711->jack_btn_check_work); cancel_work_sync(&rt711->calibration_work); } + if (rt711->first_hw_init) + pm_runtime_disable(&slave->dev); + + mutex_destroy(&rt711->calibrate_mutex); + mutex_destroy(&rt711->disable_irq_lock); + return 0; } diff --git a/sound/soc/codecs/rt711.c b/sound/soc/codecs/rt711.c index 9838fb4d5b9c..9df800abfc2d 100644 --- a/sound/soc/codecs/rt711.c +++ b/sound/soc/codecs/rt711.c @@ -242,7 +242,7 @@ static void rt711_jack_detect_handler(struct work_struct *work) if (!rt711->hs_jack) return; - if (!rt711->component->card->instantiated) + if (!rt711->component->card || !rt711->component->card->instantiated) return; if (pm_runtime_status_suspended(rt711->slave->dev.parent)) { @@ -457,17 +457,27 @@ static int rt711_set_jack_detect(struct snd_soc_component *component, struct snd_soc_jack *hs_jack, void *data) { struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component); + int ret; rt711->hs_jack = hs_jack; - if (!rt711->hw_init) { - dev_dbg(&rt711->slave->dev, - "%s hw_init not ready yet\n", __func__); + ret = pm_runtime_resume_and_get(component->dev); + if (ret < 0) { + if (ret != -EACCES) { + dev_err(component->dev, "%s: failed to resume %d\n", __func__, ret); + return ret; + } + + /* pm_runtime not enabled yet */ + dev_dbg(component->dev, "%s: skipping jack init for now\n", __func__); return 0; } rt711_jack_init(rt711); + pm_runtime_mark_last_busy(component->dev); + pm_runtime_put_autosuspend(component->dev); + return 0; } @@ -932,13 +942,6 @@ static int rt711_probe(struct snd_soc_component *component) return 0; } -static void rt711_remove(struct snd_soc_component *component) -{ - struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component); - - regcache_cache_only(rt711->regmap, true); -} - static const struct snd_soc_component_driver soc_codec_dev_rt711 = { .probe = rt711_probe, .set_bias_level = rt711_set_bias_level, @@ -949,7 +952,6 @@ static const struct snd_soc_component_driver soc_codec_dev_rt711 = { .dapm_routes = rt711_audio_map, .num_dapm_routes = ARRAY_SIZE(rt711_audio_map), .set_jack = rt711_set_jack_detect, - .remove = rt711_remove, .endianness = 1, }; @@ -1204,8 +1206,13 @@ int rt711_init(struct device *dev, struct regmap *sdw_regmap, rt711->sdw_regmap = sdw_regmap; rt711->regmap = regmap; + mutex_init(&rt711->calibrate_mutex); mutex_init(&rt711->disable_irq_lock); + INIT_DELAYED_WORK(&rt711->jack_detect_work, rt711_jack_detect_handler); + INIT_DELAYED_WORK(&rt711->jack_btn_check_work, rt711_btn_check_handler); + INIT_WORK(&rt711->calibration_work, rt711_calibration_work); + /* * Mark hw_init to false * HW init will be performed when device reports present @@ -1313,15 +1320,8 @@ int rt711_io_init(struct device *dev, struct sdw_slave *slave) if (rt711->first_hw_init) rt711_calibration(rt711); - else { - INIT_DELAYED_WORK(&rt711->jack_detect_work, - rt711_jack_detect_handler); - INIT_DELAYED_WORK(&rt711->jack_btn_check_work, - rt711_btn_check_handler); - mutex_init(&rt711->calibrate_mutex); - INIT_WORK(&rt711->calibration_work, rt711_calibration_work); + else schedule_work(&rt711->calibration_work); - } /* * if set_jack callback occurred early than io_init, diff --git a/sound/soc/codecs/rt715-sdca-sdw.c b/sound/soc/codecs/rt715-sdca-sdw.c index 0ecd2948f7aa..13e731d16675 100644 --- a/sound/soc/codecs/rt715-sdca-sdw.c +++ b/sound/soc/codecs/rt715-sdca-sdw.c @@ -13,6 +13,7 @@ #include <linux/soundwire/sdw_type.h> #include <linux/soundwire/sdw_registers.h> #include <linux/module.h> +#include <linux/pm_runtime.h> #include <linux/regmap.h> #include <sound/soc.h> #include "rt715-sdca.h" @@ -193,6 +194,16 @@ static int rt715_sdca_sdw_probe(struct sdw_slave *slave, return rt715_sdca_init(&slave->dev, mbq_regmap, regmap, slave); } +static int rt715_sdca_sdw_remove(struct sdw_slave *slave) +{ + struct rt715_sdca_priv *rt715 = dev_get_drvdata(&slave->dev); + + if (rt715->first_hw_init) + pm_runtime_disable(&slave->dev); + + return 0; +} + static const struct sdw_device_id rt715_sdca_id[] = { SDW_SLAVE_ENTRY_EXT(0x025d, 0x715, 0x3, 0x1, 0), SDW_SLAVE_ENTRY_EXT(0x025d, 0x714, 0x3, 0x1, 0), @@ -267,6 +278,7 @@ static struct sdw_driver rt715_sdw_driver = { .pm = &rt715_pm, }, .probe = rt715_sdca_sdw_probe, + .remove = rt715_sdca_sdw_remove, .ops = &rt715_sdca_slave_ops, .id_table = rt715_sdca_id, }; diff --git a/sound/soc/codecs/rt715-sdw.c b/sound/soc/codecs/rt715-sdw.c index a7b21b03c08b..b047bf87a100 100644 --- a/sound/soc/codecs/rt715-sdw.c +++ b/sound/soc/codecs/rt715-sdw.c @@ -14,6 +14,7 @@ #include <linux/soundwire/sdw_type.h> #include <linux/soundwire/sdw_registers.h> #include <linux/module.h> +#include <linux/pm_runtime.h> #include <linux/of.h> #include <linux/regmap.h> #include <sound/soc.h> @@ -514,6 +515,16 @@ static int rt715_sdw_probe(struct sdw_slave *slave, return 0; } +static int rt715_sdw_remove(struct sdw_slave *slave) +{ + struct rt715_priv *rt715 = dev_get_drvdata(&slave->dev); + + if (rt715->first_hw_init) + pm_runtime_disable(&slave->dev); + + return 0; +} + static const struct sdw_device_id rt715_id[] = { SDW_SLAVE_ENTRY_EXT(0x025d, 0x714, 0x2, 0, 0), SDW_SLAVE_ENTRY_EXT(0x025d, 0x715, 0x2, 0, 0), @@ -575,6 +586,7 @@ static struct sdw_driver rt715_sdw_driver = { .pm = &rt715_pm, }, .probe = rt715_sdw_probe, + .remove = rt715_sdw_remove, .ops = &rt715_slave_ops, .id_table = rt715_id, }; diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index 617a36a89dfe..d9f135200688 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -1287,11 +1287,17 @@ static int slim_rx_mux_put(struct snd_kcontrol *kc, struct snd_soc_dapm_update *update = NULL; u32 port_id = w->shift; + if (wcd->rx_port_value[port_id] == ucontrol->value.enumerated.item[0]) + return 0; + wcd->rx_port_value[port_id] = ucontrol->value.enumerated.item[0]; + /* Remove channel from any list it's in before adding it to a new one */ + list_del_init(&wcd->rx_chs[port_id].list); + switch (wcd->rx_port_value[port_id]) { case 0: - list_del_init(&wcd->rx_chs[port_id].list); + /* Channel already removed from lists. Nothing to do here */ break; case 1: list_add_tail(&wcd->rx_chs[port_id].list, diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c index c1b61b997f69..781ae569be29 100644 --- a/sound/soc/codecs/wcd938x.c +++ b/sound/soc/codecs/wcd938x.c @@ -2519,6 +2519,9 @@ static int wcd938x_tx_mode_put(struct snd_kcontrol *kcontrol, struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; int path = e->shift_l; + if (wcd938x->tx_mode[path] == ucontrol->value.enumerated.item[0]) + return 0; + wcd938x->tx_mode[path] = ucontrol->value.enumerated.item[0]; return 1; @@ -2541,6 +2544,9 @@ static int wcd938x_rx_hph_mode_put(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + if (wcd938x->hph_mode == ucontrol->value.enumerated.item[0]) + return 0; + wcd938x->hph_mode = ucontrol->value.enumerated.item[0]; return 1; @@ -2632,6 +2638,9 @@ static int wcd938x_ldoh_put(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + if (wcd938x->ldoh == ucontrol->value.integer.value[0]) + return 0; + wcd938x->ldoh = ucontrol->value.integer.value[0]; return 1; @@ -2654,6 +2663,9 @@ static int wcd938x_bcs_put(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + if (wcd938x->bcs_dis == ucontrol->value.integer.value[0]) + return 0; + wcd938x->bcs_dis = ucontrol->value.integer.value[0]; return 1; diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 4973ba1ed779..4ab7a672f8de 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -413,6 +413,7 @@ static int wm5110_put_dre(struct snd_kcontrol *kcontrol, unsigned int rnew = (!!ucontrol->value.integer.value[1]) << mc->rshift; unsigned int lold, rold; unsigned int lena, rena; + bool change = false; int ret; snd_soc_dapm_mutex_lock(dapm); @@ -440,8 +441,8 @@ static int wm5110_put_dre(struct snd_kcontrol *kcontrol, goto err; } - ret = regmap_update_bits(arizona->regmap, ARIZONA_DRE_ENABLE, - mask, lnew | rnew); + ret = regmap_update_bits_check(arizona->regmap, ARIZONA_DRE_ENABLE, + mask, lnew | rnew, &change); if (ret) { dev_err(arizona->dev, "Failed to set DRE: %d\n", ret); goto err; @@ -454,6 +455,9 @@ static int wm5110_put_dre(struct snd_kcontrol *kcontrol, if (!rnew && rold) wm5110_clear_pga_volume(arizona, mc->rshift); + if (change) + ret = 1; + err: snd_soc_dapm_mutex_unlock(dapm); diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 6d7fd88243aa..a7784ac15dde 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -997,7 +997,7 @@ int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol, snd_soc_dapm_sync(dapm); } - return 0; + return 1; } EXPORT_SYMBOL_GPL(wm_adsp2_preloader_put); diff --git a/sound/soc/intel/avs/topology.c b/sound/soc/intel/avs/topology.c index 0d11cc8aab0b..6a06fe387d13 100644 --- a/sound/soc/intel/avs/topology.c +++ b/sound/soc/intel/avs/topology.c @@ -128,10 +128,10 @@ struct avs_tplg_token_parser { static int avs_parse_uuid_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset) { - struct snd_soc_tplg_vendor_value_elem *tuple = elem; + struct snd_soc_tplg_vendor_uuid_elem *tuple = elem; guid_t *val = (guid_t *)((u8 *)object + offset); - guid_copy((guid_t *)val, (const guid_t *)&tuple->value); + guid_copy((guid_t *)val, (const guid_t *)&tuple->uuid); return 0; } diff --git a/sound/soc/intel/boards/bytcr_wm5102.c b/sound/soc/intel/boards/bytcr_wm5102.c index 00384c6fbcaa..330c0ace1638 100644 --- a/sound/soc/intel/boards/bytcr_wm5102.c +++ b/sound/soc/intel/boards/bytcr_wm5102.c @@ -421,8 +421,17 @@ static int snd_byt_wm5102_mc_probe(struct platform_device *pdev) priv->spkvdd_en_gpio = gpiod_get(codec_dev, "wlf,spkvdd-ena", GPIOD_OUT_LOW); put_device(codec_dev); - if (IS_ERR(priv->spkvdd_en_gpio)) - return dev_err_probe(dev, PTR_ERR(priv->spkvdd_en_gpio), "getting spkvdd-GPIO\n"); + if (IS_ERR(priv->spkvdd_en_gpio)) { + ret = PTR_ERR(priv->spkvdd_en_gpio); + /* + * The spkvdd gpio-lookup is registered by: drivers/mfd/arizona-spi.c, + * so -ENOENT means that arizona-spi hasn't probed yet. + */ + if (ret == -ENOENT) + ret = -EPROBE_DEFER; + + return dev_err_probe(dev, ret, "getting spkvdd-GPIO\n"); + } /* override platform name, if required */ byt_wm5102_card.dev = dev; diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 1f00679b4240..ad826ad82d51 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1398,6 +1398,33 @@ static struct snd_soc_card card_sof_sdw = { .late_probe = sof_sdw_card_late_probe, }; +static void mc_dailink_exit_loop(struct snd_soc_card *card) +{ + struct snd_soc_dai_link *link; + int ret; + int i, j; + + for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { + if (!codec_info_list[i].exit) + continue; + /* + * We don't need to call .exit function if there is no matched + * dai link found. + */ + for_each_card_prelinks(card, j, link) { + if (!strcmp(link->codecs[0].dai_name, + codec_info_list[i].dai_name)) { + ret = codec_info_list[i].exit(card, link); + if (ret) + dev_warn(card->dev, + "codec exit failed %d\n", + ret); + break; + } + } + } +} + static int mc_probe(struct platform_device *pdev) { struct snd_soc_card *card = &card_sof_sdw; @@ -1462,6 +1489,7 @@ static int mc_probe(struct platform_device *pdev) ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret) { dev_err(card->dev, "snd_soc_register_card failed %d\n", ret); + mc_dailink_exit_loop(card); return ret; } @@ -1473,29 +1501,8 @@ static int mc_probe(struct platform_device *pdev) static int mc_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); - struct snd_soc_dai_link *link; - int ret; - int i, j; - for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { - if (!codec_info_list[i].exit) - continue; - /* - * We don't need to call .exit function if there is no matched - * dai link found. - */ - for_each_card_prelinks(card, j, link) { - if (!strcmp(link->codecs[0].dai_name, - codec_info_list[i].dai_name)) { - ret = codec_info_list[i].exit(card, link); - if (ret) - dev_warn(&pdev->dev, - "codec exit failed %d\n", - ret); - break; - } - } - } + mc_dailink_exit_loop(card); return 0; } diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index 8ee2dea25a8d..4489d2c8b124 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -21,8 +21,7 @@ #include <sound/soc.h> #include <asm/mach-types.h> -#include <mach/corgi.h> -#include <mach/audio.h> +#include <linux/platform_data/asoc-pxa.h> #include "../codecs/wm8731.h" #include "pxa2xx-i2s.h" @@ -41,6 +40,9 @@ static int corgi_jack_func; static int corgi_spk_func; +static struct gpio_desc *gpiod_mute_l, *gpiod_mute_r, + *gpiod_apm_on, *gpiod_mic_bias; + static void corgi_ext_control(struct snd_soc_dapm_context *dapm) { snd_soc_dapm_mutex_lock(dapm); @@ -49,8 +51,8 @@ static void corgi_ext_control(struct snd_soc_dapm_context *dapm) switch (corgi_jack_func) { case CORGI_HP: /* set = unmute headphone */ - gpio_set_value(CORGI_GPIO_MUTE_L, 1); - gpio_set_value(CORGI_GPIO_MUTE_R, 1); + gpiod_set_value(gpiod_mute_l, 1); + gpiod_set_value(gpiod_mute_r, 1); snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); @@ -58,24 +60,24 @@ static void corgi_ext_control(struct snd_soc_dapm_context *dapm) break; case CORGI_MIC: /* reset = mute headphone */ - gpio_set_value(CORGI_GPIO_MUTE_L, 0); - gpio_set_value(CORGI_GPIO_MUTE_R, 0); + gpiod_set_value(gpiod_mute_l, 0); + gpiod_set_value(gpiod_mute_r, 0); snd_soc_dapm_enable_pin_unlocked(dapm, "Mic Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); break; case CORGI_LINE: - gpio_set_value(CORGI_GPIO_MUTE_L, 0); - gpio_set_value(CORGI_GPIO_MUTE_R, 0); + gpiod_set_value(gpiod_mute_l, 0); + gpiod_set_value(gpiod_mute_r, 0); snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack"); snd_soc_dapm_enable_pin_unlocked(dapm, "Line Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); break; case CORGI_HEADSET: - gpio_set_value(CORGI_GPIO_MUTE_L, 0); - gpio_set_value(CORGI_GPIO_MUTE_R, 1); + gpiod_set_value(gpiod_mute_l, 0); + gpiod_set_value(gpiod_mute_r, 1); snd_soc_dapm_enable_pin_unlocked(dapm, "Mic Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Headphone Jack"); @@ -108,8 +110,8 @@ static int corgi_startup(struct snd_pcm_substream *substream) static void corgi_shutdown(struct snd_pcm_substream *substream) { /* set = unmute headphone */ - gpio_set_value(CORGI_GPIO_MUTE_L, 1); - gpio_set_value(CORGI_GPIO_MUTE_R, 1); + gpiod_set_value(gpiod_mute_l, 1); + gpiod_set_value(gpiod_mute_r, 1); } static int corgi_hw_params(struct snd_pcm_substream *substream, @@ -199,14 +201,14 @@ static int corgi_set_spk(struct snd_kcontrol *kcontrol, static int corgi_amp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { - gpio_set_value(CORGI_GPIO_APM_ON, SND_SOC_DAPM_EVENT_ON(event)); + gpiod_set_value(gpiod_apm_on, SND_SOC_DAPM_EVENT_ON(event)); return 0; } static int corgi_mic_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { - gpio_set_value(CORGI_GPIO_MIC_BIAS, SND_SOC_DAPM_EVENT_ON(event)); + gpiod_set_value(gpiod_mic_bias, SND_SOC_DAPM_EVENT_ON(event)); return 0; } @@ -293,6 +295,19 @@ static int corgi_probe(struct platform_device *pdev) card->dev = &pdev->dev; + gpiod_mute_l = devm_gpiod_get(&pdev->dev, "mute-l", GPIOD_OUT_HIGH); + if (IS_ERR(gpiod_mute_l)) + return PTR_ERR(gpiod_mute_l); + gpiod_mute_r = devm_gpiod_get(&pdev->dev, "mute-r", GPIOD_OUT_HIGH); + if (IS_ERR(gpiod_mute_r)) + return PTR_ERR(gpiod_mute_r); + gpiod_apm_on = devm_gpiod_get(&pdev->dev, "apm-on", GPIOD_OUT_LOW); + if (IS_ERR(gpiod_apm_on)) + return PTR_ERR(gpiod_apm_on); + gpiod_mic_bias = devm_gpiod_get(&pdev->dev, "mic-bias", GPIOD_OUT_LOW); + if (IS_ERR(gpiod_mic_bias)) + return PTR_ERR(gpiod_mic_bias); + ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret) dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c index eafa1482afbe..4e0e9b778d4c 100644 --- a/sound/soc/pxa/e740_wm9705.c +++ b/sound/soc/pxa/e740_wm9705.c @@ -7,17 +7,19 @@ #include <linux/module.h> #include <linux/moduleparam.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/soc.h> -#include <mach/audio.h> -#include <mach/eseries-gpio.h> +#include <linux/platform_data/asoc-pxa.h> #include <asm/mach-types.h> +static struct gpio_desc *gpiod_output_amp, *gpiod_input_amp; +static struct gpio_desc *gpiod_audio_power; + #define E740_AUDIO_OUT 1 #define E740_AUDIO_IN 2 @@ -25,9 +27,9 @@ static int e740_audio_power; static void e740_sync_audio_power(int status) { - gpio_set_value(GPIO_E740_WM9705_nAVDD2, !status); - gpio_set_value(GPIO_E740_AMP_ON, (status & E740_AUDIO_OUT) ? 1 : 0); - gpio_set_value(GPIO_E740_MIC_ON, (status & E740_AUDIO_IN) ? 1 : 0); + gpiod_set_value(gpiod_audio_power, !status); + gpiod_set_value(gpiod_output_amp, (status & E740_AUDIO_OUT) ? 1 : 0); + gpiod_set_value(gpiod_input_amp, (status & E740_AUDIO_IN) ? 1 : 0); } static int e740_mic_amp_event(struct snd_soc_dapm_widget *w, @@ -116,36 +118,35 @@ static struct snd_soc_card e740 = { .fully_routed = true, }; -static struct gpio e740_audio_gpios[] = { - { GPIO_E740_MIC_ON, GPIOF_OUT_INIT_LOW, "Mic amp" }, - { GPIO_E740_AMP_ON, GPIOF_OUT_INIT_LOW, "Output amp" }, - { GPIO_E740_WM9705_nAVDD2, GPIOF_OUT_INIT_HIGH, "Audio power" }, -}; - static int e740_probe(struct platform_device *pdev) { struct snd_soc_card *card = &e740; int ret; - ret = gpio_request_array(e740_audio_gpios, - ARRAY_SIZE(e740_audio_gpios)); + gpiod_input_amp = devm_gpiod_get(&pdev->dev, "Mic amp", GPIOD_OUT_LOW); + ret = PTR_ERR_OR_ZERO(gpiod_input_amp); + if (ret) + return ret; + gpiod_output_amp = devm_gpiod_get(&pdev->dev, "Output amp", GPIOD_OUT_LOW); + ret = PTR_ERR_OR_ZERO(gpiod_output_amp); + if (ret) + return ret; + gpiod_audio_power = devm_gpiod_get(&pdev->dev, "Audio power", GPIOD_OUT_HIGH); + ret = PTR_ERR_OR_ZERO(gpiod_audio_power); if (ret) return ret; card->dev = &pdev->dev; ret = devm_snd_soc_register_card(&pdev->dev, card); - if (ret) { + if (ret) dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); - gpio_free_array(e740_audio_gpios, ARRAY_SIZE(e740_audio_gpios)); - } return ret; } static int e740_remove(struct platform_device *pdev) { - gpio_free_array(e740_audio_gpios, ARRAY_SIZE(e740_audio_gpios)); return 0; } diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c index d75510d7b16b..7a1e0d8bfd11 100644 --- a/sound/soc/pxa/e750_wm9705.c +++ b/sound/soc/pxa/e750_wm9705.c @@ -7,24 +7,25 @@ #include <linux/module.h> #include <linux/moduleparam.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/soc.h> -#include <mach/audio.h> -#include <mach/eseries-gpio.h> +#include <linux/platform_data/asoc-pxa.h> #include <asm/mach-types.h> +static struct gpio_desc *gpiod_spk_amp, *gpiod_hp_amp; + static int e750_spk_amp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { if (event & SND_SOC_DAPM_PRE_PMU) - gpio_set_value(GPIO_E750_SPK_AMP_OFF, 0); + gpiod_set_value(gpiod_spk_amp, 1); else if (event & SND_SOC_DAPM_POST_PMD) - gpio_set_value(GPIO_E750_SPK_AMP_OFF, 1); + gpiod_set_value(gpiod_spk_amp, 0); return 0; } @@ -33,9 +34,9 @@ static int e750_hp_amp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { if (event & SND_SOC_DAPM_PRE_PMU) - gpio_set_value(GPIO_E750_HP_AMP_OFF, 0); + gpiod_set_value(gpiod_hp_amp, 1); else if (event & SND_SOC_DAPM_POST_PMD) - gpio_set_value(GPIO_E750_HP_AMP_OFF, 1); + gpiod_set_value(gpiod_hp_amp, 0); return 0; } @@ -100,35 +101,31 @@ static struct snd_soc_card e750 = { .fully_routed = true, }; -static struct gpio e750_audio_gpios[] = { - { GPIO_E750_HP_AMP_OFF, GPIOF_OUT_INIT_HIGH, "Headphone amp" }, - { GPIO_E750_SPK_AMP_OFF, GPIOF_OUT_INIT_HIGH, "Speaker amp" }, -}; - static int e750_probe(struct platform_device *pdev) { struct snd_soc_card *card = &e750; int ret; - ret = gpio_request_array(e750_audio_gpios, - ARRAY_SIZE(e750_audio_gpios)); + gpiod_hp_amp = devm_gpiod_get(&pdev->dev, "Headphone amp", GPIOD_OUT_LOW); + ret = PTR_ERR_OR_ZERO(gpiod_hp_amp); + if (ret) + return ret; + gpiod_spk_amp = devm_gpiod_get(&pdev->dev, "Speaker amp", GPIOD_OUT_LOW); + ret = PTR_ERR_OR_ZERO(gpiod_spk_amp); if (ret) return ret; card->dev = &pdev->dev; ret = devm_snd_soc_register_card(&pdev->dev, card); - if (ret) { + if (ret) dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); - gpio_free_array(e750_audio_gpios, ARRAY_SIZE(e750_audio_gpios)); - } return ret; } static int e750_remove(struct platform_device *pdev) { - gpio_free_array(e750_audio_gpios, ARRAY_SIZE(e750_audio_gpios)); return 0; } diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c index 56d543da938a..a39c494127cf 100644 --- a/sound/soc/pxa/e800_wm9712.c +++ b/sound/soc/pxa/e800_wm9712.c @@ -7,23 +7,24 @@ #include <linux/module.h> #include <linux/moduleparam.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/soc.h> #include <asm/mach-types.h> -#include <mach/audio.h> -#include <mach/eseries-gpio.h> +#include <linux/platform_data/asoc-pxa.h> + +static struct gpio_desc *gpiod_spk_amp, *gpiod_hp_amp; static int e800_spk_amp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { if (event & SND_SOC_DAPM_PRE_PMU) - gpio_set_value(GPIO_E800_SPK_AMP_ON, 1); + gpiod_set_value(gpiod_spk_amp, 1); else if (event & SND_SOC_DAPM_POST_PMD) - gpio_set_value(GPIO_E800_SPK_AMP_ON, 0); + gpiod_set_value(gpiod_spk_amp, 0); return 0; } @@ -32,9 +33,9 @@ static int e800_hp_amp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { if (event & SND_SOC_DAPM_PRE_PMU) - gpio_set_value(GPIO_E800_HP_AMP_OFF, 0); + gpiod_set_value(gpiod_hp_amp, 1); else if (event & SND_SOC_DAPM_POST_PMD) - gpio_set_value(GPIO_E800_HP_AMP_OFF, 1); + gpiod_set_value(gpiod_hp_amp, 0); return 0; } @@ -100,35 +101,31 @@ static struct snd_soc_card e800 = { .num_dapm_routes = ARRAY_SIZE(audio_map), }; -static struct gpio e800_audio_gpios[] = { - { GPIO_E800_SPK_AMP_ON, GPIOF_OUT_INIT_HIGH, "Headphone amp" }, - { GPIO_E800_HP_AMP_OFF, GPIOF_OUT_INIT_HIGH, "Speaker amp" }, -}; - static int e800_probe(struct platform_device *pdev) { struct snd_soc_card *card = &e800; int ret; - ret = gpio_request_array(e800_audio_gpios, - ARRAY_SIZE(e800_audio_gpios)); + gpiod_hp_amp = devm_gpiod_get(&pdev->dev, "Headphone amp", GPIOD_OUT_LOW); + ret = PTR_ERR_OR_ZERO(gpiod_hp_amp); + if (ret) + return ret; + gpiod_spk_amp = devm_gpiod_get(&pdev->dev, "Speaker amp", GPIOD_OUT_LOW); + ret = PTR_ERR_OR_ZERO(gpiod_spk_amp); if (ret) return ret; card->dev = &pdev->dev; ret = devm_snd_soc_register_card(&pdev->dev, card); - if (ret) { + if (ret) dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); - gpio_free_array(e800_audio_gpios, ARRAY_SIZE(e800_audio_gpios)); - } return ret; } static int e800_remove(struct platform_device *pdev) { - gpio_free_array(e800_audio_gpios, ARRAY_SIZE(e800_audio_gpios)); return 0; } diff --git a/sound/soc/pxa/em-x270.c b/sound/soc/pxa/em-x270.c index 9076ea7e9339..b59ec22e1e7e 100644 --- a/sound/soc/pxa/em-x270.c +++ b/sound/soc/pxa/em-x270.c @@ -23,7 +23,7 @@ #include <sound/soc.h> #include <asm/mach-types.h> -#include <mach/audio.h> +#include <linux/platform_data/asoc-pxa.h> SND_SOC_DAILINK_DEFS(ac97, DAILINK_COMP_ARRAY(COMP_CPU("pxa2xx-ac97")), diff --git a/sound/soc/pxa/hx4700.c b/sound/soc/pxa/hx4700.c index 9a816156f012..a323ddb8fc3e 100644 --- a/sound/soc/pxa/hx4700.c +++ b/sound/soc/pxa/hx4700.c @@ -10,7 +10,7 @@ #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/delay.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <sound/core.h> #include <sound/jack.h> @@ -18,10 +18,10 @@ #include <sound/pcm_params.h> #include <sound/soc.h> -#include <mach/hx4700.h> #include <asm/mach-types.h> #include "pxa2xx-i2s.h" +static struct gpio_desc *gpiod_hp_driver, *gpiod_spk_sd; static struct snd_soc_jack hs_jack; /* Headphones jack detection DAPM pin */ @@ -29,20 +29,18 @@ static struct snd_soc_jack_pin hs_jack_pin[] = { { .pin = "Headphone Jack", .mask = SND_JACK_HEADPHONE, + .invert = 1, }, { .pin = "Speaker", /* disable speaker when hp jack is inserted */ .mask = SND_JACK_HEADPHONE, - .invert = 1, }, }; /* Headphones jack detection GPIO */ static struct snd_soc_jack_gpio hs_jack_gpio = { - .gpio = GPIO75_HX4700_EARPHONE_nDET, - .invert = true, - .name = "hp-gpio", + .name = "earphone-det", .report = SND_JACK_HEADPHONE, .debounce_time = 200, }; @@ -81,14 +79,14 @@ static const struct snd_soc_ops hx4700_ops = { static int hx4700_spk_power(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { - gpio_set_value(GPIO107_HX4700_SPK_nSD, !!SND_SOC_DAPM_EVENT_ON(event)); + gpiod_set_value(gpiod_spk_sd, !SND_SOC_DAPM_EVENT_ON(event)); return 0; } static int hx4700_hp_power(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { - gpio_set_value(GPIO92_HX4700_HP_DRIVER, !!SND_SOC_DAPM_EVENT_ON(event)); + gpiod_set_value(gpiod_hp_driver, !!SND_SOC_DAPM_EVENT_ON(event)); return 0; } @@ -162,11 +160,6 @@ static struct snd_soc_card snd_soc_card_hx4700 = { .fully_routed = true, }; -static struct gpio hx4700_audio_gpios[] = { - { GPIO107_HX4700_SPK_nSD, GPIOF_OUT_INIT_HIGH, "SPK_POWER" }, - { GPIO92_HX4700_HP_DRIVER, GPIOF_OUT_INIT_LOW, "EP_POWER" }, -}; - static int hx4700_audio_probe(struct platform_device *pdev) { int ret; @@ -174,26 +167,26 @@ static int hx4700_audio_probe(struct platform_device *pdev) if (!machine_is_h4700()) return -ENODEV; - ret = gpio_request_array(hx4700_audio_gpios, - ARRAY_SIZE(hx4700_audio_gpios)); + gpiod_hp_driver = devm_gpiod_get(&pdev->dev, "hp-driver", GPIOD_ASIS); + ret = PTR_ERR_OR_ZERO(gpiod_hp_driver); + if (ret) + return ret; + gpiod_spk_sd = devm_gpiod_get(&pdev->dev, "spk-sd", GPIOD_ASIS); + ret = PTR_ERR_OR_ZERO(gpiod_spk_sd); if (ret) return ret; + hs_jack_gpio.gpiod_dev = &pdev->dev; snd_soc_card_hx4700.dev = &pdev->dev; ret = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_hx4700); - if (ret) - gpio_free_array(hx4700_audio_gpios, - ARRAY_SIZE(hx4700_audio_gpios)); return ret; } static int hx4700_audio_remove(struct platform_device *pdev) { - gpio_set_value(GPIO92_HX4700_HP_DRIVER, 0); - gpio_set_value(GPIO107_HX4700_SPK_nSD, 0); - - gpio_free_array(hx4700_audio_gpios, ARRAY_SIZE(hx4700_audio_gpios)); + gpiod_set_value(gpiod_hp_driver, 0); + gpiod_set_value(gpiod_spk_sd, 0); return 0; } diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c index a5f326c97af2..9433cc927755 100644 --- a/sound/soc/pxa/magician.c +++ b/sound/soc/pxa/magician.c @@ -14,16 +14,14 @@ #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/delay.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> #include <sound/soc.h> -#include <sound/uda1380.h> -#include <mach/magician.h> #include <asm/mach-types.h> #include "../codecs/uda1380.h" #include "pxa2xx-i2s.h" @@ -36,6 +34,9 @@ static int magician_hp_switch; static int magician_spk_switch = 1; static int magician_in_sel = MAGICIAN_MIC; +static struct gpio_desc *gpiod_spk_power, *gpiod_ep_power, *gpiod_mic_power; +static struct gpio_desc *gpiod_in_sel0, *gpiod_in_sel1; + static void magician_ext_control(struct snd_soc_dapm_context *dapm) { @@ -215,10 +216,10 @@ static int magician_set_input(struct snd_kcontrol *kcontrol, switch (magician_in_sel) { case MAGICIAN_MIC: - gpio_set_value(EGPIO_MAGICIAN_IN_SEL1, 1); + gpiod_set_value(gpiod_in_sel1, 1); break; case MAGICIAN_MIC_EXT: - gpio_set_value(EGPIO_MAGICIAN_IN_SEL1, 0); + gpiod_set_value(gpiod_in_sel1, 0); } return 1; @@ -227,21 +228,21 @@ static int magician_set_input(struct snd_kcontrol *kcontrol, static int magician_spk_power(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { - gpio_set_value(EGPIO_MAGICIAN_SPK_POWER, SND_SOC_DAPM_EVENT_ON(event)); + gpiod_set_value(gpiod_spk_power, SND_SOC_DAPM_EVENT_ON(event)); return 0; } static int magician_hp_power(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { - gpio_set_value(EGPIO_MAGICIAN_EP_POWER, SND_SOC_DAPM_EVENT_ON(event)); + gpiod_set_value(gpiod_ep_power, SND_SOC_DAPM_EVENT_ON(event)); return 0; } static int magician_mic_bias(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { - gpio_set_value(EGPIO_MAGICIAN_MIC_POWER, SND_SOC_DAPM_EVENT_ON(event)); + gpiod_set_value(gpiod_mic_power, SND_SOC_DAPM_EVENT_ON(event)); return 0; } @@ -328,106 +329,38 @@ static struct snd_soc_card snd_soc_card_magician = { .fully_routed = true, }; -static struct platform_device *magician_snd_device; - -/* - * FIXME: move into magician board file once merged into the pxa tree - */ -static struct uda1380_platform_data uda1380_info = { - .gpio_power = EGPIO_MAGICIAN_CODEC_POWER, - .gpio_reset = EGPIO_MAGICIAN_CODEC_RESET, - .dac_clk = UDA1380_DAC_CLK_WSPLL, -}; - -static struct i2c_board_info i2c_board_info[] = { - { - I2C_BOARD_INFO("uda1380", 0x18), - .platform_data = &uda1380_info, - }, -}; - -static int __init magician_init(void) -{ - int ret; - struct i2c_adapter *adapter; - struct i2c_client *client; - - if (!machine_is_magician()) - return -ENODEV; - - adapter = i2c_get_adapter(0); - if (!adapter) - return -ENODEV; - client = i2c_new_client_device(adapter, i2c_board_info); - i2c_put_adapter(adapter); - if (IS_ERR(client)) - return PTR_ERR(client); - - ret = gpio_request(EGPIO_MAGICIAN_SPK_POWER, "SPK_POWER"); - if (ret) - goto err_request_spk; - ret = gpio_request(EGPIO_MAGICIAN_EP_POWER, "EP_POWER"); - if (ret) - goto err_request_ep; - ret = gpio_request(EGPIO_MAGICIAN_MIC_POWER, "MIC_POWER"); - if (ret) - goto err_request_mic; - ret = gpio_request(EGPIO_MAGICIAN_IN_SEL0, "IN_SEL0"); - if (ret) - goto err_request_in_sel0; - ret = gpio_request(EGPIO_MAGICIAN_IN_SEL1, "IN_SEL1"); - if (ret) - goto err_request_in_sel1; - - gpio_set_value(EGPIO_MAGICIAN_IN_SEL0, 0); - - magician_snd_device = platform_device_alloc("soc-audio", -1); - if (!magician_snd_device) { - ret = -ENOMEM; - goto err_pdev; - } - - platform_set_drvdata(magician_snd_device, &snd_soc_card_magician); - ret = platform_device_add(magician_snd_device); - if (ret) { - platform_device_put(magician_snd_device); - goto err_pdev; - } - - return 0; - -err_pdev: - gpio_free(EGPIO_MAGICIAN_IN_SEL1); -err_request_in_sel1: - gpio_free(EGPIO_MAGICIAN_IN_SEL0); -err_request_in_sel0: - gpio_free(EGPIO_MAGICIAN_MIC_POWER); -err_request_mic: - gpio_free(EGPIO_MAGICIAN_EP_POWER); -err_request_ep: - gpio_free(EGPIO_MAGICIAN_SPK_POWER); -err_request_spk: - return ret; -} - -static void __exit magician_exit(void) +static int magician_audio_probe(struct platform_device *pdev) { - platform_device_unregister(magician_snd_device); - - gpio_set_value(EGPIO_MAGICIAN_SPK_POWER, 0); - gpio_set_value(EGPIO_MAGICIAN_EP_POWER, 0); - gpio_set_value(EGPIO_MAGICIAN_MIC_POWER, 0); - - gpio_free(EGPIO_MAGICIAN_IN_SEL1); - gpio_free(EGPIO_MAGICIAN_IN_SEL0); - gpio_free(EGPIO_MAGICIAN_MIC_POWER); - gpio_free(EGPIO_MAGICIAN_EP_POWER); - gpio_free(EGPIO_MAGICIAN_SPK_POWER); + struct device *dev = &pdev->dev; + + gpiod_spk_power = devm_gpiod_get(dev, "SPK_POWER", GPIOD_OUT_LOW); + if (IS_ERR(gpiod_spk_power)) + return PTR_ERR(gpiod_spk_power); + gpiod_ep_power = devm_gpiod_get(dev, "EP_POWER", GPIOD_OUT_LOW); + if (IS_ERR(gpiod_ep_power)) + return PTR_ERR(gpiod_ep_power); + gpiod_mic_power = devm_gpiod_get(dev, "MIC_POWER", GPIOD_OUT_LOW); + if (IS_ERR(gpiod_mic_power)) + return PTR_ERR(gpiod_mic_power); + gpiod_in_sel0 = devm_gpiod_get(dev, "IN_SEL0", GPIOD_OUT_HIGH); + if (IS_ERR(gpiod_in_sel0)) + return PTR_ERR(gpiod_in_sel0); + gpiod_in_sel1 = devm_gpiod_get(dev, "IN_SEL1", GPIOD_OUT_LOW); + if (IS_ERR(gpiod_in_sel1)) + return PTR_ERR(gpiod_in_sel1); + + snd_soc_card_magician.dev = &pdev->dev; + return devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_magician); } -module_init(magician_init); -module_exit(magician_exit); +static struct platform_driver magician_audio_driver = { + .driver.name = "magician-audio", + .driver.pm = &snd_soc_pm_ops, + .probe = magician_audio_probe, +}; +module_platform_driver(magician_audio_driver); MODULE_AUTHOR("Philipp Zabel"); MODULE_DESCRIPTION("ALSA SoC Magician"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:magician-audio"); diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c index 763db7bbd9bb..0fa37637eca9 100644 --- a/sound/soc/pxa/mioa701_wm9713.c +++ b/sound/soc/pxa/mioa701_wm9713.c @@ -33,7 +33,7 @@ #include <linux/platform_device.h> #include <asm/mach-types.h> -#include <mach/audio.h> +#include <linux/platform_data/asoc-pxa.h> #include <sound/core.h> #include <sound/pcm.h> diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c index 65257f7fe4c4..a2321c01c160 100644 --- a/sound/soc/pxa/palm27x.c +++ b/sound/soc/pxa/palm27x.c @@ -20,7 +20,7 @@ #include <sound/jack.h> #include <asm/mach-types.h> -#include <mach/audio.h> +#include <linux/platform_data/asoc-pxa.h> #include <linux/platform_data/asoc-palm27x.h> static struct snd_soc_jack hs_jack; diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index 323ba3e23039..5fdaa477e85d 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -21,8 +21,8 @@ #include <asm/mach-types.h> #include <asm/hardware/locomo.h> -#include <mach/poodle.h> -#include <mach/audio.h> +#include <linux/platform_data/asoc-pxa.h> +#include <linux/platform_data/asoc-poodle.h> #include "../codecs/wm8731.h" #include "pxa2xx-i2s.h" @@ -38,21 +38,23 @@ static int poodle_jack_func; static int poodle_spk_func; +static struct poodle_audio_platform_data *poodle_pdata; + static void poodle_ext_control(struct snd_soc_dapm_context *dapm) { /* set up jack connection */ if (poodle_jack_func == POODLE_HP) { /* set = unmute headphone */ - locomo_gpio_write(&poodle_locomo_device.dev, - POODLE_LOCOMO_GPIO_MUTE_L, 1); - locomo_gpio_write(&poodle_locomo_device.dev, - POODLE_LOCOMO_GPIO_MUTE_R, 1); + locomo_gpio_write(poodle_pdata->locomo_dev, + poodle_pdata->gpio_mute_l, 1); + locomo_gpio_write(poodle_pdata->locomo_dev, + poodle_pdata->gpio_mute_r, 1); snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); } else { - locomo_gpio_write(&poodle_locomo_device.dev, - POODLE_LOCOMO_GPIO_MUTE_L, 0); - locomo_gpio_write(&poodle_locomo_device.dev, - POODLE_LOCOMO_GPIO_MUTE_R, 0); + locomo_gpio_write(poodle_pdata->locomo_dev, + poodle_pdata->gpio_mute_l, 0); + locomo_gpio_write(poodle_pdata->locomo_dev, + poodle_pdata->gpio_mute_r, 0); snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); } @@ -80,10 +82,10 @@ static int poodle_startup(struct snd_pcm_substream *substream) static void poodle_shutdown(struct snd_pcm_substream *substream) { /* set = unmute headphone */ - locomo_gpio_write(&poodle_locomo_device.dev, - POODLE_LOCOMO_GPIO_MUTE_L, 1); - locomo_gpio_write(&poodle_locomo_device.dev, - POODLE_LOCOMO_GPIO_MUTE_R, 1); + locomo_gpio_write(poodle_pdata->locomo_dev, + poodle_pdata->gpio_mute_l, 1); + locomo_gpio_write(poodle_pdata->locomo_dev, + poodle_pdata->gpio_mute_r, 1); } static int poodle_hw_params(struct snd_pcm_substream *substream, @@ -174,11 +176,11 @@ static int poodle_amp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { if (SND_SOC_DAPM_EVENT_ON(event)) - locomo_gpio_write(&poodle_locomo_device.dev, - POODLE_LOCOMO_GPIO_AMP_ON, 0); + locomo_gpio_write(poodle_pdata->locomo_dev, + poodle_pdata->gpio_amp_on, 0); else - locomo_gpio_write(&poodle_locomo_device.dev, - POODLE_LOCOMO_GPIO_AMP_ON, 1); + locomo_gpio_write(poodle_pdata->locomo_dev, + poodle_pdata->gpio_amp_on, 1); return 0; } @@ -254,13 +256,14 @@ static int poodle_probe(struct platform_device *pdev) struct snd_soc_card *card = &poodle; int ret; - locomo_gpio_set_dir(&poodle_locomo_device.dev, - POODLE_LOCOMO_GPIO_AMP_ON, 0); + poodle_pdata = pdev->dev.platform_data; + locomo_gpio_set_dir(poodle_pdata->locomo_dev, + poodle_pdata->gpio_amp_on, 0); /* should we mute HP at startup - burning power ?*/ - locomo_gpio_set_dir(&poodle_locomo_device.dev, - POODLE_LOCOMO_GPIO_MUTE_L, 0); - locomo_gpio_set_dir(&poodle_locomo_device.dev, - POODLE_LOCOMO_GPIO_MUTE_R, 0); + locomo_gpio_set_dir(poodle_pdata->locomo_dev, + poodle_pdata->gpio_mute_l, 0); + locomo_gpio_set_dir(poodle_pdata->locomo_dev, + poodle_pdata->gpio_mute_r, 0); card->dev = &pdev->dev; diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index 58f8541ba55c..809ea34736ed 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c @@ -21,9 +21,11 @@ #include <sound/pxa2xx-lib.h> #include <sound/dmaengine_pcm.h> -#include <mach/hardware.h> -#include <mach/regs-ac97.h> -#include <mach/audio.h> +#include <linux/platform_data/asoc-pxa.h> + +#define PCDR 0x0040 /* PCM FIFO Data Register */ +#define MODR 0x0140 /* Modem FIFO Data Register */ +#define MCDR 0x0060 /* Mic-in FIFO Data Register */ static void pxa2xx_ac97_warm_reset(struct ac97_controller *adrv) { @@ -59,35 +61,30 @@ static struct ac97_controller_ops pxa2xx_ac97_ops = { }; static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_stereo_in = { - .addr = __PREG(PCDR), .addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, .chan_name = "pcm_pcm_stereo_in", .maxburst = 32, }; static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_stereo_out = { - .addr = __PREG(PCDR), .addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, .chan_name = "pcm_pcm_stereo_out", .maxburst = 32, }; static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_aux_mono_out = { - .addr = __PREG(MODR), .addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES, .chan_name = "pcm_aux_mono_out", .maxburst = 16, }; static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_aux_mono_in = { - .addr = __PREG(MODR), .addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES, .chan_name = "pcm_aux_mono_in", .maxburst = 16, }; static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_mic_mono_in = { - .addr = __PREG(MCDR), .addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES, .chan_name = "pcm_aux_mic_mono", .maxburst = 16, @@ -226,6 +223,7 @@ static int pxa2xx_ac97_dev_probe(struct platform_device *pdev) int ret; struct ac97_controller *ctrl; pxa2xx_audio_ops_t *pdata = pdev->dev.platform_data; + struct resource *regs; void **codecs_pdata; if (pdev->id != -1) { @@ -233,6 +231,16 @@ static int pxa2xx_ac97_dev_probe(struct platform_device *pdev) return -ENXIO; } + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!regs) + return -ENXIO; + + pxa2xx_ac97_pcm_stereo_in.addr = regs->start + PCDR; + pxa2xx_ac97_pcm_stereo_out.addr = regs->start + PCDR; + pxa2xx_ac97_pcm_aux_mono_out.addr = regs->start + MODR; + pxa2xx_ac97_pcm_aux_mono_in.addr = regs->start + MODR; + pxa2xx_ac97_pcm_mic_mono_in.addr = regs->start + MCDR; + ret = pxa2xx_ac97_hw_probe(pdev); if (ret) { dev_err(&pdev->dev, "PXA2xx AC97 hw probe error (%d)\n", ret); diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index 5bfc1a966532..746e6ec9198b 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c @@ -21,21 +21,20 @@ #include <sound/pxa2xx-lib.h> #include <sound/dmaengine_pcm.h> -#include <mach/hardware.h> -#include <mach/audio.h> +#include <linux/platform_data/asoc-pxa.h> #include "pxa2xx-i2s.h" /* * I2S Controller Register and Bit Definitions */ -#define SACR0 __REG(0x40400000) /* Global Control Register */ -#define SACR1 __REG(0x40400004) /* Serial Audio I 2 S/MSB-Justified Control Register */ -#define SASR0 __REG(0x4040000C) /* Serial Audio I 2 S/MSB-Justified Interface and FIFO Status Register */ -#define SAIMR __REG(0x40400014) /* Serial Audio Interrupt Mask Register */ -#define SAICR __REG(0x40400018) /* Serial Audio Interrupt Clear Register */ -#define SADIV __REG(0x40400060) /* Audio Clock Divider Register. */ -#define SADR __REG(0x40400080) /* Serial Audio Data Register (TX and RX FIFO access Register). */ +#define SACR0 (0x0000) /* Global Control Register */ +#define SACR1 (0x0004) /* Serial Audio I 2 S/MSB-Justified Control Register */ +#define SASR0 (0x000C) /* Serial Audio I 2 S/MSB-Justified Interface and FIFO Status Register */ +#define SAIMR (0x0014) /* Serial Audio Interrupt Mask Register */ +#define SAICR (0x0018) /* Serial Audio Interrupt Clear Register */ +#define SADIV (0x0060) /* Audio Clock Divider Register. */ +#define SADR (0x0080) /* Serial Audio Data Register (TX and RX FIFO access Register). */ #define SACR0_RFTH(x) ((x) << 12) /* Rx FIFO Interrupt or DMA Trigger Threshold */ #define SACR0_TFTH(x) ((x) << 8) /* Tx FIFO Interrupt or DMA Trigger Threshold */ @@ -77,16 +76,15 @@ struct pxa_i2s_port { static struct pxa_i2s_port pxa_i2s; static struct clk *clk_i2s; static int clk_ena = 0; +static void __iomem *i2s_reg_base; static struct snd_dmaengine_dai_dma_data pxa2xx_i2s_pcm_stereo_out = { - .addr = __PREG(SADR), .addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, .chan_name = "tx", .maxburst = 32, }; static struct snd_dmaengine_dai_dma_data pxa2xx_i2s_pcm_stereo_in = { - .addr = __PREG(SADR), .addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, .chan_name = "rx", .maxburst = 32, @@ -102,7 +100,7 @@ static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream, return PTR_ERR(clk_i2s); if (!snd_soc_dai_active(cpu_dai)) - SACR0 = 0; + writel(0, i2s_reg_base + SACR0); return 0; } @@ -114,7 +112,7 @@ static int pxa_i2s_wait(void) /* flush the Rx FIFO */ for (i = 0; i < 16; i++) - SADR; + readl(i2s_reg_base + SADR); return 0; } @@ -174,39 +172,39 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream, /* is port used by another stream */ if (!(SACR0 & SACR0_ENB)) { - SACR0 = 0; + writel(0, i2s_reg_base + SACR0); if (pxa_i2s.master) - SACR0 |= SACR0_BCKD; + writel(readl(i2s_reg_base + SACR0) | (SACR0_BCKD), i2s_reg_base + SACR0); - SACR0 |= SACR0_RFTH(14) | SACR0_TFTH(1); - SACR1 |= pxa_i2s.fmt; + writel(readl(i2s_reg_base + SACR0) | (SACR0_RFTH(14) | SACR0_TFTH(1)), i2s_reg_base + SACR0); + writel(readl(i2s_reg_base + SACR1) | (pxa_i2s.fmt), i2s_reg_base + SACR1); } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - SAIMR |= SAIMR_TFS; + writel(readl(i2s_reg_base + SAIMR) | (SAIMR_TFS), i2s_reg_base + SAIMR); else - SAIMR |= SAIMR_RFS; + writel(readl(i2s_reg_base + SAIMR) | (SAIMR_RFS), i2s_reg_base + SAIMR); switch (params_rate(params)) { case 8000: - SADIV = 0x48; + writel(0x48, i2s_reg_base + SADIV); break; case 11025: - SADIV = 0x34; + writel(0x34, i2s_reg_base + SADIV); break; case 16000: - SADIV = 0x24; + writel(0x24, i2s_reg_base + SADIV); break; case 22050: - SADIV = 0x1a; + writel(0x1a, i2s_reg_base + SADIV); break; case 44100: - SADIV = 0xd; + writel(0xd, i2s_reg_base + SADIV); break; case 48000: - SADIV = 0xc; + writel(0xc, i2s_reg_base + SADIV); break; case 96000: /* not in manual and possibly slightly inaccurate */ - SADIV = 0x6; + writel(0x6, i2s_reg_base + SADIV); break; } @@ -221,10 +219,10 @@ static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, switch (cmd) { case SNDRV_PCM_TRIGGER_START: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - SACR1 &= ~SACR1_DRPL; + writel(readl(i2s_reg_base + SACR1) & (~SACR1_DRPL), i2s_reg_base + SACR1); else - SACR1 &= ~SACR1_DREC; - SACR0 |= SACR0_ENB; + writel(readl(i2s_reg_base + SACR1) & (~SACR1_DREC), i2s_reg_base + SACR1); + writel(readl(i2s_reg_base + SACR0) | (SACR0_ENB), i2s_reg_base + SACR0); break; case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: @@ -243,15 +241,15 @@ static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - SACR1 |= SACR1_DRPL; - SAIMR &= ~SAIMR_TFS; + writel(readl(i2s_reg_base + SACR1) | (SACR1_DRPL), i2s_reg_base + SACR1); + writel(readl(i2s_reg_base + SAIMR) & (~SAIMR_TFS), i2s_reg_base + SAIMR); } else { - SACR1 |= SACR1_DREC; - SAIMR &= ~SAIMR_RFS; + writel(readl(i2s_reg_base + SACR1) | (SACR1_DREC), i2s_reg_base + SACR1); + writel(readl(i2s_reg_base + SAIMR) & (~SAIMR_RFS), i2s_reg_base + SAIMR); } - if ((SACR1 & (SACR1_DREC | SACR1_DRPL)) == (SACR1_DREC | SACR1_DRPL)) { - SACR0 &= ~SACR0_ENB; + if ((readl(i2s_reg_base + SACR1) & (SACR1_DREC | SACR1_DRPL)) == (SACR1_DREC | SACR1_DRPL)) { + writel(readl(i2s_reg_base + SACR0) & (~SACR0_ENB), i2s_reg_base + SACR0); pxa_i2s_wait(); if (clk_ena) { clk_disable_unprepare(clk_i2s); @@ -264,13 +262,13 @@ static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream, static int pxa2xx_soc_pcm_suspend(struct snd_soc_component *component) { /* store registers */ - pxa_i2s.sacr0 = SACR0; - pxa_i2s.sacr1 = SACR1; - pxa_i2s.saimr = SAIMR; - pxa_i2s.sadiv = SADIV; + pxa_i2s.sacr0 = readl(i2s_reg_base + SACR0); + pxa_i2s.sacr1 = readl(i2s_reg_base + SACR1); + pxa_i2s.saimr = readl(i2s_reg_base + SAIMR); + pxa_i2s.sadiv = readl(i2s_reg_base + SADIV); /* deactivate link */ - SACR0 &= ~SACR0_ENB; + writel(readl(i2s_reg_base + SACR0) & (~SACR0_ENB), i2s_reg_base + SACR0); pxa_i2s_wait(); return 0; } @@ -279,12 +277,12 @@ static int pxa2xx_soc_pcm_resume(struct snd_soc_component *component) { pxa_i2s_wait(); - SACR0 = pxa_i2s.sacr0 & ~SACR0_ENB; - SACR1 = pxa_i2s.sacr1; - SAIMR = pxa_i2s.saimr; - SADIV = pxa_i2s.sadiv; + writel(pxa_i2s.sacr0 & ~SACR0_ENB, i2s_reg_base + SACR0); + writel(pxa_i2s.sacr1, i2s_reg_base + SACR1); + writel(pxa_i2s.saimr, i2s_reg_base + SAIMR); + writel(pxa_i2s.sadiv, i2s_reg_base + SADIV); - SACR0 = pxa_i2s.sacr0; + writel(pxa_i2s.sacr0, i2s_reg_base + SACR0); return 0; } @@ -306,12 +304,12 @@ static int pxa2xx_i2s_probe(struct snd_soc_dai *dai) * the SACR0[RST] bit must also be set and cleared to reset all * I2S controller registers. */ - SACR0 = SACR0_RST; - SACR0 = 0; + writel(SACR0_RST, i2s_reg_base + SACR0); + writel(0, i2s_reg_base + SACR0); /* Make sure RPL and REC are disabled */ - SACR1 = SACR1_DRPL | SACR1_DREC; + writel(SACR1_DRPL | SACR1_DREC, i2s_reg_base + SACR1); /* Along with FIFO servicing */ - SAIMR &= ~(SAIMR_RFS | SAIMR_TFS); + writel(readl(i2s_reg_base + SAIMR) & (~(SAIMR_RFS | SAIMR_TFS)), i2s_reg_base + SAIMR); snd_soc_dai_init_dma_data(dai, &pxa2xx_i2s_pcm_stereo_out, &pxa2xx_i2s_pcm_stereo_in); @@ -371,6 +369,22 @@ static const struct snd_soc_component_driver pxa_i2s_component = { static int pxa2xx_i2s_drv_probe(struct platform_device *pdev) { + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + if (!res) { + dev_err(&pdev->dev, "missing MMIO resource\n"); + return -ENXIO; + } + + i2s_reg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(i2s_reg_base)) { + dev_err(&pdev->dev, "ioremap failed\n"); + return PTR_ERR(i2s_reg_base); + } + + pxa2xx_i2s_pcm_stereo_out.addr = res->start + SADR; + pxa2xx_i2s_pcm_stereo_in.addr = res->start + SADR; + return devm_snd_soc_register_component(&pdev->dev, &pxa_i2s_component, &pxa_i2s_dai, 1); } diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index 7c1384a869ca..44303b6eb228 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c @@ -14,13 +14,12 @@ #include <linux/timer.h> #include <linux/interrupt.h> #include <linux/platform_device.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/soc.h> #include <asm/mach-types.h> -#include <mach/spitz.h> #include "../codecs/wm8750.h" #include "pxa2xx-i2s.h" @@ -37,7 +36,7 @@ static int spitz_jack_func; static int spitz_spk_func; -static int spitz_mic_gpio; +static struct gpio_desc *gpiod_mic, *gpiod_mute_l, *gpiod_mute_r; static void spitz_ext_control(struct snd_soc_dapm_context *dapm) { @@ -56,8 +55,8 @@ static void spitz_ext_control(struct snd_soc_dapm_context *dapm) snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); snd_soc_dapm_enable_pin_unlocked(dapm, "Headphone Jack"); - gpio_set_value(SPITZ_GPIO_MUTE_L, 1); - gpio_set_value(SPITZ_GPIO_MUTE_R, 1); + gpiod_set_value(gpiod_mute_l, 1); + gpiod_set_value(gpiod_mute_r, 1); break; case SPITZ_MIC: /* enable mic jack and bias, mute hp */ @@ -65,8 +64,8 @@ static void spitz_ext_control(struct snd_soc_dapm_context *dapm) snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); snd_soc_dapm_enable_pin_unlocked(dapm, "Mic Jack"); - gpio_set_value(SPITZ_GPIO_MUTE_L, 0); - gpio_set_value(SPITZ_GPIO_MUTE_R, 0); + gpiod_set_value(gpiod_mute_l, 0); + gpiod_set_value(gpiod_mute_r, 0); break; case SPITZ_LINE: /* enable line jack, disable mic bias and mute hp */ @@ -74,8 +73,8 @@ static void spitz_ext_control(struct snd_soc_dapm_context *dapm) snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack"); snd_soc_dapm_enable_pin_unlocked(dapm, "Line Jack"); - gpio_set_value(SPITZ_GPIO_MUTE_L, 0); - gpio_set_value(SPITZ_GPIO_MUTE_R, 0); + gpiod_set_value(gpiod_mute_l, 0); + gpiod_set_value(gpiod_mute_r, 0); break; case SPITZ_HEADSET: /* enable and unmute headset jack enable mic bias, mute L hp */ @@ -83,8 +82,8 @@ static void spitz_ext_control(struct snd_soc_dapm_context *dapm) snd_soc_dapm_enable_pin_unlocked(dapm, "Mic Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); snd_soc_dapm_enable_pin_unlocked(dapm, "Headset Jack"); - gpio_set_value(SPITZ_GPIO_MUTE_L, 0); - gpio_set_value(SPITZ_GPIO_MUTE_R, 1); + gpiod_set_value(gpiod_mute_l, 0); + gpiod_set_value(gpiod_mute_r, 1); break; case SPITZ_HP_OFF: @@ -93,8 +92,8 @@ static void spitz_ext_control(struct snd_soc_dapm_context *dapm) snd_soc_dapm_disable_pin_unlocked(dapm, "Headset Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Mic Jack"); snd_soc_dapm_disable_pin_unlocked(dapm, "Line Jack"); - gpio_set_value(SPITZ_GPIO_MUTE_L, 0); - gpio_set_value(SPITZ_GPIO_MUTE_R, 0); + gpiod_set_value(gpiod_mute_l, 0); + gpiod_set_value(gpiod_mute_r, 0); break; } @@ -199,7 +198,7 @@ static int spitz_set_spk(struct snd_kcontrol *kcontrol, static int spitz_mic_bias(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { - gpio_set_value_cansleep(spitz_mic_gpio, SND_SOC_DAPM_EVENT_ON(event)); + gpiod_set_value_cansleep(gpiod_mic, SND_SOC_DAPM_EVENT_ON(event)); return 0; } @@ -287,39 +286,28 @@ static int spitz_probe(struct platform_device *pdev) struct snd_soc_card *card = &snd_soc_spitz; int ret; - if (machine_is_akita()) - spitz_mic_gpio = AKITA_GPIO_MIC_BIAS; - else - spitz_mic_gpio = SPITZ_GPIO_MIC_BIAS; - - ret = gpio_request(spitz_mic_gpio, "MIC GPIO"); - if (ret) - goto err1; - - ret = gpio_direction_output(spitz_mic_gpio, 0); - if (ret) - goto err2; + gpiod_mic = devm_gpiod_get(&pdev->dev, "mic", GPIOD_OUT_LOW); + if (IS_ERR(gpiod_mic)) + return PTR_ERR(gpiod_mic); + gpiod_mute_l = devm_gpiod_get(&pdev->dev, "mute-l", GPIOD_OUT_LOW); + if (IS_ERR(gpiod_mute_l)) + return PTR_ERR(gpiod_mute_l); + gpiod_mute_r = devm_gpiod_get(&pdev->dev, "mute-r", GPIOD_OUT_LOW); + if (IS_ERR(gpiod_mute_r)) + return PTR_ERR(gpiod_mute_r); card->dev = &pdev->dev; ret = devm_snd_soc_register_card(&pdev->dev, card); - if (ret) { + if (ret) dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); - goto err2; - } - - return 0; -err2: - gpio_free(spitz_mic_gpio); -err1: return ret; } static int spitz_remove(struct platform_device *pdev) { - gpio_free(spitz_mic_gpio); return 0; } diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index 3b40b5fa5de7..30f83cab0c32 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c @@ -16,15 +16,14 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/device.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/soc.h> #include <asm/mach-types.h> -#include <mach/tosa.h> -#include <mach/audio.h> +#include <linux/platform_data/asoc-pxa.h> #define TOSA_HP 0 #define TOSA_MIC_INT 1 @@ -33,6 +32,7 @@ #define TOSA_SPK_ON 0 #define TOSA_SPK_OFF 1 +static struct gpio_desc *tosa_mute; static int tosa_jack_func; static int tosa_spk_func; @@ -128,7 +128,7 @@ static int tosa_set_spk(struct snd_kcontrol *kcontrol, static int tosa_hp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { - gpio_set_value(TOSA_GPIO_L_MUTE, SND_SOC_DAPM_EVENT_ON(event) ? 1 : 0); + gpiod_set_value(tosa_mute, SND_SOC_DAPM_EVENT_ON(event) ? 1 : 0); return 0; } @@ -222,10 +222,11 @@ static int tosa_probe(struct platform_device *pdev) struct snd_soc_card *card = ⤩ int ret; - ret = gpio_request_one(TOSA_GPIO_L_MUTE, GPIOF_OUT_INIT_LOW, - "Headphone Jack"); - if (ret) - return ret; + tosa_mute = devm_gpiod_get(&pdev->dev, NULL, GPIOD_OUT_LOW); + if (IS_ERR(tosa_mute)) + return dev_err_probe(&pdev->dev, PTR_ERR(tosa_mute), + "failed to get L_MUTE GPIO\n"); + gpiod_set_consumer_name(tosa_mute, "Headphone Jack"); card->dev = &pdev->dev; @@ -233,24 +234,16 @@ static int tosa_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); - gpio_free(TOSA_GPIO_L_MUTE); } return ret; } -static int tosa_remove(struct platform_device *pdev) -{ - gpio_free(TOSA_GPIO_L_MUTE); - return 0; -} - static struct platform_driver tosa_driver = { .driver = { .name = "tosa-audio", .pm = &snd_soc_pm_ops, }, .probe = tosa_probe, - .remove = tosa_remove, }; module_platform_driver(tosa_driver); diff --git a/sound/soc/pxa/z2.c b/sound/soc/pxa/z2.c index f4a7cfe22115..020dcce1df1f 100644 --- a/sound/soc/pxa/z2.c +++ b/sound/soc/pxa/z2.c @@ -13,7 +13,7 @@ #include <linux/timer.h> #include <linux/interrupt.h> #include <linux/platform_device.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <sound/core.h> #include <sound/pcm.h> @@ -21,9 +21,7 @@ #include <sound/jack.h> #include <asm/mach-types.h> -#include <mach/hardware.h> -#include <mach/audio.h> -#include <mach/z2.h> +#include <linux/platform_data/asoc-pxa.h> #include "../codecs/wm8750.h" #include "pxa2xx-i2s.h" @@ -90,7 +88,6 @@ static struct snd_soc_jack_pin hs_jack_pins[] = { /* Headset jack detection gpios */ static struct snd_soc_jack_gpio hs_jack_gpios[] = { { - .gpio = GPIO37_ZIPITZ2_HEADSET_DETECT, .name = "hsdet-gpio", .report = SND_JACK_HEADSET, .debounce_time = 200, @@ -197,6 +194,7 @@ static int __init z2_init(void) if (!z2_snd_device) return -ENOMEM; + hs_jack_gpios[0].gpiod_dev = &z2_snd_device->dev; platform_set_drvdata(z2_snd_device, &snd_soc_z2); ret = platform_device_add(z2_snd_device); diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c index 19c4a90ec1ea..ee59ef36b85a 100644 --- a/sound/soc/qcom/qdsp6/q6apm-dai.c +++ b/sound/soc/qcom/qdsp6/q6apm-dai.c @@ -147,6 +147,12 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, cfg.num_channels = runtime->channels; cfg.bit_width = prtd->bits_per_sample; + if (prtd->state) { + /* clear the previous setup if any */ + q6apm_graph_stop(prtd->graph); + q6apm_unmap_memory_regions(prtd->graph, substream->stream); + } + prtd->pcm_count = snd_pcm_lib_period_bytes(substream); prtd->pos = 0; /* rate and channels are sent to audio driver */ diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 4ce5d2579387..99a128a666fb 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -13,6 +13,7 @@ #include <linux/of_gpio.h> #include <linux/of_device.h> #include <linux/clk.h> +#include <linux/pinctrl/consumer.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> #include <linux/spinlock.h> @@ -54,8 +55,40 @@ struct rk_i2s_dev { const struct rk_i2s_pins *pins; unsigned int bclk_ratio; spinlock_t lock; /* tx/rx lock */ + struct pinctrl *pinctrl; + struct pinctrl_state *bclk_on; + struct pinctrl_state *bclk_off; }; +static int i2s_pinctrl_select_bclk_on(struct rk_i2s_dev *i2s) +{ + int ret = 0; + + if (!IS_ERR(i2s->pinctrl) && !IS_ERR_OR_NULL(i2s->bclk_on)) + ret = pinctrl_select_state(i2s->pinctrl, + i2s->bclk_on); + + if (ret) + dev_err(i2s->dev, "bclk enable failed %d\n", ret); + + return ret; +} + +static int i2s_pinctrl_select_bclk_off(struct rk_i2s_dev *i2s) +{ + + int ret = 0; + + if (!IS_ERR(i2s->pinctrl) && !IS_ERR_OR_NULL(i2s->bclk_off)) + ret = pinctrl_select_state(i2s->pinctrl, + i2s->bclk_off); + + if (ret) + dev_err(i2s->dev, "bclk disable failed %d\n", ret); + + return ret; +} + static int i2s_runtime_suspend(struct device *dev) { struct rk_i2s_dev *i2s = dev_get_drvdata(dev); @@ -92,38 +125,49 @@ static inline struct rk_i2s_dev *to_info(struct snd_soc_dai *dai) return snd_soc_dai_get_drvdata(dai); } -static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on) +static int rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on) { unsigned int val = 0; int retry = 10; + int ret = 0; spin_lock(&i2s->lock); if (on) { - regmap_update_bits(i2s->regmap, I2S_DMACR, - I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE); + ret = regmap_update_bits(i2s->regmap, I2S_DMACR, + I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE); + if (ret < 0) + goto end; - regmap_update_bits(i2s->regmap, I2S_XFER, - I2S_XFER_TXS_START | I2S_XFER_RXS_START, - I2S_XFER_TXS_START | I2S_XFER_RXS_START); + ret = regmap_update_bits(i2s->regmap, I2S_XFER, + I2S_XFER_TXS_START | I2S_XFER_RXS_START, + I2S_XFER_TXS_START | I2S_XFER_RXS_START); + if (ret < 0) + goto end; i2s->tx_start = true; } else { i2s->tx_start = false; - regmap_update_bits(i2s->regmap, I2S_DMACR, - I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE); + ret = regmap_update_bits(i2s->regmap, I2S_DMACR, + I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE); + if (ret < 0) + goto end; if (!i2s->rx_start) { - regmap_update_bits(i2s->regmap, I2S_XFER, - I2S_XFER_TXS_START | - I2S_XFER_RXS_START, - I2S_XFER_TXS_STOP | - I2S_XFER_RXS_STOP); + ret = regmap_update_bits(i2s->regmap, I2S_XFER, + I2S_XFER_TXS_START | + I2S_XFER_RXS_START, + I2S_XFER_TXS_STOP | + I2S_XFER_RXS_STOP); + if (ret < 0) + goto end; udelay(150); - regmap_update_bits(i2s->regmap, I2S_CLR, - I2S_CLR_TXC | I2S_CLR_RXC, - I2S_CLR_TXC | I2S_CLR_RXC); + ret = regmap_update_bits(i2s->regmap, I2S_CLR, + I2S_CLR_TXC | I2S_CLR_RXC, + I2S_CLR_TXC | I2S_CLR_RXC); + if (ret < 0) + goto end; regmap_read(i2s->regmap, I2S_CLR, &val); @@ -138,44 +182,57 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on) } } } +end: spin_unlock(&i2s->lock); + if (ret < 0) + dev_err(i2s->dev, "lrclk update failed\n"); + + return ret; } -static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on) +static int rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on) { unsigned int val = 0; int retry = 10; + int ret = 0; spin_lock(&i2s->lock); if (on) { - regmap_update_bits(i2s->regmap, I2S_DMACR, + ret = regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE); + if (ret < 0) + goto end; - regmap_update_bits(i2s->regmap, I2S_XFER, + ret = regmap_update_bits(i2s->regmap, I2S_XFER, I2S_XFER_TXS_START | I2S_XFER_RXS_START, I2S_XFER_TXS_START | I2S_XFER_RXS_START); + if (ret < 0) + goto end; i2s->rx_start = true; } else { i2s->rx_start = false; - regmap_update_bits(i2s->regmap, I2S_DMACR, + ret = regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE); + if (ret < 0) + goto end; if (!i2s->tx_start) { - regmap_update_bits(i2s->regmap, I2S_XFER, + ret = regmap_update_bits(i2s->regmap, I2S_XFER, I2S_XFER_TXS_START | I2S_XFER_RXS_START, I2S_XFER_TXS_STOP | I2S_XFER_RXS_STOP); - + if (ret < 0) + goto end; udelay(150); - regmap_update_bits(i2s->regmap, I2S_CLR, + ret = regmap_update_bits(i2s->regmap, I2S_CLR, I2S_CLR_TXC | I2S_CLR_RXC, I2S_CLR_TXC | I2S_CLR_RXC); - + if (ret < 0) + goto end; regmap_read(i2s->regmap, I2S_CLR, &val); - /* Should wait for clear operation to finish */ while (val) { regmap_read(i2s->regmap, I2S_CLR, &val); @@ -187,7 +244,12 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on) } } } +end: spin_unlock(&i2s->lock); + if (ret < 0) + dev_err(i2s->dev, "lrclk update failed\n"); + + return ret; } static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, @@ -425,17 +487,26 @@ static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - rockchip_snd_rxctrl(i2s, 1); + ret = rockchip_snd_rxctrl(i2s, 1); else - rockchip_snd_txctrl(i2s, 1); + ret = rockchip_snd_txctrl(i2s, 1); + /* Do not turn on bclk if lrclk open fails. */ + if (ret < 0) + return ret; + i2s_pinctrl_select_bclk_on(i2s); break; case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - rockchip_snd_rxctrl(i2s, 0); - else - rockchip_snd_txctrl(i2s, 0); + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + if (!i2s->tx_start) + i2s_pinctrl_select_bclk_off(i2s); + ret = rockchip_snd_rxctrl(i2s, 0); + } else { + if (!i2s->rx_start) + i2s_pinctrl_select_bclk_off(i2s); + ret = rockchip_snd_txctrl(i2s, 0); + } break; default: ret = -EINVAL; @@ -736,6 +807,33 @@ static int rockchip_i2s_probe(struct platform_device *pdev) } i2s->bclk_ratio = 64; + i2s->pinctrl = devm_pinctrl_get(&pdev->dev); + if (IS_ERR(i2s->pinctrl)) + dev_err(&pdev->dev, "failed to find i2s pinctrl\n"); + + i2s->bclk_on = pinctrl_lookup_state(i2s->pinctrl, + "bclk_on"); + if (IS_ERR_OR_NULL(i2s->bclk_on)) + dev_err(&pdev->dev, "failed to find i2s default state\n"); + else + dev_dbg(&pdev->dev, "find i2s bclk state\n"); + + i2s->bclk_off = pinctrl_lookup_state(i2s->pinctrl, + "bclk_off"); + if (IS_ERR_OR_NULL(i2s->bclk_off)) + dev_err(&pdev->dev, "failed to find i2s gpio state\n"); + else + dev_dbg(&pdev->dev, "find i2s bclk_off state\n"); + + i2s_pinctrl_select_bclk_off(i2s); + + i2s->playback_dma_data.addr = res->start + I2S_TXDR; + i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + i2s->playback_dma_data.maxburst = 4; + + i2s->capture_dma_data.addr = res->start + I2S_RXDR; + i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + i2s->capture_dma_data.maxburst = 4; dev_set_drvdata(&pdev->dev, i2s); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 869c76506b66..a8e842e02cdc 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -62,6 +62,8 @@ struct snd_soc_dapm_widget * snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, const struct snd_soc_dapm_widget *widget); +static unsigned int soc_dapm_read(struct snd_soc_dapm_context *dapm, int reg); + /* dapm power sequences - make this per codec in the future */ static int dapm_up_seq[] = { [snd_soc_dapm_pre] = 1, @@ -442,6 +444,9 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget, snd_soc_dapm_add_path(widget->dapm, data->widget, widget, NULL, NULL); + } else if (e->reg != SND_SOC_NOPM) { + data->value = soc_dapm_read(widget->dapm, e->reg) & + (e->mask << e->shift_l); } break; default: diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index e693070f51fe..d867f449d82d 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -526,7 +526,7 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, return -EINVAL; if (mc->platform_max && tmp > mc->platform_max) return -EINVAL; - if (tmp > mc->max - mc->min + 1) + if (tmp > mc->max - mc->min) return -EINVAL; if (invert) @@ -547,7 +547,7 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, return -EINVAL; if (mc->platform_max && tmp > mc->platform_max) return -EINVAL; - if (tmp > mc->max - mc->min + 1) + if (tmp > mc->max - mc->min) return -EINVAL; if (invert) diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 000ea906670c..e24eea725acb 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -181,12 +181,20 @@ int hda_dsp_core_run(struct snd_sof_dev *sdev, unsigned int core_mask) * Power Management. */ -static int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask) +int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask) { + struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; + const struct sof_intel_dsp_desc *chip = hda->desc; unsigned int cpa; u32 adspcs; int ret; + /* restrict core_mask to host managed cores mask */ + core_mask &= chip->host_managed_cores_mask; + /* return if core_mask is not valid */ + if (!core_mask) + return 0; + /* update bits */ snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPCS, HDA_DSP_ADSPCS_SPA_MASK(core_mask), diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index 64290125d7cd..145d483bd129 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -95,9 +95,9 @@ out_put: } /* - * first boot sequence has some extra steps. core 0 waits for power - * status on core 1, so power up core 1 also momentarily, keep it in - * reset/stall and then turn it off + * first boot sequence has some extra steps. + * power on all host managed cores and only unstall/run the boot core to boot the + * DSP then turn off all non boot cores (if any) is powered on. */ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot) { @@ -110,7 +110,7 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot) int ret; /* step 1: power up corex */ - ret = hda_dsp_enable_core(sdev, chip->host_managed_cores_mask); + ret = hda_dsp_core_power_up(sdev, chip->host_managed_cores_mask); if (ret < 0) { if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS) dev_err(sdev->dev, "error: dsp core 0/1 power up failed\n"); @@ -127,7 +127,7 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot) snd_sof_dsp_write(sdev, HDA_DSP_BAR, chip->ipc_req, ipc_hdr); /* step 3: unset core 0 reset state & unstall/run core 0 */ - ret = hda_dsp_core_run(sdev, BIT(0)); + ret = hda_dsp_core_run(sdev, chip->init_core_mask); if (ret < 0) { if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS) dev_err(sdev->dev, @@ -389,7 +389,8 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev) struct snd_dma_buffer dmab; int ret, ret1, i; - if (hda->imrboot_supported && !sdev->first_boot) { + if (sdev->system_suspend_target < SOF_SUSPEND_S4 && + hda->imrboot_supported && !sdev->first_boot) { dev_dbg(sdev->dev, "IMR restore supported, booting from IMR directly\n"); hda->boot_iteration = 0; ret = hda_dsp_boot_imr(sdev); diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c index dc1f743730c0..6888e0a4665d 100644 --- a/sound/soc/sof/intel/hda-pcm.c +++ b/sound/soc/sof/intel/hda-pcm.c @@ -192,79 +192,7 @@ snd_pcm_uframes_t hda_dsp_pcm_pointer(struct snd_sof_dev *sdev, goto found; } - switch (sof_hda_position_quirk) { - case SOF_HDA_POSITION_QUIRK_USE_SKYLAKE_LEGACY: - /* - * This legacy code, inherited from the Skylake driver, - * mixes DPIB registers and DPIB DDR updates and - * does not seem to follow any known hardware recommendations. - * It's not clear e.g. why there is a different flow - * for capture and playback, the only information that matters is - * what traffic class is used, and on all SOF-enabled platforms - * only VC0 is supported so the work-around was likely not necessary - * and quite possibly wrong. - */ - - /* DPIB/posbuf position mode: - * For Playback, Use DPIB register from HDA space which - * reflects the actual data transferred. - * For Capture, Use the position buffer for pointer, as DPIB - * is not accurate enough, its update may be completed - * earlier than the data written to DDR. - */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - pos = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, - AZX_REG_VS_SDXDPIB_XBASE + - (AZX_REG_VS_SDXDPIB_XINTERVAL * - hstream->index)); - } else { - /* - * For capture stream, we need more workaround to fix the - * position incorrect issue: - * - * 1. Wait at least 20us before reading position buffer after - * the interrupt generated(IOC), to make sure position update - * happens on frame boundary i.e. 20.833uSec for 48KHz. - * 2. Perform a dummy Read to DPIB register to flush DMA - * position value. - * 3. Read the DMA Position from posbuf. Now the readback - * value should be >= period boundary. - */ - usleep_range(20, 21); - snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, - AZX_REG_VS_SDXDPIB_XBASE + - (AZX_REG_VS_SDXDPIB_XINTERVAL * - hstream->index)); - pos = snd_hdac_stream_get_pos_posbuf(hstream); - } - break; - case SOF_HDA_POSITION_QUIRK_USE_DPIB_REGISTERS: - /* - * In case VC1 traffic is disabled this is the recommended option - */ - pos = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, - AZX_REG_VS_SDXDPIB_XBASE + - (AZX_REG_VS_SDXDPIB_XINTERVAL * - hstream->index)); - break; - case SOF_HDA_POSITION_QUIRK_USE_DPIB_DDR_UPDATE: - /* - * This is the recommended option when VC1 is enabled. - * While this isn't needed for SOF platforms it's added for - * consistency and debug. - */ - pos = snd_hdac_stream_get_pos_posbuf(hstream); - break; - default: - dev_err_once(sdev->dev, "hda_position_quirk value %d not supported\n", - sof_hda_position_quirk); - pos = 0; - break; - } - - if (pos >= hstream->bufsize) - pos = 0; - + pos = hda_dsp_stream_get_position(hstream, substream->stream, true); found: pos = bytes_to_frames(substream->runtime, pos); diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index daeb64c495e4..d95ae17e81cc 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -707,12 +707,13 @@ bool hda_dsp_check_stream_irq(struct snd_sof_dev *sdev) } static void -hda_dsp_set_bytes_transferred(struct hdac_stream *hstream, u64 buffer_size) +hda_dsp_compr_bytes_transferred(struct hdac_stream *hstream, int direction) { + u64 buffer_size = hstream->bufsize; u64 prev_pos, pos, num_bytes; div64_u64_rem(hstream->curr_pos, buffer_size, &prev_pos); - pos = snd_hdac_stream_get_pos_posbuf(hstream); + pos = hda_dsp_stream_get_position(hstream, direction, false); if (pos < prev_pos) num_bytes = (buffer_size - prev_pos) + pos; @@ -748,8 +749,7 @@ static bool hda_dsp_stream_check(struct hdac_bus *bus, u32 status) if (s->substream && sof_hda->no_ipc_position) { snd_sof_pcm_period_elapsed(s->substream); } else if (s->cstream) { - hda_dsp_set_bytes_transferred(s, - s->cstream->runtime->buffer_size); + hda_dsp_compr_bytes_transferred(s, s->cstream->direction); snd_compr_fragment_elapsed(s->cstream); } } @@ -1009,3 +1009,89 @@ void hda_dsp_stream_free(struct snd_sof_dev *sdev) devm_kfree(sdev->dev, hda_stream); } } + +snd_pcm_uframes_t hda_dsp_stream_get_position(struct hdac_stream *hstream, + int direction, bool can_sleep) +{ + struct hdac_ext_stream *hext_stream = stream_to_hdac_ext_stream(hstream); + struct sof_intel_hda_stream *hda_stream = hstream_to_sof_hda_stream(hext_stream); + struct snd_sof_dev *sdev = hda_stream->sdev; + snd_pcm_uframes_t pos; + + switch (sof_hda_position_quirk) { + case SOF_HDA_POSITION_QUIRK_USE_SKYLAKE_LEGACY: + /* + * This legacy code, inherited from the Skylake driver, + * mixes DPIB registers and DPIB DDR updates and + * does not seem to follow any known hardware recommendations. + * It's not clear e.g. why there is a different flow + * for capture and playback, the only information that matters is + * what traffic class is used, and on all SOF-enabled platforms + * only VC0 is supported so the work-around was likely not necessary + * and quite possibly wrong. + */ + + /* DPIB/posbuf position mode: + * For Playback, Use DPIB register from HDA space which + * reflects the actual data transferred. + * For Capture, Use the position buffer for pointer, as DPIB + * is not accurate enough, its update may be completed + * earlier than the data written to DDR. + */ + if (direction == SNDRV_PCM_STREAM_PLAYBACK) { + pos = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, + AZX_REG_VS_SDXDPIB_XBASE + + (AZX_REG_VS_SDXDPIB_XINTERVAL * + hstream->index)); + } else { + /* + * For capture stream, we need more workaround to fix the + * position incorrect issue: + * + * 1. Wait at least 20us before reading position buffer after + * the interrupt generated(IOC), to make sure position update + * happens on frame boundary i.e. 20.833uSec for 48KHz. + * 2. Perform a dummy Read to DPIB register to flush DMA + * position value. + * 3. Read the DMA Position from posbuf. Now the readback + * value should be >= period boundary. + */ + if (can_sleep) + usleep_range(20, 21); + + snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, + AZX_REG_VS_SDXDPIB_XBASE + + (AZX_REG_VS_SDXDPIB_XINTERVAL * + hstream->index)); + pos = snd_hdac_stream_get_pos_posbuf(hstream); + } + break; + case SOF_HDA_POSITION_QUIRK_USE_DPIB_REGISTERS: + /* + * In case VC1 traffic is disabled this is the recommended option + */ + pos = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, + AZX_REG_VS_SDXDPIB_XBASE + + (AZX_REG_VS_SDXDPIB_XINTERVAL * + hstream->index)); + break; + case SOF_HDA_POSITION_QUIRK_USE_DPIB_DDR_UPDATE: + /* + * This is the recommended option when VC1 is enabled. + * While this isn't needed for SOF platforms it's added for + * consistency and debug. + */ + pos = snd_hdac_stream_get_pos_posbuf(hstream); + break; + default: + dev_err_once(sdev->dev, "hda_position_quirk value %d not supported\n", + sof_hda_position_quirk); + pos = 0; + break; + } + + if (pos >= hstream->bufsize) + pos = 0; + + return pos; +} diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 3e0f7b0c586a..06476ffe96d7 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -497,6 +497,7 @@ struct sof_intel_hda_stream { */ int hda_dsp_probe(struct snd_sof_dev *sdev); int hda_dsp_remove(struct snd_sof_dev *sdev); +int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask); int hda_dsp_core_run(struct snd_sof_dev *sdev, unsigned int core_mask); int hda_dsp_enable_core(struct snd_sof_dev *sdev, unsigned int core_mask); int hda_dsp_core_reset_power_down(struct snd_sof_dev *sdev, @@ -564,6 +565,9 @@ int hda_dsp_stream_setup_bdl(struct snd_sof_dev *sdev, bool hda_dsp_check_ipc_irq(struct snd_sof_dev *sdev); bool hda_dsp_check_stream_irq(struct snd_sof_dev *sdev); +snd_pcm_uframes_t hda_dsp_stream_get_position(struct hdac_stream *hstream, + int direction, bool can_sleep); + struct hdac_ext_stream * hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags); int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag); diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c index 043554d7cb4a..10740c55294d 100644 --- a/sound/soc/sof/ipc3-topology.c +++ b/sound/soc/sof/ipc3-topology.c @@ -1577,24 +1577,23 @@ static int sof_ipc3_control_load_bytes(struct snd_sof_dev *sdev, struct snd_sof_ struct sof_ipc_ctrl_data *cdata; int ret; - scontrol->ipc_control_data = kzalloc(scontrol->max_size, GFP_KERNEL); - if (!scontrol->ipc_control_data) - return -ENOMEM; - - if (scontrol->max_size < sizeof(*cdata) || - scontrol->max_size < sizeof(struct sof_abi_hdr)) { - ret = -EINVAL; - goto err; + if (scontrol->max_size < (sizeof(*cdata) + sizeof(struct sof_abi_hdr))) { + dev_err(sdev->dev, "%s: insufficient size for a bytes control: %zu.\n", + __func__, scontrol->max_size); + return -EINVAL; } - /* init the get/put bytes data */ if (scontrol->priv_size > scontrol->max_size - sizeof(*cdata)) { - dev_err(sdev->dev, "err: bytes data size %zu exceeds max %zu.\n", + dev_err(sdev->dev, + "%s: bytes data size %zu exceeds max %zu.\n", __func__, scontrol->priv_size, scontrol->max_size - sizeof(*cdata)); - ret = -EINVAL; - goto err; + return -EINVAL; } + scontrol->ipc_control_data = kzalloc(scontrol->max_size, GFP_KERNEL); + if (!scontrol->ipc_control_data) + return -ENOMEM; + scontrol->size = sizeof(struct sof_ipc_ctrl_data) + scontrol->priv_size; cdata = scontrol->ipc_control_data; diff --git a/sound/soc/sof/mediatek/mt8186/mt8186.c b/sound/soc/sof/mediatek/mt8186/mt8186.c index 3333a0634e29..e006532caf2f 100644 --- a/sound/soc/sof/mediatek/mt8186/mt8186.c +++ b/sound/soc/sof/mediatek/mt8186/mt8186.c @@ -392,7 +392,7 @@ static int mt8186_dsp_probe(struct snd_sof_dev *sdev) PLATFORM_DEVID_NONE, pdev, sizeof(*pdev)); if (IS_ERR(priv->ipc_dev)) { - ret = IS_ERR(priv->ipc_dev); + ret = PTR_ERR(priv->ipc_dev); dev_err(sdev->dev, "failed to create mtk-adsp-ipc device\n"); goto err_adsp_off; } diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 18eb327a57f0..df740be645e8 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -23,6 +23,9 @@ static u32 snd_sof_dsp_power_target(struct snd_sof_dev *sdev) u32 target_dsp_state; switch (sdev->system_suspend_target) { + case SOF_SUSPEND_S5: + case SOF_SUSPEND_S4: + /* DSP should be in D3 if the system is suspending to S3+ */ case SOF_SUSPEND_S3: /* DSP should be in D3 if the system is suspending to S3 */ target_dsp_state = SOF_DSP_PM_D3; @@ -335,8 +338,24 @@ int snd_sof_prepare(struct device *dev) return 0; #if defined(CONFIG_ACPI) - if (acpi_target_system_state() == ACPI_STATE_S0) + switch (acpi_target_system_state()) { + case ACPI_STATE_S0: sdev->system_suspend_target = SOF_SUSPEND_S0IX; + break; + case ACPI_STATE_S1: + case ACPI_STATE_S2: + case ACPI_STATE_S3: + sdev->system_suspend_target = SOF_SUSPEND_S3; + break; + case ACPI_STATE_S4: + sdev->system_suspend_target = SOF_SUSPEND_S4; + break; + case ACPI_STATE_S5: + sdev->system_suspend_target = SOF_SUSPEND_S5; + break; + default: + break; + } #endif return 0; diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 9d7f53ff9c70..f0f3d72c0da7 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -85,6 +85,8 @@ enum sof_system_suspend_state { SOF_SUSPEND_NONE = 0, SOF_SUSPEND_S0IX, SOF_SUSPEND_S3, + SOF_SUSPEND_S4, + SOF_SUSPEND_S5, }; enum sof_dfsentry_type { diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c index fdbdfb7bce92..6a4af725aedd 100644 --- a/sound/usb/line6/pcm.c +++ b/sound/usb/line6/pcm.c @@ -552,10 +552,10 @@ int line6_init_pcm(struct usb_line6 *line6, line6pcm->max_packet_size_in = usb_maxpacket(line6->usbdev, - usb_rcvisocpipe(line6->usbdev, ep_read), 0); + usb_rcvisocpipe(line6->usbdev, ep_read)); line6pcm->max_packet_size_out = usb_maxpacket(line6->usbdev, - usb_sndisocpipe(line6->usbdev, ep_write), 1); + usb_sndisocpipe(line6->usbdev, ep_write)); if (!line6pcm->max_packet_size_in || !line6pcm->max_packet_size_out) { dev_err(line6pcm->line6->ifcdev, "cannot get proper max packet size\n"); diff --git a/sound/usb/midi.c b/sound/usb/midi.c index 344fbeadf161..bbff0923d264 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -1289,7 +1289,7 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi *umidi, pipe = usb_rcvintpipe(umidi->dev, ep_info->in_ep); else pipe = usb_rcvbulkpipe(umidi->dev, ep_info->in_ep); - length = usb_maxpacket(umidi->dev, pipe, 0); + length = usb_maxpacket(umidi->dev, pipe); for (i = 0; i < INPUT_URBS; ++i) { buffer = usb_alloc_coherent(umidi->dev, length, GFP_KERNEL, &ep->urbs[i]->transfer_dma); @@ -1378,7 +1378,7 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi, pipe = usb_sndbulkpipe(umidi->dev, ep_info->out_ep); switch (umidi->usb_id) { default: - ep->max_transfer = usb_maxpacket(umidi->dev, pipe, 1); + ep->max_transfer = usb_maxpacket(umidi->dev, pipe); break; /* * Various chips declare a packet size larger than 4 bytes, but diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c index 9d0e44793896..a4d32e8a1d36 100644 --- a/sound/usb/usx2y/usb_stream.c +++ b/sound/usb/usx2y/usb_stream.c @@ -51,7 +51,7 @@ static int init_pipe_urbs(struct usb_stream_kernel *sk, { int u, p; int maxpacket = use_packsize ? - use_packsize : usb_maxpacket(dev, pipe, usb_pipeout(pipe)); + use_packsize : usb_maxpacket(dev, pipe); int transfer_length = maxpacket * sk->n_o_ps; for (u = 0; u < USB_STREAM_NURBS; @@ -171,7 +171,7 @@ struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk, out_pipe = usb_sndisocpipe(dev, out_endpoint); max_packsize = use_packsize ? - use_packsize : usb_maxpacket(dev, in_pipe, 0); + use_packsize : usb_maxpacket(dev, in_pipe); /* t_period = period_frames / sample_rate @@ -187,7 +187,7 @@ struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk, read_size += packets * USB_STREAM_URBDEPTH * (max_packsize + sizeof(struct usb_stream_packet)); - max_packsize = usb_maxpacket(dev, out_pipe, 1); + max_packsize = usb_maxpacket(dev, out_pipe); write_size = max_packsize * packets * USB_STREAM_URBDEPTH; if (read_size >= 256*PAGE_SIZE || write_size >= 256*PAGE_SIZE) { diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index cfc1ea53978d..9cd5e3aae4f7 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c @@ -421,7 +421,7 @@ static int usx2y_urbs_allocate(struct snd_usx2y_substream *subs) pipe = is_playback ? usb_sndisocpipe(dev, subs->endpoint) : usb_rcvisocpipe(dev, subs->endpoint); - subs->maxpacksize = usb_maxpacket(dev, pipe, is_playback); + subs->maxpacksize = usb_maxpacket(dev, pipe); if (!subs->maxpacksize) return -EINVAL; diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index db83522c1b49..240349b644f3 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c @@ -321,7 +321,7 @@ static int usx2y_usbpcm_urbs_allocate(struct snd_usx2y_substream *subs) pipe = is_playback ? usb_sndisocpipe(dev, subs->endpoint) : usb_rcvisocpipe(dev, subs->endpoint); - subs->maxpacksize = usb_maxpacket(dev, pipe, is_playback); + subs->maxpacksize = usb_maxpacket(dev, pipe); if (!subs->maxpacksize) return -EINVAL; diff --git a/sound/xen/xen_snd_front_evtchnl.c b/sound/xen/xen_snd_front_evtchnl.c index ecbc294fc59a..26d1b3987887 100644 --- a/sound/xen/xen_snd_front_evtchnl.c +++ b/sound/xen/xen_snd_front_evtchnl.c @@ -143,12 +143,12 @@ void xen_snd_front_evtchnl_flush(struct xen_snd_front_evtchnl *channel) static void evtchnl_free(struct xen_snd_front_info *front_info, struct xen_snd_front_evtchnl *channel) { - unsigned long page = 0; + void *page = NULL; if (channel->type == EVTCHNL_TYPE_REQ) - page = (unsigned long)channel->u.req.ring.sring; + page = channel->u.req.ring.sring; else if (channel->type == EVTCHNL_TYPE_EVT) - page = (unsigned long)channel->u.evt.page; + page = channel->u.evt.page; if (!page) return; @@ -167,10 +167,7 @@ static void evtchnl_free(struct xen_snd_front_info *front_info, xenbus_free_evtchn(front_info->xb_dev, channel->port); /* End access and free the page. */ - if (channel->gref != GRANT_INVALID_REF) - gnttab_end_foreign_access(channel->gref, page); - else - free_page(page); + xenbus_teardown_ring(&page, 1, &channel->gref); memset(channel, 0, sizeof(*channel)); } @@ -196,8 +193,7 @@ static int evtchnl_alloc(struct xen_snd_front_info *front_info, int index, enum xen_snd_front_evtchnl_type type) { struct xenbus_device *xb_dev = front_info->xb_dev; - unsigned long page; - grant_ref_t gref; + void *page; irq_handler_t handler; char *handler_name = NULL; int ret; @@ -207,12 +203,9 @@ static int evtchnl_alloc(struct xen_snd_front_info *front_info, int index, channel->index = index; channel->front_info = front_info; channel->state = EVTCHNL_STATE_DISCONNECTED; - channel->gref = GRANT_INVALID_REF; - page = get_zeroed_page(GFP_KERNEL); - if (!page) { - ret = -ENOMEM; + ret = xenbus_setup_ring(xb_dev, GFP_KERNEL, &page, 1, &channel->gref); + if (ret) goto fail; - } handler_name = kasprintf(GFP_KERNEL, "%s-%s", XENSND_DRIVER_NAME, type == EVTCHNL_TYPE_REQ ? @@ -226,33 +219,18 @@ static int evtchnl_alloc(struct xen_snd_front_info *front_info, int index, mutex_init(&channel->ring_io_lock); if (type == EVTCHNL_TYPE_REQ) { - struct xen_sndif_sring *sring = (struct xen_sndif_sring *)page; + struct xen_sndif_sring *sring = page; init_completion(&channel->u.req.completion); mutex_init(&channel->u.req.req_io_lock); - SHARED_RING_INIT(sring); - FRONT_RING_INIT(&channel->u.req.ring, sring, XEN_PAGE_SIZE); - - ret = xenbus_grant_ring(xb_dev, sring, 1, &gref); - if (ret < 0) { - channel->u.req.ring.sring = NULL; - goto fail; - } + XEN_FRONT_RING_INIT(&channel->u.req.ring, sring, XEN_PAGE_SIZE); handler = evtchnl_interrupt_req; } else { - ret = gnttab_grant_foreign_access(xb_dev->otherend_id, - virt_to_gfn((void *)page), 0); - if (ret < 0) - goto fail; - - channel->u.evt.page = (struct xensnd_event_page *)page; - gref = ret; + channel->u.evt.page = page; handler = evtchnl_interrupt_evt; } - channel->gref = gref; - ret = xenbus_alloc_evtchn(xb_dev, &channel->port); if (ret < 0) goto fail; @@ -279,8 +257,6 @@ static int evtchnl_alloc(struct xen_snd_front_info *front_info, int index, return 0; fail: - if (page) - free_page(page); kfree(handler_name); dev_err(&xb_dev->dev, "Failed to allocate ring: %d\n", ret); return ret; diff --git a/sound/xen/xen_snd_front_evtchnl.h b/sound/xen/xen_snd_front_evtchnl.h index cbe51fd1ec15..3675fba70564 100644 --- a/sound/xen/xen_snd_front_evtchnl.h +++ b/sound/xen/xen_snd_front_evtchnl.h @@ -15,15 +15,6 @@ struct xen_snd_front_info; -#ifndef GRANT_INVALID_REF -/* - * FIXME: usage of grant reference 0 as invalid grant reference: - * grant reference 0 is valid, but never exposed to a PV driver, - * because of the fact it is already in use/reserved by the PV console. - */ -#define GRANT_INVALID_REF 0 -#endif - /* Timeout in ms to wait for backend to respond. */ #define VSND_WAIT_BACK_MS 3000 |