cir_driver.c revision d8556812
1/* 2 * Driver for CL-GD5480. 3 * Itai Nahshon. 4 * 5 * Support for the CL-GD7548: David Monniaux 6 * 7 * This is mainly a cut & paste from the MGA driver. 8 * Original autors and contributors list include: 9 * Radoslaw Kapitan, Andrew Vanderstock, Dirk Hohndel, 10 * David Dawes, Andrew E. Mileski, Leonard N. Zubkoff, 11 * Guy DESBIEF 12 */ 13 14#ifdef HAVE_CONFIG_H 15#include "config.h" 16#endif 17 18/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/cirrus/cir_driver.c,v 1.67 2001/05/15 10:19:37 eich Exp $ */ 19 20/* All drivers should typically include these */ 21#include "xf86.h" 22#include "xf86_OSproc.h" 23 24#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 25#include "xf86Resources.h" 26#endif 27/* All drivers need this */ 28 29/* Drivers for PCI hardware need this */ 30#include "xf86PciInfo.h" 31 32/* Drivers that need to access the PCI config space directly need this */ 33#include "xf86Pci.h" 34 35#include "cir.h" 36#include "alp.h" 37#include "lg.h" 38 39#include "vbe.h" 40 41/* 42 * Forward definitions for the functions that make up the driver. 43 */ 44 45/* Mandatory functions */ 46 47static const OptionInfoRec * CIRAvailableOptions(int chipid, int busid); 48static void CIRIdentify(int flags); 49static Bool CIRProbe(DriverPtr drv, int flags); 50 51static Bool lg_loaded = FALSE; 52static Bool alp_loaded = FALSE; 53 54#define CIR_VERSION 4000 55#define CIR_NAME "CIRRUS" 56#define CIR_DRIVER_NAME "cirrus" 57#define CIR_MAJOR_VERSION PACKAGE_VERSION_MAJOR 58#define CIR_MINOR_VERSION PACKAGE_VERSION_MINOR 59#define CIR_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL 60 61/* 62 * This contains the functions needed by the server after loading the 63 * driver module. It must be supplied, and gets added to the driver list by 64 * the Module Setup function in the dynamic case. In the static case a 65 * reference to this is compiled in, and this requires that the name of 66 * this DriverRec be an upper-case version of the driver name. 67 */ 68 69_X_EXPORT DriverRec CIRRUS = { 70 CIR_VERSION, 71 CIR_DRIVER_NAME, 72 CIRIdentify, 73 CIRProbe, 74 CIRAvailableOptions, 75 NULL, 76 0 77}; 78 79/* Supported chipsets */ 80SymTabRec CIRChipsets[] = { 81 { PCI_CHIP_GD5430, "CLGD5430" }, 82 { PCI_CHIP_GD5434_4, "CLGD5434-4" }, 83 { PCI_CHIP_GD5434_8, "CLGD5434-8" }, 84 { PCI_CHIP_GD5436, "CLGD5436" }, 85/* { PCI_CHIP_GD5440, "CLGD5440" }, */ 86 { PCI_CHIP_GD5446, "CLGD5446" }, 87 { PCI_CHIP_GD5480, "CLGD5480" }, 88 { PCI_CHIP_GD5462, "CL-GD5462" }, 89 { PCI_CHIP_GD5464, "CL-GD5464" }, 90 { PCI_CHIP_GD5464BD, "CL-GD5464BD" }, 91 { PCI_CHIP_GD5465, "CL-GD5465" }, 92 { PCI_CHIP_GD7548, "CL-GD7548" }, 93 {-1, NULL } 94}; 95 96/* List of PCI chipset names */ 97_X_EXPORT PciChipsets CIRPciChipsets[] = { 98 { PCI_CHIP_GD5430, PCI_CHIP_GD5430, RES_SHARED_VGA }, 99 { PCI_CHIP_GD5434_4,PCI_CHIP_GD5434_4, RES_SHARED_VGA }, 100 { PCI_CHIP_GD5434_8,PCI_CHIP_GD5434_8, RES_SHARED_VGA }, 101 { PCI_CHIP_GD5436, PCI_CHIP_GD5436, RES_SHARED_VGA }, 102/* { PCI_CHIP_GD5440, PCI_CHIP_GD5440, RES_SHARED_VGA }, */ 103 { PCI_CHIP_GD5446, PCI_CHIP_GD5446, RES_SHARED_VGA }, 104 { PCI_CHIP_GD5480, PCI_CHIP_GD5480, RES_SHARED_VGA }, 105 { PCI_CHIP_GD5462, PCI_CHIP_GD5462, RES_SHARED_VGA }, 106 { PCI_CHIP_GD5464, PCI_CHIP_GD5464, RES_SHARED_VGA }, 107 { PCI_CHIP_GD5464BD,PCI_CHIP_GD5464BD, RES_SHARED_VGA }, 108 { PCI_CHIP_GD5465, PCI_CHIP_GD5465, RES_SHARED_VGA }, 109 { PCI_CHIP_GD7548, PCI_CHIP_GD7548, RES_SHARED_VGA }, 110 { -1, -1, RES_UNDEFINED} 111}; 112 113#ifdef XFree86LOADER 114 115static MODULESETUPPROTO(cirSetup); 116 117static XF86ModuleVersionInfo cirVersRec = 118{ 119 "cirrus", 120 MODULEVENDORSTRING, 121 MODINFOSTRING1, 122 MODINFOSTRING2, 123 XORG_VERSION_CURRENT, 124 CIR_MAJOR_VERSION, CIR_MINOR_VERSION, CIR_PATCHLEVEL, 125 ABI_CLASS_VIDEODRV, /* This is a video driver */ 126 ABI_VIDEODRV_VERSION, 127 MOD_CLASS_VIDEODRV, 128 {0,0,0,0} 129}; 130 131/* 132 * This is the module init data. 133 * Its name has to be the driver name followed by ModuleData. 134 */ 135_X_EXPORT XF86ModuleData cirrusModuleData = { &cirVersRec, cirSetup, NULL }; 136 137static pointer 138cirSetup(pointer module, pointer opts, int *errmaj, int *errmin) 139{ 140 static Bool setupDone = FALSE; 141 142 /* This module should be loaded only once, but check to be sure. */ 143 144 if (!setupDone) { 145 setupDone = TRUE; 146 xf86AddDriver(&CIRRUS, module, 0); 147 148 return (pointer)1; 149 } 150 if (errmaj) *errmaj = LDR_ONCEONLY; 151 return NULL; 152} 153 154#endif /* XFree86LOADER */ 155 156/* Mandatory */ 157static void 158CIRIdentify(int flags) 159{ 160 xf86PrintChipsets(CIR_NAME, "driver for Cirrus chipsets", CIRChipsets); 161} 162 163static const OptionInfoRec * 164CIRAvailableOptions(int chipid, int busid) 165{ 166 int chip = chipid & 0xffff; 167 168 switch (chip) 169 { 170 case PCI_CHIP_GD5462: 171 case PCI_CHIP_GD5464: 172 case PCI_CHIP_GD5464BD: 173 case PCI_CHIP_GD5465: 174 if (lg_loaded) 175 return LgAvailableOptions(chipid); 176 else 177 return NULL; 178 179 default: 180 if (alp_loaded) 181 return AlpAvailableOptions(chipid); 182 else 183 return NULL; 184 } 185} 186 187static Bool 188CIRProbe(DriverPtr drv, int flags) 189{ 190 int i; 191 GDevPtr *devSections; 192 pciVideoPtr pPci; 193 int *usedChips; 194 int numDevSections; 195 int numUsed; 196 Bool foundScreen = FALSE; 197 ScrnInfoPtr pScrn; 198 199#ifdef CIR_DEBUG 200 ErrorF("CirProbe\n"); 201#endif 202 203 /* 204 * For PROBE_DETECT, make sure both sub-modules are loaded before 205 * calling xf86MatchPciInstances(), because the AvailableOptions() 206 * functions may be called before xf86MatchPciInstances() returns. 207 */ 208 209 if (flags & PROBE_DETECT) { 210 if (!lg_loaded) { 211 if (xf86LoadDrvSubModule(drv, "cirrus_laguna")) { 212 lg_loaded = TRUE; 213 } 214 } 215 if (!alp_loaded) { 216 if (xf86LoadDrvSubModule(drv, "cirrus_alpine")) { 217 alp_loaded = TRUE; 218 } 219 } 220 } 221 222 if ((numDevSections = xf86MatchDevice(CIR_DRIVER_NAME, 223 &devSections)) <= 0) { 224 return FALSE; 225 } 226 227#ifndef XSERVER_LIBPCIACCESS 228 if (xf86GetPciVideoInfo() == NULL) { 229 /* 230 * We won't let anything in the config file override finding no 231 * PCI video cards at all. This seems reasonable now, but we'll see. 232 */ 233 return FALSE; 234 } 235#endif 236 237 numUsed = xf86MatchPciInstances(CIR_NAME, PCI_VENDOR_CIRRUS, 238 CIRChipsets, CIRPciChipsets, devSections, 239 numDevSections, drv, &usedChips); 240 /* Free it since we don't need that list after this */ 241 xfree(devSections); 242 if (numUsed <= 0) 243 return FALSE; 244 if (flags & PROBE_DETECT) 245 foundScreen = TRUE; 246 else for (i = 0; i < numUsed; i++) { 247 /* The Laguna family of chips is so different from the Alpine 248 family that we won't share even the highest-level of 249 functions. But, the Laguna chips /are/ Cirrus chips, so 250 they should be handled in this driver (as opposed to their 251 own driver). */ 252 pPci = xf86GetPciInfoForEntity(usedChips[i]); 253 pScrn = NULL; 254 if (pPci && (PCI_DEV_DEVICE_ID(pPci) == PCI_CHIP_GD5462 || 255 PCI_DEV_DEVICE_ID(pPci) == PCI_CHIP_GD5464 || 256 PCI_DEV_DEVICE_ID(pPci) == PCI_CHIP_GD5464BD || 257 PCI_DEV_DEVICE_ID(pPci) == PCI_CHIP_GD5465)) { 258 259 if (!lg_loaded) { 260 if (!xf86LoadDrvSubModule(drv, "cirrus_laguna")) 261 continue; 262 lg_loaded = TRUE; 263 } 264 pScrn = LgProbe(usedChips[i]); 265 } else { 266 if (!alp_loaded) { 267 if (!xf86LoadDrvSubModule(drv, "cirrus_alpine")) 268 continue; 269 alp_loaded = TRUE; 270 } 271 pScrn = AlpProbe(usedChips[i]); 272 } 273 274 if (pScrn) { 275 foundScreen = TRUE; 276 /* Fill in what we can of the ScrnInfoRec */ 277 pScrn->driverVersion = CIR_VERSION; 278 pScrn->driverName = CIR_DRIVER_NAME; 279 pScrn->name = CIR_NAME; 280 pScrn->Probe = NULL; 281 } 282 } 283 xfree(usedChips); 284 285 return foundScreen; 286} 287 288/* 289 * Map the framebuffer and MMIO memory. 290 */ 291 292_X_EXPORT Bool 293CirMapMem(CirPtr pCir, int scrnIndex) 294{ 295 int mmioFlags; 296 297#ifdef CIR_DEBUG 298 ErrorF("CirMapMem\n"); 299#endif 300 301 /* 302 * Map the frame buffer. 303 */ 304 if (pCir->FbMapSize) { 305 306#ifndef XSERVER_LIBPCIACCESS 307 308 pCir->FbBase = xf86MapPciMem(scrnIndex, VIDMEM_FRAMEBUFFER, 309 pCir->PciTag, pCir->FbAddress, 310 pCir->FbMapSize); 311 if (pCir->FbBase == NULL) 312 return FALSE; 313 314#else 315 void** result = (void**)&pCir->FbBase; 316 int err = pci_device_map_range(pCir->PciInfo, 317 pCir->FbAddress, 318 pCir->FbMapSize, 319 PCI_DEV_MAP_FLAG_WRITABLE | 320 PCI_DEV_MAP_FLAG_WRITE_COMBINE, 321 result); 322 323 if (err) 324 return FALSE; 325#endif 326 } 327 328#ifdef CIR_DEBUG 329 ErrorF("CirMapMem pCir->FbBase=0x%08x\n", pCir->FbBase); 330#endif 331 332 /* 333 * Map IO registers to virtual address space 334 */ 335 if (pCir->IOAddress == 0) { 336 pCir->IOBase = NULL; /* Until we are ready to use MMIO */ 337 } else { 338 339#ifndef XSERVER_LIBPCIACCESS 340 mmioFlags = VIDMEM_MMIO; 341 /* 342 * For Alpha, we need to map SPARSE memory, since we need 343 * byte/short access. Common-level will automatically use 344 * sparse mapping for MMIO. 345 */ 346 347 pCir->IOBase = 348 xf86MapPciMem(scrnIndex, mmioFlags, pCir->PciTag, 349 pCir->IOAddress, pCir->IoMapSize); 350 if (pCir->IOBase == NULL) 351 return FALSE; 352 353#else 354 void** result = (void**)&pCir->IOBase; 355 int err = pci_device_map_range(pCir->PciInfo, 356 pCir->IOAddress, 357 pCir->IoMapSize, 358 PCI_DEV_MAP_FLAG_WRITABLE, 359 result); 360 361 if (err) 362 return FALSE; 363 364#endif 365 } 366 367#ifdef CIR_DEBUG 368 ErrorF("CirMapMem pCir->IOBase=0x%08x [length=%08x] from PCI=%08x\n", 369 pCir->IOBase, pCir->IoMapSize, pCir->IOAddress); 370 ErrorF("MMIO[GR31] = %2X\n", (int) 371 ((volatile unsigned char*) pCir->IOBase)[0x40]); 372#endif 373 374 return TRUE; 375} 376 377 378/* 379 * Unmap the framebuffer and MMIO memory. 380 */ 381 382_X_EXPORT Bool 383CirUnmapMem(CirPtr pCir, int scrnIndex) 384{ 385#ifdef CIR_DEBUG 386 ErrorF("CirUnmapMem\n"); 387#endif 388 389 if (pCir->IOBase != NULL) { 390 /* 391 * Unmap IO registers to virtual address space 392 */ 393#ifndef XSERVER_LIBPCIACCESS 394 xf86UnMapVidMem(scrnIndex, (pointer)pCir->IOBase, pCir->IoMapSize); 395#else 396 pci_device_unmap_range(pCir->PciInfo, (pointer)pCir->IOBase, pCir->IoMapSize); 397#endif 398 pCir->IOBase = NULL; 399 } 400 401#ifndef XSERVER_LIBPCIACCESS 402 xf86UnMapVidMem(scrnIndex, (pointer)pCir->FbBase, pCir->FbMapSize); 403#else 404 pci_device_unmap_range(pCir->PciInfo, (pointer)pCir->FbBase, pCir->FbMapSize); 405#endif 406 pCir->FbBase = NULL; 407 return TRUE; 408} 409 410_X_EXPORT void 411cirProbeDDC(ScrnInfoPtr pScrn, int index) 412{ 413 vbeInfoPtr pVbe; 414 415 if (xf86LoadSubModule(pScrn, "vbe")) { 416 pVbe = VBEInit(NULL,index); 417 ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 418 vbeFree(pVbe); 419 } 420} 421