brcm2708: update 4.1 patches
[openwrt/openwrt.git] / target / linux / brcm2708 / patches-4.1 / 0168-RaspiDAC3-support.patch
1 From fb26137a487ca92a90d4ac97d438f8112fca4f66 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 168/222] 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");