ASoC: fsi: Add FIFO size calculate
authorKuninori Morimoto <morimoto.kuninori@renesas.com>
Thu, 25 Mar 2010 10:15:51 +0000 (19:15 +0900)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Fri, 26 Mar 2010 11:16:27 +0000 (11:16 +0000)
Signed-off-by: Kuninori Morimoto <morimoto.kuninori@renesas.com>
Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
sound/soc/sh/fsi.c

index 7c295df..ae88865 100644 (file)
@@ -46,8 +46,9 @@
 #define MUTE           0x020C
 #define CLK_RST                0x0210
 #define SOFT_RST       0x0214
+#define FIFO_SZ                0x0218
 #define MREG_START     INT_ST
-#define MREG_END       SOFT_RST
+#define MREG_END       FIFO_SZ
 
 /* DO_FMT */
 /* DI_FMT */
 #define IR             (1 <<  4) /* Interrupt Reset */
 #define FSISR          (1 <<  0) /* Software Reset */
 
+/* FIFO_SZ */
+#define OUT_SZ_MASK    0x7
+#define BO_SZ_SHIFT    8
+#define AO_SZ_SHIFT    0
+
 #define FSI_RATES SNDRV_PCM_RATE_8000_96000
 
 #define FSI_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
@@ -384,9 +390,42 @@ static void fsi_clk_ctrl(struct fsi_priv *fsi, int enable)
                fsi_master_mask_set(master, CLK_RST, val, 0);
 }
 
-static void fsi_fifo_init(struct fsi_priv *fsi, int is_play)
+static void fsi_fifo_init(struct fsi_priv *fsi,
+                         int is_play,
+                         struct snd_soc_dai *dai)
 {
-       u32 ctrl;
+       struct fsi_master *master = fsi_get_master(fsi);
+       u32 ctrl, shift, i;
+
+       /* get on-chip RAM capacity */
+       shift = fsi_master_read(master, FIFO_SZ);
+       shift >>= fsi_is_port_a(fsi) ? AO_SZ_SHIFT : BO_SZ_SHIFT;
+       shift &= OUT_SZ_MASK;
+       fsi->fifo_max = 256 << shift;
+       dev_dbg(dai->dev, "fifo = %d words\n", fsi->fifo_max);
+
+       /*
+        * The maximum number of sample data varies depending
+        * on the number of channels selected for the format.
+        *
+        * FIFOs are used in 4-channel units in 3-channel mode
+        * and in 8-channel units in 5- to 7-channel mode
+        * meaning that more FIFOs than the required size of DPRAM
+        * are used.
+        *
+        * ex) if 256 words of DP-RAM is connected
+        * 1 channel:  256 (256 x 1 = 256)
+        * 2 channels: 128 (128 x 2 = 256)
+        * 3 channels:  64 ( 64 x 3 = 192)
+        * 4 channels:  64 ( 64 x 4 = 256)
+        * 5 channels:  32 ( 32 x 5 = 160)
+        * 6 channels:  32 ( 32 x 6 = 192)
+        * 7 channels:  32 ( 32 x 7 = 224)
+        * 8 channels:  32 ( 32 x 8 = 256)
+        */
+       for (i = 1; i < fsi->chan; i <<= 1)
+               fsi->fifo_max >>= 1;
+       dev_dbg(dai->dev, "%d channel %d store\n", fsi->chan, fsi->fifo_max);
 
        ctrl = is_play ? DOFF_CTL : DIFF_CTL;
 
@@ -689,29 +728,6 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
                dev_err(dai->dev, "unknown format.\n");
                return -EINVAL;
        }
-
-       switch (fsi->chan) {
-       case 1:
-               fsi->fifo_max = 256;
-               break;
-       case 2:
-               fsi->fifo_max = 128;
-               break;
-       case 3:
-       case 4:
-               fsi->fifo_max = 64;
-               break;
-       case 5:
-       case 6:
-       case 7:
-       case 8:
-               fsi->fifo_max = 32;
-               break;
-       default:
-               dev_err(dai->dev, "channel size error.\n");
-               return -EINVAL;
-       }
-
        fsi_reg_write(fsi, reg, data);
 
        /*
@@ -725,7 +741,7 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
        fsi_irq_clear_status(fsi);
 
        /* fifo init */
-       fsi_fifo_init(fsi, is_play);
+       fsi_fifo_init(fsi, is_play, dai);
 
        return ret;
 }