Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * ADAU7002 Stereo PDM-to-I2S/TDM converter driver
0004  *
0005  * Copyright 2014-2016 Analog Devices
0006  *  Author: Lars-Peter Clausen <lars@metafoo.de>
0007  */
0008 
0009 #include <linux/acpi.h>
0010 #include <linux/delay.h>
0011 #include <linux/init.h>
0012 #include <linux/module.h>
0013 #include <linux/of.h>
0014 #include <linux/platform_device.h>
0015 
0016 #include <sound/soc.h>
0017 
0018 struct adau7002_priv {
0019     int wakeup_delay;
0020 };
0021 
0022 static int adau7002_aif_event(struct snd_soc_dapm_widget *w,
0023                   struct snd_kcontrol *kcontrol, int event)
0024 {
0025     struct snd_soc_component *component =
0026             snd_soc_dapm_to_component(w->dapm);
0027     struct adau7002_priv *adau7002 =
0028             snd_soc_component_get_drvdata(component);
0029 
0030     switch (event) {
0031     case SND_SOC_DAPM_POST_PMU:
0032         if (adau7002->wakeup_delay)
0033             msleep(adau7002->wakeup_delay);
0034         break;
0035     }
0036 
0037     return 0;
0038 }
0039 
0040 static int adau7002_component_probe(struct snd_soc_component *component)
0041 {
0042     struct adau7002_priv *adau7002;
0043 
0044     adau7002 = devm_kzalloc(component->dev, sizeof(*adau7002),
0045                 GFP_KERNEL);
0046     if (!adau7002)
0047         return -ENOMEM;
0048 
0049     device_property_read_u32(component->dev, "wakeup-delay-ms",
0050                  &adau7002->wakeup_delay);
0051 
0052     snd_soc_component_set_drvdata(component, adau7002);
0053 
0054     return 0;
0055 }
0056 
0057 static const struct snd_soc_dapm_widget adau7002_widgets[] = {
0058     SND_SOC_DAPM_AIF_OUT_E("ADAU AIF", "Capture", 0,
0059                    SND_SOC_NOPM, 0, 0, adau7002_aif_event,
0060                    SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
0061     SND_SOC_DAPM_INPUT("PDM_DAT"),
0062     SND_SOC_DAPM_REGULATOR_SUPPLY("IOVDD", 0, 0),
0063 };
0064 
0065 static const struct snd_soc_dapm_route adau7002_routes[] = {
0066     { "ADAU AIF", NULL, "PDM_DAT"},
0067     { "Capture", NULL, "PDM_DAT" },
0068     { "Capture", NULL, "IOVDD" },
0069 };
0070 
0071 static struct snd_soc_dai_driver adau7002_dai = {
0072     .name = "adau7002-hifi",
0073     .capture = {
0074         .stream_name = "Capture",
0075         .channels_min = 2,
0076         .channels_max = 2,
0077         .rates = SNDRV_PCM_RATE_8000_96000,
0078         .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE |
0079             SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE |
0080             SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE,
0081         .sig_bits = 20,
0082     },
0083 };
0084 
0085 static const struct snd_soc_component_driver adau7002_component_driver = {
0086     .probe          = adau7002_component_probe,
0087     .dapm_widgets       = adau7002_widgets,
0088     .num_dapm_widgets   = ARRAY_SIZE(adau7002_widgets),
0089     .dapm_routes        = adau7002_routes,
0090     .num_dapm_routes    = ARRAY_SIZE(adau7002_routes),
0091     .idle_bias_on       = 1,
0092     .use_pmdown_time    = 1,
0093     .endianness     = 1,
0094 };
0095 
0096 static int adau7002_probe(struct platform_device *pdev)
0097 {
0098     return devm_snd_soc_register_component(&pdev->dev,
0099             &adau7002_component_driver,
0100             &adau7002_dai, 1);
0101 }
0102 
0103 static int adau7002_remove(struct platform_device *pdev)
0104 {
0105     return 0;
0106 }
0107 
0108 #ifdef CONFIG_OF
0109 static const struct of_device_id adau7002_dt_ids[] = {
0110     { .compatible = "adi,adau7002", },
0111     { }
0112 };
0113 MODULE_DEVICE_TABLE(of, adau7002_dt_ids);
0114 #endif
0115 
0116 #ifdef CONFIG_ACPI
0117 static const struct acpi_device_id adau7002_acpi_match[] = {
0118     { "ADAU7002", 0 },
0119     {},
0120 };
0121 MODULE_DEVICE_TABLE(acpi, adau7002_acpi_match);
0122 #endif
0123 
0124 static struct platform_driver adau7002_driver = {
0125     .driver = {
0126         .name = "adau7002",
0127         .of_match_table = of_match_ptr(adau7002_dt_ids),
0128         .acpi_match_table = ACPI_PTR(adau7002_acpi_match),
0129     },
0130     .probe = adau7002_probe,
0131     .remove = adau7002_remove,
0132 };
0133 module_platform_driver(adau7002_driver);
0134 
0135 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
0136 MODULE_DESCRIPTION("ADAU7002 Stereo PDM-to-I2S/TDM Converter driver");
0137 MODULE_LICENSE("GPL v2");