audio: propagate Error * out of audio_init
Starting from audio_driver_init, propagate errors via Error ** so that audio_init_audiodevs can simply pass &error_fatal, and AUD_register_card can signal faiure. Signed-off-by: Martin Kletzander <mkletzan@redhat.com> [Reworked the audio/audio.c parts, while keeping Martin's hw/ changes. - Paolo] Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
9dcb64c960
commit
cb94ff5f80
@ -1556,7 +1556,7 @@ size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size)
|
||||
}
|
||||
|
||||
static int audio_driver_init(AudioState *s, struct audio_driver *drv,
|
||||
bool msg, Audiodev *dev)
|
||||
Audiodev *dev, Error **errp)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
|
||||
@ -1577,12 +1577,10 @@ static int audio_driver_init(AudioState *s, struct audio_driver *drv,
|
||||
s->drv = drv;
|
||||
return 0;
|
||||
} else {
|
||||
if (!msg) {
|
||||
error_free(local_err);
|
||||
} else if (local_err) {
|
||||
error_report_err(local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
} else {
|
||||
error_report("Could not init `%s' audio driver", drv->name);
|
||||
error_setg(errp, "Could not init `%s' audio driver", drv->name);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@ -1733,7 +1731,7 @@ static void audio_create_default_audiodevs(void)
|
||||
* if dev == NULL => legacy implicit initialization, return the already created
|
||||
* state or create a new one
|
||||
*/
|
||||
static AudioState *audio_init(Audiodev *dev)
|
||||
static AudioState *audio_init(Audiodev *dev, Error **errp)
|
||||
{
|
||||
static bool atexit_registered;
|
||||
int done = 0;
|
||||
@ -1760,9 +1758,9 @@ static AudioState *audio_init(Audiodev *dev)
|
||||
drvname = AudiodevDriver_str(dev->driver);
|
||||
driver = audio_driver_lookup(drvname);
|
||||
if (driver) {
|
||||
done = !audio_driver_init(s, driver, true, dev);
|
||||
done = !audio_driver_init(s, driver, dev, errp);
|
||||
} else {
|
||||
dolog ("Unknown audio driver `%s'\n", drvname);
|
||||
error_setg(errp, "Unknown audio driver `%s'\n", drvname);
|
||||
}
|
||||
if (!done) {
|
||||
goto out;
|
||||
@ -1771,13 +1769,13 @@ static AudioState *audio_init(Audiodev *dev)
|
||||
for (;;) {
|
||||
AudiodevListEntry *e = QSIMPLEQ_FIRST(&default_audiodevs);
|
||||
if (!e) {
|
||||
dolog("no default audio driver available\n");
|
||||
error_setg(errp, "no default audio driver available");
|
||||
goto out;
|
||||
}
|
||||
s->dev = dev = e->dev;
|
||||
drvname = AudiodevDriver_str(dev->driver);
|
||||
driver = audio_driver_lookup(drvname);
|
||||
if (!audio_driver_init(s, driver, false, dev)) {
|
||||
if (!audio_driver_init(s, driver, dev, NULL)) {
|
||||
break;
|
||||
}
|
||||
QSIMPLEQ_REMOVE_HEAD(&default_audiodevs, next);
|
||||
@ -1806,7 +1804,7 @@ out:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void AUD_register_card (const char *name, QEMUSoundCard *card)
|
||||
bool AUD_register_card (const char *name, QEMUSoundCard *card, Error **errp)
|
||||
{
|
||||
if (!card->state) {
|
||||
if (!QTAILQ_EMPTY(&audio_states)) {
|
||||
@ -1820,13 +1818,18 @@ void AUD_register_card (const char *name, QEMUSoundCard *card)
|
||||
if (QSIMPLEQ_EMPTY(&default_audiodevs)) {
|
||||
audio_create_default_audiodevs();
|
||||
}
|
||||
card->state = audio_init(NULL);
|
||||
card->state = audio_init(NULL, errp);
|
||||
if (!card->state) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
card->name = g_strdup (name);
|
||||
memset (&card->entries, 0, sizeof (card->entries));
|
||||
QLIST_INSERT_HEAD(&card->state->card_head, card, entries);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AUD_remove_card (QEMUSoundCard *card)
|
||||
@ -2153,17 +2156,13 @@ void audio_define(Audiodev *dev)
|
||||
QSIMPLEQ_INSERT_TAIL(&audiodevs, e, next);
|
||||
}
|
||||
|
||||
bool audio_init_audiodevs(void)
|
||||
void audio_init_audiodevs(void)
|
||||
{
|
||||
AudiodevListEntry *e;
|
||||
|
||||
QSIMPLEQ_FOREACH(e, &audiodevs, next) {
|
||||
if (!audio_init(e->dev)) {
|
||||
return false;
|
||||
}
|
||||
audio_init(e->dev, &error_fatal);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
audsettings audiodev_to_audsettings(AudiodevPerDirectionOptions *pdo)
|
||||
|
@ -94,7 +94,7 @@ typedef struct QEMUAudioTimeStamp {
|
||||
void AUD_vlog (const char *cap, const char *fmt, va_list ap) G_GNUC_PRINTF(2, 0);
|
||||
void AUD_log (const char *cap, const char *fmt, ...) G_GNUC_PRINTF(2, 3);
|
||||
|
||||
void AUD_register_card (const char *name, QEMUSoundCard *card);
|
||||
bool AUD_register_card (const char *name, QEMUSoundCard *card, Error **errp);
|
||||
void AUD_remove_card (QEMUSoundCard *card);
|
||||
CaptureVoiceOut *AUD_add_capture(
|
||||
AudioState *s,
|
||||
@ -170,7 +170,7 @@ void audio_sample_from_uint64(void *samples, int pos,
|
||||
|
||||
void audio_define(Audiodev *audio);
|
||||
void audio_parse_option(const char *opt);
|
||||
bool audio_init_audiodevs(void);
|
||||
void audio_init_audiodevs(void);
|
||||
void audio_help(void);
|
||||
|
||||
AudioState *audio_state_by_name(const char *name, Error **errp);
|
||||
|
@ -614,7 +614,7 @@ static struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
|
||||
s->codec.card.name = g_strdup(current_machine->audiodev);
|
||||
s->codec.card.state = audio_state_by_name(s->codec.card.name, &error_fatal);
|
||||
}
|
||||
AUD_register_card("OMAP EAC", &s->codec.card);
|
||||
AUD_register_card("OMAP EAC", &s->codec.card, &error_fatal);
|
||||
|
||||
memory_region_init_io(&s->iomem, NULL, &omap_eac_ops, s, "omap.eac",
|
||||
omap_l4_region_size(ta, 0));
|
||||
|
@ -1273,6 +1273,10 @@ static void ac97_realize(PCIDevice *dev, Error **errp)
|
||||
AC97LinkState *s = AC97(dev);
|
||||
uint8_t *c = s->dev.config;
|
||||
|
||||
if (!AUD_register_card ("ac97", &s->card, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO: no need to override */
|
||||
c[PCI_COMMAND] = 0x00; /* pcicmd pci command rw, ro */
|
||||
c[PCI_COMMAND + 1] = 0x00;
|
||||
@ -1306,7 +1310,7 @@ static void ac97_realize(PCIDevice *dev, Error **errp)
|
||||
"ac97-nabm", 256);
|
||||
pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_nam);
|
||||
pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io_nabm);
|
||||
AUD_register_card("ac97", &s->card);
|
||||
|
||||
ac97_on_reset(DEVICE(s));
|
||||
}
|
||||
|
||||
|
@ -255,6 +255,10 @@ static void adlib_realizefn (DeviceState *dev, Error **errp)
|
||||
AdlibState *s = ADLIB(dev);
|
||||
struct audsettings as;
|
||||
|
||||
if (!AUD_register_card ("adlib", &s->card, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
s->opl = OPLCreate (3579545, s->freq);
|
||||
if (!s->opl) {
|
||||
error_setg (errp, "OPLCreate %d failed", s->freq);
|
||||
@ -270,8 +274,6 @@ static void adlib_realizefn (DeviceState *dev, Error **errp)
|
||||
as.fmt = AUDIO_FORMAT_S16;
|
||||
as.endianness = AUDIO_HOST_ENDIANNESS;
|
||||
|
||||
AUD_register_card ("adlib", &s->card);
|
||||
|
||||
s->voice = AUD_open_out (
|
||||
&s->card,
|
||||
s->voice,
|
||||
|
@ -678,13 +678,15 @@ static void cs4231a_realizefn (DeviceState *dev, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!AUD_register_card ("cs4231a", &s->card, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
s->pic = isa_bus_get_irq(bus, s->irq);
|
||||
k = ISADMA_GET_CLASS(s->isa_dma);
|
||||
k->register_channel(s->isa_dma, s->dma, cs_dma_read, s);
|
||||
|
||||
isa_register_ioport (d, &s->ioports, s->port);
|
||||
|
||||
AUD_register_card ("cs4231a", &s->card);
|
||||
}
|
||||
|
||||
static Property cs4231a_properties[] = {
|
||||
|
@ -853,6 +853,10 @@ static void es1370_realize(PCIDevice *dev, Error **errp)
|
||||
ES1370State *s = ES1370(dev);
|
||||
uint8_t *c = s->dev.config;
|
||||
|
||||
if (!AUD_register_card ("es1370", &s->card, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
c[PCI_STATUS + 1] = PCI_STATUS_DEVSEL_SLOW >> 8;
|
||||
|
||||
#if 0
|
||||
@ -868,7 +872,6 @@ static void es1370_realize(PCIDevice *dev, Error **errp)
|
||||
memory_region_init_io (&s->io, OBJECT(s), &es1370_io_ops, s, "es1370", 256);
|
||||
pci_register_bar (&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
|
||||
|
||||
AUD_register_card ("es1370", &s->card);
|
||||
es1370_reset (s);
|
||||
}
|
||||
|
||||
|
@ -241,14 +241,16 @@ static void gus_realizefn (DeviceState *dev, Error **errp)
|
||||
IsaDmaClass *k;
|
||||
struct audsettings as;
|
||||
|
||||
if (!AUD_register_card ("gus", &s->card, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
s->isa_dma = isa_bus_get_dma(bus, s->emu.gusdma);
|
||||
if (!s->isa_dma) {
|
||||
error_setg(errp, "ISA controller does not support DMA");
|
||||
return;
|
||||
}
|
||||
|
||||
AUD_register_card ("gus", &s->card);
|
||||
|
||||
as.freq = s->freq;
|
||||
as.nchannels = 2;
|
||||
as.fmt = AUDIO_FORMAT_S16;
|
||||
|
@ -685,11 +685,14 @@ static void hda_audio_init(HDACodecDevice *hda,
|
||||
const desc_param *param;
|
||||
uint32_t i, type;
|
||||
|
||||
if (!AUD_register_card("hda", &a->card, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
a->desc = desc;
|
||||
a->name = object_get_typename(OBJECT(a));
|
||||
dprint(a, 1, "%s: cad %d\n", __func__, a->hda.cad);
|
||||
|
||||
AUD_register_card("hda", &a->card);
|
||||
for (i = 0; i < a->desc->nnodes; i++) {
|
||||
node = a->desc->nodes + i;
|
||||
param = hda_codec_find_param(node, AC_PAR_AUDIO_WIDGET_CAP);
|
||||
|
@ -281,6 +281,11 @@ void lm4549_init(lm4549_state *s, lm4549_callback data_req_cb, void* opaque,
|
||||
{
|
||||
struct audsettings as;
|
||||
|
||||
/* Register an audio card */
|
||||
if (!AUD_register_card("lm4549", &s->card, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Store the callback and opaque pointer */
|
||||
s->data_req_cb = data_req_cb;
|
||||
s->opaque = opaque;
|
||||
@ -288,9 +293,6 @@ void lm4549_init(lm4549_state *s, lm4549_callback data_req_cb, void* opaque,
|
||||
/* Init the registers */
|
||||
lm4549_reset(s);
|
||||
|
||||
/* Register an audio card */
|
||||
AUD_register_card("lm4549", &s->card);
|
||||
|
||||
/* Open a default voice */
|
||||
as.freq = 48000;
|
||||
as.nchannels = 2;
|
||||
|
@ -123,8 +123,6 @@ static int pcspk_audio_init(PCSpkState *s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
AUD_register_card(s_spk, &s->card);
|
||||
|
||||
s->voice = AUD_open_out(&s->card, s->voice, s_spk, s, pcspk_callback, &as);
|
||||
if (!s->voice) {
|
||||
AUD_log(s_spk, "Could not open voice\n");
|
||||
@ -191,7 +189,7 @@ static void pcspk_realizefn(DeviceState *dev, Error **errp)
|
||||
|
||||
isa_register_ioport(isadev, &s->ioport, s->iobase);
|
||||
|
||||
if (s->card.state) {
|
||||
if (s->card.state && AUD_register_card(s_spk, &s->card, errp)) {
|
||||
pcspk_audio_init(s);
|
||||
}
|
||||
|
||||
|
@ -1402,6 +1402,10 @@ static void sb16_realizefn (DeviceState *dev, Error **errp)
|
||||
SB16State *s = SB16 (dev);
|
||||
IsaDmaClass *k;
|
||||
|
||||
if (!AUD_register_card ("sb16", &s->card, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
s->isa_hdma = isa_bus_get_dma(bus, s->hdma);
|
||||
s->isa_dma = isa_bus_get_dma(bus, s->dma);
|
||||
if (!s->isa_dma || !s->isa_hdma) {
|
||||
@ -1434,8 +1438,6 @@ static void sb16_realizefn (DeviceState *dev, Error **errp)
|
||||
k->register_channel(s->isa_dma, s->dma, SB_read_DMA, s);
|
||||
|
||||
s->can_write = 1;
|
||||
|
||||
AUD_register_card ("sb16", &s->card);
|
||||
}
|
||||
|
||||
static Property sb16_properties[] = {
|
||||
|
@ -426,6 +426,10 @@ static void via_ac97_realize(PCIDevice *pci_dev, Error **errp)
|
||||
ViaAC97State *s = VIA_AC97(pci_dev);
|
||||
Object *o = OBJECT(s);
|
||||
|
||||
if (!AUD_register_card ("via-ac97", &s->card, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Command register Bus Master bit is documented to be fixed at 0 but it's
|
||||
* needed for PCI DMA to work in QEMU. The pegasos2 firmware writes 0 here
|
||||
@ -445,8 +449,6 @@ static void via_ac97_realize(PCIDevice *pci_dev, Error **errp)
|
||||
pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->fm);
|
||||
memory_region_init_io(&s->midi, o, &midi_ops, s, "via-ac97.midi", 4);
|
||||
pci_register_bar(pci_dev, 2, PCI_BASE_ADDRESS_SPACE_IO, &s->midi);
|
||||
|
||||
AUD_register_card ("via-ac97", &s->card);
|
||||
}
|
||||
|
||||
static void via_ac97_exit(PCIDevice *dev)
|
||||
|
@ -624,7 +624,10 @@ static void wm8750_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
WM8750State *s = WM8750(dev);
|
||||
|
||||
AUD_register_card(CODEC, &s->card);
|
||||
if (!AUD_register_card(CODEC, &s->card, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
wm8750_reset(I2C_SLAVE(s));
|
||||
}
|
||||
|
||||
|
@ -1302,6 +1302,10 @@ static void xlnx_dp_realize(DeviceState *dev, Error **errp)
|
||||
DisplaySurface *surface;
|
||||
struct audsettings as;
|
||||
|
||||
if (!AUD_register_card("xlnx_dp.audio", &s->aud_card, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
aux_bus_realize(s->aux_bus);
|
||||
|
||||
qdev_realize(DEVICE(s->dpcd), BUS(s->aux_bus), &error_fatal);
|
||||
@ -1320,8 +1324,6 @@ static void xlnx_dp_realize(DeviceState *dev, Error **errp)
|
||||
as.fmt = AUDIO_FORMAT_S16;
|
||||
as.endianness = 0;
|
||||
|
||||
AUD_register_card("xlnx_dp.audio", &s->aud_card);
|
||||
|
||||
s->amixer_output_stream = AUD_open_out(&s->aud_card,
|
||||
s->amixer_output_stream,
|
||||
"xlnx_dp.audio.out",
|
||||
|
@ -1102,7 +1102,7 @@ static void tsc210x_init(TSC210xState *s,
|
||||
s->card.name = g_strdup(current_machine->audiodev);
|
||||
s->card.state = audio_state_by_name(s->card.name, &error_fatal);
|
||||
}
|
||||
AUD_register_card(s->name, &s->card);
|
||||
AUD_register_card(s->name, &s->card, &error_fatal);
|
||||
|
||||
qemu_register_reset((void *) tsc210x_reset, s);
|
||||
vmstate_register(NULL, 0, vmsd, s);
|
||||
|
@ -944,12 +944,15 @@ static void usb_audio_realize(USBDevice *dev, Error **errp)
|
||||
USBAudioState *s = USB_AUDIO(dev);
|
||||
int i;
|
||||
|
||||
if (!AUD_register_card(TYPE_USB_AUDIO, &s->card, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
dev->usb_desc = s->multi ? &desc_audio_multi : &desc_audio;
|
||||
|
||||
usb_desc_create_serial(dev);
|
||||
usb_desc_init(dev);
|
||||
s->dev.opaque = s;
|
||||
AUD_register_card(TYPE_USB_AUDIO, &s->card);
|
||||
|
||||
s->out.altset = ALTSET_OFF;
|
||||
s->out.vol.mute = false;
|
||||
|
@ -1962,9 +1962,7 @@ static void qemu_create_early_backends(void)
|
||||
* setting machine properties, so they can be referred to.
|
||||
*/
|
||||
configure_blockdev(&bdo_queue, machine_class, snapshot);
|
||||
if (!audio_init_audiodevs()) {
|
||||
exit(1);
|
||||
}
|
||||
audio_init_audiodevs();
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user