sisusb_init.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048
  1. /*
  2. * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
  3. *
  4. * Display mode initializing code
  5. *
  6. * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
  7. *
  8. * If distributed as part of the Linux kernel, this code is licensed under the
  9. * terms of the GPL v2.
  10. *
  11. * Otherwise, the following license terms apply:
  12. *
  13. * * Redistribution and use in source and binary forms, with or without
  14. * * modification, are permitted provided that the following conditions
  15. * * are met:
  16. * * 1) Redistributions of source code must retain the above copyright
  17. * * notice, this list of conditions and the following disclaimer.
  18. * * 2) Redistributions in binary form must reproduce the above copyright
  19. * * notice, this list of conditions and the following disclaimer in the
  20. * * documentation and/or other materials provided with the distribution.
  21. * * 3) The name of the author may not be used to endorse or promote products
  22. * * derived from this software without specific prior written permission.
  23. * *
  24. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  25. * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  26. * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  27. * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  28. * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  29. * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  30. * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  31. * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  32. * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  33. * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  34. *
  35. * Author: Thomas Winischhofer <thomas@winischhofer.net>
  36. *
  37. */
  38. #include <linux/config.h>
  39. #include <linux/module.h>
  40. #include <linux/kernel.h>
  41. #include <linux/errno.h>
  42. #include <linux/poll.h>
  43. #include <linux/init.h>
  44. #include <linux/slab.h>
  45. #include <linux/spinlock.h>
  46. #include <linux/kref.h>
  47. #include "sisusb.h"
  48. #ifdef INCL_SISUSB_CON
  49. #include "sisusb_init.h"
  50. /*********************************************/
  51. /* POINTER INITIALIZATION */
  52. /*********************************************/
  53. static void
  54. SiSUSB_InitPtr(struct SiS_Private *SiS_Pr)
  55. {
  56. SiS_Pr->SiS_ModeResInfo = SiSUSB_ModeResInfo;
  57. SiS_Pr->SiS_StandTable = SiSUSB_StandTable;
  58. SiS_Pr->SiS_SModeIDTable = SiSUSB_SModeIDTable;
  59. SiS_Pr->SiS_EModeIDTable = SiSUSB_EModeIDTable;
  60. SiS_Pr->SiS_RefIndex = SiSUSB_RefIndex;
  61. SiS_Pr->SiS_CRT1Table = SiSUSB_CRT1Table;
  62. SiS_Pr->SiS_VCLKData = SiSUSB_VCLKData;
  63. }
  64. /*********************************************/
  65. /* HELPER: Get ModeID */
  66. /*********************************************/
  67. #if 0
  68. unsigned short
  69. SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth)
  70. {
  71. unsigned short ModeIndex = 0;
  72. switch (HDisplay)
  73. {
  74. case 320:
  75. if (VDisplay == 200)
  76. ModeIndex = ModeIndex_320x200[Depth];
  77. else if (VDisplay == 240)
  78. ModeIndex = ModeIndex_320x240[Depth];
  79. break;
  80. case 400:
  81. if (VDisplay == 300)
  82. ModeIndex = ModeIndex_400x300[Depth];
  83. break;
  84. case 512:
  85. if (VDisplay == 384)
  86. ModeIndex = ModeIndex_512x384[Depth];
  87. break;
  88. case 640:
  89. if (VDisplay == 480)
  90. ModeIndex = ModeIndex_640x480[Depth];
  91. else if (VDisplay == 400)
  92. ModeIndex = ModeIndex_640x400[Depth];
  93. break;
  94. case 720:
  95. if (VDisplay == 480)
  96. ModeIndex = ModeIndex_720x480[Depth];
  97. else if (VDisplay == 576)
  98. ModeIndex = ModeIndex_720x576[Depth];
  99. break;
  100. case 768:
  101. if (VDisplay == 576)
  102. ModeIndex = ModeIndex_768x576[Depth];
  103. break;
  104. case 800:
  105. if (VDisplay == 600)
  106. ModeIndex = ModeIndex_800x600[Depth];
  107. else if (VDisplay == 480)
  108. ModeIndex = ModeIndex_800x480[Depth];
  109. break;
  110. case 848:
  111. if (VDisplay == 480)
  112. ModeIndex = ModeIndex_848x480[Depth];
  113. break;
  114. case 856:
  115. if (VDisplay == 480)
  116. ModeIndex = ModeIndex_856x480[Depth];
  117. break;
  118. case 960:
  119. if (VDisplay == 540)
  120. ModeIndex = ModeIndex_960x540[Depth];
  121. else if (VDisplay == 600)
  122. ModeIndex = ModeIndex_960x600[Depth];
  123. break;
  124. case 1024:
  125. if (VDisplay == 576)
  126. ModeIndex = ModeIndex_1024x576[Depth];
  127. else if (VDisplay == 768)
  128. ModeIndex = ModeIndex_1024x768[Depth];
  129. break;
  130. case 1152:
  131. if (VDisplay == 864)
  132. ModeIndex = ModeIndex_1152x864[Depth];
  133. break;
  134. case 1280:
  135. switch (VDisplay) {
  136. case 720:
  137. ModeIndex = ModeIndex_1280x720[Depth];
  138. break;
  139. case 768:
  140. ModeIndex = ModeIndex_1280x768[Depth];
  141. break;
  142. case 1024:
  143. ModeIndex = ModeIndex_1280x1024[Depth];
  144. break;
  145. }
  146. }
  147. return ModeIndex;
  148. }
  149. #endif /* 0 */
  150. /*********************************************/
  151. /* HELPER: SetReg, GetReg */
  152. /*********************************************/
  153. static void
  154. SiS_SetReg(struct SiS_Private *SiS_Pr, unsigned long port,
  155. unsigned short index, unsigned short data)
  156. {
  157. sisusb_setidxreg(SiS_Pr->sisusb, port, index, data);
  158. }
  159. static void
  160. SiS_SetRegByte(struct SiS_Private *SiS_Pr, unsigned long port,
  161. unsigned short data)
  162. {
  163. sisusb_setreg(SiS_Pr->sisusb, port, data);
  164. }
  165. static unsigned char
  166. SiS_GetReg(struct SiS_Private *SiS_Pr, unsigned long port,
  167. unsigned short index)
  168. {
  169. u8 data;
  170. sisusb_getidxreg(SiS_Pr->sisusb, port, index, &data);
  171. return data;
  172. }
  173. static unsigned char
  174. SiS_GetRegByte(struct SiS_Private *SiS_Pr, unsigned long port)
  175. {
  176. u8 data;
  177. sisusb_getreg(SiS_Pr->sisusb, port, &data);
  178. return data;
  179. }
  180. static void
  181. SiS_SetRegANDOR(struct SiS_Private *SiS_Pr, unsigned long port,
  182. unsigned short index, unsigned short DataAND,
  183. unsigned short DataOR)
  184. {
  185. sisusb_setidxregandor(SiS_Pr->sisusb, port, index, DataAND, DataOR);
  186. }
  187. static void
  188. SiS_SetRegAND(struct SiS_Private *SiS_Pr, unsigned long port,
  189. unsigned short index, unsigned short DataAND)
  190. {
  191. sisusb_setidxregand(SiS_Pr->sisusb, port, index, DataAND);
  192. }
  193. static void
  194. SiS_SetRegOR(struct SiS_Private *SiS_Pr,unsigned long port,
  195. unsigned short index, unsigned short DataOR)
  196. {
  197. sisusb_setidxregor(SiS_Pr->sisusb, port, index, DataOR);
  198. }
  199. /*********************************************/
  200. /* HELPER: DisplayOn, DisplayOff */
  201. /*********************************************/
  202. static void
  203. SiS_DisplayOn(struct SiS_Private *SiS_Pr)
  204. {
  205. SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, 0xDF);
  206. }
  207. /*********************************************/
  208. /* HELPER: Init Port Addresses */
  209. /*********************************************/
  210. static void
  211. SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr)
  212. {
  213. SiS_Pr->SiS_P3c4 = BaseAddr + 0x14;
  214. SiS_Pr->SiS_P3d4 = BaseAddr + 0x24;
  215. SiS_Pr->SiS_P3c0 = BaseAddr + 0x10;
  216. SiS_Pr->SiS_P3ce = BaseAddr + 0x1e;
  217. SiS_Pr->SiS_P3c2 = BaseAddr + 0x12;
  218. SiS_Pr->SiS_P3ca = BaseAddr + 0x1a;
  219. SiS_Pr->SiS_P3c6 = BaseAddr + 0x16;
  220. SiS_Pr->SiS_P3c7 = BaseAddr + 0x17;
  221. SiS_Pr->SiS_P3c8 = BaseAddr + 0x18;
  222. SiS_Pr->SiS_P3c9 = BaseAddr + 0x19;
  223. SiS_Pr->SiS_P3cb = BaseAddr + 0x1b;
  224. SiS_Pr->SiS_P3cc = BaseAddr + 0x1c;
  225. SiS_Pr->SiS_P3cd = BaseAddr + 0x1d;
  226. SiS_Pr->SiS_P3da = BaseAddr + 0x2a;
  227. SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04;
  228. }
  229. /*********************************************/
  230. /* HELPER: GetSysFlags */
  231. /*********************************************/
  232. static void
  233. SiS_GetSysFlags(struct SiS_Private *SiS_Pr)
  234. {
  235. SiS_Pr->SiS_MyCR63 = 0x63;
  236. }
  237. /*********************************************/
  238. /* HELPER: Init PCI & Engines */
  239. /*********************************************/
  240. static void
  241. SiSInitPCIetc(struct SiS_Private *SiS_Pr)
  242. {
  243. SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x20, 0xa1);
  244. /* - Enable 2D (0x40)
  245. * - Enable 3D (0x02)
  246. * - Enable 3D vertex command fetch (0x10)
  247. * - Enable 3D command parser (0x08)
  248. * - Enable 3D G/L transformation engine (0x80)
  249. */
  250. SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1E, 0xDA);
  251. }
  252. /*********************************************/
  253. /* HELPER: SET SEGMENT REGISTERS */
  254. /*********************************************/
  255. static void
  256. SiS_SetSegRegLower(struct SiS_Private *SiS_Pr, unsigned short value)
  257. {
  258. unsigned short temp;
  259. value &= 0x00ff;
  260. temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb) & 0xf0;
  261. temp |= (value >> 4);
  262. SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb, temp);
  263. temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd) & 0xf0;
  264. temp |= (value & 0x0f);
  265. SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp);
  266. }
  267. static void
  268. SiS_SetSegRegUpper(struct SiS_Private *SiS_Pr, unsigned short value)
  269. {
  270. unsigned short temp;
  271. value &= 0x00ff;
  272. temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb) & 0x0f;
  273. temp |= (value & 0xf0);
  274. SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cb, temp);
  275. temp = SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd) & 0x0f;
  276. temp |= (value << 4);
  277. SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3cd, temp);
  278. }
  279. static void
  280. SiS_SetSegmentReg(struct SiS_Private *SiS_Pr, unsigned short value)
  281. {
  282. SiS_SetSegRegLower(SiS_Pr, value);
  283. SiS_SetSegRegUpper(SiS_Pr, value);
  284. }
  285. static void
  286. SiS_ResetSegmentReg(struct SiS_Private *SiS_Pr)
  287. {
  288. SiS_SetSegmentReg(SiS_Pr, 0);
  289. }
  290. static void
  291. SiS_SetSegmentRegOver(struct SiS_Private *SiS_Pr, unsigned short value)
  292. {
  293. unsigned short temp = value >> 8;
  294. temp &= 0x07;
  295. temp |= (temp << 4);
  296. SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1d, temp);
  297. SiS_SetSegmentReg(SiS_Pr, value);
  298. }
  299. static void
  300. SiS_ResetSegmentRegOver(struct SiS_Private *SiS_Pr)
  301. {
  302. SiS_SetSegmentRegOver(SiS_Pr, 0);
  303. }
  304. static void
  305. SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr)
  306. {
  307. SiS_ResetSegmentReg(SiS_Pr);
  308. SiS_ResetSegmentRegOver(SiS_Pr);
  309. }
  310. /*********************************************/
  311. /* HELPER: SearchModeID */
  312. /*********************************************/
  313. static int
  314. SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
  315. unsigned short *ModeIdIndex)
  316. {
  317. if ((*ModeNo) <= 0x13) {
  318. if ((*ModeNo) != 0x03)
  319. return 0;
  320. (*ModeIdIndex) = 0;
  321. } else {
  322. for(*ModeIdIndex = 0; ;(*ModeIdIndex)++) {
  323. if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == (*ModeNo))
  324. break;
  325. if (SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF)
  326. return 0;
  327. }
  328. }
  329. return 1;
  330. }
  331. /*********************************************/
  332. /* HELPER: ENABLE CRT1 */
  333. /*********************************************/
  334. static void
  335. SiS_HandleCRT1(struct SiS_Private *SiS_Pr)
  336. {
  337. /* Enable CRT1 gating */
  338. SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, SiS_Pr->SiS_MyCR63, 0xbf);
  339. }
  340. /*********************************************/
  341. /* HELPER: GetColorDepth */
  342. /*********************************************/
  343. static unsigned short
  344. SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
  345. unsigned short ModeIdIndex)
  346. {
  347. static const unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8};
  348. unsigned short modeflag;
  349. short index;
  350. if (ModeNo <= 0x13) {
  351. modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
  352. } else {
  353. modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
  354. }
  355. index = (modeflag & ModeTypeMask) - ModeEGA;
  356. if (index < 0) index = 0;
  357. return ColorDepth[index];
  358. }
  359. /*********************************************/
  360. /* HELPER: GetOffset */
  361. /*********************************************/
  362. static unsigned short
  363. SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
  364. unsigned short ModeIdIndex, unsigned short rrti)
  365. {
  366. unsigned short xres, temp, colordepth, infoflag;
  367. infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;
  368. xres = SiS_Pr->SiS_RefIndex[rrti].XRes;
  369. colordepth = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex);
  370. temp = xres / 16;
  371. if (infoflag & InterlaceMode)
  372. temp <<= 1;
  373. temp *= colordepth;
  374. if (xres % 16)
  375. temp += (colordepth >> 1);
  376. return temp;
  377. }
  378. /*********************************************/
  379. /* SEQ */
  380. /*********************************************/
  381. static void
  382. SiS_SetSeqRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
  383. {
  384. unsigned char SRdata;
  385. int i;
  386. SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x00, 0x03);
  387. SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0] | 0x20;
  388. SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, SRdata);
  389. for(i = 2; i <= 4; i++) {
  390. SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i-1];
  391. SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, SRdata);
  392. }
  393. }
  394. /*********************************************/
  395. /* MISC */
  396. /*********************************************/
  397. static void
  398. SiS_SetMiscRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
  399. {
  400. unsigned char Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC;
  401. SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c2, Miscdata);
  402. }
  403. /*********************************************/
  404. /* CRTC */
  405. /*********************************************/
  406. static void
  407. SiS_SetCRTCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
  408. {
  409. unsigned char CRTCdata;
  410. unsigned short i;
  411. SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4, 0x11, 0x7f);
  412. for(i = 0; i <= 0x18; i++) {
  413. CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
  414. SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, i, CRTCdata);
  415. }
  416. }
  417. /*********************************************/
  418. /* ATT */
  419. /*********************************************/
  420. static void
  421. SiS_SetATTRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
  422. {
  423. unsigned char ARdata;
  424. unsigned short i;
  425. for(i = 0; i <= 0x13; i++) {
  426. ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i];
  427. SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
  428. SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, i);
  429. SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, ARdata);
  430. }
  431. SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
  432. SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x14);
  433. SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x00);
  434. SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
  435. SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c0, 0x20);
  436. SiS_GetRegByte(SiS_Pr, SiS_Pr->SiS_P3da);
  437. }
  438. /*********************************************/
  439. /* GRC */
  440. /*********************************************/
  441. static void
  442. SiS_SetGRCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
  443. {
  444. unsigned char GRdata;
  445. unsigned short i;
  446. for(i = 0; i <= 0x08; i++) {
  447. GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i];
  448. SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3ce, i, GRdata);
  449. }
  450. if (SiS_Pr->SiS_ModeType > ModeVGA) {
  451. /* 256 color disable */
  452. SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3ce, 0x05, 0xBF);
  453. }
  454. }
  455. /*********************************************/
  456. /* CLEAR EXTENDED REGISTERS */
  457. /*********************************************/
  458. static void
  459. SiS_ClearExt1Regs(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
  460. {
  461. int i;
  462. for(i = 0x0A; i <= 0x0E; i++) {
  463. SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, i, 0x00);
  464. }
  465. SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x37, 0xFE);
  466. }
  467. /*********************************************/
  468. /* Get rate index */
  469. /*********************************************/
  470. static unsigned short
  471. SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
  472. unsigned short ModeIdIndex)
  473. {
  474. unsigned short rrti, i, index, temp;
  475. if (ModeNo <= 0x13)
  476. return 0xFFFF;
  477. index = SiS_GetReg(SiS_Pr,SiS_Pr->SiS_P3d4, 0x33) & 0x0F;
  478. if (index > 0) index--;
  479. rrti = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
  480. ModeNo = SiS_Pr->SiS_RefIndex[rrti].ModeID;
  481. i = 0;
  482. do {
  483. if (SiS_Pr->SiS_RefIndex[rrti + i].ModeID != ModeNo)
  484. break;
  485. temp = SiS_Pr->SiS_RefIndex[rrti + i].Ext_InfoFlag & ModeTypeMask;
  486. if (temp < SiS_Pr->SiS_ModeType)
  487. break;
  488. i++;
  489. index--;
  490. } while(index != 0xFFFF);
  491. i--;
  492. return (rrti + i);
  493. }
  494. /*********************************************/
  495. /* SYNC */
  496. /*********************************************/
  497. static void
  498. SiS_SetCRT1Sync(struct SiS_Private *SiS_Pr, unsigned short rrti)
  499. {
  500. unsigned short sync = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag >> 8;
  501. sync &= 0xC0;
  502. sync |= 0x2f;
  503. SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c2, sync);
  504. }
  505. /*********************************************/
  506. /* CRTC/2 */
  507. /*********************************************/
  508. static void
  509. SiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
  510. unsigned short ModeIdIndex, unsigned short rrti)
  511. {
  512. unsigned char index;
  513. unsigned short temp, i, j, modeflag;
  514. SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3d4,0x11,0x7f);
  515. modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
  516. index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRT1CRTC;
  517. for(i = 0,j = 0; i <= 7; i++, j++) {
  518. SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,
  519. SiS_Pr->SiS_CRT1Table[index].CR[i]);
  520. }
  521. for(j = 0x10; i <= 10; i++, j++) {
  522. SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,
  523. SiS_Pr->SiS_CRT1Table[index].CR[i]);
  524. }
  525. for(j = 0x15; i <= 12; i++, j++) {
  526. SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, j,
  527. SiS_Pr->SiS_CRT1Table[index].CR[i]);
  528. }
  529. for(j = 0x0A; i <= 15; i++, j++) {
  530. SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, j,
  531. SiS_Pr->SiS_CRT1Table[index].CR[i]);
  532. }
  533. temp = SiS_Pr->SiS_CRT1Table[index].CR[16] & 0xE0;
  534. SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4, 0x0E, temp);
  535. temp = ((SiS_Pr->SiS_CRT1Table[index].CR[16]) & 0x01) << 5;
  536. if (modeflag & DoubleScanMode) temp |= 0x80;
  537. SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3d4, 0x09, 0x5F, temp);
  538. if (SiS_Pr->SiS_ModeType > ModeVGA)
  539. SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x14, 0x4F);
  540. }
  541. /*********************************************/
  542. /* OFFSET & PITCH */
  543. /*********************************************/
  544. /* (partly overruled by SetPitch() in XF86) */
  545. /*********************************************/
  546. static void
  547. SiS_SetCRT1Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
  548. unsigned short ModeIdIndex, unsigned short rrti)
  549. {
  550. unsigned short du = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, rrti);
  551. unsigned short infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;
  552. unsigned short temp;
  553. temp = (du >> 8) & 0x0f;
  554. SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0E, 0xF0, temp);
  555. SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x13, (du & 0xFF));
  556. if (infoflag & InterlaceMode) du >>= 1;
  557. du <<= 5;
  558. temp = (du >> 8) & 0xff;
  559. if (du & 0xff) temp++;
  560. temp++;
  561. SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x10, temp);
  562. }
  563. /*********************************************/
  564. /* VCLK */
  565. /*********************************************/
  566. static void
  567. SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
  568. unsigned short rrti)
  569. {
  570. unsigned short index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRTVCLK;
  571. unsigned short clka = SiS_Pr->SiS_VCLKData[index].SR2B;
  572. unsigned short clkb = SiS_Pr->SiS_VCLKData[index].SR2C;
  573. SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4,0x31,0xCF);
  574. SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2B,clka);
  575. SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2C,clkb);
  576. SiS_SetReg(SiS_Pr,SiS_Pr->SiS_P3c4,0x2D,0x01);
  577. }
  578. /*********************************************/
  579. /* FIFO */
  580. /*********************************************/
  581. static void
  582. SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
  583. unsigned short mi)
  584. {
  585. unsigned short modeflag = SiS_Pr->SiS_EModeIDTable[mi].Ext_ModeFlag;
  586. /* disable auto-threshold */
  587. SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x3D, 0xFE);
  588. SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x08, 0xAE);
  589. SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x09, 0xF0);
  590. if (ModeNo <= 0x13)
  591. return;
  592. if ((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
  593. SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x08, 0x34);
  594. SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x3D, 0x01);
  595. }
  596. }
  597. /*********************************************/
  598. /* MODE REGISTERS */
  599. /*********************************************/
  600. static void
  601. SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
  602. unsigned short rrti)
  603. {
  604. unsigned short data = 0, VCLK = 0, index = 0;
  605. if (ModeNo > 0x13) {
  606. index = SiS_Pr->SiS_RefIndex[rrti].Ext_CRTVCLK;
  607. VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
  608. }
  609. if (VCLK >= 166) data |= 0x0c;
  610. SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x32, 0xf3, data);
  611. if (VCLK >= 166)
  612. SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1f, 0xe7);
  613. /* DAC speed */
  614. data = 0x03;
  615. if (VCLK >= 260)
  616. data = 0x00;
  617. else if (VCLK >= 160)
  618. data = 0x01;
  619. else if (VCLK >= 135)
  620. data = 0x02;
  621. SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x07, 0xF8, data);
  622. }
  623. static void
  624. SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
  625. unsigned short ModeIdIndex, unsigned short rrti)
  626. {
  627. unsigned short data, infoflag = 0, modeflag;
  628. if (ModeNo <= 0x13)
  629. modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
  630. else {
  631. modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
  632. infoflag = SiS_Pr->SiS_RefIndex[rrti].Ext_InfoFlag;
  633. }
  634. /* Disable DPMS */
  635. SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x1F, 0x3F);
  636. data = 0;
  637. if (ModeNo > 0x13) {
  638. if (SiS_Pr->SiS_ModeType > ModeEGA) {
  639. data |= 0x02;
  640. data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
  641. }
  642. if (infoflag & InterlaceMode) data |= 0x20;
  643. }
  644. SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x06, 0xC0, data);
  645. data = 0;
  646. if (infoflag & InterlaceMode) {
  647. /* data = (Hsync / 8) - ((Htotal / 8) / 2) + 3 */
  648. unsigned short hrs = (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x04) |
  649. ((SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0b) & 0xc0) << 2)) - 3;
  650. unsigned short hto = (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x00) |
  651. ((SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0b) & 0x03) << 8)) + 5;
  652. data = hrs - (hto >> 1) + 3;
  653. }
  654. SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x19, (data & 0xFF));
  655. SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3d4, 0x1a, 0xFC, (data >> 8));
  656. if (modeflag & HalfDCLK)
  657. SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x01, 0x08);
  658. data = 0;
  659. if (modeflag & LineCompareOff)
  660. data = 0x08;
  661. SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0F, 0xB7, data);
  662. if ((SiS_Pr->SiS_ModeType == ModeEGA) && (ModeNo > 0x13))
  663. SiS_SetRegOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x0F, 0x40);
  664. SiS_SetRegAND(SiS_Pr, SiS_Pr->SiS_P3c4, 0x31, 0xfb);
  665. data = 0x60;
  666. if (SiS_Pr->SiS_ModeType != ModeText) {
  667. data ^= 0x60;
  668. if (SiS_Pr->SiS_ModeType != ModeEGA)
  669. data ^= 0xA0;
  670. }
  671. SiS_SetRegANDOR(SiS_Pr, SiS_Pr->SiS_P3c4, 0x21, 0x1F, data);
  672. SiS_SetVCLKState(SiS_Pr, ModeNo, rrti);
  673. if (SiS_GetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x31) & 0x40)
  674. SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x52, 0x2c);
  675. else
  676. SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x52, 0x6c);
  677. }
  678. /*********************************************/
  679. /* LOAD DAC */
  680. /*********************************************/
  681. static void
  682. SiS_WriteDAC(struct SiS_Private *SiS_Pr, unsigned long DACData,
  683. unsigned short shiftflag, unsigned short dl, unsigned short ah,
  684. unsigned short al, unsigned short dh)
  685. {
  686. unsigned short d1, d2, d3;
  687. switch (dl) {
  688. case 0:
  689. d1 = dh; d2 = ah; d3 = al;
  690. break;
  691. case 1:
  692. d1 = ah; d2 = al; d3 = dh;
  693. break;
  694. default:
  695. d1 = al; d2 = dh; d3 = ah;
  696. }
  697. SiS_SetRegByte(SiS_Pr, DACData, (d1 << shiftflag));
  698. SiS_SetRegByte(SiS_Pr, DACData, (d2 << shiftflag));
  699. SiS_SetRegByte(SiS_Pr, DACData, (d3 << shiftflag));
  700. }
  701. static void
  702. SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short mi)
  703. {
  704. unsigned short data, data2, time, i, j, k, m, n, o;
  705. unsigned short si, di, bx, sf;
  706. unsigned long DACAddr, DACData;
  707. const unsigned char *table = NULL;
  708. if (ModeNo < 0x13)
  709. data = SiS_Pr->SiS_SModeIDTable[mi].St_ModeFlag;
  710. else
  711. data = SiS_Pr->SiS_EModeIDTable[mi].Ext_ModeFlag;
  712. data &= DACInfoFlag;
  713. j = time = 64;
  714. if (data == 0x00)
  715. table = SiS_MDA_DAC;
  716. else if (data == 0x08)
  717. table = SiS_CGA_DAC;
  718. else if (data == 0x10)
  719. table = SiS_EGA_DAC;
  720. else {
  721. j = 16;
  722. time = 256;
  723. table = SiS_VGA_DAC;
  724. }
  725. DACAddr = SiS_Pr->SiS_P3c8;
  726. DACData = SiS_Pr->SiS_P3c9;
  727. sf = 0;
  728. SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c6, 0xFF);
  729. SiS_SetRegByte(SiS_Pr, DACAddr, 0x00);
  730. for(i = 0; i < j; i++) {
  731. data = table[i];
  732. for(k = 0; k < 3; k++) {
  733. data2 = 0;
  734. if (data & 0x01) data2 += 0x2A;
  735. if (data & 0x02) data2 += 0x15;
  736. SiS_SetRegByte(SiS_Pr, DACData, (data2 << sf));
  737. data >>= 2;
  738. }
  739. }
  740. if (time == 256) {
  741. for(i = 16; i < 32; i++) {
  742. data = table[i] << sf;
  743. for(k = 0; k < 3; k++)
  744. SiS_SetRegByte(SiS_Pr, DACData, data);
  745. }
  746. si = 32;
  747. for(m = 0; m < 9; m++) {
  748. di = si;
  749. bx = si + 4;
  750. for(n = 0; n < 3; n++) {
  751. for(o = 0; o < 5; o++) {
  752. SiS_WriteDAC(SiS_Pr, DACData, sf, n,
  753. table[di], table[bx], table[si]);
  754. si++;
  755. }
  756. si -= 2;
  757. for(o = 0; o < 3; o++) {
  758. SiS_WriteDAC(SiS_Pr, DACData, sf, n,
  759. table[di], table[si], table[bx]);
  760. si--;
  761. }
  762. }
  763. si += 5;
  764. }
  765. }
  766. }
  767. /*********************************************/
  768. /* SET CRT1 REGISTER GROUP */
  769. /*********************************************/
  770. static void
  771. SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
  772. unsigned short ModeIdIndex)
  773. {
  774. unsigned short StandTableIndex, rrti;
  775. SiS_Pr->SiS_CRT1Mode = ModeNo;
  776. if (ModeNo <= 0x13)
  777. StandTableIndex = 0;
  778. else
  779. StandTableIndex = 1;
  780. SiS_ResetSegmentRegisters(SiS_Pr);
  781. SiS_SetSeqRegs(SiS_Pr, StandTableIndex);
  782. SiS_SetMiscRegs(SiS_Pr, StandTableIndex);
  783. SiS_SetCRTCRegs(SiS_Pr, StandTableIndex);
  784. SiS_SetATTRegs(SiS_Pr, StandTableIndex);
  785. SiS_SetGRCRegs(SiS_Pr, StandTableIndex);
  786. SiS_ClearExt1Regs(SiS_Pr, ModeNo);
  787. rrti = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
  788. if (rrti != 0xFFFF) {
  789. SiS_SetCRT1Sync(SiS_Pr, rrti);
  790. SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, rrti);
  791. SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, rrti);
  792. SiS_SetCRT1VCLK(SiS_Pr, ModeNo, rrti);
  793. }
  794. SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex);
  795. SiS_SetCRT1ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, rrti);
  796. SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
  797. SiS_DisplayOn(SiS_Pr);
  798. }
  799. /*********************************************/
  800. /* SiSSetMode() */
  801. /*********************************************/
  802. int
  803. SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
  804. {
  805. unsigned short ModeIdIndex;
  806. unsigned long BaseAddr = SiS_Pr->IOAddress;
  807. SiSUSB_InitPtr(SiS_Pr);
  808. SiSUSBRegInit(SiS_Pr, BaseAddr);
  809. SiS_GetSysFlags(SiS_Pr);
  810. if (!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex)))
  811. return 0;
  812. SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3c4, 0x05, 0x86);
  813. SiSInitPCIetc(SiS_Pr);
  814. ModeNo &= 0x7f;
  815. SiS_Pr->SiS_ModeType =
  816. SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag & ModeTypeMask;
  817. SiS_Pr->SiS_SetFlag = LowModeTests;
  818. /* Set mode on CRT1 */
  819. SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);
  820. SiS_HandleCRT1(SiS_Pr);
  821. SiS_DisplayOn(SiS_Pr);
  822. SiS_SetRegByte(SiS_Pr, SiS_Pr->SiS_P3c6, 0xFF);
  823. /* Store mode number */
  824. SiS_SetReg(SiS_Pr, SiS_Pr->SiS_P3d4, 0x34, ModeNo);
  825. return 1;
  826. }
  827. int
  828. SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo)
  829. {
  830. unsigned short ModeNo = 0;
  831. int i;
  832. SiSUSB_InitPtr(SiS_Pr);
  833. if (VModeNo == 0x03) {
  834. ModeNo = 0x03;
  835. } else {
  836. i = 0;
  837. do {
  838. if (SiS_Pr->SiS_EModeIDTable[i].Ext_VESAID == VModeNo) {
  839. ModeNo = SiS_Pr->SiS_EModeIDTable[i].Ext_ModeID;
  840. break;
  841. }
  842. } while (SiS_Pr->SiS_EModeIDTable[i++].Ext_ModeID != 0xff);
  843. }
  844. if (!ModeNo)
  845. return 0;
  846. return SiSUSBSetMode(SiS_Pr, ModeNo);
  847. }
  848. #endif /* INCL_SISUSB_CON */