Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5e97313a authored by Kuninori Morimoto's avatar Kuninori Morimoto Committed by Mark Brown
Browse files

ASoC: fsi: add fsi_stream_handler and PIO handler



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: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent 7b1b3331
Loading
Loading
Loading
Loading
+118 −15
Original line number Diff line number Diff line
@@ -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,13 +1030,15 @@ 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);
		ret = fsi_stream_transfer(io);
		if (0 == ret)
			fsi_port_start(fsi, is_play);
		break;
	case SNDRV_PCM_TRIGGER_STOP:
@@ -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 @@ static int fsi_probe(struct platform_device *pdev)
	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);