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; 25940e9479SKuninori Morimoto struct rsnd_mod *dma; 2643cb6954SKuninori Morimoto struct rsnd_kctrl_cfg_s sen; /* sync convert enable */ 2743cb6954SKuninori Morimoto struct rsnd_kctrl_cfg_s sync; /* sync convert */ 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 14888c61cffSKuninori Morimoto static u32 rsnd_src_convert_rate(struct rsnd_dai_stream *io, 14988c61cffSKuninori Morimoto struct rsnd_src *src) 15043cb6954SKuninori Morimoto { 15143cb6954SKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 15243cb6954SKuninori Morimoto u32 convert_rate; 15343cb6954SKuninori Morimoto 15443cb6954SKuninori Morimoto if (!runtime) 15543cb6954SKuninori Morimoto return 0; 15643cb6954SKuninori Morimoto 15743cb6954SKuninori Morimoto if (!rsnd_enable_sync_convert(src)) 15843cb6954SKuninori Morimoto return src->convert_rate; 15943cb6954SKuninori Morimoto 16043cb6954SKuninori Morimoto convert_rate = src->sync.val; 16143cb6954SKuninori Morimoto 16243cb6954SKuninori Morimoto if (!convert_rate) 16343cb6954SKuninori Morimoto convert_rate = src->convert_rate; 16443cb6954SKuninori Morimoto 16543cb6954SKuninori Morimoto if (!convert_rate) 16643cb6954SKuninori Morimoto convert_rate = runtime->rate; 16743cb6954SKuninori Morimoto 16843cb6954SKuninori Morimoto return convert_rate; 16943cb6954SKuninori Morimoto } 17043cb6954SKuninori Morimoto 171ba9c949fSKuninori Morimoto unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, 172ba9c949fSKuninori Morimoto struct rsnd_dai_stream *io, 173ba9c949fSKuninori Morimoto struct snd_pcm_runtime *runtime) 174ba9c949fSKuninori Morimoto { 175b1eac430SKuninori Morimoto struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); 176ba9c949fSKuninori Morimoto struct rsnd_src *src; 177b1eac430SKuninori Morimoto unsigned int rate = 0; 178ba9c949fSKuninori Morimoto 179b1eac430SKuninori Morimoto if (src_mod) { 180b1eac430SKuninori Morimoto src = rsnd_mod_to_src(src_mod); 181ba9c949fSKuninori Morimoto 182ba9c949fSKuninori Morimoto /* 183ba9c949fSKuninori Morimoto * return convert rate if SRC is used, 184ba9c949fSKuninori Morimoto * otherwise, return runtime->rate as usual 185ba9c949fSKuninori Morimoto */ 18688c61cffSKuninori Morimoto rate = rsnd_src_convert_rate(io, src); 187b1eac430SKuninori Morimoto } 188b1eac430SKuninori Morimoto 189ba9c949fSKuninori Morimoto if (!rate) 190ba9c949fSKuninori Morimoto rate = runtime->rate; 191ba9c949fSKuninori Morimoto 192ba9c949fSKuninori Morimoto return rate; 193ba9c949fSKuninori Morimoto } 194ba9c949fSKuninori Morimoto 1954e2639ffSKuninori Morimoto static int rsnd_src_set_convert_rate(struct rsnd_mod *mod, 1964e2639ffSKuninori Morimoto struct rsnd_dai_stream *io) 197ba9c949fSKuninori Morimoto { 198ba9c949fSKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 199ba9c949fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 20088c61cffSKuninori Morimoto u32 convert_rate = rsnd_src_convert_rate(io, src); 201ba9c949fSKuninori Morimoto u32 fsrate = 0; 202ba9c949fSKuninori Morimoto 203ba9c949fSKuninori Morimoto if (convert_rate) 204ba9c949fSKuninori Morimoto fsrate = 0x0400000 / convert_rate * runtime->rate; 205ba9c949fSKuninori Morimoto 206ba9c949fSKuninori Morimoto /* Set channel number and output bit length */ 2073023b384SKuninori Morimoto rsnd_mod_write(mod, SRC_ADINR, rsnd_get_adinr_bit(mod, io)); 208ba9c949fSKuninori Morimoto 209ba9c949fSKuninori Morimoto /* Enable the initial value of IFS */ 210ba9c949fSKuninori Morimoto if (fsrate) { 211ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_IFSCR, 1); 212ba9c949fSKuninori Morimoto 213ba9c949fSKuninori Morimoto /* Set initial value of IFS */ 214ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_IFSVR, fsrate); 215ba9c949fSKuninori Morimoto } 216ba9c949fSKuninori Morimoto 217ba9c949fSKuninori Morimoto /* use DMA transfer */ 218ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_BUSIF_MODE, 1); 219ba9c949fSKuninori Morimoto 220ba9c949fSKuninori Morimoto return 0; 221ba9c949fSKuninori Morimoto } 222ba9c949fSKuninori Morimoto 2233b7843ffSKuninori Morimoto static int rsnd_src_hw_params(struct rsnd_mod *mod, 2242c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 2253b7843ffSKuninori Morimoto struct snd_pcm_substream *substream, 2263b7843ffSKuninori Morimoto struct snd_pcm_hw_params *fe_params) 2273b7843ffSKuninori Morimoto { 2283b7843ffSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 2293b7843ffSKuninori Morimoto struct snd_soc_pcm_runtime *fe = substream->private_data; 2303b7843ffSKuninori Morimoto 2313b7843ffSKuninori Morimoto /* default value (mainly for non-DT) */ 2323b7843ffSKuninori Morimoto src->convert_rate = src->info->convert_rate; 2333b7843ffSKuninori Morimoto 2343b7843ffSKuninori Morimoto /* 2353b7843ffSKuninori Morimoto * SRC assumes that it is used under DPCM if user want to use 2363b7843ffSKuninori Morimoto * sampling rate convert. Then, SRC should be FE. 2373b7843ffSKuninori Morimoto * And then, this function will be called *after* BE settings. 2383b7843ffSKuninori Morimoto * this means, each BE already has fixuped hw_params. 2393b7843ffSKuninori Morimoto * see 2403b7843ffSKuninori Morimoto * dpcm_fe_dai_hw_params() 2413b7843ffSKuninori Morimoto * dpcm_be_dai_hw_params() 2423b7843ffSKuninori Morimoto */ 2433b7843ffSKuninori Morimoto if (fe->dai_link->dynamic) { 2443b7843ffSKuninori Morimoto int stream = substream->stream; 2453b7843ffSKuninori Morimoto struct snd_soc_dpcm *dpcm; 2463b7843ffSKuninori Morimoto struct snd_pcm_hw_params *be_params; 2473b7843ffSKuninori Morimoto 2483b7843ffSKuninori Morimoto list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { 2493b7843ffSKuninori Morimoto be_params = &dpcm->hw_params; 2503b7843ffSKuninori Morimoto 2513b7843ffSKuninori Morimoto if (params_rate(fe_params) != params_rate(be_params)) 2523b7843ffSKuninori Morimoto src->convert_rate = params_rate(be_params); 2533b7843ffSKuninori Morimoto } 2543b7843ffSKuninori Morimoto } 2553b7843ffSKuninori Morimoto 2563b7843ffSKuninori Morimoto return 0; 2573b7843ffSKuninori Morimoto } 2583b7843ffSKuninori Morimoto 2593b7843ffSKuninori Morimoto static int rsnd_src_init(struct rsnd_mod *mod, 2603b7843ffSKuninori Morimoto struct rsnd_priv *priv) 261ba9c949fSKuninori Morimoto { 262ba9c949fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 263ba9c949fSKuninori Morimoto 264c9929345SKuninori Morimoto rsnd_mod_power_on(mod); 265ba9c949fSKuninori Morimoto 266379febfdSKuninori Morimoto rsnd_src_soft_reset(mod); 267379febfdSKuninori Morimoto 268d1ade514SKuninori Morimoto rsnd_src_initialize_lock(mod); 269d1ade514SKuninori Morimoto 270cfcefe01SKuninori Morimoto src->err = 0; 271cfcefe01SKuninori Morimoto 27243cb6954SKuninori Morimoto /* reset sync convert_rate */ 27343cb6954SKuninori Morimoto src->sync.val = 0; 27443cb6954SKuninori Morimoto 275ba9c949fSKuninori Morimoto return 0; 276ba9c949fSKuninori Morimoto } 277ba9c949fSKuninori Morimoto 278ba9c949fSKuninori Morimoto static int rsnd_src_quit(struct rsnd_mod *mod, 2792c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 280690602fcSKuninori Morimoto struct rsnd_priv *priv) 281ba9c949fSKuninori Morimoto { 282ba9c949fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 283cfcefe01SKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 284ba9c949fSKuninori Morimoto 285c9929345SKuninori Morimoto rsnd_mod_power_off(mod); 286ba9c949fSKuninori Morimoto 287cfcefe01SKuninori Morimoto if (src->err) 288337b0b4cSKuninori Morimoto dev_warn(dev, "%s[%d] under/over flow err = %d\n", 289337b0b4cSKuninori Morimoto rsnd_mod_name(mod), rsnd_mod_id(mod), src->err); 290cfcefe01SKuninori Morimoto 2913b7843ffSKuninori Morimoto src->convert_rate = 0; 2923b7843ffSKuninori Morimoto 29343cb6954SKuninori Morimoto /* reset sync convert_rate */ 29443cb6954SKuninori Morimoto src->sync.val = 0; 29543cb6954SKuninori Morimoto 296ba9c949fSKuninori Morimoto return 0; 297ba9c949fSKuninori Morimoto } 298ba9c949fSKuninori Morimoto 299f0ef0cb8SKuninori Morimoto static int rsnd_src_start(struct rsnd_mod *mod) 300ba9c949fSKuninori Morimoto { 301d1ade514SKuninori Morimoto rsnd_src_initialize_unlock(mod); 302ba9c949fSKuninori Morimoto 303ba9c949fSKuninori Morimoto return 0; 304ba9c949fSKuninori Morimoto } 305ba9c949fSKuninori Morimoto 306f0ef0cb8SKuninori Morimoto static int rsnd_src_stop(struct rsnd_mod *mod) 307ba9c949fSKuninori Morimoto { 308933cc8cbSKuninori Morimoto /* nothing to do */ 309ba9c949fSKuninori Morimoto return 0; 310ba9c949fSKuninori Morimoto } 311ba9c949fSKuninori Morimoto 312ba9c949fSKuninori Morimoto /* 313ba9c949fSKuninori Morimoto * Gen2 functions 314ba9c949fSKuninori Morimoto */ 315cfcefe01SKuninori Morimoto #define rsnd_src_irq_enable_gen2(mod) rsnd_src_irq_ctrol_gen2(mod, 1) 316cfcefe01SKuninori Morimoto #define rsnd_src_irq_disable_gen2(mod) rsnd_src_irq_ctrol_gen2(mod, 0) 317cfcefe01SKuninori Morimoto static void rsnd_src_irq_ctrol_gen2(struct rsnd_mod *mod, int enable) 318cfcefe01SKuninori Morimoto { 319cfcefe01SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 320cfcefe01SKuninori Morimoto u32 sys_int_val, int_val, sys_int_mask; 321cfcefe01SKuninori Morimoto int irq = src->info->irq; 322cfcefe01SKuninori Morimoto int id = rsnd_mod_id(mod); 323cfcefe01SKuninori Morimoto 324cfcefe01SKuninori Morimoto sys_int_val = 325cfcefe01SKuninori Morimoto sys_int_mask = OUF_SRC(id); 326cfcefe01SKuninori Morimoto int_val = 0x3300; 327cfcefe01SKuninori Morimoto 328cfcefe01SKuninori Morimoto /* 329cfcefe01SKuninori Morimoto * IRQ is not supported on non-DT 330cfcefe01SKuninori Morimoto * see 331cfcefe01SKuninori Morimoto * rsnd_src_probe_gen2() 332cfcefe01SKuninori Morimoto */ 333cfcefe01SKuninori Morimoto if ((irq <= 0) || !enable) { 334cfcefe01SKuninori Morimoto sys_int_val = 0; 335cfcefe01SKuninori Morimoto int_val = 0; 336cfcefe01SKuninori Morimoto } 337cfcefe01SKuninori Morimoto 3381a1bf58aSKuninori Morimoto /* 3391a1bf58aSKuninori Morimoto * WORKAROUND 3401a1bf58aSKuninori Morimoto * 3411a1bf58aSKuninori Morimoto * ignore over flow error when rsnd_enable_sync_convert() 3421a1bf58aSKuninori Morimoto */ 3431a1bf58aSKuninori Morimoto if (rsnd_enable_sync_convert(src)) 3441a1bf58aSKuninori Morimoto sys_int_val = sys_int_val & 0xffff; 3451a1bf58aSKuninori Morimoto 346cfcefe01SKuninori Morimoto rsnd_mod_write(mod, SRC_INT_ENABLE0, int_val); 347cfcefe01SKuninori Morimoto rsnd_mod_bset(mod, SCU_SYS_INT_EN0, sys_int_mask, sys_int_val); 348cfcefe01SKuninori Morimoto rsnd_mod_bset(mod, SCU_SYS_INT_EN1, sys_int_mask, sys_int_val); 349cfcefe01SKuninori Morimoto } 350cfcefe01SKuninori Morimoto 351cfcefe01SKuninori Morimoto static void rsnd_src_error_clear_gen2(struct rsnd_mod *mod) 352cfcefe01SKuninori Morimoto { 353cfcefe01SKuninori Morimoto u32 val = OUF_SRC(rsnd_mod_id(mod)); 354cfcefe01SKuninori Morimoto 355cfcefe01SKuninori Morimoto rsnd_mod_bset(mod, SCU_SYS_STATUS0, val, val); 356cfcefe01SKuninori Morimoto rsnd_mod_bset(mod, SCU_SYS_STATUS1, val, val); 357cfcefe01SKuninori Morimoto } 358cfcefe01SKuninori Morimoto 359cfcefe01SKuninori Morimoto static bool rsnd_src_error_record_gen2(struct rsnd_mod *mod) 360cfcefe01SKuninori Morimoto { 3611a1bf58aSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 3621a1bf58aSKuninori Morimoto u32 val0, val1; 363cfcefe01SKuninori Morimoto bool ret = false; 364cfcefe01SKuninori Morimoto 3651a1bf58aSKuninori Morimoto val0 = val1 = OUF_SRC(rsnd_mod_id(mod)); 3661a1bf58aSKuninori Morimoto 3671a1bf58aSKuninori Morimoto /* 3681a1bf58aSKuninori Morimoto * WORKAROUND 3691a1bf58aSKuninori Morimoto * 3701a1bf58aSKuninori Morimoto * ignore over flow error when rsnd_enable_sync_convert() 3711a1bf58aSKuninori Morimoto */ 3721a1bf58aSKuninori Morimoto if (rsnd_enable_sync_convert(src)) 3731a1bf58aSKuninori Morimoto val0 = val0 & 0xffff; 3741a1bf58aSKuninori Morimoto 3751a1bf58aSKuninori Morimoto if ((rsnd_mod_read(mod, SCU_SYS_STATUS0) & val0) || 3761a1bf58aSKuninori Morimoto (rsnd_mod_read(mod, SCU_SYS_STATUS1) & val1)) { 377cfcefe01SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 378cfcefe01SKuninori Morimoto 379cfcefe01SKuninori Morimoto src->err++; 380cfcefe01SKuninori Morimoto ret = true; 381cfcefe01SKuninori Morimoto } 382cfcefe01SKuninori Morimoto 383cfcefe01SKuninori Morimoto /* clear error static */ 384cfcefe01SKuninori Morimoto rsnd_src_error_clear_gen2(mod); 385cfcefe01SKuninori Morimoto 386cfcefe01SKuninori Morimoto return ret; 387cfcefe01SKuninori Morimoto } 388cfcefe01SKuninori Morimoto 389497debaaSKuninori Morimoto static int rsnd_src_start_gen2(struct rsnd_mod *mod, 390497debaaSKuninori Morimoto struct rsnd_dai_stream *io, 391497debaaSKuninori Morimoto struct rsnd_priv *priv) 392cfcefe01SKuninori Morimoto { 3931a1bf58aSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 3941a1bf58aSKuninori Morimoto u32 val; 3951a1bf58aSKuninori Morimoto 3964689032bSKuninori Morimoto val = rsnd_get_dalign(mod, io); 3974689032bSKuninori Morimoto 3984689032bSKuninori Morimoto rsnd_mod_write(mod, SRC_BUSIF_DALIGN, val); 3994689032bSKuninori Morimoto 4001a1bf58aSKuninori Morimoto /* 4011a1bf58aSKuninori Morimoto * WORKAROUND 4021a1bf58aSKuninori Morimoto * 4031a1bf58aSKuninori Morimoto * Enable SRC output if you want to use sync convert together with DVC 4041a1bf58aSKuninori Morimoto */ 4051a1bf58aSKuninori Morimoto val = (rsnd_io_to_mod_dvc(io) && !rsnd_enable_sync_convert(src)) ? 4061a1bf58aSKuninori Morimoto 0x01 : 0x11; 407cfcefe01SKuninori Morimoto 408cfcefe01SKuninori Morimoto rsnd_mod_write(mod, SRC_CTRL, val); 409cfcefe01SKuninori Morimoto 410cfcefe01SKuninori Morimoto rsnd_src_error_clear_gen2(mod); 411cfcefe01SKuninori Morimoto 412cfcefe01SKuninori Morimoto rsnd_src_start(mod); 413cfcefe01SKuninori Morimoto 414cfcefe01SKuninori Morimoto rsnd_src_irq_enable_gen2(mod); 415cfcefe01SKuninori Morimoto 416cfcefe01SKuninori Morimoto return 0; 417cfcefe01SKuninori Morimoto } 418cfcefe01SKuninori Morimoto 419497debaaSKuninori Morimoto static int rsnd_src_stop_gen2(struct rsnd_mod *mod, 420497debaaSKuninori Morimoto struct rsnd_dai_stream *io, 421497debaaSKuninori Morimoto struct rsnd_priv *priv) 422cfcefe01SKuninori Morimoto { 423cfcefe01SKuninori Morimoto rsnd_src_irq_disable_gen2(mod); 424cfcefe01SKuninori Morimoto 425b761bf27SKuninori Morimoto /* 426b761bf27SKuninori Morimoto * stop SRC output only 427b761bf27SKuninori Morimoto * see rsnd_src_quit_gen2 428b761bf27SKuninori Morimoto */ 429b761bf27SKuninori Morimoto rsnd_mod_write(mod, SRC_CTRL, 0x01); 430cfcefe01SKuninori Morimoto 431cfcefe01SKuninori Morimoto rsnd_src_error_record_gen2(mod); 432cfcefe01SKuninori Morimoto 433cfcefe01SKuninori Morimoto return rsnd_src_stop(mod); 434cfcefe01SKuninori Morimoto } 435cfcefe01SKuninori Morimoto 436b761bf27SKuninori Morimoto static int rsnd_src_quit_gen2(struct rsnd_mod *mod, 437b761bf27SKuninori Morimoto struct rsnd_dai_stream *io, 438b761bf27SKuninori Morimoto struct rsnd_priv *priv) 439b761bf27SKuninori Morimoto { 440b761bf27SKuninori Morimoto /* stop both out/in */ 441b761bf27SKuninori Morimoto rsnd_mod_write(mod, SRC_CTRL, 0); 442b761bf27SKuninori Morimoto 443f36a8226SKuninori Morimoto return rsnd_src_quit(mod, io, priv); 444b761bf27SKuninori Morimoto } 445b761bf27SKuninori Morimoto 44688c61cffSKuninori Morimoto static void __rsnd_src_interrupt_gen2(struct rsnd_mod *mod, 44788c61cffSKuninori Morimoto struct rsnd_dai_stream *io) 448cfcefe01SKuninori Morimoto { 44902299d98SKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 45069e32a58SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 45169e32a58SKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 452cfcefe01SKuninori Morimoto 45302299d98SKuninori Morimoto spin_lock(&priv->lock); 45402299d98SKuninori Morimoto 45502299d98SKuninori Morimoto /* ignore all cases if not working */ 456d5bbe7deSKuninori Morimoto if (!rsnd_io_is_working(io)) 45702299d98SKuninori Morimoto goto rsnd_src_interrupt_gen2_out; 458cfcefe01SKuninori Morimoto 459cfcefe01SKuninori Morimoto if (rsnd_src_error_record_gen2(mod)) { 460cfcefe01SKuninori Morimoto 461cfcefe01SKuninori Morimoto dev_dbg(dev, "%s[%d] restart\n", 462cfcefe01SKuninori Morimoto rsnd_mod_name(mod), rsnd_mod_id(mod)); 463639b231fSKuninori Morimoto 464497debaaSKuninori Morimoto rsnd_src_stop_gen2(mod, io, priv); 465497debaaSKuninori Morimoto rsnd_src_start_gen2(mod, io, priv); 46669e32a58SKuninori Morimoto } 46769e32a58SKuninori Morimoto 46869e32a58SKuninori Morimoto if (src->err > 1024) { 46969e32a58SKuninori Morimoto rsnd_src_irq_disable_gen2(mod); 47069e32a58SKuninori Morimoto 47169e32a58SKuninori Morimoto dev_warn(dev, "no more %s[%d] restart\n", 47269e32a58SKuninori Morimoto rsnd_mod_name(mod), rsnd_mod_id(mod)); 473cfcefe01SKuninori Morimoto } 47488c61cffSKuninori Morimoto 47502299d98SKuninori Morimoto rsnd_src_interrupt_gen2_out: 47602299d98SKuninori Morimoto spin_unlock(&priv->lock); 47788c61cffSKuninori Morimoto } 47888c61cffSKuninori Morimoto 47988c61cffSKuninori Morimoto static irqreturn_t rsnd_src_interrupt_gen2(int irq, void *data) 48088c61cffSKuninori Morimoto { 48188c61cffSKuninori Morimoto struct rsnd_mod *mod = data; 48288c61cffSKuninori Morimoto 48388c61cffSKuninori Morimoto rsnd_mod_interrupt(mod, __rsnd_src_interrupt_gen2); 484cfcefe01SKuninori Morimoto 485cfcefe01SKuninori Morimoto return IRQ_HANDLED; 486cfcefe01SKuninori Morimoto } 487cfcefe01SKuninori Morimoto 4884e2639ffSKuninori Morimoto static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, 4894e2639ffSKuninori Morimoto struct rsnd_dai_stream *io) 490ba9c949fSKuninori Morimoto { 491054cd7f4SKuninori Morimoto struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 492054cd7f4SKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 493054cd7f4SKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 494054cd7f4SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 49588c61cffSKuninori Morimoto u32 convert_rate = rsnd_src_convert_rate(io, src); 49643cb6954SKuninori Morimoto u32 cr, route; 497054cd7f4SKuninori Morimoto uint ratio; 498ba9c949fSKuninori Morimoto int ret; 499ba9c949fSKuninori Morimoto 500054cd7f4SKuninori Morimoto /* 6 - 1/6 are very enough ratio for SRC_BSDSR */ 501b167a578SKuninori Morimoto if (!convert_rate) 502054cd7f4SKuninori Morimoto ratio = 0; 503b167a578SKuninori Morimoto else if (convert_rate > runtime->rate) 504b167a578SKuninori Morimoto ratio = 100 * convert_rate / runtime->rate; 505054cd7f4SKuninori Morimoto else 506b167a578SKuninori Morimoto ratio = 100 * runtime->rate / convert_rate; 507054cd7f4SKuninori Morimoto 508054cd7f4SKuninori Morimoto if (ratio > 600) { 509054cd7f4SKuninori Morimoto dev_err(dev, "FSO/FSI ratio error\n"); 510054cd7f4SKuninori Morimoto return -EINVAL; 511054cd7f4SKuninori Morimoto } 512054cd7f4SKuninori Morimoto 5134e2639ffSKuninori Morimoto ret = rsnd_src_set_convert_rate(mod, io); 514ba9c949fSKuninori Morimoto if (ret < 0) 515ba9c949fSKuninori Morimoto return ret; 516ba9c949fSKuninori Morimoto 51743cb6954SKuninori Morimoto cr = 0x00011110; 51843cb6954SKuninori Morimoto route = 0x0; 519933cc8cbSKuninori Morimoto if (convert_rate) { 52043cb6954SKuninori Morimoto route = 0x1; 52143cb6954SKuninori Morimoto 52243cb6954SKuninori Morimoto if (rsnd_enable_sync_convert(src)) { 52343cb6954SKuninori Morimoto cr |= 0x1; 52443cb6954SKuninori Morimoto route |= rsnd_io_is_play(io) ? 52543cb6954SKuninori Morimoto (0x1 << 24) : (0x1 << 25); 526933cc8cbSKuninori Morimoto } 52743cb6954SKuninori Morimoto } 52843cb6954SKuninori Morimoto 52943cb6954SKuninori Morimoto rsnd_mod_write(mod, SRC_SRCCR, cr); 53043cb6954SKuninori Morimoto rsnd_mod_write(mod, SRC_ROUTE_MODE0, route); 531933cc8cbSKuninori Morimoto 532054cd7f4SKuninori Morimoto switch (rsnd_mod_id(mod)) { 533054cd7f4SKuninori Morimoto case 5: 534054cd7f4SKuninori Morimoto case 6: 535054cd7f4SKuninori Morimoto case 7: 536054cd7f4SKuninori Morimoto case 8: 537054cd7f4SKuninori Morimoto rsnd_mod_write(mod, SRC_BSDSR, 0x02400000); 538054cd7f4SKuninori Morimoto break; 539054cd7f4SKuninori Morimoto default: 540ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_BSDSR, 0x01800000); 541054cd7f4SKuninori Morimoto break; 542054cd7f4SKuninori Morimoto } 543054cd7f4SKuninori Morimoto 544ba9c949fSKuninori Morimoto rsnd_mod_write(mod, SRC_BSISR, 0x00100060); 545ba9c949fSKuninori Morimoto 546ba9c949fSKuninori Morimoto return 0; 547ba9c949fSKuninori Morimoto } 548ba9c949fSKuninori Morimoto 54988c61cffSKuninori Morimoto static int rsnd_src_set_convert_timing_gen2(struct rsnd_dai_stream *io, 55088c61cffSKuninori Morimoto struct rsnd_mod *mod) 551ba9c949fSKuninori Morimoto { 552ba9c949fSKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 553ba9c949fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 55488c61cffSKuninori Morimoto u32 convert_rate = rsnd_src_convert_rate(io, src); 555ba9c949fSKuninori Morimoto int ret; 556ba9c949fSKuninori Morimoto 557ba9c949fSKuninori Morimoto if (convert_rate) 558f708d944SKuninori Morimoto ret = rsnd_adg_set_convert_clk_gen2(mod, io, 559ba9c949fSKuninori Morimoto runtime->rate, 560ba9c949fSKuninori Morimoto convert_rate); 561ba9c949fSKuninori Morimoto else 562f708d944SKuninori Morimoto ret = rsnd_adg_set_convert_timing_gen2(mod, io); 563ba9c949fSKuninori Morimoto 564ba9c949fSKuninori Morimoto return ret; 565ba9c949fSKuninori Morimoto } 566ba9c949fSKuninori Morimoto 567ba9c949fSKuninori Morimoto static int rsnd_src_probe_gen2(struct rsnd_mod *mod, 5682c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 569690602fcSKuninori Morimoto struct rsnd_priv *priv) 570ba9c949fSKuninori Morimoto { 571ba9c949fSKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 572ba9c949fSKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 573cfcefe01SKuninori Morimoto int irq = src->info->irq; 574ba9c949fSKuninori Morimoto int ret; 575ba9c949fSKuninori Morimoto 576cfcefe01SKuninori Morimoto if (irq > 0) { 577cfcefe01SKuninori Morimoto /* 578cfcefe01SKuninori Morimoto * IRQ is not supported on non-DT 579cfcefe01SKuninori Morimoto * see 580cfcefe01SKuninori Morimoto * rsnd_src_irq_enable_gen2() 581cfcefe01SKuninori Morimoto */ 582cfcefe01SKuninori Morimoto ret = devm_request_irq(dev, irq, 583cfcefe01SKuninori Morimoto rsnd_src_interrupt_gen2, 584cfcefe01SKuninori Morimoto IRQF_SHARED, 585cfcefe01SKuninori Morimoto dev_name(dev), mod); 586cfcefe01SKuninori Morimoto if (ret) 587b543b52aSKuninori Morimoto return ret; 588cfcefe01SKuninori Morimoto } 589cfcefe01SKuninori Morimoto 59081ecbb65SKuninori Morimoto src->dma = rsnd_dma_attach(io, mod, src->info->dma_id); 591232c00b6SKuninori Morimoto if (IS_ERR(src->dma)) 592232c00b6SKuninori Morimoto return PTR_ERR(src->dma); 593cfcefe01SKuninori Morimoto 594cfcefe01SKuninori Morimoto return ret; 595ba9c949fSKuninori Morimoto } 596ba9c949fSKuninori Morimoto 597ba9c949fSKuninori Morimoto static int rsnd_src_init_gen2(struct rsnd_mod *mod, 5982c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 599690602fcSKuninori Morimoto struct rsnd_priv *priv) 600ba9c949fSKuninori Morimoto { 601ba9c949fSKuninori Morimoto int ret; 602ba9c949fSKuninori Morimoto 6033b7843ffSKuninori Morimoto ret = rsnd_src_init(mod, priv); 604ba9c949fSKuninori Morimoto if (ret < 0) 605ba9c949fSKuninori Morimoto return ret; 606ba9c949fSKuninori Morimoto 6074e2639ffSKuninori Morimoto ret = rsnd_src_set_convert_rate_gen2(mod, io); 608ba9c949fSKuninori Morimoto if (ret < 0) 609ba9c949fSKuninori Morimoto return ret; 610ba9c949fSKuninori Morimoto 61188c61cffSKuninori Morimoto ret = rsnd_src_set_convert_timing_gen2(io, mod); 612ba9c949fSKuninori Morimoto if (ret < 0) 613ba9c949fSKuninori Morimoto return ret; 614ba9c949fSKuninori Morimoto 615ba9c949fSKuninori Morimoto return 0; 616ba9c949fSKuninori Morimoto } 617ba9c949fSKuninori Morimoto 618b65a7cccSKuninori Morimoto static void rsnd_src_reconvert_update(struct rsnd_dai_stream *io, 619b65a7cccSKuninori Morimoto struct rsnd_mod *mod) 62043cb6954SKuninori Morimoto { 62143cb6954SKuninori Morimoto struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 62243cb6954SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 62388c61cffSKuninori Morimoto u32 convert_rate = rsnd_src_convert_rate(io, src); 62443cb6954SKuninori Morimoto u32 fsrate; 62543cb6954SKuninori Morimoto 62643cb6954SKuninori Morimoto if (!runtime) 62743cb6954SKuninori Morimoto return; 62843cb6954SKuninori Morimoto 62943cb6954SKuninori Morimoto if (!convert_rate) 63043cb6954SKuninori Morimoto convert_rate = runtime->rate; 63143cb6954SKuninori Morimoto 63243cb6954SKuninori Morimoto fsrate = 0x0400000 / convert_rate * runtime->rate; 63343cb6954SKuninori Morimoto 63443cb6954SKuninori Morimoto /* update IFS */ 63543cb6954SKuninori Morimoto rsnd_mod_write(mod, SRC_IFSVR, fsrate); 63643cb6954SKuninori Morimoto } 63743cb6954SKuninori Morimoto 638b9bfe9d5SKuninori Morimoto static int rsnd_src_pcm_new_gen2(struct rsnd_mod *mod, 6392c0fac19SKuninori Morimoto struct rsnd_dai_stream *io, 64043cb6954SKuninori Morimoto struct snd_soc_pcm_runtime *rtd) 64143cb6954SKuninori Morimoto { 64243cb6954SKuninori Morimoto struct rsnd_dai *rdai = rsnd_io_to_rdai(io); 64343cb6954SKuninori Morimoto struct rsnd_src *src = rsnd_mod_to_src(mod); 64443cb6954SKuninori Morimoto int ret; 64543cb6954SKuninori Morimoto 64643cb6954SKuninori Morimoto /* 64743cb6954SKuninori Morimoto * enable SRC sync convert if possible 64843cb6954SKuninori Morimoto */ 64943cb6954SKuninori Morimoto 65043cb6954SKuninori Morimoto /* 65143cb6954SKuninori Morimoto * SRC sync convert needs clock master 65243cb6954SKuninori Morimoto */ 65343cb6954SKuninori Morimoto if (!rsnd_rdai_is_clk_master(rdai)) 65443cb6954SKuninori Morimoto return 0; 65543cb6954SKuninori Morimoto 65643cb6954SKuninori Morimoto /* 65743cb6954SKuninori Morimoto * enable sync convert 65843cb6954SKuninori Morimoto */ 659b65a7cccSKuninori Morimoto ret = rsnd_kctrl_new_s(mod, io, rtd, 66043cb6954SKuninori Morimoto rsnd_io_is_play(io) ? 66143cb6954SKuninori Morimoto "SRC Out Rate Switch" : 66243cb6954SKuninori Morimoto "SRC In Rate Switch", 66343cb6954SKuninori Morimoto rsnd_src_reconvert_update, 66443cb6954SKuninori Morimoto &src->sen, 1); 66543cb6954SKuninori Morimoto if (ret < 0) 66643cb6954SKuninori Morimoto return ret; 66743cb6954SKuninori Morimoto 668b65a7cccSKuninori Morimoto ret = rsnd_kctrl_new_s(mod, io, rtd, 66943cb6954SKuninori Morimoto rsnd_io_is_play(io) ? 67043cb6954SKuninori Morimoto "SRC Out Rate" : 67143cb6954SKuninori Morimoto "SRC In Rate", 67243cb6954SKuninori Morimoto rsnd_src_reconvert_update, 67343cb6954SKuninori Morimoto &src->sync, 192000); 67443cb6954SKuninori Morimoto 67543cb6954SKuninori Morimoto return ret; 67643cb6954SKuninori Morimoto } 67743cb6954SKuninori Morimoto 678ba9c949fSKuninori Morimoto static struct rsnd_mod_ops rsnd_src_gen2_ops = { 6798aefda50SKuninori Morimoto .name = SRC_NAME, 68072adc61fSKuninori Morimoto .dma_req = rsnd_src_dma_req, 681ba9c949fSKuninori Morimoto .probe = rsnd_src_probe_gen2, 682ba9c949fSKuninori Morimoto .init = rsnd_src_init_gen2, 683b761bf27SKuninori Morimoto .quit = rsnd_src_quit_gen2, 684ba9c949fSKuninori Morimoto .start = rsnd_src_start_gen2, 685ba9c949fSKuninori Morimoto .stop = rsnd_src_stop_gen2, 6863b7843ffSKuninori Morimoto .hw_params = rsnd_src_hw_params, 687b9bfe9d5SKuninori Morimoto .pcm_new = rsnd_src_pcm_new_gen2, 688ba9c949fSKuninori Morimoto }; 689ba9c949fSKuninori Morimoto 690ba9c949fSKuninori Morimoto struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id) 691ba9c949fSKuninori Morimoto { 692ba9c949fSKuninori Morimoto if (WARN_ON(id < 0 || id >= rsnd_src_nr(priv))) 693ba9c949fSKuninori Morimoto id = 0; 694ba9c949fSKuninori Morimoto 695b76e218aSKuninori Morimoto return rsnd_mod_get((struct rsnd_src *)(priv->src) + id); 696ba9c949fSKuninori Morimoto } 697ba9c949fSKuninori Morimoto 69890e8e50fSKuninori Morimoto static void rsnd_of_parse_src(struct platform_device *pdev, 69990e8e50fSKuninori Morimoto const struct rsnd_of_data *of_data, 70090e8e50fSKuninori Morimoto struct rsnd_priv *priv) 70190e8e50fSKuninori Morimoto { 70290e8e50fSKuninori Morimoto struct device_node *src_node; 703cfcefe01SKuninori Morimoto struct device_node *np; 70490e8e50fSKuninori Morimoto struct rcar_snd_info *info = rsnd_priv_to_info(priv); 70590e8e50fSKuninori Morimoto struct rsnd_src_platform_info *src_info; 70690e8e50fSKuninori Morimoto struct device *dev = &pdev->dev; 707cfcefe01SKuninori Morimoto int nr, i; 70890e8e50fSKuninori Morimoto 70990e8e50fSKuninori Morimoto if (!of_data) 71090e8e50fSKuninori Morimoto return; 71190e8e50fSKuninori Morimoto 71282e76ed3SKuninori Morimoto src_node = rsnd_src_of_node(priv); 71390e8e50fSKuninori Morimoto if (!src_node) 71490e8e50fSKuninori Morimoto return; 71590e8e50fSKuninori Morimoto 71690e8e50fSKuninori Morimoto nr = of_get_child_count(src_node); 71790e8e50fSKuninori Morimoto if (!nr) 718f451e48dSKuninori Morimoto goto rsnd_of_parse_src_end; 71990e8e50fSKuninori Morimoto 72090e8e50fSKuninori Morimoto src_info = devm_kzalloc(dev, 72190e8e50fSKuninori Morimoto sizeof(struct rsnd_src_platform_info) * nr, 72290e8e50fSKuninori Morimoto GFP_KERNEL); 72390e8e50fSKuninori Morimoto if (!src_info) { 72490e8e50fSKuninori Morimoto dev_err(dev, "src info allocation error\n"); 725f451e48dSKuninori Morimoto goto rsnd_of_parse_src_end; 72690e8e50fSKuninori Morimoto } 72790e8e50fSKuninori Morimoto 72890e8e50fSKuninori Morimoto info->src_info = src_info; 72990e8e50fSKuninori Morimoto info->src_info_nr = nr; 730f451e48dSKuninori Morimoto 731cfcefe01SKuninori Morimoto i = 0; 732cfcefe01SKuninori Morimoto for_each_child_of_node(src_node, np) { 733cfcefe01SKuninori Morimoto src_info[i].irq = irq_of_parse_and_map(np, 0); 734cfcefe01SKuninori Morimoto 735cfcefe01SKuninori Morimoto i++; 736cfcefe01SKuninori Morimoto } 737cfcefe01SKuninori Morimoto 738f451e48dSKuninori Morimoto rsnd_of_parse_src_end: 739f451e48dSKuninori Morimoto of_node_put(src_node); 74090e8e50fSKuninori Morimoto } 74190e8e50fSKuninori Morimoto 742ba9c949fSKuninori Morimoto int rsnd_src_probe(struct platform_device *pdev, 74390e8e50fSKuninori Morimoto const struct rsnd_of_data *of_data, 744ba9c949fSKuninori Morimoto struct rsnd_priv *priv) 745ba9c949fSKuninori Morimoto { 746ba9c949fSKuninori Morimoto struct rcar_snd_info *info = rsnd_priv_to_info(priv); 747ba9c949fSKuninori Morimoto struct device *dev = rsnd_priv_to_dev(priv); 748ba9c949fSKuninori Morimoto struct rsnd_src *src; 749ba9c949fSKuninori Morimoto struct clk *clk; 750ba9c949fSKuninori Morimoto char name[RSND_SRC_NAME_SIZE]; 7512f78dd7fSKuninori Morimoto int i, nr, ret; 752ba9c949fSKuninori Morimoto 753*e8e7b7bdSKuninori Morimoto /* This driver doesn't support Gen1 at this point */ 754*e8e7b7bdSKuninori Morimoto if (rsnd_is_gen1(priv)) 755*e8e7b7bdSKuninori Morimoto return 0; 756033e7ed8SKuninori Morimoto 75790e8e50fSKuninori Morimoto rsnd_of_parse_src(pdev, of_data, priv); 75890e8e50fSKuninori Morimoto 759ba9c949fSKuninori Morimoto /* 760ba9c949fSKuninori Morimoto * init SRC 761ba9c949fSKuninori Morimoto */ 762ba9c949fSKuninori Morimoto nr = info->src_info_nr; 763ba9c949fSKuninori Morimoto if (!nr) 764ba9c949fSKuninori Morimoto return 0; 765ba9c949fSKuninori Morimoto 766ba9c949fSKuninori Morimoto src = devm_kzalloc(dev, sizeof(*src) * nr, GFP_KERNEL); 76733363f7aSKuninori Morimoto if (!src) 768ba9c949fSKuninori Morimoto return -ENOMEM; 769ba9c949fSKuninori Morimoto 770ba9c949fSKuninori Morimoto priv->src_nr = nr; 771ba9c949fSKuninori Morimoto priv->src = src; 772ba9c949fSKuninori Morimoto 773ba9c949fSKuninori Morimoto for_each_rsnd_src(src, priv, i) { 7748aefda50SKuninori Morimoto snprintf(name, RSND_SRC_NAME_SIZE, "%s.%d", 7758aefda50SKuninori Morimoto SRC_NAME, i); 776ba9c949fSKuninori Morimoto 777ba9c949fSKuninori Morimoto clk = devm_clk_get(dev, name); 778ba9c949fSKuninori Morimoto if (IS_ERR(clk)) 779ba9c949fSKuninori Morimoto return PTR_ERR(clk); 780ba9c949fSKuninori Morimoto 781ba9c949fSKuninori Morimoto src->info = &info->src_info[i]; 782ba9c949fSKuninori Morimoto 783*e8e7b7bdSKuninori Morimoto ret = rsnd_mod_init(priv, rsnd_mod_get(src), 784*e8e7b7bdSKuninori Morimoto &rsnd_src_gen2_ops, clk, RSND_MOD_SRC, i); 7852f78dd7fSKuninori Morimoto if (ret) 7862f78dd7fSKuninori Morimoto return ret; 787ba9c949fSKuninori Morimoto } 788ba9c949fSKuninori Morimoto 789ba9c949fSKuninori Morimoto return 0; 790ba9c949fSKuninori Morimoto } 7912f78dd7fSKuninori Morimoto 7922f78dd7fSKuninori Morimoto void rsnd_src_remove(struct platform_device *pdev, 7932f78dd7fSKuninori Morimoto struct rsnd_priv *priv) 7942f78dd7fSKuninori Morimoto { 7952f78dd7fSKuninori Morimoto struct rsnd_src *src; 7962f78dd7fSKuninori Morimoto int i; 7972f78dd7fSKuninori Morimoto 7982f78dd7fSKuninori Morimoto for_each_rsnd_src(src, priv, i) { 799b76e218aSKuninori Morimoto rsnd_mod_quit(rsnd_mod_get(src)); 8002f78dd7fSKuninori Morimoto } 8012f78dd7fSKuninori Morimoto } 802