[alsa-devel] [PATCH 4/4] ASoC: fsi: merge fsi_data_push/pop to fsi_fifo_data_ctrl

Kuninori Morimoto kuninori.morimoto.gx at renesas.com
Thu Sep 16 06:34:40 CEST 2010


Current FSI driver had data push/pop functions.
But the main difference of these 2 were only data src/dst address.
This mean it is possible to merge these to 1 function.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx at renesas.com>
---
 sound/soc/sh/fsi.c |  161 +++++++++++++++++++++------------------------------
 1 files changed, 66 insertions(+), 95 deletions(-)

diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 06f1e1b..ef7a606 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -580,16 +580,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		||
@@ -616,29 +618,62 @@ 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_ofs, ch_width);
+	/* get residue data number of alsa */
+	data_residue_num = fsi_len2num(fsi->buff_len - fsi->buff_ofs, ch_width);
 
-	/* max number of push data */
-	push_num_max = (fsi->fifo_max_num * fsi->chan_num) -
-			fsi_get_fifo_data_num(fsi, 1);
+	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);
 
-	push_num = min(push_num, push_num_max);
+		data_num = data_residue_num;
 
-	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;
+		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;
+		}
 	}
 
-	fsi->buff_ofs += fsi_num2ofs(push_num, ch_width);
+	data_num = min(data_num, data_num_max);
+
+	fn(fsi, data_num);
 
-	status = fsi_reg_read(fsi, DOFF_ST);
+	/* update buff_ofs */
+	fsi->buff_ofs += fsi_num2ofs(data_num, ch_width);
+
+	/* check fifo status */
+	status = fsi_reg_read(fsi, status_reg);
 	if (!startup) {
 		struct snd_soc_dai *dai = fsi_get_dai(substream);
 
@@ -647,9 +682,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);
@@ -659,77 +695,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_ofs >=
-	    fsi_num2ofs(fsi->period_num + 1, fsi->period_width)) {
-
-		over_period = 1;
-		fsi->period_num = (fsi->period_num + 1) % runtime->periods;
-
-		if (0 == fsi->period_num)
-			fsi->buff_ofs = 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_ofs, 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_ofs += fsi_num2ofs(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)
-- 
1.7.0.4



More information about the Alsa-devel mailing list