17104f784Smrg/* 27104f784SmrgCopyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved. 37104f784SmrgCopyright (C) 2000 Silicon Motion, Inc. All Rights Reserved. 47104f784SmrgCopyright (C) 2008 Francisco Jerez. All Rights Reserved. 57104f784Smrg 67104f784SmrgPermission is hereby granted, free of charge, to any person obtaining a copy of 77104f784Smrgthis software and associated documentation files (the "Software"), to deal in 87104f784Smrgthe Software without restriction, including without limitation the rights to 97104f784Smrguse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 107104f784Smrgof the Software, and to permit persons to whom the Software is furnished to do 117104f784Smrgso, subject to the following conditions: 127104f784Smrg 137104f784SmrgThe above copyright notice and this permission notice shall be included in all 147104f784Smrgcopies or substantial portions of the Software. 157104f784Smrg 167104f784SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 177104f784SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT- 187104f784SmrgNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 197104f784SmrgXFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 207104f784SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 217104f784SmrgWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 227104f784Smrg 237104f784SmrgExcept as contained in this notice, the names of The XFree86 Project and 247104f784SmrgSilicon Motion shall not be used in advertising or otherwise to promote the 257104f784Smrgsale, use or other dealings in this Software without prior written 267104f784Smrgauthorization from The XFree86 Project or Silicon Motion. 277104f784Smrg*/ 287104f784Smrg 297104f784Smrg#ifdef HAVE_CONFIG_H 307104f784Smrg#include "config.h" 317104f784Smrg#endif 327104f784Smrg 337104f784Smrg#include "smi.h" 347104f784Smrg#include "smi_crtc.h" 357104f784Smrg#include "smilynx.h" 367104f784Smrg 377104f784Smrgstatic void 387104f784SmrgSMILynx_CrtcVideoInit_crt(xf86CrtcPtr crtc) 397104f784Smrg{ 407104f784Smrg ScrnInfoPtr pScrn=crtc->scrn; 417104f784Smrg SMIPtr pSmi = SMIPTR(pScrn); 427104f784Smrg int pitch; 437104f784Smrg 447104f784Smrg ENTER(); 457104f784Smrg 467104f784Smrg switch (pScrn->bitsPerPixel) { 477104f784Smrg case 8: 487104f784Smrg WRITE_VPR(pSmi, 0x00, 0x00000000); 497104f784Smrg break; 507104f784Smrg case 16: 517104f784Smrg WRITE_VPR(pSmi, 0x00, 0x00020000); 527104f784Smrg break; 537104f784Smrg case 24: 547104f784Smrg WRITE_VPR(pSmi, 0x00, 0x00040000); 557104f784Smrg break; 567104f784Smrg case 32: 577104f784Smrg WRITE_VPR(pSmi, 0x00, 0x00030000); 587104f784Smrg break; 597104f784Smrg } 607104f784Smrg 617104f784Smrg pitch = (crtc->rotatedData? crtc->mode.HDisplay : pScrn->displayWidth) * pSmi->Bpp; 627104f784Smrg pitch = (pitch + 15) & ~15; 637104f784Smrg 647104f784Smrg WRITE_VPR(pSmi, 0x10, (crtc->mode.HDisplay * pSmi->Bpp) >> 3 << 16 | pitch >> 3); 657104f784Smrg 667104f784Smrg LEAVE(); 677104f784Smrg} 687104f784Smrg 697104f784Smrgstatic void 707104f784SmrgSMILynx_CrtcVideoInit_lcd(xf86CrtcPtr crtc) 717104f784Smrg{ 727104f784Smrg ScrnInfoPtr pScrn=crtc->scrn; 737104f784Smrg SMIPtr pSmi = SMIPTR(pScrn); 747104f784Smrg SMIRegPtr mode = pSmi->mode; 757104f784Smrg CARD16 fifo_readoffset,fifo_writeoffset; 767104f784Smrg 777104f784Smrg ENTER(); 787104f784Smrg 797104f784Smrg /* Set display depth */ 807104f784Smrg if (pScrn->bitsPerPixel > 8) 817104f784Smrg mode->SR31 |= 0x40; /* 16 bpp */ 827104f784Smrg else 837104f784Smrg mode->SR31 &= ~0x40; /* 8 bpp */ 847104f784Smrg 857104f784Smrg /* FIFO1/2 Read Offset*/ 867104f784Smrg fifo_readoffset = (crtc->rotatedData? crtc->mode.HDisplay : pScrn->displayWidth) * pSmi->Bpp; 877104f784Smrg fifo_readoffset = ((fifo_readoffset + 15) & ~15) >> 3; 887104f784Smrg 897104f784Smrg /* FIFO1 Read Offset */ 907104f784Smrg mode->SR44 = fifo_readoffset & 0x000000FF; 917104f784Smrg /* FIFO2 Read Offset */ 927104f784Smrg mode->SR4B = fifo_readoffset & 0x000000FF; 937104f784Smrg 947104f784Smrg if(pSmi->Chipset == SMI_LYNX3DM){ 957104f784Smrg /* FIFO1/2 Read Offset overflow */ 967104f784Smrg mode->SR4C = (((fifo_readoffset & 0x00000300) >> 8) << 2) | 977104f784Smrg (((fifo_readoffset & 0x00000300) >> 8) << 6); 987104f784Smrg }else{ 997104f784Smrg /* FIFO1 Read Offset overflow */ 1007104f784Smrg mode->SR45 = (mode->SR45 & 0x3F) | ((fifo_readoffset & 0x00000300) >> 8) << 6; 1017104f784Smrg /* FIFO2 Read Offset overflow */ 1027104f784Smrg mode->SR4C = (((fifo_readoffset & 0x00000300) >> 8) << 6); 1037104f784Smrg } 1047104f784Smrg 1057104f784Smrg /* FIFO Write Offset */ 1067104f784Smrg fifo_writeoffset = crtc->mode.HDisplay * pSmi->Bpp >> 3; 1077104f784Smrg mode->SR48 = fifo_writeoffset & 0x000000FF; 1087104f784Smrg mode->SR49 = (fifo_writeoffset & 0x00000300) >> 8; 1097104f784Smrg 1107104f784Smrg /* set FIFO levels */ 1117104f784Smrg mode->SR4A = 0x41; 1127104f784Smrg 1137104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31, mode->SR31); 1147104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x44, mode->SR44); 1157104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x45, mode->SR45); 1167104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x48, mode->SR48); 1177104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x49, mode->SR49); 1187104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4A, mode->SR4A); 1197104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4B, mode->SR4B); 1207104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4C, mode->SR4C); 1217104f784Smrg 1227104f784Smrg LEAVE(); 1237104f784Smrg} 1247104f784Smrg 1257104f784Smrgstatic void 1267104f784SmrgSMI730_CrtcVideoInit(xf86CrtcPtr crtc) 1277104f784Smrg{ 1287104f784Smrg ScrnInfoPtr pScrn=crtc->scrn; 1297104f784Smrg SMIPtr pSmi = SMIPTR(pScrn); 1307104f784Smrg int pitch; 1317104f784Smrg 1327104f784Smrg ENTER(); 1337104f784Smrg 1347104f784Smrg switch (pScrn->bitsPerPixel) { 1357104f784Smrg case 8: 1367104f784Smrg WRITE_VPR(pSmi, 0x00, 0x00000000); 1377104f784Smrg WRITE_FPR(pSmi, FPR00, 0x00080000); 1387104f784Smrg break; 1397104f784Smrg case 16: 1407104f784Smrg WRITE_VPR(pSmi, 0x00, 0x00020000); 1417104f784Smrg WRITE_FPR(pSmi, FPR00, 0x000A0000); 1427104f784Smrg break; 1437104f784Smrg case 24: 1447104f784Smrg WRITE_VPR(pSmi, 0x00, 0x00040000); 1457104f784Smrg WRITE_FPR(pSmi, FPR00, 0x000C0000); 1467104f784Smrg break; 1477104f784Smrg case 32: 1487104f784Smrg WRITE_VPR(pSmi, 0x00, 0x00030000); 1497104f784Smrg WRITE_FPR(pSmi, FPR00, 0x000B0000); 1507104f784Smrg break; 1517104f784Smrg } 1527104f784Smrg 1537104f784Smrg pitch = (crtc->rotatedData? crtc->mode.HDisplay : pScrn->displayWidth) * pSmi->Bpp; 1547104f784Smrg pitch = (pitch + 15) & ~15; 1557104f784Smrg 1567104f784Smrg WRITE_VPR(pSmi, 0x10, (crtc->mode.HDisplay * pSmi->Bpp) >> 3 << 16 | pitch >> 3); 1577104f784Smrg WRITE_FPR(pSmi, FPR10, (crtc->mode.HDisplay * pSmi->Bpp) >> 3 << 16 | pitch >> 3); 1587104f784Smrg 1597104f784Smrg LEAVE(); 1607104f784Smrg} 1617104f784Smrg 1627104f784Smrgstatic void 1637104f784SmrgSMILynx_CrtcAdjustFrame(xf86CrtcPtr crtc, int x, int y) 1647104f784Smrg{ 1657104f784Smrg ScrnInfoPtr pScrn=crtc->scrn; 1667104f784Smrg SMIPtr pSmi = SMIPTR(pScrn); 1677104f784Smrg SMIRegPtr mode = pSmi->mode; 1687104f784Smrg xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn); 1697104f784Smrg CARD32 Base; 1707104f784Smrg 1717104f784Smrg ENTER(); 1727104f784Smrg 1737104f784Smrg if(crtc->rotatedData) 1747104f784Smrg Base = (char*)crtc->rotatedData - (char*)pSmi->FBBase; 1757104f784Smrg else 1767104f784Smrg Base = pSmi->FBOffset + (x + y * pScrn->displayWidth) * pSmi->Bpp; 1777104f784Smrg 1787104f784Smrg 1797104f784Smrg if (SMI_LYNX3D_SERIES(pSmi->Chipset) || 1807104f784Smrg SMI_COUGAR_SERIES(pSmi->Chipset)) { 1817104f784Smrg Base = (Base + 15) & ~15; 1827104f784Smrg while ((Base % pSmi->Bpp) > 0) { 1837104f784Smrg Base -= 16; 1847104f784Smrg } 1857104f784Smrg } else { 1867104f784Smrg Base = (Base + 7) & ~7; 1877104f784Smrg while ((Base % pSmi->Bpp) > 0) 1887104f784Smrg Base -= 8; 1897104f784Smrg } 1907104f784Smrg 1917104f784Smrg Base >>= 3; 1927104f784Smrg 1937104f784Smrg if(SMI_COUGAR_SERIES(pSmi->Chipset)){ 1947104f784Smrg WRITE_VPR(pSmi, 0x0C, Base); 1957104f784Smrg WRITE_FPR(pSmi, FPR0C, Base); 1967104f784Smrg }else{ 1977104f784Smrg if(pSmi->Dualhead && crtc == crtcConf->crtc[1]){ 1987104f784Smrg /* LCD */ 1997104f784Smrg 2007104f784Smrg /* FIFO1 read start address */ 2017104f784Smrg mode->SR40 = Base & 0x000000FF; 2027104f784Smrg mode->SR41 = (Base & 0x0000FF00) >> 8; 2037104f784Smrg 2047104f784Smrg /* FIFO2 read start address */ 2057104f784Smrg mode->SR42 = Base & 0x000000FF; 2067104f784Smrg mode->SR43 = (Base & 0x0000FF00) >> 8; 2077104f784Smrg 2087104f784Smrg /* FIFO1/2 read start address overflow */ 2097104f784Smrg if(pSmi->Chipset == SMI_LYNX3DM) 2107104f784Smrg mode->SR45 = (Base & 0x000F0000) >> 16 | (Base & 0x000F0000) >> 16 << 4; 2117104f784Smrg else 2127104f784Smrg mode->SR45 = (mode->SR45 & 0xC0) | 2137104f784Smrg (Base & 0x00070000) >> 16 | (Base & 0x00070000) >> 16 << 3; 2147104f784Smrg 2157104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x40, mode->SR40); 2167104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x41, mode->SR41); 2177104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x42, mode->SR42); 2187104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x43, mode->SR43); 2197104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x45, mode->SR45); 2207104f784Smrg 2217104f784Smrg }else{ 2227104f784Smrg /* CRT or single head */ 2237104f784Smrg WRITE_VPR(pSmi, 0x0C, Base); 2247104f784Smrg } 2257104f784Smrg } 2267104f784Smrg 2277104f784Smrg LEAVE(); 2287104f784Smrg} 2297104f784Smrg 2307104f784Smrgstatic Bool 2317104f784SmrgSMILynx_CrtcModeFixup(xf86CrtcPtr crtc, 2327104f784Smrg DisplayModePtr mode, 2337104f784Smrg DisplayModePtr adjusted_mode) 2347104f784Smrg{ 2357104f784Smrg ScrnInfoPtr pScrn=crtc->scrn; 2367104f784Smrg SMIPtr pSmi = SMIPTR(pScrn); 2377104f784Smrg 2387104f784Smrg ENTER(); 2397104f784Smrg 2407104f784Smrg if (pSmi->Chipset == SMI_LYNXEMplus) { 2417104f784Smrg /* Adjust the pixel clock in case it is near one of the known 2427104f784Smrg stable frequencies (KHz) */ 2437104f784Smrg int stable_clocks[] = {46534,}; 2442ec8c4b4Smrg int epsilon = 3000; 2457104f784Smrg int i; 2467104f784Smrg 2477104f784Smrg for (i=0; i < sizeof(stable_clocks)/sizeof(int); i++) { 2487104f784Smrg if ( abs(mode->Clock - stable_clocks[i]) < epsilon) { 2497104f784Smrg adjusted_mode->Clock = stable_clocks[i]; 2507104f784Smrg break; 2517104f784Smrg } 2527104f784Smrg } 2537104f784Smrg } 2547104f784Smrg 2557104f784Smrg LEAVE(TRUE); 2567104f784Smrg} 2577104f784Smrg 2587104f784Smrgstatic void 2597104f784SmrgSMILynx_CrtcModeSet_vga(xf86CrtcPtr crtc, 2607104f784Smrg DisplayModePtr mode, 2617104f784Smrg DisplayModePtr adjusted_mode, 2627104f784Smrg int x, int y) 2637104f784Smrg{ 2647104f784Smrg ScrnInfoPtr pScrn=crtc->scrn; 2657104f784Smrg SMIPtr pSmi = SMIPTR(pScrn); 2667104f784Smrg SMIRegPtr reg = pSmi->mode; 2677104f784Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 2687104f784Smrg int vgaIOBase = hwp->IOBase; 2697104f784Smrg int vgaCRIndex = vgaIOBase + VGA_CRTC_INDEX_OFFSET; 2707104f784Smrg int vgaCRData = vgaIOBase + VGA_CRTC_DATA_OFFSET; 2717104f784Smrg vgaRegPtr vganew = &hwp->ModeReg; 2727104f784Smrg 2737104f784Smrg ENTER(); 2747104f784Smrg 2757104f784Smrg /* Initialize Video Processor Registers */ 2767104f784Smrg 2777104f784Smrg SMICRTC(crtc)->video_init(crtc); 2787104f784Smrg SMILynx_CrtcAdjustFrame(crtc, x,y); 2797104f784Smrg 2807104f784Smrg 2817104f784Smrg /* Program the PLL */ 2827104f784Smrg 2837104f784Smrg /* calculate vclk1 */ 2847104f784Smrg if (SMI_LYNX_SERIES(pSmi->Chipset)) { 2857104f784Smrg SMI_CommonCalcClock(pScrn->scrnIndex, adjusted_mode->Clock, 2867104f784Smrg 1, 1, 63, 0, 3, 2877104f784Smrg pSmi->clockRange.minClock, 2887104f784Smrg pSmi->clockRange.maxClock, 2897104f784Smrg ®->SR6C, ®->SR6D); 2907104f784Smrg } else { 2917104f784Smrg SMI_CommonCalcClock(pScrn->scrnIndex, adjusted_mode->Clock, 2927104f784Smrg 1, 1, 63, 0, 1, 2937104f784Smrg pSmi->clockRange.minClock, 2947104f784Smrg pSmi->clockRange.maxClock, 2957104f784Smrg ®->SR6C, ®->SR6D); 2967104f784Smrg } 2977104f784Smrg 2987104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6C, reg->SR6C); 2997104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6D, reg->SR6D); 3007104f784Smrg 3017104f784Smrg 3027104f784Smrg /* Adjust mode timings */ 3037104f784Smrg 3047104f784Smrg if (!vgaHWInit(pScrn, mode)) { 3057104f784Smrg LEAVE(); 3067104f784Smrg } 3077104f784Smrg 3087104f784Smrg if ((mode->HDisplay == 640) && SMI_LYNXM_SERIES(pSmi->Chipset)) { 3097104f784Smrg vganew->MiscOutReg &= ~0x0C; 3107104f784Smrg } else { 3117104f784Smrg vganew->MiscOutReg |= 0x0C; 3127104f784Smrg } 3137104f784Smrg vganew->MiscOutReg |= 0x20; 3147104f784Smrg 3157104f784Smrg { 3167104f784Smrg unsigned long HTotal=(mode->CrtcHTotal>>3)-5; 3177104f784Smrg unsigned long HBlankEnd=(mode->CrtcHBlankEnd>>3)-1; 3187104f784Smrg unsigned long VTotal=mode->CrtcVTotal-2; 3197104f784Smrg unsigned long VDisplay=mode->CrtcVDisplay-1; 3207104f784Smrg unsigned long VBlankStart=mode->CrtcVBlankStart-1; 3217104f784Smrg unsigned long VBlankEnd=mode->CrtcVBlankEnd-1; 3227104f784Smrg unsigned long VSyncStart=mode->CrtcVSyncStart; 3237104f784Smrg 3247104f784Smrg /* Fix HBlankEnd/VBlankEnd */ 3257104f784Smrg if((mode->CrtcHBlankEnd >> 3) == (mode->CrtcHTotal >> 3)) HBlankEnd=0; 3267104f784Smrg if(mode->CrtcVBlankEnd == mode->CrtcVTotal) VBlankEnd=0; 3277104f784Smrg 3287104f784Smrg vganew->CRTC[3] = (vganew->CRTC[3] & ~0x1F) | (HBlankEnd & 0x1F); 3297104f784Smrg vganew->CRTC[5] = (vganew->CRTC[5] & ~0x80) | (HBlankEnd & 0x20) >> 5 << 7; 3307104f784Smrg vganew->CRTC[22] = VBlankEnd & 0xFF; 3317104f784Smrg 3327104f784Smrg /* Write the overflow from several VGA registers */ 3337104f784Smrg reg->CR30 = (VTotal & 0x400) >> 10 << 3 | 3347104f784Smrg (VDisplay & 0x400) >> 10 << 2 | 3357104f784Smrg (VBlankStart & 0x400) >> 10 << 1 | 3367104f784Smrg (VSyncStart & 0x400) >> 10 << 0; 3377104f784Smrg 3387104f784Smrg if(pSmi->Chipset == SMI_LYNX3DM) 3397104f784Smrg reg->CR30 |= (HTotal & 0x100) >> 8 << 6; 3407104f784Smrg 3417104f784Smrg reg->CR33 = (HBlankEnd & 0xC0) >> 6 << 5 | (VBlankEnd & 0x300) >> 8 << 3; 3427104f784Smrg } 3437104f784Smrg 3447104f784Smrg vgaHWRestore(pScrn, vganew, VGA_SR_MODE); 3457104f784Smrg 3467104f784Smrg VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x30, reg->CR30); 3477104f784Smrg VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33, reg->CR33); 3487104f784Smrg 3497104f784Smrg LEAVE(); 3507104f784Smrg} 3517104f784Smrg 3527104f784Smrgstatic void 3537104f784SmrgSMILynx_CrtcModeSet_crt(xf86CrtcPtr crtc, 3547104f784Smrg DisplayModePtr mode, 3557104f784Smrg DisplayModePtr adjusted_mode, 3567104f784Smrg int x, int y) 3577104f784Smrg{ 3587104f784Smrg ScrnInfoPtr pScrn=crtc->scrn; 3597104f784Smrg SMIPtr pSmi = SMIPTR(pScrn); 3607104f784Smrg SMIRegPtr reg = pSmi->mode; 3617104f784Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 3627104f784Smrg int vgaIOBase = hwp->IOBase; 3637104f784Smrg int vgaCRIndex = vgaIOBase + VGA_CRTC_INDEX_OFFSET; 3647104f784Smrg int vgaCRData = vgaIOBase + VGA_CRTC_DATA_OFFSET; 3657104f784Smrg int i; 3667104f784Smrg 3677104f784Smrg ENTER(); 3687104f784Smrg 3697104f784Smrg /* Initialize Video Processor Registers */ 3707104f784Smrg 3717104f784Smrg SMILynx_CrtcVideoInit_crt(crtc); 3727104f784Smrg SMILynx_CrtcAdjustFrame(crtc, x,y); 3737104f784Smrg 3747104f784Smrg 3757104f784Smrg /* Program the PLL */ 3767104f784Smrg 3777104f784Smrg /* calculate vclk1 */ 3787104f784Smrg if (SMI_LYNX_SERIES(pSmi->Chipset)) { 3797104f784Smrg SMI_CommonCalcClock(pScrn->scrnIndex, adjusted_mode->Clock, 3807104f784Smrg 1, 1, 63, 0, 3, 3817104f784Smrg pSmi->clockRange.minClock, 3827104f784Smrg pSmi->clockRange.maxClock, 3837104f784Smrg ®->SR6C, ®->SR6D); 3847104f784Smrg } else { 3857104f784Smrg SMI_CommonCalcClock(pScrn->scrnIndex, adjusted_mode->Clock, 3867104f784Smrg 1, 1, 63, 0, 1, 3877104f784Smrg pSmi->clockRange.minClock, 3887104f784Smrg pSmi->clockRange.maxClock, 3897104f784Smrg ®->SR6C, ®->SR6D); 3907104f784Smrg } 3917104f784Smrg 3927104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6C, reg->SR6C); 3937104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6D, reg->SR6D); 3947104f784Smrg 3957104f784Smrg 3967104f784Smrg /* Adjust mode timings */ 3977104f784Smrg /* In virtual refresh mode, the CRT timings are controlled through 3987104f784Smrg the shadow VGA registers */ 3997104f784Smrg 4007104f784Smrg { 4017104f784Smrg unsigned long HTotal=(mode->CrtcHTotal>>3)-5; 4027104f784Smrg unsigned long HDisplay=(mode->CrtcHDisplay>>3)-1; 4037104f784Smrg unsigned long HBlankStart=(mode->CrtcHBlankStart>>3)-1; 4047104f784Smrg unsigned long HBlankEnd=(mode->CrtcHBlankEnd>>3)-1; 4057104f784Smrg unsigned long HSyncStart=mode->CrtcHSyncStart>>3; 4067104f784Smrg unsigned long HSyncEnd=mode->CrtcHSyncEnd>>3; 4077104f784Smrg unsigned long VTotal=mode->CrtcVTotal-2; 4087104f784Smrg unsigned long VDisplay=mode->CrtcVDisplay-1; 4097104f784Smrg unsigned long VBlankStart=mode->CrtcVBlankStart-1; 4107104f784Smrg unsigned long VBlankEnd=mode->CrtcVBlankEnd-1; 4117104f784Smrg unsigned long VSyncStart=mode->CrtcVSyncStart; 4127104f784Smrg unsigned long VSyncEnd=mode->CrtcVSyncEnd; 4137104f784Smrg 4147104f784Smrg /* Fix HBlankEnd/VBlankEnd */ 4157104f784Smrg if((mode->CrtcHBlankEnd >> 3) == (mode->CrtcHTotal >> 3)) HBlankEnd=0; 4167104f784Smrg if(mode->CrtcVBlankEnd == mode->CrtcVTotal) VBlankEnd=0; 4177104f784Smrg 4187104f784Smrg reg->CR40 [0x0] = HTotal & 0xFF; 4197104f784Smrg reg->CR40 [0x1] = HBlankStart & 0xFF; 4207104f784Smrg reg->CR40 [0x2] = HBlankEnd & 0x1F; 4217104f784Smrg reg->CR40 [0x3] = HSyncStart & 0xFF; 4227104f784Smrg reg->CR40 [0x4] = (HBlankEnd & 0x20) >> 5 << 7 | 4237104f784Smrg (HSyncEnd & 0x1F); 4247104f784Smrg reg->CR40 [0x5] = VTotal & 0xFF; 4257104f784Smrg reg->CR40 [0x6] = VBlankStart & 0xFF; 4267104f784Smrg reg->CR40 [0x7] = VBlankEnd & 0xFF; 4277104f784Smrg reg->CR40 [0x8] = VSyncStart & 0xFF; 4287104f784Smrg reg->CR40 [0x9] = VSyncEnd & 0x0F; 4297104f784Smrg reg->CR40 [0xA] = (VSyncStart & 0x200) >> 9 << 7 | 4307104f784Smrg (VDisplay & 0x200) >> 9 << 6 | 4317104f784Smrg (VTotal & 0x200) >> 9 << 5 | 4327104f784Smrg (VBlankStart & 0x100) >> 8 << 3 | 4337104f784Smrg (VSyncStart & 0x100) >> 8 << 2 | 4347104f784Smrg (VDisplay & 0x100) >> 8 << 1 | 4357104f784Smrg (VTotal & 0x100) >> 8 << 0; 4367104f784Smrg reg->CR40 [0xB] = ((mode->Flags & V_NVSYNC)?1:0) << 7 | 4377104f784Smrg ((mode->Flags & V_NHSYNC)?1:0) << 6 | 4387104f784Smrg (VBlankStart & 0x200) >> 9 << 5; 4397104f784Smrg reg->CR40 [0xC] = HDisplay & 0xFF; 4407104f784Smrg reg->CR40 [0xD] = VDisplay & 0xFF; 4417104f784Smrg 4427104f784Smrg reg->CR30 = (VTotal & 0x400) >> 10 << 3 | 4437104f784Smrg (VDisplay & 0x400) >> 10 << 2 | 4447104f784Smrg (VBlankStart & 0x400) >> 10 << 1 | 4457104f784Smrg (VSyncStart & 0x400) >> 10 << 0; 4467104f784Smrg 4477104f784Smrg if(pSmi->Chipset == SMI_LYNX3DM) 4487104f784Smrg reg->CR30 |= (HTotal & 0x100) >> 8 << 6; 4497104f784Smrg 4507104f784Smrg reg->CR33 = (HBlankEnd & 0xC0) >> 6 << 5 | (VBlankEnd & 0x300) >> 8 << 3; 4517104f784Smrg 4527104f784Smrg } 4537104f784Smrg 4547104f784Smrg /* Select primary set of shadow registers */ 4557104f784Smrg VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E, reg->CR90[0xE] & ~0x20); 4567104f784Smrg 4577104f784Smrg for(i=0; i <= 0xD; i++) 4587104f784Smrg VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i, reg->CR40[i]); 4597104f784Smrg 4607104f784Smrg VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x30, reg->CR30); 4617104f784Smrg VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33, reg->CR33); 4627104f784Smrg 4637104f784Smrg LEAVE(); 4647104f784Smrg} 4657104f784Smrg 4667104f784Smrgstatic void 4677104f784SmrgSMILynx_CrtcModeSet_lcd(xf86CrtcPtr crtc, 4687104f784Smrg DisplayModePtr mode, 4697104f784Smrg DisplayModePtr adjusted_mode, 4707104f784Smrg int x, int y) 4717104f784Smrg{ 4727104f784Smrg ScrnInfoPtr pScrn=crtc->scrn; 4737104f784Smrg SMIPtr pSmi = SMIPTR(pScrn); 4747104f784Smrg SMIRegPtr reg = pSmi->mode; 4757104f784Smrg 4767104f784Smrg ENTER(); 4777104f784Smrg 4787104f784Smrg /* Initialize the flat panel video processor */ 4797104f784Smrg 4807104f784Smrg SMILynx_CrtcVideoInit_lcd(crtc); 4817104f784Smrg SMILynx_CrtcAdjustFrame(crtc,x,y); 4827104f784Smrg 4837104f784Smrg 4847104f784Smrg /* Program the PLL */ 4857104f784Smrg 4867104f784Smrg /* calculate vclk2 */ 4877104f784Smrg if (SMI_LYNX_SERIES(pSmi->Chipset)) { 4887104f784Smrg SMI_CommonCalcClock(pScrn->scrnIndex, adjusted_mode->Clock, 4897104f784Smrg 1, 1, 63, 0, 0, 4907104f784Smrg pSmi->clockRange.minClock, 4917104f784Smrg pSmi->clockRange.maxClock, 4927104f784Smrg ®->SR6E, ®->SR6F); 4937104f784Smrg } else { 4947104f784Smrg SMI_CommonCalcClock(pScrn->scrnIndex, adjusted_mode->Clock, 4957104f784Smrg 1, 1, 63, 0, 1, 4967104f784Smrg pSmi->clockRange.minClock, 4977104f784Smrg pSmi->clockRange.maxClock, 4987104f784Smrg ®->SR6E, ®->SR6F); 4997104f784Smrg } 5007104f784Smrg 5017104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6E, reg->SR6E); 5027104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6F, reg->SR6F); 5037104f784Smrg 5047104f784Smrg 5057104f784Smrg /* Adjust mode timings */ 5067104f784Smrg { 5077104f784Smrg unsigned long HTotal=(mode->CrtcHTotal>>3)-1; 5087104f784Smrg unsigned long HDisplay=(mode->CrtcHDisplay>>3)-1; 5097104f784Smrg unsigned long HSyncStart=(mode->CrtcHSyncStart>>3); 5107104f784Smrg unsigned long HSyncWidth=((mode->CrtcHSyncEnd - mode->CrtcHSyncStart) >> 3) - 1; 5117104f784Smrg unsigned long VTotal=mode->CrtcVTotal-1; 5127104f784Smrg unsigned long VDisplay=mode->CrtcVDisplay-1; 5137104f784Smrg unsigned long VSyncStart=mode->CrtcVSyncStart-1; 5147104f784Smrg unsigned long VSyncWidth=mode->CrtcVSyncEnd - mode->CrtcVSyncStart - 1; 5157104f784Smrg 5167104f784Smrg reg->SR50 = (VTotal & 0x700) >> 8 << 1 | 5177104f784Smrg (HSyncStart & 0x100) >> 8 << 0; 5187104f784Smrg reg->SR51 = (VSyncStart & 0x700) >> 8 << 5 | 5197104f784Smrg (VDisplay & 0x700) >> 8 << 2 | 5207104f784Smrg (HDisplay & 0x100) >> 8 << 1 | 5217104f784Smrg (HTotal & 0x100) >> 8 << 0; 5227104f784Smrg reg->SR52 = HTotal & 0xFF; 5237104f784Smrg reg->SR53 = HDisplay & 0xFF; 5247104f784Smrg reg->SR54 = HSyncStart & 0xFF; 5257104f784Smrg reg->SR55 = VTotal & 0xFF; 5267104f784Smrg reg->SR56 = VDisplay & 0xFF; 5277104f784Smrg reg->SR57 = VSyncStart & 0xFF; 5287104f784Smrg reg->SR5A = (HSyncWidth & 0x1F) << 3 | 5297104f784Smrg (VSyncWidth & 0x07) << 0; 5307104f784Smrg 5317104f784Smrg /* XXX - Why is the polarity hardcoded here? */ 5327104f784Smrg reg->SR32 &= ~0x18; 5337104f784Smrg if (mode->HDisplay == 800) { 5347104f784Smrg reg->SR32 |= 0x18; 5357104f784Smrg } 5367104f784Smrg if ((mode->HDisplay == 1024) && SMI_LYNXM_SERIES(pSmi->Chipset)) { 5377104f784Smrg reg->SR32 |= 0x18; 5387104f784Smrg } 5397104f784Smrg } 5407104f784Smrg 5417104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x32, reg->SR32); 5427104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x50, reg->SR50); 5437104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x51, reg->SR51); 5447104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x52, reg->SR52); 5457104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x53, reg->SR53); 5467104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x54, reg->SR54); 5477104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x55, reg->SR55); 5487104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x56, reg->SR56); 5497104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x57, reg->SR57); 5507104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x5A, reg->SR5A); 5517104f784Smrg 5527104f784Smrg LEAVE(); 5537104f784Smrg} 5547104f784Smrg 5557104f784Smrgstatic void 5567104f784SmrgSMILynx_CrtcModeSet_bios(xf86CrtcPtr crtc, 5577104f784Smrg DisplayModePtr mode, 5587104f784Smrg DisplayModePtr adjusted_mode, 5597104f784Smrg int x, int y) 5607104f784Smrg{ 5617104f784Smrg ScrnInfoPtr pScrn=crtc->scrn; 5627104f784Smrg SMIPtr pSmi = SMIPTR(pScrn); 5637104f784Smrg SMIRegPtr reg = pSmi->mode; 5647104f784Smrg int i; 5657104f784Smrg CARD8 tmp; 5667104f784Smrg 5677104f784Smrg ENTER(); 568eb3dced6Smacallan#ifdef USE_INT10 5697104f784Smrg /* Find the INT 10 mode number */ 5707104f784Smrg { 5717104f784Smrg static struct { 5727104f784Smrg int x, y, bpp; 5737104f784Smrg CARD16 mode; 5747104f784Smrg } modeTable[] = 5757104f784Smrg { 5767104f784Smrg { 640, 480, 8, 0x50 }, 5777104f784Smrg { 640, 480, 16, 0x52 }, 5787104f784Smrg { 640, 480, 24, 0x53 }, 5797104f784Smrg { 640, 480, 32, 0x54 }, 5807104f784Smrg { 800, 480, 8, 0x4A }, 5817104f784Smrg { 800, 480, 16, 0x4C }, 5827104f784Smrg { 800, 480, 24, 0x4D }, 5837104f784Smrg { 800, 600, 8, 0x55 }, 5847104f784Smrg { 800, 600, 16, 0x57 }, 5857104f784Smrg { 800, 600, 24, 0x58 }, 5867104f784Smrg { 800, 600, 32, 0x59 }, 5877104f784Smrg { 1024, 768, 8, 0x60 }, 5887104f784Smrg { 1024, 768, 16, 0x62 }, 5897104f784Smrg { 1024, 768, 24, 0x63 }, 5907104f784Smrg { 1024, 768, 32, 0x64 }, 5917104f784Smrg { 1280, 1024, 8, 0x65 }, 5927104f784Smrg { 1280, 1024, 16, 0x67 }, 5937104f784Smrg { 1280, 1024, 24, 0x68 }, 5947104f784Smrg { 1280, 1024, 32, 0x69 }, 5957104f784Smrg }; 5967104f784Smrg 5977104f784Smrg reg->mode = 0; 5987104f784Smrg for (i = 0; i < sizeof(modeTable) / sizeof(modeTable[0]); i++) { 5997104f784Smrg if ((modeTable[i].x == mode->HDisplay) && 6007104f784Smrg (modeTable[i].y == mode->VDisplay) && 6017104f784Smrg (modeTable[i].bpp == pScrn->bitsPerPixel)) { 6027104f784Smrg reg->mode = modeTable[i].mode; 6037104f784Smrg break; 6047104f784Smrg } 6057104f784Smrg } 6067104f784Smrg } 607eb3dced6Smacallan#endif 6087104f784Smrg if(!reg->mode){ 6097104f784Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SMILynx_CrtcModeSet_bios: Not a known BIOS mode: " 6107104f784Smrg "falling back to direct modesetting.\n"); 6117104f784Smrg SMILynx_CrtcModeSet_vga(crtc,mode,adjusted_mode,x,y); 6127104f784Smrg LEAVE(); 6137104f784Smrg } 614eb3dced6Smacallan#ifdef USE_INT10 6157104f784Smrg pSmi->pInt10->num = 0x10; 6167104f784Smrg pSmi->pInt10->ax = reg->mode | 0x80; 6177104f784Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting mode 0x%02X\n", 6187104f784Smrg reg->mode); 6197104f784Smrg xf86ExecX86int10(pSmi->pInt10); 6207104f784Smrg 6217104f784Smrg /* Enable linear mode. */ 6227104f784Smrg outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18); 6237104f784Smrg tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA); 6247104f784Smrg outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp | 0x01); 6257104f784Smrg 6267104f784Smrg /* Enable DPR/VPR registers. */ 6277104f784Smrg tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21); 6287104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, tmp & ~0x03); 6297104f784Smrg 6307104f784Smrg 6317104f784Smrg /* Initialize Video Processor Registers */ 6327104f784Smrg 6337104f784Smrg SMICRTC(crtc)->video_init(crtc); 6347104f784Smrg SMILynx_CrtcAdjustFrame(crtc, x,y); 635eb3dced6Smacallan#endif 6367104f784Smrg LEAVE(); 6377104f784Smrg} 6387104f784Smrg 6397104f784Smrgstatic void 6407104f784SmrgSMILynx_CrtcLoadLUT_crt(xf86CrtcPtr crtc) 6417104f784Smrg{ 6427104f784Smrg ScrnInfoPtr pScrn = crtc->scrn; 6437104f784Smrg SMIPtr pSmi = SMIPTR(pScrn); 6447104f784Smrg SMIRegPtr mode = pSmi->mode; 6457104f784Smrg SMICrtcPrivatePtr crtcPriv = SMICRTC(crtc); 6467104f784Smrg int i; 6477104f784Smrg 6487104f784Smrg ENTER(); 6497104f784Smrg 6507104f784Smrg /* Write CRT RAM only */ 6517104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x66,(mode->SR66 & ~0x30) | 0x20); 6527104f784Smrg 6537104f784Smrg for(i=0;i<256;i++){ 6547104f784Smrg VGAOUT8(pSmi, VGA_DAC_WRITE_ADDR, i); 6557104f784Smrg VGAOUT8(pSmi, VGA_DAC_DATA, crtcPriv->lut_r[i] >> 8); 6567104f784Smrg VGAOUT8(pSmi, VGA_DAC_DATA, crtcPriv->lut_g[i] >> 8); 6577104f784Smrg VGAOUT8(pSmi, VGA_DAC_DATA, crtcPriv->lut_b[i] >> 8); 6587104f784Smrg } 6597104f784Smrg 6607104f784Smrg LEAVE(); 6617104f784Smrg} 6627104f784Smrg 6637104f784Smrgstatic void 6647104f784SmrgSMILynx_CrtcLoadLUT_lcd(xf86CrtcPtr crtc) 6657104f784Smrg{ 6667104f784Smrg ENTER(); 6677104f784Smrg 6687104f784Smrg /* XXX - Is it possible to load LCD LUT in Virtual Refresh mode? */ 6697104f784Smrg 6707104f784Smrg LEAVE(); 6717104f784Smrg} 6727104f784Smrg 6737104f784Smrgstatic void 6747104f784SmrgSMILynx_CrtcSetCursorColors_crt (xf86CrtcPtr crtc, int bg, int fg) 6757104f784Smrg{ 6767104f784Smrg ScrnInfoPtr pScrn = crtc->scrn; 6777104f784Smrg SMIPtr pSmi = SMIPTR(pScrn); 6787104f784Smrg CARD8 packedFG,packedBG; 6797104f784Smrg 6807104f784Smrg ENTER(); 6817104f784Smrg 6827104f784Smrg /* Pack the true color into 8 bit */ 6837104f784Smrg packedFG = (fg & 0xE00000) >> 16 | 6847104f784Smrg (fg & 0x00E000) >> 11 | 6857104f784Smrg (fg & 0x0000C0) >> 6; 6867104f784Smrg packedBG = (bg & 0xE00000) >> 16 | 6877104f784Smrg (bg & 0x00E000) >> 11 | 6887104f784Smrg (bg & 0x0000C0) >> 6; 6897104f784Smrg 6907104f784Smrg /* Program the colors */ 6917104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x8C, packedFG); 6927104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x8D, packedBG); 6937104f784Smrg 6947104f784Smrg /* Program FPR copy when on the 730 */ 6957104f784Smrg if (pSmi->Chipset == SMI_COUGAR3DR) { 6967104f784Smrg CARD32 fpr15c; 6977104f784Smrg 6987104f784Smrg fpr15c = READ_FPR(pSmi, FPR15C) & FPR15C_MASK_HWCADDREN; 6997104f784Smrg fpr15c |= packedFG; 7007104f784Smrg fpr15c |= packedBG << 8; 7017104f784Smrg WRITE_FPR(pSmi, FPR15C, fpr15c); 7027104f784Smrg } 7037104f784Smrg 7047104f784Smrg LEAVE(); 7057104f784Smrg} 7067104f784Smrg 7077104f784Smrgstatic void 7087104f784SmrgSMILynx_CrtcSetCursorPosition_crt (xf86CrtcPtr crtc, int x, int y) 7097104f784Smrg{ 7107104f784Smrg ScrnInfoPtr pScrn = crtc->scrn; 7117104f784Smrg SMIPtr pSmi = SMIPTR(pScrn); 7127104f784Smrg 7137104f784Smrg ENTER(); 7147104f784Smrg 7157104f784Smrg if (x >= 0) { 7167104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x88, 7177104f784Smrg x & 0xFF); 7187104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x89, 7197104f784Smrg (x >> 8) & 0x07); 7207104f784Smrg } 7217104f784Smrg else { 7227104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x88, 7237104f784Smrg (-x) & (SMILYNX_MAX_CURSOR - 1)); 7247104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x89, 7257104f784Smrg 0x08); 7267104f784Smrg } 7277104f784Smrg 7287104f784Smrg if (y >= 0) { 7297104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x8A, 7307104f784Smrg y & 0xFF); 7317104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x8B, 7327104f784Smrg (y >> 8) & 0x07); 7337104f784Smrg } 7347104f784Smrg else { 7357104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x8A, 7367104f784Smrg (-y) & (SMILYNX_MAX_CURSOR - 1)); 7377104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 7387104f784Smrg 0x8B, 0x08); 7397104f784Smrg } 7407104f784Smrg 7417104f784Smrg /* Program FPR copy when on the 730 */ 7427104f784Smrg if (pSmi->Chipset == SMI_COUGAR3DR) { 7437104f784Smrg CARD32 fpr158; 7447104f784Smrg 7457104f784Smrg if (x >= 0) 7467104f784Smrg fpr158 = (x & FPR158_MASK_MAXBITS) << 16; 7477104f784Smrg else 7487104f784Smrg fpr158 = ((-x & FPR158_MASK_MAXBITS) | 7497104f784Smrg FPR158_MASK_BOUNDARY) << 16; 7507104f784Smrg 7517104f784Smrg if (y >= 0) 7527104f784Smrg fpr158 |= y & FPR158_MASK_MAXBITS; 7537104f784Smrg else 7547104f784Smrg fpr158 |= (-y & FPR158_MASK_MAXBITS) | FPR158_MASK_BOUNDARY; 7557104f784Smrg 7567104f784Smrg /* Program combined coordinates */ 7577104f784Smrg WRITE_FPR(pSmi, FPR158, fpr158); 7587104f784Smrg } 7597104f784Smrg 7607104f784Smrg LEAVE(); 7617104f784Smrg} 7627104f784Smrg 7637104f784Smrgstatic void 7647104f784SmrgSMILynx_CrtcShowCursor_crt (xf86CrtcPtr crtc) 7657104f784Smrg{ 7667104f784Smrg ScrnInfoPtr pScrn = crtc->scrn; 7677104f784Smrg SMIPtr pSmi = SMIPTR(pScrn); 7687104f784Smrg char tmp; 7697104f784Smrg 7707104f784Smrg ENTER(); 7717104f784Smrg 7727104f784Smrg /* Show cursor */ 7737104f784Smrg tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81); 7747104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81, tmp | 0x80); 7757104f784Smrg 7767104f784Smrg /* Program FPR copy when on the 730 */ 7777104f784Smrg if (pSmi->Chipset == SMI_COUGAR3DR) { 7787104f784Smrg CARD32 fpr15c; 7797104f784Smrg 7807104f784Smrg /* turn on the top bit */ 7817104f784Smrg fpr15c = READ_FPR(pSmi, FPR15C); 7827104f784Smrg fpr15c |= FPR15C_MASK_HWCENABLE; 7837104f784Smrg WRITE_FPR(pSmi, FPR15C, fpr15c); 7847104f784Smrg } 7857104f784Smrg 7867104f784Smrg LEAVE(); 7877104f784Smrg} 7887104f784Smrg 7897104f784Smrgstatic void 7907104f784SmrgSMILynx_CrtcHideCursor_crt (xf86CrtcPtr crtc) 7917104f784Smrg{ 7927104f784Smrg ScrnInfoPtr pScrn = crtc->scrn; 7937104f784Smrg SMIPtr pSmi = SMIPTR(pScrn); 7947104f784Smrg char tmp; 7957104f784Smrg 7967104f784Smrg ENTER(); 7977104f784Smrg 7987104f784Smrg /* Hide cursor */ 7997104f784Smrg tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81); 8007104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81, tmp & ~0x80); 8017104f784Smrg 8027104f784Smrg /* Program FPR copy when on the 730 */ 8037104f784Smrg if (pSmi->Chipset == SMI_COUGAR3DR) { 8047104f784Smrg CARD32 fpr15c; 8057104f784Smrg 8067104f784Smrg /* turn off the top bit */ 8077104f784Smrg fpr15c = READ_FPR(pSmi, FPR15C); 8087104f784Smrg fpr15c &= ~FPR15C_MASK_HWCENABLE; 8097104f784Smrg WRITE_FPR(pSmi, FPR15C, fpr15c); 8107104f784Smrg } 8117104f784Smrg 8127104f784Smrg 8137104f784Smrg LEAVE(); 8147104f784Smrg} 8157104f784Smrg 8167104f784Smrgstatic void 8177104f784SmrgSMILynx_CrtcLoadCursorImage_crt (xf86CrtcPtr crtc, CARD8 *image) 8187104f784Smrg{ 8197104f784Smrg ScrnInfoPtr pScrn = crtc->scrn; 8207104f784Smrg SMIPtr pSmi = SMIPTR(pScrn); 8217104f784Smrg CARD8 tmp; 8227104f784Smrg int i; 8237104f784Smrg CARD8* dst; 8247104f784Smrg 8257104f784Smrg ENTER(); 8267104f784Smrg 8277104f784Smrg /* Load storage location. */ 8287104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x80, 8297104f784Smrg pSmi->FBCursorOffset / 2048); 8307104f784Smrg tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81) & 0x80; 8317104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81, 8327104f784Smrg tmp | ((pSmi->FBCursorOffset / 2048) >> 8)); 8337104f784Smrg 8347104f784Smrg /* Program FPR copy when on the 730 */ 8357104f784Smrg if (pSmi->Chipset == SMI_COUGAR3DR) { 8367104f784Smrg CARD32 fpr15c; 8377104f784Smrg 8387104f784Smrg /* put address in upper word, and disable the cursor */ 8397104f784Smrg fpr15c = READ_FPR(pSmi, FPR15C) & FPR15C_MASK_HWCCOLORS; 8407104f784Smrg fpr15c |= (pSmi->FBCursorOffset / 2048) << 16; 8417104f784Smrg WRITE_FPR(pSmi, FPR15C, fpr15c); 8427104f784Smrg } 8437104f784Smrg 8447104f784Smrg /* Copy cursor image to framebuffer storage */ 8457104f784Smrg dst = pSmi->FBBase + pSmi->FBCursorOffset; 8467104f784Smrg for(i=0; i < (SMILYNX_MAX_CURSOR * SMILYNX_MAX_CURSOR >> 2); i++){ 8477104f784Smrg *(dst++) = image[i]; 8487104f784Smrg if((i & 0x3) == 0x3) dst+=4; 8497104f784Smrg } 8507104f784Smrg 8517104f784Smrg LEAVE(); 8527104f784Smrg} 8537104f784Smrg 8547104f784Smrgstatic void 8557104f784SmrgSMILynx_CrtcDPMS_crt(xf86CrtcPtr crtc, int mode) 8567104f784Smrg{ 8577104f784Smrg ScrnInfoPtr pScrn = crtc->scrn; 8587104f784Smrg SMIPtr pSmi = SMIPTR(pScrn); 8597104f784Smrg SMIRegPtr reg = pSmi->mode; 8607104f784Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 8617104f784Smrg 8627104f784Smrg ENTER(); 8637104f784Smrg 8647104f784Smrg if(mode == DPMSModeOff) 8657104f784Smrg reg->SR21 |= 0x88; /* Disable DAC and color palette RAM */ 8667104f784Smrg else 8677104f784Smrg reg->SR21 &= ~0x88; /* Enable DAC and color palette RAM */ 8687104f784Smrg 8697104f784Smrg /* Wait for vertical retrace */ 8707104f784Smrg while (hwp->readST01(hwp) & 0x8) ; 8717104f784Smrg while (!(hwp->readST01(hwp) & 0x8)) ; 8727104f784Smrg 8737104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, reg->SR21); 8747104f784Smrg 8757104f784Smrg if(mode == DPMSModeOn){ 8767104f784Smrg /* Reload the LUT */ 8777104f784Smrg SMILynx_CrtcLoadLUT_crt(crtc); 8787104f784Smrg } 8797104f784Smrg 8807104f784Smrg LEAVE(); 8817104f784Smrg} 8827104f784Smrg 8837104f784Smrgstatic void 8847104f784SmrgSMILynx_CrtcDPMS_lcd(xf86CrtcPtr crtc, int mode) 8857104f784Smrg{ 8867104f784Smrg ScrnInfoPtr pScrn = crtc->scrn; 8877104f784Smrg SMIPtr pSmi = SMIPTR(pScrn); 8887104f784Smrg SMIRegPtr reg = pSmi->mode; 8897104f784Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 8907104f784Smrg 8917104f784Smrg ENTER(); 8927104f784Smrg 8937104f784Smrg if(mode == DPMSModeOff) 8947104f784Smrg reg->SR31 &= ~0x80; /* Disable Virtual Refresh */ 8957104f784Smrg else 8967104f784Smrg reg->SR31 |= 0x80; /* Enable Virtual Refresh */ 8977104f784Smrg 8987104f784Smrg /* Wait for vertical retrace */ 8997104f784Smrg while (hwp->readST01(hwp) & 0x8) ; 9007104f784Smrg while (!(hwp->readST01(hwp) & 0x8)) ; 9017104f784Smrg 9027104f784Smrg VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31, reg->SR31); 9037104f784Smrg 9047104f784Smrg LEAVE(); 9057104f784Smrg} 9067104f784Smrg 9077104f784SmrgBool 9087104f784SmrgSMILynx_CrtcPreInit(ScrnInfoPtr pScrn) 9097104f784Smrg{ 9107104f784Smrg SMIPtr pSmi = SMIPTR(pScrn); 9117104f784Smrg xf86CrtcPtr crtc; 9127104f784Smrg xf86CrtcFuncsPtr crtcFuncs; 9137104f784Smrg SMICrtcPrivatePtr crtcPriv; 9147104f784Smrg 9157104f784Smrg ENTER(); 9167104f784Smrg 9177104f784Smrg if(pSmi->Chipset == SMI_COUGAR3DR){ 9187104f784Smrg /* XXX - Looking at the datasheet, it seems trivial to add 9197104f784Smrg dualhead support for this chip... Little more than 9207104f784Smrg splitting the WRITE_FPR/WRITE_VPR calls in separate 9217104f784Smrg functions. Has someone access to this hardware? */ 9227104f784Smrg 9237104f784Smrg SMI_CrtcFuncsInit_base(&crtcFuncs, &crtcPriv); 9247104f784Smrg 9257104f784Smrg if(pSmi->useBIOS){ 9267104f784Smrg crtcFuncs->mode_set = SMILynx_CrtcModeSet_bios; 9277104f784Smrg }else{ 9287104f784Smrg crtcFuncs->dpms = SMILynx_CrtcDPMS_crt; 9297104f784Smrg crtcFuncs->mode_set = SMILynx_CrtcModeSet_vga; 9307104f784Smrg } 9317104f784Smrg 9327104f784Smrg crtcFuncs->mode_fixup = SMILynx_CrtcModeFixup; 9337104f784Smrg crtcPriv->adjust_frame = SMILynx_CrtcAdjustFrame; 9347104f784Smrg crtcPriv->video_init = SMI730_CrtcVideoInit; 9357104f784Smrg crtcPriv->load_lut = SMILynx_CrtcLoadLUT_crt; 9367104f784Smrg 9377104f784Smrg if(pSmi->HwCursor){ 9387104f784Smrg crtcFuncs->set_cursor_colors = SMILynx_CrtcSetCursorColors_crt; 9397104f784Smrg crtcFuncs->set_cursor_position = SMILynx_CrtcSetCursorPosition_crt; 9407104f784Smrg crtcFuncs->show_cursor = SMILynx_CrtcShowCursor_crt; 9417104f784Smrg crtcFuncs->hide_cursor = SMILynx_CrtcHideCursor_crt; 9427104f784Smrg crtcFuncs->load_cursor_image = SMILynx_CrtcLoadCursorImage_crt; 9437104f784Smrg } 9447104f784Smrg 9457104f784Smrg if(! (crtc = xf86CrtcCreate(pScrn,crtcFuncs))) 9467104f784Smrg LEAVE(FALSE); 9477104f784Smrg crtc->driver_private = crtcPriv; 9487104f784Smrg }else{ 9497104f784Smrg /* CRTC0 can drive both outputs when virtual refresh is 9507104f784Smrg disabled, and only the VGA output with virtual refresh 9517104f784Smrg enabled. */ 9527104f784Smrg SMI_CrtcFuncsInit_base(&crtcFuncs, &crtcPriv); 9537104f784Smrg 9547104f784Smrg if(pSmi->useBIOS){ 9557104f784Smrg crtcFuncs->mode_set = SMILynx_CrtcModeSet_bios; 9567104f784Smrg }else{ 9577104f784Smrg crtcFuncs->dpms = SMILynx_CrtcDPMS_crt; 9587104f784Smrg 9597104f784Smrg if(pSmi->Dualhead){ 9607104f784Smrg /* The standard VGA CRTC registers get locked in 9617104f784Smrg virtual refresh mode. */ 9627104f784Smrg crtcFuncs->mode_set = SMILynx_CrtcModeSet_crt; 9637104f784Smrg 9647104f784Smrg }else{ 9657104f784Smrg crtcFuncs->mode_set = SMILynx_CrtcModeSet_vga; 9667104f784Smrg } 9677104f784Smrg } 9687104f784Smrg 9697104f784Smrg crtcFuncs->mode_fixup = SMILynx_CrtcModeFixup; 9707104f784Smrg crtcPriv->adjust_frame = SMILynx_CrtcAdjustFrame; 9717104f784Smrg crtcPriv->video_init = SMILynx_CrtcVideoInit_crt; 9727104f784Smrg crtcPriv->load_lut = SMILynx_CrtcLoadLUT_crt; 9737104f784Smrg 9747104f784Smrg if(pSmi->HwCursor){ 9757104f784Smrg crtcFuncs->set_cursor_colors = SMILynx_CrtcSetCursorColors_crt; 9767104f784Smrg crtcFuncs->set_cursor_position = SMILynx_CrtcSetCursorPosition_crt; 9777104f784Smrg crtcFuncs->show_cursor = SMILynx_CrtcShowCursor_crt; 9787104f784Smrg crtcFuncs->hide_cursor = SMILynx_CrtcHideCursor_crt; 9797104f784Smrg crtcFuncs->load_cursor_image = SMILynx_CrtcLoadCursorImage_crt; 9807104f784Smrg } 9817104f784Smrg 9827104f784Smrg if(! (crtc = xf86CrtcCreate(pScrn,crtcFuncs))) 9837104f784Smrg LEAVE(FALSE); 9847104f784Smrg crtc->driver_private = crtcPriv; 9857104f784Smrg 9867104f784Smrg if(pSmi->Dualhead){ 9877104f784Smrg /* CRTC1 drives LCD when enabled. */ 9887104f784Smrg SMI_CrtcFuncsInit_base(&crtcFuncs, &crtcPriv); 9897104f784Smrg crtcFuncs->mode_set = SMILynx_CrtcModeSet_lcd; 9907104f784Smrg crtcFuncs->mode_fixup = SMILynx_CrtcModeFixup; 9917104f784Smrg crtcFuncs->dpms = SMILynx_CrtcDPMS_lcd; 9927104f784Smrg crtcPriv->adjust_frame = SMILynx_CrtcAdjustFrame; 9937104f784Smrg crtcPriv->video_init = SMILynx_CrtcVideoInit_lcd; 9947104f784Smrg crtcPriv->load_lut = SMILynx_CrtcLoadLUT_lcd; 9957104f784Smrg 9967104f784Smrg if(! (crtc = xf86CrtcCreate(pScrn,crtcFuncs))) 9977104f784Smrg LEAVE(FALSE); 9987104f784Smrg crtc->driver_private = crtcPriv; 9997104f784Smrg } 10007104f784Smrg } 10017104f784Smrg 10027104f784Smrg LEAVE(TRUE); 10037104f784Smrg} 10047104f784Smrg 1005