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
56static int sisfb_setup(char *options);
57#endif
58
59/* Interface to the low level console driver */
60static int sisfb_init(void);
61
62/* fbdev routines */
63static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
64 struct fb_info *info);
65
66static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
67 unsigned long arg);
68static int sisfb_set_par(struct fb_info *info);
69static int sisfb_blank(int blank,
70 struct fb_info *info);
71
72static void sisfb_handle_command(struct sis_video_info *ivideo,
73 struct sisfb_cmd *sisfb_command);
74
75static void sisfb_search_mode(char *name, bool quiet);
76static int sisfb_validate_mode(struct sis_video_info *ivideo, int modeindex, u32 vbflags);
77static u8 sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate,
78 int index);
79static int sisfb_setcolreg(unsigned regno, unsigned red, unsigned green,
80 unsigned blue, unsigned transp,
81 struct fb_info *fb_info);
82static int sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
83 struct fb_info *info);
84static void sisfb_pre_setmode(struct sis_video_info *ivideo);
85static void sisfb_post_setmode(struct sis_video_info *ivideo);
86static bool sisfb_CheckVBRetrace(struct sis_video_info *ivideo);
87static bool sisfbcheckvretracecrt2(struct sis_video_info *ivideo);
88static bool sisfbcheckvretracecrt1(struct sis_video_info *ivideo);
89static bool sisfb_bridgeisslave(struct sis_video_info *ivideo);
90static void sisfb_detect_VB_connect(struct sis_video_info *ivideo);
91static void sisfb_get_VB_type(struct sis_video_info *ivideo);
92static void sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val);
93static void sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val);
94
95/* Internal heap routines */
96static int sisfb_heap_init(struct sis_video_info *ivideo);
97static struct SIS_OH * sisfb_poh_new_node(struct SIS_HEAP *memheap);
98static struct SIS_OH * sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size);
99static void sisfb_delete_node(struct SIS_OH *poh);
100static void sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh);
101static struct SIS_OH * sisfb_poh_free(struct SIS_HEAP *memheap, u32 base);
102static void sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh);
103
104
105/* ------------------ Internal helper routines ----------------- */
106
107static void __init
108sisfb_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
143static 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
182static 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[16], 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(s1: name, s2: 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(p: strbuf1, q: 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(buf: strbuf, fmt: "%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(buf: strbuf, fmt: "%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(buf: strbuf, fmt: "%ux%ux8", xres, yres);
228 nameptr = strbuf;
229 } else {
230 sisfb_search_vesamode(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(s1: nameptr, s2: 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
259static void __init
260sisfb_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(s1: name, s2: 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
285static void __init
286sisfb_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(s1: name, s2: 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
304static void __init
305sisfb_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(s1: name, s2: "none", n: 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(s1: name,s2: 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
349static 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
406static 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
507static 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(SiS_Pr: &ivideo->SiS_Pr, VBFlags: ivideo->vbflags, VGAEngine: ivideo->sisvga_engine,
525 adaptnum: realcrtno, DDCdatatype: 0, buffer: &buffer[0], VBFlags2: 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(SiS_Pr: &ivideo->SiS_Pr, VBFlags: ivideo->vbflags, VGAEngine: ivideo->sisvga_engine,
541 adaptnum: realcrtno, DDCdatatype: 1, buffer: &buffer[0], VBFlags2: ivideo->vbflags2);
542 } while((temp) && i--);
543 if(!temp) {
544 if(sisfb_interpret_edid(monitor, buffer: &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
562static bool
563sisfb_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(SiS_Pr: &ivideo->SiS_Pr,
600 modeno: sisbios_mode[mode_idx].mode_no[ivideo->mni],
601 htotal: &htotal, vtotal: &vtotal, rateindex: 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
616static int
617sisfb_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(VGAEngine: ivideo->sisvga_engine, VBFlags: vbflags, HDisplay: sisbios_mode[myindex].xres,
662 VDisplay: sisbios_mode[myindex].yres, Depth: 0, FSTN: ivideo->sisfb_fstn,
663 CustomT: ivideo->SiS_Pr.SiS_CustomT, LCDwith: xres, LCDheight: yres, VBFlags2: ivideo->vbflags2) < 0x14) {
664 return -1;
665 }
666 break;
667
668 case CRT2_TV:
669 if (SiS_GetModeID_TV(VGAEngine: ivideo->sisvga_engine, VBFlags: vbflags, HDisplay: sisbios_mode[myindex].xres,
670 VDisplay: sisbios_mode[myindex].yres, Depth: 0, VBFlags2: ivideo->vbflags2) < 0x14) {
671 return -1;
672 }
673 break;
674
675 case CRT2_VGA:
676 if (SiS_GetModeID_VGA2(VGAEngine: ivideo->sisvga_engine, VBFlags: vbflags, HDisplay: sisbios_mode[myindex].xres,
677 VDisplay: sisbios_mode[myindex].yres, Depth: 0, VBFlags2: ivideo->vbflags2) < 0x14) {
678 return -1;
679 }
680 break;
681 }
682
683 return myindex;
684}
685
686static u8
687sisfb_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
731static bool
732sisfb_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
748static bool
749sisfballowretracecrt1(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
764static bool
765sisfbcheckvretracecrt1(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
776static void
777sisfbwaitretracecrt1(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
790static bool
791sisfbcheckvretracecrt2(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
808static bool
809sisfb_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
819static u32
820sisfb_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
869static int
870sisfb_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(SiS_Pr: &ivideo->SiS_Pr);
948 } else {
949 SiS_SiS30xBLOff(SiS_Pr: &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(SiS_Pr: &ivideo->SiS_Pr);
956 } else {
957 SiS_Chrontel701xBLOff(SiS_Pr: &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
996unsigned int
997sisfb_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(dev: ivideo->nbridge, where: reg, val: &val);
1003 return (unsigned int)val;
1004}
1005
1006void
1007sisfb_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(dev: ivideo->nbridge, where: reg, val: (u32)val);
1012}
1013
1014unsigned int
1015sisfb_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(dev: ivideo->lpcdev, where: reg, val: &val);
1023 return (unsigned int)val;
1024}
1025#endif
1026
1027#ifdef CONFIG_FB_SIS_315
1028void
1029sisfb_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(dev: ivideo->nbridge, where: reg, val: (u8)val);
1034}
1035
1036unsigned int
1037sisfb_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(dev: ivideo->lpcdev, where: reg, val: &val);
1045 return (unsigned int)val;
1046}
1047#endif
1048
1049/* ----------- FBDev related routines for all series ----------- */
1050
1051static int
1052sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
1053{
1054 return (var->bits_per_pixel == 8) ? 256 : 16;
1055}
1056
1057static void
1058sisfb_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
1083static int
1084sisfb_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
1093static void
1094sisfb_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
1105static void
1106sisfb_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
1128static void
1129sisfb_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
1161static int
1162sisfb_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(SiS_Pr: &ivideo->SiS_Pr, ModeNo: 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
1186static int
1187sisfb_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 myindex: ivideo->sisfb_mode_idx, vbflags: 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, rate: ivideo->refresh_rate, mode_idx: 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, clrscrn: 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
1307static void
1308sisfb_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
1320static void
1321sisfb_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
1334static int
1335sisfb_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, base: ivideo->current_base);
1357 sisfb_set_base_CRT2(ivideo, base: ivideo->current_base);
1358
1359 return 0;
1360}
1361
1362static int
1363sisfb_open(struct fb_info *info, int user)
1364{
1365 return 0;
1366}
1367
1368static int
1369sisfb_release(struct fb_info *info, int user)
1370{
1371 return 0;
1372}
1373
1374static int
1375sisfb_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(var: &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
1419static int
1420sisfb_set_par(struct fb_info *info)
1421{
1422 int err;
1423
1424 if((err = sisfb_do_set_var(var: &info->var, isactive: 1, info)))
1425 return err;
1426
1427 sisfb_get_fix(fix: &info->fix, con: -1, info);
1428
1429 return 0;
1430}
1431
1432static int
1433sisfb_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, myindex: search_idx,
1474 vbflags: 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,myindex: search_idx,
1490 vbflags: 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, rate: refresh_rate, mode_idx: 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(SiS_Pr: &ivideo->SiS_Pr,
1560 modeno: sisbios_mode[search_idx].mode_no[ivideo->mni],
1561 rateindex: myrateindex));
1562 sisfb_mode_rate_to_ddata(SiS_Pr: &ivideo->SiS_Pr,
1563 modeno: sisbios_mode[search_idx].mode_no[ivideo->mni],
1564 rateindex: 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, monitor: &ivideo->sisfb_thismonitor, mode_idx: search_idx,
1572 rate_idx: myrateindex, rate: 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
1624static int
1625sisfb_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
1647static int
1648sisfb_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
1657static 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(to: &sismemreq, from: (void __user *)arg, n: sizeof(sismemreq)))
1675 return -EFAULT;
1676
1677 sis_malloc(req: &sismemreq);
1678
1679 if(copy_to_user(to: (void __user *)arg, from: &sismemreq, n: sizeof(sismemreq))) {
1680 sis_free(base: (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(base: 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, vcount: &sisvbblank.vcount, hcount: &sisvbblank.hcount);
1701
1702 if(copy_to_user(to: (void __user *)arg, from: &sisvbblank, n: 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(to: (void __user *)arg, from: &ivideo->sisfb_infoblock,
1759 n: 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, val: ((int)(gpu32 >> 16)) - 32);
1803 sisfb_set_TVyposoffset(ivideo, val: ((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(to: &ivideo->sisfb_command, from: (void __user *)arg,
1812 n: sizeof(struct sisfb_cmd)))
1813 return -EFAULT;
1814
1815 sisfb_handle_command(ivideo, sisfb_command: &ivideo->sisfb_command);
1816
1817 if(copy_to_user(to: (void __user *)arg, from: &ivideo->sisfb_command,
1818 n: 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
1840static int
1841sisfb_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(lock: &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
1881static 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
1904static 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 device: nbridgeids[nbridgeidx+i], NULL)))
1938 break;
1939 }
1940 return pdev;
1941}
1942
1943static 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(dev: ivideo->nbridge, where: 0x63, val: &reg);
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
2042static 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
2167static bool sisfb_test_DDC1(struct sis_video_info *ivideo)
2168{
2169 unsigned short old;
2170 int count = 48;
2171
2172 old = SiS_ReadDDC1Bit(SiS_Pr: &ivideo->SiS_Pr);
2173 do {
2174 if(old != SiS_ReadDDC1Bit(SiS_Pr: &ivideo->SiS_Pr)) break;
2175 } while(count--);
2176 return (count != -1);
2177}
2178
2179static 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(SiS_Pr: &ivideo->SiS_Pr, VBFlags: ivideo->vbflags,
2244 VGAEngine: ivideo->sisvga_engine, adaptnum: 0, DDCdatatype: 0, NULL, VBFlags2: 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 */
2266static 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(SiS_Pr: &ivideo->SiS_Pr, VBFlags: ivideo->vbflags, VGAEngine: ivideo->sisvga_engine,
2292 adaptnum: realcrtno, DDCdatatype: 0, buffer: &buffer[0], VBFlags2: 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(SiS_Pr: &ivideo->SiS_Pr, VBFlags: ivideo->vbflags,
2301 VGAEngine: ivideo->sisvga_engine, adaptnum: realcrtno, DDCdatatype: 1,
2302 buffer: &buffer[0], VBFlags2: 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
2353static 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(SiS_Pr: &ivideo->SiS_Pr, delaytime: 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(SiS_Pr: &ivideo->SiS_Pr, delaytime: 0x1000);
2376#endif
2377 }
2378
2379 if ((result == 0) || (result >= 2))
2380 break;
2381 }
2382 return result;
2383}
2384
2385static 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(SiS_Pr: &ivideo->SiS_Pr, delaytime: 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, type: 0, test: 0);
2456 }
2457
2458 SiS_SetRegAND(SISCR, 0x32, ~0x14);
2459
2460 if(vga2_c || vga2) {
2461 if(SISDoSense(ivideo, type: vga2, test: 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(SiS_Pr: &ivideo->SiS_Pr, delaytime: 0x2000);
2481 if((result = SISDoSense(ivideo, type: svhs, test: 0x0604))) {
2482 if((result = SISDoSense(ivideo, type: cvbs, test: 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, type: svhs, test: 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, type: cvbs, test: 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, type: 0, test: 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 */
2525static 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(SiS_Pr: &ivideo->SiS_Pr, myvbinfo: 0x9c); /* Set general purpose IO for Chrontel communication */
2541 SiS_DDC2Delay(SiS_Pr: &ivideo->SiS_Pr, delaytime: 1000);
2542 temp1 = SiS_GetCH700x(SiS_Pr: &ivideo->SiS_Pr, tempax: 0x25);
2543 /* See Chrontel TB31 for explanation */
2544 temp2 = SiS_GetCH700x(SiS_Pr: &ivideo->SiS_Pr, tempax: 0x0e);
2545 if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
2546 SiS_SetCH700x(SiS_Pr: &ivideo->SiS_Pr, reg: 0x0e, val: 0x0b);
2547 SiS_DDC2Delay(SiS_Pr: &ivideo->SiS_Pr, delaytime: 300);
2548 }
2549 temp2 = SiS_GetCH700x(SiS_Pr: &ivideo->SiS_Pr, tempax: 0x25);
2550 if(temp2 != temp1) temp1 = temp2;
2551
2552 if((temp1 >= 0x22) && (temp1 <= 0x50)) {
2553 /* Read power status */
2554 temp1 = SiS_GetCH700x(SiS_Pr: &ivideo->SiS_Pr, tempax: 0x0e);
2555 if((temp1 & 0x03) != 0x03) {
2556 /* Power all outputs */
2557 SiS_SetCH700x(SiS_Pr: &ivideo->SiS_Pr, reg: 0x0e,val: 0x0b);
2558 SiS_DDC2Delay(SiS_Pr: &ivideo->SiS_Pr, delaytime: 300);
2559 }
2560 /* Sense connected TV devices */
2561 for(i = 0; i < 3; i++) {
2562 SiS_SetCH700x(SiS_Pr: &ivideo->SiS_Pr, reg: 0x10, val: 0x01);
2563 SiS_DDC2Delay(SiS_Pr: &ivideo->SiS_Pr, delaytime: 0x96);
2564 SiS_SetCH700x(SiS_Pr: &ivideo->SiS_Pr, reg: 0x10, val: 0x00);
2565 SiS_DDC2Delay(SiS_Pr: &ivideo->SiS_Pr, delaytime: 0x96);
2566 temp1 = SiS_GetCH700x(SiS_Pr: &ivideo->SiS_Pr, tempax: 0x10);
2567 if(!(temp1 & 0x08)) test[i] = 0x02;
2568 else if(!(temp1 & 0x02)) test[i] = 0x01;
2569 else test[i] = 0;
2570 SiS_DDC2Delay(SiS_Pr: &ivideo->SiS_Pr, delaytime: 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(SiS_Pr: &ivideo->SiS_Pr, reg: 0x0e, orval: 0x01, andval: 0xF8);
2593 SiS_SetRegAND(SISCR, 0x32, ~0x07);
2594 }
2595 } else if(temp1 == 0) {
2596 SiS_SetCH70xxANDOR(SiS_Pr: &ivideo->SiS_Pr, reg: 0x0e, orval: 0x01, andval: 0xF8);
2597 SiS_SetRegAND(SISCR, 0x32, ~0x07);
2598 }
2599 /* Set general purpose IO for Chrontel communication */
2600 SiS_SetChrontelGPIO(SiS_Pr: &ivideo->SiS_Pr, myvbinfo: 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(SiS_Pr: &ivideo->SiS_Pr, tempax: 0x49);
2608 SiS_SetCH701x(SiS_Pr: &ivideo->SiS_Pr, reg: 0x49, val: 0x20);
2609 SiS_DDC2Delay(SiS_Pr: &ivideo->SiS_Pr, delaytime: 0x96);
2610 temp2 = SiS_GetCH701x(SiS_Pr: &ivideo->SiS_Pr, tempax: 0x20);
2611 temp2 |= 0x01;
2612 SiS_SetCH701x(SiS_Pr: &ivideo->SiS_Pr, reg: 0x20, val: temp2);
2613 SiS_DDC2Delay(SiS_Pr: &ivideo->SiS_Pr, delaytime: 0x96);
2614 temp2 ^= 0x01;
2615 SiS_SetCH701x(SiS_Pr: &ivideo->SiS_Pr, reg: 0x20, val: temp2);
2616 SiS_DDC2Delay(SiS_Pr: &ivideo->SiS_Pr, delaytime: 0x96);
2617 temp2 = SiS_GetCH701x(SiS_Pr: &ivideo->SiS_Pr, tempax: 0x20);
2618 SiS_SetCH701x(SiS_Pr: &ivideo->SiS_Pr, reg: 0x49, val: 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
2649static 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
2797static void
2798sisfb_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(val: 0x16800000 + 0x8240, addr: ivideo->video_vbase + tempq);
2882 writel(val: templ | (1 << 10), addr: ivideo->video_vbase + tempq + 4);
2883 writel(val: 0x168F0000, addr: ivideo->video_vbase + tempq + 8);
2884 writel(val: 0x168F0000, addr: 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
2911static 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
2966static 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
3084static 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
3130static 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
3155static 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(memheap: &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
3209static struct SIS_OH *
3210sisfb_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
3243static struct SIS_OH *
3244sisfb_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(poh: 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(pohList: pohThis, poh: pohRoot);
3291
3292 return pohRoot;
3293}
3294
3295static void
3296sisfb_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
3302static void
3303sisfb_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
3314static struct SIS_OH *
3315sisfb_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: poh_freed);
3357
3358 if(poh_prev && poh_next) {
3359 poh_prev->size += (poh_freed->size + poh_next->size);
3360 sisfb_delete_node(poh: poh_next);
3361 sisfb_free_node(memheap, poh: poh_freed);
3362 sisfb_free_node(memheap, poh: 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: 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: poh_freed);
3376 return poh_next;
3377 }
3378
3379 sisfb_insert_node(pohList: &memheap->oh_free, poh: poh_freed);
3380
3381 return poh_freed;
3382}
3383
3384static void
3385sisfb_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
3394static void
3395sis_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(memheap: &ivideo->sisfb_heap, size: (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
3413void
3414sis_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
3424void
3425sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req)
3426{
3427 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3428
3429 sis_int_malloc(ivideo, req);
3430}
3431
3432/* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
3433
3434static void
3435sis_int_free(struct sis_video_info *ivideo, u32 base)
3436{
3437 struct SIS_OH *poh;
3438
3439 if((!ivideo) || (ivideo->sisfb_id != SISFB_ID) || (ivideo->havenoheap))
3440 return;
3441
3442 poh = sisfb_poh_free(memheap: &ivideo->sisfb_heap, base);
3443
3444 if(poh == NULL) {
3445 DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
3446 (unsigned int) base);
3447 }
3448}
3449
3450void
3451sis_free(u32 base)
3452{
3453 struct sis_video_info *ivideo = sisfb_heap->vinfo;
3454
3455 sis_int_free(ivideo, base);
3456}
3457
3458void
3459sis_free_new(struct pci_dev *pdev, u32 base)
3460{
3461 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
3462
3463 sis_int_free(ivideo, base);
3464}
3465
3466/* --------------------- SetMode routines ------------------------- */
3467
3468static void
3469sisfb_check_engine_and_sync(struct sis_video_info *ivideo)
3470{
3471 u8 cr30, cr31;
3472
3473 /* Check if MMIO and engines are enabled,
3474 * and sync in case they are. Can't use
3475 * ivideo->accel here, as this might have
3476 * been changed before this is called.
3477 */
3478 cr30 = SiS_GetReg(SISSR, IND_SIS_PCI_ADDRESS_SET);
3479 cr31 = SiS_GetReg(SISSR, IND_SIS_MODULE_ENABLE);
3480 /* MMIO and 2D/3D engine enabled? */
3481 if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) {
3482#ifdef CONFIG_FB_SIS_300
3483 if(ivideo->sisvga_engine == SIS_300_VGA) {
3484 /* Don't care about TurboQueue. It's
3485 * enough to know that the engines
3486 * are enabled
3487 */
3488 sisfb_syncaccel(ivideo);
3489 }
3490#endif
3491#ifdef CONFIG_FB_SIS_315
3492 if(ivideo->sisvga_engine == SIS_315_VGA) {
3493 /* Check that any queue mode is
3494 * enabled, and that the queue
3495 * is not in the state of "reset"
3496 */
3497 cr30 = SiS_GetReg(SISSR, 0x26);
3498 if((cr30 & 0xe0) && (!(cr30 & 0x01))) {
3499 sisfb_syncaccel(ivideo);
3500 }
3501 }
3502#endif
3503 }
3504}
3505
3506static void
3507sisfb_pre_setmode(struct sis_video_info *ivideo)
3508{
3509 u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0;
3510 int tvregnum = 0;
3511
3512 ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
3513
3514 SiS_SetReg(SISSR, 0x05, 0x86);
3515
3516 cr31 = SiS_GetReg(SISCR, 0x31);
3517 cr31 &= ~0x60;
3518 cr31 |= 0x04;
3519
3520 cr33 = ivideo->rate_idx & 0x0F;
3521
3522#ifdef CONFIG_FB_SIS_315
3523 if(ivideo->sisvga_engine == SIS_315_VGA) {
3524 if(ivideo->chip >= SIS_661) {
3525 cr38 = SiS_GetReg(SISCR, 0x38);
3526 cr38 &= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */
3527 } else {
3528 tvregnum = 0x38;
3529 cr38 = SiS_GetReg(SISCR, tvregnum);
3530 cr38 &= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */
3531 }
3532 }
3533#endif
3534#ifdef CONFIG_FB_SIS_300
3535 if(ivideo->sisvga_engine == SIS_300_VGA) {
3536 tvregnum = 0x35;
3537 cr38 = SiS_GetReg(SISCR, tvregnum);
3538 }
3539#endif
3540
3541 SiS_SetEnableDstn(SiS_Pr: &ivideo->SiS_Pr, enable: false);
3542 SiS_SetEnableFstn(SiS_Pr: &ivideo->SiS_Pr, enable: false);
3543 ivideo->curFSTN = ivideo->curDSTN = 0;
3544
3545 switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
3546
3547 case CRT2_TV:
3548 cr38 &= ~0xc0; /* Clear PAL-M / PAL-N bits */
3549 if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
3550#ifdef CONFIG_FB_SIS_315
3551 if(ivideo->chip >= SIS_661) {
3552 cr38 |= 0x04;
3553 if(ivideo->vbflags & TV_YPBPR525P) cr35 |= 0x20;
3554 else if(ivideo->vbflags & TV_YPBPR750P) cr35 |= 0x40;
3555 else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60;
3556 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
3557 cr35 &= ~0x01;
3558 ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
3559 } else if(ivideo->sisvga_engine == SIS_315_VGA) {
3560 cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
3561 cr38 |= 0x08;
3562 if(ivideo->vbflags & TV_YPBPR525P) cr38 |= 0x10;
3563 else if(ivideo->vbflags & TV_YPBPR750P) cr38 |= 0x20;
3564 else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30;
3565 cr31 &= ~0x01;
3566 ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
3567 }
3568#endif
3569 } else if((ivideo->vbflags & TV_HIVISION) &&
3570 (ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) {
3571 if(ivideo->chip >= SIS_661) {
3572 cr38 |= 0x04;
3573 cr35 |= 0x60;
3574 } else {
3575 cr30 |= 0x80;
3576 }
3577 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
3578 cr31 |= 0x01;
3579 cr35 |= 0x01;
3580 ivideo->currentvbflags |= TV_HIVISION;
3581 } else if(ivideo->vbflags & TV_SCART) {
3582 cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
3583 cr31 |= 0x01;
3584 cr35 |= 0x01;
3585 ivideo->currentvbflags |= TV_SCART;
3586 } else {
3587 if(ivideo->vbflags & TV_SVIDEO) {
3588 cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
3589 ivideo->currentvbflags |= TV_SVIDEO;
3590 }
3591 if(ivideo->vbflags & TV_AVIDEO) {
3592 cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE);
3593 ivideo->currentvbflags |= TV_AVIDEO;
3594 }
3595 }
3596 cr31 |= SIS_DRIVER_MODE;
3597
3598 if(ivideo->vbflags & (TV_AVIDEO | TV_SVIDEO)) {
3599 if(ivideo->vbflags & TV_PAL) {
3600 cr31 |= 0x01; cr35 |= 0x01;
3601 ivideo->currentvbflags |= TV_PAL;
3602 if(ivideo->vbflags & TV_PALM) {
3603 cr38 |= 0x40; cr35 |= 0x04;
3604 ivideo->currentvbflags |= TV_PALM;
3605 } else if(ivideo->vbflags & TV_PALN) {
3606 cr38 |= 0x80; cr35 |= 0x08;
3607 ivideo->currentvbflags |= TV_PALN;
3608 }
3609 } else {
3610 cr31 &= ~0x01; cr35 &= ~0x01;
3611 ivideo->currentvbflags |= TV_NTSC;
3612 if(ivideo->vbflags & TV_NTSCJ) {
3613 cr38 |= 0x40; cr35 |= 0x02;
3614 ivideo->currentvbflags |= TV_NTSCJ;
3615 }
3616 }
3617 }
3618 break;
3619
3620 case CRT2_LCD:
3621 cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
3622 cr31 |= SIS_DRIVER_MODE;
3623 SiS_SetEnableDstn(SiS_Pr: &ivideo->SiS_Pr, enable: ivideo->sisfb_dstn);
3624 SiS_SetEnableFstn(SiS_Pr: &ivideo->SiS_Pr, enable: ivideo->sisfb_fstn);
3625 ivideo->curFSTN = ivideo->sisfb_fstn;
3626 ivideo->curDSTN = ivideo->sisfb_dstn;
3627 break;
3628
3629 case CRT2_VGA:
3630 cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
3631 cr31 |= SIS_DRIVER_MODE;
3632 if(ivideo->sisfb_nocrt2rate) {
3633 cr33 |= (sisbios_mode[ivideo->sisfb_mode_idx].rate_idx << 4);
3634 } else {
3635 cr33 |= ((ivideo->rate_idx & 0x0F) << 4);
3636 }
3637 break;
3638
3639 default: /* disable CRT2 */
3640 cr30 = 0x00;
3641 cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
3642 }
3643
3644 SiS_SetReg(SISCR, 0x30, cr30);
3645 SiS_SetReg(SISCR, 0x33, cr33);
3646
3647 if(ivideo->chip >= SIS_661) {
3648#ifdef CONFIG_FB_SIS_315
3649 cr31 &= ~0x01; /* Clear PAL flag (now in CR35) */
3650 SiS_SetRegANDOR(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
3651 cr38 &= 0x07; /* Use only LCDA and HiVision/YPbPr bits */
3652 SiS_SetRegANDOR(SISCR, 0x38, 0xf8, cr38);
3653#endif
3654 } else if(ivideo->chip != SIS_300) {
3655 SiS_SetReg(SISCR, tvregnum, cr38);
3656 }
3657 SiS_SetReg(SISCR, 0x31, cr31);
3658
3659 ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
3660
3661 sisfb_check_engine_and_sync(ivideo);
3662}
3663
3664/* Fix SR11 for 661 and later */
3665#ifdef CONFIG_FB_SIS_315
3666static void
3667sisfb_fixup_SR11(struct sis_video_info *ivideo)
3668{
3669 u8 tmpreg;
3670
3671 if(ivideo->chip >= SIS_661) {
3672 tmpreg = SiS_GetReg(SISSR, 0x11);
3673 if(tmpreg & 0x20) {
3674 tmpreg = SiS_GetReg(SISSR, 0x3e);
3675 tmpreg = (tmpreg + 1) & 0xff;
3676 SiS_SetReg(SISSR, 0x3e, tmpreg);
3677 tmpreg = SiS_GetReg(SISSR, 0x11);
3678 }
3679 if(tmpreg & 0xf0) {
3680 SiS_SetRegAND(SISSR, 0x11, 0x0f);
3681 }
3682 }
3683}
3684#endif
3685
3686static void
3687sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
3688{
3689 if(val > 32) val = 32;
3690 if(val < -32) val = -32;
3691 ivideo->tvxpos = val;
3692
3693 if(ivideo->sisfblocked) return;
3694 if(!ivideo->modechanged) return;
3695
3696 if(ivideo->currentvbflags & CRT2_TV) {
3697
3698 if(ivideo->vbflags2 & VB2_CHRONTEL) {
3699
3700 int x = ivideo->tvx;
3701
3702 switch(ivideo->chronteltype) {
3703 case 1:
3704 x += val;
3705 if(x < 0) x = 0;
3706 SiS_SetReg(SISSR, 0x05, 0x86);
3707 SiS_SetCH700x(SiS_Pr: &ivideo->SiS_Pr, reg: 0x0a, val: (x & 0xff));
3708 SiS_SetCH70xxANDOR(SiS_Pr: &ivideo->SiS_Pr, reg: 0x08, orval: ((x & 0x0100) >> 7), andval: 0xFD);
3709 break;
3710 case 2:
3711 /* Not supported by hardware */
3712 break;
3713 }
3714
3715 } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3716
3717 u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
3718 unsigned short temp;
3719
3720 p2_1f = ivideo->p2_1f;
3721 p2_20 = ivideo->p2_20;
3722 p2_2b = ivideo->p2_2b;
3723 p2_42 = ivideo->p2_42;
3724 p2_43 = ivideo->p2_43;
3725
3726 temp = p2_1f | ((p2_20 & 0xf0) << 4);
3727 temp += (val * 2);
3728 p2_1f = temp & 0xff;
3729 p2_20 = (temp & 0xf00) >> 4;
3730 p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
3731 temp = p2_43 | ((p2_42 & 0xf0) << 4);
3732 temp += (val * 2);
3733 p2_43 = temp & 0xff;
3734 p2_42 = (temp & 0xf00) >> 4;
3735 SiS_SetReg(SISPART2, 0x1f, p2_1f);
3736 SiS_SetRegANDOR(SISPART2, 0x20, 0x0F, p2_20);
3737 SiS_SetRegANDOR(SISPART2, 0x2b, 0xF0, p2_2b);
3738 SiS_SetRegANDOR(SISPART2, 0x42, 0x0F, p2_42);
3739 SiS_SetReg(SISPART2, 0x43, p2_43);
3740 }
3741 }
3742}
3743
3744static void
3745sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
3746{
3747 if(val > 32) val = 32;
3748 if(val < -32) val = -32;
3749 ivideo->tvypos = val;
3750
3751 if(ivideo->sisfblocked) return;
3752 if(!ivideo->modechanged) return;
3753
3754 if(ivideo->currentvbflags & CRT2_TV) {
3755
3756 if(ivideo->vbflags2 & VB2_CHRONTEL) {
3757
3758 int y = ivideo->tvy;
3759
3760 switch(ivideo->chronteltype) {
3761 case 1:
3762 y -= val;
3763 if(y < 0) y = 0;
3764 SiS_SetReg(SISSR, 0x05, 0x86);
3765 SiS_SetCH700x(SiS_Pr: &ivideo->SiS_Pr, reg: 0x0b, val: (y & 0xff));
3766 SiS_SetCH70xxANDOR(SiS_Pr: &ivideo->SiS_Pr, reg: 0x08, orval: ((y & 0x0100) >> 8), andval: 0xFE);
3767 break;
3768 case 2:
3769 /* Not supported by hardware */
3770 break;
3771 }
3772
3773 } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3774
3775 char p2_01, p2_02;
3776 val /= 2;
3777 p2_01 = ivideo->p2_01;
3778 p2_02 = ivideo->p2_02;
3779
3780 p2_01 += val;
3781 p2_02 += val;
3782 if(!(ivideo->currentvbflags & (TV_HIVISION | TV_YPBPR))) {
3783 while((p2_01 <= 0) || (p2_02 <= 0)) {
3784 p2_01 += 2;
3785 p2_02 += 2;
3786 }
3787 }
3788 SiS_SetReg(SISPART2, 0x01, p2_01);
3789 SiS_SetReg(SISPART2, 0x02, p2_02);
3790 }
3791 }
3792}
3793
3794static void
3795sisfb_post_setmode(struct sis_video_info *ivideo)
3796{
3797 bool crt1isoff = false;
3798 bool doit = true;
3799#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
3800 u8 reg;
3801#endif
3802#ifdef CONFIG_FB_SIS_315
3803 u8 reg1;
3804#endif
3805
3806 SiS_SetReg(SISSR, 0x05, 0x86);
3807
3808#ifdef CONFIG_FB_SIS_315
3809 sisfb_fixup_SR11(ivideo);
3810#endif
3811
3812 /* Now we actually HAVE changed the display mode */
3813 ivideo->modechanged = 1;
3814
3815 /* We can't switch off CRT1 if bridge is in slave mode */
3816 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
3817 if(sisfb_bridgeisslave(ivideo)) doit = false;
3818 } else
3819 ivideo->sisfb_crt1off = 0;
3820
3821#ifdef CONFIG_FB_SIS_300
3822 if(ivideo->sisvga_engine == SIS_300_VGA) {
3823 if((ivideo->sisfb_crt1off) && (doit)) {
3824 crt1isoff = true;
3825 reg = 0x00;
3826 } else {
3827 crt1isoff = false;
3828 reg = 0x80;
3829 }
3830 SiS_SetRegANDOR(SISCR, 0x17, 0x7f, reg);
3831 }
3832#endif
3833#ifdef CONFIG_FB_SIS_315
3834 if(ivideo->sisvga_engine == SIS_315_VGA) {
3835 if((ivideo->sisfb_crt1off) && (doit)) {
3836 crt1isoff = true;
3837 reg = 0x40;
3838 reg1 = 0xc0;
3839 } else {
3840 crt1isoff = false;
3841 reg = 0x00;
3842 reg1 = 0x00;
3843 }
3844 SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
3845 SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, reg1);
3846 }
3847#endif
3848
3849 if(crt1isoff) {
3850 ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
3851 ivideo->currentvbflags |= VB_SINGLE_MODE;
3852 } else {
3853 ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
3854 if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
3855 ivideo->currentvbflags |= VB_MIRROR_MODE;
3856 } else {
3857 ivideo->currentvbflags |= VB_SINGLE_MODE;
3858 }
3859 }
3860
3861 SiS_SetRegAND(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
3862
3863 if(ivideo->currentvbflags & CRT2_TV) {
3864 if(ivideo->vbflags2 & VB2_SISBRIDGE) {
3865 ivideo->p2_1f = SiS_GetReg(SISPART2, 0x1f);
3866 ivideo->p2_20 = SiS_GetReg(SISPART2, 0x20);
3867 ivideo->p2_2b = SiS_GetReg(SISPART2, 0x2b);
3868 ivideo->p2_42 = SiS_GetReg(SISPART2, 0x42);
3869 ivideo->p2_43 = SiS_GetReg(SISPART2, 0x43);
3870 ivideo->p2_01 = SiS_GetReg(SISPART2, 0x01);
3871 ivideo->p2_02 = SiS_GetReg(SISPART2, 0x02);
3872 } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
3873 if(ivideo->chronteltype == 1) {
3874 ivideo->tvx = SiS_GetCH700x(SiS_Pr: &ivideo->SiS_Pr, tempax: 0x0a);
3875 ivideo->tvx |= (((SiS_GetCH700x(SiS_Pr: &ivideo->SiS_Pr, tempax: 0x08) & 0x02) >> 1) << 8);
3876 ivideo->tvy = SiS_GetCH700x(SiS_Pr: &ivideo->SiS_Pr, tempax: 0x0b);
3877 ivideo->tvy |= ((SiS_GetCH700x(SiS_Pr: &ivideo->SiS_Pr, tempax: 0x08) & 0x01) << 8);
3878 }
3879 }
3880 }
3881
3882 if(ivideo->tvxpos) {
3883 sisfb_set_TVxposoffset(ivideo, val: ivideo->tvxpos);
3884 }
3885 if(ivideo->tvypos) {
3886 sisfb_set_TVyposoffset(ivideo, val: ivideo->tvypos);
3887 }
3888
3889 /* Eventually sync engines */
3890 sisfb_check_engine_and_sync(ivideo);
3891
3892 /* (Re-)Initialize chip engines */
3893 if(ivideo->accel) {
3894 sisfb_engine_init(ivideo);
3895 } else {
3896 ivideo->engineok = 0;
3897 }
3898}
3899
3900static int
3901sisfb_reset_mode(struct sis_video_info *ivideo)
3902{
3903 if(sisfb_set_mode(ivideo, clrscrn: 0))
3904 return 1;
3905
3906 sisfb_set_pitch(ivideo);
3907 sisfb_set_base_CRT1(ivideo, base: ivideo->current_base);
3908 sisfb_set_base_CRT2(ivideo, base: ivideo->current_base);
3909
3910 return 0;
3911}
3912
3913static void
3914sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_command)
3915{
3916 int mycrt1off;
3917
3918 switch(sisfb_command->sisfb_cmd) {
3919 case SISFB_CMD_GETVBFLAGS:
3920 if(!ivideo->modechanged) {
3921 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
3922 } else {
3923 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3924 sisfb_command->sisfb_result[1] = ivideo->currentvbflags;
3925 sisfb_command->sisfb_result[2] = ivideo->vbflags2;
3926 }
3927 break;
3928 case SISFB_CMD_SWITCHCRT1:
3929 /* arg[0]: 0 = off, 1 = on, 99 = query */
3930 if(!ivideo->modechanged) {
3931 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
3932 } else if(sisfb_command->sisfb_arg[0] == 99) {
3933 /* Query */
3934 sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
3935 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3936 } else if(ivideo->sisfblocked) {
3937 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_LOCKED;
3938 } else if((!(ivideo->currentvbflags & CRT2_ENABLE)) &&
3939 (sisfb_command->sisfb_arg[0] == 0)) {
3940 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_NOCRT2;
3941 } else {
3942 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
3943 mycrt1off = sisfb_command->sisfb_arg[0] ? 0 : 1;
3944 if( ((ivideo->currentvbflags & VB_DISPTYPE_CRT1) && mycrt1off) ||
3945 ((!(ivideo->currentvbflags & VB_DISPTYPE_CRT1)) && !mycrt1off) ) {
3946 ivideo->sisfb_crt1off = mycrt1off;
3947 if(sisfb_reset_mode(ivideo)) {
3948 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OTHER;
3949 }
3950 }
3951 sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
3952 }
3953 break;
3954 /* more to come */
3955 default:
3956 sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_UNKNOWN;
3957 printk(KERN_ERR "sisfb: Unknown command 0x%x\n",
3958 sisfb_command->sisfb_cmd);
3959 }
3960}
3961
3962#ifndef MODULE
3963static int __init sisfb_setup(char *options)
3964{
3965 char *this_opt;
3966
3967 sisfb_setdefaultparms();
3968
3969 if(!options || !(*options))
3970 return 0;
3971
3972 while((this_opt = strsep(&options, ",")) != NULL) {
3973
3974 if(!(*this_opt)) continue;
3975
3976 if(!strncasecmp(s1: this_opt, s2: "off", n: 3)) {
3977 sisfb_off = 1;
3978 } else if(!strncasecmp(s1: this_opt, s2: "forcecrt2type:", n: 14)) {
3979 /* Need to check crt2 type first for fstn/dstn */
3980 sisfb_search_crt2type(name: this_opt + 14);
3981 } else if(!strncasecmp(s1: this_opt, s2: "tvmode:",n: 7)) {
3982 sisfb_search_tvstd(name: this_opt + 7);
3983 } else if(!strncasecmp(s1: this_opt, s2: "tvstandard:",n: 11)) {
3984 sisfb_search_tvstd(name: this_opt + 11);
3985 } else if(!strncasecmp(s1: this_opt, s2: "mode:", n: 5)) {
3986 sisfb_search_mode(name: this_opt + 5, quiet: false);
3987 } else if(!strncasecmp(s1: this_opt, s2: "vesa:", n: 5)) {
3988 sisfb_search_vesamode(vesamode: simple_strtoul(this_opt + 5, NULL, 0), quiet: false);
3989 } else if(!strncasecmp(s1: this_opt, s2: "rate:", n: 5)) {
3990 sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
3991 } else if(!strncasecmp(s1: this_opt, s2: "forcecrt1:", n: 10)) {
3992 sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
3993 } else if(!strncasecmp(s1: this_opt, s2: "mem:",n: 4)) {
3994 sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
3995 } else if(!strncasecmp(s1: this_opt, s2: "pdc:", n: 4)) {
3996 sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
3997 } else if(!strncasecmp(s1: this_opt, s2: "pdc1:", n: 5)) {
3998 sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
3999 } else if(!strncasecmp(s1: this_opt, s2: "noaccel", n: 7)) {
4000 sisfb_accel = 0;
4001 } else if(!strncasecmp(s1: this_opt, s2: "accel", n: 5)) {
4002 sisfb_accel = -1;
4003 } else if(!strncasecmp(s1: this_opt, s2: "noypan", n: 6)) {
4004 sisfb_ypan = 0;
4005 } else if(!strncasecmp(s1: this_opt, s2: "ypan", n: 4)) {
4006 sisfb_ypan = -1;
4007 } else if(!strncasecmp(s1: this_opt, s2: "nomax", n: 5)) {
4008 sisfb_max = 0;
4009 } else if(!strncasecmp(s1: this_opt, s2: "max", n: 3)) {
4010 sisfb_max = -1;
4011 } else if(!strncasecmp(s1: this_opt, s2: "userom:", n: 7)) {
4012 sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
4013 } else if(!strncasecmp(s1: this_opt, s2: "useoem:", n: 7)) {
4014 sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
4015 } else if(!strncasecmp(s1: this_opt, s2: "nocrt2rate", n: 10)) {
4016 sisfb_nocrt2rate = 1;
4017 } else if(!strncasecmp(s1: this_opt, s2: "scalelcd:", n: 9)) {
4018 unsigned long temp = 2;
4019 temp = simple_strtoul(this_opt + 9, NULL, 0);
4020 if((temp == 0) || (temp == 1)) {
4021 sisfb_scalelcd = temp ^ 1;
4022 }
4023 } else if(!strncasecmp(s1: this_opt, s2: "tvxposoffset:", n: 13)) {
4024 int temp = 0;
4025 temp = (int)simple_strtol(this_opt + 13, NULL, 0);
4026 if((temp >= -32) && (temp <= 32)) {
4027 sisfb_tvxposoffset = temp;
4028 }
4029 } else if(!strncasecmp(s1: this_opt, s2: "tvyposoffset:", n: 13)) {
4030 int temp = 0;
4031 temp = (int)simple_strtol(this_opt + 13, NULL, 0);
4032 if((temp >= -32) && (temp <= 32)) {
4033 sisfb_tvyposoffset = temp;
4034 }
4035 } else if(!strncasecmp(s1: this_opt, s2: "specialtiming:", n: 14)) {
4036 sisfb_search_specialtiming(name: this_opt + 14);
4037 } else if(!strncasecmp(s1: this_opt, s2: "lvdshl:", n: 7)) {
4038 int temp = 4;
4039 temp = simple_strtoul(this_opt + 7, NULL, 0);
4040 if((temp >= 0) && (temp <= 3)) {
4041 sisfb_lvdshl = temp;
4042 }
4043 } else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
4044 sisfb_search_mode(name: this_opt, quiet: true);
4045#if !defined(__i386__) && !defined(__x86_64__)
4046 } else if(!strncasecmp(this_opt, "resetcard", 9)) {
4047 sisfb_resetcard = 1;
4048 } else if(!strncasecmp(this_opt, "videoram:", 9)) {
4049 sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
4050#endif
4051 } else {
4052 printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
4053 }
4054
4055 }
4056
4057 return 0;
4058}
4059#endif
4060
4061static int sisfb_check_rom(void __iomem *rom_base,
4062 struct sis_video_info *ivideo)
4063{
4064 void __iomem *rom;
4065 int romptr;
4066
4067 if((readb(addr: rom_base) != 0x55) || (readb(addr: rom_base + 1) != 0xaa))
4068 return 0;
4069
4070 romptr = (readb(addr: rom_base + 0x18) | (readb(addr: rom_base + 0x19) << 8));
4071 if(romptr > (0x10000 - 8))
4072 return 0;
4073
4074 rom = rom_base + romptr;
4075
4076 if((readb(addr: rom) != 'P') || (readb(addr: rom + 1) != 'C') ||
4077 (readb(addr: rom + 2) != 'I') || (readb(addr: rom + 3) != 'R'))
4078 return 0;
4079
4080 if((readb(addr: rom + 4) | (readb(addr: rom + 5) << 8)) != ivideo->chip_vendor)
4081 return 0;
4082
4083 if((readb(addr: rom + 6) | (readb(addr: rom + 7) << 8)) != ivideo->chip_id)
4084 return 0;
4085
4086 return 1;
4087}
4088
4089static unsigned char *sisfb_find_rom(struct pci_dev *pdev)
4090{
4091 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4092 void __iomem *rom_base;
4093 unsigned char *myrombase = NULL;
4094 size_t romsize;
4095
4096 /* First, try the official pci ROM functions (except
4097 * on integrated chipsets which have no ROM).
4098 */
4099
4100 if(!ivideo->nbridge) {
4101
4102 if((rom_base = pci_map_rom(pdev, size: &romsize))) {
4103
4104 if(sisfb_check_rom(rom_base, ivideo)) {
4105
4106 if((myrombase = vmalloc(size: 65536))) {
4107 memcpy_fromio(myrombase, rom_base,
4108 (romsize > 65536) ? 65536 : romsize);
4109 }
4110 }
4111 pci_unmap_rom(pdev, rom: rom_base);
4112 }
4113 }
4114
4115 if(myrombase) return myrombase;
4116
4117 /* Otherwise do it the conventional way. */
4118
4119#if defined(__i386__) || defined(__x86_64__)
4120 {
4121 u32 temp;
4122
4123 for (temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
4124
4125 rom_base = ioremap(offset: temp, size: 65536);
4126 if (!rom_base)
4127 continue;
4128
4129 if (!sisfb_check_rom(rom_base, ivideo)) {
4130 iounmap(addr: rom_base);
4131 continue;
4132 }
4133
4134 if ((myrombase = vmalloc(size: 65536)))
4135 memcpy_fromio(myrombase, rom_base, 65536);
4136
4137 iounmap(addr: rom_base);
4138 break;
4139
4140 }
4141
4142 }
4143#endif
4144
4145 return myrombase;
4146}
4147
4148static void sisfb_post_map_vram(struct sis_video_info *ivideo,
4149 unsigned int *mapsize, unsigned int min)
4150{
4151 if (*mapsize < (min << 20))
4152 return;
4153
4154 ivideo->video_vbase = ioremap_wc(offset: ivideo->video_base, size: (*mapsize));
4155
4156 if(!ivideo->video_vbase) {
4157 printk(KERN_ERR
4158 "sisfb: Unable to map maximum video RAM for size detection\n");
4159 (*mapsize) >>= 1;
4160 while((!(ivideo->video_vbase = ioremap_wc(offset: ivideo->video_base, size: (*mapsize))))) {
4161 (*mapsize) >>= 1;
4162 if((*mapsize) < (min << 20))
4163 break;
4164 }
4165 if(ivideo->video_vbase) {
4166 printk(KERN_ERR
4167 "sisfb: Video RAM size detection limited to %dMB\n",
4168 (int)((*mapsize) >> 20));
4169 }
4170 }
4171}
4172
4173#ifdef CONFIG_FB_SIS_300
4174static int sisfb_post_300_buswidth(struct sis_video_info *ivideo)
4175{
4176 void __iomem *FBAddress = ivideo->video_vbase;
4177 unsigned short temp;
4178 unsigned char reg;
4179 int i, j;
4180
4181 SiS_SetRegAND(SISSR, 0x15, 0xFB);
4182 SiS_SetRegOR(SISSR, 0x15, 0x04);
4183 SiS_SetReg(SISSR, 0x13, 0x00);
4184 SiS_SetReg(SISSR, 0x14, 0xBF);
4185
4186 for(i = 0; i < 2; i++) {
4187 temp = 0x1234;
4188 for(j = 0; j < 4; j++) {
4189 writew(val: temp, addr: FBAddress);
4190 if(readw(addr: FBAddress) == temp)
4191 break;
4192 SiS_SetRegOR(SISSR, 0x3c, 0x01);
4193 reg = SiS_GetReg(SISSR, 0x05);
4194 reg = SiS_GetReg(SISSR, 0x05);
4195 SiS_SetRegAND(SISSR, 0x3c, 0xfe);
4196 reg = SiS_GetReg(SISSR, 0x05);
4197 reg = SiS_GetReg(SISSR, 0x05);
4198 temp++;
4199 }
4200 }
4201
4202 writel(val: 0x01234567L, addr: FBAddress);
4203 writel(val: 0x456789ABL, addr: (FBAddress + 4));
4204 writel(val: 0x89ABCDEFL, addr: (FBAddress + 8));
4205 writel(val: 0xCDEF0123L, addr: (FBAddress + 12));
4206
4207 reg = SiS_GetReg(SISSR, 0x3b);
4208 if(reg & 0x01) {
4209 if(readl(addr: (FBAddress + 12)) == 0xCDEF0123L)
4210 return 4; /* Channel A 128bit */
4211 }
4212
4213 if(readl(addr: (FBAddress + 4)) == 0x456789ABL)
4214 return 2; /* Channel B 64bit */
4215
4216 return 1; /* 32bit */
4217}
4218
4219static const unsigned short SiS_DRAMType[17][5] = {
4220 {0x0C,0x0A,0x02,0x40,0x39},
4221 {0x0D,0x0A,0x01,0x40,0x48},
4222 {0x0C,0x09,0x02,0x20,0x35},
4223 {0x0D,0x09,0x01,0x20,0x44},
4224 {0x0C,0x08,0x02,0x10,0x31},
4225 {0x0D,0x08,0x01,0x10,0x40},
4226 {0x0C,0x0A,0x01,0x20,0x34},
4227 {0x0C,0x09,0x01,0x08,0x32},
4228 {0x0B,0x08,0x02,0x08,0x21},
4229 {0x0C,0x08,0x01,0x08,0x30},
4230 {0x0A,0x08,0x02,0x04,0x11},
4231 {0x0B,0x0A,0x01,0x10,0x28},
4232 {0x09,0x08,0x02,0x02,0x01},
4233 {0x0B,0x09,0x01,0x08,0x24},
4234 {0x0B,0x08,0x01,0x04,0x20},
4235 {0x0A,0x08,0x01,0x02,0x10},
4236 {0x09,0x08,0x01,0x01,0x00}
4237};
4238
4239static int sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration,
4240 int buswidth, int PseudoRankCapacity,
4241 int PseudoAdrPinCount, unsigned int mapsize)
4242{
4243 void __iomem *FBAddr = ivideo->video_vbase;
4244 unsigned short sr14;
4245 unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
4246 unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
4247
4248 for (k = 0; k < ARRAY_SIZE(SiS_DRAMType); k++) {
4249 RankCapacity = buswidth * SiS_DRAMType[k][3];
4250
4251 if (RankCapacity != PseudoRankCapacity)
4252 continue;
4253
4254 if ((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount)
4255 continue;
4256
4257 BankNumHigh = RankCapacity * 16 * iteration - 1;
4258 if (iteration == 3) { /* Rank No */
4259 BankNumMid = RankCapacity * 16 - 1;
4260 } else {
4261 BankNumMid = RankCapacity * 16 * iteration / 2 - 1;
4262 }
4263
4264 PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
4265 PhysicalAdrHigh = BankNumHigh;
4266 PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
4267 PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
4268
4269 SiS_SetRegAND(SISSR, 0x15, 0xFB); /* Test */
4270 SiS_SetRegOR(SISSR, 0x15, 0x04); /* Test */
4271 sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
4272
4273 if (buswidth == 4)
4274 sr14 |= 0x80;
4275 else if (buswidth == 2)
4276 sr14 |= 0x40;
4277
4278 SiS_SetReg(SISSR, 0x13, SiS_DRAMType[k][4]);
4279 SiS_SetReg(SISSR, 0x14, sr14);
4280
4281 BankNumHigh <<= 16;
4282 BankNumMid <<= 16;
4283
4284 if ((BankNumHigh + PhysicalAdrHigh >= mapsize) ||
4285 (BankNumMid + PhysicalAdrHigh >= mapsize) ||
4286 (BankNumHigh + PhysicalAdrHalfPage >= mapsize) ||
4287 (BankNumHigh + PhysicalAdrOtherPage >= mapsize))
4288 continue;
4289
4290 /* Write data */
4291 writew(val: ((unsigned short)PhysicalAdrHigh),
4292 addr: (FBAddr + BankNumHigh + PhysicalAdrHigh));
4293 writew(val: ((unsigned short)BankNumMid),
4294 addr: (FBAddr + BankNumMid + PhysicalAdrHigh));
4295 writew(val: ((unsigned short)PhysicalAdrHalfPage),
4296 addr: (FBAddr + BankNumHigh + PhysicalAdrHalfPage));
4297 writew(val: ((unsigned short)PhysicalAdrOtherPage),
4298 addr: (FBAddr + BankNumHigh + PhysicalAdrOtherPage));
4299
4300 /* Read data */
4301 if (readw(addr: FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh)
4302 return 1;
4303 }
4304
4305 return 0;
4306}
4307
4308static void sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize)
4309{
4310 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4311 int i, j, buswidth;
4312 int PseudoRankCapacity, PseudoAdrPinCount;
4313
4314 buswidth = sisfb_post_300_buswidth(ivideo);
4315
4316 for(i = 6; i >= 0; i--) {
4317 PseudoRankCapacity = 1 << i;
4318 for(j = 4; j >= 1; j--) {
4319 PseudoAdrPinCount = 15 - j;
4320 if((PseudoRankCapacity * j) <= 64) {
4321 if(sisfb_post_300_rwtest(ivideo,
4322 iteration: j,
4323 buswidth,
4324 PseudoRankCapacity,
4325 PseudoAdrPinCount,
4326 mapsize))
4327 return;
4328 }
4329 }
4330 }
4331}
4332
4333static void sisfb_post_sis300(struct pci_dev *pdev)
4334{
4335 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
4336 unsigned char *bios = ivideo->SiS_Pr.VirtualRomBase;
4337 u8 reg, v1, v2, v3, v4, v5, v6, v7, v8;
4338 u16 index, rindex, memtype = 0;
4339 unsigned int mapsize;
4340
4341 if(!ivideo->SiS_Pr.UseROM)
4342 bios = NULL;
4343
4344 SiS_SetReg(SISSR, 0x05, 0x86);
4345
4346 if(bios) {
4347 if(bios[0x52] & 0x80) {
4348 memtype = bios[0x52];
4349 } else {
4350 memtype = SiS_GetReg(SISSR, 0x3a);
4351 }
4352 memtype &= 0x07;
4353 }
4354
4355 v3 = 0x80; v6 = 0x80;
4356 if(ivideo->revision_id <= 0x13) {
4357 v1 = 0x44; v2 = 0x42;
4358 v4 = 0x44; v5 = 0x42;
4359 } else {
4360 v1 = 0x68; v2 = 0x43; /* Assume 125Mhz MCLK */
4361 v4 = 0x68; v5 = 0x43; /* Assume 125Mhz ECLK */
4362 if(bios) {
4363 index = memtype * 5;
4364 rindex = index + 0x54;
4365 v1 = bios[rindex++];
4366 v2 = bios[rindex++];
4367 v3 = bios[rindex++];
4368 rindex = index + 0x7c;
4369 v4 = bios[rindex++];
4370 v5 = bios[rindex++];
4371 v6 = bios[rindex++];
4372 }
4373 }
4374 SiS_SetReg(SISSR, 0x28, v1);
4375 SiS_SetReg(SISSR, 0x29, v2);
4376 SiS_SetReg(SISSR, 0x2a, v3);
4377 SiS_SetReg(SISSR, 0x2e, v4);
4378 SiS_SetReg(SISSR, 0x2f, v5);
4379 SiS_SetReg(SISSR, 0x30, v6);
4380
4381 v1 = 0x10;
4382 if(bios)
4383 v1 = bios[0xa4];
4384 SiS_SetReg(SISSR, 0x07, v1); /* DAC speed */
4385
4386 SiS_SetReg(SISSR, 0x11, 0x0f); /* DDC, power save */
4387
4388 v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
4389 v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
4390 if(bios) {
4391 memtype += 0xa5;
4392 v1 = bios[memtype];
4393 v2 = bios[memtype + 8];
4394 v3 = bios[memtype + 16];
4395 v4 = bios[memtype + 24];
4396 v5 = bios[memtype + 32];
4397 v6 = bios[memtype + 40];
4398 v7 = bios[memtype + 48];
4399 v8 = bios[memtype + 56];
4400 }
4401 if(ivideo->revision_id >= 0x80)
4402 v3 &= 0xfd;
4403 SiS_SetReg(SISSR, 0x15, v1); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
4404 SiS_SetReg(SISSR, 0x16, v2);
4405 SiS_SetReg(SISSR, 0x17, v3);
4406 SiS_SetReg(SISSR, 0x18, v4);
4407 SiS_SetReg(SISSR, 0x19, v5);
4408 SiS_SetReg(SISSR, 0x1a, v6);
4409 SiS_SetReg(SISSR, 0x1b, v7);
4410 SiS_SetReg(SISSR, 0x1c, v8); /* ---- */
4411 SiS_SetRegAND(SISSR, 0x15, 0xfb);
4412 SiS_SetRegOR(SISSR, 0x15, 0x04);
4413 if(bios) {
4414 if(bios[0x53] & 0x02) {
4415 SiS_SetRegOR(SISSR, 0x19, 0x20);
4416 }
4417 }
4418 v1 = 0x04; /* DAC pedestal (BIOS 0xe5) */
4419 if(ivideo->revision_id >= 0x80)
4420 v1 |= 0x01;
4421 SiS_SetReg(SISSR, 0x1f, v1);
4422 SiS_SetReg(SISSR, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
4423 v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
4424 if(bios) {
4425 v1 = bios[0xe8];
4426 v2 = bios[0xe9];
4427 v3 = bios[0xea];
4428 }
4429 SiS_SetReg(SISSR, 0x23, v1);
4430 SiS_SetReg(SISSR, 0x24, v2);
4431 SiS_SetReg(SISSR, 0x25, v3);
4432 SiS_SetReg(SISSR, 0x21, 0x84);
4433 SiS_SetReg(SISSR, 0x22, 0x00);
4434 SiS_SetReg(SISCR, 0x37, 0x00);
4435 SiS_SetRegOR(SISPART1, 0x24, 0x01); /* unlock crt2 */
4436 SiS_SetReg(SISPART1, 0x00, 0x00);
4437 v1 = 0x40; v2 = 0x11;
4438 if(bios) {
4439 v1 = bios[0xec];
4440 v2 = bios[0xeb];
4441 }
4442 SiS_SetReg(SISPART1, 0x02, v1);
4443
4444 if(ivideo->revision_id >= 0x80)
4445 v2 &= ~0x01;
4446
4447 reg = SiS_GetReg(SISPART4, 0x00);
4448 if((reg == 1) || (reg == 2)) {
4449 SiS_SetReg(SISCR, 0x37, 0x02);
4450 SiS_SetReg(SISPART2, 0x00, 0x1c);
4451 v4 = 0x00; v5 = 0x00; v6 = 0x10;
4452 if (ivideo->SiS_Pr.UseROM && bios) {
4453 v4 = bios[0xf5];
4454 v5 = bios[0xf6];
4455 v6 = bios[0xf7];
4456 }
4457 SiS_SetReg(SISPART4, 0x0d, v4);
4458 SiS_SetReg(SISPART4, 0x0e, v5);
4459 SiS_SetReg(SISPART4, 0x10, v6);
4460 SiS_SetReg(SISPART4, 0x0f, 0x3f);
4461 reg = SiS_GetReg(SISPART4, 0x01);
4462 if(reg >= 0xb0) {
4463 reg = SiS_GetReg(SISPART4, 0x23);
4464 reg &= 0x20;
4465 reg <<= 1;
4466 SiS_SetReg(SISPART4, 0x23, reg);
4467 }
4468 } else {
4469 v2 &= ~0x10;
4470 }
4471 SiS_SetReg(SISSR, 0x32, v2);
4472
4473 SiS_SetRegAND(SISPART1, 0x24, 0xfe); /* Lock CRT2 */
4474
4475 reg = SiS_GetReg(SISSR, 0x16);
4476 reg &= 0xc3;
4477 SiS_SetReg(SISCR, 0x35, reg);
4478 SiS_SetReg(SISCR, 0x83, 0x00);
4479#if !defined(__i386__) && !defined(__x86_64__)
4480 if(sisfb_videoram) {
4481 SiS_SetReg(SISSR, 0x13, 0x28); /* ? */
4482 reg = ((sisfb_videoram >> 10) - 1) | 0x40;
4483 SiS_SetReg(SISSR, 0x14, reg);
4484 } else {
4485#endif
4486 /* Need to map max FB size for finding out about RAM size */
4487 mapsize = ivideo->video_size;
4488 sisfb_post_map_vram(ivideo, mapsize: &mapsize, min: 4);
4489
4490 if(ivideo->video_vbase) {
4491 sisfb_post_300_ramsize(pdev, mapsize);
4492 iounmap(addr: ivideo->video_vbase);
4493 } else {
4494 printk(KERN_DEBUG
4495 "sisfb: Failed to map memory for size detection, assuming 8MB\n");
4496 SiS_SetReg(SISSR, 0x13, 0x28); /* ? */
4497 SiS_SetReg(SISSR, 0x14, 0x47); /* 8MB, 64bit default */
4498 }
4499#if !defined(__i386__) && !defined(__x86_64__)
4500 }
4501#endif
4502 if(bios) {
4503 v1 = bios[0xe6];
4504 v2 = bios[0xe7];
4505 } else {
4506 reg = SiS_GetReg(SISSR, 0x3a);
4507 if((reg & 0x30) == 0x30) {
4508 v1 = 0x04; /* PCI */
4509 v2 = 0x92;
4510 } else {
4511 v1 = 0x14; /* AGP */
4512 v2 = 0xb2;
4513 }
4514 }
4515 SiS_SetReg(SISSR, 0x21, v1);
4516 SiS_SetReg(SISSR, 0x22, v2);
4517
4518 /* Sense CRT1 */
4519 sisfb_sense_crt1(ivideo);
4520
4521 /* Set default mode, don't clear screen */
4522 ivideo->SiS_Pr.SiS_UseOEM = false;
4523 SiS_SetEnableDstn(SiS_Pr: &ivideo->SiS_Pr, enable: false);
4524 SiS_SetEnableFstn(SiS_Pr: &ivideo->SiS_Pr, enable: false);
4525 ivideo->curFSTN = ivideo->curDSTN = 0;
4526 ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
4527 SiSSetMode(SiS_Pr: &ivideo->SiS_Pr, ModeNo: 0x2e | 0x80);
4528
4529 SiS_SetReg(SISSR, 0x05, 0x86);
4530
4531 /* Display off */
4532 SiS_SetRegOR(SISSR, 0x01, 0x20);
4533
4534 /* Save mode number in CR34 */
4535 SiS_SetReg(SISCR, 0x34, 0x2e);
4536
4537 /* Let everyone know what the current mode is */
4538 ivideo->modeprechange = 0x2e;
4539}
4540#endif
4541
4542#ifdef CONFIG_FB_SIS_315
4543#if 0
4544static void sisfb_post_sis315330(struct pci_dev *pdev)
4545{
4546 /* TODO */
4547}
4548#endif
4549
4550static inline int sisfb_xgi_is21(struct sis_video_info *ivideo)
4551{
4552 return ivideo->chip_real_id == XGI_21;
4553}
4554
4555static void sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
4556{
4557 unsigned int i;
4558 u8 reg;
4559
4560 for(i = 0; i <= (delay * 10 * 36); i++) {
4561 reg = SiS_GetReg(SISSR, 0x05);
4562 reg++;
4563 }
4564}
4565
4566static int sisfb_find_host_bridge(struct sis_video_info *ivideo,
4567 struct pci_dev *mypdev,
4568 unsigned short pcivendor)
4569{
4570 struct pci_dev *pdev = NULL;
4571 unsigned short temp;
4572 int ret = 0;
4573
4574 while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, from: pdev))) {
4575 temp = pdev->vendor;
4576 if(temp == pcivendor) {
4577 ret = 1;
4578 pci_dev_put(dev: pdev);
4579 break;
4580 }
4581 }
4582
4583 return ret;
4584}
4585
4586static int sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta,
4587 unsigned int enda, unsigned int mapsize)
4588{
4589 unsigned int pos;
4590 int i;
4591
4592 writel(val: 0, addr: ivideo->video_vbase);
4593
4594 for(i = starta; i <= enda; i++) {
4595 pos = 1 << i;
4596 if(pos < mapsize)
4597 writel(val: pos, addr: ivideo->video_vbase + pos);
4598 }
4599
4600 sisfb_post_xgi_delay(ivideo, delay: 150);
4601
4602 if(readl(addr: ivideo->video_vbase) != 0)
4603 return 0;
4604
4605 for(i = starta; i <= enda; i++) {
4606 pos = 1 << i;
4607 if(pos < mapsize) {
4608 if(readl(addr: ivideo->video_vbase + pos) != pos)
4609 return 0;
4610 } else
4611 return 0;
4612 }
4613
4614 return 1;
4615}
4616
4617static int sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
4618{
4619 unsigned int buswidth, ranksize, channelab, mapsize;
4620 int i, j, k, l, status;
4621 u8 reg, sr14;
4622 static const u8 dramsr13[12 * 5] = {
4623 0x02, 0x0e, 0x0b, 0x80, 0x5d,
4624 0x02, 0x0e, 0x0a, 0x40, 0x59,
4625 0x02, 0x0d, 0x0b, 0x40, 0x4d,
4626 0x02, 0x0e, 0x09, 0x20, 0x55,
4627 0x02, 0x0d, 0x0a, 0x20, 0x49,
4628 0x02, 0x0c, 0x0b, 0x20, 0x3d,
4629 0x02, 0x0e, 0x08, 0x10, 0x51,
4630 0x02, 0x0d, 0x09, 0x10, 0x45,
4631 0x02, 0x0c, 0x0a, 0x10, 0x39,
4632 0x02, 0x0d, 0x08, 0x08, 0x41,
4633 0x02, 0x0c, 0x09, 0x08, 0x35,
4634 0x02, 0x0c, 0x08, 0x04, 0x31
4635 };
4636 static const u8 dramsr13_4[4 * 5] = {
4637 0x02, 0x0d, 0x09, 0x40, 0x45,
4638 0x02, 0x0c, 0x09, 0x20, 0x35,
4639 0x02, 0x0c, 0x08, 0x10, 0x31,
4640 0x02, 0x0b, 0x08, 0x08, 0x21
4641 };
4642
4643 /* Enable linear mode, disable 0xa0000 address decoding */
4644 /* We disable a0000 address decoding, because
4645 * - if running on x86, if the card is disabled, it means
4646 * that another card is in the system. We don't want
4647 * to interphere with that primary card's textmode.
4648 * - if running on non-x86, there usually is no VGA window
4649 * at a0000.
4650 */
4651 SiS_SetRegOR(SISSR, 0x20, (0x80 | 0x04));
4652
4653 /* Need to map max FB size for finding out about RAM size */
4654 mapsize = ivideo->video_size;
4655 sisfb_post_map_vram(ivideo, mapsize: &mapsize, min: 32);
4656
4657 if(!ivideo->video_vbase) {
4658 printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n");
4659 SiS_SetReg(SISSR, 0x13, 0x35);
4660 SiS_SetReg(SISSR, 0x14, 0x41);
4661 /* TODO */
4662 return -ENOMEM;
4663 }
4664
4665 /* Non-interleaving */
4666 SiS_SetReg(SISSR, 0x15, 0x00);
4667 /* No tiling */
4668 SiS_SetReg(SISSR, 0x1c, 0x00);
4669
4670 if(ivideo->chip == XGI_20) {
4671
4672 channelab = 1;
4673 reg = SiS_GetReg(SISCR, 0x97);
4674 if(!(reg & 0x01)) { /* Single 32/16 */
4675 buswidth = 32;
4676 SiS_SetReg(SISSR, 0x13, 0xb1);
4677 SiS_SetReg(SISSR, 0x14, 0x52);
4678 sisfb_post_xgi_delay(ivideo, delay: 1);
4679 sr14 = 0x02;
4680 if(sisfb_post_xgi_rwtest(ivideo, starta: 23, enda: 24, mapsize))
4681 goto bail_out;
4682
4683 SiS_SetReg(SISSR, 0x13, 0x31);
4684 SiS_SetReg(SISSR, 0x14, 0x42);
4685 sisfb_post_xgi_delay(ivideo, delay: 1);
4686 if(sisfb_post_xgi_rwtest(ivideo, starta: 23, enda: 23, mapsize))
4687 goto bail_out;
4688
4689 buswidth = 16;
4690 SiS_SetReg(SISSR, 0x13, 0xb1);
4691 SiS_SetReg(SISSR, 0x14, 0x41);
4692 sisfb_post_xgi_delay(ivideo, delay: 1);
4693 sr14 = 0x01;
4694 if(sisfb_post_xgi_rwtest(ivideo, starta: 22, enda: 23, mapsize))
4695 goto bail_out;
4696 else
4697 SiS_SetReg(SISSR, 0x13, 0x31);
4698 } else { /* Dual 16/8 */
4699 buswidth = 16;
4700 SiS_SetReg(SISSR, 0x13, 0xb1);
4701 SiS_SetReg(SISSR, 0x14, 0x41);
4702 sisfb_post_xgi_delay(ivideo, delay: 1);
4703 sr14 = 0x01;
4704 if(sisfb_post_xgi_rwtest(ivideo, starta: 22, enda: 23, mapsize))
4705 goto bail_out;
4706
4707 SiS_SetReg(SISSR, 0x13, 0x31);
4708 SiS_SetReg(SISSR, 0x14, 0x31);
4709 sisfb_post_xgi_delay(ivideo, delay: 1);
4710 if(sisfb_post_xgi_rwtest(ivideo, starta: 22, enda: 22, mapsize))
4711 goto bail_out;
4712
4713 buswidth = 8;
4714 SiS_SetReg(SISSR, 0x13, 0xb1);
4715 SiS_SetReg(SISSR, 0x14, 0x30);
4716 sisfb_post_xgi_delay(ivideo, delay: 1);
4717 sr14 = 0x00;
4718 if(sisfb_post_xgi_rwtest(ivideo, starta: 21, enda: 22, mapsize))
4719 goto bail_out;
4720 else
4721 SiS_SetReg(SISSR, 0x13, 0x31);
4722 }
4723
4724 } else { /* XGI_40 */
4725
4726 reg = SiS_GetReg(SISCR, 0x97);
4727 if(!(reg & 0x10)) {
4728 reg = SiS_GetReg(SISSR, 0x39);
4729 reg >>= 1;
4730 }
4731
4732 if(reg & 0x01) { /* DDRII */
4733 buswidth = 32;
4734 if(ivideo->revision_id == 2) {
4735 channelab = 2;
4736 SiS_SetReg(SISSR, 0x13, 0xa1);
4737 SiS_SetReg(SISSR, 0x14, 0x44);
4738 sr14 = 0x04;
4739 sisfb_post_xgi_delay(ivideo, delay: 1);
4740 if(sisfb_post_xgi_rwtest(ivideo, starta: 23, enda: 24, mapsize))
4741 goto bail_out;
4742
4743 SiS_SetReg(SISSR, 0x13, 0x21);
4744 SiS_SetReg(SISSR, 0x14, 0x34);
4745 if(sisfb_post_xgi_rwtest(ivideo, starta: 22, enda: 23, mapsize))
4746 goto bail_out;
4747
4748 channelab = 1;
4749 SiS_SetReg(SISSR, 0x13, 0xa1);
4750 SiS_SetReg(SISSR, 0x14, 0x40);
4751 sr14 = 0x00;
4752 if(sisfb_post_xgi_rwtest(ivideo, starta: 22, enda: 23, mapsize))
4753 goto bail_out;
4754
4755 SiS_SetReg(SISSR, 0x13, 0x21);
4756 SiS_SetReg(SISSR, 0x14, 0x30);
4757 } else {
4758 channelab = 3;
4759 SiS_SetReg(SISSR, 0x13, 0xa1);
4760 SiS_SetReg(SISSR, 0x14, 0x4c);
4761 sr14 = 0x0c;
4762 sisfb_post_xgi_delay(ivideo, delay: 1);
4763 if(sisfb_post_xgi_rwtest(ivideo, starta: 23, enda: 25, mapsize))
4764 goto bail_out;
4765
4766 channelab = 2;
4767 SiS_SetReg(SISSR, 0x14, 0x48);
4768 sisfb_post_xgi_delay(ivideo, delay: 1);
4769 sr14 = 0x08;
4770 if(sisfb_post_xgi_rwtest(ivideo, starta: 23, enda: 24, mapsize))
4771 goto bail_out;
4772
4773 SiS_SetReg(SISSR, 0x13, 0x21);
4774 SiS_SetReg(SISSR, 0x14, 0x3c);
4775 sr14 = 0x0c;
4776
4777 if(sisfb_post_xgi_rwtest(ivideo, starta: 23, enda: 24, mapsize)) {
4778 channelab = 3;
4779 } else {
4780 channelab = 2;
4781 SiS_SetReg(SISSR, 0x14, 0x38);
4782 sr14 = 0x08;
4783 }
4784 }
4785 sisfb_post_xgi_delay(ivideo, delay: 1);
4786
4787 } else { /* DDR */
4788
4789 buswidth = 64;
4790 if(ivideo->revision_id == 2) {
4791 channelab = 1;
4792 SiS_SetReg(SISSR, 0x13, 0xa1);
4793 SiS_SetReg(SISSR, 0x14, 0x52);
4794 sisfb_post_xgi_delay(ivideo, delay: 1);
4795 sr14 = 0x02;
4796 if(sisfb_post_xgi_rwtest(ivideo, starta: 23, enda: 24, mapsize))
4797 goto bail_out;
4798
4799 SiS_SetReg(SISSR, 0x13, 0x21);
4800 SiS_SetReg(SISSR, 0x14, 0x42);
4801 } else {
4802 channelab = 2;
4803 SiS_SetReg(SISSR, 0x13, 0xa1);
4804 SiS_SetReg(SISSR, 0x14, 0x5a);
4805 sisfb_post_xgi_delay(ivideo, delay: 1);
4806 sr14 = 0x0a;
4807 if(sisfb_post_xgi_rwtest(ivideo, starta: 24, enda: 25, mapsize))
4808 goto bail_out;
4809
4810 SiS_SetReg(SISSR, 0x13, 0x21);
4811 SiS_SetReg(SISSR, 0x14, 0x4a);
4812 }
4813 sisfb_post_xgi_delay(ivideo, delay: 1);
4814
4815 }
4816 }
4817
4818bail_out:
4819 SiS_SetRegANDOR(SISSR, 0x14, 0xf0, sr14);
4820 sisfb_post_xgi_delay(ivideo, delay: 1);
4821
4822 j = (ivideo->chip == XGI_20) ? 5 : 9;
4823 k = (ivideo->chip == XGI_20) ? 12 : 4;
4824 status = -EIO;
4825
4826 for(i = 0; i < k; i++) {
4827
4828 reg = (ivideo->chip == XGI_20) ?
4829 dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4];
4830 SiS_SetRegANDOR(SISSR, 0x13, 0x80, reg);
4831 sisfb_post_xgi_delay(ivideo, delay: 50);
4832
4833 ranksize = (ivideo->chip == XGI_20) ?
4834 dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3];
4835
4836 reg = SiS_GetReg(SISSR, 0x13);
4837 if(reg & 0x80) ranksize <<= 1;
4838
4839 if(ivideo->chip == XGI_20) {
4840 if(buswidth == 16) ranksize <<= 1;
4841 else if(buswidth == 32) ranksize <<= 2;
4842 } else {
4843 if(buswidth == 64) ranksize <<= 1;
4844 }
4845
4846 reg = 0;
4847 l = channelab;
4848 if(l == 3) l = 4;
4849 if((ranksize * l) <= 256) {
4850 while((ranksize >>= 1)) reg += 0x10;
4851 }
4852
4853 if(!reg) continue;
4854
4855 SiS_SetRegANDOR(SISSR, 0x14, 0x0f, (reg & 0xf0));
4856 sisfb_post_xgi_delay(ivideo, delay: 1);
4857
4858 if (sisfb_post_xgi_rwtest(ivideo, starta: j, enda: ((reg >> 4) + channelab - 2 + 20), mapsize)) {
4859 status = 0;
4860 break;
4861 }
4862 }
4863
4864 iounmap(addr: ivideo->video_vbase);
4865
4866 return status;
4867}
4868
4869static void sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
4870{
4871 u8 v1, v2, v3;
4872 int index;
4873 static const u8 cs90[8 * 3] = {
4874 0x16, 0x01, 0x01,
4875 0x3e, 0x03, 0x01,
4876 0x7c, 0x08, 0x01,
4877 0x79, 0x06, 0x01,
4878 0x29, 0x01, 0x81,
4879 0x5c, 0x23, 0x01,
4880 0x5c, 0x23, 0x01,
4881 0x5c, 0x23, 0x01
4882 };
4883 static const u8 csb8[8 * 3] = {
4884 0x5c, 0x23, 0x01,
4885 0x29, 0x01, 0x01,
4886 0x7c, 0x08, 0x01,
4887 0x79, 0x06, 0x01,
4888 0x29, 0x01, 0x81,
4889 0x5c, 0x23, 0x01,
4890 0x5c, 0x23, 0x01,
4891 0x5c, 0x23, 0x01
4892 };
4893
4894 regb = 0; /* ! */
4895
4896 index = regb * 3;
4897 v1 = cs90[index]; v2 = cs90[index + 1]; v3 = cs90[index + 2];
4898 if(ivideo->haveXGIROM) {
4899 v1 = ivideo->bios_abase[0x90 + index];
4900 v2 = ivideo->bios_abase[0x90 + index + 1];
4901 v3 = ivideo->bios_abase[0x90 + index + 2];
4902 }
4903 SiS_SetReg(SISSR, 0x28, v1);
4904 SiS_SetReg(SISSR, 0x29, v2);
4905 SiS_SetReg(SISSR, 0x2a, v3);
4906 sisfb_post_xgi_delay(ivideo, delay: 0x43);
4907 sisfb_post_xgi_delay(ivideo, delay: 0x43);
4908 sisfb_post_xgi_delay(ivideo, delay: 0x43);
4909 index = regb * 3;
4910 v1 = csb8[index]; v2 = csb8[index + 1]; v3 = csb8[index + 2];
4911 if(ivideo->haveXGIROM) {
4912 v1 = ivideo->bios_abase[0xb8 + index];
4913 v2 = ivideo->bios_abase[0xb8 + index + 1];
4914 v3 = ivideo->bios_abase[0xb8 + index + 2];
4915 }
4916 SiS_SetReg(SISSR, 0x2e, v1);
4917 SiS_SetReg(SISSR, 0x2f, v2);
4918 SiS_SetReg(SISSR, 0x30, v3);
4919 sisfb_post_xgi_delay(ivideo, delay: 0x43);
4920 sisfb_post_xgi_delay(ivideo, delay: 0x43);
4921 sisfb_post_xgi_delay(ivideo, delay: 0x43);
4922}
4923
4924static void sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info *ivideo,
4925 u8 regb)
4926{
4927 unsigned char *bios = ivideo->bios_abase;
4928 u8 v1;
4929
4930 SiS_SetReg(SISSR, 0x28, 0x64);
4931 SiS_SetReg(SISSR, 0x29, 0x63);
4932 sisfb_post_xgi_delay(ivideo, delay: 15);
4933 SiS_SetReg(SISSR, 0x18, 0x00);
4934 SiS_SetReg(SISSR, 0x19, 0x20);
4935 SiS_SetReg(SISSR, 0x16, 0x00);
4936 SiS_SetReg(SISSR, 0x16, 0x80);
4937 SiS_SetReg(SISSR, 0x18, 0xc5);
4938 SiS_SetReg(SISSR, 0x19, 0x23);
4939 SiS_SetReg(SISSR, 0x16, 0x00);
4940 SiS_SetReg(SISSR, 0x16, 0x80);
4941 sisfb_post_xgi_delay(ivideo, delay: 1);
4942 SiS_SetReg(SISCR, 0x97, 0x11);
4943 sisfb_post_xgi_setclocks(ivideo, regb);
4944 sisfb_post_xgi_delay(ivideo, delay: 0x46);
4945 SiS_SetReg(SISSR, 0x18, 0xc5);
4946 SiS_SetReg(SISSR, 0x19, 0x23);
4947 SiS_SetReg(SISSR, 0x16, 0x00);
4948 SiS_SetReg(SISSR, 0x16, 0x80);
4949 sisfb_post_xgi_delay(ivideo, delay: 1);
4950 SiS_SetReg(SISSR, 0x1b, 0x04);
4951 sisfb_post_xgi_delay(ivideo, delay: 1);
4952 SiS_SetReg(SISSR, 0x1b, 0x00);
4953 sisfb_post_xgi_delay(ivideo, delay: 1);
4954 v1 = 0x31;
4955 if (ivideo->haveXGIROM) {
4956 v1 = bios[0xf0];
4957 }
4958 SiS_SetReg(SISSR, 0x18, v1);
4959 SiS_SetReg(SISSR, 0x19, 0x06);
4960 SiS_SetReg(SISSR, 0x16, 0x04);
4961 SiS_SetReg(SISSR, 0x16, 0x84);
4962 sisfb_post_xgi_delay(ivideo, delay: 1);
4963}
4964
4965static void sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info *ivideo)
4966{
4967 sisfb_post_xgi_setclocks(ivideo, regb: 1);
4968
4969 SiS_SetReg(SISCR, 0x97, 0x11);
4970 sisfb_post_xgi_delay(ivideo, delay: 0x46);
4971
4972 SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS2 */
4973 SiS_SetReg(SISSR, 0x19, 0x80);
4974 SiS_SetReg(SISSR, 0x16, 0x05);
4975 SiS_SetReg(SISSR, 0x16, 0x85);
4976
4977 SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS3 */
4978 SiS_SetReg(SISSR, 0x19, 0xc0);
4979 SiS_SetReg(SISSR, 0x16, 0x05);
4980 SiS_SetReg(SISSR, 0x16, 0x85);
4981
4982 SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS1 */
4983 SiS_SetReg(SISSR, 0x19, 0x40);
4984 SiS_SetReg(SISSR, 0x16, 0x05);
4985 SiS_SetReg(SISSR, 0x16, 0x85);
4986
4987 SiS_SetReg(SISSR, 0x18, 0x42); /* MRS1 */
4988 SiS_SetReg(SISSR, 0x19, 0x02);
4989 SiS_SetReg(SISSR, 0x16, 0x05);
4990 SiS_SetReg(SISSR, 0x16, 0x85);
4991 sisfb_post_xgi_delay(ivideo, delay: 1);
4992
4993 SiS_SetReg(SISSR, 0x1b, 0x04);
4994 sisfb_post_xgi_delay(ivideo, delay: 1);
4995
4996 SiS_SetReg(SISSR, 0x1b, 0x00);
4997 sisfb_post_xgi_delay(ivideo, delay: 1);
4998
4999 SiS_SetReg(SISSR, 0x18, 0x42); /* MRS1 */
5000 SiS_SetReg(SISSR, 0x19, 0x00);
5001 SiS_SetReg(SISSR, 0x16, 0x05);
5002 SiS_SetReg(SISSR, 0x16, 0x85);
5003 sisfb_post_xgi_delay(ivideo, delay: 1);
5004}
5005
5006static void sisfb_post_xgi_ddr2(struct sis_video_info *ivideo, u8 regb)
5007{
5008 unsigned char *bios = ivideo->bios_abase;
5009 static const u8 cs158[8] = {
5010 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5011 };
5012 static const u8 cs160[8] = {
5013 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5014 };
5015 static const u8 cs168[8] = {
5016 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5017 };
5018 u8 v1;
5019 u8 v2;
5020 u8 v3;
5021
5022 SiS_SetReg(SISCR, 0xb0, 0x80); /* DDR2 dual frequency mode */
5023 SiS_SetReg(SISCR, 0x82, 0x77);
5024 SiS_SetReg(SISCR, 0x86, 0x00);
5025 SiS_GetReg(SISCR, 0x86);
5026 SiS_SetReg(SISCR, 0x86, 0x88);
5027 SiS_GetReg(SISCR, 0x86);
5028 v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
5029 if (ivideo->haveXGIROM) {
5030 v1 = bios[regb + 0x168];
5031 v2 = bios[regb + 0x160];
5032 v3 = bios[regb + 0x158];
5033 }
5034 SiS_SetReg(SISCR, 0x86, v1);
5035 SiS_SetReg(SISCR, 0x82, 0x77);
5036 SiS_SetReg(SISCR, 0x85, 0x00);
5037 SiS_GetReg(SISCR, 0x85);
5038 SiS_SetReg(SISCR, 0x85, 0x88);
5039 SiS_GetReg(SISCR, 0x85);
5040 SiS_SetReg(SISCR, 0x85, v2);
5041 SiS_SetReg(SISCR, 0x82, v3);
5042 SiS_SetReg(SISCR, 0x98, 0x01);
5043 SiS_SetReg(SISCR, 0x9a, 0x02);
5044 if (sisfb_xgi_is21(ivideo))
5045 sisfb_post_xgi_ddr2_mrs_xg21(ivideo);
5046 else
5047 sisfb_post_xgi_ddr2_mrs_default(ivideo, regb);
5048}
5049
5050static u8 sisfb_post_xgi_ramtype(struct sis_video_info *ivideo)
5051{
5052 unsigned char *bios = ivideo->bios_abase;
5053 u8 ramtype;
5054 u8 reg;
5055 u8 v1;
5056
5057 ramtype = 0x00; v1 = 0x10;
5058 if (ivideo->haveXGIROM) {
5059 ramtype = bios[0x62];
5060 v1 = bios[0x1d2];
5061 }
5062 if (!(ramtype & 0x80)) {
5063 if (sisfb_xgi_is21(ivideo)) {
5064 SiS_SetRegAND(SISCR, 0xb4, 0xfd); /* GPIO control */
5065 SiS_SetRegOR(SISCR, 0x4a, 0x80); /* GPIOH EN */
5066 reg = SiS_GetReg(SISCR, 0x48);
5067 SiS_SetRegOR(SISCR, 0xb4, 0x02);
5068 ramtype = reg & 0x01; /* GPIOH */
5069 } else if (ivideo->chip == XGI_20) {
5070 SiS_SetReg(SISCR, 0x97, v1);
5071 reg = SiS_GetReg(SISCR, 0x97);
5072 if (reg & 0x10) {
5073 ramtype = (reg & 0x01) << 1;
5074 }
5075 } else {
5076 reg = SiS_GetReg(SISSR, 0x39);
5077 ramtype = reg & 0x02;
5078 if (!(ramtype)) {
5079 reg = SiS_GetReg(SISSR, 0x3a);
5080 ramtype = (reg >> 1) & 0x01;
5081 }
5082 }
5083 }
5084 ramtype &= 0x07;
5085
5086 return ramtype;
5087}
5088
5089static int sisfb_post_xgi(struct pci_dev *pdev)
5090{
5091 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
5092 unsigned char *bios = ivideo->bios_abase;
5093 struct pci_dev *mypdev = NULL;
5094 const u8 *ptr, *ptr2;
5095 u8 v1, v2, v3, v4, v5, reg, ramtype;
5096 u32 rega, regb, regd;
5097 int i, j, k, index;
5098 static const u8 cs78[3] = { 0xf6, 0x0d, 0x00 };
5099 static const u8 cs76[2] = { 0xa3, 0xfb };
5100 static const u8 cs7b[3] = { 0xc0, 0x11, 0x00 };
5101 static const u8 cs158[8] = {
5102 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
5103 };
5104 static const u8 cs160[8] = {
5105 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
5106 };
5107 static const u8 cs168[8] = {
5108 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
5109 };
5110 static const u8 cs128[3 * 8] = {
5111 0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
5112 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5113 0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
5114 };
5115 static const u8 cs148[2 * 8] = {
5116 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
5117 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5118 };
5119 static const u8 cs31a[8 * 4] = {
5120 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
5121 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
5122 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5123 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5124 };
5125 static const u8 cs33a[8 * 4] = {
5126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5127 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5128 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5130 };
5131 static const u8 cs45a[8 * 2] = {
5132 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
5133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5134 };
5135 static const u8 cs170[7 * 8] = {
5136 0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5137 0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5138 0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
5139 0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
5140 0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
5141 0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
5142 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
5143 };
5144 static const u8 cs1a8[3 * 8] = {
5145 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
5146 0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
5147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5148 };
5149 static const u8 cs100[2 * 8] = {
5150 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
5151 0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
5152 };
5153
5154 /* VGA enable */
5155 reg = SiS_GetRegByte(SISVGAENABLE) | 0x01;
5156 SiS_SetRegByte(SISVGAENABLE, reg);
5157
5158 /* Misc */
5159 reg = SiS_GetRegByte(SISMISCR) | 0x01;
5160 SiS_SetRegByte(SISMISCW, reg);
5161
5162 /* Unlock SR */
5163 SiS_SetReg(SISSR, 0x05, 0x86);
5164 reg = SiS_GetReg(SISSR, 0x05);
5165 if(reg != 0xa1)
5166 return 0;
5167
5168 /* Clear some regs */
5169 for(i = 0; i < 0x22; i++) {
5170 if(0x06 + i == 0x20) continue;
5171 SiS_SetReg(SISSR, 0x06 + i, 0x00);
5172 }
5173 for(i = 0; i < 0x0b; i++) {
5174 SiS_SetReg(SISSR, 0x31 + i, 0x00);
5175 }
5176 for(i = 0; i < 0x10; i++) {
5177 SiS_SetReg(SISCR, 0x30 + i, 0x00);
5178 }
5179
5180 ptr = cs78;
5181 if(ivideo->haveXGIROM) {
5182 ptr = (const u8 *)&bios[0x78];
5183 }
5184 for(i = 0; i < 3; i++) {
5185 SiS_SetReg(SISSR, 0x23 + i, ptr[i]);
5186 }
5187
5188 ptr = cs76;
5189 if(ivideo->haveXGIROM) {
5190 ptr = (const u8 *)&bios[0x76];
5191 }
5192 for(i = 0; i < 2; i++) {
5193 SiS_SetReg(SISSR, 0x21 + i, ptr[i]);
5194 }
5195
5196 v1 = 0x18; v2 = 0x00;
5197 if(ivideo->haveXGIROM) {
5198 v1 = bios[0x74];
5199 v2 = bios[0x75];
5200 }
5201 SiS_SetReg(SISSR, 0x07, v1);
5202 SiS_SetReg(SISSR, 0x11, 0x0f);
5203 SiS_SetReg(SISSR, 0x1f, v2);
5204 /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
5205 SiS_SetReg(SISSR, 0x20, 0x80 | 0x20 | 0x04);
5206 SiS_SetReg(SISSR, 0x27, 0x74);
5207
5208 ptr = cs7b;
5209 if(ivideo->haveXGIROM) {
5210 ptr = (const u8 *)&bios[0x7b];
5211 }
5212 for(i = 0; i < 3; i++) {
5213 SiS_SetReg(SISSR, 0x31 + i, ptr[i]);
5214 }
5215
5216 if(ivideo->chip == XGI_40) {
5217 if(ivideo->revision_id == 2) {
5218 SiS_SetRegANDOR(SISSR, 0x3b, 0x3f, 0xc0);
5219 }
5220 SiS_SetReg(SISCR, 0x7d, 0xfe);
5221 SiS_SetReg(SISCR, 0x7e, 0x0f);
5222 }
5223 if(ivideo->revision_id == 0) { /* 40 *and* 20? */
5224 SiS_SetRegAND(SISCR, 0x58, 0xd7);
5225 reg = SiS_GetReg(SISCR, 0xcb);
5226 if(reg & 0x20) {
5227 SiS_SetRegANDOR(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
5228 }
5229 }
5230
5231 reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00;
5232 SiS_SetRegANDOR(SISCR, 0x38, 0x1f, reg);
5233
5234 if(ivideo->chip == XGI_20) {
5235 SiS_SetReg(SISSR, 0x36, 0x70);
5236 } else {
5237 SiS_SetReg(SISVID, 0x00, 0x86);
5238 SiS_SetReg(SISVID, 0x32, 0x00);
5239 SiS_SetReg(SISVID, 0x30, 0x00);
5240 SiS_SetReg(SISVID, 0x32, 0x01);
5241 SiS_SetReg(SISVID, 0x30, 0x00);
5242 SiS_SetRegAND(SISVID, 0x2f, 0xdf);
5243 SiS_SetRegAND(SISCAP, 0x00, 0x3f);
5244
5245 SiS_SetReg(SISPART1, 0x2f, 0x01);
5246 SiS_SetReg(SISPART1, 0x00, 0x00);
5247 SiS_SetReg(SISPART1, 0x02, bios[0x7e]);
5248 SiS_SetReg(SISPART1, 0x2e, 0x08);
5249 SiS_SetRegAND(SISPART1, 0x35, 0x7f);
5250 SiS_SetRegAND(SISPART1, 0x50, 0xfe);
5251
5252 reg = SiS_GetReg(SISPART4, 0x00);
5253 if(reg == 1 || reg == 2) {
5254 SiS_SetReg(SISPART2, 0x00, 0x1c);
5255 SiS_SetReg(SISPART4, 0x0d, bios[0x7f]);
5256 SiS_SetReg(SISPART4, 0x0e, bios[0x80]);
5257 SiS_SetReg(SISPART4, 0x10, bios[0x81]);
5258 SiS_SetRegAND(SISPART4, 0x0f, 0x3f);
5259
5260 reg = SiS_GetReg(SISPART4, 0x01);
5261 if((reg & 0xf0) >= 0xb0) {
5262 reg = SiS_GetReg(SISPART4, 0x23);
5263 if(reg & 0x20) reg |= 0x40;
5264 SiS_SetReg(SISPART4, 0x23, reg);
5265 reg = (reg & 0x20) ? 0x02 : 0x00;
5266 SiS_SetRegANDOR(SISPART1, 0x1e, 0xfd, reg);
5267 }
5268 }
5269
5270 v1 = bios[0x77];
5271
5272 reg = SiS_GetReg(SISSR, 0x3b);
5273 if(reg & 0x02) {
5274 reg = SiS_GetReg(SISSR, 0x3a);
5275 v2 = (reg & 0x30) >> 3;
5276 if(!(v2 & 0x04)) v2 ^= 0x02;
5277 reg = SiS_GetReg(SISSR, 0x39);
5278 if(reg & 0x80) v2 |= 0x80;
5279 v2 |= 0x01;
5280
5281 if((mypdev = pci_get_device(PCI_VENDOR_ID_SI, device: 0x0730, NULL))) {
5282 pci_dev_put(dev: mypdev);
5283 if(((v2 & 0x06) == 2) || ((v2 & 0x06) == 4))
5284 v2 &= 0xf9;
5285 v2 |= 0x08;
5286 v1 &= 0xfe;
5287 } else {
5288 mypdev = pci_get_device(PCI_VENDOR_ID_SI, device: 0x0735, NULL);
5289 if(!mypdev)
5290 mypdev = pci_get_device(PCI_VENDOR_ID_SI, device: 0x0645, NULL);
5291 if(!mypdev)
5292 mypdev = pci_get_device(PCI_VENDOR_ID_SI, device: 0x0650, NULL);
5293 if(mypdev) {
5294 pci_read_config_dword(dev: mypdev, where: 0x94, val: &regd);
5295 regd &= 0xfffffeff;
5296 pci_write_config_dword(dev: mypdev, where: 0x94, val: regd);
5297 v1 &= 0xfe;
5298 pci_dev_put(dev: mypdev);
5299 } else if(sisfb_find_host_bridge(ivideo, mypdev: pdev, PCI_VENDOR_ID_SI)) {
5300 v1 &= 0xfe;
5301 } else if(sisfb_find_host_bridge(ivideo, mypdev: pdev, pcivendor: 0x1106) ||
5302 sisfb_find_host_bridge(ivideo, mypdev: pdev, pcivendor: 0x1022) ||
5303 sisfb_find_host_bridge(ivideo, mypdev: pdev, pcivendor: 0x700e) ||
5304 sisfb_find_host_bridge(ivideo, mypdev: pdev, pcivendor: 0x10de)) {
5305 if((v2 & 0x06) == 4)
5306 v2 ^= 0x06;
5307 v2 |= 0x08;
5308 }
5309 }
5310 SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, v2);
5311 }
5312 SiS_SetReg(SISSR, 0x22, v1);
5313
5314 if(ivideo->revision_id == 2) {
5315 v1 = SiS_GetReg(SISSR, 0x3b);
5316 v2 = SiS_GetReg(SISSR, 0x3a);
5317 regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8);
5318 if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) )
5319 SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
5320
5321 if((mypdev = pci_get_device(vendor: 0x10de, device: 0x01e0, NULL))) {
5322 /* TODO: set CR5f &0xf1 | 0x01 for version 6570
5323 * of nforce 2 ROM
5324 */
5325 if(0)
5326 SiS_SetRegANDOR(SISCR, 0x5f, 0xf1, 0x01);
5327 pci_dev_put(dev: mypdev);
5328 }
5329 }
5330
5331 v1 = 0x30;
5332 reg = SiS_GetReg(SISSR, 0x3b);
5333 v2 = SiS_GetReg(SISCR, 0x5f);
5334 if((!(reg & 0x02)) && (v2 & 0x0e))
5335 v1 |= 0x08;
5336 SiS_SetReg(SISSR, 0x27, v1);
5337
5338 if(bios[0x64] & 0x01) {
5339 SiS_SetRegANDOR(SISCR, 0x5f, 0xf0, bios[0x64]);
5340 }
5341
5342 v1 = bios[0x4f7];
5343 pci_read_config_dword(dev: pdev, where: 0x50, val: &regd);
5344 regd = (regd >> 20) & 0x0f;
5345 if(regd == 1) {
5346 v1 &= 0xfc;
5347 SiS_SetRegOR(SISCR, 0x5f, 0x08);
5348 }
5349 SiS_SetReg(SISCR, 0x48, v1);
5350
5351 SiS_SetRegANDOR(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb);
5352 SiS_SetRegANDOR(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f);
5353 SiS_SetRegANDOR(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f);
5354 SiS_SetRegANDOR(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7);
5355 SiS_SetRegANDOR(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f);
5356 SiS_SetReg(SISCR, 0x70, bios[0x4fc]);
5357 SiS_SetRegANDOR(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f);
5358 SiS_SetReg(SISCR, 0x74, 0xd0);
5359 SiS_SetRegANDOR(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30);
5360 SiS_SetRegANDOR(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
5361 SiS_SetRegANDOR(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
5362 v1 = bios[0x501];
5363 if((mypdev = pci_get_device(vendor: 0x8086, device: 0x2530, NULL))) {
5364 v1 = 0xf0;
5365 pci_dev_put(dev: mypdev);
5366 }
5367 SiS_SetReg(SISCR, 0x77, v1);
5368 }
5369
5370 /* RAM type:
5371 *
5372 * 0 == DDR1, 1 == DDR2, 2..7 == reserved?
5373 *
5374 * The code seems to written so that regb should equal ramtype,
5375 * however, so far it has been hardcoded to 0. Enable other values only
5376 * on XGI Z9, as it passes the POST, and add a warning for others.
5377 */
5378 ramtype = sisfb_post_xgi_ramtype(ivideo);
5379 if (!sisfb_xgi_is21(ivideo) && ramtype) {
5380 dev_warn(&pdev->dev,
5381 "RAM type something else than expected: %d\n",
5382 ramtype);
5383 regb = 0;
5384 } else {
5385 regb = ramtype;
5386 }
5387
5388 v1 = 0xff;
5389 if(ivideo->haveXGIROM) {
5390 v1 = bios[0x140 + regb];
5391 }
5392 SiS_SetReg(SISCR, 0x6d, v1);
5393
5394 ptr = cs128;
5395 if(ivideo->haveXGIROM) {
5396 ptr = (const u8 *)&bios[0x128];
5397 }
5398 for(i = 0, j = 0; i < 3; i++, j += 8) {
5399 SiS_SetReg(SISCR, 0x68 + i, ptr[j + regb]);
5400 }
5401
5402 ptr = cs31a;
5403 ptr2 = cs33a;
5404 if(ivideo->haveXGIROM) {
5405 index = (ivideo->chip == XGI_20) ? 0x31a : 0x3a6;
5406 ptr = (const u8 *)&bios[index];
5407 ptr2 = (const u8 *)&bios[index + 0x20];
5408 }
5409 for(i = 0; i < 2; i++) {
5410 if(i == 0) {
5411 regd = le32_to_cpu(((u32 *)ptr)[regb]);
5412 rega = 0x6b;
5413 } else {
5414 regd = le32_to_cpu(((u32 *)ptr2)[regb]);
5415 rega = 0x6e;
5416 }
5417 reg = 0x00;
5418 for(j = 0; j < 16; j++) {
5419 reg &= 0xf3;
5420 if(regd & 0x01) reg |= 0x04;
5421 if(regd & 0x02) reg |= 0x08;
5422 regd >>= 2;
5423 SiS_SetReg(SISCR, rega, reg);
5424 reg = SiS_GetReg(SISCR, rega);
5425 reg = SiS_GetReg(SISCR, rega);
5426 reg += 0x10;
5427 }
5428 }
5429
5430 SiS_SetRegAND(SISCR, 0x6e, 0xfc);
5431
5432 ptr = NULL;
5433 if(ivideo->haveXGIROM) {
5434 index = (ivideo->chip == XGI_20) ? 0x35a : 0x3e6;
5435 ptr = (const u8 *)&bios[index];
5436 }
5437 for(i = 0; i < 4; i++) {
5438 SiS_SetRegANDOR(SISCR, 0x6e, 0xfc, i);
5439 reg = 0x00;
5440 for(j = 0; j < 2; j++) {
5441 regd = 0;
5442 if(ptr) {
5443 regd = le32_to_cpu(((u32 *)ptr)[regb * 8]);
5444 ptr += 4;
5445 }
5446 /* reg = 0x00; */
5447 for(k = 0; k < 16; k++) {
5448 reg &= 0xfc;
5449 if(regd & 0x01) reg |= 0x01;
5450 if(regd & 0x02) reg |= 0x02;
5451 regd >>= 2;
5452 SiS_SetReg(SISCR, 0x6f, reg);
5453 reg = SiS_GetReg(SISCR, 0x6f);
5454 reg = SiS_GetReg(SISCR, 0x6f);
5455 reg += 0x08;
5456 }
5457 }
5458 }
5459
5460 ptr = cs148;
5461 if(ivideo->haveXGIROM) {
5462 ptr = (const u8 *)&bios[0x148];
5463 }
5464 for(i = 0, j = 0; i < 2; i++, j += 8) {
5465 SiS_SetReg(SISCR, 0x80 + i, ptr[j + regb]);
5466 }
5467
5468 SiS_SetRegAND(SISCR, 0x89, 0x8f);
5469
5470 ptr = cs45a;
5471 if(ivideo->haveXGIROM) {
5472 index = (ivideo->chip == XGI_20) ? 0x45a : 0x4e6;
5473 ptr = (const u8 *)&bios[index];
5474 }
5475 regd = le16_to_cpu(((const u16 *)ptr)[regb]);
5476 reg = 0x80;
5477 for(i = 0; i < 5; i++) {
5478 reg &= 0xfc;
5479 if(regd & 0x01) reg |= 0x01;
5480 if(regd & 0x02) reg |= 0x02;
5481 regd >>= 2;
5482 SiS_SetReg(SISCR, 0x89, reg);
5483 reg = SiS_GetReg(SISCR, 0x89);
5484 reg = SiS_GetReg(SISCR, 0x89);
5485 reg += 0x10;
5486 }
5487
5488 v1 = 0xb5; v2 = 0x20; v3 = 0xf0; v4 = 0x13;
5489 if(ivideo->haveXGIROM) {
5490 v1 = bios[0x118 + regb];
5491 v2 = bios[0xf8 + regb];
5492 v3 = bios[0x120 + regb];
5493 v4 = bios[0x1ca];
5494 }
5495 SiS_SetReg(SISCR, 0x45, v1 & 0x0f);
5496 SiS_SetReg(SISCR, 0x99, (v1 >> 4) & 0x07);
5497 SiS_SetRegOR(SISCR, 0x40, v1 & 0x80);
5498 SiS_SetReg(SISCR, 0x41, v2);
5499
5500 ptr = cs170;
5501 if(ivideo->haveXGIROM) {
5502 ptr = (const u8 *)&bios[0x170];
5503 }
5504 for(i = 0, j = 0; i < 7; i++, j += 8) {
5505 SiS_SetReg(SISCR, 0x90 + i, ptr[j + regb]);
5506 }
5507
5508 SiS_SetReg(SISCR, 0x59, v3);
5509
5510 ptr = cs1a8;
5511 if(ivideo->haveXGIROM) {
5512 ptr = (const u8 *)&bios[0x1a8];
5513 }
5514 for(i = 0, j = 0; i < 3; i++, j += 8) {
5515 SiS_SetReg(SISCR, 0xc3 + i, ptr[j + regb]);
5516 }
5517
5518 ptr = cs100;
5519 if(ivideo->haveXGIROM) {
5520 ptr = (const u8 *)&bios[0x100];
5521 }
5522 for(i = 0, j = 0; i < 2; i++, j += 8) {
5523 SiS_SetReg(SISCR, 0x8a + i, ptr[j + regb]);
5524 }
5525
5526 SiS_SetReg(SISCR, 0xcf, v4);
5527
5528 SiS_SetReg(SISCR, 0x83, 0x09);
5529 SiS_SetReg(SISCR, 0x87, 0x00);
5530
5531 if(ivideo->chip == XGI_40) {
5532 if( (ivideo->revision_id == 1) ||
5533 (ivideo->revision_id == 2) ) {
5534 SiS_SetReg(SISCR, 0x8c, 0x87);
5535 }
5536 }
5537
5538 if (regb == 1)
5539 SiS_SetReg(SISSR, 0x17, 0x80); /* DDR2 */
5540 else
5541 SiS_SetReg(SISSR, 0x17, 0x00); /* DDR1 */
5542 SiS_SetReg(SISSR, 0x1a, 0x87);
5543
5544 if(ivideo->chip == XGI_20) {
5545 SiS_SetReg(SISSR, 0x15, 0x00);
5546 SiS_SetReg(SISSR, 0x1c, 0x00);
5547 }
5548
5549 switch(ramtype) {
5550 case 0:
5551 sisfb_post_xgi_setclocks(ivideo, regb);
5552 if((ivideo->chip == XGI_20) ||
5553 (ivideo->revision_id == 1) ||
5554 (ivideo->revision_id == 2)) {
5555 v1 = cs158[regb]; v2 = cs160[regb]; v3 = cs168[regb];
5556 if(ivideo->haveXGIROM) {
5557 v1 = bios[regb + 0x158];
5558 v2 = bios[regb + 0x160];
5559 v3 = bios[regb + 0x168];
5560 }
5561 SiS_SetReg(SISCR, 0x82, v1);
5562 SiS_SetReg(SISCR, 0x85, v2);
5563 SiS_SetReg(SISCR, 0x86, v3);
5564 } else {
5565 SiS_SetReg(SISCR, 0x82, 0x88);
5566 SiS_SetReg(SISCR, 0x86, 0x00);
5567 reg = SiS_GetReg(SISCR, 0x86);
5568 SiS_SetReg(SISCR, 0x86, 0x88);
5569 reg = SiS_GetReg(SISCR, 0x86);
5570 SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
5571 SiS_SetReg(SISCR, 0x82, 0x77);
5572 SiS_SetReg(SISCR, 0x85, 0x00);
5573 reg = SiS_GetReg(SISCR, 0x85);
5574 SiS_SetReg(SISCR, 0x85, 0x88);
5575 reg = SiS_GetReg(SISCR, 0x85);
5576 SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
5577 SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
5578 }
5579 if(ivideo->chip == XGI_40) {
5580 SiS_SetReg(SISCR, 0x97, 0x00);
5581 }
5582 SiS_SetReg(SISCR, 0x98, 0x01);
5583 SiS_SetReg(SISCR, 0x9a, 0x02);
5584
5585 SiS_SetReg(SISSR, 0x18, 0x01);
5586 if((ivideo->chip == XGI_20) ||
5587 (ivideo->revision_id == 2)) {
5588 SiS_SetReg(SISSR, 0x19, 0x40);
5589 } else {
5590 SiS_SetReg(SISSR, 0x19, 0x20);
5591 }
5592 SiS_SetReg(SISSR, 0x16, 0x00);
5593 SiS_SetReg(SISSR, 0x16, 0x80);
5594 if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) {
5595 sisfb_post_xgi_delay(ivideo, delay: 0x43);
5596 sisfb_post_xgi_delay(ivideo, delay: 0x43);
5597 sisfb_post_xgi_delay(ivideo, delay: 0x43);
5598 SiS_SetReg(SISSR, 0x18, 0x00);
5599 if((ivideo->chip == XGI_20) ||
5600 (ivideo->revision_id == 2)) {
5601 SiS_SetReg(SISSR, 0x19, 0x40);
5602 } else {
5603 SiS_SetReg(SISSR, 0x19, 0x20);
5604 }
5605 } else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) {
5606 /* SiS_SetReg(SISSR, 0x16, 0x0c); */ /* ? */
5607 }
5608 SiS_SetReg(SISSR, 0x16, 0x00);
5609 SiS_SetReg(SISSR, 0x16, 0x80);
5610 sisfb_post_xgi_delay(ivideo, delay: 4);
5611 v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83;
5612 if(ivideo->haveXGIROM) {
5613 v1 = bios[0xf0];
5614 index = (ivideo->chip == XGI_20) ? 0x4b2 : 0x53e;
5615 v2 = bios[index];
5616 v3 = bios[index + 1];
5617 v4 = bios[index + 2];
5618 v5 = bios[index + 3];
5619 }
5620 SiS_SetReg(SISSR, 0x18, v1);
5621 SiS_SetReg(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01));
5622 SiS_SetReg(SISSR, 0x16, v2);
5623 SiS_SetReg(SISSR, 0x16, v3);
5624 sisfb_post_xgi_delay(ivideo, delay: 0x43);
5625 SiS_SetReg(SISSR, 0x1b, 0x03);
5626 sisfb_post_xgi_delay(ivideo, delay: 0x22);
5627 SiS_SetReg(SISSR, 0x18, v1);
5628 SiS_SetReg(SISSR, 0x19, 0x00);
5629 SiS_SetReg(SISSR, 0x16, v4);
5630 SiS_SetReg(SISSR, 0x16, v5);
5631 SiS_SetReg(SISSR, 0x1b, 0x00);
5632 break;
5633 case 1:
5634 sisfb_post_xgi_ddr2(ivideo, regb);
5635 break;
5636 default:
5637 sisfb_post_xgi_setclocks(ivideo, regb);
5638 if((ivideo->chip == XGI_40) &&
5639 ((ivideo->revision_id == 1) ||
5640 (ivideo->revision_id == 2))) {
5641 SiS_SetReg(SISCR, 0x82, bios[regb + 0x158]);
5642 SiS_SetReg(SISCR, 0x85, bios[regb + 0x160]);
5643 SiS_SetReg(SISCR, 0x86, bios[regb + 0x168]);
5644 } else {
5645 SiS_SetReg(SISCR, 0x82, 0x88);
5646 SiS_SetReg(SISCR, 0x86, 0x00);
5647 reg = SiS_GetReg(SISCR, 0x86);
5648 SiS_SetReg(SISCR, 0x86, 0x88);
5649 SiS_SetReg(SISCR, 0x82, 0x77);
5650 SiS_SetReg(SISCR, 0x85, 0x00);
5651 reg = SiS_GetReg(SISCR, 0x85);
5652 SiS_SetReg(SISCR, 0x85, 0x88);
5653 reg = SiS_GetReg(SISCR, 0x85);
5654 v1 = cs160[regb]; v2 = cs158[regb];
5655 if(ivideo->haveXGIROM) {
5656 v1 = bios[regb + 0x160];
5657 v2 = bios[regb + 0x158];
5658 }
5659 SiS_SetReg(SISCR, 0x85, v1);
5660 SiS_SetReg(SISCR, 0x82, v2);
5661 }
5662 if(ivideo->chip == XGI_40) {
5663 SiS_SetReg(SISCR, 0x97, 0x11);
5664 }
5665 if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) {
5666 SiS_SetReg(SISCR, 0x98, 0x01);
5667 } else {
5668 SiS_SetReg(SISCR, 0x98, 0x03);
5669 }
5670 SiS_SetReg(SISCR, 0x9a, 0x02);
5671
5672 if(ivideo->chip == XGI_40) {
5673 SiS_SetReg(SISSR, 0x18, 0x01);
5674 } else {
5675 SiS_SetReg(SISSR, 0x18, 0x00);
5676 }
5677 SiS_SetReg(SISSR, 0x19, 0x40);
5678 SiS_SetReg(SISSR, 0x16, 0x00);
5679 SiS_SetReg(SISSR, 0x16, 0x80);
5680 if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) {
5681 sisfb_post_xgi_delay(ivideo, delay: 0x43);
5682 sisfb_post_xgi_delay(ivideo, delay: 0x43);
5683 sisfb_post_xgi_delay(ivideo, delay: 0x43);
5684 SiS_SetReg(SISSR, 0x18, 0x00);
5685 SiS_SetReg(SISSR, 0x19, 0x40);
5686 SiS_SetReg(SISSR, 0x16, 0x00);
5687 SiS_SetReg(SISSR, 0x16, 0x80);
5688 }
5689 sisfb_post_xgi_delay(ivideo, delay: 4);
5690 v1 = 0x31;
5691 if(ivideo->haveXGIROM) {
5692 v1 = bios[0xf0];
5693 }
5694 SiS_SetReg(SISSR, 0x18, v1);
5695 SiS_SetReg(SISSR, 0x19, 0x01);
5696 if(ivideo->chip == XGI_40) {
5697 SiS_SetReg(SISSR, 0x16, bios[0x53e]);
5698 SiS_SetReg(SISSR, 0x16, bios[0x53f]);
5699 } else {
5700 SiS_SetReg(SISSR, 0x16, 0x05);
5701 SiS_SetReg(SISSR, 0x16, 0x85);
5702 }
5703 sisfb_post_xgi_delay(ivideo, delay: 0x43);
5704 if(ivideo->chip == XGI_40) {
5705 SiS_SetReg(SISSR, 0x1b, 0x01);
5706 } else {
5707 SiS_SetReg(SISSR, 0x1b, 0x03);
5708 }
5709 sisfb_post_xgi_delay(ivideo, delay: 0x22);
5710 SiS_SetReg(SISSR, 0x18, v1);
5711 SiS_SetReg(SISSR, 0x19, 0x00);
5712 if(ivideo->chip == XGI_40) {
5713 SiS_SetReg(SISSR, 0x16, bios[0x540]);
5714 SiS_SetReg(SISSR, 0x16, bios[0x541]);
5715 } else {
5716 SiS_SetReg(SISSR, 0x16, 0x05);
5717 SiS_SetReg(SISSR, 0x16, 0x85);
5718 }
5719 SiS_SetReg(SISSR, 0x1b, 0x00);
5720 }
5721
5722 regb = 0; /* ! */
5723 v1 = 0x03;
5724 if(ivideo->haveXGIROM) {
5725 v1 = bios[0x110 + regb];
5726 }
5727 SiS_SetReg(SISSR, 0x1b, v1);
5728
5729 /* RAM size */
5730 v1 = 0x00; v2 = 0x00;
5731 if(ivideo->haveXGIROM) {
5732 v1 = bios[0x62];
5733 v2 = bios[0x63];
5734 }
5735 regb = 0; /* ! */
5736 regd = 1 << regb;
5737 if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) {
5738
5739 SiS_SetReg(SISSR, 0x13, bios[regb + 0xe0]);
5740 SiS_SetReg(SISSR, 0x14, bios[regb + 0xe0 + 8]);
5741
5742 } else {
5743 int err;
5744
5745 /* Set default mode, don't clear screen */
5746 ivideo->SiS_Pr.SiS_UseOEM = false;
5747 SiS_SetEnableDstn(SiS_Pr: &ivideo->SiS_Pr, enable: false);
5748 SiS_SetEnableFstn(SiS_Pr: &ivideo->SiS_Pr, enable: false);
5749 ivideo->curFSTN = ivideo->curDSTN = 0;
5750 ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
5751 SiSSetMode(SiS_Pr: &ivideo->SiS_Pr, ModeNo: 0x2e | 0x80);
5752
5753 SiS_SetReg(SISSR, 0x05, 0x86);
5754
5755 /* Disable read-cache */
5756 SiS_SetRegAND(SISSR, 0x21, 0xdf);
5757 err = sisfb_post_xgi_ramsize(ivideo);
5758 /* Enable read-cache */
5759 SiS_SetRegOR(SISSR, 0x21, 0x20);
5760
5761 if (err) {
5762 dev_err(&pdev->dev,
5763 "%s: RAM size detection failed: %d\n",
5764 __func__, err);
5765 return 0;
5766 }
5767 }
5768
5769#if 0
5770 printk(KERN_DEBUG "-----------------\n");
5771 for(i = 0; i < 0xff; i++) {
5772 reg = SiS_GetReg(SISCR, i);
5773 printk(KERN_DEBUG "CR%02x(%x) = 0x%02x\n", i, SISCR, reg);
5774 }
5775 for(i = 0; i < 0x40; i++) {
5776 reg = SiS_GetReg(SISSR, i);
5777 printk(KERN_DEBUG "SR%02x(%x) = 0x%02x\n", i, SISSR, reg);
5778 }
5779 printk(KERN_DEBUG "-----------------\n");
5780#endif
5781
5782 /* Sense CRT1 */
5783 if(ivideo->chip == XGI_20) {
5784 SiS_SetRegOR(SISCR, 0x32, 0x20);
5785 } else {
5786 reg = SiS_GetReg(SISPART4, 0x00);
5787 if((reg == 1) || (reg == 2)) {
5788 sisfb_sense_crt1(ivideo);
5789 } else {
5790 SiS_SetRegOR(SISCR, 0x32, 0x20);
5791 }
5792 }
5793
5794 /* Set default mode, don't clear screen */
5795 ivideo->SiS_Pr.SiS_UseOEM = false;
5796 SiS_SetEnableDstn(SiS_Pr: &ivideo->SiS_Pr, enable: false);
5797 SiS_SetEnableFstn(SiS_Pr: &ivideo->SiS_Pr, enable: false);
5798 ivideo->curFSTN = ivideo->curDSTN = 0;
5799 SiSSetMode(SiS_Pr: &ivideo->SiS_Pr, ModeNo: 0x2e | 0x80);
5800
5801 SiS_SetReg(SISSR, 0x05, 0x86);
5802
5803 /* Display off */
5804 SiS_SetRegOR(SISSR, 0x01, 0x20);
5805
5806 /* Save mode number in CR34 */
5807 SiS_SetReg(SISCR, 0x34, 0x2e);
5808
5809 /* Let everyone know what the current mode is */
5810 ivideo->modeprechange = 0x2e;
5811
5812 if(ivideo->chip == XGI_40) {
5813 reg = SiS_GetReg(SISCR, 0xca);
5814 v1 = SiS_GetReg(SISCR, 0xcc);
5815 if((reg & 0x10) && (!(v1 & 0x04))) {
5816 printk(KERN_ERR
5817 "sisfb: Please connect power to the card.\n");
5818 return 0;
5819 }
5820 }
5821
5822 return 1;
5823}
5824#endif
5825
5826static int sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
5827{
5828 struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data];
5829 struct sis_video_info *ivideo = NULL;
5830 struct fb_info *sis_fb_info = NULL;
5831 u16 reg16;
5832 u8 reg;
5833 int i, ret;
5834
5835 if(sisfb_off)
5836 return -ENXIO;
5837
5838 ret = aperture_remove_conflicting_pci_devices(pdev, name: "sisfb");
5839 if (ret)
5840 return ret;
5841
5842 sis_fb_info = framebuffer_alloc(size: sizeof(*ivideo), dev: &pdev->dev);
5843 if(!sis_fb_info)
5844 return -ENOMEM;
5845
5846 ivideo = (struct sis_video_info *)sis_fb_info->par;
5847 ivideo->memyselfandi = sis_fb_info;
5848
5849 ivideo->sisfb_id = SISFB_ID;
5850
5851 if(card_list == NULL) {
5852 ivideo->cardnumber = 0;
5853 } else {
5854 struct sis_video_info *countvideo = card_list;
5855 ivideo->cardnumber = 1;
5856 while((countvideo = countvideo->next) != NULL)
5857 ivideo->cardnumber++;
5858 }
5859
5860 strscpy(ivideo->myid, chipinfo->chip_name, sizeof(ivideo->myid));
5861
5862 ivideo->warncount = 0;
5863 ivideo->chip_id = pdev->device;
5864 ivideo->chip_vendor = pdev->vendor;
5865 ivideo->revision_id = pdev->revision;
5866 ivideo->SiS_Pr.ChipRevision = ivideo->revision_id;
5867 pci_read_config_word(dev: pdev, PCI_COMMAND, val: &reg16);
5868 ivideo->sisvga_enabled = reg16 & 0x01;
5869 ivideo->pcibus = pdev->bus->number;
5870 ivideo->pcislot = PCI_SLOT(pdev->devfn);
5871 ivideo->pcifunc = PCI_FUNC(pdev->devfn);
5872 ivideo->subsysvendor = pdev->subsystem_vendor;
5873 ivideo->subsysdevice = pdev->subsystem_device;
5874
5875 ivideo->chip = chipinfo->chip;
5876 ivideo->chip_real_id = chipinfo->chip;
5877 ivideo->sisvga_engine = chipinfo->vgaengine;
5878 ivideo->hwcursor_size = chipinfo->hwcursor_size;
5879 ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable;
5880 ivideo->mni = chipinfo->mni;
5881
5882 ivideo->detectedpdc = 0xff;
5883 ivideo->detectedpdca = 0xff;
5884 ivideo->detectedlcda = 0xff;
5885
5886 ivideo->sisfb_thismonitor.datavalid = false;
5887
5888 ivideo->current_base = 0;
5889
5890 ivideo->engineok = 0;
5891
5892 ivideo->sisfb_was_boot_device = 0;
5893
5894 if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
5895 if(ivideo->sisvga_enabled)
5896 ivideo->sisfb_was_boot_device = 1;
5897 else {
5898 printk(KERN_DEBUG "sisfb: PCI device is disabled, "
5899 "but marked as boot video device ???\n");
5900 printk(KERN_DEBUG "sisfb: I will not accept this "
5901 "as the primary VGA device\n");
5902 }
5903 }
5904
5905 ivideo->sisfb_parm_mem = sisfb_parm_mem;
5906 ivideo->sisfb_accel = sisfb_accel;
5907 ivideo->sisfb_ypan = sisfb_ypan;
5908 ivideo->sisfb_max = sisfb_max;
5909 ivideo->sisfb_userom = sisfb_userom;
5910 ivideo->sisfb_useoem = sisfb_useoem;
5911 ivideo->sisfb_mode_idx = sisfb_mode_idx;
5912 ivideo->sisfb_parm_rate = sisfb_parm_rate;
5913 ivideo->sisfb_crt1off = sisfb_crt1off;
5914 ivideo->sisfb_forcecrt1 = sisfb_forcecrt1;
5915 ivideo->sisfb_crt2type = sisfb_crt2type;
5916 ivideo->sisfb_crt2flags = sisfb_crt2flags;
5917 /* pdc(a), scalelcd, special timing, lvdshl handled below */
5918 ivideo->sisfb_dstn = sisfb_dstn;
5919 ivideo->sisfb_fstn = sisfb_fstn;
5920 ivideo->sisfb_tvplug = sisfb_tvplug;
5921 ivideo->sisfb_tvstd = sisfb_tvstd;
5922 ivideo->tvxpos = sisfb_tvxposoffset;
5923 ivideo->tvypos = sisfb_tvyposoffset;
5924 ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
5925 ivideo->refresh_rate = 0;
5926 if(ivideo->sisfb_parm_rate != -1) {
5927 ivideo->refresh_rate = ivideo->sisfb_parm_rate;
5928 }
5929
5930 ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
5931 ivideo->SiS_Pr.CenterScreen = -1;
5932 ivideo->SiS_Pr.SiS_CustomT = sisfb_specialtiming;
5933 ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;
5934
5935 ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
5936 ivideo->SiS_Pr.SiS_CHOverScan = -1;
5937 ivideo->SiS_Pr.SiS_ChSW = false;
5938 ivideo->SiS_Pr.SiS_UseLCDA = false;
5939 ivideo->SiS_Pr.HaveEMI = false;
5940 ivideo->SiS_Pr.HaveEMILCD = false;
5941 ivideo->SiS_Pr.OverruleEMI = false;
5942 ivideo->SiS_Pr.SiS_SensibleSR11 = false;
5943 ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
5944 ivideo->SiS_Pr.PDC = -1;
5945 ivideo->SiS_Pr.PDCA = -1;
5946 ivideo->SiS_Pr.DDCPortMixup = false;
5947#ifdef CONFIG_FB_SIS_315
5948 if(ivideo->chip >= SIS_330) {
5949 ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
5950 if(ivideo->chip >= SIS_661) {
5951 ivideo->SiS_Pr.SiS_SensibleSR11 = true;
5952 }
5953 }
5954#endif
5955
5956 memcpy(&ivideo->default_var, &my_default_var, sizeof(my_default_var));
5957
5958 pci_set_drvdata(pdev, data: ivideo);
5959
5960 /* Patch special cases */
5961 if((ivideo->nbridge = sisfb_get_northbridge(basechipid: ivideo->chip))) {
5962 switch(ivideo->nbridge->device) {
5963#ifdef CONFIG_FB_SIS_300
5964 case PCI_DEVICE_ID_SI_730:
5965 ivideo->chip = SIS_730;
5966 strcpy(p: ivideo->myid, q: "SiS 730");
5967 break;
5968#endif
5969#ifdef CONFIG_FB_SIS_315
5970 case PCI_DEVICE_ID_SI_651:
5971 /* ivideo->chip is ok */
5972 strcpy(p: ivideo->myid, q: "SiS 651");
5973 break;
5974 case PCI_DEVICE_ID_SI_740:
5975 ivideo->chip = SIS_740;
5976 strcpy(p: ivideo->myid, q: "SiS 740");
5977 break;
5978 case PCI_DEVICE_ID_SI_661:
5979 ivideo->chip = SIS_661;
5980 strcpy(p: ivideo->myid, q: "SiS 661");
5981 break;
5982 case PCI_DEVICE_ID_SI_741:
5983 ivideo->chip = SIS_741;
5984 strcpy(p: ivideo->myid, q: "SiS 741");
5985 break;
5986 case PCI_DEVICE_ID_SI_760:
5987 ivideo->chip = SIS_760;
5988 strcpy(p: ivideo->myid, q: "SiS 760");
5989 break;
5990 case PCI_DEVICE_ID_SI_761:
5991 ivideo->chip = SIS_761;
5992 strcpy(p: ivideo->myid, q: "SiS 761");
5993 break;
5994#endif
5995 default:
5996 break;
5997 }
5998 }
5999
6000 ivideo->SiS_Pr.ChipType = ivideo->chip;
6001
6002 ivideo->SiS_Pr.ivideo = (void *)ivideo;
6003
6004#ifdef CONFIG_FB_SIS_315
6005 if((ivideo->SiS_Pr.ChipType == SIS_315PRO) ||
6006 (ivideo->SiS_Pr.ChipType == SIS_315)) {
6007 ivideo->SiS_Pr.ChipType = SIS_315H;
6008 }
6009#endif
6010
6011 if(!ivideo->sisvga_enabled) {
6012 if(pci_enable_device(dev: pdev)) {
6013 pci_dev_put(dev: ivideo->nbridge);
6014 framebuffer_release(info: sis_fb_info);
6015 return -EIO;
6016 }
6017 }
6018
6019 ivideo->video_base = pci_resource_start(pdev, 0);
6020 ivideo->video_size = pci_resource_len(pdev, 0);
6021 ivideo->mmio_base = pci_resource_start(pdev, 1);
6022 ivideo->mmio_size = pci_resource_len(pdev, 1);
6023 ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
6024 ivideo->SiS_Pr.IOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
6025
6026 SiSRegInit(SiS_Pr: &ivideo->SiS_Pr, BaseAddr: ivideo->SiS_Pr.IOAddress);
6027
6028#ifdef CONFIG_FB_SIS_300
6029 /* Find PCI systems for Chrontel/GPIO communication setup */
6030 if(ivideo->chip == SIS_630) {
6031 i = 0;
6032 do {
6033 if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
6034 mychswtable[i].subsysCard == ivideo->subsysdevice) {
6035 ivideo->SiS_Pr.SiS_ChSW = true;
6036 printk(KERN_DEBUG "sisfb: Identified [%s %s] "
6037 "requiring Chrontel/GPIO setup\n",
6038 mychswtable[i].vendorName,
6039 mychswtable[i].cardName);
6040 ivideo->lpcdev = pci_get_device(PCI_VENDOR_ID_SI, device: 0x0008, NULL);
6041 break;
6042 }
6043 i++;
6044 } while(mychswtable[i].subsysVendor != 0);
6045 }
6046#endif
6047
6048#ifdef CONFIG_FB_SIS_315
6049 if((ivideo->chip == SIS_760) && (ivideo->nbridge)) {
6050 ivideo->lpcdev = pci_get_slot(bus: ivideo->nbridge->bus, devfn: (2 << 3));
6051 }
6052#endif
6053
6054 SiS_SetReg(SISSR, 0x05, 0x86);
6055
6056 if( (!ivideo->sisvga_enabled)
6057#if !defined(__i386__) && !defined(__x86_64__)
6058 || (sisfb_resetcard)
6059#endif
6060 ) {
6061 for(i = 0x30; i <= 0x3f; i++) {
6062 SiS_SetReg(SISCR, i, 0x00);
6063 }
6064 }
6065
6066 /* Find out about current video mode */
6067 ivideo->modeprechange = 0x03;
6068 reg = SiS_GetReg(SISCR, 0x34);
6069 if(reg & 0x7f) {
6070 ivideo->modeprechange = reg & 0x7f;
6071 } else if(ivideo->sisvga_enabled) {
6072#if defined(__i386__) || defined(__x86_64__)
6073 unsigned char __iomem *tt = ioremap(offset: 0x400, size: 0x100);
6074 if(tt) {
6075 ivideo->modeprechange = readb(addr: tt + 0x49);
6076 iounmap(addr: tt);
6077 }
6078#endif
6079 }
6080
6081 /* Search and copy ROM image */
6082 ivideo->bios_abase = NULL;
6083 ivideo->SiS_Pr.VirtualRomBase = NULL;
6084 ivideo->SiS_Pr.UseROM = false;
6085 ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = false;
6086 if(ivideo->sisfb_userom) {
6087 ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev);
6088 ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase;
6089 ivideo->SiS_Pr.UseROM = (bool)(ivideo->SiS_Pr.VirtualRomBase);
6090 printk(KERN_INFO "sisfb: Video ROM %sfound\n",
6091 ivideo->SiS_Pr.UseROM ? "" : "not ");
6092 if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) {
6093 ivideo->SiS_Pr.UseROM = false;
6094 ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = true;
6095 if( (ivideo->revision_id == 2) &&
6096 (!(ivideo->bios_abase[0x1d1] & 0x01)) ) {
6097 ivideo->SiS_Pr.DDCPortMixup = true;
6098 }
6099 }
6100 } else {
6101 printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
6102 }
6103
6104 /* Find systems for special custom timing */
6105 if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
6106 sisfb_detect_custom_timing(ivideo);
6107 }
6108
6109#ifdef CONFIG_FB_SIS_315
6110 if (ivideo->chip == XGI_20) {
6111 /* Check if our Z7 chip is actually Z9 */
6112 SiS_SetRegOR(SISCR, 0x4a, 0x40); /* GPIOG EN */
6113 reg = SiS_GetReg(SISCR, 0x48);
6114 if (reg & 0x02) { /* GPIOG */
6115 ivideo->chip_real_id = XGI_21;
6116 dev_info(&pdev->dev, "Z9 detected\n");
6117 }
6118 }
6119#endif
6120
6121 /* POST card in case this has not been done by the BIOS */
6122 if( (!ivideo->sisvga_enabled)
6123#if !defined(__i386__) && !defined(__x86_64__)
6124 || (sisfb_resetcard)
6125#endif
6126 ) {
6127#ifdef CONFIG_FB_SIS_300
6128 if(ivideo->sisvga_engine == SIS_300_VGA) {
6129 if(ivideo->chip == SIS_300) {
6130 sisfb_post_sis300(pdev);
6131 ivideo->sisfb_can_post = 1;
6132 }
6133 }
6134#endif
6135
6136#ifdef CONFIG_FB_SIS_315
6137 if (ivideo->sisvga_engine == SIS_315_VGA) {
6138 int result = 1;
6139
6140 if (ivideo->chip == XGI_20) {
6141 result = sisfb_post_xgi(pdev);
6142 ivideo->sisfb_can_post = 1;
6143 } else if ((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
6144 result = sisfb_post_xgi(pdev);
6145 ivideo->sisfb_can_post = 1;
6146 } else {
6147 printk(KERN_INFO "sisfb: Card is not "
6148 "POSTed and sisfb can't do this either.\n");
6149 }
6150 if (!result) {
6151 printk(KERN_ERR "sisfb: Failed to POST card\n");
6152 ret = -ENODEV;
6153 goto error_3;
6154 }
6155 }
6156#endif
6157 }
6158
6159 ivideo->sisfb_card_posted = 1;
6160
6161 /* Find out about RAM size */
6162 if(sisfb_get_dram_size(ivideo)) {
6163 printk(KERN_INFO "sisfb: Fatal error: Unable to determine VRAM size.\n");
6164 ret = -ENODEV;
6165 goto error_3;
6166 }
6167
6168
6169 /* Enable PCI addressing and MMIO */
6170 if((ivideo->sisfb_mode_idx < 0) ||
6171 ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
6172 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
6173 SiS_SetRegOR(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
6174 /* Enable 2D accelerator engine */
6175 SiS_SetRegOR(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
6176 }
6177
6178 if(sisfb_pdc != 0xff) {
6179 if(ivideo->sisvga_engine == SIS_300_VGA)
6180 sisfb_pdc &= 0x3c;
6181 else
6182 sisfb_pdc &= 0x1f;
6183 ivideo->SiS_Pr.PDC = sisfb_pdc;
6184 }
6185#ifdef CONFIG_FB_SIS_315
6186 if(ivideo->sisvga_engine == SIS_315_VGA) {
6187 if(sisfb_pdca != 0xff)
6188 ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
6189 }
6190#endif
6191
6192 if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
6193 printk(KERN_ERR "sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
6194 (int)(ivideo->video_size >> 20));
6195 printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
6196 ret = -ENODEV;
6197 goto error_3;
6198 }
6199
6200 if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
6201 printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
6202 ret = -ENODEV;
6203 goto error_2;
6204 }
6205
6206 ivideo->video_vbase = ioremap_wc(offset: ivideo->video_base, size: ivideo->video_size);
6207 ivideo->SiS_Pr.VideoMemoryAddress = ivideo->video_vbase;
6208 if(!ivideo->video_vbase) {
6209 printk(KERN_ERR "sisfb: Fatal error: Unable to map framebuffer memory\n");
6210 ret = -ENODEV;
6211 goto error_1;
6212 }
6213
6214 ivideo->mmio_vbase = ioremap(offset: ivideo->mmio_base, size: ivideo->mmio_size);
6215 if(!ivideo->mmio_vbase) {
6216 printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
6217 ret = -ENODEV;
6218error_0: iounmap(addr: ivideo->video_vbase);
6219error_1: release_mem_region(ivideo->video_base, ivideo->video_size);
6220error_2: release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
6221error_3: vfree(addr: ivideo->bios_abase);
6222 pci_dev_put(dev: ivideo->lpcdev);
6223 pci_dev_put(dev: ivideo->nbridge);
6224 if(!ivideo->sisvga_enabled)
6225 pci_disable_device(dev: pdev);
6226 framebuffer_release(info: sis_fb_info);
6227 return ret;
6228 }
6229
6230 printk(KERN_INFO "sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
6231 ivideo->video_base, (unsigned long)ivideo->video_vbase, ivideo->video_size / 1024);
6232
6233 if(ivideo->video_offset) {
6234 printk(KERN_INFO "sisfb: Viewport offset %ldk\n",
6235 ivideo->video_offset / 1024);
6236 }
6237
6238 printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
6239 ivideo->mmio_base, (unsigned long)ivideo->mmio_vbase, ivideo->mmio_size / 1024);
6240
6241
6242 /* Determine the size of the command queue */
6243 if(ivideo->sisvga_engine == SIS_300_VGA) {
6244 ivideo->cmdQueueSize = TURBO_QUEUE_AREA_SIZE;
6245 } else {
6246 if(ivideo->chip == XGI_20) {
6247 ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE_Z7;
6248 } else {
6249 ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE;
6250 }
6251 }
6252
6253 /* Engines are no longer initialized here; this is
6254 * now done after the first mode-switch (if the
6255 * submitted var has its acceleration flags set).
6256 */
6257
6258 /* Calculate the base of the (unused) hw cursor */
6259 ivideo->hwcursor_vbase = ivideo->video_vbase
6260 + ivideo->video_size
6261 - ivideo->cmdQueueSize
6262 - ivideo->hwcursor_size;
6263 ivideo->caps |= HW_CURSOR_CAP;
6264
6265 /* Initialize offscreen memory manager */
6266 if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
6267 printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
6268 }
6269
6270 /* Used for clearing the screen only, therefore respect our mem limit */
6271 ivideo->SiS_Pr.VideoMemoryAddress += ivideo->video_offset;
6272 ivideo->SiS_Pr.VideoMemorySize = ivideo->sisfb_mem;
6273
6274 ivideo->vbflags = 0;
6275 ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
6276 ivideo->tvdefmodeidx = DEFAULT_TVMODE;
6277 ivideo->defmodeidx = DEFAULT_MODE;
6278
6279 ivideo->newrom = 0;
6280 if(ivideo->chip < XGI_20) {
6281 if(ivideo->bios_abase) {
6282 ivideo->newrom = SiSDetermineROMLayout661(SiS_Pr: &ivideo->SiS_Pr);
6283 }
6284 }
6285
6286 if((ivideo->sisfb_mode_idx < 0) ||
6287 ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
6288
6289 sisfb_sense_crt1(ivideo);
6290
6291 sisfb_get_VB_type(ivideo);
6292
6293 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
6294 sisfb_detect_VB_connect(ivideo);
6295 }
6296
6297 ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
6298
6299 /* Decide on which CRT2 device to use */
6300 if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
6301 if(ivideo->sisfb_crt2type != -1) {
6302 if((ivideo->sisfb_crt2type == CRT2_LCD) &&
6303 (ivideo->vbflags & CRT2_LCD)) {
6304 ivideo->currentvbflags |= CRT2_LCD;
6305 } else if(ivideo->sisfb_crt2type != CRT2_LCD) {
6306 ivideo->currentvbflags |= ivideo->sisfb_crt2type;
6307 }
6308 } else {
6309 /* Chrontel 700x TV detection often unreliable, therefore
6310 * use a different default order on such machines
6311 */
6312 if((ivideo->sisvga_engine == SIS_300_VGA) &&
6313 (ivideo->vbflags2 & VB2_CHRONTEL)) {
6314 if(ivideo->vbflags & CRT2_LCD)
6315 ivideo->currentvbflags |= CRT2_LCD;
6316 else if(ivideo->vbflags & CRT2_TV)
6317 ivideo->currentvbflags |= CRT2_TV;
6318 else if(ivideo->vbflags & CRT2_VGA)
6319 ivideo->currentvbflags |= CRT2_VGA;
6320 } else {
6321 if(ivideo->vbflags & CRT2_TV)
6322 ivideo->currentvbflags |= CRT2_TV;
6323 else if(ivideo->vbflags & CRT2_LCD)
6324 ivideo->currentvbflags |= CRT2_LCD;
6325 else if(ivideo->vbflags & CRT2_VGA)
6326 ivideo->currentvbflags |= CRT2_VGA;
6327 }
6328 }
6329 }
6330
6331 if(ivideo->vbflags & CRT2_LCD) {
6332 sisfb_detect_lcd_type(ivideo);
6333 }
6334
6335 sisfb_save_pdc_emi(ivideo);
6336
6337 if(!ivideo->sisfb_crt1off) {
6338 sisfb_handle_ddc(ivideo, monitor: &ivideo->sisfb_thismonitor, crtno: 0);
6339 } else {
6340 if((ivideo->vbflags2 & VB2_SISTMDSBRIDGE) &&
6341 (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
6342 sisfb_handle_ddc(ivideo, monitor: &ivideo->sisfb_thismonitor, crtno: 1);
6343 }
6344 }
6345
6346 if(ivideo->sisfb_mode_idx >= 0) {
6347 int bu = ivideo->sisfb_mode_idx;
6348 ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
6349 myindex: ivideo->sisfb_mode_idx, vbflags: ivideo->currentvbflags);
6350 if(bu != ivideo->sisfb_mode_idx) {
6351 printk(KERN_ERR "Mode %dx%dx%d failed validation\n",
6352 sisbios_mode[bu].xres,
6353 sisbios_mode[bu].yres,
6354 sisbios_mode[bu].bpp);
6355 }
6356 }
6357
6358 if(ivideo->sisfb_mode_idx < 0) {
6359 switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
6360 case CRT2_LCD:
6361 ivideo->sisfb_mode_idx = ivideo->lcddefmodeidx;
6362 break;
6363 case CRT2_TV:
6364 ivideo->sisfb_mode_idx = ivideo->tvdefmodeidx;
6365 break;
6366 default:
6367 ivideo->sisfb_mode_idx = ivideo->defmodeidx;
6368 break;
6369 }
6370 }
6371
6372 ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
6373
6374 if(ivideo->refresh_rate != 0) {
6375 sisfb_search_refresh_rate(ivideo, rate: ivideo->refresh_rate,
6376 mode_idx: ivideo->sisfb_mode_idx);
6377 }
6378
6379 if(ivideo->rate_idx == 0) {
6380 ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
6381 ivideo->refresh_rate = 60;
6382 }
6383
6384 if(ivideo->sisfb_thismonitor.datavalid) {
6385 if(!sisfb_verify_rate(ivideo, monitor: &ivideo->sisfb_thismonitor,
6386 mode_idx: ivideo->sisfb_mode_idx,
6387 rate_idx: ivideo->rate_idx,
6388 rate: ivideo->refresh_rate)) {
6389 printk(KERN_INFO "sisfb: WARNING: Refresh rate "
6390 "exceeds monitor specs!\n");
6391 }
6392 }
6393
6394 ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
6395 ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
6396 ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
6397
6398 sisfb_set_vparms(ivideo);
6399
6400 printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
6401 ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
6402 ivideo->refresh_rate);
6403
6404 /* Set up the default var according to chosen default display mode */
6405 ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
6406 ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
6407 ivideo->default_var.bits_per_pixel = ivideo->video_bpp;
6408
6409 sisfb_bpp_to_var(ivideo, var: &ivideo->default_var);
6410
6411 ivideo->default_var.pixclock = (u32) (1000000000 /
6412 sisfb_mode_rate_to_dclock(SiS_Pr: &ivideo->SiS_Pr, modeno: ivideo->mode_no, rateindex: ivideo->rate_idx));
6413
6414 if(sisfb_mode_rate_to_ddata(SiS_Pr: &ivideo->SiS_Pr, modeno: ivideo->mode_no,
6415 rateindex: ivideo->rate_idx, var: &ivideo->default_var)) {
6416 if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
6417 ivideo->default_var.pixclock <<= 1;
6418 }
6419 }
6420
6421 if(ivideo->sisfb_ypan) {
6422 /* Maximize regardless of sisfb_max at startup */
6423 ivideo->default_var.yres_virtual =
6424 sisfb_calc_maxyres(ivideo, var: &ivideo->default_var);
6425 if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
6426 ivideo->default_var.yres_virtual = ivideo->default_var.yres;
6427 }
6428 }
6429
6430 sisfb_calc_pitch(ivideo, var: &ivideo->default_var);
6431
6432 ivideo->accel = 0;
6433 if(ivideo->sisfb_accel) {
6434 ivideo->accel = -1;
6435#ifdef STUPID_ACCELF_TEXT_SHIT
6436 ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
6437#endif
6438 }
6439 sisfb_initaccel(ivideo);
6440
6441#if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
6442 sis_fb_info->flags = FBINFO_HWACCEL_YPAN |
6443 FBINFO_HWACCEL_XPAN |
6444 FBINFO_HWACCEL_COPYAREA |
6445 FBINFO_HWACCEL_FILLRECT |
6446 ((ivideo->accel) ? 0 : FBINFO_HWACCEL_DISABLED);
6447#endif
6448 sis_fb_info->var = ivideo->default_var;
6449 sis_fb_info->fix = ivideo->sisfb_fix;
6450 sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset;
6451 sis_fb_info->fbops = &sisfb_ops;
6452 sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
6453
6454 fb_alloc_cmap(cmap: &sis_fb_info->cmap, len: 256 , transp: 0);
6455
6456 printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags);
6457
6458 ivideo->wc_cookie = arch_phys_wc_add(base: ivideo->video_base,
6459 size: ivideo->video_size);
6460 if(register_framebuffer(fb_info: sis_fb_info) < 0) {
6461 printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
6462 ret = -EINVAL;
6463 iounmap(addr: ivideo->mmio_vbase);
6464 goto error_0;
6465 }
6466
6467 ivideo->registered = 1;
6468
6469 /* Enlist us */
6470 ivideo->next = card_list;
6471 card_list = ivideo;
6472
6473 printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
6474 ivideo->sisfb_accel ? "enabled" : "disabled",
6475 ivideo->sisfb_ypan ?
6476 (ivideo->sisfb_max ? "enabled (auto-max)" :
6477 "enabled (no auto-max)") :
6478 "disabled");
6479
6480
6481 fb_info(sis_fb_info, "%s frame buffer device version %d.%d.%d\n",
6482 ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
6483
6484 printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
6485
6486 } /* if mode = "none" */
6487
6488 return 0;
6489}
6490
6491/*****************************************************/
6492/* PCI DEVICE HANDLING */
6493/*****************************************************/
6494
6495static void sisfb_remove(struct pci_dev *pdev)
6496{
6497 struct sis_video_info *ivideo = pci_get_drvdata(pdev);
6498 struct fb_info *sis_fb_info = ivideo->memyselfandi;
6499 int registered = ivideo->registered;
6500 int modechanged = ivideo->modechanged;
6501
6502 /* Unmap */
6503 iounmap(addr: ivideo->mmio_vbase);
6504 iounmap(addr: ivideo->video_vbase);
6505
6506 /* Release mem regions */
6507 release_mem_region(ivideo->video_base, ivideo->video_size);
6508 release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
6509
6510 vfree(addr: ivideo->bios_abase);
6511
6512 pci_dev_put(dev: ivideo->lpcdev);
6513
6514 pci_dev_put(dev: ivideo->nbridge);
6515
6516 arch_phys_wc_del(handle: ivideo->wc_cookie);
6517
6518 /* If device was disabled when starting, disable
6519 * it when quitting.
6520 */
6521 if(!ivideo->sisvga_enabled)
6522 pci_disable_device(dev: pdev);
6523
6524 /* Unregister the framebuffer */
6525 if(ivideo->registered) {
6526 unregister_framebuffer(fb_info: sis_fb_info);
6527 framebuffer_release(info: sis_fb_info);
6528 }
6529
6530 /* OK, our ivideo is gone for good from here. */
6531
6532 /* TODO: Restore the initial mode
6533 * This sounds easy but is as good as impossible
6534 * on many machines with SiS chip and video bridge
6535 * since text modes are always set up differently
6536 * from machine to machine. Depends on the type
6537 * of integration between chipset and bridge.
6538 */
6539 if(registered && modechanged)
6540 printk(KERN_INFO
6541 "sisfb: Restoring of text mode not supported yet\n");
6542};
6543
6544static struct pci_driver sisfb_driver = {
6545 .name = "sisfb",
6546 .id_table = sisfb_pci_table,
6547 .probe = sisfb_probe,
6548 .remove = sisfb_remove,
6549};
6550
6551static int __init sisfb_init(void)
6552{
6553#ifndef MODULE
6554 char *options = NULL;
6555#endif
6556
6557 if (fb_modesetting_disabled(drvname: "sisfb"))
6558 return -ENODEV;
6559
6560#ifndef MODULE
6561 if(fb_get_options(name: "sisfb", option: &options))
6562 return -ENODEV;
6563
6564 sisfb_setup(options);
6565#endif
6566 return pci_register_driver(&sisfb_driver);
6567}
6568
6569#ifndef MODULE
6570module_init(sisfb_init);
6571#endif
6572
6573/*****************************************************/
6574/* MODULE */
6575/*****************************************************/
6576
6577#ifdef MODULE
6578
6579static char *mode = NULL;
6580static int vesa = -1;
6581static unsigned int rate = 0;
6582static unsigned int crt1off = 1;
6583static unsigned int mem = 0;
6584static char *forcecrt2type = NULL;
6585static int forcecrt1 = -1;
6586static int pdc = -1;
6587static int pdc1 = -1;
6588static int noaccel = -1;
6589static int noypan = -1;
6590static int nomax = -1;
6591static int userom = -1;
6592static int useoem = -1;
6593static char *tvstandard = NULL;
6594static int nocrt2rate = 0;
6595static int scalelcd = -1;
6596static char *specialtiming = NULL;
6597static int lvdshl = -1;
6598static int tvxposoffset = 0, tvyposoffset = 0;
6599#if !defined(__i386__) && !defined(__x86_64__)
6600static int resetcard = 0;
6601static int videoram = 0;
6602#endif
6603
6604static int __init sisfb_init_module(void)
6605{
6606 sisfb_setdefaultparms();
6607
6608 if(rate)
6609 sisfb_parm_rate = rate;
6610
6611 if((scalelcd == 0) || (scalelcd == 1))
6612 sisfb_scalelcd = scalelcd ^ 1;
6613
6614 /* Need to check crt2 type first for fstn/dstn */
6615
6616 if(forcecrt2type)
6617 sisfb_search_crt2type(forcecrt2type);
6618
6619 if(tvstandard)
6620 sisfb_search_tvstd(tvstandard);
6621
6622 if(mode)
6623 sisfb_search_mode(mode, false);
6624 else if(vesa != -1)
6625 sisfb_search_vesamode(vesa, false);
6626
6627 sisfb_crt1off = (crt1off == 0) ? 1 : 0;
6628
6629 sisfb_forcecrt1 = forcecrt1;
6630 if(forcecrt1 == 1)
6631 sisfb_crt1off = 0;
6632 else if(forcecrt1 == 0)
6633 sisfb_crt1off = 1;
6634
6635 if(noaccel == 1)
6636 sisfb_accel = 0;
6637 else if(noaccel == 0)
6638 sisfb_accel = 1;
6639
6640 if(noypan == 1)
6641 sisfb_ypan = 0;
6642 else if(noypan == 0)
6643 sisfb_ypan = 1;
6644
6645 if(nomax == 1)
6646 sisfb_max = 0;
6647 else if(nomax == 0)
6648 sisfb_max = 1;
6649
6650 if(mem)
6651 sisfb_parm_mem = mem;
6652
6653 if(userom != -1)
6654 sisfb_userom = userom;
6655
6656 if(useoem != -1)
6657 sisfb_useoem = useoem;
6658
6659 if(pdc != -1)
6660 sisfb_pdc = (pdc & 0x7f);
6661
6662 if(pdc1 != -1)
6663 sisfb_pdca = (pdc1 & 0x1f);
6664
6665 sisfb_nocrt2rate = nocrt2rate;
6666
6667 if(specialtiming)
6668 sisfb_search_specialtiming(specialtiming);
6669
6670 if((lvdshl >= 0) && (lvdshl <= 3))
6671 sisfb_lvdshl = lvdshl;
6672
6673 sisfb_tvxposoffset = tvxposoffset;
6674 sisfb_tvyposoffset = tvyposoffset;
6675
6676#if !defined(__i386__) && !defined(__x86_64__)
6677 sisfb_resetcard = (resetcard) ? 1 : 0;
6678 if(videoram)
6679 sisfb_videoram = videoram;
6680#endif
6681
6682 return sisfb_init();
6683}
6684
6685static void __exit sisfb_remove_module(void)
6686{
6687 pci_unregister_driver(&sisfb_driver);
6688 printk(KERN_DEBUG "sisfb: Module unloaded\n");
6689}
6690
6691module_init(sisfb_init_module);
6692module_exit(sisfb_remove_module);
6693
6694MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
6695MODULE_LICENSE("GPL");
6696MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
6697
6698module_param(mem, int, 0);
6699module_param(noaccel, int, 0);
6700module_param(noypan, int, 0);
6701module_param(nomax, int, 0);
6702module_param(userom, int, 0);
6703module_param(useoem, int, 0);
6704module_param(mode, charp, 0);
6705module_param(vesa, int, 0);
6706module_param(rate, int, 0);
6707module_param(forcecrt1, int, 0);
6708module_param(forcecrt2type, charp, 0);
6709module_param(scalelcd, int, 0);
6710module_param(pdc, int, 0);
6711module_param(pdc1, int, 0);
6712module_param(specialtiming, charp, 0);
6713module_param(lvdshl, int, 0);
6714module_param(tvstandard, charp, 0);
6715module_param(tvxposoffset, int, 0);
6716module_param(tvyposoffset, int, 0);
6717module_param(nocrt2rate, int, 0);
6718#if !defined(__i386__) && !defined(__x86_64__)
6719module_param(resetcard, int, 0);
6720module_param(videoram, int, 0);
6721#endif
6722
6723MODULE_PARM_DESC(mem,
6724 "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
6725 "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
6726 "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
6727 "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
6728 "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
6729 "The value is to be specified without 'KB'.\n");
6730
6731MODULE_PARM_DESC(noaccel,
6732 "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
6733 "(default: 0)\n");
6734
6735MODULE_PARM_DESC(noypan,
6736 "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
6737 "will be performed by redrawing the screen. (default: 0)\n");
6738
6739MODULE_PARM_DESC(nomax,
6740 "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
6741 "memory for the virtual screen in order to optimize scrolling performance. If\n"
6742 "this is set to anything other than 0, sisfb will not do this and thereby \n"
6743 "enable the user to positively specify a virtual Y size of the screen using\n"
6744 "fbset. (default: 0)\n");
6745
6746MODULE_PARM_DESC(mode,
6747 "\nSelects the desired default display mode in the format XxYxDepth,\n"
6748 "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
6749 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
6750 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
6751
6752MODULE_PARM_DESC(vesa,
6753 "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
6754 "0x117 (default: 0x0103)\n");
6755
6756MODULE_PARM_DESC(rate,
6757 "\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
6758 "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
6759 "will be ignored (default: 60)\n");
6760
6761MODULE_PARM_DESC(forcecrt1,
6762 "\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
6763 "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
6764 "0=CRT1 OFF) (default: [autodetected])\n");
6765
6766MODULE_PARM_DESC(forcecrt2type,
6767 "\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
6768 "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
6769 "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
6770 "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
6771 "be used instead of TV to override the TV detection. Furthermore, on systems\n"
6772 "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
6773 "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
6774 "depends on the very hardware in use. (default: [autodetected])\n");
6775
6776MODULE_PARM_DESC(scalelcd,
6777 "\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
6778 "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
6779 "show black bars around the image, TMDS panels will probably do the scaling\n"
6780 "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
6781
6782MODULE_PARM_DESC(pdc,
6783 "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
6784 "should detect this correctly in most cases; however, sometimes this is not\n"
6785 "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
6786 "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
6787 "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
6788 "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
6789
6790#ifdef CONFIG_FB_SIS_315
6791MODULE_PARM_DESC(pdc1,
6792 "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
6793 "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
6794 "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
6795 "implemented yet.\n");
6796#endif
6797
6798MODULE_PARM_DESC(specialtiming,
6799 "\nPlease refer to documentation for more information on this option.\n");
6800
6801MODULE_PARM_DESC(lvdshl,
6802 "\nPlease refer to documentation for more information on this option.\n");
6803
6804MODULE_PARM_DESC(tvstandard,
6805 "\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
6806 "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");
6807
6808MODULE_PARM_DESC(tvxposoffset,
6809 "\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
6810 "Default: 0\n");
6811
6812MODULE_PARM_DESC(tvyposoffset,
6813 "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
6814 "Default: 0\n");
6815
6816MODULE_PARM_DESC(nocrt2rate,
6817 "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
6818 "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
6819
6820#if !defined(__i386__) && !defined(__x86_64__)
6821#ifdef CONFIG_FB_SIS_300
6822MODULE_PARM_DESC(resetcard,
6823 "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
6824 "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
6825 "currently). Default: 0\n");
6826
6827MODULE_PARM_DESC(videoram,
6828 "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
6829 "some non-x86 architectures where the memory auto detection fails. Only\n"
6830 "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
6831#endif
6832#endif
6833
6834#endif /* /MODULE */
6835
6836/* _GPL only for new symbols. */
6837EXPORT_SYMBOL(sis_malloc);
6838EXPORT_SYMBOL(sis_free);
6839EXPORT_SYMBOL_GPL(sis_malloc_new);
6840EXPORT_SYMBOL_GPL(sis_free_new);
6841
6842
6843
6844

source code of linux/drivers/video/fbdev/sis/sis_main.c