PageRenderTime 72ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 1ms

/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

Large files files are truncated, but you can click here to view the full file

  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(gp

Large files files are truncated, but you can click here to view the full file