xserver-multidpi/hw/xfree86/ramdac/TI.c
Paulo Cesar Pereira de Andrade 49f77fff14 Rework symbol visibility for easier maintenance
Save in a few special cases, _X_EXPORT should not be used in C source
files. Instead, it should be used in headers, and the proper C source
include that header. Some special cases are symbols that need to be
shared between modules, but not expected to be used by external drivers,
and symbols that are accessible via LoaderSymbol/dlopen.

  This patch also adds conditionally some new sdk header files, depending
on extensions enabled. These files were added to match pattern for
other extensions/modules, that is, have the headers "deciding" symbol
visibility in the sdk. These headers are:
o Xext/panoramiXsrv.h, Xext/panoramiX.h
o fbpict.h (unconditionally)
o vidmodeproc.h
o mioverlay.h (unconditionally, used only by xaa)
o xfixes.h (unconditionally, symbols required by dri2)

  LoaderSymbol and similar functions now don't have different prototypes,
in loaderProcs.h and xf86Module.h, so that both headers can be included,
without the need of defining IN_LOADER.

  xf86NewInputDevice() device prototype readded to xf86Xinput.h, but
not exported (and with a comment about it).
2008-12-03 05:43:34 -02:00

720 lines
24 KiB
C

/*
* 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 );
#ifdef DEBUG
ErrorF( "f_out=%ld f_vco=%.1f n=%d m=%d p=%d\n",
ActualClock, VCO, *rN, *rM, *rP);
#endif
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;
}