diff options
Diffstat (limited to 'sound/soc/davinci/davinci-evm.c')
-rw-r--r-- | sound/soc/davinci/davinci-evm.c | 188 |
1 files changed, 166 insertions, 22 deletions
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index fd7c45b..623eb5e 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c @@ -16,6 +16,7 @@ #include <linux/platform_device.h> #include <linux/platform_data/edma.h> #include <linux/i2c.h> +#include <linux/of_platform.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/soc.h> @@ -23,10 +24,16 @@ #include <asm/dma.h> #include <asm/mach-types.h> +#include <linux/edma.h> + #include "davinci-pcm.h" #include "davinci-i2s.h" #include "davinci-mcasp.h" +struct snd_soc_card_drvdata_davinci { + unsigned sysclk; +}; + #define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \ SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF) static int evm_hw_params(struct snd_pcm_substream *substream, @@ -35,27 +42,11 @@ static int evm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->codec_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_card *soc_card = codec->card; int ret = 0; - unsigned sysclk; - - /* ASP1 on DM355 EVM is clocked by an external oscillator */ - if (machine_is_davinci_dm355_evm() || machine_is_davinci_dm6467_evm() || - machine_is_davinci_dm365_evm()) - sysclk = 27000000; - - /* ASP0 in DM6446 EVM is clocked by U55, as configured by - * board-dm644x-evm.c using GPIOs from U18. There are six - * options; here we "know" we use a 48 KHz sample rate. - */ - else if (machine_is_davinci_evm()) - sysclk = 12288000; - - else if (machine_is_davinci_da830_evm() || - machine_is_davinci_da850_evm()) - sysclk = 24576000; - - else - return -EINVAL; + unsigned sysclk = ((struct snd_soc_card_drvdata_davinci *) + snd_soc_card_get_drvdata(soc_card))->sysclk; /* set codec DAI configuration */ ret = snd_soc_dai_set_fmt(codec_dai, AUDIO_FORMAT); @@ -133,13 +124,22 @@ static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; + struct device_node *np = codec->card->dev->of_node; + int ret; /* Add davinci-evm specific widgets */ snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets, ARRAY_SIZE(aic3x_dapm_widgets)); - /* Set up davinci-evm specific audio path audio_map */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); + if (np) { + ret = snd_soc_of_parse_audio_routing(codec->card, + "ti,audio-routing"); + if (ret) + return ret; + } else { + /* Set up davinci-evm specific audio path audio_map */ + snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); + } /* not connected */ snd_soc_dapm_disable_pin(dapm, "MONO_LOUT"); @@ -243,35 +243,65 @@ static struct snd_soc_dai_link da850_evm_dai = { }; /* davinci dm6446 evm audio machine driver */ +/* + * ASP0 in DM6446 EVM is clocked by U55, as configured by + * board-dm644x-evm.c using GPIOs from U18. There are six + * options; here we "know" we use a 48 KHz sample rate. + */ +static struct snd_soc_card_drvdata_davinci dm6446_snd_soc_card_drvdata = { + .sysclk = 12288000, +}; + static struct snd_soc_card dm6446_snd_soc_card_evm = { .name = "DaVinci DM6446 EVM", .owner = THIS_MODULE, .dai_link = &dm6446_evm_dai, .num_links = 1, + .drvdata = &dm6446_snd_soc_card_drvdata, }; /* davinci dm355 evm audio machine driver */ +/* ASP1 on DM355 EVM is clocked by an external oscillator */ +static struct snd_soc_card_drvdata_davinci dm355_snd_soc_card_drvdata = { + .sysclk = 27000000, +}; + static struct snd_soc_card dm355_snd_soc_card_evm = { .name = "DaVinci DM355 EVM", .owner = THIS_MODULE, .dai_link = &dm355_evm_dai, .num_links = 1, + .drvdata = &dm355_snd_soc_card_drvdata, }; /* davinci dm365 evm audio machine driver */ +static struct snd_soc_card_drvdata_davinci dm365_snd_soc_card_drvdata = { + .sysclk = 27000000, +}; + static struct snd_soc_card dm365_snd_soc_card_evm = { .name = "DaVinci DM365 EVM", .owner = THIS_MODULE, .dai_link = &dm365_evm_dai, .num_links = 1, + .drvdata = &dm365_snd_soc_card_drvdata, }; /* davinci dm6467 evm audio machine driver */ +static struct snd_soc_card_drvdata_davinci dm6467_snd_soc_card_drvdata = { + .sysclk = 27000000, +}; + static struct snd_soc_card dm6467_snd_soc_card_evm = { .name = "DaVinci DM6467 EVM", .owner = THIS_MODULE, .dai_link = dm6467_evm_dai, .num_links = ARRAY_SIZE(dm6467_evm_dai), + .drvdata = &dm6467_snd_soc_card_drvdata, +}; + +static struct snd_soc_card_drvdata_davinci da830_snd_soc_card_drvdata = { + .sysclk = 24576000, }; static struct snd_soc_card da830_snd_soc_card = { @@ -279,6 +309,11 @@ static struct snd_soc_card da830_snd_soc_card = { .owner = THIS_MODULE, .dai_link = &da830_evm_dai, .num_links = 1, + .drvdata = &da830_snd_soc_card_drvdata, +}; + +static struct snd_soc_card_drvdata_davinci da850_snd_soc_card_drvdata = { + .sysclk = 24576000, }; static struct snd_soc_card da850_snd_soc_card = { @@ -286,8 +321,101 @@ static struct snd_soc_card da850_snd_soc_card = { .owner = THIS_MODULE, .dai_link = &da850_evm_dai, .num_links = 1, + .drvdata = &da850_snd_soc_card_drvdata, +}; + +#if defined(CONFIG_OF) + +/* + * The struct is used as place holder. It will be completely + * filled with data from dt node. + */ +static struct snd_soc_dai_link evm_dai_tlv320aic3x = { + .name = "TLV320AIC3X", + .stream_name = "AIC3X", + .codec_dai_name = "tlv320aic3x-hifi", + .ops = &evm_ops, + .init = evm_aic3x_init, +}; + +static const struct of_device_id davinci_evm_dt_ids[] = { + { + .compatible = "ti,da830-evm-audio", + .data = (void *) &evm_dai_tlv320aic3x, + }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, davinci_evm_dt_ids); + +/* davinci evm audio machine driver */ +static struct snd_soc_card evm_soc_card = { + .owner = THIS_MODULE, + .num_links = 1, }; +static int davinci_evm_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + const struct of_device_id *match = + of_match_device(of_match_ptr(davinci_evm_dt_ids), &pdev->dev); + struct snd_soc_dai_link *dai = (struct snd_soc_dai_link *) match->data; + struct snd_soc_card_drvdata_davinci *drvdata = NULL; + int ret = 0; + + evm_soc_card.dai_link = dai; + + dai->codec_of_node = of_parse_phandle(np, "ti,audio-codec", 0); + if (!dai->codec_of_node) + return -EINVAL; + + dai->cpu_of_node = of_parse_phandle(np, "ti,mcasp-controller", 0); + if (!dai->cpu_of_node) + return -EINVAL; + + dai->platform_of_node = dai->cpu_of_node; + + evm_soc_card.dev = &pdev->dev; + ret = snd_soc_of_parse_card_name(&evm_soc_card, "ti,model"); + if (ret) + return ret; + + drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + + ret = of_property_read_u32(np, "ti,codec-clock-rate", &drvdata->sysclk); + if (ret < 0) + return -EINVAL; + + snd_soc_card_set_drvdata(&evm_soc_card, drvdata); + ret = devm_snd_soc_register_card(&pdev->dev, &evm_soc_card); + + if (ret) + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); + + return ret; +} + +static int davinci_evm_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + + snd_soc_unregister_card(card); + + return 0; +} + +static struct platform_driver davinci_evm_driver = { + .probe = davinci_evm_probe, + .remove = davinci_evm_remove, + .driver = { + .name = "davinci_evm", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(davinci_evm_dt_ids), + }, +}; +#endif + static struct platform_device *evm_snd_device; static int __init evm_init(void) @@ -296,6 +424,15 @@ static int __init evm_init(void) int index; int ret; + /* + * If dtb is there, the devices will be created dynamically. + * Only register platfrom driver structure. + */ +#if defined(CONFIG_OF) + if (of_have_populated_dt()) + return platform_driver_register(&davinci_evm_driver); +#endif + if (machine_is_davinci_evm()) { evm_snd_dev_data = &dm6446_snd_soc_card_evm; index = 0; @@ -331,6 +468,13 @@ static int __init evm_init(void) static void __exit evm_exit(void) { +#if defined(CONFIG_OF) + if (of_have_populated_dt()) { + platform_driver_unregister(&davinci_evm_driver); + return; + } +#endif + platform_device_unregister(evm_snd_device); } |