11e0edd4dSKuninori Morimoto // SPDX-License-Identifier: GPL-2.0
21e0edd4dSKuninori Morimoto //
31e0edd4dSKuninori Morimoto // Renesas R-Car SRC support
41e0edd4dSKuninori Morimoto //
51e0edd4dSKuninori Morimoto // Copyright (C) 2013 Renesas Solutions Corp.
61e0edd4dSKuninori Morimoto // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
72b627869SKuninori Morimoto
82b627869SKuninori Morimoto /*
963346d3dSKuninori Morimoto * You can use Synchronous Sampling Rate Convert (if no DVC)
1063346d3dSKuninori Morimoto *
1163346d3dSKuninori Morimoto * amixer set "SRC Out Rate" on
1263346d3dSKuninori Morimoto * aplay xxx.wav &
1363346d3dSKuninori Morimoto * amixer set "SRC Out Rate" 96000 // convert rate to 96000Hz
1463346d3dSKuninori Morimoto * amixer set "SRC Out Rate" 22050 // convert rate to 22050Hz
1563346d3dSKuninori Morimoto */
1663346d3dSKuninori Morimoto
1763346d3dSKuninori Morimoto /*
182b627869SKuninori Morimoto * you can enable below define if you don't need
192b627869SKuninori Morimoto * SSI interrupt status debug message when debugging
201788a152SKuninori Morimoto * see rsnd_print_irq_status()
212b627869SKuninori Morimoto *
222b627869SKuninori Morimoto * #define RSND_DEBUG_NO_IRQ_STATUS 1
232b627869SKuninori Morimoto */
242b627869SKuninori Morimoto
25ba9c949fSKuninori Morimoto #include "rsnd.h"
26ba9c949fSKuninori Morimoto
278aefda50SKuninori Morimoto #define SRC_NAME "src"
288aefda50SKuninori Morimoto
29cfcefe01SKuninori Morimoto /* SCU_SYSTEM_STATUS0/1 */
30cfcefe01SKuninori Morimoto #define OUF_SRC(id) ((1 << (id + 16)) | (1 << id))
31cfcefe01SKuninori Morimoto
32ba9c949fSKuninori Morimoto struct rsnd_src {
33ba9c949fSKuninori Morimoto struct rsnd_mod mod;
34940e9479SKuninori Morimoto struct rsnd_mod *dma;
3543cb6954SKuninori Morimoto struct rsnd_kctrl_cfg_s sen; /* sync convert enable */
3643cb6954SKuninori Morimoto struct rsnd_kctrl_cfg_s sync; /* sync convert */
37adf6a681SKuninori Morimoto int irq;
38ba9c949fSKuninori Morimoto };
39ba9c949fSKuninori Morimoto
40ba9c949fSKuninori Morimoto #define RSND_SRC_NAME_SIZE 16
41ba9c949fSKuninori Morimoto
42adf6a681SKuninori Morimoto #define rsnd_src_get(priv, id) ((struct rsnd_src *)(priv->src) + id)
43da599fd3SKuninori Morimoto #define rsnd_src_nr(priv) ((priv)->src_nr)
44ab2049f9SKuninori Morimoto #define rsnd_src_sync_is_enabled(mod) (rsnd_mod_to_src(mod)->sen.val)
4582e76ed3SKuninori Morimoto
46ba9c949fSKuninori Morimoto #define rsnd_mod_to_src(_mod) \
47ba9c949fSKuninori Morimoto container_of((_mod), struct rsnd_src, mod)
48ba9c949fSKuninori Morimoto
49ba9c949fSKuninori Morimoto #define for_each_rsnd_src(pos, priv, i) \
50ba9c949fSKuninori Morimoto for ((i) = 0; \
51ba9c949fSKuninori Morimoto ((i) < rsnd_src_nr(priv)) && \
52ba9c949fSKuninori Morimoto ((pos) = (struct rsnd_src *)(priv)->src + i); \
53ba9c949fSKuninori Morimoto i++)
54ba9c949fSKuninori Morimoto
55ba9c949fSKuninori Morimoto
56ba9c949fSKuninori Morimoto /*
57ba9c949fSKuninori Morimoto * image of SRC (Sampling Rate Converter)
58ba9c949fSKuninori Morimoto *
59ba9c949fSKuninori Morimoto * 96kHz <-> +-----+ 48kHz +-----+ 48kHz +-------+
60ba9c949fSKuninori Morimoto * 48kHz <-> | SRC | <------> | SSI | <-----> | codec |
61ba9c949fSKuninori Morimoto * 44.1kHz <-> +-----+ +-----+ +-------+
62ba9c949fSKuninori Morimoto * ...
63ba9c949fSKuninori Morimoto *
64ba9c949fSKuninori Morimoto */
65ba9c949fSKuninori Morimoto
rsnd_src_activation(struct rsnd_mod * mod)6698efeeaeSKuninori Morimoto static void rsnd_src_activation(struct rsnd_mod *mod)
67379febfdSKuninori Morimoto {
68379febfdSKuninori Morimoto rsnd_mod_write(mod, SRC_SWRSR, 0);
69379febfdSKuninori Morimoto rsnd_mod_write(mod, SRC_SWRSR, 1);
70379febfdSKuninori Morimoto }
71379febfdSKuninori Morimoto
rsnd_src_halt(struct rsnd_mod * mod)72475a361aSKuninori Morimoto static void rsnd_src_halt(struct rsnd_mod *mod)
73475a361aSKuninori Morimoto {
74475a361aSKuninori Morimoto rsnd_mod_write(mod, SRC_SRCIR, 1);
75475a361aSKuninori Morimoto rsnd_mod_write(mod, SRC_SWRSR, 0);
76475a361aSKuninori Morimoto }
77475a361aSKuninori Morimoto
rsnd_src_dma_req(struct rsnd_dai_stream * io,struct rsnd_mod * mod)789b99e9a7SKuninori Morimoto static struct dma_chan *rsnd_src_dma_req(struct rsnd_dai_stream *io,
799b99e9a7SKuninori Morimoto struct rsnd_mod *mod)
8072adc61fSKuninori Morimoto {
8172adc61fSKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
8272adc61fSKuninori Morimoto int is_play = rsnd_io_is_play(io);
8372adc61fSKuninori Morimoto
8472adc61fSKuninori Morimoto return rsnd_dma_request_channel(rsnd_src_of_node(priv),
85039f2cccSKuninori Morimoto SRC_NAME, mod,
8672adc61fSKuninori Morimoto is_play ? "rx" : "tx");
8772adc61fSKuninori Morimoto }
8872adc61fSKuninori Morimoto
rsnd_src_convert_rate(struct rsnd_dai_stream * io,struct rsnd_mod * mod)8988c61cffSKuninori Morimoto static u32 rsnd_src_convert_rate(struct rsnd_dai_stream *io,
901a9be9eeSKuninori Morimoto struct rsnd_mod *mod)
9143cb6954SKuninori Morimoto {
9243cb6954SKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
931a9be9eeSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod);
9443cb6954SKuninori Morimoto u32 convert_rate;
9543cb6954SKuninori Morimoto
9643cb6954SKuninori Morimoto if (!runtime)
9743cb6954SKuninori Morimoto return 0;
9843cb6954SKuninori Morimoto
99ab2049f9SKuninori Morimoto if (!rsnd_src_sync_is_enabled(mod))
100c2aaaa57SKuninori Morimoto return rsnd_io_converted_rate(io);
10143cb6954SKuninori Morimoto
10243cb6954SKuninori Morimoto convert_rate = src->sync.val;
10343cb6954SKuninori Morimoto
10443cb6954SKuninori Morimoto if (!convert_rate)
105c2aaaa57SKuninori Morimoto convert_rate = rsnd_io_converted_rate(io);
10643cb6954SKuninori Morimoto
10743cb6954SKuninori Morimoto if (!convert_rate)
10843cb6954SKuninori Morimoto convert_rate = runtime->rate;
10943cb6954SKuninori Morimoto
11043cb6954SKuninori Morimoto return convert_rate;
11143cb6954SKuninori Morimoto }
11243cb6954SKuninori Morimoto
rsnd_src_get_rate(struct rsnd_priv * priv,struct rsnd_dai_stream * io,int is_in)113cbf1494fSKuninori Morimoto unsigned int rsnd_src_get_rate(struct rsnd_priv *priv,
114ba9c949fSKuninori Morimoto struct rsnd_dai_stream *io,
115cbf1494fSKuninori Morimoto int is_in)
116ba9c949fSKuninori Morimoto {
117b1eac430SKuninori Morimoto struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
118cbf1494fSKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
119b1eac430SKuninori Morimoto unsigned int rate = 0;
120cbf1494fSKuninori Morimoto int is_play = rsnd_io_is_play(io);
121cbf1494fSKuninori Morimoto
122cbf1494fSKuninori Morimoto /*
123cbf1494fSKuninori Morimoto * Playback
124cbf1494fSKuninori Morimoto * runtime_rate -> [SRC] -> convert_rate
125cbf1494fSKuninori Morimoto *
126cbf1494fSKuninori Morimoto * Capture
127cbf1494fSKuninori Morimoto * convert_rate -> [SRC] -> runtime_rate
128cbf1494fSKuninori Morimoto */
129cbf1494fSKuninori Morimoto
130cbf1494fSKuninori Morimoto if (is_play == is_in)
131cbf1494fSKuninori Morimoto return runtime->rate;
132ba9c949fSKuninori Morimoto
133ba9c949fSKuninori Morimoto /*
134ba9c949fSKuninori Morimoto * return convert rate if SRC is used,
135ba9c949fSKuninori Morimoto * otherwise, return runtime->rate as usual
136ba9c949fSKuninori Morimoto */
1371a9be9eeSKuninori Morimoto if (src_mod)
1381a9be9eeSKuninori Morimoto rate = rsnd_src_convert_rate(io, src_mod);
139b1eac430SKuninori Morimoto
140ba9c949fSKuninori Morimoto if (!rate)
141ba9c949fSKuninori Morimoto rate = runtime->rate;
142ba9c949fSKuninori Morimoto
143ba9c949fSKuninori Morimoto return rate;
144ba9c949fSKuninori Morimoto }
145ba9c949fSKuninori Morimoto
146399706dfSJiada Wang static const u32 bsdsr_table_pattern1[] = {
1477674bec4SKuninori Morimoto 0x01800000, /* 6 - 1/6 */
1487674bec4SKuninori Morimoto 0x01000000, /* 6 - 1/4 */
1497674bec4SKuninori Morimoto 0x00c00000, /* 6 - 1/3 */
1507674bec4SKuninori Morimoto 0x00800000, /* 6 - 1/2 */
1517674bec4SKuninori Morimoto 0x00600000, /* 6 - 2/3 */
1527674bec4SKuninori Morimoto 0x00400000, /* 6 - 1 */
1537674bec4SKuninori Morimoto };
1547674bec4SKuninori Morimoto
155399706dfSJiada Wang static const u32 bsdsr_table_pattern2[] = {
1567674bec4SKuninori Morimoto 0x02400000, /* 6 - 1/6 */
1577674bec4SKuninori Morimoto 0x01800000, /* 6 - 1/4 */
1587674bec4SKuninori Morimoto 0x01200000, /* 6 - 1/3 */
1597674bec4SKuninori Morimoto 0x00c00000, /* 6 - 1/2 */
1607674bec4SKuninori Morimoto 0x00900000, /* 6 - 2/3 */
1617674bec4SKuninori Morimoto 0x00600000, /* 6 - 1 */
1627674bec4SKuninori Morimoto };
1637674bec4SKuninori Morimoto
164399706dfSJiada Wang static const u32 bsisr_table[] = {
1657674bec4SKuninori Morimoto 0x00100060, /* 6 - 1/6 */
1667674bec4SKuninori Morimoto 0x00100040, /* 6 - 1/4 */
1677674bec4SKuninori Morimoto 0x00100030, /* 6 - 1/3 */
1687674bec4SKuninori Morimoto 0x00100020, /* 6 - 1/2 */
1697674bec4SKuninori Morimoto 0x00100020, /* 6 - 2/3 */
1707674bec4SKuninori Morimoto 0x00100020, /* 6 - 1 */
1717674bec4SKuninori Morimoto };
1727674bec4SKuninori Morimoto
173399706dfSJiada Wang static const u32 chan288888[] = {
1747674bec4SKuninori Morimoto 0x00000006, /* 1 to 2 */
1757674bec4SKuninori Morimoto 0x000001fe, /* 1 to 8 */
1767674bec4SKuninori Morimoto 0x000001fe, /* 1 to 8 */
1777674bec4SKuninori Morimoto 0x000001fe, /* 1 to 8 */
1787674bec4SKuninori Morimoto 0x000001fe, /* 1 to 8 */
1797674bec4SKuninori Morimoto 0x000001fe, /* 1 to 8 */
1807674bec4SKuninori Morimoto };
1817674bec4SKuninori Morimoto
182399706dfSJiada Wang static const u32 chan244888[] = {
1837674bec4SKuninori Morimoto 0x00000006, /* 1 to 2 */
1847674bec4SKuninori Morimoto 0x0000001e, /* 1 to 4 */
1857674bec4SKuninori Morimoto 0x0000001e, /* 1 to 4 */
1867674bec4SKuninori Morimoto 0x000001fe, /* 1 to 8 */
1877674bec4SKuninori Morimoto 0x000001fe, /* 1 to 8 */
1887674bec4SKuninori Morimoto 0x000001fe, /* 1 to 8 */
1897674bec4SKuninori Morimoto };
1907674bec4SKuninori Morimoto
191399706dfSJiada Wang static const u32 chan222222[] = {
1927674bec4SKuninori Morimoto 0x00000006, /* 1 to 2 */
1937674bec4SKuninori Morimoto 0x00000006, /* 1 to 2 */
1947674bec4SKuninori Morimoto 0x00000006, /* 1 to 2 */
1957674bec4SKuninori Morimoto 0x00000006, /* 1 to 2 */
1967674bec4SKuninori Morimoto 0x00000006, /* 1 to 2 */
1977674bec4SKuninori Morimoto 0x00000006, /* 1 to 2 */
1987674bec4SKuninori Morimoto };
1997674bec4SKuninori Morimoto
rsnd_src_set_convert_rate(struct rsnd_dai_stream * io,struct rsnd_mod * mod)20075916f65SKuninori Morimoto static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
20175916f65SKuninori Morimoto struct rsnd_mod *mod)
202ba9c949fSKuninori Morimoto {
20375916f65SKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
204cfcefe01SKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv);
20575916f65SKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
20690431eb4SKuninori Morimoto int is_play = rsnd_io_is_play(io);
20767923f77SKuninori Morimoto int use_src = 0;
2080102eed5SKuninori Morimoto u32 fin, fout;
20975916f65SKuninori Morimoto u32 ifscr, fsrate, adinr;
21075916f65SKuninori Morimoto u32 cr, route;
21190431eb4SKuninori Morimoto u32 i_busif, o_busif, tmp;
2127674bec4SKuninori Morimoto const u32 *bsdsr_table;
2137674bec4SKuninori Morimoto const u32 *chptn;
21475916f65SKuninori Morimoto uint ratio;
2157674bec4SKuninori Morimoto int chan;
2167674bec4SKuninori Morimoto int idx;
217ba9c949fSKuninori Morimoto
21875916f65SKuninori Morimoto if (!runtime)
21975916f65SKuninori Morimoto return;
220ba9c949fSKuninori Morimoto
2210102eed5SKuninori Morimoto fin = rsnd_src_get_in_rate(priv, io);
2220102eed5SKuninori Morimoto fout = rsnd_src_get_out_rate(priv, io);
2230102eed5SKuninori Morimoto
2247674bec4SKuninori Morimoto chan = rsnd_runtime_channel_original(io);
2257674bec4SKuninori Morimoto
22675916f65SKuninori Morimoto /* 6 - 1/6 are very enough ratio for SRC_BSDSR */
2270102eed5SKuninori Morimoto if (fin == fout)
22875916f65SKuninori Morimoto ratio = 0;
2290102eed5SKuninori Morimoto else if (fin > fout)
2300102eed5SKuninori Morimoto ratio = 100 * fin / fout;
23175916f65SKuninori Morimoto else
2320102eed5SKuninori Morimoto ratio = 100 * fout / fin;
233cfcefe01SKuninori Morimoto
23475916f65SKuninori Morimoto if (ratio > 600) {
23575916f65SKuninori Morimoto dev_err(dev, "FSO/FSI ratio error\n");
23675916f65SKuninori Morimoto return;
237ba9c949fSKuninori Morimoto }
238ba9c949fSKuninori Morimoto
23967923f77SKuninori Morimoto use_src = (fin != fout) | rsnd_src_sync_is_enabled(mod);
24067923f77SKuninori Morimoto
241ba9c949fSKuninori Morimoto /*
24275916f65SKuninori Morimoto * SRC_ADINR
243ba9c949fSKuninori Morimoto */
2447674bec4SKuninori Morimoto adinr = rsnd_get_adinr_bit(mod, io) | chan;
24575916f65SKuninori Morimoto
24675916f65SKuninori Morimoto /*
24775916f65SKuninori Morimoto * SRC_IFSCR / SRC_IFSVR
24875916f65SKuninori Morimoto */
24975916f65SKuninori Morimoto ifscr = 0;
25075916f65SKuninori Morimoto fsrate = 0;
25167923f77SKuninori Morimoto if (use_src) {
25293ca33c9SHiroyuki Yokoyama u64 n;
25393ca33c9SHiroyuki Yokoyama
25475916f65SKuninori Morimoto ifscr = 1;
25593ca33c9SHiroyuki Yokoyama n = (u64)0x0400000 * fin;
25693ca33c9SHiroyuki Yokoyama do_div(n, fout);
25793ca33c9SHiroyuki Yokoyama fsrate = n;
25875916f65SKuninori Morimoto }
25975916f65SKuninori Morimoto
26075916f65SKuninori Morimoto /*
26175916f65SKuninori Morimoto * SRC_SRCCR / SRC_ROUTE_MODE0
26275916f65SKuninori Morimoto */
26375916f65SKuninori Morimoto cr = 0x00011110;
26475916f65SKuninori Morimoto route = 0x0;
26567923f77SKuninori Morimoto if (use_src) {
26675916f65SKuninori Morimoto route = 0x1;
26775916f65SKuninori Morimoto
268ab2049f9SKuninori Morimoto if (rsnd_src_sync_is_enabled(mod)) {
26975916f65SKuninori Morimoto cr |= 0x1;
27075916f65SKuninori Morimoto route |= rsnd_io_is_play(io) ?
27175916f65SKuninori Morimoto (0x1 << 24) : (0x1 << 25);
27275916f65SKuninori Morimoto }
27375916f65SKuninori Morimoto }
27475916f65SKuninori Morimoto
27575916f65SKuninori Morimoto /*
27675916f65SKuninori Morimoto * SRC_BSDSR / SRC_BSISR
2777674bec4SKuninori Morimoto *
2787674bec4SKuninori Morimoto * see
2797674bec4SKuninori Morimoto * Combination of Register Setting Related to
2807674bec4SKuninori Morimoto * FSO/FSI Ratio and Channel, Latency
28175916f65SKuninori Morimoto */
28275916f65SKuninori Morimoto switch (rsnd_mod_id(mod)) {
2837674bec4SKuninori Morimoto case 0:
2847674bec4SKuninori Morimoto chptn = chan288888;
2857674bec4SKuninori Morimoto bsdsr_table = bsdsr_table_pattern1;
2867674bec4SKuninori Morimoto break;
2877674bec4SKuninori Morimoto case 1:
2887674bec4SKuninori Morimoto case 3:
2897674bec4SKuninori Morimoto case 4:
2907674bec4SKuninori Morimoto chptn = chan244888;
2917674bec4SKuninori Morimoto bsdsr_table = bsdsr_table_pattern1;
2927674bec4SKuninori Morimoto break;
2937674bec4SKuninori Morimoto case 2:
2947674bec4SKuninori Morimoto case 9:
2957674bec4SKuninori Morimoto chptn = chan222222;
2967674bec4SKuninori Morimoto bsdsr_table = bsdsr_table_pattern1;
2977674bec4SKuninori Morimoto break;
29875916f65SKuninori Morimoto case 5:
29975916f65SKuninori Morimoto case 6:
30075916f65SKuninori Morimoto case 7:
30175916f65SKuninori Morimoto case 8:
3027674bec4SKuninori Morimoto chptn = chan222222;
3037674bec4SKuninori Morimoto bsdsr_table = bsdsr_table_pattern2;
30475916f65SKuninori Morimoto break;
30575916f65SKuninori Morimoto default:
3067674bec4SKuninori Morimoto goto convert_rate_err;
30775916f65SKuninori Morimoto }
30875916f65SKuninori Morimoto
3097674bec4SKuninori Morimoto /*
3107674bec4SKuninori Morimoto * E3 need to overwrite
3117674bec4SKuninori Morimoto */
312ba164a49SJiada Wang if (rsnd_is_e3(priv))
3137674bec4SKuninori Morimoto switch (rsnd_mod_id(mod)) {
3147674bec4SKuninori Morimoto case 0:
3157674bec4SKuninori Morimoto case 4:
3167674bec4SKuninori Morimoto chptn = chan222222;
3177674bec4SKuninori Morimoto }
3187674bec4SKuninori Morimoto
3197674bec4SKuninori Morimoto for (idx = 0; idx < ARRAY_SIZE(chan222222); idx++)
3207674bec4SKuninori Morimoto if (chptn[idx] & (1 << chan))
3217674bec4SKuninori Morimoto break;
3227674bec4SKuninori Morimoto
3237674bec4SKuninori Morimoto if (chan > 8 ||
3247674bec4SKuninori Morimoto idx >= ARRAY_SIZE(chan222222))
3257674bec4SKuninori Morimoto goto convert_rate_err;
3267674bec4SKuninori Morimoto
32790431eb4SKuninori Morimoto /* BUSIF_MODE */
32890431eb4SKuninori Morimoto tmp = rsnd_get_busif_shift(io, mod);
32990431eb4SKuninori Morimoto i_busif = ( is_play ? tmp : 0) | 1;
33090431eb4SKuninori Morimoto o_busif = (!is_play ? tmp : 0) | 1;
33190431eb4SKuninori Morimoto
3320fbab951SKuninori Morimoto rsnd_mod_write(mod, SRC_ROUTE_MODE0, route);
3330fbab951SKuninori Morimoto
33475916f65SKuninori Morimoto rsnd_mod_write(mod, SRC_SRCIR, 1); /* initialize */
33575916f65SKuninori Morimoto rsnd_mod_write(mod, SRC_ADINR, adinr);
33675916f65SKuninori Morimoto rsnd_mod_write(mod, SRC_IFSCR, ifscr);
33775916f65SKuninori Morimoto rsnd_mod_write(mod, SRC_IFSVR, fsrate);
33875916f65SKuninori Morimoto rsnd_mod_write(mod, SRC_SRCCR, cr);
3397674bec4SKuninori Morimoto rsnd_mod_write(mod, SRC_BSDSR, bsdsr_table[idx]);
3407674bec4SKuninori Morimoto rsnd_mod_write(mod, SRC_BSISR, bsisr_table[idx]);
34175916f65SKuninori Morimoto rsnd_mod_write(mod, SRC_SRCIR, 0); /* cancel initialize */
34275916f65SKuninori Morimoto
34390431eb4SKuninori Morimoto rsnd_mod_write(mod, SRC_I_BUSIF_MODE, i_busif);
34490431eb4SKuninori Morimoto rsnd_mod_write(mod, SRC_O_BUSIF_MODE, o_busif);
34590431eb4SKuninori Morimoto
34675916f65SKuninori Morimoto rsnd_mod_write(mod, SRC_BUSIF_DALIGN, rsnd_get_dalign(mod, io));
34775916f65SKuninori Morimoto
3480102eed5SKuninori Morimoto rsnd_adg_set_src_timesel_gen2(mod, io, fin, fout);
3497674bec4SKuninori Morimoto
3507674bec4SKuninori Morimoto return;
3517674bec4SKuninori Morimoto
3527674bec4SKuninori Morimoto convert_rate_err:
3537674bec4SKuninori Morimoto dev_err(dev, "unknown BSDSR/BSDIR settings\n");
35475916f65SKuninori Morimoto }
35575916f65SKuninori Morimoto
rsnd_src_irq(struct rsnd_mod * mod,struct rsnd_dai_stream * io,struct rsnd_priv * priv,int enable)356b5b442abSKuninori Morimoto static int rsnd_src_irq(struct rsnd_mod *mod,
357b5b442abSKuninori Morimoto struct rsnd_dai_stream *io,
358b5b442abSKuninori Morimoto struct rsnd_priv *priv,
359b5b442abSKuninori Morimoto int enable)
360cfcefe01SKuninori Morimoto {
361cfcefe01SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod);
362cfcefe01SKuninori Morimoto u32 sys_int_val, int_val, sys_int_mask;
363adf6a681SKuninori Morimoto int irq = src->irq;
364cfcefe01SKuninori Morimoto int id = rsnd_mod_id(mod);
365cfcefe01SKuninori Morimoto
366cfcefe01SKuninori Morimoto sys_int_val =
367cfcefe01SKuninori Morimoto sys_int_mask = OUF_SRC(id);
368cfcefe01SKuninori Morimoto int_val = 0x3300;
369cfcefe01SKuninori Morimoto
370cfcefe01SKuninori Morimoto /*
371cfcefe01SKuninori Morimoto * IRQ is not supported on non-DT
372cfcefe01SKuninori Morimoto * see
37375916f65SKuninori Morimoto * rsnd_src_probe_()
374cfcefe01SKuninori Morimoto */
375cfcefe01SKuninori Morimoto if ((irq <= 0) || !enable) {
376cfcefe01SKuninori Morimoto sys_int_val = 0;
377cfcefe01SKuninori Morimoto int_val = 0;
378cfcefe01SKuninori Morimoto }
379cfcefe01SKuninori Morimoto
3801a1bf58aSKuninori Morimoto /*
3811a1bf58aSKuninori Morimoto * WORKAROUND
3821a1bf58aSKuninori Morimoto *
383ab2049f9SKuninori Morimoto * ignore over flow error when rsnd_src_sync_is_enabled()
3841a1bf58aSKuninori Morimoto */
385ab2049f9SKuninori Morimoto if (rsnd_src_sync_is_enabled(mod))
3861a1bf58aSKuninori Morimoto sys_int_val = sys_int_val & 0xffff;
3871a1bf58aSKuninori Morimoto
388cfcefe01SKuninori Morimoto rsnd_mod_write(mod, SRC_INT_ENABLE0, int_val);
389cfcefe01SKuninori Morimoto rsnd_mod_bset(mod, SCU_SYS_INT_EN0, sys_int_mask, sys_int_val);
390cfcefe01SKuninori Morimoto rsnd_mod_bset(mod, SCU_SYS_INT_EN1, sys_int_mask, sys_int_val);
391b5b442abSKuninori Morimoto
392b5b442abSKuninori Morimoto return 0;
393cfcefe01SKuninori Morimoto }
394cfcefe01SKuninori Morimoto
rsnd_src_status_clear(struct rsnd_mod * mod)3958cc225f7SKuninori Morimoto static void rsnd_src_status_clear(struct rsnd_mod *mod)
396cfcefe01SKuninori Morimoto {
397cfcefe01SKuninori Morimoto u32 val = OUF_SRC(rsnd_mod_id(mod));
398cfcefe01SKuninori Morimoto
39942b197e7SKuninori Morimoto rsnd_mod_write(mod, SCU_SYS_STATUS0, val);
40042b197e7SKuninori Morimoto rsnd_mod_write(mod, SCU_SYS_STATUS1, val);
401cfcefe01SKuninori Morimoto }
402cfcefe01SKuninori Morimoto
rsnd_src_error_occurred(struct rsnd_mod * mod)4036a25c8daSKuninori Morimoto static bool rsnd_src_error_occurred(struct rsnd_mod *mod)
404cfcefe01SKuninori Morimoto {
4052b627869SKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
4062b627869SKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv);
4071a1bf58aSKuninori Morimoto u32 val0, val1;
4082b627869SKuninori Morimoto u32 status0, status1;
409cfcefe01SKuninori Morimoto bool ret = false;
410cfcefe01SKuninori Morimoto
4111a1bf58aSKuninori Morimoto val0 = val1 = OUF_SRC(rsnd_mod_id(mod));
4121a1bf58aSKuninori Morimoto
4131a1bf58aSKuninori Morimoto /*
4141a1bf58aSKuninori Morimoto * WORKAROUND
4151a1bf58aSKuninori Morimoto *
416ab2049f9SKuninori Morimoto * ignore over flow error when rsnd_src_sync_is_enabled()
4171a1bf58aSKuninori Morimoto */
418ab2049f9SKuninori Morimoto if (rsnd_src_sync_is_enabled(mod))
4191a1bf58aSKuninori Morimoto val0 = val0 & 0xffff;
4201a1bf58aSKuninori Morimoto
4212b627869SKuninori Morimoto status0 = rsnd_mod_read(mod, SCU_SYS_STATUS0);
4222b627869SKuninori Morimoto status1 = rsnd_mod_read(mod, SCU_SYS_STATUS1);
4232b627869SKuninori Morimoto if ((status0 & val0) || (status1 & val1)) {
4241788a152SKuninori Morimoto rsnd_print_irq_status(dev, "%s err status : 0x%08x, 0x%08x\n",
425c0ea089dSKuninori Morimoto rsnd_mod_name(mod), status0, status1);
4262b627869SKuninori Morimoto
427cfcefe01SKuninori Morimoto ret = true;
4282b627869SKuninori Morimoto }
429cfcefe01SKuninori Morimoto
430cfcefe01SKuninori Morimoto return ret;
431cfcefe01SKuninori Morimoto }
432cfcefe01SKuninori Morimoto
rsnd_src_start(struct rsnd_mod * mod,struct rsnd_dai_stream * io,struct rsnd_priv * priv)43375916f65SKuninori Morimoto static int rsnd_src_start(struct rsnd_mod *mod,
434497debaaSKuninori Morimoto struct rsnd_dai_stream *io,
435497debaaSKuninori Morimoto struct rsnd_priv *priv)
436cfcefe01SKuninori Morimoto {
4371a1bf58aSKuninori Morimoto u32 val;
4381a1bf58aSKuninori Morimoto
4391a1bf58aSKuninori Morimoto /*
4401a1bf58aSKuninori Morimoto * WORKAROUND
4411a1bf58aSKuninori Morimoto *
4421a1bf58aSKuninori Morimoto * Enable SRC output if you want to use sync convert together with DVC
4431a1bf58aSKuninori Morimoto */
444ab2049f9SKuninori Morimoto val = (rsnd_io_to_mod_dvc(io) && !rsnd_src_sync_is_enabled(mod)) ?
4451a1bf58aSKuninori Morimoto 0x01 : 0x11;
446cfcefe01SKuninori Morimoto
447cfcefe01SKuninori Morimoto rsnd_mod_write(mod, SRC_CTRL, val);
448cfcefe01SKuninori Morimoto
44975916f65SKuninori Morimoto return 0;
45075916f65SKuninori Morimoto }
451cfcefe01SKuninori Morimoto
rsnd_src_stop(struct rsnd_mod * mod,struct rsnd_dai_stream * io,struct rsnd_priv * priv)45275916f65SKuninori Morimoto static int rsnd_src_stop(struct rsnd_mod *mod,
45375916f65SKuninori Morimoto struct rsnd_dai_stream *io,
45475916f65SKuninori Morimoto struct rsnd_priv *priv)
45575916f65SKuninori Morimoto {
45631739a68SKuninori Morimoto rsnd_mod_write(mod, SRC_CTRL, 0);
457cfcefe01SKuninori Morimoto
458cfcefe01SKuninori Morimoto return 0;
459cfcefe01SKuninori Morimoto }
460cfcefe01SKuninori Morimoto
rsnd_src_init(struct rsnd_mod * mod,struct rsnd_dai_stream * io,struct rsnd_priv * priv)46175916f65SKuninori Morimoto static int rsnd_src_init(struct rsnd_mod *mod,
462497debaaSKuninori Morimoto struct rsnd_dai_stream *io,
463497debaaSKuninori Morimoto struct rsnd_priv *priv)
464cfcefe01SKuninori Morimoto {
46575916f65SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod);
466*376be51cSJiasheng Jiang int ret;
467cfcefe01SKuninori Morimoto
468ef30da1cSKuninori Morimoto /* reset sync convert_rate */
469ef30da1cSKuninori Morimoto src->sync.val = 0;
470ef30da1cSKuninori Morimoto
471*376be51cSJiasheng Jiang ret = rsnd_mod_power_on(mod);
472*376be51cSJiasheng Jiang if (ret < 0)
473*376be51cSJiasheng Jiang return ret;
474cfcefe01SKuninori Morimoto
47598efeeaeSKuninori Morimoto rsnd_src_activation(mod);
476cfcefe01SKuninori Morimoto
47775916f65SKuninori Morimoto rsnd_src_set_convert_rate(io, mod);
47875916f65SKuninori Morimoto
4798cc225f7SKuninori Morimoto rsnd_src_status_clear(mod);
48075916f65SKuninori Morimoto
48175916f65SKuninori Morimoto return 0;
482cfcefe01SKuninori Morimoto }
483cfcefe01SKuninori Morimoto
rsnd_src_quit(struct rsnd_mod * mod,struct rsnd_dai_stream * io,struct rsnd_priv * priv)48475916f65SKuninori Morimoto static int rsnd_src_quit(struct rsnd_mod *mod,
485b761bf27SKuninori Morimoto struct rsnd_dai_stream *io,
486b761bf27SKuninori Morimoto struct rsnd_priv *priv)
487b761bf27SKuninori Morimoto {
48875916f65SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod);
48975916f65SKuninori Morimoto
490475a361aSKuninori Morimoto rsnd_src_halt(mod);
491475a361aSKuninori Morimoto
49275916f65SKuninori Morimoto rsnd_mod_power_off(mod);
49375916f65SKuninori Morimoto
49475916f65SKuninori Morimoto /* reset sync convert_rate */
49575916f65SKuninori Morimoto src->sync.val = 0;
49675916f65SKuninori Morimoto
49775916f65SKuninori Morimoto return 0;
498b761bf27SKuninori Morimoto }
499b761bf27SKuninori Morimoto
__rsnd_src_interrupt(struct rsnd_mod * mod,struct rsnd_dai_stream * io)50075916f65SKuninori Morimoto static void __rsnd_src_interrupt(struct rsnd_mod *mod,
50188c61cffSKuninori Morimoto struct rsnd_dai_stream *io)
502cfcefe01SKuninori Morimoto {
50302299d98SKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
5046a25c8daSKuninori Morimoto bool stop = false;
505cfcefe01SKuninori Morimoto
50602299d98SKuninori Morimoto spin_lock(&priv->lock);
50702299d98SKuninori Morimoto
50802299d98SKuninori Morimoto /* ignore all cases if not working */
509d5bbe7deSKuninori Morimoto if (!rsnd_io_is_working(io))
51075916f65SKuninori Morimoto goto rsnd_src_interrupt_out;
511cfcefe01SKuninori Morimoto
5126a25c8daSKuninori Morimoto if (rsnd_src_error_occurred(mod))
5136a25c8daSKuninori Morimoto stop = true;
51488c61cffSKuninori Morimoto
5158cc225f7SKuninori Morimoto rsnd_src_status_clear(mod);
51675916f65SKuninori Morimoto rsnd_src_interrupt_out:
5178cc225f7SKuninori Morimoto
51802299d98SKuninori Morimoto spin_unlock(&priv->lock);
5196a25c8daSKuninori Morimoto
5206a25c8daSKuninori Morimoto if (stop)
5216a25c8daSKuninori Morimoto snd_pcm_stop_xrun(io->substream);
52288c61cffSKuninori Morimoto }
52388c61cffSKuninori Morimoto
rsnd_src_interrupt(int irq,void * data)52475916f65SKuninori Morimoto static irqreturn_t rsnd_src_interrupt(int irq, void *data)
52588c61cffSKuninori Morimoto {
52688c61cffSKuninori Morimoto struct rsnd_mod *mod = data;
52788c61cffSKuninori Morimoto
52875916f65SKuninori Morimoto rsnd_mod_interrupt(mod, __rsnd_src_interrupt);
529cfcefe01SKuninori Morimoto
530cfcefe01SKuninori Morimoto return IRQ_HANDLED;
531cfcefe01SKuninori Morimoto }
532cfcefe01SKuninori Morimoto
rsnd_src_probe_(struct rsnd_mod * mod,struct rsnd_dai_stream * io,struct rsnd_priv * priv)53375916f65SKuninori Morimoto static int rsnd_src_probe_(struct rsnd_mod *mod,
5342c0fac19SKuninori Morimoto struct rsnd_dai_stream *io,
535690602fcSKuninori Morimoto struct rsnd_priv *priv)
536ba9c949fSKuninori Morimoto {
537ba9c949fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod);
538ba9c949fSKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv);
539adf6a681SKuninori Morimoto int irq = src->irq;
540ba9c949fSKuninori Morimoto int ret;
541ba9c949fSKuninori Morimoto
542cfcefe01SKuninori Morimoto if (irq > 0) {
543cfcefe01SKuninori Morimoto /*
544cfcefe01SKuninori Morimoto * IRQ is not supported on non-DT
545cfcefe01SKuninori Morimoto * see
546b5b442abSKuninori Morimoto * rsnd_src_irq()
547cfcefe01SKuninori Morimoto */
548cfcefe01SKuninori Morimoto ret = devm_request_irq(dev, irq,
54975916f65SKuninori Morimoto rsnd_src_interrupt,
550cfcefe01SKuninori Morimoto IRQF_SHARED,
551cfcefe01SKuninori Morimoto dev_name(dev), mod);
552cfcefe01SKuninori Morimoto if (ret)
553b543b52aSKuninori Morimoto return ret;
554cfcefe01SKuninori Morimoto }
555cfcefe01SKuninori Morimoto
556b99305d2SKuninori Morimoto ret = rsnd_dma_attach(io, mod, &src->dma);
557cfcefe01SKuninori Morimoto
558cfcefe01SKuninori Morimoto return ret;
559ba9c949fSKuninori Morimoto }
560ba9c949fSKuninori Morimoto
rsnd_src_pcm_new(struct rsnd_mod * mod,struct rsnd_dai_stream * io,struct snd_soc_pcm_runtime * rtd)56175916f65SKuninori Morimoto static int rsnd_src_pcm_new(struct rsnd_mod *mod,
5622c0fac19SKuninori Morimoto struct rsnd_dai_stream *io,
56343cb6954SKuninori Morimoto struct snd_soc_pcm_runtime *rtd)
56443cb6954SKuninori Morimoto {
56543cb6954SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod);
56643cb6954SKuninori Morimoto int ret;
56743cb6954SKuninori Morimoto
56843cb6954SKuninori Morimoto /*
56943cb6954SKuninori Morimoto * enable SRC sync convert if possible
57043cb6954SKuninori Morimoto */
57143cb6954SKuninori Morimoto
57243cb6954SKuninori Morimoto /*
57361a219feSKuninori Morimoto * It can't use SRC Synchronous convert
57461a219feSKuninori Morimoto * when Capture if it uses CMD
5757115cb91SKuninori Morimoto */
57661a219feSKuninori Morimoto if (rsnd_io_to_mod_cmd(io) && !rsnd_io_is_play(io))
5777115cb91SKuninori Morimoto return 0;
5787115cb91SKuninori Morimoto
5797115cb91SKuninori Morimoto /*
58043cb6954SKuninori Morimoto * enable sync convert
58143cb6954SKuninori Morimoto */
582b65a7cccSKuninori Morimoto ret = rsnd_kctrl_new_s(mod, io, rtd,
58343cb6954SKuninori Morimoto rsnd_io_is_play(io) ?
58443cb6954SKuninori Morimoto "SRC Out Rate Switch" :
58543cb6954SKuninori Morimoto "SRC In Rate Switch",
586f0b04d8bSKuninori Morimoto rsnd_kctrl_accept_anytime,
58775916f65SKuninori Morimoto rsnd_src_set_convert_rate,
58843cb6954SKuninori Morimoto &src->sen, 1);
58943cb6954SKuninori Morimoto if (ret < 0)
59043cb6954SKuninori Morimoto return ret;
59143cb6954SKuninori Morimoto
592b65a7cccSKuninori Morimoto ret = rsnd_kctrl_new_s(mod, io, rtd,
59343cb6954SKuninori Morimoto rsnd_io_is_play(io) ?
59443cb6954SKuninori Morimoto "SRC Out Rate" :
59543cb6954SKuninori Morimoto "SRC In Rate",
596f0b04d8bSKuninori Morimoto rsnd_kctrl_accept_runtime,
59775916f65SKuninori Morimoto rsnd_src_set_convert_rate,
59843cb6954SKuninori Morimoto &src->sync, 192000);
59943cb6954SKuninori Morimoto
60043cb6954SKuninori Morimoto return ret;
60143cb6954SKuninori Morimoto }
60243cb6954SKuninori Morimoto
6031f9c82b5SKuninori Morimoto #ifdef CONFIG_DEBUG_FS
rsnd_src_debug_info(struct seq_file * m,struct rsnd_dai_stream * io,struct rsnd_mod * mod)6041f9c82b5SKuninori Morimoto static void rsnd_src_debug_info(struct seq_file *m,
6051f9c82b5SKuninori Morimoto struct rsnd_dai_stream *io,
6061f9c82b5SKuninori Morimoto struct rsnd_mod *mod)
6071f9c82b5SKuninori Morimoto {
6081f9c82b5SKuninori Morimoto rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
6091f9c82b5SKuninori Morimoto rsnd_mod_id(mod) * 0x20, 0x20);
6101f9c82b5SKuninori Morimoto seq_puts(m, "\n");
6111f9c82b5SKuninori Morimoto rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
6121f9c82b5SKuninori Morimoto 0x1c0, 0x20);
6131f9c82b5SKuninori Morimoto seq_puts(m, "\n");
6141f9c82b5SKuninori Morimoto rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
6151f9c82b5SKuninori Morimoto 0x200 + rsnd_mod_id(mod) * 0x40, 0x40);
6161f9c82b5SKuninori Morimoto }
6171f9c82b5SKuninori Morimoto #define DEBUG_INFO .debug_info = rsnd_src_debug_info
6181f9c82b5SKuninori Morimoto #else
6191f9c82b5SKuninori Morimoto #define DEBUG_INFO
6201f9c82b5SKuninori Morimoto #endif
6211f9c82b5SKuninori Morimoto
62275916f65SKuninori Morimoto static struct rsnd_mod_ops rsnd_src_ops = {
6238aefda50SKuninori Morimoto .name = SRC_NAME,
62472adc61fSKuninori Morimoto .dma_req = rsnd_src_dma_req,
62575916f65SKuninori Morimoto .probe = rsnd_src_probe_,
62675916f65SKuninori Morimoto .init = rsnd_src_init,
62775916f65SKuninori Morimoto .quit = rsnd_src_quit,
62875916f65SKuninori Morimoto .start = rsnd_src_start,
62975916f65SKuninori Morimoto .stop = rsnd_src_stop,
630b5b442abSKuninori Morimoto .irq = rsnd_src_irq,
63175916f65SKuninori Morimoto .pcm_new = rsnd_src_pcm_new,
6327e7fe06dSKuninori Morimoto .get_status = rsnd_mod_get_status,
6331f9c82b5SKuninori Morimoto DEBUG_INFO
634ba9c949fSKuninori Morimoto };
635ba9c949fSKuninori Morimoto
rsnd_src_mod_get(struct rsnd_priv * priv,int id)636ba9c949fSKuninori Morimoto struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id)
637ba9c949fSKuninori Morimoto {
638ba9c949fSKuninori Morimoto if (WARN_ON(id < 0 || id >= rsnd_src_nr(priv)))
639ba9c949fSKuninori Morimoto id = 0;
640ba9c949fSKuninori Morimoto
641adf6a681SKuninori Morimoto return rsnd_mod_get(rsnd_src_get(priv, id));
64290e8e50fSKuninori Morimoto }
64390e8e50fSKuninori Morimoto
rsnd_src_probe(struct rsnd_priv * priv)6442ea6b074SKuninori Morimoto int rsnd_src_probe(struct rsnd_priv *priv)
645ba9c949fSKuninori Morimoto {
646adf6a681SKuninori Morimoto struct device_node *node;
647adf6a681SKuninori Morimoto struct device_node *np;
648ba9c949fSKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv);
649ba9c949fSKuninori Morimoto struct rsnd_src *src;
650ba9c949fSKuninori Morimoto struct clk *clk;
651ba9c949fSKuninori Morimoto char name[RSND_SRC_NAME_SIZE];
6522f78dd7fSKuninori Morimoto int i, nr, ret;
653ba9c949fSKuninori Morimoto
654e8e7b7bdSKuninori Morimoto /* This driver doesn't support Gen1 at this point */
655e8e7b7bdSKuninori Morimoto if (rsnd_is_gen1(priv))
656e8e7b7bdSKuninori Morimoto return 0;
657033e7ed8SKuninori Morimoto
658adf6a681SKuninori Morimoto node = rsnd_src_of_node(priv);
659adf6a681SKuninori Morimoto if (!node)
660adf6a681SKuninori Morimoto return 0; /* not used is not error */
66190e8e50fSKuninori Morimoto
662c413983eSKuninori Morimoto nr = rsnd_node_count(priv, node, SRC_NAME);
663adf6a681SKuninori Morimoto if (!nr) {
664adf6a681SKuninori Morimoto ret = -EINVAL;
665adf6a681SKuninori Morimoto goto rsnd_src_probe_done;
666adf6a681SKuninori Morimoto }
667ba9c949fSKuninori Morimoto
668a86854d0SKees Cook src = devm_kcalloc(dev, nr, sizeof(*src), GFP_KERNEL);
669adf6a681SKuninori Morimoto if (!src) {
670adf6a681SKuninori Morimoto ret = -ENOMEM;
671adf6a681SKuninori Morimoto goto rsnd_src_probe_done;
672adf6a681SKuninori Morimoto }
673ba9c949fSKuninori Morimoto
674ba9c949fSKuninori Morimoto priv->src_nr = nr;
675ba9c949fSKuninori Morimoto priv->src = src;
676ba9c949fSKuninori Morimoto
677adf6a681SKuninori Morimoto i = 0;
678adf6a681SKuninori Morimoto for_each_child_of_node(node, np) {
679de196515SSergei Shtylyov if (!of_device_is_available(np))
680de196515SSergei Shtylyov goto skip;
681de196515SSergei Shtylyov
682d09a7db4SKuninori Morimoto i = rsnd_node_fixed_index(dev, np, SRC_NAME, i);
683d09a7db4SKuninori Morimoto if (i < 0) {
684d09a7db4SKuninori Morimoto ret = -EINVAL;
685d09a7db4SKuninori Morimoto of_node_put(np);
686d09a7db4SKuninori Morimoto goto rsnd_src_probe_done;
687d09a7db4SKuninori Morimoto }
688c413983eSKuninori Morimoto
689adf6a681SKuninori Morimoto src = rsnd_src_get(priv, i);
690adf6a681SKuninori Morimoto
6918aefda50SKuninori Morimoto snprintf(name, RSND_SRC_NAME_SIZE, "%s.%d",
6928aefda50SKuninori Morimoto SRC_NAME, i);
693ba9c949fSKuninori Morimoto
694adf6a681SKuninori Morimoto src->irq = irq_of_parse_and_map(np, 0);
695adf6a681SKuninori Morimoto if (!src->irq) {
696adf6a681SKuninori Morimoto ret = -EINVAL;
69753ba2aa3SJulia Lawall of_node_put(np);
698adf6a681SKuninori Morimoto goto rsnd_src_probe_done;
699adf6a681SKuninori Morimoto }
700ba9c949fSKuninori Morimoto
701adf6a681SKuninori Morimoto clk = devm_clk_get(dev, name);
702adf6a681SKuninori Morimoto if (IS_ERR(clk)) {
703adf6a681SKuninori Morimoto ret = PTR_ERR(clk);
70453ba2aa3SJulia Lawall of_node_put(np);
705adf6a681SKuninori Morimoto goto rsnd_src_probe_done;
706adf6a681SKuninori Morimoto }
707ba9c949fSKuninori Morimoto
708e8e7b7bdSKuninori Morimoto ret = rsnd_mod_init(priv, rsnd_mod_get(src),
7097e7fe06dSKuninori Morimoto &rsnd_src_ops, clk, RSND_MOD_SRC, i);
71053ba2aa3SJulia Lawall if (ret) {
71153ba2aa3SJulia Lawall of_node_put(np);
712adf6a681SKuninori Morimoto goto rsnd_src_probe_done;
71353ba2aa3SJulia Lawall }
714adf6a681SKuninori Morimoto
715de196515SSergei Shtylyov skip:
716adf6a681SKuninori Morimoto i++;
717ba9c949fSKuninori Morimoto }
718ba9c949fSKuninori Morimoto
719adf6a681SKuninori Morimoto ret = 0;
720adf6a681SKuninori Morimoto
721adf6a681SKuninori Morimoto rsnd_src_probe_done:
722adf6a681SKuninori Morimoto of_node_put(node);
723adf6a681SKuninori Morimoto
724adf6a681SKuninori Morimoto return ret;
725ba9c949fSKuninori Morimoto }
7262f78dd7fSKuninori Morimoto
rsnd_src_remove(struct rsnd_priv * priv)7272ea6b074SKuninori Morimoto void rsnd_src_remove(struct rsnd_priv *priv)
7282f78dd7fSKuninori Morimoto {
7292f78dd7fSKuninori Morimoto struct rsnd_src *src;
7302f78dd7fSKuninori Morimoto int i;
7312f78dd7fSKuninori Morimoto
7322f78dd7fSKuninori Morimoto for_each_rsnd_src(src, priv, i) {
733b76e218aSKuninori Morimoto rsnd_mod_quit(rsnd_mod_get(src));
7342f78dd7fSKuninori Morimoto }
7352f78dd7fSKuninori Morimoto }
736