PCSPK (PC Speaker) is an embedded audio device. We don't want it to use audio
when QEMU is configured with `--disable-audio`. This is achieved with minimal,
non-invasive changes to the code.
In essence, the changes ensure that PCSPK does not use the corresponding
audio backend, while functioning the same way in non-audio aspects.
Signed-off-by: Sergei Heifetz <heifetz@yandex-team.com>
---
hw/audio/pcspk.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c
index 916c56fa4c..03fe816024 100644
--- a/hw/audio/pcspk.c
+++ b/hw/audio/pcspk.c
@@ -36,10 +36,12 @@
#include "qom/object.h"
#include "trace.h"
+#ifdef CONFIG_AUDIO
#define PCSPK_BUF_LEN 1792
#define PCSPK_SAMPLE_RATE 32000
#define PCSPK_MAX_FREQ (PCSPK_SAMPLE_RATE >> 1)
#define PCSPK_MIN_COUNT DIV_ROUND_UP(PIT_FREQ, PCSPK_MAX_FREQ)
+#endif
OBJECT_DECLARE_SIMPLE_TYPE(PCSpkState, PC_SPEAKER)
@@ -48,18 +50,25 @@ struct PCSpkState {
MemoryRegion ioport;
uint32_t iobase;
+#ifdef CONFIG_AUDIO
uint8_t sample_buf[PCSPK_BUF_LEN];
+#endif
AudioBackend *audio_be;
+#ifdef CONFIG_AUDIO
SWVoiceOut *voice;
+#endif
PITCommonState *pit;
+#ifdef CONFIG_AUDIO
unsigned int pit_count;
unsigned int samples;
unsigned int play_pos;
+#endif
uint8_t data_on;
uint8_t dummy_refresh_clock;
bool migrate;
};
+#ifdef CONFIG_AUDIO
static const char *s_spk = "pcspk";
static inline void generate_samples(PCSpkState *s)
@@ -131,6 +140,7 @@ static int pcspk_audio_init(PCSpkState *s)
return 0;
}
+#endif
static uint64_t pcspk_io_read(void *opaque, hwaddr addr,
unsigned size)
@@ -161,11 +171,13 @@ static void pcspk_io_write(void *opaque, hwaddr addr, uint64_t val,
s->data_on = (val >> 1) & 1;
pit_set_gate(s->pit, 2, gate);
+#ifdef CONFIG_AUDIO
if (s->voice) {
if (gate) /* restart */
s->play_pos = 0;
AUD_set_active_out(s->voice, gate & s->data_on);
}
+#endif
}
static const MemoryRegionOps pcspk_io_ops = {
@@ -196,10 +208,12 @@ static void pcspk_realizefn(DeviceState *dev, Error **errp)
isa_register_ioport(isadev, &s->ioport, s->iobase);
+#ifdef CONFIG_AUDIO
if (s->audio_be && AUD_backend_check(&s->audio_be, errp)) {
pcspk_audio_init(s);
return;
}
+#endif
}
static bool migrate_needed(void *opaque)
--
2.34.1
On 2/17/26 06:27, Sergei Heifetz wrote:
> PCSPK (PC Speaker) is an embedded audio device. We don't want it to use audio
> when QEMU is configured with `--disable-audio`. This is achieved with minimal,
> non-invasive changes to the code.
>
> In essence, the changes ensure that PCSPK does not use the corresponding
> audio backend, while functioning the same way in non-audio aspects.
>
> Signed-off-by: Sergei Heifetz <heifetz@yandex-team.com>
> ---
> hw/audio/pcspk.c | 14 ++++++++++++++
> 1 file changed, 14 insertions(+)
>
> diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c
> index 916c56fa4c..03fe816024 100644
> --- a/hw/audio/pcspk.c
> +++ b/hw/audio/pcspk.c
> @@ -36,10 +36,12 @@
> #include "qom/object.h"
> #include "trace.h"
>
> +#ifdef CONFIG_AUDIO
> #define PCSPK_BUF_LEN 1792
> #define PCSPK_SAMPLE_RATE 32000
> #define PCSPK_MAX_FREQ (PCSPK_SAMPLE_RATE >> 1)
> #define PCSPK_MIN_COUNT DIV_ROUND_UP(PIT_FREQ, PCSPK_MAX_FREQ)
> +#endif
Not needed.
>
> OBJECT_DECLARE_SIMPLE_TYPE(PCSpkState, PC_SPEAKER)
>
> @@ -48,18 +50,25 @@ struct PCSpkState {
>
> MemoryRegion ioport;
> uint32_t iobase;
> +#ifdef CONFIG_AUDIO
> uint8_t sample_buf[PCSPK_BUF_LEN];
> +#endif
> AudioBackend *audio_be;
> +#ifdef CONFIG_AUDIO
> SWVoiceOut *voice;
> +#endif
> PITCommonState *pit;
> +#ifdef CONFIG_AUDIO
> unsigned int pit_count;
> unsigned int samples;
> unsigned int play_pos;
> +#endif
Please reorder the fields to have a single #ifdef/#endif. Also leave out
DEFINE_AUDIO_PROPERTIES(PCSpkState, audio_be),
which lets you remove audio_be.
Thanks,
Paolo
> uint8_t data_on;
> uint8_t dummy_refresh_clock;
> bool migrate;
> };
>
> +#ifdef CONFIG_AUDIO
> static const char *s_spk = "pcspk";
>
> static inline void generate_samples(PCSpkState *s)
> @@ -131,6 +140,7 @@ static int pcspk_audio_init(PCSpkState *s)
>
> return 0;
> }
> +#endif
>
> static uint64_t pcspk_io_read(void *opaque, hwaddr addr,
> unsigned size)
> @@ -161,11 +171,13 @@ static void pcspk_io_write(void *opaque, hwaddr addr, uint64_t val,
>
> s->data_on = (val >> 1) & 1;
> pit_set_gate(s->pit, 2, gate);
> +#ifdef CONFIG_AUDIO
> if (s->voice) {
> if (gate) /* restart */
> s->play_pos = 0;
> AUD_set_active_out(s->voice, gate & s->data_on);
> }
> +#endif
> }
>
> static const MemoryRegionOps pcspk_io_ops = {
> @@ -196,10 +208,12 @@ static void pcspk_realizefn(DeviceState *dev, Error **errp)
>
> isa_register_ioport(isadev, &s->ioport, s->iobase);
>
> +#ifdef CONFIG_AUDIO
> if (s->audio_be && AUD_backend_check(&s->audio_be, errp)) {
> pcspk_audio_init(s);
> return;
> }
> +#endif
> }
>
> static bool migrate_needed(void *opaque)
On 2/17/26 14:56, Paolo Bonzini wrote:
> On 2/17/26 06:27, Sergei Heifetz wrote:
>> PCSPK (PC Speaker) is an embedded audio device. We don't want it to
>> use audio
>> when QEMU is configured with `--disable-audio`. This is achieved with
>> minimal,
>> non-invasive changes to the code.
>>
>> In essence, the changes ensure that PCSPK does not use the corresponding
>> audio backend, while functioning the same way in non-audio aspects.
>>
>> Signed-off-by: Sergei Heifetz <heifetz@yandex-team.com>
>> ---
>> hw/audio/pcspk.c | 14 ++++++++++++++
>> 1 file changed, 14 insertions(+)
>>
>> diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c
>> index 916c56fa4c..03fe816024 100644
>> --- a/hw/audio/pcspk.c
>> +++ b/hw/audio/pcspk.c
>> @@ -36,10 +36,12 @@
>> #include "qom/object.h"
>> #include "trace.h"
>> +#ifdef CONFIG_AUDIO
>> #define PCSPK_BUF_LEN 1792
>> #define PCSPK_SAMPLE_RATE 32000
>> #define PCSPK_MAX_FREQ (PCSPK_SAMPLE_RATE >> 1)
>> #define PCSPK_MIN_COUNT DIV_ROUND_UP(PIT_FREQ, PCSPK_MAX_FREQ)
>> +#endif
>
> Not needed.
It certainly isn’t needed, but I thought it made sense to add it for
consistency. I’ll drop it.
>
>> OBJECT_DECLARE_SIMPLE_TYPE(PCSpkState, PC_SPEAKER)
>> @@ -48,18 +50,25 @@ struct PCSpkState {
>> MemoryRegion ioport;
>> uint32_t iobase;
>> +#ifdef CONFIG_AUDIO
>> uint8_t sample_buf[PCSPK_BUF_LEN];
>> +#endif
>> AudioBackend *audio_be;
>> +#ifdef CONFIG_AUDIO
>> SWVoiceOut *voice;
>> +#endif
>> PITCommonState *pit;
>> +#ifdef CONFIG_AUDIO
>> unsigned int pit_count;
>> unsigned int samples;
>> unsigned int play_pos;
>> +#endif
>
> Please reorder the fields to have a single #ifdef/#endif.
Ok.
> Also leave out
>
> DEFINE_AUDIO_PROPERTIES(PCSpkState, audio_be),
>
> which lets you remove audio_be.
The reason I didn't remove audio_be initially is that it would require
compiling out a few lines in `hw/i386/pc.c`:
```
object_property_add_alias(OBJECT(pcms), "pcspk-audiodev",
OBJECT(pcms->pcspk), "audiodev");
```
I don't see any problems with that, so I can do it as well.
>
> Thanks,
>
> Paolo
>
>> uint8_t data_on;
>> uint8_t dummy_refresh_clock;
>> bool migrate;
>> };
>> +#ifdef CONFIG_AUDIO
>> static const char *s_spk = "pcspk";
>> static inline void generate_samples(PCSpkState *s)
>> @@ -131,6 +140,7 @@ static int pcspk_audio_init(PCSpkState *s)
>> return 0;
>> }
>> +#endif
>> static uint64_t pcspk_io_read(void *opaque, hwaddr addr,
>> unsigned size)
>> @@ -161,11 +171,13 @@ static void pcspk_io_write(void *opaque, hwaddr
>> addr, uint64_t val,
>> s->data_on = (val >> 1) & 1;
>> pit_set_gate(s->pit, 2, gate);
>> +#ifdef CONFIG_AUDIO
>> if (s->voice) {
>> if (gate) /* restart */
>> s->play_pos = 0;
>> AUD_set_active_out(s->voice, gate & s->data_on);
>> }
>> +#endif
>> }
>> static const MemoryRegionOps pcspk_io_ops = {
>> @@ -196,10 +208,12 @@ static void pcspk_realizefn(DeviceState *dev,
>> Error **errp)
>> isa_register_ioport(isadev, &s->ioport, s->iobase);
>> +#ifdef CONFIG_AUDIO
>> if (s->audio_be && AUD_backend_check(&s->audio_be, errp)) {
>> pcspk_audio_init(s);
>> return;
>> }
>> +#endif
>> }
>> static bool migrate_needed(void *opaque)
>
On 17/02/2026 06.27, Sergei Heifetz wrote:
> PCSPK (PC Speaker) is an embedded audio device. We don't want it to use audio
> when QEMU is configured with `--disable-audio`. This is achieved with minimal,
> non-invasive changes to the code.
>
> In essence, the changes ensure that PCSPK does not use the corresponding
> audio backend, while functioning the same way in non-audio aspects.
>
> Signed-off-by: Sergei Heifetz <heifetz@yandex-team.com>
> ---
> hw/audio/pcspk.c | 14 ++++++++++++++
> 1 file changed, 14 insertions(+)
>
> diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c
> index 916c56fa4c..03fe816024 100644
> --- a/hw/audio/pcspk.c
> +++ b/hw/audio/pcspk.c
> @@ -36,10 +36,12 @@
> #include "qom/object.h"
> #include "trace.h"
>
> +#ifdef CONFIG_AUDIO
> #define PCSPK_BUF_LEN 1792
> #define PCSPK_SAMPLE_RATE 32000
> #define PCSPK_MAX_FREQ (PCSPK_SAMPLE_RATE >> 1)
> #define PCSPK_MIN_COUNT DIV_ROUND_UP(PIT_FREQ, PCSPK_MAX_FREQ)
> +#endif
>
> OBJECT_DECLARE_SIMPLE_TYPE(PCSpkState, PC_SPEAKER)
>
> @@ -48,18 +50,25 @@ struct PCSpkState {
>
> MemoryRegion ioport;
> uint32_t iobase;
> +#ifdef CONFIG_AUDIO
> uint8_t sample_buf[PCSPK_BUF_LEN];
> +#endif
> AudioBackend *audio_be;
> +#ifdef CONFIG_AUDIO
> SWVoiceOut *voice;
> +#endif
> PITCommonState *pit;
> +#ifdef CONFIG_AUDIO
> unsigned int pit_count;
> unsigned int samples;
> unsigned int play_pos;
> +#endif
Could you maybe group the fields that should get disabled together in one
#ifdef here? ... AFAIK the order of the fields should not matter, so it
should be ok to move them together.
Thomas
On 2/17/26 14:14, Thomas Huth wrote:
> On 17/02/2026 06.27, Sergei Heifetz wrote:
>> PCSPK (PC Speaker) is an embedded audio device. We don't want it to
>> use audio
>> when QEMU is configured with `--disable-audio`. This is achieved with
>> minimal,
>> non-invasive changes to the code.
>>
>> In essence, the changes ensure that PCSPK does not use the corresponding
>> audio backend, while functioning the same way in non-audio aspects.
>>
>> Signed-off-by: Sergei Heifetz <heifetz@yandex-team.com>
>> ---
>> hw/audio/pcspk.c | 14 ++++++++++++++
>> 1 file changed, 14 insertions(+)
>>
>> diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c
>> index 916c56fa4c..03fe816024 100644
>> --- a/hw/audio/pcspk.c
>> +++ b/hw/audio/pcspk.c
>> @@ -36,10 +36,12 @@
>> #include "qom/object.h"
>> #include "trace.h"
>> +#ifdef CONFIG_AUDIO
>> #define PCSPK_BUF_LEN 1792
>> #define PCSPK_SAMPLE_RATE 32000
>> #define PCSPK_MAX_FREQ (PCSPK_SAMPLE_RATE >> 1)
>> #define PCSPK_MIN_COUNT DIV_ROUND_UP(PIT_FREQ, PCSPK_MAX_FREQ)
>> +#endif
>> OBJECT_DECLARE_SIMPLE_TYPE(PCSpkState, PC_SPEAKER)
>> @@ -48,18 +50,25 @@ struct PCSpkState {
>> MemoryRegion ioport;
>> uint32_t iobase;
>> +#ifdef CONFIG_AUDIO
>> uint8_t sample_buf[PCSPK_BUF_LEN];
>> +#endif
>> AudioBackend *audio_be;
>> +#ifdef CONFIG_AUDIO
>> SWVoiceOut *voice;
>> +#endif
>> PITCommonState *pit;
>> +#ifdef CONFIG_AUDIO
>> unsigned int pit_count;
>> unsigned int samples;
>> unsigned int play_pos;
>> +#endif
>
> Could you maybe group the fields that should get disabled together in
> one #ifdef here? ... AFAIK the order of the fields should not matter,
> so it should be ok to move them together.
>
> Thomas
>
Yes, I agree — I don’t see any reason why the order would matter here. I
just wanted to be extra careful. I’ll change it.
Thanks for reviewing.
© 2016 - 2026 Red Hat, Inc.