eb05615134
mibstore.h defines miInitializeBackingStore() as an empty stub, and goes away in xserver 1.14.
1022 lines
28 KiB
C
1022 lines
28 KiB
C
/* Copyright (c) 2003-2008 Advanced Micro Devices, Inc.
|
|
*
|
|
* Portioned modeled from xf86-video-intel/src/i830_driver.c
|
|
* Copyright 2001 VA Linux Systems Inc., Fremont, California.
|
|
* Copyright \ufffd 2002 by David Dawes
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to
|
|
* deal in the Software without restriction, including without limitation the
|
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
* sell copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
* IN THE SOFTWARE.
|
|
*
|
|
* Neither the name of the Advanced Micro Devices, Inc. nor the names of its
|
|
* contributors may be used to endorse or promote products derived from this
|
|
* software without specific prior written permission.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "xf86.h"
|
|
#include "xf86_OSproc.h"
|
|
#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
|
|
#include "xf86Resources.h"
|
|
#endif
|
|
#include "xf86i2c.h"
|
|
#include "xf86Crtc.h"
|
|
#include "xf86cmap.h"
|
|
#include "compiler.h"
|
|
#include "mipointer.h"
|
|
#include "fb.h"
|
|
#include "miscstruct.h"
|
|
#include "micmap.h"
|
|
#include "vbe.h"
|
|
#include "fb.h"
|
|
#include "cim_defs.h"
|
|
#include "cim_regs.h"
|
|
#include "geode.h"
|
|
|
|
/* Bring in VGA functions */
|
|
#include "lx_vga.c"
|
|
|
|
#define LX_MAX_WIDTH 1940
|
|
#define LX_MAX_HEIGHT 1600
|
|
|
|
/* Size of the register blocks */
|
|
|
|
#define LX_GP_REG_SIZE 0x4000
|
|
#define LX_VG_REG_SIZE 0x4000
|
|
#define LX_VID_REG_SIZE 0x4000
|
|
#define LX_VIP_REG_SIZE 0x4000
|
|
|
|
/* Size of the Cimarron command buffer */
|
|
#define CIM_CMD_BFR_SZ 0x200000
|
|
|
|
extern OptionInfoRec LX_GeodeOptions[];
|
|
|
|
unsigned char *XpressROMPtr;
|
|
|
|
static Bool
|
|
LXSaveScreen(ScreenPtr pScrn, int mode)
|
|
{
|
|
ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
|
|
GeodePtr pGeode = GEODEPTR(pScrni);
|
|
|
|
if (pGeode->useVGA && !pScrni->vtSema)
|
|
return vgaHWSaveScreen(pScrn, mode);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* This is an overly complex MSR read mechanism */
|
|
|
|
/* From Cimarron - the VSAII read/write methods - we use these as fallback */
|
|
|
|
#define LX_MSR_READ(adr,lo,hi) \
|
|
__asm__ __volatile__( \
|
|
" mov $0x0AC1C, %%edx\n" \
|
|
" mov $0xFC530007, %%eax\n" \
|
|
" out %%eax,%%dx\n" \
|
|
" add $2,%%dl\n" \
|
|
" in %%dx, %%ax" \
|
|
: "=a" (lo), "=d" (hi) \
|
|
: "c" (adr))
|
|
|
|
#define LX_MSR_WRITE(adr,low,high) \
|
|
{ int d0, d1, d2, d3, d4; \
|
|
__asm__ __volatile__( \
|
|
" push %%ebx\n" \
|
|
" mov $0x0AC1C, %%edx\n" \
|
|
" mov $0xFC530007, %%eax\n" \
|
|
" out %%eax,%%dx\n" \
|
|
" add $2,%%dl\n" \
|
|
" mov %6, %%ebx\n" \
|
|
" mov %7, %0\n" \
|
|
" mov %5, %3\n" \
|
|
" xor %2, %2\n" \
|
|
" xor %1, %1\n" \
|
|
" out %%ax, %%dx\n" \
|
|
" pop %%ebx\n" \
|
|
: "=a"(d0),"=&D"(d1),"=&S"(d2), \
|
|
"=c"(d3),"=d"(d4) \
|
|
: "1"(adr),"2"(high),"3"(low)); \
|
|
}
|
|
|
|
static void
|
|
LXReadMSR(unsigned long addr, unsigned long *lo, unsigned long *hi)
|
|
{
|
|
if (GeodeReadMSR(addr, lo, hi) == -1) {
|
|
unsigned int l, h;
|
|
|
|
LX_MSR_READ(addr, l, h);
|
|
*lo = l;
|
|
*hi = h;
|
|
}
|
|
}
|
|
|
|
static void
|
|
LXWriteMSR(unsigned long addr, unsigned long lo, unsigned long hi)
|
|
{
|
|
if (GeodeWriteMSR(addr, lo, hi) == -1)
|
|
LX_MSR_WRITE(addr, lo, hi);
|
|
}
|
|
|
|
static unsigned int
|
|
LXCalcPitch(ScrnInfoPtr pScrni)
|
|
{
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
|
|
if (pGeode->tryCompression)
|
|
return GeodeCalculatePitchBytes(pScrni->virtualX, pScrni->bitsPerPixel);
|
|
else
|
|
return ((pScrni->virtualX + 3) & ~3) * (pScrni->bitsPerPixel >> 3);
|
|
}
|
|
|
|
#ifdef XSERVER_LIBPCIACCESS
|
|
static inline void *
|
|
map_pci_mem(ScrnInfoPtr pScrni, int vram,
|
|
struct pci_device *dev, int bar, int size)
|
|
{
|
|
void *ptr;
|
|
void **result = (void **) &ptr;
|
|
int map_size = size ? size : dev->regions[bar].size;
|
|
|
|
int err = pci_device_map_range(dev,
|
|
dev->regions[bar].base_addr,
|
|
map_size,
|
|
PCI_DEV_MAP_FLAG_WRITABLE |
|
|
(vram ? PCI_DEV_MAP_FLAG_WRITE_COMBINE : 0),
|
|
result);
|
|
|
|
if (err)
|
|
return NULL;
|
|
return ptr;
|
|
}
|
|
|
|
static inline int
|
|
unmap_pci_mem(ScrnInfoPtr pScrni, struct pci_device *dev, void *ptr, int size)
|
|
{
|
|
return pci_device_unmap_range(dev, ptr, size);
|
|
}
|
|
|
|
#endif
|
|
|
|
static Bool
|
|
LXMapMem(ScrnInfoPtr pScrni)
|
|
{
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
int index = pScrni->scrnIndex;
|
|
unsigned long cmd_bfr_phys;
|
|
|
|
pciVideoPtr pci = xf86GetPciInfoForEntity(pGeode->pEnt->index);
|
|
|
|
#ifndef XSERVER_LIBPCIACCESS
|
|
PCITAG tag;
|
|
|
|
tag = pciTag(pci->bus, pci->device, pci->func);
|
|
|
|
cim_gp_ptr = (unsigned char *) xf86MapPciMem(index, VIDMEM_MMIO,
|
|
tag, pci->memBase[1],
|
|
LX_GP_REG_SIZE);
|
|
|
|
cim_vg_ptr = (unsigned char *) xf86MapPciMem(index, VIDMEM_MMIO,
|
|
tag, pci->memBase[2],
|
|
LX_VG_REG_SIZE);
|
|
|
|
cim_vid_ptr = (unsigned char *) xf86MapPciMem(index, VIDMEM_MMIO,
|
|
tag, pci->memBase[3],
|
|
LX_VID_REG_SIZE);
|
|
|
|
cim_vip_ptr = (unsigned char *) xf86MapPciMem(index, VIDMEM_MMIO,
|
|
tag, pci->memBase[4],
|
|
LX_VIP_REG_SIZE);
|
|
|
|
cim_fb_ptr = (unsigned char *) xf86MapPciMem(index, VIDMEM_FRAMEBUFFER,
|
|
tag, pci->memBase[0],
|
|
pGeode->FBAvail +
|
|
CIM_CMD_BFR_SZ);
|
|
#else
|
|
cim_gp_ptr = map_pci_mem(pScrni, 0, pci, 1, LX_GP_REG_SIZE);
|
|
cim_vg_ptr = map_pci_mem(pScrni, 0, pci, 2, LX_VG_REG_SIZE);
|
|
cim_vid_ptr = map_pci_mem(pScrni, 0, pci, 3, LX_VID_REG_SIZE);
|
|
cim_vip_ptr = map_pci_mem(pScrni, 0, pci, 4, LX_VIP_REG_SIZE);
|
|
cim_fb_ptr =
|
|
map_pci_mem(pScrni, 1, pci, 0, pGeode->FBAvail + CIM_CMD_BFR_SZ);
|
|
#endif
|
|
|
|
if (pScrni->memPhysBase == 0)
|
|
pScrni->memPhysBase = PCI_REGION_BASE(pci, 0, REGION_MEM);
|
|
|
|
cmd_bfr_phys = PCI_REGION_BASE(pci, 0, REGION_MEM) + pGeode->CmdBfrOffset;
|
|
cim_cmd_base_ptr = cim_fb_ptr + pGeode->CmdBfrOffset;
|
|
|
|
if (!cim_gp_ptr || !cim_vg_ptr || !cim_vid_ptr || !cim_fb_ptr ||
|
|
!cim_vip_ptr)
|
|
return FALSE;
|
|
|
|
gp_set_frame_buffer_base(PCI_REGION_BASE(pci, 0, REGION_MEM),
|
|
pGeode->FBAvail);
|
|
gp_set_command_buffer_base(cmd_bfr_phys, 0, pGeode->CmdBfrSize);
|
|
|
|
XpressROMPtr = xf86MapVidMem(index, VIDMEM_FRAMEBUFFER, 0xF0000, 0x10000);
|
|
|
|
pGeode->FBBase = cim_fb_ptr;
|
|
|
|
if (!pGeode->NoAccel)
|
|
pGeode->pExa->memoryBase = pGeode->FBBase;
|
|
|
|
xf86DrvMsg(index, X_INFO, "Geode LX video memory %x bytes at %p\n",
|
|
pGeode->FBAvail, pGeode->FBBase);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* Check to see if VGA exists - we map the space and look for a
|
|
signature - if it doesn't match exactly, then we assume no VGA.
|
|
*/
|
|
|
|
static Bool
|
|
LXCheckVGA(ScrnInfoPtr pScrni)
|
|
{
|
|
|
|
unsigned char *ptr;
|
|
const char *vgasig = "IBM VGA Compatible";
|
|
int ret;
|
|
|
|
ptr =
|
|
xf86MapVidMem(pScrni->scrnIndex, VIDMEM_FRAMEBUFFER, 0xC001E,
|
|
strlen(vgasig));
|
|
|
|
if (ptr == NULL)
|
|
return FALSE;
|
|
|
|
ret = memcmp(ptr, vgasig, strlen(vgasig));
|
|
xf86UnMapVidMem(pScrni->scrnIndex, (pointer) ptr, strlen(vgasig));
|
|
|
|
return ret ? FALSE : TRUE;
|
|
}
|
|
|
|
static Bool
|
|
LXCrtcResize(ScrnInfoPtr pScrni, int width, int height)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
static const xf86CrtcConfigFuncsRec lx_xf86crtc_config_funcs = {
|
|
LXCrtcResize,
|
|
};
|
|
|
|
static Bool
|
|
LXPreInit(ScrnInfoPtr pScrni, int flags)
|
|
{
|
|
GeodePtr pGeode;
|
|
EntityInfoPtr pEnt;
|
|
OptionInfoRec *GeodeOptions = &LX_GeodeOptions[0];
|
|
rgb defaultWeight = { 0, 0, 0 };
|
|
char *s;
|
|
|
|
if (pScrni->numEntities != 1)
|
|
return FALSE;
|
|
|
|
pEnt = xf86GetEntityInfo(pScrni->entityList[0]);
|
|
#ifndef XSERVER_LIBPCIACCESS
|
|
if (pEnt->resources)
|
|
return FALSE;
|
|
#endif
|
|
if (flags & PROBE_DETECT) {
|
|
GeodeProbeDDC(pScrni, pEnt->index);
|
|
return TRUE;
|
|
}
|
|
|
|
pGeode = pScrni->driverPrivate = xnfcalloc(1, sizeof(GeodeRec));
|
|
|
|
if (pGeode == NULL)
|
|
return FALSE;
|
|
|
|
pGeode->useVGA = LXCheckVGA(pScrni);
|
|
pGeode->VGAActive = FALSE;
|
|
pGeode->pEnt = pEnt;
|
|
|
|
if (pGeode->useVGA) {
|
|
if (!xf86LoadSubModule(pScrni, "vgahw") || !vgaHWGetHWRec(pScrni))
|
|
pGeode->useVGA = FALSE;
|
|
else
|
|
vgaHWSetStdFuncs(VGAHWPTR(pScrni));
|
|
|
|
pGeode->vesa = calloc(1, sizeof(VESARec));
|
|
}
|
|
|
|
cim_rdmsr = LXReadMSR;
|
|
cim_wrmsr = LXWriteMSR;
|
|
|
|
/* Set up the Cimarron MSR tables */
|
|
msr_init_table();
|
|
|
|
/* By default, we support panel and CRT - the config file should
|
|
* disable the ones we don't want
|
|
*/
|
|
|
|
pGeode->Output = OUTPUT_PANEL | OUTPUT_CRT;
|
|
|
|
/* Fill in the monitor information */
|
|
pScrni->monitor = pScrni->confScreen->monitor;
|
|
|
|
if (!xf86SetDepthBpp(pScrni, 16, 16, 16, Support24bppFb | Support32bppFb))
|
|
return FALSE;
|
|
|
|
switch (pScrni->depth) {
|
|
case 8:
|
|
pScrni->rgbBits = 8;
|
|
case 16:
|
|
case 24:
|
|
case 32:
|
|
break;
|
|
default:
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
|
|
"The driver does not support %d as a depth.\n",
|
|
pScrni->depth);
|
|
return FALSE;
|
|
}
|
|
|
|
xf86PrintDepthBpp(pScrni);
|
|
|
|
if (!xf86SetWeight(pScrni, defaultWeight, defaultWeight))
|
|
return FALSE;
|
|
|
|
if (!xf86SetDefaultVisual(pScrni, -1))
|
|
return FALSE;
|
|
|
|
/*
|
|
* If the driver can do gamma correction, it should call xf86SetGamma()
|
|
* here.
|
|
*/
|
|
{
|
|
Gamma zeros = { 0.0, 0.0, 0.0 };
|
|
|
|
if (!xf86SetGamma(pScrni, zeros)) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
pScrni->progClock = TRUE;
|
|
xf86CollectOptions(pScrni, NULL);
|
|
xf86ProcessOptions(pScrni->scrnIndex, pScrni->options, GeodeOptions);
|
|
|
|
/* Set up our various options that may get reversed as we go on */
|
|
|
|
pGeode->tryHWCursor = TRUE;
|
|
pGeode->tryCompression = TRUE;
|
|
|
|
/* Protect against old versions of EXA */
|
|
|
|
#if (EXA_VERSION_MAJOR < 2)
|
|
pGeode->NoAccel = TRUE;
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
|
|
"*** This driver was compiled with EXA version %d\n");
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
|
|
"*** we need version 2 or greater\n");
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
|
|
"*** All accelerations are being turned off.\n");
|
|
#else
|
|
pGeode->NoAccel = FALSE;
|
|
#endif
|
|
|
|
pGeode->exaBfrSz = DEFAULT_EXA_SCRATCH_BFRSZ;
|
|
|
|
xf86GetOptValBool(GeodeOptions, LX_OPTION_HW_CURSOR, &pGeode->tryHWCursor);
|
|
|
|
if (!xf86GetOptValInteger(GeodeOptions, LX_OPTION_FBSIZE,
|
|
(int *) &(pGeode->FBAvail)))
|
|
pGeode->FBAvail = 0;
|
|
|
|
/* For compatability - allow SWCursor too */
|
|
|
|
if (xf86ReturnOptValBool(GeodeOptions, LX_OPTION_SW_CURSOR, FALSE))
|
|
pGeode->tryHWCursor = FALSE;
|
|
|
|
if (xf86ReturnOptValBool(GeodeOptions, LX_OPTION_NOCOMPRESSION, FALSE))
|
|
pGeode->tryCompression = FALSE;
|
|
|
|
if (xf86ReturnOptValBool(GeodeOptions, LX_OPTION_NOACCEL, FALSE))
|
|
pGeode->NoAccel = TRUE;
|
|
|
|
pGeode->rotation = RR_Rotate_0;
|
|
|
|
if ((s = xf86GetOptValString(GeodeOptions, LX_OPTION_ROTATE))) {
|
|
|
|
if (!xf86NameCmp(s, "LEFT"))
|
|
pGeode->rotation = RR_Rotate_90;
|
|
else if (!xf86NameCmp(s, "INVERT"))
|
|
pGeode->rotation = RR_Rotate_180;
|
|
else if (!xf86NameCmp(s, "CCW"))
|
|
pGeode->rotation = RR_Rotate_270;
|
|
else
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "Invalid rotation %s.\n", s);
|
|
}
|
|
|
|
xf86GetOptValInteger(GeodeOptions, LX_OPTION_EXA_SCRATCH_BFRSZ,
|
|
(int *) &(pGeode->exaBfrSz));
|
|
|
|
if (pGeode->exaBfrSz <= 0)
|
|
pGeode->exaBfrSz = 0;
|
|
|
|
if (pGeode->Output & OUTPUT_PANEL) {
|
|
if (xf86ReturnOptValBool(GeodeOptions, LX_OPTION_NOPANEL, FALSE))
|
|
pGeode->Output &= ~OUTPUT_PANEL;
|
|
}
|
|
|
|
/* Panel detection code -
|
|
* 1. See if an OLPC DCON is attached - we can make some assumptions
|
|
* about the panel if so.
|
|
* 2. Use panel mode specified in the config
|
|
* 3. "Autodetect" the panel through VSA
|
|
*/
|
|
|
|
if (dcon_init(pScrni)) {
|
|
pGeode->Output = OUTPUT_PANEL | OUTPUT_DCON;
|
|
}
|
|
else if (pGeode->Output & OUTPUT_PANEL) {
|
|
char *pmode = xf86GetOptValString(GeodeOptions, LX_OPTION_PANEL_MODE);
|
|
|
|
if (pmode != NULL)
|
|
pGeode->panelMode = LXGetManualPanelMode(pmode);
|
|
|
|
if (pGeode->panelMode == NULL)
|
|
pGeode->panelMode = LXGetLegacyPanelMode(pScrni);
|
|
|
|
if (pGeode->panelMode == NULL)
|
|
pGeode->Output &= ~OUTPUT_PANEL;
|
|
}
|
|
|
|
/* Default to turn scaling on for panels */
|
|
|
|
if (pGeode->Output & OUTPUT_PANEL)
|
|
pGeode->Scale = TRUE;
|
|
|
|
xf86DrvMsg(pScrni->scrnIndex, X_INFO, "LX output options:\n");
|
|
xf86DrvMsg(pScrni->scrnIndex, X_INFO, " CRT: %s\n",
|
|
pGeode->Output & OUTPUT_CRT ? "YES" : "NO");
|
|
|
|
xf86DrvMsg(pScrni->scrnIndex, X_INFO, " PANEL: %s\n",
|
|
pGeode->Output & OUTPUT_PANEL ? "YES" : "NO");
|
|
|
|
xf86DrvMsg(pScrni->scrnIndex, X_INFO, " DCON: %s\n",
|
|
pGeode->Output & OUTPUT_DCON ? "YES" : "NO");
|
|
|
|
xf86DrvMsg(pScrni->scrnIndex, X_INFO, " VGA: %s\n",
|
|
pGeode->useVGA ? "YES" : "NO");
|
|
|
|
/* Set up VGA */
|
|
|
|
if (pGeode->useVGA) {
|
|
VESARec *pVesa;
|
|
|
|
if (!xf86LoadSubModule(pScrni, "int10"))
|
|
return FALSE;
|
|
|
|
pVesa = pGeode->vesa;
|
|
|
|
if ((pVesa->pInt = xf86InitInt10(pGeode->pEnt->index)) == NULL) {
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
|
|
"Unable to initialize 1NT10 support\n");
|
|
pGeode->useVGA = FALSE;
|
|
}
|
|
}
|
|
|
|
/* Read the amount of framebuffer memory */
|
|
/* First try to read it from the framebuffer, and if that fails,
|
|
* do it the legacy way
|
|
*/
|
|
|
|
if (pGeode->FBAvail == 0) {
|
|
if (GeodeGetSizeFromFB(&pGeode->FBAvail)) {
|
|
unsigned long value;
|
|
|
|
cim_outw(0xAC1C, 0xFC53);
|
|
cim_outw(0xAC1C, 0x0200);
|
|
|
|
value = (unsigned long) (cim_inw(0xAC1E)) & 0xFE;
|
|
pGeode->FBAvail = value << 20;
|
|
}
|
|
}
|
|
|
|
pScrni->fbOffset = 0;
|
|
|
|
if (pGeode->pEnt->device->videoRam == 0)
|
|
pScrni->videoRam = pGeode->FBAvail / 1024;
|
|
else {
|
|
pScrni->videoRam = pGeode->pEnt->device->videoRam;
|
|
pGeode->FBAvail = pScrni->videoRam << 10;
|
|
}
|
|
|
|
/* If we have <= 16Mb of memory then compression is going
|
|
to hurt - so warn and disable */
|
|
|
|
if (pGeode->tryCompression && pGeode->FBAvail <= 0x1000000) {
|
|
xf86DrvMsg(pScrni->scrnIndex, X_INFO,
|
|
"%x bytes of video memory is less then optimal\n",
|
|
pGeode->FBAvail);
|
|
xf86DrvMsg(pScrni->scrnIndex, X_INFO,
|
|
"when compression is on. Disabling compression.\n");
|
|
pGeode->tryCompression = FALSE;
|
|
}
|
|
|
|
/* Carve out some memory for the command buffer */
|
|
|
|
pGeode->CmdBfrSize = CIM_CMD_BFR_SZ;
|
|
pGeode->FBAvail -= CIM_CMD_BFR_SZ;
|
|
|
|
pGeode->CmdBfrOffset = pGeode->FBAvail;
|
|
|
|
/* Allocate a a CRTC config structure */
|
|
xf86CrtcConfigInit(pScrni, &lx_xf86crtc_config_funcs);
|
|
|
|
/* Set up the GPU CRTC */
|
|
LXSetupCrtc(pScrni);
|
|
|
|
xf86CrtcSetSizeRange(pScrni, 320, 200, LX_MAX_WIDTH, LX_MAX_HEIGHT);
|
|
|
|
/* Setup the output */
|
|
LXSetupOutput(pScrni);
|
|
|
|
if (!xf86InitialConfiguration(pScrni, FALSE)) {
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "No valid modes.\n");
|
|
return FALSE;
|
|
}
|
|
|
|
xf86PrintModes(pScrni);
|
|
|
|
pScrni->currentMode = pScrni->modes;
|
|
|
|
pGeode->Pitch = LXCalcPitch(pScrni);
|
|
|
|
xf86SetDpi(pScrni, 0, 0);
|
|
|
|
/* Load the modules we'll need */
|
|
|
|
if (xf86LoadSubModule(pScrni, "fb") == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (!pGeode->NoAccel) {
|
|
if (!xf86LoadSubModule(pScrni, "exa"))
|
|
return FALSE;
|
|
}
|
|
#ifndef XSERVER_LIBPCIACCESS
|
|
if (xf86RegisterResources(pGeode->pEnt->index, NULL, ResExclusive)) {
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
|
|
"Couldn't register the resources.\n");
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
LXRestore(ScrnInfoPtr pScrni)
|
|
{
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
|
|
if (pGeode->useVGA) {
|
|
vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
|
|
|
|
vgaHWProtect(pScrni, TRUE);
|
|
vgaHWRestore(pScrni, &pvgaHW->SavedReg, VGA_SR_ALL);
|
|
vgaHWProtect(pScrni, FALSE);
|
|
}
|
|
}
|
|
|
|
static Bool
|
|
LXUnmapMem(ScrnInfoPtr pScrni)
|
|
{
|
|
#ifndef XSERVER_LIBPCIACCESS
|
|
xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_gp_ptr, LX_GP_REG_SIZE);
|
|
xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_vg_ptr, LX_VG_REG_SIZE);
|
|
xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_vid_ptr, LX_VID_REG_SIZE);
|
|
xf86UnMapVidMem(pScrni->scrnIndex, (pointer) cim_vip_ptr, LX_VIP_REG_SIZE);
|
|
#else
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
pciVideoPtr pci = xf86GetPciInfoForEntity(pGeode->pEnt->index);
|
|
|
|
unmap_pci_mem(pScrni, pci, cim_gp_ptr, LX_GP_REG_SIZE);
|
|
unmap_pci_mem(pScrni, pci, cim_vg_ptr, LX_VG_REG_SIZE);
|
|
unmap_pci_mem(pScrni, pci, cim_vid_ptr, LX_VID_REG_SIZE);
|
|
unmap_pci_mem(pScrni, pci, cim_vip_ptr, LX_VIP_REG_SIZE);
|
|
unmap_pci_mem(pScrni, pci, cim_fb_ptr, pGeode->FBAvail + CIM_CMD_BFR_SZ);
|
|
#endif
|
|
|
|
xf86UnMapVidMem(pScrni->scrnIndex, XpressROMPtr, 0x10000);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* These should be correctly accounted for rotation */
|
|
|
|
void
|
|
LXAdjustFrame(ADJUST_FRAME_ARGS_DECL)
|
|
{
|
|
SCRN_INFO_PTR(arg);
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
|
|
unsigned long offset;
|
|
|
|
offset = (y * pGeode->Pitch);
|
|
offset += x * (pScrni->bitsPerPixel >> 3);
|
|
|
|
vg_set_display_offset(offset);
|
|
}
|
|
|
|
static Bool
|
|
LXSwitchMode(SWITCH_MODE_ARGS_DECL)
|
|
{
|
|
SCRN_INFO_PTR(arg);
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
|
|
/* Set the new mode */
|
|
return xf86SetSingleMode(pScrni, pMode, pGeode->rotation);
|
|
}
|
|
|
|
static void
|
|
LXLeaveGraphics(ScrnInfoPtr pScrni)
|
|
{
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
VG_PANNING_COORDINATES panning;
|
|
|
|
gp_wait_until_idle();
|
|
|
|
vg_set_custom_mode(&(pGeode->FBcimdisplaytiming.vgDisplayMode),
|
|
pGeode->FBcimdisplaytiming.wBpp);
|
|
|
|
vg_set_compression_enable(0);
|
|
|
|
/* Restore the previous Compression state */
|
|
if (pGeode->FBCompressionEnable) {
|
|
vg_configure_compression(&(pGeode->FBCBData));
|
|
vg_set_compression_enable(1);
|
|
}
|
|
|
|
vg_set_display_pitch(pGeode->FBcimdisplaytiming.wPitch);
|
|
vg_set_display_offset(pGeode->FBDisplayOffset);
|
|
|
|
/* Restore Cursor */
|
|
vg_set_cursor_position(pGeode->FBCursor.cursor_x,
|
|
pGeode->FBCursor.cursor_y, &panning);
|
|
|
|
LXRestore(pScrni);
|
|
|
|
if (pGeode->useVGA && pGeode->VGAActive) {
|
|
pGeode->vesa->pInt->num = 0x10;
|
|
pGeode->vesa->pInt->ax = 0x0 | pGeode->FBBIOSMode;
|
|
pGeode->vesa->pInt->bx = 0;
|
|
xf86ExecX86int10(pGeode->vesa->pInt);
|
|
vg_delay_milliseconds(3);
|
|
}
|
|
|
|
pScrni->vtSema = FALSE;
|
|
}
|
|
|
|
static Bool
|
|
LXCloseScreen(CLOSE_SCREEN_ARGS_DECL)
|
|
{
|
|
ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
|
|
if (pScrni->vtSema)
|
|
LXLeaveGraphics(pScrni);
|
|
|
|
if (pGeode->pExa) {
|
|
exaDriverFini(pScrn);
|
|
free(pGeode->pExa);
|
|
pGeode->pExa = NULL;
|
|
}
|
|
|
|
/* Unmap the offscreen allocations */
|
|
GeodeCloseOffscreen(pScrni);
|
|
|
|
LXUnmapMem(pScrni);
|
|
|
|
if (pGeode->useVGA)
|
|
vgaHWUnmapMem(pScrni);
|
|
|
|
pScrni->PointerMoved = pGeode->PointerMoved;
|
|
pScrn->CloseScreen = pGeode->CloseScreen;
|
|
|
|
if (pScrn->CloseScreen)
|
|
return (*pScrn->CloseScreen) (CLOSE_SCREEN_ARGS);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
LXEnterGraphics(ScreenPtr pScrn, ScrnInfoPtr pScrni)
|
|
{
|
|
int bpp;
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
|
|
pGeode->VGAActive = gu3_get_vga_active();
|
|
|
|
gp_wait_until_idle();
|
|
|
|
vg_get_current_display_mode(&pGeode->FBcimdisplaytiming.vgDisplayMode,
|
|
&bpp);
|
|
|
|
pGeode->FBcimdisplaytiming.wBpp = bpp;
|
|
pGeode->FBcimdisplaytiming.wPitch = vg_get_display_pitch();
|
|
|
|
pGeode->FBDisplayOffset = vg_get_display_offset();
|
|
|
|
if (pGeode->useVGA && pGeode->VGAActive) {
|
|
vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
|
|
|
|
pGeode->FBBIOSMode = pvgaHW->readCrtc(pvgaHW, 0x040);
|
|
}
|
|
|
|
pGeode->FBCompressionEnable = vg_get_compression_enable();
|
|
vg_get_compression_info(&(pGeode->FBCBData));
|
|
|
|
/* Save Cursor offset */
|
|
vg_get_cursor_info(&pGeode->FBCursor);
|
|
|
|
/* Turn off the VGA */
|
|
|
|
if (pGeode->useVGA) {
|
|
unsigned short sequencer;
|
|
vgaHWPtr pvgaHW = VGAHWPTR(pScrni);
|
|
|
|
/* Unlock VGA registers */
|
|
vgaHWUnlock(pvgaHW);
|
|
|
|
/* Save the current state and setup the current mode */
|
|
vgaHWSave(pScrni, &VGAHWPTR(pScrni)->SavedReg, VGA_SR_ALL);
|
|
|
|
/* DISABLE VGA SEQUENCER */
|
|
/* This allows the VGA state machine to terminate. We must delay */
|
|
/* such that there are no pending MBUS requests. */
|
|
|
|
cim_outb(DC3_SEQUENCER_INDEX, DC3_SEQUENCER_CLK_MODE);
|
|
sequencer = cim_inb(DC3_SEQUENCER_DATA);
|
|
sequencer |= DC3_CLK_MODE_SCREEN_OFF;
|
|
cim_outb(DC3_SEQUENCER_DATA, sequencer);
|
|
|
|
vg_delay_milliseconds(1);
|
|
|
|
/* BLANK THE VGA DISPLAY */
|
|
cim_outw(DC3_SEQUENCER_INDEX, DC3_SEQUENCER_RESET);
|
|
sequencer = cim_inb(DC3_SEQUENCER_DATA);
|
|
sequencer &= ~DC3_RESET_VGA_DISP_ENABLE;
|
|
cim_outb(DC3_SEQUENCER_DATA, sequencer);
|
|
|
|
vg_delay_milliseconds(1);
|
|
}
|
|
|
|
/* Clear the framebuffer */
|
|
memset(pGeode->FBBase, 0, pGeode->displaySize);
|
|
|
|
/* Set the modes */
|
|
if (!xf86SetDesiredModes(pScrni))
|
|
return FALSE;
|
|
|
|
pScrni->vtSema = TRUE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
LXLoadPalette(ScrnInfoPtr pScrni,
|
|
int numColors, int *indizes, LOCO * colors, VisualPtr pVisual)
|
|
{
|
|
int i, index, color;
|
|
|
|
for (i = 0; i < numColors; i++) {
|
|
index = indizes[i] & 0xFF;
|
|
color = (((unsigned long) (colors[index].red & 0xFF)) << 16) |
|
|
(((unsigned long) (colors[index].green & 0xFF)) << 8) |
|
|
((unsigned long) (colors[index].blue & 0xFF));
|
|
|
|
vg_set_display_palette_entry(index, color);
|
|
}
|
|
}
|
|
|
|
static Bool
|
|
LXScreenInit(SCREEN_INIT_ARGS_DECL)
|
|
{
|
|
ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn);
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
int ret;
|
|
unsigned int dwidth;
|
|
|
|
pGeode->starting = TRUE;
|
|
|
|
/* If we are using VGA then go ahead and map the memory */
|
|
|
|
if (pGeode->useVGA) {
|
|
|
|
if (!vgaHWMapMem(pScrni))
|
|
return FALSE;
|
|
|
|
vgaHWGetIOBase(VGAHWPTR(pScrni));
|
|
}
|
|
|
|
if (!pGeode->NoAccel) {
|
|
|
|
pGeode->pExa = exaDriverAlloc();
|
|
|
|
if (pGeode->pExa) {
|
|
|
|
pGeode->pExa->memoryBase = 0;
|
|
pGeode->pExa->memorySize = 0;
|
|
|
|
pGeode->pExa->pixmapOffsetAlign = 32;
|
|
pGeode->pExa->pixmapPitchAlign = 32;
|
|
pGeode->pExa->flags = EXA_OFFSCREEN_PIXMAPS;
|
|
pGeode->pExa->maxX = LX_MAX_WIDTH - 1;
|
|
pGeode->pExa->maxY = LX_MAX_HEIGHT - 1;
|
|
}
|
|
else {
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
|
|
"Couldn't allocate the EXA structure.\n");
|
|
pGeode->NoAccel = TRUE;
|
|
}
|
|
}
|
|
|
|
/* Map the memory here before doing anything else */
|
|
|
|
if (!LXMapMem(pScrni))
|
|
return FALSE;
|
|
|
|
LXInitOffscreen(pScrni);
|
|
|
|
/* XXX FIXME - Take down any of the structures on failure? */
|
|
if (!LXEnterGraphics(pScrn, pScrni))
|
|
return FALSE;
|
|
|
|
miClearVisualTypes();
|
|
|
|
/* XXX Again - take down anything? */
|
|
|
|
if (pScrni->bitsPerPixel > 8) {
|
|
if (!miSetVisualTypes(pScrni->depth,
|
|
TrueColorMask, pScrni->rgbBits,
|
|
pScrni->defaultVisual)) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
else {
|
|
if (!miSetVisualTypes(pScrni->depth,
|
|
miGetDefaultVisualMask(pScrni->depth),
|
|
pScrni->rgbBits, pScrni->defaultVisual)) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
miSetPixmapDepths();
|
|
|
|
if (pScrni->virtualX > pScrni->displayWidth)
|
|
pScrni->displayWidth = pScrni->virtualX;
|
|
|
|
/* Point at the visible area to start */
|
|
|
|
/* fbScreenInit assumes that the stride is display width *
|
|
* bytes per pixel. If compression is on, then our stride might
|
|
* be completely different, so we divide the pitch by the
|
|
* bytes per pixel to fake fbScreenInit into doing the right thing */
|
|
|
|
dwidth = pGeode->Pitch / ((pScrni->bitsPerPixel + 7) / 8);
|
|
|
|
ret = fbScreenInit(pScrn, pGeode->FBBase,
|
|
pScrni->virtualX, pScrni->virtualY,
|
|
pScrni->xDpi, pScrni->yDpi, dwidth,
|
|
pScrni->bitsPerPixel);
|
|
|
|
if (!ret)
|
|
return FALSE;
|
|
|
|
xf86SetBlackWhitePixels(pScrn);
|
|
|
|
/* Set up the color ordering */
|
|
if (pScrni->bitsPerPixel > 8) {
|
|
VisualPtr visual = pScrn->visuals + pScrn->numVisuals;
|
|
|
|
while (--visual >= pScrn->visuals) {
|
|
if ((visual->class | DynamicClass) == DirectColor) {
|
|
visual->offsetRed = pScrni->offset.red;
|
|
visual->offsetGreen = pScrni->offset.green;
|
|
visual->offsetBlue = pScrni->offset.blue;
|
|
visual->redMask = pScrni->mask.red;
|
|
visual->greenMask = pScrni->mask.green;
|
|
visual->blueMask = pScrni->mask.blue;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Must follow the color ordering */
|
|
fbPictureInit(pScrn, 0, 0);
|
|
|
|
if (!pGeode->NoAccel)
|
|
pGeode->NoAccel = LXExaInit(pScrn) ? FALSE : TRUE;
|
|
|
|
xf86SetBackingStore(pScrn);
|
|
|
|
/* Set up the soft cursor */
|
|
miDCInitialize(pScrn, xf86GetPointerScreenFuncs());
|
|
|
|
/* Set up the HW cursor - must follow the soft cursor init */
|
|
|
|
if (pGeode->tryHWCursor) {
|
|
if (!LXCursorInit(pScrn))
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR,
|
|
"Hardware cursor initialization failed.\n");
|
|
}
|
|
|
|
/* Set up the color map */
|
|
|
|
if (!miCreateDefColormap(pScrn))
|
|
return FALSE;
|
|
|
|
if (pScrni->bitsPerPixel == 8) {
|
|
/* Must follow initialization of the default colormap */
|
|
|
|
if (!xf86HandleColormaps(pScrn, 256, 8,
|
|
LXLoadPalette, NULL,
|
|
CMAP_PALETTED_TRUECOLOR |
|
|
CMAP_RELOAD_ON_MODE_SWITCH)) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
xf86DPMSInit(pScrn, xf86DPMSSet, 0);
|
|
|
|
LXInitVideo(pScrn);
|
|
|
|
pGeode->PointerMoved = pScrni->PointerMoved;
|
|
pScrni->PointerMoved = GeodePointerMoved;
|
|
|
|
pGeode->CloseScreen = pScrn->CloseScreen;
|
|
pScrn->CloseScreen = LXCloseScreen;
|
|
pScrn->SaveScreen = LXSaveScreen;
|
|
|
|
if (!xf86CrtcScreenInit(pScrn)) {
|
|
xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "CRTCScreenInit failed.\n");
|
|
return FALSE;
|
|
}
|
|
|
|
if (serverGeneration == 1)
|
|
xf86ShowUnusedOptions(pScrni->scrnIndex, pScrni->options);
|
|
|
|
pGeode->starting = FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static int
|
|
LXValidMode(VALID_MODE_ARGS_DECL)
|
|
{
|
|
return MODE_OK;
|
|
}
|
|
|
|
static Bool
|
|
LXEnterVT(VT_FUNC_ARGS_DECL)
|
|
{
|
|
SCRN_INFO_PTR(arg);
|
|
return LXEnterGraphics(NULL, pScrni);
|
|
}
|
|
|
|
static void
|
|
LXLeaveVT(VT_FUNC_ARGS_DECL)
|
|
{
|
|
SCRN_INFO_PTR(arg);
|
|
GeodeRec *pGeode = GEODEPTR(pScrni);
|
|
|
|
pGeode->PrevDisplayOffset = vg_get_display_offset();
|
|
LXLeaveGraphics(pScrni);
|
|
}
|
|
|
|
void
|
|
LXSetupChipsetFPtr(ScrnInfoPtr pScrn)
|
|
{
|
|
pScrn->PreInit = LXPreInit;
|
|
pScrn->ScreenInit = LXScreenInit;
|
|
pScrn->SwitchMode = LXSwitchMode;
|
|
pScrn->AdjustFrame = LXAdjustFrame;
|
|
pScrn->EnterVT = LXEnterVT;
|
|
pScrn->LeaveVT = LXLeaveVT;
|
|
pScrn->FreeScreen = GeodeFreeScreen;
|
|
pScrn->ValidMode = LXValidMode;
|
|
}
|