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