diff options
Diffstat (limited to 'kernel/drv/oss_sbxfi')
-rw-r--r-- | kernel/drv/oss_sbxfi/.config | 1 | ||||
-rw-r--r-- | kernel/drv/oss_sbxfi/.devices | 3 | ||||
-rw-r--r-- | kernel/drv/oss_sbxfi/.name | 1 | ||||
-rw-r--r-- | kernel/drv/oss_sbxfi/.params | 15 | ||||
-rw-r--r-- | kernel/drv/oss_sbxfi/20k1reg.h | 911 | ||||
-rw-r--r-- | kernel/drv/oss_sbxfi/hwaccess.h | 71 | ||||
-rw-r--r-- | kernel/drv/oss_sbxfi/oss_sbxfi.c | 1078 | ||||
-rw-r--r-- | kernel/drv/oss_sbxfi/oss_sbxfi.man | 20 | ||||
-rw-r--r-- | kernel/drv/oss_sbxfi/sbxfi.h | 166 | ||||
-rw-r--r-- | kernel/drv/oss_sbxfi/sbxfi_hwaccess.c | 1391 |
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 +} |