aboutsummaryrefslogtreecommitdiff
path: root/sound/soc/davinci/davinci-pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/davinci/davinci-pcm.c')
-rw-r--r--sound/soc/davinci/davinci-pcm.c361
1 files changed, 169 insertions, 192 deletions
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index 9d35b8c1a62..7809e9d935f 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -16,6 +16,8 @@
#include <linux/slab.h>
#include <linux/dma-mapping.h>
#include <linux/kernel.h>
+#include <linux/genalloc.h>
+#include <linux/platform_data/edma.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -23,8 +25,6 @@
#include <sound/soc.h>
#include <asm/dma.h>
-#include <mach/edma.h>
-#include <mach/sram.h>
#include "davinci-pcm.h"
@@ -49,17 +49,8 @@ static void print_buf_info(int slot, char *name)
static struct snd_pcm_hardware pcm_hardware_playback = {
.info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
- .formats = (SNDRV_PCM_FMTBIT_S16_LE),
- .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
- SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
- SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
- SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
- SNDRV_PCM_RATE_KNOT),
- .rate_min = 8000,
- .rate_max = 96000,
- .channels_min = 2,
- .channels_max = 2,
+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME|
+ SNDRV_PCM_INFO_BATCH),
.buffer_bytes_max = 128 * 1024,
.period_bytes_min = 32,
.period_bytes_max = 8 * 1024,
@@ -71,17 +62,8 @@ static struct snd_pcm_hardware pcm_hardware_playback = {
static struct snd_pcm_hardware pcm_hardware_capture = {
.info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_PAUSE),
- .formats = (SNDRV_PCM_FMTBIT_S16_LE),
- .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
- SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
- SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
- SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
- SNDRV_PCM_RATE_KNOT),
- .rate_min = 8000,
- .rate_max = 96000,
- .channels_min = 2,
- .channels_max = 2,
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_BATCH),
.buffer_bytes_max = 128 * 1024,
.period_bytes_min = 32,
.period_bytes_max = 8 * 1024,
@@ -139,6 +121,22 @@ struct davinci_runtime_data {
struct edmacc_param ram_params;
};
+static void davinci_pcm_period_elapsed(struct snd_pcm_substream *substream)
+{
+ struct davinci_runtime_data *prtd = substream->runtime->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ prtd->period++;
+ if (unlikely(prtd->period >= runtime->periods))
+ prtd->period = 0;
+}
+
+static void davinci_pcm_period_reset(struct snd_pcm_substream *substream)
+{
+ struct davinci_runtime_data *prtd = substream->runtime->private_data;
+
+ prtd->period = 0;
+}
/*
* Not used with ping/pong
*/
@@ -146,7 +144,6 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
{
struct davinci_runtime_data *prtd = substream->runtime->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
- int link = prtd->asp_link[0];
unsigned int period_size;
unsigned int dma_offset;
dma_addr_t dma_pos;
@@ -164,7 +161,8 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
fifo_level = prtd->params->fifo_level;
pr_debug("davinci_pcm: audio_set_dma_params_play channel = %d "
- "dma_ptr = %x period_size=%x\n", link, dma_pos, period_size);
+ "dma_ptr = %x period_size=%x\n", prtd->asp_link[0], dma_pos,
+ period_size);
data_type = prtd->params->data_type;
count = period_size / data_type;
@@ -175,7 +173,7 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
src = dma_pos;
dst = prtd->params->dma_addr;
src_bidx = data_type;
- dst_bidx = 0;
+ dst_bidx = 4;
src_cidx = data_type * fifo_level;
dst_cidx = 0;
} else {
@@ -188,21 +186,20 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
}
acnt = prtd->params->acnt;
- edma_set_src(link, src, INCR, W8BIT);
- edma_set_dest(link, dst, INCR, W8BIT);
+ edma_set_src(prtd->asp_link[0], src, INCR, W8BIT);
+ edma_set_dest(prtd->asp_link[0], dst, INCR, W8BIT);
- edma_set_src_index(link, src_bidx, src_cidx);
- edma_set_dest_index(link, dst_bidx, dst_cidx);
+ edma_set_src_index(prtd->asp_link[0], src_bidx, src_cidx);
+ edma_set_dest_index(prtd->asp_link[0], dst_bidx, dst_cidx);
if (!fifo_level)
- edma_set_transfer_params(link, acnt, count, 1, 0, ASYNC);
+ edma_set_transfer_params(prtd->asp_link[0], acnt, count, 1, 0,
+ ASYNC);
else
- edma_set_transfer_params(link, acnt, fifo_level, count,
- fifo_level, ABSYNC);
-
- prtd->period++;
- if (unlikely(prtd->period >= runtime->periods))
- prtd->period = 0;
+ edma_set_transfer_params(prtd->asp_link[0], acnt,
+ fifo_level,
+ count, fifo_level,
+ ABSYNC);
}
static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data)
@@ -213,21 +210,24 @@ static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data)
print_buf_info(prtd->ram_channel, "i ram_channel");
pr_debug("davinci_pcm: link=%d, status=0x%x\n", link, ch_status);
- if (unlikely(ch_status != DMA_COMPLETE))
+ if (unlikely(ch_status != EDMA_DMA_COMPLETE))
return;
if (snd_pcm_running(substream)) {
+ spin_lock(&prtd->lock);
if (prtd->ram_channel < 0) {
/* No ping/pong must fix up link dma data*/
- spin_lock(&prtd->lock);
davinci_pcm_enqueue_dma(substream);
- spin_unlock(&prtd->lock);
}
+ davinci_pcm_period_elapsed(substream);
+ spin_unlock(&prtd->lock);
snd_pcm_period_elapsed(substream);
}
}
-static int allocate_sram(struct snd_pcm_substream *substream, unsigned size,
+#ifdef CONFIG_GENERIC_ALLOCATOR
+static int allocate_sram(struct snd_pcm_substream *substream,
+ struct gen_pool *sram_pool, unsigned size,
struct snd_pcm_hardware *ppcm)
{
struct snd_dma_buffer *buf = &substream->dma_buffer;
@@ -239,7 +239,7 @@ static int allocate_sram(struct snd_pcm_substream *substream, unsigned size,
return 0;
ppcm->period_bytes_max = size;
- iram_virt = sram_alloc(size, &iram_phys);
+ iram_virt = gen_pool_dma_alloc(sram_pool, size, &iram_phys);
if (!iram_virt)
goto exit1;
iram_dma = kzalloc(sizeof(*iram_dma), GFP_KERNEL);
@@ -253,11 +253,33 @@ static int allocate_sram(struct snd_pcm_substream *substream, unsigned size,
return 0;
exit2:
if (iram_virt)
- sram_free(iram_virt, size);
+ gen_pool_free(sram_pool, (unsigned)iram_virt, size);
exit1:
return -ENOMEM;
}
+static void davinci_free_sram(struct snd_pcm_substream *substream,
+ struct snd_dma_buffer *iram_dma)
+{
+ struct davinci_runtime_data *prtd = substream->runtime->private_data;
+ struct gen_pool *sram_pool = prtd->params->sram_pool;
+
+ gen_pool_free(sram_pool, (unsigned) iram_dma->area, iram_dma->bytes);
+}
+#else
+static int allocate_sram(struct snd_pcm_substream *substream,
+ struct gen_pool *sram_pool, unsigned size,
+ struct snd_pcm_hardware *ppcm)
+{
+ return 0;
+}
+
+static void davinci_free_sram(struct snd_pcm_substream *substream,
+ struct snd_dma_buffer *iram_dma)
+{
+}
+#endif
+
/*
* Only used with ping/pong.
* This is called after runtime->dma_addr, period_bytes and data_type are valid
@@ -274,7 +296,6 @@ static int ping_pong_dma_setup(struct snd_pcm_substream *substream)
unsigned int acnt = params->acnt;
/* divide by 2 for ping/pong */
unsigned int ping_size = snd_pcm_lib_period_bytes(substream) >> 1;
- int link = prtd->asp_link[1];
unsigned int fifo_level = prtd->params->fifo_level;
unsigned int count;
if ((data_type == 0) || (data_type > 4)) {
@@ -285,28 +306,26 @@ static int ping_pong_dma_setup(struct snd_pcm_substream *substream)
dma_addr_t asp_src_pong = iram_dma->addr + ping_size;
ram_src_cidx = ping_size;
ram_dst_cidx = -ping_size;
- edma_set_src(link, asp_src_pong, INCR, W8BIT);
+ edma_set_src(prtd->asp_link[1], asp_src_pong, INCR, W8BIT);
- link = prtd->asp_link[0];
- edma_set_src_index(link, data_type, data_type * fifo_level);
- link = prtd->asp_link[1];
- edma_set_src_index(link, data_type, data_type * fifo_level);
+ edma_set_src_index(prtd->asp_link[0], data_type,
+ data_type * fifo_level);
+ edma_set_src_index(prtd->asp_link[1], data_type,
+ data_type * fifo_level);
- link = prtd->ram_link;
- edma_set_src(link, runtime->dma_addr, INCR, W32BIT);
+ edma_set_src(prtd->ram_link, runtime->dma_addr, INCR, W32BIT);
} else {
dma_addr_t asp_dst_pong = iram_dma->addr + ping_size;
ram_src_cidx = -ping_size;
ram_dst_cidx = ping_size;
- edma_set_dest(link, asp_dst_pong, INCR, W8BIT);
+ edma_set_dest(prtd->asp_link[1], asp_dst_pong, INCR, W8BIT);
- link = prtd->asp_link[0];
- edma_set_dest_index(link, data_type, data_type * fifo_level);
- link = prtd->asp_link[1];
- edma_set_dest_index(link, data_type, data_type * fifo_level);
+ edma_set_dest_index(prtd->asp_link[0], data_type,
+ data_type * fifo_level);
+ edma_set_dest_index(prtd->asp_link[1], data_type,
+ data_type * fifo_level);
- link = prtd->ram_link;
- edma_set_dest(link, runtime->dma_addr, INCR, W32BIT);
+ edma_set_dest(prtd->ram_link, runtime->dma_addr, INCR, W32BIT);
}
if (!fifo_level) {
@@ -323,10 +342,9 @@ static int ping_pong_dma_setup(struct snd_pcm_substream *substream)
count, fifo_level, ABSYNC);
}
- link = prtd->ram_link;
- edma_set_src_index(link, ping_size, ram_src_cidx);
- edma_set_dest_index(link, ping_size, ram_dst_cidx);
- edma_set_transfer_params(link, ping_size, 2,
+ edma_set_src_index(prtd->ram_link, ping_size, ram_src_cidx);
+ edma_set_dest_index(prtd->ram_link, ping_size, ram_dst_cidx);
+ edma_set_transfer_params(prtd->ram_link, ping_size, 2,
runtime->periods, 2, ASYNC);
/* init master params */
@@ -375,32 +393,32 @@ static int request_ping_pong(struct snd_pcm_substream *substream,
{
dma_addr_t asp_src_ping;
dma_addr_t asp_dst_ping;
- int link;
+ int ret;
struct davinci_pcm_dma_params *params = prtd->params;
/* Request ram master channel */
- link = prtd->ram_channel = edma_alloc_channel(EDMA_CHANNEL_ANY,
+ ret = prtd->ram_channel = edma_alloc_channel(EDMA_CHANNEL_ANY,
davinci_pcm_dma_irq, substream,
prtd->params->ram_chan_q);
- if (link < 0)
+ if (ret < 0)
goto exit1;
/* Request ram link channel */
- link = prtd->ram_link = edma_alloc_slot(
+ ret = prtd->ram_link = edma_alloc_slot(
EDMA_CTLR(prtd->ram_channel), EDMA_SLOT_ANY);
- if (link < 0)
+ if (ret < 0)
goto exit2;
- link = prtd->asp_link[1] = edma_alloc_slot(
+ ret = prtd->asp_link[1] = edma_alloc_slot(
EDMA_CTLR(prtd->asp_channel), EDMA_SLOT_ANY);
- if (link < 0)
+ if (ret < 0)
goto exit3;
prtd->ram_link2 = -1;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- link = prtd->ram_link2 = edma_alloc_slot(
+ ret = prtd->ram_link2 = edma_alloc_slot(
EDMA_CTLR(prtd->ram_channel), EDMA_SLOT_ANY);
- if (link < 0)
+ if (ret < 0)
goto exit4;
}
/* circle ping-pong buffers */
@@ -417,35 +435,33 @@ static int request_ping_pong(struct snd_pcm_substream *substream,
asp_dst_ping = iram_dma->addr;
}
/* ping */
- link = prtd->asp_link[0];
- edma_set_src(link, asp_src_ping, INCR, W16BIT);
- edma_set_dest(link, asp_dst_ping, INCR, W16BIT);
- edma_set_src_index(link, 0, 0);
- edma_set_dest_index(link, 0, 0);
+ edma_set_src(prtd->asp_link[0], asp_src_ping, INCR, W16BIT);
+ edma_set_dest(prtd->asp_link[0], asp_dst_ping, INCR, W16BIT);
+ edma_set_src_index(prtd->asp_link[0], 0, 0);
+ edma_set_dest_index(prtd->asp_link[0], 0, 0);
- edma_read_slot(link, &prtd->asp_params);
+ edma_read_slot(prtd->asp_link[0], &prtd->asp_params);
prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f) | TCINTEN);
- prtd->asp_params.opt |= TCCHEN | EDMA_TCC(prtd->ram_channel & 0x3f);
- edma_write_slot(link, &prtd->asp_params);
+ prtd->asp_params.opt |= TCCHEN |
+ EDMA_TCC(prtd->ram_channel & 0x3f);
+ edma_write_slot(prtd->asp_link[0], &prtd->asp_params);
/* pong */
- link = prtd->asp_link[1];
- edma_set_src(link, asp_src_ping, INCR, W16BIT);
- edma_set_dest(link, asp_dst_ping, INCR, W16BIT);
- edma_set_src_index(link, 0, 0);
- edma_set_dest_index(link, 0, 0);
+ edma_set_src(prtd->asp_link[1], asp_src_ping, INCR, W16BIT);
+ edma_set_dest(prtd->asp_link[1], asp_dst_ping, INCR, W16BIT);
+ edma_set_src_index(prtd->asp_link[1], 0, 0);
+ edma_set_dest_index(prtd->asp_link[1], 0, 0);
- edma_read_slot(link, &prtd->asp_params);
+ edma_read_slot(prtd->asp_link[1], &prtd->asp_params);
prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f));
/* interrupt after every pong completion */
prtd->asp_params.opt |= TCINTEN | TCCHEN |
- EDMA_TCC(EDMA_CHAN_SLOT(prtd->ram_channel));
- edma_write_slot(link, &prtd->asp_params);
+ EDMA_TCC(prtd->ram_channel & 0x3f);
+ edma_write_slot(prtd->asp_link[1], &prtd->asp_params);
/* ram */
- link = prtd->ram_link;
- edma_set_src(link, iram_dma->addr, INCR, W32BIT);
- edma_set_dest(link, iram_dma->addr, INCR, W32BIT);
+ edma_set_src(prtd->ram_link, iram_dma->addr, INCR, W32BIT);
+ edma_set_dest(prtd->ram_link, iram_dma->addr, INCR, W32BIT);
pr_debug("%s: audio dma channels/slots in use for ram:%u %u %u,"
"for asp:%u %u %u\n", __func__,
prtd->ram_channel, prtd->ram_link, prtd->ram_link2,
@@ -462,7 +478,7 @@ exit2:
edma_free_channel(prtd->ram_channel);
prtd->ram_channel = -1;
exit1:
- return link;
+ return ret;
}
static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
@@ -470,22 +486,22 @@ static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
struct snd_dma_buffer *iram_dma;
struct davinci_runtime_data *prtd = substream->runtime->private_data;
struct davinci_pcm_dma_params *params = prtd->params;
- int link;
+ int ret;
if (!params)
return -ENODEV;
/* Request asp master DMA channel */
- link = prtd->asp_channel = edma_alloc_channel(params->channel,
+ ret = prtd->asp_channel = edma_alloc_channel(params->channel,
davinci_pcm_dma_irq, substream,
prtd->params->asp_chan_q);
- if (link < 0)
+ if (ret < 0)
goto exit1;
/* Request asp link channels */
- link = prtd->asp_link[0] = edma_alloc_slot(
+ ret = prtd->asp_link[0] = edma_alloc_slot(
EDMA_CTLR(prtd->asp_channel), EDMA_SLOT_ANY);
- if (link < 0)
+ if (ret < 0)
goto exit2;
iram_dma = (struct snd_dma_buffer *)substream->dma_buffer.private_data;
@@ -505,17 +521,17 @@ static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
* the buffer and its length (ccnt) ... use it as a template
* so davinci_pcm_enqueue_dma() takes less time in IRQ.
*/
- edma_read_slot(link, &prtd->asp_params);
+ edma_read_slot(prtd->asp_link[0], &prtd->asp_params);
prtd->asp_params.opt |= TCINTEN |
EDMA_TCC(EDMA_CHAN_SLOT(prtd->asp_channel));
- prtd->asp_params.link_bcntrld = EDMA_CHAN_SLOT(link) << 5;
- edma_write_slot(link, &prtd->asp_params);
+ prtd->asp_params.link_bcntrld = EDMA_CHAN_SLOT(prtd->asp_link[0]) << 5;
+ edma_write_slot(prtd->asp_link[0], &prtd->asp_params);
return 0;
exit2:
edma_free_channel(prtd->asp_channel);
prtd->asp_channel = -1;
exit1:
- return link;
+ return ret;
}
static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
@@ -527,6 +543,13 @@ static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
+ edma_start(prtd->asp_channel);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
+ prtd->ram_channel >= 0) {
+ /* copy 1st iram buffer */
+ edma_start(prtd->ram_channel);
+ }
+ break;
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
edma_resume(prtd->asp_channel);
@@ -550,6 +573,7 @@ static int davinci_pcm_prepare(struct snd_pcm_substream *substream)
{
struct davinci_runtime_data *prtd = substream->runtime->private_data;
+ davinci_pcm_period_reset(substream);
if (prtd->ram_channel >= 0) {
int ret = ping_pong_dma_setup(substream);
if (ret < 0)
@@ -565,21 +589,31 @@ static int davinci_pcm_prepare(struct snd_pcm_substream *substream)
print_buf_info(prtd->asp_link[0], "asp_link[0]");
print_buf_info(prtd->asp_link[1], "asp_link[1]");
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- /* copy 1st iram buffer */
- edma_start(prtd->ram_channel);
- }
- edma_start(prtd->asp_channel);
+ /*
+ * There is a phase offset of 2 periods between the position
+ * used by dma setup and the position reported in the pointer
+ * function.
+ *
+ * The phase offset, when not using ping-pong buffers, is due to
+ * the two consecutive calls to davinci_pcm_enqueue_dma() below.
+ *
+ * Whereas here, with ping-pong buffers, the phase is due to
+ * there being an entire buffer transfer complete before the
+ * first dma completion event triggers davinci_pcm_dma_irq().
+ */
+ davinci_pcm_period_elapsed(substream);
+ davinci_pcm_period_elapsed(substream);
+
return 0;
}
- prtd->period = 0;
davinci_pcm_enqueue_dma(substream);
+ davinci_pcm_period_elapsed(substream);
/* Copy self-linked parameter RAM entry into master channel */
edma_read_slot(prtd->asp_link[0], &prtd->asp_params);
edma_write_slot(prtd->asp_channel, &prtd->asp_params);
davinci_pcm_enqueue_dma(substream);
- edma_start(prtd->asp_channel);
+ davinci_pcm_period_elapsed(substream);
return 0;
}
@@ -591,51 +625,23 @@ davinci_pcm_pointer(struct snd_pcm_substream *substream)
struct davinci_runtime_data *prtd = runtime->private_data;
unsigned int offset;
int asp_count;
- dma_addr_t asp_src, asp_dst;
-
+ unsigned int period_size = snd_pcm_lib_period_bytes(substream);
+
+ /*
+ * There is a phase offset of 2 periods between the position used by dma
+ * setup and the position reported in the pointer function. Either +2 in
+ * the dma setup or -2 here in the pointer function (with wrapping,
+ * both) accounts for this offset -- choose the latter since it makes
+ * the first-time setup clearer.
+ */
spin_lock(&prtd->lock);
- if (prtd->ram_channel >= 0) {
- int ram_count;
- int mod_ram;
- dma_addr_t ram_src, ram_dst;
- unsigned int period_size = snd_pcm_lib_period_bytes(substream);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- /* reading ram before asp should be safe
- * as long as the asp transfers less than a ping size
- * of bytes between the 2 reads
- */
- edma_get_position(prtd->ram_channel,
- &ram_src, &ram_dst);
- edma_get_position(prtd->asp_channel,
- &asp_src, &asp_dst);
- asp_count = asp_src - prtd->asp_params.src;
- ram_count = ram_src - prtd->ram_params.src;
- mod_ram = ram_count % period_size;
- mod_ram -= asp_count;
- if (mod_ram < 0)
- mod_ram += period_size;
- else if (mod_ram == 0) {
- if (snd_pcm_running(substream))
- mod_ram += period_size;
- }
- ram_count -= mod_ram;
- if (ram_count < 0)
- ram_count += period_size * runtime->periods;
- } else {
- edma_get_position(prtd->ram_channel,
- &ram_src, &ram_dst);
- ram_count = ram_dst - prtd->ram_params.dst;
- }
- asp_count = ram_count;
- } else {
- edma_get_position(prtd->asp_channel, &asp_src, &asp_dst);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- asp_count = asp_src - runtime->dma_addr;
- else
- asp_count = asp_dst - runtime->dma_addr;
- }
+ asp_count = prtd->period - 2;
spin_unlock(&prtd->lock);
+ if (asp_count < 0)
+ asp_count += runtime->periods;
+ asp_count *= period_size;
+
offset = bytes_to_frames(runtime, asp_count);
if (offset >= runtime->buffer_size)
offset = 0;
@@ -660,7 +666,7 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream)
ppcm = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
&pcm_hardware_playback : &pcm_hardware_capture;
- allocate_sram(substream, params->sram_size, ppcm);
+ allocate_sram(substream, params->sram_pool, params->sram_size, ppcm);
snd_soc_set_runtime_hwparams(substream, ppcm);
/* ensure that buffer size is a multiple of period size */
ret = snd_pcm_hw_constraint_integer(runtime,
@@ -803,25 +809,23 @@ static void davinci_pcm_free(struct snd_pcm *pcm)
buf->area = NULL;
iram_dma = buf->private_data;
if (iram_dma) {
- sram_free(iram_dma->area, iram_dma->bytes);
+ davinci_free_sram(substream, iram_dma);
kfree(iram_dma);
}
}
}
-static u64 davinci_pcm_dmamask = 0xffffffff;
-
-static int davinci_pcm_new(struct snd_card *card,
- struct snd_soc_dai *dai, struct snd_pcm *pcm)
+static int davinci_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
+ struct snd_card *card = rtd->card->snd_card;
+ struct snd_pcm *pcm = rtd->pcm;
int ret;
- if (!card->dev->dma_mask)
- card->dev->dma_mask = &davinci_pcm_dmamask;
- if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = 0xffffffff;
+ ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
+ if (ret)
+ return ret;
- if (dai->driver->playback.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = davinci_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK,
pcm_hardware_playback.buffer_bytes_max);
@@ -829,7 +833,7 @@ static int davinci_pcm_new(struct snd_card *card,
return ret;
}
- if (dai->driver->capture.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
ret = davinci_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE,
pcm_hardware_capture.buffer_bytes_max);
@@ -846,38 +850,11 @@ static struct snd_soc_platform_driver davinci_soc_platform = {
.pcm_free = davinci_pcm_free,
};
-static int __devinit davinci_soc_platform_probe(struct platform_device *pdev)
-{
- return snd_soc_register_platform(&pdev->dev, &davinci_soc_platform);
-}
-
-static int __devexit davinci_soc_platform_remove(struct platform_device *pdev)
-{
- snd_soc_unregister_platform(&pdev->dev);
- return 0;
-}
-
-static struct platform_driver davinci_pcm_driver = {
- .driver = {
- .name = "davinci-pcm-audio",
- .owner = THIS_MODULE,
- },
-
- .probe = davinci_soc_platform_probe,
- .remove = __devexit_p(davinci_soc_platform_remove),
-};
-
-static int __init snd_davinci_pcm_init(void)
-{
- return platform_driver_register(&davinci_pcm_driver);
-}
-module_init(snd_davinci_pcm_init);
-
-static void __exit snd_davinci_pcm_exit(void)
+int davinci_soc_platform_register(struct device *dev)
{
- platform_driver_unregister(&davinci_pcm_driver);
+ return devm_snd_soc_register_platform(dev, &davinci_soc_platform);
}
-module_exit(snd_davinci_pcm_exit);
+EXPORT_SYMBOL_GPL(davinci_soc_platform_register);
MODULE_AUTHOR("Vladimir Barinov");
MODULE_DESCRIPTION("TI DAVINCI PCM DMA module");