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