1 /* 2 * Copyright 2007-2008, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Ithamar Adema, ithamar AT unet DOT nl 7 */ 8 9 10 #include "driver.h" 11 12 13 int32 api_version = B_CUR_DRIVER_API_VERSION; 14 15 hda_controller gCards[MAX_CARDS]; 16 uint32 gNumCards; 17 pci_module_info* gPci; 18 19 20 static struct { 21 uint16 vendor; 22 uint16 device; 23 } kSupportedDevices[] = { 24 { 0x8086, 0xa170}, // 100 Series HD Audio 25 { 0x8086, 0x9d71}, // 200 Series HD Audio 26 { 0x8086, 0xa348}, // 300 Series cAVS 27 { 0x8086, 0x9dc8}, // 300 Series HD Audio 28 { 0x8086, 0x06c8}, // 400 Series cAVS 29 { 0x8086, 0x02c8}, // 400 Series HD Audio 30 { 0x8086, 0xa0c8}, // 500 Series HD Audio 31 { 0x8086, 0x51c8}, // 600 Series HD Audio 32 { 0x8086, 0x4dc8}, // JasperLake HD Audio 33 { 0x8086, 0x43c8}, // Tiger Lake-H HD Audio 34 { 0x8086, 0xa171}, // CM238 HD Audio 35 { 0x8086, 0x3198}, // GeminiLake HD Audio 36 }; 37 38 39 static bool 40 supports_device(pci_info &info) 41 { 42 for (size_t i = 0; i < B_COUNT_OF(kSupportedDevices); i++) { 43 if (info.vendor_id == kSupportedDevices[i].vendor 44 && info.device_id == kSupportedDevices[i].device) { 45 return true; 46 } 47 } 48 return false; 49 } 50 51 52 extern "C" status_t 53 init_hardware(void) 54 { 55 pci_info info; 56 long i; 57 58 if (get_module(B_PCI_MODULE_NAME, (module_info**)&gPci) != B_OK) 59 return ENODEV; 60 61 for (i = 0; gPci->get_nth_pci_info(i, &info) == B_OK; i++) { 62 if ((info.class_base == PCI_multimedia 63 && info.class_sub == PCI_hd_audio) 64 || supports_device(info)) { 65 put_module(B_PCI_MODULE_NAME); 66 return B_OK; 67 } 68 } 69 70 put_module(B_PCI_MODULE_NAME); 71 return ENODEV; 72 } 73 74 75 extern "C" status_t 76 init_driver(void) 77 { 78 char path[B_PATH_NAME_LENGTH]; 79 pci_info info; 80 long i; 81 82 if (get_module(B_PCI_MODULE_NAME, (module_info**)&gPci) != B_OK) 83 return ENODEV; 84 85 gNumCards = 0; 86 87 for (i = 0; gPci->get_nth_pci_info(i, &info) == B_OK 88 && gNumCards < MAX_CARDS; i++) { 89 if ((info.class_base == PCI_multimedia 90 && info.class_sub == PCI_hd_audio) 91 || supports_device(info)) { 92 #ifdef __HAIKU__ 93 if ((*gPci->reserve_device)(info.bus, info.device, info.function, 94 "hda", &gCards[gNumCards]) < B_OK) { 95 dprintf("HDA: Failed to reserve PCI:%d:%d:%d\n", 96 info.bus, info.device, info.function); 97 continue; 98 } 99 #endif 100 memset(&gCards[gNumCards], 0, sizeof(hda_controller)); 101 gCards[gNumCards].pci_info = info; 102 gCards[gNumCards].opened = 0; 103 sprintf(path, DEVFS_PATH_FORMAT, gNumCards); 104 gCards[gNumCards++].devfs_path = strdup(path); 105 106 dprintf("HDA: Detected controller @ PCI:%d:%d:%d, IRQ:%d, " 107 "type %04x/%04x (%04x/%04x)\n", 108 info.bus, info.device, info.function, 109 info.u.h0.interrupt_line, info.vendor_id, info.device_id, 110 info.u.h0.subsystem_vendor_id, info.u.h0.subsystem_id); 111 } 112 } 113 114 if (gNumCards == 0) { 115 put_module(B_PCI_MODULE_NAME); 116 return ENODEV; 117 } 118 119 return B_OK; 120 } 121 122 123 extern "C" void 124 uninit_driver(void) 125 { 126 for (uint32 i = 0; i < gNumCards; i++) { 127 #ifdef __HAIKU__ 128 (*gPci->unreserve_device)(gCards[i].pci_info.bus, 129 gCards[i].pci_info.device, gCards[i].pci_info.function, "hda", 130 &gCards[i]); 131 #endif 132 free((void*)gCards[i].devfs_path); 133 gCards[i].devfs_path = NULL; 134 } 135 136 put_module(B_PCI_MODULE_NAME); 137 } 138 139 140 extern "C" const char** 141 publish_devices(void) 142 { 143 static const char* devs[MAX_CARDS + 1]; 144 uint32 i; 145 146 for (i = 0; i < gNumCards; i++) 147 devs[i] = gCards[i].devfs_path; 148 149 devs[i] = NULL; 150 151 return devs; 152 } 153 154 155 extern "C" device_hooks* 156 find_device(const char* name) 157 { 158 return &gDriverHooks; 159 } 160