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 33da599fd3SKuninori Morimoto #define rsnd_src_nr(priv) ((priv)->src_nr) 3443cb6954SKuninori Morimoto #define rsnd_enable_sync_convert(src) ((src)->sen.val) 3582e76ed3SKuninori Morimoto #define rsnd_src_of_node(priv) \ 3682e76ed3SKuninori Morimoto of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,src") 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 58ba9c949fSKuninori Morimoto /* 59ba9c949fSKuninori Morimoto * src.c is caring... 60ba9c949fSKuninori Morimoto * 61ba9c949fSKuninori Morimoto * Gen1 62ba9c949fSKuninori Morimoto * 63ba9c949fSKuninori Morimoto * [mem] -> [SRU] -> [SSI] 64ba9c949fSKuninori Morimoto * |--------| 65ba9c949fSKuninori Morimoto * 66ba9c949fSKuninori Morimoto * Gen2 67ba9c949fSKuninori Morimoto * 68ba9c949fSKuninori Morimoto * [mem] -> [SRC] -> [SSIU] -> [SSI] 69ba9c949fSKuninori Morimoto * |-----------------| 70ba9c949fSKuninori Morimoto */ 71ba9c949fSKuninori Morimoto 72ba9c949fSKuninori Morimoto /* 73ba9c949fSKuninori Morimoto * How to use SRC bypass mode for debugging 74ba9c949fSKuninori Morimoto * 75ba9c949fSKuninori Morimoto * SRC has bypass mode, and it is useful for debugging. 76ba9c949fSKuninori Morimoto * In Gen2 case, 77ba9c949fSKuninori Morimoto * SRCm_MODE controls whether SRC is used or not 78ba9c949fSKuninori Morimoto * SSI_MODE0 controls whether SSIU which receives SRC data 79ba9c949fSKuninori Morimoto * is used or not. 80ba9c949fSKuninori Morimoto * Both SRCm_MODE/SSI_MODE0 settings are needed if you use SRC, 81ba9c949fSKuninori Morimoto * but SRC bypass mode needs SSI_MODE0 only. 82ba9c949fSKuninori Morimoto * 83ba9c949fSKuninori Morimoto * This driver request 84ba9c949fSKuninori Morimoto * struct rsnd_src_platform_info { 85ba9c949fSKuninori Morimoto * u32 convert_rate; 8629e69fd2SKuninori Morimoto * int dma_id; 87ba9c949fSKuninori Morimoto * } 88ba9c949fSKuninori Morimoto * 89ba9c949fSKuninori Morimoto * rsnd_src_convert_rate() indicates 90ba9c949fSKuninori Morimoto * above convert_rate, and it controls 91ba9c949fSKuninori Morimoto * whether SRC is used or not. 92ba9c949fSKuninori Morimoto * 93ba9c949fSKuninori Morimoto * ex) doesn't use SRC 9429e69fd2SKuninori Morimoto * static struct rsnd_dai_platform_info rsnd_dai = { 9529e69fd2SKuninori Morimoto * .playback = { .ssi = &rsnd_ssi[0], }, 96ba9c949fSKuninori Morimoto * }; 97ba9c949fSKuninori Morimoto * 98ba9c949fSKuninori Morimoto * ex) uses SRC 9929e69fd2SKuninori Morimoto * static struct rsnd_src_platform_info rsnd_src[] = { 10029e69fd2SKuninori Morimoto * RSND_SCU(48000, 0), 10129e69fd2SKuninori Morimoto * ... 10229e69fd2SKuninori Morimoto * }; 10329e69fd2SKuninori Morimoto * static struct rsnd_dai_platform_info rsnd_dai = { 10429e69fd2SKuninori Morimoto * .playback = { .ssi = &rsnd_ssi[0], .src = &rsnd_src[0] }, 105ba9c949fSKuninori Morimoto * }; 106ba9c949fSKuninori Morimoto * 107ba9c949fSKuninori Morimoto * ex) uses SRC bypass mode 10829e69fd2SKuninori Morimoto * static struct rsnd_src_platform_info rsnd_src[] = { 10929e69fd2SKuninori Morimoto * RSND_SCU(0, 0), 11029e69fd2SKuninori Morimoto * ... 11129e69fd2SKuninori Morimoto * }; 11229e69fd2SKuninori Morimoto * static struct rsnd_dai_platform_info rsnd_dai = { 11329e69fd2SKuninori Morimoto * .playback = { .ssi = &rsnd_ssi[0], .src = &rsnd_src[0] }, 114ba9c949fSKuninori Morimoto * }; 115ba9c949fSKuninori Morimoto * 116ba9c949fSKuninori Morimoto */ 117ba9c949fSKuninori Morimoto 118ba9c949fSKuninori Morimoto /* 119ba9c949fSKuninori Morimoto * Gen1/Gen2 common functions 120ba9c949fSKuninori Morimoto */ 121*379febfdSKuninori Morimoto static void rsnd_src_soft_reset(struct rsnd_mod *mod) 122*379febfdSKuninori Morimoto { 123*379febfdSKuninori Morimoto rsnd_mod_write(mod, SRC_SWRSR, 0); 124*379febfdSKuninori Morimoto rsnd_mod_write(mod, SRC_SWRSR, 1); 125*379febfdSKuninori Morimoto } 126*379febfdSKuninori Morimoto 1279b99e9a7SKuninori Morimoto static struct dma_chan *rsnd_src_dma_req(struct rsnd_dai_stream *io, 1289b99e9a7SKuninori Morimoto struct rsnd_mod *mod) 12972adc61fSKuninori Morimoto { 13072adc61fSKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 13172adc61fSKuninori Morimoto int is_play = rsnd_io_is_play(io); 13272adc61fSKuninori Morimoto 13372adc61fSKuninori Morimoto return rsnd_dma_request_channel(rsnd_src_of_node(priv), 13472adc61fSKuninori Morimoto mod, 13572adc61fSKuninori Morimoto is_play ? "rx" : "tx"); 13672adc61fSKuninori Morimoto } 13772adc61fSKuninori Morimoto 138d9288d0bSKuninori Morimoto int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, 1394e2639ffSKuninori Morimoto struct rsnd_dai_stream *io, 140d9288d0bSKuninori Morimoto int use_busif) 141ba9c949fSKuninori Morimoto { 142f708d944SKuninori Morimoto struct rsnd_dai *rdai = rsnd_io_to_rdai(io); 1431cc71959SKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 144ba9c949fSKuninori Morimoto int ssi_id = rsnd_mod_id(ssi_mod); 145ba9c949fSKuninori Morimoto 146ba9c949fSKuninori Morimoto /* 147ba9c949fSKuninori Morimoto * SSI_MODE0 148ba9c949fSKuninori Morimoto */ 149ba9c949fSKuninori Morimoto rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id), 150d9288d0bSKuninori Morimoto !use_busif << ssi_id); 151ba9c949fSKuninori Morimoto 152ba9c949fSKuninori Morimoto /* 153ba9c949fSKuninori Morimoto * SSI_MODE1 154ba9c949fSKuninori Morimoto */ 155ba9c949fSKuninori Morimoto if (rsnd_ssi_is_pin_sharing(ssi_mod)) { 156ba9c949fSKuninori Morimoto int shift = -1; 157ba9c949fSKuninori Morimoto switch (ssi_id) { 158ba9c949fSKuninori Morimoto case 1: 159ba9c949fSKuninori Morimoto shift = 0; 160ba9c949fSKuninori Morimoto break; 161ba9c949fSKuninori Morimoto case 2: 162ba9c949fSKuninori Morimoto shift = 2; 163ba9c949fSKuninori Morimoto break; 164ba9c949fSKuninori Morimoto case 4: 165ba9c949fSKuninori Morimoto shift = 16; 166ba9c949fSKuninori Morimoto break; 167ba9c949fSKuninori Morimoto } 168ba9c949fSKuninori Morimoto 169ba9c949fSKuninori Morimoto if (shift >= 0) 170ba9c949fSKuninori Morimoto rsnd_mod_bset(ssi_mod, SSI_MODE1, 171ba9c949fSKuninori Morimoto 0x3 << shift, 1723ed6448cSKuninori Morimoto rsnd_rdai_is_clk_master(rdai) ? 173ba9c949fSKuninori Morimoto 0x2 << shift : 0x1 << shift); 174ba9c949fSKuninori Morimoto } 175ba9c949fSKuninori Morimoto 176d9288d0bSKuninori Morimoto /* 177d9288d0bSKuninori Morimoto * DMA settings for SSIU 178d9288d0bSKuninori Morimoto */ 179d9288d0bSKuninori Morimoto if (use_busif) { 1801cc71959SKuninori Morimoto u32 val = 0x76543210; 1811cc71959SKuninori Morimoto u32 mask = ~0; 1821cc71959SKuninori Morimoto 183d9288d0bSKuninori Morimoto rsnd_mod_write(ssi_mod, SSI_BUSIF_ADINR, 1844e2639ffSKuninori Morimoto rsnd_get_adinr(ssi_mod, io)); 185d9288d0bSKuninori Morimoto rsnd_mod_write(ssi_mod, SSI_BUSIF_MODE, 1); 186d9288d0bSKuninori Morimoto rsnd_mod_write(ssi_mod, SSI_CTRL, 0x1); 1871cc71959SKuninori Morimoto 1881cc71959SKuninori Morimoto mask <<= runtime->channels * 4; 1891cc71959SKuninori Morimoto val = val & mask; 1901cc71959SKuninori Morimoto 1911cc71959SKuninori Morimoto switch (runtime->sample_bits) { 1921cc71959SKuninori Morimoto case 16: 1931cc71959SKuninori Morimoto val |= 0x67452301 & ~mask; 1941cc71959SKuninori Morimoto break; 1951cc71959SKuninori Morimoto case 32: 1961cc71959SKuninori Morimoto val |= 0x76543210 & ~mask; 1971cc71959SKuninori Morimoto break; 1981cc71959SKuninori Morimoto } 199cdde84d1SKuninori Morimoto rsnd_mod_write(ssi_mod, SSI_BUSIF_DALIGN, val); 2001cc71959SKuninori Morimoto 201d9288d0bSKuninori Morimoto } 202d9288d0bSKuninori Morimoto 203d9288d0bSKuninori Morimoto return 0; 204d9288d0bSKuninori Morimoto } 205d9288d0bSKuninori Morimoto 2064e2639ffSKuninori Morimoto int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod, 2074e2639ffSKuninori Morimoto struct rsnd_dai_stream *io) 208d9288d0bSKuninori Morimoto { 209d9288d0bSKuninori Morimoto /* 210d9288d0bSKuninori Morimoto * DMA settings for SSIU 211d9288d0bSKuninori Morimoto */ 212d9288d0bSKuninori Morimoto rsnd_mod_write(ssi_mod, SSI_CTRL, 0); 213d9288d0bSKuninori Morimoto 214ba9c949fSKuninori Morimoto return 0; 215ba9c949fSKuninori Morimoto } 216ba9c949fSKuninori Morimoto 217f708d944SKuninori Morimoto int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod) 218ba9c949fSKuninori Morimoto { 219ba9c949fSKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); 220ba9c949fSKuninori Morimoto 221c17dba8bSKuninori Morimoto if (rsnd_is_gen1(priv)) 222c17dba8bSKuninori Morimoto return 0; 223c17dba8bSKuninori Morimoto 224c17dba8bSKuninori Morimoto /* enable SSI interrupt if Gen2 */ 225efa991dcSKuninori Morimoto rsnd_mod_write(ssi_mod, SSI_INT_ENABLE, 226efa991dcSKuninori Morimoto rsnd_ssi_is_dma_mode(ssi_mod) ? 227efa991dcSKuninori Morimoto 0x0e000000 : 0x0f000000); 228ba9c949fSKuninori Morimoto 229ba9c949fSKuninori Morimoto return 0; 230ba9c949fSKuninori Morimoto } 231ba9c949fSKuninori Morimoto 232f708d944SKuninori Morimoto int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod) 233c17dba8bSKuninori Morimoto { 234c17dba8bSKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); 235c17dba8bSKuninori Morimoto 236c17dba8bSKuninori Morimoto if (rsnd_is_gen1(priv)) 237c17dba8bSKuninori Morimoto return 0; 238c17dba8bSKuninori Morimoto 239c17dba8bSKuninori Morimoto /* disable SSI interrupt if Gen2 */ 240efa991dcSKuninori Morimoto rsnd_mod_write(ssi_mod, SSI_INT_ENABLE, 0x00000000); 241c17dba8bSKuninori Morimoto 242c17dba8bSKuninori Morimoto return 0; 243c17dba8bSKuninori Morimoto } 244c17dba8bSKuninori Morimoto 24588c61cffSKuninori Morimoto static u32 rsnd_src_convert_rate(struct rsnd_dai_stream *io, 24688c61cffSKuninori Morimoto struct rsnd_src *src) 24743cb6954SKuninori Morimoto { 24843cb6954SKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 24943cb6954SKuninori Morimoto u32 convert_rate; 25043cb6954SKuninori Morimoto 25143cb6954SKuninori Morimoto if (!runtime) 25243cb6954SKuninori Morimoto return 0; 25343cb6954SKuninori Morimoto 25443cb6954SKuninori Morimoto if (!rsnd_enable_sync_convert(src)) 25543cb6954SKuninori Morimoto return src->convert_rate; 25643cb6954SKuninori Morimoto 25743cb6954SKuninori Morimoto convert_rate = src->sync.val; 25843cb6954SKuninori Morimoto 25943cb6954SKuninori Morimoto if (!convert_rate) 26043cb6954SKuninori Morimoto convert_rate = src->convert_rate; 26143cb6954SKuninori Morimoto 26243cb6954SKuninori Morimoto if (!convert_rate) 26343cb6954SKuninori Morimoto convert_rate = runtime->rate; 26443cb6954SKuninori Morimoto 26543cb6954SKuninori Morimoto return convert_rate; 26643cb6954SKuninori Morimoto } 26743cb6954SKuninori Morimoto 268ba9c949fSKuninori Morimoto unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, 269ba9c949fSKuninori Morimoto struct rsnd_dai_stream *io, 270ba9c949fSKuninori Morimoto struct snd_pcm_runtime *runtime) 271ba9c949fSKuninori Morimoto { 272b1eac430SKuninori Morimoto struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); 273ba9c949fSKuninori Morimoto struct rsnd_src *src; 274b1eac430SKuninori Morimoto unsigned int rate = 0; 275ba9c949fSKuninori Morimoto 276b1eac430SKuninori Morimoto if (src_mod) { 277b1eac430SKuninori Morimoto src = rsnd_mod_to_src(src_mod); 278ba9c949fSKuninori Morimoto 279ba9c949fSKuninori Morimoto /* 280ba9c949fSKuninori Morimoto * return convert rate if SRC is used, 281ba9c949fSKuninori Morimoto * otherwise, return runtime->rate as usual 282ba9c949fSKuninori Morimoto */ 28388c61cffSKuninori Morimoto rate = rsnd_src_convert_rate(io, src); 284b1eac430SKuninori Morimoto } 285b1eac430SKuninori Morimoto 286ba9c949fSKuninori Morimoto if (!rate) 287ba9c949fSKuninori Morimoto rate = runtime->rate; 288ba9c949fSKuninori Morimoto 289ba9c949fSKuninori Morimoto return rate; 290ba9c949fSKuninori Morimoto } 291ba9c949fSKuninori Morimoto 2924e2639ffSKuninori Morimoto static int rsnd_src_set_convert_rate(struct rsnd_mod *mod, 2934e2639ffSKuninori Morimoto struct rsnd_dai_stream *io) 294ba9c949fSKuninori Morimoto { 295ba9c949fSKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 296ba9c949fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 29788c61cffSKuninori Morimoto u32 convert_rate = rsnd_src_convert_rate(io, src); 298ba9c949fSKuninori Morimoto u32 fsrate = 0; 299ba9c949fSKuninori Morimoto 300ba9c949fSKuninori Morimoto if (convert_rate) 301ba9c949fSKuninori Morimoto fsrate = 0x0400000 / convert_rate * runtime->rate; 302ba9c949fSKuninori Morimoto 303ba9c949fSKuninori Morimoto /* Set channel number and output bit length */ 3044e2639ffSKuninori Morimoto rsnd_mod_write(mod, SRC_ADINR, rsnd_get_adinr(mod, io)); 305ba9c949fSKuninori Morimoto 306ba9c949fSKuninori Morimoto /* Enable the initial value of IFS */ 307ba9c949fSKuninori Morimoto if (fsrate) { 308ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_IFSCR, 1); 309ba9c949fSKuninori Morimoto 310ba9c949fSKuninori Morimoto /* Set initial value of IFS */ 311ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_IFSVR, fsrate); 312ba9c949fSKuninori Morimoto } 313ba9c949fSKuninori Morimoto 314ba9c949fSKuninori Morimoto /* use DMA transfer */ 315ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_BUSIF_MODE, 1); 316ba9c949fSKuninori Morimoto 317ba9c949fSKuninori Morimoto return 0; 318ba9c949fSKuninori Morimoto } 319ba9c949fSKuninori Morimoto 3203b7843ffSKuninori Morimoto static int rsnd_src_hw_params(struct rsnd_mod *mod, 3212c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 3223b7843ffSKuninori Morimoto struct snd_pcm_substream *substream, 3233b7843ffSKuninori Morimoto struct snd_pcm_hw_params *fe_params) 3243b7843ffSKuninori Morimoto { 3253b7843ffSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 3263b7843ffSKuninori Morimoto struct snd_soc_pcm_runtime *fe = substream->private_data; 3273b7843ffSKuninori Morimoto 3283b7843ffSKuninori Morimoto /* default value (mainly for non-DT) */ 3293b7843ffSKuninori Morimoto src->convert_rate = src->info->convert_rate; 3303b7843ffSKuninori Morimoto 3313b7843ffSKuninori Morimoto /* 3323b7843ffSKuninori Morimoto * SRC assumes that it is used under DPCM if user want to use 3333b7843ffSKuninori Morimoto * sampling rate convert. Then, SRC should be FE. 3343b7843ffSKuninori Morimoto * And then, this function will be called *after* BE settings. 3353b7843ffSKuninori Morimoto * this means, each BE already has fixuped hw_params. 3363b7843ffSKuninori Morimoto * see 3373b7843ffSKuninori Morimoto * dpcm_fe_dai_hw_params() 3383b7843ffSKuninori Morimoto * dpcm_be_dai_hw_params() 3393b7843ffSKuninori Morimoto */ 3403b7843ffSKuninori Morimoto if (fe->dai_link->dynamic) { 3413b7843ffSKuninori Morimoto int stream = substream->stream; 3423b7843ffSKuninori Morimoto struct snd_soc_dpcm *dpcm; 3433b7843ffSKuninori Morimoto struct snd_pcm_hw_params *be_params; 3443b7843ffSKuninori Morimoto 3453b7843ffSKuninori Morimoto list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { 3463b7843ffSKuninori Morimoto be_params = &dpcm->hw_params; 3473b7843ffSKuninori Morimoto 3483b7843ffSKuninori Morimoto if (params_rate(fe_params) != params_rate(be_params)) 3493b7843ffSKuninori Morimoto src->convert_rate = params_rate(be_params); 3503b7843ffSKuninori Morimoto } 3513b7843ffSKuninori Morimoto } 3523b7843ffSKuninori Morimoto 3533b7843ffSKuninori Morimoto return 0; 3543b7843ffSKuninori Morimoto } 3553b7843ffSKuninori Morimoto 3563b7843ffSKuninori Morimoto static int rsnd_src_init(struct rsnd_mod *mod, 3573b7843ffSKuninori Morimoto struct rsnd_priv *priv) 358ba9c949fSKuninori Morimoto { 359ba9c949fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 360ba9c949fSKuninori Morimoto 36185642952SKuninori Morimoto rsnd_mod_hw_start(mod); 362ba9c949fSKuninori Morimoto 363*379febfdSKuninori Morimoto rsnd_src_soft_reset(mod); 364*379febfdSKuninori Morimoto 365cfcefe01SKuninori Morimoto src->err = 0; 366cfcefe01SKuninori Morimoto 36743cb6954SKuninori Morimoto /* reset sync convert_rate */ 36843cb6954SKuninori Morimoto src->sync.val = 0; 36943cb6954SKuninori Morimoto 370603cefa5SKuninori Morimoto /* 371603cefa5SKuninori Morimoto * Initialize the operation of the SRC internal circuits 372603cefa5SKuninori Morimoto * see rsnd_src_start() 373603cefa5SKuninori Morimoto */ 374603cefa5SKuninori Morimoto rsnd_mod_write(mod, SRC_SRCIR, 1); 375603cefa5SKuninori Morimoto 376ba9c949fSKuninori Morimoto return 0; 377ba9c949fSKuninori Morimoto } 378ba9c949fSKuninori Morimoto 379ba9c949fSKuninori Morimoto static int rsnd_src_quit(struct rsnd_mod *mod, 3802c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 381690602fcSKuninori Morimoto struct rsnd_priv *priv) 382ba9c949fSKuninori Morimoto { 383ba9c949fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 384cfcefe01SKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 385ba9c949fSKuninori Morimoto 38685642952SKuninori Morimoto rsnd_mod_hw_stop(mod); 387ba9c949fSKuninori Morimoto 388cfcefe01SKuninori Morimoto if (src->err) 389337b0b4cSKuninori Morimoto dev_warn(dev, "%s[%d] under/over flow err = %d\n", 390337b0b4cSKuninori Morimoto rsnd_mod_name(mod), rsnd_mod_id(mod), src->err); 391cfcefe01SKuninori Morimoto 3923b7843ffSKuninori Morimoto src->convert_rate = 0; 3933b7843ffSKuninori Morimoto 39443cb6954SKuninori Morimoto /* reset sync convert_rate */ 39543cb6954SKuninori Morimoto src->sync.val = 0; 39643cb6954SKuninori Morimoto 397ba9c949fSKuninori Morimoto return 0; 398ba9c949fSKuninori Morimoto } 399ba9c949fSKuninori Morimoto 400f0ef0cb8SKuninori Morimoto static int rsnd_src_start(struct rsnd_mod *mod) 401ba9c949fSKuninori Morimoto { 402ba9c949fSKuninori Morimoto /* 403ba9c949fSKuninori Morimoto * Cancel the initialization and operate the SRC function 404603cefa5SKuninori Morimoto * see rsnd_src_init() 405ba9c949fSKuninori Morimoto */ 406ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_SRCIR, 0); 407ba9c949fSKuninori Morimoto 408ba9c949fSKuninori Morimoto return 0; 409ba9c949fSKuninori Morimoto } 410ba9c949fSKuninori Morimoto 411f0ef0cb8SKuninori Morimoto static int rsnd_src_stop(struct rsnd_mod *mod) 412ba9c949fSKuninori Morimoto { 413933cc8cbSKuninori Morimoto /* nothing to do */ 414ba9c949fSKuninori Morimoto return 0; 415ba9c949fSKuninori Morimoto } 416ba9c949fSKuninori Morimoto 417ba9c949fSKuninori Morimoto /* 418ba9c949fSKuninori Morimoto * Gen1 functions 419ba9c949fSKuninori Morimoto */ 42088c61cffSKuninori Morimoto static int rsnd_src_set_route_gen1(struct rsnd_dai_stream *io, 42188c61cffSKuninori Morimoto struct rsnd_mod *mod) 422ba9c949fSKuninori Morimoto { 423ba9c949fSKuninori Morimoto struct src_route_config { 424ba9c949fSKuninori Morimoto u32 mask; 425ba9c949fSKuninori Morimoto int shift; 426ba9c949fSKuninori Morimoto } routes[] = { 427ba9c949fSKuninori Morimoto { 0xF, 0, }, /* 0 */ 428ba9c949fSKuninori Morimoto { 0xF, 4, }, /* 1 */ 429ba9c949fSKuninori Morimoto { 0xF, 8, }, /* 2 */ 430ba9c949fSKuninori Morimoto { 0x7, 12, }, /* 3 */ 431ba9c949fSKuninori Morimoto { 0x7, 16, }, /* 4 */ 432ba9c949fSKuninori Morimoto { 0x7, 20, }, /* 5 */ 433ba9c949fSKuninori Morimoto { 0x7, 24, }, /* 6 */ 434ba9c949fSKuninori Morimoto { 0x3, 28, }, /* 7 */ 435ba9c949fSKuninori Morimoto { 0x3, 30, }, /* 8 */ 436ba9c949fSKuninori Morimoto }; 437ba9c949fSKuninori Morimoto u32 mask; 438ba9c949fSKuninori Morimoto u32 val; 439ba9c949fSKuninori Morimoto int id; 440ba9c949fSKuninori Morimoto 441ba9c949fSKuninori Morimoto id = rsnd_mod_id(mod); 442ba9c949fSKuninori Morimoto if (id < 0 || id >= ARRAY_SIZE(routes)) 443ba9c949fSKuninori Morimoto return -EIO; 444ba9c949fSKuninori Morimoto 445ba9c949fSKuninori Morimoto /* 446ba9c949fSKuninori Morimoto * SRC_ROUTE_SELECT 447ba9c949fSKuninori Morimoto */ 448985a4f6eSKuninori Morimoto val = rsnd_io_is_play(io) ? 0x1 : 0x2; 449ba9c949fSKuninori Morimoto val = val << routes[id].shift; 450ba9c949fSKuninori Morimoto mask = routes[id].mask << routes[id].shift; 451ba9c949fSKuninori Morimoto 452ba9c949fSKuninori Morimoto rsnd_mod_bset(mod, SRC_ROUTE_SEL, mask, val); 453ba9c949fSKuninori Morimoto 454ba9c949fSKuninori Morimoto return 0; 455ba9c949fSKuninori Morimoto } 456ba9c949fSKuninori Morimoto 45788c61cffSKuninori Morimoto static int rsnd_src_set_convert_timing_gen1(struct rsnd_dai_stream *io, 45888c61cffSKuninori Morimoto struct rsnd_mod *mod) 459ba9c949fSKuninori Morimoto { 460ba9c949fSKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 461ba9c949fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 462ba9c949fSKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 46388c61cffSKuninori Morimoto u32 convert_rate = rsnd_src_convert_rate(io, src); 464ba9c949fSKuninori Morimoto u32 mask; 465ba9c949fSKuninori Morimoto u32 val; 466ba9c949fSKuninori Morimoto int shift; 467ba9c949fSKuninori Morimoto int id = rsnd_mod_id(mod); 468ba9c949fSKuninori Morimoto int ret; 469ba9c949fSKuninori Morimoto 470ba9c949fSKuninori Morimoto /* 471ba9c949fSKuninori Morimoto * SRC_TIMING_SELECT 472ba9c949fSKuninori Morimoto */ 473ba9c949fSKuninori Morimoto shift = (id % 4) * 8; 474ba9c949fSKuninori Morimoto mask = 0x1F << shift; 475ba9c949fSKuninori Morimoto 476ba9c949fSKuninori Morimoto /* 477ba9c949fSKuninori Morimoto * ADG is used as source clock if SRC was used, 478ba9c949fSKuninori Morimoto * then, SSI WS is used as destination clock. 479ba9c949fSKuninori Morimoto * SSI WS is used as source clock if SRC is not used 480ba9c949fSKuninori Morimoto * (when playback, source/destination become reverse when capture) 481ba9c949fSKuninori Morimoto */ 482ba9c949fSKuninori Morimoto ret = 0; 483ba9c949fSKuninori Morimoto if (convert_rate) { 484ba9c949fSKuninori Morimoto /* use ADG */ 485ba9c949fSKuninori Morimoto val = 0; 486ba9c949fSKuninori Morimoto ret = rsnd_adg_set_convert_clk_gen1(priv, mod, 487ba9c949fSKuninori Morimoto runtime->rate, 488ba9c949fSKuninori Morimoto convert_rate); 489ba9c949fSKuninori Morimoto } else if (8 == id) { 490ba9c949fSKuninori Morimoto /* use SSI WS, but SRU8 is special */ 491ba9c949fSKuninori Morimoto val = id << shift; 492ba9c949fSKuninori Morimoto } else { 493ba9c949fSKuninori Morimoto /* use SSI WS */ 494ba9c949fSKuninori Morimoto val = (id + 1) << shift; 495ba9c949fSKuninori Morimoto } 496ba9c949fSKuninori Morimoto 497ba9c949fSKuninori Morimoto if (ret < 0) 498ba9c949fSKuninori Morimoto return ret; 499ba9c949fSKuninori Morimoto 500ba9c949fSKuninori Morimoto switch (id / 4) { 501ba9c949fSKuninori Morimoto case 0: 502ba9c949fSKuninori Morimoto rsnd_mod_bset(mod, SRC_TMG_SEL0, mask, val); 503ba9c949fSKuninori Morimoto break; 504ba9c949fSKuninori Morimoto case 1: 505ba9c949fSKuninori Morimoto rsnd_mod_bset(mod, SRC_TMG_SEL1, mask, val); 506ba9c949fSKuninori Morimoto break; 507ba9c949fSKuninori Morimoto case 2: 508ba9c949fSKuninori Morimoto rsnd_mod_bset(mod, SRC_TMG_SEL2, mask, val); 509ba9c949fSKuninori Morimoto break; 510ba9c949fSKuninori Morimoto } 511ba9c949fSKuninori Morimoto 512ba9c949fSKuninori Morimoto return 0; 513ba9c949fSKuninori Morimoto } 514ba9c949fSKuninori Morimoto 5154e2639ffSKuninori Morimoto static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod, 5164e2639ffSKuninori Morimoto struct rsnd_dai_stream *io) 517ba9c949fSKuninori Morimoto { 518933cc8cbSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 519ba9c949fSKuninori Morimoto int ret; 520ba9c949fSKuninori Morimoto 5214e2639ffSKuninori Morimoto ret = rsnd_src_set_convert_rate(mod, io); 522ba9c949fSKuninori Morimoto if (ret < 0) 523ba9c949fSKuninori Morimoto return ret; 524ba9c949fSKuninori Morimoto 525ba9c949fSKuninori Morimoto /* Select SRC mode (fixed value) */ 526ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_SRCCR, 0x00010110); 527ba9c949fSKuninori Morimoto 528ba9c949fSKuninori Morimoto /* Set the restriction value of the FS ratio (98%) */ 529ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_MNFSR, 530ba9c949fSKuninori Morimoto rsnd_mod_read(mod, SRC_IFSVR) / 100 * 98); 531ba9c949fSKuninori Morimoto 532933cc8cbSKuninori Morimoto /* Gen1/Gen2 are not compatible */ 53388c61cffSKuninori Morimoto if (rsnd_src_convert_rate(io, src)) 534933cc8cbSKuninori Morimoto rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); 535933cc8cbSKuninori Morimoto 536ba9c949fSKuninori Morimoto /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ 537ba9c949fSKuninori Morimoto 538ba9c949fSKuninori Morimoto return 0; 539ba9c949fSKuninori Morimoto } 540ba9c949fSKuninori Morimoto 541ba9c949fSKuninori Morimoto static int rsnd_src_init_gen1(struct rsnd_mod *mod, 5422c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 543690602fcSKuninori Morimoto struct rsnd_priv *priv) 544ba9c949fSKuninori Morimoto { 545ba9c949fSKuninori Morimoto int ret; 546ba9c949fSKuninori Morimoto 5473b7843ffSKuninori Morimoto ret = rsnd_src_init(mod, priv); 548ba9c949fSKuninori Morimoto if (ret < 0) 549ba9c949fSKuninori Morimoto return ret; 550ba9c949fSKuninori Morimoto 55188c61cffSKuninori Morimoto ret = rsnd_src_set_route_gen1(io, mod); 552ba9c949fSKuninori Morimoto if (ret < 0) 553ba9c949fSKuninori Morimoto return ret; 554ba9c949fSKuninori Morimoto 5554e2639ffSKuninori Morimoto ret = rsnd_src_set_convert_rate_gen1(mod, io); 556ba9c949fSKuninori Morimoto if (ret < 0) 557ba9c949fSKuninori Morimoto return ret; 558ba9c949fSKuninori Morimoto 55988c61cffSKuninori Morimoto ret = rsnd_src_set_convert_timing_gen1(io, mod); 560ba9c949fSKuninori Morimoto if (ret < 0) 561ba9c949fSKuninori Morimoto return ret; 562ba9c949fSKuninori Morimoto 563ba9c949fSKuninori Morimoto return 0; 564ba9c949fSKuninori Morimoto } 565ba9c949fSKuninori Morimoto 566ba9c949fSKuninori Morimoto static int rsnd_src_start_gen1(struct rsnd_mod *mod, 5672c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 568690602fcSKuninori Morimoto struct rsnd_priv *priv) 569ba9c949fSKuninori Morimoto { 570ba9c949fSKuninori Morimoto int id = rsnd_mod_id(mod); 571ba9c949fSKuninori Morimoto 572ba9c949fSKuninori Morimoto rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id)); 573ba9c949fSKuninori Morimoto 574f0ef0cb8SKuninori Morimoto return rsnd_src_start(mod); 575ba9c949fSKuninori Morimoto } 576ba9c949fSKuninori Morimoto 577ba9c949fSKuninori Morimoto static int rsnd_src_stop_gen1(struct rsnd_mod *mod, 5782c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 579690602fcSKuninori Morimoto struct rsnd_priv *priv) 580ba9c949fSKuninori Morimoto { 581ba9c949fSKuninori Morimoto int id = rsnd_mod_id(mod); 582ba9c949fSKuninori Morimoto 583ba9c949fSKuninori Morimoto rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0); 584ba9c949fSKuninori Morimoto 585f0ef0cb8SKuninori Morimoto return rsnd_src_stop(mod); 586ba9c949fSKuninori Morimoto } 587ba9c949fSKuninori Morimoto 588ba9c949fSKuninori Morimoto static struct rsnd_mod_ops rsnd_src_gen1_ops = { 5898aefda50SKuninori Morimoto .name = SRC_NAME, 59072adc61fSKuninori Morimoto .dma_req = rsnd_src_dma_req, 591ba9c949fSKuninori Morimoto .init = rsnd_src_init_gen1, 592ba9c949fSKuninori Morimoto .quit = rsnd_src_quit, 593ba9c949fSKuninori Morimoto .start = rsnd_src_start_gen1, 594ba9c949fSKuninori Morimoto .stop = rsnd_src_stop_gen1, 5953b7843ffSKuninori Morimoto .hw_params = rsnd_src_hw_params, 596ba9c949fSKuninori Morimoto }; 597ba9c949fSKuninori Morimoto 598ba9c949fSKuninori Morimoto /* 599ba9c949fSKuninori Morimoto * Gen2 functions 600ba9c949fSKuninori Morimoto */ 601cfcefe01SKuninori Morimoto #define rsnd_src_irq_enable_gen2(mod) rsnd_src_irq_ctrol_gen2(mod, 1) 602cfcefe01SKuninori Morimoto #define rsnd_src_irq_disable_gen2(mod) rsnd_src_irq_ctrol_gen2(mod, 0) 603cfcefe01SKuninori Morimoto static void rsnd_src_irq_ctrol_gen2(struct rsnd_mod *mod, int enable) 604cfcefe01SKuninori Morimoto { 605cfcefe01SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 606cfcefe01SKuninori Morimoto u32 sys_int_val, int_val, sys_int_mask; 607cfcefe01SKuninori Morimoto int irq = src->info->irq; 608cfcefe01SKuninori Morimoto int id = rsnd_mod_id(mod); 609cfcefe01SKuninori Morimoto 610cfcefe01SKuninori Morimoto sys_int_val = 611cfcefe01SKuninori Morimoto sys_int_mask = OUF_SRC(id); 612cfcefe01SKuninori Morimoto int_val = 0x3300; 613cfcefe01SKuninori Morimoto 614cfcefe01SKuninori Morimoto /* 615cfcefe01SKuninori Morimoto * IRQ is not supported on non-DT 616cfcefe01SKuninori Morimoto * see 617cfcefe01SKuninori Morimoto * rsnd_src_probe_gen2() 618cfcefe01SKuninori Morimoto */ 619cfcefe01SKuninori Morimoto if ((irq <= 0) || !enable) { 620cfcefe01SKuninori Morimoto sys_int_val = 0; 621cfcefe01SKuninori Morimoto int_val = 0; 622cfcefe01SKuninori Morimoto } 623cfcefe01SKuninori Morimoto 6241a1bf58aSKuninori Morimoto /* 6251a1bf58aSKuninori Morimoto * WORKAROUND 6261a1bf58aSKuninori Morimoto * 6271a1bf58aSKuninori Morimoto * ignore over flow error when rsnd_enable_sync_convert() 6281a1bf58aSKuninori Morimoto */ 6291a1bf58aSKuninori Morimoto if (rsnd_enable_sync_convert(src)) 6301a1bf58aSKuninori Morimoto sys_int_val = sys_int_val & 0xffff; 6311a1bf58aSKuninori Morimoto 632cfcefe01SKuninori Morimoto rsnd_mod_write(mod, SRC_INT_ENABLE0, int_val); 633cfcefe01SKuninori Morimoto rsnd_mod_bset(mod, SCU_SYS_INT_EN0, sys_int_mask, sys_int_val); 634cfcefe01SKuninori Morimoto rsnd_mod_bset(mod, SCU_SYS_INT_EN1, sys_int_mask, sys_int_val); 635cfcefe01SKuninori Morimoto } 636cfcefe01SKuninori Morimoto 637cfcefe01SKuninori Morimoto static void rsnd_src_error_clear_gen2(struct rsnd_mod *mod) 638cfcefe01SKuninori Morimoto { 639cfcefe01SKuninori Morimoto u32 val = OUF_SRC(rsnd_mod_id(mod)); 640cfcefe01SKuninori Morimoto 641cfcefe01SKuninori Morimoto rsnd_mod_bset(mod, SCU_SYS_STATUS0, val, val); 642cfcefe01SKuninori Morimoto rsnd_mod_bset(mod, SCU_SYS_STATUS1, val, val); 643cfcefe01SKuninori Morimoto } 644cfcefe01SKuninori Morimoto 645cfcefe01SKuninori Morimoto static bool rsnd_src_error_record_gen2(struct rsnd_mod *mod) 646cfcefe01SKuninori Morimoto { 6471a1bf58aSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 6481a1bf58aSKuninori Morimoto u32 val0, val1; 649cfcefe01SKuninori Morimoto bool ret = false; 650cfcefe01SKuninori Morimoto 6511a1bf58aSKuninori Morimoto val0 = val1 = OUF_SRC(rsnd_mod_id(mod)); 6521a1bf58aSKuninori Morimoto 6531a1bf58aSKuninori Morimoto /* 6541a1bf58aSKuninori Morimoto * WORKAROUND 6551a1bf58aSKuninori Morimoto * 6561a1bf58aSKuninori Morimoto * ignore over flow error when rsnd_enable_sync_convert() 6571a1bf58aSKuninori Morimoto */ 6581a1bf58aSKuninori Morimoto if (rsnd_enable_sync_convert(src)) 6591a1bf58aSKuninori Morimoto val0 = val0 & 0xffff; 6601a1bf58aSKuninori Morimoto 6611a1bf58aSKuninori Morimoto if ((rsnd_mod_read(mod, SCU_SYS_STATUS0) & val0) || 6621a1bf58aSKuninori Morimoto (rsnd_mod_read(mod, SCU_SYS_STATUS1) & val1)) { 663cfcefe01SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 664cfcefe01SKuninori Morimoto 665cfcefe01SKuninori Morimoto src->err++; 666cfcefe01SKuninori Morimoto ret = true; 667cfcefe01SKuninori Morimoto } 668cfcefe01SKuninori Morimoto 669cfcefe01SKuninori Morimoto /* clear error static */ 670cfcefe01SKuninori Morimoto rsnd_src_error_clear_gen2(mod); 671cfcefe01SKuninori Morimoto 672cfcefe01SKuninori Morimoto return ret; 673cfcefe01SKuninori Morimoto } 674cfcefe01SKuninori Morimoto 67588c61cffSKuninori Morimoto static int _rsnd_src_start_gen2(struct rsnd_mod *mod, 67688c61cffSKuninori Morimoto struct rsnd_dai_stream *io) 677cfcefe01SKuninori Morimoto { 6781a1bf58aSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 6791a1bf58aSKuninori Morimoto u32 val; 6801a1bf58aSKuninori Morimoto 6811a1bf58aSKuninori Morimoto /* 6821a1bf58aSKuninori Morimoto * WORKAROUND 6831a1bf58aSKuninori Morimoto * 6841a1bf58aSKuninori Morimoto * Enable SRC output if you want to use sync convert together with DVC 6851a1bf58aSKuninori Morimoto */ 6861a1bf58aSKuninori Morimoto val = (rsnd_io_to_mod_dvc(io) && !rsnd_enable_sync_convert(src)) ? 6871a1bf58aSKuninori Morimoto 0x01 : 0x11; 688cfcefe01SKuninori Morimoto 689cfcefe01SKuninori Morimoto rsnd_mod_write(mod, SRC_CTRL, val); 690cfcefe01SKuninori Morimoto 691cfcefe01SKuninori Morimoto rsnd_src_error_clear_gen2(mod); 692cfcefe01SKuninori Morimoto 693cfcefe01SKuninori Morimoto rsnd_src_start(mod); 694cfcefe01SKuninori Morimoto 695cfcefe01SKuninori Morimoto rsnd_src_irq_enable_gen2(mod); 696cfcefe01SKuninori Morimoto 697cfcefe01SKuninori Morimoto return 0; 698cfcefe01SKuninori Morimoto } 699cfcefe01SKuninori Morimoto 700cfcefe01SKuninori Morimoto static int _rsnd_src_stop_gen2(struct rsnd_mod *mod) 701cfcefe01SKuninori Morimoto { 702cfcefe01SKuninori Morimoto rsnd_src_irq_disable_gen2(mod); 703cfcefe01SKuninori Morimoto 704cfcefe01SKuninori Morimoto rsnd_mod_write(mod, SRC_CTRL, 0); 705cfcefe01SKuninori Morimoto 706cfcefe01SKuninori Morimoto rsnd_src_error_record_gen2(mod); 707cfcefe01SKuninori Morimoto 708cfcefe01SKuninori Morimoto return rsnd_src_stop(mod); 709cfcefe01SKuninori Morimoto } 710cfcefe01SKuninori Morimoto 71188c61cffSKuninori Morimoto static void __rsnd_src_interrupt_gen2(struct rsnd_mod *mod, 71288c61cffSKuninori Morimoto struct rsnd_dai_stream *io) 713cfcefe01SKuninori Morimoto { 71402299d98SKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 715cfcefe01SKuninori Morimoto 71602299d98SKuninori Morimoto spin_lock(&priv->lock); 71702299d98SKuninori Morimoto 71802299d98SKuninori Morimoto /* ignore all cases if not working */ 719d5bbe7deSKuninori Morimoto if (!rsnd_io_is_working(io)) 72002299d98SKuninori Morimoto goto rsnd_src_interrupt_gen2_out; 721cfcefe01SKuninori Morimoto 722cfcefe01SKuninori Morimoto if (rsnd_src_error_record_gen2(mod)) { 723cfcefe01SKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 724639b231fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 725cfcefe01SKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 726cfcefe01SKuninori Morimoto 727cfcefe01SKuninori Morimoto dev_dbg(dev, "%s[%d] restart\n", 728cfcefe01SKuninori Morimoto rsnd_mod_name(mod), rsnd_mod_id(mod)); 729639b231fSKuninori Morimoto 730639b231fSKuninori Morimoto _rsnd_src_stop_gen2(mod); 731639b231fSKuninori Morimoto if (src->err < 1024) 73288c61cffSKuninori Morimoto _rsnd_src_start_gen2(mod, io); 733639b231fSKuninori Morimoto else 734639b231fSKuninori Morimoto dev_warn(dev, "no more SRC restart\n"); 735cfcefe01SKuninori Morimoto } 73688c61cffSKuninori Morimoto 73702299d98SKuninori Morimoto rsnd_src_interrupt_gen2_out: 73802299d98SKuninori Morimoto spin_unlock(&priv->lock); 73988c61cffSKuninori Morimoto } 74088c61cffSKuninori Morimoto 74188c61cffSKuninori Morimoto static irqreturn_t rsnd_src_interrupt_gen2(int irq, void *data) 74288c61cffSKuninori Morimoto { 74388c61cffSKuninori Morimoto struct rsnd_mod *mod = data; 74488c61cffSKuninori Morimoto 74588c61cffSKuninori Morimoto rsnd_mod_interrupt(mod, __rsnd_src_interrupt_gen2); 746cfcefe01SKuninori Morimoto 747cfcefe01SKuninori Morimoto return IRQ_HANDLED; 748cfcefe01SKuninori Morimoto } 749cfcefe01SKuninori Morimoto 7504e2639ffSKuninori Morimoto static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, 7514e2639ffSKuninori Morimoto struct rsnd_dai_stream *io) 752ba9c949fSKuninori Morimoto { 753054cd7f4SKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 754054cd7f4SKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 755054cd7f4SKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 756054cd7f4SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 75788c61cffSKuninori Morimoto u32 convert_rate = rsnd_src_convert_rate(io, src); 75843cb6954SKuninori Morimoto u32 cr, route; 759054cd7f4SKuninori Morimoto uint ratio; 760ba9c949fSKuninori Morimoto int ret; 761ba9c949fSKuninori Morimoto 762054cd7f4SKuninori Morimoto /* 6 - 1/6 are very enough ratio for SRC_BSDSR */ 763b167a578SKuninori Morimoto if (!convert_rate) 764054cd7f4SKuninori Morimoto ratio = 0; 765b167a578SKuninori Morimoto else if (convert_rate > runtime->rate) 766b167a578SKuninori Morimoto ratio = 100 * convert_rate / runtime->rate; 767054cd7f4SKuninori Morimoto else 768b167a578SKuninori Morimoto ratio = 100 * runtime->rate / convert_rate; 769054cd7f4SKuninori Morimoto 770054cd7f4SKuninori Morimoto if (ratio > 600) { 771054cd7f4SKuninori Morimoto dev_err(dev, "FSO/FSI ratio error\n"); 772054cd7f4SKuninori Morimoto return -EINVAL; 773054cd7f4SKuninori Morimoto } 774054cd7f4SKuninori Morimoto 7754e2639ffSKuninori Morimoto ret = rsnd_src_set_convert_rate(mod, io); 776ba9c949fSKuninori Morimoto if (ret < 0) 777ba9c949fSKuninori Morimoto return ret; 778ba9c949fSKuninori Morimoto 77943cb6954SKuninori Morimoto cr = 0x00011110; 78043cb6954SKuninori Morimoto route = 0x0; 781933cc8cbSKuninori Morimoto if (convert_rate) { 78243cb6954SKuninori Morimoto route = 0x1; 78343cb6954SKuninori Morimoto 78443cb6954SKuninori Morimoto if (rsnd_enable_sync_convert(src)) { 78543cb6954SKuninori Morimoto cr |= 0x1; 78643cb6954SKuninori Morimoto route |= rsnd_io_is_play(io) ? 78743cb6954SKuninori Morimoto (0x1 << 24) : (0x1 << 25); 788933cc8cbSKuninori Morimoto } 78943cb6954SKuninori Morimoto } 79043cb6954SKuninori Morimoto 79143cb6954SKuninori Morimoto rsnd_mod_write(mod, SRC_SRCCR, cr); 79243cb6954SKuninori Morimoto rsnd_mod_write(mod, SRC_ROUTE_MODE0, route); 793933cc8cbSKuninori Morimoto 794054cd7f4SKuninori Morimoto switch (rsnd_mod_id(mod)) { 795054cd7f4SKuninori Morimoto case 5: 796054cd7f4SKuninori Morimoto case 6: 797054cd7f4SKuninori Morimoto case 7: 798054cd7f4SKuninori Morimoto case 8: 799054cd7f4SKuninori Morimoto rsnd_mod_write(mod, SRC_BSDSR, 0x02400000); 800054cd7f4SKuninori Morimoto break; 801054cd7f4SKuninori Morimoto default: 802ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_BSDSR, 0x01800000); 803054cd7f4SKuninori Morimoto break; 804054cd7f4SKuninori Morimoto } 805054cd7f4SKuninori Morimoto 806ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_BSISR, 0x00100060); 807ba9c949fSKuninori Morimoto 808ba9c949fSKuninori Morimoto return 0; 809ba9c949fSKuninori Morimoto } 810ba9c949fSKuninori Morimoto 81188c61cffSKuninori Morimoto static int rsnd_src_set_convert_timing_gen2(struct rsnd_dai_stream *io, 81288c61cffSKuninori Morimoto struct rsnd_mod *mod) 813ba9c949fSKuninori Morimoto { 814ba9c949fSKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 815ba9c949fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 81688c61cffSKuninori Morimoto u32 convert_rate = rsnd_src_convert_rate(io, src); 817ba9c949fSKuninori Morimoto int ret; 818ba9c949fSKuninori Morimoto 819ba9c949fSKuninori Morimoto if (convert_rate) 820f708d944SKuninori Morimoto ret = rsnd_adg_set_convert_clk_gen2(mod, io, 821ba9c949fSKuninori Morimoto runtime->rate, 822ba9c949fSKuninori Morimoto convert_rate); 823ba9c949fSKuninori Morimoto else 824f708d944SKuninori Morimoto ret = rsnd_adg_set_convert_timing_gen2(mod, io); 825ba9c949fSKuninori Morimoto 826ba9c949fSKuninori Morimoto return ret; 827ba9c949fSKuninori Morimoto } 828ba9c949fSKuninori Morimoto 829ba9c949fSKuninori Morimoto static int rsnd_src_probe_gen2(struct rsnd_mod *mod, 8302c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 831690602fcSKuninori Morimoto struct rsnd_priv *priv) 832ba9c949fSKuninori Morimoto { 833ba9c949fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 834ba9c949fSKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 835cfcefe01SKuninori Morimoto int irq = src->info->irq; 836ba9c949fSKuninori Morimoto int ret; 837ba9c949fSKuninori Morimoto 838cfcefe01SKuninori Morimoto if (irq > 0) { 839cfcefe01SKuninori Morimoto /* 840cfcefe01SKuninori Morimoto * IRQ is not supported on non-DT 841cfcefe01SKuninori Morimoto * see 842cfcefe01SKuninori Morimoto * rsnd_src_irq_enable_gen2() 843cfcefe01SKuninori Morimoto */ 844cfcefe01SKuninori Morimoto ret = devm_request_irq(dev, irq, 845cfcefe01SKuninori Morimoto rsnd_src_interrupt_gen2, 846cfcefe01SKuninori Morimoto IRQF_SHARED, 847cfcefe01SKuninori Morimoto dev_name(dev), mod); 848cfcefe01SKuninori Morimoto if (ret) 849b543b52aSKuninori Morimoto return ret; 850cfcefe01SKuninori Morimoto } 851cfcefe01SKuninori Morimoto 8529b99e9a7SKuninori Morimoto ret = rsnd_dma_init(io, 853ba9c949fSKuninori Morimoto rsnd_mod_to_dma(mod), 854ba9c949fSKuninori Morimoto src->info->dma_id); 855cfcefe01SKuninori Morimoto 856cfcefe01SKuninori Morimoto return ret; 857ba9c949fSKuninori Morimoto } 858ba9c949fSKuninori Morimoto 859ba9c949fSKuninori Morimoto static int rsnd_src_remove_gen2(struct rsnd_mod *mod, 8602c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 861690602fcSKuninori Morimoto struct rsnd_priv *priv) 862ba9c949fSKuninori Morimoto { 8639b99e9a7SKuninori Morimoto rsnd_dma_quit(io, rsnd_mod_to_dma(mod)); 864ba9c949fSKuninori Morimoto 865ba9c949fSKuninori Morimoto return 0; 866ba9c949fSKuninori Morimoto } 867ba9c949fSKuninori Morimoto 868ba9c949fSKuninori Morimoto static int rsnd_src_init_gen2(struct rsnd_mod *mod, 8692c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 870690602fcSKuninori Morimoto struct rsnd_priv *priv) 871ba9c949fSKuninori Morimoto { 872ba9c949fSKuninori Morimoto int ret; 873ba9c949fSKuninori Morimoto 8743b7843ffSKuninori Morimoto ret = rsnd_src_init(mod, priv); 875ba9c949fSKuninori Morimoto if (ret < 0) 876ba9c949fSKuninori Morimoto return ret; 877ba9c949fSKuninori Morimoto 8784e2639ffSKuninori Morimoto ret = rsnd_src_set_convert_rate_gen2(mod, io); 879ba9c949fSKuninori Morimoto if (ret < 0) 880ba9c949fSKuninori Morimoto return ret; 881ba9c949fSKuninori Morimoto 88288c61cffSKuninori Morimoto ret = rsnd_src_set_convert_timing_gen2(io, mod); 883ba9c949fSKuninori Morimoto if (ret < 0) 884ba9c949fSKuninori Morimoto return ret; 885ba9c949fSKuninori Morimoto 886ba9c949fSKuninori Morimoto return 0; 887ba9c949fSKuninori Morimoto } 888ba9c949fSKuninori Morimoto 889ba9c949fSKuninori Morimoto static int rsnd_src_start_gen2(struct rsnd_mod *mod, 8902c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 891690602fcSKuninori Morimoto struct rsnd_priv *priv) 892ba9c949fSKuninori Morimoto { 8939b99e9a7SKuninori Morimoto rsnd_dma_start(io, rsnd_mod_to_dma(mod)); 894ba9c949fSKuninori Morimoto 89588c61cffSKuninori Morimoto return _rsnd_src_start_gen2(mod, io); 896ba9c949fSKuninori Morimoto } 897ba9c949fSKuninori Morimoto 898ba9c949fSKuninori Morimoto static int rsnd_src_stop_gen2(struct rsnd_mod *mod, 8992c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 900690602fcSKuninori Morimoto struct rsnd_priv *priv) 901ba9c949fSKuninori Morimoto { 902cfcefe01SKuninori Morimoto int ret; 903ba9c949fSKuninori Morimoto 904cfcefe01SKuninori Morimoto ret = _rsnd_src_stop_gen2(mod); 905ba9c949fSKuninori Morimoto 9069b99e9a7SKuninori Morimoto rsnd_dma_stop(io, rsnd_mod_to_dma(mod)); 907ba9c949fSKuninori Morimoto 908cfcefe01SKuninori Morimoto return ret; 909ba9c949fSKuninori Morimoto } 910ba9c949fSKuninori Morimoto 911b65a7cccSKuninori Morimoto static void rsnd_src_reconvert_update(struct rsnd_dai_stream *io, 912b65a7cccSKuninori Morimoto struct rsnd_mod *mod) 91343cb6954SKuninori Morimoto { 91443cb6954SKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 91543cb6954SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 91688c61cffSKuninori Morimoto u32 convert_rate = rsnd_src_convert_rate(io, src); 91743cb6954SKuninori Morimoto u32 fsrate; 91843cb6954SKuninori Morimoto 91943cb6954SKuninori Morimoto if (!runtime) 92043cb6954SKuninori Morimoto return; 92143cb6954SKuninori Morimoto 92243cb6954SKuninori Morimoto if (!convert_rate) 92343cb6954SKuninori Morimoto convert_rate = runtime->rate; 92443cb6954SKuninori Morimoto 92543cb6954SKuninori Morimoto fsrate = 0x0400000 / convert_rate * runtime->rate; 92643cb6954SKuninori Morimoto 92743cb6954SKuninori Morimoto /* update IFS */ 92843cb6954SKuninori Morimoto rsnd_mod_write(mod, SRC_IFSVR, fsrate); 92943cb6954SKuninori Morimoto } 93043cb6954SKuninori Morimoto 93143cb6954SKuninori Morimoto static int rsnd_src_pcm_new(struct rsnd_mod *mod, 9322c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 93343cb6954SKuninori Morimoto struct snd_soc_pcm_runtime *rtd) 93443cb6954SKuninori Morimoto { 93543cb6954SKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 93643cb6954SKuninori Morimoto struct rsnd_dai *rdai = rsnd_io_to_rdai(io); 93743cb6954SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 93843cb6954SKuninori Morimoto int ret; 93943cb6954SKuninori Morimoto 94043cb6954SKuninori Morimoto /* 94143cb6954SKuninori Morimoto * enable SRC sync convert if possible 94243cb6954SKuninori Morimoto */ 94343cb6954SKuninori Morimoto 94443cb6954SKuninori Morimoto /* 94543cb6954SKuninori Morimoto * Gen1 is not supported 94643cb6954SKuninori Morimoto */ 94743cb6954SKuninori Morimoto if (rsnd_is_gen1(priv)) 94843cb6954SKuninori Morimoto return 0; 94943cb6954SKuninori Morimoto 95043cb6954SKuninori Morimoto /* 95143cb6954SKuninori Morimoto * SRC sync convert needs clock master 95243cb6954SKuninori Morimoto */ 95343cb6954SKuninori Morimoto if (!rsnd_rdai_is_clk_master(rdai)) 95443cb6954SKuninori Morimoto return 0; 95543cb6954SKuninori Morimoto 95643cb6954SKuninori Morimoto /* 95743cb6954SKuninori Morimoto * enable sync convert 95843cb6954SKuninori Morimoto */ 959b65a7cccSKuninori Morimoto ret = rsnd_kctrl_new_s(mod, io, rtd, 96043cb6954SKuninori Morimoto rsnd_io_is_play(io) ? 96143cb6954SKuninori Morimoto "SRC Out Rate Switch" : 96243cb6954SKuninori Morimoto "SRC In Rate Switch", 96343cb6954SKuninori Morimoto rsnd_src_reconvert_update, 96443cb6954SKuninori Morimoto &src->sen, 1); 96543cb6954SKuninori Morimoto if (ret < 0) 96643cb6954SKuninori Morimoto return ret; 96743cb6954SKuninori Morimoto 968b65a7cccSKuninori Morimoto ret = rsnd_kctrl_new_s(mod, io, rtd, 96943cb6954SKuninori Morimoto rsnd_io_is_play(io) ? 97043cb6954SKuninori Morimoto "SRC Out Rate" : 97143cb6954SKuninori Morimoto "SRC In Rate", 97243cb6954SKuninori Morimoto rsnd_src_reconvert_update, 97343cb6954SKuninori Morimoto &src->sync, 192000); 97443cb6954SKuninori Morimoto 97543cb6954SKuninori Morimoto return ret; 97643cb6954SKuninori Morimoto } 97743cb6954SKuninori Morimoto 978ba9c949fSKuninori Morimoto static struct rsnd_mod_ops rsnd_src_gen2_ops = { 9798aefda50SKuninori Morimoto .name = SRC_NAME, 98072adc61fSKuninori Morimoto .dma_req = rsnd_src_dma_req, 981ba9c949fSKuninori Morimoto .probe = rsnd_src_probe_gen2, 982ba9c949fSKuninori Morimoto .remove = rsnd_src_remove_gen2, 983ba9c949fSKuninori Morimoto .init = rsnd_src_init_gen2, 984ba9c949fSKuninori Morimoto .quit = rsnd_src_quit, 985ba9c949fSKuninori Morimoto .start = rsnd_src_start_gen2, 986ba9c949fSKuninori Morimoto .stop = rsnd_src_stop_gen2, 9873b7843ffSKuninori Morimoto .hw_params = rsnd_src_hw_params, 98843cb6954SKuninori Morimoto .pcm_new = rsnd_src_pcm_new, 989ba9c949fSKuninori Morimoto }; 990ba9c949fSKuninori Morimoto 991ba9c949fSKuninori Morimoto struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id) 992ba9c949fSKuninori Morimoto { 993ba9c949fSKuninori Morimoto if (WARN_ON(id < 0 || id >= rsnd_src_nr(priv))) 994ba9c949fSKuninori Morimoto id = 0; 995ba9c949fSKuninori Morimoto 996ba9c949fSKuninori Morimoto return &((struct rsnd_src *)(priv->src) + id)->mod; 997ba9c949fSKuninori Morimoto } 998ba9c949fSKuninori Morimoto 99990e8e50fSKuninori Morimoto static void rsnd_of_parse_src(struct platform_device *pdev, 100090e8e50fSKuninori Morimoto const struct rsnd_of_data *of_data, 100190e8e50fSKuninori Morimoto struct rsnd_priv *priv) 100290e8e50fSKuninori Morimoto { 100390e8e50fSKuninori Morimoto struct device_node *src_node; 1004cfcefe01SKuninori Morimoto struct device_node *np; 100590e8e50fSKuninori Morimoto struct rcar_snd_info *info = rsnd_priv_to_info(priv); 100690e8e50fSKuninori Morimoto struct rsnd_src_platform_info *src_info; 100790e8e50fSKuninori Morimoto struct device *dev = &pdev->dev; 1008cfcefe01SKuninori Morimoto int nr, i; 100990e8e50fSKuninori Morimoto 101090e8e50fSKuninori Morimoto if (!of_data) 101190e8e50fSKuninori Morimoto return; 101290e8e50fSKuninori Morimoto 101382e76ed3SKuninori Morimoto src_node = rsnd_src_of_node(priv); 101490e8e50fSKuninori Morimoto if (!src_node) 101590e8e50fSKuninori Morimoto return; 101690e8e50fSKuninori Morimoto 101790e8e50fSKuninori Morimoto nr = of_get_child_count(src_node); 101890e8e50fSKuninori Morimoto if (!nr) 1019f451e48dSKuninori Morimoto goto rsnd_of_parse_src_end; 102090e8e50fSKuninori Morimoto 102190e8e50fSKuninori Morimoto src_info = devm_kzalloc(dev, 102290e8e50fSKuninori Morimoto sizeof(struct rsnd_src_platform_info) * nr, 102390e8e50fSKuninori Morimoto GFP_KERNEL); 102490e8e50fSKuninori Morimoto if (!src_info) { 102590e8e50fSKuninori Morimoto dev_err(dev, "src info allocation error\n"); 1026f451e48dSKuninori Morimoto goto rsnd_of_parse_src_end; 102790e8e50fSKuninori Morimoto } 102890e8e50fSKuninori Morimoto 102990e8e50fSKuninori Morimoto info->src_info = src_info; 103090e8e50fSKuninori Morimoto info->src_info_nr = nr; 1031f451e48dSKuninori Morimoto 1032cfcefe01SKuninori Morimoto i = 0; 1033cfcefe01SKuninori Morimoto for_each_child_of_node(src_node, np) { 1034cfcefe01SKuninori Morimoto src_info[i].irq = irq_of_parse_and_map(np, 0); 1035cfcefe01SKuninori Morimoto 1036cfcefe01SKuninori Morimoto i++; 1037cfcefe01SKuninori Morimoto } 1038cfcefe01SKuninori Morimoto 1039f451e48dSKuninori Morimoto rsnd_of_parse_src_end: 1040f451e48dSKuninori Morimoto of_node_put(src_node); 104190e8e50fSKuninori Morimoto } 104290e8e50fSKuninori Morimoto 1043ba9c949fSKuninori Morimoto int rsnd_src_probe(struct platform_device *pdev, 104490e8e50fSKuninori Morimoto const struct rsnd_of_data *of_data, 1045ba9c949fSKuninori Morimoto struct rsnd_priv *priv) 1046ba9c949fSKuninori Morimoto { 1047ba9c949fSKuninori Morimoto struct rcar_snd_info *info = rsnd_priv_to_info(priv); 1048ba9c949fSKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 1049ba9c949fSKuninori Morimoto struct rsnd_src *src; 1050ba9c949fSKuninori Morimoto struct rsnd_mod_ops *ops; 1051ba9c949fSKuninori Morimoto struct clk *clk; 1052ba9c949fSKuninori Morimoto char name[RSND_SRC_NAME_SIZE]; 10532f78dd7fSKuninori Morimoto int i, nr, ret; 1054ba9c949fSKuninori Morimoto 1055033e7ed8SKuninori Morimoto ops = NULL; 1056033e7ed8SKuninori Morimoto if (rsnd_is_gen1(priv)) 1057033e7ed8SKuninori Morimoto ops = &rsnd_src_gen1_ops; 1058033e7ed8SKuninori Morimoto if (rsnd_is_gen2(priv)) 1059033e7ed8SKuninori Morimoto ops = &rsnd_src_gen2_ops; 1060033e7ed8SKuninori Morimoto if (!ops) { 1061033e7ed8SKuninori Morimoto dev_err(dev, "unknown Generation\n"); 1062033e7ed8SKuninori Morimoto return -EIO; 1063033e7ed8SKuninori Morimoto } 1064033e7ed8SKuninori Morimoto 106590e8e50fSKuninori Morimoto rsnd_of_parse_src(pdev, of_data, priv); 106690e8e50fSKuninori Morimoto 1067ba9c949fSKuninori Morimoto /* 1068ba9c949fSKuninori Morimoto * init SRC 1069ba9c949fSKuninori Morimoto */ 1070ba9c949fSKuninori Morimoto nr = info->src_info_nr; 1071ba9c949fSKuninori Morimoto if (!nr) 1072ba9c949fSKuninori Morimoto return 0; 1073ba9c949fSKuninori Morimoto 1074ba9c949fSKuninori Morimoto src = devm_kzalloc(dev, sizeof(*src) * nr, GFP_KERNEL); 107533363f7aSKuninori Morimoto if (!src) 1076ba9c949fSKuninori Morimoto return -ENOMEM; 1077ba9c949fSKuninori Morimoto 1078ba9c949fSKuninori Morimoto priv->src_nr = nr; 1079ba9c949fSKuninori Morimoto priv->src = src; 1080ba9c949fSKuninori Morimoto 1081ba9c949fSKuninori Morimoto for_each_rsnd_src(src, priv, i) { 10828aefda50SKuninori Morimoto snprintf(name, RSND_SRC_NAME_SIZE, "%s.%d", 10838aefda50SKuninori Morimoto SRC_NAME, i); 1084ba9c949fSKuninori Morimoto 1085ba9c949fSKuninori Morimoto clk = devm_clk_get(dev, name); 1086ba9c949fSKuninori Morimoto if (IS_ERR(clk)) 1087ba9c949fSKuninori Morimoto return PTR_ERR(clk); 1088ba9c949fSKuninori Morimoto 1089ba9c949fSKuninori Morimoto src->info = &info->src_info[i]; 1090ba9c949fSKuninori Morimoto 10912099bc8eSKuninori Morimoto ret = rsnd_mod_init(priv, &src->mod, ops, clk, RSND_MOD_SRC, i); 10922f78dd7fSKuninori Morimoto if (ret) 10932f78dd7fSKuninori Morimoto return ret; 1094ba9c949fSKuninori Morimoto } 1095ba9c949fSKuninori Morimoto 1096ba9c949fSKuninori Morimoto return 0; 1097ba9c949fSKuninori Morimoto } 10982f78dd7fSKuninori Morimoto 10992f78dd7fSKuninori Morimoto void rsnd_src_remove(struct platform_device *pdev, 11002f78dd7fSKuninori Morimoto struct rsnd_priv *priv) 11012f78dd7fSKuninori Morimoto { 11022f78dd7fSKuninori Morimoto struct rsnd_src *src; 11032f78dd7fSKuninori Morimoto int i; 11042f78dd7fSKuninori Morimoto 11052f78dd7fSKuninori Morimoto for_each_rsnd_src(src, priv, i) { 11062f78dd7fSKuninori Morimoto rsnd_mod_quit(&src->mod); 11072f78dd7fSKuninori Morimoto } 11082f78dd7fSKuninori Morimoto } 1109