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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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