xref: /linux/sound/soc/generic/simple-card-utils.c (revision 10accd2e6890b57db8e717e9aee91b791f90fe14)
1 /*
2  * simple-card-core.c
3  *
4  * Copyright (c) 2016 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 #include <linux/of.h>
11 #include <sound/simple_card_utils.h>
12 
13 int asoc_simple_card_parse_daifmt(struct device *dev,
14 				  struct device_node *node,
15 				  struct device_node *codec,
16 				  char *prefix,
17 				  unsigned int *retfmt)
18 {
19 	struct device_node *bitclkmaster = NULL;
20 	struct device_node *framemaster = NULL;
21 	int prefix_len = prefix ? strlen(prefix) : 0;
22 	unsigned int daifmt;
23 
24 	daifmt = snd_soc_of_parse_daifmt(node, prefix,
25 					 &bitclkmaster, &framemaster);
26 	daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
27 
28 	if (prefix_len && !bitclkmaster && !framemaster) {
29 		/*
30 		 * No dai-link level and master setting was not found from
31 		 * sound node level, revert back to legacy DT parsing and
32 		 * take the settings from codec node.
33 		 */
34 		dev_dbg(dev, "Revert to legacy daifmt parsing\n");
35 
36 		daifmt = snd_soc_of_parse_daifmt(codec, NULL, NULL, NULL) |
37 			(daifmt & ~SND_SOC_DAIFMT_CLOCK_MASK);
38 	} else {
39 		if (codec == bitclkmaster)
40 			daifmt |= (codec == framemaster) ?
41 				SND_SOC_DAIFMT_CBM_CFM : SND_SOC_DAIFMT_CBM_CFS;
42 		else
43 			daifmt |= (codec == framemaster) ?
44 				SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS;
45 	}
46 
47 	of_node_put(bitclkmaster);
48 	of_node_put(framemaster);
49 
50 	*retfmt = daifmt;
51 
52 	return 0;
53 }
54 EXPORT_SYMBOL_GPL(asoc_simple_card_parse_daifmt);
55 
56 int asoc_simple_card_set_dailink_name(struct device *dev,
57 				      struct snd_soc_dai_link *dai_link,
58 				      const char *fmt, ...)
59 {
60 	va_list ap;
61 	char *name = NULL;
62 	int ret = -ENOMEM;
63 
64 	va_start(ap, fmt);
65 	name = devm_kvasprintf(dev, GFP_KERNEL, fmt, ap);
66 	va_end(ap);
67 
68 	if (name) {
69 		ret = 0;
70 
71 		dai_link->name		= name;
72 		dai_link->stream_name	= name;
73 	}
74 
75 	return ret;
76 }
77 EXPORT_SYMBOL_GPL(asoc_simple_card_set_dailink_name);
78 
79 int asoc_simple_card_parse_card_name(struct snd_soc_card *card,
80 				     char *prefix)
81 {
82 	char prop[128];
83 	int ret;
84 
85 	snprintf(prop, sizeof(prop), "%sname", prefix);
86 
87 	/* Parse the card name from DT */
88 	ret = snd_soc_of_parse_card_name(card, prop);
89 	if (ret < 0)
90 		return ret;
91 
92 	if (!card->name && card->dai_link)
93 		card->name = card->dai_link->name;
94 
95 	return 0;
96 }
97 EXPORT_SYMBOL_GPL(asoc_simple_card_parse_card_name);
98