12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 274d04c3eSThomas Petazzoni /* 374d04c3eSThomas Petazzoni * Copyright (C) 2014 Marvell 474d04c3eSThomas Petazzoni * 574d04c3eSThomas Petazzoni * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> 674d04c3eSThomas Petazzoni */ 774d04c3eSThomas Petazzoni 874d04c3eSThomas Petazzoni #include <linux/module.h> 974d04c3eSThomas Petazzoni #include <linux/moduleparam.h> 1074d04c3eSThomas Petazzoni #include <linux/interrupt.h> 1174d04c3eSThomas Petazzoni #include <linux/platform_device.h> 1274d04c3eSThomas Petazzoni #include <linux/slab.h> 1374d04c3eSThomas Petazzoni #include <sound/soc.h> 1474d04c3eSThomas Petazzoni #include <linux/of.h> 1574d04c3eSThomas Petazzoni #include <linux/platform_data/asoc-kirkwood.h> 1674d04c3eSThomas Petazzoni #include "../codecs/cs42l51.h" 1774d04c3eSThomas Petazzoni 1874d04c3eSThomas Petazzoni static int a370db_hw_params(struct snd_pcm_substream *substream, 1974d04c3eSThomas Petazzoni struct snd_pcm_hw_params *params) 2074d04c3eSThomas Petazzoni { 216501cad6SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 22f844705fSKuninori Morimoto struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 2374d04c3eSThomas Petazzoni unsigned int freq; 2474d04c3eSThomas Petazzoni 2574d04c3eSThomas Petazzoni switch (params_rate(params)) { 2674d04c3eSThomas Petazzoni default: 2774d04c3eSThomas Petazzoni case 44100: 2874d04c3eSThomas Petazzoni freq = 11289600; 2974d04c3eSThomas Petazzoni break; 3074d04c3eSThomas Petazzoni case 48000: 3174d04c3eSThomas Petazzoni freq = 12288000; 3274d04c3eSThomas Petazzoni break; 3374d04c3eSThomas Petazzoni case 96000: 3474d04c3eSThomas Petazzoni freq = 24576000; 3574d04c3eSThomas Petazzoni break; 3674d04c3eSThomas Petazzoni } 3774d04c3eSThomas Petazzoni 3874d04c3eSThomas Petazzoni return snd_soc_dai_set_sysclk(codec_dai, 0, freq, SND_SOC_CLOCK_IN); 3974d04c3eSThomas Petazzoni } 4074d04c3eSThomas Petazzoni 419b6fdef6SJulia Lawall static const struct snd_soc_ops a370db_ops = { 4274d04c3eSThomas Petazzoni .hw_params = a370db_hw_params, 4374d04c3eSThomas Petazzoni }; 4474d04c3eSThomas Petazzoni 4574d04c3eSThomas Petazzoni static const struct snd_soc_dapm_widget a370db_dapm_widgets[] = { 4674d04c3eSThomas Petazzoni SND_SOC_DAPM_HP("Out Jack", NULL), 4774d04c3eSThomas Petazzoni SND_SOC_DAPM_LINE("In Jack", NULL), 4874d04c3eSThomas Petazzoni }; 4974d04c3eSThomas Petazzoni 5074d04c3eSThomas Petazzoni static const struct snd_soc_dapm_route a370db_route[] = { 5174d04c3eSThomas Petazzoni { "Out Jack", NULL, "HPL" }, 5274d04c3eSThomas Petazzoni { "Out Jack", NULL, "HPR" }, 5374d04c3eSThomas Petazzoni { "AIN1L", NULL, "In Jack" }, 5474d04c3eSThomas Petazzoni { "AIN1L", NULL, "In Jack" }, 5574d04c3eSThomas Petazzoni }; 5674d04c3eSThomas Petazzoni 571d17821fSKuninori Morimoto SND_SOC_DAILINK_DEFS(analog, 581d17821fSKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("i2s")), 59bb6630d1SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "cs42l51-hifi")), 60bb6630d1SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY())); 611d17821fSKuninori Morimoto 621d17821fSKuninori Morimoto SND_SOC_DAILINK_DEFS(spdif_out, 631d17821fSKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("spdif")), 64bb6630d1SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "dit-hifi")), 65bb6630d1SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY())); 661d17821fSKuninori Morimoto 671d17821fSKuninori Morimoto SND_SOC_DAILINK_DEFS(spdif_in, 681d17821fSKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("spdif")), 69bb6630d1SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "dir-hifi")), 70bb6630d1SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY())); 711d17821fSKuninori Morimoto 7274d04c3eSThomas Petazzoni static struct snd_soc_dai_link a370db_dai[] = { 7374d04c3eSThomas Petazzoni { 7474d04c3eSThomas Petazzoni .name = "CS42L51", 7574d04c3eSThomas Petazzoni .stream_name = "analog", 7674d04c3eSThomas Petazzoni .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, 7774d04c3eSThomas Petazzoni .ops = &a370db_ops, 781d17821fSKuninori Morimoto SND_SOC_DAILINK_REG(analog), 7974d04c3eSThomas Petazzoni }, 80cece5656SThomas Petazzoni { 81cece5656SThomas Petazzoni .name = "S/PDIF out", 82cece5656SThomas Petazzoni .stream_name = "spdif-out", 83cece5656SThomas Petazzoni .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, 841d17821fSKuninori Morimoto SND_SOC_DAILINK_REG(spdif_out), 85cece5656SThomas Petazzoni }, 86cece5656SThomas Petazzoni { 87cece5656SThomas Petazzoni .name = "S/PDIF in", 88cece5656SThomas Petazzoni .stream_name = "spdif-in", 89cece5656SThomas Petazzoni .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, 901d17821fSKuninori Morimoto SND_SOC_DAILINK_REG(spdif_in), 91cece5656SThomas Petazzoni }, 9274d04c3eSThomas Petazzoni }; 9374d04c3eSThomas Petazzoni 9474d04c3eSThomas Petazzoni static struct snd_soc_card a370db = { 9574d04c3eSThomas Petazzoni .name = "a370db", 9674d04c3eSThomas Petazzoni .owner = THIS_MODULE, 9774d04c3eSThomas Petazzoni .dai_link = a370db_dai, 9874d04c3eSThomas Petazzoni .num_links = ARRAY_SIZE(a370db_dai), 9974d04c3eSThomas Petazzoni .dapm_widgets = a370db_dapm_widgets, 10074d04c3eSThomas Petazzoni .num_dapm_widgets = ARRAY_SIZE(a370db_dapm_widgets), 10174d04c3eSThomas Petazzoni .dapm_routes = a370db_route, 10274d04c3eSThomas Petazzoni .num_dapm_routes = ARRAY_SIZE(a370db_route), 10374d04c3eSThomas Petazzoni }; 10474d04c3eSThomas Petazzoni 10574d04c3eSThomas Petazzoni static int a370db_probe(struct platform_device *pdev) 10674d04c3eSThomas Petazzoni { 10774d04c3eSThomas Petazzoni struct snd_soc_card *card = &a370db; 10874d04c3eSThomas Petazzoni 10974d04c3eSThomas Petazzoni card->dev = &pdev->dev; 11074d04c3eSThomas Petazzoni 1111d17821fSKuninori Morimoto a370db_dai[0].cpus->of_node = 11274d04c3eSThomas Petazzoni of_parse_phandle(pdev->dev.of_node, 11374d04c3eSThomas Petazzoni "marvell,audio-controller", 0); 114bb6630d1SKuninori Morimoto a370db_dai[0].platforms->of_node = a370db_dai[0].cpus->of_node; 11574d04c3eSThomas Petazzoni 1161d17821fSKuninori Morimoto a370db_dai[0].codecs->of_node = 11774d04c3eSThomas Petazzoni of_parse_phandle(pdev->dev.of_node, 11874d04c3eSThomas Petazzoni "marvell,audio-codec", 0); 11974d04c3eSThomas Petazzoni 1201d17821fSKuninori Morimoto a370db_dai[1].cpus->of_node = a370db_dai[0].cpus->of_node; 121bb6630d1SKuninori Morimoto a370db_dai[1].platforms->of_node = a370db_dai[0].cpus->of_node; 122cece5656SThomas Petazzoni 1231d17821fSKuninori Morimoto a370db_dai[1].codecs->of_node = 124cece5656SThomas Petazzoni of_parse_phandle(pdev->dev.of_node, 125cece5656SThomas Petazzoni "marvell,audio-codec", 1); 126cece5656SThomas Petazzoni 1271d17821fSKuninori Morimoto a370db_dai[2].cpus->of_node = a370db_dai[0].cpus->of_node; 128bb6630d1SKuninori Morimoto a370db_dai[2].platforms->of_node = a370db_dai[0].cpus->of_node; 129cece5656SThomas Petazzoni 1301d17821fSKuninori Morimoto a370db_dai[2].codecs->of_node = 131cece5656SThomas Petazzoni of_parse_phandle(pdev->dev.of_node, 132cece5656SThomas Petazzoni "marvell,audio-codec", 2); 133cece5656SThomas Petazzoni 13474d04c3eSThomas Petazzoni return devm_snd_soc_register_card(card->dev, card); 13574d04c3eSThomas Petazzoni } 13674d04c3eSThomas Petazzoni 13774d04c3eSThomas Petazzoni static const struct of_device_id a370db_dt_ids[] = { 13874d04c3eSThomas Petazzoni { .compatible = "marvell,a370db-audio" }, 13974d04c3eSThomas Petazzoni { }, 14074d04c3eSThomas Petazzoni }; 14130953a80SLuis de Bethencourt MODULE_DEVICE_TABLE(of, a370db_dt_ids); 14274d04c3eSThomas Petazzoni 14374d04c3eSThomas Petazzoni static struct platform_driver a370db_driver = { 14474d04c3eSThomas Petazzoni .driver = { 14574d04c3eSThomas Petazzoni .name = "a370db-audio", 14674d04c3eSThomas Petazzoni .of_match_table = of_match_ptr(a370db_dt_ids), 14774d04c3eSThomas Petazzoni }, 14874d04c3eSThomas Petazzoni .probe = a370db_probe, 14974d04c3eSThomas Petazzoni }; 15074d04c3eSThomas Petazzoni 15174d04c3eSThomas Petazzoni module_platform_driver(a370db_driver); 15274d04c3eSThomas Petazzoni 15374d04c3eSThomas Petazzoni MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>"); 15474d04c3eSThomas Petazzoni MODULE_DESCRIPTION("ALSA SoC a370db audio client"); 15574d04c3eSThomas Petazzoni MODULE_LICENSE("GPL"); 15674d04c3eSThomas Petazzoni MODULE_ALIAS("platform:a370db-audio"); 157