From 9ec6cc8bb31f7f4854011c767c945ec5fcbdbe48 Mon Sep 17 00:00:00 2001 From: Connor Behan Date: Fri, 28 Feb 2014 13:46:13 -0800 Subject: [PATCH] Rework modesetting API Content-Type: text/plain; charset="utf-8" --- configure.ac | 2 +- src/r128.h | 13 +- src/r128_crtc.c | 222 ++++++++++++++ src/r128_cursor.c | 169 ++++++----- src/r128_driver.c | 842 ++++++++++-------------------------------------------- src/r128_output.c | 238 +++++++++++++++ src/r128_probe.h | 12 + 7 files changed, 742 insertions(+), 756 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/r128.h b/src/r128.h index ee0b1d4..a57b516 100644 --- a/src/r128.h +++ b/src/r128.h @@ -262,12 +262,13 @@ typedef struct { typedef enum { - MT_NONE, - MT_CRT, - MT_LCD, - MT_DFP, - MT_CTV, - MT_STV + MT_UNKNOWN = -1, + MT_NONE = 0, + MT_CRT = 1, + MT_LCD = 2, + MT_DFP = 3, + MT_CTV = 4, + MT_STV = 5 } R128MonitorType; #ifdef USE_EXA diff --git a/src/r128_crtc.c b/src/r128_crtc.c new file mode 100644 index 0000000..839a9c5 --- /dev/null +++ b/src/r128_crtc.c @@ -0,0 +1,222 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "xf86.h" +#include "xf86Modes.h" + +#include "r128.h" +#include "r128_reg.h" + +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 void r128_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr adjusted_mode) +{ + return TRUE; +} + +static void r128_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue, int size) +{ + ScrnInfoPtr pScrn = crtc->scrn; + 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; + ScreenInfoPtr 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 Bool r128_crtc_unlock(xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + ScreenInfoPtr 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 +} + +static const xf86CrtcFuncsRec r128_crtc_funcs = { + .dpms = r128_crtc_dpms, + .save = NULL, + .restore = NULL, + .mode_fixup = r128_crtc_mode_fixup, + .mode_set = r128_crtc_mode_set, + .gamma_set = r128_crtc_gamma_set, + .lock = r128_crtc_lock, + .unlock = r128_crtc_unlock, + .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..44b6140 100644 --- a/src/r128_cursor.c +++ b/src/r128_cursor.c @@ -73,6 +73,34 @@ ((char *)a)[3] = ((char *)b)[2] #endif +static void R128CrtcCursor(xf86CrtcPtr crtc, Bool force) +{ + ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + R128CrtcPrivatePtr r128_crtc = crtc->driver_private; + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + + int crtc_id = r128_crtc->crtc_id; + Bool show; + + if (!crtc->enabled && !crtc->cursorShown) return; + show = crtc->cursorInRange && crtc->enabled; + + if (show && (force || !crtc->cursorShown)) { + if (crtc_id == 0) + OUTREGP(R128_CRTC_GEN_CNTL, R128_CRTC_CUR_EN, ~R128_CRTC_CUR_EN); + else if (crtc_id == 1) + OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_CUR_EN, ~R128_CRTC2_CUR_EN); + crtc->cursorShown = TRUE; + } else if (!show && (force || crtc->cursorShown)) { + if (crtc_id == 0) + OUTREGP(R128_CRTC_GEN_CNTL, 0, ~R128_CRTC_CUR_EN); + else if (crtc_id == 1) + OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~R128_CRTC2_CUR_EN); + crtc->cursorShown = FALSE; + } +} /* Set cursor foreground and background colors. */ static void R128SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) @@ -94,40 +122,65 @@ static void R128SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) /* Set cursor position to (x,y) with offset into cursor bitmap at (xorigin,yorigin). */ -static void R128SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) +static void R128RandrSetCursorPosition(ScrnInfoPtr pScrn, 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); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + xf86CursorInfoPtr cursor = info->cursor; + + Bool inrange; + int temp, c; + int oldx = x, oldy = y; + int hotspotx = 0, hotspoty = 0; + int xorigin, yorigin; + + oldx += pScrn->frameX0; /* Undo what xf86HWCurs did */ + oldy += pScrn->frameY0; + + for (c = 0; c < xf86_config->num_crtc; c++) { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + DisplayModePtr mode = &crtc->mode; + int thisx = x - crtc->x; + int thisy = y - crtc->y; + + if (!crtc->enabled && !crtc->cursorShown) continue; + + /* There is a screen display problem when the cursor position is set + * wholely outside of the viewport. We trap that here, turning the + * cursor off when that happens, and back on when it comes back into + * the viewport. + */ + inrange = TRUE; + if (thisx >= mode->HDisplay || thisy >= mode->VDisplay || + thisx <= -cursor->MaxWidth || thisy <= -cursor->MaxHeight) { + inrange = FALSE; + thisx = 0; + thisy = 0; + } + + temp = 0; + xorigin = 0; + yorigin = 0; + if (thisx < 0) xorigin = -thisx + 1; + if (thisy < 0) yorigin = -thisy + 1; + if (xorigin >= cursor->MaxWidth) xorigin = cursor->MaxWidth - 1; + if (yorigin >= cursor->MaxHeight) yorigin = cursor->MaxHeight - 1; + + temp |= (xorigin ? 0 : thisx) << 16; + temp |= (yorigin ? 0 : thisy); + + if(c == 0) { + OUTREG(R128_CUR_HORZ_VERT_OFF, (R128_CUR_LOCK | (xorigin << 16) | yorigin)); + OUTREG(R128_CUR_HORZ_VERT_POSN, (R128_CUR_LOCK | temp)); + OUTREG(R128_CUR_OFFSET, info->cursor_start + yorigin * 16); + } else if (c == 1) { + OUTREG(R128_CUR2_HORZ_VERT_OFF, (R128_CUR2_LOCK | (xorigin << 16) | yorigin)); + OUTREG(R128_CUR2_HORZ_VERT_POSN, (R128_CUR2_LOCK | temp)); + OUTREG(R128_CUR2_OFFSET, info->cursor_start + pScrn->fbOffset + yorigin * 16); + } + crtc->cursorInRange = inrage; + R128CrtcCursor(crtc, FALSE); } } @@ -140,17 +193,16 @@ static void R128LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image) CARD32 *s = (pointer)image; CARD32 *d = (pointer)((CARD8*)info->FB + info->cursor_start); int y; - CARD32 save; + CARD32 save1, save2; - if(!info->IsSecondary) - { - save = INREG(R128_CRTC_GEN_CNTL); - OUTREG(R128_CRTC_GEN_CNTL, save & (CARD32)~R128_CRTC_CUR_EN); + if (!info->IsSecondary) { + save1 = INREG(R128_CRTC_GEN_CNTL); + OUTREG(R128_CRTC_GEN_CNTL, save1 & (CARD32)~R128_CRTC_CUR_EN); } - else - { - save = INREG(R128_CRTC2_GEN_CNTL); - OUTREG(R128_CRTC2_GEN_CNTL, save & (CARD32)~R128_CRTC2_CUR_EN); + + if (info->IsSecondary || info->HasCrtc2) { + save2 = INREG(R128_CRTC2_GEN_CNTL); + OUTREG(R128_CRTC2_GEN_CNTL, save2 & (CARD32)~R128_CRTC2_CUR_EN); } #if X_BYTE_ORDER == X_BIG_ENDIAN @@ -206,41 +258,30 @@ static void R128LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image) *d++ = 0x00000000; } - if(!info->IsSecondary) - OUTREG(R128_CRTC_GEN_CNTL, save); - else - OUTREG(R128_CRTC2_GEN_CNTL, save); + OUTREG(R128_CRTC_GEN_CNTL, save1); + OUTREG(R128_CRTC2_GEN_CNTL, save2); } /* Hide hardware cursor. */ static void R128HideCursor(ScrnInfoPtr pScrn) { - R128InfoPtr info = R128PTR(pScrn); - unsigned char *R128MMIO = info->MMIO; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int c; - if(info->IsSecondary) - OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~R128_CRTC2_CUR_EN); - else - OUTREGP(R128_CRTC_GEN_CNTL, 0, ~R128_CRTC_CUR_EN); + for (c = 0; c < xf86_config->num_crtc; c++) + R128CrtcCursor(xf86_config->crtc[c], TRUE); } /* Show hardware cursor. */ static void R128ShowCursor(ScrnInfoPtr pScrn) { - R128InfoPtr info = R128PTR(pScrn); - unsigned char *R128MMIO = info->MMIO; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int c; - 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); - } + for (c = 0; c < xf86_config->num_crtc; c++) + R128CrtcCursor(xf86_config->crtc[c], FALSE); } /* Determine if hardware cursor is in use. */ @@ -286,7 +327,7 @@ Bool R128CursorInit(ScreenPtr pScreen) | HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK); cursor->SetCursorColors = R128SetCursorColors; - cursor->SetCursorPosition = R128SetCursorPosition; + cursor->SetCursorPosition = R128RandrSetCursorPosition; cursor->LoadCursorImage = R128LoadCursorImage; cursor->HideCursor = R128HideCursor; cursor->ShowCursor = R128ShowCursor; diff --git a/src/r128_driver.c b/src/r128_driver.c index 0a0b82b..61fbff0 100644 --- a/src/r128_driver.c +++ b/src/r128_driver.c @@ -120,10 +120,6 @@ 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, @@ -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) { @@ -1338,411 +1262,6 @@ R128I2cInit(ScrnInfoPtr pScrn) 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 +1404,42 @@ 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; + + 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) + return FALSE; + } + return TRUE; +} + static void R128ProbeDDC(ScrnInfoPtr pScrn, int indx) { @@ -1902,6 +1457,7 @@ R128ProbeDDC(ScrnInfoPtr pScrn, int indx) /* R128PreInit is called once at server startup. */ Bool R128PreInit(ScrnInfoPtr pScrn, int flags) { + xf86CrtcConfigPtr xf86_config; R128InfoPtr info; xf86Int10InfoPtr pInt10 = NULL; @@ -1976,6 +1532,10 @@ Bool R128PreInit(ScrnInfoPtr pScrn, int flags) #endif pScrn->monitor = pScrn->confScreen->monitor; + /* Allocate an xf86CrtcConfig */ + xf86CrtcConfigInit(pScrn); + xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + if (!R128PreInitVisual(pScrn)) goto fail; /* We can't do this until we have a @@ -2016,8 +1576,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 +1611,31 @@ 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, 1600, 1200); /* Don't fail on this one */ R128PreInitDDC(pScrn, pInt10); - if (!R128PreInitGamma(pScrn)) goto fail; + if (!R128PreInitControllers(pScrn, pInt10)) goto fail; + + if (!xf86InitialConfiguration(pScrn, FALSE)) { + 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 +1643,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); @@ -2117,55 +1698,65 @@ static void R128LoadPalette(ScrnInfoPtr pScrn, int numColors, { 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 + RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b); +#else + crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256); +#endif } } @@ -2296,10 +1887,14 @@ Bool R128ScreenInit(SCREEN_INIT_ARGS_DECL) info->PaletteSavedOnVT = FALSE; R128Save(pScrn); + pScrn->vtSema = TRUE; + /* xf86CrtcRotate accesses pScrn->pScreen */ + pScrn->pScreen = pScreen; + if (info->FBDev) { if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) return FALSE; } else { - if (!R128ModeInit(pScrn, pScrn->currentMode)) return FALSE; + if (!xf86SetDesiredModes(pScrn)) return FALSE; } R128SaveScreen(pScreen, SCREEN_SAVER_ON); @@ -2736,28 +2331,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); @@ -2792,6 +2370,20 @@ 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; } @@ -4376,12 +3968,19 @@ Bool R128EnterVT(VT_FUNC_ARGS_DECL) { SCRN_INFO_PTR(arg); R128InfoPtr info = R128PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(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); @@ -4503,130 +4102,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..2d9af4c --- /dev/null +++ b/src/r128_output.c @@ -0,0 +1,238 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "xf86.h" +#include "xf86Modes.h" + +#include "r128.h" +#include "r128_reg.h" + +static void r128_dpms(xf86OutputPtr output, int mode) +{ + switch(mode) { + case DPMSModeOn: + R128DPMSSetOn(output); + break; + case DPMSModeStandby: + case DPMSModeSusped: + 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_set(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode) +{ +} + +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, + .mode_set = r128_mode_set, + .detect = r128_detect, + .get_modes = r128_get_modes, + .destroy = r128_destroy, +}; + +static void R128DPMSSetOn(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + R128CrtcPrivatePtr 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; + } +} + +static void R128DPMSSetOff(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + R128CrtcPrivatePtr 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; + } +} + +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); +} + +static R128MonitorType R128DisplayDDCConnected(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + R128CrtcPrivatePtr r128_output = output->driver_private; + + R128MonitorType MonType = MT_NONE; + xf86MonPtr *MonInfo = &output->MonInfo; + + 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"); + MonType = 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 { + MonType = MT_NONE; + } + + return MonType; +} + +DisplayModePtr R128ProbeOutputModes(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + R128InfoPtr info = R128PTR(pScrn); + R128OutputPrivatePtr r128_output = output->driver_private; + DisplayModePtr mode; + xf86MonPtr edid_mon; + DisplayModePtr modes = NULL; + + if (r128_output->type == OUTPUT_DVI || r128_output->type == OUTPUT_VGA) { + edid_mon = xf86OutputGetEDID(output, r128_output->pI2CBus); + xf86OutputSetEDID(output, edid_mon); + + modes = xf86OutputGetEDIDModes(output); + return modes; + } + + if (r128_output->type == OUTPUT_LVDS) { + /* okay we got DDC info */ + if (output->MonInfo) { + /* Debug info for now, at least */ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID for output %d\n", r128_output->num); + xf86PrintEDID(output->MonInfo); + + modes = xf86DDCGetModes(pScrn->scrnIndex, output->MonInfo); + + for (mode = modes; mode != NULL; mode = mode->next) { + if (mode->Flags & V_INTERLACE) mode->status = MODE_NO_INTERLACE; + if (mode->Flags & V_DBLSCAN) mode->status = MODE_NO_DBLESCAN; + } + xf86PruneInvalidModes(pScrn, &modes, TRUE); + + /* do some physical size stuff */ + } + /* XXX: Maybe R128ValidateFPModes() needs to be kept? */ + } + + if (modes) { + xf86ValidateModesUserConfig(pScrn, modes); + xf86PruneInvalidModes(pScrn, &modes, FALSE); + } + + return modes; +} diff --git a/src/r128_probe.h b/src/r128_probe.h index 7b55e71..e7fe22f 100644 --- a/src/r128_probe.h +++ b/src/r128_probe.h @@ -90,6 +90,15 @@ extern DriverRec R128; +typedef struct _R128CrtcPrivateRec { + int crtc_id; + int binding; + /* Lookup table values to be set when the CRTC is enabled */ + CARD8 lut_r[256], lut_g[256], lut_b[256]; +} R128CrtcPrivateRec, *R128CrtcPrivatePtr; + +#define R128_MAX_CRTC 2 + typedef struct { Bool IsDRIEnabled; @@ -101,6 +110,9 @@ typedef struct Bool IsSecondaryRestored; Bool RestorePrimary; + xf86CrtcPtr pCrtc[R128_MAX_CRTC]; + R128CrtcPrivatePtr Controller[R128_MAX_CRTC]; + ScrnInfoPtr pSecondaryScrn; ScrnInfoPtr pPrimaryScrn; } R128EntRec, *R128EntPtr; -- 1.8.5.3