From 1f2da4feb098871ccf3b54aa6df14ae12b8b7ebe Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Wed, 25 May 2011 17:37:45 +0200 Subject: ux500-ASoC: Update ux500 driver to use dmaengine ST-Ericsson Linux next: 342252 ST-Ericsson ID: 342253 ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Robert Marklund Change-Id: I6d0b04aaa9f3e0d170cb3dd2510960f606c4435f Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/24728 Reviewed-by: Philippe LANGLAIS --- sound/soc/ux500/ux500_msp_dai.c | 26 ++++++++------------------ sound/soc/ux500/ux500_msp_dai.h | 4 ++-- sound/soc/ux500/ux500_pcm.c | 35 +++++++++++++++++++---------------- sound/soc/ux500/ux500_pcm.h | 1 + 4 files changed, 30 insertions(+), 36 deletions(-) (limited to 'sound') diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c index 354a0edb8bf..78e78e1fc04 100644 --- a/sound/soc/ux500/ux500_msp_dai.c +++ b/sound/soc/ux500/ux500_msp_dai.c @@ -97,17 +97,15 @@ dma_addr_t ux500_msp_dai_i2s_get_pointer(int dai_idx, int stream_id) } int ux500_msp_dai_i2s_configure_sg(dma_addr_t dma_addr, - int sg_len, - int sg_size, + int period_cnt, + size_t period_len, int dai_idx, int stream_id) { struct ux500_platform_drvdata *drvdata = &platform_drvdata[dai_idx]; struct i2s_message message; struct i2s_device *i2s_dev; - int i; int ret = 0; - struct scatterlist *sg; bool playback_req_valid = (drvdata->playback_active && stream_id == SNDRV_PCM_STREAM_PLAYBACK); @@ -115,11 +113,11 @@ int ux500_msp_dai_i2s_configure_sg(dma_addr_t dma_addr, (drvdata->capture_active && stream_id == SNDRV_PCM_STREAM_CAPTURE); - pr_debug("%s: Enter (MSP Index: %u, SG-length: %u, SG-size: %u).\n", + pr_debug("%s: Enter (MSP Index: %u, period-cnt: %u, period-len: %u).\n", __func__, dai_idx, - sg_len, - sg_size); + period_cnt, + period_len); if (!playback_req_valid && !capture_req_valid) { pr_err("%s: The I2S controller is not available." @@ -131,19 +129,13 @@ int ux500_msp_dai_i2s_configure_sg(dma_addr_t dma_addr, i2s_dev = drvdata->i2s; - sg = kzalloc(sizeof(struct scatterlist) * sg_len, GFP_ATOMIC); - sg_init_table(sg, sg_len); - for (i = 0; i < sg_len; i++) { - sg_dma_address(&sg[i]) = dma_addr + i * sg_size; - sg_dma_len(&sg[i]) = sg_size; - } - message.i2s_transfer_mode = I2S_TRANSFER_MODE_CYCLIC_DMA; message.i2s_direction = (stream_id == SNDRV_PCM_STREAM_PLAYBACK) ? I2S_DIRECTION_TX : I2S_DIRECTION_RX; - message.sg = sg; - message.sg_len = sg_len; + message.buf_addr = dma_addr; + message.buf_len = period_cnt * period_len; + message.period_len = period_len; ret = i2s_transfer(i2s_dev->controller, &message); if (ret < 0) { @@ -152,8 +144,6 @@ int ux500_msp_dai_i2s_configure_sg(dma_addr_t dma_addr, dai_idx); } - kfree(sg); - return ret; } diff --git a/sound/soc/ux500/ux500_msp_dai.h b/sound/soc/ux500/ux500_msp_dai.h index 36aaa386c6a..64a23506bca 100644 --- a/sound/soc/ux500/ux500_msp_dai.h +++ b/sound/soc/ux500/ux500_msp_dai.h @@ -67,8 +67,8 @@ extern struct snd_soc_dai ux500_msp_dai[UX500_NBR_OF_DAI]; bool ux500_msp_dai_i2s_get_underrun_status(int dai_idx); dma_addr_t ux500_msp_dai_i2s_get_pointer(int dai_idx, int stream_id); int ux500_msp_dai_i2s_configure_sg(dma_addr_t dma_addr, - int sg_len, - int sg_size, + int perod_cnt, + size_t period_len, int dai_idx, int stream_id); int ux500_msp_dai_i2s_send_data(void *data, size_t bytes, int dai_idx); diff --git a/sound/soc/ux500/ux500_pcm.c b/sound/soc/ux500/ux500_pcm.c index 0556706776d..1372e8d6e3f 100644 --- a/sound/soc/ux500/ux500_pcm.c +++ b/sound/soc/ux500/ux500_pcm.c @@ -111,8 +111,17 @@ void ux500_pcm_dma_eot_handler(void *data) runtime = substream->runtime; private = substream->runtime->private_data; - if (ux500_msp_dai_i2s_get_underrun_status(private->msp_id)) + if (ux500_msp_dai_i2s_get_underrun_status(private->msp_id)) { private->no_of_underruns++; + pr_debug("%s: Nr of underruns (%d)\n", __func__, + private->no_of_underruns); + } + + /* calc the offset in the circular buffer */ + private->offset += frames_to_bytes(runtime, + runtime->period_size); + private->offset %= frames_to_bytes(runtime, + runtime->period_size) * runtime->periods; snd_pcm_period_elapsed(substream); } @@ -250,12 +259,12 @@ static int ux500_pcm_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: private->no_of_underruns = 0; + private->offset = 0; ret = ux500_msp_dai_i2s_configure_sg(runtime->dma_addr, - runtime->periods, - frames_to_bytes(runtime, - runtime->period_size), - private->msp_id, - stream_id); + runtime->periods, + frames_to_bytes(runtime, runtime->period_size), + private->msp_id, + stream_id); if (ret) { pr_err("%s: Failed to configure sg-list!\n", __func__); return -EINVAL; @@ -284,18 +293,12 @@ static int ux500_pcm_trigger(struct snd_pcm_substream *substream, int cmd) static snd_pcm_uframes_t ux500_pcm_pointer(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct ux500_pcm_private *private = substream->runtime->private_data; - int stream_id = substream->pstr->stream; - unsigned int offset; - dma_addr_t addr; - - pr_debug("%s: Enter\n", __func__); + struct ux500_pcm_private *private = runtime->private_data; - addr = ux500_msp_dai_i2s_get_pointer(private->msp_id, stream_id); - offset = bytes_to_frames(runtime, addr - runtime->dma_addr); - pr_debug("%s: Offset = %u\n", __func__, offset); + pr_debug("%s: dma_offset %d frame %ld\n", __func__, private->offset, + bytes_to_frames(substream->runtime, private->offset)); - return offset; + return bytes_to_frames(substream->runtime, private->offset); } static int ux500_pcm_mmap(struct snd_pcm_substream *substream, diff --git a/sound/soc/ux500/ux500_pcm.h b/sound/soc/ux500/ux500_pcm.h index de2df94fd97..50f46615275 100644 --- a/sound/soc/ux500/ux500_pcm.h +++ b/sound/soc/ux500/ux500_pcm.h @@ -36,6 +36,7 @@ struct ux500_pcm_private { int msp_id; int stream_id; unsigned int no_of_underruns; + unsigned int offset; }; void ux500_pcm_dma_eot_handler(void *data); -- cgit v1.2.3