1/* 2 * XG20, XG21, XG40, XG42 frame buffer device 3 * for Linux kernels 2.5.x, 2.6.x 4 * Base on TW's sis fbdev code. 5 */ 6 7//#include <linux/config.h> 8#include <linux/version.h> 9#include <linux/module.h> 10#include <linux/moduleparam.h> 11#include <linux/kernel.h> 12#include <linux/spinlock.h> 13#include <linux/errno.h> 14#include <linux/string.h> 15#include <linux/mm.h> 16#include <linux/tty.h> 17#include <linux/slab.h> 18#include <linux/delay.h> 19#include <linux/fb.h> 20#include <linux/console.h> 21#include <linux/selection.h> 22#include <linux/ioport.h> 23#include <linux/init.h> 24#include <linux/pci.h> 25#include <linux/vmalloc.h> 26#include <linux/vt_kern.h> 27#include <linux/capability.h> 28#include <linux/fs.h> 29#include <linux/types.h> 30#include <linux/proc_fs.h> 31 32 33#ifndef XGIFB_PAN 34#define XGIFB_PAN 35#endif 36 37#include <asm/io.h> 38#ifdef CONFIG_MTRR 39#include <asm/mtrr.h> 40#endif 41 42#include "XGIfb.h" 43#include "vgatypes.h" 44#include "XGI_main.h" 45#include "vb_util.h" 46 47 48#define Index_CR_GPIO_Reg1 0x48 49#define Index_CR_GPIO_Reg2 0x49 50#define Index_CR_GPIO_Reg3 0x4a 51 52#define GPIOG_EN (1<<6) 53#define GPIOG_WRITE (1<<6) 54#define GPIOG_READ (1<<1) 55int XGIfb_GetXG21DefaultLVDSModeIdx(void); 56 57/* -------------------- Macro definitions ---------------------------- */ 58 59#undef XGIFBDEBUG 60 61#ifdef XGIFBDEBUG 62#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) 63#else 64#define DPRINTK(fmt, args...) 65#endif 66 67#ifdef XGIFBDEBUG 68static void dumpVGAReg(void) 69{ 70 u8 i,reg; 71 72outXGIIDXREG(XGISR, 0x05, 0x86); 73/* 74outXGIIDXREG(XGISR, 0x08, 0x4f); 75outXGIIDXREG(XGISR, 0x0f, 0x20); 76outXGIIDXREG(XGISR, 0x11, 0x4f); 77outXGIIDXREG(XGISR, 0x13, 0x45); 78outXGIIDXREG(XGISR, 0x14, 0x51); 79outXGIIDXREG(XGISR, 0x1e, 0x41); 80outXGIIDXREG(XGISR, 0x1f, 0x0); 81outXGIIDXREG(XGISR, 0x20, 0xa1); 82outXGIIDXREG(XGISR, 0x22, 0xfb); 83outXGIIDXREG(XGISR, 0x26, 0x22); 84outXGIIDXREG(XGISR, 0x3e, 0x07); 85*/ 86 87//outXGIIDXREG(XGICR, 0x19, 0x00); 88//outXGIIDXREG(XGICR, 0x1a, 0x3C); 89//outXGIIDXREG(XGICR, 0x22, 0xff); 90//outXGIIDXREG(XGICR, 0x3D, 0x10); 91 92//outXGIIDXREG(XGICR, 0x4a, 0xf3); 93 94//outXGIIDXREG(XGICR, 0x57, 0x0); 95//outXGIIDXREG(XGICR, 0x7a, 0x2c); 96 97//outXGIIDXREG(XGICR, 0x82, 0xcc); 98//outXGIIDXREG(XGICR, 0x8c, 0x0); 99/* 100outXGIIDXREG(XGICR, 0x99, 0x1); 101outXGIIDXREG(XGICR, 0x41, 0x40); 102*/ 103 104 for(i=0; i < 0x4f; i++) 105 { 106 inXGIIDXREG(XGISR, i, reg); 107 printk("\no 3c4 %x",i); 108 printk("\ni 3c5 => %x",reg); 109 } 110 111 for(i=0; i < 0xF0; i++) 112 { 113 inXGIIDXREG(XGICR, i, reg); 114 printk("\no 3d4 %x",i); 115 printk("\ni 3d5 => %x",reg); 116 } 117/* 118 119 outXGIIDXREG(XGIPART1,0x2F,1); 120 for(i=1; i < 0x50; i++) 121 { 122 inXGIIDXREG(XGIPART1, i, reg); 123 printk("\no d004 %x",i); 124 printk("\ni d005 => %x",reg); 125 } 126 127 for(i=0; i < 0x50; i++) 128 { 129 inXGIIDXREG(XGIPART2, i, reg); 130 printk("\no d010 %x",i); 131 printk("\ni d011 => %x",reg); 132 } 133 for(i=0; i < 0x50; i++) 134 { 135 inXGIIDXREG(XGIPART3, i, reg); 136 printk("\no d012 %x",i); 137 printk("\ni d013 => %x",reg); 138 } 139 for(i=0; i < 0x50; i++) 140 { 141 inXGIIDXREG(XGIPART4, i, reg); 142 printk("\no d014 %x",i); 143 printk("\ni d015 => %x",reg); 144 } 145*/ 146} 147#else 148static inline void dumpVGAReg(void) {} 149#endif 150 151/* data for XGI components */ 152struct video_info xgi_video_info; 153 154 155#define DEBUGPRN(x) 156 157 158/* --------------- Hardware Access Routines -------------------------- */ 159 160int 161XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr, struct xgi_hw_device_info *HwDeviceExtension, 162 unsigned char modeno, unsigned char rateindex) 163{ 164 unsigned short ModeNo = modeno; 165 unsigned short ModeIdIndex = 0, ClockIndex = 0; 166 unsigned short RefreshRateTableIndex = 0; 167 168 /*unsigned long temp = 0;*/ 169 int Clock; 170 XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase; 171 InitTo330Pointer( HwDeviceExtension->jChipType, XGI_Pr ) ; 172 173 RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, XGI_Pr ) ; 174 175/* 176 temp = XGI_SearchModeID( ModeNo , &ModeIdIndex, XGI_Pr ) ; 177 if(!temp) { 178 printk(KERN_ERR "Could not find mode %x\n", ModeNo); 179 return 65000; 180 } 181 182 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex; 183 RefreshRateTableIndex += (rateindex - 1); 184 185*/ 186 ClockIndex = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK; 187 if(HwDeviceExtension->jChipType < XGI_315H) { 188 ClockIndex &= 0x3F; 189 } 190 Clock = XGI_Pr->VCLKData[ClockIndex].CLOCK * 1000 ; 191 192 return(Clock); 193} 194 195int 196XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr, struct xgi_hw_device_info *HwDeviceExtension, 197 unsigned char modeno, unsigned char rateindex, 198 u32 *left_margin, u32 *right_margin, 199 u32 *upper_margin, u32 *lower_margin, 200 u32 *hsync_len, u32 *vsync_len, 201 u32 *sync, u32 *vmode) 202{ 203 unsigned short ModeNo = modeno; 204 unsigned short ModeIdIndex = 0, index = 0; 205 unsigned short RefreshRateTableIndex = 0; 206 207 unsigned short VRE, VBE, VRS, VBS, VDE, VT; 208 unsigned short HRE, HBE, HRS, HBS, HDE, HT; 209 unsigned char sr_data, cr_data, cr_data2; 210 unsigned long cr_data3; 211 int A, B, C, D, E, F, temp, j; 212 XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase; 213 InitTo330Pointer( HwDeviceExtension->jChipType, XGI_Pr ) ; 214 RefreshRateTableIndex = XGI_GetRatePtrCRT2( HwDeviceExtension, ModeNo , ModeIdIndex, XGI_Pr ) ; 215/* 216 temp = XGI_SearchModeID( ModeNo, &ModeIdIndex, XGI_Pr); 217 if(!temp) return 0; 218 219 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex; 220 RefreshRateTableIndex += (rateindex - 1); 221*/ 222 index = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC; 223 224 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[5]; 225 226 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[0]; 227 228 /* Horizontal total */ 229 HT = (cr_data & 0xff) | 230 ((unsigned short) (sr_data & 0x03) << 8); 231 A = HT + 5; 232 233 /*cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1]; 234 235 Horizontal display enable end 236 HDE = (cr_data & 0xff) | 237 ((unsigned short) (sr_data & 0x0C) << 6);*/ 238 HDE = (XGI_Pr->RefIndex[RefreshRateTableIndex].XRes >> 3) -1; 239 E = HDE + 1; 240 241 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[3]; 242 243 /* Horizontal retrace (=sync) start */ 244 HRS = (cr_data & 0xff) | 245 ((unsigned short) (sr_data & 0xC0) << 2); 246 F = HRS - E - 3; 247 248 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1]; 249 250 /* Horizontal blank start */ 251 HBS = (cr_data & 0xff) | 252 ((unsigned short) (sr_data & 0x30) << 4); 253 254 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[6]; 255 256 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[2]; 257 258 cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[4]; 259 260 /* Horizontal blank end */ 261 HBE = (cr_data & 0x1f) | 262 ((unsigned short) (cr_data2 & 0x80) >> 2) | 263 ((unsigned short) (sr_data & 0x03) << 6); 264 265 /* Horizontal retrace (=sync) end */ 266 HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3); 267 268 temp = HBE - ((E - 1) & 255); 269 B = (temp > 0) ? temp : (temp + 256); 270 271 temp = HRE - ((E + F + 3) & 63); 272 C = (temp > 0) ? temp : (temp + 64); 273 274 D = B - F - C; 275 276 *left_margin = D * 8; 277 *right_margin = F * 8; 278 *hsync_len = C * 8; 279 280 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[14]; 281 282 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[8]; 283 284 cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[9]; 285 286 /* Vertical total */ 287 VT = (cr_data & 0xFF) | 288 ((unsigned short) (cr_data2 & 0x01) << 8) | 289 ((unsigned short)(cr_data2 & 0x20) << 4) | 290 ((unsigned short) (sr_data & 0x01) << 10); 291 A = VT + 2; 292 293 //cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10]; 294 295 /* Vertical display enable end */ 296/* VDE = (cr_data & 0xff) | 297 ((unsigned short) (cr_data2 & 0x02) << 7) | 298 ((unsigned short) (cr_data2 & 0x40) << 3) | 299 ((unsigned short) (sr_data & 0x02) << 9); */ 300 VDE = XGI_Pr->RefIndex[RefreshRateTableIndex].YRes -1; 301 E = VDE + 1; 302 303 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10]; 304 305 /* Vertical retrace (=sync) start */ 306 VRS = (cr_data & 0xff) | 307 ((unsigned short) (cr_data2 & 0x04) << 6) | 308 ((unsigned short) (cr_data2 & 0x80) << 2) | 309 ((unsigned short) (sr_data & 0x08) << 7); 310 F = VRS + 1 - E; 311 312 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[12]; 313 314 cr_data3 = (XGI_Pr->XGINEWUB_CRT1Table[index].CR[14] & 0x80) << 5; 315 316 /* Vertical blank start */ 317 VBS = (cr_data & 0xff) | 318 ((unsigned short) (cr_data2 & 0x08) << 5) | 319 ((unsigned short) (cr_data3 & 0x20) << 4) | 320 ((unsigned short) (sr_data & 0x04) << 8); 321 322 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[13]; 323 324 /* Vertical blank end */ 325 VBE = (cr_data & 0xff) | 326 ((unsigned short) (sr_data & 0x10) << 4); 327 temp = VBE - ((E - 1) & 511); 328 B = (temp > 0) ? temp : (temp + 512); 329 330 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[11]; 331 332 /* Vertical retrace (=sync) end */ 333 VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1); 334 temp = VRE - ((E + F - 1) & 31); 335 C = (temp > 0) ? temp : (temp + 32); 336 337 D = B - F - C; 338 339 *upper_margin = D; 340 *lower_margin = F; 341 *vsync_len = C; 342 343 if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000) 344 *sync &= ~FB_SYNC_VERT_HIGH_ACT; 345 else 346 *sync |= FB_SYNC_VERT_HIGH_ACT; 347 348 if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000) 349 *sync &= ~FB_SYNC_HOR_HIGH_ACT; 350 else 351 *sync |= FB_SYNC_HOR_HIGH_ACT; 352 353 *vmode = FB_VMODE_NONINTERLACED; 354 if(XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080) 355 *vmode = FB_VMODE_INTERLACED; 356 else { 357 j = 0; 358 while(XGI_Pr->EModeIDTable[j].Ext_ModeID != 0xff) { 359 if(XGI_Pr->EModeIDTable[j].Ext_ModeID == 360 XGI_Pr->RefIndex[RefreshRateTableIndex].ModeID) { 361 if(XGI_Pr->EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) { 362 *vmode = FB_VMODE_DOUBLE; 363 } 364 break; 365 } 366 j++; 367 } 368 } 369 370 return 1; 371} 372 373 374 375 376void XGIRegInit(struct vb_device_info *XGI_Pr, unsigned long BaseAddr) 377{ 378 XGI_Pr->RelIO = BaseAddr; 379 XGI_Pr->P3c4 = BaseAddr + 0x14; 380 XGI_Pr->P3d4 = BaseAddr + 0x24; 381 XGI_Pr->P3c0 = BaseAddr + 0x10; 382 XGI_Pr->P3ce = BaseAddr + 0x1e; 383 XGI_Pr->P3c2 = BaseAddr + 0x12; 384 XGI_Pr->P3ca = BaseAddr + 0x1a; 385 XGI_Pr->P3c6 = BaseAddr + 0x16; 386 XGI_Pr->P3c7 = BaseAddr + 0x17; 387 XGI_Pr->P3c8 = BaseAddr + 0x18; 388 XGI_Pr->P3c9 = BaseAddr + 0x19; 389 XGI_Pr->P3da = BaseAddr + 0x2A; 390 XGI_Pr->Part1Port = BaseAddr + XGI_CRT2_PORT_04; /* Digital video interface registers (LCD) */ 391 XGI_Pr->Part2Port = BaseAddr + XGI_CRT2_PORT_10; /* 301 TV Encoder registers */ 392 XGI_Pr->Part3Port = BaseAddr + XGI_CRT2_PORT_12; /* 301 Macrovision registers */ 393 XGI_Pr->Part4Port = BaseAddr + XGI_CRT2_PORT_14; /* 301 VGA2 (and LCD) registers */ 394 XGI_Pr->Part5Port = BaseAddr + XGI_CRT2_PORT_14+2; /* 301 palette address port registers */ 395 396} 397 398 399void XGIfb_set_reg4(u16 port, unsigned long data) 400{ 401 outl((u32) (data & 0xffffffff), port); 402} 403 404u32 XGIfb_get_reg3(u16 port) 405{ 406 u32 data; 407 408 data = inl(port); 409 return (data); 410} 411 412/* ------------ Interface for init & mode switching code ------------- */ 413 414unsigned char 415XGIfb_query_VGA_config_space(struct xgi_hw_device_info *pXGIhw_ext, 416 unsigned long offset, unsigned long set, unsigned long *value) 417{ 418 static struct pci_dev *pdev = NULL; 419 static unsigned char init = 0, valid_pdev = 0; 420 421 if (!set) 422 DPRINTK("XGIfb: Get VGA offset 0x%lx\n", offset); 423 else 424 DPRINTK("XGIfb: Set offset 0x%lx to 0x%lx\n", offset, *value); 425 426 if (!init) { 427 init = 1; 428 pdev = pci_get_device(PCI_VENDOR_ID_XG, xgi_video_info.chip_id, pdev); 429 if (pdev) { 430 valid_pdev = 1; 431 pci_dev_put(pdev); 432 } 433 } 434 435 if (!valid_pdev) { 436 printk(KERN_DEBUG "XGIfb: Can't find XGI %d VGA device.\n", 437 xgi_video_info.chip_id); 438 return 0; 439 } 440 441 if (set == 0) 442 pci_read_config_dword(pdev, offset, (u32 *)value); 443 else 444 pci_write_config_dword(pdev, offset, (u32)(*value)); 445 446 return 1; 447} 448 449/*unsigned char XGIfb_query_north_bridge_space(struct xgi_hw_device_info *pXGIhw_ext, 450 unsigned long offset, unsigned long set, unsigned long *value) 451{ 452 static struct pci_dev *pdev = NULL; 453 static unsigned char init = 0, valid_pdev = 0; 454 u16 nbridge_id = 0; 455 456 if (!init) { 457 init = 1; 458 switch (xgi_video_info.chip) { 459 case XGI_540: 460 nbridge_id = PCI_DEVICE_ID_XG_540; 461 break; 462 case XGI_630: 463 nbridge_id = PCI_DEVICE_ID_XG_630; 464 break; 465 case XGI_730: 466 nbridge_id = PCI_DEVICE_ID_XG_730; 467 break; 468 case XGI_550: 469 nbridge_id = PCI_DEVICE_ID_XG_550; 470 break; 471 case XGI_650: 472 nbridge_id = PCI_DEVICE_ID_XG_650; 473 break; 474 case XGI_740: 475 nbridge_id = PCI_DEVICE_ID_XG_740; 476 break; 477 default: 478 nbridge_id = 0; 479 break; 480 } 481 482 pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridge_id, pdev); 483 if (pdev) 484 valid_pdev = 1; 485 } 486 487 if (!valid_pdev) { 488 printk(KERN_DEBUG "XGIfb: Can't find XGI %d North Bridge device.\n", 489 nbridge_id); 490 return 0; 491 } 492 493 if (set == 0) 494 pci_read_config_dword(pdev, offset, (u32 *)value); 495 else 496 pci_write_config_dword(pdev, offset, (u32)(*value)); 497 498 return 1; 499} 500*/ 501/* ------------------ Internal helper routines ----------------- */ 502 503static void XGIfb_search_mode(const char *name) 504{ 505 int i = 0, j = 0, l; 506 507 if(name == NULL) { 508 printk(KERN_ERR "XGIfb: Internal error, using default mode.\n"); 509 xgifb_mode_idx = DEFAULT_MODE; 510 if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD)) 511 { 512 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx(); 513 } 514 return; 515 } 516 517 518 if (!strcmp(name, XGIbios_mode[MODE_INDEX_NONE].name)) { 519 printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n"); 520 xgifb_mode_idx = DEFAULT_MODE; 521 if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD)) 522 { 523 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx(); 524 } 525 return; 526 } 527 528 while(XGIbios_mode[i].mode_no != 0) { 529 l = min(strlen(name), strlen(XGIbios_mode[i].name)); 530 if (!strncmp(name, XGIbios_mode[i].name, l)) { 531 xgifb_mode_idx = i; 532 j = 1; 533 break; 534 } 535 i++; 536 } 537 if(!j) printk(KERN_INFO "XGIfb: Invalid mode '%s'\n", name); 538} 539 540static void XGIfb_search_vesamode(unsigned int vesamode) 541{ 542 int i = 0, j = 0; 543 544 if(vesamode == 0) { 545 546 printk(KERN_ERR "XGIfb: Mode 'none' not supported anymore. Using default.\n"); 547 xgifb_mode_idx = DEFAULT_MODE; 548 if ((xgi_video_info.chip == XG21) && ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD)) 549 { 550 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx(); 551 } 552 return; 553 } 554 555 vesamode &= 0x1dff; /* Clean VESA mode number from other flags */ 556 557 while(XGIbios_mode[i].mode_no != 0) { 558 if( (XGIbios_mode[i].vesa_mode_no_1 == vesamode) || 559 (XGIbios_mode[i].vesa_mode_no_2 == vesamode) ) { 560 xgifb_mode_idx = i; 561 j = 1; 562 break; 563 } 564 i++; 565 } 566 if(!j) printk(KERN_INFO "XGIfb: Invalid VESA mode 0x%x'\n", vesamode); 567} 568 569int XGIfb_GetXG21LVDSData(void) 570{ 571 u8 tmp; 572 unsigned char *pData; 573 int i,j,k; 574 575 inXGIIDXREG(XGISR,0x1e,tmp); 576 outXGIIDXREG(XGISR, 0x1e, tmp|4); 577 578 pData = xgi_video_info.mmio_vbase+0x20000; 579 if ((pData[0x0]==0x55) && (pData[0x1]==0xAA) && (pData[0x65] & 0x1)) 580 { 581 i = pData[ 0x316 ] | ( pData[ 0x317 ] << 8 ); 582 j = pData[ i-1 ] ; 583 if ( j == 0xff ) 584 { 585 j = 1; 586 } 587 k = 0; 588 do 589 { 590 XGI21_LCDCapList[k].LVDS_Capability = pData[ i ] | ( pData[ i + 1 ] << 8 ); 591 XGI21_LCDCapList[k].LVDSHT = pData[ i + 2 ] | ( pData[ i + 3 ] << 8 ) ; 592 XGI21_LCDCapList[k].LVDSVT = pData[ i + 4 ] | ( pData[ i + 5 ] << 8 ); 593 XGI21_LCDCapList[k].LVDSHDE = pData[ i + 6 ] | ( pData[ i + 7 ] << 8 ); 594 XGI21_LCDCapList[k].LVDSVDE = pData[ i + 8 ] | ( pData[ i + 9 ] << 8 ); 595 XGI21_LCDCapList[k].LVDSHFP = pData[ i + 10 ] | ( pData[ i + 11 ] << 8 ); 596 XGI21_LCDCapList[k].LVDSVFP = pData[ i + 12 ] | ( pData[ i + 13 ] << 8 ); 597 XGI21_LCDCapList[k].LVDSHSYNC = pData[ i + 14 ] | ( pData[ i + 15 ] << 8 ); 598 XGI21_LCDCapList[k].LVDSVSYNC = pData[ i + 16 ] | ( pData[ i + 17 ] << 8 ); 599 XGI21_LCDCapList[k].VCLKData1 = pData[ i + 18 ] ; 600 XGI21_LCDCapList[k].VCLKData2 = pData[ i + 19 ] ; 601 XGI21_LCDCapList[k].PSC_S1 = pData[ i + 20 ] ; 602 XGI21_LCDCapList[k].PSC_S2 = pData[ i + 21 ] ; 603 XGI21_LCDCapList[k].PSC_S3 = pData[ i + 22 ] ; 604 XGI21_LCDCapList[k].PSC_S4 = pData[ i + 23 ] ; 605 XGI21_LCDCapList[k].PSC_S5 = pData[ i + 24 ] ; 606 i += 25; 607 j--; 608 k++; 609 } while ((j > 0) && 610 (k < (sizeof(XGI21_LCDCapList)/sizeof(struct XGI21_LVDSCapStruct)))); 611 return 1; 612 } 613 return 0; 614} 615 616int XGIfb_GetXG21DefaultLVDSModeIdx(void) 617{ 618 619 int found_mode = 0; 620 int XGIfb_mode_idx = 0; 621 622 found_mode = 0; 623 while( (XGIbios_mode[XGIfb_mode_idx].mode_no != 0) && 624 (XGIbios_mode[XGIfb_mode_idx].xres <= XGI21_LCDCapList[0].LVDSHDE) ) 625 { 626 if( (XGIbios_mode[XGIfb_mode_idx].xres == XGI21_LCDCapList[0].LVDSHDE) && 627 (XGIbios_mode[XGIfb_mode_idx].yres == XGI21_LCDCapList[0].LVDSVDE) && 628 (XGIbios_mode[XGIfb_mode_idx].bpp == 8)) 629 { 630 XGIfb_mode_no = XGIbios_mode[XGIfb_mode_idx].mode_no; 631 found_mode = 1; 632 break; 633 } 634 XGIfb_mode_idx++; 635 } 636 if (!found_mode) 637 XGIfb_mode_idx = 0; 638 639 return (XGIfb_mode_idx); 640} 641 642 643static int XGIfb_validate_mode(int myindex) 644{ 645 u16 xres, yres; 646 647 if (xgi_video_info.chip == XG21) 648 { 649 if ((xgi_video_info.disp_state & DISPTYPE_DISP2) == DISPTYPE_LCD) 650 { 651 xres = XGI21_LCDCapList[0].LVDSHDE; 652 yres = XGI21_LCDCapList[0].LVDSVDE; 653 if(XGIbios_mode[myindex].xres > xres) 654 return(-1); 655 if(XGIbios_mode[myindex].yres > yres) 656 return(-1); 657 if ((XGIbios_mode[myindex].xres < xres) && (XGIbios_mode[myindex].yres < yres) ) 658 { 659 if (XGIbios_mode[myindex].bpp > 8) 660 return(-1); 661 } 662 663 } 664 return(myindex); 665 666 } 667 668 if (xgi_video_info.chip == XG27) 669 return(myindex); 670 671 if(!(XGIbios_mode[myindex].chipset & MD_XGI315)) 672 return(-1); 673 674 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) { 675 case DISPTYPE_LCD: 676 switch (XGIhw_ext.ulCRT2LCDType) { 677 case LCD_640x480: 678 xres = 640; yres = 480; break; 679 case LCD_800x600: 680 xres = 800; yres = 600; break; 681 case LCD_1024x600: 682 xres = 1024; yres = 600; break; 683 case LCD_1024x768: 684 xres = 1024; yres = 768; break; 685 case LCD_1152x768: 686 xres = 1152; yres = 768; break; 687 case LCD_1280x960: 688 xres = 1280; yres = 960; break; 689 case LCD_1280x768: 690 xres = 1280; yres = 768; break; 691 case LCD_1280x1024: 692 xres = 1280; yres = 1024; break; 693 case LCD_1400x1050: 694 xres = 1400; yres = 1050; break; 695 case LCD_1600x1200: 696 xres = 1600; yres = 1200; break; 697// case LCD_320x480: // TW: FSTN 698// xres = 320; yres = 480; break; 699 default: 700 xres = 0; yres = 0; break; 701 } 702 if(XGIbios_mode[myindex].xres > xres) { 703 return(-1); 704 } 705 if(XGIbios_mode[myindex].yres > yres) { 706 return(-1); 707 } 708 if((XGIhw_ext.ulExternalChip == 0x01) || // LVDS 709 (XGIhw_ext.ulExternalChip == 0x05)) // LVDS+Chrontel 710 { 711 switch (XGIbios_mode[myindex].xres) { 712 case 512: 713 if(XGIbios_mode[myindex].yres != 512) return -1; 714 if(XGIhw_ext.ulCRT2LCDType == LCD_1024x600) return -1; 715 break; 716 case 640: 717 if((XGIbios_mode[myindex].yres != 400) && 718 (XGIbios_mode[myindex].yres != 480)) 719 return -1; 720 break; 721 case 800: 722 if(XGIbios_mode[myindex].yres != 600) return -1; 723 break; 724 case 1024: 725 if((XGIbios_mode[myindex].yres != 600) && 726 (XGIbios_mode[myindex].yres != 768)) 727 return -1; 728 if((XGIbios_mode[myindex].yres == 600) && 729 (XGIhw_ext.ulCRT2LCDType != LCD_1024x600)) 730 return -1; 731 break; 732 case 1152: 733 if((XGIbios_mode[myindex].yres) != 768) return -1; 734 if(XGIhw_ext.ulCRT2LCDType != LCD_1152x768) return -1; 735 break; 736 case 1280: 737 if((XGIbios_mode[myindex].yres != 768) && 738 (XGIbios_mode[myindex].yres != 1024)) 739 return -1; 740 if((XGIbios_mode[myindex].yres == 768) && 741 (XGIhw_ext.ulCRT2LCDType != LCD_1280x768)) 742 return -1; 743 break; 744 case 1400: 745 if(XGIbios_mode[myindex].yres != 1050) return -1; 746 break; 747 case 1600: 748 if(XGIbios_mode[myindex].yres != 1200) return -1; 749 break; 750 default: 751 return -1; 752 } 753 } else { 754 switch (XGIbios_mode[myindex].xres) { 755 case 512: 756 if(XGIbios_mode[myindex].yres != 512) return -1; 757 break; 758 case 640: 759 if((XGIbios_mode[myindex].yres != 400) && 760 (XGIbios_mode[myindex].yres != 480)) 761 return -1; 762 break; 763 case 800: 764 if(XGIbios_mode[myindex].yres != 600) return -1; 765 break; 766 case 1024: 767 if(XGIbios_mode[myindex].yres != 768) return -1; 768 break; 769 case 1280: 770 if((XGIbios_mode[myindex].yres != 960) && 771 (XGIbios_mode[myindex].yres != 1024)) 772 return -1; 773 if(XGIbios_mode[myindex].yres == 960) { 774 if(XGIhw_ext.ulCRT2LCDType == LCD_1400x1050) 775 return -1; 776 } 777 break; 778 case 1400: 779 if(XGIbios_mode[myindex].yres != 1050) return -1; 780 break; 781 case 1600: 782 if(XGIbios_mode[myindex].yres != 1200) return -1; 783 break; 784 default: 785 return -1; 786 } 787 } 788 break; 789 case DISPTYPE_TV: 790 switch (XGIbios_mode[myindex].xres) { 791 case 512: 792 case 640: 793 case 800: 794 break; 795 case 720: 796 if (xgi_video_info.TV_type == TVMODE_NTSC) { 797 if (XGIbios_mode[myindex].yres != 480) { 798 return(-1); 799 } 800 } else if (xgi_video_info.TV_type == TVMODE_PAL) { 801 if (XGIbios_mode[myindex].yres != 576) { 802 return(-1); 803 } 804 } 805 // TW: LVDS/CHRONTEL does not support 720 806 if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL || 807 xgi_video_info.hasVB == HASVB_CHRONTEL) { 808 return(-1); 809 } 810 break; 811 case 1024: 812 if (xgi_video_info.TV_type == TVMODE_NTSC) { 813 if(XGIbios_mode[myindex].bpp == 32) { 814 return(-1); 815 } 816 } 817 // TW: LVDS/CHRONTEL only supports < 800 (1024 on 650/Ch7019) 818 if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL || 819 xgi_video_info.hasVB == HASVB_CHRONTEL) { 820 if(xgi_video_info.chip < XGI_315H) { 821 return(-1); 822 } 823 } 824 break; 825 default: 826 return(-1); 827 } 828 break; 829 case DISPTYPE_CRT2: 830 if(XGIbios_mode[myindex].xres > 1280) return -1; 831 break; 832 } 833 return(myindex); 834 835} 836 837static void XGIfb_search_crt2type(const char *name) 838{ 839 int i = 0; 840 841 if(name == NULL) 842 return; 843 844 while(XGI_crt2type[i].type_no != -1) { 845 if (!strcmp(name, XGI_crt2type[i].name)) { 846 XGIfb_crt2type = XGI_crt2type[i].type_no; 847 XGIfb_tvplug = XGI_crt2type[i].tvplug_no; 848 break; 849 } 850 i++; 851 } 852 if(XGIfb_crt2type < 0) 853 printk(KERN_INFO "XGIfb: Invalid CRT2 type: %s\n", name); 854} 855 856static void XGIfb_search_queuemode(const char *name) 857{ 858 int i = 0; 859 860 if(name == NULL) 861 return; 862 863 while (XGI_queuemode[i].type_no != -1) { 864 if (!strcmp(name, XGI_queuemode[i].name)) { 865 XGIfb_queuemode = XGI_queuemode[i].type_no; 866 break; 867 } 868 i++; 869 } 870 if (XGIfb_queuemode < 0) 871 printk(KERN_INFO "XGIfb: Invalid queuemode type: %s\n", name); 872} 873 874static u8 XGIfb_search_refresh_rate(unsigned int rate) 875{ 876 u16 xres, yres; 877 int i = 0; 878 879 xres = XGIbios_mode[xgifb_mode_idx].xres; 880 yres = XGIbios_mode[xgifb_mode_idx].yres; 881 882 XGIfb_rate_idx = 0; 883 while ((XGIfb_vrate[i].idx != 0) && (XGIfb_vrate[i].xres <= xres)) { 884 if ((XGIfb_vrate[i].xres == xres) && (XGIfb_vrate[i].yres == yres)) { 885 if (XGIfb_vrate[i].refresh == rate) { 886 XGIfb_rate_idx = XGIfb_vrate[i].idx; 887 break; 888 } else if (XGIfb_vrate[i].refresh > rate) { 889 if ((XGIfb_vrate[i].refresh - rate) <= 3) { 890 DPRINTK("XGIfb: Adjusting rate from %d up to %d\n", 891 rate, XGIfb_vrate[i].refresh); 892 XGIfb_rate_idx = XGIfb_vrate[i].idx; 893 xgi_video_info.refresh_rate = XGIfb_vrate[i].refresh; 894 } else if (((rate - XGIfb_vrate[i-1].refresh) <= 2) 895 && (XGIfb_vrate[i].idx != 1)) { 896 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n", 897 rate, XGIfb_vrate[i-1].refresh); 898 XGIfb_rate_idx = XGIfb_vrate[i-1].idx; 899 xgi_video_info.refresh_rate = XGIfb_vrate[i-1].refresh; 900 } 901 break; 902 } else if((rate - XGIfb_vrate[i].refresh) <= 2) { 903 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n", 904 rate, XGIfb_vrate[i].refresh); 905 XGIfb_rate_idx = XGIfb_vrate[i].idx; 906 break; 907 } 908 } 909 i++; 910 } 911 if (XGIfb_rate_idx > 0) { 912 return XGIfb_rate_idx; 913 } else { 914 printk(KERN_INFO 915 "XGIfb: Unsupported rate %d for %dx%d\n", rate, xres, yres); 916 return 0; 917 } 918} 919 920static void XGIfb_search_tvstd(const char *name) 921{ 922 int i = 0; 923 924 if(name == NULL) 925 return; 926 927 while (XGI_tvtype[i].type_no != -1) { 928 if (!strcmp(name, XGI_tvtype[i].name)) { 929 XGIfb_tvmode = XGI_tvtype[i].type_no; 930 break; 931 } 932 i++; 933 } 934} 935 936static unsigned char XGIfb_bridgeisslave(void) 937{ 938 unsigned char usScratchP1_00; 939 940 if (xgi_video_info.hasVB == HASVB_NONE) 941 return 0; 942 943 inXGIIDXREG(XGIPART1,0x00,usScratchP1_00); 944 if ((usScratchP1_00 & 0x50) == 0x10) 945 return 1; 946 else 947 return 0; 948} 949 950static unsigned char XGIfbcheckvretracecrt1(void) 951{ 952 unsigned char temp; 953 954 inXGIIDXREG(XGICR,0x17,temp); 955 if (!(temp & 0x80)) 956 return 0; 957 958 959 inXGIIDXREG(XGISR,0x1f,temp); 960 if (temp & 0xc0) 961 return 0; 962 963 if (inXGIREG(XGIINPSTAT) & 0x08) 964 return 1; 965 else 966 return 0; 967} 968 969static unsigned char XGIfbcheckvretracecrt2(void) 970{ 971 unsigned char temp; 972 if (xgi_video_info.hasVB == HASVB_NONE) 973 return 0; 974 inXGIIDXREG(XGIPART1, 0x30, temp); 975 if (temp & 0x02) 976 return 0; 977 else 978 return 1; 979} 980 981static unsigned char XGIfb_CheckVBRetrace(void) 982{ 983 if(xgi_video_info.disp_state & DISPTYPE_DISP2) { 984 if(XGIfb_bridgeisslave()) { 985 return(XGIfbcheckvretracecrt1()); 986 } else { 987 return(XGIfbcheckvretracecrt2()); 988 } 989 } 990 return(XGIfbcheckvretracecrt1()); 991} 992 993/* ----------- FBDev related routines for all series ----------- */ 994 995 996static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var) 997{ 998 switch(var->bits_per_pixel) { 999 case 8: 1000 var->red.offset = var->green.offset = var->blue.offset = 0; 1001 var->red.length = var->green.length = var->blue.length = 6; 1002 xgi_video_info.video_cmap_len = 256; 1003 break; 1004 case 16: 1005 var->red.offset = 11; 1006 var->red.length = 5; 1007 var->green.offset = 5; 1008 var->green.length = 6; 1009 var->blue.offset = 0; 1010 var->blue.length = 5; 1011 var->transp.offset = 0; 1012 var->transp.length = 0; 1013 xgi_video_info.video_cmap_len = 16; 1014 break; 1015 case 32: 1016 var->red.offset = 16; 1017 var->red.length = 8; 1018 var->green.offset = 8; 1019 var->green.length = 8; 1020 var->blue.offset = 0; 1021 var->blue.length = 8; 1022 var->transp.offset = 24; 1023 var->transp.length = 8; 1024 xgi_video_info.video_cmap_len = 16; 1025 break; 1026 } 1027} 1028 1029 1030 1031static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, 1032 struct fb_info *info) 1033{ 1034 1035 unsigned int htotal = var->left_margin + var->xres + 1036 var->right_margin + var->hsync_len; 1037 unsigned int vtotal = var->upper_margin + var->yres + 1038 var->lower_margin + var->vsync_len; 1039#if defined(__powerpc__) 1040 u8 sr_data, cr_data; 1041#endif 1042 unsigned int drate = 0, hrate = 0; 1043 int found_mode = 0; 1044 int old_mode; 1045// unsigned char reg,reg1; 1046 1047 DEBUGPRN("Inside do_set_var"); 1048// printk(KERN_DEBUG "XGIfb:var->yres=%d, var->upper_margin=%d, var->lower_margin=%d, var->vsync_len=%d\n", var->yres,var->upper_margin,var->lower_margin,var->vsync_len); 1049 1050 info->var.xres_virtual = var->xres_virtual; 1051 info->var.yres_virtual = var->yres_virtual; 1052 info->var.bits_per_pixel = var->bits_per_pixel; 1053 1054 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) 1055 vtotal <<= 1; 1056 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) 1057 vtotal <<= 2; 1058 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) 1059 { 1060// vtotal <<= 1; 1061// var->yres <<= 1; 1062 } 1063 1064 if(!htotal || !vtotal) { 1065 DPRINTK("XGIfb: Invalid 'var' information\n"); 1066 return -EINVAL; 1067 } 1068 printk(KERN_DEBUG "XGIfb: var->pixclock=%d, htotal=%d, vtotal=%d\n", 1069 var->pixclock,htotal,vtotal); 1070 1071 1072 1073 if(var->pixclock && htotal && vtotal) { 1074 drate = 1000000000 / var->pixclock; 1075 hrate = (drate * 1000) / htotal; 1076 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal); 1077 } else { 1078 xgi_video_info.refresh_rate = 60; 1079 } 1080 1081 printk(KERN_DEBUG "XGIfb: Change mode to %dx%dx%d-%dHz\n", 1082 var->xres,var->yres,var->bits_per_pixel,xgi_video_info.refresh_rate); 1083 1084 old_mode = xgifb_mode_idx; 1085 xgifb_mode_idx = 0; 1086 1087 while( (XGIbios_mode[xgifb_mode_idx].mode_no != 0) && 1088 (XGIbios_mode[xgifb_mode_idx].xres <= var->xres) ) { 1089 if( (XGIbios_mode[xgifb_mode_idx].xres == var->xres) && 1090 (XGIbios_mode[xgifb_mode_idx].yres == var->yres) && 1091 (XGIbios_mode[xgifb_mode_idx].bpp == var->bits_per_pixel)) { 1092 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no; 1093 found_mode = 1; 1094 break; 1095 } 1096 xgifb_mode_idx++; 1097 } 1098 1099 if(found_mode) 1100 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx); 1101 else 1102 xgifb_mode_idx = -1; 1103 1104 if(xgifb_mode_idx < 0) { 1105 printk(KERN_ERR "XGIfb: Mode %dx%dx%d not supported\n", var->xres, 1106 var->yres, var->bits_per_pixel); 1107 xgifb_mode_idx = old_mode; 1108 return -EINVAL; 1109 } 1110 1111 if(XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) { 1112 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx; 1113 xgi_video_info.refresh_rate = 60; 1114 } 1115 1116 if(isactive) { 1117 1118 1119 XGIfb_pre_setmode(); 1120 if(XGISetModeNew( &XGIhw_ext, XGIfb_mode_no) == 0) { 1121 printk(KERN_ERR "XGIfb: Setting mode[0x%x] failed\n", XGIfb_mode_no); 1122 return -EINVAL; 1123 } 1124 info->fix.line_length = ((info->var.xres_virtual * info->var.bits_per_pixel)>>6); 1125 1126 outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD); 1127 1128 outXGIIDXREG(XGICR,0x13,(info->fix.line_length & 0x00ff)); 1129 outXGIIDXREG(XGISR,0x0E,(info->fix.line_length & 0xff00)>>8); 1130 1131 XGIfb_post_setmode(); 1132 1133 DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d \n", 1134 XGIbios_mode[xgifb_mode_idx].xres, 1135 XGIbios_mode[xgifb_mode_idx].yres, 1136 XGIbios_mode[xgifb_mode_idx].bpp, 1137 xgi_video_info.refresh_rate); 1138 1139 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp; 1140 xgi_video_info.video_vwidth = info->var.xres_virtual; 1141 xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres; 1142 xgi_video_info.video_vheight = info->var.yres_virtual; 1143 xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres; 1144 xgi_video_info.org_x = xgi_video_info.org_y = 0; 1145 xgi_video_info.video_linelength = info->var.xres_virtual * (xgi_video_info.video_bpp >> 3); 1146 xgi_video_info.accel = 0; 1147 if(XGIfb_accel) { 1148 xgi_video_info.accel = (var->accel_flags & FB_ACCELF_TEXT) ? -1 : 0; 1149 } 1150 switch(xgi_video_info.video_bpp) 1151 { 1152 case 8: 1153 xgi_video_info.DstColor = 0x0000; 1154 xgi_video_info.XGI310_AccelDepth = 0x00000000; 1155 xgi_video_info.video_cmap_len = 256; 1156#if defined(__powerpc__) 1157 inXGIIDXREG (XGICR, 0x4D, cr_data); 1158 outXGIIDXREG(XGICR, 0x4D, (cr_data & 0xE0)); 1159#endif 1160 break; 1161 case 16: 1162 xgi_video_info.DstColor = 0x8000; 1163 xgi_video_info.XGI310_AccelDepth = 0x00010000; 1164#if defined(__powerpc__) 1165 inXGIIDXREG (XGICR, 0x4D, cr_data); 1166 outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B)); 1167#endif 1168 xgi_video_info.video_cmap_len = 16; 1169 break; 1170 case 32: 1171 xgi_video_info.DstColor = 0xC000; 1172 xgi_video_info.XGI310_AccelDepth = 0x00020000; 1173 xgi_video_info.video_cmap_len = 16; 1174#if defined(__powerpc__) 1175 inXGIIDXREG (XGICR, 0x4D, cr_data); 1176 outXGIIDXREG(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15)); 1177#endif 1178 break; 1179 default: 1180 xgi_video_info.video_cmap_len = 16; 1181 printk(KERN_ERR "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp); 1182 xgi_video_info.accel = 0; 1183 break; 1184 } 1185 } 1186 XGIfb_bpp_to_var(var); /*update ARGB info*/ 1187 DEBUGPRN("End of do_set_var"); 1188 1189 dumpVGAReg(); 1190 return 0; 1191} 1192 1193#ifdef XGIFB_PAN 1194static int XGIfb_pan_var(struct fb_var_screeninfo *var) 1195{ 1196 unsigned int base; 1197 1198// printk("Inside pan_var"); 1199 1200 if (var->xoffset > (var->xres_virtual - var->xres)) { 1201// printk( "Pan: xo: %d xv %d xr %d\n", 1202// var->xoffset, var->xres_virtual, var->xres); 1203 return -EINVAL; 1204 } 1205 if(var->yoffset > (var->yres_virtual - var->yres)) { 1206// printk( "Pan: yo: %d yv %d yr %d\n", 1207// var->yoffset, var->yres_virtual, var->yres); 1208 return -EINVAL; 1209 } 1210 base = var->yoffset * var->xres_virtual + var->xoffset; 1211 1212 /* calculate base bpp dep. */ 1213 switch(var->bits_per_pixel) { 1214 case 16: 1215 base >>= 1; 1216 break; 1217 case 32: 1218 break; 1219 case 8: 1220 default: 1221 base >>= 2; 1222 break; 1223 } 1224 1225 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD); 1226 1227 outXGIIDXREG(XGICR, 0x0D, base & 0xFF); 1228 outXGIIDXREG(XGICR, 0x0C, (base >> 8) & 0xFF); 1229 outXGIIDXREG(XGISR, 0x0D, (base >> 16) & 0xFF); 1230 outXGIIDXREG(XGISR, 0x37, (base >> 24) & 0x03); 1231 setXGIIDXREG(XGISR, 0x37, 0xDF, (base >> 21) & 0x04); 1232 1233 if(xgi_video_info.disp_state & DISPTYPE_DISP2) { 1234 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01); 1235 outXGIIDXREG(XGIPART1, 0x06, (base & 0xFF)); 1236 outXGIIDXREG(XGIPART1, 0x05, ((base >> 8) & 0xFF)); 1237 outXGIIDXREG(XGIPART1, 0x04, ((base >> 16) & 0xFF)); 1238 setXGIIDXREG(XGIPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7); 1239 } 1240// printk("End of pan_var"); 1241 return 0; 1242} 1243#endif 1244 1245 1246void XGI_dispinfo(struct ap_data *rec) 1247{ 1248 rec->minfo.bpp = xgi_video_info.video_bpp; 1249 rec->minfo.xres = xgi_video_info.video_width; 1250 rec->minfo.yres = xgi_video_info.video_height; 1251 rec->minfo.v_xres = xgi_video_info.video_vwidth; 1252 rec->minfo.v_yres = xgi_video_info.video_vheight; 1253 rec->minfo.org_x = xgi_video_info.org_x; 1254 rec->minfo.org_y = xgi_video_info.org_y; 1255 rec->minfo.vrate = xgi_video_info.refresh_rate; 1256 rec->iobase = xgi_video_info.vga_base - 0x30; 1257 rec->mem_size = xgi_video_info.video_size; 1258 rec->disp_state = xgi_video_info.disp_state; 1259 rec->version = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL; 1260 rec->hasVB = xgi_video_info.hasVB; 1261 rec->TV_type = xgi_video_info.TV_type; 1262 rec->TV_plug = xgi_video_info.TV_plug; 1263 rec->chip = xgi_video_info.chip; 1264} 1265 1266 1267 1268 1269static int XGIfb_open(struct fb_info *info, int user) 1270{ 1271 return 0; 1272} 1273 1274static int XGIfb_release(struct fb_info *info, int user) 1275{ 1276 return 0; 1277} 1278 1279static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var) 1280{ 1281 int rc = 16; 1282 1283 switch(var->bits_per_pixel) { 1284 case 8: 1285 rc = 256; 1286 break; 1287 case 16: 1288 rc = 16; 1289 break; 1290 case 32: 1291 rc = 16; 1292 break; 1293 } 1294 return rc; 1295} 1296 1297static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, 1298 unsigned transp, struct fb_info *info) 1299{ 1300 if (regno >= XGIfb_get_cmap_len(&info->var)) 1301 return 1; 1302 1303 switch (info->var.bits_per_pixel) { 1304 case 8: 1305 outXGIREG(XGIDACA, regno); 1306 outXGIREG(XGIDACD, (red >> 10)); 1307 outXGIREG(XGIDACD, (green >> 10)); 1308 outXGIREG(XGIDACD, (blue >> 10)); 1309 if (xgi_video_info.disp_state & DISPTYPE_DISP2) { 1310 outXGIREG(XGIDAC2A, regno); 1311 outXGIREG(XGIDAC2D, (red >> 8)); 1312 outXGIREG(XGIDAC2D, (green >> 8)); 1313 outXGIREG(XGIDAC2D, (blue >> 8)); 1314 } 1315 break; 1316 case 16: 1317 ((u32 *)(info->pseudo_palette))[regno] = 1318 ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); 1319 break; 1320 case 32: 1321 red >>= 8; 1322 green >>= 8; 1323 blue >>= 8; 1324 ((u32 *) (info->pseudo_palette))[regno] = 1325 (red << 16) | (green << 8) | (blue); 1326 break; 1327 } 1328 return 0; 1329} 1330 1331static int XGIfb_set_par(struct fb_info *info) 1332{ 1333 int err; 1334 1335// printk("XGIfb: inside set_par\n"); 1336 if((err = XGIfb_do_set_var(&info->var, 1, info))) 1337 return err; 1338 XGIfb_get_fix(&info->fix, -1, info); 1339// printk("XGIfb:end of set_par\n"); 1340 return 0; 1341} 1342 1343static int XGIfb_check_var(struct fb_var_screeninfo *var, 1344 struct fb_info *info) 1345{ 1346 unsigned int htotal = 1347 var->left_margin + var->xres + var->right_margin + 1348 var->hsync_len; 1349 unsigned int vtotal = 0; 1350 unsigned int drate = 0, hrate = 0; 1351 int found_mode = 0; 1352 int refresh_rate, search_idx; 1353 1354 DEBUGPRN("Inside check_var"); 1355 1356 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) { 1357 vtotal = var->upper_margin + var->yres + var->lower_margin + 1358 var->vsync_len; 1359 vtotal <<= 1; 1360 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) { 1361 vtotal = var->upper_margin + var->yres + var->lower_margin + 1362 var->vsync_len; 1363 vtotal <<= 2; 1364 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { 1365 vtotal = var->upper_margin + (var->yres/2) + var->lower_margin + 1366 var->vsync_len; 1367 } else vtotal = var->upper_margin + var->yres + var->lower_margin + 1368 var->vsync_len; 1369 1370 if(!(htotal) || !(vtotal)) { 1371 XGIFAIL("XGIfb: no valid timing data"); 1372 } 1373 1374 1375 if(var->pixclock && htotal && vtotal) { 1376 drate = 1000000000 / var->pixclock; 1377 hrate = (drate * 1000) / htotal; 1378 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2 / vtotal); 1379 printk(KERN_DEBUG \ 1380 "%s: pixclock = %d ,htotal=%d, vtotal=%d\n" \ 1381 "%s: drate=%d, hrate=%d, refresh_rate=%d\n", 1382 __func__,var->pixclock, htotal, vtotal, 1383 __func__, drate, hrate, xgi_video_info.refresh_rate); 1384 } else { 1385 xgi_video_info.refresh_rate = 60; 1386 } 1387 1388/* 1389 if((var->pixclock) && (htotal)) { 1390 drate = 1E12 / var->pixclock; 1391 hrate = drate / htotal; 1392 refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5); 1393 } else refresh_rate = 60; 1394*/ 1395 /* TW: Calculation wrong for 1024x600 - force it to 60Hz */ 1396 if((var->xres == 1024) && (var->yres == 600)) refresh_rate = 60; 1397 1398 search_idx = 0; 1399 while((XGIbios_mode[search_idx].mode_no != 0) && 1400 (XGIbios_mode[search_idx].xres <= var->xres) ) { 1401 if((XGIbios_mode[search_idx].xres == var->xres) && 1402 (XGIbios_mode[search_idx].yres == var->yres) && 1403 (XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) { 1404 if(XGIfb_validate_mode(search_idx) > 0) { 1405 found_mode = 1; 1406 break; 1407 } 1408 } 1409 search_idx++; 1410 } 1411 1412 if(!found_mode) { 1413 1414 printk(KERN_ERR "XGIfb: %dx%dx%d is no valid mode\n", 1415 var->xres, var->yres, var->bits_per_pixel); 1416 1417 search_idx = 0; 1418 while(XGIbios_mode[search_idx].mode_no != 0) { 1419 1420 if( (var->xres <= XGIbios_mode[search_idx].xres) && 1421 (var->yres <= XGIbios_mode[search_idx].yres) && 1422 (var->bits_per_pixel == XGIbios_mode[search_idx].bpp) ) { 1423 if(XGIfb_validate_mode(search_idx) > 0) { 1424 found_mode = 1; 1425 break; 1426 } 1427 } 1428 search_idx++; 1429 } 1430 if(found_mode) { 1431 var->xres = XGIbios_mode[search_idx].xres; 1432 var->yres = XGIbios_mode[search_idx].yres; 1433 printk(KERN_DEBUG "XGIfb: Adapted to mode %dx%dx%d\n", 1434 var->xres, var->yres, var->bits_per_pixel); 1435 1436 } else { 1437 printk(KERN_ERR "XGIfb: Failed to find similar mode to %dx%dx%d\n", 1438 var->xres, var->yres, var->bits_per_pixel); 1439 return -EINVAL; 1440 } 1441 } 1442 1443 /* TW: TODO: Check the refresh rate */ 1444 1445 /* Adapt RGB settings */ 1446 XGIfb_bpp_to_var(var); 1447 1448 /* Sanity check for offsets */ 1449 if (var->xoffset < 0) 1450 var->xoffset = 0; 1451 if (var->yoffset < 0) 1452 var->yoffset = 0; 1453 1454 1455 if(!XGIfb_ypan) { 1456 if(var->xres != var->xres_virtual) 1457 var->xres_virtual = var->xres; 1458 if(var->yres != var->yres_virtual) 1459 var->yres_virtual = var->yres; 1460 }/* else { 1461 // TW: Now patch yres_virtual if we use panning 1462 // May I do this? 1463 var->yres_virtual = xgi_video_info.heapstart / (var->xres * (var->bits_per_pixel >> 3)); 1464 if(var->yres_virtual <= var->yres) { 1465 // TW: Paranoia check 1466 var->yres_virtual = var->yres; 1467 } 1468 }*/ 1469 1470 /* Truncate offsets to maximum if too high */ 1471 if (var->xoffset > var->xres_virtual - var->xres) 1472 var->xoffset = var->xres_virtual - var->xres - 1; 1473 1474 if (var->yoffset > var->yres_virtual - var->yres) 1475 var->yoffset = var->yres_virtual - var->yres - 1; 1476 1477 /* Set everything else to 0 */ 1478 var->red.msb_right = 1479 var->green.msb_right = 1480 var->blue.msb_right = 1481 var->transp.offset = var->transp.length = var->transp.msb_right = 0; 1482 1483 DEBUGPRN("end of check_var"); 1484 return 0; 1485} 1486 1487#ifdef XGIFB_PAN 1488static int XGIfb_pan_display( struct fb_var_screeninfo *var, 1489 struct fb_info* info) 1490{ 1491 int err; 1492 1493// printk("\nInside pan_display:"); 1494 1495 if (var->xoffset > (var->xres_virtual - var->xres)) 1496 return -EINVAL; 1497 if (var->yoffset > (var->yres_virtual - var->yres)) 1498 return -EINVAL; 1499 1500 if (var->vmode & FB_VMODE_YWRAP) { 1501 if (var->yoffset < 0 1502 || var->yoffset >= info->var.yres_virtual 1503 || var->xoffset) return -EINVAL; 1504 } else { 1505 if (var->xoffset + info->var.xres > info->var.xres_virtual || 1506 var->yoffset + info->var.yres > info->var.yres_virtual) 1507 return -EINVAL; 1508 } 1509 1510 if((err = XGIfb_pan_var(var)) < 0) return err; 1511 1512 info->var.xoffset = var->xoffset; 1513 info->var.yoffset = var->yoffset; 1514 if (var->vmode & FB_VMODE_YWRAP) 1515 info->var.vmode |= FB_VMODE_YWRAP; 1516 else 1517 info->var.vmode &= ~FB_VMODE_YWRAP; 1518 1519// printk(" End of pan_display"); 1520 return 0; 1521} 1522#endif 1523 1524 1525static int XGIfb_blank(int blank, struct fb_info *info) 1526{ 1527 u8 reg; 1528 1529 inXGIIDXREG(XGICR, 0x17, reg); 1530 1531 if(blank > 0) 1532 reg &= 0x7f; 1533 else 1534 reg |= 0x80; 1535 1536 outXGIIDXREG(XGICR, 0x17, reg); 1537 outXGIIDXREG(XGISR, 0x00, 0x01); /* Synchronous Reset */ 1538 outXGIIDXREG(XGISR, 0x00, 0x03); /* End Reset */ 1539 return(0); 1540} 1541 1542 1543static int XGIfb_ioctl(struct fb_info *info, unsigned int cmd, 1544 unsigned long arg) 1545{ 1546 DEBUGPRN("inside ioctl"); 1547 switch (cmd) { 1548 case FBIO_ALLOC: 1549 if (!capable(CAP_SYS_RAWIO)) 1550 return -EPERM; 1551 XGI_malloc((struct XGI_memreq *) arg); 1552 break; 1553 case FBIO_FREE: 1554 if (!capable(CAP_SYS_RAWIO)) 1555 return -EPERM; 1556 XGI_free(*(unsigned long *) arg); 1557 break; 1558 case FBIOGET_HWCINFO: 1559 { 1560 unsigned long *hwc_offset = (unsigned long *) arg; 1561 1562 if (XGIfb_caps & HW_CURSOR_CAP) 1563 *hwc_offset = XGIfb_hwcursor_vbase - 1564 (unsigned long) xgi_video_info.video_vbase; 1565 else 1566 *hwc_offset = 0; 1567 1568 break; 1569 } 1570 case FBIOPUT_MODEINFO: 1571 { 1572 struct mode_info *x = (struct mode_info *)arg; 1573 1574 xgi_video_info.video_bpp = x->bpp; 1575 xgi_video_info.video_width = x->xres; 1576 xgi_video_info.video_height = x->yres; 1577 xgi_video_info.video_vwidth = x->v_xres; 1578 xgi_video_info.video_vheight = x->v_yres; 1579 xgi_video_info.org_x = x->org_x; 1580 xgi_video_info.org_y = x->org_y; 1581 xgi_video_info.refresh_rate = x->vrate; 1582 xgi_video_info.video_linelength = xgi_video_info.video_vwidth * (xgi_video_info.video_bpp >> 3); 1583 switch(xgi_video_info.video_bpp) { 1584 case 8: 1585 xgi_video_info.DstColor = 0x0000; 1586 xgi_video_info.XGI310_AccelDepth = 0x00000000; 1587 xgi_video_info.video_cmap_len = 256; 1588 break; 1589 case 16: 1590 xgi_video_info.DstColor = 0x8000; 1591 xgi_video_info.XGI310_AccelDepth = 0x00010000; 1592 xgi_video_info.video_cmap_len = 16; 1593 break; 1594 case 32: 1595 xgi_video_info.DstColor = 0xC000; 1596 xgi_video_info.XGI310_AccelDepth = 0x00020000; 1597 xgi_video_info.video_cmap_len = 16; 1598 break; 1599 default: 1600 xgi_video_info.video_cmap_len = 16; 1601 printk(KERN_ERR "XGIfb: Unsupported accel depth %d", xgi_video_info.video_bpp); 1602 xgi_video_info.accel = 0; 1603 break; 1604 } 1605 1606 break; 1607 } 1608 case FBIOGET_DISPINFO: 1609 XGI_dispinfo((struct ap_data *)arg); 1610 break; 1611 case XGIFB_GET_INFO: /* TW: New for communication with X driver */ 1612 { 1613 struct XGIfb_info *x = (struct XGIfb_info *)arg; 1614 1615 //x->XGIfb_id = XGIFB_ID; 1616 x->XGIfb_version = VER_MAJOR; 1617 x->XGIfb_revision = VER_MINOR; 1618 x->XGIfb_patchlevel = VER_LEVEL; 1619 x->chip_id = xgi_video_info.chip_id; 1620 x->memory = xgi_video_info.video_size / 1024; 1621 x->heapstart = xgi_video_info.heapstart / 1024; 1622 x->fbvidmode = XGIfb_mode_no; 1623 x->XGIfb_caps = XGIfb_caps; 1624 x->XGIfb_tqlen = 512; /* yet unused */ 1625 x->XGIfb_pcibus = xgi_video_info.pcibus; 1626 x->XGIfb_pcislot = xgi_video_info.pcislot; 1627 x->XGIfb_pcifunc = xgi_video_info.pcifunc; 1628 x->XGIfb_lcdpdc = XGIfb_detectedpdc; 1629 x->XGIfb_lcda = XGIfb_detectedlcda; 1630 break; 1631 } 1632 case XGIFB_GET_VBRSTATUS: 1633 { 1634 unsigned long *vbrstatus = (unsigned long *) arg; 1635 if(XGIfb_CheckVBRetrace()) *vbrstatus = 1; 1636 else *vbrstatus = 0; 1637 } 1638 default: 1639 return -EINVAL; 1640 } 1641 DEBUGPRN("end of ioctl"); 1642 return 0; 1643 1644} 1645 1646 1647 1648/* ----------- FBDev related routines for all series ---------- */ 1649 1650static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con, 1651 struct fb_info *info) 1652{ 1653 DEBUGPRN("inside get_fix"); 1654 memset(fix, 0, sizeof(struct fb_fix_screeninfo)); 1655 1656 strcpy(fix->id, myid); 1657 1658 fix->smem_start = xgi_video_info.video_base; 1659 1660 fix->smem_len = xgi_video_info.video_size; 1661 1662 1663/* if((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) { 1664 if (xgi_video_info.video_size > 0x1000000) { 1665 fix->smem_len = 0xD00000; 1666 } else if (xgi_video_info.video_size > 0x800000) 1667 fix->smem_len = 0x800000; 1668 else 1669 fix->smem_len = 0x400000; 1670 } else 1671 fix->smem_len = XGIfb_mem * 1024; 1672*/ 1673 fix->type = video_type; 1674 fix->type_aux = 0; 1675 if(xgi_video_info.video_bpp == 8) 1676 fix->visual = FB_VISUAL_PSEUDOCOLOR; 1677 else 1678 fix->visual = FB_VISUAL_DIRECTCOLOR; 1679 fix->xpanstep = 0; 1680#ifdef XGIFB_PAN 1681 if(XGIfb_ypan) fix->ypanstep = 1; 1682#endif 1683 fix->ywrapstep = 0; 1684 fix->line_length = xgi_video_info.video_linelength; 1685 fix->mmio_start = xgi_video_info.mmio_base; 1686 fix->mmio_len = XGIfb_mmio_size; 1687 if(xgi_video_info.chip >= XG40) 1688 fix->accel = FB_ACCEL_XGI_XABRE; 1689 else 1690 fix->accel = FB_ACCEL_XGI_GLAMOUR_2; 1691 1692 1693 DEBUGPRN("end of get_fix"); 1694 return 0; 1695} 1696 1697 1698static struct fb_ops XGIfb_ops = { 1699 .owner = THIS_MODULE, 1700 .fb_open = XGIfb_open, 1701 .fb_release = XGIfb_release, 1702 .fb_check_var = XGIfb_check_var, 1703 .fb_set_par = XGIfb_set_par, 1704 .fb_setcolreg = XGIfb_setcolreg, 1705#ifdef XGIFB_PAN 1706 .fb_pan_display = XGIfb_pan_display, 1707#endif 1708 .fb_blank = XGIfb_blank, 1709 .fb_fillrect = fbcon_XGI_fillrect, 1710 .fb_copyarea = fbcon_XGI_copyarea, 1711 .fb_imageblit = cfb_imageblit, 1712 .fb_sync = fbcon_XGI_sync, 1713 .fb_ioctl = XGIfb_ioctl, 1714// .fb_mmap = XGIfb_mmap, 1715}; 1716 1717/* ---------------- Chip generation dependent routines ---------------- */ 1718 1719 1720/* for XGI 315/550/650/740/330 */ 1721 1722static int XGIfb_get_dram_size(void) 1723{ 1724 1725 u8 ChannelNum,tmp; 1726 u8 reg = 0; 1727 1728 /* xorg driver sets 32MB * 1 channel */ 1729 if (xgi_video_info.chip == XG27) 1730 outXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, 0x51); 1731 1732 inXGIIDXREG(XGISR, IND_XGI_DRAM_SIZE, reg); 1733 switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) { 1734 case XGI_DRAM_SIZE_1MB: 1735 xgi_video_info.video_size = 0x100000; 1736 break; 1737 case XGI_DRAM_SIZE_2MB: 1738 xgi_video_info.video_size = 0x200000; 1739 break; 1740 case XGI_DRAM_SIZE_4MB: 1741 xgi_video_info.video_size = 0x400000; 1742 break; 1743 case XGI_DRAM_SIZE_8MB: 1744 xgi_video_info.video_size = 0x800000; 1745 break; 1746 case XGI_DRAM_SIZE_16MB: 1747 xgi_video_info.video_size = 0x1000000; 1748 break; 1749 case XGI_DRAM_SIZE_32MB: 1750 xgi_video_info.video_size = 0x2000000; 1751 break; 1752 case XGI_DRAM_SIZE_64MB: 1753 xgi_video_info.video_size = 0x4000000; 1754 break; 1755 case XGI_DRAM_SIZE_128MB: 1756 xgi_video_info.video_size = 0x8000000; 1757 break; 1758 case XGI_DRAM_SIZE_256MB: 1759 xgi_video_info.video_size = 0x10000000; 1760 break; 1761 default: 1762 return -1; 1763 } 1764 1765 tmp = (reg & 0x0c) >> 2; 1766 switch(xgi_video_info.chip) 1767 { 1768 case XG20: 1769 case XG21: 1770 case XG27: 1771 ChannelNum = 1; 1772 break; 1773 1774 case XG42: 1775 if(reg & 0x04) 1776 ChannelNum = 2; 1777 else 1778 ChannelNum = 1; 1779 break; 1780 1781 case XG45: 1782 if(tmp == 1) 1783 ChannelNum = 2; 1784 else 1785 if(tmp == 2) 1786 ChannelNum = 3; 1787 else 1788 if(tmp == 3) 1789 ChannelNum = 4; 1790 else 1791 ChannelNum = 1; 1792 break; 1793 1794 case XG40: 1795 default: 1796 if(tmp == 2) 1797 ChannelNum = 2; 1798 else 1799 if(tmp == 3) 1800 ChannelNum = 3; 1801 else 1802 ChannelNum = 1; 1803 break; 1804 } 1805 1806 1807 xgi_video_info.video_size = xgi_video_info.video_size * ChannelNum; 1808 //PLiad fixed for benchmarking and fb set 1809 //xgi_video_info.video_size = 0x200000;//1024x768x16 1810 //xgi_video_info.video_size = 0x1000000;//benchmark 1811 1812 printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n",reg,xgi_video_info.video_size ,ChannelNum ); 1813 return 0; 1814 1815} 1816 1817static void XGIfb_detect_VB(void) 1818{ 1819 u8 cr32, temp=0; 1820 1821 xgi_video_info.TV_plug = xgi_video_info.TV_type = 0; 1822 1823 switch(xgi_video_info.hasVB) { 1824 case HASVB_LVDS_CHRONTEL: 1825 case HASVB_CHRONTEL: 1826 break; 1827 case HASVB_301: 1828 case HASVB_302: 1829// XGI_Sense30x(); //Yi-Lin TV Sense? 1830 break; 1831 } 1832 1833 inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR32, cr32); 1834 1835 if ((cr32 & XGI_CRT1) && !XGIfb_crt1off) 1836 XGIfb_crt1off = 0; 1837 else { 1838 if (cr32 & 0x5F) 1839 XGIfb_crt1off = 1; 1840 else 1841 XGIfb_crt1off = 0; 1842 } 1843 1844 if (XGIfb_crt2type != -1) 1845 /* TW: Override with option */ 1846 xgi_video_info.disp_state = XGIfb_crt2type; 1847 else if (cr32 & XGI_VB_TV) 1848 xgi_video_info.disp_state = DISPTYPE_TV; 1849 else if (cr32 & XGI_VB_LCD) 1850 xgi_video_info.disp_state = DISPTYPE_LCD; 1851 else if (cr32 & XGI_VB_CRT2) 1852 xgi_video_info.disp_state = DISPTYPE_CRT2; 1853 else 1854 xgi_video_info.disp_state = 0; 1855 1856 if(XGIfb_tvplug != -1) 1857 /* PR/TW: Override with option */ 1858 xgi_video_info.TV_plug = XGIfb_tvplug; 1859 else if (cr32 & XGI_VB_HIVISION) { 1860 xgi_video_info.TV_type = TVMODE_HIVISION; 1861 xgi_video_info.TV_plug = TVPLUG_SVIDEO; 1862 } 1863 else if (cr32 & XGI_VB_SVIDEO) 1864 xgi_video_info.TV_plug = TVPLUG_SVIDEO; 1865 else if (cr32 & XGI_VB_COMPOSITE) 1866 xgi_video_info.TV_plug = TVPLUG_COMPOSITE; 1867 else if (cr32 & XGI_VB_SCART) 1868 xgi_video_info.TV_plug = TVPLUG_SCART; 1869 1870 if(xgi_video_info.TV_type == 0) { 1871 /* TW: PAL/NTSC changed for 650 */ 1872 if((xgi_video_info.chip <= XGI_315PRO) || (xgi_video_info.chip >= XGI_330)) { 1873 1874 inXGIIDXREG(XGICR, 0x38, temp); 1875 if(temp & 0x10) 1876 xgi_video_info.TV_type = TVMODE_PAL; 1877 else 1878 xgi_video_info.TV_type = TVMODE_NTSC; 1879 1880 } else { 1881 1882 inXGIIDXREG(XGICR, 0x79, temp); 1883 if(temp & 0x20) 1884 xgi_video_info.TV_type = TVMODE_PAL; 1885 else 1886 xgi_video_info.TV_type = TVMODE_NTSC; 1887 } 1888 } 1889 1890 /* TW: Copy forceCRT1 option to CRT1off if option is given */ 1891 if (XGIfb_forcecrt1 != -1) { 1892 if (XGIfb_forcecrt1) XGIfb_crt1off = 0; 1893 else XGIfb_crt1off = 1; 1894 } 1895} 1896 1897static void XGIfb_get_VB_type(void) 1898{ 1899 u8 reg; 1900 1901 if (!XGIfb_has_VB()) { 1902 inXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR37, reg); 1903 switch ((reg & XGI_EXTERNAL_CHIP_MASK) >> 1) { 1904 case XGI310_EXTERNAL_CHIP_LVDS: 1905 xgi_video_info.hasVB = HASVB_LVDS; 1906 break; 1907 case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL: 1908 xgi_video_info.hasVB = HASVB_LVDS_CHRONTEL; 1909 break; 1910 default: 1911 break; 1912 } 1913 } 1914} 1915 1916 1917static int XGIfb_has_VB(void) 1918{ 1919 u8 vb_chipid; 1920 1921 inXGIIDXREG(XGIPART4, 0x00, vb_chipid); 1922 switch (vb_chipid) { 1923 case 0x01: 1924 xgi_video_info.hasVB = HASVB_301; 1925 break; 1926 case 0x02: 1927 xgi_video_info.hasVB = HASVB_302; 1928 break; 1929 default: 1930 xgi_video_info.hasVB = HASVB_NONE; 1931 return 0; 1932 } 1933 return 1; 1934} 1935 1936 1937 1938/* ------------------ Sensing routines ------------------ */ 1939 1940/* TW: Determine and detect attached devices on XGI30x */ 1941int 1942XGIDoSense(int tempbl, int tempbh, int tempcl, int tempch) 1943{ 1944 int temp,i; 1945 1946 outXGIIDXREG(XGIPART4,0x11,tempbl); 1947 temp = tempbh | tempcl; 1948 setXGIIDXREG(XGIPART4,0x10,0xe0,temp); 1949 for(i=0; i<10; i++) XGI_LongWait(&XGI_Pr); 1950 tempch &= 0x7f; 1951 inXGIIDXREG(XGIPART4,0x03,temp); 1952 temp ^= 0x0e; 1953 temp &= tempch; 1954 return(temp); 1955} 1956 1957void 1958XGI_Sense30x(void) 1959{ 1960 u8 backupP4_0d; 1961 u8 testsvhs_tempbl, testsvhs_tempbh; 1962 u8 testsvhs_tempcl, testsvhs_tempch; 1963 u8 testcvbs_tempbl, testcvbs_tempbh; 1964 u8 testcvbs_tempcl, testcvbs_tempch; 1965 u8 testvga2_tempbl, testvga2_tempbh; 1966 u8 testvga2_tempcl, testvga2_tempch; 1967 int myflag, result; 1968 1969 inXGIIDXREG(XGIPART4,0x0d,backupP4_0d); 1970 outXGIIDXREG(XGIPART4,0x0d,(backupP4_0d | 0x04)); 1971 1972 1973 1974 testvga2_tempbh = 0x00; testvga2_tempbl = 0xd1; 1975 testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9; 1976 testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3; 1977 if((XGIhw_ext.ujVBChipID != VB_CHIP_301) && 1978 (XGIhw_ext.ujVBChipID != VB_CHIP_302)) { 1979 testvga2_tempbh = 0x01; testvga2_tempbl = 0x90; 1980 testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b; 1981 testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74; 1982 if(XGIhw_ext.ujVBChipID == VB_CHIP_301LV || 1983 XGIhw_ext.ujVBChipID == VB_CHIP_302LV) { 1984 testvga2_tempbh = 0x00; testvga2_tempbl = 0x00; 1985 testsvhs_tempbh = 0x02; testsvhs_tempbl = 0x00; 1986 testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x00; 1987 } 1988 } 1989 if(XGIhw_ext.ujVBChipID != VB_CHIP_301LV && 1990 XGIhw_ext.ujVBChipID != VB_CHIP_302LV) { 1991 inXGIIDXREG(XGIPART4,0x01,myflag); 1992 if(myflag & 0x04) { 1993 testvga2_tempbh = 0x00; testvga2_tempbl = 0xfd; 1994 testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xdd; 1995 testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xee; 1996 } 1997 } 1998 if((XGIhw_ext.ujVBChipID == VB_CHIP_301LV) || 1999 (XGIhw_ext.ujVBChipID == VB_CHIP_302LV) ) { 2000 testvga2_tempbh = 0x00; testvga2_tempbl = 0x00; 2001 testvga2_tempch = 0x00; testvga2_tempcl = 0x00; 2002 testsvhs_tempch = 0x04; testsvhs_tempcl = 0x08; 2003 testcvbs_tempch = 0x08; testcvbs_tempcl = 0x08; 2004 } else { 2005 testvga2_tempch = 0x0e; testvga2_tempcl = 0x08; 2006 testsvhs_tempch = 0x06; testsvhs_tempcl = 0x04; 2007 testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04; 2008 } 2009 2010 2011 if(testvga2_tempch || testvga2_tempcl || testvga2_tempbh || testvga2_tempbl) { 2012 result = XGIDoSense(testvga2_tempbl, testvga2_tempbh, 2013 testvga2_tempcl, testvga2_tempch); 2014 if(result) { 2015 printk(KERN_INFO "XGIfb: Detected secondary VGA connection\n"); 2016 orXGIIDXREG(XGICR, 0x32, 0x10); 2017 } 2018 } 2019 2020 result = XGIDoSense(testsvhs_tempbl, testsvhs_tempbh, 2021 testsvhs_tempcl, testsvhs_tempch); 2022 if(result) { 2023 printk(KERN_INFO "XGIfb: Detected TV connected to SVHS output\n"); 2024 /* TW: So we can be sure that there IS a SVHS output */ 2025 xgi_video_info.TV_plug = TVPLUG_SVIDEO; 2026 orXGIIDXREG(XGICR, 0x32, 0x02); 2027 } 2028 2029 if(!result) { 2030 result = XGIDoSense(testcvbs_tempbl, testcvbs_tempbh, 2031 testcvbs_tempcl, testcvbs_tempch); 2032 if(result) { 2033 printk(KERN_INFO "XGIfb: Detected TV connected to CVBS output\n"); 2034 /* TW: So we can be sure that there IS a CVBS output */ 2035 xgi_video_info.TV_plug = TVPLUG_COMPOSITE; 2036 orXGIIDXREG(XGICR, 0x32, 0x01); 2037 } 2038 } 2039 XGIDoSense(0, 0, 0, 0); 2040 2041 outXGIIDXREG(XGIPART4,0x0d,backupP4_0d); 2042} 2043 2044 2045 2046/* ------------------------ Heap routines -------------------------- */ 2047 2048static int XGIfb_heap_init(void) 2049{ 2050 XGI_OH *poh; 2051 u8 temp=0; 2052 2053 int agp_enabled = 1; 2054 u32 agp_size; 2055 unsigned long *cmdq_baseport = 0; 2056 unsigned long *read_port = 0; 2057 unsigned long *write_port = 0; 2058 XGI_CMDTYPE cmd_type; 2059#ifndef AGPOFF 2060 struct agp_kern_info *agp_info; 2061 struct agp_memory *agp; 2062 u32 agp_phys; 2063#endif 2064 2065/* TW: The heap start is either set manually using the "mem" parameter, or 2066 * defaults as follows: 2067 * -) If more than 16MB videoRAM available, let our heap start at 12MB. 2068 * -) If more than 8MB videoRAM available, let our heap start at 8MB. 2069 * -) If 4MB or less is available, let it start at 4MB. 2070 * This is for avoiding a clash with X driver which uses the beginning 2071 * of the videoRAM. To limit size of X framebuffer, use Option MaxXFBMem 2072 * in XF86Config-4. 2073 * The heap start can also be specified by parameter "mem" when starting the XGIfb 2074 * driver. XGIfb mem=1024 lets heap starts at 1MB, etc. 2075 */ 2076 if ((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) { 2077 if (xgi_video_info.video_size > 0x1000000) { 2078 xgi_video_info.heapstart = 0xD00000; 2079 } else if (xgi_video_info.video_size > 0x800000) { 2080 xgi_video_info.heapstart = 0x800000; 2081 } else { 2082 xgi_video_info.heapstart = 0x400000; 2083 } 2084 } else { 2085 xgi_video_info.heapstart = XGIfb_mem * 1024; 2086 } 2087 XGIfb_heap_start = 2088 (unsigned long) (xgi_video_info.video_vbase + xgi_video_info.heapstart); 2089 printk(KERN_INFO "XGIfb: Memory heap starting at %dK\n", 2090 (int)(xgi_video_info.heapstart / 1024)); 2091 2092 XGIfb_heap_end = (unsigned long) xgi_video_info.video_vbase + xgi_video_info.video_size; 2093 XGIfb_heap_size = XGIfb_heap_end - XGIfb_heap_start; 2094 2095 2096 2097 /* TW: Now initialize the 310 series' command queue mode. 2098 * On 310/325, there are three queue modes available which 2099 * are chosen by setting bits 7:5 in SR26: 2100 * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep 2101 * track of the queue, the FIFO, command parsing and so 2102 * on. This is the one comparable to the 300 series. 2103 * 2. VRAM queue mode (bit 6, 0x40). In this case, one will 2104 * have to do queue management himself. Register 0x85c4 will 2105 * hold the location of the next free queue slot, 0x85c8 2106 * is the "queue read pointer" whose way of working is 2107 * unknown to me. Anyway, this mode would require a 2108 * translation of the MMIO commands to some kind of 2109 * accelerator assembly and writing these commands 2110 * to the memory location pointed to by 0x85c4. 2111 * We will not use this, as nobody knows how this 2112 * "assembly" works, and as it would require a complete 2113 * re-write of the accelerator code. 2114 * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the 2115 * queue in AGP memory space. 2116 * 2117 * SR26 bit 4 is called "Bypass H/W queue". 2118 * SR26 bit 1 is called "Enable Command Queue Auto Correction" 2119 * SR26 bit 0 resets the queue 2120 * Size of queue memory is encoded in bits 3:2 like this: 2121 * 00 (0x00) 512K 2122 * 01 (0x04) 1M 2123 * 10 (0x08) 2M 2124 * 11 (0x0C) 4M 2125 * The queue location is to be written to 0x85C0. 2126 * 2127 */ 2128 cmdq_baseport = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_PHYBASE); 2129 write_port = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_WRITEPORT); 2130 read_port = (unsigned long *)(xgi_video_info.mmio_vbase + MMIO_QUEUE_READPORT); 2131 2132 DPRINTK("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport, read_port, write_port); 2133 2134 agp_size = COMMAND_QUEUE_AREA_SIZE; 2135 2136#ifndef AGPOFF 2137 if (XGIfb_queuemode == AGP_CMD_QUEUE) { 2138 agp_info = vmalloc(sizeof(*agp_info)); 2139 memset((void*)agp_info, 0x00, sizeof(*agp_info)); 2140 agp_copy_info(agp_info); 2141 2142 agp_backend_acquire(); 2143 2144 agp = agp_allocate_memory(COMMAND_QUEUE_AREA_SIZE/PAGE_SIZE, 2145 AGP_NORMAL_MEMORY); 2146 if (agp == NULL) { 2147 DPRINTK("XGIfb: Allocating AGP buffer failed.\n"); 2148 agp_enabled = 0; 2149 } else { 2150 if (agp_bind_memory(agp, agp->pg_start) != 0) { 2151 DPRINTK("XGIfb: AGP: Failed to bind memory\n"); 2152 /* TODO: Free AGP memory here */ 2153 agp_enabled = 0; 2154 } else { 2155 agp_enable(0); 2156 } 2157 } 2158 } 2159#else 2160 agp_enabled = 0; 2161#endif 2162 2163 /* TW: Now select the queue mode */ 2164 2165 if ((agp_enabled) && (XGIfb_queuemode == AGP_CMD_QUEUE)) { 2166 cmd_type = AGP_CMD_QUEUE; 2167 printk(KERN_INFO "XGIfb: Using AGP queue mode\n"); 2168/* } else if (XGIfb_heap_size >= COMMAND_QUEUE_AREA_SIZE) */ 2169 } else if (XGIfb_queuemode == VM_CMD_QUEUE) { 2170 cmd_type = VM_CMD_QUEUE; 2171 printk(KERN_INFO "XGIfb: Using VRAM queue mode\n"); 2172 } else { 2173 printk(KERN_INFO "XGIfb: Using MMIO queue mode\n"); 2174 cmd_type = MMIO_CMD; 2175 } 2176 2177 switch (agp_size) { 2178 case 0x80000: 2179 temp = XGI_CMD_QUEUE_SIZE_512k; 2180 break; 2181 case 0x100000: 2182 temp = XGI_CMD_QUEUE_SIZE_1M; 2183 break; 2184 case 0x200000: 2185 temp = XGI_CMD_QUEUE_SIZE_2M; 2186 break; 2187 case 0x400000: 2188 temp = XGI_CMD_QUEUE_SIZE_4M; 2189 break; 2190 } 2191 2192 switch (cmd_type) { 2193 case AGP_CMD_QUEUE: 2194#ifndef AGPOFF 2195 DPRINTK("XGIfb: AGP buffer base = 0x%lx, offset = 0x%x, size = %dK\n", 2196 agp_info->aper_base, agp->physical, agp_size/1024); 2197 2198 agp_phys = agp_info->aper_base + agp->physical; 2199 2200 outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, 0); 2201 outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, XGI_AGP_2X); 2202 2203 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD); 2204 2205 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET); 2206 2207 *write_port = *read_port; 2208 2209 temp |= XGI_AGP_CMDQUEUE_ENABLE; 2210 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp); 2211 2212 *cmdq_baseport = agp_phys; 2213 2214 XGIfb_caps |= AGP_CMD_QUEUE_CAP; 2215#endif 2216 break; 2217 2218 case VM_CMD_QUEUE: 2219 XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE; 2220 XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE; 2221 2222 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD); 2223 2224 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET); 2225 2226 *write_port = *read_port; 2227 2228 temp |= XGI_VRAM_CMDQUEUE_ENABLE; 2229 outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp); 2230 2231 *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE; 2232 2233 XGIfb_caps |= VM_CMD_QUEUE_CAP; 2234 2235 DPRINTK("XGIfb: VM Cmd Queue offset = 0x%lx, size is %dK\n", 2236 *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024); 2237 break; 2238 2239 default: /* MMIO */ 2240 2241// printk("%s:%d - I'm here\n", __FUNCTION__, __LINE__); 2242 /* TW: This previously only wrote XGI_MMIO_CMD_ENABLE 2243 * to IND_XGI_CMDQUEUE_SET. I doubt that this is 2244 * enough. Reserve memory in any way. 2245 */ 2246 break; 2247 } 2248 2249 2250 2251 2252 /* TW: Now reserve memory for the HWCursor. It is always located at the very 2253 top of the videoRAM, right below the TB memory area (if used). */ 2254 if (XGIfb_heap_size >= XGIfb_hwcursor_size) { 2255 XGIfb_heap_end -= XGIfb_hwcursor_size; 2256 XGIfb_heap_size -= XGIfb_hwcursor_size; 2257 XGIfb_hwcursor_vbase = XGIfb_heap_end; 2258 2259 XGIfb_caps |= HW_CURSOR_CAP; 2260 2261 DPRINTK("XGIfb: Hardware Cursor start at 0x%lx, size is %dK\n", 2262 XGIfb_heap_end, XGIfb_hwcursor_size/1024); 2263 } 2264 2265 XGIfb_heap.poha_chain = NULL; 2266 XGIfb_heap.poh_freelist = NULL; 2267 2268 poh = XGIfb_poh_new_node(); 2269 2270 if(poh == NULL) return 1; 2271 2272 poh->poh_next = &XGIfb_heap.oh_free; 2273 poh->poh_prev = &XGIfb_heap.oh_free; 2274 poh->size = XGIfb_heap_end - XGIfb_heap_start + 1; 2275 poh->offset = XGIfb_heap_start - (unsigned long) xgi_video_info.video_vbase; 2276 2277 DPRINTK("XGIfb: Heap start:0x%p, end:0x%p, len=%dk\n", 2278 (char *) XGIfb_heap_start, (char *) XGIfb_heap_end, 2279 (unsigned int) poh->size / 1024); 2280 2281 DPRINTK("XGIfb: First Node offset:0x%x, size:%dk\n", 2282 (unsigned int) poh->offset, (unsigned int) poh->size / 1024); 2283 2284 XGIfb_heap.oh_free.poh_next = poh; 2285 XGIfb_heap.oh_free.poh_prev = poh; 2286 XGIfb_heap.oh_free.size = 0; 2287 XGIfb_heap.max_freesize = poh->size; 2288 2289 XGIfb_heap.oh_used.poh_next = &XGIfb_heap.oh_used; 2290 XGIfb_heap.oh_used.poh_prev = &XGIfb_heap.oh_used; 2291 XGIfb_heap.oh_used.size = SENTINEL; 2292 2293 return 0; 2294} 2295 2296static XGI_OH *XGIfb_poh_new_node(void) 2297{ 2298 int i; 2299 unsigned long cOhs; 2300 XGI_OHALLOC *poha; 2301 XGI_OH *poh; 2302 2303 if (XGIfb_heap.poh_freelist == NULL) { 2304 poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL); 2305 if(!poha) return NULL; 2306 2307 poha->poha_next = XGIfb_heap.poha_chain; 2308 XGIfb_heap.poha_chain = poha; 2309 2310 cOhs = (OH_ALLOC_SIZE - sizeof(XGI_OHALLOC)) / sizeof(XGI_OH) + 1; 2311 2312 poh = &poha->aoh[0]; 2313 for (i = cOhs - 1; i != 0; i--) { 2314 poh->poh_next = poh + 1; 2315 poh = poh + 1; 2316 } 2317 2318 poh->poh_next = NULL; 2319 XGIfb_heap.poh_freelist = &poha->aoh[0]; 2320 } 2321 2322 poh = XGIfb_heap.poh_freelist; 2323 XGIfb_heap.poh_freelist = poh->poh_next; 2324 2325 return (poh); 2326} 2327 2328static XGI_OH *XGIfb_poh_allocate(unsigned long size) 2329{ 2330 XGI_OH *pohThis; 2331 XGI_OH *pohRoot; 2332 int bAllocated = 0; 2333 2334 if (size > XGIfb_heap.max_freesize) { 2335 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n", 2336 (unsigned int) size / 1024); 2337 return (NULL); 2338 } 2339 2340 pohThis = XGIfb_heap.oh_free.poh_next; 2341 2342 while (pohThis != &XGIfb_heap.oh_free) { 2343 if (size <= pohThis->size) { 2344 bAllocated = 1; 2345 break; 2346 } 2347 pohThis = pohThis->poh_next; 2348 } 2349 2350 if (!bAllocated) { 2351 DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n", 2352 (unsigned int) size / 1024); 2353 return (NULL); 2354 } 2355 2356 if (size == pohThis->size) { 2357 pohRoot = pohThis; 2358 XGIfb_delete_node(pohThis); 2359 } else { 2360 pohRoot = XGIfb_poh_new_node(); 2361 2362 if (pohRoot == NULL) { 2363 return (NULL); 2364 } 2365 2366 pohRoot->offset = pohThis->offset; 2367 pohRoot->size = size; 2368 2369 pohThis->offset += size; 2370 pohThis->size -= size; 2371 } 2372 2373 XGIfb_heap.max_freesize -= size; 2374 2375 pohThis = &XGIfb_heap.oh_used; 2376 XGIfb_insert_node(pohThis, pohRoot); 2377 2378 return (pohRoot); 2379} 2380 2381static void XGIfb_delete_node(XGI_OH *poh) 2382{ 2383 XGI_OH *poh_prev; 2384 XGI_OH *poh_next; 2385 2386 poh_prev = poh->poh_prev; 2387 poh_next = poh->poh_next; 2388 2389 poh_prev->poh_next = poh_next; 2390 poh_next->poh_prev = poh_prev; 2391 2392} 2393 2394static void XGIfb_insert_node(XGI_OH *pohList, XGI_OH *poh) 2395{ 2396 XGI_OH *pohTemp; 2397 2398 pohTemp = pohList->poh_next; 2399 2400 pohList->poh_next = poh; 2401 pohTemp->poh_prev = poh; 2402 2403 poh->poh_prev = pohList; 2404 poh->poh_next = pohTemp; 2405} 2406 2407static XGI_OH *XGIfb_poh_free(unsigned long base) 2408{ 2409 XGI_OH *pohThis; 2410 XGI_OH *poh_freed; 2411 XGI_OH *poh_prev; 2412 XGI_OH *poh_next; 2413 unsigned long ulUpper; 2414 unsigned long ulLower; 2415 int foundNode = 0; 2416 2417 poh_freed = XGIfb_heap.oh_used.poh_next; 2418 2419 while(poh_freed != &XGIfb_heap.oh_used) { 2420 if(poh_freed->offset == base) { 2421 foundNode = 1; 2422 break; 2423 } 2424 2425 poh_freed = poh_freed->poh_next; 2426 } 2427 2428 if (!foundNode) return (NULL); 2429 2430 XGIfb_heap.max_freesize += poh_freed->size; 2431 2432 poh_prev = poh_next = NULL; 2433 ulUpper = poh_freed->offset + poh_freed->size; 2434 ulLower = poh_freed->offset; 2435 2436 pohThis = XGIfb_heap.oh_free.poh_next; 2437 2438 while (pohThis != &XGIfb_heap.oh_free) { 2439 if (pohThis->offset == ulUpper) { 2440 poh_next = pohThis; 2441 } 2442 else if ((pohThis->offset + pohThis->size) == 2443 ulLower) { 2444 poh_prev = pohThis; 2445 } 2446 pohThis = pohThis->poh_next; 2447 } 2448 2449 XGIfb_delete_node(poh_freed); 2450 2451 if (poh_prev && poh_next) { 2452 poh_prev->size += (poh_freed->size + poh_next->size); 2453 XGIfb_delete_node(poh_next); 2454 XGIfb_free_node(poh_freed); 2455 XGIfb_free_node(poh_next); 2456 return (poh_prev); 2457 } 2458 2459 if (poh_prev) { 2460 poh_prev->size += poh_freed->size; 2461 XGIfb_free_node(poh_freed); 2462 return (poh_prev); 2463 } 2464 2465 if (poh_next) { 2466 poh_next->size += poh_freed->size; 2467 poh_next->offset = poh_freed->offset; 2468 XGIfb_free_node(poh_freed); 2469 return (poh_next); 2470 } 2471 2472 XGIfb_insert_node(&XGIfb_heap.oh_free, poh_freed); 2473 2474 return (poh_freed); 2475} 2476 2477static void XGIfb_free_node(XGI_OH *poh) 2478{ 2479 if(poh == NULL) return; 2480 2481 poh->poh_next = XGIfb_heap.poh_freelist; 2482 XGIfb_heap.poh_freelist = poh; 2483 2484} 2485 2486void XGI_malloc(struct XGI_memreq *req) 2487{ 2488 XGI_OH *poh; 2489 2490 poh = XGIfb_poh_allocate(req->size); 2491 2492 if(poh == NULL) { 2493 req->offset = 0; 2494 req->size = 0; 2495 DPRINTK("XGIfb: Video RAM allocation failed\n"); 2496 } else { 2497 DPRINTK("XGIfb: Video RAM allocation succeeded: 0x%p\n", 2498 (char *) (poh->offset + (unsigned long) xgi_video_info.video_vbase)); 2499 2500 req->offset = poh->offset; 2501 req->size = poh->size; 2502 } 2503 2504} 2505 2506void XGI_free(unsigned long base) 2507{ 2508 XGI_OH *poh; 2509 2510 poh = XGIfb_poh_free(base); 2511 2512 if(poh == NULL) { 2513 DPRINTK("XGIfb: XGIfb_poh_free() failed at base 0x%x\n", 2514 (unsigned int) base); 2515 } 2516} 2517 2518/* --------------------- SetMode routines ------------------------- */ 2519 2520static void XGIfb_pre_setmode(void) 2521{ 2522 u8 cr30 = 0, cr31 = 0; 2523 2524 inXGIIDXREG(XGICR, 0x31, cr31); 2525 cr31 &= ~0x60; 2526 2527 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) { 2528 case DISPTYPE_CRT2: 2529 cr30 = (XGI_VB_OUTPUT_CRT2 | XGI_SIMULTANEOUS_VIEW_ENABLE); 2530 cr31 |= XGI_DRIVER_MODE; 2531 break; 2532 case DISPTYPE_LCD: 2533 cr30 = (XGI_VB_OUTPUT_LCD | XGI_SIMULTANEOUS_VIEW_ENABLE); 2534 cr31 |= XGI_DRIVER_MODE; 2535 break; 2536 case DISPTYPE_TV: 2537 if (xgi_video_info.TV_type == TVMODE_HIVISION) 2538 cr30 = (XGI_VB_OUTPUT_HIVISION | XGI_SIMULTANEOUS_VIEW_ENABLE); 2539 else if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) 2540 cr30 = (XGI_VB_OUTPUT_SVIDEO | XGI_SIMULTANEOUS_VIEW_ENABLE); 2541 else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE) 2542 cr30 = (XGI_VB_OUTPUT_COMPOSITE | XGI_SIMULTANEOUS_VIEW_ENABLE); 2543 else if (xgi_video_info.TV_plug == TVPLUG_SCART) 2544 cr30 = (XGI_VB_OUTPUT_SCART | XGI_SIMULTANEOUS_VIEW_ENABLE); 2545 cr31 |= XGI_DRIVER_MODE; 2546 2547 if (XGIfb_tvmode == 1 || xgi_video_info.TV_type == TVMODE_PAL) 2548 cr31 |= 0x01; 2549 else 2550 cr31 &= ~0x01; 2551 break; 2552 default: /* disable CRT2 */ 2553 cr30 = 0x00; 2554 cr31 |= (XGI_DRIVER_MODE | XGI_VB_OUTPUT_DISABLE); 2555 } 2556 2557 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30); 2558 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31); 2559 outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR33, (XGIfb_rate_idx & 0x0F)); 2560 2561 if(xgi_video_info.accel) XGIfb_syncaccel(); 2562 2563 2564} 2565 2566static void XGIfb_post_setmode(void) 2567{ 2568 u8 reg; 2569 unsigned char doit = 1; 2570/* outXGIIDXREG(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD); 2571 outXGIIDXREG(XGICR,0x13,0x00); 2572 setXGIIDXREG(XGISR,0x0E,0xF0,0x01); 2573*test**/ 2574 if (xgi_video_info.video_bpp == 8) { 2575 /* TW: We can't switch off CRT1 on LVDS/Chrontel in 8bpp Modes */ 2576 if ((xgi_video_info.hasVB == HASVB_LVDS) || (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL)) { 2577 doit = 0; 2578 } 2579 /* TW: We can't switch off CRT1 on 301B-DH in 8bpp Modes if using LCD */ 2580 if (xgi_video_info.disp_state & DISPTYPE_LCD) { 2581 doit = 0; 2582 } 2583 } 2584 2585 /* TW: We can't switch off CRT1 if bridge is in slave mode */ 2586 if(xgi_video_info.hasVB != HASVB_NONE) { 2587 inXGIIDXREG(XGIPART1, 0x00, reg); 2588 2589 2590 if ((reg & 0x50) == 0x10) 2591 doit = 0; 2592 2593 2594 } else 2595 XGIfb_crt1off = 0; 2596 2597 inXGIIDXREG(XGICR, 0x17, reg); 2598 if ((XGIfb_crt1off) && (doit)) 2599 reg &= ~0x80; 2600 else 2601 reg |= 0x80; 2602 outXGIIDXREG(XGICR, 0x17, reg); 2603 2604 andXGIIDXREG(XGISR, IND_XGI_RAMDAC_CONTROL, ~0x04); 2605 2606 if((xgi_video_info.disp_state & DISPTYPE_TV) && (xgi_video_info.hasVB == HASVB_301)) { 2607 2608 inXGIIDXREG(XGIPART4, 0x01, reg); 2609 2610 if(reg < 0xB0) { /* Set filter for XGI301 */ 2611 2612 switch (xgi_video_info.video_width) { 2613 case 320: 2614 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 4 : 12; 2615 break; 2616 case 640: 2617 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 5 : 13; 2618 break; 2619 case 720: 2620 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 6 : 14; 2621 break; 2622 case 800: 2623 filter_tb = (xgi_video_info.TV_type == TVMODE_NTSC) ? 7 : 15; 2624 break; 2625 default: 2626 filter = -1; 2627 break; 2628 } 2629 2630 orXGIIDXREG(XGIPART1, XGIfb_CRT2_write_enable, 0x01); 2631 2632 if(xgi_video_info.TV_type == TVMODE_NTSC) { 2633 2634 andXGIIDXREG(XGIPART2, 0x3a, 0x1f); 2635 2636 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) { 2637 2638 andXGIIDXREG(XGIPART2, 0x30, 0xdf); 2639 2640 } else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE) { 2641 2642 orXGIIDXREG(XGIPART2, 0x30, 0x20); 2643 2644 switch (xgi_video_info.video_width) { 2645 case 640: 2646 outXGIIDXREG(XGIPART2, 0x35, 0xEB); 2647 outXGIIDXREG(XGIPART2, 0x36, 0x04); 2648 outXGIIDXREG(XGIPART2, 0x37, 0x25); 2649 outXGIIDXREG(XGIPART2, 0x38, 0x18); 2650 break; 2651 case 720: 2652 outXGIIDXREG(XGIPART2, 0x35, 0xEE); 2653 outXGIIDXREG(XGIPART2, 0x36, 0x0C); 2654 outXGIIDXREG(XGIPART2, 0x37, 0x22); 2655 outXGIIDXREG(XGIPART2, 0x38, 0x08); 2656 break; 2657 case 800: 2658 outXGIIDXREG(XGIPART2, 0x35, 0xEB); 2659 outXGIIDXREG(XGIPART2, 0x36, 0x15); 2660 outXGIIDXREG(XGIPART2, 0x37, 0x25); 2661 outXGIIDXREG(XGIPART2, 0x38, 0xF6); 2662 break; 2663 } 2664 } 2665 2666 } else if(xgi_video_info.TV_type == TVMODE_PAL) { 2667 2668 andXGIIDXREG(XGIPART2, 0x3A, 0x1F); 2669 2670 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) { 2671 2672 andXGIIDXREG(XGIPART2, 0x30, 0xDF); 2673 2674 } else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE) { 2675 2676 orXGIIDXREG(XGIPART2, 0x30, 0x20); 2677 2678 switch (xgi_video_info.video_width) { 2679 case 640: 2680 outXGIIDXREG(XGIPART2, 0x35, 0xF1); 2681 outXGIIDXREG(XGIPART2, 0x36, 0xF7); 2682 outXGIIDXREG(XGIPART2, 0x37, 0x1F); 2683 outXGIIDXREG(XGIPART2, 0x38, 0x32); 2684 break; 2685 case 720: 2686 outXGIIDXREG(XGIPART2, 0x35, 0xF3); 2687 outXGIIDXREG(XGIPART2, 0x36, 0x00); 2688 outXGIIDXREG(XGIPART2, 0x37, 0x1D); 2689 outXGIIDXREG(XGIPART2, 0x38, 0x20); 2690 break; 2691 case 800: 2692 outXGIIDXREG(XGIPART2, 0x35, 0xFC); 2693 outXGIIDXREG(XGIPART2, 0x36, 0xFB); 2694 outXGIIDXREG(XGIPART2, 0x37, 0x14); 2695 outXGIIDXREG(XGIPART2, 0x38, 0x2A); 2696 break; 2697 } 2698 } 2699 } 2700 2701 if ((filter >= 0) && (filter <=7)) { 2702 DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n", filter_tb, filter, 2703 XGI_TV_filter[filter_tb].filter[filter][0], 2704 XGI_TV_filter[filter_tb].filter[filter][1], 2705 XGI_TV_filter[filter_tb].filter[filter][2], 2706 XGI_TV_filter[filter_tb].filter[filter][3] 2707 ); 2708 outXGIIDXREG(XGIPART2, 0x35, (XGI_TV_filter[filter_tb].filter[filter][0])); 2709 outXGIIDXREG(XGIPART2, 0x36, (XGI_TV_filter[filter_tb].filter[filter][1])); 2710 outXGIIDXREG(XGIPART2, 0x37, (XGI_TV_filter[filter_tb].filter[filter][2])); 2711 outXGIIDXREG(XGIPART2, 0x38, (XGI_TV_filter[filter_tb].filter[filter][3])); 2712 } 2713 2714 } 2715 2716 } 2717 2718} 2719 2720#ifndef MODULE 2721XGIINITSTATIC int __init XGIfb_setup(char *options) 2722{ 2723 char *this_opt; 2724 2725 2726 2727 xgi_video_info.refresh_rate = 0; 2728 2729 printk(KERN_INFO "XGIfb: Options %s\n", options); 2730 2731 if (!options || !*options) 2732 return 0; 2733 2734 while((this_opt = strsep(&options, ",")) != NULL) { 2735 2736 if (!*this_opt) continue; 2737 2738 if (!strncmp(this_opt, "mode:", 5)) { 2739 XGIfb_search_mode(this_opt + 5); 2740 } else if (!strncmp(this_opt, "vesa:", 5)) { 2741 XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0)); 2742 } else if (!strncmp(this_opt, "mode:", 5)) { 2743 XGIfb_search_mode(this_opt + 5); 2744 } else if (!strncmp(this_opt, "vesa:", 5)) { 2745 XGIfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0)); 2746 } else if (!strncmp(this_opt, "vrate:", 6)) { 2747 xgi_video_info.refresh_rate = simple_strtoul(this_opt + 6, NULL, 0); 2748 } else if (!strncmp(this_opt, "rate:", 5)) { 2749 xgi_video_info.refresh_rate = simple_strtoul(this_opt + 5, NULL, 0); 2750 } else if (!strncmp(this_opt, "off", 3)) { 2751 XGIfb_off = 1; 2752 } else if (!strncmp(this_opt, "crt1off", 7)) { 2753 XGIfb_crt1off = 1; 2754 } else if (!strncmp(this_opt, "filter:", 7)) { 2755 filter = (int)simple_strtoul(this_opt + 7, NULL, 0); 2756 } else if (!strncmp(this_opt, "forcecrt2type:", 14)) { 2757 XGIfb_search_crt2type(this_opt + 14); 2758 } else if (!strncmp(this_opt, "forcecrt1:", 10)) { 2759 XGIfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0); 2760 } else if (!strncmp(this_opt, "tvmode:",7)) { 2761 XGIfb_search_tvstd(this_opt + 7); 2762 } else if (!strncmp(this_opt, "tvstandard:",11)) { 2763 XGIfb_search_tvstd(this_opt + 7); 2764 } else if (!strncmp(this_opt, "mem:",4)) { 2765 XGIfb_mem = simple_strtoul(this_opt + 4, NULL, 0); 2766 } else if (!strncmp(this_opt, "dstn", 4)) { 2767 enable_dstn = 1; 2768 /* TW: DSTN overrules forcecrt2type */ 2769 XGIfb_crt2type = DISPTYPE_LCD; 2770 } else if (!strncmp(this_opt, "queuemode:", 10)) { 2771 XGIfb_search_queuemode(this_opt + 10); 2772 } else if (!strncmp(this_opt, "pdc:", 4)) { 2773 XGIfb_pdc = simple_strtoul(this_opt + 4, NULL, 0); 2774 if(XGIfb_pdc & ~0x3c) { 2775 printk(KERN_INFO "XGIfb: Illegal pdc parameter\n"); 2776 XGIfb_pdc = 0; 2777 } 2778 } else if (!strncmp(this_opt, "noaccel", 7)) { 2779 XGIfb_accel = 0; 2780 } else if (!strncmp(this_opt, "noypan", 6)) { 2781 XGIfb_ypan = 0; 2782 } else if (!strncmp(this_opt, "userom:", 7)) { 2783 XGIfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0); 2784// } else if (!strncmp(this_opt, "useoem:", 7)) { 2785// XGIfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0); 2786 } else { 2787 XGIfb_search_mode(this_opt); 2788// printk(KERN_INFO "XGIfb: Invalid option %s\n", this_opt); 2789 } 2790 2791 /* TW: Acceleration only with MMIO mode */ 2792 if((XGIfb_queuemode != -1) && (XGIfb_queuemode != MMIO_CMD)) { 2793 XGIfb_ypan = 0; 2794 XGIfb_accel = 0; 2795 } 2796 /* TW: Panning only with acceleration */ 2797 if(XGIfb_accel == 0) XGIfb_ypan = 0; 2798 2799 } 2800 printk("\nxgifb: outa xgifb_setup 3450"); 2801 return 0; 2802} 2803#endif 2804 2805static unsigned char VBIOS_BUF[65535]; 2806 2807unsigned char *attempt_map_rom(struct pci_dev *dev, void *copy_address) 2808{ 2809 u32 rom_size = 0; 2810 u32 rom_address = 0; 2811 int j; 2812 2813 /* Get the size of the expansion rom */ 2814 pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0xFFFFFFFF); 2815 pci_read_config_dword(dev, PCI_ROM_ADDRESS, &rom_size); 2816 if ((rom_size & 0x01) == 0) 2817 { 2818 printk("No ROM\n"); 2819 return NULL; 2820 } 2821 2822 rom_size &= 0xFFFFF800; 2823 rom_size = (~rom_size)+1; 2824 2825 rom_address = pci_resource_start(dev, 0); 2826 if (rom_address == 0 || rom_address == 0xFFFFFFF0) 2827 { 2828 printk("No suitable rom address found\n"); return NULL; 2829 } 2830 2831 printk("ROM Size is %dK, Address is %x\n", rom_size/1024, rom_address); 2832 2833 /* Map ROM */ 2834 pci_write_config_dword(dev, PCI_ROM_ADDRESS, rom_address | PCI_ROM_ADDRESS_ENABLE); 2835 2836 /* memcpy(copy_address, rom_address, rom_size); */ 2837 { 2838 unsigned char *virt_addr = ioremap(rom_address, 0x8000000); 2839 2840 unsigned char *from = (unsigned char *)virt_addr; 2841 unsigned char *to = (unsigned char *)copy_address; 2842 for (j=0; j<65536 /*rom_size*/; j++) *to++ = *from++; 2843 } 2844 2845 pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0); 2846 2847 printk("Copy is done\n"); 2848 2849 return copy_address; 2850} 2851 2852int __devinit xgifb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 2853{ 2854 u16 reg16; 2855 u8 reg, reg1; 2856 u8 CR48,CR38; 2857 if (XGIfb_off) 2858 return -ENXIO; 2859 2860 XGIfb_registered = 0; 2861 2862 memset(&XGIhw_ext, 0, sizeof(struct xgi_hw_device_info)); 2863 fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev); 2864 if(!fb_info) return -ENOMEM; 2865 2866 xgi_video_info.chip_id = pdev->device; 2867 pci_read_config_byte(pdev, PCI_REVISION_ID,&xgi_video_info.revision_id); 2868 pci_read_config_word(pdev, PCI_COMMAND, ®16); 2869 XGIhw_ext.jChipRevision = xgi_video_info.revision_id; 2870 XGIvga_enabled = reg16 & 0x01; 2871 2872 xgi_video_info.pcibus = pdev->bus->number; 2873 xgi_video_info.pcislot = PCI_SLOT(pdev->devfn); 2874 xgi_video_info.pcifunc = PCI_FUNC(pdev->devfn); 2875 xgi_video_info.subsysvendor = pdev->subsystem_vendor; 2876 xgi_video_info.subsysdevice = pdev->subsystem_device; 2877 2878 xgi_video_info.video_base = pci_resource_start(pdev, 0); 2879 xgi_video_info.mmio_base = pci_resource_start(pdev, 1); 2880 XGIfb_mmio_size = pci_resource_len(pdev, 1); 2881 xgi_video_info.vga_base = pci_resource_start(pdev, 2) + 0x30; 2882 XGIhw_ext.pjIOAddress = (unsigned char *)xgi_video_info.vga_base; 2883 //XGI_Pr.RelIO = ioremap(pci_resource_start(pdev, 2), 128) + 0x30; 2884 printk("XGIfb: Relocate IO address: %lx [%08lx]\n", 2885 (unsigned long)pci_resource_start(pdev, 2), XGI_Pr.RelIO); 2886 2887 if (pci_enable_device(pdev)) 2888 return -EIO; 2889 2890 XGIRegInit(&XGI_Pr, (unsigned long)XGIhw_ext.pjIOAddress); 2891 2892 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD); 2893 inXGIIDXREG(XGISR, IND_XGI_PASSWORD, reg1); 2894 2895 if(reg1 != 0xa1) /*I/O error */ 2896 { 2897 printk("\nXGIfb: I/O error!!!"); 2898 return -EIO; 2899 } 2900 2901 switch (xgi_video_info.chip_id) { 2902 case PCI_DEVICE_ID_XG_20: 2903 orXGIIDXREG(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN); 2904 inXGIIDXREG(XGICR, Index_CR_GPIO_Reg1, CR48); 2905 if (CR48&GPIOG_READ) 2906 xgi_video_info.chip = XG21; 2907 else 2908 xgi_video_info.chip = XG20; 2909 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2; 2910 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315; 2911 break; 2912 case PCI_DEVICE_ID_XG_40: 2913 xgi_video_info.chip = XG40; 2914 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2; 2915 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315; 2916 break; 2917 case PCI_DEVICE_ID_XG_41: 2918 xgi_video_info.chip = XG41; 2919 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2; 2920 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315; 2921 break; 2922 case PCI_DEVICE_ID_XG_42: 2923 xgi_video_info.chip = XG42; 2924 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2; 2925 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315; 2926 break; 2927 case PCI_DEVICE_ID_XG_27: 2928 xgi_video_info.chip = XG27; 2929 XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2; 2930 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315; 2931 break; 2932 default: 2933 return -ENODEV; 2934 } 2935 2936 printk("XGIfb:chipid = %x\n",xgi_video_info.chip); 2937 XGIhw_ext.jChipType = xgi_video_info.chip; 2938 2939 switch (xgi_video_info.chip) { 2940 case XG40: 2941 case XG41: 2942 case XG42: 2943 case XG45: 2944 case XG20: 2945 case XG21: 2946 case XG27: 2947 XGIhw_ext.bIntegratedMMEnabled = 1; 2948 break; 2949 2950 default: 2951 break; 2952 } 2953 2954 2955 XGIhw_ext.pDevice = NULL; 2956 if ((xgi_video_info.chip == XG21) || (XGIfb_userom)) 2957 { 2958 XGIhw_ext.pjVirtualRomBase = attempt_map_rom(pdev, VBIOS_BUF); 2959 2960 if(XGIhw_ext.pjVirtualRomBase) 2961 printk(KERN_INFO "XGIfb: Video ROM found and mapped to %p\n",XGIhw_ext.pjVirtualRomBase); 2962 else 2963 printk(KERN_INFO "XGIfb: Video ROM not found\n"); 2964 } else { 2965 XGIhw_ext.pjVirtualRomBase = NULL; 2966 printk(KERN_INFO "XGIfb: Video ROM usage disabled\n"); 2967 } 2968 XGIhw_ext.pjCustomizedROMImage = NULL; 2969 XGIhw_ext.bSkipDramSizing = 0; 2970 XGIhw_ext.pQueryVGAConfigSpace = &XGIfb_query_VGA_config_space; 2971// XGIhw_ext.pQueryNorthBridgeSpace = &XGIfb_query_north_bridge_space; 2972 strcpy(XGIhw_ext.szVBIOSVer, "0.84"); 2973 2974 2975 XGIhw_ext.pSR = vmalloc(sizeof(struct XGI_DSReg) * SR_BUFFER_SIZE); 2976 if (XGIhw_ext.pSR == NULL) 2977 { 2978 printk(KERN_ERR "XGIfb: Fatal error: Allocating SRReg space failed.\n"); 2979 return -ENODEV; 2980 } 2981 XGIhw_ext.pSR[0].jIdx = XGIhw_ext.pSR[0].jVal = 0xFF; 2982 2983 XGIhw_ext.pCR = vmalloc(sizeof(struct XGI_DSReg) * CR_BUFFER_SIZE); 2984 if (XGIhw_ext.pCR == NULL) 2985 { 2986 vfree(XGIhw_ext.pSR); 2987 printk(KERN_ERR "XGIfb: Fatal error: Allocating CRReg space failed.\n"); 2988 return -ENODEV; 2989 } 2990 XGIhw_ext.pCR[0].jIdx = XGIhw_ext.pCR[0].jVal = 0xFF; 2991 2992 2993 2994 2995 if (!XGIvga_enabled) 2996 { 2997 /* Mapping Max FB Size for 315 Init */ 2998 XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000); 2999 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) 3000 { 3001#ifdef LINUXBIOS 3002 printk("XGIfb: XGIInit() ..."); 3003 /* XGIInitNewt for LINUXBIOS only */ 3004 if(XGIInitNew(&XGIhw_ext)) 3005 { 3006 printk("OK\n"); 3007 } 3008 else 3009 { 3010 printk("Fail\n"); 3011 } 3012#endif 3013 3014 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD); 3015 3016 3017 } 3018 } 3019#ifdef LINUXBIOS 3020 else 3021 { 3022 XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000); 3023 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) 3024 { 3025 3026 outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD); 3027 3028 // yilin Because no VBIOS DRAM Sizing, Dram size will error. 3029 // Set SR13 ,14 temporarily for UDtech 3030 outXGIIDXREG(XGISR, 0x13, 0x45); 3031 outXGIIDXREG(XGISR, 0x14, 0x51); 3032 3033 3034 } 3035 } 3036#endif 3037 if (XGIfb_get_dram_size()) 3038 { 3039 vfree(XGIhw_ext.pSR); 3040 vfree(XGIhw_ext.pCR); 3041 printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n"); 3042 return -ENODEV; 3043 } 3044 3045 3046 3047 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) 3048 { 3049 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */ 3050 orXGIIDXREG(XGISR, IND_XGI_PCI_ADDRESS_SET, (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE)); 3051 /* Enable 2D accelerator engine */ 3052 orXGIIDXREG(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D); 3053 } 3054 3055 XGIhw_ext.ulVideoMemorySize = xgi_video_info.video_size; 3056 3057 if (!request_mem_region(xgi_video_info.video_base, xgi_video_info.video_size, "XGIfb FB")) 3058 { printk("unable request memory size %x",xgi_video_info.video_size); 3059 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve frame buffer memory\n"); 3060 printk(KERN_ERR "XGIfb: Is there another framebuffer driver active?\n"); 3061 vfree(XGIhw_ext.pSR); 3062 vfree(XGIhw_ext.pCR); 3063 return -ENODEV; 3064 } 3065 3066 if (!request_mem_region(xgi_video_info.mmio_base, XGIfb_mmio_size, "XGIfb MMIO")) 3067 { 3068 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve MMIO region\n"); 3069 release_mem_region(xgi_video_info.video_base, xgi_video_info.video_size); 3070 vfree(XGIhw_ext.pSR); 3071 vfree(XGIhw_ext.pCR); 3072 return -ENODEV; 3073 } 3074 3075 xgi_video_info.video_vbase = XGIhw_ext.pjVideoMemoryAddress = 3076 ioremap(xgi_video_info.video_base, xgi_video_info.video_size); 3077 xgi_video_info.mmio_vbase = ioremap(xgi_video_info.mmio_base, XGIfb_mmio_size); 3078 3079 printk(KERN_INFO "XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n", 3080 xgi_video_info.video_base, xgi_video_info.video_vbase,xgi_video_info.video_size / 1024); 3081 3082 printk(KERN_INFO "XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n", 3083 xgi_video_info.mmio_base, xgi_video_info.mmio_vbase,XGIfb_mmio_size / 1024); 3084 printk("XGIfb: XGIInitNew() ..."); 3085 if(XGIInitNew(&XGIhw_ext)) 3086 { 3087 printk("OK\n"); 3088 } 3089 else 3090 { 3091 printk("Fail\n"); 3092 } 3093 3094 if(XGIfb_heap_init()) 3095 { 3096 printk(KERN_WARNING "XGIfb: Failed to initialize offscreen memory heap\n"); 3097 } 3098 3099 3100 xgi_video_info.mtrr = (unsigned int) 0; 3101 3102 if((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) 3103 { 3104 xgi_video_info.hasVB = HASVB_NONE; 3105 if((xgi_video_info.chip == XG20)||(xgi_video_info.chip == XG27)) 3106 xgi_video_info.hasVB = HASVB_NONE; 3107 else if(xgi_video_info.chip == XG21) { 3108 inXGIIDXREG(XGICR,0x38,CR38); 3109 if ((CR38&0xE0) == 0xC0) { 3110 xgi_video_info.disp_state = DISPTYPE_LCD; 3111 if (!XGIfb_GetXG21LVDSData()) { 3112 int m; 3113 for (m = 0; m < sizeof(XGI21_LCDCapList)/sizeof(struct XGI21_LVDSCapStruct); m++) { 3114 if ((XGI21_LCDCapList[m].LVDSHDE == XGIbios_mode[xgifb_mode_idx].xres) && 3115 (XGI21_LCDCapList[m].LVDSVDE == XGIbios_mode[xgifb_mode_idx].yres)) { 3116 XGINew_SetReg1( XGI_Pr.P3d4 , 0x36, m) ; 3117 } 3118 } 3119 } 3120 } 3121 else if ((CR38&0xE0) == 0x60) 3122 xgi_video_info.hasVB = HASVB_CHRONTEL ; 3123 else 3124 xgi_video_info.hasVB = HASVB_NONE; 3125 } 3126 else 3127 XGIfb_get_VB_type(); 3128 3129 XGIhw_ext.ujVBChipID = VB_CHIP_UNKNOWN; 3130 3131 XGIhw_ext.ulExternalChip = 0; 3132 3133 switch (xgi_video_info.hasVB) { 3134 case HASVB_301: 3135 inXGIIDXREG(XGIPART4, 0x01, reg); 3136 if (reg >= 0xE0) { 3137 XGIhw_ext.ujVBChipID = VB_CHIP_302LV; 3138 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg); 3139 } else if (reg >= 0xD0) { 3140 XGIhw_ext.ujVBChipID = VB_CHIP_301LV; 3141 printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n",reg); 3142 } 3143 /* else if (reg >= 0xB0) { 3144 XGIhw_ext.ujVBChipID = VB_CHIP_301B; 3145 inXGIIDXREG(XGIPART4,0x23,reg1); 3146 printk("XGIfb: XGI301B bridge detected\n"); 3147 }*/ 3148 else { 3149 XGIhw_ext.ujVBChipID = VB_CHIP_301; 3150 printk("XGIfb: XGI301 bridge detected\n"); 3151 } 3152 break; 3153 case HASVB_302: 3154 inXGIIDXREG(XGIPART4, 0x01, reg); 3155 if (reg >= 0xE0) { 3156 XGIhw_ext.ujVBChipID = VB_CHIP_302LV; 3157 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg); 3158 } else if (reg >= 0xD0) { 3159 XGIhw_ext.ujVBChipID = VB_CHIP_301LV; 3160 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n",reg); 3161 } else if (reg >= 0xB0) { 3162 inXGIIDXREG(XGIPART4,0x23,reg1); 3163 3164 XGIhw_ext.ujVBChipID = VB_CHIP_302B; 3165 3166 } else { 3167 XGIhw_ext.ujVBChipID = VB_CHIP_302; 3168 printk(KERN_INFO "XGIfb: XGI302 bridge detected\n"); 3169 } 3170 break; 3171 case HASVB_LVDS: 3172 XGIhw_ext.ulExternalChip = 0x1; 3173 printk(KERN_INFO "XGIfb: LVDS transmitter detected\n"); 3174 break; 3175 case HASVB_TRUMPION: 3176 XGIhw_ext.ulExternalChip = 0x2; 3177 printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n"); 3178 break; 3179 case HASVB_CHRONTEL: 3180 XGIhw_ext.ulExternalChip = 0x4; 3181 printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n"); 3182 break; 3183 case HASVB_LVDS_CHRONTEL: 3184 XGIhw_ext.ulExternalChip = 0x5; 3185 printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n"); 3186 break; 3187 default: 3188 printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n"); 3189 break; 3190 } 3191 3192 if (xgi_video_info.hasVB != HASVB_NONE) { 3193 XGIfb_detect_VB(); 3194 } 3195 3196 if (xgi_video_info.disp_state & DISPTYPE_DISP2) { 3197 if (XGIfb_crt1off) 3198 xgi_video_info.disp_state |= DISPMODE_SINGLE; 3199 else 3200 xgi_video_info.disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1); 3201 } else { 3202 xgi_video_info.disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1; 3203 } 3204 3205 if (xgi_video_info.disp_state & DISPTYPE_LCD) { 3206 if (!enable_dstn) { 3207 inXGIIDXREG(XGICR, IND_XGI_LCD_PANEL, reg); 3208 reg &= 0x0f; 3209 XGIhw_ext.ulCRT2LCDType = XGI310paneltype[reg]; 3210 3211 } else { 3212 // TW: FSTN/DSTN 3213 XGIhw_ext.ulCRT2LCDType = LCD_320x480; 3214 } 3215 } 3216 3217 XGIfb_detectedpdc = 0; 3218 3219 XGIfb_detectedlcda = 0xff; 3220#ifndef LINUXBIOS 3221 3222 /* TW: Try to find about LCDA */ 3223 3224 if((XGIhw_ext.ujVBChipID == VB_CHIP_302B) || 3225 (XGIhw_ext.ujVBChipID == VB_CHIP_301LV) || 3226 (XGIhw_ext.ujVBChipID == VB_CHIP_302LV)) 3227 { 3228 int tmp; 3229 inXGIIDXREG(XGICR,0x34,tmp); 3230 if(tmp <= 0x13) 3231 { 3232 // Currently on LCDA? (Some BIOSes leave CR38) 3233 inXGIIDXREG(XGICR,0x38,tmp); 3234 if((tmp & 0x03) == 0x03) 3235 { 3236/* XGI_Pr.XGI_UseLCDA = 1; */ 3237 }else 3238 { 3239 // Currently on LCDA? (Some newer BIOSes set D0 in CR35) 3240 inXGIIDXREG(XGICR,0x35,tmp); 3241 if(tmp & 0x01) 3242 { 3243/* XGI_Pr.XGI_UseLCDA = 1; */ 3244 }else 3245 { 3246 inXGIIDXREG(XGICR,0x30,tmp); 3247 if(tmp & 0x20) 3248 { 3249 inXGIIDXREG(XGIPART1,0x13,tmp); 3250 if(tmp & 0x04) 3251 { 3252/* XGI_Pr.XGI_UseLCDA = 1; */ 3253 } 3254 } 3255 } 3256 } 3257 } 3258 3259 } 3260 3261 3262#endif 3263 3264 if (xgifb_mode_idx >= 0) 3265 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx); 3266 3267 if (xgifb_mode_idx < 0) { 3268 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) { 3269 case DISPTYPE_LCD: 3270 xgifb_mode_idx = DEFAULT_LCDMODE; 3271 if (xgi_video_info.chip == XG21) 3272 { 3273 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx(); 3274 } 3275 break; 3276 case DISPTYPE_TV: 3277 xgifb_mode_idx = DEFAULT_TVMODE; 3278 break; 3279 default: 3280 xgifb_mode_idx = DEFAULT_MODE; 3281 break; 3282 } 3283 } 3284 3285 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no; 3286 3287 3288 if( xgi_video_info.refresh_rate == 0) 3289 xgi_video_info.refresh_rate = 60; /*yilin set default refresh rate */ 3290 if(XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) 3291 { 3292 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx; 3293 xgi_video_info.refresh_rate = 60; 3294 } 3295 3296 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp; 3297 xgi_video_info.video_vwidth = xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres; 3298 xgi_video_info.video_vheight = xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres; 3299 xgi_video_info.org_x = xgi_video_info.org_y = 0; 3300 xgi_video_info.video_linelength = xgi_video_info.video_width * (xgi_video_info.video_bpp >> 3); 3301 switch(xgi_video_info.video_bpp) { 3302 case 8: 3303 xgi_video_info.DstColor = 0x0000; 3304 xgi_video_info.XGI310_AccelDepth = 0x00000000; 3305 xgi_video_info.video_cmap_len = 256; 3306 break; 3307 case 16: 3308 xgi_video_info.DstColor = 0x8000; 3309 xgi_video_info.XGI310_AccelDepth = 0x00010000; 3310 xgi_video_info.video_cmap_len = 16; 3311 break; 3312 case 32: 3313 xgi_video_info.DstColor = 0xC000; 3314 xgi_video_info.XGI310_AccelDepth = 0x00020000; 3315 xgi_video_info.video_cmap_len = 16; 3316 break; 3317 default: 3318 xgi_video_info.video_cmap_len = 16; 3319 printk(KERN_INFO "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp); 3320 break; 3321 } 3322 3323 3324 3325 printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n", 3326 xgi_video_info.video_width, xgi_video_info.video_height, xgi_video_info.video_bpp, 3327 xgi_video_info.refresh_rate); 3328 3329 default_var.xres = default_var.xres_virtual = xgi_video_info.video_width; 3330 default_var.yres = default_var.yres_virtual = xgi_video_info.video_height; 3331 default_var.bits_per_pixel = xgi_video_info.video_bpp; 3332 3333 XGIfb_bpp_to_var(&default_var); 3334 3335 default_var.pixclock = (u32) (1000000000 / 3336 XGIfb_mode_rate_to_dclock(&XGI_Pr, &XGIhw_ext, 3337 XGIfb_mode_no, XGIfb_rate_idx)); 3338 3339 if(XGIfb_mode_rate_to_ddata(&XGI_Pr, &XGIhw_ext, 3340 XGIfb_mode_no, XGIfb_rate_idx, 3341 &default_var.left_margin, &default_var.right_margin, 3342 &default_var.upper_margin, &default_var.lower_margin, 3343 &default_var.hsync_len, &default_var.vsync_len, 3344 &default_var.sync, &default_var.vmode)) { 3345 3346 if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { 3347 default_var.yres <<= 1; 3348 default_var.yres_virtual <<= 1; 3349 } else if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) { 3350 default_var.pixclock >>= 1; 3351 default_var.yres >>= 1; 3352 default_var.yres_virtual >>= 1; 3353 } 3354 3355 } 3356 3357 xgi_video_info.accel = 0; 3358 if(XGIfb_accel) { 3359 xgi_video_info.accel = -1; 3360 default_var.accel_flags |= FB_ACCELF_TEXT; 3361 XGIfb_initaccel(); 3362 } 3363 3364 fb_info->flags = FBINFO_FLAG_DEFAULT; 3365 fb_info->var = default_var; 3366 fb_info->fix = XGIfb_fix; 3367 fb_info->par = &xgi_video_info; 3368 fb_info->screen_base = xgi_video_info.video_vbase; 3369 fb_info->fbops = &XGIfb_ops; 3370 XGIfb_get_fix(&fb_info->fix, -1, fb_info); 3371 fb_info->pseudo_palette = pseudo_palette; 3372 3373 fb_alloc_cmap(&fb_info->cmap, 256 , 0); 3374 3375 3376#ifdef CONFIG_MTRR 3377 xgi_video_info.mtrr = mtrr_add((unsigned int) xgi_video_info.video_base, 3378 (unsigned int) xgi_video_info.video_size, 3379 MTRR_TYPE_WRCOMB, 1); 3380 if(xgi_video_info.mtrr) { 3381 printk(KERN_INFO "XGIfb: Added MTRRs\n"); 3382 } 3383#endif 3384 3385 if(register_framebuffer(fb_info) < 0) 3386 { 3387 return -EINVAL; 3388 } 3389 3390 XGIfb_registered = 1; 3391 3392 printk(KERN_INFO "XGIfb: Installed XGIFB_GET_INFO ioctl (%lx)\n", 3393 XGIFB_GET_INFO); 3394 3395/* printk(KERN_INFO "XGIfb: 2D acceleration is %s, scrolling mode %s\n", 3396 XGIfb_accel ? "enabled" : "disabled", 3397 XGIfb_ypan ? "ypan" : "redraw"); 3398*/ 3399 printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n", 3400 fb_info->node, myid, VER_MAJOR, VER_MINOR, VER_LEVEL); 3401 3402 3403 } 3404 3405 dumpVGAReg(); 3406 3407 return 0; 3408} 3409 3410 3411/*****************************************************/ 3412/* PCI DEVICE HANDLING */ 3413/*****************************************************/ 3414 3415static void __devexit xgifb_remove(struct pci_dev *pdev) 3416{ 3417 /* Unregister the framebuffer */ 3418// if(xgi_video_info.registered) { 3419 unregister_framebuffer(fb_info); 3420 framebuffer_release(fb_info); 3421// } 3422 3423 pci_set_drvdata(pdev, NULL); 3424 3425}; 3426 3427static struct pci_driver xgifb_driver = { 3428 .name = "xgifb", 3429 .id_table = xgifb_pci_table, 3430 .probe = xgifb_probe, 3431 .remove = __devexit_p(xgifb_remove) 3432}; 3433 3434XGIINITSTATIC int __init xgifb_init(void) 3435{ 3436#ifndef MODULE 3437 char *option = NULL; 3438 3439 if (fb_get_options("xgifb", &option)) 3440 return -ENODEV; 3441 XGIfb_setup(option); 3442#endif 3443 return(pci_register_driver(&xgifb_driver)); 3444} 3445 3446 3447#ifndef MODULE 3448module_init(xgifb_init); 3449#endif 3450 3451/*****************************************************/ 3452/* MODULE */ 3453/*****************************************************/ 3454 3455#ifdef MODULE 3456 3457static char *mode = NULL; 3458static int vesa = 0; 3459static unsigned int rate = 0; 3460static unsigned int crt1off = 1; 3461static unsigned int mem = 0; 3462static char *forcecrt2type = NULL; 3463static int forcecrt1 = -1; 3464static int pdc = -1; 3465static int pdc1 = -1; 3466static int noaccel = -1; 3467static int noypan = -1; 3468static int nomax = -1; 3469static int userom = -1; 3470static int useoem = -1; 3471static char *tvstandard = NULL; 3472static int nocrt2rate = 0; 3473static int scalelcd = -1; 3474static char *specialtiming = NULL; 3475static int lvdshl = -1; 3476static int tvxposoffset = 0, tvyposoffset = 0; 3477#if !defined(__i386__) && !defined(__x86_64__) 3478static int resetcard = 0; 3479static int videoram = 0; 3480#endif 3481 3482MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver"); 3483MODULE_LICENSE("GPL"); 3484MODULE_AUTHOR("XGITECH , Others"); 3485 3486 3487 3488module_param(mem, int, 0); 3489module_param(noaccel, int, 0); 3490module_param(noypan, int, 0); 3491module_param(nomax, int, 0); 3492module_param(userom, int, 0); 3493module_param(useoem, int, 0); 3494module_param(mode, charp, 0); 3495module_param(vesa, int, 0); 3496module_param(rate, int, 0); 3497module_param(forcecrt1, int, 0); 3498module_param(forcecrt2type, charp, 0); 3499module_param(scalelcd, int, 0); 3500module_param(pdc, int, 0); 3501module_param(pdc1, int, 0); 3502module_param(specialtiming, charp, 0); 3503module_param(lvdshl, int, 0); 3504module_param(tvstandard, charp, 0); 3505module_param(tvxposoffset, int, 0); 3506module_param(tvyposoffset, int, 0); 3507module_param(filter, int, 0); 3508module_param(nocrt2rate, int, 0); 3509#if !defined(__i386__) && !defined(__x86_64__) 3510module_param(resetcard, int, 0); 3511module_param(videoram, int, 0); 3512#endif 3513 3514 3515MODULE_PARM_DESC(mem, 3516 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n" 3517 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n" 3518 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n" 3519 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n" 3520 "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n" 3521 "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n" 3522 "for XFree86 4.x/X.org 6.7 and later.\n"); 3523 3524MODULE_PARM_DESC(noaccel, 3525 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n" 3526 "(default: 0)\n"); 3527 3528MODULE_PARM_DESC(noypan, 3529 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n" 3530 "will be performed by redrawing the screen. (default: 0)\n"); 3531 3532MODULE_PARM_DESC(nomax, 3533 "\nIf y-panning is enabled, xgifb will by default use the entire available video\n" 3534 "memory for the virtual screen in order to optimize scrolling performance. If\n" 3535 "this is set to anything other than 0, xgifb will not do this and thereby \n" 3536 "enable the user to positively specify a virtual Y size of the screen using\n" 3537 "fbset. (default: 0)\n"); 3538 3539 3540 3541MODULE_PARM_DESC(mode, 3542 "\nSelects the desired default display mode in the format XxYxDepth,\n" 3543 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n" 3544 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n" 3545 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n"); 3546 3547MODULE_PARM_DESC(vesa, 3548 "\nSelects the desired default display mode by VESA defined mode number, eg.\n" 3549 "0x117 (default: 0x0103)\n"); 3550 3551 3552MODULE_PARM_DESC(rate, 3553 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n" 3554 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n" 3555 "will be ignored (default: 60)\n"); 3556 3557MODULE_PARM_DESC(forcecrt1, 3558 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n" 3559 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n" 3560 "0=CRT1 OFF) (default: [autodetected])\n"); 3561 3562MODULE_PARM_DESC(forcecrt2type, 3563 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n" 3564 "LCD, TV or secondary VGA. With this option, this autodetection can be\n" 3565 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n" 3566 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n" 3567 "be used instead of TV to override the TV detection. Furthermore, on systems\n" 3568 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n" 3569 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n" 3570 "depends on the very hardware in use. (default: [autodetected])\n"); 3571 3572MODULE_PARM_DESC(scalelcd, 3573 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n" 3574 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n" 3575 "show black bars around the image, TMDS panels will probably do the scaling\n" 3576 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n"); 3577 3578MODULE_PARM_DESC(pdc, 3579 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n" 3580 "should detect this correctly in most cases; however, sometimes this is not\n" 3581 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n" 3582 "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n" 3583 "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n" 3584 "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n"); 3585 3586MODULE_PARM_DESC(pdc1, 3587 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n" 3588 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n" 3589 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n" 3590 "implemented yet.\n"); 3591 3592MODULE_PARM_DESC(specialtiming, 3593 "\nPlease refer to documentation for more information on this option.\n"); 3594 3595MODULE_PARM_DESC(lvdshl, 3596 "\nPlease refer to documentation for more information on this option.\n"); 3597 3598MODULE_PARM_DESC(tvstandard, 3599 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n" 3600 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n"); 3601 3602MODULE_PARM_DESC(tvxposoffset, 3603 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n" 3604 "Default: 0\n"); 3605 3606MODULE_PARM_DESC(tvyposoffset, 3607 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n" 3608 "Default: 0\n"); 3609 3610MODULE_PARM_DESC(filter, 3611 "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n" 3612 "(Possible values 0-7, default: [no filter])\n"); 3613 3614MODULE_PARM_DESC(nocrt2rate, 3615 "\nSetting this to 1 will force the driver to use the default refresh rate for\n" 3616 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n"); 3617 3618 3619 3620 3621int __init xgifb_init_module(void) 3622{ 3623 printk("\nXGIfb_init_module"); 3624 if(mode) 3625 XGIfb_search_mode(mode); 3626 else if (vesa != -1) 3627 XGIfb_search_vesamode(vesa); 3628 3629 return(xgifb_init()); 3630} 3631 3632static void __exit xgifb_remove_module(void) 3633{ 3634 pci_unregister_driver(&xgifb_driver); 3635 printk(KERN_DEBUG "xgifb: Module unloaded\n"); 3636} 3637 3638module_init(xgifb_init_module); 3639module_exit(xgifb_remove_module); 3640 3641#endif /* /MODULE */ 3642 3643EXPORT_SYMBOL(XGI_malloc); 3644EXPORT_SYMBOL(XGI_free); 3645