0001
0002
0003
0004
0005
0006
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");