aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Hackmann <ghackmann@google.com>2013-11-05 11:08:42 -0800
committerDavid 'Digit' Turner <digit@google.com>2014-05-26 10:30:04 +0200
commit8b536b4565cb3466ce0bf3e1b3557bd68b147400 (patch)
tree3e57ba1c8c83bfc50533fff93d5145f5b54690a5
parent3b9fe9c1fcbac7741d9d33ce014fac1b22f44999 (diff)
downloadqemu-arm-8b536b4565cb3466ce0bf3e1b3557bd68b147400.tar.gz
goldfish_audio: port to modern qemu apis
Signed-off-by: Greg Hackmann <ghackmann@google.com>
-rw-r--r--hw/audio/Makefile.objs1
-rw-r--r--hw/audio/goldfish_audio.c390
-rw-r--r--trace-events9
3 files changed, 195 insertions, 205 deletions
diff --git a/hw/audio/Makefile.objs b/hw/audio/Makefile.objs
index 7ce85a2e88..b55c9e032d 100644
--- a/hw/audio/Makefile.objs
+++ b/hw/audio/Makefile.objs
@@ -6,6 +6,7 @@ common-obj-$(CONFIG_ADLIB) += fmopl.o adlib.o
common-obj-$(CONFIG_GUS) += gus.o gusemu_hal.o gusemu_mixer.o
common-obj-$(CONFIG_CS4231A) += cs4231a.o
common-obj-$(CONFIG_HDA) += intel-hda.o hda-codec.o
+common-obj-$(CONFIG_GOLDFISH) += goldfish_audio.o
common-obj-$(CONFIG_PCSPK) += pcspk.o
common-obj-$(CONFIG_WM8750) += wm8750.o
diff --git a/hw/audio/goldfish_audio.c b/hw/audio/goldfish_audio.c
index dc4ae7936b..2bd5d835a7 100644
--- a/hw/audio/goldfish_audio.c
+++ b/hw/audio/goldfish_audio.c
@@ -9,21 +9,14 @@
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
*/
-#include "qemu_file.h"
-#include "goldfish_device.h"
+#include "hw/hw.h"
#include "audio/audio.h"
-#include "qemu_debug.h"
-#include "android/globals.h"
+#include "hw/sysbus.h"
+#include "qemu/error-report.h"
+#include "trace.h"
-#define DEBUG 1
-
-#if DEBUG
-# define D(...) VERBOSE_PRINT(audio,__VA_ARGS__)
-#else
-# define D(...) ((void)0)
-#endif
-
-extern void dprint(const char* fmt, ...);
+#define TYPE_GOLDFISH_AUDIO "goldfish_audio"
+#define GOLDFISH_AUDIO(obj) OBJECT_CHECK(struct goldfish_audio_state, (obj), TYPE_GOLDFISH_AUDIO)
enum {
/* audio status register */
@@ -66,33 +59,28 @@ struct goldfish_audio_buff {
struct goldfish_audio_state {
- struct goldfish_device dev;
+ SysBusDevice parent;
+
+ bool input;
+ bool output;
+
+ MemoryRegion iomem;
+ qemu_irq irq;
+
// buffer flags
uint32_t int_status;
// irq enable mask for int_status
uint32_t int_enable;
- // address of the read buffer
- uint32_t read_buffer;
- // path to file or device to use for input
- const char* input_source;
- // true if input is a wav file
- int input_is_wav;
- // true if we need to convert stereo -> mono
- int input_is_stereo;
- // file descriptor to use for input
- int input_fd;
-
// number of bytes available in the read buffer
- int read_buffer_available;
+ uint32_t read_buffer_available;
- // set to 1 or 2 to indicate which buffer we are writing from, or zero if both buffers are empty
- int current_buffer;
+ // set to 0 or 1 to indicate which buffer we are writing from, or -1 if both buffers are empty
+ int8_t current_buffer;
// current data to write
- struct goldfish_audio_buff out_buff1[1];
- struct goldfish_audio_buff out_buff2[1];
- struct goldfish_audio_buff in_buff[1];
+ struct goldfish_audio_buff out_buffs[2];
+ struct goldfish_audio_buff in_buff;
// for QEMU sound output
QEMUSoundCard card;
@@ -127,7 +115,7 @@ static void
goldfish_audio_buff_ensure( struct goldfish_audio_buff* b, uint32_t size )
{
if (b->capacity < size) {
- b->data = qemu_realloc(b->data, size);
+ b->data = g_realloc(b->data, size);
b->capacity = size;
}
}
@@ -159,20 +147,6 @@ goldfish_audio_buff_write( struct goldfish_audio_buff* b )
}
static int
-goldfish_audio_buff_send( struct goldfish_audio_buff* b, int free, struct goldfish_audio_state* s )
-{
- int ret, write = b->length;
-
- if (write > free)
- write = free;
-
- ret = AUD_write(s->voice, b->data + b->offset, write);
- b->offset += ret;
- b->length -= ret;
- return ret;
-}
-
-static int
goldfish_audio_buff_available( struct goldfish_audio_buff* b )
{
return b->length - b->offset;
@@ -190,7 +164,7 @@ goldfish_audio_buff_recv( struct goldfish_audio_buff* b, int avail, struct gol
return 0;
if (avail2 > 0)
- D("%s: AUD_read(%d) returned %d", __FUNCTION__, avail2, read);
+ trace_goldfish_audio_buff_recv(avail2, read);
cpu_physical_memory_write( b->address + b->offset, b->data, read );
b->offset += read;
@@ -198,219 +172,212 @@ goldfish_audio_buff_recv( struct goldfish_audio_buff* b, int avail, struct gol
return read;
}
-static void
-goldfish_audio_buff_put( struct goldfish_audio_buff* b, QEMUFile* f )
-{
- qemu_put_be32(f, b->address );
- qemu_put_be32(f, b->length );
- qemu_put_be32(f, b->offset );
- qemu_put_buffer(f, b->data, b->length );
-}
-
-static void
-goldfish_audio_buff_get( struct goldfish_audio_buff* b, QEMUFile* f )
-{
- b->address = qemu_get_be32(f);
- b->length = qemu_get_be32(f);
- b->offset = qemu_get_be32(f);
- goldfish_audio_buff_ensure(b, b->length);
- qemu_get_buffer(f, b->data, b->length);
-}
-
/* update this whenever you change the goldfish_audio_state structure */
-#define AUDIO_STATE_SAVE_VERSION 2
-
-#define QFIELD_STRUCT struct goldfish_audio_state
-QFIELD_BEGIN(audio_state_fields)
- QFIELD_INT32(int_status),
- QFIELD_INT32(int_enable),
- QFIELD_INT32(read_buffer_available),
- QFIELD_INT32(current_buffer),
-QFIELD_END
-
-static void audio_state_save( QEMUFile* f, void* opaque )
-{
- struct goldfish_audio_state* s = opaque;
-
- qemu_put_struct(f, audio_state_fields, s);
-
- goldfish_audio_buff_put (s->out_buff1, f);
- goldfish_audio_buff_put (s->out_buff2, f);
- goldfish_audio_buff_put (s->in_buff, f);
-}
-
-static int audio_state_load( QEMUFile* f, void* opaque, int version_id )
-{
- struct goldfish_audio_state* s = opaque;
- int ret;
-
- if (version_id != AUDIO_STATE_SAVE_VERSION)
- return -1;
+#define AUDIO_STATE_SAVE_VERSION 3
+
+static const VMStateDescription goldfish_audio_buff_vmsd = {
+ .name = "goldfish_audio_buff",
+ .version_id = AUDIO_STATE_SAVE_VERSION,
+ .minimum_version_id = AUDIO_STATE_SAVE_VERSION,
+ .minimum_version_id_old = AUDIO_STATE_SAVE_VERSION,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(address, struct goldfish_audio_buff),
+ VMSTATE_UINT32(length, struct goldfish_audio_buff),
+ VMSTATE_UINT32(offset, struct goldfish_audio_buff),
+ VMSTATE_VARRAY_UINT32(data, struct goldfish_audio_buff, length,
+ 0, vmstate_info_uint8, uint8_t),
+ VMSTATE_END_OF_LIST()
+ }
+};
- ret = qemu_get_struct(f, audio_state_fields, s);
- if (!ret) {
- goldfish_audio_buff_get( s->out_buff1, f );
- goldfish_audio_buff_get( s->out_buff2, f );
- goldfish_audio_buff_get (s->in_buff, f);
+static const VMStateDescription goldfish_audio_vmsd = {
+ .name = "goldfish_audio",
+ .version_id = AUDIO_STATE_SAVE_VERSION,
+ .minimum_version_id = AUDIO_STATE_SAVE_VERSION,
+ .minimum_version_id_old = AUDIO_STATE_SAVE_VERSION,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(int_status, struct goldfish_audio_state),
+ VMSTATE_UINT32(int_enable, struct goldfish_audio_state),
+ VMSTATE_UINT32(read_buffer_available, struct goldfish_audio_state),
+ VMSTATE_INT8(current_buffer, struct goldfish_audio_state),
+ VMSTATE_STRUCT_ARRAY(out_buffs, struct goldfish_audio_state, 2, 0,
+ goldfish_audio_buff_vmsd, struct goldfish_audio_buff),
+ VMSTATE_STRUCT(in_buff, struct goldfish_audio_state, 0,
+ goldfish_audio_buff_vmsd, struct goldfish_audio_buff),
+ VMSTATE_END_OF_LIST()
}
- return ret;
-}
+};
static void enable_audio(struct goldfish_audio_state *s, int enable)
{
- // enable or disable the output voice
if (s->voice != NULL) {
- AUD_set_active_out(s->voice, (enable & (AUDIO_INT_WRITE_BUFFER_1_EMPTY | AUDIO_INT_WRITE_BUFFER_2_EMPTY)) != 0);
- goldfish_audio_buff_reset( s->out_buff1 );
- goldfish_audio_buff_reset( s->out_buff2 );
+ goldfish_audio_buff_reset( &s->out_buffs[0] );
+ goldfish_audio_buff_reset( &s->out_buffs[1] );
}
if (s->voicein) {
AUD_set_active_in (s->voicein, (enable & AUDIO_INT_READ_BUFFER_FULL) != 0);
- goldfish_audio_buff_reset( s->in_buff );
+ goldfish_audio_buff_reset( &s->in_buff );
}
- s->current_buffer = 0;
+ s->current_buffer = -1;
}
static void start_read(struct goldfish_audio_state *s, uint32_t count)
{
//printf( "... goldfish audio start_read, count=%d\n", count );
- goldfish_audio_buff_set_length( s->in_buff, count );
+ goldfish_audio_buff_set_length( &s->in_buff, count );
s->read_buffer_available = count;
}
-static uint32_t goldfish_audio_read(void *opaque, target_phys_addr_t offset)
+static uint64_t goldfish_audio_read(void *opaque, hwaddr offset, unsigned size)
{
- uint32_t ret;
+ uint64_t ret;
struct goldfish_audio_state *s = opaque;
switch(offset) {
case AUDIO_INT_STATUS:
// return current buffer status flags
ret = s->int_status & s->int_enable;
if(ret) {
- goldfish_device_set_irq(&s->dev, 0, 0);
+ qemu_irq_lower(s->irq);
}
return ret;
case AUDIO_READ_SUPPORTED:
- D("%s: AUDIO_READ_SUPPORTED returns %d", __FUNCTION__,
+ trace_goldfish_audio_memory_read("AUDIO_READ_SUPPORTED",
(s->voicein != NULL));
return (s->voicein != NULL);
case AUDIO_READ_BUFFER_AVAILABLE:
- D("%s: AUDIO_READ_BUFFER_AVAILABLE returns %d", __FUNCTION__,
+ trace_goldfish_audio_memory_read("AUDIO_READ_BUFFER_AVAILABLE",
s->read_buffer_available);
- goldfish_audio_buff_write( s->in_buff );
+ goldfish_audio_buff_write( &s->in_buff );
return s->read_buffer_available;
default:
- cpu_abort (cpu_single_env, "goldfish_audio_read: Bad offset %x\n", offset);
+ error_report ("goldfish_audio_read: Bad offset 0x" TARGET_FMT_plx,
+ offset);
return 0;
}
}
-static void goldfish_audio_write(void *opaque, target_phys_addr_t offset, uint32_t val)
+static void goldfish_audio_write_buffer(struct goldfish_audio_state *s,
+ unsigned int buf, uint32_t length)
+{
+ if (s->current_buffer == -1)
+ s->current_buffer = buf;
+ goldfish_audio_buff_set_length(&s->out_buffs[buf], length);
+ goldfish_audio_buff_read(&s->out_buffs[buf]);
+ AUD_set_active_out(s->voice, 1);
+}
+
+static void goldfish_audio_write(void *opaque, hwaddr offset, uint64_t val,
+ unsigned size)
{
struct goldfish_audio_state *s = opaque;
switch(offset) {
case AUDIO_INT_ENABLE:
/* enable buffer empty interrupts */
- D("%s: AUDIO_INT_ENABLE %d", __FUNCTION__, val );
+ trace_goldfish_audio_memory_write("AUDIO_INT_ENABLE", val);
enable_audio(s, val);
s->int_enable = val;
s->int_status = (AUDIO_INT_WRITE_BUFFER_1_EMPTY | AUDIO_INT_WRITE_BUFFER_2_EMPTY);
- goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable));
+ qemu_set_irq(s->irq, s->int_status & s->int_enable);
break;
case AUDIO_SET_WRITE_BUFFER_1:
/* save pointer to buffer 1 */
- D( "%s: AUDIO_SET_WRITE_BUFFER_1 %08x", __FUNCTION__, val);
- goldfish_audio_buff_set_address( s->out_buff1, val );
+ trace_goldfish_audio_memory_write("AUDIO_SET_WRITE_BUFFER_1", val);
+ goldfish_audio_buff_set_address( &s->out_buffs[0], val );
break;
case AUDIO_SET_WRITE_BUFFER_2:
/* save pointer to buffer 2 */
- D( "%s: AUDIO_SET_WRITE_BUFFER_2 %08x", __FUNCTION__, val);
- goldfish_audio_buff_set_address( s->out_buff2, val );
+ trace_goldfish_audio_memory_write("AUDIO_SET_WRITE_BUFFER_2", val);
+ goldfish_audio_buff_set_address( &s->out_buffs[1], val );
break;
case AUDIO_WRITE_BUFFER_1:
/* record that data in buffer 1 is ready to write */
- //D( "%s: AUDIO_WRITE_BUFFER_1 %08x", __FUNCTION__, val);
- if (s->current_buffer == 0) s->current_buffer = 1;
- goldfish_audio_buff_set_length( s->out_buff1, val );
- goldfish_audio_buff_read( s->out_buff1 );
+ trace_goldfish_audio_memory_write("AUDIO_WRITE_BUFFER_1", val);
+ goldfish_audio_write_buffer(s, 0, val);
s->int_status &= ~AUDIO_INT_WRITE_BUFFER_1_EMPTY;
break;
case AUDIO_WRITE_BUFFER_2:
/* record that data in buffer 2 is ready to write */
- //D( "%s: AUDIO_WRITE_BUFFER_2 %08x", __FUNCTION__, val);
- if (s->current_buffer == 0) s->current_buffer = 2;
- goldfish_audio_buff_set_length( s->out_buff2, val );
- goldfish_audio_buff_read( s->out_buff2 );
+ trace_goldfish_audio_memory_write("AUDIO_WRITE_BUFFER_2", val);
+ goldfish_audio_write_buffer(s, 1, val);
s->int_status &= ~AUDIO_INT_WRITE_BUFFER_2_EMPTY;
break;
case AUDIO_SET_READ_BUFFER:
/* save pointer to the read buffer */
- goldfish_audio_buff_set_address( s->in_buff, val );
- D( "%s: AUDIO_SET_READ_BUFFER %08x", __FUNCTION__, val );
+ goldfish_audio_buff_set_address( &s->in_buff, val );
+ trace_goldfish_audio_memory_write("AUDIO_SET_READ_BUFFER", val);
break;
case AUDIO_START_READ:
- D( "%s: AUDIO_START_READ %d", __FUNCTION__, val );
+ trace_goldfish_audio_memory_write("AUDIO_START_READ", val);
start_read(s, val);
s->int_status &= ~AUDIO_INT_READ_BUFFER_FULL;
- goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable));
+ qemu_set_irq(s->irq, s->int_status & s->int_enable);
break;
default:
- cpu_abort (cpu_single_env, "goldfish_audio_write: Bad offset %x\n", offset);
+ error_report ("goldfish_audio_write: Bad offset 0x" TARGET_FMT_plx,
+ offset);
}
}
+static bool goldfish_audio_flush(struct goldfish_audio_state *s, int buf,
+ int *free, uint32_t *new_status)
+{
+ struct goldfish_audio_buff *b = &s->out_buffs[buf];
+ int to_write = audio_MIN(b->length, *free);
+
+ if (!to_write)
+ return false;
+
+ int written = AUD_write(s->voice, b->data + b->offset, to_write);
+ if (!written)
+ return false;
+
+ b->offset += written;
+ b->length -= written;
+ *free -= written;
+ trace_goldfish_audio_buff_send(written, buf + 1);
+
+ if (!goldfish_audio_buff_length(b) == 0)
+ *new_status |= buf ? AUDIO_INT_WRITE_BUFFER_1_EMPTY :
+ AUDIO_INT_WRITE_BUFFER_2_EMPTY;
+
+ return true;
+}
+
static void goldfish_audio_callback(void *opaque, int free)
{
struct goldfish_audio_state *s = opaque;
- int new_status = 0;
-
- /* loop until free is zero or both buffers are empty */
- while (free && s->current_buffer) {
+ uint32_t new_status = 0;
- /* write data in buffer 1 */
- while (free && s->current_buffer == 1) {
- int written = goldfish_audio_buff_send( s->out_buff1, free, s );
- if (written) {
- D("%s: sent %5d bytes to audio output (buffer 1)", __FUNCTION__, written);
- free -= written;
+ if (s->current_buffer != -1) {
+ int8_t i = s->current_buffer;
+ int8_t j = (i + 1) % 2;
- if (goldfish_audio_buff_length( s->out_buff1 ) == 0) {
- new_status |= AUDIO_INT_WRITE_BUFFER_1_EMPTY;
- s->current_buffer = (goldfish_audio_buff_length( s->out_buff2 ) ? 2 : 0);
- }
- } else {
- break;
- }
- }
+ goldfish_audio_flush(s, i, &free, &new_status);
+ goldfish_audio_flush(s, j, &free, &new_status);
- /* write data in buffer 2 */
- while (free && s->current_buffer == 2) {
- int written = goldfish_audio_buff_send( s->out_buff2, free, s );
- if (written) {
- D("%s: sent %5d bytes to audio output (buffer 2)", __FUNCTION__, written);
- free -= written;
-
- if (goldfish_audio_buff_length( s->out_buff2 ) == 0) {
- new_status |= AUDIO_INT_WRITE_BUFFER_2_EMPTY;
- s->current_buffer = (goldfish_audio_buff_length( s->out_buff1 ) ? 1 : 0);
- }
+ if (!goldfish_audio_buff_length(&s->out_buffs[i])) {
+ if (goldfish_audio_buff_length(&s->out_buffs[j])) {
+ s->current_buffer = j;
} else {
- break;
+ s->current_buffer = -1;
}
}
}
+ if (free) /* out of samples, pause playback */
+ AUD_set_active_out(s->voice, 0);
+
if (new_status && new_status != s->int_status) {
s->int_status |= new_status;
- goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable));
+ qemu_set_irq(s->irq, s->int_status & s->int_enable);
}
}
@@ -420,57 +387,45 @@ goldfish_audio_in_callback(void *opaque, int avail)
struct goldfish_audio_state *s = opaque;
int new_status = 0;
- if (goldfish_audio_buff_available( s->in_buff ) == 0 )
+ if (goldfish_audio_buff_available( &s->in_buff ) == 0 )
return;
while (avail > 0) {
- int read = goldfish_audio_buff_recv( s->in_buff, avail, s );
+ int read = goldfish_audio_buff_recv( &s->in_buff, avail, s );
if (read == 0)
break;
avail -= read;
- if (goldfish_audio_buff_available( s->in_buff) == 0) {
+ if (goldfish_audio_buff_available( &s->in_buff) == 0) {
new_status |= AUDIO_INT_READ_BUFFER_FULL;
- D("%s: AUDIO_INT_READ_BUFFER_FULL available=%d",
- __FUNCTION__, goldfish_audio_buff_length( s->in_buff ));
+ trace_goldfish_audio_buff_full(
+ goldfish_audio_buff_length( &s->in_buff ));
break;
}
}
if (new_status && new_status != s->int_status) {
s->int_status |= new_status;
- goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable));
+ qemu_set_irq(s->irq, s->int_status & s->int_enable);
}
}
-static CPUReadMemoryFunc *goldfish_audio_readfn[] = {
- goldfish_audio_read,
- goldfish_audio_read,
- goldfish_audio_read
-};
-
-static CPUWriteMemoryFunc *goldfish_audio_writefn[] = {
- goldfish_audio_write,
- goldfish_audio_write,
- goldfish_audio_write
+static const MemoryRegionOps goldfish_audio_iomem_ops = {
+ .read = goldfish_audio_read,
+ .write = goldfish_audio_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .impl.min_access_size = 4,
+ .impl.max_access_size = 4,
};
-void goldfish_audio_init(uint32_t base, int id, const char* input_source)
+static void goldfish_audio_realize(DeviceState *dev, Error **errp)
{
- struct goldfish_audio_state *s;
+ SysBusDevice *sbdev = SYS_BUS_DEVICE(dev);
+ struct goldfish_audio_state *s = GOLDFISH_AUDIO(dev);
struct audsettings as;
- /* nothing to do if no audio input and output */
- if (!android_hw->hw_audioOutput && !android_hw->hw_audioInput)
- return;
-
- s = (struct goldfish_audio_state *)qemu_mallocz(sizeof(*s));
- s->dev.name = "goldfish_audio";
- s->dev.id = id;
- s->dev.base = base;
- s->dev.size = 0x1000;
- s->dev.irq_count = 1;
+ sysbus_init_irq(sbdev, &s->irq);
AUD_register_card( "goldfish_audio", &s->card);
@@ -479,7 +434,7 @@ void goldfish_audio_init(uint32_t base, int id, const char* input_source)
as.fmt = AUD_FMT_S16;
as.endianness = AUDIO_HOST_ENDIANNESS;
- if (android_hw->hw_audioOutput) {
+ if (s->output) {
s->voice = AUD_open_out (
&s->card,
NULL,
@@ -489,7 +444,7 @@ void goldfish_audio_init(uint32_t base, int id, const char* input_source)
&as
);
if (!s->voice) {
- dprint("warning: opening audio output failed\n");
+ error_setg(errp, "opening audio output failed");
return;
}
}
@@ -499,7 +454,7 @@ void goldfish_audio_init(uint32_t base, int id, const char* input_source)
as.fmt = AUD_FMT_S16;
as.endianness = AUDIO_HOST_ENDIANNESS;
- if (android_hw->hw_audioInput) {
+ if (s->input) {
s->voicein = AUD_open_in (
&s->card,
NULL,
@@ -509,17 +464,44 @@ void goldfish_audio_init(uint32_t base, int id, const char* input_source)
&as
);
if (!s->voicein) {
- dprint("warning: opening audio input failed\n");
+ error_report("warning: opening audio input failed");
}
}
- goldfish_audio_buff_init( s->out_buff1 );
- goldfish_audio_buff_init( s->out_buff2 );
- goldfish_audio_buff_init( s->in_buff );
+ goldfish_audio_buff_init( &s->out_buffs[0] );
+ goldfish_audio_buff_init( &s->out_buffs[1] );
+ goldfish_audio_buff_init( &s->in_buff );
+
+ memory_region_init_io(&s->iomem, OBJECT(s), &goldfish_audio_iomem_ops, s,
+ "goldfish_audio", 0x100);
+ sysbus_init_mmio(sbdev, &s->iomem);
+}
+
+static Property goldfish_audio_properties[] = {
+ DEFINE_PROP_BOOL("input", struct goldfish_audio_state, input, true),
+ DEFINE_PROP_BOOL("output", struct goldfish_audio_state, output, true),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void goldfish_audio_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->realize = goldfish_audio_realize;
+ dc->desc = "goldfish audio";
+ dc->props = goldfish_audio_properties;
+}
- goldfish_device_add(&s->dev, goldfish_audio_readfn, goldfish_audio_writefn, s);
+static const TypeInfo goldfish_audio_info = {
+ .name = TYPE_GOLDFISH_AUDIO,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(struct goldfish_audio_state),
+ .class_init = goldfish_audio_class_init,
+};
- register_savevm( "audio_state", 0, AUDIO_STATE_SAVE_VERSION,
- audio_state_save, audio_state_load, s );
+static void goldfish_audio_register(void)
+{
+ type_register_static(&goldfish_audio_info);
}
+type_init(goldfish_audio_register);
diff --git a/trace-events b/trace-events
index 7d71d230c9..709de68ed5 100644
--- a/trace-events
+++ b/trace-events
@@ -1257,4 +1257,11 @@ pci_cfg_write(const char *dev, unsigned devid, unsigned fnid, unsigned offs, uns
goldfish_fb_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
goldfish_fb_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
goldfish_fb_update_display(int y, int h, int x, int w) "y:%d,h:%d,x=%d,w=%d"
-goldfish_fb_update_stats(float peak, float total) "peak %.2f %% total %.2f %%" \ No newline at end of file
+goldfish_fb_update_stats(float peak, float total) "peak %.2f %% total %.2f %%"
+
+# hw/audio/goldfish_audio.c
+goldfish_audio_memory_read(const char *regname, uint32_t value) "%s returns %d"
+goldfish_audio_memory_write(const char *regname, uint32_t value) "%s %08x"
+goldfish_audio_buff_recv(int size, int read) "AUD_read (%d) returned %d"
+goldfish_audio_buff_send(int size, int buffer) "sent %5d bytes to audio output (buffer %d)"
+goldfish_audio_buff_full(int available) "AUDIO_INT_READ_BUFFER_FULL available=%d"