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