diff options
Diffstat (limited to 'sound/soc/generic/simple-card.c')
-rw-r--r-- | sound/soc/generic/simple-card.c | 229 |
1 files changed, 158 insertions, 71 deletions
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index cef7776b712c..d1b7293c133e 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c | |||
@@ -10,10 +10,13 @@ | |||
10 | */ | 10 | */ |
11 | #include <linux/clk.h> | 11 | #include <linux/clk.h> |
12 | #include <linux/device.h> | 12 | #include <linux/device.h> |
13 | #include <linux/gpio.h> | ||
13 | #include <linux/module.h> | 14 | #include <linux/module.h> |
14 | #include <linux/of.h> | 15 | #include <linux/of.h> |
16 | #include <linux/of_gpio.h> | ||
15 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
16 | #include <linux/string.h> | 18 | #include <linux/string.h> |
19 | #include <sound/jack.h> | ||
17 | #include <sound/simple_card.h> | 20 | #include <sound/simple_card.h> |
18 | #include <sound/soc-dai.h> | 21 | #include <sound/soc-dai.h> |
19 | #include <sound/soc.h> | 22 | #include <sound/soc.h> |
@@ -25,9 +28,15 @@ struct simple_card_data { | |||
25 | struct asoc_simple_dai codec_dai; | 28 | struct asoc_simple_dai codec_dai; |
26 | } *dai_props; | 29 | } *dai_props; |
27 | unsigned int mclk_fs; | 30 | unsigned int mclk_fs; |
31 | int gpio_hp_det; | ||
32 | int gpio_mic_det; | ||
28 | struct snd_soc_dai_link dai_link[]; /* dynamically allocated */ | 33 | struct snd_soc_dai_link dai_link[]; /* dynamically allocated */ |
29 | }; | 34 | }; |
30 | 35 | ||
36 | #define simple_priv_to_dev(priv) ((priv)->snd_card.dev) | ||
37 | #define simple_priv_to_link(priv, i) ((priv)->snd_card.dai_link + i) | ||
38 | #define simple_priv_to_props(priv, i) ((priv)->dai_props + i) | ||
39 | |||
31 | static int asoc_simple_card_hw_params(struct snd_pcm_substream *substream, | 40 | static int asoc_simple_card_hw_params(struct snd_pcm_substream *substream, |
32 | struct snd_pcm_hw_params *params) | 41 | struct snd_pcm_hw_params *params) |
33 | { | 42 | { |
@@ -50,6 +59,32 @@ static struct snd_soc_ops asoc_simple_card_ops = { | |||
50 | .hw_params = asoc_simple_card_hw_params, | 59 | .hw_params = asoc_simple_card_hw_params, |
51 | }; | 60 | }; |
52 | 61 | ||
62 | static struct snd_soc_jack simple_card_hp_jack; | ||
63 | static struct snd_soc_jack_pin simple_card_hp_jack_pins[] = { | ||
64 | { | ||
65 | .pin = "Headphones", | ||
66 | .mask = SND_JACK_HEADPHONE, | ||
67 | }, | ||
68 | }; | ||
69 | static struct snd_soc_jack_gpio simple_card_hp_jack_gpio = { | ||
70 | .name = "Headphone detection", | ||
71 | .report = SND_JACK_HEADPHONE, | ||
72 | .debounce_time = 150, | ||
73 | }; | ||
74 | |||
75 | static struct snd_soc_jack simple_card_mic_jack; | ||
76 | static struct snd_soc_jack_pin simple_card_mic_jack_pins[] = { | ||
77 | { | ||
78 | .pin = "Mic Jack", | ||
79 | .mask = SND_JACK_MICROPHONE, | ||
80 | }, | ||
81 | }; | ||
82 | static struct snd_soc_jack_gpio simple_card_mic_jack_gpio = { | ||
83 | .name = "Mic detection", | ||
84 | .report = SND_JACK_MICROPHONE, | ||
85 | .debounce_time = 150, | ||
86 | }; | ||
87 | |||
53 | static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, | 88 | static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, |
54 | struct asoc_simple_dai *set) | 89 | struct asoc_simple_dai *set) |
55 | { | 90 | { |
@@ -105,42 +140,70 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) | |||
105 | if (ret < 0) | 140 | if (ret < 0) |
106 | return ret; | 141 | return ret; |
107 | 142 | ||
143 | if (gpio_is_valid(priv->gpio_hp_det)) { | ||
144 | snd_soc_jack_new(codec->codec, "Headphones", SND_JACK_HEADPHONE, | ||
145 | &simple_card_hp_jack); | ||
146 | snd_soc_jack_add_pins(&simple_card_hp_jack, | ||
147 | ARRAY_SIZE(simple_card_hp_jack_pins), | ||
148 | simple_card_hp_jack_pins); | ||
149 | |||
150 | simple_card_hp_jack_gpio.gpio = priv->gpio_hp_det; | ||
151 | snd_soc_jack_add_gpios(&simple_card_hp_jack, 1, | ||
152 | &simple_card_hp_jack_gpio); | ||
153 | } | ||
154 | |||
155 | if (gpio_is_valid(priv->gpio_mic_det)) { | ||
156 | snd_soc_jack_new(codec->codec, "Mic Jack", SND_JACK_MICROPHONE, | ||
157 | &simple_card_mic_jack); | ||
158 | snd_soc_jack_add_pins(&simple_card_mic_jack, | ||
159 | ARRAY_SIZE(simple_card_mic_jack_pins), | ||
160 | simple_card_mic_jack_pins); | ||
161 | simple_card_mic_jack_gpio.gpio = priv->gpio_mic_det; | ||
162 | snd_soc_jack_add_gpios(&simple_card_mic_jack, 1, | ||
163 | &simple_card_mic_jack_gpio); | ||
164 | } | ||
108 | return 0; | 165 | return 0; |
109 | } | 166 | } |
110 | 167 | ||
111 | static int | 168 | static int |
112 | asoc_simple_card_sub_parse_of(struct device_node *np, | 169 | asoc_simple_card_sub_parse_of(struct device_node *np, |
113 | struct asoc_simple_dai *dai, | 170 | struct asoc_simple_dai *dai, |
114 | const struct device_node **p_node, | 171 | struct device_node **p_node, |
115 | const char **name) | 172 | const char **name, |
173 | int *args_count) | ||
116 | { | 174 | { |
117 | struct device_node *node; | 175 | struct of_phandle_args args; |
118 | struct clk *clk; | 176 | struct clk *clk; |
119 | u32 val; | 177 | u32 val; |
120 | int ret; | 178 | int ret; |
121 | 179 | ||
122 | /* | 180 | /* |
123 | * get node via "sound-dai = <&phandle port>" | 181 | * Get node via "sound-dai = <&phandle port>" |
124 | * it will be used as xxx_of_node on soc_bind_dai_link() | 182 | * it will be used as xxx_of_node on soc_bind_dai_link() |
125 | */ | 183 | */ |
126 | node = of_parse_phandle(np, "sound-dai", 0); | 184 | ret = of_parse_phandle_with_args(np, "sound-dai", |
127 | if (!node) | 185 | "#sound-dai-cells", 0, &args); |
128 | return -ENODEV; | 186 | if (ret) |
129 | *p_node = node; | 187 | return ret; |
188 | |||
189 | *p_node = args.np; | ||
190 | |||
191 | if (args_count) | ||
192 | *args_count = args.args_count; | ||
130 | 193 | ||
131 | /* get dai->name */ | 194 | /* Get dai->name */ |
132 | ret = snd_soc_of_get_dai_name(np, name); | 195 | ret = snd_soc_of_get_dai_name(np, name); |
133 | if (ret < 0) | 196 | if (ret < 0) |
134 | return ret; | 197 | return ret; |
135 | 198 | ||
136 | /* parse TDM slot */ | 199 | /* Parse TDM slot */ |
137 | ret = snd_soc_of_parse_tdm_slot(np, &dai->slots, &dai->slot_width); | 200 | ret = snd_soc_of_parse_tdm_slot(np, &dai->slots, &dai->slot_width); |
138 | if (ret) | 201 | if (ret) |
139 | return ret; | 202 | return ret; |
140 | 203 | ||
141 | /* | 204 | /* |
142 | * dai->sysclk come from | 205 | * Parse dai->sysclk come from "clocks = <&xxx>" |
143 | * "clocks = <&xxx>" (if system has common clock) | 206 | * (if system has common clock) |
144 | * or "system-clock-frequency = <xxx>" | 207 | * or "system-clock-frequency = <xxx>" |
145 | * or device's module clock. | 208 | * or device's module clock. |
146 | */ | 209 | */ |
@@ -155,7 +218,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, | |||
155 | } else if (!of_property_read_u32(np, "system-clock-frequency", &val)) { | 218 | } else if (!of_property_read_u32(np, "system-clock-frequency", &val)) { |
156 | dai->sysclk = val; | 219 | dai->sysclk = val; |
157 | } else { | 220 | } else { |
158 | clk = of_clk_get(node, 0); | 221 | clk = of_clk_get(args.np, 0); |
159 | if (!IS_ERR(clk)) | 222 | if (!IS_ERR(clk)) |
160 | dai->sysclk = clk_get_rate(clk); | 223 | dai->sysclk = clk_get_rate(clk); |
161 | } | 224 | } |
@@ -163,12 +226,14 @@ asoc_simple_card_sub_parse_of(struct device_node *np, | |||
163 | return 0; | 226 | return 0; |
164 | } | 227 | } |
165 | 228 | ||
166 | static int simple_card_dai_link_of(struct device_node *node, | 229 | static int asoc_simple_card_dai_link_of(struct device_node *node, |
167 | struct device *dev, | 230 | struct simple_card_data *priv, |
168 | struct snd_soc_dai_link *dai_link, | 231 | int idx, |
169 | struct simple_dai_props *dai_props, | 232 | bool is_top_level_node) |
170 | bool is_top_level_node) | ||
171 | { | 233 | { |
234 | struct device *dev = simple_priv_to_dev(priv); | ||
235 | struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx); | ||
236 | struct simple_dai_props *dai_props = simple_priv_to_props(priv, idx); | ||
172 | struct device_node *np = NULL; | 237 | struct device_node *np = NULL; |
173 | struct device_node *bitclkmaster = NULL; | 238 | struct device_node *bitclkmaster = NULL; |
174 | struct device_node *framemaster = NULL; | 239 | struct device_node *framemaster = NULL; |
@@ -176,8 +241,9 @@ static int simple_card_dai_link_of(struct device_node *node, | |||
176 | char *name; | 241 | char *name; |
177 | char prop[128]; | 242 | char prop[128]; |
178 | char *prefix = ""; | 243 | char *prefix = ""; |
179 | int ret; | 244 | int ret, cpu_args; |
180 | 245 | ||
246 | /* For single DAI link & old style of DT node */ | ||
181 | if (is_top_level_node) | 247 | if (is_top_level_node) |
182 | prefix = "simple-audio-card,"; | 248 | prefix = "simple-audio-card,"; |
183 | 249 | ||
@@ -195,7 +261,8 @@ static int simple_card_dai_link_of(struct device_node *node, | |||
195 | 261 | ||
196 | ret = asoc_simple_card_sub_parse_of(np, &dai_props->cpu_dai, | 262 | ret = asoc_simple_card_sub_parse_of(np, &dai_props->cpu_dai, |
197 | &dai_link->cpu_of_node, | 263 | &dai_link->cpu_of_node, |
198 | &dai_link->cpu_dai_name); | 264 | &dai_link->cpu_dai_name, |
265 | &cpu_args); | ||
199 | if (ret < 0) | 266 | if (ret < 0) |
200 | goto dai_link_of_err; | 267 | goto dai_link_of_err; |
201 | 268 | ||
@@ -226,14 +293,16 @@ static int simple_card_dai_link_of(struct device_node *node, | |||
226 | 293 | ||
227 | ret = asoc_simple_card_sub_parse_of(np, &dai_props->codec_dai, | 294 | ret = asoc_simple_card_sub_parse_of(np, &dai_props->codec_dai, |
228 | &dai_link->codec_of_node, | 295 | &dai_link->codec_of_node, |
229 | &dai_link->codec_dai_name); | 296 | &dai_link->codec_dai_name, NULL); |
230 | if (ret < 0) | 297 | if (ret < 0) |
231 | goto dai_link_of_err; | 298 | goto dai_link_of_err; |
232 | 299 | ||
233 | if (strlen(prefix) && !bitclkmaster && !framemaster) { | 300 | if (strlen(prefix) && !bitclkmaster && !framemaster) { |
234 | /* No dai-link level and master setting was not found from | 301 | /* |
235 | sound node level, revert back to legacy DT parsing and | 302 | * No DAI link level and master setting was found |
236 | take the settings from codec node. */ | 303 | * from sound node level, revert back to legacy DT |
304 | * parsing and take the settings from codec node. | ||
305 | */ | ||
237 | dev_dbg(dev, "%s: Revert to legacy daifmt parsing\n", | 306 | dev_dbg(dev, "%s: Revert to legacy daifmt parsing\n", |
238 | __func__); | 307 | __func__); |
239 | dai_props->cpu_dai.fmt = dai_props->codec_dai.fmt = | 308 | dai_props->cpu_dai.fmt = dai_props->codec_dai.fmt = |
@@ -262,10 +331,10 @@ static int simple_card_dai_link_of(struct device_node *node, | |||
262 | goto dai_link_of_err; | 331 | goto dai_link_of_err; |
263 | } | 332 | } |
264 | 333 | ||
265 | /* simple-card assumes platform == cpu */ | 334 | /* Simple Card assumes platform == cpu */ |
266 | dai_link->platform_of_node = dai_link->cpu_of_node; | 335 | dai_link->platform_of_node = dai_link->cpu_of_node; |
267 | 336 | ||
268 | /* Link name is created from CPU/CODEC dai name */ | 337 | /* DAI link name is created from CPU/CODEC dai name */ |
269 | name = devm_kzalloc(dev, | 338 | name = devm_kzalloc(dev, |
270 | strlen(dai_link->cpu_dai_name) + | 339 | strlen(dai_link->cpu_dai_name) + |
271 | strlen(dai_link->codec_dai_name) + 2, | 340 | strlen(dai_link->codec_dai_name) + 2, |
@@ -274,6 +343,7 @@ static int simple_card_dai_link_of(struct device_node *node, | |||
274 | dai_link->codec_dai_name); | 343 | dai_link->codec_dai_name); |
275 | dai_link->name = dai_link->stream_name = name; | 344 | dai_link->name = dai_link->stream_name = name; |
276 | dai_link->ops = &asoc_simple_card_ops; | 345 | dai_link->ops = &asoc_simple_card_ops; |
346 | dai_link->init = asoc_simple_card_dai_init; | ||
277 | 347 | ||
278 | dev_dbg(dev, "\tname : %s\n", dai_link->stream_name); | 348 | dev_dbg(dev, "\tname : %s\n", dai_link->stream_name); |
279 | dev_dbg(dev, "\tcpu : %s / %04x / %d\n", | 349 | dev_dbg(dev, "\tcpu : %s / %04x / %d\n", |
@@ -285,6 +355,18 @@ static int simple_card_dai_link_of(struct device_node *node, | |||
285 | dai_props->codec_dai.fmt, | 355 | dai_props->codec_dai.fmt, |
286 | dai_props->codec_dai.sysclk); | 356 | dai_props->codec_dai.sysclk); |
287 | 357 | ||
358 | /* | ||
359 | * In soc_bind_dai_link() will check cpu name after | ||
360 | * of_node matching if dai_link has cpu_dai_name. | ||
361 | * but, it will never match if name was created by | ||
362 | * fmt_single_name() remove cpu_dai_name if cpu_args | ||
363 | * was 0. See: | ||
364 | * fmt_single_name() | ||
365 | * fmt_multiple_name() | ||
366 | */ | ||
367 | if (!cpu_args) | ||
368 | dai_link->cpu_dai_name = NULL; | ||
369 | |||
288 | dai_link_of_err: | 370 | dai_link_of_err: |
289 | if (np) | 371 | if (np) |
290 | of_node_put(np); | 372 | of_node_put(np); |
@@ -296,19 +378,19 @@ dai_link_of_err: | |||
296 | } | 378 | } |
297 | 379 | ||
298 | static int asoc_simple_card_parse_of(struct device_node *node, | 380 | static int asoc_simple_card_parse_of(struct device_node *node, |
299 | struct simple_card_data *priv, | 381 | struct simple_card_data *priv) |
300 | struct device *dev, | ||
301 | int multi) | ||
302 | { | 382 | { |
303 | struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link; | 383 | struct device *dev = simple_priv_to_dev(priv); |
304 | struct simple_dai_props *dai_props = priv->dai_props; | ||
305 | u32 val; | 384 | u32 val; |
306 | int ret; | 385 | int ret; |
307 | 386 | ||
308 | /* parsing the card name from DT */ | 387 | if (!node) |
388 | return -EINVAL; | ||
389 | |||
390 | /* Parse the card name from DT */ | ||
309 | snd_soc_of_parse_card_name(&priv->snd_card, "simple-audio-card,name"); | 391 | snd_soc_of_parse_card_name(&priv->snd_card, "simple-audio-card,name"); |
310 | 392 | ||
311 | /* off-codec widgets */ | 393 | /* The off-codec widgets */ |
312 | if (of_property_read_bool(node, "simple-audio-card,widgets")) { | 394 | if (of_property_read_bool(node, "simple-audio-card,widgets")) { |
313 | ret = snd_soc_of_parse_audio_simple_widgets(&priv->snd_card, | 395 | ret = snd_soc_of_parse_audio_simple_widgets(&priv->snd_card, |
314 | "simple-audio-card,widgets"); | 396 | "simple-audio-card,widgets"); |
@@ -332,32 +414,45 @@ static int asoc_simple_card_parse_of(struct device_node *node, | |||
332 | dev_dbg(dev, "New simple-card: %s\n", priv->snd_card.name ? | 414 | dev_dbg(dev, "New simple-card: %s\n", priv->snd_card.name ? |
333 | priv->snd_card.name : ""); | 415 | priv->snd_card.name : ""); |
334 | 416 | ||
335 | if (multi) { | 417 | /* Single/Muti DAI link(s) & New style of DT node */ |
418 | if (of_get_child_by_name(node, "simple-audio-card,dai-link")) { | ||
336 | struct device_node *np = NULL; | 419 | struct device_node *np = NULL; |
337 | int i; | 420 | int i = 0; |
338 | for (i = 0; (np = of_get_next_child(node, np)); i++) { | 421 | |
422 | for_each_child_of_node(node, np) { | ||
339 | dev_dbg(dev, "\tlink %d:\n", i); | 423 | dev_dbg(dev, "\tlink %d:\n", i); |
340 | ret = simple_card_dai_link_of(np, dev, dai_link + i, | 424 | ret = asoc_simple_card_dai_link_of(np, priv, |
341 | dai_props + i, false); | 425 | i, false); |
342 | if (ret < 0) { | 426 | if (ret < 0) { |
343 | of_node_put(np); | 427 | of_node_put(np); |
344 | return ret; | 428 | return ret; |
345 | } | 429 | } |
430 | i++; | ||
346 | } | 431 | } |
347 | } else { | 432 | } else { |
348 | ret = simple_card_dai_link_of(node, dev, dai_link, dai_props, | 433 | /* For single DAI link & old style of DT node */ |
349 | true); | 434 | ret = asoc_simple_card_dai_link_of(node, priv, 0, true); |
350 | if (ret < 0) | 435 | if (ret < 0) |
351 | return ret; | 436 | return ret; |
352 | } | 437 | } |
353 | 438 | ||
439 | priv->gpio_hp_det = of_get_named_gpio(node, | ||
440 | "simple-audio-card,hp-det-gpio", 0); | ||
441 | if (priv->gpio_hp_det == -EPROBE_DEFER) | ||
442 | return -EPROBE_DEFER; | ||
443 | |||
444 | priv->gpio_mic_det = of_get_named_gpio(node, | ||
445 | "simple-audio-card,mic-det-gpio", 0); | ||
446 | if (priv->gpio_mic_det == -EPROBE_DEFER) | ||
447 | return -EPROBE_DEFER; | ||
448 | |||
354 | if (!priv->snd_card.name) | 449 | if (!priv->snd_card.name) |
355 | priv->snd_card.name = priv->snd_card.dai_link->name; | 450 | priv->snd_card.name = priv->snd_card.dai_link->name; |
356 | 451 | ||
357 | return 0; | 452 | return 0; |
358 | } | 453 | } |
359 | 454 | ||
360 | /* update the reference count of the devices nodes at end of probe */ | 455 | /* Decrease the reference count of the device nodes */ |
361 | static int asoc_simple_card_unref(struct platform_device *pdev) | 456 | static int asoc_simple_card_unref(struct platform_device *pdev) |
362 | { | 457 | { |
363 | struct snd_soc_card *card = platform_get_drvdata(pdev); | 458 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
@@ -384,34 +479,32 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
384 | struct snd_soc_dai_link *dai_link; | 479 | struct snd_soc_dai_link *dai_link; |
385 | struct device_node *np = pdev->dev.of_node; | 480 | struct device_node *np = pdev->dev.of_node; |
386 | struct device *dev = &pdev->dev; | 481 | struct device *dev = &pdev->dev; |
387 | int num_links, multi, ret; | 482 | int num_links, ret; |
388 | 483 | ||
389 | /* get the number of DAI links */ | 484 | /* Get the number of DAI links */ |
390 | if (np && of_get_child_by_name(np, "simple-audio-card,dai-link")) { | 485 | if (np && of_get_child_by_name(np, "simple-audio-card,dai-link")) |
391 | num_links = of_get_child_count(np); | 486 | num_links = of_get_child_count(np); |
392 | multi = 1; | 487 | else |
393 | } else { | ||
394 | num_links = 1; | 488 | num_links = 1; |
395 | multi = 0; | ||
396 | } | ||
397 | 489 | ||
398 | /* allocate the private data and the DAI link array */ | 490 | /* Allocate the private data and the DAI link array */ |
399 | priv = devm_kzalloc(dev, | 491 | priv = devm_kzalloc(dev, |
400 | sizeof(*priv) + sizeof(*dai_link) * num_links, | 492 | sizeof(*priv) + sizeof(*dai_link) * num_links, |
401 | GFP_KERNEL); | 493 | GFP_KERNEL); |
402 | if (!priv) | 494 | if (!priv) |
403 | return -ENOMEM; | 495 | return -ENOMEM; |
404 | 496 | ||
405 | /* | 497 | /* Init snd_soc_card */ |
406 | * init snd_soc_card | ||
407 | */ | ||
408 | priv->snd_card.owner = THIS_MODULE; | 498 | priv->snd_card.owner = THIS_MODULE; |
409 | priv->snd_card.dev = dev; | 499 | priv->snd_card.dev = dev; |
410 | dai_link = priv->dai_link; | 500 | dai_link = priv->dai_link; |
411 | priv->snd_card.dai_link = dai_link; | 501 | priv->snd_card.dai_link = dai_link; |
412 | priv->snd_card.num_links = num_links; | 502 | priv->snd_card.num_links = num_links; |
413 | 503 | ||
414 | /* get room for the other properties */ | 504 | priv->gpio_hp_det = -ENOENT; |
505 | priv->gpio_mic_det = -ENOENT; | ||
506 | |||
507 | /* Get room for the other properties */ | ||
415 | priv->dai_props = devm_kzalloc(dev, | 508 | priv->dai_props = devm_kzalloc(dev, |
416 | sizeof(*priv->dai_props) * num_links, | 509 | sizeof(*priv->dai_props) * num_links, |
417 | GFP_KERNEL); | 510 | GFP_KERNEL); |
@@ -420,25 +513,13 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
420 | 513 | ||
421 | if (np && of_device_is_available(np)) { | 514 | if (np && of_device_is_available(np)) { |
422 | 515 | ||
423 | ret = asoc_simple_card_parse_of(np, priv, dev, multi); | 516 | ret = asoc_simple_card_parse_of(np, priv); |
424 | if (ret < 0) { | 517 | if (ret < 0) { |
425 | if (ret != -EPROBE_DEFER) | 518 | if (ret != -EPROBE_DEFER) |
426 | dev_err(dev, "parse error %d\n", ret); | 519 | dev_err(dev, "parse error %d\n", ret); |
427 | goto err; | 520 | goto err; |
428 | } | 521 | } |
429 | 522 | ||
430 | /* | ||
431 | * soc_bind_dai_link() will check cpu name | ||
432 | * after of_node matching if dai_link has cpu_dai_name. | ||
433 | * but, it will never match if name was created by fmt_single_name() | ||
434 | * remove cpu_dai_name to escape name matching. | ||
435 | * see | ||
436 | * fmt_single_name() | ||
437 | * fmt_multiple_name() | ||
438 | */ | ||
439 | if (num_links == 1) | ||
440 | dai_link->cpu_dai_name = NULL; | ||
441 | |||
442 | } else { | 523 | } else { |
443 | struct asoc_simple_card_info *cinfo; | 524 | struct asoc_simple_card_info *cinfo; |
444 | 525 | ||
@@ -464,6 +545,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
464 | dai_link->codec_name = cinfo->codec; | 545 | dai_link->codec_name = cinfo->codec; |
465 | dai_link->cpu_dai_name = cinfo->cpu_dai.name; | 546 | dai_link->cpu_dai_name = cinfo->cpu_dai.name; |
466 | dai_link->codec_dai_name = cinfo->codec_dai.name; | 547 | dai_link->codec_dai_name = cinfo->codec_dai.name; |
548 | dai_link->init = asoc_simple_card_dai_init; | ||
467 | memcpy(&priv->dai_props->cpu_dai, &cinfo->cpu_dai, | 549 | memcpy(&priv->dai_props->cpu_dai, &cinfo->cpu_dai, |
468 | sizeof(priv->dai_props->cpu_dai)); | 550 | sizeof(priv->dai_props->cpu_dai)); |
469 | memcpy(&priv->dai_props->codec_dai, &cinfo->codec_dai, | 551 | memcpy(&priv->dai_props->codec_dai, &cinfo->codec_dai, |
@@ -473,11 +555,6 @@ static int asoc_simple_card_probe(struct platform_device *pdev) | |||
473 | priv->dai_props->codec_dai.fmt |= cinfo->daifmt; | 555 | priv->dai_props->codec_dai.fmt |= cinfo->daifmt; |
474 | } | 556 | } |
475 | 557 | ||
476 | /* | ||
477 | * init snd_soc_dai_link | ||
478 | */ | ||
479 | dai_link->init = asoc_simple_card_dai_init; | ||
480 | |||
481 | snd_soc_card_set_drvdata(&priv->snd_card, priv); | 558 | snd_soc_card_set_drvdata(&priv->snd_card, priv); |
482 | 559 | ||
483 | ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); | 560 | ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card); |
@@ -491,6 +568,16 @@ err: | |||
491 | 568 | ||
492 | static int asoc_simple_card_remove(struct platform_device *pdev) | 569 | static int asoc_simple_card_remove(struct platform_device *pdev) |
493 | { | 570 | { |
571 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
572 | struct simple_card_data *priv = snd_soc_card_get_drvdata(card); | ||
573 | |||
574 | if (gpio_is_valid(priv->gpio_hp_det)) | ||
575 | snd_soc_jack_free_gpios(&simple_card_hp_jack, 1, | ||
576 | &simple_card_hp_jack_gpio); | ||
577 | if (gpio_is_valid(priv->gpio_mic_det)) | ||
578 | snd_soc_jack_free_gpios(&simple_card_mic_jack, 1, | ||
579 | &simple_card_mic_jack_gpio); | ||
580 | |||
494 | return asoc_simple_card_unref(pdev); | 581 | return asoc_simple_card_unref(pdev); |
495 | } | 582 | } |
496 | 583 | ||