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)
39 * will be filled in the future
45 static int rsnd_gen1_path_init(struct rsnd_priv
*priv
,
46 struct rsnd_dai
*rdai
,
47 struct rsnd_dai_stream
*io
)
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)
58 * Gen1 SRU = Gen2 SCU + SSIU + etc
60 * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is
63 * Then, SSI id = SCU id here
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
);
73 mod
= rsnd_ssi_mod_get(priv
, id
);
74 ret
= rsnd_dai_connect(rdai
, mod
, io
);
79 mod
= rsnd_scu_mod_get(priv
, id
);
80 ret
= rsnd_dai_connect(rdai
, mod
, io
);
85 static int rsnd_gen1_path_exit(struct rsnd_priv
*priv
,
86 struct rsnd_dai
*rdai
,
87 struct rsnd_dai_stream
*io
)
89 struct rsnd_mod
*mod
, *n
;
93 * remove all mod from rdai
95 for_each_rsnd_mod(mod
, n
, io
)
96 ret
|= rsnd_dai_disconnect(mod
);
101 static struct rsnd_gen_ops rsnd_gen1_ops
= {
102 .path_init
= rsnd_gen1_path_init
,
103 .path_exit
= rsnd_gen1_path_exit
,
106 #define RSND_GEN1_REG_MAP(g, s, i, oi, oa) \
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; \
113 static void rsnd_gen1_reg_map_init(struct rsnd_gen
*gen
)
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);
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);
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);
141 static int rsnd_gen1_probe(struct platform_device
*pdev
,
142 struct rcar_snd_info
*info
,
143 struct rsnd_priv
*priv
)
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
;
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
);
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
]))
166 gen
->ops
= &rsnd_gen1_ops
;
167 rsnd_gen1_reg_map_init(gen
);
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
]);
181 static void rsnd_gen1_remove(struct platform_device
*pdev
,
182 struct rsnd_priv
*priv
)
189 int rsnd_gen_path_init(struct rsnd_priv
*priv
,
190 struct rsnd_dai
*rdai
,
191 struct rsnd_dai_stream
*io
)
193 struct rsnd_gen
*gen
= rsnd_priv_to_gen(priv
);
195 return gen
->ops
->path_init(priv
, rdai
, io
);
198 int rsnd_gen_path_exit(struct rsnd_priv
*priv
,
199 struct rsnd_dai
*rdai
,
200 struct rsnd_dai_stream
*io
)
202 struct rsnd_gen
*gen
= rsnd_priv_to_gen(priv
);
204 return gen
->ops
->path_exit(priv
, rdai
, io
);
207 void __iomem
*rsnd_gen_reg_get(struct rsnd_priv
*priv
,
208 struct rsnd_mod
*mod
,
211 struct rsnd_gen
*gen
= rsnd_priv_to_gen(priv
);
212 struct device
*dev
= rsnd_priv_to_dev(priv
);
214 u32 offset_id
, offset_adr
;
216 if (reg
>= RSND_REG_MAX
) {
217 dev_err(dev
, "rsnd_reg reg error\n");
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
;
226 dev_err(dev
, "unsupported reg access %d\n", reg
);
230 if (offset_id
&& mod
)
231 offset_id
*= rsnd_mod_id(mod
);
234 * index/offset were set on gen1/gen2
237 return gen
->base
[index
] + offset_id
+ offset_adr
;
240 int rsnd_gen_probe(struct platform_device
*pdev
,
241 struct rcar_snd_info
*info
,
242 struct rsnd_priv
*priv
)
244 struct device
*dev
= rsnd_priv_to_dev(priv
);
245 struct rsnd_gen
*gen
;
248 gen
= devm_kzalloc(dev
, sizeof(*gen
), GFP_KERNEL
);
250 dev_err(dev
, "GEN allocate failed\n");
261 for (i
= 0; i
< RSND_REG_MAX
; i
++)
262 gen
->reg_map
[i
].index
= -1;
267 if (rsnd_is_gen1(priv
))
268 return rsnd_gen1_probe(pdev
, info
, priv
);
270 dev_err(dev
, "unknown generation R-Car sound device\n");
275 void rsnd_gen_remove(struct platform_device
*pdev
,
276 struct rsnd_priv
*priv
)
278 if (rsnd_is_gen1(priv
))
279 rsnd_gen1_remove(pdev
, priv
);