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