1*c087a94bSLad Prabhakar // SPDX-License-Identifier: GPL-2.0 2*c087a94bSLad Prabhakar // 3*c087a94bSLad Prabhakar // mix.c 4*c087a94bSLad Prabhakar // 5*c087a94bSLad Prabhakar // Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 6*c087a94bSLad Prabhakar 7*c087a94bSLad Prabhakar /* 8*c087a94bSLad Prabhakar * CTUn MIXn 9*c087a94bSLad Prabhakar * +------+ +------+ 10*c087a94bSLad Prabhakar * [SRC3 / SRC6] -> |CTU n0| -> [MIX n0| -> 11*c087a94bSLad Prabhakar * [SRC4 / SRC9] -> |CTU n1| -> [MIX n1| -> 12*c087a94bSLad Prabhakar * [SRC0 / SRC1] -> |CTU n2| -> [MIX n2| -> 13*c087a94bSLad Prabhakar * [SRC2 / SRC5] -> |CTU n3| -> [MIX n3| -> 14*c087a94bSLad Prabhakar * +------+ +------+ 15*c087a94bSLad Prabhakar * 16*c087a94bSLad Prabhakar * ex) 17*c087a94bSLad Prabhakar * DAI0 : playback = <&src0 &ctu02 &mix0 &dvc0 &ssi0>; 18*c087a94bSLad Prabhakar * DAI1 : playback = <&src2 &ctu03 &mix0 &dvc0 &ssi0>; 19*c087a94bSLad Prabhakar * 20*c087a94bSLad Prabhakar * MIX Volume 21*c087a94bSLad Prabhakar * amixer set "MIX",0 100% // DAI0 Volume 22*c087a94bSLad Prabhakar * amixer set "MIX",1 100% // DAI1 Volume 23*c087a94bSLad Prabhakar * 24*c087a94bSLad Prabhakar * Volume Ramp 25*c087a94bSLad Prabhakar * amixer set "MIX Ramp Up Rate" "0.125 dB/1 step" 26*c087a94bSLad Prabhakar * amixer set "MIX Ramp Down Rate" "4 dB/1 step" 27*c087a94bSLad Prabhakar * amixer set "MIX Ramp" on 28*c087a94bSLad Prabhakar * aplay xxx.wav & 29*c087a94bSLad Prabhakar * amixer set "MIX",0 80% // DAI0 Volume Down 30*c087a94bSLad Prabhakar * amixer set "MIX",1 100% // DAI1 Volume Up 31*c087a94bSLad Prabhakar */ 32*c087a94bSLad Prabhakar 33*c087a94bSLad Prabhakar #include "rsnd.h" 34*c087a94bSLad Prabhakar 35*c087a94bSLad Prabhakar #define MIX_NAME_SIZE 16 36*c087a94bSLad Prabhakar #define MIX_NAME "mix" 37*c087a94bSLad Prabhakar 38*c087a94bSLad Prabhakar struct rsnd_mix { 39*c087a94bSLad Prabhakar struct rsnd_mod mod; 40*c087a94bSLad Prabhakar struct rsnd_kctrl_cfg_s volumeA; /* MDBAR */ 41*c087a94bSLad Prabhakar struct rsnd_kctrl_cfg_s volumeB; /* MDBBR */ 42*c087a94bSLad Prabhakar struct rsnd_kctrl_cfg_s volumeC; /* MDBCR */ 43*c087a94bSLad Prabhakar struct rsnd_kctrl_cfg_s volumeD; /* MDBDR */ 44*c087a94bSLad Prabhakar struct rsnd_kctrl_cfg_s ren; /* Ramp Enable */ 45*c087a94bSLad Prabhakar struct rsnd_kctrl_cfg_s rup; /* Ramp Rate Up */ 46*c087a94bSLad Prabhakar struct rsnd_kctrl_cfg_s rdw; /* Ramp Rate Down */ 47*c087a94bSLad Prabhakar u32 flags; 48*c087a94bSLad Prabhakar }; 49*c087a94bSLad Prabhakar 50*c087a94bSLad Prabhakar #define ONCE_KCTRL_INITIALIZED (1 << 0) 51*c087a94bSLad Prabhakar #define HAS_VOLA (1 << 1) 52*c087a94bSLad Prabhakar #define HAS_VOLB (1 << 2) 53*c087a94bSLad Prabhakar #define HAS_VOLC (1 << 3) 54*c087a94bSLad Prabhakar #define HAS_VOLD (1 << 4) 55*c087a94bSLad Prabhakar 56*c087a94bSLad Prabhakar #define VOL_MAX 0x3ff 57*c087a94bSLad Prabhakar 58*c087a94bSLad Prabhakar #define rsnd_mod_to_mix(_mod) \ 59*c087a94bSLad Prabhakar container_of((_mod), struct rsnd_mix, mod) 60*c087a94bSLad Prabhakar 61*c087a94bSLad Prabhakar #define rsnd_mix_get(priv, id) ((struct rsnd_mix *)(priv->mix) + id) 62*c087a94bSLad Prabhakar #define rsnd_mix_nr(priv) ((priv)->mix_nr) 63*c087a94bSLad Prabhakar #define for_each_rsnd_mix(pos, priv, i) \ 64*c087a94bSLad Prabhakar for ((i) = 0; \ 65*c087a94bSLad Prabhakar ((i) < rsnd_mix_nr(priv)) && \ 66*c087a94bSLad Prabhakar ((pos) = (struct rsnd_mix *)(priv)->mix + i); \ 67*c087a94bSLad Prabhakar i++) 68*c087a94bSLad Prabhakar 69*c087a94bSLad Prabhakar static void rsnd_mix_activation(struct rsnd_mod *mod) 70*c087a94bSLad Prabhakar { 71*c087a94bSLad Prabhakar rsnd_mod_write(mod, MIX_SWRSR, 0); 72*c087a94bSLad Prabhakar rsnd_mod_write(mod, MIX_SWRSR, 1); 73*c087a94bSLad Prabhakar } 74*c087a94bSLad Prabhakar 75*c087a94bSLad Prabhakar static void rsnd_mix_halt(struct rsnd_mod *mod) 76*c087a94bSLad Prabhakar { 77*c087a94bSLad Prabhakar rsnd_mod_write(mod, MIX_MIXIR, 1); 78*c087a94bSLad Prabhakar rsnd_mod_write(mod, MIX_SWRSR, 0); 79*c087a94bSLad Prabhakar } 80*c087a94bSLad Prabhakar 81*c087a94bSLad Prabhakar #define rsnd_mix_get_vol(mix, X) \ 82*c087a94bSLad Prabhakar rsnd_flags_has(mix, HAS_VOL##X) ? \ 83*c087a94bSLad Prabhakar (VOL_MAX - rsnd_kctrl_vals(mix->volume##X)) : 0 84*c087a94bSLad Prabhakar static void rsnd_mix_volume_parameter(struct rsnd_dai_stream *io, 85*c087a94bSLad Prabhakar struct rsnd_mod *mod) 86*c087a94bSLad Prabhakar { 87*c087a94bSLad Prabhakar struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 88*c087a94bSLad Prabhakar struct device *dev = rsnd_priv_to_dev(priv); 89*c087a94bSLad Prabhakar struct rsnd_mix *mix = rsnd_mod_to_mix(mod); 90*c087a94bSLad Prabhakar u32 volA = rsnd_mix_get_vol(mix, A); 91*c087a94bSLad Prabhakar u32 volB = rsnd_mix_get_vol(mix, B); 92*c087a94bSLad Prabhakar u32 volC = rsnd_mix_get_vol(mix, C); 93*c087a94bSLad Prabhakar u32 volD = rsnd_mix_get_vol(mix, D); 94*c087a94bSLad Prabhakar 95*c087a94bSLad Prabhakar dev_dbg(dev, "MIX A/B/C/D = %02x/%02x/%02x/%02x\n", 96*c087a94bSLad Prabhakar volA, volB, volC, volD); 97*c087a94bSLad Prabhakar 98*c087a94bSLad Prabhakar rsnd_mod_write(mod, MIX_MDBAR, volA); 99*c087a94bSLad Prabhakar rsnd_mod_write(mod, MIX_MDBBR, volB); 100*c087a94bSLad Prabhakar rsnd_mod_write(mod, MIX_MDBCR, volC); 101*c087a94bSLad Prabhakar rsnd_mod_write(mod, MIX_MDBDR, volD); 102*c087a94bSLad Prabhakar } 103*c087a94bSLad Prabhakar 104*c087a94bSLad Prabhakar static void rsnd_mix_volume_init(struct rsnd_dai_stream *io, 105*c087a94bSLad Prabhakar struct rsnd_mod *mod) 106*c087a94bSLad Prabhakar { 107*c087a94bSLad Prabhakar struct rsnd_mix *mix = rsnd_mod_to_mix(mod); 108*c087a94bSLad Prabhakar 109*c087a94bSLad Prabhakar rsnd_mod_write(mod, MIX_MIXIR, 1); 110*c087a94bSLad Prabhakar 111*c087a94bSLad Prabhakar /* General Information */ 112*c087a94bSLad Prabhakar rsnd_mod_write(mod, MIX_ADINR, rsnd_runtime_channel_after_ctu(io)); 113*c087a94bSLad Prabhakar 114*c087a94bSLad Prabhakar /* volume step */ 115*c087a94bSLad Prabhakar rsnd_mod_write(mod, MIX_MIXMR, rsnd_kctrl_vals(mix->ren)); 116*c087a94bSLad Prabhakar rsnd_mod_write(mod, MIX_MVPDR, rsnd_kctrl_vals(mix->rup) << 8 | 117*c087a94bSLad Prabhakar rsnd_kctrl_vals(mix->rdw)); 118*c087a94bSLad Prabhakar 119*c087a94bSLad Prabhakar /* common volume parameter */ 120*c087a94bSLad Prabhakar rsnd_mix_volume_parameter(io, mod); 121*c087a94bSLad Prabhakar 122*c087a94bSLad Prabhakar rsnd_mod_write(mod, MIX_MIXIR, 0); 123*c087a94bSLad Prabhakar } 124*c087a94bSLad Prabhakar 125*c087a94bSLad Prabhakar static void rsnd_mix_volume_update(struct rsnd_dai_stream *io, 126*c087a94bSLad Prabhakar struct rsnd_mod *mod) 127*c087a94bSLad Prabhakar { 128*c087a94bSLad Prabhakar /* Disable MIX dB setting */ 129*c087a94bSLad Prabhakar rsnd_mod_write(mod, MIX_MDBER, 0); 130*c087a94bSLad Prabhakar 131*c087a94bSLad Prabhakar /* common volume parameter */ 132*c087a94bSLad Prabhakar rsnd_mix_volume_parameter(io, mod); 133*c087a94bSLad Prabhakar 134*c087a94bSLad Prabhakar /* Enable MIX dB setting */ 135*c087a94bSLad Prabhakar rsnd_mod_write(mod, MIX_MDBER, 1); 136*c087a94bSLad Prabhakar } 137*c087a94bSLad Prabhakar 138*c087a94bSLad Prabhakar static int rsnd_mix_probe_(struct rsnd_mod *mod, 139*c087a94bSLad Prabhakar struct rsnd_dai_stream *io, 140*c087a94bSLad Prabhakar struct rsnd_priv *priv) 141*c087a94bSLad Prabhakar { 142*c087a94bSLad Prabhakar return rsnd_cmd_attach(io, rsnd_mod_id(mod)); 143*c087a94bSLad Prabhakar } 144*c087a94bSLad Prabhakar 145*c087a94bSLad Prabhakar static int rsnd_mix_init(struct rsnd_mod *mod, 146*c087a94bSLad Prabhakar struct rsnd_dai_stream *io, 147*c087a94bSLad Prabhakar struct rsnd_priv *priv) 148*c087a94bSLad Prabhakar { 149*c087a94bSLad Prabhakar int ret; 150*c087a94bSLad Prabhakar 151*c087a94bSLad Prabhakar ret = rsnd_mod_power_on(mod); 152*c087a94bSLad Prabhakar if (ret < 0) 153*c087a94bSLad Prabhakar return ret; 154*c087a94bSLad Prabhakar 155*c087a94bSLad Prabhakar rsnd_mix_activation(mod); 156*c087a94bSLad Prabhakar 157*c087a94bSLad Prabhakar rsnd_mix_volume_init(io, mod); 158*c087a94bSLad Prabhakar 159*c087a94bSLad Prabhakar rsnd_mix_volume_update(io, mod); 160*c087a94bSLad Prabhakar 161*c087a94bSLad Prabhakar return 0; 162*c087a94bSLad Prabhakar } 163*c087a94bSLad Prabhakar 164*c087a94bSLad Prabhakar static int rsnd_mix_quit(struct rsnd_mod *mod, 165*c087a94bSLad Prabhakar struct rsnd_dai_stream *io, 166*c087a94bSLad Prabhakar struct rsnd_priv *priv) 167*c087a94bSLad Prabhakar { 168*c087a94bSLad Prabhakar rsnd_mix_halt(mod); 169*c087a94bSLad Prabhakar 170*c087a94bSLad Prabhakar rsnd_mod_power_off(mod); 171*c087a94bSLad Prabhakar 172*c087a94bSLad Prabhakar return 0; 173*c087a94bSLad Prabhakar } 174*c087a94bSLad Prabhakar 175*c087a94bSLad Prabhakar static int rsnd_mix_pcm_new(struct rsnd_mod *mod, 176*c087a94bSLad Prabhakar struct rsnd_dai_stream *io, 177*c087a94bSLad Prabhakar struct snd_soc_pcm_runtime *rtd) 178*c087a94bSLad Prabhakar { 179*c087a94bSLad Prabhakar struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 180*c087a94bSLad Prabhakar struct device *dev = rsnd_priv_to_dev(priv); 181*c087a94bSLad Prabhakar struct rsnd_mix *mix = rsnd_mod_to_mix(mod); 182*c087a94bSLad Prabhakar struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); 183*c087a94bSLad Prabhakar struct rsnd_kctrl_cfg_s *volume; 184*c087a94bSLad Prabhakar int ret; 185*c087a94bSLad Prabhakar 186*c087a94bSLad Prabhakar switch (rsnd_mod_id(src_mod)) { 187*c087a94bSLad Prabhakar case 3: 188*c087a94bSLad Prabhakar case 6: /* MDBAR */ 189*c087a94bSLad Prabhakar volume = &mix->volumeA; 190*c087a94bSLad Prabhakar rsnd_flags_set(mix, HAS_VOLA); 191*c087a94bSLad Prabhakar break; 192*c087a94bSLad Prabhakar case 4: 193*c087a94bSLad Prabhakar case 9: /* MDBBR */ 194*c087a94bSLad Prabhakar volume = &mix->volumeB; 195*c087a94bSLad Prabhakar rsnd_flags_set(mix, HAS_VOLB); 196*c087a94bSLad Prabhakar break; 197*c087a94bSLad Prabhakar case 0: 198*c087a94bSLad Prabhakar case 1: /* MDBCR */ 199*c087a94bSLad Prabhakar volume = &mix->volumeC; 200*c087a94bSLad Prabhakar rsnd_flags_set(mix, HAS_VOLC); 201*c087a94bSLad Prabhakar break; 202*c087a94bSLad Prabhakar case 2: 203*c087a94bSLad Prabhakar case 5: /* MDBDR */ 204*c087a94bSLad Prabhakar volume = &mix->volumeD; 205*c087a94bSLad Prabhakar rsnd_flags_set(mix, HAS_VOLD); 206*c087a94bSLad Prabhakar break; 207*c087a94bSLad Prabhakar default: 208*c087a94bSLad Prabhakar dev_err(dev, "unknown SRC is connected\n"); 209*c087a94bSLad Prabhakar return -EINVAL; 210*c087a94bSLad Prabhakar } 211*c087a94bSLad Prabhakar 212*c087a94bSLad Prabhakar /* Volume */ 213*c087a94bSLad Prabhakar ret = rsnd_kctrl_new_s(mod, io, rtd, 214*c087a94bSLad Prabhakar "MIX Playback Volume", 215*c087a94bSLad Prabhakar rsnd_kctrl_accept_anytime, 216*c087a94bSLad Prabhakar rsnd_mix_volume_update, 217*c087a94bSLad Prabhakar volume, VOL_MAX); 218*c087a94bSLad Prabhakar if (ret < 0) 219*c087a94bSLad Prabhakar return ret; 220*c087a94bSLad Prabhakar rsnd_kctrl_vals(*volume) = VOL_MAX; 221*c087a94bSLad Prabhakar 222*c087a94bSLad Prabhakar if (rsnd_flags_has(mix, ONCE_KCTRL_INITIALIZED)) 223*c087a94bSLad Prabhakar return ret; 224*c087a94bSLad Prabhakar 225*c087a94bSLad Prabhakar /* Ramp */ 226*c087a94bSLad Prabhakar ret = rsnd_kctrl_new_s(mod, io, rtd, 227*c087a94bSLad Prabhakar "MIX Ramp Switch", 228*c087a94bSLad Prabhakar rsnd_kctrl_accept_anytime, 229*c087a94bSLad Prabhakar rsnd_mix_volume_update, 230*c087a94bSLad Prabhakar &mix->ren, 1); 231*c087a94bSLad Prabhakar if (ret < 0) 232*c087a94bSLad Prabhakar return ret; 233*c087a94bSLad Prabhakar 234*c087a94bSLad Prabhakar ret = rsnd_kctrl_new_e(mod, io, rtd, 235*c087a94bSLad Prabhakar "MIX Ramp Up Rate", 236*c087a94bSLad Prabhakar rsnd_kctrl_accept_anytime, 237*c087a94bSLad Prabhakar rsnd_mix_volume_update, 238*c087a94bSLad Prabhakar &mix->rup, 239*c087a94bSLad Prabhakar volume_ramp_rate, 240*c087a94bSLad Prabhakar VOLUME_RAMP_MAX_MIX); 241*c087a94bSLad Prabhakar if (ret < 0) 242*c087a94bSLad Prabhakar return ret; 243*c087a94bSLad Prabhakar 244*c087a94bSLad Prabhakar ret = rsnd_kctrl_new_e(mod, io, rtd, 245*c087a94bSLad Prabhakar "MIX Ramp Down Rate", 246*c087a94bSLad Prabhakar rsnd_kctrl_accept_anytime, 247*c087a94bSLad Prabhakar rsnd_mix_volume_update, 248*c087a94bSLad Prabhakar &mix->rdw, 249*c087a94bSLad Prabhakar volume_ramp_rate, 250*c087a94bSLad Prabhakar VOLUME_RAMP_MAX_MIX); 251*c087a94bSLad Prabhakar 252*c087a94bSLad Prabhakar rsnd_flags_set(mix, ONCE_KCTRL_INITIALIZED); 253*c087a94bSLad Prabhakar 254*c087a94bSLad Prabhakar return ret; 255*c087a94bSLad Prabhakar } 256*c087a94bSLad Prabhakar 257*c087a94bSLad Prabhakar #ifdef CONFIG_DEBUG_FS 258*c087a94bSLad Prabhakar static void rsnd_mix_debug_info(struct seq_file *m, 259*c087a94bSLad Prabhakar struct rsnd_dai_stream *io, 260*c087a94bSLad Prabhakar struct rsnd_mod *mod) 261*c087a94bSLad Prabhakar { 262*c087a94bSLad Prabhakar rsnd_debugfs_mod_reg_show(m, mod, RSND_BASE_SCU, 263*c087a94bSLad Prabhakar 0xd00 + rsnd_mod_id(mod) * 0x40, 0x30); 264*c087a94bSLad Prabhakar } 265*c087a94bSLad Prabhakar #define DEBUG_INFO .debug_info = rsnd_mix_debug_info 266*c087a94bSLad Prabhakar #else 267*c087a94bSLad Prabhakar #define DEBUG_INFO 268*c087a94bSLad Prabhakar #endif 269*c087a94bSLad Prabhakar 270*c087a94bSLad Prabhakar static struct rsnd_mod_ops rsnd_mix_ops = { 271*c087a94bSLad Prabhakar .name = MIX_NAME, 272*c087a94bSLad Prabhakar .probe = rsnd_mix_probe_, 273*c087a94bSLad Prabhakar .init = rsnd_mix_init, 274*c087a94bSLad Prabhakar .quit = rsnd_mix_quit, 275*c087a94bSLad Prabhakar .pcm_new = rsnd_mix_pcm_new, 276*c087a94bSLad Prabhakar .get_status = rsnd_mod_get_status, 277*c087a94bSLad Prabhakar DEBUG_INFO 278*c087a94bSLad Prabhakar }; 279*c087a94bSLad Prabhakar 280*c087a94bSLad Prabhakar struct rsnd_mod *rsnd_mix_mod_get(struct rsnd_priv *priv, int id) 281*c087a94bSLad Prabhakar { 282*c087a94bSLad Prabhakar if (WARN_ON(id < 0 || id >= rsnd_mix_nr(priv))) 283*c087a94bSLad Prabhakar id = 0; 284*c087a94bSLad Prabhakar 285*c087a94bSLad Prabhakar return rsnd_mod_get(rsnd_mix_get(priv, id)); 286*c087a94bSLad Prabhakar } 287*c087a94bSLad Prabhakar 288*c087a94bSLad Prabhakar int rsnd_mix_probe(struct rsnd_priv *priv) 289*c087a94bSLad Prabhakar { 290*c087a94bSLad Prabhakar struct device_node *node; 291*c087a94bSLad Prabhakar struct device_node *np; 292*c087a94bSLad Prabhakar struct device *dev = rsnd_priv_to_dev(priv); 293*c087a94bSLad Prabhakar struct rsnd_mix *mix; 294*c087a94bSLad Prabhakar struct clk *clk; 295*c087a94bSLad Prabhakar char name[MIX_NAME_SIZE]; 296*c087a94bSLad Prabhakar int i, nr, ret; 297*c087a94bSLad Prabhakar 298*c087a94bSLad Prabhakar node = rsnd_mix_of_node(priv); 299*c087a94bSLad Prabhakar if (!node) 300*c087a94bSLad Prabhakar return 0; /* not used is not error */ 301*c087a94bSLad Prabhakar 302*c087a94bSLad Prabhakar nr = of_get_child_count(node); 303*c087a94bSLad Prabhakar if (!nr) { 304*c087a94bSLad Prabhakar ret = -EINVAL; 305*c087a94bSLad Prabhakar goto rsnd_mix_probe_done; 306*c087a94bSLad Prabhakar } 307*c087a94bSLad Prabhakar 308*c087a94bSLad Prabhakar mix = devm_kcalloc(dev, nr, sizeof(*mix), GFP_KERNEL); 309*c087a94bSLad Prabhakar if (!mix) { 310*c087a94bSLad Prabhakar ret = -ENOMEM; 311*c087a94bSLad Prabhakar goto rsnd_mix_probe_done; 312*c087a94bSLad Prabhakar } 313*c087a94bSLad Prabhakar 314*c087a94bSLad Prabhakar priv->mix_nr = nr; 315*c087a94bSLad Prabhakar priv->mix = mix; 316*c087a94bSLad Prabhakar 317*c087a94bSLad Prabhakar i = 0; 318*c087a94bSLad Prabhakar ret = 0; 319*c087a94bSLad Prabhakar for_each_child_of_node(node, np) { 320*c087a94bSLad Prabhakar mix = rsnd_mix_get(priv, i); 321*c087a94bSLad Prabhakar 322*c087a94bSLad Prabhakar snprintf(name, MIX_NAME_SIZE, "%s.%d", 323*c087a94bSLad Prabhakar MIX_NAME, i); 324*c087a94bSLad Prabhakar 325*c087a94bSLad Prabhakar clk = devm_clk_get(dev, name); 326*c087a94bSLad Prabhakar if (IS_ERR(clk)) { 327*c087a94bSLad Prabhakar ret = PTR_ERR(clk); 328*c087a94bSLad Prabhakar of_node_put(np); 329*c087a94bSLad Prabhakar goto rsnd_mix_probe_done; 330*c087a94bSLad Prabhakar } 331*c087a94bSLad Prabhakar 332*c087a94bSLad Prabhakar ret = rsnd_mod_init(priv, rsnd_mod_get(mix), &rsnd_mix_ops, 333*c087a94bSLad Prabhakar clk, RSND_MOD_MIX, i); 334*c087a94bSLad Prabhakar if (ret) { 335*c087a94bSLad Prabhakar of_node_put(np); 336*c087a94bSLad Prabhakar goto rsnd_mix_probe_done; 337*c087a94bSLad Prabhakar } 338*c087a94bSLad Prabhakar 339*c087a94bSLad Prabhakar i++; 340*c087a94bSLad Prabhakar } 341*c087a94bSLad Prabhakar 342*c087a94bSLad Prabhakar rsnd_mix_probe_done: 343*c087a94bSLad Prabhakar of_node_put(node); 344*c087a94bSLad Prabhakar 345*c087a94bSLad Prabhakar return ret; 346*c087a94bSLad Prabhakar } 347*c087a94bSLad Prabhakar 348*c087a94bSLad Prabhakar void rsnd_mix_remove(struct rsnd_priv *priv) 349*c087a94bSLad Prabhakar { 350*c087a94bSLad Prabhakar struct rsnd_mix *mix; 351*c087a94bSLad Prabhakar int i; 352*c087a94bSLad Prabhakar 353*c087a94bSLad Prabhakar for_each_rsnd_mix(mix, priv, i) { 354*c087a94bSLad Prabhakar rsnd_mod_quit(rsnd_mod_get(mix)); 355*c087a94bSLad Prabhakar } 356*c087a94bSLad Prabhakar } 357