1 /*
2 * SiS 300/540/630[S]/730[S],
3 * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX],
4 * XGI V3XT/V5/V8, Z7
5 * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
6 *
7 * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the named License,
12 * or any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
22 *
23 * Author: Thomas Winischhofer <thomas@winischhofer.net>
24 *
25 * Author of (practically wiped) code base:
26 * SiS (www.sis.com)
27 * Copyright (C) 1999 Silicon Integrated Systems, Inc.
28 *
29 * See http://www.winischhofer.net/ for more information and updates
30 *
31 * Originally based on the VBE 2.0 compliant graphic boards framebuffer driver,
32 * which is (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
33 *
34 */
35
36 #include <linux/module.h>
37 #include <linux/moduleparam.h>
38 #include <linux/kernel.h>
39 #include <linux/spinlock.h>
40 #include <linux/errno.h>
41 #include <linux/string.h>
42 #include <linux/mm.h>
43 #include <linux/screen_info.h>
44 #include <linux/slab.h>
45 #include <linux/fb.h>
46 #include <linux/selection.h>
47 #include <linux/ioport.h>
48 #include <linux/init.h>
49 #include <linux/pci.h>
50 #include <linux/vmalloc.h>
51 #include <linux/capability.h>
52 #include <linux/fs.h>
53 #include <linux/types.h>
54 #include <linux/uaccess.h>
55 #include <asm/io.h>
56
57 #include "sis.h"
58 #include "sis_main.h"
59 #include "init301.h"
60
61 #if !defined(CONFIG_FB_SIS_300) && !defined(CONFIG_FB_SIS_315)
62 #warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
63 #warning sisfb will not work!
64 #endif
65
66 /* ---------------------- Prototypes ------------------------- */
67
68 /* Interface used by the world */
69 #ifndef MODULE
70 static int sisfb_setup(char *options);
71 #endif
72
73 /* Interface to the low level console driver */
74 static int sisfb_init(void);
75
76 /* fbdev routines */
77 static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
78 struct fb_info *info);
79
80 static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
81 unsigned long arg);
82 static int sisfb_set_par(struct fb_info *info);
83 static int sisfb_blank(int blank,
84 struct fb_info *info);
85
86 static void sisfb_handle_command(struct sis_video_info *ivideo,
87 struct sisfb_cmd *sisfb_command);
88
89 static void sisfb_search_mode(char *name, bool quiet);
90 static int sisfb_validate_mode(struct sis_video_info *ivideo, int modeindex, u32 vbflags);
91 static u8 sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate,
92 int index);
93 static int sisfb_setcolreg(unsigned regno, unsigned red, unsigned green,
94 unsigned blue, unsigned transp,
95 struct fb_info *fb_info);
96 static int sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
97 struct fb_info *info);
98 static void sisfb_pre_setmode(struct sis_video_info *ivideo);
99 static void sisfb_post_setmode(struct sis_video_info *ivideo);
100 static bool sisfb_CheckVBRetrace(struct sis_video_info *ivideo);
101 static bool sisfbcheckvretracecrt2(struct sis_video_info *ivideo);
102 static bool sisfbcheckvretracecrt1(struct sis_video_info *ivideo);
103 static bool sisfb_bridgeisslave(struct sis_video_info *ivideo);
104 static void sisfb_detect_VB_connect(struct sis_video_info *ivideo);
105 static void sisfb_get_VB_type(struct sis_video_info *ivideo);
106 static void sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val);
107 static void sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val);
108
109 /* Internal heap routines */
110 static int sisfb_heap_init(struct sis_video_info *ivideo);
111 static struct SIS_OH * sisfb_poh_new_node(struct SIS_HEAP *memheap);
112 static struct SIS_OH * sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size);
113 static void sisfb_delete_node(struct SIS_OH *poh);
114 static void sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh);
115 static struct SIS_OH * sisfb_poh_free(struct SIS_HEAP *memheap, u32 base);
116 static void sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh);
117
118
119 /* ------------------ Internal helper routines ----------------- */
120
121 static void __init
sisfb_setdefaultparms(void)122 sisfb_setdefaultparms(void)
123 {
124 sisfb_off = 0;
125 sisfb_parm_mem = 0;
126 sisfb_accel = -1;
127 sisfb_ypan = -1;
128 sisfb_max = -1;
129 sisfb_userom = -1;
130 sisfb_useoem = -1;
131 sisfb_mode_idx = -1;
132 sisfb_parm_rate = -1;
133 sisfb_crt1off = 0;
134 sisfb_forcecrt1 = -1;
135 sisfb_crt2type = -1;
136 sisfb_crt2flags = 0;
137 sisfb_pdc = 0xff;
138 sisfb_pdca = 0xff;
139 sisfb_scalelcd = -1;
140 sisfb_specialtiming = CUT_NONE;
141 sisfb_lvdshl = -1;
142 sisfb_dstn = 0;
143 sisfb_fstn = 0;
144 sisfb_tvplug = -1;
145 sisfb_tvstd = -1;
146 sisfb_tvxposoffset = 0;
147 sisfb_tvyposoffset = 0;
148 sisfb_nocrt2rate = 0;
149 #if !defined(__i386__) && !defined(__x86_64__)
150 sisfb_resetcard = 0;
151 sisfb_videoram = 0;
152 #endif
153 }
154
155 /* ------------- Parameter parsing -------------- */
156
sisfb_search_vesamode(unsigned int vesamode,bool quiet)157 static void sisfb_search_vesamode(unsigned int vesamode, bool quiet)
158 {
159 int i = 0, j = 0;
160
161 /* We don't know the hardware specs yet and there is no ivideo */
162
163 if(vesamode == 0) {
164 if(!quiet)
165 printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
166
167 sisfb_mode_idx = DEFAULT_MODE;
168
169 return;
170 }
171
172 vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
173
174 while(sisbios_mode[i++].mode_no[0] != 0) {
175 if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
176 (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
177 if(sisfb_fstn) {
178 if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
179 sisbios_mode[i-1].mode_no[1] == 0x56 ||
180 sisbios_mode[i-1].mode_no[1] == 0x53)
181 continue;
182 } else {
183 if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
184 sisbios_mode[i-1].mode_no[1] == 0x5b)
185 continue;
186 }
187 sisfb_mode_idx = i - 1;
188 j = 1;
189 break;
190 }
191 }
192 if((!j) && !quiet)
193 printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
194 }
195
sisfb_search_mode(char * name,bool quiet)196 static void sisfb_search_mode(char *name, bool quiet)
197 {
198 unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
199 int i = 0;
200 char strbuf[16], strbuf1[20];
201 char *nameptr = name;
202
203 /* We don't know the hardware specs yet and there is no ivideo */
204
205 if(name == NULL) {
206 if(!quiet)
207 printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
208
209 sisfb_mode_idx = DEFAULT_MODE;
210 return;
211 }
212
213 if(!strncasecmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
214 if(!quiet)
215 printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
216
217 sisfb_mode_idx = DEFAULT_MODE;
218 return;
219 }
220
221 if(strlen(name) <= 19) {
222 strcpy(strbuf1, name);
223 for(i = 0; i < strlen(strbuf1); i++) {
224 if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
225 }
226
227 /* This does some fuzzy mode naming detection */
228 if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
229 if((rate <= 32) || (depth > 32)) {
230 j = rate; rate = depth; depth = j;
231 }
232 sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
233 nameptr = strbuf;
234 sisfb_parm_rate = rate;
235 } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
236 sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
237 nameptr = strbuf;
238 } else {
239 xres = 0;
240 if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
241 sprintf(strbuf, "%ux%ux8", xres, yres);
242 nameptr = strbuf;
243 } else {
244 sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
245 return;
246 }
247 }
248 }
249
250 i = 0; j = 0;
251 while(sisbios_mode[i].mode_no[0] != 0) {
252 if(!strncasecmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
253 if(sisfb_fstn) {
254 if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
255 sisbios_mode[i-1].mode_no[1] == 0x56 ||
256 sisbios_mode[i-1].mode_no[1] == 0x53)
257 continue;
258 } else {
259 if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
260 sisbios_mode[i-1].mode_no[1] == 0x5b)
261 continue;
262 }
263 sisfb_mode_idx = i - 1;
264 j = 1;
265 break;
266 }
267 }
268
269 if((!j) && !quiet)
270 printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
271 }
272
273 #ifndef MODULE
sisfb_get_vga_mode_from_kernel(void)274 static void sisfb_get_vga_mode_from_kernel(void)
275 {
276 #ifdef CONFIG_X86
277 char mymode[32];
278 int mydepth = screen_info.lfb_depth;
279
280 if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return;
281
282 if( (screen_info.lfb_width >= 320) && (screen_info.lfb_width <= 2048) &&
283 (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) &&
284 (mydepth >= 8) && (mydepth <= 32) ) {
285
286 if(mydepth == 24) mydepth = 32;
287
288 sprintf(mymode, "%ux%ux%u", screen_info.lfb_width,
289 screen_info.lfb_height,
290 mydepth);
291
292 printk(KERN_DEBUG
293 "sisfb: Using vga mode %s pre-set by kernel as default\n",
294 mymode);
295
296 sisfb_search_mode(mymode, true);
297 }
298 #endif
299 return;
300 }
301 #endif
302
303 static void __init
sisfb_search_crt2type(const char * name)304 sisfb_search_crt2type(const char *name)
305 {
306 int i = 0;
307
308 /* We don't know the hardware specs yet and there is no ivideo */
309
310 if(name == NULL) return;
311
312 while(sis_crt2type[i].type_no != -1) {
313 if(!strncasecmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
314 sisfb_crt2type = sis_crt2type[i].type_no;
315 sisfb_tvplug = sis_crt2type[i].tvplug_no;
316 sisfb_crt2flags = sis_crt2type[i].flags;
317 break;
318 }
319 i++;
320 }
321
322 sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0;
323 sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0;
324
325 if(sisfb_crt2type < 0)
326 printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
327 }
328
329 static void __init
sisfb_search_tvstd(const char * name)330 sisfb_search_tvstd(const char *name)
331 {
332 int i = 0;
333
334 /* We don't know the hardware specs yet and there is no ivideo */
335
336 if(name == NULL)
337 return;
338
339 while(sis_tvtype[i].type_no != -1) {
340 if(!strncasecmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
341 sisfb_tvstd = sis_tvtype[i].type_no;
342 break;
343 }
344 i++;
345 }
346 }
347
348 static void __init
sisfb_search_specialtiming(const char * name)349 sisfb_search_specialtiming(const char *name)
350 {
351 int i = 0;
352 bool found = false;
353
354 /* We don't know the hardware specs yet and there is no ivideo */
355
356 if(name == NULL)
357 return;
358
359 if(!strncasecmp(name, "none", 4)) {
360 sisfb_specialtiming = CUT_FORCENONE;
361 printk(KERN_DEBUG "sisfb: Special timing disabled\n");
362 } else {
363 while(mycustomttable[i].chipID != 0) {
364 if(!strncasecmp(name,mycustomttable[i].optionName,
365 strlen(mycustomttable[i].optionName))) {
366 sisfb_specialtiming = mycustomttable[i].SpecialID;
367 found = true;
368 printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
369 mycustomttable[i].vendorName,
370 mycustomttable[i].cardName,
371 mycustomttable[i].optionName);
372 break;
373 }
374 i++;
375 }
376 if(!found) {
377 printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
378 printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
379 i = 0;
380 while(mycustomttable[i].chipID != 0) {
381 printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
382 mycustomttable[i].optionName,
383 mycustomttable[i].vendorName,
384 mycustomttable[i].cardName);
385 i++;
386 }
387 }
388 }
389 }
390
391 /* ----------- Various detection routines ----------- */
392
sisfb_detect_custom_timing(struct sis_video_info * ivideo)393 static void sisfb_detect_custom_timing(struct sis_video_info *ivideo)
394 {
395 unsigned char *biosver = NULL;
396 unsigned char *biosdate = NULL;
397 bool footprint;
398 u32 chksum = 0;
399 int i, j;
400
401 if(ivideo->SiS_Pr.UseROM) {
402 biosver = ivideo->SiS_Pr.VirtualRomBase + 0x06;
403 biosdate = ivideo->SiS_Pr.VirtualRomBase + 0x2c;
404 for(i = 0; i < 32768; i++)
405 chksum += ivideo->SiS_Pr.VirtualRomBase[i];
406 }
407
408 i = 0;
409 do {
410 if( (mycustomttable[i].chipID == ivideo->chip) &&
411 ((!strlen(mycustomttable[i].biosversion)) ||
412 (ivideo->SiS_Pr.UseROM &&
413 (!strncmp(mycustomttable[i].biosversion, biosver,
414 strlen(mycustomttable[i].biosversion))))) &&
415 ((!strlen(mycustomttable[i].biosdate)) ||
416 (ivideo->SiS_Pr.UseROM &&
417 (!strncmp(mycustomttable[i].biosdate, biosdate,
418 strlen(mycustomttable[i].biosdate))))) &&
419 ((!mycustomttable[i].bioschksum) ||
420 (ivideo->SiS_Pr.UseROM &&
421 (mycustomttable[i].bioschksum == chksum))) &&
422 (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
423 (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
424 footprint = true;
425 for(j = 0; j < 5; j++) {
426 if(mycustomttable[i].biosFootprintAddr[j]) {
427 if(ivideo->SiS_Pr.UseROM) {
428 if(ivideo->SiS_Pr.VirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
429 mycustomttable[i].biosFootprintData[j]) {
430 footprint = false;
431 }
432 } else
433 footprint = false;
434 }
435 }
436 if(footprint) {
437 ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
438 printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
439 mycustomttable[i].vendorName,
440 mycustomttable[i].cardName);
441 printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
442 mycustomttable[i].optionName);
443 break;
444 }
445 }
446 i++;
447 } while(mycustomttable[i].chipID);
448 }
449
sisfb_interpret_edid(struct sisfb_monitor * monitor,u8 * buffer)450 static bool sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
451 {
452 int i, j, xres, yres, refresh, index;
453 u32 emodes;
454
455 if(buffer[0] != 0x00 || buffer[1] != 0xff ||
456 buffer[2] != 0xff || buffer[3] != 0xff ||
457 buffer[4] != 0xff || buffer[5] != 0xff ||
458 buffer[6] != 0xff || buffer[7] != 0x00) {
459 printk(KERN_DEBUG "sisfb: Bad EDID header\n");
460 return false;
461 }
462
463 if(buffer[0x12] != 0x01) {
464 printk(KERN_INFO "sisfb: EDID version %d not supported\n",
465 buffer[0x12]);
466 return false;
467 }
468
469 monitor->feature = buffer[0x18];
470
471 if(!(buffer[0x14] & 0x80)) {
472 if(!(buffer[0x14] & 0x08)) {
473 printk(KERN_INFO
474 "sisfb: WARNING: Monitor does not support separate syncs\n");
475 }
476 }
477
478 if(buffer[0x13] >= 0x01) {
479 /* EDID V1 rev 1 and 2: Search for monitor descriptor
480 * to extract ranges
481 */
482 j = 0x36;
483 for(i=0; i<4; i++) {
484 if(buffer[j] == 0x00 && buffer[j + 1] == 0x00 &&
485 buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd &&
486 buffer[j + 4] == 0x00) {
487 monitor->hmin = buffer[j + 7];
488 monitor->hmax = buffer[j + 8];
489 monitor->vmin = buffer[j + 5];
490 monitor->vmax = buffer[j + 6];
491 monitor->dclockmax = buffer[j + 9] * 10 * 1000;
492 monitor->datavalid = true;
493 break;
494 }
495 j += 18;
496 }
497 }
498
499 if(!monitor->datavalid) {
500 /* Otherwise: Get a range from the list of supported
501 * Estabished Timings. This is not entirely accurate,
502 * because fixed frequency monitors are not supported
503 * that way.
504 */
505 monitor->hmin = 65535; monitor->hmax = 0;
506 monitor->vmin = 65535; monitor->vmax = 0;
507 monitor->dclockmax = 0;
508 emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16);
509 for(i = 0; i < 13; i++) {
510 if(emodes & sisfb_ddcsmodes[i].mask) {
511 if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h;
512 if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1;
513 if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v;
514 if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v;
515 if(monitor->dclockmax < sisfb_ddcsmodes[i].d) monitor->dclockmax = sisfb_ddcsmodes[i].d;
516 }
517 }
518 index = 0x26;
519 for(i = 0; i < 8; i++) {
520 xres = (buffer[index] + 31) * 8;
521 switch(buffer[index + 1] & 0xc0) {
522 case 0xc0: yres = (xres * 9) / 16; break;
523 case 0x80: yres = (xres * 4) / 5; break;
524 case 0x40: yres = (xres * 3) / 4; break;
525 default: yres = xres; break;
526 }
527 refresh = (buffer[index + 1] & 0x3f) + 60;
528 if((xres >= 640) && (yres >= 480)) {
529 for(j = 0; j < 8; j++) {
530 if((xres == sisfb_ddcfmodes[j].x) &&
531 (yres == sisfb_ddcfmodes[j].y) &&
532 (refresh == sisfb_ddcfmodes[j].v)) {
533 if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h;
534 if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1;
535 if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v;
536 if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v;
537 if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[j].d;
538 }
539 }
540 }
541 index += 2;
542 }
543 if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) {
544 monitor->datavalid = true;
545 }
546 }
547
548 return monitor->datavalid;
549 }
550
sisfb_handle_ddc(struct sis_video_info * ivideo,struct sisfb_monitor * monitor,int crtno)551 static void sisfb_handle_ddc(struct sis_video_info *ivideo,
552 struct sisfb_monitor *monitor, int crtno)
553 {
554 unsigned short temp, i, realcrtno = crtno;
555 unsigned char buffer[256];
556
557 monitor->datavalid = false;
558
559 if(crtno) {
560 if(ivideo->vbflags & CRT2_LCD) realcrtno = 1;
561 else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
562 else return;
563 }
564
565 if((ivideo->sisfb_crt1off) && (!crtno))
566 return;
567
568 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
569 realcrtno, 0, &buffer[0], ivideo->vbflags2);
570 if((!temp) || (temp == 0xffff)) {
571 printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
572 return;
573 } else {
574 printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1);
575 printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n",
576 crtno + 1,
577 (temp & 0x1a) ? "" : "[none of the supported]",
578 (temp & 0x02) ? "2 " : "",
579 (temp & 0x08) ? "D&P" : "",
580 (temp & 0x10) ? "FPDI-2" : "");
581 if(temp & 0x02) {
582 i = 3; /* Number of retrys */
583 do {
584 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
585 realcrtno, 1, &buffer[0], ivideo->vbflags2);
586 } while((temp) && i--);
587 if(!temp) {
588 if(sisfb_interpret_edid(monitor, &buffer[0])) {
589 printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
590 monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax,
591 monitor->dclockmax / 1000);
592 } else {
593 printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1);
594 }
595 } else {
596 printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1);
597 }
598 } else {
599 printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n");
600 }
601 }
602 }
603
604 /* -------------- Mode validation --------------- */
605
606 static bool
sisfb_verify_rate(struct sis_video_info * ivideo,struct sisfb_monitor * monitor,int mode_idx,int rate_idx,int rate)607 sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
608 int mode_idx, int rate_idx, int rate)
609 {
610 int htotal, vtotal;
611 unsigned int dclock, hsync;
612
613 if(!monitor->datavalid)
614 return true;
615
616 if(mode_idx < 0)
617 return false;
618
619 /* Skip for 320x200, 320x240, 640x400 */
620 switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
621 case 0x59:
622 case 0x41:
623 case 0x4f:
624 case 0x50:
625 case 0x56:
626 case 0x53:
627 case 0x2f:
628 case 0x5d:
629 case 0x5e:
630 return true;
631 #ifdef CONFIG_FB_SIS_315
632 case 0x5a:
633 case 0x5b:
634 if(ivideo->sisvga_engine == SIS_315_VGA) return true;
635 #endif
636 }
637
638 if(rate < (monitor->vmin - 1))
639 return false;
640 if(rate > (monitor->vmax + 1))
641 return false;
642
643 if(sisfb_gettotalfrommode(&ivideo->SiS_Pr,
644 sisbios_mode[mode_idx].mode_no[ivideo->mni],
645 &htotal, &vtotal, rate_idx)) {
646 dclock = (htotal * vtotal * rate) / 1000;
647 if(dclock > (monitor->dclockmax + 1000))
648 return false;
649 hsync = dclock / htotal;
650 if(hsync < (monitor->hmin - 1))
651 return false;
652 if(hsync > (monitor->hmax + 1))
653 return false;
654 } else {
655 return false;
656 }
657 return true;
658 }
659
660 static int
sisfb_validate_mode(struct sis_video_info * ivideo,int myindex,u32 vbflags)661 sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
662 {
663 u16 xres=0, yres, myres;
664
665 #ifdef CONFIG_FB_SIS_300
666 if(ivideo->sisvga_engine == SIS_300_VGA) {
667 if(!(sisbios_mode[myindex].chipset & MD_SIS300))
668 return -1 ;
669 }
670 #endif
671 #ifdef CONFIG_FB_SIS_315
672 if(ivideo->sisvga_engine == SIS_315_VGA) {
673 if(!(sisbios_mode[myindex].chipset & MD_SIS315))
674 return -1;
675 }
676 #endif
677
678 myres = sisbios_mode[myindex].yres;
679
680 switch(vbflags & VB_DISPTYPE_DISP2) {
681
682 case CRT2_LCD:
683 xres = ivideo->lcdxres; yres = ivideo->lcdyres;
684
685 if((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) &&
686 (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) {
687 if(sisbios_mode[myindex].xres > xres)
688 return -1;
689 if(myres > yres)
690 return -1;
691 }
692
693 if(ivideo->sisfb_fstn) {
694 if(sisbios_mode[myindex].xres == 320) {
695 if(myres == 240) {
696 switch(sisbios_mode[myindex].mode_no[1]) {
697 case 0x50: myindex = MODE_FSTN_8; break;
698 case 0x56: myindex = MODE_FSTN_16; break;
699 case 0x53: return -1;
700 }
701 }
702 }
703 }
704
705 if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
706 sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
707 ivideo->SiS_Pr.SiS_CustomT, xres, yres, ivideo->vbflags2) < 0x14) {
708 return -1;
709 }
710 break;
711
712 case CRT2_TV:
713 if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
714 sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
715 return -1;
716 }
717 break;
718
719 case CRT2_VGA:
720 if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
721 sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
722 return -1;
723 }
724 break;
725 }
726
727 return myindex;
728 }
729
730 static u8
sisfb_search_refresh_rate(struct sis_video_info * ivideo,unsigned int rate,int mode_idx)731 sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx)
732 {
733 int i = 0;
734 u16 xres = sisbios_mode[mode_idx].xres;
735 u16 yres = sisbios_mode[mode_idx].yres;
736
737 ivideo->rate_idx = 0;
738 while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
739 if((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {
740 if(sisfb_vrate[i].refresh == rate) {
741 ivideo->rate_idx = sisfb_vrate[i].idx;
742 break;
743 } else if(sisfb_vrate[i].refresh > rate) {
744 if((sisfb_vrate[i].refresh - rate) <= 3) {
745 DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
746 rate, sisfb_vrate[i].refresh);
747 ivideo->rate_idx = sisfb_vrate[i].idx;
748 ivideo->refresh_rate = sisfb_vrate[i].refresh;
749 } else if((sisfb_vrate[i].idx != 1) &&
750 ((rate - sisfb_vrate[i-1].refresh) <= 2)) {
751 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
752 rate, sisfb_vrate[i-1].refresh);
753 ivideo->rate_idx = sisfb_vrate[i-1].idx;
754 ivideo->refresh_rate = sisfb_vrate[i-1].refresh;
755 }
756 break;
757 } else if((rate - sisfb_vrate[i].refresh) <= 2) {
758 DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
759 rate, sisfb_vrate[i].refresh);
760 ivideo->rate_idx = sisfb_vrate[i].idx;
761 break;
762 }
763 }
764 i++;
765 }
766 if(ivideo->rate_idx > 0) {
767 return ivideo->rate_idx;
768 } else {
769 printk(KERN_INFO "sisfb: Unsupported rate %d for %dx%d\n",
770 rate, xres, yres);
771 return 0;
772 }
773 }
774
775 static bool
sisfb_bridgeisslave(struct sis_video_info * ivideo)776 sisfb_bridgeisslave(struct sis_video_info *ivideo)
777 {
778 unsigned char P1_00;
779
780 if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE))
781 return false;
782
783 P1_00 = SiS_GetReg(SISPART1, 0x00);
784 if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
785 ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
786 return true;
787 } else {
788 return false;
789 }
790 }
791
792 static bool
sisfballowretracecrt1(struct sis_video_info * ivideo)793 sisfballowretracecrt1(struct sis_video_info *ivideo)
794 {
795 u8 temp;
796
797 temp = SiS_GetReg(SISCR, 0x17);
798 if(!(temp & 0x80))
799 return false;
800
801 temp = SiS_GetReg(SISSR, 0x1f);
802 if(temp & 0xc0)
803 return false;
804
805 return true;
806 }
807
808 static bool
sisfbcheckvretracecrt1(struct sis_video_info * ivideo)809 sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
810 {
811 if(!sisfballowretracecrt1(ivideo))
812 return false;
813
814 if (SiS_GetRegByte(SISINPSTAT) & 0x08)
815 return true;
816 else
817 return false;
818 }
819
820 static void
sisfbwaitretracecrt1(struct sis_video_info * ivideo)821 sisfbwaitretracecrt1(struct sis_video_info *ivideo)
822 {
823 int watchdog;
824
825 if(!sisfballowretracecrt1(ivideo))
826 return;
827
828 watchdog = 65536;
829 while ((!(SiS_GetRegByte(SISINPSTAT) & 0x08)) && --watchdog);
830 watchdog = 65536;
831 while ((SiS_GetRegByte(SISINPSTAT) & 0x08) && --watchdog);
832 }
833
834 static bool
sisfbcheckvretracecrt2(struct sis_video_info * ivideo)835 sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
836 {
837 unsigned char temp, reg;
838
839 switch(ivideo->sisvga_engine) {
840 case SIS_300_VGA: reg = 0x25; break;
841 case SIS_315_VGA: reg = 0x30; break;
842 default: return false;
843 }
844
845 temp = SiS_GetReg(SISPART1, reg);
846 if(temp & 0x02)
847 return true;
848 else
849 return false;
850 }
851
852 static bool
sisfb_CheckVBRetrace(struct sis_video_info * ivideo)853 sisfb_CheckVBRetrace(struct sis_video_info *ivideo)
854 {
855 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
856 if(!sisfb_bridgeisslave(ivideo)) {
857 return sisfbcheckvretracecrt2(ivideo);
858 }
859 }
860 return sisfbcheckvretracecrt1(ivideo);
861 }
862
863 static u32
sisfb_setupvbblankflags(struct sis_video_info * ivideo,u32 * vcount,u32 * hcount)864 sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
865 {
866 u8 idx, reg1, reg2, reg3, reg4;
867 u32 ret = 0;
868
869 (*vcount) = (*hcount) = 0;
870
871 if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
872
873 ret |= (FB_VBLANK_HAVE_VSYNC |
874 FB_VBLANK_HAVE_HBLANK |
875 FB_VBLANK_HAVE_VBLANK |
876 FB_VBLANK_HAVE_VCOUNT |
877 FB_VBLANK_HAVE_HCOUNT);
878 switch(ivideo->sisvga_engine) {
879 case SIS_300_VGA: idx = 0x25; break;
880 default:
881 case SIS_315_VGA: idx = 0x30; break;
882 }
883 reg1 = SiS_GetReg(SISPART1, (idx+0)); /* 30 */
884 reg2 = SiS_GetReg(SISPART1, (idx+1)); /* 31 */
885 reg3 = SiS_GetReg(SISPART1, (idx+2)); /* 32 */
886 reg4 = SiS_GetReg(SISPART1, (idx+3)); /* 33 */
887 if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
888 if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
889 if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
890 (*vcount) = reg3 | ((reg4 & 0x70) << 4);
891 (*hcount) = reg2 | ((reg4 & 0x0f) << 8);
892
893 } else if(sisfballowretracecrt1(ivideo)) {
894
895 ret |= (FB_VBLANK_HAVE_VSYNC |
896 FB_VBLANK_HAVE_VBLANK |
897 FB_VBLANK_HAVE_VCOUNT |
898 FB_VBLANK_HAVE_HCOUNT);
899 reg1 = SiS_GetRegByte(SISINPSTAT);
900 if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
901 if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
902 reg1 = SiS_GetReg(SISCR, 0x20);
903 reg1 = SiS_GetReg(SISCR, 0x1b);
904 reg2 = SiS_GetReg(SISCR, 0x1c);
905 reg3 = SiS_GetReg(SISCR, 0x1d);
906 (*vcount) = reg2 | ((reg3 & 0x07) << 8);
907 (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
908 }
909
910 return ret;
911 }
912
913 static int
sisfb_myblank(struct sis_video_info * ivideo,int blank)914 sisfb_myblank(struct sis_video_info *ivideo, int blank)
915 {
916 u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
917 bool backlight = true;
918
919 switch(blank) {
920 case FB_BLANK_UNBLANK: /* on */
921 sr01 = 0x00;
922 sr11 = 0x00;
923 sr1f = 0x00;
924 cr63 = 0x00;
925 p2_0 = 0x20;
926 p1_13 = 0x00;
927 backlight = true;
928 break;
929 case FB_BLANK_NORMAL: /* blank */
930 sr01 = 0x20;
931 sr11 = 0x00;
932 sr1f = 0x00;
933 cr63 = 0x00;
934 p2_0 = 0x20;
935 p1_13 = 0x00;
936 backlight = true;
937 break;
938 case FB_BLANK_VSYNC_SUSPEND: /* no vsync */
939 sr01 = 0x20;
940 sr11 = 0x08;
941 sr1f = 0x80;
942 cr63 = 0x40;
943 p2_0 = 0x40;
944 p1_13 = 0x80;
945 backlight = false;
946 break;
947 case FB_BLANK_HSYNC_SUSPEND: /* no hsync */
948 sr01 = 0x20;
949 sr11 = 0x08;
950 sr1f = 0x40;
951 cr63 = 0x40;
952 p2_0 = 0x80;
953 p1_13 = 0x40;
954 backlight = false;
955 break;
956 case FB_BLANK_POWERDOWN: /* off */
957 sr01 = 0x20;
958 sr11 = 0x08;
959 sr1f = 0xc0;
960 cr63 = 0x40;
961 p2_0 = 0xc0;
962 p1_13 = 0xc0;
963 backlight = false;
964 break;
965 default:
966 return 1;
967 }
968
969 if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
970
971 if( (!ivideo->sisfb_thismonitor.datavalid) ||
972 ((ivideo->sisfb_thismonitor.datavalid) &&
973 (ivideo->sisfb_thismonitor.feature & 0xe0))) {
974
975 if(ivideo->sisvga_engine == SIS_315_VGA) {
976 SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
977 }
978
979 if(!(sisfb_bridgeisslave(ivideo))) {
980 SiS_SetRegANDOR(SISSR, 0x01, ~0x20, sr01);
981 SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, sr1f);
982 }
983 }
984
985 }
986
987 if(ivideo->currentvbflags & CRT2_LCD) {
988
989 if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
990 if(backlight) {
991 SiS_SiS30xBLOn(&ivideo->SiS_Pr);
992 } else {
993 SiS_SiS30xBLOff(&ivideo->SiS_Pr);
994 }
995 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
996 #ifdef CONFIG_FB_SIS_315
997 if(ivideo->vbflags2 & VB2_CHRONTEL) {
998 if(backlight) {
999 SiS_Chrontel701xBLOn(&ivideo->SiS_Pr);
1000 } else {
1001 SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
1002 }
1003 }
1004 #endif
1005 }
1006
1007 if(((ivideo->sisvga_engine == SIS_300_VGA) &&
1008 (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) ||
1009 ((ivideo->sisvga_engine == SIS_315_VGA) &&
1010 ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) {
1011 SiS_SetRegANDOR(SISSR, 0x11, ~0x0c, sr11);
1012 }
1013
1014 if(ivideo->sisvga_engine == SIS_300_VGA) {
1015 if((ivideo->vbflags2 & VB2_30xB) &&
1016 (!(ivideo->vbflags2 & VB2_30xBDH))) {
1017 SiS_SetRegANDOR(SISPART1, 0x13, 0x3f, p1_13);
1018 }
1019 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
1020 if((ivideo->vbflags2 & VB2_30xB) &&
1021 (!(ivideo->vbflags2 & VB2_30xBDH))) {
1022 SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
1023 }
1024 }
1025
1026 } else if(ivideo->currentvbflags & CRT2_VGA) {
1027
1028 if(ivideo->vbflags2 & VB2_30xB) {
1029 SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
1030 }
1031
1032 }
1033
1034 return 0;
1035 }
1036
1037 /* ------------- Callbacks from init.c/init301.c -------------- */
1038
1039 #ifdef CONFIG_FB_SIS_300
1040 unsigned int
sisfb_read_nbridge_pci_dword(struct SiS_Private * SiS_Pr,int reg)1041 sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg)
1042 {
1043 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1044 u32 val = 0;
1045
1046 pci_read_config_dword(ivideo->nbridge, reg, &val);
1047 return (unsigned int)val;
1048 }
1049
1050 void
sisfb_write_nbridge_pci_dword(struct SiS_Private * SiS_Pr,int reg,unsigned int val)1051 sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val)
1052 {
1053 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1054
1055 pci_write_config_dword(ivideo->nbridge, reg, (u32)val);
1056 }
1057
1058 unsigned int
sisfb_read_lpc_pci_dword(struct SiS_Private * SiS_Pr,int reg)1059 sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg)
1060 {
1061 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1062 u32 val = 0;
1063
1064 if(!ivideo->lpcdev) return 0;
1065
1066 pci_read_config_dword(ivideo->lpcdev, reg, &val);
1067 return (unsigned int)val;
1068 }
1069 #endif
1070
1071 #ifdef CONFIG_FB_SIS_315
1072 void
sisfb_write_nbridge_pci_byte(struct SiS_Private * SiS_Pr,int reg,unsigned char val)1073 sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val)
1074 {
1075 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1076
1077 pci_write_config_byte(ivideo->nbridge, reg, (u8)val);
1078 }
1079
1080 unsigned int
sisfb_read_mio_pci_word(struct SiS_Private * SiS_Pr,int reg)1081 sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg)
1082 {
1083 struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
1084 u16 val = 0;
1085
1086 if(!ivideo->lpcdev) return 0;
1087
1088 pci_read_config_word(ivideo->lpcdev, reg, &val);
1089 return (unsigned int)val;
1090 }
1091 #endif
1092
1093 /* ----------- FBDev related routines for all series ----------- */
1094
1095 static int
sisfb_get_cmap_len(const struct fb_var_screeninfo * var)1096 sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
1097 {
1098 return (var->bits_per_pixel == 8) ? 256 : 16;
1099 }
1100
1101 static void
sisfb_set_vparms(struct sis_video_info * ivideo)1102 sisfb_set_vparms(struct sis_video_info *ivideo)
1103 {
1104 switch(ivideo->video_bpp) {
1105 case 8:
1106 ivideo->DstColor = 0x0000;
1107 ivideo->SiS310_AccelDepth = 0x00000000;
1108 ivideo->video_cmap_len = 256;
1109 break;
1110 case 16:
1111 ivideo->DstColor = 0x8000;
1112 ivideo->SiS310_AccelDepth = 0x00010000;
1113 ivideo->video_cmap_len = 16;
1114 break;
1115 case 32:
1116 ivideo->DstColor = 0xC000;
1117 ivideo->SiS310_AccelDepth = 0x00020000;
1118 ivideo->video_cmap_len = 16;
1119 break;
1120 default:
1121 ivideo->video_cmap_len = 16;
1122 printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp);
1123 ivideo->accel = 0;
1124 }
1125 }
1126
1127 static int
sisfb_calc_maxyres(struct sis_video_info * ivideo,struct fb_var_screeninfo * var)1128 sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1129 {
1130 int maxyres = ivideo->sisfb_mem / (var->xres_virtual * (var->bits_per_pixel >> 3));
1131
1132 if(maxyres > 32767) maxyres = 32767;
1133
1134 return maxyres;
1135 }
1136
1137 static void
sisfb_calc_pitch(struct sis_video_info * ivideo,struct fb_var_screeninfo * var)1138 sisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1139 {
1140 ivideo->video_linelength = var->xres_virtual * (var->bits_per_pixel >> 3);
1141 ivideo->scrnpitchCRT1 = ivideo->video_linelength;
1142 if(!(ivideo->currentvbflags & CRT1_LCDA)) {
1143 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1144 ivideo->scrnpitchCRT1 <<= 1;
1145 }
1146 }
1147 }
1148
1149 static void
sisfb_set_pitch(struct sis_video_info * ivideo)1150 sisfb_set_pitch(struct sis_video_info *ivideo)
1151 {
1152 bool isslavemode = false;
1153 unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3;
1154 unsigned short HDisplay2 = ivideo->video_linelength >> 3;
1155
1156 if(sisfb_bridgeisslave(ivideo)) isslavemode = true;
1157
1158 /* We need to set pitch for CRT1 if bridge is in slave mode, too */
1159 if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
1160 SiS_SetReg(SISCR, 0x13, (HDisplay1 & 0xFF));
1161 SiS_SetRegANDOR(SISSR, 0x0E, 0xF0, (HDisplay1 >> 8));
1162 }
1163
1164 /* We must not set the pitch for CRT2 if bridge is in slave mode */
1165 if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
1166 SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
1167 SiS_SetReg(SISPART1, 0x07, (HDisplay2 & 0xFF));
1168 SiS_SetRegANDOR(SISPART1, 0x09, 0xF0, (HDisplay2 >> 8));
1169 }
1170 }
1171
1172 static void
sisfb_bpp_to_var(struct sis_video_info * ivideo,struct fb_var_screeninfo * var)1173 sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
1174 {
1175 ivideo->video_cmap_len = sisfb_get_cmap_len(var);
1176
1177 switch(var->bits_per_pixel) {
1178 case 8:
1179 var->red.offset = var->green.offset = var->blue.offset = 0;
1180 var->red.length = var->green.length = var->blue.length = 8;
1181 break;
1182 case 16:
1183 var->red.offset = 11;
1184 var->red.length = 5;
1185 var->green.offset = 5;
1186 var->green.length = 6;
1187 var->blue.offset = 0;
1188 var->blue.length = 5;
1189 var->transp.offset = 0;
1190 var->transp.length = 0;
1191 break;
1192 case 32:
1193 var->red.offset = 16;
1194 var->red.length = 8;
1195 var->green.offset = 8;
1196 var->green.length = 8;
1197 var->blue.offset = 0;
1198 var->blue.length = 8;
1199 var->transp.offset = 24;
1200 var->transp.length = 8;
1201 break;
1202 }
1203 }
1204
1205 static int
sisfb_set_mode(struct sis_video_info * ivideo,int clrscrn)1206 sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
1207 {
1208 unsigned short modeno = ivideo->mode_no;
1209
1210 /* >=2.6.12's fbcon clears the screen anyway */
1211 modeno |= 0x80;
1212
1213 SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1214
1215 sisfb_pre_setmode(ivideo);
1216
1217 if(!SiSSetMode(&ivideo->SiS_Pr, modeno)) {
1218 printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
1219 return -EINVAL;
1220 }
1221
1222 SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1223
1224 sisfb_post_setmode(ivideo);
1225
1226 return 0;
1227 }
1228
1229
1230 static int
sisfb_do_set_var(struct fb_var_screeninfo * var,int isactive,struct fb_info * info)1231 sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info)
1232 {
1233 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1234 unsigned int htotal = 0, vtotal = 0;
1235 unsigned int drate = 0, hrate = 0;
1236 int found_mode = 0, ret;
1237 int old_mode;
1238 u32 pixclock;
1239
1240 htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
1241
1242 vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
1243
1244 pixclock = var->pixclock;
1245
1246 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1247 vtotal += var->yres;
1248 vtotal <<= 1;
1249 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1250 vtotal += var->yres;
1251 vtotal <<= 2;
1252 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1253 vtotal += var->yres;
1254 vtotal <<= 1;
1255 } else vtotal += var->yres;
1256
1257 if(!(htotal) || !(vtotal)) {
1258 DPRINTK("sisfb: Invalid 'var' information\n");
1259 return -EINVAL;
1260 }
1261
1262 if(pixclock && htotal && vtotal) {
1263 drate = 1000000000 / pixclock;
1264 hrate = (drate * 1000) / htotal;
1265 ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1266 } else {
1267 ivideo->refresh_rate = 60;
1268 }
1269
1270 old_mode = ivideo->sisfb_mode_idx;
1271 ivideo->sisfb_mode_idx = 0;
1272
1273 while( (sisbios_mode[ivideo->sisfb_mode_idx].mode_no[0] != 0) &&
1274 (sisbios_mode[ivideo->sisfb_mode_idx].xres <= var->xres) ) {
1275 if( (sisbios_mode[ivideo->sisfb_mode_idx].xres == var->xres) &&
1276 (sisbios_mode[ivideo->sisfb_mode_idx].yres == var->yres) &&
1277 (sisbios_mode[ivideo->sisfb_mode_idx].bpp == var->bits_per_pixel)) {
1278 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
1279 found_mode = 1;
1280 break;
1281 }
1282 ivideo->sisfb_mode_idx++;
1283 }
1284
1285 if(found_mode) {
1286 ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
1287 ivideo->sisfb_mode_idx, ivideo->currentvbflags);
1288 } else {
1289 ivideo->sisfb_mode_idx = -1;
1290 }
1291
1292 if(ivideo->sisfb_mode_idx < 0) {
1293 printk(KERN_ERR "sisfb: Mode %dx%dx%d not supported\n", var->xres,
1294 var->yres, var->bits_per_pixel);
1295 ivideo->sisfb_mode_idx = old_mode;
1296 return -EINVAL;
1297 }
1298
1299 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
1300
1301 if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) {
1302 ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
1303 ivideo->refresh_rate = 60;
1304 }
1305
1306 if(isactive) {
1307 /* If acceleration to be used? Need to know
1308 * before pre/post_set_mode()
1309 */
1310 ivideo->accel = 0;
1311 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
1312 #ifdef STUPID_ACCELF_TEXT_SHIT
1313 if(var->accel_flags & FB_ACCELF_TEXT) {
1314 info->flags &= ~FBINFO_HWACCEL_DISABLED;
1315 } else {
1316 info->flags |= FBINFO_HWACCEL_DISABLED;
1317 }
1318 #endif
1319 if(!(info->flags & FBINFO_HWACCEL_DISABLED)) ivideo->accel = -1;
1320 #else
1321 if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1;
1322 #endif
1323
1324 if((ret = sisfb_set_mode(ivideo, 1))) {
1325 return ret;
1326 }
1327
1328 ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
1329 ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
1330 ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
1331
1332 sisfb_calc_pitch(ivideo, var);
1333 sisfb_set_pitch(ivideo);
1334
1335 sisfb_set_vparms(ivideo);
1336
1337 ivideo->current_width = ivideo->video_width;
1338 ivideo->current_height = ivideo->video_height;
1339 ivideo->current_bpp = ivideo->video_bpp;
1340 ivideo->current_htotal = htotal;
1341 ivideo->current_vtotal = vtotal;
1342 ivideo->current_linelength = ivideo->video_linelength;
1343 ivideo->current_pixclock = var->pixclock;
1344 ivideo->current_refresh_rate = ivideo->refresh_rate;
1345 ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
1346 }
1347
1348 return 0;
1349 }
1350
1351 static void
sisfb_set_base_CRT1(struct sis_video_info * ivideo,unsigned int base)1352 sisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base)
1353 {
1354 SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
1355
1356 SiS_SetReg(SISCR, 0x0D, base & 0xFF);
1357 SiS_SetReg(SISCR, 0x0C, (base >> 8) & 0xFF);
1358 SiS_SetReg(SISSR, 0x0D, (base >> 16) & 0xFF);
1359 if(ivideo->sisvga_engine == SIS_315_VGA) {
1360 SiS_SetRegANDOR(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
1361 }
1362 }
1363
1364 static void
sisfb_set_base_CRT2(struct sis_video_info * ivideo,unsigned int base)1365 sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
1366 {
1367 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1368 SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
1369 SiS_SetReg(SISPART1, 0x06, (base & 0xFF));
1370 SiS_SetReg(SISPART1, 0x05, ((base >> 8) & 0xFF));
1371 SiS_SetReg(SISPART1, 0x04, ((base >> 16) & 0xFF));
1372 if(ivideo->sisvga_engine == SIS_315_VGA) {
1373 SiS_SetRegANDOR(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
1374 }
1375 }
1376 }
1377
1378 static int
sisfb_pan_var(struct sis_video_info * ivideo,struct fb_info * info,struct fb_var_screeninfo * var)1379 sisfb_pan_var(struct sis_video_info *ivideo, struct fb_info *info,
1380 struct fb_var_screeninfo *var)
1381 {
1382 ivideo->current_base = var->yoffset * info->var.xres_virtual
1383 + var->xoffset;
1384
1385 /* calculate base bpp dep. */
1386 switch (info->var.bits_per_pixel) {
1387 case 32:
1388 break;
1389 case 16:
1390 ivideo->current_base >>= 1;
1391 break;
1392 case 8:
1393 default:
1394 ivideo->current_base >>= 2;
1395 break;
1396 }
1397
1398 ivideo->current_base += (ivideo->video_offset >> 2);
1399
1400 sisfb_set_base_CRT1(ivideo, ivideo->current_base);
1401 sisfb_set_base_CRT2(ivideo, ivideo->current_base);
1402
1403 return 0;
1404 }
1405
1406 static int
sisfb_open(struct fb_info * info,int user)1407 sisfb_open(struct fb_info *info, int user)
1408 {
1409 return 0;
1410 }
1411
1412 static int
sisfb_release(struct fb_info * info,int user)1413 sisfb_release(struct fb_info *info, int user)
1414 {
1415 return 0;
1416 }
1417
1418 static int
sisfb_setcolreg(unsigned regno,unsigned red,unsigned green,unsigned blue,unsigned transp,struct fb_info * info)1419 sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
1420 unsigned transp, struct fb_info *info)
1421 {
1422 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1423
1424 if(regno >= sisfb_get_cmap_len(&info->var))
1425 return 1;
1426
1427 switch(info->var.bits_per_pixel) {
1428 case 8:
1429 SiS_SetRegByte(SISDACA, regno);
1430 SiS_SetRegByte(SISDACD, (red >> 10));
1431 SiS_SetRegByte(SISDACD, (green >> 10));
1432 SiS_SetRegByte(SISDACD, (blue >> 10));
1433 if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
1434 SiS_SetRegByte(SISDAC2A, regno);
1435 SiS_SetRegByte(SISDAC2D, (red >> 8));
1436 SiS_SetRegByte(SISDAC2D, (green >> 8));
1437 SiS_SetRegByte(SISDAC2D, (blue >> 8));
1438 }
1439 break;
1440 case 16:
1441 if (regno >= 16)
1442 break;
1443
1444 ((u32 *)(info->pseudo_palette))[regno] =
1445 (red & 0xf800) |
1446 ((green & 0xfc00) >> 5) |
1447 ((blue & 0xf800) >> 11);
1448 break;
1449 case 32:
1450 if (regno >= 16)
1451 break;
1452
1453 red >>= 8;
1454 green >>= 8;
1455 blue >>= 8;
1456 ((u32 *)(info->pseudo_palette))[regno] =
1457 (red << 16) | (green << 8) | (blue);
1458 break;
1459 }
1460 return 0;
1461 }
1462
1463 static int
sisfb_set_par(struct fb_info * info)1464 sisfb_set_par(struct fb_info *info)
1465 {
1466 int err;
1467
1468 if((err = sisfb_do_set_var(&info->var, 1, info)))
1469 return err;
1470
1471 sisfb_get_fix(&info->fix, -1, info);
1472
1473 return 0;
1474 }
1475
1476 static int
sisfb_check_var(struct fb_var_screeninfo * var,struct fb_info * info)1477 sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1478 {
1479 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1480 unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
1481 unsigned int drate = 0, hrate = 0, maxyres;
1482 int found_mode = 0;
1483 int refresh_rate, search_idx, tidx;
1484 bool recalc_clock = false;
1485 u32 pixclock;
1486
1487 htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
1488
1489 vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
1490
1491 pixclock = var->pixclock;
1492
1493 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1494 vtotal += var->yres;
1495 vtotal <<= 1;
1496 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1497 vtotal += var->yres;
1498 vtotal <<= 2;
1499 } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1500 vtotal += var->yres;
1501 vtotal <<= 1;
1502 } else
1503 vtotal += var->yres;
1504
1505 if(!(htotal) || !(vtotal)) {
1506 SISFAIL("sisfb: no valid timing data");
1507 }
1508
1509 search_idx = 0;
1510 while( (sisbios_mode[search_idx].mode_no[0] != 0) &&
1511 (sisbios_mode[search_idx].xres <= var->xres) ) {
1512 if( (sisbios_mode[search_idx].xres == var->xres) &&
1513 (sisbios_mode[search_idx].yres == var->yres) &&
1514 (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1515 if((tidx = sisfb_validate_mode(ivideo, search_idx,
1516 ivideo->currentvbflags)) > 0) {
1517 found_mode = 1;
1518 search_idx = tidx;
1519 break;
1520 }
1521 }
1522 search_idx++;
1523 }
1524
1525 if(!found_mode) {
1526 search_idx = 0;
1527 while(sisbios_mode[search_idx].mode_no[0] != 0) {
1528 if( (var->xres <= sisbios_mode[search_idx].xres) &&
1529 (var->yres <= sisbios_mode[search_idx].yres) &&
1530 (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
1531 if((tidx = sisfb_validate_mode(ivideo,search_idx,
1532 ivideo->currentvbflags)) > 0) {
1533 found_mode = 1;
1534 search_idx = tidx;
1535 break;
1536 }
1537 }
1538 search_idx++;
1539 }
1540 if(found_mode) {
1541 printk(KERN_DEBUG
1542 "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
1543 var->xres, var->yres, var->bits_per_pixel,
1544 sisbios_mode[search_idx].xres,
1545 sisbios_mode[search_idx].yres,
1546 var->bits_per_pixel);
1547 var->xres = sisbios_mode[search_idx].xres;
1548 var->yres = sisbios_mode[search_idx].yres;
1549 } else {
1550 printk(KERN_ERR
1551 "sisfb: Failed to find supported mode near %dx%dx%d\n",
1552 var->xres, var->yres, var->bits_per_pixel);
1553 return -EINVAL;
1554 }
1555 }
1556
1557 if( ((ivideo->vbflags2 & VB2_LVDS) ||
1558 ((ivideo->vbflags2 & VB2_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
1559 (var->bits_per_pixel == 8) ) {
1560 /* Slave modes on LVDS and 301B-DH */
1561 refresh_rate = 60;
1562 recalc_clock = true;
1563 } else if( (ivideo->current_htotal == htotal) &&
1564 (ivideo->current_vtotal == vtotal) &&
1565 (ivideo->current_pixclock == pixclock) ) {
1566 /* x=x & y=y & c=c -> assume depth change */
1567 drate = 1000000000 / pixclock;
1568 hrate = (drate * 1000) / htotal;
1569 refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1570 } else if( ( (ivideo->current_htotal != htotal) ||
1571 (ivideo->current_vtotal != vtotal) ) &&
1572 (ivideo->current_pixclock == var->pixclock) ) {
1573 /* x!=x | y!=y & c=c -> invalid pixclock */
1574 if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
1575 refresh_rate =
1576 ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
1577 } else if(ivideo->sisfb_parm_rate != -1) {
1578 /* Sic, sisfb_parm_rate - want to know originally desired rate here */
1579 refresh_rate = ivideo->sisfb_parm_rate;
1580 } else {
1581 refresh_rate = 60;
1582 }
1583 recalc_clock = true;
1584 } else if((pixclock) && (htotal) && (vtotal)) {
1585 drate = 1000000000 / pixclock;
1586 hrate = (drate * 1000) / htotal;
1587 refresh_rate = (unsigned int) (hrate * 2 / vtotal);
1588 } else if(ivideo->current_refresh_rate) {
1589 refresh_rate = ivideo->current_refresh_rate;
1590 recalc_clock = true;
1591 } else {
1592 refresh_rate = 60;
1593 recalc_clock = true;
1594 }
1595
1596 myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);
1597
1598 /* Eventually recalculate timing and clock */
1599 if(recalc_clock) {
1600 if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
1601 var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
1602 sisbios_mode[search_idx].mode_no[ivideo->mni],
1603 myrateindex));
1604 sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr,
1605 sisbios_mode[search_idx].mode_no[ivideo->mni],
1606 myrateindex, var);
1607 if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1608 var->pixclock <<= 1;
1609 }
1610 }
1611
1612 if(ivideo->sisfb_thismonitor.datavalid) {
1613 if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
1614 myrateindex, refresh_rate)) {
1615 printk(KERN_INFO
1616 "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
1617 }
1618 }
1619
1620 /* Adapt RGB settings */
1621 sisfb_bpp_to_var(ivideo, var);
1622
1623 if(var->xres > var->xres_virtual)
1624 var->xres_virtual = var->xres;
1625
1626 if(ivideo->sisfb_ypan) {
1627 maxyres = sisfb_calc_maxyres(ivideo, var);
1628 if(ivideo->sisfb_max) {
1629 var->yres_virtual = maxyres;
1630 } else {
1631 if(var->yres_virtual > maxyres) {
1632 var->yres_virtual = maxyres;
1633 }
1634 }
1635 if(var->yres_virtual <= var->yres) {
1636 var->yres_virtual = var->yres;
1637 }
1638 } else {
1639 if(var->yres != var->yres_virtual) {
1640 var->yres_virtual = var->yres;
1641 }
1642 var->xoffset = 0;
1643 var->yoffset = 0;
1644 }
1645
1646 /* Truncate offsets to maximum if too high */
1647 if(var->xoffset > var->xres_virtual - var->xres) {
1648 var->xoffset = var->xres_virtual - var->xres - 1;
1649 }
1650
1651 if(var->yoffset > var->yres_virtual - var->yres) {
1652 var->yoffset = var->yres_virtual - var->yres - 1;
1653 }
1654
1655 /* Set everything else to 0 */
1656 var->red.msb_right =
1657 var->green.msb_right =
1658 var->blue.msb_right =
1659 var->transp.offset =
1660 var->transp.length =
1661 var->transp.msb_right = 0;
1662
1663 return 0;
1664 }
1665
1666 static int
sisfb_pan_display(struct fb_var_screeninfo * var,struct fb_info * info)1667 sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
1668 {
1669 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1670 int err;
1671
1672 if (var->vmode & FB_VMODE_YWRAP)
1673 return -EINVAL;
1674
1675 if (var->xoffset + info->var.xres > info->var.xres_virtual ||
1676 var->yoffset + info->var.yres > info->var.yres_virtual)
1677 return -EINVAL;
1678
1679 err = sisfb_pan_var(ivideo, info, var);
1680 if (err < 0)
1681 return err;
1682
1683 info->var.xoffset = var->xoffset;
1684 info->var.yoffset = var->yoffset;
1685
1686 return 0;
1687 }
1688
1689 static int
sisfb_blank(int blank,struct fb_info * info)1690 sisfb_blank(int blank, struct fb_info *info)
1691 {
1692 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1693
1694 return sisfb_myblank(ivideo, blank);
1695 }
1696
1697 /* ----------- FBDev related routines for all series ---------- */
1698
sisfb_ioctl(struct fb_info * info,unsigned int cmd,unsigned long arg)1699 static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
1700 unsigned long arg)
1701 {
1702 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1703 struct sis_memreq sismemreq;
1704 struct fb_vblank sisvbblank;
1705 u32 gpu32 = 0;
1706 #ifndef __user
1707 #define __user
1708 #endif
1709 u32 __user *argp = (u32 __user *)arg;
1710
1711 switch(cmd) {
1712 case FBIO_ALLOC:
1713 if(!capable(CAP_SYS_RAWIO))
1714 return -EPERM;
1715
1716 if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq)))
1717 return -EFAULT;
1718
1719 sis_malloc(&sismemreq);
1720
1721 if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) {
1722 sis_free((u32)sismemreq.offset);
1723 return -EFAULT;
1724 }
1725 break;
1726
1727 case FBIO_FREE:
1728 if(!capable(CAP_SYS_RAWIO))
1729 return -EPERM;
1730
1731 if(get_user(gpu32, argp))
1732 return -EFAULT;
1733
1734 sis_free(gpu32);
1735 break;
1736
1737 case FBIOGET_VBLANK:
1738
1739 memset(&sisvbblank, 0, sizeof(struct fb_vblank));
1740
1741 sisvbblank.count = 0;
1742 sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
1743
1744 if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank)))
1745 return -EFAULT;
1746
1747 break;
1748
1749 case SISFB_GET_INFO_SIZE:
1750 return put_user(sizeof(struct sisfb_info), argp);
1751
1752 case SISFB_GET_INFO_OLD:
1753 if(ivideo->warncount++ < 10)
1754 printk(KERN_INFO
1755 "sisfb: Deprecated ioctl call received - update your application!\n");
1756 /* fall through */
1757 case SISFB_GET_INFO: /* For communication with X driver */
1758 ivideo->sisfb_infoblock.sisfb_id = SISFB_ID;
1759 ivideo->sisfb_infoblock.sisfb_version = VER_MAJOR;
1760 ivideo->sisfb_infoblock.sisfb_revision = VER_MINOR;
1761 ivideo->sisfb_infoblock.sisfb_patchlevel = VER_LEVEL;
1762 ivideo->sisfb_infoblock.chip_id = ivideo->chip_id;
1763 ivideo->sisfb_infoblock.sisfb_pci_vendor = ivideo->chip_vendor;
1764 ivideo->sisfb_infoblock.memory = ivideo->video_size / 1024;
1765 ivideo->sisfb_infoblock.heapstart = ivideo->heapstart / 1024;
1766 if(ivideo->modechanged) {
1767 ivideo->sisfb_infoblock.fbvidmode = ivideo->mode_no;
1768 } else {
1769 ivideo->sisfb_infoblock.fbvidmode = ivideo->modeprechange;
1770 }
1771 ivideo->sisfb_infoblock.sisfb_caps = ivideo->caps;
1772 ivideo->sisfb_infoblock.sisfb_tqlen = ivideo->cmdQueueSize / 1024;
1773 ivideo->sisfb_infoblock.sisfb_pcibus = ivideo->pcibus;
1774 ivideo->sisfb_infoblock.sisfb_pcislot = ivideo->pcislot;
1775 ivideo->sisfb_infoblock.sisfb_pcifunc = ivideo->pcifunc;
1776 ivideo->sisfb_infoblock.sisfb_lcdpdc = ivideo->detectedpdc;
1777 ivideo->sisfb_infoblock.sisfb_lcdpdca = ivideo->detectedpdca;
1778 ivideo->sisfb_infoblock.sisfb_lcda = ivideo->detectedlcda;
1779 ivideo->sisfb_infoblock.sisfb_vbflags = ivideo->vbflags;
1780 ivideo->sisfb_infoblock.sisfb_currentvbflags = ivideo->currentvbflags;
1781 ivideo->sisfb_infoblock.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
1782 ivideo->sisfb_infoblock.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
1783 ivideo->sisfb_infoblock.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
1784 ivideo->sisfb_infoblock.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
1785 ivideo->sisfb_infoblock.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
1786 ivideo->sisfb_infoblock.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
1787 ivideo->sisfb_infoblock.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
1788 ivideo->sisfb_infoblock.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
1789 ivideo->sisfb_infoblock.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
1790 ivideo->sisfb_infoblock.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
1791 ivideo->sisfb_infoblock.sisfb_heapsize = ivideo->sisfb_heap_size / 1024;
1792 ivideo->sisfb_infoblock.sisfb_videooffset = ivideo->video_offset;
1793 ivideo->sisfb_infoblock.sisfb_curfstn = ivideo->curFSTN;
1794 ivideo->sisfb_infoblock.sisfb_curdstn = ivideo->curDSTN;
1795 ivideo->sisfb_infoblock.sisfb_vbflags2 = ivideo->vbflags2;
1796 ivideo->sisfb_infoblock.sisfb_can_post = ivideo->sisfb_can_post ? 1 : 0;
1797 ivideo->sisfb_infoblock.sisfb_card_posted = ivideo->sisfb_card_posted ? 1 : 0;
1798 ivideo->sisfb_infoblock.sisfb_was_boot_device = ivideo->sisfb_was_boot_device ? 1 : 0;
1799
1800 if(copy_to_user((void __user *)arg, &ivideo->sisfb_infoblock,
1801 sizeof(ivideo->sisfb_infoblock)))
1802 return -EFAULT;
1803
1804 break;
1805
1806 case SISFB_GET_VBRSTATUS_OLD:
1807 if(ivideo->warncount++ < 10)
1808 printk(KERN_INFO
1809 "sisfb: Deprecated ioctl call received - update your application!\n");
1810 /* fall through */
1811 case SISFB_GET_VBRSTATUS:
1812 if(sisfb_CheckVBRetrace(ivideo))
1813 return put_user((u32)1, argp);
1814 else
1815 return put_user((u32)0, argp);
1816
1817 case SISFB_GET_AUTOMAXIMIZE_OLD:
1818 if(ivideo->warncount++ < 10)
1819 printk(KERN_INFO
1820 "sisfb: Deprecated ioctl call received - update your application!\n");
1821 /* fall through */
1822 case SISFB_GET_AUTOMAXIMIZE:
1823 if(ivideo->sisfb_max)
1824 return put_user((u32)1, argp);
1825 else
1826 return put_user((u32)0, argp);
1827
1828 case SISFB_SET_AUTOMAXIMIZE_OLD:
1829 if(ivideo->warncount++ < 10)
1830 printk(KERN_INFO
1831 "sisfb: Deprecated ioctl call received - update your application!\n");
1832 /* fall through */
1833 case SISFB_SET_AUTOMAXIMIZE:
1834 if(get_user(gpu32, argp))
1835 return -EFAULT;
1836
1837 ivideo->sisfb_max = (gpu32) ? 1 : 0;
1838 break;
1839
1840 case SISFB_SET_TVPOSOFFSET:
1841 if(get_user(gpu32, argp))
1842 return -EFAULT;
1843
1844 sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);
1845 sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);
1846 break;
1847
1848 case SISFB_GET_TVPOSOFFSET:
1849 return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),
1850 argp);
1851
1852 case SISFB_COMMAND:
1853 if(copy_from_user(&ivideo->sisfb_command, (void __user *)arg,
1854 sizeof(struct sisfb_cmd)))
1855 return -EFAULT;
1856
1857 sisfb_handle_command(ivideo, &ivideo->sisfb_command);
1858
1859 if(copy_to_user((void __user *)arg, &ivideo->sisfb_command,
1860 sizeof(struct sisfb_cmd)))
1861 return -EFAULT;
1862
1863 break;
1864
1865 case SISFB_SET_LOCK:
1866 if(get_user(gpu32, argp))
1867 return -EFAULT;
1868
1869 ivideo->sisfblocked = (gpu32) ? 1 : 0;
1870 break;
1871
1872 default:
1873 #ifdef SIS_NEW_CONFIG_COMPAT
1874 return -ENOIOCTLCMD;
1875 #else
1876 return -EINVAL;
1877 #endif
1878 }
1879 return 0;
1880 }
1881
1882 static int
sisfb_get_fix(struct fb_fix_screeninfo * fix,int con,struct fb_info * info)1883 sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
1884 {
1885 struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
1886
1887 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1888
1889 strlcpy(fix->id, ivideo->myid, sizeof(fix->id));
1890
1891 mutex_lock(&info->mm_lock);
1892 fix->smem_start = ivideo->video_base + ivideo->video_offset;
1893 fix->smem_len = ivideo->sisfb_mem;
1894 mutex_unlock(&info->mm_lock);
1895 fix->type = FB_TYPE_PACKED_PIXELS;
1896 fix->type_aux = 0;
1897 fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
1898 fix->xpanstep = 1;
1899 fix->ypanstep = (ivideo->sisfb_ypan) ? 1 : 0;
1900 fix->ywrapstep = 0;
1901 fix->line_length = ivideo->video_linelength;
1902 fix->mmio_start = ivideo->mmio_base;
1903 fix->mmio_len = ivideo->mmio_size;
1904 if(ivideo->sisvga_engine == SIS_300_VGA) {
1905 fix->accel = FB_ACCEL_SIS_GLAMOUR;
1906 } else if((ivideo->chip == SIS_330) ||
1907 (ivideo->chip == SIS_760) ||
1908 (ivideo->chip == SIS_761)) {
1909 fix->accel = FB_ACCEL_SIS_XABRE;
1910 } else if(ivideo->chip == XGI_20) {
1911 fix->accel = FB_ACCEL_XGI_VOLARI_Z;
1912 } else if(ivideo->chip >= XGI_40) {
1913 fix->accel = FB_ACCEL_XGI_VOLARI_V;
1914 } else {
1915 fix->accel = FB_ACCEL_SIS_GLAMOUR_2;
1916 }
1917
1918 return 0;
1919 }
1920
1921 /* ---------------- fb_ops structures ----------------- */
1922
1923 static struct fb_ops sisfb_ops = {
1924 .owner = THIS_MODULE,
1925 .fb_open = sisfb_open,
1926 .fb_release = sisfb_release,
1927 .fb_check_var = sisfb_check_var,
1928 .fb_set_par = sisfb_set_par,
1929 .fb_setcolreg = sisfb_setcolreg,
1930 .fb_pan_display = sisfb_pan_display,
1931 .fb_blank = sisfb_blank,
1932 .fb_fillrect = fbcon_sis_fillrect,
1933 .fb_copyarea = fbcon_sis_copyarea,
1934 .fb_imageblit = cfb_imageblit,
1935 .fb_sync = fbcon_sis_sync,
1936 #ifdef SIS_NEW_CONFIG_COMPAT
1937 .fb_compat_ioctl= sisfb_ioctl,
1938 #endif
1939 .fb_ioctl = sisfb_ioctl
1940 };
1941
1942 /* ---------------- Chip generation dependent routines ---------------- */
1943
sisfb_get_northbridge(int basechipid)1944 static struct pci_dev *sisfb_get_northbridge(int basechipid)
1945 {
1946 struct pci_dev *pdev = NULL;
1947 int nbridgenum, nbridgeidx, i;
1948 static const unsigned short nbridgeids[] = {
1949 PCI_DEVICE_ID_SI_540, /* for SiS 540 VGA */
1950 PCI_DEVICE_ID_SI_630, /* for SiS 630/730 VGA */
1951 PCI_DEVICE_ID_SI_730,
1952 PCI_DEVICE_ID_SI_550, /* for SiS 550 VGA */
1953 PCI_DEVICE_ID_SI_650, /* for SiS 650/651/740 VGA */
1954 PCI_DEVICE_ID_SI_651,
1955 PCI_DEVICE_ID_SI_740,
1956 PCI_DEVICE_ID_SI_661, /* for SiS 661/741/660/760/761 VGA */
1957 PCI_DEVICE_ID_SI_741,
1958 PCI_DEVICE_ID_SI_660,
1959 PCI_DEVICE_ID_SI_760,
1960 PCI_DEVICE_ID_SI_761
1961 };
1962
1963 switch(basechipid) {
1964 #ifdef CONFIG_FB_SIS_300
1965 case SIS_540: nbridgeidx = 0; nbridgenum = 1; break;
1966 case SIS_630: nbridgeidx = 1; nbridgenum = 2; break;
1967 #endif
1968 #ifdef CONFIG_FB_SIS_315
1969 case SIS_550: nbridgeidx = 3; nbridgenum = 1; break;
1970 case SIS_650: nbridgeidx = 4; nbridgenum = 3; break;
1971 case SIS_660: nbridgeidx = 7; nbridgenum = 5; break;
1972 #endif
1973 default: return NULL;
1974 }
1975 for(i = 0; i < nbridgenum; i++) {
1976 if((pdev = pci_get_device(PCI_VENDOR_ID_SI,
1977 nbridgeids[nbridgeidx+i], NULL)))
1978 break;
1979 }
1980 return pdev;
1981 }
1982
sisfb_get_dram_size(struct sis_video_info * ivideo)1983 static int sisfb_get_dram_size(struct sis_video_info *ivideo)
1984 {
1985 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
1986 u8 reg;
1987 #endif
1988
1989 ivideo->video_size = 0;
1990 ivideo->UMAsize = ivideo->LFBsize = 0;
1991
1992 switch(ivideo->chip) {
1993 #ifdef CONFIG_FB_SIS_300
1994 case SIS_300:
1995 reg = SiS_GetReg(SISSR, 0x14);
1996 ivideo->video_size = ((reg & 0x3F) + 1) << 20;
1997 break;
1998 case SIS_540:
1999 case SIS_630:
2000 case SIS_730:
2001 if(!ivideo->nbridge)
2002 return -1;
2003 pci_read_config_byte(ivideo->nbridge, 0x63, ®);
2004 ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);
2005 break;
2006 #endif
2007 #ifdef CONFIG_FB_SIS_315
2008 case SIS_315H:
2009 case SIS_315PRO:
2010 case SIS_315:
2011 reg = SiS_GetReg(SISSR, 0x14);
2012 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2013 switch((reg >> 2) & 0x03) {
2014 case 0x01:
2015 case 0x03:
2016 ivideo->video_size <<= 1;
2017 break;
2018 case 0x02:
2019 ivideo->video_size += (ivideo->video_size/2);
2020 }
2021 break;
2022 case SIS_330:
2023 reg = SiS_GetReg(SISSR, 0x14);
2024 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2025 if(reg & 0x0c) ivideo->video_size <<= 1;
2026 break;
2027 case SIS_550:
2028 case SIS_650:
2029 case SIS_740:
2030 reg = SiS_GetReg(SISSR, 0x14);
2031 ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
2032 break;
2033 case SIS_661:
2034 case SIS_741:
2035 reg = SiS_GetReg(SISCR, 0x79);
2036 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2037 break;
2038 case SIS_660:
2039 case SIS_760:
2040 case SIS_761:
2041 reg = SiS_GetReg(SISCR, 0x79);
2042 reg = (reg & 0xf0) >> 4;
2043 if(reg) {
2044 ivideo->video_size = (1 << reg) << 20;
2045 ivideo->UMAsize = ivideo->video_size;
2046 }
2047 reg = SiS_GetReg(SISCR, 0x78);
2048 reg &= 0x30;
2049 if(reg) {
2050 if(reg == 0x10) {
2051 ivideo->LFBsize = (32 << 20);
2052 } else {
2053 ivideo->LFBsize = (64 << 20);
2054 }
2055 ivideo->video_size += ivideo->LFBsize;
2056 }
2057 break;
2058 case SIS_340:
2059 case XGI_20:
2060 case XGI_40:
2061 reg = SiS_GetReg(SISSR, 0x14);
2062 ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
2063 if(ivideo->chip != XGI_20) {
2064 reg = (reg & 0x0c) >> 2;
2065 if(ivideo->revision_id == 2) {
2066 if(reg & 0x01) reg = 0x02;
2067 else reg = 0x00;
2068 }
2069 if(reg == 0x02) ivideo->video_size <<= 1;
2070 else if(reg == 0x03) ivideo->video_size <<= 2;
2071 }
2072 break;
2073 #endif
2074 default:
2075 return -1;
2076 }
2077 return 0;
2078 }
2079
2080 /* -------------- video bridge device detection --------------- */
2081
sisfb_detect_VB_connect(struct sis_video_info * ivideo)2082 static void sisfb_detect_VB_connect(struct sis_video_info *ivideo)
2083 {
2084 u8 cr32, temp;
2085
2086 /* No CRT2 on XGI Z7 */
2087 if(ivideo->chip == XGI_20) {
2088 ivideo->sisfb_crt1off = 0;
2089 return;
2090 }
2091
2092 #ifdef CONFIG_FB_SIS_300
2093 if(ivideo->sisvga_engine == SIS_300_VGA) {
2094 temp = SiS_GetReg(SISSR, 0x17);
2095 if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
2096 /* PAL/NTSC is stored on SR16 on such machines */
2097 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
2098 temp = SiS_GetReg(SISSR, 0x16);
2099 if(temp & 0x20)
2100 ivideo->vbflags |= TV_PAL;
2101 else
2102 ivideo->vbflags |= TV_NTSC;
2103 }
2104 }
2105 }
2106 #endif
2107
2108 cr32 = SiS_GetReg(SISCR, 0x32);
2109
2110 if(cr32 & SIS_CRT1) {
2111 ivideo->sisfb_crt1off = 0;
2112 } else {
2113 ivideo->sisfb_crt1off = (cr32 & 0xDF) ? 1 : 0;
2114 }
2115
2116 ivideo->vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
2117
2118 if(cr32 & SIS_VB_TV) ivideo->vbflags |= CRT2_TV;
2119 if(cr32 & SIS_VB_LCD) ivideo->vbflags |= CRT2_LCD;
2120 if(cr32 & SIS_VB_CRT2) ivideo->vbflags |= CRT2_VGA;
2121
2122 /* Check given parms for hardware compatibility.
2123 * (Cannot do this in the search_xx routines since we don't
2124 * know what hardware we are running on then)
2125 */
2126
2127 if(ivideo->chip != SIS_550) {
2128 ivideo->sisfb_dstn = ivideo->sisfb_fstn = 0;
2129 }
2130
2131 if(ivideo->sisfb_tvplug != -1) {
2132 if( (ivideo->sisvga_engine != SIS_315_VGA) ||
2133 (!(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) ) {
2134 if(ivideo->sisfb_tvplug & TV_YPBPR) {
2135 ivideo->sisfb_tvplug = -1;
2136 printk(KERN_ERR "sisfb: YPbPr not supported\n");
2137 }
2138 }
2139 }
2140 if(ivideo->sisfb_tvplug != -1) {
2141 if( (ivideo->sisvga_engine != SIS_315_VGA) ||
2142 (!(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) ) {
2143 if(ivideo->sisfb_tvplug & TV_HIVISION) {
2144 ivideo->sisfb_tvplug = -1;
2145 printk(KERN_ERR "sisfb: HiVision not supported\n");
2146 }
2147 }
2148 }
2149 if(ivideo->sisfb_tvstd != -1) {
2150 if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) &&
2151 (!((ivideo->sisvga_engine == SIS_315_VGA) &&
2152 (ivideo->vbflags2 & VB2_CHRONTEL))) ) {
2153 if(ivideo->sisfb_tvstd & (TV_PALM | TV_PALN | TV_NTSCJ)) {
2154 ivideo->sisfb_tvstd = -1;
2155 printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
2156 }
2157 }
2158 }
2159
2160 /* Detect/set TV plug & type */
2161 if(ivideo->sisfb_tvplug != -1) {
2162 ivideo->vbflags |= ivideo->sisfb_tvplug;
2163 } else {
2164 if(cr32 & SIS_VB_YPBPR) ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */
2165 else if(cr32 & SIS_VB_HIVISION) ivideo->vbflags |= TV_HIVISION;
2166 else if(cr32 & SIS_VB_SCART) ivideo->vbflags |= TV_SCART;
2167 else {
2168 if(cr32 & SIS_VB_SVIDEO) ivideo->vbflags |= TV_SVIDEO;
2169 if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO;
2170 }
2171 }
2172
2173 if(!(ivideo->vbflags & (TV_YPBPR | TV_HIVISION))) {
2174 if(ivideo->sisfb_tvstd != -1) {
2175 ivideo->vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ);
2176 ivideo->vbflags |= ivideo->sisfb_tvstd;
2177 }
2178 if(ivideo->vbflags & TV_SCART) {
2179 ivideo->vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ);
2180 ivideo->vbflags |= TV_PAL;
2181 }
2182 if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
2183 if(ivideo->sisvga_engine == SIS_300_VGA) {
2184 temp = SiS_GetReg(SISSR, 0x38);
2185 if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2186 else ivideo->vbflags |= TV_NTSC;
2187 } else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
2188 temp = SiS_GetReg(SISSR, 0x38);
2189 if(temp & 0x01) ivideo->vbflags |= TV_PAL;
2190 else ivideo->vbflags |= TV_NTSC;
2191 } else {
2192 temp = SiS_GetReg(SISCR, 0x79);
2193 if(temp & 0x20) ivideo->vbflags |= TV_PAL;
2194 else ivideo->vbflags |= TV_NTSC;
2195 }
2196 }
2197 }
2198
2199 /* Copy forceCRT1 option to CRT1off if option is given */
2200 if(ivideo->sisfb_forcecrt1 != -1) {
2201 ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
2202 }
2203 }
2204
2205 /* ------------------ Sensing routines ------------------ */
2206
sisfb_test_DDC1(struct sis_video_info * ivideo)2207 static bool sisfb_test_DDC1(struct sis_video_info *ivideo)
2208 {
2209 unsigned short old;
2210 int count = 48;
2211
2212 old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr);
2213 do {
2214 if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
2215 } while(count--);
2216 return (count != -1);
2217 }
2218
sisfb_sense_crt1(struct sis_video_info * ivideo)2219 static void sisfb_sense_crt1(struct sis_video_info *ivideo)
2220 {
2221 bool mustwait = false;
2222 u8 sr1F, cr17;
2223 #ifdef CONFIG_FB_SIS_315
2224 u8 cr63=0;
2225 #endif
2226 u16 temp = 0xffff;
2227 int i;
2228
2229 sr1F = SiS_GetReg(SISSR, 0x1F);
2230 SiS_SetRegOR(SISSR, 0x1F, 0x04);
2231 SiS_SetRegAND(SISSR, 0x1F, 0x3F);
2232 if(sr1F & 0xc0) mustwait = true;
2233
2234 #ifdef CONFIG_FB_SIS_315
2235 if(ivideo->sisvga_engine == SIS_315_VGA) {
2236 cr63 = SiS_GetReg(SISCR, ivideo->SiS_Pr.SiS_MyCR63);
2237 cr63 &= 0x40;
2238 SiS_SetRegAND(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF);
2239 }
2240 #endif
2241
2242 cr17 = SiS_GetReg(SISCR, 0x17);
2243 cr17 &= 0x80;
2244 if(!cr17) {
2245 SiS_SetRegOR(SISCR, 0x17, 0x80);
2246 mustwait = true;
2247 SiS_SetReg(SISSR, 0x00, 0x01);
2248 SiS_SetReg(SISSR, 0x00, 0x03);
2249 }
2250
2251 if(mustwait) {
2252 for(i=0; i < 10; i++) sisfbwaitretracecrt1(ivideo);
2253 }
2254
2255 #ifdef CONFIG_FB_SIS_315
2256 if(ivideo->chip >= SIS_330) {
2257 SiS_SetRegAND(SISCR, 0x32, ~0x20);
2258 if(ivideo->chip >= SIS_340) {
2259 SiS_SetReg(SISCR, 0x57, 0x4a);
2260 } else {
2261 SiS_SetReg(SISCR, 0x57, 0x5f);
2262 }
2263 SiS_SetRegOR(SISCR, 0x53, 0x02);
2264 while ((SiS_GetRegByte(SISINPSTAT)) & 0x01) break;
2265 while (!((SiS_GetRegByte(SISINPSTAT)) & 0x01)) break;
2266 if ((SiS_GetRegByte(SISMISCW)) & 0x10) temp = 1;
2267 SiS_SetRegAND(SISCR, 0x53, 0xfd);
2268 SiS_SetRegAND(SISCR, 0x57, 0x00);
2269 }
2270 #endif
2271
2272 if(temp == 0xffff) {
2273 i = 3;
2274 do {
2275 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
2276 ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2);
2277 } while(((temp == 0) || (temp == 0xffff)) && i--);
2278
2279 if((temp == 0) || (temp == 0xffff)) {
2280 if(sisfb_test_DDC1(ivideo)) temp = 1;
2281 }
2282 }
2283
2284 if((temp) && (temp != 0xffff)) {
2285 SiS_SetRegOR(SISCR, 0x32, 0x20);
2286 }
2287
2288 #ifdef CONFIG_FB_SIS_315
2289 if(ivideo->sisvga_engine == SIS_315_VGA) {
2290 SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF, cr63);
2291 }
2292 #endif
2293
2294 SiS_SetRegANDOR(SISCR, 0x17, 0x7F, cr17);
2295
2296 SiS_SetReg(SISSR, 0x1F, sr1F);
2297 }
2298
2299 /* Determine and detect attached devices on SiS30x */
SiS_SenseLCD(struct sis_video_info * ivideo)2300 static void SiS_SenseLCD(struct sis_video_info *ivideo)
2301 {
2302 unsigned char buffer[256];
2303 unsigned short temp, realcrtno, i;
2304 u8 reg, cr37 = 0, paneltype = 0;
2305 u16 xres, yres;
2306
2307 ivideo->SiS_Pr.PanelSelfDetected = false;
2308
2309 /* LCD detection only for TMDS bridges */
2310 if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
2311 return;
2312 if(ivideo->vbflags2 & VB2_30xBDH)
2313 return;
2314
2315 /* If LCD already set up by BIOS, skip it */
2316 reg = SiS_GetReg(SISCR, 0x32);
2317 if(reg & 0x08)
2318 return;
2319
2320 realcrtno = 1;
2321 if(ivideo->SiS_Pr.DDCPortMixup)
2322 realcrtno = 0;
2323
2324 /* Check DDC capabilities */
2325 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
2326 realcrtno, 0, &buffer[0], ivideo->vbflags2);
2327
2328 if((!temp) || (temp == 0xffff) || (!(temp & 0x02)))
2329 return;
2330
2331 /* Read DDC data */
2332 i = 3; /* Number of retrys */
2333 do {
2334 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
2335 ivideo->sisvga_engine, realcrtno, 1,
2336 &buffer[0], ivideo->vbflags2);
2337 } while((temp) && i--);
2338
2339 if(temp)
2340 return;
2341
2342 /* No digital device */
2343 if(!(buffer[0x14] & 0x80))
2344 return;
2345
2346 /* First detailed timing preferred timing? */
2347 if(!(buffer[0x18] & 0x02))
2348 return;
2349
2350 xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
2351 yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
2352
2353 switch(xres) {
2354 case 1024:
2355 if(yres == 768)
2356 paneltype = 0x02;
2357 break;
2358 case 1280:
2359 if(yres == 1024)
2360 paneltype = 0x03;
2361 break;
2362 case 1600:
2363 if((yres == 1200) && (ivideo->vbflags2 & VB2_30xC))
2364 paneltype = 0x0b;
2365 break;
2366 }
2367
2368 if(!paneltype)
2369 return;
2370
2371 if(buffer[0x23])
2372 cr37 |= 0x10;
2373
2374 if((buffer[0x47] & 0x18) == 0x18)
2375 cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
2376 else
2377 cr37 |= 0xc0;
2378
2379 SiS_SetReg(SISCR, 0x36, paneltype);
2380 cr37 &= 0xf1;
2381 SiS_SetRegANDOR(SISCR, 0x37, 0x0c, cr37);
2382 SiS_SetRegOR(SISCR, 0x32, 0x08);
2383
2384 ivideo->SiS_Pr.PanelSelfDetected = true;
2385 }
2386
SISDoSense(struct sis_video_info * ivideo,u16 type,u16 test)2387 static int SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
2388 {
2389 int temp, mytest, result, i, j;
2390
2391 for(j = 0; j < 10; j++) {
2392 result = 0;
2393 for(i = 0; i < 3; i++) {
2394 mytest = test;
2395 SiS_SetReg(SISPART4, 0x11, (type & 0x00ff));
2396 temp = (type >> 8) | (mytest & 0x00ff);
2397 SiS_SetRegANDOR(SISPART4, 0x10, 0xe0, temp);
2398 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
2399 mytest >>= 8;
2400 mytest &= 0x7f;
2401 temp = SiS_GetReg(SISPART4, 0x03);
2402 temp ^= 0x0e;
2403 temp &= mytest;
2404 if(temp == mytest) result++;
2405 #if 1
2406 SiS_SetReg(SISPART4, 0x11, 0x00);
2407 SiS_SetRegAND(SISPART4, 0x10, 0xe0);
2408 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
2409 #endif
2410 }
2411 if((result == 0) || (result >= 2)) break;
2412 }
2413 return result;
2414 }
2415
SiS_Sense30x(struct sis_video_info * ivideo)2416 static void SiS_Sense30x(struct sis_video_info *ivideo)
2417 {
2418 u8 backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
2419 u16 svhs=0, svhs_c=0;
2420 u16 cvbs=0, cvbs_c=0;
2421 u16 vga2=0, vga2_c=0;
2422 int myflag, result;
2423 char stdstr[] = "sisfb: Detected";
2424 char tvstr[] = "TV connected to";
2425
2426 if(ivideo->vbflags2 & VB2_301) {
2427 svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
2428 myflag = SiS_GetReg(SISPART4, 0x01);
2429 if(myflag & 0x04) {
2430 svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
2431 }
2432 } else if(ivideo->vbflags2 & (VB2_301B | VB2_302B)) {
2433 svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
2434 } else if(ivideo->vbflags2 & (VB2_301LV | VB2_302LV)) {
2435 svhs = 0x0200; cvbs = 0x0100;
2436 } else if(ivideo->vbflags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) {
2437 svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
2438 } else
2439 return;
2440
2441 vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
2442 if(ivideo->vbflags & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) {
2443 svhs_c = 0x0408; cvbs_c = 0x0808;
2444 }
2445
2446 biosflag = 2;
2447 if(ivideo->haveXGIROM) {
2448 biosflag = ivideo->bios_abase[0x58] & 0x03;
2449 } else if(ivideo->newrom) {
2450 if(ivideo->bios_abase[0x5d] & 0x04) biosflag |= 0x01;
2451 } else if(ivideo->sisvga_engine == SIS_300_VGA) {
2452 if(ivideo->bios_abase) {
2453 biosflag = ivideo->bios_abase[0xfe] & 0x03;
2454 }
2455 }
2456
2457 if(ivideo->chip == SIS_300) {
2458 myflag = SiS_GetReg(SISSR, 0x3b);
2459 if(!(myflag & 0x01)) vga2 = vga2_c = 0;
2460 }
2461
2462 if(!(ivideo->vbflags2 & VB2_SISVGA2BRIDGE)) {
2463 vga2 = vga2_c = 0;
2464 }
2465
2466 backupSR_1e = SiS_GetReg(SISSR, 0x1e);
2467 SiS_SetRegOR(SISSR, 0x1e, 0x20);
2468
2469 backupP4_0d = SiS_GetReg(SISPART4, 0x0d);
2470 if(ivideo->vbflags2 & VB2_30xC) {
2471 SiS_SetRegANDOR(SISPART4, 0x0d, ~0x07, 0x01);
2472 } else {
2473 SiS_SetRegOR(SISPART4, 0x0d, 0x04);
2474 }
2475 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2476
2477 backupP2_00 = SiS_GetReg(SISPART2, 0x00);
2478 SiS_SetReg(SISPART2, 0x00, ((backupP2_00 | 0x1c) & 0xfc));
2479
2480 backupP2_4d = SiS_GetReg(SISPART2, 0x4d);
2481 if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) {
2482 SiS_SetReg(SISPART2, 0x4d, (backupP2_4d & ~0x10));
2483 }
2484
2485 if(!(ivideo->vbflags2 & VB2_30xCLV)) {
2486 SISDoSense(ivideo, 0, 0);
2487 }
2488
2489 SiS_SetRegAND(SISCR, 0x32, ~0x14);
2490
2491 if(vga2_c || vga2) {
2492 if(SISDoSense(ivideo, vga2, vga2_c)) {
2493 if(biosflag & 0x01) {
2494 printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr);
2495 SiS_SetRegOR(SISCR, 0x32, 0x04);
2496 } else {
2497 printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
2498 SiS_SetRegOR(SISCR, 0x32, 0x10);
2499 }
2500 }
2501 }
2502
2503 SiS_SetRegAND(SISCR, 0x32, 0x3f);
2504
2505 if(ivideo->vbflags2 & VB2_30xCLV) {
2506 SiS_SetRegOR(SISPART4, 0x0d, 0x04);
2507 }
2508
2509 if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
2510 SiS_SetReg(SISPART2, 0x4d, (backupP2_4d | 0x10));
2511 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
2512 if((result = SISDoSense(ivideo, svhs, 0x0604))) {
2513 if((result = SISDoSense(ivideo, cvbs, 0x0804))) {
2514 printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr);
2515 SiS_SetRegOR(SISCR, 0x32, 0x80);
2516 }
2517 }
2518 SiS_SetReg(SISPART2, 0x4d, backupP2_4d);
2519 }
2520
2521 SiS_SetRegAND(SISCR, 0x32, ~0x03);
2522
2523 if(!(ivideo->vbflags & TV_YPBPR)) {
2524 if((result = SISDoSense(ivideo, svhs, svhs_c))) {
2525 printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
2526 SiS_SetRegOR(SISCR, 0x32, 0x02);
2527 }
2528 if((biosflag & 0x02) || (!result)) {
2529 if(SISDoSense(ivideo, cvbs, cvbs_c)) {
2530 printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
2531 SiS_SetRegOR(SISCR, 0x32, 0x01);
2532 }
2533 }
2534 }
2535
2536 SISDoSense(ivideo, 0, 0);
2537
2538 SiS_SetReg(SISPART2, 0x00, backupP2_00);
2539 SiS_SetReg(SISPART4, 0x0d, backupP4_0d);
2540 SiS_SetReg(SISSR, 0x1e, backupSR_1e);
2541
2542 if(ivideo->vbflags2 & VB2_30xCLV) {
2543 biosflag = SiS_GetReg(SISPART2, 0x00);
2544 if(biosflag & 0x20) {
2545 for(myflag = 2; myflag > 0; myflag--) {
2546 biosflag ^= 0x20;
2547 SiS_SetReg(SISPART2, 0x00, biosflag);
2548 }
2549 }
2550 }
2551
2552 SiS_SetReg(SISPART2, 0x00, backupP2_00);
2553 }
2554
2555 /* Determine and detect attached TV's on Chrontel */
SiS_SenseCh(struct sis_video_info * ivideo)2556 static void SiS_SenseCh(struct sis_video_info *ivideo)
2557 {
2558 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
2559 u8 temp1, temp2;
2560 char stdstr[] = "sisfb: Chrontel: Detected TV connected to";
2561 #endif
2562 #ifdef CONFIG_FB_SIS_300
2563 unsigned char test[3];
2564 int i;
2565 #endif
2566
2567 if(ivideo->chip < SIS_315H) {
2568
2569 #ifdef CONFIG_FB_SIS_300
2570 ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 1; /* Chrontel 700x */
2571 SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x9c); /* Set general purpose IO for Chrontel communication */
2572 SiS_DDC2Delay(&ivideo->SiS_Pr, 1000);
2573 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
2574 /* See Chrontel TB31 for explanation */
2575 temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
2576 if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
2577 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e, 0x0b);
2578 SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
2579 }
2580 temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
2581 if(temp2 != temp1) temp1 = temp2;
2582
2583 if((temp1 >= 0x22) && (temp1 <= 0x50)) {
2584 /* Read power status */
2585 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
2586 if((temp1 & 0x03) != 0x03) {
2587 /* Power all outputs */
2588 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e,0x0b);
2589 SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
2590 }
2591 /* Sense connected TV devices */
2592 for(i = 0; i < 3; i++) {
2593 SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x01);
2594 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2595 SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x00);
2596 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2597 temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10);
2598 if(!(temp1 & 0x08)) test[i] = 0x02;
2599 else if(!(temp1 & 0x02)) test[i] = 0x01;
2600 else test[i] = 0;
2601 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2602 }
2603
2604 if(test[0] == test[1]) temp1 = test[0];
2605 else if(test[0] == test[2]) temp1 = test[0];
2606 else if(test[1] == test[2]) temp1 = test[1];
2607 else {
2608 printk(KERN_INFO
2609 "sisfb: TV detection unreliable - test results varied\n");
2610 temp1 = test[2];
2611 }
2612 if(temp1 == 0x02) {
2613 printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2614 ivideo->vbflags |= TV_SVIDEO;
2615 SiS_SetRegOR(SISCR, 0x32, 0x02);
2616 SiS_SetRegAND(SISCR, 0x32, ~0x05);
2617 } else if (temp1 == 0x01) {
2618 printk(KERN_INFO "%s CVBS output\n", stdstr);
2619 ivideo->vbflags |= TV_AVIDEO;
2620 SiS_SetRegOR(SISCR, 0x32, 0x01);
2621 SiS_SetRegAND(SISCR, 0x32, ~0x06);
2622 } else {
2623 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2624 SiS_SetRegAND(SISCR, 0x32, ~0x07);
2625 }
2626 } else if(temp1 == 0) {
2627 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
2628 SiS_SetRegAND(SISCR, 0x32, ~0x07);
2629 }
2630 /* Set general purpose IO for Chrontel communication */
2631 SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00);
2632 #endif
2633
2634 } else {
2635
2636 #ifdef CONFIG_FB_SIS_315
2637 ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2; /* Chrontel 7019 */
2638 temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
2639 SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, 0x20);
2640 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2641 temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
2642 temp2 |= 0x01;
2643 SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
2644 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2645 temp2 ^= 0x01;
2646 SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
2647 SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
2648 temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
2649 SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, temp1);
2650 temp1 = 0;
2651 if(temp2 & 0x02) temp1 |= 0x01;
2652 if(temp2 & 0x10) temp1 |= 0x01;
2653 if(temp2 & 0x04) temp1 |= 0x02;
2654 if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04;
2655 switch(temp1) {
2656 case 0x01:
2657 printk(KERN_INFO "%s CVBS output\n", stdstr);
2658 ivideo->vbflags |= TV_AVIDEO;
2659 SiS_SetRegOR(SISCR, 0x32, 0x01);
2660 SiS_SetRegAND(SISCR, 0x32, ~0x06);
2661 break;
2662 case 0x02:
2663 printk(KERN_INFO "%s SVIDEO output\n", stdstr);
2664 ivideo->vbflags |= TV_SVIDEO;
2665 SiS_SetRegOR(SISCR, 0x32, 0x02);
2666 SiS_SetRegAND(SISCR, 0x32, ~0x05);
2667 break;
2668 case 0x04:
2669 printk(KERN_INFO "%s SCART output\n", stdstr);
2670 SiS_SetRegOR(SISCR, 0x32, 0x04);
2671 SiS_SetRegAND(SISCR, 0x32, ~0x03);
2672 break;
2673 default:
2674 SiS_SetRegAND(SISCR, 0x32, ~0x07);
2675 }
2676 #endif
2677 }
2678 }
2679
sisfb_get_VB_type(struct sis_video_info * ivideo)2680 static void sisfb_get_VB_type(struct sis_video_info *ivideo)
2681 {
2682 char stdstr[] = "sisfb: Detected";
2683 char bridgestr[] = "video bridge";
2684 u8 vb_chipid;
2685 u8 reg;
2686
2687 /* No CRT2 on XGI Z7 */
2688 if(ivideo->chip == XGI_20)
2689 return;
2690
2691 vb_chipid = SiS_GetReg(SISPART4, 0x00);
2692 switch(vb_chipid) {
2693 case 0x01:
2694 reg = SiS_GetReg(SISPART4, 0x01);
2695 if(reg < 0xb0) {
2696 ivideo->vbflags |= VB_301; /* Deprecated */
2697 ivideo->vbflags2 |= VB2_301;
2698 printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
2699 } else if(reg < 0xc0) {
2700 ivideo->vbflags |= VB_301B; /* Deprecated */
2701 ivideo->vbflags2 |= VB2_301B;
2702 reg = SiS_GetReg(SISPART4, 0x23);
2703 if(!(reg & 0x02)) {
2704 ivideo->vbflags |= VB_30xBDH; /* Deprecated */
2705 ivideo->vbflags2 |= VB2_30xBDH;
2706 printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
2707 } else {
2708 printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
2709 }
2710 } else if(reg < 0xd0) {
2711 ivideo->vbflags |= VB_301C; /* Deprecated */
2712 ivideo->vbflags2 |= VB2_301C;
2713 printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
2714 } else if(reg < 0xe0) {
2715 ivideo->vbflags |= VB_301LV; /* Deprecated */
2716 ivideo->vbflags2 |= VB2_301LV;
2717 printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
2718 } else if(reg <= 0xe1) {
2719 reg = SiS_GetReg(SISPART4, 0x39);
2720 if(reg == 0xff) {
2721 ivideo->vbflags |= VB_302LV; /* Deprecated */
2722 ivideo->vbflags2 |= VB2_302LV;
2723 printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
2724 } else {
2725 ivideo->vbflags |= VB_301C; /* Deprecated */
2726 ivideo->vbflags2 |= VB2_301C;
2727 printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
2728 #if 0
2729 ivideo->vbflags |= VB_302ELV; /* Deprecated */
2730 ivideo->vbflags2 |= VB2_302ELV;
2731 printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
2732 #endif
2733 }
2734 }
2735 break;
2736 case 0x02:
2737 ivideo->vbflags |= VB_302B; /* Deprecated */
2738 ivideo->vbflags2 |= VB2_302B;
2739 printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
2740 break;
2741 }
2742
2743 if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
2744 reg = SiS_GetReg(SISCR, 0x37);
2745 reg &= SIS_EXTERNAL_CHIP_MASK;
2746 reg >>= 1;
2747 if(ivideo->sisvga_engine == SIS_300_VGA) {
2748 #ifdef CONFIG_FB_SIS_300
2749 switch(reg) {
2750 case SIS_EXTERNAL_CHIP_LVDS:
2751 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2752 ivideo->vbflags2 |= VB2_LVDS;
2753 break;
2754 case SIS_EXTERNAL_CHIP_TRUMPION:
2755 ivideo->vbflags |= (VB_LVDS | VB_TRUMPION); /* Deprecated */
2756 ivideo->vbflags2 |= (VB2_LVDS | VB2_TRUMPION);
2757 break;
2758 case SIS_EXTERNAL_CHIP_CHRONTEL:
2759 ivideo->vbflags |= VB_CHRONTEL; /* Deprecated */
2760 ivideo->vbflags2 |= VB2_CHRONTEL;
2761 break;
2762 case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
2763 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2764 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2765 break;
2766 }
2767 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 1;
2768 #endif
2769 } else if(ivideo->chip < SIS_661) {
2770 #ifdef CONFIG_FB_SIS_315
2771 switch (reg) {
2772 case SIS310_EXTERNAL_CHIP_LVDS:
2773 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2774 ivideo->vbflags2 |= VB2_LVDS;
2775 break;
2776 case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
2777 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2778 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2779 break;
2780 }
2781 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
2782 #endif
2783 } else if(ivideo->chip >= SIS_661) {
2784 #ifdef CONFIG_FB_SIS_315
2785 reg = SiS_GetReg(SISCR, 0x38);
2786 reg >>= 5;
2787 switch(reg) {
2788 case 0x02:
2789 ivideo->vbflags |= VB_LVDS; /* Deprecated */
2790 ivideo->vbflags2 |= VB2_LVDS;
2791 break;
2792 case 0x03:
2793 ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
2794 ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
2795 break;
2796 case 0x04:
2797 ivideo->vbflags |= (VB_LVDS | VB_CONEXANT); /* Deprecated */
2798 ivideo->vbflags2 |= (VB2_LVDS | VB2_CONEXANT);
2799 break;
2800 }
2801 if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
2802 #endif
2803 }
2804 if(ivideo->vbflags2 & VB2_LVDS) {
2805 printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
2806 }
2807 if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags2 & VB2_TRUMPION)) {
2808 printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
2809 }
2810 if(ivideo->vbflags2 & VB2_CHRONTEL) {
2811 printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
2812 }
2813 if((ivideo->chip >= SIS_661) && (ivideo->vbflags2 & VB2_CONEXANT)) {
2814 printk(KERN_INFO "%s Conexant external device\n", stdstr);
2815 }
2816 }
2817
2818 if(ivideo->vbflags2 & VB2_SISBRIDGE) {
2819 SiS_SenseLCD(ivideo);
2820 SiS_Sense30x(ivideo);
2821 } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
2822 SiS_SenseCh(ivideo);
2823 }
2824 }
2825
2826 /* ---------- Engine initialization routines ------------ */
2827
2828 static void
sisfb_engine_init(struct sis_video_info * ivideo)2829 sisfb_engine_init(struct sis_video_info *ivideo)
2830 {
2831
2832 /* Initialize command queue (we use MMIO only) */
2833
2834 /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
2835
2836 ivideo->caps &= ~(TURBO_QUEUE_CAP |
2837 MMIO_CMD_QUEUE_CAP |
2838 VM_CMD_QUEUE_CAP |
2839 AGP_CMD_QUEUE_CAP);
2840
2841 #ifdef CONFIG_FB_SIS_300
2842 if(ivideo->sisvga_engine == SIS_300_VGA) {
2843 u32 tqueue_pos;
2844 u8 tq_state;
2845
2846 tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024);
2847
2848 tq_state = SiS_GetReg(SISSR, IND_SIS_TURBOQUEUE_SET);
2849 tq_state |= 0xf0;
2850 tq_state &= 0xfc;
2851 tq_state |= (u8)(tqueue_pos >> 8);
2852 SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
2853
2854 SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
2855
2856 ivideo->caps |= TURBO_QUEUE_CAP;
2857 }
2858 #endif
2859
2860 #ifdef CONFIG_FB_SIS_315
2861 if(ivideo->sisvga_engine == SIS_315_VGA) {
2862 u32 tempq = 0, templ;
2863 u8 temp;
2864
2865 if(ivideo->chip == XGI_20) {
2866 switch(ivideo->cmdQueueSize) {
2867 case (64 * 1024):
2868 temp = SIS_CMD_QUEUE_SIZE_Z7_64k;
2869 break;
2870 case (128 * 1024):
2871 default:
2872 temp = SIS_CMD_QUEUE_SIZE_Z7_128k;
2873 }
2874 } else {
2875 switch(ivideo->cmdQueueSize) {
2876 case (4 * 1024 * 1024):
2877 temp = SIS_CMD_QUEUE_SIZE_4M;
2878 break;
2879 case (2 * 1024 * 1024):
2880 temp = SIS_CMD_QUEUE_SIZE_2M;
2881 break;
2882 case (1 * 1024 * 1024):
2883 temp = SIS_CMD_QUEUE_SIZE_1M;
2884 break;
2885 default:
2886 case (512 * 1024):
2887 temp = SIS_CMD_QUEUE_SIZE_512k;
2888 }
2889 }
2890
2891 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
2892 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
2893
2894 if((ivideo->chip >= XGI_40) && ivideo->modechanged) {
2895 /* Must disable dual pipe on XGI_40. Can't do
2896 * this in MMIO mode, because it requires
2897 * setting/clearing a bit in the MMIO fire trigger
2898 * register.
2899 */
2900 if(!((templ = MMIO_IN32(ivideo->mmio_vbase, 0x8240)) & (1 << 10))) {
2901
2902 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0);
2903
2904 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE));
2905
2906 tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR);
2907 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq);
2908
2909 tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
2910 MMIO_OUT32(ivideo->mmio_vbase, Q_BASE_ADDR, tempq);
2911
2912 writel(0x16800000 + 0x8240, ivideo->video_vbase + tempq);
2913 writel(templ | (1 << 10), ivideo->video_vbase + tempq + 4);
2914 writel(0x168F0000, ivideo->video_vbase + tempq + 8);
2915 writel(0x168F0000, ivideo->video_vbase + tempq + 12);
2916
2917 MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, (tempq + 16));
2918
2919 sisfb_syncaccel(ivideo);
2920
2921 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
2922
2923 }
2924 }
2925
2926 tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
2927 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
2928
2929 temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
2930 SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, temp);
2931
2932 tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
2933 MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
2934
2935 ivideo->caps |= MMIO_CMD_QUEUE_CAP;
2936 }
2937 #endif
2938
2939 ivideo->engineok = 1;
2940 }
2941
sisfb_detect_lcd_type(struct sis_video_info * ivideo)2942 static void sisfb_detect_lcd_type(struct sis_video_info *ivideo)
2943 {
2944 u8 reg;
2945 int i;
2946
2947 reg = SiS_GetReg(SISCR, 0x36);
2948 reg &= 0x0f;
2949 if(ivideo->sisvga_engine == SIS_300_VGA) {
2950 ivideo->CRT2LCDType = sis300paneltype[reg];
2951 } else if(ivideo->chip >= SIS_661) {
2952 ivideo->CRT2LCDType = sis661paneltype[reg];
2953 } else {
2954 ivideo->CRT2LCDType = sis310paneltype[reg];
2955 if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
2956 if((ivideo->CRT2LCDType != LCD_320x240_2) &&
2957 (ivideo->CRT2LCDType != LCD_320x240_3)) {
2958 ivideo->CRT2LCDType = LCD_320x240;
2959 }
2960 }
2961 }
2962
2963 if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
2964 /* For broken BIOSes: Assume 1024x768, RGB18 */
2965 ivideo->CRT2LCDType = LCD_1024x768;
2966 SiS_SetRegANDOR(SISCR, 0x36, 0xf0, 0x02);
2967 SiS_SetRegANDOR(SISCR, 0x37, 0xee, 0x01);
2968 printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
2969 }
2970
2971 for(i = 0; i < SIS_LCD_NUMBER; i++) {
2972 if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
2973 ivideo->lcdxres = sis_lcd_data[i].xres;
2974 ivideo->lcdyres = sis_lcd_data[i].yres;
2975 ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
2976 break;
2977 }
2978 }
2979
2980 #ifdef CONFIG_FB_SIS_300
2981 if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
2982 ivideo->lcdxres = 1360; ivideo->lcdyres = 1024;
2983 ivideo->lcddefmodeidx = DEFAULT_MODE_1360;
2984 } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
2985 ivideo->lcdxres = 848; ivideo->lcdyres = 480;
2986 ivideo->lcddefmodeidx = DEFAULT_MODE_848;
2987 } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL856) {
2988 ivideo->lcdxres = 856; ivideo->lcdyres = 480;
2989 ivideo->lcddefmodeidx = DEFAULT_MODE_856;
2990 }
2991 #endif
2992
2993 printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
2994 ivideo->lcdxres, ivideo->lcdyres);
2995 }
2996
sisfb_save_pdc_emi(struct sis_video_info * ivideo)2997 static void sisfb_save_pdc_emi(struct sis_video_info *ivideo)
2998 {
2999 #ifdef CONFIG_FB_SIS_300
3000 /* Save the current PanelDelayCompensation if the LCD is currently used */
3001 if(ivideo->sisvga_engine == SIS_300_VGA) {
3002 if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) {
3003 int tmp;
3004 tmp = SiS_GetReg(SISCR, 0x30);
3005 if(tmp & 0x20) {
3006 /* Currently on LCD? If yes, read current pdc */
3007 ivideo->detectedpdc = SiS_GetReg(SISPART1, 0x13);
3008 ivideo->detectedpdc &= 0x3c;
3009 if(ivideo->SiS_Pr.PDC == -1) {
3010 /* Let option override detection */
3011 ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
3012 }
3013 printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
3014 ivideo->detectedpdc);
3015 }
3016 if((ivideo->SiS_Pr.PDC != -1) &&
3017 (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
3018 printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
3019 ivideo->SiS_Pr.PDC);
3020 }
3021 }
3022 }
3023 #endif
3024
3025 #ifdef CONFIG_FB_SIS_315
3026 if(ivideo->sisvga_engine == SIS_315_VGA) {
3027
3028 /* Try to find about LCDA */
3029 if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) {
3030 int tmp;
3031 tmp = SiS_GetReg(SISPART1, 0x13);
3032 if(tmp & 0x04) {
3033 ivideo->SiS_Pr.SiS_UseLCDA = true;
3034 ivideo->detectedlcda = 0x03;
3035 }
3036 }
3037
3038 /* Save PDC */
3039 if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
3040 int tmp;
3041 tmp = SiS_GetReg(SISCR, 0x30);
3042 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
3043 /* Currently on LCD? If yes, read current pdc */
3044 u8 pdc;
3045 pdc = SiS_GetReg(SISPART1, 0x2D);
3046 ivideo->detectedpdc = (pdc & 0x0f) << 1;
3047 ivideo->detectedpdca = (pdc & 0xf0) >> 3;
3048 pdc = SiS_GetReg(SISPART1, 0x35);
3049 ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
3050 pdc = SiS_GetReg(SISPART1, 0x20);
3051 ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
3052 if(ivideo->newrom) {
3053 /* New ROM invalidates other PDC resp. */
3054 if(ivideo->detectedlcda != 0xff) {
3055 ivideo->detectedpdc = 0xff;
3056 } else {
3057 ivideo->detectedpdca = 0xff;
3058 }
3059 }
3060 if(ivideo->SiS_Pr.PDC == -1) {
3061 if(ivideo->detectedpdc != 0xff) {
3062 ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
3063 }
3064 }
3065 if(ivideo->SiS_Pr.PDCA == -1) {
3066 if(ivideo->detectedpdca != 0xff) {
3067 ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
3068 }
3069 }
3070 if(ivideo->detectedpdc != 0xff) {
3071 printk(KERN_INFO
3072 "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
3073 ivideo->detectedpdc);
3074 }
3075 if(ivideo->detectedpdca != 0xff) {
3076 printk(KERN_INFO
3077 "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
3078 ivideo->detectedpdca);
3079 }
3080 }
3081
3082 /* Save EMI */
3083 if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) {
3084 ivideo->SiS_Pr.EMI_30 = SiS_GetReg(SISPART4, 0x30);
3085 ivideo->SiS_Pr.EMI_31 = SiS_GetReg(SISPART4, 0x31);
3086 ivideo->SiS_Pr.EMI_32 = SiS_GetReg(SISPART4, 0x32);
3087 ivideo->SiS_Pr.EMI_33 = SiS_GetReg(SISPART4, 0x33);
3088 ivideo->SiS_Pr.HaveEMI = true;
3089 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
3090 ivideo->SiS_Pr.HaveEMILCD = true;
3091 }
3092 }
3093 }
3094
3095 /* Let user override detected PDCs (all bridges) */
3096 if(ivideo->vbflags2 & VB2_30xBLV) {
3097 if((ivideo->SiS_Pr.PDC != -1) &&
3098 (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
3099 printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
3100 ivideo->SiS_Pr.PDC);
3101 }
3102 if((ivideo->SiS_Pr.PDCA != -1) &&
3103 (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
3104 printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
3105 ivideo->SiS_Pr.PDCA);
3106 }
3107 }
3108
3109 }
3110 #endif
3111 }
3112
3113 /* -------------------- Memory manager routines ---------------------- */
3114
sisfb_getheapstart(struct sis_video_info * ivideo)3115 static u32 sisfb_getheapstart(struct sis_video_info *ivideo)
3116 {
3117 u32 ret = ivideo->sisfb_parm_mem * 1024;
3118 u32 maxoffs = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
3119 u32 def;
3120
3121 /* Calculate heap start = end of memory for console
3122 *
3123 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
3124 * C = console, D = heap, H = HWCursor, Q = cmd-queue
3125 *
3126 * On 76x in UMA+LFB mode, the layout is as follows:
3127 * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
3128 * where the heap is the entire UMA area, eventually
3129 * into the LFB area if the given mem parameter is
3130 * higher than the size of the UMA memory.
3131 *
3132 * Basically given by "mem" parameter
3133 *
3134 * maximum = videosize - cmd_queue - hwcursor
3135 * (results in a heap of size 0)
3136 * default = SiS 300: depends on videosize
3137 * SiS 315/330/340/XGI: 32k below max
3138 */
3139
3140 if(ivideo->sisvga_engine == SIS_300_VGA) {
3141 if(ivideo->video_size > 0x1000000) {
3142 def = 0xc00000;
3143 } else if(ivideo->video_size > 0x800000) {
3144 def = 0x800000;
3145 } else {
3146 def = 0x400000;
3147 }
3148 } else if(ivideo->UMAsize && ivideo->LFBsize) {
3149 ret = def = 0;
3150 } else {
3151 def = maxoffs - 0x8000;
3152 }
3153
3154 /* Use default for secondary card for now (FIXME) */
3155 if((!ret) || (ret > maxoffs) || (ivideo->cardnumber != 0))
3156 ret = def;
3157
3158 return ret;
3159 }
3160
sisfb_getheapsize(struct sis_video_info * ivideo)3161 static u32 sisfb_getheapsize(struct sis_video_info *ivideo)
3162 {
3163 u32 max = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
3164 u32 ret = 0;
3165
3166 if(ivideo->UMAsize && ivideo->LFBsize) {
3167 if( (!ivideo->sisfb_parm_mem) ||
3168 ((ivideo->sisfb_parm_mem * 1024) > max) ||
3169 ((max - (ivideo->sisfb_parm_mem * 1024)) < ivideo->UMAsize) ) {
3170 ret = ivideo->UMAsize;
3171 max -= ivideo->UMAsize;
3172 } else {
3173 ret = max - (ivideo->sisfb_parm_mem * 1024);
3174 max = ivideo->sisfb_parm_mem * 1024;
3175 }
3176 ivideo->video_offset = ret;
3177 ivideo->sisfb_mem = max;
3178 } else {
3179 ret = max - ivideo->heapstart;
3180 ivideo->sisfb_mem = ivideo->heapstart;
3181 }
3182
3183 return ret;
3184 }
3185
sisfb_heap_init(struct sis_video_info * ivideo)3186 static int sisfb_heap_init(struct sis_video_info *ivideo)
3187 {
3188 struct SIS_OH *poh;
3189
3190 ivideo->video_offset = 0;
3191 if(ivideo->sisfb_parm_mem) {
3192 if( (ivideo->sisfb_parm_mem < (2 * 1024 * 1024)) ||
3193 (ivideo->sisfb_parm_mem > ivideo->video_size) ) {
3194 ivideo->sisfb_parm_mem = 0;
3195 }
3196 }
3197
3198 ivideo->heapstart = sisfb_getheapstart(ivideo);
3199 ivideo->sisfb_heap_size = sisfb_getheapsize(ivideo);
3200
3201 ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
3202 ivideo->sisfb_heap_end = ivideo->sisfb_heap_start + ivideo->sisfb_heap_size;
3203
3204 printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
3205 (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
3206
3207 ivideo->sisfb_heap.vinfo = ivideo;
3208
3209 ivideo->sisfb_heap.poha_chain = NULL;
3210 ivideo->sisfb_heap.poh_freelist = NULL;
3211
3212 poh = sisfb_poh_new_node(&ivideo->sisfb_heap);
3213 if(poh == NULL)
3214 return 1;
3215
3216 poh->poh_next = &ivideo->sisfb_heap.oh_free;
3217 poh->poh_prev = &ivideo->sisfb_heap.oh_free;
3218 poh->size = ivideo->sisfb_heap_size;
3219 poh->offset = ivideo->heapstart;
3220
3221 ivideo->sisfb_heap.oh_free.poh_next = poh;
3222 ivideo->sisfb_heap.oh_free.poh_prev = poh;
3223 ivideo->sisfb_heap.oh_free.size = 0;
3224 ivideo->sisfb_heap.max_freesize = poh->size;
3225
3226 ivideo->sisfb_heap.oh_used.poh_next = &ivideo->sisfb_heap.oh_used;
3227 ivideo->sisfb_heap.oh_used.poh_prev = &ivideo->sisfb_heap.oh_used;
3228 ivideo->sisfb_heap.oh_used.size = SENTINEL;
3229
3230 if(ivideo->cardnumber == 0) {
3231 /* For the first card, make this heap the "global" one
3232 * for old DRM (which could handle only one card)
3233 */
3234 sisfb_heap = &ivideo->sisfb_heap;
3235 }
3236
3237 return 0;
3238 }
3239
3240 static struct SIS_OH *
sisfb_poh_new_node(struct SIS_HEAP * memheap)3241 sisfb_poh_new_node(struct SIS_HEAP *memheap)
3242 {
3243 struct SIS_OHALLOC *poha;
3244 struct SIS_OH *poh;
3245 unsigned long cOhs;
3246 int i;
3247
3248 if(memheap->poh_freelist == NULL) {
3249 poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL);
3250 if(!poha)
3251 return NULL;
3252
3253 poha->poha_next = memheap->poha_chain;
3254 memheap->poha_chain = poha;
3255
3256 cOhs = (SIS_OH_ALLOC_SIZE - sizeof(struct SIS_OHALLOC)) / sizeof(struct SIS_OH) + 1;
3257
3258 poh = &poha->aoh[0];
3259 for(i = cOhs - 1; i != 0; i--) {
3260 poh->poh_next = poh + 1;
3261 poh = poh + 1;
3262 }
3263
3264 poh->poh_next = NULL;
3265 memheap->poh_freelist = &poha->aoh[0];
3266 }
3267
3268 poh = memheap->poh_freelist;
3269 memheap->poh_freelist = poh->poh_next;
3270
3271 return poh;
3272 }
3273
3274 static struct SIS_OH *
sisfb_poh_allocate(struct SIS_HEAP * memheap,u32 size)3275 sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size)
3276 {
3277 struct SIS_OH *pohThis;
3278 struct SIS_OH *pohRoot;
3279 int bAllocated = 0;
3280
3281 if(size > memheap->max_freesize) {
3282 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3283 (unsigned int) size / 1024);
3284 return NULL;
3285 }
3286
3287 pohThis = memheap->oh_free.poh_next;
3288
3289 while(pohThis != &memheap->oh_free) {
3290 if(size <= pohThis->size) {
3291 bAllocated = 1;
3292 break;
3293 }
3294 pohThis = pohThis->poh_next;
3295 }
3296
3297 if(!bAllocated) {
3298 DPRINTK("sisfb: Can't allocate %dk video memory\n",
3299 (unsigned int) size / 1024);
3300 return NULL;
3301 }
3302
3303 if(size == pohThis->size) {
3304 pohRoot = pohThis;
3305 sisfb_delete_node(pohThis);
3306 } else {
3307 pohRoot = sisfb_poh_new_node(memheap);
3308 if(pohRoot == NULL)
3309 return NULL;
3310
3311 pohRoot->offset = pohThis->offset;
3312 pohRoot->size = size;
3313
3314 pohThis->offset += size;
3315 pohThis->size -= size;
3316 }
3317
3318 memheap->max_freesize -= size;
3319
3320 pohThis = &memheap->oh_used;
3321 sisfb_insert_node(pohThis, pohRoot);
3322
3323 return pohRoot;
3324 }
3325
3326 static void
sisfb_delete_node(struct SIS_OH * poh)3327 sisfb_delete_node(struct SIS_OH *poh)
3328 {
3329 poh->poh_prev->poh_next = poh->poh_next;
3330 poh->poh_next->poh_prev = poh->poh_prev;
3331 }
3332
3333 static void
sisfb_insert_node(struct SIS_OH * pohList,struct SIS_OH * poh)3334 sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh)
3335 {
3336 struct SIS_OH *pohTemp = pohList->poh_next;
3337
3338 pohList->poh_next = poh;
3339 pohTemp->poh_prev = poh;
3340
3341 poh->poh_prev = pohList;
3342 poh->poh_next = pohTemp;
3343 }
3344
3345 static struct SIS_OH *
sisfb_poh_free(struct SIS_HEAP * memheap,u32 base)3346 sisfb_poh_free(struct SIS_HEAP *memheap, u32 base)
3347 {
3348 struct SIS_OH *pohThis;
3349 struct SIS_OH *poh_freed;
3350 struct SIS_OH *poh_prev;
3351 struct SIS_OH *poh_next;
3352 u32 ulUpper;
3353 u32 ulLower;
3354 int foundNode = 0;
3355
3356 poh_freed = memheap->oh_used.poh_next;
3357
3358 while(poh_freed != &memheap->oh_used) {
3359 if(poh_freed->offset == base) {
3360 foundNode = 1;
3361 break;
3362 }
3363
3364 poh_freed = poh_freed->poh_next;
3365 }
3366
3367 if(!foundNode)
3368 return NULL;
3369
3370 memheap->max_freesize += poh_freed->size;
3371
3372 poh_prev = poh_next = NULL;
3373 ulUpper = poh_freed->offset + poh_freed->size;
3374 ulLower = poh_freed->offset;
3375
3376 pohThis = memheap->oh_free.poh_next;
3377
3378 while(pohThis != &memheap->oh_free) {
3379 if(pohThis->offset == ulUpper) {
3380 poh_next = pohThis;
3381 } else if((pohThis->offset + pohThis->size) == ulLower) {
3382 poh_prev = pohThis;
3383 }
3384 pohThis = pohThis->poh_next;
3385 }
3386
3387 sisfb_delete_node(poh_freed);
3388
3389 if(poh_prev && poh_next) {
3390 poh_prev->size += (poh_freed->size + poh_next->size);
3391 sisfb_delete_node(poh_next);
3392 sisfb_free_node(memheap, poh_freed);
3393 sisfb_free_node(memheap, poh_next);
3394 return poh_prev;
3395 }
3396
3397 if(poh_prev) {
3398 poh_prev->size += poh_freed->size;
3399 sisfb_free_node(memheap, poh_freed);
3400 return poh_prev;
3401 }
3402
3403 if(poh_next) {
3404 poh_next->size += poh_freed->size;
3405 poh_next->offset = poh_freed->offset;
3406 sisfb_free_node(memheap, poh_freed);
3407 return poh_next;
3408 }
3409
3410 sisfb_insert_node(&memheap->oh_free, poh_freed);
3411
3412 return poh_freed;
3413 }
3414
3415 static void
sisfb_free_node(struct SIS_HEAP * memheap,struct SIS_OH * poh)3416 sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh)
3417 {
3418 if(poh == NULL)
3419 return;
3420
3421 poh->poh_next = memheap->poh_freelist;
3422 memheap->poh_freelist = poh;
3423 }
3424
3425 static void
sis_int_malloc(struct sis_video_info * ivideo,struct sis_memreq * req)3426 sis_int_malloc(struct sis_video_info *ivideo, struct sis_memreq *req)
3427 {
3428 struct SIS_OH *poh = NULL;
3429
3430 if((ivideo) && (ivideo->sisfb_id == SISFB_ID) && (!ivideo->havenoheap))
3431 poh = sisfb_poh_allocate(&ivideo->sisfb_heap, (u32)req->size);
3432
3433 if(poh == NULL) {
3434 req->offset = req->size = 0;
3435 DPRINTK("sisfb: Video RAM allocation failed\n");
3436 } else {
3437 req->offset = poh->offset;
3438 req->size = poh->size;
3439 DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
3440 (poh->offset + ivideo->video_vbase));
3441 }
3442 }
3443
3444 void
sis_malloc(struct sis_memreq * req)3445 sis_malloc(struct sis_memreq *req)
3446 {
3447 struct sis_video_info *ivideo = sisfb_heap->vinfo;
3448
3449 if(&ivideo->sisfb_heap == sisfb_heap)
3450 sis_int_malloc(ivideo, req);
3451 else
3452 req->offset = req->size = 0;
3453 }
3454
3455 void
sis_malloc_new(struct pci_dev * pdev,struct sis_memreq * req)3456 sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req)
3457 {
3458 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3459
3460 sis_int_malloc(ivideo, req);
3461 }
3462
3463 /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
3464
3465 static void
sis_int_free(struct sis_video_info * ivideo,u32 base)3466 sis_int_free(struct sis_video_info *ivideo, u32 base)
3467 {
3468 struct SIS_OH *poh;
3469
3470 if((!ivideo) || (ivideo->sisfb_id != SISFB_ID) || (ivideo->havenoheap))
3471 return;
3472
3473 poh = sisfb_poh_free(&ivideo->sisfb_heap, base);
3474
3475 if(poh == NULL) {
3476 DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
3477 (unsigned int) base);
3478 }
3479 }
3480
3481 void
sis_free(u32 base)3482 sis_free(u32 base)
3483 {
3484 struct sis_video_info *ivideo = sisfb_heap->vinfo;
3485
3486 sis_int_free(ivideo, base);
3487 }
3488
3489 void
sis_free_new(struct pci_dev * pdev,u32 base)3490 sis_free_new(struct pci_dev *pdev, u32 base)
3491 {
3492 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3493
3494 sis_int_free(ivideo, base);
3495 }
3496
3497 /* --------------------- SetMode routines ------------------------- */
3498
3499 static void
sisfb_check_engine_and_sync(struct sis_video_info * ivideo)3500 sisfb_check_engine_and_sync(struct sis_video_info *ivideo)
3501 {
3502 u8 cr30, cr31;
3503
3504 /* Check if MMIO and engines are enabled,
3505 * and sync in case they are. Can't use
3506 * ivideo->accel here, as this might have
3507 * been changed before this is called.
3508 */
3509 cr30 = SiS_GetReg(SISSR, IND_SIS_PCI_ADDRESS_SET);
3510 cr31 = SiS_GetReg(SISSR, IND_SIS_MODULE_ENABLE);
3511 /* MMIO and 2D/3D engine enabled? */
3512 if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) {
3513 #ifdef CONFIG_FB_SIS_300
3514 if(ivideo->sisvga_engine == SIS_300_VGA) {
3515 /* Don't care about TurboQueue. It's
3516 * enough to know that the engines
3517 * are enabled
3518 */
3519 sisfb_syncaccel(ivideo);
3520 }
3521 #endif
3522 #ifdef CONFIG_FB_SIS_315
3523 if(ivideo->sisvga_engine == SIS_315_VGA) {
3524 /* Check that any queue mode is
3525 * enabled, and that the queue
3526 * is not in the state of "reset"
3527 */
3528 cr30 = SiS_GetReg(SISSR, 0x26);
3529 if((cr30 & 0xe0) && (!(cr30 & 0x01))) {
3530 sisfb_syncaccel(ivideo);
3531 }
3532 }
3533 #endif
3534 }
3535 }
3536
3537 static void
sisfb_pre_setmode(struct sis_video_info * ivideo)3538 sisfb_pre_setmode(struct sis_video_info *ivideo)
3539 {
3540 u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0;
3541 int tvregnum = 0;
3542
3543 ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
3544
3545 SiS_SetReg(SISSR, 0x05, 0x86);
3546
3547 cr31 = SiS_GetReg(SISCR, 0x31);
3548 cr31 &= ~0x60;
3549 cr31 |= 0x04;
3550
3551 cr33 = ivideo->rate_idx & 0x0F;
3552
3553 #ifdef CONFIG_FB_SIS_315
3554 if(ivideo->sisvga_engine == SIS_315_VGA) {
3555 if(ivideo->chip >= SIS_661) {
3556 cr38 = SiS_GetReg(SISCR, 0x38);
3557 cr38 &= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */
3558 } else {
3559 tvregnum = 0x38;
3560 cr38 = SiS_GetReg(SISCR, tvregnum);
3561 cr38 &= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */
3562 }
3563 }
3564 #endif
3565 #ifdef CONFIG_FB_SIS_300
3566 if(ivideo->sisvga_engine == SIS_300_VGA) {
3567 tvregnum = 0x35;
3568 cr38 = SiS_GetReg(SISCR, tvregnum);
3569 }
3570 #endif
3571
3572 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
3573 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
3574 ivideo->curFSTN = ivideo->curDSTN = 0;
3575
3576 switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
3577
3578 case CRT2_TV:
3579 cr38 &= ~0xc0; /* Clear PAL-M / PAL-N bits */
3580 if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
3581 #ifdef CONFIG_FB_SIS_315
3582 if(ivideo->chip >= SIS_661) {
3583 cr38 |= 0x04;
3584 if(ivideo->vbflags & TV_YPBPR525P) cr35 |= 0x20;
3585 else if(ivideo->vbflags & TV_YPBPR750P) cr35 |= 0x40;
3586 else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60;
3587 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
3588 cr35 &= ~0x01;
3589 ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
3590 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
3591 cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
3592 cr38 |= 0x08;
3593 if(ivideo->vbflags & TV_YPBPR525P) cr38 |= 0x10;
3594 else if(ivideo->vbflags & TV_YPBPR750P) cr38 |= 0x20;
3595 else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30;
3596 cr31 &= ~0x01;
3597 ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
3598 }
3599 #endif
3600 } else if((ivideo->vbflags & TV_HIVISION) &&
3601 (ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) {
3602 if(ivideo->chip >= SIS_661) {
3603 cr38 |= 0x04;
3604 cr35 |= 0x60;
3605 } else {
3606 cr30 |= 0x80;
3607 }
3608 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
3609 cr31 |= 0x01;
3610 cr35 |= 0x01;
3611 ivideo->currentvbflags |= TV_HIVISION;
3612 } else if(ivideo->vbflags & TV_SCART) {
3613 cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
3614 cr31 |= 0x01;
3615 cr35 |= 0x01;
3616 ivideo->currentvbflags |= TV_SCART;
3617 } else {
3618 if(ivideo->vbflags & TV_SVIDEO) {
3619 cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
3620 ivideo->currentvbflags |= TV_SVIDEO;
3621 }
3622 if(ivideo->vbflags & TV_AVIDEO) {
3623 cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE);
3624 ivideo->currentvbflags |= TV_AVIDEO;
3625 }
3626 }
3627 cr31 |= SIS_DRIVER_MODE;
3628
3629 if(ivideo->vbflags & (TV_AVIDEO | TV_SVIDEO)) {
3630 if(ivideo->vbflags & TV_PAL) {
3631 cr31 |= 0x01; cr35 |= 0x01;
3632 ivideo->currentvbflags |= TV_PAL;
3633 if(ivideo->vbflags & TV_PALM) {
3634 cr38 |= 0x40; cr35 |= 0x04;
3635 ivideo->currentvbflags |= TV_PALM;
3636 } else if(ivideo->vbflags & TV_PALN) {
3637 cr38 |= 0x80; cr35 |= 0x08;
3638 ivideo->currentvbflags |= TV_PALN;
3639 }
3640 } else {
3641 cr31 &= ~0x01; cr35 &= ~0x01;
3642 ivideo->currentvbflags |= TV_NTSC;
3643 if(ivideo->vbflags & TV_NTSCJ) {
3644 cr38 |= 0x40; cr35 |= 0x02;
3645 ivideo->currentvbflags |= TV_NTSCJ;
3646 }
3647 }
3648 }
3649 break;
3650
3651 case CRT2_LCD:
3652 cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
3653 cr31 |= SIS_DRIVER_MODE;
3654 SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn);
3655 SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn);
3656 ivideo->curFSTN = ivideo->sisfb_fstn;
3657 ivideo->curDSTN = ivideo->sisfb_dstn;
3658 break;
3659
3660 case CRT2_VGA:
3661 cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
3662 cr31 |= SIS_DRIVER_MODE;
3663 if(ivideo->sisfb_nocrt2rate) {
3664 cr33 |= (sisbios_mode[ivideo->sisfb_mode_idx].rate_idx << 4);
3665 } else {
3666 cr33 |= ((ivideo->rate_idx & 0x0F) << 4);
3667 }
3668 break;
3669
3670 default: /* disable CRT2 */
3671 cr30 = 0x00;
3672 cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
3673 }
3674
3675 SiS_SetReg(SISCR, 0x30, cr30);
3676 SiS_SetReg(SISCR, 0x33, cr33);
3677
3678 if(ivideo->chip >= SIS_661) {
3679 #ifdef CONFIG_FB_SIS_315
3680 cr31 &= ~0x01; /* Clear PAL flag (now in CR35) */
3681 SiS_SetRegANDOR(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
3682 cr38 &= 0x07; /* Use only LCDA and HiVision/YPbPr bits */
3683 SiS_SetRegANDOR(SISCR, 0x38, 0xf8, cr38);
3684 #endif
3685 } else if(ivideo->chip != SIS_300) {
3686 SiS_SetReg(SISCR, tvregnum, cr38);
3687 }
3688 SiS_SetReg(SISCR, 0x31, cr31);
3689
3690 ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
3691
3692 sisfb_check_engine_and_sync(ivideo);
3693 }
3694
3695 /* Fix SR11 for 661 and later */
3696 #ifdef CONFIG_FB_SIS_315
3697 static void
sisfb_fixup_SR11(struct sis_video_info * ivideo)3698 sisfb_fixup_SR11(struct sis_video_info *ivideo)
3699 {
3700 u8 tmpreg;
3701
3702 if(ivideo->chip >= SIS_661) {
3703 tmpreg = SiS_GetReg(SISSR, 0x11);
3704 if(tmpreg & 0x20) {
3705 tmpreg = SiS_GetReg(SISSR, 0x3e);
3706 tmpreg = (tmpreg + 1) & 0xff;
3707 SiS_SetReg(SISSR, 0x3e, tmpreg);
3708 tmpreg = SiS_GetReg(SISSR, 0x11);
3709 }
3710 if(tmpreg & 0xf0) {
3711 SiS_SetRegAND(SISSR, 0x11, 0x0f);
3712 }
3713 }
3714 }
3715 #endif
3716
3717 static void
sisfb_set_TVxposoffset(struct sis_video_info * ivideo,int val)3718 sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
3719 {
3720 if(val > 32) val = 32;
3721 if(val < -32) val = -32;
3722 ivideo->tvxpos = val;
3723
3724 if(ivideo->sisfblocked) return;
3725 if(!ivideo->modechanged) return;
3726
3727 if(ivideo->currentvbflags & CRT2_TV) {
3728
3729 if(ivideo->vbflags2 & VB2_CHRONTEL) {
3730
3731 int x = ivideo->tvx;
3732
3733 switch(ivideo->chronteltype) {
3734 case 1:
3735 x += val;
3736 if(x < 0) x = 0;
3737 SiS_SetReg(SISSR, 0x05, 0x86);
3738 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff));
3739 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD);
3740 break;
3741 case 2:
3742 /* Not supported by hardware */
3743 break;
3744 }
3745
3746 } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3747
3748 u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
3749 unsigned short temp;
3750
3751 p2_1f = ivideo->p2_1f;
3752 p2_20 = ivideo->p2_20;
3753 p2_2b = ivideo->p2_2b;
3754 p2_42 = ivideo->p2_42;
3755 p2_43 = ivideo->p2_43;
3756
3757 temp = p2_1f | ((p2_20 & 0xf0) << 4);
3758 temp += (val * 2);
3759 p2_1f = temp & 0xff;
3760 p2_20 = (temp & 0xf00) >> 4;
3761 p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
3762 temp = p2_43 | ((p2_42 & 0xf0) << 4);
3763 temp += (val * 2);
3764 p2_43 = temp & 0xff;
3765 p2_42 = (temp & 0xf00) >> 4;
3766 SiS_SetReg(SISPART2, 0x1f, p2_1f);
3767 SiS_SetRegANDOR(SISPART2, 0x20, 0x0F, p2_20);
3768 SiS_SetRegANDOR(SISPART2, 0x2b, 0xF0, p2_2b);
3769 SiS_SetRegANDOR(SISPART2, 0x42, 0x0F, p2_42);
3770 SiS_SetReg(SISPART2, 0x43, p2_43);
3771 }
3772 }
3773 }
3774
3775 static void
sisfb_set_TVyposoffset(struct sis_video_info * ivideo,int val)3776 sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
3777 {
3778 if(val > 32) val = 32;
3779 if(val < -32) val = -32;
3780 ivideo->tvypos = val;
3781
3782 if(ivideo->sisfblocked) return;
3783 if(!ivideo->modechanged) return;
3784
3785 if(ivideo->currentvbflags & CRT2_TV) {
3786
3787 if(ivideo->vbflags2 & VB2_CHRONTEL) {
3788
3789 int y = ivideo->tvy;
3790
3791 switch(ivideo->chronteltype) {
3792 case 1:
3793 y -= val;
3794 if(y < 0) y = 0;
3795 SiS_SetReg(SISSR, 0x05, 0x86);
3796 SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff));
3797 SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE);
3798 break;
3799 case 2:
3800 /* Not supported by hardware */
3801 break;
3802 }
3803
3804 } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3805
3806 char p2_01, p2_02;
3807 val /= 2;
3808 p2_01 = ivideo->p2_01;
3809 p2_02 = ivideo->p2_02;
3810
3811 p2_01 += val;
3812 p2_02 += val;
3813 if(!(ivideo->currentvbflags & (TV_HIVISION | TV_YPBPR))) {
3814 while((p2_01 <= 0) || (p2_02 <= 0)) {
3815 p2_01 += 2;
3816 p2_02 += 2;
3817 }
3818 }
3819 SiS_SetReg(SISPART2, 0x01, p2_01);
3820 SiS_SetReg(SISPART2, 0x02, p2_02);
3821 }
3822 }
3823 }
3824
3825 static void
sisfb_post_setmode(struct sis_video_info * ivideo)3826 sisfb_post_setmode(struct sis_video_info *ivideo)
3827 {
3828 bool crt1isoff = false;
3829 bool doit = true;
3830 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
3831 u8 reg;
3832 #endif
3833 #ifdef CONFIG_FB_SIS_315
3834 u8 reg1;
3835 #endif
3836
3837 SiS_SetReg(SISSR, 0x05, 0x86);
3838
3839 #ifdef CONFIG_FB_SIS_315
3840 sisfb_fixup_SR11(ivideo);
3841 #endif
3842
3843 /* Now we actually HAVE changed the display mode */
3844 ivideo->modechanged = 1;
3845
3846 /* We can't switch off CRT1 if bridge is in slave mode */
3847 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
3848 if(sisfb_bridgeisslave(ivideo)) doit = false;
3849 } else
3850 ivideo->sisfb_crt1off = 0;
3851
3852 #ifdef CONFIG_FB_SIS_300
3853 if(ivideo->sisvga_engine == SIS_300_VGA) {
3854 if((ivideo->sisfb_crt1off) && (doit)) {
3855 crt1isoff = true;
3856 reg = 0x00;
3857 } else {
3858 crt1isoff = false;
3859 reg = 0x80;
3860 }
3861 SiS_SetRegANDOR(SISCR, 0x17, 0x7f, reg);
3862 }
3863 #endif
3864 #ifdef CONFIG_FB_SIS_315
3865 if(ivideo->sisvga_engine == SIS_315_VGA) {
3866 if((ivideo->sisfb_crt1off) && (doit)) {
3867 crt1isoff = true;
3868 reg = 0x40;
3869 reg1 = 0xc0;
3870 } else {
3871 crt1isoff = false;
3872 reg = 0x00;
3873 reg1 = 0x00;
3874 }
3875 SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
3876 SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, reg1);
3877 }
3878 #endif
3879
3880 if(crt1isoff) {
3881 ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
3882 ivideo->currentvbflags |= VB_SINGLE_MODE;
3883 } else {
3884 ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
3885 if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
3886 ivideo->currentvbflags |= VB_MIRROR_MODE;
3887 } else {
3888 ivideo->currentvbflags |= VB_SINGLE_MODE;
3889 }
3890 }
3891
3892 SiS_SetRegAND(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
3893
3894 if(ivideo->currentvbflags & CRT2_TV) {
3895 if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3896 ivideo->p2_1f = SiS_GetReg(SISPART2, 0x1f);
3897 ivideo->p2_20 = SiS_GetReg(SISPART2, 0x20);
3898 ivideo->p2_2b = SiS_GetReg(SISPART2, 0x2b);
3899 ivideo->p2_42 = SiS_GetReg(SISPART2, 0x42);
3900 ivideo->p2_43 = SiS_GetReg(SISPART2, 0x43);
3901 ivideo->p2_01 = SiS_GetReg(SISPART2, 0x01);
3902 ivideo->p2_02 = SiS_GetReg(SISPART2, 0x02);
3903 } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
3904 if(ivideo->chronteltype == 1) {
3905 ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
3906 ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
3907 ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
3908 ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
3909 }
3910 }
3911 }
3912
3913 if(ivideo->tvxpos) {
3914 sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
3915 }
3916 if(ivideo->tvypos) {
3917 sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
3918 }
3919
3920 /* Eventually sync engines */
3921 sisfb_check_engine_and_sync(ivideo);
3922
3923 /* (Re-)Initialize chip engines */
3924 if(ivideo->accel) {
3925 sisfb_engine_init(ivideo);
3926 } else {
3927 ivideo->engineok = 0;
3928 }
3929 }
3930
3931 static int
sisfb_reset_mode(struct sis_video_info * ivideo)3932 sisfb_reset_mode(struct sis_video_info *ivideo)
3933 {
3934 if(sisfb_set_mode(ivideo, 0))
3935 return 1;
3936
3937 sisfb_set_pitch(ivideo);
3938 sisfb_set_base_CRT1(ivideo, ivideo->current_base);
3939 sisfb_set_base_CRT2(ivideo, ivideo->current_base);
3940
3941 return 0;
3942 }
3943
3944 static void
sisfb_handle_command(struct sis_video_info * ivideo,struct sisfb_cmd * sisfb_command)3945 sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_command)
3946 {
3947 int mycrt1off;
3948
3949 switch(sisfb_command->sisfb_cmd) {
3950 case SISFB_CMD_GETVBFLAGS:
3951 if(!ivideo->modechanged) {
3952 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
3953 } else {
3954 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3955 sisfb_command->sisfb_result[1] = ivideo->currentvbflags;
3956 sisfb_command->sisfb_result[2] = ivideo->vbflags2;
3957 }
3958 break;
3959 case SISFB_CMD_SWITCHCRT1:
3960 /* arg[0]: 0 = off, 1 = on, 99 = query */
3961 if(!ivideo->modechanged) {
3962 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
3963 } else if(sisfb_command->sisfb_arg[0] == 99) {
3964 /* Query */
3965 sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
3966 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3967 } else if(ivideo->sisfblocked) {
3968 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_LOCKED;
3969 } else if((!(ivideo->currentvbflags & CRT2_ENABLE)) &&
3970 (sisfb_command->sisfb_arg[0] == 0)) {
3971 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_NOCRT2;
3972 } else {
3973 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3974 mycrt1off = sisfb_command->sisfb_arg[0] ? 0 : 1;
3975 if( ((ivideo->currentvbflags & VB_DISPTYPE_CRT1) && mycrt1off) ||
3976 ((!(ivideo->currentvbflags & VB_DISPTYPE_CRT1)) && !mycrt1off) ) {
3977 ivideo->sisfb_crt1off = mycrt1off;
3978 if(sisfb_reset_mode(ivideo)) {
3979 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OTHER;
3980 }
3981 }
3982 sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
3983 }
3984 break;
3985 /* more to come */
3986 default:
3987 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_UNKNOWN;
3988 printk(KERN_ERR "sisfb: Unknown command 0x%x\n",
3989 sisfb_command->sisfb_cmd);
3990 }
3991 }
3992
3993 #ifndef MODULE
sisfb_setup(char * options)3994 static int __init sisfb_setup(char *options)
3995 {
3996 char *this_opt;
3997
3998 sisfb_setdefaultparms();
3999
4000 if(!options || !(*options))
4001 return 0;
4002
4003 while((this_opt = strsep(&options, ",")) != NULL) {
4004
4005 if(!(*this_opt)) continue;
4006
4007 if(!strncasecmp(this_opt, "off", 3)) {
4008 sisfb_off = 1;
4009 } else if(!strncasecmp(this_opt, "forcecrt2type:", 14)) {
4010 /* Need to check crt2 type first for fstn/dstn */
4011 sisfb_search_crt2type(this_opt + 14);
4012 } else if(!strncasecmp(this_opt, "tvmode:",7)) {
4013 sisfb_search_tvstd(this_opt + 7);
4014 } else if(!strncasecmp(this_opt, "tvstandard:",11)) {
4015 sisfb_search_tvstd(this_opt + 11);
4016 } else if(!strncasecmp(this_opt, "mode:", 5)) {
4017 sisfb_search_mode(this_opt + 5, false);
4018 } else if(!strncasecmp(this_opt, "vesa:", 5)) {
4019 sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), false);
4020 } else if(!strncasecmp(this_opt, "rate:", 5)) {
4021 sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
4022 } else if(!strncasecmp(this_opt, "forcecrt1:", 10)) {
4023 sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
4024 } else if(!strncasecmp(this_opt, "mem:",4)) {
4025 sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
4026 } else if(!strncasecmp(this_opt, "pdc:", 4)) {
4027 sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
4028 } else if(!strncasecmp(this_opt, "pdc1:", 5)) {
4029 sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
4030 } else if(!strncasecmp(this_opt, "noaccel", 7)) {
4031 sisfb_accel = 0;
4032 } else if(!strncasecmp(this_opt, "accel", 5)) {
4033 sisfb_accel = -1;
4034 } else if(!strncasecmp(this_opt, "noypan", 6)) {
4035 sisfb_ypan = 0;
4036 } else if(!strncasecmp(this_opt, "ypan", 4)) {
4037 sisfb_ypan = -1;
4038 } else if(!strncasecmp(this_opt, "nomax", 5)) {
4039 sisfb_max = 0;
4040 } else if(!strncasecmp(this_opt, "max", 3)) {
4041 sisfb_max = -1;
4042 } else if(!strncasecmp(this_opt, "userom:", 7)) {
4043 sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
4044 } else if(!strncasecmp(this_opt, "useoem:", 7)) {
4045 sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
4046 } else if(!strncasecmp(this_opt, "nocrt2rate", 10)) {
4047 sisfb_nocrt2rate = 1;
4048 } else if(!strncasecmp(this_opt, "scalelcd:", 9)) {
4049 unsigned long temp = 2;
4050 temp = simple_strtoul(this_opt + 9, NULL, 0);
4051 if((temp == 0) || (temp == 1)) {
4052 sisfb_scalelcd = temp ^ 1;
4053 }
4054 } else if(!strncasecmp(this_opt, "tvxposoffset:", 13)) {
4055 int temp = 0;
4056 temp = (int)simple_strtol(this_opt + 13, NULL, 0);
4057 if((temp >= -32) && (temp <= 32)) {
4058 sisfb_tvxposoffset = temp;
4059 }
4060 } else if(!strncasecmp(this_opt, "tvyposoffset:", 13)) {
4061 int temp = 0;
4062 temp = (int)simple_strtol(this_opt + 13, NULL, 0);
4063 if((temp >= -32) && (temp <= 32)) {
4064 sisfb_tvyposoffset = temp;
4065 }
4066 } else if(!strncasecmp(this_opt, "specialtiming:", 14)) {
4067 sisfb_search_specialtiming(this_opt + 14);
4068 } else if(!strncasecmp(this_opt, "lvdshl:", 7)) {
4069 int temp = 4;
4070 temp = simple_strtoul(this_opt + 7, NULL, 0);
4071 if((temp >= 0) && (temp <= 3)) {
4072 sisfb_lvdshl = temp;
4073 }
4074 } else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
4075 sisfb_search_mode(this_opt, true);
4076 #if !defined(__i386__) && !defined(__x86_64__)
4077 } else if(!strncasecmp(this_opt, "resetcard", 9)) {
4078 sisfb_resetcard = 1;
4079 } else if(!strncasecmp(this_opt, "videoram:", 9)) {
4080 sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
4081 #endif
4082 } else {
4083 printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
4084 }
4085
4086 }
4087
4088 return 0;
4089 }
4090 #endif
4091
sisfb_check_rom(void __iomem * rom_base,struct sis_video_info * ivideo)4092 static int sisfb_check_rom(void __iomem *rom_base,
4093 struct sis_video_info *ivideo)
4094 {
4095 void __iomem *rom;
4096 int romptr;
4097
4098 if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa))
4099 return 0;
4100
4101 romptr = (readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
4102 if(romptr > (0x10000 - 8))
4103 return 0;
4104
4105 rom = rom_base + romptr;
4106
4107 if((readb(rom) != 'P') || (readb(rom + 1) != 'C') ||
4108 (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R'))
4109 return 0;
4110
4111 if((readb(rom + 4) | (readb(rom + 5) << 8)) != ivideo->chip_vendor)
4112 return 0;
4113
4114 if((readb(rom + 6) | (readb(rom + 7) << 8)) != ivideo->chip_id)
4115 return 0;
4116
4117 return 1;
4118 }
4119
sisfb_find_rom(struct pci_dev * pdev)4120 static unsigned char *sisfb_find_rom(struct pci_dev *pdev)
4121 {
4122 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4123 void __iomem *rom_base;
4124 unsigned char *myrombase = NULL;
4125 size_t romsize;
4126
4127 /* First, try the official pci ROM functions (except
4128 * on integrated chipsets which have no ROM).
4129 */
4130
4131 if(!ivideo->nbridge) {
4132
4133 if((rom_base = pci_map_rom(pdev, &romsize))) {
4134
4135 if(sisfb_check_rom(rom_base, ivideo)) {
4136
4137 if((myrombase = vmalloc(65536))) {
4138 memcpy_fromio(myrombase, rom_base,
4139 (romsize > 65536) ? 65536 : romsize);
4140 }
4141 }
4142 pci_unmap_rom(pdev, rom_base);
4143 }
4144 }
4145
4146 if(myrombase) return myrombase;
4147
4148 /* Otherwise do it the conventional way. */
4149
4150 #if defined(__i386__) || defined(__x86_64__)
4151 {
4152 u32 temp;
4153
4154 for (temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
4155
4156 rom_base = ioremap(temp, 65536);
4157 if (!rom_base)
4158 continue;
4159
4160 if (!sisfb_check_rom(rom_base, ivideo)) {
4161 iounmap(rom_base);
4162 continue;
4163 }
4164
4165 if ((myrombase = vmalloc(65536)))
4166 memcpy_fromio(myrombase, rom_base, 65536);
4167
4168 iounmap(rom_base);
4169 break;
4170
4171 }
4172
4173 }
4174 #endif
4175
4176 return myrombase;
4177 }
4178
sisfb_post_map_vram(struct sis_video_info * ivideo,unsigned int * mapsize,unsigned int min)4179 static void sisfb_post_map_vram(struct sis_video_info *ivideo,
4180 unsigned int *mapsize, unsigned int min)
4181 {
4182 if (*mapsize < (min << 20))
4183 return;
4184
4185 ivideo->video_vbase = ioremap_wc(ivideo->video_base, (*mapsize));
4186
4187 if(!ivideo->video_vbase) {
4188 printk(KERN_ERR
4189 "sisfb: Unable to map maximum video RAM for size detection\n");
4190 (*mapsize) >>= 1;
4191 while((!(ivideo->video_vbase = ioremap_wc(ivideo->video_base, (*mapsize))))) {
4192 (*mapsize) >>= 1;
4193 if((*mapsize) < (min << 20))
4194 break;
4195 }
4196 if(ivideo->video_vbase) {
4197 printk(KERN_ERR
4198 "sisfb: Video RAM size detection limited to %dMB\n",
4199 (int)((*mapsize) >> 20));
4200 }
4201 }
4202 }
4203
4204 #ifdef CONFIG_FB_SIS_300
sisfb_post_300_buswidth(struct sis_video_info * ivideo)4205 static int sisfb_post_300_buswidth(struct sis_video_info *ivideo)
4206 {
4207 void __iomem *FBAddress = ivideo->video_vbase;
4208 unsigned short temp;
4209 unsigned char reg;
4210 int i, j;
4211
4212 SiS_SetRegAND(SISSR, 0x15, 0xFB);
4213 SiS_SetRegOR(SISSR, 0x15, 0x04);
4214 SiS_SetReg(SISSR, 0x13, 0x00);
4215 SiS_SetReg(SISSR, 0x14, 0xBF);
4216
4217 for(i = 0; i < 2; i++) {
4218 temp = 0x1234;
4219 for(j = 0; j < 4; j++) {
4220 writew(temp, FBAddress);
4221 if(readw(FBAddress) == temp)
4222 break;
4223 SiS_SetRegOR(SISSR, 0x3c, 0x01);
4224 reg = SiS_GetReg(SISSR, 0x05);
4225 reg = SiS_GetReg(SISSR, 0x05);
4226 SiS_SetRegAND(SISSR, 0x3c, 0xfe);
4227 reg = SiS_GetReg(SISSR, 0x05);
4228 reg = SiS_GetReg(SISSR, 0x05);
4229 temp++;
4230 }
4231 }
4232
4233 writel(0x01234567L, FBAddress);
4234 writel(0x456789ABL, (FBAddress + 4));
4235 writel(0x89ABCDEFL, (FBAddress + 8));
4236 writel(0xCDEF0123L, (FBAddress + 12));
4237
4238 reg = SiS_GetReg(SISSR, 0x3b);
4239 if(reg & 0x01) {
4240 if(readl((FBAddress + 12)) == 0xCDEF0123L)
4241 return 4; /* Channel A 128bit */
4242 }
4243
4244 if(readl((FBAddress + 4)) == 0x456789ABL)
4245 return 2; /* Channel B 64bit */
4246
4247 return 1; /* 32bit */
4248 }
4249
4250 static const unsigned short SiS_DRAMType[17][5] = {
4251 {0x0C,0x0A,0x02,0x40,0x39},
4252 {0x0D,0x0A,0x01,0x40,0x48},
4253 {0x0C,0x09,0x02,0x20,0x35},
4254 {0x0D,0x09,0x01,0x20,0x44},
4255 {0x0C,0x08,0x02,0x10,0x31},
4256 {0x0D,0x08,0x01,0x10,0x40},
4257 {0x0C,0x0A,0x01,0x20,0x34},
4258 {0x0C,0x09,0x01,0x08,0x32},
4259 {0x0B,0x08,0x02,0x08,0x21},
4260 {0x0C,0x08,0x01,0x08,0x30},
4261 {0x0A,0x08,0x02,0x04,0x11},
4262 {0x0B,0x0A,0x01,0x10,0x28},
4263 {0x09,0x08,0x02,0x02,0x01},
4264 {0x0B,0x09,0x01,0x08,0x24},
4265 {0x0B,0x08,0x01,0x04,0x20},
4266 {0x0A,0x08,0x01,0x02,0x10},
4267 {0x09,0x08,0x01,0x01,0x00}
4268 };
4269
sisfb_post_300_rwtest(struct sis_video_info * ivideo,int iteration,int buswidth,int PseudoRankCapacity,int PseudoAdrPinCount,unsigned int mapsize)4270 static int sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration,
4271 int buswidth, int PseudoRankCapacity,
4272 int PseudoAdrPinCount, unsigned int mapsize)
4273 {
4274 void __iomem *FBAddr = ivideo->video_vbase;
4275 unsigned short sr14;
4276 unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
4277 unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
4278
4279 for(k = 0; k < ARRAY_SIZE(SiS_DRAMType); k++) {
4280
4281 RankCapacity = buswidth * SiS_DRAMType[k][3];
4282
4283 if(RankCapacity != PseudoRankCapacity)
4284 continue;
4285
4286 if((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount)
4287 continue;
4288
4289 BankNumHigh = RankCapacity * 16 * iteration - 1;
4290 if(iteration == 3) { /* Rank No */
4291 BankNumMid = RankCapacity * 16 - 1;
4292 } else {
4293 BankNumMid = RankCapacity * 16 * iteration / 2 - 1;
4294 }
4295
4296 PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
4297 PhysicalAdrHigh = BankNumHigh;
4298 PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
4299 PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
4300
4301 SiS_SetRegAND(SISSR, 0x15, 0xFB); /* Test */
4302 SiS_SetRegOR(SISSR, 0x15, 0x04); /* Test */
4303 sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
4304 if(buswidth == 4) sr14 |= 0x80;
4305 else if(buswidth == 2) sr14 |= 0x40;
4306 SiS_SetReg(SISSR, 0x13, SiS_DRAMType[k][4]);
4307 SiS_SetReg(SISSR, 0x14, sr14);
4308
4309 BankNumHigh <<= 16;
4310 BankNumMid <<= 16;
4311
4312 if((BankNumHigh + PhysicalAdrHigh >= mapsize) ||
4313 (BankNumMid + PhysicalAdrHigh >= mapsize) ||
4314 (BankNumHigh + PhysicalAdrHalfPage >= mapsize) ||
4315 (BankNumHigh + PhysicalAdrOtherPage >= mapsize))
4316 continue;
4317
4318 /* Write data */
4319 writew(((unsigned short)PhysicalAdrHigh),
4320 (FBAddr + BankNumHigh + PhysicalAdrHigh));
4321 writew(((unsigned short)BankNumMid),
4322 (FBAddr + BankNumMid + PhysicalAdrHigh));
4323 writew(((unsigned short)PhysicalAdrHalfPage),
4324 (FBAddr + BankNumHigh + PhysicalAdrHalfPage));
4325 writew(((unsigned short)PhysicalAdrOtherPage),
4326 (FBAddr + BankNumHigh + PhysicalAdrOtherPage));
4327
4328 /* Read data */
4329 if(readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh)
4330 return 1;
4331 }
4332
4333 return 0;
4334 }
4335
sisfb_post_300_ramsize(struct pci_dev * pdev,unsigned int mapsize)4336 static void sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize)
4337 {
4338 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4339 int i, j, buswidth;
4340 int PseudoRankCapacity, PseudoAdrPinCount;
4341
4342 buswidth = sisfb_post_300_buswidth(ivideo);
4343
4344 for(i = 6; i >= 0; i--) {
4345 PseudoRankCapacity = 1 << i;
4346 for(j = 4; j >= 1; j--) {
4347 PseudoAdrPinCount = 15 - j;
4348 if((PseudoRankCapacity * j) <= 64) {
4349 if(sisfb_post_300_rwtest(ivideo,
4350 j,
4351 buswidth,
4352 PseudoRankCapacity,
4353 PseudoAdrPinCount,
4354 mapsize))
4355 return;
4356 }
4357 }
4358 }
4359 }
4360
sisfb_post_sis300(struct pci_dev * pdev)4361 static void sisfb_post_sis300(struct pci_dev *pdev)
4362 {
4363 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4364 unsigned char *bios = ivideo->SiS_Pr.VirtualRomBase;
4365 u8 reg, v1, v2, v3, v4, v5, v6, v7, v8;
4366 u16 index, rindex, memtype = 0;
4367 unsigned int mapsize;
4368
4369 if(!ivideo->SiS_Pr.UseROM)
4370 bios = NULL;
4371
4372 SiS_SetReg(SISSR, 0x05, 0x86);
4373
4374 if(bios) {
4375 if(bios[0x52] & 0x80) {
4376 memtype = bios[0x52];
4377 } else {
4378 memtype = SiS_GetReg(SISSR, 0x3a);
4379 }
4380 memtype &= 0x07;
4381 }
4382
4383 v3 = 0x80; v6 = 0x80;
4384 if(ivideo->revision_id <= 0x13) {
4385 v1 = 0x44; v2 = 0x42;
4386 v4 = 0x44; v5 = 0x42;
4387 } else {
4388 v1 = 0x68; v2 = 0x43; /* Assume 125Mhz MCLK */
4389 v4 = 0x68; v5 = 0x43; /* Assume 125Mhz ECLK */
4390 if(bios) {
4391 index = memtype * 5;
4392 rindex = index + 0x54;
4393 v1 = bios[rindex++];
4394 v2 = bios[rindex++];
4395 v3 = bios[rindex++];
4396 rindex = index + 0x7c;
4397 v4 = bios[rindex++];
4398 v5 = bios[rindex++];
4399 v6 = bios[rindex++];
4400 }
4401 }
4402 SiS_SetReg(SISSR, 0x28, v1);
4403 SiS_SetReg(SISSR, 0x29, v2);
4404 SiS_SetReg(SISSR, 0x2a, v3);
4405 SiS_SetReg(SISSR, 0x2e, v4);
4406 SiS_SetReg(SISSR, 0x2f, v5);
4407 SiS_SetReg(SISSR, 0x30, v6);
4408
4409 v1 = 0x10;
4410 if(bios)
4411 v1 = bios[0xa4];
4412 SiS_SetReg(SISSR, 0x07, v1); /* DAC speed */
4413
4414 SiS_SetReg(SISSR, 0x11, 0x0f); /* DDC, power save */
4415
4416 v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
4417 v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
4418 if(bios) {
4419 memtype += 0xa5;
4420 v1 = bios[memtype];
4421 v2 = bios[memtype + 8];
4422 v3 = bios[memtype + 16];
4423 v4 = bios[memtype + 24];
4424 v5 = bios[memtype + 32];
4425 v6 = bios[memtype + 40];
4426 v7 = bios[memtype + 48];
4427 v8 = bios[memtype + 56];
4428 }
4429 if(ivideo->revision_id >= 0x80)
4430 v3 &= 0xfd;
4431 SiS_SetReg(SISSR, 0x15, v1); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
4432 SiS_SetReg(SISSR, 0x16, v2);
4433 SiS_SetReg(SISSR, 0x17, v3);
4434 SiS_SetReg(SISSR, 0x18, v4);
4435 SiS_SetReg(SISSR, 0x19, v5);
4436 SiS_SetReg(SISSR, 0x1a, v6);
4437 SiS_SetReg(SISSR, 0x1b, v7);
4438 SiS_SetReg(SISSR, 0x1c, v8); /* ---- */
4439 SiS_SetRegAND(SISSR, 0x15, 0xfb);
4440 SiS_SetRegOR(SISSR, 0x15, 0x04);
4441 if(bios) {
4442 if(bios[0x53] & 0x02) {
4443 SiS_SetRegOR(SISSR, 0x19, 0x20);
4444 }
4445 }
4446 v1 = 0x04; /* DAC pedestal (BIOS 0xe5) */
4447 if(ivideo->revision_id >= 0x80)
4448 v1 |= 0x01;
4449 SiS_SetReg(SISSR, 0x1f, v1);
4450 SiS_SetReg(SISSR, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
4451 v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
4452 if(bios) {
4453 v1 = bios[0xe8];
4454 v2 = bios[0xe9];
4455 v3 = bios[0xea];
4456 }
4457 SiS_SetReg(SISSR, 0x23, v1);
4458 SiS_SetReg(SISSR, 0x24, v2);
4459 SiS_SetReg(SISSR, 0x25, v3);
4460 SiS_SetReg(SISSR, 0x21, 0x84);
4461 SiS_SetReg(SISSR, 0x22, 0x00);
4462 SiS_SetReg(SISCR, 0x37, 0x00);
4463 SiS_SetRegOR(SISPART1, 0x24, 0x01); /* unlock crt2 */
4464 SiS_SetReg(SISPART1, 0x00, 0x00);
4465 v1 = 0x40; v2 = 0x11;
4466 if(bios) {
4467 v1 = bios[0xec];
4468 v2 = bios[0xeb];
4469 }
4470 SiS_SetReg(SISPART1, 0x02, v1);
4471
4472 if(ivideo->revision_id >= 0x80)
4473 v2 &= ~0x01;
4474
4475 reg = SiS_GetReg(SISPART4, 0x00);
4476 if((reg == 1) || (reg == 2)) {
4477 SiS_SetReg(SISCR, 0x37, 0x02);
4478 SiS_SetReg(SISPART2, 0x00, 0x1c);
4479 v4 = 0x00; v5 = 0x00; v6 = 0x10;
4480 if(ivideo->SiS_Pr.UseROM) {
4481 v4 = bios[0xf5];
4482 v5 = bios[0xf6];
4483 v6 = bios[0xf7];
4484 }
4485 SiS_SetReg(SISPART4, 0x0d, v4);
4486 SiS_SetReg(SISPART4, 0x0e, v5);
4487 SiS_SetReg(SISPART4, 0x10, v6);
4488 SiS_SetReg(SISPART4, 0x0f, 0x3f);
4489 reg = SiS_GetReg(SISPART4, 0x01);
4490 if(reg >= 0xb0) {
4491 reg = SiS_GetReg(SISPART4, 0x23);
4492 reg &= 0x20;
4493 reg <<= 1;
4494 SiS_SetReg(SISPART4, 0x23, reg);
4495 }
4496 } else {
4497 v2 &= ~0x10;
4498 }
4499 SiS_SetReg(SISSR, 0x32, v2);
4500
4501 SiS_SetRegAND(SISPART1, 0x24, 0xfe); /* Lock CRT2 */
4502
4503 reg = SiS_GetReg(SISSR, 0x16);
4504 reg &= 0xc3;
4505 SiS_SetReg(SISCR, 0x35, reg);
4506 SiS_SetReg(SISCR, 0x83, 0x00);
4507 #if !defined(__i386__) && !defined(__x86_64__)
4508 if(sisfb_videoram) {
4509 SiS_SetReg(SISSR, 0x13, 0x28); /* ? */
4510 reg = ((sisfb_videoram >> 10) - 1) | 0x40;
4511 SiS_SetReg(SISSR, 0x14, reg);
4512 } else {
4513 #endif
4514 /* Need to map max FB size for finding out about RAM size */
4515 mapsize = ivideo->video_size;
4516 sisfb_post_map_vram(ivideo, &mapsize, 4);
4517
4518 if(ivideo->video_vbase) {
4519 sisfb_post_300_ramsize(pdev, mapsize);
4520 iounmap(ivideo->video_vbase);
4521 } else {
4522 printk(KERN_DEBUG
4523 "sisfb: Failed to map memory for size detection, assuming 8MB\n");
4524 SiS_SetReg(SISSR, 0x13, 0x28); /* ? */
4525 SiS_SetReg(SISSR, 0x14, 0x47); /* 8MB, 64bit default */
4526 }
4527 #if !defined(__i386__) && !defined(__x86_64__)
4528 }
4529 #endif
4530 if(bios) {
4531 v1 = bios[0xe6];
4532 v2 = bios[0xe7];
4533 } else {
4534 reg = SiS_GetReg(SISSR, 0x3a);
4535 if((reg & 0x30) == 0x30) {
4536 v1 = 0x04; /* PCI */
4537 v2 = 0x92;
4538 } else {
4539 v1 = 0x14; /* AGP */
4540 v2 = 0xb2;
4541 }
4542 }
4543 SiS_SetReg(SISSR, 0x21, v1);
4544 SiS_SetReg(SISSR, 0x22, v2);
4545
4546 /* Sense CRT1 */
4547 sisfb_sense_crt1(ivideo);
4548
4549 /* Set default mode, don't clear screen */
4550 ivideo->SiS_Pr.SiS_UseOEM = false;
4551 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
4552 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
4553 ivideo->curFSTN = ivideo->curDSTN = 0;
4554 ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
4555 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
4556
4557 SiS_SetReg(SISSR, 0x05, 0x86);
4558
4559 /* Display off */
4560 SiS_SetRegOR(SISSR, 0x01, 0x20);
4561
4562 /* Save mode number in CR34 */
4563 SiS_SetReg(SISCR, 0x34, 0x2e);
4564
4565 /* Let everyone know what the current mode is */
4566 ivideo->modeprechange = 0x2e;
4567 }
4568 #endif
4569
4570 #ifdef CONFIG_FB_SIS_315
4571 #if 0
4572 static void sisfb_post_sis315330(struct pci_dev *pdev)
4573 {
4574 /* TODO */
4575 }
4576 #endif
4577
sisfb_xgi_is21(struct sis_video_info * ivideo)4578 static inline int sisfb_xgi_is21(struct sis_video_info *ivideo)
4579 {
4580 return ivideo->chip_real_id == XGI_21;
4581 }
4582
sisfb_post_xgi_delay(struct sis_video_info * ivideo,int delay)4583 static void sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
4584 {
4585 unsigned int i;
4586 u8 reg;
4587
4588 for(i = 0; i <= (delay * 10 * 36); i++) {
4589 reg = SiS_GetReg(SISSR, 0x05);
4590 reg++;
4591 }
4592 }
4593
sisfb_find_host_bridge(struct sis_video_info * ivideo,struct pci_dev * mypdev,unsigned short pcivendor)4594 static int sisfb_find_host_bridge(struct sis_video_info *ivideo,
4595 struct pci_dev *mypdev,
4596 unsigned short pcivendor)
4597 {
4598 struct pci_dev *pdev = NULL;
4599 unsigned short temp;
4600 int ret = 0;
4601
4602 while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, pdev))) {
4603 temp = pdev->vendor;
4604 if(temp == pcivendor) {
4605 ret = 1;
4606 pci_dev_put(pdev);
4607 break;
4608 }
4609 }
4610
4611 return ret;
4612 }
4613
sisfb_post_xgi_rwtest(struct sis_video_info * ivideo,int starta,unsigned int enda,unsigned int mapsize)4614 static int sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta,
4615 unsigned int enda, unsigned int mapsize)
4616 {
4617 unsigned int pos;
4618 int i;
4619
4620 writel(0, ivideo->video_vbase);
4621
4622 for(i = starta; i <= enda; i++) {
4623 pos = 1 << i;
4624 if(pos < mapsize)
4625 writel(pos, ivideo->video_vbase + pos);
4626 }
4627
4628 sisfb_post_xgi_delay(ivideo, 150);
4629
4630 if(readl(ivideo->video_vbase) != 0)
4631 return 0;
4632
4633 for(i = starta; i <= enda; i++) {
4634 pos = 1 << i;
4635 if(pos < mapsize) {
4636 if(readl(ivideo->video_vbase + pos) != pos)
4637 return 0;
4638 } else
4639 return 0;
4640 }
4641
4642 return 1;
4643 }
4644
sisfb_post_xgi_ramsize(struct sis_video_info * ivideo)4645 static int sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
4646 {
4647 unsigned int buswidth, ranksize, channelab, mapsize;
4648 int i, j, k, l, status;
4649 u8 reg, sr14;
4650 static const u8 dramsr13[12 * 5] = {
4651 0x02, 0x0e, 0x0b, 0x80, 0x5d,
4652 0x02, 0x0e, 0x0a, 0x40, 0x59,
4653 0x02, 0x0d, 0x0b, 0x40, 0x4d,
4654 0x02, 0x0e, 0x09, 0x20, 0x55,
4655 0x02, 0x0d, 0x0a, 0x20, 0x49,
4656 0x02, 0x0c, 0x0b, 0x20, 0x3d,
4657 0x02, 0x0e, 0x08, 0x10, 0x51,
4658 0x02, 0x0d, 0x09, 0x10, 0x45,
4659 0x02, 0x0c, 0x0a, 0x10, 0x39,
4660 0x02, 0x0d, 0x08, 0x08, 0x41,
4661 0x02, 0x0c, 0x09, 0x08, 0x35,
4662 0x02, 0x0c, 0x08, 0x04, 0x31
4663 };
4664 static const u8 dramsr13_4[4 * 5] = {
4665 0x02, 0x0d, 0x09, 0x40, 0x45,
4666 0x02, 0x0c, 0x09, 0x20, 0x35,
4667 0x02, 0x0c, 0x08, 0x10, 0x31,
4668 0x02, 0x0b, 0x08, 0x08, 0x21
4669 };
4670
4671 /* Enable linear mode, disable 0xa0000 address decoding */
4672 /* We disable a0000 address decoding, because
4673 * - if running on x86, if the card is disabled, it means
4674 * that another card is in the system. We don't want
4675 * to interphere with that primary card's textmode.
4676 * - if running on non-x86, there usually is no VGA window
4677 * at a0000.
4678 */
4679 SiS_SetRegOR(SISSR, 0x20, (0x80 | 0x04));
4680
4681 /* Need to map max FB size for finding out about RAM size */
4682 mapsize = ivideo->video_size;
4683 sisfb_post_map_vram(ivideo, &mapsize, 32);
4684
4685 if(!ivideo->video_vbase) {
4686 printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n");
4687 SiS_SetReg(SISSR, 0x13, 0x35);
4688 SiS_SetReg(SISSR, 0x14, 0x41);
4689 /* TODO */
4690 return -ENOMEM;
4691 }
4692
4693 /* Non-interleaving */
4694 SiS_SetReg(SISSR, 0x15, 0x00);
4695 /* No tiling */
4696 SiS_SetReg(SISSR, 0x1c, 0x00);
4697
4698 if(ivideo->chip == XGI_20) {
4699
4700 channelab = 1;
4701 reg = SiS_GetReg(SISCR, 0x97);
4702 if(!(reg & 0x01)) { /* Single 32/16 */
4703 buswidth = 32;
4704 SiS_SetReg(SISSR, 0x13, 0xb1);
4705 SiS_SetReg(SISSR, 0x14, 0x52);
4706 sisfb_post_xgi_delay(ivideo, 1);
4707 sr14 = 0x02;
4708 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4709 goto bail_out;
4710
4711 SiS_SetReg(SISSR, 0x13, 0x31);
4712 SiS_SetReg(SISSR, 0x14, 0x42);
4713 sisfb_post_xgi_delay(ivideo, 1);
4714 if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize))
4715 goto bail_out;
4716
4717 buswidth = 16;
4718 SiS_SetReg(SISSR, 0x13, 0xb1);
4719 SiS_SetReg(SISSR, 0x14, 0x41);
4720 sisfb_post_xgi_delay(ivideo, 1);
4721 sr14 = 0x01;
4722 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4723 goto bail_out;
4724 else
4725 SiS_SetReg(SISSR, 0x13, 0x31);
4726 } else { /* Dual 16/8 */
4727 buswidth = 16;
4728 SiS_SetReg(SISSR, 0x13, 0xb1);
4729 SiS_SetReg(SISSR, 0x14, 0x41);
4730 sisfb_post_xgi_delay(ivideo, 1);
4731 sr14 = 0x01;
4732 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4733 goto bail_out;
4734
4735 SiS_SetReg(SISSR, 0x13, 0x31);
4736 SiS_SetReg(SISSR, 0x14, 0x31);
4737 sisfb_post_xgi_delay(ivideo, 1);
4738 if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize))
4739 goto bail_out;
4740
4741 buswidth = 8;
4742 SiS_SetReg(SISSR, 0x13, 0xb1);
4743 SiS_SetReg(SISSR, 0x14, 0x30);
4744 sisfb_post_xgi_delay(ivideo, 1);
4745 sr14 = 0x00;
4746 if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize))
4747 goto bail_out;
4748 else
4749 SiS_SetReg(SISSR, 0x13, 0x31);
4750 }
4751
4752 } else { /* XGI_40 */
4753
4754 reg = SiS_GetReg(SISCR, 0x97);
4755 if(!(reg & 0x10)) {
4756 reg = SiS_GetReg(SISSR, 0x39);
4757 reg >>= 1;
4758 }
4759
4760 if(reg & 0x01) { /* DDRII */
4761 buswidth = 32;
4762 if(ivideo->revision_id == 2) {
4763 channelab = 2;
4764 SiS_SetReg(SISSR, 0x13, 0xa1);
4765 SiS_SetReg(SISSR, 0x14, 0x44);
4766 sr14 = 0x04;
4767 sisfb_post_xgi_delay(ivideo, 1);
4768 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4769 goto bail_out;
4770
4771 SiS_SetReg(SISSR, 0x13, 0x21);
4772 SiS_SetReg(SISSR, 0x14, 0x34);
4773 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4774 goto bail_out;
4775
4776 channelab = 1;
4777 SiS_SetReg(SISSR, 0x13, 0xa1);
4778 SiS_SetReg(SISSR, 0x14, 0x40);
4779 sr14 = 0x00;
4780 if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
4781 goto bail_out;
4782
4783 SiS_SetReg(SISSR, 0x13, 0x21);
4784 SiS_SetReg(SISSR, 0x14, 0x30);
4785 } else {
4786 channelab = 3;
4787 SiS_SetReg(SISSR, 0x13, 0xa1);
4788 SiS_SetReg(SISSR, 0x14, 0x4c);
4789 sr14 = 0x0c;
4790 sisfb_post_xgi_delay(ivideo, 1);
4791 if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize))
4792 goto bail_out;
4793
4794 channelab = 2;
4795 SiS_SetReg(SISSR, 0x14, 0x48);
4796 sisfb_post_xgi_delay(ivideo, 1);
4797 sr14 = 0x08;
4798 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4799 goto bail_out;
4800
4801 SiS_SetReg(SISSR, 0x13, 0x21);
4802 SiS_SetReg(SISSR, 0x14, 0x3c);
4803 sr14 = 0x0c;
4804
4805 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) {
4806 channelab = 3;
4807 } else {
4808 channelab = 2;
4809 SiS_SetReg(SISSR, 0x14, 0x38);
4810 sr14 = 0x08;
4811 }
4812 }
4813 sisfb_post_xgi_delay(ivideo, 1);
4814
4815 } else { /* DDR */
4816
4817 buswidth = 64;
4818 if(ivideo->revision_id == 2) {
4819 channelab = 1;
4820 SiS_SetReg(SISSR, 0x13, 0xa1);
4821 SiS_SetReg(SISSR, 0x14, 0x52);
4822 sisfb_post_xgi_delay(ivideo, 1);
4823 sr14 = 0x02;
4824 if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
4825 goto bail_out;
4826
4827 SiS_SetReg(SISSR, 0x13, 0x21);
4828 SiS_SetReg(SISSR, 0x14, 0x42);
4829 } else {
4830 channelab = 2;
4831 SiS_SetReg(SISSR, 0x13, 0xa1);
4832 SiS_SetReg(SISSR, 0x14, 0x5a);
4833 sisfb_post_xgi_delay(ivideo, 1);
4834 sr14 = 0x0a;
4835 if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize))
4836 goto bail_out;
4837
4838 SiS_SetReg(SISSR, 0x13, 0x21);
4839 SiS_SetReg(SISSR, 0x14, 0x4a);
4840 }
4841 sisfb_post_xgi_delay(ivideo, 1);
4842
4843 }
4844 }
4845
4846 bail_out:
4847 SiS_SetRegANDOR(SISSR, 0x14, 0xf0, sr14);
4848 sisfb_post_xgi_delay(ivideo, 1);
4849
4850 j = (ivideo->chip == XGI_20) ? 5 : 9;
4851 k = (ivideo->chip == XGI_20) ? 12 : 4;
4852 status = -EIO;
4853
4854 for(i = 0; i < k; i++) {
4855
4856 reg = (ivideo->chip == XGI_20) ?
4857 dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4];
4858 SiS_SetRegANDOR(SISSR, 0x13, 0x80, reg);
4859 sisfb_post_xgi_delay(ivideo, 50);
4860
4861 ranksize = (ivideo->chip == XGI_20) ?
4862 dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3];
4863
4864 reg = SiS_GetReg(SISSR, 0x13);
4865 if(reg & 0x80) ranksize <<= 1;
4866
4867 if(ivideo->chip == XGI_20) {
4868 if(buswidth == 16) ranksize <<= 1;
4869 else if(buswidth == 32) ranksize <<= 2;
4870 } else {
4871 if(buswidth == 64) ranksize <<= 1;
4872 }
4873
4874 reg = 0;
4875 l = channelab;
4876 if(l == 3) l = 4;
4877 if((ranksize * l) <= 256) {
4878 while((ranksize >>= 1)) reg += 0x10;
4879 }
4880
4881 if(!reg) continue;
4882
4883 SiS_SetRegANDOR(SISSR, 0x14, 0x0f, (reg & 0xf0));
4884 sisfb_post_xgi_delay(ivideo, 1);
4885
4886 if (sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize)) {
4887 status = 0;
4888 break;
4889 }
4890 }
4891
4892 iounmap(ivideo->video_vbase);
4893
4894 return status;
4895 }
4896
sisfb_post_xgi_setclocks(struct sis_video_info * ivideo,u8 regb)4897 static void sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
4898 {
4899 u8 v1, v2, v3;
4900 int index;
4901 static const u8 cs90[8 * 3] = {
4902 0x16, 0x01, 0x01,
4903 0x3e, 0x03, 0x01,
4904 0x7c, 0x08, 0x01,
4905 0x79, 0x06, 0x01,
4906 0x29, 0x01, 0x81,
4907 0x5c, 0x23, 0x01,
4908 0x5c, 0x23, 0x01,
4909 0x5c, 0x23, 0x01
4910 };
4911 static const u8 csb8[8 * 3] = {
4912 0x5c, 0x23, 0x01,
4913 0x29, 0x01, 0x01,
4914 0x7c, 0x08, 0x01,
4915 0x79, 0x06, 0x01,
4916 0x29, 0x01, 0x81,
4917 0x5c, 0x23, 0x01,
4918 0x5c, 0x23, 0x01,
4919 0x5c, 0x23, 0x01
4920 };
4921
4922 regb = 0; /* ! */
4923
4924 index = regb * 3;
4925 v1 = cs90[index]; v2 = cs90[index + 1]; v3 = cs90[index + 2];
4926 if(ivideo->haveXGIROM) {
4927 v1 = ivideo->bios_abase[0x90 + index];
4928 v2 = ivideo->bios_abase[0x90 + index + 1];
4929 v3 = ivideo->bios_abase[0x90 + index + 2];
4930 }
4931 SiS_SetReg(SISSR, 0x28, v1);
4932 SiS_SetReg(SISSR, 0x29, v2);
4933 SiS_SetReg(SISSR, 0x2a, v3);
4934 sisfb_post_xgi_delay(ivideo, 0x43);
4935 sisfb_post_xgi_delay(ivideo, 0x43);
4936 sisfb_post_xgi_delay(ivideo, 0x43);
4937 index = regb * 3;
4938 v1 = csb8[index]; v2 = csb8[index + 1]; v3 = csb8[index + 2];
4939 if(ivideo->haveXGIROM) {
4940 v1 = ivideo->bios_abase[0xb8 + index];
4941 v2 = ivideo->bios_abase[0xb8 + index + 1];
4942 v3 = ivideo->bios_abase[0xb8 + index + 2];
4943 }
4944 SiS_SetReg(SISSR, 0x2e, v1);
4945 SiS_SetReg(SISSR, 0x2f, v2);
4946 SiS_SetReg(SISSR, 0x30, v3);
4947 sisfb_post_xgi_delay(ivideo, 0x43);
4948 sisfb_post_xgi_delay(ivideo, 0x43);
4949 sisfb_post_xgi_delay(ivideo, 0x43);
4950 }
4951
sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info * ivideo,u8 regb)4952 static void sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info *ivideo,
4953 u8 regb)
4954 {
4955 unsigned char *bios = ivideo->bios_abase;
4956 u8 v1;
4957
4958 SiS_SetReg(SISSR, 0x28, 0x64);
4959 SiS_SetReg(SISSR, 0x29, 0x63);
4960 sisfb_post_xgi_delay(ivideo, 15);
4961 SiS_SetReg(SISSR, 0x18, 0x00);
4962 SiS_SetReg(SISSR, 0x19, 0x20);
4963 SiS_SetReg(SISSR, 0x16, 0x00);
4964 SiS_SetReg(SISSR, 0x16, 0x80);
4965 SiS_SetReg(SISSR, 0x18, 0xc5);
4966 SiS_SetReg(SISSR, 0x19, 0x23);
4967 SiS_SetReg(SISSR, 0x16, 0x00);
4968 SiS_SetReg(SISSR, 0x16, 0x80);
4969 sisfb_post_xgi_delay(ivideo, 1);
4970 SiS_SetReg(SISCR, 0x97, 0x11);
4971 sisfb_post_xgi_setclocks(ivideo, regb);
4972 sisfb_post_xgi_delay(ivideo, 0x46);
4973 SiS_SetReg(SISSR, 0x18, 0xc5);
4974 SiS_SetReg(SISSR, 0x19, 0x23);
4975 SiS_SetReg(SISSR, 0x16, 0x00);
4976 SiS_SetReg(SISSR, 0x16, 0x80);
4977 sisfb_post_xgi_delay(ivideo, 1);
4978 SiS_SetReg(SISSR, 0x1b, 0x04);
4979 sisfb_post_xgi_delay(ivideo, 1);
4980 SiS_SetReg(SISSR, 0x1b, 0x00);
4981 sisfb_post_xgi_delay(ivideo, 1);
4982 v1 = 0x31;
4983 if (ivideo->haveXGIROM) {
4984 v1 = bios[0xf0];
4985 }
4986 SiS_SetReg(SISSR, 0x18, v1);
4987 SiS_SetReg(SISSR, 0x19, 0x06);
4988 SiS_SetReg(SISSR, 0x16, 0x04);
4989 SiS_SetReg(SISSR, 0x16, 0x84);
4990 sisfb_post_xgi_delay(ivideo, 1);
4991 }
4992
sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info * ivideo)4993 static void sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info *ivideo)
4994 {
4995 sisfb_post_xgi_setclocks(ivideo, 1);
4996
4997 SiS_SetReg(SISCR, 0x97, 0x11);
4998 sisfb_post_xgi_delay(ivideo, 0x46);
4999
5000 SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS2 */
5001 SiS_SetReg(SISSR, 0x19, 0x80);
5002 SiS_SetReg(SISSR, 0x16, 0x05);
5003 SiS_SetReg(SISSR, 0x16, 0x85);
5004
5005 SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS3 */
5006 SiS_SetReg(SISSR, 0x19, 0xc0);
5007 SiS_SetReg(SISSR, 0x16, 0x05);
5008 SiS_SetReg(SISSR, 0x16, 0x85);
5009
5010 SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS1 */
5011 SiS_SetReg(SISSR, 0x19, 0x40);
5012 SiS_SetReg(SISSR, 0x16, 0x05);
5013 SiS_SetReg(SISSR, 0x16, 0x85);
5014
5015 SiS_SetReg(SISSR, 0x18, 0x42); /* MRS1 */
5016 SiS_SetReg(SISSR, 0x19, 0x02);
5017 SiS_SetReg(SISSR, 0x16, 0x05);
5018 SiS_SetReg(SISSR, 0x16, 0x85);
5019 sisfb_post_xgi_delay(ivideo, 1);
5020
5021 SiS_SetReg(SISSR, 0x1b, 0x04);
5022 sisfb_post_xgi_delay(ivideo, 1);
5023
5024 SiS_SetReg(SISSR, 0x1b, 0x00);
5025 sisfb_post_xgi_delay(ivideo, 1);
5026
5027 SiS_SetReg(SISSR, 0x18, 0x42); /* MRS1 */
5028 SiS_SetReg(SISSR, 0x19, 0x00);
5029 SiS_SetReg(SISSR, 0x16, 0x05);
5030 SiS_SetReg(SISSR, 0x16, 0x85);
5031 sisfb_post_xgi_delay(ivideo, 1);
5032 }
5033
sisfb_post_xgi_ddr2(struct sis_video_info * ivideo,u8 regb)5034 static void sisfb_post_xgi_ddr2(struct sis_video_info *ivideo, u8 regb)
5035 {
5036 unsigned char *bios = ivideo->bios_abase;
5037 static const u8 cs158[8] = {
5038 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5039 };
5040 static const u8 cs160[8] = {
5041 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5042 };
5043 static const u8 cs168[8] = {
5044 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5045 };
5046 u8 reg;
5047 u8 v1;
5048 u8 v2;
5049 u8 v3;
5050
5051 SiS_SetReg(SISCR, 0xb0, 0x80); /* DDR2 dual frequency mode */
5052 SiS_SetReg(SISCR, 0x82, 0x77);
5053 SiS_SetReg(SISCR, 0x86, 0x00);
5054 reg = SiS_GetReg(SISCR, 0x86);
5055 SiS_SetReg(SISCR, 0x86, 0x88);
5056 reg = SiS_GetReg(SISCR, 0x86);
5057 v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
5058 if (ivideo->haveXGIROM) {
5059 v1 = bios[regb + 0x168];
5060 v2 = bios[regb + 0x160];
5061 v3 = bios[regb + 0x158];
5062 }
5063 SiS_SetReg(SISCR, 0x86, v1);
5064 SiS_SetReg(SISCR, 0x82, 0x77);
5065 SiS_SetReg(SISCR, 0x85, 0x00);
5066 reg = SiS_GetReg(SISCR, 0x85);
5067 SiS_SetReg(SISCR, 0x85, 0x88);
5068 reg = SiS_GetReg(SISCR, 0x85);
5069 SiS_SetReg(SISCR, 0x85, v2);
5070 SiS_SetReg(SISCR, 0x82, v3);
5071 SiS_SetReg(SISCR, 0x98, 0x01);
5072 SiS_SetReg(SISCR, 0x9a, 0x02);
5073 if (sisfb_xgi_is21(ivideo))
5074 sisfb_post_xgi_ddr2_mrs_xg21(ivideo);
5075 else
5076 sisfb_post_xgi_ddr2_mrs_default(ivideo, regb);
5077 }
5078
sisfb_post_xgi_ramtype(struct sis_video_info * ivideo)5079 static u8 sisfb_post_xgi_ramtype(struct sis_video_info *ivideo)
5080 {
5081 unsigned char *bios = ivideo->bios_abase;
5082 u8 ramtype;
5083 u8 reg;
5084 u8 v1;
5085
5086 ramtype = 0x00; v1 = 0x10;
5087 if (ivideo->haveXGIROM) {
5088 ramtype = bios[0x62];
5089 v1 = bios[0x1d2];
5090 }
5091 if (!(ramtype & 0x80)) {
5092 if (sisfb_xgi_is21(ivideo)) {
5093 SiS_SetRegAND(SISCR, 0xb4, 0xfd); /* GPIO control */
5094 SiS_SetRegOR(SISCR, 0x4a, 0x80); /* GPIOH EN */
5095 reg = SiS_GetReg(SISCR, 0x48);
5096 SiS_SetRegOR(SISCR, 0xb4, 0x02);
5097 ramtype = reg & 0x01; /* GPIOH */
5098 } else if (ivideo->chip == XGI_20) {
5099 SiS_SetReg(SISCR, 0x97, v1);
5100 reg = SiS_GetReg(SISCR, 0x97);
5101 if (reg & 0x10) {
5102 ramtype = (reg & 0x01) << 1;
5103 }
5104 } else {
5105 reg = SiS_GetReg(SISSR, 0x39);
5106 ramtype = reg & 0x02;
5107 if (!(ramtype)) {
5108 reg = SiS_GetReg(SISSR, 0x3a);
5109 ramtype = (reg >> 1) & 0x01;
5110 }
5111 }
5112 }
5113 ramtype &= 0x07;
5114
5115 return ramtype;
5116 }
5117
sisfb_post_xgi(struct pci_dev * pdev)5118 static int sisfb_post_xgi(struct pci_dev *pdev)
5119 {
5120 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
5121 unsigned char *bios = ivideo->bios_abase;
5122 struct pci_dev *mypdev = NULL;
5123 const u8 *ptr, *ptr2;
5124 u8 v1, v2, v3, v4, v5, reg, ramtype;
5125 u32 rega, regb, regd;
5126 int i, j, k, index;
5127 static const u8 cs78[3] = { 0xf6, 0x0d, 0x00 };
5128 static const u8 cs76[2] = { 0xa3, 0xfb };
5129 static const u8 cs7b[3] = { 0xc0, 0x11, 0x00 };
5130 static const u8 cs158[8] = {
5131 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5132 };
5133 static const u8 cs160[8] = {
5134 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5135 };
5136 static const u8 cs168[8] = {
5137 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5138 };
5139 static const u8 cs128[3 * 8] = {
5140 0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
5141 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5142 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
5143 };
5144 static const u8 cs148[2 * 8] = {
5145 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
5146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5147 };
5148 static const u8 cs31a[8 * 4] = {
5149 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
5150 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
5151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5152 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5153 };
5154 static const u8 cs33a[8 * 4] = {
5155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5157 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5159 };
5160 static const u8 cs45a[8 * 2] = {
5161 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
5162 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5163 };
5164 static const u8 cs170[7 * 8] = {
5165 0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5166 0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5167 0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
5168 0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5169 0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
5170 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
5171 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
5172 };
5173 static const u8 cs1a8[3 * 8] = {
5174 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
5175 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
5176 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5177 };
5178 static const u8 cs100[2 * 8] = {
5179 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
5180 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
5181 };
5182
5183 /* VGA enable */
5184 reg = SiS_GetRegByte(SISVGAENABLE) | 0x01;
5185 SiS_SetRegByte(SISVGAENABLE, reg);
5186
5187 /* Misc */
5188 reg = SiS_GetRegByte(SISMISCR) | 0x01;
5189 SiS_SetRegByte(SISMISCW, reg);
5190
5191 /* Unlock SR */
5192 SiS_SetReg(SISSR, 0x05, 0x86);
5193 reg = SiS_GetReg(SISSR, 0x05);
5194 if(reg != 0xa1)
5195 return 0;
5196
5197 /* Clear some regs */
5198 for(i = 0; i < 0x22; i++) {
5199 if(0x06 + i == 0x20) continue;
5200 SiS_SetReg(SISSR, 0x06 + i, 0x00);
5201 }
5202 for(i = 0; i < 0x0b; i++) {
5203 SiS_SetReg(SISSR, 0x31 + i, 0x00);
5204 }
5205 for(i = 0; i < 0x10; i++) {
5206 SiS_SetReg(SISCR, 0x30 + i, 0x00);
5207 }
5208
5209 ptr = cs78;
5210 if(ivideo->haveXGIROM) {
5211 ptr = (const u8 *)&bios[0x78];
5212 }
5213 for(i = 0; i < 3; i++) {
5214 SiS_SetReg(SISSR, 0x23 + i, ptr[i]);
5215 }
5216
5217 ptr = cs76;
5218 if(ivideo->haveXGIROM) {
5219 ptr = (const u8 *)&bios[0x76];
5220 }
5221 for(i = 0; i < 2; i++) {
5222 SiS_SetReg(SISSR, 0x21 + i, ptr[i]);
5223 }
5224
5225 v1 = 0x18; v2 = 0x00;
5226 if(ivideo->haveXGIROM) {
5227 v1 = bios[0x74];
5228 v2 = bios[0x75];
5229 }
5230 SiS_SetReg(SISSR, 0x07, v1);
5231 SiS_SetReg(SISSR, 0x11, 0x0f);
5232 SiS_SetReg(SISSR, 0x1f, v2);
5233 /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
5234 SiS_SetReg(SISSR, 0x20, 0x80 | 0x20 | 0x04);
5235 SiS_SetReg(SISSR, 0x27, 0x74);
5236
5237 ptr = cs7b;
5238 if(ivideo->haveXGIROM) {
5239 ptr = (const u8 *)&bios[0x7b];
5240 }
5241 for(i = 0; i < 3; i++) {
5242 SiS_SetReg(SISSR, 0x31 + i, ptr[i]);
5243 }
5244
5245 if(ivideo->chip == XGI_40) {
5246 if(ivideo->revision_id == 2) {
5247 SiS_SetRegANDOR(SISSR, 0x3b, 0x3f, 0xc0);
5248 }
5249 SiS_SetReg(SISCR, 0x7d, 0xfe);
5250 SiS_SetReg(SISCR, 0x7e, 0x0f);
5251 }
5252 if(ivideo->revision_id == 0) { /* 40 *and* 20? */
5253 SiS_SetRegAND(SISCR, 0x58, 0xd7);
5254 reg = SiS_GetReg(SISCR, 0xcb);
5255 if(reg & 0x20) {
5256 SiS_SetRegANDOR(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
5257 }
5258 }
5259
5260 reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00;
5261 SiS_SetRegANDOR(SISCR, 0x38, 0x1f, reg);
5262
5263 if(ivideo->chip == XGI_20) {
5264 SiS_SetReg(SISSR, 0x36, 0x70);
5265 } else {
5266 SiS_SetReg(SISVID, 0x00, 0x86);
5267 SiS_SetReg(SISVID, 0x32, 0x00);
5268 SiS_SetReg(SISVID, 0x30, 0x00);
5269 SiS_SetReg(SISVID, 0x32, 0x01);
5270 SiS_SetReg(SISVID, 0x30, 0x00);
5271 SiS_SetRegAND(SISVID, 0x2f, 0xdf);
5272 SiS_SetRegAND(SISCAP, 0x00, 0x3f);
5273
5274 SiS_SetReg(SISPART1, 0x2f, 0x01);
5275 SiS_SetReg(SISPART1, 0x00, 0x00);
5276 SiS_SetReg(SISPART1, 0x02, bios[0x7e]);
5277 SiS_SetReg(SISPART1, 0x2e, 0x08);
5278 SiS_SetRegAND(SISPART1, 0x35, 0x7f);
5279 SiS_SetRegAND(SISPART1, 0x50, 0xfe);
5280
5281 reg = SiS_GetReg(SISPART4, 0x00);
5282 if(reg == 1 || reg == 2) {
5283 SiS_SetReg(SISPART2, 0x00, 0x1c);
5284 SiS_SetReg(SISPART4, 0x0d, bios[0x7f]);
5285 SiS_SetReg(SISPART4, 0x0e, bios[0x80]);
5286 SiS_SetReg(SISPART4, 0x10, bios[0x81]);
5287 SiS_SetRegAND(SISPART4, 0x0f, 0x3f);
5288
5289 reg = SiS_GetReg(SISPART4, 0x01);
5290 if((reg & 0xf0) >= 0xb0) {
5291 reg = SiS_GetReg(SISPART4, 0x23);
5292 if(reg & 0x20) reg |= 0x40;
5293 SiS_SetReg(SISPART4, 0x23, reg);
5294 reg = (reg & 0x20) ? 0x02 : 0x00;
5295 SiS_SetRegANDOR(SISPART1, 0x1e, 0xfd, reg);
5296 }
5297 }
5298
5299 v1 = bios[0x77];
5300
5301 reg = SiS_GetReg(SISSR, 0x3b);
5302 if(reg & 0x02) {
5303 reg = SiS_GetReg(SISSR, 0x3a);
5304 v2 = (reg & 0x30) >> 3;
5305 if(!(v2 & 0x04)) v2 ^= 0x02;
5306 reg = SiS_GetReg(SISSR, 0x39);
5307 if(reg & 0x80) v2 |= 0x80;
5308 v2 |= 0x01;
5309
5310 if((mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0730, NULL))) {
5311 pci_dev_put(mypdev);
5312 if(((v2 & 0x06) == 2) || ((v2 & 0x06) == 4))
5313 v2 &= 0xf9;
5314 v2 |= 0x08;
5315 v1 &= 0xfe;
5316 } else {
5317 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0735, NULL);
5318 if(!mypdev)
5319 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0645, NULL);
5320 if(!mypdev)
5321 mypdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0650, NULL);
5322 if(mypdev) {
5323 pci_read_config_dword(mypdev, 0x94, ®d);
5324 regd &= 0xfffffeff;
5325 pci_write_config_dword(mypdev, 0x94, regd);
5326 v1 &= 0xfe;
5327 pci_dev_put(mypdev);
5328 } else if(sisfb_find_host_bridge(ivideo, pdev, PCI_VENDOR_ID_SI)) {
5329 v1 &= 0xfe;
5330 } else if(sisfb_find_host_bridge(ivideo, pdev, 0x1106) ||
5331 sisfb_find_host_bridge(ivideo, pdev, 0x1022) ||
5332 sisfb_find_host_bridge(ivideo, pdev, 0x700e) ||
5333 sisfb_find_host_bridge(ivideo, pdev, 0x10de)) {
5334 if((v2 & 0x06) == 4)
5335 v2 ^= 0x06;
5336 v2 |= 0x08;
5337 }
5338 }
5339 SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, v2);
5340 }
5341 SiS_SetReg(SISSR, 0x22, v1);
5342
5343 if(ivideo->revision_id == 2) {
5344 v1 = SiS_GetReg(SISSR, 0x3b);
5345 v2 = SiS_GetReg(SISSR, 0x3a);
5346 regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8);
5347 if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) )
5348 SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
5349
5350 if((mypdev = pci_get_device(0x10de, 0x01e0, NULL))) {
5351 /* TODO: set CR5f &0xf1 | 0x01 for version 6570
5352 * of nforce 2 ROM
5353 */
5354 if(0)
5355 SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
5356 pci_dev_put(mypdev);
5357 }
5358 }
5359
5360 v1 = 0x30;
5361 reg = SiS_GetReg(SISSR, 0x3b);
5362 v2 = SiS_GetReg(SISCR, 0x5f);
5363 if((!(reg & 0x02)) && (v2 & 0x0e))
5364 v1 |= 0x08;
5365 SiS_SetReg(SISSR, 0x27, v1);
5366
5367 if(bios[0x64] & 0x01) {
5368 SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, bios[0x64]);
5369 }
5370
5371 v1 = bios[0x4f7];
5372 pci_read_config_dword(pdev, 0x50, ®d);
5373 regd = (regd >> 20) & 0x0f;
5374 if(regd == 1) {
5375 v1 &= 0xfc;
5376 SiS_SetRegOR(SISCR, 0x5f, 0x08);
5377 }
5378 SiS_SetReg(SISCR, 0x48, v1);
5379
5380 SiS_SetRegANDOR(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb);
5381 SiS_SetRegANDOR(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f);
5382 SiS_SetRegANDOR(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f);
5383 SiS_SetRegANDOR(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7);
5384 SiS_SetRegANDOR(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f);
5385 SiS_SetReg(SISCR, 0x70, bios[0x4fc]);
5386 SiS_SetRegANDOR(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f);
5387 SiS_SetReg(SISCR, 0x74, 0xd0);
5388 SiS_SetRegANDOR(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30);
5389 SiS_SetRegANDOR(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
5390 SiS_SetRegANDOR(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
5391 v1 = bios[0x501];
5392 if((mypdev = pci_get_device(0x8086, 0x2530, NULL))) {
5393 v1 = 0xf0;
5394 pci_dev_put(mypdev);
5395 }
5396 SiS_SetReg(SISCR, 0x77, v1);
5397 }
5398
5399 /* RAM type:
5400 *
5401 * 0 == DDR1, 1 == DDR2, 2..7 == reserved?
5402 *
5403 * The code seems to written so that regb should equal ramtype,
5404 * however, so far it has been hardcoded to 0. Enable other values only
5405 * on XGI Z9, as it passes the POST, and add a warning for others.
5406 */
5407 ramtype = sisfb_post_xgi_ramtype(ivideo);
5408 if (!sisfb_xgi_is21(ivideo) && ramtype) {
5409 dev_warn(&pdev->dev,
5410 "RAM type something else than expected: %d\n",
5411 ramtype);
5412 regb = 0;
5413 } else {
5414 regb = ramtype;
5415 }
5416
5417 v1 = 0xff;
5418 if(ivideo->haveXGIROM) {
5419 v1 = bios[0x140 + regb];
5420 }
5421 SiS_SetReg(SISCR, 0x6d, v1);
5422
5423 ptr = cs128;
5424 if(ivideo->haveXGIROM) {
5425 ptr = (const u8 *)&bios[0x128];
5426 }
5427 for(i = 0, j = 0; i < 3; i++, j += 8) {
5428 SiS_SetReg(SISCR, 0x68 + i, ptr[j + regb]);
5429 }
5430
5431 ptr = cs31a;
5432 ptr2 = cs33a;
5433 if(ivideo->haveXGIROM) {
5434 index = (ivideo->chip == XGI_20) ? 0x31a : 0x3a6;
5435 ptr = (const u8 *)&bios[index];
5436 ptr2 = (const u8 *)&bios[index + 0x20];
5437 }
5438 for(i = 0; i < 2; i++) {
5439 if(i == 0) {
5440 regd = le32_to_cpu(((u32 *)ptr)[regb]);
5441 rega = 0x6b;
5442 } else {
5443 regd = le32_to_cpu(((u32 *)ptr2)[regb]);
5444 rega = 0x6e;
5445 }
5446 reg = 0x00;
5447 for(j = 0; j < 16; j++) {
5448 reg &= 0xf3;
5449 if(regd & 0x01) reg |= 0x04;
5450 if(regd & 0x02) reg |= 0x08;
5451 regd >>= 2;
5452 SiS_SetReg(SISCR, rega, reg);
5453 reg = SiS_GetReg(SISCR, rega);
5454 reg = SiS_GetReg(SISCR, rega);
5455 reg += 0x10;
5456 }
5457 }
5458
5459 SiS_SetRegAND(SISCR, 0x6e, 0xfc);
5460
5461 ptr = NULL;
5462 if(ivideo->haveXGIROM) {
5463 index = (ivideo->chip == XGI_20) ? 0x35a : 0x3e6;
5464 ptr = (const u8 *)&bios[index];
5465 }
5466 for(i = 0; i < 4; i++) {
5467 SiS_SetRegANDOR(SISCR, 0x6e, 0xfc, i);
5468 reg = 0x00;
5469 for(j = 0; j < 2; j++) {
5470 regd = 0;
5471 if(ptr) {
5472 regd = le32_to_cpu(((u32 *)ptr)[regb * 8]);
5473 ptr += 4;
5474 }
5475 /* reg = 0x00; */
5476 for(k = 0; k < 16; k++) {
5477 reg &= 0xfc;
5478 if(regd & 0x01) reg |= 0x01;
5479 if(regd & 0x02) reg |= 0x02;
5480 regd >>= 2;
5481 SiS_SetReg(SISCR, 0x6f, reg);
5482 reg = SiS_GetReg(SISCR, 0x6f);
5483 reg = SiS_GetReg(SISCR, 0x6f);
5484 reg += 0x08;
5485 }
5486 }
5487 }
5488
5489 ptr = cs148;
5490 if(ivideo->haveXGIROM) {
5491 ptr = (const u8 *)&bios[0x148];
5492 }
5493 for(i = 0, j = 0; i < 2; i++, j += 8) {
5494 SiS_SetReg(SISCR, 0x80 + i, ptr[j + regb]);
5495 }
5496
5497 SiS_SetRegAND(SISCR, 0x89, 0x8f);
5498
5499 ptr = cs45a;
5500 if(ivideo->haveXGIROM) {
5501 index = (ivideo->chip == XGI_20) ? 0x45a : 0x4e6;
5502 ptr = (const u8 *)&bios[index];
5503 }
5504 regd = le16_to_cpu(((const u16 *)ptr)[regb]);
5505 reg = 0x80;
5506 for(i = 0; i < 5; i++) {
5507 reg &= 0xfc;
5508 if(regd & 0x01) reg |= 0x01;
5509 if(regd & 0x02) reg |= 0x02;
5510 regd >>= 2;
5511 SiS_SetReg(SISCR, 0x89, reg);
5512 reg = SiS_GetReg(SISCR, 0x89);
5513 reg = SiS_GetReg(SISCR, 0x89);
5514 reg += 0x10;
5515 }
5516
5517 v1 = 0xb5; v2 = 0x20; v3 = 0xf0; v4 = 0x13;
5518 if(ivideo->haveXGIROM) {
5519 v1 = bios[0x118 + regb];
5520 v2 = bios[0xf8 + regb];
5521 v3 = bios[0x120 + regb];
5522 v4 = bios[0x1ca];
5523 }
5524 SiS_SetReg(SISCR, 0x45, v1 & 0x0f);
5525 SiS_SetReg(SISCR, 0x99, (v1 >> 4) & 0x07);
5526 SiS_SetRegOR(SISCR, 0x40, v1 & 0x80);
5527 SiS_SetReg(SISCR, 0x41, v2);
5528
5529 ptr = cs170;
5530 if(ivideo->haveXGIROM) {
5531 ptr = (const u8 *)&bios[0x170];
5532 }
5533 for(i = 0, j = 0; i < 7; i++, j += 8) {
5534 SiS_SetReg(SISCR, 0x90 + i, ptr[j + regb]);
5535 }
5536
5537 SiS_SetReg(SISCR, 0x59, v3);
5538
5539 ptr = cs1a8;
5540 if(ivideo->haveXGIROM) {
5541 ptr = (const u8 *)&bios[0x1a8];
5542 }
5543 for(i = 0, j = 0; i < 3; i++, j += 8) {
5544 SiS_SetReg(SISCR, 0xc3 + i, ptr[j + regb]);
5545 }
5546
5547 ptr = cs100;
5548 if(ivideo->haveXGIROM) {
5549 ptr = (const u8 *)&bios[0x100];
5550 }
5551 for(i = 0, j = 0; i < 2; i++, j += 8) {
5552 SiS_SetReg(SISCR, 0x8a + i, ptr[j + regb]);
5553 }
5554
5555 SiS_SetReg(SISCR, 0xcf, v4);
5556
5557 SiS_SetReg(SISCR, 0x83, 0x09);
5558 SiS_SetReg(SISCR, 0x87, 0x00);
5559
5560 if(ivideo->chip == XGI_40) {
5561 if( (ivideo->revision_id == 1) ||
5562 (ivideo->revision_id == 2) ) {
5563 SiS_SetReg(SISCR, 0x8c, 0x87);
5564 }
5565 }
5566
5567 if (regb == 1)
5568 SiS_SetReg(SISSR, 0x17, 0x80); /* DDR2 */
5569 else
5570 SiS_SetReg(SISSR, 0x17, 0x00); /* DDR1 */
5571 SiS_SetReg(SISSR, 0x1a, 0x87);
5572
5573 if(ivideo->chip == XGI_20) {
5574 SiS_SetReg(SISSR, 0x15, 0x00);
5575 SiS_SetReg(SISSR, 0x1c, 0x00);
5576 }
5577
5578 switch(ramtype) {
5579 case 0:
5580 sisfb_post_xgi_setclocks(ivideo, regb);
5581 if((ivideo->chip == XGI_20) ||
5582 (ivideo->revision_id == 1) ||
5583 (ivideo->revision_id == 2)) {
5584 v1 = cs158[regb]; v2 = cs160[regb]; v3 = cs168[regb];
5585 if(ivideo->haveXGIROM) {
5586 v1 = bios[regb + 0x158];
5587 v2 = bios[regb + 0x160];
5588 v3 = bios[regb + 0x168];
5589 }
5590 SiS_SetReg(SISCR, 0x82, v1);
5591 SiS_SetReg(SISCR, 0x85, v2);
5592 SiS_SetReg(SISCR, 0x86, v3);
5593 } else {
5594 SiS_SetReg(SISCR, 0x82, 0x88);
5595 SiS_SetReg(SISCR, 0x86, 0x00);
5596 reg = SiS_GetReg(SISCR, 0x86);
5597 SiS_SetReg(SISCR, 0x86, 0x88);
5598 reg = SiS_GetReg(SISCR, 0x86);
5599 SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
5600 SiS_SetReg(SISCR, 0x82, 0x77);
5601 SiS_SetReg(SISCR, 0x85, 0x00);
5602 reg = SiS_GetReg(SISCR, 0x85);
5603 SiS_SetReg(SISCR, 0x85, 0x88);
5604 reg = SiS_GetReg(SISCR, 0x85);
5605 SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
5606 SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
5607 }
5608 if(ivideo->chip == XGI_40) {
5609 SiS_SetReg(SISCR, 0x97, 0x00);
5610 }
5611 SiS_SetReg(SISCR, 0x98, 0x01);
5612 SiS_SetReg(SISCR, 0x9a, 0x02);
5613
5614 SiS_SetReg(SISSR, 0x18, 0x01);
5615 if((ivideo->chip == XGI_20) ||
5616 (ivideo->revision_id == 2)) {
5617 SiS_SetReg(SISSR, 0x19, 0x40);
5618 } else {
5619 SiS_SetReg(SISSR, 0x19, 0x20);
5620 }
5621 SiS_SetReg(SISSR, 0x16, 0x00);
5622 SiS_SetReg(SISSR, 0x16, 0x80);
5623 if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) {
5624 sisfb_post_xgi_delay(ivideo, 0x43);
5625 sisfb_post_xgi_delay(ivideo, 0x43);
5626 sisfb_post_xgi_delay(ivideo, 0x43);
5627 SiS_SetReg(SISSR, 0x18, 0x00);
5628 if((ivideo->chip == XGI_20) ||
5629 (ivideo->revision_id == 2)) {
5630 SiS_SetReg(SISSR, 0x19, 0x40);
5631 } else {
5632 SiS_SetReg(SISSR, 0x19, 0x20);
5633 }
5634 } else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) {
5635 /* SiS_SetReg(SISSR, 0x16, 0x0c); */ /* ? */
5636 }
5637 SiS_SetReg(SISSR, 0x16, 0x00);
5638 SiS_SetReg(SISSR, 0x16, 0x80);
5639 sisfb_post_xgi_delay(ivideo, 4);
5640 v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83;
5641 if(ivideo->haveXGIROM) {
5642 v1 = bios[0xf0];
5643 index = (ivideo->chip == XGI_20) ? 0x4b2 : 0x53e;
5644 v2 = bios[index];
5645 v3 = bios[index + 1];
5646 v4 = bios[index + 2];
5647 v5 = bios[index + 3];
5648 }
5649 SiS_SetReg(SISSR, 0x18, v1);
5650 SiS_SetReg(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01));
5651 SiS_SetReg(SISSR, 0x16, v2);
5652 SiS_SetReg(SISSR, 0x16, v3);
5653 sisfb_post_xgi_delay(ivideo, 0x43);
5654 SiS_SetReg(SISSR, 0x1b, 0x03);
5655 sisfb_post_xgi_delay(ivideo, 0x22);
5656 SiS_SetReg(SISSR, 0x18, v1);
5657 SiS_SetReg(SISSR, 0x19, 0x00);
5658 SiS_SetReg(SISSR, 0x16, v4);
5659 SiS_SetReg(SISSR, 0x16, v5);
5660 SiS_SetReg(SISSR, 0x1b, 0x00);
5661 break;
5662 case 1:
5663 sisfb_post_xgi_ddr2(ivideo, regb);
5664 break;
5665 default:
5666 sisfb_post_xgi_setclocks(ivideo, regb);
5667 if((ivideo->chip == XGI_40) &&
5668 ((ivideo->revision_id == 1) ||
5669 (ivideo->revision_id == 2))) {
5670 SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
5671 SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
5672 SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
5673 } else {
5674 SiS_SetReg(SISCR, 0x82, 0x88);
5675 SiS_SetReg(SISCR, 0x86, 0x00);
5676 reg = SiS_GetReg(SISCR, 0x86);
5677 SiS_SetReg(SISCR, 0x86, 0x88);
5678 SiS_SetReg(SISCR, 0x82, 0x77);
5679 SiS_SetReg(SISCR, 0x85, 0x00);
5680 reg = SiS_GetReg(SISCR, 0x85);
5681 SiS_SetReg(SISCR, 0x85, 0x88);
5682 reg = SiS_GetReg(SISCR, 0x85);
5683 v1 = cs160[regb]; v2 = cs158[regb];
5684 if(ivideo->haveXGIROM) {
5685 v1 = bios[regb + 0x160];
5686 v2 = bios[regb + 0x158];
5687 }
5688 SiS_SetReg(SISCR, 0x85, v1);
5689 SiS_SetReg(SISCR, 0x82, v2);
5690 }
5691 if(ivideo->chip == XGI_40) {
5692 SiS_SetReg(SISCR, 0x97, 0x11);
5693 }
5694 if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) {
5695 SiS_SetReg(SISCR, 0x98, 0x01);
5696 } else {
5697 SiS_SetReg(SISCR, 0x98, 0x03);
5698 }
5699 SiS_SetReg(SISCR, 0x9a, 0x02);
5700
5701 if(ivideo->chip == XGI_40) {
5702 SiS_SetReg(SISSR, 0x18, 0x01);
5703 } else {
5704 SiS_SetReg(SISSR, 0x18, 0x00);
5705 }
5706 SiS_SetReg(SISSR, 0x19, 0x40);
5707 SiS_SetReg(SISSR, 0x16, 0x00);
5708 SiS_SetReg(SISSR, 0x16, 0x80);
5709 if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) {
5710 sisfb_post_xgi_delay(ivideo, 0x43);
5711 sisfb_post_xgi_delay(ivideo, 0x43);
5712 sisfb_post_xgi_delay(ivideo, 0x43);
5713 SiS_SetReg(SISSR, 0x18, 0x00);
5714 SiS_SetReg(SISSR, 0x19, 0x40);
5715 SiS_SetReg(SISSR, 0x16, 0x00);
5716 SiS_SetReg(SISSR, 0x16, 0x80);
5717 }
5718 sisfb_post_xgi_delay(ivideo, 4);
5719 v1 = 0x31;
5720 if(ivideo->haveXGIROM) {
5721 v1 = bios[0xf0];
5722 }
5723 SiS_SetReg(SISSR, 0x18, v1);
5724 SiS_SetReg(SISSR, 0x19, 0x01);
5725 if(ivideo->chip == XGI_40) {
5726 SiS_SetReg(SISSR, 0x16, bios[0x53e]);
5727 SiS_SetReg(SISSR, 0x16, bios[0x53f]);
5728 } else {
5729 SiS_SetReg(SISSR, 0x16, 0x05);
5730 SiS_SetReg(SISSR, 0x16, 0x85);
5731 }
5732 sisfb_post_xgi_delay(ivideo, 0x43);
5733 if(ivideo->chip == XGI_40) {
5734 SiS_SetReg(SISSR, 0x1b, 0x01);
5735 } else {
5736 SiS_SetReg(SISSR, 0x1b, 0x03);
5737 }
5738 sisfb_post_xgi_delay(ivideo, 0x22);
5739 SiS_SetReg(SISSR, 0x18, v1);
5740 SiS_SetReg(SISSR, 0x19, 0x00);
5741 if(ivideo->chip == XGI_40) {
5742 SiS_SetReg(SISSR, 0x16, bios[0x540]);
5743 SiS_SetReg(SISSR, 0x16, bios[0x541]);
5744 } else {
5745 SiS_SetReg(SISSR, 0x16, 0x05);
5746 SiS_SetReg(SISSR, 0x16, 0x85);
5747 }
5748 SiS_SetReg(SISSR, 0x1b, 0x00);
5749 }
5750
5751 regb = 0; /* ! */
5752 v1 = 0x03;
5753 if(ivideo->haveXGIROM) {
5754 v1 = bios[0x110 + regb];
5755 }
5756 SiS_SetReg(SISSR, 0x1b, v1);
5757
5758 /* RAM size */
5759 v1 = 0x00; v2 = 0x00;
5760 if(ivideo->haveXGIROM) {
5761 v1 = bios[0x62];
5762 v2 = bios[0x63];
5763 }
5764 regb = 0; /* ! */
5765 regd = 1 << regb;
5766 if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) {
5767
5768 SiS_SetReg(SISSR, 0x13, bios[regb + 0xe0]);
5769 SiS_SetReg(SISSR, 0x14, bios[regb + 0xe0 + 8]);
5770
5771 } else {
5772 int err;
5773
5774 /* Set default mode, don't clear screen */
5775 ivideo->SiS_Pr.SiS_UseOEM = false;
5776 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
5777 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
5778 ivideo->curFSTN = ivideo->curDSTN = 0;
5779 ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
5780 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
5781
5782 SiS_SetReg(SISSR, 0x05, 0x86);
5783
5784 /* Disable read-cache */
5785 SiS_SetRegAND(SISSR, 0x21, 0xdf);
5786 err = sisfb_post_xgi_ramsize(ivideo);
5787 /* Enable read-cache */
5788 SiS_SetRegOR(SISSR, 0x21, 0x20);
5789
5790 if (err) {
5791 dev_err(&pdev->dev,
5792 "%s: RAM size detection failed: %d\n",
5793 __func__, err);
5794 return 0;
5795 }
5796 }
5797
5798 #if 0
5799 printk(KERN_DEBUG "-----------------\n");
5800 for(i = 0; i < 0xff; i++) {
5801 reg = SiS_GetReg(SISCR, i);
5802 printk(KERN_DEBUG "CR%02x(%x) = 0x%02x\n", i, SISCR, reg);
5803 }
5804 for(i = 0; i < 0x40; i++) {
5805 reg = SiS_GetReg(SISSR, i);
5806 printk(KERN_DEBUG "SR%02x(%x) = 0x%02x\n", i, SISSR, reg);
5807 }
5808 printk(KERN_DEBUG "-----------------\n");
5809 #endif
5810
5811 /* Sense CRT1 */
5812 if(ivideo->chip == XGI_20) {
5813 SiS_SetRegOR(SISCR, 0x32, 0x20);
5814 } else {
5815 reg = SiS_GetReg(SISPART4, 0x00);
5816 if((reg == 1) || (reg == 2)) {
5817 sisfb_sense_crt1(ivideo);
5818 } else {
5819 SiS_SetRegOR(SISCR, 0x32, 0x20);
5820 }
5821 }
5822
5823 /* Set default mode, don't clear screen */
5824 ivideo->SiS_Pr.SiS_UseOEM = false;
5825 SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
5826 SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
5827 ivideo->curFSTN = ivideo->curDSTN = 0;
5828 SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
5829
5830 SiS_SetReg(SISSR, 0x05, 0x86);
5831
5832 /* Display off */
5833 SiS_SetRegOR(SISSR, 0x01, 0x20);
5834
5835 /* Save mode number in CR34 */
5836 SiS_SetReg(SISCR, 0x34, 0x2e);
5837
5838 /* Let everyone know what the current mode is */
5839 ivideo->modeprechange = 0x2e;
5840
5841 if(ivideo->chip == XGI_40) {
5842 reg = SiS_GetReg(SISCR, 0xca);
5843 v1 = SiS_GetReg(SISCR, 0xcc);
5844 if((reg & 0x10) && (!(v1 & 0x04))) {
5845 printk(KERN_ERR
5846 "sisfb: Please connect power to the card.\n");
5847 return 0;
5848 }
5849 }
5850
5851 return 1;
5852 }
5853 #endif
5854
sisfb_probe(struct pci_dev * pdev,const struct pci_device_id * ent)5855 static int sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
5856 {
5857 struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data];
5858 struct sis_video_info *ivideo = NULL;
5859 struct fb_info *sis_fb_info = NULL;
5860 u16 reg16;
5861 u8 reg;
5862 int i, ret;
5863
5864 if(sisfb_off)
5865 return -ENXIO;
5866
5867 sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
5868 if(!sis_fb_info)
5869 return -ENOMEM;
5870
5871 ivideo = (struct sis_video_info *)sis_fb_info->par;
5872 ivideo->memyselfandi = sis_fb_info;
5873
5874 ivideo->sisfb_id = SISFB_ID;
5875
5876 if(card_list == NULL) {
5877 ivideo->cardnumber = 0;
5878 } else {
5879 struct sis_video_info *countvideo = card_list;
5880 ivideo->cardnumber = 1;
5881 while((countvideo = countvideo->next) != NULL)
5882 ivideo->cardnumber++;
5883 }
5884
5885 strlcpy(ivideo->myid, chipinfo->chip_name, sizeof(ivideo->myid));
5886
5887 ivideo->warncount = 0;
5888 ivideo->chip_id = pdev->device;
5889 ivideo->chip_vendor = pdev->vendor;
5890 ivideo->revision_id = pdev->revision;
5891 ivideo->SiS_Pr.ChipRevision = ivideo->revision_id;
5892 pci_read_config_word(pdev, PCI_COMMAND, ®16);
5893 ivideo->sisvga_enabled = reg16 & 0x01;
5894 ivideo->pcibus = pdev->bus->number;
5895 ivideo->pcislot = PCI_SLOT(pdev->devfn);
5896 ivideo->pcifunc = PCI_FUNC(pdev->devfn);
5897 ivideo->subsysvendor = pdev->subsystem_vendor;
5898 ivideo->subsysdevice = pdev->subsystem_device;
5899
5900 #ifndef MODULE
5901 if(sisfb_mode_idx == -1) {
5902 sisfb_get_vga_mode_from_kernel();
5903 }
5904 #endif
5905
5906 ivideo->chip = chipinfo->chip;
5907 ivideo->chip_real_id = chipinfo->chip;
5908 ivideo->sisvga_engine = chipinfo->vgaengine;
5909 ivideo->hwcursor_size = chipinfo->hwcursor_size;
5910 ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable;
5911 ivideo->mni = chipinfo->mni;
5912
5913 ivideo->detectedpdc = 0xff;
5914 ivideo->detectedpdca = 0xff;
5915 ivideo->detectedlcda = 0xff;
5916
5917 ivideo->sisfb_thismonitor.datavalid = false;
5918
5919 ivideo->current_base = 0;
5920
5921 ivideo->engineok = 0;
5922
5923 ivideo->sisfb_was_boot_device = 0;
5924
5925 if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
5926 if(ivideo->sisvga_enabled)
5927 ivideo->sisfb_was_boot_device = 1;
5928 else {
5929 printk(KERN_DEBUG "sisfb: PCI device is disabled, "
5930 "but marked as boot video device ???\n");
5931 printk(KERN_DEBUG "sisfb: I will not accept this "
5932 "as the primary VGA device\n");
5933 }
5934 }
5935
5936 ivideo->sisfb_parm_mem = sisfb_parm_mem;
5937 ivideo->sisfb_accel = sisfb_accel;
5938 ivideo->sisfb_ypan = sisfb_ypan;
5939 ivideo->sisfb_max = sisfb_max;
5940 ivideo->sisfb_userom = sisfb_userom;
5941 ivideo->sisfb_useoem = sisfb_useoem;
5942 ivideo->sisfb_mode_idx = sisfb_mode_idx;
5943 ivideo->sisfb_parm_rate = sisfb_parm_rate;
5944 ivideo->sisfb_crt1off = sisfb_crt1off;
5945 ivideo->sisfb_forcecrt1 = sisfb_forcecrt1;
5946 ivideo->sisfb_crt2type = sisfb_crt2type;
5947 ivideo->sisfb_crt2flags = sisfb_crt2flags;
5948 /* pdc(a), scalelcd, special timing, lvdshl handled below */
5949 ivideo->sisfb_dstn = sisfb_dstn;
5950 ivideo->sisfb_fstn = sisfb_fstn;
5951 ivideo->sisfb_tvplug = sisfb_tvplug;
5952 ivideo->sisfb_tvstd = sisfb_tvstd;
5953 ivideo->tvxpos = sisfb_tvxposoffset;
5954 ivideo->tvypos = sisfb_tvyposoffset;
5955 ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
5956 ivideo->refresh_rate = 0;
5957 if(ivideo->sisfb_parm_rate != -1) {
5958 ivideo->refresh_rate = ivideo->sisfb_parm_rate;
5959 }
5960
5961 ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
5962 ivideo->SiS_Pr.CenterScreen = -1;
5963 ivideo->SiS_Pr.SiS_CustomT = sisfb_specialtiming;
5964 ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;
5965
5966 ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
5967 ivideo->SiS_Pr.SiS_CHOverScan = -1;
5968 ivideo->SiS_Pr.SiS_ChSW = false;
5969 ivideo->SiS_Pr.SiS_UseLCDA = false;
5970 ivideo->SiS_Pr.HaveEMI = false;
5971 ivideo->SiS_Pr.HaveEMILCD = false;
5972 ivideo->SiS_Pr.OverruleEMI = false;
5973 ivideo->SiS_Pr.SiS_SensibleSR11 = false;
5974 ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
5975 ivideo->SiS_Pr.PDC = -1;
5976 ivideo->SiS_Pr.PDCA = -1;
5977 ivideo->SiS_Pr.DDCPortMixup = false;
5978 #ifdef CONFIG_FB_SIS_315
5979 if(ivideo->chip >= SIS_330) {
5980 ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
5981 if(ivideo->chip >= SIS_661) {
5982 ivideo->SiS_Pr.SiS_SensibleSR11 = true;
5983 }
5984 }
5985 #endif
5986
5987 memcpy(&ivideo->default_var, &my_default_var, sizeof(my_default_var));
5988
5989 pci_set_drvdata(pdev, ivideo);
5990
5991 /* Patch special cases */
5992 if((ivideo->nbridge = sisfb_get_northbridge(ivideo->chip))) {
5993 switch(ivideo->nbridge->device) {
5994 #ifdef CONFIG_FB_SIS_300
5995 case PCI_DEVICE_ID_SI_730:
5996 ivideo->chip = SIS_730;
5997 strcpy(ivideo->myid, "SiS 730");
5998 break;
5999 #endif
6000 #ifdef CONFIG_FB_SIS_315
6001 case PCI_DEVICE_ID_SI_651:
6002 /* ivideo->chip is ok */
6003 strcpy(ivideo->myid, "SiS 651");
6004 break;
6005 case PCI_DEVICE_ID_SI_740:
6006 ivideo->chip = SIS_740;
6007 strcpy(ivideo->myid, "SiS 740");
6008 break;
6009 case PCI_DEVICE_ID_SI_661:
6010 ivideo->chip = SIS_661;
6011 strcpy(ivideo->myid, "SiS 661");
6012 break;
6013 case PCI_DEVICE_ID_SI_741:
6014 ivideo->chip = SIS_741;
6015 strcpy(ivideo->myid, "SiS 741");
6016 break;
6017 case PCI_DEVICE_ID_SI_760:
6018 ivideo->chip = SIS_760;
6019 strcpy(ivideo->myid, "SiS 760");
6020 break;
6021 case PCI_DEVICE_ID_SI_761:
6022 ivideo->chip = SIS_761;
6023 strcpy(ivideo->myid, "SiS 761");
6024 break;
6025 #endif
6026 default:
6027 break;
6028 }
6029 }
6030
6031 ivideo->SiS_Pr.ChipType = ivideo->chip;
6032
6033 ivideo->SiS_Pr.ivideo = (void *)ivideo;
6034
6035 #ifdef CONFIG_FB_SIS_315
6036 if((ivideo->SiS_Pr.ChipType == SIS_315PRO) ||
6037 (ivideo->SiS_Pr.ChipType == SIS_315)) {
6038 ivideo->SiS_Pr.ChipType = SIS_315H;
6039 }
6040 #endif
6041
6042 if(!ivideo->sisvga_enabled) {
6043 if(pci_enable_device(pdev)) {
6044 pci_dev_put(ivideo->nbridge);
6045 framebuffer_release(sis_fb_info);
6046 return -EIO;
6047 }
6048 }
6049
6050 ivideo->video_base = pci_resource_start(pdev, 0);
6051 ivideo->video_size = pci_resource_len(pdev, 0);
6052 ivideo->mmio_base = pci_resource_start(pdev, 1);
6053 ivideo->mmio_size = pci_resource_len(pdev, 1);
6054 ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
6055 ivideo->SiS_Pr.IOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
6056
6057 SiSRegInit(&ivideo->SiS_Pr, ivideo->SiS_Pr.IOAddress);
6058
6059 #ifdef CONFIG_FB_SIS_300
6060 /* Find PCI systems for Chrontel/GPIO communication setup */
6061 if(ivideo->chip == SIS_630) {
6062 i = 0;
6063 do {
6064 if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
6065 mychswtable[i].subsysCard == ivideo->subsysdevice) {
6066 ivideo->SiS_Pr.SiS_ChSW = true;
6067 printk(KERN_DEBUG "sisfb: Identified [%s %s] "
6068 "requiring Chrontel/GPIO setup\n",
6069 mychswtable[i].vendorName,
6070 mychswtable[i].cardName);
6071 ivideo->lpcdev = pci_get_device(PCI_VENDOR_ID_SI, 0x0008, NULL);
6072 break;
6073 }
6074 i++;
6075 } while(mychswtable[i].subsysVendor != 0);
6076 }
6077 #endif
6078
6079 #ifdef CONFIG_FB_SIS_315
6080 if((ivideo->chip == SIS_760) && (ivideo->nbridge)) {
6081 ivideo->lpcdev = pci_get_slot(ivideo->nbridge->bus, (2 << 3));
6082 }
6083 #endif
6084
6085 SiS_SetReg(SISSR, 0x05, 0x86);
6086
6087 if( (!ivideo->sisvga_enabled)
6088 #if !defined(__i386__) && !defined(__x86_64__)
6089 || (sisfb_resetcard)
6090 #endif
6091 ) {
6092 for(i = 0x30; i <= 0x3f; i++) {
6093 SiS_SetReg(SISCR, i, 0x00);
6094 }
6095 }
6096
6097 /* Find out about current video mode */
6098 ivideo->modeprechange = 0x03;
6099 reg = SiS_GetReg(SISCR, 0x34);
6100 if(reg & 0x7f) {
6101 ivideo->modeprechange = reg & 0x7f;
6102 } else if(ivideo->sisvga_enabled) {
6103 #if defined(__i386__) || defined(__x86_64__)
6104 unsigned char __iomem *tt = ioremap(0x400, 0x100);
6105 if(tt) {
6106 ivideo->modeprechange = readb(tt + 0x49);
6107 iounmap(tt);
6108 }
6109 #endif
6110 }
6111
6112 /* Search and copy ROM image */
6113 ivideo->bios_abase = NULL;
6114 ivideo->SiS_Pr.VirtualRomBase = NULL;
6115 ivideo->SiS_Pr.UseROM = false;
6116 ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = false;
6117 if(ivideo->sisfb_userom) {
6118 ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev);
6119 ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase;
6120 ivideo->SiS_Pr.UseROM = (bool)(ivideo->SiS_Pr.VirtualRomBase);
6121 printk(KERN_INFO "sisfb: Video ROM %sfound\n",
6122 ivideo->SiS_Pr.UseROM ? "" : "not ");
6123 if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) {
6124 ivideo->SiS_Pr.UseROM = false;
6125 ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = true;
6126 if( (ivideo->revision_id == 2) &&
6127 (!(ivideo->bios_abase[0x1d1] & 0x01)) ) {
6128 ivideo->SiS_Pr.DDCPortMixup = true;
6129 }
6130 }
6131 } else {
6132 printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
6133 }
6134
6135 /* Find systems for special custom timing */
6136 if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
6137 sisfb_detect_custom_timing(ivideo);
6138 }
6139
6140 #ifdef CONFIG_FB_SIS_315
6141 if (ivideo->chip == XGI_20) {
6142 /* Check if our Z7 chip is actually Z9 */
6143 SiS_SetRegOR(SISCR, 0x4a, 0x40); /* GPIOG EN */
6144 reg = SiS_GetReg(SISCR, 0x48);
6145 if (reg & 0x02) { /* GPIOG */
6146 ivideo->chip_real_id = XGI_21;
6147 dev_info(&pdev->dev, "Z9 detected\n");
6148 }
6149 }
6150 #endif
6151
6152 /* POST card in case this has not been done by the BIOS */
6153 if( (!ivideo->sisvga_enabled)
6154 #if !defined(__i386__) && !defined(__x86_64__)
6155 || (sisfb_resetcard)
6156 #endif
6157 ) {
6158 #ifdef CONFIG_FB_SIS_300
6159 if(ivideo->sisvga_engine == SIS_300_VGA) {
6160 if(ivideo->chip == SIS_300) {
6161 sisfb_post_sis300(pdev);
6162 ivideo->sisfb_can_post = 1;
6163 }
6164 }
6165 #endif
6166
6167 #ifdef CONFIG_FB_SIS_315
6168 if(ivideo->sisvga_engine == SIS_315_VGA) {
6169 int result = 1;
6170 /* if((ivideo->chip == SIS_315H) ||
6171 (ivideo->chip == SIS_315) ||
6172 (ivideo->chip == SIS_315PRO) ||
6173 (ivideo->chip == SIS_330)) {
6174 sisfb_post_sis315330(pdev);
6175 } else */ if(ivideo->chip == XGI_20) {
6176 result = sisfb_post_xgi(pdev);
6177 ivideo->sisfb_can_post = 1;
6178 } else if((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
6179 result = sisfb_post_xgi(pdev);
6180 ivideo->sisfb_can_post = 1;
6181 } else {
6182 printk(KERN_INFO "sisfb: Card is not "
6183 "POSTed and sisfb can't do this either.\n");
6184 }
6185 if(!result) {
6186 printk(KERN_ERR "sisfb: Failed to POST card\n");
6187 ret = -ENODEV;
6188 goto error_3;
6189 }
6190 }
6191 #endif
6192 }
6193
6194 ivideo->sisfb_card_posted = 1;
6195
6196 /* Find out about RAM size */
6197 if(sisfb_get_dram_size(ivideo)) {
6198 printk(KERN_INFO "sisfb: Fatal error: Unable to determine VRAM size.\n");
6199 ret = -ENODEV;
6200 goto error_3;
6201 }
6202
6203
6204 /* Enable PCI addressing and MMIO */
6205 if((ivideo->sisfb_mode_idx < 0) ||
6206 ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
6207 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
6208 SiS_SetRegOR(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
6209 /* Enable 2D accelerator engine */
6210 SiS_SetRegOR(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
6211 }
6212
6213 if(sisfb_pdc != 0xff) {
6214 if(ivideo->sisvga_engine == SIS_300_VGA)
6215 sisfb_pdc &= 0x3c;
6216 else
6217 sisfb_pdc &= 0x1f;
6218 ivideo->SiS_Pr.PDC = sisfb_pdc;
6219 }
6220 #ifdef CONFIG_FB_SIS_315
6221 if(ivideo->sisvga_engine == SIS_315_VGA) {
6222 if(sisfb_pdca != 0xff)
6223 ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
6224 }
6225 #endif
6226
6227 if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
6228 printk(KERN_ERR "sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
6229 (int)(ivideo->video_size >> 20));
6230 printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
6231 ret = -ENODEV;
6232 goto error_3;
6233 }
6234
6235 if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
6236 printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
6237 ret = -ENODEV;
6238 goto error_2;
6239 }
6240
6241 ivideo->video_vbase = ioremap_wc(ivideo->video_base, ivideo->video_size);
6242 ivideo->SiS_Pr.VideoMemoryAddress = ivideo->video_vbase;
6243 if(!ivideo->video_vbase) {
6244 printk(KERN_ERR "sisfb: Fatal error: Unable to map framebuffer memory\n");
6245 ret = -ENODEV;
6246 goto error_1;
6247 }
6248
6249 ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size);
6250 if(!ivideo->mmio_vbase) {
6251 printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
6252 ret = -ENODEV;
6253 error_0: iounmap(ivideo->video_vbase);
6254 error_1: release_mem_region(ivideo->video_base, ivideo->video_size);
6255 error_2: release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
6256 error_3: vfree(ivideo->bios_abase);
6257 pci_dev_put(ivideo->lpcdev);
6258 pci_dev_put(ivideo->nbridge);
6259 if(!ivideo->sisvga_enabled)
6260 pci_disable_device(pdev);
6261 framebuffer_release(sis_fb_info);
6262 return ret;
6263 }
6264
6265 printk(KERN_INFO "sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
6266 ivideo->video_base, (unsigned long)ivideo->video_vbase, ivideo->video_size / 1024);
6267
6268 if(ivideo->video_offset) {
6269 printk(KERN_INFO "sisfb: Viewport offset %ldk\n",
6270 ivideo->video_offset / 1024);
6271 }
6272
6273 printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
6274 ivideo->mmio_base, (unsigned long)ivideo->mmio_vbase, ivideo->mmio_size / 1024);
6275
6276
6277 /* Determine the size of the command queue */
6278 if(ivideo->sisvga_engine == SIS_300_VGA) {
6279 ivideo->cmdQueueSize = TURBO_QUEUE_AREA_SIZE;
6280 } else {
6281 if(ivideo->chip == XGI_20) {
6282 ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE_Z7;
6283 } else {
6284 ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE;
6285 }
6286 }
6287
6288 /* Engines are no longer initialized here; this is
6289 * now done after the first mode-switch (if the
6290 * submitted var has its acceleration flags set).
6291 */
6292
6293 /* Calculate the base of the (unused) hw cursor */
6294 ivideo->hwcursor_vbase = ivideo->video_vbase
6295 + ivideo->video_size
6296 - ivideo->cmdQueueSize
6297 - ivideo->hwcursor_size;
6298 ivideo->caps |= HW_CURSOR_CAP;
6299
6300 /* Initialize offscreen memory manager */
6301 if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
6302 printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
6303 }
6304
6305 /* Used for clearing the screen only, therefore respect our mem limit */
6306 ivideo->SiS_Pr.VideoMemoryAddress += ivideo->video_offset;
6307 ivideo->SiS_Pr.VideoMemorySize = ivideo->sisfb_mem;
6308
6309 ivideo->vbflags = 0;
6310 ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
6311 ivideo->tvdefmodeidx = DEFAULT_TVMODE;
6312 ivideo->defmodeidx = DEFAULT_MODE;
6313
6314 ivideo->newrom = 0;
6315 if(ivideo->chip < XGI_20) {
6316 if(ivideo->bios_abase) {
6317 ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr);
6318 }
6319 }
6320
6321 if((ivideo->sisfb_mode_idx < 0) ||
6322 ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
6323
6324 sisfb_sense_crt1(ivideo);
6325
6326 sisfb_get_VB_type(ivideo);
6327
6328 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
6329 sisfb_detect_VB_connect(ivideo);
6330 }
6331
6332 ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
6333
6334 /* Decide on which CRT2 device to use */
6335 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
6336 if(ivideo->sisfb_crt2type != -1) {
6337 if((ivideo->sisfb_crt2type == CRT2_LCD) &&
6338 (ivideo->vbflags & CRT2_LCD)) {
6339 ivideo->currentvbflags |= CRT2_LCD;
6340 } else if(ivideo->sisfb_crt2type != CRT2_LCD) {
6341 ivideo->currentvbflags |= ivideo->sisfb_crt2type;
6342 }
6343 } else {
6344 /* Chrontel 700x TV detection often unreliable, therefore
6345 * use a different default order on such machines
6346 */
6347 if((ivideo->sisvga_engine == SIS_300_VGA) &&
6348 (ivideo->vbflags2 & VB2_CHRONTEL)) {
6349 if(ivideo->vbflags & CRT2_LCD)
6350 ivideo->currentvbflags |= CRT2_LCD;
6351 else if(ivideo->vbflags & CRT2_TV)
6352 ivideo->currentvbflags |= CRT2_TV;
6353 else if(ivideo->vbflags & CRT2_VGA)
6354 ivideo->currentvbflags |= CRT2_VGA;
6355 } else {
6356 if(ivideo->vbflags & CRT2_TV)
6357 ivideo->currentvbflags |= CRT2_TV;
6358 else if(ivideo->vbflags & CRT2_LCD)
6359 ivideo->currentvbflags |= CRT2_LCD;
6360 else if(ivideo->vbflags & CRT2_VGA)
6361 ivideo->currentvbflags |= CRT2_VGA;
6362 }
6363 }
6364 }
6365
6366 if(ivideo->vbflags & CRT2_LCD) {
6367 sisfb_detect_lcd_type(ivideo);
6368 }
6369
6370 sisfb_save_pdc_emi(ivideo);
6371
6372 if(!ivideo->sisfb_crt1off) {
6373 sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
6374 } else {
6375 if((ivideo->vbflags2 & VB2_SISTMDSBRIDGE) &&
6376 (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
6377 sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
6378 }
6379 }
6380
6381 if(ivideo->sisfb_mode_idx >= 0) {
6382 int bu = ivideo->sisfb_mode_idx;
6383 ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
6384 ivideo->sisfb_mode_idx, ivideo->currentvbflags);
6385 if(bu != ivideo->sisfb_mode_idx) {
6386 printk(KERN_ERR "Mode %dx%dx%d failed validation\n",
6387 sisbios_mode[bu].xres,
6388 sisbios_mode[bu].yres,
6389 sisbios_mode[bu].bpp);
6390 }
6391 }
6392
6393 if(ivideo->sisfb_mode_idx < 0) {
6394 switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
6395 case CRT2_LCD:
6396 ivideo->sisfb_mode_idx = ivideo->lcddefmodeidx;
6397 break;
6398 case CRT2_TV:
6399 ivideo->sisfb_mode_idx = ivideo->tvdefmodeidx;
6400 break;
6401 default:
6402 ivideo->sisfb_mode_idx = ivideo->defmodeidx;
6403 break;
6404 }
6405 }
6406
6407 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
6408
6409 if(ivideo->refresh_rate != 0) {
6410 sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate,
6411 ivideo->sisfb_mode_idx);
6412 }
6413
6414 if(ivideo->rate_idx == 0) {
6415 ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
6416 ivideo->refresh_rate = 60;
6417 }
6418
6419 if(ivideo->sisfb_thismonitor.datavalid) {
6420 if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor,
6421 ivideo->sisfb_mode_idx,
6422 ivideo->rate_idx,
6423 ivideo->refresh_rate)) {
6424 printk(KERN_INFO "sisfb: WARNING: Refresh rate "
6425 "exceeds monitor specs!\n");
6426 }
6427 }
6428
6429 ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
6430 ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
6431 ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
6432
6433 sisfb_set_vparms(ivideo);
6434
6435 printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
6436 ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
6437 ivideo->refresh_rate);
6438
6439 /* Set up the default var according to chosen default display mode */
6440 ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
6441 ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
6442 ivideo->default_var.bits_per_pixel = ivideo->video_bpp;
6443
6444 sisfb_bpp_to_var(ivideo, &ivideo->default_var);
6445
6446 ivideo->default_var.pixclock = (u32) (1000000000 /
6447 sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, ivideo->mode_no, ivideo->rate_idx));
6448
6449 if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, ivideo->mode_no,
6450 ivideo->rate_idx, &ivideo->default_var)) {
6451 if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
6452 ivideo->default_var.pixclock <<= 1;
6453 }
6454 }
6455
6456 if(ivideo->sisfb_ypan) {
6457 /* Maximize regardless of sisfb_max at startup */
6458 ivideo->default_var.yres_virtual =
6459 sisfb_calc_maxyres(ivideo, &ivideo->default_var);
6460 if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
6461 ivideo->default_var.yres_virtual = ivideo->default_var.yres;
6462 }
6463 }
6464
6465 sisfb_calc_pitch(ivideo, &ivideo->default_var);
6466
6467 ivideo->accel = 0;
6468 if(ivideo->sisfb_accel) {
6469 ivideo->accel = -1;
6470 #ifdef STUPID_ACCELF_TEXT_SHIT
6471 ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
6472 #endif
6473 }
6474 sisfb_initaccel(ivideo);
6475
6476 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
6477 sis_fb_info->flags = FBINFO_DEFAULT |
6478 FBINFO_HWACCEL_YPAN |
6479 FBINFO_HWACCEL_XPAN |
6480 FBINFO_HWACCEL_COPYAREA |
6481 FBINFO_HWACCEL_FILLRECT |
6482 ((ivideo->accel) ? 0 : FBINFO_HWACCEL_DISABLED);
6483 #else
6484 sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
6485 #endif
6486 sis_fb_info->var = ivideo->default_var;
6487 sis_fb_info->fix = ivideo->sisfb_fix;
6488 sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset;
6489 sis_fb_info->fbops = &sisfb_ops;
6490 sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
6491
6492 fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
6493
6494 printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags);
6495
6496 ivideo->wc_cookie = arch_phys_wc_add(ivideo->video_base,
6497 ivideo->video_size);
6498 if(register_framebuffer(sis_fb_info) < 0) {
6499 printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
6500 ret = -EINVAL;
6501 iounmap(ivideo->mmio_vbase);
6502 goto error_0;
6503 }
6504
6505 ivideo->registered = 1;
6506
6507 /* Enlist us */
6508 ivideo->next = card_list;
6509 card_list = ivideo;
6510
6511 printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
6512 ivideo->sisfb_accel ? "enabled" : "disabled",
6513 ivideo->sisfb_ypan ?
6514 (ivideo->sisfb_max ? "enabled (auto-max)" :
6515 "enabled (no auto-max)") :
6516 "disabled");
6517
6518
6519 fb_info(sis_fb_info, "%s frame buffer device version %d.%d.%d\n",
6520 ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
6521
6522 printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
6523
6524 } /* if mode = "none" */
6525
6526 return 0;
6527 }
6528
6529 /*****************************************************/
6530 /* PCI DEVICE HANDLING */
6531 /*****************************************************/
6532
sisfb_remove(struct pci_dev * pdev)6533 static void sisfb_remove(struct pci_dev *pdev)
6534 {
6535 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
6536 struct fb_info *sis_fb_info = ivideo->memyselfandi;
6537 int registered = ivideo->registered;
6538 int modechanged = ivideo->modechanged;
6539
6540 /* Unmap */
6541 iounmap(ivideo->mmio_vbase);
6542 iounmap(ivideo->video_vbase);
6543
6544 /* Release mem regions */
6545 release_mem_region(ivideo->video_base, ivideo->video_size);
6546 release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
6547
6548 vfree(ivideo->bios_abase);
6549
6550 pci_dev_put(ivideo->lpcdev);
6551
6552 pci_dev_put(ivideo->nbridge);
6553
6554 arch_phys_wc_del(ivideo->wc_cookie);
6555
6556 /* If device was disabled when starting, disable
6557 * it when quitting.
6558 */
6559 if(!ivideo->sisvga_enabled)
6560 pci_disable_device(pdev);
6561
6562 /* Unregister the framebuffer */
6563 if(ivideo->registered) {
6564 unregister_framebuffer(sis_fb_info);
6565 framebuffer_release(sis_fb_info);
6566 }
6567
6568 /* OK, our ivideo is gone for good from here. */
6569
6570 /* TODO: Restore the initial mode
6571 * This sounds easy but is as good as impossible
6572 * on many machines with SiS chip and video bridge
6573 * since text modes are always set up differently
6574 * from machine to machine. Depends on the type
6575 * of integration between chipset and bridge.
6576 */
6577 if(registered && modechanged)
6578 printk(KERN_INFO
6579 "sisfb: Restoring of text mode not supported yet\n");
6580 };
6581
6582 static struct pci_driver sisfb_driver = {
6583 .name = "sisfb",
6584 .id_table = sisfb_pci_table,
6585 .probe = sisfb_probe,
6586 .remove = sisfb_remove,
6587 };
6588
sisfb_init(void)6589 static int __init sisfb_init(void)
6590 {
6591 #ifndef MODULE
6592 char *options = NULL;
6593
6594 if(fb_get_options("sisfb", &options))
6595 return -ENODEV;
6596
6597 sisfb_setup(options);
6598 #endif
6599 return pci_register_driver(&sisfb_driver);
6600 }
6601
6602 #ifndef MODULE
6603 module_init(sisfb_init);
6604 #endif
6605
6606 /*****************************************************/
6607 /* MODULE */
6608 /*****************************************************/
6609
6610 #ifdef MODULE
6611
6612 static char *mode = NULL;
6613 static int vesa = -1;
6614 static unsigned int rate = 0;
6615 static unsigned int crt1off = 1;
6616 static unsigned int mem = 0;
6617 static char *forcecrt2type = NULL;
6618 static int forcecrt1 = -1;
6619 static int pdc = -1;
6620 static int pdc1 = -1;
6621 static int noaccel = -1;
6622 static int noypan = -1;
6623 static int nomax = -1;
6624 static int userom = -1;
6625 static int useoem = -1;
6626 static char *tvstandard = NULL;
6627 static int nocrt2rate = 0;
6628 static int scalelcd = -1;
6629 static char *specialtiming = NULL;
6630 static int lvdshl = -1;
6631 static int tvxposoffset = 0, tvyposoffset = 0;
6632 #if !defined(__i386__) && !defined(__x86_64__)
6633 static int resetcard = 0;
6634 static int videoram = 0;
6635 #endif
6636
sisfb_init_module(void)6637 static int __init sisfb_init_module(void)
6638 {
6639 sisfb_setdefaultparms();
6640
6641 if(rate)
6642 sisfb_parm_rate = rate;
6643
6644 if((scalelcd == 0) || (scalelcd == 1))
6645 sisfb_scalelcd = scalelcd ^ 1;
6646
6647 /* Need to check crt2 type first for fstn/dstn */
6648
6649 if(forcecrt2type)
6650 sisfb_search_crt2type(forcecrt2type);
6651
6652 if(tvstandard)
6653 sisfb_search_tvstd(tvstandard);
6654
6655 if(mode)
6656 sisfb_search_mode(mode, false);
6657 else if(vesa != -1)
6658 sisfb_search_vesamode(vesa, false);
6659
6660 sisfb_crt1off = (crt1off == 0) ? 1 : 0;
6661
6662 sisfb_forcecrt1 = forcecrt1;
6663 if(forcecrt1 == 1)
6664 sisfb_crt1off = 0;
6665 else if(forcecrt1 == 0)
6666 sisfb_crt1off = 1;
6667
6668 if(noaccel == 1)
6669 sisfb_accel = 0;
6670 else if(noaccel == 0)
6671 sisfb_accel = 1;
6672
6673 if(noypan == 1)
6674 sisfb_ypan = 0;
6675 else if(noypan == 0)
6676 sisfb_ypan = 1;
6677
6678 if(nomax == 1)
6679 sisfb_max = 0;
6680 else if(nomax == 0)
6681 sisfb_max = 1;
6682
6683 if(mem)
6684 sisfb_parm_mem = mem;
6685
6686 if(userom != -1)
6687 sisfb_userom = userom;
6688
6689 if(useoem != -1)
6690 sisfb_useoem = useoem;
6691
6692 if(pdc != -1)
6693 sisfb_pdc = (pdc & 0x7f);
6694
6695 if(pdc1 != -1)
6696 sisfb_pdca = (pdc1 & 0x1f);
6697
6698 sisfb_nocrt2rate = nocrt2rate;
6699
6700 if(specialtiming)
6701 sisfb_search_specialtiming(specialtiming);
6702
6703 if((lvdshl >= 0) && (lvdshl <= 3))
6704 sisfb_lvdshl = lvdshl;
6705
6706 sisfb_tvxposoffset = tvxposoffset;
6707 sisfb_tvyposoffset = tvyposoffset;
6708
6709 #if !defined(__i386__) && !defined(__x86_64__)
6710 sisfb_resetcard = (resetcard) ? 1 : 0;
6711 if(videoram)
6712 sisfb_videoram = videoram;
6713 #endif
6714
6715 return sisfb_init();
6716 }
6717
sisfb_remove_module(void)6718 static void __exit sisfb_remove_module(void)
6719 {
6720 pci_unregister_driver(&sisfb_driver);
6721 printk(KERN_DEBUG "sisfb: Module unloaded\n");
6722 }
6723
6724 module_init(sisfb_init_module);
6725 module_exit(sisfb_remove_module);
6726
6727 MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
6728 MODULE_LICENSE("GPL");
6729 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
6730
6731 module_param(mem, int, 0);
6732 module_param(noaccel, int, 0);
6733 module_param(noypan, int, 0);
6734 module_param(nomax, int, 0);
6735 module_param(userom, int, 0);
6736 module_param(useoem, int, 0);
6737 module_param(mode, charp, 0);
6738 module_param(vesa, int, 0);
6739 module_param(rate, int, 0);
6740 module_param(forcecrt1, int, 0);
6741 module_param(forcecrt2type, charp, 0);
6742 module_param(scalelcd, int, 0);
6743 module_param(pdc, int, 0);
6744 module_param(pdc1, int, 0);
6745 module_param(specialtiming, charp, 0);
6746 module_param(lvdshl, int, 0);
6747 module_param(tvstandard, charp, 0);
6748 module_param(tvxposoffset, int, 0);
6749 module_param(tvyposoffset, int, 0);
6750 module_param(nocrt2rate, int, 0);
6751 #if !defined(__i386__) && !defined(__x86_64__)
6752 module_param(resetcard, int, 0);
6753 module_param(videoram, int, 0);
6754 #endif
6755
6756 MODULE_PARM_DESC(mem,
6757 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
6758 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
6759 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
6760 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
6761 "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
6762 "The value is to be specified without 'KB'.\n");
6763
6764 MODULE_PARM_DESC(noaccel,
6765 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
6766 "(default: 0)\n");
6767
6768 MODULE_PARM_DESC(noypan,
6769 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
6770 "will be performed by redrawing the screen. (default: 0)\n");
6771
6772 MODULE_PARM_DESC(nomax,
6773 "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
6774 "memory for the virtual screen in order to optimize scrolling performance. If\n"
6775 "this is set to anything other than 0, sisfb will not do this and thereby \n"
6776 "enable the user to positively specify a virtual Y size of the screen using\n"
6777 "fbset. (default: 0)\n");
6778
6779 MODULE_PARM_DESC(mode,
6780 "\nSelects the desired default display mode in the format XxYxDepth,\n"
6781 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
6782 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
6783 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
6784
6785 MODULE_PARM_DESC(vesa,
6786 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
6787 "0x117 (default: 0x0103)\n");
6788
6789 MODULE_PARM_DESC(rate,
6790 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
6791 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
6792 "will be ignored (default: 60)\n");
6793
6794 MODULE_PARM_DESC(forcecrt1,
6795 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
6796 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
6797 "0=CRT1 OFF) (default: [autodetected])\n");
6798
6799 MODULE_PARM_DESC(forcecrt2type,
6800 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
6801 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
6802 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
6803 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
6804 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
6805 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
6806 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
6807 "depends on the very hardware in use. (default: [autodetected])\n");
6808
6809 MODULE_PARM_DESC(scalelcd,
6810 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
6811 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
6812 "show black bars around the image, TMDS panels will probably do the scaling\n"
6813 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
6814
6815 MODULE_PARM_DESC(pdc,
6816 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
6817 "should detect this correctly in most cases; however, sometimes this is not\n"
6818 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
6819 "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
6820 "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
6821 "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
6822
6823 #ifdef CONFIG_FB_SIS_315
6824 MODULE_PARM_DESC(pdc1,
6825 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
6826 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
6827 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
6828 "implemented yet.\n");
6829 #endif
6830
6831 MODULE_PARM_DESC(specialtiming,
6832 "\nPlease refer to documentation for more information on this option.\n");
6833
6834 MODULE_PARM_DESC(lvdshl,
6835 "\nPlease refer to documentation for more information on this option.\n");
6836
6837 MODULE_PARM_DESC(tvstandard,
6838 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
6839 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
6840
6841 MODULE_PARM_DESC(tvxposoffset,
6842 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
6843 "Default: 0\n");
6844
6845 MODULE_PARM_DESC(tvyposoffset,
6846 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
6847 "Default: 0\n");
6848
6849 MODULE_PARM_DESC(nocrt2rate,
6850 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
6851 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
6852
6853 #if !defined(__i386__) && !defined(__x86_64__)
6854 #ifdef CONFIG_FB_SIS_300
6855 MODULE_PARM_DESC(resetcard,
6856 "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
6857 "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
6858 "currently). Default: 0\n");
6859
6860 MODULE_PARM_DESC(videoram,
6861 "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
6862 "some non-x86 architectures where the memory auto detection fails. Only\n"
6863 "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
6864 #endif
6865 #endif
6866
6867 #endif /* /MODULE */
6868
6869 /* _GPL only for new symbols. */
6870 EXPORT_SYMBOL(sis_malloc);
6871 EXPORT_SYMBOL(sis_free);
6872 EXPORT_SYMBOL_GPL(sis_malloc_new);
6873 EXPORT_SYMBOL_GPL(sis_free_new);
6874
6875
6876
6877