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

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
...@@ -159,18 +159,27 @@ typedef int (*set_rate_func)(struct device *dev, int is_porta, int rate, int ena ...@@ -159,18 +159,27 @@ typedef int (*set_rate_func)(struct device *dev, int is_porta, int rate, int ena
* struct * struct
*/ */
struct fsi_stream_handler;
struct fsi_stream { 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 fifo_sample_capa; /* sample capacity of FSI FIFO */
int buff_sample_capa; /* sample capacity of ALSA buffer */ int buff_sample_capa; /* sample capacity of ALSA buffer */
int buff_sample_pos; /* sample position of ALSA buffer */ int buff_sample_pos; /* sample position of ALSA buffer */
int period_samples; /* sample number / 1 period */ int period_samples; /* sample number / 1 period */
int period_pos; /* current period position */ int period_pos; /* current period position */
int sample_width; /* sample width */ int sample_width; /* sample width */
int uerr_num; int uerr_num;
int oerr_num; int oerr_num;
/*
* thse are initialized by fsi_handler_init()
*/
struct fsi_stream_handler *handler;
struct fsi_priv *priv;
}; };
struct fsi_priv { struct fsi_priv {
...@@ -190,6 +199,16 @@ struct fsi_priv { ...@@ -190,6 +199,16 @@ struct fsi_priv {
long rate; 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 { struct fsi_core {
int ver; int ver;
...@@ -435,6 +454,11 @@ static int fsi_stream_is_working(struct fsi_priv *fsi, ...@@ -435,6 +454,11 @@ static int fsi_stream_is_working(struct fsi_priv *fsi,
return ret; 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, static void fsi_stream_init(struct fsi_priv *fsi,
int is_play, int is_play,
struct snd_pcm_substream *substream) struct snd_pcm_substream *substream)
...@@ -482,6 +506,53 @@ static void fsi_stream_quit(struct fsi_priv *fsi, int is_play) ...@@ -482,6 +506,53 @@ static void fsi_stream_quit(struct fsi_priv *fsi, int is_play)
spin_unlock_irqrestore(&master->lock, flags); 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 * pio function
*/ */
...@@ -743,13 +814,11 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, struct fsi_stream *io, ...@@ -743,13 +814,11 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, struct fsi_stream *io,
return 0; 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_residues; /* samples in FSI fifo */
int sample_space; /* ALSA free samples space */ int sample_space; /* ALSA free samples space */
int samples; int samples;
struct fsi_stream *io = fsi_stream_get(fsi, is_play);
sample_residues = fsi_get_current_fifo_samples(fsi, io); sample_residues = fsi_get_current_fifo_samples(fsi, io);
sample_space = io->buff_sample_capa - io->buff_sample_pos; sample_space = io->buff_sample_capa - io->buff_sample_pos;
...@@ -762,13 +831,11 @@ static int fsi_data_pop(struct fsi_priv *fsi) ...@@ -762,13 +831,11 @@ static int fsi_data_pop(struct fsi_priv *fsi)
samples); 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_residues; /* ALSA residue samples */
int sample_space; /* FSI fifo free samples space */ int sample_space; /* FSI fifo free samples space */
int samples; int samples;
struct fsi_stream *io = fsi_stream_get(fsi, is_play);
sample_residues = io->buff_sample_capa - io->buff_sample_pos; sample_residues = io->buff_sample_capa - io->buff_sample_pos;
sample_space = io->fifo_sample_capa - sample_space = io->fifo_sample_capa -
...@@ -782,6 +849,14 @@ static int fsi_data_push(struct fsi_priv *fsi) ...@@ -782,6 +849,14 @@ static int fsi_data_push(struct fsi_priv *fsi)
samples); 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) static irqreturn_t fsi_interrupt(int irq, void *data)
{ {
struct fsi_master *master = data; struct fsi_master *master = data;
...@@ -792,13 +867,13 @@ static irqreturn_t fsi_interrupt(int irq, void *data) ...@@ -792,13 +867,13 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
fsi_master_mask_set(master, SOFT_RST, IR, IR); fsi_master_mask_set(master, SOFT_RST, IR, IR);
if (int_st & AB_IO(1, AO_SHIFT)) 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)) 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)) 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)) 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->fsia);
fsi_count_fifo_err(&master->fsib); fsi_count_fifo_err(&master->fsib);
...@@ -955,14 +1030,16 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, ...@@ -955,14 +1030,16 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
struct fsi_priv *fsi = fsi_get_priv(substream); 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 is_play = fsi_is_play(substream);
int ret = 0; int ret = 0;
switch (cmd) { switch (cmd) {
case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_START:
fsi_stream_init(fsi, is_play, substream); fsi_stream_init(fsi, is_play, substream);
ret = is_play ? fsi_data_push(fsi) : fsi_data_pop(fsi); ret = fsi_stream_transfer(io);
fsi_port_start(fsi, is_play); if (0 == ret)
fsi_port_start(fsi, is_play);
break; break;
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
fsi_port_stop(fsi, is_play); fsi_port_stop(fsi, is_play);
...@@ -1224,6 +1301,13 @@ static struct snd_soc_platform_driver fsi_soc_platform = { ...@@ -1224,6 +1301,13 @@ static struct snd_soc_platform_driver fsi_soc_platform = {
/* /*
* platform function * 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) static int fsi_probe(struct platform_device *pdev)
{ {
...@@ -1270,10 +1354,22 @@ static int fsi_probe(struct platform_device *pdev) ...@@ -1270,10 +1354,22 @@ static int fsi_probe(struct platform_device *pdev)
/* FSI A setting */ /* FSI A setting */
master->fsia.base = master->base; master->fsia.base = master->base;
master->fsia.master = master; 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 */ /* FSI B setting */
master->fsib.base = master->base + 0x40; master->fsib.base = master->base + 0x40;
master->fsib.master = master; 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); pm_runtime_enable(&pdev->dev);
dev_set_drvdata(&pdev->dev, master); dev_set_drvdata(&pdev->dev, master);
...@@ -1282,7 +1378,7 @@ static int fsi_probe(struct platform_device *pdev) ...@@ -1282,7 +1378,7 @@ static int fsi_probe(struct platform_device *pdev)
id_entry->name, master); id_entry->name, master);
if (ret) { if (ret) {
dev_err(&pdev->dev, "irq request err\n"); dev_err(&pdev->dev, "irq request err\n");
goto exit_iounmap; goto exit_fsib;
} }
ret = snd_soc_register_platform(&pdev->dev, &fsi_soc_platform); ret = snd_soc_register_platform(&pdev->dev, &fsi_soc_platform);
...@@ -1304,6 +1400,10 @@ static int fsi_probe(struct platform_device *pdev) ...@@ -1304,6 +1400,10 @@ static int fsi_probe(struct platform_device *pdev)
snd_soc_unregister_platform(&pdev->dev); snd_soc_unregister_platform(&pdev->dev);
exit_free_irq: exit_free_irq:
free_irq(irq, master); free_irq(irq, master);
exit_fsib:
fsi_stream_remove(&master->fsib);
exit_fsia:
fsi_stream_remove(&master->fsia);
exit_iounmap: exit_iounmap:
iounmap(master->base); iounmap(master->base);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
...@@ -1326,6 +1426,9 @@ static int fsi_remove(struct platform_device *pdev) ...@@ -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_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai));
snd_soc_unregister_platform(&pdev->dev); snd_soc_unregister_platform(&pdev->dev);
fsi_stream_remove(&master->fsia);
fsi_stream_remove(&master->fsib);
iounmap(master->base); iounmap(master->base);
kfree(master); kfree(master);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment