GNU Linux-libre 4.19.268-gnu1
[releases.git] / sound / soc / generic / simple-card-utils.c
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 *name)
177 {
178         struct clk *clk;
179         u32 val;
180
181         /*
182          * Parse dai->sysclk come from "clocks = <&xxx>"
183          * (if system has common clock)
184          *  or "system-clock-frequency = <xxx>"
185          *  or device's module clock.
186          */
187         clk = devm_get_clk_from_child(dev, node, NULL);
188         if (!IS_ERR(clk)) {
189                 simple_dai->sysclk = clk_get_rate(clk);
190
191                 asoc_simple_card_clk_register(simple_dai, clk);
192         } else if (!of_property_read_u32(node, "system-clock-frequency", &val)) {
193                 simple_dai->sysclk = val;
194         } else {
195                 clk = devm_get_clk_from_child(dev, dai_of_node, NULL);
196                 if (!IS_ERR(clk))
197                         simple_dai->sysclk = clk_get_rate(clk);
198         }
199
200         if (of_property_read_bool(node, "system-clock-direction-out"))
201                 simple_dai->clk_direction = SND_SOC_CLOCK_OUT;
202
203         dev_dbg(dev, "%s : sysclk = %d, direction %d\n", name,
204                 simple_dai->sysclk, simple_dai->clk_direction);
205
206         return 0;
207 }
208 EXPORT_SYMBOL_GPL(asoc_simple_card_parse_clk);
209
210 int asoc_simple_card_parse_dai(struct device_node *node,
211                                     struct device_node **dai_of_node,
212                                     const char **dai_name,
213                                     const char *list_name,
214                                     const char *cells_name,
215                                     int *is_single_link)
216 {
217         struct of_phandle_args args;
218         int ret;
219
220         if (!node)
221                 return 0;
222
223         /*
224          * Get node via "sound-dai = <&phandle port>"
225          * it will be used as xxx_of_node on soc_bind_dai_link()
226          */
227         ret = of_parse_phandle_with_args(node, list_name, cells_name, 0, &args);
228         if (ret)
229                 return ret;
230
231         /* Get dai->name */
232         if (dai_name) {
233                 ret = snd_soc_of_get_dai_name(node, dai_name);
234                 if (ret < 0)
235                         return ret;
236         }
237
238         *dai_of_node = args.np;
239
240         if (is_single_link)
241                 *is_single_link = !args.args_count;
242
243         return 0;
244 }
245 EXPORT_SYMBOL_GPL(asoc_simple_card_parse_dai);
246
247 static int asoc_simple_card_get_dai_id(struct device_node *ep)
248 {
249         struct device_node *node;
250         struct device_node *endpoint;
251         int i, id;
252         int ret;
253
254         ret = snd_soc_get_dai_id(ep);
255         if (ret != -ENOTSUPP)
256                 return ret;
257
258         node = of_graph_get_port_parent(ep);
259
260         /*
261          * Non HDMI sound case, counting port/endpoint on its DT
262          * is enough. Let's count it.
263          */
264         i = 0;
265         id = -1;
266         for_each_endpoint_of_node(node, endpoint) {
267                 if (endpoint == ep)
268                         id = i;
269                 i++;
270         }
271
272         of_node_put(node);
273
274         if (id < 0)
275                 return -ENODEV;
276
277         return id;
278 }
279
280 int asoc_simple_card_parse_graph_dai(struct device_node *ep,
281                                      struct device_node **dai_of_node,
282                                      const char **dai_name)
283 {
284         struct device_node *node;
285         struct of_phandle_args args;
286         int ret;
287
288         if (!ep)
289                 return 0;
290         if (!dai_name)
291                 return 0;
292
293         node = of_graph_get_port_parent(ep);
294
295         /* Get dai->name */
296         args.np         = node;
297         args.args[0]    = asoc_simple_card_get_dai_id(ep);
298         args.args_count = (of_graph_get_endpoint_count(node) > 1);
299
300         ret = snd_soc_get_dai_name(&args, dai_name);
301         if (ret < 0)
302                 return ret;
303
304         *dai_of_node = node;
305
306         return 0;
307 }
308 EXPORT_SYMBOL_GPL(asoc_simple_card_parse_graph_dai);
309
310 int asoc_simple_card_init_dai(struct snd_soc_dai *dai,
311                               struct asoc_simple_dai *simple_dai)
312 {
313         int ret;
314
315         if (simple_dai->sysclk) {
316                 ret = snd_soc_dai_set_sysclk(dai, 0, simple_dai->sysclk,
317                                              simple_dai->clk_direction);
318                 if (ret && ret != -ENOTSUPP) {
319                         dev_err(dai->dev, "simple-card: set_sysclk error\n");
320                         return ret;
321                 }
322         }
323
324         if (simple_dai->slots) {
325                 ret = snd_soc_dai_set_tdm_slot(dai,
326                                                simple_dai->tx_slot_mask,
327                                                simple_dai->rx_slot_mask,
328                                                simple_dai->slots,
329                                                simple_dai->slot_width);
330                 if (ret && ret != -ENOTSUPP) {
331                         dev_err(dai->dev, "simple-card: set_tdm_slot error\n");
332                         return ret;
333                 }
334         }
335
336         return 0;
337 }
338 EXPORT_SYMBOL_GPL(asoc_simple_card_init_dai);
339
340 int asoc_simple_card_canonicalize_dailink(struct snd_soc_dai_link *dai_link)
341 {
342         /* Assumes platform == cpu */
343         if (!dai_link->platform_of_node)
344                 dai_link->platform_of_node = dai_link->cpu_of_node;
345
346         return 0;
347 }
348 EXPORT_SYMBOL_GPL(asoc_simple_card_canonicalize_dailink);
349
350 void asoc_simple_card_canonicalize_cpu(struct snd_soc_dai_link *dai_link,
351                                        int is_single_links)
352 {
353         /*
354          * In soc_bind_dai_link() will check cpu name after
355          * of_node matching if dai_link has cpu_dai_name.
356          * but, it will never match if name was created by
357          * fmt_single_name() remove cpu_dai_name if cpu_args
358          * was 0. See:
359          *      fmt_single_name()
360          *      fmt_multiple_name()
361          */
362         if (is_single_links)
363                 dai_link->cpu_dai_name = NULL;
364 }
365 EXPORT_SYMBOL_GPL(asoc_simple_card_canonicalize_cpu);
366
367 int asoc_simple_card_clean_reference(struct snd_soc_card *card)
368 {
369         struct snd_soc_dai_link *dai_link;
370         int num_links;
371
372         for (num_links = 0, dai_link = card->dai_link;
373              num_links < card->num_links;
374              num_links++, dai_link++) {
375                 of_node_put(dai_link->cpu_of_node);
376                 of_node_put(dai_link->codec_of_node);
377         }
378         return 0;
379 }
380 EXPORT_SYMBOL_GPL(asoc_simple_card_clean_reference);
381
382 int asoc_simple_card_of_parse_routing(struct snd_soc_card *card,
383                                       char *prefix,
384                                       int optional)
385 {
386         struct device_node *node = card->dev->of_node;
387         char prop[128];
388
389         if (!prefix)
390                 prefix = "";
391
392         snprintf(prop, sizeof(prop), "%s%s", prefix, "routing");
393
394         if (!of_property_read_bool(node, prop)) {
395                 if (optional)
396                         return 0;
397                 return -EINVAL;
398         }
399
400         return snd_soc_of_parse_audio_routing(card, prop);
401 }
402 EXPORT_SYMBOL_GPL(asoc_simple_card_of_parse_routing);
403
404 int asoc_simple_card_of_parse_widgets(struct snd_soc_card *card,
405                                       char *prefix)
406 {
407         struct device_node *node = card->dev->of_node;
408         char prop[128];
409
410         if (!prefix)
411                 prefix = "";
412
413         snprintf(prop, sizeof(prop), "%s%s", prefix, "widgets");
414
415         if (of_property_read_bool(node, prop))
416                 return snd_soc_of_parse_audio_simple_widgets(card, prop);
417
418         /* no widgets is not error */
419         return 0;
420 }
421 EXPORT_SYMBOL_GPL(asoc_simple_card_of_parse_widgets);
422
423 int asoc_simple_card_init_jack(struct snd_soc_card *card,
424                                struct asoc_simple_jack *sjack,
425                                int is_hp, char *prefix)
426 {
427         struct device *dev = card->dev;
428         enum of_gpio_flags flags;
429         char prop[128];
430         char *pin_name;
431         char *gpio_name;
432         int mask;
433         int det;
434
435         if (!prefix)
436                 prefix = "";
437
438         sjack->gpio.gpio = -ENOENT;
439
440         if (is_hp) {
441                 snprintf(prop, sizeof(prop), "%shp-det-gpio", prefix);
442                 pin_name        = "Headphones";
443                 gpio_name       = "Headphone detection";
444                 mask            = SND_JACK_HEADPHONE;
445         } else {
446                 snprintf(prop, sizeof(prop), "%smic-det-gpio", prefix);
447                 pin_name        = "Mic Jack";
448                 gpio_name       = "Mic detection";
449                 mask            = SND_JACK_MICROPHONE;
450         }
451
452         det = of_get_named_gpio_flags(dev->of_node, prop, 0, &flags);
453         if (det == -EPROBE_DEFER)
454                 return -EPROBE_DEFER;
455
456         if (gpio_is_valid(det)) {
457                 sjack->pin.pin          = pin_name;
458                 sjack->pin.mask         = mask;
459
460                 sjack->gpio.name        = gpio_name;
461                 sjack->gpio.report      = mask;
462                 sjack->gpio.gpio        = det;
463                 sjack->gpio.invert      = !!(flags & OF_GPIO_ACTIVE_LOW);
464                 sjack->gpio.debounce_time = 150;
465
466                 snd_soc_card_jack_new(card, pin_name, mask,
467                                       &sjack->jack,
468                                       &sjack->pin, 1);
469
470                 snd_soc_jack_add_gpios(&sjack->jack, 1,
471                                        &sjack->gpio);
472         }
473
474         return 0;
475 }
476 EXPORT_SYMBOL_GPL(asoc_simple_card_init_jack);
477
478 /* Module information */
479 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
480 MODULE_DESCRIPTION("ALSA SoC Simple Card Utils");
481 MODULE_LICENSE("GPL v2");