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