Commit 374a528111fa07878090bd9694a3e153814de39c

Authored by Kuninori Morimoto
Committed by Mark Brown
1 parent 849fc82a6f

ASoC: rsnd: SSI supports DMA transfer via BUSIF

This patch adds BUSIF support for R-Car sound DMAEngine transfer.
The sound data will be transferred via FIFO which can cover blank time
which will happen when DMA channel is switching.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@linaro.org>

Showing 5 changed files with 190 additions and 7 deletions Side-by-side Diff

include/sound/rcar_snd.h
... ... @@ -36,6 +36,7 @@
36 36 #define RSND_SSI_CLK_PIN_SHARE (1 << 31)
37 37 #define RSND_SSI_CLK_FROM_ADG (1 << 30) /* clock parent is master */
38 38 #define RSND_SSI_SYNC (1 << 29) /* SSI34_sync etc */
  39 +#define RSND_SSI_DEPENDENT (1 << 28) /* SSI needs SRU/SCU */
39 40  
40 41 #define RSND_SSI_PLAY (1 << 24)
41 42  
... ... @@ -50,6 +51,11 @@
50 51 int pio_irq;
51 52 u32 flags;
52 53 };
  54 +
  55 +/*
  56 + * flags
  57 + */
  58 +#define RSND_SCU_USB_HPBIF (1 << 31) /* it needs RSND_SSI_DEPENDENT */
