1 /* 2 * Renesas R-Car Gen1 SRU/SSI support 3 * 4 * Copyright (C) 2013 Renesas Solutions Corp. 5 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 */ 11 #include "rsnd.h" 12 13 struct rsnd_gen_ops { 14 int (*path_init)(struct rsnd_priv *priv, 15 struct rsnd_dai *rdai, 16 struct rsnd_dai_stream *io); 17 int (*path_exit)(struct rsnd_priv *priv, 18 struct rsnd_dai *rdai, 19 struct rsnd_dai_stream *io); 20 }; 21 22 struct rsnd_gen_reg_map { 23 int index; /* -1 : not supported */ 24 u32 offset_id; /* offset of ssi0, ssi1, ssi2... */ 25 u32 offset_adr; /* offset of SSICR, SSISR, ... */ 26 }; 27 28 struct rsnd_gen { 29 void __iomem *base[RSND_BASE_MAX]; 30 31 struct rsnd_gen_reg_map reg_map[RSND_REG_MAX]; 32 struct rsnd_gen_ops *ops; 33 }; 34 35 #define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen) 36 37 /* 38 * Gen2 39 * will be filled in the future 40 */ 41 42 /* 43 * Gen1 44 */ 45 static int rsnd_gen1_path_init(struct rsnd_priv *priv, 46 struct rsnd_dai *rdai, 47 struct rsnd_dai_stream *io) 48 { 49 struct rsnd_mod *mod; 50 int ret; 51 int id; 52 53 /* 54 * Gen1 is created by SRU/SSI, and this SRU is base module of 55 * Gen2's SCU/SSIU/SSI. (Gen2 SCU/SSIU came from SRU) 56 * 57 * Easy image is.. 58 * Gen1 SRU = Gen2 SCU + SSIU + etc 59 * 60 * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is 61 * using fixed path. 62 * 63 * Then, SSI id = SCU id here 64 */ 65 66 /* get SSI's ID */ 67 mod = rsnd_ssi_mod_get_frm_dai(priv, 68 rsnd_dai_id(priv, rdai), 69 rsnd_dai_is_play(rdai, io)); 70 id = rsnd_mod_id(mod); 71 72 /* SSI */ 73 mod = rsnd_ssi_mod_get(priv, id); 74 ret = rsnd_dai_connect(rdai, mod, io); 75 if (ret < 0) 76 return ret; 77 78 /* SCU */ 79 mod = rsnd_scu_mod_get(priv, id); 80 ret = rsnd_dai_connect(rdai, mod, io); 81 82 return ret; 83 } 84 85 static int rsnd_gen1_path_exit(struct rsnd_priv *priv, 86 struct rsnd_dai *rdai, 87 struct rsnd_dai_stream *io) 88 { 89 struct rsnd_mod *mod, *n; 90 int ret = 0; 91 92 /* 93 * remove all mod from rdai 94 */ 95 for_each_rsnd_mod(mod, n, io) 96 ret |= rsnd_dai_disconnect(mod); 97 98 return ret; 99 } 100 101 static struct rsnd_gen_ops rsnd_gen1_ops = { 102 .path_init = rsnd_gen1_path_init, 103 .path_exit = rsnd_gen1_path_exit, 104 }; 105 106 #define RSND_GEN1_REG_MAP(g, s, i, oi, oa) \ 107 do { \ 108 (g)->reg_map[RSND_REG_##i].index = RSND_GEN1_##s; \ 109 (g)->reg_map[RSND_REG_##i].offset_id = oi; \ 110 (g)->reg_map[RSND_REG_##i].offset_adr = oa; \ 111 } while (0) 112 113 static void rsnd_gen1_reg_map_init(struct rsnd_gen *gen) 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); 120 RSND_GEN1_REG_MAP(gen, SRU, SSI_MODE0, 0x0, 0xD0); 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); 124 125 RSND_GEN1_REG_MAP(gen, ADG, BRRA, 0x0, 0x00); 126 RSND_GEN1_REG_MAP(gen, ADG, BRRB, 0x0, 0x04); 127 RSND_GEN1_REG_MAP(gen, ADG, SSICKR, 0x0, 0x08); 128 RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL0, 0x0, 0x0c); 129 RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL1, 0x0, 0x10); 130 RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL3, 0x0, 0x18); 131 RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL4, 0x0, 0x1c); 132 RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL5, 0x0, 0x20); 133 134 RSND_GEN1_REG_MAP(gen, SSI, SSICR, 0x40, 0x00); 135 RSND_GEN1_REG_MAP(gen, SSI, SSISR, 0x40, 0x04); 136 RSND_GEN1_REG_MAP(gen, SSI, SSITDR, 0x40, 0x08); 137 RSND_GEN1_REG_MAP(gen, SSI, SSIRDR, 0x40, 0x0c); 138 RSND_GEN1_REG_MAP(gen, SSI, SSIWSR, 0x40, 0x20); 139 } 140 141 static int rsnd_gen1_probe(struct platform_device *pdev, 142 struct rcar_snd_info *info, 143 struct rsnd_priv *priv) 144 { 145 struct device *dev = rsnd_priv_to_dev(priv); 146 struct rsnd_gen *gen = rsnd_priv_to_gen(priv); 147 struct resource *sru_res; 148 struct resource *adg_res; 149 struct resource *ssi_res; 150 151 /* 152 * map address 153 */ 154 sru_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_SRU); 155 adg_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_ADG); 156 ssi_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_SSI); 157 158 gen->base[RSND_GEN1_SRU] = devm_ioremap_resource(dev, sru_res); 159 gen->base[RSND_GEN1_ADG] = devm_ioremap_resource(dev, adg_res); 160 gen->base[RSND_GEN1_SSI] = devm_ioremap_resource(dev, ssi_res); 161 if (IS_ERR(gen->base[RSND_GEN1_SRU]) || 162 IS_ERR(gen->base[RSND_GEN1_ADG]) || 163 IS_ERR(gen->base[RSND_GEN1_SSI])) 164 return -ENODEV; 165 166 gen->ops = &rsnd_gen1_ops; 167 rsnd_gen1_reg_map_init(gen); 168 169 dev_dbg(dev, "Gen1 device probed\n"); 170 dev_dbg(dev, "SRU : %08x => %p\n", sru_res->start, 171 gen->base[RSND_GEN1_SRU]); 172 dev_dbg(dev, "ADG : %08x => %p\n", adg_res->start, 173 gen->base[RSND_GEN1_ADG]); 174 dev_dbg(dev, "SSI : %08x => %p\n", ssi_res->start, 175 gen->base[RSND_GEN1_SSI]); 176 177 return 0; 178 179 } 180 181 static void rsnd_gen1_remove(struct platform_device *pdev, 182 struct rsnd_priv *priv) 183 { 184 } 185 186 /* 187 * Gen 188 */ 189 int rsnd_gen_path_init(struct rsnd_priv *priv, 190 struct rsnd_dai *rdai, 191 struct rsnd_dai_stream *io) 192 { 193 struct rsnd_gen *gen = rsnd_priv_to_gen(priv); 194 195 return gen->ops->path_init(priv, rdai, io); 196 } 197 198 int rsnd_gen_path_exit(struct rsnd_priv *priv, 199 struct rsnd_dai *rdai, 200 struct rsnd_dai_stream *io) 201 { 202 struct rsnd_gen *gen = rsnd_priv_to_gen(priv); 203 204 return gen->ops->path_exit(priv, rdai, io); 205 } 206 207 void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, 208 struct rsnd_mod *mod, 209 enum rsnd_reg reg) 210 { 211 struct rsnd_gen *gen = rsnd_priv_to_gen(priv); 212 struct device *dev = rsnd_priv_to_dev(priv); 213 int index; 214 u32 offset_id, offset_adr; 215 216 if (reg >= RSND_REG_MAX) { 217 dev_err(dev, "rsnd_reg reg error\n"); 218 return NULL; 219 } 220 221 index = gen->reg_map[reg].index; 222 offset_id = gen->reg_map[reg].offset_id; 223 offset_adr = gen->reg_map[reg].offset_adr; 224 225 if (index < 0) { 226 dev_err(dev, "unsupported reg access %d\n", reg); 227 return NULL; 228 } 229 230 if (offset_id && mod) 231 offset_id *= rsnd_mod_id(mod); 232 233 /* 234 * index/offset were set on gen1/gen2 235 */ 236 237 return gen->base[index] + offset_id + offset_adr; 238 } 239 240 int rsnd_gen_probe(struct platform_device *pdev, 241 struct rcar_snd_info *info, 242 struct rsnd_priv *priv) 243 { 244 struct device *dev = rsnd_priv_to_dev(priv); 245 struct rsnd_gen *gen; 246 int i; 247 248 gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL); 249 if (!gen) { 250 dev_err(dev, "GEN allocate failed\n"); 251 return -ENOMEM; 252 } 253 254 priv->gen = gen; 255 256 /* 257 * see 258 * rsnd_reg_get() 259 * rsnd_gen_probe() 260 */ 261 for (i = 0; i < RSND_REG_MAX; i++) 262 gen->reg_map[i].index = -1; 263 264 /* 265 * init each module 266 */ 267 if (rsnd_is_gen1(priv)) 268 return rsnd_gen1_probe(pdev, info, priv); 269 270 dev_err(dev, "unknown generation R-Car sound device\n"); 271 272 return -ENODEV; 273 } 274 275 void rsnd_gen_remove(struct platform_device *pdev, 276 struct rsnd_priv *priv) 277 { 278 if (rsnd_is_gen1(priv)) 279 rsnd_gen1_remove(pdev, priv); 280 } 281