brcm2708: update 3.10 patches with raspberrypi/rpi-3.10.y of 27 Apr. 2014
[openwrt/svn-archive/archive.git] / target / linux / brcm2708 / patches-3.10 / 0185-Add-IQaudIO-Sound-Card-support-for-Raspberry-Pi.patch
1 From e84e7c3905da79d7fc5f2f60453673a577dddbd3 Mon Sep 17 00:00:00 2001
2 From: Gordon Garrity <gordon@iqaudio.com>
3 Date: Sat, 8 Mar 2014 16:56:57 +0000
4 Subject: [PATCH 185/196] Add IQaudIO Sound Card support for Raspberry Pi
5
6 ---
7 arch/arm/configs/bcmrpi_defconfig | 1 +
8 arch/arm/mach-bcm2708/bcm2708.c | 22 ++
9 sound/soc/bcm/Kconfig | 7 +
10 sound/soc/bcm/Makefile | 3 +
11 sound/soc/bcm/iqaudio-dac.c | 111 +++++++
12 sound/soc/codecs/Kconfig | 4 +
13 sound/soc/codecs/Makefile | 2 +
14 sound/soc/codecs/pcm512x.c | 677 ++++++++++++++++++++++++++++++++++++++
15 sound/soc/codecs/pcm512x.h | 142 ++++++++
16 9 files changed, 969 insertions(+)
17 create mode 100644 sound/soc/bcm/iqaudio-dac.c
18 create mode 100644 sound/soc/codecs/pcm512x.c
19 create mode 100644 sound/soc/codecs/pcm512x.h
20
21 diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig
22 index ca40634..90fe241 100644
23 --- a/arch/arm/configs/bcmrpi_defconfig
24 +++ b/arch/arm/configs/bcmrpi_defconfig
25 @@ -744,6 +744,7 @@ CONFIG_SND_BCM2708_SOC_I2S=m
26 CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
27 CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m
28 CONFIG_SND_BCM2708_SOC_RPI_DAC=m
29 +CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
30 CONFIG_SOUND_PRIME=m
31 CONFIG_HIDRAW=y
32 CONFIG_HID_A4TECH=m
33 diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c
34 index caa9f48..68d78f1 100644
35 --- a/arch/arm/mach-bcm2708/bcm2708.c
36 +++ b/arch/arm/mach-bcm2708/bcm2708.c
37 @@ -685,6 +685,22 @@ static struct platform_device snd_pcm1794a_codec_device = {
38 };
39 #endif
40
41 +
42 +#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE)
43 +static struct platform_device snd_rpi_iqaudio_dac_device = {
44 + .name = "snd-rpi-iqaudio-dac",
45 + .id = 0,
46 + .num_resources = 0,
47 +};
48 +
49 +// Use the actual device name rather than generic driver name
50 +static struct i2c_board_info __initdata snd_pcm512x_i2c_devices[] = {
51 + {
52 + I2C_BOARD_INFO("pcm5122", 0x4c)
53 + },
54 +};
55 +#endif
56 +
57 int __init bcm_register_device(struct platform_device *pdev)
58 {
59 int ret;
60 @@ -831,6 +847,12 @@ void __init bcm2708_init(void)
61 bcm_register_device(&snd_pcm1794a_codec_device);
62 #endif
63
64 +#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE)
65 + bcm_register_device(&snd_rpi_iqaudio_dac_device);
66 + i2c_register_board_info(1, snd_pcm512x_i2c_devices, ARRAY_SIZE(snd_pcm512x_i2c_devices));
67 +#endif
68 +
69 +
70 for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
71 struct amba_device *d = amba_devs[i];
72 amba_device_register(d, &iomem_resource);
73 diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig
74 index 7e2afc2..0fe398f 100644
75 --- a/sound/soc/bcm/Kconfig
76 +++ b/sound/soc/bcm/Kconfig
77 @@ -29,3 +29,10 @@ config SND_BCM2708_SOC_RPI_DAC
78 select SND_SOC_PCM1794A
79 help
80 Say Y or M if you want to add support for RPi-DAC.
81 +
82 +config SND_BCM2708_SOC_IQAUDIO_DAC
83 + tristate "Support for IQaudIO-DAC"
84 + depends on SND_BCM2708_SOC_I2S
85 + select SND_SOC_PCM512x
86 + help
87 + Say Y or M if you want to add support for IQaudIO-DAC.
88 diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile
89 index 54e37eb..918f460 100644
90 --- a/sound/soc/bcm/Makefile
91 +++ b/sound/soc/bcm/Makefile
92 @@ -7,7 +7,10 @@ obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o
93 snd-soc-hifiberry-dac-objs := hifiberry_dac.o
94 snd-soc-hifiberry-digi-objs := hifiberry_digi.o
95 snd-soc-rpi-dac-objs := rpi-dac.o
96 +snd-soc-iqaudio-dac-objs := iqaudio-dac.o
97
98 obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o
99 obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o
100 obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o
101 +obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o
102 +
103 diff --git a/sound/soc/bcm/iqaudio-dac.c b/sound/soc/bcm/iqaudio-dac.c
104 new file mode 100644
105 index 0000000..6be0c0e
106 --- /dev/null
107 +++ b/sound/soc/bcm/iqaudio-dac.c
108 @@ -0,0 +1,111 @@
109 +/*
110 + * ASoC Driver for IQaudIO DAC
111 + *
112 + * Author: Florian Meier <florian.meier@koalo.de>
113 + * Copyright 2013
114 + *
115 + * This program is free software; you can redistribute it and/or
116 + * modify it under the terms of the GNU General Public License
117 + * version 2 as published by the Free Software Foundation.
118 + *
119 + * This program is distributed in the hope that it will be useful, but
120 + * WITHOUT ANY WARRANTY; without even the implied warranty of
121 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
122 + * General Public License for more details.
123 + */
124 +
125 +#include <linux/module.h>
126 +#include <linux/platform_device.h>
127 +
128 +#include <sound/core.h>
129 +#include <sound/pcm.h>
130 +#include <sound/pcm_params.h>
131 +#include <sound/soc.h>
132 +#include <sound/jack.h>
133 +
134 +static int snd_rpi_iqaudio_dac_init(struct snd_soc_pcm_runtime *rtd)
135 +{
136 +// NOT USED struct snd_soc_codec *codec = rtd->codec;
137 +
138 + return 0;
139 +}
140 +
141 +static int snd_rpi_iqaudio_dac_hw_params(struct snd_pcm_substream *substream,
142 + struct snd_pcm_hw_params *params)
143 +{
144 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
145 +// NOT USED struct snd_soc_dai *codec_dai = rtd->codec_dai;
146 +// NOT USED struct snd_soc_codec *codec = rtd->codec;
147 + struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
148 +
149 + unsigned int sample_bits =
150 + snd_pcm_format_physical_width(params_format(params));
151 +
152 + return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2);
153 +}
154 +
155 +/* machine stream operations */
156 +static struct snd_soc_ops snd_rpi_iqaudio_dac_ops = {
157 + .hw_params = snd_rpi_iqaudio_dac_hw_params,
158 +};
159 +
160 +static struct snd_soc_dai_link snd_rpi_iqaudio_dac_dai[] = {
161 +{
162 + .name = "IQaudIO DAC",
163 + .stream_name = "IQaudIO DAC HiFi",
164 + .cpu_dai_name = "bcm2708-i2s.0",
165 + .codec_dai_name = "pcm512x-hifi",
166 + .platform_name = "bcm2708-i2s.0",
167 + .codec_name = "pcm512x.1-004c",
168 + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
169 + SND_SOC_DAIFMT_CBS_CFS,
170 + .ops = &snd_rpi_iqaudio_dac_ops,
171 + .init = snd_rpi_iqaudio_dac_init,
172 +},
173 +};
174 +
175 +/* audio machine driver */
176 +static struct snd_soc_card snd_rpi_iqaudio_dac = {
177 + .name = "snd_rpi_iqaudio_dac",
178 + .dai_link = snd_rpi_iqaudio_dac_dai,
179 + .num_links = ARRAY_SIZE(snd_rpi_iqaudio_dac_dai),
180 +};
181 +
182 +static int snd_rpi_iqaudio_dac_probe(struct platform_device *pdev)
183 +{
184 + int ret = 0;
185 +
186 + snd_rpi_iqaudio_dac.dev = &pdev->dev;
187 + ret = snd_soc_register_card(&snd_rpi_iqaudio_dac);
188 + if (ret)
189 + dev_err(&pdev->dev,
190 + "snd_soc_register_card() failed: %d\n", ret);
191 +
192 + return ret;
193 +}
194 +
195 +static int snd_rpi_iqaudio_dac_remove(struct platform_device *pdev)
196 +{
197 + return snd_soc_unregister_card(&snd_rpi_iqaudio_dac);
198 +}
199 +
200 +static const struct of_device_id iqaudio_of_match[] = {
201 + { .compatible = "iqaudio,iqaudio-dac", },
202 + {},
203 +};
204 +
205 +static struct platform_driver snd_rpi_iqaudio_dac_driver = {
206 + .driver = {
207 + .name = "snd-rpi-iqaudio-dac",
208 + .owner = THIS_MODULE,
209 + .of_match_table = iqaudio_of_match,
210 + },
211 + .probe = snd_rpi_iqaudio_dac_probe,
212 + .remove = snd_rpi_iqaudio_dac_remove,
213 +};
214 +
215 +module_platform_driver(snd_rpi_iqaudio_dac_driver);
216 +
217 +MODULE_AUTHOR("Florian Meier <florian.meier@koalo.de>");
218 +MODULE_DESCRIPTION("ASoC Driver for IQAudio DAC");
219 +MODULE_LICENSE("GPL v2");
220 diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
221 index ef9ac1e..d0e7539 100644
222 --- a/sound/soc/codecs/Kconfig
223 +++ b/sound/soc/codecs/Kconfig
224 @@ -57,6 +57,7 @@ config SND_SOC_ALL_CODECS
225 select SND_SOC_PCM3008
226 select SND_SOC_PCM1794A
227 select SND_SOC_PCM5102A
228 + select SND_SOC_PCM512x if SND_SOC_I2C_AND_SPI
229 select SND_SOC_RT5631 if I2C
230 select SND_SOC_SGTL5000 if I2C
231 select SND_SOC_SI476X if MFD_SI476X_CORE
232 @@ -301,6 +302,9 @@ config SND_SOC_PCM1794A
233 config SND_SOC_PCM5102A
234 tristate
235
236 +config SND_SOC_PCM512x
237 + tristate
238 +
239 config SND_SOC_RT5631
240 tristate
241
242 diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
243 index e98b865..e630e06 100644
244 --- a/sound/soc/codecs/Makefile
245 +++ b/sound/soc/codecs/Makefile
246 @@ -45,6 +45,7 @@ snd-soc-omap-hdmi-codec-objs := omap-hdmi.o
247 snd-soc-pcm3008-objs := pcm3008.o
248 snd-soc-pcm1794a-objs := pcm1794a.o
249 snd-soc-pcm5102a-objs := pcm5102a.o
250 +snd-soc-pcm512x-objs := pcm512x.o
251 snd-soc-rt5631-objs := rt5631.o
252 snd-soc-sgtl5000-objs := sgtl5000.o
253 snd-soc-alc5623-objs := alc5623.o
254 @@ -174,6 +175,7 @@ obj-$(CONFIG_SND_SOC_OMAP_HDMI_CODEC) += snd-soc-omap-hdmi-codec.o
255 obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
256 obj-$(CONFIG_SND_SOC_PCM1794A) += snd-soc-pcm1794a.o
257 obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o
258 +obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o
259 obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
260 obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
261 obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o
262 diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c
263 new file mode 100644
264 index 0000000..ed36a4a
265 --- /dev/null
266 +++ b/sound/soc/codecs/pcm512x.c
267 @@ -0,0 +1,677 @@
268 +/*
269 + * Driver for the PCM512x CODECs
270 + *
271 + * Author: Mark Brown <broonie@linaro.org>
272 + * Copyright 2014 Linaro Ltd
273 + *
274 + * This program is free software; you can redistribute it and/or
275 + * modify it under the terms of the GNU General Public License
276 + * version 2 as published by the Free Software Foundation.
277 + *
278 + * This program is distributed in the hope that it will be useful, but
279 + * WITHOUT ANY WARRANTY; without even the implied warranty of
280 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
281 + * General Public License for more details.
282 + */
283 +
284 +
285 +#include <linux/init.h>
286 +#include <linux/module.h>
287 +#include <linux/clk.h>
288 +#include <linux/i2c.h>
289 +#include <linux/pm_runtime.h>
290 +#include <linux/regmap.h>
291 +#include <linux/regulator/consumer.h>
292 +#include <linux/spi/spi.h>
293 +#include <sound/soc.h>
294 +#include <sound/soc-dapm.h>
295 +#include <sound/tlv.h>
296 +
297 +#include "pcm512x.h"
298 +
299 +#define PCM512x_NUM_SUPPLIES 3
300 +static const char *pcm512x_supply_names[PCM512x_NUM_SUPPLIES] = {
301 + "AVDD",
302 + "DVDD",
303 + "CPVDD",
304 +};
305 +
306 +struct pcm512x_priv {
307 + struct regmap *regmap;
308 + struct clk *sclk;
309 + struct regulator_bulk_data supplies[PCM512x_NUM_SUPPLIES];
310 + struct notifier_block supply_nb[PCM512x_NUM_SUPPLIES];
311 +};
312 +
313 +/*
314 + * We can't use the same notifier block for more than one supply and
315 + * there's no way I can see to get from a callback to the caller
316 + * except container_of().
317 + */
318 +#define PCM512x_REGULATOR_EVENT(n) \
319 +static int pcm512x_regulator_event_##n(struct notifier_block *nb, \
320 + unsigned long event, void *data) \
321 +{ \
322 + struct pcm512x_priv *pcm512x = container_of(nb, struct pcm512x_priv, \
323 + supply_nb[n]); \
324 + if (event & REGULATOR_EVENT_DISABLE) { \
325 + regcache_mark_dirty(pcm512x->regmap); \
326 + regcache_cache_only(pcm512x->regmap, true); \
327 + } \
328 + return 0; \
329 +}
330 +
331 +PCM512x_REGULATOR_EVENT(0)
332 +PCM512x_REGULATOR_EVENT(1)
333 +PCM512x_REGULATOR_EVENT(2)
334 +
335 +static const struct reg_default pcm512x_reg_defaults[] = {
336 + { PCM512x_RESET, 0x00 },
337 + { PCM512x_POWER, 0x00 },
338 + { PCM512x_MUTE, 0x00 },
339 + { PCM512x_DSP, 0x00 },
340 + { PCM512x_PLL_REF, 0x00 },
341 + { PCM512x_DAC_ROUTING, 0x11 },
342 + { PCM512x_DSP_PROGRAM, 0x01 },
343 + { PCM512x_CLKDET, 0x00 },
344 + { PCM512x_AUTO_MUTE, 0x00 },
345 + { PCM512x_ERROR_DETECT, 0x00 },
346 + { PCM512x_DIGITAL_VOLUME_1, 0x00 },
347 + { PCM512x_DIGITAL_VOLUME_2, 0x30 },
348 + { PCM512x_DIGITAL_VOLUME_3, 0x30 },
349 + { PCM512x_DIGITAL_MUTE_1, 0x22 },
350 + { PCM512x_DIGITAL_MUTE_2, 0x00 },
351 + { PCM512x_DIGITAL_MUTE_3, 0x07 },
352 +};
353 +
354 +static bool pcm512x_readable(struct device *dev, unsigned int reg)
355 +{
356 + switch (reg) {
357 + case PCM512x_RESET:
358 + case PCM512x_POWER:
359 + case PCM512x_MUTE:
360 + case PCM512x_PLL_EN:
361 + case PCM512x_SPI_MISO_FUNCTION:
362 + case PCM512x_DSP:
363 + case PCM512x_GPIO_EN:
364 + case PCM512x_BCLK_LRCLK_CFG:
365 + case PCM512x_DSP_GPIO_INPUT:
366 + case PCM512x_MASTER_MODE:
367 + case PCM512x_PLL_REF:
368 + case PCM512x_PLL_COEFF_0:
369 + case PCM512x_PLL_COEFF_1:
370 + case PCM512x_PLL_COEFF_2:
371 + case PCM512x_PLL_COEFF_3:
372 + case PCM512x_PLL_COEFF_4:
373 + case PCM512x_DSP_CLKDIV:
374 + case PCM512x_DAC_CLKDIV:
375 + case PCM512x_NCP_CLKDIV:
376 + case PCM512x_OSR_CLKDIV:
377 + case PCM512x_MASTER_CLKDIV_1:
378 + case PCM512x_MASTER_CLKDIV_2:
379 + case PCM512x_FS_SPEED_MODE:
380 + case PCM512x_IDAC_1:
381 + case PCM512x_IDAC_2:
382 + case PCM512x_ERROR_DETECT:
383 + case PCM512x_I2S_1:
384 + case PCM512x_I2S_2:
385 + case PCM512x_DAC_ROUTING:
386 + case PCM512x_DSP_PROGRAM:
387 + case PCM512x_CLKDET:
388 + case PCM512x_AUTO_MUTE:
389 + case PCM512x_DIGITAL_VOLUME_1:
390 + case PCM512x_DIGITAL_VOLUME_2:
391 + case PCM512x_DIGITAL_VOLUME_3:
392 + case PCM512x_DIGITAL_MUTE_1:
393 + case PCM512x_DIGITAL_MUTE_2:
394 + case PCM512x_DIGITAL_MUTE_3:
395 + case PCM512x_GPIO_OUTPUT_1:
396 + case PCM512x_GPIO_OUTPUT_2:
397 + case PCM512x_GPIO_OUTPUT_3:
398 + case PCM512x_GPIO_OUTPUT_4:
399 + case PCM512x_GPIO_OUTPUT_5:
400 + case PCM512x_GPIO_OUTPUT_6:
401 + case PCM512x_GPIO_CONTROL_1:
402 + case PCM512x_GPIO_CONTROL_2:
403 + case PCM512x_OVERFLOW:
404 + case PCM512x_RATE_DET_1:
405 + case PCM512x_RATE_DET_2:
406 + case PCM512x_RATE_DET_3:
407 + case PCM512x_RATE_DET_4:
408 + case PCM512x_ANALOG_MUTE_DET:
409 + case PCM512x_GPIN:
410 + case PCM512x_DIGITAL_MUTE_DET:
411 + return true;
412 + default:
413 + return false;
414 + }
415 +}
416 +
417 +static bool pcm512x_volatile(struct device *dev, unsigned int reg)
418 +{
419 + switch (reg) {
420 + case PCM512x_PLL_EN:
421 + case PCM512x_OVERFLOW:
422 + case PCM512x_RATE_DET_1:
423 + case PCM512x_RATE_DET_2:
424 + case PCM512x_RATE_DET_3:
425 + case PCM512x_RATE_DET_4:
426 + case PCM512x_ANALOG_MUTE_DET:
427 + case PCM512x_GPIN:
428 + case PCM512x_DIGITAL_MUTE_DET:
429 + return true;
430 + default:
431 + return false;
432 + }
433 +}
434 +
435 +static const DECLARE_TLV_DB_SCALE(digital_tlv, -10350, 50, 1);
436 +
437 +static const char *pcm512x_dsp_program_texts[] = {
438 + "FIR interpolation with de-emphasis",
439 + "Low latency IIR with de-emphasis",
440 + "High attenuation with de-emphasis",
441 + "Ringing-less low latency FIR",
442 +};
443 +
444 +static const unsigned int pcm512x_dsp_program_values[] = {
445 + 1,
446 + 2,
447 + 3,
448 + 5,
449 + 7,
450 +};
451 +
452 +static const SOC_VALUE_ENUM_SINGLE_DECL(pcm512x_dsp_program,
453 + PCM512x_DSP_PROGRAM, 0, 0x1f,
454 + pcm512x_dsp_program_texts,
455 + pcm512x_dsp_program_values);
456 +
457 +static const char *pcm512x_clk_missing_text[] = {
458 + "1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s"
459 +};
460 +
461 +static const struct soc_enum pcm512x_clk_missing =
462 + SOC_ENUM_SINGLE(PCM512x_CLKDET, 0, 7, pcm512x_clk_missing_text);
463 +
464 +static const char *pcm512x_autom_text[] = {
465 + "21ms", "106ms", "213ms", "533ms", "1.07s", "2.13s", "5.33s", "10.66s"
466 +};
467 +
468 +static const struct soc_enum pcm512x_autom_l =
469 + SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATML_SHIFT, 7,
470 + pcm512x_autom_text);
471 +
472 +static const struct soc_enum pcm512x_autom_r =
473 + SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATMR_SHIFT, 7,
474 + pcm512x_autom_text);
475 +
476 +static const char *pcm512x_ramp_rate_text[] = {
477 + "1 sample/update", "2 samples/update", "4 samples/update",
478 + "Immediate"
479 +};
480 +
481 +static const struct soc_enum pcm512x_vndf =
482 + SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDF_SHIFT, 4,
483 + pcm512x_ramp_rate_text);
484 +
485 +static const struct soc_enum pcm512x_vnuf =
486 + SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUF_SHIFT, 4,
487 + pcm512x_ramp_rate_text);
488 +
489 +static const struct soc_enum pcm512x_vedf =
490 + SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDF_SHIFT, 4,
491 + pcm512x_ramp_rate_text);
492 +
493 +static const char *pcm512x_ramp_step_text[] = {
494 + "4dB/step", "2dB/step", "1dB/step", "0.5dB/step"
495 +};
496 +
497 +static const struct soc_enum pcm512x_vnds =
498 + SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDS_SHIFT, 4,
499 + pcm512x_ramp_step_text);
500 +
501 +static const struct soc_enum pcm512x_vnus =
502 + SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUS_SHIFT, 4,
503 + pcm512x_ramp_step_text);
504 +
505 +static const struct soc_enum pcm512x_veds =
506 + SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDS_SHIFT, 4,
507 + pcm512x_ramp_step_text);
508 +
509 +static const struct snd_kcontrol_new pcm512x_controls[] = {
510 +SOC_DOUBLE_R_TLV("Playback Digital Volume", PCM512x_DIGITAL_VOLUME_2,
511 + PCM512x_DIGITAL_VOLUME_3, 0, 255, 1, digital_tlv),
512 +SOC_DOUBLE("Playback Digital Switch", PCM512x_MUTE, PCM512x_RQML_SHIFT,
513 + PCM512x_RQMR_SHIFT, 1, 1),
514 +
515 +SOC_SINGLE("Deemphasis Switch", PCM512x_DSP, PCM512x_DEMP_SHIFT, 1, 1),
516 +SOC_VALUE_ENUM("DSP Program", pcm512x_dsp_program),
517 +
518 +SOC_ENUM("Clock Missing Period", pcm512x_clk_missing),
519 +SOC_ENUM("Auto Mute Time Left", pcm512x_autom_l),
520 +SOC_ENUM("Auto Mute Time Right", pcm512x_autom_r),
521 +SOC_SINGLE("Auto Mute Mono Switch", PCM512x_DIGITAL_MUTE_3,
522 + PCM512x_ACTL_SHIFT, 1, 0),
523 +SOC_DOUBLE("Auto Mute Switch", PCM512x_DIGITAL_MUTE_3, PCM512x_AMLE_SHIFT,
524 + PCM512x_AMLR_SHIFT, 1, 0),
525 +
526 +SOC_ENUM("Volume Ramp Down Rate", pcm512x_vndf),
527 +SOC_ENUM("Volume Ramp Down Step", pcm512x_vnds),
528 +SOC_ENUM("Volume Ramp Up Rate", pcm512x_vnuf),
529 +SOC_ENUM("Volume Ramp Up Step", pcm512x_vnus),
530 +SOC_ENUM("Volume Ramp Down Emergency Rate", pcm512x_vedf),
531 +SOC_ENUM("Volume Ramp Down Emergency Step", pcm512x_veds),
532 +};
533 +
534 +static const struct snd_soc_dapm_widget pcm512x_dapm_widgets[] = {
535 +SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0),
536 +SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0),
537 +
538 +SND_SOC_DAPM_OUTPUT("OUTL"),
539 +SND_SOC_DAPM_OUTPUT("OUTR"),
540 +};
541 +
542 +static const struct snd_soc_dapm_route pcm512x_dapm_routes[] = {
543 + { "DACL", NULL, "Playback" },
544 + { "DACR", NULL, "Playback" },
545 +
546 + { "OUTL", NULL, "DACL" },
547 + { "OUTR", NULL, "DACR" },
548 +};
549 +
550 +static int pcm512x_set_bias_level(struct snd_soc_codec *codec,
551 + enum snd_soc_bias_level level)
552 +{
553 + struct pcm512x_priv *pcm512x = dev_get_drvdata(codec->dev);
554 + int ret;
555 +
556 + switch (level) {
557 + case SND_SOC_BIAS_ON:
558 + case SND_SOC_BIAS_PREPARE:
559 + break;
560 +
561 + case SND_SOC_BIAS_STANDBY:
562 + ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
563 + PCM512x_RQST, 0);
564 + if (ret != 0) {
565 + dev_err(codec->dev, "Failed to remove standby: %d\n",
566 + ret);
567 + return ret;
568 + }
569 + break;
570 +
571 + case SND_SOC_BIAS_OFF:
572 + ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
573 + PCM512x_RQST, PCM512x_RQST);
574 + if (ret != 0) {
575 + dev_err(codec->dev, "Failed to request standby: %d\n",
576 + ret);
577 + return ret;
578 + }
579 + break;
580 + }
581 +
582 + codec->dapm.bias_level = level;
583 +
584 + return 0;
585 +}
586 +
587 +static struct snd_soc_dai_driver pcm512x_dai = {
588 + .name = "pcm512x-hifi",
589 + .playback = {
590 + .stream_name = "Playback",
591 + .channels_min = 2,
592 + .channels_max = 2,
593 + .rates = SNDRV_PCM_RATE_8000_192000,
594 + .formats = SNDRV_PCM_FMTBIT_S16_LE |
595 + SNDRV_PCM_FMTBIT_S24_LE |
596 + SNDRV_PCM_FMTBIT_S32_LE
597 + },
598 +};
599 +
600 +static struct snd_soc_codec_driver pcm512x_codec_driver = {
601 + .set_bias_level = pcm512x_set_bias_level,
602 + .idle_bias_off = true,
603 +
604 + .controls = pcm512x_controls,
605 + .num_controls = ARRAY_SIZE(pcm512x_controls),
606 + .dapm_widgets = pcm512x_dapm_widgets,
607 + .num_dapm_widgets = ARRAY_SIZE(pcm512x_dapm_widgets),
608 + .dapm_routes = pcm512x_dapm_routes,
609 + .num_dapm_routes = ARRAY_SIZE(pcm512x_dapm_routes),
610 +};
611 +
612 +static const struct regmap_config pcm512x_regmap = {
613 + .reg_bits = 8,
614 + .val_bits = 8,
615 +
616 + .readable_reg = pcm512x_readable,
617 + .volatile_reg = pcm512x_volatile,
618 +
619 + .max_register = PCM512x_MAX_REGISTER,
620 + .reg_defaults = pcm512x_reg_defaults,
621 + .num_reg_defaults = ARRAY_SIZE(pcm512x_reg_defaults),
622 + .cache_type = REGCACHE_RBTREE,
623 +};
624 +
625 +static const struct of_device_id pcm512x_of_match[] = {
626 + { .compatible = "ti,pcm5121", },
627 + { .compatible = "ti,pcm5122", },
628 + { }
629 +};
630 +MODULE_DEVICE_TABLE(of, pcm512x_of_match);
631 +
632 +static int pcm512x_probe(struct device *dev, struct regmap *regmap)
633 +{
634 + struct pcm512x_priv *pcm512x;
635 + int i, ret;
636 +
637 + pcm512x = devm_kzalloc(dev, sizeof(struct pcm512x_priv), GFP_KERNEL);
638 + if (!pcm512x)
639 + return -ENOMEM;
640 +
641 + dev_set_drvdata(dev, pcm512x);
642 + pcm512x->regmap = regmap;
643 +
644 + for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++)
645 + pcm512x->supplies[i].supply = pcm512x_supply_names[i];
646 +
647 + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(pcm512x->supplies),
648 + pcm512x->supplies);
649 + if (ret != 0) {
650 + dev_err(dev, "Failed to get supplies: %d\n", ret);
651 + return ret;
652 + }
653 +
654 + pcm512x->supply_nb[0].notifier_call = pcm512x_regulator_event_0;
655 + pcm512x->supply_nb[1].notifier_call = pcm512x_regulator_event_1;
656 + pcm512x->supply_nb[2].notifier_call = pcm512x_regulator_event_2;
657 +
658 + for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++) {
659 + ret = regulator_register_notifier(pcm512x->supplies[i].consumer,
660 + &pcm512x->supply_nb[i]);
661 + if (ret != 0) {
662 + dev_err(dev,
663 + "Failed to register regulator notifier: %d\n",
664 + ret);
665 + }
666 + }
667 +
668 + ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies),
669 + pcm512x->supplies);
670 + if (ret != 0) {
671 + dev_err(dev, "Failed to enable supplies: %d\n", ret);
672 + return ret;
673 + }
674 +
675 + /* Reset the device, verifying I/O in the process for I2C */
676 + ret = regmap_write(regmap, PCM512x_RESET,
677 + PCM512x_RSTM | PCM512x_RSTR);
678 + if (ret != 0) {
679 + dev_err(dev, "Failed to reset device: %d\n", ret);
680 + goto err;
681 + }
682 +
683 + ret = regmap_write(regmap, PCM512x_RESET, 0);
684 + if (ret != 0) {
685 + dev_err(dev, "Failed to reset device: %d\n", ret);
686 + goto err;
687 + }
688 +
689 + pcm512x->sclk = devm_clk_get(dev, NULL);
690 + if (IS_ERR(pcm512x->sclk)) {
691 + if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER)
692 + return -EPROBE_DEFER;
693 +
694 + dev_info(dev, "No SCLK, using BCLK: %ld\n",
695 + PTR_ERR(pcm512x->sclk));
696 +
697 + /* Disable reporting of missing SCLK as an error */
698 + regmap_update_bits(regmap, PCM512x_ERROR_DETECT,
699 + PCM512x_IDCH, PCM512x_IDCH);
700 +
701 + /* Switch PLL input to BCLK */
702 + regmap_update_bits(regmap, PCM512x_PLL_REF,
703 + PCM512x_SREF, PCM512x_SREF);
704 + } else {
705 + ret = clk_prepare_enable(pcm512x->sclk);
706 + if (ret != 0) {
707 + dev_err(dev, "Failed to enable SCLK: %d\n", ret);
708 + return ret;
709 + }
710 + }
711 +
712 + /* Default to standby mode */
713 + ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
714 + PCM512x_RQST, PCM512x_RQST);
715 + if (ret != 0) {
716 + dev_err(dev, "Failed to request standby: %d\n",
717 + ret);
718 + goto err_clk;
719 + }
720 +
721 + pm_runtime_set_active(dev);
722 + pm_runtime_enable(dev);
723 + pm_runtime_idle(dev);
724 +
725 + ret = snd_soc_register_codec(dev, &pcm512x_codec_driver,
726 + &pcm512x_dai, 1);
727 + if (ret != 0) {
728 + dev_err(dev, "Failed to register CODEC: %d\n", ret);
729 + goto err_pm;
730 + }
731 +
732 + dev_info(dev, "Completed initialisation - pcm512x_probe");
733 +
734 + return 0;
735 +
736 +err_pm:
737 + pm_runtime_disable(dev);
738 +err_clk:
739 + if (!IS_ERR(pcm512x->sclk))
740 + clk_disable_unprepare(pcm512x->sclk);
741 +err:
742 + regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
743 + pcm512x->supplies);
744 + return ret;
745 +}
746 +
747 +static void pcm512x_remove(struct device *dev)
748 +{
749 + struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
750 +
751 + snd_soc_unregister_codec(dev);
752 + pm_runtime_disable(dev);
753 + if (!IS_ERR(pcm512x->sclk))
754 + clk_disable_unprepare(pcm512x->sclk);
755 + regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
756 + pcm512x->supplies);
757 +}
758 +
759 +/* TODO
760 +static int pcm512x_suspend(struct device *dev)
761 +{
762 + struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
763 + int ret;
764 +
765 + ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
766 + PCM512x_RQPD, PCM512x_RQPD);
767 + if (ret != 0) {
768 + dev_err(dev, "Failed to request power down: %d\n", ret);
769 + return ret;
770 + }
771 +
772 + ret = regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
773 + pcm512x->supplies);
774 + if (ret != 0) {
775 + dev_err(dev, "Failed to disable supplies: %d\n", ret);
776 + return ret;
777 + }
778 +
779 + if (!IS_ERR(pcm512x->sclk))
780 + clk_disable_unprepare(pcm512x->sclk);
781 +
782 + return 0;
783 +}
784 +
785 +static int pcm512x_resume(struct device *dev)
786 +{
787 + struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
788 + int ret;
789 +
790 + if (!IS_ERR(pcm512x->sclk)) {
791 + ret = clk_prepare_enable(pcm512x->sclk);
792 + if (ret != 0) {
793 + dev_err(dev, "Failed to enable SCLK: %d\n", ret);
794 + return ret;
795 + }
796 + }
797 +
798 + ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies),
799 + pcm512x->supplies);
800 + if (ret != 0) {
801 + dev_err(dev, "Failed to enable supplies: %d\n", ret);
802 + return ret;
803 + }
804 +
805 + regcache_cache_only(pcm512x->regmap, false);
806 + ret = regcache_sync(pcm512x->regmap);
807 + if (ret != 0) {
808 + dev_err(dev, "Failed to sync cache: %d\n", ret);
809 + return ret;
810 + }
811 +
812 + ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
813 + PCM512x_RQPD, 0);
814 + if (ret != 0) {
815 + dev_err(dev, "Failed to remove power down: %d\n", ret);
816 + return ret;
817 + }
818 +
819 + return 0;
820 +}
821 +
822 +// END OF PCM512x_suspend and resume calls TODO
823 +*/
824 +
825 +static const struct dev_pm_ops pcm512x_pm_ops = {
826 + SET_RUNTIME_PM_OPS(pcm512x_suspend, pcm512x_resume, NULL)
827 +};
828 +
829 +#if IS_ENABLED(CONFIG_I2C)
830 +static int pcm512x_i2c_probe(struct i2c_client *i2c,
831 + const struct i2c_device_id *id)
832 +{
833 + struct regmap *regmap;
834 +
835 + regmap = devm_regmap_init_i2c(i2c, &pcm512x_regmap);
836 + if (IS_ERR(regmap))
837 + return PTR_ERR(regmap);
838 +
839 + return pcm512x_probe(&i2c->dev, regmap);
840 +}
841 +
842 +static int pcm512x_i2c_remove(struct i2c_client *i2c)
843 +{
844 + pcm512x_remove(&i2c->dev);
845 + return 0;
846 +}
847 +
848 +static const struct i2c_device_id pcm512x_i2c_id[] = {
849 + { "pcm5121", },
850 + { "pcm5122", },
851 + { }
852 +};
853 +MODULE_DEVICE_TABLE(i2c, pcm512x_i2c_id);
854 +
855 +static struct i2c_driver pcm512x_i2c_driver = {
856 + .probe = pcm512x_i2c_probe,
857 + .remove = pcm512x_i2c_remove,
858 + .id_table = pcm512x_i2c_id,
859 + .driver = {
860 + .name = "pcm512x",
861 + .owner = THIS_MODULE,
862 + .of_match_table = pcm512x_of_match,
863 + .pm = &pcm512x_pm_ops,
864 + },
865 +};
866 +#endif
867 +
868 +#if defined(CONFIG_SPI_MASTER)
869 +static int pcm512x_spi_probe(struct spi_device *spi)
870 +{
871 + struct regmap *regmap;
872 + int ret;
873 +
874 + regmap = devm_regmap_init_spi(spi, &pcm512x_regmap);
875 + if (IS_ERR(regmap)) {
876 + ret = PTR_ERR(regmap);
877 + return ret;
878 + }
879 +
880 + return pcm512x_probe(&spi->dev, regmap);
881 +}
882 +
883 +static int pcm512x_spi_remove(struct spi_device *spi)
884 +{
885 + pcm512x_remove(&spi->dev);
886 + return 0;
887 +}
888 +
889 +static const struct spi_device_id pcm512x_spi_id[] = {
890 + { "pcm5121", },
891 + { "pcm5122", },
892 + { },
893 +};
894 +MODULE_DEVICE_TABLE(spi, pcm512x_spi_id);
895 +
896 +static struct spi_driver pcm512x_spi_driver = {
897 + .probe = pcm512x_spi_probe,
898 + .remove = pcm512x_spi_remove,
899 + .id_table = pcm512x_spi_id,
900 + .driver = {
901 + .name = "pcm512x",
902 + .owner = THIS_MODULE,
903 + .of_match_table = pcm512x_of_match,
904 + .pm = &pcm512x_pm_ops,
905 + },
906 +};
907 +#endif
908 +
909 +static int __init pcm512x_modinit(void)
910 +{
911 + int ret = 0;
912 +
913 +#if IS_ENABLED(CONFIG_I2C)
914 + ret = i2c_add_driver(&pcm512x_i2c_driver);
915 + if (ret) {
916 + printk(KERN_ERR "Failed to register pcm512x I2C driver: %d\n",
917 + ret);
918 + }
919 +#endif
920 +#if defined(CONFIG_SPI_MASTER)
921 + ret = spi_register_driver(&pcm512x_spi_driver);
922 + if (ret != 0) {
923 + printk(KERN_ERR "Failed to register pcm512x SPI driver: %d\n",
924 + ret);
925 + }
926 +#endif
927 + return ret;
928 +}
929 +module_init(pcm512x_modinit);
930 +
931 +static void __exit pcm512x_exit(void)
932 +{
933 +#if IS_ENABLED(CONFIG_I2C)
934 + i2c_del_driver(&pcm512x_i2c_driver);
935 +#endif
936 +#if defined(CONFIG_SPI_MASTER)
937 + spi_unregister_driver(&pcm512x_spi_driver);
938 +#endif
939 +}
940 +module_exit(pcm512x_exit);
941 +
942 +MODULE_DESCRIPTION("ASoC PCM512x codec driver");
943 +MODULE_AUTHOR("Mark Brown <broonie@linaro.org>");
944 +MODULE_LICENSE("GPL v2");
945 diff --git a/sound/soc/codecs/pcm512x.h b/sound/soc/codecs/pcm512x.h
946 new file mode 100644
947 index 0000000..b2f518e
948 --- /dev/null
949 +++ b/sound/soc/codecs/pcm512x.h
950 @@ -0,0 +1,142 @@
951 +/*
952 + * Driver for the PCM512x CODECs
953 + *
954 + * Author: Mark Brown <broonie@linaro.org>
955 + * Copyright 2014 Linaro Ltd
956 + *
957 + * This program is free software; you can redistribute it and/or
958 + * modify it under the terms of the GNU General Public License
959 + * version 2 as published by the Free Software Foundation.
960 + *
961 + * This program is distributed in the hope that it will be useful, but
962 + * WITHOUT ANY WARRANTY; without even the implied warranty of
963 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
964 + * General Public License for more details.
965 + */
966 +
967 +#ifndef _SND_SOC_PCM512X
968 +#define _SND_SOC_PCM512X
969 +
970 +#define PCM512x_PAGE_0_BASE 0
971 +
972 +#define PCM512x_PAGE 0
973 +
974 +#define PCM512x_RESET (PCM512x_PAGE_0_BASE + 1)
975 +#define PCM512x_POWER (PCM512x_PAGE_0_BASE + 2)
976 +#define PCM512x_MUTE (PCM512x_PAGE_0_BASE + 3)
977 +#define PCM512x_PLL_EN (PCM512x_PAGE_0_BASE + 4)
978 +#define PCM512x_SPI_MISO_FUNCTION (PCM512x_PAGE_0_BASE + 6)
979 +#define PCM512x_DSP (PCM512x_PAGE_0_BASE + 7)
980 +#define PCM512x_GPIO_EN (PCM512x_PAGE_0_BASE + 8)
981 +#define PCM512x_BCLK_LRCLK_CFG (PCM512x_PAGE_0_BASE + 9)
982 +#define PCM512x_DSP_GPIO_INPUT (PCM512x_PAGE_0_BASE + 10)
983 +#define PCM512x_MASTER_MODE (PCM512x_PAGE_0_BASE + 12)
984 +#define PCM512x_PLL_REF (PCM512x_PAGE_0_BASE + 13)
985 +#define PCM512x_PLL_COEFF_0 (PCM512x_PAGE_0_BASE + 20)
986 +#define PCM512x_PLL_COEFF_1 (PCM512x_PAGE_0_BASE + 21)
987 +#define PCM512x_PLL_COEFF_2 (PCM512x_PAGE_0_BASE + 22)
988 +#define PCM512x_PLL_COEFF_3 (PCM512x_PAGE_0_BASE + 23)
989 +#define PCM512x_PLL_COEFF_4 (PCM512x_PAGE_0_BASE + 24)
990 +#define PCM512x_DSP_CLKDIV (PCM512x_PAGE_0_BASE + 27)
991 +#define PCM512x_DAC_CLKDIV (PCM512x_PAGE_0_BASE + 28)
992 +#define PCM512x_NCP_CLKDIV (PCM512x_PAGE_0_BASE + 29)
993 +#define PCM512x_OSR_CLKDIV (PCM512x_PAGE_0_BASE + 30)
994 +#define PCM512x_MASTER_CLKDIV_1 (PCM512x_PAGE_0_BASE + 32)
995 +#define PCM512x_MASTER_CLKDIV_2 (PCM512x_PAGE_0_BASE + 33)
996 +#define PCM512x_FS_SPEED_MODE (PCM512x_PAGE_0_BASE + 34)
997 +#define PCM512x_IDAC_1 (PCM512x_PAGE_0_BASE + 35)
998 +#define PCM512x_IDAC_2 (PCM512x_PAGE_0_BASE + 36)
999 +#define PCM512x_ERROR_DETECT (PCM512x_PAGE_0_BASE + 37)
1000 +#define PCM512x_I2S_1 (PCM512x_PAGE_0_BASE + 40)
1001 +#define PCM512x_I2S_2 (PCM512x_PAGE_0_BASE + 41)
1002 +#define PCM512x_DAC_ROUTING (PCM512x_PAGE_0_BASE + 42)
1003 +#define PCM512x_DSP_PROGRAM (PCM512x_PAGE_0_BASE + 43)
1004 +#define PCM512x_CLKDET (PCM512x_PAGE_0_BASE + 44)
1005 +#define PCM512x_AUTO_MUTE (PCM512x_PAGE_0_BASE + 59)
1006 +#define PCM512x_DIGITAL_VOLUME_1 (PCM512x_PAGE_0_BASE + 60)
1007 +#define PCM512x_DIGITAL_VOLUME_2 (PCM512x_PAGE_0_BASE + 61)
1008 +#define PCM512x_DIGITAL_VOLUME_3 (PCM512x_PAGE_0_BASE + 62)
1009 +#define PCM512x_DIGITAL_MUTE_1 (PCM512x_PAGE_0_BASE + 63)
1010 +#define PCM512x_DIGITAL_MUTE_2 (PCM512x_PAGE_0_BASE + 64)
1011 +#define PCM512x_DIGITAL_MUTE_3 (PCM512x_PAGE_0_BASE + 65)
1012 +#define PCM512x_GPIO_OUTPUT_1 (PCM512x_PAGE_0_BASE + 80)
1013 +#define PCM512x_GPIO_OUTPUT_2 (PCM512x_PAGE_0_BASE + 81)
1014 +#define PCM512x_GPIO_OUTPUT_3 (PCM512x_PAGE_0_BASE + 82)
1015 +#define PCM512x_GPIO_OUTPUT_4 (PCM512x_PAGE_0_BASE + 83)
1016 +#define PCM512x_GPIO_OUTPUT_5 (PCM512x_PAGE_0_BASE + 84)
1017 +#define PCM512x_GPIO_OUTPUT_6 (PCM512x_PAGE_0_BASE + 85)
1018 +#define PCM512x_GPIO_CONTROL_1 (PCM512x_PAGE_0_BASE + 86)
1019 +#define PCM512x_GPIO_CONTROL_2 (PCM512x_PAGE_0_BASE + 87)
1020 +#define PCM512x_OVERFLOW (PCM512x_PAGE_0_BASE + 90)
1021 +#define PCM512x_RATE_DET_1 (PCM512x_PAGE_0_BASE + 91)
1022 +#define PCM512x_RATE_DET_2 (PCM512x_PAGE_0_BASE + 92)
1023 +#define PCM512x_RATE_DET_3 (PCM512x_PAGE_0_BASE + 93)
1024 +#define PCM512x_RATE_DET_4 (PCM512x_PAGE_0_BASE + 94)
1025 +#define PCM512x_ANALOG_MUTE_DET (PCM512x_PAGE_0_BASE + 108)
1026 +#define PCM512x_GPIN (PCM512x_PAGE_0_BASE + 119)
1027 +#define PCM512x_DIGITAL_MUTE_DET (PCM512x_PAGE_0_BASE + 120)
1028 +
1029 +#define PCM512x_MAX_REGISTER (PCM512x_PAGE_0_BASE + 120)
1030 +
1031 +/* Page 0, Register 1 - reset */
1032 +#define PCM512x_RSTR (1 << 0)
1033 +#define PCM512x_RSTM (1 << 4)
1034 +
1035 +/* Page 0, Register 2 - power */
1036 +#define PCM512x_RQPD (1 << 0)
1037 +#define PCM512x_RQPD_SHIFT 0
1038 +#define PCM512x_RQST (1 << 4)
1039 +#define PCM512x_RQST_SHIFT 4
1040 +
1041 +/* Page 0, Register 3 - mute */
1042 +#define PCM512x_RQMR_SHIFT 0
1043 +#define PCM512x_RQML_SHIFT 4
1044 +
1045 +/* Page 0, Register 4 - PLL */
1046 +#define PCM512x_PLCE (1 << 0)
1047 +#define PCM512x_RLCE_SHIFT 0
1048 +#define PCM512x_PLCK (1 << 4)
1049 +#define PCM512x_PLCK_SHIFT 4
1050 +
1051 +/* Page 0, Register 7 - DSP */
1052 +#define PCM512x_SDSL (1 << 0)
1053 +#define PCM512x_SDSL_SHIFT 0
1054 +#define PCM512x_DEMP (1 << 4)
1055 +#define PCM512x_DEMP_SHIFT 4
1056 +
1057 +/* Page 0, Register 13 - PLL reference */
1058 +#define PCM512x_SREF (1 << 4)
1059 +
1060 +/* Page 0, Register 37 - Error detection */
1061 +#define PCM512x_IPLK (1 << 0)
1062 +#define PCM512x_DCAS (1 << 1)
1063 +#define PCM512x_IDCM (1 << 2)
1064 +#define PCM512x_IDCH (1 << 3)
1065 +#define PCM512x_IDSK (1 << 4)
1066 +#define PCM512x_IDBK (1 << 5)
1067 +#define PCM512x_IDFS (1 << 6)
1068 +
1069 +/* Page 0, Register 42 - DAC routing */
1070 +#define PCM512x_AUPR_SHIFT 0
1071 +#define PCM512x_AUPL_SHIFT 4
1072 +
1073 +/* Page 0, Register 59 - auto mute */
1074 +#define PCM512x_ATMR_SHIFT 0
1075 +#define PCM512x_ATML_SHIFT 4
1076 +
1077 +/* Page 0, Register 63 - ramp rates */
1078 +#define PCM512x_VNDF_SHIFT 6
1079 +#define PCM512x_VNDS_SHIFT 4
1080 +#define PCM512x_VNUF_SHIFT 2
1081 +#define PCM512x_VNUS_SHIFT 0
1082 +
1083 +/* Page 0, Register 64 - emergency ramp rates */
1084 +#define PCM512x_VEDF_SHIFT 6
1085 +#define PCM512x_VEDS_SHIFT 4
1086 +
1087 +/* Page 0, Register 65 - Digital mute enables */
1088 +#define PCM512x_ACTL_SHIFT 2
1089 +#define PCM512x_AMLE_SHIFT 1
1090 +#define PCM512x_AMLR_SHIFT 0
1091 +
1092 +#endif
1093 --
1094 1.9.1
1095