[alsa-devel] [PATCH 11/19] ASoC: fsi: add fsi_stream_handler and PIO handler

Kuninori Morimoto kuninori.morimoto.gx at renesas.com
Fri Feb 3 09:55:55 CET 2012


This patch adds struct fsi_stream_handler and defined fsi_pio_push/pop_handler.
these are controled by fsi_steam_xxx() function.

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

diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 24dbe16..b02886a 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -159,18 +159,27 @@ typedef int (*set_rate_func)(struct device *dev, int is_porta, int rate, int ena
  *		struct
  */
 
+struct fsi_stream_handler;
 struct fsi_stream {
-	struct snd_pcm_substream *substream;
 
+	/*
+	 * these are initialized by fsi_stream_init()
+	 */
+	struct snd_pcm_substream *substream;
 	int fifo_sample_capa;	/* sample capacity of FSI FIFO */
 	int buff_sample_capa;	/* sample capacity of ALSA buffer */
 	int buff_sample_pos;	/* sample position of ALSA buffer */
 	int period_samples;	/* sample number / 1 period */
 	int period_pos;		/* current period position */
 	int sample_width;	/* sample width */
-
 	int uerr_num;
 	int oerr_num;
+
+	/*
+	 * thse are initialized by fsi_handler_init()
+	 */
+	struct fsi_stream_handler *handler;
+	struct fsi_priv		*priv;
 };
 
 struct fsi_priv {
@@ -190,6 +199,16 @@ struct fsi_priv {
 	long rate;
 };
 
+struct fsi_stream_handler {
+	int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io);
+	int (*transfer)(struct fsi_priv *fsi, struct fsi_stream *io);
+	int (*remove)(struct fsi_priv *fsi, struct fsi_stream *io);
+};
+#define fsi_stream_handler_call(io, func, args...)	\
+	(!(io) ? -ENODEV :				\
+	 !((io)->handler->func) ? 0 :			\
+	 (io)->handler->func(args))
+
 struct fsi_core {
 	int ver;
 
@@ -435,6 +454,11 @@ static int fsi_stream_is_working(struct fsi_priv *fsi,
 	return ret;
 }
 
+static struct fsi_priv *fsi_stream_to_priv(struct fsi_stream *io)
+{
+	return io->priv;
+}
+
 static void fsi_stream_init(struct fsi_priv *fsi,
 			    int is_play,
 			    struct snd_pcm_substream *substream)
@@ -482,6 +506,53 @@ static void fsi_stream_quit(struct fsi_priv *fsi, int is_play)
 	spin_unlock_irqrestore(&master->lock, flags);
 }
 
+static int fsi_stream_transfer(struct fsi_stream *io)
+{
+	struct fsi_priv *fsi = fsi_stream_to_priv(io);
+	if (!fsi)
+		return -EIO;
+
+	return fsi_stream_handler_call(io, transfer, fsi, io);
+}
+
+static int fsi_stream_probe(struct fsi_priv *fsi)
+{
+	struct fsi_stream *io;
+	int ret1, ret2;
+
+	io = &fsi->playback;
+	ret1 = fsi_stream_handler_call(io, probe, fsi, io);
+
+	io = &fsi->capture;
+	ret2 = fsi_stream_handler_call(io, probe, fsi, io);
+
+	if (ret1 < 0)
+		return ret1;
+	if (ret2 < 0)
+		return ret2;
+
+	return 0;
+}
+
+static int fsi_stream_remove(struct fsi_priv *fsi)
+{
+	struct fsi_stream *io;
+	int ret1, ret2;
+
+	io = &fsi->playback;
+	ret1 = fsi_stream_handler_call(io, remove, fsi, io);
+
+	io = &fsi->capture;
+	ret2 = fsi_stream_handler_call(io, remove, fsi, io);
+
+	if (ret1 < 0)
+		return ret1;
+	if (ret2 < 0)
+		return ret2;
+
+	return 0;
+}
+
 /*
  *		pio function
  */
@@ -743,13 +814,11 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, struct fsi_stream *io,
 	return 0;
 }
 
-static int fsi_data_pop(struct fsi_priv *fsi)
+static int fsi_pio_pop(struct fsi_priv *fsi, struct fsi_stream *io)
 {
-	int is_play = 0;
 	int sample_residues;	/* samples in FSI fifo */
 	int sample_space;	/* ALSA free samples space */
 	int samples;
-	struct fsi_stream *io = fsi_stream_get(fsi, is_play);
 
 	sample_residues	= fsi_get_current_fifo_samples(fsi, io);
 	sample_space	= io->buff_sample_capa - io->buff_sample_pos;
@@ -762,13 +831,11 @@ static int fsi_data_pop(struct fsi_priv *fsi)
 				  samples);
 }
 
