1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // simple-card-utils.c 4 // 5 // Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 6 7 #include <linux/clk.h> 8 #include <linux/gpio.h> 9 #include <linux/gpio/consumer.h> 10 #include <linux/module.h> 11 #include <linux/of.h> 12 #include <linux/of_gpio.h> 13 #include <linux/of_graph.h> 14 #include <sound/jack.h> 15 #include <sound/simple_card_utils.h> 16 17 void asoc_simple_card_convert_fixup(struct asoc_simple_card_data *data, 18 struct snd_pcm_hw_params *params) 19 { 20 struct snd_interval *rate = hw_param_interval(params, 21 SNDRV_PCM_HW_PARAM_RATE); 22 struct snd_interval *channels = hw_param_interval(params, 23 SNDRV_PCM_HW_PARAM_CHANNELS); 24 25 if (data->convert_rate) 26 rate->min = 27 rate->max = data->convert_rate; 28 29 if (data->convert_channels) 30 channels->min = 31 channels->max = data->convert_channels; 32 } 33 EXPORT_SYMBOL_GPL(asoc_simple_card_convert_fixup); 34 35 void asoc_simple_card_parse_convert(struct device *dev, char *prefix, 36 struct asoc_simple_card_data *data) 37 { 38 struct device_node *np = dev->of_node; 39 char prop[128]; 40 41 if (!prefix) 42 prefix = ""; 43 44 /* sampling rate convert */ 45 snprintf(prop, sizeof(prop), "%s%s", prefix, "convert-rate"); 46 of_property_read_u32(np, prop, &data->convert_rate); 47 48 /* channels transfer */ 49 snprintf(prop, sizeof(prop), "%s%s", prefix, "convert-channels"); 50 of_property_read_u32(np, prop, &data->convert_channels); 51 52 dev_dbg(dev, "convert_rate %d\n", data->convert_rate); 53 dev_dbg(dev, "convert_channels %d\n", data->convert_channels); 54 } 55 EXPORT_SYMBOL_GPL(asoc_simple_card_parse_convert); 56 57 int asoc_simple_card_parse_daifmt(struct device *dev, 58 struct device_node *node, 59 struct device_node *codec, 60 char *prefix, 61 unsigned int *retfmt) 62 { 63 struct device_node *bitclkmaster = NULL; 64 struct device_node *framemaster = NULL; 65 unsigned int daifmt; 66 67 daifmt = snd_soc_of_parse_daifmt(node, prefix, 68 &bitclkmaster, &framemaster); 69 daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK; 70 71 if (!bitclkmaster && !framemaster) { 72 /* 73 * No dai-link level and master setting was not found from 74 * sound node level, revert back to legacy DT parsing and 75 * take the settings from codec node. 76 */ 77 dev_dbg(dev, "Revert to legacy daifmt parsing\n"); 78 79 daifmt = snd_soc_of_parse_daifmt(codec, NULL, NULL, NULL) | 80 (daifmt & ~SND_SOC_DAIFMT_CLOCK_MASK); 81 } else { 82 if (codec == bitclkmaster) 83 daifmt |= (codec == framemaster) ? 84 SND_SOC_DAIFMT_CBM_CFM : SND_SOC_DAIFMT_CBM_CFS; 85 else 86 daifmt |= (codec == framemaster) ? 87 SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS; 88 } 89 90 of_node_put(bitclkmaster); 91 of_node_put(framemaster); 92 93 *retfmt = daifmt; 94 95 dev_dbg(dev, "format : %04x\n", daifmt); 96 97 return 0; 98 } 99 EXPORT_SYMBOL_GPL(asoc_simple_card_parse_daifmt); 100 101 int asoc_simple_card_set_dailink_name(struct device *dev, 102 struct snd_soc_dai_link *dai_link, 103 const char *fmt, ...) 104 { 105 va_list ap; 106 char *name = NULL; 107 int ret = -ENOMEM; 108 109 va_start(ap, fmt); 110 name = devm_kvasprintf(dev, GFP_KERNEL, fmt, ap); 111 va_end(ap); 112 113 if (name) { 114 ret = 0; 115 116 dai_link->name = name; 117 dai_link->stream_name = name; 118 119 dev_dbg(dev, "name : %s\n", name); 120 } 121 122 return ret; 123 } 124 EXPORT_SYMBOL_GPL(asoc_simple_card_set_dailink_name); 125 126 int asoc_simple_card_parse_card_name(struct snd_soc_card *card, 127 char *prefix) 128 { 129 int ret; 130 131 if (!prefix) 132 prefix = ""; 133 134 /* Parse the card name from DT */ 135 ret = snd_soc_of_parse_card_name(card, "label"); 136 if (ret < 0 || !card->name) { 137 char prop[128]; 138 139 snprintf(prop, sizeof(prop), "%sname", prefix); 140 ret = snd_soc_of_parse_card_name(card, prop); 141 if (ret < 0) 142 return ret; 143 } 144 145 if (!card->name && card->dai_link) 146 card->name = card->dai_link->name; 147 148 dev_dbg(card->dev, "Card Name: %s\n", card->name ? card->name : ""); 149 150 return 0; 151 } 152 EXPORT_SYMBOL_GPL(asoc_simple_card_parse_card_name); 153 154 static void asoc_simple_card_clk_register(struct asoc_simple_dai *dai, 155 struct clk *clk) 156 { 157 dai->clk = clk; 158 } 159 160 int asoc_simple_card_clk_enable(struct asoc_simple_dai *dai) 161 { 162 return clk_prepare_enable(dai->clk); 163 } 164 EXPORT_SYMBOL_GPL(asoc_simple_card_clk_enable); 165 166 void asoc_simple_card_clk_disable(struct asoc_simple_dai *dai) 167 { 168 clk_disable_unprepare(dai->clk); 169 } 170 EXPORT_SYMBOL_GPL(asoc_simple_card_clk_disable); 171 172 int asoc_simple_card_parse_clk(struct device *dev, 173 struct device_node *node, 174 struct device_node *dai_of_node, 175 struct asoc_simple_dai *simple_dai, 176 const char *dai_name, 177 struct snd_soc_dai_link_component *dlc) 178 { 179 struct clk *clk; 180 u32 val; 181 182 /* 183 * Use snd_soc_dai_link_component instead of legacy style. 184 * It is only for codec, but cpu will be supported in the future. 185 * see 186 * soc-core.c :: snd_soc_init_multicodec() 187 */ 188 if (dlc) { 189 dai_of_node = dlc->of_node; 190 dai_name = dlc->dai_name; 191 } 192 193 /* 194 * Parse dai->sysclk come from "clocks = <&xxx>" 195 * (if system has common clock) 196 * or "system-clock-frequency = <xxx>" 197 * or device's module clock. 198 */ 199 clk = devm_get_clk_from_child(dev, node, NULL); 200 if (!IS_ERR(clk)) { 201 simple_dai->sysclk = clk_get_rate(clk); 202 203 asoc_simple_card_clk_register(simple_dai, clk); 204 } else if (!of_property_read_u32(node, "system-clock-frequency", &val)) { 205 simple_dai->sysclk = val; 206 } else { 207 clk = devm_get_clk_from_child(dev, dai_of_node, NULL); 208 if (!IS_ERR(clk)) 209 simple_dai->sysclk = clk_get_rate(clk); 210 } 211 212 if (of_property_read_bool(node, "system-clock-direction-out")) 213 simple_dai->clk_direction = SND_SOC_CLOCK_OUT; 214 215 dev_dbg(dev, "%s : sysclk = %d, direction %d\n", dai_name, 216 simple_dai->sysclk, simple_dai->clk_direction); 217 218 return 0; 219 } 220 EXPORT_SYMBOL_GPL(asoc_simple_card_parse_clk); 221 222 int asoc_simple_card_parse_dai(struct device_node *node, 223 struct snd_soc_dai_link_component *dlc, 224 struct device_node **dai_of_node, 225 const char **dai_name, 226 const char *list_name, 227 const char *cells_name, 228 int *is_single_link) 229 { 230 struct of_phandle_args args; 231 int ret; 232 233 if (!node) 234 return 0; 235 236 /* 237 * Use snd_soc_dai_link_component instead of legacy style. 238 * It is only for codec, but cpu will be supported in the future. 239 * see 240 * soc-core.c :: snd_soc_init_multicodec() 241 */ 242 if (dlc) { 243 dai_name = &dlc->dai_name; 244 dai_of_node = &dlc->of_node; 245 } 246 247 /* 248 * Get node via "sound-dai = <&phandle port>" 249 * it will be used as xxx_of_node on soc_bind_dai_link() 250 */ 251 ret = of_parse_phandle_with_args(node, list_name, cells_name, 0, &args); 252 if (ret) 253 return ret; 254 255 /* Get dai->name */ 256 if (dai_name) { 257 ret = snd_soc_of_get_dai_name(node, dai_name); 258 if (ret < 0) 259 return ret; 260 } 261 262 *dai_of_node = args.np; 263 264 if (is_single_link) 265 *is_single_link = !args.args_count; 266 267 return 0; 268 } 269 EXPORT_SYMBOL_GPL(asoc_simple_card_parse_dai); 270 271 static int asoc_simple_card_get_dai_id(struct device_node *ep) 272 { 273 struct device_node *node; 274 struct device_node *endpoint; 275 int i, id; 276 int ret; 277 278 ret = snd_soc_get_dai_id(ep); 279 if (ret != -ENOTSUPP) 280 return ret; 281 282 node = of_graph_get_port_parent(ep); 283 284 /* 285 * Non HDMI sound case, counting port/endpoint on its DT 286 * is enough. Let's count it. 287 */ 288 i = 0; 289 id = -1; 290 for_each_endpoint_of_node(node, endpoint) { 291 if (endpoint == ep) 292 id = i; 293 i++; 294 } 295 296 of_node_put(node); 297 298 if (id < 0) 299 return -ENODEV; 300 301 return id; 302 } 303 304 int asoc_simple_card_parse_graph_dai(struct device_node *ep, 305 struct snd_soc_dai_link_component *dlc, 306 struct device_node **dai_of_node, 307 const char **dai_name) 308 { 309 struct device_node *node; 310 struct of_phandle_args args; 311 int ret; 312 313 /* 314 * Use snd_soc_dai_link_component instead of legacy style. 315 * It is only for codec, but cpu will be supported in the future. 316 * see 317 * soc-core.c :: snd_soc_init_multicodec() 318 */ 319 if (dlc) { 320 dai_name = &dlc->dai_name; 321 dai_of_node = &dlc->of_node; 322 } 323 324 if (!ep) 325 return 0; 326 if (!dai_name) 327 return 0; 328 329 node = of_graph_get_port_parent(ep); 330 331 /* Get dai->name */ 332 args.np = node; 333 args.args[0] = asoc_simple_card_get_dai_id(ep); 334 args.args_count = (of_graph_get_endpoint_count(node) > 1); 335 336 ret = snd_soc_get_dai_name(&args, dai_name); 337 if (ret < 0) 338 return ret; 339 340 *dai_of_node = node; 341 342 return 0; 343 } 344 EXPORT_SYMBOL_GPL(asoc_simple_card_parse_graph_dai); 345 346 int asoc_simple_card_init_dai(struct snd_soc_dai *dai, 347 struct asoc_simple_dai *simple_dai) 348 { 349 int ret; 350 351 if (simple_dai->sysclk) { 352 ret = snd_soc_dai_set_sysclk(dai, 0, simple_dai->sysclk, 353 simple_dai->clk_direction); 354 if (ret && ret != -ENOTSUPP) { 355 dev_err(dai->dev, "simple-card: set_sysclk error\n"); 356 return ret; 357 } 358 } 359 360 if (simple_dai->slots) { 361 ret = snd_soc_dai_set_tdm_slot(dai, 362 simple_dai->tx_slot_mask, 363 simple_dai->rx_slot_mask, 364 simple_dai->slots, 365 simple_dai->slot_width); 366 if (ret && ret != -ENOTSUPP) { 367 dev_err(dai->dev, "simple-card: set_tdm_slot error\n"); 368 return ret; 369 } 370 } 371 372 return 0; 373 } 374 EXPORT_SYMBOL_GPL(asoc_simple_card_init_dai); 375 376 int asoc_simple_card_canonicalize_dailink(struct snd_soc_dai_link *dai_link) 377 { 378 /* Assumes platform == cpu */ 379 if (!dai_link->platform->of_node) 380 dai_link->platform->of_node = dai_link->cpu_of_node; 381 382 return 0; 383 384 } 385 EXPORT_SYMBOL_GPL(asoc_simple_card_canonicalize_dailink); 386 387 void asoc_simple_card_canonicalize_cpu(struct snd_soc_dai_link *dai_link, 388 int is_single_links) 389 { 390 /* 391 * In soc_bind_dai_link() will check cpu name after 392 * of_node matching if dai_link has cpu_dai_name. 393 * but, it will never match if name was created by 394 * fmt_single_name() remove cpu_dai_name if cpu_args 395 * was 0. See: 396 * fmt_single_name() 397 * fmt_multiple_name() 398 */ 399 if (is_single_links) 400 dai_link->cpu_dai_name = NULL; 401 } 402 EXPORT_SYMBOL_GPL(asoc_simple_card_canonicalize_cpu); 403 404 int asoc_simple_card_clean_reference(struct snd_soc_card *card) 405 { 406 struct snd_soc_dai_link *dai_link; 407 int i; 408 409 for_each_card_prelinks(card, i, dai_link) { 410 of_node_put(dai_link->cpu_of_node); 411 of_node_put(dai_link->codecs->of_node); 412 } 413 return 0; 414 } 415 EXPORT_SYMBOL_GPL(asoc_simple_card_clean_reference); 416 417 int asoc_simple_card_of_parse_routing(struct snd_soc_card *card, 418 char *prefix, 419 int optional) 420 { 421 struct device_node *node = card->dev->of_node; 422 char prop[128]; 423 424 if (!prefix) 425 prefix = ""; 426 427 snprintf(prop, sizeof(prop), "%s%s", prefix, "routing"); 428 429 if (!of_property_read_bool(node, prop)) { 430 if (optional) 431 return 0; 432 return -EINVAL; 433 } 434 435 return snd_soc_of_parse_audio_routing(card, prop); 436 } 437 EXPORT_SYMBOL_GPL(asoc_simple_card_of_parse_routing); 438 439 int asoc_simple_card_of_parse_widgets(struct snd_soc_card *card, 440 char *prefix) 441 { 442 struct device_node *node = card->dev->of_node; 443 char prop[128]; 444 445 if (!prefix) 446 prefix = ""; 447 448 snprintf(prop, sizeof(prop), "%s%s", prefix, "widgets"); 449 450 if (of_property_read_bool(node, prop)) 451 return snd_soc_of_parse_audio_simple_widgets(card, prop); 452 453 /* no widgets is not error */ 454 return 0; 455 } 456 EXPORT_SYMBOL_GPL(asoc_simple_card_of_parse_widgets); 457 458 int asoc_simple_card_init_jack(struct snd_soc_card *card, 459 struct asoc_simple_jack *sjack, 460 int is_hp, char *prefix) 461 { 462 struct device *dev = card->dev; 463 enum of_gpio_flags flags; 464 char prop[128]; 465 char *pin_name; 466 char *gpio_name; 467 int mask; 468 int det; 469 470 if (!prefix) 471 prefix = ""; 472 473 sjack->gpio.gpio = -ENOENT; 474 475 if (is_hp) { 476 snprintf(prop, sizeof(prop), "%shp-det-gpio", prefix); 477 pin_name = "Headphones"; 478 gpio_name = "Headphone detection"; 479 mask = SND_JACK_HEADPHONE; 480 } else { 481 snprintf(prop, sizeof(prop), "%smic-det-gpio", prefix); 482 pin_name = "Mic Jack"; 483 gpio_name = "Mic detection"; 484 mask = SND_JACK_MICROPHONE; 485 } 486 487 det = of_get_named_gpio_flags(dev->of_node, prop, 0, &flags); 488 if (det == -EPROBE_DEFER) 489 return -EPROBE_DEFER; 490 491 if (gpio_is_valid(det)) { 492 sjack->pin.pin = pin_name; 493 sjack->pin.mask = mask; 494 495 sjack->gpio.name = gpio_name; 496 sjack->gpio.report = mask; 497 sjack->gpio.gpio = det; 498 sjack->gpio.invert = !!(flags & OF_GPIO_ACTIVE_LOW); 499 sjack->gpio.debounce_time = 150; 500 501 snd_soc_card_jack_new(card, pin_name, mask, 502 &sjack->jack, 503 &sjack->pin, 1); 504 505 snd_soc_jack_add_gpios(&sjack->jack, 1, 506 &sjack->gpio); 507 } 508 509 return 0; 510 } 511 EXPORT_SYMBOL_GPL(asoc_simple_card_init_jack); 512 513 /* Module information */ 514 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); 515 MODULE_DESCRIPTION("ALSA SoC Simple Card Utils"); 516 MODULE_LICENSE("GPL v2"); 517