Diff
1diff --git a/data/mappings/info_config.hjson b/data/mappings/info_config.hjson
2index e2e9569372e762c60976713f5fa94553e83a5fb3..c0417b8839614e15e300e8b290671a394bf590db 100644
3--- a/data/mappings/info_config.hjson
4+++ b/data/mappings/info_config.hjson
5@@ -19,6 +19,8 @@
6 // Audio
7 "AUDIO_DEFAULT_ON": {"info_key": "audio.default.on", "value_type": "bool"},
8 "AUDIO_DEFAULT_CLICKY_ON": {"info_key": "audio.default.clicky", "value_type": "bool"},
9+ "AUDIO_POWER_CONTROL_PIN": {"info_key": "audio.power_control.pin"},
10+ "AUDIO_POWER_CONTROL_PIN_ON_STATE": {"info_key": "audio.power_control.on_state", "value_type": "int" },
11 "AUDIO_VOICES": {"info_key": "audio.voices", "value_type": "flag"},
12 "SENDSTRING_BELL": {"info_key": "audio.macro_beep", "value_type": "flag"},
13
14diff --git a/data/schemas/keyboard.jsonschema b/data/schemas/keyboard.jsonschema
15index 340eb64ba1aeb42bd349eb1fbb0b9101b774f6b1..5c6788913b0f1b1d1265ba885e02a2a14b0da78a 100644
16--- a/data/schemas/keyboard.jsonschema
17+++ b/data/schemas/keyboard.jsonschema
18@@ -135,6 +135,14 @@
19 },
20 "macro_beep": {"type": "boolean"},
21 "pins": {"$ref": "qmk.definitions.v1#/mcu_pin_array"},
22+ "power_control": {
23+ "type": "object",
24+ "additionalProperties": false,
25+ "properties": {
26+ "on_state": {"$ref": "qmk.definitions.v1#/bit"},
27+ "pin": {"$ref": "qmk.definitions.v1#/mcu_pin"}
28+ }
29+ },
30 "voices": {"type": "boolean"}
31 }
32 },
33diff --git a/docs/feature_audio.md b/docs/feature_audio.md
34index 5227d063c3a543a456000338fe40647fc2f30951..05f32e9840128a333258291a7fa5b37c8b1b4fe2 100644
35--- a/docs/feature_audio.md
36+++ b/docs/feature_audio.md
37@@ -171,29 +171,31 @@ The available keycodes for audio are:
38
39 ## Audio Config
40
41-| Settings | Default | Description |
42-|---------------------------------|----------------------|-------------------------------------------------------------------------------|
43-|`AUDIO_PIN` | *Not defined* |Configures the pin that the speaker is connected to. |
44-|`AUDIO_PIN_ALT` | *Not defined* |Configures the pin for a second speaker or second pin connected to one speaker.|
45-|`AUDIO_PIN_ALT_AS_NEGATIVE` | *Not defined* |Enables support for one speaker connected to two pins. |
46-|`AUDIO_INIT_DELAY` | *Not defined* |Enables delay during startup song to accomidate for USB startup issues. |
47-|`AUDIO_ENABLE_TONE_MULTIPLEXING` | *Not defined* |Enables time splicing/multiplexing to create multiple tones simutaneously. |
48-|`STARTUP_SONG` | `STARTUP_SOUND` |Plays when the keyboard starts up (audio.c) |
49-|`GOODBYE_SONG` | `GOODBYE_SOUND` |Plays when you press the QK_BOOT key (quantum.c) |
50-|`AG_NORM_SONG` | `AG_NORM_SOUND` |Plays when you press AG_NORM (process_magic.c) |
51-|`AG_SWAP_SONG` | `AG_SWAP_SOUND` |Plays when you press AG_SWAP (process_magic.c) |
52-|`CG_NORM_SONG` | `AG_NORM_SOUND` |Plays when you press CG_NORM (process_magic.c) |
53-|`CG_SWAP_SONG` | `AG_SWAP_SOUND` |Plays when you press CG_SWAP (process_magic.c) |
54-|`MUSIC_ON_SONG` | `MUSIC_ON_SOUND` |Plays when music mode is activated (process_music.c) |
55-|`MUSIC_OFF_SONG` | `MUSIC_OFF_SOUND` |Plays when music mode is deactivated (process_music.c) |
56-|`MIDI_ON_SONG` | `MUSIC_ON_SOUND` |Plays when midi mode is activated (process_music.c) |
57-|`MIDI_OFF_SONG` | `MUSIC_OFF_SOUND` |Plays when midi mode is deactivated (process_music.c) |
58-|`CHROMATIC_SONG` | `CHROMATIC_SOUND` |Plays when the chromatic music mode is selected (process_music.c) |
59-|`GUITAR_SONG` | `GUITAR_SOUND` |Plays when the guitar music mode is selected (process_music.c) |
60-|`VIOLIN_SONG` | `VIOLIN_SOUND` |Plays when the violin music mode is selected (process_music.c) |
61-|`MAJOR_SONG` | `MAJOR_SOUND` |Plays when the major music mode is selected (process_music.c) |
62-|`DEFAULT_LAYER_SONGS` | *Not defined* |Plays song when switched default layers with [`set_single_persistent_default_layer(layer)`](ref_functions.md#setting-the-persistent-default-layer)(quantum.c) |
63-|`SENDSTRING_BELL` | *Not defined* |Plays chime when the "enter" ("\a") character is sent (send_string.c) |
64+| Settings | Default | Description |
65+|----------------------------------|----------------------|---------------------------------------------------------------------------------------------|
66+|`AUDIO_PIN` | *Not defined* |Configures the pin that the speaker is connected to. |
67+|`AUDIO_PIN_ALT` | *Not defined* |Configures the pin for a second speaker or second pin connected to one speaker. |
68+|`AUDIO_PIN_ALT_AS_NEGATIVE` | *Not defined* |Enables support for one speaker connected to two pins. |
69+|`AUDIO_INIT_DELAY` | *Not defined* |Enables delay during startup song to accomidate for USB startup issues. |
70+|`AUDIO_ENABLE_TONE_MULTIPLEXING` | *Not defined* |Enables time splicing/multiplexing to create multiple tones simutaneously. |
71+|`AUDIO_POWER_CONTROL_PIN` | *Not defined* |Enables power control code to enable or cut off power to speaker (such as with PAM8302 amp). |
72+|`AUDIO_POWER_CONTROL_PIN_ON_STATE`| `1` |The state of the audio power control pin when audio is "on" - `1` for high, `0` for low. |
73+|`STARTUP_SONG` | `STARTUP_SOUND` |Plays when the keyboard starts up (audio.c) |
74+|`GOODBYE_SONG` | `GOODBYE_SOUND` |Plays when you press the QK_BOOT key (quantum.c) |
75+|`AG_NORM_SONG` | `AG_NORM_SOUND` |Plays when you press AG_NORM (process_magic.c) |
76+|`AG_SWAP_SONG` | `AG_SWAP_SOUND` |Plays when you press AG_SWAP (process_magic.c) |
77+|`CG_NORM_SONG` | `AG_NORM_SOUND` |Plays when you press CG_NORM (process_magic.c) |
78+|`CG_SWAP_SONG` | `AG_SWAP_SOUND` |Plays when you press CG_SWAP (process_magic.c) |
79+|`MUSIC_ON_SONG` | `MUSIC_ON_SOUND` |Plays when music mode is activated (process_music.c) |
80+|`MUSIC_OFF_SONG` | `MUSIC_OFF_SOUND` |Plays when music mode is deactivated (process_music.c) |
81+|`MIDI_ON_SONG` | `MUSIC_ON_SOUND` |Plays when midi mode is activated (process_music.c) |
82+|`MIDI_OFF_SONG` | `MUSIC_OFF_SOUND` |Plays when midi mode is deactivated (process_music.c) |
83+|`CHROMATIC_SONG` | `CHROMATIC_SOUND` |Plays when the chromatic music mode is selected (process_music.c) |
84+|`GUITAR_SONG` | `GUITAR_SOUND` |Plays when the guitar music mode is selected (process_music.c) |
85+|`VIOLIN_SONG` | `VIOLIN_SOUND` |Plays when the violin music mode is selected (process_music.c) |
86+|`MAJOR_SONG` | `MAJOR_SOUND` |Plays when the major music mode is selected (process_music.c) |
87+|`DEFAULT_LAYER_SONGS` | *Not defined* |Plays song when switched default layers with [`set_single_persistent_default_layer(layer)`](ref_functions.md#setting-the-persistent-default-layer)(quantum.c). |
88+|`SENDSTRING_BELL` | *Not defined* |Plays chime when the "enter" ("\a") character is sent (send_string.c) |
89
90 ## Tempo
91 the 'speed' at which SONGs are played is dictated by the set Tempo, which is measured in beats-per-minute. Note lengths are defined relative to that.
92diff --git a/docs/reference_info_json.md b/docs/reference_info_json.md
93index 796db1f2446235d50a642d571884ba7d37dce718..b715c14041cb24f4c13c10bef3eb850d3435a08a 100644
94--- a/docs/reference_info_json.md
95+++ b/docs/reference_info_json.md
96@@ -123,10 +123,17 @@ Configures the [Audio](feature_audio.md) feature.
97 * Default: `false`
98 * `pins` (Required)
99 * The GPIO pin(s) connected to the speaker(s).
100+ * `power_control`
101+ * `on_state`
102+ * The logical GPIO state required to turn the speaker on.
103+ * Default: `1` (on = high)
104+ * `pin`
105+ * The GPIO pin connected to speaker power circuit.
106 * `voices`
107 * Use multiple audio voices.
108 * Default: `false`
109
110+
111 ## Backlight :id=backlight
112
113 Configures the [Backlight](feature_backlight.md) feature.
114diff --git a/keyboards/adafruit/macropad/config.h b/keyboards/adafruit/macropad/config.h
115index 7f2e9ab6f96f46ac230dc73e9bc64d23e2fad573..725530a512b8c603aa4e59c55f9c0de2b037601b 100644
116--- a/keyboards/adafruit/macropad/config.h
117+++ b/keyboards/adafruit/macropad/config.h
118@@ -48,5 +48,3 @@
119 #define AUDIO_PWM_CHANNEL RP2040_PWM_CHANNEL_A
120 #define AUDIO_INIT_DELAY
121 #define AUDIO_CLICKY
122-
123-#define SPEAKER_SHUTDOWN GP14
124diff --git a/keyboards/adafruit/macropad/info.json b/keyboards/adafruit/macropad/info.json
125index 0facf7e0f667a4150a03cadbea045fd0de8a3bc9..295af7833988252f3e948531f2fa43c128c99cc3 100644
126--- a/keyboards/adafruit/macropad/info.json
127+++ b/keyboards/adafruit/macropad/info.json
128@@ -8,6 +8,11 @@
129 "pid": "0x0108",
130 "device_version": "0.0.1"
131 },
132+ "audio": {
133+ "power_control": {
134+ "pin": "GP14"
135+ }
136+ },
137 "encoder": {
138 "rotary": [
139 {"pin_a": "GP18", "pin_b": "GP17"}
140diff --git a/keyboards/adafruit/macropad/macropad.c b/keyboards/adafruit/macropad/macropad.c
141deleted file mode 100644
142index 5c1d2ba5930725ab4df6787b526651b5fd985110..0000000000000000000000000000000000000000
143--- a/keyboards/adafruit/macropad/macropad.c
144+++ /dev/null
145@@ -1,42 +0,0 @@
146-/* Copyright 2022 Jose Pablo Ramirez <jp.ramangulo@gmail.com>
147- *
148- * This program is free software: you can redistribute it and/or modify
149- * it under the terms of the GNU General Public License as published by
150- * the Free Software Foundation, either version 2 of the License, or
151- * (at your option) any later version.
152- *
153- * This program is distributed in the hope that it will be useful,
154- * but WITHOUT ANY WARRANTY; without even the implied warranty of
155- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
156- * GNU General Public License for more details.
157- *
158- * You should have received a copy of the GNU General Public License
159- * along with this program. If not, see <http://www.gnu.org/licenses/>.
160- */
161-
162-#include "quantum.h"
163-
164-#ifdef AUDIO_ENABLE
165-void keyboard_pre_init_kb(void) {
166- // ensure pin is set and enabled pre-audio init
167- setPinOutput(SPEAKER_SHUTDOWN);
168- writePinHigh(SPEAKER_SHUTDOWN);
169- keyboard_pre_init_user();
170-}
171-
172-void keyboard_post_init_kb(void) {
173- // set pin based on active status
174- writePin(SPEAKER_SHUTDOWN, audio_is_on());
175- keyboard_post_init_user();
176-}
177-
178-void audio_on_user(void) {
179- writePinHigh(SPEAKER_SHUTDOWN);
180-}
181-
182-void audio_off_user(void) {
183- // needs a delay or it runs right after play note.
184- wait_ms(200);
185- writePinLow(SPEAKER_SHUTDOWN);
186-}
187-#endif
188diff --git a/platforms/avr/drivers/audio_pwm_hardware.c b/platforms/avr/drivers/audio_pwm_hardware.c
189index d484fba00fbd5705681927b5789986f4855193d6..16264cf0a2286c0eabe83d4eacf614340c19b24a 100644
190--- a/platforms/avr/drivers/audio_pwm_hardware.c
191+++ b/platforms/avr/drivers/audio_pwm_hardware.c
192@@ -213,7 +213,7 @@ void channel_2_stop(void) {
193 }
194 #endif
195
196-void audio_driver_initialize(void) {
197+void audio_driver_initialize_impl(void) {
198 #ifdef AUDIO1_PIN_SET
199 channel_1_stop();
200 gpio_set_pin_output(AUDIO1_PIN);
201@@ -254,7 +254,7 @@ void audio_driver_initialize(void) {
202 #endif
203 }
204
205-void audio_driver_stop(void) {
206+void audio_driver_stop_impl(void) {
207 #ifdef AUDIO1_PIN_SET
208 channel_1_stop();
209 #endif
210@@ -264,7 +264,7 @@ void audio_driver_stop(void) {
211 #endif
212 }
213
214-void audio_driver_start(void) {
215+void audio_driver_start_impl(void) {
216 #ifdef AUDIO1_PIN_SET
217 channel_1_start();
218 if (playing_note) {
219diff --git a/platforms/chibios/drivers/audio_dac_additive.c b/platforms/chibios/drivers/audio_dac_additive.c
220index d6fde42b68fc8d0e276e97a87de55f88223b2a0c..8e29053301f9377626c74b7a96c1ab771a89efb8 100644
221--- a/platforms/chibios/drivers/audio_dac_additive.c
222+++ b/platforms/chibios/drivers/audio_dac_additive.c
223@@ -303,7 +303,7 @@ static const DACConfig dac_conf = {.init = AUDIO_DAC_OFF_VALUE, .datamode = DAC_
224 */
225 static const DACConversionGroup dac_conv_cfg = {.num_channels = 1U, .end_cb = dac_end, .error_cb = dac_error, .trigger = DAC_TRG(0b000)};
226
227-void audio_driver_initialize(void) {
228+void audio_driver_initialize_impl(void) {
229 if ((AUDIO_PIN == A4) || (AUDIO_PIN_ALT == A4)) {
230 palSetLineMode(A4, PAL_MODE_INPUT_ANALOG);
231 dacStart(&DACD1, &dac_conf);
232@@ -350,11 +350,11 @@ void audio_driver_initialize(void) {
233 gptStart(&GPTD6, &gpt6cfg1);
234 }
235
236-void audio_driver_stop(void) {
237+void audio_driver_stop_impl(void) {
238 state = OUTPUT_SHOULD_STOP;
239 }
240
241-void audio_driver_start(void) {
242+void audio_driver_start_impl(void) {
243 gptStartContinuous(&GPTD6, 2U);
244
245 for (uint8_t i = 0; i < AUDIO_MAX_SIMULTANEOUS_TONES; i++) {
246diff --git a/platforms/chibios/drivers/audio_dac_basic.c b/platforms/chibios/drivers/audio_dac_basic.c
247index 9a3f3fea1f3911269a029895a61761993b270781..99b938e610afb8987fd4d3acb21ef3cc2f30b2d5 100644
248--- a/platforms/chibios/drivers/audio_dac_basic.c
249+++ b/platforms/chibios/drivers/audio_dac_basic.c
250@@ -190,7 +190,7 @@ static void gpt_audio_state_cb(GPTDriver *gptp) {
251 }
252 }
253
254-void audio_driver_initialize(void) {
255+void audio_driver_initialize_impl(void) {
256 if ((AUDIO_PIN == A4) || (AUDIO_PIN_ALT == A4)) {
257 palSetPadMode(GPIOA, 4, PAL_MODE_INPUT_ANALOG);
258 dacStart(&DACD1, &dac_conf_ch1);
259@@ -223,7 +223,7 @@ void audio_driver_initialize(void) {
260 gptStart(&AUDIO_STATE_TIMER, &gptStateUpdateCfg);
261 }
262
263-void audio_driver_stop(void) {
264+void audio_driver_stop_impl(void) {
265 if ((AUDIO_PIN == A4) || (AUDIO_PIN_ALT == A4)) {
266 gptStopTimer(&GPTD6);
267
268@@ -241,7 +241,7 @@ void audio_driver_stop(void) {
269 gptStopTimer(&AUDIO_STATE_TIMER);
270 }
271
272-void audio_driver_start(void) {
273+void audio_driver_start_impl(void) {
274 if ((AUDIO_PIN == A4) || (AUDIO_PIN_ALT == A4)) {
275 dacStartConversion(&DACD1, &dac_conv_grp_ch1, (dacsample_t *)dac_buffer_1, AUDIO_DAC_BUFFER_SIZE);
276 }
277diff --git a/platforms/chibios/drivers/audio_pwm_hardware.c b/platforms/chibios/drivers/audio_pwm_hardware.c
278index 21b5c6892cdb0eb2f939299fab460bedf8b8f764..1ba7ec13bcfdd2b0aaf012b3a75892b1219c53ee 100644
279--- a/platforms/chibios/drivers/audio_pwm_hardware.c
280+++ b/platforms/chibios/drivers/audio_pwm_hardware.c
281@@ -87,7 +87,7 @@ static void audio_callback(virtual_timer_t *vtp, void *p) {
282 chSysUnlockFromISR();
283 }
284
285-void audio_driver_initialize(void) {
286+void audio_driver_initialize_impl(void) {
287 pwmStart(&AUDIO_PWM_DRIVER, &pwmCFG);
288
289 // connect the AUDIO_PIN to the PWM hardware
290@@ -100,7 +100,7 @@ void audio_driver_initialize(void) {
291 chVTObjectInit(&audio_vt);
292 }
293
294-void audio_driver_start(void) {
295+void audio_driver_start_impl(void) {
296 channel_1_stop();
297 channel_1_start();
298
299@@ -115,7 +115,7 @@ void audio_driver_start(void) {
300 }
301 }
302
303-void audio_driver_stop(void) {
304+void audio_driver_stop_impl(void) {
305 channel_1_stop();
306 chVTReset(&audio_vt);
307 }
308diff --git a/platforms/chibios/drivers/audio_pwm_software.c b/platforms/chibios/drivers/audio_pwm_software.c
309index 663a9eca165a7375d1cc8292c2227e5c3bdaa527..f48323900b40ad8447a795c42572522aacd639f1 100644
310--- a/platforms/chibios/drivers/audio_pwm_software.c
311+++ b/platforms/chibios/drivers/audio_pwm_software.c
312@@ -121,7 +121,7 @@ GPTConfig gptCFG = {
313 .callback = gpt_callback,
314 };
315
316-void audio_driver_initialize(void) {
317+void audio_driver_initialize_impl(void) {
318 pwmStart(&AUDIO_PWM_DRIVER, &pwmCFG);
319
320 palSetLineMode(AUDIO_PIN, PAL_MODE_OUTPUT_PUSHPULL);
321@@ -138,7 +138,7 @@ void audio_driver_initialize(void) {
322 gptStart(&AUDIO_STATE_TIMER, &gptCFG);
323 }
324
325-void audio_driver_start(void) {
326+void audio_driver_start_impl(void) {
327 channel_1_stop();
328 channel_1_start();
329
330@@ -147,7 +147,7 @@ void audio_driver_start(void) {
331 }
332 }
333
334-void audio_driver_stop(void) {
335+void audio_driver_stop_impl(void) {
336 channel_1_stop();
337 gptStopTimer(&AUDIO_STATE_TIMER);
338 }
339diff --git a/platforms/test/drivers/audio_pwm_hardware.c b/platforms/test/drivers/audio_pwm_hardware.c
340index 336e4f58449d4e1afe99eb5186cd1a4461463ebf..3a0384117a47d40b6d5a7938b9f148a2c9ee033c 100644
341--- a/platforms/test/drivers/audio_pwm_hardware.c
342+++ b/platforms/test/drivers/audio_pwm_hardware.c
343@@ -15,6 +15,6 @@
344
345 #include "audio.h"
346
347-void audio_driver_initialize(void) {}
348-void audio_driver_start() {}
349-void audio_driver_stop() {}
350+void audio_driver_initialize_impl(void) {}
351+void audio_driver_start_impl() {}
352+void audio_driver_stop_impl() {}
353diff --git a/quantum/audio/audio.c b/quantum/audio/audio.c
354index c1a150049305e5a9a4c7929ae0669c90160bdf3f..b2611c5f09966d8cb96747f836de7250fe5736a8 100644
355--- a/quantum/audio/audio.c
356+++ b/quantum/audio/audio.c
357@@ -20,6 +20,7 @@
358 #include "debug.h"
359 #include "wait.h"
360 #include "util.h"
361+#include "gpio.h"
362
363 /* audio system:
364 *
365@@ -121,6 +122,32 @@ static bool audio_initialized = false;
366 static bool audio_driver_stopped = true;
367 audio_config_t audio_config;
368
369+#ifndef AUDIO_POWER_CONTROL_PIN_ON_STATE
370+# define AUDIO_POWER_CONTROL_PIN_ON_STATE 1
371+#endif
372+
373+void audio_driver_initialize(void) {
374+#ifdef AUDIO_POWER_CONTROL_PIN
375+ gpio_set_pin_output_push_pull(AUDIO_POWER_CONTROL_PIN);
376+ gpio_write_pin(AUDIO_POWER_CONTROL_PIN, !AUDIO_POWER_CONTROL_PIN_ON_STATE);
377+#endif
378+ audio_driver_initialize_impl();
379+}
380+
381+void audio_driver_stop(void) {
382+ audio_driver_stop_impl();
383+#ifdef AUDIO_POWER_CONTROL_PIN
384+ gpio_write_pin(AUDIO_POWER_CONTROL_PIN, !AUDIO_POWER_CONTROL_PIN_ON_STATE);
385+#endif
386+}
387+
388+void audio_driver_start(void) {
389+#ifdef AUDIO_POWER_CONTROL_PIN
390+ gpio_write_pin(AUDIO_POWER_CONTROL_PIN, AUDIO_POWER_CONTROL_PIN_ON_STATE);
391+#endif
392+ audio_driver_start_impl();
393+}
394+
395 void eeconfig_update_audio_current(void) {
396 eeconfig_update_audio(audio_config.raw);
397 }
398diff --git a/quantum/audio/audio.h b/quantum/audio/audio.h
399index eb0bedc6f9fcc79589715bcae04e54cac68a4892..054331d6f33a870890d319a0cf6cb681107b4d2d 100644
400--- a/quantum/audio/audio.h
401+++ b/quantum/audio/audio.h
402@@ -215,9 +215,9 @@ void audio_startup(void);
403 // hardware interface
404
405 // implementation in the driver_avr/arm_* respective parts
406-void audio_driver_initialize(void);
407-void audio_driver_start(void);
408-void audio_driver_stop(void);
409+void audio_driver_initialize_impl(void);
410+void audio_driver_start_impl(void);
411+void audio_driver_stop_impl(void);
412
413 /**
414 * @brief get the number of currently active tones