kernel: update 4.1 to 4.1.10
[openwrt.git] / target / linux / brcm2708 / patches-4.1 / 0170-RaspiDAC3-support.patch
1 From 023b465fbab6f672219706bbe19a9fbfa38c6192 Mon Sep 17 00:00:00 2001
2 From: Jan Grulich <jan@grulich.eu>
3 Date: Mon, 24 Aug 2015 16:03:47 +0100
4 Subject: [PATCH 170/171] RaspiDAC3 support
5
6 Signed-off-by: Jan Grulich <jan@grulich.eu>
7 ---
8  arch/arm/boot/dts/overlays/Makefile              |   1 +
9  arch/arm/boot/dts/overlays/README                |   6 +
10  arch/arm/boot/dts/overlays/raspidac3-overlay.dts |  45 ++++++
11  arch/arm/configs/bcm2709_defconfig               |   1 +
12  arch/arm/configs/bcmrpi_defconfig                |   1 +
13  sound/soc/bcm/Kconfig                            |   8 +
14  sound/soc/bcm/Makefile                           |   2 +
15  sound/soc/bcm/raspidac3.c                        | 191 +++++++++++++++++++++++
16  8 files changed, 255 insertions(+)
17  create mode 100644 arch/arm/boot/dts/overlays/raspidac3-overlay.dts
18  create mode 100644 sound/soc/bcm/raspidac3.c
19
20 --- a/arch/arm/boot/dts/overlays/Makefile
21 +++ b/arch/arm/boot/dts/overlays/Makefile
22 @@ -37,6 +37,7 @@ dtb-$(RPI_DT_OVERLAYS) += pitft28-resist
23  dtb-$(RPI_DT_OVERLAYS) += pps-gpio-overlay.dtb
24  dtb-$(RPI_DT_OVERLAYS) += pwm-overlay.dtb
25  dtb-$(RPI_DT_OVERLAYS) += pwm-2chan-overlay.dtb
26 +dtb-$(RPI_DT_OVERLAYS) += raspidac3-overlay.dtb
27  dtb-$(RPI_DT_OVERLAYS) += rpi-dac-overlay.dtb
28  dtb-$(RPI_DT_OVERLAYS) += rpi-display-overlay.dtb
29  dtb-$(RPI_DT_OVERLAYS) += rpi-ft5406-overlay.dtb
30 --- a/arch/arm/boot/dts/overlays/README
31 +++ b/arch/arm/boot/dts/overlays/README
32 @@ -455,6 +455,12 @@ Params: pin                      Output
33          clock                    PWM clock frequency (informational)
34  
35  
36 +Name:   raspidac3
37 +Info:   Configures the RaspiDAV Rev.3x audio card
38 +Load:   dtoverlay=raspidac3
39 +Params: <None>
40 +
41 +
42  Name:   rpi-dac
43  Info:   Configures the RPi DAC audio card
44  Load:   dtoverlay=rpi-dac
45 --- /dev/null
46 +++ b/arch/arm/boot/dts/overlays/raspidac3-overlay.dts
47 @@ -0,0 +1,45 @@
48 +// Definitions for RaspiDACv3
49 +/dts-v1/;
50 +/plugin/;
51 +
52 +/ {
53 +       compatible = "brcm,bcm2708";
54 +
55 +       fragment@0 {
56 +               target = <&sound>;
57 +               __overlay__ {
58 +                       compatible = "jg,raspidacv3";
59 +                       i2s-controller = <&i2s>;
60 +                       status = "okay";
61 +               };
62 +       };
63 +
64 +       fragment@1 {
65 +               target = <&i2s>;
66 +               __overlay__ {
67 +                       status = "okay";
68 +               };
69 +       };
70 +
71 +       fragment@2 {
72 +               target = <&i2c1>;
73 +               __overlay__ {
74 +                       #address-cells = <1>;
75 +                       #size-cells = <0>;
76 +                       status = "okay";
77 +
78 +                       pcm5122@4c {
79 +                               #sound-dai-cells = <0>;
80 +                               compatible = "ti,pcm5122";
81 +                               reg = <0x4c>;
82 +                               status = "okay";
83 +                       };
84 +
85 +                       tpa6130a2: tpa6130a2@60 {
86 +                               compatible = "ti,tpa6130a2";
87 +                               reg = <0x60>;
88 +                               status = "okay";
89 +                       };
90 +               };
91 +       };
92 +};
93 --- a/arch/arm/configs/bcm2709_defconfig
94 +++ b/arch/arm/configs/bcm2709_defconfig
95 @@ -830,6 +830,7 @@ CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m
96  CONFIG_SND_BCM2708_SOC_RPI_DAC=m
97  CONFIG_SND_BCM2708_SOC_RPI_PROTO=m
98  CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
99 +CONFIG_SND_BCM2708_SOC_RASPIDAC3=m
100  CONFIG_SND_SOC_WM8804_I2C=m
101  CONFIG_SND_SIMPLE_CARD=m
102  CONFIG_SOUND_PRIME=m
103 --- a/arch/arm/configs/bcmrpi_defconfig
104 +++ b/arch/arm/configs/bcmrpi_defconfig
105 @@ -823,6 +823,7 @@ CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m
106  CONFIG_SND_BCM2708_SOC_RPI_DAC=m
107  CONFIG_SND_BCM2708_SOC_RPI_PROTO=m
108  CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
109 +CONFIG_SND_BCM2708_SOC_RASPIDAC3=m
110  CONFIG_SND_SOC_WM8804_I2C=m
111  CONFIG_SND_SIMPLE_CARD=m
112  CONFIG_SOUND_PRIME=m
113 --- a/sound/soc/bcm/Kconfig
114 +++ b/sound/soc/bcm/Kconfig
115 @@ -67,3 +67,11 @@ config SND_BCM2708_SOC_IQAUDIO_DAC
116         select SND_SOC_PCM512x_I2C
117         help
118           Say Y or M if you want to add support for IQaudIO-DAC.
119 +
120 +config SND_BCM2708_SOC_RASPIDAC3
121 +       tristate "Support for RaspiDAC Rev.3x"
122 +       depends on SND_BCM2708_SOC_I2S
123 +       select SND_SOC_PCM512x_I2C
124 +       select SND_SOC_TPA6130A2
125 +       help
126 +         Say Y or M if you want to add support for RaspiDAC Rev.3x.
127 --- a/sound/soc/bcm/Makefile
128 +++ b/sound/soc/bcm/Makefile
129 @@ -16,6 +16,7 @@ snd-soc-hifiberry-amp-objs := hifiberry_
130  snd-soc-rpi-dac-objs := rpi-dac.o
131  snd-soc-rpi-proto-objs := rpi-proto.o
132  snd-soc-iqaudio-dac-objs := iqaudio-dac.o
133 +snd-soc-raspidac3-objs := raspidac3.o
134  
135  obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o
136  obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o
137 @@ -24,3 +25,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_A
138  obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o
139  obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o
140  obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o
141 +obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o
142 --- /dev/null
143 +++ b/sound/soc/bcm/raspidac3.c
144 @@ -0,0 +1,191 @@
145 +/*
146 + * ASoC Driver for RaspiDAC v3
147 + *
148 + * Author:     Jan Grulich <jan@grulich.eu>
149 + *             Copyright 2015
150 + *              based on code by Daniel Matuschek <daniel@hifiberry.com>
151 + *             based on code by Florian Meier <florian.meier@koalo.de>
152 + *
153 + * This program is free software; you can redistribute it and/or
154 + * modify it under the terms of the GNU General Public License
155 + * version 2 as published by the Free Software Foundation.
156 + *
157 + * This program is distributed in the hope that it will be useful, but
158 + * WITHOUT ANY WARRANTY; without even the implied warranty of
159 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
160 + * General Public License for more details.
161 + */
162 +
163 +#include <linux/module.h>
164 +#include <linux/platform_device.h>
165 +
166 +#include <sound/core.h>
167 +#include <sound/pcm.h>
168 +#include <sound/pcm_params.h>
169 +#include <sound/soc.h>
170 +#include <sound/jack.h>
171 +#include <sound/soc-dapm.h>
172 +
173 +#include "../codecs/pcm512x.h"
174 +#include "../codecs/tpa6130a2.h"
175 +
176 +/* sound card init */
177 +static int snd_rpi_raspidac3_init(struct snd_soc_pcm_runtime *rtd)
178 +{
179 +       int ret;
180 +       struct snd_soc_card *card = rtd->card;
181 +       struct snd_soc_codec *codec = rtd->codec;
182 +       snd_soc_update_bits(codec, PCM512x_GPIO_EN, 0x08, 0x08);
183 +       snd_soc_update_bits(codec, PCM512x_GPIO_OUTPUT_4, 0xf, 0x02);
184 +       snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x00);
185 +
186 +       ret = snd_soc_limit_volume(codec, "Digital Playback Volume", 207);
187 +       if (ret < 0)
188 +               dev_warn(card->dev, "Failed to set volume limit: %d\n", ret);
189 +       else {
190 +               struct snd_kcontrol *kctl;
191 +
192 +               ret = tpa6130a2_add_controls(codec);
193 +               if (ret < 0)
194 +                       dev_warn(card->dev, "Failed to add TPA6130A2 controls: %d\n",
195 +                                ret);
196 +               ret = snd_soc_limit_volume(codec,
197 +                                          "TPA6130A2 Headphone Playback Volume",
198 +                                          54);
199 +               if (ret < 0)
200 +                       dev_warn(card->dev, "Failed to set TPA6130A2 volume limit: %d\n",
201 +                                ret);
202 +               kctl = snd_soc_card_get_kcontrol(card,
203 +                                                "TPA6130A2 Headphone Playback Volume");
204 +               if (kctl) {
205 +                       strcpy(kctl->id.name, "Headphones Playback Volume");
206 +                       /* disable the volume dB scale so alsamixer works */
207 +                       kctl->vd[0].access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
208 +               }
209 +
210 +               kctl = snd_soc_card_get_kcontrol(card,
211 +                                                "TPA6130A2 Headphone Playback Switch");
212 +               if (kctl)
213 +                       strcpy(kctl->id.name, "Headphones Playback Switch");
214 +       }
215 +
216 +       return 0;
217 +}
218 +
219 +/* set hw parameters */
220 +static int snd_rpi_raspidac3_hw_params(struct snd_pcm_substream *substream,
221 +                                      struct snd_pcm_hw_params *params)
222 +{
223 +       struct snd_soc_pcm_runtime *rtd = substream->private_data;
224 +       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
225 +
226 +       unsigned int sample_bits =
227 +               snd_pcm_format_physical_width(params_format(params));
228 +
229 +       return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2);
230 +}
231 +
232 +/* startup */
233 +static int snd_rpi_raspidac3_startup(struct snd_pcm_substream *substream) {
234 +       struct snd_soc_pcm_runtime *rtd = substream->private_data;
235 +       struct snd_soc_codec *codec = rtd->codec;
236 +       snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x08);
237 +       tpa6130a2_stereo_enable(codec, 1);
238 +       return 0;
239 +}
240 +
241 +/* shutdown */
242 +static void snd_rpi_raspidac3_shutdown(struct snd_pcm_substream *substream) {
243 +       struct snd_soc_pcm_runtime *rtd = substream->private_data;
244 +       struct snd_soc_codec *codec = rtd->codec;
245 +       snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08,0x00);
246 +       tpa6130a2_stereo_enable(codec, 0);
247 +}
248 +
249 +/* machine stream operations */
250 +static struct snd_soc_ops snd_rpi_raspidac3_ops = {
251 +       .hw_params = snd_rpi_raspidac3_hw_params,
252 +       .startup = snd_rpi_raspidac3_startup,
253 +       .shutdown = snd_rpi_raspidac3_shutdown,
254 +};
255 +
256 +/* interface setup */
257 +static struct snd_soc_dai_link snd_rpi_raspidac3_dai[] = {
258 +{
259 +       .name           = "RaspiDAC Rev.3x",
260 +       .stream_name    = "RaspiDAC HiFi",
261 +       .cpu_dai_name   = "bcm2708-i2s.0",
262 +       .codec_dai_name = "pcm512x-hifi",
263 +       .platform_name  = "bcm2708-i2s.0",
264 +       .codec_name     = "pcm512x.1-004c",
265 +       .dai_fmt        = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
266 +                               SND_SOC_DAIFMT_CBS_CFS,
267 +       .ops            = &snd_rpi_raspidac3_ops,
268 +       .init           = snd_rpi_raspidac3_init,
269 +},
270 +};
271 +
272 +/* audio machine driver */
273 +static struct snd_soc_card snd_rpi_raspidac3 = {
274 +       .name         = "RaspiDAC Rev.3x HiFi Audio Card",
275 +       .dai_link     = snd_rpi_raspidac3_dai,
276 +       .num_links    = ARRAY_SIZE(snd_rpi_raspidac3_dai),
277 +};
278 +
279 +/* sound card test */
280 +static int snd_rpi_raspidac3_probe(struct platform_device *pdev)
281 +{
282 +       int ret = 0;
283 +
284 +       snd_rpi_raspidac3.dev = &pdev->dev;
285 +
286 +       if (pdev->dev.of_node) {
287 +           struct device_node *i2s_node;
288 +           struct snd_soc_dai_link *dai = &snd_rpi_raspidac3_dai[0];
289 +           i2s_node = of_parse_phandle(pdev->dev.of_node,
290 +                                       "i2s-controller", 0);
291 +
292 +           if (i2s_node) {
293 +               dai->cpu_dai_name = NULL;
294 +               dai->cpu_of_node = i2s_node;
295 +               dai->platform_name = NULL;
296 +               dai->platform_of_node = i2s_node;
297 +           }
298 +       }
299 +
300 +       ret = snd_soc_register_card(&snd_rpi_raspidac3);
301 +       if (ret)
302 +               dev_err(&pdev->dev,
303 +                       "snd_soc_register_card() failed: %d\n", ret);
304 +
305 +       return ret;
306 +}
307 +
308 +/* sound card disconnect */
309 +static int snd_rpi_raspidac3_remove(struct platform_device *pdev)
310 +{
311 +       return snd_soc_unregister_card(&snd_rpi_raspidac3);
312 +}
313 +
314 +static const struct of_device_id raspidac3_of_match[] = {
315 +       { .compatible = "jg,raspidacv3", },
316 +       {},
317 +};
318 +MODULE_DEVICE_TABLE(of, raspidac3_of_match);
319 +
320 +/* sound card platform driver */
321 +static struct platform_driver snd_rpi_raspidac3_driver = {
322 +       .driver = {
323 +               .name   = "snd-rpi-raspidac3",
324 +               .owner  = THIS_MODULE,
325 +               .of_match_table = raspidac3_of_match,
326 +       },
327 +       .probe          = snd_rpi_raspidac3_probe,
328 +       .remove         = snd_rpi_raspidac3_remove,
329 +};
330 +
331 +module_platform_driver(snd_rpi_raspidac3_driver);
332 +
333 +MODULE_AUTHOR("Jan Grulich <jan@grulich.eu>");
334 +MODULE_DESCRIPTION("ASoC Driver for RaspiDAC Rev.3x");
335 +MODULE_LICENSE("GPL v2");