Merge branch 'fix/asoc' into for-linus
authorTakashi Iwai <tiwai@suse.de>
Fri, 15 May 2009 13:38:26 +0000 (15:38 +0200)
committerTakashi Iwai <tiwai@suse.de>
Fri, 15 May 2009 13:38:26 +0000 (15:38 +0200)
* fix/asoc:
  ASoC: DaVinci EVM board support buildfixes
  ASoC: DaVinci I2S updates
  ASoC: davinci-pcm buildfixes
  pxa2xx-ac97: fix reset gpio mode setting
  ASoC: soc-core: fix crash when removing not instantiated card

arch/arm/mach-davinci/include/mach/asp.h [new file with mode: 0644]
sound/arm/pxa2xx-ac97-lib.c
sound/soc/davinci/Kconfig
sound/soc/davinci/davinci-evm.c
sound/soc/davinci/davinci-i2s.c
sound/soc/davinci/davinci-pcm.c
sound/soc/soc-core.c

diff --git a/arch/arm/mach-davinci/include/mach/asp.h b/arch/arm/mach-davinci/include/mach/asp.h
new file mode 100644 (file)
index 0000000..e0abc43
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * <mach/asp.h> - DaVinci Audio Serial Port support
+ */
+#ifndef __ASM_ARCH_DAVINCI_ASP_H
+#define __ASM_ARCH_DAVINCI_ASP_H
+
+#include <mach/irqs.h>
+
+/* Bases of register banks */
+#define DAVINCI_ASP0_BASE      0x01E02000
+#define DAVINCI_ASP1_BASE      0x01E04000
+
+/* EDMA channels */
+#define DAVINCI_DMA_ASP0_TX    2
+#define DAVINCI_DMA_ASP0_RX    3
+#define DAVINCI_DMA_ASP1_TX    8
+#define DAVINCI_DMA_ASP1_RX    9
+
+/* Interrupts */
+#define DAVINCI_ASP0_RX_INT    IRQ_MBRINT
+#define DAVINCI_ASP0_TX_INT    IRQ_MBXINT
+#define DAVINCI_ASP1_RX_INT    IRQ_MBRINT
+#define DAVINCI_ASP1_TX_INT    IRQ_MBXINT
+
+#endif /* __ASM_ARCH_DAVINCI_ASP_H */
index a2c12d1..6fdca97 100644 (file)
@@ -65,7 +65,7 @@ static void set_resetgpio_mode(int resetgpio_action)
                switch (resetgpio_action) {
                case RESETGPIO_NORMAL_ALTFUNC:
                        if (reset_gpio == 113)
-                               mode = 113 | GPIO_OUT | GPIO_DFLT_LOW;
+                               mode = 113 | GPIO_ALT_FN_2_OUT;
                        if (reset_gpio == 95)
                                mode = 95 | GPIO_ALT_FN_1_OUT;
                        break;
index bd7392c..411a710 100644 (file)
@@ -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"
index 9b90b34..58fd1cb 100644 (file)
 #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;
index ffdb943..b1ea52f 100644 (file)
 
 #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;
 
index 7af3b5b..a059965 100644 (file)
@@ -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);
 
index 99712f6..1cd149b 100644 (file)
@@ -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)