revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / AHI / Drivers / ac97 / ac97-init.c
blob465275fb7afa1d06ffaa539657d98aa0a67c3241
2 #define DEBUG 1
3 #include <aros/debug.h>
5 #include <asm/io.h>
7 #include "library.h"
8 #include "DriverData.h"
10 OOP_AttrBase __IHidd_PCIDev;
12 static const struct {
13 UWORD VendorID;
14 UWORD ProductID;
15 STRPTR Model;
16 } support[] = {
17 { 0x8086, 0x2415, "Intel 82801AA" },
18 { 0x8086, 0x2425, "Intel 82801AB" },
19 { 0x8086, 0x2445, "Intel 82801BA" },
20 { 0x8086, 0x2485, "Intel ICH3" },
21 { 0x8086, 0x24c5, "Intel ICH4" },
22 { 0x8086, 0x24d5, "Intel ICH5" },
23 { 0x8086, 0x25a6, "ESB" },
24 { 0x8086, 0x266e, "Intel ICH6" },
25 { 0x8086, 0x27de, "Intel ICH7" },
26 { 0x8086, 0x2698, "ESB2" },
27 { 0x8086, 0x7195, "Intel 440MX" },
28 { 0x1039, 0x7012, "SIS 7012" },
29 { 0x10de, 0x01b1, "NVIDIA nForce" },
30 { 0x10de, 0x003a, "MCP04" },
31 { 0x10de, 0x006a, "NVIDIA nForce2" },
32 { 0x10de, 0x0059, "CK804" },
33 { 0x10de, 0x008a, "MCP2S AC'97 Audio Controller" },
34 { 0x10de, 0x00da, "NVIDIA nForce3" },
35 { 0x10de, 0x00ea, "CK8S" },
36 { 0x10de, 0x026b, "MCP51" },
37 { 0x1022, 0x746d, "AMD 8111" },
38 { 0x1022, 0x7445, "AMD 768" },
39 { 0x10b9, 0x5455, "Ali 5455" },
40 {0,0,NULL},
43 static void i8x0_set_reg(struct ac97Base *ac97Base, ULONG reg, UWORD value)
45 int count=1000000;
47 while(count-- && (inb((IPTR)ac97Base->dmabase + ACC_SEMA) & 1));
49 outw(value, (IPTR)ac97Base->mixerbase + reg);
52 static UWORD i8x0_get_reg(struct ac97Base *ac97Base, ULONG reg)
54 int count=1000000;
56 while(count-- && (inb((IPTR)ac97Base->dmabase + ACC_SEMA) & 1));
58 return inw((IPTR)ac97Base->mixerbase + reg);
61 /******************************************************************************
62 ** Custom driver init *********************************************************
63 ******************************************************************************/
64 #define ac97Base ((struct ac97Base *)hook->h_Data)
65 #define AHIsubBase ((struct DriverBase *)hook->h_Data)
66 static AROS_UFH3(void, Enumerator,
67 AROS_UFHA(struct Hook *, hook, A0),
68 AROS_UFHA(OOP_Object *, device, A2),
69 AROS_UFHA(APTR, msg, A1))
71 AROS_USERFUNC_INIT
73 IPTR VendorID = 0, ProductID = 0, value = 0;
74 int i;
76 D(bug("[AHI:AC97] %s()\n", __func__));
78 OOP_GetAttr(device, aHidd_PCIDevice_ProductID, &ProductID);
79 OOP_GetAttr(device, aHidd_PCIDevice_VendorID, &VendorID);
81 D(bug("[AHI:AC97] %s: Querying PCI 'audio' device %04x:%04x\n", __func__, VendorID, ProductID));
83 for (i=0; support[i].VendorID; i++)
85 if (VendorID == support[i].VendorID && ProductID == support[i].ProductID)
87 struct TagItem attrs[] = {
88 { aHidd_PCIDevice_isIO, TRUE },
89 { aHidd_PCIDevice_isMEM, FALSE },
90 { aHidd_PCIDevice_isMaster, TRUE },
91 { TAG_DONE, 0UL },
94 D(bug("[AHI:AC97] %s: Detected supported '%s' card\n", __func__, support[i].Model));
96 ac97Base->mixer_set_reg = i8x0_set_reg;
97 ac97Base->mixer_get_reg = i8x0_get_reg;
99 OOP_SetAttrs(device, (struct TagItem *)&attrs);
101 OOP_GetAttr(device, aHidd_PCIDevice_Base0, &value);
102 ac97Base->mixerbase = (APTR)value;
103 OOP_GetAttr(device, aHidd_PCIDevice_Base1, &value);
104 ac97Base->dmabase = (APTR)value;
105 OOP_GetAttr(device, aHidd_PCIDevice_INTLine, &value);
106 ac97Base->irq_num = (ULONG)value;
109 bug("[AHI:AC97] %s: Mixer IO base @ %p\n", __func__, ac97Base->mixerbase);
110 bug("[AHI:AC97] %s: DMA IO base @ %p\n", __func__, ac97Base->dmabase);
113 if (VendorID == 0x1039 && ProductID == 0x7012)
115 /* SIS 7012 */
116 ac97Base->off_po_sr = DEFAULT_PO_PICB; /* swap registers */
117 ac97Base->off_po_picb = DEFAULT_PO_SR;
118 ac97Base->size_shift = 1; /* chip requires size in bytes, not samples */
120 else
122 /* All other cards */
123 ac97Base->off_po_sr = DEFAULT_PO_SR; /* swap registers */
124 ac97Base->off_po_picb = DEFAULT_PO_PICB;
125 ac97Base->size_shift = 0;
128 #if defined(__AROS__) && (__WORDSIZE==64)
129 ac97Base->buffer = CreatePool(MEMF_CLEAR | MEMF_31BIT, 131072, 65536);
130 #endif
131 if ((value = (IPTR)AllocMem((8*32) + ALIGN_AC97OUT, MEMF_PUBLIC | MEMF_31BIT | MEMF_CLEAR)) != 0)
133 ac97Base->PCM_out = (APTR)ALIGN_AC97(value);
134 D(bug("[AHI:AC97] %s: PCM_out base @ %p\n", __func__, ac97Base->PCM_out));
136 ac97Base->cardfound = TRUE;
138 outl(2, (IPTR)ac97Base->dmabase + GLOB_CNT);
140 ac97Base->mixer_set_reg(ac97Base, AC97_RESET, 0);
141 ac97Base->mixer_set_reg(ac97Base, AC97_POWERDOWN, 0);
143 /* Set master volume to no attenuation, mute off */
144 ac97Base->mixer_set_reg(ac97Base, AC97_MASTER_VOL, 0x0000);
145 ac97Base->mixer_set_reg(ac97Base, AC97_HEADPHONE_VOL, 0x0000);
146 ac97Base->mixer_set_reg(ac97Base, AC97_TONE, 0x0f0f);
147 ac97Base->mixer_set_reg(ac97Base, AC97_PCM_VOL, 0x0000);
150 bug("[AHI:AC97] %s: Powerdown = %02x\n", __func__, ac97Base->mixer_get_reg(ac97Base, AC97_POWERDOWN));
151 bug("[AHI:AC97] %s: GLOB_CNT = %08x\n", __func__, inl((IPTR)ac97Base->dmabase + GLOB_CNT));
152 bug("[AHI:AC97] %s: GLOB_STA = %08x\n", __func__, inl((IPTR)ac97Base->dmabase + GLOB_STA));
156 int i;
157 for (i=0; i < 64; i+=2)
159 D(bug("[AHI:AC97] reg %02x = %04x\n", i, ac97Base->mixer_get_reg(ac97Base, i)));
162 outl((ULONG)(IPTR)ac97Base->PCM_out, (IPTR)ac97Base->dmabase + PO_BDBAR);
165 bug("[AHI:AC97] %s: PO_BDBAR=%p\n", __func__, (APTR)(IPTR)inl((IPTR)ac97Base->dmabase + PO_BDBAR));
166 bug("[AHI:AC97] %s: PO_REGS=%08x\n", __func__, inl((IPTR)ac97Base->dmabase + PO_CIV));
167 bug("[AHI:AC97] %s: PO_PICB=%04x\n", __func__, inw((IPTR)ac97Base->dmabase + ac97Base->off_po_picb));
168 bug("[AHI:AC97] %s: PO_PIV=%02x\n", __func__, inb((IPTR)ac97Base->dmabase + PO_PIV));
169 bug("[AHI:AC97] %s: PO_CR=%02x\n", __func__, inb((IPTR)ac97Base->dmabase + PO_CR));
175 AROS_USERFUNC_EXIT
177 #undef ac97Base
178 #undef AHIsubBase
180 BOOL DriverInit( struct DriverBase* AHIsubBase )
182 struct ac97Base* ac97Base = (struct ac97Base*) AHIsubBase;
184 ac97Base->dosbase = OpenLibrary( DOSNAME, 37 );
185 ac97Base->sysbase = SysBase;
187 D(bug("[AHI:AC97] %s()\n", __func__));
189 if(DOSBase)
191 ac97Base->oopbase = (APTR)OpenLibrary(AROSOOP_NAME, 0);
192 if (OOPBase)
194 __IHidd_PCIDev = OOP_ObtainAttrBase(IID_Hidd_PCIDevice);
196 D(bug("[AHI:AC97] %s: Libraries opened\n", __func__));
198 if (__IHidd_PCIDev)
200 OOP_Object *pci = OOP_NewObject(NULL, CLID_Hidd_PCI, NULL);
202 D(bug("[AHI:AC97] %s: PCIDevice AttrBase = %x\n", __func__, __IHidd_PCIDev));
204 if (pci)
206 struct Hook FindHook = {
207 h_Entry: (IPTR(*)())Enumerator,
208 h_Data: ac97Base,
211 struct TagItem Reqs[] = {
212 { tHidd_PCI_Class, 0x04 },
213 { tHidd_PCI_SubClass, 0x01 },
214 { TAG_DONE, 0UL },
217 struct pHidd_PCI_EnumDevices enummsg = {
218 mID: OOP_GetMethodID(CLID_Hidd_PCI, moHidd_PCI_EnumDevices),
219 callback: &FindHook,
220 requirements: (struct TagItem *)&Reqs,
221 }, *msg = &enummsg;
223 D(bug("[AHI:AC97] %s: Got PCI object\n", __func__));
225 ac97Base->cardfound = FALSE;
227 OOP_DoMethod(pci, (OOP_Msg)msg);
229 OOP_DisposeObject(pci);
231 return ac97Base->cardfound;
235 else
237 Req("Unable to open 'oop.library'\n");
240 else
242 Req( "Unable to open 'dos.library' version 37.\n" );
245 return FALSE;
249 /******************************************************************************
250 ** Custom driver clean-up *****************************************************
251 ******************************************************************************/
253 VOID DriverCleanup( struct DriverBase* AHIsubBase )
255 struct ac97Base* ac97Base = (struct ac97Base*) AHIsubBase;
257 OOP_ReleaseAttrBase(IID_Hidd_PCIDevice);
258 CloseLibrary( (struct Library*) DOSBase );
259 CloseLibrary( (struct Library*) ac97Base->oopbase);