3 * Asahi Kasei AK5386 Single-ended 24-Bit 192kHz delta-sigma ADC
5 * (c) 2013 Daniel Mack <zonque@gmail.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
12 #include <linux/module.h>
13 #include <linux/slab.h>
15 #include <linux/of_gpio.h>
16 #include <linux/of_device.h>
17 #include <sound/soc.h>
18 #include <sound/pcm.h>
19 #include <sound/initval.h>
25 static const struct snd_soc_dapm_widget ak5386_dapm_widgets
[] = {
26 SND_SOC_DAPM_INPUT("AINL"),
27 SND_SOC_DAPM_INPUT("AINR"),
30 static const struct snd_soc_dapm_route ak5386_dapm_routes
[] = {
31 { "Capture", NULL
, "AINL" },
32 { "Capture", NULL
, "AINR" },
35 static struct snd_soc_codec_driver soc_codec_ak5386
= {
36 .dapm_widgets
= ak5386_dapm_widgets
,
37 .num_dapm_widgets
= ARRAY_SIZE(ak5386_dapm_widgets
),
38 .dapm_routes
= ak5386_dapm_routes
,
39 .num_dapm_routes
= ARRAY_SIZE(ak5386_dapm_routes
),
42 static int ak5386_set_dai_fmt(struct snd_soc_dai
*codec_dai
,
45 struct snd_soc_codec
*codec
= codec_dai
->codec
;
47 format
&= SND_SOC_DAIFMT_FORMAT_MASK
;
48 if (format
!= SND_SOC_DAIFMT_LEFT_J
&&
49 format
!= SND_SOC_DAIFMT_I2S
) {
50 dev_err(codec
->dev
, "Invalid DAI format\n");
57 static int ak5386_hw_params(struct snd_pcm_substream
*substream
,
58 struct snd_pcm_hw_params
*params
,
59 struct snd_soc_dai
*dai
)
61 struct snd_soc_codec
*codec
= dai
->codec
;
62 struct ak5386_priv
*priv
= snd_soc_codec_get_drvdata(codec
);
67 * All external clocks (MCLK, SCLK and LRCK) must be present unless
68 * PDN pin = āLā. If these clocks are not provided, the AK5386 may
69 * draw excess current due to its use of internal dynamically
70 * refreshed logic. If the external clocks are not present, place
71 * the AK5386 in power-down mode (PDN pin = āLā).
74 if (gpio_is_valid(priv
->reset_gpio
))
75 gpio_set_value(priv
->reset_gpio
, 1);
80 static int ak5386_hw_free(struct snd_pcm_substream
*substream
,
81 struct snd_soc_dai
*dai
)
83 struct snd_soc_codec
*codec
= dai
->codec
;
84 struct ak5386_priv
*priv
= snd_soc_codec_get_drvdata(codec
);
86 if (gpio_is_valid(priv
->reset_gpio
))
87 gpio_set_value(priv
->reset_gpio
, 0);
92 static const struct snd_soc_dai_ops ak5386_dai_ops
= {
93 .set_fmt
= ak5386_set_dai_fmt
,
94 .hw_params
= ak5386_hw_params
,
95 .hw_free
= ak5386_hw_free
,
98 static struct snd_soc_dai_driver ak5386_dai
= {
99 .name
= "ak5386-hifi",
101 .stream_name
= "Capture",
104 .rates
= SNDRV_PCM_RATE_8000_192000
,
105 .formats
= SNDRV_PCM_FMTBIT_S8
|
106 SNDRV_PCM_FMTBIT_S16_LE
|
107 SNDRV_PCM_FMTBIT_S24_LE
|
108 SNDRV_PCM_FMTBIT_S24_3LE
,
110 .ops
= &ak5386_dai_ops
,
114 static const struct of_device_id ak5386_dt_ids
[] = {
115 { .compatible
= "asahi-kasei,ak5386", },
118 MODULE_DEVICE_TABLE(of
, ak5386_dt_ids
);
121 static int ak5386_probe(struct platform_device
*pdev
)
123 struct device
*dev
= &pdev
->dev
;
124 struct ak5386_priv
*priv
;
126 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
130 priv
->reset_gpio
= -EINVAL
;
131 dev_set_drvdata(dev
, priv
);
133 if (of_match_device(of_match_ptr(ak5386_dt_ids
), dev
))
134 priv
->reset_gpio
= of_get_named_gpio(dev
->of_node
,
137 if (gpio_is_valid(priv
->reset_gpio
))
138 if (devm_gpio_request_one(dev
, priv
->reset_gpio
,
141 priv
->reset_gpio
= -EINVAL
;
143 return snd_soc_register_codec(dev
, &soc_codec_ak5386
,
147 static int ak5386_remove(struct platform_device
*pdev
)
149 snd_soc_unregister_codec(&pdev
->dev
);
153 static struct platform_driver ak5386_driver
= {
154 .probe
= ak5386_probe
,
155 .remove
= ak5386_remove
,
158 .owner
= THIS_MODULE
,
159 .of_match_table
= of_match_ptr(ak5386_dt_ids
),
163 module_platform_driver(ak5386_driver
);
165 MODULE_DESCRIPTION("ASoC driver for AK5386 ADC");
166 MODULE_AUTHOR("Daniel Mack <zonque@gmail.com>");
167 MODULE_LICENSE("GPL");