53 59  
54 60 struct rsnd_scu_platform_info {
55 61 u32 flags;
sound/soc/sh/rcar/gen.c
... ... @@ -34,9 +34,6 @@
34 34  
35 35 #define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen)
36 36  
37   -#define rsnd_is_gen1(s) ((s)->info->flags & RSND_GEN1)
38   -#define rsnd_is_gen2(s) ((s)->info->flags & RSND_GEN2)
39   -
40 37 /*
41 38 * Gen2
42 39 * will be filled in the future
43 40  
... ... @@ -115,8 +112,15 @@
115 112  
116 113 static void rsnd_gen1_reg_map_init(struct rsnd_gen *gen)
117 114 {
  115 + RSND_GEN1_REG_MAP(gen, SRU, SRC_ROUTE_SEL, 0x0, 0x00);
  116 + RSND_GEN1_REG_MAP(gen, SRU, SRC_TMG_SEL0, 0x0, 0x08);
  117 + RSND_GEN1_REG_MAP(gen, SRU, SRC_TMG_SEL1, 0x0, 0x0c);
  118 + RSND_GEN1_REG_MAP(gen, SRU, SRC_TMG_SEL2, 0x0, 0x10);
  119 + RSND_GEN1_REG_MAP(gen, SRU, SRC_CTRL, 0x0, 0xc0);
118 120 RSND_GEN1_REG_MAP(gen, SRU, SSI_MODE0, 0x0, 0xD0);
119 121 RSND_GEN1_REG_MAP(gen, SRU, SSI_MODE1, 0x0, 0xD4);
  122 + RSND_GEN1_REG_MAP(gen, SRU, BUSIF_MODE, 0x4, 0x20);
  123 + RSND_GEN1_REG_MAP(gen, SRU, BUSIF_ADINR, 0x40, 0x214);
120 124  
121 125 RSND_GEN1_REG_MAP(gen, ADG, BRRA, 0x0, 0x00);
122 126 RSND_GEN1_REG_MAP(gen, ADG, BRRB, 0x0, 0x04);
sound/soc/sh/rcar/rsnd.h
... ... @@ -32,8 +32,15 @@
32 32 */
33 33 enum rsnd_reg {
34 34 /* SRU/SCU */
  35 + RSND_REG_SRC_ROUTE_SEL,
  36 + RSND_REG_SRC_TMG_SEL0,
  37 + RSND_REG_SRC_TMG_SEL1,
  38 + RSND_REG_SRC_TMG_SEL2,
  39 + RSND_REG_SRC_CTRL,
35 40 RSND_REG_SSI_MODE0,
36 41 RSND_REG_SSI_MODE1,
  42 + RSND_REG_BUSIF_MODE,
  43 + RSND_REG_BUSIF_ADINR,
37 44  
38 45 /* ADG */
39 46 RSND_REG_BRRA,
... ... @@ -213,6 +220,8 @@
213 220 void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv,
214 221 struct rsnd_mod *mod,
215 222 enum rsnd_reg reg);
  223 +#define rsnd_is_gen1(s) ((s)->info->flags & RSND_GEN1)
  224 +#define rsnd_is_gen2(s) ((s)->info->flags & RSND_GEN2)
216 225  
217 226 /*
218 227 * R-Car ADG
sound/soc/sh/rcar/scu.c
... ... @@ -15,6 +15,18 @@
15 15 struct rsnd_mod mod;
16 16 };
17 17  
  18 +#define rsnd_scu_mode_flags(p) ((p)->info->flags)
  19 +
  20 +/*
  21 + * ADINR
  22 + */
  23 +#define OTBL_24 (0 << 16)
  24 +#define OTBL_22 (2 << 16)
  25 +#define OTBL_20 (4 << 16)
  26 +#define OTBL_18 (6 << 16)
  27 +#define OTBL_16 (8 << 16)
  28 +
  29 +
18 30 #define rsnd_mod_to_scu(_mod) \
19 31 container_of((_mod), struct rsnd_scu, mod)
20 32  
... ... @@ -24,6 +36,116 @@
24 36 ((pos) = (struct rsnd_scu *)(priv)->scu + i); \
25 37 i++)
26 38  
  39 +static int rsnd_scu_set_route(struct rsnd_priv *priv,
  40 + struct rsnd_mod *mod,
  41 + struct rsnd_dai *rdai,
  42 + struct rsnd_dai_stream *io)
  43 +{
  44 + struct scu_route_config {
  45 + u32 mask;
  46 + int shift;
  47 + } routes[] = {
  48 + { 0xF, 0, }, /* 0 */
  49 + { 0xF, 4, }, /* 1 */
  50 + { 0xF, 8, }, /* 2 */
  51 + { 0x7, 12, }, /* 3 */
  52 + { 0x7, 16, }, /* 4 */
  53 + { 0x7, 20, }, /* 5 */
  54 + { 0x7, 24, }, /* 6 */
  55 + { 0x3, 28, }, /* 7 */
  56 + { 0x3, 30, }, /* 8 */
  57 + };
  58 +
  59 + u32 mask;
  60 + u32 val;
  61 + int shift;
  62 + int id;
  63 +
  64 + /*
  65 + * Gen1 only
  66 + */
  67 + if (!rsnd_is_gen1(priv))
  68 + return 0;
  69 +
  70 + id = rsnd_mod_id(mod);
  71 + if (id < 0 || id > ARRAY_SIZE(routes))
  72 + return -EIO;
  73 +
  74 + /*
  75 + * SRC_ROUTE_SELECT
  76 + */
  77 + val = rsnd_dai_is_play(rdai, io) ? 0x1 : 0x2;
  78 + val = val << routes[id].shift;
  79 + mask = routes[id].mask << routes[id].shift;
  80 +
  81 + rsnd_mod_bset(mod, SRC_ROUTE_SEL, mask, val);
  82 +
  83 + /*
  84 + * SRC_TIMING_SELECT
  85 + */
  86 + shift = (id % 4) * 8;
  87 + mask = 0x1F << shift;
  88 + if (8 == id) /* SRU8 is very special */
  89 + val = id << shift;
  90 + else
  91 + val = (id + 1) << shift;
  92 +
  93 + switch (id / 4) {
  94 + case 0:
  95 + rsnd_mod_bset(mod, SRC_TMG_SEL0, mask, val);
  96 + break;
  97 + case 1:
  98 + rsnd_mod_bset(mod, SRC_TMG_SEL1, mask, val);
  99 + break;
  100 + case 2:
  101 + rsnd_mod_bset(mod, SRC_TMG_SEL2, mask, val);
  102 + break;
  103 + }
  104 +
  105 + return 0;
  106 +}
  107 +
  108 +static int rsnd_scu_set_mode(struct rsnd_priv *priv,
  109 + struct rsnd_mod *mod,
  110 + struct rsnd_dai *rdai,
  111 + struct rsnd_dai_stream *io)
  112 +{
  113 + int id = rsnd_mod_id(mod);
  114 + u32 val;
  115 +
  116 + if (rsnd_is_gen1(priv)) {
  117 + val = (1 << id);
  118 + rsnd_mod_bset(mod, SRC_CTRL, val, val);
  119 + }
  120 +
  121 + return 0;
  122 +}
  123 +
  124 +static int rsnd_scu_set_hpbif(struct rsnd_priv *priv,
  125 + struct rsnd_mod *mod,
  126 + struct rsnd_dai *rdai,
  127 + struct rsnd_dai_stream *io)
  128 +{
  129 + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
  130 + u32 adinr = runtime->channels;
  131 +
  132 + switch (runtime->sample_bits) {
  133 + case 16:
  134 + adinr |= OTBL_16;
  135 + break;
  136 + case 32:
  137 + adinr |= OTBL_24;
  138 + break;
  139 + default:
  140 + return -EIO;
  141 + }
  142 +
  143 + rsnd_mod_write(mod, BUSIF_MODE, 1);
  144 + rsnd_mod_write(mod, BUSIF_ADINR, adinr);
  145 +
  146 + return 0;
  147 +}
  148 +
