1ba9c949fSKuninori Morimoto /* 2ba9c949fSKuninori Morimoto * Renesas R-Car SRC support 3ba9c949fSKuninori Morimoto * 4ba9c949fSKuninori Morimoto * Copyright (C) 2013 Renesas Solutions Corp. 5ba9c949fSKuninori Morimoto * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 6ba9c949fSKuninori Morimoto * 7ba9c949fSKuninori Morimoto * This program is free software; you can redistribute it and/or modify 8ba9c949fSKuninori Morimoto * it under the terms of the GNU General Public License version 2 as 9ba9c949fSKuninori Morimoto * published by the Free Software Foundation. 10ba9c949fSKuninori Morimoto */ 11ba9c949fSKuninori Morimoto #include "rsnd.h" 12ba9c949fSKuninori Morimoto 138aefda50SKuninori Morimoto #define SRC_NAME "src" 148aefda50SKuninori Morimoto 15cfcefe01SKuninori Morimoto /* SRCx_STATUS */ 16cfcefe01SKuninori Morimoto #define OUF_SRCO ((1 << 12) | (1 << 13)) 17cfcefe01SKuninori Morimoto #define OUF_SRCI ((1 << 9) | (1 << 8)) 18cfcefe01SKuninori Morimoto 19cfcefe01SKuninori Morimoto /* SCU_SYSTEM_STATUS0/1 */ 20cfcefe01SKuninori Morimoto #define OUF_SRC(id) ((1 << (id + 16)) | (1 << id)) 21cfcefe01SKuninori Morimoto 22ba9c949fSKuninori Morimoto struct rsnd_src { 23ba9c949fSKuninori Morimoto struct rsnd_src_platform_info *info; /* rcar_snd.h */ 24ba9c949fSKuninori Morimoto struct rsnd_mod mod; 2543cb6954SKuninori Morimoto struct rsnd_kctrl_cfg_s sen; /* sync convert enable */ 2643cb6954SKuninori Morimoto struct rsnd_kctrl_cfg_s sync; /* sync convert */ 273b7843ffSKuninori Morimoto u32 convert_rate; /* sampling rate convert */ 28cfcefe01SKuninori Morimoto int err; 29ba9c949fSKuninori Morimoto }; 30ba9c949fSKuninori Morimoto 31ba9c949fSKuninori Morimoto #define RSND_SRC_NAME_SIZE 16 32ba9c949fSKuninori Morimoto 3343cb6954SKuninori Morimoto #define rsnd_enable_sync_convert(src) ((src)->sen.val) 3482e76ed3SKuninori Morimoto #define rsnd_src_of_node(priv) \ 3582e76ed3SKuninori Morimoto of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,src") 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 57ba9c949fSKuninori Morimoto /* 58ba9c949fSKuninori Morimoto * src.c is caring... 59ba9c949fSKuninori Morimoto * 60ba9c949fSKuninori Morimoto * Gen1 61ba9c949fSKuninori Morimoto * 62ba9c949fSKuninori Morimoto * [mem] -> [SRU] -> [SSI] 63ba9c949fSKuninori Morimoto * |--------| 64ba9c949fSKuninori Morimoto * 65ba9c949fSKuninori Morimoto * Gen2 66ba9c949fSKuninori Morimoto * 67ba9c949fSKuninori Morimoto * [mem] -> [SRC] -> [SSIU] -> [SSI] 68ba9c949fSKuninori Morimoto * |-----------------| 69ba9c949fSKuninori Morimoto */ 70ba9c949fSKuninori Morimoto 71ba9c949fSKuninori Morimoto /* 72ba9c949fSKuninori Morimoto * How to use SRC bypass mode for debugging 73ba9c949fSKuninori Morimoto * 74ba9c949fSKuninori Morimoto * SRC has bypass mode, and it is useful for debugging. 75ba9c949fSKuninori Morimoto * In Gen2 case, 76ba9c949fSKuninori Morimoto * SRCm_MODE controls whether SRC is used or not 77ba9c949fSKuninori Morimoto * SSI_MODE0 controls whether SSIU which receives SRC data 78ba9c949fSKuninori Morimoto * is used or not. 79ba9c949fSKuninori Morimoto * Both SRCm_MODE/SSI_MODE0 settings are needed if you use SRC, 80ba9c949fSKuninori Morimoto * but SRC bypass mode needs SSI_MODE0 only. 81ba9c949fSKuninori Morimoto * 82ba9c949fSKuninori Morimoto * This driver request 83ba9c949fSKuninori Morimoto * struct rsnd_src_platform_info { 84ba9c949fSKuninori Morimoto * u32 convert_rate; 8529e69fd2SKuninori Morimoto * int dma_id; 86ba9c949fSKuninori Morimoto * } 87ba9c949fSKuninori Morimoto * 88ba9c949fSKuninori Morimoto * rsnd_src_convert_rate() indicates 89ba9c949fSKuninori Morimoto * above convert_rate, and it controls 90ba9c949fSKuninori Morimoto * whether SRC is used or not. 91ba9c949fSKuninori Morimoto * 92ba9c949fSKuninori Morimoto * ex) doesn't use SRC 9329e69fd2SKuninori Morimoto * static struct rsnd_dai_platform_info rsnd_dai = { 9429e69fd2SKuninori Morimoto * .playback = { .ssi = &rsnd_ssi[0], }, 95ba9c949fSKuninori Morimoto * }; 96ba9c949fSKuninori Morimoto * 97ba9c949fSKuninori Morimoto * ex) uses SRC 9829e69fd2SKuninori Morimoto * static struct rsnd_src_platform_info rsnd_src[] = { 9929e69fd2SKuninori Morimoto * RSND_SCU(48000, 0), 10029e69fd2SKuninori Morimoto * ... 10129e69fd2SKuninori Morimoto * }; 10229e69fd2SKuninori Morimoto * static struct rsnd_dai_platform_info rsnd_dai = { 10329e69fd2SKuninori Morimoto * .playback = { .ssi = &rsnd_ssi[0], .src = &rsnd_src[0] }, 104ba9c949fSKuninori Morimoto * }; 105ba9c949fSKuninori Morimoto * 106ba9c949fSKuninori Morimoto * ex) uses SRC bypass mode 10729e69fd2SKuninori Morimoto * static struct rsnd_src_platform_info rsnd_src[] = { 10829e69fd2SKuninori Morimoto * RSND_SCU(0, 0), 10929e69fd2SKuninori Morimoto * ... 11029e69fd2SKuninori Morimoto * }; 11129e69fd2SKuninori Morimoto * static struct rsnd_dai_platform_info rsnd_dai = { 11229e69fd2SKuninori Morimoto * .playback = { .ssi = &rsnd_ssi[0], .src = &rsnd_src[0] }, 113ba9c949fSKuninori Morimoto * }; 114ba9c949fSKuninori Morimoto * 115ba9c949fSKuninori Morimoto */ 116ba9c949fSKuninori Morimoto 117ba9c949fSKuninori Morimoto /* 118ba9c949fSKuninori Morimoto * Gen1/Gen2 common functions 119ba9c949fSKuninori Morimoto */ 12072adc61fSKuninori Morimoto static struct dma_chan *rsnd_src_dma_req(struct rsnd_mod *mod) 12172adc61fSKuninori Morimoto { 12272adc61fSKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 12372adc61fSKuninori Morimoto struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); 12472adc61fSKuninori Morimoto int is_play = rsnd_io_is_play(io); 12572adc61fSKuninori Morimoto 12672adc61fSKuninori Morimoto return rsnd_dma_request_channel(rsnd_src_of_node(priv), 12772adc61fSKuninori Morimoto mod, 12872adc61fSKuninori Morimoto is_play ? "rx" : "tx"); 12972adc61fSKuninori Morimoto } 13072adc61fSKuninori Morimoto 131d9288d0bSKuninori Morimoto int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, 132d9288d0bSKuninori Morimoto int use_busif) 133ba9c949fSKuninori Morimoto { 1341cc71959SKuninori Morimoto struct rsnd_dai_stream *io = rsnd_mod_to_io(ssi_mod); 135f708d944SKuninori Morimoto struct rsnd_dai *rdai = rsnd_io_to_rdai(io); 1361cc71959SKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 137ba9c949fSKuninori Morimoto int ssi_id = rsnd_mod_id(ssi_mod); 138ba9c949fSKuninori Morimoto 139ba9c949fSKuninori Morimoto /* 140ba9c949fSKuninori Morimoto * SSI_MODE0 141ba9c949fSKuninori Morimoto */ 142ba9c949fSKuninori Morimoto rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id), 143d9288d0bSKuninori Morimoto !use_busif << ssi_id); 144ba9c949fSKuninori Morimoto 145ba9c949fSKuninori Morimoto /* 146ba9c949fSKuninori Morimoto * SSI_MODE1 147ba9c949fSKuninori Morimoto */ 148ba9c949fSKuninori Morimoto if (rsnd_ssi_is_pin_sharing(ssi_mod)) { 149ba9c949fSKuninori Morimoto int shift = -1; 150ba9c949fSKuninori Morimoto switch (ssi_id) { 151ba9c949fSKuninori Morimoto case 1: 152ba9c949fSKuninori Morimoto shift = 0; 153ba9c949fSKuninori Morimoto break; 154ba9c949fSKuninori Morimoto case 2: 155ba9c949fSKuninori Morimoto shift = 2; 156ba9c949fSKuninori Morimoto break; 157ba9c949fSKuninori Morimoto case 4: 158ba9c949fSKuninori Morimoto shift = 16; 159ba9c949fSKuninori Morimoto break; 160ba9c949fSKuninori Morimoto } 161ba9c949fSKuninori Morimoto 162ba9c949fSKuninori Morimoto if (shift >= 0) 163ba9c949fSKuninori Morimoto rsnd_mod_bset(ssi_mod, SSI_MODE1, 164ba9c949fSKuninori Morimoto 0x3 << shift, 1653ed6448cSKuninori Morimoto rsnd_rdai_is_clk_master(rdai) ? 166ba9c949fSKuninori Morimoto 0x2 << shift : 0x1 << shift); 167ba9c949fSKuninori Morimoto } 168ba9c949fSKuninori Morimoto 169d9288d0bSKuninori Morimoto /* 170d9288d0bSKuninori Morimoto * DMA settings for SSIU 171d9288d0bSKuninori Morimoto */ 172d9288d0bSKuninori Morimoto if (use_busif) { 1731cc71959SKuninori Morimoto u32 val = 0x76543210; 1741cc71959SKuninori Morimoto u32 mask = ~0; 1751cc71959SKuninori Morimoto 176d9288d0bSKuninori Morimoto rsnd_mod_write(ssi_mod, SSI_BUSIF_ADINR, 177d9288d0bSKuninori Morimoto rsnd_get_adinr(ssi_mod)); 178d9288d0bSKuninori Morimoto rsnd_mod_write(ssi_mod, SSI_BUSIF_MODE, 1); 179d9288d0bSKuninori Morimoto rsnd_mod_write(ssi_mod, SSI_CTRL, 0x1); 1801cc71959SKuninori Morimoto 1811cc71959SKuninori Morimoto mask <<= runtime->channels * 4; 1821cc71959SKuninori Morimoto val = val & mask; 1831cc71959SKuninori Morimoto 1841cc71959SKuninori Morimoto switch (runtime->sample_bits) { 1851cc71959SKuninori Morimoto case 16: 1861cc71959SKuninori Morimoto val |= 0x67452301 & ~mask; 1871cc71959SKuninori Morimoto break; 1881cc71959SKuninori Morimoto case 32: 1891cc71959SKuninori Morimoto val |= 0x76543210 & ~mask; 1901cc71959SKuninori Morimoto break; 1911cc71959SKuninori Morimoto } 1921cc71959SKuninori Morimoto rsnd_mod_write(ssi_mod, BUSIF_DALIGN, val); 1931cc71959SKuninori Morimoto 194d9288d0bSKuninori Morimoto } 195d9288d0bSKuninori Morimoto 196d9288d0bSKuninori Morimoto return 0; 197d9288d0bSKuninori Morimoto } 198d9288d0bSKuninori Morimoto 199f708d944SKuninori Morimoto int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod) 200d9288d0bSKuninori Morimoto { 201d9288d0bSKuninori Morimoto /* 202d9288d0bSKuninori Morimoto * DMA settings for SSIU 203d9288d0bSKuninori Morimoto */ 204d9288d0bSKuninori Morimoto rsnd_mod_write(ssi_mod, SSI_CTRL, 0); 205d9288d0bSKuninori Morimoto 206ba9c949fSKuninori Morimoto return 0; 207ba9c949fSKuninori Morimoto } 208ba9c949fSKuninori Morimoto 209f708d944SKuninori Morimoto int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod) 210ba9c949fSKuninori Morimoto { 211ba9c949fSKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); 212ba9c949fSKuninori Morimoto 213c17dba8bSKuninori Morimoto if (rsnd_is_gen1(priv)) 214c17dba8bSKuninori Morimoto return 0; 215c17dba8bSKuninori Morimoto 216c17dba8bSKuninori Morimoto /* enable SSI interrupt if Gen2 */ 217c17dba8bSKuninori Morimoto if (rsnd_ssi_is_dma_mode(ssi_mod)) 218c17dba8bSKuninori Morimoto rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0e000000); 219c17dba8bSKuninori Morimoto else 220ba9c949fSKuninori Morimoto rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0f000000); 221ba9c949fSKuninori Morimoto 222ba9c949fSKuninori Morimoto return 0; 223ba9c949fSKuninori Morimoto } 224ba9c949fSKuninori Morimoto 225f708d944SKuninori Morimoto int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod) 226c17dba8bSKuninori Morimoto { 227c17dba8bSKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); 228c17dba8bSKuninori Morimoto 229c17dba8bSKuninori Morimoto if (rsnd_is_gen1(priv)) 230c17dba8bSKuninori Morimoto return 0; 231c17dba8bSKuninori Morimoto 232c17dba8bSKuninori Morimoto /* disable SSI interrupt if Gen2 */ 233c17dba8bSKuninori Morimoto rsnd_mod_write(ssi_mod, INT_ENABLE, 0x00000000); 234c17dba8bSKuninori Morimoto 235c17dba8bSKuninori Morimoto return 0; 236c17dba8bSKuninori Morimoto } 237c17dba8bSKuninori Morimoto 23843cb6954SKuninori Morimoto static u32 rsnd_src_convert_rate(struct rsnd_src *src) 23943cb6954SKuninori Morimoto { 24043cb6954SKuninori Morimoto struct rsnd_mod *mod = &src->mod; 24143cb6954SKuninori Morimoto struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); 24243cb6954SKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 24343cb6954SKuninori Morimoto u32 convert_rate; 24443cb6954SKuninori Morimoto 24543cb6954SKuninori Morimoto if (!runtime) 24643cb6954SKuninori Morimoto return 0; 24743cb6954SKuninori Morimoto 24843cb6954SKuninori Morimoto if (!rsnd_enable_sync_convert(src)) 24943cb6954SKuninori Morimoto return src->convert_rate; 25043cb6954SKuninori Morimoto 25143cb6954SKuninori Morimoto convert_rate = src->sync.val; 25243cb6954SKuninori Morimoto 25343cb6954SKuninori Morimoto if (!convert_rate) 25443cb6954SKuninori Morimoto convert_rate = src->convert_rate; 25543cb6954SKuninori Morimoto 25643cb6954SKuninori Morimoto if (!convert_rate) 25743cb6954SKuninori Morimoto convert_rate = runtime->rate; 25843cb6954SKuninori Morimoto 25943cb6954SKuninori Morimoto return convert_rate; 26043cb6954SKuninori Morimoto } 26143cb6954SKuninori Morimoto 262ba9c949fSKuninori Morimoto unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, 263ba9c949fSKuninori Morimoto struct rsnd_dai_stream *io, 264ba9c949fSKuninori Morimoto struct snd_pcm_runtime *runtime) 265ba9c949fSKuninori Morimoto { 266b1eac430SKuninori Morimoto struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); 267ba9c949fSKuninori Morimoto struct rsnd_src *src; 268b1eac430SKuninori Morimoto unsigned int rate = 0; 269ba9c949fSKuninori Morimoto 270b1eac430SKuninori Morimoto if (src_mod) { 271b1eac430SKuninori Morimoto src = rsnd_mod_to_src(src_mod); 272ba9c949fSKuninori Morimoto 273ba9c949fSKuninori Morimoto /* 274ba9c949fSKuninori Morimoto * return convert rate if SRC is used, 275ba9c949fSKuninori Morimoto * otherwise, return runtime->rate as usual 276ba9c949fSKuninori Morimoto */ 277ba9c949fSKuninori Morimoto rate = rsnd_src_convert_rate(src); 278b1eac430SKuninori Morimoto } 279b1eac430SKuninori Morimoto 280ba9c949fSKuninori Morimoto if (!rate) 281ba9c949fSKuninori Morimoto rate = runtime->rate; 282ba9c949fSKuninori Morimoto 283ba9c949fSKuninori Morimoto return rate; 284ba9c949fSKuninori Morimoto } 285ba9c949fSKuninori Morimoto 286f708d944SKuninori Morimoto static int rsnd_src_set_convert_rate(struct rsnd_mod *mod) 287ba9c949fSKuninori Morimoto { 288b42fccf6SKuninori Morimoto struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); 289ba9c949fSKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 290ba9c949fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 291ba9c949fSKuninori Morimoto u32 convert_rate = rsnd_src_convert_rate(src); 292ba9c949fSKuninori Morimoto u32 fsrate = 0; 293ba9c949fSKuninori Morimoto 294ba9c949fSKuninori Morimoto if (convert_rate) 295ba9c949fSKuninori Morimoto fsrate = 0x0400000 / convert_rate * runtime->rate; 296ba9c949fSKuninori Morimoto 297ba9c949fSKuninori Morimoto /* set/clear soft reset */ 298ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_SWRSR, 0); 299ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_SWRSR, 1); 300ba9c949fSKuninori Morimoto 301ba9c949fSKuninori Morimoto /* Set channel number and output bit length */ 302d7bdbc5dSKuninori Morimoto rsnd_mod_write(mod, SRC_ADINR, rsnd_get_adinr(mod)); 303ba9c949fSKuninori Morimoto 304ba9c949fSKuninori Morimoto /* Enable the initial value of IFS */ 305ba9c949fSKuninori Morimoto if (fsrate) { 306ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_IFSCR, 1); 307ba9c949fSKuninori Morimoto 308ba9c949fSKuninori Morimoto /* Set initial value of IFS */ 309ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_IFSVR, fsrate); 310ba9c949fSKuninori Morimoto } 311ba9c949fSKuninori Morimoto 312ba9c949fSKuninori Morimoto /* use DMA transfer */ 313ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_BUSIF_MODE, 1); 314ba9c949fSKuninori Morimoto 315ba9c949fSKuninori Morimoto return 0; 316ba9c949fSKuninori Morimoto } 317ba9c949fSKuninori Morimoto 3183b7843ffSKuninori Morimoto static int rsnd_src_hw_params(struct rsnd_mod *mod, 319*2c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 3203b7843ffSKuninori Morimoto struct snd_pcm_substream *substream, 3213b7843ffSKuninori Morimoto struct snd_pcm_hw_params *fe_params) 3223b7843ffSKuninori Morimoto { 3233b7843ffSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 3243b7843ffSKuninori Morimoto struct snd_soc_pcm_runtime *fe = substream->private_data; 3253b7843ffSKuninori Morimoto 3263b7843ffSKuninori Morimoto /* default value (mainly for non-DT) */ 3273b7843ffSKuninori Morimoto src->convert_rate = src->info->convert_rate; 3283b7843ffSKuninori Morimoto 3293b7843ffSKuninori Morimoto /* 3303b7843ffSKuninori Morimoto * SRC assumes that it is used under DPCM if user want to use 3313b7843ffSKuninori Morimoto * sampling rate convert. Then, SRC should be FE. 3323b7843ffSKuninori Morimoto * And then, this function will be called *after* BE settings. 3333b7843ffSKuninori Morimoto * this means, each BE already has fixuped hw_params. 3343b7843ffSKuninori Morimoto * see 3353b7843ffSKuninori Morimoto * dpcm_fe_dai_hw_params() 3363b7843ffSKuninori Morimoto * dpcm_be_dai_hw_params() 3373b7843ffSKuninori Morimoto */ 3383b7843ffSKuninori Morimoto if (fe->dai_link->dynamic) { 3393b7843ffSKuninori Morimoto int stream = substream->stream; 3403b7843ffSKuninori Morimoto struct snd_soc_dpcm *dpcm; 3413b7843ffSKuninori Morimoto struct snd_pcm_hw_params *be_params; 3423b7843ffSKuninori Morimoto 3433b7843ffSKuninori Morimoto list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { 3443b7843ffSKuninori Morimoto be_params = &dpcm->hw_params; 3453b7843ffSKuninori Morimoto 3463b7843ffSKuninori Morimoto if (params_rate(fe_params) != params_rate(be_params)) 3473b7843ffSKuninori Morimoto src->convert_rate = params_rate(be_params); 3483b7843ffSKuninori Morimoto } 3493b7843ffSKuninori Morimoto } 3503b7843ffSKuninori Morimoto 3513b7843ffSKuninori Morimoto return 0; 3523b7843ffSKuninori Morimoto } 3533b7843ffSKuninori Morimoto 3543b7843ffSKuninori Morimoto static int rsnd_src_init(struct rsnd_mod *mod, 3553b7843ffSKuninori Morimoto struct rsnd_priv *priv) 356ba9c949fSKuninori Morimoto { 357ba9c949fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 358ba9c949fSKuninori Morimoto 35985642952SKuninori Morimoto rsnd_mod_hw_start(mod); 360ba9c949fSKuninori Morimoto 361cfcefe01SKuninori Morimoto src->err = 0; 362cfcefe01SKuninori Morimoto 36343cb6954SKuninori Morimoto /* reset sync convert_rate */ 36443cb6954SKuninori Morimoto src->sync.val = 0; 36543cb6954SKuninori Morimoto 366603cefa5SKuninori Morimoto /* 367603cefa5SKuninori Morimoto * Initialize the operation of the SRC internal circuits 368603cefa5SKuninori Morimoto * see rsnd_src_start() 369603cefa5SKuninori Morimoto */ 370603cefa5SKuninori Morimoto rsnd_mod_write(mod, SRC_SRCIR, 1); 371603cefa5SKuninori Morimoto 372ba9c949fSKuninori Morimoto return 0; 373ba9c949fSKuninori Morimoto } 374ba9c949fSKuninori Morimoto 375ba9c949fSKuninori Morimoto static int rsnd_src_quit(struct rsnd_mod *mod, 376*2c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 377690602fcSKuninori Morimoto struct rsnd_priv *priv) 378ba9c949fSKuninori Morimoto { 379ba9c949fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 380cfcefe01SKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 381ba9c949fSKuninori Morimoto 38285642952SKuninori Morimoto rsnd_mod_hw_stop(mod); 383ba9c949fSKuninori Morimoto 384cfcefe01SKuninori Morimoto if (src->err) 385337b0b4cSKuninori Morimoto dev_warn(dev, "%s[%d] under/over flow err = %d\n", 386337b0b4cSKuninori Morimoto rsnd_mod_name(mod), rsnd_mod_id(mod), src->err); 387cfcefe01SKuninori Morimoto 3883b7843ffSKuninori Morimoto src->convert_rate = 0; 3893b7843ffSKuninori Morimoto 39043cb6954SKuninori Morimoto /* reset sync convert_rate */ 39143cb6954SKuninori Morimoto src->sync.val = 0; 39243cb6954SKuninori Morimoto 393ba9c949fSKuninori Morimoto return 0; 394ba9c949fSKuninori Morimoto } 395ba9c949fSKuninori Morimoto 396f0ef0cb8SKuninori Morimoto static int rsnd_src_start(struct rsnd_mod *mod) 397ba9c949fSKuninori Morimoto { 398ba9c949fSKuninori Morimoto /* 399ba9c949fSKuninori Morimoto * Cancel the initialization and operate the SRC function 400603cefa5SKuninori Morimoto * see rsnd_src_init() 401ba9c949fSKuninori Morimoto */ 402ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_SRCIR, 0); 403ba9c949fSKuninori Morimoto 404ba9c949fSKuninori Morimoto return 0; 405ba9c949fSKuninori Morimoto } 406ba9c949fSKuninori Morimoto 407f0ef0cb8SKuninori Morimoto static int rsnd_src_stop(struct rsnd_mod *mod) 408ba9c949fSKuninori Morimoto { 409933cc8cbSKuninori Morimoto /* nothing to do */ 410ba9c949fSKuninori Morimoto return 0; 411ba9c949fSKuninori Morimoto } 412ba9c949fSKuninori Morimoto 413ba9c949fSKuninori Morimoto /* 414ba9c949fSKuninori Morimoto * Gen1 functions 415ba9c949fSKuninori Morimoto */ 416f708d944SKuninori Morimoto static int rsnd_src_set_route_gen1(struct rsnd_mod *mod) 417ba9c949fSKuninori Morimoto { 418b42fccf6SKuninori Morimoto struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); 419ba9c949fSKuninori Morimoto struct src_route_config { 420ba9c949fSKuninori Morimoto u32 mask; 421ba9c949fSKuninori Morimoto int shift; 422ba9c949fSKuninori Morimoto } routes[] = { 423ba9c949fSKuninori Morimoto { 0xF, 0, }, /* 0 */ 424ba9c949fSKuninori Morimoto { 0xF, 4, }, /* 1 */ 425ba9c949fSKuninori Morimoto { 0xF, 8, }, /* 2 */ 426ba9c949fSKuninori Morimoto { 0x7, 12, }, /* 3 */ 427ba9c949fSKuninori Morimoto { 0x7, 16, }, /* 4 */ 428ba9c949fSKuninori Morimoto { 0x7, 20, }, /* 5 */ 429ba9c949fSKuninori Morimoto { 0x7, 24, }, /* 6 */ 430ba9c949fSKuninori Morimoto { 0x3, 28, }, /* 7 */ 431ba9c949fSKuninori Morimoto { 0x3, 30, }, /* 8 */ 432ba9c949fSKuninori Morimoto }; 433ba9c949fSKuninori Morimoto u32 mask; 434ba9c949fSKuninori Morimoto u32 val; 435ba9c949fSKuninori Morimoto int id; 436ba9c949fSKuninori Morimoto 437ba9c949fSKuninori Morimoto id = rsnd_mod_id(mod); 438ba9c949fSKuninori Morimoto if (id < 0 || id >= ARRAY_SIZE(routes)) 439ba9c949fSKuninori Morimoto return -EIO; 440ba9c949fSKuninori Morimoto 441ba9c949fSKuninori Morimoto /* 442ba9c949fSKuninori Morimoto * SRC_ROUTE_SELECT 443ba9c949fSKuninori Morimoto */ 444985a4f6eSKuninori Morimoto val = rsnd_io_is_play(io) ? 0x1 : 0x2; 445ba9c949fSKuninori Morimoto val = val << routes[id].shift; 446ba9c949fSKuninori Morimoto mask = routes[id].mask << routes[id].shift; 447ba9c949fSKuninori Morimoto 448ba9c949fSKuninori Morimoto rsnd_mod_bset(mod, SRC_ROUTE_SEL, mask, val); 449ba9c949fSKuninori Morimoto 450ba9c949fSKuninori Morimoto return 0; 451ba9c949fSKuninori Morimoto } 452ba9c949fSKuninori Morimoto 453f708d944SKuninori Morimoto static int rsnd_src_set_convert_timing_gen1(struct rsnd_mod *mod) 454ba9c949fSKuninori Morimoto { 455b42fccf6SKuninori Morimoto struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); 456ba9c949fSKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 457ba9c949fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 458ba9c949fSKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 459ba9c949fSKuninori Morimoto u32 convert_rate = rsnd_src_convert_rate(src); 460ba9c949fSKuninori Morimoto u32 mask; 461ba9c949fSKuninori Morimoto u32 val; 462ba9c949fSKuninori Morimoto int shift; 463ba9c949fSKuninori Morimoto int id = rsnd_mod_id(mod); 464ba9c949fSKuninori Morimoto int ret; 465ba9c949fSKuninori Morimoto 466ba9c949fSKuninori Morimoto /* 467ba9c949fSKuninori Morimoto * SRC_TIMING_SELECT 468ba9c949fSKuninori Morimoto */ 469ba9c949fSKuninori Morimoto shift = (id % 4) * 8; 470ba9c949fSKuninori Morimoto mask = 0x1F << shift; 471ba9c949fSKuninori Morimoto 472ba9c949fSKuninori Morimoto /* 473ba9c949fSKuninori Morimoto * ADG is used as source clock if SRC was used, 474ba9c949fSKuninori Morimoto * then, SSI WS is used as destination clock. 475ba9c949fSKuninori Morimoto * SSI WS is used as source clock if SRC is not used 476ba9c949fSKuninori Morimoto * (when playback, source/destination become reverse when capture) 477ba9c949fSKuninori Morimoto */ 478ba9c949fSKuninori Morimoto ret = 0; 479ba9c949fSKuninori Morimoto if (convert_rate) { 480ba9c949fSKuninori Morimoto /* use ADG */ 481ba9c949fSKuninori Morimoto val = 0; 482ba9c949fSKuninori Morimoto ret = rsnd_adg_set_convert_clk_gen1(priv, mod, 483ba9c949fSKuninori Morimoto runtime->rate, 484ba9c949fSKuninori Morimoto convert_rate); 485ba9c949fSKuninori Morimoto } else if (8 == id) { 486ba9c949fSKuninori Morimoto /* use SSI WS, but SRU8 is special */ 487ba9c949fSKuninori Morimoto val = id << shift; 488ba9c949fSKuninori Morimoto } else { 489ba9c949fSKuninori Morimoto /* use SSI WS */ 490ba9c949fSKuninori Morimoto val = (id + 1) << shift; 491ba9c949fSKuninori Morimoto } 492ba9c949fSKuninori Morimoto 493ba9c949fSKuninori Morimoto if (ret < 0) 494ba9c949fSKuninori Morimoto return ret; 495ba9c949fSKuninori Morimoto 496ba9c949fSKuninori Morimoto switch (id / 4) { 497ba9c949fSKuninori Morimoto case 0: 498ba9c949fSKuninori Morimoto rsnd_mod_bset(mod, SRC_TMG_SEL0, mask, val); 499ba9c949fSKuninori Morimoto break; 500ba9c949fSKuninori Morimoto case 1: 501ba9c949fSKuninori Morimoto rsnd_mod_bset(mod, SRC_TMG_SEL1, mask, val); 502ba9c949fSKuninori Morimoto break; 503ba9c949fSKuninori Morimoto case 2: 504ba9c949fSKuninori Morimoto rsnd_mod_bset(mod, SRC_TMG_SEL2, mask, val); 505ba9c949fSKuninori Morimoto break; 506ba9c949fSKuninori Morimoto } 507ba9c949fSKuninori Morimoto 508ba9c949fSKuninori Morimoto return 0; 509ba9c949fSKuninori Morimoto } 510ba9c949fSKuninori Morimoto 511f708d944SKuninori Morimoto static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod) 512ba9c949fSKuninori Morimoto { 513933cc8cbSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 514ba9c949fSKuninori Morimoto int ret; 515ba9c949fSKuninori Morimoto 516f708d944SKuninori Morimoto ret = rsnd_src_set_convert_rate(mod); 517ba9c949fSKuninori Morimoto if (ret < 0) 518ba9c949fSKuninori Morimoto return ret; 519ba9c949fSKuninori Morimoto 520ba9c949fSKuninori Morimoto /* Select SRC mode (fixed value) */ 521ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_SRCCR, 0x00010110); 522ba9c949fSKuninori Morimoto 523ba9c949fSKuninori Morimoto /* Set the restriction value of the FS ratio (98%) */ 524ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_MNFSR, 525ba9c949fSKuninori Morimoto rsnd_mod_read(mod, SRC_IFSVR) / 100 * 98); 526ba9c949fSKuninori Morimoto 527933cc8cbSKuninori Morimoto /* Gen1/Gen2 are not compatible */ 528933cc8cbSKuninori Morimoto if (rsnd_src_convert_rate(src)) 529933cc8cbSKuninori Morimoto rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); 530933cc8cbSKuninori Morimoto 531ba9c949fSKuninori Morimoto /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ 532ba9c949fSKuninori Morimoto 533ba9c949fSKuninori Morimoto return 0; 534ba9c949fSKuninori Morimoto } 535ba9c949fSKuninori Morimoto 536ba9c949fSKuninori Morimoto static int rsnd_src_init_gen1(struct rsnd_mod *mod, 537*2c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 538690602fcSKuninori Morimoto struct rsnd_priv *priv) 539ba9c949fSKuninori Morimoto { 540ba9c949fSKuninori Morimoto int ret; 541ba9c949fSKuninori Morimoto 5423b7843ffSKuninori Morimoto ret = rsnd_src_init(mod, priv); 543ba9c949fSKuninori Morimoto if (ret < 0) 544ba9c949fSKuninori Morimoto return ret; 545ba9c949fSKuninori Morimoto 546f708d944SKuninori Morimoto ret = rsnd_src_set_route_gen1(mod); 547ba9c949fSKuninori Morimoto if (ret < 0) 548ba9c949fSKuninori Morimoto return ret; 549ba9c949fSKuninori Morimoto 550f708d944SKuninori Morimoto ret = rsnd_src_set_convert_rate_gen1(mod); 551ba9c949fSKuninori Morimoto if (ret < 0) 552ba9c949fSKuninori Morimoto return ret; 553ba9c949fSKuninori Morimoto 554f708d944SKuninori Morimoto ret = rsnd_src_set_convert_timing_gen1(mod); 555ba9c949fSKuninori Morimoto if (ret < 0) 556ba9c949fSKuninori Morimoto return ret; 557ba9c949fSKuninori Morimoto 558ba9c949fSKuninori Morimoto return 0; 559ba9c949fSKuninori Morimoto } 560ba9c949fSKuninori Morimoto 561ba9c949fSKuninori Morimoto static int rsnd_src_start_gen1(struct rsnd_mod *mod, 562*2c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 563690602fcSKuninori Morimoto struct rsnd_priv *priv) 564ba9c949fSKuninori Morimoto { 565ba9c949fSKuninori Morimoto int id = rsnd_mod_id(mod); 566ba9c949fSKuninori Morimoto 567ba9c949fSKuninori Morimoto rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id)); 568ba9c949fSKuninori Morimoto 569f0ef0cb8SKuninori Morimoto return rsnd_src_start(mod); 570ba9c949fSKuninori Morimoto } 571ba9c949fSKuninori Morimoto 572ba9c949fSKuninori Morimoto static int rsnd_src_stop_gen1(struct rsnd_mod *mod, 573*2c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 574690602fcSKuninori Morimoto struct rsnd_priv *priv) 575ba9c949fSKuninori Morimoto { 576ba9c949fSKuninori Morimoto int id = rsnd_mod_id(mod); 577ba9c949fSKuninori Morimoto 578ba9c949fSKuninori Morimoto rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0); 579ba9c949fSKuninori Morimoto 580f0ef0cb8SKuninori Morimoto return rsnd_src_stop(mod); 581ba9c949fSKuninori Morimoto } 582ba9c949fSKuninori Morimoto 583ba9c949fSKuninori Morimoto static struct rsnd_mod_ops rsnd_src_gen1_ops = { 5848aefda50SKuninori Morimoto .name = SRC_NAME, 58572adc61fSKuninori Morimoto .dma_req = rsnd_src_dma_req, 586ba9c949fSKuninori Morimoto .init = rsnd_src_init_gen1, 587ba9c949fSKuninori Morimoto .quit = rsnd_src_quit, 588ba9c949fSKuninori Morimoto .start = rsnd_src_start_gen1, 589ba9c949fSKuninori Morimoto .stop = rsnd_src_stop_gen1, 5903b7843ffSKuninori Morimoto .hw_params = rsnd_src_hw_params, 591ba9c949fSKuninori Morimoto }; 592ba9c949fSKuninori Morimoto 593ba9c949fSKuninori Morimoto /* 594ba9c949fSKuninori Morimoto * Gen2 functions 595ba9c949fSKuninori Morimoto */ 596cfcefe01SKuninori Morimoto #define rsnd_src_irq_enable_gen2(mod) rsnd_src_irq_ctrol_gen2(mod, 1) 597cfcefe01SKuninori Morimoto #define rsnd_src_irq_disable_gen2(mod) rsnd_src_irq_ctrol_gen2(mod, 0) 598cfcefe01SKuninori Morimoto static void rsnd_src_irq_ctrol_gen2(struct rsnd_mod *mod, int enable) 599cfcefe01SKuninori Morimoto { 600cfcefe01SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 601cfcefe01SKuninori Morimoto u32 sys_int_val, int_val, sys_int_mask; 602cfcefe01SKuninori Morimoto int irq = src->info->irq; 603cfcefe01SKuninori Morimoto int id = rsnd_mod_id(mod); 604cfcefe01SKuninori Morimoto 605cfcefe01SKuninori Morimoto sys_int_val = 606cfcefe01SKuninori Morimoto sys_int_mask = OUF_SRC(id); 607cfcefe01SKuninori Morimoto int_val = 0x3300; 608cfcefe01SKuninori Morimoto 609cfcefe01SKuninori Morimoto /* 610cfcefe01SKuninori Morimoto * IRQ is not supported on non-DT 611cfcefe01SKuninori Morimoto * see 612cfcefe01SKuninori Morimoto * rsnd_src_probe_gen2() 613cfcefe01SKuninori Morimoto */ 614cfcefe01SKuninori Morimoto if ((irq <= 0) || !enable) { 615cfcefe01SKuninori Morimoto sys_int_val = 0; 616cfcefe01SKuninori Morimoto int_val = 0; 617cfcefe01SKuninori Morimoto } 618cfcefe01SKuninori Morimoto 619cfcefe01SKuninori Morimoto rsnd_mod_write(mod, SRC_INT_ENABLE0, int_val); 620cfcefe01SKuninori Morimoto rsnd_mod_bset(mod, SCU_SYS_INT_EN0, sys_int_mask, sys_int_val); 621cfcefe01SKuninori Morimoto rsnd_mod_bset(mod, SCU_SYS_INT_EN1, sys_int_mask, sys_int_val); 622cfcefe01SKuninori Morimoto } 623cfcefe01SKuninori Morimoto 624cfcefe01SKuninori Morimoto static void rsnd_src_error_clear_gen2(struct rsnd_mod *mod) 625cfcefe01SKuninori Morimoto { 626cfcefe01SKuninori Morimoto u32 val = OUF_SRC(rsnd_mod_id(mod)); 627cfcefe01SKuninori Morimoto 628cfcefe01SKuninori Morimoto rsnd_mod_bset(mod, SCU_SYS_STATUS0, val, val); 629cfcefe01SKuninori Morimoto rsnd_mod_bset(mod, SCU_SYS_STATUS1, val, val); 630cfcefe01SKuninori Morimoto } 631cfcefe01SKuninori Morimoto 632cfcefe01SKuninori Morimoto static bool rsnd_src_error_record_gen2(struct rsnd_mod *mod) 633cfcefe01SKuninori Morimoto { 634cfcefe01SKuninori Morimoto u32 val = OUF_SRC(rsnd_mod_id(mod)); 635cfcefe01SKuninori Morimoto bool ret = false; 636cfcefe01SKuninori Morimoto 637cfcefe01SKuninori Morimoto if ((rsnd_mod_read(mod, SCU_SYS_STATUS0) & val) || 638cfcefe01SKuninori Morimoto (rsnd_mod_read(mod, SCU_SYS_STATUS1) & val)) { 639cfcefe01SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 640cfcefe01SKuninori Morimoto 641cfcefe01SKuninori Morimoto src->err++; 642cfcefe01SKuninori Morimoto ret = true; 643cfcefe01SKuninori Morimoto } 644cfcefe01SKuninori Morimoto 645cfcefe01SKuninori Morimoto /* clear error static */ 646cfcefe01SKuninori Morimoto rsnd_src_error_clear_gen2(mod); 647cfcefe01SKuninori Morimoto 648cfcefe01SKuninori Morimoto return ret; 649cfcefe01SKuninori Morimoto } 650cfcefe01SKuninori Morimoto 651cfcefe01SKuninori Morimoto static int _rsnd_src_start_gen2(struct rsnd_mod *mod) 652cfcefe01SKuninori Morimoto { 653cfcefe01SKuninori Morimoto struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); 654cfcefe01SKuninori Morimoto u32 val = rsnd_io_to_mod_dvc(io) ? 0x01 : 0x11; 655cfcefe01SKuninori Morimoto 656cfcefe01SKuninori Morimoto rsnd_mod_write(mod, SRC_CTRL, val); 657cfcefe01SKuninori Morimoto 658cfcefe01SKuninori Morimoto rsnd_src_error_clear_gen2(mod); 659cfcefe01SKuninori Morimoto 660cfcefe01SKuninori Morimoto rsnd_src_start(mod); 661cfcefe01SKuninori Morimoto 662cfcefe01SKuninori Morimoto rsnd_src_irq_enable_gen2(mod); 663cfcefe01SKuninori Morimoto 664cfcefe01SKuninori Morimoto return 0; 665cfcefe01SKuninori Morimoto } 666cfcefe01SKuninori Morimoto 667cfcefe01SKuninori Morimoto static int _rsnd_src_stop_gen2(struct rsnd_mod *mod) 668cfcefe01SKuninori Morimoto { 669cfcefe01SKuninori Morimoto rsnd_src_irq_disable_gen2(mod); 670cfcefe01SKuninori Morimoto 671cfcefe01SKuninori Morimoto rsnd_mod_write(mod, SRC_CTRL, 0); 672cfcefe01SKuninori Morimoto 673cfcefe01SKuninori Morimoto rsnd_src_error_record_gen2(mod); 674cfcefe01SKuninori Morimoto 675cfcefe01SKuninori Morimoto return rsnd_src_stop(mod); 676cfcefe01SKuninori Morimoto } 677cfcefe01SKuninori Morimoto 678cfcefe01SKuninori Morimoto static irqreturn_t rsnd_src_interrupt_gen2(int irq, void *data) 679cfcefe01SKuninori Morimoto { 680cfcefe01SKuninori Morimoto struct rsnd_mod *mod = data; 68102299d98SKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 682cfcefe01SKuninori Morimoto 68302299d98SKuninori Morimoto spin_lock(&priv->lock); 68402299d98SKuninori Morimoto 68502299d98SKuninori Morimoto /* ignore all cases if not working */ 68602299d98SKuninori Morimoto if (!rsnd_mod_is_working(mod)) 68702299d98SKuninori Morimoto goto rsnd_src_interrupt_gen2_out; 688cfcefe01SKuninori Morimoto 689cfcefe01SKuninori Morimoto if (rsnd_src_error_record_gen2(mod)) { 690cfcefe01SKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 691639b231fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 692cfcefe01SKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 693cfcefe01SKuninori Morimoto 694cfcefe01SKuninori Morimoto dev_dbg(dev, "%s[%d] restart\n", 695cfcefe01SKuninori Morimoto rsnd_mod_name(mod), rsnd_mod_id(mod)); 696639b231fSKuninori Morimoto 697639b231fSKuninori Morimoto _rsnd_src_stop_gen2(mod); 698639b231fSKuninori Morimoto if (src->err < 1024) 699639b231fSKuninori Morimoto _rsnd_src_start_gen2(mod); 700639b231fSKuninori Morimoto else 701639b231fSKuninori Morimoto dev_warn(dev, "no more SRC restart\n"); 702cfcefe01SKuninori Morimoto } 70302299d98SKuninori Morimoto rsnd_src_interrupt_gen2_out: 70402299d98SKuninori Morimoto spin_unlock(&priv->lock); 705cfcefe01SKuninori Morimoto 706cfcefe01SKuninori Morimoto return IRQ_HANDLED; 707cfcefe01SKuninori Morimoto } 708cfcefe01SKuninori Morimoto 709f708d944SKuninori Morimoto static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod) 710ba9c949fSKuninori Morimoto { 711054cd7f4SKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 712054cd7f4SKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 713054cd7f4SKuninori Morimoto struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); 714054cd7f4SKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 715054cd7f4SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 716b167a578SKuninori Morimoto u32 convert_rate = rsnd_src_convert_rate(src); 71743cb6954SKuninori Morimoto u32 cr, route; 718054cd7f4SKuninori Morimoto uint ratio; 719ba9c949fSKuninori Morimoto int ret; 720ba9c949fSKuninori Morimoto 721054cd7f4SKuninori Morimoto /* 6 - 1/6 are very enough ratio for SRC_BSDSR */ 722b167a578SKuninori Morimoto if (!convert_rate) 723054cd7f4SKuninori Morimoto ratio = 0; 724b167a578SKuninori Morimoto else if (convert_rate > runtime->rate) 725b167a578SKuninori Morimoto ratio = 100 * convert_rate / runtime->rate; 726054cd7f4SKuninori Morimoto else 727b167a578SKuninori Morimoto ratio = 100 * runtime->rate / convert_rate; 728054cd7f4SKuninori Morimoto 729054cd7f4SKuninori Morimoto if (ratio > 600) { 730054cd7f4SKuninori Morimoto dev_err(dev, "FSO/FSI ratio error\n"); 731054cd7f4SKuninori Morimoto return -EINVAL; 732054cd7f4SKuninori Morimoto } 733054cd7f4SKuninori Morimoto 734f708d944SKuninori Morimoto ret = rsnd_src_set_convert_rate(mod); 735ba9c949fSKuninori Morimoto if (ret < 0) 736ba9c949fSKuninori Morimoto return ret; 737ba9c949fSKuninori Morimoto 73843cb6954SKuninori Morimoto cr = 0x00011110; 73943cb6954SKuninori Morimoto route = 0x0; 740933cc8cbSKuninori Morimoto if (convert_rate) { 74143cb6954SKuninori Morimoto route = 0x1; 74243cb6954SKuninori Morimoto 74343cb6954SKuninori Morimoto if (rsnd_enable_sync_convert(src)) { 74443cb6954SKuninori Morimoto cr |= 0x1; 74543cb6954SKuninori Morimoto route |= rsnd_io_is_play(io) ? 74643cb6954SKuninori Morimoto (0x1 << 24) : (0x1 << 25); 747933cc8cbSKuninori Morimoto } 74843cb6954SKuninori Morimoto } 74943cb6954SKuninori Morimoto 75043cb6954SKuninori Morimoto rsnd_mod_write(mod, SRC_SRCCR, cr); 75143cb6954SKuninori Morimoto rsnd_mod_write(mod, SRC_ROUTE_MODE0, route); 752933cc8cbSKuninori Morimoto 753054cd7f4SKuninori Morimoto switch (rsnd_mod_id(mod)) { 754054cd7f4SKuninori Morimoto case 5: 755054cd7f4SKuninori Morimoto case 6: 756054cd7f4SKuninori Morimoto case 7: 757054cd7f4SKuninori Morimoto case 8: 758054cd7f4SKuninori Morimoto rsnd_mod_write(mod, SRC_BSDSR, 0x02400000); 759054cd7f4SKuninori Morimoto break; 760054cd7f4SKuninori Morimoto default: 761ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_BSDSR, 0x01800000); 762054cd7f4SKuninori Morimoto break; 763054cd7f4SKuninori Morimoto } 764054cd7f4SKuninori Morimoto 765ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_BSISR, 0x00100060); 766ba9c949fSKuninori Morimoto 767ba9c949fSKuninori Morimoto return 0; 768ba9c949fSKuninori Morimoto } 769ba9c949fSKuninori Morimoto 770f708d944SKuninori Morimoto static int rsnd_src_set_convert_timing_gen2(struct rsnd_mod *mod) 771ba9c949fSKuninori Morimoto { 772b42fccf6SKuninori Morimoto struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); 773ba9c949fSKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 774ba9c949fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 775ba9c949fSKuninori Morimoto u32 convert_rate = rsnd_src_convert_rate(src); 776ba9c949fSKuninori Morimoto int ret; 777ba9c949fSKuninori Morimoto 778ba9c949fSKuninori Morimoto if (convert_rate) 779f708d944SKuninori Morimoto ret = rsnd_adg_set_convert_clk_gen2(mod, io, 780ba9c949fSKuninori Morimoto runtime->rate, 781ba9c949fSKuninori Morimoto convert_rate); 782ba9c949fSKuninori Morimoto else 783f708d944SKuninori Morimoto ret = rsnd_adg_set_convert_timing_gen2(mod, io); 784ba9c949fSKuninori Morimoto 785ba9c949fSKuninori Morimoto return ret; 786ba9c949fSKuninori Morimoto } 787ba9c949fSKuninori Morimoto 788ba9c949fSKuninori Morimoto static int rsnd_src_probe_gen2(struct rsnd_mod *mod, 789*2c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 790690602fcSKuninori Morimoto struct rsnd_priv *priv) 791ba9c949fSKuninori Morimoto { 792ba9c949fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 793ba9c949fSKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 794cfcefe01SKuninori Morimoto int irq = src->info->irq; 795ba9c949fSKuninori Morimoto int ret; 796ba9c949fSKuninori Morimoto 797cfcefe01SKuninori Morimoto if (irq > 0) { 798cfcefe01SKuninori Morimoto /* 799cfcefe01SKuninori Morimoto * IRQ is not supported on non-DT 800cfcefe01SKuninori Morimoto * see 801cfcefe01SKuninori Morimoto * rsnd_src_irq_enable_gen2() 802cfcefe01SKuninori Morimoto */ 803cfcefe01SKuninori Morimoto ret = devm_request_irq(dev, irq, 804cfcefe01SKuninori Morimoto rsnd_src_interrupt_gen2, 805cfcefe01SKuninori Morimoto IRQF_SHARED, 806cfcefe01SKuninori Morimoto dev_name(dev), mod); 807cfcefe01SKuninori Morimoto if (ret) 808b543b52aSKuninori Morimoto return ret; 809cfcefe01SKuninori Morimoto } 810cfcefe01SKuninori Morimoto 811ba9c949fSKuninori Morimoto ret = rsnd_dma_init(priv, 812ba9c949fSKuninori Morimoto rsnd_mod_to_dma(mod), 813ba9c949fSKuninori Morimoto src->info->dma_id); 814cfcefe01SKuninori Morimoto 815cfcefe01SKuninori Morimoto return ret; 816ba9c949fSKuninori Morimoto } 817ba9c949fSKuninori Morimoto 818ba9c949fSKuninori Morimoto static int rsnd_src_remove_gen2(struct rsnd_mod *mod, 819*2c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 820690602fcSKuninori Morimoto struct rsnd_priv *priv) 821ba9c949fSKuninori Morimoto { 8228a2ff426SKuninori Morimoto rsnd_dma_quit(rsnd_mod_to_dma(mod)); 823ba9c949fSKuninori Morimoto 824ba9c949fSKuninori Morimoto return 0; 825ba9c949fSKuninori Morimoto } 826ba9c949fSKuninori Morimoto 827ba9c949fSKuninori Morimoto static int rsnd_src_init_gen2(struct rsnd_mod *mod, 828*2c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 829690602fcSKuninori Morimoto struct rsnd_priv *priv) 830ba9c949fSKuninori Morimoto { 831ba9c949fSKuninori Morimoto int ret; 832ba9c949fSKuninori Morimoto 8333b7843ffSKuninori Morimoto ret = rsnd_src_init(mod, priv); 834ba9c949fSKuninori Morimoto if (ret < 0) 835ba9c949fSKuninori Morimoto return ret; 836ba9c949fSKuninori Morimoto 837f708d944SKuninori Morimoto ret = rsnd_src_set_convert_rate_gen2(mod); 838ba9c949fSKuninori Morimoto if (ret < 0) 839ba9c949fSKuninori Morimoto return ret; 840ba9c949fSKuninori Morimoto 841f708d944SKuninori Morimoto ret = rsnd_src_set_convert_timing_gen2(mod); 842ba9c949fSKuninori Morimoto if (ret < 0) 843ba9c949fSKuninori Morimoto return ret; 844ba9c949fSKuninori Morimoto 845ba9c949fSKuninori Morimoto return 0; 846ba9c949fSKuninori Morimoto } 847ba9c949fSKuninori Morimoto 848ba9c949fSKuninori Morimoto static int rsnd_src_start_gen2(struct rsnd_mod *mod, 849*2c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 850690602fcSKuninori Morimoto struct rsnd_priv *priv) 851ba9c949fSKuninori Morimoto { 852cfcefe01SKuninori Morimoto rsnd_dma_start(rsnd_mod_to_dma(mod)); 853ba9c949fSKuninori Morimoto 854cfcefe01SKuninori Morimoto return _rsnd_src_start_gen2(mod); 855ba9c949fSKuninori Morimoto } 856ba9c949fSKuninori Morimoto 857ba9c949fSKuninori Morimoto static int rsnd_src_stop_gen2(struct rsnd_mod *mod, 858*2c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 859690602fcSKuninori Morimoto struct rsnd_priv *priv) 860ba9c949fSKuninori Morimoto { 861cfcefe01SKuninori Morimoto int ret; 862ba9c949fSKuninori Morimoto 863cfcefe01SKuninori Morimoto ret = _rsnd_src_stop_gen2(mod); 864ba9c949fSKuninori Morimoto 865cfcefe01SKuninori Morimoto rsnd_dma_stop(rsnd_mod_to_dma(mod)); 866ba9c949fSKuninori Morimoto 867cfcefe01SKuninori Morimoto return ret; 868ba9c949fSKuninori Morimoto } 869ba9c949fSKuninori Morimoto 87043cb6954SKuninori Morimoto static void rsnd_src_reconvert_update(struct rsnd_mod *mod) 87143cb6954SKuninori Morimoto { 87243cb6954SKuninori Morimoto struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); 87343cb6954SKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 87443cb6954SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 87543cb6954SKuninori Morimoto u32 convert_rate = rsnd_src_convert_rate(src); 87643cb6954SKuninori Morimoto u32 fsrate; 87743cb6954SKuninori Morimoto 87843cb6954SKuninori Morimoto if (!runtime) 87943cb6954SKuninori Morimoto return; 88043cb6954SKuninori Morimoto 88143cb6954SKuninori Morimoto if (!convert_rate) 88243cb6954SKuninori Morimoto convert_rate = runtime->rate; 88343cb6954SKuninori Morimoto 88443cb6954SKuninori Morimoto fsrate = 0x0400000 / convert_rate * runtime->rate; 88543cb6954SKuninori Morimoto 88643cb6954SKuninori Morimoto /* update IFS */ 88743cb6954SKuninori Morimoto rsnd_mod_write(mod, SRC_IFSVR, fsrate); 88843cb6954SKuninori Morimoto } 88943cb6954SKuninori Morimoto 89043cb6954SKuninori Morimoto static int rsnd_src_pcm_new(struct rsnd_mod *mod, 891*2c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 89243cb6954SKuninori Morimoto struct snd_soc_pcm_runtime *rtd) 89343cb6954SKuninori Morimoto { 89443cb6954SKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 89543cb6954SKuninori Morimoto struct rsnd_dai *rdai = rsnd_io_to_rdai(io); 89643cb6954SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 89743cb6954SKuninori Morimoto int ret; 89843cb6954SKuninori Morimoto 89943cb6954SKuninori Morimoto /* 90043cb6954SKuninori Morimoto * enable SRC sync convert if possible 90143cb6954SKuninori Morimoto */ 90243cb6954SKuninori Morimoto 90343cb6954SKuninori Morimoto /* 90443cb6954SKuninori Morimoto * Gen1 is not supported 90543cb6954SKuninori Morimoto */ 90643cb6954SKuninori Morimoto if (rsnd_is_gen1(priv)) 90743cb6954SKuninori Morimoto return 0; 90843cb6954SKuninori Morimoto 90943cb6954SKuninori Morimoto /* 91043cb6954SKuninori Morimoto * SRC sync convert needs clock master 91143cb6954SKuninori Morimoto */ 91243cb6954SKuninori Morimoto if (!rsnd_rdai_is_clk_master(rdai)) 91343cb6954SKuninori Morimoto return 0; 91443cb6954SKuninori Morimoto 91543cb6954SKuninori Morimoto /* 91643cb6954SKuninori Morimoto * We can't use SRC sync convert 91743cb6954SKuninori Morimoto * if it has DVC 91843cb6954SKuninori Morimoto */ 91943cb6954SKuninori Morimoto if (rsnd_io_to_mod_dvc(io)) 92043cb6954SKuninori Morimoto return 0; 92143cb6954SKuninori Morimoto 92243cb6954SKuninori Morimoto /* 92343cb6954SKuninori Morimoto * enable sync convert 92443cb6954SKuninori Morimoto */ 92543cb6954SKuninori Morimoto ret = rsnd_kctrl_new_s(mod, rtd, 92643cb6954SKuninori Morimoto rsnd_io_is_play(io) ? 92743cb6954SKuninori Morimoto "SRC Out Rate Switch" : 92843cb6954SKuninori Morimoto "SRC In Rate Switch", 92943cb6954SKuninori Morimoto rsnd_src_reconvert_update, 93043cb6954SKuninori Morimoto &src->sen, 1); 93143cb6954SKuninori Morimoto if (ret < 0) 93243cb6954SKuninori Morimoto return ret; 93343cb6954SKuninori Morimoto 93443cb6954SKuninori Morimoto ret = rsnd_kctrl_new_s(mod, rtd, 93543cb6954SKuninori Morimoto rsnd_io_is_play(io) ? 93643cb6954SKuninori Morimoto "SRC Out Rate" : 93743cb6954SKuninori Morimoto "SRC In Rate", 93843cb6954SKuninori Morimoto rsnd_src_reconvert_update, 93943cb6954SKuninori Morimoto &src->sync, 192000); 94043cb6954SKuninori Morimoto 94143cb6954SKuninori Morimoto return ret; 94243cb6954SKuninori Morimoto } 94343cb6954SKuninori Morimoto 944ba9c949fSKuninori Morimoto static struct rsnd_mod_ops rsnd_src_gen2_ops = { 9458aefda50SKuninori Morimoto .name = SRC_NAME, 94672adc61fSKuninori Morimoto .dma_req = rsnd_src_dma_req, 947ba9c949fSKuninori Morimoto .probe = rsnd_src_probe_gen2, 948ba9c949fSKuninori Morimoto .remove = rsnd_src_remove_gen2, 949ba9c949fSKuninori Morimoto .init = rsnd_src_init_gen2, 950ba9c949fSKuninori Morimoto .quit = rsnd_src_quit, 951ba9c949fSKuninori Morimoto .start = rsnd_src_start_gen2, 952ba9c949fSKuninori Morimoto .stop = rsnd_src_stop_gen2, 9533b7843ffSKuninori Morimoto .hw_params = rsnd_src_hw_params, 95443cb6954SKuninori Morimoto .pcm_new = rsnd_src_pcm_new, 955ba9c949fSKuninori Morimoto }; 956ba9c949fSKuninori Morimoto 957ba9c949fSKuninori Morimoto struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id) 958ba9c949fSKuninori Morimoto { 959ba9c949fSKuninori Morimoto if (WARN_ON(id < 0 || id >= rsnd_src_nr(priv))) 960ba9c949fSKuninori Morimoto id = 0; 961ba9c949fSKuninori Morimoto 962ba9c949fSKuninori Morimoto return &((struct rsnd_src *)(priv->src) + id)->mod; 963ba9c949fSKuninori Morimoto } 964ba9c949fSKuninori Morimoto 96590e8e50fSKuninori Morimoto static void rsnd_of_parse_src(struct platform_device *pdev, 96690e8e50fSKuninori Morimoto const struct rsnd_of_data *of_data, 96790e8e50fSKuninori Morimoto struct rsnd_priv *priv) 96890e8e50fSKuninori Morimoto { 96990e8e50fSKuninori Morimoto struct device_node *src_node; 970cfcefe01SKuninori Morimoto struct device_node *np; 97190e8e50fSKuninori Morimoto struct rcar_snd_info *info = rsnd_priv_to_info(priv); 97290e8e50fSKuninori Morimoto struct rsnd_src_platform_info *src_info; 97390e8e50fSKuninori Morimoto struct device *dev = &pdev->dev; 974cfcefe01SKuninori Morimoto int nr, i; 97590e8e50fSKuninori Morimoto 97690e8e50fSKuninori Morimoto if (!of_data) 97790e8e50fSKuninori Morimoto return; 97890e8e50fSKuninori Morimoto 97982e76ed3SKuninori Morimoto src_node = rsnd_src_of_node(priv); 98090e8e50fSKuninori Morimoto if (!src_node) 98190e8e50fSKuninori Morimoto return; 98290e8e50fSKuninori Morimoto 98390e8e50fSKuninori Morimoto nr = of_get_child_count(src_node); 98490e8e50fSKuninori Morimoto if (!nr) 985f451e48dSKuninori Morimoto goto rsnd_of_parse_src_end; 98690e8e50fSKuninori Morimoto 98790e8e50fSKuninori Morimoto src_info = devm_kzalloc(dev, 98890e8e50fSKuninori Morimoto sizeof(struct rsnd_src_platform_info) * nr, 98990e8e50fSKuninori Morimoto GFP_KERNEL); 99090e8e50fSKuninori Morimoto if (!src_info) { 99190e8e50fSKuninori Morimoto dev_err(dev, "src info allocation error\n"); 992f451e48dSKuninori Morimoto goto rsnd_of_parse_src_end; 99390e8e50fSKuninori Morimoto } 99490e8e50fSKuninori Morimoto 99590e8e50fSKuninori Morimoto info->src_info = src_info; 99690e8e50fSKuninori Morimoto info->src_info_nr = nr; 997f451e48dSKuninori Morimoto 998cfcefe01SKuninori Morimoto i = 0; 999cfcefe01SKuninori Morimoto for_each_child_of_node(src_node, np) { 1000cfcefe01SKuninori Morimoto src_info[i].irq = irq_of_parse_and_map(np, 0); 1001cfcefe01SKuninori Morimoto 1002cfcefe01SKuninori Morimoto i++; 1003cfcefe01SKuninori Morimoto } 1004cfcefe01SKuninori Morimoto 1005f451e48dSKuninori Morimoto rsnd_of_parse_src_end: 1006f451e48dSKuninori Morimoto of_node_put(src_node); 100790e8e50fSKuninori Morimoto } 100890e8e50fSKuninori Morimoto 1009ba9c949fSKuninori Morimoto int rsnd_src_probe(struct platform_device *pdev, 101090e8e50fSKuninori Morimoto const struct rsnd_of_data *of_data, 1011ba9c949fSKuninori Morimoto struct rsnd_priv *priv) 1012ba9c949fSKuninori Morimoto { 1013ba9c949fSKuninori Morimoto struct rcar_snd_info *info = rsnd_priv_to_info(priv); 1014ba9c949fSKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 1015ba9c949fSKuninori Morimoto struct rsnd_src *src; 1016ba9c949fSKuninori Morimoto struct rsnd_mod_ops *ops; 1017ba9c949fSKuninori Morimoto struct clk *clk; 1018ba9c949fSKuninori Morimoto char name[RSND_SRC_NAME_SIZE]; 10192f78dd7fSKuninori Morimoto int i, nr, ret; 1020ba9c949fSKuninori Morimoto 1021033e7ed8SKuninori Morimoto ops = NULL; 1022033e7ed8SKuninori Morimoto if (rsnd_is_gen1(priv)) 1023033e7ed8SKuninori Morimoto ops = &rsnd_src_gen1_ops; 1024033e7ed8SKuninori Morimoto if (rsnd_is_gen2(priv)) 1025033e7ed8SKuninori Morimoto ops = &rsnd_src_gen2_ops; 1026033e7ed8SKuninori Morimoto if (!ops) { 1027033e7ed8SKuninori Morimoto dev_err(dev, "unknown Generation\n"); 1028033e7ed8SKuninori Morimoto return -EIO; 1029033e7ed8SKuninori Morimoto } 1030033e7ed8SKuninori Morimoto 103190e8e50fSKuninori Morimoto rsnd_of_parse_src(pdev, of_data, priv); 103290e8e50fSKuninori Morimoto 1033ba9c949fSKuninori Morimoto /* 1034ba9c949fSKuninori Morimoto * init SRC 1035ba9c949fSKuninori Morimoto */ 1036ba9c949fSKuninori Morimoto nr = info->src_info_nr; 1037ba9c949fSKuninori Morimoto if (!nr) 1038ba9c949fSKuninori Morimoto return 0; 1039ba9c949fSKuninori Morimoto 1040ba9c949fSKuninori Morimoto src = devm_kzalloc(dev, sizeof(*src) * nr, GFP_KERNEL); 1041ba9c949fSKuninori Morimoto if (!src) { 1042ba9c949fSKuninori Morimoto dev_err(dev, "SRC allocate failed\n"); 1043ba9c949fSKuninori Morimoto return -ENOMEM; 1044ba9c949fSKuninori Morimoto } 1045ba9c949fSKuninori Morimoto 1046ba9c949fSKuninori Morimoto priv->src_nr = nr; 1047ba9c949fSKuninori Morimoto priv->src = src; 1048ba9c949fSKuninori Morimoto 1049ba9c949fSKuninori Morimoto for_each_rsnd_src(src, priv, i) { 10508aefda50SKuninori Morimoto snprintf(name, RSND_SRC_NAME_SIZE, "%s.%d", 10518aefda50SKuninori Morimoto SRC_NAME, i); 1052ba9c949fSKuninori Morimoto 1053ba9c949fSKuninori Morimoto clk = devm_clk_get(dev, name); 1054ba9c949fSKuninori Morimoto if (IS_ERR(clk)) 1055ba9c949fSKuninori Morimoto return PTR_ERR(clk); 1056ba9c949fSKuninori Morimoto 1057ba9c949fSKuninori Morimoto src->info = &info->src_info[i]; 1058ba9c949fSKuninori Morimoto 10592099bc8eSKuninori Morimoto ret = rsnd_mod_init(priv, &src->mod, ops, clk, RSND_MOD_SRC, i); 10602f78dd7fSKuninori Morimoto if (ret) 10612f78dd7fSKuninori Morimoto return ret; 1062ba9c949fSKuninori Morimoto } 1063ba9c949fSKuninori Morimoto 1064ba9c949fSKuninori Morimoto return 0; 1065ba9c949fSKuninori Morimoto } 10662f78dd7fSKuninori Morimoto 10672f78dd7fSKuninori Morimoto void rsnd_src_remove(struct platform_device *pdev, 10682f78dd7fSKuninori Morimoto struct rsnd_priv *priv) 10692f78dd7fSKuninori Morimoto { 10702f78dd7fSKuninori Morimoto struct rsnd_src *src; 10712f78dd7fSKuninori Morimoto int i; 10722f78dd7fSKuninori Morimoto 10732f78dd7fSKuninori Morimoto for_each_rsnd_src(src, priv, i) { 10742f78dd7fSKuninori Morimoto rsnd_mod_quit(&src->mod); 10752f78dd7fSKuninori Morimoto } 10762f78dd7fSKuninori Morimoto } 1077