Loading arch/arm/mach-davinci/include/mach/asp.h 0 → 100644 +25 −0 Original line number Diff line number Diff line /* * <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 */ sound/soc/davinci/Kconfig +4 −3 Original line number Diff line number Diff line Loading @@ -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" Loading sound/soc/davinci/davinci-evm.c +52 −11 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -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, }; Loading @@ -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; Loading sound/soc/davinci/davinci-i2s.c +23 −3 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading sound/soc/davinci/davinci-pcm.c +42 −29 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <sound/soc.h> #include <asm/dma.h> #include <mach/edma.h> #include "davinci-pcm.h" Loading Loading @@ -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 */ }; Loading Loading @@ -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; Loading @@ -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) Loading @@ -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; } prtd->slave_lch = ret; /* Link slave DMA channel in loopback */ davinci_dma_link_lch(prtd->slave_lch, prtd->slave_lch); /* 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; } Loading @@ -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; Loading @@ -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; } Loading @@ -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 Loading Loading @@ -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); Loading Loading
arch/arm/mach-davinci/include/mach/asp.h 0 → 100644 +25 −0 Original line number Diff line number Diff line /* * <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 */
sound/soc/davinci/Kconfig +4 −3 Original line number Diff line number Diff line Loading @@ -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" Loading
sound/soc/davinci/davinci-evm.c +52 −11 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -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, }; Loading @@ -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; Loading
sound/soc/davinci/davinci-i2s.c +23 −3 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading
sound/soc/davinci/davinci-pcm.c +42 −29 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <sound/soc.h> #include <asm/dma.h> #include <mach/edma.h> #include "davinci-pcm.h" Loading Loading @@ -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 */ }; Loading Loading @@ -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; Loading @@ -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) Loading @@ -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; } prtd->slave_lch = ret; /* Link slave DMA channel in loopback */ davinci_dma_link_lch(prtd->slave_lch, prtd->slave_lch); /* 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; } Loading @@ -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; Loading @@ -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; } Loading @@ -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 Loading Loading @@ -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); Loading