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 /* 92b627869SKuninori Morimoto * you can enable below define if you don't need 102b627869SKuninori Morimoto * SSI interrupt status debug message when debugging 112b627869SKuninori Morimoto * see rsnd_dbg_irq_status() 122b627869SKuninori Morimoto * 132b627869SKuninori Morimoto * #define RSND_DEBUG_NO_IRQ_STATUS 1 142b627869SKuninori Morimoto */ 152b627869SKuninori Morimoto 16ba9c949fSKuninori Morimoto #include "rsnd.h" 17ba9c949fSKuninori Morimoto 188aefda50SKuninori Morimoto #define SRC_NAME "src" 198aefda50SKuninori Morimoto 20cfcefe01SKuninori Morimoto /* SCU_SYSTEM_STATUS0/1 */ 21cfcefe01SKuninori Morimoto #define OUF_SRC(id) ((1 << (id + 16)) | (1 << id)) 22cfcefe01SKuninori Morimoto 23ba9c949fSKuninori Morimoto struct rsnd_src { 24ba9c949fSKuninori Morimoto struct rsnd_mod mod; 25940e9479SKuninori Morimoto struct rsnd_mod *dma; 2643cb6954SKuninori Morimoto struct rsnd_kctrl_cfg_s sen; /* sync convert enable */ 2743cb6954SKuninori Morimoto struct rsnd_kctrl_cfg_s sync; /* sync convert */ 28adf6a681SKuninori Morimoto int irq; 29ba9c949fSKuninori Morimoto }; 30ba9c949fSKuninori Morimoto 31ba9c949fSKuninori Morimoto #define RSND_SRC_NAME_SIZE 16 32ba9c949fSKuninori Morimoto 33adf6a681SKuninori Morimoto #define rsnd_src_get(priv, id) ((struct rsnd_src *)(priv->src) + id) 34da599fd3SKuninori Morimoto #define rsnd_src_nr(priv) ((priv)->src_nr) 35ab2049f9SKuninori Morimoto #define rsnd_src_sync_is_enabled(mod) (rsnd_mod_to_src(mod)->sen.val) 3682e76ed3SKuninori Morimoto 37ba9c949fSKuninori Morimoto #define rsnd_mod_to_src(_mod) \ 38ba9c949fSKuninori Morimoto container_of((_mod), struct rsnd_src, mod) 39ba9c949fSKuninori Morimoto 40ba9c949fSKuninori Morimoto #define for_each_rsnd_src(pos, priv, i) \ 41ba9c949fSKuninori Morimoto for ((i) = 0; \ 42ba9c949fSKuninori Morimoto ((i) < rsnd_src_nr(priv)) && \ 43ba9c949fSKuninori Morimoto ((pos) = (struct rsnd_src *)(priv)->src + i); \ 44ba9c949fSKuninori Morimoto i++) 45ba9c949fSKuninori Morimoto 46ba9c949fSKuninori Morimoto 47ba9c949fSKuninori Morimoto /* 48ba9c949fSKuninori Morimoto * image of SRC (Sampling Rate Converter) 49ba9c949fSKuninori Morimoto * 50ba9c949fSKuninori Morimoto * 96kHz <-> +-----+ 48kHz +-----+ 48kHz +-------+ 51ba9c949fSKuninori Morimoto * 48kHz <-> | SRC | <------> | SSI | <-----> | codec | 52ba9c949fSKuninori Morimoto * 44.1kHz <-> +-----+ +-----+ +-------+ 53ba9c949fSKuninori Morimoto * ... 54ba9c949fSKuninori Morimoto * 55ba9c949fSKuninori Morimoto */ 56ba9c949fSKuninori Morimoto 5798efeeaeSKuninori Morimoto static void rsnd_src_activation(struct rsnd_mod *mod) 58379febfdSKuninori Morimoto { 59379febfdSKuninori Morimoto rsnd_mod_write(mod, SRC_SWRSR, 0); 60379febfdSKuninori Morimoto rsnd_mod_write(mod, SRC_SWRSR, 1); 61379febfdSKuninori Morimoto } 62379febfdSKuninori Morimoto 63475a361aSKuninori Morimoto static void rsnd_src_halt(struct rsnd_mod *mod) 64475a361aSKuninori Morimoto { 65475a361aSKuninori Morimoto rsnd_mod_write(mod, SRC_SRCIR, 1); 66475a361aSKuninori Morimoto rsnd_mod_write(mod, SRC_SWRSR, 0); 67475a361aSKuninori Morimoto } 68475a361aSKuninori Morimoto 699b99e9a7SKuninori Morimoto static struct dma_chan *rsnd_src_dma_req(struct rsnd_dai_stream *io, 709b99e9a7SKuninori Morimoto struct rsnd_mod *mod) 7172adc61fSKuninori Morimoto { 7272adc61fSKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 7372adc61fSKuninori Morimoto int is_play = rsnd_io_is_play(io); 7472adc61fSKuninori Morimoto 7572adc61fSKuninori Morimoto return rsnd_dma_request_channel(rsnd_src_of_node(priv), 7672adc61fSKuninori Morimoto mod, 7772adc61fSKuninori Morimoto is_play ? "rx" : "tx"); 7872adc61fSKuninori Morimoto } 7972adc61fSKuninori Morimoto 8088c61cffSKuninori Morimoto static u32 rsnd_src_convert_rate(struct rsnd_dai_stream *io, 811a9be9eeSKuninori Morimoto struct rsnd_mod *mod) 8243cb6954SKuninori Morimoto { 8343cb6954SKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 841a9be9eeSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 8543cb6954SKuninori Morimoto u32 convert_rate; 8643cb6954SKuninori Morimoto 8743cb6954SKuninori Morimoto if (!runtime) 8843cb6954SKuninori Morimoto return 0; 8943cb6954SKuninori Morimoto 90ab2049f9SKuninori Morimoto if (!rsnd_src_sync_is_enabled(mod)) 91c2aaaa57SKuninori Morimoto return rsnd_io_converted_rate(io); 9243cb6954SKuninori Morimoto 9343cb6954SKuninori Morimoto convert_rate = src->sync.val; 9443cb6954SKuninori Morimoto 9543cb6954SKuninori Morimoto if (!convert_rate) 96c2aaaa57SKuninori Morimoto convert_rate = rsnd_io_converted_rate(io); 9743cb6954SKuninori Morimoto 9843cb6954SKuninori Morimoto if (!convert_rate) 9943cb6954SKuninori Morimoto convert_rate = runtime->rate; 10043cb6954SKuninori Morimoto 10143cb6954SKuninori Morimoto return convert_rate; 10243cb6954SKuninori Morimoto } 10343cb6954SKuninori Morimoto 104cbf1494fSKuninori Morimoto unsigned int rsnd_src_get_rate(struct rsnd_priv *priv, 105ba9c949fSKuninori Morimoto struct rsnd_dai_stream *io, 106cbf1494fSKuninori Morimoto int is_in) 107ba9c949fSKuninori Morimoto { 108b1eac430SKuninori Morimoto struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); 109cbf1494fSKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 110b1eac430SKuninori Morimoto unsigned int rate = 0; 111cbf1494fSKuninori Morimoto int is_play = rsnd_io_is_play(io); 112cbf1494fSKuninori Morimoto 113cbf1494fSKuninori Morimoto /* 114cbf1494fSKuninori Morimoto * Playback 115cbf1494fSKuninori Morimoto * runtime_rate -> [SRC] -> convert_rate 116cbf1494fSKuninori Morimoto * 117cbf1494fSKuninori Morimoto * Capture 118cbf1494fSKuninori Morimoto * convert_rate -> [SRC] -> runtime_rate 119cbf1494fSKuninori Morimoto */ 120cbf1494fSKuninori Morimoto 121cbf1494fSKuninori Morimoto if (is_play == is_in) 122cbf1494fSKuninori Morimoto return runtime->rate; 123ba9c949fSKuninori Morimoto 124ba9c949fSKuninori Morimoto /* 125ba9c949fSKuninori Morimoto * return convert rate if SRC is used, 126ba9c949fSKuninori Morimoto * otherwise, return runtime->rate as usual 127ba9c949fSKuninori Morimoto */ 1281a9be9eeSKuninori Morimoto if (src_mod) 1291a9be9eeSKuninori Morimoto rate = rsnd_src_convert_rate(io, src_mod); 130b1eac430SKuninori Morimoto 131ba9c949fSKuninori Morimoto if (!rate) 132ba9c949fSKuninori Morimoto rate = runtime->rate; 133ba9c949fSKuninori Morimoto 134ba9c949fSKuninori Morimoto return rate; 135ba9c949fSKuninori Morimoto } 136ba9c949fSKuninori Morimoto 1377674bec4SKuninori Morimoto const static u32 bsdsr_table_pattern1[] = { 1387674bec4SKuninori Morimoto 0x01800000, /* 6 - 1/6 */ 1397674bec4SKuninori Morimoto 0x01000000, /* 6 - 1/4 */ 1407674bec4SKuninori Morimoto 0x00c00000, /* 6 - 1/3 */ 1417674bec4SKuninori Morimoto 0x00800000, /* 6 - 1/2 */ 1427674bec4SKuninori Morimoto 0x00600000, /* 6 - 2/3 */ 1437674bec4SKuninori Morimoto 0x00400000, /* 6 - 1 */ 1447674bec4SKuninori Morimoto }; 1457674bec4SKuninori Morimoto 1467674bec4SKuninori Morimoto const static u32 bsdsr_table_pattern2[] = { 1477674bec4SKuninori Morimoto 0x02400000, /* 6 - 1/6 */ 1487674bec4SKuninori Morimoto 0x01800000, /* 6 - 1/4 */ 1497674bec4SKuninori Morimoto 0x01200000, /* 6 - 1/3 */ 1507674bec4SKuninori Morimoto 0x00c00000, /* 6 - 1/2 */ 1517674bec4SKuninori Morimoto 0x00900000, /* 6 - 2/3 */ 1527674bec4SKuninori Morimoto 0x00600000, /* 6 - 1 */ 1537674bec4SKuninori Morimoto }; 1547674bec4SKuninori Morimoto 1557674bec4SKuninori Morimoto const static u32 bsisr_table[] = { 1567674bec4SKuninori Morimoto 0x00100060, /* 6 - 1/6 */ 1577674bec4SKuninori Morimoto 0x00100040, /* 6 - 1/4 */ 1587674bec4SKuninori Morimoto 0x00100030, /* 6 - 1/3 */ 1597674bec4SKuninori Morimoto 0x00100020, /* 6 - 1/2 */ 1607674bec4SKuninori Morimoto 0x00100020, /* 6 - 2/3 */ 1617674bec4SKuninori Morimoto 0x00100020, /* 6 - 1 */ 1627674bec4SKuninori Morimoto }; 1637674bec4SKuninori Morimoto 1647674bec4SKuninori Morimoto const static u32 chan288888[] = { 1657674bec4SKuninori Morimoto 0x00000006, /* 1 to 2 */ 1667674bec4SKuninori Morimoto 0x000001fe, /* 1 to 8 */ 1677674bec4SKuninori Morimoto 0x000001fe, /* 1 to 8 */ 1687674bec4SKuninori Morimoto 0x000001fe, /* 1 to 8 */ 1697674bec4SKuninori Morimoto 0x000001fe, /* 1 to 8 */ 1707674bec4SKuninori Morimoto 0x000001fe, /* 1 to 8 */ 1717674bec4SKuninori Morimoto }; 1727674bec4SKuninori Morimoto 1737674bec4SKuninori Morimoto const static u32 chan244888[] = { 1747674bec4SKuninori Morimoto 0x00000006, /* 1 to 2 */ 1757674bec4SKuninori Morimoto 0x0000001e, /* 1 to 4 */ 1767674bec4SKuninori Morimoto 0x0000001e, /* 1 to 4 */ 1777674bec4SKuninori Morimoto 0x000001fe, /* 1 to 8 */ 1787674bec4SKuninori Morimoto 0x000001fe, /* 1 to 8 */ 1797674bec4SKuninori Morimoto 0x000001fe, /* 1 to 8 */ 1807674bec4SKuninori Morimoto }; 1817674bec4SKuninori Morimoto 1827674bec4SKuninori Morimoto const static u32 chan222222[] = { 1837674bec4SKuninori Morimoto 0x00000006, /* 1 to 2 */ 1847674bec4SKuninori Morimoto 0x00000006, /* 1 to 2 */ 1857674bec4SKuninori Morimoto 0x00000006, /* 1 to 2 */ 1867674bec4SKuninori Morimoto 0x00000006, /* 1 to 2 */ 1877674bec4SKuninori Morimoto 0x00000006, /* 1 to 2 */ 1887674bec4SKuninori Morimoto 0x00000006, /* 1 to 2 */ 1897674bec4SKuninori Morimoto }; 1907674bec4SKuninori Morimoto 19175916f65SKuninori Morimoto static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io, 19275916f65SKuninori Morimoto struct rsnd_mod *mod) 193ba9c949fSKuninori Morimoto { 19475916f65SKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 195cfcefe01SKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 19675916f65SKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 19790431eb4SKuninori Morimoto int is_play = rsnd_io_is_play(io); 19867923f77SKuninori Morimoto int use_src = 0; 1990102eed5SKuninori Morimoto u32 fin, fout; 20075916f65SKuninori Morimoto u32 ifscr, fsrate, adinr; 20175916f65SKuninori Morimoto u32 cr, route; 20290431eb4SKuninori Morimoto u32 i_busif, o_busif, tmp; 2037674bec4SKuninori Morimoto const u32 *bsdsr_table; 2047674bec4SKuninori Morimoto const u32 *chptn; 20575916f65SKuninori Morimoto uint ratio; 2067674bec4SKuninori Morimoto int chan; 2077674bec4SKuninori Morimoto int idx; 208ba9c949fSKuninori Morimoto 20975916f65SKuninori Morimoto if (!runtime) 21075916f65SKuninori Morimoto return; 211ba9c949fSKuninori Morimoto 2120102eed5SKuninori Morimoto fin = rsnd_src_get_in_rate(priv, io); 2130102eed5SKuninori Morimoto fout = rsnd_src_get_out_rate(priv, io); 2140102eed5SKuninori Morimoto 2157674bec4SKuninori Morimoto chan = rsnd_runtime_channel_original(io); 2167674bec4SKuninori Morimoto 21775916f65SKuninori Morimoto /* 6 - 1/6 are very enough ratio for SRC_BSDSR */ 2180102eed5SKuninori Morimoto if (fin == fout) 21975916f65SKuninori Morimoto ratio = 0; 2200102eed5SKuninori Morimoto else if (fin > fout) 2210102eed5SKuninori Morimoto ratio = 100 * fin / fout; 22275916f65SKuninori Morimoto else 2230102eed5SKuninori Morimoto ratio = 100 * fout / fin; 224cfcefe01SKuninori Morimoto 22575916f65SKuninori Morimoto if (ratio > 600) { 22675916f65SKuninori Morimoto dev_err(dev, "FSO/FSI ratio error\n"); 22775916f65SKuninori Morimoto return; 228ba9c949fSKuninori Morimoto } 229ba9c949fSKuninori Morimoto 23067923f77SKuninori Morimoto use_src = (fin != fout) | rsnd_src_sync_is_enabled(mod); 23167923f77SKuninori Morimoto 232ba9c949fSKuninori Morimoto /* 23375916f65SKuninori Morimoto * SRC_ADINR 234ba9c949fSKuninori Morimoto */ 2357674bec4SKuninori Morimoto adinr = rsnd_get_adinr_bit(mod, io) | chan; 23675916f65SKuninori Morimoto 23775916f65SKuninori Morimoto /* 23875916f65SKuninori Morimoto * SRC_IFSCR / SRC_IFSVR 23975916f65SKuninori Morimoto */ 24075916f65SKuninori Morimoto ifscr = 0; 24175916f65SKuninori Morimoto fsrate = 0; 24267923f77SKuninori Morimoto if (use_src) { 24393ca33c9SHiroyuki Yokoyama u64 n; 24493ca33c9SHiroyuki Yokoyama 24575916f65SKuninori Morimoto ifscr = 1; 24693ca33c9SHiroyuki Yokoyama n = (u64)0x0400000 * fin; 24793ca33c9SHiroyuki Yokoyama do_div(n, fout); 24893ca33c9SHiroyuki Yokoyama fsrate = n; 24975916f65SKuninori Morimoto } 25075916f65SKuninori Morimoto 25175916f65SKuninori Morimoto /* 25275916f65SKuninori Morimoto * SRC_SRCCR / SRC_ROUTE_MODE0 25375916f65SKuninori Morimoto */ 25475916f65SKuninori Morimoto cr = 0x00011110; 25575916f65SKuninori Morimoto route = 0x0; 25667923f77SKuninori Morimoto if (use_src) { 25775916f65SKuninori Morimoto route = 0x1; 25875916f65SKuninori Morimoto 259ab2049f9SKuninori Morimoto if (rsnd_src_sync_is_enabled(mod)) { 26075916f65SKuninori Morimoto cr |= 0x1; 26175916f65SKuninori Morimoto route |= rsnd_io_is_play(io) ? 26275916f65SKuninori Morimoto (0x1 << 24) : (0x1 << 25); 26375916f65SKuninori Morimoto } 26475916f65SKuninori Morimoto } 26575916f65SKuninori Morimoto 26675916f65SKuninori Morimoto /* 26775916f65SKuninori Morimoto * SRC_BSDSR / SRC_BSISR 2687674bec4SKuninori Morimoto * 2697674bec4SKuninori Morimoto * see 2707674bec4SKuninori Morimoto * Combination of Register Setting Related to 2717674bec4SKuninori Morimoto * FSO/FSI Ratio and Channel, Latency 27275916f65SKuninori Morimoto */ 27375916f65SKuninori Morimoto switch (rsnd_mod_id(mod)) { 2747674bec4SKuninori Morimoto case 0: 2757674bec4SKuninori Morimoto chptn = chan288888; 2767674bec4SKuninori Morimoto bsdsr_table = bsdsr_table_pattern1; 2777674bec4SKuninori Morimoto break; 2787674bec4SKuninori Morimoto case 1: 2797674bec4SKuninori Morimoto case 3: 2807674bec4SKuninori Morimoto case 4: 2817674bec4SKuninori Morimoto chptn = chan244888; 2827674bec4SKuninori Morimoto bsdsr_table = bsdsr_table_pattern1; 2837674bec4SKuninori Morimoto break; 2847674bec4SKuninori Morimoto case 2: 2857674bec4SKuninori Morimoto case 9: 2867674bec4SKuninori Morimoto chptn = chan222222; 2877674bec4SKuninori Morimoto bsdsr_table = bsdsr_table_pattern1; 2887674bec4SKuninori Morimoto break; 28975916f65SKuninori Morimoto case 5: 29075916f65SKuninori Morimoto case 6: 29175916f65SKuninori Morimoto case 7: 29275916f65SKuninori Morimoto case 8: 2937674bec4SKuninori Morimoto chptn = chan222222; 2947674bec4SKuninori Morimoto bsdsr_table = bsdsr_table_pattern2; 29575916f65SKuninori Morimoto break; 29675916f65SKuninori Morimoto default: 2977674bec4SKuninori Morimoto goto convert_rate_err; 29875916f65SKuninori Morimoto } 29975916f65SKuninori Morimoto 3007674bec4SKuninori Morimoto /* 3017674bec4SKuninori Morimoto * E3 need to overwrite 3027674bec4SKuninori Morimoto */ 303*ba164a49SJiada Wang if (rsnd_is_e3(priv)) 3047674bec4SKuninori Morimoto switch (rsnd_mod_id(mod)) { 3057674bec4SKuninori Morimoto case 0: 3067674bec4SKuninori Morimoto case 4: 3077674bec4SKuninori Morimoto chptn = chan222222; 3087674bec4SKuninori Morimoto } 3097674bec4SKuninori Morimoto 3107674bec4SKuninori Morimoto for (idx = 0; idx < ARRAY_SIZE(chan222222); idx++) 3117674bec4SKuninori Morimoto if (chptn[idx] & (1 << chan)) 3127674bec4SKuninori Morimoto break; 3137674bec4SKuninori Morimoto 3147674bec4SKuninori Morimoto if (chan > 8 || 3157674bec4SKuninori Morimoto idx >= ARRAY_SIZE(chan222222)) 3167674bec4SKuninori Morimoto goto convert_rate_err; 3177674bec4SKuninori Morimoto 31890431eb4SKuninori Morimoto /* BUSIF_MODE */ 31990431eb4SKuninori Morimoto tmp = rsnd_get_busif_shift(io, mod); 32090431eb4SKuninori Morimoto i_busif = ( is_play ? tmp : 0) | 1; 32190431eb4SKuninori Morimoto o_busif = (!is_play ? tmp : 0) | 1; 32290431eb4SKuninori Morimoto 3230fbab951SKuninori Morimoto rsnd_mod_write(mod, SRC_ROUTE_MODE0, route); 3240fbab951SKuninori Morimoto 32575916f65SKuninori Morimoto rsnd_mod_write(mod, SRC_SRCIR, 1); /* initialize */ 32675916f65SKuninori Morimoto rsnd_mod_write(mod, SRC_ADINR, adinr); 32775916f65SKuninori Morimoto rsnd_mod_write(mod, SRC_IFSCR, ifscr); 32875916f65SKuninori Morimoto rsnd_mod_write(mod, SRC_IFSVR, fsrate); 32975916f65SKuninori Morimoto rsnd_mod_write(mod, SRC_SRCCR, cr); 3307674bec4SKuninori Morimoto rsnd_mod_write(mod, SRC_BSDSR, bsdsr_table[idx]); 3317674bec4SKuninori Morimoto rsnd_mod_write(mod, SRC_BSISR, bsisr_table[idx]); 33275916f65SKuninori Morimoto rsnd_mod_write(mod, SRC_SRCIR, 0); /* cancel initialize */ 33375916f65SKuninori Morimoto 33490431eb4SKuninori Morimoto rsnd_mod_write(mod, SRC_I_BUSIF_MODE, i_busif); 33590431eb4SKuninori Morimoto rsnd_mod_write(mod, SRC_O_BUSIF_MODE, o_busif); 33690431eb4SKuninori Morimoto 33775916f65SKuninori Morimoto rsnd_mod_write(mod, SRC_BUSIF_DALIGN, rsnd_get_dalign(mod, io)); 33875916f65SKuninori Morimoto 3390102eed5SKuninori Morimoto rsnd_adg_set_src_timesel_gen2(mod, io, fin, fout); 3407674bec4SKuninori Morimoto 3417674bec4SKuninori Morimoto return; 3427674bec4SKuninori Morimoto 3437674bec4SKuninori Morimoto convert_rate_err: 3447674bec4SKuninori Morimoto dev_err(dev, "unknown BSDSR/BSDIR settings\n"); 34575916f65SKuninori Morimoto } 34675916f65SKuninori Morimoto 347b5b442abSKuninori Morimoto static int rsnd_src_irq(struct rsnd_mod *mod, 348b5b442abSKuninori Morimoto struct rsnd_dai_stream *io, 349b5b442abSKuninori Morimoto struct rsnd_priv *priv, 350b5b442abSKuninori Morimoto int enable) 351cfcefe01SKuninori Morimoto { 352cfcefe01SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 353cfcefe01SKuninori Morimoto u32 sys_int_val, int_val, sys_int_mask; 354adf6a681SKuninori Morimoto int irq = src->irq; 355cfcefe01SKuninori Morimoto int id = rsnd_mod_id(mod); 356cfcefe01SKuninori Morimoto 357cfcefe01SKuninori Morimoto sys_int_val = 358cfcefe01SKuninori Morimoto sys_int_mask = OUF_SRC(id); 359cfcefe01SKuninori Morimoto int_val = 0x3300; 360cfcefe01SKuninori Morimoto 361cfcefe01SKuninori Morimoto /* 362cfcefe01SKuninori Morimoto * IRQ is not supported on non-DT 363cfcefe01SKuninori Morimoto * see 36475916f65SKuninori Morimoto * rsnd_src_probe_() 365cfcefe01SKuninori Morimoto */ 366cfcefe01SKuninori Morimoto if ((irq <= 0) || !enable) { 367cfcefe01SKuninori Morimoto sys_int_val = 0; 368cfcefe01SKuninori Morimoto int_val = 0; 369cfcefe01SKuninori Morimoto } 370cfcefe01SKuninori Morimoto 3711a1bf58aSKuninori Morimoto /* 3721a1bf58aSKuninori Morimoto * WORKAROUND 3731a1bf58aSKuninori Morimoto * 374ab2049f9SKuninori Morimoto * ignore over flow error when rsnd_src_sync_is_enabled() 3751a1bf58aSKuninori Morimoto */ 376ab2049f9SKuninori Morimoto if (rsnd_src_sync_is_enabled(mod)) 3771a1bf58aSKuninori Morimoto sys_int_val = sys_int_val & 0xffff; 3781a1bf58aSKuninori Morimoto 379cfcefe01SKuninori Morimoto rsnd_mod_write(mod, SRC_INT_ENABLE0, int_val); 380cfcefe01SKuninori Morimoto rsnd_mod_bset(mod, SCU_SYS_INT_EN0, sys_int_mask, sys_int_val); 381cfcefe01SKuninori Morimoto rsnd_mod_bset(mod, SCU_SYS_INT_EN1, sys_int_mask, sys_int_val); 382b5b442abSKuninori Morimoto 383b5b442abSKuninori Morimoto return 0; 384cfcefe01SKuninori Morimoto } 385cfcefe01SKuninori Morimoto 3868cc225f7SKuninori Morimoto static void rsnd_src_status_clear(struct rsnd_mod *mod) 387cfcefe01SKuninori Morimoto { 388cfcefe01SKuninori Morimoto u32 val = OUF_SRC(rsnd_mod_id(mod)); 389cfcefe01SKuninori Morimoto 39042b197e7SKuninori Morimoto rsnd_mod_write(mod, SCU_SYS_STATUS0, val); 39142b197e7SKuninori Morimoto rsnd_mod_write(mod, SCU_SYS_STATUS1, val); 392cfcefe01SKuninori Morimoto } 393cfcefe01SKuninori Morimoto 3946a25c8daSKuninori Morimoto static bool rsnd_src_error_occurred(struct rsnd_mod *mod) 395cfcefe01SKuninori Morimoto { 3962b627869SKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 3972b627869SKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 3981a1bf58aSKuninori Morimoto u32 val0, val1; 3992b627869SKuninori Morimoto u32 status0, status1; 400cfcefe01SKuninori Morimoto bool ret = false; 401cfcefe01SKuninori Morimoto 4021a1bf58aSKuninori Morimoto val0 = val1 = OUF_SRC(rsnd_mod_id(mod)); 4031a1bf58aSKuninori Morimoto 4041a1bf58aSKuninori Morimoto /* 4051a1bf58aSKuninori Morimoto * WORKAROUND 4061a1bf58aSKuninori Morimoto * 407ab2049f9SKuninori Morimoto * ignore over flow error when rsnd_src_sync_is_enabled() 4081a1bf58aSKuninori Morimoto */ 409ab2049f9SKuninori Morimoto if (rsnd_src_sync_is_enabled(mod)) 4101a1bf58aSKuninori Morimoto val0 = val0 & 0xffff; 4111a1bf58aSKuninori Morimoto 4122b627869SKuninori Morimoto status0 = rsnd_mod_read(mod, SCU_SYS_STATUS0); 4132b627869SKuninori Morimoto status1 = rsnd_mod_read(mod, SCU_SYS_STATUS1); 4142b627869SKuninori Morimoto if ((status0 & val0) || (status1 & val1)) { 415c0ea089dSKuninori Morimoto rsnd_dbg_irq_status(dev, "%s err status : 0x%08x, 0x%08x\n", 416c0ea089dSKuninori Morimoto rsnd_mod_name(mod), status0, status1); 4172b627869SKuninori Morimoto 418cfcefe01SKuninori Morimoto ret = true; 4192b627869SKuninori Morimoto } 420cfcefe01SKuninori Morimoto 421cfcefe01SKuninori Morimoto return ret; 422cfcefe01SKuninori Morimoto } 423cfcefe01SKuninori Morimoto 42475916f65SKuninori Morimoto static int rsnd_src_start(struct rsnd_mod *mod, 425497debaaSKuninori Morimoto struct rsnd_dai_stream *io, 426497debaaSKuninori Morimoto struct rsnd_priv *priv) 427cfcefe01SKuninori Morimoto { 4281a1bf58aSKuninori Morimoto u32 val; 4291a1bf58aSKuninori Morimoto 4301a1bf58aSKuninori Morimoto /* 4311a1bf58aSKuninori Morimoto * WORKAROUND 4321a1bf58aSKuninori Morimoto * 4331a1bf58aSKuninori Morimoto * Enable SRC output if you want to use sync convert together with DVC 4341a1bf58aSKuninori Morimoto */ 435ab2049f9SKuninori Morimoto val = (rsnd_io_to_mod_dvc(io) && !rsnd_src_sync_is_enabled(mod)) ? 4361a1bf58aSKuninori Morimoto 0x01 : 0x11; 437cfcefe01SKuninori Morimoto 438cfcefe01SKuninori Morimoto rsnd_mod_write(mod, SRC_CTRL, val); 439cfcefe01SKuninori Morimoto 44075916f65SKuninori Morimoto return 0; 44175916f65SKuninori Morimoto } 442cfcefe01SKuninori Morimoto 44375916f65SKuninori Morimoto static int rsnd_src_stop(struct rsnd_mod *mod, 44475916f65SKuninori Morimoto struct rsnd_dai_stream *io, 44575916f65SKuninori Morimoto struct rsnd_priv *priv) 44675916f65SKuninori Morimoto { 44731739a68SKuninori Morimoto rsnd_mod_write(mod, SRC_CTRL, 0); 448cfcefe01SKuninori Morimoto 449cfcefe01SKuninori Morimoto return 0; 450cfcefe01SKuninori Morimoto } 451cfcefe01SKuninori Morimoto 45275916f65SKuninori Morimoto static int rsnd_src_init(struct rsnd_mod *mod, 453497debaaSKuninori Morimoto struct rsnd_dai_stream *io, 454497debaaSKuninori Morimoto struct rsnd_priv *priv) 455cfcefe01SKuninori Morimoto { 45675916f65SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 457cfcefe01SKuninori Morimoto 458ef30da1cSKuninori Morimoto /* reset sync convert_rate */ 459ef30da1cSKuninori Morimoto src->sync.val = 0; 460ef30da1cSKuninori Morimoto 46175916f65SKuninori Morimoto rsnd_mod_power_on(mod); 462cfcefe01SKuninori Morimoto 46398efeeaeSKuninori Morimoto rsnd_src_activation(mod); 464cfcefe01SKuninori Morimoto 46575916f65SKuninori Morimoto rsnd_src_set_convert_rate(io, mod); 46675916f65SKuninori Morimoto 4678cc225f7SKuninori Morimoto rsnd_src_status_clear(mod); 46875916f65SKuninori Morimoto 46975916f65SKuninori Morimoto return 0; 470cfcefe01SKuninori Morimoto } 471cfcefe01SKuninori Morimoto 47275916f65SKuninori Morimoto static int rsnd_src_quit(struct rsnd_mod *mod, 473b761bf27SKuninori Morimoto struct rsnd_dai_stream *io, 474b761bf27SKuninori Morimoto struct rsnd_priv *priv) 475b761bf27SKuninori Morimoto { 47675916f65SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 47775916f65SKuninori Morimoto 478475a361aSKuninori Morimoto rsnd_src_halt(mod); 479475a361aSKuninori Morimoto 48075916f65SKuninori Morimoto rsnd_mod_power_off(mod); 48175916f65SKuninori Morimoto 48275916f65SKuninori Morimoto /* reset sync convert_rate */ 48375916f65SKuninori Morimoto src->sync.val = 0; 48475916f65SKuninori Morimoto 48575916f65SKuninori Morimoto return 0; 486b761bf27SKuninori Morimoto } 487b761bf27SKuninori Morimoto 48875916f65SKuninori Morimoto static void __rsnd_src_interrupt(struct rsnd_mod *mod, 48988c61cffSKuninori Morimoto struct rsnd_dai_stream *io) 490cfcefe01SKuninori Morimoto { 49102299d98SKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 4926a25c8daSKuninori Morimoto bool stop = false; 493cfcefe01SKuninori Morimoto 49402299d98SKuninori Morimoto spin_lock(&priv->lock); 49502299d98SKuninori Morimoto 49602299d98SKuninori Morimoto /* ignore all cases if not working */ 497d5bbe7deSKuninori Morimoto if (!rsnd_io_is_working(io)) 49875916f65SKuninori Morimoto goto rsnd_src_interrupt_out; 499cfcefe01SKuninori Morimoto 5006a25c8daSKuninori Morimoto if (rsnd_src_error_occurred(mod)) 5016a25c8daSKuninori Morimoto stop = true; 50288c61cffSKuninori Morimoto 5038cc225f7SKuninori Morimoto rsnd_src_status_clear(mod); 50475916f65SKuninori Morimoto rsnd_src_interrupt_out: 5058cc225f7SKuninori Morimoto 50602299d98SKuninori Morimoto spin_unlock(&priv->lock); 5076a25c8daSKuninori Morimoto 5086a25c8daSKuninori Morimoto if (stop) 5096a25c8daSKuninori Morimoto snd_pcm_stop_xrun(io->substream); 51088c61cffSKuninori Morimoto } 51188c61cffSKuninori Morimoto 51275916f65SKuninori Morimoto static irqreturn_t rsnd_src_interrupt(int irq, void *data) 51388c61cffSKuninori Morimoto { 51488c61cffSKuninori Morimoto struct rsnd_mod *mod = data; 51588c61cffSKuninori Morimoto 51675916f65SKuninori Morimoto rsnd_mod_interrupt(mod, __rsnd_src_interrupt); 517cfcefe01SKuninori Morimoto 518cfcefe01SKuninori Morimoto return IRQ_HANDLED; 519cfcefe01SKuninori Morimoto } 520cfcefe01SKuninori Morimoto 52175916f65SKuninori Morimoto static int rsnd_src_probe_(struct rsnd_mod *mod, 5222c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 523690602fcSKuninori Morimoto struct rsnd_priv *priv) 524ba9c949fSKuninori Morimoto { 525ba9c949fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 526ba9c949fSKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 527adf6a681SKuninori Morimoto int irq = src->irq; 528ba9c949fSKuninori Morimoto int ret; 529ba9c949fSKuninori Morimoto 530cfcefe01SKuninori Morimoto if (irq > 0) { 531cfcefe01SKuninori Morimoto /* 532cfcefe01SKuninori Morimoto * IRQ is not supported on non-DT 533cfcefe01SKuninori Morimoto * see 534b5b442abSKuninori Morimoto * rsnd_src_irq() 535cfcefe01SKuninori Morimoto */ 536cfcefe01SKuninori Morimoto ret = devm_request_irq(dev, irq, 53775916f65SKuninori Morimoto rsnd_src_interrupt, 538cfcefe01SKuninori Morimoto IRQF_SHARED, 539cfcefe01SKuninori Morimoto dev_name(dev), mod); 540cfcefe01SKuninori Morimoto if (ret) 541b543b52aSKuninori Morimoto return ret; 542cfcefe01SKuninori Morimoto } 543cfcefe01SKuninori Morimoto 544b99305d2SKuninori Morimoto ret = rsnd_dma_attach(io, mod, &src->dma); 545cfcefe01SKuninori Morimoto 546cfcefe01SKuninori Morimoto return ret; 547ba9c949fSKuninori Morimoto } 548ba9c949fSKuninori Morimoto 54975916f65SKuninori Morimoto static int rsnd_src_pcm_new(struct rsnd_mod *mod, 5502c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 55143cb6954SKuninori Morimoto struct snd_soc_pcm_runtime *rtd) 55243cb6954SKuninori Morimoto { 55343cb6954SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 55443cb6954SKuninori Morimoto int ret; 55543cb6954SKuninori Morimoto 55643cb6954SKuninori Morimoto /* 55743cb6954SKuninori Morimoto * enable SRC sync convert if possible 55843cb6954SKuninori Morimoto */ 55943cb6954SKuninori Morimoto 56043cb6954SKuninori Morimoto /* 56161a219feSKuninori Morimoto * It can't use SRC Synchronous convert 56261a219feSKuninori Morimoto * when Capture if it uses CMD 5637115cb91SKuninori Morimoto */ 56461a219feSKuninori Morimoto if (rsnd_io_to_mod_cmd(io) && !rsnd_io_is_play(io)) 5657115cb91SKuninori Morimoto return 0; 5667115cb91SKuninori Morimoto 5677115cb91SKuninori Morimoto /* 56843cb6954SKuninori Morimoto * enable sync convert 56943cb6954SKuninori Morimoto */ 570b65a7cccSKuninori Morimoto ret = rsnd_kctrl_new_s(mod, io, rtd, 57143cb6954SKuninori Morimoto rsnd_io_is_play(io) ? 57243cb6954SKuninori Morimoto "SRC Out Rate Switch" : 57343cb6954SKuninori Morimoto "SRC In Rate Switch", 574f0b04d8bSKuninori Morimoto rsnd_kctrl_accept_anytime, 57575916f65SKuninori Morimoto rsnd_src_set_convert_rate, 57643cb6954SKuninori Morimoto &src->sen, 1); 57743cb6954SKuninori Morimoto if (ret < 0) 57843cb6954SKuninori Morimoto return ret; 57943cb6954SKuninori Morimoto 580b65a7cccSKuninori Morimoto ret = rsnd_kctrl_new_s(mod, io, rtd, 58143cb6954SKuninori Morimoto rsnd_io_is_play(io) ? 58243cb6954SKuninori Morimoto "SRC Out Rate" : 58343cb6954SKuninori Morimoto "SRC In Rate", 584f0b04d8bSKuninori Morimoto rsnd_kctrl_accept_runtime, 58575916f65SKuninori Morimoto rsnd_src_set_convert_rate, 58643cb6954SKuninori Morimoto &src->sync, 192000); 58743cb6954SKuninori Morimoto 58843cb6954SKuninori Morimoto return ret; 58943cb6954SKuninori Morimoto } 59043cb6954SKuninori Morimoto 59175916f65SKuninori Morimoto static struct rsnd_mod_ops rsnd_src_ops = { 5928aefda50SKuninori Morimoto .name = SRC_NAME, 59372adc61fSKuninori Morimoto .dma_req = rsnd_src_dma_req, 59475916f65SKuninori Morimoto .probe = rsnd_src_probe_, 59575916f65SKuninori Morimoto .init = rsnd_src_init, 59675916f65SKuninori Morimoto .quit = rsnd_src_quit, 59775916f65SKuninori Morimoto .start = rsnd_src_start, 59875916f65SKuninori Morimoto .stop = rsnd_src_stop, 599b5b442abSKuninori Morimoto .irq = rsnd_src_irq, 60075916f65SKuninori Morimoto .pcm_new = rsnd_src_pcm_new, 6017e7fe06dSKuninori Morimoto .get_status = rsnd_mod_get_status, 602ba9c949fSKuninori Morimoto }; 603ba9c949fSKuninori Morimoto 604ba9c949fSKuninori Morimoto struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id) 605ba9c949fSKuninori Morimoto { 606ba9c949fSKuninori Morimoto if (WARN_ON(id < 0 || id >= rsnd_src_nr(priv))) 607ba9c949fSKuninori Morimoto id = 0; 608ba9c949fSKuninori Morimoto 609adf6a681SKuninori Morimoto return rsnd_mod_get(rsnd_src_get(priv, id)); 61090e8e50fSKuninori Morimoto } 61190e8e50fSKuninori Morimoto 6122ea6b074SKuninori Morimoto int rsnd_src_probe(struct rsnd_priv *priv) 613ba9c949fSKuninori Morimoto { 614adf6a681SKuninori Morimoto struct device_node *node; 615adf6a681SKuninori Morimoto struct device_node *np; 616ba9c949fSKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 617ba9c949fSKuninori Morimoto struct rsnd_src *src; 618ba9c949fSKuninori Morimoto struct clk *clk; 619ba9c949fSKuninori Morimoto char name[RSND_SRC_NAME_SIZE]; 6202f78dd7fSKuninori Morimoto int i, nr, ret; 621ba9c949fSKuninori Morimoto 622e8e7b7bdSKuninori Morimoto /* This driver doesn't support Gen1 at this point */ 623e8e7b7bdSKuninori Morimoto if (rsnd_is_gen1(priv)) 624e8e7b7bdSKuninori Morimoto return 0; 625033e7ed8SKuninori Morimoto 626adf6a681SKuninori Morimoto node = rsnd_src_of_node(priv); 627adf6a681SKuninori Morimoto if (!node) 628adf6a681SKuninori Morimoto return 0; /* not used is not error */ 62990e8e50fSKuninori Morimoto 630adf6a681SKuninori Morimoto nr = of_get_child_count(node); 631adf6a681SKuninori Morimoto if (!nr) { 632adf6a681SKuninori Morimoto ret = -EINVAL; 633adf6a681SKuninori Morimoto goto rsnd_src_probe_done; 634adf6a681SKuninori Morimoto } 635ba9c949fSKuninori Morimoto 636a86854d0SKees Cook src = devm_kcalloc(dev, nr, sizeof(*src), GFP_KERNEL); 637adf6a681SKuninori Morimoto if (!src) { 638adf6a681SKuninori Morimoto ret = -ENOMEM; 639adf6a681SKuninori Morimoto goto rsnd_src_probe_done; 640adf6a681SKuninori Morimoto } 641ba9c949fSKuninori Morimoto 642ba9c949fSKuninori Morimoto priv->src_nr = nr; 643ba9c949fSKuninori Morimoto priv->src = src; 644ba9c949fSKuninori Morimoto 645adf6a681SKuninori Morimoto i = 0; 646adf6a681SKuninori Morimoto for_each_child_of_node(node, np) { 647de196515SSergei Shtylyov if (!of_device_is_available(np)) 648de196515SSergei Shtylyov goto skip; 649de196515SSergei Shtylyov 650adf6a681SKuninori Morimoto src = rsnd_src_get(priv, i); 651adf6a681SKuninori Morimoto 6528aefda50SKuninori Morimoto snprintf(name, RSND_SRC_NAME_SIZE, "%s.%d", 6538aefda50SKuninori Morimoto SRC_NAME, i); 654ba9c949fSKuninori Morimoto 655adf6a681SKuninori Morimoto src->irq = irq_of_parse_and_map(np, 0); 656adf6a681SKuninori Morimoto if (!src->irq) { 657adf6a681SKuninori Morimoto ret = -EINVAL; 65853ba2aa3SJulia Lawall of_node_put(np); 659adf6a681SKuninori Morimoto goto rsnd_src_probe_done; 660adf6a681SKuninori Morimoto } 661ba9c949fSKuninori Morimoto 662adf6a681SKuninori Morimoto clk = devm_clk_get(dev, name); 663adf6a681SKuninori Morimoto if (IS_ERR(clk)) { 664adf6a681SKuninori Morimoto ret = PTR_ERR(clk); 66553ba2aa3SJulia Lawall of_node_put(np); 666adf6a681SKuninori Morimoto goto rsnd_src_probe_done; 667adf6a681SKuninori Morimoto } 668ba9c949fSKuninori Morimoto 669e8e7b7bdSKuninori Morimoto ret = rsnd_mod_init(priv, rsnd_mod_get(src), 6707e7fe06dSKuninori Morimoto &rsnd_src_ops, clk, RSND_MOD_SRC, i); 67153ba2aa3SJulia Lawall if (ret) { 67253ba2aa3SJulia Lawall of_node_put(np); 673adf6a681SKuninori Morimoto goto rsnd_src_probe_done; 67453ba2aa3SJulia Lawall } 675adf6a681SKuninori Morimoto 676de196515SSergei Shtylyov skip: 677adf6a681SKuninori Morimoto i++; 678ba9c949fSKuninori Morimoto } 679ba9c949fSKuninori Morimoto 680adf6a681SKuninori Morimoto ret = 0; 681adf6a681SKuninori Morimoto 682adf6a681SKuninori Morimoto rsnd_src_probe_done: 683adf6a681SKuninori Morimoto of_node_put(node); 684adf6a681SKuninori Morimoto 685adf6a681SKuninori Morimoto return ret; 686ba9c949fSKuninori Morimoto } 6872f78dd7fSKuninori Morimoto 6882ea6b074SKuninori Morimoto void rsnd_src_remove(struct rsnd_priv *priv) 6892f78dd7fSKuninori Morimoto { 6902f78dd7fSKuninori Morimoto struct rsnd_src *src; 6912f78dd7fSKuninori Morimoto int i; 6922f78dd7fSKuninori Morimoto 6932f78dd7fSKuninori Morimoto for_each_rsnd_src(src, priv, i) { 694b76e218aSKuninori Morimoto rsnd_mod_quit(rsnd_mod_get(src)); 6952f78dd7fSKuninori Morimoto } 6962f78dd7fSKuninori Morimoto } 697