/* * Copyright 1998 by Alan Hourihane, Wigan, England. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Alan Hourihane not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. Alan Hourihane makes no representations * about the suitability of this software for any purpose. It is provided * "as is" without express or implied warranty. * * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> * * Modified from IBM.c to support TI RAMDAC routines * by Jens Owen, <jens@tungstengraphics.com>. */ #ifdef HAVE_XORG_CONFIG_H #include <xorg-config.h> #endif #include "xf86.h" #include "xf86_OSproc.h" #include "xf86Cursor.h" #define INIT_TI_RAMDAC_INFO #include "TIPriv.h" #include "xf86RamDacPriv.h" /* The following values are in kHz */ #define TI_MIN_VCO_FREQ 110000 #define TI_MAX_VCO_FREQ 220000 unsigned long TIramdacCalculateMNPForClock( unsigned long RefClock, /* In 100Hz units */ unsigned long ReqClock, /* In 100Hz units */ char IsPixClock, /* boolean, is this the pixel or the sys clock */ unsigned long MinClock, /* Min VCO rating */ unsigned long MaxClock, /* Max VCO rating */ unsigned long *rM, /* M Out */ unsigned long *rN, /* N Out */ unsigned long *rP /* Min P In, P Out */ ) { unsigned long n, p; unsigned long best_m = 0, best_n = 0; double VCO, IntRef = (double)RefClock; double m_err, inc_m, calc_m; unsigned long ActualClock; /* Make sure that MinClock <= ReqClock <= MaxClock */ if ( ReqClock < MinClock) ReqClock = MinClock; if ( ReqClock > MaxClock ) ReqClock = MaxClock; /* * ActualClock = VCO / 2 ^ p * Choose p so that TI_MIN_VCO_FREQ <= VCO <= TI_MAX_VCO_FREQ * Note that since TI_MAX_VCO_FREQ = 2 * TI_MIN_VCO_FREQ * we don't have to bother checking for this maximum limit. */ VCO = (double)ReqClock; for ( p = 0; p < 3 && VCO < TI_MIN_VCO_FREQ; ( p )++ ) VCO *= 2.0; /* * We avoid doing multiplications by ( 65 - n ), * and add an increment instead - this keeps any error small. */ inc_m = VCO / ( IntRef * 8.0 ); /* Initial value of calc_m for the loop */ calc_m = inc_m + inc_m + inc_m; /* Initial amount of error for an integer - impossibly large */ m_err = 2.0; /* Search for the closest INTEGER value of ( 65 - m ) */ for ( n = 3; n <= 25; ( n )++, calc_m += inc_m ) { /* Ignore values of ( 65 - m ) which we can't use */ if ( calc_m < 3.0 || calc_m > 64.0 ) continue; /* * Pick the closest INTEGER (has smallest fractional part). * The optimizer should clean this up for us. */ if (( calc_m - ( int ) calc_m ) < m_err ) { m_err = calc_m - ( int ) calc_m; best_m = ( int ) calc_m; best_n = n; } } /* 65 - ( 65 - x ) = x */ *rM = 65 - best_m; *rN = 65 - best_n; *rP = p; /* Now all the calculations can be completed */ VCO = 8.0 * IntRef * best_m / best_n; ActualClock = VCO / ( 1 << p ); DebugF( "f_out=%ld f_vco=%.1f n=%d m=%d p=%d\n", ActualClock, VCO, *rN, *rM, *rP); return ActualClock; } void TIramdacRestore(ScrnInfoPtr pScrn, RamDacRecPtr ramdacPtr, RamDacRegRecPtr ramdacReg) { int i; unsigned long status; /* Here we pass a short, so that we can evaluate a mask too * So that the mask is the high byte and the data the low byte * Order is important */ TIRESTORE(TIDAC_latch_ctrl); TIRESTORE(TIDAC_true_color_ctrl); TIRESTORE(TIDAC_multiplex_ctrl); TIRESTORE(TIDAC_clock_select); TIRESTORE(TIDAC_palette_page); TIRESTORE(TIDAC_general_ctrl); TIRESTORE(TIDAC_misc_ctrl); /* 0x2A & 0x2B are reserved */ TIRESTORE(TIDAC_key_over_low); TIRESTORE(TIDAC_key_over_high); TIRESTORE(TIDAC_key_red_low); TIRESTORE(TIDAC_key_red_high); TIRESTORE(TIDAC_key_green_low); TIRESTORE(TIDAC_key_green_high); TIRESTORE(TIDAC_key_blue_low); TIRESTORE(TIDAC_key_blue_high); TIRESTORE(TIDAC_key_ctrl); (*ramdacPtr->WriteDAC)(pScrn, TIDAC_clock_ctrl, 0, 0x30); (*ramdacPtr->WriteDAC)(pScrn, TIDAC_clock_ctrl, 0, 0x38); TIRESTORE(TIDAC_clock_ctrl); TIRESTORE(TIDAC_sense_test); TIRESTORE(TIDAC_ind_curs_ctrl); /* only restore clocks if they were valid to begin with */ if (ramdacReg->DacRegs[TIDAC_PIXEL_VALID]) { /* Reset pixel clock */ (*ramdacPtr->WriteDAC)(pScrn, TIDAC_pll_addr, 0, 0x22); (*ramdacPtr->WriteDAC)(pScrn, TIDAC_pll_pixel_data, 0, 0x3c); /* Restore N, M & P values for pixel clocks */ (*ramdacPtr->WriteDAC)(pScrn, TIDAC_pll_addr, 0, 0); (*ramdacPtr->WriteDAC)(pScrn, TIDAC_pll_pixel_data, 0, ramdacReg->DacRegs[TIDAC_PIXEL_N]); (*ramdacPtr->WriteDAC)(pScrn, TIDAC_pll_pixel_data, 0, ramdacReg->DacRegs[TIDAC_PIXEL_M]); (*ramdacPtr->WriteDAC)(pScrn, TIDAC_pll_pixel_data, 0, ramdacReg->DacRegs[TIDAC_PIXEL_P]); /* wait for pixel clock to lock */ i = 1000000; do { status = (*ramdacPtr->ReadDAC)(pScrn, TIDAC_pll_pixel_data); } while ((!(status & 0x40)) && (--i)); if (!(status & 0x40)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Pixel clock setup timed out\n"); return; } } if (ramdacReg->DacRegs[TIDAC_LOOP_VALID]) { /* Reset loop clock */ (*ramdacPtr->WriteDAC)(pScrn, TIDAC_pll_addr, 0, 0x22); (*ramdacPtr->WriteDAC)(pScrn, TIDAC_pll_loop_data, 0, 0x70); /* Restore N, M & P values for pixel clocks */ (*ramdacPtr->WriteDAC)(pScrn, TIDAC_pll_addr, 0, 0); (*ramdacPtr->WriteDAC)(pScrn, TIDAC_pll_loop_data, 0, ramdacReg->DacRegs[TIDAC_LOOP_N]); (*ramdacPtr->WriteDAC)(pScrn, TIDAC_pll_loop_data, 0, ramdacReg->DacRegs[TIDAC_LOOP_M]); (*ramdacPtr->WriteDAC)(pScrn, TIDAC_pll_loop_data, 0, ramdacReg->DacRegs[TIDAC_LOOP_P]); /* wait for loop clock to lock */ i = 1000000; do { status = (*ramdacPtr->ReadDAC)(pScrn, TIDAC_pll_loop_data); } while ((!(status & 0x40)) && (--i)); if (!(status & 0x40)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Loop clock setup timed out\n"); return; } } /* restore palette */ (*ramdacPtr->WriteAddress)(pScrn, 0); #ifndef NOT_DONE for (i=0;i<768;i++) (*ramdacPtr->WriteData)(pScrn, ramdacReg->DAC[i]); #else (*ramdacPtr->WriteData)(pScrn, 0); (*ramdacPtr->WriteData)(pScrn, 0); (*ramdacPtr->WriteData)(pScrn, 0); for (i=0;i<765;i++) (*ramdacPtr->WriteData)(pScrn, 0xff); #endif } void TIramdacSave(ScrnInfoPtr pScrn, RamDacRecPtr ramdacPtr, RamDacRegRecPtr ramdacReg) { int i; (*ramdacPtr->ReadAddress)(pScrn, 0); for (i=0;i<768;i++) ramdacReg->DAC[i] = (*ramdacPtr->ReadData)(pScrn); /* Read back N,M and P values for pixel clock */ (*ramdacPtr->WriteDAC)(pScrn, TIDAC_pll_addr, 0, 0); ramdacReg->DacRegs[TIDAC_PIXEL_N] = (*ramdacPtr->ReadDAC)(pScrn, TIDAC_pll_pixel_data); (*ramdacPtr->WriteDAC)(pScrn, TIDAC_pll_addr, 0, 0x11); ramdacReg->DacRegs[TIDAC_PIXEL_M] = (*ramdacPtr->ReadDAC)(pScrn, TIDAC_pll_pixel_data); (*ramdacPtr->WriteDAC)(pScrn, TIDAC_pll_addr, 0, 0x22); ramdacReg->DacRegs[TIDAC_PIXEL_P] = (*ramdacPtr->ReadDAC)(pScrn, TIDAC_pll_pixel_data); /* Read back N,M and P values for loop clock */ (*ramdacPtr->WriteDAC)(pScrn, TIDAC_pll_addr, 0, 0); ramdacReg->DacRegs[TIDAC_LOOP_N] = (*ramdacPtr->ReadDAC)(pScrn, TIDAC_pll_loop_data); (*ramdacPtr->WriteDAC)(pScrn, TIDAC_pll_addr, 0, 0x11); ramdacReg->DacRegs[TIDAC_LOOP_M] = (*ramdacPtr->ReadDAC)(pScrn, TIDAC_pll_loop_data); (*ramdacPtr->WriteDAC)(pScrn, TIDAC_pll_addr, 0, 0x22); ramdacReg->DacRegs[TIDAC_LOOP_P] = (*ramdacPtr->ReadDAC)(pScrn, TIDAC_pll_loop_data); /* Order is important */ TISAVE(TIDAC_latch_ctrl); TISAVE(TIDAC_true_color_ctrl); TISAVE(TIDAC_multiplex_ctrl); TISAVE(TIDAC_clock_select); TISAVE(TIDAC_palette_page); TISAVE(TIDAC_general_ctrl); TISAVE(TIDAC_misc_ctrl); /* 0x2A & 0x2B are reserved */ TISAVE(TIDAC_key_over_low); TISAVE(TIDAC_key_over_high); TISAVE(TIDAC_key_red_low); TISAVE(TIDAC_key_red_high); TISAVE(TIDAC_key_green_low); TISAVE(TIDAC_key_green_high); TISAVE(TIDAC_key_blue_low); TISAVE(TIDAC_key_blue_high); TISAVE(TIDAC_key_ctrl); TISAVE(TIDAC_clock_ctrl); TISAVE(TIDAC_sense_test); TISAVE(TIDAC_ind_curs_ctrl); } RamDacHelperRecPtr TIramdacProbe(ScrnInfoPtr pScrn, RamDacSupportedInfoRecPtr ramdacs) { RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn); RamDacHelperRecPtr ramdacHelperPtr = NULL; Bool RamDacIsSupported = FALSE; int TIramdac_ID = -1; int i; unsigned char id, rev, rev2, id2; /* read ID and revision */ rev = (*ramdacPtr->ReadDAC)(pScrn, TIDAC_rev); id = (*ramdacPtr->ReadDAC)(pScrn, TIDAC_id); /* check if ID and revision are read only */ (*ramdacPtr->WriteDAC)(pScrn, ~rev, 0, TIDAC_rev); (*ramdacPtr->WriteDAC)(pScrn, ~id, 0, TIDAC_id); rev2 = (*ramdacPtr->ReadDAC)(pScrn, TIDAC_rev); id2 = (*ramdacPtr->ReadDAC)(pScrn, TIDAC_id); switch (id) { case TIDAC_TVP_3030_ID: if (id == id2 && rev == rev2) /* check for READ ONLY */ TIramdac_ID = TI3030_RAMDAC; break; case TIDAC_TVP_3026_ID: if (id == id2 && rev == rev2) /* check for READ ONLY */ TIramdac_ID = TI3026_RAMDAC; break; } (*ramdacPtr->WriteDAC)(pScrn, rev, 0, TIDAC_rev); (*ramdacPtr->WriteDAC)(pScrn, id, 0, TIDAC_id); if (TIramdac_ID == -1) { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Cannot determine TI RAMDAC type, aborting\n"); return NULL; } else { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Attached RAMDAC is %s\n", TIramdacDeviceInfo[TIramdac_ID&0xFFFF].DeviceName); } for (i=0;ramdacs[i].token != -1;i++) { if (ramdacs[i].token == TIramdac_ID) RamDacIsSupported = TRUE; } if (!RamDacIsSupported) { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "This TI RAMDAC is NOT supported by this driver, aborting\n"); return NULL; } ramdacHelperPtr = RamDacHelperCreateInfoRec(); switch (TIramdac_ID) { case TI3030_RAMDAC: ramdacHelperPtr->SetBpp = TIramdac3030SetBpp; ramdacHelperPtr->HWCursorInit = TIramdacHWCursorInit; break; case TI3026_RAMDAC: ramdacHelperPtr->SetBpp = TIramdac3026SetBpp; ramdacHelperPtr->HWCursorInit = TIramdacHWCursorInit; break; } ramdacPtr->RamDacType = TIramdac_ID; ramdacHelperPtr->RamDacType = TIramdac_ID; ramdacHelperPtr->Save = TIramdacSave; ramdacHelperPtr->Restore = TIramdacRestore; return ramdacHelperPtr; } void TIramdac3026SetBpp(ScrnInfoPtr pScrn, RamDacRegRecPtr ramdacReg) { switch (pScrn->bitsPerPixel) { case 32: /* order is important */ ramdacReg->DacRegs[TIDAC_latch_ctrl] = 0x06; ramdacReg->DacRegs[TIDAC_true_color_ctrl] = 0x46; ramdacReg->DacRegs[TIDAC_multiplex_ctrl] = 0x5c; ramdacReg->DacRegs[TIDAC_clock_select] = 0x05; ramdacReg->DacRegs[TIDAC_palette_page] = 0x00; ramdacReg->DacRegs[TIDAC_general_ctrl] = 0x10; ramdacReg->DacRegs[TIDAC_misc_ctrl] = 0x3C; /* 0x2A & 0x2B are reserved */ ramdacReg->DacRegs[TIDAC_key_over_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_over_high] = 0xFF; ramdacReg->DacRegs[TIDAC_key_red_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_red_high] = 0xFF; ramdacReg->DacRegs[TIDAC_key_green_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_green_high] = 0xFF; ramdacReg->DacRegs[TIDAC_key_blue_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_blue_high] = 0x00; ramdacReg->DacRegs[TIDAC_key_ctrl] = 0x10; ramdacReg->DacRegs[TIDAC_sense_test] = 0x00; if (pScrn->overlayFlags & OVERLAY_8_32_PLANAR) { ramdacReg->DacRegs[TIDAC_true_color_ctrl] = 0x06; ramdacReg->DacRegs[TIDAC_misc_ctrl] = 0x3C; ramdacReg->DacRegs[TIDAC_key_ctrl] = 0x01; } ramdacReg->DacRegs[TIDAC_ind_curs_ctrl] = 0x00; break; case 24: /* order is important */ ramdacReg->DacRegs[TIDAC_latch_ctrl] = 0x06; ramdacReg->DacRegs[TIDAC_true_color_ctrl] = 0x56; ramdacReg->DacRegs[TIDAC_multiplex_ctrl] = 0x58; ramdacReg->DacRegs[TIDAC_clock_select] = 0x25; ramdacReg->DacRegs[TIDAC_palette_page] = 0x00; ramdacReg->DacRegs[TIDAC_general_ctrl] = 0x00; ramdacReg->DacRegs[TIDAC_misc_ctrl] = 0x2C; /* 0x2A & 0x2B are reserved */ ramdacReg->DacRegs[TIDAC_key_over_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_over_high] = 0xFF; ramdacReg->DacRegs[TIDAC_key_red_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_red_high] = 0xFF; ramdacReg->DacRegs[TIDAC_key_green_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_green_high] = 0xFF; ramdacReg->DacRegs[TIDAC_key_blue_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_blue_high] = 0x00; ramdacReg->DacRegs[TIDAC_key_ctrl] = 0x10; ramdacReg->DacRegs[TIDAC_sense_test] = 0x00; ramdacReg->DacRegs[TIDAC_ind_curs_ctrl] = 0x00; break; case 16: /* order is important */ #if 0 /* Matrox driver uses this */ ramdacReg->DacRegs[TIDAC_latch_ctrl] = 0x07; #else ramdacReg->DacRegs[TIDAC_latch_ctrl] = 0x06; #endif if (pScrn->depth == 16) { ramdacReg->DacRegs[TIDAC_true_color_ctrl] = 0x45; } else { ramdacReg->DacRegs[TIDAC_true_color_ctrl] = 0x44; } #if 0 /* Matrox driver uses this */ ramdacReg->DacRegs[TIDAC_multiplex_ctrl] = 0x50; ramdacReg->DacRegs[TIDAC_clock_select] = 0x15; ramdacReg->DacRegs[TIDAC_palette_page] = 0x00; ramdacReg->DacRegs[TIDAC_general_ctrl] = 0x00; #else ramdacReg->DacRegs[TIDAC_multiplex_ctrl] = 0x54; ramdacReg->DacRegs[TIDAC_clock_select] = 0x05; ramdacReg->DacRegs[TIDAC_palette_page] = 0x00; ramdacReg->DacRegs[TIDAC_general_ctrl] = 0x10; #endif ramdacReg->DacRegs[TIDAC_misc_ctrl] = 0x2C; /* 0x2A & 0x2B are reserved */ ramdacReg->DacRegs[TIDAC_key_over_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_over_high] = 0xFF; ramdacReg->DacRegs[TIDAC_key_red_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_red_high] = 0xFF; ramdacReg->DacRegs[TIDAC_key_green_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_green_high] = 0xFF; ramdacReg->DacRegs[TIDAC_key_blue_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_blue_high] = 0x00; ramdacReg->DacRegs[TIDAC_key_ctrl] = 0x10; ramdacReg->DacRegs[TIDAC_sense_test] = 0x00; ramdacReg->DacRegs[TIDAC_ind_curs_ctrl] = 0x00; break; case 8: /* order is important */ ramdacReg->DacRegs[TIDAC_latch_ctrl] = 0x06; ramdacReg->DacRegs[TIDAC_true_color_ctrl] = 0x80; ramdacReg->DacRegs[TIDAC_multiplex_ctrl] = 0x4c; ramdacReg->DacRegs[TIDAC_clock_select] = 0x05; ramdacReg->DacRegs[TIDAC_palette_page] = 0x00; ramdacReg->DacRegs[TIDAC_general_ctrl] = 0x10; ramdacReg->DacRegs[TIDAC_misc_ctrl] = 0x1C; /* 0x2A & 0x2B are reserved */ ramdacReg->DacRegs[TIDAC_key_over_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_over_high] = 0xFF; ramdacReg->DacRegs[TIDAC_key_red_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_red_high] = 0xFF; ramdacReg->DacRegs[TIDAC_key_green_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_green_high] = 0xFF; ramdacReg->DacRegs[TIDAC_key_blue_low] = 0x00; ramdacReg->DacRegs[TIDAC_key_blue_high] = 0x00; ramdacReg->DacRegs[TIDAC_key_ctrl] = 0x00; ramdacReg->DacRegs[TIDAC_sense_test] = 0x00; ramdacReg->DacRegs[TIDAC_ind_curs_ctrl] = 0x00; break; } } void TIramdac3030SetBpp(ScrnInfoPtr pScrn, RamDacRegRecPtr ramdacReg) { switch (pScrn->bitsPerPixel) { case 32: /* order is important */ ramdacReg->DacRegs[TIDAC_latch_ctrl] = 0x06; ramdacReg->DacRegs[TIDAC_true_color_ctrl] = 0x46; ramdacReg->DacRegs[TIDAC_multiplex_ctrl] = 0x5D; ramdacReg->DacRegs[TIDAC_clock_select] = 0x05; ramdacReg->DacRegs[TIDAC_palette_page] = 0x00; ramdacReg->DacRegs[TIDAC_general_ctrl] = 0x10; ramdacReg->DacRegs[TIDAC_misc_ctrl] = 0x3C; /* 0x2A & 0x2B are reserved */ ramdacReg->DacRegs[TIDAC_key_over_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_over_high] = 0xFF; ramdacReg->DacRegs[TIDAC_key_red_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_red_high] = 0xFF; ramdacReg->DacRegs[TIDAC_key_green_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_green_high] = 0xFF; ramdacReg->DacRegs[TIDAC_key_blue_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_blue_high] = 0x00; ramdacReg->DacRegs[TIDAC_key_ctrl] = 0x10; ramdacReg->DacRegs[TIDAC_sense_test] = 0x00; if (pScrn->overlayFlags & OVERLAY_8_32_PLANAR) { ramdacReg->DacRegs[TIDAC_true_color_ctrl] = 0x06; ramdacReg->DacRegs[TIDAC_misc_ctrl] = 0x3C; ramdacReg->DacRegs[TIDAC_key_ctrl] = 0x01; } ramdacReg->DacRegs[TIDAC_ind_curs_ctrl] = 0x00; break; case 24: /* order is important */ ramdacReg->DacRegs[TIDAC_latch_ctrl] = 0x06; ramdacReg->DacRegs[TIDAC_true_color_ctrl] = 0x56; ramdacReg->DacRegs[TIDAC_multiplex_ctrl] = 0x58; ramdacReg->DacRegs[TIDAC_clock_select] = 0x25; ramdacReg->DacRegs[TIDAC_palette_page] = 0x00; ramdacReg->DacRegs[TIDAC_general_ctrl] = 0x00; ramdacReg->DacRegs[TIDAC_misc_ctrl] = 0x2C; /* 0x2A & 0x2B are reserved */ ramdacReg->DacRegs[TIDAC_key_over_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_over_high] = 0xFF; ramdacReg->DacRegs[TIDAC_key_red_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_red_high] = 0xFF; ramdacReg->DacRegs[TIDAC_key_green_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_green_high] = 0xFF; ramdacReg->DacRegs[TIDAC_key_blue_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_blue_high] = 0x00; ramdacReg->DacRegs[TIDAC_key_ctrl] = 0x10; ramdacReg->DacRegs[TIDAC_sense_test] = 0x00; ramdacReg->DacRegs[TIDAC_ind_curs_ctrl] = 0x00; break; case 16: /* order is important */ #if 0 /* Matrox driver uses this */ ramdacReg->DacRegs[TIDAC_latch_ctrl] = 0x07; #else ramdacReg->DacRegs[TIDAC_latch_ctrl] = 0x06; #endif if (pScrn->depth == 16) { ramdacReg->DacRegs[TIDAC_true_color_ctrl] = 0x45; } else { ramdacReg->DacRegs[TIDAC_true_color_ctrl] = 0x44; } #if 0 /* Matrox driver uses this */ ramdacReg->DacRegs[TIDAC_multiplex_ctrl] = 0x50; ramdacReg->DacRegs[TIDAC_clock_select] = 0x15; ramdacReg->DacRegs[TIDAC_palette_page] = 0x00; ramdacReg->DacRegs[TIDAC_general_ctrl] = 0x00; #else ramdacReg->DacRegs[TIDAC_multiplex_ctrl] = 0x55; ramdacReg->DacRegs[TIDAC_clock_select] = 0x85; ramdacReg->DacRegs[TIDAC_palette_page] = 0x00; ramdacReg->DacRegs[TIDAC_general_ctrl] = 0x10; #endif ramdacReg->DacRegs[TIDAC_misc_ctrl] = 0x2C; /* 0x2A & 0x2B are reserved */ ramdacReg->DacRegs[TIDAC_key_over_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_over_high] = 0xFF; ramdacReg->DacRegs[TIDAC_key_red_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_red_high] = 0xFF; ramdacReg->DacRegs[TIDAC_key_green_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_green_high] = 0xFF; ramdacReg->DacRegs[TIDAC_key_blue_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_blue_high] = 0x00; ramdacReg->DacRegs[TIDAC_key_ctrl] = 0x10; ramdacReg->DacRegs[TIDAC_sense_test] = 0x00; ramdacReg->DacRegs[TIDAC_ind_curs_ctrl] = 0x00; break; case 8: /* order is important */ ramdacReg->DacRegs[TIDAC_latch_ctrl] = 0x06; ramdacReg->DacRegs[TIDAC_true_color_ctrl] = 0x80; ramdacReg->DacRegs[TIDAC_multiplex_ctrl] = 0x4d; ramdacReg->DacRegs[TIDAC_clock_select] = 0x05; ramdacReg->DacRegs[TIDAC_palette_page] = 0x00; ramdacReg->DacRegs[TIDAC_general_ctrl] = 0x10; ramdacReg->DacRegs[TIDAC_misc_ctrl] = 0x1C; /* 0x2A & 0x2B are reserved */ ramdacReg->DacRegs[TIDAC_key_over_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_over_high] = 0xFF; ramdacReg->DacRegs[TIDAC_key_red_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_red_high] = 0xFF; ramdacReg->DacRegs[TIDAC_key_green_low] = 0xFF; ramdacReg->DacRegs[TIDAC_key_green_high] = 0xFF; ramdacReg->DacRegs[TIDAC_key_blue_low] = 0x00; ramdacReg->DacRegs[TIDAC_key_blue_high] = 0x00; ramdacReg->DacRegs[TIDAC_key_ctrl] = 0x00; ramdacReg->DacRegs[TIDAC_sense_test] = 0x00; ramdacReg->DacRegs[TIDAC_ind_curs_ctrl] = 0x00; break; } } static void TIramdacShowCursor(ScrnInfoPtr pScrn) { RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn); /* Enable cursor - X11 mode */ (*ramdacPtr->WriteDAC)(pScrn, TIDAC_ind_curs_ctrl, 0, 0x03); } static void TIramdacHideCursor(ScrnInfoPtr pScrn) { RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn); /* Disable cursor - X11 mode */ (*ramdacPtr->WriteDAC)(pScrn, TIDAC_ind_curs_ctrl, 0, 0x00); } static void TIramdacSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) { RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn); x += 64; y += 64; (*ramdacPtr->WriteDAC)(pScrn, TIDAC_CURS_XLOW, 0, x & 0xff); (*ramdacPtr->WriteDAC)(pScrn, TIDAC_CURS_XHIGH, 0, (x >> 8) & 0x0f); (*ramdacPtr->WriteDAC)(pScrn, TIDAC_CURS_YLOW, 0, y & 0xff); (*ramdacPtr->WriteDAC)(pScrn, TIDAC_CURS_YHIGH, 0, (y >> 8) & 0x0f); } static void TIramdacSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) { RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn); /* Background color */ (*ramdacPtr->WriteDAC)(pScrn, TIDAC_CURS_WRITE_ADDR, 0, 1); (*ramdacPtr->WriteDAC)(pScrn, TIDAC_CURS_COLOR, 0, ((bg&0x00ff0000) >> 16)); (*ramdacPtr->WriteDAC)(pScrn, TIDAC_CURS_COLOR, 0, ((bg&0x0000ff00) >> 8)); (*ramdacPtr->WriteDAC)(pScrn, TIDAC_CURS_COLOR, 0, (bg&0x000000ff) ); /* Foreground color */ (*ramdacPtr->WriteDAC)(pScrn, TIDAC_CURS_WRITE_ADDR, 0, 2); (*ramdacPtr->WriteDAC)(pScrn, TIDAC_CURS_COLOR, 0, ((fg&0x00ff0000) >> 16)); (*ramdacPtr->WriteDAC)(pScrn, TIDAC_CURS_COLOR, 0, ((fg&0x0000ff00) >> 8)); (*ramdacPtr->WriteDAC)(pScrn, TIDAC_CURS_COLOR, 0, (fg&0x000000ff) ); } static void TIramdacLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) { RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn); int i = 1024; /* reset A9,A8 */ (*ramdacPtr->WriteDAC)(pScrn, TIDAC_ind_curs_ctrl, 0, 0x00); /* reset cursor RAM load address A7..A0 */ (*ramdacPtr->WriteDAC)(pScrn, TIDAC_INDEX, 0x00, 0x00); while(i--) { /* NOT_DONE: might need a delay here */ (*ramdacPtr->WriteDAC)(pScrn, TIDAC_CURS_RAM_DATA, 0, *(src++)); } } static Bool TIramdacUseHWCursor(ScreenPtr pScr, CursorPtr pCurs) { return TRUE; } void TIramdacHWCursorInit(xf86CursorInfoPtr infoPtr) { infoPtr->MaxWidth = 64; infoPtr->MaxHeight = 64; infoPtr->Flags = HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | HARDWARE_CURSOR_SOURCE_MASK_NOT_INTERLEAVED; infoPtr->SetCursorColors = TIramdacSetCursorColors; infoPtr->SetCursorPosition = TIramdacSetCursorPosition; infoPtr->LoadCursorImage = TIramdacLoadCursorImage; infoPtr->HideCursor = TIramdacHideCursor; infoPtr->ShowCursor = TIramdacShowCursor; infoPtr->UseHWCursor = TIramdacUseHWCursor; } void TIramdacLoadPalette( ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, VisualPtr pVisual ){ RamDacRecPtr hwp = RAMDACSCRPTR(pScrn); int i, index, shift; if (pScrn->depth == 16) { for(i = 0; i < numColors; i++) { index = indices[i]; (*hwp->WriteAddress)(pScrn, index << 2); (*hwp->WriteData)(pScrn, colors[index >> 1].red); (*hwp->WriteData)(pScrn, colors[index].green); (*hwp->WriteData)(pScrn, colors[index >> 1].blue); if(index <= 31) { (*hwp->WriteAddress)(pScrn, index << 3); (*hwp->WriteData)(pScrn, colors[index].red); (*hwp->WriteData)(pScrn, colors[(index << 1) + 1].green); (*hwp->WriteData)(pScrn, colors[index].blue); } } } else { shift = (pScrn->depth == 15) ? 3 : 0; for(i = 0; i < numColors; i++) { index = indices[i]; (*hwp->WriteAddress)(pScrn, index << shift); (*hwp->WriteData)(pScrn, colors[index].red); (*hwp->WriteData)(pScrn, colors[index].green); (*hwp->WriteData)(pScrn, colors[index].blue); } } } TIramdacLoadPaletteProc *TIramdacLoadPaletteWeak(void) { return TIramdacLoadPalette; }