Skip to content

Commit 4d27e44

Browse files
yc-hou-0919scorpiochang
authored andcommitted
Add Google voice HAT sound card
Change-Id: Iaf141901d36f528e2e42acd56c3c510806f6743a Reviewed-on: https://tp-biosrd-v02/gerrit/82240 Reviewed-by: Scorpio Chang(張志賢) <Scorpio_Chang@asus.com> Tested-by: Scorpio Chang(張志賢) <Scorpio_Chang@asus.com>
1 parent 8716c70 commit 4d27e44

File tree

7 files changed

+407
-0
lines changed

7 files changed

+407
-0
lines changed

arch/arm/boot/dts/overlays/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ dtbo-$(CONFIG_ARCH_ROCKCHIP) += \
2020
lirc-rpi.dtbo \
2121
lirc-toshiba.dtbo \
2222
mcp2515-can0.dtbo \
23+
googlevoicehat-soundcard.dtbo \
2324

2425

2526
targets += dtbs dtbs_install
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Definitions for Google voiceHAT v1 soundcard overlay
2+
/dts-v1/;
3+
/plugin/;
4+
5+
/ {
6+
compatible = "rockchip,rk3288-miniarm", "rockchip,rk3288";
7+
8+
fragment@0 {
9+
target = <&i2s>;
10+
__overlay__ {
11+
status = "okay";
12+
};
13+
};
14+
15+
fragment@1 {
16+
target = <&gpio7>;
17+
__overlay__ {
18+
googlevoicehat_pins: googlevoicehat_pins {
19+
rockchip,pins = <7 7 1 &pcfg_pull_up>;
20+
};
21+
};
22+
};
23+
24+
25+
fragment@2 {
26+
target-path = "/";
27+
__overlay__ {
28+
voicehat-codec {
29+
#sound-dai-cells = <0>;
30+
compatible = "google,voicehat";
31+
pinctrl-names = "default";
32+
pinctrl-0 = <&googlevoicehat_pins>;
33+
sdmode-gpios= <&gpio7 7 0>;
34+
status = "okay";
35+
};
36+
};
37+
};
38+
39+
fragment@3 {
40+
target-path = "/sound-ext-card";
41+
__overlay__ {
42+
compatible = "googlevoicehat,googlevoicehat-soundcard";
43+
i2s-controller = <&i2s>;
44+
status = "okay";
45+
};
46+
};
47+
48+
/* Must disable other i2s device(s) first */
49+
fragment@4 {
50+
target-path ="/sound-simple-card";
51+
__overlay__ {
52+
status = "disabled";
53+
};
54+
};
55+
56+
fragment@5 {
57+
target = <&hdmi>;
58+
__overlay__ {
59+
hdmi-i2s-audio-disable;
60+
};
61+
};
62+
};

arch/arm/configs/miniarm-rk3288_defconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,3 +826,4 @@ CONFIG_TASK_IO_ACCOUNTING=y
826826
CONFIG_CAN=y
827827
CONFIG_CAN_DEV=y
828828
CONFIG_CAN_MCP251X=y
829+
CONFIG_SND_SOC_GOOGLEVOICEHAT_CARD=y

sound/soc/rockchip/Kconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,9 @@ config SND_SOC_JUSTBOOM_DIGI
143143
select SND_SOC_WM8804_I2C
144144
help
145145
Say Y or M if you want to add support for JustBoom Digi.
146+
147+
config SND_SOC_GOOGLEVOICEHAT_CARD
148+
tristate "Support for Google voice HAT sound card"
149+
select SND_SOC_VOICEHAT
150+
help
151+
Say Y or M if you want to add support for Google voice HAT sound card.

sound/soc/rockchip/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ snd-soc-iqaudio-dac-objs := iqaudio-dac.o
2424
snd-soc-iqaudio-digi-objs := iqaudio-digi.o
2525
snd-soc-justboom-dac-objs := justboom-dac.o
2626
snd-soc-justboom-digi-objs := justboom-digi.o
27+
snd-soc-googlevoicehat-soundcard-objs := googlevoicehat-soundcard.o
28+
snd-soc-googlevoicehat-codec-objs := googlevoicehat-codec.o
2729

