Commit | Line | Data |
---|---|---|
1536a968 KM |
1 | /* |
2 | * Renesas R-Car | |
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 | #ifndef RSND_H | |
12 | #define RSND_H | |
13 | ||
14 | #include <linux/clk.h> | |
15 | #include <linux/device.h> | |
0a4d94c0 | 16 | #include <linux/dma-mapping.h> |
1536a968 KM |
17 | #include <linux/io.h> |
18 | #include <linux/list.h> | |
19 | #include <linux/module.h> | |
0a4d94c0 KM |
20 | #include <linux/sh_dma.h> |
21 | #include <linux/workqueue.h> | |
1536a968 KM |
22 | #include <sound/rcar_snd.h> |
23 | #include <sound/soc.h> | |
24 | #include <sound/pcm_params.h> | |
25 | ||
26 | /* | |
27 | * pseudo register | |
28 | * | |
29 | * The register address offsets SRU/SCU/SSIU on Gen1/Gen2 are very different. | |
30 | * This driver uses pseudo register in order to hide it. | |
31 | * see gen1/gen2 for detail | |
32 | */ | |
3337744a | 33 | enum rsnd_reg { |
507d466c | 34 | /* SRU/SCU/SSIU */ |
2582718c KM |
35 | RSND_REG_SRC_ROUTE_SEL, /* for Gen1 */ |
36 | RSND_REG_SRC_TMG_SEL0, /* for Gen1 */ | |
37 | RSND_REG_SRC_TMG_SEL1, /* for Gen1 */ | |
38 | RSND_REG_SRC_TMG_SEL2, /* for Gen1 */ | |
39 | RSND_REG_SRC_ROUTE_CTRL, /* for Gen1 */ | |
629509c5 KM |
40 | RSND_REG_SRC_CTRL, /* for Gen2 */ |
41 | RSND_REG_SSI_CTRL, /* for Gen2 */ | |
42 | RSND_REG_SSI_CONTROL, | |
43 | RSND_REG_SSI_BUSIF_MODE, /* for Gen2 */ | |
44 | RSND_REG_SSI_BUSIF_ADINR, /* for Gen2 */ | |
07539c1d KM |
45 | RSND_REG_SSI_MODE0, |
46 | RSND_REG_SSI_MODE1, | |
52ea2a79 | 47 | RSND_REG_INT_ENABLE, /* for Gen2 */ |
0290d2a4 | 48 | RSND_REG_SRC_BUSIF_MODE, |
ef749400 KM |
49 | RSND_REG_SRC_ROUTE_MODE0, |
50 | RSND_REG_SRC_SWRSR, | |
51 | RSND_REG_SRC_SRCIR, | |
690ef81e | 52 | RSND_REG_SRC_ADINR, |
ef749400 KM |
53 | RSND_REG_SRC_IFSCR, |
54 | RSND_REG_SRC_IFSVR, | |
55 | RSND_REG_SRC_SRCCR, | |
1b7b08ef | 56 | RSND_REG_SRC_MNFSR, /* for Gen1 */ |
629509c5 KM |
57 | RSND_REG_SRC_BSDSR, /* for Gen2 */ |
58 | RSND_REG_SRC_BSISR, /* for Gen2 */ | |
07539c1d | 59 | |
dfc9403b KM |
60 | /* ADG */ |
61 | RSND_REG_BRRA, | |
62 | RSND_REG_BRRB, | |
63 | RSND_REG_SSICKR, | |
64 | RSND_REG_AUDIO_CLK_SEL0, | |
65 | RSND_REG_AUDIO_CLK_SEL1, | |
66 | RSND_REG_AUDIO_CLK_SEL2, | |
ef749400 KM |
67 | RSND_REG_AUDIO_CLK_SEL3, /* for Gen1 */ |
68 | RSND_REG_AUDIO_CLK_SEL4, /* for Gen1 */ | |
69 | RSND_REG_AUDIO_CLK_SEL5, /* for Gen1 */ | |
ee2c828d | 70 | RSND_REG_DIV_EN, /* for Gen2 */ |
629509c5 KM |
71 | RSND_REG_SRCIN_TIMSEL0, /* for Gen2 */ |
72 | RSND_REG_SRCIN_TIMSEL1, /* for Gen2 */ | |
73 | RSND_REG_SRCIN_TIMSEL2, /* for Gen2 */ | |
74 | RSND_REG_SRCIN_TIMSEL3, /* for Gen2 */ | |
75 | RSND_REG_SRCIN_TIMSEL4, /* for Gen2 */ | |
76 | RSND_REG_SRCOUT_TIMSEL0, /* for Gen2 */ | |
77 | RSND_REG_SRCOUT_TIMSEL1, /* for Gen2 */ | |
78 | RSND_REG_SRCOUT_TIMSEL2, /* for Gen2 */ | |
79 | RSND_REG_SRCOUT_TIMSEL3, /* for Gen2 */ | |
80 | RSND_REG_SRCOUT_TIMSEL4, /* for Gen2 */ | |
dfc9403b | 81 | |
ae5c3223 KM |
82 | /* SSI */ |
83 | RSND_REG_SSICR, | |
84 | RSND_REG_SSISR, | |
85 | RSND_REG_SSITDR, | |
86 | RSND_REG_SSIRDR, | |
87 | RSND_REG_SSIWSR, | |
88 | ||
3337744a KM |
89 | RSND_REG_MAX, |
90 | }; | |
91 | ||
1536a968 | 92 | struct rsnd_priv; |
cdaa3cdf | 93 | struct rsnd_mod; |
1536a968 KM |
94 | struct rsnd_dai; |
95 | struct rsnd_dai_stream; | |
96 | ||
3337744a KM |
97 | /* |
98 | * R-Car basic functions | |
99 | */ | |
100 | #define rsnd_mod_read(m, r) \ | |
101 | rsnd_read(rsnd_mod_to_priv(m), m, RSND_REG_##r) | |
102 | #define rsnd_mod_write(m, r, d) \ | |
103 | rsnd_write(rsnd_mod_to_priv(m), m, RSND_REG_##r, d) | |
104 | #define rsnd_mod_bset(m, r, s, d) \ | |
105 | rsnd_bset(rsnd_mod_to_priv(m), m, RSND_REG_##r, s, d) | |
106 | ||
3337744a KM |
107 | u32 rsnd_read(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg); |
108 | void rsnd_write(struct rsnd_priv *priv, struct rsnd_mod *mod, | |
109 | enum rsnd_reg reg, u32 data); | |
110 | void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg, | |
111 | u32 mask, u32 data); | |
112 | ||
0a4d94c0 KM |
113 | /* |
114 | * R-Car DMA | |
115 | */ | |
116 | struct rsnd_dma { | |
0a4d94c0 KM |
117 | struct sh_dmae_slave slave; |
118 | struct work_struct work; | |
119 | struct dma_chan *chan; | |
120 | enum dma_data_direction dir; | |
0a4d94c0 KM |
121 | |
122 | int submit_loop; | |
4686a0ad | 123 | int offset; /* it cares A/B plane */ |
0a4d94c0 KM |
124 | }; |
125 | ||
126 | void rsnd_dma_start(struct rsnd_dma *dma); | |
127 | void rsnd_dma_stop(struct rsnd_dma *dma); | |
128 | int rsnd_dma_available(struct rsnd_dma *dma); | |
129 | int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, | |
4686a0ad | 130 | int is_play, int id); |
0a4d94c0 KM |
131 | void rsnd_dma_quit(struct rsnd_priv *priv, |
132 | struct rsnd_dma *dma); | |
133 | ||
134 | ||
cdaa3cdf KM |
135 | /* |
136 | * R-Car sound mod | |
137 | */ | |
138 | ||
139 | struct rsnd_mod_ops { | |
140 | char *name; | |
141 | int (*init)(struct rsnd_mod *mod, | |
142 | struct rsnd_dai *rdai, | |
143 | struct rsnd_dai_stream *io); | |
144 | int (*quit)(struct rsnd_mod *mod, | |
145 | struct rsnd_dai *rdai, | |
146 | struct rsnd_dai_stream *io); | |
147 | int (*start)(struct rsnd_mod *mod, | |
148 | struct rsnd_dai *rdai, | |
149 | struct rsnd_dai_stream *io); | |
150 | int (*stop)(struct rsnd_mod *mod, | |
151 | struct rsnd_dai *rdai, | |
152 | struct rsnd_dai_stream *io); | |
153 | }; | |
154 | ||
4686a0ad | 155 | struct rsnd_dai_stream; |
cdaa3cdf KM |
156 | struct rsnd_mod { |
157 | int id; | |
158 | struct rsnd_priv *priv; | |
159 | struct rsnd_mod_ops *ops; | |
160 | struct list_head list; /* connect to rsnd_dai playback/capture */ | |
0a4d94c0 | 161 | struct rsnd_dma dma; |
4686a0ad | 162 | struct rsnd_dai_stream *io; |
cdaa3cdf KM |
163 | }; |
164 | ||
165 | #define rsnd_mod_to_priv(mod) ((mod)->priv) | |
0a4d94c0 KM |
166 | #define rsnd_mod_to_dma(mod) (&(mod)->dma) |
167 | #define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma) | |
4686a0ad | 168 | #define rsnd_mod_to_io(mod) ((mod)->io) |
cdaa3cdf KM |
169 | #define rsnd_mod_id(mod) ((mod)->id) |
170 | #define for_each_rsnd_mod(pos, n, io) \ | |
171 | list_for_each_entry_safe(pos, n, &(io)->head, list) | |
92d9587e KM |
172 | #define __rsnd_mod_call(mod, func, rdai, io) \ |
173 | ({ \ | |
174 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ | |
175 | struct device *dev = rsnd_priv_to_dev(priv); \ | |
176 | dev_dbg(dev, "%s-%d-%s\n", \ | |
177 | rsnd_mod_name(mod), rsnd_mod_id(mod), #func); \ | |
178 | (mod)->ops->func(mod, rdai, io); \ | |
179 | }) | |
180 | ||
cdaa3cdf KM |
181 | #define rsnd_mod_call(mod, func, rdai, io) \ |
182 | (!(mod) ? -ENODEV : \ | |
183 | !((mod)->ops->func) ? 0 : \ | |
92d9587e | 184 | __rsnd_mod_call(mod, func, rdai, io)) |
cdaa3cdf KM |
185 | |
186 | void rsnd_mod_init(struct rsnd_priv *priv, | |
187 | struct rsnd_mod *mod, | |
188 | struct rsnd_mod_ops *ops, | |
189 | int id); | |
190 | char *rsnd_mod_name(struct rsnd_mod *mod); | |
191 | ||
1536a968 KM |
192 | /* |
193 | * R-Car sound DAI | |
194 | */ | |
195 | #define RSND_DAI_NAME_SIZE 16 | |
196 | struct rsnd_dai_stream { | |
197 | struct list_head head; /* head of rsnd_mod list */ | |
198 | struct snd_pcm_substream *substream; | |
199 | int byte_pos; | |
200 | int period_pos; | |
201 | int byte_per_period; | |
202 | int next_period_byte; | |
203 | }; | |
204 | ||
205 | struct rsnd_dai { | |
206 | char name[RSND_DAI_NAME_SIZE]; | |
207 | struct rsnd_dai_platform_info *info; /* rcar_snd.h */ | |
208 | struct rsnd_dai_stream playback; | |
209 | struct rsnd_dai_stream capture; | |
210 | ||
a3737731 DC |
211 | unsigned int clk_master:1; |
212 | unsigned int bit_clk_inv:1; | |
213 | unsigned int frm_clk_inv:1; | |
214 | unsigned int sys_delay:1; | |
215 | unsigned int data_alignment:1; | |
1536a968 KM |
216 | }; |
217 | ||
218 | #define rsnd_dai_nr(priv) ((priv)->dai_nr) | |
219 | #define for_each_rsnd_dai(rdai, priv, i) \ | |
00463c11 KM |
220 | for (i = 0; \ |
221 | (i < rsnd_dai_nr(priv)) && \ | |
222 | ((rdai) = rsnd_dai_get(priv, i)); \ | |
223 | i++) | |
1536a968 KM |
224 | |
225 | struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id); | |
cdaa3cdf KM |
226 | int rsnd_dai_disconnect(struct rsnd_mod *mod); |
227 | int rsnd_dai_connect(struct rsnd_dai *rdai, struct rsnd_mod *mod, | |
228 | struct rsnd_dai_stream *io); | |
1536a968 | 229 | int rsnd_dai_is_play(struct rsnd_dai *rdai, struct rsnd_dai_stream *io); |
4b4dab82 | 230 | int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai); |
1536a968 | 231 | #define rsnd_dai_get_platform_info(rdai) ((rdai)->info) |
ae5c3223 | 232 | #define rsnd_io_to_runtime(io) ((io)->substream->runtime) |
1536a968 KM |
233 | |
234 | void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt); | |
235 | int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional); | |
e779a20d | 236 | #define rsnd_dai_is_clk_master(rdai) ((rdai)->clk_master) |
1536a968 | 237 | |
3337744a KM |
238 | /* |
239 | * R-Car Gen1/Gen2 | |
240 | */ | |
241 | int rsnd_gen_probe(struct platform_device *pdev, | |
242 | struct rcar_snd_info *info, | |
243 | struct rsnd_priv *priv); | |
244 | void rsnd_gen_remove(struct platform_device *pdev, | |
245 | struct rsnd_priv *priv); | |
246 | int rsnd_gen_path_init(struct rsnd_priv *priv, | |
247 | struct rsnd_dai *rdai, | |
248 | struct rsnd_dai_stream *io); | |
249 | int rsnd_gen_path_exit(struct rsnd_priv *priv, | |
250 | struct rsnd_dai *rdai, | |
251 | struct rsnd_dai_stream *io); | |
252 | void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, | |
253 | struct rsnd_mod *mod, | |
254 | enum rsnd_reg reg); | |
c5d5a58d KM |
255 | #define rsnd_is_gen1(s) (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN1) |
256 | #define rsnd_is_gen2(s) (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN2) | |
3337744a | 257 | |
dfc9403b KM |
258 | /* |
259 | * R-Car ADG | |
260 | */ | |
261 | int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod); | |
262 | int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate); | |
263 | int rsnd_adg_probe(struct platform_device *pdev, | |
264 | struct rcar_snd_info *info, | |
265 | struct rsnd_priv *priv); | |
266 | void rsnd_adg_remove(struct platform_device *pdev, | |
267 | struct rsnd_priv *priv); | |
28dc4b63 KM |
268 | int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, |
269 | struct rsnd_mod *mod, | |
270 | unsigned int src_rate, | |
271 | unsigned int dst_rate); | |
629509c5 KM |
272 | int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, |
273 | struct rsnd_dai *rdai, | |
274 | struct rsnd_dai_stream *io, | |
275 | unsigned int src_rate, | |
276 | unsigned int dst_rate); | |
277 | int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, | |
278 | struct rsnd_dai *rdai, | |
279 | struct rsnd_dai_stream *io); | |
dfc9403b | 280 | |
1536a968 KM |
281 | /* |
282 | * R-Car sound priv | |
283 | */ | |
284 | struct rsnd_priv { | |
285 | ||
286 | struct device *dev; | |
287 | struct rcar_snd_info *info; | |
288 | spinlock_t lock; | |
289 | ||
3337744a KM |
290 | /* |
291 | * below value will be filled on rsnd_gen_probe() | |
292 | */ | |
293 | void *gen; | |
294 | ||
07539c1d KM |
295 | /* |
296 | * below value will be filled on rsnd_scu_probe() | |
297 | */ | |
298 | void *scu; | |
299 | int scu_nr; | |
300 | ||
dfc9403b KM |
301 | /* |
302 | * below value will be filled on rsnd_adg_probe() | |
303 | */ | |
304 | void *adg; | |
305 | ||
ae5c3223 KM |
306 | /* |
307 | * below value will be filled on rsnd_ssi_probe() | |
308 | */ | |
dd27d808 KM |
309 | void *ssi; |
310 | int ssi_nr; | |
ae5c3223 | 311 | |
1536a968 KM |
312 | /* |
313 | * below value will be filled on rsnd_dai_probe() | |
314 | */ | |
315 | struct snd_soc_dai_driver *daidrv; | |
316 | struct rsnd_dai *rdai; | |
317 | int dai_nr; | |
318 | }; | |
319 | ||
320 | #define rsnd_priv_to_dev(priv) ((priv)->dev) | |
321 | #define rsnd_lock(priv, flags) spin_lock_irqsave(&priv->lock, flags) | |
322 | #define rsnd_unlock(priv, flags) spin_unlock_irqrestore(&priv->lock, flags) | |
323 | ||
07539c1d KM |
324 | /* |
325 | * R-Car SCU | |
326 | */ | |
327 | int rsnd_scu_probe(struct platform_device *pdev, | |
328 | struct rcar_snd_info *info, | |
329 | struct rsnd_priv *priv); | |
330 | void rsnd_scu_remove(struct platform_device *pdev, | |
331 | struct rsnd_priv *priv); | |
332 | struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id); | |
ef749400 KM |
333 | unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, |
334 | struct rsnd_mod *ssi_mod, | |
335 | struct snd_pcm_runtime *runtime); | |
336 | ||
07539c1d KM |
337 | #define rsnd_scu_nr(priv) ((priv)->scu_nr) |
338 | ||
ae5c3223 KM |
339 | /* |
340 | * R-Car SSI | |
341 | */ | |
342 | int rsnd_ssi_probe(struct platform_device *pdev, | |
343 | struct rcar_snd_info *info, | |
344 | struct rsnd_priv *priv); | |
345 | void rsnd_ssi_remove(struct platform_device *pdev, | |
346 | struct rsnd_priv *priv); | |
347 | struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); | |
4b4dab82 KM |
348 | struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, |
349 | int dai_id, int is_play); | |
7b5ce975 | 350 | int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod); |
32f27ebf | 351 | int rsnd_ssi_is_play(struct rsnd_mod *mod); |
ae5c3223 | 352 | |
1536a968 | 353 | #endif |