#include "qemu/osdep.h"
#include "hw/audio/soundhw.h"
#include "audio/audio.h"
-#include "hw/pci/pci.h"
+#include "hw/pci/pci_device.h"
#include "hw/qdev-properties.h"
#include "migration/vmstate.h"
#include "qemu/module.h"
#include "sysemu/dma.h"
#include "qom/object.h"
-
-enum {
- AC97_Reset = 0x00,
- AC97_Master_Volume_Mute = 0x02,
- AC97_Headphone_Volume_Mute = 0x04,
- AC97_Master_Volume_Mono_Mute = 0x06,
- AC97_Master_Tone_RL = 0x08,
- AC97_PC_BEEP_Volume_Mute = 0x0A,
- AC97_Phone_Volume_Mute = 0x0C,
- AC97_Mic_Volume_Mute = 0x0E,
- AC97_Line_In_Volume_Mute = 0x10,
- AC97_CD_Volume_Mute = 0x12,
- AC97_Video_Volume_Mute = 0x14,
- AC97_Aux_Volume_Mute = 0x16,
- AC97_PCM_Out_Volume_Mute = 0x18,
- AC97_Record_Select = 0x1A,
- AC97_Record_Gain_Mute = 0x1C,
- AC97_Record_Gain_Mic_Mute = 0x1E,
- AC97_General_Purpose = 0x20,
- AC97_3D_Control = 0x22,
- AC97_AC_97_RESERVED = 0x24,
- AC97_Powerdown_Ctrl_Stat = 0x26,
- AC97_Extended_Audio_ID = 0x28,
- AC97_Extended_Audio_Ctrl_Stat = 0x2A,
- AC97_PCM_Front_DAC_Rate = 0x2C,
- AC97_PCM_Surround_DAC_Rate = 0x2E,
- AC97_PCM_LFE_DAC_Rate = 0x30,
- AC97_PCM_LR_ADC_Rate = 0x32,
- AC97_MIC_ADC_Rate = 0x34,
- AC97_6Ch_Vol_C_LFE_Mute = 0x36,
- AC97_6Ch_Vol_L_R_Surround_Mute = 0x38,
- AC97_Vendor_Reserved = 0x58,
- AC97_Sigmatel_Analog = 0x6c, /* We emulate a Sigmatel codec */
- AC97_Sigmatel_Dac2Invert = 0x6e, /* We emulate a Sigmatel codec */
- AC97_Vendor_ID1 = 0x7c,
- AC97_Vendor_ID2 = 0x7e
-};
+#include "ac97.h"
#define SOFT_VOLUME
#define SR_FIFOE 16 /* rwc */
#define BD_IOC (1 << 31)
#define BD_BUP (1 << 30)
-#define EACS_VRA 1
-#define EACS_VRM 8
-
-#define MUTE_SHIFT 15
-
#define TYPE_AC97 "AC97"
OBJECT_DECLARE_SIMPLE_TYPE(AC97LinkState, AC97)
static void pi_callback(void *opaque, int avail);
static void mc_callback(void *opaque, int avail);
-static void warm_reset(AC97LinkState *s)
-{
- (void)s;
-}
-
-static void cold_reset(AC97LinkState *s)
-{
- (void)s;
-}
-
static void fetch_bd(AC97LinkState *s, AC97BusMasterRegs *r)
{
uint8_t b[8];
static uint32_t nam_readw(void *opaque, uint32_t addr)
{
AC97LinkState *s = opaque;
- uint32_t index = addr;
s->cas = 0;
- return mixer_load(s, index);
+ return mixer_load(s, addr);
}
static uint32_t nam_readl(void *opaque, uint32_t addr)
static void nam_writew(void *opaque, uint32_t addr, uint32_t val)
{
AC97LinkState *s = opaque;
- uint32_t index = addr;
+
s->cas = 0;
- switch (index) {
+ switch (addr) {
case AC97_Reset:
mixer_reset(s);
break;
case AC97_Powerdown_Ctrl_Stat:
val &= ~0x800f;
- val |= mixer_load(s, index) & 0xf;
- mixer_store(s, index, val);
+ val |= mixer_load(s, addr) & 0xf;
+ mixer_store(s, addr, val);
break;
case AC97_PCM_Out_Volume_Mute:
case AC97_Master_Volume_Mute:
case AC97_Record_Gain_Mute:
- set_volume(s, index, val);
+ set_volume(s, addr, val);
break;
case AC97_Record_Select:
record_select(s, val);
break;
case AC97_PCM_Front_DAC_Rate:
if (mixer_load(s, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRA) {
- mixer_store(s, index, val);
+ mixer_store(s, addr, val);
dolog("Set front DAC rate to %d\n", val);
open_voice(s, PO_INDEX, val);
} else {
break;
case AC97_MIC_ADC_Rate:
if (mixer_load(s, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRM) {
- mixer_store(s, index, val);
+ mixer_store(s, addr, val);
dolog("Set MIC ADC rate to %d\n", val);
open_voice(s, MC_INDEX, val);
} else {
break;
case AC97_PCM_LR_ADC_Rate:
if (mixer_load(s, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRA) {
- mixer_store(s, index, val);
+ mixer_store(s, addr, val);
dolog("Set front LR ADC rate to %d\n", val);
open_voice(s, PI_INDEX, val);
} else {
break;
default:
dolog("U nam writew 0x%x <- 0x%x\n", addr, val);
- mixer_store(s, index, val);
+ mixer_store(s, addr, val);
break;
}
}
{
AC97LinkState *s = opaque;
AC97BusMasterRegs *r = NULL;
- uint32_t index = addr;
uint32_t val = ~0U;
- switch (index) {
+ switch (addr) {
case CAS:
dolog("CAS %d\n", s->cas);
val = s->cas;
case PI_CIV:
case PO_CIV:
case MC_CIV:
- r = &s->bm_regs[GET_BM(index)];
+ r = &s->bm_regs[GET_BM(addr)];
val = r->civ;
- dolog("CIV[%d] -> 0x%x\n", GET_BM(index), val);
+ dolog("CIV[%d] -> 0x%x\n", GET_BM(addr), val);
break;
case PI_LVI:
case PO_LVI:
case MC_LVI:
- r = &s->bm_regs[GET_BM(index)];
+ r = &s->bm_regs[GET_BM(addr)];
val = r->lvi;
- dolog("LVI[%d] -> 0x%x\n", GET_BM(index), val);
+ dolog("LVI[%d] -> 0x%x\n", GET_BM(addr), val);
break;
case PI_PIV:
case PO_PIV:
case MC_PIV:
- r = &s->bm_regs[GET_BM(index)];
+ r = &s->bm_regs[GET_BM(addr)];
val = r->piv;
- dolog("PIV[%d] -> 0x%x\n", GET_BM(index), val);
+ dolog("PIV[%d] -> 0x%x\n", GET_BM(addr), val);
break;
case PI_CR:
case PO_CR:
case MC_CR:
- r = &s->bm_regs[GET_BM(index)];
+ r = &s->bm_regs[GET_BM(addr)];
val = r->cr;
- dolog("CR[%d] -> 0x%x\n", GET_BM(index), val);
+ dolog("CR[%d] -> 0x%x\n", GET_BM(addr), val);
break;
case PI_SR:
case PO_SR:
case MC_SR:
- r = &s->bm_regs[GET_BM(index)];
+ r = &s->bm_regs[GET_BM(addr)];
val = r->sr & 0xff;
- dolog("SRb[%d] -> 0x%x\n", GET_BM(index), val);
+ dolog("SRb[%d] -> 0x%x\n", GET_BM(addr), val);
break;
default:
dolog("U nabm readb 0x%x -> 0x%x\n", addr, val);
{
AC97LinkState *s = opaque;
AC97BusMasterRegs *r = NULL;
- uint32_t index = addr;
uint32_t val = ~0U;
- switch (index) {
+ switch (addr) {
case PI_SR:
case PO_SR:
case MC_SR:
- r = &s->bm_regs[GET_BM(index)];
+ r = &s->bm_regs[GET_BM(addr)];
val = r->sr;
- dolog("SR[%d] -> 0x%x\n", GET_BM(index), val);
+ dolog("SR[%d] -> 0x%x\n", GET_BM(addr), val);
break;
case PI_PICB:
case PO_PICB:
case MC_PICB:
- r = &s->bm_regs[GET_BM(index)];
+ r = &s->bm_regs[GET_BM(addr)];
val = r->picb;
- dolog("PICB[%d] -> 0x%x\n", GET_BM(index), val);
+ dolog("PICB[%d] -> 0x%x\n", GET_BM(addr), val);
break;
default:
dolog("U nabm readw 0x%x -> 0x%x\n", addr, val);
{
AC97LinkState *s = opaque;
AC97BusMasterRegs *r = NULL;
- uint32_t index = addr;
uint32_t val = ~0U;
- switch (index) {
+ switch (addr) {
case PI_BDBAR:
case PO_BDBAR:
case MC_BDBAR:
- r = &s->bm_regs[GET_BM(index)];
+ r = &s->bm_regs[GET_BM(addr)];
val = r->bdbar;
- dolog("BMADDR[%d] -> 0x%x\n", GET_BM(index), val);
+ dolog("BMADDR[%d] -> 0x%x\n", GET_BM(addr), val);
break;
case PI_CIV:
case PO_CIV:
case MC_CIV:
- r = &s->bm_regs[GET_BM(index)];
+ r = &s->bm_regs[GET_BM(addr)];
val = r->civ | (r->lvi << 8) | (r->sr << 16);
- dolog("CIV LVI SR[%d] -> 0x%x, 0x%x, 0x%x\n", GET_BM(index),
+ dolog("CIV LVI SR[%d] -> 0x%x, 0x%x, 0x%x\n", GET_BM(addr),
r->civ, r->lvi, r->sr);
break;
case PI_PICB:
case PO_PICB:
case MC_PICB:
- r = &s->bm_regs[GET_BM(index)];
+ r = &s->bm_regs[GET_BM(addr)];
val = r->picb | (r->piv << 16) | (r->cr << 24);
- dolog("PICB PIV CR[%d] -> 0x%x 0x%x 0x%x 0x%x\n", GET_BM(index),
+ dolog("PICB PIV CR[%d] -> 0x%x 0x%x 0x%x 0x%x\n", GET_BM(addr),
val, r->picb, r->piv, r->cr);
break;
case GLOB_CNT:
{
AC97LinkState *s = opaque;
AC97BusMasterRegs *r = NULL;
- uint32_t index = addr;
- switch (index) {
+
+ switch (addr) {
case PI_LVI:
case PO_LVI:
case MC_LVI:
- r = &s->bm_regs[GET_BM(index)];
+ r = &s->bm_regs[GET_BM(addr)];
if ((r->cr & CR_RPBM) && (r->sr & SR_DCH)) {
r->sr &= ~(SR_DCH | SR_CELV);
r->civ = r->piv;
fetch_bd(s, r);
}
r->lvi = val % 32;
- dolog("LVI[%d] <- 0x%x\n", GET_BM(index), val);
+ dolog("LVI[%d] <- 0x%x\n", GET_BM(addr), val);
break;
case PI_CR:
case PO_CR:
case MC_CR:
- r = &s->bm_regs[GET_BM(index)];
+ r = &s->bm_regs[GET_BM(addr)];
if (val & CR_RR) {
reset_bm_regs(s, r);
} else {
voice_set_active(s, r - s->bm_regs, 1);
}
}
- dolog("CR[%d] <- 0x%x (cr 0x%x)\n", GET_BM(index), val, r->cr);
+ dolog("CR[%d] <- 0x%x (cr 0x%x)\n", GET_BM(addr), val, r->cr);
break;
case PI_SR:
case PO_SR:
case MC_SR:
- r = &s->bm_regs[GET_BM(index)];
+ r = &s->bm_regs[GET_BM(addr)];
r->sr |= val & ~(SR_RO_MASK | SR_WCLEAR_MASK);
update_sr(s, r, r->sr & ~(val & SR_WCLEAR_MASK));
- dolog("SR[%d] <- 0x%x (sr 0x%x)\n", GET_BM(index), val, r->sr);
+ dolog("SR[%d] <- 0x%x (sr 0x%x)\n", GET_BM(addr), val, r->sr);
break;
default:
dolog("U nabm writeb 0x%x <- 0x%x\n", addr, val);
{
AC97LinkState *s = opaque;
AC97BusMasterRegs *r = NULL;
- uint32_t index = addr;
- switch (index) {
+
+ switch (addr) {
case PI_SR:
case PO_SR:
case MC_SR:
- r = &s->bm_regs[GET_BM(index)];
+ r = &s->bm_regs[GET_BM(addr)];
r->sr |= val & ~(SR_RO_MASK | SR_WCLEAR_MASK);
update_sr(s, r, r->sr & ~(val & SR_WCLEAR_MASK));
- dolog("SR[%d] <- 0x%x (sr 0x%x)\n", GET_BM(index), val, r->sr);
+ dolog("SR[%d] <- 0x%x (sr 0x%x)\n", GET_BM(addr), val, r->sr);
break;
default:
dolog("U nabm writew 0x%x <- 0x%x\n", addr, val);
{
AC97LinkState *s = opaque;
AC97BusMasterRegs *r = NULL;
- uint32_t index = addr;
- switch (index) {
+
+ switch (addr) {
case PI_BDBAR:
case PO_BDBAR:
case MC_BDBAR:
- r = &s->bm_regs[GET_BM(index)];
+ r = &s->bm_regs[GET_BM(addr)];
r->bdbar = val & ~3;
- dolog("BDBAR[%d] <- 0x%x (bdbar 0x%x)\n", GET_BM(index), val, r->bdbar);
+ dolog("BDBAR[%d] <- 0x%x (bdbar 0x%x)\n", GET_BM(addr), val, r->bdbar);
break;
case GLOB_CNT:
- if (val & GC_WR) {
- warm_reset(s);
- }
- if (val & GC_CR) {
- cold_reset(s);
- }
+ /* TODO: Handle WR or CR being set (warm/cold reset requests) */
if (!(val & (GC_WR | GC_CR))) {
s->glob_cnt = val & GC_VALID_MASK;
}
.name = "ac97_bm_regs",
.version_id = 1,
.minimum_version_id = 1,
- .fields = (VMStateField[]) {
+ .fields = (const VMStateField[]) {
VMSTATE_UINT32(bdbar, AC97BusMasterRegs),
VMSTATE_UINT8(civ, AC97BusMasterRegs),
VMSTATE_UINT8(lvi, AC97BusMasterRegs),
.version_id = 3,
.minimum_version_id = 2,
.post_load = ac97_post_load,
- .fields = (VMStateField[]) {
+ .fields = (const VMStateField[]) {
VMSTATE_PCI_DEVICE(dev, AC97LinkState),
VMSTATE_UINT32(glob_cnt, AC97LinkState),
VMSTATE_UINT32(glob_sta, AC97LinkState),
static void ac97_on_reset(DeviceState *dev)
{
- AC97LinkState *s = container_of(dev, AC97LinkState, dev.qdev);
+ AC97LinkState *s = AC97(dev);
reset_bm_regs(s, &s->bm_regs[0]);
reset_bm_regs(s, &s->bm_regs[1]);
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;
"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));
}