-static int fsi_data_push(struct fsi_priv *fsi)
+static int fsi_pio_push(struct fsi_priv *fsi, struct fsi_stream *io)
 {
-	int is_play = 1;
 	int sample_residues;	/* ALSA residue samples */
 	int sample_space;	/* FSI fifo free samples space */
 	int samples;
-	struct fsi_stream *io = fsi_stream_get(fsi, is_play);
 
 	sample_residues	= io->buff_sample_capa - io->buff_sample_pos;
 	sample_space	= io->fifo_sample_capa -
@@ -782,6 +849,14 @@ static int fsi_data_push(struct fsi_priv *fsi)
 				  samples);
 }
 
+static struct fsi_stream_handler fsi_pio_push_handler = {
+	.transfer	= fsi_pio_push,
+};
+
+static struct fsi_stream_handler fsi_pio_pop_handler = {
+	.transfer	= fsi_pio_pop,
+};
+
 static irqreturn_t fsi_interrupt(int irq, void *data)
 {
 	struct fsi_master *master = data;
@@ -792,13 +867,13 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
 	fsi_master_mask_set(master, SOFT_RST, IR, IR);
 
 	if (int_st & AB_IO(1, AO_SHIFT))
-		fsi_data_push(&master->fsia);
+		fsi_stream_transfer(&master->fsia.playback);
 	if (int_st & AB_IO(1, BO_SHIFT))
-		fsi_data_push(&master->fsib);
+		fsi_stream_transfer(&master->fsib.playback);
 	if (int_st & AB_IO(1, AI_SHIFT))
-		fsi_data_pop(&master->fsia);
+		fsi_stream_transfer(&master->fsia.capture);
 	if (int_st & AB_IO(1, BI_SHIFT))
-		fsi_data_pop(&master->fsib);
+		fsi_stream_transfer(&master->fsib.capture);
 
 	fsi_count_fifo_err(&master->fsia);
 	fsi_count_fifo_err(&master->fsib);
@@ -955,14 +1030,16 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
 			   struct snd_soc_dai *dai)
 {
 	struct fsi_priv *fsi = fsi_get_priv(substream);
+	struct fsi_stream *io = fsi_stream_get(fsi, fsi_is_play(substream));
 	int is_play = fsi_is_play(substream);
 	int ret = 0;
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 		fsi_stream_init(fsi, is_play, substream);
-		ret = is_play ? fsi_data_push(fsi) : fsi_data_pop(fsi);
-		fsi_port_start(fsi, is_play);
+		ret = fsi_stream_transfer(io);
+		if (0 == ret)
+			fsi_port_start(fsi, is_play);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 		fsi_port_stop(fsi, is_play);
@@ -1224,6 +1301,13 @@ static struct snd_soc_platform_driver fsi_soc_platform = {
 /*
  *		platform function
  */
+static void fsi_handler_init(struct fsi_priv *fsi)
+{
+	fsi->playback.handler	= &fsi_pio_push_handler; /* default PIO */
+	fsi->playback.priv	= fsi;
+	fsi->capture.handler	= &fsi_pio_pop_handler;  /* default PIO */
+	fsi->capture.priv	= fsi;
+}
 
 static int fsi_probe(struct platform_device *pdev)
 {
@@ -1270,10 +1354,22 @@ static int fsi_probe(struct platform_device *pdev)
 	/* FSI A setting */
 	master->fsia.base	= master->base;
 	master->fsia.master	= master;
+	fsi_handler_init(&master->fsia);
+	ret = fsi_stream_probe(&master->fsia);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "FSIA stream probe failed\n");
+		goto exit_iounmap;
+	}
 
 	/* FSI B setting */
 	master->fsib.base	= master->base + 0x40;
 	master->fsib.master	= master;
+	fsi_handler_init(&master->fsib);
+	ret = fsi_stream_probe(&master->fsib);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "FSIB stream probe failed\n");
+		goto exit_fsia;
+	}
 
 	pm_runtime_enable(&pdev->dev);
 	dev_set_drvdata(&pdev->dev, master);
@@ -1282,7 +1378,7 @@ static int fsi_probe(struct platform_device *pdev)
 			  id_entry->name, master);
 	if (ret) {
 		dev_err(&pdev->dev, "irq request err\n");
-		goto exit_iounmap;
+		goto exit_fsib;
 	}
 
 	ret = snd_soc_register_platform(&pdev->dev, &fsi_soc_platform);
@@ -1304,6 +1400,10 @@ exit_snd_soc:
 	snd_soc_unregister_platform(&pdev->dev);
 exit_free_irq:
 	free_irq(irq, master);
+exit_fsib:
+	fsi_stream_remove(&master->fsib);
+exit_fsia:
+	fsi_stream_remove(&master->fsia);
 exit_iounmap:
 	iounmap(master->base);
 	pm_runtime_disable(&pdev->dev);
@@ -1326,6 +1426,9 @@ static int fsi_remove(struct platform_device *pdev)
 	snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai));
 	snd_soc_unregister_platform(&pdev->dev);
 
+	fsi_stream_remove(&master->fsia);
+	fsi_stream_remove(&master->fsib);
+
 	iounmap(master->base);
 	kfree(master);
 
-- 
1.7.5.4



More information about the Alsa-devel mailing list