sisusb_init.c 27 KB

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