720 lines
24 KiB
C
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;
|
|
}
|