[alsa-devel] [PATCH 0/5 v2] ASoC: fsi: DMA support 1st step
Dear Mark, Liam
These patches are v2 of 1st step for DMA support of FSI driver
Kuninori Morimoto (5): ASoC: fsi: Add fsi_dma_get_area ASoC: fsi: modify noisy comment out ASoC: fsi: Add fsi_dma_soft_push/pop function ASoC: fsi: modify variable name to easy to understand ASoC: fsi: merge fsi_data_push/pop to fsi_fifo_data_ctrl
2nd patch modify noisy comment out which Liam said.
Best regards -- Kuninori Morimoto
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
o no change
sound/soc/sh/fsi.c | 11 +++++++---- 1 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index abc6d83..44a2b6e 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -357,6 +357,11 @@ static int fsi_get_fifo_residue(struct fsi_priv *fsi, int is_play) return residue; }
+static u8 *fsi_dma_get_area(struct fsi_priv *fsi) +{ + return fsi->substream->runtime->dma_area + fsi->byte_offset; +} + /************************************************************************
@@ -550,8 +555,7 @@ static int fsi_data_push(struct fsi_priv *fsi, int startup) if (fifo_free < send) send = fifo_free;
- start = runtime->dma_area; - start += fsi->byte_offset; + start = fsi_dma_get_area(fsi);
switch (width) { case 2: @@ -633,8 +637,7 @@ static int fsi_data_pop(struct fsi_priv *fsi, int startup) if (free < fifo_fill) fifo_fill = free;
- start = runtime->dma_area; - start += fsi->byte_offset; + start = fsi_dma_get_area(fsi);
switch (width) { case 2:
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
o this patch is added for v2
sound/soc/sh/fsi.c | 102 ++++++++++++++++++---------------------------------- 1 files changed, 35 insertions(+), 67 deletions(-)
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 44a2b6e..2247412 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -101,13 +101,10 @@
#define FSI_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
-/************************************************************************ - - - struct - +/* + * struct + */
-************************************************************************/ struct fsi_priv { void __iomem *base; struct snd_pcm_substream *substream; @@ -142,13 +139,10 @@ struct fsi_master { spinlock_t lock; };
-/************************************************************************ - - - basic read write function - +/* + * basic read write function + */
-************************************************************************/ static void __fsi_reg_write(u32 reg, u32 data) { /* valid data area is 24bit */ @@ -251,13 +245,10 @@ static void fsi_master_mask_set(struct fsi_master *master, spin_unlock_irqrestore(&master->lock, flags); }
-/************************************************************************ - - - basic function - +/* + * basic function + */
-************************************************************************/ static struct fsi_master *fsi_get_master(struct fsi_priv *fsi) { return fsi->master; @@ -362,13 +353,10 @@ static u8 *fsi_dma_get_area(struct fsi_priv *fsi) return fsi->substream->runtime->dma_area + fsi->byte_offset; }
-/************************************************************************ - - - irq function - +/* + * irq function + */
-************************************************************************/ static void fsi_irq_enable(struct fsi_priv *fsi, int is_play) { u32 data = fsi_port_ab_io_bit(fsi, is_play); @@ -409,13 +397,11 @@ static void fsi_irq_clear_status(struct fsi_priv *fsi) fsi_master_mask_set(master, master->core->int_st, data, 0); }
-/************************************************************************ - - - SPDIF master clock function - -These functions are used later FSI2 -************************************************************************/ +/* + * SPDIF master clock function + * + * These functions are used later FSI2 + */ static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable) { struct fsi_master *master = fsi_get_master(fsi); @@ -432,13 +418,10 @@ static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable) fsi_master_mask_set(master, fsi->mst_ctrl, val, 0); }
-/************************************************************************ - - - ctrl function - +/* + * ctrl function + */
-************************************************************************/ static void fsi_clk_ctrl(struct fsi_priv *fsi, int enable) { u32 val = fsi_is_port_a(fsi) ? (1 << 0) : (1 << 4); @@ -697,13 +680,10 @@ static irqreturn_t fsi_interrupt(int irq, void *data) return IRQ_HANDLED; }
-/************************************************************************ - - - dai ops - +/* + * dai ops + */
-************************************************************************/ static int fsi_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { @@ -922,13 +902,10 @@ static struct snd_soc_dai_ops fsi_dai_ops = { .hw_params = fsi_dai_hw_params, };
-/************************************************************************ - - - pcm ops - +/* + * pcm ops + */
-************************************************************************/ static struct snd_pcm_hardware fsi_pcm_hardware = { .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP | @@ -994,13 +971,10 @@ static struct snd_pcm_ops fsi_pcm_ops = { .pointer = fsi_pointer, };
-/************************************************************************ - - - snd_soc_platform - +/* + * snd_soc_platform + */
-************************************************************************/ #define PREALLOC_BUFFER (32 * 1024) #define PREALLOC_BUFFER_MAX (32 * 1024)
@@ -1024,13 +998,10 @@ static int fsi_pcm_new(struct snd_card *card, PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); }
-/************************************************************************ - - - alsa struct - +/* + * alsa struct + */
-************************************************************************/ static struct snd_soc_dai_driver fsi_soc_dai[] = { { .name = "fsia-dai", @@ -1072,13 +1043,10 @@ static struct snd_soc_platform_driver fsi_soc_platform = { .pcm_free = fsi_pcm_free, };
-/************************************************************************ - - - platform function - +/* + * platform function + */
-************************************************************************/ static int fsi_probe(struct platform_device *pdev) { struct fsi_master *master;
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
o didn't use noisy comment out
sound/soc/sh/fsi.c | 72 +++++++++++++++++++++++++++++++++++++++------------- 1 files changed, 54 insertions(+), 18 deletions(-)
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 2247412..1306153 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -348,11 +348,59 @@ static int fsi_get_fifo_residue(struct fsi_priv *fsi, int is_play) return residue; }
+/* + * dma function + */ + static u8 *fsi_dma_get_area(struct fsi_priv *fsi) { return fsi->substream->runtime->dma_area + fsi->byte_offset; }
+static void fsi_dma_soft_push16(struct fsi_priv *fsi, int size) +{ + u16 *start; + int i; + + start = (u16 *)fsi_dma_get_area(fsi); + + for (i = 0; i < size; i++) + fsi_reg_write(fsi, DODT, ((u32)*(start + i) << 8)); +} + +static void fsi_dma_soft_pop16(struct fsi_priv *fsi, int size) +{ + u16 *start; + int i; + + start = (u16 *)fsi_dma_get_area(fsi); + + for (i = 0; i < size; i++) + *(start + i) = (u16)(fsi_reg_read(fsi, DIDT) >> 8); +} + +static void fsi_dma_soft_push32(struct fsi_priv *fsi, int size) +{ + u32 *start; + int i; + + start = (u32 *)fsi_dma_get_area(fsi); + + for (i = 0; i < size; i++) + fsi_reg_write(fsi, DODT, *(start + i)); +} + +static void fsi_dma_soft_pop32(struct fsi_priv *fsi, int size) +{ + u32 *start; + int i; + + start = (u32 *)fsi_dma_get_area(fsi); + + for (i = 0; i < size; i++) + *(start + i) = fsi_reg_read(fsi, DIDT); +} + /* * irq function */ @@ -500,8 +548,7 @@ static int fsi_data_push(struct fsi_priv *fsi, int startup) int send; int fifo_free; int width; - u8 *start; - int i, over_period; + int over_period;
if (!fsi || !fsi->substream || @@ -538,17 +585,12 @@ static int fsi_data_push(struct fsi_priv *fsi, int startup) if (fifo_free < send) send = fifo_free;
- start = fsi_dma_get_area(fsi); - switch (width) { case 2: - for (i = 0; i < send; i++) - fsi_reg_write(fsi, DODT, - ((u32)*((u16 *)start + i) << 8)); + fsi_dma_soft_push16(fsi, send); break; case 4: - for (i = 0; i < send; i++) - fsi_reg_write(fsi, DODT, *((u32 *)start + i)); + fsi_dma_soft_push32(fsi, send); break; default: return -EINVAL; @@ -583,8 +625,7 @@ static int fsi_data_pop(struct fsi_priv *fsi, int startup) int free; int fifo_fill; int width; - u8 *start; - int i, over_period; + int over_period;
if (!fsi || !fsi->substream || @@ -620,17 +661,12 @@ static int fsi_data_pop(struct fsi_priv *fsi, int startup) if (free < fifo_fill) fifo_fill = free;
- start = fsi_dma_get_area(fsi); - switch (width) { case 2: - for (i = 0; i < fifo_fill; i++) - *((u16 *)start + i) = - (u16)(fsi_reg_read(fsi, DIDT) >> 8); + fsi_dma_soft_pop16(fsi, fifo_fill); break; case 4: - for (i = 0; i < fifo_fill; i++) - *((u32 *)start + i) = fsi_reg_read(fsi, DIDT); + fsi_dma_soft_pop32(fsi, fifo_fill); break; default: return -EINVAL;
Current FSI driver is using data-length / width / number / offset for variables. But it was a very confusing name.
This patch rename them to easy to understand, and add new functions for it.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
o _ofs => _offset o it doesn't use period_width
sound/soc/sh/fsi.c | 173 +++++++++++++++++++++++++++++----------------------- 1 files changed, 96 insertions(+), 77 deletions(-)
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 1306153..b817aae 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -102,6 +102,15 @@ #define FSI_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
/* + * FSI driver use below type name for variable + * + * xxx_len : data length + * xxx_width : data width + * xxx_offset : data offset + * xxx_num : number of data + */ + +/* * struct */
@@ -110,13 +119,13 @@ struct fsi_priv { struct snd_pcm_substream *substream; struct fsi_master *master;
- int fifo_max; - int chan; + int fifo_max_num; + int chan_num;
- int byte_offset; + int buff_offset; + int buff_len; int period_len; - int buffer_len; - int periods; + int period_num;
u32 mst_ctrl; }; @@ -320,32 +329,43 @@ static void fsi_stream_push(struct fsi_priv *fsi, u32 period_len) { fsi->substream = substream; - fsi->buffer_len = buffer_len; + fsi->buff_len = buffer_len; + fsi->buff_offset = 0; fsi->period_len = period_len; - fsi->byte_offset = 0; - fsi->periods = 0; + fsi->period_num = 0; }
static void fsi_stream_pop(struct fsi_priv *fsi) { fsi->substream = NULL; - fsi->buffer_len = 0; + fsi->buff_len = 0; + fsi->buff_offset = 0; fsi->period_len = 0; - fsi->byte_offset = 0; - fsi->periods = 0; + fsi->period_num = 0; }
-static int fsi_get_fifo_residue(struct fsi_priv *fsi, int is_play) +static int fsi_get_fifo_data_num(struct fsi_priv *fsi, int is_play) { u32 status; u32 reg = is_play ? DOFF_ST : DIFF_ST; - int residue; + int data_num;
status = fsi_reg_read(fsi, reg); - residue = 0x1ff & (status >> 8); - residue *= fsi->chan; + data_num = 0x1ff & (status >> 8); + data_num *= fsi->chan_num; + + return data_num; +}
- return residue; +static int fsi_len2num(int len, int width) +{ + return len / width; +} + +#define fsi_num2offset(a, b) fsi_num2len(a, b) +static int fsi_num2len(int num, int width) +{ + return num * width; }
/* @@ -354,50 +374,50 @@ static int fsi_get_fifo_residue(struct fsi_priv *fsi, int is_play)
static u8 *fsi_dma_get_area(struct fsi_priv *fsi) { - return fsi->substream->runtime->dma_area + fsi->byte_offset; + return fsi->substream->runtime->dma_area + fsi->buff_offset; }
-static void fsi_dma_soft_push16(struct fsi_priv *fsi, int size) +static void fsi_dma_soft_push16(struct fsi_priv *fsi, int num) { u16 *start; int i;
start = (u16 *)fsi_dma_get_area(fsi);
- for (i = 0; i < size; i++) + for (i = 0; i < num; i++) fsi_reg_write(fsi, DODT, ((u32)*(start + i) << 8)); }
-static void fsi_dma_soft_pop16(struct fsi_priv *fsi, int size) +static void fsi_dma_soft_pop16(struct fsi_priv *fsi, int num) { u16 *start; int i;
start = (u16 *)fsi_dma_get_area(fsi);
- for (i = 0; i < size; i++) + for (i = 0; i < num; i++) *(start + i) = (u16)(fsi_reg_read(fsi, DIDT) >> 8); }
-static void fsi_dma_soft_push32(struct fsi_priv *fsi, int size) +static void fsi_dma_soft_push32(struct fsi_priv *fsi, int num) { u32 *start; int i;
start = (u32 *)fsi_dma_get_area(fsi);
- for (i = 0; i < size; i++) + for (i = 0; i < num; i++) fsi_reg_write(fsi, DODT, *(start + i)); }
-static void fsi_dma_soft_pop32(struct fsi_priv *fsi, int size) +static void fsi_dma_soft_pop32(struct fsi_priv *fsi, int num) { u32 *start; int i;
start = (u32 *)fsi_dma_get_area(fsi);
- for (i = 0; i < size; i++) + for (i = 0; i < num; i++) *(start + i) = fsi_reg_read(fsi, DIDT); }
@@ -492,8 +512,8 @@ static void fsi_fifo_init(struct fsi_priv *fsi, shift = fsi_master_read(master, FIFO_SZ); shift >>= fsi_is_port_a(fsi) ? AO_SZ_SHIFT : BO_SZ_SHIFT; shift &= OUT_SZ_MASK; - fsi->fifo_max = 256 << shift; - dev_dbg(dai->dev, "fifo = %d words\n", fsi->fifo_max); + fsi->fifo_max_num = 256 << shift; + dev_dbg(dai->dev, "fifo = %d words\n", fsi->fifo_max_num);
/* * The maximum number of sample data varies depending @@ -514,9 +534,10 @@ static void fsi_fifo_init(struct fsi_priv *fsi, * 7 channels: 32 ( 32 x 7 = 224) * 8 channels: 32 ( 32 x 8 = 256) */ - for (i = 1; i < fsi->chan; i <<= 1) - fsi->fifo_max >>= 1; - dev_dbg(dai->dev, "%d channel %d store\n", fsi->chan, fsi->fifo_max); + for (i = 1; i < fsi->chan_num; i <<= 1) + fsi->fifo_max_num >>= 1; + dev_dbg(dai->dev, "%d channel %d store\n", + fsi->chan_num, fsi->fifo_max_num);
ctrl = is_play ? DOFF_CTL : DIFF_CTL;
@@ -545,9 +566,9 @@ static int fsi_data_push(struct fsi_priv *fsi, int startup) struct snd_pcm_runtime *runtime; struct snd_pcm_substream *substream = NULL; u32 status; - int send; - int fifo_free; - int width; + int push_num; + int push_num_max; + int ch_width; int over_period;
if (!fsi || @@ -562,41 +583,40 @@ static int fsi_data_push(struct fsi_priv *fsi, int startup) /* FSI FIFO has limit. * So, this driver can not send periods data at a time */ - if (fsi->byte_offset >= - fsi->period_len * (fsi->periods + 1)) { + if (fsi->buff_offset >= + fsi_num2offset(fsi->period_num + 1, fsi->period_len)) {
over_period = 1; - fsi->periods = (fsi->periods + 1) % runtime->periods; + fsi->period_num = (fsi->period_num + 1) % runtime->periods;
- if (0 == fsi->periods) - fsi->byte_offset = 0; + if (0 == fsi->period_num) + fsi->buff_offset = 0; }
/* get 1 channel data width */ - width = frames_to_bytes(runtime, 1) / fsi->chan; + ch_width = frames_to_bytes(runtime, 1) / fsi->chan_num;
- /* get send size for alsa */ - send = (fsi->buffer_len - fsi->byte_offset) / width; + /* number of push data */ + push_num = fsi_len2num(fsi->buff_len - fsi->buff_offset, ch_width);
- /* get FIFO free size */ - fifo_free = (fsi->fifo_max * fsi->chan) - fsi_get_fifo_residue(fsi, 1); + /* max number of push data */ + push_num_max = (fsi->fifo_max_num * fsi->chan_num) - + fsi_get_fifo_data_num(fsi, 1);
- /* size check */ - if (fifo_free < send) - send = fifo_free; + push_num = min(push_num, push_num_max);
- switch (width) { + switch (ch_width) { case 2: - fsi_dma_soft_push16(fsi, send); + fsi_dma_soft_push16(fsi, push_num); break; case 4: - fsi_dma_soft_push32(fsi, send); + fsi_dma_soft_push32(fsi, push_num); break; default: return -EINVAL; }
- fsi->byte_offset += send * width; + fsi->buff_offset += fsi_num2offset(push_num, ch_width);
status = fsi_reg_read(fsi, DOFF_ST); if (!startup) { @@ -622,9 +642,9 @@ static int fsi_data_pop(struct fsi_priv *fsi, int startup) struct snd_pcm_runtime *runtime; struct snd_pcm_substream *substream = NULL; u32 status; - int free; - int fifo_fill; - int width; + int pop_num; + int pop_num_max; + int ch_width; int over_period;
if (!fsi || @@ -639,40 +659,39 @@ static int fsi_data_pop(struct fsi_priv *fsi, int startup) /* FSI FIFO has limit. * So, this driver can not send periods data at a time */ - if (fsi->byte_offset >= - fsi->period_len * (fsi->periods + 1)) { + if (fsi->buff_offset >= + fsi_num2offset(fsi->period_num + 1, fsi->period_len)) {
over_period = 1; - fsi->periods = (fsi->periods + 1) % runtime->periods; + fsi->period_num = (fsi->period_num + 1) % runtime->periods;
- if (0 == fsi->periods) - fsi->byte_offset = 0; + if (0 == fsi->period_num) + fsi->buff_offset = 0; }
/* get 1 channel data width */ - width = frames_to_bytes(runtime, 1) / fsi->chan; + ch_width = frames_to_bytes(runtime, 1) / fsi->chan_num;
/* get free space for alsa */ - free = (fsi->buffer_len - fsi->byte_offset) / width; + pop_num_max = fsi_len2num(fsi->buff_len - fsi->buff_offset, ch_width);
/* get recv size */ - fifo_fill = fsi_get_fifo_residue(fsi, 0); + pop_num = fsi_get_fifo_data_num(fsi, 0);
- if (free < fifo_fill) - fifo_fill = free; + pop_num = min(pop_num_max, pop_num);
- switch (width) { + switch (ch_width) { case 2: - fsi_dma_soft_pop16(fsi, fifo_fill); + fsi_dma_soft_pop16(fsi, pop_num); break; case 4: - fsi_dma_soft_pop32(fsi, fifo_fill); + fsi_dma_soft_pop32(fsi, pop_num); break; default: return -EINVAL; }
- fsi->byte_offset += fifo_fill * width; + fsi->buff_offset += fsi_num2offset(pop_num, ch_width);
status = fsi_reg_read(fsi, DIFF_ST); if (!startup) { @@ -763,29 +782,29 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, switch (fmt) { case SH_FSI_FMT_MONO: data = CR_MONO; - fsi->chan = 1; + fsi->chan_num = 1; break; case SH_FSI_FMT_MONO_DELAY: data = CR_MONO_D; - fsi->chan = 1; + fsi->chan_num = 1; break; case SH_FSI_FMT_PCM: data = CR_PCM; - fsi->chan = 2; + fsi->chan_num = 2; break; case SH_FSI_FMT_I2S: data = CR_I2S; - fsi->chan = 2; + fsi->chan_num = 2; break; case SH_FSI_FMT_TDM: - fsi->chan = is_play ? + fsi->chan_num = is_play ? SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags); - data = CR_TDM | (fsi->chan - 1); + data = CR_TDM | (fsi->chan_num - 1); break; case SH_FSI_FMT_TDM_DELAY: - fsi->chan = is_play ? + fsi->chan_num = is_play ? SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags); - data = CR_TDM_D | (fsi->chan - 1); + data = CR_TDM_D | (fsi->chan_num - 1); break; case SH_FSI_FMT_SPDIF: if (master->core->ver < 2) { @@ -793,7 +812,7 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, return -EINVAL; } data = CR_SPDIF; - fsi->chan = 2; + fsi->chan_num = 2; fsi_spdif_clk_ctrl(fsi, 1); fsi_reg_mask_set(fsi, OUT_SEL, 0x0010, 0x0010); break; @@ -992,7 +1011,7 @@ static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream) struct fsi_priv *fsi = fsi_get_priv(substream); long location;
- location = (fsi->byte_offset - 1); + location = (fsi->buff_offset - 1); if (location < 0) location = 0;
Current FSI driver had data push/pop functions. But the main operation of these 2 were very similar. This mean it is possible to merge these to 1 function.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
depend on [PATCH 4/5 v2] ASoC: fsi: modify variable name to easy to understand
sound/soc/sh/fsi.c | 162 +++++++++++++++++++++------------------------------ 1 files changed, 67 insertions(+), 95 deletions(-)
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index b817aae..16a028f 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -560,16 +560,18 @@ static void fsi_soft_all_reset(struct fsi_master *master) mdelay(10); }
-/* playback interrupt */ -static int fsi_data_push(struct fsi_priv *fsi, int startup) +static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int startup, int is_play) { struct snd_pcm_runtime *runtime; struct snd_pcm_substream *substream = NULL; u32 status; - int push_num; - int push_num_max; + u32 status_reg = is_play ? DOFF_ST : DIFF_ST; + int data_residue_num; + int data_num; + int data_num_max; int ch_width; int over_period; + void (*fn)(struct fsi_priv *fsi, int size);
if (!fsi || !fsi->substream || @@ -596,29 +598,63 @@ static int fsi_data_push(struct fsi_priv *fsi, int startup) /* get 1 channel data width */ ch_width = frames_to_bytes(runtime, 1) / fsi->chan_num;
- /* number of push data */ - push_num = fsi_len2num(fsi->buff_len - fsi->buff_offset, ch_width); - - /* max number of push data */ - push_num_max = (fsi->fifo_max_num * fsi->chan_num) - - fsi_get_fifo_data_num(fsi, 1); + /* get residue data number of alsa */ + data_residue_num = fsi_len2num(fsi->buff_len - fsi->buff_offset, + ch_width); + + if (is_play) { + /* + * for play-back + * + * data_num_max : number of FSI fifo free space + * data_num : number of ALSA residue data + */ + data_num_max = fsi->fifo_max_num * fsi->chan_num; + data_num_max -= fsi_get_fifo_data_num(fsi, is_play); + + data_num = data_residue_num; + + switch (ch_width) { + case 2: + fn = fsi_dma_soft_push16; + break; + case 4: + fn = fsi_dma_soft_push32; + break; + default: + return -EINVAL; + } + } else { + /* + * for capture + * + * data_num_max : number of ALSA free space + * data_num : number of data in FSI fifo + */ + data_num_max = data_residue_num; + data_num = fsi_get_fifo_data_num(fsi, is_play); + + switch (ch_width) { + case 2: + fn = fsi_dma_soft_pop16; + break; + case 4: + fn = fsi_dma_soft_pop32; + break; + default: + return -EINVAL; + } + }
- push_num = min(push_num, push_num_max); + data_num = min(data_num, data_num_max);
- switch (ch_width) { - case 2: - fsi_dma_soft_push16(fsi, push_num); - break; - case 4: - fsi_dma_soft_push32(fsi, push_num); - break; - default: - return -EINVAL; - } + fn(fsi, data_num);
- fsi->buff_offset += fsi_num2offset(push_num, ch_width); + /* update buff_offset */ + fsi->buff_offset += fsi_num2offset(data_num, ch_width);
- status = fsi_reg_read(fsi, DOFF_ST); + /* check fifo status */ + status = fsi_reg_read(fsi, status_reg); if (!startup) { struct snd_soc_dai *dai = fsi_get_dai(substream);
@@ -627,9 +663,10 @@ static int fsi_data_push(struct fsi_priv *fsi, int startup) if (status & ERR_UNDER) dev_err(dai->dev, "under run\n"); } - fsi_reg_write(fsi, DOFF_ST, 0); + fsi_reg_write(fsi, status_reg, 0);
- fsi_irq_enable(fsi, 1); + /* re-enable irq */ + fsi_irq_enable(fsi, is_play);
if (over_period) snd_pcm_period_elapsed(substream); @@ -639,77 +676,12 @@ static int fsi_data_push(struct fsi_priv *fsi, int startup)
static int fsi_data_pop(struct fsi_priv *fsi, int startup) { - struct snd_pcm_runtime *runtime; - struct snd_pcm_substream *substream = NULL; - u32 status; - int pop_num; - int pop_num_max; - int ch_width; - int over_period; - - if (!fsi || - !fsi->substream || - !fsi->substream->runtime) - return -EINVAL; - - over_period = 0; - substream = fsi->substream; - runtime = substream->runtime; - - /* FSI FIFO has limit. - * So, this driver can not send periods data at a time - */ - if (fsi->buff_offset >= - fsi_num2offset(fsi->period_num + 1, fsi->period_len)) { - - over_period = 1; - fsi->period_num = (fsi->period_num + 1) % runtime->periods; - - if (0 == fsi->period_num) - fsi->buff_offset = 0; - } - - /* get 1 channel data width */ - ch_width = frames_to_bytes(runtime, 1) / fsi->chan_num; - - /* get free space for alsa */ - pop_num_max = fsi_len2num(fsi->buff_len - fsi->buff_offset, ch_width); - - /* get recv size */ - pop_num = fsi_get_fifo_data_num(fsi, 0); - - pop_num = min(pop_num_max, pop_num); - - switch (ch_width) { - case 2: - fsi_dma_soft_pop16(fsi, pop_num); - break; - case 4: - fsi_dma_soft_pop32(fsi, pop_num); - break; - default: - return -EINVAL; - } - - fsi->buff_offset += fsi_num2offset(pop_num, ch_width); - - status = fsi_reg_read(fsi, DIFF_ST); - if (!startup) { - struct snd_soc_dai *dai = fsi_get_dai(substream); - - if (status & ERR_OVER) - dev_err(dai->dev, "over run\n"); - if (status & ERR_UNDER) - dev_err(dai->dev, "under run\n"); - } - fsi_reg_write(fsi, DIFF_ST, 0); - - fsi_irq_enable(fsi, 0); - - if (over_period) - snd_pcm_period_elapsed(substream); + return fsi_fifo_data_ctrl(fsi, startup, 0); +}
- return 0; +static int fsi_data_push(struct fsi_priv *fsi, int startup) +{ + return fsi_fifo_data_ctrl(fsi, startup, 1); }
static irqreturn_t fsi_interrupt(int irq, void *data)
On Fri, Sep 17, 2010 at 01:47:09PM +0900, Kuninori Morimoto wrote:
Dear Mark, Liam
These patches are v2 of 1st step for DMA support of FSI driver
Kuninori Morimoto (5): ASoC: fsi: Add fsi_dma_get_area ASoC: fsi: modify noisy comment out ASoC: fsi: Add fsi_dma_soft_push/pop function
Applied these three.
ASoC: fsi: modify variable name to easy to understand ASoC: fsi: merge fsi_data_push/pop to fsi_fifo_data_ctrl
I've not yet reviewed these fully.
participants (2)
-
Kuninori Morimoto
-
Mark Brown