2830
obj-$(CONFIG_SND_SOC_ROCKCHIP_DA7219) += snd-soc-rockchip-da7219.o
2931
obj-$(CONFIG_SND_SOC_ROCKCHIP_HDMI_ANALOG) += snd-soc-rockchip-hdmi-analog.o
@@ -40,3 +42,5 @@ obj-$(CONFIG_SND_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o
4042
obj-$(CONFIG_SND_SOC_IQAUDIO_DIGI) += snd-soc-iqaudio-digi.o
4143
obj-$(CONFIG_SND_SOC_JUSTBOOM_DAC) += snd-soc-justboom-dac.o
4244
obj-$(CONFIG_SND_SOC_JUSTBOOM_DIGI) += snd-soc-justboom-digi.o
45+
obj-$(CONFIG_SND_SOC_GOOGLEVOICEHAT_CARD) += snd-soc-googlevoicehat-soundcard.o
46+
obj-$(CONFIG_SND_SOC_GOOGLEVOICEHAT_CARD) += snd-soc-googlevoicehat-codec.o
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
/*
2+
* Driver for the Google voiceHAT audio codec for Raspberry Pi.
3+
*
4+
* Author: Peter Malkin <petermalkin@google.com>
5+
* Copyright 2016
6+
*
7+
* This program is free software; you can redistribute it and/or
8+
* modify it under the terms of the GNU General Public License
9+
* version 2 as published by the Free Software Foundation.
10+
*
11+
* This program is distributed in the hope that it will be useful, but
12+
* WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* General Public License for more details.
15+
*/
16+
17+
#include <linux/device.h>
18+
#include <linux/err.h>
19+
#include <linux/gpio.h>
20+
#include <linux/gpio/consumer.h>
21+
#include <linux/init.h>
22+
#include <linux/kernel.h>
23+
#include <linux/mod_devicetable.h>
24+
#include <linux/module.h>
25+
#include <linux/of.h>
26+
#include <linux/platform_device.h>
27+
#include <linux/version.h>
28+
#include <sound/pcm.h>
29+
#include <sound/soc.h>
30+
#include <sound/soc-dai.h>
31+
#include <sound/soc-dapm.h>
32+
33+
#define ICS43432_RATE_MIN_HZ 7190 /* from data sheet */
34+
#define ICS43432_RATE_MAX_HZ 52800 /* from data sheet */
35+
#define SDMODE_DELAY_MS \
36+
5 /* Delay in enabling SDMODE after clock settles to remove pop */
37+
38+
struct voicehat_priv {
39+
struct delayed_work enable_sdmode_work;
40+
struct gpio_desc *sdmode_gpio;
41+
unsigned int sdmode_delay;
42+
};
43+
44+
static void voicehat_enable_sdmode_work(struct work_struct *work) {
45+
struct voicehat_priv *voicehat =
46+
container_of(work, struct voicehat_priv, enable_sdmode_work.work);
47+
gpiod_set_value(voicehat->sdmode_gpio, 1);
48+
}
49+
50+
static int voicehat_codec_probe(struct snd_soc_codec *codec) {
51+
struct voicehat_priv *voicehat = snd_soc_codec_get_drvdata(codec);
52+
53+
voicehat->sdmode_gpio = devm_gpiod_get(codec->dev, "sdmode", GPIOD_OUT_LOW);
54+
if (IS_ERR(voicehat->sdmode_gpio)) {
55+
dev_err(codec->dev, "Unable to allocate GPIO pin\n");
56+
return PTR_ERR(voicehat->sdmode_gpio);
57+
}
58+
59+
INIT_DELAYED_WORK(&voicehat->enable_sdmode_work, voicehat_enable_sdmode_work);
60+
return 0;
61+
}
62+
63+
static int voicehat_codec_remove(struct snd_soc_codec *codec) {
64+
struct voicehat_priv *voicehat = snd_soc_codec_get_drvdata(codec);
65+
66+
cancel_delayed_work_sync(&voicehat->enable_sdmode_work);
67+
68+
return 0;
69+
}
70+
71+
static const struct snd_soc_dapm_widget voicehat_dapm_widgets[] = {
72+
SND_SOC_DAPM_OUTPUT("Speaker"),
73+
};
74+
75+
static const struct snd_soc_dapm_route voicehat_dapm_routes[] = {
76+
{"Speaker", NULL, "HiFi Playback"},
77+
};
78+
79+
static struct snd_soc_codec_driver voicehat_codec_driver = {
80+
.probe = voicehat_codec_probe,
81+
.remove = voicehat_codec_remove,
82+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
83+
.component_driver = {
84+
#endif
85+
.dapm_widgets = voicehat_dapm_widgets,
86+
.num_dapm_widgets = ARRAY_SIZE(voicehat_dapm_widgets),
87+
.dapm_routes = voicehat_dapm_routes,
88+
.num_dapm_routes = ARRAY_SIZE(voicehat_dapm_routes),
89+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
90+
},
91+
#endif
92+
};
93+
94+
static int voicehat_daiops_trigger(struct snd_pcm_substream *substream, int cmd,
95+
struct snd_soc_dai *dai) {
96+
struct snd_soc_codec *codec = dai->codec;
97+
struct voicehat_priv *voicehat = snd_soc_codec_get_drvdata(codec);
98+
99+
if (voicehat->sdmode_delay == 0) return 0;
100+
101+
dev_dbg(dai->dev, "CMD %d", cmd);
102+
dev_dbg(dai->dev, "Playback Active %d", dai->playback_active);
103+
dev_dbg(dai->dev, "Capture Active %d", dai->capture_active);
104+
105+
switch (cmd) {
106+
case SNDRV_PCM_TRIGGER_START:
107+
case SNDRV_PCM_TRIGGER_RESUME:
108+
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
109+
if (dai->playback_active) {
110+
dev_info(dai->dev, "Enabling audio amp...\n");
111+
queue_delayed_work(system_power_efficient_wq,
112+
&voicehat->enable_sdmode_work,
113+
msecs_to_jiffies(voicehat->sdmode_delay));
114+
}
115+
break;
116+
case SNDRV_PCM_TRIGGER_STOP:
117+
case SNDRV_PCM_TRIGGER_SUSPEND:
118+
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
119+
if (dai->playback_active) {
120+
cancel_delayed_work(&voicehat->enable_sdmode_work);
121+
dev_info(dai->dev, "Disabling audio amp...\n");
122+
gpiod_set_value(voicehat->sdmode_gpio, 0);
123+
}
124+
break;
125+
}
126+
return 0;
127+
}
128+
129+
static const struct snd_soc_dai_ops voicehat_dai_ops = {
130+
.trigger = voicehat_daiops_trigger,
131+
};
132+
133+
static struct snd_soc_dai_driver voicehat_dai = {
134+
.name = "voicehat-hifi",
135+
.capture = {.stream_name = "HiFi Capture",
136+
.channels_min = 2,
137+
.channels_max = 2,
138+
.rates = SNDRV_PCM_RATE_48000,
139+
.formats = SNDRV_PCM_FMTBIT_S32_LE},
140+
.playback = {.stream_name = "HiFi Playback",
141+
.channels_min = 2,
142+
.channels_max = 2,
143+
.rates = SNDRV_PCM_RATE_48000,
144+
.formats = SNDRV_PCM_FMTBIT_S32_LE},
145+
.ops = &voicehat_dai_ops,
146+
.symmetric_rates = 1};
147+
148+
#ifdef CONFIG_OF
149+
static const struct of_device_id voicehat_ids[] = {
150+
{
151+
.compatible = "google,voicehat",
152+
},
153+
{}};
154+
MODULE_DEVICE_TABLE(of, voicehat_ids);
155+
#endif
156+
157+
static int voicehat_platform_probe(struct platform_device *pdev) {
158+
struct voicehat_priv *voicehat;
159+
int ret;
160+
161+
voicehat = devm_kzalloc(&pdev->dev, sizeof(*voicehat), GFP_KERNEL);
162+
if (!voicehat) return -ENOMEM;
163+
164+
ret = device_property_read_u32(&pdev->dev, "voicehat_sdmode_delay",
165+
&voicehat->sdmode_delay);
166+
167+
if (ret) {
168+
voicehat->sdmode_delay = SDMODE_DELAY_MS;
169+
dev_info(&pdev->dev,
170+
"property 'voicehat_sdmode_delay' not found default 5 mS");
171+
} else {
172+
dev_info(&pdev->dev, "property 'voicehat_sdmode_delay' found delay= %d mS",
173+
voicehat->sdmode_delay);
174+
}
175+
176+
dev_set_drvdata(&pdev->dev, voicehat);
177+
178+
return snd_soc_register_codec(&pdev->dev, &voicehat_codec_driver, &voicehat_dai, 1);
179+
}
180+
181+
static int voicehat_platform_remove(struct platform_device *pdev) {
182+
snd_soc_unregister_codec(&pdev->dev);
183+
return 0;
184+
}
185+
186+
static struct platform_driver voicehat_driver = {
187+
.driver =
188+
{
189+
.name = "voicehat-codec", .of_match_table = of_match_ptr(voicehat_ids),
190+
},
191+
.probe = voicehat_platform_probe,
192+
.remove = voicehat_platform_remove,
193+
};
194+
195+
module_platform_driver(voicehat_driver);
196+
197+
MODULE_DESCRIPTION("Google voiceHAT Codec driver");
198+
MODULE_AUTHOR("Peter Malkin <petermalkin@google.com>");
199+
MODULE_LICENSE("GPL v2");

0 commit comments

Comments
 (0)