OSDN Git Service

ASoC: fsi: use PIO handler if DMA handler was invalid
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Fri, 25 May 2012 06:56:19 +0000 (23:56 -0700)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Sun, 3 Jun 2012 12:06:39 +0000 (13:06 +0100)
PIO handler is not good performance, but works on all platform.
So, switch to PIO handler if DMA handler was invalid case.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
sound/soc/sh/fsi.c

index fcaa6b8..53486ff 100644 (file)
@@ -247,7 +247,7 @@ struct fsi_priv {
 struct fsi_stream_handler {
        int (*init)(struct fsi_priv *fsi, struct fsi_stream *io);
        int (*quit)(struct fsi_priv *fsi, struct fsi_stream *io);
-       int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io);
+       int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev);
        int (*transfer)(struct fsi_priv *fsi, struct fsi_stream *io);
        int (*remove)(struct fsi_priv *fsi, struct fsi_stream *io);
        void (*start_stop)(struct fsi_priv *fsi, struct fsi_stream *io,
@@ -571,16 +571,16 @@ static int fsi_stream_transfer(struct fsi_stream *io)
 #define fsi_stream_stop(fsi, io)\
        fsi_stream_handler_call(io, start_stop, fsi, io, 0)
 
-static int fsi_stream_probe(struct fsi_priv *fsi)
+static int fsi_stream_probe(struct fsi_priv *fsi, struct device *dev)
 {
        struct fsi_stream *io;
        int ret1, ret2;
 
        io = &fsi->playback;
-       ret1 = fsi_stream_handler_call(io, probe, fsi, io);
+       ret1 = fsi_stream_handler_call(io, probe, fsi, io, dev);
 
        io = &fsi->capture;
-       ret2 = fsi_stream_handler_call(io, probe, fsi, io);
+       ret2 = fsi_stream_handler_call(io, probe, fsi, io, dev);
 
        if (ret1 < 0)
                return ret1;
@@ -1173,7 +1173,7 @@ static void fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
                fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
 }
 
-static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io)
+static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev)
 {
        dma_cap_mask_t mask;
 
@@ -1181,8 +1181,19 @@ static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io)
        dma_cap_set(DMA_SLAVE, mask);
 
        io->chan = dma_request_channel(mask, fsi_dma_filter, &io->slave);
-       if (!io->chan)
-               return -EIO;
+       if (!io->chan) {
+
+               /* switch to PIO handler */
+               if (fsi_stream_is_play(fsi, io))
+                       fsi->playback.handler   = &fsi_pio_push_handler;
+               else
+                       fsi->capture.handler    = &fsi_pio_pop_handler;
+
+               dev_info(dev, "switch handler (dma => pio)\n");
+
+               /* probe again */
+               return fsi_stream_probe(fsi, dev);
+       }
 
        tasklet_init(&io->tasklet, fsi_dma_do_tasklet, (unsigned long)io);
 
@@ -1672,7 +1683,7 @@ static int fsi_probe(struct platform_device *pdev)
        master->fsia.master     = master;
        master->fsia.info       = &info->port_a;
        fsi_handler_init(&master->fsia);
-       ret = fsi_stream_probe(&master->fsia);
+       ret = fsi_stream_probe(&master->fsia, &pdev->dev);
        if (ret < 0) {
                dev_err(&pdev->dev, "FSIA stream probe failed\n");
                goto exit_iounmap;
@@ -1683,7 +1694,7 @@ static int fsi_probe(struct platform_device *pdev)
        master->fsib.master     = master;
        master->fsib.info       = &info->port_b;
        fsi_handler_init(&master->fsib);
-       ret = fsi_stream_probe(&master->fsib);
+       ret = fsi_stream_probe(&master->fsib, &pdev->dev);
        if (ret < 0) {
                dev_err(&pdev->dev, "FSIB stream probe failed\n");
                goto exit_fsia;