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; 25232c00b6SKuninori Morimoto struct rsnd_dma *dma; 2643cb6954SKuninori Morimoto struct rsnd_kctrl_cfg_s sen; /* sync convert enable */ 2743cb6954SKuninori Morimoto struct rsnd_kctrl_cfg_s sync; /* sync convert */ 283b7843ffSKuninori Morimoto u32 convert_rate; /* sampling rate convert */ 29cfcefe01SKuninori Morimoto int err; 30ba9c949fSKuninori Morimoto }; 31ba9c949fSKuninori Morimoto 32ba9c949fSKuninori Morimoto #define RSND_SRC_NAME_SIZE 16 33ba9c949fSKuninori Morimoto 34232c00b6SKuninori Morimoto #define rsnd_src_to_dma(src) ((src)->dma) 35da599fd3SKuninori Morimoto #define rsnd_src_nr(priv) ((priv)->src_nr) 3643cb6954SKuninori Morimoto #define rsnd_enable_sync_convert(src) ((src)->sen.val) 3782e76ed3SKuninori Morimoto #define rsnd_src_of_node(priv) \ 3882e76ed3SKuninori Morimoto of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,src") 3982e76ed3SKuninori Morimoto 40ba9c949fSKuninori Morimoto #define rsnd_mod_to_src(_mod) \ 41ba9c949fSKuninori Morimoto container_of((_mod), struct rsnd_src, mod) 42ba9c949fSKuninori Morimoto 43ba9c949fSKuninori Morimoto #define for_each_rsnd_src(pos, priv, i) \ 44ba9c949fSKuninori Morimoto for ((i) = 0; \ 45ba9c949fSKuninori Morimoto ((i) < rsnd_src_nr(priv)) && \ 46ba9c949fSKuninori Morimoto ((pos) = (struct rsnd_src *)(priv)->src + i); \ 47ba9c949fSKuninori Morimoto i++) 48ba9c949fSKuninori Morimoto 49ba9c949fSKuninori Morimoto 50ba9c949fSKuninori Morimoto /* 51ba9c949fSKuninori Morimoto * image of SRC (Sampling Rate Converter) 52ba9c949fSKuninori Morimoto * 53ba9c949fSKuninori Morimoto * 96kHz <-> +-----+ 48kHz +-----+ 48kHz +-------+ 54ba9c949fSKuninori Morimoto * 48kHz <-> | SRC | <------> | SSI | <-----> | codec | 55ba9c949fSKuninori Morimoto * 44.1kHz <-> +-----+ +-----+ +-------+ 56ba9c949fSKuninori Morimoto * ... 57ba9c949fSKuninori Morimoto * 58ba9c949fSKuninori Morimoto */ 59ba9c949fSKuninori Morimoto 60ba9c949fSKuninori Morimoto /* 61ba9c949fSKuninori Morimoto * src.c is caring... 62ba9c949fSKuninori Morimoto * 63ba9c949fSKuninori Morimoto * Gen1 64ba9c949fSKuninori Morimoto * 65ba9c949fSKuninori Morimoto * [mem] -> [SRU] -> [SSI] 66ba9c949fSKuninori Morimoto * |--------| 67ba9c949fSKuninori Morimoto * 68ba9c949fSKuninori Morimoto * Gen2 69ba9c949fSKuninori Morimoto * 70ba9c949fSKuninori Morimoto * [mem] -> [SRC] -> [SSIU] -> [SSI] 71ba9c949fSKuninori Morimoto * |-----------------| 72ba9c949fSKuninori Morimoto */ 73ba9c949fSKuninori Morimoto 74ba9c949fSKuninori Morimoto /* 75ba9c949fSKuninori Morimoto * How to use SRC bypass mode for debugging 76ba9c949fSKuninori Morimoto * 77ba9c949fSKuninori Morimoto * SRC has bypass mode, and it is useful for debugging. 78ba9c949fSKuninori Morimoto * In Gen2 case, 79ba9c949fSKuninori Morimoto * SRCm_MODE controls whether SRC is used or not 80ba9c949fSKuninori Morimoto * SSI_MODE0 controls whether SSIU which receives SRC data 81ba9c949fSKuninori Morimoto * is used or not. 82ba9c949fSKuninori Morimoto * Both SRCm_MODE/SSI_MODE0 settings are needed if you use SRC, 83ba9c949fSKuninori Morimoto * but SRC bypass mode needs SSI_MODE0 only. 84ba9c949fSKuninori Morimoto * 85ba9c949fSKuninori Morimoto * This driver request 86ba9c949fSKuninori Morimoto * struct rsnd_src_platform_info { 87ba9c949fSKuninori Morimoto * u32 convert_rate; 8829e69fd2SKuninori Morimoto * int dma_id; 89ba9c949fSKuninori Morimoto * } 90ba9c949fSKuninori Morimoto * 91ba9c949fSKuninori Morimoto * rsnd_src_convert_rate() indicates 92ba9c949fSKuninori Morimoto * above convert_rate, and it controls 93ba9c949fSKuninori Morimoto * whether SRC is used or not. 94ba9c949fSKuninori Morimoto * 95ba9c949fSKuninori Morimoto * ex) doesn't use SRC 9629e69fd2SKuninori Morimoto * static struct rsnd_dai_platform_info rsnd_dai = { 9729e69fd2SKuninori Morimoto * .playback = { .ssi = &rsnd_ssi[0], }, 98ba9c949fSKuninori Morimoto * }; 99ba9c949fSKuninori Morimoto * 100ba9c949fSKuninori Morimoto * ex) uses SRC 10129e69fd2SKuninori Morimoto * static struct rsnd_src_platform_info rsnd_src[] = { 10229e69fd2SKuninori Morimoto * RSND_SCU(48000, 0), 10329e69fd2SKuninori Morimoto * ... 10429e69fd2SKuninori Morimoto * }; 10529e69fd2SKuninori Morimoto * static struct rsnd_dai_platform_info rsnd_dai = { 10629e69fd2SKuninori Morimoto * .playback = { .ssi = &rsnd_ssi[0], .src = &rsnd_src[0] }, 107ba9c949fSKuninori Morimoto * }; 108ba9c949fSKuninori Morimoto * 109ba9c949fSKuninori Morimoto * ex) uses SRC bypass mode 11029e69fd2SKuninori Morimoto * static struct rsnd_src_platform_info rsnd_src[] = { 11129e69fd2SKuninori Morimoto * RSND_SCU(0, 0), 11229e69fd2SKuninori Morimoto * ... 11329e69fd2SKuninori Morimoto * }; 11429e69fd2SKuninori Morimoto * static struct rsnd_dai_platform_info rsnd_dai = { 11529e69fd2SKuninori Morimoto * .playback = { .ssi = &rsnd_ssi[0], .src = &rsnd_src[0] }, 116ba9c949fSKuninori Morimoto * }; 117ba9c949fSKuninori Morimoto * 118ba9c949fSKuninori Morimoto */ 119ba9c949fSKuninori Morimoto 120ba9c949fSKuninori Morimoto /* 121ba9c949fSKuninori Morimoto * Gen1/Gen2 common functions 122ba9c949fSKuninori Morimoto */ 123379febfdSKuninori Morimoto static void rsnd_src_soft_reset(struct rsnd_mod *mod) 124379febfdSKuninori Morimoto { 125379febfdSKuninori Morimoto rsnd_mod_write(mod, SRC_SWRSR, 0); 126379febfdSKuninori Morimoto rsnd_mod_write(mod, SRC_SWRSR, 1); 127379febfdSKuninori Morimoto } 128379febfdSKuninori Morimoto 129d1ade514SKuninori Morimoto 130d1ade514SKuninori Morimoto #define rsnd_src_initialize_lock(mod) __rsnd_src_initialize_lock(mod, 1) 131d1ade514SKuninori Morimoto #define rsnd_src_initialize_unlock(mod) __rsnd_src_initialize_lock(mod, 0) 132d1ade514SKuninori Morimoto static void __rsnd_src_initialize_lock(struct rsnd_mod *mod, u32 enable) 133d1ade514SKuninori Morimoto { 134d1ade514SKuninori Morimoto rsnd_mod_write(mod, SRC_SRCIR, enable); 135d1ade514SKuninori Morimoto } 136d1ade514SKuninori Morimoto 1379b99e9a7SKuninori Morimoto static struct dma_chan *rsnd_src_dma_req(struct rsnd_dai_stream *io, 1389b99e9a7SKuninori Morimoto struct rsnd_mod *mod) 13972adc61fSKuninori Morimoto { 14072adc61fSKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 14172adc61fSKuninori Morimoto int is_play = rsnd_io_is_play(io); 14272adc61fSKuninori Morimoto 14372adc61fSKuninori Morimoto return rsnd_dma_request_channel(rsnd_src_of_node(priv), 14472adc61fSKuninori Morimoto mod, 14572adc61fSKuninori Morimoto is_play ? "rx" : "tx"); 14672adc61fSKuninori Morimoto } 14772adc61fSKuninori Morimoto 148d9288d0bSKuninori Morimoto int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, 1494e2639ffSKuninori Morimoto struct rsnd_dai_stream *io, 150d9288d0bSKuninori Morimoto int use_busif) 151ba9c949fSKuninori Morimoto { 152f708d944SKuninori Morimoto struct rsnd_dai *rdai = rsnd_io_to_rdai(io); 153ba9c949fSKuninori Morimoto int ssi_id = rsnd_mod_id(ssi_mod); 154ba9c949fSKuninori Morimoto 155ba9c949fSKuninori Morimoto /* 156ba9c949fSKuninori Morimoto * SSI_MODE0 157ba9c949fSKuninori Morimoto */ 158ba9c949fSKuninori Morimoto rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id), 159d9288d0bSKuninori Morimoto !use_busif << ssi_id); 160ba9c949fSKuninori Morimoto 161ba9c949fSKuninori Morimoto /* 162ba9c949fSKuninori Morimoto * SSI_MODE1 163ba9c949fSKuninori Morimoto */ 164b415b4d3SKuninori Morimoto if (rsnd_ssi_is_pin_sharing(io)) { 165ba9c949fSKuninori Morimoto int shift = -1; 166ba9c949fSKuninori Morimoto switch (ssi_id) { 167ba9c949fSKuninori Morimoto case 1: 168ba9c949fSKuninori Morimoto shift = 0; 169ba9c949fSKuninori Morimoto break; 170ba9c949fSKuninori Morimoto case 2: 171ba9c949fSKuninori Morimoto shift = 2; 172ba9c949fSKuninori Morimoto break; 173ba9c949fSKuninori Morimoto case 4: 174ba9c949fSKuninori Morimoto shift = 16; 175ba9c949fSKuninori Morimoto break; 176ba9c949fSKuninori Morimoto } 177ba9c949fSKuninori Morimoto 178ba9c949fSKuninori Morimoto if (shift >= 0) 179ba9c949fSKuninori Morimoto rsnd_mod_bset(ssi_mod, SSI_MODE1, 180ba9c949fSKuninori Morimoto 0x3 << shift, 1813ed6448cSKuninori Morimoto rsnd_rdai_is_clk_master(rdai) ? 182ba9c949fSKuninori Morimoto 0x2 << shift : 0x1 << shift); 183ba9c949fSKuninori Morimoto } 184ba9c949fSKuninori Morimoto 185d9288d0bSKuninori Morimoto /* 186d9288d0bSKuninori Morimoto * DMA settings for SSIU 187d9288d0bSKuninori Morimoto */ 188d9288d0bSKuninori Morimoto if (use_busif) { 1894689032bSKuninori Morimoto u32 val = rsnd_get_dalign(ssi_mod, io); 1901cc71959SKuninori Morimoto 191d9288d0bSKuninori Morimoto rsnd_mod_write(ssi_mod, SSI_BUSIF_ADINR, 1923023b384SKuninori Morimoto rsnd_get_adinr_bit(ssi_mod, io)); 193d9288d0bSKuninori Morimoto rsnd_mod_write(ssi_mod, SSI_BUSIF_MODE, 1); 194d9288d0bSKuninori Morimoto rsnd_mod_write(ssi_mod, SSI_CTRL, 0x1); 1951cc71959SKuninori Morimoto 196cdde84d1SKuninori Morimoto rsnd_mod_write(ssi_mod, SSI_BUSIF_DALIGN, val); 197d9288d0bSKuninori Morimoto } 198d9288d0bSKuninori Morimoto 199d9288d0bSKuninori Morimoto return 0; 200d9288d0bSKuninori Morimoto } 201d9288d0bSKuninori Morimoto 2024e2639ffSKuninori Morimoto int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod, 2034e2639ffSKuninori Morimoto struct rsnd_dai_stream *io) 204d9288d0bSKuninori Morimoto { 205d9288d0bSKuninori Morimoto /* 206d9288d0bSKuninori Morimoto * DMA settings for SSIU 207d9288d0bSKuninori Morimoto */ 208d9288d0bSKuninori Morimoto rsnd_mod_write(ssi_mod, SSI_CTRL, 0); 209d9288d0bSKuninori Morimoto 210ba9c949fSKuninori Morimoto return 0; 211ba9c949fSKuninori Morimoto } 212ba9c949fSKuninori Morimoto 21388c61cffSKuninori Morimoto static u32 rsnd_src_convert_rate(struct rsnd_dai_stream *io, 21488c61cffSKuninori Morimoto struct rsnd_src *src) 21543cb6954SKuninori Morimoto { 21643cb6954SKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 21743cb6954SKuninori Morimoto u32 convert_rate; 21843cb6954SKuninori Morimoto 21943cb6954SKuninori Morimoto if (!runtime) 22043cb6954SKuninori Morimoto return 0; 22143cb6954SKuninori Morimoto 22243cb6954SKuninori Morimoto if (!rsnd_enable_sync_convert(src)) 22343cb6954SKuninori Morimoto return src->convert_rate; 22443cb6954SKuninori Morimoto 22543cb6954SKuninori Morimoto convert_rate = src->sync.val; 22643cb6954SKuninori Morimoto 22743cb6954SKuninori Morimoto if (!convert_rate) 22843cb6954SKuninori Morimoto convert_rate = src->convert_rate; 22943cb6954SKuninori Morimoto 23043cb6954SKuninori Morimoto if (!convert_rate) 23143cb6954SKuninori Morimoto convert_rate = runtime->rate; 23243cb6954SKuninori Morimoto 23343cb6954SKuninori Morimoto return convert_rate; 23443cb6954SKuninori Morimoto } 23543cb6954SKuninori Morimoto 236ba9c949fSKuninori Morimoto unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, 237ba9c949fSKuninori Morimoto struct rsnd_dai_stream *io, 238ba9c949fSKuninori Morimoto struct snd_pcm_runtime *runtime) 239ba9c949fSKuninori Morimoto { 240b1eac430SKuninori Morimoto struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); 241ba9c949fSKuninori Morimoto struct rsnd_src *src; 242b1eac430SKuninori Morimoto unsigned int rate = 0; 243ba9c949fSKuninori Morimoto 244b1eac430SKuninori Morimoto if (src_mod) { 245b1eac430SKuninori Morimoto src = rsnd_mod_to_src(src_mod); 246ba9c949fSKuninori Morimoto 247ba9c949fSKuninori Morimoto /* 248ba9c949fSKuninori Morimoto * return convert rate if SRC is used, 249ba9c949fSKuninori Morimoto * otherwise, return runtime->rate as usual 250ba9c949fSKuninori Morimoto */ 25188c61cffSKuninori Morimoto rate = rsnd_src_convert_rate(io, src); 252b1eac430SKuninori Morimoto } 253b1eac430SKuninori Morimoto 254ba9c949fSKuninori Morimoto if (!rate) 255ba9c949fSKuninori Morimoto rate = runtime->rate; 256ba9c949fSKuninori Morimoto 257ba9c949fSKuninori Morimoto return rate; 258ba9c949fSKuninori Morimoto } 259ba9c949fSKuninori Morimoto 2604e2639ffSKuninori Morimoto static int rsnd_src_set_convert_rate(struct rsnd_mod *mod, 2614e2639ffSKuninori Morimoto struct rsnd_dai_stream *io) 262ba9c949fSKuninori Morimoto { 263ba9c949fSKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 264ba9c949fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 26588c61cffSKuninori Morimoto u32 convert_rate = rsnd_src_convert_rate(io, src); 266ba9c949fSKuninori Morimoto u32 fsrate = 0; 267ba9c949fSKuninori Morimoto 268ba9c949fSKuninori Morimoto if (convert_rate) 269ba9c949fSKuninori Morimoto fsrate = 0x0400000 / convert_rate * runtime->rate; 270ba9c949fSKuninori Morimoto 271ba9c949fSKuninori Morimoto /* Set channel number and output bit length */ 2723023b384SKuninori Morimoto rsnd_mod_write(mod, SRC_ADINR, rsnd_get_adinr_bit(mod, io)); 273ba9c949fSKuninori Morimoto 274ba9c949fSKuninori Morimoto /* Enable the initial value of IFS */ 275ba9c949fSKuninori Morimoto if (fsrate) { 276ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_IFSCR, 1); 277ba9c949fSKuninori Morimoto 278ba9c949fSKuninori Morimoto /* Set initial value of IFS */ 279ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_IFSVR, fsrate); 280ba9c949fSKuninori Morimoto } 281ba9c949fSKuninori Morimoto 282ba9c949fSKuninori Morimoto /* use DMA transfer */ 283ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_BUSIF_MODE, 1); 284ba9c949fSKuninori Morimoto 285ba9c949fSKuninori Morimoto return 0; 286ba9c949fSKuninori Morimoto } 287ba9c949fSKuninori Morimoto 2883b7843ffSKuninori Morimoto static int rsnd_src_hw_params(struct rsnd_mod *mod, 2892c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 2903b7843ffSKuninori Morimoto struct snd_pcm_substream *substream, 2913b7843ffSKuninori Morimoto struct snd_pcm_hw_params *fe_params) 2923b7843ffSKuninori Morimoto { 2933b7843ffSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 2943b7843ffSKuninori Morimoto struct snd_soc_pcm_runtime *fe = substream->private_data; 2953b7843ffSKuninori Morimoto 2963b7843ffSKuninori Morimoto /* default value (mainly for non-DT) */ 2973b7843ffSKuninori Morimoto src->convert_rate = src->info->convert_rate; 2983b7843ffSKuninori Morimoto 2993b7843ffSKuninori Morimoto /* 3003b7843ffSKuninori Morimoto * SRC assumes that it is used under DPCM if user want to use 3013b7843ffSKuninori Morimoto * sampling rate convert. Then, SRC should be FE. 3023b7843ffSKuninori Morimoto * And then, this function will be called *after* BE settings. 3033b7843ffSKuninori Morimoto * this means, each BE already has fixuped hw_params. 3043b7843ffSKuninori Morimoto * see 3053b7843ffSKuninori Morimoto * dpcm_fe_dai_hw_params() 3063b7843ffSKuninori Morimoto * dpcm_be_dai_hw_params() 3073b7843ffSKuninori Morimoto */ 3083b7843ffSKuninori Morimoto if (fe->dai_link->dynamic) { 3093b7843ffSKuninori Morimoto int stream = substream->stream; 3103b7843ffSKuninori Morimoto struct snd_soc_dpcm *dpcm; 3113b7843ffSKuninori Morimoto struct snd_pcm_hw_params *be_params; 3123b7843ffSKuninori Morimoto 3133b7843ffSKuninori Morimoto list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { 3143b7843ffSKuninori Morimoto be_params = &dpcm->hw_params; 3153b7843ffSKuninori Morimoto 3163b7843ffSKuninori Morimoto if (params_rate(fe_params) != params_rate(be_params)) 3173b7843ffSKuninori Morimoto src->convert_rate = params_rate(be_params); 3183b7843ffSKuninori Morimoto } 3193b7843ffSKuninori Morimoto } 3203b7843ffSKuninori Morimoto 3213b7843ffSKuninori Morimoto return 0; 3223b7843ffSKuninori Morimoto } 3233b7843ffSKuninori Morimoto 3243b7843ffSKuninori Morimoto static int rsnd_src_init(struct rsnd_mod *mod, 3253b7843ffSKuninori Morimoto struct rsnd_priv *priv) 326ba9c949fSKuninori Morimoto { 327ba9c949fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 328ba9c949fSKuninori Morimoto 329c9929345SKuninori Morimoto rsnd_mod_power_on(mod); 330ba9c949fSKuninori Morimoto 331379febfdSKuninori Morimoto rsnd_src_soft_reset(mod); 332379febfdSKuninori Morimoto 333d1ade514SKuninori Morimoto rsnd_src_initialize_lock(mod); 334d1ade514SKuninori Morimoto 335cfcefe01SKuninori Morimoto src->err = 0; 336cfcefe01SKuninori Morimoto 33743cb6954SKuninori Morimoto /* reset sync convert_rate */ 33843cb6954SKuninori Morimoto src->sync.val = 0; 33943cb6954SKuninori Morimoto 340ba9c949fSKuninori Morimoto return 0; 341ba9c949fSKuninori Morimoto } 342ba9c949fSKuninori Morimoto 343ba9c949fSKuninori Morimoto static int rsnd_src_quit(struct rsnd_mod *mod, 3442c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 345690602fcSKuninori Morimoto struct rsnd_priv *priv) 346ba9c949fSKuninori Morimoto { 347ba9c949fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 348cfcefe01SKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 349ba9c949fSKuninori Morimoto 350c9929345SKuninori Morimoto rsnd_mod_power_off(mod); 351ba9c949fSKuninori Morimoto 352cfcefe01SKuninori Morimoto if (src->err) 353337b0b4cSKuninori Morimoto dev_warn(dev, "%s[%d] under/over flow err = %d\n", 354337b0b4cSKuninori Morimoto rsnd_mod_name(mod), rsnd_mod_id(mod), src->err); 355cfcefe01SKuninori Morimoto 3563b7843ffSKuninori Morimoto src->convert_rate = 0; 3573b7843ffSKuninori Morimoto 35843cb6954SKuninori Morimoto /* reset sync convert_rate */ 35943cb6954SKuninori Morimoto src->sync.val = 0; 36043cb6954SKuninori Morimoto 361ba9c949fSKuninori Morimoto return 0; 362ba9c949fSKuninori Morimoto } 363ba9c949fSKuninori Morimoto 364f0ef0cb8SKuninori Morimoto static int rsnd_src_start(struct rsnd_mod *mod) 365ba9c949fSKuninori Morimoto { 366d1ade514SKuninori Morimoto rsnd_src_initialize_unlock(mod); 367ba9c949fSKuninori Morimoto 368ba9c949fSKuninori Morimoto return 0; 369ba9c949fSKuninori Morimoto } 370ba9c949fSKuninori Morimoto 371f0ef0cb8SKuninori Morimoto static int rsnd_src_stop(struct rsnd_mod *mod) 372ba9c949fSKuninori Morimoto { 373933cc8cbSKuninori Morimoto /* nothing to do */ 374ba9c949fSKuninori Morimoto return 0; 375ba9c949fSKuninori Morimoto } 376ba9c949fSKuninori Morimoto 377ba9c949fSKuninori Morimoto /* 378ba9c949fSKuninori Morimoto * Gen1 functions 379ba9c949fSKuninori Morimoto */ 38088c61cffSKuninori Morimoto static int rsnd_src_set_route_gen1(struct rsnd_dai_stream *io, 38188c61cffSKuninori Morimoto struct rsnd_mod *mod) 382ba9c949fSKuninori Morimoto { 383ba9c949fSKuninori Morimoto struct src_route_config { 384ba9c949fSKuninori Morimoto u32 mask; 385ba9c949fSKuninori Morimoto int shift; 386ba9c949fSKuninori Morimoto } routes[] = { 387ba9c949fSKuninori Morimoto { 0xF, 0, }, /* 0 */ 388ba9c949fSKuninori Morimoto { 0xF, 4, }, /* 1 */ 389ba9c949fSKuninori Morimoto { 0xF, 8, }, /* 2 */ 390ba9c949fSKuninori Morimoto { 0x7, 12, }, /* 3 */ 391ba9c949fSKuninori Morimoto { 0x7, 16, }, /* 4 */ 392ba9c949fSKuninori Morimoto { 0x7, 20, }, /* 5 */ 393ba9c949fSKuninori Morimoto { 0x7, 24, }, /* 6 */ 394ba9c949fSKuninori Morimoto { 0x3, 28, }, /* 7 */ 395ba9c949fSKuninori Morimoto { 0x3, 30, }, /* 8 */ 396ba9c949fSKuninori Morimoto }; 397ba9c949fSKuninori Morimoto u32 mask; 398ba9c949fSKuninori Morimoto u32 val; 399ba9c949fSKuninori Morimoto int id; 400ba9c949fSKuninori Morimoto 401ba9c949fSKuninori Morimoto id = rsnd_mod_id(mod); 402ba9c949fSKuninori Morimoto if (id < 0 || id >= ARRAY_SIZE(routes)) 403ba9c949fSKuninori Morimoto return -EIO; 404ba9c949fSKuninori Morimoto 405ba9c949fSKuninori Morimoto /* 406ba9c949fSKuninori Morimoto * SRC_ROUTE_SELECT 407ba9c949fSKuninori Morimoto */ 408985a4f6eSKuninori Morimoto val = rsnd_io_is_play(io) ? 0x1 : 0x2; 409ba9c949fSKuninori Morimoto val = val << routes[id].shift; 410ba9c949fSKuninori Morimoto mask = routes[id].mask << routes[id].shift; 411ba9c949fSKuninori Morimoto 412ba9c949fSKuninori Morimoto rsnd_mod_bset(mod, SRC_ROUTE_SEL, mask, val); 413ba9c949fSKuninori Morimoto 414ba9c949fSKuninori Morimoto return 0; 415ba9c949fSKuninori Morimoto } 416ba9c949fSKuninori Morimoto 41788c61cffSKuninori Morimoto static int rsnd_src_set_convert_timing_gen1(struct rsnd_dai_stream *io, 41888c61cffSKuninori Morimoto struct rsnd_mod *mod) 419ba9c949fSKuninori Morimoto { 420ba9c949fSKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 421ba9c949fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 422ba9c949fSKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 42388c61cffSKuninori Morimoto u32 convert_rate = rsnd_src_convert_rate(io, src); 424ba9c949fSKuninori Morimoto u32 mask; 425ba9c949fSKuninori Morimoto u32 val; 426ba9c949fSKuninori Morimoto int shift; 427ba9c949fSKuninori Morimoto int id = rsnd_mod_id(mod); 428ba9c949fSKuninori Morimoto int ret; 429ba9c949fSKuninori Morimoto 430ba9c949fSKuninori Morimoto /* 431ba9c949fSKuninori Morimoto * SRC_TIMING_SELECT 432ba9c949fSKuninori Morimoto */ 433ba9c949fSKuninori Morimoto shift = (id % 4) * 8; 434ba9c949fSKuninori Morimoto mask = 0x1F << shift; 435ba9c949fSKuninori Morimoto 436ba9c949fSKuninori Morimoto /* 437ba9c949fSKuninori Morimoto * ADG is used as source clock if SRC was used, 438ba9c949fSKuninori Morimoto * then, SSI WS is used as destination clock. 439ba9c949fSKuninori Morimoto * SSI WS is used as source clock if SRC is not used 440ba9c949fSKuninori Morimoto * (when playback, source/destination become reverse when capture) 441ba9c949fSKuninori Morimoto */ 442ba9c949fSKuninori Morimoto ret = 0; 443ba9c949fSKuninori Morimoto if (convert_rate) { 444ba9c949fSKuninori Morimoto /* use ADG */ 445ba9c949fSKuninori Morimoto val = 0; 446ba9c949fSKuninori Morimoto ret = rsnd_adg_set_convert_clk_gen1(priv, mod, 447ba9c949fSKuninori Morimoto runtime->rate, 448ba9c949fSKuninori Morimoto convert_rate); 449ba9c949fSKuninori Morimoto } else if (8 == id) { 450ba9c949fSKuninori Morimoto /* use SSI WS, but SRU8 is special */ 451ba9c949fSKuninori Morimoto val = id << shift; 452ba9c949fSKuninori Morimoto } else { 453ba9c949fSKuninori Morimoto /* use SSI WS */ 454ba9c949fSKuninori Morimoto val = (id + 1) << shift; 455ba9c949fSKuninori Morimoto } 456ba9c949fSKuninori Morimoto 457ba9c949fSKuninori Morimoto if (ret < 0) 458ba9c949fSKuninori Morimoto return ret; 459ba9c949fSKuninori Morimoto 460ba9c949fSKuninori Morimoto switch (id / 4) { 461ba9c949fSKuninori Morimoto case 0: 462ba9c949fSKuninori Morimoto rsnd_mod_bset(mod, SRC_TMG_SEL0, mask, val); 463ba9c949fSKuninori Morimoto break; 464ba9c949fSKuninori Morimoto case 1: 465ba9c949fSKuninori Morimoto rsnd_mod_bset(mod, SRC_TMG_SEL1, mask, val); 466ba9c949fSKuninori Morimoto break; 467ba9c949fSKuninori Morimoto case 2: 468ba9c949fSKuninori Morimoto rsnd_mod_bset(mod, SRC_TMG_SEL2, mask, val); 469ba9c949fSKuninori Morimoto break; 470ba9c949fSKuninori Morimoto } 471ba9c949fSKuninori Morimoto 472ba9c949fSKuninori Morimoto return 0; 473ba9c949fSKuninori Morimoto } 474ba9c949fSKuninori Morimoto 4754e2639ffSKuninori Morimoto static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod, 4764e2639ffSKuninori Morimoto struct rsnd_dai_stream *io) 477ba9c949fSKuninori Morimoto { 478933cc8cbSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 479ba9c949fSKuninori Morimoto int ret; 480ba9c949fSKuninori Morimoto 4814e2639ffSKuninori Morimoto ret = rsnd_src_set_convert_rate(mod, io); 482ba9c949fSKuninori Morimoto if (ret < 0) 483ba9c949fSKuninori Morimoto return ret; 484ba9c949fSKuninori Morimoto 485ba9c949fSKuninori Morimoto /* Select SRC mode (fixed value) */ 486ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_SRCCR, 0x00010110); 487ba9c949fSKuninori Morimoto 488ba9c949fSKuninori Morimoto /* Set the restriction value of the FS ratio (98%) */ 489ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_MNFSR, 490ba9c949fSKuninori Morimoto rsnd_mod_read(mod, SRC_IFSVR) / 100 * 98); 491ba9c949fSKuninori Morimoto 492933cc8cbSKuninori Morimoto /* Gen1/Gen2 are not compatible */ 49388c61cffSKuninori Morimoto if (rsnd_src_convert_rate(io, src)) 494933cc8cbSKuninori Morimoto rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); 495933cc8cbSKuninori Morimoto 496ba9c949fSKuninori Morimoto /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ 497ba9c949fSKuninori Morimoto 498ba9c949fSKuninori Morimoto return 0; 499ba9c949fSKuninori Morimoto } 500ba9c949fSKuninori Morimoto 501ba9c949fSKuninori Morimoto static int rsnd_src_init_gen1(struct rsnd_mod *mod, 5022c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 503690602fcSKuninori Morimoto struct rsnd_priv *priv) 504ba9c949fSKuninori Morimoto { 505ba9c949fSKuninori Morimoto int ret; 506ba9c949fSKuninori Morimoto 5073b7843ffSKuninori Morimoto ret = rsnd_src_init(mod, priv); 508ba9c949fSKuninori Morimoto if (ret < 0) 509ba9c949fSKuninori Morimoto return ret; 510ba9c949fSKuninori Morimoto 51188c61cffSKuninori Morimoto ret = rsnd_src_set_route_gen1(io, mod); 512ba9c949fSKuninori Morimoto if (ret < 0) 513ba9c949fSKuninori Morimoto return ret; 514ba9c949fSKuninori Morimoto 5154e2639ffSKuninori Morimoto ret = rsnd_src_set_convert_rate_gen1(mod, io); 516ba9c949fSKuninori Morimoto if (ret < 0) 517ba9c949fSKuninori Morimoto return ret; 518ba9c949fSKuninori Morimoto 51988c61cffSKuninori Morimoto ret = rsnd_src_set_convert_timing_gen1(io, mod); 520ba9c949fSKuninori Morimoto if (ret < 0) 521ba9c949fSKuninori Morimoto return ret; 522ba9c949fSKuninori Morimoto 523ba9c949fSKuninori Morimoto return 0; 524ba9c949fSKuninori Morimoto } 525ba9c949fSKuninori Morimoto 526ba9c949fSKuninori Morimoto static int rsnd_src_start_gen1(struct rsnd_mod *mod, 5272c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 528690602fcSKuninori Morimoto struct rsnd_priv *priv) 529ba9c949fSKuninori Morimoto { 530ba9c949fSKuninori Morimoto int id = rsnd_mod_id(mod); 531ba9c949fSKuninori Morimoto 532ba9c949fSKuninori Morimoto rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id)); 533ba9c949fSKuninori Morimoto 534f0ef0cb8SKuninori Morimoto return rsnd_src_start(mod); 535ba9c949fSKuninori Morimoto } 536ba9c949fSKuninori Morimoto 537ba9c949fSKuninori Morimoto static int rsnd_src_stop_gen1(struct rsnd_mod *mod, 5382c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 539690602fcSKuninori Morimoto struct rsnd_priv *priv) 540ba9c949fSKuninori Morimoto { 541ba9c949fSKuninori Morimoto int id = rsnd_mod_id(mod); 542ba9c949fSKuninori Morimoto 543ba9c949fSKuninori Morimoto rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0); 544ba9c949fSKuninori Morimoto 545f0ef0cb8SKuninori Morimoto return rsnd_src_stop(mod); 546ba9c949fSKuninori Morimoto } 547ba9c949fSKuninori Morimoto 548ba9c949fSKuninori Morimoto static struct rsnd_mod_ops rsnd_src_gen1_ops = { 5498aefda50SKuninori Morimoto .name = SRC_NAME, 55072adc61fSKuninori Morimoto .dma_req = rsnd_src_dma_req, 551ba9c949fSKuninori Morimoto .init = rsnd_src_init_gen1, 552ba9c949fSKuninori Morimoto .quit = rsnd_src_quit, 553ba9c949fSKuninori Morimoto .start = rsnd_src_start_gen1, 554ba9c949fSKuninori Morimoto .stop = rsnd_src_stop_gen1, 5553b7843ffSKuninori Morimoto .hw_params = rsnd_src_hw_params, 556ba9c949fSKuninori Morimoto }; 557ba9c949fSKuninori Morimoto 558ba9c949fSKuninori Morimoto /* 559ba9c949fSKuninori Morimoto * Gen2 functions 560ba9c949fSKuninori Morimoto */ 561cfcefe01SKuninori Morimoto #define rsnd_src_irq_enable_gen2(mod) rsnd_src_irq_ctrol_gen2(mod, 1) 562cfcefe01SKuninori Morimoto #define rsnd_src_irq_disable_gen2(mod) rsnd_src_irq_ctrol_gen2(mod, 0) 563cfcefe01SKuninori Morimoto static void rsnd_src_irq_ctrol_gen2(struct rsnd_mod *mod, int enable) 564cfcefe01SKuninori Morimoto { 565cfcefe01SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 566cfcefe01SKuninori Morimoto u32 sys_int_val, int_val, sys_int_mask; 567cfcefe01SKuninori Morimoto int irq = src->info->irq; 568cfcefe01SKuninori Morimoto int id = rsnd_mod_id(mod); 569cfcefe01SKuninori Morimoto 570cfcefe01SKuninori Morimoto sys_int_val = 571cfcefe01SKuninori Morimoto sys_int_mask = OUF_SRC(id); 572cfcefe01SKuninori Morimoto int_val = 0x3300; 573cfcefe01SKuninori Morimoto 574cfcefe01SKuninori Morimoto /* 575cfcefe01SKuninori Morimoto * IRQ is not supported on non-DT 576cfcefe01SKuninori Morimoto * see 577cfcefe01SKuninori Morimoto * rsnd_src_probe_gen2() 578cfcefe01SKuninori Morimoto */ 579cfcefe01SKuninori Morimoto if ((irq <= 0) || !enable) { 580cfcefe01SKuninori Morimoto sys_int_val = 0; 581cfcefe01SKuninori Morimoto int_val = 0; 582cfcefe01SKuninori Morimoto } 583cfcefe01SKuninori Morimoto 5841a1bf58aSKuninori Morimoto /* 5851a1bf58aSKuninori Morimoto * WORKAROUND 5861a1bf58aSKuninori Morimoto * 5871a1bf58aSKuninori Morimoto * ignore over flow error when rsnd_enable_sync_convert() 5881a1bf58aSKuninori Morimoto */ 5891a1bf58aSKuninori Morimoto if (rsnd_enable_sync_convert(src)) 5901a1bf58aSKuninori Morimoto sys_int_val = sys_int_val & 0xffff; 5911a1bf58aSKuninori Morimoto 592cfcefe01SKuninori Morimoto rsnd_mod_write(mod, SRC_INT_ENABLE0, int_val); 593cfcefe01SKuninori Morimoto rsnd_mod_bset(mod, SCU_SYS_INT_EN0, sys_int_mask, sys_int_val); 594cfcefe01SKuninori Morimoto rsnd_mod_bset(mod, SCU_SYS_INT_EN1, sys_int_mask, sys_int_val); 595cfcefe01SKuninori Morimoto } 596cfcefe01SKuninori Morimoto 597cfcefe01SKuninori Morimoto static void rsnd_src_error_clear_gen2(struct rsnd_mod *mod) 598cfcefe01SKuninori Morimoto { 599cfcefe01SKuninori Morimoto u32 val = OUF_SRC(rsnd_mod_id(mod)); 600cfcefe01SKuninori Morimoto 601cfcefe01SKuninori Morimoto rsnd_mod_bset(mod, SCU_SYS_STATUS0, val, val); 602cfcefe01SKuninori Morimoto rsnd_mod_bset(mod, SCU_SYS_STATUS1, val, val); 603cfcefe01SKuninori Morimoto } 604cfcefe01SKuninori Morimoto 605cfcefe01SKuninori Morimoto static bool rsnd_src_error_record_gen2(struct rsnd_mod *mod) 606cfcefe01SKuninori Morimoto { 6071a1bf58aSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 6081a1bf58aSKuninori Morimoto u32 val0, val1; 609cfcefe01SKuninori Morimoto bool ret = false; 610cfcefe01SKuninori Morimoto 6111a1bf58aSKuninori Morimoto val0 = val1 = OUF_SRC(rsnd_mod_id(mod)); 6121a1bf58aSKuninori Morimoto 6131a1bf58aSKuninori Morimoto /* 6141a1bf58aSKuninori Morimoto * WORKAROUND 6151a1bf58aSKuninori Morimoto * 6161a1bf58aSKuninori Morimoto * ignore over flow error when rsnd_enable_sync_convert() 6171a1bf58aSKuninori Morimoto */ 6181a1bf58aSKuninori Morimoto if (rsnd_enable_sync_convert(src)) 6191a1bf58aSKuninori Morimoto val0 = val0 & 0xffff; 6201a1bf58aSKuninori Morimoto 6211a1bf58aSKuninori Morimoto if ((rsnd_mod_read(mod, SCU_SYS_STATUS0) & val0) || 6221a1bf58aSKuninori Morimoto (rsnd_mod_read(mod, SCU_SYS_STATUS1) & val1)) { 623cfcefe01SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 624cfcefe01SKuninori Morimoto 625cfcefe01SKuninori Morimoto src->err++; 626cfcefe01SKuninori Morimoto ret = true; 627cfcefe01SKuninori Morimoto } 628cfcefe01SKuninori Morimoto 629cfcefe01SKuninori Morimoto /* clear error static */ 630cfcefe01SKuninori Morimoto rsnd_src_error_clear_gen2(mod); 631cfcefe01SKuninori Morimoto 632cfcefe01SKuninori Morimoto return ret; 633cfcefe01SKuninori Morimoto } 634cfcefe01SKuninori Morimoto 63588c61cffSKuninori Morimoto static int _rsnd_src_start_gen2(struct rsnd_mod *mod, 63688c61cffSKuninori Morimoto struct rsnd_dai_stream *io) 637cfcefe01SKuninori Morimoto { 6381a1bf58aSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 6391a1bf58aSKuninori Morimoto u32 val; 6401a1bf58aSKuninori Morimoto 6414689032bSKuninori Morimoto val = rsnd_get_dalign(mod, io); 6424689032bSKuninori Morimoto 6434689032bSKuninori Morimoto rsnd_mod_write(mod, SRC_BUSIF_DALIGN, val); 6444689032bSKuninori Morimoto 6451a1bf58aSKuninori Morimoto /* 6461a1bf58aSKuninori Morimoto * WORKAROUND 6471a1bf58aSKuninori Morimoto * 6481a1bf58aSKuninori Morimoto * Enable SRC output if you want to use sync convert together with DVC 6491a1bf58aSKuninori Morimoto */ 6501a1bf58aSKuninori Morimoto val = (rsnd_io_to_mod_dvc(io) && !rsnd_enable_sync_convert(src)) ? 6511a1bf58aSKuninori Morimoto 0x01 : 0x11; 652cfcefe01SKuninori Morimoto 653cfcefe01SKuninori Morimoto rsnd_mod_write(mod, SRC_CTRL, val); 654cfcefe01SKuninori Morimoto 655cfcefe01SKuninori Morimoto rsnd_src_error_clear_gen2(mod); 656cfcefe01SKuninori Morimoto 657cfcefe01SKuninori Morimoto rsnd_src_start(mod); 658cfcefe01SKuninori Morimoto 659cfcefe01SKuninori Morimoto rsnd_src_irq_enable_gen2(mod); 660cfcefe01SKuninori Morimoto 661cfcefe01SKuninori Morimoto return 0; 662cfcefe01SKuninori Morimoto } 663cfcefe01SKuninori Morimoto 664cfcefe01SKuninori Morimoto static int _rsnd_src_stop_gen2(struct rsnd_mod *mod) 665cfcefe01SKuninori Morimoto { 666cfcefe01SKuninori Morimoto rsnd_src_irq_disable_gen2(mod); 667cfcefe01SKuninori Morimoto 668*b761bf27SKuninori Morimoto /* 669*b761bf27SKuninori Morimoto * stop SRC output only 670*b761bf27SKuninori Morimoto * see rsnd_src_quit_gen2 671*b761bf27SKuninori Morimoto */ 672*b761bf27SKuninori Morimoto rsnd_mod_write(mod, SRC_CTRL, 0x01); 673cfcefe01SKuninori Morimoto 674cfcefe01SKuninori Morimoto rsnd_src_error_record_gen2(mod); 675cfcefe01SKuninori Morimoto 676cfcefe01SKuninori Morimoto return rsnd_src_stop(mod); 677cfcefe01SKuninori Morimoto } 678cfcefe01SKuninori Morimoto 679*b761bf27SKuninori Morimoto static int rsnd_src_quit_gen2(struct rsnd_mod *mod, 680*b761bf27SKuninori Morimoto struct rsnd_dai_stream *io, 681*b761bf27SKuninori Morimoto struct rsnd_priv *priv) 682*b761bf27SKuninori Morimoto { 683*b761bf27SKuninori Morimoto /* stop both out/in */ 684*b761bf27SKuninori Morimoto rsnd_mod_write(mod, SRC_CTRL, 0); 685*b761bf27SKuninori Morimoto 686*b761bf27SKuninori Morimoto return 0; 687*b761bf27SKuninori Morimoto } 688*b761bf27SKuninori Morimoto 68988c61cffSKuninori Morimoto static void __rsnd_src_interrupt_gen2(struct rsnd_mod *mod, 69088c61cffSKuninori Morimoto struct rsnd_dai_stream *io) 691cfcefe01SKuninori Morimoto { 69202299d98SKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 693cfcefe01SKuninori Morimoto 69402299d98SKuninori Morimoto spin_lock(&priv->lock); 69502299d98SKuninori Morimoto 69602299d98SKuninori Morimoto /* ignore all cases if not working */ 697d5bbe7deSKuninori Morimoto if (!rsnd_io_is_working(io)) 69802299d98SKuninori Morimoto goto rsnd_src_interrupt_gen2_out; 699cfcefe01SKuninori Morimoto 700cfcefe01SKuninori Morimoto if (rsnd_src_error_record_gen2(mod)) { 701cfcefe01SKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 702639b231fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 703cfcefe01SKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 704cfcefe01SKuninori Morimoto 705cfcefe01SKuninori Morimoto dev_dbg(dev, "%s[%d] restart\n", 706cfcefe01SKuninori Morimoto rsnd_mod_name(mod), rsnd_mod_id(mod)); 707639b231fSKuninori Morimoto 708639b231fSKuninori Morimoto _rsnd_src_stop_gen2(mod); 709639b231fSKuninori Morimoto if (src->err < 1024) 71088c61cffSKuninori Morimoto _rsnd_src_start_gen2(mod, io); 711639b231fSKuninori Morimoto else 712639b231fSKuninori Morimoto dev_warn(dev, "no more SRC restart\n"); 713cfcefe01SKuninori Morimoto } 71488c61cffSKuninori Morimoto 71502299d98SKuninori Morimoto rsnd_src_interrupt_gen2_out: 71602299d98SKuninori Morimoto spin_unlock(&priv->lock); 71788c61cffSKuninori Morimoto } 71888c61cffSKuninori Morimoto 71988c61cffSKuninori Morimoto static irqreturn_t rsnd_src_interrupt_gen2(int irq, void *data) 72088c61cffSKuninori Morimoto { 72188c61cffSKuninori Morimoto struct rsnd_mod *mod = data; 72288c61cffSKuninori Morimoto 72388c61cffSKuninori Morimoto rsnd_mod_interrupt(mod, __rsnd_src_interrupt_gen2); 724cfcefe01SKuninori Morimoto 725cfcefe01SKuninori Morimoto return IRQ_HANDLED; 726cfcefe01SKuninori Morimoto } 727cfcefe01SKuninori Morimoto 7284e2639ffSKuninori Morimoto static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, 7294e2639ffSKuninori Morimoto struct rsnd_dai_stream *io) 730ba9c949fSKuninori Morimoto { 731054cd7f4SKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 732054cd7f4SKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 733054cd7f4SKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 734054cd7f4SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 73588c61cffSKuninori Morimoto u32 convert_rate = rsnd_src_convert_rate(io, src); 73643cb6954SKuninori Morimoto u32 cr, route; 737054cd7f4SKuninori Morimoto uint ratio; 738ba9c949fSKuninori Morimoto int ret; 739ba9c949fSKuninori Morimoto 740054cd7f4SKuninori Morimoto /* 6 - 1/6 are very enough ratio for SRC_BSDSR */ 741b167a578SKuninori Morimoto if (!convert_rate) 742054cd7f4SKuninori Morimoto ratio = 0; 743b167a578SKuninori Morimoto else if (convert_rate > runtime->rate) 744b167a578SKuninori Morimoto ratio = 100 * convert_rate / runtime->rate; 745054cd7f4SKuninori Morimoto else 746b167a578SKuninori Morimoto ratio = 100 * runtime->rate / convert_rate; 747054cd7f4SKuninori Morimoto 748054cd7f4SKuninori Morimoto if (ratio > 600) { 749054cd7f4SKuninori Morimoto dev_err(dev, "FSO/FSI ratio error\n"); 750054cd7f4SKuninori Morimoto return -EINVAL; 751054cd7f4SKuninori Morimoto } 752054cd7f4SKuninori Morimoto 7534e2639ffSKuninori Morimoto ret = rsnd_src_set_convert_rate(mod, io); 754ba9c949fSKuninori Morimoto if (ret < 0) 755ba9c949fSKuninori Morimoto return ret; 756ba9c949fSKuninori Morimoto 75743cb6954SKuninori Morimoto cr = 0x00011110; 75843cb6954SKuninori Morimoto route = 0x0; 759933cc8cbSKuninori Morimoto if (convert_rate) { 76043cb6954SKuninori Morimoto route = 0x1; 76143cb6954SKuninori Morimoto 76243cb6954SKuninori Morimoto if (rsnd_enable_sync_convert(src)) { 76343cb6954SKuninori Morimoto cr |= 0x1; 76443cb6954SKuninori Morimoto route |= rsnd_io_is_play(io) ? 76543cb6954SKuninori Morimoto (0x1 << 24) : (0x1 << 25); 766933cc8cbSKuninori Morimoto } 76743cb6954SKuninori Morimoto } 76843cb6954SKuninori Morimoto 76943cb6954SKuninori Morimoto rsnd_mod_write(mod, SRC_SRCCR, cr); 77043cb6954SKuninori Morimoto rsnd_mod_write(mod, SRC_ROUTE_MODE0, route); 771933cc8cbSKuninori Morimoto 772054cd7f4SKuninori Morimoto switch (rsnd_mod_id(mod)) { 773054cd7f4SKuninori Morimoto case 5: 774054cd7f4SKuninori Morimoto case 6: 775054cd7f4SKuninori Morimoto case 7: 776054cd7f4SKuninori Morimoto case 8: 777054cd7f4SKuninori Morimoto rsnd_mod_write(mod, SRC_BSDSR, 0x02400000); 778054cd7f4SKuninori Morimoto break; 779054cd7f4SKuninori Morimoto default: 780ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_BSDSR, 0x01800000); 781054cd7f4SKuninori Morimoto break; 782054cd7f4SKuninori Morimoto } 783054cd7f4SKuninori Morimoto 784ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_BSISR, 0x00100060); 785ba9c949fSKuninori Morimoto 786ba9c949fSKuninori Morimoto return 0; 787ba9c949fSKuninori Morimoto } 788ba9c949fSKuninori Morimoto 78988c61cffSKuninori Morimoto static int rsnd_src_set_convert_timing_gen2(struct rsnd_dai_stream *io, 79088c61cffSKuninori Morimoto struct rsnd_mod *mod) 791ba9c949fSKuninori Morimoto { 792ba9c949fSKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 793ba9c949fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 79488c61cffSKuninori Morimoto u32 convert_rate = rsnd_src_convert_rate(io, src); 795ba9c949fSKuninori Morimoto int ret; 796ba9c949fSKuninori Morimoto 797ba9c949fSKuninori Morimoto if (convert_rate) 798f708d944SKuninori Morimoto ret = rsnd_adg_set_convert_clk_gen2(mod, io, 799ba9c949fSKuninori Morimoto runtime->rate, 800ba9c949fSKuninori Morimoto convert_rate); 801ba9c949fSKuninori Morimoto else 802f708d944SKuninori Morimoto ret = rsnd_adg_set_convert_timing_gen2(mod, io); 803ba9c949fSKuninori Morimoto 804ba9c949fSKuninori Morimoto return ret; 805ba9c949fSKuninori Morimoto } 806ba9c949fSKuninori Morimoto 807ba9c949fSKuninori Morimoto static int rsnd_src_probe_gen2(struct rsnd_mod *mod, 8082c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 809690602fcSKuninori Morimoto struct rsnd_priv *priv) 810ba9c949fSKuninori Morimoto { 811ba9c949fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 812ba9c949fSKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 813cfcefe01SKuninori Morimoto int irq = src->info->irq; 814ba9c949fSKuninori Morimoto int ret; 815ba9c949fSKuninori Morimoto 816cfcefe01SKuninori Morimoto if (irq > 0) { 817cfcefe01SKuninori Morimoto /* 818cfcefe01SKuninori Morimoto * IRQ is not supported on non-DT 819cfcefe01SKuninori Morimoto * see 820cfcefe01SKuninori Morimoto * rsnd_src_irq_enable_gen2() 821cfcefe01SKuninori Morimoto */ 822cfcefe01SKuninori Morimoto ret = devm_request_irq(dev, irq, 823cfcefe01SKuninori Morimoto rsnd_src_interrupt_gen2, 824cfcefe01SKuninori Morimoto IRQF_SHARED, 825cfcefe01SKuninori Morimoto dev_name(dev), mod); 826cfcefe01SKuninori Morimoto if (ret) 827b543b52aSKuninori Morimoto return ret; 828cfcefe01SKuninori Morimoto } 829cfcefe01SKuninori Morimoto 83081ecbb65SKuninori Morimoto src->dma = rsnd_dma_attach(io, mod, src->info->dma_id); 831232c00b6SKuninori Morimoto if (IS_ERR(src->dma)) 832232c00b6SKuninori Morimoto return PTR_ERR(src->dma); 833cfcefe01SKuninori Morimoto 834cfcefe01SKuninori Morimoto return ret; 835ba9c949fSKuninori Morimoto } 836ba9c949fSKuninori Morimoto 837ba9c949fSKuninori Morimoto static int rsnd_src_remove_gen2(struct rsnd_mod *mod, 8382c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 839690602fcSKuninori Morimoto struct rsnd_priv *priv) 840ba9c949fSKuninori Morimoto { 841232c00b6SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 842232c00b6SKuninori Morimoto 843232c00b6SKuninori Morimoto rsnd_dma_quit(io, rsnd_src_to_dma(src)); 844ba9c949fSKuninori Morimoto 845ba9c949fSKuninori Morimoto return 0; 846ba9c949fSKuninori Morimoto } 847ba9c949fSKuninori Morimoto 848ba9c949fSKuninori Morimoto static int rsnd_src_init_gen2(struct rsnd_mod *mod, 8492c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 850690602fcSKuninori Morimoto struct rsnd_priv *priv) 851ba9c949fSKuninori Morimoto { 852ba9c949fSKuninori Morimoto int ret; 853ba9c949fSKuninori Morimoto 8543b7843ffSKuninori Morimoto ret = rsnd_src_init(mod, priv); 855ba9c949fSKuninori Morimoto if (ret < 0) 856ba9c949fSKuninori Morimoto return ret; 857ba9c949fSKuninori Morimoto 8584e2639ffSKuninori Morimoto ret = rsnd_src_set_convert_rate_gen2(mod, io); 859ba9c949fSKuninori Morimoto if (ret < 0) 860ba9c949fSKuninori Morimoto return ret; 861ba9c949fSKuninori Morimoto 86288c61cffSKuninori Morimoto ret = rsnd_src_set_convert_timing_gen2(io, mod); 863ba9c949fSKuninori Morimoto if (ret < 0) 864ba9c949fSKuninori Morimoto return ret; 865ba9c949fSKuninori Morimoto 866ba9c949fSKuninori Morimoto return 0; 867ba9c949fSKuninori Morimoto } 868ba9c949fSKuninori Morimoto 869ba9c949fSKuninori Morimoto static int rsnd_src_start_gen2(struct rsnd_mod *mod, 8702c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 871690602fcSKuninori Morimoto struct rsnd_priv *priv) 872ba9c949fSKuninori Morimoto { 873232c00b6SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 874232c00b6SKuninori Morimoto 875232c00b6SKuninori Morimoto rsnd_dma_start(io, rsnd_src_to_dma(src)); 876ba9c949fSKuninori Morimoto 87788c61cffSKuninori Morimoto return _rsnd_src_start_gen2(mod, io); 878ba9c949fSKuninori Morimoto } 879ba9c949fSKuninori Morimoto 880ba9c949fSKuninori Morimoto static int rsnd_src_stop_gen2(struct rsnd_mod *mod, 8812c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 882690602fcSKuninori Morimoto struct rsnd_priv *priv) 883ba9c949fSKuninori Morimoto { 884232c00b6SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 885cfcefe01SKuninori Morimoto int ret; 886ba9c949fSKuninori Morimoto 887cfcefe01SKuninori Morimoto ret = _rsnd_src_stop_gen2(mod); 888ba9c949fSKuninori Morimoto 889232c00b6SKuninori Morimoto rsnd_dma_stop(io, rsnd_src_to_dma(src)); 890ba9c949fSKuninori Morimoto 891cfcefe01SKuninori Morimoto return ret; 892ba9c949fSKuninori Morimoto } 893ba9c949fSKuninori Morimoto 894b65a7cccSKuninori Morimoto static void rsnd_src_reconvert_update(struct rsnd_dai_stream *io, 895b65a7cccSKuninori Morimoto struct rsnd_mod *mod) 89643cb6954SKuninori Morimoto { 89743cb6954SKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 89843cb6954SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 89988c61cffSKuninori Morimoto u32 convert_rate = rsnd_src_convert_rate(io, src); 90043cb6954SKuninori Morimoto u32 fsrate; 90143cb6954SKuninori Morimoto 90243cb6954SKuninori Morimoto if (!runtime) 90343cb6954SKuninori Morimoto return; 90443cb6954SKuninori Morimoto 90543cb6954SKuninori Morimoto if (!convert_rate) 90643cb6954SKuninori Morimoto convert_rate = runtime->rate; 90743cb6954SKuninori Morimoto 90843cb6954SKuninori Morimoto fsrate = 0x0400000 / convert_rate * runtime->rate; 90943cb6954SKuninori Morimoto 91043cb6954SKuninori Morimoto /* update IFS */ 91143cb6954SKuninori Morimoto rsnd_mod_write(mod, SRC_IFSVR, fsrate); 91243cb6954SKuninori Morimoto } 91343cb6954SKuninori Morimoto 914b9bfe9d5SKuninori Morimoto static int rsnd_src_pcm_new_gen2(struct rsnd_mod *mod, 9152c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 91643cb6954SKuninori Morimoto struct snd_soc_pcm_runtime *rtd) 91743cb6954SKuninori Morimoto { 91843cb6954SKuninori Morimoto struct rsnd_dai *rdai = rsnd_io_to_rdai(io); 91943cb6954SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 92043cb6954SKuninori Morimoto int ret; 92143cb6954SKuninori Morimoto 92243cb6954SKuninori Morimoto /* 92343cb6954SKuninori Morimoto * enable SRC sync convert if possible 92443cb6954SKuninori Morimoto */ 92543cb6954SKuninori Morimoto 92643cb6954SKuninori Morimoto /* 92743cb6954SKuninori Morimoto * SRC sync convert needs clock master 92843cb6954SKuninori Morimoto */ 92943cb6954SKuninori Morimoto if (!rsnd_rdai_is_clk_master(rdai)) 93043cb6954SKuninori Morimoto return 0; 93143cb6954SKuninori Morimoto 93243cb6954SKuninori Morimoto /* 93343cb6954SKuninori Morimoto * enable sync convert 93443cb6954SKuninori Morimoto */ 935b65a7cccSKuninori Morimoto ret = rsnd_kctrl_new_s(mod, io, rtd, 93643cb6954SKuninori Morimoto rsnd_io_is_play(io) ? 93743cb6954SKuninori Morimoto "SRC Out Rate Switch" : 93843cb6954SKuninori Morimoto "SRC In Rate Switch", 93943cb6954SKuninori Morimoto rsnd_src_reconvert_update, 94043cb6954SKuninori Morimoto &src->sen, 1); 94143cb6954SKuninori Morimoto if (ret < 0) 94243cb6954SKuninori Morimoto return ret; 94343cb6954SKuninori Morimoto 944b65a7cccSKuninori Morimoto ret = rsnd_kctrl_new_s(mod, io, rtd, 94543cb6954SKuninori Morimoto rsnd_io_is_play(io) ? 94643cb6954SKuninori Morimoto "SRC Out Rate" : 94743cb6954SKuninori Morimoto "SRC In Rate", 94843cb6954SKuninori Morimoto rsnd_src_reconvert_update, 94943cb6954SKuninori Morimoto &src->sync, 192000); 95043cb6954SKuninori Morimoto 95143cb6954SKuninori Morimoto return ret; 95243cb6954SKuninori Morimoto } 95343cb6954SKuninori Morimoto 954ba9c949fSKuninori Morimoto static struct rsnd_mod_ops rsnd_src_gen2_ops = { 9558aefda50SKuninori Morimoto .name = SRC_NAME, 95672adc61fSKuninori Morimoto .dma_req = rsnd_src_dma_req, 957ba9c949fSKuninori Morimoto .probe = rsnd_src_probe_gen2, 958ba9c949fSKuninori Morimoto .remove = rsnd_src_remove_gen2, 959ba9c949fSKuninori Morimoto .init = rsnd_src_init_gen2, 960*b761bf27SKuninori Morimoto .quit = rsnd_src_quit_gen2, 961ba9c949fSKuninori Morimoto .start = rsnd_src_start_gen2, 962ba9c949fSKuninori Morimoto .stop = rsnd_src_stop_gen2, 9633b7843ffSKuninori Morimoto .hw_params = rsnd_src_hw_params, 964b9bfe9d5SKuninori Morimoto .pcm_new = rsnd_src_pcm_new_gen2, 965ba9c949fSKuninori Morimoto }; 966ba9c949fSKuninori Morimoto 967ba9c949fSKuninori Morimoto struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id) 968ba9c949fSKuninori Morimoto { 969ba9c949fSKuninori Morimoto if (WARN_ON(id < 0 || id >= rsnd_src_nr(priv))) 970ba9c949fSKuninori Morimoto id = 0; 971ba9c949fSKuninori Morimoto 972b76e218aSKuninori Morimoto return rsnd_mod_get((struct rsnd_src *)(priv->src) + id); 973ba9c949fSKuninori Morimoto } 974ba9c949fSKuninori Morimoto 97590e8e50fSKuninori Morimoto static void rsnd_of_parse_src(struct platform_device *pdev, 97690e8e50fSKuninori Morimoto const struct rsnd_of_data *of_data, 97790e8e50fSKuninori Morimoto struct rsnd_priv *priv) 97890e8e50fSKuninori Morimoto { 97990e8e50fSKuninori Morimoto struct device_node *src_node; 980cfcefe01SKuninori Morimoto struct device_node *np; 98190e8e50fSKuninori Morimoto struct rcar_snd_info *info = rsnd_priv_to_info(priv); 98290e8e50fSKuninori Morimoto struct rsnd_src_platform_info *src_info; 98390e8e50fSKuninori Morimoto struct device *dev = &pdev->dev; 984cfcefe01SKuninori Morimoto int nr, i; 98590e8e50fSKuninori Morimoto 98690e8e50fSKuninori Morimoto if (!of_data) 98790e8e50fSKuninori Morimoto return; 98890e8e50fSKuninori Morimoto 98982e76ed3SKuninori Morimoto src_node = rsnd_src_of_node(priv); 99090e8e50fSKuninori Morimoto if (!src_node) 99190e8e50fSKuninori Morimoto return; 99290e8e50fSKuninori Morimoto 99390e8e50fSKuninori Morimoto nr = of_get_child_count(src_node); 99490e8e50fSKuninori Morimoto if (!nr) 995f451e48dSKuninori Morimoto goto rsnd_of_parse_src_end; 99690e8e50fSKuninori Morimoto 99790e8e50fSKuninori Morimoto src_info = devm_kzalloc(dev, 99890e8e50fSKuninori Morimoto sizeof(struct rsnd_src_platform_info) * nr, 99990e8e50fSKuninori Morimoto GFP_KERNEL); 100090e8e50fSKuninori Morimoto if (!src_info) { 100190e8e50fSKuninori Morimoto dev_err(dev, "src info allocation error\n"); 1002f451e48dSKuninori Morimoto goto rsnd_of_parse_src_end; 100390e8e50fSKuninori Morimoto } 100490e8e50fSKuninori Morimoto 100590e8e50fSKuninori Morimoto info->src_info = src_info; 100690e8e50fSKuninori Morimoto info->src_info_nr = nr; 1007f451e48dSKuninori Morimoto 1008cfcefe01SKuninori Morimoto i = 0; 1009cfcefe01SKuninori Morimoto for_each_child_of_node(src_node, np) { 1010cfcefe01SKuninori Morimoto src_info[i].irq = irq_of_parse_and_map(np, 0); 1011cfcefe01SKuninori Morimoto 1012cfcefe01SKuninori Morimoto i++; 1013cfcefe01SKuninori Morimoto } 1014cfcefe01SKuninori Morimoto 1015f451e48dSKuninori Morimoto rsnd_of_parse_src_end: 1016f451e48dSKuninori Morimoto of_node_put(src_node); 101790e8e50fSKuninori Morimoto } 101890e8e50fSKuninori Morimoto 1019ba9c949fSKuninori Morimoto int rsnd_src_probe(struct platform_device *pdev, 102090e8e50fSKuninori Morimoto const struct rsnd_of_data *of_data, 1021ba9c949fSKuninori Morimoto struct rsnd_priv *priv) 1022ba9c949fSKuninori Morimoto { 1023ba9c949fSKuninori Morimoto struct rcar_snd_info *info = rsnd_priv_to_info(priv); 1024ba9c949fSKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 1025ba9c949fSKuninori Morimoto struct rsnd_src *src; 1026ba9c949fSKuninori Morimoto struct rsnd_mod_ops *ops; 1027ba9c949fSKuninori Morimoto struct clk *clk; 1028ba9c949fSKuninori Morimoto char name[RSND_SRC_NAME_SIZE]; 10292f78dd7fSKuninori Morimoto int i, nr, ret; 1030ba9c949fSKuninori Morimoto 1031033e7ed8SKuninori Morimoto ops = NULL; 103243624957SKuninori Morimoto if (rsnd_is_gen1(priv)) { 1033033e7ed8SKuninori Morimoto ops = &rsnd_src_gen1_ops; 103443624957SKuninori Morimoto dev_warn(dev, "Gen1 support will be removed soon\n"); 103543624957SKuninori Morimoto } 1036033e7ed8SKuninori Morimoto if (rsnd_is_gen2(priv)) 1037033e7ed8SKuninori Morimoto ops = &rsnd_src_gen2_ops; 1038033e7ed8SKuninori Morimoto if (!ops) { 1039033e7ed8SKuninori Morimoto dev_err(dev, "unknown Generation\n"); 1040033e7ed8SKuninori Morimoto return -EIO; 1041033e7ed8SKuninori Morimoto } 1042033e7ed8SKuninori Morimoto 104390e8e50fSKuninori Morimoto rsnd_of_parse_src(pdev, of_data, priv); 104490e8e50fSKuninori Morimoto 1045ba9c949fSKuninori Morimoto /* 1046ba9c949fSKuninori Morimoto * init SRC 1047ba9c949fSKuninori Morimoto */ 1048ba9c949fSKuninori Morimoto nr = info->src_info_nr; 1049ba9c949fSKuninori Morimoto if (!nr) 1050ba9c949fSKuninori Morimoto return 0; 1051ba9c949fSKuninori Morimoto 1052ba9c949fSKuninori Morimoto src = devm_kzalloc(dev, sizeof(*src) * nr, GFP_KERNEL); 105333363f7aSKuninori Morimoto if (!src) 1054ba9c949fSKuninori Morimoto return -ENOMEM; 1055ba9c949fSKuninori Morimoto 1056ba9c949fSKuninori Morimoto priv->src_nr = nr; 1057ba9c949fSKuninori Morimoto priv->src = src; 1058ba9c949fSKuninori Morimoto 1059ba9c949fSKuninori Morimoto for_each_rsnd_src(src, priv, i) { 10608aefda50SKuninori Morimoto snprintf(name, RSND_SRC_NAME_SIZE, "%s.%d", 10618aefda50SKuninori Morimoto SRC_NAME, i); 1062ba9c949fSKuninori Morimoto 1063ba9c949fSKuninori Morimoto clk = devm_clk_get(dev, name); 1064ba9c949fSKuninori Morimoto if (IS_ERR(clk)) 1065ba9c949fSKuninori Morimoto return PTR_ERR(clk); 1066ba9c949fSKuninori Morimoto 1067ba9c949fSKuninori Morimoto src->info = &info->src_info[i]; 1068ba9c949fSKuninori Morimoto 1069b76e218aSKuninori Morimoto ret = rsnd_mod_init(priv, rsnd_mod_get(src), ops, clk, RSND_MOD_SRC, i); 10702f78dd7fSKuninori Morimoto if (ret) 10712f78dd7fSKuninori Morimoto return ret; 1072ba9c949fSKuninori Morimoto } 1073ba9c949fSKuninori Morimoto 1074ba9c949fSKuninori Morimoto return 0; 1075ba9c949fSKuninori Morimoto } 10762f78dd7fSKuninori Morimoto 10772f78dd7fSKuninori Morimoto void rsnd_src_remove(struct platform_device *pdev, 10782f78dd7fSKuninori Morimoto struct rsnd_priv *priv) 10792f78dd7fSKuninori Morimoto { 10802f78dd7fSKuninori Morimoto struct rsnd_src *src; 10812f78dd7fSKuninori Morimoto int i; 10822f78dd7fSKuninori Morimoto 10832f78dd7fSKuninori Morimoto for_each_rsnd_src(src, priv, i) { 1084b76e218aSKuninori Morimoto rsnd_mod_quit(rsnd_mod_get(src)); 10852f78dd7fSKuninori Morimoto } 10862f78dd7fSKuninori Morimoto } 1087