From 1abc4890915a417899d759b7e8e0430fb46ca424 Mon Sep 17 00:00:00 2001 From: Connor Behan Date: Sun, 25 May 2014 12:37:06 -0700 Subject: [PATCH] Rework modesetting API v7 Content-Type: text/plain; charset="utf-8" --- configure.ac | 2 +- src/Makefile.am | 3 +- src/r128.h | 48 +- src/r128_crtc.c | 476 ++++++++++++++++++++ src/r128_cursor.c | 294 ++++++------ src/r128_driver.c | 1285 +++++++++++------------------------------------------ src/r128_output.c | 461 +++++++++++++++++++ src/r128_probe.c | 1 - src/r128_probe.h | 70 +++ src/r128_video.c | 17 +- 10 files changed, 1465 insertions(+), 1192 deletions(-) create mode 100644 src/r128_crtc.c create mode 100644 src/r128_output.c diff --git a/configure.ac b/configure.ac index 56554ec..3cc3113 100644 --- a/configure.ac +++ b/configure.ac @@ -76,7 +76,7 @@ XORG_DRIVER_CHECK_EXT(XF86MISC, xf86miscproto) XORG_DRIVER_CHECK_EXT(DPMSExtension, xextproto) # Obtain compiler/linker options for the driver dependencies -PKG_CHECK_MODULES(XORG, [xorg-server >= 1.2 xproto fontsproto $REQUIRED_MODULES]) +PKG_CHECK_MODULES(XORG, [xorg-server >= 1.3 xproto fontsproto $REQUIRED_MODULES]) PKG_CHECK_MODULES(XEXT, [xextproto >= 7.0.99.1], HAVE_XEXTPROTO_71="yes"; AC_DEFINE(HAVE_XEXTPROTO_71, 1, [xextproto 7.1 available]), HAVE_XEXTPROTO_71="no") diff --git a/src/Makefile.am b/src/Makefile.am index 23e6c49..e4618ea 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -41,7 +41,8 @@ r128_drv_la_LDFLAGS = -module -avoid-version r128_drv_ladir = @moduledir@/drivers r128_drv_la_SOURCES = \ r128_accel.c r128_cursor.c r128_dga.c r128_driver.c \ - r128_video.c r128_misc.c r128_probe.c $(R128_EXA_SRCS) $(R128_DRI_SRCS) + r128_video.c r128_misc.c r128_crtc.c r128_output.c r128_probe.c \ + $(R128_EXA_SRCS) $(R128_DRI_SRCS) EXTRA_DIST = \ compat-api.h \ diff --git a/src/r128.h b/src/r128.h index ee0b1d4..3e5334e 100644 --- a/src/r128.h +++ b/src/r128.h @@ -74,6 +74,7 @@ #endif #include "fb.h" +#include "xf86Crtc.h" #include "compat-api.h" #include "atipcirename.h" @@ -110,7 +111,7 @@ #define cpu_to_le16(x) (x) #endif -#define R128_DEBUG 0 /* Turn off debugging output */ +#define R128_DEBUG 1 /* Turn off debugging output */ #define R128_IDLE_RETRY 32 /* Fall out of idle loops after this count */ #define R128_TIMEOUT 2000000 /* Fall out of wait loops after this count */ #define R128_MMIOSIZE 0x4000 @@ -260,16 +261,6 @@ typedef struct { DisplayModePtr mode; } R128FBLayout; -typedef enum -{ - MT_NONE, - MT_CRT, - MT_LCD, - MT_DFP, - MT_CTV, - MT_STV -} R128MonitorType; - #ifdef USE_EXA struct r128_2d_state { Bool in_use; @@ -523,10 +514,10 @@ typedef struct { Bool isDFP; Bool isPro2; - I2CBusPtr pI2CBus; CARD32 DDCReg; Bool VGAAccess; + R128BIOSConnector BiosConnector[R128_MAX_BIOS_CONNECTOR]; /****** Added for dualhead support *******************/ BOOL HasCRTC2; /* M3/M4 */ @@ -562,6 +553,39 @@ extern int R128MinBits(int val); extern void R128InitVideo(ScreenPtr pScreen); +extern void R128InitCommonRegisters(R128SavePtr save, R128InfoPtr info); +extern void R128InitFPRegisters(R128SavePtr orig, R128SavePtr save, DisplayModePtr mode, R128InfoPtr info); +extern Bool R128InitCrtcBase(xf86CrtcPtr crtc, R128SavePtr save, int x, int y); +extern Bool R128InitCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save, DisplayModePtr mode, R128InfoPtr info); +extern void R128InitPLLRegisters(ScrnInfoPtr pScrn, R128SavePtr save, R128PLLPtr pll, double dot_clock); +extern Bool R128InitDDARegisters(ScrnInfoPtr pScrn, R128SavePtr save, R128PLLPtr pll, R128InfoPtr info, DisplayModePtr mode); +extern Bool R128InitCrtc2Base(xf86CrtcPtr crtc, R128SavePtr save, int x, int y); +extern Bool R128InitCrtc2Registers(ScrnInfoPtr pScrn, R128SavePtr save, DisplayModePtr mode, R128InfoPtr info); +extern void R128InitPLL2Registers(ScrnInfoPtr pScrn, R128SavePtr save, R128PLLPtr pll, double dot_clock); +extern Bool R128InitDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr save, R128PLLPtr pll, R128InfoPtr info, DisplayModePtr mode); +extern void R128RestoreCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr restore); +extern void R128RestoreFPRegisters(ScrnInfoPtr pScrn, R128SavePtr restore); +extern void R128RestoreCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr restore); +extern void R128RestorePLLRegisters(ScrnInfoPtr pScrn, R128SavePtr restore); +extern void R128RestoreDDARegisters(ScrnInfoPtr pScrn, R128SavePtr restore); +extern void R128RestoreCrtc2Registers(ScrnInfoPtr pScrn, R128SavePtr restore); +extern void R128RestorePLL2Registers(ScrnInfoPtr pScrn, R128SavePtr restore); +extern void R128RestoreDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr restore); + +extern void r128_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg); +extern void r128_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y); +extern void r128_crtc_show_cursor(xf86CrtcPtr crtc); +extern void r128_crtc_hide_cursor(xf86CrtcPtr crtc); +extern void r128_crtc_load_cursor_image(xf86CrtcPtr crtc, unsigned char *src); + +extern Bool R128SetupConnectors(ScrnInfoPtr pScrn); +extern Bool R128AllocateControllers(ScrnInfoPtr pScrn, int mask); +extern void R128Blank(ScrnInfoPtr pScrn); +extern void R128Unblank(ScrnInfoPtr pScrn); +extern void R128DPMSSetOn(xf86OutputPtr output); +extern void R128DPMSSetOff(xf86OutputPtr output); +extern DisplayModePtr R128ProbeOutputModes(xf86OutputPtr output); + #ifdef R128DRI extern Bool R128DRIScreenInit(ScreenPtr pScreen); extern void R128DRICloseScreen(ScreenPtr pScreen); diff --git a/src/r128_crtc.c b/src/r128_crtc.c new file mode 100644 index 0000000..72a2a8b --- /dev/null +++ b/src/r128_crtc.c @@ -0,0 +1,476 @@ +/* + * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and + * VA Linux Systems Inc., Fremont, California. + * + * All Rights Reserved. + * + * 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 on 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 (including the + * next paragraph) 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 + * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR + * THEIR SUPPLIERS 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "xf86.h" +#include "xf86Modes.h" + +#include "r128.h" +#include "r128_probe.h" +#include "r128_reg.h" + +static void r128_crtc_load_lut(xf86CrtcPtr crtc); + +static void r128_crtc_dpms(xf86CrtcPtr crtc, int mode) +{ + int mask; + ScrnInfoPtr pScrn = crtc->scrn; + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + R128CrtcPrivatePtr r128_crtc = crtc->driver_private; + + /* XXX: The HSYNC and VSYNC bits for CRTC2 don't exist on the r128? */ + mask = r128_crtc->crtc_id ? R128_CRTC2_DISP_DIS : (R128_CRTC_DISPLAY_DIS | R128_CRTC_HSYNC_DIS | R128_CRTC_VSYNC_DIS); + + switch (mode) { + case DPMSModeOn: + if (r128_crtc->crtc_id) { + OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~mask); + } else { + OUTREGP(R128_CRTC_EXT_CNTL, 0, ~mask); + } + break; + case DPMSModeStandby: + if (r128_crtc->crtc_id) { + OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_DISP_DIS, ~mask); + } else { + OUTREGP(R128_CRTC_EXT_CNTL, (R128_CRTC_DISPLAY_DIS | R128_CRTC_HSYNC_DIS), ~mask); + } + break; + case DPMSModeSuspend: + if (r128_crtc->crtc_id) { + OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_DISP_DIS, ~mask); + } else { + OUTREGP(R128_CRTC_EXT_CNTL, (R128_CRTC_DISPLAY_DIS | R128_CRTC_VSYNC_DIS), ~mask); + } + break; + case DPMSModeOff: + if (r128_crtc->crtc_id) { + OUTREGP(R128_CRTC2_GEN_CNTL, mask, ~mask); + } else { + OUTREGP(R128_CRTC_EXT_CNTL, mask, ~mask); + } + break; + } + + if (mode != DPMSModeOff) + r128_crtc_load_lut(crtc); +} + +void r128_crtc_load_lut(xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + R128CrtcPrivatePtr r128_crtc = crtc->driver_private; + int i; + + if (!crtc->enabled) + return; + + PAL_SELECT(r128_crtc->crtc_id); + + for (i = 0; i < 256; i++) { + OUTPAL(i, r128_crtc->lut_r[i], r128_crtc->lut_g[i], r128_crtc->lut_b[i]); + } +} + +static Bool r128_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr adjusted_mode) +{ + return TRUE; +} + +static void r128_crtc_mode_prepare(xf86CrtcPtr crtc) +{ + r128_crtc_dpms(crtc, DPMSModeOff); +} + +static void r128_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr adjusted_mode, int x, int y) +{ + ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + R128CrtcPrivatePtr r128_crtc = crtc->driver_private; + R128InfoPtr info = R128PTR(pScrn); + R128MonitorType montype = MT_UNKNOWN; + + double dot_clock = adjusted_mode->Clock / 1000.0; + int i; + + if (r128_crtc->cursor_offset) r128_crtc_hide_cursor(crtc); + xf86PrintModeline(pScrn->scrnIndex, adjusted_mode); + R128InitCommonRegisters(&info->ModeReg, info); + + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + R128OutputPrivatePtr r128_output = output->driver_private; + + if (output->crtc == crtc) + montype = r128_output->MonType; + } + + switch (r128_crtc->crtc_id) { + case 0: + R128InitCrtcRegisters(pScrn, &info->ModeReg, adjusted_mode, info); + R128InitCrtcBase(crtc, &info->ModeReg, x, y); + if (dot_clock) { + R128InitPLLRegisters(pScrn, &info->ModeReg, &info->pll, dot_clock); + R128InitDDARegisters(pScrn, &info->ModeReg, &info->pll, info, adjusted_mode); + } else { + info->ModeReg.ppll_ref_div = info->SavedReg.ppll_ref_div; + info->ModeReg.ppll_div_3 = info->SavedReg.ppll_div_3; + info->ModeReg.htotal_cntl = info->SavedReg.htotal_cntl; + info->ModeReg.dda_config = info->SavedReg.dda_config; + info->ModeReg.dda_on_off = info->SavedReg.dda_on_off; + } + break; + case 1: + R128InitCrtc2Registers(pScrn, &info->ModeReg, adjusted_mode, info); + R128InitCrtc2Base(crtc, &info->ModeReg, x, y); + if (dot_clock) { + R128InitPLL2Registers(pScrn, &info->ModeReg, &info->pll, dot_clock); + R128InitDDA2Registers(pScrn, &info->ModeReg, &info->pll, info, adjusted_mode); + } + break; + } + + if ((info->HasCRTC2 || info->isDFP) && r128_crtc->crtc_id == 0) + R128InitFPRegisters(&info->SavedReg, &info->ModeReg, adjusted_mode, info); + R128RestoreCommonRegisters(pScrn, &info->ModeReg); + + switch (r128_crtc->crtc_id) { + case 0: + R128RestoreDDARegisters(pScrn, &info->ModeReg); + R128RestoreCrtcRegisters(pScrn, &info->ModeReg); + R128RestorePLLRegisters(pScrn, &info->ModeReg); + break; + case 1: + R128RestoreDDA2Registers(pScrn, &info->ModeReg); + R128RestoreCrtc2Registers(pScrn, &info->ModeReg); + R128RestorePLL2Registers(pScrn, &info->ModeReg); + break; + } + + if ((info->HasCRTC2 || info->isDFP) && r128_crtc->crtc_id == 0) + R128RestoreFPRegisters(pScrn, &info->ModeReg); + + /* XXX: InitFPRegisters looks similar to radeon's InitRMXRegisters so + * maybe it should be called from mode_set in the output code. + */ + if (r128_crtc->cursor_offset) r128_crtc_show_cursor(crtc); +} + +static void r128_crtc_mode_commit(xf86CrtcPtr crtc) +{ + r128_crtc_dpms(crtc, DPMSModeOn); +} + +static void r128_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue, int size) +{ + R128CrtcPrivatePtr r128_crtc = crtc->driver_private; + int i; + + for (i = 0; i < 256; i++) { + r128_crtc->lut_r[i] = red[i] >> 8; + r128_crtc->lut_g[i] = green[i] >> 8; + r128_crtc->lut_b[i] = blue[i] >> 8; + } + + r128_crtc_load_lut(crtc); +} + +static Bool r128_crtc_lock(xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + ScreenPtr pScreen = xf86ScrnToScreen(pScrn); + R128InfoPtr info = R128PTR(pScrn); + +#ifdef HAVE_XAA_H + if (info->accel) info->accel->Sync(pScrn); +#endif +#ifdef USE_EXA + if (info->ExaDriver) exaWaitSync(pScreen); +#endif + + return FALSE; +} + +static void r128_crtc_unlock(xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + ScreenPtr pScreen = xf86ScrnToScreen(pScrn); + R128InfoPtr info = R128PTR(pScrn); + +#ifdef HAVE_XAA_H + if (info->accel) info->accel->Sync(pScrn); +#endif +#ifdef USE_EXA + if (info->ExaDriver) exaWaitSync(pScreen); +#endif +} + +#ifdef HAVE_XAA_H +static FBLinearPtr r128_xf86AllocateOffscreenLinear(ScreenPtr pScreen, int length, int granularity, + MoveLinearCallbackProcPtr moveCB, + RemoveLinearCallbackProcPtr removeCB, + pointer privData) +{ + FBLinearPtr linear; + int max_size; + + linear = xf86AllocateOffscreenLinear(pScreen, length, granularity, moveCB, removeCB, privData); + if (linear != NULL) return linear; + + /* The above allocation did not succeed, so purge unlocked stuff and try again. */ + xf86QueryLargestOffscreenLinear(pScreen, &max_size, granularity, PRIORITY_EXTREME); + + if (max_size < length) return NULL; + xf86PurgeUnlockedOffscreenAreas(pScreen); + + linear = xf86AllocateOffscreenLinear(pScreen, length, granularity, moveCB, removeCB, privData); + return linear; +} +#endif + +static void *r128_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height) +{ + ScrnInfoPtr pScrn = crtc->scrn; + ScreenPtr pScreen = xf86ScrnToScreen(pScrn); + R128InfoPtr info = R128PTR(pScrn); + + R128CrtcPrivatePtr r128_crtc = crtc->driver_private; + unsigned long rotate_offset = 0; + unsigned long rotate_pitch; + int cpp = pScrn->bitsPerPixel / 8; + int align = 4096; + int size; + + rotate_pitch = pScrn->displayWidth * cpp; + size = rotate_pitch * height; + +#ifdef USE_EXA + if (info->ExaDriver) { + assert(r128_crtc->rotate_mem_exa == NULL); + r128_crtc->rotate_mem_exa = exaOffscreenAlloc(pScreen, size, align, TRUE, NULL, NULL); + + if (r128_crtc->rotate_mem_exa == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't allocate shadow memory for rotated CRTC\n"); + return NULL; + } + + rotate_offset = r128_crtc->rotate_mem_exa->offset; + } +#endif +#ifdef HAVE_XAA_H + if (info->accel) { + size = (size + cpp - 1) / cpp; + align = (align + cpp - 1) / cpp; + + assert(r128_crtc->rotate_mem_xaa == NULL); + r128_crtc->rotate_mem_xaa = r128_xf86AllocateOffscreenLinear(pScreen, size, align, NULL, NULL, NULL); + + if (r128_crtc->rotate_mem_exa == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't allocate shadow memory for rotated CRTC\n"); + return NULL; + } + + rotate_offset = r128_crtc->rotate_mem_xaa->offset * cpp; + } +#endif + + /* If allocations failed or if there was no accel. */ + if (rotate_offset == 0) + return NULL; + + return info->FB + rotate_offset; +} + +static PixmapPtr r128_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) +{ + ScrnInfoPtr pScrn = crtc->scrn; + PixmapPtr rotate_pixmap; + unsigned long rotate_pitch; + int cpp = pScrn->bitsPerPixel / 8; + + if (!data) data = r128_crtc_shadow_allocate(crtc, width, height); + + rotate_pitch = pScrn->displayWidth * cpp; + rotate_pixmap = GetScratchPixmapHeader(xf86ScrnToScreen(pScrn), + width, height, + pScrn->depth, + pScrn->bitsPerPixel, + rotate_pitch, + data); + + if (rotate_pixmap == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't allocate shadow memory for rotated CRTC\n"); + return NULL; + } + + return rotate_pixmap; +} + +static void r128_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data) +{ + ScrnInfoPtr pScrn = crtc->scrn; + ScreenPtr pScreen = xf86ScrnToScreen(pScrn); + R128InfoPtr info = R128PTR(pScrn); + + R128CrtcPrivatePtr r128_crtc = crtc->driver_private; + + if (rotate_pixmap) FreeScratchPixmapHeader(rotate_pixmap); + + if (data) { +#ifdef USE_EXA + if (info->ExaDriver && r128_crtc->rotate_mem_exa != NULL) { + exaOffscreenFree(pScreen, r128_crtc->rotate_mem_exa); + r128_crtc->rotate_mem_exa = NULL; + } +#endif +#ifdef HAVE_XAA_H + if (info->accel) { + xf86FreeOffscreenLinear(r128_crtc->rotate_mem_xaa); + r128_crtc->rotate_mem_xaa = NULL; + } +#endif + } +} + +static const xf86CrtcFuncsRec r128_crtc_funcs = { + .dpms = r128_crtc_dpms, + .save = NULL, + .restore = NULL, + .mode_fixup = r128_crtc_mode_fixup, + .prepare = r128_crtc_mode_prepare, + .mode_set = r128_crtc_mode_set, + .commit = r128_crtc_mode_commit, + .gamma_set = r128_crtc_gamma_set, + .lock = r128_crtc_lock, + .unlock = r128_crtc_unlock, + .shadow_create = r128_crtc_shadow_create, + .shadow_allocate = r128_crtc_shadow_allocate, + .shadow_destroy = r128_crtc_shadow_destroy, + .set_cursor_colors = r128_crtc_set_cursor_colors, + .set_cursor_position = r128_crtc_set_cursor_position, + .show_cursor = r128_crtc_show_cursor, + .hide_cursor = r128_crtc_hide_cursor, + .load_cursor_image = r128_crtc_load_cursor_image, + .destroy = NULL, +}; + +Bool R128AllocateControllers(ScrnInfoPtr pScrn, int mask) +{ + R128EntPtr pR128Ent = R128EntPriv(pScrn); + R128InfoPtr info = R128PTR(pScrn); + + if (mask & 1) { + if (pR128Ent->Controller[0]) + return TRUE; + + pR128Ent->pCrtc[0] = xf86CrtcCreate(pScrn, &r128_crtc_funcs); + if (!pR128Ent->pCrtc[0]) + return FALSE; + + pR128Ent->Controller[0] = xnfcalloc(sizeof(R128CrtcPrivateRec), 1); + if (!pR128Ent->Controller[0]) + return FALSE; + + pR128Ent->pCrtc[0]->driver_private = pR128Ent->Controller[0]; + pR128Ent->Controller[0]->crtc_id = 0; + } + + if (mask & 2) { + if (!info->HasCRTC2) + return TRUE; + + pR128Ent->pCrtc[1] = xf86CrtcCreate(pScrn, &r128_crtc_funcs); + if (!pR128Ent->pCrtc[1]) + return FALSE; + + pR128Ent->Controller[1] = xnfcalloc(sizeof(R128CrtcPrivateRec), 1); + if (!pR128Ent->Controller[1]) { + free(pR128Ent->Controller[0]); + return FALSE; + } + + pR128Ent->pCrtc[1]->driver_private = pR128Ent->Controller[1]; + pR128Ent->Controller[1]->crtc_id = 1; + } + + return TRUE; +} + +void R128Blank(ScrnInfoPtr pScrn) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86OutputPtr output; + xf86CrtcPtr crtc; + int o, c; + + for (c = 0; c < xf86_config->num_crtc; c++) { + crtc = xf86_config->crtc[c]; + for (o = 0; o < xf86_config->num_output; o++) { + output = xf86_config->output[o]; + if (output->crtc != crtc) + continue; + + output->funcs->dpms(output, DPMSModeOff); + } + crtc->funcs->dpms(crtc, DPMSModeOff); + } +} + +void R128Unblank(ScrnInfoPtr pScrn) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86OutputPtr output; + xf86CrtcPtr crtc; + int o, c; + + for (c = 0; c < xf86_config->num_crtc; c++) { + crtc = xf86_config->crtc[c]; + if (!crtc->enabled) + continue; + crtc->funcs->dpms(crtc, DPMSModeOn); + for (o = 0; o < xf86_config->num_output; o++) { + output = xf86_config->output[o]; + if (output->crtc != crtc) + continue; + + output->funcs->dpms(output, DPMSModeOn); + } + } +} diff --git a/src/r128_cursor.c b/src/r128_cursor.c index b76913c..ad6752f 100644 --- a/src/r128_cursor.c +++ b/src/r128_cursor.c @@ -59,6 +59,9 @@ #include "exa.h" #endif +#define CURSOR_WIDTH 64 +#define CURSOR_HEIGHT 64 + #if X_BYTE_ORDER == X_BIG_ENDIAN #define P_SWAP32( a , b ) \ ((char *)a)[0] = ((char *)b)[3]; \ @@ -73,84 +76,121 @@ ((char *)a)[3] = ((char *)b)[2] #endif +void r128_crtc_show_cursor(xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + R128CrtcPrivatePtr r128_crtc = crtc->driver_private; + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + int crtc_id = r128_crtc->crtc_id; + + switch (crtc_id) { + case 0: + OUTREGP(R128_CRTC_GEN_CNTL, R128_CRTC_CUR_EN, ~R128_CRTC_CUR_EN); + break; + case 1: + OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_CUR_EN, ~R128_CRTC2_CUR_EN); + break; + default: + return; + } +} -/* Set cursor foreground and background colors. */ -static void R128SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) +void r128_crtc_hide_cursor(xf86CrtcPtr crtc) { - R128InfoPtr info = R128PTR(pScrn); + ScrnInfoPtr pScrn = crtc->scrn; + R128CrtcPrivatePtr r128_crtc = crtc->driver_private; + R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; + int crtc_id = r128_crtc->crtc_id; - if(info->IsSecondary) - { + switch (crtc_id) { + case 0: + OUTREGP(R128_CRTC_GEN_CNTL, 0, ~R128_CRTC_CUR_EN); + break; + case 1: + OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~R128_CRTC2_CUR_EN); + break; + default: + return; + } +} + +void r128_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg) +{ + ScrnInfoPtr pScrn = crtc->scrn; + R128CrtcPrivatePtr r128_crtc = crtc->driver_private; + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + int crtc_id = r128_crtc->crtc_id; + + switch (crtc_id) { + case 0: + OUTREG(R128_CUR_CLR0, bg); + OUTREG(R128_CUR_CLR1, fg); + break; + case 1: OUTREG(R128_CUR2_CLR0, bg); OUTREG(R128_CUR2_CLR1, fg); - } - else - { - OUTREG(R128_CUR_CLR0, bg); - OUTREG(R128_CUR_CLR1, fg); + break; + default: + return; } } -/* Set cursor position to (x,y) with offset into cursor bitmap at - (xorigin,yorigin). */ -static void R128SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) +void r128_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y) { - R128InfoPtr info = R128PTR(pScrn); - unsigned char *R128MMIO = info->MMIO; - xf86CursorInfoPtr cursor = info->cursor; - int xorigin = 0; - int yorigin = 0; - int total_y = pScrn->frameY1 - pScrn->frameY0; - - if (x < 0) xorigin = -x; - if (y < 0) yorigin = -y; - if (y > total_y) y = total_y; - if (info->Flags & V_DBLSCAN) y *= 2; - if (xorigin >= cursor->MaxWidth) xorigin = cursor->MaxWidth - 1; - if (yorigin >= cursor->MaxHeight) yorigin = cursor->MaxHeight - 1; - - if(!info->IsSecondary) - { - OUTREG(R128_CUR_HORZ_VERT_OFF, R128_CUR_LOCK | (xorigin << 16) | yorigin); - OUTREG(R128_CUR_HORZ_VERT_POSN, (R128_CUR_LOCK - | ((xorigin ? 0 : x) << 16) - | (yorigin ? 0 : y))); - OUTREG(R128_CUR_OFFSET, info->cursor_start + yorigin * 16); - } - else - { - OUTREG(R128_CUR2_HORZ_VERT_OFF, (R128_CUR2_LOCK - | (xorigin << 16) - | yorigin)); - OUTREG(R128_CUR2_HORZ_VERT_POSN, (R128_CUR2_LOCK - | ((xorigin ? 0 : x) << 16) - | (yorigin ? 0 : y))); - OUTREG(R128_CUR2_OFFSET, - info->cursor_start + pScrn->fbOffset + yorigin * 16); + ScrnInfoPtr pScrn = crtc->scrn; + R128InfoPtr info = R128PTR(pScrn); + R128CrtcPrivatePtr r128_crtc = crtc->driver_private; + unsigned char *R128MMIO = info->MMIO; + int crtc_id = r128_crtc->crtc_id; + + int xorigin = 0, yorigin = 0; + DisplayModePtr mode = &crtc->mode; + + if (x < 0) xorigin = -x + 1; + if (y < 0) yorigin = -y + 1; + if (xorigin >= CURSOR_WIDTH) xorigin = CURSOR_WIDTH - 1; + if (yorigin >= CURSOR_HEIGHT) yorigin = CURSOR_HEIGHT - 1; + + if (mode->Flags & V_INTERLACE) + y /= 2; + else if (mode->Flags & V_DBLSCAN) + y *= 2; + + if(crtc_id == 0) { + OUTREG(R128_CUR_HORZ_VERT_OFF, (R128_CUR_LOCK | (xorigin << 16) | yorigin)); + OUTREG(R128_CUR_HORZ_VERT_POSN, (R128_CUR_LOCK | ((xorigin ? 0 : x) << 16) | (yorigin ? 0 : y))); + OUTREG(R128_CUR_OFFSET, r128_crtc->cursor_offset + pScrn->fbOffset + yorigin * 16); + } else if (crtc_id == 1) { + OUTREG(R128_CUR2_HORZ_VERT_OFF, (R128_CUR2_LOCK | (xorigin << 16) | yorigin)); + OUTREG(R128_CUR2_HORZ_VERT_POSN, (R128_CUR2_LOCK | ((xorigin ? 0 : x) << 16) | (yorigin ? 0 : y))); + OUTREG(R128_CUR2_OFFSET, r128_crtc->cursor_offset + pScrn->fbOffset + yorigin * 16); } } -/* Copy cursor image from `image' to video memory. R128SetCursorPosition - will be called after this, so we can ignore xorigin and yorigin. */ -static void R128LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image) +void r128_crtc_load_cursor_image(xf86CrtcPtr crtc, unsigned char *src) { + ScrnInfoPtr pScrn = crtc->scrn; + R128CrtcPrivatePtr r128_crtc = crtc->driver_private; + int crtc_id = r128_crtc->crtc_id; + + R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; - CARD32 *s = (pointer)image; - CARD32 *d = (pointer)((CARD8*)info->FB + info->cursor_start); + CARD32 *s = (pointer)src; + CARD32 *d = (pointer)(info->FB + r128_crtc->cursor_offset + pScrn->fbOffset); + CARD32 save1 = 0; + CARD32 save2 = 0; int y; - CARD32 save; - if(!info->IsSecondary) - { - save = INREG(R128_CRTC_GEN_CNTL); - OUTREG(R128_CRTC_GEN_CNTL, save & (CARD32)~R128_CRTC_CUR_EN); - } - else - { - save = INREG(R128_CRTC2_GEN_CNTL); - OUTREG(R128_CRTC2_GEN_CNTL, save & (CARD32)~R128_CRTC2_CUR_EN); + if (crtc_id == 0) { + save1 = INREG(R128_CRTC_GEN_CNTL); + OUTREG(R128_CRTC_GEN_CNTL, save1 & (CARD32)~R128_CRTC_CUR_EN); + } else if (crtc_id == 1) { + save2 = INREG(R128_CRTC2_GEN_CNTL); + OUTREG(R128_CRTC2_GEN_CNTL, save2 & (CARD32)~R128_CRTC2_CUR_EN); } #if X_BYTE_ORDER == X_BIG_ENDIAN @@ -197,59 +237,10 @@ static void R128LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image) } #endif - /* Set the area after the cursor to be all transparent so that we - won't display corrupted cursors on the screen */ - for (y = 0; y < 64; y++) { - *d++ = 0xffffffff; /* The AND bits */ - *d++ = 0xffffffff; - *d++ = 0x00000000; /* The XOR bits */ - *d++ = 0x00000000; - } - - - if(!info->IsSecondary) - OUTREG(R128_CRTC_GEN_CNTL, save); + if (crtc_id == 0) + OUTREG(R128_CRTC_GEN_CNTL, save1); else - OUTREG(R128_CRTC2_GEN_CNTL, save); - -} - -/* Hide hardware cursor. */ -static void R128HideCursor(ScrnInfoPtr pScrn) -{ - R128InfoPtr info = R128PTR(pScrn); - unsigned char *R128MMIO = info->MMIO; - - if(info->IsSecondary) - OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~R128_CRTC2_CUR_EN); - else - OUTREGP(R128_CRTC_GEN_CNTL, 0, ~R128_CRTC_CUR_EN); -} - -/* Show hardware cursor. */ -static void R128ShowCursor(ScrnInfoPtr pScrn) -{ - R128InfoPtr info = R128PTR(pScrn); - unsigned char *R128MMIO = info->MMIO; - - if(info->IsSecondary) - { - OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_CUR_EN, - ~R128_CRTC2_CUR_EN); - } - else - { - OUTREGP(R128_CRTC_GEN_CNTL, R128_CRTC_CUR_EN, ~R128_CRTC_CUR_EN); - } -} - -/* Determine if hardware cursor is in use. */ -static Bool R128UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) -{ - ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); - R128InfoPtr info = R128PTR(pScrn); - - return info->cursor_start ? TRUE : FALSE; + OUTREG(R128_CRTC2_GEN_CNTL, save2); } /* Initialize hardware cursor support. */ @@ -257,77 +248,72 @@ Bool R128CursorInit(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); R128InfoPtr info = R128PTR(pScrn); - xf86CursorInfoPtr cursor; FBAreaPtr fbarea = NULL; #ifdef USE_EXA ExaOffscreenArea* osArea = NULL; #else void* osArea = NULL; #endif + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + CARD32 cursor_offset = 0; + int cpp = info->CurrentLayout.pixel_bytes; int width; + int width_bytes; int height; int size; + int size_bytes; + int c; - int cpp = info->CurrentLayout.pixel_bytes; - - if (!(cursor = info->cursor = xf86CreateCursorInfoRec())) return FALSE; - - cursor->MaxWidth = 64; - cursor->MaxHeight = 64; - cursor->Flags = (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP - | HARDWARE_CURSOR_SHOW_TRANSPARENT - | HARDWARE_CURSOR_UPDATE_UNHIDDEN -#if X_BYTE_ORDER == X_LITTLE_ENDIAN - | HARDWARE_CURSOR_BIT_ORDER_MSBFIRST -#endif - | HARDWARE_CURSOR_INVERT_MASK - | HARDWARE_CURSOR_AND_SOURCE_WITH_MASK - | HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 - | HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK); - - cursor->SetCursorColors = R128SetCursorColors; - cursor->SetCursorPosition = R128SetCursorPosition; - cursor->LoadCursorImage = R128LoadCursorImage; - cursor->HideCursor = R128HideCursor; - cursor->ShowCursor = R128ShowCursor; - cursor->UseHWCursor = R128UseHWCursor; - - size = (cursor->MaxWidth/4) * cursor->MaxHeight; + size = CURSOR_WIDTH * CURSOR_HEIGHT / 4; + size_bytes = size * 2; width = pScrn->displayWidth; - height = (size*2 + 1023) / pScrn->displayWidth; + width_bytes = width * (pScrn->bitsPerPixel / 8); + height = ((size_bytes * xf86_config->num_crtc) + width_bytes - 1) / width_bytes; if(!info->useEXA) { fbarea = xf86AllocateOffscreenArea(pScreen, width, height, 16, NULL, NULL, NULL); - if (fbarea) { - info->cursor_start = R128_ALIGN((fbarea->box.x1 - + width * fbarea->box.y1) - * cpp, 16); - info->cursor_end = info->cursor_start + size; - } + if (fbarea) + cursor_offset = R128_ALIGN((fbarea->box.x1 + width * fbarea->box.y1) * cpp, 16); } #ifdef USE_EXA else { osArea = exaOffscreenAlloc(pScreen, width * height, 16, TRUE, NULL, NULL); - if (osArea) { - info->cursor_start = osArea->offset; - info->cursor_end = osArea->offset + osArea->size; - } + if (osArea) + cursor_offset = osArea->offset; } #endif if ((!info->useEXA && !fbarea) || (info->useEXA && !osArea)) { - info->cursor_start = 0; xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Hardware cursor disabled" " due to insufficient offscreen memory\n"); + return FALSE; + } else { + for (c = 0; c < xf86_config->num_crtc; c++) { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + R128CrtcPrivatePtr r128_crtc = crtc->driver_private; + + r128_crtc->cursor_offset = cursor_offset + (c * size); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Will use %d kb for hardware cursor %d at offset 0x%08x\n", + (size_bytes * xf86_config->num_crtc) / 1024, c, + (unsigned int)r128_crtc->cursor_offset); + } } - R128TRACE(("R128CursorInit (0x%08x-0x%08x)\n", - info->cursor_start, info->cursor_end)); - - return xf86InitCursor(pScreen, cursor); + return xf86_cursors_init(pScreen, CURSOR_WIDTH, CURSOR_HEIGHT, + (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | + HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | + HARDWARE_CURSOR_SHOW_TRANSPARENT | + HARDWARE_CURSOR_UPDATE_UNHIDDEN | +#if X_BYTE_ORDER == X_LITTLE_ENDIAN + HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | +#endif + HARDWARE_CURSOR_INVERT_MASK | + HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK | + HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64)); } diff --git a/src/r128_driver.c b/src/r128_driver.c index f425c3b..c883022 100644 --- a/src/r128_driver.c +++ b/src/r128_driver.c @@ -84,6 +84,7 @@ /* X and server generic header files */ #include "xf86.h" #include "xf86_OSproc.h" +#include "xf86RandR12.h" #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 #include "xf86RAC.h" #include "xf86Resources.h" @@ -119,11 +120,6 @@ static Bool R128CloseScreen(CLOSE_SCREEN_ARGS_DECL); static Bool R128SaveScreen(ScreenPtr pScreen, int mode); static void R128Save(ScrnInfoPtr pScrn); static void R128Restore(ScrnInfoPtr pScrn); -static Bool R128ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); -static void R128DisplayPowerManagementSet(ScrnInfoPtr pScrn, - int PowerManagementMode, int flags); -static void R128DisplayPowerManagementSetLCD(ScrnInfoPtr pScrn, - int PowerManagementMode, int flags); typedef enum { OPTION_NOACCEL, @@ -258,6 +254,7 @@ static Bool R128MapMMIO(ScrnInfoPtr pScrn) info->PciTag, info->MMIOAddr, R128_MMIOSIZE); + if (!info->MMIO) return FALSE; #else int err = pci_device_map_range(info->PciInfo, info->MMIOAddr, @@ -274,7 +271,6 @@ static Bool R128MapMMIO(ScrnInfoPtr pScrn) #endif } - if (!info->MMIO) return FALSE; return TRUE; } @@ -402,78 +398,6 @@ void R128WaitForVerticalSync(ScrnInfoPtr pScrn) } } -/* Blank screen. */ -static void R128Blank(ScrnInfoPtr pScrn) -{ - R128InfoPtr info = R128PTR(pScrn); - unsigned char *R128MMIO = info->MMIO; - - if(!info->IsSecondary) - { - switch(info->DisplayType) - { - case MT_LCD: - OUTREGP(R128_LVDS_GEN_CNTL, R128_LVDS_DISPLAY_DIS, - ~R128_LVDS_DISPLAY_DIS); - break; - case MT_CRT: - OUTREGP(R128_CRTC_EXT_CNTL, R128_CRTC_DISPLAY_DIS, ~R128_CRTC_DISPLAY_DIS); - break; - case MT_DFP: - OUTREGP(R128_FP_GEN_CNTL, R128_FP_BLANK_DIS, ~R128_FP_BLANK_DIS); - break; - case MT_NONE: - default: - break; - } - } - else - { - OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_DISP_DIS, ~R128_CRTC2_DISP_DIS); - } -} - -/* Unblank screen. */ -static void R128Unblank(ScrnInfoPtr pScrn) -{ - R128InfoPtr info = R128PTR(pScrn); - unsigned char *R128MMIO = info->MMIO; - - if(!info->IsSecondary) - { - switch(info->DisplayType) - { - case MT_LCD: - OUTREGP(R128_LVDS_GEN_CNTL, 0, - ~R128_LVDS_DISPLAY_DIS); - break; - case MT_CRT: - OUTREGP(R128_CRTC_EXT_CNTL, 0, ~R128_CRTC_DISPLAY_DIS); - break; - case MT_DFP: - OUTREGP(R128_FP_GEN_CNTL, 0, ~R128_FP_BLANK_DIS); - break; - case MT_NONE: - default: - break; - } - } - else - { - switch(info->DisplayType) - { - case MT_LCD: - case MT_DFP: - case MT_CRT: - OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~R128_CRTC2_DISP_DIS); - break; - case MT_NONE: - default: - break; - } - } -} - /* Compute log base 2 of val. */ int R128MinBits(int val) { @@ -1058,9 +982,9 @@ static Bool R128PreInitConfig(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Option \"Display\" ignored " "(framebuffer device determines display type)\n"); - else if (info->IsPrimary || info->IsSecondary) + else if (!Display) info->BIOSDisplay = R128_DUALHEAD; - else if (!Display || !xf86NameCmp(Display, "FP")) + else if (!xf86NameCmp(Display, "FP")) info->BIOSDisplay = R128_BIOS_DISPLAY_FP; else if (!xf86NameCmp(Display, "BIOS")) info->BIOSDisplay = INREG8(R128_BIOS_5_SCRATCH); @@ -1079,9 +1003,6 @@ static Bool R128PreInitConfig(ScrnInfoPtr pScrn) info->BIOSDisplay = R128_BIOS_DISPLAY_CRT; } - R128MMIO = NULL; - R128UnmapMMIO(pScrn); - /* RAM */ switch (info->MemCntl & 0x3) { case 0: /* SDR SGRAM 1:1 */ @@ -1256,6 +1177,7 @@ static Bool R128PreInitDDC(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) #endif if (!xf86LoadSubModule(pScrn, "ddc")) return FALSE; + xf86LoadSubModule(pScrn, "i2c"); #if defined(__powerpc__) || defined(__alpha__) || defined(__sparc__) /* Int10 is broken on PPC and some Alphas */ @@ -1281,468 +1203,6 @@ static Bool R128PreInitGamma(ScrnInfoPtr pScrn) return TRUE; } -static void -R128I2CGetBits(I2CBusPtr b, int *Clock, int *data) -{ - ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; - R128InfoPtr info = R128PTR(pScrn); - unsigned long val; - unsigned char *R128MMIO = info->MMIO; - - /* Get the result. */ - val = INREG(info->DDCReg); - *Clock = (val & R128_GPIO_MONID_Y_3) != 0; - *data = (val & R128_GPIO_MONID_Y_0) != 0; - -} - -static void -R128I2CPutBits(I2CBusPtr b, int Clock, int data) -{ - ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; - R128InfoPtr info = R128PTR(pScrn); - unsigned long val; - unsigned char *R128MMIO = info->MMIO; - - val = INREG(info->DDCReg) - & ~(CARD32)(R128_GPIO_MONID_EN_0 | R128_GPIO_MONID_EN_3); - val |= (Clock ? 0:R128_GPIO_MONID_EN_3); - val |= (data ? 0:R128_GPIO_MONID_EN_0); - OUTREG(info->DDCReg, val); -} - - -static Bool -R128I2cInit(ScrnInfoPtr pScrn) -{ - R128InfoPtr info = R128PTR(pScrn); - if ( !xf86LoadSubModule(pScrn, "i2c") ) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to load i2c module\n"); - return FALSE; - } - - info->pI2CBus = xf86CreateI2CBusRec(); - if(!info->pI2CBus) return FALSE; - - info->pI2CBus->BusName = "DDC"; - info->pI2CBus->scrnIndex = pScrn->scrnIndex; - info->DDCReg = R128_GPIO_MONID; - info->pI2CBus->I2CPutBits = R128I2CPutBits; - info->pI2CBus->I2CGetBits = R128I2CGetBits; - info->pI2CBus->AcknTimeout = 5; - - if (!xf86I2CBusInit(info->pI2CBus)) { - return FALSE; - } - return TRUE; -} - -/* return TRUE is a DFP is indeed connected to a DVI port */ -static Bool R128GetDFPInfo(ScrnInfoPtr pScrn) -{ - R128InfoPtr info = R128PTR(pScrn); - int i; - xf86MonPtr MonInfo = NULL; - xf86MonPtr ddc; - unsigned char *R128MMIO = info->MMIO; - - if(!R128I2cInit(pScrn)){ - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "I2C initialization failed!\n"); - } - - OUTREG(info->DDCReg, (INREG(info->DDCReg) - | R128_GPIO_MONID_MASK_0 | R128_GPIO_MONID_MASK_3)); - - OUTREG(info->DDCReg, INREG(info->DDCReg) - & ~(CARD32)(R128_GPIO_MONID_A_0 | R128_GPIO_MONID_A_3)); - - MonInfo = xf86DoEDID_DDC2(XF86_SCRN_ARG(pScrn), info->pI2CBus); - if(!MonInfo) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "No DFP detected\n"); - return FALSE; - } - xf86SetDDCproperties(pScrn, MonInfo); - ddc = pScrn->monitor->DDC; - - for(i=0; i<4; i++) - { - if((ddc->det_mon[i].type == 0) && - (ddc->det_mon[i].section.d_timings.h_active > 0) && - (ddc->det_mon[i].section.d_timings.v_active > 0)) - { - info->PanelXRes = - ddc->det_mon[i].section.d_timings.h_active; - info->PanelYRes = - ddc->det_mon[i].section.d_timings.v_active; - - info->HOverPlus = - ddc->det_mon[i].section.d_timings.h_sync_off; - info->HSyncWidth = - ddc->det_mon[i].section.d_timings.h_sync_width; - info->HBlank = - ddc->det_mon[i].section.d_timings.h_blanking; - info->VOverPlus = - ddc->det_mon[i].section.d_timings.v_sync_off; - info->VSyncWidth = - ddc->det_mon[i].section.d_timings.v_sync_width; - info->VBlank = - ddc->det_mon[i].section.d_timings.v_blanking; - } - } - return TRUE; -} - - -static void R128SetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) -{ - int i; - xf86MonPtr ddc = pScrn->monitor->DDC; - if(flag) /*HSync*/ - { - for(i=0; i<4; i++) - { - if(ddc->det_mon[i].type == DS_RANGES) - { - pScrn->monitor->nHsync = 1; - pScrn->monitor->hsync[0].lo = - ddc->det_mon[i].section.ranges.min_h; - pScrn->monitor->hsync[0].hi = - ddc->det_mon[i].section.ranges.max_h; - return; - } - } - /*if no sync ranges detected in detailed timing table, - let's try to derive them from supported VESA modes - Are we doing too much here!!!? - **/ - i = 0; - if(ddc->timings1.t1 & 0x02) /*800x600@56*/ - { - pScrn->monitor->hsync[i].lo = - pScrn->monitor->hsync[i].hi = 35.2; - i++; - } - if(ddc->timings1.t1 & 0x04) /*640x480@75*/ - { - pScrn->monitor->hsync[i].lo = - pScrn->monitor->hsync[i].hi = 37.5; - i++; - } - if((ddc->timings1.t1 & 0x08) || (ddc->timings1.t1 & 0x01)) - { - pScrn->monitor->hsync[i].lo = - pScrn->monitor->hsync[i].hi = 37.9; - i++; - } - if(ddc->timings1.t2 & 0x40) - { - pScrn->monitor->hsync[i].lo = - pScrn->monitor->hsync[i].hi = 46.9; - i++; - } - if((ddc->timings1.t2 & 0x80) || (ddc->timings1.t2 & 0x08)) - { - pScrn->monitor->hsync[i].lo = - pScrn->monitor->hsync[i].hi = 48.1; - i++; - } - if(ddc->timings1.t2 & 0x04) - { - pScrn->monitor->hsync[i].lo = - pScrn->monitor->hsync[i].hi = 56.5; - i++; - } - if(ddc->timings1.t2 & 0x02) - { - pScrn->monitor->hsync[i].lo = - pScrn->monitor->hsync[i].hi = 60.0; - i++; - } - if(ddc->timings1.t2 & 0x01) - { - pScrn->monitor->hsync[i].lo = - pScrn->monitor->hsync[i].hi = 64.0; - i++; - } - pScrn->monitor->nHsync = i; - } - else /*Vrefresh*/ - { - for(i=0; i<4; i++) - { - if(ddc->det_mon[i].type == DS_RANGES) - { - pScrn->monitor->nVrefresh = 1; - pScrn->monitor->vrefresh[0].lo = - ddc->det_mon[i].section.ranges.min_v; - pScrn->monitor->vrefresh[0].hi = - ddc->det_mon[i].section.ranges.max_v; - return; - } - } - i = 0; - if(ddc->timings1.t1 & 0x02) /*800x600@56*/ - { - pScrn->monitor->vrefresh[i].lo = - pScrn->monitor->vrefresh[i].hi = 56; - i++; - } - if((ddc->timings1.t1 & 0x01) || (ddc->timings1.t2 & 0x08)) - { - pScrn->monitor->vrefresh[i].lo = - pScrn->monitor->vrefresh[i].hi = 60; - i++; - } - if(ddc->timings1.t2 & 0x04) - { - pScrn->monitor->vrefresh[i].lo = - pScrn->monitor->vrefresh[i].hi = 70; - i++; - } - if((ddc->timings1.t1 & 0x08) || (ddc->timings1.t2 & 0x80)) - { - pScrn->monitor->vrefresh[i].lo = - pScrn->monitor->vrefresh[i].hi = 72; - i++; - } - if((ddc->timings1.t1 & 0x04) || (ddc->timings1.t2 & 0x40) - || (ddc->timings1.t2 & 0x02) || (ddc->timings1.t2 & 0x01)) - { - pScrn->monitor->vrefresh[i].lo = - pScrn->monitor->vrefresh[i].hi = 75; - i++; - } - pScrn->monitor->nVrefresh = i; - } -} - -/*********** - free's xf86ValidateModes routine deosn't work well with DFPs - here is our own validation routine. All modes between - 640<=XRes<=MaxRes and 480<=YRes<=MaxYRes will be permitted. - NOTE: RageProII doesn't support rmx, can only work with the - standard modes the monitor can support (scale). -************/ - -static int R128ValidateFPModes(ScrnInfoPtr pScrn) -{ - int i, j, count=0, width, height; - R128InfoPtr info = R128PTR(pScrn); - DisplayModePtr last = NULL, new = NULL, first = NULL; - xf86MonPtr ddc; - - /* Free any allocated modes during configuration. We don't need them*/ - while (pScrn->modes) - { - xf86DeleteMode(&pScrn->modes, pScrn->modes); - } - while (pScrn->modePool) - { - xf86DeleteMode(&pScrn->modePool, pScrn->modePool); - } - - pScrn->virtualX = pScrn->display->virtualX; - pScrn->virtualY = pScrn->display->virtualY; - - /* If no mode specified in config, we use native resolution*/ - if(!pScrn->display->modes[0]) - { - pScrn->display->modes[0] = xnfalloc(16); - sprintf(pScrn->display->modes[0], "%dx%d", - info->PanelXRes, info->PanelYRes); - } - - for(i=0; pScrn->display->modes[i] != NULL; i++) - { - if (sscanf(pScrn->display->modes[i], "%dx%d", &width, &height) == 2) - { - - if(width < 640 || width > info->PanelXRes || - height < 480 || height > info->PanelYRes) - { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Mode %s is out of range.\n" - "Valid mode should be between 640x480-%dx%d\n", - pScrn->display->modes[i], info->PanelXRes, info->PanelYRes); - continue; - } - - new = xnfcalloc(1, sizeof(DisplayModeRec)); - new->prev = last; - new->name = xnfalloc(strlen(pScrn->display->modes[i]) + 1); - strcpy(new->name, pScrn->display->modes[i]); - new->HDisplay = new->CrtcHDisplay = width; - new->VDisplay = new->CrtcVDisplay = height; - - ddc = pScrn->monitor->DDC; - for(j=0; jdet_mon[j].type == 0){ - new->Clock = ddc->det_mon[j].section.d_timings.clock / 1000; - break; - } - } - - if(new->prev) new->prev->next = new; - last = new; - if(!first) first = new; - pScrn->display->virtualX = - pScrn->virtualX = MAX(pScrn->virtualX, width); - pScrn->display->virtualY = - pScrn->virtualY = MAX(pScrn->virtualY, height); - count++; - } - else - { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Mode name %s is invalid\n", pScrn->display->modes[i]); - continue; - } - } - - if(last) - { - last->next = first; - first->prev = last; - pScrn->modes = first; - - /*FIXME: May need to validate line pitch here*/ - { - int dummy = 0; - switch(pScrn->depth / 8) - { - case 1: - dummy = 128 - pScrn->virtualX % 128; - break; - case 2: - dummy = 32 - pScrn->virtualX % 32; - break; - case 3: - case 4: - dummy = 16 - pScrn->virtualX % 16; - } - pScrn->displayWidth = pScrn->virtualX + dummy; - } - - } - - return count; -} - - -/* This is called by R128PreInit to validate modes and compute parameters - for all of the valid modes. */ -static Bool R128PreInitModes(ScrnInfoPtr pScrn) -{ - R128InfoPtr info = R128PTR(pScrn); - ClockRangePtr clockRanges; - int modesFound; - - if(info->isDFP) { - R128MapMem(pScrn); - info->BIOSDisplay = R128_BIOS_DISPLAY_FP; - /* validate if DFP really connected. */ - if(!R128GetDFPInfo(pScrn)) { - info->isDFP = FALSE; - info->BIOSDisplay = R128_BIOS_DISPLAY_CRT; - } else if(!info->isPro2) { - /* RageProII doesn't support rmx, we can't use native-mode - stretching for other non-native modes. It will rely on - whatever VESA modes monitor can support. */ - modesFound = R128ValidateFPModes(pScrn); - if(modesFound < 1) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "No valid mode found for this DFP/LCD\n"); - R128UnmapMem(pScrn); - return FALSE; - - } - } - R128UnmapMem(pScrn); - } - - if(!info->isDFP || info->isPro2) { - /* Get mode information */ - pScrn->progClock = TRUE; - clockRanges = xnfcalloc(sizeof(*clockRanges), 1); - clockRanges->next = NULL; - clockRanges->minClock = info->pll.min_pll_freq; - clockRanges->maxClock = info->pll.max_pll_freq * 10; - clockRanges->clockIndex = -1; - if (info->HasPanelRegs || info->isDFP) { - clockRanges->interlaceAllowed = FALSE; - clockRanges->doubleScanAllowed = FALSE; - } else { - clockRanges->interlaceAllowed = TRUE; - clockRanges->doubleScanAllowed = TRUE; - } - - if(pScrn->monitor->DDC) { - /*if we still don't know sync range yet, let's try EDID. - Note that, since we can have dual heads, the Xconfigurator - may not be able to probe both monitors correctly through - vbe probe function (R128ProbeDDC). Here we provide an - additional way to auto-detect sync ranges if they haven't - been added to XF86Config manually. - **/ - if(pScrn->monitor->nHsync <= 0) - R128SetSyncRangeFromEdid(pScrn, 1); - if(pScrn->monitor->nVrefresh <= 0) - R128SetSyncRangeFromEdid(pScrn, 0); - } - - modesFound = xf86ValidateModes(pScrn, - pScrn->monitor->Modes, - pScrn->display->modes, - clockRanges, - NULL, /* linePitches */ - 8 * 64, /* minPitch */ - 8 * 1024, /* maxPitch */ -/* - * ATI docs say pitchInc must be 8 * 64, but this doesn't permit a pitch of - * 800 bytes, which is known to work on the Rage128 LF on clamshell iBooks - */ - 8 * 32, /* pitchInc */ - 128, /* minHeight */ - 2048, /* maxHeight */ - pScrn->display->virtualX, - pScrn->display->virtualY, - info->FbMapSize, - LOOKUP_BEST_REFRESH); - - if (modesFound < 1 && info->FBDev) { - fbdevHWUseBuildinMode(pScrn); - pScrn->displayWidth = fbdevHWGetLineLength(pScrn)/(pScrn->bitsPerPixel/8); - modesFound = 1; - } - - if (modesFound == -1) return FALSE; - xf86PruneDriverModes(pScrn); - if (!modesFound || !pScrn->modes) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); - return FALSE; - } - xf86SetCrtcForModes(pScrn, 0); - } - /* Set DPI */ - pScrn->currentMode = pScrn->modes; - xf86PrintModes(pScrn); - - xf86SetDpi(pScrn, 0, 0); - - /* Get ScreenInit function */ - if (!xf86LoadSubModule(pScrn, "fb")) return FALSE; - - info->CurrentLayout.displayWidth = pScrn->displayWidth; - info->CurrentLayout.mode = pScrn->currentMode; - - return TRUE; -} - /* This is called by R128PreInit to initialize the hardware cursor. */ static Bool R128PreInitCursor(ScrnInfoPtr pScrn) { @@ -1885,6 +1345,43 @@ static Bool R128PreInitDRI(ScrnInfoPtr pScrn) } #endif +static Bool R128PreInitControllers(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) +{ + R128InfoPtr info = R128PTR(pScrn); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; + int mask; + int found = 0; + + if (info->IsPrimary) + mask = 1; + else if (info->IsSecondary) + mask = 2; + else + mask = 3; + + if (!R128GetBIOSParameters(pScrn, pInt10)) + return FALSE; + + if (!R128GetPLLParameters(pScrn)) + return FALSE; + + if (!R128AllocateControllers(pScrn, mask)) + return FALSE; + + if (!R128SetupConnectors(pScrn)) + return FALSE; + + for (i = 0; i < config->num_output; i++) { + xf86OutputPtr output = config->output[i]; + + output->status = (*output->funcs->detect) (output); + if (output->status == XF86OutputStatusConnected) + found++; + } + return !!found; +} + static void R128ProbeDDC(ScrnInfoPtr pScrn, int indx) { @@ -1899,6 +1396,17 @@ R128ProbeDDC(ScrnInfoPtr pScrn, int indx) #endif } +static Bool R128CRTCResize(ScrnInfoPtr pScrn, int width, int height) +{ + pScrn->virtualX = width; + pScrn->virtualY = height; + return TRUE; +} + +static const xf86CrtcConfigFuncsRec R128CRTCResizeFuncs = { + R128CRTCResize +}; + /* R128PreInit is called once at server startup. */ Bool R128PreInit(ScrnInfoPtr pScrn, int flags) { @@ -1976,6 +1484,9 @@ Bool R128PreInit(ScrnInfoPtr pScrn, int flags) #endif pScrn->monitor = pScrn->confScreen->monitor; + /* Allocate an xf86CrtcConfig */ + xf86CrtcConfigInit(pScrn, &R128CRTCResizeFuncs); + if (!R128PreInitVisual(pScrn)) goto fail; /* We can't do this until we have a @@ -2016,8 +1527,6 @@ Bool R128PreInit(ScrnInfoPtr pScrn, int flags) "module load skipped\n"); #endif - - if (!R128PreInitWeight(pScrn)) goto fail; if(xf86GetOptValInteger(info->Options, OPTION_VIDEO_KEY, &(info->videoKey))) { @@ -2053,20 +1562,30 @@ Bool R128PreInit(ScrnInfoPtr pScrn, int flags) } if (!info->FBDev) - if (!R128PreInitInt10(pScrn, &pInt10)) goto fail; - - if (!R128PreInitConfig(pScrn)) goto fail; + if (!R128PreInitInt10(pScrn, &pInt10)) goto fail; - if (!R128GetBIOSParameters(pScrn, pInt10)) goto fail; + if (!R128PreInitConfig(pScrn)) goto fail; - if (!R128GetPLLParameters(pScrn)) goto fail; + xf86CrtcSetSizeRange(pScrn, 320, 200, 4096, 4096); /* Don't fail on this one */ R128PreInitDDC(pScrn, pInt10); - if (!R128PreInitGamma(pScrn)) goto fail; + if (!R128PreInitControllers(pScrn, pInt10)) goto fail; + + if (!xf86InitialConfiguration(pScrn, TRUE)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); + goto fail; + } + pScrn->displayWidth = (pScrn->virtualX + 63) & ~63; - if (!R128PreInitModes(pScrn)) goto fail; + /* Set display resolution */ + xf86SetDpi(pScrn, 0, 0); + + /* Get ScreenInit function */ + if (!xf86LoadSubModule(pScrn, "fb")) return FALSE; + + if (!R128PreInitGamma(pScrn)) goto fail; if (!R128PreInitCursor(pScrn)) goto fail; @@ -2074,6 +1593,18 @@ Bool R128PreInit(ScrnInfoPtr pScrn, int flags) if (!R128PreInitDRI(pScrn)) goto fail; #endif + info->CurrentLayout.displayWidth = pScrn->displayWidth; + + if (!xf86RandR12PreInit(pScrn)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n"); + goto fail; + } + + if (pScrn->modes == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n"); + goto fail; + } + /* Free the video bios (if applicable) */ if (info->VBIOS) { free(info->VBIOS); @@ -2084,6 +1615,9 @@ Bool R128PreInit(ScrnInfoPtr pScrn, int flags) if (pInt10) xf86FreeInt10(pInt10); + if (info->MMIO) R128UnmapMMIO(pScrn); + info->MMIO = NULL; + xf86DrvMsg(pScrn->scrnIndex, X_NOTICE, "For information on using the multimedia capabilities\n\tof this" " adapter, please see http://gatos.sf.net.\n"); @@ -2116,56 +1650,66 @@ static void R128LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, VisualPtr pVisual) { R128InfoPtr info = R128PTR(pScrn); - unsigned char *R128MMIO = info->MMIO; - int i, j; - int idx; - unsigned char r, g, b; - - /* If the second monitor is connected, we also - need to deal with the secondary palette*/ - if (info->IsSecondary) j = 1; - else j = 0; - - PAL_SELECT(j); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i, j; + int c, index; + CARD16 lut_r[256], lut_g[256], lut_b[256]; + + for (c = 0; c < xf86_config->num_crtc; c++) { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + R128CrtcPrivatePtr r128_crtc = crtc->driver_private; + + for (i = 0 ; i < 256; i++) { + lut_r[i] = r128_crtc->lut_r[i] << 8; + lut_g[i] = r128_crtc->lut_g[i] << 8; + lut_b[i] = r128_crtc->lut_b[i] << 8; + } + switch (info->CurrentLayout.depth) { + case 15: + for (i = 0; i < numColors; i++) { + index = indices[i]; + for (j = 0; j < 8; j++) { + lut_r[index * 8 + j] = colors[index].red << 8; + lut_g[index * 8 + j] = colors[index].green << 8; + lut_b[index * 8 + j] = colors[index].blue << 8; + } + } + case 16: + for (i = 0; i < numColors; i++) { + index = indices[i]; + + /* XXX: The old version of R128LoadPalette did not do this and + * the old version of RADEONLoadPalette has a comment asking why. + */ + if (i <= 31) { + for (j = 0; j < 8; j++) { + lut_r[index * 8 + j] = colors[index].red << 8; + lut_b[index * 8 + j] = colors[index].blue << 8; + } + } - /* Select palette 0 (main CRTC) if using FP-enabled chip */ - /*if (info->HasPanelRegs || info->isDFP) PAL_SELECT(0);*/ + for (j = 0; j < 4; j++) { + lut_g[index * 4 + j] = colors[index].green << 8; + } + } + default: + for (i = 0; i < numColors; i++) { + index = indices[i]; + lut_r[index] = colors[index].red << 8; + lut_g[index] = colors[index].green << 8; + lut_b[index] = colors[index].blue << 8; + } + break; + } - if (info->CurrentLayout.depth == 15) { - /* 15bpp mode. This sends 32 values. */ - for (i = 0; i < numColors; i++) { - idx = indices[i]; - r = colors[idx].red; - g = colors[idx].green; - b = colors[idx].blue; - OUTPAL(idx * 8, r, g, b); - } - } - else if (info->CurrentLayout.depth == 16) { - /* 16bpp mode. This sends 64 values. */ - /* There are twice as many green values as - there are values for red and blue. So, - we take each red and blue pair, and - combine it with each of the two green - values. */ - for (i = 0; i < numColors; i++) { - idx = indices[i]; - r = colors[idx / 2].red; - g = colors[idx].green; - b = colors[idx / 2].blue; - OUTPAL(idx * 4, r, g, b); - } - } - else { - /* 8bpp mode. This sends 256 values. */ - for (i = 0; i < numColors; i++) { - idx = indices[i]; - r = colors[idx].red; - b = colors[idx].blue; - g = colors[idx].green; - OUTPAL(idx, r, g, b); - } + /* Make the change through RandR */ +#ifdef RANDR_12_INTERFACE + if (crtc->randr_crtc) + RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b); + else +#endif + crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256); } } @@ -2296,14 +1840,6 @@ Bool R128ScreenInit(SCREEN_INIT_ARGS_DECL) info->PaletteSavedOnVT = FALSE; R128Save(pScrn); - if (info->FBDev) { - if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) return FALSE; - } else { - if (!R128ModeInit(pScrn, pScrn->currentMode)) return FALSE; - } - - R128SaveScreen(pScreen, SCREEN_SAVER_ON); - pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); /* Visual setup */ miClearVisualTypes(); @@ -2701,6 +2237,19 @@ Bool R128ScreenInit(SCREEN_INIT_ARGS_DECL) #endif } + pScrn->vtSema = TRUE; + /* xf86CrtcRotate accesses pScrn->pScreen */ + pScrn->pScreen = pScreen; + + if (info->FBDev) { + if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) return FALSE; + } else { + if (!xf86SetDesiredModes(pScrn)) return FALSE; + } + + R128SaveScreen(pScreen, SCREEN_SAVER_ON); + //pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); + /* DGA setup */ R128DGAInit(pScreen); @@ -2737,28 +2286,11 @@ Bool R128ScreenInit(SCREEN_INIT_ARGS_DECL) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using software cursor\n"); } - /* Colormap setup */ - if (!miCreateDefColormap(pScreen)) return FALSE; - if (!xf86HandleColormaps(pScreen, 256, info->dac6bits ? 6 : 8, - (info->FBDev ? fbdevHWLoadPaletteWeak() : - R128LoadPalette), NULL, - CMAP_PALETTED_TRUECOLOR - | CMAP_RELOAD_ON_MODE_SWITCH -#if 0 /* This option messes up text mode! (eich@suse.de) */ - | CMAP_LOAD_EVEN_IF_OFFSCREEN -#endif - )) return FALSE; - /* DPMS setup - FIXME: also for mirror mode in non-fbdev case? - Michel */ if (info->FBDev) xf86DPMSInit(pScreen, fbdevHWDPMSSetWeak(), 0); - - else { - if (info->DisplayType == MT_LCD) - xf86DPMSInit(pScreen, R128DisplayPowerManagementSetLCD, 0); - else - xf86DPMSInit(pScreen, R128DisplayPowerManagementSet, 0); - } + else + xf86DPMSInit(pScreen, xf86DPMSSet, 0); if (!info->IsSecondary) R128InitVideo(pScreen); @@ -2793,11 +2325,25 @@ Bool R128ScreenInit(SCREEN_INIT_ARGS_DECL) info->BlockHandler = pScreen->BlockHandler; pScreen->BlockHandler = R128BlockHandler; + if (!xf86CrtcScreenInit(pScreen)) return FALSE; + + /* Colormap setup */ + if (!miCreateDefColormap(pScreen)) return FALSE; + if (!xf86HandleColormaps(pScreen, 256, info->dac6bits ? 6 : 8, + (info->FBDev ? fbdevHWLoadPaletteWeak() : + R128LoadPalette), NULL, + CMAP_PALETTED_TRUECOLOR + | CMAP_RELOAD_ON_MODE_SWITCH +#if 0 /* This option messes up text mode! (eich@suse.de) */ + | CMAP_LOAD_EVEN_IF_OFFSCREEN +#endif + )) return FALSE; + return TRUE; } /* Write common registers (initialized to 0). */ -static void R128RestoreCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) +void R128RestoreCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) { R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; @@ -2821,7 +2367,7 @@ static void R128RestoreCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) } /* Write CRTC registers. */ -static void R128RestoreCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) +void R128RestoreCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) { R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; @@ -2844,7 +2390,7 @@ static void R128RestoreCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) } /* Write CRTC2 registers. */ -static void R128RestoreCrtc2Registers(ScrnInfoPtr pScrn, +void R128RestoreCrtc2Registers(ScrnInfoPtr pScrn, R128SavePtr restore) { R128InfoPtr info = R128PTR(pScrn); @@ -2863,7 +2409,7 @@ static void R128RestoreCrtc2Registers(ScrnInfoPtr pScrn, } /* Write flat panel registers */ -static void R128RestoreFPRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) +void R128RestoreFPRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) { R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; @@ -2936,7 +2482,7 @@ static void R128PLL2WriteUpdate(ScrnInfoPtr pScrn) } /* Write PLL registers. */ -static void R128RestorePLLRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) +void R128RestorePLLRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) { R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; @@ -2999,7 +2545,7 @@ static void R128RestorePLLRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) } /* Write PLL2 registers. */ -static void R128RestorePLL2Registers(ScrnInfoPtr pScrn, R128SavePtr restore) +void R128RestorePLL2Registers(ScrnInfoPtr pScrn, R128SavePtr restore) { R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; @@ -3068,7 +2614,7 @@ static void R128RestorePLL2Registers(ScrnInfoPtr pScrn, R128SavePtr restore) } /* Write DDA registers. */ -static void R128RestoreDDARegisters(ScrnInfoPtr pScrn, R128SavePtr restore) +void R128RestoreDDARegisters(ScrnInfoPtr pScrn, R128SavePtr restore) { R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; @@ -3078,7 +2624,7 @@ static void R128RestoreDDARegisters(ScrnInfoPtr pScrn, R128SavePtr restore) } /* Write DDA registers. */ -static void R128RestoreDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr restore) +void R128RestoreDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr restore) { R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; @@ -3087,126 +2633,6 @@ static void R128RestoreDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr restore) OUTREG(R128_DDA2_ON_OFF, restore->dda2_on_off); } -/* Write palette data. */ -static void R128RestorePalette(ScrnInfoPtr pScrn, R128SavePtr restore) -{ - R128InfoPtr info = R128PTR(pScrn); - unsigned char *R128MMIO = info->MMIO; - int i; - - if (!restore->palette_valid) return; - - PAL_SELECT(1); - OUTPAL_START(0); - for (i = 0; i < 256; i++) { - R128WaitForFifo(pScrn, 32); /* delay */ - OUTPAL_NEXT_CARD32(restore->palette2[i]); - } - - PAL_SELECT(0); - OUTPAL_START(0); - for (i = 0; i < 256; i++) { - R128WaitForFifo(pScrn, 32); /* delay */ - OUTPAL_NEXT_CARD32(restore->palette[i]); - } - -} - -/* Write out state to define a new video mode. */ -static void R128RestoreMode(ScrnInfoPtr pScrn, R128SavePtr restore) -{ - R128InfoPtr info = R128PTR(pScrn); - DevUnion* pPriv; - R128EntPtr pR128Ent; - static R128SaveRec restore0; - - R128TRACE(("R128RestoreMode(%p)\n", restore)); - if(!info->HasCRTC2) - { - R128RestoreCommonRegisters(pScrn, restore); - R128RestoreDDARegisters(pScrn, restore); - R128RestoreCrtcRegisters(pScrn, restore); - if((info->DisplayType == MT_DFP) || - (info->DisplayType == MT_LCD)) - { - R128RestoreFPRegisters(pScrn, restore); - } - R128RestorePLLRegisters(pScrn, restore); - return; - } - - pPriv = xf86GetEntityPrivate(pScrn->entityList[0], - getR128EntityIndex()); - pR128Ent = pPriv->ptr; - - - /***** - When changing mode with Dual-head card (VE/M6), care must - be taken for the special order in setting registers. CRTC2 has - to be set before changing CRTC_EXT register. - In the dual-head setup, X server calls this routine twice with - primary and secondary pScrn pointers respectively. The calls - can come with different order. Regardless the order of X server issuing - the calls, we have to ensure we set registers in the right order!!! - Otherwise we may get a blank screen. - *****/ - - if(info->IsSecondary) - { - if (!pR128Ent->RestorePrimary && !info->SwitchingMode) - R128RestoreCommonRegisters(pScrn, restore); - R128RestoreDDA2Registers(pScrn, restore); - R128RestoreCrtc2Registers(pScrn, restore); - R128RestorePLL2Registers(pScrn, restore); - - if(info->SwitchingMode) return; - - pR128Ent->IsSecondaryRestored = TRUE; - - if(pR128Ent->RestorePrimary) - { - R128InfoPtr info0 = R128PTR(pR128Ent->pPrimaryScrn); - pR128Ent->RestorePrimary = FALSE; - - R128RestoreCrtcRegisters(pScrn, &restore0); - if((info0->DisplayType == MT_DFP) || - (info0->DisplayType == MT_LCD)) - { - R128RestoreFPRegisters(pScrn, &restore0); - } - - R128RestorePLLRegisters(pScrn, &restore0); - pR128Ent->IsSecondaryRestored = FALSE; - - } - } - else - { - if (!pR128Ent->IsSecondaryRestored) - R128RestoreCommonRegisters(pScrn, restore); - R128RestoreDDARegisters(pScrn, restore); - if(!pR128Ent->HasSecondary || pR128Ent->IsSecondaryRestored - || info->SwitchingMode) - { - pR128Ent->IsSecondaryRestored = FALSE; - R128RestoreCrtcRegisters(pScrn, restore); - if((info->DisplayType == MT_DFP) || - (info->DisplayType == MT_LCD)) - { - R128RestoreFPRegisters(pScrn, restore); - } - R128RestorePLLRegisters(pScrn, restore); - } - else - { - memcpy(&restore0, restore, sizeof(restore0)); - pR128Ent->RestorePrimary = TRUE; - } - } - - R128RestorePalette(pScrn, restore); -} - /* Read common registers. */ static void R128SaveCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr save) { @@ -3450,9 +2876,19 @@ static void R128Restore(ScrnInfoPtr pScrn) OUTREG(R128_CLOCK_CNTL_INDEX, restore->clock_cntl_index); OUTREG(R128_GEN_RESET_CNTL, restore->gen_reset_cntl); OUTREG(R128_DP_DATATYPE, restore->dp_datatype); + + R128RestoreCommonRegisters(pScrn, restore); + if (info->HasCRTC2) { + R128RestoreDDA2Registers(pScrn, restore); + R128RestoreCrtc2Registers(pScrn, restore); + R128RestorePLL2Registers(pScrn, restore); + } + R128RestoreDDARegisters(pScrn, restore); + R128RestoreCrtcRegisters(pScrn, restore); + R128RestorePLLRegisters(pScrn, restore); + R128RestoreFPRegisters(pScrn, restore); } - R128RestoreMode(pScrn, restore); #ifdef WITH_VGAHW if (info->VGAAccess) { vgaHWPtr hwp = VGAHWPTR(pScrn); @@ -3492,7 +2928,7 @@ static void R128Restore(ScrnInfoPtr pScrn) } /* Define common registers for requested video mode. */ -static void R128InitCommonRegisters(R128SavePtr save, R128InfoPtr info) +void R128InitCommonRegisters(R128SavePtr save, R128InfoPtr info) { save->ovr_clr = 0; save->ovr_wid_left_right = 0; @@ -3518,8 +2954,64 @@ static void R128InitCommonRegisters(R128SavePtr save, R128InfoPtr info) save->bus_cntl |= R128_BUS_RD_DISCARD_EN | R128_BUS_RD_ABORT_EN; } +Bool R128InitCrtcBase(xf86CrtcPtr crtc, R128SavePtr save, int x, int y) +{ + ScrnInfoPtr pScrn = crtc->scrn; + R128InfoPtr info = R128PTR(pScrn); + int offset = y * info->CurrentLayout.displayWidth + x; + int Base = pScrn->fbOffset; + + switch (info->CurrentLayout.pixel_code) { + case 15: + case 16: offset *= 2; break; + case 24: offset *= 3; break; + case 32: offset *= 4; break; + } + Base += offset; + + if (crtc->rotatedData != NULL) + Base = pScrn->fbOffset + (char *)crtc->rotatedData - (char *)info->FB; + + Base &= ~7; /* 3 lower bits are always 0 */ + if (info->CurrentLayout.pixel_code == 24) + Base += 8 * (Base % 3); /* Must be multiple of 8 and 3 */ + + save->crtc_offset = Base; + save->crtc_offset_cntl = 0; + + return TRUE; +} + +Bool R128InitCrtc2Base(xf86CrtcPtr crtc, R128SavePtr save, int x, int y) +{ + ScrnInfoPtr pScrn = crtc->scrn; + R128InfoPtr info = R128PTR(pScrn); + int offset = y * info->CurrentLayout.displayWidth + x; + int Base = pScrn->fbOffset; + + switch (info->CurrentLayout.pixel_code) { + case 15: + case 16: offset *= 2; break; + case 24: offset *= 3; break; + case 32: offset *= 4; break; + } + Base += offset; + + if (crtc->rotatedData != NULL) + Base = pScrn->fbOffset + (char *)crtc->rotatedData - (char *)info->FB; + + Base &= ~7; /* 3 lower bits are always 0 */ + if (info->CurrentLayout.pixel_code == 24) + Base += 8 * (Base % 3); /* Must be multiple of 8 and 3 */ + + save->crtc2_offset = Base; + save->crtc2_offset_cntl = 0; + + return TRUE; +} + /* Define CRTC registers for requested video mode. */ -static Bool R128InitCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save, +Bool R128InitCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save, DisplayModePtr mode, R128InfoPtr info) { int format; @@ -3633,8 +3125,6 @@ static Bool R128InitCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save, | ((mode->Flags & V_NVSYNC) ? R128_CRTC_V_SYNC_POL : 0)); - save->crtc_offset = 0; - save->crtc_offset_cntl = 0; save->crtc_pitch = info->CurrentLayout.displayWidth / 8; R128TRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n", @@ -3654,7 +3144,7 @@ static Bool R128InitCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save, } /* Define CRTC2 registers for requested video mode. */ -static Bool R128InitCrtc2Registers(ScrnInfoPtr pScrn, R128SavePtr save, +Bool R128InitCrtc2Registers(ScrnInfoPtr pScrn, R128SavePtr save, DisplayModePtr mode, R128InfoPtr info) { int format; @@ -3727,10 +3217,6 @@ static Bool R128InitCrtc2Registers(ScrnInfoPtr pScrn, R128SavePtr save, | ((mode->Flags & V_NVSYNC) ? R128_CRTC2_V_SYNC_POL : 0)); - - save->crtc2_offset = 0; - save->crtc2_offset_cntl = 0; - save->crtc2_pitch = info->CurrentLayout.displayWidth / 8; R128TRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n", @@ -3740,7 +3226,7 @@ static Bool R128InitCrtc2Registers(ScrnInfoPtr pScrn, R128SavePtr save, } /* Define CRTC registers for requested video mode. */ -static void R128InitFPRegisters(R128SavePtr orig, R128SavePtr save, +void R128InitFPRegisters(R128SavePtr orig, R128SavePtr save, DisplayModePtr mode, R128InfoPtr info) { int xres = mode->CrtcHDisplay; @@ -3853,7 +3339,7 @@ static void R128InitFPRegisters(R128SavePtr orig, R128SavePtr save, } /* Define PLL registers for requested video mode. */ -static void R128InitPLLRegisters(ScrnInfoPtr pScrn, R128SavePtr save, +void R128InitPLLRegisters(ScrnInfoPtr pScrn, R128SavePtr save, R128PLLPtr pll, double dot_clock) { unsigned long freq = dot_clock * 100; @@ -3905,7 +3391,7 @@ static void R128InitPLLRegisters(ScrnInfoPtr pScrn, R128SavePtr save, } /* Define PLL2 registers for requested video mode. */ -static void R128InitPLL2Registers(ScrnInfoPtr pScrn, R128SavePtr save, +void R128InitPLL2Registers(ScrnInfoPtr pScrn, R128SavePtr save, R128PLLPtr pll, double dot_clock) { unsigned long freq = dot_clock * 100; @@ -3957,7 +3443,7 @@ static void R128InitPLL2Registers(ScrnInfoPtr pScrn, R128SavePtr save, } /* Define DDA registers for requested video mode. */ -static Bool R128InitDDARegisters(ScrnInfoPtr pScrn, R128SavePtr save, +Bool R128InitDDARegisters(ScrnInfoPtr pScrn, R128SavePtr save, R128PLLPtr pll, R128InfoPtr info, DisplayModePtr mode) { @@ -4026,7 +3512,7 @@ static Bool R128InitDDARegisters(ScrnInfoPtr pScrn, R128SavePtr save, } /* Define DDA2 registers for requested video mode. */ -static Bool R128InitDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr save, +Bool R128InitDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr save, R128PLLPtr pll, R128InfoPtr info, DisplayModePtr mode) { @@ -4106,122 +3592,6 @@ static void R128InitPalette(R128SavePtr save) } #endif -/* Define registers for a requested video mode. */ -static Bool R128Init(ScrnInfoPtr pScrn, DisplayModePtr mode, R128SavePtr save) -{ - R128InfoPtr info = R128PTR(pScrn); - double dot_clock = mode->Clock/1000.0; - -#if R128_DEBUG - ErrorF("%-12.12s %7.2f %4d %4d %4d %4d %4d %4d %4d %4d (%d,%d)", - mode->name, - dot_clock, - - mode->HDisplay, - mode->HSyncStart, - mode->HSyncEnd, - mode->HTotal, - - mode->VDisplay, - mode->VSyncStart, - mode->VSyncEnd, - mode->VTotal, - pScrn->depth, - pScrn->bitsPerPixel); - if (mode->Flags & V_DBLSCAN) ErrorF(" D"); - if (mode->Flags & V_CSYNC) ErrorF(" C"); - if (mode->Flags & V_INTERLACE) ErrorF(" I"); - if (mode->Flags & V_PHSYNC) ErrorF(" +H"); - if (mode->Flags & V_NHSYNC) ErrorF(" -H"); - if (mode->Flags & V_PVSYNC) ErrorF(" +V"); - if (mode->Flags & V_NVSYNC) ErrorF(" -V"); - ErrorF("\n"); - ErrorF("%-12.12s %7.2f %4d %4d %4d %4d %4d %4d %4d %4d (%d,%d)", - mode->name, - dot_clock, - - mode->CrtcHDisplay, - mode->CrtcHSyncStart, - mode->CrtcHSyncEnd, - mode->CrtcHTotal, - - mode->CrtcVDisplay, - mode->CrtcVSyncStart, - mode->CrtcVSyncEnd, - mode->CrtcVTotal, - pScrn->depth, - pScrn->bitsPerPixel); - if (mode->Flags & V_DBLSCAN) ErrorF(" D"); - if (mode->Flags & V_CSYNC) ErrorF(" C"); - if (mode->Flags & V_INTERLACE) ErrorF(" I"); - if (mode->Flags & V_PHSYNC) ErrorF(" +H"); - if (mode->Flags & V_NHSYNC) ErrorF(" -H"); - if (mode->Flags & V_PVSYNC) ErrorF(" +V"); - if (mode->Flags & V_NVSYNC) ErrorF(" -V"); - ErrorF("\n"); -#endif - - info->Flags = mode->Flags; - - if(info->IsSecondary) - { - if (!R128InitCrtc2Registers(pScrn, save, - pScrn->currentMode,info)) - return FALSE; - R128InitPLL2Registers(pScrn, save, &info->pll, dot_clock); - if (!R128InitDDA2Registers(pScrn, save, &info->pll, info, mode)) - return FALSE; - } - else - { - R128InitCommonRegisters(save, info); - if(!R128InitCrtcRegisters(pScrn, save, mode, info)) - return FALSE; - if(dot_clock) - { - R128InitPLLRegisters(pScrn, save, &info->pll, dot_clock); - if (!R128InitDDARegisters(pScrn, save, &info->pll, info, mode)) - return FALSE; - } - else - { - save->ppll_ref_div = info->SavedReg.ppll_ref_div; - save->ppll_div_3 = info->SavedReg.ppll_div_3; - save->htotal_cntl = info->SavedReg.htotal_cntl; - save->dda_config = info->SavedReg.dda_config; - save->dda_on_off = info->SavedReg.dda_on_off; - } - /* not used for now */ - /*if (!info->PaletteSavedOnVT) RADEONInitPalette(save);*/ - } - - if (((info->DisplayType == MT_DFP) || - (info->DisplayType == MT_LCD))) - { - R128InitFPRegisters(&info->SavedReg, save, mode, info); - } - - R128TRACE(("R128Init returns %p\n", save)); - return TRUE; -} - -/* Initialize a new mode. */ -static Bool R128ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) -{ - R128InfoPtr info = R128PTR(pScrn); - - if (!R128Init(pScrn, mode, &info->ModeReg)) return FALSE; - /* FIXME? DRILock/DRIUnlock here? */ - pScrn->vtSema = TRUE; - R128Blank(pScrn); - R128RestoreMode(pScrn, &info->ModeReg); - R128Unblank(pScrn); - - info->CurrentLayout.mode = mode; - - return TRUE; -} - static Bool R128SaveScreen(ScreenPtr pScreen, int mode) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); @@ -4252,7 +3622,7 @@ Bool R128SwitchMode(SWITCH_MODE_ARGS_DECL) Bool ret; info->SwitchingMode = TRUE; - ret = R128ModeInit(pScrn, mode); + ret = xf86SetSingleMode(pScrn, mode, RR_Rotate_0); info->SwitchingMode = FALSE; return ret; } @@ -4379,10 +3749,16 @@ Bool R128EnterVT(VT_FUNC_ARGS_DECL) R128InfoPtr info = R128PTR(pScrn); R128TRACE(("R128EnterVT\n")); + + pScrn->vtSema = TRUE; if (info->FBDev) { if (!fbdevHWEnterVT(VT_FUNC_ARGS)) return FALSE; - } else - if (!R128ModeInit(pScrn, pScrn->currentMode)) return FALSE; + } else { + if (!xf86SetDesiredModes(pScrn)) return FALSE; + } + + //if (!R128ModeInit(pScrn, pScrn->currentMode)) return FALSE; + if (info->accelOn) R128EngineInit(pScrn); @@ -4399,7 +3775,7 @@ Bool R128EnterVT(VT_FUNC_ARGS_DECL) #endif info->PaletteSavedOnVT = FALSE; - pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); + //pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); return TRUE; } @@ -4504,130 +3880,3 @@ void R128FreeScreen(FREE_SCREEN_ARGS_DECL) #endif R128FreeRec(pScrn); } - -/* Sets VESA Display Power Management Signaling (DPMS) Mode. */ -static void R128DisplayPowerManagementSet(ScrnInfoPtr pScrn, - int PowerManagementMode, int flags) -{ - R128InfoPtr info = R128PTR(pScrn); - unsigned char *R128MMIO = info->MMIO; - int mask = (R128_CRTC_DISPLAY_DIS - | R128_CRTC_HSYNC_DIS - | R128_CRTC_VSYNC_DIS); - int mask2 = R128_CRTC2_DISP_DIS; - - switch (PowerManagementMode) { - case DPMSModeOn: - /* Screen: On; HSync: On, VSync: On */ - if (info->IsSecondary) - OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~mask2); - else - OUTREGP(R128_CRTC_EXT_CNTL, 0, ~mask); - break; - case DPMSModeStandby: - /* Screen: Off; HSync: Off, VSync: On */ - if (info->IsSecondary) - OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_DISP_DIS, ~mask2); - else - OUTREGP(R128_CRTC_EXT_CNTL, - R128_CRTC_DISPLAY_DIS | R128_CRTC_HSYNC_DIS, ~mask); - break; - case DPMSModeSuspend: - /* Screen: Off; HSync: On, VSync: Off */ - if (info->IsSecondary) - OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_DISP_DIS, ~mask2); - else - OUTREGP(R128_CRTC_EXT_CNTL, - R128_CRTC_DISPLAY_DIS | R128_CRTC_VSYNC_DIS, ~mask); - break; - case DPMSModeOff: - /* Screen: Off; HSync: Off, VSync: Off */ - if (info->IsSecondary) - OUTREGP(R128_CRTC2_GEN_CNTL, mask2, ~mask2); - else - OUTREGP(R128_CRTC_EXT_CNTL, mask, ~mask); - break; - } - if(info->isDFP) { - switch (PowerManagementMode) { - case DPMSModeOn: - OUTREG(R128_FP_GEN_CNTL, INREG(R128_FP_GEN_CNTL) | (R128_FP_FPON | R128_FP_TDMS_EN)); - break; - case DPMSModeStandby: - case DPMSModeSuspend: - case DPMSModeOff: - OUTREG(R128_FP_GEN_CNTL, INREG(R128_FP_GEN_CNTL) & ~(R128_FP_FPON | R128_FP_TDMS_EN)); - break; - } - } -} - -static int r128_set_backlight_enable(ScrnInfoPtr pScrn, int on); - -static void R128DisplayPowerManagementSetLCD(ScrnInfoPtr pScrn, - int PowerManagementMode, int flags) -{ - R128InfoPtr info = R128PTR(pScrn); - unsigned char *R128MMIO = info->MMIO; - int mask = R128_LVDS_DISPLAY_DIS; - - switch (PowerManagementMode) { - case DPMSModeOn: - /* Screen: On; HSync: On, VSync: On */ - OUTREGP(R128_LVDS_GEN_CNTL, 0, ~mask); - r128_set_backlight_enable(pScrn, 1); - break; - case DPMSModeStandby: - /* Fall through */ - case DPMSModeSuspend: - /* Fall through */ - break; - case DPMSModeOff: - /* Screen: Off; HSync: Off, VSync: Off */ - OUTREGP(R128_LVDS_GEN_CNTL, mask, ~mask); - r128_set_backlight_enable(pScrn, 0); - break; - } -} - -static int r128_set_backlight_enable(ScrnInfoPtr pScrn, int on) -{ - R128InfoPtr info = R128PTR(pScrn); - unsigned char *R128MMIO = info->MMIO; - unsigned int lvds_gen_cntl = INREG(R128_LVDS_GEN_CNTL); - - lvds_gen_cntl |= (/*R128_LVDS_BL_MOD_EN |*/ R128_LVDS_BLON); - if (on) { - lvds_gen_cntl |= R128_LVDS_DIGON; - if (!(lvds_gen_cntl & R128_LVDS_ON)) { - lvds_gen_cntl &= ~R128_LVDS_BLON; - OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl); - (void)INREG(R128_LVDS_GEN_CNTL); - usleep(10000); - lvds_gen_cntl |= R128_LVDS_BLON; - OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl); - } -#if 0 - lvds_gen_cntl &= ~R128_LVDS_BL_MOD_LEVEL_MASK; - lvds_gen_cntl |= (0xFF /* backlight_conv[level] */ << - R128_LVDS_BL_MOD_LEVEL_SHIFT); -#endif - lvds_gen_cntl |= (R128_LVDS_ON | R128_LVDS_EN); - lvds_gen_cntl &= ~R128_LVDS_DISPLAY_DIS; - } else { -#if 0 - lvds_gen_cntl &= ~R128_LVDS_BL_MOD_LEVEL_MASK; - lvds_gen_cntl |= (0xFF /* backlight_conv[0] */ << - R128_LVDS_BL_MOD_LEVEL_SHIFT); -#endif - lvds_gen_cntl |= R128_LVDS_DISPLAY_DIS; - OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl); - usleep(10); - lvds_gen_cntl &= ~(R128_LVDS_ON | R128_LVDS_EN | R128_LVDS_BLON - | R128_LVDS_DIGON); - } - - OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl); - - return 0; -} diff --git a/src/r128_output.c b/src/r128_output.c new file mode 100644 index 0000000..0287098 --- /dev/null +++ b/src/r128_output.c @@ -0,0 +1,461 @@ +/* + * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and + * VA Linux Systems Inc., Fremont, California. + * + * All Rights Reserved. + * + * 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 on 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 (including the + * next paragraph) 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 + * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR + * THEIR SUPPLIERS 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "xf86.h" +#include "xf86Modes.h" + +#include "r128.h" +#include "r128_probe.h" +#include "r128_reg.h" + +static void R128ConnectorFindMonitor(ScrnInfoPtr pScrn, xf86OutputPtr output); + +static void r128_dpms(xf86OutputPtr output, int mode) +{ + switch(mode) { + case DPMSModeOn: + R128DPMSSetOn(output); + break; + case DPMSModeStandby: + case DPMSModeSuspend: + case DPMSModeOff: + R128DPMSSetOff(output); + break; + } +} + +static void r128_save(xf86OutputPtr output) +{ +} + +static void r128_restore(xf86OutputPtr output) +{ +} + +static int r128_mode_valid(xf86OutputPtr output, DisplayModePtr mode) +{ + return MODE_OK; +} + +static Bool r128_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode) +{ + return TRUE; +} + +static void r128_mode_prepare(xf86OutputPtr output) +{ + r128_dpms(output, DPMSModeOff); +} + +static void r128_mode_set(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode) +{ +} + +static void r128_mode_commit(xf86OutputPtr output) +{ + r128_dpms(output, DPMSModeOn); +} + +static xf86OutputStatus r128_detect(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + R128OutputPrivatePtr r128_output = output->driver_private; + + r128_output->MonType = MT_UNKNOWN; + R128ConnectorFindMonitor(pScrn, output); + + if (r128_output->MonType == MT_UNKNOWN) { + output->subpixel_order = SubPixelUnknown; + return XF86OutputStatusUnknown; + } else if (r128_output->MonType == MT_NONE) { + output->subpixel_order = SubPixelUnknown; + return XF86OutputStatusDisconnected; + } else { + switch(r128_output->MonType) { + case MT_LCD: + case MT_DFP: + output->subpixel_order = SubPixelHorizontalRGB; + break; + default: + output->subpixel_order = SubPixelNone; + break; + } + + return XF86OutputStatusConnected; + } +} + +static DisplayModePtr r128_get_modes(xf86OutputPtr output) +{ + DisplayModePtr modes; + modes = R128ProbeOutputModes(output); + return modes; +} + +static void r128_destroy(xf86OutputPtr output) +{ + if (output->driver_private) + free(output->driver_private); +} + +static const xf86OutputFuncsRec r128_output_funcs = { + .dpms = r128_dpms, + .save = r128_save, + .restore = r128_restore, + .mode_valid = r128_mode_valid, + .mode_fixup = r128_mode_fixup, + .prepare = r128_mode_prepare, + .mode_set = r128_mode_set, + .commit = r128_mode_commit, + .detect = r128_detect, + .get_modes = r128_get_modes, + .destroy = r128_destroy, +}; + +void R128DPMSSetOn(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + R128OutputPrivatePtr r128_output = output->driver_private; + R128MonitorType MonType = r128_output->MonType; + + switch(MonType) { + case MT_LCD: + OUTREGP(R128_LVDS_GEN_CNTL, R128_LVDS_BLON, ~R128_LVDS_BLON); + usleep(info->PanelPwrDly * 1000); + OUTREGP(R128_LVDS_GEN_CNTL, R128_LVDS_ON, ~R128_LVDS_ON); + break; + case MT_DFP: + OUTREGP(R128_FP_GEN_CNTL, (R128_FP_FPON | R128_FP_TDMS_EN), ~(R128_FP_FPON | R128_FP_TDMS_EN)); + break; + default: + break; + } +} + +void R128DPMSSetOff(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + R128OutputPrivatePtr r128_output = output->driver_private; + R128MonitorType MonType = r128_output->MonType; + + switch(MonType) { + case MT_LCD: + OUTREGP(R128_LVDS_GEN_CNTL, 0, ~(R128_LVDS_BLON | R128_LVDS_ON)); + break; + case MT_DFP: + OUTREGP(R128_FP_GEN_CNTL, 0, ~(R128_FP_FPON | R128_FP_TDMS_EN)); + break; + default: + break; + } +} + +static R128MonitorType R128DisplayDDCConnected(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + R128OutputPrivatePtr r128_output = output->driver_private; + + R128MonitorType MonType = MT_NONE; + xf86MonPtr *MonInfo = &output->MonInfo; + + if (info->HasCRTC2 && r128_output->num == 0) + return MT_LCD; + + if (r128_output->pI2CBus) { + /* XXX: Radeon does something more complicated to appease old monitors + * but it might be dangerous to put that here because r128 and radeon + * DDC registers are slightly different. */ + + OUTREG(info->DDCReg, (INREG(info->DDCReg) + | R128_GPIO_MONID_MASK_0 | R128_GPIO_MONID_MASK_3)); + + OUTREG(info->DDCReg, INREG(info->DDCReg) + & ~(CARD32)(R128_GPIO_MONID_A_0 | R128_GPIO_MONID_A_3)); + + *MonInfo = xf86DoEDID_DDC2(XF86_SCRN_ARG(pScrn), r128_output->pI2CBus); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DDC2/I2C is not properly initialized\n"); + return MT_NONE; + } + + if (*MonInfo) { + if ((*MonInfo)->rawData[0x14] & 0x80) { + if (INREG(R128_FP_GEN_CNTL) & R128_FP_TDMS_EN) + MonType = MT_DFP; + else + MonType = MT_LCD; + } else { + MonType = MT_CRT; + } + } else if (xf86I2CProbeAddress(r128_output->pI2CBus, 0x0060)) { + /* XXX: Even in cases where the I2C functions are too buggy to detect a + * valid EDID (maybe they are for Apple Sense?) they still might be able + * to detect if a monitor is present at all. */ + MonType = MT_CRT; + } + + return MonType; +} + +static void R128ConnectorFindMonitor(ScrnInfoPtr pScrn, xf86OutputPtr output) +{ + R128OutputPrivatePtr r128_output = output->driver_private; + + /* XXX: We should figure out how the DAC and BIOS scratch registers work + * to handle the non-DDC case. */ + if (r128_output->MonType == MT_UNKNOWN) + r128_output->MonType = R128DisplayDDCConnected(output); +} + +DisplayModePtr R128ProbeOutputModes(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + R128OutputPrivatePtr r128_output = output->driver_private; + DisplayModePtr modes = NULL; + DisplayModePtr mode; + xf86MonPtr edid_mon; + + if (r128_output->type == OUTPUT_DVI) { + edid_mon = xf86OutputGetEDID(output, r128_output->pI2CBus); + xf86OutputSetEDID(output, edid_mon); + + modes = xf86OutputGetEDIDModes(output); + } + + /* Letting this function return NULL would be a bad idea. With old cards + * like r128, users often specify a small resolution in order to get DRI. + * If the X server has to guess modes, the list it comes up with includes + * high resolutions. + */ + if (!modes) + modes = xf86GetDefaultModes(); + + for (mode = modes; mode != NULL; mode = mode->next) { + xf86SetModeCrtc(mode, INTERLACE_HALVE_V); + if (mode->status == MODE_OK) + mode->status = R128ValidMode(XF86_SCRN_ARG(pScrn), mode, TRUE, MODECHECK_FINAL); + } + + xf86ValidateModesUserConfig(pScrn, modes); + xf86PruneInvalidModes(pScrn, &modes, FALSE); + + return modes; +} + +static xf86OutputPtr R128OutputCreate(ScrnInfoPtr pScrn, const char *name, int i) +{ + char buf[32]; + sprintf(buf, name, i); + return xf86OutputCreate(pScrn, &r128_output_funcs, buf); +} + +static void R128I2CGetBits(I2CBusPtr b, int *Clock, int *data) +{ + ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; + R128InfoPtr info = R128PTR(pScrn); + unsigned long val; + unsigned char *R128MMIO = info->MMIO; + + /* Get the result. */ + val = INREG(info->DDCReg); + *Clock = (val & R128_GPIO_MONID_Y_3) != 0; + *data = (val & R128_GPIO_MONID_Y_0) != 0; +} + +static void R128I2CPutBits(I2CBusPtr b, int Clock, int data) +{ + ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; + R128InfoPtr info = R128PTR(pScrn); + unsigned long val; + unsigned char *R128MMIO = info->MMIO; + + val = INREG(info->DDCReg) + & ~(CARD32)(R128_GPIO_MONID_EN_0 | R128_GPIO_MONID_EN_3); + val |= (Clock ? 0:R128_GPIO_MONID_EN_3); + val |= (data ? 0:R128_GPIO_MONID_EN_0); + OUTREG(info->DDCReg, val); +} + +static Bool R128I2CInit(xf86OutputPtr output, I2CBusPtr *bus_ptr, char *name) +{ + ScrnInfoPtr pScrn = output->scrn; + R128InfoPtr info = R128PTR(pScrn); + I2CBusPtr pI2CBus; + + info->DDCReg = R128_GPIO_MONID; + if ( !xf86LoadSubModule(pScrn, "i2c") ) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to load i2c module\n"); + return FALSE; + } + + pI2CBus = xf86CreateI2CBusRec(); + if(!pI2CBus) return FALSE; + + pI2CBus->BusName = name; + pI2CBus->scrnIndex = pScrn->scrnIndex; + pI2CBus->I2CPutBits = R128I2CPutBits; + pI2CBus->I2CGetBits = R128I2CGetBits; + pI2CBus->AcknTimeout = 5; + + if (!xf86I2CBusInit(pI2CBus)) { + return FALSE; + } + + *bus_ptr = pI2CBus; + return TRUE; +} + +void R128SetOutputType(ScrnInfoPtr pScrn, R128OutputPrivatePtr r128_output) +{ + R128OutputType output = OUTPUT_NONE; + + switch (r128_output->ConnectorType) { + case CONNECTOR_VGA: + output = OUTPUT_VGA; + break; + case CONNECTOR_LVDS: + output = OUTPUT_LVDS; + break; + case CONNECTOR_DVI_D: + case CONNECTOR_DVI_I: + case CONNECTOR_DVI_A: + output = OUTPUT_DVI; + break; + default: + output = OUTPUT_NONE; + } + + r128_output->type = output; +} + +void R128SetupGenericConnectors(ScrnInfoPtr pScrn) +{ + R128InfoPtr info = R128PTR(pScrn); + + if (!info->HasCRTC2 && !info->isDFP) { + info->BiosConnector[0].ConnectorType = CONNECTOR_VGA; + info->BiosConnector[0].valid = TRUE; + return; + } else if (!info->HasCRTC2) { + info->BiosConnector[0].ConnectorType = CONNECTOR_DVI_D; + info->BiosConnector[0].valid = TRUE; + return; + } + + info->BiosConnector[0].ConnectorType = CONNECTOR_LVDS; + info->BiosConnector[0].valid = TRUE; + + info->BiosConnector[1].ConnectorType = CONNECTOR_VGA; + info->BiosConnector[1].valid = TRUE; +} + +Bool R128SetupConnectors(ScrnInfoPtr pScrn) +{ + R128InfoPtr info = R128PTR(pScrn); + xf86OutputPtr output; + int num_vga = 0; + int num_dvi = 0; + int i; + + for (i = 0; i < R128_MAX_BIOS_CONNECTOR; i++) { + info->BiosConnector[i].valid = FALSE; + info->BiosConnector[i].ConnectorType = CONNECTOR_NONE; + } + + /* XXX: Can we make R128GetConnectorInfoFromBIOS()? */ + R128SetupGenericConnectors(pScrn); + + for (i = 0; i < R128_MAX_BIOS_CONNECTOR; i++) { + if (info->BiosConnector[i].valid) { + if ((info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_D) || + (info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_I) || + (info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_A)) { + num_dvi++; + } else if (info->BiosConnector[i].ConnectorType == CONNECTOR_VGA) { + num_vga++; + } + } + } + + for (i = 0; i < R128_MAX_BIOS_CONNECTOR; i++) { + if (info->BiosConnector[i].valid) { + R128OutputPrivatePtr r128_output; + R128ConnectorType conntype = info->BiosConnector[i].ConnectorType; + + if (conntype == CONNECTOR_NONE) + continue; + + r128_output = xnfcalloc(sizeof(R128OutputPrivateRec), 1); + if (!r128_output) return FALSE; + + r128_output->MonType = MT_UNKNOWN; + r128_output->ConnectorType = conntype; + r128_output->num = i; + + if ((conntype == CONNECTOR_DVI_D) || + (conntype == CONNECTOR_DVI_I) || + (conntype == CONNECTOR_DVI_A)) { + output = R128OutputCreate(pScrn, "DVI-%d", --num_dvi); + } else if (conntype == CONNECTOR_VGA) { + output = R128OutputCreate(pScrn, "VGA-%d", --num_vga); + } else { + output = R128OutputCreate(pScrn, "LVDS", 0); + } + + if (!output) return FALSE; + output->interlaceAllowed = TRUE; + output->doubleScanAllowed = TRUE; + output->driver_private = r128_output; + + if (conntype == CONNECTOR_LVDS) + output->possible_crtcs = 1; + else + output->possible_crtcs = 2; + + output->possible_clones = 0; + R128SetOutputType(pScrn, r128_output); + R128I2CInit(output, &r128_output->pI2CBus, output->name); + } + } + + return TRUE; +} diff --git a/src/r128_probe.c b/src/r128_probe.c index 12e0c1c..e623bc9 100644 --- a/src/r128_probe.c +++ b/src/r128_probe.c @@ -48,7 +48,6 @@ #include "xf86Resources.h" #endif -#include "compat-api.h" #include "r128_probe.h" #ifndef XSERVER_LIBPCIACCESS diff --git a/src/r128_probe.h b/src/r128_probe.h index 7b55e71..96d72e9 100644 --- a/src/r128_probe.h +++ b/src/r128_probe.h @@ -37,6 +37,15 @@ #define _R128_PROBE_H_ 1 #include "xf86str.h" +#include "xf86DDC.h" +#include "randrstr.h" +#include "xf86Crtc.h" + +#include "compat-api.h" + +#ifdef USE_EXA +#include "exa.h" +#endif /* Chip definitions */ #define PCI_VENDOR_ATI 0x1002 @@ -90,6 +99,64 @@ extern DriverRec R128; +typedef enum +{ + MT_UNKNOWN = -1, + MT_NONE = 0, + MT_CRT = 1, + MT_LCD = 2, + MT_DFP = 3, + MT_CTV = 4, + MT_STV = 5 +} R128MonitorType; + +typedef enum +{ + CONNECTOR_NONE, + CONNECTOR_VGA, + CONNECTOR_DVI_I, + CONNECTOR_DVI_D, + CONNECTOR_DVI_A, + CONNECTOR_LVDS +} R128ConnectorType; + +typedef enum +{ + OUTPUT_NONE, + OUTPUT_VGA, + OUTPUT_DVI, + OUTPUT_LVDS +} R128OutputType; + +typedef struct _R128CrtcPrivateRec { +#ifdef HAVE_XAA_H + FBLinearPtr rotate_mem_xaa; +#endif +#ifdef USE_EXA + ExaOffscreenArea *rotate_mem_exa; +#endif + int crtc_id; + CARD32 cursor_offset; + /* Lookup table values to be set when the CRTC is enabled */ + CARD8 lut_r[256], lut_g[256], lut_b[256]; +} R128CrtcPrivateRec, *R128CrtcPrivatePtr; + +typedef struct { + R128ConnectorType ConnectorType; + Bool valid; +} R128BIOSConnector; + +typedef struct _R128OutputPrivateRec { + int num; + R128OutputType type; + R128ConnectorType ConnectorType; + R128MonitorType MonType; + I2CBusPtr pI2CBus; +} R128OutputPrivateRec, *R128OutputPrivatePtr; + +#define R128_MAX_CRTC 2 +#define R128_MAX_BIOS_CONNECTOR 2 + typedef struct { Bool IsDRIEnabled; @@ -101,6 +168,9 @@ typedef struct Bool IsSecondaryRestored; Bool RestorePrimary; + xf86CrtcPtr pCrtc[R128_MAX_CRTC]; + R128CrtcPrivatePtr Controller[R128_MAX_CRTC]; + ScrnInfoPtr pSecondaryScrn; ScrnInfoPtr pPrimaryScrn; } R128EntRec, *R128EntPtr; diff --git a/src/r128_video.c b/src/r128_video.c index dccaa42..6439a24 100644 --- a/src/r128_video.c +++ b/src/r128_video.c @@ -226,7 +226,7 @@ R128SetupImageVideo(ScreenPtr pScreen) return NULL; adapt->type = XvWindowMask | XvInputMask | XvImageMask; - adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + adapt->flags = VIDEO_OVERLAID_IMAGES /*| VIDEO_CLIP_TO_VIEWPORT*/; adapt->name = "ATI Rage128 Video Overlay"; adapt->nEncodings = 1; adapt->pEncodings = &DummyEncoding; @@ -849,6 +849,13 @@ R128PutImage( int top, left, npixels, nlines; BoxRec dstBox; CARD32 tmp; + + /* Currently, the video is only visible on the first monitor. + * In the future we could try to make this smarter, or just implement + * textured video. */ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcPtr crtc = xf86_config->crtc[0]; + #if X_BYTE_ORDER == X_BIG_ENDIAN unsigned char *R128MMIO = info->MMIO; CARD32 config_cntl = INREG(R128_CONFIG_CNTL); @@ -893,10 +900,10 @@ R128PutImage( clipBoxes, width, height)) return Success; - dstBox.x1 -= pScrn->frameX0; - dstBox.x2 -= pScrn->frameX0; - dstBox.y1 -= pScrn->frameY0; - dstBox.y2 -= pScrn->frameY0; + dstBox.x1 -= crtc->x; + dstBox.x2 -= crtc->x; + dstBox.y1 -= crtc->y; + dstBox.y2 -= crtc->y; switch(id) { case FOURCC_YV12: -- 1.9.2