summaryrefslogtreecommitdiff
path: root/kernel/drv/oss_sbxfi
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/drv/oss_sbxfi')
-rw-r--r--kernel/drv/oss_sbxfi/.config1
-rw-r--r--kernel/drv/oss_sbxfi/.devices3
-rw-r--r--kernel/drv/oss_sbxfi/.name1
-rw-r--r--kernel/drv/oss_sbxfi/.params15
-rw-r--r--kernel/drv/oss_sbxfi/20k1reg.h911
-rw-r--r--kernel/drv/oss_sbxfi/hwaccess.h71
-rw-r--r--kernel/drv/oss_sbxfi/oss_sbxfi.c1078
-rw-r--r--kernel/drv/oss_sbxfi/oss_sbxfi.man20
-rw-r--r--kernel/drv/oss_sbxfi/sbxfi.h166
-rw-r--r--kernel/drv/oss_sbxfi/sbxfi_hwaccess.c1391
10 files changed, 3657 insertions, 0 deletions
diff --git a/kernel/drv/oss_sbxfi/.config b/kernel/drv/oss_sbxfi/.config
new file mode 100644
index 0000000..5280084
--- /dev/null
+++ b/kernel/drv/oss_sbxfi/.config
@@ -0,0 +1 @@
+platform=i86pc
diff --git a/kernel/drv/oss_sbxfi/.devices b/kernel/drv/oss_sbxfi/.devices
new file mode 100644
index 0000000..01f85a4
--- /dev/null
+++ b/kernel/drv/oss_sbxfi/.devices
@@ -0,0 +1,3 @@
+oss_sbxfi pci1102,5 Creative SB X-Fi 20K1 *EARLY BETA*
+oss_sbxfi pci1102,b Creative SB X-Fi 20K2 *EARLY BETA*
+#oss_sbxfi pci1102,9 Creative SB X-Fi PCI-e *EARLY BETA*
diff --git a/kernel/drv/oss_sbxfi/.name b/kernel/drv/oss_sbxfi/.name
new file mode 100644
index 0000000..d63384d
--- /dev/null
+++ b/kernel/drv/oss_sbxfi/.name
@@ -0,0 +1 @@
+Creative Sound Blaster X-Fi
diff --git a/kernel/drv/oss_sbxfi/.params b/kernel/drv/oss_sbxfi/.params
new file mode 100644
index 0000000..d9df108
--- /dev/null
+++ b/kernel/drv/oss_sbxfi/.params
@@ -0,0 +1,15 @@
+int sbxfi_type=0;
+/*
+ * Override sbxfi autodetection.
+ * Values: 0-4. Default: 0
+ * 0 - Autodetect
+ * 1 - Sound Blaster X-Fi (SB046x/067x/076x)
+ * 2 - Sound Blaster X-Fi (SB073x)
+ * 3 - Sound Blaster X-Fi (SB055x)
+ * 4 - Sound Blaster X-Fi (UAA)
+ * 5 - Sound Blaster X-Fi (SB0760)
+ * 6 - Sound Blaster X-Fi (SB0880-1)
+ * 7 - Sound Blaster X-Fi (SB0880-2)
+ * 8 - Sound Blaster X-Fi (SB0880-3)
+ */
+
diff --git a/kernel/drv/oss_sbxfi/20k1reg.h b/kernel/drv/oss_sbxfi/20k1reg.h
new file mode 100644
index 0000000..051c5a0
--- /dev/null
+++ b/kernel/drv/oss_sbxfi/20k1reg.h
@@ -0,0 +1,911 @@
+/**
+*******************************************************************************
+Confidential & Proprietary
+Private & Confidential
+Creative Confidential
+*******************************************************************************
+*/
+/**
+*******************************************************************************
+Copyright (C) Creative Technology, Ltd., 2007. All rights reserved.
+*******************************************************************************
+**/
+#ifndef _201kreg_H
+#define _20k1reg_H
+
+
+// PCI config registers
+#define PCI_CFGHDR_VENDORID 0x00
+#define PCI_CFGHDR_DEVICEID 0x02
+#define PCI_CFGHDR_CMDREG 0x04
+#define PCI_CFGHDR_STATUSREG 0x06
+#define PCI_CFGHDR_REVID 0x08
+#define PCI_CFGHDR_DEVCLASS 0x09
+#define PCI_CFGHDR_CACHESIZE 0x0C
+#define PCI_CFGHDR_LATENCY 0x0D
+#define PCI_CFGHDR_HEADERTYPE 0x0E
+#define PCI_CFGHDR_BIST 0x0F
+
+#define PCI_CFGHDR_BASEREG0 0x10
+#define PCI_CFGHDR_BASEREG1 0x14
+#define PCI_CFGHDR_BASEREG2 0x18
+#define PCI_CFGHDR_BASEREG3 0x1C
+#define PCI_CFGHDR_BASEREG4 0x20
+#define PCI_CFGHDR_BASEREG5 0x24
+
+#define PCI_CFGHDR_RESERVED1 0x28
+#define PCI_CFGHDR_SUBVENDORID 0x2C
+#define PCI_CFGHDR_SUBSYSTEMID 0x2E
+#define PCI_CFGHDR_EXPANDROM 0x30
+#define PCI_CFGHDR_RESERVED2 0x34
+#define PCI_CFGHDR_CAPS_PTR 0x34
+
+#define PCI_CFGHDR_IRQLINE 0x3C
+#define PCI_CFGHDR_IRQPIN 0x3D
+#define PCI_CFGHDR_MINGRANT 0x3E
+#define PCI_CFGHDR_MAXLATENCY 0x3F
+#define PCI_CFGHDR_LACR1 0x40
+#define PCI_CFGHDR_LACR2 0x41
+#define PCI_CFGHDR_LACR3 0x42
+#define PCI_CFGHDR_LACR4 0x43
+
+
+// 20k1 registers
+
+#define DSPXRAM_START 0x000000
+#define DSPXRAM_END 0x013FFC
+#define DSPAXRAM_START 0x020000
+#define DSPAXRAM_END 0x023FFC
+#define DSPYRAM_START 0x040000
+#define DSPYRAM_END 0x04FFFC
+#define DSPAYRAM_START 0x020000
+#define DSPAYRAM_END 0x063FFC
+#define DSPMICRO_START 0x080000
+#define DSPMICRO_END 0x0B3FFC
+#define DSP0IO_START 0x100000
+#define DSP0IO_END 0x101FFC
+#define AUDIORINGIPDSP0_START 0x100000
+#define AUDIORINGIPDSP0_END 0x1003FC
+#define AUDIORINGOPDSP0_START 0x100400
+#define AUDIORINGOPDSP0_END 0x1007FC
+#define AUDPARARINGIODSP0_START 0x100800
+#define AUDPARARINGIODSP0_END 0x100BFC
+#define DSP0LOCALHWREG_START 0x100C00
+#define DSP0LOCALHWREG_END 0x100C3C
+#define DSP0XYRAMAGINDEX_START 0x100C40
+#define DSP0XYRAMAGINDEX_END 0x100C5C
+#define DSP0XYRAMAGMDFR_START 0x100C60
+#define DSP0XYRAMAGMDFR_END 0x100C7C
+#define DSP0INTCONTLVEC_START 0x100C80
+#define DSP0INTCONTLVEC_END 0x100CD8
+#define INTCONTLGLOBALREG_START 0x100D1C
+#define INTCONTLGLOBALREG_END 0x100D3C
+#define HOSTINTFPORTADDRCONTDSP0 0x100D40
+#define HOSTINTFPORTDATADSP0 0x100D44
+#define TIME0PERENBDSP0 0x100D60
+#define TIME0COUNTERDSP0 0x100D64
+#define TIME1PERENBDSP0 0x100D68
+#define TIME1COUNTERDSP0 0x100D6C
+#define TIME2PERENBDSP0 0x100D70
+#define TIME2COUNTERDSP0 0x100D74
+#define TIME3PERENBDSP0 0x100D78
+#define TIME3COUNTERDSP0 0x100D7C
+#define XRAMINDOPERREFNOUP_STARTDSP0 0x100D80
+#define XRAMINDOPERREFNOUP_ENDDSP0 0x100D9C
+#define XRAMINDOPERREFUP_STARTDSP0 0x100DA0
+#define XRAMINDOPERREFUP_ENDDSP0 0x100DBC
+#define YRAMINDOPERREFNOUP_STARTDSP0 0x100DC0
+#define YRAMINDOPERREFNOUP_ENDDSP0 0x100DDC
+#define YRAMINDOPERREFUP_STARTDSP0 0x100DE0
+#define YRAMINDOPERREFUP_ENDDSP0 0x100DFC
+#define DSP0CONDCODE 0x100E00
+#define DSP0STACKFLAG 0x100E04
+#define DSP0PROGCOUNTSTACKPTREG 0x100E08
+#define DSP0PROGCOUNTSTACKDATAREG 0x100E0C
+#define DSP0CURLOOPADDRREG 0x100E10
+#define DSP0CURLOOPCOUNT 0x100E14
+#define DSP0TOPLOOPCOUNTSTACK 0x100E18
+#define DSP0TOPLOOPADDRSTACK 0x100E1C
+#define DSP0LOOPSTACKPTR 0x100E20
+#define DSP0STASSTACKDATAREG 0x100E24
+#define DSP0STASSTACKPTR 0x100E28
+#define DSP0PROGCOUNT 0x100E2C
+#define GLOBDSPDEBGREG 0x100E30
+#define GLOBDSPBREPTRREG 0x100E30
+#define DSP0XYRAMBASE_START 0x100EA0
+#define DSP0XYRAMBASE_END 0x100EBC
+#define DSP0XYRAMLENG_START 0x100EC0
+#define DSP0XYRAMLENG_END 0x100EDC
+#define SEMAPHOREREGDSP0 0x100EE0
+#define DSP0INTCONTMASKREG 0x100EE4
+#define DSP0INTCONTPENDREG 0x100EE8
+#define DSP0INTCONTSERVINT 0x100EEC
+#define DSPINTCONTEXTINTMODREG 0x100EEC
+#define GPIODSP0 0x100EFC
+#define DMADSPBASEADDRREG_STARTDSP0 0x100F00
+#define DMADSPBASEADDRREG_ENDDSP0 0x100F1C
+#define DMAHOSTBASEADDRREG_STARTDSP0 0x100F20
+#define DMAHOSTBASEADDRREG_ENDDSP0 0x100F3C
+#define DMADSPCURADDRREG_STARTDSP0 0x100F40
+#define DMADSPCURADDRREG_ENDDSP0 0x100F5C
+#define DMAHOSTCURADDRREG_STARTDSP0 0x100F60
+#define DMAHOSTCURADDRREG_ENDDSP0 0x100F7C
+#define DMATANXCOUNTREG_STARTDSP0 0x100F80
+#define DMATANXCOUNTREG_ENDDSP0 0x100F9C
+#define DMATIMEBUGREG_STARTDSP0 0x100FA0
+#define DMATIMEBUGREG_ENDDSP0 0x100FAC
+#define DMACNTLMODFREG_STARTDSP0 0x100FA0
+#define DMACNTLMODFREG_ENDDSP0 0x100FAC
+
+#define DMAGLOBSTATSREGDSP0 0x100FEC
+#define DSP0XGPRAM_START 0x101000
+#define DSP0XGPRAM_END 0x1017FC
+#define DSP0YGPRAM_START 0x101800
+#define DSP0YGPRAM_END 0x101FFC
+
+
+
+
+#define AUDIORINGIPDSP1_START 0x102000
+#define AUDIORINGIPDSP1_END 0x1023FC
+#define AUDIORINGOPDSP1_START 0x102400
+#define AUDIORINGOPDSP1_END 0x1027FC
+#define AUDPARARINGIODSP1_START 0x102800
+#define AUDPARARINGIODSP1_END 0x102BFC
+#define DSP1LOCALHWREG_START 0x102C00
+#define DSP1LOCALHWREG_END 0x102C3C
+#define DSP1XYRAMAGINDEX_START 0x102C40
+#define DSP1XYRAMAGINDEX_END 0x102C5C
+#define DSP1XYRAMAGMDFR_START 0x102C60
+#define DSP1XYRAMAGMDFR_END 0x102C7C
+#define DSP1INTCONTLVEC_START 0x102C80
+#define DSP1INTCONTLVEC_END 0x102CD8
+#define HOSTINTFPORTADDRCONTDSP1 0x102D40
+#define HOSTINTFPORTDATADSP1 0x102D44
+#define TIME0PERENBDSP1 0x102D60
+#define TIME0COUNTERDSP1 0x102D64
+#define TIME1PERENBDSP1 0x102D68
+#define TIME1COUNTERDSP1 0x102D6C
+#define TIME2PERENBDSP1 0x102D70
+#define TIME2COUNTERDSP1 0x102D74
+#define TIME3PERENBDSP1 0x102D78
+#define TIME3COUNTERDSP1 0x102D7C
+#define XRAMINDOPERREFNOUP_STARTDSP1 0x102D80
+#define XRAMINDOPERREFNOUP_ENDDSP1 0x102D9C
+#define XRAMINDOPERREFUP_STARTDSP1 0x102DA0
+#define XRAMINDOPERREFUP_ENDDSP1 0x102DBC
+#define YRAMINDOPERREFNOUP_STARTDSP1 0x102DC0
+#define YRAMINDOPERREFNOUP_ENDDSP1 0x102DDC
+#define YRAMINDOPERREFUP_STARTDSP1 0x102DE0
+#define YRAMINDOPERREFUP_ENDDSP1 0x102DFC
+
+#define DSP1CONDCODE 0x102E00
+#define DSP1STACKFLAG 0x102E04
+#define DSP1PROGCOUNTSTACKPTREG 0x102E08
+#define DSP1PROGCOUNTSTACKDATAREG 0x102E0C
+#define DSP1CURLOOPADDRREG 0x102E10
+#define DSP1CURLOOPCOUNT 0x102E14
+#define DSP1TOPLOOPCOUNTSTACK 0x102E18
+#define DSP1TOPLOOPADDRSTACK 0x102E1C
+#define DSP1LOOPSTACKPTR 0x102E20
+#define DSP1STASSTACKDATAREG 0x102E24
+#define DSP1STASSTACKPTR 0x102E28
+#define DSP1PROGCOUNT 0x102E2C
+#define DSP1XYRAMBASE_START 0x102EA0
+#define DSP1XYRAMBASE_END 0x102EBC
+#define DSP1XYRAMLENG_START 0x102EC0
+#define DSP1XYRAMLENG_END 0x102EDC
+#define SEMAPHOREREGDSP1 0x102EE0
+#define DSP1INTCONTMASKREG 0x102EE4
+#define DSP1INTCONTPENDREG 0x102EE8
+#define DSP1INTCONTSERVINT 0x102EEC
+#define GPIODSP1 0x102EFC
+#define DMADSPBASEADDRREG_STARTDSP1 0x102F00
+#define DMADSPBASEADDRREG_ENDDSP1 0x102F1C
+#define DMAHOSTBASEADDRREG_STARTDSP1 0x102F20
+#define DMAHOSTBASEADDRREG_ENDDSP1 0x102F3C
+#define DMADSPCURADDRREG_STARTDSP1 0x102F40
+#define DMADSPCURADDRREG_ENDDSP1 0x102F5C
+#define DMAHOSTCURADDRREG_STARTDSP1 0x102F60
+#define DMAHOSTCURADDRREG_ENDDSP1 0x102F7C
+#define DMATANXCOUNTREG_STARTDSP1 0x102F80
+#define DMATANXCOUNTREG_ENDDSP1 0x102F9C
+#define DMATIMEBUGREG_STARTDSP1 0x102FA0
+#define DMATIMEBUGREG_ENDDSP1 0x102FAC
+#define DMACNTLMODFREG_STARTDSP1 0x102FA0
+#define DMACNTLMODFREG_ENDDSP1 0x102FAC
+
+#define DMAGLOBSTATSREGDSP1 0x102FEC
+#define DSP1XGPRAM_START 0x103000
+#define DSP1XGPRAM_END 0x1033FC
+#define DSP1YGPRAM_START 0x103400
+#define DSP1YGPRAM_END 0x1037FC
+
+
+
+#define AUDIORINGIPDSP2_START 0x104000
+#define AUDIORINGIPDSP2_END 0x1043FC
+#define AUDIORINGOPDSP2_START 0x104400
+#define AUDIORINGOPDSP2_END 0x1047FC
+#define AUDPARARINGIODSP2_START 0x104800
+#define AUDPARARINGIODSP2_END 0x104BFC
+#define DSP2LOCALHWREG_START 0x104C00
+#define DSP2LOCALHWREG_END 0x104C3C
+#define DSP2XYRAMAGINDEX_START 0x104C40
+#define DSP2XYRAMAGINDEX_END 0x104C5C
+#define DSP2XYRAMAGMDFR_START 0x104C60
+#define DSP2XYRAMAGMDFR_END 0x104C7C
+#define DSP2INTCONTLVEC_START 0x104C80
+#define DSP2INTCONTLVEC_END 0x104CD8
+#define HOSTINTFPORTADDRCONTDSP2 0x104D40
+#define HOSTINTFPORTDATADSP2 0x104D44
+#define TIME0PERENBDSP2 0x104D60
+#define TIME0COUNTERDSP2 0x104D64
+#define TIME1PERENBDSP2 0x104D68
+#define TIME1COUNTERDSP2 0x104D6C
+#define TIME2PERENBDSP2 0x104D70
+#define TIME2COUNTERDSP2 0x104D74
+#define TIME3PERENBDSP2 0x104D78
+#define TIME3COUNTERDSP2 0x104D7C
+#define XRAMINDOPERREFNOUP_STARTDSP2 0x104D80
+#define XRAMINDOPERREFNOUP_ENDDSP2 0x104D9C
+#define XRAMINDOPERREFUP_STARTDSP2 0x104DA0
+#define XRAMINDOPERREFUP_ENDDSP2 0x104DBC
+#define YRAMINDOPERREFNOUP_STARTDSP2 0x104DC0
+#define YRAMINDOPERREFNOUP_ENDDSP2 0x104DDC
+#define YRAMINDOPERREFUP_STARTDSP2 0x104DE0
+#define YRAMINDOPERREFUP_ENDDSP2 0x104DFC
+#define DSP2CONDCODE 0x104E00
+#define DSP2STACKFLAG 0x104E04
+#define DSP2PROGCOUNTSTACKPTREG 0x104E08
+#define DSP2PROGCOUNTSTACKDATAREG 0x104E0C
+#define DSP2CURLOOPADDRREG 0x104E10
+#define DSP2CURLOOPCOUNT 0x104E14
+#define DSP2TOPLOOPCOUNTSTACK 0x104E18
+#define DSP2TOPLOOPADDRSTACK 0x104E1C
+#define DSP2LOOPSTACKPTR 0x104E20
+#define DSP2STASSTACKDATAREG 0x104E24
+#define DSP2STASSTACKPTR 0x104E28
+#define DSP2PROGCOUNT 0x104E2C
+#define DSP2XYRAMBASE_START 0x104EA0
+#define DSP2XYRAMBASE_END 0x104EBC
+#define DSP2XYRAMLENG_START 0x104EC0
+#define DSP2XYRAMLENG_END 0x104EDC
+#define SEMAPHOREREGDSP2 0x104EE0
+#define DSP2INTCONTMASKREG 0x104EE4
+#define DSP2INTCONTPENDREG 0x104EE8
+#define DSP2INTCONTSERVINT 0x104EEC
+#define GPIODSP2 0x104EFC
+#define DMADSPBASEADDRREG_STARTDSP2 0x104F00
+#define DMADSPBASEADDRREG_ENDDSP2 0x104F1C
+#define DMAHOSTBASEADDRREG_STARTDSP2 0x104F20
+#define DMAHOSTBASEADDRREG_ENDDSP2 0x104F3C
+#define DMADSPCURADDRREG_STARTDSP2 0x104F40
+#define DMADSPCURADDRREG_ENDDSP2 0x104F5C
+#define DMAHOSTCURADDRREG_STARTDSP2 0x104F60
+#define DMAHOSTCURADDRREG_ENDDSP2 0x104F7C
+#define DMATANXCOUNTREG_STARTDSP2 0x104F80
+#define DMATANXCOUNTREG_ENDDSP2 0x104F9C
+#define DMATIMEBUGREG_STARTDSP2 0x104FA0
+#define DMATIMEBUGREG_ENDDSP2 0x104FAC
+#define DMACNTLMODFREG_STARTDSP2 0x104FA0
+#define DMACNTLMODFREG_ENDDSP2 0x104FAC
+
+#define DMAGLOBSTATSREGDSP2 0x104FEC
+#define DSP2XGPRAM_START 0x105000
+#define DSP2XGPRAM_END 0x1051FC
+#define DSP2YGPRAM_START 0x105800
+#define DSP2YGPRAM_END 0x1059FC
+
+
+
+#define AUDIORINGIPDSP3_START 0x106000
+#define AUDIORINGIPDSP3_END 0x1063FC
+#define AUDIORINGOPDSP3_START 0x106400
+#define AUDIORINGOPDSP3_END 0x1067FC
+#define AUDPARARINGIODSP3_START 0x106800
+#define AUDPARARINGIODSP3_END 0x106BFC
+#define DSP3LOCALHWREG_START 0x106C00
+#define DSP3LOCALHWREG_END 0x106C3C
+#define DSP3XYRAMAGINDEX_START 0x106C40
+#define DSP3XYRAMAGINDEX_END 0x106C5C
+#define DSP3XYRAMAGMDFR_START 0x106C60
+#define DSP3XYRAMAGMDFR_END 0x106C7C
+#define DSP3INTCONTLVEC_START 0x106C80
+#define DSP3INTCONTLVEC_END 0x106CD8
+#define HOSTINTFPORTADDRCONTDSP3 0x106D40
+#define HOSTINTFPORTDATADSP3 0x106D44
+#define TIME0PERENBDSP3 0x106D60
+#define TIME0COUNTERDSP3 0x106D64
+#define TIME1PERENBDSP3 0x106D68
+#define TIME1COUNTERDSP3 0x106D6C
+#define TIME2PERENBDSP3 0x106D70
+#define TIME2COUNTERDSP3 0x106D74
+#define TIME3PERENBDSP3 0x106D78
+#define TIME3COUNTERDSP3 0x106D7C
+#define XRAMINDOPERREFNOUP_STARTDSP3 0x106D80
+#define XRAMINDOPERREFNOUP_ENDDSP3 0x106D9C
+#define XRAMINDOPERREFUP_STARTDSP3 0x106DA0
+#define XRAMINDOPERREFUP_ENDDSP3 0x106DBC
+#define YRAMINDOPERREFNOUP_STARTDSP3 0x106DC0
+#define YRAMINDOPERREFNOUP_ENDDSP3 0x106DDC
+#define YRAMINDOPERREFUP_STARTDSP3 0x106DE0
+#define YRAMINDOPERREFUP_ENDDSP3 0x100DFC
+
+#define DSP3CONDCODE 0x106E00
+#define DSP3STACKFLAG 0x106E04
+#define DSP3PROGCOUNTSTACKPTREG 0x106E08
+#define DSP3PROGCOUNTSTACKDATAREG 0x106E0C
+#define DSP3CURLOOPADDRREG 0x106E10
+#define DSP3CURLOOPCOUNT 0x106E14
+#define DSP3TOPLOOPCOUNTSTACK 0x106E18
+#define DSP3TOPLOOPADDRSTACK 0x106E1C
+#define DSP3LOOPSTACKPTR 0x106E20
+#define DSP3STASSTACKDATAREG 0x106E24
+#define DSP3STASSTACKPTR 0x106E28
+#define DSP3PROGCOUNT 0x106E2C
+#define DSP3XYRAMBASE_START 0x106EA0
+#define DSP3XYRAMBASE_END 0x106EBC
+#define DSP3XYRAMLENG_START 0x106EC0
+#define DSP3XYRAMLENG_END 0x106EDC
+#define SEMAPHOREREGDSP3 0x106EE0
+#define DSP3INTCONTMASKREG 0x106EE4
+#define DSP3INTCONTPENDREG 0x106EE8
+#define DSP3INTCONTSERVINT 0x106EEC
+#define GPIODSP3 0x106EFC
+#define DMADSPBASEADDRREG_STARTDSP3 0x106F00
+#define DMADSPBASEADDRREG_ENDDSP3 0x106F1C
+#define DMAHOSTBASEADDRREG_STARTDSP3 0x106F20
+#define DMAHOSTBASEADDRREG_ENDDSP3 0x106F3C
+#define DMADSPCURADDRREG_STARTDSP3 0x106F40
+#define DMADSPCURADDRREG_ENDDSP3 0x106F5C
+#define DMAHOSTCURADDRREG_STARTDSP3 0x106F60
+#define DMAHOSTCURADDRREG_ENDDSP3 0x106F7C
+#define DMATANXCOUNTREG_STARTDSP3 0x106F80
+#define DMATANXCOUNTREG_ENDDSP3 0x106F9C
+#define DMATIMEBUGREG_STARTDSP3 0x106FA0
+#define DMATIMEBUGREG_ENDDSP3 0x106FAC
+#define DMACNTLMODFREG_STARTDSP3 0x106FA0
+#define DMACNTLMODFREG_ENDDSP3 0x106FAC
+
+#define DMAGLOBSTATSREGDSP3 0x106FEC
+#define DSP3XGPRAM_START 0x107000
+#define DSP3XGPRAM_END 0x1071FC
+#define DSP3YGPRAM_START 0x107800
+#define DSP3YGPRAM_END 0x1079FC
+
+//end of DSP reg definitions
+
+#define DSPAIMAP_START 0x108000
+#define DSPAIMAP_END 0x1083FC
+#define DSPPIMAP_START 0x108400
+#define DSPPIMAP_END 0x1087FC
+#define DSPPOMAP_START 0x108800
+#define DSPPOMAP_END 0x108BFC
+#define DSPPOCTL 0x108C00
+#define TKCTL_START 0x110000
+#define TKCTL_END 0x110FFC
+#define TKCC_START 0x111000
+#define TKCC_END 0x111FFC
+#define TKIMAP_START 0x112000
+#define TKIMAP_END 0x112FFC
+#define TKDCTR16 0x113000
+#define TKPB16 0x113004
+#define TKBS16 0x113008
+#define TKDCTR32 0x11300C
+#define TKPB32 0x113010
+#define TKBS32 0x113014
+#define ICDCTR16 0x113018
+#define ITBS16 0x11301C
+#define ICDCTR32 0x113020
+#define ITBS32 0x113024
+#define ITSTART 0x113028
+#define TKSQ 0x11302C
+
+#define TKSCCTL_START 0x114000
+#define TKSCCTL_END 0x11403C
+#define TKSCADR_START 0x114100
+#define TKSCADR_END 0x11413C
+#define TKSCDATAX_START 0x114800
+#define TKSCDATAX_END 0x1149FC
+#define TKPCDATAX_START 0x120000
+#define TKPCDATAX_END 0x12FFFC
+
+#define MALSA 0x130000
+#define MAPPHA 0x130004
+#define MAPPLA 0x130008
+#define MALSB 0x130010
+#define MAPPHB 0x130014
+#define MAPPLB 0x130018
+
+#define TANSPORTMAPABREGS_START 0x130020
+#define TANSPORTMAPABREGS_END 0x13A2FC
+
+#define PTPAHX 0x13B000
+#define PTPALX 0x13B004
+//#define PTPALX 0x13B004
+
+#define TANSPPAGETABLEPHYADDR015_START 0x13B008
+#define TANSPPAGETABLEPHYADDR015_END 0x13B07C
+#define TRNQADRX_START 0x13B100
+#define TRNQADRX_END 0x13B13C
+#define TRNQTIMX_START 0x13B200
+#define TRNQTIMX_END 0x13B23C
+#define TRNQAPARMX_START 0x13B300
+#define TRNQAPARMX_END 0x13B33C
+
+#define TRNQCNT 0x13B400
+#define TRNCTL 0x13B404
+#define TRNIS 0x13B408
+#define TRNCURTS 0x13B40C
+
+#define AMOP_START(n) 0x140000+(8*(n))
+#define AMOP_END 0x147FFC
+#define PMOP_START 0x148000
+#define PMOP_END 0x14FFFC
+#define PCURR_START 0x150000
+#define PCURR_END 0x153FFC
+#define PTRAG_START 0x154000
+#define PTRAG_END 0x157FFC
+#define PSR_START 0x158000
+#define PSR_END 0x15BFFC
+
+#define PFSTAT4SEG_START 0x160000
+#define PFSTAT4SEG_END 0x160BFC
+#define PFSTAT2SEG_START 0x160C00
+#define PFSTAT2SEG_END 0x1617FC
+#define PFTARG4SEG_START 0x164000
+#define PFTARG4SEG_END 0x164BFC
+#define PFTARG2SEG_START 0x164C00
+#define PFTARG2SEG_END 0x1657FC
+#define PFSR4SEG_START 0x168000
+#define PFSR4SEG_END 0x168BFC
+#define PFSR2SEG_START 0x168C00
+#define PFSR2SEG_END 0x1697FC
+#define PCURRMS4SEG_START 0x16C000
+#define PCURRMS4SEG_END 0x16CCFC
+#define PCURRMS2SEG_START 0x16CC00
+#define PCURRMS2SEG_END 0x16D7FC
+#define PTARGMS4SEG_START 0x170000
+#define PTARGMS4SEG_END 0x172FFC
+#define PTARGMS2SEG_START 0x173000
+#define PTARGMS2SEG_END 0x1747FC
+#define PSRMS4SEG_START 0x170000
+#define PSRMS4SEG_END 0x172FFC
+#define PSRMS2SEG_START 0x173000
+#define PSRMS2SEG_END 0x1747FC
+
+#define PRING_LO_START 0x190000
+#define PRING_LO_END 0x193FFC
+#define PRING_HI_START 0x194000
+#define PRING_HI_END 0x197FFC
+#define PRING_LO_HI_START(n) 0x198000+(4*(n))
+#define PRING_LO_HI_END 0x19BFFC
+
+#define PINTFIFO 0x1A0000
+#define SRCCTL(n) 0x1B0000+((n)*0x100)
+# define SRCCTL_ILSZ (1<<16) // bits 16-19
+# define SRCCTL_IE (1<<15)
+#define SRCCCR(n) 0x1B0004+(0x100*(n))
+#define SRCIMAP(n) 0x1B0008+(0x100*(n))
+#define SRCODDC 0x1B000C
+#define SRCCA(n) 0x1B0010+((n)*0x100)
+#define SRCCF(n) 0x1B0014+((n)*0x100)
+#define SRCSA(n) 0x1B0018+((n)*0x100)
+#define SRCLA(n) 0x1B001C+((n)*0x100)
+#define SRCCTLSWR 0x1B0020
+
+///SRC HERE
+#define SRCALBA 0x1B002C
+#define SRCMCTL 0x1B012C
+#define SRCCERR 0x1B022C
+#define SRCITB 0x1B032C
+#define SRCIPM 0x1B082C
+#define SRCIP(n) 0x1B102C+((n)*0x100)
+#define SRCENBSTAT 0x1B202C
+#define SRCENBLO 0x1B212C
+#define SRCENBHI 0x1B222C
+#define SRCENBS 0x1B352C
+#define SRCENB07 0x1B282C
+#define SRCENBS07 0x1B302C
+
+#define SRCDN0Z0 0x1B0030
+#define SRCDN0Z1 0x1B0034
+#define SRCDN0Z2 0x1B0038
+#define SRCDN0Z3 0x1B003C
+#define SRCDN1Z0 0x1B0040
+#define SRCDN1Z1 0x1B0044
+#define SRCDN1Z2 0x1B0048
+#define SRCDN1Z3 0x1B004C
+#define SRCDN1Z4 0x1B0050
+#define SRCDN1Z5 0x1B0054
+#define SRCDN1Z6 0x1B0058
+#define SRCDN1Z7 0x1B005C
+#define SRCUPZ0 0x1B0060
+#define SRCUPZ1 0x1B0064
+#define SRCUPZ2 0x1B0068
+#define SRCUPZ3 0x1B006C
+#define SRCUPZ4 0x1B0070
+#define SRCUPZ5 0x1B0074
+#define SRCUPZ6 0x1B0078
+#define SRCUPZ7 0x1B007C
+#define SRCCD0 0x1B0080
+#define SRCCD1 0x1B0084
+#define SRCCD2 0x1B0088
+#define SRCCD3 0x1B008C
+#define SRCCD4 0x1B0090
+#define SRCCD5 0x1B0094
+#define SRCCD6 0x1B0098
+#define SRCCD7 0x1B009C
+#define SRCCD8 0x1B00A0
+#define SRCCD9 0x1B00A4
+#define SRCCDA 0x1B00A8
+#define SRCCDB 0x1B00AC
+#define SRCCDC 0x1B00B0
+#define SRCCDD 0x1B00B4
+#define SRCCDE 0x1B00B8
+#define SRCCDF 0x1B00BC
+#define SRCCD10 0x1B00C0
+#define SRCCD11 0x1B00C4
+#define SRCCD12 0x1B00C8
+#define SRCCD13 0x1B00CC
+#define SRCCD14 0x1B00D0
+#define SRCCD15 0x1B00D4
+#define SRCCD16 0x1B00D8
+#define SRCCD17 0x1B00DC
+#define SRCCD18 0x1B00E0
+#define SRCCD19 0x1B00E4
+#define SRCCD1A 0x1B00E8
+#define SRCCD1B 0x1B00EC
+#define SRCCD1C 0x1B00F0
+#define SRCCD1D 0x1B00F4
+#define SRCCD1E 0x1B00F8
+#define SRCCD1F 0x1B00FC
+
+#define SRCCONTRBLOCK_START 0x1B0100
+#define SRCCONTRBLOCK_END 0x1BFFFC
+#define FILTOP_START 0x1C0000
+#define FILTOP_END 0x1C05FC
+#define FILTIMAP_START 0x1C0800
+#define FILTIMAP_END 0x1C0DFC
+#define FILTZ1_START 0x1C1000
+#define FILTZ1_END 0x1C15FC
+#define FILTZ2_START 0x1C1800
+#define FILTZ2_END 0x1C1DFC
+#define DAOIMAP_START(n) 0x1C5000+(4*(n))
+#define DAOIMAP_END 0x1C5124
+
+#define AC97D 0x1C5400
+#define AC97A 0x1C5404
+#define AC97CTL 0x1C5408
+#define I2SCTL 0x1C5420
+
+#define SPOSA 0x1C5440
+#define SPOSB 0x1C5444
+#define SPOSC 0x1C5448
+#define SPOSD 0x1C544C
+
+#define SPISA 0x1C5450
+#define SPISB 0x1C5454
+#define SPISC 0x1C5458
+#define SPISD 0x1C545C
+
+#define SPFSCTL 0x1C5460
+
+#define SPFS0 0x1C5468
+#define SPFS1 0x1C546C
+#define SPFS2 0x1C5470
+#define SPFS3 0x1C5474
+#define SPFS4 0x1C5478
+#define SPFS5 0x1C547C
+
+#define SPOCTL 0x1C5480
+#define SPICTL 0x1C5484
+#define SPISTS 0x1C5488
+#define SPINTP 0x1C548C
+#define SPINTE 0x1C5490
+#define SPUTCTLAB 0x1C5494
+#define SPUTCTLCD 0x1C5498
+
+#define SRTSPA 0x1C54C0
+#define SRTSPB 0x1C54C4
+#define SRTSPC 0x1C54C8
+#define SRTSPD 0x1C54CC
+
+#define SRTSCTLA 0x1C54D0
+#define SRTSCTLB 0x1C54D4
+#define SRTSCTLC 0x1C54D8
+#define SRTSCTLD 0x1C54DC
+
+#define SRTI2S 0x1C54E0
+#define SRTICTL 0x1C54F0
+
+#define WC 0x1C6000
+#define TIMR 0x1C6004
+# define TIMR_IE (1<<15)
+# define TIMR_IP (1<<14)
+
+#define GIP 0x1C6010
+# define PLL_INT (1<<10)
+# define FI_INT (1<<9)
+# define IT_INT (1<<8)
+# define PCI_INT (1<<7)
+# define URT_INT (1<<6)
+# define GPI_INT (1<<5)
+# define MIX_INT (1<<4)
+# define DAI_INT (1<<3)
+# define TP_INT (1<<2)
+# define DSP_INT (1<<1)
+# define SRC_INT (1<<0)
+#define GIE 0x1C6014
+#define DIE 0x1C6018
+#define DIC 0x1C601C
+#define GPIO 0x1C6020
+#define GPIOCTL 0x1C6024
+#define GPIP 0x1C6028
+#define GPIE 0x1C602C
+#define DSPINT0 0x1C6030
+#define DSPEIOC 0x1C6034
+//#define MUADAT 0x00700000L /* Midi Uart A DATa */
+//#define MUACMD 0x00710000L /* Midi Uart A CoMmanD */
+//#define MUASTAT 0x00710000L /* Midi Uart A STATus */
+//#define MUBDAT 0x00720000L /* Midi Uart B DATa */
+//#define MUBCMD 0x00730000L /* Midi Uart B CoMmanD */
+//#define MUBSTAT 0x00730000L /* Midi Uart B STATus */
+#define MUADAT 0x1C6040
+#define MUACMD 0x1C6044
+#define MUASTAT 0x1C6044
+#define MUBDAT 0x1C6048
+#define MUBCMD 0x1C604C
+#define MUBSTAT 0x1C604C
+#define UARTCMA 0x1C6050
+#define UARTCMB 0x1C6054
+#define UARTIP 0x1C6058
+#define UARTIE 0x1C605C
+#define PLLCTL 0x1C6060
+#define PLLDCD 0x1C6064
+#define GCTL 0x1C6070
+#define ID0 0x1C6080
+#define ID1 0x1C6084
+#define ID2 0x1C6088
+#define ID3 0x1C608C
+#define SDRCTL 0x1C7000
+
+
+#define I2SA_L 0x0L
+#define I2SA_R 0x1L
+#define I2SB_L 0x8L
+#define I2SB_R 0x9L
+#define I2SC_L 0x10L
+#define I2SC_R 0x11L
+#define I2SD_L 0x18L
+#define I2SD_R 0x19L
+
+
+
+typedef enum
+{
+ //block 0
+ FIL_CH_0 = 0,
+ SRC_CH_0 = 0x1,
+ MIXER_SUM_CH_0 = 0xc,
+
+ //block 1
+ FIL_CH_1 = 0x10,
+ SRC_CH_1 = 0x11,
+ MIXER_SUM_CH_1 = 0x1c,
+
+
+ DAI_CH_AC97L = 0x5e5,
+ DAI_CH_AC97R = 0x7e5,
+ DAI_CH_AC97MIC = 0xde5,
+
+//daoi i2s out block
+ DAI_CH_I2SAL = 0x0,
+ DAI_CH_I2SAR = 0x1,
+ DAI_CH_I2SA1L = 0x2,
+ DAI_CH_I2SA1R = 0x3,
+ DAI_CH_I2SA2L = 0x4,
+ DAI_CH_I2SA2R = 0x5,
+ DAI_CH_I2SA3L = 0x6,
+ DAI_CH_I2SA3R = 0x7,
+
+ DAI_CH_I2SBL = 0x8,
+ DAI_CH_I2SBR = 0x9,
+ DAI_CH_I2SB1L = 0xa,
+ DAI_CH_I2SB1R = 0xb,
+ DAI_CH_I2SB2L = 0xc,
+ DAI_CH_I2SB2R = 0xd,
+ DAI_CH_I2SB3L = 0xe,
+ DAI_CH_I2SB3R = 0xf,
+
+ DAI_CH_I2SCL = 0x10,
+ DAI_CH_I2SCR = 0x11,
+ DAI_CH_I2SC1L = 0x12,
+ DAI_CH_I2SC1R = 0x13,
+ DAI_CH_I2SC2L = 0x14,
+ DAI_CH_I2SC2R = 0x15,
+ DAI_CH_I2SC3L = 0x16,
+ DAI_CH_I2SC3R = 0x17,
+
+ DAI_CH_I2SDL = 0x18,
+ DAI_CH_I2SDR = 0x19,
+ DAI_CH_I2SD1L = 0x1a,
+ DAI_CH_I2SD1R = 0x1b,
+ DAI_CH_I2SD2L = 0x1c,
+ DAI_CH_I2SD2R = 0x1d,
+ DAI_CH_I2SD3L = 0x1e,
+ DAI_CH_I2SD3R = 0x1f,
+
+//daoi spdif out
+ DAI_CH_SPDIFAL = 0x20,
+ DAI_CH_SPDIFAR = 0x21,
+ DAI_CH_SPDIFA1L = 0x22,
+ DAI_CH_SPDIFA1R = 0x23,
+ DAI_CH_SPDIFA2L = 0x24,
+ DAI_CH_SPDIFA2R = 0x25,
+ DAI_CH_SPDIFA3L = 0x26,
+ DAI_CH_SPDIFA3R = 0x27,
+
+ DAI_CH_SPDIFBL = 0x28,
+ DAI_CH_SPDIFBR = 0x29,
+ DAI_CH_SPDIFB1L = 0x2a,
+ DAI_CH_SPDIFB1R = 0x2b,
+ DAI_CH_SPDIFB2L = 0x2c,
+ DAI_CH_SPDIFB2R = 0x2d,
+ DAI_CH_SPDIFB3L = 0x2e,
+ DAI_CH_SPDIFB3R = 0x2f,
+
+ DAI_CH_SPDIFCL = 0x30,
+ DAI_CH_SPDIFCR = 0x31,
+ DAI_CH_SPDIFC1L = 0x32,
+ DAI_CH_SPDIFC1R = 0x33,
+ DAI_CH_SPDIFC2L = 0x34,
+ DAI_CH_SPDIFC2R = 0x35,
+ DAI_CH_SPDIFC3L = 0x36,
+ DAI_CH_SPDIFC3R = 0x37,
+
+ DAI_CH_SPDIFDL = 0x38,
+ DAI_CH_SPDIFDR = 0x39,
+ DAI_CH_SPDIFD1L = 0x3a,
+ DAI_CH_SPDIFD1R = 0x3b,
+ DAI_CH_SPDIFD2L = 0x3c,
+ DAI_CH_SPDIFD2R = 0x3d,
+ DAI_CH_SPDIFD3L = 0x3e,
+ DAI_CH_SPDIFD3R = 0x3f,
+
+//daio i2s block(in)
+ DAI_CH_I2SINA1L = 0x035,
+ DAI_CH_I2SINA1R = 0x03D,
+ DAI_CH_I2SINB1L = 0x0B5,
+ DAI_CH_I2SINB1R = 0x0BD,
+ DAI_CH_I2SINC1L = 0x135,
+ DAI_CH_I2SINC1R = 0x13D,
+ DAI_CH_I2SIND1L = 0x1B5,
+ DAI_CH_I2SIND1R = 0x1BD,
+ DAI_CH_I2SINA2L = 0x235,
+ DAI_CH_I2SINA2R = 0x23D,
+ DAI_CH_I2SINB2L = 0x2B5,
+ DAI_CH_I2SINB2R = 0x2BD,
+ DAI_CH_I2SINC2L = 0x335,
+ DAI_CH_I2SINC2R = 0x33D,
+ DAI_CH_I2SIND2L = 0x3B5,
+ DAI_CH_I2SIND2R = 0x3BD,
+ DAI_CH_I2SINA3L = 0x435,
+ DAI_CH_I2SINA3R = 0x43D,
+ DAI_CH_I2SINB3L = 0x4B5,
+ DAI_CH_I2SINB3R = 0x4BD,
+ DAI_CH_I2SINC3L = 0x535,
+ DAI_CH_I2SINC3R = 0x53D,
+ DAI_CH_I2SIND3L = 0x5B5,
+ DAI_CH_I2SIND3R = 0x5BD,
+ DAI_CH_I2SINA4L = 0x635,
+ DAI_CH_I2SINA4R = 0x63D,
+ DAI_CH_I2SINB4L = 0x6B5,
+ DAI_CH_I2SINB4R = 0x6BD,
+ DAI_CH_I2SINC4L = 0x735,
+ DAI_CH_I2SINC4R = 0x73D,
+ DAI_CH_I2SIND4L = 0x7B5,
+ DAI_CH_I2SIND4R = 0x7BD,
+ DAI_CH_I2SINA5L = 0x835,
+ DAI_CH_I2SINA5R = 0x83D,
+ DAI_CH_I2SINB5L = 0x8B5,
+ DAI_CH_I2SINB5R = 0x8BD,
+ DAI_CH_I2SINC5L = 0x935,
+ DAI_CH_I2SINC5R = 0x93D,
+ DAI_CH_I2SIND5L = 0x9B5,
+ DAI_CH_I2SIND5R = 0x9BD,
+ DAI_CH_I2SINA6L = 0xA35,
+ DAI_CH_I2SINA6R = 0xA3D,
+ DAI_CH_I2SINB6L = 0xAB5,
+ DAI_CH_I2SINB6R = 0xABD,
+ DAI_CH_I2SINC6L = 0xB35,
+ DAI_CH_I2SINC6R = 0xB3D,
+ DAI_CH_I2SIND6L = 0xBB5,
+ DAI_CH_I2SIND6R = 0xBBD,
+ DAI_CH_I2SINA7L = 0xC35,
+ DAI_CH_I2SINA7R = 0xC3D,
+ DAI_CH_I2SINB7L = 0xCB5,
+ DAI_CH_I2SINB7R = 0xCBD,
+ DAI_CH_I2SINC7L = 0xD35,
+ DAI_CH_I2SINC7R = 0xD3D,
+ DAI_CH_I2SIND7L = 0xDB5,
+ DAI_CH_I2SIND7R = 0xDBD,
+ DAI_CH_I2SINA8L = 0xE35,
+ DAI_CH_I2SINA8R = 0xE3D,
+ DAI_CH_I2SINB8L = 0xEB5,
+ DAI_CH_I2SINB8R = 0xEBD,
+ DAI_CH_I2SINC8L = 0xF35,
+ DAI_CH_I2SINC8R = 0xF3D,
+ DAI_CH_I2SIND8L = 0xFB5,
+ DAI_CH_I2SIND8R = 0xFBD,
+
+ //daio cd-spidf block
+ DAI_CH_CDSPDIFINA1L = 0x015,
+ DAI_CH_CDSPDIFINA1R = 0x01D,
+ DAI_CH_CDSPDIFINB1L = 0x095,
+ DAI_CH_CDSPDIFINB1R = 0x09D,
+ DAI_CH_CDSPDIFINC1L = 0x115,
+ DAI_CH_CDSPDIFINC1R = 0x11D,
+ DAI_CH_CDSPDIFIND1L = 0x195,
+ DAI_CH_CDSPDIFIND1R = 0x19D,
+ DAI_CH_CDSPDIFINA2L = 0x215,
+ DAI_CH_CDSPDIFINA2R = 0x21D,
+ DAI_CH_CDSPDIFINB2L = 0x295,
+ DAI_CH_CDSPDIFINB2R = 0x29D,
+ DAI_CH_CDSPDIFINC2L = 0x315,
+ DAI_CH_CDSPDIFINC2R = 0x31D,
+ DAI_CH_CDSPDIFIND2L = 0x395,
+ DAI_CH_CDSPDIFIND2R = 0x39D,
+ DAI_CH_CDSPDIFINA3L = 0x415,
+ DAI_CH_CDSPDIFINA3R = 0x41D,
+ DAI_CH_CDSPDIFINB3L = 0x495,
+ DAI_CH_CDSPDIFINB3R = 0x49D,
+ DAI_CH_CDSPDIFINC3L = 0x515,
+ DAI_CH_CDSPDIFINC3R = 0x51D,
+ DAI_CH_CDSPDIFIND3L = 0x595,
+ DAI_CH_CDSPDIFIND3R = 0x59D,
+ DAI_CH_CDSPDIFINA4L = 0x615,
+ DAI_CH_CDSPDIFINA4R = 0x61D,
+ DAI_CH_CDSPDIFINB4L = 0x695,
+ DAI_CH_CDSPDIFINB4R = 0x69D,
+ DAI_CH_CDSPDIFINC4L = 0x715,
+ DAI_CH_CDSPDIFINC4R = 0x71D,
+ DAI_CH_CDSPDIFIND4L = 0x795,
+ DAI_CH_CDSPDIFIND4R = 0x79D,
+ DAI_CH_CDSPDIFINA5L = 0x815,
+ DAI_CH_CDSPDIFINA5R = 0x81D,
+ DAI_CH_CDSPDIFINB5L = 0x895,
+ DAI_CH_CDSPDIFINB5R = 0x89D,
+ DAI_CH_CDSPDIFINC5L = 0x915,
+ DAI_CH_CDSPDIFINC5R = 0x91D,
+ DAI_CH_CDSPDIFIND5L = 0x995,
+ DAI_CH_CDSPDIFIND5R = 0x99D,
+ DAI_CH_CDSPDIFINA6L = 0xA15,
+ DAI_CH_CDSPDIFINA6R = 0xA1D,
+ DAI_CH_CDSPDIFINB6L = 0xA95,
+ DAI_CH_CDSPDIFINB6R = 0xA9D,
+ DAI_CH_CDSPDIFINC6L = 0xB15,
+ DAI_CH_CDSPDIFINC6R = 0xB1D,
+ DAI_CH_CDSPDIFIND6L = 0xB95,
+ DAI_CH_CDSPDIFIND6R = 0xB9D,
+ DAI_CH_CDSPDIFINA7L = 0xC15,
+ DAI_CH_CDSPDIFINA7R = 0xC1D,
+ DAI_CH_CDSPDIFINB7L = 0xC95,
+ DAI_CH_CDSPDIFINB7R = 0xC9D,
+ DAI_CH_CDSPDIFINC7L = 0xD15,
+ DAI_CH_CDSPDIFINC7R = 0xD1D,
+ DAI_CH_CDSPDIFIND7L = 0xD95,
+ DAI_CH_CDSPDIFIND7R = 0xD9D,
+ DAI_CH_CDSPDIFINA8L = 0xE15,
+ DAI_CH_CDSPDIFINA8R = 0xE1D,
+ DAI_CH_CDSPDIFINB8L = 0xE95,
+ DAI_CH_CDSPDIFINB8R = 0xE9D,
+ DAI_CH_CDSPDIFINC8L = 0xF15,
+ DAI_CH_CDSPDIFINC8R = 0xF1D,
+ DAI_CH_CDSPDIFIND8L = 0xF95,
+ DAI_CH_CDSPDIFIND8R = 0xF9D
+} ARCHANNEL;
+
+
+#endif
diff --git a/kernel/drv/oss_sbxfi/hwaccess.h b/kernel/drv/oss_sbxfi/hwaccess.h
new file mode 100644
index 0000000..872e2e2
--- /dev/null
+++ b/kernel/drv/oss_sbxfi/hwaccess.h
@@ -0,0 +1,71 @@
+/**
+*******************************************************************************
+Confidential & Proprietary
+Private & Confidential
+Creative Confidential
+*******************************************************************************
+*/
+/**
+*******************************************************************************
+Copyright (C) Creative Technology, Ltd., 2007. All rights reserved.
+*******************************************************************************
+**/
+
+#ifndef _HWACCESS_H_
+#define _HWACCESS_H_
+
+unsigned int GetAudioSrcChan (unsigned int srcchn);
+unsigned int GetAudioSumChan (unsigned int chn);
+unsigned int GetParamPitchChan (unsigned int i);
+void WriteAMOP (sbxfi_devc_t * devc, unsigned int xdata, unsigned int ydata,
+ unsigned int chn, unsigned int hidata);
+void WriteSRC (sbxfi_devc_t * devc, unsigned int srcca, unsigned int srccf,
+ unsigned int srcsa, unsigned int srcla, unsigned int srcccr, unsigned int srcctl,
+ unsigned int chn);
+unsigned int HwRead20K1PCI (sbxfi_devc_t * devc, unsigned int dwReg);
+unsigned int HwRead20K1 (sbxfi_devc_t * devc, unsigned int dwReg);
+void HwWrite20K1 (sbxfi_devc_t * devc, unsigned int dwReg, unsigned int dwData);
+void HwWrite20K1PCI (sbxfi_devc_t * devc, unsigned int dwReg, unsigned int dwData);
+unsigned int ReadCfgDword (unsigned int dwBusNum, unsigned int dwDevNum, unsigned int dwFuncNum,
+ unsigned int dwReg);
+unsigned short ReadCfgWord (unsigned int dwBusNum, unsigned int dwDevNum, unsigned int dwFuncNum,
+ unsigned int dwReg);
+void WriteConfigDword (unsigned int dwBusNum, unsigned int dwDevNum, unsigned int dwFuncNum,
+ unsigned int dwReg, unsigned int dwData);
+
+unsigned char DetectAndConfigureHardware (sbxfi_devc_t * devc);
+unsigned char IsVistaCompatibleHardware (sbxfi_devc_t * devc);
+void SwitchToXFiCore (sbxfi_devc_t * devc);
+CTSTATUS InitHardware (sbxfi_devc_t * devc);
+CTSTATUS AllocateBuffers (sbxfi_devc_t * devc, sbxfi_portc_t * portc);
+void FreeBuffers (sbxfi_devc_t * devc, sbxfi_portc_t * portc);
+void SetupHardwarePageTable (sbxfi_devc_t * devc, sbxfi_portc_t * portc);
+void InitADC (sbxfi_devc_t * devc, unsigned int src, unsigned char mic20db);
+void ResetDAC (sbxfi_devc_t * devc);
+void InitDAC (sbxfi_devc_t * devc, sbxfi_portc_t * portc);
+
+void SetupPlayMixer (sbxfi_devc_t * devc, sbxfi_portc_t * portc);
+void UpdatePlayMixer (sbxfi_devc_t * devc, sbxfi_portc_t * portc);
+void SetupPlayFormat (sbxfi_devc_t * devc, sbxfi_portc_t * portc);
+void SetupAndStartPlaySRC (sbxfi_devc_t * devc, sbxfi_portc_t * portc);
+void StopPlaySRC (sbxfi_devc_t * devc, sbxfi_portc_t * portc);
+void SetupPlayInputMapper (sbxfi_devc_t * devc, sbxfi_portc_t * portc);
+void StopPlay (sbxfi_devc_t * devc, sbxfi_portc_t * portc);
+
+void SetupRecordMixer (sbxfi_devc_t * devc, sbxfi_portc_t * portc);
+void SetupRecordFormat (sbxfi_devc_t * devc);
+void SetupAndStartRecordSRC (sbxfi_devc_t * devc, sbxfi_portc_t * portc);
+void StopRecordSRC (sbxfi_devc_t * devc, sbxfi_portc_t * portc);
+void SetupRecordInputMapper (sbxfi_devc_t * devc, sbxfi_portc_t * portc);
+void SetupInputToOutputMonitoring (sbxfi_devc_t * devc,
+ sbxfi_portc_t * portc);
+
+void _dumpRegisters (sbxfi_devc_t * devc, sbxfi_portc_t * portc);
+void _dumpSRCs (sbxfi_devc_t * devc, sbxfi_portc_t * portc);
+void _dumpGlobal (sbxfi_devc_t * devc);
+
+#define osDelayms(usecs) oss_udelay(usecs)
+#define osInportd(devc, ioaddr) INL(devc->osdev, ioaddr)
+#define osOutportd(devc, ioaddr, data) OUTL(devc->osdev, data, ioaddr)
+
+#endif
diff --git a/kernel/drv/oss_sbxfi/oss_sbxfi.c b/kernel/drv/oss_sbxfi/oss_sbxfi.c
new file mode 100644
index 0000000..837ab33
--- /dev/null
+++ b/kernel/drv/oss_sbxfi/oss_sbxfi.c
@@ -0,0 +1,1078 @@
+/*
+ * Purpose: Driver for Sound Blaster X-Fi (emu20k)
+ *
+ */
+
+/*
+ *
+ * This file is part of Open Sound System.
+ *
+ * Copyright (C) 4Front Technologies 1996-2008.
+ *
+ * This this source file is released under GPL v2 license (no other versions).
+ * See the COPYING file included in the main directory of this source
+ * distribution for the license terms and conditions.
+ *
+ */
+
+#include "oss_sbxfi_cfg.h"
+#include <oss_pci.h>
+#include "sbxfi.h"
+#include "20k1reg.h"
+#include "hwaccess.h"
+
+#define PCI_VENDOR_CREATIVE 0x1102
+#define CREATIVE_SBXFI_K1 0x0005
+#define CREATIVE_SBXFI_K2 0x000b
+#define CREATIVE_SBXFI_E 0x0009
+
+#define TIMER_INTERVAL 5 /* In milliseconds */
+
+#define DEFAULT_PLAY_RATE 96000 /* Default rate of play devices */
+#define DEFAULT_REC_RATE 96000 /* Default rate of rec devices */
+#define HARDWARE_RATE 96000 /* Internal rate used by the hardware */
+
+static void
+set_interval_timer(sbxfi_devc_t *devc, int msecs)
+{
+ int tic = (HARDWARE_RATE*msecs)/1000;
+
+ HwWrite20K1 (devc, TIMR, tic | TIMR_IE|TIMR_IP);
+}
+
+static int
+sbxfi_intr(oss_device_t *osdev)
+{
+ unsigned int status;
+ sbxfi_devc_t *devc = osdev->devc;
+
+ status = HwRead20K1 (devc, GIP);
+
+ if (status==0) /* Not for me */
+ return 0;
+
+ devc->interrupt_count++;
+
+#if 0
+ // Not using loop interrupts.
+ if (status & SRC_INT) /* SRC interrupt(s) pending */
+ {
+ unsigned int srcipm, srcip;
+ int i;
+
+ srcipm = HwRead20K1 (devc, SRCIPM); /* SRC interrupt pending map register */
+
+ for (i=0;i<7;i++)
+ if (srcipm & (1<<i))
+ {
+ int j;
+ srcip = HwRead20K1 (devc, SRCIP(i)); /* SRC interrupt pending register for block(i) */
+
+ for (j=0;j<32;j++)
+ if (srcip & (1<<j))
+ {
+ int chn=i*32+j;
+ sbxfi_portc_t *portc;
+
+ portc=devc->src_to_portc[chn];
+
+ if (portc==NULL)
+ {
+ cmn_err(CE_NOTE, "portc==NULL\n");
+ continue;
+ }
+
+ oss_audio_outputintr(portc->dev, 0);
+ }
+
+ HwWrite20K1 (devc, SRCIP(i), srcip); /* Acknowledge SRC interrupts for block(i) */
+ }
+ }
+#endif
+
+ if (status & IT_INT)
+ {
+ /*
+ * Interval timer interrupt
+ */
+ sbxfi_portc_t *portc;
+ int i;
+
+ for (i=0;i<devc->nr_outdevs;i++)
+ {
+ portc=&devc->play_portc[i];
+ if (portc->running)
+ oss_audio_outputintr(portc->dev, 0);
+ }
+
+ for (i=0;i<devc->nr_indevs;i++)
+ {
+ portc=&devc->rec_portc[i];
+ if (portc->running)
+ oss_audio_inputintr(portc->dev, 0);
+ }
+
+ set_interval_timer(devc, TIMER_INTERVAL); /* Rearm interval timer */
+ }
+
+ HwWrite20K1 (devc, GIP, status & FI_INT); /* Acknowledge interrupts */
+ return 1;
+}
+
+ /*ARGSUSED*/ static int
+sbxfi_mixer_ioctl (int dev, int audiodev, unsigned int cmd, ioctl_arg arg)
+{
+ return OSS_EINVAL;
+}
+
+static mixer_driver_t sbxfi_mixer_driver = {
+ sbxfi_mixer_ioctl
+};
+
+static int
+sbxfi_set_rate (int dev, int arg)
+{
+ sbxfi_devc_t *devc = audio_engines[dev]->devc;
+ sbxfi_portc_t *portc = audio_engines[dev]->portc;
+ oss_native_word flags;
+
+ MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
+#if 0
+ // TODO: Implement support for other rates
+
+ if (arg == 0)
+ {
+ MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
+ return portc->rate;
+ }
+
+#else
+ if (portc->direction == PCM_ENABLE_OUTPUT)
+ arg=DEFAULT_PLAY_RATE;
+ else
+ arg=DEFAULT_REC_RATE;
+#endif
+ MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
+ return portc->rate = arg;
+}
+
+static short
+sbxfi_set_channels (int dev, short arg)
+{
+ sbxfi_portc_t *portc = audio_engines[dev]->portc;
+
+ if (arg == 0)
+ return portc->channels;
+
+ if (arg<2)
+ arg=2;
+ else
+ if (arg > MAX_PLAY_CHANNELS)
+ arg = MAX_PLAY_CHANNELS;
+ arg &= ~1; /* Even number of channels */
+
+ return portc->channels = arg;
+}
+
+static unsigned int
+sbxfi_set_format (int dev, unsigned int arg)
+{
+ sbxfi_portc_t *portc = audio_engines[dev]->portc;
+
+ if (arg == 0)
+ return portc->fmt;
+
+ return portc->fmt = SUPPORTED_FORMAT;
+}
+
+static int
+sbxfi_ioctl (int dev, unsigned int cmd, ioctl_arg arg)
+{
+ //sbxfi_portc_t *portc = audio_engines[dev]->portc;
+ //sbxfi_devc_t *devc = audio_engines[dev]->devc;
+
+ return OSS_EINVAL;
+}
+
+static void sbxfi_trigger (int dev, int state);
+
+static void
+sbxfi_reset (int dev)
+{
+ sbxfi_trigger (dev, 0);
+}
+
+ /*ARGSUSED*/ static int
+sbxfi_open_input (int dev, int mode, int open_flags)
+{
+ sbxfi_portc_t *portc = audio_engines[dev]->portc;
+ sbxfi_devc_t *devc = audio_engines[dev]->devc;
+ adev_p adev = audio_engines[dev];
+ oss_native_word flags;
+
+ if (mode & OPEN_WRITE)
+ {
+ cmn_err (CE_CONT, "Playback is not possible with %s\n", adev->devnode);
+ return OSS_ENOTSUP;
+ }
+
+ MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
+
+ if (portc->open_mode)
+ {
+ MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
+ return OSS_EBUSY;
+ }
+ portc->open_mode = mode;
+
+ MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
+ return 0;
+}
+
+ /*ARGSUSED*/ static int
+sbxfi_open_output (int dev, int mode, int open_flags)
+{
+ sbxfi_portc_t *portc = audio_engines[dev]->portc;
+ sbxfi_devc_t *devc = audio_engines[dev]->devc;
+ oss_native_word flags;
+ adev_p adev = audio_engines[dev];
+
+ if (mode == OPEN_READ)
+ {
+ cmn_err (CE_CONT, "Recording is not possible with %s\n", adev->devnode);
+ return OSS_ENOTSUP;
+ }
+
+ MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
+
+ if (portc->open_mode)
+ {
+ MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
+ return OSS_EBUSY;
+ }
+
+ portc->open_mode = mode;
+
+ MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
+ return 0;
+}
+
+static void
+sbxfi_close (int dev, int mode)
+{
+ sbxfi_portc_t *portc = audio_engines[dev]->portc;
+ sbxfi_devc_t *devc = audio_engines[dev]->devc;
+ oss_native_word flags;
+
+ MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
+
+ portc->open_mode = 0;
+
+ MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
+}
+
+ /*ARGSUSED*/ static void
+sbxfi_output_block (int dev, oss_native_word buf, int count, int fragsize,
+ int intrflag)
+{
+}
+
+ /*ARGSUSED*/ static void
+sbxfi_start_input (int dev, oss_native_word buf, int count, int fragsize,
+ int intrflag)
+{
+}
+
+static void
+sbxfi_trigger (int dev, int state)
+{
+ sbxfi_devc_t *devc = audio_engines[dev]->devc;
+ sbxfi_portc_t *portc = audio_engines[dev]->portc;
+ oss_native_word flags;
+
+ MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
+
+ if (portc->state_bits == state) /* No change */
+ {
+ MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
+ return;
+ }
+ portc->state_bits = state;
+
+ if (portc->direction == PCM_ENABLE_OUTPUT)
+ if (portc->open_mode & OPEN_WRITE)
+ {
+ if (state & PCM_ENABLE_OUTPUT)
+ {
+ SetupAndStartPlaySRC (devc, portc);
+ portc->running=1;
+ }
+ else
+ {
+ StopPlaySRC (devc, portc);
+ portc->running=0;
+ }
+ }
+
+ if (portc->direction == PCM_ENABLE_INPUT)
+ if (portc->open_mode & OPEN_READ)
+ {
+ if (state & PCM_ENABLE_INPUT)
+ {
+ SetupAndStartRecordSRC (devc, portc);
+ portc->running=1;
+ }
+ else
+ {
+ StopRecordSRC (devc, portc);
+ portc->running=0;
+ }
+ }
+
+ MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
+}
+
+ /*ARGSUSED*/ static int
+sbxfi_prepare_for_input (int dev, int bsize, int bcount)
+{
+ sbxfi_devc_t *devc = audio_engines[dev]->devc;
+ sbxfi_portc_t *portc = audio_engines[dev]->portc;
+ dmap_p dmap = audio_engines[dev]->dmap_in;
+ oss_native_word flags;
+ int i;
+
+ if (audio_engines[dev]->flags & ADEV_NOINPUT)
+ return OSS_EACCES;
+
+ MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
+
+ // Fill record buffer to the page table entries.
+ // This need to sync up with setting SRCs start addx
+ for (i=0;i<(bsize*bcount)/4096;i++)
+ devc->pdwPageTable[portc->pgtable_index+i] = dmap->dmabuf_phys + (i*4096);
+
+ InitADC (devc, portc->dwDAChan[0], FALSE);
+
+ // Program input mapper
+ SetupRecordInputMapper (devc, portc);
+
+ // Program I2S
+ SetupRecordFormat (devc);
+ SetupRecordMixer (devc, portc);
+
+ MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
+
+ return 0;
+}
+
+ /*ARGSUSED*/ static int
+sbxfi_prepare_for_output (int dev, int bsize, int bcount)
+{
+ sbxfi_devc_t *devc = audio_engines[dev]->devc;
+ sbxfi_portc_t *portc = audio_engines[dev]->portc;
+ dmap_p dmap = audio_engines[dev]->dmap_out;
+ oss_native_word flags;
+ int i;
+
+ if (audio_engines[dev]->flags & ADEV_NOOUTPUT)
+ return OSS_EACCES;
+
+ MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
+
+ // Fill play buffer to the page table entries.
+ // This need to sync up with setting SRCs start addx
+ for (i=0;i<(bsize*bcount)/4096;i++)
+ devc->pdwPageTable[portc->pgtable_index+i] = dmap->dmabuf_phys + (i*4096);
+
+ InitDAC (devc, portc);
+
+ // Program I2S
+ SetupPlayFormat (devc, portc);
+ SetupPlayMixer (devc, portc);
+
+ // Program input mapper
+ SetupPlayInputMapper (devc, portc);
+
+ MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
+
+ return 0;
+}
+
+/*ARGSUSED*/
+static int
+sbxfi_get_buffer_pointer (int dev, dmap_t * dmap, int direction)
+{
+ sbxfi_devc_t *devc = audio_engines[dev]->devc;
+ sbxfi_portc_t *portc = audio_engines[dev]->portc;
+ int pos;
+
+ pos = HwRead20K1 (devc, SRCCA(portc->SrcChan)) & 0x03ffffff;
+
+ if (pos>=128)
+ pos -= 128; /* The pointer is always 128 bytes ahead */
+
+ pos -= portc->pgtable_index*4096;
+
+ return pos;
+}
+
+static audiodrv_t sbxfi_output_driver = {
+ sbxfi_open_output,
+ sbxfi_close,
+ sbxfi_output_block,
+ sbxfi_start_input,
+ sbxfi_ioctl,
+ sbxfi_prepare_for_input,
+ sbxfi_prepare_for_output,
+ sbxfi_reset,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ sbxfi_trigger,
+ sbxfi_set_rate,
+ sbxfi_set_format,
+ sbxfi_set_channels,
+ NULL,
+ NULL,
+ NULL, /* check input */
+ NULL, /* sbxfi_check_output */
+ NULL, /* sbxfi_alloc_buffer */
+ NULL, /* sbxfi_free_buffer */
+ NULL,
+ NULL,
+ sbxfi_get_buffer_pointer
+};
+
+static audiodrv_t sbxfi_input_driver = {
+ sbxfi_open_input,
+ sbxfi_close,
+ sbxfi_output_block,
+ sbxfi_start_input,
+ sbxfi_ioctl,
+ sbxfi_prepare_for_input,
+ sbxfi_prepare_for_output,
+ sbxfi_reset,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ sbxfi_trigger,
+ sbxfi_set_rate,
+ sbxfi_set_format,
+ sbxfi_set_channels,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL, /* sbxfi_alloc_buffer */
+ NULL, /* sbxfi_free_buffer */
+ NULL,
+ NULL,
+ sbxfi_get_buffer_pointer
+};
+
+static int
+init_play_device (sbxfi_devc_t * devc,
+ char *name, int dev_flags)
+{
+ int opts, dev, formats;
+ char tmp[80];
+ sbxfi_portc_t *portc = NULL;
+ adev_p adev;
+
+ sprintf (tmp, "%s %s", devc->name, name);
+
+ if (devc->nr_outdevs > MAX_OUTPUTDEVS)
+ {
+ cmn_err (CE_CONT, "Too many audio devices\n");
+ return -1;
+ }
+
+ opts = ADEV_AUTOMODE | ADEV_NOINPUT;
+
+ formats = SUPPORTED_FORMAT;
+
+ if ((dev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION,
+ devc->osdev,
+ devc->osdev,
+ tmp,
+ &sbxfi_output_driver,
+ sizeof (audiodrv_t),
+ opts, formats, devc, -1)) < 0)
+ {
+ return -1;
+ }
+
+ if (devc->first_dev == -1)
+ {
+ devc->first_dev = dev;
+ }
+ adev = audio_engines[dev];
+
+ portc = &devc->play_portc[devc->nr_outdevs];
+
+ adev->portc = portc;
+ adev->devc = devc;
+ adev->mixer_dev = devc->mixer_dev;
+ adev->rate_source = devc->first_dev;
+ adev->min_rate = 48000;
+ adev->max_rate = 92600;
+ adev->min_block=4096;
+ adev->dmabuf_maxaddr = MEMLIMIT_ISA;
+
+ portc->dev = dev;
+ portc->open_mode = 0;
+ portc->fmt = SUPPORTED_FORMAT;
+ portc->dev_flags = dev_flags;
+ portc->state_bits = 0;
+ portc->direction = PCM_ENABLE_OUTPUT;
+
+ portc->rate = DEFAULT_PLAY_RATE;
+
+ // use the following SRC channels for Play
+ portc->SrcChan = devc->next_src;
+ devc->next_src += MAX_PLAY_CHANNELS;
+ devc->src_to_portc[portc->SrcChan]=portc;
+
+ portc->dwDAChan[0] = I2SA_L;
+ portc->dwDAChan[1] = I2SA_R;
+#if MAX_PLAY_CHANNELS>2
+ portc->dwDAChan[2] = I2SB_L;
+ portc->dwDAChan[3] = I2SB_R;
+ portc->dwDAChan[4] = I2SC_L;
+ portc->dwDAChan[5] = I2SC_R;
+#endif
+
+ portc->vol_left=portc->vol_right=MIXER_VOLSTEPS;
+
+ adev->min_channels = 2;
+ adev->max_channels = MAX_PLAY_CHANNELS;
+
+ portc->pgtable_index = devc->next_pg;
+ devc->next_pg += 128/4; // Up to 128k for buffer
+
+ devc->nr_outdevs++;
+
+ return dev;
+}
+
+static int
+init_rec_device (sbxfi_devc_t * devc,
+ char *name, int dev_flags)
+{
+ int opts, dev, formats;
+ char tmp[80];
+ sbxfi_portc_t *portc = NULL;
+ adev_p adev;
+
+ sprintf (tmp, "%s %s", devc->name, name);
+
+ if (devc->nr_indevs > MAX_INPUTDEVS)
+ {
+ cmn_err (CE_CONT, "Too many audio devices\n");
+ return -1;
+ }
+
+ opts = ADEV_AUTOMODE | ADEV_NOOUTPUT;
+
+ formats = SUPPORTED_FORMAT;
+
+ if ((dev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION,
+ devc->osdev,
+ devc->osdev,
+ tmp,
+ &sbxfi_input_driver,
+ sizeof (audiodrv_t),
+ opts, formats, devc, -1)) < 0)
+ {
+ return -1;
+ }
+
+ if (devc->first_dev == -1)
+ {
+ devc->first_dev = dev;
+ }
+ adev = audio_engines[dev];
+
+ portc = &devc->rec_portc[devc->nr_indevs];
+
+ adev->portc = portc;
+ adev->devc = devc;
+ adev->mixer_dev = devc->mixer_dev;
+ adev->rate_source = devc->first_dev;
+ adev->min_rate = 48000;
+ adev->max_rate = 96000;
+ adev->min_block=4096;
+ adev->dmabuf_maxaddr = MEMLIMIT_ISA;
+
+ portc->dev = dev;
+ portc->open_mode = 0;
+ portc->fmt = SUPPORTED_FORMAT;
+ portc->dev_flags = dev_flags;
+ portc->state_bits = 0;
+ portc->direction = PCM_ENABLE_INPUT;
+
+ portc->rate = DEFAULT_REC_RATE;
+
+ // use the following SRC channels for record
+ portc->SrcChan = devc->next_src;
+ devc->next_src += 2;
+ devc->src_to_portc[portc->SrcChan]=portc;
+
+ portc->dwDAChan[0] = ADC_SRC_LINEIN;
+
+ portc->vol_left=portc->vol_right=MIXER_VOLSTEPS;
+
+ adev->min_channels = 2;
+ adev->max_channels = 2;
+
+ portc->pgtable_index = devc->next_pg;
+ devc->next_pg += 128/4; // Up to 128k for buffer
+
+ devc->nr_indevs++;
+
+ return dev;
+}
+
+static int
+sbxfi_set_playvol (int dev, int ctrl, unsigned int cmd, int value)
+{
+ sbxfi_devc_t *devc = mixer_devs[dev]->devc;
+ sbxfi_portc_t *portc;
+ int left, right;
+
+ if (ctrl<0 || ctrl >= devc->nr_outdevs)
+ return OSS_ENXIO;
+ portc = &devc->play_portc[ctrl];
+
+ if (cmd == SNDCTL_MIX_READ)
+ {
+ return portc->vol_left | (portc->vol_right << 16);
+ }
+
+ if (cmd == SNDCTL_MIX_WRITE)
+ {
+ left = value & 0xffff;
+ right = (value>>16) & 0xffff;
+
+ if (left > MIXER_VOLSTEPS)
+ left=MIXER_VOLSTEPS;
+ if (right > MIXER_VOLSTEPS)
+ right=MIXER_VOLSTEPS;
+
+ portc->vol_left=left;
+ portc->vol_right=right;
+ if (portc->running)
+ SetupPlayMixer(devc, portc);
+
+ return portc->vol_left | (portc->vol_right << 16);
+ }
+
+ return OSS_EINVAL;
+}
+
+static int
+sbxfi_set_recvol (int dev, int ctrl, unsigned int cmd, int value)
+{
+ sbxfi_devc_t *devc = mixer_devs[dev]->devc;
+ sbxfi_portc_t *portc;
+ int left, right;
+
+ if (ctrl<0 || ctrl >= devc->nr_indevs)
+ return OSS_ENXIO;
+ portc = &devc->rec_portc[ctrl];
+
+ if (cmd == SNDCTL_MIX_READ)
+ {
+ return portc->vol_left | (portc->vol_right << 16);
+ }
+
+ if (cmd == SNDCTL_MIX_WRITE)
+ {
+ left = value & 0xffff;
+ right = (value>>16) & 0xffff;
+
+ if (left > MIXER_VOLSTEPS)
+ left=MIXER_VOLSTEPS;
+ if (right > MIXER_VOLSTEPS)
+ right=MIXER_VOLSTEPS;
+
+ portc->vol_left=left;
+ portc->vol_right=right;
+ if (portc->running)
+ SetupRecordMixer(devc, portc);
+
+ return portc->vol_left | (portc->vol_right << 16);
+ }
+
+ return OSS_EINVAL;
+}
+
+static int
+sbxfi_set_recsrc (int dev, int ctrl, unsigned int cmd, int value)
+{
+ sbxfi_devc_t *devc = mixer_devs[dev]->devc;
+ sbxfi_portc_t *portc;
+
+ if (ctrl<0 || ctrl >= devc->nr_indevs)
+ return OSS_ENXIO;
+ portc = &devc->rec_portc[ctrl];
+
+ if (cmd == SNDCTL_MIX_READ)
+ {
+ return portc->dwDAChan[0];
+ }
+
+ if (cmd == SNDCTL_MIX_WRITE)
+ {
+ if (value<0 || value>ADC_SRC_NONE)
+ return portc->dwDAChan[0];
+
+ return portc->dwDAChan[0]=value;
+ }
+
+ return OSS_EINVAL;
+}
+
+static int
+sbxfi_mix_init (int dev)
+{
+ int root=0, ctl;
+
+ if ((ctl = mixer_ext_create_control (dev, root,
+ 0, sbxfi_set_playvol,
+ MIXT_STEREOSLIDER16,
+ "play", MIXER_VOLSTEPS,
+ MIXF_PCMVOL | MIXF_READABLE |
+ MIXF_WRITEABLE | MIXF_CENTIBEL)) <
+ 0)
+ return ctl;
+
+ if ((ctl = mixer_ext_create_control (dev, root,
+ 0, sbxfi_set_recvol,
+ MIXT_STEREOSLIDER16,
+ "rec", MIXER_VOLSTEPS,
+ MIXF_RECVOL | MIXF_READABLE |
+ MIXF_WRITEABLE | MIXF_CENTIBEL)) <
+ 0)
+ return ctl;
+
+ if ((ctl = mixer_ext_create_control (dev, root,
+ 0, sbxfi_set_recsrc,
+ MIXT_ENUM,
+ "recsrc", 5,
+ MIXF_READABLE |
+ MIXF_WRITEABLE | MIXF_CENTIBEL)) <
+ 0)
+ return ctl;
+
+ mixer_ext_set_strings (dev, ctl, "mic line video aux none", 0);
+
+ return 0;
+}
+
+int
+oss_sbxfi_attach (oss_device_t * osdev)
+{
+ unsigned short pci_command, vendor, device, revision;
+ unsigned short subvendor, subdevice;
+ int pdev, rdev;
+ extern int sbxfi_type;
+
+ sbxfi_devc_t *devc;
+ sbxfi_portc_t *portc;
+
+ if ((devc = PMALLOC (osdev, sizeof (*devc))) == NULL)
+ {
+ cmn_err (CE_WARN, "Out of memory\n");
+ return 0;
+ }
+
+ memset (devc, 0, sizeof (*devc));
+
+ portc = &devc->play_portc[0];
+
+ devc->osdev = osdev;
+ osdev->devc = devc;
+ devc->name = "Sound Blaster X-Fi";
+
+ pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor);
+ pci_read_config_word (osdev, PCI_DEVICE_ID, &device);
+
+ DDB (cmn_err
+ (CE_CONT, "oss_sbxfi_attach(Vendor %x, device %x)\n", vendor, device));
+
+ if (vendor != PCI_VENDOR_CREATIVE ||
+ (device != CREATIVE_SBXFI_K1 && device != CREATIVE_SBXFI_K2 &&
+ device != CREATIVE_SBXFI_E))
+ {
+ cmn_err (CE_WARN, "Hardware not recognized (vendor=%x, dev=%x)\n",
+ vendor, device);
+ return 0;
+ }
+ MUTEX_INIT (osdev, devc->mutex, MH_DRV);
+ MUTEX_INIT (osdev, devc->low_mutex, MH_DRV + 1);
+
+ pci_read_config_word (osdev, PCI_SUBSYSTEM_VENDOR_ID, &subvendor);
+ pci_read_config_word (osdev, PCI_SUBSYSTEM_ID, &subdevice);
+ pci_read_config_word (osdev, PCI_REVISION_ID, &revision);
+
+ devc->wVendorID = vendor;
+ devc->wDeviceID = device;
+ devc->wSubsystemVendorID = subvendor;
+ devc->wSubsystemID = subdevice;
+ devc->wChipRevision = revision;
+
+ switch (sbxfi_type)
+ {
+ case 1:
+ devc->name = "Sound Blaster X-Fi (SB046x/067x/076x)";
+ devc->hw_family = HW_ORIG;
+ break;
+
+ case 2:
+ devc->name = "Sound Blaster X-Fi (SB073x)";
+ devc->hw_family = HW_073x;
+ break;
+
+ case 3:
+ devc->name = "Sound Blaster X-Fi (SB055x)";
+ devc->hw_family = HW_055x;
+ break;
+
+ case 4:
+ devc->name = "Sound Blaster X-Fi (UAA)";
+ devc->hw_family = HW_UAA;
+ break;
+
+ case 5:
+ devc->name = "Sound Blaster X-Fi (SB076x)";
+ devc->hw_family = HW_0760;
+ break;
+
+ case 6:
+ devc->name = "Sound Blaster X-Fi (SB0880-1)";
+ devc->hw_family = HW_08801;
+ break;
+
+ case 7:
+ devc->name = "Sound Blaster X-Fi (SB0880-2)";
+ devc->hw_family = HW_08802;
+ break;
+
+ case 8:
+ devc->name = "Sound Blaster X-Fi (SB0880-3)";
+ devc->hw_family = HW_08803;
+ break;
+
+ case 0:
+ default:
+ devc->hw_family = 0;
+ break;
+ }
+
+ if (!devc->hw_family && device == CREATIVE_SBXFI_K1) // EMU20K1 models
+ switch (subdevice)
+ {
+ case 0x0021: /* SB0460 */
+ case 0x0023:
+ case 0x0024:
+ case 0x0025:
+ case 0x0026:
+ case 0x0027:
+ case 0x0028:
+ case 0x002a:
+ case 0x002b:
+ case 0x002c:
+ case 0x002d:
+ case 0x002e:
+ case 0x0032:
+ case 0x0033:
+ case 0x0034: /* This is actually Auzentech Prelude (subvendor 415a) */
+ /*
+ * Original X-Fi hardware revision (SB046x/067x/076x)
+ */
+ devc->name = "Sound Blaster X-Fi (SB046x/067x/076x)";
+ devc->hw_family = HW_ORIG;
+ break;
+
+ case 0x0029:
+ case 0x0031:
+ devc->name = "Sound Blaster X-Fi (SB073x)";
+ devc->hw_family = HW_073x;
+ break;
+
+ case 0x0022:
+ case 0x002f:
+ devc->name = "Sound Blaster X-Fi (SB055x)";
+ devc->hw_family = HW_055x;
+ break;
+
+ default:
+ if (subdevice >= 0x6000 && subdevice <= 0x6fff) /* "Vista compatible" HW */
+ {
+ devc->name = "Sound Blaster X-Fi (UAA)";
+ devc->hw_family = HW_UAA;
+ }
+ }
+
+ if (!devc->hw_family && device == CREATIVE_SBXFI_K2) // EMU 20K2 models
+ switch (subdevice)
+ {
+ case PCI_SUBDEVICE_ID_CREATIVE_SB0760:
+ devc->name = "Sound Blaster X-Fi (SB076x)";
+ devc->hw_family = HW_0760;
+ break;
+
+ case PCI_SUBDEVICE_ID_CREATIVE_SB08801:
+ devc->name = "Sound Blaster X-Fi (SB0880-1)";
+ devc->hw_family = HW_08801;
+ break;
+
+ case PCI_SUBDEVICE_ID_CREATIVE_SB08802:
+ devc->name = "Sound Blaster X-Fi (SB0880-2)";
+ devc->hw_family = HW_08802;
+ break;
+
+ case PCI_SUBDEVICE_ID_CREATIVE_SB08803:
+ devc->name = "Sound Blaster X-Fi (SB0880-3)";
+ devc->hw_family = HW_08803;
+ break;
+
+ default:
+ devc->name = "Sound Blaster X-Fi (20K2)";
+ devc->hw_family = HW_UAA; // Just a wild guess
+ }
+
+ if (!devc->hw_family && device == CREATIVE_SBXFI_E) // PCI-e models
+ {
+ devc->name = "Sound Blaster X-Fi (PCI-e)";
+ devc->hw_family = HW_UAA; // Just a wild guess
+ }
+
+
+#if 1
+// Temporary hacking until proper 20K2 support is in place
+ if (devc->hw_family > HW_UAA) devc->hw_family = HW_UAA;
+#endif
+
+ oss_register_device (osdev, devc->name);
+
+ pci_read_config_word (osdev, PCI_COMMAND, &pci_command);
+ pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
+ pci_write_config_word (osdev, PCI_COMMAND, pci_command);
+
+ if ((osdev->hw_info = PMALLOC (osdev, 200)) != NULL)
+ {
+ sprintf (osdev->hw_info, "PCI device %04x:%04x, subdevice %04x:%04x\n",
+ vendor, device, subvendor, subdevice);
+ }
+
+ devc->interrupt_count=0;
+ if (oss_register_interrupts (devc->osdev, 0, sbxfi_intr, NULL) < 0)
+ {
+ cmn_err (CE_WARN, "Unable to install interrupt handler\n");
+ return 0;
+ }
+
+ // Detect and Configure X-Fi PCI config space.
+ // Obtain the resource configuration from PCI config space.
+ if (!DetectAndConfigureHardware (devc))
+ {
+ cmn_err (CE_WARN, "Cannot configure X-Fi hardware...\n");
+ return 0;
+ }
+
+ if (IsVistaCompatibleHardware (devc))
+ {
+ // Switch to audio core to X-Fi core.
+ SwitchToXFiCore (devc);
+ }
+
+ // Initialize hardware. This include setup the PLL etc.
+ if (InitHardware (devc) != CTSTATUS_SUCCESS)
+ {
+ cmn_err (CE_WARN, "Init Hardware failed...\n");
+ return 0;
+ }
+
+ devc->dwPageTableSize = 1024; /* For up to 4M of memory */
+ devc->pdwPageTable = CONTIG_MALLOC (devc->osdev,
+ devc->dwPageTableSize,
+ MEMLIMIT_ISA, &devc->dwPTBPhysAddx, devc->pgtable_dma_handle);
+
+ HwWrite20K1 (devc, PTPALX, devc->dwPTBPhysAddx);
+ HwWrite20K1 (devc, PTPAHX, 0);
+
+ HwWrite20K1 (devc, TRNCTL, 0x13);
+ HwWrite20K1 (devc, TRNIS, 0x200c01);
+
+ HwWrite20K1 (devc, GIE, FI_INT); /* Enable "forced" interrupts */
+ HwWrite20K1 (devc, GIP, FI_INT); /* Trigger forced interrupt */
+
+ oss_udelay(1000);
+ if (devc->interrupt_count==0)
+ cmn_err(CE_WARN, "Interrupts don't seem to be working.\n");
+
+ set_interval_timer(devc, TIMER_INTERVAL);
+
+/*
+ * Disable FI and enable selected global interrupts
+ * (SRC, Interval Timer).
+ */
+ HwWrite20K1 (devc, GIE, SRC_INT | IT_INT);
+
+ if ((devc->mixer_dev = oss_install_mixer (OSS_MIXER_DRIVER_VERSION,
+ devc->osdev,
+ devc->osdev,
+ devc->name,
+ &sbxfi_mixer_driver,
+ sizeof (mixer_driver_t),
+ devc)) >= 0)
+ {
+ mixer_devs[devc->mixer_dev]->hw_devc = devc;
+ mixer_devs[devc->mixer_dev]->priority = 1; /* Possible default mixer candidate */
+ mixer_ext_set_init_fn (devc->mixer_dev, sbxfi_mix_init, 10);
+ }
+
+ devc->first_dev=-1; /* Not assigned */
+ pdev = init_play_device (devc, "output", 0);
+ rdev = init_rec_device (devc, "input", 0);
+#ifdef CONFIG_OSS_VMIX
+ if (pdev != -1)
+ {
+ vmix_attach_audiodev (devc->osdev, pdev, rdev, 0);
+ }
+#endif
+
+#if 0
+ // Initialize ADC
+ InitADC (devc, ADC_SRC_LINEIN, FALSE);
+#endif
+
+ return 1;
+}
+
+int
+oss_sbxfi_detach (oss_device_t * osdev)
+{
+ sbxfi_devc_t *devc = (sbxfi_devc_t *) osdev->devc;
+
+ if (oss_disable_device (osdev) < 0)
+ return 0;
+
+ HwWrite20K1 (devc, GIE, 0); /* Disable global interrupts */
+ oss_unregister_interrupts (devc->osdev);
+
+ HwWrite20K1 (devc, PTPALX, 0);
+ if (devc->pdwPageTable != NULL)
+ {
+ CONTIG_FREE (devc->osdev, devc->pdwPageTable, devc->dwPageTableSize, devc->pgtable_dma_handle);
+ devc->pdwPageTable = NULL;
+ }
+ oss_unregister_device (osdev);
+ MUTEX_CLEANUP (devc->mutex);
+ MUTEX_CLEANUP (devc->low_mutex);
+ return 1;
+}
diff --git a/kernel/drv/oss_sbxfi/oss_sbxfi.man b/kernel/drv/oss_sbxfi/oss_sbxfi.man
new file mode 100644
index 0000000..a1f10bd
--- /dev/null
+++ b/kernel/drv/oss_sbxfi/oss_sbxfi.man
@@ -0,0 +1,20 @@
+NAME
+oss_sbxfi - SoundBlaster X-Fi audio driver
+
+DESCRIPTION
+Open Sound System driver for the SoundBlaster X-Fi cards.
+
+OPTIONS
+o sbxfi_type Override X-Fi type autodetection. Values:
+ 0 - Autodetect type
+ 1 - Sound Blaster X-Fi (SB046x/067x/076x)
+ 2 - Sound Blaster X-Fi (SB073x)
+ 3 - Sound Blaster X-Fi (SB055x)
+ 4 - Sound Blaster X-Fi (UAA)
+ Default : 0.
+
+FILES
+CONFIGFILEPATH/oss_sbxfi.conf Device configuration file.
+
+AUTHOR
+4Front Technologies
diff --git a/kernel/drv/oss_sbxfi/sbxfi.h b/kernel/drv/oss_sbxfi/sbxfi.h
new file mode 100644
index 0000000..dfb529f
--- /dev/null
+++ b/kernel/drv/oss_sbxfi/sbxfi.h
@@ -0,0 +1,166 @@
+/*
+ *
+ * This file is part of Open Sound System.
+ *
+ * Copyright (C) 4Front Technologies 1996-2008.
+ *
+ * This this source file is released under GPL v2 license (no other versions).
+ * See the COPYING file included in the main directory of this source
+ * distribution for the license terms and conditions.
+ *
+ */
+
+#define PCI_SUBDEVICE_ID_CREATIVE_SB0760 0x0024
+#define PCI_SUBDEVICE_ID_CREATIVE_SB08801 0x0041
+#define PCI_SUBDEVICE_ID_CREATIVE_SB08802 0x0042
+#define PCI_SUBDEVICE_ID_CREATIVE_SB08803 0x0043
+
+#define MAX_OUTPUTDEVS 1
+#define MAX_INPUTDEVS 1
+#define SUPPORTED_FORMAT (AFMT_S16_LE)
+
+#define MIXER_VOLSTEPS 144 /* Centibel steps */
+
+//#define MAX_PLAY_CHANNELS 6 /* Does not work */
+#define MAX_PLAY_CHANNELS 2
+
+#if 0
+typedef unsigned char CTBYTE, *PCTBYTE;
+typedef unsigned short unsigned short, *Punsigned short;
+typedef signed short CTSHORT, *PCTSHORT;
+typedef unsigned int unsigned int, *unsigned int *;
+typedef signed long CTLONG, *PCTLONG;
+typedef void CTVOID, *PCTVOID;
+typedef unsigned int CTBOOL, *PCTBOOL;
+typedef unsigned int CTUINT, *PCTUINT;
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+typedef unsigned int CTSTATUS;
+typedef oss_native_word IOADDR;
+
+enum GlobalErrorCode
+{
+ CTSTATUS_SUCCESS = 0x0000,
+ CTSTATUS_ERROR,
+ CTSTATUS_INVALIDPARAM,
+ CTSTATUS_NOTSUPPORTED,
+ CTSTATUS_NOMEMORY,
+ CTSTATUS_INVALIDIO,
+ CTSTATUS_INVALIDIRQ,
+ CTSTATUS_INVALIDDMA,
+ CTSTATUS_INVALIDID,
+ CTSTATUS_INVALIDVALUE,
+ CTSTATUS_BADFORMAT_BITS,
+ CTSTATUS_BADFORMAT_RATE,
+ CTSTATUS_BADFORMAT_CHANNELS,
+ CTSTATUS_INUSE,
+ CTSTATUS_STILLPLAYING,
+ CTSTATUS_ALLOCATED,
+ CTSTATUS_INVALID_FORMAT,
+ CTSTATUS_OUT_OF_RESOURCE,
+ CTSTATUS_CHIP_INUSE,
+ CTSTATUS_NOCHIPRESOURCE,
+ CTSTATUS_PORTS_INUSE,
+ CTSTATUS_EXIT,
+ CTSTATUS_FAILURE
+};
+
+
+#define ADC_SRC_MICIN 0x0
+#define ADC_SRC_LINEIN 0x1
+#define ADC_SRC_VIDEO 0x2
+#define ADC_SRC_AUX 0x3
+#define ADC_SRC_NONE 0x4
+
+typedef struct
+{
+ char *name;
+ int dev;
+ int open_mode;
+ int fmt;
+ int dev_flags;
+ int direction;
+ int state_bits;
+ int pgtable_index; // Pointer to the first page table entry
+
+ int running;
+
+ int channels;
+
+ unsigned int rate;
+
+ // Audio Ring resources
+ unsigned int SrcChan;
+
+ unsigned int dwDAChan[MAX_PLAY_CHANNELS];
+
+ // Play volumes
+ int vol_left, vol_right;
+} sbxfi_portc_t;
+
+typedef struct
+{
+ oss_device_t *osdev;
+ oss_mutex_t mutex;
+ oss_mutex_t low_mutex;
+
+ char *name;
+ int hw_family;
+
+// 20K1 models
+#define HW_ORIG 0x0001
+#define HW_073x 0x0002
+#define HW_055x 0x0004
+#define HW_UAA 0x0008
+
+// 20K2 models
+#define HW_0760 0x0010
+#define HW_08801 0x0020
+#define HW_08802 0x0040
+#define HW_08803 0x0080
+
+
+ unsigned int interrupt_count;
+
+ // Hardware IDs
+ unsigned short wVendorID;
+ unsigned short wDeviceID;
+ unsigned short wSubsystemVendorID;
+ unsigned short wSubsystemID;
+ unsigned short wChipRevision;
+
+ // Hardware Resources
+ unsigned int dwMemBase;
+ unsigned short wIOPortBase;
+
+ // Buffers
+ oss_native_word dwPTBPhysAddx;
+ unsigned int *pdwPageTable;
+ unsigned int dwPageTableSize;
+ oss_dma_handle_t pgtable_dma_handle;
+ int next_pg; /* Next free index in the page table */
+
+ sbxfi_portc_t play_portc[MAX_OUTPUTDEVS];
+ int nr_outdevs;
+
+ sbxfi_portc_t rec_portc[MAX_INPUTDEVS];
+ int nr_indevs;
+
+ // Mixer
+ int mixer_dev;
+
+ // Audio
+ int first_dev;
+
+ int next_src; // Next free SRC channel
+
+ sbxfi_portc_t *src_to_portc[256];
+} sbxfi_devc_t;
diff --git a/kernel/drv/oss_sbxfi/sbxfi_hwaccess.c b/kernel/drv/oss_sbxfi/sbxfi_hwaccess.c
new file mode 100644
index 0000000..4d4dad9
--- /dev/null
+++ b/kernel/drv/oss_sbxfi/sbxfi_hwaccess.c
@@ -0,0 +1,1391 @@
+/**
+*******************************************************************************
+Confidential & Proprietary
+Private & Confidential
+Creative Confidential
+*******************************************************************************
+*/
+/**
+*******************************************************************************
+Copyright (C) Creative Technology, Ltd., 2007. All rights reserved.
+*******************************************************************************
+**/
+#include "oss_sbxfi_cfg.h"
+#include <oss_pci.h>
+#include "sbxfi.h"
+#include "20k1reg.h"
+#include "hwaccess.h"
+
+static const int
+volume_table[MIXER_VOLSTEPS+1] =
+{
+ 0x0000000, 0x000010a, 0x0000110, 0x0000116, 0x000011d,
+ 0x0000124, 0x000012a, 0x0000131, 0x0000138, 0x0000140,
+ 0x0000147, 0x000014f, 0x0000157, 0x000015f, 0x0000167,
+ 0x000016f, 0x0000178, 0x0000180, 0x0000189, 0x0000193,
+ 0x000019c, 0x00001a6, 0x00001af, 0x00001b9, 0x00001c4,
+ 0x00001ce, 0x00001d9, 0x00001e4, 0x00001ef, 0x00001fb,
+ 0x0000207, 0x0000213, 0x000021f, 0x000022c, 0x0000239,
+ 0x0000246, 0x0000254, 0x0000262, 0x0000270, 0x000027e,
+ 0x000028d, 0x000029c, 0x00002ac, 0x00002bc, 0x00002cc,
+ 0x00002dd, 0x00002ee, 0x0000300, 0x0000311, 0x0000324,
+ 0x0000336, 0x000034a, 0x000035d, 0x0000371, 0x0000386,
+ 0x000039b, 0x00003b0, 0x00003c6, 0x00003dd, 0x00003f4,
+ 0x000040c, 0x0000424, 0x000043c, 0x0000456, 0x0000470,
+ 0x000048a, 0x00004a5, 0x00004c1, 0x00004dd, 0x00004fa,
+ 0x0000518, 0x0000536, 0x0000555, 0x0000575, 0x0000596,
+ 0x00005b7, 0x00005d9, 0x00005fc, 0x0000620, 0x0000644,
+ 0x000066a, 0x0000690, 0x00006b7, 0x00006df, 0x0000708,
+ 0x0000732, 0x000075d, 0x0000789, 0x00007b6, 0x00007e4,
+ 0x0000813, 0x0000843, 0x0000874, 0x00008a7, 0x00008da,
+ 0x000090f, 0x0000945, 0x000097c, 0x00009b5, 0x00009ef,
+ 0x0000a2a, 0x0000a67, 0x0000aa5, 0x0000ae4, 0x0000b25,
+ 0x0000b68, 0x0000bac, 0x0000bf1, 0x0000c38, 0x0000c81,
+ 0x0000ccc, 0x0000d18, 0x0000d66, 0x0000db6, 0x0000e08,
+ 0x0000e5c, 0x0000eb1, 0x0000f09, 0x0000f63, 0x0000fbe,
+ 0x000101c, 0x000107c, 0x00010df, 0x0001143, 0x00011aa,
+ 0x0001214, 0x000127f, 0x00012ee, 0x000135f, 0x00013d2,
+ 0x0001448, 0x00014c1, 0x000153d, 0x00015bc, 0x000163d,
+ 0x00016c2, 0x000174a, 0x00017d4, 0x0001863, 0x00018f4,
+ 0x0001989, 0x0001a21, 0x0001abd, 0x0001b5c, 0x0001c00
+};
+
+unsigned char
+DetectAndConfigureHardware (sbxfi_devc_t * devc)
+{
+ unsigned short wData;
+
+ // Default setting for hendrix card is memory access, so must get IO access port from bar5.
+ // bar0 will be converted to IO access in SwitchToXFiCore()
+ if (devc->hw_family == HW_UAA)
+ {
+ // Base IO address is at register lcoation 0x24 (bar5)
+ pci_read_config_word (devc->osdev, PCI_BASE_ADDRESS_5, &wData);
+ devc->wIOPortBase = wData & 0xFFFC;
+ }
+ else
+ {
+ // Get the IO base address
+ pci_read_config_word (devc->osdev, PCI_BASE_ADDRESS_0, &wData);
+ devc->wIOPortBase = wData & 0xFFFC;
+ }
+
+ return TRUE;
+}
+
+unsigned char
+IsVistaCompatibleHardware (sbxfi_devc_t * devc)
+{
+ // Check the subsystem id
+ if (devc->hw_family == HW_UAA)
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void
+SwitchToXFiCore (sbxfi_devc_t * devc)
+{
+ unsigned int bar0, bar1, bar2, bar3, bar4, bar5, irq, clSize, lTimer;
+
+ // program the hardware to X-Fi core.
+ // Check whether its hendrix card
+ // Save the previous memory/io address
+
+ pci_read_config_dword (devc->osdev, PCI_BASE_ADDRESS_0, &bar0);
+ pci_read_config_dword (devc->osdev, PCI_BASE_ADDRESS_1, &bar1);
+ pci_read_config_dword (devc->osdev, PCI_BASE_ADDRESS_2, &bar2);
+ pci_read_config_dword (devc->osdev, PCI_BASE_ADDRESS_3, &bar3);
+ pci_read_config_dword (devc->osdev, PCI_BASE_ADDRESS_4, &bar4);
+ pci_read_config_dword (devc->osdev, PCI_BASE_ADDRESS_5, &bar5);
+
+ pci_read_config_dword (devc->osdev, PCI_INTERRUPT_LINE, &irq);
+ pci_read_config_dword (devc->osdev, PCI_CFGHDR_CACHESIZE, &clSize);
+ pci_read_config_dword (devc->osdev, PCI_CFGHDR_LATENCY, &lTimer);
+
+ cmn_err (CE_CONT, "Switching to xfi core...\n");
+
+ // Switch to XFi core config space with BAR0
+ pci_write_config_dword (devc->osdev, 0xA0, 0x87654321);
+
+ // copy Base I/O address from UAA core to X-Fi core
+ pci_write_config_dword (devc->osdev, PCI_BASE_ADDRESS_5, bar5);
+
+ // Switch to XFi core config space without BAR0
+ pci_write_config_dword (devc->osdev, 0xA0, 0x12345678);
+
+ // copy all other setting from UAA config space to X-Fi config space
+ pci_write_config_dword (devc->osdev, PCI_BASE_ADDRESS_1, bar1);
+ pci_write_config_dword (devc->osdev, PCI_BASE_ADDRESS_2, bar2);
+ pci_write_config_dword (devc->osdev, PCI_BASE_ADDRESS_3, bar3);
+ pci_write_config_dword (devc->osdev, PCI_BASE_ADDRESS_4, bar4);
+
+ pci_write_config_dword (devc->osdev, PCI_INTERRUPT_LINE, irq);
+ pci_write_config_dword (devc->osdev, PCI_CFGHDR_CACHESIZE, clSize);
+ pci_write_config_dword (devc->osdev, PCI_CFGHDR_LATENCY, lTimer);
+
+ pci_write_config_dword (devc->osdev, PCI_CFGHDR_CMDREG, 0x07);
+
+ /*
+ NOTE:
+ The steps below is needed to switch the control signals to X-Fi core.
+
+ It needs to access the mode change register which reside in the UAA core BAR0 + 0x00003ffc.
+ Since this demo sample is a real-mode DOS program, it will need other services such as XMS to access
+ memory above 1MB.
+
+ Here is the pseudo code:
+
+ WriteMemory((bar0 + 0x00003ffc),0x43544c58); // CTLX
+ WriteMemory((bar0 + 0x00003ffc),0x43544c2d); // CTL-
+ WriteMemory((bar0 + 0x00003ffc),0x43544c46); // CTLF
+ WriteMemory((bar0 + 0x00003ffc),0x43544c69); // CTLi
+ */
+}
+
+
+CTSTATUS
+InitHardware (sbxfi_devc_t * devc)
+{
+ unsigned int gctlorg;
+ unsigned int dwIterCount, dwData;
+
+
+ // kick in auto-init
+ gctlorg = HwRead20K1 (devc, GCTL);
+ HwWrite20K1 (devc, GCTL, (~0x2 & gctlorg));
+ HwWrite20K1 (devc, GCTL, (0x2 | gctlorg));
+ osDelayms (1000);
+ // poll for AID in GCTL to be set
+ dwIterCount = 0x400000;
+ do
+ {
+ dwData = HwRead20K1 (devc, GCTL);
+ }
+ while (!(dwData & 0x00100000) && --dwIterCount);
+
+ // AID bit is not set when time out, return failure.
+ if (!(dwData & 0x00100000))
+ return CTSTATUS_ERROR;
+
+ gctlorg = HwRead20K1 (devc, GCTL);
+ HwWrite20K1 (devc, GCTL, (0x100aa3 | gctlorg));
+ osDelayms (10000);
+
+ HwWrite20K1 (devc, GIE, 0);
+ HwWrite20K1 (devc, SRCIP(0), 0);
+ osDelayms (30000);
+
+ if (((HwRead20K1 (devc, PLLCTL)) != 0x1480a001)
+ && ((HwRead20K1 (devc, PLLCTL)) != 0x1480a731))
+ {
+ HwWrite20K1 (devc, PLLCTL, 0x1480a001);
+ }
+ osDelayms (40000);
+ dwData = HwRead20K1 (devc, PLLCTL);
+
+ // configure GPIO per the card's family.
+ switch (devc->hw_family)
+ {
+ case HW_055x:
+ HwWrite20K1 (devc, GPIOCTL, 0x13fe);
+ break;
+ case HW_073x:
+ HwWrite20K1 (devc, GPIOCTL, 0x00e6);
+ break;
+ case HW_UAA:
+ HwWrite20K1 (devc, GPIOCTL, 0x00c2);
+ break;
+ case HW_ORIG:
+ default:
+ HwWrite20K1 (devc, GPIOCTL, 0x01e6);
+ break;
+ }
+
+ return CTSTATUS_SUCCESS;
+}
+
+CTSTATUS
+AllocateBuffers (sbxfi_devc_t * devc, sbxfi_portc_t * portc)
+{
+ int ctStatus = CTSTATUS_SUCCESS;
+
+#if 0
+ if (devc->pdwPageTable == NULL)
+ ctStatus = CTSTATUS_NOMEMORY;
+ else
+ {
+ // alloc playL buffer
+ portc->pdwPlayLBuffer = CONTIG_MALLOC (devc->osdev,
+ portc->dwPlayLBufferSize,
+ MEMLIMIT_32BITS,
+ &portc->dwPlayLPhysAddx, portc->playl_dma_handle);
+
+ if (portc->pdwPlayLBuffer == NULL)
+ ctStatus = CTSTATUS_NOMEMORY;
+ else
+ {
+ // alloc playR buffer
+ portc->pdwPlayRBuffer = CONTIG_MALLOC (devc->osdev,
+ portc->dwPlayRBufferSize,
+ MEMLIMIT_32BITS,
+ &portc->dwPlayLPhysAddx,portc->playr_dma_handle);
+
+ if (portc->pdwPlayRBuffer == NULL)
+ ctStatus = CTSTATUS_NOMEMORY;
+ else
+ {
+ // alloc recordL buffer
+ portc->pdwRecordLBuffer = CONTIG_MALLOC (devc->osdev,
+ portc->
+ dwRecordLBufferSize,
+ MEMLIMIT_32BITS,
+ &portc->
+ dwRecordLPhysAddx, portc->recl_dma_handle);
+
+ if (portc->pdwRecordLBuffer == NULL)
+ ctStatus = CTSTATUS_NOMEMORY;
+ else
+ {
+ // alloc recordR buffer
+ portc->pdwRecordRBuffer = CONTIG_MALLOC (devc->osdev,
+ portc->
+ dwRecordRBufferSize,
+ MEMLIMIT_32BITS,
+ &portc->
+ dwRecordRPhysAddx, portc->recr_dma_handle);
+ if (portc->pdwRecordRBuffer == NULL)
+ ctStatus = CTSTATUS_NOMEMORY;
+ }
+ }
+ }
+ }
+
+ if (ctStatus != CTSTATUS_SUCCESS)
+ FreeBuffers (devc, portc);
+#endif
+
+ return ctStatus;
+}
+
+void
+FreeBuffers (sbxfi_devc_t * devc, sbxfi_portc_t * portc)
+{
+#if 0
+ if (portc->pdwRecordLBuffer != NULL)
+ {
+ CONTIG_FREE (devc->osdev, portc->pdwRecordLBuffer,
+ portc->dwRecordLBufferSize, portc->recl_dma_handle);
+ portc->pdwRecordLBuffer = NULL;
+ }
+
+ if (portc->pdwRecordRBuffer != NULL)
+ {
+ CONTIG_FREE (devc->osdev, portc->pdwRecordRBuffer,
+ portc->dwRecordRBufferSize, portc->recr_dma_handle);
+ portc->pdwRecordRBuffer = NULL;
+ }
+
+ if (portc->pdwPlayLBuffer != NULL)
+ {
+ CONTIG_FREE (devc->osdev, portc->pdwPlayLBuffer,
+ portc->dwPlayLBufferSize, portc->playl_dma_handle);
+ portc->pdwPlayLBuffer = NULL;
+ }
+
+ if (portc->pdwPlayRBuffer != NULL)
+ {
+ CONTIG_FREE (devc->osdev, portc->pdwPlayRBuffer,
+ portc->dwPlayRBufferSize, portc->playr_dma_handle);
+ portc->pdwPlayRBuffer = NULL;
+ }
+#endif
+}
+
+void
+_SetupSB055xADC (sbxfi_devc_t * devc, unsigned int src, unsigned char mic20db)
+{
+ unsigned short gpioorg;
+ unsigned short gpioval = 0x28;
+
+
+ // check and set the following GPIO bits accordingly
+ // ADC_Gain = GPIO2
+ // Mic_Pwr_on = GPIO7
+ // Digital_IO_Sel = GPIO8
+ // Mic_Sw = GPIO9
+ // Aux/MicLine_Sw = GPIO12
+ switch (src)
+ {
+ case ADC_SRC_MICIN:
+ gpioval = 0x28;
+ if (mic20db)
+ gpioval |= 4;
+ break;
+
+ case ADC_SRC_LINEIN:
+ gpioval = 0;
+ break;
+
+ case ADC_SRC_VIDEO:
+ gpioval = 0x100; // not supported, set to digital
+ break;
+
+ case ADC_SRC_AUX:
+ gpioval = 0x1000;
+ break;
+
+ case ADC_SRC_NONE:
+ gpioval = 0x100; // set to digital
+ break;
+
+ default:
+ break;
+ }
+
+ gpioorg = (unsigned short) HwRead20K1 (devc, GPIO);
+ gpioorg &= 0xec7b;
+ gpioorg |= gpioval;
+ HwWrite20K1 (devc, GPIO, gpioorg);
+
+ return;
+}
+
+void
+_SetupADC (sbxfi_devc_t * devc, unsigned int src, unsigned char mic20db)
+{
+ unsigned int i = 0;
+ unsigned short gpioorg;
+ unsigned short input_source;
+ unsigned int adcdata = 0;
+
+ input_source = 0x100; // default to analog
+ switch (src)
+ {
+ case ADC_SRC_MICIN:
+ adcdata = 0x1;
+ input_source = 0x180; // set GPIO7 to select Mic
+ break;
+
+ case ADC_SRC_LINEIN:
+ adcdata = 0x2;
+ break;
+
+ case ADC_SRC_VIDEO:
+ adcdata = 0x4;
+ break;
+
+ case ADC_SRC_AUX:
+ adcdata = 0x8;
+ break;
+
+ case ADC_SRC_NONE:
+ adcdata = 0x0;
+ input_source = 0x0; // set to Digital
+ break;
+
+ default:
+ break;
+ }
+
+
+ HwWrite20K1PCI (devc, 0xcc, 0x8c);
+ HwWrite20K1PCI (devc, 0xcc, 0x0e);
+ if (((HwRead20K1PCI (devc, 0xcc)) & 0xff) != 0xaa)
+ {
+ HwWrite20K1PCI (devc, 0xcc, 0xee);
+ HwWrite20K1PCI (devc, 0xcc, 0xaa);
+ }
+
+ if (((HwRead20K1PCI (devc, 0xcc)) & 0xff) != 0xaa)
+ return;
+
+ HwWrite20K1PCI (devc, 0xEC, 0x05); //write to i2c status control
+
+ HwWrite20K1PCI (devc, 0xE0, 0x001a0080);
+ HwWrite20K1PCI (devc, 0xE4, 0x080e);
+
+ i = 0;
+ while (i != 0x800000)
+ {
+ i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000);
+ }
+
+ HwWrite20K1PCI (devc, 0xE0, 0x001a0080);
+ HwWrite20K1PCI (devc, 0xE4, 0x0a18);
+
+ i = 0;
+ while (i != 0x800000)
+ {
+ i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000);
+ }
+
+ HwWrite20K1PCI (devc, 0xE0, 0x001a0080);
+
+ if (mic20db)
+ HwWrite20K1PCI (devc, 0xE4, 0xf71c);
+ else
+ HwWrite20K1PCI (devc, 0xE4, 0xcf1c);
+
+ i = 0;
+ while (i != 0x800000)
+ {
+ i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000);
+ }
+
+ HwWrite20K1PCI (devc, 0xE0, 0x001a0080);
+
+ if (mic20db)
+ HwWrite20K1PCI (devc, 0xE4, 0xf71e);
+ else
+ HwWrite20K1PCI (devc, 0xE4, 0xcf1e);
+
+ i = 0;
+ while (i != 0x800000)
+ {
+ i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000);
+ }
+
+ HwWrite20K1PCI (devc, 0xE0, 0x001a0080);
+ HwWrite20K1PCI (devc, 0xE4, 0x8628);
+
+ i = 0;
+ while (i != 0x800000)
+ {
+ i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000);
+ }
+
+ HwWrite20K1PCI (devc, 0xE0, 0x001a0080);
+ HwWrite20K1PCI (devc, 0xE4, 0x2a | (adcdata << 0x8));
+
+ i = 0;
+ while (i != 0x800000)
+ {
+ i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000);
+ } //i2c ready poll
+
+ gpioorg = (unsigned short) HwRead20K1 (devc, GPIO);
+ gpioorg &= 0xfe7f;
+ gpioorg |= input_source;
+ HwWrite20K1 (devc, GPIO, gpioorg);
+
+ i = 0;
+ while (i != 0x800000)
+ {
+ i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000);
+ }
+
+ if (!((HwRead20K1 (devc, ID0)) & 0x100))
+ {
+ HwWrite20K1PCI (devc, 0xE0, 0x001a0080);
+ HwWrite20K1PCI (devc, 0xE4, 0x2616);
+ }
+
+ return;
+}
+
+void
+InitADC (sbxfi_devc_t * devc, unsigned int src, unsigned char mic20db)
+{
+ unsigned short wSSID;
+
+ wSSID = devc->wSubsystemID;
+ if ((wSSID == 0x0022) || (wSSID == 0x002F))
+ {
+ // Sb055x card
+ _SetupSB055xADC (devc, src, mic20db);
+ }
+ else
+ {
+ _SetupADC (devc, src, mic20db);
+ }
+
+ return;
+}
+
+void
+ResetDAC (sbxfi_devc_t * devc)
+{
+ unsigned int i = 0;
+ unsigned short gpioorg;
+
+
+ HwWrite20K1PCI (devc, 0xcc, 0x8c);
+ HwWrite20K1PCI (devc, 0xcc, 0x0e);
+ if (((HwRead20K1PCI (devc, 0xcc)) & 0xff) != 0xaa)
+ {
+ HwWrite20K1PCI (devc, 0xcc, 0xee);
+ HwWrite20K1PCI (devc, 0xcc, 0xaa);
+ }
+ if (((HwRead20K1PCI (devc, 0xcc)) & 0xff) != 0xaa)
+ return;
+
+ HwWrite20K1PCI (devc, 0xEC, 0x05); //write to i2c status control
+ i = 0;
+ while (i != 0x800000)
+ {
+ i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000);
+ }
+
+ // To be effective, need to reset the DAC twice.
+ for (i = 0; i < 2; i++)
+ {
+ osDelayms (100000);
+ gpioorg = (unsigned short) HwRead20K1 (devc, GPIO);
+ gpioorg &= 0xfffd;
+ HwWrite20K1 (devc, GPIO, gpioorg);
+ osDelayms (1000);
+ HwWrite20K1 (devc, GPIO, gpioorg | 0x2);
+ } //set gpio
+
+ HwWrite20K1PCI (devc, 0xE0, 0x00180080);
+ HwWrite20K1PCI (devc, 0xE4, 0x8001);
+
+ i = 0;
+ while (i != 0x800000)
+ {
+ i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000);
+ }
+
+ HwWrite20K1PCI (devc, 0xE0, 0x00180080);
+ HwWrite20K1PCI (devc, 0xE4, 0x1002);
+
+ i = 0;
+ while (i != 0x800000)
+ {
+ i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000);
+ }
+}
+
+void
+InitDAC (sbxfi_devc_t * devc, sbxfi_portc_t * portc)
+{
+ unsigned int i = 0;
+ unsigned int wData;
+ unsigned short gpioorg;
+ unsigned int dwSamplingRate;
+ unsigned short wSSID;
+
+
+ wSSID = devc->wSubsystemID;
+ // if SB055x, unmute outputs
+ if ((wSSID == 0x0022) || (wSSID == 0x002F))
+ {
+ gpioorg = (unsigned short) HwRead20K1 (devc, GPIO);
+ gpioorg &= 0xffbf; // set GPIO6 to low
+ gpioorg |= 2; // set GPIO1 to high
+ HwWrite20K1 (devc, GPIO, gpioorg);
+
+ return;
+ }
+
+
+ dwSamplingRate = portc->rate;
+
+ // Mute outputs
+ gpioorg = (unsigned short) HwRead20K1 (devc, GPIO);
+ gpioorg &= 0xffbf;
+ HwWrite20K1 (devc, GPIO, gpioorg);
+
+ ResetDAC (devc);
+
+ HwWrite20K1PCI (devc, 0xcc, 0x8c);
+ HwWrite20K1PCI (devc, 0xcc, 0x0e);
+ if (((HwRead20K1PCI (devc, 0xcc)) & 0xff) != 0xaa)
+ {
+ HwWrite20K1PCI (devc, 0xcc, 0xee);
+ HwWrite20K1PCI (devc, 0xcc, 0xaa);
+ }
+ if (((HwRead20K1PCI (devc, 0xcc)) & 0xff) != 0xaa)
+ return;
+
+ HwWrite20K1PCI (devc, 0xEC, 0x05); //write to i2c status control
+
+ i = 0;
+ while (i != 0x800000)
+ {
+ i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000);
+ }
+
+ if (dwSamplingRate == 48000)
+ wData = 0x2400;
+ else if (dwSamplingRate == 96000)
+ wData = 0x2500;
+ else if (dwSamplingRate == 192000)
+ wData = 0x2600;
+ else
+ wData = 0x2400;
+
+ HwWrite20K1PCI (devc, 0xE0, 0x00180080);
+ HwWrite20K1PCI (devc, 0xE4, (wData | 0x6));
+
+ i = 0;
+ while (i != 0x800000)
+ {
+ i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000);
+ }
+
+ HwWrite20K1PCI (devc, 0xE0, 0x00180080);
+ HwWrite20K1PCI (devc, 0xE4, (wData | 0x9));
+
+ i = 0;
+ while (i != 0x800000)
+ {
+ i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000);
+ }
+
+ HwWrite20K1PCI (devc, 0xE0, 0x00180080);
+ HwWrite20K1PCI (devc, 0xE4, (wData | 0xc));
+
+ i = 0;
+ while (i != 0x800000)
+ {
+ i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000);
+ }
+
+ HwWrite20K1PCI (devc, 0xE0, 0x00180080);
+ HwWrite20K1PCI (devc, 0xE4, (wData | 0xf));
+
+ i = 0;
+ while (i != 0x800000)
+ {
+ i = ((HwRead20K1PCI (devc, 0xEC)) & 0x800000);
+ }
+
+ // unmute outputs
+ gpioorg = (unsigned short) HwRead20K1 (devc, GPIO);
+ gpioorg = gpioorg | 0x40;
+ HwWrite20K1 (devc, GPIO, gpioorg);
+}
+
+
+void
+SetupPlayInputMapper (sbxfi_devc_t * devc, sbxfi_portc_t * portc)
+{
+/*
+ * TODO: This routine supports only stereo
+ */
+ unsigned int i;
+ unsigned int srcch;
+ unsigned int dio1, dio2;
+ unsigned int dwSamplingRate;
+
+
+ srcch = portc->SrcChan;
+ dio1 = portc->dwDAChan[0];
+ dio2 = portc->dwDAChan[1];
+ dwSamplingRate = portc->rate;
+
+ // initialize input mappers
+ for (i = 0; i < 0x50; i++)
+ HwWrite20K1 (devc, DAOIMAP_START(i), 0);
+
+ if (dwSamplingRate == 48000)
+ {
+ if (dio1 == 0)
+ {
+ HwWrite20K1 (devc, DAOIMAP_START(dio1), 0);
+ for (i=1;i<portc->channels;i++)
+ HwWrite20K1 (devc, DAOIMAP_START(dio2),
+ (dio1 << 16) | GetAudioSrcChan (srcch+i));
+ HwWrite20K1 (devc, DAOIMAP_START(dio1),
+ (dio2 << 16) | GetAudioSrcChan (srcch));
+ }
+ else
+ {
+ HwWrite20K1 (devc, DAOIMAP_START(0), 0);
+ HwWrite20K1 (devc, DAOIMAP_START(dio1),
+ (dio2 << 16) | GetAudioSrcChan (srcch));
+ for (i=1;i<portc->channels;i++)
+ HwWrite20K1 (devc, DAOIMAP_START(dio2),
+ (0 << 16) | GetAudioSrcChan (srcch+i));
+ HwWrite20K1 (devc, DAOIMAP_START(0), (dio1 << 16) | 0);
+ }
+ }
+ else if (dwSamplingRate == 96000)
+ {
+ // input mapper. Input mapper is a circular linked-list
+ if (dio1 == 0)
+ {
+ HwWrite20K1 (devc, DAOIMAP_START(dio1), 0);
+ for (i=1;i<portc->channels;i++)
+ HwWrite20K1 (devc, DAOIMAP_START(dio2),
+ ((dio1 + 2) << 16) | GetAudioSrcChan (srcch+i));
+ HwWrite20K1 (devc, DAOIMAP_START(dio1 + 2),
+ ((dio2 + 2) << 16) | GetAudioSrcChan (srcch + 0x80));
+ for (i=1;i<portc->channels;i++)
+ HwWrite20K1 (devc, DAOIMAP_START(dio2 + 2),
+ (dio1 << 16) | GetAudioSrcChan (srcch+i + 0x80));
+ HwWrite20K1 (devc, DAOIMAP_START(dio1),
+ (dio2 << 16) | GetAudioSrcChan (srcch));
+ }
+ else
+ {
+ HwWrite20K1 (devc, DAOIMAP_START(0), 0);
+ HwWrite20K1 (devc, DAOIMAP_START(dio1),
+ (dio2 << 16) | GetAudioSrcChan (srcch));
+ for (i=1;i<portc->channels;i++)
+ HwWrite20K1 (devc, DAOIMAP_START(dio2),
+ ((dio1 + 2) << 16) | GetAudioSrcChan (srcch+i));
+ HwWrite20K1 (devc, DAOIMAP_START(dio1 + 2),
+ ((dio2 + 2) << 16) | GetAudioSrcChan (srcch + 0x80));
+ for (i=1;i<portc->channels;i++)
+ HwWrite20K1 (devc, DAOIMAP_START(dio2 + 2),
+ (0 << 16) | GetAudioSrcChan (srcch+i + 0x80));
+ HwWrite20K1 (devc, DAOIMAP_START(0), (dio1 << 16) | 0);
+ }
+ }
+}
+
+void
+SetupPlayFormat (sbxfi_devc_t * devc, sbxfi_portc_t * portc)
+{
+ unsigned int i2sorg;
+ unsigned int dio1;
+ unsigned int dwSamplingRate;
+
+
+ dio1 = portc->dwDAChan[0];
+ dwSamplingRate = portc->rate;
+
+ // Read I2S CTL. Keep original value.
+ i2sorg = HwRead20K1 (devc, I2SCTL);
+
+#if 1
+ i2sorg = i2sorg | 0x04040404; // All I2S outputs enabled
+#else
+ // setup I2S value to program
+ switch (dio1)
+ {
+ case I2SA_L:
+ i2sorg = i2sorg | 0x4;
+ break;
+ case I2SB_L:
+ i2sorg = i2sorg | 0x400;
+ break;
+ case I2SC_L:
+ i2sorg = i2sorg | 0x40000;
+ break;
+ case I2SD_L:
+ i2sorg = i2sorg | 0x4000000;
+ break;
+ default:
+ i2sorg = i2sorg | 0x4;
+ break;
+ }
+#endif
+
+ // Program I2S with proper sample rate and enable the correct I2S channel.
+ i2sorg &= 0xfffffffc;
+ if (dwSamplingRate == 96000)
+ {
+ i2sorg = i2sorg | 2;
+ HwWrite20K1 (devc, I2SCTL, i2sorg);
+ }
+ else
+ {
+ i2sorg = i2sorg | 1;
+ HwWrite20K1 (devc, I2SCTL, i2sorg);
+ }
+}
+
+void
+SetupPlayMixer (sbxfi_devc_t * devc, sbxfi_portc_t * portc)
+{
+ int i;
+ unsigned int fixed_pitch;
+ unsigned int srcArchn, srcArchnC;
+ unsigned int srcPrchn, srcPrchnC;
+ unsigned int srcArchn2, srcArchnC2;
+ unsigned int srcch;
+ unsigned int dwSamplingRate;
+ unsigned int dwYData;
+
+ srcch = portc->SrcChan;
+ dwSamplingRate = portc->rate;
+
+ // NOTE: Y-Data is a 14-bit immediate floating-point constant multiplier.
+ // Adjust the Y-Data to control the multiplier.
+ // This can be used to control the level of the signal.
+ // dwYData = 0x1c00; // Original level used by Creative's driver.
+ dwYData = volume_table[portc->vol_left];
+
+ srcArchn = GetAudioSrcChan (srcch);
+ srcArchnC = GetAudioSrcChan (srcch + 0x80); // conjugate channel for srcch
+ srcPrchn = GetParamPitchChan (srcch);
+ srcPrchnC = GetParamPitchChan (srcch + 0x80);
+
+ // since input is same as output, pitch is 1.0
+ // convert to fixed-point 8.24 format, shift left 24 bit.
+ fixed_pitch = 1;
+ fixed_pitch = fixed_pitch << 24;
+
+ // write the pitch to param ring of the corresponsing SRC pitch slot
+ HwWrite20K1 (devc, PRING_LO_HI_START(srcPrchn), fixed_pitch);
+ HwWrite20K1 (devc, PRING_LO_HI_START(srcPrchnC), fixed_pitch);
+
+ WriteAMOP (devc, srcArchn, dwYData, srcArchn, 0);
+ if (dwSamplingRate == 96000)
+ {
+ WriteAMOP (devc, srcArchnC, dwYData, srcArchnC, 0);
+ }
+
+ // Handle subsequent channels
+
+ for (i=1;i<portc->channels;i++)
+ {
+ dwYData = volume_table[(i&1) ? portc->vol_right : portc->vol_left];
+
+ // Since we will use 1st SRC ch as pitch master,
+ // we do not need to program the pitch for SRC ch2
+
+ srcArchn2 = GetAudioSrcChan (srcch+i);
+ srcArchnC2 = GetAudioSrcChan (srcch+i + 0x80); // conjugate channel for srcch+i
+
+ WriteAMOP (devc, srcArchn2, dwYData, srcArchn2, 0);
+ if (dwSamplingRate == 96000)
+ {
+ WriteAMOP (devc, srcArchnC2, dwYData, srcArchnC2, 0);
+ }
+ }
+}
+
+void
+SetupAndStartPlaySRC (sbxfi_devc_t * devc, sbxfi_portc_t * portc)
+{
+ unsigned int Sa, Ladr, Ca, Ctl = 0x44c;
+ unsigned int srcch;
+ unsigned int dwSamplingRate;
+ int count;
+ int i;
+
+ srcch = portc->SrcChan;
+ dwSamplingRate = portc->rate;
+
+ count = audio_engines[portc->dev]->dmap_out->bytes_in_use;
+
+ // start addx: 1st entry in page table.
+ // Note: this must match with pagetable entry
+ Sa = portc->pgtable_index * 4096;
+ Ladr = Sa + count;
+ Ca = Sa + 0x100;
+ if (dwSamplingRate == 48000)
+ Ctl = 0x44c; // Set the Pitch Master for stereo.
+ else if ((dwSamplingRate == 96000))
+ Ctl = 0x45c; // Set the Pitch Master for stereo.
+
+ Ctl |= (portc->channels-1)*SRCCTL_ILSZ; /* Number of interleaved channels to follow */
+
+ // Program SRC for channel 1, enable interrupts and interleaved channels
+ WriteSRC (devc, Ca, 0, Sa, Ladr, 0x100, Ctl, srcch);
+
+ Ladr = Sa + count;
+ Ca = Sa + 0x100;
+
+ for (i=1;i<portc->channels;i++)
+ {
+ if (dwSamplingRate == 48000)
+ Ctl = 0x4c; // slave
+ else if ((dwSamplingRate == 96000))
+ Ctl = 0x5c; // slave
+ Ctl |= (portc->channels-i-1)*SRCCTL_ILSZ;
+
+ // Program SRC for channel 2
+ WriteSRC (devc, Ca, 0, Sa, Ladr, 0x100, Ctl, srcch+i);
+ }
+
+ //_dumpRegisters (devc, portc);
+}
+
+void
+StopPlay (sbxfi_devc_t * devc, sbxfi_portc_t * portc)
+{
+ unsigned int srcch;
+ unsigned int dwData;
+ int i;
+
+ srcch = portc->SrcChan;
+
+ //WriteSRC(devc, 0, 0, 0, 0, 0, 0, srcch);
+ //WriteSRC(devc, 0, 0, 0, 0, 0, 0, srcch2);
+
+ dwData = HwRead20K1 (devc, SRCCTL(srcch));
+ dwData &= 0xfffffff0;
+ dwData |= 0;
+ dwData &= ~SRCCTL_IE; /* Interrupt disable */
+ HwWrite20K1 (devc, SRCCTL(srcch), dwData);
+
+ for (i=1;i<portc->channels;i++)
+ {
+ dwData = HwRead20K1 (devc, SRCCTL(srcch+i));
+ dwData &= 0xfffffff0;
+ dwData |= 0;
+ HwWrite20K1 (devc, SRCCTL(srcch+i), dwData);
+ }
+}
+
+
+void
+StopPlaySRC (sbxfi_devc_t * devc, sbxfi_portc_t * portc)
+{
+#ifndef INTERNAL_LOOPBACK
+ StopPlay (devc, portc);
+#endif
+}
+
+
+//======================== RECORD ==========================
+
+
+
+void
+SetupRecordInputMapper (sbxfi_devc_t * devc, sbxfi_portc_t * portc)
+{
+ unsigned int srcch, srcch2;
+
+
+ srcch = portc->SrcChan;
+ srcch2 = portc->SrcChan+1;
+
+ // Internal loopback means loop play channels to record
+#ifdef INTERNAL_LOOPBACK
+ {
+ unsigned int playch1, playch2;
+
+ playch1 = portc->dwPlayLSrcChan;
+ playch2 = portc->dwPlayRSrcChan;
+ if (srcch == 0)
+ {
+ HwWrite20K1 (devc, SRCIMAP(0), 0);
+ HwWrite20K1 (devc, SRCIMAP(srcch2),
+ srcch2 << 24 | (0x80 +
+ srcch) << 16 |
+ GetAudioSrcChan (playch2));
+ HwWrite20K1 (devc, SRCIMAP(0x80 + srcch),
+ (0x80 + srcch) << 24 | (srcch2 +
+ 0x80) << 16 |
+ GetAudioSrcChan (playch1 + 0x80));
+ HwWrite20K1 (devc, SRCIMAP(0x81 + srcch2),
+ (0x80 +
+ srcch2) << 24 | 0 << 16 | GetAudioSrcChan (playch2 +
+ 0x80));
+ HwWrite20K1 (devc, SRCIMAP(srcch),
+ srcch << 24 | srcch2 << 16 | GetAudioSrcChan (playch1));
+ }
+ else
+ {
+ HwWrite20K1 (devc, SRCIMAP(0), 0);
+ HwWrite20K1 (devc, SRCIMAP(srcch),
+ srcch << 24 | srcch2 << 16 | GetAudioSrcChan (playch1));
+ HwWrite20K1 (devc, SRCIMAP(srcch2),
+ srcch2 << 24 | (0x80 +
+ srcch) << 16 |
+ GetAudioSrcChan (playch2));
+ HwWrite20K1 (devc, SRCIMAP(0x80 + srcch),
+ (0x80 + srcch) << 24 | (srcch2 +
+ 0x80) << 16 |
+ GetAudioSrcChan (playch1 + 0x80));
+ HwWrite20K1 (devc, SRCIMAP(0x80 + srcch2),
+ (0x80 +
+ srcch2) << 24 | 0 << 16 | GetAudioSrcChan (playch2 +
+ 0x80));
+ HwWrite20K1 (devc, SRCIMAP(0),
+ (0 << 24) | (srcch << 16) | 0x0);
+ }
+ }
+#else
+ {
+ if (srcch == 0)
+ {
+ HwWrite20K1 (devc, SRCIMAP(0), 0);
+ HwWrite20K1 (devc, SRCIMAP(srcch2),
+ srcch2 << 24 | (0x80 +
+ srcch) << 16 |
+ GetAudioSumChan (srcch2));
+ HwWrite20K1 (devc, SRCIMAP(0x80 + srcch),
+ (0x80 + srcch) << 24 | (srcch2 +
+ 0x80) << 16 |
+ GetAudioSumChan (srcch + 0x80));
+ HwWrite20K1 (devc, SRCIMAP(0x81 + srcch2),
+ (0x80 +
+ srcch2) << 24 | 0 << 16 | GetAudioSumChan (srcch2 +
+ 0x80));
+ HwWrite20K1 (devc, SRCIMAP(srcch),
+ srcch << 24 | srcch2 << 16 | GetAudioSumChan (srcch));
+ }
+ else
+ {
+ HwWrite20K1 (devc, SRCIMAP(0), 0);
+ HwWrite20K1 (devc, SRCIMAP(srcch),
+ srcch << 24 | srcch2 << 16 | GetAudioSumChan (srcch));
+ HwWrite20K1 (devc, SRCIMAP(srcch2),
+ srcch2 << 24 | (0x80 +
+ srcch) << 16 |
+ GetAudioSumChan (srcch2));
+ HwWrite20K1 (devc, SRCIMAP(0x80 + srcch),
+ (0x80 + srcch) << 24 | (srcch2 +
+ 0x80) << 16 |
+ GetAudioSumChan (srcch + 0x80));
+ HwWrite20K1 (devc, SRCIMAP(0x80 + srcch2),
+ (0x80 +
+ srcch2) << 24 | 0 << 16 | GetAudioSumChan (srcch2 +
+ 0x80));
+ HwWrite20K1 (devc, SRCIMAP(0),
+ (0 << 24) | (srcch << 16) | 0x0);
+ }
+ }
+#endif
+}
+
+
+void
+_SetupInputToOutputMonitoring (sbxfi_devc_t * devc, sbxfi_portc_t * portc)
+{
+ unsigned int i;
+ unsigned int dio1, dio2;
+ unsigned int srcch, srcch2;
+
+
+ srcch = portc->SrcChan;
+ srcch2 = portc->SrcChan+1;
+
+ dio1 = portc->dwDAChan[0];
+ dio2 = portc->dwDAChan[1];
+
+ // initialize input mappers
+ for (i = 0; i < 0x50; i++)
+ HwWrite20K1 (devc, DAOIMAP_START(i), 0);
+
+ HwWrite20K1 (devc, DAOIMAP_START(dio1), 0);
+ HwWrite20K1 (devc, DAOIMAP_START(dio2),
+ ((dio1 + 2) << 16) | GetAudioSumChan (srcch2));
+ HwWrite20K1 (devc, DAOIMAP_START(dio1 + 2),
+ ((dio2 + 2) << 16) | GetAudioSumChan (srcch + 0x80));
+ HwWrite20K1 (devc, DAOIMAP_START(dio2 + 2),
+ (dio1 << 16) | GetAudioSumChan (srcch2 + 0x80));
+ HwWrite20K1 (devc, DAOIMAP_START(dio1),
+ (dio2 << 16) | GetAudioSumChan (srcch));
+}
+
+void
+SetupRecordMixer (sbxfi_devc_t * devc, sbxfi_portc_t * portc)
+{
+ unsigned int fixed_pitch;
+ unsigned int srcPrchn1, srcPrchnC1;
+ unsigned int srcch, srcch2, srcchnC1, srcchnC2;
+ unsigned int dwYData;
+ unsigned short i, inch1, inch2;
+
+
+ srcch = portc->SrcChan;
+ srcch2 = portc->SrcChan+1;
+
+ // NOTE: Y-Data is a 14-bit immediate floating-point constant multiplier.
+ // Adjust the Y-Data to control the multiplier.
+ // This can be used to control the level of the signal.
+ dwYData = 0x1c00;
+
+ srcchnC1 = srcch + 0x80;
+ srcchnC2 = srcch2 + 0x80;
+
+ srcPrchn1 = GetParamPitchChan (srcch);
+ srcPrchnC1 = GetParamPitchChan (srcch + 0x80);
+
+ // since input is 2x of output, pitch is 2.0
+ // convert to fixed-point 8.24 format, shift left 24 bit.
+ fixed_pitch = 2;
+ fixed_pitch = fixed_pitch << 24;
+
+ // write the pitch to param ring of the corresponsing SRC pitch slot
+ HwWrite20K1 (devc, PRING_LO_HI_START(srcPrchn1), fixed_pitch);
+ HwWrite20K1 (devc, PRING_LO_HI_START(srcPrchnC1), fixed_pitch);
+
+ inch1 = 0x1b5; // I2S-In3 L
+ inch2 = 0x1bd; // I2S-In3 R
+ // program all I2S-In3 slots
+ for (i = 0; i < 8; i++)
+ {
+ if (i <= 3)
+ {
+ WriteAMOP (devc, inch1 + (i * 0x200), dwYData, inch1 + (i * 0x200),
+ (0x80000000 + srcch));
+ WriteAMOP (devc, inch2 + (i * 0x200), dwYData, inch2 + (i * 0x200),
+ (0x80000000 + srcch2));
+ }
+ else
+ {
+ WriteAMOP (devc, inch1 + (i * 0x200), dwYData, inch1 + (i * 0x200),
+ (0x80000000 + srcchnC1));
+ WriteAMOP (devc, inch2 + (i * 0x200), dwYData, inch2 + (i * 0x200),
+ (0x80000000 + srcchnC2));
+ }
+ }
+
+ // enable physical input I2S_in3 to I2S-Out0 monitoring
+ _SetupInputToOutputMonitoring (devc, portc);
+}
+
+void
+SetupRecordFormat (sbxfi_devc_t * devc)
+{
+ unsigned int i2sorg;
+
+ i2sorg = HwRead20K1 (devc, I2SCTL);
+
+ // enable I2S-D input
+ i2sorg |= 0x90000000;
+ HwWrite20K1 (devc, I2SCTL, i2sorg);
+}
+
+void
+SetupAndStartRecordSRC (sbxfi_devc_t * devc, sbxfi_portc_t * portc)
+{
+ unsigned int Sa, Ladr, Ca, Ctl = 0x64d;
+ int count;
+ unsigned int srcch, srcch2;
+ unsigned int dwSamplingRate;
+
+
+ srcch = portc->SrcChan;
+ srcch2 = portc->SrcChan+1;
+ dwSamplingRate = portc->rate;
+
+ count = audio_engines[portc->dev]->dmap_in->bytes_in_use;
+
+ // convert the num samples to bytes count
+
+ // hardcoded values:
+ // start addx: 4th entry in page table.
+ Sa = portc->pgtable_index * 4096;
+ Ladr = Sa + count;
+ Ca = Sa + 0x80;
+ if (dwSamplingRate == 48000)
+ Ctl = 0x64d; // record must start with RUN state!.
+ else if ((dwSamplingRate == 96000))
+ Ctl = 0x65d;
+
+ Ctl |= SRCCTL_ILSZ; // Interleaved stereo
+
+ WriteSRC (devc, Ca, 0, Sa, Ladr, 0x100, Ctl, srcch);
+
+ Ladr = Sa + count;
+ Ca = Sa + 0x80;
+ if (dwSamplingRate == 48000)
+ Ctl = 0x24d;
+ else if ((dwSamplingRate == 96000))
+ Ctl = 0x25d;
+
+ WriteSRC (devc, Ca, 0, Sa, Ladr, 0x80, Ctl, srcch2);
+
+ // Enable SRC input from Audio Ring
+ HwWrite20K1 (devc, SRCMCTL, 0x1);
+
+// _dumpRegisters(devc);
+}
+
+void
+StopRecordSRC (sbxfi_devc_t * devc, sbxfi_portc_t * portc)
+{
+ unsigned int srcch, srcch2;
+ unsigned int dwData;
+ unsigned int i;
+
+ srcch = portc->SrcChan;
+ srcch2 = portc->SrcChan+1;
+
+ //WriteSRC(devc, 0, 0, 0, 0, 0, 0, srcch);
+ //WriteSRC(devc, 0, 0, 0, 0, 0, 0, srcch2);
+
+ dwData = HwRead20K1 (devc, SRCCTL(srcch));
+ dwData &= 0xfffffff0;
+ dwData |= 0;
+ HwWrite20K1 (devc, SRCCTL(srcch), dwData);
+
+ dwData = HwRead20K1 (devc, SRCCTL(srcch2));
+ dwData &= 0xfffffff0;
+ dwData |= 0;
+ HwWrite20K1 (devc, SRCCTL(srcch2), dwData);
+
+#ifdef INTERNAL_LOOPBACK
+ StopPlay (devc, portc);
+#endif
+
+ // Disable SRC inputs from Audio Ring
+ HwWrite20K1 (devc, SRCMCTL, 0x0);
+
+ for (i = 0; i < 0x50; i++)
+ HwWrite20K1 (devc, DAOIMAP_START(i), 0);
+}
+
+//========================
+
+unsigned int
+HwRead20K1PCI (sbxfi_devc_t * devc, unsigned int dwReg)
+{
+ unsigned int dwVal;
+ oss_native_word flags;
+
+ MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
+ osOutportd (devc, (IOADDR) devc->wIOPortBase + 0x10, dwReg);
+ dwVal = osInportd (devc, (IOADDR) (devc->wIOPortBase + 0x14));
+ MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
+
+ return dwVal;
+}
+
+unsigned int
+HwRead20K1 (sbxfi_devc_t * devc, unsigned int dwReg)
+{
+ unsigned int dwVal;
+
+ oss_native_word flags;
+
+ MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
+ osOutportd (devc, (IOADDR) devc->wIOPortBase + 0x0, dwReg);
+ dwVal = osInportd (devc, (IOADDR) (devc->wIOPortBase + 0x4));
+ MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
+
+ return dwVal;
+}
+
+void
+HwWrite20K1PCI (sbxfi_devc_t * devc, unsigned int dwReg, unsigned int dwData)
+{
+ oss_native_word flags;
+
+ MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
+ osOutportd (devc, (IOADDR) devc->wIOPortBase + 0x10, dwReg);
+ osOutportd (devc, (IOADDR) (devc->wIOPortBase + 0x14), dwData);
+ MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
+}
+
+void
+HwWrite20K1 (sbxfi_devc_t * devc, unsigned int dwReg, unsigned int dwData)
+{
+ oss_native_word flags;
+
+ MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
+ osOutportd (devc, (IOADDR) devc->wIOPortBase + 0x0, dwReg);
+ osOutportd (devc, (IOADDR) (devc->wIOPortBase + 0x4), dwData);
+ MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
+}
+
+void
+WriteSRC
+ (sbxfi_devc_t * devc,
+ unsigned int srcca,
+ unsigned int srccf,
+ unsigned int srcsa, unsigned int srcla, unsigned int srcccr, unsigned int srcctl, unsigned int chn)
+{
+ HwWrite20K1 (devc, SRCCA(chn), srcca); // Current Address
+ HwWrite20K1 (devc, SRCCF(chn), srccf); // Current Fraction
+ HwWrite20K1 (devc, SRCSA(chn), srcsa); // START address
+ HwWrite20K1 (devc, SRCLA(chn), srcla); // LOOP address
+ HwWrite20K1 (devc, SRCCCR(chn), srcccr); // Cache control
+ HwWrite20K1 (devc, SRCCTL(chn), srcctl); // SRCCTL
+}
+
+#define CRM_TIMESLOT_ALLOC_BLOCK_SIZE 16
+#define CRM_PTS_PITCH 6
+#define CRM_PARAM_SRC_OFFSET 0x60
+
+unsigned int
+GetParamPitchChan (unsigned int i)
+{
+ int interpChanID =
+ (((int) i * CRM_TIMESLOT_ALLOC_BLOCK_SIZE) + CRM_PTS_PITCH) -
+ CRM_PARAM_SRC_OFFSET;
+ if (interpChanID < 0)
+ {
+ interpChanID += 4096;
+ }
+ return (unsigned int) interpChanID;
+}
+
+unsigned int
+GetAudioSrcChan (unsigned int srcchn)
+{
+ // SRC channel is in Audio Ring slot 1, after every 16 slot.
+ return (unsigned int) ((srcchn << 4) + 0x1);
+}
+
+unsigned int
+GetAudioSumChan (unsigned int chn)
+{
+ // SUM channel is in Audio Ring slot 0xc, after every 16 slot.
+ return (unsigned int) ((chn << 4) + 0xc);
+}
+
+void
+WriteAMOP
+ (sbxfi_devc_t * devc,
+ unsigned int xdata, unsigned int ydata, unsigned int chn, unsigned int hidata)
+{
+ HwWrite20K1 (devc, AMOP_START(chn), ((((unsigned int) ydata) << 18) | xdata << 4 | 1)); // Audio mixer, y-immediate
+ HwWrite20K1 (devc, AMOP_START(chn) + 4, hidata); // Audio mixer.
+}
+
+void
+_dumpRegisters (sbxfi_devc_t * devc, sbxfi_portc_t * portc)
+{
+ _dumpGlobal (devc);
+ _dumpSRCs (devc, portc);
+}
+
+void
+_dumpSRCs (sbxfi_devc_t * devc, sbxfi_portc_t * portc)
+{
+ unsigned int chn;
+
+ chn = portc->SrcChan;
+ cmn_err (CE_CONT,
+ "SRC chn=%lx, CA=%lx, CF=%lx, SA=%lx, LA=%lx, CCR=%lx, CTL=%lx\n",
+ chn, HwRead20K1 (devc, SRCCA(chn)),
+ HwRead20K1 (devc, SRCCF(chn)), HwRead20K1 (devc,
+ SRCSA(chn)),
+ HwRead20K1 (devc, SRCLA(chn)), HwRead20K1 (devc,
+ SRCCCR(chn)),
+ HwRead20K1 (devc, SRCCTL(chn)));
+
+ chn = portc->SrcChan+1;
+ cmn_err (CE_CONT,
+ "SRC chn=%lx, CA=%lx, CF=%lx, SA=%lx, LA=%lx, CCR=%lx, CTL=%lx\n",
+ chn, HwRead20K1 (devc, SRCCA(chn)),
+ HwRead20K1 (devc, SRCCF(chn)), HwRead20K1 (devc,
+ SRCSA(chn)),
+ HwRead20K1 (devc, SRCLA(chn)), HwRead20K1 (devc,
+ SRCCCR(chn)),
+ HwRead20K1 (devc, SRCCTL(chn)));
+}
+
+
+void
+_dumpGlobal (sbxfi_devc_t * devc)
+{
+ unsigned int i;
+
+ cmn_err (CE_CONT,
+ "GCTL=%lx, PLLCTL=%lx, GPIOCTL=%lx, GPIO=%lx, I2SCTL=%lx\n",
+ HwRead20K1 (devc, GCTL), HwRead20K1 (devc, PLLCTL),
+ HwRead20K1 (devc, GPIOCTL), HwRead20K1 (devc, GPIO),
+ HwRead20K1 (devc, I2SCTL));
+#if 1
+ cmn_err (CE_CONT, "DAOIMAP....\n");
+ for (i = 0; i < 0x50; i++)
+ {
+ cmn_err (CE_CONT, "%02lx: %lx ", i,
+ HwRead20K1 (devc, DAOIMAP_START(i)));
+ if (((i + 1) % 8) == 0)
+ cmn_err (CE_CONT, "\n");
+ }
+#endif
+#if 0
+ cmn_err (CE_CONT, "PageTable PhysAddx=%lx\n", HwRead20K1 (devc, PTPALX));
+ for (i = 0; i < 10; i++)
+ {
+ cmn_err (CE_CONT, "Entry[%lx]=%lx\n", i, devc->pdwPageTable[i]);
+ }
+#endif
+}