1a710770eSDavid Lambert /* 2a710770eSDavid Lambert * dmic.c -- SoC audio for Generic Digital MICs 3a710770eSDavid Lambert * 4a710770eSDavid Lambert * Author: Liam Girdwood <lrg@slimlogic.co.uk> 5a710770eSDavid Lambert * 6a710770eSDavid Lambert * This program is free software; you can redistribute it and/or 7a710770eSDavid Lambert * modify it under the terms of the GNU General Public License 8a710770eSDavid Lambert * version 2 as published by the Free Software Foundation. 9a710770eSDavid Lambert * 10a710770eSDavid Lambert * This program is distributed in the hope that it will be useful, but 11a710770eSDavid Lambert * WITHOUT ANY WARRANTY; without even the implied warranty of 12a710770eSDavid Lambert * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13a710770eSDavid Lambert * General Public License for more details. 14a710770eSDavid Lambert * 15a710770eSDavid Lambert * You should have received a copy of the GNU General Public License 16a710770eSDavid Lambert * along with this program; if not, write to the Free Software 17a710770eSDavid Lambert * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 18a710770eSDavid Lambert * 02110-1301 USA 19a710770eSDavid Lambert * 20a710770eSDavid Lambert */ 21a710770eSDavid Lambert 22*23c7159aShuang lin #include <linux/gpio.h> 23*23c7159aShuang lin #include <linux/gpio/consumer.h> 24a710770eSDavid Lambert #include <linux/platform_device.h> 25a710770eSDavid Lambert #include <linux/slab.h> 26da155d5bSPaul Gortmaker #include <linux/module.h> 27a710770eSDavid Lambert #include <sound/core.h> 28a710770eSDavid Lambert #include <sound/pcm.h> 29a710770eSDavid Lambert #include <sound/soc.h> 30a710770eSDavid Lambert #include <sound/soc-dapm.h> 31a710770eSDavid Lambert 32*23c7159aShuang lin static int dmic_daiops_trigger(struct snd_pcm_substream *substream, 33*23c7159aShuang lin int cmd, struct snd_soc_dai *dai) 34*23c7159aShuang lin { 35*23c7159aShuang lin struct gpio_desc *dmic_en = snd_soc_dai_get_drvdata(dai); 36*23c7159aShuang lin 37*23c7159aShuang lin if (!dmic_en) 38*23c7159aShuang lin return 0; 39*23c7159aShuang lin 40*23c7159aShuang lin switch (cmd) { 41*23c7159aShuang lin case SNDRV_PCM_TRIGGER_START: 42*23c7159aShuang lin case SNDRV_PCM_TRIGGER_RESUME: 43*23c7159aShuang lin case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 44*23c7159aShuang lin gpiod_set_value(dmic_en, 1); 45*23c7159aShuang lin break; 46*23c7159aShuang lin case SNDRV_PCM_TRIGGER_STOP: 47*23c7159aShuang lin case SNDRV_PCM_TRIGGER_SUSPEND: 48*23c7159aShuang lin case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 49*23c7159aShuang lin gpiod_set_value(dmic_en, 0); 50*23c7159aShuang lin break; 51*23c7159aShuang lin } 52*23c7159aShuang lin 53*23c7159aShuang lin return 0; 54*23c7159aShuang lin } 55*23c7159aShuang lin 56*23c7159aShuang lin static const struct snd_soc_dai_ops dmic_dai_ops = { 57*23c7159aShuang lin .trigger = dmic_daiops_trigger, 58*23c7159aShuang lin }; 59*23c7159aShuang lin 60a710770eSDavid Lambert static struct snd_soc_dai_driver dmic_dai = { 61a710770eSDavid Lambert .name = "dmic-hifi", 62a710770eSDavid Lambert .capture = { 63a710770eSDavid Lambert .stream_name = "Capture", 64a710770eSDavid Lambert .channels_min = 1, 65a710770eSDavid Lambert .channels_max = 8, 66a710770eSDavid Lambert .rates = SNDRV_PCM_RATE_CONTINUOUS, 67a710770eSDavid Lambert .formats = SNDRV_PCM_FMTBIT_S32_LE 68a710770eSDavid Lambert | SNDRV_PCM_FMTBIT_S24_LE 69a710770eSDavid Lambert | SNDRV_PCM_FMTBIT_S16_LE, 70a710770eSDavid Lambert }, 71*23c7159aShuang lin .ops = &dmic_dai_ops, 72a710770eSDavid Lambert }; 73a710770eSDavid Lambert 74*23c7159aShuang lin static int dmic_codec_probe(struct snd_soc_codec *codec) 75*23c7159aShuang lin { 76*23c7159aShuang lin struct gpio_desc *dmic_en; 77*23c7159aShuang lin 78*23c7159aShuang lin dmic_en = devm_gpiod_get_optional(codec->dev, 79*23c7159aShuang lin "dmicen", GPIOD_OUT_LOW); 80*23c7159aShuang lin if (IS_ERR(dmic_en)) 81*23c7159aShuang lin return PTR_ERR(dmic_en); 82*23c7159aShuang lin 83*23c7159aShuang lin snd_soc_codec_set_drvdata(codec, dmic_en); 84*23c7159aShuang lin 85*23c7159aShuang lin return 0; 86*23c7159aShuang lin } 87*23c7159aShuang lin 88d5e4b0adSMisael Lopez Cruz static const struct snd_soc_dapm_widget dmic_dapm_widgets[] = { 89d5e4b0adSMisael Lopez Cruz SND_SOC_DAPM_AIF_OUT("DMIC AIF", "Capture", 0, 90d5e4b0adSMisael Lopez Cruz SND_SOC_NOPM, 0, 0), 91d5e4b0adSMisael Lopez Cruz SND_SOC_DAPM_INPUT("DMic"), 92d5e4b0adSMisael Lopez Cruz }; 93d5e4b0adSMisael Lopez Cruz 94d5e4b0adSMisael Lopez Cruz static const struct snd_soc_dapm_route intercon[] = { 95d5e4b0adSMisael Lopez Cruz {"DMIC AIF", NULL, "DMic"}, 96d5e4b0adSMisael Lopez Cruz }; 97d5e4b0adSMisael Lopez Cruz 98*23c7159aShuang lin static const struct snd_soc_codec_driver soc_dmic = { 99*23c7159aShuang lin .probe = dmic_codec_probe, 100a73b8e89SKuninori Morimoto .component_driver = { 101a85f9da7SLars-Peter Clausen .dapm_widgets = dmic_dapm_widgets, 102a85f9da7SLars-Peter Clausen .num_dapm_widgets = ARRAY_SIZE(dmic_dapm_widgets), 103a85f9da7SLars-Peter Clausen .dapm_routes = intercon, 104a85f9da7SLars-Peter Clausen .num_dapm_routes = ARRAY_SIZE(intercon), 105a73b8e89SKuninori Morimoto }, 106d5e4b0adSMisael Lopez Cruz }; 107a710770eSDavid Lambert 1087a79e94eSBill Pemberton static int dmic_dev_probe(struct platform_device *pdev) 109a710770eSDavid Lambert { 110a710770eSDavid Lambert return snd_soc_register_codec(&pdev->dev, 111a710770eSDavid Lambert &soc_dmic, &dmic_dai, 1); 112a710770eSDavid Lambert } 113a710770eSDavid Lambert 1147a79e94eSBill Pemberton static int dmic_dev_remove(struct platform_device *pdev) 115a710770eSDavid Lambert { 116a710770eSDavid Lambert snd_soc_unregister_codec(&pdev->dev); 117a710770eSDavid Lambert return 0; 118a710770eSDavid Lambert } 119a710770eSDavid Lambert 120a710770eSDavid Lambert MODULE_ALIAS("platform:dmic-codec"); 121a710770eSDavid Lambert 12229685e20SArnaud Pouliquen static const struct of_device_id dmic_dev_match[] = { 12329685e20SArnaud Pouliquen {.compatible = "dmic-codec"}, 12429685e20SArnaud Pouliquen {} 12529685e20SArnaud Pouliquen }; 12629685e20SArnaud Pouliquen 127a710770eSDavid Lambert static struct platform_driver dmic_driver = { 128a710770eSDavid Lambert .driver = { 129a710770eSDavid Lambert .name = "dmic-codec", 13029685e20SArnaud Pouliquen .of_match_table = dmic_dev_match, 131a710770eSDavid Lambert }, 132a710770eSDavid Lambert .probe = dmic_dev_probe, 1337a79e94eSBill Pemberton .remove = dmic_dev_remove, 134a710770eSDavid Lambert }; 135a710770eSDavid Lambert 1365bbcc3c0SMark Brown module_platform_driver(dmic_driver); 137a710770eSDavid Lambert 138a710770eSDavid Lambert MODULE_DESCRIPTION("Generic DMIC driver"); 139a710770eSDavid Lambert MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>"); 140a710770eSDavid Lambert MODULE_LICENSE("GPL"); 141