blob: 15dccd5989606e9f1d0dcbdf85d07406eae830e2 [file] [log] [blame]
Kuninori Morimoto1536a962013-07-21 21:35:52 -07001/*
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>
Kuninori Morimoto0a4d94c2013-07-28 18:58:50 -070016#include <linux/dma-mapping.h>
Kuninori Morimoto1536a962013-07-21 21:35:52 -070017#include <linux/io.h>
18#include <linux/list.h>
19#include <linux/module.h>
Kuninori Morimoto0a4d94c2013-07-28 18:58:50 -070020#include <linux/sh_dma.h>
21#include <linux/workqueue.h>
Kuninori Morimoto1536a962013-07-21 21:35:52 -070022#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 */
Kuninori Morimoto33377442013-07-21 21:36:21 -070033enum rsnd_reg {
Kuninori Morimoto07539c12013-07-21 21:36:35 -070034 /* SRU/SCU */
35 RSND_REG_SSI_MODE0,
36 RSND_REG_SSI_MODE1,
37
Kuninori Morimotodfc94032013-07-21 21:36:46 -070038 /* ADG */
39 RSND_REG_BRRA,
40 RSND_REG_BRRB,
41 RSND_REG_SSICKR,
42 RSND_REG_AUDIO_CLK_SEL0,
43 RSND_REG_AUDIO_CLK_SEL1,
44 RSND_REG_AUDIO_CLK_SEL2,
45 RSND_REG_AUDIO_CLK_SEL3,
46 RSND_REG_AUDIO_CLK_SEL4,
47 RSND_REG_AUDIO_CLK_SEL5,
48
Kuninori Morimotoae5c3222013-07-21 21:36:57 -070049 /* SSI */
50 RSND_REG_SSICR,
51 RSND_REG_SSISR,
52 RSND_REG_SSITDR,
53 RSND_REG_SSIRDR,
54 RSND_REG_SSIWSR,
55
Kuninori Morimoto33377442013-07-21 21:36:21 -070056 RSND_REG_MAX,
57};
58
Kuninori Morimoto1536a962013-07-21 21:35:52 -070059struct rsnd_priv;
Kuninori Morimotocdaa3cd2013-07-21 21:36:03 -070060struct rsnd_mod;
Kuninori Morimoto1536a962013-07-21 21:35:52 -070061struct rsnd_dai;
62struct rsnd_dai_stream;
63
64/*
Kuninori Morimoto33377442013-07-21 21:36:21 -070065 * R-Car basic functions
66 */
67#define rsnd_mod_read(m, r) \
68 rsnd_read(rsnd_mod_to_priv(m), m, RSND_REG_##r)
69#define rsnd_mod_write(m, r, d) \
70 rsnd_write(rsnd_mod_to_priv(m), m, RSND_REG_##r, d)
71#define rsnd_mod_bset(m, r, s, d) \
72 rsnd_bset(rsnd_mod_to_priv(m), m, RSND_REG_##r, s, d)
73
74#define rsnd_priv_read(p, r) rsnd_read(p, NULL, RSND_REG_##r)
75#define rsnd_priv_write(p, r, d) rsnd_write(p, NULL, RSND_REG_##r, d)
76#define rsnd_priv_bset(p, r, s, d) rsnd_bset(p, NULL, RSND_REG_##r, s, d)
77
78u32 rsnd_read(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg);
79void rsnd_write(struct rsnd_priv *priv, struct rsnd_mod *mod,
80 enum rsnd_reg reg, u32 data);
81void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg,
82 u32 mask, u32 data);
83
84/*
Kuninori Morimoto0a4d94c2013-07-28 18:58:50 -070085 * R-Car DMA
86 */
87struct rsnd_dma {
88 struct rsnd_priv *priv;
89 struct sh_dmae_slave slave;
90 struct work_struct work;
91 struct dma_chan *chan;
92 enum dma_data_direction dir;
93 int (*inquiry)(struct rsnd_dma *dma, dma_addr_t *buf, int *len);
94 int (*complete)(struct rsnd_dma *dma);
95
96 int submit_loop;
97};
98
99void rsnd_dma_start(struct rsnd_dma *dma);
100void rsnd_dma_stop(struct rsnd_dma *dma);
101int rsnd_dma_available(struct rsnd_dma *dma);
102int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
103 int is_play, int id,
104 int (*inquiry)(struct rsnd_dma *dma, dma_addr_t *buf, int *len),
105 int (*complete)(struct rsnd_dma *dma));
106void rsnd_dma_quit(struct rsnd_priv *priv,
107 struct rsnd_dma *dma);
108
109
110/*
Kuninori Morimotocdaa3cd2013-07-21 21:36:03 -0700111 * R-Car sound mod
112 */
113
114struct rsnd_mod_ops {
115 char *name;
116 int (*init)(struct rsnd_mod *mod,
117 struct rsnd_dai *rdai,
118 struct rsnd_dai_stream *io);
119 int (*quit)(struct rsnd_mod *mod,
120 struct rsnd_dai *rdai,
121 struct rsnd_dai_stream *io);
122 int (*start)(struct rsnd_mod *mod,
123 struct rsnd_dai *rdai,
124 struct rsnd_dai_stream *io);
125 int (*stop)(struct rsnd_mod *mod,
126 struct rsnd_dai *rdai,
127 struct rsnd_dai_stream *io);
128};
129
130struct rsnd_mod {
131 int id;
132 struct rsnd_priv *priv;
133 struct rsnd_mod_ops *ops;
134 struct list_head list; /* connect to rsnd_dai playback/capture */
Kuninori Morimoto0a4d94c2013-07-28 18:58:50 -0700135 struct rsnd_dma dma;
Kuninori Morimotocdaa3cd2013-07-21 21:36:03 -0700136};
137
138#define rsnd_mod_to_priv(mod) ((mod)->priv)
Kuninori Morimoto0a4d94c2013-07-28 18:58:50 -0700139#define rsnd_mod_to_dma(mod) (&(mod)->dma)
140#define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma)
Kuninori Morimotocdaa3cd2013-07-21 21:36:03 -0700141#define rsnd_mod_id(mod) ((mod)->id)
142#define for_each_rsnd_mod(pos, n, io) \
143 list_for_each_entry_safe(pos, n, &(io)->head, list)
144#define rsnd_mod_call(mod, func, rdai, io) \
145 (!(mod) ? -ENODEV : \
146 !((mod)->ops->func) ? 0 : \
147 (mod)->ops->func(mod, rdai, io))
148
149void rsnd_mod_init(struct rsnd_priv *priv,
150 struct rsnd_mod *mod,
151 struct rsnd_mod_ops *ops,
152 int id);
153char *rsnd_mod_name(struct rsnd_mod *mod);
154
155/*
Kuninori Morimoto1536a962013-07-21 21:35:52 -0700156 * R-Car sound DAI
157 */
158#define RSND_DAI_NAME_SIZE 16
159struct rsnd_dai_stream {
160 struct list_head head; /* head of rsnd_mod list */
161 struct snd_pcm_substream *substream;
162 int byte_pos;
163 int period_pos;
164 int byte_per_period;
165 int next_period_byte;
166};
167
168struct rsnd_dai {
169 char name[RSND_DAI_NAME_SIZE];
170 struct rsnd_dai_platform_info *info; /* rcar_snd.h */
171 struct rsnd_dai_stream playback;
172 struct rsnd_dai_stream capture;
173
174 int clk_master:1;
175 int bit_clk_inv:1;
176 int frm_clk_inv:1;
177 int sys_delay:1;
178 int data_alignment:1;
179};
180
181#define rsnd_dai_nr(priv) ((priv)->dai_nr)
182#define for_each_rsnd_dai(rdai, priv, i) \
183 for (i = 0, (rdai) = rsnd_dai_get(priv, i); \
184 i < rsnd_dai_nr(priv); \
185 i++, (rdai) = rsnd_dai_get(priv, i))
186
187struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id);
Kuninori Morimotocdaa3cd2013-07-21 21:36:03 -0700188int rsnd_dai_disconnect(struct rsnd_mod *mod);
189int rsnd_dai_connect(struct rsnd_dai *rdai, struct rsnd_mod *mod,
190 struct rsnd_dai_stream *io);
Kuninori Morimoto1536a962013-07-21 21:35:52 -0700191int rsnd_dai_is_play(struct rsnd_dai *rdai, struct rsnd_dai_stream *io);
Kuninori Morimoto4b4dab82013-07-28 18:58:29 -0700192int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai);
Kuninori Morimoto1536a962013-07-21 21:35:52 -0700193#define rsnd_dai_get_platform_info(rdai) ((rdai)->info)
Kuninori Morimotoae5c3222013-07-21 21:36:57 -0700194#define rsnd_io_to_runtime(io) ((io)->substream->runtime)
Kuninori Morimoto1536a962013-07-21 21:35:52 -0700195
196void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt);
197int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional);
198
199/*
Kuninori Morimoto33377442013-07-21 21:36:21 -0700200 * R-Car Gen1/Gen2
201 */
202int rsnd_gen_probe(struct platform_device *pdev,
203 struct rcar_snd_info *info,
204 struct rsnd_priv *priv);
205void rsnd_gen_remove(struct platform_device *pdev,
206 struct rsnd_priv *priv);
207int rsnd_gen_path_init(struct rsnd_priv *priv,
208 struct rsnd_dai *rdai,
209 struct rsnd_dai_stream *io);
210int rsnd_gen_path_exit(struct rsnd_priv *priv,
211 struct rsnd_dai *rdai,
212 struct rsnd_dai_stream *io);
213void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv,
214 struct rsnd_mod *mod,
215 enum rsnd_reg reg);
216
217/*
Kuninori Morimotodfc94032013-07-21 21:36:46 -0700218 * R-Car ADG
219 */
220int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod);
221int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate);
222int rsnd_adg_probe(struct platform_device *pdev,
223 struct rcar_snd_info *info,
224 struct rsnd_priv *priv);
225void rsnd_adg_remove(struct platform_device *pdev,
226 struct rsnd_priv *priv);
227
228/*
Kuninori Morimoto1536a962013-07-21 21:35:52 -0700229 * R-Car sound priv
230 */
231struct rsnd_priv {
232
233 struct device *dev;
234 struct rcar_snd_info *info;
235 spinlock_t lock;
236
237 /*
Kuninori Morimoto33377442013-07-21 21:36:21 -0700238 * below value will be filled on rsnd_gen_probe()
239 */
240 void *gen;
241
242 /*
Kuninori Morimoto07539c12013-07-21 21:36:35 -0700243 * below value will be filled on rsnd_scu_probe()
244 */
245 void *scu;
246 int scu_nr;
247
248 /*
Kuninori Morimotodfc94032013-07-21 21:36:46 -0700249 * below value will be filled on rsnd_adg_probe()
250 */
251 void *adg;
252
253 /*
Kuninori Morimotoae5c3222013-07-21 21:36:57 -0700254 * below value will be filled on rsnd_ssi_probe()
255 */
256 void *ssiu;
257
258 /*
Kuninori Morimoto1536a962013-07-21 21:35:52 -0700259 * below value will be filled on rsnd_dai_probe()
260 */
261 struct snd_soc_dai_driver *daidrv;
262 struct rsnd_dai *rdai;
263 int dai_nr;
264};
265
266#define rsnd_priv_to_dev(priv) ((priv)->dev)
267#define rsnd_lock(priv, flags) spin_lock_irqsave(&priv->lock, flags)
268#define rsnd_unlock(priv, flags) spin_unlock_irqrestore(&priv->lock, flags)
269
Kuninori Morimoto07539c12013-07-21 21:36:35 -0700270/*
271 * R-Car SCU
272 */
273int rsnd_scu_probe(struct platform_device *pdev,
274 struct rcar_snd_info *info,
275 struct rsnd_priv *priv);
276void rsnd_scu_remove(struct platform_device *pdev,
277 struct rsnd_priv *priv);
278struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id);
279#define rsnd_scu_nr(priv) ((priv)->scu_nr)
280
Kuninori Morimotoae5c3222013-07-21 21:36:57 -0700281/*
282 * R-Car SSI
283 */
284int rsnd_ssi_probe(struct platform_device *pdev,
285 struct rcar_snd_info *info,
286 struct rsnd_priv *priv);
287void rsnd_ssi_remove(struct platform_device *pdev,
288 struct rsnd_priv *priv);
289struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id);
Kuninori Morimoto4b4dab82013-07-28 18:58:29 -0700290struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv,
291 int dai_id, int is_play);
Kuninori Morimotoae5c3222013-07-21 21:36:57 -0700292
Kuninori Morimoto1536a962013-07-21 21:35:52 -0700293#endif