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" 17*7674bec4SKuninori Morimoto #include <linux/sys_soc.h> 18ba9c949fSKuninori Morimoto 198aefda50SKuninori Morimoto #define SRC_NAME "src" 208aefda50SKuninori Morimoto 21cfcefe01SKuninori Morimoto /* SCU_SYSTEM_STATUS0/1 */ 22cfcefe01SKuninori Morimoto #define OUF_SRC(id) ((1 << (id + 16)) | (1 << id)) 23cfcefe01SKuninori Morimoto 24ba9c949fSKuninori Morimoto struct rsnd_src { 25ba9c949fSKuninori Morimoto struct rsnd_mod mod; 26940e9479SKuninori Morimoto struct rsnd_mod *dma; 2743cb6954SKuninori Morimoto struct rsnd_kctrl_cfg_s sen; /* sync convert enable */ 2843cb6954SKuninori Morimoto struct rsnd_kctrl_cfg_s sync; /* sync convert */ 29adf6a681SKuninori Morimoto int irq; 30ba9c949fSKuninori Morimoto }; 31ba9c949fSKuninori Morimoto 32ba9c949fSKuninori Morimoto #define RSND_SRC_NAME_SIZE 16 33ba9c949fSKuninori Morimoto 34adf6a681SKuninori Morimoto #define rsnd_src_get(priv, id) ((struct rsnd_src *)(priv->src) + id) 35da599fd3SKuninori Morimoto #define rsnd_src_nr(priv) ((priv)->src_nr) 36ab2049f9SKuninori Morimoto #define rsnd_src_sync_is_enabled(mod) (rsnd_mod_to_src(mod)->sen.val) 3782e76ed3SKuninori Morimoto 38ba9c949fSKuninori Morimoto #define rsnd_mod_to_src(_mod) \ 39ba9c949fSKuninori Morimoto container_of((_mod), struct rsnd_src, mod) 40ba9c949fSKuninori Morimoto 41ba9c949fSKuninori Morimoto #define for_each_rsnd_src(pos, priv, i) \ 42ba9c949fSKuninori Morimoto for ((i) = 0; \ 43ba9c949fSKuninori Morimoto ((i) < rsnd_src_nr(priv)) && \ 44ba9c949fSKuninori Morimoto ((pos) = (struct rsnd_src *)(priv)->src + i); \ 45ba9c949fSKuninori Morimoto i++) 46ba9c949fSKuninori Morimoto 47ba9c949fSKuninori Morimoto 48ba9c949fSKuninori Morimoto /* 49ba9c949fSKuninori Morimoto * image of SRC (Sampling Rate Converter) 50ba9c949fSKuninori Morimoto * 51ba9c949fSKuninori Morimoto * 96kHz <-> +-----+ 48kHz +-----+ 48kHz +-------+ 52ba9c949fSKuninori Morimoto * 48kHz <-> | SRC | <------> | SSI | <-----> | codec | 53ba9c949fSKuninori Morimoto * 44.1kHz <-> +-----+ +-----+ +-------+ 54ba9c949fSKuninori Morimoto * ... 55ba9c949fSKuninori Morimoto * 56ba9c949fSKuninori Morimoto */ 57ba9c949fSKuninori Morimoto 5898efeeaeSKuninori Morimoto static void rsnd_src_activation(struct rsnd_mod *mod) 59379febfdSKuninori Morimoto { 60379febfdSKuninori Morimoto rsnd_mod_write(mod, SRC_SWRSR, 0); 61379febfdSKuninori Morimoto rsnd_mod_write(mod, SRC_SWRSR, 1); 62379febfdSKuninori Morimoto } 63379febfdSKuninori Morimoto 64475a361aSKuninori Morimoto static void rsnd_src_halt(struct rsnd_mod *mod) 65475a361aSKuninori Morimoto { 66475a361aSKuninori Morimoto rsnd_mod_write(mod, SRC_SRCIR, 1); 67475a361aSKuninori Morimoto rsnd_mod_write(mod, SRC_SWRSR, 0); 68475a361aSKuninori Morimoto } 69475a361aSKuninori Morimoto 709b99e9a7SKuninori Morimoto static struct dma_chan *rsnd_src_dma_req(struct rsnd_dai_stream *io, 719b99e9a7SKuninori Morimoto struct rsnd_mod *mod) 7272adc61fSKuninori Morimoto { 7372adc61fSKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 7472adc61fSKuninori Morimoto int is_play = rsnd_io_is_play(io); 7572adc61fSKuninori Morimoto 7672adc61fSKuninori Morimoto return rsnd_dma_request_channel(rsnd_src_of_node(priv), 7772adc61fSKuninori Morimoto mod, 7872adc61fSKuninori Morimoto is_play ? "rx" : "tx"); 7972adc61fSKuninori Morimoto } 8072adc61fSKuninori Morimoto 8188c61cffSKuninori Morimoto static u32 rsnd_src_convert_rate(struct rsnd_dai_stream *io, 821a9be9eeSKuninori Morimoto struct rsnd_mod *mod) 8343cb6954SKuninori Morimoto { 8443cb6954SKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 851a9be9eeSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 8643cb6954SKuninori Morimoto u32 convert_rate; 8743cb6954SKuninori Morimoto 8843cb6954SKuninori Morimoto if (!runtime) 8943cb6954SKuninori Morimoto return 0; 9043cb6954SKuninori Morimoto 91ab2049f9SKuninori Morimoto if (!rsnd_src_sync_is_enabled(mod)) 92c2aaaa57SKuninori Morimoto return rsnd_io_converted_rate(io); 9343cb6954SKuninori Morimoto 9443cb6954SKuninori Morimoto convert_rate = src->sync.val; 9543cb6954SKuninori Morimoto 9643cb6954SKuninori Morimoto if (!convert_rate) 97c2aaaa57SKuninori Morimoto convert_rate = rsnd_io_converted_rate(io); 9843cb6954SKuninori Morimoto 9943cb6954SKuninori Morimoto if (!convert_rate) 10043cb6954SKuninori Morimoto convert_rate = runtime->rate; 10143cb6954SKuninori Morimoto 10243cb6954SKuninori Morimoto return convert_rate; 10343cb6954SKuninori Morimoto } 10443cb6954SKuninori Morimoto 105cbf1494fSKuninori Morimoto unsigned int rsnd_src_get_rate(struct rsnd_priv *priv, 106ba9c949fSKuninori Morimoto struct rsnd_dai_stream *io, 107cbf1494fSKuninori Morimoto int is_in) 108ba9c949fSKuninori Morimoto { 109b1eac430SKuninori Morimoto struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); 110cbf1494fSKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 111b1eac430SKuninori Morimoto unsigned int rate = 0; 112cbf1494fSKuninori Morimoto int is_play = rsnd_io_is_play(io); 113cbf1494fSKuninori Morimoto 114cbf1494fSKuninori Morimoto /* 115cbf1494fSKuninori Morimoto * Playback 116cbf1494fSKuninori Morimoto * runtime_rate -> [SRC] -> convert_rate 117cbf1494fSKuninori Morimoto * 118cbf1494fSKuninori Morimoto * Capture 119cbf1494fSKuninori Morimoto * convert_rate -> [SRC] -> runtime_rate 120cbf1494fSKuninori Morimoto */ 121cbf1494fSKuninori Morimoto 122cbf1494fSKuninori Morimoto if (is_play == is_in) 123cbf1494fSKuninori Morimoto return runtime->rate; 124ba9c949fSKuninori Morimoto 125ba9c949fSKuninori Morimoto /* 126ba9c949fSKuninori Morimoto * return convert rate if SRC is used, 127ba9c949fSKuninori Morimoto * otherwise, return runtime->rate as usual 128ba9c949fSKuninori Morimoto */ 1291a9be9eeSKuninori Morimoto if (src_mod) 1301a9be9eeSKuninori Morimoto rate = rsnd_src_convert_rate(io, src_mod); 131b1eac430SKuninori Morimoto 132ba9c949fSKuninori Morimoto if (!rate) 133ba9c949fSKuninori Morimoto rate = runtime->rate; 134ba9c949fSKuninori Morimoto 135ba9c949fSKuninori Morimoto return rate; 136ba9c949fSKuninori Morimoto } 137ba9c949fSKuninori Morimoto 138*7674bec4SKuninori Morimoto const static u32 bsdsr_table_pattern1[] = { 139*7674bec4SKuninori Morimoto 0x01800000, /* 6 - 1/6 */ 140*7674bec4SKuninori Morimoto 0x01000000, /* 6 - 1/4 */ 141*7674bec4SKuninori Morimoto 0x00c00000, /* 6 - 1/3 */ 142*7674bec4SKuninori Morimoto 0x00800000, /* 6 - 1/2 */ 143*7674bec4SKuninori Morimoto 0x00600000, /* 6 - 2/3 */ 144*7674bec4SKuninori Morimoto 0x00400000, /* 6 - 1 */ 145*7674bec4SKuninori Morimoto }; 146*7674bec4SKuninori Morimoto 147*7674bec4SKuninori Morimoto const static u32 bsdsr_table_pattern2[] = { 148*7674bec4SKuninori Morimoto 0x02400000, /* 6 - 1/6 */ 149*7674bec4SKuninori Morimoto 0x01800000, /* 6 - 1/4 */ 150*7674bec4SKuninori Morimoto 0x01200000, /* 6 - 1/3 */ 151*7674bec4SKuninori Morimoto 0x00c00000, /* 6 - 1/2 */ 152*7674bec4SKuninori Morimoto 0x00900000, /* 6 - 2/3 */ 153*7674bec4SKuninori Morimoto 0x00600000, /* 6 - 1 */ 154*7674bec4SKuninori Morimoto }; 155*7674bec4SKuninori Morimoto 156*7674bec4SKuninori Morimoto const static u32 bsisr_table[] = { 157*7674bec4SKuninori Morimoto 0x00100060, /* 6 - 1/6 */ 158*7674bec4SKuninori Morimoto 0x00100040, /* 6 - 1/4 */ 159*7674bec4SKuninori Morimoto 0x00100030, /* 6 - 1/3 */ 160*7674bec4SKuninori Morimoto 0x00100020, /* 6 - 1/2 */ 161*7674bec4SKuninori Morimoto 0x00100020, /* 6 - 2/3 */ 162*7674bec4SKuninori Morimoto 0x00100020, /* 6 - 1 */ 163*7674bec4SKuninori Morimoto }; 164*7674bec4SKuninori Morimoto 165*7674bec4SKuninori Morimoto const static u32 chan288888[] = { 166*7674bec4SKuninori Morimoto 0x00000006, /* 1 to 2 */ 167*7674bec4SKuninori Morimoto 0x000001fe, /* 1 to 8 */ 168*7674bec4SKuninori Morimoto 0x000001fe, /* 1 to 8 */ 169*7674bec4SKuninori Morimoto 0x000001fe, /* 1 to 8 */ 170*7674bec4SKuninori Morimoto 0x000001fe, /* 1 to 8 */ 171*7674bec4SKuninori Morimoto 0x000001fe, /* 1 to 8 */ 172*7674bec4SKuninori Morimoto }; 173*7674bec4SKuninori Morimoto 174*7674bec4SKuninori Morimoto const static u32 chan244888[] = { 175*7674bec4SKuninori Morimoto 0x00000006, /* 1 to 2 */ 176*7674bec4SKuninori Morimoto 0x0000001e, /* 1 to 4 */ 177*7674bec4SKuninori Morimoto 0x0000001e, /* 1 to 4 */ 178*7674bec4SKuninori Morimoto 0x000001fe, /* 1 to 8 */ 179*7674bec4SKuninori Morimoto 0x000001fe, /* 1 to 8 */ 180*7674bec4SKuninori Morimoto 0x000001fe, /* 1 to 8 */ 181*7674bec4SKuninori Morimoto }; 182*7674bec4SKuninori Morimoto 183*7674bec4SKuninori Morimoto const static u32 chan222222[] = { 184*7674bec4SKuninori Morimoto 0x00000006, /* 1 to 2 */ 185*7674bec4SKuninori Morimoto 0x00000006, /* 1 to 2 */ 186*7674bec4SKuninori Morimoto 0x00000006, /* 1 to 2 */ 187*7674bec4SKuninori Morimoto 0x00000006, /* 1 to 2 */ 188*7674bec4SKuninori Morimoto 0x00000006, /* 1 to 2 */ 189*7674bec4SKuninori Morimoto 0x00000006, /* 1 to 2 */ 190*7674bec4SKuninori Morimoto }; 191*7674bec4SKuninori Morimoto 192*7674bec4SKuninori Morimoto static const struct soc_device_attribute ov_soc[] = { 193*7674bec4SKuninori Morimoto { .soc_id = "r8a77990" }, /* E3 */ 194*7674bec4SKuninori Morimoto { /* sentinel */ } 195*7674bec4SKuninori Morimoto }; 196*7674bec4SKuninori Morimoto 19775916f65SKuninori Morimoto static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io, 19875916f65SKuninori Morimoto struct rsnd_mod *mod) 199ba9c949fSKuninori Morimoto { 20075916f65SKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 201cfcefe01SKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 20275916f65SKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 203*7674bec4SKuninori Morimoto const struct soc_device_attribute *soc = soc_device_match(ov_soc); 20490431eb4SKuninori Morimoto int is_play = rsnd_io_is_play(io); 20567923f77SKuninori Morimoto int use_src = 0; 2060102eed5SKuninori Morimoto u32 fin, fout; 20775916f65SKuninori Morimoto u32 ifscr, fsrate, adinr; 20875916f65SKuninori Morimoto u32 cr, route; 20990431eb4SKuninori Morimoto u32 i_busif, o_busif, tmp; 210*7674bec4SKuninori Morimoto const u32 *bsdsr_table; 211*7674bec4SKuninori Morimoto const u32 *chptn; 21275916f65SKuninori Morimoto uint ratio; 213*7674bec4SKuninori Morimoto int chan; 214*7674bec4SKuninori Morimoto int idx; 215ba9c949fSKuninori Morimoto 21675916f65SKuninori Morimoto if (!runtime) 21775916f65SKuninori Morimoto return; 218ba9c949fSKuninori Morimoto 2190102eed5SKuninori Morimoto fin = rsnd_src_get_in_rate(priv, io); 2200102eed5SKuninori Morimoto fout = rsnd_src_get_out_rate(priv, io); 2210102eed5SKuninori Morimoto 222*7674bec4SKuninori Morimoto chan = rsnd_runtime_channel_original(io); 223*7674bec4SKuninori Morimoto 22475916f65SKuninori Morimoto /* 6 - 1/6 are very enough ratio for SRC_BSDSR */ 2250102eed5SKuninori Morimoto if (fin == fout) 22675916f65SKuninori Morimoto ratio = 0; 2270102eed5SKuninori Morimoto else if (fin > fout) 2280102eed5SKuninori Morimoto ratio = 100 * fin / fout; 22975916f65SKuninori Morimoto else 2300102eed5SKuninori Morimoto ratio = 100 * fout / fin; 231cfcefe01SKuninori Morimoto 23275916f65SKuninori Morimoto if (ratio > 600) { 23375916f65SKuninori Morimoto dev_err(dev, "FSO/FSI ratio error\n"); 23475916f65SKuninori Morimoto return; 235ba9c949fSKuninori Morimoto } 236ba9c949fSKuninori Morimoto 23767923f77SKuninori Morimoto use_src = (fin != fout) | rsnd_src_sync_is_enabled(mod); 23867923f77SKuninori Morimoto 239ba9c949fSKuninori Morimoto /* 24075916f65SKuninori Morimoto * SRC_ADINR 241ba9c949fSKuninori Morimoto */ 242*7674bec4SKuninori Morimoto adinr = rsnd_get_adinr_bit(mod, io) | chan; 24375916f65SKuninori Morimoto 24475916f65SKuninori Morimoto /* 24575916f65SKuninori Morimoto * SRC_IFSCR / SRC_IFSVR 24675916f65SKuninori Morimoto */ 24775916f65SKuninori Morimoto ifscr = 0; 24875916f65SKuninori Morimoto fsrate = 0; 24967923f77SKuninori Morimoto if (use_src) { 25093ca33c9SHiroyuki Yokoyama u64 n; 25193ca33c9SHiroyuki Yokoyama 25275916f65SKuninori Morimoto ifscr = 1; 25393ca33c9SHiroyuki Yokoyama n = (u64)0x0400000 * fin; 25493ca33c9SHiroyuki Yokoyama do_div(n, fout); 25593ca33c9SHiroyuki Yokoyama fsrate = n; 25675916f65SKuninori Morimoto } 25775916f65SKuninori Morimoto 25875916f65SKuninori Morimoto /* 25975916f65SKuninori Morimoto * SRC_SRCCR / SRC_ROUTE_MODE0 26075916f65SKuninori Morimoto */ 26175916f65SKuninori Morimoto cr = 0x00011110; 26275916f65SKuninori Morimoto route = 0x0; 26367923f77SKuninori Morimoto if (use_src) { 26475916f65SKuninori Morimoto route = 0x1; 26575916f65SKuninori Morimoto 266ab2049f9SKuninori Morimoto if (rsnd_src_sync_is_enabled(mod)) { 26775916f65SKuninori Morimoto cr |= 0x1; 26875916f65SKuninori Morimoto route |= rsnd_io_is_play(io) ? 26975916f65SKuninori Morimoto (0x1 << 24) : (0x1 << 25); 27075916f65SKuninori Morimoto } 27175916f65SKuninori Morimoto } 27275916f65SKuninori Morimoto 27375916f65SKuninori Morimoto /* 27475916f65SKuninori Morimoto * SRC_BSDSR / SRC_BSISR 275*7674bec4SKuninori Morimoto * 276*7674bec4SKuninori Morimoto * see 277*7674bec4SKuninori Morimoto * Combination of Register Setting Related to 278*7674bec4SKuninori Morimoto * FSO/FSI Ratio and Channel, Latency 27975916f65SKuninori Morimoto */ 28075916f65SKuninori Morimoto switch (rsnd_mod_id(mod)) { 281*7674bec4SKuninori Morimoto case 0: 282*7674bec4SKuninori Morimoto chptn = chan288888; 283*7674bec4SKuninori Morimoto bsdsr_table = bsdsr_table_pattern1; 284*7674bec4SKuninori Morimoto break; 285*7674bec4SKuninori Morimoto case 1: 286*7674bec4SKuninori Morimoto case 3: 287*7674bec4SKuninori Morimoto case 4: 288*7674bec4SKuninori Morimoto chptn = chan244888; 289*7674bec4SKuninori Morimoto bsdsr_table = bsdsr_table_pattern1; 290*7674bec4SKuninori Morimoto break; 291*7674bec4SKuninori Morimoto case 2: 292*7674bec4SKuninori Morimoto case 9: 293*7674bec4SKuninori Morimoto chptn = chan222222; 294*7674bec4SKuninori Morimoto bsdsr_table = bsdsr_table_pattern1; 295*7674bec4SKuninori Morimoto break; 29675916f65SKuninori Morimoto case 5: 29775916f65SKuninori Morimoto case 6: 29875916f65SKuninori Morimoto case 7: 29975916f65SKuninori Morimoto case 8: 300*7674bec4SKuninori Morimoto chptn = chan222222; 301*7674bec4SKuninori Morimoto bsdsr_table = bsdsr_table_pattern2; 30275916f65SKuninori Morimoto break; 30375916f65SKuninori Morimoto default: 304*7674bec4SKuninori Morimoto goto convert_rate_err; 30575916f65SKuninori Morimoto } 30675916f65SKuninori Morimoto 307*7674bec4SKuninori Morimoto /* 308*7674bec4SKuninori Morimoto * E3 need to overwrite 309*7674bec4SKuninori Morimoto */ 310*7674bec4SKuninori Morimoto if (soc) 311*7674bec4SKuninori Morimoto switch (rsnd_mod_id(mod)) { 312*7674bec4SKuninori Morimoto case 0: 313*7674bec4SKuninori Morimoto case 4: 314*7674bec4SKuninori Morimoto chptn = chan222222; 315*7674bec4SKuninori Morimoto } 316*7674bec4SKuninori Morimoto 317*7674bec4SKuninori Morimoto for (idx = 0; idx < ARRAY_SIZE(chan222222); idx++) 318*7674bec4SKuninori Morimoto if (chptn[idx] & (1 << chan)) 319*7674bec4SKuninori Morimoto break; 320*7674bec4SKuninori Morimoto 321*7674bec4SKuninori Morimoto if (chan > 8 || 322*7674bec4SKuninori Morimoto idx >= ARRAY_SIZE(chan222222)) 323*7674bec4SKuninori Morimoto goto convert_rate_err; 324*7674bec4SKuninori Morimoto 32590431eb4SKuninori Morimoto /* BUSIF_MODE */ 32690431eb4SKuninori Morimoto tmp = rsnd_get_busif_shift(io, mod); 32790431eb4SKuninori Morimoto i_busif = ( is_play ? tmp : 0) | 1; 32890431eb4SKuninori Morimoto o_busif = (!is_play ? tmp : 0) | 1; 32990431eb4SKuninori Morimoto 3300fbab951SKuninori Morimoto rsnd_mod_write(mod, SRC_ROUTE_MODE0, route); 3310fbab951SKuninori Morimoto 33275916f65SKuninori Morimoto rsnd_mod_write(mod, SRC_SRCIR, 1); /* initialize */ 33375916f65SKuninori Morimoto rsnd_mod_write(mod, SRC_ADINR, adinr); 33475916f65SKuninori Morimoto rsnd_mod_write(mod, SRC_IFSCR, ifscr); 33575916f65SKuninori Morimoto rsnd_mod_write(mod, SRC_IFSVR, fsrate); 33675916f65SKuninori Morimoto rsnd_mod_write(mod, SRC_SRCCR, cr); 337*7674bec4SKuninori Morimoto rsnd_mod_write(mod, SRC_BSDSR, bsdsr_table[idx]); 338*7674bec4SKuninori Morimoto rsnd_mod_write(mod, SRC_BSISR, bsisr_table[idx]); 33975916f65SKuninori Morimoto rsnd_mod_write(mod, SRC_SRCIR, 0); /* cancel initialize */ 34075916f65SKuninori Morimoto 34190431eb4SKuninori Morimoto rsnd_mod_write(mod, SRC_I_BUSIF_MODE, i_busif); 34290431eb4SKuninori Morimoto rsnd_mod_write(mod, SRC_O_BUSIF_MODE, o_busif); 34390431eb4SKuninori Morimoto 34475916f65SKuninori Morimoto rsnd_mod_write(mod, SRC_BUSIF_DALIGN, rsnd_get_dalign(mod, io)); 34575916f65SKuninori Morimoto 3460102eed5SKuninori Morimoto rsnd_adg_set_src_timesel_gen2(mod, io, fin, fout); 347*7674bec4SKuninori Morimoto 348*7674bec4SKuninori Morimoto return; 349*7674bec4SKuninori Morimoto 350*7674bec4SKuninori Morimoto convert_rate_err: 351*7674bec4SKuninori Morimoto dev_err(dev, "unknown BSDSR/BSDIR settings\n"); 35275916f65SKuninori Morimoto } 35375916f65SKuninori Morimoto 354b5b442abSKuninori Morimoto static int rsnd_src_irq(struct rsnd_mod *mod, 355b5b442abSKuninori Morimoto struct rsnd_dai_stream *io, 356b5b442abSKuninori Morimoto struct rsnd_priv *priv, 357b5b442abSKuninori Morimoto int enable) 358cfcefe01SKuninori Morimoto { 359cfcefe01SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 360cfcefe01SKuninori Morimoto u32 sys_int_val, int_val, sys_int_mask; 361adf6a681SKuninori Morimoto int irq = src->irq; 362cfcefe01SKuninori Morimoto int id = rsnd_mod_id(mod); 363cfcefe01SKuninori Morimoto 364cfcefe01SKuninori Morimoto sys_int_val = 365cfcefe01SKuninori Morimoto sys_int_mask = OUF_SRC(id); 366cfcefe01SKuninori Morimoto int_val = 0x3300; 367cfcefe01SKuninori Morimoto 368cfcefe01SKuninori Morimoto /* 369cfcefe01SKuninori Morimoto * IRQ is not supported on non-DT 370cfcefe01SKuninori Morimoto * see 37175916f65SKuninori Morimoto * rsnd_src_probe_() 372cfcefe01SKuninori Morimoto */ 373cfcefe01SKuninori Morimoto if ((irq <= 0) || !enable) { 374cfcefe01SKuninori Morimoto sys_int_val = 0; 375cfcefe01SKuninori Morimoto int_val = 0; 376cfcefe01SKuninori Morimoto } 377cfcefe01SKuninori Morimoto 3781a1bf58aSKuninori Morimoto /* 3791a1bf58aSKuninori Morimoto * WORKAROUND 3801a1bf58aSKuninori Morimoto * 381ab2049f9SKuninori Morimoto * ignore over flow error when rsnd_src_sync_is_enabled() 3821a1bf58aSKuninori Morimoto */ 383ab2049f9SKuninori Morimoto if (rsnd_src_sync_is_enabled(mod)) 3841a1bf58aSKuninori Morimoto sys_int_val = sys_int_val & 0xffff; 3851a1bf58aSKuninori Morimoto 386cfcefe01SKuninori Morimoto rsnd_mod_write(mod, SRC_INT_ENABLE0, int_val); 387cfcefe01SKuninori Morimoto rsnd_mod_bset(mod, SCU_SYS_INT_EN0, sys_int_mask, sys_int_val); 388cfcefe01SKuninori Morimoto rsnd_mod_bset(mod, SCU_SYS_INT_EN1, sys_int_mask, sys_int_val); 389b5b442abSKuninori Morimoto 390b5b442abSKuninori Morimoto return 0; 391cfcefe01SKuninori Morimoto } 392cfcefe01SKuninori Morimoto 3938cc225f7SKuninori Morimoto static void rsnd_src_status_clear(struct rsnd_mod *mod) 394cfcefe01SKuninori Morimoto { 395cfcefe01SKuninori Morimoto u32 val = OUF_SRC(rsnd_mod_id(mod)); 396cfcefe01SKuninori Morimoto 39742b197e7SKuninori Morimoto rsnd_mod_write(mod, SCU_SYS_STATUS0, val); 39842b197e7SKuninori Morimoto rsnd_mod_write(mod, SCU_SYS_STATUS1, val); 399cfcefe01SKuninori Morimoto } 400cfcefe01SKuninori Morimoto 4016a25c8daSKuninori Morimoto static bool rsnd_src_error_occurred(struct rsnd_mod *mod) 402cfcefe01SKuninori Morimoto { 4032b627869SKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 4042b627869SKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 4051a1bf58aSKuninori Morimoto u32 val0, val1; 4062b627869SKuninori Morimoto u32 status0, status1; 407cfcefe01SKuninori Morimoto bool ret = false; 408cfcefe01SKuninori Morimoto 4091a1bf58aSKuninori Morimoto val0 = val1 = OUF_SRC(rsnd_mod_id(mod)); 4101a1bf58aSKuninori Morimoto 4111a1bf58aSKuninori Morimoto /* 4121a1bf58aSKuninori Morimoto * WORKAROUND 4131a1bf58aSKuninori Morimoto * 414ab2049f9SKuninori Morimoto * ignore over flow error when rsnd_src_sync_is_enabled() 4151a1bf58aSKuninori Morimoto */ 416ab2049f9SKuninori Morimoto if (rsnd_src_sync_is_enabled(mod)) 4171a1bf58aSKuninori Morimoto val0 = val0 & 0xffff; 4181a1bf58aSKuninori Morimoto 4192b627869SKuninori Morimoto status0 = rsnd_mod_read(mod, SCU_SYS_STATUS0); 4202b627869SKuninori Morimoto status1 = rsnd_mod_read(mod, SCU_SYS_STATUS1); 4212b627869SKuninori Morimoto if ((status0 & val0) || (status1 & val1)) { 422c0ea089dSKuninori Morimoto rsnd_dbg_irq_status(dev, "%s err status : 0x%08x, 0x%08x\n", 423c0ea089dSKuninori Morimoto rsnd_mod_name(mod), status0, status1); 4242b627869SKuninori Morimoto 425cfcefe01SKuninori Morimoto ret = true; 4262b627869SKuninori Morimoto } 427cfcefe01SKuninori Morimoto 428cfcefe01SKuninori Morimoto return ret; 429cfcefe01SKuninori Morimoto } 430cfcefe01SKuninori Morimoto 43175916f65SKuninori Morimoto static int rsnd_src_start(struct rsnd_mod *mod, 432497debaaSKuninori Morimoto struct rsnd_dai_stream *io, 433497debaaSKuninori Morimoto struct rsnd_priv *priv) 434cfcefe01SKuninori Morimoto { 4351a1bf58aSKuninori Morimoto u32 val; 4361a1bf58aSKuninori Morimoto 4371a1bf58aSKuninori Morimoto /* 4381a1bf58aSKuninori Morimoto * WORKAROUND 4391a1bf58aSKuninori Morimoto * 4401a1bf58aSKuninori Morimoto * Enable SRC output if you want to use sync convert together with DVC 4411a1bf58aSKuninori Morimoto */ 442ab2049f9SKuninori Morimoto val = (rsnd_io_to_mod_dvc(io) && !rsnd_src_sync_is_enabled(mod)) ? 4431a1bf58aSKuninori Morimoto 0x01 : 0x11; 444cfcefe01SKuninori Morimoto 445cfcefe01SKuninori Morimoto rsnd_mod_write(mod, SRC_CTRL, val); 446cfcefe01SKuninori Morimoto 44775916f65SKuninori Morimoto return 0; 44875916f65SKuninori Morimoto } 449cfcefe01SKuninori Morimoto 45075916f65SKuninori Morimoto static int rsnd_src_stop(struct rsnd_mod *mod, 45175916f65SKuninori Morimoto struct rsnd_dai_stream *io, 45275916f65SKuninori Morimoto struct rsnd_priv *priv) 45375916f65SKuninori Morimoto { 45431739a68SKuninori Morimoto rsnd_mod_write(mod, SRC_CTRL, 0); 455cfcefe01SKuninori Morimoto 456cfcefe01SKuninori Morimoto return 0; 457cfcefe01SKuninori Morimoto } 458cfcefe01SKuninori Morimoto 45975916f65SKuninori Morimoto static int rsnd_src_init(struct rsnd_mod *mod, 460497debaaSKuninori Morimoto struct rsnd_dai_stream *io, 461497debaaSKuninori Morimoto struct rsnd_priv *priv) 462cfcefe01SKuninori Morimoto { 46375916f65SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 464cfcefe01SKuninori Morimoto 465ef30da1cSKuninori Morimoto /* reset sync convert_rate */ 466ef30da1cSKuninori Morimoto src->sync.val = 0; 467ef30da1cSKuninori Morimoto 46875916f65SKuninori Morimoto rsnd_mod_power_on(mod); 469cfcefe01SKuninori Morimoto 47098efeeaeSKuninori Morimoto rsnd_src_activation(mod); 471cfcefe01SKuninori Morimoto 47275916f65SKuninori Morimoto rsnd_src_set_convert_rate(io, mod); 47375916f65SKuninori Morimoto 4748cc225f7SKuninori Morimoto rsnd_src_status_clear(mod); 47575916f65SKuninori Morimoto 47675916f65SKuninori Morimoto return 0; 477cfcefe01SKuninori Morimoto } 478cfcefe01SKuninori Morimoto 47975916f65SKuninori Morimoto static int rsnd_src_quit(struct rsnd_mod *mod, 480b761bf27SKuninori Morimoto struct rsnd_dai_stream *io, 481b761bf27SKuninori Morimoto struct rsnd_priv *priv) 482b761bf27SKuninori Morimoto { 48375916f65SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 48475916f65SKuninori Morimoto 485475a361aSKuninori Morimoto rsnd_src_halt(mod); 486475a361aSKuninori Morimoto 48775916f65SKuninori Morimoto rsnd_mod_power_off(mod); 48875916f65SKuninori Morimoto 48975916f65SKuninori Morimoto /* reset sync convert_rate */ 49075916f65SKuninori Morimoto src->sync.val = 0; 49175916f65SKuninori Morimoto 49275916f65SKuninori Morimoto return 0; 493b761bf27SKuninori Morimoto } 494b761bf27SKuninori Morimoto 49575916f65SKuninori Morimoto static void __rsnd_src_interrupt(struct rsnd_mod *mod, 49688c61cffSKuninori Morimoto struct rsnd_dai_stream *io) 497cfcefe01SKuninori Morimoto { 49802299d98SKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 4996a25c8daSKuninori Morimoto bool stop = false; 500cfcefe01SKuninori Morimoto 50102299d98SKuninori Morimoto spin_lock(&priv->lock); 50202299d98SKuninori Morimoto 50302299d98SKuninori Morimoto /* ignore all cases if not working */ 504d5bbe7deSKuninori Morimoto if (!rsnd_io_is_working(io)) 50575916f65SKuninori Morimoto goto rsnd_src_interrupt_out; 506cfcefe01SKuninori Morimoto 5076a25c8daSKuninori Morimoto if (rsnd_src_error_occurred(mod)) 5086a25c8daSKuninori Morimoto stop = true; 50988c61cffSKuninori Morimoto 5108cc225f7SKuninori Morimoto rsnd_src_status_clear(mod); 51175916f65SKuninori Morimoto rsnd_src_interrupt_out: 5128cc225f7SKuninori Morimoto 51302299d98SKuninori Morimoto spin_unlock(&priv->lock); 5146a25c8daSKuninori Morimoto 5156a25c8daSKuninori Morimoto if (stop) 5166a25c8daSKuninori Morimoto snd_pcm_stop_xrun(io->substream); 51788c61cffSKuninori Morimoto } 51888c61cffSKuninori Morimoto 51975916f65SKuninori Morimoto static irqreturn_t rsnd_src_interrupt(int irq, void *data) 52088c61cffSKuninori Morimoto { 52188c61cffSKuninori Morimoto struct rsnd_mod *mod = data; 52288c61cffSKuninori Morimoto 52375916f65SKuninori Morimoto rsnd_mod_interrupt(mod, __rsnd_src_interrupt); 524cfcefe01SKuninori Morimoto 525cfcefe01SKuninori Morimoto return IRQ_HANDLED; 526cfcefe01SKuninori Morimoto } 527cfcefe01SKuninori Morimoto 52875916f65SKuninori Morimoto static int rsnd_src_probe_(struct rsnd_mod *mod, 5292c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 530690602fcSKuninori Morimoto struct rsnd_priv *priv) 531ba9c949fSKuninori Morimoto { 532ba9c949fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 533ba9c949fSKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 534adf6a681SKuninori Morimoto int irq = src->irq; 535ba9c949fSKuninori Morimoto int ret; 536ba9c949fSKuninori Morimoto 537cfcefe01SKuninori Morimoto if (irq > 0) { 538cfcefe01SKuninori Morimoto /* 539cfcefe01SKuninori Morimoto * IRQ is not supported on non-DT 540cfcefe01SKuninori Morimoto * see 541b5b442abSKuninori Morimoto * rsnd_src_irq() 542cfcefe01SKuninori Morimoto */ 543cfcefe01SKuninori Morimoto ret = devm_request_irq(dev, irq, 54475916f65SKuninori Morimoto rsnd_src_interrupt, 545cfcefe01SKuninori Morimoto IRQF_SHARED, 546cfcefe01SKuninori Morimoto dev_name(dev), mod); 547cfcefe01SKuninori Morimoto if (ret) 548b543b52aSKuninori Morimoto return ret; 549cfcefe01SKuninori Morimoto } 550cfcefe01SKuninori Morimoto 551b99305d2SKuninori Morimoto ret = rsnd_dma_attach(io, mod, &src->dma); 552cfcefe01SKuninori Morimoto 553cfcefe01SKuninori Morimoto return ret; 554ba9c949fSKuninori Morimoto } 555ba9c949fSKuninori Morimoto 55675916f65SKuninori Morimoto static int rsnd_src_pcm_new(struct rsnd_mod *mod, 5572c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 55843cb6954SKuninori Morimoto struct snd_soc_pcm_runtime *rtd) 55943cb6954SKuninori Morimoto { 56043cb6954SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 56143cb6954SKuninori Morimoto int ret; 56243cb6954SKuninori Morimoto 56343cb6954SKuninori Morimoto /* 56443cb6954SKuninori Morimoto * enable SRC sync convert if possible 56543cb6954SKuninori Morimoto */ 56643cb6954SKuninori Morimoto 56743cb6954SKuninori Morimoto /* 56861a219feSKuninori Morimoto * It can't use SRC Synchronous convert 56961a219feSKuninori Morimoto * when Capture if it uses CMD 5707115cb91SKuninori Morimoto */ 57161a219feSKuninori Morimoto if (rsnd_io_to_mod_cmd(io) && !rsnd_io_is_play(io)) 5727115cb91SKuninori Morimoto return 0; 5737115cb91SKuninori Morimoto 5747115cb91SKuninori Morimoto /* 57543cb6954SKuninori Morimoto * enable sync convert 57643cb6954SKuninori Morimoto */ 577b65a7cccSKuninori Morimoto ret = rsnd_kctrl_new_s(mod, io, rtd, 57843cb6954SKuninori Morimoto rsnd_io_is_play(io) ? 57943cb6954SKuninori Morimoto "SRC Out Rate Switch" : 58043cb6954SKuninori Morimoto "SRC In Rate Switch", 581f0b04d8bSKuninori Morimoto rsnd_kctrl_accept_anytime, 58275916f65SKuninori Morimoto rsnd_src_set_convert_rate, 58343cb6954SKuninori Morimoto &src->sen, 1); 58443cb6954SKuninori Morimoto if (ret < 0) 58543cb6954SKuninori Morimoto return ret; 58643cb6954SKuninori Morimoto 587b65a7cccSKuninori Morimoto ret = rsnd_kctrl_new_s(mod, io, rtd, 58843cb6954SKuninori Morimoto rsnd_io_is_play(io) ? 58943cb6954SKuninori Morimoto "SRC Out Rate" : 59043cb6954SKuninori Morimoto "SRC In Rate", 591f0b04d8bSKuninori Morimoto rsnd_kctrl_accept_runtime, 59275916f65SKuninori Morimoto rsnd_src_set_convert_rate, 59343cb6954SKuninori Morimoto &src->sync, 192000); 59443cb6954SKuninori Morimoto 59543cb6954SKuninori Morimoto return ret; 59643cb6954SKuninori Morimoto } 59743cb6954SKuninori Morimoto 59875916f65SKuninori Morimoto static struct rsnd_mod_ops rsnd_src_ops = { 5998aefda50SKuninori Morimoto .name = SRC_NAME, 60072adc61fSKuninori Morimoto .dma_req = rsnd_src_dma_req, 60175916f65SKuninori Morimoto .probe = rsnd_src_probe_, 60275916f65SKuninori Morimoto .init = rsnd_src_init, 60375916f65SKuninori Morimoto .quit = rsnd_src_quit, 60475916f65SKuninori Morimoto .start = rsnd_src_start, 60575916f65SKuninori Morimoto .stop = rsnd_src_stop, 606b5b442abSKuninori Morimoto .irq = rsnd_src_irq, 60775916f65SKuninori Morimoto .pcm_new = rsnd_src_pcm_new, 6087e7fe06dSKuninori Morimoto .get_status = rsnd_mod_get_status, 609ba9c949fSKuninori Morimoto }; 610ba9c949fSKuninori Morimoto 611ba9c949fSKuninori Morimoto struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id) 612ba9c949fSKuninori Morimoto { 613ba9c949fSKuninori Morimoto if (WARN_ON(id < 0 || id >= rsnd_src_nr(priv))) 614ba9c949fSKuninori Morimoto id = 0; 615ba9c949fSKuninori Morimoto 616adf6a681SKuninori Morimoto return rsnd_mod_get(rsnd_src_get(priv, id)); 61790e8e50fSKuninori Morimoto } 61890e8e50fSKuninori Morimoto 6192ea6b074SKuninori Morimoto int rsnd_src_probe(struct rsnd_priv *priv) 620ba9c949fSKuninori Morimoto { 621adf6a681SKuninori Morimoto struct device_node *node; 622adf6a681SKuninori Morimoto struct device_node *np; 623ba9c949fSKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 624ba9c949fSKuninori Morimoto struct rsnd_src *src; 625ba9c949fSKuninori Morimoto struct clk *clk; 626ba9c949fSKuninori Morimoto char name[RSND_SRC_NAME_SIZE]; 6272f78dd7fSKuninori Morimoto int i, nr, ret; 628ba9c949fSKuninori Morimoto 629e8e7b7bdSKuninori Morimoto /* This driver doesn't support Gen1 at this point */ 630e8e7b7bdSKuninori Morimoto if (rsnd_is_gen1(priv)) 631e8e7b7bdSKuninori Morimoto return 0; 632033e7ed8SKuninori Morimoto 633adf6a681SKuninori Morimoto node = rsnd_src_of_node(priv); 634adf6a681SKuninori Morimoto if (!node) 635adf6a681SKuninori Morimoto return 0; /* not used is not error */ 63690e8e50fSKuninori Morimoto 637adf6a681SKuninori Morimoto nr = of_get_child_count(node); 638adf6a681SKuninori Morimoto if (!nr) { 639adf6a681SKuninori Morimoto ret = -EINVAL; 640adf6a681SKuninori Morimoto goto rsnd_src_probe_done; 641adf6a681SKuninori Morimoto } 642ba9c949fSKuninori Morimoto 643a86854d0SKees Cook src = devm_kcalloc(dev, nr, sizeof(*src), GFP_KERNEL); 644adf6a681SKuninori Morimoto if (!src) { 645adf6a681SKuninori Morimoto ret = -ENOMEM; 646adf6a681SKuninori Morimoto goto rsnd_src_probe_done; 647adf6a681SKuninori Morimoto } 648ba9c949fSKuninori Morimoto 649ba9c949fSKuninori Morimoto priv->src_nr = nr; 650ba9c949fSKuninori Morimoto priv->src = src; 651ba9c949fSKuninori Morimoto 652adf6a681SKuninori Morimoto i = 0; 653adf6a681SKuninori Morimoto for_each_child_of_node(node, np) { 654de196515SSergei Shtylyov if (!of_device_is_available(np)) 655de196515SSergei Shtylyov goto skip; 656de196515SSergei Shtylyov 657adf6a681SKuninori Morimoto src = rsnd_src_get(priv, i); 658adf6a681SKuninori Morimoto 6598aefda50SKuninori Morimoto snprintf(name, RSND_SRC_NAME_SIZE, "%s.%d", 6608aefda50SKuninori Morimoto SRC_NAME, i); 661ba9c949fSKuninori Morimoto 662adf6a681SKuninori Morimoto src->irq = irq_of_parse_and_map(np, 0); 663adf6a681SKuninori Morimoto if (!src->irq) { 664adf6a681SKuninori Morimoto ret = -EINVAL; 66553ba2aa3SJulia Lawall of_node_put(np); 666adf6a681SKuninori Morimoto goto rsnd_src_probe_done; 667adf6a681SKuninori Morimoto } 668ba9c949fSKuninori Morimoto 669adf6a681SKuninori Morimoto clk = devm_clk_get(dev, name); 670adf6a681SKuninori Morimoto if (IS_ERR(clk)) { 671adf6a681SKuninori Morimoto ret = PTR_ERR(clk); 67253ba2aa3SJulia Lawall of_node_put(np); 673adf6a681SKuninori Morimoto goto rsnd_src_probe_done; 674adf6a681SKuninori Morimoto } 675ba9c949fSKuninori Morimoto 676e8e7b7bdSKuninori Morimoto ret = rsnd_mod_init(priv, rsnd_mod_get(src), 6777e7fe06dSKuninori Morimoto &rsnd_src_ops, clk, RSND_MOD_SRC, i); 67853ba2aa3SJulia Lawall if (ret) { 67953ba2aa3SJulia Lawall of_node_put(np); 680adf6a681SKuninori Morimoto goto rsnd_src_probe_done; 68153ba2aa3SJulia Lawall } 682adf6a681SKuninori Morimoto 683de196515SSergei Shtylyov skip: 684adf6a681SKuninori Morimoto i++; 685ba9c949fSKuninori Morimoto } 686ba9c949fSKuninori Morimoto 687adf6a681SKuninori Morimoto ret = 0; 688adf6a681SKuninori Morimoto 689adf6a681SKuninori Morimoto rsnd_src_probe_done: 690adf6a681SKuninori Morimoto of_node_put(node); 691adf6a681SKuninori Morimoto 692adf6a681SKuninori Morimoto return ret; 693ba9c949fSKuninori Morimoto } 6942f78dd7fSKuninori Morimoto 6952ea6b074SKuninori Morimoto void rsnd_src_remove(struct rsnd_priv *priv) 6962f78dd7fSKuninori Morimoto { 6972f78dd7fSKuninori Morimoto struct rsnd_src *src; 6982f78dd7fSKuninori Morimoto int i; 6992f78dd7fSKuninori Morimoto 7002f78dd7fSKuninori Morimoto for_each_rsnd_src(src, priv, i) { 701b76e218aSKuninori Morimoto rsnd_mod_quit(rsnd_mod_get(src)); 7022f78dd7fSKuninori Morimoto } 7032f78dd7fSKuninori Morimoto } 704