1 // SPDX-License-Identifier: GPL-2.0
5 // Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
8 #include <linux/gpio.h>
9 #include <linux/gpio/consumer.h>
10 #include <linux/module.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>
17 void asoc_simple_card_convert_fixup(struct asoc_simple_card_data
*data
,
18 struct snd_pcm_hw_params
*params
)
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
);
25 if (data
->convert_rate
)
27 rate
->max
= data
->convert_rate
;
29 if (data
->convert_channels
)
31 channels
->max
= data
->convert_channels
;
33 EXPORT_SYMBOL_GPL(asoc_simple_card_convert_fixup
);
35 void asoc_simple_card_parse_convert(struct device
*dev
, char *prefix
,
36 struct asoc_simple_card_data
*data
)
38 struct device_node
*np
= dev
->of_node
;
44 /* sampling rate convert */
45 snprintf(prop
, sizeof(prop
), "%s%s", prefix
, "convert-rate");
46 of_property_read_u32(np
, prop
, &data
->convert_rate
);
48 /* channels transfer */
49 snprintf(prop
, sizeof(prop
), "%s%s", prefix
, "convert-channels");
50 of_property_read_u32(np
, prop
, &data
->convert_channels
);
52 dev_dbg(dev
, "convert_rate %d\n", data
->convert_rate
);
53 dev_dbg(dev
, "convert_channels %d\n", data
->convert_channels
);
55 EXPORT_SYMBOL_GPL(asoc_simple_card_parse_convert
);
57 int asoc_simple_card_parse_daifmt(struct device
*dev
,
58 struct device_node
*node
,
59 struct device_node
*codec
,
63 struct device_node
*bitclkmaster
= NULL
;
64 struct device_node
*framemaster
= NULL
;
67 daifmt
= snd_soc_of_parse_daifmt(node
, prefix
,
68 &bitclkmaster
, &framemaster
);
69 daifmt
&= ~SND_SOC_DAIFMT_MASTER_MASK
;
71 if (!bitclkmaster
&& !framemaster
) {
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.
77 dev_dbg(dev
, "Revert to legacy daifmt parsing\n");
79 daifmt
= snd_soc_of_parse_daifmt(codec
, NULL
, NULL
, NULL
) |
80 (daifmt
& ~SND_SOC_DAIFMT_CLOCK_MASK
);
82 if (codec
== bitclkmaster
)
83 daifmt
|= (codec
== framemaster
) ?
84 SND_SOC_DAIFMT_CBM_CFM
: SND_SOC_DAIFMT_CBM_CFS
;
86 daifmt
|= (codec
== framemaster
) ?
87 SND_SOC_DAIFMT_CBS_CFM
: SND_SOC_DAIFMT_CBS_CFS
;
90 of_node_put(bitclkmaster
);
91 of_node_put(framemaster
);
95 dev_dbg(dev
, "format : %04x\n", daifmt
);
99 EXPORT_SYMBOL_GPL(asoc_simple_card_parse_daifmt
);
101 int asoc_simple_card_set_dailink_name(struct device
*dev
,
102 struct snd_soc_dai_link
*dai_link
,
103 const char *fmt
, ...)
110 name
= devm_kvasprintf(dev
, GFP_KERNEL
, fmt
, ap
);
116 dai_link
->name
= name
;
117 dai_link
->stream_name
= name
;
119 dev_dbg(dev
, "name : %s\n", name
);
124 EXPORT_SYMBOL_GPL(asoc_simple_card_set_dailink_name
);
126 int asoc_simple_card_parse_card_name(struct snd_soc_card
*card
,
134 /* Parse the card name from DT */
135 ret
= snd_soc_of_parse_card_name(card
, "label");
136 if (ret
< 0 || !card
->name
) {
139 snprintf(prop
, sizeof(prop
), "%sname", prefix
);
140 ret
= snd_soc_of_parse_card_name(card
, prop
);
145 if (!card
->name
&& card
->dai_link
)
146 card
->name
= card
->dai_link
->name
;
148 dev_dbg(card
->dev
, "Card Name: %s\n", card
->name
? card
->name
: "");
152 EXPORT_SYMBOL_GPL(asoc_simple_card_parse_card_name
);
154 static void asoc_simple_card_clk_register(struct asoc_simple_dai
*dai
,
160 int asoc_simple_card_clk_enable(struct asoc_simple_dai
*dai
)
162 return clk_prepare_enable(dai
->clk
);
164 EXPORT_SYMBOL_GPL(asoc_simple_card_clk_enable
);
166 void asoc_simple_card_clk_disable(struct asoc_simple_dai
*dai
)
168 clk_disable_unprepare(dai
->clk
);
170 EXPORT_SYMBOL_GPL(asoc_simple_card_clk_disable
);
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
,
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.
187 clk
= devm_get_clk_from_child(dev
, node
, NULL
);
189 simple_dai
->sysclk
= clk_get_rate(clk
);
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
;
195 clk
= devm_get_clk_from_child(dev
, dai_of_node
, NULL
);
197 simple_dai
->sysclk
= clk_get_rate(clk
);
200 if (of_property_read_bool(node
, "system-clock-direction-out"))
201 simple_dai
->clk_direction
= SND_SOC_CLOCK_OUT
;
203 dev_dbg(dev
, "%s : sysclk = %d, direction %d\n", name
,
204 simple_dai
->sysclk
, simple_dai
->clk_direction
);
208 EXPORT_SYMBOL_GPL(asoc_simple_card_parse_clk
);
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
,
217 struct of_phandle_args args
;
224 * Get node via "sound-dai = <&phandle port>"
225 * it will be used as xxx_of_node on soc_bind_dai_link()
227 ret
= of_parse_phandle_with_args(node
, list_name
, cells_name
, 0, &args
);
233 ret
= snd_soc_of_get_dai_name(node
, dai_name
);
238 *dai_of_node
= args
.np
;
241 *is_single_link
= !args
.args_count
;
245 EXPORT_SYMBOL_GPL(asoc_simple_card_parse_dai
);
247 static int asoc_simple_card_get_dai_id(struct device_node
*ep
)
249 struct device_node
*node
;
250 struct device_node
*endpoint
;
254 ret
= snd_soc_get_dai_id(ep
);
255 if (ret
!= -ENOTSUPP
)
258 node
= of_graph_get_port_parent(ep
);
261 * Non HDMI sound case, counting port/endpoint on its DT
262 * is enough. Let's count it.
266 for_each_endpoint_of_node(node
, endpoint
) {
280 int asoc_simple_card_parse_graph_dai(struct device_node
*ep
,
281 struct device_node
**dai_of_node
,
282 const char **dai_name
)
284 struct device_node
*node
;
285 struct of_phandle_args args
;
293 node
= of_graph_get_port_parent(ep
);
297 args
.args
[0] = asoc_simple_card_get_dai_id(ep
);
298 args
.args_count
= (of_graph_get_endpoint_count(node
) > 1);
300 ret
= snd_soc_get_dai_name(&args
, dai_name
);
308 EXPORT_SYMBOL_GPL(asoc_simple_card_parse_graph_dai
);
310 int asoc_simple_card_init_dai(struct snd_soc_dai
*dai
,
311 struct asoc_simple_dai
*simple_dai
)
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");
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
,
329 simple_dai
->slot_width
);
330 if (ret
&& ret
!= -ENOTSUPP
) {
331 dev_err(dai
->dev
, "simple-card: set_tdm_slot error\n");
338 EXPORT_SYMBOL_GPL(asoc_simple_card_init_dai
);
340 int asoc_simple_card_canonicalize_dailink(struct snd_soc_dai_link
*dai_link
)
342 /* Assumes platform == cpu */
343 if (!dai_link
->platform_of_node
)
344 dai_link
->platform_of_node
= dai_link
->cpu_of_node
;
348 EXPORT_SYMBOL_GPL(asoc_simple_card_canonicalize_dailink
);
350 void asoc_simple_card_canonicalize_cpu(struct snd_soc_dai_link
*dai_link
,
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
360 * fmt_multiple_name()
363 dai_link
->cpu_dai_name
= NULL
;
365 EXPORT_SYMBOL_GPL(asoc_simple_card_canonicalize_cpu
);
367 int asoc_simple_card_clean_reference(struct snd_soc_card
*card
)
369 struct snd_soc_dai_link
*dai_link
;
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
);
380 EXPORT_SYMBOL_GPL(asoc_simple_card_clean_reference
);
382 int asoc_simple_card_of_parse_routing(struct snd_soc_card
*card
,
386 struct device_node
*node
= card
->dev
->of_node
;
392 snprintf(prop
, sizeof(prop
), "%s%s", prefix
, "routing");
394 if (!of_property_read_bool(node
, prop
)) {
400 return snd_soc_of_parse_audio_routing(card
, prop
);
402 EXPORT_SYMBOL_GPL(asoc_simple_card_of_parse_routing
);
404 int asoc_simple_card_of_parse_widgets(struct snd_soc_card
*card
,
407 struct device_node
*node
= card
->dev
->of_node
;
413 snprintf(prop
, sizeof(prop
), "%s%s", prefix
, "widgets");
415 if (of_property_read_bool(node
, prop
))
416 return snd_soc_of_parse_audio_simple_widgets(card
, prop
);
418 /* no widgets is not error */
421 EXPORT_SYMBOL_GPL(asoc_simple_card_of_parse_widgets
);
423 int asoc_simple_card_init_jack(struct snd_soc_card
*card
,
424 struct asoc_simple_jack
*sjack
,
425 int is_hp
, char *prefix
)
427 struct device
*dev
= card
->dev
;
428 enum of_gpio_flags flags
;
438 sjack
->gpio
.gpio
= -ENOENT
;
441 snprintf(prop
, sizeof(prop
), "%shp-det-gpio", prefix
);
442 pin_name
= "Headphones";
443 gpio_name
= "Headphone detection";
444 mask
= SND_JACK_HEADPHONE
;
446 snprintf(prop
, sizeof(prop
), "%smic-det-gpio", prefix
);
447 pin_name
= "Mic Jack";
448 gpio_name
= "Mic detection";
449 mask
= SND_JACK_MICROPHONE
;
452 det
= of_get_named_gpio_flags(dev
->of_node
, prop
, 0, &flags
);
453 if (det
== -EPROBE_DEFER
)
454 return -EPROBE_DEFER
;
456 if (gpio_is_valid(det
)) {
457 sjack
->pin
.pin
= pin_name
;
458 sjack
->pin
.mask
= mask
;
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;
466 snd_soc_card_jack_new(card
, pin_name
, mask
,
470 snd_soc_jack_add_gpios(&sjack
->jack
, 1,
476 EXPORT_SYMBOL_GPL(asoc_simple_card_init_jack
);
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");