libnvdimm, namespace: allow creation of multiple pmem-namespaces per region
[cascardo/linux.git] / sound / soc / generic / simple-card-utils.c
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);