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