root/drivers/usb/misc/sisusbvga/sisusb_init.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. SiSUSB_InitPtr
  2. SiS_SetReg
  3. SiS_SetRegByte
  4. SiS_GetReg
  5. SiS_GetRegByte
  6. SiS_SetRegANDOR
  7. SiS_SetRegAND
  8. SiS_SetRegOR
  9. SiS_DisplayOn
  10. SiSUSBRegInit
  11. SiS_GetSysFlags
  12. SiSInitPCIetc
  13. SiS_SetSegRegLower
  14. SiS_SetSegRegUpper
  15. SiS_SetSegmentReg
  16. SiS_ResetSegmentReg
  17. SiS_SetSegmentRegOver
  18. SiS_ResetSegmentRegOver
  19. SiS_ResetSegmentRegisters
  20. SiS_SearchModeID
  21. SiS_HandleCRT1
  22. SiS_GetColorDepth
  23. SiS_GetOffset
  24. SiS_SetSeqRegs
  25. SiS_SetMiscRegs
  26. SiS_SetCRTCRegs
  27. SiS_SetATTRegs
  28. SiS_SetGRCRegs
  29. SiS_ClearExt1Regs
  30. SiS_GetRatePtr
  31. SiS_SetCRT1Sync
  32. SiS_SetCRT1CRTC
  33. SiS_SetCRT1Offset
  34. SiS_SetCRT1VCLK
  35. SiS_SetCRT1FIFO_310
  36. SiS_SetVCLKState
  37. SiS_SetCRT1ModeRegs
  38. SiS_WriteDAC
  39. SiS_LoadDAC
  40. SiS_SetCRT1Group
  41. SiSUSBSetMode
  42. SiSUSBSetVESAMode

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

/* [<][>][^][v][top][bottom][index][help] */