2 * Renesas R-Car Gen1 SRU/SSI support
4 * Copyright (C) 2013 Renesas Solutions Corp.
5 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
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.
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
);
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, ... */
29 void __iomem
*base
[RSND_BASE_MAX
];
31 struct rsnd_gen_reg_map reg_map
[RSND_REG_MAX
];
32 struct rsnd_gen_ops
*ops
;
35 #define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen)
37 #define rsnd_is_gen1(s) ((s)->info->flags & RSND_GEN1)
38 #define rsnd_is_gen2(s) ((s)->info->flags & RSND_GEN2)
42 * will be filled in the future
48 static int rsnd_gen1_path_init(struct rsnd_priv
*priv
,
49 struct rsnd_dai
*rdai
,
50 struct rsnd_dai_stream
*io
)
57 * Gen1 is created by SRU/SSI, and this SRU is base module of
58 * Gen2's SCU/SSIU/SSI. (Gen2 SCU/SSIU came from SRU)
61 * Gen1 SRU = Gen2 SCU + SSIU + etc
63 * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is
66 * Then, SSI id = SCU id here
70 mod
= rsnd_ssi_mod_get_frm_dai(priv
,
71 rsnd_dai_id(priv
, rdai
),
72 rsnd_dai_is_play(rdai
, io
));
73 id
= rsnd_mod_id(mod
);
76 mod
= rsnd_ssi_mod_get(priv
, id
);
77 ret
= rsnd_dai_connect(rdai
, mod
, io
);
82 mod
= rsnd_scu_mod_get(priv
, id
);
83 ret
= rsnd_dai_connect(rdai
, mod
, io
);
88 static int rsnd_gen1_path_exit(struct rsnd_priv
*priv
,
89 struct rsnd_dai
*rdai
,
90 struct rsnd_dai_stream
*io
)
92 struct rsnd_mod
*mod
, *n
;
96 * remove all mod from rdai
98 for_each_rsnd_mod(mod
, n
, io
)
99 ret
|= rsnd_dai_disconnect(mod
);
104 static struct rsnd_gen_ops rsnd_gen1_ops
= {
105 .path_init
= rsnd_gen1_path_init
,
106 .path_exit
= rsnd_gen1_path_exit
,
109 #define RSND_GEN1_REG_MAP(g, s, i, oi, oa) \
111 (g)->reg_map[RSND_REG_##i].index = RSND_GEN1_##s; \
112 (g)->reg_map[RSND_REG_##i].offset_id = oi; \
113 (g)->reg_map[RSND_REG_##i].offset_adr = oa; \
116 static void rsnd_gen1_reg_map_init(struct rsnd_gen
*gen
)
118 RSND_GEN1_REG_MAP(gen
, SRU
, SSI_MODE0
, 0x0, 0xD0);
119 RSND_GEN1_REG_MAP(gen
, SRU
, SSI_MODE1
, 0x0, 0xD4);
121 RSND_GEN1_REG_MAP(gen
, ADG
, BRRA
, 0x0, 0x00);
122 RSND_GEN1_REG_MAP(gen
, ADG
, BRRB
, 0x0, 0x04);
123 RSND_GEN1_REG_MAP(gen
, ADG
, SSICKR
, 0x0, 0x08);
124 RSND_GEN1_REG_MAP(gen
, ADG
, AUDIO_CLK_SEL0
, 0x0, 0x0c);
125 RSND_GEN1_REG_MAP(gen
, ADG
, AUDIO_CLK_SEL1
, 0x0, 0x10);
126 RSND_GEN1_REG_MAP(gen
, ADG
, AUDIO_CLK_SEL3
, 0x0, 0x18);
127 RSND_GEN1_REG_MAP(gen
, ADG
, AUDIO_CLK_SEL4
, 0x0, 0x1c);
128 RSND_GEN1_REG_MAP(gen
, ADG
, AUDIO_CLK_SEL5
, 0x0, 0x20);
130 RSND_GEN1_REG_MAP(gen
, SSI
, SSICR
, 0x40, 0x00);
131 RSND_GEN1_REG_MAP(gen
, SSI
, SSISR
, 0x40, 0x04);
132 RSND_GEN1_REG_MAP(gen
, SSI
, SSITDR
, 0x40, 0x08);
133 RSND_GEN1_REG_MAP(gen
, SSI
, SSIRDR
, 0x40, 0x0c);
134 RSND_GEN1_REG_MAP(gen
, SSI
, SSIWSR
, 0x40, 0x20);
137 static int rsnd_gen1_probe(struct platform_device
*pdev
,
138 struct rcar_snd_info
*info
,
139 struct rsnd_priv
*priv
)
141 struct device
*dev
= rsnd_priv_to_dev(priv
);
142 struct rsnd_gen
*gen
= rsnd_priv_to_gen(priv
);
143 struct resource
*sru_res
;
144 struct resource
*adg_res
;
145 struct resource
*ssi_res
;
150 sru_res
= platform_get_resource(pdev
, IORESOURCE_MEM
, RSND_GEN1_SRU
);
151 adg_res
= platform_get_resource(pdev
, IORESOURCE_MEM
, RSND_GEN1_ADG
);
152 ssi_res
= platform_get_resource(pdev
, IORESOURCE_MEM
, RSND_GEN1_SSI
);
154 gen
->base
[RSND_GEN1_SRU
] = devm_ioremap_resource(dev
, sru_res
);
155 gen
->base
[RSND_GEN1_ADG
] = devm_ioremap_resource(dev
, adg_res
);
156 gen
->base
[RSND_GEN1_SSI
] = devm_ioremap_resource(dev
, ssi_res
);
157 if (IS_ERR(gen
->base
[RSND_GEN1_SRU
]) ||
158 IS_ERR(gen
->base
[RSND_GEN1_ADG
]) ||
159 IS_ERR(gen
->base
[RSND_GEN1_SSI
]))
162 gen
->ops
= &rsnd_gen1_ops
;
163 rsnd_gen1_reg_map_init(gen
);
165 dev_dbg(dev
, "Gen1 device probed\n");
166 dev_dbg(dev
, "SRU : %08x => %p\n", sru_res
->start
,
167 gen
->base
[RSND_GEN1_SRU
]);
168 dev_dbg(dev
, "ADG : %08x => %p\n", adg_res
->start
,
169 gen
->base
[RSND_GEN1_ADG
]);
170 dev_dbg(dev
, "SSI : %08x => %p\n", ssi_res
->start
,
171 gen
->base
[RSND_GEN1_SSI
]);
177 static void rsnd_gen1_remove(struct platform_device
*pdev
,
178 struct rsnd_priv
*priv
)
185 int rsnd_gen_path_init(struct rsnd_priv
*priv
,
186 struct rsnd_dai
*rdai
,
187 struct rsnd_dai_stream
*io
)
189 struct rsnd_gen
*gen
= rsnd_priv_to_gen(priv
);
191 return gen
->ops
->path_init(priv
, rdai
, io
);
194 int rsnd_gen_path_exit(struct rsnd_priv
*priv
,
195 struct rsnd_dai
*rdai
,
196 struct rsnd_dai_stream
*io
)
198 struct rsnd_gen
*gen
= rsnd_priv_to_gen(priv
);
200 return gen
->ops
->path_exit(priv
, rdai
, io
);
203 void __iomem
*rsnd_gen_reg_get(struct rsnd_priv
*priv
,
204 struct rsnd_mod
*mod
,
207 struct rsnd_gen
*gen
= rsnd_priv_to_gen(priv
);
208 struct device
*dev
= rsnd_priv_to_dev(priv
);
210 u32 offset_id
, offset_adr
;
212 if (reg
>= RSND_REG_MAX
) {
213 dev_err(dev
, "rsnd_reg reg error\n");
217 index
= gen
->reg_map
[reg
].index
;
218 offset_id
= gen
->reg_map
[reg
].offset_id
;
219 offset_adr
= gen
->reg_map
[reg
].offset_adr
;
222 dev_err(dev
, "unsupported reg access %d\n", reg
);
226 if (offset_id
&& mod
)
227 offset_id
*= rsnd_mod_id(mod
);
230 * index/offset were set on gen1/gen2
233 return gen
->base
[index
] + offset_id
+ offset_adr
;
236 int rsnd_gen_probe(struct platform_device
*pdev
,
237 struct rcar_snd_info
*info
,
238 struct rsnd_priv
*priv
)
240 struct device
*dev
= rsnd_priv_to_dev(priv
);
241 struct rsnd_gen
*gen
;
244 gen
= devm_kzalloc(dev
, sizeof(*gen
), GFP_KERNEL
);
246 dev_err(dev
, "GEN allocate failed\n");
257 for (i
= 0; i
< RSND_REG_MAX
; i
++)
258 gen
->reg_map
[i
].index
= -1;
263 if (rsnd_is_gen1(priv
))
264 return rsnd_gen1_probe(pdev
, info
, priv
);
266 dev_err(dev
, "unknown generation R-Car sound device\n");
271 void rsnd_gen_remove(struct platform_device
*pdev
,
272 struct rsnd_priv
*priv
)
274 if (rsnd_is_gen1(priv
))
275 rsnd_gen1_remove(pdev
, priv
);