Merge tag 'regulator-fix-v5.15-rc2' of git://git.kernel.org/pub/scm/linux/kernel...
[platform/kernel/linux-starfive.git] / sound / soc / samsung / aries_wm8994.c
1 // SPDX-License-Identifier: GPL-2.0+
2 #include <linux/extcon.h>
3 #include <linux/iio/consumer.h>
4 #include <linux/iio/iio.h>
5 #include <linux/input-event-codes.h>
6 #include <linux/mfd/wm8994/registers.h>
7 #include <linux/module.h>
8 #include <linux/of.h>
9 #include <linux/of_device.h>
10 #include <linux/of_gpio.h>
11 #include <linux/regulator/consumer.h>
12 #include <sound/jack.h>
13 #include <sound/pcm_params.h>
14 #include <sound/soc.h>
15
16 #include "i2s.h"
17 #include "../codecs/wm8994.h"
18
19 #define ARIES_MCLK1_FREQ 24000000
20
21 struct aries_wm8994_variant {
22         unsigned int modem_dai_fmt;
23         bool has_fm_radio;
24 };
25
26 struct aries_wm8994_data {
27         struct extcon_dev *usb_extcon;
28         struct regulator *reg_main_micbias;
29         struct regulator *reg_headset_micbias;
30         struct gpio_desc *gpio_headset_detect;
31         struct gpio_desc *gpio_headset_key;
32         struct gpio_desc *gpio_earpath_sel;
33         struct iio_channel *adc;
34         const struct aries_wm8994_variant *variant;
35 };
36
37 /* USB dock */
38 static struct snd_soc_jack aries_dock;
39
40 static struct snd_soc_jack_pin dock_pins[] = {
41         {
42                 .pin = "LINE",
43                 .mask = SND_JACK_LINEOUT,
44         },
45 };
46
47 static int aries_extcon_notifier(struct notifier_block *this,
48                                  unsigned long connected, void *_cmd)
49 {
50         if (connected)
51                 snd_soc_jack_report(&aries_dock, SND_JACK_LINEOUT,
52                                 SND_JACK_LINEOUT);
53         else
54                 snd_soc_jack_report(&aries_dock, 0, SND_JACK_LINEOUT);
55
56         return NOTIFY_DONE;
57 }
58
59 static struct notifier_block aries_extcon_notifier_block = {
60         .notifier_call = aries_extcon_notifier,
61 };
62
63 /* Headset jack */
64 static struct snd_soc_jack aries_headset;
65
66 static struct snd_soc_jack_pin jack_pins[] = {
67         {
68                 .pin = "HP",
69                 .mask = SND_JACK_HEADPHONE,
70         }, {
71                 .pin = "Headset Mic",
72                 .mask = SND_JACK_MICROPHONE,
73         },
74 };
75
76 static struct snd_soc_jack_zone headset_zones[] = {
77         {
78                 .min_mv = 0,
79                 .max_mv = 241,
80                 .jack_type = SND_JACK_HEADPHONE,
81         }, {
82                 .min_mv = 242,
83                 .max_mv = 2980,
84                 .jack_type = SND_JACK_HEADSET,
85         }, {
86                 .min_mv = 2981,
87                 .max_mv = UINT_MAX,
88                 .jack_type = SND_JACK_HEADPHONE,
89         },
90 };
91
92 static irqreturn_t headset_det_irq_thread(int irq, void *data)
93 {
94         struct aries_wm8994_data *priv = (struct aries_wm8994_data *) data;
95         int ret = 0;
96         int time_left_ms = 300;
97         int adc;
98
99         while (time_left_ms > 0) {
100                 if (!gpiod_get_value(priv->gpio_headset_detect)) {
101                         snd_soc_jack_report(&aries_headset, 0,
102                                         SND_JACK_HEADSET);
103                         gpiod_set_value(priv->gpio_earpath_sel, 0);
104                         return IRQ_HANDLED;
105                 }
106                 msleep(20);
107                 time_left_ms -= 20;
108         }
109
110         /* Temporarily enable micbias and earpath selector */
111         ret = regulator_enable(priv->reg_headset_micbias);
112         if (ret)
113                 pr_err("%s failed to enable micbias: %d", __func__, ret);
114
115         gpiod_set_value(priv->gpio_earpath_sel, 1);
116
117         ret = iio_read_channel_processed(priv->adc, &adc);
118         if (ret < 0) {
119                 /* failed to read ADC, so assume headphone */
120                 pr_err("%s failed to read ADC, assuming headphones", __func__);
121                 snd_soc_jack_report(&aries_headset, SND_JACK_HEADPHONE,
122                                 SND_JACK_HEADSET);
123         } else {
124                 snd_soc_jack_report(&aries_headset,
125                                 snd_soc_jack_get_type(&aries_headset, adc),
126                                 SND_JACK_HEADSET);
127         }
128
129         ret = regulator_disable(priv->reg_headset_micbias);
130         if (ret)
131                 pr_err("%s failed disable micbias: %d", __func__, ret);
132
133         /* Disable earpath selector when no mic connected */
134         if (!(aries_headset.status & SND_JACK_MICROPHONE))
135                 gpiod_set_value(priv->gpio_earpath_sel, 0);
136
137         return IRQ_HANDLED;
138 }
139
140 static int headset_button_check(void *data)
141 {
142         struct aries_wm8994_data *priv = (struct aries_wm8994_data *) data;
143
144         /* Filter out keypresses when 4 pole jack not detected */
145         if (gpiod_get_value_cansleep(priv->gpio_headset_key) &&
146                         aries_headset.status & SND_JACK_MICROPHONE)
147                 return SND_JACK_BTN_0;
148
149         return 0;
150 }
151
152 static struct snd_soc_jack_gpio headset_button_gpio[] = {
153         {
154                 .name = "Media Button",
155                 .report = SND_JACK_BTN_0,
156                 .debounce_time  = 30,
157                 .jack_status_check = headset_button_check,
158         },
159 };
160
161 static int aries_spk_cfg(struct snd_soc_dapm_widget *w,
162                         struct snd_kcontrol *kcontrol, int event)
163 {
164         struct snd_soc_card *card = w->dapm->card;
165         struct snd_soc_pcm_runtime *rtd;
166         struct snd_soc_component *component;
167         int ret = 0;
168
169         rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
170         component = asoc_rtd_to_codec(rtd, 0)->component;
171
172         /**
173          * We have an odd setup - the SPKMODE pin is pulled up so
174          * we only have access to the left side SPK configs,
175          * but SPKOUTR isn't bridged so when playing back in
176          * stereo, we only get the left hand channel.  The only
177          * option we're left with is to force the AIF into mono
178          * mode.
179          */
180         switch (event) {
181         case SND_SOC_DAPM_POST_PMU:
182                 ret = snd_soc_component_update_bits(component,
183                                 WM8994_AIF1_DAC1_FILTERS_1,
184                                 WM8994_AIF1DAC1_MONO, WM8994_AIF1DAC1_MONO);
185                 break;
186         case SND_SOC_DAPM_PRE_PMD:
187                 ret = snd_soc_component_update_bits(component,
188                                 WM8994_AIF1_DAC1_FILTERS_1,
189                                 WM8994_AIF1DAC1_MONO, 0);
190                 break;
191         }
192
193         return ret;
194 }
195
196 static int aries_main_bias(struct snd_soc_dapm_widget *w,
197                           struct snd_kcontrol *kcontrol, int event)
198 {
199         struct snd_soc_card *card = w->dapm->card;
200         struct aries_wm8994_data *priv = snd_soc_card_get_drvdata(card);
201         int ret = 0;
202
203         switch (event) {
204         case SND_SOC_DAPM_PRE_PMU:
205                 ret = regulator_enable(priv->reg_main_micbias);
206                 break;
207         case SND_SOC_DAPM_POST_PMD:
208                 ret = regulator_disable(priv->reg_main_micbias);
209                 break;
210         }
211
212         return ret;
213 }
214
215 static int aries_headset_bias(struct snd_soc_dapm_widget *w,
216                           struct snd_kcontrol *kcontrol, int event)
217 {
218         struct snd_soc_card *card = w->dapm->card;
219         struct aries_wm8994_data *priv = snd_soc_card_get_drvdata(card);
220         int ret = 0;
221
222         switch (event) {
223         case SND_SOC_DAPM_PRE_PMU:
224                 ret = regulator_enable(priv->reg_headset_micbias);
225                 break;
226         case SND_SOC_DAPM_POST_PMD:
227                 ret = regulator_disable(priv->reg_headset_micbias);
228                 break;
229         }
230
231         return ret;
232 }
233
234 static const struct snd_kcontrol_new aries_controls[] = {
235         SOC_DAPM_PIN_SWITCH("Modem In"),
236         SOC_DAPM_PIN_SWITCH("Modem Out"),
237 };
238
239 static const struct snd_soc_dapm_widget aries_dapm_widgets[] = {
240         SND_SOC_DAPM_HP("HP", NULL),
241
242         SND_SOC_DAPM_SPK("SPK", aries_spk_cfg),
243         SND_SOC_DAPM_SPK("RCV", NULL),
244
245         SND_SOC_DAPM_LINE("LINE", NULL),
246
247         SND_SOC_DAPM_MIC("Main Mic", aries_main_bias),
248         SND_SOC_DAPM_MIC("Headset Mic", aries_headset_bias),
249
250         SND_SOC_DAPM_MIC("Bluetooth Mic", NULL),
251         SND_SOC_DAPM_SPK("Bluetooth SPK", NULL),
252
253         SND_SOC_DAPM_LINE("Modem In", NULL),
254         SND_SOC_DAPM_LINE("Modem Out", NULL),
255
256         /* This must be last as it is conditionally not used */
257         SND_SOC_DAPM_LINE("FM In", NULL),
258 };
259
260 static int aries_hw_params(struct snd_pcm_substream *substream,
261         struct snd_pcm_hw_params *params)
262 {
263         struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
264         struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
265         unsigned int pll_out;
266         int ret;
267
268         /* AIF1CLK should be >=3MHz for optimal performance */
269         if (params_width(params) == 24)
270                 pll_out = params_rate(params) * 384;
271         else if (params_rate(params) == 8000 || params_rate(params) == 11025)
272                 pll_out = params_rate(params) * 512;
273         else
274                 pll_out = params_rate(params) * 256;
275
276         ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1,
277                                 ARIES_MCLK1_FREQ, pll_out);
278         if (ret < 0)
279                 return ret;
280
281         ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1,
282                                 pll_out, SND_SOC_CLOCK_IN);
283         if (ret < 0)
284                 return ret;
285
286         return 0;
287 }
288
289 static int aries_hw_free(struct snd_pcm_substream *substream)
290 {
291         struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
292         struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
293         int ret;
294
295         /* Switch sysclk to MCLK1 */
296         ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_MCLK1,
297                                 ARIES_MCLK1_FREQ, SND_SOC_CLOCK_IN);
298         if (ret < 0)
299                 return ret;
300
301         /* Stop PLL */
302         ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1,
303                                 ARIES_MCLK1_FREQ, 0);
304         if (ret < 0)
305                 return ret;
306
307         return 0;
308 }
309
310 /*
311  * Main DAI operations
312  */
313 static const struct snd_soc_ops aries_ops = {
314         .hw_params = aries_hw_params,
315         .hw_free = aries_hw_free,
316 };
317
318 static int aries_baseband_init(struct snd_soc_pcm_runtime *rtd)
319 {
320         struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
321         unsigned int pll_out;
322         int ret;
323
324         pll_out = 8000 * 512;
325
326         /* Set the codec FLL */
327         ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL2, WM8994_FLL_SRC_MCLK1,
328                         ARIES_MCLK1_FREQ, pll_out);
329         if (ret < 0)
330                 return ret;
331
332         /* Set the codec system clock */
333         ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL2,
334                         pll_out, SND_SOC_CLOCK_IN);
335         if (ret < 0)
336                 return ret;
337
338         return 0;
339 }
340
341 static int aries_late_probe(struct snd_soc_card *card)
342 {
343         struct aries_wm8994_data *priv = snd_soc_card_get_drvdata(card);
344         int ret, irq;
345
346         ret = snd_soc_card_jack_new(card, "Dock", SND_JACK_LINEOUT,
347                         &aries_dock, dock_pins, ARRAY_SIZE(dock_pins));
348         if (ret)
349                 return ret;
350
351         ret = devm_extcon_register_notifier(card->dev,
352                         priv->usb_extcon, EXTCON_JACK_LINE_OUT,
353                         &aries_extcon_notifier_block);
354         if (ret)
355                 return ret;
356
357         if (extcon_get_state(priv->usb_extcon,
358                         EXTCON_JACK_LINE_OUT) > 0)
359                 snd_soc_jack_report(&aries_dock, SND_JACK_LINEOUT,
360                                 SND_JACK_LINEOUT);
361         else
362                 snd_soc_jack_report(&aries_dock, 0, SND_JACK_LINEOUT);
363
364         ret = snd_soc_card_jack_new(card, "Headset",
365                         SND_JACK_HEADSET | SND_JACK_BTN_0,
366                         &aries_headset,
367                         jack_pins, ARRAY_SIZE(jack_pins));
368         if (ret)
369                 return ret;
370
371         ret = snd_soc_jack_add_zones(&aries_headset, ARRAY_SIZE(headset_zones),
372                         headset_zones);
373         if (ret)
374                 return ret;
375
376         irq = gpiod_to_irq(priv->gpio_headset_detect);
377         if (irq < 0) {
378                 dev_err(card->dev, "Failed to map headset detect gpio to irq");
379                 return -EINVAL;
380         }
381
382         ret = devm_request_threaded_irq(card->dev, irq, NULL,
383                         headset_det_irq_thread,
384                         IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
385                         IRQF_ONESHOT, "headset_detect", priv);
386         if (ret) {
387                 dev_err(card->dev, "Failed to request headset detect irq");
388                 return ret;
389         }
390
391         headset_button_gpio[0].data = priv;
392         headset_button_gpio[0].desc = priv->gpio_headset_key;
393
394         snd_jack_set_key(aries_headset.jack, SND_JACK_BTN_0, KEY_MEDIA);
395
396         return snd_soc_jack_add_gpios(&aries_headset,
397                         ARRAY_SIZE(headset_button_gpio), headset_button_gpio);
398 }
399
400 static const struct snd_soc_pcm_stream baseband_params = {
401         .formats = SNDRV_PCM_FMTBIT_S16_LE,
402         .rate_min = 8000,
403         .rate_max = 8000,
404         .channels_min = 1,
405         .channels_max = 1,
406 };
407
408 static const struct snd_soc_pcm_stream bluetooth_params = {
409         .formats = SNDRV_PCM_FMTBIT_S16_LE,
410         .rate_min = 8000,
411         .rate_max = 8000,
412         .channels_min = 1,
413         .channels_max = 2,
414 };
415
416 static const struct snd_soc_dapm_widget aries_modem_widgets[] = {
417         SND_SOC_DAPM_INPUT("Modem RX"),
418         SND_SOC_DAPM_OUTPUT("Modem TX"),
419 };
420
421 static const struct snd_soc_dapm_route aries_modem_routes[] = {
422         { "Modem Capture", NULL, "Modem RX" },
423         { "Modem TX", NULL, "Modem Playback" },
424 };
425
426 static const struct snd_soc_component_driver aries_component = {
427         .name                   = "aries-audio",
428         .dapm_widgets           = aries_modem_widgets,
429         .num_dapm_widgets       = ARRAY_SIZE(aries_modem_widgets),
430         .dapm_routes            = aries_modem_routes,
431         .num_dapm_routes        = ARRAY_SIZE(aries_modem_routes),
432         .idle_bias_on           = 1,
433         .use_pmdown_time        = 1,
434         .endianness             = 1,
435         .non_legacy_dai_naming  = 1,
436 };
437
438 static struct snd_soc_dai_driver aries_ext_dai[] = {
439         {
440                 .name = "Voice call",
441                 .playback = {
442                         .stream_name = "Modem Playback",
443                         .channels_min = 1,
444                         .channels_max = 1,
445                         .rate_min = 8000,
446                         .rate_max = 8000,
447                         .rates = SNDRV_PCM_RATE_8000,
448                         .formats = SNDRV_PCM_FMTBIT_S16_LE,
449                 },
450                 .capture = {
451                         .stream_name = "Modem Capture",
452                         .channels_min = 1,
453                         .channels_max = 1,
454                         .rate_min = 8000,
455                         .rate_max = 8000,
456                         .rates = SNDRV_PCM_RATE_8000,
457                         .formats = SNDRV_PCM_FMTBIT_S16_LE,
458                 },
459         },
460 };
461
462 SND_SOC_DAILINK_DEFS(aif1,
463         DAILINK_COMP_ARRAY(COMP_CPU(SAMSUNG_I2S_DAI)),
464         DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif1")),
465         DAILINK_COMP_ARRAY(COMP_EMPTY()));
466
467 SND_SOC_DAILINK_DEFS(baseband,
468         DAILINK_COMP_ARRAY(COMP_CPU("Voice call")),
469         DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif2")));
470
471 SND_SOC_DAILINK_DEFS(bluetooth,
472         DAILINK_COMP_ARRAY(COMP_CPU("bt-sco-pcm")),
473         DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif3")));
474
475 static struct snd_soc_dai_link aries_dai[] = {
476         {
477                 .name = "WM8994 AIF1",
478                 .stream_name = "HiFi",
479                 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
480                         SND_SOC_DAIFMT_CBM_CFM,
481                 .ops = &aries_ops,
482                 SND_SOC_DAILINK_REG(aif1),
483         },
484         {
485                 .name = "WM8994 AIF2",
486                 .stream_name = "Baseband",
487                 .init = &aries_baseband_init,
488                 .params = &baseband_params,
489                 .ignore_suspend = 1,
490                 SND_SOC_DAILINK_REG(baseband),
491         },
492         {
493                 .name = "WM8994 AIF3",
494                 .stream_name = "Bluetooth",
495                 .params = &bluetooth_params,
496                 .ignore_suspend = 1,
497                 SND_SOC_DAILINK_REG(bluetooth),
498         },
499 };
500
501 static struct snd_soc_card aries_card = {
502         .name = "ARIES",
503         .owner = THIS_MODULE,
504         .dai_link = aries_dai,
505         .num_links = ARRAY_SIZE(aries_dai),
506         .controls = aries_controls,
507         .num_controls = ARRAY_SIZE(aries_controls),
508         .dapm_widgets = aries_dapm_widgets,
509         .num_dapm_widgets = ARRAY_SIZE(aries_dapm_widgets),
510         .late_probe = aries_late_probe,
511 };
512
513 static const struct aries_wm8994_variant fascinate4g_variant = {
514         .modem_dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS
515                 | SND_SOC_DAIFMT_IB_NF,
516         .has_fm_radio = false,
517 };
518
519 static const struct aries_wm8994_variant aries_variant = {
520         .modem_dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM
521                 | SND_SOC_DAIFMT_IB_NF,
522         .has_fm_radio = true,
523 };
524
525 static const struct of_device_id samsung_wm8994_of_match[] = {
526         {
527                 .compatible = "samsung,fascinate4g-wm8994",
528                 .data = &fascinate4g_variant,
529         },
530         {
531                 .compatible = "samsung,aries-wm8994",
532                 .data = &aries_variant,
533         },
534         { /* sentinel */ },
535 };
536 MODULE_DEVICE_TABLE(of, samsung_wm8994_of_match);
537
538 static int aries_audio_probe(struct platform_device *pdev)
539 {
540         struct device_node *np = pdev->dev.of_node;
541         struct device_node *cpu, *codec, *extcon_np;
542         struct device *dev = &pdev->dev;
543         struct snd_soc_card *card = &aries_card;
544         struct aries_wm8994_data *priv;
545         struct snd_soc_dai_link *dai_link;
546         const struct of_device_id *match;
547         int ret, i;
548
549         if (!np)
550                 return -EINVAL;
551
552         card->dev = dev;
553
554         priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
555         if (!priv)
556                 return -ENOMEM;
557
558         snd_soc_card_set_drvdata(card, priv);
559
560         match = of_match_node(samsung_wm8994_of_match, np);
561         priv->variant = match->data;
562
563         /* Remove FM widget if not present */
564         if (!priv->variant->has_fm_radio)
565                 card->num_dapm_widgets--;
566
567         priv->reg_main_micbias = devm_regulator_get(dev, "main-micbias");
568         if (IS_ERR(priv->reg_main_micbias)) {
569                 dev_err(dev, "Failed to get main micbias regulator\n");
570                 return PTR_ERR(priv->reg_main_micbias);
571         }
572
573         priv->reg_headset_micbias = devm_regulator_get(dev, "headset-micbias");
574         if (IS_ERR(priv->reg_headset_micbias)) {
575                 dev_err(dev, "Failed to get headset micbias regulator\n");
576                 return PTR_ERR(priv->reg_headset_micbias);
577         }
578
579         priv->gpio_earpath_sel = devm_gpiod_get(dev, "earpath-sel",
580                         GPIOD_OUT_LOW);
581         if (IS_ERR(priv->gpio_earpath_sel)) {
582                 dev_err(dev, "Failed to get earpath selector gpio");
583                 return PTR_ERR(priv->gpio_earpath_sel);
584         }
585
586         extcon_np = of_parse_phandle(np, "extcon", 0);
587         priv->usb_extcon = extcon_find_edev_by_node(extcon_np);
588         if (IS_ERR(priv->usb_extcon)) {
589                 if (PTR_ERR(priv->usb_extcon) != -EPROBE_DEFER)
590                         dev_err(dev, "Failed to get extcon device");
591                 return PTR_ERR(priv->usb_extcon);
592         }
593         of_node_put(extcon_np);
594
595         priv->adc = devm_iio_channel_get(dev, "headset-detect");
596         if (IS_ERR(priv->adc)) {
597                 if (PTR_ERR(priv->adc) != -EPROBE_DEFER)
598                         dev_err(dev, "Failed to get ADC channel");
599                 return PTR_ERR(priv->adc);
600         }
601         if (priv->adc->channel->type != IIO_VOLTAGE)
602                 return -EINVAL;
603
604         priv->gpio_headset_key = devm_gpiod_get(dev, "headset-key",
605                         GPIOD_IN);
606         if (IS_ERR(priv->gpio_headset_key)) {
607                 dev_err(dev, "Failed to get headset key gpio");
608                 return PTR_ERR(priv->gpio_headset_key);
609         }
610
611         priv->gpio_headset_detect = devm_gpiod_get(dev,
612                         "headset-detect", GPIOD_IN);
613         if (IS_ERR(priv->gpio_headset_detect)) {
614                 dev_err(dev, "Failed to get headset detect gpio");
615                 return PTR_ERR(priv->gpio_headset_detect);
616         }
617
618         /* Update card-name if provided through DT, else use default name */
619         snd_soc_of_parse_card_name(card, "model");
620
621         ret = snd_soc_of_parse_audio_routing(card, "samsung,audio-routing");
622         if (ret < 0) {
623                 dev_err(dev, "Audio routing invalid/unspecified\n");
624                 return ret;
625         }
626
627         aries_dai[1].dai_fmt = priv->variant->modem_dai_fmt;
628
629         cpu = of_get_child_by_name(dev->of_node, "cpu");
630         if (!cpu)
631                 return -EINVAL;
632
633         codec = of_get_child_by_name(dev->of_node, "codec");
634         if (!codec)
635                 return -EINVAL;
636
637         for_each_card_prelinks(card, i, dai_link) {
638                 dai_link->codecs->of_node = of_parse_phandle(codec,
639                                 "sound-dai", 0);
640                 if (!dai_link->codecs->of_node) {
641                         ret = -EINVAL;
642                         goto out;
643                 }
644         }
645
646         /* Set CPU and platform of_node for main DAI */
647         aries_dai[0].cpus->of_node = of_parse_phandle(cpu,
648                         "sound-dai", 0);
649         if (!aries_dai[0].cpus->of_node) {
650                 ret = -EINVAL;
651                 goto out;
652         }
653
654         aries_dai[0].platforms->of_node = aries_dai[0].cpus->of_node;
655
656         /* Set CPU of_node for BT DAI */
657         aries_dai[2].cpus->of_node = of_parse_phandle(cpu,
658                         "sound-dai", 1);
659         if (!aries_dai[2].cpus->of_node) {
660                 ret = -EINVAL;
661                 goto out;
662         }
663
664         ret = devm_snd_soc_register_component(dev, &aries_component,
665                                 aries_ext_dai, ARRAY_SIZE(aries_ext_dai));
666         if (ret < 0) {
667                 dev_err(dev, "Failed to register component: %d\n", ret);
668                 goto out;
669         }
670
671         ret = devm_snd_soc_register_card(dev, card);
672         if (ret)
673                 dev_err(dev, "snd_soc_register_card() failed:%d\n", ret);
674
675 out:
676         of_node_put(cpu);
677         of_node_put(codec);
678
679         return ret;
680 }
681
682 static struct platform_driver aries_audio_driver = {
683         .driver         = {
684                 .name   = "aries-audio-wm8994",
685                 .of_match_table = of_match_ptr(samsung_wm8994_of_match),
686                 .pm     = &snd_soc_pm_ops,
687         },
688         .probe          = aries_audio_probe,
689 };
690
691 module_platform_driver(aries_audio_driver);
692
693 MODULE_DESCRIPTION("ALSA SoC ARIES WM8994");
694 MODULE_LICENSE("GPL");
695 MODULE_ALIAS("platform:aries-audio-wm8994");