Beispiel #1
0
static int milkymist_ac97_init(SysBusDevice *dev)
{
    MilkymistAC97State *s = FROM_SYSBUS(typeof(*s), dev);

    struct audsettings as;
    sysbus_init_irq(dev, &s->crrequest_irq);
    sysbus_init_irq(dev, &s->crreply_irq);
    sysbus_init_irq(dev, &s->dmar_irq);
    sysbus_init_irq(dev, &s->dmaw_irq);

    AUD_register_card("Milkymist AC'97", &s->card);

    as.freq = 48000;
    as.nchannels = 2;
    as.fmt = AUD_FMT_S16;
    as.endianness = 1;

    s->voice_in = AUD_open_in(&s->card, s->voice_in,
            "mm_ac97.in", s, ac97_in_cb, &as);
    s->voice_out = AUD_open_out(&s->card, s->voice_out,
            "mm_ac97.out", s, ac97_out_cb, &as);

    memory_region_init_io(&s->regs_region, &ac97_mmio_ops, s,
            "milkymist-ac97", R_MAX * 4);
    sysbus_init_mmio(dev, &s->regs_region);

    return 0;
}
static int virtio_audio_load(QEMUFile *f, void *opaque, int version_id)
{
    VirtIOAudio *s = opaque;
    VirtIOAudioStream *stream;
    int i;
    int mode;

    if (version_id != 1)
        return -EINVAL;

    /* FIXME: Do bad things happen if there is a transfer in progress?  */

    virtio_load(&s->vdev, f);

    for (i = 0; i < NUM_STREAMS; i++) {
        stream = &s->stream[i];

        stream->has_buffer = 0;
        stream->data_left = 0;
        if (stream->in_voice) {
            AUD_close_in(&s->card, stream->in_voice);
            stream->in_voice = NULL;
        }
        if (stream->out_voice) {
            AUD_close_out(&s->card, stream->out_voice);
            stream->out_voice = NULL;
        }
        mode = qemu_get_byte(f);
        stream->fmt.endianness = qemu_get_byte(f);
        stream->fmt.nchannels = qemu_get_be16(f);
        stream->fmt.fmt = qemu_get_be32(f);
        stream->fmt.freq = qemu_get_be32(f);
        if (mode & 2) {
            stream->in_voice = AUD_open_in(&s->card, stream->in_voice,
                                           "virtio-audio.in",
                                           stream,
                                           virtio_audio_callback,
                                           &stream->fmt);
            AUD_set_active_in(stream->in_voice, mode & 1);
        } else if (mode & 4) {
            stream->out_voice = AUD_open_out(&s->card, stream->out_voice,
                                             "virtio-audio.out",
                                             stream,
                                             virtio_audio_callback,
                                             &stream->fmt);
            AUD_set_active_out(stream->out_voice, mode & 1);
        }
    }

    return 0;
}
Beispiel #3
0
static void milkymist_ac97_realize(DeviceState *dev, Error **errp)
{
    MilkymistAC97State *s = MILKYMIST_AC97(dev);
    struct audsettings as;

    AUD_register_card("Milkymist AC'97", &s->card);

    as.freq = 48000;
    as.nchannels = 2;
    as.fmt = AUD_FMT_S16;
    as.endianness = 1;

    s->voice_in = AUD_open_in(&s->card, s->voice_in,
            "mm_ac97.in", s, ac97_in_cb, &as);
    s->voice_out = AUD_open_out(&s->card, s->voice_out,
            "mm_ac97.out", s, ac97_out_cb, &as);
}
Beispiel #4
0
static void hda_audio_setup(HDAAudioStream *st)
{
    if (st->node == NULL) {
        return;
    }

    dprint(st->state, 1, "%s: format: %d x %s @ %d Hz\n",
           st->node->name, st->as.nchannels,
           fmt2name[st->as.fmt], st->as.freq);

    if (st->output) {
        st->voice.out = AUD_open_out(&st->state->card, st->voice.out,
                                     st->node->name, st,
                                     hda_audio_output_cb, &st->as);
    } else {
        st->voice.in = AUD_open_in(&st->state->card, st->voice.in,
                                   st->node->name, st,
                                   hda_audio_input_cb, &st->as);
    }
}
/* Command queue.  */
static void virtio_audio_handle_cmd(VirtIODevice *vdev, VirtQueue *vq)
{
    VirtIOAudio *s = to_virtio_audio(vdev);
    VirtIOAudioStream *stream;
    VirtQueueElement elem;
    int out_n;
    uint32_t *p;
    int len;
    size_t out_bytes;
    uint32_t value;

    while (virtqueue_pop(s->cmd_vq, &elem)) {
        size_t bytes_transferred = 0;
        for (out_n = 0; out_n < elem.out_num; out_n++) {
            p = (uint32_t *)elem.out_sg[out_n].iov_base;
            len = elem.out_sg[out_n].iov_len;
            while (len > 0) {
                if (len < 12) {
                    BADF("Bad command length\n");
                    break;
                }
                DPRINTF("Command %d %d %d\n",
                        ldl_p(p), ldl_p(p + 1), ldl_p (p + 2));
                value = ldl_p(p + 1);
                if (value >= NUM_STREAMS)
                    break;
                stream = &s->stream[value];
                value = ldl_p(p + 2);
                switch (ldl_p(p)) {
                case VIRTIO_AUDIO_CMD_SET_ENDIAN:
                    stream->fmt.endianness = value;
                    break;
                case VIRTIO_AUDIO_CMD_SET_CHANNELS:
                    stream->fmt.nchannels = value;
                    break;
                case VIRTIO_AUDIO_CMD_SET_FMT:
                    stream->fmt.fmt = value;
                    break;
                case VIRTIO_AUDIO_CMD_SET_FREQ:
                    stream->fmt.freq = value;
                    break;
                case VIRTIO_AUDIO_CMD_INIT:
                    out_bytes = 0;
                    if (value == 1) {
                        if (stream->out_voice) {
                            AUD_close_out(&s->card, stream->out_voice);
                            stream->out_voice = NULL;
                        }
                        stream->in_voice =
                          AUD_open_in(&s->card, stream->in_voice,
                                      "virtio-audio.in",
                                      stream,
                                      virtio_audio_callback,
                                      &stream->fmt);
                        virtio_audio_cmd_result(0, &elem, &out_bytes);
                    } else if (value == 0) {
                        if (stream->in_voice) {
                            AUD_close_in(&s->card, stream->in_voice);
                            stream->in_voice = NULL;
                        }
                        stream->out_voice =
                          AUD_open_out(&s->card, stream->out_voice,
                                       "virtio-audio.out",
                                       stream,
                                       virtio_audio_callback,
                                       &stream->fmt);
                        value = AUD_get_buffer_size_out(stream->out_voice);
                        virtio_audio_cmd_result(value, &elem, &out_bytes);
                    } else { // let us close all down
                        if (stream->out_voice) {
                            AUD_close_out(&s->card, stream->out_voice);
                            stream->out_voice = NULL;
                        }
                        if (stream->in_voice) {
                            AUD_close_in(&s->card, stream->in_voice);
                            stream->in_voice = NULL;
                        }                        
                    }
                    bytes_transferred += out_bytes;
                    break;
                case VIRTIO_AUDIO_CMD_RUN:
                    if (stream->in_voice) {
                        AUD_set_active_in(stream->in_voice, value);
                    } else if (stream->out_voice) {
                        AUD_set_active_out(stream->out_voice, value);
                    } else
                    {
                        DPRINTF("Cannot execute CMD_RUN as no voice is active\n");
                    }
                    break;
                }
                p += 3;
                len -= 12;
                bytes_transferred += 12;
            }
        }
        virtqueue_push(s->cmd_vq, &elem, bytes_transferred);
        virtio_notify(vdev, s->cmd_vq);		
    }
}