aboutsummaryrefslogtreecommitdiff
path: root/sound/soc
diff options
context:
space:
mode:
authorDavid Woodhouse <David.Woodhouse@intel.com>2009-06-08 12:21:27 +0100
committerDavid Woodhouse <David.Woodhouse@intel.com>2009-06-08 12:21:27 +0100
commite635a01ea0a16cf7cd31ecd2305870385dca9be6 (patch)
treec7153e7dee5caf6ac90d85694ff27e4d0b606290 /sound/soc
parent143070e74630b9557e1bb64d899ff2cc5a1dcb48 (diff)
parent947391cfbaa3b08558844c0b187bcd0223c3f660 (diff)
Merge branch 'next-mtd' of git://aeryn.fluff.org.uk/bjdooks/linux
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/codecs/wm8990.c40
-rw-r--r--sound/soc/davinci/Kconfig7
-rw-r--r--sound/soc/davinci/davinci-evm.c63
-rw-r--r--sound/soc/davinci/davinci-i2s.c26
-rw-r--r--sound/soc/davinci/davinci-pcm.c71
-rw-r--r--sound/soc/soc-core.c3
6 files changed, 144 insertions, 66 deletions
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index c518c3e5aa3..40cd274eb1e 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -729,7 +729,7 @@ SND_SOC_DAPM_MIXER_E("INMIXL", WM8990_INTDRIVBITS, WM8990_INMIXL_PWR_BIT, 0,
inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
/* AINLMUX */
-SND_SOC_DAPM_MUX_E("AILNMUX", WM8990_INTDRIVBITS, WM8990_AINLMUX_PWR_BIT, 0,
+SND_SOC_DAPM_MUX_E("AINLMUX", WM8990_INTDRIVBITS, WM8990_AINLMUX_PWR_BIT, 0,
&wm8990_dapm_ainlmux_controls, inmixer_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
@@ -740,7 +740,7 @@ SND_SOC_DAPM_MIXER_E("INMIXR", WM8990_INTDRIVBITS, WM8990_INMIXR_PWR_BIT, 0,
inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
/* AINRMUX */
-SND_SOC_DAPM_MUX_E("AIRNMUX", WM8990_INTDRIVBITS, WM8990_AINRMUX_PWR_BIT, 0,
+SND_SOC_DAPM_MUX_E("AINRMUX", WM8990_INTDRIVBITS, WM8990_AINRMUX_PWR_BIT, 0,
&wm8990_dapm_ainrmux_controls, inmixer_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
@@ -848,40 +848,40 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"LIN12 PGA", "LIN2 Switch", "LIN2"},
/* LIN34 PGA */
{"LIN34 PGA", "LIN3 Switch", "LIN3"},
- {"LIN34 PGA", "LIN4 Switch", "LIN4"},
+ {"LIN34 PGA", "LIN4 Switch", "LIN4/RXN"},
/* INMIXL */
{"INMIXL", "Record Left Volume", "LOMIX"},
{"INMIXL", "LIN2 Volume", "LIN2"},
{"INMIXL", "LINPGA12 Switch", "LIN12 PGA"},
{"INMIXL", "LINPGA34 Switch", "LIN34 PGA"},
- /* AILNMUX */
- {"AILNMUX", "INMIXL Mix", "INMIXL"},
- {"AILNMUX", "DIFFINL Mix", "LIN12PGA"},
- {"AILNMUX", "DIFFINL Mix", "LIN34PGA"},
- {"AILNMUX", "RXVOICE Mix", "LIN4/RXN"},
- {"AILNMUX", "RXVOICE Mix", "RIN4/RXP"},
+ /* AINLMUX */
+ {"AINLMUX", "INMIXL Mix", "INMIXL"},
+ {"AINLMUX", "DIFFINL Mix", "LIN12 PGA"},
+ {"AINLMUX", "DIFFINL Mix", "LIN34 PGA"},
+ {"AINLMUX", "RXVOICE Mix", "LIN4/RXN"},
+ {"AINLMUX", "RXVOICE Mix", "RIN4/RXP"},
/* ADC */
- {"Left ADC", NULL, "AILNMUX"},
+ {"Left ADC", NULL, "AINLMUX"},
/* RIN12 PGA */
{"RIN12 PGA", "RIN1 Switch", "RIN1"},
{"RIN12 PGA", "RIN2 Switch", "RIN2"},
/* RIN34 PGA */
{"RIN34 PGA", "RIN3 Switch", "RIN3"},
- {"RIN34 PGA", "RIN4 Switch", "RIN4"},
+ {"RIN34 PGA", "RIN4 Switch", "RIN4/RXP"},
/* INMIXL */
{"INMIXR", "Record Right Volume", "ROMIX"},
{"INMIXR", "RIN2 Volume", "RIN2"},
{"INMIXR", "RINPGA12 Switch", "RIN12 PGA"},
{"INMIXR", "RINPGA34 Switch", "RIN34 PGA"},
- /* AIRNMUX */
- {"AIRNMUX", "INMIXR Mix", "INMIXR"},
- {"AIRNMUX", "DIFFINR Mix", "RIN12PGA"},
- {"AIRNMUX", "DIFFINR Mix", "RIN34PGA"},
- {"AIRNMUX", "RXVOICE Mix", "RIN4/RXN"},
- {"AIRNMUX", "RXVOICE Mix", "RIN4/RXP"},
+ /* AINRMUX */
+ {"AINRMUX", "INMIXR Mix", "INMIXR"},
+ {"AINRMUX", "DIFFINR Mix", "RIN12 PGA"},
+ {"AINRMUX", "DIFFINR Mix", "RIN34 PGA"},
+ {"AINRMUX", "RXVOICE Mix", "LIN4/RXN"},
+ {"AINRMUX", "RXVOICE Mix", "RIN4/RXP"},
/* ADC */
- {"Right ADC", NULL, "AIRNMUX"},
+ {"Right ADC", NULL, "AINRMUX"},
/* LOMIX */
{"LOMIX", "LOMIX RIN3 Bypass Switch", "RIN3"},
@@ -922,7 +922,7 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"LOPMIX", "LOPMIX Left Mixer PGA Switch", "LOPGA"},
/* OUT3MIX */
- {"OUT3MIX", "OUT3MIX LIN4/RXP Bypass Switch", "LIN4/RXP"},
+ {"OUT3MIX", "OUT3MIX LIN4/RXP Bypass Switch", "LIN4/RXN"},
{"OUT3MIX", "OUT3MIX Left Out PGA Switch", "LOPGA"},
/* OUT4MIX */
@@ -949,7 +949,7 @@ static const struct snd_soc_dapm_route audio_map[] = {
/* Output Pins */
{"LON", NULL, "LONMIX"},
{"LOP", NULL, "LOPMIX"},
- {"OUT", NULL, "OUT3MIX"},
+ {"OUT3", NULL, "OUT3MIX"},
{"LOUT", NULL, "LOUT PGA"},
{"SPKN", NULL, "SPKMIX"},
{"ROUT", NULL, "ROUT PGA"},
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig
index bd7392c9657..411a710be66 100644
--- a/sound/soc/davinci/Kconfig
+++ b/sound/soc/davinci/Kconfig
@@ -10,13 +10,14 @@ config SND_DAVINCI_SOC_I2S
tristate
config SND_DAVINCI_SOC_EVM
- tristate "SoC Audio support for DaVinci EVM"
- depends on SND_DAVINCI_SOC && MACH_DAVINCI_EVM
+ tristate "SoC Audio support for DaVinci DM6446 or DM355 EVM"
+ depends on SND_DAVINCI_SOC
+ depends on MACH_DAVINCI_EVM || MACH_DAVINCI_DM355_EVM
select SND_DAVINCI_SOC_I2S
select SND_SOC_TLV320AIC3X
help
Say Y if you want to add support for SoC audio on TI
- DaVinci EVM platform.
+ DaVinci DM6446 or DM355 EVM platforms.
config SND_DAVINCI_SOC_SFFSDR
tristate "SoC Audio support for SFFSDR"
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index 9b90b347007..58fd1cbedd8 100644
--- a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -20,7 +20,11 @@
#include <sound/soc-dapm.h>
#include <asm/dma.h>
-#include <mach/hardware.h>
+#include <asm/mach-types.h>
+
+#include <mach/asp.h>
+#include <mach/edma.h>
+#include <mach/mux.h>
#include "../codecs/tlv320aic3x.h"
#include "davinci-pcm.h"
@@ -150,7 +154,7 @@ static struct snd_soc_card snd_soc_card_evm = {
/* evm audio private data */
static struct aic3x_setup_data evm_aic3x_setup = {
- .i2c_bus = 0,
+ .i2c_bus = 1,
.i2c_address = 0x1b,
};
@@ -161,36 +165,73 @@ static struct snd_soc_device evm_snd_devdata = {
.codec_data = &evm_aic3x_setup,
};
+/* DM6446 EVM uses ASP0; line-out is a pair of RCA jacks */
static struct resource evm_snd_resources[] = {
{
- .start = DAVINCI_MCBSP_BASE,
- .end = DAVINCI_MCBSP_BASE + SZ_8K - 1,
+ .start = DAVINCI_ASP0_BASE,
+ .end = DAVINCI_ASP0_BASE + SZ_8K - 1,
.flags = IORESOURCE_MEM,
},
};
static struct evm_snd_platform_data evm_snd_data = {
- .tx_dma_ch = DM644X_DMACH_MCBSP_TX,
- .rx_dma_ch = DM644X_DMACH_MCBSP_RX,
+ .tx_dma_ch = DAVINCI_DMA_ASP0_TX,
+ .rx_dma_ch = DAVINCI_DMA_ASP0_RX,
+};
+
+/* DM335 EVM uses ASP1; line-out is a stereo mini-jack */
+static struct resource dm335evm_snd_resources[] = {
+ {
+ .start = DAVINCI_ASP1_BASE,
+ .end = DAVINCI_ASP1_BASE + SZ_8K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct evm_snd_platform_data dm335evm_snd_data = {
+ .tx_dma_ch = DAVINCI_DMA_ASP1_TX,
+ .rx_dma_ch = DAVINCI_DMA_ASP1_RX,
};
static struct platform_device *evm_snd_device;
static int __init evm_init(void)
{
+ struct resource *resources;
+ unsigned num_resources;
+ struct evm_snd_platform_data *data;
+ int index;
int ret;
- evm_snd_device = platform_device_alloc("soc-audio", 0);
+ if (machine_is_davinci_evm()) {
+ davinci_cfg_reg(DM644X_MCBSP);
+
+ resources = evm_snd_resources;
+ num_resources = ARRAY_SIZE(evm_snd_resources);
+ data = &evm_snd_data;
+ index = 0;
+ } else if (machine_is_davinci_dm355_evm()) {
+ /* we don't use ASP1 IRQs, or we'd need to mux them ... */
+ davinci_cfg_reg(DM355_EVT8_ASP1_TX);
+ davinci_cfg_reg(DM355_EVT9_ASP1_RX);
+
+ resources = dm335evm_snd_resources;
+ num_resources = ARRAY_SIZE(dm335evm_snd_resources);
+ data = &dm335evm_snd_data;
+ index = 1;
+ } else
+ return -EINVAL;
+
+ evm_snd_device = platform_device_alloc("soc-audio", index);
if (!evm_snd_device)
return -ENOMEM;
platform_set_drvdata(evm_snd_device, &evm_snd_devdata);
evm_snd_devdata.dev = &evm_snd_device->dev;
- platform_device_add_data(evm_snd_device, &evm_snd_data,
- sizeof(evm_snd_data));
+ platform_device_add_data(evm_snd_device, data, sizeof(*data));
- ret = platform_device_add_resources(evm_snd_device, evm_snd_resources,
- ARRAY_SIZE(evm_snd_resources));
+ ret = platform_device_add_resources(evm_snd_device, resources,
+ num_resources);
if (ret) {
platform_device_put(evm_snd_device);
return ret;
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index ffdb9439d3d..b1ea52fc83c 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -24,6 +24,26 @@
#include "davinci-pcm.h"
+
+/*
+ * NOTE: terminology here is confusing.
+ *
+ * - This driver supports the "Audio Serial Port" (ASP),
+ * found on dm6446, dm355, and other DaVinci chips.
+ *
+ * - But it labels it a "Multi-channel Buffered Serial Port"
+ * (McBSP) as on older chips like the dm642 ... which was
+ * backward-compatible, possibly explaining that confusion.
+ *
+ * - OMAP chips have a controller called McBSP, which is
+ * incompatible with the DaVinci flavor of McBSP.
+ *
+ * - Newer DaVinci chips have a controller called McASP,
+ * incompatible with ASP and with either McBSP.
+ *
+ * In short: this uses ASP to implement I2S, not McBSP.
+ * And it won't be the only DaVinci implemention of I2S.
+ */
#define DAVINCI_MCBSP_DRR_REG 0x00
#define DAVINCI_MCBSP_DXR_REG 0x04
#define DAVINCI_MCBSP_SPCR_REG 0x08
@@ -421,7 +441,7 @@ static int davinci_i2s_probe(struct platform_device *pdev,
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_card *card = socdev->card;
- struct snd_soc_dai *cpu_dai = card->dai_link[pdev->id].cpu_dai;
+ struct snd_soc_dai *cpu_dai = card->dai_link->cpu_dai;
struct davinci_mcbsp_dev *dev;
struct resource *mem, *ioarea;
struct evm_snd_platform_data *pdata;
@@ -448,7 +468,7 @@ static int davinci_i2s_probe(struct platform_device *pdev,
cpu_dai->private_data = dev;
- dev->clk = clk_get(&pdev->dev, "McBSPCLK");
+ dev->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(dev->clk)) {
ret = -ENODEV;
goto err_free_mem;
@@ -483,7 +503,7 @@ static void davinci_i2s_remove(struct platform_device *pdev,
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_card *card = socdev->card;
- struct snd_soc_dai *cpu_dai = card->dai_link[pdev->id].cpu_dai;
+ struct snd_soc_dai *cpu_dai = card->dai_link->cpu_dai;
struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
struct resource *mem;
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index 7af3b5b3a53..a0599658848 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -22,6 +22,7 @@
#include <sound/soc.h>
#include <asm/dma.h>
+#include <mach/edma.h>
#include "davinci-pcm.h"
@@ -51,7 +52,7 @@ struct davinci_runtime_data {
spinlock_t lock;
int period; /* current DMA period */
int master_lch; /* Master DMA channel */
- int slave_lch; /* Slave DMA channel */
+ int slave_lch; /* linked parameter RAM reload slot */
struct davinci_pcm_dma_params *params; /* DMA params */
};
@@ -90,18 +91,18 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
dst_bidx = data_type;
}
- davinci_set_dma_src_params(lch, src, INCR, W8BIT);
- davinci_set_dma_dest_params(lch, dst, INCR, W8BIT);
- davinci_set_dma_src_index(lch, src_bidx, 0);
- davinci_set_dma_dest_index(lch, dst_bidx, 0);
- davinci_set_dma_transfer_params(lch, data_type, count, 1, 0, ASYNC);
+ edma_set_src(lch, src, INCR, W8BIT);
+ edma_set_dest(lch, dst, INCR, W8BIT);
+ edma_set_src_index(lch, src_bidx, 0);
+ edma_set_dest_index(lch, dst_bidx, 0);
+ edma_set_transfer_params(lch, data_type, count, 1, 0, ASYNC);
prtd->period++;
if (unlikely(prtd->period >= runtime->periods))
prtd->period = 0;
}
-static void davinci_pcm_dma_irq(int lch, u16 ch_status, void *data)
+static void davinci_pcm_dma_irq(unsigned lch, u16 ch_status, void *data)
{
struct snd_pcm_substream *substream = data;
struct davinci_runtime_data *prtd = substream->runtime->private_data;
@@ -125,7 +126,7 @@ static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
struct davinci_runtime_data *prtd = substream->runtime->private_data;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct davinci_pcm_dma_params *dma_data = rtd->dai->cpu_dai->dma_data;
- int tcc = TCC_ANY;
+ struct edmacc_param p_ram;
int ret;
if (!dma_data)
@@ -134,22 +135,34 @@ static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
prtd->params = dma_data;
/* Request master DMA channel */
- ret = davinci_request_dma(prtd->params->channel, prtd->params->name,
+ ret = edma_alloc_channel(prtd->params->channel,
davinci_pcm_dma_irq, substream,
- &prtd->master_lch, &tcc, EVENTQ_0);
- if (ret)
+ EVENTQ_0);
+ if (ret < 0)
return ret;
+ prtd->master_lch = ret;
- /* Request slave DMA channel */
- ret = davinci_request_dma(PARAM_ANY, "Link",
- NULL, NULL, &prtd->slave_lch, &tcc, EVENTQ_0);
- if (ret) {
- davinci_free_dma(prtd->master_lch);
+ /* Request parameter RAM reload slot */
+ ret = edma_alloc_slot(EDMA_SLOT_ANY);
+ if (ret < 0) {
+ edma_free_channel(prtd->master_lch);
return ret;
}
-
- /* Link slave DMA channel in loopback */
- davinci_dma_link_lch(prtd->slave_lch, prtd->slave_lch);
+ prtd->slave_lch = ret;
+
+ /* Issue transfer completion IRQ when the channel completes a
+ * transfer, then always reload from the same slot (by a kind
+ * of loopback link). The completion IRQ handler will update
+ * the reload slot with a new buffer.
+ *
+ * REVISIT save p_ram here after setting up everything except
+ * the buffer and its length (ccnt) ... use it as a template
+ * so davinci_pcm_enqueue_dma() takes less time in IRQ.
+ */
+ edma_read_slot(prtd->slave_lch, &p_ram);
+ p_ram.opt |= TCINTEN | EDMA_TCC(prtd->master_lch);
+ p_ram.link_bcntrld = prtd->slave_lch << 5;
+ edma_write_slot(prtd->slave_lch, &p_ram);
return 0;
}
@@ -165,12 +178,12 @@ static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- davinci_start_dma(prtd->master_lch);
+ edma_start(prtd->master_lch);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- davinci_stop_dma(prtd->master_lch);
+ edma_stop(prtd->master_lch);
break;
default:
ret = -EINVAL;
@@ -185,14 +198,14 @@ static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
static int davinci_pcm_prepare(struct snd_pcm_substream *substream)
{
struct davinci_runtime_data *prtd = substream->runtime->private_data;
- struct paramentry_descriptor temp;
+ struct edmacc_param temp;
prtd->period = 0;
davinci_pcm_enqueue_dma(substream);
- /* Get slave channel dma params for master channel startup */
- davinci_get_dma_params(prtd->slave_lch, &temp);
- davinci_set_dma_params(prtd->master_lch, &temp);
+ /* Copy self-linked parameter RAM entry into master channel */
+ edma_read_slot(prtd->slave_lch, &temp);
+ edma_write_slot(prtd->master_lch, &temp);
return 0;
}
@@ -208,7 +221,7 @@ davinci_pcm_pointer(struct snd_pcm_substream *substream)
spin_lock(&prtd->lock);
- davinci_dma_getposition(prtd->master_lch, &src, &dst);
+ edma_get_position(prtd->master_lch, &src, &dst);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
count = src - runtime->dma_addr;
else
@@ -253,10 +266,10 @@ static int davinci_pcm_close(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime;
struct davinci_runtime_data *prtd = runtime->private_data;
- davinci_dma_unlink_lch(prtd->slave_lch, prtd->slave_lch);
+ edma_unlink(prtd->slave_lch);
- davinci_free_dma(prtd->slave_lch);
- davinci_free_dma(prtd->master_lch);
+ edma_free_slot(prtd->slave_lch);
+ edma_free_channel(prtd->master_lch);
kfree(prtd);
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 99712f652d0..1cd149b9ce6 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -954,6 +954,9 @@ static int soc_remove(struct platform_device *pdev)
struct snd_soc_platform *platform = card->platform;
struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
+ if (!card->instantiated)
+ return 0;
+
run_delayed_work(&card->delayed_work);
if (platform->remove)