aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2014-05-27 04:53:19 -0400
committerMark Brown <broonie@linaro.org>2014-05-27 15:54:51 -0400
commit2923af024681508132881c9e5ddd65cd51b0d8e3 (patch)
treeb4f3c3835312c4b9675a9fc73b84e460b1243974 /sound/soc
parentdab464b60b2435a2aaae3630266db8ad130b7fad (diff)
ASoC: Add ADAU1381/ADAU1781 audio CODEC support
This patch adds support for the Analog Devices ADAU1381 and ADAU1781 audio CODECs. The device is a low-power, 24-bit stereo audio CODEC with multiple analog inputs and outputs, two digital microphone inputs and an I2S interface. The device can be controlled either using I2C or SPI. The main difference between the two variants is that the ADAU1781 has a freely programmable SigmaDSP processor, while the ADAU1381 has a fixed function wind noise reduction filter. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/codecs/Kconfig16
-rw-r--r--sound/soc/codecs/Makefile6
-rw-r--r--sound/soc/codecs/adau1781-i2c.c58
-rw-r--r--sound/soc/codecs/adau1781-spi.c75
-rw-r--r--sound/soc/codecs/adau1781.c511
-rw-r--r--sound/soc/codecs/adau1781.h23
6 files changed, 689 insertions, 0 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 4233ed118c48..dd5deea9221a 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -25,6 +25,8 @@ config SND_SOC_ALL_CODECS
25 select SND_SOC_ADAU1373 if I2C 25 select SND_SOC_ADAU1373 if I2C
26 select SND_SOC_ADAU1761_I2C if I2C 26 select SND_SOC_ADAU1761_I2C if I2C
27 select SND_SOC_ADAU1761_SPI if SPI 27 select SND_SOC_ADAU1761_SPI if SPI
28 select SND_SOC_ADAU1781_I2C if I2C
29 select SND_SOC_ADAU1781_SPI if SPI
28 select SND_SOC_ADAV801 if SPI_MASTER 30 select SND_SOC_ADAV801 if SPI_MASTER
29 select SND_SOC_ADAV803 if I2C 31 select SND_SOC_ADAV803 if I2C
30 select SND_SOC_ADAU1977_SPI if SPI_MASTER 32 select SND_SOC_ADAU1977_SPI if SPI_MASTER
@@ -238,6 +240,20 @@ config SND_SOC_ADAU1761_SPI
238 select SND_SOC_ADAU1761 240 select SND_SOC_ADAU1761
239 select REGMAP_SPI 241 select REGMAP_SPI
240 242
243config SND_SOC_ADAU1781
244 select SND_SOC_ADAU17X1
245 tristate
246
247config SND_SOC_ADAU1781_I2C
248 tristate
249 select SND_SOC_ADAU1781
250 select REGMAP_I2C
251
252config SND_SOC_ADAU1781_SPI
253 tristate
254 select SND_SOC_ADAU1781
255 select REGMAP_SPI
256
241config SND_SOC_ADAU1977 257config SND_SOC_ADAU1977
242 tristate 258 tristate
243 259
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index e96499ca76bd..4ef1a1ed5f92 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -13,6 +13,9 @@ snd-soc-adau17x1-objs := adau17x1.o
13snd-soc-adau1761-objs := adau1761.o 13snd-soc-adau1761-objs := adau1761.o
14snd-soc-adau1761-i2c-objs := adau1761-i2c.o 14snd-soc-adau1761-i2c-objs := adau1761-i2c.o
15snd-soc-adau1761-spi-objs := adau1761-spi.o 15snd-soc-adau1761-spi-objs := adau1761-spi.o
16snd-soc-adau1781-objs := adau1781.o
17snd-soc-adau1781-i2c-objs := adau1781-i2c.o
18snd-soc-adau1781-spi-objs := adau1781-spi.o
16snd-soc-adau1977-objs := adau1977.o 19snd-soc-adau1977-objs := adau1977.o
17snd-soc-adau1977-spi-objs := adau1977-spi.o 20snd-soc-adau1977-spi-objs := adau1977-spi.o
18snd-soc-adau1977-i2c-objs := adau1977-i2c.o 21snd-soc-adau1977-i2c-objs := adau1977-i2c.o
@@ -166,6 +169,9 @@ obj-$(CONFIG_SND_SOC_ADAU17X1) += snd-soc-adau17x1.o
166obj-$(CONFIG_SND_SOC_ADAU1761) += snd-soc-adau1761.o 169obj-$(CONFIG_SND_SOC_ADAU1761) += snd-soc-adau1761.o
167obj-$(CONFIG_SND_SOC_ADAU1761_I2C) += snd-soc-adau1761-i2c.o 170obj-$(CONFIG_SND_SOC_ADAU1761_I2C) += snd-soc-adau1761-i2c.o
168obj-$(CONFIG_SND_SOC_ADAU1761_SPI) += snd-soc-adau1761-spi.o 171obj-$(CONFIG_SND_SOC_ADAU1761_SPI) += snd-soc-adau1761-spi.o
172obj-$(CONFIG_SND_SOC_ADAU1781) += snd-soc-adau1781.o
173obj-$(CONFIG_SND_SOC_ADAU1781_I2C) += snd-soc-adau1781-i2c.o
174obj-$(CONFIG_SND_SOC_ADAU1781_SPI) += snd-soc-adau1781-spi.o
169obj-$(CONFIG_SND_SOC_ADAU1977) += snd-soc-adau1977.o 175obj-$(CONFIG_SND_SOC_ADAU1977) += snd-soc-adau1977.o
170obj-$(CONFIG_SND_SOC_ADAU1977_SPI) += snd-soc-adau1977-spi.o 176obj-$(CONFIG_SND_SOC_ADAU1977_SPI) += snd-soc-adau1977-spi.o
171obj-$(CONFIG_SND_SOC_ADAU1977_I2C) += snd-soc-adau1977-i2c.o 177obj-$(CONFIG_SND_SOC_ADAU1977_I2C) += snd-soc-adau1977-i2c.o
diff --git a/sound/soc/codecs/adau1781-i2c.c b/sound/soc/codecs/adau1781-i2c.c
new file mode 100644
index 000000000000..2ce4362ccec1
--- /dev/null
+++ b/sound/soc/codecs/adau1781-i2c.c
@@ -0,0 +1,58 @@
1/*
2 * Driver for ADAU1381/ADAU1781 CODEC
3 *
4 * Copyright 2014 Analog Devices Inc.
5 * Author: Lars-Peter Clausen <lars@metafoo.de>
6 *
7 * Licensed under the GPL-2.
8 */
9
10#include <linux/i2c.h>
11#include <linux/mod_devicetable.h>
12#include <linux/module.h>
13#include <linux/regmap.h>
14#include <sound/soc.h>
15
16#include "adau1781.h"
17
18static int adau1781_i2c_probe(struct i2c_client *client,
19 const struct i2c_device_id *id)
20{
21 struct regmap_config config;
22
23 config = adau1781_regmap_config;
24 config.val_bits = 8;
25 config.reg_bits = 16;
26
27 return adau1781_probe(&client->dev,
28 devm_regmap_init_i2c(client, &config),
29 id->driver_data, NULL);
30}
31
32static int adau1781_i2c_remove(struct i2c_client *client)
33{
34 snd_soc_unregister_codec(&client->dev);
35 return 0;
36}
37
38static const struct i2c_device_id adau1781_i2c_ids[] = {
39 { "adau1381", ADAU1381 },
40 { "adau1781", ADAU1781 },
41 { }
42};
43MODULE_DEVICE_TABLE(i2c, adau1781_i2c_ids);
44
45static struct i2c_driver adau1781_i2c_driver = {
46 .driver = {
47 .name = "adau1781",
48 .owner = THIS_MODULE,
49 },
50 .probe = adau1781_i2c_probe,
51 .remove = adau1781_i2c_remove,
52 .id_table = adau1781_i2c_ids,
53};
54module_i2c_driver(adau1781_i2c_driver);
55
56MODULE_DESCRIPTION("ASoC ADAU1381/ADAU1781 CODEC I2C driver");
57MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
58MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/adau1781-spi.c b/sound/soc/codecs/adau1781-spi.c
new file mode 100644
index 000000000000..194686716bbe
--- /dev/null
+++ b/sound/soc/codecs/adau1781-spi.c
@@ -0,0 +1,75 @@
1/*
2 * Driver for ADAU1381/ADAU1781 CODEC
3 *
4 * Copyright 2014 Analog Devices Inc.
5 * Author: Lars-Peter Clausen <lars@metafoo.de>
6 *
7 * Licensed under the GPL-2.
8 */
9
10#include <linux/mod_devicetable.h>
11#include <linux/module.h>
12#include <linux/regmap.h>
13#include <linux/spi/spi.h>
14#include <sound/soc.h>
15
16#include "adau1781.h"
17
18static void adau1781_spi_switch_mode(struct device *dev)
19{
20 struct spi_device *spi = to_spi_device(dev);
21
22 /*
23 * To get the device into SPI mode CLATCH has to be pulled low three
24 * times. Do this by issuing three dummy reads.
25 */
26 spi_w8r8(spi, 0x00);
27 spi_w8r8(spi, 0x00);
28 spi_w8r8(spi, 0x00);
29}
30
31static int adau1781_spi_probe(struct spi_device *spi)
32{
33 const struct spi_device_id *id = spi_get_device_id(spi);
34 struct regmap_config config;
35
36 if (!id)
37 return -EINVAL;
38
39 config = adau1781_regmap_config;
40 config.val_bits = 8;
41 config.reg_bits = 24;
42 config.read_flag_mask = 0x1;
43
44 return adau1781_probe(&spi->dev,
45 devm_regmap_init_spi(spi, &config),
46 id->driver_data, adau1781_spi_switch_mode);
47}
48
49static int adau1781_spi_remove(struct spi_device *spi)
50{
51 snd_soc_unregister_codec(&spi->dev);
52 return 0;
53}
54
55static const struct spi_device_id adau1781_spi_id[] = {
56 { "adau1381", ADAU1381 },
57 { "adau1781", ADAU1781 },
58 { }
59};
60MODULE_DEVICE_TABLE(spi, adau1781_spi_id);
61
62static struct spi_driver adau1781_spi_driver = {
63 .driver = {
64 .name = "adau1781",
65 .owner = THIS_MODULE,
66 },
67 .probe = adau1781_spi_probe,
68 .remove = adau1781_spi_remove,
69 .id_table = adau1781_spi_id,
70};
71module_spi_driver(adau1781_spi_driver);
72
73MODULE_DESCRIPTION("ASoC ADAU1381/ADAU1781 CODEC SPI driver");
74MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
75MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/adau1781.c b/sound/soc/codecs/adau1781.c
new file mode 100644
index 000000000000..045a61413840
--- /dev/null
+++ b/sound/soc/codecs/adau1781.c
@@ -0,0 +1,511 @@
1/*
2 * Driver for ADAU1781/ADAU1781 codec
3 *
4 * Copyright 2011-2013 Analog Devices Inc.
5 * Author: Lars-Peter Clausen <lars@metafoo.de>
6 *
7 * Licensed under the GPL-2 or later.
8 */
9
10#include <linux/module.h>
11#include <linux/init.h>
12#include <linux/i2c.h>
13#include <linux/spi/spi.h>
14#include <linux/slab.h>
15#include <sound/core.h>
16#include <sound/pcm.h>
17#include <sound/pcm_params.h>
18#include <sound/soc.h>
19#include <sound/tlv.h>
20#include <linux/platform_data/adau17x1.h>
21
22#include "adau17x1.h"
23#include "adau1781.h"
24
25#define ADAU1781_DMIC_BEEP_CTRL 0x4008
26#define ADAU1781_LEFT_PGA 0x400e
27#define ADAU1781_RIGHT_PGA 0x400f
28#define ADAU1781_LEFT_PLAYBACK_MIXER 0x401c
29#define ADAU1781_RIGHT_PLAYBACK_MIXER 0x401e
30#define ADAU1781_MONO_PLAYBACK_MIXER 0x401f
31#define ADAU1781_LEFT_LINEOUT 0x4025
32#define ADAU1781_RIGHT_LINEOUT 0x4026
33#define ADAU1781_SPEAKER 0x4027
34#define ADAU1781_BEEP_ZC 0x4028
35#define ADAU1781_DEJITTER 0x4032
36#define ADAU1781_DIG_PWDN0 0x4080
37#define ADAU1781_DIG_PWDN1 0x4081
38
39#define ADAU1781_INPUT_DIFFERNTIAL BIT(3)
40
41#define ADAU1381_FIRMWARE "adau1381.bin"
42#define ADAU1781_FIRMWARE "adau1781.bin"
43
44static const struct reg_default adau1781_reg_defaults[] = {
45 { ADAU1781_DMIC_BEEP_CTRL, 0x00 },
46 { ADAU1781_LEFT_PGA, 0xc7 },
47 { ADAU1781_RIGHT_PGA, 0xc7 },
48 { ADAU1781_LEFT_PLAYBACK_MIXER, 0x00 },
49 { ADAU1781_RIGHT_PLAYBACK_MIXER, 0x00 },
50 { ADAU1781_MONO_PLAYBACK_MIXER, 0x00 },
51 { ADAU1781_LEFT_LINEOUT, 0x00 },
52 { ADAU1781_RIGHT_LINEOUT, 0x00 },
53 { ADAU1781_SPEAKER, 0x00 },
54 { ADAU1781_BEEP_ZC, 0x19 },
55 { ADAU1781_DEJITTER, 0x60 },
56 { ADAU1781_DIG_PWDN1, 0x0c },
57 { ADAU1781_DIG_PWDN1, 0x00 },
58 { ADAU17X1_CLOCK_CONTROL, 0x00 },
59 { ADAU17X1_PLL_CONTROL, 0x00 },
60 { ADAU17X1_REC_POWER_MGMT, 0x00 },
61 { ADAU17X1_MICBIAS, 0x04 },
62 { ADAU17X1_SERIAL_PORT0, 0x00 },
63 { ADAU17X1_SERIAL_PORT1, 0x00 },
64 { ADAU17X1_CONVERTER0, 0x00 },
65 { ADAU17X1_CONVERTER1, 0x00 },
66 { ADAU17X1_LEFT_INPUT_DIGITAL_VOL, 0x00 },
67 { ADAU17X1_RIGHT_INPUT_DIGITAL_VOL, 0x00 },
68 { ADAU17X1_ADC_CONTROL, 0x00 },
69 { ADAU17X1_PLAY_POWER_MGMT, 0x00 },
70 { ADAU17X1_DAC_CONTROL0, 0x00 },
71 { ADAU17X1_DAC_CONTROL1, 0x00 },
72 { ADAU17X1_DAC_CONTROL2, 0x00 },
73 { ADAU17X1_SERIAL_PORT_PAD, 0x00 },
74 { ADAU17X1_CONTROL_PORT_PAD0, 0x00 },
75 { ADAU17X1_CONTROL_PORT_PAD1, 0x00 },
76 { ADAU17X1_DSP_SAMPLING_RATE, 0x01 },
77 { ADAU17X1_SERIAL_INPUT_ROUTE, 0x00 },
78 { ADAU17X1_SERIAL_OUTPUT_ROUTE, 0x00 },
79 { ADAU17X1_DSP_ENABLE, 0x00 },
80 { ADAU17X1_DSP_RUN, 0x00 },
81 { ADAU17X1_SERIAL_SAMPLING_RATE, 0x00 },
82};
83
84static const DECLARE_TLV_DB_SCALE(adau1781_speaker_tlv, 0, 200, 0);
85
86static const DECLARE_TLV_DB_RANGE(adau1781_pga_tlv,
87 0, 1, TLV_DB_SCALE_ITEM(0, 600, 0),
88 2, 3, TLV_DB_SCALE_ITEM(1000, 400, 0),
89 4, 4, TLV_DB_SCALE_ITEM(1700, 0, 0),
90 5, 7, TLV_DB_SCALE_ITEM(2000, 600, 0)
91);
92
93static const DECLARE_TLV_DB_RANGE(adau1781_beep_tlv,
94 0, 1, TLV_DB_SCALE_ITEM(0, 600, 0),
95 2, 3, TLV_DB_SCALE_ITEM(1000, 400, 0),
96 4, 4, TLV_DB_SCALE_ITEM(-2300, 0, 0),
97 5, 7, TLV_DB_SCALE_ITEM(2000, 600, 0)
98);
99
100static const DECLARE_TLV_DB_SCALE(adau1781_sidetone_tlv, -1800, 300, 1);
101
102static const char * const adau1781_speaker_bias_select_text[] = {
103 "Normal operation", "Power saving", "Enhanced performance",
104};
105
106static const char * const adau1781_bias_select_text[] = {
107 "Normal operation", "Extreme power saving", "Power saving",
108 "Enhanced performance",
109};
110
111static SOC_ENUM_SINGLE_DECL(adau1781_adc_bias_enum,
112 ADAU17X1_REC_POWER_MGMT, 3, adau1781_bias_select_text);
113static SOC_ENUM_SINGLE_DECL(adau1781_speaker_bias_enum,
114 ADAU17X1_PLAY_POWER_MGMT, 6, adau1781_speaker_bias_select_text);
115static SOC_ENUM_SINGLE_DECL(adau1781_dac_bias_enum,
116 ADAU17X1_PLAY_POWER_MGMT, 4, adau1781_bias_select_text);
117static SOC_ENUM_SINGLE_DECL(adau1781_playback_bias_enum,
118 ADAU17X1_PLAY_POWER_MGMT, 2, adau1781_bias_select_text);
119static SOC_ENUM_SINGLE_DECL(adau1781_capture_bias_enum,
120 ADAU17X1_REC_POWER_MGMT, 1, adau1781_bias_select_text);
121
122static const struct snd_kcontrol_new adau1781_controls[] = {
123 SOC_SINGLE_TLV("Beep Capture Volume", ADAU1781_DMIC_BEEP_CTRL, 0, 7, 0,
124 adau1781_beep_tlv),
125 SOC_DOUBLE_R_TLV("PGA Capture Volume", ADAU1781_LEFT_PGA,
126 ADAU1781_RIGHT_PGA, 5, 7, 0, adau1781_pga_tlv),
127 SOC_DOUBLE_R("PGA Capture Switch", ADAU1781_LEFT_PGA,
128 ADAU1781_RIGHT_PGA, 1, 1, 0),
129
130 SOC_DOUBLE_R("Lineout Playback Switch", ADAU1781_LEFT_LINEOUT,
131 ADAU1781_RIGHT_LINEOUT, 1, 1, 0),
132 SOC_SINGLE("Beep ZC Switch", ADAU1781_BEEP_ZC, 0, 1, 0),
133
134 SOC_SINGLE("Mono Playback Switch", ADAU1781_MONO_PLAYBACK_MIXER,
135 0, 1, 0),
136 SOC_SINGLE_TLV("Mono Playback Volume", ADAU1781_SPEAKER, 6, 3, 0,
137 adau1781_speaker_tlv),
138
139 SOC_ENUM("ADC Bias", adau1781_adc_bias_enum),
140 SOC_ENUM("DAC Bias", adau1781_dac_bias_enum),
141 SOC_ENUM("Capture Bias", adau1781_capture_bias_enum),
142 SOC_ENUM("Playback Bias", adau1781_playback_bias_enum),
143 SOC_ENUM("Speaker Bias", adau1781_speaker_bias_enum),
144};
145
146static const struct snd_kcontrol_new adau1781_beep_mixer_controls[] = {
147 SOC_DAPM_SINGLE("Beep Capture Switch", ADAU1781_DMIC_BEEP_CTRL,
148 3, 1, 0),
149};
150
151static const struct snd_kcontrol_new adau1781_left_mixer_controls[] = {
152 SOC_DAPM_SINGLE_AUTODISABLE("Switch",
153 ADAU1781_LEFT_PLAYBACK_MIXER, 5, 1, 0),
154 SOC_DAPM_SINGLE_TLV("Beep Playback Volume",
155 ADAU1781_LEFT_PLAYBACK_MIXER, 1, 8, 0, adau1781_sidetone_tlv),
156};
157
158static const struct snd_kcontrol_new adau1781_right_mixer_controls[] = {
159 SOC_DAPM_SINGLE_AUTODISABLE("Switch",
160 ADAU1781_RIGHT_PLAYBACK_MIXER, 6, 1, 0),
161 SOC_DAPM_SINGLE_TLV("Beep Playback Volume",
162 ADAU1781_LEFT_PLAYBACK_MIXER, 1, 8, 0, adau1781_sidetone_tlv),
163};
164
165static const struct snd_kcontrol_new adau1781_mono_mixer_controls[] = {
166 SOC_DAPM_SINGLE_AUTODISABLE("Left Switch",
167 ADAU1781_MONO_PLAYBACK_MIXER, 7, 1, 0),
168 SOC_DAPM_SINGLE_AUTODISABLE("Right Switch",
169 ADAU1781_MONO_PLAYBACK_MIXER, 6, 1, 0),
170 SOC_DAPM_SINGLE_TLV("Beep Playback Volume",
171 ADAU1781_MONO_PLAYBACK_MIXER, 2, 8, 0, adau1781_sidetone_tlv),
172};
173
174static int adau1781_dejitter_fixup(struct snd_soc_dapm_widget *w,
175 struct snd_kcontrol *kcontrol, int event)
176{
177 struct snd_soc_codec *codec = w->codec;
178 struct adau *adau = snd_soc_codec_get_drvdata(codec);
179
180 /* After any power changes have been made the dejitter circuit
181 * has to be reinitialized. */
182 regmap_write(adau->regmap, ADAU1781_DEJITTER, 0);
183 if (!adau->master)
184 regmap_write(adau->regmap, ADAU1781_DEJITTER, 5);
185
186 return 0;
187}
188
189static const struct snd_soc_dapm_widget adau1781_dapm_widgets[] = {
190 SND_SOC_DAPM_PGA("Left PGA", ADAU1781_LEFT_PGA, 0, 0, NULL, 0),
191 SND_SOC_DAPM_PGA("Right PGA", ADAU1781_RIGHT_PGA, 0, 0, NULL, 0),
192
193 SND_SOC_DAPM_OUT_DRV("Speaker", ADAU1781_SPEAKER, 0, 0, NULL, 0),
194
195 SOC_MIXER_NAMED_CTL_ARRAY("Beep Mixer", ADAU17X1_MICBIAS, 4, 0,
196 adau1781_beep_mixer_controls),
197
198 SOC_MIXER_ARRAY("Left Lineout Mixer", SND_SOC_NOPM, 0, 0,
199 adau1781_left_mixer_controls),
200 SOC_MIXER_ARRAY("Right Lineout Mixer", SND_SOC_NOPM, 0, 0,
201 adau1781_right_mixer_controls),
202 SOC_MIXER_ARRAY("Mono Mixer", SND_SOC_NOPM, 0, 0,
203 adau1781_mono_mixer_controls),
204
205 SND_SOC_DAPM_SUPPLY("Serial Input Routing", ADAU1781_DIG_PWDN0,
206 2, 0, NULL, 0),
207 SND_SOC_DAPM_SUPPLY("Serial Output Routing", ADAU1781_DIG_PWDN0,
208 3, 0, NULL, 0),
209 SND_SOC_DAPM_SUPPLY("Clock Domain Transfer", ADAU1781_DIG_PWDN0,
210 5, 0, NULL, 0),
211 SND_SOC_DAPM_SUPPLY("Serial Ports", ADAU1781_DIG_PWDN0, 4, 0, NULL, 0),
212 SND_SOC_DAPM_SUPPLY("ADC Engine", ADAU1781_DIG_PWDN0, 7, 0, NULL, 0),
213 SND_SOC_DAPM_SUPPLY("DAC Engine", ADAU1781_DIG_PWDN1, 0, 0, NULL, 0),
214 SND_SOC_DAPM_SUPPLY("Digital Mic", ADAU1781_DIG_PWDN1, 1, 0, NULL, 0),
215
216 SND_SOC_DAPM_SUPPLY("Sound Engine", ADAU1781_DIG_PWDN0, 0, 0, NULL, 0),
217 SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, ADAU1781_DIG_PWDN0, 1, 0, NULL, 0),
218
219 SND_SOC_DAPM_SUPPLY("Zero Crossing Detector", ADAU1781_DIG_PWDN1, 2, 0,
220 NULL, 0),
221
222 SND_SOC_DAPM_POST("Dejitter fixup", adau1781_dejitter_fixup),
223
224 SND_SOC_DAPM_INPUT("BEEP"),
225
226 SND_SOC_DAPM_OUTPUT("AOUTL"),
227 SND_SOC_DAPM_OUTPUT("AOUTR"),
228 SND_SOC_DAPM_OUTPUT("SP"),
229 SND_SOC_DAPM_INPUT("LMIC"),
230 SND_SOC_DAPM_INPUT("RMIC"),
231};
232
233static const struct snd_soc_dapm_route adau1781_dapm_routes[] = {
234 { "Left Lineout Mixer", NULL, "Left Playback Enable" },
235 { "Right Lineout Mixer", NULL, "Right Playback Enable" },
236
237 { "Left Lineout Mixer", "Beep Playback Volume", "Beep Mixer" },
238 { "Left Lineout Mixer", "Switch", "Left DAC" },
239
240 { "Right Lineout Mixer", "Beep Playback Volume", "Beep Mixer" },
241 { "Right Lineout Mixer", "Switch", "Right DAC" },
242
243 { "Mono Mixer", "Beep Playback Volume", "Beep Mixer" },
244 { "Mono Mixer", "Right Switch", "Right DAC" },
245 { "Mono Mixer", "Left Switch", "Left DAC" },
246 { "Speaker", NULL, "Mono Mixer" },
247
248 { "Mono Mixer", NULL, "SYSCLK" },
249 { "Left Lineout Mixer", NULL, "SYSCLK" },
250 { "Left Lineout Mixer", NULL, "SYSCLK" },
251
252 { "Beep Mixer", "Beep Capture Switch", "BEEP" },
253 { "Beep Mixer", NULL, "Zero Crossing Detector" },
254
255 { "Left DAC", NULL, "DAC Engine" },
256 { "Right DAC", NULL, "DAC Engine" },
257
258 { "Sound Engine", NULL, "SYSCLK" },
259 { "DSP", NULL, "Sound Engine" },
260
261 { "Left Decimator", NULL, "ADC Engine" },
262 { "Right Decimator", NULL, "ADC Engine" },
263
264 { "AIFCLK", NULL, "SYSCLK" },
265
266 { "Playback", NULL, "Serial Input Routing" },
267 { "Playback", NULL, "Serial Ports" },
268 { "Playback", NULL, "Clock Domain Transfer" },
269 { "Capture", NULL, "Serial Output Routing" },
270 { "Capture", NULL, "Serial Ports" },
271 { "Capture", NULL, "Clock Domain Transfer" },
272
273 { "AOUTL", NULL, "Left Lineout Mixer" },
274 { "AOUTR", NULL, "Right Lineout Mixer" },
275 { "SP", NULL, "Speaker" },
276};
277
278static const struct snd_soc_dapm_route adau1781_adc_dapm_routes[] = {
279 { "Left PGA", NULL, "LMIC" },
280 { "Right PGA", NULL, "RMIC" },
281
282 { "Left Decimator", NULL, "Left PGA" },
283 { "Right Decimator", NULL, "Right PGA" },
284};
285
286static const char * const adau1781_dmic_select_text[] = {
287 "DMIC1", "DMIC2",
288};
289
290static SOC_ENUM_SINGLE_VIRT_DECL(adau1781_dmic_select_enum,
291 adau1781_dmic_select_text);
292
293static const struct snd_kcontrol_new adau1781_dmic_mux =
294 SOC_DAPM_ENUM("DMIC Select", adau1781_dmic_select_enum);
295
296static const struct snd_soc_dapm_widget adau1781_dmic_dapm_widgets[] = {
297 SND_SOC_DAPM_MUX("DMIC Select", SND_SOC_NOPM, 0, 0, &adau1781_dmic_mux),
298
299 SND_SOC_DAPM_ADC("DMIC1", NULL, ADAU1781_DMIC_BEEP_CTRL, 4, 0),
300 SND_SOC_DAPM_ADC("DMIC2", NULL, ADAU1781_DMIC_BEEP_CTRL, 5, 0),
301};
302
303static const struct snd_soc_dapm_route adau1781_dmic_dapm_routes[] = {
304 { "DMIC1", NULL, "LMIC" },
305 { "DMIC2", NULL, "RMIC" },
306
307 { "DMIC1", NULL, "Digital Mic" },
308 { "DMIC2", NULL, "Digital Mic" },
309
310 { "DMIC Select", "DMIC1", "DMIC1" },
311 { "DMIC Select", "DMIC2", "DMIC2" },
312
313 { "Left Decimator", NULL, "DMIC Select" },
314 { "Right Decimator", NULL, "DMIC Select" },
315};
316
317static int adau1781_set_bias_level(struct snd_soc_codec *codec,
318 enum snd_soc_bias_level level)
319{
320 struct adau *adau = snd_soc_codec_get_drvdata(codec);
321
322 switch (level) {
323 case SND_SOC_BIAS_ON:
324 break;
325 case SND_SOC_BIAS_PREPARE:
326 break;
327 case SND_SOC_BIAS_STANDBY:
328 regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL,
329 ADAU17X1_CLOCK_CONTROL_SYSCLK_EN,
330 ADAU17X1_CLOCK_CONTROL_SYSCLK_EN);
331
332 /* Precharge */
333 regmap_update_bits(adau->regmap, ADAU1781_DIG_PWDN1, 0x8, 0x8);
334 break;
335 case SND_SOC_BIAS_OFF:
336 regmap_update_bits(adau->regmap, ADAU1781_DIG_PWDN1, 0xc, 0x0);
337 regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL,
338 ADAU17X1_CLOCK_CONTROL_SYSCLK_EN, 0);
339 break;
340 }
341
342 codec->dapm.bias_level = level;
343 return 0;
344}
345
346static bool adau1781_readable_register(struct device *dev, unsigned int reg)
347{
348 switch (reg) {
349 case ADAU1781_DMIC_BEEP_CTRL:
350 case ADAU1781_LEFT_PGA:
351 case ADAU1781_RIGHT_PGA:
352 case ADAU1781_LEFT_PLAYBACK_MIXER:
353 case ADAU1781_RIGHT_PLAYBACK_MIXER:
354 case ADAU1781_MONO_PLAYBACK_MIXER:
355 case ADAU1781_LEFT_LINEOUT:
356 case ADAU1781_RIGHT_LINEOUT:
357 case ADAU1781_SPEAKER:
358 case ADAU1781_BEEP_ZC:
359 case ADAU1781_DEJITTER:
360 case ADAU1781_DIG_PWDN0:
361 case ADAU1781_DIG_PWDN1:
362 return true;
363 default:
364 break;
365 }
366
367 return adau17x1_readable_register(dev, reg);
368}
369
370static int adau1781_set_input_mode(struct adau *adau, unsigned int reg,
371 bool differential)
372{
373 unsigned int val;
374
375 if (differential)
376 val = ADAU1781_INPUT_DIFFERNTIAL;
377 else
378 val = 0;
379
380 return regmap_update_bits(adau->regmap, reg,
381 ADAU1781_INPUT_DIFFERNTIAL, val);
382}
383
384static int adau1781_codec_probe(struct snd_soc_codec *codec)
385{
386 struct adau1781_platform_data *pdata = dev_get_platdata(codec->dev);
387 struct adau *adau = snd_soc_codec_get_drvdata(codec);
388 const char *firmware;
389 int ret;
390
391 ret = adau17x1_add_widgets(codec);
392 if (ret)
393 return ret;
394
395 if (pdata) {
396 ret = adau1781_set_input_mode(adau, ADAU1781_LEFT_PGA,
397 pdata->left_input_differential);
398 if (ret)
399 return ret;
400 ret = adau1781_set_input_mode(adau, ADAU1781_RIGHT_PGA,
401 pdata->right_input_differential);
402 if (ret)
403 return ret;
404 }
405
406 if (pdata && pdata->use_dmic) {
407 ret = snd_soc_dapm_new_controls(&codec->dapm,
408 adau1781_dmic_dapm_widgets,
409 ARRAY_SIZE(adau1781_dmic_dapm_widgets));
410 if (ret)
411 return ret;
412 ret = snd_soc_dapm_add_routes(&codec->dapm,
413 adau1781_dmic_dapm_routes,
414 ARRAY_SIZE(adau1781_dmic_dapm_routes));
415 if (ret)
416 return ret;
417 } else {
418 ret = snd_soc_dapm_add_routes(&codec->dapm,
419 adau1781_adc_dapm_routes,
420 ARRAY_SIZE(adau1781_adc_dapm_routes));
421 if (ret)
422 return ret;
423 }
424
425 switch (adau->type) {
426 case ADAU1381:
427 firmware = ADAU1381_FIRMWARE;
428 break;
429 case ADAU1781:
430 firmware = ADAU1781_FIRMWARE;
431 break;
432 default:
433 return -EINVAL;
434 }
435
436 ret = adau17x1_add_routes(codec);
437 if (ret < 0)
438 return ret;
439
440 ret = adau17x1_load_firmware(adau, codec->dev, firmware);
441 if (ret)
442 dev_warn(codec->dev, "Failed to load firmware\n");
443
444 return 0;
445}
446
447static const struct snd_soc_codec_driver adau1781_codec_driver = {
448 .probe = adau1781_codec_probe,
449 .suspend = adau17x1_suspend,
450 .resume = adau17x1_resume,
451 .set_bias_level = adau1781_set_bias_level,
452
453 .controls = adau1781_controls,
454 .num_controls = ARRAY_SIZE(adau1781_controls),
455 .dapm_widgets = adau1781_dapm_widgets,
456 .num_dapm_widgets = ARRAY_SIZE(adau1781_dapm_widgets),
457 .dapm_routes = adau1781_dapm_routes,
458 .num_dapm_routes = ARRAY_SIZE(adau1781_dapm_routes),
459};
460
461#define ADAU1781_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \
462 SNDRV_PCM_FMTBIT_S32_LE)
463
464static struct snd_soc_dai_driver adau1781_dai_driver = {
465 .name = "adau-hifi",
466 .playback = {
467 .stream_name = "Playback",
468 .channels_min = 2,
469 .channels_max = 8,
470 .rates = SNDRV_PCM_RATE_8000_96000,
471 .formats = ADAU1781_FORMATS,
472 },
473 .capture = {
474 .stream_name = "Capture",
475 .channels_min = 2,
476 .channels_max = 8,
477 .rates = SNDRV_PCM_RATE_8000_96000,
478 .formats = ADAU1781_FORMATS,
479 },
480 .ops = &adau17x1_dai_ops,
481};
482
483const struct regmap_config adau1781_regmap_config = {
484 .val_bits = 8,
485 .reg_bits = 16,
486 .max_register = 0x40f8,
487 .reg_defaults = adau1781_reg_defaults,
488 .num_reg_defaults = ARRAY_SIZE(adau1781_reg_defaults),
489 .readable_reg = adau1781_readable_register,
490 .volatile_reg = adau17x1_volatile_register,
491 .cache_type = REGCACHE_RBTREE,
492};
493EXPORT_SYMBOL_GPL(adau1781_regmap_config);
494
495int adau1781_probe(struct device *dev, struct regmap *regmap,
496 enum adau17x1_type type, void (*switch_mode)(struct device *dev))
497{
498 int ret;
499
500 ret = adau17x1_probe(dev, regmap, type, switch_mode);
501 if (ret)
502 return ret;
503
504 return snd_soc_register_codec(dev, &adau1781_codec_driver,
505 &adau1781_dai_driver, 1);
506}
507EXPORT_SYMBOL_GPL(adau1781_probe);
508
509MODULE_DESCRIPTION("ASoC ADAU1381/ADAU1781 driver");
510MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
511MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/adau1781.h b/sound/soc/codecs/adau1781.h
new file mode 100644
index 000000000000..2b96e0a9ff2e
--- /dev/null
+++ b/sound/soc/codecs/adau1781.h
@@ -0,0 +1,23 @@
1/*
2 * ADAU1381/ADAU1781 driver
3 *
4 * Copyright 2014 Analog Devices Inc.
5 * Author: Lars-Peter Clausen <lars@metafoo.de>
6 *
7 * Licensed under the GPL-2.
8 */
9
10#ifndef __SOUND_SOC_CODECS_ADAU1781_H__
11#define __SOUND_SOC_CODECS_ADAU1781_H__
12
13#include <linux/regmap.h>
14#include "adau17x1.h"
15
16struct device;
17
18int adau1781_probe(struct device *dev, struct regmap *regmap,
19 enum adau17x1_type type, void (*switch_mode)(struct device *dev));
20
21extern const struct regmap_config adau1781_regmap_config;
22
23#endif