c8b4820c9374fc2fd803cb8f372b65122b964c3c
[oweals/openwrt.git] / target / linux / brcm2708 / patches-4.19 / 950-0780-Allow-simultaneous-use-of-JustBoom-DAC-and-Digi.patch
1 From 8f11db84e124da59b8a717d66fc424ef070f4be0 Mon Sep 17 00:00:00 2001
2 From: Johannes Krude <johannes@krude.de>
3 Date: Sat, 16 Nov 2019 13:14:43 +0100
4 Subject: [PATCH] Allow simultaneous use of JustBoom DAC and Digi
5
6 Signed-off-by: Johannes Krude <johannes@krude.de>
7 ---
8  arch/arm/boot/dts/overlays/Makefile           |   1 +
9  arch/arm/boot/dts/overlays/README             |  20 ++
10  .../dts/overlays/justboom-both-overlay.dts    |  65 +++++
11  sound/soc/bcm/Kconfig                         |  12 +
12  sound/soc/bcm/Makefile                        |   2 +
13  sound/soc/bcm/justboom-both.c                 | 269 ++++++++++++++++++
14  11 files changed, 374 insertions(+)
15  create mode 100644 arch/arm/boot/dts/overlays/justboom-both-overlay.dts
16  create mode 100644 sound/soc/bcm/justboom-both.c
17
18 --- a/arch/arm/boot/dts/overlays/Makefile
19 +++ b/arch/arm/boot/dts/overlays/Makefile
20 @@ -86,6 +86,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
21         iqaudio-digi-wm8804-audio.dtbo \
22         irs1125.dtbo \
23         jedec-spi-nor.dtbo \
24 +       justboom-both.dtbo \
25         justboom-dac.dtbo \
26         justboom-digi.dtbo \
27         ltc294x.dtbo \
28 --- a/arch/arm/boot/dts/overlays/README
29 +++ b/arch/arm/boot/dts/overlays/README
30 @@ -1388,6 +1388,26 @@ Params: flash-spi<n>-<m>        Enables
31                                  on SPI<n>, CS#<m>.
32  
33  
34 +Name:   justboom-both
35 +Info:   Simultaneous usage of an justboom-dac and justboom-digi based
36 +        card
37 +Load:   dtoverlay=justboom-both,<param>=<val>
38 +Params: 24db_digital_gain       Allow gain to be applied via the PCM512x codec
39 +                                Digital volume control. Enable with
40 +                                "dtoverlay=justboom-dac,24db_digital_gain"
41 +                                (The default behaviour is that the Digital
42 +                                volume control is limited to a maximum of
43 +                                0dB. ie. it can attenuate but not provide
44 +                                gain. For most users, this will be desired
45 +                                as it will prevent clipping. By appending
46 +                                the 24dB_digital_gain parameter, the Digital
47 +                                volume control will allow up to 24dB of
48 +                                gain. If this parameter is enabled, it is the
49 +                                responsibility of the user to ensure that
50 +                                the Digital volume control is set to a value
51 +                                that does not result in clipping/distortion!)
52 +
53 +
54  Name:   justboom-dac
55  Info:   Configures the JustBoom DAC HAT, Amp HAT, DAC Zero and Amp Zero audio
56          cards
57 --- /dev/null
58 +++ b/arch/arm/boot/dts/overlays/justboom-both-overlay.dts
59 @@ -0,0 +1,65 @@
60 +// SPDX-License-Identifier: GPL-2.0
61 +// Definitions for JustBoom Both (Digi+DAC)
62 +/dts-v1/;
63 +/plugin/;
64 +
65 +/ {
66 +       compatible = "brcm,bcm2835";
67 +
68 +       fragment@0 {
69 +               target = <&i2s>;
70 +               __overlay__ {
71 +                       status = "okay";
72 +               };
73 +       };
74 +
75 +       fragment@1 {
76 +               target = <&i2c1>;
77 +               __overlay__ {
78 +                       #address-cells = <1>;
79 +                       #size-cells = <0>;
80 +                       status = "okay";
81 +
82 +                       wm8804@3b {
83 +                               #sound-dai-cells = <0>;
84 +                               compatible = "wlf,wm8804";
85 +                               reg = <0x3b>;
86 +                               PVDD-supply = <&vdd_3v3_reg>;
87 +                               DVDD-supply = <&vdd_3v3_reg>;
88 +                               status = "okay";
89 +                       };
90 +               };
91 +       };
92 +
93 +       fragment@2 {
94 +               target = <&i2c1>;
95 +               __overlay__ {
96 +                       #address-cells = <1>;
97 +                       #size-cells = <0>;
98 +                       status = "okay";
99 +
100 +                       pcm5122@4d {
101 +                               #sound-dai-cells = <0>;
102 +                               compatible = "ti,pcm5122";
103 +                               reg = <0x4d>;
104 +                               AVDD-supply = <&vdd_3v3_reg>;
105 +                               DVDD-supply = <&vdd_3v3_reg>;
106 +                               CPVDD-supply = <&vdd_3v3_reg>;
107 +                               status = "okay";
108 +                       };
109 +               };
110 +       };
111 +
112 +       fragment@3 {
113 +               target = <&sound>;
114 +               frag3: __overlay__ {
115 +                       compatible = "justboom,justboom-both";
116 +                       i2s-controller = <&i2s>;
117 +                       status = "okay";
118 +               };
119 +       };
120 +
121 +       __overrides__ {
122 +               24db_digital_gain = <&frag3>,"justboom,24db_digital_gain?";
123 +       };
124 +};
125 --- a/sound/soc/bcm/Kconfig
126 +++ b/sound/soc/bcm/Kconfig
127 @@ -102,6 +102,18 @@ config SND_BCM2708_SOC_RPI_PROTO
128         help
129           Say Y or M if you want to add support for Audio Codec Board PROTO (WM8731).
130  
131 +config SND_BCM2708_SOC_JUSTBOOM_BOTH
132 +       tristate "Support for simultaneous JustBoom Digi and JustBoom DAC"
133 +       depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
134 +       select SND_SOC_WM8804
135 +       select SND_SOC_PCM512x
136 +       help
137 +               Say Y or M if you want to add support for simultaneous
138 +               JustBoom Digi and JustBoom DAC.
139 +
140 +               This is not the right choice if you only have one but both of
141 +               these cards.
142 +
143  config SND_BCM2708_SOC_JUSTBOOM_DAC
144         tristate "Support for JustBoom DAC"
145         depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
146 --- a/sound/soc/bcm/Makefile
147 +++ b/sound/soc/bcm/Makefile
148 @@ -16,6 +16,7 @@ snd-soc-hifiberry-dacplus-objs := hifibe
149  snd-soc-hifiberry-dacplusadc-objs := hifiberry_dacplusadc.o
150  snd-soc-hifiberry-dacplusadcpro-objs := hifiberry_dacplusadcpro.o
151  snd-soc-hifiberry-dacplusdsp-objs := hifiberry_dacplusdsp.o
152 +snd-soc-justboom-both-objs := justboom-both.o
153  snd-soc-justboom-dac-objs := justboom-dac.o
154  snd-soc-rpi-cirrus-objs := rpi-cirrus.o
155  snd-soc-rpi-proto-objs := rpi-proto.o
156 @@ -42,6 +43,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_D
157  obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADC) += snd-soc-hifiberry-dacplusadc.o
158  obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSADCPRO) += snd-soc-hifiberry-dacplusadcpro.o
159  obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUSDSP) += snd-soc-hifiberry-dacplusdsp.o
160 +obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_BOTH) += snd-soc-justboom-both.o
161  obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o
162  obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS) += snd-soc-rpi-cirrus.o
163  obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o
164 --- /dev/null
165 +++ b/sound/soc/bcm/justboom-both.c
166 @@ -0,0 +1,269 @@
167 +// SPDX-License-Identifier: GPL-2.0
168 +/*
169 + * rpi--wm8804.c -- ALSA SoC Raspberry Pi soundcard.
170 + *
171 + * Authors: Johannes Krude <johannes@krude.de
172 + *
173 + * Driver for when connecting simultaneously justboom-digi and justboom-dac
174 + *
175 + * Based upon code from:
176 + * justboom-digi.c
177 + * by Milan Neskovic <info@justboom.co>
178 + * justboom-dac.c
179 + * by Milan Neskovic <info@justboom.co>
180 + *
181 + * This program is free software; you can redistribute it and/or
182 + * modify it under the terms of the GNU General Public License
183 + * version 2 as published by the Free Software Foundation.
184 + *
185 + * This program is distributed in the hope that it will be useful, but
186 + * WITHOUT ANY WARRANTY; without even the implied warranty of
187 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
188 + * General Public License for more details.
189 + */
190 +
191 +#include <linux/module.h>
192 +#include <linux/platform_device.h>
193 +
194 +#include <sound/core.h>
195 +#include <sound/pcm.h>
196 +#include <sound/pcm_params.h>
197 +#include <sound/soc.h>
198 +#include <sound/jack.h>
199 +
200 +#include "../codecs/wm8804.h"
201 +#include "../codecs/pcm512x.h"
202 +
203 +
204 +static bool digital_gain_0db_limit = true;
205 +
206 +static int snd_rpi_justboom_both_init(struct snd_soc_pcm_runtime *rtd)
207 +{
208 +       struct snd_soc_component *digi = rtd->codec_dais[0]->component;
209 +       struct snd_soc_component *dac = rtd->codec_dais[1]->component;
210 +
211 +       /* enable  TX output */
212 +       snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x4, 0x0);
213 +
214 +       snd_soc_component_update_bits(dac, PCM512x_GPIO_EN, 0x08, 0x08);
215 +       snd_soc_component_update_bits(dac, PCM512x_GPIO_OUTPUT_4, 0xf, 0x02);
216 +       snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
217 +
218 +       if (digital_gain_0db_limit) {
219 +               int ret;
220 +               struct snd_soc_card *card = rtd->card;
221 +
222 +               ret = snd_soc_limit_volume(card, "Digital Playback Volume",
223 +                                                                       207);
224 +               if (ret < 0)
225 +                       dev_warn(card->dev, "Failed to set volume limit: %d\n",
226 +                                                                       ret);
227 +       }
228 +
229 +       return 0;
230 +}
231 +
232 +static int snd_rpi_justboom_both_hw_params(struct snd_pcm_substream *substream,
233 +                                      struct snd_pcm_hw_params *params)
234 +{
235 +       struct snd_soc_pcm_runtime *rtd = substream->private_data;
236 +       struct snd_soc_dai *codec_dai = rtd->codec_dai;
237 +       struct snd_soc_component *digi = rtd->codec_dais[0]->component;
238 +       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
239 +
240 +       int sysclk = 27000000; /* This is fixed on this board */
241 +
242 +       long mclk_freq    = 0;
243 +       int mclk_div      = 1;
244 +       int sampling_freq = 1;
245 +
246 +       int ret;
247 +
248 +       int samplerate = params_rate(params);
249 +
250 +       if (samplerate <= 96000) {
251 +               mclk_freq = samplerate*256;
252 +               mclk_div  = WM8804_MCLKDIV_256FS;
253 +       } else {
254 +               mclk_freq = samplerate*128;
255 +               mclk_div  = WM8804_MCLKDIV_128FS;
256 +       }
257 +
258 +       switch (samplerate) {
259 +       case 32000:
260 +               sampling_freq = 0x03;
261 +               break;
262 +       case 44100:
263 +               sampling_freq = 0x00;
264 +               break;
265 +       case 48000:
266 +               sampling_freq = 0x02;
267 +               break;
268 +       case 88200:
269 +               sampling_freq = 0x08;
270 +               break;
271 +       case 96000:
272 +               sampling_freq = 0x0a;
273 +               break;
274 +       case 176400:
275 +               sampling_freq = 0x0c;
276 +               break;
277 +       case 192000:
278 +               sampling_freq = 0x0e;
279 +               break;
280 +       default:
281 +               dev_err(rtd->card->dev,
282 +               "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n",
283 +               samplerate);
284 +       }
285 +
286 +       snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div);
287 +       snd_soc_dai_set_pll(codec_dai, 0, 0, sysclk, mclk_freq);
288 +
289 +       ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL,
290 +                                       sysclk, SND_SOC_CLOCK_OUT);
291 +       if (ret < 0) {
292 +               dev_err(rtd->card->dev,
293 +               "Failed to set WM8804 SYSCLK: %d\n", ret);
294 +               return ret;
295 +       }
296 +
297 +       /* Enable TX output */
298 +       snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x4, 0x0);
299 +
300 +       /* Power on */
301 +       snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x9, 0);
302 +
303 +       /* set sampling frequency status bits */
304 +       snd_soc_component_update_bits(digi, WM8804_SPDTX4, 0x0f, sampling_freq);
305 +
306 +       return snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
307 +}
308 +
309 +static int snd_rpi_justboom_both_startup(struct snd_pcm_substream *substream)
310 +{
311 +       struct snd_soc_pcm_runtime *rtd = substream->private_data;
312 +       struct snd_soc_component *digi = rtd->codec_dais[0]->component;
313 +       struct snd_soc_component *dac = rtd->codec_dais[1]->component;
314 +
315 +       /* turn on digital output */
316 +       snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x3c, 0x00);
317 +
318 +       snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x08);
319 +
320 +       return 0;
321 +}
322 +
323 +static void snd_rpi_justboom_both_shutdown(struct snd_pcm_substream *substream)
324 +{
325 +       struct snd_soc_pcm_runtime *rtd = substream->private_data;
326 +       struct snd_soc_component *digi = rtd->codec_dais[0]->component;
327 +       struct snd_soc_component *dac = rtd->codec_dais[1]->component;
328 +
329 +       snd_soc_component_update_bits(dac, PCM512x_GPIO_CONTROL_1, 0x08, 0x00);
330 +
331 +       /* turn off output */
332 +       snd_soc_component_update_bits(digi, WM8804_PWRDN, 0x3c, 0x3c);
333 +}
334 +
335 +/* machine stream operations */
336 +static struct snd_soc_ops snd_rpi_justboom_both_ops = {
337 +       .hw_params = snd_rpi_justboom_both_hw_params,
338 +       .startup   = snd_rpi_justboom_both_startup,
339 +       .shutdown  = snd_rpi_justboom_both_shutdown,
340 +};
341 +
342 +static struct snd_soc_dai_link_component justboom_both_codecs[] = {
343 +{
344 +       .dai_name = "wm8804-spdif",
345 +       .name     = "wm8804.1-003b",
346 +},
347 +{
348 +       .dai_name = "pcm512x-hifi",
349 +       .name     = "pcm512x.1-004d",
350 +},
351 +};
352 +
353 +static struct snd_soc_dai_link snd_rpi_justboom_both_dai[] = {
354 +{
355 +       .name           = "JustBoom Digi",
356 +       .stream_name    = "JustBoom Digi HiFi",
357 +       .cpu_dai_name   = "bcm2708-i2s.0",
358 +       .platform_name  = "bcm2708-i2s.0",
359 +       .codecs         = justboom_both_codecs,
360 +       .num_codecs     = ARRAY_SIZE(justboom_both_codecs),
361 +       .dai_fmt        = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
362 +                                       SND_SOC_DAIFMT_CBM_CFM,
363 +       .ops            = &snd_rpi_justboom_both_ops,
364 +       .init           = snd_rpi_justboom_both_init,
365 +},
366 +};
367 +
368 +/* audio machine driver */
369 +static struct snd_soc_card snd_rpi_justboom_both = {
370 +       .name             = "snd_rpi_justboom_both",
371 +       .driver_name      = "JustBoomBoth",
372 +       .owner            = THIS_MODULE,
373 +       .dai_link         = snd_rpi_justboom_both_dai,
374 +       .num_links        = ARRAY_SIZE(snd_rpi_justboom_both_dai),
375 +};
376 +
377 +static int snd_rpi_justboom_both_probe(struct platform_device *pdev)
378 +{
379 +       int ret = 0;
380 +
381 +       snd_rpi_justboom_both.dev = &pdev->dev;
382 +
383 +       if (pdev->dev.of_node) {
384 +               struct device_node *i2s_node;
385 +               struct snd_soc_dai_link *dai = &snd_rpi_justboom_both_dai[0];
386 +
387 +               i2s_node = of_parse_phandle(pdev->dev.of_node,
388 +                                       "i2s-controller", 0);
389 +
390 +               if (i2s_node) {
391 +                       dai->cpu_dai_name = NULL;
392 +                       dai->cpu_of_node = i2s_node;
393 +                       dai->platform_name = NULL;
394 +                       dai->platform_of_node = i2s_node;
395 +               }
396 +
397 +               digital_gain_0db_limit = !of_property_read_bool(
398 +                       pdev->dev.of_node, "justboom,24db_digital_gain");
399 +       }
400 +
401 +       ret = snd_soc_register_card(&snd_rpi_justboom_both);
402 +       if (ret && ret != -EPROBE_DEFER) {
403 +               dev_err(&pdev->dev,
404 +                       "snd_soc_register_card() failed: %d\n", ret);
405 +       }
406 +
407 +       return ret;
408 +}
409 +
410 +static int snd_rpi_justboom_both_remove(struct platform_device *pdev)
411 +{
412 +       return snd_soc_unregister_card(&snd_rpi_justboom_both);
413 +}
414 +
415 +static const struct of_device_id snd_rpi_justboom_both_of_match[] = {
416 +       { .compatible = "justboom,justboom-both", },
417 +       {},
418 +};
419 +MODULE_DEVICE_TABLE(of, snd_rpi_justboom_both_of_match);
420 +
421 +static struct platform_driver snd_rpi_justboom_both_driver = {
422 +       .driver = {
423 +               .name   = "snd-rpi-justboom-both",
424 +               .owner  = THIS_MODULE,
425 +               .of_match_table = snd_rpi_justboom_both_of_match,
426 +       },
427 +       .probe          = snd_rpi_justboom_both_probe,
428 +       .remove         = snd_rpi_justboom_both_remove,
429 +};
430 +
431 +module_platform_driver(snd_rpi_justboom_both_driver);
432 +
433 +MODULE_AUTHOR("Johannes Krude <johannes@krude.de>");
434 +MODULE_DESCRIPTION("ASoC Driver for simultaneous use of JustBoom PI Digi & DAC HAT Sound Cards");
435 +MODULE_LICENSE("GPL v2");