1 /* 2 * Renesas R-Car DVC support 3 * 4 * Copyright (C) 2014 Renesas Solutions Corp. 5 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 */ 11 12 /* 13 * Playback Volume 14 * amixer set "DVC Out" 100% 15 * 16 * Capture Volume 17 * amixer set "DVC In" 100% 18 * 19 * Playback Mute 20 * amixer set "DVC Out Mute" on 21 * 22 * Capture Mute 23 * amixer set "DVC In Mute" on 24 * 25 * Volume Ramp 26 * amixer set "DVC Out Ramp Up Rate" "0.125 dB/64 steps" 27 * amixer set "DVC Out Ramp Down Rate" "0.125 dB/512 steps" 28 * amixer set "DVC Out Ramp" on 29 * aplay xxx.wav & 30 * amixer set "DVC Out" 80% // Volume Down 31 * amixer set "DVC Out" 100% // Volume Up 32 */ 33 34 #include "rsnd.h" 35 36 #define RSND_DVC_NAME_SIZE 16 37 38 #define DVC_NAME "dvc" 39 40 struct rsnd_dvc { 41 struct rsnd_mod mod; 42 struct rsnd_kctrl_cfg_m volume; 43 struct rsnd_kctrl_cfg_m mute; 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 rdown; /* Ramp Rate Down */ 47 }; 48 49 #define rsnd_dvc_get(priv, id) ((struct rsnd_dvc *)(priv->dvc) + id) 50 #define rsnd_dvc_nr(priv) ((priv)->dvc_nr) 51 52 #define rsnd_mod_to_dvc(_mod) \ 53 container_of((_mod), struct rsnd_dvc, mod) 54 55 #define for_each_rsnd_dvc(pos, priv, i) \ 56 for ((i) = 0; \ 57 ((i) < rsnd_dvc_nr(priv)) && \ 58 ((pos) = (struct rsnd_dvc *)(priv)->dvc + i); \ 59 i++) 60 61 static const char * const dvc_ramp_rate[] = { 62 "128 dB/1 step", /* 00000 */ 63 "64 dB/1 step", /* 00001 */ 64 "32 dB/1 step", /* 00010 */ 65 "16 dB/1 step", /* 00011 */ 66 "8 dB/1 step", /* 00100 */ 67 "4 dB/1 step", /* 00101 */ 68 "2 dB/1 step", /* 00110 */ 69 "1 dB/1 step", /* 00111 */ 70 "0.5 dB/1 step", /* 01000 */ 71 "0.25 dB/1 step", /* 01001 */ 72 "0.125 dB/1 step", /* 01010 */ 73 "0.125 dB/2 steps", /* 01011 */ 74 "0.125 dB/4 steps", /* 01100 */ 75 "0.125 dB/8 steps", /* 01101 */ 76 "0.125 dB/16 steps", /* 01110 */ 77 "0.125 dB/32 steps", /* 01111 */ 78 "0.125 dB/64 steps", /* 10000 */ 79 "0.125 dB/128 steps", /* 10001 */ 80 "0.125 dB/256 steps", /* 10010 */ 81 "0.125 dB/512 steps", /* 10011 */ 82 "0.125 dB/1024 steps", /* 10100 */ 83 "0.125 dB/2048 steps", /* 10101 */ 84 "0.125 dB/4096 steps", /* 10110 */ 85 "0.125 dB/8192 steps", /* 10111 */ 86 }; 87 88 static void rsnd_dvc_activation(struct rsnd_mod *mod) 89 { 90 rsnd_mod_write(mod, DVC_SWRSR, 0); 91 rsnd_mod_write(mod, DVC_SWRSR, 1); 92 } 93 94 static void rsnd_dvc_halt(struct rsnd_mod *mod) 95 { 96 rsnd_mod_write(mod, DVC_DVUIR, 1); 97 rsnd_mod_write(mod, DVC_SWRSR, 0); 98 } 99 100 #define rsnd_dvc_get_vrpdr(dvc) (dvc->rup.val << 8 | dvc->rdown.val) 101 #define rsnd_dvc_get_vrdbr(dvc) (0x3ff - (dvc->volume.val[0] >> 13)) 102 103 static void rsnd_dvc_volume_parameter(struct rsnd_dai_stream *io, 104 struct rsnd_mod *mod) 105 { 106 struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); 107 u32 val[RSND_MAX_CHANNELS]; 108 int i; 109 110 /* Enable Ramp */ 111 if (dvc->ren.val) 112 for (i = 0; i < RSND_MAX_CHANNELS; i++) 113 val[i] = dvc->volume.cfg.max; 114 else 115 for (i = 0; i < RSND_MAX_CHANNELS; i++) 116 val[i] = dvc->volume.val[i]; 117 118 /* Enable Digital Volume */ 119 rsnd_mod_write(mod, DVC_VOL0R, val[0]); 120 rsnd_mod_write(mod, DVC_VOL1R, val[1]); 121 rsnd_mod_write(mod, DVC_VOL2R, val[2]); 122 rsnd_mod_write(mod, DVC_VOL3R, val[3]); 123 rsnd_mod_write(mod, DVC_VOL4R, val[4]); 124 rsnd_mod_write(mod, DVC_VOL5R, val[5]); 125 rsnd_mod_write(mod, DVC_VOL6R, val[6]); 126 rsnd_mod_write(mod, DVC_VOL7R, val[7]); 127 } 128 129 static void rsnd_dvc_volume_init(struct rsnd_dai_stream *io, 130 struct rsnd_mod *mod) 131 { 132 struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); 133 u32 adinr = 0; 134 u32 dvucr = 0; 135 u32 vrctr = 0; 136 u32 vrpdr = 0; 137 u32 vrdbr = 0; 138 139 adinr = rsnd_get_adinr_bit(mod, io) | 140 rsnd_runtime_channel_after_ctu(io); 141 142 /* Enable Digital Volume, Zero Cross Mute Mode */ 143 dvucr |= 0x101; 144 145 /* Enable Ramp */ 146 if (dvc->ren.val) { 147 dvucr |= 0x10; 148 149 /* 150 * FIXME !! 151 * use scale-downed Digital Volume 152 * as Volume Ramp 153 * 7F FFFF -> 3FF 154 */ 155 vrctr = 0xff; 156 vrpdr = rsnd_dvc_get_vrpdr(dvc); 157 vrdbr = rsnd_dvc_get_vrdbr(dvc); 158 } 159 160 /* Initialize operation */ 161 rsnd_mod_write(mod, DVC_DVUIR, 1); 162 163 /* General Information */ 164 rsnd_mod_write(mod, DVC_ADINR, adinr); 165 rsnd_mod_write(mod, DVC_DVUCR, dvucr); 166 167 /* Volume Ramp Parameter */ 168 rsnd_mod_write(mod, DVC_VRCTR, vrctr); 169 rsnd_mod_write(mod, DVC_VRPDR, vrpdr); 170 rsnd_mod_write(mod, DVC_VRDBR, vrdbr); 171 172 /* Digital Volume Function Parameter */ 173 rsnd_dvc_volume_parameter(io, mod); 174 175 /* cancel operation */ 176 rsnd_mod_write(mod, DVC_DVUIR, 0); 177 } 178 179 static void rsnd_dvc_volume_update(struct rsnd_dai_stream *io, 180 struct rsnd_mod *mod) 181 { 182 struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); 183 u32 zcmcr = 0; 184 u32 vrpdr = 0; 185 u32 vrdbr = 0; 186 int i; 187 188 for (i = 0; i < dvc->mute.cfg.size; i++) 189 zcmcr |= (!!dvc->mute.cfg.val[i]) << i; 190 191 if (dvc->ren.val) { 192 vrpdr = rsnd_dvc_get_vrpdr(dvc); 193 vrdbr = rsnd_dvc_get_vrdbr(dvc); 194 } 195 196 /* Disable DVC Register access */ 197 rsnd_mod_write(mod, DVC_DVUER, 0); 198 199 /* Zero Cross Mute Function */ 200 rsnd_mod_write(mod, DVC_ZCMCR, zcmcr); 201 202 /* Volume Ramp Function */ 203 rsnd_mod_write(mod, DVC_VRPDR, vrpdr); 204 rsnd_mod_write(mod, DVC_VRDBR, vrdbr); 205 /* add DVC_VRWTR here */ 206 207 /* Digital Volume Function Parameter */ 208 rsnd_dvc_volume_parameter(io, mod); 209 210 /* Enable DVC Register access */ 211 rsnd_mod_write(mod, DVC_DVUER, 1); 212 } 213 214 static int rsnd_dvc_probe_(struct rsnd_mod *mod, 215 struct rsnd_dai_stream *io, 216 struct rsnd_priv *priv) 217 { 218 return rsnd_cmd_attach(io, rsnd_mod_id(mod)); 219 } 220 221 static int rsnd_dvc_init(struct rsnd_mod *mod, 222 struct rsnd_dai_stream *io, 223 struct rsnd_priv *priv) 224 { 225 rsnd_mod_power_on(mod); 226 227 rsnd_dvc_activation(mod); 228 229 rsnd_dvc_volume_init(io, mod); 230 231 rsnd_dvc_volume_update(io, mod); 232 233 return 0; 234 } 235 236 static int rsnd_dvc_quit(struct rsnd_mod *mod, 237 struct rsnd_dai_stream *io, 238 struct rsnd_priv *priv) 239 { 240 rsnd_dvc_halt(mod); 241 242 rsnd_mod_power_off(mod); 243 244 return 0; 245 } 246 247 static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, 248 struct rsnd_dai_stream *io, 249 struct snd_soc_pcm_runtime *rtd) 250 { 251 struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); 252 struct rsnd_dai *rdai = rsnd_io_to_rdai(io); 253 int is_play = rsnd_io_is_play(io); 254 int channels = rsnd_rdai_channels_get(rdai); 255 int ret; 256 257 /* Volume */ 258 ret = rsnd_kctrl_new_m(mod, io, rtd, 259 is_play ? 260 "DVC Out Playback Volume" : "DVC In Capture Volume", 261 rsnd_kctrl_accept_anytime, 262 rsnd_dvc_volume_update, 263 &dvc->volume, channels, 264 0x00800000 - 1); 265 if (ret < 0) 266 return ret; 267 268 /* Mute */ 269 ret = rsnd_kctrl_new_m(mod, io, rtd, 270 is_play ? 271 "DVC Out Mute Switch" : "DVC In Mute Switch", 272 rsnd_kctrl_accept_anytime, 273 rsnd_dvc_volume_update, 274 &dvc->mute, channels, 275 1); 276 if (ret < 0) 277 return ret; 278 279 /* Ramp */ 280 ret = rsnd_kctrl_new_s(mod, io, rtd, 281 is_play ? 282 "DVC Out Ramp Switch" : "DVC In Ramp Switch", 283 rsnd_kctrl_accept_anytime, 284 rsnd_dvc_volume_update, 285 &dvc->ren, 1); 286 if (ret < 0) 287 return ret; 288 289 ret = rsnd_kctrl_new_e(mod, io, rtd, 290 is_play ? 291 "DVC Out Ramp Up Rate" : "DVC In Ramp Up Rate", 292 rsnd_kctrl_accept_anytime, 293 rsnd_dvc_volume_update, 294 &dvc->rup, 295 dvc_ramp_rate); 296 if (ret < 0) 297 return ret; 298 299 ret = rsnd_kctrl_new_e(mod, io, rtd, 300 is_play ? 301 "DVC Out Ramp Down Rate" : "DVC In Ramp Down Rate", 302 rsnd_kctrl_accept_anytime, 303 rsnd_dvc_volume_update, 304 &dvc->rdown, 305 dvc_ramp_rate); 306 307 if (ret < 0) 308 return ret; 309 310 return 0; 311 } 312 313 static struct dma_chan *rsnd_dvc_dma_req(struct rsnd_dai_stream *io, 314 struct rsnd_mod *mod) 315 { 316 struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 317 318 return rsnd_dma_request_channel(rsnd_dvc_of_node(priv), 319 mod, "tx"); 320 } 321 322 static struct rsnd_mod_ops rsnd_dvc_ops = { 323 .name = DVC_NAME, 324 .dma_req = rsnd_dvc_dma_req, 325 .probe = rsnd_dvc_probe_, 326 .init = rsnd_dvc_init, 327 .quit = rsnd_dvc_quit, 328 .pcm_new = rsnd_dvc_pcm_new, 329 }; 330 331 struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id) 332 { 333 if (WARN_ON(id < 0 || id >= rsnd_dvc_nr(priv))) 334 id = 0; 335 336 return rsnd_mod_get(rsnd_dvc_get(priv, id)); 337 } 338 339 int rsnd_dvc_probe(struct rsnd_priv *priv) 340 { 341 struct device_node *node; 342 struct device_node *np; 343 struct device *dev = rsnd_priv_to_dev(priv); 344 struct rsnd_dvc *dvc; 345 struct clk *clk; 346 char name[RSND_DVC_NAME_SIZE]; 347 int i, nr, ret; 348 349 /* This driver doesn't support Gen1 at this point */ 350 if (rsnd_is_gen1(priv)) 351 return 0; 352 353 node = rsnd_dvc_of_node(priv); 354 if (!node) 355 return 0; /* not used is not error */ 356 357 nr = of_get_child_count(node); 358 if (!nr) { 359 ret = -EINVAL; 360 goto rsnd_dvc_probe_done; 361 } 362 363 dvc = devm_kzalloc(dev, sizeof(*dvc) * nr, GFP_KERNEL); 364 if (!dvc) { 365 ret = -ENOMEM; 366 goto rsnd_dvc_probe_done; 367 } 368 369 priv->dvc_nr = nr; 370 priv->dvc = dvc; 371 372 i = 0; 373 ret = 0; 374 for_each_child_of_node(node, np) { 375 dvc = rsnd_dvc_get(priv, i); 376 377 snprintf(name, RSND_DVC_NAME_SIZE, "%s.%d", 378 DVC_NAME, i); 379 380 clk = devm_clk_get(dev, name); 381 if (IS_ERR(clk)) { 382 ret = PTR_ERR(clk); 383 goto rsnd_dvc_probe_done; 384 } 385 386 ret = rsnd_mod_init(priv, rsnd_mod_get(dvc), &rsnd_dvc_ops, 387 clk, rsnd_mod_get_status, RSND_MOD_DVC, i); 388 if (ret) 389 goto rsnd_dvc_probe_done; 390 391 i++; 392 } 393 394 rsnd_dvc_probe_done: 395 of_node_put(node); 396 397 return ret; 398 } 399 400 void rsnd_dvc_remove(struct rsnd_priv *priv) 401 { 402 struct rsnd_dvc *dvc; 403 int i; 404 405 for_each_rsnd_dvc(dvc, priv, i) { 406 rsnd_mod_quit(rsnd_mod_get(dvc)); 407 } 408 } 409