27 149 static int rsnd_scu_init(struct rsnd_mod *mod,
28 150 struct rsnd_dai *rdai,
29 151 struct rsnd_dai_stream *io)
30 152  
31 153  
32 154  
... ... @@ -53,10 +175,37 @@
53 175 struct rsnd_dai_stream *io)
54 176 {
55 177 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
  178 + struct rsnd_scu *scu = rsnd_mod_to_scu(mod);
56 179 struct device *dev = rsnd_priv_to_dev(priv);
  180 + u32 flags = rsnd_scu_mode_flags(scu);
  181 + int ret;
57 182  
58   - dev_dbg(dev, "%s.%d start\n", rsnd_mod_name(mod), rsnd_mod_id(mod));
  183 + /*
  184 + * SCU will be used if it has RSND_SCU_USB_HPBIF flags
  185 + */
  186 + if (!(flags & RSND_SCU_USB_HPBIF)) {
  187 + /* it use PIO transter */
  188 + dev_dbg(dev, "%s%d is not used\n",
  189 + rsnd_mod_name(mod), rsnd_mod_id(mod));
59 190  
  191 + return 0;
  192 + }
  193 +
  194 + /* it use DMA transter */
  195 + ret = rsnd_scu_set_route(priv, mod, rdai, io);
  196 + if (ret < 0)
  197 + return ret;
  198 +
  199 + ret = rsnd_scu_set_mode(priv, mod, rdai, io);
  200 + if (ret < 0)
  201 + return ret;
  202 +
  203 + ret = rsnd_scu_set_hpbif(priv, mod, rdai, io);
  204 + if (ret < 0)
  205 + return ret;
  206 +
  207 + dev_dbg(dev, "%s%d start\n", rsnd_mod_name(mod), rsnd_mod_id(mod));
  208 +
60 209 return 0;
61 210 }
62 211  
63 212  
... ... @@ -112,8 +261,9 @@
112 261 rsnd_mod_init(priv, &scu->mod,
113 262 &rsnd_scu_ops, i);
114 263 scu->info = &info->scu_info[i];
115   - }
116 264  
  265 + dev_dbg(dev, "SCU%d probed\n", i);
  266 + }
117 267 dev_dbg(dev, "scu probed\n");
118 268  
119 269 return 0;
sound/soc/sh/rcar/ssi.c
... ... @@ -104,6 +104,7 @@
104 104 static void rsnd_ssi_mode_init(struct rsnd_priv *priv,
105 105 struct rsnd_ssiu *ssiu)
106 106 {
  107 + struct device *dev = rsnd_priv_to_dev(priv);
107 108 struct rsnd_ssi *ssi;
108 109 u32 flags;
109 110 u32 val;
110 111  
... ... @@ -113,9 +114,18 @@
113 114 * SSI_MODE0
114 115 */
115 116 ssiu->ssi_mode0 = 0;
116   - for_each_rsnd_ssi(ssi, priv, i)
117   - ssiu->ssi_mode0 |= (1 << i);
  117 + for_each_rsnd_ssi(ssi, priv, i) {
  118 + flags = rsnd_ssi_mode_flags(ssi);
118 119  
  120 + /* see also BUSIF_MODE */
  121 + if (!(flags & RSND_SSI_DEPENDENT)) {
  122 + ssiu->ssi_mode0 |= (1 << i);
  123 + dev_dbg(dev, "SSI%d uses INDEPENDENT mode\n", i);
  124 + } else {
  125 + dev_dbg(dev, "SSI%d uses DEPENDENT mode\n", i);
  126 + }
  127 + }
  128 +
119 129 /*
120 130 * SSI_MODE1
121 131 */
... ... @@ -670,6 +680,8 @@
670 680 dev_info(dev, "SSI DMA failed. try PIO transter\n");
671 681 else
672 682 ops = &rsnd_ssi_dma_ops;
  683 +
  684 + dev_dbg(dev, "SSI%d use DMA transfer\n", i);
673 685 }
674 686  
675 687 /*
... ... @@ -687,6 +699,8 @@
687 699 }
688 700  
689 701 ops = &rsnd_ssi_pio_ops;
  702 +
  703 + dev_dbg(dev, "SSI%d use PIO transfer\n", i);
690 704 }
691 705  
692 706 rsnd_mod_init(priv, &ssi->mod, ops, i);