aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@linaro.org>2014-02-06 07:03:27 -0500
committerMark Brown <broonie@linaro.org>2014-02-06 07:55:38 -0500
commit5a3af1293194d07610fd7fdf680b3e7f916dca84 (patch)
treea25d606936d66eda103449ccfec873319274b708
parent38dbfb59d1175ef458d006556061adeaa8751b72 (diff)
ASoC: pcm512x: Add PCM512x driver
The PCM512x devices are a family of monolithic CMOS integrated circuits that include a stereo digital-to-analog converter and additional support circuitry. This is an initial driver which supports some core functionality for the device which covers common use cases but does not cover all features. Currently only slave clocking modes with automatic clock configuration are supported and most of the DSP configuration for the device is not enabled. Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--Documentation/devicetree/bindings/sound/pcm512x.txt30
-rw-r--r--sound/soc/codecs/Kconfig4
-rw-r--r--sound/soc/codecs/Makefile2
-rw-r--r--sound/soc/codecs/pcm512x.c672
-rw-r--r--sound/soc/codecs/pcm512x.h142
5 files changed, 850 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/sound/pcm512x.txt b/Documentation/devicetree/bindings/sound/pcm512x.txt
new file mode 100644
index 000000000000..faff75e64573
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/pcm512x.txt
@@ -0,0 +1,30 @@
1PCM512x audio CODECs
2
3These devices support both I2C and SPI (configured with pin strapping
4on the board).
5
6Required properties:
7
8 - compatible : One of "ti,pcm5121" or "ti,pcm5122"
9
10 - reg : the I2C address of the device for I2C, the chip select
11 number for SPI.
12
13 - AVDD-supply, DVDD-supply, and CPVDD-supply : power supplies for the
14 device, as covered in bindings/regulator/regulator.txt
15
16Optional properties:
17
18 - clocks : A clock specifier for the clock connected as SCLK. If this
19 is absent the device will be configured to clock from BCLK.
20
21Example:
22
23 pcm5122: pcm5122@4c {
24 compatible = "ti,pcm5122";
25 reg = <0x4c>;
26
27 AVDD-supply = <&reg_3v3_analog>;
28 DVDD-supply = <&reg_1v8>;
29 CPVDD-supply = <&reg_3v3>;
30 };
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 983d087aa92a..56d0c2845680 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -59,6 +59,7 @@ config SND_SOC_ALL_CODECS
59 select SND_SOC_PCM1681 if I2C 59 select SND_SOC_PCM1681 if I2C
60 select SND_SOC_PCM1792A if SPI_MASTER 60 select SND_SOC_PCM1792A if SPI_MASTER
61 select SND_SOC_PCM3008 61 select SND_SOC_PCM3008
62 select SND_SOC_PCM512x if SND_SOC_I2C_AND_SPI
62 select SND_SOC_RT5631 if I2C 63 select SND_SOC_RT5631 if I2C
63 select SND_SOC_RT5640 if I2C 64 select SND_SOC_RT5640 if I2C
64 select SND_SOC_SGTL5000 if I2C 65 select SND_SOC_SGTL5000 if I2C
@@ -313,6 +314,9 @@ config SND_SOC_PCM1792A
313config SND_SOC_PCM3008 314config SND_SOC_PCM3008
314 tristate 315 tristate
315 316
317config SND_SOC_PCM512x
318 tristate "Texas Instruments PCM512x CODECs"
319
316config SND_SOC_RT5631 320config SND_SOC_RT5631
317 tristate 321 tristate
318 322
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index bc126764a44d..d3b536fc075d 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -46,6 +46,7 @@ snd-soc-hdmi-codec-objs := hdmi.o
46snd-soc-pcm1681-objs := pcm1681.o 46snd-soc-pcm1681-objs := pcm1681.o
47snd-soc-pcm1792a-codec-objs := pcm1792a.o 47snd-soc-pcm1792a-codec-objs := pcm1792a.o
48snd-soc-pcm3008-objs := pcm3008.o 48snd-soc-pcm3008-objs := pcm3008.o
49snd-soc-pcm512x-objs := pcm512x.o
49snd-soc-rt5631-objs := rt5631.o 50snd-soc-rt5631-objs := rt5631.o
50snd-soc-rt5640-objs := rt5640.o 51snd-soc-rt5640-objs := rt5640.o
51snd-soc-sgtl5000-objs := sgtl5000.o 52snd-soc-sgtl5000-objs := sgtl5000.o
@@ -179,6 +180,7 @@ obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o
179obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o 180obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o
180obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o 181obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o
181obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o 182obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
183obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o
182obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o 184obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
183obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o 185obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o
184obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o 186obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c
new file mode 100644
index 000000000000..5ad3e9aa3cb4
--- /dev/null
+++ b/sound/soc/codecs/pcm512x.c
@@ -0,0 +1,672 @@
1/*
2 * Driver for the PCM512x CODECs
3 *
4 * Author: Mark Brown <broonie@linaro.org>
5 * Copyright 2014 Linaro Ltd
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 */
16
17
18#include <linux/init.h>
19#include <linux/module.h>
20#include <linux/clk.h>
21#include <linux/i2c.h>
22#include <linux/pm_runtime.h>
23#include <linux/regmap.h>
24#include <linux/regulator/consumer.h>
25#include <linux/spi/spi.h>
26#include <sound/soc.h>
27#include <sound/soc-dapm.h>
28#include <sound/tlv.h>
29
30#include "pcm512x.h"
31
32#define PCM512x_NUM_SUPPLIES 3
33static const char *pcm512x_supply_names[PCM512x_NUM_SUPPLIES] = {
34 "AVDD",
35 "DVDD",
36 "CPVDD",
37};
38
39struct pcm512x_priv {
40 struct regmap *regmap;
41 struct clk *sclk;
42 struct regulator_bulk_data supplies[PCM512x_NUM_SUPPLIES];
43 struct notifier_block supply_nb[PCM512x_NUM_SUPPLIES];
44};
45
46/*
47 * We can't use the same notifier block for more than one supply and
48 * there's no way I can see to get from a callback to the caller
49 * except container_of().
50 */
51#define PCM512x_REGULATOR_EVENT(n) \
52static int pcm512x_regulator_event_##n(struct notifier_block *nb, \
53 unsigned long event, void *data) \
54{ \
55 struct pcm512x_priv *pcm512x = container_of(nb, struct pcm512x_priv, \
56 supply_nb[n]); \
57 if (event & REGULATOR_EVENT_DISABLE) { \
58 regcache_mark_dirty(pcm512x->regmap); \
59 regcache_cache_only(pcm512x->regmap, true); \
60 } \
61 return 0; \
62}
63
64PCM512x_REGULATOR_EVENT(0)
65PCM512x_REGULATOR_EVENT(1)
66PCM512x_REGULATOR_EVENT(2)
67
68static const struct reg_default pcm512x_reg_defaults[] = {
69 { PCM512x_RESET, 0x00 },
70 { PCM512x_POWER, 0x00 },
71 { PCM512x_MUTE, 0x00 },
72 { PCM512x_DSP, 0x00 },
73 { PCM512x_PLL_REF, 0x00 },
74 { PCM512x_DAC_ROUTING, 0x11 },
75 { PCM512x_DSP_PROGRAM, 0x01 },
76 { PCM512x_CLKDET, 0x00 },
77 { PCM512x_AUTO_MUTE, 0x00 },
78 { PCM512x_ERROR_DETECT, 0x00 },
79 { PCM512x_DIGITAL_VOLUME_1, 0x00 },
80 { PCM512x_DIGITAL_VOLUME_2, 0x30 },
81 { PCM512x_DIGITAL_VOLUME_3, 0x30 },
82 { PCM512x_DIGITAL_MUTE_1, 0x22 },
83 { PCM512x_DIGITAL_MUTE_2, 0x00 },
84 { PCM512x_DIGITAL_MUTE_3, 0x07 },
85};
86
87static bool pcm512x_readable(struct device *dev, unsigned int reg)
88{
89 switch (reg) {
90 case PCM512x_RESET:
91 case PCM512x_POWER:
92 case PCM512x_MUTE:
93 case PCM512x_PLL_EN:
94 case PCM512x_SPI_MISO_FUNCTION:
95 case PCM512x_DSP:
96 case PCM512x_GPIO_EN:
97 case PCM512x_BCLK_LRCLK_CFG:
98 case PCM512x_DSP_GPIO_INPUT:
99 case PCM512x_MASTER_MODE:
100 case PCM512x_PLL_REF:
101 case PCM512x_PLL_COEFF_0:
102 case PCM512x_PLL_COEFF_1:
103 case PCM512x_PLL_COEFF_2:
104 case PCM512x_PLL_COEFF_3:
105 case PCM512x_PLL_COEFF_4:
106 case PCM512x_DSP_CLKDIV:
107 case PCM512x_DAC_CLKDIV:
108 case PCM512x_NCP_CLKDIV:
109 case PCM512x_OSR_CLKDIV:
110 case PCM512x_MASTER_CLKDIV_1:
111 case PCM512x_MASTER_CLKDIV_2:
112 case PCM512x_FS_SPEED_MODE:
113 case PCM512x_IDAC_1:
114 case PCM512x_IDAC_2:
115 case PCM512x_ERROR_DETECT:
116 case PCM512x_I2S_1:
117 case PCM512x_I2S_2:
118 case PCM512x_DAC_ROUTING:
119 case PCM512x_DSP_PROGRAM:
120 case PCM512x_CLKDET:
121 case PCM512x_AUTO_MUTE:
122 case PCM512x_DIGITAL_VOLUME_1:
123 case PCM512x_DIGITAL_VOLUME_2:
124 case PCM512x_DIGITAL_VOLUME_3:
125 case PCM512x_DIGITAL_MUTE_1:
126 case PCM512x_DIGITAL_MUTE_2:
127 case PCM512x_DIGITAL_MUTE_3:
128 case PCM512x_GPIO_OUTPUT_1:
129 case PCM512x_GPIO_OUTPUT_2:
130 case PCM512x_GPIO_OUTPUT_3:
131 case PCM512x_GPIO_OUTPUT_4:
132 case PCM512x_GPIO_OUTPUT_5:
133 case PCM512x_GPIO_OUTPUT_6:
134 case PCM512x_GPIO_CONTROL_1:
135 case PCM512x_GPIO_CONTROL_2:
136 case PCM512x_OVERFLOW:
137 case PCM512x_RATE_DET_1:
138 case PCM512x_RATE_DET_2:
139 case PCM512x_RATE_DET_3:
140 case PCM512x_RATE_DET_4:
141 case PCM512x_ANALOG_MUTE_DET:
142 case PCM512x_GPIN:
143 case PCM512x_DIGITAL_MUTE_DET:
144 return true;
145 default:
146 return false;
147 }
148}
149
150static bool pcm512x_volatile(struct device *dev, unsigned int reg)
151{
152 switch (reg) {
153 case PCM512x_PLL_EN:
154 case PCM512x_OVERFLOW:
155 case PCM512x_RATE_DET_1:
156 case PCM512x_RATE_DET_2:
157 case PCM512x_RATE_DET_3:
158 case PCM512x_RATE_DET_4:
159 case PCM512x_ANALOG_MUTE_DET:
160 case PCM512x_GPIN:
161 case PCM512x_DIGITAL_MUTE_DET:
162 return true;
163 default:
164 return false;
165 }
166}
167
168static const DECLARE_TLV_DB_SCALE(digital_tlv, -10350, 50, 1);
169
170static const char *pcm512x_dsp_program_texts[] = {
171 "FIR interpolation with de-emphasis",
172 "Low latency IIR with de-emphasis",
173 "Fixed process flow",
174 "High attenuation with de-emphasis",
175 "Ringing-less low latency FIR",
176};
177
178static const unsigned int pcm512x_dsp_program_values[] = {
179 1,
180 2,
181 3,
182 5,
183 7,
184};
185
186static const SOC_VALUE_ENUM_SINGLE_DECL(pcm512x_dsp_program,
187 PCM512x_DSP_PROGRAM, 0, 0x1f,
188 pcm512x_dsp_program_texts,
189 pcm512x_dsp_program_values);
190
191static const char *pcm512x_clk_missing_text[] = {
192 "1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s"
193};
194
195static const struct soc_enum pcm512x_clk_missing =
196 SOC_ENUM_SINGLE(PCM512x_CLKDET, 0, 8, pcm512x_clk_missing_text);
197
198static const char *pcm512x_autom_text[] = {
199 "21ms", "106ms", "213ms", "533ms", "1.07s", "2.13s", "5.33s", "10.66s"
200};
201
202static const struct soc_enum pcm512x_autom_l =
203 SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATML_SHIFT, 8,
204 pcm512x_autom_text);
205
206static const struct soc_enum pcm512x_autom_r =
207 SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATMR_SHIFT, 8,
208 pcm512x_autom_text);
209
210static const char *pcm512x_ramp_rate_text[] = {
211 "1 sample/update", "2 samples/update", "4 samples/update",
212 "Immediate"
213};
214
215static const struct soc_enum pcm512x_vndf =
216 SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDF_SHIFT, 4,
217 pcm512x_ramp_rate_text);
218
219static const struct soc_enum pcm512x_vnuf =
220 SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUF_SHIFT, 4,
221 pcm512x_ramp_rate_text);
222
223static const struct soc_enum pcm512x_vedf =
224 SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDF_SHIFT, 4,
225 pcm512x_ramp_rate_text);
226
227static const char *pcm512x_ramp_step_text[] = {
228 "4dB/step", "2dB/step", "1dB/step", "0.5dB/step"
229};
230
231static const struct soc_enum pcm512x_vnds =
232 SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDS_SHIFT, 4,
233 pcm512x_ramp_step_text);
234
235static const struct soc_enum pcm512x_vnus =
236 SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUS_SHIFT, 4,
237 pcm512x_ramp_step_text);
238
239static const struct soc_enum pcm512x_veds =
240 SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDS_SHIFT, 4,
241 pcm512x_ramp_step_text);
242
243static const struct snd_kcontrol_new pcm512x_controls[] = {
244SOC_DOUBLE_R_TLV("Playback Digital Volume", PCM512x_DIGITAL_VOLUME_2,
245 PCM512x_DIGITAL_VOLUME_3, 0, 255, 1, digital_tlv),
246SOC_DOUBLE("Playback Digital Switch", PCM512x_MUTE, PCM512x_RQML_SHIFT,
247 PCM512x_RQMR_SHIFT, 1, 1),
248
249SOC_SINGLE("Deemphasis Switch", PCM512x_DSP, PCM512x_DEMP_SHIFT, 1, 1),
250SOC_VALUE_ENUM("DSP Program", pcm512x_dsp_program),
251
252SOC_ENUM("Clock Missing Period", pcm512x_clk_missing),
253SOC_ENUM("Auto Mute Time Left", pcm512x_autom_l),
254SOC_ENUM("Auto Mute Time Right", pcm512x_autom_r),
255SOC_SINGLE("Auto Mute Mono Switch", PCM512x_DIGITAL_MUTE_3,
256 PCM512x_ACTL_SHIFT, 1, 0),
257SOC_DOUBLE("Auto Mute Switch", PCM512x_DIGITAL_MUTE_3, PCM512x_AMLE_SHIFT,
258 PCM512x_AMLR_SHIFT, 1, 0),
259
260SOC_ENUM("Volume Ramp Down Rate", pcm512x_vndf),
261SOC_ENUM("Volume Ramp Down Step", pcm512x_vnds),
262SOC_ENUM("Volume Ramp Up Rate", pcm512x_vnuf),
263SOC_ENUM("Volume Ramp Up Step", pcm512x_vnus),
264SOC_ENUM("Volume Ramp Down Emergency Rate", pcm512x_vedf),
265SOC_ENUM("Volume Ramp Down Emergency Step", pcm512x_veds),
266};
267
268static const struct snd_soc_dapm_widget pcm512x_dapm_widgets[] = {
269SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0),
270SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0),
271
272SND_SOC_DAPM_OUTPUT("OUTL"),
273SND_SOC_DAPM_OUTPUT("OUTR"),
274};
275
276static const struct snd_soc_dapm_route pcm512x_dapm_routes[] = {
277 { "DACL", NULL, "Playback" },
278 { "DACR", NULL, "Playback" },
279
280 { "OUTL", NULL, "DACL" },
281 { "OUTR", NULL, "DACR" },
282};
283
284static int pcm512x_set_bias_level(struct snd_soc_codec *codec,
285 enum snd_soc_bias_level level)
286{
287 struct pcm512x_priv *pcm512x = dev_get_drvdata(codec->dev);
288 int ret;
289
290 switch (level) {
291 case SND_SOC_BIAS_ON:
292 case SND_SOC_BIAS_PREPARE:
293 break;
294
295 case SND_SOC_BIAS_STANDBY:
296 ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
297 PCM512x_RQST, 0);
298 if (ret != 0) {
299 dev_err(codec->dev, "Failed to remove standby: %d\n",
300 ret);
301 return ret;
302 }
303 break;
304
305 case SND_SOC_BIAS_OFF:
306 ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
307 PCM512x_RQST, PCM512x_RQST);
308 if (ret != 0) {
309 dev_err(codec->dev, "Failed to request standby: %d\n",
310 ret);
311 return ret;
312 }
313 break;
314 }
315
316 codec->dapm.bias_level = level;
317
318 return 0;
319}
320
321static struct snd_soc_dai_driver pcm512x_dai = {
322 .name = "pcm512x-hifi",
323 .playback = {
324 .stream_name = "Playback",
325 .channels_min = 2,
326 .channels_max = 2,
327 .rates = SNDRV_PCM_RATE_8000_192000,
328 .formats = SNDRV_PCM_FMTBIT_S16_LE |
329 SNDRV_PCM_FMTBIT_S24_LE |
330 SNDRV_PCM_FMTBIT_S32_LE
331 },
332};
333
334static struct snd_soc_codec_driver pcm512x_codec_driver = {
335 .set_bias_level = pcm512x_set_bias_level,
336 .idle_bias_off = true,
337
338 .controls = pcm512x_controls,
339 .num_controls = ARRAY_SIZE(pcm512x_controls),
340 .dapm_widgets = pcm512x_dapm_widgets,
341 .num_dapm_widgets = ARRAY_SIZE(pcm512x_dapm_widgets),
342 .dapm_routes = pcm512x_dapm_routes,
343 .num_dapm_routes = ARRAY_SIZE(pcm512x_dapm_routes),
344};
345
346static const struct regmap_config pcm512x_regmap = {
347 .reg_bits = 8,
348 .val_bits = 8,
349
350 .readable_reg = pcm512x_readable,
351 .volatile_reg = pcm512x_volatile,
352
353 .max_register = PCM512x_MAX_REGISTER,
354 .reg_defaults = pcm512x_reg_defaults,
355 .num_reg_defaults = ARRAY_SIZE(pcm512x_reg_defaults),
356 .cache_type = REGCACHE_RBTREE,
357};
358
359static const struct of_device_id pcm512x_of_match[] = {
360 { .compatible = "ti,pcm5121", },
361 { .compatible = "ti,pcm5122", },
362 { }
363};
364MODULE_DEVICE_TABLE(of, pcm512x_of_match);
365
366static int pcm512x_probe(struct device *dev, struct regmap *regmap)
367{
368 struct pcm512x_priv *pcm512x;
369 int i, ret;
370
371 pcm512x = devm_kzalloc(dev, sizeof(struct pcm512x_priv), GFP_KERNEL);
372 if (!pcm512x)
373 return -ENOMEM;
374
375 dev_set_drvdata(dev, pcm512x);
376 pcm512x->regmap = regmap;
377
378 for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++)
379 pcm512x->supplies[i].supply = pcm512x_supply_names[i];
380
381 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(pcm512x->supplies),
382 pcm512x->supplies);
383 if (ret != 0) {
384 dev_err(dev, "Failed to get supplies: %d\n", ret);
385 return ret;
386 }
387
388 pcm512x->supply_nb[0].notifier_call = pcm512x_regulator_event_0;
389 pcm512x->supply_nb[1].notifier_call = pcm512x_regulator_event_1;
390 pcm512x->supply_nb[2].notifier_call = pcm512x_regulator_event_2;
391
392 for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++) {
393 ret = regulator_register_notifier(pcm512x->supplies[i].consumer,
394 &pcm512x->supply_nb[i]);
395 if (ret != 0) {
396 dev_err(dev,
397 "Failed to register regulator notifier: %d\n",
398 ret);
399 }
400 }
401
402 ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies),
403 pcm512x->supplies);
404 if (ret != 0) {
405 dev_err(dev, "Failed to enable supplies: %d\n", ret);
406 return ret;
407 }
408
409 /* Reset the device, verifying I/O in the process for I2C */
410 ret = regmap_write(regmap, PCM512x_RESET,
411 PCM512x_RSTM | PCM512x_RSTR);
412 if (ret != 0) {
413 dev_err(dev, "Failed to reset device: %d\n", ret);
414 goto err;
415 }
416
417 ret = regmap_write(regmap, PCM512x_RESET, 0);
418 if (ret != 0) {
419 dev_err(dev, "Failed to reset device: %d\n", ret);
420 goto err;
421 }
422
423 pcm512x->sclk = devm_clk_get(dev, NULL);
424 if (IS_ERR(pcm512x->sclk)) {
425 if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER)
426 return -EPROBE_DEFER;
427
428 dev_info(dev, "No SCLK, using BCLK: %ld\n",
429 PTR_ERR(pcm512x->sclk));
430
431 /* Disable reporting of missing SCLK as an error */
432 regmap_update_bits(regmap, PCM512x_ERROR_DETECT,
433 PCM512x_IDCH, PCM512x_IDCH);
434
435 /* Switch PLL input to BCLK */
436 regmap_update_bits(regmap, PCM512x_PLL_REF,
437 PCM512x_SREF, PCM512x_SREF);
438 } else {
439 ret = clk_prepare_enable(pcm512x->sclk);
440 if (ret != 0) {
441 dev_err(dev, "Failed to enable SCLK: %d\n", ret);
442 return ret;
443 }
444 }
445
446 /* Default to standby mode */
447 ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
448 PCM512x_RQST, PCM512x_RQST);
449 if (ret != 0) {
450 dev_err(dev, "Failed to request standby: %d\n",
451 ret);
452 goto err_clk;
453 }
454
455 pm_runtime_set_active(dev);
456 pm_runtime_enable(dev);
457 pm_runtime_idle(dev);
458
459 ret = snd_soc_register_codec(dev, &pcm512x_codec_driver,
460 &pcm512x_dai, 1);
461 if (ret != 0) {
462 dev_err(dev, "Failed to register CODEC: %d\n", ret);
463 goto err_pm;
464 }
465
466 return 0;
467
468err_pm:
469 pm_runtime_disable(dev);
470err_clk:
471 if (!IS_ERR(pcm512x->sclk))
472 clk_disable_unprepare(pcm512x->sclk);
473err:
474 regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
475 pcm512x->supplies);
476 return ret;
477}
478
479static void pcm512x_remove(struct device *dev)
480{
481 struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
482
483 snd_soc_unregister_codec(dev);
484 pm_runtime_disable(dev);
485 if (!IS_ERR(pcm512x->sclk))
486 clk_disable_unprepare(pcm512x->sclk);
487 regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
488 pcm512x->supplies);
489}
490
491static int pcm512x_suspend(struct device *dev)
492{
493 struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
494 int ret;
495
496 ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
497 PCM512x_RQPD, PCM512x_RQPD);
498 if (ret != 0) {
499 dev_err(dev, "Failed to request power down: %d\n", ret);
500 return ret;
501 }
502
503 ret = regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
504 pcm512x->supplies);
505 if (ret != 0) {
506 dev_err(dev, "Failed to disable supplies: %d\n", ret);
507 return ret;
508 }
509
510 if (!IS_ERR(pcm512x->sclk))
511 clk_disable_unprepare(pcm512x->sclk);
512
513 return 0;
514}
515
516static int pcm512x_resume(struct device *dev)
517{
518 struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
519 int ret;
520
521 if (!IS_ERR(pcm512x->sclk)) {
522 ret = clk_prepare_enable(pcm512x->sclk);
523 if (ret != 0) {
524 dev_err(dev, "Failed to enable SCLK: %d\n", ret);
525 return ret;
526 }
527 }
528
529 ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies),
530 pcm512x->supplies);
531 if (ret != 0) {
532 dev_err(dev, "Failed to enable supplies: %d\n", ret);
533 return ret;
534 }
535
536 regcache_cache_only(pcm512x->regmap, false);
537 ret = regcache_sync(pcm512x->regmap);
538 if (ret != 0) {
539 dev_err(dev, "Failed to sync cache: %d\n", ret);
540 return ret;
541 }
542
543 ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
544 PCM512x_RQPD, 0);
545 if (ret != 0) {
546 dev_err(dev, "Failed to remove power down: %d\n", ret);
547 return ret;
548 }
549
550 return 0;
551}
552
553static const struct dev_pm_ops pcm512x_pm_ops = {
554 SET_RUNTIME_PM_OPS(pcm512x_suspend, pcm512x_resume, NULL)
555};
556
557#if IS_ENABLED(CONFIG_I2C)
558static int pcm512x_i2c_probe(struct i2c_client *i2c,
559 const struct i2c_device_id *id)
560{
561 struct regmap *regmap;
562
563 regmap = devm_regmap_init_i2c(i2c, &pcm512x_regmap);
564 if (IS_ERR(regmap))
565 return PTR_ERR(regmap);
566
567 return pcm512x_probe(&i2c->dev, regmap);
568}
569
570static int pcm512x_i2c_remove(struct i2c_client *i2c)
571{
572 pcm512x_remove(&i2c->dev);
573 return 0;
574}
575
576static const struct i2c_device_id pcm512x_i2c_id[] = {
577 { "pcm5121", },
578 { "pcm5122", },
579 { }
580};
581MODULE_DEVICE_TABLE(i2c, pcm512x_i2c_id);
582
583static struct i2c_driver pcm512x_i2c_driver = {
584 .probe = pcm512x_i2c_probe,
585 .remove = pcm512x_i2c_remove,
586 .id_table = pcm512x_i2c_id,
587 .driver = {
588 .name = "pcm512x",
589 .owner = THIS_MODULE,
590 .of_match_table = pcm512x_of_match,
591 .pm = &pcm512x_pm_ops,
592 },
593};
594#endif
595
596#if defined(CONFIG_SPI_MASTER)
597static int pcm512x_spi_probe(struct spi_device *spi)
598{
599 struct regmap *regmap;
600 int ret;
601
602 regmap = devm_regmap_init_spi(spi, &pcm512x_regmap);
603 if (IS_ERR(regmap)) {
604 ret = PTR_ERR(regmap);
605 return ret;
606 }
607
608 return pcm512x_probe(&spi->dev, regmap);
609}
610
611static int pcm512x_spi_remove(struct spi_device *spi)
612{
613 pcm512x_remove(&spi->dev);
614 return 0;
615}
616
617static const struct spi_device_id pcm512x_spi_id[] = {
618 { "pcm5121", },
619 { "pcm5122", },
620 { },
621};
622MODULE_DEVICE_TABLE(spi, pcm512x_spi_id);
623
624static struct spi_driver pcm512x_spi_driver = {
625 .probe = pcm512x_spi_probe,
626 .remove = pcm512x_spi_remove,
627 .id_table = pcm512x_spi_id,
628 .driver = {
629 .name = "pcm512x",
630 .owner = THIS_MODULE,
631 .of_match_table = pcm512x_of_match,
632 .pm = &pcm512x_pm_ops,
633 },
634};
635#endif
636
637static int __init pcm512x_modinit(void)
638{
639 int ret = 0;
640
641#if IS_ENABLED(CONFIG_I2C)
642 ret = i2c_add_driver(&pcm512x_i2c_driver);
643 if (ret) {
644 printk(KERN_ERR "Failed to register pcm512x I2C driver: %d\n",
645 ret);
646 }
647#endif
648#if defined(CONFIG_SPI_MASTER)
649 ret = spi_register_driver(&pcm512x_spi_driver);
650 if (ret != 0) {
651 printk(KERN_ERR "Failed to register pcm512x SPI driver: %d\n",
652 ret);
653 }
654#endif
655 return ret;
656}
657module_init(pcm512x_modinit);
658
659static void __exit pcm512x_exit(void)
660{
661#if IS_ENABLED(CONFIG_I2C)
662 i2c_del_driver(&pcm512x_i2c_driver);
663#endif
664#if defined(CONFIG_SPI_MASTER)
665 spi_unregister_driver(&pcm512x_spi_driver);
666#endif
667}
668module_exit(pcm512x_exit);
669
670MODULE_DESCRIPTION("ASoC PCM512x codec driver");
671MODULE_AUTHOR("Mark Brown <broonie@linaro.org>");
672MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/pcm512x.h b/sound/soc/codecs/pcm512x.h
new file mode 100644
index 000000000000..b2f518ecb35c
--- /dev/null
+++ b/sound/soc/codecs/pcm512x.h
@@ -0,0 +1,142 @@
1/*
2 * Driver for the PCM512x CODECs
3 *
4 * Author: Mark Brown <broonie@linaro.org>
5 * Copyright 2014 Linaro Ltd
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 */
16
17#ifndef _SND_SOC_PCM512X
18#define _SND_SOC_PCM512X
19
20#define PCM512x_PAGE_0_BASE 0
21
22#define PCM512x_PAGE 0
23
24#define PCM512x_RESET (PCM512x_PAGE_0_BASE + 1)
25#define PCM512x_POWER (PCM512x_PAGE_0_BASE + 2)
26#define PCM512x_MUTE (PCM512x_PAGE_0_BASE + 3)
27#define PCM512x_PLL_EN (PCM512x_PAGE_0_BASE + 4)
28#define PCM512x_SPI_MISO_FUNCTION (PCM512x_PAGE_0_BASE + 6)
29#define PCM512x_DSP (PCM512x_PAGE_0_BASE + 7)
30#define PCM512x_GPIO_EN (PCM512x_PAGE_0_BASE + 8)
31#define PCM512x_BCLK_LRCLK_CFG (PCM512x_PAGE_0_BASE + 9)
32#define PCM512x_DSP_GPIO_INPUT (PCM512x_PAGE_0_BASE + 10)
33#define PCM512x_MASTER_MODE (PCM512x_PAGE_0_BASE + 12)
34#define PCM512x_PLL_REF (PCM512x_PAGE_0_BASE + 13)
35#define PCM512x_PLL_COEFF_0 (PCM512x_PAGE_0_BASE + 20)
36#define PCM512x_PLL_COEFF_1 (PCM512x_PAGE_0_BASE + 21)
37#define PCM512x_PLL_COEFF_2 (PCM512x_PAGE_0_BASE + 22)
38#define PCM512x_PLL_COEFF_3 (PCM512x_PAGE_0_BASE + 23)
39#define PCM512x_PLL_COEFF_4 (PCM512x_PAGE_0_BASE + 24)
40#define PCM512x_DSP_CLKDIV (PCM512x_PAGE_0_BASE + 27)
41#define PCM512x_DAC_CLKDIV (PCM512x_PAGE_0_BASE + 28)
42#define PCM512x_NCP_CLKDIV (PCM512x_PAGE_0_BASE + 29)
43#define PCM512x_OSR_CLKDIV (PCM512x_PAGE_0_BASE + 30)
44#define PCM512x_MASTER_CLKDIV_1 (PCM512x_PAGE_0_BASE + 32)
45#define PCM512x_MASTER_CLKDIV_2 (PCM512x_PAGE_0_BASE + 33)
46#define PCM512x_FS_SPEED_MODE (PCM512x_PAGE_0_BASE + 34)
47#define PCM512x_IDAC_1 (PCM512x_PAGE_0_BASE + 35)
48#define PCM512x_IDAC_2 (PCM512x_PAGE_0_BASE + 36)
49#define PCM512x_ERROR_DETECT (PCM512x_PAGE_0_BASE + 37)
50#define PCM512x_I2S_1 (PCM512x_PAGE_0_BASE + 40)
51#define PCM512x_I2S_2 (PCM512x_PAGE_0_BASE + 41)
52#define PCM512x_DAC_ROUTING (PCM512x_PAGE_0_BASE + 42)
53#define PCM512x_DSP_PROGRAM (PCM512x_PAGE_0_BASE + 43)
54#define PCM512x_CLKDET (PCM512x_PAGE_0_BASE + 44)
55#define PCM512x_AUTO_MUTE (PCM512x_PAGE_0_BASE + 59)
56#define PCM512x_DIGITAL_VOLUME_1 (PCM512x_PAGE_0_BASE + 60)
57#define PCM512x_DIGITAL_VOLUME_2 (PCM512x_PAGE_0_BASE + 61)
58#define PCM512x_DIGITAL_VOLUME_3 (PCM512x_PAGE_0_BASE + 62)
59#define PCM512x_DIGITAL_MUTE_1 (PCM512x_PAGE_0_BASE + 63)
60#define PCM512x_DIGITAL_MUTE_2 (PCM512x_PAGE_0_BASE + 64)
61#define PCM512x_DIGITAL_MUTE_3 (PCM512x_PAGE_0_BASE + 65)
62#define PCM512x_GPIO_OUTPUT_1 (PCM512x_PAGE_0_BASE + 80)
63#define PCM512x_GPIO_OUTPUT_2 (PCM512x_PAGE_0_BASE + 81)
64#define PCM512x_GPIO_OUTPUT_3 (PCM512x_PAGE_0_BASE + 82)
65#define PCM512x_GPIO_OUTPUT_4 (PCM512x_PAGE_0_BASE + 83)
66#define PCM512x_GPIO_OUTPUT_5 (PCM512x_PAGE_0_BASE + 84)
67#define PCM512x_GPIO_OUTPUT_6 (PCM512x_PAGE_0_BASE + 85)
68#define PCM512x_GPIO_CONTROL_1 (PCM512x_PAGE_0_BASE + 86)
69#define PCM512x_GPIO_CONTROL_2 (PCM512x_PAGE_0_BASE + 87)
70#define PCM512x_OVERFLOW (PCM512x_PAGE_0_BASE + 90)
71#define PCM512x_RATE_DET_1 (PCM512x_PAGE_0_BASE + 91)
72#define PCM512x_RATE_DET_2 (PCM512x_PAGE_0_BASE + 92)
73#define PCM512x_RATE_DET_3 (PCM512x_PAGE_0_BASE + 93)
74#define PCM512x_RATE_DET_4 (PCM512x_PAGE_0_BASE + 94)
75#define PCM512x_ANALOG_MUTE_DET (PCM512x_PAGE_0_BASE + 108)
76#define PCM512x_GPIN (PCM512x_PAGE_0_BASE + 119)
77#define PCM512x_DIGITAL_MUTE_DET (PCM512x_PAGE_0_BASE + 120)
78
79#define PCM512x_MAX_REGISTER (PCM512x_PAGE_0_BASE + 120)
80
81/* Page 0, Register 1 - reset */
82#define PCM512x_RSTR (1 << 0)
83#define PCM512x_RSTM (1 << 4)
84
85/* Page 0, Register 2 - power */
86#define PCM512x_RQPD (1 << 0)
87#define PCM512x_RQPD_SHIFT 0
88#define PCM512x_RQST (1 << 4)
89#define PCM512x_RQST_SHIFT 4
90
91/* Page 0, Register 3 - mute */
92#define PCM512x_RQMR_SHIFT 0
93#define PCM512x_RQML_SHIFT 4
94
95/* Page 0, Register 4 - PLL */
96#define PCM512x_PLCE (1 << 0)
97#define PCM512x_RLCE_SHIFT 0
98#define PCM512x_PLCK (1 << 4)
99#define PCM512x_PLCK_SHIFT 4
100
101/* Page 0, Register 7 - DSP */
102#define PCM512x_SDSL (1 << 0)
103#define PCM512x_SDSL_SHIFT 0
104#define PCM512x_DEMP (1 << 4)
105#define PCM512x_DEMP_SHIFT 4
106
107/* Page 0, Register 13 - PLL reference */
108#define PCM512x_SREF (1 << 4)
109
110/* Page 0, Register 37 - Error detection */
111#define PCM512x_IPLK (1 << 0)
112#define PCM512x_DCAS (1 << 1)
113#define PCM512x_IDCM (1 << 2)
114#define PCM512x_IDCH (1 << 3)
115#define PCM512x_IDSK (1 << 4)
116#define PCM512x_IDBK (1 << 5)
117#define PCM512x_IDFS (1 << 6)
118
119/* Page 0, Register 42 - DAC routing */
120#define PCM512x_AUPR_SHIFT 0
121#define PCM512x_AUPL_SHIFT 4
122
123/* Page 0, Register 59 - auto mute */
124#define PCM512x_ATMR_SHIFT 0
125#define PCM512x_ATML_SHIFT 4
126
127/* Page 0, Register 63 - ramp rates */
128#define PCM512x_VNDF_SHIFT 6
129#define PCM512x_VNDS_SHIFT 4
130#define PCM512x_VNUF_SHIFT 2
131#define PCM512x_VNUS_SHIFT 0
132
133/* Page 0, Register 64 - emergency ramp rates */
134#define PCM512x_VEDF_SHIFT 6
135#define PCM512x_VEDS_SHIFT 4
136
137/* Page 0, Register 65 - Digital mute enables */
138#define PCM512x_ACTL_SHIFT 2
139#define PCM512x_AMLE_SHIFT 1
140#define PCM512x_AMLR_SHIFT 0
141
142#endif