1*07910542SSiarzhuk Zharski /* 2*07910542SSiarzhuk Zharski * SiS 7018, Trident 4D Wave DX/NX, Acer Lab M5451 Sound Driver. 3*07910542SSiarzhuk Zharski * Copyright (c) 2002, 2008-2011 S.Zharski <imker@gmx.li> 4*07910542SSiarzhuk Zharski * Distributed under the terms of the MIT license. 5*07910542SSiarzhuk Zharski * 6*07910542SSiarzhuk Zharski */ 7*07910542SSiarzhuk Zharski 8*07910542SSiarzhuk Zharski 9*07910542SSiarzhuk Zharski #include "Driver.h" 10*07910542SSiarzhuk Zharski 11*07910542SSiarzhuk Zharski #include <kernel_cpp.h> 12*07910542SSiarzhuk Zharski #include <string.h> 13*07910542SSiarzhuk Zharski 14*07910542SSiarzhuk Zharski #include "Device.h" 15*07910542SSiarzhuk Zharski #include "Settings.h" 16*07910542SSiarzhuk Zharski 17*07910542SSiarzhuk Zharski 18*07910542SSiarzhuk Zharski int32 api_version = B_CUR_DRIVER_API_VERSION; 19*07910542SSiarzhuk Zharski 20*07910542SSiarzhuk Zharski size_t gNumCards = 0; 21*07910542SSiarzhuk Zharski Device *gDevices[MAX_DEVICES] = { 0 }; 22*07910542SSiarzhuk Zharski char *gDeviceNames[MAX_DEVICES + 1] = { 0 }; 23*07910542SSiarzhuk Zharski pci_module_info *gPCI = NULL; 24*07910542SSiarzhuk Zharski 25*07910542SSiarzhuk Zharski 26*07910542SSiarzhuk Zharski static Device::Info cardInfos[] = { 27*07910542SSiarzhuk Zharski { SiS7018, "SiS 7018" }, 28*07910542SSiarzhuk Zharski { ALi5451, "ALi M5451" }, 29*07910542SSiarzhuk Zharski { TridentDX, "Trident DX" }, 30*07910542SSiarzhuk Zharski { TridentNX, "Trident NX" } 31*07910542SSiarzhuk Zharski }; 32*07910542SSiarzhuk Zharski 33*07910542SSiarzhuk Zharski 34*07910542SSiarzhuk Zharski status_t 35*07910542SSiarzhuk Zharski init_hardware() 36*07910542SSiarzhuk Zharski { 37*07910542SSiarzhuk Zharski dprintf("sis7018:init_hardware:ver:%s\n", kVersion); 38*07910542SSiarzhuk Zharski status_t result = get_module(B_PCI_MODULE_NAME, (module_info **)&gPCI); 39*07910542SSiarzhuk Zharski if (result < B_OK) { 40*07910542SSiarzhuk Zharski return ENOSYS; 41*07910542SSiarzhuk Zharski } 42*07910542SSiarzhuk Zharski 43*07910542SSiarzhuk Zharski pci_info info = {0}; 44*07910542SSiarzhuk Zharski for (long i = 0; B_OK == (*gPCI->get_nth_pci_info)(i, &info); i++) { 45*07910542SSiarzhuk Zharski for (size_t idx = 0; idx < _countof(cardInfos); idx++) { 46*07910542SSiarzhuk Zharski if (info.vendor_id == cardInfos[idx].VendorId() && 47*07910542SSiarzhuk Zharski info.device_id == cardInfos[idx].DeviceId()) 48*07910542SSiarzhuk Zharski { 49*07910542SSiarzhuk Zharski put_module(B_PCI_MODULE_NAME); 50*07910542SSiarzhuk Zharski return B_OK; 51*07910542SSiarzhuk Zharski } 52*07910542SSiarzhuk Zharski } 53*07910542SSiarzhuk Zharski } 54*07910542SSiarzhuk Zharski 55*07910542SSiarzhuk Zharski put_module(B_PCI_MODULE_NAME); 56*07910542SSiarzhuk Zharski return ENODEV; 57*07910542SSiarzhuk Zharski } 58*07910542SSiarzhuk Zharski 59*07910542SSiarzhuk Zharski 60*07910542SSiarzhuk Zharski status_t 61*07910542SSiarzhuk Zharski init_driver() 62*07910542SSiarzhuk Zharski { 63*07910542SSiarzhuk Zharski status_t status = get_module(B_PCI_MODULE_NAME, (module_info **)&gPCI); 64*07910542SSiarzhuk Zharski if (status < B_OK) { 65*07910542SSiarzhuk Zharski return ENOSYS; 66*07910542SSiarzhuk Zharski } 67*07910542SSiarzhuk Zharski 68*07910542SSiarzhuk Zharski load_settings(); 69*07910542SSiarzhuk Zharski 70*07910542SSiarzhuk Zharski pci_info info = { 0 }; 71*07910542SSiarzhuk Zharski for (long i = 0; B_OK == (*gPCI->get_nth_pci_info)(i, &info); i++) { 72*07910542SSiarzhuk Zharski for (size_t idx = 0; idx < _countof(cardInfos); idx++) { 73*07910542SSiarzhuk Zharski if (info.vendor_id == cardInfos[idx].VendorId() && 74*07910542SSiarzhuk Zharski info.device_id == cardInfos[idx].DeviceId()) 75*07910542SSiarzhuk Zharski { 76*07910542SSiarzhuk Zharski if (gNumCards == MAX_DEVICES) { 77*07910542SSiarzhuk Zharski ERROR("Skipped:%s [%#06x:%#06x]\n", cardInfos[idx].Name(), 78*07910542SSiarzhuk Zharski cardInfos[idx].VendorId(), cardInfos[idx].DeviceId()); 79*07910542SSiarzhuk Zharski break; 80*07910542SSiarzhuk Zharski } 81*07910542SSiarzhuk Zharski 82*07910542SSiarzhuk Zharski Device* device = new Device(cardInfos[idx], info); 83*07910542SSiarzhuk Zharski if (device == 0) { 84*07910542SSiarzhuk Zharski return ENODEV; 85*07910542SSiarzhuk Zharski } 86*07910542SSiarzhuk Zharski 87*07910542SSiarzhuk Zharski status_t status = device->InitCheck(); 88*07910542SSiarzhuk Zharski if (status < B_OK) { 89*07910542SSiarzhuk Zharski delete device; 90*07910542SSiarzhuk Zharski break; 91*07910542SSiarzhuk Zharski } 92*07910542SSiarzhuk Zharski 93*07910542SSiarzhuk Zharski status = device->Setup(); 94*07910542SSiarzhuk Zharski if (status < B_OK) { 95*07910542SSiarzhuk Zharski delete device; 96*07910542SSiarzhuk Zharski break; 97*07910542SSiarzhuk Zharski } 98*07910542SSiarzhuk Zharski 99*07910542SSiarzhuk Zharski char name[32] = {0}; 100*07910542SSiarzhuk Zharski sprintf(name, "audio/hmulti/%s/%ld", 101*07910542SSiarzhuk Zharski cardInfos[idx].Name(), gNumCards); 102*07910542SSiarzhuk Zharski gDeviceNames[gNumCards] = strdup(name); 103*07910542SSiarzhuk Zharski gDevices[gNumCards++] = device; 104*07910542SSiarzhuk Zharski 105*07910542SSiarzhuk Zharski TRACE("Found:%s [%#06x:%#06x]\n", cardInfos[idx].Name(), 106*07910542SSiarzhuk Zharski cardInfos[idx].VendorId(), cardInfos[idx].DeviceId()); 107*07910542SSiarzhuk Zharski } 108*07910542SSiarzhuk Zharski } 109*07910542SSiarzhuk Zharski } 110*07910542SSiarzhuk Zharski 111*07910542SSiarzhuk Zharski if (gNumCards == 0) { 112*07910542SSiarzhuk Zharski put_module(B_PCI_MODULE_NAME); 113*07910542SSiarzhuk Zharski return ENODEV; 114*07910542SSiarzhuk Zharski } 115*07910542SSiarzhuk Zharski 116*07910542SSiarzhuk Zharski return B_OK; 117*07910542SSiarzhuk Zharski } 118*07910542SSiarzhuk Zharski 119*07910542SSiarzhuk Zharski 120*07910542SSiarzhuk Zharski void 121*07910542SSiarzhuk Zharski uninit_driver() 122*07910542SSiarzhuk Zharski { 123*07910542SSiarzhuk Zharski for (size_t i = 0; i < MAX_DEVICES; i++) { 124*07910542SSiarzhuk Zharski if (gDevices[i]) { 125*07910542SSiarzhuk Zharski delete gDevices[i]; 126*07910542SSiarzhuk Zharski gDevices[i] = NULL; 127*07910542SSiarzhuk Zharski } 128*07910542SSiarzhuk Zharski 129*07910542SSiarzhuk Zharski free(gDeviceNames[i]); 130*07910542SSiarzhuk Zharski gDeviceNames[i] = NULL; 131*07910542SSiarzhuk Zharski } 132*07910542SSiarzhuk Zharski 133*07910542SSiarzhuk Zharski put_module(B_PCI_MODULE_NAME); 134*07910542SSiarzhuk Zharski 135*07910542SSiarzhuk Zharski release_settings(); 136*07910542SSiarzhuk Zharski } 137*07910542SSiarzhuk Zharski 138*07910542SSiarzhuk Zharski 139*07910542SSiarzhuk Zharski static status_t 140*07910542SSiarzhuk Zharski SiS7018_open(const char *name, uint32 flags, void **cookie) 141*07910542SSiarzhuk Zharski { 142*07910542SSiarzhuk Zharski status_t status = ENODEV; 143*07910542SSiarzhuk Zharski *cookie = NULL; 144*07910542SSiarzhuk Zharski for (size_t i = 0; i < MAX_DEVICES; i++) { 145*07910542SSiarzhuk Zharski if (gDeviceNames[i] && !strcmp(gDeviceNames[i], name)) { 146*07910542SSiarzhuk Zharski status = gDevices[i]->Open(flags); 147*07910542SSiarzhuk Zharski *cookie = gDevices[i]; 148*07910542SSiarzhuk Zharski } 149*07910542SSiarzhuk Zharski } 150*07910542SSiarzhuk Zharski 151*07910542SSiarzhuk Zharski return status; 152*07910542SSiarzhuk Zharski } 153*07910542SSiarzhuk Zharski 154*07910542SSiarzhuk Zharski 155*07910542SSiarzhuk Zharski static status_t 156*07910542SSiarzhuk Zharski SiS7018_read(void *cookie, off_t position, void *buffer, size_t *numBytes) 157*07910542SSiarzhuk Zharski { 158*07910542SSiarzhuk Zharski Device *device = (Device *)cookie; 159*07910542SSiarzhuk Zharski return device->Read((uint8 *)buffer, numBytes); 160*07910542SSiarzhuk Zharski } 161*07910542SSiarzhuk Zharski 162*07910542SSiarzhuk Zharski 163*07910542SSiarzhuk Zharski static status_t 164*07910542SSiarzhuk Zharski SiS7018_write(void *cookie, off_t position, 165*07910542SSiarzhuk Zharski const void *buffer, size_t *numBytes) 166*07910542SSiarzhuk Zharski { 167*07910542SSiarzhuk Zharski Device *device = (Device *)cookie; 168*07910542SSiarzhuk Zharski return device->Write((const uint8 *)buffer, numBytes); 169*07910542SSiarzhuk Zharski } 170*07910542SSiarzhuk Zharski 171*07910542SSiarzhuk Zharski 172*07910542SSiarzhuk Zharski static status_t 173*07910542SSiarzhuk Zharski SiS7018_control(void *cookie, uint32 op, void *buffer, size_t length) 174*07910542SSiarzhuk Zharski { 175*07910542SSiarzhuk Zharski Device *device = (Device *)cookie; 176*07910542SSiarzhuk Zharski return device->Control(op, buffer, length); 177*07910542SSiarzhuk Zharski } 178*07910542SSiarzhuk Zharski 179*07910542SSiarzhuk Zharski 180*07910542SSiarzhuk Zharski static status_t 181*07910542SSiarzhuk Zharski SiS7018_close(void *cookie) 182*07910542SSiarzhuk Zharski { 183*07910542SSiarzhuk Zharski Device *device = (Device *)cookie; 184*07910542SSiarzhuk Zharski return device->Close(); 185*07910542SSiarzhuk Zharski } 186*07910542SSiarzhuk Zharski 187*07910542SSiarzhuk Zharski 188*07910542SSiarzhuk Zharski static status_t 189*07910542SSiarzhuk Zharski SiS7018_free(void *cookie) 190*07910542SSiarzhuk Zharski { 191*07910542SSiarzhuk Zharski Device *device = (Device *)cookie; 192*07910542SSiarzhuk Zharski return device->Free(); 193*07910542SSiarzhuk Zharski } 194*07910542SSiarzhuk Zharski 195*07910542SSiarzhuk Zharski 196*07910542SSiarzhuk Zharski const char ** 197*07910542SSiarzhuk Zharski publish_devices() 198*07910542SSiarzhuk Zharski { 199*07910542SSiarzhuk Zharski for (size_t i = 0; i < MAX_DEVICES; i++) { 200*07910542SSiarzhuk Zharski if (gDevices[i] == NULL) 201*07910542SSiarzhuk Zharski continue; 202*07910542SSiarzhuk Zharski 203*07910542SSiarzhuk Zharski if (gDeviceNames[i]) 204*07910542SSiarzhuk Zharski TRACE("%s\n", gDeviceNames[i]); 205*07910542SSiarzhuk Zharski } 206*07910542SSiarzhuk Zharski 207*07910542SSiarzhuk Zharski return (const char **)&gDeviceNames[0]; 208*07910542SSiarzhuk Zharski } 209*07910542SSiarzhuk Zharski 210*07910542SSiarzhuk Zharski 211*07910542SSiarzhuk Zharski device_hooks * 212*07910542SSiarzhuk Zharski find_device(const char *name) 213*07910542SSiarzhuk Zharski { 214*07910542SSiarzhuk Zharski static device_hooks deviceHooks = { 215*07910542SSiarzhuk Zharski SiS7018_open, 216*07910542SSiarzhuk Zharski SiS7018_close, 217*07910542SSiarzhuk Zharski SiS7018_free, 218*07910542SSiarzhuk Zharski SiS7018_control, 219*07910542SSiarzhuk Zharski SiS7018_read, 220*07910542SSiarzhuk Zharski SiS7018_write, 221*07910542SSiarzhuk Zharski NULL, // select 222*07910542SSiarzhuk Zharski NULL // deselect 223*07910542SSiarzhuk Zharski }; 224*07910542SSiarzhuk Zharski 225*07910542SSiarzhuk Zharski return &deviceHooks; 226*07910542SSiarzhuk Zharski } 227*07910542SSiarzhuk Zharski 228