linux/sound/soc/codecs/adau7002.c
Agrawal, Akshu 7b57085a33
ASoC: ADAU7002: Add optional delay before start of capture
On capture through some of dmic we observe a glitch at the
start of record. This is because we start capturing even before
dmic is ready to send out data.
The optional delay will be applied after enabling the mic.

Signed-off-by: Akshu Agrawal <akshu.agrawal@amd.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
2019-01-08 13:05:14 +00:00

140 lines
3.4 KiB
C

/*
* ADAU7002 Stereo PDM-to-I2S/TDM converter driver
*
* Copyright 2014-2016 Analog Devices
* Author: Lars-Peter Clausen <lars@metafoo.de>
*
* Licensed under the GPL-2.
*/
#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <sound/soc.h>
struct adau7002_priv {
int wakeup_delay;
};
static int adau7002_aif_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
struct adau7002_priv *adau7002 =
snd_soc_component_get_drvdata(component);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
if (adau7002->wakeup_delay)
msleep(adau7002->wakeup_delay);
break;
}
return 0;
}
static int adau7002_component_probe(struct snd_soc_component *component)
{
struct adau7002_priv *adau7002;
adau7002 = devm_kzalloc(component->dev, sizeof(*adau7002),
GFP_KERNEL);
if (!adau7002)
return -ENOMEM;
device_property_read_u32(component->dev, "wakeup-delay-ms",
&adau7002->wakeup_delay);
snd_soc_component_set_drvdata(component, adau7002);
return 0;
}
static const struct snd_soc_dapm_widget adau7002_widgets[] = {
SND_SOC_DAPM_AIF_OUT_E("ADAU AIF", "Capture", 0,
SND_SOC_NOPM, 0, 0, adau7002_aif_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_INPUT("PDM_DAT"),
SND_SOC_DAPM_REGULATOR_SUPPLY("IOVDD", 0, 0),
};
static const struct snd_soc_dapm_route adau7002_routes[] = {
{ "ADAU AIF", NULL, "PDM_DAT"},
{ "Capture", NULL, "PDM_DAT" },
{ "Capture", NULL, "IOVDD" },
};
static struct snd_soc_dai_driver adau7002_dai = {
.name = "adau7002-hifi",
.capture = {
.stream_name = "Capture",
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_96000,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE |
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE,
.sig_bits = 20,
},
};
static const struct snd_soc_component_driver adau7002_component_driver = {
.probe = adau7002_component_probe,
.dapm_widgets = adau7002_widgets,
.num_dapm_widgets = ARRAY_SIZE(adau7002_widgets),
.dapm_routes = adau7002_routes,
.num_dapm_routes = ARRAY_SIZE(adau7002_routes),
.idle_bias_on = 1,
.use_pmdown_time = 1,
.endianness = 1,
.non_legacy_dai_naming = 1,
};
static int adau7002_probe(struct platform_device *pdev)
{
return devm_snd_soc_register_component(&pdev->dev,
&adau7002_component_driver,
&adau7002_dai, 1);
}
static int adau7002_remove(struct platform_device *pdev)
{
return 0;
}
#ifdef CONFIG_OF
static const struct of_device_id adau7002_dt_ids[] = {
{ .compatible = "adi,adau7002", },
{ }
};
MODULE_DEVICE_TABLE(of, adau7002_dt_ids);
#endif
#ifdef CONFIG_ACPI
static const struct acpi_device_id adau7002_acpi_match[] = {
{ "ADAU7002", 0 },
{},
};
MODULE_DEVICE_TABLE(acpi, adau7002_acpi_match);
#endif
static struct platform_driver adau7002_driver = {
.driver = {
.name = "adau7002",
.of_match_table = of_match_ptr(adau7002_dt_ids),
.acpi_match_table = ACPI_PTR(adau7002_acpi_match),
},
.probe = adau7002_probe,
.remove = adau7002_remove,
};
module_platform_driver(adau7002_driver);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("ADAU7002 Stereo PDM-to-I2S/TDM Converter driver");
MODULE_LICENSE("GPL v2");