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