0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/module.h>
0010 #include <linux/moduleparam.h>
0011 #include <linux/timer.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/i2c.h>
0015 #include <linux/of_platform.h>
0016 #include <linux/clk.h>
0017 #include <sound/core.h>
0018 #include <sound/pcm.h>
0019 #include <sound/soc.h>
0020
0021 #include <asm/dma.h>
0022 #include <asm/mach-types.h>
0023
0024 struct snd_soc_card_drvdata_davinci {
0025 struct clk *mclk;
0026 unsigned sysclk;
0027 };
0028
0029 static int evm_startup(struct snd_pcm_substream *substream)
0030 {
0031 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0032 struct snd_soc_card *soc_card = rtd->card;
0033 struct snd_soc_card_drvdata_davinci *drvdata =
0034 snd_soc_card_get_drvdata(soc_card);
0035
0036 if (drvdata->mclk)
0037 return clk_prepare_enable(drvdata->mclk);
0038
0039 return 0;
0040 }
0041
0042 static void evm_shutdown(struct snd_pcm_substream *substream)
0043 {
0044 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0045 struct snd_soc_card *soc_card = rtd->card;
0046 struct snd_soc_card_drvdata_davinci *drvdata =
0047 snd_soc_card_get_drvdata(soc_card);
0048
0049 clk_disable_unprepare(drvdata->mclk);
0050 }
0051
0052 static int evm_hw_params(struct snd_pcm_substream *substream,
0053 struct snd_pcm_hw_params *params)
0054 {
0055 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0056 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
0057 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
0058 struct snd_soc_card *soc_card = rtd->card;
0059 int ret = 0;
0060 unsigned sysclk = ((struct snd_soc_card_drvdata_davinci *)
0061 snd_soc_card_get_drvdata(soc_card))->sysclk;
0062
0063
0064 ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
0065 if (ret < 0)
0066 return ret;
0067
0068
0069 ret = snd_soc_dai_set_sysclk(cpu_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
0070 if (ret < 0 && ret != -ENOTSUPP)
0071 return ret;
0072
0073 return 0;
0074 }
0075
0076 static const struct snd_soc_ops evm_ops = {
0077 .startup = evm_startup,
0078 .shutdown = evm_shutdown,
0079 .hw_params = evm_hw_params,
0080 };
0081
0082
0083 static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
0084 SND_SOC_DAPM_HP("Headphone Jack", NULL),
0085 SND_SOC_DAPM_LINE("Line Out", NULL),
0086 SND_SOC_DAPM_MIC("Mic Jack", NULL),
0087 SND_SOC_DAPM_LINE("Line In", NULL),
0088 };
0089
0090
0091 static const struct snd_soc_dapm_route audio_map[] = {
0092
0093 {"Headphone Jack", NULL, "HPLOUT"},
0094 {"Headphone Jack", NULL, "HPROUT"},
0095
0096
0097 {"Line Out", NULL, "LLOUT"},
0098 {"Line Out", NULL, "RLOUT"},
0099
0100
0101 {"MIC3L", NULL, "Mic Bias"},
0102 {"MIC3R", NULL, "Mic Bias"},
0103 {"Mic Bias", NULL, "Mic Jack"},
0104
0105
0106 {"LINE1L", NULL, "Line In"},
0107 {"LINE2L", NULL, "Line In"},
0108 {"LINE1R", NULL, "Line In"},
0109 {"LINE2R", NULL, "Line In"},
0110 };
0111
0112
0113 static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd)
0114 {
0115 struct snd_soc_card *card = rtd->card;
0116 struct device_node *np = card->dev->of_node;
0117 int ret;
0118
0119
0120 snd_soc_dapm_new_controls(&card->dapm, aic3x_dapm_widgets,
0121 ARRAY_SIZE(aic3x_dapm_widgets));
0122
0123 if (np) {
0124 ret = snd_soc_of_parse_audio_routing(card, "ti,audio-routing");
0125 if (ret)
0126 return ret;
0127 } else {
0128
0129 snd_soc_dapm_add_routes(&card->dapm, audio_map,
0130 ARRAY_SIZE(audio_map));
0131 }
0132
0133
0134 snd_soc_dapm_nc_pin(&card->dapm, "MONO_LOUT");
0135 snd_soc_dapm_nc_pin(&card->dapm, "HPLCOM");
0136 snd_soc_dapm_nc_pin(&card->dapm, "HPRCOM");
0137
0138 return 0;
0139 }
0140
0141
0142 SND_SOC_DAILINK_DEFS(dm6446,
0143 DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcbsp")),
0144 DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.1-001b",
0145 "tlv320aic3x-hifi")),
0146 DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcbsp")));
0147
0148 static struct snd_soc_dai_link dm6446_evm_dai = {
0149 .name = "TLV320AIC3X",
0150 .stream_name = "AIC3X",
0151 .init = evm_aic3x_init,
0152 .ops = &evm_ops,
0153 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
0154 SND_SOC_DAIFMT_IB_NF,
0155 SND_SOC_DAILINK_REG(dm6446),
0156 };
0157
0158 SND_SOC_DAILINK_DEFS(dm355,
0159 DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcbsp.1")),
0160 DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.1-001b",
0161 "tlv320aic3x-hifi")),
0162 DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcbsp.1")));
0163
0164 static struct snd_soc_dai_link dm355_evm_dai = {
0165 .name = "TLV320AIC3X",
0166 .stream_name = "AIC3X",
0167 .init = evm_aic3x_init,
0168 .ops = &evm_ops,
0169 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
0170 SND_SOC_DAIFMT_IB_NF,
0171 SND_SOC_DAILINK_REG(dm355),
0172 };
0173
0174 #ifdef CONFIG_SND_SOC_DM365_AIC3X_CODEC
0175 SND_SOC_DAILINK_DEFS(dm365,
0176 DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcbsp")),
0177 DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.1-0018",
0178 "tlv320aic3x-hifi")),
0179 DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcbsp")));
0180 #elif defined(CONFIG_SND_SOC_DM365_VOICE_CODEC)
0181 SND_SOC_DAILINK_DEFS(dm365,
0182 DAILINK_COMP_ARRAY(COMP_CPU("davinci-vcif")),
0183 DAILINK_COMP_ARRAY(COMP_CODEC("cq93vc-codec", "cq93vc-hifi")),
0184 DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-vcif")));
0185 #endif
0186
0187 static struct snd_soc_dai_link dm365_evm_dai = {
0188 #ifdef CONFIG_SND_SOC_DM365_AIC3X_CODEC
0189 .name = "TLV320AIC3X",
0190 .stream_name = "AIC3X",
0191 .init = evm_aic3x_init,
0192 .ops = &evm_ops,
0193 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
0194 SND_SOC_DAIFMT_IB_NF,
0195 SND_SOC_DAILINK_REG(dm365),
0196 #elif defined(CONFIG_SND_SOC_DM365_VOICE_CODEC)
0197 .name = "Voice Codec - CQ93VC",
0198 .stream_name = "CQ93",
0199 SND_SOC_DAILINK_REG(dm365),
0200 #endif
0201 };
0202
0203 SND_SOC_DAILINK_DEFS(dm6467_aic3x,
0204 DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcasp.0")),
0205 DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.0-001a",
0206 "tlv320aic3x-hifi")),
0207 DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcasp.0")));
0208
0209 SND_SOC_DAILINK_DEFS(dm6467_spdif,
0210 DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcasp.1")),
0211 DAILINK_COMP_ARRAY(COMP_CODEC("spdif_dit", "dit-hifi")),
0212 DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcasp.1")));
0213
0214 static struct snd_soc_dai_link dm6467_evm_dai[] = {
0215 {
0216 .name = "TLV320AIC3X",
0217 .stream_name = "AIC3X",
0218 .init = evm_aic3x_init,
0219 .ops = &evm_ops,
0220 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
0221 SND_SOC_DAIFMT_IB_NF,
0222 SND_SOC_DAILINK_REG(dm6467_aic3x),
0223 },
0224 {
0225 .name = "McASP",
0226 .stream_name = "spdif",
0227 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
0228 SND_SOC_DAIFMT_IB_NF,
0229 SND_SOC_DAILINK_REG(dm6467_spdif),
0230 },
0231 };
0232
0233 SND_SOC_DAILINK_DEFS(da830,
0234 DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcasp.1")),
0235 DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.1-0018",
0236 "tlv320aic3x-hifi")),
0237 DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcasp.1")));
0238
0239 static struct snd_soc_dai_link da830_evm_dai = {
0240 .name = "TLV320AIC3X",
0241 .stream_name = "AIC3X",
0242 .init = evm_aic3x_init,
0243 .ops = &evm_ops,
0244 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
0245 SND_SOC_DAIFMT_IB_NF,
0246 SND_SOC_DAILINK_REG(da830),
0247 };
0248
0249 SND_SOC_DAILINK_DEFS(da850,
0250 DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcasp.0")),
0251 DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.1-0018",
0252 "tlv320aic3x-hifi")),
0253 DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcasp.0")));
0254
0255 static struct snd_soc_dai_link da850_evm_dai = {
0256 .name = "TLV320AIC3X",
0257 .stream_name = "AIC3X",
0258 .init = evm_aic3x_init,
0259 .ops = &evm_ops,
0260 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
0261 SND_SOC_DAIFMT_IB_NF,
0262 SND_SOC_DAILINK_REG(da850),
0263 };
0264
0265
0266
0267
0268
0269
0270
0271 static struct snd_soc_card_drvdata_davinci dm6446_snd_soc_card_drvdata = {
0272 .sysclk = 12288000,
0273 };
0274
0275 static struct snd_soc_card dm6446_snd_soc_card_evm = {
0276 .name = "DaVinci DM6446 EVM",
0277 .owner = THIS_MODULE,
0278 .dai_link = &dm6446_evm_dai,
0279 .num_links = 1,
0280 .drvdata = &dm6446_snd_soc_card_drvdata,
0281 };
0282
0283
0284
0285 static struct snd_soc_card_drvdata_davinci dm355_snd_soc_card_drvdata = {
0286 .sysclk = 27000000,
0287 };
0288
0289 static struct snd_soc_card dm355_snd_soc_card_evm = {
0290 .name = "DaVinci DM355 EVM",
0291 .owner = THIS_MODULE,
0292 .dai_link = &dm355_evm_dai,
0293 .num_links = 1,
0294 .drvdata = &dm355_snd_soc_card_drvdata,
0295 };
0296
0297
0298 static struct snd_soc_card_drvdata_davinci dm365_snd_soc_card_drvdata = {
0299 .sysclk = 27000000,
0300 };
0301
0302 static struct snd_soc_card dm365_snd_soc_card_evm = {
0303 .name = "DaVinci DM365 EVM",
0304 .owner = THIS_MODULE,
0305 .dai_link = &dm365_evm_dai,
0306 .num_links = 1,
0307 .drvdata = &dm365_snd_soc_card_drvdata,
0308 };
0309
0310
0311 static struct snd_soc_card_drvdata_davinci dm6467_snd_soc_card_drvdata = {
0312 .sysclk = 27000000,
0313 };
0314
0315 static struct snd_soc_card dm6467_snd_soc_card_evm = {
0316 .name = "DaVinci DM6467 EVM",
0317 .owner = THIS_MODULE,
0318 .dai_link = dm6467_evm_dai,
0319 .num_links = ARRAY_SIZE(dm6467_evm_dai),
0320 .drvdata = &dm6467_snd_soc_card_drvdata,
0321 };
0322
0323 static struct snd_soc_card_drvdata_davinci da830_snd_soc_card_drvdata = {
0324 .sysclk = 24576000,
0325 };
0326
0327 static struct snd_soc_card da830_snd_soc_card = {
0328 .name = "DA830/OMAP-L137 EVM",
0329 .owner = THIS_MODULE,
0330 .dai_link = &da830_evm_dai,
0331 .num_links = 1,
0332 .drvdata = &da830_snd_soc_card_drvdata,
0333 };
0334
0335 static struct snd_soc_card_drvdata_davinci da850_snd_soc_card_drvdata = {
0336 .sysclk = 24576000,
0337 };
0338
0339 static struct snd_soc_card da850_snd_soc_card = {
0340 .name = "DA850/OMAP-L138 EVM",
0341 .owner = THIS_MODULE,
0342 .dai_link = &da850_evm_dai,
0343 .num_links = 1,
0344 .drvdata = &da850_snd_soc_card_drvdata,
0345 };
0346
0347 #if defined(CONFIG_OF)
0348
0349
0350
0351
0352
0353 SND_SOC_DAILINK_DEFS(evm,
0354 DAILINK_COMP_ARRAY(COMP_EMPTY()),
0355 DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "tlv320aic3x-hifi")),
0356 DAILINK_COMP_ARRAY(COMP_EMPTY()));
0357
0358 static struct snd_soc_dai_link evm_dai_tlv320aic3x = {
0359 .name = "TLV320AIC3X",
0360 .stream_name = "AIC3X",
0361 .ops = &evm_ops,
0362 .init = evm_aic3x_init,
0363 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
0364 SND_SOC_DAIFMT_IB_NF,
0365 SND_SOC_DAILINK_REG(evm),
0366 };
0367
0368 static const struct of_device_id davinci_evm_dt_ids[] = {
0369 {
0370 .compatible = "ti,da830-evm-audio",
0371 .data = (void *) &evm_dai_tlv320aic3x,
0372 },
0373 { }
0374 };
0375 MODULE_DEVICE_TABLE(of, davinci_evm_dt_ids);
0376
0377
0378 static struct snd_soc_card evm_soc_card = {
0379 .owner = THIS_MODULE,
0380 .num_links = 1,
0381 };
0382
0383 static int davinci_evm_probe(struct platform_device *pdev)
0384 {
0385 struct device_node *np = pdev->dev.of_node;
0386 const struct of_device_id *match;
0387 struct snd_soc_dai_link *dai;
0388 struct snd_soc_card_drvdata_davinci *drvdata = NULL;
0389 struct clk *mclk;
0390 int ret = 0;
0391
0392 match = of_match_device(of_match_ptr(davinci_evm_dt_ids), &pdev->dev);
0393 if (!match) {
0394 dev_err(&pdev->dev, "Error: No device match found\n");
0395 return -ENODEV;
0396 }
0397
0398 dai = (struct snd_soc_dai_link *) match->data;
0399
0400 evm_soc_card.dai_link = dai;
0401
0402 dai->codecs->of_node = of_parse_phandle(np, "ti,audio-codec", 0);
0403 if (!dai->codecs->of_node)
0404 return -EINVAL;
0405
0406 dai->cpus->of_node = of_parse_phandle(np, "ti,mcasp-controller", 0);
0407 if (!dai->cpus->of_node)
0408 return -EINVAL;
0409
0410 dai->platforms->of_node = dai->cpus->of_node;
0411
0412 evm_soc_card.dev = &pdev->dev;
0413 ret = snd_soc_of_parse_card_name(&evm_soc_card, "ti,model");
0414 if (ret)
0415 return ret;
0416
0417 mclk = devm_clk_get(&pdev->dev, "mclk");
0418 if (PTR_ERR(mclk) == -EPROBE_DEFER) {
0419 return -EPROBE_DEFER;
0420 } else if (IS_ERR(mclk)) {
0421 dev_dbg(&pdev->dev, "mclk not found.\n");
0422 mclk = NULL;
0423 }
0424
0425 drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
0426 if (!drvdata)
0427 return -ENOMEM;
0428
0429 drvdata->mclk = mclk;
0430
0431 ret = of_property_read_u32(np, "ti,codec-clock-rate", &drvdata->sysclk);
0432
0433 if (ret < 0) {
0434 if (!drvdata->mclk) {
0435 dev_err(&pdev->dev,
0436 "No clock or clock rate defined.\n");
0437 return -EINVAL;
0438 }
0439 drvdata->sysclk = clk_get_rate(drvdata->mclk);
0440 } else if (drvdata->mclk) {
0441 unsigned int requestd_rate = drvdata->sysclk;
0442 clk_set_rate(drvdata->mclk, drvdata->sysclk);
0443 drvdata->sysclk = clk_get_rate(drvdata->mclk);
0444 if (drvdata->sysclk != requestd_rate)
0445 dev_warn(&pdev->dev,
0446 "Could not get requested rate %u using %u.\n",
0447 requestd_rate, drvdata->sysclk);
0448 }
0449
0450 snd_soc_card_set_drvdata(&evm_soc_card, drvdata);
0451 ret = devm_snd_soc_register_card(&pdev->dev, &evm_soc_card);
0452
0453 if (ret)
0454 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
0455
0456 return ret;
0457 }
0458
0459 static struct platform_driver davinci_evm_driver = {
0460 .probe = davinci_evm_probe,
0461 .driver = {
0462 .name = "davinci_evm",
0463 .pm = &snd_soc_pm_ops,
0464 .of_match_table = of_match_ptr(davinci_evm_dt_ids),
0465 },
0466 };
0467 #endif
0468
0469 static struct platform_device *evm_snd_device;
0470
0471 static int __init evm_init(void)
0472 {
0473 struct snd_soc_card *evm_snd_dev_data;
0474 int index;
0475 int ret;
0476
0477
0478
0479
0480
0481 #if defined(CONFIG_OF)
0482 if (of_have_populated_dt())
0483 return platform_driver_register(&davinci_evm_driver);
0484 #endif
0485
0486 if (machine_is_davinci_evm()) {
0487 evm_snd_dev_data = &dm6446_snd_soc_card_evm;
0488 index = 0;
0489 } else if (machine_is_davinci_dm355_evm()) {
0490 evm_snd_dev_data = &dm355_snd_soc_card_evm;
0491 index = 1;
0492 } else if (machine_is_davinci_dm365_evm()) {
0493 evm_snd_dev_data = &dm365_snd_soc_card_evm;
0494 index = 0;
0495 } else if (machine_is_davinci_dm6467_evm()) {
0496 evm_snd_dev_data = &dm6467_snd_soc_card_evm;
0497 index = 0;
0498 } else if (machine_is_davinci_da830_evm()) {
0499 evm_snd_dev_data = &da830_snd_soc_card;
0500 index = 1;
0501 } else if (machine_is_davinci_da850_evm()) {
0502 evm_snd_dev_data = &da850_snd_soc_card;
0503 index = 0;
0504 } else
0505 return -EINVAL;
0506
0507 evm_snd_device = platform_device_alloc("soc-audio", index);
0508 if (!evm_snd_device)
0509 return -ENOMEM;
0510
0511 platform_set_drvdata(evm_snd_device, evm_snd_dev_data);
0512 ret = platform_device_add(evm_snd_device);
0513 if (ret)
0514 platform_device_put(evm_snd_device);
0515
0516 return ret;
0517 }
0518
0519 static void __exit evm_exit(void)
0520 {
0521 #if defined(CONFIG_OF)
0522 if (of_have_populated_dt()) {
0523 platform_driver_unregister(&davinci_evm_driver);
0524 return;
0525 }
0526 #endif
0527
0528 platform_device_unregister(evm_snd_device);
0529 }
0530
0531 module_init(evm_init);
0532 module_exit(evm_exit);
0533
0534 MODULE_AUTHOR("Vladimir Barinov");
0535 MODULE_DESCRIPTION("TI DAVINCI EVM ASoC driver");
0536 MODULE_LICENSE("GPL");