Merge branch 'fix/asoc' into for-linus
* 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
This commit is contained in:
commit
60befb97f5
25
arch/arm/mach-davinci/include/mach/asp.h
Normal file
25
arch/arm/mach-davinci/include/mach/asp.h
Normal file
|
@ -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 */
|
|
@ -65,7 +65,7 @@ static void set_resetgpio_mode(int resetgpio_action)
|
||||||
switch (resetgpio_action) {
|
switch (resetgpio_action) {
|
||||||
case RESETGPIO_NORMAL_ALTFUNC:
|
case RESETGPIO_NORMAL_ALTFUNC:
|
||||||
if (reset_gpio == 113)
|
if (reset_gpio == 113)
|
||||||
mode = 113 | GPIO_OUT | GPIO_DFLT_LOW;
|
mode = 113 | GPIO_ALT_FN_2_OUT;
|
||||||
if (reset_gpio == 95)
|
if (reset_gpio == 95)
|
||||||
mode = 95 | GPIO_ALT_FN_1_OUT;
|
mode = 95 | GPIO_ALT_FN_1_OUT;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -10,13 +10,14 @@ config SND_DAVINCI_SOC_I2S
|
||||||
tristate
|
tristate
|
||||||
|
|
||||||
config SND_DAVINCI_SOC_EVM
|
config SND_DAVINCI_SOC_EVM
|
||||||
tristate "SoC Audio support for DaVinci EVM"
|
tristate "SoC Audio support for DaVinci DM6446 or DM355 EVM"
|
||||||
depends on SND_DAVINCI_SOC && MACH_DAVINCI_EVM
|
depends on SND_DAVINCI_SOC
|
||||||
|
depends on MACH_DAVINCI_EVM || MACH_DAVINCI_DM355_EVM
|
||||||
select SND_DAVINCI_SOC_I2S
|
select SND_DAVINCI_SOC_I2S
|
||||||
select SND_SOC_TLV320AIC3X
|
select SND_SOC_TLV320AIC3X
|
||||||
help
|
help
|
||||||
Say Y if you want to add support for SoC audio on TI
|
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
|
config SND_DAVINCI_SOC_SFFSDR
|
||||||
tristate "SoC Audio support for SFFSDR"
|
tristate "SoC Audio support for SFFSDR"
|
||||||
|
|
|
@ -20,7 +20,11 @@
|
||||||
#include <sound/soc-dapm.h>
|
#include <sound/soc-dapm.h>
|
||||||
|
|
||||||
#include <asm/dma.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 "../codecs/tlv320aic3x.h"
|
||||||
#include "davinci-pcm.h"
|
#include "davinci-pcm.h"
|
||||||
|
@ -150,7 +154,7 @@ static struct snd_soc_card snd_soc_card_evm = {
|
||||||
|
|
||||||
/* evm audio private data */
|
/* evm audio private data */
|
||||||
static struct aic3x_setup_data evm_aic3x_setup = {
|
static struct aic3x_setup_data evm_aic3x_setup = {
|
||||||
.i2c_bus = 0,
|
.i2c_bus = 1,
|
||||||
.i2c_address = 0x1b,
|
.i2c_address = 0x1b,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -161,36 +165,73 @@ static struct snd_soc_device evm_snd_devdata = {
|
||||||
.codec_data = &evm_aic3x_setup,
|
.codec_data = &evm_aic3x_setup,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* DM6446 EVM uses ASP0; line-out is a pair of RCA jacks */
|
||||||
static struct resource evm_snd_resources[] = {
|
static struct resource evm_snd_resources[] = {
|
||||||
{
|
{
|
||||||
.start = DAVINCI_MCBSP_BASE,
|
.start = DAVINCI_ASP0_BASE,
|
||||||
.end = DAVINCI_MCBSP_BASE + SZ_8K - 1,
|
.end = DAVINCI_ASP0_BASE + SZ_8K - 1,
|
||||||
.flags = IORESOURCE_MEM,
|
.flags = IORESOURCE_MEM,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct evm_snd_platform_data evm_snd_data = {
|
static struct evm_snd_platform_data evm_snd_data = {
|
||||||
.tx_dma_ch = DM644X_DMACH_MCBSP_TX,
|
.tx_dma_ch = DAVINCI_DMA_ASP0_TX,
|
||||||
.rx_dma_ch = DM644X_DMACH_MCBSP_RX,
|
.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 struct platform_device *evm_snd_device;
|
||||||
|
|
||||||
static int __init evm_init(void)
|
static int __init evm_init(void)
|
||||||
{
|
{
|
||||||
|
struct resource *resources;
|
||||||
|
unsigned num_resources;
|
||||||
|
struct evm_snd_platform_data *data;
|
||||||
|
int index;
|
||||||
int ret;
|
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)
|
if (!evm_snd_device)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
platform_set_drvdata(evm_snd_device, &evm_snd_devdata);
|
platform_set_drvdata(evm_snd_device, &evm_snd_devdata);
|
||||||
evm_snd_devdata.dev = &evm_snd_device->dev;
|
evm_snd_devdata.dev = &evm_snd_device->dev;
|
||||||
platform_device_add_data(evm_snd_device, &evm_snd_data,
|
platform_device_add_data(evm_snd_device, data, sizeof(*data));
|
||||||
sizeof(evm_snd_data));
|
|
||||||
|
|
||||||
ret = platform_device_add_resources(evm_snd_device, evm_snd_resources,
|
ret = platform_device_add_resources(evm_snd_device, resources,
|
||||||
ARRAY_SIZE(evm_snd_resources));
|
num_resources);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
platform_device_put(evm_snd_device);
|
platform_device_put(evm_snd_device);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -24,6 +24,26 @@
|
||||||
|
|
||||||
#include "davinci-pcm.h"
|
#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_DRR_REG 0x00
|
||||||
#define DAVINCI_MCBSP_DXR_REG 0x04
|
#define DAVINCI_MCBSP_DXR_REG 0x04
|
||||||
#define DAVINCI_MCBSP_SPCR_REG 0x08
|
#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_device *socdev = platform_get_drvdata(pdev);
|
||||||
struct snd_soc_card *card = socdev->card;
|
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 davinci_mcbsp_dev *dev;
|
||||||
struct resource *mem, *ioarea;
|
struct resource *mem, *ioarea;
|
||||||
struct evm_snd_platform_data *pdata;
|
struct evm_snd_platform_data *pdata;
|
||||||
|
@ -448,7 +468,7 @@ static int davinci_i2s_probe(struct platform_device *pdev,
|
||||||
|
|
||||||
cpu_dai->private_data = dev;
|
cpu_dai->private_data = dev;
|
||||||
|
|
||||||
dev->clk = clk_get(&pdev->dev, "McBSPCLK");
|
dev->clk = clk_get(&pdev->dev, NULL);
|
||||||
if (IS_ERR(dev->clk)) {
|
if (IS_ERR(dev->clk)) {
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto err_free_mem;
|
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_device *socdev = platform_get_drvdata(pdev);
|
||||||
struct snd_soc_card *card = socdev->card;
|
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 davinci_mcbsp_dev *dev = cpu_dai->private_data;
|
||||||
struct resource *mem;
|
struct resource *mem;
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <sound/soc.h>
|
#include <sound/soc.h>
|
||||||
|
|
||||||
#include <asm/dma.h>
|
#include <asm/dma.h>
|
||||||
|
#include <mach/edma.h>
|
||||||
|
|
||||||
#include "davinci-pcm.h"
|
#include "davinci-pcm.h"
|
||||||
|
|
||||||
|
@ -51,7 +52,7 @@ struct davinci_runtime_data {
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
int period; /* current DMA period */
|
int period; /* current DMA period */
|
||||||
int master_lch; /* Master DMA channel */
|
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 */
|
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;
|
dst_bidx = data_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
davinci_set_dma_src_params(lch, src, INCR, W8BIT);
|
edma_set_src(lch, src, INCR, W8BIT);
|
||||||
davinci_set_dma_dest_params(lch, dst, INCR, W8BIT);
|
edma_set_dest(lch, dst, INCR, W8BIT);
|
||||||
davinci_set_dma_src_index(lch, src_bidx, 0);
|
edma_set_src_index(lch, src_bidx, 0);
|
||||||
davinci_set_dma_dest_index(lch, dst_bidx, 0);
|
edma_set_dest_index(lch, dst_bidx, 0);
|
||||||
davinci_set_dma_transfer_params(lch, data_type, count, 1, 0, ASYNC);
|
edma_set_transfer_params(lch, data_type, count, 1, 0, ASYNC);
|
||||||
|
|
||||||
prtd->period++;
|
prtd->period++;
|
||||||
if (unlikely(prtd->period >= runtime->periods))
|
if (unlikely(prtd->period >= runtime->periods))
|
||||||
prtd->period = 0;
|
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 snd_pcm_substream *substream = data;
|
||||||
struct davinci_runtime_data *prtd = substream->runtime->private_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 davinci_runtime_data *prtd = substream->runtime->private_data;
|
||||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
struct davinci_pcm_dma_params *dma_data = rtd->dai->cpu_dai->dma_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;
|
int ret;
|
||||||
|
|
||||||
if (!dma_data)
|
if (!dma_data)
|
||||||
|
@ -134,22 +135,34 @@ static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
|
||||||
prtd->params = dma_data;
|
prtd->params = dma_data;
|
||||||
|
|
||||||
/* Request master DMA channel */
|
/* 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,
|
davinci_pcm_dma_irq, substream,
|
||||||
&prtd->master_lch, &tcc, EVENTQ_0);
|
EVENTQ_0);
|
||||||
if (ret)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
prtd->master_lch = ret;
|
||||||
|
|
||||||
/* Request slave DMA channel */
|
/* Request parameter RAM reload slot */
|
||||||
ret = davinci_request_dma(PARAM_ANY, "Link",
|
ret = edma_alloc_slot(EDMA_SLOT_ANY);
|
||||||
NULL, NULL, &prtd->slave_lch, &tcc, EVENTQ_0);
|
if (ret < 0) {
|
||||||
if (ret) {
|
edma_free_channel(prtd->master_lch);
|
||||||
davinci_free_dma(prtd->master_lch);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
prtd->slave_lch = ret;
|
||||||
|
|
||||||
/* Link slave DMA channel in loopback */
|
/* Issue transfer completion IRQ when the channel completes a
|
||||||
davinci_dma_link_lch(prtd->slave_lch, prtd->slave_lch);
|
* 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;
|
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_START:
|
||||||
case SNDRV_PCM_TRIGGER_RESUME:
|
case SNDRV_PCM_TRIGGER_RESUME:
|
||||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||||
davinci_start_dma(prtd->master_lch);
|
edma_start(prtd->master_lch);
|
||||||
break;
|
break;
|
||||||
case SNDRV_PCM_TRIGGER_STOP:
|
case SNDRV_PCM_TRIGGER_STOP:
|
||||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||||
davinci_stop_dma(prtd->master_lch);
|
edma_stop(prtd->master_lch);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ret = -EINVAL;
|
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)
|
static int davinci_pcm_prepare(struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
struct davinci_runtime_data *prtd = substream->runtime->private_data;
|
struct davinci_runtime_data *prtd = substream->runtime->private_data;
|
||||||
struct paramentry_descriptor temp;
|
struct edmacc_param temp;
|
||||||
|
|
||||||
prtd->period = 0;
|
prtd->period = 0;
|
||||||
davinci_pcm_enqueue_dma(substream);
|
davinci_pcm_enqueue_dma(substream);
|
||||||
|
|
||||||
/* Get slave channel dma params for master channel startup */
|
/* Copy self-linked parameter RAM entry into master channel */
|
||||||
davinci_get_dma_params(prtd->slave_lch, &temp);
|
edma_read_slot(prtd->slave_lch, &temp);
|
||||||
davinci_set_dma_params(prtd->master_lch, &temp);
|
edma_write_slot(prtd->master_lch, &temp);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -208,7 +221,7 @@ davinci_pcm_pointer(struct snd_pcm_substream *substream)
|
||||||
|
|
||||||
spin_lock(&prtd->lock);
|
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)
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||||
count = src - runtime->dma_addr;
|
count = src - runtime->dma_addr;
|
||||||
else
|
else
|
||||||
|
@ -253,10 +266,10 @@ static int davinci_pcm_close(struct snd_pcm_substream *substream)
|
||||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||||
struct davinci_runtime_data *prtd = runtime->private_data;
|
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);
|
edma_free_slot(prtd->slave_lch);
|
||||||
davinci_free_dma(prtd->master_lch);
|
edma_free_channel(prtd->master_lch);
|
||||||
|
|
||||||
kfree(prtd);
|
kfree(prtd);
|
||||||
|
|
||||||
|
|
|
@ -954,6 +954,9 @@ static int soc_remove(struct platform_device *pdev)
|
||||||
struct snd_soc_platform *platform = card->platform;
|
struct snd_soc_platform *platform = card->platform;
|
||||||
struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
|
struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
|
||||||
|
|
||||||
|
if (!card->instantiated)
|
||||||
|
return 0;
|
||||||
|
|
||||||
run_delayed_work(&card->delayed_work);
|
run_delayed_work(&card->delayed_work);
|
||||||
|
|
||||||
if (platform->remove)
|
if (platform->remove)
|
||||||
|
|
Loading…
Reference in a new issue