#include #include #include #include static int mc_tlv320_init(struct snd_soc_pcm_runtime *rtd); static int mc_tlv320_startup(struct snd_pcm_substream *substream); static int mc_tlv320_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params); static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000 }; static struct snd_pcm_hw_constraint_list hw_rates = { .count = ARRAY_SIZE(rates), .list = rates, .mask = 0, }; static struct snd_soc_ops mc_tlv320_ops = { .startup = mc_tlv320_startup, .hw_params = mc_tlv320_hw_params, }; /* Multicore digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link mc_tlv320_dai[] = { { .name = "TLV320AIC3X", .stream_name = "AIC3X", .cpu_dai_name = "mc_i2s.3", .codec_dai_name = "tlv320aic3x-hifi", .init = mc_tlv320_init, .platform_name = "multicore-audio.3", .codec_name = "tlv320aic3x-codec.0-0018", .ops = &mc_tlv320_ops, }, }; static struct snd_soc_card mc_asoc = { .name = "mc_audio", .owner = THIS_MODULE, .dai_link = mc_tlv320_dai, .num_links = ARRAY_SIZE(mc_tlv320_dai), }; static struct platform_device *mc_snd_device; static int mc_tlv320_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; runtime->hw.rate_min = hw_rates.list[0]; runtime->hw.rate_max = hw_rates.list[hw_rates.count - 1]; runtime->hw.rates = MC_PCM_RATES; return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_rates); } static int mc_tlv320_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai; int ret; /* set codec DAI configuration */ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); if (ret < 0) return ret; /* set cpu DAI configuration */ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_CONT); if (ret < 0) return ret; /* set the codec system clock */ ret = snd_soc_dai_set_sysclk(codec_dai, 0, 10000000, SND_SOC_CLOCK_OUT); if (ret < 0) return ret; /* ret = snd_soc_dapm_disable_pin(codec_dai, "MONO_LOUT"); if (ret < 0) return ret; */ return 0; } /* davinci-evm machine dapm widgets */ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_LINE("Line Out", NULL), SND_SOC_DAPM_MIC("Mic Jack", NULL), SND_SOC_DAPM_LINE("Line In", NULL), }; /* davinci-evm machine audio_mapnections to the codec pins */ static const struct snd_soc_dapm_route audio_map[] = { /* Headphone connected to HPLOUT, HPROUT */ {"Headphone Jack", NULL, "HPLOUT"}, {"Headphone Jack", NULL, "HPROUT"}, /* Line Out connected to LLOUT, RLOUT */ {"Line Out", NULL, "LLOUT"}, {"Line Out", NULL, "RLOUT"}, /* Mic connected to (MIC3L | MIC3R) */ {"MIC3L", NULL, "Mic Bias 2V"}, {"MIC3R", NULL, "Mic Bias 2V"}, {"Mic Bias 2V", NULL, "Mic Jack"}, /* Line In connected to (LINE1L | LINE2L), (LINE1R | LINE2R) */ {"LINE1L", NULL, "Line In"}, {"LINE2L", NULL, "Line In"}, {"LINE1R", NULL, "Line In"}, {"LINE2R", NULL, "Line In"}, }; static int mc_tlv320_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; /* 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)); /* not connected */ snd_soc_dapm_disable_pin(dapm, "MONO_LOUT"); snd_soc_dapm_disable_pin(dapm, "HPLCOM"); snd_soc_dapm_disable_pin(dapm, "HPRCOM"); /* always connected */ snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); snd_soc_dapm_enable_pin(dapm, "Line Out"); snd_soc_dapm_enable_pin(dapm, "Mic Jack"); snd_soc_dapm_enable_pin(dapm, "Line In"); return 0; } static int __init mc_audio_init(void) { int ret; mc_snd_device = platform_device_alloc("soc-audio", -1); if (!mc_snd_device) return -ENOMEM; platform_set_drvdata(mc_snd_device, &mc_asoc); ret = platform_device_add(mc_snd_device); if (ret) { platform_device_put(mc_snd_device); return ret; } return 0; } static void __exit mc_audio_exit(void) { platform_device_unregister(mc_snd_device); } late_initcall(mc_audio_init); module_exit(mc_audio_exit); MODULE_AUTHOR("Dmitry Podkhvatilin"); MODULE_DESCRIPTION("ALSA SoC MULTICORE"); MODULE_LICENSE("GPL");