aboutsummaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-04-07 08:53:38 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-07 08:53:38 -0700
commit81d91acf8c093565f65383ae0349b9255fbb2d0d (patch)
tree4e72f779a88ab87b76afb3fb16adf053e7044071 /sound
parent132ea5e9aa9ce13f62ba45db8e43ec887d1106e9 (diff)
parent0dd7b0cbb2e426553f184f5aeba40a2203f33700 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6: (36 commits) ALSA: hda - Add VREF powerdown sequence for another board ALSA: oss - volume control for CSWITCH and CROUTE ALSA: hda - add missing comma in ad1884_slave_vols sound: usb-audio: allow period sizes less than 1 ms sound: usb-audio: save data packet interval in audioformat structure sound: usb-audio: remove check_hw_params_convention() sound: usb-audio: show sample format width in proc file ASoC: fsl_dma: Pass the proper device for dma mapping routines ASoC: Fix null dereference in ak4535_remove() ALSA: hda - enable SPDIF output for Intel DX58SO board ALSA: snd-atmel-abdac: increase periods_min to 6 instead of 4 ALSA: snd-atmel-abdac: replace bus_id with dev_name() ALSA: snd-atmel-ac97c: replace bus_id with dev_name() ALSA: snd-atmel-ac97c: cleanup registers when removing driver ALSA: snd-atmel-ac97c: do a proper reset of the external codec ALSA: snd-atmel-ac97c: enable interrupts to catch events for error reporting ALSA: snd-atmel-ac97c: set correct size for buffer hardware parameter ALSA: snd-atmel-ac97c: do not overwrite OCA and ICA when assigning channels ALSA: snd-atmel-ac97c: remove dead break statements after return in switch case ALSA: snd-atmel-ac97c: cleanup register definitions ...
Diffstat (limited to 'sound')
-rw-r--r--sound/arm/pxa2xx-ac97-lib.c15
-rw-r--r--sound/atmel/abdac.c4
-rw-r--r--sound/atmel/ac97c.c128
-rw-r--r--sound/atmel/ac97c.h14
-rw-r--r--sound/core/oss/mixer_oss.c8
-rw-r--r--sound/isa/opl3sa2.c1
-rw-r--r--sound/pci/hda/patch_analog.c2
-rw-r--r--sound/pci/hda/patch_realtek.c5
-rw-r--r--sound/pci/hda/patch_sigmatel.c20
-rw-r--r--sound/ppc/powermac.c2
-rw-r--r--sound/soc/codecs/ak4535.c3
-rw-r--r--sound/soc/codecs/twl4030.c59
-rw-r--r--sound/soc/codecs/twl4030.h1
-rw-r--r--sound/soc/codecs/wm9705.c37
-rw-r--r--sound/soc/fsl/fsl_dma.c29
-rw-r--r--sound/soc/fsl/fsl_ssi.c99
-rw-r--r--sound/soc/omap/omap-mcbsp.c11
-rw-r--r--sound/soc/pxa/Kconfig10
-rw-r--r--sound/soc/pxa/Makefile2
-rw-r--r--sound/soc/pxa/magician.c560
-rw-r--r--sound/soc/pxa/pxa-ssp.c12
-rw-r--r--sound/soc/soc-core.c20
-rw-r--r--sound/usb/usbaudio.c255
23 files changed, 1062 insertions, 235 deletions
diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c
index 7793d2a511c..0afd1a8226f 100644
--- a/sound/arm/pxa2xx-ac97-lib.c
+++ b/sound/arm/pxa2xx-ac97-lib.c
@@ -238,6 +238,8 @@ static inline void pxa_ac97_cold_pxa3xx(void)
bool pxa2xx_ac97_try_warm_reset(struct snd_ac97 *ac97)
{
+ unsigned long gsr;
+
#ifdef CONFIG_PXA25x
if (cpu_is_pxa25x())
pxa_ac97_warm_pxa25x();
@@ -254,10 +256,10 @@ bool pxa2xx_ac97_try_warm_reset(struct snd_ac97 *ac97)
else
#endif
BUG();
-
- if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) {
+ gsr = GSR | gsr_bits;
+ if (!(gsr & (GSR_PCR | GSR_SCR))) {
printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n",
- __func__, gsr_bits);
+ __func__, gsr);
return false;
}
@@ -268,6 +270,8 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_try_warm_reset);
bool pxa2xx_ac97_try_cold_reset(struct snd_ac97 *ac97)
{
+ unsigned long gsr;
+
#ifdef CONFIG_PXA25x
if (cpu_is_pxa25x())
pxa_ac97_cold_pxa25x();
@@ -285,9 +289,10 @@ bool pxa2xx_ac97_try_cold_reset(struct snd_ac97 *ac97)
#endif
BUG();
- if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) {
+ gsr = GSR | gsr_bits;
+ if (!(gsr & (GSR_PCR | GSR_SCR))) {
printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n",
- __func__, gsr_bits);
+ __func__, gsr);
return false;
}
diff --git a/sound/atmel/abdac.c b/sound/atmel/abdac.c
index 28b3c7f7cfe..f2f41c85422 100644
--- a/sound/atmel/abdac.c
+++ b/sound/atmel/abdac.c
@@ -165,7 +165,7 @@ static struct snd_pcm_hardware atmel_abdac_hw = {
.buffer_bytes_max = 64 * 4096,
.period_bytes_min = 4096,
.period_bytes_max = 4096,
- .periods_min = 4,
+ .periods_min = 6,
.periods_max = 64,
};
@@ -502,7 +502,7 @@ static int __devinit atmel_abdac_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, card);
dev_info(&pdev->dev, "Atmel ABDAC at 0x%p using %s\n",
- dac->regs, dac->dma.chan->dev->device.bus_id);
+ dac->regs, dev_name(&dac->dma.chan->dev->device));
return retval;
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c
index dd72e00e5ae..0c0f8771656 100644
--- a/sound/atmel/ac97c.c
+++ b/sound/atmel/ac97c.c
@@ -1,5 +1,5 @@
/*
- * Driver for the Atmel AC97C controller
+ * Driver for Atmel AC97C
*
* Copyright (C) 2005-2009 Atmel Corporation
*
@@ -10,6 +10,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/bitmap.h>
+#include <linux/device.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/init.h>
@@ -65,6 +66,7 @@ struct atmel_ac97c {
/* Serialize access to opened variable */
spinlock_t lock;
void __iomem *regs;
+ int irq;
int opened;
int reset_pin;
};
@@ -150,10 +152,10 @@ static struct snd_pcm_hardware atmel_ac97c_hw = {
.rate_max = 48000,
.channels_min = 1,
.channels_max = 2,
- .buffer_bytes_max = 64 * 4096,
+ .buffer_bytes_max = 2 * 2 * 64 * 2048,
.period_bytes_min = 4096,
.period_bytes_max = 4096,
- .periods_min = 4,
+ .periods_min = 6,
.periods_max = 64,
};
@@ -297,9 +299,11 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream)
{
struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
- unsigned long word = 0;
+ unsigned long word = ac97c_readl(chip, OCA);
int retval;
+ word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT));
+
/* assign channels to AC97C channel A */
switch (runtime->channels) {
case 1:
@@ -312,7 +316,6 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream)
default:
/* TODO: support more than two channels */
return -EINVAL;
- break;
}
ac97c_writel(chip, OCA, word);
@@ -324,13 +327,25 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream)
word |= AC97C_CMR_CEM_LITTLE;
break;
case SNDRV_PCM_FORMAT_S16_BE: /* fall through */
- default:
word &= ~(AC97C_CMR_CEM_LITTLE);
break;
+ default:
+ word = ac97c_readl(chip, OCA);
+ word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT));
+ ac97c_writel(chip, OCA, word);
+ return -EINVAL;
}
+ /* Enable underrun interrupt on channel A */
+ word |= AC97C_CSR_UNRUN;
+
ac97c_writel(chip, CAMR, word);
+ /* Enable channel A event interrupt */
+ word = ac97c_readl(chip, IMR);
+ word |= AC97C_SR_CAEVT;
+ ac97c_writel(chip, IER, word);
+
/* set variable rate if needed */
if (runtime->rate != 48000) {
word = ac97c_readl(chip, MR);
@@ -359,9 +374,11 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream)
{
struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
- unsigned long word = 0;
+ unsigned long word = ac97c_readl(chip, ICA);
int retval;
+ word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT));
+
/* assign channels to AC97C channel A */
switch (runtime->channels) {
case 1:
@@ -374,7 +391,6 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream)
default:
/* TODO: support more than two channels */
return -EINVAL;
- break;
}
ac97c_writel(chip, ICA, word);
@@ -386,13 +402,25 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream)
word |= AC97C_CMR_CEM_LITTLE;
break;
case SNDRV_PCM_FORMAT_S16_BE: /* fall through */
- default:
word &= ~(AC97C_CMR_CEM_LITTLE);
break;
+ default:
+ word = ac97c_readl(chip, ICA);
+ word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT));
+ ac97c_writel(chip, ICA, word);
+ return -EINVAL;
}
+ /* Enable overrun interrupt on channel A */
+ word |= AC97C_CSR_OVRUN;
+
ac97c_writel(chip, CAMR, word);
+ /* Enable channel A event interrupt */
+ word = ac97c_readl(chip, IMR);
+ word |= AC97C_SR_CAEVT;
+ ac97c_writel(chip, IER, word);
+
/* set variable rate if needed */
if (runtime->rate != 48000) {
word = ac97c_readl(chip, MR);
@@ -543,6 +571,43 @@ static struct snd_pcm_ops atmel_ac97_capture_ops = {
.pointer = atmel_ac97c_capture_pointer,
};
+static irqreturn_t atmel_ac97c_interrupt(int irq, void *dev)
+{
+ struct atmel_ac97c *chip = (struct atmel_ac97c *)dev;
+ irqreturn_t retval = IRQ_NONE;
+ u32 sr = ac97c_readl(chip, SR);
+ u32 casr = ac97c_readl(chip, CASR);
+ u32 cosr = ac97c_readl(chip, COSR);
+
+ if (sr & AC97C_SR_CAEVT) {
+ dev_info(&chip->pdev->dev, "channel A event%s%s%s%s%s%s\n",
+ casr & AC97C_CSR_OVRUN ? " OVRUN" : "",
+ casr & AC97C_CSR_RXRDY ? " RXRDY" : "",
+ casr & AC97C_CSR_UNRUN ? " UNRUN" : "",
+ casr & AC97C_CSR_TXEMPTY ? " TXEMPTY" : "",
+ casr & AC97C_CSR_TXRDY ? " TXRDY" : "",
+ !casr ? " NONE" : "");
+ retval = IRQ_HANDLED;
+ }
+
+ if (sr & AC97C_SR_COEVT) {
+ dev_info(&chip->pdev->dev, "codec channel event%s%s%s%s%s\n",
+ cosr & AC97C_CSR_OVRUN ? " OVRUN" : "",
+ cosr & AC97C_CSR_RXRDY ? " RXRDY" : "",
+ cosr & AC97C_CSR_TXEMPTY ? " TXEMPTY" : "",
+ cosr & AC97C_CSR_TXRDY ? " TXRDY" : "",
+ !cosr ? " NONE" : "");
+ retval = IRQ_HANDLED;
+ }
+
+ if (retval == IRQ_NONE) {
+ dev_err(&chip->pdev->dev, "spurious interrupt sr 0x%08x "
+ "casr 0x%08x cosr 0x%08x\n", sr, casr, cosr);
+ }
+
+ return retval;
+}
+
static int __devinit atmel_ac97c_pcm_new(struct atmel_ac97c *chip)
{
struct snd_pcm *pcm;
@@ -665,17 +730,17 @@ static bool filter(struct dma_chan *chan, void *slave)
static void atmel_ac97c_reset(struct atmel_ac97c *chip)
{
- ac97c_writel(chip, MR, AC97C_MR_WRST);
+ ac97c_writel(chip, MR, 0);
+ ac97c_writel(chip, MR, AC97C_MR_ENA);
+ ac97c_writel(chip, CAMR, 0);
+ ac97c_writel(chip, COMR, 0);
if (gpio_is_valid(chip->reset_pin)) {
gpio_set_value(chip->reset_pin, 0);
/* AC97 v2.2 specifications says minimum 1 us. */
- udelay(10);
+ udelay(2);
gpio_set_value(chip->reset_pin, 1);
}
-
- udelay(1);
- ac97c_writel(chip, MR, AC97C_MR_ENA);
}
static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
@@ -690,6 +755,7 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
.read = atmel_ac97c_read,
};
int retval;
+ int irq;
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!regs) {
@@ -703,6 +769,12 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
return -ENXIO;
}
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_dbg(&pdev->dev, "could not get irq\n");
+ return -ENXIO;
+ }
+
pclk = clk_get(&pdev->dev, "pclk");
if (IS_ERR(pclk)) {
dev_dbg(&pdev->dev, "no peripheral clock\n");
@@ -719,6 +791,13 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
chip = get_chip(card);
+ retval = request_irq(irq, atmel_ac97c_interrupt, 0, "AC97C", chip);
+ if (retval) {
+ dev_dbg(&pdev->dev, "unable to request irq %d\n", irq);
+ goto err_request_irq;
+ }
+ chip->irq = irq;
+
spin_lock_init(&chip->lock);
strcpy(card->driver, "Atmel AC97C");
@@ -747,14 +826,18 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
snd_card_set_dev(card, &pdev->dev);
+ atmel_ac97c_reset(chip);
+
+ /* Enable overrun interrupt from codec channel */
+ ac97c_writel(chip, COMR, AC97C_CSR_OVRUN);
+ ac97c_writel(chip, IER, ac97c_readl(chip, IMR) | AC97C_SR_COEVT);
+
retval = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus);
if (retval) {
dev_dbg(&pdev->dev, "could not register on ac97 bus\n");
goto err_ac97_bus;
}
- atmel_ac97c_reset(chip);
-
retval = atmel_ac97c_mixer_new(chip);
if (retval) {
dev_dbg(&pdev->dev, "could not register ac97 mixer\n");
@@ -773,7 +856,7 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
chip->dma.rx_chan = dma_request_channel(mask, filter, dws);
dev_info(&chip->pdev->dev, "using %s for DMA RX\n",
- chip->dma.rx_chan->dev->device.bus_id);
+ dev_name(&chip->dma.rx_chan->dev->device));
set_bit(DMA_RX_CHAN_PRESENT, &chip->flags);
}
@@ -789,7 +872,7 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
chip->dma.tx_chan = dma_request_channel(mask, filter, dws);
dev_info(&chip->pdev->dev, "using %s for DMA TX\n",
- chip->dma.tx_chan->dev->device.bus_id);
+ dev_name(&chip->dma.tx_chan->dev->device));
set_bit(DMA_TX_CHAN_PRESENT, &chip->flags);
}
@@ -809,7 +892,7 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
retval = snd_card_register(card);
if (retval) {
dev_dbg(&pdev->dev, "could not register sound card\n");
- goto err_ac97_bus;
+ goto err_dma;
}
platform_set_drvdata(pdev, card);
@@ -836,6 +919,8 @@ err_ac97_bus:
iounmap(chip->regs);
err_ioremap:
+ free_irq(irq, chip);
+err_request_irq:
snd_card_free(card);
err_snd_card_new:
clk_disable(pclk);
@@ -884,9 +969,14 @@ static int __devexit atmel_ac97c_remove(struct platform_device *pdev)
if (gpio_is_valid(chip->reset_pin))
gpio_free(chip->reset_pin);
+ ac97c_writel(chip, CAMR, 0);
+ ac97c_writel(chip, COMR, 0);
+ ac97c_writel(chip, MR, 0);
+
clk_disable(chip->pclk);
clk_put(chip->pclk);
iounmap(chip->regs);
+ free_irq(chip->irq, chip);
if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags))
dma_release_channel(chip->dma.rx_chan);
diff --git a/sound/atmel/ac97c.h b/sound/atmel/ac97c.h
index c17bd582598..ecbba5021c8 100644
--- a/sound/atmel/ac97c.h
+++ b/sound/atmel/ac97c.h
@@ -1,5 +1,5 @@
/*
- * Register definitions for the Atmel AC97C controller
+ * Register definitions for Atmel AC97C
*
* Copyright (C) 2005-2009 Atmel Corporation
*
@@ -17,10 +17,6 @@
#define AC97C_CATHR 0x24
#define AC97C_CASR 0x28
#define AC97C_CAMR 0x2c
-#define AC97C_CBRHR 0x30
-#define AC97C_CBTHR 0x34
-#define AC97C_CBSR 0x38
-#define AC97C_CBMR 0x3c
#define AC97C_CORHR 0x40
#define AC97C_COTHR 0x44
#define AC97C_COSR 0x48
@@ -46,8 +42,10 @@
#define AC97C_MR_VRA (1 << 2)
#define AC97C_CSR_TXRDY (1 << 0)
+#define AC97C_CSR_TXEMPTY (1 << 1)
#define AC97C_CSR_UNRUN (1 << 2)
#define AC97C_CSR_RXRDY (1 << 4)
+#define AC97C_CSR_OVRUN (1 << 5)
#define AC97C_CSR_ENDTX (1 << 10)
#define AC97C_CSR_ENDRX (1 << 14)
@@ -61,11 +59,15 @@
#define AC97C_CMR_DMAEN (1 << 22)
#define AC97C_SR_CAEVT (1 << 3)
+#define AC97C_SR_COEVT (1 << 2)
+#define AC97C_SR_WKUP (1 << 1)
+#define AC97C_SR_SOF (1 << 0)
+#define AC97C_CH_MASK(slot) \
+ (0x7 << (3 * (AC97_SLOT_##slot - 3)))
#define AC97C_CH_ASSIGN(slot, channel) \
(AC97C_CHANNEL_##channel << (3 * (AC97_SLOT_##slot - 3)))
#define AC97C_CHANNEL_NONE 0x0
#define AC97C_CHANNEL_A 0x1
-#define AC97C_CHANNEL_B 0x2
#endif /* __SOUND_ATMEL_AC97C_H */
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index e570649184e..5dcd8a52697 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -703,19 +703,27 @@ static int snd_mixer_oss_put_volume1(struct snd_mixer_oss_file *fmixer,
if (left || right) {
if (slot->present & SNDRV_MIXER_OSS_PRESENT_PSWITCH)
snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PSWITCH], left, right, 0);
+ if (slot->present & SNDRV_MIXER_OSS_PRESENT_CSWITCH)
+ snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CSWITCH], left, right, 0);
if (slot->present & SNDRV_MIXER_OSS_PRESENT_GSWITCH)
snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GSWITCH], left, right, 0);
if (slot->present & SNDRV_MIXER_OSS_PRESENT_PROUTE)
snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PROUTE], left, right, 1);
+ if (slot->present & SNDRV_MIXER_OSS_PRESENT_CROUTE)
+ snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CROUTE], left, right, 1);
if (slot->present & SNDRV_MIXER_OSS_PRESENT_GROUTE)
snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GROUTE], left, right, 1);
} else {
if (slot->present & SNDRV_MIXER_OSS_PRESENT_PSWITCH) {
snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PSWITCH], left, right, 0);
+ } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_CSWITCH) {
+ snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CSWITCH], left, right, 0);
} else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GSWITCH) {
snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GSWITCH], left, right, 0);
} else if (slot->present & SNDRV_MIXER_OSS_PRESENT_PROUTE) {
snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PROUTE], left, right, 1);
+ } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_CROUTE) {
+ snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CROUTE], left, right, 1);
} else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GROUTE) {
snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GROUTE], left, right, 1);
}
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index ef95279da7a..0481a55334b 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -481,6 +481,7 @@ OPL3SA2_DOUBLE_TLV("Master Playback Volume", 0, 0x07, 0x08, 0, 0, 15, 1,
OPL3SA2_SINGLE("Mic Playback Switch", 0, 0x09, 7, 1, 1),
OPL3SA2_SINGLE_TLV("Mic Playback Volume", 0, 0x09, 0, 31, 1,
db_scale_5bit_12db_max),
+OPL3SA2_SINGLE("ZV Port Switch", 0, 0x02, 0, 1, 0),
};
static struct snd_kcontrol_new snd_opl3sa2_tone_controls[] = {
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 5bb48ee8b6c..38ad3f7b040 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -3256,7 +3256,7 @@ static const char *ad1884_slave_vols[] = {
"Mic Playback Volume",
"CD Playback Volume",
"Internal Mic Playback Volume",
- "Docking Mic Playback Volume"
+ "Docking Mic Playback Volume",
/* "Beep Playback Volume", */
"IEC958 Playback Volume",
NULL
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 82097790f6f..f35e58a2d92 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -8764,6 +8764,10 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
{}
};
+static hda_nid_t alc883_slave_dig_outs[] = {
+ ALC1200_DIGOUT_NID, 0,
+};
+
static hda_nid_t alc1200_slave_dig_outs[] = {
ALC883_DIGOUT_NID, 0,
};
@@ -8809,6 +8813,7 @@ static struct alc_config_preset alc883_presets[] = {
.dac_nids = alc883_dac_nids,
.dig_out_nid = ALC883_DIGOUT_NID,
.dig_in_nid = ALC883_DIGIN_NID,
+ .slave_dig_outs = alc883_slave_dig_outs,
.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_intel_modes),
.channel_mode = alc883_3ST_6ch_intel_modes,
.need_dac_fix = 1,
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index b5e108aa8f6..61996a2f45d 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -4413,6 +4413,24 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
if (spec->num_pwrs > 0)
stac92xx_pin_sense(codec, event->nid);
stac92xx_report_jack(codec, event->nid);
+
+ switch (codec->subsystem_id) {
+ case 0x103c308f:
+ if (event->nid == 0xb) {
+ int pin = AC_PINCTL_IN_EN;
+
+ if (get_pin_presence(codec, 0xa)
+ && get_pin_presence(codec, 0xb))
+ pin |= AC_PINCTL_VREF_80;
+ if (!get_pin_presence(codec, 0xb))
+ pin |= AC_PINCTL_VREF_80;
+
+ /* toggle VREF state based on mic + hp pin
+ * status
+ */
+ stac92xx_auto_set_pinctl(codec, 0x0a, pin);
+ }
+ }
break;
case STAC_VREF_EVENT:
data = snd_hda_codec_read(codec, codec->afg, 0,
@@ -4895,6 +4913,7 @@ again:
switch (codec->vendor_id) {
case 0x111d7604:
case 0x111d7605:
+ case 0x111d76d5:
if (spec->board_config == STAC_92HD83XXX_PWR_REF)
break;
spec->num_pwrs = 0;
@@ -5707,6 +5726,7 @@ static struct hda_codec_preset snd_hda_preset_sigmatel[] = {
{ .id = 0x111d7603, .name = "92HD75B3X5", .patch = patch_stac92hd71bxx},
{ .id = 0x111d7604, .name = "92HD83C1X5", .patch = patch_stac92hd83xxx},
{ .id = 0x111d7605, .name = "92HD81B1X5", .patch = patch_stac92hd83xxx},
+ { .id = 0x111d76d5, .name = "92HD81B1C5", .patch = patch_stac92hd83xxx},
{ .id = 0x111d7608, .name = "92HD75B2X5", .patch = patch_stac92hd71bxx},
{ .id = 0x111d7674, .name = "92HD73D1X5", .patch = patch_stac92hd73xx },
{ .id = 0x111d7675, .name = "92HD73C1X5", .patch = patch_stac92hd73xx },
diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c
index 5a929069dce..a2b69b8cff4 100644
--- a/sound/ppc/powermac.c
+++ b/sound/ppc/powermac.c
@@ -51,7 +51,7 @@ static struct platform_device *device;
/*
*/
-static int __init snd_pmac_probe(struct platform_device *devptr)
+static int __devinit snd_pmac_probe(struct platform_device *devptr)
{
struct snd_card *card;
struct snd_pmac *chip;
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index 1f63d387a2f..dd338020276 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -659,7 +659,8 @@ static int ak4535_remove(struct platform_device *pdev)
snd_soc_free_pcms(socdev);
snd_soc_dapm_free(socdev);
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- i2c_unregister_device(codec->control_data);
+ if (codec->control_data)
+ i2c_unregister_device(codec->control_data);
i2c_del_driver(&ak4535_i2c_driver);
#endif
kfree(codec->private_data);
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 97738e2ece0..bfda7a88e82 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -122,6 +122,9 @@ struct twl4030_priv {
unsigned int bypass_state;
unsigned int codec_powered;
unsigned int codec_muted;
+
+ struct snd_pcm_substream *master_substream;
+ struct snd_pcm_substream *slave_substream;
};
/*
@@ -1217,6 +1220,50 @@ static int twl4030_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
+static int twl4030_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->codec;
+ struct twl4030_priv *twl4030 = codec->private_data;
+
+ /* If we already have a playback or capture going then constrain
+ * this substream to match it.
+ */
+ if (twl4030->master_substream) {
+ struct snd_pcm_runtime *master_runtime;
+ master_runtime = twl4030->master_substream->runtime;
+
+ snd_pcm_hw_constraint_minmax(substream->runtime,
+ SNDRV_PCM_HW_PARAM_RATE,
+ master_runtime->rate,
+ master_runtime->rate);
+
+ snd_pcm_hw_constraint_minmax(substream->runtime,
+ SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
+ master_runtime->sample_bits,
+ master_runtime->sample_bits);
+
+ twl4030->slave_substream = substream;
+ } else
+ twl4030->master_substream = substream;
+
+ return 0;
+}
+
+static void twl4030_shutdown(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->codec;
+ struct twl4030_priv *twl4030 = codec->private_data;
+
+ if (twl4030->master_substream == substream)
+ twl4030->master_substream = twl4030->slave_substream;
+
+ twl4030->slave_substream = NULL;
+}
+
static int twl4030_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
@@ -1224,8 +1271,13 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec;
+ struct twl4030_priv *twl4030 = codec->private_data;
u8 mode, old_mode, format, old_format;
+ if (substream == twl4030->slave_substream)
+ /* Ignoring hw_params for slave substream */
+ return 0;
+
/* bit rate */
old_mode = twl4030_read_reg_cache(codec,
TWL4030_REG_CODEC_MODE) & ~TWL4030_CODECPDZ;
@@ -1259,6 +1311,9 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
case 48000:
mode |= TWL4030_APLL_RATE_48000;
break;
+ case 96000:
+ mode |= TWL4030_APLL_RATE_96000;
+ break;
default:
printk(KERN_ERR "TWL4030 hw params: unknown rate %d\n",
params_rate(params));
@@ -1384,6 +1439,8 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai,
#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE)
static struct snd_soc_dai_ops twl4030_dai_ops = {
+ .startup = twl4030_startup,
+ .shutdown = twl4030_shutdown,
.hw_params = twl4030_hw_params,
.set_sysclk = twl4030_set_dai_sysclk,
.set_fmt = twl4030_set_dai_fmt,
@@ -1395,7 +1452,7 @@ struct snd_soc_dai twl4030_dai = {
.stream_name = "Playback",
.channels_min = 2,
.channels_max = 2,
- .rates = TWL4030_RATES,
+ .rates = TWL4030_RATES | SNDRV_PCM_RATE_96000,
.formats = TWL4030_FORMATS,},
.capture = {
.stream_name = "Capture",
diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h
index 33dbb144dad..cb63765db1d 100644
--- a/sound/soc/codecs/twl4030.h
+++ b/sound/soc/codecs/twl4030.h
@@ -109,6 +109,7 @@
#define TWL4030_APLL_RATE_32000 0x80
#define TWL4030_APLL_RATE_44100 0x90
#define TWL4030_APLL_RATE_48000 0xA0
+#define TWL4030_APLL_RATE_96000 0xE0
#define TWL4030_SEL_16K 0x04
#define TWL4030_CODECPDZ 0x02
#define TWL4030_OPT_MODE 0x01
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c
index 3265817c5c2..6e23a81dba7 100644
--- a/sound/soc/codecs/wm9705.c
+++ b/sound/soc/codecs/wm9705.c
@@ -317,6 +317,41 @@ static int wm9705_reset(struct snd_soc_codec *codec)
return -EIO;
}
+#ifdef CONFIG_PM
+static int wm9705_soc_suspend(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->card->codec;
+
+ soc_ac97_ops.write(codec->ac97, AC97_POWERDOWN, 0xffff);
+
+ return 0;
+}
+
+static int wm9705_soc_resume(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = socdev->card->codec;
+ int i, ret;
+ u16 *cache = codec->reg_cache;
+
+ ret = wm9705_reset(codec);
+ if (ret < 0) {
+ printk(KERN_ERR "could not reset AC97 codec\n");
+ return ret;
+ }
+
+ for (i = 2; i < ARRAY_SIZE(wm9705_reg) << 1; i += 2) {
+ soc_ac97_ops.write(codec->ac97, i, cache[i>>1]);
+ }
+
+ return 0;
+}
+#else
+#define wm9705_soc_suspend NULL
+#define wm9705_soc_resume NULL
+#endif
+
static int wm9705_soc_probe(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
@@ -407,6 +442,8 @@ static int wm9705_soc_remove(struct platform_device *pdev)
struct snd_soc_codec_device soc_codec_dev_wm9705 = {
.probe = wm9705_soc_probe,
.remove = wm9705_soc_remove,
+ .suspend = wm9705_soc_suspend,
+ .resume = wm9705_soc_resume,
};
EXPORT_SYMBOL_GPL(soc_codec_dev_wm9705);
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
index b3eb8570cd7..b1a3a278819 100644
--- a/sound/soc/fsl/fsl_dma.c
+++ b/sound/soc/fsl/fsl_dma.c
@@ -300,7 +300,7 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
if (!card->dev->coherent_dma_mask)
card->dev->coherent_dma_mask = fsl_dma_dmamask;
- ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->dev,
+ ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
fsl_dma_hardware.buffer_bytes_max,
&pcm->streams[0].substream->dma_buffer);
if (ret) {
@@ -310,7 +310,7 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
return -ENOMEM;
}
- ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->dev,
+ ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
fsl_dma_hardware.buffer_bytes_max,
&pcm->streams[1].substream->dma_buffer);
if (ret) {
@@ -418,7 +418,7 @@ static int fsl_dma_open(struct snd_pcm_substream *substream)
return -EBUSY;
}
- dma_private = dma_alloc_coherent(substream->pcm->dev,
+ dma_private = dma_alloc_coherent(substream->pcm->card->dev,
sizeof(struct fsl_dma_private), &ld_buf_phys, GFP_KERNEL);
if (!dma_private) {
dev_err(substream->pcm->card->dev,
@@ -445,7 +445,7 @@ static int fsl_dma_open(struct snd_pcm_substream *substream)
dev_err(substream->pcm->card->dev,
"can't register ISR for IRQ %u (ret=%i)\n",
dma_private->irq, ret);
- dma_free_coherent(substream->pcm->dev,
+ dma_free_coherent(substream->pcm->card->dev,
sizeof(struct fsl_dma_private),
dma_private, dma_private->ld_buf_phys);
return ret;
@@ -697,6 +697,23 @@ static snd_pcm_uframes_t fsl_dma_pointer(struct snd_pcm_substream *substream)
else
position = in_be32(&dma_channel->dar);
+ /*
+ * When capture is started, the SSI immediately starts to fill its FIFO.
+ * This means that the DMA controller is not started until the FIFO is
+ * full. However, ALSA calls this function before that happens, when
+ * MR.DAR is still zero. In this case, just return zero to indicate
+ * that nothing has been received yet.
+ */
+ if (!position)
+ return 0;