1f2055e14SPeter Ujfalusi /* 2f2055e14SPeter Ujfalusi * omap-abe-twl6040.c -- SoC audio for TI OMAP based boards with ABE and 3f2055e14SPeter Ujfalusi * twl6040 codec 4f2055e14SPeter Ujfalusi * 5f2055e14SPeter Ujfalusi * Author: Misael Lopez Cruz <misael.lopez@ti.com> 6f2055e14SPeter Ujfalusi * 7f2055e14SPeter Ujfalusi * This program is free software; you can redistribute it and/or 8f2055e14SPeter Ujfalusi * modify it under the terms of the GNU General Public License 9f2055e14SPeter Ujfalusi * version 2 as published by the Free Software Foundation. 10f2055e14SPeter Ujfalusi * 11f2055e14SPeter Ujfalusi * This program is distributed in the hope that it will be useful, but 12f2055e14SPeter Ujfalusi * WITHOUT ANY WARRANTY; without even the implied warranty of 13f2055e14SPeter Ujfalusi * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14f2055e14SPeter Ujfalusi * General Public License for more details. 15f2055e14SPeter Ujfalusi * 16f2055e14SPeter Ujfalusi * You should have received a copy of the GNU General Public License 17f2055e14SPeter Ujfalusi * along with this program; if not, write to the Free Software 18f2055e14SPeter Ujfalusi * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 19f2055e14SPeter Ujfalusi * 02110-1301 USA 20f2055e14SPeter Ujfalusi * 21f2055e14SPeter Ujfalusi */ 22f2055e14SPeter Ujfalusi 23f2055e14SPeter Ujfalusi #include <linux/clk.h> 24f2055e14SPeter Ujfalusi #include <linux/platform_device.h> 25f2055e14SPeter Ujfalusi #include <linux/mfd/twl6040.h> 26f2055e14SPeter Ujfalusi #include <linux/module.h> 27f2055e14SPeter Ujfalusi #include <linux/of.h> 28f2055e14SPeter Ujfalusi 29f2055e14SPeter Ujfalusi #include <sound/core.h> 30f2055e14SPeter Ujfalusi #include <sound/pcm.h> 31f2055e14SPeter Ujfalusi #include <sound/soc.h> 32f2055e14SPeter Ujfalusi #include <sound/jack.h> 33f2055e14SPeter Ujfalusi 34f2055e14SPeter Ujfalusi #include "omap-dmic.h" 35f2055e14SPeter Ujfalusi #include "omap-mcpdm.h" 36f2055e14SPeter Ujfalusi #include "../codecs/twl6040.h" 37f2055e14SPeter Ujfalusi 38*1306ab2eSKuninori Morimoto SND_SOC_DAILINK_DEF(link0_cpus, 39*1306ab2eSKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY())); 40*1306ab2eSKuninori Morimoto SND_SOC_DAILINK_DEF(link0_codecs, 41bc9dfc4cSKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("twl6040-codec", 42*1306ab2eSKuninori Morimoto "twl6040-legacy"))); 43bc9dfc4cSKuninori Morimoto 44*1306ab2eSKuninori Morimoto SND_SOC_DAILINK_DEF(link1_cpus, 45bc9dfc4cSKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY())); 46*1306ab2eSKuninori Morimoto SND_SOC_DAILINK_DEF(link1_codecs, 47*1306ab2eSKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", 48*1306ab2eSKuninori Morimoto "dmic-hifi"))); 49bc9dfc4cSKuninori Morimoto 50f2055e14SPeter Ujfalusi struct abe_twl6040 { 51f2055e14SPeter Ujfalusi struct snd_soc_card card; 52f2055e14SPeter Ujfalusi struct snd_soc_dai_link dai_links[2]; 53f2055e14SPeter Ujfalusi int jack_detection; /* board can detect jack events */ 54f2055e14SPeter Ujfalusi int mclk_freq; /* MCLK frequency speed for twl6040 */ 55f2055e14SPeter Ujfalusi }; 56f2055e14SPeter Ujfalusi 57f2055e14SPeter Ujfalusi static struct platform_device *dmic_codec_dev; 58f2055e14SPeter Ujfalusi 59f2055e14SPeter Ujfalusi static int omap_abe_hw_params(struct snd_pcm_substream *substream, 60f2055e14SPeter Ujfalusi struct snd_pcm_hw_params *params) 61f2055e14SPeter Ujfalusi { 62f2055e14SPeter Ujfalusi struct snd_soc_pcm_runtime *rtd = substream->private_data; 63f2055e14SPeter Ujfalusi struct snd_soc_dai *codec_dai = rtd->codec_dai; 64f2055e14SPeter Ujfalusi struct snd_soc_card *card = rtd->card; 65f2055e14SPeter Ujfalusi struct abe_twl6040 *priv = snd_soc_card_get_drvdata(card); 66f2055e14SPeter Ujfalusi int clk_id, freq; 67f2055e14SPeter Ujfalusi int ret; 68f2055e14SPeter Ujfalusi 69f2055e14SPeter Ujfalusi clk_id = twl6040_get_clk_id(codec_dai->component); 70f2055e14SPeter Ujfalusi if (clk_id == TWL6040_SYSCLK_SEL_HPPLL) 71f2055e14SPeter Ujfalusi freq = priv->mclk_freq; 72f2055e14SPeter Ujfalusi else if (clk_id == TWL6040_SYSCLK_SEL_LPPLL) 73f2055e14SPeter Ujfalusi freq = 32768; 74f2055e14SPeter Ujfalusi else 75f2055e14SPeter Ujfalusi return -EINVAL; 76f2055e14SPeter Ujfalusi 77f2055e14SPeter Ujfalusi /* set the codec mclk */ 78f2055e14SPeter Ujfalusi ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, freq, 79f2055e14SPeter Ujfalusi SND_SOC_CLOCK_IN); 80f2055e14SPeter Ujfalusi if (ret) { 81f2055e14SPeter Ujfalusi printk(KERN_ERR "can't set codec system clock\n"); 82f2055e14SPeter Ujfalusi return ret; 83f2055e14SPeter Ujfalusi } 84f2055e14SPeter Ujfalusi return ret; 85f2055e14SPeter Ujfalusi } 86f2055e14SPeter Ujfalusi 87f2055e14SPeter Ujfalusi static const struct snd_soc_ops omap_abe_ops = { 88f2055e14SPeter Ujfalusi .hw_params = omap_abe_hw_params, 89f2055e14SPeter Ujfalusi }; 90f2055e14SPeter Ujfalusi 91f2055e14SPeter Ujfalusi static int omap_abe_dmic_hw_params(struct snd_pcm_substream *substream, 92f2055e14SPeter Ujfalusi struct snd_pcm_hw_params *params) 93f2055e14SPeter Ujfalusi { 94f2055e14SPeter Ujfalusi struct snd_soc_pcm_runtime *rtd = substream->private_data; 95f2055e14SPeter Ujfalusi struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 96f2055e14SPeter Ujfalusi int ret = 0; 97f2055e14SPeter Ujfalusi 98f2055e14SPeter Ujfalusi ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_DMIC_SYSCLK_PAD_CLKS, 99f2055e14SPeter Ujfalusi 19200000, SND_SOC_CLOCK_IN); 100f2055e14SPeter Ujfalusi if (ret < 0) { 101f2055e14SPeter Ujfalusi printk(KERN_ERR "can't set DMIC cpu system clock\n"); 102f2055e14SPeter Ujfalusi return ret; 103f2055e14SPeter Ujfalusi } 104f2055e14SPeter Ujfalusi ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_DMIC_ABE_DMIC_CLK, 2400000, 105f2055e14SPeter Ujfalusi SND_SOC_CLOCK_OUT); 106f2055e14SPeter Ujfalusi if (ret < 0) { 107f2055e14SPeter Ujfalusi printk(KERN_ERR "can't set DMIC output clock\n"); 108f2055e14SPeter Ujfalusi return ret; 109f2055e14SPeter Ujfalusi } 110f2055e14SPeter Ujfalusi return 0; 111f2055e14SPeter Ujfalusi } 112f2055e14SPeter Ujfalusi 113f2055e14SPeter Ujfalusi static struct snd_soc_ops omap_abe_dmic_ops = { 114f2055e14SPeter Ujfalusi .hw_params = omap_abe_dmic_hw_params, 115f2055e14SPeter Ujfalusi }; 116f2055e14SPeter Ujfalusi 117f2055e14SPeter Ujfalusi /* Headset jack */ 118f2055e14SPeter Ujfalusi static struct snd_soc_jack hs_jack; 119f2055e14SPeter Ujfalusi 120f2055e14SPeter Ujfalusi /*Headset jack detection DAPM pins */ 121f2055e14SPeter Ujfalusi static struct snd_soc_jack_pin hs_jack_pins[] = { 122f2055e14SPeter Ujfalusi { 123f2055e14SPeter Ujfalusi .pin = "Headset Mic", 124f2055e14SPeter Ujfalusi .mask = SND_JACK_MICROPHONE, 125f2055e14SPeter Ujfalusi }, 126f2055e14SPeter Ujfalusi { 127f2055e14SPeter Ujfalusi .pin = "Headset Stereophone", 128f2055e14SPeter Ujfalusi .mask = SND_JACK_HEADPHONE, 129f2055e14SPeter Ujfalusi }, 130f2055e14SPeter Ujfalusi }; 131f2055e14SPeter Ujfalusi 132f2055e14SPeter Ujfalusi /* SDP4430 machine DAPM */ 133f2055e14SPeter Ujfalusi static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { 134f2055e14SPeter Ujfalusi /* Outputs */ 135f2055e14SPeter Ujfalusi SND_SOC_DAPM_HP("Headset Stereophone", NULL), 136f2055e14SPeter Ujfalusi SND_SOC_DAPM_SPK("Earphone Spk", NULL), 137f2055e14SPeter Ujfalusi SND_SOC_DAPM_SPK("Ext Spk", NULL), 138f2055e14SPeter Ujfalusi SND_SOC_DAPM_LINE("Line Out", NULL), 139f2055e14SPeter Ujfalusi SND_SOC_DAPM_SPK("Vibrator", NULL), 140f2055e14SPeter Ujfalusi 141f2055e14SPeter Ujfalusi /* Inputs */ 142f2055e14SPeter Ujfalusi SND_SOC_DAPM_MIC("Headset Mic", NULL), 143f2055e14SPeter Ujfalusi SND_SOC_DAPM_MIC("Main Handset Mic", NULL), 144f2055e14SPeter Ujfalusi SND_SOC_DAPM_MIC("Sub Handset Mic", NULL), 145f2055e14SPeter Ujfalusi SND_SOC_DAPM_LINE("Line In", NULL), 146f2055e14SPeter Ujfalusi 147f2055e14SPeter Ujfalusi /* Digital microphones */ 148f2055e14SPeter Ujfalusi SND_SOC_DAPM_MIC("Digital Mic", NULL), 149f2055e14SPeter Ujfalusi }; 150f2055e14SPeter Ujfalusi 151f2055e14SPeter Ujfalusi static const struct snd_soc_dapm_route audio_map[] = { 152f2055e14SPeter Ujfalusi /* Routings for outputs */ 153f2055e14SPeter Ujfalusi {"Headset Stereophone", NULL, "HSOL"}, 154f2055e14SPeter Ujfalusi {"Headset Stereophone", NULL, "HSOR"}, 155f2055e14SPeter Ujfalusi 156f2055e14SPeter Ujfalusi {"Earphone Spk", NULL, "EP"}, 157f2055e14SPeter Ujfalusi 158f2055e14SPeter Ujfalusi {"Ext Spk", NULL, "HFL"}, 159f2055e14SPeter Ujfalusi {"Ext Spk", NULL, "HFR"}, 160f2055e14SPeter Ujfalusi 161f2055e14SPeter Ujfalusi {"Line Out", NULL, "AUXL"}, 162f2055e14SPeter Ujfalusi {"Line Out", NULL, "AUXR"}, 163f2055e14SPeter Ujfalusi 164f2055e14SPeter Ujfalusi {"Vibrator", NULL, "VIBRAL"}, 165f2055e14SPeter Ujfalusi {"Vibrator", NULL, "VIBRAR"}, 166f2055e14SPeter Ujfalusi 167f2055e14SPeter Ujfalusi /* Routings for inputs */ 168f2055e14SPeter Ujfalusi {"HSMIC", NULL, "Headset Mic"}, 169f2055e14SPeter Ujfalusi {"Headset Mic", NULL, "Headset Mic Bias"}, 170f2055e14SPeter Ujfalusi 171f2055e14SPeter Ujfalusi {"MAINMIC", NULL, "Main Handset Mic"}, 172f2055e14SPeter Ujfalusi {"Main Handset Mic", NULL, "Main Mic Bias"}, 173f2055e14SPeter Ujfalusi 174f2055e14SPeter Ujfalusi {"SUBMIC", NULL, "Sub Handset Mic"}, 175f2055e14SPeter Ujfalusi {"Sub Handset Mic", NULL, "Main Mic Bias"}, 176f2055e14SPeter Ujfalusi 177f2055e14SPeter Ujfalusi {"AFML", NULL, "Line In"}, 178f2055e14SPeter Ujfalusi {"AFMR", NULL, "Line In"}, 179f2055e14SPeter Ujfalusi }; 180f2055e14SPeter Ujfalusi 181f2055e14SPeter Ujfalusi static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd) 182f2055e14SPeter Ujfalusi { 183f2055e14SPeter Ujfalusi struct snd_soc_component *component = rtd->codec_dai->component; 184f2055e14SPeter Ujfalusi struct snd_soc_card *card = rtd->card; 185f2055e14SPeter Ujfalusi struct abe_twl6040 *priv = snd_soc_card_get_drvdata(card); 186f2055e14SPeter Ujfalusi int hs_trim; 187f2055e14SPeter Ujfalusi int ret = 0; 188f2055e14SPeter Ujfalusi 189f2055e14SPeter Ujfalusi /* 190f2055e14SPeter Ujfalusi * Configure McPDM offset cancellation based on the HSOTRIM value from 191f2055e14SPeter Ujfalusi * twl6040. 192f2055e14SPeter Ujfalusi */ 193f2055e14SPeter Ujfalusi hs_trim = twl6040_get_trim_value(component, TWL6040_TRIM_HSOTRIM); 194f2055e14SPeter Ujfalusi omap_mcpdm_configure_dn_offsets(rtd, TWL6040_HSF_TRIM_LEFT(hs_trim), 195f2055e14SPeter Ujfalusi TWL6040_HSF_TRIM_RIGHT(hs_trim)); 196f2055e14SPeter Ujfalusi 197f2055e14SPeter Ujfalusi /* Headset jack detection only if it is supported */ 198f2055e14SPeter Ujfalusi if (priv->jack_detection) { 199f2055e14SPeter Ujfalusi ret = snd_soc_card_jack_new(rtd->card, "Headset Jack", 200f2055e14SPeter Ujfalusi SND_JACK_HEADSET, &hs_jack, 201f2055e14SPeter Ujfalusi hs_jack_pins, 202f2055e14SPeter Ujfalusi ARRAY_SIZE(hs_jack_pins)); 203f2055e14SPeter Ujfalusi if (ret) 204f2055e14SPeter Ujfalusi return ret; 205f2055e14SPeter Ujfalusi 206f2055e14SPeter Ujfalusi twl6040_hs_jack_detect(component, &hs_jack, SND_JACK_HEADSET); 207f2055e14SPeter Ujfalusi } 208f2055e14SPeter Ujfalusi 209f2055e14SPeter Ujfalusi return 0; 210f2055e14SPeter Ujfalusi } 211f2055e14SPeter Ujfalusi 212f2055e14SPeter Ujfalusi static const struct snd_soc_dapm_route dmic_audio_map[] = { 213f2055e14SPeter Ujfalusi {"DMic", NULL, "Digital Mic"}, 214f2055e14SPeter Ujfalusi {"Digital Mic", NULL, "Digital Mic1 Bias"}, 215f2055e14SPeter Ujfalusi }; 216f2055e14SPeter Ujfalusi 217f2055e14SPeter Ujfalusi static int omap_abe_dmic_init(struct snd_soc_pcm_runtime *rtd) 218f2055e14SPeter Ujfalusi { 219f2055e14SPeter Ujfalusi struct snd_soc_dapm_context *dapm = &rtd->card->dapm; 220f2055e14SPeter Ujfalusi 221f2055e14SPeter Ujfalusi return snd_soc_dapm_add_routes(dapm, dmic_audio_map, 222f2055e14SPeter Ujfalusi ARRAY_SIZE(dmic_audio_map)); 223f2055e14SPeter Ujfalusi } 224f2055e14SPeter Ujfalusi 225f2055e14SPeter Ujfalusi static int omap_abe_probe(struct platform_device *pdev) 226f2055e14SPeter Ujfalusi { 227f2055e14SPeter Ujfalusi struct device_node *node = pdev->dev.of_node; 228f2055e14SPeter Ujfalusi struct snd_soc_card *card; 229f2055e14SPeter Ujfalusi struct device_node *dai_node; 230f2055e14SPeter Ujfalusi struct abe_twl6040 *priv; 231f2055e14SPeter Ujfalusi int num_links = 0; 232f2055e14SPeter Ujfalusi int ret = 0; 233f2055e14SPeter Ujfalusi 234f2055e14SPeter Ujfalusi if (!node) { 235f2055e14SPeter Ujfalusi dev_err(&pdev->dev, "of node is missing.\n"); 236f2055e14SPeter Ujfalusi return -ENODEV; 237f2055e14SPeter Ujfalusi } 238f2055e14SPeter Ujfalusi 239f2055e14SPeter Ujfalusi priv = devm_kzalloc(&pdev->dev, sizeof(struct abe_twl6040), GFP_KERNEL); 240f2055e14SPeter Ujfalusi if (priv == NULL) 241f2055e14SPeter Ujfalusi return -ENOMEM; 242f2055e14SPeter Ujfalusi 243f2055e14SPeter Ujfalusi card = &priv->card; 244f2055e14SPeter Ujfalusi card->dev = &pdev->dev; 245f2055e14SPeter Ujfalusi card->owner = THIS_MODULE; 246f2055e14SPeter Ujfalusi card->dapm_widgets = twl6040_dapm_widgets; 247f2055e14SPeter Ujfalusi card->num_dapm_widgets = ARRAY_SIZE(twl6040_dapm_widgets); 248f2055e14SPeter Ujfalusi card->dapm_routes = audio_map; 249f2055e14SPeter Ujfalusi card->num_dapm_routes = ARRAY_SIZE(audio_map); 250f2055e14SPeter Ujfalusi 251f2055e14SPeter Ujfalusi if (snd_soc_of_parse_card_name(card, "ti,model")) { 252f2055e14SPeter Ujfalusi dev_err(&pdev->dev, "Card name is not provided\n"); 253f2055e14SPeter Ujfalusi return -ENODEV; 254f2055e14SPeter Ujfalusi } 255f2055e14SPeter Ujfalusi 256f2055e14SPeter Ujfalusi ret = snd_soc_of_parse_audio_routing(card, "ti,audio-routing"); 257f2055e14SPeter Ujfalusi if (ret) { 258f2055e14SPeter Ujfalusi dev_err(&pdev->dev, "Error while parsing DAPM routing\n"); 259f2055e14SPeter Ujfalusi return ret; 260f2055e14SPeter Ujfalusi } 261f2055e14SPeter Ujfalusi 262f2055e14SPeter Ujfalusi dai_node = of_parse_phandle(node, "ti,mcpdm", 0); 263f2055e14SPeter Ujfalusi if (!dai_node) { 264f2055e14SPeter Ujfalusi dev_err(&pdev->dev, "McPDM node is not provided\n"); 265f2055e14SPeter Ujfalusi return -EINVAL; 266f2055e14SPeter Ujfalusi } 267f2055e14SPeter Ujfalusi 268f2055e14SPeter Ujfalusi priv->dai_links[0].name = "DMIC"; 269f2055e14SPeter Ujfalusi priv->dai_links[0].stream_name = "TWL6040"; 270bc9dfc4cSKuninori Morimoto priv->dai_links[0].cpus = link0_cpus; 271bc9dfc4cSKuninori Morimoto priv->dai_links[0].num_cpus = 1; 272bc9dfc4cSKuninori Morimoto priv->dai_links[0].cpus->of_node = dai_node; 273bc9dfc4cSKuninori Morimoto priv->dai_links[0].codecs = link0_codecs; 274bc9dfc4cSKuninori Morimoto priv->dai_links[0].num_codecs = 1; 275f2055e14SPeter Ujfalusi priv->dai_links[0].init = omap_abe_twl6040_init; 276f2055e14SPeter Ujfalusi priv->dai_links[0].ops = &omap_abe_ops; 277f2055e14SPeter Ujfalusi 278f2055e14SPeter Ujfalusi dai_node = of_parse_phandle(node, "ti,dmic", 0); 279f2055e14SPeter Ujfalusi if (dai_node) { 280f2055e14SPeter Ujfalusi num_links = 2; 281f2055e14SPeter Ujfalusi priv->dai_links[1].name = "TWL6040"; 282f2055e14SPeter Ujfalusi priv->dai_links[1].stream_name = "DMIC Capture"; 283bc9dfc4cSKuninori Morimoto priv->dai_links[1].cpus = link1_cpus; 284bc9dfc4cSKuninori Morimoto priv->dai_links[1].num_cpus = 1; 285bc9dfc4cSKuninori Morimoto priv->dai_links[1].cpus->of_node = dai_node; 286bc9dfc4cSKuninori Morimoto priv->dai_links[1].codecs = link1_codecs; 287bc9dfc4cSKuninori Morimoto priv->dai_links[1].num_codecs = 1; 288f2055e14SPeter Ujfalusi priv->dai_links[1].init = omap_abe_dmic_init; 289f2055e14SPeter Ujfalusi priv->dai_links[1].ops = &omap_abe_dmic_ops; 290f2055e14SPeter Ujfalusi } else { 291f2055e14SPeter Ujfalusi num_links = 1; 292f2055e14SPeter Ujfalusi } 293f2055e14SPeter Ujfalusi 294f2055e14SPeter Ujfalusi priv->jack_detection = of_property_read_bool(node, "ti,jack-detection"); 295f2055e14SPeter Ujfalusi of_property_read_u32(node, "ti,mclk-freq", &priv->mclk_freq); 296f2055e14SPeter Ujfalusi if (!priv->mclk_freq) { 297f2055e14SPeter Ujfalusi dev_err(&pdev->dev, "MCLK frequency not provided\n"); 298f2055e14SPeter Ujfalusi return -EINVAL; 299f2055e14SPeter Ujfalusi } 300f2055e14SPeter Ujfalusi 301f2055e14SPeter Ujfalusi card->fully_routed = 1; 302f2055e14SPeter Ujfalusi 303f2055e14SPeter Ujfalusi if (!priv->mclk_freq) { 304f2055e14SPeter Ujfalusi dev_err(&pdev->dev, "MCLK frequency missing\n"); 305f2055e14SPeter Ujfalusi return -ENODEV; 306f2055e14SPeter Ujfalusi } 307f2055e14SPeter Ujfalusi 308f2055e14SPeter Ujfalusi card->dai_link = priv->dai_links; 309f2055e14SPeter Ujfalusi card->num_links = num_links; 310f2055e14SPeter Ujfalusi 311f2055e14SPeter Ujfalusi snd_soc_card_set_drvdata(card, priv); 312f2055e14SPeter Ujfalusi 313f2055e14SPeter Ujfalusi ret = devm_snd_soc_register_card(&pdev->dev, card); 314f2055e14SPeter Ujfalusi if (ret) 315f2055e14SPeter Ujfalusi dev_err(&pdev->dev, "devm_snd_soc_register_card() failed: %d\n", 316f2055e14SPeter Ujfalusi ret); 317f2055e14SPeter Ujfalusi 318f2055e14SPeter Ujfalusi return ret; 319f2055e14SPeter Ujfalusi } 320f2055e14SPeter Ujfalusi 321f2055e14SPeter Ujfalusi static const struct of_device_id omap_abe_of_match[] = { 322f2055e14SPeter Ujfalusi {.compatible = "ti,abe-twl6040", }, 323f2055e14SPeter Ujfalusi { }, 324f2055e14SPeter Ujfalusi }; 325f2055e14SPeter Ujfalusi MODULE_DEVICE_TABLE(of, omap_abe_of_match); 326f2055e14SPeter Ujfalusi 327f2055e14SPeter Ujfalusi static struct platform_driver omap_abe_driver = { 328f2055e14SPeter Ujfalusi .driver = { 329f2055e14SPeter Ujfalusi .name = "omap-abe-twl6040", 330f2055e14SPeter Ujfalusi .pm = &snd_soc_pm_ops, 331f2055e14SPeter Ujfalusi .of_match_table = omap_abe_of_match, 332f2055e14SPeter Ujfalusi }, 333f2055e14SPeter Ujfalusi .probe = omap_abe_probe, 334f2055e14SPeter Ujfalusi }; 335f2055e14SPeter Ujfalusi 336f2055e14SPeter Ujfalusi static int __init omap_abe_init(void) 337f2055e14SPeter Ujfalusi { 338f2055e14SPeter Ujfalusi int ret; 339f2055e14SPeter Ujfalusi 340f2055e14SPeter Ujfalusi dmic_codec_dev = platform_device_register_simple("dmic-codec", -1, NULL, 341f2055e14SPeter Ujfalusi 0); 342f2055e14SPeter Ujfalusi if (IS_ERR(dmic_codec_dev)) { 343f2055e14SPeter Ujfalusi pr_err("%s: dmic-codec device registration failed\n", __func__); 344f2055e14SPeter Ujfalusi return PTR_ERR(dmic_codec_dev); 345f2055e14SPeter Ujfalusi } 346f2055e14SPeter Ujfalusi 347f2055e14SPeter Ujfalusi ret = platform_driver_register(&omap_abe_driver); 348f2055e14SPeter Ujfalusi if (ret) { 349f2055e14SPeter Ujfalusi pr_err("%s: platform driver registration failed\n", __func__); 350f2055e14SPeter Ujfalusi platform_device_unregister(dmic_codec_dev); 351f2055e14SPeter Ujfalusi } 352f2055e14SPeter Ujfalusi 353f2055e14SPeter Ujfalusi return ret; 354f2055e14SPeter Ujfalusi } 355f2055e14SPeter Ujfalusi module_init(omap_abe_init); 356f2055e14SPeter Ujfalusi 357f2055e14SPeter Ujfalusi static void __exit omap_abe_exit(void) 358f2055e14SPeter Ujfalusi { 359f2055e14SPeter Ujfalusi platform_driver_unregister(&omap_abe_driver); 360f2055e14SPeter Ujfalusi platform_device_unregister(dmic_codec_dev); 361f2055e14SPeter Ujfalusi } 362f2055e14SPeter Ujfalusi module_exit(omap_abe_exit); 363f2055e14SPeter Ujfalusi 364f2055e14SPeter Ujfalusi MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>"); 365f2055e14SPeter Ujfalusi MODULE_DESCRIPTION("ALSA SoC for OMAP boards with ABE and twl6040 codec"); 366f2055e14SPeter Ujfalusi MODULE_LICENSE("GPL"); 367f2055e14SPeter Ujfalusi MODULE_ALIAS("platform:omap-abe-twl6040"); 368