0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/clk.h>
0010 #include <linux/i2c.h>
0011 #include <linux/module.h>
0012 #include <linux/of_platform.h>
0013 #if IS_ENABLED(CONFIG_SND_AC97_CODEC)
0014 #include <sound/ac97_codec.h>
0015 #endif
0016 #include <sound/pcm_params.h>
0017 #include <sound/soc.h>
0018 #include <sound/jack.h>
0019 #include <sound/simple_card_utils.h>
0020
0021 #include "fsl_esai.h"
0022 #include "fsl_sai.h"
0023 #include "imx-audmux.h"
0024
0025 #include "../codecs/sgtl5000.h"
0026 #include "../codecs/wm8962.h"
0027 #include "../codecs/wm8960.h"
0028 #include "../codecs/wm8994.h"
0029 #include "../codecs/tlv320aic31xx.h"
0030
0031 #define CS427x_SYSCLK_MCLK 0
0032
0033 #define RX 0
0034 #define TX 1
0035
0036
0037 #define DAI_FMT_BASE (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF)
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047 struct codec_priv {
0048 unsigned long mclk_freq;
0049 unsigned long free_freq;
0050 u32 mclk_id;
0051 u32 fll_id;
0052 u32 pll_id;
0053 };
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064 struct cpu_priv {
0065 unsigned long sysclk_freq[2];
0066 u32 sysclk_dir[2];
0067 u32 sysclk_id[2];
0068 u32 slot_width;
0069 };
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089 struct fsl_asoc_card_priv {
0090 struct snd_soc_dai_link dai_link[3];
0091 struct asoc_simple_jack hp_jack;
0092 struct asoc_simple_jack mic_jack;
0093 struct platform_device *pdev;
0094 struct codec_priv codec_priv;
0095 struct cpu_priv cpu_priv;
0096 struct snd_soc_card card;
0097 u8 streams;
0098 u32 sample_rate;
0099 snd_pcm_format_t sample_format;
0100 u32 asrc_rate;
0101 snd_pcm_format_t asrc_format;
0102 u32 dai_fmt;
0103 char name[32];
0104 };
0105
0106
0107
0108
0109
0110
0111
0112
0113 static const struct snd_soc_dapm_route audio_map[] = {
0114
0115 {"Playback", NULL, "CPU-Playback"},
0116 {"CPU-Capture", NULL, "Capture"},
0117
0118 {"CPU-Playback", NULL, "ASRC-Playback"},
0119 {"ASRC-Capture", NULL, "CPU-Capture"},
0120 };
0121
0122 static const struct snd_soc_dapm_route audio_map_ac97[] = {
0123
0124 {"Playback", NULL, "AC97 Playback"},
0125 {"AC97 Capture", NULL, "Capture"},
0126
0127 {"AC97 Playback", NULL, "ASRC-Playback"},
0128 {"ASRC-Capture", NULL, "AC97 Capture"},
0129 };
0130
0131 static const struct snd_soc_dapm_route audio_map_tx[] = {
0132
0133 {"Playback", NULL, "CPU-Playback"},
0134
0135 {"CPU-Playback", NULL, "ASRC-Playback"},
0136 };
0137
0138 static const struct snd_soc_dapm_route audio_map_rx[] = {
0139
0140 {"CPU-Capture", NULL, "Capture"},
0141
0142 {"ASRC-Capture", NULL, "CPU-Capture"},
0143 };
0144
0145
0146 static const struct snd_soc_dapm_widget fsl_asoc_card_dapm_widgets[] = {
0147 SND_SOC_DAPM_LINE("Line Out Jack", NULL),
0148 SND_SOC_DAPM_LINE("Line In Jack", NULL),
0149 SND_SOC_DAPM_HP("Headphone Jack", NULL),
0150 SND_SOC_DAPM_SPK("Ext Spk", NULL),
0151 SND_SOC_DAPM_MIC("Mic Jack", NULL),
0152 SND_SOC_DAPM_MIC("AMIC", NULL),
0153 SND_SOC_DAPM_MIC("DMIC", NULL),
0154 };
0155
0156 static bool fsl_asoc_card_is_ac97(struct fsl_asoc_card_priv *priv)
0157 {
0158 return priv->dai_fmt == SND_SOC_DAIFMT_AC97;
0159 }
0160
0161 static int fsl_asoc_card_hw_params(struct snd_pcm_substream *substream,
0162 struct snd_pcm_hw_params *params)
0163 {
0164 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0165 struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
0166 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
0167 struct codec_priv *codec_priv = &priv->codec_priv;
0168 struct cpu_priv *cpu_priv = &priv->cpu_priv;
0169 struct device *dev = rtd->card->dev;
0170 unsigned int pll_out;
0171 int ret;
0172
0173 priv->sample_rate = params_rate(params);
0174 priv->sample_format = params_format(params);
0175 priv->streams |= BIT(substream->stream);
0176
0177 if (fsl_asoc_card_is_ac97(priv))
0178 return 0;
0179
0180
0181 ret = snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0), cpu_priv->sysclk_id[tx],
0182 cpu_priv->sysclk_freq[tx],
0183 cpu_priv->sysclk_dir[tx]);
0184 if (ret && ret != -ENOTSUPP) {
0185 dev_err(dev, "failed to set sysclk for cpu dai\n");
0186 goto fail;
0187 }
0188
0189 if (cpu_priv->slot_width) {
0190 ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2,
0191 cpu_priv->slot_width);
0192 if (ret && ret != -ENOTSUPP) {
0193 dev_err(dev, "failed to set TDM slot for cpu dai\n");
0194 goto fail;
0195 }
0196 }
0197
0198
0199 if (codec_priv->pll_id && codec_priv->fll_id) {
0200 if (priv->sample_format == SNDRV_PCM_FORMAT_S24_LE)
0201 pll_out = priv->sample_rate * 384;
0202 else
0203 pll_out = priv->sample_rate * 256;
0204
0205 ret = snd_soc_dai_set_pll(asoc_rtd_to_codec(rtd, 0),
0206 codec_priv->pll_id,
0207 codec_priv->mclk_id,
0208 codec_priv->mclk_freq, pll_out);
0209 if (ret) {
0210 dev_err(dev, "failed to start FLL: %d\n", ret);
0211 goto fail;
0212 }
0213
0214 ret = snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0),
0215 codec_priv->fll_id,
0216 pll_out, SND_SOC_CLOCK_IN);
0217
0218 if (ret && ret != -ENOTSUPP) {
0219 dev_err(dev, "failed to set SYSCLK: %d\n", ret);
0220 goto fail;
0221 }
0222 }
0223
0224 return 0;
0225
0226 fail:
0227 priv->streams &= ~BIT(substream->stream);
0228 return ret;
0229 }
0230
0231 static int fsl_asoc_card_hw_free(struct snd_pcm_substream *substream)
0232 {
0233 struct snd_soc_pcm_runtime *rtd = substream->private_data;
0234 struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
0235 struct codec_priv *codec_priv = &priv->codec_priv;
0236 struct device *dev = rtd->card->dev;
0237 int ret;
0238
0239 priv->streams &= ~BIT(substream->stream);
0240
0241 if (!priv->streams && codec_priv->pll_id && codec_priv->fll_id) {
0242
0243 ret = snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0),
0244 codec_priv->mclk_id,
0245 codec_priv->free_freq,
0246 SND_SOC_CLOCK_IN);
0247 if (ret) {
0248 dev_err(dev, "failed to switch away from FLL: %d\n", ret);
0249 return ret;
0250 }
0251
0252 ret = snd_soc_dai_set_pll(asoc_rtd_to_codec(rtd, 0),
0253 codec_priv->pll_id, 0, 0, 0);
0254 if (ret && ret != -ENOTSUPP) {
0255 dev_err(dev, "failed to stop FLL: %d\n", ret);
0256 return ret;
0257 }
0258 }
0259
0260 return 0;
0261 }
0262
0263 static const struct snd_soc_ops fsl_asoc_card_ops = {
0264 .hw_params = fsl_asoc_card_hw_params,
0265 .hw_free = fsl_asoc_card_hw_free,
0266 };
0267
0268 static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
0269 struct snd_pcm_hw_params *params)
0270 {
0271 struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
0272 struct snd_interval *rate;
0273 struct snd_mask *mask;
0274
0275 rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
0276 rate->max = rate->min = priv->asrc_rate;
0277
0278 mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
0279 snd_mask_none(mask);
0280 snd_mask_set_format(mask, priv->asrc_format);
0281
0282 return 0;
0283 }
0284
0285 SND_SOC_DAILINK_DEFS(hifi,
0286 DAILINK_COMP_ARRAY(COMP_EMPTY()),
0287 DAILINK_COMP_ARRAY(COMP_EMPTY()),
0288 DAILINK_COMP_ARRAY(COMP_EMPTY()));
0289
0290 SND_SOC_DAILINK_DEFS(hifi_fe,
0291 DAILINK_COMP_ARRAY(COMP_EMPTY()),
0292 DAILINK_COMP_ARRAY(COMP_DUMMY()),
0293 DAILINK_COMP_ARRAY(COMP_EMPTY()));
0294
0295 SND_SOC_DAILINK_DEFS(hifi_be,
0296 DAILINK_COMP_ARRAY(COMP_EMPTY()),
0297 DAILINK_COMP_ARRAY(COMP_EMPTY()),
0298 DAILINK_COMP_ARRAY(COMP_DUMMY()));
0299
0300 static struct snd_soc_dai_link fsl_asoc_card_dai[] = {
0301
0302 {
0303 .name = "HiFi",
0304 .stream_name = "HiFi",
0305 .ops = &fsl_asoc_card_ops,
0306 SND_SOC_DAILINK_REG(hifi),
0307 },
0308
0309 {
0310 .name = "HiFi-ASRC-FE",
0311 .stream_name = "HiFi-ASRC-FE",
0312 .dpcm_playback = 1,
0313 .dpcm_capture = 1,
0314 .dynamic = 1,
0315 SND_SOC_DAILINK_REG(hifi_fe),
0316 },
0317 {
0318 .name = "HiFi-ASRC-BE",
0319 .stream_name = "HiFi-ASRC-BE",
0320 .be_hw_params_fixup = be_hw_params_fixup,
0321 .ops = &fsl_asoc_card_ops,
0322 .dpcm_playback = 1,
0323 .dpcm_capture = 1,
0324 .no_pcm = 1,
0325 SND_SOC_DAILINK_REG(hifi_be),
0326 },
0327 };
0328
0329 static int fsl_asoc_card_audmux_init(struct device_node *np,
0330 struct fsl_asoc_card_priv *priv)
0331 {
0332 struct device *dev = &priv->pdev->dev;
0333 u32 int_ptcr = 0, ext_ptcr = 0;
0334 int int_port, ext_port;
0335 int ret;
0336
0337 ret = of_property_read_u32(np, "mux-int-port", &int_port);
0338 if (ret) {
0339 dev_err(dev, "mux-int-port missing or invalid\n");
0340 return ret;
0341 }
0342 ret = of_property_read_u32(np, "mux-ext-port", &ext_port);
0343 if (ret) {
0344 dev_err(dev, "mux-ext-port missing or invalid\n");
0345 return ret;
0346 }
0347
0348
0349
0350
0351
0352 int_port--;
0353 ext_port--;
0354
0355
0356
0357
0358
0359
0360 switch (priv->dai_fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
0361 case SND_SOC_DAIFMT_CBP_CFP:
0362 int_ptcr = IMX_AUDMUX_V2_PTCR_RFSEL(8 | ext_port) |
0363 IMX_AUDMUX_V2_PTCR_RCSEL(8 | ext_port) |
0364 IMX_AUDMUX_V2_PTCR_TFSEL(ext_port) |
0365 IMX_AUDMUX_V2_PTCR_TCSEL(ext_port) |
0366 IMX_AUDMUX_V2_PTCR_RFSDIR |
0367 IMX_AUDMUX_V2_PTCR_RCLKDIR |
0368 IMX_AUDMUX_V2_PTCR_TFSDIR |
0369 IMX_AUDMUX_V2_PTCR_TCLKDIR;
0370 break;
0371 case SND_SOC_DAIFMT_CBP_CFC:
0372 int_ptcr = IMX_AUDMUX_V2_PTCR_RCSEL(8 | ext_port) |
0373 IMX_AUDMUX_V2_PTCR_TCSEL(ext_port) |
0374 IMX_AUDMUX_V2_PTCR_RCLKDIR |
0375 IMX_AUDMUX_V2_PTCR_TCLKDIR;
0376 ext_ptcr = IMX_AUDMUX_V2_PTCR_RFSEL(8 | int_port) |
0377 IMX_AUDMUX_V2_PTCR_TFSEL(int_port) |
0378 IMX_AUDMUX_V2_PTCR_RFSDIR |
0379 IMX_AUDMUX_V2_PTCR_TFSDIR;
0380 break;
0381 case SND_SOC_DAIFMT_CBC_CFP:
0382 int_ptcr = IMX_AUDMUX_V2_PTCR_RFSEL(8 | ext_port) |
0383 IMX_AUDMUX_V2_PTCR_TFSEL(ext_port) |
0384 IMX_AUDMUX_V2_PTCR_RFSDIR |
0385 IMX_AUDMUX_V2_PTCR_TFSDIR;
0386 ext_ptcr = IMX_AUDMUX_V2_PTCR_RCSEL(8 | int_port) |
0387 IMX_AUDMUX_V2_PTCR_TCSEL(int_port) |
0388 IMX_AUDMUX_V2_PTCR_RCLKDIR |
0389 IMX_AUDMUX_V2_PTCR_TCLKDIR;
0390 break;
0391 case SND_SOC_DAIFMT_CBC_CFC:
0392 ext_ptcr = IMX_AUDMUX_V2_PTCR_RFSEL(8 | int_port) |
0393 IMX_AUDMUX_V2_PTCR_RCSEL(8 | int_port) |
0394 IMX_AUDMUX_V2_PTCR_TFSEL(int_port) |
0395 IMX_AUDMUX_V2_PTCR_TCSEL(int_port) |
0396 IMX_AUDMUX_V2_PTCR_RFSDIR |
0397 IMX_AUDMUX_V2_PTCR_RCLKDIR |
0398 IMX_AUDMUX_V2_PTCR_TFSDIR |
0399 IMX_AUDMUX_V2_PTCR_TCLKDIR;
0400 break;
0401 default:
0402 if (!fsl_asoc_card_is_ac97(priv))
0403 return -EINVAL;
0404 }
0405
0406 if (fsl_asoc_card_is_ac97(priv)) {
0407 int_ptcr = IMX_AUDMUX_V2_PTCR_SYN |
0408 IMX_AUDMUX_V2_PTCR_TCSEL(ext_port) |
0409 IMX_AUDMUX_V2_PTCR_TCLKDIR;
0410 ext_ptcr = IMX_AUDMUX_V2_PTCR_SYN |
0411 IMX_AUDMUX_V2_PTCR_TFSEL(int_port) |
0412 IMX_AUDMUX_V2_PTCR_TFSDIR;
0413 }
0414
0415
0416 if (!fsl_asoc_card_is_ac97(priv)) {
0417 unsigned int pdcr =
0418 IMX_AUDMUX_V2_PDCR_RXDSEL(ext_port);
0419
0420 ret = imx_audmux_v2_configure_port(int_port, 0,
0421 pdcr);
0422 if (ret) {
0423 dev_err(dev, "audmux internal port setup failed\n");
0424 return ret;
0425 }
0426 }
0427
0428 ret = imx_audmux_v2_configure_port(int_port, int_ptcr,
0429 IMX_AUDMUX_V2_PDCR_RXDSEL(ext_port));
0430 if (ret) {
0431 dev_err(dev, "audmux internal port setup failed\n");
0432 return ret;
0433 }
0434
0435 if (!fsl_asoc_card_is_ac97(priv)) {
0436 unsigned int pdcr =
0437 IMX_AUDMUX_V2_PDCR_RXDSEL(int_port);
0438
0439 ret = imx_audmux_v2_configure_port(ext_port, 0,
0440 pdcr);
0441 if (ret) {
0442 dev_err(dev, "audmux external port setup failed\n");
0443 return ret;
0444 }
0445 }
0446
0447 ret = imx_audmux_v2_configure_port(ext_port, ext_ptcr,
0448 IMX_AUDMUX_V2_PDCR_RXDSEL(int_port));
0449 if (ret) {
0450 dev_err(dev, "audmux external port setup failed\n");
0451 return ret;
0452 }
0453
0454 return 0;
0455 }
0456
0457 static int hp_jack_event(struct notifier_block *nb, unsigned long event,
0458 void *data)
0459 {
0460 struct snd_soc_jack *jack = (struct snd_soc_jack *)data;
0461 struct snd_soc_dapm_context *dapm = &jack->card->dapm;
0462
0463 if (event & SND_JACK_HEADPHONE)
0464
0465 return snd_soc_dapm_disable_pin(dapm, "Ext Spk");
0466 else
0467 return snd_soc_dapm_enable_pin(dapm, "Ext Spk");
0468 }
0469
0470 static struct notifier_block hp_jack_nb = {
0471 .notifier_call = hp_jack_event,
0472 };
0473
0474 static int mic_jack_event(struct notifier_block *nb, unsigned long event,
0475 void *data)
0476 {
0477 struct snd_soc_jack *jack = (struct snd_soc_jack *)data;
0478 struct snd_soc_dapm_context *dapm = &jack->card->dapm;
0479
0480 if (event & SND_JACK_MICROPHONE)
0481
0482 return snd_soc_dapm_disable_pin(dapm, "DMIC");
0483 else
0484 return snd_soc_dapm_enable_pin(dapm, "DMIC");
0485 }
0486
0487 static struct notifier_block mic_jack_nb = {
0488 .notifier_call = mic_jack_event,
0489 };
0490
0491 static int fsl_asoc_card_late_probe(struct snd_soc_card *card)
0492 {
0493 struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(card);
0494 struct snd_soc_pcm_runtime *rtd = list_first_entry(
0495 &card->rtd_list, struct snd_soc_pcm_runtime, list);
0496 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
0497 struct codec_priv *codec_priv = &priv->codec_priv;
0498 struct device *dev = card->dev;
0499 int ret;
0500
0501 if (fsl_asoc_card_is_ac97(priv)) {
0502 #if IS_ENABLED(CONFIG_SND_AC97_CODEC)
0503 struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
0504 struct snd_ac97 *ac97 = snd_soc_component_get_drvdata(component);
0505
0506
0507
0508
0509
0510
0511 snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS,
0512 AC97_EA_SPSA_SLOT_MASK, AC97_EA_SPSA_3_4);
0513 #endif
0514
0515 return 0;
0516 }
0517
0518 ret = snd_soc_dai_set_sysclk(codec_dai, codec_priv->mclk_id,
0519 codec_priv->mclk_freq, SND_SOC_CLOCK_IN);
0520 if (ret && ret != -ENOTSUPP) {
0521 dev_err(dev, "failed to set sysclk in %s\n", __func__);
0522 return ret;
0523 }
0524
0525 return 0;
0526 }
0527
0528 static int fsl_asoc_card_probe(struct platform_device *pdev)
0529 {
0530 struct device_node *cpu_np, *codec_np, *asrc_np;
0531 struct device_node *np = pdev->dev.of_node;
0532 struct platform_device *asrc_pdev = NULL;
0533 struct device_node *bitclkprovider = NULL;
0534 struct device_node *frameprovider = NULL;
0535 struct platform_device *cpu_pdev;
0536 struct fsl_asoc_card_priv *priv;
0537 struct device *codec_dev = NULL;
0538 const char *codec_dai_name;
0539 const char *codec_dev_name;
0540 u32 asrc_fmt = 0;
0541 u32 width;
0542 int ret;
0543
0544 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
0545 if (!priv)
0546 return -ENOMEM;
0547
0548 cpu_np = of_parse_phandle(np, "audio-cpu", 0);
0549
0550 if (!cpu_np)
0551 cpu_np = of_parse_phandle(np, "ssi-controller", 0);
0552 if (!cpu_np) {
0553 dev_err(&pdev->dev, "CPU phandle missing or invalid\n");
0554 ret = -EINVAL;
0555 goto fail;
0556 }
0557
0558 cpu_pdev = of_find_device_by_node(cpu_np);
0559 if (!cpu_pdev) {
0560 dev_err(&pdev->dev, "failed to find CPU DAI device\n");
0561 ret = -EINVAL;
0562 goto fail;
0563 }
0564
0565 codec_np = of_parse_phandle(np, "audio-codec", 0);
0566 if (codec_np) {
0567 struct platform_device *codec_pdev;
0568 struct i2c_client *codec_i2c;
0569
0570 codec_i2c = of_find_i2c_device_by_node(codec_np);
0571 if (codec_i2c) {
0572 codec_dev = &codec_i2c->dev;
0573 codec_dev_name = codec_i2c->name;
0574 }
0575 if (!codec_dev) {
0576 codec_pdev = of_find_device_by_node(codec_np);
0577 if (codec_pdev) {
0578 codec_dev = &codec_pdev->dev;
0579 codec_dev_name = codec_pdev->name;
0580 }
0581 }
0582 }
0583
0584 asrc_np = of_parse_phandle(np, "audio-asrc", 0);
0585 if (asrc_np)
0586 asrc_pdev = of_find_device_by_node(asrc_np);
0587
0588
0589 if (codec_dev) {
0590 struct clk *codec_clk = clk_get(codec_dev, NULL);
0591
0592 if (!IS_ERR(codec_clk)) {
0593 priv->codec_priv.mclk_freq = clk_get_rate(codec_clk);
0594 clk_put(codec_clk);
0595 }
0596 }
0597
0598
0599 priv->sample_rate = 44100;
0600 priv->sample_format = SNDRV_PCM_FORMAT_S16_LE;
0601
0602
0603 priv->dai_fmt = DAI_FMT_BASE;
0604
0605 memcpy(priv->dai_link, fsl_asoc_card_dai,
0606 sizeof(struct snd_soc_dai_link) * ARRAY_SIZE(priv->dai_link));
0607
0608 priv->card.dapm_routes = audio_map;
0609 priv->card.num_dapm_routes = ARRAY_SIZE(audio_map);
0610
0611 if (of_device_is_compatible(np, "fsl,imx-audio-cs42888")) {
0612 codec_dai_name = "cs42888";
0613 priv->cpu_priv.sysclk_freq[TX] = priv->codec_priv.mclk_freq;
0614 priv->cpu_priv.sysclk_freq[RX] = priv->codec_priv.mclk_freq;
0615 priv->cpu_priv.sysclk_dir[TX] = SND_SOC_CLOCK_OUT;
0616 priv->cpu_priv.sysclk_dir[RX] = SND_SOC_CLOCK_OUT;
0617 priv->cpu_priv.slot_width = 32;
0618 priv->dai_fmt |= SND_SOC_DAIFMT_CBC_CFC;
0619 } else if (of_device_is_compatible(np, "fsl,imx-audio-cs427x")) {
0620 codec_dai_name = "cs4271-hifi";
0621 priv->codec_priv.mclk_id = CS427x_SYSCLK_MCLK;
0622 priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP;
0623 } else if (of_device_is_compatible(np, "fsl,imx-audio-sgtl5000")) {
0624 codec_dai_name = "sgtl5000";
0625 priv->codec_priv.mclk_id = SGTL5000_SYSCLK;
0626 priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP;
0627 } else if (of_device_is_compatible(np, "fsl,imx-audio-tlv320aic32x4")) {
0628 codec_dai_name = "tlv320aic32x4-hifi";
0629 priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP;
0630 } else if (of_device_is_compatible(np, "fsl,imx-audio-tlv320aic31xx")) {
0631 codec_dai_name = "tlv320dac31xx-hifi";
0632 priv->dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
0633 priv->dai_link[1].dpcm_capture = 0;
0634 priv->dai_link[2].dpcm_capture = 0;
0635 priv->cpu_priv.sysclk_dir[TX] = SND_SOC_CLOCK_OUT;
0636 priv->cpu_priv.sysclk_dir[RX] = SND_SOC_CLOCK_OUT;
0637 priv->card.dapm_routes = audio_map_tx;
0638 priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx);
0639 } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8962")) {
0640 codec_dai_name = "wm8962";
0641 priv->codec_priv.mclk_id = WM8962_SYSCLK_MCLK;
0642 priv->codec_priv.fll_id = WM8962_SYSCLK_FLL;
0643 priv->codec_priv.pll_id = WM8962_FLL;
0644 priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP;
0645 } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8960")) {
0646 codec_dai_name = "wm8960-hifi";
0647 priv->codec_priv.fll_id = WM8960_SYSCLK_AUTO;
0648 priv->codec_priv.pll_id = WM8960_SYSCLK_AUTO;
0649 priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP;
0650 } else if (of_device_is_compatible(np, "fsl,imx-audio-ac97")) {
0651 codec_dai_name = "ac97-hifi";
0652 priv->dai_fmt = SND_SOC_DAIFMT_AC97;
0653 priv->card.dapm_routes = audio_map_ac97;
0654 priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_ac97);
0655 } else if (of_device_is_compatible(np, "fsl,imx-audio-mqs")) {
0656 codec_dai_name = "fsl-mqs-dai";
0657 priv->dai_fmt = SND_SOC_DAIFMT_LEFT_J |
0658 SND_SOC_DAIFMT_CBC_CFC |
0659 SND_SOC_DAIFMT_NB_NF;
0660 priv->dai_link[1].dpcm_capture = 0;
0661 priv->dai_link[2].dpcm_capture = 0;
0662 priv->card.dapm_routes = audio_map_tx;
0663 priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx);
0664 } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8524")) {
0665 codec_dai_name = "wm8524-hifi";
0666 priv->dai_fmt |= SND_SOC_DAIFMT_CBC_CFC;
0667 priv->dai_link[1].dpcm_capture = 0;
0668 priv->dai_link[2].dpcm_capture = 0;
0669 priv->cpu_priv.slot_width = 32;
0670 priv->card.dapm_routes = audio_map_tx;
0671 priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx);
0672 } else if (of_device_is_compatible(np, "fsl,imx-audio-si476x")) {
0673 codec_dai_name = "si476x-codec";
0674 priv->dai_fmt |= SND_SOC_DAIFMT_CBC_CFC;
0675 priv->card.dapm_routes = audio_map_rx;
0676 priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_rx);
0677 } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8958")) {
0678 codec_dai_name = "wm8994-aif1";
0679 priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP;
0680 priv->codec_priv.mclk_id = WM8994_FLL_SRC_MCLK1;
0681 priv->codec_priv.fll_id = WM8994_SYSCLK_FLL1;
0682 priv->codec_priv.pll_id = WM8994_FLL1;
0683 priv->codec_priv.free_freq = priv->codec_priv.mclk_freq;
0684 priv->card.dapm_routes = NULL;
0685 priv->card.num_dapm_routes = 0;
0686 } else {
0687 dev_err(&pdev->dev, "unknown Device Tree compatible\n");
0688 ret = -EINVAL;
0689 goto asrc_fail;
0690 }
0691
0692
0693
0694
0695
0696 of_property_read_u32(np, "mclk-id", &priv->codec_priv.mclk_id);
0697
0698
0699 snd_soc_daifmt_parse_clock_provider_as_phandle(np, NULL, &bitclkprovider, &frameprovider);
0700 if (bitclkprovider || frameprovider) {
0701 unsigned int daifmt = snd_soc_daifmt_parse_format(np, NULL);
0702
0703 if (codec_np == bitclkprovider)
0704 daifmt |= (codec_np == frameprovider) ?
0705 SND_SOC_DAIFMT_CBP_CFP : SND_SOC_DAIFMT_CBP_CFC;
0706 else
0707 daifmt |= (codec_np == frameprovider) ?
0708 SND_SOC_DAIFMT_CBC_CFP : SND_SOC_DAIFMT_CBC_CFC;
0709
0710
0711 priv->dai_fmt = daifmt;
0712 }
0713
0714
0715 if (priv->dai_fmt & SND_SOC_DAIFMT_CBP_CFP) {
0716 priv->cpu_priv.sysclk_dir[TX] = SND_SOC_CLOCK_IN;
0717 priv->cpu_priv.sysclk_dir[RX] = SND_SOC_CLOCK_IN;
0718 }
0719
0720 of_node_put(bitclkprovider);
0721 of_node_put(frameprovider);
0722
0723 if (!fsl_asoc_card_is_ac97(priv) && !codec_dev) {
0724 dev_dbg(&pdev->dev, "failed to find codec device\n");
0725 ret = -EPROBE_DEFER;
0726 goto asrc_fail;
0727 }
0728
0729
0730 if (of_node_name_eq(cpu_np, "ssi")) {
0731
0732 ret = fsl_asoc_card_audmux_init(np, priv);
0733 if (ret) {
0734 dev_err(&pdev->dev, "failed to init audmux\n");
0735 goto asrc_fail;
0736 }
0737 } else if (of_node_name_eq(cpu_np, "esai")) {
0738 struct clk *esai_clk = clk_get(&cpu_pdev->dev, "extal");
0739
0740 if (!IS_ERR(esai_clk)) {
0741 priv->cpu_priv.sysclk_freq[TX] = clk_get_rate(esai_clk);
0742 priv->cpu_priv.sysclk_freq[RX] = clk_get_rate(esai_clk);
0743 clk_put(esai_clk);
0744 } else if (PTR_ERR(esai_clk) == -EPROBE_DEFER) {
0745 ret = -EPROBE_DEFER;
0746 goto asrc_fail;
0747 }
0748
0749 priv->cpu_priv.sysclk_id[1] = ESAI_HCKT_EXTAL;
0750 priv->cpu_priv.sysclk_id[0] = ESAI_HCKR_EXTAL;
0751 } else if (of_node_name_eq(cpu_np, "sai")) {
0752 priv->cpu_priv.sysclk_id[1] = FSL_SAI_CLK_MAST1;
0753 priv->cpu_priv.sysclk_id[0] = FSL_SAI_CLK_MAST1;
0754 }
0755
0756
0757 priv->pdev = pdev;
0758 priv->card.dev = &pdev->dev;
0759 priv->card.owner = THIS_MODULE;
0760 ret = snd_soc_of_parse_card_name(&priv->card, "model");
0761 if (ret) {
0762 snprintf(priv->name, sizeof(priv->name), "%s-audio",
0763 fsl_asoc_card_is_ac97(priv) ? "ac97" : codec_dev_name);
0764 priv->card.name = priv->name;
0765 }
0766 priv->card.dai_link = priv->dai_link;
0767 priv->card.late_probe = fsl_asoc_card_late_probe;
0768 priv->card.dapm_widgets = fsl_asoc_card_dapm_widgets;
0769 priv->card.num_dapm_widgets = ARRAY_SIZE(fsl_asoc_card_dapm_widgets);
0770
0771
0772 if (!asrc_pdev)
0773 priv->card.num_dapm_routes /= 2;
0774
0775 if (of_property_read_bool(np, "audio-routing")) {
0776 ret = snd_soc_of_parse_audio_routing(&priv->card, "audio-routing");
0777 if (ret) {
0778 dev_err(&pdev->dev, "failed to parse audio-routing: %d\n", ret);
0779 goto asrc_fail;
0780 }
0781 }
0782
0783
0784 priv->dai_link[0].cpus->of_node = cpu_np;
0785 priv->dai_link[0].codecs->dai_name = codec_dai_name;
0786
0787 if (!fsl_asoc_card_is_ac97(priv))
0788 priv->dai_link[0].codecs->of_node = codec_np;
0789 else {
0790 u32 idx;
0791
0792 ret = of_property_read_u32(cpu_np, "cell-index", &idx);
0793 if (ret) {
0794 dev_err(&pdev->dev,
0795 "cannot get CPU index property\n");
0796 goto asrc_fail;
0797 }
0798
0799 priv->dai_link[0].codecs->name =
0800 devm_kasprintf(&pdev->dev, GFP_KERNEL,
0801 "ac97-codec.%u",
0802 (unsigned int)idx);
0803 if (!priv->dai_link[0].codecs->name) {
0804 ret = -ENOMEM;
0805 goto asrc_fail;
0806 }
0807 }
0808
0809 priv->dai_link[0].platforms->of_node = cpu_np;
0810 priv->dai_link[0].dai_fmt = priv->dai_fmt;
0811 priv->card.num_links = 1;
0812
0813 if (asrc_pdev) {
0814
0815 priv->dai_link[1].cpus->of_node = asrc_np;
0816 priv->dai_link[1].platforms->of_node = asrc_np;
0817 priv->dai_link[2].codecs->dai_name = codec_dai_name;
0818 priv->dai_link[2].codecs->of_node = codec_np;
0819 priv->dai_link[2].codecs->name =
0820 priv->dai_link[0].codecs->name;
0821 priv->dai_link[2].cpus->of_node = cpu_np;
0822 priv->dai_link[2].dai_fmt = priv->dai_fmt;
0823 priv->card.num_links = 3;
0824
0825 ret = of_property_read_u32(asrc_np, "fsl,asrc-rate",
0826 &priv->asrc_rate);
0827 if (ret) {
0828 dev_err(&pdev->dev, "failed to get output rate\n");
0829 ret = -EINVAL;
0830 goto asrc_fail;
0831 }
0832
0833 ret = of_property_read_u32(asrc_np, "fsl,asrc-format", &asrc_fmt);
0834 priv->asrc_format = (__force snd_pcm_format_t)asrc_fmt;
0835 if (ret) {
0836
0837 ret = of_property_read_u32(asrc_np, "fsl,asrc-width",
0838 &width);
0839 if (ret) {
0840 dev_err(&pdev->dev,
0841 "failed to decide output format\n");
0842 goto asrc_fail;
0843 }
0844
0845 if (width == 24)
0846 priv->asrc_format = SNDRV_PCM_FORMAT_S24_LE;
0847 else
0848 priv->asrc_format = SNDRV_PCM_FORMAT_S16_LE;
0849 }
0850 }
0851
0852
0853 platform_set_drvdata(pdev, priv);
0854 snd_soc_card_set_drvdata(&priv->card, priv);
0855
0856 ret = devm_snd_soc_register_card(&pdev->dev, &priv->card);
0857 if (ret) {
0858 dev_err_probe(&pdev->dev, ret, "snd_soc_register_card failed\n");
0859 goto asrc_fail;
0860 }
0861
0862
0863
0864
0865
0866
0867
0868
0869
0870 if (of_property_read_bool(np, "hp-det-gpio")) {
0871 ret = asoc_simple_init_jack(&priv->card, &priv->hp_jack,
0872 1, NULL, "Headphone Jack");
0873 if (ret)
0874 goto asrc_fail;
0875
0876 snd_soc_jack_notifier_register(&priv->hp_jack.jack, &hp_jack_nb);
0877 }
0878
0879 if (of_property_read_bool(np, "mic-det-gpio")) {
0880 ret = asoc_simple_init_jack(&priv->card, &priv->mic_jack,
0881 0, NULL, "Mic Jack");
0882 if (ret)
0883 goto asrc_fail;
0884
0885 snd_soc_jack_notifier_register(&priv->mic_jack.jack, &mic_jack_nb);
0886 }
0887
0888 asrc_fail:
0889 of_node_put(asrc_np);
0890 of_node_put(codec_np);
0891 put_device(&cpu_pdev->dev);
0892 fail:
0893 of_node_put(cpu_np);
0894
0895 return ret;
0896 }
0897
0898 static const struct of_device_id fsl_asoc_card_dt_ids[] = {
0899 { .compatible = "fsl,imx-audio-ac97", },
0900 { .compatible = "fsl,imx-audio-cs42888", },
0901 { .compatible = "fsl,imx-audio-cs427x", },
0902 { .compatible = "fsl,imx-audio-tlv320aic32x4", },
0903 { .compatible = "fsl,imx-audio-tlv320aic31xx", },
0904 { .compatible = "fsl,imx-audio-sgtl5000", },
0905 { .compatible = "fsl,imx-audio-wm8962", },
0906 { .compatible = "fsl,imx-audio-wm8960", },
0907 { .compatible = "fsl,imx-audio-mqs", },
0908 { .compatible = "fsl,imx-audio-wm8524", },
0909 { .compatible = "fsl,imx-audio-si476x", },
0910 { .compatible = "fsl,imx-audio-wm8958", },
0911 {}
0912 };
0913 MODULE_DEVICE_TABLE(of, fsl_asoc_card_dt_ids);
0914
0915 static struct platform_driver fsl_asoc_card_driver = {
0916 .probe = fsl_asoc_card_probe,
0917 .driver = {
0918 .name = "fsl-asoc-card",
0919 .pm = &snd_soc_pm_ops,
0920 .of_match_table = fsl_asoc_card_dt_ids,
0921 },
0922 };
0923 module_platform_driver(fsl_asoc_card_driver);
0924
0925 MODULE_DESCRIPTION("Freescale Generic ASoC Sound Card driver with ASRC");
0926 MODULE_AUTHOR("Nicolin Chen <nicoleotsuka@gmail.com>");
0927 MODULE_ALIAS("platform:fsl-asoc-card");
0928 MODULE_LICENSE("GPL");