diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2013-09-24 02:12:27 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-09-24 14:53:36 -0400 |
commit | 55e5b6fd5af04b6d8b0ac6635edf49476ff298ba (patch) | |
tree | 8a80a5daad4dcada6ceaffaa6b634bbbe4751afd /sound/soc/sh/rcar/gen.c | |
parent | efeb970ee799b80c984a42d5706081af6047e160 (diff) |
ASoC: rsnd: use regmap instead of original register mapping method
Current Linux kernel is supporting regmap/regmap_field,
and, it is good match for Renesas Sound Gen1/Gen2 register mapping.
This patch uses regmap instead of original method for register access
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound/soc/sh/rcar/gen.c')
-rw-r--r-- | sound/soc/sh/rcar/gen.c | 224 |
1 files changed, 143 insertions, 81 deletions
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 331fc558d796..61212ee97c28 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c | |||
@@ -24,21 +24,97 @@ struct rsnd_gen_ops { | |||
24 | struct rsnd_dai_stream *io); | 24 | struct rsnd_dai_stream *io); |
25 | }; | 25 | }; |
26 | 26 | ||
27 | struct rsnd_gen_reg_map { | ||
28 | int index; /* -1 : not supported */ | ||
29 | u32 offset_id; /* offset of ssi0, ssi1, ssi2... */ | ||
30 | u32 offset_adr; /* offset of SSICR, SSISR, ... */ | ||
31 | }; | ||
32 | |||
33 | struct rsnd_gen { | 27 | struct rsnd_gen { |
34 | void __iomem *base[RSND_BASE_MAX]; | 28 | void __iomem *base[RSND_BASE_MAX]; |
35 | 29 | ||
36 | struct rsnd_gen_reg_map reg_map[RSND_REG_MAX]; | ||
37 | struct rsnd_gen_ops *ops; | 30 | struct rsnd_gen_ops *ops; |
31 | |||
32 | struct regmap *regmap; | ||
33 | struct regmap_field *regs[RSND_REG_MAX]; | ||
38 | }; | 34 | }; |
39 | 35 | ||
40 | #define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen) | 36 | #define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen) |
41 | 37 | ||
38 | #define RSND_REG_SET(gen, id, reg_id, offset, _id_offset, _id_size) \ | ||
39 | [id] = { \ | ||
40 | .reg = (unsigned int)gen->base[reg_id] + offset, \ | ||
41 | .lsb = 0, \ | ||
42 | .msb = 31, \ | ||
43 | .id_size = _id_size, \ | ||
44 | .id_offset = _id_offset, \ | ||
45 | } | ||
46 | |||
47 | /* | ||
48 | * basic function | ||
49 | */ | ||
50 | static int rsnd_regmap_write32(void *context, const void *_data, size_t count) | ||
51 | { | ||
52 | struct rsnd_priv *priv = context; | ||
53 | struct device *dev = rsnd_priv_to_dev(priv); | ||
54 | u32 *data = (u32 *)_data; | ||
55 | u32 val = data[1]; | ||
56 | void __iomem *reg = (void *)data[0]; | ||
57 | |||
58 | iowrite32(val, reg); | ||
59 | |||
60 | dev_dbg(dev, "w %p : %08x\n", reg, val); | ||
61 | |||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static int rsnd_regmap_read32(void *context, | ||
66 | const void *_data, size_t reg_size, | ||
67 | void *_val, size_t val_size) | ||
68 | { | ||
69 | struct rsnd_priv *priv = context; | ||
70 | struct device *dev = rsnd_priv_to_dev(priv); | ||
71 | u32 *data = (u32 *)_data; | ||
72 | u32 *val = (u32 *)_val; | ||
73 | void __iomem *reg = (void *)data[0]; | ||
74 | |||
75 | *val = ioread32(reg); | ||
76 | |||
77 | dev_dbg(dev, "r %p : %08x\n", reg, *val); | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static struct regmap_bus rsnd_regmap_bus = { | ||
83 | .write = rsnd_regmap_write32, | ||
84 | .read = rsnd_regmap_read32, | ||
85 | .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, | ||
86 | .val_format_endian_default = REGMAP_ENDIAN_NATIVE, | ||
87 | }; | ||
88 | |||
89 | u32 rsnd_read(struct rsnd_priv *priv, | ||
90 | struct rsnd_mod *mod, enum rsnd_reg reg) | ||
91 | { | ||
92 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | ||
93 | u32 val; | ||
94 | |||
95 | regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val); | ||
96 | |||
97 | return val; | ||
98 | } | ||
99 | |||
100 | void rsnd_write(struct rsnd_priv *priv, | ||
101 | struct rsnd_mod *mod, | ||
102 | enum rsnd_reg reg, u32 data) | ||
103 | { | ||
104 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | ||
105 | |||
106 | regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data); | ||
107 | } | ||
108 | |||
109 | void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, | ||
110 | enum rsnd_reg reg, u32 mask, u32 data) | ||
111 | { | ||
112 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | ||
113 | |||
114 | regmap_fields_update_bits(gen->regs[reg], rsnd_mod_id(mod), | ||
115 | mask, data); | ||
116 | } | ||
117 | |||
42 | /* | 118 | /* |
43 | * Gen2 | 119 | * Gen2 |
44 | * will be filled in the future | 120 | * will be filled in the future |
@@ -103,39 +179,64 @@ static int rsnd_gen1_path_exit(struct rsnd_priv *priv, | |||
103 | return ret; | 179 | return ret; |
104 | } | 180 | } |
105 | 181 | ||
106 | #define RSND_GEN1_REG_MAP(g, s, i, oi, oa) \ | 182 | /* single address mapping */ |
107 | do { \ | 183 | #define RSND_GEN1_S_REG(gen, reg, id, offset) \ |
108 | (g)->reg_map[RSND_REG_##i].index = RSND_GEN1_##s; \ | 184 | RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, 0, 9) |
109 | (g)->reg_map[RSND_REG_##i].offset_id = oi; \ | ||
110 | (g)->reg_map[RSND_REG_##i].offset_adr = oa; \ | ||
111 | } while (0) | ||
112 | 185 | ||
113 | static void rsnd_gen1_reg_map_init(struct rsnd_gen *gen) | 186 | /* multi address mapping */ |
187 | #define RSND_GEN1_M_REG(gen, reg, id, offset, _id_offset) \ | ||
188 | RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, _id_offset, 9) | ||
189 | |||
190 | static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) | ||
114 | { | 191 | { |
115 | RSND_GEN1_REG_MAP(gen, SRU, SRC_ROUTE_SEL, 0x0, 0x00); | 192 | int i; |
116 | RSND_GEN1_REG_MAP(gen, SRU, SRC_TMG_SEL0, 0x0, 0x08); | 193 | struct device *dev = rsnd_priv_to_dev(priv); |
117 | RSND_GEN1_REG_MAP(gen, SRU, SRC_TMG_SEL1, 0x0, 0x0c); | 194 | struct regmap_config regc; |
118 | RSND_GEN1_REG_MAP(gen, SRU, SRC_TMG_SEL2, 0x0, 0x10); | 195 | struct reg_field regf[RSND_REG_MAX] = { |
119 | RSND_GEN1_REG_MAP(gen, SRU, SRC_CTRL, 0x0, 0xc0); | 196 | RSND_GEN1_S_REG(gen, SRU, SRC_ROUTE_SEL, 0x00), |
120 | RSND_GEN1_REG_MAP(gen, SRU, SSI_MODE0, 0x0, 0xD0); | 197 | RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL0, 0x08), |
121 | RSND_GEN1_REG_MAP(gen, SRU, SSI_MODE1, 0x0, 0xD4); | 198 | RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL1, 0x0c), |
122 | RSND_GEN1_REG_MAP(gen, SRU, BUSIF_MODE, 0x4, 0x20); | 199 | RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL2, 0x10), |
123 | RSND_GEN1_REG_MAP(gen, SRU, BUSIF_ADINR, 0x40, 0x214); | 200 | RSND_GEN1_S_REG(gen, SRU, SRC_CTRL, 0xc0), |
124 | 201 | RSND_GEN1_S_REG(gen, SRU, SSI_MODE0, 0xD0), | |
125 | RSND_GEN1_REG_MAP(gen, ADG, BRRA, 0x0, 0x00); | 202 | RSND_GEN1_S_REG(gen, SRU, SSI_MODE1, 0xD4), |
126 | RSND_GEN1_REG_MAP(gen, ADG, BRRB, 0x0, 0x04); | 203 | RSND_GEN1_M_REG(gen, SRU, BUSIF_MODE, 0x20, 0x4), |
127 | RSND_GEN1_REG_MAP(gen, ADG, SSICKR, 0x0, 0x08); | 204 | RSND_GEN1_M_REG(gen, SRU, BUSIF_ADINR, 0x214, 0x40), |
128 | RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL0, 0x0, 0x0c); | 205 | |
129 | RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL1, 0x0, 0x10); | 206 | RSND_GEN1_S_REG(gen, ADG, BRRA, 0x00), |
130 | RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL3, 0x0, 0x18); | 207 | RSND_GEN1_S_REG(gen, ADG, BRRB, 0x04), |
131 | RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL4, 0x0, 0x1c); | 208 | RSND_GEN1_S_REG(gen, ADG, SSICKR, 0x08), |
132 | RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL5, 0x0, 0x20); | 209 | RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL0, 0x0c), |
133 | 210 | RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL1, 0x10), | |
134 | RSND_GEN1_REG_MAP(gen, SSI, SSICR, 0x40, 0x00); | 211 | RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL3, 0x18), |
135 | RSND_GEN1_REG_MAP(gen, SSI, SSISR, 0x40, 0x04); | 212 | RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL4, 0x1c), |
136 | RSND_GEN1_REG_MAP(gen, SSI, SSITDR, 0x40, 0x08); | 213 | RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL5, 0x20), |
137 | RSND_GEN1_REG_MAP(gen, SSI, SSIRDR, 0x40, 0x0c); | 214 | |
138 | RSND_GEN1_REG_MAP(gen, SSI, SSIWSR, 0x40, 0x20); | 215 | RSND_GEN1_M_REG(gen, SSI, SSICR, 0x00, 0x40), |
216 | RSND_GEN1_M_REG(gen, SSI, SSISR, 0x04, 0x40), | ||
217 | RSND_GEN1_M_REG(gen, SSI, SSITDR, 0x08, 0x40), | ||
218 | RSND_GEN1_M_REG(gen, SSI, SSIRDR, 0x0c, 0x40), | ||
219 | RSND_GEN1_M_REG(gen, SSI, SSIWSR, 0x20, 0x40), | ||
220 | }; | ||
221 | |||
222 | memset(®c, 0, sizeof(regc)); | ||
223 | regc.reg_bits = 32; | ||
224 | regc.val_bits = 32; | ||
225 | |||
226 | gen->regmap = devm_regmap_init(dev, &rsnd_regmap_bus, priv, ®c); | ||
227 | if (IS_ERR(gen->regmap)) { | ||
228 | dev_err(dev, "regmap error %ld\n", PTR_ERR(gen->regmap)); | ||
229 | return PTR_ERR(gen->regmap); | ||
230 | } | ||
231 | |||
232 | for (i = 0; i < RSND_REG_MAX; i++) { | ||
233 | gen->regs[i] = devm_regmap_field_alloc(dev, gen->regmap, regf[i]); | ||
234 | if (IS_ERR(gen->regs[i])) | ||
235 | return PTR_ERR(gen->regs[i]); | ||
236 | |||
237 | } | ||
238 | |||
239 | return 0; | ||
139 | } | 240 | } |
140 | 241 | ||
141 | static int rsnd_gen1_probe(struct platform_device *pdev, | 242 | static int rsnd_gen1_probe(struct platform_device *pdev, |
@@ -147,6 +248,7 @@ static int rsnd_gen1_probe(struct platform_device *pdev, | |||
147 | struct resource *sru_res; | 248 | struct resource *sru_res; |
148 | struct resource *adg_res; | 249 | struct resource *adg_res; |
149 | struct resource *ssi_res; | 250 | struct resource *ssi_res; |
251 | int ret; | ||
150 | 252 | ||
151 | /* | 253 | /* |
152 | * map address | 254 | * map address |
@@ -163,7 +265,9 @@ static int rsnd_gen1_probe(struct platform_device *pdev, | |||
163 | IS_ERR(gen->base[RSND_GEN1_SSI])) | 265 | IS_ERR(gen->base[RSND_GEN1_SSI])) |
164 | return -ENODEV; | 266 | return -ENODEV; |
165 | 267 | ||
166 | rsnd_gen1_reg_map_init(gen); | 268 | ret = rsnd_gen1_regmap_init(priv, gen); |
269 | if (ret < 0) | ||
270 | return ret; | ||
167 | 271 | ||
168 | dev_dbg(dev, "Gen1 device probed\n"); | 272 | dev_dbg(dev, "Gen1 device probed\n"); |
169 | dev_dbg(dev, "SRU : %08x => %p\n", sru_res->start, | 273 | dev_dbg(dev, "SRU : %08x => %p\n", sru_res->start, |
@@ -210,46 +314,12 @@ int rsnd_gen_path_exit(struct rsnd_priv *priv, | |||
210 | return gen->ops->path_exit(priv, rdai, io); | 314 | return gen->ops->path_exit(priv, rdai, io); |
211 | } | 315 | } |
212 | 316 | ||
213 | void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, | ||
214 | struct rsnd_mod *mod, | ||
215 | enum rsnd_reg reg) | ||
216 | { | ||
217 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | ||
218 | struct device *dev = rsnd_priv_to_dev(priv); | ||
219 | int index; | ||
220 | u32 offset_id, offset_adr; | ||
221 | |||
222 | if (reg >= RSND_REG_MAX) { | ||
223 | dev_err(dev, "rsnd_reg reg error\n"); | ||
224 | return NULL; | ||
225 | } | ||
226 | |||
227 | index = gen->reg_map[reg].index; | ||
228 | offset_id = gen->reg_map[reg].offset_id; | ||
229 | offset_adr = gen->reg_map[reg].offset_adr; | ||
230 | |||
231 | if (index < 0) { | ||
232 | dev_err(dev, "unsupported reg access %d\n", reg); | ||
233 | return NULL; | ||
234 | } | ||
235 | |||
236 | if (offset_id && mod) | ||
237 | offset_id *= rsnd_mod_id(mod); | ||
238 | |||
239 | /* | ||
240 | * index/offset were set on gen1/gen2 | ||
241 | */ | ||
242 | |||
243 | return gen->base[index] + offset_id + offset_adr; | ||
244 | } | ||
245 | |||
246 | int rsnd_gen_probe(struct platform_device *pdev, | 317 | int rsnd_gen_probe(struct platform_device *pdev, |
247 | struct rcar_snd_info *info, | 318 | struct rcar_snd_info *info, |
248 | struct rsnd_priv *priv) | 319 | struct rsnd_priv *priv) |
249 | { | 320 | { |
250 | struct device *dev = rsnd_priv_to_dev(priv); | 321 | struct device *dev = rsnd_priv_to_dev(priv); |
251 | struct rsnd_gen *gen; | 322 | struct rsnd_gen *gen; |
252 | int i; | ||
253 | 323 | ||
254 | gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL); | 324 | gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL); |
255 | if (!gen) { | 325 | if (!gen) { |
@@ -267,14 +337,6 @@ int rsnd_gen_probe(struct platform_device *pdev, | |||
267 | 337 | ||
268 | priv->gen = gen; | 338 | priv->gen = gen; |
269 | 339 | ||
270 | /* | ||
271 | * see | ||
272 | * rsnd_reg_get() | ||
273 | * rsnd_gen_probe() | ||
274 | */ | ||
275 | for (i = 0; i < RSND_REG_MAX; i++) | ||
276 | gen->reg_map[i].index = -1; | ||
277 | |||
278 | return gen->ops->probe(pdev, info, priv); | 340 | return gen->ops->probe(pdev, info, priv); |
279 | } | 341 | } |
280 | 342 | ||