Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 //
0003 // Copyright (C) 2015 - 2016 Samsung Electronics Co., Ltd.
0004 //
0005 // Authors: Inha Song <ideal.song@samsung.com>
0006 //          Sylwester Nawrocki <s.nawrocki@samsung.com>
0007 
0008 #include <linux/clk.h>
0009 #include <linux/gpio.h>
0010 #include <linux/gpio/consumer.h>
0011 #include <linux/module.h>
0012 #include <linux/of.h>
0013 #include <sound/pcm_params.h>
0014 #include <sound/soc.h>
0015 
0016 #include "i2s.h"
0017 #include "../codecs/wm5110.h"
0018 
0019 /*
0020  * The source clock is XCLKOUT with its mux set to the external fixed rate
0021  * oscillator (XXTI).
0022  */
0023 #define MCLK_RATE   24000000U
0024 
0025 #define TM2_DAI_AIF1    0
0026 #define TM2_DAI_AIF2    1
0027 
0028 struct tm2_machine_priv {
0029     struct snd_soc_component *component;
0030     unsigned int sysclk_rate;
0031     struct gpio_desc *gpio_mic_bias;
0032 };
0033 
0034 static int tm2_start_sysclk(struct snd_soc_card *card)
0035 {
0036     struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card);
0037     struct snd_soc_component *component = priv->component;
0038     int ret;
0039 
0040     ret = snd_soc_component_set_pll(component, WM5110_FLL1_REFCLK,
0041                     ARIZONA_FLL_SRC_MCLK1,
0042                     MCLK_RATE,
0043                     priv->sysclk_rate);
0044     if (ret < 0) {
0045         dev_err(component->dev, "Failed to set FLL1 source: %d\n", ret);
0046         return ret;
0047     }
0048 
0049     ret = snd_soc_component_set_pll(component, WM5110_FLL1,
0050                     ARIZONA_FLL_SRC_MCLK1,
0051                     MCLK_RATE,
0052                     priv->sysclk_rate);
0053     if (ret < 0) {
0054         dev_err(component->dev, "Failed to start FLL1: %d\n", ret);
0055         return ret;
0056     }
0057 
0058     ret = snd_soc_component_set_sysclk(component, ARIZONA_CLK_SYSCLK,
0059                        ARIZONA_CLK_SRC_FLL1,
0060                        priv->sysclk_rate,
0061                        SND_SOC_CLOCK_IN);
0062     if (ret < 0) {
0063         dev_err(component->dev, "Failed to set SYSCLK source: %d\n", ret);
0064         return ret;
0065     }
0066 
0067     return 0;
0068 }
0069 
0070 static int tm2_stop_sysclk(struct snd_soc_card *card)
0071 {
0072     struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card);
0073     struct snd_soc_component *component = priv->component;
0074     int ret;
0075 
0076     ret = snd_soc_component_set_pll(component, WM5110_FLL1, 0, 0, 0);
0077     if (ret < 0) {
0078         dev_err(component->dev, "Failed to stop FLL1: %d\n", ret);
0079         return ret;
0080     }
0081 
0082     ret = snd_soc_component_set_sysclk(component, ARIZONA_CLK_SYSCLK,
0083                        ARIZONA_CLK_SRC_FLL1, 0, 0);
0084     if (ret < 0) {
0085         dev_err(component->dev, "Failed to stop SYSCLK: %d\n", ret);
0086         return ret;
0087     }
0088 
0089     return 0;
0090 }
0091 
0092 static int tm2_aif1_hw_params(struct snd_pcm_substream *substream,
0093                 struct snd_pcm_hw_params *params)
0094 {
0095     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0096     struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
0097     struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(rtd->card);
0098 
0099     switch (params_rate(params)) {
0100     case 4000:
0101     case 8000:
0102     case 12000:
0103     case 16000:
0104     case 24000:
0105     case 32000:
0106     case 48000:
0107     case 96000:
0108     case 192000:
0109         /* Highest possible SYSCLK frequency: 147.456MHz */
0110         priv->sysclk_rate = 147456000U;
0111         break;
0112     case 11025:
0113     case 22050:
0114     case 44100:
0115     case 88200:
0116     case 176400:
0117         /* Highest possible SYSCLK frequency: 135.4752 MHz */
0118         priv->sysclk_rate = 135475200U;
0119         break;
0120     default:
0121         dev_err(component->dev, "Not supported sample rate: %d\n",
0122             params_rate(params));
0123         return -EINVAL;
0124     }
0125 
0126     return tm2_start_sysclk(rtd->card);
0127 }
0128 
0129 static const struct snd_soc_ops tm2_aif1_ops = {
0130     .hw_params = tm2_aif1_hw_params,
0131 };
0132 
0133 static int tm2_aif2_hw_params(struct snd_pcm_substream *substream,
0134                 struct snd_pcm_hw_params *params)
0135 {
0136     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0137     struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
0138     unsigned int asyncclk_rate;
0139     int ret;
0140 
0141     switch (params_rate(params)) {
0142     case 8000:
0143     case 12000:
0144     case 16000:
0145         /* Highest possible ASYNCCLK frequency: 49.152MHz */
0146         asyncclk_rate = 49152000U;
0147         break;
0148     case 11025:
0149         /* Highest possible ASYNCCLK frequency: 45.1584 MHz */
0150         asyncclk_rate = 45158400U;
0151         break;
0152     default:
0153         dev_err(component->dev, "Not supported sample rate: %d\n",
0154             params_rate(params));
0155         return -EINVAL;
0156     }
0157 
0158     ret = snd_soc_component_set_pll(component, WM5110_FLL2_REFCLK,
0159                     ARIZONA_FLL_SRC_MCLK1,
0160                     MCLK_RATE,
0161                     asyncclk_rate);
0162     if (ret < 0) {
0163         dev_err(component->dev, "Failed to set FLL2 source: %d\n", ret);
0164         return ret;
0165     }
0166 
0167     ret = snd_soc_component_set_pll(component, WM5110_FLL2,
0168                     ARIZONA_FLL_SRC_MCLK1,
0169                     MCLK_RATE,
0170                     asyncclk_rate);
0171     if (ret < 0) {
0172         dev_err(component->dev, "Failed to start FLL2: %d\n", ret);
0173         return ret;
0174     }
0175 
0176     ret = snd_soc_component_set_sysclk(component, ARIZONA_CLK_ASYNCCLK,
0177                        ARIZONA_CLK_SRC_FLL2,
0178                        asyncclk_rate,
0179                        SND_SOC_CLOCK_IN);
0180     if (ret < 0) {
0181         dev_err(component->dev, "Failed to set ASYNCCLK source: %d\n", ret);
0182         return ret;
0183     }
0184 
0185     return 0;
0186 }
0187 
0188 static int tm2_aif2_hw_free(struct snd_pcm_substream *substream)
0189 {
0190     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0191     struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
0192     int ret;
0193 
0194     /* disable FLL2 */
0195     ret = snd_soc_component_set_pll(component, WM5110_FLL2, ARIZONA_FLL_SRC_MCLK1,
0196                     0, 0);
0197     if (ret < 0)
0198         dev_err(component->dev, "Failed to stop FLL2: %d\n", ret);
0199 
0200     return ret;
0201 }
0202 
0203 static const struct snd_soc_ops tm2_aif2_ops = {
0204     .hw_params = tm2_aif2_hw_params,
0205     .hw_free = tm2_aif2_hw_free,
0206 };
0207 
0208 static int tm2_hdmi_hw_params(struct snd_pcm_substream *substream,
0209                   struct snd_pcm_hw_params *params)
0210 {
0211     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0212     struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
0213     unsigned int bfs;
0214     int bitwidth, ret;
0215 
0216     bitwidth = snd_pcm_format_width(params_format(params));
0217     if (bitwidth < 0) {
0218         dev_err(rtd->card->dev, "Invalid bit-width: %d\n", bitwidth);
0219         return bitwidth;
0220     }
0221 
0222     switch (bitwidth) {
0223     case 48:
0224         bfs = 64;
0225         break;
0226     case 16:
0227         bfs = 32;
0228         break;
0229     default:
0230         dev_err(rtd->card->dev, "Unsupported bit-width: %d\n", bitwidth);
0231         return -EINVAL;
0232     }
0233 
0234     switch (params_rate(params)) {
0235     case 48000:
0236     case 96000:
0237     case 192000:
0238         break;
0239     default:
0240         dev_err(rtd->card->dev, "Unsupported sample rate: %d\n",
0241             params_rate(params));
0242         return -EINVAL;
0243     }
0244 
0245     ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_OPCLK,
0246                     0, SAMSUNG_I2S_OPCLK_PCLK);
0247     if (ret < 0)
0248         return ret;
0249 
0250     ret = snd_soc_dai_set_clkdiv(cpu_dai, SAMSUNG_I2S_DIV_BCLK, bfs);
0251     if (ret < 0)
0252         return ret;
0253 
0254     return 0;
0255 }
0256 
0257 static const struct snd_soc_ops tm2_hdmi_ops = {
0258     .hw_params = tm2_hdmi_hw_params,
0259 };
0260 
0261 static int tm2_mic_bias(struct snd_soc_dapm_widget *w,
0262                 struct snd_kcontrol *kcontrol, int event)
0263 {
0264     struct snd_soc_card *card = w->dapm->card;
0265     struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card);
0266 
0267     switch (event) {
0268     case SND_SOC_DAPM_PRE_PMU:
0269         gpiod_set_value_cansleep(priv->gpio_mic_bias,  1);
0270         break;
0271     case SND_SOC_DAPM_POST_PMD:
0272         gpiod_set_value_cansleep(priv->gpio_mic_bias,  0);
0273         break;
0274     }
0275 
0276     return 0;
0277 }
0278 
0279 static int tm2_set_bias_level(struct snd_soc_card *card,
0280                 struct snd_soc_dapm_context *dapm,
0281                 enum snd_soc_bias_level level)
0282 {
0283     struct snd_soc_pcm_runtime *rtd;
0284 
0285     rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]);
0286 
0287     if (dapm->dev != asoc_rtd_to_codec(rtd, 0)->dev)
0288         return 0;
0289 
0290     switch (level) {
0291     case SND_SOC_BIAS_STANDBY:
0292         if (card->dapm.bias_level == SND_SOC_BIAS_OFF)
0293             tm2_start_sysclk(card);
0294         break;
0295     case SND_SOC_BIAS_OFF:
0296         tm2_stop_sysclk(card);
0297         break;
0298     default:
0299         break;
0300     }
0301 
0302     return 0;
0303 }
0304 
0305 static struct snd_soc_aux_dev tm2_speaker_amp_dev;
0306 
0307 static int tm2_late_probe(struct snd_soc_card *card)
0308 {
0309     struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card);
0310     unsigned int ch_map[] = { 0, 1 };
0311     struct snd_soc_dai *amp_pdm_dai;
0312     struct snd_soc_pcm_runtime *rtd;
0313     struct snd_soc_dai *aif1_dai;
0314     struct snd_soc_dai *aif2_dai;
0315     int ret;
0316 
0317     rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[TM2_DAI_AIF1]);
0318     aif1_dai = asoc_rtd_to_codec(rtd, 0);
0319     priv->component = asoc_rtd_to_codec(rtd, 0)->component;
0320 
0321     ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0);
0322     if (ret < 0) {
0323         dev_err(aif1_dai->dev, "Failed to set SYSCLK: %d\n", ret);
0324         return ret;
0325     }
0326 
0327     rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[TM2_DAI_AIF2]);
0328     aif2_dai = asoc_rtd_to_codec(rtd, 0);
0329 
0330     ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0);
0331     if (ret < 0) {
0332         dev_err(aif2_dai->dev, "Failed to set ASYNCCLK: %d\n", ret);
0333         return ret;
0334     }
0335 
0336     amp_pdm_dai = snd_soc_find_dai(&tm2_speaker_amp_dev.dlc);
0337     if (!amp_pdm_dai)
0338         return -ENODEV;
0339 
0340     /* Set the MAX98504 V/I sense PDM Tx DAI channel mapping */
0341     ret = snd_soc_dai_set_channel_map(amp_pdm_dai, ARRAY_SIZE(ch_map),
0342                       ch_map, 0, NULL);
0343     if (ret < 0)
0344         return ret;
0345 
0346     ret = snd_soc_dai_set_tdm_slot(amp_pdm_dai, 0x3, 0x0, 2, 16);
0347     if (ret < 0)
0348         return ret;
0349 
0350     return 0;
0351 }
0352 
0353 static const struct snd_kcontrol_new tm2_controls[] = {
0354     SOC_DAPM_PIN_SWITCH("HP"),
0355     SOC_DAPM_PIN_SWITCH("SPK"),
0356     SOC_DAPM_PIN_SWITCH("RCV"),
0357     SOC_DAPM_PIN_SWITCH("VPS"),
0358     SOC_DAPM_PIN_SWITCH("HDMI"),
0359 
0360     SOC_DAPM_PIN_SWITCH("Main Mic"),
0361     SOC_DAPM_PIN_SWITCH("Sub Mic"),
0362     SOC_DAPM_PIN_SWITCH("Third Mic"),
0363 
0364     SOC_DAPM_PIN_SWITCH("Headset Mic"),
0365 };
0366 
0367 static const struct snd_soc_dapm_widget tm2_dapm_widgets[] = {
0368     SND_SOC_DAPM_HP("HP", NULL),
0369     SND_SOC_DAPM_SPK("SPK", NULL),
0370     SND_SOC_DAPM_SPK("RCV", NULL),
0371     SND_SOC_DAPM_LINE("VPS", NULL),
0372     SND_SOC_DAPM_LINE("HDMI", NULL),
0373 
0374     SND_SOC_DAPM_MIC("Main Mic", tm2_mic_bias),
0375     SND_SOC_DAPM_MIC("Sub Mic", NULL),
0376     SND_SOC_DAPM_MIC("Third Mic", NULL),
0377 
0378     SND_SOC_DAPM_MIC("Headset Mic", NULL),
0379 };
0380 
0381 static const struct snd_soc_component_driver tm2_component = {
0382     .name   = "tm2-audio",
0383 };
0384 
0385 static struct snd_soc_dai_driver tm2_ext_dai[] = {
0386     {
0387         .name = "Voice call",
0388         .playback = {
0389             .channels_min = 1,
0390             .channels_max = 4,
0391             .rate_min = 8000,
0392             .rate_max = 48000,
0393             .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
0394                     SNDRV_PCM_RATE_48000),
0395             .formats = SNDRV_PCM_FMTBIT_S16_LE,
0396         },
0397         .capture = {
0398             .channels_min = 1,
0399             .channels_max = 4,
0400             .rate_min = 8000,
0401             .rate_max = 48000,
0402             .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
0403                     SNDRV_PCM_RATE_48000),
0404             .formats = SNDRV_PCM_FMTBIT_S16_LE,
0405         },
0406     },
0407     {
0408         .name = "Bluetooth",
0409         .playback = {
0410             .channels_min = 1,
0411             .channels_max = 4,
0412             .rate_min = 8000,
0413             .rate_max = 16000,
0414             .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
0415             .formats = SNDRV_PCM_FMTBIT_S16_LE,
0416         },
0417         .capture = {
0418             .channels_min = 1,
0419             .channels_max = 2,
0420             .rate_min = 8000,
0421             .rate_max = 16000,
0422             .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000),
0423             .formats = SNDRV_PCM_FMTBIT_S16_LE,
0424         },
0425     },
0426 };
0427 
0428 SND_SOC_DAILINK_DEFS(aif1,
0429     DAILINK_COMP_ARRAY(COMP_CPU(SAMSUNG_I2S_DAI)),
0430     DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm5110-aif1")),
0431     DAILINK_COMP_ARRAY(COMP_EMPTY()));
0432 
0433 SND_SOC_DAILINK_DEFS(voice,
0434     DAILINK_COMP_ARRAY(COMP_CPU(SAMSUNG_I2S_DAI)),
0435     DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm5110-aif2")),
0436     DAILINK_COMP_ARRAY(COMP_EMPTY()));
0437 
0438 SND_SOC_DAILINK_DEFS(bt,
0439     DAILINK_COMP_ARRAY(COMP_CPU(SAMSUNG_I2S_DAI)),
0440     DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm5110-aif3")),
0441     DAILINK_COMP_ARRAY(COMP_EMPTY()));
0442 
0443 SND_SOC_DAILINK_DEFS(hdmi,
0444     DAILINK_COMP_ARRAY(COMP_EMPTY()),
0445     DAILINK_COMP_ARRAY(COMP_EMPTY()),
0446     DAILINK_COMP_ARRAY(COMP_EMPTY()));
0447 
0448 static struct snd_soc_dai_link tm2_dai_links[] = {
0449     {
0450         .name       = "WM5110 AIF1",
0451         .stream_name    = "HiFi Primary",
0452         .ops        = &tm2_aif1_ops,
0453         .dai_fmt    = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
0454                   SND_SOC_DAIFMT_CBM_CFM,
0455         SND_SOC_DAILINK_REG(aif1),
0456     }, {
0457         .name       = "WM5110 Voice",
0458         .stream_name    = "Voice call",
0459         .ops        = &tm2_aif2_ops,
0460         .dai_fmt    = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
0461                   SND_SOC_DAIFMT_CBM_CFM,
0462         .ignore_suspend = 1,
0463         SND_SOC_DAILINK_REG(voice),
0464     }, {
0465         .name       = "WM5110 BT",
0466         .stream_name    = "Bluetooth",
0467         .dai_fmt    = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
0468                   SND_SOC_DAIFMT_CBM_CFM,
0469         .ignore_suspend = 1,
0470         SND_SOC_DAILINK_REG(bt),
0471     }, {
0472         .name       = "HDMI",
0473         .stream_name    = "i2s1",
0474         .ops        = &tm2_hdmi_ops,
0475         .dai_fmt    = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
0476                   SND_SOC_DAIFMT_CBS_CFS,
0477         SND_SOC_DAILINK_REG(hdmi),
0478     }
0479 };
0480 
0481 static struct snd_soc_card tm2_card = {
0482     .owner          = THIS_MODULE,
0483 
0484     .dai_link       = tm2_dai_links,
0485     .controls       = tm2_controls,
0486     .num_controls       = ARRAY_SIZE(tm2_controls),
0487     .dapm_widgets       = tm2_dapm_widgets,
0488     .num_dapm_widgets   = ARRAY_SIZE(tm2_dapm_widgets),
0489     .aux_dev        = &tm2_speaker_amp_dev,
0490     .num_aux_devs       = 1,
0491 
0492     .late_probe     = tm2_late_probe,
0493     .set_bias_level     = tm2_set_bias_level,
0494 };
0495 
0496 static int tm2_probe(struct platform_device *pdev)
0497 {
0498     struct device_node *cpu_dai_node[2] = {};
0499     struct device_node *codec_dai_node[2] = {};
0500     const char *cells_name = NULL;
0501     struct device *dev = &pdev->dev;
0502     struct snd_soc_card *card = &tm2_card;
0503     struct tm2_machine_priv *priv;
0504     struct snd_soc_dai_link *dai_link;
0505     int num_codecs, ret, i;
0506 
0507     priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0508     if (!priv)
0509         return -ENOMEM;
0510 
0511     snd_soc_card_set_drvdata(card, priv);
0512     card->dev = dev;
0513 
0514     priv->gpio_mic_bias = devm_gpiod_get(dev, "mic-bias", GPIOD_OUT_HIGH);
0515     if (IS_ERR(priv->gpio_mic_bias)) {
0516         dev_err(dev, "Failed to get mic bias gpio\n");
0517         return PTR_ERR(priv->gpio_mic_bias);
0518     }
0519 
0520     ret = snd_soc_of_parse_card_name(card, "model");
0521     if (ret < 0) {
0522         dev_err(dev, "Card name is not specified\n");
0523         return ret;
0524     }
0525 
0526     ret = snd_soc_of_parse_audio_routing(card, "samsung,audio-routing");
0527     if (ret < 0) {
0528         dev_err(dev, "Audio routing is not specified or invalid\n");
0529         return ret;
0530     }
0531 
0532     card->aux_dev[0].dlc.of_node = of_parse_phandle(dev->of_node,
0533                             "audio-amplifier", 0);
0534     if (!card->aux_dev[0].dlc.of_node) {
0535         dev_err(dev, "audio-amplifier property invalid or missing\n");
0536         return -EINVAL;
0537     }
0538 
0539     num_codecs = of_count_phandle_with_args(dev->of_node, "audio-codec",
0540                          NULL);
0541 
0542     /* Skip the HDMI link if not specified in DT */
0543     if (num_codecs > 1) {
0544         card->num_links = ARRAY_SIZE(tm2_dai_links);
0545         cells_name = "#sound-dai-cells";
0546     } else {
0547         card->num_links = ARRAY_SIZE(tm2_dai_links) - 1;
0548     }
0549 
0550     for (i = 0; i < num_codecs; i++) {
0551         struct of_phandle_args args;
0552 
0553         ret = of_parse_phandle_with_args(dev->of_node, "i2s-controller",
0554                          cells_name, i, &args);
0555         if (ret) {
0556             dev_err(dev, "i2s-controller property parse error: %d\n", i);
0557             ret = -EINVAL;
0558             goto dai_node_put;
0559         }
0560         cpu_dai_node[i] = args.np;
0561 
0562         codec_dai_node[i] = of_parse_phandle(dev->of_node,
0563                              "audio-codec", i);
0564         if (!codec_dai_node[i]) {
0565             dev_err(dev, "audio-codec property parse error\n");
0566             ret = -EINVAL;
0567             goto dai_node_put;
0568         }
0569     }
0570 
0571     /* Initialize WM5110 - I2S and HDMI - I2S1 DAI links */
0572     for_each_card_prelinks(card, i, dai_link) {
0573         unsigned int dai_index = 0; /* WM5110 */
0574 
0575         dai_link->cpus->name = NULL;
0576         dai_link->platforms->name = NULL;
0577 
0578         if (num_codecs > 1 && i == card->num_links - 1)
0579             dai_index = 1; /* HDMI */
0580 
0581         dai_link->codecs->of_node = codec_dai_node[dai_index];
0582         dai_link->cpus->of_node = cpu_dai_node[dai_index];
0583         dai_link->platforms->of_node = cpu_dai_node[dai_index];
0584     }
0585 
0586     if (num_codecs > 1) {
0587         struct of_phandle_args args;
0588 
0589         /* HDMI DAI link (I2S1) */
0590         i = card->num_links - 1;
0591 
0592         ret = of_parse_phandle_with_fixed_args(dev->of_node,
0593                         "audio-codec", 0, 1, &args);
0594         if (ret) {
0595             dev_err(dev, "audio-codec property parse error\n");
0596             goto dai_node_put;
0597         }
0598 
0599         ret = snd_soc_get_dai_name(&args, &card->dai_link[i].codecs->dai_name);
0600         if (ret) {
0601             dev_err(dev, "Unable to get codec_dai_name\n");
0602             goto dai_node_put;
0603         }
0604     }
0605 
0606     ret = devm_snd_soc_register_component(dev, &tm2_component,
0607                 tm2_ext_dai, ARRAY_SIZE(tm2_ext_dai));
0608     if (ret < 0) {
0609         dev_err(dev, "Failed to register component: %d\n", ret);
0610         goto dai_node_put;
0611     }
0612 
0613     ret = devm_snd_soc_register_card(dev, card);
0614     if (ret < 0) {
0615         dev_err_probe(dev, ret, "Failed to register card\n");
0616         goto dai_node_put;
0617     }
0618 
0619 dai_node_put:
0620     for (i = 0; i < num_codecs; i++) {
0621         of_node_put(codec_dai_node[i]);
0622         of_node_put(cpu_dai_node[i]);
0623     }
0624 
0625     of_node_put(card->aux_dev[0].dlc.of_node);
0626 
0627     return ret;
0628 }
0629 
0630 static int tm2_pm_prepare(struct device *dev)
0631 {
0632     struct snd_soc_card *card = dev_get_drvdata(dev);
0633 
0634     return tm2_stop_sysclk(card);
0635 }
0636 
0637 static void tm2_pm_complete(struct device *dev)
0638 {
0639     struct snd_soc_card *card = dev_get_drvdata(dev);
0640 
0641     tm2_start_sysclk(card);
0642 }
0643 
0644 static const struct dev_pm_ops tm2_pm_ops = {
0645     .prepare    = tm2_pm_prepare,
0646     .suspend    = snd_soc_suspend,
0647     .resume     = snd_soc_resume,
0648     .complete   = tm2_pm_complete,
0649     .freeze     = snd_soc_suspend,
0650     .thaw       = snd_soc_resume,
0651     .poweroff   = snd_soc_poweroff,
0652     .restore    = snd_soc_resume,
0653 };
0654 
0655 static const struct of_device_id tm2_of_match[] = {
0656     { .compatible = "samsung,tm2-audio" },
0657     { },
0658 };
0659 MODULE_DEVICE_TABLE(of, tm2_of_match);
0660 
0661 static struct platform_driver tm2_driver = {
0662     .driver = {
0663         .name       = "tm2-audio",
0664         .pm     = &tm2_pm_ops,
0665         .of_match_table = tm2_of_match,
0666     },
0667     .probe  = tm2_probe,
0668 };
0669 module_platform_driver(tm2_driver);
0670 
0671 MODULE_AUTHOR("Inha Song <ideal.song@samsung.com>");
0672 MODULE_DESCRIPTION("ALSA SoC Exynos TM2 Audio Support");
0673 MODULE_LICENSE("GPL v2");