diff options
author | Philippe Langlais <philippe.langlais@linaro.org> | 2011-03-25 09:43:27 +0100 |
---|---|---|
committer | Robert Marklund <robert.marklund@stericsson.com> | 2011-05-13 10:40:09 +0200 |
commit | a674bce43c41440d62929395e3f5953c11801fa0 (patch) | |
tree | 20d1cef2eb7c3d4fffafd941591fb6558d19baf0 /sound | |
parent | f76e46f382500d1cfdbe38ec8baf758f04ab3bb6 (diff) |
Ux500 ASoC: Use of cyclic DMA.
Platform driver rewritten to make use of cyclic DMA by
sending a cyclic SG-list before playback is started.
Updates to support cyclic DMA in MSP I2S-driver.
ST-Ericsson ID: ER 278088
Change-Id: I9d143fc4704cff6f5415175ab14085b9ab98d6d4
Signed-off-by: Ola Lilja <ola.o.lilja@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/9353
Reviewed-by: Rabin VINCENT <rabin.vincent@stericsson.com>
Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com>
Conflicts:
drivers/misc/i2s/i2s.c
drivers/misc/i2s/i2s_test_protocol_driver.c
drivers/misc/i2s/msp_i2s.c
drivers/misc/i2s/msp_i2s.h
include/linux/i2s/i2s.h
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/ux500/ux500_msp_dai.c | 139 | ||||
-rw-r--r-- | sound/soc/ux500/ux500_msp_dai.h | 8 | ||||
-rw-r--r-- | sound/soc/ux500/ux500_pcm.c | 122 | ||||
-rw-r--r-- | sound/soc/ux500/ux500_pcm.h | 12 | ||||
-rw-r--r-- | sound/u8500_acodec_ab8500.c | 11 |
5 files changed, 164 insertions, 128 deletions
diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c index 36836918a36..432f5646b67 100644 --- a/sound/soc/ux500/ux500_msp_dai.c +++ b/sound/soc/ux500/ux500_msp_dai.c @@ -11,19 +11,20 @@ * it under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. */ -#include <sound/soc.h> -#include <sound/soc-dai.h> +#include <linux/slab.h> #include <asm/dma.h> -#include "ux500_msp_dai.h" -#include "ux500_pcm.h" +#include <linux/bitops.h> #include <mach/msp.h> #include <linux/i2s/i2s.h> -#include <linux/bitops.h> + +#include <sound/soc.h> +#include <sound/soc-dai.h> +#include "ux500_msp_dai.h" +#include "ux500_pcm.h" static struct ux500_msp_dai_private ux500_msp_dai_private[UX500_NBR_OF_DAI] = { { - .lock = __SPIN_LOCK_UNLOCKED(ux500_msp_dai_private[0].lock), .i2s = NULL, .fmt = 0, .slots = 1, @@ -32,7 +33,6 @@ static struct ux500_msp_dai_private ux500_msp_dai_private[UX500_NBR_OF_DAI] = { .slot_width = 16, }, { - .lock = __SPIN_LOCK_UNLOCKED(ux500_msp_dai_private[1].lock), .i2s = NULL, .fmt = 0, .slots = 1, @@ -41,7 +41,6 @@ static struct ux500_msp_dai_private ux500_msp_dai_private[UX500_NBR_OF_DAI] = { .slot_width = 16, }, { - .lock = __SPIN_LOCK_UNLOCKED(ux500_msp_dai_private[2].lock), .i2s = NULL, .fmt = 0, .slots = 1, @@ -53,19 +52,12 @@ static struct ux500_msp_dai_private ux500_msp_dai_private[UX500_NBR_OF_DAI] = { static int ux500_msp_dai_i2s_probe(struct i2s_device *i2s) { - unsigned long flags; - pr_info("%s: Enter (chip_select = %d, i2s = %d).\n", __func__, (int)i2s->chip_select, (int)(i2s)); - spin_lock_irqsave( - &ux500_msp_dai_private[i2s->chip_select].lock, - flags); ux500_msp_dai_private[i2s->chip_select].i2s = i2s; - spin_unlock_irqrestore( - &ux500_msp_dai_private[i2s->chip_select].lock, - flags); + try_module_get(i2s->controller->dev.parent->driver->owner); i2s_set_drvdata( i2s, @@ -76,7 +68,6 @@ static int ux500_msp_dai_i2s_probe(struct i2s_device *i2s) static int ux500_msp_dai_i2s_remove(struct i2s_device *i2s) { - unsigned long flags; struct ux500_msp_dai_private *ux500_msp_dai_private = i2s_get_drvdata(i2s); @@ -84,13 +75,8 @@ static int ux500_msp_dai_i2s_remove(struct i2s_device *i2s) __func__, (int)i2s->chip_select); - spin_lock_irqsave(&ux500_msp_dai_private->lock, flags); - ux500_msp_dai_private->i2s = NULL; i2s_set_drvdata(i2s, NULL); - spin_unlock_irqrestore( - &ux500_msp_dai_private->lock, - flags); pr_debug("%s: Calling module_put.\n", __func__); @@ -117,22 +103,91 @@ static struct i2s_driver i2sdrv_i2s = { .id_table = dev_id_table, }; +bool ux500_msp_dai_i2s_get_underrun_status(int dai_idx) +{ + struct ux500_msp_dai_private *dai_private = &ux500_msp_dai_private[dai_idx]; + int status = i2s_hw_status(dai_private->i2s->controller); + return (bool)(status & TRANSMIT_UNDERRUN_ERR_INT); +} + +dma_addr_t ux500_msp_dai_i2s_get_pointer(int dai_idx, int stream_id) +{ + struct ux500_msp_dai_private *dai_private = &ux500_msp_dai_private[dai_idx]; + return i2s_get_pointer(dai_private->i2s->controller, + (stream_id == SNDRV_PCM_STREAM_PLAYBACK) ? + I2S_DIRECTION_TX : + I2S_DIRECTION_RX); +} + +int ux500_msp_dai_i2s_configure_sg(dma_addr_t dma_addr, + int sg_len, + int sg_size, + int dai_idx, + int stream_id) +{ + struct ux500_msp_dai_private *dai_private = &ux500_msp_dai_private[dai_idx]; + struct i2s_message message; + struct i2s_device *i2s_dev; + int i; + int ret = 0; + struct scatterlist *sg; + + pr_debug("%s: Enter (MSP Index: %u, SG-length: %u, SG-size: %u).\n", + __func__, + dai_idx, + sg_len, + sg_size); + + if (!ux500_msp_dai[dai_idx].playback.active) { + pr_err("%s: The I2S controller is not available." + "MSP index:%d\n", + __func__, + dai_idx); + return ret; + } + + i2s_dev = dai_private->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; + + ret = i2s_transfer(i2s_dev->controller, &message); + if (ret < 0) { + pr_err("%s: Error: i2s_transfer failed. MSP index: %d\n", + __func__, + dai_idx); + } + + kfree(sg); + + return ret; +} + int ux500_msp_dai_i2s_send_data(void *data, size_t bytes, int dai_idx) { - unsigned long flags; struct ux500_msp_dai_private *dai_private = &ux500_msp_dai_private[dai_idx]; struct i2s_message message; struct i2s_device *i2s_dev; int ret = 0; - pr_debug("%s: Enter MSP Index:%d bytes = %d).\n", + pr_debug("%s: Enter. (MSP-index: %d, bytes = %d).\n", __func__, dai_idx, (int)bytes); - spin_lock_irqsave(&dai_private->lock, flags); i2s_dev = dai_private->i2s; @@ -141,17 +196,13 @@ int ux500_msp_dai_i2s_send_data(void *data, "MSP index:%d\n", __func__, dai_idx); - spin_unlock_irqrestore(&dai_private->lock, flags); return ret; } + message.i2s_transfer_mode = I2S_TRANSFER_MODE_SINGLE_DMA; + message.i2s_direction = I2S_DIRECTION_TX; message.txbytes = bytes; message.txdata = data; - message.rxbytes = 0; - message.rxdata = NULL; - message.dma_flag = 1; - - spin_unlock_irqrestore(&dai_private->lock, flags); ret = i2s_transfer(i2s_dev->controller, &message); if (ret < 0) { @@ -167,43 +218,37 @@ int ux500_msp_dai_i2s_receive_data(void *data, size_t bytes, int dai_idx) { - unsigned long flags; struct ux500_msp_dai_private *dai_private = &ux500_msp_dai_private[dai_idx]; struct i2s_message message; struct i2s_device *i2s_dev; int ret = 0; - pr_debug("%s: Enter MSP Index: %d, bytes = %d).\n", + pr_debug("%s: Enter. (MSP-index: %d, Bytes: %d).\n", __func__, dai_idx, (int)bytes); - spin_lock_irqsave(&dai_private->lock, flags); - i2s_dev = dai_private->i2s; if (!ux500_msp_dai[dai_idx].capture.active) { - pr_err("%s: The MSP controller is not available." - "MSP index: %d\n", + pr_err("%s: MSP controller is not available. (MSP-index: %d)\n", __func__, dai_idx); - spin_unlock_irqrestore(&dai_private->lock, flags); return ret; } + message.i2s_transfer_mode = I2S_TRANSFER_MODE_SINGLE_DMA; + message.i2s_direction = I2S_DIRECTION_RX; message.rxbytes = bytes; message.rxdata = data; - message.txbytes = 0; - message.txdata = NULL; message.dma_flag = 1; - spin_unlock_irqrestore(&dai_private->lock, flags); - ret = i2s_transfer(i2s_dev->controller, &message); if (ret < 0) { - pr_err("%s: Error: i2s_transfer failed. Msp index: %d\n", + pr_err("%s: i2s_transfer failed (%d)! (MSP-index: %d)\n", __func__, + ret, dai_idx); } @@ -598,7 +643,6 @@ static int ux500_msp_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *msp_dai) { int ret = 0; - unsigned long flags_private; struct ux500_msp_dai_private *dai_private = msp_dai->private_data; struct snd_pcm_runtime *runtime = substream->runtime; struct msp_config msp_config; @@ -613,10 +657,9 @@ static int ux500_msp_dai_prepare(struct snd_pcm_substream *substream, pr_debug("%s: Setting up dai with rate %u.\n", __func__, runtime->rate); - spin_lock_irqsave(&dai_private->lock, flags_private); + ux500_msp_dai_compile_msp_config(substream, dai_private, runtime->rate, &msp_config); - spin_unlock_irqrestore(&dai_private->lock, flags_private); ret = i2s_setup(dai_private->i2s->controller, &msp_config); if (ret < 0) { @@ -778,7 +821,6 @@ static int ux500_msp_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *msp_dai) { - unsigned long flags; int ret = 0; struct ux500_msp_dai_private *dai_private = msp_dai->private_data; @@ -793,8 +835,6 @@ static int ux500_msp_dai_trigger(struct snd_pcm_substream *substream, (int)dai_private->i2s->chip_select, cmd); - spin_lock_irqsave(&dai_private->lock, flags); - switch (cmd) { case SNDRV_PCM_TRIGGER_START: ret = 0; @@ -815,7 +855,6 @@ static int ux500_msp_dai_trigger(struct snd_pcm_substream *substream, break; } - spin_unlock_irqrestore(&dai_private->lock, flags); return ret; } diff --git a/sound/soc/ux500/ux500_msp_dai.h b/sound/soc/ux500/ux500_msp_dai.h index 0ad8b380318..90bc518fc83 100644 --- a/sound/soc/ux500/ux500_msp_dai.h +++ b/sound/soc/ux500/ux500_msp_dai.h @@ -39,7 +39,6 @@ #define UX500_MSP_MAX_CHANNELS 8 struct ux500_msp_dai_private { - spinlock_t lock; struct i2s_device *i2s; unsigned int fmt; unsigned int tx_mask; @@ -50,6 +49,13 @@ struct ux500_msp_dai_private { 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 dai_idx, + int stream_id); int ux500_msp_dai_i2s_send_data(void *data, size_t bytes, int dai_idx); int ux500_msp_dai_i2s_receive_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 6a5567e1445..c0765f7a839 100644 --- a/sound/soc/ux500/ux500_pcm.c +++ b/sound/soc/ux500/ux500_pcm.c @@ -27,73 +27,49 @@ #include "ux500_msp_dai.h" static struct snd_pcm_hardware ux500_pcm_hw_playback = { - .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_PAUSE), - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | - SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_U16_BE, + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_RESUME | + SNDRV_PCM_INFO_PAUSE, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_U16_LE | + SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_U16_BE, .rates = SNDRV_PCM_RATE_KNOT, .rate_min = UX500_PLATFORM_MIN_RATE_PLAYBACK, .rate_max = UX500_PLATFORM_MAX_RATE_PLAYBACK, .channels_min = UX500_PLATFORM_MIN_CHANNELS, .channels_max = UX500_PLATFORM_MAX_CHANNELS, - .buffer_bytes_max = UX500_PLATFORM_BUFFER_SIZE, - .period_bytes_min = UX500_PLATFORM_MIN_PERIOD_BYTES, - .period_bytes_max = PAGE_SIZE, - .periods_min = UX500_PLATFORM_BUFFER_SIZE / PAGE_SIZE, - .periods_max = UX500_PLATFORM_BUFFER_SIZE / - UX500_PLATFORM_MIN_PERIOD_BYTES + .buffer_bytes_max = UX500_PLATFORM_BUFFER_BYTES_MAX, + .period_bytes_min = UX500_PLATFORM_PERIODS_BYTES_MIN, + .period_bytes_max = UX500_PLATFORM_PERIODS_BYTES_MAX, + .periods_min = UX500_PLATFORM_PERIODS_MIN, + .periods_max = UX500_PLATFORM_PERIODS_MAX, }; static struct snd_pcm_hardware ux500_pcm_hw_capture = { - .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_PAUSE), - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | - SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_U16_BE, + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_RESUME | + SNDRV_PCM_INFO_PAUSE, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_U16_LE | + SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_U16_BE, .rates = SNDRV_PCM_RATE_KNOT, .rate_min = UX500_PLATFORM_MIN_RATE_CAPTURE, .rate_max = UX500_PLATFORM_MAX_RATE_CAPTURE, .channels_min = UX500_PLATFORM_MIN_CHANNELS, .channels_max = UX500_PLATFORM_MAX_CHANNELS, - .buffer_bytes_max = UX500_PLATFORM_BUFFER_SIZE, - .period_bytes_min = UX500_PLATFORM_MIN_PERIOD_BYTES, - .period_bytes_max = PAGE_SIZE, - .periods_min = UX500_PLATFORM_BUFFER_SIZE / PAGE_SIZE, - .periods_max = UX500_PLATFORM_BUFFER_SIZE / - UX500_PLATFORM_MIN_PERIOD_BYTES + .buffer_bytes_max = UX500_PLATFORM_BUFFER_BYTES_MAX, + .period_bytes_min = UX500_PLATFORM_PERIODS_BYTES_MIN, + .period_bytes_max = UX500_PLATFORM_PERIODS_BYTES_MAX, + .periods_min = UX500_PLATFORM_PERIODS_MIN, + .periods_max = UX500_PLATFORM_PERIODS_MAX, }; -static void ux500_pcm_dma_enqueue(struct snd_pcm_substream *substream) -{ - unsigned int dma_size; - struct snd_pcm_runtime *runtime = substream->runtime; - struct ux500_pcm_private *private = substream->runtime->private_data; - - pr_debug("%s: Enter MSP Index: %d.\n", - __func__, - private->msp_id); - - dma_size = frames_to_bytes(runtime, runtime->period_size); - if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) { - ux500_msp_dai_i2s_send_data( - (void *)(runtime->dma_addr + private->offset), - dma_size, - private->msp_id); - } else{ - ux500_msp_dai_i2s_receive_data( - (void *)(runtime->dma_addr + private->offset), - dma_size, - private->msp_id); - } - - private->period++; - private->period %= runtime->periods; - private->offset = - frames_to_bytes(runtime, runtime->period_size) * - private->period; -} - static void ux500_pcm_dma_hw_free(struct device *dev, - struct snd_pcm_substream *substream) + struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_dma_buffer *buf = runtime->dma_buffer_p; @@ -125,10 +101,10 @@ void ux500_pcm_dma_eot_handler(void *data) runtime = substream->runtime; private = substream->runtime->private_data; - snd_pcm_period_elapsed(substream); + if (ux500_msp_dai_i2s_get_underrun_status(private->msp_id)) + private->no_of_underruns++; - if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) - ux500_pcm_dma_enqueue(substream); + snd_pcm_period_elapsed(substream); } } EXPORT_SYMBOL(ux500_pcm_dma_eot_handler); @@ -237,22 +213,37 @@ static int ux500_pcm_prepare(struct snd_pcm_substream *substream) static int ux500_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { - int i; - struct ux500_pcm_private *private = substream->runtime->private_data; + int ret; + struct snd_pcm_runtime *runtime = substream->runtime; + struct ux500_pcm_private *private = runtime->private_data; + int stream_id = substream->pstr->stream; pr_debug("%s: Enter\n", __func__); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - for (i = 0; i < UX500_PLATFORM_PERIODS_QUEUED_DMA; i++) - ux500_pcm_dma_enqueue(substream); + private->no_of_underruns = 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); + if (ret) { + pr_err("%s: Failed to configure sg-list!\n", __func__); + return -EINVAL; + } break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: break; + case SNDRV_PCM_TRIGGER_STOP: pr_debug("%s: SNDRV_PCM_TRIGGER_STOP\n", __func__); - private->period = 0; + pr_debug("%s: no_of_underruns = %u\n", + __func__, + private->no_of_underruns); break; default: @@ -266,18 +257,17 @@ 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) { - unsigned int offset; 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__); - offset = bytes_to_frames(runtime, private->offset); - if (offset < 0 || private->offset < 0) - pr_debug("%s: Offset=%i %i\n", - __func__, - offset, - private->offset); + 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); return offset; } diff --git a/sound/soc/ux500/ux500_pcm.h b/sound/soc/ux500/ux500_pcm.h index 80f050128c8..9d8b36d9b6f 100644 --- a/sound/soc/ux500/ux500_pcm.h +++ b/sound/soc/ux500/ux500_pcm.h @@ -16,8 +16,6 @@ #include <mach/msp.h> -#define UX500_PLATFORM_BUFFER_SIZE (64*1024) - #define UX500_PLATFORM_MIN_RATE_PLAYBACK 8000 #define UX500_PLATFORM_MAX_RATE_PLAYBACK 48000 #define UX500_PLATFORM_MIN_RATE_CAPTURE 8000 @@ -25,17 +23,19 @@ #define UX500_PLATFORM_MIN_CHANNELS 1 #define UX500_PLATFORM_MAX_CHANNELS 8 -#define UX500_PLATFORM_MIN_PERIOD_BYTES 128 -#define UX500_PLATFORM_PERIODS_QUEUED_DMA 5 +#define UX500_PLATFORM_PERIODS_BYTES_MIN 128 +#define UX500_PLATFORM_PERIODS_BYTES_MAX (64 * PAGE_SIZE) +#define UX500_PLATFORM_PERIODS_MIN 2 +#define UX500_PLATFORM_PERIODS_MAX 48 +#define UX500_PLATFORM_BUFFER_BYTES_MAX (2048 * PAGE_SIZE) extern struct snd_soc_platform ux500_soc_platform; struct ux500_pcm_private { int msp_id; int stream_id; - int period; - unsigned int offset; + unsigned int no_of_underruns; }; void ux500_pcm_dma_eot_handler(void *data); diff --git a/sound/u8500_acodec_ab8500.c b/sound/u8500_acodec_ab8500.c index 2c1ae702b79..c75da368832 100644 --- a/sound/u8500_acodec_ab8500.c +++ b/sound/u8500_acodec_ab8500.c @@ -333,10 +333,11 @@ t_ab8500_codec_error u8500_acodec_send_data(int client_id, void *data, stm_dbg(DBG_ST.acodec, " I2S controller not available\n"); return -1; } + + message.i2s_transfer_mode = I2S_TRANSFER_MODE_SINGLE_DMA; + message.i2s_direction = I2S_DIRECTION_TX; message.txbytes = bytes; message.txdata = data; - message.rxbytes = 0; - message.rxdata = NULL; message.dma_flag = dma_flag; bytes_transmit = i2s_transfer(i2s_dev->controller, &message); @@ -369,12 +370,12 @@ t_ab8500_codec_error u8500_acodec_loopback_configure(int client_id, void *data, return -1; } + message.i2s_transfer_mode = I2S_TRANSFER_MODE_INF_LOOPBACK; message.rxbytes = bytes; message.rxdata = data; message.txbytes = bytes; message.txdata = data; message.dma_flag = dma_flag; - message.inf_loopback_xfer = true; bytes_receive = i2s_transfer(i2s_dev->controller, &message); @@ -406,10 +407,10 @@ t_ab8500_codec_error u8500_acodec_receive_data(int client_id, void *data, return -1; } + message.i2s_transfer_mode = I2S_TRANSFER_MODE_SINGLE_DMA; + message.i2s_direction = I2S_DIRECTION_RX; message.rxbytes = bytes; message.rxdata = data; - message.txbytes = 0; - message.txdata = NULL; message.dma_flag = dma_flag; bytes_receive = i2s_transfer(i2s_dev->controller, &message); |