sis_main.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:108k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * SiS 300/630/730/540/315/550/650/740 frame buffer device
  3.  * for Linux kernels 2.4.x and 2.5.x
  4.  *
  5.  * Partly based on the VBE 2.0 compliant graphic boards framebuffer driver,
  6.  * which is (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
  7.  *
  8.  * Authors:    SiS (www.sis.com.tw)
  9.  * (Various others)
  10.  * Thomas Winischhofer <thomas@winischhofer.net>:
  11.  * - many fixes and enhancements for all chipset series,
  12.  * - extended bridge handling, TV output for Chrontel 7005
  13.  *                      - 650/LVDS support (for LCD panels up to 1400x1050)
  14.  *                      - 650/Chrontel 7019 support
  15.  *                      - 301B/301LV(x)/302B/302LV(x) LCD and TV support
  16.  * - memory queue handling enhancements,
  17.  *                      - 2D acceleration and y-panning,
  18.  *                      - portation to 2.5 API (yet incomplete)
  19.  * - everything marked with "TW" and more
  20.  * (see http://www.winischhofer.net/
  21.  * for more information and updates)
  22.  */
  23. #include <linux/config.h>
  24. #include <linux/version.h>
  25. #include <linux/module.h>
  26. #include <linux/kernel.h>
  27. #include <linux/errno.h>
  28. #include <linux/string.h>
  29. #include <linux/mm.h>
  30. #include <linux/tty.h>
  31. #include <linux/slab.h>
  32. #include <linux/delay.h>
  33. #include <linux/fb.h>
  34. #include <linux/console.h>
  35. #include <linux/selection.h>
  36. #include <linux/ioport.h>
  37. #include <linux/init.h>
  38. #include <linux/pci.h>
  39. #include <linux/vt_kern.h>
  40. #include <linux/capability.h>
  41. #include <linux/fs.h>
  42. #include <linux/agp_backend.h>
  43. #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,33)
  44. #include <linux/spinlock.h>
  45. #endif
  46. #include "osdef.h"
  47. #include <linux/types.h>
  48. #include <linux/sisfb.h>
  49. #include <asm/io.h>
  50. #include <asm/mtrr.h>
  51. #include <video/fbcon.h>
  52. #include <video/fbcon-cfb8.h>
  53. #include <video/fbcon-cfb16.h>
  54. #include <video/fbcon-cfb24.h>
  55. #include <video/fbcon-cfb32.h>
  56. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)
  57. #include "../fbcon-accel.h"
  58. #endif
  59. #include "vgatypes.h"
  60. #include "sis_main.h"
  61. #include "sis.h"
  62. //#ifdef LINUXBIOS
  63. //#include "bios.h"
  64. //#endif
  65. /* -------------------- Macro definitions ---------------------------- */
  66. #undef SISFBDEBUG /* TW: no debugging */
  67. #ifdef SISFBDEBUG
  68. #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
  69. #else
  70. #define DPRINTK(fmt, args...)
  71. #endif
  72. #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33)
  73. #ifdef SISFBACCEL
  74. #ifdef FBCON_HAS_CFB8
  75. extern struct display_switch fbcon_sis8;
  76. #endif
  77. #ifdef FBCON_HAS_CFB16
  78. extern struct display_switch fbcon_sis16;
  79. #endif
  80. #ifdef FBCON_HAS_CFB32
  81. extern struct display_switch fbcon_sis32;
  82. #endif
  83. #endif
  84. #endif
  85. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)
  86. /* TEMP */
  87. void my_cfb_imageblit(struct fb_info *info, struct fb_image *image);
  88. #endif
  89. /* --------------- Hardware Access Routines -------------------------- */
  90. void sisfb_set_reg4(u16 port, unsigned long data)
  91. {
  92. outl((u32) (data & 0xffffffff), port);
  93. }
  94. u32 sisfb_get_reg3(u16 port)
  95. {
  96. u32 data;
  97. data = inl(port);
  98. return (data);
  99. }
  100. /* -------------------- Interface to BIOS code -------------------- */
  101. BOOLEAN
  102. sisfb_query_VGA_config_space(PSIS_HW_DEVICE_INFO psishw_ext,
  103. unsigned long offset, unsigned long set, unsigned long *value)
  104. {
  105. static struct pci_dev *pdev = NULL;
  106. static unsigned char init = 0, valid_pdev = 0;
  107. if (!set)
  108. DPRINTK("sisfb: Get VGA offset 0x%lxn", offset);
  109. else
  110. DPRINTK("sisfb: Set offset 0x%lx to 0x%lxn", offset, *value);
  111. if (!init) {
  112. init = TRUE;
  113. pci_for_each_dev(pdev) {
  114. DPRINTK("sisfb: Current: 0x%x, target: 0x%xn",
  115.          pdev->device, ivideo.chip_id);
  116. if ((pdev->vendor == PCI_VENDOR_ID_SI)
  117.            && (pdev->device == ivideo.chip_id)) {
  118. valid_pdev = TRUE;
  119. break;
  120. }
  121. }
  122. }
  123. if (!valid_pdev) {
  124. printk(KERN_DEBUG "sisfb: Can't find SiS %d VGA device.n",
  125. ivideo.chip_id);
  126. return FALSE;
  127. }
  128. if (set == 0)
  129. pci_read_config_dword(pdev, offset, (u32 *)value);
  130. else
  131. pci_write_config_dword(pdev, offset, (u32)(*value));
  132. return TRUE;
  133. }
  134. BOOLEAN sisfb_query_north_bridge_space(PSIS_HW_DEVICE_INFO psishw_ext,
  135. unsigned long offset, unsigned long set, unsigned long *value)
  136. {
  137. static struct pci_dev *pdev = NULL;
  138. static unsigned char init = 0, valid_pdev = 0;
  139. u16 nbridge_id = 0;
  140. if (!init) {
  141. init = TRUE;
  142. switch (ivideo.chip) {
  143. case SIS_540:
  144. nbridge_id = PCI_DEVICE_ID_SI_540;
  145. break;
  146. case SIS_630:
  147. nbridge_id = PCI_DEVICE_ID_SI_630;
  148. break;
  149. case SIS_730:
  150. nbridge_id = PCI_DEVICE_ID_SI_730;
  151. break;
  152. case SIS_550:
  153. nbridge_id = PCI_DEVICE_ID_SI_550;
  154. break;
  155. case SIS_650:
  156. nbridge_id = PCI_DEVICE_ID_SI_650;
  157. break;
  158. default:
  159. nbridge_id = 0;
  160. break;
  161. }
  162. pci_for_each_dev(pdev) {
  163. DPRINTK("Current: 0x%x, target: 0x%xn",
  164. pdev->device, ivideo.chip_id);
  165. if ((pdev->vendor == PCI_VENDOR_ID_SI)
  166. && (pdev->device == nbridge_id)) {
  167. valid_pdev = TRUE;
  168. break;
  169. }
  170. }
  171. }
  172. if (!valid_pdev) {
  173. printk(KERN_DEBUG "sisfb: Can't find SiS %d North Bridge device.n",
  174. nbridge_id);
  175. return FALSE;
  176. }
  177. if (set == 0)
  178. pci_read_config_dword(pdev, offset, (u32 *)value);
  179. else
  180. pci_write_config_dword(pdev, offset, (u32)(*value));
  181. return TRUE;
  182. }
  183. /* -------------------- Exported functions ----------------------------- */
  184. static void sis_get_glyph(struct fb_info *info, SIS_GLYINFO *gly)
  185. {
  186. #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)
  187. #define currcon info->currcon
  188. #endif
  189. struct display *p = &fb_display[currcon];
  190. u16 c;
  191. u8 *cdat;
  192. int widthb;
  193. u8 *gbuf = gly->gmask;
  194. int size;
  195. TWDEBUG("Inside get_glyph");
  196. gly->fontheight = fontheight(p);
  197. gly->fontwidth = fontwidth(p);
  198. widthb = (fontwidth(p) + 7) / 8;
  199. c = gly->ch & p->charmask;
  200. if (fontwidth(p) <= 8)
  201. cdat = p->fontdata + c * fontheight(p);
  202. else
  203. cdat = p->fontdata + (c * fontheight(p) << 1);
  204. size = fontheight(p) * widthb;
  205. memcpy(gbuf, cdat, size);
  206. gly->ngmask = size;
  207. TWDEBUG("End of get_glyph");
  208. #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)
  209. #undef currcon 
  210. #endif
  211. }
  212. void sis_dispinfo(struct ap_data *rec)
  213. {
  214.         TWDEBUG("Inside dispinfo");
  215. rec->minfo.bpp    = ivideo.video_bpp;
  216. rec->minfo.xres   = ivideo.video_width;
  217. rec->minfo.yres   = ivideo.video_height;
  218. rec->minfo.v_xres = ivideo.video_vwidth;
  219. rec->minfo.v_yres = ivideo.video_vheight;
  220. rec->minfo.org_x  = ivideo.org_x;
  221. rec->minfo.org_y  = ivideo.org_y;
  222. rec->minfo.vrate  = ivideo.refresh_rate;
  223. rec->iobase       = ivideo.vga_base - 0x30;
  224. rec->mem_size     = ivideo.video_size;
  225. rec->disp_state   = ivideo.disp_state; 
  226. rec->version      = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL; 
  227. rec->hasVB        = ivideo.hasVB; 
  228. rec->TV_type      = ivideo.TV_type; 
  229. rec->TV_plug      = ivideo.TV_plug; 
  230. rec->chip         = ivideo.chip;
  231. TWDEBUG("End of dispinfo");
  232. }
  233. /* ------------------ Internal Routines ------------------------------ */
  234. static void sisfb_search_mode(const char *name)
  235. {
  236. int i = 0, j = 0;
  237. if(name == NULL)
  238. return;
  239. while(sisbios_mode[i].mode_no != 0) {
  240. if (!strcmp(name, sisbios_mode[i].name)) {
  241. sisfb_mode_idx = i;
  242. j = 1;
  243. break;
  244. }
  245. i++;
  246. }
  247. if(!j) printk(KERN_INFO "sisfb: Invalid mode '%s'n", name);
  248. }
  249. static void sisfb_search_vesamode(unsigned int vesamode)
  250. {
  251. int i = 0, j = 0;
  252. if(vesamode == 0) {
  253. sisfb_mode_idx = MODE_INDEX_NONE;
  254. return;
  255. }
  256. vesamode &= 0x1dff;  /* Clean VESA mode number from other flags */
  257. while(sisbios_mode[i].mode_no != 0) {
  258. if( (sisbios_mode[i].vesa_mode_no_1 == vesamode) ||
  259.     (sisbios_mode[i].vesa_mode_no_2 == vesamode) ) {
  260. sisfb_mode_idx = i;
  261. j = 1;
  262. break;
  263. }
  264. i++;
  265. }
  266. if(!j) printk(KERN_INFO "sisfb: Invalid VESA mode 0x%x'n", vesamode);
  267. }
  268. static int sisfb_validate_mode(int myindex)
  269. {
  270.    u16 xres, yres;
  271. #ifdef CONFIG_FB_SIS_300
  272.    if(sisvga_engine == SIS_300_VGA) {
  273.        if(!(sisbios_mode[sisfb_mode_idx].chipset & MD_SIS300)) {
  274.            return(-1);
  275.        }
  276.    }
  277. #endif
  278. #ifdef CONFIG_FB_SIS_315
  279.    if(sisvga_engine == SIS_315_VGA) {
  280.        if(!(sisbios_mode[myindex].chipset & MD_SIS315)) {
  281.    return(-1);
  282.        }
  283.    }
  284. #endif
  285.    switch (ivideo.disp_state & DISPTYPE_DISP2) {
  286.      case DISPTYPE_LCD:
  287. switch (sishw_ext.ulCRT2LCDType) {
  288. case LCD_1024x768:
  289.   xres = 1024; yres =  768;  break;
  290. case LCD_1280x1024:
  291. xres = 1280; yres = 1024;  break;
  292. case LCD_1280x960:
  293.         xres = 1280; yres =  960;  break;
  294. case LCD_2048x1536:
  295. xres = 2048; yres = 1536;  break;
  296. case LCD_1920x1440:
  297. xres = 1920; yres = 1440;  break;
  298. case LCD_1600x1200:
  299. xres = 1600; yres = 1200;  break;
  300. case LCD_800x600:
  301. xres =  800; yres =  600;  break;
  302. case LCD_640x480:
  303. xres =  640; yres =  480;  break;
  304. case LCD_320x480: /* TW: FSTN */
  305. xres =  320; yres =  480;  break;
  306.         case LCD_1024x600:
  307. xres = 1024; yres =  600;  break;
  308. case LCD_1152x864:
  309. xres = 1152; yres =  864;  break;
  310. case LCD_1152x768:
  311. xres = 1152; yres =  768;  break;
  312. case LCD_1280x768:
  313. xres = 1280; yres =  768;  break;
  314. case LCD_1400x1050:
  315. xres = 1400; yres = 1050;  break;
  316. default:
  317.         xres =    0; yres =    0;  break;
  318. }
  319. if(sisbios_mode[myindex].xres > xres) {
  320.         return(-1);
  321. }
  322.         if(sisbios_mode[myindex].yres > yres) {
  323.         return(-1);
  324. }
  325. if (sisbios_mode[myindex].xres == 720) {
  326. return(-1);
  327. }
  328. break;
  329.      case DISPTYPE_TV:
  330. switch (sisbios_mode[myindex].xres) {
  331. case 512:
  332. case 640:
  333. case 800:
  334. break;
  335. case 720:
  336. if (ivideo.TV_type == TVMODE_NTSC) {
  337. if (sisbios_mode[myindex].yres != 480) {
  338. return(-1);
  339. }
  340. } else if (ivideo.TV_type == TVMODE_PAL) {
  341. if (sisbios_mode[myindex].yres != 576) {
  342. return(-1);
  343. }
  344. }
  345. /* TW: LVDS/CHRONTEL does not support 720 */
  346. if (ivideo.hasVB == HASVB_LVDS_CHRONTEL ||
  347. ivideo.hasVB == HASVB_CHRONTEL) {
  348. return(-1);
  349. }
  350. break;
  351. case 1024:
  352. if (ivideo.TV_type == TVMODE_NTSC) {
  353. if(sisbios_mode[myindex].bpp == 32) {
  354.        return(-1);
  355. }
  356. }
  357. /* TW: LVDS/CHRONTEL only supports < 800 (1024 on 650/Ch7019)*/
  358. if (ivideo.hasVB == HASVB_LVDS_CHRONTEL ||
  359. ivideo.hasVB == HASVB_CHRONTEL) {
  360.     if(ivideo.chip < SIS_315H) {
  361. return(-1);
  362.     }
  363. }
  364. break;
  365. default:
  366. return(-1);
  367. }
  368. break;
  369.      }
  370.      return(myindex);
  371. }
  372. static void sisfb_search_crt2type(const char *name)
  373. {
  374. int i = 0;
  375. if(name == NULL)
  376. return;
  377. while(sis_crt2type[i].type_no != -1) {
  378. if (!strcmp(name, sis_crt2type[i].name)) {
  379. sisfb_crt2type = sis_crt2type[i].type_no;
  380. sisfb_tvplug = sis_crt2type[i].tvplug_no;
  381. break;
  382. }
  383. i++;
  384. }
  385. if(sisfb_crt2type < 0)
  386. printk(KERN_INFO "sisfb: Invalid CRT2 type: %sn", name);
  387. }
  388. static void sisfb_search_queuemode(const char *name)
  389. {
  390. int i = 0;
  391. if(name == NULL)
  392. return;
  393. while (sis_queuemode[i].type_no != -1) {
  394. if (!strcmp(name, sis_queuemode[i].name)) {
  395. sisfb_queuemode = sis_queuemode[i].type_no;
  396. break;
  397. }
  398. i++;
  399. }
  400. if (sisfb_queuemode < 0)
  401. printk(KERN_INFO "sisfb: Invalid queuemode type: %sn", name);
  402. }
  403. static u8 sisfb_search_refresh_rate(unsigned int rate)
  404. {
  405. u16 xres, yres;
  406. int i = 0;
  407. xres = sisbios_mode[sisfb_mode_idx].xres;
  408. yres = sisbios_mode[sisfb_mode_idx].yres;
  409. sisfb_rate_idx = 0;
  410. while ((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
  411. if ((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {
  412. if (sisfb_vrate[i].refresh == rate) {
  413. sisfb_rate_idx = sisfb_vrate[i].idx;
  414. break;
  415. } else if (sisfb_vrate[i].refresh > rate) {
  416. if ((sisfb_vrate[i].refresh - rate) <= 2) {
  417. DPRINTK("sisfb: Adjusting rate from %d up to %dn",
  418. rate, sisfb_vrate[i].refresh);
  419. sisfb_rate_idx = sisfb_vrate[i].idx;
  420. ivideo.refresh_rate = sisfb_vrate[i].refresh;
  421. } else if (((rate - sisfb_vrate[i-1].refresh) <= 2)
  422. && (sisfb_vrate[i].idx != 1)) {
  423. DPRINTK("sisfb: Adjusting rate from %d down to %dn",
  424. rate, sisfb_vrate[i-1].refresh);
  425. sisfb_rate_idx = sisfb_vrate[i-1].idx;
  426. ivideo.refresh_rate = sisfb_vrate[i-1].refresh;
  427. }
  428. break;
  429. }
  430. }
  431. i++;
  432. }
  433. if (sisfb_rate_idx > 0) {
  434. return sisfb_rate_idx;
  435. } else {
  436. printk(KERN_INFO
  437. "sisfb: Unsupported rate %d for %dx%dn", rate, xres, yres);
  438. return 0;
  439. }
  440. }
  441. #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33)
  442. static int sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue,
  443.  unsigned *transp, struct fb_info *fb_info)
  444. {
  445. if (regno >= ivideo.video_cmap_len)
  446. return 1;
  447. *red = sis_palette[regno].red;
  448. *green = sis_palette[regno].green;
  449. *blue = sis_palette[regno].blue;
  450. *transp = 0;
  451. return 0;
  452. }
  453. #endif
  454. static int sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
  455.                            unsigned transp, struct fb_info *fb_info)
  456. {
  457. if (regno >= ivideo.video_cmap_len)
  458. return 1;
  459. sis_palette[regno].red = red;
  460. sis_palette[regno].green = green;
  461. sis_palette[regno].blue = blue;
  462. switch (ivideo.video_bpp) {
  463. #ifdef FBCON_HAS_CFB8
  464. case 8:
  465.         outSISREG(SISDACA, regno);
  466. outSISREG(SISDACD, (red >> 10));
  467. outSISREG(SISDACD, (green >> 10));
  468. outSISREG(SISDACD, (blue >> 10));
  469. if (ivideo.disp_state & DISPTYPE_DISP2) {
  470.         outSISREG(SISDAC2A, regno);
  471. outSISREG(SISDAC2D, (red >> 8));
  472. outSISREG(SISDAC2D, (green >> 8));
  473. outSISREG(SISDAC2D, (blue >> 8));
  474. }
  475. break;
  476. #endif
  477. #ifdef FBCON_HAS_CFB16
  478. case 15:
  479. case 16:
  480. sis_fbcon_cmap.cfb16[regno] =
  481.     ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
  482. break;
  483. #endif
  484. #ifdef FBCON_HAS_CFB24
  485. case 24:
  486. red >>= 8;
  487. green >>= 8;
  488. blue >>= 8;
  489. sis_fbcon_cmap.cfb24[regno] = (red << 16) | (green << 8) | (blue);
  490. break;
  491. #endif
  492. #ifdef FBCON_HAS_CFB32
  493. case 32:
  494. red >>= 8;
  495. green >>= 8;
  496. blue >>= 8;
  497. sis_fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | (blue);
  498. break;
  499. #endif
  500. }
  501. return 0;
  502. }
  503. static int sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
  504.       struct fb_info *info)
  505. {
  506. unsigned int htotal =
  507. var->left_margin + var->xres + var->right_margin +
  508. var->hsync_len;
  509. unsigned int vtotal = 0; /* TW */
  510. /* var->upper_margin + var->yres + var->lower_margin +
  511. var->vsync_len;     */
  512. double drate = 0, hrate = 0;
  513. int found_mode = 0;
  514. int old_mode;
  515. TWDEBUG("Inside do_set_var");
  516. if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
  517. vtotal = var->upper_margin + var->yres + var->lower_margin +
  518.          var->vsync_len;   /* TW */
  519. vtotal <<= 1;
  520. } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
  521. vtotal = var->upper_margin + var->yres + var->lower_margin +
  522.          var->vsync_len;   /* TW */
  523. vtotal <<= 2;
  524. } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
  525. vtotal = var->upper_margin + (var->yres/2) + var->lower_margin +
  526.          var->vsync_len;   /* TW */
  527. /* var->yres <<= 1; */ /* TW */
  528. } else  vtotal = var->upper_margin + var->yres + var->lower_margin +
  529.          var->vsync_len;
  530. if(!(htotal) || !(vtotal)) {
  531. DPRINTK("sisfb: Invalid 'var' informationn");
  532. return -EINVAL;
  533. }
  534. drate = 1E12 / var->pixclock;
  535. hrate = drate / htotal;
  536. ivideo.refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
  537. /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
  538. if((var->xres == 1024) && (var->yres == 600)) ivideo.refresh_rate = 60;
  539. printk("sisfb: Change mode to %dx%dx%d-%dHzn",
  540. var->xres,var->yres,var->bits_per_pixel,ivideo.refresh_rate);
  541. old_mode = sisfb_mode_idx;
  542. sisfb_mode_idx = 0;
  543. while( (sisbios_mode[sisfb_mode_idx].mode_no != 0) &&
  544.        (sisbios_mode[sisfb_mode_idx].xres <= var->xres) ) {
  545. if( (sisbios_mode[sisfb_mode_idx].xres == var->xres) &&
  546.     (sisbios_mode[sisfb_mode_idx].yres == var->yres) &&
  547.     (sisbios_mode[sisfb_mode_idx].bpp == var->bits_per_pixel)) {
  548. sisfb_mode_no = sisbios_mode[sisfb_mode_idx].mode_no;
  549. found_mode = 1;
  550. break;
  551. }
  552. sisfb_mode_idx++;
  553. }
  554. if(found_mode)
  555. sisfb_mode_idx = sisfb_validate_mode(sisfb_mode_idx);
  556. else
  557. sisfb_mode_idx = -1;
  558.         if(sisfb_mode_idx < 0) {
  559. printk("sisfb: Mode %dx%dx%d not supportedn", var->xres,
  560.        var->yres, var->bits_per_pixel);
  561. sisfb_mode_idx = old_mode;
  562. return -EINVAL;
  563. }
  564. if(sisfb_search_refresh_rate(ivideo.refresh_rate) == 0) {
  565. sisfb_rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;
  566. ivideo.refresh_rate = 60;
  567. }
  568. #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33)
  569. if(((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) {
  570. #else
  571. if(isactive) {
  572. #endif
  573. sisfb_pre_setmode();
  574. if(SiSSetMode(&SiS_Pr, &sishw_ext, sisfb_mode_no) == 0) {
  575. printk("sisfb: Setting mode[0x%x] failedn", sisfb_mode_no);
  576. return -EINVAL;
  577. }
  578. outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
  579. sisfb_post_setmode();
  580. DPRINTK("sisfb: Set new mode: %dx%dx%d-%d n",
  581. sisbios_mode[sisfb_mode_idx].xres,
  582. sisbios_mode[sisfb_mode_idx].yres,
  583. sisbios_mode[sisfb_mode_idx].bpp,
  584. ivideo.refresh_rate);
  585. ivideo.video_bpp = sisbios_mode[sisfb_mode_idx].bpp;
  586. ivideo.video_vwidth = ivideo.video_width = sisbios_mode[sisfb_mode_idx].xres;
  587. ivideo.video_vheight = ivideo.video_height = sisbios_mode[sisfb_mode_idx].yres;
  588. ivideo.org_x = ivideo.org_y = 0;
  589. ivideo.video_linelength = ivideo.video_width * (ivideo.video_bpp >> 3);
  590. switch(ivideo.video_bpp) {
  591.          case 8:
  592.              ivideo.DstColor = 0x0000;
  593.      ivideo.SiS310_AccelDepth = 0x00000000;
  594. ivideo.video_cmap_len = 256;
  595.              break;
  596.          case 16:
  597.              ivideo.DstColor = 0x8000;
  598.              ivideo.SiS310_AccelDepth = 0x00010000;
  599. ivideo.video_cmap_len = 16;
  600.              break;
  601.          case 32:
  602.              ivideo.DstColor = 0xC000;
  603.      ivideo.SiS310_AccelDepth = 0x00020000;
  604. ivideo.video_cmap_len = 16;
  605.              break;
  606. default:
  607. ivideo.video_cmap_len = 16;
  608.         printk(KERN_ERR "sisfb: Unsupported accel depth %d", ivideo.video_bpp);
  609. break;
  610.      }
  611. }
  612. TWDEBUG("End of do_set_var");
  613. return 0;
  614. }
  615. /* ------ Internal functions only for 2.4 series ------- */
  616. #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33)
  617. static void sisfb_set_disp(int con, struct fb_var_screeninfo *var,
  618.                            struct fb_info *info)
  619. {
  620. struct fb_fix_screeninfo fix;
  621. long   flags;
  622. struct display *display;
  623. struct display_switch *sw;
  624. if(con >= 0)
  625. display = &fb_display[con];
  626. else
  627. display = &sis_disp;
  628. sisfb_get_fix(&fix, con, 0);
  629. #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,23)
  630. display->screen_base = ivideo.video_vbase;
  631. #endif
  632. display->visual = fix.visual;
  633. display->type = fix.type;
  634. display->type_aux = fix.type_aux;
  635. display->ypanstep = fix.ypanstep;
  636. display->ywrapstep = fix.ywrapstep;
  637. display->line_length = fix.line_length;
  638. display->next_line = fix.line_length;
  639. display->can_soft_blank = 0;
  640. display->inverse = sisfb_inverse;
  641. display->var = *var;
  642. save_flags(flags);
  643. switch (ivideo.video_bpp) {
  644. #ifdef FBCON_HAS_CFB8
  645.    case 8:
  646. #ifdef SISFBACCEL
  647. sw = sisfb_accel ? &fbcon_sis8 : &fbcon_cfb8;
  648. #else
  649. sw = &fbcon_cfb8;
  650. #endif
  651. break;
  652. #endif
  653. #ifdef FBCON_HAS_CFB16
  654.    case 15:
  655.    case 16:
  656. #ifdef SISFBACCEL
  657. sw = sisfb_accel ? &fbcon_sis16 : &fbcon_cfb16;
  658. #else
  659. sw = &fbcon_cfb16;
  660. #endif
  661. display->dispsw_data = sis_fbcon_cmap.cfb16;
  662. break;
  663. #endif
  664. #ifdef FBCON_HAS_CFB24
  665.    case 24:
  666. sw = &fbcon_cfb24;
  667. display->dispsw_data = sis_fbcon_cmap.cfb24;
  668. break;
  669. #endif
  670. #ifdef FBCON_HAS_CFB32
  671.    case 32:
  672. #ifdef SISFBACCEL
  673. sw = sisfb_accel ? &fbcon_sis32 : &fbcon_cfb32;
  674. #else
  675. sw = &fbcon_cfb32;
  676. #endif
  677. display->dispsw_data = sis_fbcon_cmap.cfb32;
  678. break;
  679. #endif
  680.    default:
  681. sw = &fbcon_dummy;
  682. return;
  683. }
  684. memcpy(&sisfb_sw, sw, sizeof(*sw));
  685. display->dispsw = &sisfb_sw;
  686. restore_flags(flags);
  687. #ifdef SISFB_PAN
  688.         if(sisfb_ypan) {
  689.        /* display->scrollmode = SCROLL_YPAN; - not defined */
  690. } else {
  691.     display->scrollmode = SCROLL_YREDRAW;
  692.     sisfb_sw.bmove = fbcon_redraw_bmove;
  693. }
  694. #else
  695. display->scrollmode = SCROLL_YREDRAW;
  696. sisfb_sw.bmove = fbcon_redraw_bmove;
  697. #endif
  698. }
  699. static void sisfb_do_install_cmap(int con, struct fb_info *info)
  700. {
  701. #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)
  702. if (con != info->currcon)
  703. return;
  704.         if (fb_display[con].cmap.len)
  705.                 fb_set_cmap(&fb_display[con].cmap, 1, info);
  706.         else
  707. fb_set_cmap(fb_default_cmap(ivideo.video_cmap_len), 1, info);
  708. #else
  709.         if (con != currcon)
  710. return;
  711.         if (fb_display[con].cmap.len)
  712. fb_set_cmap(&fb_display[con].cmap, 1, sisfb_setcolreg, info);
  713.         else
  714. fb_set_cmap(fb_default_cmap(ivideo.video_cmap_len), 1,
  715.     sisfb_setcolreg, info);
  716. #endif
  717. }
  718. #endif
  719. /* ------ functions for all series ------ */
  720. #ifdef SISFB_PAN
  721. static void sisfb_pan_var(struct fb_var_screeninfo *var)
  722. {
  723. unsigned int base;
  724. TWDEBUG("Inside pan_var");
  725.         base = var->yoffset * var->xres_virtual + var->xoffset;
  726.         /* calculate base bpp dep. */
  727.         switch(var->bits_per_pixel) {
  728.         case 16:
  729.          base >>= 1;
  730.          break;
  731. case 32:
  732.              break;
  733. case 8:
  734.         default:
  735.          base >>= 2;
  736.              break;
  737.         }
  738. outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
  739.         outSISIDXREG(SISCR, 0x0D, base & 0xFF);
  740. outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF);
  741. outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF);
  742. if(sisvga_engine == SIS_315_VGA) {
  743. setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
  744. }
  745.         if(ivideo.disp_state & DISPTYPE_DISP2) {
  746. orSISIDXREG(SISPART1, sisfb_CRT2_write_enable, 0x01);
  747.          outSISIDXREG(SISPART1, 0x06, (base & 0xFF));
  748.          outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF));
  749.          outSISIDXREG(SISPART1, 0x04, ((base >> 16) & 0xFF));
  750. if(sisvga_engine == SIS_315_VGA) {
  751. setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
  752. }
  753.         }
  754. TWDEBUG("End of pan_var");
  755. }
  756. #endif
  757. static void sisfb_crtc_to_var(struct fb_var_screeninfo *var)
  758. {
  759. u16 VRE, VBE, VRS, VBS, VDE, VT;
  760. u16 HRE, HBE, HRS, HBS, HDE, HT;
  761. u8  sr_data, cr_data, cr_data2, cr_data3, mr_data;
  762. int A, B, C, D, E, F, temp;
  763. double hrate, drate;
  764. TWDEBUG("Inside crtc_to_var");
  765. inSISIDXREG(SISSR, IND_SIS_COLOR_MODE, sr_data);
  766. if (sr_data & SIS_INTERLACED_MODE)
  767. var->vmode = FB_VMODE_INTERLACED;
  768. else
  769. var->vmode = FB_VMODE_NONINTERLACED;
  770. switch ((sr_data & 0x1C) >> 2) {
  771.    case SIS_8BPP_COLOR_MODE:
  772. var->bits_per_pixel = 8;
  773. break;
  774.    case SIS_16BPP_COLOR_MODE:
  775. var->bits_per_pixel = 16;
  776. break;
  777.    case SIS_32BPP_COLOR_MODE:
  778. var->bits_per_pixel = 32;
  779. break;
  780. }
  781. switch (var->bits_per_pixel) {
  782.    case 8:
  783. var->red.length = 6;
  784. var->green.length = 6;
  785. var->blue.length = 6;
  786. ivideo.video_cmap_len = 256;
  787. break;
  788.    case 16:
  789. var->red.offset = 11;
  790. var->red.length = 5;
  791. var->green.offset = 5;
  792. var->green.length = 6;
  793. var->blue.offset = 0;
  794. var->blue.length = 5;
  795. var->transp.offset = 0;
  796. var->transp.length = 0;
  797. ivideo.video_cmap_len = 16;
  798. break;
  799.    case 24:
  800. var->red.offset = 16;
  801. var->red.length = 8;
  802. var->green.offset = 8;
  803. var->green.length = 8;
  804. var->blue.offset = 0;
  805. var->blue.length = 8;
  806. var->transp.offset = 0;
  807. var->transp.length = 0;
  808. ivideo.video_cmap_len = 16;
  809. break;
  810.    case 32:
  811. var->red.offset = 16;
  812. var->red.length = 8;
  813. var->green.offset = 8;
  814. var->green.length = 8;
  815. var->blue.offset = 0;
  816. var->blue.length = 8;
  817. var->transp.offset = 24;
  818. var->transp.length = 8;
  819. ivideo.video_cmap_len = 16;
  820. break;
  821. }
  822. inSISIDXREG(SISSR, 0x0A, sr_data);
  823.         inSISIDXREG(SISCR, 0x06, cr_data);
  824.         inSISIDXREG(SISCR, 0x07, cr_data2);
  825. VT = (cr_data & 0xFF) | ((u16) (cr_data2 & 0x01) << 8) |
  826.      ((u16) (cr_data2 & 0x20) << 4) | ((u16) (sr_data & 0x01) << 10);
  827. A = VT + 2;
  828. inSISIDXREG(SISCR, 0x12, cr_data);
  829. VDE = (cr_data & 0xff) | ((u16) (cr_data2 & 0x02) << 7) |
  830.       ((u16) (cr_data2 & 0x40) << 3) | ((u16) (sr_data & 0x02) << 9);
  831. E = VDE + 1;
  832. inSISIDXREG(SISCR, 0x10, cr_data);
  833. VRS = (cr_data & 0xff) | ((u16) (cr_data2 & 0x04) << 6) |
  834.       ((u16) (cr_data2 & 0x80) << 2) | ((u16) (sr_data & 0x08) << 7);
  835. F = VRS + 1 - E;
  836. inSISIDXREG(SISCR, 0x15, cr_data);
  837. inSISIDXREG(SISCR, 0x09, cr_data3);
  838. VBS = (cr_data & 0xff) | ((u16) (cr_data2 & 0x08) << 5) |
  839.       ((u16) (cr_data3 & 0x20) << 4) | ((u16) (sr_data & 0x04) << 8);
  840. inSISIDXREG(SISCR, 0x16, cr_data);
  841. VBE = (cr_data & 0xff) | ((u16) (sr_data & 0x10) << 4);
  842. temp = VBE - ((E - 1) & 511);
  843. B = (temp > 0) ? temp : (temp + 512);
  844. inSISIDXREG(SISCR, 0x11, cr_data);
  845. VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
  846. temp = VRE - ((E + F - 1) & 31);
  847. C = (temp > 0) ? temp : (temp + 32);
  848. D = B - F - C;
  849.         var->yres = E;
  850. #ifndef SISFB_PAN
  851. var->yres_virtual = E;
  852. #endif
  853. /* TW: We have to report the physical dimension to the console! */
  854. if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
  855. var->yres <<= 1;
  856. #ifndef SISFB_PAN
  857. var->yres_virtual <<= 1;
  858. #endif
  859. }
  860. /* TW end */
  861. var->upper_margin = D;
  862. var->lower_margin = F;
  863. var->vsync_len = C;
  864. inSISIDXREG(SISSR, 0x0b, sr_data);
  865. inSISIDXREG(SISCR, 0x00, cr_data);
  866. HT = (cr_data & 0xff) | ((u16) (sr_data & 0x03) << 8);
  867. A = HT + 5;
  868. inSISIDXREG(SISCR, 0x01, cr_data);
  869. HDE = (cr_data & 0xff) | ((u16) (sr_data & 0x0C) << 6);
  870. E = HDE + 1;
  871. inSISIDXREG(SISCR, 0x04, cr_data);
  872. HRS = (cr_data & 0xff) | ((u16) (sr_data & 0xC0) << 2);
  873. F = HRS - E - 3;
  874. inSISIDXREG(SISCR, 0x02, cr_data);
  875. HBS = (cr_data & 0xff) | ((u16) (sr_data & 0x30) << 4);
  876. inSISIDXREG(SISSR, 0x0c, sr_data);
  877. inSISIDXREG(SISCR, 0x03, cr_data);
  878. inSISIDXREG(SISCR, 0x15, cr_data2);
  879. HBE = (cr_data & 0x1f) | ((u16) (cr_data2 & 0x80) >> 2) |
  880.       ((u16) (sr_data & 0x03) << 6);
  881. HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
  882. temp = HBE - ((E - 1) & 255);
  883. B = (temp > 0) ? temp : (temp + 256);
  884. temp = HRE - ((E + F + 3) & 63);
  885. C = (temp > 0) ? temp : (temp + 64);
  886. D = B - F - C;
  887. var->xres = var->xres_virtual = E * 8;
  888. var->left_margin = D * 8;
  889. var->right_margin = F * 8;
  890. var->hsync_len = C * 8;
  891. var->activate = FB_ACTIVATE_NOW;
  892. var->sync = 0;
  893. mr_data = inSISREG(SISMISCR);
  894. #if 0
  895. mr_data = vgarb(0x1C);
  896. #endif
  897. if (mr_data & 0x80)
  898. var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
  899. else
  900. var->sync |= FB_SYNC_VERT_HIGH_ACT;
  901. if (mr_data & 0x40)
  902. var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
  903. else
  904. var->sync |= FB_SYNC_HOR_HIGH_ACT;
  905. VT += 2;
  906. VT <<= 1;
  907. HT = (HT + 5) * 8;
  908. hrate = (double) ivideo.refresh_rate * (double) VT / 2;
  909. drate = hrate * HT;
  910. var->pixclock = (u32) (1E12 / drate);
  911. #ifdef SISFB_PAN
  912. if(sisfb_ypan) {
  913.     var->yres_virtual = ivideo.heapstart / (var->xres * (var->bits_per_pixel >> 3));
  914.     if(var->yres_virtual <= var->yres) {
  915.         var->yres_virtual = var->yres;
  916.     }
  917. } else
  918. #endif
  919.    var->yres_virtual = var->yres;
  920.         TWDEBUG("end of crtc_to_var");
  921. }
  922. /* ------------------ Public Routines -------------------------------- */
  923. /* -------- functions only for for 2.4 series ------- */
  924. #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33)
  925. static int sisfb_set_var(struct fb_var_screeninfo *var, int con,
  926.  struct fb_info *info)
  927. {
  928. #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)
  929. #define currcon info->currcon
  930. #endif
  931. int err;
  932. unsigned int cols, rows;
  933. fb_display[con].var.activate = FB_ACTIVATE_NOW;
  934.         if(sisfb_do_set_var(var, con == currcon, info)) {
  935. sisfb_crtc_to_var(var);
  936. return -EINVAL;
  937. }
  938. sisfb_crtc_to_var(var);
  939. sisfb_set_disp(con, var, info);
  940. if(info->changevar)
  941. (*info->changevar) (con);
  942. if((err = fb_alloc_cmap(&fb_display[con].cmap, 0, 0)))
  943. return err;
  944. sisfb_do_install_cmap(con, info);
  945. cols = sisbios_mode[sisfb_mode_idx].cols;
  946. rows = sisbios_mode[sisfb_mode_idx].rows;
  947. vc_resize_con(rows, cols, fb_display[con].conp->vc_num);
  948. return 0;
  949. #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)
  950. #undef currcon
  951. #endif
  952. }
  953. static int sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
  954.   struct fb_info *info)
  955. {
  956. #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)
  957. #define currcon info->currcon
  958. #endif
  959.         if (con == currcon)
  960. return fb_get_cmap(cmap, kspc, sis_getcolreg, info);
  961. else if (fb_display[con].cmap.len)
  962. fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
  963. else
  964. fb_copy_cmap(fb_default_cmap(ivideo.video_cmap_len), cmap, kspc ? 0 : 2);
  965. return 0;
  966. #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)
  967. #undef currcon
  968. #endif
  969. }
  970. static int sisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
  971.   struct fb_info *info)
  972. {
  973. int err;
  974. if (!fb_display[con].cmap.len) {
  975. err = fb_alloc_cmap(&fb_display[con].cmap, ivideo.video_cmap_len, 0);
  976. if (err)
  977. return err;
  978. }
  979. #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)
  980. if (con == info->currcon)
  981. return fb_set_cmap(cmap, kspc, info);
  982. #else
  983.         if (con == currcon)
  984. return fb_set_cmap(cmap, kspc, sisfb_setcolreg, info);
  985. #endif
  986. else
  987. fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
  988. return 0;
  989. }
  990. #endif
  991. /* -------- functions only for 2.5 series ------- */
  992. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)
  993. static int sisfb_set_par(struct fb_info *info)
  994. {
  995. int err;
  996. TWDEBUG("inside set_parn");
  997.         if((err = sisfb_do_set_var(&info->var, 1, info)))
  998. return err;
  999. sisfb_get_fix(&info->fix, info->currcon, info);
  1000. TWDEBUG("end of set_par");
  1001. return 0;
  1002. }
  1003. static int sisfb_check_var(struct fb_var_screeninfo *var,
  1004.                             struct fb_info *info)
  1005. {
  1006. unsigned int htotal =
  1007. var->left_margin + var->xres + var->right_margin +
  1008. var->hsync_len;
  1009. unsigned int vtotal = 0;
  1010. double drate = 0, hrate = 0;
  1011. int found_mode = 0;
  1012. int refresh_rate, search_idx;
  1013. TWDEBUG("Inside check_var");
  1014. if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
  1015. vtotal = var->upper_margin + var->yres + var->lower_margin +
  1016.          var->vsync_len;   /* TW */
  1017. vtotal <<= 1;
  1018. } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
  1019. vtotal = var->upper_margin + var->yres + var->lower_margin +
  1020.          var->vsync_len;   /* TW */
  1021. vtotal <<= 2;
  1022. } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
  1023. vtotal = var->upper_margin + (var->yres/2) + var->lower_margin +
  1024.          var->vsync_len;   /* TW */
  1025. /* var->yres <<= 1; */ /* TW */
  1026. } else  vtotal = var->upper_margin + var->yres + var->lower_margin +
  1027.          var->vsync_len;
  1028. if(!(htotal) || !(vtotal)) {
  1029. SISFAIL("sisfb: no valid timing data");
  1030. }
  1031. drate = 1E12 / var->pixclock;
  1032. hrate = drate / htotal;
  1033. refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
  1034. /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
  1035. if((var->xres == 1024) && (var->yres == 600)) refresh_rate = 60;
  1036. search_idx = 0;
  1037. while( (sisbios_mode[search_idx].mode_no != 0) &&
  1038.        (sisbios_mode[search_idx].xres <= var->xres) ) {
  1039. if( (sisbios_mode[search_idx].xres == var->xres) &&
  1040.     (sisbios_mode[search_idx].yres == var->yres) &&
  1041.     (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
  1042. found_mode = 1;
  1043. break;
  1044. }
  1045. search_idx++;
  1046. }
  1047. /* TW: TODO: Check the refresh rate */
  1048. if(found_mode)
  1049. search_idx = sisfb_validate_mode(search_idx);
  1050. else
  1051. SISFAIL("sisfb: no valid mode");
  1052.         if(sisfb_mode_idx < 0) {
  1053. SISFAIL("sisfb: mode not supported");
  1054. }
  1055. /* TW: Horiz-panning not supported */
  1056. if(var->xres != var->xres_virtual)
  1057. var->xres_virtual = var->xres;
  1058. if(!sisfb_ypan) {
  1059. if(var->yres != var->yres_virtual)
  1060. var->yres_virtual = var->yres;
  1061. } else {
  1062.    /* TW: Now patch yres_virtual if we use panning */
  1063.    /* *** May I do this? *** */
  1064.    var->yres_virtual = ivideo.heapstart / (var->xres * (var->bits_per_pixel >> 3));
  1065.     if(var->yres_virtual <= var->yres) {
  1066.      /* TW: Paranoia check */
  1067.         var->yres_virtual = var->yres;
  1068.     }
  1069. }
  1070. TWDEBUG("end of check_var");
  1071. return 0;
  1072. }
  1073. #endif
  1074. /* -------- functions for all series ------- */
  1075. static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
  1076.  struct fb_info *info)
  1077. {
  1078. TWDEBUG("inside get_fix");
  1079. memset(fix, 0, sizeof(struct fb_fix_screeninfo));
  1080. strcpy(fix->id, sis_fb_info.modename);
  1081. fix->smem_start = ivideo.video_base;
  1082.         /* TW */
  1083.         if((!sisfb_mem) || (sisfb_mem > (ivideo.video_size/1024))) {
  1084.     if (ivideo.video_size > 0x1000000) {
  1085.         fix->smem_len = 0xc00000;
  1086.     } else if (ivideo.video_size > 0x800000)
  1087. fix->smem_len = 0x800000;
  1088.     else
  1089. fix->smem_len = 0x400000;
  1090.         } else
  1091. fix->smem_len = sisfb_mem * 1024;
  1092. fix->type        = video_type;
  1093. fix->type_aux    = 0;
  1094. if(ivideo.video_bpp == 8)
  1095. fix->visual = FB_VISUAL_PSEUDOCOLOR;
  1096. else
  1097. fix->visual = FB_VISUAL_TRUECOLOR;
  1098. fix->xpanstep    = 0;
  1099. #ifdef SISFB_PAN
  1100.         if(sisfb_ypan)   fix->ypanstep = 1;
  1101. #endif
  1102. fix->ywrapstep   = 0;
  1103. fix->line_length = ivideo.video_linelength;
  1104. fix->mmio_start  = ivideo.mmio_base;
  1105. fix->mmio_len    = sisfb_mmio_size;
  1106. fix->accel       = FB_ACCEL_SIS_GLAMOUR;
  1107. fix->reserved[0] = ivideo.video_size & 0xFFFF;
  1108. fix->reserved[1] = (ivideo.video_size >> 16) & 0xFFFF;
  1109. fix->reserved[2] = sisfb_caps;
  1110. TWDEBUG("end of get_fix");
  1111. return 0;
  1112. }
  1113. static int sisfb_get_var(struct fb_var_screeninfo *var, int con,
  1114.  struct fb_info *info)
  1115. {
  1116. TWDEBUG("inside get_var");
  1117. if(con == -1)
  1118. memcpy(var, &default_var, sizeof(struct fb_var_screeninfo));
  1119. else
  1120. *var = fb_display[con].var;
  1121. /* JennyLee 2001126: for FSTN */
  1122. if (var->xres == 320 && var->yres == 480)
  1123. var->yres = 240;
  1124. /* ~JennyLee */
  1125. TWDEBUG("end of get_var");
  1126. return 0;
  1127. }
  1128. #ifdef SISFB_PAN
  1129. static int sisfb_pan_display(struct fb_var_screeninfo *var, int con,
  1130. struct fb_info* info)
  1131. {
  1132. #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)
  1133. #define currcon info->currcon
  1134. #endif
  1135. TWDEBUG("inside pan_display");
  1136. if (var->vmode & FB_VMODE_YWRAP) {
  1137. if (var->yoffset < 0 || var->yoffset >= fb_display[con].var.yres_virtual || var->xoffset)
  1138. return -EINVAL;
  1139. } else {
  1140. if (var->xoffset+fb_display[con].var.xres > fb_display[con].var.xres_virtual ||
  1141.     var->yoffset+fb_display[con].var.yres > fb_display[con].var.yres_virtual)
  1142. return -EINVAL;
  1143. }
  1144.         if (con == currcon)
  1145. sisfb_pan_var(var);
  1146. fb_display[con].var.xoffset = var->xoffset;
  1147. fb_display[con].var.yoffset = var->yoffset;
  1148. if (var->vmode & FB_VMODE_YWRAP)
  1149. fb_display[con].var.vmode |= FB_VMODE_YWRAP;
  1150. else
  1151. fb_display[con].var.vmode &= ~FB_VMODE_YWRAP;
  1152. TWDEBUG("end of pan_display");
  1153. return 0;
  1154. #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)
  1155. #undef currcon
  1156. #endif
  1157. }
  1158. #endif
  1159. static int sisfb_ioctl(struct inode *inode, struct file *file,
  1160.        unsigned int cmd, unsigned long arg, int con,
  1161.        struct fb_info *info)
  1162. {
  1163. TWDEBUG("inside ioctl");
  1164. switch (cmd) {
  1165.    case FBIO_ALLOC:
  1166. if (!capable(CAP_SYS_RAWIO))
  1167. return -EPERM;
  1168. sis_malloc((struct sis_memreq *) arg);
  1169. break;
  1170.    case FBIO_FREE:
  1171. if (!capable(CAP_SYS_RAWIO))
  1172. return -EPERM;
  1173. sis_free(*(unsigned long *) arg);
  1174. break;
  1175.    case FBIOGET_GLYPH:
  1176.                 sis_get_glyph(info,(SIS_GLYINFO *) arg);
  1177. break;
  1178.    case FBIOGET_HWCINFO:
  1179. {
  1180. unsigned long *hwc_offset = (unsigned long *) arg;
  1181. if (sisfb_caps & HW_CURSOR_CAP)
  1182. *hwc_offset = sisfb_hwcursor_vbase -
  1183.     (unsigned long) ivideo.video_vbase;
  1184. else
  1185. *hwc_offset = 0;
  1186. break;
  1187. }
  1188.    case FBIOPUT_MODEINFO:
  1189. {
  1190. struct mode_info *x = (struct mode_info *)arg;
  1191. ivideo.video_bpp        = x->bpp;
  1192. ivideo.video_width      = x->xres;
  1193. ivideo.video_height     = x->yres;
  1194. ivideo.video_vwidth     = x->v_xres;
  1195. ivideo.video_vheight    = x->v_yres;
  1196. ivideo.org_x            = x->org_x;
  1197. ivideo.org_y            = x->org_y;
  1198. ivideo.refresh_rate     = x->vrate;
  1199. ivideo.video_linelength = ivideo.video_width * (ivideo.video_bpp >> 3);
  1200. switch(ivideo.video_bpp) {
  1201.          case 8:
  1202.              ivideo.DstColor = 0x0000;
  1203.      ivideo.SiS310_AccelDepth = 0x00000000;
  1204. ivideo.video_cmap_len = 256;
  1205.              break;
  1206.          case 16:
  1207.              ivideo.DstColor = 0x8000;
  1208.              ivideo.SiS310_AccelDepth = 0x00010000;
  1209. ivideo.video_cmap_len = 16;
  1210.              break;
  1211.          case 32:
  1212.              ivideo.DstColor = 0xC000;
  1213.      ivideo.SiS310_AccelDepth = 0x00020000;
  1214. ivideo.video_cmap_len = 16;
  1215.              break;
  1216. default:
  1217. ivideo.video_cmap_len = 16;
  1218.           printk(KERN_ERR "sisfb: Unsupported accel depth %d", ivideo.video_bpp);
  1219. break;
  1220.      }
  1221. break;
  1222. }
  1223.    case FBIOGET_DISPINFO:
  1224. sis_dispinfo((struct ap_data *)arg);
  1225. break;
  1226.    case SISFB_GET_INFO:  /* TW: New for communication with X driver */
  1227.         {
  1228. sisfb_info *x = (sisfb_info *)arg;
  1229. x->sisfb_id = SISFB_ID;
  1230. x->sisfb_version = VER_MAJOR;
  1231. x->sisfb_revision = VER_MINOR;
  1232. x->sisfb_patchlevel = VER_LEVEL;
  1233. x->chip_id = ivideo.chip_id;
  1234. x->memory = ivideo.video_size / 1024;
  1235. x->heapstart = ivideo.heapstart / 1024;
  1236. x->fbvidmode = sisfb_mode_no;
  1237. x->sisfb_caps = sisfb_caps;
  1238. x->sisfb_tqlen = 512; /* yet unused */
  1239.                 break;
  1240. }
  1241.    default:
  1242. return -EINVAL;
  1243. }
  1244. TWDEBUG("end of ioctl");
  1245. return 0;
  1246. }
  1247. static int sisfb_mmap(struct fb_info *info, struct file *file,
  1248.       struct vm_area_struct *vma)
  1249. {
  1250. #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)
  1251. #define currcon info->currcon
  1252. #endif
  1253. struct fb_var_screeninfo var;
  1254. unsigned long start;
  1255. unsigned long off;
  1256. u32 len;
  1257. TWDEBUG("inside mmap");
  1258. if(vma->vm_pgoff > (~0UL >> PAGE_SHIFT))  return -EINVAL;
  1259. off = vma->vm_pgoff << PAGE_SHIFT;
  1260. start = (unsigned long) ivideo.video_base;
  1261. len = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.video_size);
  1262. if (off >= len) {
  1263. off -= len;
  1264. sisfb_get_var(&var, currcon, info);
  1265. if(var.accel_flags) return -EINVAL;
  1266. start = (unsigned long) ivideo.mmio_base;
  1267. len = PAGE_ALIGN((start & ~PAGE_MASK) + sisfb_mmio_size);
  1268. }
  1269. start &= PAGE_MASK;
  1270. if((vma->vm_end - vma->vm_start + off) > len) return -EINVAL;
  1271. off += start;
  1272. vma->vm_pgoff = off >> PAGE_SHIFT;
  1273. #if defined(__i386__) || defined(__x86_64__)
  1274. if (boot_cpu_data.x86 > 3)
  1275. pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
  1276. #endif
  1277. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
  1278. if (io_remap_page_range(vma->vm_start, off, vma->vm_end - vma->vm_start,
  1279. vma->vm_page_prot))
  1280. #else /* TW: 2.5 API */
  1281. if (io_remap_page_range(vma, vma->vm_start, off, vma->vm_end - vma->vm_start,
  1282. vma->vm_page_prot))
  1283. #endif
  1284. return -EAGAIN;
  1285.         TWDEBUG("end of mmap");
  1286. return 0;
  1287. #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)
  1288. #undef currcon
  1289. #endif
  1290. }
  1291. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)
  1292. static struct fb_ops sisfb_ops = {
  1293. .owner        = THIS_MODULE,
  1294. .fb_set_var   = gen_set_var,
  1295. .fb_get_cmap  = gen_get_cmap,
  1296. .fb_set_cmap  = gen_set_cmap,
  1297. .fb_check_var = sisfb_check_var,
  1298. .fb_set_par   = sisfb_set_par,
  1299.         .fb_setcolreg = sisfb_setcolreg,
  1300.         .fb_blank     = sisfb_blank,
  1301. #ifdef SISFB_PAN
  1302.         .fb_pan_display = sisfb_pan_display,
  1303. #endif
  1304.         .fb_fillrect  = fbcon_sis_fillrect,
  1305. .fb_copyarea  = fbcon_sis_copyarea,
  1306. .fb_imageblit = my_cfb_imageblit,
  1307. .fb_ioctl     = sisfb_ioctl,
  1308. .fb_mmap      = sisfb_mmap,
  1309. };
  1310. #endif
  1311. #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33)
  1312. static struct fb_ops sisfb_ops = {
  1313. owner: THIS_MODULE,
  1314. fb_get_fix: sisfb_get_fix,
  1315. fb_get_var: sisfb_get_var,
  1316. fb_set_var: sisfb_set_var,
  1317. fb_get_cmap: sisfb_get_cmap,
  1318. fb_set_cmap: sisfb_set_cmap,
  1319. #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)
  1320.         fb_setcolreg:   sisfb_setcolreg,
  1321.         fb_blank:       sisfb_blank,
  1322. #endif
  1323. #ifdef SISFB_PAN
  1324.         fb_pan_display: sisfb_pan_display,
  1325. #endif
  1326. fb_ioctl: sisfb_ioctl,
  1327. fb_mmap: sisfb_mmap,
  1328. };
  1329. #endif
  1330. /* ------------ Interface to the low level console driver -------------*/
  1331. #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33) /* --------- for 2.4 series --------- */
  1332. static int sisfb_update_var(int con, struct fb_info *info)
  1333. {
  1334. #ifdef SISFB_PAN
  1335.         sisfb_pan_var(&fb_display[con].var);
  1336. #endif
  1337. return 0;
  1338. }
  1339. static int sisfb_switch(int con, struct fb_info *info)
  1340. {
  1341. int cols, rows;
  1342. #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)
  1343. #define currcon info->currcon
  1344. #endif
  1345.         if(fb_display[currcon].cmap.len)
  1346. fb_get_cmap(&fb_display[currcon].cmap, 1, sis_getcolreg, info);
  1347. fb_display[con].var.activate = FB_ACTIVATE_NOW;
  1348. if(!memcmp(&fb_display[con].var, &fb_display[currcon].var,
  1349.                            sizeof(struct fb_var_screeninfo))) {
  1350. currcon = con;
  1351. return 1;
  1352. }
  1353. currcon = con;
  1354. sisfb_do_set_var(&fb_display[con].var, 1, info);
  1355. sisfb_set_disp(con, &fb_display[con].var, info);
  1356. sisfb_do_install_cmap(con, info);
  1357. cols = sisbios_mode[sisfb_mode_idx].cols;
  1358. rows = sisbios_mode[sisfb_mode_idx].rows;
  1359. vc_resize_con(rows, cols, fb_display[con].conp->vc_num);
  1360. sisfb_update_var(con, info);
  1361. return 1;
  1362. #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)
  1363. #undef currcon
  1364. #endif
  1365. }
  1366. static void sisfb_blank(int blank, struct fb_info *info)
  1367. {
  1368. u8 reg;
  1369. inSISIDXREG(SISCR, 0x17, reg);
  1370. if(blank > 0)
  1371. reg &= 0x7f;
  1372. else
  1373. reg |= 0x80;
  1374. outSISIDXREG(SISCR, 0x17, reg);
  1375. }
  1376. #endif
  1377. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34) /* ---------- for 2.5 series -------- */
  1378. static int sisfb_blank(int blank, struct fb_info *info)
  1379. {
  1380. u8 reg;
  1381. inSISIDXREG(SISCR, 0x17, reg);
  1382. if(blank > 0)
  1383. reg &= 0x7f;
  1384. else
  1385. reg |= 0x80;
  1386. outSISIDXREG(SISCR, 0x17, reg);
  1387.         return(0);
  1388. }
  1389. #endif
  1390. /* --------------- Chip-dependent Routines --------------------------- */
  1391. #ifdef CONFIG_FB_SIS_300 /* for SiS 300/630/540/730 */
  1392. static int sisfb_get_dram_size_300(void)
  1393. {
  1394. struct pci_dev *pdev = NULL;
  1395. int pdev_valid = 0;
  1396. u8  pci_data, reg;
  1397. u16 nbridge_id;
  1398. switch (ivideo.chip) {
  1399.    case SIS_540:
  1400. nbridge_id = PCI_DEVICE_ID_SI_540;
  1401. break;
  1402.    case SIS_630:
  1403. nbridge_id = PCI_DEVICE_ID_SI_630;
  1404. break;
  1405.    case SIS_730:
  1406. nbridge_id = PCI_DEVICE_ID_SI_730;
  1407. break;
  1408.    default:
  1409. nbridge_id = 0;
  1410. break;
  1411. }
  1412. if (nbridge_id == 0) {  /* 300 */
  1413.         inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE,reg);
  1414. ivideo.video_size =
  1415.         ((unsigned int) ((reg & SIS_DRAM_SIZE_MASK) + 1) << 20);
  1416. } else { /* 540, 630, 730 */
  1417. pci_for_each_dev(pdev) {
  1418. if ((pdev->vendor == PCI_VENDOR_ID_SI) 
  1419.        && (pdev->device == nbridge_id)) {
  1420. pci_read_config_byte(pdev, IND_BRI_DRAM_STATUS, &pci_data);
  1421. pci_data = (pci_data & BRI_DRAM_SIZE_MASK) >> 4;
  1422. ivideo.video_size = (unsigned int)(1 << (pci_data+21));
  1423. pdev_valid = 1;
  1424. reg = SIS_DATA_BUS_64 << 6;
  1425. switch (pci_data) {
  1426.    case BRI_DRAM_SIZE_2MB:
  1427. reg |= SIS_DRAM_SIZE_2MB;
  1428. break;
  1429.    case BRI_DRAM_SIZE_4MB:
  1430. reg |= SIS_DRAM_SIZE_4MB;
  1431. break;
  1432.    case BRI_DRAM_SIZE_8MB:
  1433. reg |= SIS_DRAM_SIZE_8MB;
  1434. break;
  1435.    case BRI_DRAM_SIZE_16MB:
  1436. reg |= SIS_DRAM_SIZE_16MB;
  1437. break;
  1438.    case BRI_DRAM_SIZE_32MB:
  1439. reg |= SIS_DRAM_SIZE_32MB;
  1440. break;
  1441.    case BRI_DRAM_SIZE_64MB:
  1442. reg |= SIS_DRAM_SIZE_64MB;
  1443. break;
  1444. }
  1445. outSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
  1446. break;
  1447. }  
  1448. }   
  1449. if (!pdev_valid)  return -1;
  1450. }
  1451. return 0;
  1452. }
  1453. static void sisfb_detect_VB_connect_300()
  1454. {
  1455. u8 sr16, sr17, cr32, temp;
  1456. ivideo.TV_plug = ivideo.TV_type = 0;
  1457.         switch(ivideo.hasVB) {
  1458.   case HASVB_LVDS_CHRONTEL:
  1459.   case HASVB_CHRONTEL:
  1460.      SiS_SenseCh();
  1461.      break;
  1462.   case HASVB_301:
  1463.   case HASVB_302:
  1464.      SiS_Sense30x();
  1465.      break;
  1466. }
  1467. inSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_17, sr17);
  1468.         inSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR32, cr32);
  1469. if ((sr17 & 0x0F) && (ivideo.chip != SIS_300)) {
  1470. if ((sr17 & 0x01) && !sisfb_crt1off)
  1471. sisfb_crt1off = 0;
  1472. else {
  1473. if (sr17 & 0x0E)
  1474. sisfb_crt1off = 1;
  1475. else
  1476. sisfb_crt1off = 0;
  1477. }
  1478. if (sisfb_crt2type != -1)
  1479. /* TW: override detected CRT2 type */
  1480. ivideo.disp_state = sisfb_crt2type;
  1481. else if (sr17 & 0x08 )
  1482. ivideo.disp_state = DISPTYPE_CRT2;
  1483. else if (sr17 & 0x02)
  1484. ivideo.disp_state = DISPTYPE_LCD;
  1485. else if (sr17 & 0x04)
  1486. ivideo.disp_state = DISPTYPE_TV;
  1487. else
  1488. ivideo.disp_state = 0;
  1489. if(sisfb_tvplug != -1)
  1490. /* PR/TW: override detected TV type */
  1491. ivideo.TV_plug = sisfb_tvplug;
  1492. else if (sr17 & 0x20)
  1493. ivideo.TV_plug = TVPLUG_SVIDEO;
  1494. else if (sr17 & 0x10)
  1495. ivideo.TV_plug = TVPLUG_COMPOSITE;
  1496. inSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_16, sr16);
  1497. if (sr16 & 0x20)
  1498. ivideo.TV_type = TVMODE_PAL;
  1499. else
  1500. ivideo.TV_type = TVMODE_NTSC;
  1501. } else {
  1502. if ((cr32 & SIS_CRT1) && !sisfb_crt1off)
  1503. sisfb_crt1off = 0;
  1504. else {
  1505. if (cr32 & 0x5F)
  1506. sisfb_crt1off = 1;
  1507. else
  1508. sisfb_crt1off = 0;
  1509. }
  1510. if (sisfb_crt2type != -1)
  1511. /* TW: override detected CRT2 type */
  1512. ivideo.disp_state = sisfb_crt2type;
  1513. else if (cr32 & SIS_VB_CRT2)
  1514. ivideo.disp_state = DISPTYPE_CRT2;
  1515. else if (cr32 & SIS_VB_LCD)
  1516. ivideo.disp_state = DISPTYPE_LCD;
  1517. else if (cr32 & SIS_VB_TV)
  1518. ivideo.disp_state = DISPTYPE_TV;
  1519. else
  1520. ivideo.disp_state = 0;
  1521. /* TW: Detect TV plug & type */
  1522. if(sisfb_tvplug != -1)
  1523. /* PR/TW: override with option */
  1524.         ivideo.TV_plug = sisfb_tvplug;
  1525. #ifdef oldHV
  1526. else if (cr32 & SIS_VB_HIVISION) {
  1527. ivideo.TV_type = TVMODE_HIVISION;
  1528. ivideo.TV_plug = TVPLUG_SVIDEO;
  1529. }
  1530. #endif
  1531. else if (cr32 & SIS_VB_SVIDEO)
  1532. ivideo.TV_plug = TVPLUG_SVIDEO;
  1533. else if (cr32 & SIS_VB_COMPOSITE)
  1534. ivideo.TV_plug = TVPLUG_COMPOSITE;
  1535. else if (cr32 & SIS_VB_SCART)
  1536. ivideo.TV_plug = TVPLUG_SCART;
  1537. if (ivideo.TV_type == 0) {
  1538.         inSISIDXREG(SISSR, IND_SIS_POWER_ON_TRAP, temp);
  1539. if (temp & 0x01)
  1540. ivideo.TV_type = TVMODE_PAL;
  1541. else
  1542. ivideo.TV_type = TVMODE_NTSC;
  1543. }
  1544. }
  1545. /* TW: Copy forceCRT1 option to CRT1off if option is given */
  1546.      if (sisfb_forcecrt1 != -1) {
  1547.      if(sisfb_forcecrt1) sisfb_crt1off = 0;
  1548. else                sisfb_crt1off = 1;
  1549.      }
  1550. }
  1551. static void sisfb_get_VB_type_300(void)
  1552. {
  1553. u8 reg;
  1554. if(ivideo.chip != SIS_300) {
  1555. if(!sisfb_has_VB_300()) {
  1556.         inSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR37, reg);
  1557. switch ((reg & SIS_EXTERNAL_CHIP_MASK) >> 1) {
  1558.    case SIS_EXTERNAL_CHIP_SIS301:
  1559. ivideo.hasVB = HASVB_301;
  1560. break;
  1561.    case SIS_EXTERNAL_CHIP_LVDS:
  1562. ivideo.hasVB = HASVB_LVDS;
  1563. break;
  1564.    case SIS_EXTERNAL_CHIP_TRUMPION:
  1565. ivideo.hasVB = HASVB_TRUMPION;
  1566. break;
  1567.    case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
  1568. ivideo.hasVB = HASVB_LVDS_CHRONTEL;
  1569. break;
  1570.    case SIS_EXTERNAL_CHIP_CHRONTEL:
  1571. ivideo.hasVB = HASVB_CHRONTEL;
  1572. break;
  1573.    default:
  1574. break;
  1575. }
  1576. }
  1577. } else {
  1578. sisfb_has_VB_300();
  1579. }
  1580. }
  1581. static int sisfb_has_VB_300(void)
  1582. {
  1583. u8 vb_chipid;
  1584. inSISIDXREG(SISPART4, 0x00, vb_chipid);
  1585. switch (vb_chipid) {
  1586.    case 0x01:
  1587. ivideo.hasVB = HASVB_301;
  1588. break;
  1589.    case 0x02:
  1590. ivideo.hasVB = HASVB_302;
  1591. break;
  1592.    case 0x03:
  1593. ivideo.hasVB = HASVB_303;
  1594. break;
  1595.    default:
  1596. ivideo.hasVB = HASVB_NONE;
  1597. return FALSE;
  1598. }
  1599. return TRUE;
  1600. }
  1601. #endif  /* CONFIG_FB_SIS_300 */
  1602. #ifdef CONFIG_FB_SIS_315    /* for SiS 315/550/650/740 */
  1603. static int sisfb_get_dram_size_315(void)
  1604. {
  1605. struct pci_dev *pdev = NULL;
  1606. int pdev_valid = 0;
  1607. u8  pci_data;
  1608. u8  reg = 0;
  1609. if (ivideo.chip == SIS_550 || ivideo.chip == SIS_650) {
  1610. #ifdef LINUXBIOS
  1611. pci_for_each_dev(pdev) {
  1612. if ( (pdev->vendor == PCI_VENDOR_ID_SI)
  1613. && ( (pdev->device == PCI_DEVICE_ID_SI_550) ||
  1614.      (pdev->device == PCI_DEVICE_ID_SI_650))) {
  1615. pci_read_config_byte(pdev, IND_BRI_DRAM_STATUS,
  1616.                      &pci_data);
  1617. pci_data = (pci_data & BRI_DRAM_SIZE_MASK) >> 4;
  1618. ivideo.video_size = (unsigned int)(1 << (pci_data + 21));
  1619. pdev_valid = 1;
  1620. /* TW: Initialize SR14 "by hand" */
  1621. inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
  1622. reg &= 0xC0;
  1623. switch (pci_data) {
  1624.    case BRI_DRAM_SIZE_4MB:
  1625. reg |= SIS550_DRAM_SIZE_4MB;
  1626. break;
  1627.    case BRI_DRAM_SIZE_8MB:
  1628. reg |= SIS550_DRAM_SIZE_8MB;
  1629. break;
  1630.    case BRI_DRAM_SIZE_16MB:
  1631. reg |= SIS550_DRAM_SIZE_16MB;
  1632. break;
  1633.    case BRI_DRAM_SIZE_32MB:
  1634. reg |= SIS550_DRAM_SIZE_32MB;
  1635. break;
  1636.    case BRI_DRAM_SIZE_64MB:
  1637. reg |= SIS550_DRAM_SIZE_64MB;
  1638. break;
  1639. }
  1640.         /* TODO: set Dual channel and bus width bits here */
  1641. outSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
  1642. break;
  1643. }  
  1644. }
  1645. if (!pdev_valid)  return -1;
  1646. #else
  1647.                 inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
  1648. switch (reg & SIS550_DRAM_SIZE_MASK) {
  1649.    case SIS550_DRAM_SIZE_4MB:
  1650. ivideo.video_size = 0x400000;   break;
  1651.    case SIS550_DRAM_SIZE_8MB:
  1652. ivideo.video_size = 0x800000;   break;
  1653.    case SIS550_DRAM_SIZE_16MB:
  1654. ivideo.video_size = 0x1000000;  break;
  1655.    case SIS550_DRAM_SIZE_24MB:
  1656. ivideo.video_size = 0x1800000;  break;
  1657.    case SIS550_DRAM_SIZE_32MB:
  1658. ivideo.video_size = 0x2000000; break;
  1659.    case SIS550_DRAM_SIZE_64MB:
  1660. ivideo.video_size = 0x4000000; break;
  1661.    case SIS550_DRAM_SIZE_96MB:
  1662. ivideo.video_size = 0x6000000; break;
  1663.    case SIS550_DRAM_SIZE_128MB:
  1664. ivideo.video_size = 0x8000000; break;
  1665.    case SIS550_DRAM_SIZE_256MB:
  1666. ivideo.video_size = 0x10000000; break;
  1667.    default:
  1668.         /* TW: Some 550 BIOSes don't seem to initialize SR14 correctly (if at all),
  1669.  *     do it the hard way ourselves in this case. Unfortunately, we don't
  1670.  *     support 24, 48, 96 and other "odd" amounts here.
  1671.  */
  1672.         printk(KERN_INFO
  1673.        "sisfb: Warning: Could not determine memory size, "
  1674.        "now reading from PCI confign");
  1675. pdev_valid = 0;
  1676. pci_for_each_dev(pdev) {
  1677.    if ( (pdev->vendor == PCI_VENDOR_ID_SI)
  1678.          && (pdev->device == PCI_DEVICE_ID_SI_550) ) {
  1679. pci_read_config_byte(pdev, IND_BRI_DRAM_STATUS,
  1680.                      &pci_data);
  1681. pci_data = (pci_data & BRI_DRAM_SIZE_MASK) >> 4;
  1682. ivideo.video_size = (unsigned int)(1 << (pci_data+21));
  1683. pdev_valid = 1;
  1684. /* TW: Initialize SR14=IND_SIS_DRAM_SIZE */
  1685. inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
  1686. reg &= 0xC0;
  1687. switch (pci_data) {
  1688.    case BRI_DRAM_SIZE_4MB:
  1689. reg |= SIS550_DRAM_SIZE_4MB;  break;
  1690.    case BRI_DRAM_SIZE_8MB:
  1691. reg |= SIS550_DRAM_SIZE_8MB;  break;
  1692.    case BRI_DRAM_SIZE_16MB:
  1693. reg |= SIS550_DRAM_SIZE_16MB; break;
  1694.    case BRI_DRAM_SIZE_32MB:
  1695. reg |= SIS550_DRAM_SIZE_32MB; break;
  1696.    case BRI_DRAM_SIZE_64MB:
  1697. reg |= SIS550_DRAM_SIZE_64MB; break;
  1698.    default:
  1699.     printk(KERN_INFO "sisfb: Unable to determine memory size, giving up.n");
  1700. return -1;
  1701. }
  1702. outSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
  1703.    }
  1704. }
  1705. if (!pdev_valid) {
  1706. printk(KERN_INFO "sisfb: Total confusion - No SiS PCI VGA device found?!n");
  1707. return -1;
  1708. }
  1709. return 0;
  1710. }
  1711. #endif
  1712. return 0;
  1713. } else { /* 315 */
  1714.         inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
  1715. switch ((reg & SIS315_DRAM_SIZE_MASK) >> 4) {
  1716.    case SIS315_DRAM_SIZE_2MB:
  1717. ivideo.video_size = 0x200000;
  1718. break;
  1719.    case SIS315_DRAM_SIZE_4MB:
  1720. ivideo.video_size = 0x400000;
  1721. break;
  1722.    case SIS315_DRAM_SIZE_8MB:
  1723. ivideo.video_size = 0x800000;
  1724. break;
  1725.    case SIS315_DRAM_SIZE_16MB:
  1726. ivideo.video_size = 0x1000000;
  1727. break;
  1728.    case SIS315_DRAM_SIZE_32MB:
  1729. ivideo.video_size = 0x2000000;
  1730. break;
  1731.    case SIS315_DRAM_SIZE_64MB:
  1732. ivideo.video_size = 0x4000000;
  1733. break;
  1734.    case SIS315_DRAM_SIZE_128MB:
  1735. ivideo.video_size = 0x8000000;
  1736. break;
  1737.    default:
  1738. return -1;
  1739. }
  1740. }
  1741. reg &= SIS315_DUAL_CHANNEL_MASK;
  1742. reg >>= 2;
  1743. switch (reg) {
  1744.    case SIS315_SINGLE_CHANNEL_2_RANK:
  1745. ivideo.video_size <<= 1;
  1746. break;
  1747.    case SIS315_DUAL_CHANNEL_1_RANK:
  1748. ivideo.video_size <<= 1;
  1749. break;
  1750.    case SIS315_ASYM_DDR: /* TW: DDR asymentric */
  1751. ivideo.video_size += (ivideo.video_size/2);
  1752. break;
  1753. }
  1754. return 0;
  1755. }
  1756. static void sisfb_detect_VB_connect_315(void)
  1757. {
  1758. u8 cr32, temp=0;
  1759. ivideo.TV_plug = ivideo.TV_type = 0;
  1760.         switch(ivideo.hasVB) {
  1761.   case HASVB_LVDS_CHRONTEL:
  1762.   case HASVB_CHRONTEL:
  1763.      SiS_SenseCh();
  1764.      break;
  1765.   case HASVB_301:
  1766.   case HASVB_302:
  1767.      SiS_Sense30x();
  1768.      break;
  1769. }
  1770. inSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR32, cr32);
  1771. if ((cr32 & SIS_CRT1) && !sisfb_crt1off)
  1772. sisfb_crt1off = 0;
  1773. else {
  1774. if (cr32 & 0x5F)   
  1775. sisfb_crt1off = 1;
  1776. else
  1777. sisfb_crt1off = 0;
  1778. }
  1779. if (sisfb_crt2type != -1)
  1780. /* TW: Override with option */
  1781. ivideo.disp_state = sisfb_crt2type;
  1782. else if (cr32 & SIS_VB_CRT2)
  1783. ivideo.disp_state = DISPTYPE_CRT2;
  1784. else if (cr32 & SIS_VB_LCD)
  1785. ivideo.disp_state = DISPTYPE_LCD;
  1786. else if (cr32 & SIS_VB_TV)
  1787. ivideo.disp_state = DISPTYPE_TV;
  1788. else
  1789. ivideo.disp_state = 0;
  1790. if(sisfb_tvplug != -1)
  1791. /* PR/TW: Override with option */
  1792.         ivideo.TV_plug = sisfb_tvplug;
  1793. #ifdef oldHV
  1794. else if (cr32 & SIS_VB_HIVISION) {
  1795. ivideo.TV_type = TVMODE_HIVISION;
  1796. ivideo.TV_plug = TVPLUG_SVIDEO;
  1797. }
  1798. #endif
  1799. else if (cr32 & SIS_VB_SVIDEO)
  1800. ivideo.TV_plug = TVPLUG_SVIDEO;
  1801. else if (cr32 & SIS_VB_COMPOSITE)
  1802. ivideo.TV_plug = TVPLUG_COMPOSITE;
  1803. else if (cr32 & SIS_VB_SCART)
  1804. ivideo.TV_plug = TVPLUG_SCART;
  1805. if(ivideo.TV_type == 0) {
  1806.     /* TW: PAL/NTSC changed for 650 */
  1807.     if(ivideo.chip <= SIS_315PRO) {
  1808.                 inSISIDXREG(SISCR, 0x38, temp);
  1809. if(temp & 0x10)
  1810. ivideo.TV_type = TVMODE_PAL;
  1811. else
  1812. ivideo.TV_type = TVMODE_NTSC;
  1813.     } else {
  1814.         inSISIDXREG(SISCR, 0x79, temp);
  1815. if(temp & 0x20)
  1816. ivideo.TV_type = TVMODE_PAL;
  1817. else
  1818. ivideo.TV_type = TVMODE_NTSC;
  1819.     }
  1820. }
  1821. /* TW: Copy forceCRT1 option to CRT1off if option is given */
  1822.      if (sisfb_forcecrt1 != -1) {
  1823.      if (sisfb_forcecrt1) sisfb_crt1off = 0;
  1824. else                 sisfb_crt1off = 1;
  1825.      }
  1826. }
  1827. static void sisfb_get_VB_type_315(void)
  1828. {
  1829. u8 reg;
  1830. if (!sisfb_has_VB_315()) {
  1831.         inSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR37, reg);
  1832. /* TW: CR37 changed on 310/325 series */
  1833. switch ((reg & SIS_EXTERNAL_CHIP_MASK) >> 1) {
  1834.    case SIS_EXTERNAL_CHIP_SIS301:
  1835. ivideo.hasVB = HASVB_301;
  1836. break;
  1837.    case SIS310_EXTERNAL_CHIP_LVDS:
  1838. ivideo.hasVB = HASVB_LVDS;
  1839. break;
  1840.    case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
  1841. ivideo.hasVB = HASVB_LVDS_CHRONTEL;
  1842. break;
  1843.    default:
  1844. break;
  1845. }
  1846. }
  1847. }
  1848. static int sisfb_has_VB_315(void)
  1849. {
  1850. u8 vb_chipid;
  1851. inSISIDXREG(SISPART4, 0x00, vb_chipid);
  1852. switch (vb_chipid) {
  1853.    case 0x01:
  1854. ivideo.hasVB = HASVB_301;
  1855. break;
  1856.    case 0x02:
  1857. ivideo.hasVB = HASVB_302;
  1858. break;
  1859.    case 0x03:
  1860. ivideo.hasVB = HASVB_303;
  1861. break;
  1862.    default:
  1863. ivideo.hasVB = HASVB_NONE;
  1864. return FALSE;
  1865. }
  1866. return TRUE;
  1867. }
  1868. #endif   /* CONFIG_FB_SIS_315 */
  1869. /* -------------- Sensing routines --------------- */
  1870. /* TW: Determine and detect attached devices on SiS30x */
  1871. int
  1872. SISDoSense(int tempbl, int tempbh, int tempcl, int tempch)
  1873. {
  1874.     int temp,i;
  1875.     outSISIDXREG(SISPART4,0x11,tempbl);
  1876.     temp = tempbh | tempcl;
  1877.     setSISIDXREG(SISPART4,0x10,0xe0,temp);
  1878.     for(i=0; i<10; i++) SiS_LongWait(&SiS_Pr);
  1879.     tempch &= 0x7f;
  1880.     inSISIDXREG(SISPART4,0x03,temp);
  1881.     temp ^= 0x0e;
  1882.     temp &= tempch;
  1883.     return(temp);
  1884. }
  1885. void
  1886. SiS_Sense30x(void)
  1887. {
  1888.   u8 backupP4_0d;
  1889.   u8 testsvhs_tempbl, testsvhs_tempbh;
  1890.   u8 testsvhs_tempcl, testsvhs_tempch;
  1891.   u8 testcvbs_tempbl, testcvbs_tempbh;
  1892.   u8 testcvbs_tempcl, testcvbs_tempch;
  1893.   int myflag, result;
  1894.   inSISIDXREG(SISPART4,0x0d,backupP4_0d);
  1895.   outSISIDXREG(SISPART4,0x0d,(backupP4_0d | 0x04));
  1896.   if(sisvga_engine == SIS_300_VGA) {
  1897.         testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9;
  1898. testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3;
  1899. if((sishw_ext.ujVBChipID != VB_CHIP_301) &&
  1900.    (sishw_ext.ujVBChipID != VB_CHIP_302) ) {
  1901.    testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b;
  1902.    testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74;
  1903. }
  1904. inSISIDXREG(SISPART4,0x01,myflag);
  1905. if(myflag & 0x04) {
  1906.    testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xdd;
  1907.    testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xee;
  1908. }
  1909. testsvhs_tempch = 0x06; testsvhs_tempcl = 0x04;
  1910. testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04;
  1911.   } else if((ivideo.chip == SIS_315) ||
  1912.          (ivideo.chip == SIS_315H) ||
  1913.     (ivideo.chip == SIS_315PRO)) {
  1914.         testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9;
  1915. testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3;
  1916. if((sishw_ext.ujVBChipID != VB_CHIP_301) &&
  1917.    (sishw_ext.ujVBChipID != VB_CHIP_302) ) {
  1918.       testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b;
  1919.       testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74;
  1920. }
  1921. inSISIDXREG(SISPART4,0x01,myflag);
  1922. if(myflag & 0x04) {
  1923.    testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xdd;
  1924.    testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xee;
  1925. }
  1926. testsvhs_tempch = 0x06; testsvhs_tempcl = 0x04;
  1927. testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04;
  1928.     } else {
  1929.         testsvhs_tempbh = 0x02; testsvhs_tempbl = 0x00;
  1930. testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x00;
  1931. testsvhs_tempch = 0x04; testsvhs_tempcl = 0x08;
  1932. testcvbs_tempch = 0x08; testcvbs_tempcl = 0x08;
  1933.     }
  1934.     result = SISDoSense(testsvhs_tempbl, testsvhs_tempbh,
  1935.                         testsvhs_tempcl, testsvhs_tempch);
  1936.     if(result) {
  1937.         printk(KERN_INFO "sisfb: Detected TV connected to SVHS outputn");
  1938.         /* TW: So we can be sure that there IS a SVHS output */
  1939. ivideo.TV_plug = TVPLUG_SVIDEO;
  1940. orSISIDXREG(SISCR, 0x32, 0x02);
  1941.     }
  1942.     if(!result) {
  1943.         result = SISDoSense(testcvbs_tempbl, testcvbs_tempbh,
  1944.                     testcvbs_tempcl, testcvbs_tempch);
  1945. if(result) {
  1946.     printk(KERN_INFO "sisfb: Detected TV connected to CVBS outputn");
  1947.     /* TW: So we can be sure that there IS a CVBS output */
  1948.     ivideo.TV_plug = TVPLUG_COMPOSITE;
  1949.     orSISIDXREG(SISCR, 0x32, 0x01);
  1950. }
  1951.     }
  1952.     SISDoSense(0, 0, 0, 0);
  1953.     outSISIDXREG(SISPART4,0x0d,backupP4_0d);
  1954. }
  1955. /* TW: Determine and detect attached TV's on Chrontel */
  1956. void
  1957. SiS_SenseCh(void)
  1958. {
  1959.    u8 temp1;
  1960. #ifdef CONFIG_FB_SIS_315
  1961.    u8 temp2;
  1962. #endif
  1963.    if(ivideo.chip < SIS_315H) {
  1964. #ifdef CONFIG_FB_SIS_300
  1965.        SiS_Pr.SiS_IF_DEF_CH70xx = 1; /* TW: Chrontel 7005 */
  1966.        temp1 = SiS_GetCH700x(&SiS_Pr, 0x25);
  1967.        if ((temp1 >= 50) && (temp1 <= 100)) {
  1968.    /* TW: Read power status */
  1969.    temp1 = SiS_GetCH700x(&SiS_Pr, 0x0e);
  1970.    if((temp1 & 0x03) != 0x03) {
  1971.               /* TW: Power all outputs */
  1972. SiS_SetCH70xxANDOR(&SiS_Pr, 0x030E,0xF8);
  1973.    }
  1974.    /* TW: Sense connected TV devices */
  1975.    SiS_SetCH700x(&SiS_Pr, 0x0110);
  1976.    SiS_SetCH700x(&SiS_Pr, 0x0010);
  1977.    temp1 = SiS_GetCH700x(&SiS_Pr, 0x10);
  1978.    if(!(temp1 & 0x08)) {
  1979. printk(KERN_INFO
  1980.    "sisfb: Chrontel: Detected TV connected to SVHS outputn");
  1981. /* TW: So we can be sure that there IS a SVHS output */
  1982. ivideo.TV_plug = TVPLUG_SVIDEO;
  1983. orSISIDXREG(SISCR, 0x32, 0x02);
  1984.    } else if (!(temp1 & 0x02)) {
  1985. printk(KERN_INFO
  1986.    "sisfb: Chrontel: Detected TV connected to CVBS outputn");
  1987. /* TW: So we can be sure that there IS a CVBS output */
  1988. ivideo.TV_plug = TVPLUG_COMPOSITE;
  1989. orSISIDXREG(SISCR, 0x32, 0x01);
  1990.    } else {
  1991.   SiS_SetCH70xxANDOR(&SiS_Pr, 0x010E,0xF8);
  1992.    }
  1993.        } else if(temp1 == 0) {
  1994.   SiS_SetCH70xxANDOR(&SiS_Pr, 0x010E,0xF8);
  1995.        }
  1996. #endif
  1997.    } else {
  1998. #ifdef CONFIG_FB_SIS_315
  1999. SiS_Pr.SiS_IF_DEF_CH70xx = 2; /* TW: Chrontel 7019 */
  2000.         temp1 = SiS_GetCH701x(&SiS_Pr, 0x49);
  2001. SiS_SetCH701x(&SiS_Pr, 0x2049);
  2002. SiS_DDC2Delay(&SiS_Pr, 0x96);
  2003. temp2 = SiS_GetCH701x(&SiS_Pr, 0x20);
  2004. temp2 |= 0x01;
  2005. SiS_SetCH701x(&SiS_Pr, (temp2 << 8) | 0x20);
  2006. SiS_DDC2Delay(&SiS_Pr, 0x96);
  2007. temp2 ^= 0x01;
  2008. SiS_SetCH701x(&SiS_Pr, (temp2 << 8) | 0x20);
  2009. SiS_DDC2Delay(&SiS_Pr, 0x96);
  2010. temp2 = SiS_GetCH701x(&SiS_Pr, 0x20);
  2011. SiS_SetCH701x(&SiS_Pr, (temp1 << 8) | 0x49);
  2012.         temp1 = 0;
  2013. if(temp2 & 0x02) temp1 |= 0x01;
  2014. if(temp2 & 0x10) temp1 |= 0x01;
  2015. if(temp2 & 0x04) temp1 |= 0x02;
  2016. if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04;
  2017. switch(temp1) {
  2018. case 0x01:
  2019.      printk(KERN_INFO
  2020. "sisfb: Chrontel: Detected TV connected to CVBS outputn");
  2021.      ivideo.TV_plug = TVPLUG_COMPOSITE;
  2022.      orSISIDXREG(SISCR, 0x32, 0x01);
  2023.              break;
  2024. case 0x02:
  2025.      printk(KERN_INFO
  2026. "sisfb: Chrontel: Detected TV connected to SVHS outputn");
  2027.      ivideo.TV_plug = TVPLUG_SVIDEO;
  2028.      orSISIDXREG(SISCR, 0x32, 0x02);
  2029.              break;
  2030. case 0x04:
  2031.      /* TW: This should not happen */
  2032.      printk(KERN_INFO
  2033. "sisfb: Chrontel: Detected TV connected to SCART output!?n");
  2034.              break;
  2035. }
  2036. #endif
  2037.    }
  2038. }
  2039. /* --------------------- Heap Routines ------------------------------- */
  2040. static int sisfb_heap_init(void)
  2041. {
  2042. SIS_OH *poh;
  2043. u8 temp=0;
  2044. #ifdef CONFIG_FB_SIS_315
  2045. int            agp_enabled = 1;
  2046. u32            agp_size;
  2047. unsigned long *cmdq_baseport = 0;
  2048. unsigned long *read_port = 0;
  2049. unsigned long *write_port = 0;
  2050. SIS_CMDTYPE    cmd_type;
  2051. #ifndef AGPOFF
  2052. agp_kern_info  *agp_info;
  2053. agp_memory     *agp;
  2054. u32            agp_phys;
  2055. #endif
  2056. #endif
  2057. /* TW: The heap start is either set manually using the "mem" parameter, or
  2058.  *     defaults as follows:
  2059.  *     -) If more than 16MB videoRAM available, let our heap start at 12MB.
  2060.  *     -) If more than  8MB videoRAM available, let our heap start at  8MB.
  2061.  *     -) If 4MB or less is available, let it start at 4MB.
  2062.  *     This is for avoiding a clash with X driver which uses the beginning
  2063.  *     of the videoRAM. To limit size of X framebuffer, use Option MaxXFBMem
  2064.  *     in XF86Config-4.
  2065.  *     The heap start can also be specified by parameter "mem" when starting the sisfb
  2066.  *     driver. sisfb mem=1024 lets heap starts at 1MB, etc.
  2067.  */
  2068.      if ((!sisfb_mem) || (sisfb_mem > (ivideo.video_size/1024))) {
  2069.         if (ivideo.video_size > 0x1000000) {
  2070.         ivideo.heapstart = 0xc00000;
  2071. } else if (ivideo.video_size > 0x800000) {
  2072.         ivideo.heapstart = 0x800000;
  2073. } else {
  2074. ivideo.heapstart = 0x400000;
  2075. }
  2076.      } else {
  2077.            ivideo.heapstart = sisfb_mem * 1024;
  2078.      }
  2079.      sisfb_heap_start =
  2080.        (unsigned long) (ivideo.video_vbase + ivideo.heapstart);
  2081.      printk(KERN_INFO "sisfb: Memory heap starting at %dKn",
  2082.       (int)(ivideo.heapstart / 1024));
  2083.      sisfb_heap_end = (unsigned long) ivideo.video_vbase + ivideo.video_size;
  2084.      sisfb_heap_size = sisfb_heap_end - sisfb_heap_start;
  2085. #ifdef CONFIG_FB_SIS_315
  2086.      if (sisvga_engine == SIS_315_VGA) {
  2087.         /* TW: Now initialize the 310 series' command queue mode.
  2088.  * On 310/325, there are three queue modes available which
  2089.  * are chosen by setting bits 7:5 in SR26:
  2090.  * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep
  2091.  *    track of the queue, the FIFO, command parsing and so
  2092.  *    on. This is the one comparable to the 300 series.
  2093.  * 2. VRAM queue mode (bit 6, 0x40). In this case, one will
  2094.  *    have to do queue management himself. Register 0x85c4 will
  2095.  *    hold the location of the next free queue slot, 0x85c8
  2096.  *    is the "queue read pointer" whose way of working is
  2097.  *    unknown to me. Anyway, this mode would require a
  2098.  *    translation of the MMIO commands to some kind of
  2099.  *    accelerator assembly and writing these commands
  2100.  *    to the memory location pointed to by 0x85c4.
  2101.  *    We will not use this, as nobody knows how this
  2102.  *    "assembly" works, and as it would require a complete
  2103.  *    re-write of the accelerator code.
  2104.  * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the
  2105.  *    queue in AGP memory space.
  2106.  *
  2107.  * SR26 bit 4 is called "Bypass H/W queue".
  2108.  * SR26 bit 1 is called "Enable Command Queue Auto Correction"
  2109.  * SR26 bit 0 resets the queue
  2110.  * Size of queue memory is encoded in bits 3:2 like this:
  2111.  *    00  (0x00)  512K
  2112.  *    01  (0x04)  1M
  2113.  *    10  (0x08)  2M
  2114.  *    11  (0x0C)  4M
  2115.  * The queue location is to be written to 0x85C0.
  2116.  *
  2117.          */
  2118. cmdq_baseport = (unsigned long *)(ivideo.mmio_vbase + MMIO_QUEUE_PHYBASE);
  2119. write_port    = (unsigned long *)(ivideo.mmio_vbase + MMIO_QUEUE_WRITEPORT);
  2120. read_port     = (unsigned long *)(ivideo.mmio_vbase + MMIO_QUEUE_READPORT);
  2121. DPRINTK("AGP base: 0x%p, read: 0x%p, write: 0x%pn", cmdq_baseport, read_port, write_port);
  2122. agp_size  = COMMAND_QUEUE_AREA_SIZE;
  2123. #ifndef AGPOFF
  2124. if (sisfb_queuemode == AGP_CMD_QUEUE) {
  2125. agp_info = vmalloc(sizeof(agp_kern_info));
  2126. memset((void*)agp_info, 0x00, sizeof(agp_kern_info));
  2127. agp_copy_info(agp_info);
  2128. agp_backend_acquire();
  2129. agp = agp_allocate_memory(COMMAND_QUEUE_AREA_SIZE/PAGE_SIZE,
  2130.   AGP_NORMAL_MEMORY);
  2131. if (agp == NULL) {
  2132. DPRINTK("sisfb: Allocating AGP buffer failed.n");
  2133. agp_enabled = 0;
  2134. } else {
  2135. if (agp_bind_memory(agp, agp->pg_start) != 0) {
  2136. DPRINTK("sisfb: AGP: Failed to bind memoryn");
  2137. /* TODO: Free AGP memory here */
  2138. agp_enabled = 0;
  2139. } else {
  2140. agp_enable(0);
  2141. }
  2142. }
  2143. }
  2144. #else
  2145. agp_enabled = 0;
  2146. #endif
  2147. /* TW: Now select the queue mode */
  2148. if ((agp_enabled) && (sisfb_queuemode == AGP_CMD_QUEUE)) {
  2149. cmd_type = AGP_CMD_QUEUE;
  2150. printk(KERN_INFO "sisfb: Using AGP queue moden");
  2151. /* } else if (sisfb_heap_size >= COMMAND_QUEUE_AREA_SIZE)  */
  2152.         } else if (sisfb_queuemode == VM_CMD_QUEUE) {
  2153. cmd_type = VM_CMD_QUEUE;
  2154. printk(KERN_INFO "sisfb: Using VRAM queue moden");
  2155. } else {
  2156. printk(KERN_INFO "sisfb: Using MMIO queue moden");
  2157. cmd_type = MMIO_CMD;
  2158. }
  2159. switch (agp_size) {
  2160.    case 0x80000:
  2161. temp = SIS_CMD_QUEUE_SIZE_512k;
  2162. break;
  2163.    case 0x100000:
  2164. temp = SIS_CMD_QUEUE_SIZE_1M;
  2165. break;
  2166.    case 0x200000:
  2167. temp = SIS_CMD_QUEUE_SIZE_2M;
  2168. break;
  2169.    case 0x400000:
  2170. temp = SIS_CMD_QUEUE_SIZE_4M;
  2171. break;
  2172. }
  2173. switch (cmd_type) {
  2174.    case AGP_CMD_QUEUE:
  2175. #ifndef AGPOFF
  2176. DPRINTK("sisfb: AGP buffer base = 0x%lx, offset = 0x%x, size = %dKn",
  2177. agp_info->aper_base, agp->physical, agp_size/1024);
  2178. agp_phys = agp_info->aper_base + agp->physical;
  2179. outSISIDXREG(SISCR,  IND_SIS_AGP_IO_PAD, 0);
  2180. outSISIDXREG(SISCR,  IND_SIS_AGP_IO_PAD, SIS_AGP_2X);
  2181.                 outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
  2182. outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
  2183. *write_port = *read_port;
  2184. temp |= SIS_AGP_CMDQUEUE_ENABLE;
  2185. outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
  2186. *cmdq_baseport = agp_phys;
  2187. sisfb_caps |= AGP_CMD_QUEUE_CAP;
  2188. #endif
  2189. break;
  2190.    case VM_CMD_QUEUE:
  2191. sisfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
  2192. sisfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
  2193. outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
  2194. outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
  2195. *write_port = *read_port;
  2196. temp |= SIS_VRAM_CMDQUEUE_ENABLE;
  2197. outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
  2198. *cmdq_baseport = ivideo.video_size - COMMAND_QUEUE_AREA_SIZE;
  2199. sisfb_caps |= VM_CMD_QUEUE_CAP;
  2200. DPRINTK("sisfb: VM Cmd Queue offset = 0x%lx, size is %dKn",
  2201. *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
  2202. break;
  2203.    default:  /* MMIO */
  2204.     /* TW: This previously only wrote SIS_MMIO_CMD_ENABLE
  2205.  * to IND_SIS_CMDQUEUE_SET. I doubt that this is
  2206.  * enough. Reserve memory in any way.
  2207.  */
  2208.     sisfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
  2209. sisfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
  2210. outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
  2211. outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
  2212. *write_port = *read_port;
  2213. /* TW: Set Auto_Correction bit */
  2214. temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
  2215. outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
  2216. *cmdq_baseport = ivideo.video_size - COMMAND_QUEUE_AREA_SIZE;
  2217. sisfb_caps |= MMIO_CMD_QUEUE_CAP;
  2218. DPRINTK("sisfb: MMIO Cmd Queue offset = 0x%lx, size is %dKn",
  2219. *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
  2220. break;
  2221. }
  2222.      } /* sisvga_engine = 315 */
  2223. #endif
  2224. #ifdef CONFIG_FB_SIS_300
  2225.      if (sisvga_engine == SIS_300_VGA) {
  2226.        /* TW: Now initialize TurboQueue. TB is always located at the very
  2227.      * top of the video RAM. */
  2228.     if (sisfb_heap_size >= TURBO_QUEUE_AREA_SIZE) {
  2229. unsigned int  tqueue_pos;
  2230. u8 tq_state;
  2231. tqueue_pos = (ivideo.video_size -
  2232.        TURBO_QUEUE_AREA_SIZE) / (64 * 1024);
  2233. temp = (u8) (tqueue_pos & 0xff);
  2234. inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
  2235. tq_state |= 0xf0;
  2236. tq_state &= 0xfc;
  2237. tq_state |= (u8) (tqueue_pos >> 8);
  2238. outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
  2239. outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, temp);
  2240. sisfb_caps |= TURBO_QUEUE_CAP;
  2241. sisfb_heap_end -= TURBO_QUEUE_AREA_SIZE;
  2242. sisfb_heap_size -= TURBO_QUEUE_AREA_SIZE;
  2243. DPRINTK("sisfb: TurboQueue start at 0x%lx, size is %dKn",
  2244. sisfb_heap_end, TURBO_QUEUE_AREA_SIZE/1024);
  2245.     }
  2246.      }
  2247. #endif
  2248.      /* TW: Now reserve memory for the HWCursor. It is always located at the very
  2249.             top of the videoRAM, right below the TB memory area (if used). */
  2250.      if (sisfb_heap_size >= sisfb_hwcursor_size) {
  2251. sisfb_heap_end -= sisfb_hwcursor_size;
  2252. sisfb_heap_size -= sisfb_hwcursor_size;
  2253. sisfb_hwcursor_vbase = sisfb_heap_end;
  2254. sisfb_caps |= HW_CURSOR_CAP;
  2255. DPRINTK("sisfb: Hardware Cursor start at 0x%lx, size is %dKn",
  2256. sisfb_heap_end, sisfb_hwcursor_size/1024);
  2257.      }
  2258.      sisfb_heap.poha_chain = NULL;
  2259.      sisfb_heap.poh_freelist = NULL;
  2260.      poh = sisfb_poh_new_node();
  2261.      if(poh == NULL)  return 1;
  2262.      poh->poh_next = &sisfb_heap.oh_free;
  2263.      poh->poh_prev = &sisfb_heap.oh_free;
  2264.      poh->size = sisfb_heap_end - sisfb_heap_start + 1;
  2265.      poh->offset = sisfb_heap_start - (unsigned long) ivideo.video_vbase;
  2266.      DPRINTK("sisfb: Heap start:0x%p, end:0x%p, len=%dkn",
  2267. (char *) sisfb_heap_start, (char *) sisfb_heap_end,
  2268. (unsigned int) poh->size / 1024);
  2269.      DPRINTK("sisfb: First Node offset:0x%x, size:%dkn",
  2270. (unsigned int) poh->offset, (unsigned int) poh->size / 1024);
  2271.      sisfb_heap.oh_free.poh_next = poh;
  2272.      sisfb_heap.oh_free.poh_prev = poh;
  2273.      sisfb_heap.oh_free.size = 0;
  2274.      sisfb_heap.max_freesize = poh->size;
  2275.      sisfb_heap.oh_used.poh_next = &sisfb_heap.oh_used;
  2276.      sisfb_heap.oh_used.poh_prev = &sisfb_heap.oh_used;
  2277.      sisfb_heap.oh_used.size = SENTINEL;
  2278.      return 0;
  2279. }
  2280. static SIS_OH *sisfb_poh_new_node(void)
  2281. {
  2282. int           i;
  2283. unsigned long cOhs;
  2284. SIS_OHALLOC   *poha;
  2285. SIS_OH        *poh;
  2286. if (sisfb_heap.poh_freelist == NULL) {
  2287. poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
  2288. if(!poha) return NULL;
  2289. poha->poha_next = sisfb_heap.poha_chain;
  2290. sisfb_heap.poha_chain = poha;
  2291. cOhs = (OH_ALLOC_SIZE - sizeof(SIS_OHALLOC)) / sizeof(SIS_OH) + 1;
  2292. poh = &poha->aoh[0];
  2293. for (i = cOhs - 1; i != 0; i--) {
  2294. poh->poh_next = poh + 1;
  2295. poh = poh + 1;
  2296. }
  2297. poh->poh_next = NULL;
  2298. sisfb_heap.poh_freelist = &poha->aoh[0];
  2299. }
  2300. poh = sisfb_heap.poh_freelist;
  2301. sisfb_heap.poh_freelist = poh->poh_next;
  2302. return (poh);
  2303. }
  2304. static SIS_OH *sisfb_poh_allocate(unsigned long size)
  2305. {
  2306. SIS_OH *pohThis;
  2307. SIS_OH *pohRoot;
  2308. int     bAllocated = 0;
  2309. if (size > sisfb_heap.max_freesize) {
  2310. DPRINTK("sisfb: Can't allocate %dk size on offscreenn",
  2311. (unsigned int) size / 1024);
  2312. return (NULL);
  2313. }
  2314. pohThis = sisfb_heap.oh_free.poh_next;
  2315. while (pohThis != &sisfb_heap.oh_free) {
  2316. if (size <= pohThis->size) {
  2317. bAllocated = 1;
  2318. break;
  2319. }
  2320. pohThis = pohThis->poh_next;
  2321. }
  2322. if (!bAllocated) {
  2323. DPRINTK("sisfb: Can't allocate %dk size on offscreenn",
  2324. (unsigned int) size / 1024);
  2325. return (NULL);
  2326. }
  2327. if (size == pohThis->size) {
  2328. pohRoot = pohThis;
  2329. sisfb_delete_node(pohThis);
  2330. } else {
  2331. pohRoot = sisfb_poh_new_node();
  2332. if (pohRoot == NULL) {
  2333. return (NULL);
  2334. }
  2335. pohRoot->offset = pohThis->offset;
  2336. pohRoot->size = size;
  2337. pohThis->offset += size;
  2338. pohThis->size -= size;
  2339. }
  2340. sisfb_heap.max_freesize -= size;
  2341. pohThis = &sisfb_heap.oh_used;
  2342. sisfb_insert_node(pohThis, pohRoot);
  2343. return (pohRoot);
  2344. }
  2345. static void sisfb_delete_node(SIS_OH *poh)
  2346. {
  2347. SIS_OH *poh_prev;
  2348. SIS_OH *poh_next;
  2349. poh_prev = poh->poh_prev;
  2350. poh_next = poh->poh_next;
  2351. poh_prev->poh_next = poh_next;
  2352. poh_next->poh_prev = poh_prev;
  2353. }
  2354. static void sisfb_insert_node(SIS_OH *pohList, SIS_OH *poh)
  2355. {
  2356. SIS_OH *pohTemp;
  2357. pohTemp = pohList->poh_next;
  2358. pohList->poh_next = poh;
  2359. pohTemp->poh_prev = poh;
  2360. poh->poh_prev = pohList;
  2361. poh->poh_next = pohTemp;
  2362. }
  2363. static SIS_OH *sisfb_poh_free(unsigned long base)
  2364. {
  2365. SIS_OH *pohThis;
  2366. SIS_OH *poh_freed;
  2367. SIS_OH *poh_prev;
  2368. SIS_OH *poh_next;
  2369. unsigned long ulUpper;
  2370. unsigned long ulLower;
  2371. int foundNode = 0;
  2372. poh_freed = sisfb_heap.oh_used.poh_next;
  2373. while(poh_freed != &sisfb_heap.oh_used) {
  2374. if(poh_freed->offset == base) {
  2375. foundNode = 1;
  2376. break;
  2377. }
  2378. poh_freed = poh_freed->poh_next;
  2379. }
  2380. if (!foundNode)  return (NULL);
  2381. sisfb_heap.max_freesize += poh_freed->size;
  2382. poh_prev = poh_next = NULL;
  2383. ulUpper = poh_freed->offset + poh_freed->size;
  2384. ulLower = poh_freed->offset;
  2385. pohThis = sisfb_heap.oh_free.poh_next;
  2386. while (pohThis != &sisfb_heap.oh_free) {
  2387. if (pohThis->offset == ulUpper) {
  2388. poh_next = pohThis;
  2389. }
  2390. else if ((pohThis->offset + pohThis->size) ==
  2391.  ulLower) {
  2392. poh_prev = pohThis;
  2393. }
  2394. pohThis = pohThis->poh_next;
  2395. }
  2396. sisfb_delete_node(poh_freed);
  2397. if (poh_prev && poh_next) {
  2398. poh_prev->size += (poh_freed->size + poh_next->size);
  2399. sisfb_delete_node(poh_next);
  2400. sisfb_free_node(poh_freed);
  2401. sisfb_free_node(poh_next);
  2402. return (poh_prev);
  2403. }
  2404. if (poh_prev) {
  2405. poh_prev->size += poh_freed->size;
  2406. sisfb_free_node(poh_freed);
  2407. return (poh_prev);
  2408. }
  2409. if (poh_next) {
  2410. poh_next->size += poh_freed->size;
  2411. poh_next->offset = poh_freed->offset;
  2412. sisfb_free_node(poh_freed);
  2413. return (poh_next);
  2414. }
  2415. sisfb_insert_node(&sisfb_heap.oh_free, poh_freed);
  2416. return (poh_freed);
  2417. }
  2418. static void sisfb_free_node(SIS_OH *poh)
  2419. {
  2420. if(poh == NULL) return;
  2421. poh->poh_next = sisfb_heap.poh_freelist;
  2422. sisfb_heap.poh_freelist = poh;
  2423. }
  2424. void sis_malloc(struct sis_memreq *req)
  2425. {
  2426. SIS_OH *poh;
  2427. poh = sisfb_poh_allocate(req->size);
  2428. if(poh == NULL) {
  2429. req->offset = 0;
  2430. req->size = 0;
  2431. DPRINTK("sisfb: Video RAM allocation failedn");
  2432. } else {
  2433. DPRINTK("sisfb: Video RAM allocation succeeded: 0x%pn",
  2434. (char *) (poh->offset + (unsigned long) ivideo.video_vbase));
  2435. req->offset = poh->offset;
  2436. req->size = poh->size;
  2437. }
  2438. }
  2439. void sis_free(unsigned long base)
  2440. {
  2441. SIS_OH *poh;
  2442. poh = sisfb_poh_free(base);
  2443. if(poh == NULL) {
  2444. DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%xn",
  2445. (unsigned int) base);
  2446. }
  2447. }
  2448. /* ------------------ SetMode Routines ------------------------------- */
  2449. static void sisfb_pre_setmode(void)
  2450. {
  2451. u8 cr30 = 0, cr31 = 0;
  2452. inSISIDXREG(SISCR, 0x31, cr31);
  2453. cr31 &= ~0x60;
  2454. switch (ivideo.disp_state & DISPTYPE_DISP2) {
  2455.    case DISPTYPE_CRT2:
  2456. printk(KERN_INFO "sisfb: CRT2 type is VGAn");
  2457. cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
  2458. cr31 |= SIS_DRIVER_MODE;
  2459. break;
  2460.    case DISPTYPE_LCD:
  2461. printk(KERN_INFO "sisfb: CRT2 type is LCDn");
  2462. cr30  = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
  2463. cr31 |= SIS_DRIVER_MODE;
  2464. break;
  2465.    case DISPTYPE_TV:
  2466. printk(KERN_INFO "sisfb: CRT2 type is TVn");
  2467. if (ivideo.TV_type == TVMODE_HIVISION)
  2468. cr30 = (SIS_VB_OUTPUT_HIVISION | SIS_SIMULTANEOUS_VIEW_ENABLE);
  2469. else if (ivideo.TV_plug == TVPLUG_SVIDEO)
  2470. cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
  2471. else if (ivideo.TV_plug == TVPLUG_COMPOSITE)
  2472. cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE);
  2473. else if (ivideo.TV_plug == TVPLUG_SCART)
  2474. cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
  2475. cr31 |= SIS_DRIVER_MODE;
  2476.         if (sisfb_tvmode == 1 || ivideo.TV_type == TVMODE_PAL)
  2477. cr31 |= 0x01;
  2478.                 else   /* if (sisfb_tvmode == 2 || ivideo.TV_type == TVMODE_NTSC) - nonsense */
  2479.                         cr31 &= ~0x01;
  2480. break;
  2481.    default: /* CRT2 disable */
  2482. printk(KERN_INFO "sisfb: CRT2 is disabledn");
  2483. cr30 = 0x00;
  2484. cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
  2485. }
  2486. outSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR30, cr30);
  2487. outSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR31, cr31);
  2488.         outSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR33, (sisfb_rate_idx & 0x0F));
  2489. }
  2490. static void sisfb_post_setmode(void)
  2491. {
  2492. u8 reg;
  2493. BOOLEAN doit = TRUE;
  2494. /* TW: We can't switch off CRT1 on LVDS/Chrontel in 8bpp Modes */
  2495. if ((ivideo.hasVB == HASVB_LVDS) || (ivideo.hasVB == HASVB_LVDS_CHRONTEL)) {
  2496. if (ivideo.video_bpp == 8) {
  2497. doit = FALSE;
  2498. }
  2499. }
  2500. /* TW: We can't switch off CRT1 on 630+301B in 8bpp Modes */
  2501. if ( (sishw_ext.ujVBChipID == VB_CHIP_301B) && (sisvga_engine == SIS_300_VGA) &&
  2502.      (ivideo.disp_state & DISPTYPE_LCD) ) {
  2503.         if (ivideo.video_bpp == 8) {
  2504. doit = FALSE;
  2505.         }
  2506. }
  2507. /* TW: We can't switch off CRT1 if bridge is in slave mode */
  2508. if(ivideo.hasVB != HASVB_NONE) {
  2509. inSISIDXREG(SISPART1, 0x00, reg);
  2510. if(sisvga_engine == SIS_300_VGA) {
  2511. if((reg & 0xa0) == 0x20) {
  2512. doit = FALSE;
  2513. }
  2514. }
  2515. if(sisvga_engine == SIS_315_VGA) {
  2516. if((reg & 0x50) == 0x10) {
  2517. doit = FALSE;
  2518. }
  2519. }
  2520. } else sisfb_crt1off = 0;
  2521. inSISIDXREG(SISCR, 0x17, reg);
  2522. if((sisfb_crt1off) && (doit))
  2523. reg &= ~0x80;
  2524. else        
  2525. reg |= 0x80;
  2526. outSISIDXREG(SISCR, 0x17, reg);
  2527.         andSISIDXREG(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
  2528. if((ivideo.disp_state & DISPTYPE_TV) && (ivideo.hasVB == HASVB_301)) {
  2529.    inSISIDXREG(SISPART4, 0x01, reg);
  2530.    if(reg < 0xB0) {         /* Set filter for SiS301 */
  2531. switch (ivideo.video_width) {
  2532.    case 320:
  2533. filter_tb = (ivideo.TV_type == TVMODE_NTSC) ? 4 : 12;
  2534. break;
  2535.    case 640:
  2536. filter_tb = (ivideo.TV_type == TVMODE_NTSC) ? 5 : 13;
  2537. break;
  2538.    case 720:
  2539. filter_tb = (ivideo.TV_type == TVMODE_NTSC) ? 6 : 14;
  2540. break;
  2541.    case 800:
  2542. filter_tb = (ivideo.TV_type == TVMODE_NTSC) ? 7 : 15;
  2543. break;
  2544.    default:
  2545. filter = -1;
  2546. break;
  2547. }
  2548. orSISIDXREG(SISPART1, sisfb_CRT2_write_enable, 0x01);
  2549. if(ivideo.TV_type == TVMODE_NTSC) {
  2550.         andSISIDXREG(SISPART2, 0x3a, 0x1f);
  2551. if (ivideo.TV_plug == TVPLUG_SVIDEO) {
  2552.         andSISIDXREG(SISPART2, 0x30, 0xdf);
  2553. } else if (ivideo.TV_plug == TVPLUG_COMPOSITE) {
  2554.         orSISIDXREG(SISPART2, 0x30, 0x20);
  2555. switch (ivideo.video_width) {
  2556. case 640:
  2557.         outSISIDXREG(SISPART2, 0x35, 0xEB);
  2558. outSISIDXREG(SISPART2, 0x36, 0x04);
  2559. outSISIDXREG(SISPART2, 0x37, 0x25);
  2560. outSISIDXREG(SISPART2, 0x38, 0x18);
  2561. break;
  2562. case 720:
  2563. outSISIDXREG(SISPART2, 0x35, 0xEE);
  2564. outSISIDXREG(SISPART2, 0x36, 0x0C);
  2565. outSISIDXREG(SISPART2, 0x37, 0x22);
  2566. outSISIDXREG(SISPART2, 0x38, 0x08);
  2567. break;
  2568. case 800:
  2569. outSISIDXREG(SISPART2, 0x35, 0xEB);
  2570. outSISIDXREG(SISPART2, 0x36, 0x15);
  2571. outSISIDXREG(SISPART2, 0x37, 0x25);
  2572. outSISIDXREG(SISPART2, 0x38, 0xF6);
  2573. break;
  2574. }
  2575. }
  2576. } else if(ivideo.TV_type == TVMODE_PAL) {
  2577. andSISIDXREG(SISPART2, 0x3A, 0x1F);
  2578. if (ivideo.TV_plug == TVPLUG_SVIDEO) {
  2579.         andSISIDXREG(SISPART2, 0x30, 0xDF);
  2580. } else if (ivideo.TV_plug == TVPLUG_COMPOSITE) {
  2581.         orSISIDXREG(SISPART2, 0x30, 0x20);
  2582. switch (ivideo.video_width) {
  2583. case 640:
  2584. outSISIDXREG(SISPART2, 0x35, 0xF1);
  2585. outSISIDXREG(SISPART2, 0x36, 0xF7);
  2586. outSISIDXREG(SISPART2, 0x37, 0x1F);
  2587. outSISIDXREG(SISPART2, 0x38, 0x32);
  2588. break;
  2589. case 720:
  2590. outSISIDXREG(SISPART2, 0x35, 0xF3);
  2591. outSISIDXREG(SISPART2, 0x36, 0x00);
  2592. outSISIDXREG(SISPART2, 0x37, 0x1D);
  2593. outSISIDXREG(SISPART2, 0x38, 0x20);
  2594. break;
  2595. case 800:
  2596. outSISIDXREG(SISPART2, 0x35, 0xFC);
  2597. outSISIDXREG(SISPART2, 0x36, 0xFB);
  2598. outSISIDXREG(SISPART2, 0x37, 0x14);
  2599. outSISIDXREG(SISPART2, 0x38, 0x2A);
  2600. break;
  2601. }
  2602. }
  2603. }
  2604. if ((filter >= 0) && (filter <=7)) {
  2605. DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02xn", filter_tb, filter, 
  2606. sis_TV_filter[filter_tb].filter[filter][0],
  2607. sis_TV_filter[filter_tb].filter[filter][1],
  2608. sis_TV_filter[filter_tb].filter[filter][2],
  2609. sis_TV_filter[filter_tb].filter[filter][3]
  2610. );
  2611. outSISIDXREG(SISPART2, 0x35, (sis_TV_filter[filter_tb].filter[filter][0]));
  2612. outSISIDXREG(SISPART2, 0x36, (sis_TV_filter[filter_tb].filter[filter][1]));
  2613. outSISIDXREG(SISPART2, 0x37, (sis_TV_filter[filter_tb].filter[filter][2]));
  2614. outSISIDXREG(SISPART2, 0x38, (sis_TV_filter[filter_tb].filter[filter][3]));
  2615. }
  2616.      }
  2617.   
  2618. }
  2619. }
  2620. #ifndef MODULE
  2621. int sisfb_setup(char *options)
  2622. {
  2623. char *this_opt;
  2624. sis_fb_info.fontname[0] = '';
  2625. ivideo.refresh_rate = 0;
  2626.         printk(KERN_INFO "sisfb: Options %sn", options);
  2627. if (!options || !*options)
  2628. return 0;
  2629. while((this_opt = strsep(&options, ",")) != NULL) {
  2630. if (!*this_opt) continue;
  2631. if (!strcmp(this_opt, "inverse")) {
  2632. sisfb_inverse = 1;
  2633. /* fb_invert_cmaps(); */
  2634. } else if (!strncmp(this_opt, "font:", 5)) {
  2635. strcpy(sis_fb_info.fontname, this_opt + 5);
  2636. } else if (!strncmp(this_opt, "mode:", 5)) {
  2637. sisfb_search_mode(this_opt + 5);
  2638. } else if (!strncmp(this_opt, "vesa:", 5)) {
  2639. sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0));
  2640. } else if (!strncmp(this_opt, "vrate:", 6)) {
  2641. ivideo.refresh_rate =
  2642.     simple_strtoul(this_opt + 6, NULL, 0);
  2643. } else if (!strncmp(this_opt, "rate:", 5)) {
  2644. ivideo.refresh_rate =
  2645.     simple_strtoul(this_opt + 5, NULL, 0);
  2646. } else if (!strncmp(this_opt, "off", 3)) {
  2647. sisfb_off = 1;
  2648. } else if (!strncmp(this_opt, "crt1off", 7)) {
  2649. sisfb_crt1off = 1;
  2650. } else if (!strncmp(this_opt, "filter:", 7)) {
  2651. filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
  2652. } else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
  2653. sisfb_search_crt2type(this_opt + 14);
  2654. } else if (!strncmp(this_opt, "forcecrt1:", 10)) {
  2655. sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
  2656.                 } else if (!strncmp(this_opt, "tvmode:",7)) {
  2657.                         if (!strncmp(this_opt + 7, "pal",3))
  2658.                           sisfb_tvmode = 1;
  2659.                         if (!strncmp(this_opt + 7, "ntsc",4))
  2660.                           sisfb_tvmode = 2;
  2661.                 } else if (!strncmp(this_opt, "tvstandard:",11)) {
  2662.                         if (!strncmp(this_opt + 11, "pal",3))
  2663.                           sisfb_tvmode = 1;
  2664.                         else if (!strncmp(this_opt + 11, "ntsc",4))
  2665.                           sisfb_tvmode = 2;
  2666.                 }else if (!strncmp(this_opt, "mem:",4)) {
  2667.         sisfb_mem = simple_strtoul(this_opt + 4, NULL, 0);
  2668.                 } else if (!strncmp(this_opt, "dstn", 4)) {
  2669. enable_dstn = 1;
  2670. /* TW: DSTN overrules forcecrt2type */
  2671. sisfb_crt2type = DISPTYPE_LCD;
  2672. } else if (!strncmp(this_opt, "queuemode:", 10)) {
  2673. sisfb_search_queuemode(this_opt + 10);
  2674. } else if (!strncmp(this_opt, "pdc:", 4)) {
  2675.         sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
  2676.         if(sisfb_pdc & ~0x3c) {
  2677.    printk(KERN_INFO "sisfb: Illegal pdc parametern");
  2678.    sisfb_pdc = 0;
  2679.         }
  2680. } else if (!strncmp(this_opt, "noaccel", 7)) {
  2681. sisfb_accel = 0;
  2682. } else if (!strncmp(this_opt, "noypan", 6)) {
  2683.         sisfb_ypan = 0;
  2684. } else {
  2685. printk(KERN_INFO "sisfb: Invalid parameter %sn", this_opt);
  2686. }
  2687. /* TW: Acceleration only with MMIO mode */
  2688. if((sisfb_queuemode != -1) && (sisfb_queuemode != MMIO_CMD)) {
  2689. sisfb_ypan = 0;
  2690. sisfb_accel = 0;
  2691. }
  2692. /* TW: Panning only with acceleration */
  2693. if(sisfb_accel == 0) sisfb_ypan = 0;
  2694. }
  2695. return 0;
  2696. }
  2697. #endif
  2698. int __init sisfb_init(void)
  2699. {
  2700. struct pci_dev *pdev = NULL;
  2701. struct board *b;
  2702. int pdev_valid = 0;
  2703. /* unsigned long rom_vbase;  */
  2704. u32 reg32;
  2705. u16 reg16;
  2706. u8  reg;
  2707. outb(0x77, 0x80);
  2708. #if 0 
  2709. /* for DOC VB */
  2710. sisfb_set_reg4(0xcf8,0x800000e0);
  2711. reg32 = sisfb_get_reg3(0xcfc);
  2712. reg32 = reg32 | 0x00001000;
  2713. sisfb_set_reg4(0xcfc,reg32);
  2714. }
  2715. #endif
  2716. if (sisfb_off)
  2717. return -ENXIO;
  2718. if (enable_dstn)
  2719. SetEnableDstn(&SiS_Pr);
  2720. memset(&sis_fb_info, 0, sizeof(sis_fb_info));
  2721. memset(&sis_disp, 0, sizeof(sis_disp));
  2722. pci_for_each_dev(pdev) {
  2723. for (b = sisdev_list; b->vendor; b++) {
  2724. if ((b->vendor == pdev->vendor)
  2725.     && (b->device == pdev->device)) {
  2726. pdev_valid = 1;
  2727. strcpy(sis_fb_info.modename, b->name);
  2728. ivideo.chip_id = pdev->device;
  2729. pci_read_config_byte(pdev, PCI_REVISION_ID,
  2730.                      &ivideo.revision_id);
  2731. pci_read_config_word(pdev, PCI_COMMAND, &reg16);
  2732. sishw_ext.jChipRevision = ivideo.revision_id;
  2733. sisvga_enabled = reg16 & 0x01;
  2734. break;
  2735. }
  2736. }
  2737. if (pdev_valid)
  2738. break;
  2739. }
  2740. if (!pdev_valid)
  2741. return -ENODEV;
  2742. switch (ivideo.chip_id) {
  2743.    case PCI_DEVICE_ID_SI_300:
  2744. ivideo.chip = SIS_300;
  2745. sisvga_engine = SIS_300_VGA;
  2746. sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_300;
  2747. sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_300;
  2748. break;
  2749.    case PCI_DEVICE_ID_SI_630_VGA:
  2750. {
  2751. sisfb_set_reg4(0xCF8, 0x80000000);
  2752. reg32 = sisfb_get_reg3(0xCFC);
  2753. if(reg32 == 0x07301039) {
  2754. ivideo.chip = SIS_730;
  2755. strcpy(sis_fb_info.modename, "SIS 730");
  2756. } else
  2757. ivideo.chip = SIS_630;
  2758. sisvga_engine = SIS_300_VGA;
  2759. sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_300;
  2760. sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_300;
  2761. break;
  2762. }
  2763.    case PCI_DEVICE_ID_SI_540_VGA:
  2764. ivideo.chip = SIS_540;
  2765. sisvga_engine = SIS_300_VGA;
  2766. sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_300;
  2767. sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_300;
  2768. break;
  2769.    case PCI_DEVICE_ID_SI_315H:
  2770. ivideo.chip = SIS_315H;
  2771. sisvga_engine = SIS_315_VGA;
  2772. sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315;
  2773. sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
  2774. break;
  2775.    case PCI_DEVICE_ID_SI_315:
  2776. ivideo.chip = SIS_315;
  2777. sisvga_engine = SIS_315_VGA;
  2778. sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315;
  2779. sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
  2780. break;
  2781.    case PCI_DEVICE_ID_SI_315PRO:
  2782. ivideo.chip = SIS_315PRO;
  2783. sisvga_engine = SIS_315_VGA;
  2784. sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315;
  2785. sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
  2786. break;
  2787.    case PCI_DEVICE_ID_SI_550_VGA:
  2788. ivideo.chip = SIS_550;
  2789. sisvga_engine = SIS_315_VGA;
  2790. sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315;
  2791. sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
  2792. break;
  2793.    case PCI_DEVICE_ID_SI_650_VGA:
  2794. ivideo.chip = SIS_650;
  2795. sisvga_engine = SIS_315_VGA;
  2796. sisfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315;
  2797. sisfb_CRT2_write_enable = IND_SIS_CRT2_WRITE_ENABLE_315;
  2798. break;
  2799. }
  2800. sishw_ext.jChipType = ivideo.chip;
  2801. /* for Debug */
  2802. if ((sishw_ext.jChipType == SIS_315PRO) 
  2803.    || (sishw_ext.jChipType == SIS_315) )
  2804. sishw_ext.jChipType = SIS_315H;
  2805. DPRINTK("%s is used as %s device (VGA Engine %d).n",
  2806. sis_fb_info.modename, sisvga_enabled ? "primary" : "secondary", sisvga_engine);
  2807. ivideo.video_base = pci_resource_start(pdev, 0);
  2808. ivideo.mmio_base = pci_resource_start(pdev, 1);
  2809. sishw_ext.ulIOAddress = (unsigned short) ivideo.vga_base =
  2810.     (unsigned short) SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
  2811. sisfb_mmio_size =  pci_resource_len(pdev, 1);
  2812. if(!sisvga_enabled) {
  2813. if (pci_enable_device(pdev))   return -EIO;
  2814. }
  2815. SiSRegInit(&SiS_Pr, (USHORT)sishw_ext.ulIOAddress);
  2816. // Eden Eden
  2817. //#ifdef LINUXBIOS
  2818. // sishw_ext.VirtualRomBase = rom_vbase = (unsigned long) rom_data;
  2819. //#else
  2820. // {
  2821. // unsigned long rom_base  = 0x000C0000;
  2822. //
  2823. // request_region(rom_base, 32, "sisfb");
  2824. // sishw_ext.VirtualRomBase = rom_vbase 
  2825. // = (unsigned long) ioremap(rom_base, MAX_ROM_SCAN);
  2826. // }
  2827. //#endif
  2828. // ~Eden Chen
  2829.         outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
  2830. #ifdef LINUXBIOS
  2831. #ifdef CONFIG_FB_SIS_300
  2832. if (sisvga_engine == SIS_300_VGA) {
  2833.         outSISIDXREG(SISSR, 0x28, 0x37);
  2834.                 outSISIDXREG(SISSR, 0x29, 0x61);
  2835.                 orSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_1A, SIS_SCRATCH_REG_1A_MASK);
  2836. }
  2837. #endif
  2838. #ifdef CONFIG_FB_SIS_315
  2839. if (ivideo.chip == SIS_550 || ivideo.chip == SIS_650) {
  2840.         outSISIDXREG(SISSR, 0x28, 0x5a);
  2841.                 outSISIDXREG(SISSR, 0x29, 0x64);
  2842.                 outSISIDXREG(SISCR, 0x3a, 0x00);
  2843. }
  2844. #endif
  2845. #endif /* LinuxBIOS */
  2846. if (sisvga_engine == SIS_315_VGA) {
  2847. switch (ivideo.chip) {
  2848.    case SIS_315H:
  2849.    case SIS_315:
  2850. sishw_ext.bIntegratedMMEnabled = TRUE;
  2851. break;
  2852.    case SIS_550:
  2853.    case SIS_650:
  2854. sishw_ext.bIntegratedMMEnabled = TRUE;
  2855. break;
  2856.    default:
  2857. break;
  2858. }
  2859. } else if (sisvga_engine == SIS_300_VGA) {
  2860. if (ivideo.chip == SIS_300) {
  2861. sishw_ext.bIntegratedMMEnabled = TRUE;
  2862. } else {
  2863.         inSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_1A, reg);
  2864. if (reg & SIS_SCRATCH_REG_1A_MASK)
  2865. sishw_ext.bIntegratedMMEnabled = TRUE;
  2866. else
  2867. sishw_ext.bIntegratedMMEnabled = FALSE;
  2868. }
  2869. }
  2870. sishw_ext.pDevice = NULL;
  2871. sishw_ext.pjVirtualRomBase = NULL;
  2872. sishw_ext.pjCustomizedROMImage = NULL;
  2873. sishw_ext.bSkipDramSizing = 0;
  2874. sishw_ext.pQueryVGAConfigSpace = &sisfb_query_VGA_config_space;
  2875. sishw_ext.pQueryNorthBridgeSpace = &sisfb_query_north_bridge_space;
  2876. strcpy(sishw_ext.szVBIOSVer, "0.84");
  2877. /* TW: Mode numbers for 1280x960 are different for 300 and 310/325 series */
  2878. if(sisvga_engine == SIS_300_VGA) {
  2879. sisbios_mode[MODEINDEX_1280x960].mode_no = 0x6e;
  2880. sisbios_mode[MODEINDEX_1280x960+1].mode_no = 0x6f;
  2881. sisbios_mode[MODEINDEX_1280x960+2].mode_no = 0x7b;
  2882. sisbios_mode[MODEINDEX_1280x960+3].mode_no = 0x7b;
  2883. }
  2884. sishw_ext.pSR = vmalloc(sizeof(SIS_DSReg) * SR_BUFFER_SIZE);
  2885. if (sishw_ext.pSR == NULL) {
  2886. printk(KERN_ERR "sisfb: Fatal error: Allocating SRReg space failed.n");
  2887. return -ENODEV;
  2888. }
  2889. sishw_ext.pSR[0].jIdx = sishw_ext.pSR[0].jVal = 0xFF;
  2890. sishw_ext.pCR = vmalloc(sizeof(SIS_DSReg) * CR_BUFFER_SIZE);
  2891. if (sishw_ext.pCR == NULL) {
  2892.         vfree(sishw_ext.pSR);
  2893. printk(KERN_ERR "sisfb: Fatal error: Allocating CRReg space failed.n");
  2894. return -ENODEV;
  2895. }
  2896. sishw_ext.pCR[0].jIdx = sishw_ext.pCR[0].jVal = 0xFF;
  2897. #ifdef CONFIG_FB_SIS_300
  2898. if(sisvga_engine == SIS_300_VGA) {
  2899. if(!sisvga_enabled) {
  2900. sishw_ext.pjVideoMemoryAddress
  2901. = ioremap(ivideo.video_base, 0x2000000);
  2902. if ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF) {   /* TW: for mode "none" */
  2903.         /* TW: SiSInit now for LinuxBIOS only */
  2904. /* SiSInit(&SiS_Pr, &sishw_ext);  */
  2905. outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
  2906. }
  2907. }
  2908. #ifdef LINUXBIOS
  2909. else {
  2910. sishw_ext.pjVideoMemoryAddress
  2911. = ioremap(ivideo.video_base, 0x2000000);
  2912. if ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF) {   /* TW: for mode "none" */
  2913. SiSInit(&SiS_Pr, &sishw_ext);
  2914. outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
  2915. }
  2916. }
  2917. if((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF) {   /* TW: for mode "none" */
  2918.         orSISIDXREG(SISSR, 0x07, 0x10);
  2919. }
  2920. #endif
  2921. if(sisfb_get_dram_size_300()) {
  2922.         vfree(sishw_ext.pSR);
  2923. vfree(sishw_ext.pCR);
  2924. printk(KERN_ERR "sisfb: Fatal error: Unable to determine RAM sizen");
  2925. return -ENODEV;
  2926. }
  2927. }
  2928. #endif
  2929. #ifdef CONFIG_FB_SIS_315
  2930. if (sisvga_engine == SIS_315_VGA) {
  2931. if (!sisvga_enabled) {
  2932. /* Mapping Max FB Size for 315 Init */
  2933. // Eden Chen
  2934. //sishw_ext.VirtualVideoMemoryAddress 
  2935. sishw_ext.pjVideoMemoryAddress 
  2936. = ioremap(ivideo.video_base, 0x8000000);
  2937. if ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF) {   /* TW: for mode "none" */
  2938.         /* TW: SISInit is now for LINUXBIOS only */
  2939. /* SiSInit(&SiS_Pr, &sishw_ext); */
  2940. outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
  2941. sishw_ext.bSkipDramSizing = TRUE;
  2942. sishw_ext.pSR[0].jIdx = 0x13;
  2943. sishw_ext.pSR[1].jIdx = 0x14;
  2944. sishw_ext.pSR[2].jIdx = 0xFF;
  2945. inSISIDXREG(SISSR, 0x13, sishw_ext.pSR[0].jVal);
  2946. inSISIDXREG(SISSR, 0x14, sishw_ext.pSR[1].jVal);
  2947. sishw_ext.pSR[2].jVal = 0xFF;
  2948. }
  2949. }
  2950. #ifdef LINUXBIOS
  2951. else {
  2952. sishw_ext.pjVideoMemoryAddress
  2953. = ioremap(ivideo.video_base, 0x8000000);
  2954. if ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF) {   /* TW: for mode "none" */
  2955. SiSInit(&SiS_Pr, &sishw_ext);
  2956. outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
  2957. sishw_ext.bSkipDramSizing = TRUE;
  2958. sishw_ext.pSR[0].jIdx = 0x13;
  2959. sishw_ext.pSR[1].jIdx = 0x14;
  2960. sishw_ext.pSR[2].jIdx = 0xFF;
  2961. inSISIDXREG(SISSR, 0x13, sishw_ext.pSR[0].jVal);
  2962. inSISIDXREG(SISSR, 0x14, sishw_ext.pSR[1].jVal);
  2963. sishw_ext.pSR[2].jVal = 0xFF;
  2964. }
  2965. }
  2966. #endif
  2967. if (sisfb_get_dram_size_315()) {
  2968. vfree(sishw_ext.pSR);
  2969. vfree(sishw_ext.pCR);
  2970. printk(KERN_INFO "sisfb: Fatal error: Unable to determine RAM size.n");
  2971. return -ENODEV;
  2972. }
  2973. }
  2974. #endif
  2975. if ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF) {   /* TW: for mode "none" */
  2976.         /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE  */
  2977.         orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
  2978.                 /* Enable 2D accelerator engine */
  2979.         orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
  2980. }
  2981. sishw_ext.ulVideoMemorySize = ivideo.video_size;
  2982. if(sisfb_pdc) {
  2983.     sishw_ext.pdc = sisfb_pdc;
  2984. } else {
  2985.     sishw_ext.pdc = 0;
  2986. }
  2987. if (!request_mem_region(ivideo.video_base, ivideo.video_size, "sisfb FB")) {
  2988. printk(KERN_ERR "sisfb: Fatal error: Unable to reserve frame buffer memoryn");
  2989. printk(KERN_ERR "sisfb: Is there another framebuffer driver active?n");
  2990. vfree(sishw_ext.pSR);
  2991. vfree(sishw_ext.pCR);
  2992. return -ENODEV;
  2993. }
  2994. if (!request_mem_region(ivideo.mmio_base, sisfb_mmio_size, "sisfb MMIO")) {
  2995. printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO regionn");
  2996. release_mem_region(ivideo.video_base, ivideo.video_size);
  2997. vfree(sishw_ext.pSR);
  2998. vfree(sishw_ext.pCR);
  2999. return -ENODEV;
  3000. }
  3001. sishw_ext.pjVideoMemoryAddress = ivideo.video_vbase
  3002. = ioremap(ivideo.video_base, ivideo.video_size);
  3003. ivideo.mmio_vbase = ioremap(ivideo.mmio_base, sisfb_mmio_size);
  3004. printk(KERN_INFO "sisfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dkn",
  3005.        ivideo.video_base, ivideo.video_vbase,
  3006.        ivideo.video_size / 1024);
  3007. printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%p, size %ldkn",
  3008.        ivideo.mmio_base, ivideo.mmio_vbase,
  3009.        sisfb_mmio_size / 1024);
  3010. if(sisfb_heap_init()) {
  3011. printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heapn");
  3012. }
  3013. ivideo.mtrr = (unsigned int) 0;
  3014. if ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF) {   /* TW: for mode "none" */
  3015. #ifdef CONFIG_FB_SIS_300
  3016. if (sisvga_engine == SIS_300_VGA) {
  3017. sisfb_get_VB_type_300();
  3018. }
  3019. #endif
  3020. #ifdef CONFIG_FB_SIS_315
  3021. if (sisvga_engine == SIS_315_VGA) {
  3022. sisfb_get_VB_type_315();
  3023. }
  3024. #endif
  3025. sishw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
  3026. sishw_ext.usExternalChip = 0;
  3027. switch (ivideo.hasVB) {
  3028. case HASVB_301:
  3029.         inSISIDXREG(SISPART4, 0x01, reg);
  3030. if (reg >= 0xE0) {
  3031. sishw_ext.ujVBChipID = VB_CHIP_301LVX;
  3032. printk(KERN_INFO "sisfb: SiS301LVX bridge detected (revision 0x%02x)n",reg);
  3033.    } else if (reg >= 0xD0) {
  3034. sishw_ext.ujVBChipID = VB_CHIP_301LV;
  3035. printk(KERN_INFO "sisfb: SiS301LV bridge detected (revision 0x%02x)n",reg);
  3036.    } else if (reg >= 0xB0) {
  3037. sishw_ext.ujVBChipID = VB_CHIP_301B;
  3038. printk(KERN_INFO "sisfb: SiS301B bridge detected (revision 0x%02xn",reg);
  3039. } else {
  3040. sishw_ext.ujVBChipID = VB_CHIP_301;
  3041. printk(KERN_INFO "sisfb: SiS301 bridge detectedn");
  3042. }
  3043. break;
  3044. case HASVB_302:
  3045.         inSISIDXREG(SISPART4, 0x01, reg);
  3046. if (reg >= 0xE0) {
  3047. sishw_ext.ujVBChipID = VB_CHIP_302LVX;
  3048. printk(KERN_INFO "sisfb: SiS302LVX bridge detected (revision 0x%02x)n",reg);
  3049.    } else if (reg >= 0xD0) {
  3050. sishw_ext.ujVBChipID = VB_CHIP_302LV;
  3051. printk(KERN_INFO "sisfb: SiS302LV bridge detected (revision 0x%02x)n",reg);
  3052.    } else if (reg >= 0xB0) {
  3053.         sishw_ext.ujVBChipID = VB_CHIP_302B;
  3054. printk(KERN_INFO "sisfb: SiS302B bridge detected (revision 0x%02x)n",reg);
  3055. } else {
  3056.         sishw_ext.ujVBChipID = VB_CHIP_302;
  3057. printk(KERN_INFO "sisfb: SiS302 bridge detectedn");
  3058. }
  3059. break;
  3060. case HASVB_303:
  3061. sishw_ext.ujVBChipID = VB_CHIP_303;
  3062. printk(KERN_INFO "sisfb: SiS303 bridge detected (not supported)n");
  3063. break;
  3064. case HASVB_LVDS:
  3065. sishw_ext.usExternalChip = 0x1;
  3066. printk(KERN_INFO "sisfb: LVDS transmitter detectedn");
  3067. break;
  3068. case HASVB_TRUMPION:
  3069. sishw_ext.usExternalChip = 0x2;
  3070. printk(KERN_INFO "sisfb: Trumpion Zurac LVDS scaler detectedn");
  3071. break;
  3072. case HASVB_CHRONTEL:
  3073. sishw_ext.usExternalChip = 0x4;
  3074. printk(KERN_INFO "sisfb: Chrontel TV encoder detectedn");
  3075. break;
  3076. case HASVB_LVDS_CHRONTEL:
  3077. sishw_ext.usExternalChip = 0x5;
  3078. printk(KERN_INFO "sisfb: LVDS transmitter and Chrontel TV encoder detectedn");
  3079. break;
  3080. default:
  3081. printk(KERN_INFO "sisfb: No or unknown bridge type detectedn");
  3082. break;
  3083. }
  3084. if (ivideo.hasVB != HASVB_NONE) {
  3085. #ifdef CONFIG_FB_SIS_300
  3086.       if (sisvga_engine == SIS_300_VGA) {
  3087. sisfb_detect_VB_connect_300();
  3088.                       }
  3089. #endif
  3090. #ifdef CONFIG_FB_SIS_315
  3091.       if (sisvga_engine == SIS_315_VGA) {
  3092. sisfb_detect_VB_connect_315();
  3093.                       }
  3094. #endif
  3095. }
  3096. if (ivideo.disp_state & DISPTYPE_DISP2) {
  3097. if (sisfb_crt1off)
  3098. ivideo.disp_state |= DISPMODE_SINGLE;
  3099. else
  3100. ivideo.disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);
  3101. } else {
  3102. ivideo.disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;
  3103. }
  3104. if (ivideo.disp_state & DISPTYPE_LCD) {
  3105.     if (!enable_dstn) {
  3106.         inSISIDXREG(SISCR, IND_SIS_LCD_PANEL, reg);
  3107. reg &= 0x0f;
  3108. if (sisvga_engine == SIS_300_VGA) {
  3109.     sishw_ext.ulCRT2LCDType = sis300paneltype[reg];
  3110. } else {
  3111.     sishw_ext.ulCRT2LCDType = sis310paneltype[reg];
  3112. }
  3113.     } else {
  3114.         /* TW: FSTN/DSTN */
  3115. sishw_ext.ulCRT2LCDType = LCD_320x480;
  3116.     }
  3117. }
  3118. if (sisfb_mode_idx >= 0)
  3119. sisfb_mode_idx = sisfb_validate_mode(sisfb_mode_idx);
  3120. if (sisfb_mode_idx < 0) {
  3121. switch (ivideo.disp_state & DISPTYPE_DISP2) {
  3122.    case DISPTYPE_LCD:
  3123. sisfb_mode_idx = DEFAULT_LCDMODE;
  3124. break;
  3125.    case DISPTYPE_TV:
  3126. sisfb_mode_idx = DEFAULT_TVMODE;
  3127. break;
  3128.    default:
  3129. sisfb_mode_idx = DEFAULT_MODE;
  3130. break;
  3131. }
  3132. }
  3133. sisfb_mode_no = sisbios_mode[sisfb_mode_idx].mode_no;
  3134. if (ivideo.refresh_rate != 0)
  3135. sisfb_search_refresh_rate(ivideo.refresh_rate);
  3136. if (sisfb_rate_idx == 0) {
  3137. sisfb_rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;
  3138. ivideo.refresh_rate = 60;
  3139. }
  3140. ivideo.video_bpp = sisbios_mode[sisfb_mode_idx].bpp;
  3141. ivideo.video_vwidth = ivideo.video_width = sisbios_mode[sisfb_mode_idx].xres;
  3142. ivideo.video_vheight = ivideo.video_height = sisbios_mode[sisfb_mode_idx].yres;
  3143. ivideo.org_x = ivideo.org_y = 0;
  3144. ivideo.video_linelength = ivideo.video_width * (ivideo.video_bpp >> 3);
  3145. switch(ivideo.video_bpp) {
  3146.          case 8:
  3147.              ivideo.DstColor = 0x0000;
  3148.      ivideo.SiS310_AccelDepth = 0x00000000;
  3149. ivideo.video_cmap_len = 256;
  3150.              break;
  3151.          case 16:
  3152.              ivideo.DstColor = 0x8000;
  3153.              ivideo.SiS310_AccelDepth = 0x00010000;
  3154. ivideo.video_cmap_len = 16;
  3155.              break;
  3156.          case 32:
  3157.              ivideo.DstColor = 0xC000;
  3158.      ivideo.SiS310_AccelDepth = 0x00020000;
  3159. ivideo.video_cmap_len = 16;
  3160.              break;
  3161. default:
  3162. ivideo.video_cmap_len = 16;
  3163.         printk(KERN_INFO "sisfb: Unsupported accel depth %d", ivideo.video_bpp);
  3164. sisfb_accel = 0;
  3165. break;
  3166.      }
  3167. printk(KERN_INFO "sisfb: Mode is %dx%dx%d (%dHz)n",
  3168.         ivideo.video_width, ivideo.video_height, ivideo.video_bpp,
  3169. ivideo.refresh_rate);
  3170. sisfb_pre_setmode();
  3171. if (SiSSetMode(&SiS_Pr, &sishw_ext, sisfb_mode_no) == 0) {
  3172. printk("sisfb: Setting mode[0x%x] failed, using default moden", sisfb_mode_no);
  3173. return -1;
  3174. }
  3175. outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
  3176. sisfb_post_setmode();
  3177. sisfb_crtc_to_var(&default_var);
  3178. if(sisfb_accel) {
  3179.    sisfb_initaccel();
  3180. }
  3181. #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33) /* ---- 2.4 series init ---- */
  3182. #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)
  3183. sis_fb_info.screen_base = ivideo.video_vbase;
  3184. sis_fb_info.currcon = -1;
  3185. #endif
  3186. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
  3187. sis_fb_info.node = -1;
  3188. #else
  3189. sis_fb_info.node = NODEV;
  3190. #endif
  3191. #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,23)
  3192. sis_fb_info.blank = &sisfb_blank;
  3193. #endif
  3194. sis_fb_info.fbops = &sisfb_ops;
  3195. sis_fb_info.switch_con = &sisfb_switch;
  3196. sis_fb_info.updatevar = &sisfb_update_var;
  3197. sis_fb_info.changevar = NULL;
  3198. sis_fb_info.disp = &sis_disp;
  3199. sis_fb_info.flags = FBINFO_FLAG_DEFAULT;
  3200. sisfb_set_disp(-1, &default_var, &sis_fb_info);
  3201. #endif
  3202. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34) /* ---- 2.5 series init ---- */
  3203. sis_fb_info.screen_base = ivideo.video_vbase;
  3204. sis_fb_info.node = NODEV;
  3205. sis_fb_info.fbops = &sisfb_ops;
  3206. sisfb_get_fix(&sis_fb_info.fix, -1, &sis_fb_info);
  3207. sis_fb_info.pseudo_palette = pseudo_palette;
  3208. sis_fb_info.flags = FBINFO_FLAG_DEFAULT;
  3209. sis_fb_info.changevar = NULL;
  3210. sis_fb_info.currcon = -1;
  3211. sis_fb_info.disp = &sis_disp;
  3212. sis_fb_info.switch_con = gen_switch;
  3213. sis_fb_info.updatevar = gen_update_var;
  3214. fb_alloc_cmap(&sis_fb_info.cmap, 256, 0);
  3215. sis_fb_info.var = default_var;
  3216. #endif
  3217. #ifdef CONFIG_MTRR
  3218. ivideo.mtrr = mtrr_add((unsigned int) ivideo.video_base,
  3219. (unsigned int) ivideo.video_size,
  3220. MTRR_TYPE_WRCOMB, 1);
  3221. if(ivideo.mtrr) {
  3222. printk(KERN_INFO "sisfb: Added MTRRsn");
  3223. }
  3224. #endif
  3225. #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33)
  3226. vc_resize_con(1, 1, 0);
  3227. #endif
  3228. TWDEBUG("Before calling register_framebuffer");
  3229. if(register_framebuffer(&sis_fb_info) < 0)
  3230. return -EINVAL;
  3231. printk(KERN_INFO "sisfb: Installed SISFB_GET_INFO ioctl (%x)n", SISFB_GET_INFO);
  3232. #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33)
  3233. printk(KERN_INFO "sisfb: 2D acceleration is %s, scrolling mode %sn",
  3234.      sisfb_accel ? "enabled" : "disabled",
  3235.      sisfb_ypan  ? "ypan" : "redraw");
  3236. #endif
  3237. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)
  3238. printk(KERN_INFO "sisfb: 2D acceleration is %sn",
  3239.      sisfb_accel ? "enabled" : "disabled");
  3240. #endif
  3241. printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02dn",
  3242.         GET_FB_IDX(sis_fb_info.node), sis_fb_info.modename, VER_MAJOR, VER_MINOR,
  3243.         VER_LEVEL);
  3244. } /* TW: if mode = "none" */
  3245. return 0;
  3246. }
  3247. /* ------------------------------------------------------------------------------ */
  3248. /* TW: As long as the generic framebuffer parts don't work as modules, we use
  3249.    our own stuff here. I can't debug a fb driver if I need to compile the driver
  3250.    into the kernel. It simply drives me nuts.
  3251.  */
  3252. #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,33)
  3253. #include <linux/version.h>
  3254. #include <linux/string.h>
  3255. #include <linux/fb.h>
  3256. #include <asm/types.h>
  3257. #include <video/fbcon.h>
  3258. void my_cfb_imageblit(struct fb_info *p, struct fb_image *image)
  3259. {
  3260. int pad, ppw;
  3261. int x2, y2, n, i, j, k, l = 7;
  3262. unsigned long tmp = ~0 << (BITS_PER_LONG - p->var.bits_per_pixel);
  3263. unsigned long fgx, bgx, fgcolor, bgcolor, eorx;
  3264. unsigned long end_mask;
  3265. unsigned long *dst = NULL;
  3266. u8 *dst1;
  3267. u8 *src;
  3268. /*
  3269.  * We could use hardware clipping but on many cards you get around hardware
  3270.  * clipping by writing to framebuffer directly like we are doing here.
  3271.  */
  3272. x2 = image->dx + image->width;
  3273. y2 = image->dy + image->height;
  3274. image->dx = image->dx > 0 ? image->dx : 0;
  3275. image->dy = image->dy > 0 ? image->dy : 0;
  3276. x2 = x2 < p->var.xres_virtual ? x2 : p->var.xres_virtual;
  3277. y2 = y2 < p->var.yres_virtual ? y2 : p->var.yres_virtual;
  3278. image->width  = x2 - image->dx;
  3279. image->height = y2 - image->dy;
  3280. dst1 = p->screen_base + image->dy * p->fix.line_length +
  3281. ((image->dx * p->var.bits_per_pixel) >> 3);
  3282. ppw = BITS_PER_LONG/p->var.bits_per_pixel;
  3283. src = image->data;
  3284. if (image->depth == 1) {
  3285. if (p->fix.visual == FB_VISUAL_TRUECOLOR) {
  3286. fgx = fgcolor = ((u32 *)(p->pseudo_palette))[image->fg_color];
  3287. bgx = bgcolor = ((u32 *)(p->pseudo_palette))[image->bg_color];
  3288. } else {
  3289. fgx = fgcolor = image->fg_color;
  3290. bgx = bgcolor = image->bg_color;
  3291. }
  3292. for (i = 0; i < ppw-1; i++) {
  3293. fgx <<= p->var.bits_per_pixel;
  3294. bgx <<= p->var.bits_per_pixel;
  3295. fgx |= fgcolor;
  3296. bgx |= bgcolor;
  3297. }
  3298. eorx = fgx ^ bgx;
  3299. n = ((image->width + 7) >> 3);
  3300. pad = (n << 3) - image->width;
  3301. n = image->width % ppw;
  3302. for (i = 0; i < image->height; i++) {
  3303. dst = (unsigned long *) dst1;
  3304. for (j = image->width/ppw; j > 0; j--) {
  3305. end_mask = 0;
  3306. for (k = ppw; k > 0; k--) {
  3307. if (test_bit(l, (unsigned long *) src))
  3308. end_mask |= (tmp >> (p->var.bits_per_pixel*(k-1)));
  3309. l--;
  3310. if (l < 0) { l = 7; src++; }
  3311. }
  3312. fb_writel((end_mask & eorx)^bgx, dst);
  3313. dst++;
  3314. }
  3315. if (n) {
  3316. end_mask = 0;
  3317. for (j = n; j > 0; j--) {
  3318. if (test_bit(l, (unsigned long *) src))
  3319. end_mask |= (tmp >> (p->var.bits_per_pixel*(j-1)));
  3320. l--;
  3321. if (l < 0) { l = 7; src++; }
  3322. }
  3323. fb_writel((end_mask & eorx)^bgx, dst);
  3324. dst++;
  3325. }
  3326. l -= pad;
  3327. dst1 += p->fix.line_length;
  3328. }
  3329. } else {
  3330. /* Draw the penguin */
  3331. n = ((image->width * p->var.bits_per_pixel) >> 3);
  3332. end_mask = 0;
  3333. }
  3334. }
  3335. #endif
  3336. /* -------------------------------------------------------------------------------- */
  3337. #ifdef MODULE
  3338. static char         *mode = NULL;
  3339. static int          vesa = -1;
  3340. static unsigned int rate = 0;
  3341. static unsigned int crt1off = 1;
  3342. static unsigned int mem = 0;
  3343. static unsigned int dstn = 0;
  3344. static char         *forcecrt2type = NULL;
  3345. static int          forcecrt1 = -1;
  3346. static char         *queuemode = NULL;
  3347. static int          pdc = 0;
  3348. static int          noaccel = -1;
  3349. static int          noypan  = -1;
  3350. static int          inverse = 0;
  3351. MODULE_DESCRIPTION("SiS 300/540/630/730/315/550/650/740 framebuffer driver");
  3352. MODULE_LICENSE("GPL");
  3353. MODULE_AUTHOR("Various; SiS; Thomas Winischhofer <thomas@winischhofer.net>");
  3354. MODULE_PARM(mode, "s");
  3355. MODULE_PARM_DESC(mode,
  3356.        "nSelects the desired display mode in the format [X]x[Y]x[Depth], eg.n"
  3357.          "800x600x16 (default: none if sisfb is a module; this leaves then"
  3358.  "console untouched and the driver will only do the video memoryn"
  3359.  "management for eg. DRM/DRI; 800x600x8 if sisfb is in the kernel)");
  3360. MODULE_PARM(vesa, "i");
  3361. MODULE_PARM_DESC(vesa,
  3362.        "nSelects the desired display mode by VESA defined mode number, eg. 0x117n"
  3363.          "(default: 0x0000 if sisfb is a module; this leaves the console untouchedn"
  3364.  "and the driver will only do the video memory management for eg. DRM/DRI;n"
  3365.  "0x0103 if sisfb is in the kernel)");
  3366. MODULE_PARM(rate, "i");
  3367. MODULE_PARM_DESC(rate,
  3368. "nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.n"
  3369. "(default: 60)");
  3370. MODULE_PARM(crt1off,   "i");
  3371. MODULE_PARM_DESC(crt1off,
  3372. "(Deprecated, please use forcecrt1)");
  3373. MODULE_PARM(filter, "i");
  3374. MODULE_PARM_DESC(filter,
  3375. "nSelects TV flicker filter type (only for systems with a SiS301 video bridge).n"
  3376.   "(Possible values 0-7, default: [no filter])");
  3377. MODULE_PARM(dstn,   "i"); /* JennyLee 20011211 */
  3378. MODULE_PARM_DESC(dstn,
  3379. "nSelects DSTN/FSTN display mode for SiS550. This sets CRT2 type to LCD andn"
  3380.   "overrides forcecrt2type setting. (1=ON, 0=OFF) (default: 0)");
  3381. MODULE_PARM(queuemode,   "s");
  3382. MODULE_PARM_DESC(queuemode,
  3383. "nSelects the queue mode on 315/550/650/740. Possible choices are AGP, VRAM orn"
  3384.      "MMIO. AGP is only available if the kernel has AGP support. The queue mode isn"
  3385.   "important to programs using the 2D/3D accelerator of the SiS chip. The modesn"
  3386.   "require a totally different way of programming the engines. If any mode thann"
  3387.   "MMIO is selected, sisfb will disable its own 2D acceleration. Onn"
  3388.   "300/540/630/730, this option is ignored. (default: MMIO)");
  3389. /* TW: "Import" the options from the X driver */
  3390. MODULE_PARM(mem,    "i");
  3391. MODULE_PARM_DESC(mem,
  3392. "nDetermines the beginning of the video memory heap in KB. This heap is usedn"
  3393.   "for video RAM management for eg. DRM/DRI. The default depends on the amountn"
  3394.   "of video RAM available. If 8MB of video RAM or less is available, the heapn"
  3395.   "starts at 4096KB, if between 8 and 16MB are available at 8192KB, otherwisen"
  3396.   "at 12288KB. The value is to be specified without 'KB' and should matchn"
  3397.   "the MaxXFBMem setting for XFree 4.x (x>=2).");
  3398. MODULE_PARM(forcecrt2type, "s");
  3399. MODULE_PARM_DESC(forcecrt2type,
  3400. "nIf this option is omitted, the driver autodetects CRT2 output devices, such asn"
  3401.   "LCD, TV or secondary VGA. With this option, this autodetection can ben"
  3402.   "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.n"
  3403.   "On systems with a 301(B) bridge, parameters SVIDEO, COMPOSITE or SCART can ben"
  3404.   "used instead of TV to override the TV detection. (default: [autodetected])");
  3405. MODULE_PARM(forcecrt1, "i");
  3406. MODULE_PARM_DESC(forcecrt1,
  3407. "nNormally, the driver autodetects whether or not CRT1 (external VGA) is n"
  3408.   "connected. With this option, the detection can be overridden (1=CRT1 ON,n"
  3409.   " 0=CRT1 off) (default: [autodetected])");
  3410. MODULE_PARM(pdc, "i");
  3411. MODULE_PARM_DESC(pdc,
  3412.         "n(300 series only) This is for manually selecting the LCD panel delayn"
  3413.   "compensation. The driver should detect this correctly in most cases; however,n"
  3414.   "sometimes this is not possible. If you see 'small waves' on the LCD, tryn"
  3415.   "setting this to 4, 32 or 24. If the problem persists, try other valuesn"
  3416.   "between 4 and 60 in steps of 4. (default: [autodetected])");
  3417. MODULE_PARM(noaccel, "i");
  3418. MODULE_PARM_DESC(noaccel,
  3419.         "nIf set to anything other than 0, 2D acceleration and y-panning will ben"
  3420. "disabled. (default: 0)");
  3421. MODULE_PARM(noypan, "i");
  3422. MODULE_PARM_DESC(noypan,
  3423.         "nIf set to anything other than 0, y-panning will be disabled and scrollingn"
  3424. "will be performed by redrawing the screen. This required 2D acceleration, son"
  3425. "if the option noaccel is set, y-panning will be disabled. (default: 0)");
  3426. MODULE_PARM(inverse, "i");
  3427. MODULE_PARM_DESC(inverse,
  3428.         "nSetting this to anything but 0 should invert the display colors, but thisn"
  3429. "does not seem to work. (default: 0)");
  3430. int init_module(void)
  3431. {
  3432. if(mode)
  3433. sisfb_search_mode(mode);
  3434. else if(vesa != -1)
  3435. sisfb_search_vesamode(vesa);
  3436. else  /* TW: set mode=none if no mode is given - we do this only if we are a module */
  3437. sisfb_mode_idx = MODE_INDEX_NONE;
  3438. ivideo.refresh_rate = rate;
  3439. if(forcecrt2type)
  3440. sisfb_search_crt2type(forcecrt2type);
  3441. if(crt1off == 0)
  3442. sisfb_crt1off = 1;
  3443. else
  3444. sisfb_crt1off = 0;
  3445. sisfb_forcecrt1 = forcecrt1;
  3446. if(forcecrt1 == 1)
  3447. sisfb_crt1off = 0;
  3448. else if(forcecrt1 == 0)
  3449. sisfb_crt1off = 1;
  3450. if(noaccel == 1)      sisfb_accel = 0;
  3451. else if(noaccel == 0) sisfb_accel = 1;
  3452. if(noypan == 1)       sisfb_ypan = 0;
  3453. else if(noypan == 0)  sisfb_ypan = 1;
  3454. /* TW: Panning only with acceleration */
  3455. if(sisfb_accel == 0)  sisfb_ypan = 0;
  3456. if(inverse)           sisfb_inverse = 1;
  3457. if(mem)       sisfb_mem = mem;
  3458. enable_dstn = dstn;
  3459. /* TW: DSTN overrules forcecrt2type */
  3460. if (enable_dstn)      sisfb_crt2type = DISPTYPE_LCD;
  3461. if (queuemode)        sisfb_search_queuemode(queuemode);
  3462. /* TW: If other queuemode than MMIO, disable 2D accel any ypan */
  3463. if((sisfb_queuemode != -1) && (sisfb_queuemode != MMIO_CMD)) {
  3464.         sisfb_accel = 0;
  3465. sisfb_ypan = 0;
  3466. }
  3467.         if(pdc) {
  3468.    if(!(pdc & ~0x3c)) {
  3469.         sisfb_pdc = pdc & 0x3c;
  3470.    }
  3471. }
  3472. if(sisfb_init() < 0) return -ENODEV;
  3473. return 0;
  3474. }
  3475. void cleanup_module(void)
  3476. {
  3477. /* TW: Release mem regions */
  3478. release_mem_region(ivideo.video_base, ivideo.video_size);
  3479. release_mem_region(ivideo.mmio_base, sisfb_mmio_size);
  3480. #ifdef CONFIG_MTRR
  3481. /* TW: Release MTRR region */
  3482. if(ivideo.mtrr) mtrr_del(ivideo.mtrr,
  3483.       (unsigned int)ivideo.video_base,
  3484.                       (unsigned int)ivideo.video_size);
  3485. #endif
  3486. /* Unregister the framebuffer */
  3487. unregister_framebuffer(&sis_fb_info);
  3488. printk(KERN_INFO "sisfb: Module unloadedn");
  3489. }
  3490. #endif
  3491. EXPORT_SYMBOL(sis_malloc);
  3492. EXPORT_SYMBOL(sis_free);
  3493. EXPORT_SYMBOL(sis_dispinfo);
  3494. EXPORT_SYMBOL(ivideo);
  3495.