PageRenderTime 211ms CodeModel.GetById 19ms RepoModel.GetById 2ms app.codeStats 3ms

/drivers/video/sis/sis_main.c

https://bitbucket.org/slukk/jb-tsm-kernel-4.2
C | 6893 lines | 5707 code | 912 blank | 274 comment | 1588 complexity | b7a04ec041fc4b313d8bc981fab44fb9 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1. /*
  2. * SiS 300/540/630[S]/730[S],
  3. * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX],
  4. * XGI V3XT/V5/V8, Z7
  5. * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
  6. *
  7. * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the named License,
  12. * or any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
  22. *
  23. * Author: Thomas Winischhofer <thomas@winischhofer.net>
  24. *
  25. * Author of (practically wiped) code base:
  26. * SiS (www.sis.com)
  27. * Copyright (C) 1999 Silicon Integrated Systems, Inc.
  28. *
  29. * See http://www.winischhofer.net/ for more information and updates
  30. *
  31. * Originally based on the VBE 2.0 compliant graphic boards framebuffer driver,
  32. * which is (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
  33. *
  34. */
  35. #include <linux/module.h>
  36. #include <linux/moduleparam.h>
  37. #include <linux/kernel.h>
  38. #include <linux/spinlock.h>
  39. #include <linux/errno.h>
  40. #include <linux/string.h>
  41. #include <linux/mm.h>
  42. #include <linux/screen_info.h>
  43. #include <linux/slab.h>
  44. #include <linux/fb.h>
  45. #include <linux/selection.h>
  46. #include <linux/ioport.h>
  47. #include <linux/init.h>
  48. #include <linux/pci.h>
  49. #include <linux/vmalloc.h>
  50. #include <linux/capability.h>
  51. #include <linux/fs.h>
  52. #include <linux/types.h>
  53. #include <linux/uaccess.h>
  54. #include <asm/io.h>
  55. #ifdef CONFIG_MTRR
  56. #include <asm/mtrr.h>
  57. #endif
  58. #include "sis.h"
  59. #include "sis_main.h"
  60. #if !defined(CONFIG_FB_SIS_300) && !defined(CONFIG_FB_SIS_315)
  61. #warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
  62. #warning sisfb will not work!
  63. #endif
  64. static void sisfb_handle_command(struct sis_video_info *ivideo,
  65. struct sisfb_cmd *sisfb_command);
  66. /* ------------------ Internal helper routines ----------------- */
  67. static void __init
  68. sisfb_setdefaultparms(void)
  69. {
  70. sisfb_off = 0;
  71. sisfb_parm_mem = 0;
  72. sisfb_accel = -1;
  73. sisfb_ypan = -1;
  74. sisfb_max = -1;
  75. sisfb_userom = -1;
  76. sisfb_useoem = -1;
  77. sisfb_mode_idx = -1;
  78. sisfb_parm_rate = -1;
  79. sisfb_crt1off = 0;
  80. sisfb_forcecrt1 = -1;
  81. sisfb_crt2type = -1;
  82. sisfb_crt2flags = 0;
  83. sisfb_pdc = 0xff;
  84. sisfb_pdca = 0xff;
  85. sisfb_scalelcd = -1;
  86. sisfb_specialtiming = CUT_NONE;
  87. sisfb_lvdshl = -1;
  88. sisfb_dstn = 0;
  89. sisfb_fstn = 0;
  90. sisfb_tvplug = -1;
  91. sisfb_tvstd = -1;
  92. sisfb_tvxposoffset = 0;
  93. sisfb_tvyposoffset = 0;
  94. sisfb_nocrt2rate = 0;
  95. #if !defined(__i386__) && !defined(__x86_64__)
  96. sisfb_resetcard = 0;
  97. sisfb_videoram = 0;
  98. #endif
  99. }
  100. /* ------------- Parameter parsing -------------- */
  101. static void __devinit
  102. sisfb_search_vesamode(unsigned int vesamode, bool quiet)
  103. {
  104. int i = 0, j = 0;
  105. /* We don't know the hardware specs yet and there is no ivideo */
  106. if(vesamode == 0) {
  107. if(!quiet)
  108. printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
  109. sisfb_mode_idx = DEFAULT_MODE;
  110. return;
  111. }
  112. vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
  113. while(sisbios_mode[i++].mode_no[0] != 0) {
  114. if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
  115. (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
  116. if(sisfb_fstn) {
  117. if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
  118. sisbios_mode[i-1].mode_no[1] == 0x56 ||
  119. sisbios_mode[i-1].mode_no[1] == 0x53)
  120. continue;
  121. } else {
  122. if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
  123. sisbios_mode[i-1].mode_no[1] == 0x5b)
  124. continue;
  125. }
  126. sisfb_mode_idx = i - 1;
  127. j = 1;
  128. break;
  129. }
  130. }
  131. if((!j) && !quiet)
  132. printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
  133. }
  134. static void __devinit
  135. sisfb_search_mode(char *name, bool quiet)
  136. {
  137. unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
  138. int i = 0;
  139. char strbuf[16], strbuf1[20];
  140. char *nameptr = name;
  141. /* We don't know the hardware specs yet and there is no ivideo */
  142. if(name == NULL) {
  143. if(!quiet)
  144. printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
  145. sisfb_mode_idx = DEFAULT_MODE;
  146. return;
  147. }
  148. if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
  149. if(!quiet)
  150. printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
  151. sisfb_mode_idx = DEFAULT_MODE;
  152. return;
  153. }
  154. if(strlen(name) <= 19) {
  155. strcpy(strbuf1, name);
  156. for(i = 0; i < strlen(strbuf1); i++) {
  157. if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
  158. }
  159. /* This does some fuzzy mode naming detection */
  160. if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
  161. if((rate <= 32) || (depth > 32)) {
  162. j = rate; rate = depth; depth = j;
  163. }
  164. sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
  165. nameptr = strbuf;
  166. sisfb_parm_rate = rate;
  167. } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
  168. sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
  169. nameptr = strbuf;
  170. } else {
  171. xres = 0;
  172. if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
  173. sprintf(strbuf, "%ux%ux8", xres, yres);
  174. nameptr = strbuf;
  175. } else {
  176. sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
  177. return;
  178. }
  179. }
  180. }
  181. i = 0; j = 0;
  182. while(sisbios_mode[i].mode_no[0] != 0) {
  183. if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
  184. if(sisfb_fstn) {
  185. if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
  186. sisbios_mode[i-1].mode_no[1] == 0x56 ||
  187. sisbios_mode[i-1].mode_no[1] == 0x53)
  188. continue;
  189. } else {
  190. if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
  191. sisbios_mode[i-1].mode_no[1] == 0x5b)
  192. continue;
  193. }
  194. sisfb_mode_idx = i - 1;
  195. j = 1;
  196. break;
  197. }
  198. }
  199. if((!j) && !quiet)
  200. printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
  201. }
  202. #ifndef MODULE
  203. static void __devinit
  204. sisfb_get_vga_mode_from_kernel(void)
  205. {
  206. #ifdef CONFIG_X86
  207. char mymode[32];
  208. int mydepth = screen_info.lfb_depth;
  209. if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return;
  210. if( (screen_info.lfb_width >= 320) && (screen_info.lfb_width <= 2048) &&
  211. (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) &&
  212. (mydepth >= 8) && (mydepth <= 32) ) {
  213. if(mydepth == 24) mydepth = 32;
  214. sprintf(mymode, "%ux%ux%u", screen_info.lfb_width,
  215. screen_info.lfb_height,
  216. mydepth);
  217. printk(KERN_DEBUG
  218. "sisfb: Using vga mode %s pre-set by kernel as default\n",
  219. mymode);
  220. sisfb_search_mode(mymode, true);
  221. }
  222. #endif
  223. return;
  224. }
  225. #endif
  226. static void __init
  227. sisfb_search_crt2type(const char *name)
  228. {
  229. int i = 0;
  230. /* We don't know the hardware specs yet and there is no ivideo */
  231. if(name == NULL) return;
  232. while(sis_crt2type[i].type_no != -1) {
  233. if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
  234. sisfb_crt2type = sis_crt2type[i].type_no;
  235. sisfb_tvplug = sis_crt2type[i].tvplug_no;
  236. sisfb_crt2flags = sis_crt2type[i].flags;
  237. break;
  238. }
  239. i++;
  240. }
  241. sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0;
  242. sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0;
  243. if(sisfb_crt2type < 0)
  244. printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
  245. }
  246. static void __init
  247. sisfb_search_tvstd(const char *name)
  248. {
  249. int i = 0;
  250. /* We don't know the hardware specs yet and there is no ivideo */
  251. if(name == NULL)
  252. return;
  253. while(sis_tvtype[i].type_no != -1) {
  254. if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
  255. sisfb_tvstd = sis_tvtype[i].type_no;
  256. break;
  257. }
  258. i++;
  259. }
  260. }
  261. static void __init
  262. sisfb_search_specialtiming(const char *name)
  263. {
  264. int i = 0;
  265. bool found = false;
  266. /* We don't know the hardware specs yet and there is no ivideo */
  267. if(name == NULL)
  268. return;
  269. if(!strnicmp(name, "none", 4)) {
  270. sisfb_specialtiming = CUT_FORCENONE;
  271. printk(KERN_DEBUG "sisfb: Special timing disabled\n");
  272. } else {
  273. while(mycustomttable[i].chipID != 0) {
  274. if(!strnicmp(name,mycustomttable[i].optionName,
  275. strlen(mycustomttable[i].optionName))) {
  276. sisfb_specialtiming = mycustomttable[i].SpecialID;
  277. found = true;
  278. printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
  279. mycustomttable[i].vendorName,
  280. mycustomttable[i].cardName,
  281. mycustomttable[i].optionName);
  282. break;
  283. }
  284. i++;
  285. }
  286. if(!found) {
  287. printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
  288. printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
  289. i = 0;
  290. while(mycustomttable[i].chipID != 0) {
  291. printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
  292. mycustomttable[i].optionName,
  293. mycustomttable[i].vendorName,
  294. mycustomttable[i].cardName);
  295. i++;
  296. }
  297. }
  298. }
  299. }
  300. /* ----------- Various detection routines ----------- */
  301. static void __devinit
  302. sisfb_detect_custom_timing(struct sis_video_info *ivideo)
  303. {
  304. unsigned char *biosver = NULL;
  305. unsigned char *biosdate = NULL;
  306. bool footprint;
  307. u32 chksum = 0;
  308. int i, j;
  309. if(ivideo->SiS_Pr.UseROM) {
  310. biosver = ivideo->SiS_Pr.VirtualRomBase + 0x06;
  311. biosdate = ivideo->SiS_Pr.VirtualRomBase + 0x2c;
  312. for(i = 0; i < 32768; i++)
  313. chksum += ivideo->SiS_Pr.VirtualRomBase[i];
  314. }
  315. i = 0;
  316. do {
  317. if( (mycustomttable[i].chipID == ivideo->chip) &&
  318. ((!strlen(mycustomttable[i].biosversion)) ||
  319. (ivideo->SiS_Pr.UseROM &&
  320. (!strncmp(mycustomttable[i].biosversion, biosver,
  321. strlen(mycustomttable[i].biosversion))))) &&
  322. ((!strlen(mycustomttable[i].biosdate)) ||
  323. (ivideo->SiS_Pr.UseROM &&
  324. (!strncmp(mycustomttable[i].biosdate, biosdate,
  325. strlen(mycustomttable[i].biosdate))))) &&
  326. ((!mycustomttable[i].bioschksum) ||
  327. (ivideo->SiS_Pr.UseROM &&
  328. (mycustomttable[i].bioschksum == chksum))) &&
  329. (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
  330. (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
  331. footprint = true;
  332. for(j = 0; j < 5; j++) {
  333. if(mycustomttable[i].biosFootprintAddr[j]) {
  334. if(ivideo->SiS_Pr.UseROM) {
  335. if(ivideo->SiS_Pr.VirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
  336. mycustomttable[i].biosFootprintData[j]) {
  337. footprint = false;
  338. }
  339. } else
  340. footprint = false;
  341. }
  342. }
  343. if(footprint) {
  344. ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
  345. printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
  346. mycustomttable[i].vendorName,
  347. mycustomttable[i].cardName);
  348. printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
  349. mycustomttable[i].optionName);
  350. break;
  351. }
  352. }
  353. i++;
  354. } while(mycustomttable[i].chipID);
  355. }
  356. static bool __devinit
  357. sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
  358. {
  359. int i, j, xres, yres, refresh, index;
  360. u32 emodes;
  361. if(buffer[0] != 0x00 || buffer[1] != 0xff ||
  362. buffer[2] != 0xff || buffer[3] != 0xff ||
  363. buffer[4] != 0xff || buffer[5] != 0xff ||
  364. buffer[6] != 0xff || buffer[7] != 0x00) {
  365. printk(KERN_DEBUG "sisfb: Bad EDID header\n");
  366. return false;
  367. }
  368. if(buffer[0x12] != 0x01) {
  369. printk(KERN_INFO "sisfb: EDID version %d not supported\n",
  370. buffer[0x12]);
  371. return false;
  372. }
  373. monitor->feature = buffer[0x18];
  374. if(!(buffer[0x14] & 0x80)) {
  375. if(!(buffer[0x14] & 0x08)) {
  376. printk(KERN_INFO
  377. "sisfb: WARNING: Monitor does not support separate syncs\n");
  378. }
  379. }
  380. if(buffer[0x13] >= 0x01) {
  381. /* EDID V1 rev 1 and 2: Search for monitor descriptor
  382. * to extract ranges
  383. */
  384. j = 0x36;
  385. for(i=0; i<4; i++) {
  386. if(buffer[j] == 0x00 && buffer[j + 1] == 0x00 &&
  387. buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd &&
  388. buffer[j + 4] == 0x00) {
  389. monitor->hmin = buffer[j + 7];
  390. monitor->hmax = buffer[j + 8];
  391. monitor->vmin = buffer[j + 5];
  392. monitor->vmax = buffer[j + 6];
  393. monitor->dclockmax = buffer[j + 9] * 10 * 1000;
  394. monitor->datavalid = true;
  395. break;
  396. }
  397. j += 18;
  398. }
  399. }
  400. if(!monitor->datavalid) {
  401. /* Otherwise: Get a range from the list of supported
  402. * Estabished Timings. This is not entirely accurate,
  403. * because fixed frequency monitors are not supported
  404. * that way.
  405. */
  406. monitor->hmin = 65535; monitor->hmax = 0;
  407. monitor->vmin = 65535; monitor->vmax = 0;
  408. monitor->dclockmax = 0;
  409. emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16);
  410. for(i = 0; i < 13; i++) {
  411. if(emodes & sisfb_ddcsmodes[i].mask) {
  412. if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h;
  413. if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1;
  414. if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v;
  415. if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v;
  416. if(monitor->dclockmax < sisfb_ddcsmodes[i].d) monitor->dclockmax = sisfb_ddcsmodes[i].d;
  417. }
  418. }
  419. index = 0x26;
  420. for(i = 0; i < 8; i++) {
  421. xres = (buffer[index] + 31) * 8;
  422. switch(buffer[index + 1] & 0xc0) {
  423. case 0xc0: yres = (xres * 9) / 16; break;
  424. case 0x80: yres = (xres * 4) / 5; break;
  425. case 0x40: yres = (xres * 3) / 4; break;
  426. default: yres = xres; break;
  427. }
  428. refresh = (buffer[index + 1] & 0x3f) + 60;
  429. if((xres >= 640) && (yres >= 480)) {
  430. for(j = 0; j < 8; j++) {
  431. if((xres == sisfb_ddcfmodes[j].x) &&
  432. (yres == sisfb_ddcfmodes[j].y) &&
  433. (refresh == sisfb_ddcfmodes[j].v)) {
  434. if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h;
  435. if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1;
  436. if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v;
  437. if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v;
  438. if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[j].d;
  439. }
  440. }
  441. }
  442. index += 2;
  443. }
  444. if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) {
  445. monitor->datavalid = true;
  446. }
  447. }
  448. return monitor->datavalid;
  449. }
  450. static void __devinit
  451. sisfb_handle_ddc(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, int crtno)
  452. {
  453. unsigned short temp, i, realcrtno = crtno;
  454. unsigned char buffer[256];
  455. monitor->datavalid = false;
  456. if(crtno) {
  457. if(ivideo->vbflags & CRT2_LCD) realcrtno = 1;
  458. else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
  459. else return;
  460. }
  461. if((ivideo->sisfb_crt1off) && (!crtno))
  462. return;
  463. temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
  464. realcrtno, 0, &buffer[0], ivideo->vbflags2);
  465. if((!temp) || (temp == 0xffff)) {
  466. printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
  467. return;
  468. } else {
  469. printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1);
  470. printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n",
  471. crtno + 1,
  472. (temp & 0x1a) ? "" : "[none of the supported]",
  473. (temp & 0x02) ? "2 " : "",
  474. (temp & 0x08) ? "D&P" : "",
  475. (temp & 0x10) ? "FPDI-2" : "");
  476. if(temp & 0x02) {
  477. i = 3; /* Number of retrys */
  478. do {
  479. temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
  480. realcrtno, 1, &buffer[0], ivideo->vbflags2);
  481. } while((temp) && i--);
  482. if(!temp) {
  483. if(sisfb_interpret_edid(monitor, &buffer[0])) {
  484. printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
  485. monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax,
  486. monitor->dclockmax / 1000);
  487. } else {
  488. printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1);
  489. }
  490. } else {
  491. printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1);
  492. }
  493. } else {
  494. printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n");
  495. }
  496. }
  497. }
  498. /* -------------- Mode validation --------------- */
  499. static bool
  500. sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
  501. int mode_idx, int rate_idx, int rate)
  502. {
  503. int htotal, vtotal;
  504. unsigned int dclock, hsync;
  505. if(!monitor->datavalid)
  506. return true;
  507. if(mode_idx < 0)
  508. return false;
  509. /* Skip for 320x200, 320x240, 640x400 */
  510. switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
  511. case 0x59:
  512. case 0x41:
  513. case 0x4f:
  514. case 0x50:
  515. case 0x56:
  516. case 0x53:
  517. case 0x2f:
  518. case 0x5d:
  519. case 0x5e:
  520. return true;
  521. #ifdef CONFIG_FB_SIS_315
  522. case 0x5a:
  523. case 0x5b:
  524. if(ivideo->sisvga_engine == SIS_315_VGA) return true;
  525. #endif
  526. }
  527. if(rate < (monitor->vmin - 1))
  528. return false;
  529. if(rate > (monitor->vmax + 1))
  530. return false;
  531. if(sisfb_gettotalfrommode(&ivideo->SiS_Pr,
  532. sisbios_mode[mode_idx].mode_no[ivideo->mni],
  533. &htotal, &vtotal, rate_idx)) {
  534. dclock = (htotal * vtotal * rate) / 1000;
  535. if(dclock > (monitor->dclockmax + 1000))
  536. return false;
  537. hsync = dclock / htotal;
  538. if(hsync < (monitor->hmin - 1))
  539. return false;
  540. if(hsync > (monitor->hmax + 1))
  541. return false;
  542. } else {
  543. return false;
  544. }
  545. return true;
  546. }
  547. static int
  548. sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
  549. {
  550. u16 xres=0, yres, myres;
  551. #ifdef CONFIG_FB_SIS_300
  552. if(ivideo->sisvga_engine == SIS_300_VGA) {
  553. if(!(sisbios_mode[myindex].chipset & MD_SIS300))
  554. return -1 ;
  555. }
  556. #endif
  557. #ifdef CONFIG_FB_SIS_315
  558. if(ivideo->sisvga_engine == SIS_315_VGA) {
  559. if(!(sisbios_mode[myindex].chipset & MD_SIS315))
  560. return -1;
  561. }
  562. #endif
  563. myres = sisbios_mode[myindex].yres;
  564. switch(vbflags & VB_DISPTYPE_DISP2) {
  565. case CRT2_LCD:
  566. xres = ivideo->lcdxres; yres = ivideo->lcdyres;
  567. if((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) &&
  568. (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) {
  569. if(sisbios_mode[myindex].xres > xres)
  570. return -1;
  571. if(myres > yres)
  572. return -1;
  573. }
  574. if(ivideo->sisfb_fstn) {
  575. if(sisbios_mode[myindex].xres == 320) {
  576. if(myres == 240) {
  577. switch(sisbios_mode[myindex].mode_no[1]) {
  578. case 0x50: myindex = MODE_FSTN_8; break;
  579. case 0x56: myindex = MODE_FSTN_16; break;
  580. case 0x53: return -1;
  581. }
  582. }
  583. }
  584. }
  585. if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
  586. sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
  587. ivideo->SiS_Pr.SiS_CustomT, xres, yres, ivideo->vbflags2) < 0x14) {
  588. return -1;
  589. }
  590. break;
  591. case CRT2_TV:
  592. if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
  593. sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
  594. return -1;
  595. }
  596. break;
  597. case CRT2_VGA:
  598. if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
  599. sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
  600. return -1;
  601. }
  602. break;
  603. }
  604. return myindex;
  605. }
  606. static u8
  607. sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx)
  608. {
  609. int i = 0;
  610. u16 xres = sisbios_mode[mode_idx].xres;
  611. u16 yres = sisbios_mode[mode_idx].yres;
  612. ivideo->rate_idx = 0;
  613. while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
  614. if((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {
  615. if(sisfb_vrate[i].refresh == rate) {
  616. ivideo->rate_idx = sisfb_vrate[i].idx;
  617. break;
  618. } else if(sisfb_vrate[i].refresh > rate) {
  619. if((sisfb_vrate[i].refresh - rate) <= 3) {
  620. DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
  621. rate, sisfb_vrate[i].refresh);
  622. ivideo->rate_idx = sisfb_vrate[i].idx;
  623. ivideo->refresh_rate = sisfb_vrate[i].refresh;
  624. } else if((sisfb_vrate[i].idx != 1) &&
  625. ((rate - sisfb_vrate[i-1].refresh) <= 2)) {
  626. DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
  627. rate, sisfb_vrate[i-1].refresh);
  628. ivideo->rate_idx = sisfb_vrate[i-1].idx;
  629. ivideo->refresh_rate = sisfb_vrate[i-1].refresh;
  630. }
  631. break;
  632. } else if((rate - sisfb_vrate[i].refresh) <= 2) {
  633. DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
  634. rate, sisfb_vrate[i].refresh);
  635. ivideo->rate_idx = sisfb_vrate[i].idx;
  636. break;
  637. }
  638. }
  639. i++;
  640. }
  641. if(ivideo->rate_idx > 0) {
  642. return ivideo->rate_idx;
  643. } else {
  644. printk(KERN_INFO "sisfb: Unsupported rate %d for %dx%d\n",
  645. rate, xres, yres);
  646. return 0;
  647. }
  648. }
  649. static bool
  650. sisfb_bridgeisslave(struct sis_video_info *ivideo)
  651. {
  652. unsigned char P1_00;
  653. if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE))
  654. return false;
  655. P1_00 = SiS_GetReg(SISPART1, 0x00);
  656. if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
  657. ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
  658. return true;
  659. } else {
  660. return false;
  661. }
  662. }
  663. static bool
  664. sisfballowretracecrt1(struct sis_video_info *ivideo)
  665. {
  666. u8 temp;
  667. temp = SiS_GetReg(SISCR, 0x17);
  668. if(!(temp & 0x80))
  669. return false;
  670. temp = SiS_GetReg(SISSR, 0x1f);
  671. if(temp & 0xc0)
  672. return false;
  673. return true;
  674. }
  675. static bool
  676. sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
  677. {
  678. if(!sisfballowretracecrt1(ivideo))
  679. return false;
  680. if (SiS_GetRegByte(SISINPSTAT) & 0x08)
  681. return true;
  682. else
  683. return false;
  684. }
  685. static void
  686. sisfbwaitretracecrt1(struct sis_video_info *ivideo)
  687. {
  688. int watchdog;
  689. if(!sisfballowretracecrt1(ivideo))
  690. return;
  691. watchdog = 65536;
  692. while ((!(SiS_GetRegByte(SISINPSTAT) & 0x08)) && --watchdog);
  693. watchdog = 65536;
  694. while ((SiS_GetRegByte(SISINPSTAT) & 0x08) && --watchdog);
  695. }
  696. static bool
  697. sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
  698. {
  699. unsigned char temp, reg;
  700. switch(ivideo->sisvga_engine) {
  701. case SIS_300_VGA: reg = 0x25; break;
  702. case SIS_315_VGA: reg = 0x30; break;
  703. default: return false;
  704. }
  705. temp = SiS_GetReg(SISPART1, reg);
  706. if(temp & 0x02)
  707. return true;
  708. else
  709. return false;
  710. }
  711. static bool
  712. sisfb_CheckVBRetrace(struct sis_video_info *ivideo)
  713. {
  714. if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
  715. if(!sisfb_bridgeisslave(ivideo)) {
  716. return sisfbcheckvretracecrt2(ivideo);
  717. }
  718. }
  719. return sisfbcheckvretracecrt1(ivideo);
  720. }
  721. static u32
  722. sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
  723. {
  724. u8 idx, reg1, reg2, reg3, reg4;
  725. u32 ret = 0;
  726. (*vcount) = (*hcount) = 0;
  727. if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
  728. ret |= (FB_VBLANK_HAVE_VSYNC |
  729. FB_VBLANK_HAVE_HBLANK |
  730. FB_VBLANK_HAVE_VBLANK |
  731. FB_VBLANK_HAVE_VCOUNT |
  732. FB_VBLANK_HAVE_HCOUNT);
  733. switch(ivideo->sisvga_engine) {
  734. case SIS_300_VGA: idx = 0x25; break;
  735. default:
  736. case SIS_315_VGA: idx = 0x30; break;
  737. }
  738. reg1 = SiS_GetReg(SISPART1, (idx+0)); /* 30 */
  739. reg2 = SiS_GetReg(SISPART1, (idx+1)); /* 31 */
  740. reg3 = SiS_GetReg(SISPART1, (idx+2)); /* 32 */
  741. reg4 = SiS_GetReg(SISPART1, (idx+3)); /* 33 */
  742. if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
  743. if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
  744. if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
  745. (*vcount) = reg3 | ((reg4 & 0x70) << 4);
  746. (*hcount) = reg2 | ((reg4 & 0x0f) << 8);
  747. } else if(sisfballowretracecrt1(ivideo)) {
  748. ret |= (FB_VBLANK_HAVE_VSYNC |
  749. FB_VBLANK_HAVE_VBLANK |
  750. FB_VBLANK_HAVE_VCOUNT |
  751. FB_VBLANK_HAVE_HCOUNT);
  752. reg1 = SiS_GetRegByte(SISINPSTAT);
  753. if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
  754. if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
  755. reg1 = SiS_GetReg(SISCR, 0x20);
  756. reg1 = SiS_GetReg(SISCR, 0x1b);
  757. reg2 = SiS_GetReg(SISCR, 0x1c);
  758. reg3 = SiS_GetReg(SISCR, 0x1d);
  759. (*vcount) = reg2 | ((reg3 & 0x07) << 8);
  760. (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
  761. }
  762. return ret;
  763. }
  764. static int
  765. sisfb_myblank(struct sis_video_info *ivideo, int blank)
  766. {
  767. u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
  768. bool backlight = true;
  769. switch(blank) {
  770. case FB_BLANK_UNBLANK: /* on */
  771. sr01 = 0x00;
  772. sr11 = 0x00;
  773. sr1f = 0x00;
  774. cr63 = 0x00;
  775. p2_0 = 0x20;
  776. p1_13 = 0x00;
  777. backlight = true;
  778. break;
  779. case FB_BLANK_NORMAL: /* blank */
  780. sr01 = 0x20;
  781. sr11 = 0x00;
  782. sr1f = 0x00;
  783. cr63 = 0x00;
  784. p2_0 = 0x20;
  785. p1_13 = 0x00;
  786. backlight = true;
  787. break;
  788. case FB_BLANK_VSYNC_SUSPEND: /* no vsync */
  789. sr01 = 0x20;
  790. sr11 = 0x08;
  791. sr1f = 0x80;
  792. cr63 = 0x40;
  793. p2_0 = 0x40;
  794. p1_13 = 0x80;
  795. backlight = false;
  796. break;
  797. case FB_BLANK_HSYNC_SUSPEND: /* no hsync */
  798. sr01 = 0x20;
  799. sr11 = 0x08;
  800. sr1f = 0x40;
  801. cr63 = 0x40;
  802. p2_0 = 0x80;
  803. p1_13 = 0x40;
  804. backlight = false;
  805. break;
  806. case FB_BLANK_POWERDOWN: /* off */
  807. sr01 = 0x20;
  808. sr11 = 0x08;
  809. sr1f = 0xc0;
  810. cr63 = 0x40;
  811. p2_0 = 0xc0;
  812. p1_13 = 0xc0;
  813. backlight = false;
  814. break;
  815. default:
  816. return 1;
  817. }
  818. if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
  819. if( (!ivideo->sisfb_thismonitor.datavalid) ||
  820. ((ivideo->sisfb_thismonitor.datavalid) &&
  821. (ivideo->sisfb_thismonitor.feature & 0xe0))) {
  822. if(ivideo->sisvga_engine == SIS_315_VGA) {
  823. SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
  824. }
  825. if(!(sisfb_bridgeisslave(ivideo))) {
  826. SiS_SetRegANDOR(SISSR, 0x01, ~0x20, sr01);
  827. SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, sr1f);
  828. }
  829. }
  830. }
  831. if(ivideo->currentvbflags & CRT2_LCD) {
  832. if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
  833. if(backlight) {
  834. SiS_SiS30xBLOn(&ivideo->SiS_Pr);
  835. } else {
  836. SiS_SiS30xBLOff(&ivideo->SiS_Pr);
  837. }
  838. } else if(ivideo->sisvga_engine == SIS_315_VGA) {
  839. #ifdef CONFIG_FB_SIS_315
  840. if(ivideo->vbflags2 & VB2_CHRONTEL) {
  841. if(backlight) {
  842. SiS_Chrontel701xBLOn(&ivideo->SiS_Pr);
  843. } else {
  844. SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
  845. }
  846. }
  847. #endif
  848. }
  849. if(((ivideo->sisvga_engine == SIS_300_VGA) &&
  850. (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) ||
  851. ((ivideo->sisvga_engine == SIS_315_VGA) &&
  852. ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) {
  853. SiS_SetRegANDOR(SISSR, 0x11, ~0x0c, sr11);
  854. }
  855. if(ivideo->sisvga_engine == SIS_300_VGA) {
  856. if((ivideo->vbflags2 & VB2_30xB) &&
  857. (!(ivideo->vbflags2 & VB2_30xBDH))) {
  858. SiS_SetRegANDOR(SISPART1, 0x13, 0x3f, p1_13);
  859. }
  860. } else if(ivideo->sisvga_engine == SIS_315_VGA) {
  861. if((ivideo->vbflags2 & VB2_30xB) &&
  862. (!(ivideo->vbflags2 & VB2_30xBDH))) {
  863. SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
  864. }
  865. }
  866. } else if(ivideo->currentvbflags & CRT2_VGA) {
  867. if(ivideo->vbflags2 & VB2_30xB) {
  868. SiS_SetRegANDOR(SISPART2, 0x00, 0x1f, p2_0);
  869. }
  870. }
  871. return 0;
  872. }
  873. /* ------------- Callbacks from init.c/init301.c -------------- */
  874. #ifdef CONFIG_FB_SIS_300
  875. unsigned int
  876. sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg)
  877. {
  878. struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
  879. u32 val = 0;
  880. pci_read_config_dword(ivideo->nbridge, reg, &val);
  881. return (unsigned int)val;
  882. }
  883. void
  884. sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val)
  885. {
  886. struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
  887. pci_write_config_dword(ivideo->nbridge, reg, (u32)val);
  888. }
  889. unsigned int
  890. sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg)
  891. {
  892. struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
  893. u32 val = 0;
  894. if(!ivideo->lpcdev) return 0;
  895. pci_read_config_dword(ivideo->lpcdev, reg, &val);
  896. return (unsigned int)val;
  897. }
  898. #endif
  899. #ifdef CONFIG_FB_SIS_315
  900. void
  901. sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val)
  902. {
  903. struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
  904. pci_write_config_byte(ivideo->nbridge, reg, (u8)val);
  905. }
  906. unsigned int
  907. sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg)
  908. {
  909. struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
  910. u16 val = 0;
  911. if(!ivideo->lpcdev) return 0;
  912. pci_read_config_word(ivideo->lpcdev, reg, &val);
  913. return (unsigned int)val;
  914. }
  915. #endif
  916. /* ----------- FBDev related routines for all series ----------- */
  917. static int
  918. sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
  919. {
  920. return (var->bits_per_pixel == 8) ? 256 : 16;
  921. }
  922. static void
  923. sisfb_set_vparms(struct sis_video_info *ivideo)
  924. {
  925. switch(ivideo->video_bpp) {
  926. case 8:
  927. ivideo->DstColor = 0x0000;
  928. ivideo->SiS310_AccelDepth = 0x00000000;
  929. ivideo->video_cmap_len = 256;
  930. break;
  931. case 16:
  932. ivideo->DstColor = 0x8000;
  933. ivideo->SiS310_AccelDepth = 0x00010000;
  934. ivideo->video_cmap_len = 16;
  935. break;
  936. case 32:
  937. ivideo->DstColor = 0xC000;
  938. ivideo->SiS310_AccelDepth = 0x00020000;
  939. ivideo->video_cmap_len = 16;
  940. break;
  941. default:
  942. ivideo->video_cmap_len = 16;
  943. printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp);
  944. ivideo->accel = 0;
  945. }
  946. }
  947. static int
  948. sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
  949. {
  950. int maxyres = ivideo->sisfb_mem / (var->xres_virtual * (var->bits_per_pixel >> 3));
  951. if(maxyres > 32767) maxyres = 32767;
  952. return maxyres;
  953. }
  954. static void
  955. sisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
  956. {
  957. ivideo->video_linelength = var->xres_virtual * (var->bits_per_pixel >> 3);
  958. ivideo->scrnpitchCRT1 = ivideo->video_linelength;
  959. if(!(ivideo->currentvbflags & CRT1_LCDA)) {
  960. if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
  961. ivideo->scrnpitchCRT1 <<= 1;
  962. }
  963. }
  964. }
  965. static void
  966. sisfb_set_pitch(struct sis_video_info *ivideo)
  967. {
  968. bool isslavemode = false;
  969. unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3;
  970. unsigned short HDisplay2 = ivideo->video_linelength >> 3;
  971. if(sisfb_bridgeisslave(ivideo)) isslavemode = true;
  972. /* We need to set pitch for CRT1 if bridge is in slave mode, too */
  973. if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
  974. SiS_SetReg(SISCR, 0x13, (HDisplay1 & 0xFF));
  975. SiS_SetRegANDOR(SISSR, 0x0E, 0xF0, (HDisplay1 >> 8));
  976. }
  977. /* We must not set the pitch for CRT2 if bridge is in slave mode */
  978. if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
  979. SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
  980. SiS_SetReg(SISPART1, 0x07, (HDisplay2 & 0xFF));
  981. SiS_SetRegANDOR(SISPART1, 0x09, 0xF0, (HDisplay2 >> 8));
  982. }
  983. }
  984. static void
  985. sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
  986. {
  987. ivideo->video_cmap_len = sisfb_get_cmap_len(var);
  988. switch(var->bits_per_pixel) {
  989. case 8:
  990. var->red.offset = var->green.offset = var->blue.offset = 0;
  991. var->red.length = var->green.length = var->blue.length = 8;
  992. break;
  993. case 16:
  994. var->red.offset = 11;
  995. var->red.length = 5;
  996. var->green.offset = 5;
  997. var->green.length = 6;
  998. var->blue.offset = 0;
  999. var->blue.length = 5;
  1000. var->transp.offset = 0;
  1001. var->transp.length = 0;
  1002. break;
  1003. case 32:
  1004. var->red.offset = 16;
  1005. var->red.length = 8;
  1006. var->green.offset = 8;
  1007. var->green.length = 8;
  1008. var->blue.offset = 0;
  1009. var->blue.length = 8;
  1010. var->transp.offset = 24;
  1011. var->transp.length = 8;
  1012. break;
  1013. }
  1014. }
  1015. static int
  1016. sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
  1017. {
  1018. unsigned short modeno = ivideo->mode_no;
  1019. /* >=2.6.12's fbcon clears the screen anyway */
  1020. modeno |= 0x80;
  1021. SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
  1022. sisfb_pre_setmode(ivideo);
  1023. if(!SiSSetMode(&ivideo->SiS_Pr, modeno)) {
  1024. printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
  1025. return -EINVAL;
  1026. }
  1027. SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
  1028. sisfb_post_setmode(ivideo);
  1029. return 0;
  1030. }
  1031. static int
  1032. sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info)
  1033. {
  1034. struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
  1035. unsigned int htotal = 0, vtotal = 0;
  1036. unsigned int drate = 0, hrate = 0;
  1037. int found_mode = 0, ret;
  1038. int old_mode;
  1039. u32 pixclock;
  1040. htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
  1041. vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
  1042. pixclock = var->pixclock;
  1043. if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
  1044. vtotal += var->yres;
  1045. vtotal <<= 1;
  1046. } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
  1047. vtotal += var->yres;
  1048. vtotal <<= 2;
  1049. } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
  1050. vtotal += var->yres;
  1051. vtotal <<= 1;
  1052. } else vtotal += var->yres;
  1053. if(!(htotal) || !(vtotal)) {
  1054. DPRINTK("sisfb: Invalid 'var' information\n");
  1055. return -EINVAL;
  1056. }
  1057. if(pixclock && htotal && vtotal) {
  1058. drate = 1000000000 / pixclock;
  1059. hrate = (drate * 1000) / htotal;
  1060. ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
  1061. } else {
  1062. ivideo->refresh_rate = 60;
  1063. }
  1064. old_mode = ivideo->sisfb_mode_idx;
  1065. ivideo->sisfb_mode_idx = 0;
  1066. while( (sisbios_mode[ivideo->sisfb_mode_idx].mode_no[0] != 0) &&
  1067. (sisbios_mode[ivideo->sisfb_mode_idx].xres <= var->xres) ) {
  1068. if( (sisbios_mode[ivideo->sisfb_mode_idx].xres == var->xres) &&
  1069. (sisbios_mode[ivideo->sisfb_mode_idx].yres == var->yres) &&
  1070. (sisbios_mode[ivideo->sisfb_mode_idx].bpp == var->bits_per_pixel)) {
  1071. ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
  1072. found_mode = 1;
  1073. break;
  1074. }
  1075. ivideo->sisfb_mode_idx++;
  1076. }
  1077. if(found_mode) {
  1078. ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
  1079. ivideo->sisfb_mode_idx, ivideo->currentvbflags);
  1080. } else {
  1081. ivideo->sisfb_mode_idx = -1;
  1082. }
  1083. if(ivideo->sisfb_mode_idx < 0) {
  1084. printk(KERN_ERR "sisfb: Mode %dx%dx%d not supported\n", var->xres,
  1085. var->yres, var->bits_per_pixel);
  1086. ivideo->sisfb_mode_idx = old_mode;
  1087. return -EINVAL;
  1088. }
  1089. ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
  1090. if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) {
  1091. ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
  1092. ivideo->refresh_rate = 60;
  1093. }
  1094. if(isactive) {
  1095. /* If acceleration to be used? Need to know
  1096. * before pre/post_set_mode()
  1097. */
  1098. ivideo->accel = 0;
  1099. #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
  1100. #ifdef STUPID_ACCELF_TEXT_SHIT
  1101. if(var->accel_flags & FB_ACCELF_TEXT) {
  1102. info->flags &= ~FBINFO_HWACCEL_DISABLED;
  1103. } else {
  1104. info->flags |= FBINFO_HWACCEL_DISABLED;
  1105. }
  1106. #endif
  1107. if(!(info->flags & FBINFO_HWACCEL_DISABLED)) ivideo->accel = -1;
  1108. #else
  1109. if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1;
  1110. #endif
  1111. if((ret = sisfb_set_mode(ivideo, 1))) {
  1112. return ret;
  1113. }
  1114. ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
  1115. ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
  1116. ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
  1117. sisfb_calc_pitch(ivideo, var);
  1118. sisfb_set_pitch(ivideo);
  1119. sisfb_set_vparms(ivideo);
  1120. ivideo->current_width = ivideo->video_width;
  1121. ivideo->current_height = ivideo->video_height;
  1122. ivideo->current_bpp = ivideo->video_bpp;
  1123. ivideo->current_htotal = htotal;
  1124. ivideo->current_vtotal = vtotal;
  1125. ivideo->current_linelength = ivideo->video_linelength;
  1126. ivideo->current_pixclock = var->pixclock;
  1127. ivideo->current_refresh_rate = ivideo->refresh_rate;
  1128. ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
  1129. }
  1130. return 0;
  1131. }
  1132. static void
  1133. sisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base)
  1134. {
  1135. SiS_SetReg(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
  1136. SiS_SetReg(SISCR, 0x0D, base & 0xFF);
  1137. SiS_SetReg(SISCR, 0x0C, (base >> 8) & 0xFF);
  1138. SiS_SetReg(SISSR, 0x0D, (base >> 16) & 0xFF);
  1139. if(ivideo->sisvga_engine == SIS_315_VGA) {
  1140. SiS_SetRegANDOR(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
  1141. }
  1142. }
  1143. static void
  1144. sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
  1145. {
  1146. if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
  1147. SiS_SetRegOR(SISPART1, ivideo->CRT2_write_enable, 0x01);
  1148. SiS_SetReg(SISPART1, 0x06, (base & 0xFF));
  1149. SiS_SetReg(SISPART1, 0x05, ((base >> 8) & 0xFF));
  1150. SiS_SetReg(SISPART1, 0x04, ((base >> 16) & 0xFF));
  1151. if(ivideo->sisvga_engine == SIS_315_VGA) {
  1152. SiS_SetRegANDOR(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
  1153. }
  1154. }
  1155. }
  1156. static int
  1157. sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
  1158. {
  1159. if(var->xoffset > (var->xres_virtual - var->xres)) {
  1160. return -EINVAL;
  1161. }
  1162. if(var->yoffset > (var->yres_virtual - var->yres)) {
  1163. return -EINVAL;
  1164. }
  1165. ivideo->current_base = (var->yoffset * var->xres_virtual) + var->xoffset;
  1166. /* calculate base bpp dep. */
  1167. switch(var->bits_per_pixel) {
  1168. case 32:
  1169. break;
  1170. case 16:
  1171. ivideo->current_base >>= 1;
  1172. break;
  1173. case 8:
  1174. default:
  1175. ivideo->current_base >>= 2;
  1176. break;
  1177. }
  1178. ivideo->current_base += (ivideo->video_offset >> 2);
  1179. sisfb_set_base_CRT1(ivideo, ivideo->current_base);
  1180. sisfb_set_base_CRT2(ivideo, ivideo->current_base);
  1181. return 0;
  1182. }
  1183. static int
  1184. sisfb_open(struct fb_info *info, int user)
  1185. {
  1186. return 0;
  1187. }
  1188. static int
  1189. sisfb_release(struct fb_info *info, int user)
  1190. {
  1191. return 0;
  1192. }
  1193. static int
  1194. sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
  1195. unsigned transp, struct fb_info *info)
  1196. {
  1197. struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
  1198. if(regno >= sisfb_get_cmap_len(&info->var))
  1199. return 1;
  1200. switch(info->var.bits_per_pixel) {
  1201. case 8:
  1202. SiS_SetRegByte(SISDACA, regno);
  1203. SiS_SetRegByte(SISDACD, (red >> 10));
  1204. SiS_SetRegByte(SISDACD, (green >> 10));
  1205. SiS_SetRegByte(SISDACD, (blue >> 10));
  1206. if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
  1207. SiS_SetRegByte(SISDAC2A, regno);
  1208. SiS_SetRegByte(SISDAC2D, (red >> 8));
  1209. SiS_SetRegByte(SISDAC2D, (green >> 8));
  1210. SiS_SetRegByte(SISDAC2D, (blue >> 8));
  1211. }
  1212. break;
  1213. case 16:
  1214. if (regno >= 16)
  1215. break;
  1216. ((u32 *)(info->pseudo_palette))[regno] =
  1217. (red & 0xf800) |
  1218. ((green & 0xfc00) >> 5) |
  1219. ((blue & 0xf800) >> 11);
  1220. break;
  1221. case 32:
  1222. if (regno >= 16)
  1223. break;
  1224. red >>= 8;
  1225. green >>= 8;
  1226. blue >>= 8;
  1227. ((u32 *)(info->pseudo_palette))[regno] =
  1228. (red << 16) | (green << 8) | (blue);
  1229. break;
  1230. }
  1231. return 0;
  1232. }
  1233. static int
  1234. sisfb_set_par(struct fb_info *info)
  1235. {
  1236. int err;
  1237. if((err = sisfb_do_set_var(&info->var, 1, info)))
  1238. return err;
  1239. sisfb_get_fix(&info->fix, -1, info);
  1240. return 0;
  1241. }
  1242. static int
  1243. sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
  1244. {
  1245. struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
  1246. unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
  1247. unsigned int drate = 0, hrate = 0, maxyres;
  1248. int found_mode = 0;
  1249. int refresh_rate, search_idx, tidx;
  1250. bool recalc_clock = false;
  1251. u32 pixclock;
  1252. htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
  1253. vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
  1254. pixclock = var->pixclock;
  1255. if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
  1256. vtotal += var->yres;
  1257. vtotal <<= 1;
  1258. } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
  1259. vtotal += var->yres;
  1260. vtotal <<= 2;
  1261. } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
  1262. vtotal += var->yres;
  1263. vtotal <<= 1;
  1264. } else
  1265. vtotal += var->yres;
  1266. if(!(htotal) || !(vtotal)) {
  1267. SISFAIL("sisfb: no valid timing data");
  1268. }
  1269. search_idx = 0;
  1270. while( (sisbios_mode[search_idx].mode_no[0] != 0) &&
  1271. (sisbios_mode[search_idx].xres <= var->xres) ) {
  1272. if( (sisbios_mode[search_idx].xres == var->xres) &&
  1273. (sisbios_mode[search_idx].yres == var->yres) &&
  1274. (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
  1275. if((tidx = sisfb_validate_mode(ivideo, search_idx,
  1276. ivideo->currentvbflags)) > 0) {
  1277. found_mode = 1;
  1278. search_idx = tidx;
  1279. break;
  1280. }
  1281. }
  1282. search_idx++;
  1283. }
  1284. if(!found_mode) {
  1285. search_idx = 0;
  1286. while(sisbios_mode[search_idx].mode_no[0] != 0) {
  1287. if( (var->xres <= sisbios_mode[search_idx].xres) &&
  1288. (var->yres <= sisbios_mode[search_idx].yres) &&
  1289. (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
  1290. if((tidx = sisfb_validate_mode(ivideo,search_idx,
  1291. ivideo->currentvbflags)) > 0) {
  1292. found_mode = 1;
  1293. search_idx = tidx;
  1294. break;
  1295. }
  1296. }
  1297. search_idx++;
  1298. }
  1299. if(found_mode) {
  1300. printk(KERN_DEBUG
  1301. "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
  1302. var->xres, var->yres, var->bits_per_pixel,
  1303. sisbios_mode[search_idx].xres,
  1304. sisbios_mode[search_idx].yres,
  1305. var->bits_per_pixel);
  1306. var->xres = sisbios_mode[search_idx].xres;
  1307. var->yres = sisbios_mode[search_idx].yres;
  1308. } else {
  1309. printk(KERN_ERR
  1310. "sisfb: Failed to find supported mode near %dx%dx%d\n",
  1311. var->xres, var->yres, var->bits_per_pixel);
  1312. return -EINVAL;
  1313. }
  1314. }
  1315. if( ((ivideo->vbflags2 & VB2_LVDS) ||
  1316. ((ivideo->vbflags2 & VB2_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
  1317. (var->bits_per_pixel == 8) ) {
  1318. /* Slave modes on LVDS and 301B-DH */
  1319. refresh_rate = 60;
  1320. recalc_clock = true;
  1321. } else if( (ivideo->current_htotal == htotal) &&
  1322. (ivideo->current_vtotal == vtotal) &&
  1323. (ivideo->current_pixclock == pixclock) ) {
  1324. /* x=x & y=y & c=c -> assume depth change */
  1325. drate = 1000000000 / pixclock;
  1326. hrate = (drate * 1000) / htotal;
  1327. refresh_rate = (unsigned int) (hrate * 2 / vtotal);
  1328. } else if( ( (ivideo->current_htotal != htotal) ||
  1329. (ivideo->current_vtotal != vtotal) ) &&
  1330. (ivideo->current_pixclock == var->pixclock) ) {
  1331. /* x!=x | y!=y & c=c -> invalid pixclock */
  1332. if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
  1333. refresh_rate =
  1334. ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
  1335. } else if(ivideo->sisfb_parm_rate != -1) {
  1336. /* Sic, sisfb_parm_rate - want to know originally desired rate here */
  1337. refresh_rate = ivideo->sisfb_parm_rate;
  1338. } else {
  1339. refresh_rate = 60;
  1340. }
  1341. recalc_clock = true;
  1342. } else if((pixclock) && (htotal) && (vtotal)) {
  1343. drate = 1000000000 / pixclock;
  1344. hrate = (drate * 1000) / htotal;
  1345. refresh_rate = (unsigned int) (hrate * 2 / vtotal);
  1346. } else if(ivideo->current_refresh_rate) {
  1347. refresh_rate = ivideo->current_refresh_rate;
  1348. recalc_clock = true;
  1349. } else {
  1350. refresh_rate = 60;
  1351. recalc_clock = true;
  1352. }
  1353. myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);
  1354. /* Eventually recalculate timing and clock */
  1355. if(recalc_clock) {
  1356. if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
  1357. var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
  1358. sisbios_mode[search_idx].mode_no[ivideo->mni],
  1359. myrateindex));
  1360. sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr,
  1361. sisbios_mode[search_idx].mode_no[ivideo->mni],
  1362. myrateindex, var);
  1363. if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
  1364. var->pixclock <<= 1;
  1365. }
  1366. }
  1367. if(ivideo->sisfb_thismonitor.datavalid) {
  1368. if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
  1369. myrateindex, refresh_rate)) {
  1370. printk(KERN_INFO
  1371. "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
  1372. }
  1373. }
  1374. /* Adapt RGB settings */
  1375. sisfb_bpp_to_var(ivideo, var);
  1376. /* Sanity check for offsets */
  1377. if(var->xoffset < 0) var->xoffset = 0;
  1378. if(var->yoffset < 0) var->yoffset = 0;
  1379. if(var->xres > var->xres_virtual)
  1380. var->xres_virtual = var->xres;
  1381. if(ivideo->sisfb_ypan) {
  1382. maxyres = sisfb_calc_maxyres(ivideo, var);
  1383. if(ivideo->sisfb_max) {
  1384. var->yres_virtual = maxyres;
  1385. } else {
  1386. if(var->yres_virtual > maxyres) {
  1387. var->yres_virtual = maxyres;
  1388. }
  1389. }
  1390. if(var->yres_virtual <= var->yres) {
  1391. var->yres_virtual = var->yres;
  1392. }
  1393. } else {
  1394. if(var->yres != var->yres_virtual) {
  1395. var->yres_virtual = var->yres;
  1396. }
  1397. var->xoffset = 0;
  1398. var->yoffset = 0;
  1399. }
  1400. /* Truncate offsets to maximum if too high */
  1401. if(var->xoffset > var->xres_virtual - var->xres) {
  1402. var->xoffset = var->xres_virtual - var->xres - 1;
  1403. }
  1404. if(var->yoffset > var->yres_virtual - var->yres) {
  1405. var->yoffset = var->yres_virtual - var->yres - 1;
  1406. }
  1407. /* Set everything else to 0 */
  1408. var->red.msb_right =
  1409. var->green.msb_right =
  1410. var->blue.msb_right =
  1411. var->transp.offset =
  1412. var->transp.length =
  1413. var->transp.msb_right = 0;
  1414. return 0;
  1415. }
  1416. static int
  1417. sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
  1418. {
  1419. struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
  1420. int err;
  1421. if(var->xoffset > (var->xres_virtual - var->xres))
  1422. return -EINVAL;
  1423. if(var->yoffset > (var->yres_virtual - var->yres))
  1424. return -EINVAL;
  1425. if(var->vmode & FB_VMODE_YWRAP)
  1426. return -EINVAL;
  1427. if(var->xoffset + info->var.xres > info->var.xres_virtual ||
  1428. var->yoffset + info->var.yres > info->var.yres_virtual)
  1429. return -EINVAL;
  1430. if((err = sisfb_pan_var(ivideo, var)) < 0)
  1431. return err;
  1432. info->var.xoffset = var->xoffset;
  1433. info->var.yoffset = var->yoffset;
  1434. return 0;
  1435. }
  1436. static int
  1437. sisfb_blank(int blank, struct fb_info *info)
  1438. {
  1439. struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
  1440. return sisfb_myblank(ivideo, blank);
  1441. }
  1442. /* ----------- FBDev related routines for all series ---------- */
  1443. static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
  1444. unsigned long arg)
  1445. {
  1446. struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
  1447. struct sis_memreq sismemreq;
  1448. struct fb_vblank sisvbblank;
  1449. u32 gpu32 = 0;
  1450. #ifndef __user
  1451. #define __user
  1452. #endif
  1453. u32 __user *argp = (u32 __user *)arg;
  1454. switch(cmd) {
  1455. case FBIO_ALLOC:
  1456. if(!capable(CAP_SYS_RAWIO))
  1457. return -EPERM;
  1458. if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq)))
  1459. return -EFAULT;
  1460. sis_malloc(&sismemreq);
  1461. if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) {
  1462. sis_free((u32)sismemreq.offset);
  1463. return -EFAULT;
  1464. }
  1465. break;
  1466. case FBIO_FREE:
  1467. if(!capable(CAP_SYS_RAWIO))
  1468. return -EPERM;
  1469. if(get_user(gpu32, argp))
  1470. return -EFAULT;
  1471. sis_free(gpu32);
  1472. break;
  1473. case FBIOGET_VBLANK:
  1474. memset(&sisvbblank, 0, sizeof(struct fb_vblank));
  1475. sisvbblank.count = 0;
  1476. sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
  1477. if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank)))
  1478. return -EFAULT;
  1479. break;
  1480. case SISFB_GET_INFO_SIZE:
  1481. return put_user(sizeof(struct sisfb_info), argp);
  1482. case SISFB_GET_INFO_OLD:
  1483. if(ivideo->warncount++ < 10)
  1484. printk(KERN_INFO
  1485. "sisfb: Deprecated ioctl call received - update your application!\n");
  1486. case SISFB_GET_INFO: /* For communication with X driver */
  1487. ivideo->sisfb_infoblock.sisfb_id = SISFB_ID;
  1488. ivideo->sisfb_infoblock.sisfb_version = VER_MAJOR;
  1489. ivideo->sisfb_infoblock.sisfb_revision = VER_MINOR;
  1490. ivideo->sisfb_infoblock.sisfb_patchlevel = VER_LEVEL;
  1491. ivideo->sisfb_infoblock.chip_id = ivideo->chip_id;
  1492. ivideo->sisfb_infoblock.sisfb_pci_vendor = ivideo->chip_vendor;
  1493. ivideo->sisfb_infoblock.memory = ivideo->video_size / 1024;
  1494. ivideo->sisfb_infoblock.heapstart = ivideo->heapstart / 1024;
  1495. if(ivideo->modechanged) {
  1496. ivideo->sisfb_infoblock.fbvidmode = ivideo->mode_no;
  1497. } else {
  1498. ivideo->sisfb_infoblock.fbvidmode = ivideo->modeprechange;
  1499. }
  1500. ivideo->sisfb_infoblock.sisfb_caps = ivideo->caps;
  1501. ivideo->sisfb_infoblock.sisfb_tqlen = ivideo->cmdQueueSize / 1024;
  1502. ivideo->sisfb_infoblock.sisfb_pcibus = ivideo->pcibus;
  1503. ivideo->sisfb_infoblock.sisfb_pcislot = ivideo->pcislot;
  1504. ivideo->sisfb_infoblock.sisfb_pcifunc = ivideo->pcifunc;
  1505. ivideo->sisfb_infoblock.sisfb_lcdpdc = ivideo->detectedpdc;
  1506. ivideo->sisfb_infoblock.sisfb_lcdpdca = ivideo->detectedpdca;
  1507. ivideo->sisfb_infoblock.sisfb_lcda = ivideo->detectedlcda;
  1508. ivideo->sisfb_infoblock.sisfb_vbflags = ivideo->vbflags;
  1509. ivideo->sisfb_infoblock.sisfb_currentvbflags = ivideo->currentvbflags;
  1510. ivideo->sisfb_infoblock.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
  1511. ivideo->sisfb_infoblock.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
  1512. ivideo->sisfb_infoblock.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
  1513. ivideo->sisfb_infoblock.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
  1514. ivideo->sisfb_infoblock.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
  1515. ivideo->sisfb_infoblock.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
  1516. ivideo->sisfb_infoblock.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
  1517. ivideo->sisfb_infoblock.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
  1518. ivideo->sisfb_infoblock.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
  1519. ivideo->sisfb_infoblock.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
  1520. ivideo->sisfb_infoblock.sisfb_heapsize = ivideo->sisfb_heap_size / 1024;
  1521. ivideo->sisfb_infoblock.sisfb_videooffset = ivideo->video_offset;
  1522. ivideo->sisfb_infoblock.sisfb_curfstn = ivideo->curFSTN;
  1523. ivideo->sisfb_infoblock.sisfb_curdstn = ivideo->curDSTN;
  1524. ivideo->sisfb_infoblock.sisfb_vbflags2 = ivideo->vbflags2;
  1525. ivideo->sisfb_infoblock.sisfb_can_post = ivideo->sisfb_can_post ? 1 : 0;
  1526. ivideo->sisfb_infoblock.sisfb_card_posted = ivideo->sisfb_card_posted ? 1 : 0;
  1527. ivideo->sisfb_infoblock.sisfb_was_boot_device = ivideo->sisfb_was_boot_device ? 1 : 0;
  1528. if(copy_to_user((void __user *)arg, &ivideo->sisfb_infoblock,
  1529. sizeof(ivideo->sisfb_infoblock)))
  1530. return -EFAULT;
  1531. break;
  1532. case SISFB_GET_VBRSTATUS_OLD:
  1533. if(ivideo->warncount++ < 10)
  1534. printk(KERN_INFO
  1535. "sisfb: Deprecated ioctl call received - update your application!\n");
  1536. case SISFB_GET_VBRSTATUS:
  1537. if(sisfb_CheckVBRetrace(ivideo))
  1538. return put_user((u32)1, argp);
  1539. else
  1540. return put_user((u32)0, argp);
  1541. case SISFB_GET_AUTOMAXIMIZE_OLD:
  1542. if(ivideo->warncount++ < 10)
  1543. printk(KERN_INFO
  1544. "sisfb: Deprecated ioctl call received - update your application!\n");
  1545. case SISFB_GET_AUTOMAXIMIZE:
  1546. if(ivideo->sisfb_max)
  1547. return put_user((u32)1, argp);
  1548. else
  1549. return put_user((u32)0, argp);
  1550. case SISFB_SET_AUTOMAXIMIZE_OLD:
  1551. if(ivideo->warncount++ < 10)
  1552. printk(KERN_INFO
  1553. "sisfb: Deprecated ioctl call received - update your application!\n");
  1554. case SISFB_SET_AUTOMAXIMIZE:
  1555. if(get_user(gpu32, argp))
  1556. return -EFAULT;
  1557. ivideo->sisfb_max = (gpu32) ? 1 : 0;
  1558. break;
  1559. case SISFB_SET_TVPOSOFFSET:
  1560. if(get_user(gpu32, argp))
  1561. return -EFAULT;
  1562. sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);
  1563. sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);
  1564. break;
  1565. case SISFB_GET_TVPOSOFFSET:
  1566. return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),
  1567. argp);
  1568. case SISFB_COMMAND:
  1569. if(copy_from_user(&ivideo->sisfb_command, (void __user *)arg,
  1570. sizeof(struct sisfb_cmd)))
  1571. return -EFAULT;
  1572. sisfb_handle_command(ivideo, &ivideo->sisfb_command);
  1573. if(copy_to_user((void __user *)arg, &ivideo->sisfb_command,
  1574. sizeof(struct sisfb_cmd)))
  1575. return -EFAULT;
  1576. break;
  1577. case SISFB_SET_LOCK:
  1578. if(get_user(gpu32, argp))
  1579. return -EFAULT;
  1580. ivideo->sisfblocked = (gpu32) ? 1 : 0;
  1581. break;
  1582. default:
  1583. #ifdef SIS_NEW_CONFIG_COMPAT
  1584. return -ENOIOCTLCMD;
  1585. #else
  1586. return -EINVAL;
  1587. #endif
  1588. }
  1589. return 0;
  1590. }
  1591. static int
  1592. sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
  1593. {
  1594. struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
  1595. memset(fix, 0, sizeof(struct fb_fix_screeninfo));
  1596. strlcpy(fix->id, ivideo->myid, sizeof(fix->id));
  1597. mutex_lock(&info->mm_lock);
  1598. fix->smem_start = ivideo->video_base + ivideo->video_offset;
  1599. fix->smem_len = ivideo->sisfb_mem;
  1600. mutex_unlock(&info->mm_lock);
  1601. fix->type = FB_TYPE_PACKED_PIXELS;
  1602. fix->type_aux = 0;
  1603. fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
  1604. fix->xpanstep = 1;
  1605. fix->ypanstep = (ivideo->sisfb_ypan) ? 1 : 0;
  1606. fix->ywrapstep = 0;
  1607. fix->line_length = ivideo->video_linelength;
  1608. fix->mmio_start = ivideo->mmio_base;
  1609. fix->mmio_len = ivideo->mmio_size;
  1610. if(ivideo->sisvga_engine == SIS_300_VGA) {
  1611. fix->accel = FB_ACCEL_SIS_GLAMOUR;
  1612. } else if((ivideo->chip == SIS_330) ||
  1613. (ivideo->chip == SIS_760) ||
  1614. (ivideo->chip == SIS_761)) {
  1615. fix->accel = FB_ACCEL_SIS_XABRE;
  1616. } else if(ivideo->chip == XGI_20) {
  1617. fix->accel = FB_ACCEL_XGI_VOLARI_Z;
  1618. } else if(ivideo->chip >= XGI_40) {
  1619. fix->accel = FB_ACCEL_XGI_VOLARI_V;
  1620. } else {
  1621. fix->accel = FB_ACCEL_SIS_GLAMOUR_2;
  1622. }
  1623. return 0;
  1624. }
  1625. /* ---------------- fb_ops structures ----------------- */
  1626. static struct fb_ops sisfb_ops = {
  1627. .owner = THIS_MODULE,
  1628. .fb_open = sisfb_open,
  1629. .fb_release = sisfb_release,
  1630. .fb_check_var = sisfb_check_var,
  1631. .fb_set_par = sisfb_set_par,
  1632. .fb_setcolreg = sisfb_setcolreg,
  1633. .fb_pan_display = sisfb_pan_display,
  1634. .fb_blank = sisfb_blank,
  1635. .fb_fillrect = fbcon_sis_fillrect,
  1636. .fb_copyarea = fbcon_sis_copyarea,
  1637. .fb_imageblit = cfb_imageblit,
  1638. .fb_sync = fbcon_sis_sync,
  1639. #ifdef SIS_NEW_CONFIG_COMPAT
  1640. .fb_compat_ioctl= sisfb_ioctl,
  1641. #endif
  1642. .fb_ioctl = sisfb_ioctl
  1643. };
  1644. /* ---------------- Chip generation dependent routines ---------------- */
  1645. static struct pci_dev * __devinit
  1646. sisfb_get_northbridge(int basechipid)
  1647. {
  1648. struct pci_dev *pdev = NULL;
  1649. int nbridgenum, nbridgeidx, i;
  1650. static const unsigned short nbridgeids[] = {
  1651. PCI_DEVICE_ID_SI_540, /* for SiS 540 VGA */
  1652. PCI_DEVICE_ID_SI_630, /* for SiS 630/730 VGA */
  1653. PCI_DEVICE_ID_SI_730,
  1654. PCI_DEVICE_ID_SI_550, /* for SiS 550 VGA */
  1655. PCI_DEVICE_ID_SI_650, /* for SiS 650/651/740 VGA */
  1656. PCI_DEVICE_ID_SI_651,
  1657. PCI_DEVICE_ID_SI_740,
  1658. PCI_DEVICE_ID_SI_661, /* for SiS 661/741/660/760/761 VGA */
  1659. PCI_DEVICE_ID_SI_741,
  1660. PCI_DEVICE_ID_SI_660,
  1661. PCI_DEVICE_ID_SI_760,
  1662. PCI_DEVICE_ID_SI_761
  1663. };
  1664. switch(basechipid) {
  1665. #ifdef CONFIG_FB_SIS_300
  1666. case SIS_540: nbridgeidx = 0; nbridgenum = 1; break;
  1667. case SIS_630: nbridgeidx = 1; nbridgenum = 2; break;
  1668. #endif
  1669. #ifdef CONFIG_FB_SIS_315
  1670. case SIS_550: nbridgeidx = 3; nbridgenum = 1; break;
  1671. case SIS_650: nbridgeidx = 4; nbridgenum = 3; break;
  1672. case SIS_660: nbridgeidx = 7; nbridgenum = 5; break;
  1673. #endif
  1674. default: return NULL;
  1675. }
  1676. for(i = 0; i < nbridgenum; i++) {
  1677. if((pdev = pci_get_device(PCI_VENDOR_ID_SI,
  1678. nbridgeids[nbridgeidx+i], NULL)))
  1679. break;
  1680. }
  1681. return pdev;
  1682. }
  1683. static int __devinit
  1684. sisfb_get_dram_size(struct sis_video_info *ivideo)
  1685. {
  1686. #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
  1687. u8 reg;
  1688. #endif
  1689. ivideo->video_size = 0;
  1690. ivideo->UMAsize = ivideo->LFBsize = 0;
  1691. switch(ivideo->chip) {
  1692. #ifdef CONFIG_FB_SIS_300
  1693. case SIS_300:
  1694. reg = SiS_GetReg(SISSR, 0x14);
  1695. ivideo->video_size = ((reg & 0x3F) + 1) << 20;
  1696. break;
  1697. case SIS_540:
  1698. case SIS_630:
  1699. case SIS_730:
  1700. if(!ivideo->nbridge)
  1701. return -1;
  1702. pci_read_config_byte(ivideo->nbridge, 0x63, &reg);
  1703. ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);
  1704. break;
  1705. #endif
  1706. #ifdef CONFIG_FB_SIS_315
  1707. case SIS_315H:
  1708. case SIS_315PRO:
  1709. case SIS_315:
  1710. reg = SiS_GetReg(SISSR, 0x14);
  1711. ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
  1712. switch((reg >> 2) & 0x03) {
  1713. case 0x01:
  1714. case 0x03:
  1715. ivideo->video_size <<= 1;
  1716. break;
  1717. case 0x02:
  1718. ivideo->video_size += (ivideo->video_size/2);
  1719. }
  1720. break;
  1721. case SIS_330:
  1722. reg = SiS_GetReg(SISSR, 0x14);
  1723. ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
  1724. if(reg & 0x0c) ivideo->video_size <<= 1;
  1725. break;
  1726. case SIS_550:
  1727. case SIS_650:
  1728. case SIS_740:
  1729. reg = SiS_GetReg(SISSR, 0x14);
  1730. ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
  1731. break;
  1732. case SIS_661:
  1733. case SIS_741:
  1734. reg = SiS_GetReg(SISCR, 0x79);
  1735. ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
  1736. break;
  1737. case SIS_660:
  1738. case SIS_760:
  1739. case SIS_761:
  1740. reg = SiS_GetReg(SISCR, 0x79);
  1741. reg = (reg & 0xf0) >> 4;
  1742. if(reg) {
  1743. ivideo->video_size = (1 << reg) << 20;
  1744. ivideo->UMAsize = ivideo->video_size;
  1745. }
  1746. reg = SiS_GetReg(SISCR, 0x78);
  1747. reg &= 0x30;
  1748. if(reg) {
  1749. if(reg == 0x10) {
  1750. ivideo->LFBsize = (32 << 20);
  1751. } else {
  1752. ivideo->LFBsize = (64 << 20);
  1753. }
  1754. ivideo->video_size += ivideo->LFBsize;
  1755. }
  1756. break;
  1757. case SIS_340:
  1758. case XGI_20:
  1759. case XGI_40:
  1760. reg = SiS_GetReg(SISSR, 0x14);
  1761. ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
  1762. if(ivideo->chip != XGI_20) {
  1763. reg = (reg & 0x0c) >> 2;
  1764. if(ivideo->revision_id == 2) {
  1765. if(reg & 0x01) reg = 0x02;
  1766. else reg = 0x00;
  1767. }
  1768. if(reg == 0x02) ivideo->video_size <<= 1;
  1769. else if(reg == 0x03) ivideo->video_size <<= 2;
  1770. }
  1771. break;
  1772. #endif
  1773. default:
  1774. return -1;
  1775. }
  1776. return 0;
  1777. }
  1778. /* -------------- video bridge device detection --------------- */
  1779. static void __devinit
  1780. sisfb_detect_VB_connect(struct sis_video_info *ivideo)
  1781. {
  1782. u8 cr32, temp;
  1783. /* No CRT2 on XGI Z7 */
  1784. if(ivideo->chip == XGI_20) {
  1785. ivideo->sisfb_crt1off = 0;
  1786. return;
  1787. }
  1788. #ifdef CONFIG_FB_SIS_300
  1789. if(ivideo->sisvga_engine == SIS_300_VGA) {
  1790. temp = SiS_GetReg(SISSR, 0x17);
  1791. if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
  1792. /* PAL/NTSC is stored on SR16 on such machines */
  1793. if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
  1794. temp = SiS_GetReg(SISSR, 0x16);
  1795. if(temp & 0x20)
  1796. ivideo->vbflags |= TV_PAL;
  1797. else
  1798. ivideo->vbflags |= TV_NTSC;
  1799. }
  1800. }
  1801. }
  1802. #endif
  1803. cr32 = SiS_GetReg(SISCR, 0x32);
  1804. if(cr32 & SIS_CRT1) {
  1805. ivideo->sisfb_crt1off = 0;
  1806. } else {
  1807. ivideo->sisfb_crt1off = (cr32 & 0xDF) ? 1 : 0;
  1808. }
  1809. ivideo->vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
  1810. if(cr32 & SIS_VB_TV) ivideo->vbflags |= CRT2_TV;
  1811. if(cr32 & SIS_VB_LCD) ivideo->vbflags |= CRT2_LCD;
  1812. if(cr32 & SIS_VB_CRT2) ivideo->vbflags |= CRT2_VGA;
  1813. /* Check given parms for hardware compatibility.
  1814. * (Cannot do this in the search_xx routines since we don't
  1815. * know what hardware we are running on then)
  1816. */
  1817. if(ivideo->chip != SIS_550) {
  1818. ivideo->sisfb_dstn = ivideo->sisfb_fstn = 0;
  1819. }
  1820. if(ivideo->sisfb_tvplug != -1) {
  1821. if( (ivideo->sisvga_engine != SIS_315_VGA) ||
  1822. (!(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) ) {
  1823. if(ivideo->sisfb_tvplug & TV_YPBPR) {
  1824. ivideo->sisfb_tvplug = -1;
  1825. printk(KERN_ERR "sisfb: YPbPr not supported\n");
  1826. }
  1827. }
  1828. }
  1829. if(ivideo->sisfb_tvplug != -1) {
  1830. if( (ivideo->sisvga_engine != SIS_315_VGA) ||
  1831. (!(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) ) {
  1832. if(ivideo->sisfb_tvplug & TV_HIVISION) {
  1833. ivideo->sisfb_tvplug = -1;
  1834. printk(KERN_ERR "sisfb: HiVision not supported\n");
  1835. }
  1836. }
  1837. }
  1838. if(ivideo->sisfb_tvstd != -1) {
  1839. if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) &&
  1840. (!((ivideo->sisvga_engine == SIS_315_VGA) &&
  1841. (ivideo->vbflags2 & VB2_CHRONTEL))) ) {
  1842. if(ivideo->sisfb_tvstd & (TV_PALM | TV_PALN | TV_NTSCJ)) {
  1843. ivideo->sisfb_tvstd = -1;
  1844. printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
  1845. }
  1846. }
  1847. }
  1848. /* Detect/set TV plug & type */
  1849. if(ivideo->sisfb_tvplug != -1) {
  1850. ivideo->vbflags |= ivideo->sisfb_tvplug;
  1851. } else {
  1852. if(cr32 & SIS_VB_YPBPR) ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */
  1853. else if(cr32 & SIS_VB_HIVISION) ivideo->vbflags |= TV_HIVISION;
  1854. else if(cr32 & SIS_VB_SCART) ivideo->vbflags |= TV_SCART;
  1855. else {
  1856. if(cr32 & SIS_VB_SVIDEO) ivideo->vbflags |= TV_SVIDEO;
  1857. if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO;
  1858. }
  1859. }
  1860. if(!(ivideo->vbflags & (TV_YPBPR | TV_HIVISION))) {
  1861. if(ivideo->sisfb_tvstd != -1) {
  1862. ivideo->vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ);
  1863. ivideo->vbflags |= ivideo->sisfb_tvstd;
  1864. }
  1865. if(ivideo->vbflags & TV_SCART) {
  1866. ivideo->vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ);
  1867. ivideo->vbflags |= TV_PAL;
  1868. }
  1869. if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
  1870. if(ivideo->sisvga_engine == SIS_300_VGA) {
  1871. temp = SiS_GetReg(SISSR, 0x38);
  1872. if(temp & 0x01) ivideo->vbflags |= TV_PAL;
  1873. else ivideo->vbflags |= TV_NTSC;
  1874. } else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
  1875. temp = SiS_GetReg(SISSR, 0x38);
  1876. if(temp & 0x01) ivideo->vbflags |= TV_PAL;
  1877. else ivideo->vbflags |= TV_NTSC;
  1878. } else {
  1879. temp = SiS_GetReg(SISCR, 0x79);
  1880. if(temp & 0x20) ivideo->vbflags |= TV_PAL;
  1881. else ivideo->vbflags |= TV_NTSC;
  1882. }
  1883. }
  1884. }
  1885. /* Copy forceCRT1 option to CRT1off if option is given */
  1886. if(ivideo->sisfb_forcecrt1 != -1) {
  1887. ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
  1888. }
  1889. }
  1890. /* ------------------ Sensing routines ------------------ */
  1891. static bool __devinit
  1892. sisfb_test_DDC1(struct sis_video_info *ivideo)
  1893. {
  1894. unsigned short old;
  1895. int count = 48;
  1896. old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr);
  1897. do {
  1898. if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
  1899. } while(count--);
  1900. return (count != -1);
  1901. }
  1902. static void __devinit
  1903. sisfb_sense_crt1(struct sis_video_info *ivideo)
  1904. {
  1905. bool mustwait = false;
  1906. u8 sr1F, cr17;
  1907. #ifdef CONFIG_FB_SIS_315
  1908. u8 cr63=0;
  1909. #endif
  1910. u16 temp = 0xffff;
  1911. int i;
  1912. sr1F = SiS_GetReg(SISSR, 0x1F);
  1913. SiS_SetRegOR(SISSR, 0x1F, 0x04);
  1914. SiS_SetRegAND(SISSR, 0x1F, 0x3F);
  1915. if(sr1F & 0xc0) mustwait = true;
  1916. #ifdef CONFIG_FB_SIS_315
  1917. if(ivideo->sisvga_engine == SIS_315_VGA) {
  1918. cr63 = SiS_GetReg(SISCR, ivideo->SiS_Pr.SiS_MyCR63);
  1919. cr63 &= 0x40;
  1920. SiS_SetRegAND(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF);
  1921. }
  1922. #endif
  1923. cr17 = SiS_GetReg(SISCR, 0x17);
  1924. cr17 &= 0x80;
  1925. if(!cr17) {
  1926. SiS_SetRegOR(SISCR, 0x17, 0x80);
  1927. mustwait = true;
  1928. SiS_SetReg(SISSR, 0x00, 0x01);
  1929. SiS_SetReg(SISSR, 0x00, 0x03);
  1930. }
  1931. if(mustwait) {
  1932. for(i=0; i < 10; i++) sisfbwaitretracecrt1(ivideo);
  1933. }
  1934. #ifdef CONFIG_FB_SIS_315
  1935. if(ivideo->chip >= SIS_330) {
  1936. SiS_SetRegAND(SISCR, 0x32, ~0x20);
  1937. if(ivideo->chip >= SIS_340) {
  1938. SiS_SetReg(SISCR, 0x57, 0x4a);
  1939. } else {
  1940. SiS_SetReg(SISCR, 0x57, 0x5f);
  1941. }
  1942. SiS_SetRegOR(SISCR, 0x53, 0x02);
  1943. while ((SiS_GetRegByte(SISINPSTAT)) & 0x01) break;
  1944. while (!((SiS_GetRegByte(SISINPSTAT)) & 0x01)) break;
  1945. if ((SiS_GetRegByte(SISMISCW)) & 0x10) temp = 1;
  1946. SiS_SetRegAND(SISCR, 0x53, 0xfd);
  1947. SiS_SetRegAND(SISCR, 0x57, 0x00);
  1948. }
  1949. #endif
  1950. if(temp == 0xffff) {
  1951. i = 3;
  1952. do {
  1953. temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
  1954. ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2);
  1955. } while(((temp == 0) || (temp == 0xffff)) && i--);
  1956. if((temp == 0) || (temp == 0xffff)) {
  1957. if(sisfb_test_DDC1(ivideo)) temp = 1;
  1958. }
  1959. }
  1960. if((temp) && (temp != 0xffff)) {
  1961. SiS_SetRegOR(SISCR, 0x32, 0x20);
  1962. }
  1963. #ifdef CONFIG_FB_SIS_315
  1964. if(ivideo->sisvga_engine == SIS_315_VGA) {
  1965. SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF, cr63);
  1966. }
  1967. #endif
  1968. SiS_SetRegANDOR(SISCR, 0x17, 0x7F, cr17);
  1969. SiS_SetReg(SISSR, 0x1F, sr1F);
  1970. }
  1971. /* Determine and detect attached devices on SiS30x */
  1972. static void __devinit
  1973. SiS_SenseLCD(struct sis_video_info *ivideo)
  1974. {
  1975. unsigned char buffer[256];
  1976. unsigned short temp, realcrtno, i;
  1977. u8 reg, cr37 = 0, paneltype = 0;
  1978. u16 xres, yres;
  1979. ivideo->SiS_Pr.PanelSelfDetected = false;
  1980. /* LCD detection only for TMDS bridges */
  1981. if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
  1982. return;
  1983. if(ivideo->vbflags2 & VB2_30xBDH)
  1984. return;
  1985. /* If LCD already set up by BIOS, skip it */
  1986. reg = SiS_GetReg(SISCR, 0x32);
  1987. if(reg & 0x08)
  1988. return;
  1989. realcrtno = 1;
  1990. if(ivideo->SiS_Pr.DDCPortMixup)
  1991. realcrtno = 0;
  1992. /* Check DDC capabilities */
  1993. temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
  1994. realcrtno, 0, &buffer[0], ivideo->vbflags2);
  1995. if((!temp) || (temp == 0xffff) || (!(temp & 0x02)))
  1996. return;
  1997. /* Read DDC data */
  1998. i = 3; /* Number of retrys */
  1999. do {
  2000. temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
  2001. ivideo->sisvga_engine, realcrtno, 1,
  2002. &buffer[0], ivideo->vbflags2);
  2003. } while((temp) && i--);
  2004. if(temp)
  2005. return;
  2006. /* No digital device */
  2007. if(!(buffer[0x14] & 0x80))
  2008. return;
  2009. /* First detailed timing preferred timing? */
  2010. if(!(buffer[0x18] & 0x02))
  2011. return;
  2012. xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
  2013. yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
  2014. switch(xres) {
  2015. case 1024:
  2016. if(yres == 768)
  2017. paneltype = 0x02;
  2018. break;
  2019. case 1280:
  2020. if(yres == 1024)
  2021. paneltype = 0x03;
  2022. break;
  2023. case 1600:
  2024. if((yres == 1200) && (ivideo->vbflags2 & VB2_30xC))
  2025. paneltype = 0x0b;
  2026. break;
  2027. }
  2028. if(!paneltype)
  2029. return;
  2030. if(buffer[0x23])
  2031. cr37 |= 0x10;
  2032. if((buffer[0x47] & 0x18) == 0x18)
  2033. cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
  2034. else
  2035. cr37 |= 0xc0;
  2036. SiS_SetReg(SISCR, 0x36, paneltype);
  2037. cr37 &= 0xf1;
  2038. SiS_SetRegANDOR(SISCR, 0x37, 0x0c, cr37);
  2039. SiS_SetRegOR(SISCR, 0x32, 0x08);
  2040. ivideo->SiS_Pr.PanelSelfDetected = true;
  2041. }
  2042. static int __devinit
  2043. SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
  2044. {
  2045. int temp, mytest, result, i, j;
  2046. for(j = 0; j < 10; j++) {
  2047. result = 0;
  2048. for(i = 0; i < 3; i++) {
  2049. mytest = test;
  2050. SiS_SetReg(SISPART4, 0x11, (type & 0x00ff));
  2051. temp = (type >> 8) | (mytest & 0x00ff);
  2052. SiS_SetRegANDOR(SISPART4, 0x10, 0xe0, temp);
  2053. SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
  2054. mytest >>= 8;
  2055. mytest &= 0x7f;
  2056. temp = SiS_GetReg(SISPART4, 0x03);
  2057. temp ^= 0x0e;
  2058. temp &= mytest;
  2059. if(temp == mytest) result++;
  2060. #if 1
  2061. SiS_SetReg(SISPART4, 0x11, 0x00);
  2062. SiS_SetRegAND(SISPART4, 0x10, 0xe0);
  2063. SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
  2064. #endif
  2065. }
  2066. if((result == 0) || (result >= 2)) break;
  2067. }
  2068. return result;
  2069. }
  2070. static void __devinit
  2071. SiS_Sense30x(struct sis_video_info *ivideo)
  2072. {
  2073. u8 backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
  2074. u16 svhs=0, svhs_c=0;
  2075. u16 cvbs=0, cvbs_c=0;
  2076. u16 vga2=0, vga2_c=0;
  2077. int myflag, result;
  2078. char stdstr[] = "sisfb: Detected";
  2079. char tvstr[] = "TV connected to";
  2080. if(ivideo->vbflags2 & VB2_301) {
  2081. svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
  2082. myflag = SiS_GetReg(SISPART4, 0x01);
  2083. if(myflag & 0x04) {
  2084. svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
  2085. }
  2086. } else if(ivideo->vbflags2 & (VB2_301B | VB2_302B)) {
  2087. svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
  2088. } else if(ivideo->vbflags2 & (VB2_301LV | VB2_302LV)) {
  2089. svhs = 0x0200; cvbs = 0x0100;
  2090. } else if(ivideo->vbflags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) {
  2091. svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
  2092. } else
  2093. return;
  2094. vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
  2095. if(ivideo->vbflags & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) {
  2096. svhs_c = 0x0408; cvbs_c = 0x0808;
  2097. }
  2098. biosflag = 2;
  2099. if(ivideo->haveXGIROM) {
  2100. biosflag = ivideo->bios_abase[0x58] & 0x03;
  2101. } else if(ivideo->newrom) {
  2102. if(ivideo->bios_abase[0x5d] & 0x04) biosflag |= 0x01;
  2103. } else if(ivideo->sisvga_engine == SIS_300_VGA) {
  2104. if(ivideo->bios_abase) {
  2105. biosflag = ivideo->bios_abase[0xfe] & 0x03;
  2106. }
  2107. }
  2108. if(ivideo->chip == SIS_300) {
  2109. myflag = SiS_GetReg(SISSR, 0x3b);
  2110. if(!(myflag & 0x01)) vga2 = vga2_c = 0;
  2111. }
  2112. if(!(ivideo->vbflags2 & VB2_SISVGA2BRIDGE)) {
  2113. vga2 = vga2_c = 0;
  2114. }
  2115. backupSR_1e = SiS_GetReg(SISSR, 0x1e);
  2116. SiS_SetRegOR(SISSR, 0x1e, 0x20);
  2117. backupP4_0d = SiS_GetReg(SISPART4, 0x0d);
  2118. if(ivideo->vbflags2 & VB2_30xC) {
  2119. SiS_SetRegANDOR(SISPART4, 0x0d, ~0x07, 0x01);
  2120. } else {
  2121. SiS_SetRegOR(SISPART4, 0x0d, 0x04);
  2122. }
  2123. SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
  2124. backupP2_00 = SiS_GetReg(SISPART2, 0x00);
  2125. SiS_SetReg(SISPART2, 0x00, ((backupP2_00 | 0x1c) & 0xfc));
  2126. backupP2_4d = SiS_GetReg(SISPART2, 0x4d);
  2127. if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) {
  2128. SiS_SetReg(SISPART2, 0x4d, (backupP2_4d & ~0x10));
  2129. }
  2130. if(!(ivideo->vbflags2 & VB2_30xCLV)) {
  2131. SISDoSense(ivideo, 0, 0);
  2132. }
  2133. SiS_SetRegAND(SISCR, 0x32, ~0x14);
  2134. if(vga2_c || vga2) {
  2135. if(SISDoSense(ivideo, vga2, vga2_c)) {
  2136. if(biosflag & 0x01) {
  2137. printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr);
  2138. SiS_SetRegOR(SISCR, 0x32, 0x04);
  2139. } else {
  2140. printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
  2141. SiS_SetRegOR(SISCR, 0x32, 0x10);
  2142. }
  2143. }
  2144. }
  2145. SiS_SetRegAND(SISCR, 0x32, 0x3f);
  2146. if(ivideo->vbflags2 & VB2_30xCLV) {
  2147. SiS_SetRegOR(SISPART4, 0x0d, 0x04);
  2148. }
  2149. if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
  2150. SiS_SetReg(SISPART2, 0x4d, (backupP2_4d | 0x10));
  2151. SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
  2152. if((result = SISDoSense(ivideo, svhs, 0x0604))) {
  2153. if((result = SISDoSense(ivideo, cvbs, 0x0804))) {
  2154. printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr);
  2155. SiS_SetRegOR(SISCR, 0x32, 0x80);
  2156. }
  2157. }
  2158. SiS_SetReg(SISPART2, 0x4d, backupP2_4d);
  2159. }
  2160. SiS_SetRegAND(SISCR, 0x32, ~0x03);
  2161. if(!(ivideo->vbflags & TV_YPBPR)) {
  2162. if((result = SISDoSense(ivideo, svhs, svhs_c))) {
  2163. printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
  2164. SiS_SetRegOR(SISCR, 0x32, 0x02);
  2165. }
  2166. if((biosflag & 0x02) || (!result)) {
  2167. if(SISDoSense(ivideo, cvbs, cvbs_c)) {
  2168. printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
  2169. SiS_SetRegOR(SISCR, 0x32, 0x01);
  2170. }
  2171. }
  2172. }
  2173. SISDoSense(ivideo, 0, 0);
  2174. SiS_SetReg(SISPART2, 0x00, backupP2_00);
  2175. SiS_SetReg(SISPART4, 0x0d, backupP4_0d);
  2176. SiS_SetReg(SISSR, 0x1e, backupSR_1e);
  2177. if(ivideo->vbflags2 & VB2_30xCLV) {
  2178. biosflag = SiS_GetReg(SISPART2, 0x00);
  2179. if(biosflag & 0x20) {
  2180. for(myflag = 2; myflag > 0; myflag--) {
  2181. biosflag ^= 0x20;
  2182. SiS_SetReg(SISPART2, 0x00, biosflag);
  2183. }
  2184. }
  2185. }
  2186. SiS_SetReg(SISPART2, 0x00, backupP2_00);
  2187. }
  2188. /* Determine and detect attached TV's on Chrontel */
  2189. static void __devinit
  2190. SiS_SenseCh(struct sis_video_info *ivideo)
  2191. {
  2192. #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
  2193. u8 temp1, temp2;
  2194. char stdstr[] = "sisfb: Chrontel: Detected TV connected to";
  2195. #endif
  2196. #ifdef CONFIG_FB_SIS_300
  2197. unsigned char test[3];
  2198. int i;
  2199. #endif
  2200. if(ivideo->chip < SIS_315H) {
  2201. #ifdef CONFIG_FB_SIS_300
  2202. ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 1; /* Chrontel 700x */
  2203. SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x9c); /* Set general purpose IO for Chrontel communication */
  2204. SiS_DDC2Delay(&ivideo->SiS_Pr, 1000);
  2205. temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
  2206. /* See Chrontel TB31 for explanation */
  2207. temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
  2208. if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
  2209. SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e, 0x0b);
  2210. SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
  2211. }
  2212. temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
  2213. if(temp2 != temp1) temp1 = temp2;
  2214. if((temp1 >= 0x22) && (temp1 <= 0x50)) {
  2215. /* Read power status */
  2216. temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
  2217. if((temp1 & 0x03) != 0x03) {
  2218. /* Power all outputs */
  2219. SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e,0x0b);
  2220. SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
  2221. }
  2222. /* Sense connected TV devices */
  2223. for(i = 0; i < 3; i++) {
  2224. SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x01);
  2225. SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
  2226. SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x00);
  2227. SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
  2228. temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10);
  2229. if(!(temp1 & 0x08)) test[i] = 0x02;
  2230. else if(!(temp1 & 0x02)) test[i] = 0x01;
  2231. else test[i] = 0;
  2232. SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
  2233. }
  2234. if(test[0] == test[1]) temp1 = test[0];
  2235. else if(test[0] == test[2]) temp1 = test[0];
  2236. else if(test[1] == test[2]) temp1 = test[1];
  2237. else {
  2238. printk(KERN_INFO
  2239. "sisfb: TV detection unreliable - test results varied\n");
  2240. temp1 = test[2];
  2241. }
  2242. if(temp1 == 0x02) {
  2243. printk(KERN_INFO "%s SVIDEO output\n", stdstr);
  2244. ivideo->vbflags |= TV_SVIDEO;
  2245. SiS_SetRegOR(SISCR, 0x32, 0x02);
  2246. SiS_SetRegAND(SISCR, 0x32, ~0x05);
  2247. } else if (temp1 == 0x01) {
  2248. printk(KERN_INFO "%s CVBS output\n", stdstr);
  2249. ivideo->vbflags |= TV_AVIDEO;
  2250. SiS_SetRegOR(SISCR, 0x32, 0x01);
  2251. SiS_SetRegAND(SISCR, 0x32, ~0x06);
  2252. } else {
  2253. SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
  2254. SiS_SetRegAND(SISCR, 0x32, ~0x07);
  2255. }
  2256. } else if(temp1 == 0) {
  2257. SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
  2258. SiS_SetRegAND(SISCR, 0x32, ~0x07);
  2259. }
  2260. /* Set general purpose IO for Chrontel communication */
  2261. SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00);
  2262. #endif
  2263. } else {
  2264. #ifdef CONFIG_FB_SIS_315
  2265. ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2; /* Chrontel 7019 */
  2266. temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
  2267. SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, 0x20);
  2268. SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
  2269. temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
  2270. temp2 |= 0x01;
  2271. SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
  2272. SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
  2273. temp2 ^= 0x01;
  2274. SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
  2275. SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
  2276. temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
  2277. SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, temp1);
  2278. temp1 = 0;
  2279. if(temp2 & 0x02) temp1 |= 0x01;
  2280. if(temp2 & 0x10) temp1 |= 0x01;
  2281. if(temp2 & 0x04) temp1 |= 0x02;
  2282. if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04;
  2283. switch(temp1) {
  2284. case 0x01:
  2285. printk(KERN_INFO "%s CVBS output\n", stdstr);
  2286. ivideo->vbflags |= TV_AVIDEO;
  2287. SiS_SetRegOR(SISCR, 0x32, 0x01);
  2288. SiS_SetRegAND(SISCR, 0x32, ~0x06);
  2289. break;
  2290. case 0x02:
  2291. printk(KERN_INFO "%s SVIDEO output\n", stdstr);
  2292. ivideo->vbflags |= TV_SVIDEO;
  2293. SiS_SetRegOR(SISCR, 0x32, 0x02);
  2294. SiS_SetRegAND(SISCR, 0x32, ~0x05);
  2295. break;
  2296. case 0x04:
  2297. printk(KERN_INFO "%s SCART output\n", stdstr);
  2298. SiS_SetRegOR(SISCR, 0x32, 0x04);
  2299. SiS_SetRegAND(SISCR, 0x32, ~0x03);
  2300. break;
  2301. default:
  2302. SiS_SetRegAND(SISCR, 0x32, ~0x07);
  2303. }
  2304. #endif
  2305. }
  2306. }
  2307. static void __devinit
  2308. sisfb_get_VB_type(struct sis_video_info *ivideo)
  2309. {
  2310. char stdstr[] = "sisfb: Detected";
  2311. char bridgestr[] = "video bridge";
  2312. u8 vb_chipid;
  2313. u8 reg;
  2314. /* No CRT2 on XGI Z7 */
  2315. if(ivideo->chip == XGI_20)
  2316. return;
  2317. vb_chipid = SiS_GetReg(SISPART4, 0x00);
  2318. switch(vb_chipid) {
  2319. case 0x01:
  2320. reg = SiS_GetReg(SISPART4, 0x01);
  2321. if(reg < 0xb0) {
  2322. ivideo->vbflags |= VB_301; /* Deprecated */
  2323. ivideo->vbflags2 |= VB2_301;
  2324. printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
  2325. } else if(reg < 0xc0) {
  2326. ivideo->vbflags |= VB_301B; /* Deprecated */
  2327. ivideo->vbflags2 |= VB2_301B;
  2328. reg = SiS_GetReg(SISPART4, 0x23);
  2329. if(!(reg & 0x02)) {
  2330. ivideo->vbflags |= VB_30xBDH; /* Deprecated */
  2331. ivideo->vbflags2 |= VB2_30xBDH;
  2332. printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
  2333. } else {
  2334. printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
  2335. }
  2336. } else if(reg < 0xd0) {
  2337. ivideo->vbflags |= VB_301C; /* Deprecated */
  2338. ivideo->vbflags2 |= VB2_301C;
  2339. printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
  2340. } else if(reg < 0xe0) {
  2341. ivideo->vbflags |= VB_301LV; /* Deprecated */
  2342. ivideo->vbflags2 |= VB2_301LV;
  2343. printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
  2344. } else if(reg <= 0xe1) {
  2345. reg = SiS_GetReg(SISPART4, 0x39);
  2346. if(reg == 0xff) {
  2347. ivideo->vbflags |= VB_302LV; /* Deprecated */
  2348. ivideo->vbflags2 |= VB2_302LV;
  2349. printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
  2350. } else {
  2351. ivideo->vbflags |= VB_301C; /* Deprecated */
  2352. ivideo->vbflags2 |= VB2_301C;
  2353. printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
  2354. #if 0
  2355. ivideo->vbflags |= VB_302ELV; /* Deprecated */
  2356. ivideo->vbflags2 |= VB2_302ELV;
  2357. printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
  2358. #endif
  2359. }
  2360. }
  2361. break;
  2362. case 0x02:
  2363. ivideo->vbflags |= VB_302B; /* Deprecated */
  2364. ivideo->vbflags2 |= VB2_302B;
  2365. printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
  2366. break;
  2367. }
  2368. if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
  2369. reg = SiS_GetReg(SISCR, 0x37);
  2370. reg &= SIS_EXTERNAL_CHIP_MASK;
  2371. reg >>= 1;
  2372. if(ivideo->sisvga_engine == SIS_300_VGA) {
  2373. #ifdef CONFIG_FB_SIS_300
  2374. switch(reg) {
  2375. case SIS_EXTERNAL_CHIP_LVDS:
  2376. ivideo->vbflags |= VB_LVDS; /* Deprecated */
  2377. ivideo->vbflags2 |= VB2_LVDS;
  2378. break;
  2379. case SIS_EXTERNAL_CHIP_TRUMPION:
  2380. ivideo->vbflags |= (VB_LVDS | VB_TRUMPION); /* Deprecated */
  2381. ivideo->vbflags2 |= (VB2_LVDS | VB2_TRUMPION);
  2382. break;
  2383. case SIS_EXTERNAL_CHIP_CHRONTEL:
  2384. ivideo->vbflags |= VB_CHRONTEL; /* Deprecated */
  2385. ivideo->vbflags2 |= VB2_CHRONTEL;
  2386. break;
  2387. case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
  2388. ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
  2389. ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
  2390. break;
  2391. }
  2392. if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 1;
  2393. #endif
  2394. } else if(ivideo->chip < SIS_661) {
  2395. #ifdef CONFIG_FB_SIS_315
  2396. switch (reg) {
  2397. case SIS310_EXTERNAL_CHIP_LVDS:
  2398. ivideo->vbflags |= VB_LVDS; /* Deprecated */
  2399. ivideo->vbflags2 |= VB2_LVDS;
  2400. break;
  2401. case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
  2402. ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
  2403. ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
  2404. break;
  2405. }
  2406. if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
  2407. #endif
  2408. } else if(ivideo->chip >= SIS_661) {
  2409. #ifdef CONFIG_FB_SIS_315
  2410. reg = SiS_GetReg(SISCR, 0x38);
  2411. reg >>= 5;
  2412. switch(reg) {
  2413. case 0x02:
  2414. ivideo->vbflags |= VB_LVDS; /* Deprecated */
  2415. ivideo->vbflags2 |= VB2_LVDS;
  2416. break;
  2417. case 0x03:
  2418. ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL); /* Deprecated */
  2419. ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
  2420. break;
  2421. case 0x04:
  2422. ivideo->vbflags |= (VB_LVDS | VB_CONEXANT); /* Deprecated */
  2423. ivideo->vbflags2 |= (VB2_LVDS | VB2_CONEXANT);
  2424. break;
  2425. }
  2426. if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
  2427. #endif
  2428. }
  2429. if(ivideo->vbflags2 & VB2_LVDS) {
  2430. printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
  2431. }
  2432. if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags2 & VB2_TRUMPION)) {
  2433. printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
  2434. }
  2435. if(ivideo->vbflags2 & VB2_CHRONTEL) {
  2436. printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
  2437. }
  2438. if((ivideo->chip >= SIS_661) && (ivideo->vbflags2 & VB2_CONEXANT)) {
  2439. printk(KERN_INFO "%s Conexant external device\n", stdstr);
  2440. }
  2441. }
  2442. if(ivideo->vbflags2 & VB2_SISBRIDGE) {
  2443. SiS_SenseLCD(ivideo);
  2444. SiS_Sense30x(ivideo);
  2445. } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
  2446. SiS_SenseCh(ivideo);
  2447. }
  2448. }
  2449. /* ---------- Engine initialization routines ------------ */
  2450. static void
  2451. sisfb_engine_init(struct sis_video_info *ivideo)
  2452. {
  2453. /* Initialize command queue (we use MMIO only) */
  2454. /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
  2455. ivideo->caps &= ~(TURBO_QUEUE_CAP |
  2456. MMIO_CMD_QUEUE_CAP |
  2457. VM_CMD_QUEUE_CAP |
  2458. AGP_CMD_QUEUE_CAP);
  2459. #ifdef CONFIG_FB_SIS_300
  2460. if(ivideo->sisvga_engine == SIS_300_VGA) {
  2461. u32 tqueue_pos;
  2462. u8 tq_state;
  2463. tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024);
  2464. tq_state = SiS_GetReg(SISSR, IND_SIS_TURBOQUEUE_SET);
  2465. tq_state |= 0xf0;
  2466. tq_state &= 0xfc;
  2467. tq_state |= (u8)(tqueue_pos >> 8);
  2468. SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
  2469. SiS_SetReg(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
  2470. ivideo->caps |= TURBO_QUEUE_CAP;
  2471. }
  2472. #endif
  2473. #ifdef CONFIG_FB_SIS_315
  2474. if(ivideo->sisvga_engine == SIS_315_VGA) {
  2475. u32 tempq = 0, templ;
  2476. u8 temp;
  2477. if(ivideo->chip == XGI_20) {
  2478. switch(ivideo->cmdQueueSize) {
  2479. case (64 * 1024):
  2480. temp = SIS_CMD_QUEUE_SIZE_Z7_64k;
  2481. break;
  2482. case (128 * 1024):
  2483. default:
  2484. temp = SIS_CMD_QUEUE_SIZE_Z7_128k;
  2485. }
  2486. } else {
  2487. switch(ivideo->cmdQueueSize) {
  2488. case (4 * 1024 * 1024):
  2489. temp = SIS_CMD_QUEUE_SIZE_4M;
  2490. break;
  2491. case (2 * 1024 * 1024):
  2492. temp = SIS_CMD_QUEUE_SIZE_2M;
  2493. break;
  2494. case (1 * 1024 * 1024):
  2495. temp = SIS_CMD_QUEUE_SIZE_1M;
  2496. break;
  2497. default:
  2498. case (512 * 1024):
  2499. temp = SIS_CMD_QUEUE_SIZE_512k;
  2500. }
  2501. }
  2502. SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
  2503. SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
  2504. if((ivideo->chip >= XGI_40) && ivideo->modechanged) {
  2505. /* Must disable dual pipe on XGI_40. Can't do
  2506. * this in MMIO mode, because it requires
  2507. * setting/clearing a bit in the MMIO fire trigger
  2508. * register.
  2509. */
  2510. if(!((templ = MMIO_IN32(ivideo->mmio_vbase, 0x8240)) & (1 << 10))) {
  2511. MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0);
  2512. SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE));
  2513. tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR);
  2514. MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq);
  2515. tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
  2516. MMIO_OUT32(ivideo->mmio_vbase, Q_BASE_ADDR, tempq);
  2517. writel(0x16800000 + 0x8240, ivideo->video_vbase + tempq);
  2518. writel(templ | (1 << 10), ivideo->video_vbase + tempq + 4);
  2519. writel(0x168F0000, ivideo->video_vbase + tempq + 8);
  2520. writel(0x168F0000, ivideo->video_vbase + tempq + 12);
  2521. MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, (tempq + 16));
  2522. sisfb_syncaccel(ivideo);
  2523. SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
  2524. }
  2525. }
  2526. tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
  2527. MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
  2528. temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
  2529. SiS_SetReg(SISSR, IND_SIS_CMDQUEUE_SET, temp);
  2530. tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
  2531. MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
  2532. ivideo->caps |= MMIO_CMD_QUEUE_CAP;
  2533. }
  2534. #endif
  2535. ivideo->engineok = 1;
  2536. }
  2537. static void __devinit
  2538. sisfb_detect_lcd_type(struct sis_video_info *ivideo)
  2539. {
  2540. u8 reg;
  2541. int i;
  2542. reg = SiS_GetReg(SISCR, 0x36);
  2543. reg &= 0x0f;
  2544. if(ivideo->sisvga_engine == SIS_300_VGA) {
  2545. ivideo->CRT2LCDType = sis300paneltype[reg];
  2546. } else if(ivideo->chip >= SIS_661) {
  2547. ivideo->CRT2LCDType = sis661paneltype[reg];
  2548. } else {
  2549. ivideo->CRT2LCDType = sis310paneltype[reg];
  2550. if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
  2551. if((ivideo->CRT2LCDType != LCD_320x240_2) &&
  2552. (ivideo->CRT2LCDType != LCD_320x240_3)) {
  2553. ivideo->CRT2LCDType = LCD_320x240;
  2554. }
  2555. }
  2556. }
  2557. if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
  2558. /* For broken BIOSes: Assume 1024x768, RGB18 */
  2559. ivideo->CRT2LCDType = LCD_1024x768;
  2560. SiS_SetRegANDOR(SISCR, 0x36, 0xf0, 0x02);
  2561. SiS_SetRegANDOR(SISCR, 0x37, 0xee, 0x01);
  2562. printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
  2563. }
  2564. for(i = 0; i < SIS_LCD_NUMBER; i++) {
  2565. if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
  2566. ivideo->lcdxres = sis_lcd_data[i].xres;
  2567. ivideo->lcdyres = sis_lcd_data[i].yres;
  2568. ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
  2569. break;
  2570. }
  2571. }
  2572. #ifdef CONFIG_FB_SIS_300
  2573. if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
  2574. ivideo->lcdxres = 1360; ivideo->lcdyres = 1024;
  2575. ivideo->lcddefmodeidx = DEFAULT_MODE_1360;
  2576. } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
  2577. ivideo->lcdxres = 848; ivideo->lcdyres = 480;
  2578. ivideo->lcddefmodeidx = DEFAULT_MODE_848;
  2579. } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL856) {
  2580. ivideo->lcdxres = 856; ivideo->lcdyres = 480;
  2581. ivideo->lcddefmodeidx = DEFAULT_MODE_856;
  2582. }
  2583. #endif
  2584. printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
  2585. ivideo->lcdxres, ivideo->lcdyres);
  2586. }
  2587. static void __devinit
  2588. sisfb_save_pdc_emi(struct sis_video_info *ivideo)
  2589. {
  2590. #ifdef CONFIG_FB_SIS_300
  2591. /* Save the current PanelDelayCompensation if the LCD is currently used */
  2592. if(ivideo->sisvga_engine == SIS_300_VGA) {
  2593. if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) {
  2594. int tmp;
  2595. tmp = SiS_GetReg(SISCR, 0x30);
  2596. if(tmp & 0x20) {
  2597. /* Currently on LCD? If yes, read current pdc */
  2598. ivideo->detectedpdc = SiS_GetReg(SISPART1, 0x13);
  2599. ivideo->detectedpdc &= 0x3c;
  2600. if(ivideo->SiS_Pr.PDC == -1) {
  2601. /* Let option override detection */
  2602. ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
  2603. }
  2604. printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
  2605. ivideo->detectedpdc);
  2606. }
  2607. if((ivideo->SiS_Pr.PDC != -1) &&
  2608. (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
  2609. printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
  2610. ivideo->SiS_Pr.PDC);
  2611. }
  2612. }
  2613. }
  2614. #endif
  2615. #ifdef CONFIG_FB_SIS_315
  2616. if(ivideo->sisvga_engine == SIS_315_VGA) {
  2617. /* Try to find about LCDA */
  2618. if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) {
  2619. int tmp;
  2620. tmp = SiS_GetReg(SISPART1, 0x13);
  2621. if(tmp & 0x04) {
  2622. ivideo->SiS_Pr.SiS_UseLCDA = true;
  2623. ivideo->detectedlcda = 0x03;
  2624. }
  2625. }
  2626. /* Save PDC */
  2627. if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
  2628. int tmp;
  2629. tmp = SiS_GetReg(SISCR, 0x30);
  2630. if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
  2631. /* Currently on LCD? If yes, read current pdc */
  2632. u8 pdc;
  2633. pdc = SiS_GetReg(SISPART1, 0x2D);
  2634. ivideo->detectedpdc = (pdc & 0x0f) << 1;
  2635. ivideo->detectedpdca = (pdc & 0xf0) >> 3;
  2636. pdc = SiS_GetReg(SISPART1, 0x35);
  2637. ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
  2638. pdc = SiS_GetReg(SISPART1, 0x20);
  2639. ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
  2640. if(ivideo->newrom) {
  2641. /* New ROM invalidates other PDC resp. */
  2642. if(ivideo->detectedlcda != 0xff) {
  2643. ivideo->detectedpdc = 0xff;
  2644. } else {
  2645. ivideo->detectedpdca = 0xff;
  2646. }
  2647. }
  2648. if(ivideo->SiS_Pr.PDC == -1) {
  2649. if(ivideo->detectedpdc != 0xff) {
  2650. ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
  2651. }
  2652. }
  2653. if(ivideo->SiS_Pr.PDCA == -1) {
  2654. if(ivideo->detectedpdca != 0xff) {
  2655. ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
  2656. }
  2657. }
  2658. if(ivideo->detectedpdc != 0xff) {
  2659. printk(KERN_INFO
  2660. "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
  2661. ivideo->detectedpdc);
  2662. }
  2663. if(ivideo->detectedpdca != 0xff) {
  2664. printk(KERN_INFO
  2665. "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
  2666. ivideo->detectedpdca);
  2667. }
  2668. }
  2669. /* Save EMI */
  2670. if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) {
  2671. ivideo->SiS_Pr.EMI_30 = SiS_GetReg(SISPART4, 0x30);
  2672. ivideo->SiS_Pr.EMI_31 = SiS_GetReg(SISPART4, 0x31);
  2673. ivideo->SiS_Pr.EMI_32 = SiS_GetReg(SISPART4, 0x32);
  2674. ivideo->SiS_Pr.EMI_33 = SiS_GetReg(SISPART4, 0x33);
  2675. ivideo->SiS_Pr.HaveEMI = true;
  2676. if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
  2677. ivideo->SiS_Pr.HaveEMILCD = true;
  2678. }
  2679. }
  2680. }
  2681. /* Let user override detected PDCs (all bridges) */
  2682. if(ivideo->vbflags2 & VB2_30xBLV) {
  2683. if((ivideo->SiS_Pr.PDC != -1) &&
  2684. (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
  2685. printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
  2686. ivideo->SiS_Pr.PDC);
  2687. }
  2688. if((ivideo->SiS_Pr.PDCA != -1) &&
  2689. (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
  2690. printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
  2691. ivideo->SiS_Pr.PDCA);
  2692. }
  2693. }
  2694. }
  2695. #endif
  2696. }
  2697. /* -------------------- Memory manager routines ---------------------- */
  2698. static u32 __devinit
  2699. sisfb_getheapstart(struct sis_video_info *ivideo)
  2700. {
  2701. u32 ret = ivideo->sisfb_parm_mem * 1024;
  2702. u32 maxoffs = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
  2703. u32 def;
  2704. /* Calculate heap start = end of memory for console
  2705. *
  2706. * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
  2707. * C = console, D = heap, H = HWCursor, Q = cmd-queue
  2708. *
  2709. * On 76x in UMA+LFB mode, the layout is as follows:
  2710. * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
  2711. * where the heap is the entire UMA area, eventually
  2712. * into the LFB area if the given mem parameter is
  2713. * higher than the size of the UMA memory.
  2714. *
  2715. * Basically given by "mem" parameter
  2716. *
  2717. * maximum = videosize - cmd_queue - hwcursor
  2718. * (results in a heap of size 0)
  2719. * default = SiS 300: depends on videosize
  2720. * SiS 315/330/340/XGI: 32k below max
  2721. */
  2722. if(ivideo->sisvga_engine == SIS_300_VGA) {
  2723. if(ivideo->video_size > 0x1000000) {
  2724. def = 0xc00000;
  2725. } else if(ivideo->video_size > 0x800000) {
  2726. def = 0x800000;
  2727. } else {
  2728. def = 0x400000;
  2729. }
  2730. } else if(ivideo->UMAsize && ivideo->LFBsize) {
  2731. ret = def = 0;
  2732. } else {
  2733. def = maxoffs - 0x8000;
  2734. }
  2735. /* Use default for secondary card for now (FIXME) */
  2736. if((!ret) || (ret > maxoffs) || (ivideo->cardnumber != 0))
  2737. ret = def;
  2738. return ret;
  2739. }
  2740. static u32 __devinit
  2741. sisfb_getheapsize(struct sis_video_info *ivideo)
  2742. {
  2743. u32 max = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
  2744. u32 ret = 0;
  2745. if(ivideo->UMAsize && ivideo->LFBsize) {
  2746. if( (!ivideo->sisfb_parm_mem) ||
  2747. ((ivideo->sisfb_parm_mem * 1024) > max) ||
  2748. ((max - (ivideo->sisfb_parm_mem * 1024)) < ivideo->UMAsize) ) {
  2749. ret = ivideo->UMAsize;
  2750. max -= ivideo->UMAsize;
  2751. } else {
  2752. ret = max - (ivideo->sisfb_parm_mem * 1024);
  2753. max = ivideo->sisfb_parm_mem * 1024;
  2754. }
  2755. ivideo->video_offset = ret;
  2756. ivideo->sisfb_mem = max;
  2757. } else {
  2758. ret = max - ivideo->heapstart;
  2759. ivideo->sisfb_mem = ivideo->heapstart;
  2760. }
  2761. return ret;
  2762. }
  2763. static int __devinit
  2764. sisfb_heap_init(struct sis_video_info *ivideo)
  2765. {
  2766. struct SIS_OH *poh;
  2767. ivideo->video_offset = 0;
  2768. if(ivideo->sisfb_parm_mem) {
  2769. if( (ivideo->sisfb_parm_mem < (2 * 1024 * 1024)) ||
  2770. (ivideo->sisfb_parm_mem > ivideo->video_size) ) {
  2771. ivideo->sisfb_parm_mem = 0;
  2772. }
  2773. }
  2774. ivideo->heapstart = sisfb_getheapstart(ivideo);
  2775. ivideo->sisfb_heap_size = sisfb_getheapsize(ivideo);
  2776. ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
  2777. ivideo->sisfb_heap_end = ivideo->sisfb_heap_start + ivideo->sisfb_heap_size;
  2778. printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
  2779. (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
  2780. ivideo->sisfb_heap.vinfo = ivideo;
  2781. ivideo->sisfb_heap.poha_chain = NULL;
  2782. ivideo->sisfb_heap.poh_freelist = NULL;
  2783. poh = sisfb_poh_new_node(&ivideo->sisfb_heap);
  2784. if(poh == NULL)
  2785. return 1;
  2786. poh->poh_next = &ivideo->sisfb_heap.oh_free;
  2787. poh->poh_prev = &ivideo->sisfb_heap.oh_free;
  2788. poh->size = ivideo->sisfb_heap_size;
  2789. poh->offset = ivideo->heapstart;
  2790. ivideo->sisfb_heap.oh_free.poh_next = poh;
  2791. ivideo->sisfb_heap.oh_free.poh_prev = poh;
  2792. ivideo->sisfb_heap.oh_free.size = 0;
  2793. ivideo->sisfb_heap.max_freesize = poh->size;
  2794. ivideo->sisfb_heap.oh_used.poh_next = &ivideo->sisfb_heap.oh_used;
  2795. ivideo->sisfb_heap.oh_used.poh_prev = &ivideo->sisfb_heap.oh_used;
  2796. ivideo->sisfb_heap.oh_used.size = SENTINEL;
  2797. if(ivideo->cardnumber == 0) {
  2798. /* For the first card, make this heap the "global" one
  2799. * for old DRM (which could handle only one card)
  2800. */
  2801. sisfb_heap = &ivideo->sisfb_heap;
  2802. }
  2803. return 0;
  2804. }
  2805. static struct SIS_OH *
  2806. sisfb_poh_new_node(struct SIS_HEAP *memheap)
  2807. {
  2808. struct SIS_OHALLOC *poha;
  2809. struct SIS_OH *poh;
  2810. unsigned long cOhs;
  2811. int i;
  2812. if(memheap->poh_freelist == NULL) {
  2813. poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL);
  2814. if(!poha)
  2815. return NULL;
  2816. poha->poha_next = memheap->poha_chain;
  2817. memheap->poha_chain = poha;
  2818. cOhs = (SIS_OH_ALLOC_SIZE - sizeof(struct SIS_OHALLOC)) / sizeof(struct SIS_OH) + 1;
  2819. poh = &poha->aoh[0];
  2820. for(i = cOhs - 1; i != 0; i--) {
  2821. poh->poh_next = poh + 1;
  2822. poh = poh + 1;
  2823. }
  2824. poh->poh_next = NULL;
  2825. memheap->poh_freelist = &poha->aoh[0];
  2826. }
  2827. poh = memheap->poh_freelist;
  2828. memheap->poh_freelist = poh->poh_next;
  2829. return poh;
  2830. }
  2831. static struct SIS_OH *
  2832. sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size)
  2833. {
  2834. struct SIS_OH *pohThis;
  2835. struct SIS_OH *pohRoot;
  2836. int bAllocated = 0;
  2837. if(size > memheap->max_freesize) {
  2838. DPRINTK("sisfb: Can't allocate %dk video memory\n",
  2839. (unsigned int) size / 1024);
  2840. return NULL;
  2841. }
  2842. pohThis = memheap->oh_free.poh_next;
  2843. while(pohThis != &memheap->oh_free) {
  2844. if(size <= pohThis->size) {
  2845. bAllocated = 1;
  2846. break;
  2847. }
  2848. pohThis = pohThis->poh_next;
  2849. }
  2850. if(!bAllocated) {
  2851. DPRINTK("sisfb: Can't allocate %dk video memory\n",
  2852. (unsigned int) size / 1024);
  2853. return NULL;
  2854. }
  2855. if(size == pohThis->size) {
  2856. pohRoot = pohThis;
  2857. sisfb_delete_node(pohThis);
  2858. } else {
  2859. pohRoot = sisfb_poh_new_node(memheap);
  2860. if(pohRoot == NULL)
  2861. return NULL;
  2862. pohRoot->offset = pohThis->offset;
  2863. pohRoot->size = size;
  2864. pohThis->offset += size;
  2865. pohThis->size -= size;
  2866. }
  2867. memheap->max_freesize -= size;
  2868. pohThis = &memheap->oh_used;
  2869. sisfb_insert_node(pohThis, pohRoot);
  2870. return pohRoot;
  2871. }
  2872. static void
  2873. sisfb_delete_node(struct SIS_OH *poh)
  2874. {
  2875. poh->poh_prev->poh_next = poh->poh_next;
  2876. poh->poh_next->poh_prev = poh->poh_prev;
  2877. }
  2878. static void
  2879. sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh)
  2880. {
  2881. struct SIS_OH *pohTemp = pohList->poh_next;
  2882. pohList->poh_next = poh;
  2883. pohTemp->poh_prev = poh;
  2884. poh->poh_prev = pohList;
  2885. poh->poh_next = pohTemp;
  2886. }
  2887. static struct SIS_OH *
  2888. sisfb_poh_free(struct SIS_HEAP *memheap, u32 base)
  2889. {
  2890. struct SIS_OH *pohThis;
  2891. struct SIS_OH *poh_freed;
  2892. struct SIS_OH *poh_prev;
  2893. struct SIS_OH *poh_next;
  2894. u32 ulUpper;
  2895. u32 ulLower;
  2896. int foundNode = 0;
  2897. poh_freed = memheap->oh_used.poh_next;
  2898. while(poh_freed != &memheap->oh_used) {
  2899. if(poh_freed->offset == base) {
  2900. foundNode = 1;
  2901. break;
  2902. }
  2903. poh_freed = poh_freed->poh_next;
  2904. }
  2905. if(!foundNode)
  2906. return NULL;
  2907. memheap->max_freesize += poh_freed->size;
  2908. poh_prev = poh_next = NULL;
  2909. ulUpper = poh_freed->offset + poh_freed->size;
  2910. ulLower = poh_freed->offset;
  2911. pohThis = memheap->oh_free.poh_next;
  2912. while(pohThis != &memheap->oh_free) {
  2913. if(pohThis->offset == ulUpper) {
  2914. poh_next = pohThis;
  2915. } else if((pohThis->offset + pohThis->size) == ulLower) {
  2916. poh_prev = pohThis;
  2917. }
  2918. pohThis = pohThis->poh_next;
  2919. }
  2920. sisfb_delete_node(poh_freed);
  2921. if(poh_prev && poh_next) {
  2922. poh_prev->size += (poh_freed->size + poh_next->size);
  2923. sisfb_delete_node(poh_next);
  2924. sisfb_free_node(memheap, poh_freed);
  2925. sisfb_free_node(memheap, poh_next);
  2926. return poh_prev;
  2927. }
  2928. if(poh_prev) {
  2929. poh_prev->size += poh_freed->size;
  2930. sisfb_free_node(memheap, poh_freed);
  2931. return poh_prev;
  2932. }
  2933. if(poh_next) {
  2934. poh_next->size += poh_freed->size;
  2935. poh_next->offset = poh_freed->offset;
  2936. sisfb_free_node(memheap, poh_freed);
  2937. return poh_next;
  2938. }
  2939. sisfb_insert_node(&memheap->oh_free, poh_freed);
  2940. return poh_freed;
  2941. }
  2942. static void
  2943. sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh)
  2944. {
  2945. if(poh == NULL)
  2946. return;
  2947. poh->poh_next = memheap->poh_freelist;
  2948. memheap->poh_freelist = poh;
  2949. }
  2950. static void
  2951. sis_int_malloc(struct sis_video_info *ivideo, struct sis_memreq *req)
  2952. {
  2953. struct SIS_OH *poh = NULL;
  2954. if((ivideo) && (ivideo->sisfb_id == SISFB_ID) && (!ivideo->havenoheap))
  2955. poh = sisfb_poh_allocate(&ivideo->sisfb_heap, (u32)req->size);
  2956. if(poh == NULL) {
  2957. req->offset = req->size = 0;
  2958. DPRINTK("sisfb: Video RAM allocation failed\n");
  2959. } else {
  2960. req->offset = poh->offset;
  2961. req->size = poh->size;
  2962. DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
  2963. (poh->offset + ivideo->video_vbase));
  2964. }
  2965. }
  2966. void
  2967. sis_malloc(struct sis_memreq *req)
  2968. {
  2969. struct sis_video_info *ivideo = sisfb_heap->vinfo;
  2970. if(&ivideo->sisfb_heap == sisfb_heap)
  2971. sis_int_malloc(ivideo, req);
  2972. else
  2973. req->offset = req->size = 0;
  2974. }
  2975. void
  2976. sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req)
  2977. {
  2978. struct sis_video_info *ivideo = pci_get_drvdata(pdev);
  2979. sis_int_malloc(ivideo, req);
  2980. }
  2981. /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
  2982. static void
  2983. sis_int_free(struct sis_video_info *ivideo, u32 base)
  2984. {
  2985. struct SIS_OH *poh;
  2986. if((!ivideo) || (ivideo->sisfb_id != SISFB_ID) || (ivideo->havenoheap))
  2987. return;
  2988. poh = sisfb_poh_free(&ivideo->sisfb_heap, base);
  2989. if(poh == NULL) {
  2990. DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
  2991. (unsigned int) base);
  2992. }
  2993. }
  2994. void
  2995. sis_free(u32 base)
  2996. {
  2997. struct sis_video_info *ivideo = sisfb_heap->vinfo;
  2998. sis_int_free(ivideo, base);
  2999. }
  3000. void
  3001. sis_free_new(struct pci_dev *pdev, u32 base)
  3002. {
  3003. struct sis_video_info *ivideo = pci_get_drvdata(pdev);
  3004. sis_int_free(ivideo, base);
  3005. }
  3006. /* --------------------- SetMode routines ------------------------- */
  3007. static void
  3008. sisfb_check_engine_and_sync(struct sis_video_info *ivideo)
  3009. {
  3010. u8 cr30, cr31;
  3011. /* Check if MMIO and engines are enabled,
  3012. * and sync in case they are. Can't use
  3013. * ivideo->accel here, as this might have
  3014. * been changed before this is called.
  3015. */
  3016. cr30 = SiS_GetReg(SISSR, IND_SIS_PCI_ADDRESS_SET);
  3017. cr31 = SiS_GetReg(SISSR, IND_SIS_MODULE_ENABLE);
  3018. /* MMIO and 2D/3D engine enabled? */
  3019. if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) {
  3020. #ifdef CONFIG_FB_SIS_300
  3021. if(ivideo->sisvga_engine == SIS_300_VGA) {
  3022. /* Don't care about TurboQueue. It's
  3023. * enough to know that the engines
  3024. * are enabled
  3025. */
  3026. sisfb_syncaccel(ivideo);
  3027. }
  3028. #endif
  3029. #ifdef CONFIG_FB_SIS_315
  3030. if(ivideo->sisvga_engine == SIS_315_VGA) {
  3031. /* Check that any queue mode is
  3032. * enabled, and that the queue
  3033. * is not in the state of "reset"
  3034. */
  3035. cr30 = SiS_GetReg(SISSR, 0x26);
  3036. if((cr30 & 0xe0) && (!(cr30 & 0x01))) {
  3037. sisfb_syncaccel(ivideo);
  3038. }
  3039. }
  3040. #endif
  3041. }
  3042. }
  3043. static void
  3044. sisfb_pre_setmode(struct sis_video_info *ivideo)
  3045. {
  3046. u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0;
  3047. int tvregnum = 0;
  3048. ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
  3049. SiS_SetReg(SISSR, 0x05, 0x86);
  3050. cr31 = SiS_GetReg(SISCR, 0x31);
  3051. cr31 &= ~0x60;
  3052. cr31 |= 0x04;
  3053. cr33 = ivideo->rate_idx & 0x0F;
  3054. #ifdef CONFIG_FB_SIS_315
  3055. if(ivideo->sisvga_engine == SIS_315_VGA) {
  3056. if(ivideo->chip >= SIS_661) {
  3057. cr38 = SiS_GetReg(SISCR, 0x38);
  3058. cr38 &= ~0x07; /* Clear LCDA/DualEdge and YPbPr bits */
  3059. } else {
  3060. tvregnum = 0x38;
  3061. cr38 = SiS_GetReg(SISCR, tvregnum);
  3062. cr38 &= ~0x3b; /* Clear LCDA/DualEdge and YPbPr bits */
  3063. }
  3064. }
  3065. #endif
  3066. #ifdef CONFIG_FB_SIS_300
  3067. if(ivideo->sisvga_engine == SIS_300_VGA) {
  3068. tvregnum = 0x35;
  3069. cr38 = SiS_GetReg(SISCR, tvregnum);
  3070. }
  3071. #endif
  3072. SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
  3073. SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
  3074. ivideo->curFSTN = ivideo->curDSTN = 0;
  3075. switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
  3076. case CRT2_TV:
  3077. cr38 &= ~0xc0; /* Clear PAL-M / PAL-N bits */
  3078. if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
  3079. #ifdef CONFIG_FB_SIS_315
  3080. if(ivideo->chip >= SIS_661) {
  3081. cr38 |= 0x04;
  3082. if(ivideo->vbflags & TV_YPBPR525P) cr35 |= 0x20;
  3083. else if(ivideo->vbflags & TV_YPBPR750P) cr35 |= 0x40;
  3084. else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60;
  3085. cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
  3086. cr35 &= ~0x01;
  3087. ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
  3088. } else if(ivideo->sisvga_engine == SIS_315_VGA) {
  3089. cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
  3090. cr38 |= 0x08;
  3091. if(ivideo->vbflags & TV_YPBPR525P) cr38 |= 0x10;
  3092. else if(ivideo->vbflags & TV_YPBPR750P) cr38 |= 0x20;
  3093. else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30;
  3094. cr31 &= ~0x01;
  3095. ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
  3096. }
  3097. #endif
  3098. } else if((ivideo->vbflags & TV_HIVISION) &&
  3099. (ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) {
  3100. if(ivideo->chip >= SIS_661) {
  3101. cr38 |= 0x04;
  3102. cr35 |= 0x60;
  3103. } else {
  3104. cr30 |= 0x80;
  3105. }
  3106. cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
  3107. cr31 |= 0x01;
  3108. cr35 |= 0x01;
  3109. ivideo->currentvbflags |= TV_HIVISION;
  3110. } else if(ivideo->vbflags & TV_SCART) {
  3111. cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
  3112. cr31 |= 0x01;
  3113. cr35 |= 0x01;
  3114. ivideo->currentvbflags |= TV_SCART;
  3115. } else {
  3116. if(ivideo->vbflags & TV_SVIDEO) {
  3117. cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
  3118. ivideo->currentvbflags |= TV_SVIDEO;
  3119. }
  3120. if(ivideo->vbflags & TV_AVIDEO) {
  3121. cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE);
  3122. ivideo->currentvbflags |= TV_AVIDEO;
  3123. }
  3124. }
  3125. cr31 |= SIS_DRIVER_MODE;
  3126. if(ivideo->vbflags & (TV_AVIDEO | TV_SVIDEO)) {
  3127. if(ivideo->vbflags & TV_PAL) {
  3128. cr31 |= 0x01; cr35 |= 0x01;
  3129. ivideo->currentvbflags |= TV_PAL;
  3130. if(ivideo->vbflags & TV_PALM) {
  3131. cr38 |= 0x40; cr35 |= 0x04;
  3132. ivideo->currentvbflags |= TV_PALM;
  3133. } else if(ivideo->vbflags & TV_PALN) {
  3134. cr38 |= 0x80; cr35 |= 0x08;
  3135. ivideo->currentvbflags |= TV_PALN;
  3136. }
  3137. } else {
  3138. cr31 &= ~0x01; cr35 &= ~0x01;
  3139. ivideo->currentvbflags |= TV_NTSC;
  3140. if(ivideo->vbflags & TV_NTSCJ) {
  3141. cr38 |= 0x40; cr35 |= 0x02;
  3142. ivideo->currentvbflags |= TV_NTSCJ;
  3143. }
  3144. }
  3145. }
  3146. break;
  3147. case CRT2_LCD:
  3148. cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
  3149. cr31 |= SIS_DRIVER_MODE;
  3150. SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn);
  3151. SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn);
  3152. ivideo->curFSTN = ivideo->sisfb_fstn;
  3153. ivideo->curDSTN = ivideo->sisfb_dstn;
  3154. break;
  3155. case CRT2_VGA:
  3156. cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
  3157. cr31 |= SIS_DRIVER_MODE;
  3158. if(ivideo->sisfb_nocrt2rate) {
  3159. cr33 |= (sisbios_mode[ivideo->sisfb_mode_idx].rate_idx << 4);
  3160. } else {
  3161. cr33 |= ((ivideo->rate_idx & 0x0F) << 4);
  3162. }
  3163. break;
  3164. default: /* disable CRT2 */
  3165. cr30 = 0x00;
  3166. cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
  3167. }
  3168. SiS_SetReg(SISCR, 0x30, cr30);
  3169. SiS_SetReg(SISCR, 0x33, cr33);
  3170. if(ivideo->chip >= SIS_661) {
  3171. #ifdef CONFIG_FB_SIS_315
  3172. cr31 &= ~0x01; /* Clear PAL flag (now in CR35) */
  3173. SiS_SetRegANDOR(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
  3174. cr38 &= 0x07; /* Use only LCDA and HiVision/YPbPr bits */
  3175. SiS_SetRegANDOR(SISCR, 0x38, 0xf8, cr38);
  3176. #endif
  3177. } else if(ivideo->chip != SIS_300) {
  3178. SiS_SetReg(SISCR, tvregnum, cr38);
  3179. }
  3180. SiS_SetReg(SISCR, 0x31, cr31);
  3181. ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
  3182. sisfb_check_engine_and_sync(ivideo);
  3183. }
  3184. /* Fix SR11 for 661 and later */
  3185. #ifdef CONFIG_FB_SIS_315
  3186. static void
  3187. sisfb_fixup_SR11(struct sis_video_info *ivideo)
  3188. {
  3189. u8 tmpreg;
  3190. if(ivideo->chip >= SIS_661) {
  3191. tmpreg = SiS_GetReg(SISSR, 0x11);
  3192. if(tmpreg & 0x20) {
  3193. tmpreg = SiS_GetReg(SISSR, 0x3e);
  3194. tmpreg = (tmpreg + 1) & 0xff;
  3195. SiS_SetReg(SISSR, 0x3e, tmpreg);
  3196. tmpreg = SiS_GetReg(SISSR, 0x11);
  3197. }
  3198. if(tmpreg & 0xf0) {
  3199. SiS_SetRegAND(SISSR, 0x11, 0x0f);
  3200. }
  3201. }
  3202. }
  3203. #endif
  3204. static void
  3205. sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
  3206. {
  3207. if(val > 32) val = 32;
  3208. if(val < -32) val = -32;
  3209. ivideo->tvxpos = val;
  3210. if(ivideo->sisfblocked) return;
  3211. if(!ivideo->modechanged) return;
  3212. if(ivideo->currentvbflags & CRT2_TV) {
  3213. if(ivideo->vbflags2 & VB2_CHRONTEL) {
  3214. int x = ivideo->tvx;
  3215. switch(ivideo->chronteltype) {
  3216. case 1:
  3217. x += val;
  3218. if(x < 0) x = 0;
  3219. SiS_SetReg(SISSR, 0x05, 0x86);
  3220. SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff));
  3221. SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD);
  3222. break;
  3223. case 2:
  3224. /* Not supported by hardware */
  3225. break;
  3226. }
  3227. } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
  3228. u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
  3229. unsigned short temp;
  3230. p2_1f = ivideo->p2_1f;
  3231. p2_20 = ivideo->p2_20;
  3232. p2_2b = ivideo->p2_2b;
  3233. p2_42 = ivideo->p2_42;
  3234. p2_43 = ivideo->p2_43;
  3235. temp = p2_1f | ((p2_20 & 0xf0) << 4);
  3236. temp += (val * 2);
  3237. p2_1f = temp & 0xff;
  3238. p2_20 = (temp & 0xf00) >> 4;
  3239. p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
  3240. temp = p2_43 | ((p2_42 & 0xf0) << 4);
  3241. temp += (val * 2);
  3242. p2_43 = temp & 0xff;
  3243. p2_42 = (temp & 0xf00) >> 4;
  3244. SiS_SetReg(SISPART2, 0x1f, p2_1f);
  3245. SiS_SetRegANDOR(SISPART2, 0x20, 0x0F, p2_20);
  3246. SiS_SetRegANDOR(SISPART2, 0x2b, 0xF0, p2_2b);
  3247. SiS_SetRegANDOR(SISPART2, 0x42, 0x0F, p2_42);
  3248. SiS_SetReg(SISPART2, 0x43, p2_43);
  3249. }
  3250. }
  3251. }
  3252. static void
  3253. sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
  3254. {
  3255. if(val > 32) val = 32;
  3256. if(val < -32) val = -32;
  3257. ivideo->tvypos = val;
  3258. if(ivideo->sisfblocked) return;
  3259. if(!ivideo->modechanged) return;
  3260. if(ivideo->currentvbflags & CRT2_TV) {
  3261. if(ivideo->vbflags2 & VB2_CHRONTEL) {
  3262. int y = ivideo->tvy;
  3263. switch(ivideo->chronteltype) {
  3264. case 1:
  3265. y -= val;
  3266. if(y < 0) y = 0;
  3267. SiS_SetReg(SISSR, 0x05, 0x86);
  3268. SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff));
  3269. SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE);
  3270. break;
  3271. case 2:
  3272. /* Not supported by hardware */
  3273. break;
  3274. }
  3275. } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
  3276. char p2_01, p2_02;
  3277. val /= 2;
  3278. p2_01 = ivideo->p2_01;
  3279. p2_02 = ivideo->p2_02;
  3280. p2_01 += val;
  3281. p2_02 += val;
  3282. if(!(ivideo->currentvbflags & (TV_HIVISION | TV_YPBPR))) {
  3283. while((p2_01 <= 0) || (p2_02 <= 0)) {
  3284. p2_01 += 2;
  3285. p2_02 += 2;
  3286. }
  3287. }
  3288. SiS_SetReg(SISPART2, 0x01, p2_01);
  3289. SiS_SetReg(SISPART2, 0x02, p2_02);
  3290. }
  3291. }
  3292. }
  3293. static void
  3294. sisfb_post_setmode(struct sis_video_info *ivideo)
  3295. {
  3296. bool crt1isoff = false;
  3297. bool doit = true;
  3298. #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
  3299. u8 reg;
  3300. #endif
  3301. #ifdef CONFIG_FB_SIS_315
  3302. u8 reg1;
  3303. #endif
  3304. SiS_SetReg(SISSR, 0x05, 0x86);
  3305. #ifdef CONFIG_FB_SIS_315
  3306. sisfb_fixup_SR11(ivideo);
  3307. #endif
  3308. /* Now we actually HAVE changed the display mode */
  3309. ivideo->modechanged = 1;
  3310. /* We can't switch off CRT1 if bridge is in slave mode */
  3311. if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
  3312. if(sisfb_bridgeisslave(ivideo)) doit = false;
  3313. } else
  3314. ivideo->sisfb_crt1off = 0;
  3315. #ifdef CONFIG_FB_SIS_300
  3316. if(ivideo->sisvga_engine == SIS_300_VGA) {
  3317. if((ivideo->sisfb_crt1off) && (doit)) {
  3318. crt1isoff = true;
  3319. reg = 0x00;
  3320. } else {
  3321. crt1isoff = false;
  3322. reg = 0x80;
  3323. }
  3324. SiS_SetRegANDOR(SISCR, 0x17, 0x7f, reg);
  3325. }
  3326. #endif
  3327. #ifdef CONFIG_FB_SIS_315
  3328. if(ivideo->sisvga_engine == SIS_315_VGA) {
  3329. if((ivideo->sisfb_crt1off) && (doit)) {
  3330. crt1isoff = true;
  3331. reg = 0x40;
  3332. reg1 = 0xc0;
  3333. } else {
  3334. crt1isoff = false;
  3335. reg = 0x00;
  3336. reg1 = 0x00;
  3337. }
  3338. SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
  3339. SiS_SetRegANDOR(SISSR, 0x1f, 0x3f, reg1);
  3340. }
  3341. #endif
  3342. if(crt1isoff) {
  3343. ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
  3344. ivideo->currentvbflags |= VB_SINGLE_MODE;
  3345. } else {
  3346. ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
  3347. if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
  3348. ivideo->currentvbflags |= VB_MIRROR_MODE;
  3349. } else {
  3350. ivideo->currentvbflags |= VB_SINGLE_MODE;
  3351. }
  3352. }
  3353. SiS_SetRegAND(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
  3354. if(ivideo->currentvbflags & CRT2_TV) {
  3355. if(ivideo->vbflags2 & VB2_SISBRIDGE) {
  3356. ivideo->p2_1f = SiS_GetReg(SISPART2, 0x1f);
  3357. ivideo->p2_20 = SiS_GetReg(SISPART2, 0x20);
  3358. ivideo->p2_2b = SiS_GetReg(SISPART2, 0x2b);
  3359. ivideo->p2_42 = SiS_GetReg(SISPART2, 0x42);
  3360. ivideo->p2_43 = SiS_GetReg(SISPART2, 0x43);
  3361. ivideo->p2_01 = SiS_GetReg(SISPART2, 0x01);
  3362. ivideo->p2_02 = SiS_GetReg(SISPART2, 0x02);
  3363. } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
  3364. if(ivideo->chronteltype == 1) {
  3365. ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
  3366. ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
  3367. ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
  3368. ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
  3369. }
  3370. }
  3371. }
  3372. if(ivideo->tvxpos) {
  3373. sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
  3374. }
  3375. if(ivideo->tvypos) {
  3376. sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
  3377. }
  3378. /* Eventually sync engines */
  3379. sisfb_check_engine_and_sync(ivideo);
  3380. /* (Re-)Initialize chip engines */
  3381. if(ivideo->accel) {
  3382. sisfb_engine_init(ivideo);
  3383. } else {
  3384. ivideo->engineok = 0;
  3385. }
  3386. }
  3387. static int
  3388. sisfb_reset_mode(struct sis_video_info *ivideo)
  3389. {
  3390. if(sisfb_set_mode(ivideo, 0))
  3391. return 1;
  3392. sisfb_set_pitch(ivideo);
  3393. sisfb_set_base_CRT1(ivideo, ivideo->current_base);
  3394. sisfb_set_base_CRT2(ivideo, ivideo->current_base);
  3395. return 0;
  3396. }
  3397. static void
  3398. sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_command)
  3399. {
  3400. int mycrt1off;
  3401. switch(sisfb_command->sisfb_cmd) {
  3402. case SISFB_CMD_GETVBFLAGS:
  3403. if(!ivideo->modechanged) {
  3404. sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
  3405. } else {
  3406. sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
  3407. sisfb_command->sisfb_result[1] = ivideo->currentvbflags;
  3408. sisfb_command->sisfb_result[2] = ivideo->vbflags2;
  3409. }
  3410. break;
  3411. case SISFB_CMD_SWITCHCRT1:
  3412. /* arg[0]: 0 = off, 1 = on, 99 = query */
  3413. if(!ivideo->modechanged) {
  3414. sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
  3415. } else if(sisfb_command->sisfb_arg[0] == 99) {
  3416. /* Query */
  3417. sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
  3418. sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
  3419. } else if(ivideo->sisfblocked) {
  3420. sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_LOCKED;
  3421. } else if((!(ivideo->currentvbflags & CRT2_ENABLE)) &&
  3422. (sisfb_command->sisfb_arg[0] == 0)) {
  3423. sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_NOCRT2;
  3424. } else {
  3425. sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
  3426. mycrt1off = sisfb_command->sisfb_arg[0] ? 0 : 1;
  3427. if( ((ivideo->currentvbflags & VB_DISPTYPE_CRT1) && mycrt1off) ||
  3428. ((!(ivideo->currentvbflags & VB_DISPTYPE_CRT1)) && !mycrt1off) ) {
  3429. ivideo->sisfb_crt1off = mycrt1off;
  3430. if(sisfb_reset_mode(ivideo)) {
  3431. sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OTHER;
  3432. }
  3433. }
  3434. sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
  3435. }
  3436. break;
  3437. /* more to come */
  3438. default:
  3439. sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_UNKNOWN;
  3440. printk(KERN_ERR "sisfb: Unknown command 0x%x\n",
  3441. sisfb_command->sisfb_cmd);
  3442. }
  3443. }
  3444. #ifndef MODULE
  3445. static int __init sisfb_setup(char *options)
  3446. {
  3447. char *this_opt;
  3448. sisfb_setdefaultparms();
  3449. if(!options || !(*options))
  3450. return 0;
  3451. while((this_opt = strsep(&options, ",")) != NULL) {
  3452. if(!(*this_opt)) continue;
  3453. if(!strnicmp(this_opt, "off", 3)) {
  3454. sisfb_off = 1;
  3455. } else if(!strnicmp(this_opt, "forcecrt2type:", 14)) {
  3456. /* Need to check crt2 type first for fstn/dstn */
  3457. sisfb_search_crt2type(this_opt + 14);
  3458. } else if(!strnicmp(this_opt, "tvmode:",7)) {
  3459. sisfb_search_tvstd(this_opt + 7);
  3460. } else if(!strnicmp(this_opt, "tvstandard:",11)) {
  3461. sisfb_search_tvstd(this_opt + 11);
  3462. } else if(!strnicmp(this_opt, "mode:", 5)) {
  3463. sisfb_search_mode(this_opt + 5, false);
  3464. } else if(!strnicmp(this_opt, "vesa:", 5)) {
  3465. sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), false);
  3466. } else if(!strnicmp(this_opt, "rate:", 5)) {
  3467. sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
  3468. } else if(!strnicmp(this_opt, "forcecrt1:", 10)) {
  3469. sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
  3470. } else if(!strnicmp(this_opt, "mem:",4)) {
  3471. sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
  3472. } else if(!strnicmp(this_opt, "pdc:", 4)) {
  3473. sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
  3474. } else if(!strnicmp(this_opt, "pdc1:", 5)) {
  3475. sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
  3476. } else if(!strnicmp(this_opt, "noaccel", 7)) {
  3477. sisfb_accel = 0;
  3478. } else if(!strnicmp(this_opt, "accel", 5)) {
  3479. sisfb_accel = -1;
  3480. } else if(!strnicmp(this_opt, "noypan", 6)) {
  3481. sisfb_ypan = 0;
  3482. } else if(!strnicmp(this_opt, "ypan", 4)) {
  3483. sisfb_ypan = -1;
  3484. } else if(!strnicmp(this_opt, "nomax", 5)) {
  3485. sisfb_max = 0;
  3486. } else if(!strnicmp(this_opt, "max", 3)) {
  3487. sisfb_max = -1;
  3488. } else if(!strnicmp(this_opt, "userom:", 7)) {
  3489. sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
  3490. } else if(!strnicmp(this_opt, "useoem:", 7)) {
  3491. sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
  3492. } else if(!strnicmp(this_opt, "nocrt2rate", 10)) {
  3493. sisfb_nocrt2rate = 1;
  3494. } else if(!strnicmp(this_opt, "scalelcd:", 9)) {
  3495. unsigned long temp = 2;
  3496. temp = simple_strtoul(this_opt + 9, NULL, 0);
  3497. if((temp == 0) || (temp == 1)) {
  3498. sisfb_scalelcd = temp ^ 1;
  3499. }
  3500. } else if(!strnicmp(this_opt, "tvxposoffset:", 13)) {
  3501. int temp = 0;
  3502. temp = (int)simple_strtol(this_opt + 13, NULL, 0);
  3503. if((temp >= -32) && (temp <= 32)) {
  3504. sisfb_tvxposoffset = temp;
  3505. }
  3506. } else if(!strnicmp(this_opt, "tvyposoffset:", 13)) {
  3507. int temp = 0;
  3508. temp = (int)simple_strtol(this_opt + 13, NULL, 0);
  3509. if((temp >= -32) && (temp <= 32)) {
  3510. sisfb_tvyposoffset = temp;
  3511. }
  3512. } else if(!strnicmp(this_opt, "specialtiming:", 14)) {
  3513. sisfb_search_specialtiming(this_opt + 14);
  3514. } else if(!strnicmp(this_opt, "lvdshl:", 7)) {
  3515. int temp = 4;
  3516. temp = simple_strtoul(this_opt + 7, NULL, 0);
  3517. if((temp >= 0) && (temp <= 3)) {
  3518. sisfb_lvdshl = temp;
  3519. }
  3520. } else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
  3521. sisfb_search_mode(this_opt, true);
  3522. #if !defined(__i386__) && !defined(__x86_64__)
  3523. } else if(!strnicmp(this_opt, "resetcard", 9)) {
  3524. sisfb_resetcard = 1;
  3525. } else if(!strnicmp(this_opt, "videoram:", 9)) {
  3526. sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
  3527. #endif
  3528. } else {
  3529. printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
  3530. }
  3531. }
  3532. return 0;
  3533. }
  3534. #endif
  3535. static int __devinit
  3536. sisfb_check_rom(void __iomem *rom_base, struct sis_video_info *ivideo)
  3537. {
  3538. void __iomem *rom;
  3539. int romptr;
  3540. if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa))
  3541. return 0;
  3542. romptr = (readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
  3543. if(romptr > (0x10000 - 8))
  3544. return 0;
  3545. rom = rom_base + romptr;
  3546. if((readb(rom) != 'P') || (readb(rom + 1) != 'C') ||
  3547. (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R'))
  3548. return 0;
  3549. if((readb(rom + 4) | (readb(rom + 5) << 8)) != ivideo->chip_vendor)
  3550. return 0;
  3551. if((readb(rom + 6) | (readb(rom + 7) << 8)) != ivideo->chip_id)
  3552. return 0;
  3553. return 1;
  3554. }
  3555. static unsigned char * __devinit
  3556. sisfb_find_rom(struct pci_dev *pdev)
  3557. {
  3558. struct sis_video_info *ivideo = pci_get_drvdata(pdev);
  3559. void __iomem *rom_base;
  3560. unsigned char *myrombase = NULL;
  3561. size_t romsize;
  3562. /* First, try the official pci ROM functions (except
  3563. * on integrated chipsets which have no ROM).
  3564. */
  3565. if(!ivideo->nbridge) {
  3566. if((rom_base = pci_map_rom(pdev, &romsize))) {
  3567. if(sisfb_check_rom(rom_base, ivideo)) {
  3568. if((myrombase = vmalloc(65536))) {
  3569. memcpy_fromio(myrombase, rom_base,
  3570. (romsize > 65536) ? 65536 : romsize);
  3571. }
  3572. }
  3573. pci_unmap_rom(pdev, rom_base);
  3574. }
  3575. }
  3576. if(myrombase) return myrombase;
  3577. /* Otherwise do it the conventional way. */
  3578. #if defined(__i386__) || defined(__x86_64__)
  3579. {
  3580. u32 temp;
  3581. for (temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
  3582. rom_base = ioremap(temp, 65536);
  3583. if (!rom_base)
  3584. continue;
  3585. if (!sisfb_check_rom(rom_base, ivideo)) {
  3586. iounmap(rom_base);
  3587. continue;
  3588. }
  3589. if ((myrombase = vmalloc(65536)))
  3590. memcpy_fromio(myrombase, rom_base, 65536);
  3591. iounmap(rom_base);
  3592. break;
  3593. }
  3594. }
  3595. #endif
  3596. return myrombase;
  3597. }
  3598. static void __devinit
  3599. sisfb_post_map_vram(struct sis_video_info *ivideo, unsigned int *mapsize,
  3600. unsigned int min)
  3601. {
  3602. if (*mapsize < (min << 20))
  3603. return;
  3604. ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize));
  3605. if(!ivideo->video_vbase) {
  3606. printk(KERN_ERR
  3607. "sisfb: Unable to map maximum video RAM for size detection\n");
  3608. (*mapsize) >>= 1;
  3609. while((!(ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize))))) {
  3610. (*mapsize) >>= 1;
  3611. if((*mapsize) < (min << 20))
  3612. break;
  3613. }
  3614. if(ivideo->video_vbase) {
  3615. printk(KERN_ERR
  3616. "sisfb: Video RAM size detection limited to %dMB\n",
  3617. (int)((*mapsize) >> 20));
  3618. }
  3619. }
  3620. }
  3621. #ifdef CONFIG_FB_SIS_300
  3622. static int __devinit
  3623. sisfb_post_300_buswidth(struct sis_video_info *ivideo)
  3624. {
  3625. void __iomem *FBAddress = ivideo->video_vbase;
  3626. unsigned short temp;
  3627. unsigned char reg;
  3628. int i, j;
  3629. SiS_SetRegAND(SISSR, 0x15, 0xFB);
  3630. SiS_SetRegOR(SISSR, 0x15, 0x04);
  3631. SiS_SetReg(SISSR, 0x13, 0x00);
  3632. SiS_SetReg(SISSR, 0x14, 0xBF);
  3633. for(i = 0; i < 2; i++) {
  3634. temp = 0x1234;
  3635. for(j = 0; j < 4; j++) {
  3636. writew(temp, FBAddress);
  3637. if(readw(FBAddress) == temp)
  3638. break;
  3639. SiS_SetRegOR(SISSR, 0x3c, 0x01);
  3640. reg = SiS_GetReg(SISSR, 0x05);
  3641. reg = SiS_GetReg(SISSR, 0x05);
  3642. SiS_SetRegAND(SISSR, 0x3c, 0xfe);
  3643. reg = SiS_GetReg(SISSR, 0x05);
  3644. reg = SiS_GetReg(SISSR, 0x05);
  3645. temp++;
  3646. }
  3647. }
  3648. writel(0x01234567L, FBAddress);
  3649. writel(0x456789ABL, (FBAddress + 4));
  3650. writel(0x89ABCDEFL, (FBAddress + 8));
  3651. writel(0xCDEF0123L, (FBAddress + 12));
  3652. reg = SiS_GetReg(SISSR, 0x3b);
  3653. if(reg & 0x01) {
  3654. if(readl((FBAddress + 12)) == 0xCDEF0123L)
  3655. return 4; /* Channel A 128bit */
  3656. }
  3657. if(readl((FBAddress + 4)) == 0x456789ABL)
  3658. return 2; /* Channel B 64bit */
  3659. return 1; /* 32bit */
  3660. }
  3661. static int __devinit
  3662. sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth,
  3663. int PseudoRankCapacity, int PseudoAdrPinCount,
  3664. unsigned int mapsize)
  3665. {
  3666. void __iomem *FBAddr = ivideo->video_vbase;
  3667. unsigned short sr14;
  3668. unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
  3669. unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
  3670. static const unsigned short SiS_DRAMType[17][5] = {
  3671. {0x0C,0x0A,0x02,0x40,0x39},
  3672. {0x0D,0x0A,0x01,0x40,0x48},
  3673. {0x0C,0x09,0x02,0x20,0x35},
  3674. {0x0D,0x09,0x01,0x20,0x44},
  3675. {0x0C,0x08,0x02,0x10,0x31},
  3676. {0x0D,0x08,0x01,0x10,0x40},
  3677. {0x0C,0x0A,0x01,0x20,0x34},
  3678. {0x0C,0x09,0x01,0x08,0x32},
  3679. {0x0B,0x08,0x02,0x08,0x21},
  3680. {0x0C,0x08,0x01,0x08,0x30},
  3681. {0x0A,0x08,0x02,0x04,0x11},
  3682. {0x0B,0x0A,0x01,0x10,0x28},
  3683. {0x09,0x08,0x02,0x02,0x01},
  3684. {0x0B,0x09,0x01,0x08,0x24},
  3685. {0x0B,0x08,0x01,0x04,0x20},
  3686. {0x0A,0x08,0x01,0x02,0x10},
  3687. {0x09,0x08,0x01,0x01,0x00}
  3688. };
  3689. for(k = 0; k <= 16; k++) {
  3690. RankCapacity = buswidth * SiS_DRAMType[k][3];
  3691. if(RankCapacity != PseudoRankCapacity)
  3692. continue;
  3693. if((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount)
  3694. continue;
  3695. BankNumHigh = RankCapacity * 16 * iteration - 1;
  3696. if(iteration == 3) { /* Rank No */
  3697. BankNumMid = RankCapacity * 16 - 1;
  3698. } else {
  3699. BankNumMid = RankCapacity * 16 * iteration / 2 - 1;
  3700. }
  3701. PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
  3702. PhysicalAdrHigh = BankNumHigh;
  3703. PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
  3704. PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
  3705. SiS_SetRegAND(SISSR, 0x15, 0xFB); /* Test */
  3706. SiS_SetRegOR(SISSR, 0x15, 0x04); /* Test */
  3707. sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
  3708. if(buswidth == 4) sr14 |= 0x80;
  3709. else if(buswidth == 2) sr14 |= 0x40;
  3710. SiS_SetReg(SISSR, 0x13, SiS_DRAMType[k][4]);
  3711. SiS_SetReg(SISSR, 0x14, sr14);
  3712. BankNumHigh <<= 16;
  3713. BankNumMid <<= 16;
  3714. if((BankNumHigh + PhysicalAdrHigh >= mapsize) ||
  3715. (BankNumMid + PhysicalAdrHigh >= mapsize) ||
  3716. (BankNumHigh + PhysicalAdrHalfPage >= mapsize) ||
  3717. (BankNumHigh + PhysicalAdrOtherPage >= mapsize))
  3718. continue;
  3719. /* Write data */
  3720. writew(((unsigned short)PhysicalAdrHigh),
  3721. (FBAddr + BankNumHigh + PhysicalAdrHigh));
  3722. writew(((unsigned short)BankNumMid),
  3723. (FBAddr + BankNumMid + PhysicalAdrHigh));
  3724. writew(((unsigned short)PhysicalAdrHalfPage),
  3725. (FBAddr + BankNumHigh + PhysicalAdrHalfPage));
  3726. writew(((unsigned short)PhysicalAdrOtherPage),
  3727. (FBAddr + BankNumHigh + PhysicalAdrOtherPage));
  3728. /* Read data */
  3729. if(readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh)
  3730. return 1;
  3731. }
  3732. return 0;
  3733. }
  3734. static void __devinit
  3735. sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize)
  3736. {
  3737. struct sis_video_info *ivideo = pci_get_drvdata(pdev);
  3738. int i, j, buswidth;
  3739. int PseudoRankCapacity, PseudoAdrPinCount;
  3740. buswidth = sisfb_post_300_buswidth(ivideo);
  3741. for(i = 6; i >= 0; i--) {
  3742. PseudoRankCapacity = 1 << i;
  3743. for(j = 4; j >= 1; j--) {
  3744. PseudoAdrPinCount = 15 - j;
  3745. if((PseudoRankCapacity * j) <= 64) {
  3746. if(sisfb_post_300_rwtest(ivideo,
  3747. j,
  3748. buswidth,
  3749. PseudoRankCapacity,
  3750. PseudoAdrPinCount,
  3751. mapsize))
  3752. return;
  3753. }
  3754. }
  3755. }
  3756. }
  3757. static void __devinit
  3758. sisfb_post_sis300(struct pci_dev *pdev)
  3759. {
  3760. struct sis_video_info *ivideo = pci_get_drvdata(pdev);
  3761. unsigned char *bios = ivideo->SiS_Pr.VirtualRomBase;
  3762. u8 reg, v1, v2, v3, v4, v5, v6, v7, v8;
  3763. u16 index, rindex, memtype = 0;
  3764. unsigned int mapsize;
  3765. if(!ivideo->SiS_Pr.UseROM)
  3766. bios = NULL;
  3767. SiS_SetReg(SISSR, 0x05, 0x86);
  3768. if(bios) {
  3769. if(bios[0x52] & 0x80) {
  3770. memtype = bios[0x52];
  3771. } else {
  3772. memtype = SiS_GetReg(SISSR, 0x3a);
  3773. }
  3774. memtype &= 0x07;
  3775. }
  3776. v3 = 0x80; v6 = 0x80;
  3777. if(ivideo->revision_id <= 0x13) {
  3778. v1 = 0x44; v2 = 0x42;
  3779. v4 = 0x44; v5 = 0x42;
  3780. } else {
  3781. v1 = 0x68; v2 = 0x43; /* Assume 125Mhz MCLK */
  3782. v4 = 0x68; v5 = 0x43; /* Assume 125Mhz ECLK */
  3783. if(bios) {
  3784. index = memtype * 5;
  3785. rindex = index + 0x54;
  3786. v1 = bios[rindex++];
  3787. v2 = bios[rindex++];
  3788. v3 = bios[rindex++];
  3789. rindex = index + 0x7c;
  3790. v4 = bios[rindex++];
  3791. v5 = bios[rindex++];
  3792. v6 = bios[rindex++];
  3793. }
  3794. }
  3795. SiS_SetReg(SISSR, 0x28, v1);
  3796. SiS_SetReg(SISSR, 0x29, v2);
  3797. SiS_SetReg(SISSR, 0x2a, v3);
  3798. SiS_SetReg(SISSR, 0x2e, v4);
  3799. SiS_SetReg(SISSR, 0x2f, v5);
  3800. SiS_SetReg(SISSR, 0x30, v6);
  3801. v1 = 0x10;
  3802. if(bios)
  3803. v1 = bios[0xa4];
  3804. SiS_SetReg(SISSR, 0x07, v1); /* DAC speed */
  3805. SiS_SetReg(SISSR, 0x11, 0x0f); /* DDC, power save */
  3806. v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
  3807. v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
  3808. if(bios) {
  3809. memtype += 0xa5;
  3810. v1 = bios[memtype];
  3811. v2 = bios[memtype + 8];
  3812. v3 = bios[memtype + 16];
  3813. v4 = bios[memtype + 24];
  3814. v5 = bios[memtype + 32];
  3815. v6 = bios[memtype + 40];
  3816. v7 = bios[memtype + 48];
  3817. v8 = bios[memtype + 56];
  3818. }
  3819. if(ivideo->revision_id >= 0x80)
  3820. v3 &= 0xfd;
  3821. SiS_SetReg(SISSR, 0x15, v1); /* Ram type (assuming 0, BIOS 0xa5 step 8) */
  3822. SiS_SetReg(SISSR, 0x16, v2);
  3823. SiS_SetReg(SISSR, 0x17, v3);
  3824. SiS_SetReg(SISSR, 0x18, v4);
  3825. SiS_SetReg(SISSR, 0x19, v5);
  3826. SiS_SetReg(SISSR, 0x1a, v6);
  3827. SiS_SetReg(SISSR, 0x1b, v7);
  3828. SiS_SetReg(SISSR, 0x1c, v8); /* ---- */
  3829. SiS_SetRegAND(SISSR, 0x15, 0xfb);
  3830. SiS_SetRegOR(SISSR, 0x15, 0x04);
  3831. if(bios) {
  3832. if(bios[0x53] & 0x02) {
  3833. SiS_SetRegOR(SISSR, 0x19, 0x20);
  3834. }
  3835. }
  3836. v1 = 0x04; /* DAC pedestal (BIOS 0xe5) */
  3837. if(ivideo->revision_id >= 0x80)
  3838. v1 |= 0x01;
  3839. SiS_SetReg(SISSR, 0x1f, v1);
  3840. SiS_SetReg(SISSR, 0x20, 0xa4); /* linear & relocated io & disable a0000 */
  3841. v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
  3842. if(bios) {
  3843. v1 = bios[0xe8];
  3844. v2 = bios[0xe9];
  3845. v3 = bios[0xea];
  3846. }
  3847. SiS_SetReg(SISSR, 0x23, v1);
  3848. SiS_SetReg(SISSR, 0x24, v2);
  3849. SiS_SetReg(SISSR, 0x25, v3);
  3850. SiS_SetReg(SISSR, 0x21, 0x84);
  3851. SiS_SetReg(SISSR, 0x22, 0x00);
  3852. SiS_SetReg(SISCR, 0x37, 0x00);
  3853. SiS_SetRegOR(SISPART1, 0x24, 0x01); /* unlock crt2 */
  3854. SiS_SetReg(SISPART1, 0x00, 0x00);
  3855. v1 = 0x40; v2 = 0x11;
  3856. if(bios) {
  3857. v1 = bios[0xec];
  3858. v2 = bios[0xeb];
  3859. }
  3860. SiS_SetReg(SISPART1, 0x02, v1);
  3861. if(ivideo->revision_id >= 0x80)
  3862. v2 &= ~0x01;
  3863. reg = SiS_GetReg(SISPART4, 0x00);
  3864. if((reg == 1) || (reg == 2)) {
  3865. SiS_SetReg(SISCR, 0x37, 0x02);
  3866. SiS_SetReg(SISPART2, 0x00, 0x1c);
  3867. v4 = 0x00; v5 = 0x00; v6 = 0x10;
  3868. if(ivideo->SiS_Pr.UseROM) {
  3869. v4 = bios[0xf5];
  3870. v5 = bios[0xf6];
  3871. v6 = bios[0xf7];
  3872. }
  3873. SiS_SetReg(SISPART4, 0x0d, v4);
  3874. SiS_SetReg(SISPART4, 0x0e, v5);
  3875. SiS_SetReg(SISPART4, 0x10, v6);
  3876. SiS_SetReg(SISPART4, 0x0f, 0x3f);
  3877. reg = SiS_GetReg(SISPART4, 0x01);
  3878. if(reg >= 0xb0) {
  3879. reg = SiS_GetReg(SISPART4, 0x23);
  3880. reg &= 0x20;
  3881. reg <<= 1;
  3882. SiS_SetReg(SISPART4, 0x23, reg);
  3883. }
  3884. } else {
  3885. v2 &= ~0x10;
  3886. }
  3887. SiS_SetReg(SISSR, 0x32, v2);
  3888. SiS_SetRegAND(SISPART1, 0x24, 0xfe); /* Lock CRT2 */
  3889. reg = SiS_GetReg(SISSR, 0x16);
  3890. reg &= 0xc3;
  3891. SiS_SetReg(SISCR, 0x35, reg);
  3892. SiS_SetReg(SISCR, 0x83, 0x00);
  3893. #if !defined(__i386__) && !defined(__x86_64__)
  3894. if(sisfb_videoram) {
  3895. SiS_SetReg(SISSR, 0x13, 0x28); /* ? */
  3896. reg = ((sisfb_videoram >> 10) - 1) | 0x40;
  3897. SiS_SetReg(SISSR, 0x14, reg);
  3898. } else {
  3899. #endif
  3900. /* Need to map max FB size for finding out about RAM size */
  3901. mapsize = ivideo->video_size;
  3902. sisfb_post_map_vram(ivideo, &mapsize, 4);
  3903. if(ivideo->video_vbase) {
  3904. sisfb_post_300_ramsize(pdev, mapsize);
  3905. iounmap(ivideo->video_vbase);
  3906. } else {
  3907. printk(KERN_DEBUG
  3908. "sisfb: Failed to map memory for size detection, assuming 8MB\n");
  3909. SiS_SetReg(SISSR, 0x13, 0x28); /* ? */
  3910. SiS_SetReg(SISSR, 0x14, 0x47); /* 8MB, 64bit default */
  3911. }
  3912. #if !defined(__i386__) && !defined(__x86_64__)
  3913. }
  3914. #endif
  3915. if(bios) {
  3916. v1 = bios[0xe6];
  3917. v2 = bios[0xe7];
  3918. } else {
  3919. reg = SiS_GetReg(SISSR, 0x3a);
  3920. if((reg & 0x30) == 0x30) {
  3921. v1 = 0x04; /* PCI */
  3922. v2 = 0x92;
  3923. } else {
  3924. v1 = 0x14; /* AGP */
  3925. v2 = 0xb2;
  3926. }
  3927. }
  3928. SiS_SetReg(SISSR, 0x21, v1);
  3929. SiS_SetReg(SISSR, 0x22, v2);
  3930. /* Sense CRT1 */
  3931. sisfb_sense_crt1(ivideo);
  3932. /* Set default mode, don't clear screen */
  3933. ivideo->SiS_Pr.SiS_UseOEM = false;
  3934. SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
  3935. SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
  3936. ivideo->curFSTN = ivideo->curDSTN = 0;
  3937. ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
  3938. SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
  3939. SiS_SetReg(SISSR, 0x05, 0x86);
  3940. /* Display off */
  3941. SiS_SetRegOR(SISSR, 0x01, 0x20);
  3942. /* Save mode number in CR34 */
  3943. SiS_SetReg(SISCR, 0x34, 0x2e);
  3944. /* Let everyone know what the current mode is */
  3945. ivideo->modeprechange = 0x2e;
  3946. }
  3947. #endif
  3948. #ifdef CONFIG_FB_SIS_315
  3949. #if 0
  3950. static void __devinit
  3951. sisfb_post_sis315330(struct pci_dev *pdev)
  3952. {
  3953. /* TODO */
  3954. }
  3955. #endif
  3956. static inline int sisfb_xgi_is21(struct sis_video_info *ivideo)
  3957. {
  3958. return ivideo->chip_real_id == XGI_21;
  3959. }
  3960. static void __devinit
  3961. sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
  3962. {
  3963. unsigned int i;
  3964. u8 reg;
  3965. for(i = 0; i <= (delay * 10 * 36); i++) {
  3966. reg = SiS_GetReg(SISSR, 0x05);
  3967. reg++;
  3968. }
  3969. }
  3970. static int __devinit
  3971. sisfb_find_host_bridge(struct sis_video_info *ivideo, struct pci_dev *mypdev,
  3972. unsigned short pcivendor)
  3973. {
  3974. struct pci_dev *pdev = NULL;
  3975. unsigned short temp;
  3976. int ret = 0;
  3977. while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, pdev))) {
  3978. temp = pdev->vendor;
  3979. if(temp == pcivendor) {
  3980. ret = 1;
  3981. pci_dev_put(pdev);
  3982. break;
  3983. }
  3984. }
  3985. return ret;
  3986. }
  3987. static int __devinit
  3988. sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta,
  3989. unsigned int enda, unsigned int mapsize)
  3990. {
  3991. unsigned int pos;
  3992. int i;
  3993. writel(0, ivideo->video_vbase);
  3994. for(i = starta; i <= enda; i++) {
  3995. pos = 1 << i;
  3996. if(pos < mapsize)
  3997. writel(pos, ivideo->video_vbase + pos);
  3998. }
  3999. sisfb_post_xgi_delay(ivideo, 150);
  4000. if(readl(ivideo->video_vbase) != 0)
  4001. return 0;
  4002. for(i = starta; i <= enda; i++) {
  4003. pos = 1 << i;
  4004. if(pos < mapsize) {
  4005. if(readl(ivideo->video_vbase + pos) != pos)
  4006. return 0;
  4007. } else
  4008. return 0;
  4009. }
  4010. return 1;
  4011. }
  4012. static int __devinit
  4013. sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
  4014. {
  4015. unsigned int buswidth, ranksize, channelab, mapsize;
  4016. int i, j, k, l, status;
  4017. u8 reg, sr14;
  4018. static const u8 dramsr13[12 * 5] = {
  4019. 0x02, 0x0e, 0x0b, 0x80, 0x5d,
  4020. 0x02, 0x0e, 0x0a, 0x40, 0x59,
  4021. 0x02, 0x0d, 0x0b, 0x40, 0x4d,
  4022. 0x02, 0x0e, 0x09, 0x20, 0x55,
  4023. 0x02, 0x0d, 0x0a, 0x20, 0x49,
  4024. 0x02, 0x0c, 0x0b, 0x20, 0x3d,
  4025. 0x02, 0x0e, 0x08, 0x10, 0x51,
  4026. 0x02, 0x0d, 0x09, 0x10, 0x45,
  4027. 0x02, 0x0c, 0x0a, 0x10, 0x39,
  4028. 0x02, 0x0d, 0x08, 0x08, 0x41,
  4029. 0x02, 0x0c, 0x09, 0x08, 0x35,
  4030. 0x02, 0x0c, 0x08, 0x04, 0x31
  4031. };
  4032. static const u8 dramsr13_4[4 * 5] = {
  4033. 0x02, 0x0d, 0x09, 0x40, 0x45,
  4034. 0x02, 0x0c, 0x09, 0x20, 0x35,
  4035. 0x02, 0x0c, 0x08, 0x10, 0x31,
  4036. 0x02, 0x0b, 0x08, 0x08, 0x21
  4037. };
  4038. /* Enable linear mode, disable 0xa0000 address decoding */
  4039. /* We disable a0000 address decoding, because
  4040. * - if running on x86, if the card is disabled, it means
  4041. * that another card is in the system. We don't want
  4042. * to interphere with that primary card's textmode.
  4043. * - if running on non-x86, there usually is no VGA window
  4044. * at a0000.
  4045. */
  4046. SiS_SetRegOR(SISSR, 0x20, (0x80 | 0x04));
  4047. /* Need to map max FB size for finding out about RAM size */
  4048. mapsize = ivideo->video_size;
  4049. sisfb_post_map_vram(ivideo, &mapsize, 32);
  4050. if(!ivideo->video_vbase) {
  4051. printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n");
  4052. SiS_SetReg(SISSR, 0x13, 0x35);
  4053. SiS_SetReg(SISSR, 0x14, 0x41);
  4054. /* TODO */
  4055. return -ENOMEM;
  4056. }
  4057. /* Non-interleaving */
  4058. SiS_SetReg(SISSR, 0x15, 0x00);
  4059. /* No tiling */
  4060. SiS_SetReg(SISSR, 0x1c, 0x00);
  4061. if(ivideo->chip == XGI_20) {
  4062. channelab = 1;
  4063. reg = SiS_GetReg(SISCR, 0x97);
  4064. if(!(reg & 0x01)) { /* Single 32/16 */
  4065. buswidth = 32;
  4066. SiS_SetReg(SISSR, 0x13, 0xb1);
  4067. SiS_SetReg(SISSR, 0x14, 0x52);
  4068. sisfb_post_xgi_delay(ivideo, 1);
  4069. sr14 = 0x02;
  4070. if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
  4071. goto bail_out;
  4072. SiS_SetReg(SISSR, 0x13, 0x31);
  4073. SiS_SetReg(SISSR, 0x14, 0x42);
  4074. sisfb_post_xgi_delay(ivideo, 1);
  4075. if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize))
  4076. goto bail_out;
  4077. buswidth = 16;
  4078. SiS_SetReg(SISSR, 0x13, 0xb1);
  4079. SiS_SetReg(SISSR, 0x14, 0x41);
  4080. sisfb_post_xgi_delay(ivideo, 1);
  4081. sr14 = 0x01;
  4082. if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
  4083. goto bail_out;
  4084. else
  4085. SiS_SetReg(SISSR, 0x13, 0x31);
  4086. } else { /* Dual 16/8 */
  4087. buswidth = 16;
  4088. SiS_SetReg(SISSR, 0x13, 0xb1);
  4089. SiS_SetReg(SISSR, 0x14, 0x41);
  4090. sisfb_post_xgi_delay(ivideo, 1);
  4091. sr14 = 0x01;
  4092. if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
  4093. goto bail_out;
  4094. SiS_SetReg(SISSR, 0x13, 0x31);
  4095. SiS_SetReg(SISSR, 0x14, 0x31);
  4096. sisfb_post_xgi_delay(ivideo, 1);
  4097. if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize))
  4098. goto bail_out;
  4099. buswidth = 8;
  4100. SiS_SetReg(SISSR, 0x13, 0xb1);
  4101. SiS_SetReg(SISSR, 0x14, 0x30);
  4102. sisfb_post_xgi_delay(ivideo, 1);
  4103. sr14 = 0x00;
  4104. if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize))
  4105. goto bail_out;
  4106. else
  4107. SiS_SetReg(SISSR, 0x13, 0x31);
  4108. }
  4109. } else { /* XGI_40 */
  4110. reg = SiS_GetReg(SISCR, 0x97);
  4111. if(!(reg & 0x10)) {
  4112. reg = SiS_GetReg(SISSR, 0x39);
  4113. reg >>= 1;
  4114. }
  4115. if(reg & 0x01) { /* DDRII */
  4116. buswidth = 32;
  4117. if(ivideo->revision_id == 2) {
  4118. channelab = 2;
  4119. SiS_SetReg(SISSR, 0x13, 0xa1);
  4120. SiS_SetReg(SISSR, 0x14, 0x44);
  4121. sr14 = 0x04;
  4122. sisfb_post_xgi_delay(ivideo, 1);
  4123. if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
  4124. goto bail_out;
  4125. SiS_SetReg(SISSR, 0x13, 0x21);
  4126. SiS_SetReg(SISSR, 0x14, 0x34);
  4127. if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
  4128. goto bail_out;
  4129. channelab = 1;
  4130. SiS_SetReg(SISSR, 0x13, 0xa1);
  4131. SiS_SetReg(SISSR, 0x14, 0x40);
  4132. sr14 = 0x00;
  4133. if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
  4134. goto bail_out;
  4135. SiS_SetReg(SISSR, 0x13, 0x21);
  4136. SiS_SetReg(SISSR, 0x14, 0x30);
  4137. } else {
  4138. channelab = 3;
  4139. SiS_SetReg(SISSR, 0x13, 0xa1);
  4140. SiS_SetReg(SISSR, 0x14, 0x4c);
  4141. sr14 = 0x0c;
  4142. sisfb_post_xgi_delay(ivideo, 1);
  4143. if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize))
  4144. goto bail_out;
  4145. channelab = 2;
  4146. SiS_SetReg(SISSR, 0x14, 0x48);
  4147. sisfb_post_xgi_delay(ivideo, 1);
  4148. sr14 = 0x08;
  4149. if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
  4150. goto bail_out;
  4151. SiS_SetReg(SISSR, 0x13, 0x21);
  4152. SiS_SetReg(SISSR, 0x14, 0x3c);
  4153. sr14 = 0x0c;
  4154. if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) {
  4155. channelab = 3;
  4156. } else {
  4157. channelab = 2;
  4158. SiS_SetReg(SISSR, 0x14, 0x38);
  4159. sr14 = 0x08;
  4160. }
  4161. }
  4162. sisfb_post_xgi_delay(ivideo, 1);
  4163. } else { /* DDR */
  4164. buswidth = 64;
  4165. if(ivideo->revision_id == 2) {
  4166. channelab = 1;
  4167. SiS_SetReg(SISSR, 0x13, 0xa1);
  4168. SiS_SetReg(SISSR, 0x14, 0x52);
  4169. sisfb_post_xgi_delay(ivideo, 1);
  4170. sr14 = 0x02;
  4171. if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
  4172. goto bail_out;
  4173. SiS_SetReg(SISSR, 0x13, 0x21);
  4174. SiS_SetReg(SISSR, 0x14, 0x42);
  4175. } else {
  4176. channelab = 2;
  4177. SiS_SetReg(SISSR, 0x13, 0xa1);
  4178. SiS_SetReg(SISSR, 0x14, 0x5a);
  4179. sisfb_post_xgi_delay(ivideo, 1);
  4180. sr14 = 0x0a;
  4181. if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize))
  4182. goto bail_out;
  4183. SiS_SetReg(SISSR, 0x13, 0x21);
  4184. SiS_SetReg(SISSR, 0x14, 0x4a);
  4185. }
  4186. sisfb_post_xgi_delay(ivideo, 1);
  4187. }
  4188. }
  4189. bail_out:
  4190. SiS_SetRegANDOR(SISSR, 0x14, 0xf0, sr14);
  4191. sisfb_post_xgi_delay(ivideo, 1);
  4192. j = (ivideo->chip == XGI_20) ? 5 : 9;
  4193. k = (ivideo->chip == XGI_20) ? 12 : 4;
  4194. status = -EIO;
  4195. for(i = 0; i < k; i++) {
  4196. reg = (ivideo->chip == XGI_20) ?
  4197. dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4];
  4198. SiS_SetRegANDOR(SISSR, 0x13, 0x80, reg);
  4199. sisfb_post_xgi_delay(ivideo, 50);
  4200. ranksize = (ivideo->chip == XGI_20) ?
  4201. dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3];
  4202. reg = SiS_GetReg(SISSR, 0x13);
  4203. if(reg & 0x80) ranksize <<= 1;
  4204. if(ivideo->chip == XGI_20) {
  4205. if(buswidth == 16) ranksize <<= 1;
  4206. else if(buswidth == 32) ranksize <<= 2;
  4207. } else {
  4208. if(buswidth == 64) ranksize <<= 1;
  4209. }
  4210. reg = 0;
  4211. l = channelab;
  4212. if(l == 3) l = 4;
  4213. if((ranksize * l) <= 256) {
  4214. while((ranksize >>= 1)) reg += 0x10;
  4215. }
  4216. if(!reg) continue;
  4217. SiS_SetRegANDOR(SISSR, 0x14, 0x0f, (reg & 0xf0));
  4218. sisfb_post_xgi_delay(ivideo, 1);
  4219. if (sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize)) {
  4220. status = 0;
  4221. break;
  4222. }
  4223. }
  4224. iounmap(ivideo->video_vbase);
  4225. return status;
  4226. }
  4227. static void __devinit
  4228. sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
  4229. {
  4230. u8 v1, v2, v3;
  4231. int index;
  4232. static const u8 cs90[8 * 3] = {
  4233. 0x16, 0x01, 0x01,
  4234. 0x3e, 0x03, 0x01,
  4235. 0x7c, 0x08, 0x01,
  4236. 0x79, 0x06, 0x01,
  4237. 0x29, 0x01, 0x81,
  4238. 0x5c, 0x23, 0x01,
  4239. 0x5c, 0x23, 0x01,
  4240. 0x5c, 0x23, 0x01
  4241. };
  4242. static const u8 csb8[8 * 3] = {
  4243. 0x5c, 0x23, 0x01,
  4244. 0x29, 0x01, 0x01,
  4245. 0x7c, 0x08, 0x01,
  4246. 0x79, 0x06, 0x01,
  4247. 0x29, 0x01, 0x81,
  4248. 0x5c, 0x23, 0x01,
  4249. 0x5c, 0x23, 0x01,
  4250. 0x5c, 0x23, 0x01
  4251. };
  4252. regb = 0; /* ! */
  4253. index = regb * 3;
  4254. v1 = cs90[index]; v2 = cs90[index + 1]; v3 = cs90[index + 2];
  4255. if(ivideo->haveXGIROM) {
  4256. v1 = ivideo->bios_abase[0x90 + index];
  4257. v2 = ivideo->bios_abase[0x90 + index + 1];
  4258. v3 = ivideo->bios_abase[0x90 + index + 2];
  4259. }
  4260. SiS_SetReg(SISSR, 0x28, v1);
  4261. SiS_SetReg(SISSR, 0x29, v2);
  4262. SiS_SetReg(SISSR, 0x2a, v3);
  4263. sisfb_post_xgi_delay(ivideo, 0x43);
  4264. sisfb_post_xgi_delay(ivideo, 0x43);
  4265. sisfb_post_xgi_delay(ivideo, 0x43);
  4266. index = regb * 3;
  4267. v1 = csb8[index]; v2 = csb8[index + 1]; v3 = csb8[index + 2];
  4268. if(ivideo->haveXGIROM) {
  4269. v1 = ivideo->bios_abase[0xb8 + index];
  4270. v2 = ivideo->bios_abase[0xb8 + index + 1];
  4271. v3 = ivideo->bios_abase[0xb8 + index + 2];
  4272. }
  4273. SiS_SetReg(SISSR, 0x2e, v1);
  4274. SiS_SetReg(SISSR, 0x2f, v2);
  4275. SiS_SetReg(SISSR, 0x30, v3);
  4276. sisfb_post_xgi_delay(ivideo, 0x43);
  4277. sisfb_post_xgi_delay(ivideo, 0x43);
  4278. sisfb_post_xgi_delay(ivideo, 0x43);
  4279. }
  4280. static void __devinit
  4281. sisfb_post_xgi_ddr2_mrs_default(struct sis_video_info *ivideo, u8 regb)
  4282. {
  4283. unsigned char *bios = ivideo->bios_abase;
  4284. u8 v1;
  4285. SiS_SetReg(SISSR, 0x28, 0x64);
  4286. SiS_SetReg(SISSR, 0x29, 0x63);
  4287. sisfb_post_xgi_delay(ivideo, 15);
  4288. SiS_SetReg(SISSR, 0x18, 0x00);
  4289. SiS_SetReg(SISSR, 0x19, 0x20);
  4290. SiS_SetReg(SISSR, 0x16, 0x00);
  4291. SiS_SetReg(SISSR, 0x16, 0x80);
  4292. SiS_SetReg(SISSR, 0x18, 0xc5);
  4293. SiS_SetReg(SISSR, 0x19, 0x23);
  4294. SiS_SetReg(SISSR, 0x16, 0x00);
  4295. SiS_SetReg(SISSR, 0x16, 0x80);
  4296. sisfb_post_xgi_delay(ivideo, 1);
  4297. SiS_SetReg(SISCR, 0x97, 0x11);
  4298. sisfb_post_xgi_setclocks(ivideo, regb);
  4299. sisfb_post_xgi_delay(ivideo, 0x46);
  4300. SiS_SetReg(SISSR, 0x18, 0xc5);
  4301. SiS_SetReg(SISSR, 0x19, 0x23);
  4302. SiS_SetReg(SISSR, 0x16, 0x00);
  4303. SiS_SetReg(SISSR, 0x16, 0x80);
  4304. sisfb_post_xgi_delay(ivideo, 1);
  4305. SiS_SetReg(SISSR, 0x1b, 0x04);
  4306. sisfb_post_xgi_delay(ivideo, 1);
  4307. SiS_SetReg(SISSR, 0x1b, 0x00);
  4308. sisfb_post_xgi_delay(ivideo, 1);
  4309. v1 = 0x31;
  4310. if (ivideo->haveXGIROM) {
  4311. v1 = bios[0xf0];
  4312. }
  4313. SiS_SetReg(SISSR, 0x18, v1);
  4314. SiS_SetReg(SISSR, 0x19, 0x06);
  4315. SiS_SetReg(SISSR, 0x16, 0x04);
  4316. SiS_SetReg(SISSR, 0x16, 0x84);
  4317. sisfb_post_xgi_delay(ivideo, 1);
  4318. }
  4319. static void __devinit
  4320. sisfb_post_xgi_ddr2_mrs_xg21(struct sis_video_info *ivideo)
  4321. {
  4322. sisfb_post_xgi_setclocks(ivideo, 1);
  4323. SiS_SetReg(SISCR, 0x97, 0x11);
  4324. sisfb_post_xgi_delay(ivideo, 0x46);
  4325. SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS2 */
  4326. SiS_SetReg(SISSR, 0x19, 0x80);
  4327. SiS_SetReg(SISSR, 0x16, 0x05);
  4328. SiS_SetReg(SISSR, 0x16, 0x85);
  4329. SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS3 */
  4330. SiS_SetReg(SISSR, 0x19, 0xc0);
  4331. SiS_SetReg(SISSR, 0x16, 0x05);
  4332. SiS_SetReg(SISSR, 0x16, 0x85);
  4333. SiS_SetReg(SISSR, 0x18, 0x00); /* EMRS1 */
  4334. SiS_SetReg(SISSR, 0x19, 0x40);
  4335. SiS_SetReg(SISSR, 0x16, 0x05);
  4336. SiS_SetReg(SISSR, 0x16, 0x85);
  4337. SiS_SetReg(SISSR, 0x18, 0x42); /* MRS1 */
  4338. SiS_SetReg(SISSR, 0x19, 0x02);
  4339. SiS_SetReg(SISSR, 0x16, 0x05);
  4340. SiS_SetReg(SISSR, 0x16, 0x85);
  4341. sisfb_post_xgi_delay(ivideo, 1);
  4342. SiS_SetReg(SISSR, 0x1b, 0x04);
  4343. sisfb_post_xgi_delay(ivideo, 1);
  4344. SiS_SetReg(SISSR, 0x1b, 0x00);
  4345. sisfb_post_xgi_delay(ivideo, 1);
  4346. SiS_SetReg(SISSR, 0x18, 0x42); /* MRS1 */
  4347. SiS_SetReg(SISSR, 0x19, 0x00);
  4348. SiS_SetReg(SISSR, 0x16, 0x05);
  4349. SiS_SetReg(SISSR, 0x16, 0x85);
  4350. sisfb_post_xgi_delay(ivideo, 1);
  4351. }
  4352. static void __devinit
  4353. sisfb_post_xgi_ddr2(struct sis_video_info *ivideo, u8 regb)
  4354. {
  4355. unsigned char *bios = ivideo->bios_abase;
  4356. static const u8 cs158[8] = {
  4357. 0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
  4358. };
  4359. static const u8 cs160[8] = {
  4360. 0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
  4361. };
  4362. static const u8 cs168[8] = {
  4363. 0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
  4364. };
  4365. u8 reg;
  4366. u8 v1;
  4367. u8 v2;
  4368. u8 v3;
  4369. SiS_SetReg(SISCR, 0xb0, 0x80); /* DDR2 dual frequency mode */
  4370. SiS_SetReg(SISCR, 0x82, 0x77);
  4371. SiS_SetReg(SISCR, 0x86, 0x00);
  4372. reg = SiS_GetReg(SISCR, 0x86);
  4373. SiS_SetReg(SISCR, 0x86, 0x88);
  4374. reg = SiS_GetReg(SISCR, 0x86);
  4375. v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
  4376. if (ivideo->haveXGIROM) {
  4377. v1 = bios[regb + 0x168];
  4378. v2 = bios[regb + 0x160];
  4379. v3 = bios[regb + 0x158];
  4380. }
  4381. SiS_SetReg(SISCR, 0x86, v1);
  4382. SiS_SetReg(SISCR, 0x82, 0x77);
  4383. SiS_SetReg(SISCR, 0x85, 0x00);
  4384. reg = SiS_GetReg(SISCR, 0x85);
  4385. SiS_SetReg(SISCR, 0x85, 0x88);
  4386. reg = SiS_GetReg(SISCR, 0x85);
  4387. SiS_SetReg(SISCR, 0x85, v2);
  4388. SiS_SetReg(SISCR, 0x82, v3);
  4389. SiS_SetReg(SISCR, 0x98, 0x01);
  4390. SiS_SetReg(SISCR, 0x9a, 0x02);
  4391. if (sisfb_xgi_is21(ivideo))
  4392. sisfb_post_xgi_ddr2_mrs_xg21(ivideo);
  4393. else
  4394. sisfb_post_xgi_ddr2_mrs_default(ivideo, regb);
  4395. }
  4396. static u8 __devinit
  4397. sisfb_post_xgi_ramtype(struct sis_video_info *ivideo)
  4398. {
  4399. unsigned char *bios = ivideo->