1 /* 2 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 * 26 * Author: Alan Hourihane <alanh (at) tungstengraphics.com> 27 * Author: Jakob Bornecrantz <wallbraker (at) gmail.com> 28 * 29 */ 30 31 #include "../../state_trackers/xorg/xorg_winsys.h" 32 #include <nouveau.h> 33 #include <xorg/dri.h> 34 #include <xf86drmMode.h> 35 36 static void nouveau_xorg_identify(int flags); 37 static Bool nouveau_xorg_pci_probe(DriverPtr driver, int entity_num, 38 struct pci_device *device, 39 intptr_t match_data); 40 41 static const struct pci_id_match nouveau_xorg_device_match[] = { 42 { 0x10de, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 43 0x00030000, 0x00ffffff, 0 }, 44 {0, 0, 0}, 45 }; 46 47 static PciChipsets nouveau_xorg_pci_devices[] = { 48 {PCI_MATCH_ANY, PCI_MATCH_ANY, NULL}, 49 {-1, -1, NULL} 50 }; 51 52 static XF86ModuleVersionInfo nouveau_xorg_version = { 53 "nouveau2", 54 MODULEVENDORSTRING, 55 MODINFOSTRING1, 56 MODINFOSTRING2, 57 XORG_VERSION_CURRENT, 58 0, 1, 0, /* major, minor, patch */ 59 ABI_CLASS_VIDEODRV, 60 ABI_VIDEODRV_VERSION, 61 MOD_CLASS_VIDEODRV, 62 {0, 0, 0, 0} 63 }; 64 65 /* 66 * Xorg driver exported structures 67 */ 68 69 _X_EXPORT DriverRec nouveau2 = { 70 1, 71 "nouveau2", 72 nouveau_xorg_identify, 73 NULL, 74 xorg_tracker_available_options, 75 NULL, 76 0, 77 NULL, 78 nouveau_xorg_device_match, 79 nouveau_xorg_pci_probe 80 }; 81 82 static MODULESETUPPROTO(nouveau_xorg_setup); 83 84 _X_EXPORT XF86ModuleData nouveau2ModuleData = { 85 &nouveau_xorg_version, 86 nouveau_xorg_setup, 87 NULL 88 }; 89 90 /* 91 * Xorg driver functions 92 */ 93 94 static pointer 95 nouveau_xorg_setup(pointer module, pointer opts, int *errmaj, int *errmin) 96 { 97 static Bool setupDone = 0; 98 99 /* This module should be loaded only once, but check to be sure. 100 */ 101 if (!setupDone) { 102 setupDone = 1; 103 xf86AddDriver(&nouveau2, module, HaveDriverFuncs); 104 105 /* 106 * The return value must be non-NULL on success even though there 107 * is no TearDownProc. 108 */ 109 return (pointer) 1; 110 } else { 111 if (errmaj) 112 *errmaj = LDR_ONCEONLY; 113 return NULL; 114 } 115 } 116 117 static void 118 nouveau_xorg_identify(int flags) 119 { 120 xf86DrvMsg(0, X_INFO, "nouveau2: Gallium3D based 2D driver for NV30+ NVIDIA chipsets\n"); 121 } 122 123 static Bool 124 nouveau_xorg_pci_probe(DriverPtr driver, 125 int entity_num, struct pci_device *device, intptr_t match_data) 126 { 127 ScrnInfoPtr scrn = NULL; 128 EntityInfoPtr entity; 129 struct nouveau_device *dev = NULL; 130 char *busid; 131 int chipset, ret; 132 133 if (device->vendor_id != 0x10DE) 134 return FALSE; 135 136 if (!xf86LoaderCheckSymbol("DRICreatePCIBusID")) { 137 xf86DrvMsg(-1, X_ERROR, "[drm] No DRICreatePCIBusID symbol\n"); 138 return FALSE; 139 } 140 busid = DRICreatePCIBusID(device); 141 142 ret = nouveau_device_open(busid, &dev); 143 if (ret) { 144 xf86DrvMsg(-1, X_ERROR, "[drm] failed to open device\n"); 145 free(busid); 146 return FALSE; 147 } 148 149 chipset = dev->chipset; 150 nouveau_device_del(&dev); 151 152 ret = drmCheckModesettingSupported(busid); 153 free(busid); 154 if (ret) { 155 xf86DrvMsg(-1, X_ERROR, "[drm] KMS not enabled\n"); 156 return FALSE; 157 } 158 159 switch (chipset & 0xf0) { 160 case 0x00: 161 case 0x10: 162 case 0x20: 163 xf86DrvMsg(-1, X_NOTICE, "Too old chipset: NV%02x\n", chipset); 164 return FALSE; 165 case 0x30: 166 case 0x40: 167 case 0x60: 168 case 0x50: 169 case 0x80: 170 case 0x90: 171 case 0xa0: 172 case 0xc0: 173 xf86DrvMsg(-1, X_INFO, "Detected chipset: NV%02x\n", chipset); 174 break; 175 default: 176 xf86DrvMsg(-1, X_ERROR, "Unknown chipset: NV%02x\n", chipset); 177 return FALSE; 178 } 179 180 scrn = xf86ConfigPciEntity(scrn, 0, entity_num, nouveau_xorg_pci_devices, 181 NULL, NULL, NULL, NULL, NULL); 182 if (scrn != NULL) { 183 scrn->driverVersion = 1; 184 scrn->driverName = "nouveau"; 185 scrn->name = "nouveau2"; 186 scrn->Probe = NULL; 187 188 entity = xf86GetEntityInfo(entity_num); 189 190 /* Use all the functions from the xorg tracker */ 191 xorg_tracker_set_functions(scrn); 192 } 193 return scrn != NULL; 194 } 195