xref: /linux/sound/soc/renesas/rcar/adg.c (revision 79a1d390f879563119bf2848b621bc7eed228c7d)
1c087a94bSLad Prabhakar // SPDX-License-Identifier: GPL-2.0
2c087a94bSLad Prabhakar //
3c087a94bSLad Prabhakar // Helper routines for R-Car sound ADG.
4c087a94bSLad Prabhakar //
5c087a94bSLad Prabhakar //  Copyright (C) 2013  Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
6c087a94bSLad Prabhakar #include <linux/clk-provider.h>
7c087a94bSLad Prabhakar #include <linux/clkdev.h>
8c087a94bSLad Prabhakar #include "rsnd.h"
9c087a94bSLad Prabhakar 
10c087a94bSLad Prabhakar #define CLKA	0
11c087a94bSLad Prabhakar #define CLKB	1
12c087a94bSLad Prabhakar #define CLKC	2
13c087a94bSLad Prabhakar #define CLKI	3
14c087a94bSLad Prabhakar #define CLKINMAX 4
15c087a94bSLad Prabhakar 
16c087a94bSLad Prabhakar #define CLKOUT	0
17c087a94bSLad Prabhakar #define CLKOUT1	1
18c087a94bSLad Prabhakar #define CLKOUT2	2
19c087a94bSLad Prabhakar #define CLKOUT3	3
20c087a94bSLad Prabhakar #define CLKOUTMAX 4
21c087a94bSLad Prabhakar 
22c087a94bSLad Prabhakar #define BRRx_MASK(x) (0x3FF & x)
23c087a94bSLad Prabhakar 
24c087a94bSLad Prabhakar static struct rsnd_mod_ops adg_ops = {
25c087a94bSLad Prabhakar 	.name = "adg",
26c087a94bSLad Prabhakar };
27c087a94bSLad Prabhakar 
28c087a94bSLad Prabhakar #define ADG_HZ_441	0
29c087a94bSLad Prabhakar #define ADG_HZ_48	1
30c087a94bSLad Prabhakar #define ADG_HZ_SIZE	2
31c087a94bSLad Prabhakar 
32c087a94bSLad Prabhakar struct rsnd_adg {
33c087a94bSLad Prabhakar 	struct clk *clkin[CLKINMAX];
34c087a94bSLad Prabhakar 	struct clk *clkout[CLKOUTMAX];
35c087a94bSLad Prabhakar 	struct clk *null_clk;
36c087a94bSLad Prabhakar 	struct clk_onecell_data onecell;
37c087a94bSLad Prabhakar 	struct rsnd_mod mod;
38c087a94bSLad Prabhakar 	int clkin_rate[CLKINMAX];
39c087a94bSLad Prabhakar 	int clkin_size;
40c087a94bSLad Prabhakar 	int clkout_size;
41c087a94bSLad Prabhakar 	u32 ckr;
42c087a94bSLad Prabhakar 	u32 brga;
43c087a94bSLad Prabhakar 	u32 brgb;
44c087a94bSLad Prabhakar 
45c087a94bSLad Prabhakar 	int brg_rate[ADG_HZ_SIZE]; /* BRGA / BRGB */
46c087a94bSLad Prabhakar };
47c087a94bSLad Prabhakar 
48c087a94bSLad Prabhakar #define for_each_rsnd_clkin(pos, adg, i)	\
49c087a94bSLad Prabhakar 	for (i = 0;				\
50c087a94bSLad Prabhakar 	     (i < adg->clkin_size) &&		\
51c087a94bSLad Prabhakar 	     ((pos) = adg->clkin[i]);		\
52c087a94bSLad Prabhakar 	     i++)
53c087a94bSLad Prabhakar #define for_each_rsnd_clkout(pos, adg, i)	\
54c087a94bSLad Prabhakar 	for (i = 0;				\
55c087a94bSLad Prabhakar 	     (i < adg->clkout_size) &&		\
56c087a94bSLad Prabhakar 	     ((pos) = adg->clkout[i]);	\
57c087a94bSLad Prabhakar 	     i++)
58c087a94bSLad Prabhakar #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg)
59c087a94bSLad Prabhakar 
60c087a94bSLad Prabhakar static const char * const clkin_name_gen4[] = {
61c087a94bSLad Prabhakar 	[CLKA]	= "clkin",
62c087a94bSLad Prabhakar };
63c087a94bSLad Prabhakar 
64c087a94bSLad Prabhakar static const char * const clkin_name_gen2[] = {
65c087a94bSLad Prabhakar 	[CLKA]	= "clk_a",
66c087a94bSLad Prabhakar 	[CLKB]	= "clk_b",
67c087a94bSLad Prabhakar 	[CLKC]	= "clk_c",
68c087a94bSLad Prabhakar 	[CLKI]	= "clk_i",
69c087a94bSLad Prabhakar };
70c087a94bSLad Prabhakar 
71c087a94bSLad Prabhakar static const char * const clkout_name_gen2[] = {
72c087a94bSLad Prabhakar 	[CLKOUT]  = "audio_clkout",
73c087a94bSLad Prabhakar 	[CLKOUT1] = "audio_clkout1",
74c087a94bSLad Prabhakar 	[CLKOUT2] = "audio_clkout2",
75c087a94bSLad Prabhakar 	[CLKOUT3] = "audio_clkout3",
76c087a94bSLad Prabhakar };
77c087a94bSLad Prabhakar 
rsnd_adg_calculate_brgx(unsigned long div)78c087a94bSLad Prabhakar static u32 rsnd_adg_calculate_brgx(unsigned long div)
79c087a94bSLad Prabhakar {
80c087a94bSLad Prabhakar 	int i;
81c087a94bSLad Prabhakar 
82c087a94bSLad Prabhakar 	if (!div)
83c087a94bSLad Prabhakar 		return 0;
84c087a94bSLad Prabhakar 
85c087a94bSLad Prabhakar 	for (i = 3; i >= 0; i--) {
86c087a94bSLad Prabhakar 		int ratio = 2 << (i * 2);
87c087a94bSLad Prabhakar 		if (0 == (div % ratio))
88c087a94bSLad Prabhakar 			return (u32)((i << 8) | ((div / ratio) - 1));
89c087a94bSLad Prabhakar 	}
90c087a94bSLad Prabhakar 
91c087a94bSLad Prabhakar 	return ~0;
92c087a94bSLad Prabhakar }
93c087a94bSLad Prabhakar 
rsnd_adg_ssi_ws_timing_gen2(struct rsnd_dai_stream * io)94c087a94bSLad Prabhakar static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_dai_stream *io)
95c087a94bSLad Prabhakar {
96c087a94bSLad Prabhakar 	struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);
97c087a94bSLad Prabhakar 	int id = rsnd_mod_id(ssi_mod);
98c087a94bSLad Prabhakar 	int ws = id;
99c087a94bSLad Prabhakar 
100c087a94bSLad Prabhakar 	if (rsnd_ssi_is_pin_sharing(io)) {
101c087a94bSLad Prabhakar 		switch (id) {
102c087a94bSLad Prabhakar 		case 1:
103c087a94bSLad Prabhakar 		case 2:
104c087a94bSLad Prabhakar 		case 9:
105c087a94bSLad Prabhakar 			ws = 0;
106c087a94bSLad Prabhakar 			break;
107c087a94bSLad Prabhakar 		case 4:
108c087a94bSLad Prabhakar 			ws = 3;
109c087a94bSLad Prabhakar 			break;
110c087a94bSLad Prabhakar 		case 8:
111c087a94bSLad Prabhakar 			ws = 7;
112c087a94bSLad Prabhakar 			break;
113c087a94bSLad Prabhakar 		}
114c087a94bSLad Prabhakar 	} else {
115c087a94bSLad Prabhakar 		/*
116c087a94bSLad Prabhakar 		 * SSI8 is not connected to ADG.
117c087a94bSLad Prabhakar 		 * Thus SSI9 is using ws = 8
118c087a94bSLad Prabhakar 		 */
119c087a94bSLad Prabhakar 		if (id == 9)
120c087a94bSLad Prabhakar 			ws = 8;
121c087a94bSLad Prabhakar 	}
122c087a94bSLad Prabhakar 
123c087a94bSLad Prabhakar 	return (0x6 + ws) << 8;
124c087a94bSLad Prabhakar }
125c087a94bSLad Prabhakar 
__rsnd_adg_get_timesel_ratio(struct rsnd_priv * priv,struct rsnd_dai_stream * io,unsigned int target_rate,unsigned int * target_val,unsigned int * target_en)126c087a94bSLad Prabhakar static void __rsnd_adg_get_timesel_ratio(struct rsnd_priv *priv,
127c087a94bSLad Prabhakar 				       struct rsnd_dai_stream *io,
128c087a94bSLad Prabhakar 				       unsigned int target_rate,
129c087a94bSLad Prabhakar 				       unsigned int *target_val,
130c087a94bSLad Prabhakar 				       unsigned int *target_en)
131c087a94bSLad Prabhakar {
132c087a94bSLad Prabhakar 	struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
133c087a94bSLad Prabhakar 	struct device *dev = rsnd_priv_to_dev(priv);
134c087a94bSLad Prabhakar 	int sel;
135c087a94bSLad Prabhakar 	unsigned int val, en;
136c087a94bSLad Prabhakar 	unsigned int min, diff;
137c087a94bSLad Prabhakar 	unsigned int sel_rate[] = {
138c087a94bSLad Prabhakar 		adg->clkin_rate[CLKA],	/* 0000: CLKA */
139c087a94bSLad Prabhakar 		adg->clkin_rate[CLKB],	/* 0001: CLKB */
140c087a94bSLad Prabhakar 		adg->clkin_rate[CLKC],	/* 0010: CLKC */
141c087a94bSLad Prabhakar 		adg->brg_rate[ADG_HZ_441],	/* 0011: BRGA */
142c087a94bSLad Prabhakar 		adg->brg_rate[ADG_HZ_48],	/* 0100: BRGB */
143c087a94bSLad Prabhakar 	};
144c087a94bSLad Prabhakar 
145c087a94bSLad Prabhakar 	min = ~0;
146c087a94bSLad Prabhakar 	val = 0;
147c087a94bSLad Prabhakar 	en = 0;
148c087a94bSLad Prabhakar 	for (sel = 0; sel < ARRAY_SIZE(sel_rate); sel++) {
149c087a94bSLad Prabhakar 		int idx = 0;
150c087a94bSLad Prabhakar 		int step = 2;
151c087a94bSLad Prabhakar 		int div;
152c087a94bSLad Prabhakar 
153c087a94bSLad Prabhakar 		if (!sel_rate[sel])
154c087a94bSLad Prabhakar 			continue;
155c087a94bSLad Prabhakar 
156c087a94bSLad Prabhakar 		for (div = 2; div <= 98304; div += step) {
157c087a94bSLad Prabhakar 			diff = abs(target_rate - sel_rate[sel] / div);
158c087a94bSLad Prabhakar 			if (min > diff) {
159c087a94bSLad Prabhakar 				val = (sel << 8) | idx;
160c087a94bSLad Prabhakar 				min = diff;
161c087a94bSLad Prabhakar 				en = 1 << (sel + 1); /* fixme */
162c087a94bSLad Prabhakar 			}
163c087a94bSLad Prabhakar 
164c087a94bSLad Prabhakar 			/*
165c087a94bSLad Prabhakar 			 * step of 0_0000 / 0_0001 / 0_1101
166c087a94bSLad Prabhakar 			 * are out of order
167c087a94bSLad Prabhakar 			 */
168c087a94bSLad Prabhakar 			if ((idx > 2) && (idx % 2))
169c087a94bSLad Prabhakar 				step *= 2;
170c087a94bSLad Prabhakar 			if (idx == 0x1c) {
171c087a94bSLad Prabhakar 				div += step;
172c087a94bSLad Prabhakar 				step *= 2;
173c087a94bSLad Prabhakar 			}
174c087a94bSLad Prabhakar 			idx++;
175c087a94bSLad Prabhakar 		}
176c087a94bSLad Prabhakar 	}
177c087a94bSLad Prabhakar 
178c087a94bSLad Prabhakar 	if (min == ~0) {
179c087a94bSLad Prabhakar 		dev_err(dev, "no Input clock\n");
180c087a94bSLad Prabhakar 		return;
181c087a94bSLad Prabhakar 	}
182c087a94bSLad Prabhakar 
183c087a94bSLad Prabhakar 	*target_val = val;
184c087a94bSLad Prabhakar 	if (target_en)
185c087a94bSLad Prabhakar 		*target_en = en;
186c087a94bSLad Prabhakar }
187c087a94bSLad Prabhakar 
rsnd_adg_get_timesel_ratio(struct rsnd_priv * priv,struct rsnd_dai_stream * io,unsigned int in_rate,unsigned int out_rate,u32 * in,u32 * out,u32 * en)188c087a94bSLad Prabhakar static void rsnd_adg_get_timesel_ratio(struct rsnd_priv *priv,
189c087a94bSLad Prabhakar 				       struct rsnd_dai_stream *io,
190c087a94bSLad Prabhakar 				       unsigned int in_rate,
191c087a94bSLad Prabhakar 				       unsigned int out_rate,
192c087a94bSLad Prabhakar 				       u32 *in, u32 *out, u32 *en)
193c087a94bSLad Prabhakar {
194c087a94bSLad Prabhakar 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
195c087a94bSLad Prabhakar 	unsigned int target_rate;
196c087a94bSLad Prabhakar 	u32 *target_val;
197c087a94bSLad Prabhakar 	u32 _in;
198c087a94bSLad Prabhakar 	u32 _out;
199c087a94bSLad Prabhakar 	u32 _en;
200c087a94bSLad Prabhakar 
201c087a94bSLad Prabhakar 	/* default = SSI WS */
202c087a94bSLad Prabhakar 	_in =
203c087a94bSLad Prabhakar 	_out = rsnd_adg_ssi_ws_timing_gen2(io);
204c087a94bSLad Prabhakar 
205c087a94bSLad Prabhakar 	target_rate = 0;
206c087a94bSLad Prabhakar 	target_val = NULL;
207c087a94bSLad Prabhakar 	_en = 0;
208c087a94bSLad Prabhakar 	if (runtime->rate != in_rate) {
209c087a94bSLad Prabhakar 		target_rate = out_rate;
210c087a94bSLad Prabhakar 		target_val  = &_out;
211c087a94bSLad Prabhakar 	} else if (runtime->rate != out_rate) {
212c087a94bSLad Prabhakar 		target_rate = in_rate;
213c087a94bSLad Prabhakar 		target_val  = &_in;
214c087a94bSLad Prabhakar 	}
215c087a94bSLad Prabhakar 
216c087a94bSLad Prabhakar 	if (target_rate)
217c087a94bSLad Prabhakar 		__rsnd_adg_get_timesel_ratio(priv, io,
218c087a94bSLad Prabhakar 					     target_rate,
219c087a94bSLad Prabhakar 					     target_val, &_en);
220c087a94bSLad Prabhakar 
221c087a94bSLad Prabhakar 	if (in)
222c087a94bSLad Prabhakar 		*in = _in;
223c087a94bSLad Prabhakar 	if (out)
224c087a94bSLad Prabhakar 		*out = _out;
225c087a94bSLad Prabhakar 	if (en)
226c087a94bSLad Prabhakar 		*en = _en;
227c087a94bSLad Prabhakar }
228c087a94bSLad Prabhakar 
rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod * cmd_mod,struct rsnd_dai_stream * io)229c087a94bSLad Prabhakar int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *cmd_mod,
230c087a94bSLad Prabhakar 				 struct rsnd_dai_stream *io)
231c087a94bSLad Prabhakar {
232c087a94bSLad Prabhakar 	struct rsnd_priv *priv = rsnd_mod_to_priv(cmd_mod);
233c087a94bSLad Prabhakar 	struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
234c087a94bSLad Prabhakar 	struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
235c087a94bSLad Prabhakar 	int id = rsnd_mod_id(cmd_mod);
236c087a94bSLad Prabhakar 	int shift = (id % 2) ? 16 : 0;
237c087a94bSLad Prabhakar 	u32 mask, val;
238c087a94bSLad Prabhakar 
239c087a94bSLad Prabhakar 	rsnd_adg_get_timesel_ratio(priv, io,
240c087a94bSLad Prabhakar 				   rsnd_src_get_in_rate(priv, io),
241c087a94bSLad Prabhakar 				   rsnd_src_get_out_rate(priv, io),
242c087a94bSLad Prabhakar 				   NULL, &val, NULL);
243c087a94bSLad Prabhakar 
244c087a94bSLad Prabhakar 	val  = val	<< shift;
245c087a94bSLad Prabhakar 	mask = 0x0f1f	<< shift;
246c087a94bSLad Prabhakar 
247c087a94bSLad Prabhakar 	rsnd_mod_bset(adg_mod, CMDOUT_TIMSEL, mask, val);
248c087a94bSLad Prabhakar 
249c087a94bSLad Prabhakar 	return 0;
250c087a94bSLad Prabhakar }
251c087a94bSLad Prabhakar 
rsnd_adg_set_src_timesel_gen2(struct rsnd_mod * src_mod,struct rsnd_dai_stream * io,unsigned int in_rate,unsigned int out_rate)252c087a94bSLad Prabhakar int rsnd_adg_set_src_timesel_gen2(struct rsnd_mod *src_mod,
253c087a94bSLad Prabhakar 				  struct rsnd_dai_stream *io,
254c087a94bSLad Prabhakar 				  unsigned int in_rate,
255c087a94bSLad Prabhakar 				  unsigned int out_rate)
256c087a94bSLad Prabhakar {
257c087a94bSLad Prabhakar 	struct rsnd_priv *priv = rsnd_mod_to_priv(src_mod);
258c087a94bSLad Prabhakar 	struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
259c087a94bSLad Prabhakar 	struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
260c087a94bSLad Prabhakar 	u32 in, out;
261c087a94bSLad Prabhakar 	u32 mask, en;
262c087a94bSLad Prabhakar 	int id = rsnd_mod_id(src_mod);
263c087a94bSLad Prabhakar 	int shift = (id % 2) ? 16 : 0;
264c087a94bSLad Prabhakar 
265c087a94bSLad Prabhakar 	rsnd_mod_make_sure(src_mod, RSND_MOD_SRC);
266c087a94bSLad Prabhakar 
267c087a94bSLad Prabhakar 	rsnd_adg_get_timesel_ratio(priv, io,
268c087a94bSLad Prabhakar 				   in_rate, out_rate,
269c087a94bSLad Prabhakar 				   &in, &out, &en);
270c087a94bSLad Prabhakar 
271c087a94bSLad Prabhakar 	in   = in	<< shift;
272c087a94bSLad Prabhakar 	out  = out	<< shift;
273c087a94bSLad Prabhakar 	mask = 0x0f1f	<< shift;
274c087a94bSLad Prabhakar 
275c087a94bSLad Prabhakar 	rsnd_mod_bset(adg_mod, SRCIN_TIMSEL(id / 2),  mask, in);
276c087a94bSLad Prabhakar 	rsnd_mod_bset(adg_mod, SRCOUT_TIMSEL(id / 2), mask, out);
277c087a94bSLad Prabhakar 
278c087a94bSLad Prabhakar 	if (en)
279c087a94bSLad Prabhakar 		rsnd_mod_bset(adg_mod, DIV_EN, en, en);
280c087a94bSLad Prabhakar 
281c087a94bSLad Prabhakar 	return 0;
282c087a94bSLad Prabhakar }
283c087a94bSLad Prabhakar 
rsnd_adg_set_ssi_clk(struct rsnd_mod * ssi_mod,u32 val)284c087a94bSLad Prabhakar static void rsnd_adg_set_ssi_clk(struct rsnd_mod *ssi_mod, u32 val)
285c087a94bSLad Prabhakar {
286c087a94bSLad Prabhakar 	struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod);
287c087a94bSLad Prabhakar 	struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
288c087a94bSLad Prabhakar 	struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
289c087a94bSLad Prabhakar 	struct device *dev = rsnd_priv_to_dev(priv);
290c087a94bSLad Prabhakar 	int id = rsnd_mod_id(ssi_mod);
291c087a94bSLad Prabhakar 	int shift = (id % 4) * 8;
292c087a94bSLad Prabhakar 	u32 mask = 0xFF << shift;
293c087a94bSLad Prabhakar 
294c087a94bSLad Prabhakar 	rsnd_mod_make_sure(ssi_mod, RSND_MOD_SSI);
295c087a94bSLad Prabhakar 
296c087a94bSLad Prabhakar 	val = val << shift;
297c087a94bSLad Prabhakar 
298c087a94bSLad Prabhakar 	/*
299c087a94bSLad Prabhakar 	 * SSI 8 is not connected to ADG.
300c087a94bSLad Prabhakar 	 * it works with SSI 7
301c087a94bSLad Prabhakar 	 */
302c087a94bSLad Prabhakar 	if (id == 8)
303c087a94bSLad Prabhakar 		return;
304c087a94bSLad Prabhakar 
305c087a94bSLad Prabhakar 	rsnd_mod_bset(adg_mod, AUDIO_CLK_SEL(id / 4), mask, val);
306c087a94bSLad Prabhakar 
307c087a94bSLad Prabhakar 	dev_dbg(dev, "AUDIO_CLK_SEL is 0x%x\n", val);
308c087a94bSLad Prabhakar }
309c087a94bSLad Prabhakar 
rsnd_adg_clk_query(struct rsnd_priv * priv,unsigned int rate)310c087a94bSLad Prabhakar int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate)
311c087a94bSLad Prabhakar {
312c087a94bSLad Prabhakar 	struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
313c087a94bSLad Prabhakar 	struct clk *clk;
314c087a94bSLad Prabhakar 	int i;
315c087a94bSLad Prabhakar 	int sel_table[] = {
316c087a94bSLad Prabhakar 		[CLKA] = 0x1,
317c087a94bSLad Prabhakar 		[CLKB] = 0x2,
318c087a94bSLad Prabhakar 		[CLKC] = 0x3,
319c087a94bSLad Prabhakar 		[CLKI] = 0x0,
320c087a94bSLad Prabhakar 	};
321c087a94bSLad Prabhakar 
322c087a94bSLad Prabhakar 	/*
323c087a94bSLad Prabhakar 	 * find suitable clock from
324c087a94bSLad Prabhakar 	 * AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC/AUDIO_CLKI.
325c087a94bSLad Prabhakar 	 */
326c087a94bSLad Prabhakar 	for_each_rsnd_clkin(clk, adg, i)
327c087a94bSLad Prabhakar 		if (rate == adg->clkin_rate[i])
328c087a94bSLad Prabhakar 			return sel_table[i];
329c087a94bSLad Prabhakar 
330c087a94bSLad Prabhakar 	/*
331c087a94bSLad Prabhakar 	 * find divided clock from BRGA/BRGB
332c087a94bSLad Prabhakar 	 */
333c087a94bSLad Prabhakar 	if (rate == adg->brg_rate[ADG_HZ_441])
334c087a94bSLad Prabhakar 		return 0x10;
335c087a94bSLad Prabhakar 
336c087a94bSLad Prabhakar 	if (rate == adg->brg_rate[ADG_HZ_48])
337c087a94bSLad Prabhakar 		return 0x20;
338c087a94bSLad Prabhakar 
339c087a94bSLad Prabhakar 	return -EIO;
340c087a94bSLad Prabhakar }
341c087a94bSLad Prabhakar 
rsnd_adg_ssi_clk_stop(struct rsnd_mod * ssi_mod)342c087a94bSLad Prabhakar int rsnd_adg_ssi_clk_stop(struct rsnd_mod *ssi_mod)
343c087a94bSLad Prabhakar {
344c087a94bSLad Prabhakar 	rsnd_adg_set_ssi_clk(ssi_mod, 0);
345c087a94bSLad Prabhakar 
346c087a94bSLad Prabhakar 	return 0;
347c087a94bSLad Prabhakar }
348c087a94bSLad Prabhakar 
rsnd_adg_ssi_clk_try_start(struct rsnd_mod * ssi_mod,unsigned int rate)349c087a94bSLad Prabhakar int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate)
350c087a94bSLad Prabhakar {
351c087a94bSLad Prabhakar 	struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod);
352c087a94bSLad Prabhakar 	struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
353c087a94bSLad Prabhakar 	struct device *dev = rsnd_priv_to_dev(priv);
354c087a94bSLad Prabhakar 	struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
355c087a94bSLad Prabhakar 	int data;
356c087a94bSLad Prabhakar 	u32 ckr = 0;
357c087a94bSLad Prabhakar 
358c087a94bSLad Prabhakar 	data = rsnd_adg_clk_query(priv, rate);
359c087a94bSLad Prabhakar 	if (data < 0)
360c087a94bSLad Prabhakar 		return data;
361c087a94bSLad Prabhakar 
362c087a94bSLad Prabhakar 	rsnd_adg_set_ssi_clk(ssi_mod, data);
363c087a94bSLad Prabhakar 
364c087a94bSLad Prabhakar 	if (0 == (rate % 8000))
365c087a94bSLad Prabhakar 		ckr = 0x80000000; /* BRGB output = 48kHz */
366c087a94bSLad Prabhakar 
367c087a94bSLad Prabhakar 	rsnd_mod_bset(adg_mod, BRGCKR, 0x80770000, adg->ckr | ckr);
368c087a94bSLad Prabhakar 
369c087a94bSLad Prabhakar 	dev_dbg(dev, "CLKOUT is based on BRG%c (= %dHz)\n",
370c087a94bSLad Prabhakar 		(ckr) ? 'B' : 'A',
371c087a94bSLad Prabhakar 		(ckr) ?	adg->brg_rate[ADG_HZ_48] :
372c087a94bSLad Prabhakar 			adg->brg_rate[ADG_HZ_441]);
373c087a94bSLad Prabhakar 
374c087a94bSLad Prabhakar 	return 0;
375c087a94bSLad Prabhakar }
376c087a94bSLad Prabhakar 
rsnd_adg_clk_control(struct rsnd_priv * priv,int enable)377*139fa599SKuninori Morimoto int rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
378c087a94bSLad Prabhakar {
379c087a94bSLad Prabhakar 	struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
380c087a94bSLad Prabhakar 	struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
381c087a94bSLad Prabhakar 	struct clk *clk;
382*139fa599SKuninori Morimoto 	int ret = 0, i;
383c087a94bSLad Prabhakar 
384c087a94bSLad Prabhakar 	if (enable) {
385c087a94bSLad Prabhakar 		rsnd_mod_bset(adg_mod, BRGCKR, 0x80770000, adg->ckr);
386c087a94bSLad Prabhakar 		rsnd_mod_write(adg_mod, BRRA,  adg->brga);
387c087a94bSLad Prabhakar 		rsnd_mod_write(adg_mod, BRRB,  adg->brgb);
388c087a94bSLad Prabhakar 	}
389c087a94bSLad Prabhakar 
390c087a94bSLad Prabhakar 	for_each_rsnd_clkin(clk, adg, i) {
391c087a94bSLad Prabhakar 		if (enable) {
392*139fa599SKuninori Morimoto 			ret = clk_prepare_enable(clk);
393c087a94bSLad Prabhakar 
394c087a94bSLad Prabhakar 			/*
395c087a94bSLad Prabhakar 			 * We shouldn't use clk_get_rate() under
396c087a94bSLad Prabhakar 			 * atomic context. Let's keep it when
397c087a94bSLad Prabhakar 			 * rsnd_adg_clk_enable() was called
398c087a94bSLad Prabhakar 			 */
399*139fa599SKuninori Morimoto 			if (ret < 0)
400*139fa599SKuninori Morimoto 				break;
401*139fa599SKuninori Morimoto 
402c087a94bSLad Prabhakar 			adg->clkin_rate[i] = clk_get_rate(clk);
403c087a94bSLad Prabhakar 		} else {
404*139fa599SKuninori Morimoto 			if (adg->clkin_rate[i])
405c087a94bSLad Prabhakar 				clk_disable_unprepare(clk);
406*139fa599SKuninori Morimoto 
407*139fa599SKuninori Morimoto 			adg->clkin_rate[i] = 0;
408c087a94bSLad Prabhakar 		}
409c087a94bSLad Prabhakar 	}
410*139fa599SKuninori Morimoto 
411*139fa599SKuninori Morimoto 	/*
412*139fa599SKuninori Morimoto 	 * rsnd_adg_clk_enable() might return error (_disable() will not).
413*139fa599SKuninori Morimoto 	 * We need to rollback in such case
414*139fa599SKuninori Morimoto 	 */
415*139fa599SKuninori Morimoto 	if (ret < 0)
416*139fa599SKuninori Morimoto 		rsnd_adg_clk_disable(priv);
417*139fa599SKuninori Morimoto 
418*139fa599SKuninori Morimoto 	return ret;
419c087a94bSLad Prabhakar }
420c087a94bSLad Prabhakar 
rsnd_adg_create_null_clk(struct rsnd_priv * priv,const char * const name,const char * parent)421c087a94bSLad Prabhakar static struct clk *rsnd_adg_create_null_clk(struct rsnd_priv *priv,
422c087a94bSLad Prabhakar 					    const char * const name,
423c087a94bSLad Prabhakar 					    const char *parent)
424c087a94bSLad Prabhakar {
425c087a94bSLad Prabhakar 	struct device *dev = rsnd_priv_to_dev(priv);
426c087a94bSLad Prabhakar 	struct clk *clk;
427c087a94bSLad Prabhakar 
428c087a94bSLad Prabhakar 	clk = clk_register_fixed_rate(dev, name, parent, 0, 0);
429c087a94bSLad Prabhakar 	if (IS_ERR_OR_NULL(clk)) {
430c087a94bSLad Prabhakar 		dev_err(dev, "create null clk error\n");
431c087a94bSLad Prabhakar 		return ERR_CAST(clk);
432c087a94bSLad Prabhakar 	}
433c087a94bSLad Prabhakar 
434c087a94bSLad Prabhakar 	return clk;
435c087a94bSLad Prabhakar }
436c087a94bSLad Prabhakar 
rsnd_adg_null_clk_get(struct rsnd_priv * priv)437c087a94bSLad Prabhakar static struct clk *rsnd_adg_null_clk_get(struct rsnd_priv *priv)
438c087a94bSLad Prabhakar {
439c087a94bSLad Prabhakar 	struct rsnd_adg *adg = priv->adg;
440c087a94bSLad Prabhakar 
441c087a94bSLad Prabhakar 	if (!adg->null_clk) {
442c087a94bSLad Prabhakar 		static const char * const name = "rsnd_adg_null";
443c087a94bSLad Prabhakar 
444c087a94bSLad Prabhakar 		adg->null_clk = rsnd_adg_create_null_clk(priv, name, NULL);
445c087a94bSLad Prabhakar 	}
446c087a94bSLad Prabhakar 
447c087a94bSLad Prabhakar 	return adg->null_clk;
448c087a94bSLad Prabhakar }
449c087a94bSLad Prabhakar 
rsnd_adg_null_clk_clean(struct rsnd_priv * priv)450c087a94bSLad Prabhakar static void rsnd_adg_null_clk_clean(struct rsnd_priv *priv)
451c087a94bSLad Prabhakar {
452c087a94bSLad Prabhakar 	struct rsnd_adg *adg = priv->adg;
453c087a94bSLad Prabhakar 
454c087a94bSLad Prabhakar 	if (adg->null_clk)
455c087a94bSLad Prabhakar 		clk_unregister_fixed_rate(adg->null_clk);
456c087a94bSLad Prabhakar }
457c087a94bSLad Prabhakar 
rsnd_adg_get_clkin(struct rsnd_priv * priv)458c087a94bSLad Prabhakar static int rsnd_adg_get_clkin(struct rsnd_priv *priv)
459c087a94bSLad Prabhakar {
460c087a94bSLad Prabhakar 	struct rsnd_adg *adg = priv->adg;
461c087a94bSLad Prabhakar 	struct device *dev = rsnd_priv_to_dev(priv);
462c087a94bSLad Prabhakar 	struct clk *clk;
463c087a94bSLad Prabhakar 	const char * const *clkin_name;
464c087a94bSLad Prabhakar 	int clkin_size;
465c087a94bSLad Prabhakar 	int i;
466c087a94bSLad Prabhakar 
467c087a94bSLad Prabhakar 	clkin_name = clkin_name_gen2;
468c087a94bSLad Prabhakar 	clkin_size = ARRAY_SIZE(clkin_name_gen2);
469c087a94bSLad Prabhakar 	if (rsnd_is_gen4(priv)) {
470c087a94bSLad Prabhakar 		clkin_name = clkin_name_gen4;
471c087a94bSLad Prabhakar 		clkin_size = ARRAY_SIZE(clkin_name_gen4);
472c087a94bSLad Prabhakar 	}
473c087a94bSLad Prabhakar 
474c087a94bSLad Prabhakar 	for (i = 0; i < clkin_size; i++) {
475c087a94bSLad Prabhakar 		clk = devm_clk_get(dev, clkin_name[i]);
476c087a94bSLad Prabhakar 
477c087a94bSLad Prabhakar 		if (IS_ERR_OR_NULL(clk))
478c087a94bSLad Prabhakar 			clk = rsnd_adg_null_clk_get(priv);
479c087a94bSLad Prabhakar 		if (IS_ERR_OR_NULL(clk))
480c087a94bSLad Prabhakar 			goto err;
481c087a94bSLad Prabhakar 
482c087a94bSLad Prabhakar 		adg->clkin[i] = clk;
483c087a94bSLad Prabhakar 	}
484c087a94bSLad Prabhakar 
485c087a94bSLad Prabhakar 	adg->clkin_size = clkin_size;
486c087a94bSLad Prabhakar 
487c087a94bSLad Prabhakar 	return 0;
488c087a94bSLad Prabhakar 
489c087a94bSLad Prabhakar err:
490c087a94bSLad Prabhakar 	dev_err(dev, "adg clock IN get failed\n");
491c087a94bSLad Prabhakar 
492c087a94bSLad Prabhakar 	rsnd_adg_null_clk_clean(priv);
493c087a94bSLad Prabhakar 
494c087a94bSLad Prabhakar 	return -EIO;
495c087a94bSLad Prabhakar }
496c087a94bSLad Prabhakar 
rsnd_adg_unregister_clkout(struct rsnd_priv * priv)497c087a94bSLad Prabhakar static void rsnd_adg_unregister_clkout(struct rsnd_priv *priv)
498c087a94bSLad Prabhakar {
499c087a94bSLad Prabhakar 	struct rsnd_adg *adg = priv->adg;
500c087a94bSLad Prabhakar 	struct clk *clk;
501c087a94bSLad Prabhakar 	int i;
502c087a94bSLad Prabhakar 
503c087a94bSLad Prabhakar 	for_each_rsnd_clkout(clk, adg, i)
504c087a94bSLad Prabhakar 		clk_unregister_fixed_rate(clk);
505c087a94bSLad Prabhakar }
506c087a94bSLad Prabhakar 
rsnd_adg_get_clkout(struct rsnd_priv * priv)507c087a94bSLad Prabhakar static int rsnd_adg_get_clkout(struct rsnd_priv *priv)
508c087a94bSLad Prabhakar {
509c087a94bSLad Prabhakar 	struct rsnd_adg *adg = priv->adg;
510c087a94bSLad Prabhakar 	struct clk *clk;
511c087a94bSLad Prabhakar 	struct device *dev = rsnd_priv_to_dev(priv);
512c087a94bSLad Prabhakar 	struct device_node *np = dev->of_node;
513c087a94bSLad Prabhakar 	struct property *prop;
514c087a94bSLad Prabhakar 	u32 ckr, brgx, brga, brgb;
515c087a94bSLad Prabhakar 	u32 req_rate[ADG_HZ_SIZE] = {};
516c087a94bSLad Prabhakar 	uint32_t count = 0;
517c087a94bSLad Prabhakar 	unsigned long req_Hz[ADG_HZ_SIZE];
518c087a94bSLad Prabhakar 	int clkout_size;
519c087a94bSLad Prabhakar 	int i, req_size;
520c087a94bSLad Prabhakar 	int approximate = 0;
521c087a94bSLad Prabhakar 	const char *parent_clk_name = NULL;
522c087a94bSLad Prabhakar 	const char * const *clkout_name;
523c087a94bSLad Prabhakar 	int brg_table[] = {
524c087a94bSLad Prabhakar 		[CLKA] = 0x0,
525c087a94bSLad Prabhakar 		[CLKB] = 0x1,
526c087a94bSLad Prabhakar 		[CLKC] = 0x4,
527c087a94bSLad Prabhakar 		[CLKI] = 0x2,
528c087a94bSLad Prabhakar 	};
529c087a94bSLad Prabhakar 
530c087a94bSLad Prabhakar 	ckr = 0;
531c087a94bSLad Prabhakar 	brga = 0xff; /* default */
532c087a94bSLad Prabhakar 	brgb = 0xff; /* default */
533c087a94bSLad Prabhakar 
534c087a94bSLad Prabhakar 	/*
535c087a94bSLad Prabhakar 	 * ADG supports BRRA/BRRB output only
536c087a94bSLad Prabhakar 	 * this means all clkout0/1/2/3 will be same rate
537c087a94bSLad Prabhakar 	 */
538c087a94bSLad Prabhakar 	prop = of_find_property(np, "clock-frequency", NULL);
539c087a94bSLad Prabhakar 	if (!prop)
540c087a94bSLad Prabhakar 		goto rsnd_adg_get_clkout_end;
541c087a94bSLad Prabhakar 
542c087a94bSLad Prabhakar 	req_size = prop->length / sizeof(u32);
543c087a94bSLad Prabhakar 	if (req_size > ADG_HZ_SIZE) {
544c087a94bSLad Prabhakar 		dev_err(dev, "too many clock-frequency\n");
545c087a94bSLad Prabhakar 		return -EINVAL;
546c087a94bSLad Prabhakar 	}
547c087a94bSLad Prabhakar 
548c087a94bSLad Prabhakar 	of_property_read_u32_array(np, "clock-frequency", req_rate, req_size);
549c087a94bSLad Prabhakar 	req_Hz[ADG_HZ_48]  = 0;
550c087a94bSLad Prabhakar 	req_Hz[ADG_HZ_441] = 0;
551c087a94bSLad Prabhakar 	for (i = 0; i < req_size; i++) {
552c087a94bSLad Prabhakar 		if (0 == (req_rate[i] % 44100))
553c087a94bSLad Prabhakar 			req_Hz[ADG_HZ_441] = req_rate[i];
554c087a94bSLad Prabhakar 		if (0 == (req_rate[i] % 48000))
555c087a94bSLad Prabhakar 			req_Hz[ADG_HZ_48] = req_rate[i];
556c087a94bSLad Prabhakar 	}
557c087a94bSLad Prabhakar 
558c087a94bSLad Prabhakar 	/*
559c087a94bSLad Prabhakar 	 * This driver is assuming that AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC
560c087a94bSLad Prabhakar 	 * have 44.1kHz or 48kHz base clocks for now.
561c087a94bSLad Prabhakar 	 *
562c087a94bSLad Prabhakar 	 * SSI itself can divide parent clock by 1/1 - 1/16
563c087a94bSLad Prabhakar 	 * see
564c087a94bSLad Prabhakar 	 *	rsnd_adg_ssi_clk_try_start()
565c087a94bSLad Prabhakar 	 *	rsnd_ssi_master_clk_start()
566c087a94bSLad Prabhakar 	 */
567c087a94bSLad Prabhakar 
568c087a94bSLad Prabhakar 	/*
569c087a94bSLad Prabhakar 	 * [APPROXIMATE]
570c087a94bSLad Prabhakar 	 *
571c087a94bSLad Prabhakar 	 * clk_i (internal clock) can't create accurate rate, it will be approximate rate.
572c087a94bSLad Prabhakar 	 *
573c087a94bSLad Prabhakar 	 * <Note>
574c087a94bSLad Prabhakar 	 *
575c087a94bSLad Prabhakar 	 * clk_i needs x2 of required maximum rate.
576c087a94bSLad Prabhakar 	 * see
577c087a94bSLad Prabhakar 	 *	- Minimum division of BRRA/BRRB
578c087a94bSLad Prabhakar 	 *	- rsnd_ssi_clk_query()
579c087a94bSLad Prabhakar 	 *
580c087a94bSLad Prabhakar 	 * Sample Settings for TDM 8ch, 32bit width
581c087a94bSLad Prabhakar 	 *
582c087a94bSLad Prabhakar 	 *	8(ch) x 32(bit) x 44100(Hz) x 2<Note> = 22579200
583c087a94bSLad Prabhakar 	 *	8(ch) x 32(bit) x 48000(Hz) x 2<Note> = 24576000
584c087a94bSLad Prabhakar 	 *
585c087a94bSLad Prabhakar 	 *	clock-frequency = <22579200 24576000>;
586c087a94bSLad Prabhakar 	 */
587c087a94bSLad Prabhakar 	for_each_rsnd_clkin(clk, adg, i) {
588c087a94bSLad Prabhakar 		u32 rate, div;
589c087a94bSLad Prabhakar 
590c087a94bSLad Prabhakar 		rate = clk_get_rate(clk);
591c087a94bSLad Prabhakar 
592c087a94bSLad Prabhakar 		if (0 == rate) /* not used */
593c087a94bSLad Prabhakar 			continue;
594c087a94bSLad Prabhakar 
595c087a94bSLad Prabhakar 		/* BRGA */
596c087a94bSLad Prabhakar 
597c087a94bSLad Prabhakar 		if (i == CLKI)
598c087a94bSLad Prabhakar 			/* see [APPROXIMATE] */
599c087a94bSLad Prabhakar 			rate = (clk_get_rate(clk) / req_Hz[ADG_HZ_441]) * req_Hz[ADG_HZ_441];
600c087a94bSLad Prabhakar 		if (!adg->brg_rate[ADG_HZ_441] && req_Hz[ADG_HZ_441] && (0 == rate % 44100)) {
601c087a94bSLad Prabhakar 			div = rate / req_Hz[ADG_HZ_441];
602c087a94bSLad Prabhakar 			brgx = rsnd_adg_calculate_brgx(div);
603c087a94bSLad Prabhakar 			if (BRRx_MASK(brgx) == brgx) {
604c087a94bSLad Prabhakar 				brga = brgx;
605c087a94bSLad Prabhakar 				adg->brg_rate[ADG_HZ_441] = rate / div;
606c087a94bSLad Prabhakar 				ckr |= brg_table[i] << 20;
607c087a94bSLad Prabhakar 				if (req_Hz[ADG_HZ_441])
608c087a94bSLad Prabhakar 					parent_clk_name = __clk_get_name(clk);
609c087a94bSLad Prabhakar 				if (i == CLKI)
610c087a94bSLad Prabhakar 					approximate = 1;
611c087a94bSLad Prabhakar 			}
612c087a94bSLad Prabhakar 		}
613c087a94bSLad Prabhakar 
614c087a94bSLad Prabhakar 		/* BRGB */
615c087a94bSLad Prabhakar 
616c087a94bSLad Prabhakar 		if (i == CLKI)
617c087a94bSLad Prabhakar 			/* see [APPROXIMATE] */
618c087a94bSLad Prabhakar 			rate = (clk_get_rate(clk) / req_Hz[ADG_HZ_48]) * req_Hz[ADG_HZ_48];
619c087a94bSLad Prabhakar 		if (!adg->brg_rate[ADG_HZ_48] && req_Hz[ADG_HZ_48] && (0 == rate % 48000)) {
620c087a94bSLad Prabhakar 			div = rate / req_Hz[ADG_HZ_48];
621c087a94bSLad Prabhakar 			brgx = rsnd_adg_calculate_brgx(div);
622c087a94bSLad Prabhakar 			if (BRRx_MASK(brgx) == brgx) {
623c087a94bSLad Prabhakar 				brgb = brgx;
624c087a94bSLad Prabhakar 				adg->brg_rate[ADG_HZ_48] = rate / div;
625c087a94bSLad Prabhakar 				ckr |= brg_table[i] << 16;
626c087a94bSLad Prabhakar 				if (req_Hz[ADG_HZ_48])
627c087a94bSLad Prabhakar 					parent_clk_name = __clk_get_name(clk);
628c087a94bSLad Prabhakar 				if (i == CLKI)
629c087a94bSLad Prabhakar 					approximate = 1;
630c087a94bSLad Prabhakar 			}
631c087a94bSLad Prabhakar 		}
632c087a94bSLad Prabhakar 	}
633c087a94bSLad Prabhakar 
634c087a94bSLad Prabhakar 	if (!(adg->brg_rate[ADG_HZ_48]  && req_Hz[ADG_HZ_48]) &&
635c087a94bSLad Prabhakar 	    !(adg->brg_rate[ADG_HZ_441] && req_Hz[ADG_HZ_441]))
636c087a94bSLad Prabhakar 		goto rsnd_adg_get_clkout_end;
637c087a94bSLad Prabhakar 
638c087a94bSLad Prabhakar 	if (approximate)
639c087a94bSLad Prabhakar 		dev_info(dev, "It uses CLK_I as approximate rate");
640c087a94bSLad Prabhakar 
641c087a94bSLad Prabhakar 	clkout_name = clkout_name_gen2;
642c087a94bSLad Prabhakar 	clkout_size = ARRAY_SIZE(clkout_name_gen2);
643c087a94bSLad Prabhakar 	if (rsnd_is_gen4(priv))
644c087a94bSLad Prabhakar 		clkout_size = 1; /* reuse clkout_name_gen2[] */
645c087a94bSLad Prabhakar 
646c087a94bSLad Prabhakar 	/*
647c087a94bSLad Prabhakar 	 * ADG supports BRRA/BRRB output only.
648c087a94bSLad Prabhakar 	 * this means all clkout0/1/2/3 will be * same rate
649c087a94bSLad Prabhakar 	 */
650c087a94bSLad Prabhakar 
651c087a94bSLad Prabhakar 	of_property_read_u32(np, "#clock-cells", &count);
652c087a94bSLad Prabhakar 	/*
653c087a94bSLad Prabhakar 	 * for clkout
654c087a94bSLad Prabhakar 	 */
655c087a94bSLad Prabhakar 	if (!count) {
656c087a94bSLad Prabhakar 		clk = clk_register_fixed_rate(dev, clkout_name[CLKOUT],
657c087a94bSLad Prabhakar 					      parent_clk_name, 0, req_rate[0]);
658c087a94bSLad Prabhakar 		if (IS_ERR_OR_NULL(clk))
659c087a94bSLad Prabhakar 			goto err;
660c087a94bSLad Prabhakar 
661c087a94bSLad Prabhakar 		adg->clkout[CLKOUT] = clk;
662c087a94bSLad Prabhakar 		adg->clkout_size = 1;
663c087a94bSLad Prabhakar 		of_clk_add_provider(np, of_clk_src_simple_get, clk);
664c087a94bSLad Prabhakar 	}
665c087a94bSLad Prabhakar 	/*
666c087a94bSLad Prabhakar 	 * for clkout0/1/2/3
667c087a94bSLad Prabhakar 	 */
668c087a94bSLad Prabhakar 	else {
669c087a94bSLad Prabhakar 		for (i = 0; i < clkout_size; i++) {
670c087a94bSLad Prabhakar 			clk = clk_register_fixed_rate(dev, clkout_name[i],
671c087a94bSLad Prabhakar 						      parent_clk_name, 0,
672c087a94bSLad Prabhakar 						      req_rate[0]);
673c087a94bSLad Prabhakar 			if (IS_ERR_OR_NULL(clk))
674c087a94bSLad Prabhakar 				goto err;
675c087a94bSLad Prabhakar 
676c087a94bSLad Prabhakar 			adg->clkout[i] = clk;
677c087a94bSLad Prabhakar 		}
678c087a94bSLad Prabhakar 		adg->onecell.clks	= adg->clkout;
679c087a94bSLad Prabhakar 		adg->onecell.clk_num	= clkout_size;
680c087a94bSLad Prabhakar 		adg->clkout_size	= clkout_size;
681c087a94bSLad Prabhakar 		of_clk_add_provider(np, of_clk_src_onecell_get,
682c087a94bSLad Prabhakar 				    &adg->onecell);
683c087a94bSLad Prabhakar 	}
684c087a94bSLad Prabhakar 
685c087a94bSLad Prabhakar rsnd_adg_get_clkout_end:
686c087a94bSLad Prabhakar 	adg->ckr = ckr;
687c087a94bSLad Prabhakar 	adg->brga = brga;
688c087a94bSLad Prabhakar 	adg->brgb = brgb;
689c087a94bSLad Prabhakar 
690c087a94bSLad Prabhakar 	return 0;
691c087a94bSLad Prabhakar 
692c087a94bSLad Prabhakar err:
693c087a94bSLad Prabhakar 	dev_err(dev, "adg clock OUT get failed\n");
694c087a94bSLad Prabhakar 
695c087a94bSLad Prabhakar 	rsnd_adg_unregister_clkout(priv);
696c087a94bSLad Prabhakar 
697c087a94bSLad Prabhakar 	return -EIO;
698c087a94bSLad Prabhakar }
699c087a94bSLad Prabhakar 
700c087a94bSLad Prabhakar #if defined(DEBUG) || defined(CONFIG_DEBUG_FS)
701c087a94bSLad Prabhakar __printf(3, 4)
dbg_msg(struct device * dev,struct seq_file * m,const char * fmt,...)702c087a94bSLad Prabhakar static void dbg_msg(struct device *dev, struct seq_file *m,
703c087a94bSLad Prabhakar 				   const char *fmt, ...)
704c087a94bSLad Prabhakar {
705c087a94bSLad Prabhakar 	char msg[128];
706c087a94bSLad Prabhakar 	va_list args;
707c087a94bSLad Prabhakar 
708c087a94bSLad Prabhakar 	va_start(args, fmt);
709c087a94bSLad Prabhakar 	vsnprintf(msg, sizeof(msg), fmt, args);
710c087a94bSLad Prabhakar 	va_end(args);
711c087a94bSLad Prabhakar 
712c087a94bSLad Prabhakar 	if (m)
713c087a94bSLad Prabhakar 		seq_puts(m, msg);
714c087a94bSLad Prabhakar 	else
715c087a94bSLad Prabhakar 		dev_dbg(dev, "%s", msg);
716c087a94bSLad Prabhakar }
717c087a94bSLad Prabhakar 
rsnd_adg_clk_dbg_info(struct rsnd_priv * priv,struct seq_file * m)718c087a94bSLad Prabhakar void rsnd_adg_clk_dbg_info(struct rsnd_priv *priv, struct seq_file *m)
719c087a94bSLad Prabhakar {
720c087a94bSLad Prabhakar 	struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
721c087a94bSLad Prabhakar 	struct device *dev = rsnd_priv_to_dev(priv);
722c087a94bSLad Prabhakar 	struct clk *clk;
723c087a94bSLad Prabhakar 	int i;
724c087a94bSLad Prabhakar 
725c087a94bSLad Prabhakar 	for_each_rsnd_clkin(clk, adg, i)
726c087a94bSLad Prabhakar 		dbg_msg(dev, m, "%-18s : %pa : %ld\n",
727c087a94bSLad Prabhakar 			__clk_get_name(clk), clk, clk_get_rate(clk));
728c087a94bSLad Prabhakar 
729c087a94bSLad Prabhakar 	dbg_msg(dev, m, "BRGCKR = 0x%08x, BRRA/BRRB = 0x%x/0x%x\n",
730c087a94bSLad Prabhakar 		adg->ckr, adg->brga, adg->brgb);
731c087a94bSLad Prabhakar 	dbg_msg(dev, m, "BRGA (for 44100 base) = %d\n", adg->brg_rate[ADG_HZ_441]);
732c087a94bSLad Prabhakar 	dbg_msg(dev, m, "BRGB (for 48000 base) = %d\n", adg->brg_rate[ADG_HZ_48]);
733c087a94bSLad Prabhakar 
734c087a94bSLad Prabhakar 	/*
735c087a94bSLad Prabhakar 	 * Actual CLKOUT will be exchanged in rsnd_adg_ssi_clk_try_start()
736c087a94bSLad Prabhakar 	 * by BRGCKR::BRGCKR_31
737c087a94bSLad Prabhakar 	 */
738c087a94bSLad Prabhakar 	for_each_rsnd_clkout(clk, adg, i)
739c087a94bSLad Prabhakar 		dbg_msg(dev, m, "%-18s : %pa : %ld\n",
740c087a94bSLad Prabhakar 			__clk_get_name(clk), clk, clk_get_rate(clk));
741c087a94bSLad Prabhakar }
742c087a94bSLad Prabhakar #else
743c087a94bSLad Prabhakar #define rsnd_adg_clk_dbg_info(priv, m)
744c087a94bSLad Prabhakar #endif
745c087a94bSLad Prabhakar 
rsnd_adg_probe(struct rsnd_priv * priv)746c087a94bSLad Prabhakar int rsnd_adg_probe(struct rsnd_priv *priv)
747c087a94bSLad Prabhakar {
748c087a94bSLad Prabhakar 	struct rsnd_adg *adg;
749c087a94bSLad Prabhakar 	struct device *dev = rsnd_priv_to_dev(priv);
750c087a94bSLad Prabhakar 	int ret;
751c087a94bSLad Prabhakar 
752c087a94bSLad Prabhakar 	adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL);
753c087a94bSLad Prabhakar 	if (!adg)
754c087a94bSLad Prabhakar 		return -ENOMEM;
755c087a94bSLad Prabhakar 
756c087a94bSLad Prabhakar 	ret = rsnd_mod_init(priv, &adg->mod, &adg_ops,
757c087a94bSLad Prabhakar 		      NULL, 0, 0);
758c087a94bSLad Prabhakar 	if (ret)
759c087a94bSLad Prabhakar 		return ret;
760c087a94bSLad Prabhakar 
761c087a94bSLad Prabhakar 	priv->adg = adg;
762c087a94bSLad Prabhakar 
763c087a94bSLad Prabhakar 	ret = rsnd_adg_get_clkin(priv);
764c087a94bSLad Prabhakar 	if (ret)
765c087a94bSLad Prabhakar 		return ret;
766c087a94bSLad Prabhakar 
767c087a94bSLad Prabhakar 	ret = rsnd_adg_get_clkout(priv);
768c087a94bSLad Prabhakar 	if (ret)
769c087a94bSLad Prabhakar 		return ret;
770c087a94bSLad Prabhakar 
771*139fa599SKuninori Morimoto 	ret = rsnd_adg_clk_enable(priv);
772*139fa599SKuninori Morimoto 	if (ret)
773*139fa599SKuninori Morimoto 		return ret;
774*139fa599SKuninori Morimoto 
775c087a94bSLad Prabhakar 	rsnd_adg_clk_dbg_info(priv, NULL);
776c087a94bSLad Prabhakar 
777c087a94bSLad Prabhakar 	return 0;
778c087a94bSLad Prabhakar }
779c087a94bSLad Prabhakar 
rsnd_adg_remove(struct rsnd_priv * priv)780c087a94bSLad Prabhakar void rsnd_adg_remove(struct rsnd_priv *priv)
781c087a94bSLad Prabhakar {
782c087a94bSLad Prabhakar 	struct device *dev = rsnd_priv_to_dev(priv);
783c087a94bSLad Prabhakar 	struct device_node *np = dev->of_node;
784c087a94bSLad Prabhakar 
785c087a94bSLad Prabhakar 	rsnd_adg_unregister_clkout(priv);
786c087a94bSLad Prabhakar 
787c087a94bSLad Prabhakar 	of_clk_del_provider(np);
788c087a94bSLad Prabhakar 
789c087a94bSLad Prabhakar 	rsnd_adg_clk_disable(priv);
790c087a94bSLad Prabhakar 
791c087a94bSLad Prabhakar 	/* It should be called after rsnd_adg_clk_disable() */
792c087a94bSLad Prabhakar 	rsnd_adg_null_clk_clean(priv);
793c087a94bSLad Prabhakar }
794