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