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 #include "rsnd.h" 12 13 #define RSND_DVC_NAME_SIZE 16 14 #define RSND_DVC_VOLUME_MAX 100 15 #define RSND_DVC_VOLUME_NUM 2 16 17 #define DVC_NAME "dvc" 18 19 struct rsnd_dvc { 20 struct rsnd_dvc_platform_info *info; /* rcar_snd.h */ 21 struct rsnd_mod mod; 22 struct clk *clk; 23 long volume[RSND_DVC_VOLUME_NUM]; 24 }; 25 26 #define rsnd_mod_to_dvc(_mod) \ 27 container_of((_mod), struct rsnd_dvc, mod) 28 29 #define for_each_rsnd_dvc(pos, priv, i) \ 30 for ((i) = 0; \ 31 ((i) < rsnd_dvc_nr(priv)) && \ 32 ((pos) = (struct rsnd_dvc *)(priv)->dvc + i); \ 33 i++) 34 35 static void rsnd_dvc_volume_update(struct rsnd_mod *mod) 36 { 37 struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); 38 u32 max = (0x00800000 - 1); 39 u32 vol[RSND_DVC_VOLUME_NUM]; 40 int i; 41 42 for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) 43 vol[i] = max / RSND_DVC_VOLUME_MAX * dvc->volume[i]; 44 45 rsnd_mod_write(mod, DVC_VOL0R, vol[0]); 46 rsnd_mod_write(mod, DVC_VOL1R, vol[1]); 47 } 48 49 static int rsnd_dvc_probe_gen2(struct rsnd_mod *mod, 50 struct rsnd_dai *rdai) 51 { 52 struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 53 struct device *dev = rsnd_priv_to_dev(priv); 54 55 dev_dbg(dev, "%s (Gen2) is probed\n", rsnd_mod_name(mod)); 56 57 return 0; 58 } 59 60 static int rsnd_dvc_init(struct rsnd_mod *dvc_mod, 61 struct rsnd_dai *rdai) 62 { 63 struct rsnd_dvc *dvc = rsnd_mod_to_dvc(dvc_mod); 64 struct rsnd_dai_stream *io = rsnd_mod_to_io(dvc_mod); 65 struct rsnd_priv *priv = rsnd_mod_to_priv(dvc_mod); 66 struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); 67 struct device *dev = rsnd_priv_to_dev(priv); 68 int dvc_id = rsnd_mod_id(dvc_mod); 69 int src_id = rsnd_mod_id(src_mod); 70 u32 route[] = { 71 [0] = 0x30000, 72 [1] = 0x30001, 73 [2] = 0x40000, 74 [3] = 0x10000, 75 [4] = 0x20000, 76 [5] = 0x40100 77 }; 78 79 if (src_id >= ARRAY_SIZE(route)) { 80 dev_err(dev, "DVC%d isn't connected to SRC%d\n", dvc_id, src_id); 81 return -EINVAL; 82 } 83 84 clk_prepare_enable(dvc->clk); 85 86 /* 87 * fixme 88 * it doesn't support CTU/MIX 89 */ 90 rsnd_mod_write(dvc_mod, CMD_ROUTE_SLCT, route[src_id]); 91 92 rsnd_mod_write(dvc_mod, DVC_SWRSR, 0); 93 rsnd_mod_write(dvc_mod, DVC_SWRSR, 1); 94 95 rsnd_mod_write(dvc_mod, DVC_DVUIR, 1); 96 97 rsnd_mod_write(dvc_mod, DVC_ADINR, rsnd_get_adinr(dvc_mod)); 98 99 /* enable Volume */ 100 rsnd_mod_write(dvc_mod, DVC_DVUCR, 0x100); 101 102 /* ch0/ch1 Volume */ 103 rsnd_dvc_volume_update(dvc_mod); 104 105 rsnd_mod_write(dvc_mod, DVC_DVUIR, 0); 106 107 rsnd_mod_write(dvc_mod, DVC_DVUER, 1); 108 109 rsnd_adg_set_cmd_timsel_gen2(rdai, dvc_mod, io); 110 111 return 0; 112 } 113 114 static int rsnd_dvc_quit(struct rsnd_mod *mod, 115 struct rsnd_dai *rdai) 116 { 117 struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); 118 119 clk_disable_unprepare(dvc->clk); 120 121 return 0; 122 } 123 124 static int rsnd_dvc_start(struct rsnd_mod *mod, 125 struct rsnd_dai *rdai) 126 { 127 rsnd_mod_write(mod, CMD_CTRL, 0x10); 128 129 return 0; 130 } 131 132 static int rsnd_dvc_stop(struct rsnd_mod *mod, 133 struct rsnd_dai *rdai) 134 { 135 rsnd_mod_write(mod, CMD_CTRL, 0); 136 137 return 0; 138 } 139 140 static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl, 141 struct snd_ctl_elem_info *uinfo) 142 { 143 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 144 uinfo->count = RSND_DVC_VOLUME_NUM; 145 uinfo->value.integer.min = 0; 146 uinfo->value.integer.max = RSND_DVC_VOLUME_MAX; 147 148 return 0; 149 } 150 151 static int rsnd_dvc_volume_get(struct snd_kcontrol *kctrl, 152 struct snd_ctl_elem_value *ucontrol) 153 { 154 struct rsnd_mod *mod = snd_kcontrol_chip(kctrl); 155 struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); 156 int i; 157 158 for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) 159 ucontrol->value.integer.value[i] = dvc->volume[i]; 160 161 return 0; 162 } 163 164 static int rsnd_dvc_volume_put(struct snd_kcontrol *kctrl, 165 struct snd_ctl_elem_value *ucontrol) 166 { 167 struct rsnd_mod *mod = snd_kcontrol_chip(kctrl); 168 struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); 169 int i, change = 0; 170 171 for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) { 172 if (ucontrol->value.integer.value[i] < 0 || 173 ucontrol->value.integer.value[i] > RSND_DVC_VOLUME_MAX) 174 return -EINVAL; 175 176 change |= (ucontrol->value.integer.value[i] != dvc->volume[i]); 177 } 178 179 if (change) { 180 for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) 181 dvc->volume[i] = ucontrol->value.integer.value[i]; 182 183 rsnd_dvc_volume_update(mod); 184 } 185 186 return change; 187 } 188 189 static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, 190 struct rsnd_dai *rdai, 191 struct snd_soc_pcm_runtime *rtd) 192 { 193 struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); 194 struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 195 struct device *dev = rsnd_priv_to_dev(priv); 196 struct snd_card *card = rtd->card->snd_card; 197 struct snd_kcontrol *kctrl; 198 static struct snd_kcontrol_new knew = { 199 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 200 .name = "Playback Volume", 201 .info = rsnd_dvc_volume_info, 202 .get = rsnd_dvc_volume_get, 203 .put = rsnd_dvc_volume_put, 204 }; 205 int ret; 206 207 if (!rsnd_dai_is_play(rdai, io)) { 208 dev_err(dev, "DVC%d is connected to Capture DAI\n", 209 rsnd_mod_id(mod)); 210 return -EINVAL; 211 } 212 213 kctrl = snd_ctl_new1(&knew, mod); 214 if (!kctrl) 215 return -ENOMEM; 216 217 ret = snd_ctl_add(card, kctrl); 218 if (ret < 0) 219 return ret; 220 221 return 0; 222 } 223 224 static struct rsnd_mod_ops rsnd_dvc_ops = { 225 .name = DVC_NAME, 226 .probe = rsnd_dvc_probe_gen2, 227 .init = rsnd_dvc_init, 228 .quit = rsnd_dvc_quit, 229 .start = rsnd_dvc_start, 230 .stop = rsnd_dvc_stop, 231 .pcm_new = rsnd_dvc_pcm_new, 232 }; 233 234 struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id) 235 { 236 if (WARN_ON(id < 0 || id >= rsnd_dvc_nr(priv))) 237 id = 0; 238 239 return &((struct rsnd_dvc *)(priv->dvc) + id)->mod; 240 } 241 242 int rsnd_dvc_probe(struct platform_device *pdev, 243 const struct rsnd_of_data *of_data, 244 struct rsnd_priv *priv) 245 { 246 struct rcar_snd_info *info = rsnd_priv_to_info(priv); 247 struct device *dev = rsnd_priv_to_dev(priv); 248 struct rsnd_dvc *dvc; 249 struct clk *clk; 250 char name[RSND_DVC_NAME_SIZE]; 251 int i, nr; 252 253 nr = info->dvc_info_nr; 254 if (!nr) 255 return 0; 256 257 /* This driver doesn't support Gen1 at this point */ 258 if (rsnd_is_gen1(priv)) { 259 dev_warn(dev, "CMD is not supported on Gen1\n"); 260 return -EINVAL; 261 } 262 263 dvc = devm_kzalloc(dev, sizeof(*dvc) * nr, GFP_KERNEL); 264 if (!dvc) { 265 dev_err(dev, "CMD allocate failed\n"); 266 return -ENOMEM; 267 } 268 269 priv->dvc_nr = nr; 270 priv->dvc = dvc; 271 272 for_each_rsnd_dvc(dvc, priv, i) { 273 snprintf(name, RSND_DVC_NAME_SIZE, "%s.%d", 274 DVC_NAME, i); 275 276 clk = devm_clk_get(dev, name); 277 if (IS_ERR(clk)) 278 return PTR_ERR(clk); 279 280 dvc->info = &info->dvc_info[i]; 281 dvc->clk = clk; 282 283 rsnd_mod_init(priv, &dvc->mod, &rsnd_dvc_ops, RSND_MOD_DVC, i); 284 285 dev_dbg(dev, "CMD%d probed\n", i); 286 } 287 288 return 0; 289 } 290