sis_main.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:65k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * SiS 300/630/540/315H/315 frame buffer device For Kernal 2.4.x
  3.  *
  4.  * This driver is partly based on the VBE 2.0 compliant graphic 
  5.  * boards framebuffer driver, which is 
  6.  * 
  7.  * (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
  8.  *
  9.  */
  10. //#undef SISFBDEBUG
  11. #include <linux/config.h>
  12. #include <linux/module.h>
  13. #include <linux/kernel.h>
  14. #include <linux/errno.h>
  15. #include <linux/string.h>
  16. #include <linux/mm.h>
  17. #include <linux/tty.h>
  18. #include <linux/slab.h>
  19. #include <linux/delay.h>
  20. #include <linux/fb.h>
  21. #include <linux/console.h>
  22. #include <linux/selection.h>
  23. #include <linux/ioport.h>
  24. #include <linux/init.h>
  25. #include <linux/pci.h>
  26. #include <linux/vt_kern.h>
  27. #include <linux/capability.h>
  28. #include <linux/fs.h>
  29. #include <linux/agp_backend.h>
  30. #include <linux/types.h>
  31. #include <linux/sisfb.h>
  32. #include <asm/io.h>
  33. #include <asm/mtrr.h>
  34. #include <video/fbcon.h>
  35. #include <video/fbcon-cfb8.h>
  36. #include <video/fbcon-cfb16.h>
  37. #include <video/fbcon-cfb24.h>
  38. #include <video/fbcon-cfb32.h>
  39. #include "osdef.h"
  40. #include "vgatypes.h"
  41. #include "sis_main.h"
  42. /* -------------------- Macro definitions ---------------------------- */
  43. #ifdef SISFBDEBUG
  44. #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
  45. #else
  46. #define DPRINTK(fmt, args...)
  47. #endif
  48. #define vgawb(reg,data) 
  49.            (outb(data, ivideo.vga_base+reg))
  50. #define vgaww(reg,data) 
  51.            (outw(data, ivideo.vga_base+reg))
  52. #define vgawl(reg,data) 
  53.            (outl(data, ivideo.vga_base+reg))
  54. #define vgarb(reg)      
  55.            (inb(ivideo.vga_base+reg))
  56. /* --------------- Hardware Access Routines -------------------------- */
  57. void sisfb_set_reg1 (u16 port, u16 index, u16 data)
  58. {
  59. outb ((u8) (index & 0xff), port);
  60. port++;
  61. outb ((u8) (data & 0xff), port);
  62. }
  63. void sisfb_set_reg3 (u16 port, u16 data)
  64. {
  65. outb ((u8) (data & 0xff), port);
  66. }
  67. void sisfb_set_reg4 (u16 port, unsigned long data)
  68. {
  69. outl ((u32) (data & 0xffffffff), port);
  70. }
  71. u8 sisfb_get_reg1 (u16 port, u16 index)
  72. {
  73. u8 data;
  74. outb ((u8) (index & 0xff), port);
  75. port += 1;
  76. data = inb (port);
  77. return (data);
  78. }
  79. u8 sisfb_get_reg2 (u16 port)
  80. {
  81. u8 data;
  82. data = inb (port);
  83. return (data);
  84. }
  85. u32 sisfb_get_reg3 (u16 port)
  86. {
  87. u32 data;
  88. data = inl (port);
  89. return (data);
  90. }
  91. /* --------------- Interface to BIOS code ---------------------------- */
  92. BOOLEAN sisfb_query_VGA_config_space (PSIS_HW_DEVICE_INFO psishw_ext,
  93.       unsigned long offset, unsigned long set,
  94.       unsigned long *value)
  95. {
  96. static struct pci_dev *pdev = NULL;
  97. static unsigned char init = 0, valid_pdev = 0;
  98. if (!set)
  99. DPRINTK ("Get VGA offset 0x%lxn", offset);
  100. else
  101. DPRINTK ("Set offset 0x%lx to 0x%lxn", offset, *value);
  102. if (!init) {
  103. init = TRUE;
  104. pci_for_each_dev (pdev) {
  105. DPRINTK ("Current: 0x%x, target: 0x%xn", pdev->device,
  106.  ivideo.chip_id);
  107. if ((pdev->vendor == PCI_VENDOR_ID_SI)
  108.     && (pdev->device == ivideo.chip_id)) {
  109. valid_pdev = TRUE;
  110. break;
  111. }
  112. }
  113. }
  114. if (!valid_pdev) {
  115. printk (KERN_DEBUG "Can't find SiS %d VGA device.n",
  116. ivideo.chip_id);
  117. return FALSE;
  118. }
  119. if (set == 0)
  120. pci_read_config_dword (pdev, offset, (u32 *) value);
  121. else
  122. pci_write_config_dword (pdev, offset, (u32) (*value));
  123. return TRUE;
  124. }
  125. BOOLEAN sisfb_query_north_bridge_space (PSIS_HW_DEVICE_INFO psishw_ext,
  126. unsigned long offset, unsigned long set,
  127. unsigned long *value)
  128. {
  129. static struct pci_dev *pdev = NULL;
  130. static unsigned char init = 0, valid_pdev = 0;
  131. u16 nbridge_id = 0;
  132. if (!init) {
  133. init = TRUE;
  134. switch (ivideo.chip) {
  135. case SIS_540:
  136. nbridge_id = PCI_DEVICE_ID_SI_540;
  137. break;
  138. case SIS_630:
  139. nbridge_id = PCI_DEVICE_ID_SI_630;
  140. break;
  141. case SIS_730:
  142. nbridge_id = PCI_DEVICE_ID_SI_730;
  143. break;
  144. case SIS_550:
  145. nbridge_id = PCI_DEVICE_ID_SI_550;
  146. break;
  147. default:
  148. nbridge_id = 0;
  149. break;
  150. }
  151. pci_for_each_dev (pdev) {
  152. DPRINTK ("Current: 0x%x, target: 0x%xn", pdev->device,
  153.  ivideo.chip_id);
  154. if ((pdev->vendor == PCI_VENDOR_ID_SI)
  155.     && (pdev->device == nbridge_id)) {
  156. valid_pdev = TRUE;
  157. break;
  158. }
  159. }
  160. }
  161. if (!valid_pdev) {
  162. printk (KERN_DEBUG "Can't find SiS %d North Bridge device.n",
  163. nbridge_id);
  164. return FALSE;
  165. }
  166. if (set == 0)
  167. pci_read_config_dword (pdev, offset, (u32 *) value);
  168. else
  169. pci_write_config_dword (pdev, offset, (u32) (*value));
  170. return TRUE;
  171. }
  172. /* -------------------- Export functions ----------------------------- */
  173. static void sis_get_glyph (SIS_GLYINFO * gly)
  174. {
  175. struct display *p = &fb_display[currcon];
  176. u16 c;
  177. u8 *cdat;
  178. int widthb;
  179. u8 *gbuf = gly->gmask;
  180. int size;
  181. gly->fontheight = fontheight (p);
  182. gly->fontwidth = fontwidth (p);
  183. widthb = (fontwidth (p) + 7) / 8;
  184. c = gly->ch & p->charmask;
  185. if (fontwidth (p) <= 8)
  186. cdat = p->fontdata + c * fontheight (p);
  187. else
  188. cdat = p->fontdata + (c * fontheight (p) << 1);
  189. size = fontheight (p) * widthb;
  190. memcpy (gbuf, cdat, size);
  191. gly->ngmask = size;
  192. }
  193. void sis_dispinfo (struct ap_data *rec)
  194. {
  195. rec->minfo.bpp = ivideo.video_bpp;
  196. rec->minfo.xres = ivideo.video_width;
  197. rec->minfo.yres = ivideo.video_height;
  198. rec->minfo.v_xres = ivideo.video_vwidth;
  199. rec->minfo.v_yres = ivideo.video_vheight;
  200. rec->minfo.org_x = ivideo.org_x;
  201. rec->minfo.org_y = ivideo.org_y;
  202. rec->minfo.vrate = ivideo.refresh_rate;
  203. rec->iobase = ivideo.vga_base - 0x30;
  204. rec->mem_size = ivideo.video_size;
  205. rec->disp_state = ivideo.disp_state;
  206. rec->version = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL;
  207. rec->hasVB = ivideo.hasVB;
  208. rec->TV_type = ivideo.TV_type;
  209. rec->TV_plug = ivideo.TV_plug;
  210. rec->chip = ivideo.chip;
  211. }
  212. /* ------------------ Internal Routines ------------------------------ */
  213. static void sisfb_search_mode (const char *name)
  214. {
  215. int i = 0;
  216. if (name == NULL)
  217. return;
  218. while (sisbios_mode[i].mode_no != 0) {
  219. if (!strcmp (name, sisbios_mode[i].name)) {
  220. sisfb_mode_idx = i;
  221. break;
  222. }
  223. i++;
  224. }
  225. if (sisfb_mode_idx < 0)
  226. DPRINTK ("Invalid user mode : %sn", name);
  227. }
  228. static void sisfb_validate_mode (void)
  229. {
  230. switch (ivideo.disp_state & DISPTYPE_DISP2) {
  231. case DISPTYPE_LCD:
  232. // Eden Chen
  233. switch (sishw_ext.ulCRT2LCDType) {
  234. case LCD_1024x768:
  235. if (sisbios_mode[sisfb_mode_idx].xres > 1024)
  236. sisfb_mode_idx = -1;
  237. break;
  238. case LCD_1280x1024:
  239. case LCD_1280x960:
  240. if (sisbios_mode[sisfb_mode_idx].xres > 1280)
  241. sisfb_mode_idx = -1;
  242. break;
  243. case LCD_2048x1536:
  244. if (sisbios_mode[sisfb_mode_idx].xres > 2048)
  245. sisfb_mode_idx = -1;
  246. break;
  247. case LCD_1920x1440:
  248. if (sisbios_mode[sisfb_mode_idx].xres > 1920)
  249. sisfb_mode_idx = -1;
  250. break;
  251. case LCD_1600x1200:
  252. if (sisbios_mode[sisfb_mode_idx].xres > 1600)
  253. sisfb_mode_idx = -1;
  254. break;
  255. case LCD_800x600:
  256. if (sisbios_mode[sisfb_mode_idx].xres > 800)
  257. sisfb_mode_idx = -1;
  258. break;
  259. case LCD_640x480:
  260. if (sisbios_mode[sisfb_mode_idx].xres > 640)
  261. sisfb_mode_idx = -1;
  262. break;
  263. default:
  264. sisfb_mode_idx = -1;
  265. }
  266. // ~Eden Chen
  267. if (sisbios_mode[sisfb_mode_idx].xres == 720)
  268. sisfb_mode_idx = -1;
  269. break;
  270. case DISPTYPE_TV:
  271. switch (sisbios_mode[sisfb_mode_idx].xres) {
  272. case 800:
  273. case 640:
  274. break;
  275. case 720:
  276. if (ivideo.TV_type == TVMODE_NTSC) {
  277. if (sisbios_mode[sisfb_mode_idx].yres != 480)
  278. sisfb_mode_idx = -1;
  279. } else if (ivideo.TV_type == TVMODE_PAL) {
  280. if (sisbios_mode[sisfb_mode_idx].yres != 576)
  281. sisfb_mode_idx = -1;
  282. }
  283. break;
  284. /*karl */
  285. case 1024:
  286. if (ivideo.TV_type == TVMODE_NTSC) {
  287. if (sisbios_mode[sisfb_mode_idx].bpp == 32)
  288. sisfb_mode_idx -= 1;
  289. }
  290. break;
  291. default:
  292. sisfb_mode_idx = -1;
  293. }
  294. break;
  295. }
  296. }
  297. static u8 sisfb_search_refresh_rate (unsigned int rate)
  298. {
  299. u16 xres, yres;
  300. int i = 0;
  301. xres = sisbios_mode[sisfb_mode_idx].xres;
  302. yres = sisbios_mode[sisfb_mode_idx].yres;
  303. sisfb_rate_idx = 0;
  304. while ((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
  305. if ((sisfb_vrate[i].xres == xres)
  306.     && (sisfb_vrate[i].yres == yres)) {
  307. if (sisfb_vrate[i].refresh == rate) {
  308. sisfb_rate_idx = sisfb_vrate[i].idx;
  309. break;
  310. } else if (sisfb_vrate[i].refresh > rate) {
  311. if ((sisfb_vrate[i].refresh - rate) <= 2) {
  312. DPRINTK
  313.     ("Adjust rate from %d up to %dn",
  314.      rate, sisfb_vrate[i].refresh);
  315. sisfb_rate_idx = sisfb_vrate[i].idx;
  316. ivideo.refresh_rate =
  317.     sisfb_vrate[i].refresh;
  318. } else if (((rate - sisfb_vrate[i - 1].refresh) <=  2) 
  319.      && (sisfb_vrate[i].idx != 1)) {
  320. DPRINTK("Adjust rate from %d down to %dn",
  321.      rate, sisfb_vrate[i - 1].refresh);
  322. sisfb_rate_idx = sisfb_vrate[i - 1].idx;
  323. ivideo.refresh_rate = sisfb_vrate[i - 1].refresh;
  324. }
  325. break;
  326. }
  327. }
  328. i++;
  329. }
  330. if (sisfb_rate_idx > 0) {
  331. return sisfb_rate_idx;
  332. } else {
  333. DPRINTK ("Unsupported rate %d for %dx%d moden", rate, xres,
  334.  yres);
  335. return 0;
  336. }
  337. }
  338. static int sis_getcolreg (unsigned regno, unsigned *red, unsigned *green, unsigned *blue,
  339.        unsigned *transp, struct fb_info *fb_info)
  340. {
  341. if (regno >= video_cmap_len)
  342. return 1;
  343. *red = palette[regno].red;
  344. *green = palette[regno].green;
  345. *blue = palette[regno].blue;
  346. *transp = 0;
  347. return 0;
  348. }
  349. static int sis_setcolreg (unsigned regno, unsigned red, unsigned green, unsigned blue,
  350.        unsigned transp, struct fb_info *fb_info)
  351. {
  352. if (regno >= video_cmap_len)
  353. return 1;
  354. palette[regno].red = red;
  355. palette[regno].green = green;
  356. palette[regno].blue = blue;
  357. switch (ivideo.video_bpp) {
  358. #ifdef FBCON_HAS_CFB8
  359. case 8:
  360. vgawb (DAC_ADR, regno);
  361. vgawb (DAC_DATA, red >> 10);
  362. vgawb (DAC_DATA, green >> 10);
  363. vgawb (DAC_DATA, blue >> 10);
  364. if (ivideo.disp_state & DISPTYPE_DISP2) {
  365. vgawb (DAC2_ADR, regno);
  366. vgawb (DAC2_DATA, red >> 8);
  367. vgawb (DAC2_DATA, green >> 8);
  368. vgawb (DAC2_DATA, blue >> 8);
  369. }
  370. break;
  371. #endif
  372. #ifdef FBCON_HAS_CFB16
  373. case 15:
  374. case 16:
  375. fbcon_cmap.cfb16[regno] =
  376.     ((red & 0xf800)) |
  377.     ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
  378. break;
  379. #endif
  380. #ifdef FBCON_HAS_CFB24
  381. case 24:
  382. red >>= 8;
  383. green >>= 8;
  384. blue >>= 8;
  385. fbcon_cmap.cfb24[regno] = (red << 16) | (green << 8) | (blue);
  386. break;
  387. #endif
  388. #ifdef FBCON_HAS_CFB32
  389. case 32:
  390. red >>= 8;
  391. green >>= 8;
  392. blue >>= 8;
  393. fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | (blue);
  394. break;
  395. #endif
  396. }
  397. return 0;
  398. }
  399. static int sisfb_do_set_var (struct fb_var_screeninfo *var, int isactive,
  400.   struct fb_info *info)
  401. {
  402. unsigned int htotal =
  403.     var->left_margin + var->xres + var->right_margin + var->hsync_len;
  404. unsigned int vtotal =
  405.     var->upper_margin + var->yres + var->lower_margin + var->vsync_len;
  406. double drate = 0, hrate = 0;
  407. int found_mode = 0;
  408. int old_mode;
  409. if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
  410. vtotal <<= 1;
  411. else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
  412. vtotal <<= 2;
  413. else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
  414. var->yres <<= 1;
  415. if (!htotal || !vtotal) {
  416. DPRINTK ("Invalid 'var' Information!n");
  417. return -EINVAL;
  418. }
  419. drate = 1E12 / var->pixclock;
  420. hrate = drate / htotal;
  421. ivideo.refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
  422. DPRINTK ("Chagne mode to %dx%dx%d-%dMHzn",
  423.  var->xres, var->yres, var->bits_per_pixel,
  424.  ivideo.refresh_rate);
  425. old_mode = sisfb_mode_idx;
  426. sisfb_mode_idx = 0;
  427. while ((sisbios_mode[sisfb_mode_idx].mode_no != 0)
  428.        && (sisbios_mode[sisfb_mode_idx].xres <= var->xres)) {
  429. if ((sisbios_mode[sisfb_mode_idx].xres == var->xres)
  430.     && (sisbios_mode[sisfb_mode_idx].yres == var->yres)
  431.     && (sisbios_mode[sisfb_mode_idx].bpp ==
  432. var->bits_per_pixel)) {
  433. sisfb_mode_no = sisbios_mode[sisfb_mode_idx].mode_no;
  434. found_mode = 1;
  435. break;
  436. }
  437. sisfb_mode_idx++;
  438. }
  439. if (found_mode)
  440. sisfb_validate_mode ();
  441. else
  442. sisfb_mode_idx = -1;
  443. if (sisfb_mode_idx < 0) {
  444. DPRINTK ("sisfb does not support mode %dx%d-%dn", var->xres,
  445.  var->yres, var->bits_per_pixel);
  446. sisfb_mode_idx = old_mode;
  447. return -EINVAL;
  448. }
  449. if (sisfb_search_refresh_rate (ivideo.refresh_rate) == 0) {
  450. sisfb_rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;
  451. ivideo.refresh_rate = 60;
  452. }
  453. if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) {
  454. sisfb_pre_setmode ();
  455. // Eden Chen
  456. /*
  457. #ifdef CONFIG_FB_SIS_300
  458. if (SiSSetMode(&sishw_ext, sisfb_mode_no)) {
  459. DPRINTK("set mode[0x%x]: failedn", sisfb_mode_no);
  460. return -1;
  461. }
  462. #endif
  463. #ifdef CONFIG_FB_SIS_315
  464. if (SiSSetMode310(&sishw_ext, sisfb_mode_no)) {
  465. DPRINTK("set mode[0x%x]: failedn", sisfb_mode_no);
  466. return -1;
  467. }
  468. #endif
  469. */
  470. if (SiSSetMode (&sishw_ext, sisfb_mode_no) == 0) {
  471. DPRINTK ("set mode[0x%x]: failedn", sisfb_mode_no);
  472. return -1;
  473. }
  474. vgawb (SEQ_ADR, IND_SIS_PASSWORD);
  475. vgawb (SEQ_DATA, SIS_PASSWORD);
  476. // ~Eden Chen
  477. sisfb_post_setmode ();
  478. DPRINTK ("Set New Mode : %dx%dx%d-%d n",
  479.  sisbios_mode[sisfb_mode_idx].xres,
  480.  sisbios_mode[sisfb_mode_idx].yres,
  481.  sisbios_mode[sisfb_mode_idx].bpp, ivideo.refresh_rate);
  482. ivideo.video_bpp = sisbios_mode[sisfb_mode_idx].bpp;
  483. ivideo.video_vwidth = ivideo.video_width =
  484.     sisbios_mode[sisfb_mode_idx].xres;
  485. ivideo.video_vheight = ivideo.video_height =
  486.     sisbios_mode[sisfb_mode_idx].yres;
  487. ivideo.org_x = ivideo.org_y = 0;
  488. video_linelength = ivideo.video_width * (ivideo.video_bpp >> 3);
  489. }
  490. return 0;
  491. }
  492. static void sisfb_set_disp (int con, struct fb_var_screeninfo *var)
  493. {
  494. struct fb_fix_screeninfo fix;
  495. struct display *display;
  496. struct display_switch *sw;
  497. u32 flags;
  498. if (con >= 0)
  499. display = &fb_display[con];
  500. else
  501. display = &disp;
  502. sisfb_get_fix (&fix, con, 0);
  503. display->screen_base = ivideo.video_vbase;
  504. display->visual = fix.visual;
  505. display->type = fix.type;
  506. display->type_aux = fix.type_aux;
  507. display->ypanstep = fix.ypanstep;
  508. display->ywrapstep = fix.ywrapstep;
  509. display->line_length = fix.line_length;
  510. display->next_line = fix.line_length;
  511. display->can_soft_blank = 0;
  512. display->inverse = sisfb_inverse;
  513. display->var = *var;
  514. save_flags (flags);
  515. switch (ivideo.video_bpp) {
  516. #ifdef FBCON_HAS_CFB8
  517. case 8:
  518. sw = &fbcon_cfb8;
  519. break;
  520. #endif
  521. #ifdef FBCON_HAS_CFB16
  522. case 15:
  523. case 16:
  524. sw = &fbcon_cfb16;
  525. display->dispsw_data = fbcon_cmap.cfb16;
  526. break;
  527. #endif
  528. #ifdef FBCON_HAS_CFB24
  529. case 24:
  530. sw = &fbcon_cfb24;
  531. display->dispsw_data = fbcon_cmap.cfb24;
  532. break;
  533. #endif
  534. #ifdef FBCON_HAS_CFB32
  535. case 32:
  536. sw = &fbcon_cfb32;
  537. display->dispsw_data = fbcon_cmap.cfb32;
  538. break;
  539. #endif
  540. default:
  541. sw = &fbcon_dummy;
  542. return;
  543. }
  544. memcpy (&sisfb_sw, sw, sizeof (*sw));
  545. display->dispsw = &sisfb_sw;
  546. restore_flags (flags);
  547. display->scrollmode = SCROLL_YREDRAW;
  548. sisfb_sw.bmove = fbcon_redraw_bmove;
  549. }
  550. static void sisfb_do_install_cmap (int con, struct fb_info *info)
  551. {
  552. if (con != currcon)
  553. return;
  554. if (fb_display[con].cmap.len)
  555. fb_set_cmap (&fb_display[con].cmap, 1, sis_setcolreg, info);
  556. else
  557. fb_set_cmap (fb_default_cmap (video_cmap_len), 1,
  558.      sis_setcolreg, info);
  559. }
  560. /* --------------- Chip-dependent Routines --------------------------- */
  561. #ifdef CONFIG_FB_SIS_300 /* for SiS 300/630/540/730 */
  562. static int sisfb_get_dram_size_300 (void)
  563. {
  564. struct pci_dev *pdev = NULL;
  565. int pdev_valid = 0;
  566. u8 pci_data, reg;
  567. u16 nbridge_id;
  568. switch (ivideo.chip) {
  569. case SIS_540:
  570. nbridge_id = PCI_DEVICE_ID_SI_540;
  571. break;
  572. case SIS_630:
  573. nbridge_id = PCI_DEVICE_ID_SI_630;
  574. break;
  575. case SIS_730:
  576. nbridge_id = PCI_DEVICE_ID_SI_730;
  577. break;
  578. default:
  579. nbridge_id = 0;
  580. break;
  581. }
  582. if (nbridge_id == 0) {
  583. vgawb (SEQ_ADR, IND_SIS_DRAM_SIZE);
  584. ivideo.video_size =
  585.     ((unsigned
  586.       int) ((vgarb (SEQ_DATA) & SIS_DRAM_SIZE_MASK) + 1) << 20);
  587. } else {
  588. pci_for_each_dev (pdev) {
  589. if ((pdev->vendor == PCI_VENDOR_ID_SI)
  590.     && (pdev->device == nbridge_id)) {
  591. //&& (pdev->device == PCI_DEVICE_ID_SI_630)) {
  592. pci_read_config_byte (pdev, IND_BRI_DRAM_STATUS,
  593.       &pci_data);
  594. pci_data = (pci_data & BRI_DRAM_SIZE_MASK) >> 4;
  595. ivideo.video_size =
  596.     (unsigned int) (1 << (pci_data + 21));
  597. pdev_valid = 1;
  598. reg = SIS_DATA_BUS_64 << 6;
  599. vgawb (SEQ_ADR, IND_SIS_DRAM_SIZE);
  600. switch (pci_data) {
  601. case BRI_DRAM_SIZE_2MB:
  602. reg |= SIS_DRAM_SIZE_2MB;
  603. break;
  604. case BRI_DRAM_SIZE_4MB:
  605. reg |= SIS_DRAM_SIZE_4MB;
  606. break;
  607. case BRI_DRAM_SIZE_8MB:
  608. reg |= SIS_DRAM_SIZE_8MB;
  609. break;
  610. case BRI_DRAM_SIZE_16MB:
  611. reg |= SIS_DRAM_SIZE_16MB;
  612. break;
  613. case BRI_DRAM_SIZE_32MB:
  614. reg |= SIS_DRAM_SIZE_32MB;
  615. break;
  616. case BRI_DRAM_SIZE_64MB:
  617. reg |= SIS_DRAM_SIZE_64MB;
  618. break;
  619. }
  620. vgawb (SEQ_DATA, reg);
  621. break;
  622. }
  623. }
  624. if (!pdev_valid)
  625. return -1;
  626. }
  627. return 0;
  628. }
  629. static void sisfb_detect_VB_connect_300(void)
  630. {
  631. u8 sr16, sr17, cr32, temp;
  632. vgawb (SEQ_ADR, IND_SIS_SCRATCH_REG_17);
  633. sr17 = vgarb (SEQ_DATA);
  634. vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR32);
  635. cr32 = vgarb (CRTC_DATA);
  636. ivideo.TV_plug = ivideo.TV_type = 0;
  637. if ((sr17 & 0x0F) && (ivideo.chip != SIS_300)) {
  638. if ((sr17 & 0x01) && !sisfb_crt1off)
  639. sisfb_crt1off = 0;
  640. else {
  641. if (sr17 & 0x0E)
  642. sisfb_crt1off = 1;
  643. else
  644. sisfb_crt1off = 0;
  645. }
  646. if (sr17 & 0x08)
  647. ivideo.disp_state = DISPTYPE_CRT2;
  648. else if (sr17 & 0x02)
  649. ivideo.disp_state = DISPTYPE_LCD;
  650. else if (sr17 & 0x04) {
  651. ivideo.disp_state = DISPTYPE_TV;
  652. if (sr17 & 0x20)
  653. ivideo.TV_plug = TVPLUG_SVIDEO;
  654. else if (sr17 & 0x10)
  655. ivideo.TV_plug = TVPLUG_COMPOSITE;
  656. vgawb (SEQ_ADR, IND_SIS_SCRATCH_REG_16);
  657. sr16 = vgarb (SEQ_DATA);
  658. if (sr16 & 0x20)
  659. ivideo.TV_type = TVMODE_PAL;
  660. else
  661. ivideo.TV_type = TVMODE_NTSC;
  662. } else
  663. ivideo.disp_state = 0;
  664. } else {
  665. if ((cr32 & SIS_CRT1) && !sisfb_crt1off)
  666. sisfb_crt1off = 0;
  667. else {
  668. if (cr32 & 0x5F)
  669. sisfb_crt1off = 1;
  670. else
  671. sisfb_crt1off = 0;
  672. }
  673. if (cr32 & SIS_VB_CRT2)
  674. ivideo.disp_state = DISPTYPE_CRT2;
  675. else if (cr32 & SIS_VB_LCD)
  676. ivideo.disp_state = DISPTYPE_LCD;
  677. else if (cr32 & SIS_VB_TV) {
  678. ivideo.disp_state = DISPTYPE_TV;
  679. if (cr32 & SIS_VB_HIVISION) {
  680. ivideo.TV_type = TVMODE_HIVISION;
  681. ivideo.TV_plug = TVPLUG_SVIDEO;
  682. } else if (cr32 & SIS_VB_SVIDEO)
  683. ivideo.TV_plug = TVPLUG_SVIDEO;
  684. else if (cr32 & SIS_VB_COMPOSITE)
  685. ivideo.TV_plug = TVPLUG_COMPOSITE;
  686. else if (cr32 & SIS_VB_SCART)
  687. ivideo.TV_plug = TVPLUG_SCART;
  688. if (ivideo.TV_type == 0) {
  689. // Eden Chen
  690. //temp = *((u8 *)(sishw_ext.VirtualRomBase+0x52));
  691. //if (temp&0x40) {
  692. //      temp=*((u8 *)(sishw_ext.VirtualRomBase+0x53));
  693. //} else {
  694. vgawb (SEQ_ADR, IND_SIS_POWER_ON_TRAP);
  695. temp = vgarb (SEQ_DATA);
  696. //}
  697. // ~Eden Chen
  698. if (temp & 0x01)
  699. ivideo.TV_type = TVMODE_PAL;
  700. else
  701. ivideo.TV_type = TVMODE_NTSC;
  702. }
  703. } else
  704. ivideo.disp_state = 0;
  705. }
  706. }
  707. static void sisfb_get_VB_type_300 (void)
  708. {
  709. u8 reg;
  710. if (ivideo.chip != SIS_300) {
  711. if (!sisfb_has_VB_300 ()) {
  712. vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR37);
  713. reg = vgarb (CRTC_DATA);
  714. switch ((reg & SIS_EXTERNAL_CHIP_MASK) >> 1) {
  715. case SIS_EXTERNAL_CHIP_SIS301:
  716. ivideo.hasVB = HASVB_301;
  717. break;
  718. case SIS_EXTERNAL_CHIP_LVDS:
  719. ivideo.hasVB = HASVB_LVDS;
  720. break;
  721. case SIS_EXTERNAL_CHIP_TRUMPION:
  722. ivideo.hasVB = HASVB_TRUMPION;
  723. break;
  724. case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
  725. ivideo.hasVB = HASVB_LVDS_CHRONTEL;
  726. break;
  727. case SIS_EXTERNAL_CHIP_CHRONTEL:
  728. ivideo.hasVB = HASVB_CHRONTEL;
  729. break;
  730. default:
  731. break;
  732. }
  733. }
  734. } else {
  735. sisfb_has_VB_300 ();
  736. }
  737. //sishw_ext.hasVB = ivideo.hasVB;
  738. }
  739. static int sisfb_has_VB_300 (void)
  740. {
  741. // Eden Chen
  742. //u8 sr38, sr39, vb_chipid;
  743. u8 vb_chipid;
  744. //vgawb(SEQ_ADR, IND_SIS_POWER_ON_TRAP);
  745. //sr38 = vgarb(SEQ_DATA);
  746. //vgawb(SEQ_ADR, IND_SIS_POWER_ON_TRAP2);
  747. //sr39 = vgarb(SEQ_DATA);
  748. vgawb (VB_PART4_ADR, 0x0);
  749. vb_chipid = vgarb (VB_PART4_DATA);
  750. switch (vb_chipid) {
  751. case 0x01:
  752. ivideo.hasVB = HASVB_301;
  753. break;
  754. case 0x02:
  755. ivideo.hasVB = HASVB_302;
  756. break;
  757. case 0x03:
  758. ivideo.hasVB = HASVB_303;
  759. break;
  760. default:
  761. ivideo.hasVB = HASVB_NONE;
  762. return FALSE;
  763. }
  764. return TRUE;
  765. }
  766. #endif /* CONFIG_FB_SIS_300 */
  767. #ifdef CONFIG_FB_SIS_315 /* for SiS 315H/315 */
  768. static int sisfb_get_dram_size_315 (void)
  769. {
  770. #ifdef LINUXBIOS
  771. struct pci_dev *pdev = NULL;
  772. int pdev_valid = 0;
  773. u8 pci_data;
  774. #endif
  775. u8 reg = 0;
  776. if (ivideo.chip == SIS_550) {
  777. #ifdef LINUXBIOS
  778. pci_for_each_dev (pdev) {
  779. if ((pdev->vendor == PCI_VENDOR_ID_SI)
  780.     && (pdev->device == PCI_DEVICE_ID_SI_550)) {
  781. pci_read_config_byte (pdev, IND_BRI_DRAM_STATUS,
  782.       &pci_data);
  783. pci_data = (pci_data & BRI_DRAM_SIZE_MASK) >> 4;
  784. ivideo.video_size =
  785.     (unsigned int) (1 << (pci_data + 21));
  786. pdev_valid = 1;
  787. vgawb (SEQ_ADR, IND_SIS_DRAM_SIZE);
  788. reg = vgarb (SEQ_DATA) & 0xC0;
  789. switch (pci_data) {
  790. //case BRI_DRAM_SIZE_2MB:
  791. //      reg |= (SIS315_DRAM_SIZE_2MB << 4); break;
  792. case BRI_DRAM_SIZE_4MB:
  793. reg |= SIS550_DRAM_SIZE_4MB;
  794. break;
  795. case BRI_DRAM_SIZE_8MB:
  796. reg |= SIS550_DRAM_SIZE_8MB;
  797. break;
  798. case BRI_DRAM_SIZE_16MB:
  799. reg |= SIS550_DRAM_SIZE_16MB;
  800. break;
  801. case BRI_DRAM_SIZE_32MB:
  802. reg |= SIS550_DRAM_SIZE_32MB;
  803. break;
  804. case BRI_DRAM_SIZE_64MB:
  805. reg |= SIS550_DRAM_SIZE_64MB;
  806. break;
  807. /* case BRI_DRAM_SIZE_128MB:
  808.    reg |= (SIS315_DRAM_SIZE_128MB << 4); break; */
  809. }
  810. /* TODO : set Dual channel and bus width bits here */
  811. vgawb (SEQ_DATA, reg);
  812. break;
  813. }
  814. }
  815. if (!pdev_valid)
  816. return -1;
  817. #else
  818. vgawb (SEQ_ADR, IND_SIS_DRAM_SIZE);
  819. reg = vgarb (SEQ_DATA);
  820. switch (reg & SIS550_DRAM_SIZE_MASK) {
  821. case SIS550_DRAM_SIZE_4MB:
  822. ivideo.video_size = 0x400000;
  823. break;
  824. case SIS550_DRAM_SIZE_8MB:
  825. ivideo.video_size = 0x800000;
  826. break;
  827. case SIS550_DRAM_SIZE_16MB:
  828. ivideo.video_size = 0x1000000;
  829. break;
  830. case SIS550_DRAM_SIZE_24MB:
  831. ivideo.video_size = 0x1800000;
  832. break;
  833. case SIS550_DRAM_SIZE_32MB:
  834. ivideo.video_size = 0x2000000;
  835. break;
  836. case SIS550_DRAM_SIZE_64MB:
  837. ivideo.video_size = 0x4000000;
  838. break;
  839. case SIS550_DRAM_SIZE_96MB:
  840. ivideo.video_size = 0x6000000;
  841. break;
  842. case SIS550_DRAM_SIZE_128MB:
  843. ivideo.video_size = 0x8000000;
  844. break;
  845. case SIS550_DRAM_SIZE_256MB:
  846. ivideo.video_size = 0x10000000;
  847. break;
  848. default:
  849. return -1;
  850. }
  851. #endif
  852. return 0;
  853. } else {
  854. vgawb (SEQ_ADR, IND_SIS_DRAM_SIZE);
  855. reg = vgarb (SEQ_DATA);
  856. switch ((reg & SIS315_DRAM_SIZE_MASK) >> 4) {
  857. case SIS315_DRAM_SIZE_2MB:
  858. ivideo.video_size = 0x200000;
  859. break;
  860. case SIS315_DRAM_SIZE_4MB:
  861. ivideo.video_size = 0x400000;
  862. break;
  863. case SIS315_DRAM_SIZE_8MB:
  864. ivideo.video_size = 0x800000;
  865. break;
  866. case SIS315_DRAM_SIZE_16MB:
  867. ivideo.video_size = 0x1000000;
  868. break;
  869. case SIS315_DRAM_SIZE_32MB:
  870. ivideo.video_size = 0x2000000;
  871. break;
  872. case SIS315_DRAM_SIZE_64MB:
  873. ivideo.video_size = 0x4000000;
  874. break;
  875. case SIS315_DRAM_SIZE_128MB:
  876. ivideo.video_size = 0x8000000;
  877. break;
  878. default:
  879. return -1;
  880. }
  881. }
  882. reg &= SIS315_DUAL_CHANNEL_MASK;
  883. reg >>= 2;
  884. switch (reg) {
  885. case SIS315_SINGLE_CHANNEL_2_RANK:
  886. ivideo.video_size <<= 1;
  887. break;
  888. case SIS315_DUAL_CHANNEL_1_RANK:
  889. ivideo.video_size <<= 1;
  890. break;
  891. }
  892. return 0;
  893. }
  894. static void sisfb_detect_VB_connect_315 (void)
  895. {
  896. u8 cr32, temp;
  897. vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR32);
  898. cr32 = vgarb (CRTC_DATA);
  899. ivideo.TV_plug = ivideo.TV_type = 0;
  900. if ((cr32 & SIS_CRT1) && !sisfb_crt1off)
  901. sisfb_crt1off = 0;
  902. else {
  903. if (cr32 & 0x5F)
  904. sisfb_crt1off = 1;
  905. else
  906. sisfb_crt1off = 0;
  907. }
  908. if (cr32 & SIS_VB_CRT2)
  909. ivideo.disp_state = DISPTYPE_CRT2;
  910. else if (cr32 & SIS_VB_LCD)
  911. ivideo.disp_state = DISPTYPE_LCD;
  912. else if (cr32 & SIS_VB_TV) {
  913. ivideo.disp_state = DISPTYPE_TV;
  914. if (cr32 & SIS_VB_HIVISION) {
  915. ivideo.TV_type = TVMODE_HIVISION;
  916. ivideo.TV_plug = TVPLUG_SVIDEO;
  917. } else if (cr32 & SIS_VB_SVIDEO)
  918. ivideo.TV_plug = TVPLUG_SVIDEO;
  919. else if (cr32 & SIS_VB_COMPOSITE)
  920. ivideo.TV_plug = TVPLUG_COMPOSITE;
  921. else if (cr32 & SIS_VB_SCART)
  922. ivideo.TV_plug = TVPLUG_SCART;
  923. if (ivideo.TV_type == 0) {
  924. vgawb (SEQ_ADR, IND_SIS_POWER_ON_TRAP);
  925. temp = vgarb (SEQ_DATA);
  926. if (temp & 0x01)
  927. ivideo.TV_type = TVMODE_PAL;
  928. else
  929. ivideo.TV_type = TVMODE_NTSC;
  930. }
  931. } else
  932. ivideo.disp_state = 0;
  933. }
  934. static void sisfb_get_VB_type_315 (void)
  935. {
  936. u8 vb_chipid;
  937. vgawb (VB_PART4_ADR, 0x0);
  938. vb_chipid = vgarb (VB_PART4_DATA);
  939. switch (vb_chipid) {
  940. case 0x01:
  941. ivideo.hasVB = HASVB_301;
  942. break;
  943. case 0x02:
  944. ivideo.hasVB = HASVB_302;
  945. break;
  946. case 0x03:
  947. ivideo.hasVB = HASVB_303;
  948. break;
  949. default:
  950. ivideo.hasVB = HASVB_NONE;
  951. }
  952. // Eden Chen
  953. //sishw_ext.hasVB = ivideo.hasVB;
  954. // ~Eden Chen
  955. }
  956. #endif /* CONFIG_FB_SIS_315 */
  957. /* --------------------- Heap Routines ------------------------------- */
  958. static int sisfb_heap_init (void)
  959. {
  960. SIS_OH *poh;
  961. u8 temp = 0;
  962. #ifdef CONFIG_FB_SIS_315
  963. int agp_enabled = 1;
  964. u32 agp_size;
  965. unsigned long *cmdq_baseport = 0;
  966. unsigned long *read_port = 0;
  967. unsigned long *write_port = 0;
  968. SIS_CMDTYPE cmd_type;
  969. #ifndef AGPOFF
  970. agp_kern_info *agp_info;
  971. agp_memory *agp;
  972. u32 agp_phys;
  973. #endif
  974. #endif
  975. /*karl:10/01/2001 */
  976. if (!sisfb_mem) {
  977. if (ivideo.video_size > 0x800000)
  978. sisfb_heap_start =
  979.     (unsigned long) ivideo.video_vbase + 0x800000;
  980. else
  981. sisfb_heap_start =
  982.     (unsigned long) ivideo.video_vbase + 0x400000;
  983. } else
  984. sisfb_heap_start =
  985.     (unsigned long) (ivideo.video_vbase + sisfb_mem * 0x100000);
  986. sisfb_heap_end = (unsigned long) ivideo.video_vbase + ivideo.video_size;
  987. sisfb_heap_size = sisfb_heap_end - sisfb_heap_start;
  988. #ifdef CONFIG_FB_SIS_315
  989. cmdq_baseport =
  990.     (unsigned long *) (ivideo.mmio_vbase + MMIO_QUEUE_PHYBASE);
  991. write_port =
  992.     (unsigned long *) (ivideo.mmio_vbase + MMIO_QUEUE_WRITEPORT);
  993. read_port = (unsigned long *) (ivideo.mmio_vbase + MMIO_QUEUE_READPORT);
  994. DPRINTK ("AGP base: 0x%p, read: 0x%p, write: 0x%pn", cmdq_baseport,
  995.  read_port, write_port);
  996. agp_size = COMMAND_QUEUE_AREA_SIZE;
  997. #ifndef AGPOFF
  998. agp_info = vmalloc (sizeof (agp_kern_info));
  999. memset ((void *) agp_info, 0x00, sizeof (agp_kern_info));
  1000. agp_copy_info (agp_info);
  1001. agp_backend_acquire ();
  1002. agp =
  1003.     agp_allocate_memory (COMMAND_QUEUE_AREA_SIZE / PAGE_SIZE,
  1004.  AGP_NORMAL_MEMORY);
  1005. if (agp == NULL) {
  1006. DPRINTK ("Allocate AGP buffer failed.n");
  1007. agp_enabled = 0;
  1008. } else {
  1009. if (agp_bind_memory (agp, agp->pg_start) != 0) {
  1010. DPRINTK ("AGP : can not bind memoryn");
  1011. agp_enabled = 0;
  1012. } else {
  1013. agp_enable (0);
  1014. }
  1015. }
  1016. #else
  1017. agp_enabled = 0;
  1018. #endif
  1019. if (agp_enabled)
  1020. cmd_type = AGP_CMD_QUEUE;
  1021. else if (sisfb_heap_size >= COMMAND_QUEUE_AREA_SIZE)
  1022. cmd_type = VM_CMD_QUEUE;
  1023. else
  1024. cmd_type = MMIO_CMD;
  1025. switch (agp_size) {
  1026. case 0x80000:
  1027. temp = SIS_CMD_QUEUE_SIZE_512k;
  1028. break;
  1029. case 0x100000:
  1030. temp = SIS_CMD_QUEUE_SIZE_1M;
  1031. break;
  1032. case 0x200000:
  1033. temp = SIS_CMD_QUEUE_SIZE_2M;
  1034. break;
  1035. case 0x400000:
  1036. temp = SIS_CMD_QUEUE_SIZE_4M;
  1037. break;
  1038. }
  1039. switch (cmd_type) {
  1040. case AGP_CMD_QUEUE:
  1041. #ifndef AGPOFF
  1042. DPRINTK ("AGP buffer base:0x%lx, offset:0x%x, size is %dKn",
  1043.  agp_info->aper_base, agp->physical, agp_size / 1024);
  1044. agp_phys = agp_info->aper_base + agp->physical;
  1045. vgawb (CRTC_ADR, IND_SIS_AGP_IO_PAD);
  1046. vgawb (CRTC_DATA, 0);
  1047. vgawb (CRTC_DATA, SIS_AGP_2X);
  1048. vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_THRESHOLD);
  1049. vgawb (SEQ_DATA, COMMAND_QUEUE_THRESHOLD);
  1050. vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_SET);
  1051. vgawb (SEQ_DATA, SIS_CMD_QUEUE_RESET);
  1052. *write_port = *read_port;
  1053. temp |= SIS_AGP_CMDQUEUE_ENABLE;
  1054. vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_SET);
  1055. vgawb (SEQ_DATA, temp);
  1056. *cmdq_baseport = agp_phys;
  1057. sisfb_caps |= AGP_CMD_QUEUE_CAP;
  1058. #endif
  1059. break;
  1060. case VM_CMD_QUEUE:
  1061. sisfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
  1062. sisfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
  1063. vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_THRESHOLD);
  1064. vgawb (SEQ_DATA, COMMAND_QUEUE_THRESHOLD);
  1065. vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_SET);
  1066. vgawb (SEQ_DATA, SIS_CMD_QUEUE_RESET);
  1067. *write_port = *read_port;
  1068. temp |= SIS_VRAM_CMDQUEUE_ENABLE;
  1069. vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_SET);
  1070. vgawb (SEQ_DATA, temp);
  1071. *cmdq_baseport = ivideo.video_size - COMMAND_QUEUE_AREA_SIZE;
  1072. sisfb_caps |= VM_CMD_QUEUE_CAP;
  1073. DPRINTK ("VM Cmd Queue offset = 0x%lx, size is %dKn",
  1074.  *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE / 1024);
  1075. break;
  1076. default:
  1077. vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_SET);
  1078. vgawb (SEQ_DATA, SIS_MMIO_CMD_ENABLE);
  1079. break;
  1080. }
  1081. #endif
  1082. #ifdef CONFIG_FB_SIS_300
  1083. if (sisfb_heap_size >= TURBO_QUEUE_AREA_SIZE) {
  1084. unsigned int tqueue_pos;
  1085. u8 tq_state;
  1086. tqueue_pos =
  1087.     (ivideo.video_size - TURBO_QUEUE_AREA_SIZE) / (64 * 1024);
  1088. temp = (u8) (tqueue_pos & 0xff);
  1089. vgawb (SEQ_ADR, IND_SIS_TURBOQUEUE_SET);
  1090. tq_state = vgarb (SEQ_DATA);
  1091. tq_state |= 0xf0;
  1092. tq_state &= 0xfc;
  1093. tq_state |= (u8) (tqueue_pos >> 8);
  1094. vgawb (SEQ_DATA, tq_state);
  1095. vgawb (SEQ_ADR, IND_SIS_TURBOQUEUE_ADR);
  1096. vgawb (SEQ_DATA, temp);
  1097. sisfb_caps |= TURBO_QUEUE_CAP;
  1098. sisfb_heap_end -= TURBO_QUEUE_AREA_SIZE;
  1099. sisfb_heap_size -= TURBO_QUEUE_AREA_SIZE;
  1100. DPRINTK ("Turbo Queue: start at 0x%lx, size is %dKn",
  1101.  sisfb_heap_end, TURBO_QUEUE_AREA_SIZE / 1024);
  1102. }
  1103. #endif
  1104. if (sisfb_heap_size >= HW_CURSOR_AREA_SIZE) {
  1105. sisfb_heap_end -= HW_CURSOR_AREA_SIZE;
  1106. sisfb_heap_size -= HW_CURSOR_AREA_SIZE;
  1107. sisfb_hwcursor_vbase = sisfb_heap_end;
  1108. sisfb_caps |= HW_CURSOR_CAP;
  1109. DPRINTK ("Hardware Cursor: start at 0x%lx, size is %dKn",
  1110.  sisfb_heap_end, HW_CURSOR_AREA_SIZE / 1024);
  1111. }
  1112. sisfb_heap.poha_chain = NULL;
  1113. sisfb_heap.poh_freelist = NULL;
  1114. poh = sisfb_poh_new_node ();
  1115. if (poh == NULL)
  1116. return 1;
  1117. poh->poh_next = &sisfb_heap.oh_free;
  1118. poh->poh_prev = &sisfb_heap.oh_free;
  1119. poh->size = sisfb_heap_end - sisfb_heap_start + 1;
  1120. poh->offset = sisfb_heap_start - (unsigned long) ivideo.video_vbase;
  1121. DPRINTK ("sisfb:Heap start:0x%p, end:0x%p, len=%dkn",
  1122.  (char *) sisfb_heap_start, (char *) sisfb_heap_end,
  1123.  (unsigned int) poh->size / 1024);
  1124. DPRINTK ("sisfb:First Node offset:0x%x, size:%dkn",
  1125.  (unsigned int) poh->offset, (unsigned int) poh->size / 1024);
  1126. sisfb_heap.oh_free.poh_next = poh;
  1127. sisfb_heap.oh_free.poh_prev = poh;
  1128. sisfb_heap.oh_free.size = 0;
  1129. sisfb_heap.max_freesize = poh->size;
  1130. sisfb_heap.oh_used.poh_next = &sisfb_heap.oh_used;
  1131. sisfb_heap.oh_used.poh_prev = &sisfb_heap.oh_used;
  1132. sisfb_heap.oh_used.size = SENTINEL;
  1133. return 0;
  1134. }
  1135. static SIS_OH *sisfb_poh_new_node (void)
  1136. {
  1137. int i;
  1138. unsigned long cOhs;
  1139. SIS_OHALLOC *poha;
  1140. SIS_OH *poh;
  1141. if (sisfb_heap.poh_freelist == NULL) {
  1142. poha = kmalloc (OH_ALLOC_SIZE, GFP_KERNEL);
  1143. poha->poha_next = sisfb_heap.poha_chain;
  1144. sisfb_heap.poha_chain = poha;
  1145. cOhs =
  1146.     (OH_ALLOC_SIZE -
  1147.      sizeof (SIS_OHALLOC)) / sizeof (SIS_OH) + 1;
  1148. poh = &poha->aoh[0];
  1149. for (i = cOhs - 1; i != 0; i--) {
  1150. poh->poh_next = poh + 1;
  1151. poh = poh + 1;
  1152. }
  1153. poh->poh_next = NULL;
  1154. sisfb_heap.poh_freelist = &poha->aoh[0];
  1155. }
  1156. poh = sisfb_heap.poh_freelist;
  1157. sisfb_heap.poh_freelist = poh->poh_next;
  1158. return (poh);
  1159. }
  1160. static SIS_OH *sisfb_poh_allocate (unsigned long size)
  1161. {
  1162. SIS_OH *pohThis;
  1163. SIS_OH *pohRoot;
  1164. int bAllocated = 0;
  1165. if (size > sisfb_heap.max_freesize) {
  1166. DPRINTK ("sisfb: Can't allocate %dk size on offscreenn",
  1167.  (unsigned int) size / 1024);
  1168. return (NULL);
  1169. }
  1170. pohThis = sisfb_heap.oh_free.poh_next;
  1171. while (pohThis != &sisfb_heap.oh_free) {
  1172. if (size <= pohThis->size) {
  1173. bAllocated = 1;
  1174. break;
  1175. }
  1176. pohThis = pohThis->poh_next;
  1177. }
  1178. if (!bAllocated) {
  1179. DPRINTK ("sisfb: Can't allocate %dk size on offscreenn",
  1180.  (unsigned int) size / 1024);
  1181. return (NULL);
  1182. }
  1183. if (size == pohThis->size) {
  1184. pohRoot = pohThis;
  1185. sisfb_delete_node (pohThis);
  1186. } else {
  1187. pohRoot = sisfb_poh_new_node ();
  1188. if (pohRoot == NULL) {
  1189. return (NULL);
  1190. }
  1191. pohRoot->offset = pohThis->offset;
  1192. pohRoot->size = size;
  1193. pohThis->offset += size;
  1194. pohThis->size -= size;
  1195. }
  1196. sisfb_heap.max_freesize -= size;
  1197. pohThis = &sisfb_heap.oh_used;
  1198. sisfb_insert_node (pohThis, pohRoot);
  1199. return (pohRoot);
  1200. }
  1201. static void sisfb_delete_node (SIS_OH * poh)
  1202. {
  1203. SIS_OH *poh_prev;
  1204. SIS_OH *poh_next;
  1205. poh_prev = poh->poh_prev;
  1206. poh_next = poh->poh_next;
  1207. poh_prev->poh_next = poh_next;
  1208. poh_next->poh_prev = poh_prev;
  1209. return;
  1210. }
  1211. static void sisfb_insert_node (SIS_OH * pohList, SIS_OH * poh)
  1212. {
  1213. SIS_OH *pohTemp;
  1214. pohTemp = pohList->poh_next;
  1215. pohList->poh_next = poh;
  1216. pohTemp->poh_prev = poh;
  1217. poh->poh_prev = pohList;
  1218. poh->poh_next = pohTemp;
  1219. }
  1220. static SIS_OH *sisfb_poh_free (unsigned long base)
  1221. {
  1222. SIS_OH *pohThis;
  1223. SIS_OH *poh_freed;
  1224. SIS_OH *poh_prev;
  1225. SIS_OH *poh_next;
  1226. unsigned long ulUpper;
  1227. unsigned long ulLower;
  1228. int foundNode = 0;
  1229. poh_freed = sisfb_heap.oh_used.poh_next;
  1230. while (poh_freed != &sisfb_heap.oh_used) {
  1231. if (poh_freed->offset == base) {
  1232. foundNode = 1;
  1233. break;
  1234. }
  1235. poh_freed = poh_freed->poh_next;
  1236. }
  1237. if (!foundNode)
  1238. return (NULL);
  1239. sisfb_heap.max_freesize += poh_freed->size;
  1240. poh_prev = poh_next = NULL;
  1241. ulUpper = poh_freed->offset + poh_freed->size;
  1242. ulLower = poh_freed->offset;
  1243. pohThis = sisfb_heap.oh_free.poh_next;
  1244. while (pohThis != &sisfb_heap.oh_free) {
  1245. if (pohThis->offset == ulUpper) {
  1246. poh_next = pohThis;
  1247. } else if ((pohThis->offset + pohThis->size) == ulLower) {
  1248. poh_prev = pohThis;
  1249. }
  1250. pohThis = pohThis->poh_next;
  1251. }
  1252. sisfb_delete_node (poh_freed);
  1253. if (poh_prev && poh_next) {
  1254. poh_prev->size += (poh_freed->size + poh_next->size);
  1255. sisfb_delete_node (poh_next);
  1256. sisfb_free_node (poh_freed);
  1257. sisfb_free_node (poh_next);
  1258. return (poh_prev);
  1259. }
  1260. if (poh_prev) {
  1261. poh_prev->size += poh_freed->size;
  1262. sisfb_free_node (poh_freed);
  1263. return (poh_prev);
  1264. }
  1265. if (poh_next) {
  1266. poh_next->size += poh_freed->size;
  1267. poh_next->offset = poh_freed->offset;
  1268. sisfb_free_node (poh_freed);
  1269. return (poh_next);
  1270. }
  1271. sisfb_insert_node (&sisfb_heap.oh_free, poh_freed);
  1272. return (poh_freed);
  1273. }
  1274. static void sisfb_free_node (SIS_OH * poh)
  1275. {
  1276. if (poh == NULL) {
  1277. return;
  1278. }
  1279. poh->poh_next = sisfb_heap.poh_freelist;
  1280. sisfb_heap.poh_freelist = poh;
  1281. return;
  1282. }
  1283. void sis_malloc (struct sis_memreq *req)
  1284. {
  1285. SIS_OH *poh;
  1286. poh = sisfb_poh_allocate (req->size);
  1287. if (poh == NULL) {
  1288. req->offset = 0;
  1289. req->size = 0;
  1290. DPRINTK ("sisfb: VMEM Allocation Failedn");
  1291. } else {
  1292. DPRINTK ("sisfb: VMEM Allocation Successed : 0x%pn",
  1293.  (char *) (poh->offset +
  1294.    (unsigned long) ivideo.video_vbase));
  1295. req->offset = poh->offset;
  1296. req->size = poh->size;
  1297. }
  1298. }
  1299. void sis_free (unsigned long base)
  1300. {
  1301. SIS_OH *poh;
  1302. poh = sisfb_poh_free (base);
  1303. if (poh == NULL) {
  1304. DPRINTK ("sisfb: sisfb_poh_free() failed at base 0x%xn",
  1305.  (unsigned int) base);
  1306. }
  1307. }
  1308. /* ------------------ SetMode Routines ------------------------------- */
  1309. static void sisfb_pre_setmode (void)
  1310. {
  1311. u8 cr30 = 0, cr31 = 0;
  1312. vgawb (CRTC_ADR, 0x31);
  1313. cr31 = vgarb (CRTC_DATA) & ~0x60;
  1314. switch (ivideo.disp_state & DISPTYPE_DISP2) {
  1315. case DISPTYPE_CRT2:
  1316. cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
  1317. cr31 |= SIS_DRIVER_MODE;
  1318. break;
  1319. case DISPTYPE_LCD:
  1320. cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
  1321. cr31 |= SIS_DRIVER_MODE;
  1322. break;
  1323. case DISPTYPE_TV:
  1324. if (ivideo.TV_type == TVMODE_HIVISION)
  1325. cr30 =
  1326.     (SIS_VB_OUTPUT_HIVISION |
  1327.      SIS_SIMULTANEOUS_VIEW_ENABLE);
  1328. else if (ivideo.TV_plug == TVPLUG_SVIDEO)
  1329. cr30 =
  1330.     (SIS_VB_OUTPUT_SVIDEO |
  1331.      SIS_SIMULTANEOUS_VIEW_ENABLE);
  1332. else if (ivideo.TV_plug == TVPLUG_COMPOSITE)
  1333. cr30 =
  1334.     (SIS_VB_OUTPUT_COMPOSITE |
  1335.      SIS_SIMULTANEOUS_VIEW_ENABLE);
  1336. else if (ivideo.TV_plug == TVPLUG_SCART)
  1337. cr30 =
  1338.     (SIS_VB_OUTPUT_SCART |
  1339.      SIS_SIMULTANEOUS_VIEW_ENABLE);
  1340. cr31 |= SIS_DRIVER_MODE;
  1341. /*karl */
  1342. if (sisfb_tvmode == 1)
  1343. cr31 |= 0x1;
  1344. if (sisfb_tvmode == 2)
  1345. cr31 &= ~0x1;
  1346. break;
  1347. default:
  1348. cr30 = 0x00;
  1349. cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
  1350. }
  1351. vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR30);
  1352. vgawb (CRTC_DATA, cr30);
  1353. vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR31);
  1354. vgawb (CRTC_DATA, cr31);
  1355. vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR33);
  1356. vgawb (CRTC_DATA, sisfb_rate_idx & 0x0F);
  1357. }
  1358. static void sisfb_post_setmode (void)
  1359. {
  1360. u8 reg;
  1361. vgawb (CRTC_ADR, 0x17);
  1362. reg = vgarb (CRTC_DATA);
  1363. if ((ivideo.hasVB == HASVB_LVDS)
  1364.     || (ivideo.hasVB == HASVB_LVDS_CHRONTEL)) if (ivideo.video_bpp == 8)
  1365. sisfb_crt1off = 0;
  1366. if (sisfb_crt1off)
  1367. reg &= ~0x80;
  1368. else
  1369. reg |= 0x80;
  1370. vgawb (CRTC_DATA, reg);
  1371. vgawb (SEQ_ADR, IND_SIS_RAMDAC_CONTROL);
  1372. reg = vgarb (SEQ_DATA);
  1373. reg &= ~0x04;
  1374. vgawb (SEQ_DATA, reg);
  1375. if ((ivideo.disp_state & DISPTYPE_TV) && (ivideo.hasVB == HASVB_301)) {
  1376. /*karl */
  1377. vgawb (VB_PART4_ADR, 0x01);
  1378. reg = vgarb (VB_PART4_DATA);
  1379. if ((reg != 0xB1) && (reg != 0xB0)) { /*301B Revision ID */
  1380. // Eden Chen
  1381. switch (ivideo.video_width) {
  1382. case 320:
  1383. filter_tb =
  1384.     (ivideo.TV_type == TVMODE_NTSC) ? 4 : 12;
  1385. break;
  1386. case 640:
  1387. filter_tb =
  1388.     (ivideo.TV_type == TVMODE_NTSC) ? 5 : 13;
  1389. break;
  1390. case 720:
  1391. filter_tb =
  1392.     (ivideo.TV_type == TVMODE_NTSC) ? 6 : 14;
  1393. break;
  1394. case 800:
  1395. filter_tb =
  1396.     (ivideo.TV_type == TVMODE_NTSC) ? 7 : 15;
  1397. break;
  1398. default:
  1399. filter = -1;
  1400. break;
  1401. }
  1402. // ~Eden Chen
  1403. // Eden Chen
  1404. //vgawb(VB_PART1_ADR,  0x24);
  1405. vgawb (VB_PART1_ADR, IND_SIS_CRT2_WRITE_ENABLE);
  1406. // ~Eden Chen
  1407. vgawb (VB_PART1_DATA, 0x1);
  1408. // Eden Chen for Debug
  1409. // ~Eden Chen
  1410. if (ivideo.TV_type == TVMODE_NTSC) {
  1411. vgawb (VB_PART2_ADR, 0x3A);
  1412. reg = vgarb (VB_PART2_DATA);
  1413. reg &= 0x1F;
  1414. vgawb (VB_PART2_DATA, reg);
  1415. if (ivideo.TV_plug == TVPLUG_SVIDEO) {
  1416. vgawb (VB_PART2_ADR, 0x30);
  1417. reg = vgarb (VB_PART2_DATA);
  1418. reg &= 0xDF;
  1419. vgawb (VB_PART2_DATA, reg);
  1420. } else if (ivideo.TV_plug == TVPLUG_COMPOSITE) {
  1421. vgawb (VB_PART2_ADR, 0x30);
  1422. reg = vgarb (VB_PART2_DATA);
  1423. reg |= 0x20;
  1424. vgawb (VB_PART2_DATA, reg);
  1425. switch (ivideo.video_width) {
  1426. case 640:
  1427. vgawb (VB_PART2_ADR, 0x35);
  1428. vgawb (VB_PART2_DATA, 0xEB);
  1429. vgawb (VB_PART2_ADR, 0x36);
  1430. vgawb (VB_PART2_DATA, 0x04);
  1431. vgawb (VB_PART2_ADR, 0x37);
  1432. vgawb (VB_PART2_DATA, 0x25);
  1433. vgawb (VB_PART2_ADR, 0x38);
  1434. vgawb (VB_PART2_DATA, 0x18);
  1435. break;
  1436. case 720:
  1437. vgawb (VB_PART2_ADR, 0x35);
  1438. vgawb (VB_PART2_DATA, 0xEE);
  1439. vgawb (VB_PART2_ADR, 0x36);
  1440. vgawb (VB_PART2_DATA, 0x0C);
  1441. vgawb (VB_PART2_ADR, 0x37);
  1442. vgawb (VB_PART2_DATA, 0x22);
  1443. vgawb (VB_PART2_ADR, 0x38);
  1444. vgawb (VB_PART2_DATA, 0x08);
  1445. break;
  1446. case 800:
  1447. vgawb (VB_PART2_ADR, 0x35);
  1448. vgawb (VB_PART2_DATA, 0xEB);
  1449. vgawb (VB_PART2_ADR, 0x36);
  1450. vgawb (VB_PART2_DATA, 0x15);
  1451. vgawb (VB_PART2_ADR, 0x37);
  1452. vgawb (VB_PART2_DATA, 0x25);
  1453. vgawb (VB_PART2_ADR, 0x38);
  1454. vgawb (VB_PART2_DATA, 0xF6);
  1455. break;
  1456. }
  1457. }
  1458. } else if (ivideo.TV_type == TVMODE_PAL) {
  1459. vgawb (VB_PART2_ADR, 0x3A);
  1460. reg = vgarb (VB_PART2_DATA);
  1461. reg &= 0x1F;
  1462. vgawb (VB_PART2_DATA, reg);
  1463. if (ivideo.TV_plug == TVPLUG_SVIDEO) {
  1464. vgawb (VB_PART2_ADR, 0x30);
  1465. reg = vgarb (VB_PART2_DATA);
  1466. reg &= 0xDF;
  1467. vgawb (VB_PART2_DATA, reg);
  1468. } else if (ivideo.TV_plug == TVPLUG_COMPOSITE) {
  1469. vgawb (VB_PART2_ADR, 0x30);
  1470. reg = vgarb (VB_PART2_DATA);
  1471. reg |= 0x20;
  1472. vgawb (VB_PART2_DATA, reg);
  1473. switch (ivideo.video_width) {
  1474. case 640:
  1475. vgawb (VB_PART2_ADR, 0x35);
  1476. vgawb (VB_PART2_DATA, 0xF1);
  1477. vgawb (VB_PART2_ADR, 0x36);
  1478. vgawb (VB_PART2_DATA, 0xF7);
  1479. vgawb (VB_PART2_ADR, 0x37);
  1480. vgawb (VB_PART2_DATA, 0x1F);
  1481. vgawb (VB_PART2_ADR, 0x38);
  1482. vgawb (VB_PART2_DATA, 0x32);
  1483. break;
  1484. case 720:
  1485. vgawb (VB_PART2_ADR, 0x35);
  1486. vgawb (VB_PART2_DATA, 0xF3);
  1487. vgawb (VB_PART2_ADR, 0x36);
  1488. vgawb (VB_PART2_DATA, 0x00);
  1489. vgawb (VB_PART2_ADR, 0x37);
  1490. vgawb (VB_PART2_DATA, 0x1D);
  1491. vgawb (VB_PART2_ADR, 0x38);
  1492. vgawb (VB_PART2_DATA, 0x20);
  1493. break;
  1494. case 800:
  1495. vgawb (VB_PART2_ADR, 0x35);
  1496. vgawb (VB_PART2_DATA, 0xFC);
  1497. vgawb (VB_PART2_ADR, 0x36);
  1498. vgawb (VB_PART2_DATA, 0xFB);
  1499. vgawb (VB_PART2_ADR, 0x37);
  1500. vgawb (VB_PART2_DATA, 0x14);
  1501. vgawb (VB_PART2_ADR, 0x38);
  1502. vgawb (VB_PART2_DATA, 0x2A);
  1503. break;
  1504. }
  1505. }
  1506. }
  1507. // Eden 
  1508. if ((filter >= 0) && (filter <= 7)) {
  1509. DPRINTK
  1510.     ("FilterTable[%d]-%d: %02x %02x %02x %02xn",
  1511.      filter_tb, filter,
  1512.      sis_TV_filter[filter_tb].filter[filter][0],
  1513.      sis_TV_filter[filter_tb].filter[filter][1],
  1514.      sis_TV_filter[filter_tb].filter[filter][2],
  1515.      sis_TV_filter[filter_tb].filter[filter][3]
  1516.     );
  1517. vgawb (VB_PART2_ADR, 0x35);
  1518. vgawb (VB_PART2_DATA,
  1519.        sis_TV_filter[filter_tb].
  1520.        filter[filter][0]);
  1521. vgawb (VB_PART2_ADR, 0x36);
  1522. vgawb (VB_PART2_DATA,
  1523.        sis_TV_filter[filter_tb].
  1524.        filter[filter][1]);
  1525. vgawb (VB_PART2_ADR, 0x37);
  1526. vgawb (VB_PART2_DATA,
  1527.        sis_TV_filter[filter_tb].
  1528.        filter[filter][2]);
  1529. vgawb (VB_PART2_ADR, 0x38);
  1530. vgawb (VB_PART2_DATA,
  1531.        sis_TV_filter[filter_tb].
  1532.        filter[filter][3]);
  1533. }
  1534. // ~Eden 
  1535. }
  1536. }
  1537. }
  1538. static void sisfb_crtc_to_var (struct fb_var_screeninfo *var)
  1539. {
  1540. u16 VRE, VBE, VRS, VBS, VDE, VT;
  1541. u16 HRE, HBE, HRS, HBS, HDE, HT;
  1542. u8 sr_data, cr_data, cr_data2, cr_data3, mr_data;
  1543. int A, B, C, D, E, F, temp;
  1544. double hrate, drate;
  1545. vgawb (SEQ_ADR, IND_SIS_COLOR_MODE);
  1546. sr_data = vgarb (SEQ_DATA);
  1547. if (sr_data & SIS_INTERLACED_MODE)
  1548. var->vmode = FB_VMODE_INTERLACED;
  1549. else
  1550. var->vmode = FB_VMODE_NONINTERLACED;
  1551. switch ((sr_data & 0x1C) >> 2) {
  1552. case SIS_8BPP_COLOR_MODE:
  1553. var->bits_per_pixel = 8;
  1554. break;
  1555. case SIS_16BPP_COLOR_MODE:
  1556. var->bits_per_pixel = 16;
  1557. break;
  1558. case SIS_32BPP_COLOR_MODE:
  1559. var->bits_per_pixel = 32;
  1560. break;
  1561. }
  1562. switch (var->bits_per_pixel) {
  1563. case 8:
  1564. var->red.length = 6;
  1565. var->green.length = 6;
  1566. var->blue.length = 6;
  1567. video_cmap_len = 256;
  1568. break;
  1569. case 16:
  1570. var->red.offset = 11;
  1571. var->red.length = 5;
  1572. var->green.offset = 5;
  1573. var->green.length = 6;
  1574. var->blue.offset = 0;
  1575. var->blue.length = 5;
  1576. var->transp.offset = 0;
  1577. var->transp.length = 0;
  1578. video_cmap_len = 16;
  1579. break;
  1580. case 24:
  1581. var->red.offset = 16;
  1582. var->red.length = 8;
  1583. var->green.offset = 8;
  1584. var->green.length = 8;
  1585. var->blue.offset = 0;
  1586. var->blue.length = 8;
  1587. var->transp.offset = 0;
  1588. var->transp.length = 0;
  1589. video_cmap_len = 16;
  1590. break;
  1591. case 32:
  1592. var->red.offset = 16;
  1593. var->red.length = 8;
  1594. var->green.offset = 8;
  1595. var->green.length = 8;
  1596. var->blue.offset = 0;
  1597. var->blue.length = 8;
  1598. var->transp.offset = 24;
  1599. var->transp.length = 8;
  1600. video_cmap_len = 16;
  1601. break;
  1602. }
  1603. vgawb (SEQ_ADR, 0xA);
  1604. sr_data = vgarb (SEQ_DATA);
  1605. vgawb (CRTC_ADR, 0x6);
  1606. cr_data = vgarb (CRTC_DATA);
  1607. vgawb (CRTC_ADR, 0x7);
  1608. cr_data2 = vgarb (CRTC_DATA);
  1609. VT =
  1610.     (cr_data & 0xFF) | ((u16) (cr_data2 & 0x01) << 8) |
  1611.     ((u16) (cr_data2 & 0x20) << 4) | ((u16) (sr_data & 0x01) << 10);
  1612. A = VT + 2;
  1613. vgawb (CRTC_ADR, 0x12);
  1614. cr_data = vgarb (CRTC_DATA);
  1615. VDE =
  1616.     (cr_data & 0xff) | ((u16) (cr_data2 & 0x02) << 7) |
  1617.     ((u16) (cr_data2 & 0x40) << 3) | ((u16) (sr_data & 0x02) << 9);
  1618. E = VDE + 1;
  1619. vgawb (CRTC_ADR, 0x10);
  1620. cr_data = vgarb (CRTC_DATA);
  1621. VRS =
  1622.     (cr_data & 0xff) | ((u16) (cr_data2 & 0x04) << 6) |
  1623.     ((u16) (cr_data2 & 0x80) << 2) | ((u16) (sr_data & 0x08) << 7);
  1624. F = VRS + 1 - E;
  1625. vgawb (CRTC_ADR, 0x15);
  1626. cr_data = vgarb (CRTC_DATA);
  1627. vgawb (CRTC_ADR, 0x9);
  1628. cr_data3 = vgarb (CRTC_DATA);
  1629. VBS = (cr_data & 0xff) | ((u16) (cr_data2 & 0x08) << 5) |
  1630.     ((u16) (cr_data3 & 0x20) << 4) | ((u16) (sr_data & 0x04) << 8);
  1631. vgawb (CRTC_ADR, 0x16);
  1632. cr_data = vgarb (CRTC_DATA);
  1633. VBE = (cr_data & 0xff) | ((u16) (sr_data & 0x10) << 4);
  1634. temp = VBE - ((E - 1) & 511);
  1635. B = (temp > 0) ? temp : (temp + 512);
  1636. vgawb (CRTC_ADR, 0x11);
  1637. cr_data = vgarb (CRTC_DATA);
  1638. VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
  1639. temp = VRE - ((E + F - 1) & 31);
  1640. C = (temp > 0) ? temp : (temp + 32);
  1641. D = B - F - C;
  1642. var->yres = var->yres_virtual = E;
  1643. var->upper_margin = D;
  1644. var->lower_margin = F;
  1645. var->vsync_len = C;
  1646. vgawb (SEQ_ADR, 0xb);
  1647. sr_data = vgarb (SEQ_DATA);
  1648. vgawb (CRTC_ADR, 0x0);
  1649. cr_data = vgarb (CRTC_DATA);
  1650. HT = (cr_data & 0xff) | ((u16) (sr_data & 0x03) << 8);
  1651. A = HT + 5;
  1652. vgawb (CRTC_ADR, 0x1);
  1653. cr_data = vgarb (CRTC_DATA);
  1654. HDE = (cr_data & 0xff) | ((u16) (sr_data & 0x0C) << 6);
  1655. E = HDE + 1;
  1656. vgawb (CRTC_ADR, 0x4);
  1657. cr_data = vgarb (CRTC_DATA);
  1658. HRS = (cr_data & 0xff) | ((u16) (sr_data & 0xC0) << 2);
  1659. F = HRS - E - 3;
  1660. vgawb (CRTC_ADR, 0x2);
  1661. cr_data = vgarb (CRTC_DATA);
  1662. HBS = (cr_data & 0xff) | ((u16) (sr_data & 0x30) << 4);
  1663. vgawb (SEQ_ADR, 0xc);
  1664. sr_data = vgarb (SEQ_DATA);
  1665. vgawb (CRTC_ADR, 0x3);
  1666. cr_data = vgarb (CRTC_DATA);
  1667. vgawb (CRTC_ADR, 0x5);
  1668. cr_data2 = vgarb (CRTC_DATA);
  1669. HBE =
  1670.     (cr_data & 0x1f) | ((u16) (cr_data2 & 0x80) >> 2) |
  1671.     ((u16) (sr_data & 0x03) << 6);
  1672. HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
  1673. temp = HBE - ((E - 1) & 255);
  1674. B = (temp > 0) ? temp : (temp + 256);
  1675. temp = HRE - ((E + F + 3) & 63);
  1676. C = (temp > 0) ? temp : (temp + 64);
  1677. D = B - F - C;
  1678. var->xres = var->xres_virtual = E * 8;
  1679. var->left_margin = D * 8;
  1680. var->right_margin = F * 8;
  1681. var->hsync_len = C * 8;
  1682. var->activate = FB_ACTIVATE_NOW;
  1683. var->sync = 0;
  1684. mr_data = vgarb (0x1C);
  1685. if (mr_data & 0x80)
  1686. var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
  1687. else
  1688. var->sync |= FB_SYNC_VERT_HIGH_ACT;
  1689. if (mr_data & 0x40)
  1690. var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
  1691. else
  1692. var->sync |= FB_SYNC_HOR_HIGH_ACT;
  1693. VT += 2;
  1694. VT <<= 1;
  1695. HT = (HT + 5) * 8;
  1696. hrate = (double) ivideo.refresh_rate * (double) VT / 2;
  1697. drate = hrate * HT;
  1698. var->pixclock = (u32) (1E12 / drate);
  1699. }
  1700. /* ------------------ Public Routines -------------------------------- */
  1701. static int sisfb_get_fix (struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
  1702. {
  1703. memset (fix, 0, sizeof (struct fb_fix_screeninfo));
  1704. strcpy (fix->id, fb_info.modename);
  1705. fix->smem_start = ivideo.video_base;
  1706. /*karl:10/01/2001 */
  1707. if (!sisfb_mem) {
  1708. if (ivideo.video_size > 0x800000)
  1709. fix->smem_len = 0x800000;
  1710. else
  1711. fix->smem_len = 0x400000;
  1712. } else
  1713. fix->smem_len = sisfb_mem * 0x100000;
  1714. fix->type = video_type;
  1715. fix->type_aux = 0;
  1716. if (ivideo.video_bpp == 8)
  1717. fix->visual = FB_VISUAL_PSEUDOCOLOR;
  1718. else
  1719. fix->visual = FB_VISUAL_TRUECOLOR;
  1720. fix->xpanstep = 0;
  1721. fix->ypanstep = 0;
  1722. fix->ywrapstep = 0;
  1723. fix->line_length = video_linelength;
  1724. fix->mmio_start = ivideo.mmio_base;
  1725. fix->mmio_len = sisfb_mmio_size;
  1726. fix->accel = FB_ACCEL_SIS_GLAMOUR;
  1727. fix->reserved[0] = ivideo.video_size & 0xFFFF;
  1728. fix->reserved[1] = (ivideo.video_size >> 16) & 0xFFFF;
  1729. fix->reserved[2] = sisfb_caps;
  1730. return 0;
  1731. }
  1732. static int sisfb_get_var (struct fb_var_screeninfo *var, int con, struct fb_info *info)
  1733. {
  1734. if (con == -1)
  1735. memcpy (var, &default_var, sizeof (struct fb_var_screeninfo));
  1736. else
  1737. *var = fb_display[con].var;
  1738. return 0;
  1739. }
  1740. static int sisfb_set_var (struct fb_var_screeninfo *var, int con, struct fb_info *info)
  1741. {
  1742. int err;
  1743. unsigned int cols, rows;
  1744. fb_display[con].var.activate = FB_ACTIVATE_NOW;
  1745. if (sisfb_do_set_var (var, con == currcon, info)) {
  1746. sisfb_crtc_to_var (var);
  1747. return -EINVAL;
  1748. }
  1749. sisfb_crtc_to_var (var);
  1750. sisfb_set_disp (con, var);
  1751. if (info->changevar)
  1752. (*info->changevar) (con);
  1753. if ((err = fb_alloc_cmap (&fb_display[con].cmap, 0, 0)))
  1754. return err;
  1755. sisfb_do_install_cmap (con, info);
  1756. cols = sisbios_mode[sisfb_mode_idx].cols;
  1757. rows = sisbios_mode[sisfb_mode_idx].rows;
  1758. vc_resize_con (rows, cols, fb_display[con].conp->vc_num);
  1759. return 0;
  1760. }
  1761. static int sisfb_get_cmap (struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
  1762. {
  1763. if (con == currcon)
  1764. return fb_get_cmap (cmap, kspc, sis_getcolreg, info);
  1765. else if (fb_display[con].cmap.len)
  1766. fb_copy_cmap (&fb_display[con].cmap, cmap, kspc ? 0 : 2);
  1767. else
  1768. fb_copy_cmap (fb_default_cmap (video_cmap_len), cmap,
  1769.       kspc ? 0 : 2);
  1770. return 0;
  1771. }
  1772. static int sisfb_set_cmap (struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
  1773. {
  1774. int err;
  1775. if (!fb_display[con].cmap.len) {
  1776. err = fb_alloc_cmap (&fb_display[con].cmap, video_cmap_len, 0);
  1777. if (err)
  1778. return err;
  1779. }
  1780. if (con == currcon)
  1781. return fb_set_cmap (cmap, kspc, sis_setcolreg, info);
  1782. else
  1783. fb_copy_cmap (cmap, &fb_display[con].cmap, kspc ? 0 : 1);
  1784. return 0;
  1785. }
  1786. static int sisfb_ioctl (struct inode *inode, struct file *file,
  1787.      unsigned int cmd, unsigned long arg, int con, struct fb_info *info)
  1788. {
  1789. switch (cmd) {
  1790. case FBIO_ALLOC:
  1791. if (!capable (CAP_SYS_RAWIO))
  1792. return -EPERM;
  1793. sis_malloc ((struct sis_memreq *) arg);
  1794. break;
  1795. case FBIO_FREE:
  1796. if (!capable (CAP_SYS_RAWIO))
  1797. return -EPERM;
  1798. sis_free (*(unsigned long *) arg);
  1799. break;
  1800. case FBIOGET_GLYPH:
  1801. sis_get_glyph ((SIS_GLYINFO *) arg);
  1802. break;
  1803. case FBIOGET_HWCINFO:
  1804. {
  1805. unsigned long *hwc_offset = (unsigned long *) arg;
  1806. if (sisfb_caps & HW_CURSOR_CAP)
  1807. *hwc_offset = sisfb_hwcursor_vbase -
  1808.     (unsigned long) ivideo.video_vbase;
  1809. else
  1810. *hwc_offset = 0;
  1811. break;
  1812. }
  1813. case FBIOPUT_MODEINFO:
  1814. {
  1815. struct mode_info *x = (struct mode_info *) arg;
  1816. ivideo.video_bpp = x->bpp;
  1817. ivideo.video_width = x->xres;
  1818. ivideo.video_height = x->yres;
  1819. ivideo.video_vwidth = x->v_xres;
  1820. ivideo.video_vheight = x->v_yres;
  1821. ivideo.org_x = x->org_x;
  1822. ivideo.org_y = x->org_y;
  1823. ivideo.refresh_rate = x->vrate;
  1824. break;
  1825. }
  1826. case FBIOGET_DISPINFO:
  1827. sis_dispinfo ((struct ap_data *) arg);
  1828. break;
  1829. default:
  1830. return -EINVAL;
  1831. }
  1832. return 0;
  1833. }
  1834. static int sisfb_mmap (struct fb_info *info, struct file *file, struct vm_area_struct *vma)
  1835. {
  1836. struct fb_var_screeninfo var;
  1837. unsigned long start;
  1838. unsigned long off;
  1839. u32 len;
  1840. if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
  1841. return -EINVAL;
  1842. off = vma->vm_pgoff << PAGE_SHIFT;
  1843. start = (unsigned long) ivideo.video_base;
  1844. len = PAGE_ALIGN ((start & ~PAGE_MASK) + ivideo.video_size);
  1845. if (off >= len) {
  1846. off -= len;
  1847. sisfb_get_var (&var, currcon, info);
  1848. if (var.accel_flags)
  1849. return -EINVAL;
  1850. start = (unsigned long) ivideo.mmio_base;
  1851. len = PAGE_ALIGN ((start & ~PAGE_MASK) + sisfb_mmio_size);
  1852. }
  1853. start &= PAGE_MASK;
  1854. if ((vma->vm_end - vma->vm_start + off) > len)
  1855. return -EINVAL;
  1856. off += start;
  1857. vma->vm_pgoff = off >> PAGE_SHIFT;
  1858. #if defined(__i386__)
  1859. if (boot_cpu_data.x86 > 3)
  1860. pgprot_val (vma->vm_page_prot) |= _PAGE_PCD;
  1861. #endif
  1862. if (io_remap_page_range(vma->vm_start, off, vma->vm_end - vma->vm_start, vma->vm_page_prot)) 
  1863. return -EAGAIN;
  1864. return 0;
  1865. }
  1866. static struct fb_ops sisfb_ops = {
  1867. owner:THIS_MODULE,
  1868. fb_get_fix:sisfb_get_fix,
  1869. fb_get_var:sisfb_get_var,
  1870. fb_set_var:sisfb_set_var,
  1871. fb_get_cmap:sisfb_get_cmap,
  1872. fb_set_cmap:sisfb_set_cmap,
  1873. fb_ioctl:sisfb_ioctl,
  1874. fb_mmap:sisfb_mmap,
  1875. };
  1876. /* ------------ Interface to the low level console driver -------------*/
  1877. static int sisfb_update_var (int con, struct fb_info *info)
  1878. {
  1879. return 0;
  1880. }
  1881. static int sisfb_switch (int con, struct fb_info *info)
  1882. {
  1883. int cols, rows;
  1884. if (fb_display[currcon].cmap.len)
  1885. fb_get_cmap (&fb_display[currcon].cmap, 1, sis_getcolreg, info);
  1886. fb_display[con].var.activate = FB_ACTIVATE_NOW;
  1887. if (!memcmp(&fb_display[con].var, &fb_display[currcon].var, sizeof (struct fb_var_screeninfo))) {
  1888. currcon = con;
  1889. return 1;
  1890. }
  1891. currcon = con;
  1892. sisfb_do_set_var (&fb_display[con].var, 1, info);
  1893. sisfb_set_disp (con, &fb_display[con].var);
  1894. sisfb_do_install_cmap (con, info);
  1895. cols = sisbios_mode[sisfb_mode_idx].cols;
  1896. rows = sisbios_mode[sisfb_mode_idx].rows;
  1897. vc_resize_con (rows, cols, fb_display[con].conp->vc_num);
  1898. sisfb_update_var (con, info);
  1899. return 1;
  1900. }
  1901. static void sisfb_blank (int blank, struct fb_info *info)
  1902. {
  1903. u8 reg;
  1904. vgawb (CRTC_ADR, 0x17);
  1905. reg = vgarb (CRTC_DATA);
  1906. if (blank > 0)
  1907. reg &= 0x7f;
  1908. else
  1909. reg |= 0x80;
  1910. vgawb (CRTC_ADR, 0x17);
  1911. vgawb (CRTC_DATA, reg);
  1912. }
  1913. int sisfb_setup (char *options)
  1914. {
  1915. char *this_opt;
  1916. fb_info.fontname[0] = '';
  1917. ivideo.refresh_rate = 0;
  1918. if (!options || !*options)
  1919. return 0;
  1920. for (this_opt = strtok (options, ","); this_opt;
  1921.      this_opt = strtok (NULL, ",")) {
  1922. if (!*this_opt)
  1923. continue;
  1924. if (!strcmp (this_opt, "inverse")) {
  1925. sisfb_inverse = 1;
  1926. fb_invert_cmaps ();
  1927. } else if (!strncmp (this_opt, "font:", 5)) {
  1928. strcpy (fb_info.fontname, this_opt + 5);
  1929. } else if (!strncmp (this_opt, "mode:", 5)) {
  1930. sisfb_search_mode (this_opt + 5);
  1931. } else if (!strncmp (this_opt, "vrate:", 6)) {
  1932. ivideo.refresh_rate =
  1933.     simple_strtoul (this_opt + 6, NULL, 0);
  1934. } else if (!strncmp (this_opt, "off", 3)) {
  1935. sisfb_off = 1;
  1936. } else if (!strncmp (this_opt, "crt1off", 7)) {
  1937. sisfb_crt1off = 1;
  1938. } else if (!strncmp (this_opt, "filter:", 7)) {
  1939. filter = (int) simple_strtoul (this_opt + 7, NULL, 0);
  1940. }
  1941. /*karl */
  1942. else if (!strncmp (this_opt, "tvmode:", 7)) {
  1943. if (!strncmp (this_opt + 7, "pal", 3))
  1944. sisfb_tvmode = 1;
  1945. if (!strncmp (this_opt + 7, "ntsc", 4))
  1946. sisfb_tvmode = 2;
  1947. }
  1948. /*karl:10/01/2001 */
  1949. else if (!strncmp (this_opt, "mem:", 4)) {
  1950. sisfb_mem = simple_strtoul (this_opt + 4, NULL, 0);
  1951. } else
  1952. DPRINTK ("invalid parameter %sn", this_opt);
  1953. }
  1954. return 0;
  1955. }
  1956. int __init sisfb_init (void)
  1957. {
  1958. struct pci_dev *pdev = NULL;
  1959. struct board *b;
  1960. int pdev_valid = 0;
  1961. //unsigned long rom_vbase;
  1962. u32 reg32;
  1963. u16 reg16;
  1964. u8 reg;
  1965. int nRes;
  1966. outb (0x77, 0x80);
  1967. if (sisfb_off)
  1968. return -ENXIO;
  1969. pci_for_each_dev (pdev)
  1970. {
  1971. for (b = sisdev_list; b->vendor; b++) {
  1972. if ((b->vendor == pdev->vendor)
  1973.     && (b->device == pdev->device)) {
  1974. pdev_valid = 1;
  1975. strcpy (fb_info.modename, b->name);
  1976. ivideo.chip_id = pdev->device;
  1977. pci_read_config_byte (pdev, PCI_REVISION_ID,
  1978.       &ivideo.revision_id);
  1979. pci_read_config_word (pdev, PCI_COMMAND, &reg16);
  1980. // Eden Chen
  1981. //sishw_ext.uRevisionID = ivideo.revision_id;
  1982. sishw_ext.jChipRevision = ivideo.revision_id;
  1983. // ~Eden Chen
  1984. sisvga_enabled = reg16 & 0x1;
  1985. break;
  1986. }
  1987. }
  1988. if (pdev_valid)
  1989. break;
  1990. }
  1991. if (!pdev_valid)
  1992. return -1;
  1993. // Eden Chen
  1994. switch (ivideo.chip_id) {
  1995. case PCI_DEVICE_ID_SI_300:
  1996. ivideo.chip = SIS_300;
  1997. sisvga_engine = SIS_300_VGA;
  1998. break;
  1999. case PCI_DEVICE_ID_SI_630_VGA:
  2000. {
  2001. sisfb_set_reg4 (0xCF8, 0x80000000);
  2002. reg32 = sisfb_get_reg3 (0xCFC);
  2003. if (reg32 == 0x07301039) {
  2004. ivideo.chip = SIS_730;
  2005. strcpy (fb_info.modename, "SIS 730");
  2006. } else
  2007. ivideo.chip = SIS_630;
  2008. sisvga_engine = SIS_300_VGA;
  2009. break;
  2010. }
  2011. case PCI_DEVICE_ID_SI_540_VGA:
  2012. ivideo.chip = SIS_540;
  2013. sisvga_engine = SIS_300_VGA;
  2014. break;
  2015. case PCI_DEVICE_ID_SI_315H:
  2016. ivideo.chip = SIS_315H;
  2017. sisvga_engine = SIS_315_VGA;
  2018. break;
  2019. case PCI_DEVICE_ID_SI_315:
  2020. ivideo.chip = SIS_315;
  2021. sisvga_engine = SIS_315_VGA;
  2022. break;
  2023. case PCI_DEVICE_ID_SI_315PRO:
  2024. ivideo.chip = SIS_315PRO;
  2025. sisvga_engine = SIS_315_VGA;
  2026. break;
  2027. case PCI_DEVICE_ID_SI_550_VGA:
  2028. ivideo.chip = SIS_550;
  2029. sisvga_engine = SIS_315_VGA;
  2030. break;
  2031. }
  2032. // Eden Chen
  2033. //sishw_ext.jChipID = ivideo.chip;
  2034. sishw_ext.jChipType = ivideo.chip;
  2035. // for Debug
  2036. if ((sishw_ext.jChipType == SIS_315PRO)
  2037.     || (sishw_ext.jChipType == SIS_315))
  2038. sishw_ext.jChipType = SIS_315H;
  2039. // ~Eden Chen
  2040. DPRINTK ("%s is used as %s device(VGA Engine %d).n",
  2041.  fb_info.modename, sisvga_enabled ? "primary" : "secondary",
  2042.  sisvga_engine);
  2043. ivideo.video_base = pci_resource_start (pdev, 0);
  2044. ivideo.mmio_base = pci_resource_start (pdev, 1);
  2045. // Eden Chen
  2046. //sishw_ext.IOAddress = (unsigned short) ivideo.vga_base 
  2047. //      = pci_resource_start(pdev, 2) + 0x30;
  2048. sishw_ext.ulIOAddress = (unsigned short) ivideo.vga_base = pci_resource_start (pdev, 2) + 0x30;
  2049. // ~Eden Chen
  2050. sisfb_mmio_size = pci_resource_len (pdev, 1);
  2051. if (!sisvga_enabled)
  2052. if (pci_enable_device (pdev))
  2053. return -EIO;
  2054. vgawb (SEQ_ADR, IND_SIS_PASSWORD);
  2055. vgawb (SEQ_DATA, SIS_PASSWORD);
  2056. #ifdef LINUXBIOS
  2057. #ifdef CONFIG_FB_SIS_300
  2058. if (sisvga_engine == SIS_300_VGA)
  2059. {
  2060. vgawb (SEQ_ADR, 0x28);
  2061. vgawb (SEQ_DATA, 0x37);
  2062. vgawb (SEQ_ADR, 0x29);
  2063. vgawb (SEQ_DATA, 0x61);
  2064. vgawb (SEQ_ADR, IND_SIS_SCRATCH_REG_1A);
  2065. reg = vgarb (SEQ_DATA);
  2066. reg |= SIS_SCRATCH_REG_1A_MASK;
  2067. vgawb (SEQ_DATA, reg);
  2068. }
  2069. #endif
  2070. #ifdef CONFIG_FB_SIS_315
  2071. if (ivideo.chip == SIS_550) {
  2072. vgawb (SEQ_ADR, 0x28);
  2073. vgawb (SEQ_DATA, 0x5A);
  2074. vgawb (SEQ_ADR, 0x29);
  2075. vgawb (SEQ_DATA, 0x64);
  2076. vgawb (CRTC_ADR, 0x3A);
  2077. vgawb (CRTC_DATA, 0x00);
  2078. }
  2079. #endif
  2080. #endif
  2081. if (sisvga_engine == SIS_315_VGA) {
  2082. switch (ivideo.chip) {
  2083. case SIS_315H:
  2084. case SIS_315:
  2085. sishw_ext.bIntegratedMMEnabled = TRUE;
  2086. break;
  2087. case SIS_550:
  2088. // Eden Chen
  2089. //vgawb(SEQ_ADR, IND_SIS_SCRATCH_REG_1A);
  2090. //reg = vgarb(SEQ_DATA);
  2091. //if (reg & SIS_SCRATCH_REG_1A_MASK)
  2092. //      sishw_ext.bIntegratedMMEnabled = TRUE;
  2093. //else
  2094. //      sishw_ext.bIntegratedMMEnabled = FALSE;
  2095. //for Debug
  2096. sishw_ext.bIntegratedMMEnabled = TRUE;
  2097. // ~Eden Chen
  2098. break;
  2099. default:
  2100. break;
  2101. }
  2102. } else if (sisvga_engine == SIS_300_VGA) {
  2103. if (ivideo.chip == SIS_300) {
  2104. sishw_ext.bIntegratedMMEnabled = TRUE;
  2105. } else {
  2106. vgawb (SEQ_ADR, IND_SIS_SCRATCH_REG_1A);
  2107. reg = vgarb (SEQ_DATA);
  2108. if (reg & SIS_SCRATCH_REG_1A_MASK)
  2109. sishw_ext.bIntegratedMMEnabled = TRUE;
  2110. else
  2111. sishw_ext.bIntegratedMMEnabled = FALSE;
  2112. }
  2113. }
  2114. // Eden Chen
  2115. sishw_ext.pDevice = NULL;
  2116. sishw_ext.pjVirtualRomBase = NULL;
  2117. sishw_ext.pjCustomizedROMImage = NULL;
  2118. sishw_ext.bSkipDramSizing = 0;
  2119. sishw_ext.pQueryVGAConfigSpace = &sisfb_query_VGA_config_space;
  2120. sishw_ext.pQueryNorthBridgeSpace = &sisfb_query_north_bridge_space;
  2121. strcpy (sishw_ext.szVBIOSVer, "0.84");
  2122. sishw_ext.pSR = vmalloc (sizeof (SIS_DSReg) * SR_BUFFER_SIZE);
  2123. if (sishw_ext.pSR == NULL)
  2124. printk (KERN_DEBUG "Allocated SRReg space fail.n");
  2125. sishw_ext.pSR[0].jIdx = sishw_ext.pSR[0].jVal = 0xFF;
  2126. sishw_ext.pCR = vmalloc (sizeof (SIS_DSReg) * CR_BUFFER_SIZE);
  2127. if (sishw_ext.pCR == NULL)
  2128. printk (KERN_DEBUG "Allocated CRReg space fail.n");
  2129. sishw_ext.pCR[0].jIdx = sishw_ext.pCR[0].jVal = 0xFF;
  2130. // ~Eden Chen
  2131. #ifdef CONFIG_FB_SIS_300
  2132. if (sisvga_engine == SIS_300_VGA) {
  2133. if (!sisvga_enabled) {
  2134. // Eden Chen
  2135. sishw_ext.pjVideoMemoryAddress = ioremap (ivideo.video_base, 0x2000000);
  2136. //SiSInit300(&sishw_ext);
  2137. SiSInit (&sishw_ext);
  2138. vgawb (SEQ_ADR, IND_SIS_PASSWORD);
  2139. vgawb (SEQ_DATA, SIS_PASSWORD);
  2140. // ~Eden Chen
  2141. }
  2142. #ifdef LINUXBIOS
  2143. else {
  2144. // Eden Chen
  2145. sishw_ext.pjVideoMemoryAddress
  2146.     = ioremap (ivideo.video_base, 0x2000000);
  2147. //SiSInit300(&sishw_ext);
  2148. SiSInit (&sishw_ext);
  2149. vgawb (SEQ_ADR, IND_SIS_PASSWORD);
  2150. vgawb (SEQ_DATA, SIS_PASSWORD);
  2151. // ~Eden Chen
  2152. }
  2153. vgawb (SEQ_ADR, 0x7);
  2154. reg = vgarb (SEQ_DATA);
  2155. reg |= 0x10;
  2156. vgawb (SEQ_DATA, reg);
  2157. #endif
  2158. sisfb_get_dram_size_300 ();
  2159. }
  2160. #endif
  2161. #ifdef CONFIG_FB_SIS_315
  2162. if (sisvga_engine == SIS_315_VGA) {
  2163. if (!sisvga_enabled) {
  2164. /* Mapping Max FB Size for 315 Init */
  2165. // Eden Chen
  2166. //sishw_ext.VirtualVideoMemoryAddress 
  2167. sishw_ext.pjVideoMemoryAddress = ioremap (ivideo.video_base, 0x8000000);
  2168. //SiSInit310(&sishw_ext);
  2169. SiSInit (&sishw_ext);
  2170. vgawb (SEQ_ADR, IND_SIS_PASSWORD);
  2171. vgawb (SEQ_DATA, SIS_PASSWORD);
  2172. sishw_ext.bSkipDramSizing = TRUE;
  2173. vgawb (SEQ_ADR, 0x13);
  2174. sishw_ext.pSR[0].jIdx = 0x13;
  2175. sishw_ext.pSR[0].jVal = vgarb (SEQ_DATA);
  2176. vgawb (SEQ_ADR, 0x14);
  2177. sishw_ext.pSR[1].jIdx = 0x14;
  2178. sishw_ext.pSR[1].jVal = vgarb (SEQ_DATA);
  2179. sishw_ext.pSR[2].jIdx = 0xFF;
  2180. sishw_ext.pSR[2].jVal = 0xFF;
  2181. // Eden Chen
  2182. }
  2183. #ifdef LINUXBIOS
  2184. else {
  2185. sishw_ext.pjVideoMemoryAddress = ioremap (ivideo.video_base, 0x8000000);
  2186. SiSInit (&sishw_ext);
  2187. vgawb (SEQ_ADR, IND_SIS_PASSWORD);
  2188. vgawb (SEQ_DATA, SIS_PASSWORD);
  2189. sishw_ext.bSkipDramSizing = TRUE;
  2190. vgawb (SEQ_ADR, 0x13);
  2191. sishw_ext.pSR[0].jIdx = 0x13;
  2192. sishw_ext.pSR[0].jVal = vgarb (SEQ_DATA);
  2193. vgawb (SEQ_ADR, 0x14);
  2194. sishw_ext.pSR[1].jIdx = 0x14;
  2195. sishw_ext.pSR[1].jVal = vgarb (SEQ_DATA);
  2196. sishw_ext.pSR[2].jIdx = 0xFF;
  2197. sishw_ext.pSR[2].jVal = 0xFF;
  2198. }
  2199. #endif
  2200. sisfb_get_dram_size_315 ();
  2201. }
  2202. #endif
  2203. //Eden Chen 
  2204. vgawb (SEQ_ADR, IND_SIS_PCI_ADDRESS_SET);
  2205. reg = vgarb (SEQ_DATA);
  2206. reg |= SIS_PCI_ADDR_ENABLE;
  2207. reg |= SIS_MEM_MAP_IO_ENABLE;
  2208. vgawb (SEQ_DATA, reg);
  2209. vgawb (SEQ_ADR, IND_SIS_MODULE_ENABLE);
  2210. reg = vgarb (SEQ_DATA);
  2211. reg |= SIS_ENABLE_2D;
  2212. vgawb (SEQ_DATA, reg);
  2213. //~Eden Chen
  2214. // Eden Chen
  2215. sishw_ext.ulVideoMemorySize = ivideo.video_size;
  2216. // ~Eden Chen
  2217. if (!request_mem_region (ivideo.video_base, ivideo.video_size, "sisfb FB")) {
  2218. printk (KERN_ERR "sisfb: cannot reserve frame buffer memoryn");
  2219. return -ENODEV;
  2220. }
  2221. if (!request_mem_region (ivideo.mmio_base, sisfb_mmio_size, "sisfb MMIO")) {
  2222. printk (KERN_ERR "sisfb: cannot reserve MMIO regionn");
  2223. release_mem_region (ivideo.video_base, ivideo.video_size);
  2224. return -ENODEV;
  2225. }
  2226. // Eden Chen
  2227. //sishw_ext.VirtualVideoMemoryAddress = ivideo.video_vbase 
  2228. sishw_ext.pjVideoMemoryAddress = ivideo.video_vbase = ioremap (ivideo.video_base, ivideo.video_size);
  2229. // Eden Chen
  2230. ivideo.mmio_vbase = ioremap (ivideo.mmio_base, sisfb_mmio_size);
  2231. printk (KERN_INFO
  2232. "sisfb: framebuffer at 0x%lx, mapped to 0x%p, size %dkn",
  2233. ivideo.video_base, ivideo.video_vbase, ivideo.video_size / 1024);
  2234. printk (KERN_INFO
  2235. "sisfb: MMIO at 0x%lx, mapped to 0x%p, size %ldkn",
  2236. ivideo.mmio_base, ivideo.mmio_vbase, sisfb_mmio_size / 1024);
  2237. #ifdef CONFIG_FB_SIS_300
  2238. if (sisvga_engine == SIS_300_VGA) {
  2239. sisfb_get_VB_type_300 ();
  2240. if (ivideo.hasVB != HASVB_NONE) {
  2241. sisfb_detect_VB_connect_300 ();
  2242. }
  2243. }
  2244. #endif
  2245. #ifdef CONFIG_FB_SIS_315
  2246. if (sisvga_engine == SIS_315_VGA) {
  2247. sisfb_get_VB_type_315 ();
  2248. if (ivideo.hasVB != HASVB_NONE) {
  2249. sisfb_detect_VB_connect_315 ();
  2250. }
  2251. }
  2252. #endif
  2253. // Eden Chen
  2254. sishw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
  2255. sishw_ext.usExternalChip = 0;
  2256. switch (ivideo.hasVB) {
  2257. case HASVB_301:
  2258. /*karl */
  2259. vgawb (VB_PART4_ADR, 0x01);
  2260. reg = vgarb (VB_PART4_DATA);
  2261. if ((reg != 0xB1) && (reg != 0xB0))
  2262. sishw_ext.ujVBChipID = VB_CHIP_301;
  2263. else
  2264. sishw_ext.ujVBChipID = VB_CHIP_301B;
  2265. break;
  2266. case HASVB_302:
  2267. sishw_ext.ujVBChipID = VB_CHIP_302;
  2268. break;
  2269. case HASVB_303:
  2270. sishw_ext.ujVBChipID = VB_CHIP_303;
  2271. break;
  2272. case HASVB_LVDS:
  2273. sishw_ext.usExternalChip = 0x1;
  2274. break;
  2275. case HASVB_TRUMPION:
  2276. sishw_ext.usExternalChip = 0x2;
  2277. break;
  2278. case HASVB_CHRONTEL:
  2279. sishw_ext.usExternalChip = 0x4;
  2280. break;
  2281. case HASVB_LVDS_CHRONTEL:
  2282. sishw_ext.usExternalChip = 0x5;
  2283. break;
  2284. default:
  2285. break;
  2286. }
  2287. // ~Eden Chen
  2288. if (ivideo.disp_state & DISPTYPE_DISP2) {
  2289. if (sisfb_crt1off)
  2290. ivideo.disp_state |= DISPMODE_SINGLE;
  2291. else
  2292. ivideo.disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1);
  2293. } else
  2294. ivideo.disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1;
  2295. if (ivideo.disp_state & DISPTYPE_LCD) {
  2296. vgawb (CRTC_ADR, IND_SIS_LCD_PANEL);
  2297. reg = vgarb (CRTC_DATA);
  2298. // Eden Chen
  2299. switch (reg) {
  2300. case SIS_LCD_PANEL_800X600:
  2301. sishw_ext.ulCRT2LCDType = LCD_800x600;
  2302. break;
  2303. case SIS_LCD_PANEL_1024X768:
  2304. sishw_ext.ulCRT2LCDType = LCD_1024x768;
  2305. break;
  2306. case SIS_LCD_PANEL_1280X1024:
  2307. sishw_ext.ulCRT2LCDType = LCD_1280x1024;
  2308. break;
  2309. case SIS_LCD_PANEL_640X480:
  2310. sishw_ext.ulCRT2LCDType = LCD_640x480;
  2311. break;
  2312. case SIS_LCD_PANEL_1280X960:
  2313. sishw_ext.ulCRT2LCDType = LCD_1280x960;
  2314. break;
  2315. default:
  2316. sishw_ext.ulCRT2LCDType = LCD_1024x768;
  2317. break;
  2318. }
  2319. // ~Eden Chen
  2320. }
  2321. if (sisfb_mode_idx >= 0)
  2322. sisfb_validate_mode ();
  2323. if (sisfb_mode_idx < 0) {
  2324. switch (ivideo.disp_state & DISPTYPE_DISP2) {
  2325. case DISPTYPE_LCD:
  2326. sisfb_mode_idx = DEFAULT_LCDMODE;
  2327. break;
  2328. case DISPTYPE_TV:
  2329. sisfb_mode_idx = DEFAULT_TVMODE;
  2330. break;
  2331. default:
  2332. sisfb_mode_idx = DEFAULT_MODE;
  2333. break;
  2334. }
  2335. }
  2336. sisfb_mode_no = sisbios_mode[sisfb_mode_idx].mode_no;
  2337. if (ivideo.refresh_rate != 0)
  2338. sisfb_search_refresh_rate (ivideo.refresh_rate);
  2339. if (sisfb_rate_idx == 0) {
  2340. sisfb_rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;
  2341. ivideo.refresh_rate = 60;
  2342. }
  2343. ivideo.video_bpp = sisbios_mode[sisfb_mode_idx].bpp;
  2344. ivideo.video_vwidth = ivideo.video_width = sisbios_mode[sisfb_mode_idx].xres;
  2345. ivideo.video_vheight = ivideo.video_height = sisbios_mode[sisfb_mode_idx].yres;
  2346. ivideo.org_x = ivideo.org_y = 0;
  2347. video_linelength = ivideo.video_width * (ivideo.video_bpp >> 3);
  2348. printk (KERN_INFO "sisfb: mode is %dx%dx%d, linelength=%dn",
  2349. ivideo.video_width, ivideo.video_height, ivideo.video_bpp,
  2350. video_linelength);
  2351. // Eden Chen
  2352. // Check interface correction  For Debug
  2353. DPRINTK ("VM Adr=0x%pn", sishw_ext.pjVideoMemoryAddress);
  2354. DPRINTK ("VM Size=%ldKn", sishw_ext.ulVideoMemorySize / 1024);
  2355. DPRINTK ("IO Adr=0x%lxn", sishw_ext.ulIOAddress);
  2356. DPRINTK ("Chip=%dn", sishw_ext.jChipType);
  2357. DPRINTK ("ChipRevision=%dn", sishw_ext.jChipRevision);
  2358. DPRINTK ("VBChip=%dn", sishw_ext.ujVBChipID);
  2359. DPRINTK ("ExtVB=%dn", sishw_ext.usExternalChip);
  2360. DPRINTK ("LCD=%ldn", sishw_ext.ulCRT2LCDType);
  2361. DPRINTK ("bIntegratedMMEnabled=%dn", sishw_ext.bIntegratedMMEnabled);
  2362. // ~Eden Chen
  2363. sisfb_pre_setmode ();
  2364. if (SiSSetMode (&sishw_ext, sisfb_mode_no) == 0) {
  2365. DPRINTK ("set mode[0x%x]: failedn", sisfb_mode_no);
  2366. return -1;
  2367. }
  2368. vgawb (SEQ_ADR, IND_SIS_PASSWORD);
  2369. vgawb (SEQ_DATA, SIS_PASSWORD);
  2370. // Eden Chen
  2371. sisfb_post_setmode ();
  2372. sisfb_crtc_to_var (&default_var);
  2373. fb_info.changevar = NULL;
  2374. fb_info.node = -1;
  2375. fb_info.fbops = &sisfb_ops;
  2376. fb_info.disp = &disp;
  2377. fb_info.switch_con = &sisfb_switch;
  2378. fb_info.updatevar = &sisfb_update_var;
  2379. fb_info.blank = &sisfb_blank;
  2380. fb_info.flags = FBINFO_FLAG_DEFAULT;
  2381. sisfb_set_disp (-1, &default_var);
  2382. if (sisfb_heap_init ()) {
  2383. DPRINTK ("sisfb: Failed to enable offscreen heapn");
  2384. }
  2385. /*H.C. */
  2386. nRes =  mtrr_add ((unsigned int) ivideo.video_base, (unsigned int) ivideo.video_size,  MTRR_TYPE_WRCOMB, 1);
  2387. vc_resize_con (1, 1, 0);
  2388. if (register_framebuffer (&fb_info) < 0)
  2389. return -EINVAL;
  2390. printk (KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02dn",
  2391. GET_FB_IDX (fb_info.node), fb_info.modename, VER_MAJOR, VER_MINOR,
  2392. VER_LEVEL);
  2393. return 0;
  2394. }
  2395. #ifdef MODULE
  2396. static char *mode = NULL;
  2397. static unsigned int rate = 0;
  2398. static unsigned int crt1 = 1;
  2399. MODULE_PARM (mode, "s");
  2400. MODULE_PARM (rate, "i");
  2401. MODULE_PARM (crt1, "i");
  2402. MODULE_PARM (filter, "i");
  2403. int init_module (void)
  2404. {
  2405. if (mode)
  2406. sisfb_search_mode (mode);
  2407. ivideo.refresh_rate = rate;
  2408. if (crt1 == 0)
  2409. sisfb_crt1off = 1;
  2410. else
  2411. sisfb_crt1off = 0;
  2412. sisfb_init ();
  2413. return 0;
  2414. }
  2415. void cleanup_module (void)
  2416. {
  2417. unregister_framebuffer (&fb_info);
  2418. }
  2419. #endif
  2420. EXPORT_SYMBOL (sis_malloc);
  2421. EXPORT_SYMBOL (sis_free);
  2422. EXPORT_SYMBOL (sis_dispinfo);
  2423. EXPORT_SYMBOL (ivideo);