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