All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexander Graf <agraf@suse.de>
To: Michael Walle <michael@walle.cc>
Cc: "Edgar E. Iglesias" <edgar.iglesias@gmail.com>, qemu-devel@nongnu.org
Subject: [Qemu-devel] Re: [PATCH 01/14] lm32: add Milkymist AC97 support
Date: Wed, 16 Mar 2011 17:50:30 +0100	[thread overview]
Message-ID: <4D80EA56.6050800@suse.de> (raw)
In-Reply-To: <1299537165-16711-2-git-send-email-michael@walle.cc>

On 03/07/2011 11:32 PM, Michael Walle wrote:
> This patch adds support for the Milkymist AC97 compatible sound output and
> input core.

Malc, could you please take a look at this? :)

> Signed-off-by: Michael Walle<michael@walle.cc>
> ---
>   Makefile.target     |    1 +
>   configure           |    3 +
>   hw/milkymist-ac97.c |  335 +++++++++++++++++++++++++++++++++++++++++++++++++++
>   trace-events        |   12 ++
>   4 files changed, 351 insertions(+), 0 deletions(-)
>   create mode 100644 hw/milkymist-ac97.c
>
> diff --git a/Makefile.target b/Makefile.target
> index f0df98e..3be7868 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -256,6 +256,7 @@ obj-lm32-y += lm32_juart.o
>   obj-lm32-y += lm32_timer.o
>   obj-lm32-y += lm32_uart.o
>   obj-lm32-y += lm32_sys.o
> +obj-lm32-y += milkymist-ac97.o
>
>   obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
>   obj-mips-y += mips_addr.o mips_timer.o mips_int.o
> diff --git a/configure b/configure
> index 5513d3e..e75e1a2 100755
> --- a/configure
> +++ b/configure
> @@ -3281,6 +3281,9 @@ if test "$target_softmmu" = "yes" ; then
>     arm)
>       cflags="-DHAS_AUDIO $cflags"
>     ;;
> +  lm32)
> +    cflags="-DHAS_AUDIO $cflags"
> +  ;;
>     i386|mips|ppc)
>       cflags="-DHAS_AUDIO -DHAS_AUDIO_CHOICE $cflags"
>     ;;
> diff --git a/hw/milkymist-ac97.c b/hw/milkymist-ac97.c
> new file mode 100644
> index 0000000..6c9e318
> --- /dev/null
> +++ b/hw/milkymist-ac97.c
> @@ -0,0 +1,335 @@
> +/*
> + *  QEMU model of the Milkymist System Controller.
> + *
> + *  Copyright (c) 2010 Michael Walle<michael@walle.cc>
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see<http://www.gnu.org/licenses/>.
> + *
> + *
> + * Specification available at:
> + *   http://www.milkymist.org/socdoc/ac97.pdf
> + */
> +
> +#include "hw.h"
> +#include "sysbus.h"
> +#include "trace.h"
> +#include "audio/audio.h"
> +#include "qemu-error.h"
> +
> +enum {
> +    R_AC97_CTRL = 0,
> +    R_AC97_ADDR,
> +    R_AC97_DATAOUT,
> +    R_AC97_DATAIN,
> +    R_D_CTRL,
> +    R_D_ADDR,
> +    R_D_REMAINING,
> +    R_RESERVED,
> +    R_U_CTRL,
> +    R_U_ADDR,
> +    R_U_REMAINING,
> +    R_MAX
> +};
> +
> +enum {
> +    AC97_CTRL_RQEN  = (1<<0),
> +    AC97_CTRL_WRITE = (1<<1),
> +};
> +
> +enum {
> +    CTRL_EN = (1<<0),
> +};
> +
> +struct MilkymistAC97State {
> +    SysBusDevice busdev;
> +
> +    QEMUSoundCard card;
> +    SWVoiceIn *voice_in;
> +    SWVoiceOut *voice_out;
> +
> +    uint32_t regs[R_MAX];
> +
> +    qemu_irq crrequest_irq;
> +    qemu_irq crreply_irq;
> +    qemu_irq dmar_irq;
> +    qemu_irq dmaw_irq;
> +};
> +typedef struct MilkymistAC97State MilkymistAC97State;
> +
> +static void update_voices(MilkymistAC97State *s)
> +{
> +    if (s->regs[R_D_CTRL]&  CTRL_EN) {
> +        AUD_set_active_out(s->voice_out, 1);
> +    } else {
> +        AUD_set_active_out(s->voice_out, 0);
> +    }
> +
> +    if (s->regs[R_U_CTRL]&  CTRL_EN) {
> +        AUD_set_active_in(s->voice_in, 1);
> +    } else {
> +        AUD_set_active_in(s->voice_in, 0);
> +    }
> +}
> +
> +static uint32_t ac97_read(void *opaque, target_phys_addr_t addr)
> +{
> +    MilkymistAC97State *s = opaque;
> +    uint32_t r = 0;
> +
> +    addr>>= 2;
> +    switch (addr) {
> +    case R_AC97_CTRL:
> +    case R_AC97_ADDR:
> +    case R_AC97_DATAOUT:
> +    case R_AC97_DATAIN:
> +    case R_D_CTRL:
> +    case R_D_ADDR:
> +    case R_D_REMAINING:
> +    case R_U_CTRL:
> +    case R_U_ADDR:
> +    case R_U_REMAINING:
> +        r = s->regs[addr];
> +        break;
> +
> +    default:
> +        error_report("milkymist_ac97: read access to unkown register 0x"
> +                TARGET_FMT_plx, addr<<  2);
> +        break;
> +    }
> +
> +    trace_milkymist_ac97_memory_read(addr<<  2, r);
> +
> +    return r;
> +}
> +
> +static void ac97_write(void *opaque, target_phys_addr_t addr, uint32_t value)
> +{
> +    MilkymistAC97State *s = opaque;
> +
> +    trace_milkymist_ac97_memory_write(addr, value);
> +
> +    addr>>= 2;
> +    switch (addr) {
> +    case R_AC97_CTRL:
> +        /* always raise an IRQ according to the direction */
> +        if (value&  AC97_CTRL_RQEN) {
> +            if (value&  AC97_CTRL_WRITE) {
> +                trace_milkymist_ac97_pulse_irq_crrequest();
> +                qemu_irq_pulse(s->crrequest_irq);
> +            } else {
> +                trace_milkymist_ac97_pulse_irq_crreply();
> +                qemu_irq_pulse(s->crreply_irq);
> +            }
> +        }
> +
> +        /* RQEN is self clearing */
> +        s->regs[addr] = value&  ~AC97_CTRL_RQEN;
> +        break;
> +    case R_D_CTRL:
> +    case R_U_CTRL:
> +        s->regs[addr] = value;
> +        update_voices(s);
> +        break;
> +    case R_AC97_ADDR:
> +    case R_AC97_DATAOUT:
> +    case R_AC97_DATAIN:
> +    case R_D_ADDR:
> +    case R_D_REMAINING:
> +    case R_U_ADDR:
> +    case R_U_REMAINING:
> +        s->regs[addr] = value;
> +        break;
> +
> +    default:
> +        error_report("milkymist_ac97: write access to unkown register 0x"
> +                TARGET_FMT_plx, addr);
> +        break;
> +    }
> +
> +}
> +
> +static CPUReadMemoryFunc * const ac97_read_fn[] = {
> +    NULL,
> +    NULL,
> +&ac97_read,
> +};
> +
> +static CPUWriteMemoryFunc * const ac97_write_fn[] = {
> +    NULL,
> +    NULL,
> +&ac97_write,
> +};
> +
> +static void ac97_in_cb(void *opaque, int avail_b)
> +{
> +    MilkymistAC97State *s = opaque;
> +    uint8_t buf[4096];
> +    uint32_t remaining = s->regs[R_U_REMAINING];
> +    int temp = audio_MIN(remaining, avail_b);
> +    uint32_t addr = s->regs[R_U_ADDR];
> +    int transferred = 0;
> +
> +    trace_milkymist_ac97_in_cb(avail_b, remaining);
> +
> +    /* prevent from raising an IRQ */
> +    if (temp == 0) {
> +        return;
> +    }
> +
> +    while (temp) {
> +        int acquired, to_copy;
> +
> +        to_copy = audio_MIN(temp, sizeof(buf));
> +        acquired = AUD_read(s->voice_in, buf, to_copy);
> +        if (!acquired) {
> +            break;
> +        }
> +
> +        cpu_physical_memory_write(addr, buf, acquired);
> +
> +        temp -= acquired;
> +        addr += acquired;
> +        transferred += acquired;
> +    }
> +
> +    trace_milkymist_ac97_in_cb_transferred(transferred);
> +
> +    s->regs[R_U_ADDR] = addr;
> +    s->regs[R_U_REMAINING] -= transferred;
> +
> +    if ((s->regs[R_U_CTRL]&  CTRL_EN)&&  (s->regs[R_U_REMAINING] == 0)) {
> +        trace_milkymist_ac97_pulse_irq_dmaw();
> +        qemu_irq_pulse(s->dmaw_irq);
> +    }
> +}
> +
> +static void ac97_out_cb(void *opaque, int free_b)
> +{
> +    MilkymistAC97State *s = opaque;
> +    uint8_t buf[4096];
> +    uint32_t remaining = s->regs[R_D_REMAINING];
> +    int temp = audio_MIN(remaining, free_b);
> +    uint32_t addr = s->regs[R_D_ADDR];
> +    int transferred = 0;
> +
> +    trace_milkymist_ac97_out_cb(free_b, remaining);
> +
> +    /* prevent from raising an IRQ */
> +    if (temp == 0) {
> +        return;
> +    }
> +
> +    while (temp) {
> +        int copied, to_copy;
> +
> +        to_copy = audio_MIN(temp, sizeof(buf));
> +        cpu_physical_memory_read(addr, buf, to_copy);
> +        copied = AUD_write(s->voice_out, buf, to_copy);
> +        if (!copied) {
> +            break;
> +        }
> +        temp -= copied;
> +        addr += copied;
> +        transferred += copied;
> +    }
> +
> +    trace_milkymist_ac97_out_cb_transferred(transferred);
> +
> +    s->regs[R_D_ADDR] = addr;
> +    s->regs[R_D_REMAINING] -= transferred;
> +
> +    if ((s->regs[R_D_CTRL]&  CTRL_EN)&&  (s->regs[R_D_REMAINING] == 0)) {
> +        trace_milkymist_ac97_pulse_irq_dmar();
> +        qemu_irq_pulse(s->dmar_irq);
> +    }
> +}
> +
> +static void milkymist_ac97_reset(DeviceState *d)
> +{
> +    MilkymistAC97State *s = container_of(d, MilkymistAC97State, busdev.qdev);
> +    int i;
> +
> +    for (i = 0; i<  R_MAX; i++) {
> +        s->regs[i] = 0;
> +    }
> +
> +    AUD_set_active_in(s->voice_in, 0);
> +    AUD_set_active_out(s->voice_out, 0);
> +}
> +
> +static int ac97_post_load(void *opaque, int version_id)
> +{
> +    MilkymistAC97State *s = opaque;
> +
> +    update_voices(s);
> +
> +    return 0;
> +}
> +
> +static int milkymist_ac97_init(SysBusDevice *dev)
> +{
> +    MilkymistAC97State *s = FROM_SYSBUS(typeof(*s), dev);
> +    int ac97_regs;
> +
> +    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);
> +
> +    ac97_regs = cpu_register_io_memory(ac97_read_fn, ac97_write_fn, s,
> +            DEVICE_NATIVE_ENDIAN);
> +    sysbus_init_mmio(dev, R_MAX * 4, ac97_regs);
> +
> +    return 0;
> +}
> +
> +static const VMStateDescription vmstate_milkymist_ac97 = {
> +    .name = "milkymist-ac97",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .minimum_version_id_old = 1,
> +    .post_load = ac97_post_load,
> +    .fields      = (VMStateField[]) {
> +        VMSTATE_UINT32_ARRAY(regs, MilkymistAC97State, R_MAX),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static SysBusDeviceInfo milkymist_ac97_info = {
> +    .init = milkymist_ac97_init,
> +    .qdev.name  = "milkymist-ac97",
> +    .qdev.size  = sizeof(MilkymistAC97State),
> +    .qdev.vmsd  =&vmstate_milkymist_ac97,
> +    .qdev.reset = milkymist_ac97_reset,
> +};
> +
> +static void milkymist_ac97_register(void)
> +{
> +    sysbus_register_withprop(&milkymist_ac97_info);
> +}
> +
> +device_init(milkymist_ac97_register)
> diff --git a/trace-events b/trace-events
> index c791719..9241ac9 100644
> --- a/trace-events
> +++ b/trace-events
> @@ -283,3 +283,15 @@ disable lm32_uart_irq_state(int level) "irq state %d"
>
>   # hw/lm32_sys.c
>   disable lm32_sys_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
> +
> +# hw/milkymist-ac97.c
> +disable milkymist_ac97_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x"
> +disable milkymist_ac97_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x"
> +disable milkymist_ac97_pulse_irq_crrequest(void) "Pulse IRQ CR request"
> +disable milkymist_ac97_pulse_irq_crreply(void) "Pulse IRQ CR reply"
> +disable milkymist_ac97_pulse_irq_dmaw(void) "Pulse IRQ DMA write"
> +disable milkymist_ac97_pulse_irq_dmar(void) "Pulse IRQ DMA read"
> +disable milkymist_ac97_in_cb(int avail, uint32_t remaining) "avail %d remaining %u"
> +disable milkymist_ac97_in_cb_transferred(int transferred) "transferred %d"
> +disable milkymist_ac97_out_cb(int free, uint32_t remaining) "free %d remaining %u"
> +disable milkymist_ac97_out_cb_transferred(int transferred) "transferred %d"

  reply	other threads:[~2011-03-16 16:58 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-03-07 22:32 [Qemu-devel] [PATCH 00/14] lm32: Milkymist board support Michael Walle
2011-03-07 22:32 ` [Qemu-devel] [PATCH 01/14] lm32: add Milkymist AC97 support Michael Walle
2011-03-16 16:50   ` Alexander Graf [this message]
2011-03-16 18:12     ` [Qemu-devel] " malc
2011-03-16 23:02       ` Michael Walle
2011-03-16 23:49         ` Alexander Graf
2011-03-17  0:10         ` malc
2011-03-07 22:32 ` [Qemu-devel] [PATCH 02/14] lm32: add Milkymist HPDMC support Michael Walle
2011-03-07 22:32 ` [Qemu-devel] [PATCH 03/14] lm32: add Milkymist memory card support Michael Walle
2011-03-07 22:32 ` [Qemu-devel] [PATCH 04/14] lm32: add Milkymist Minimac support Michael Walle
2011-03-07 22:32 ` [Qemu-devel] [PATCH 05/14] lm32: add Milkymist PFPU support Michael Walle
2011-03-07 22:32 ` [Qemu-devel] [PATCH 06/14] lm32: add Milkymist SoftUSB support Michael Walle
2011-03-07 22:32 ` [Qemu-devel] [PATCH 07/14] lm32: add Milkymist System Controller support Michael Walle
2011-03-07 22:32 ` [Qemu-devel] [PATCH 08/14] configure: add opengl detection Michael Walle
2011-03-07 22:32 ` [Qemu-devel] [PATCH 09/14] lm32: add Milkymist TMU2 support Michael Walle
2011-03-07 22:32 ` [Qemu-devel] [PATCH 10/14] lm32: add Milkymist UART support Michael Walle
2011-03-07 22:32 ` [Qemu-devel] [PATCH 11/14] lm32: add Milkymist VGAFB support Michael Walle
2011-03-07 22:32 ` [Qemu-devel] [PATCH 12/14] lm32: add milkymist hw support functions Michael Walle
2011-03-07 22:32 ` [Qemu-devel] [PATCH 13/14] lm32: add support for the Milkymist board Michael Walle
2011-03-07 22:32 ` [Qemu-devel] [PATCH 14/14] MAINTAINERS: add " Michael Walle
2011-03-16 17:08 ` [Qemu-devel] Re: [PATCH 00/14] lm32: Milkymist board support Alexander Graf
2011-03-24  9:28   ` Alexander Graf
2011-04-04  8:46     ` Edgar E. Iglesias

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4D80EA56.6050800@suse.de \
    --to=agraf@suse.de \
    --cc=edgar.iglesias@gmail.com \
    --cc=michael@walle.cc \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.