Update driver for RandR 1.2 X server API.

This is not entirely what I'd like to see, but it's at least functional.

Limitations:
	Can't disable/enable crtcs
	Can't move outputs on/off crtcs

But, it does handle monitor hot-plug, detecting changes in VGA and SDVO
status on-the fly. Which makes for good demo material.
This commit is contained in:
Keith Packard 2006-09-20 22:38:55 -07:00
parent cbaf3cf74b
commit f6500e94fe
9 changed files with 677 additions and 190 deletions

View File

@ -99,8 +99,6 @@ if test "x$GCC" = "xyes"; then
-Wnested-externs -fno-strict-aliasing"
fi
CFLAGS="$CFLAGS $WARN_CFLAGS"
AM_CONDITIONAL(DRI, test x$DRI = xyes)
if test "$DRI" = yes; then
PKG_CHECK_MODULES(DRI, [libdrm >= 2.0 xf86driproto])
@ -110,6 +108,7 @@ fi
AC_SUBST([DRI_CFLAGS])
AC_SUBST([XORG_CFLAGS])
AC_SUBST([WARN_CFLAGS])
AC_SUBST([moduledir])
DRIVER_NAME=i810

View File

@ -24,7 +24,7 @@ SUBDIRS = xvmc bios_reader ch7xxx sil164
# -avoid-version prevents gratuitous .0.0.0 version numbers on the end
# _ladir passes a dummy rpath to libtool so the thing will actually link
# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@ -DI830_XV
AM_CFLAGS = @WARN_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ -DI830_XV
i810_drv_la_LTLIBRARIES = i810_drv.la
i810_drv_la_LDFLAGS = -module -avoid-version

View File

@ -79,6 +79,16 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* Paulo César Pereira de Andrade <pcpa@conectiva.com.br>.
*/
#define PIPE_CRT_ID 0
#define PIPE_TV_ID 1
#define PIPE_DFP_ID 2
#define PIPE_LFP_ID 3
#define PIPE_CRT2_ID 4
#define PIPE_TV2_ID 5
#define PIPE_DFP2_ID 6
#define PIPE_LFP2_ID 7
#define PIPE_NUM_ID 8
#define PIPE_NONE 0<<0
#define PIPE_CRT 1<<0
#define PIPE_TV 1<<1
@ -201,10 +211,12 @@ typedef struct _I830SDVODriver {
CARD32 save_SDVOX;
} I830SDVORec, *I830SDVOPtr;
extern const char *i830_output_type_names[];
struct _I830OutputRec {
int type;
int pipe;
int flags;
/* int pipe;
int flags;*/
xf86MonPtr MonInfo;
I2CBusPtr pI2CBus;
I2CBusPtr pDDCBus;
@ -233,6 +245,10 @@ typedef struct _I830Rec {
Bool gammaEnabled[MAX_DISPLAY_PIPES];
int pipeX[MAX_DISPLAY_PIPES];
int pipeY[MAX_DISPLAY_PIPES];
Bool cursorInRange[MAX_DISPLAY_PIPES];
Bool cursorShown[MAX_DISPLAY_PIPES];
Bool Clone;
int CloneRefresh;
int CloneHDisplay;
@ -518,6 +534,7 @@ extern void I830SetMMIOAccess(I830Ptr pI830);
extern void I830PrintErrorState(ScrnInfoPtr pScrn);
extern void I830Sync(ScrnInfoPtr pScrn);
extern void I830InitHWCursor(ScrnInfoPtr pScrn);
extern void I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe);
extern Bool I830CursorInit(ScreenPtr pScreen);
extern void I830EmitInvarientState(ScrnInfoPtr pScrn);
extern void I830SelectBuffer(ScrnInfoPtr pScrn, int buffer);
@ -610,6 +627,7 @@ DisplayModePtr i830GetGTF(int h_pixels, int v_lines, float freq,
int I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time);
/* i830_randr.c */
Bool I830RandRCreateScreenResources (ScreenPtr pScreen);
Bool I830RandRInit(ScreenPtr pScreen, int rotation);
Bool I830RandRSetConfig(ScreenPtr pScreen, Rotation rotation, int rate,
RRScreenSizePtr pSize);

View File

@ -79,13 +79,107 @@ static void I830LoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs);
static Bool I830UseHWCursorARGB(ScreenPtr pScrn, CursorPtr pCurs);
#endif
void
I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe)
{
I830Ptr pI830 = I830PTR(pScrn);
CARD32 temp;
Bool show;
if (!pI830->planeEnabled[pipe])
return;
show = pI830->cursorOn && pI830->cursorInRange[pipe];
if (show && !pI830->cursorShown[pipe])
{
if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
int cursor_control, cursor_base;
if (pipe == 0)
{
cursor_control = CURSOR_A_CONTROL;
cursor_base = CURSOR_A_BASE;
}
else
{
cursor_control = CURSOR_B_CONTROL;
cursor_base = CURSOR_B_BASE;
}
temp = INREG(cursor_control);
temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
if (pI830->CursorIsARGB) {
temp |= CURSOR_MODE_64_ARGB_AX;
if (pI830->gammaEnabled[pipe])
temp |= MCURSOR_GAMMA_ENABLE;
} else
temp |= CURSOR_MODE_64_4C_AX;
temp |= (pipe << 28); /* Connect to correct pipe */
/* Need to set mode, then address. */
OUTREG(cursor_control, temp);
if (pI830->CursorIsARGB)
OUTREG(cursor_base, pI830->CursorMemARGB->Physical);
else
OUTREG(cursor_base, pI830->CursorMem->Physical);
} else {
temp = INREG(CURSOR_CONTROL);
temp &= ~(CURSOR_FORMAT_MASK);
temp |= CURSOR_ENABLE;
if (pI830->CursorIsARGB) {
temp |= CURSOR_FORMAT_ARGB;
if (pI830->gammaEnabled[pipe])
temp |= CURSOR_GAMMA_ENABLE;
} else
temp |= CURSOR_FORMAT_3C;
OUTREG(CURSOR_CONTROL, temp);
if (pI830->CursorIsARGB)
OUTREG(CURSOR_BASEADDR, pI830->CursorMemARGB->Start);
else
OUTREG(CURSOR_BASEADDR, pI830->CursorMem->Start);
}
pI830->cursorShown[pipe] = TRUE;
}
else if (!show && pI830->cursorShown[pipe])
{
if (IS_MOBILE(pI830) || IS_I9XX(pI830))
{
int cursor_control, cursor_base;
if (pipe == 0)
{
cursor_control = CURSOR_A_CONTROL;
cursor_base = CURSOR_A_BASE;
}
else
{
cursor_control = CURSOR_B_CONTROL;
cursor_base = CURSOR_B_BASE;
}
temp = INREG(cursor_control);
temp &= ~(CURSOR_MODE|MCURSOR_GAMMA_ENABLE);
temp |= CURSOR_MODE_DISABLE;
OUTREG(cursor_control, temp);
/* This is needed to flush the above change. */
if (pI830->CursorIsARGB)
OUTREG(cursor_base, pI830->CursorMemARGB->Physical);
else
OUTREG(cursor_base, pI830->CursorMem->Physical);
} else {
temp = INREG(CURSOR_CONTROL);
temp &= ~(CURSOR_ENABLE|CURSOR_GAMMA_ENABLE);
OUTREG(CURSOR_CONTROL, temp);
}
pI830->cursorShown[pipe] = FALSE;
}
}
void
I830InitHWCursor(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
CARD32 temp;
int i;
DPRINTF(PFX, "I830InitHWCursor\n");
for (i = 0; i < MAX_DISPLAY_PIPES; i++) pI830->cursorShown[i] = FALSE;
/* Initialise the HW cursor registers, leaving the cursor hidden. */
if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
temp = INREG(CURSOR_A_CONTROL);
@ -356,121 +450,109 @@ static void I830LoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs)
static void
I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
{
I830Ptr pI830 = I830PTR(pScrn);
CARD32 temp = 0;
Bool hide = FALSE, show = FALSE;
int oldx = x, oldy = y;
int hotspotx = 0, hotspoty = 0;
#if 0
static Bool outsideViewport = FALSE;
#endif
I830Ptr pI830 = I830PTR(pScrn);
CARD32 temp;
Bool inrange;
int oldx = x, oldy = y;
int hotspotx = 0, hotspoty = 0;
int pipe;
oldx += pScrn->frameX0; /* undo what xf86HWCurs did */
oldy += pScrn->frameY0;
oldx += pScrn->frameX0; /* undo what xf86HWCurs did */
oldy += pScrn->frameY0;
switch (pI830->rotation) {
case RR_Rotate_0:
x = oldx;
y = oldy;
break;
case RR_Rotate_90:
x = oldy;
y = pScrn->pScreen->width - oldx;
hotspoty = I810_CURSOR_X;
break;
case RR_Rotate_180:
x = pScrn->pScreen->width - oldx;
y = pScrn->pScreen->height - oldy;
hotspotx = I810_CURSOR_X;
hotspoty = I810_CURSOR_Y;
break;
case RR_Rotate_270:
x = pScrn->pScreen->height - oldy;
y = oldx;
hotspotx = I810_CURSOR_Y;
break;
}
switch (pI830->rotation) {
case RR_Rotate_0:
x = oldx;
y = oldy;
break;
case RR_Rotate_90:
x = oldy;
y = pScrn->pScreen->width - oldx;
hotspoty = I810_CURSOR_X;
break;
case RR_Rotate_180:
x = pScrn->pScreen->width - oldx;
y = pScrn->pScreen->height - oldy;
hotspotx = I810_CURSOR_X;
hotspoty = I810_CURSOR_Y;
break;
case RR_Rotate_270:
x = pScrn->pScreen->height - oldy;
y = oldx;
hotspotx = I810_CURSOR_Y;
break;
}
x -= hotspotx;
y -= hotspoty;
x -= hotspotx;
y -= hotspoty;
/* Now, readjust */
x -= pScrn->frameX0;
y -= pScrn->frameY0;
for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++)
{
DisplayModePtr mode = &pI830->pipeCurMode[pipe];
int thisx = x - pI830->pipeX[pipe];
int thisy = y - pI830->pipeY[pipe];
/* Clamp the cursor position to the visible screen area. Ignore this if we
* are doing motion (with SilkenMouse) while the currentMode being changed.
*/
if (pScrn->currentMode != NULL) {
if (x >= pScrn->currentMode->HDisplay)
x = pScrn->currentMode->HDisplay - 1;
if (y >= pScrn->currentMode->VDisplay)
y = pScrn->currentMode->VDisplay - 1;
}
if (x <= -I810_CURSOR_X) x = -I810_CURSOR_X + 1;
if (y <= -I810_CURSOR_Y) y = -I810_CURSOR_Y + 1;
if (!pI830->planeEnabled[pipe])
continue;
#if 0
/*
* 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.
*/
if (x >= pScrn->currentMode->HDisplay ||
y >= pScrn->currentMode->VDisplay ||
x <= -I810_CURSOR_X || y <= -I810_CURSOR_Y) {
hide = TRUE;
outsideViewport = TRUE;
} else if (outsideViewport) {
show = TRUE;
outsideViewport = FALSE;
}
#endif
/*
* 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 <= -I810_CURSOR_X || thisy <= -I810_CURSOR_Y)
{
inrange = FALSE;
thisx = 0;
thisy = 0;
}
if (x < 0) {
temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
x = -x;
}
if (y < 0) {
temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
y = -y;
}
temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
temp = 0;
if (thisx < 0) {
temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
thisx = -thisx;
}
if (thisy < 0) {
temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
thisy = -thisy;
}
temp |= ((thisx & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
temp |= ((thisy & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
OUTREG(CURSOR_A_POSITION, temp);
if (pI830->Clone)
OUTREG(CURSOR_B_POSITION, temp);
if (pipe == 0)
OUTREG(CURSOR_A_POSITION, temp);
if (pipe == 1)
OUTREG(CURSOR_B_POSITION, temp);
if (pI830->cursorOn) {
if (hide)
pI830->CursorInfoRec->HideCursor(pScrn);
else if (show)
pI830->CursorInfoRec->ShowCursor(pScrn);
pI830->cursorOn = TRUE;
}
pI830->cursorInRange[pipe] = inrange;
I830SetPipeCursor (pScrn, pipe);
}
/* have to upload the base for the new position */
if (IS_I9XX(pI830)) {
if (pI830->CursorIsARGB)
OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
else
OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical);
if (pI830->Clone) {
if (pI830->CursorIsARGB)
OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical);
else
OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical);
}
}
/* have to upload the base for the new position */
if (IS_I9XX(pI830)) {
if (pI830->CursorIsARGB)
OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
else
OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical);
if (pI830->Clone) {
if (pI830->CursorIsARGB)
OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical);
else
OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical);
}
}
}
static void
I830ShowCursor(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
CARD32 temp;
int pipe;
DPRINTF(PFX, "I830ShowCursor\n");
DPRINTF(PFX,
@ -482,81 +564,22 @@ I830ShowCursor(ScrnInfoPtr pScrn)
" Value of CursorMemARGB->Start is %x ",
pI830->CursorMemARGB->Physical, pI830->CursorMemARGB->Start);
pI830->cursorOn = TRUE;
if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
temp = INREG(CURSOR_A_CONTROL);
temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
if (pI830->CursorIsARGB) {
temp |= CURSOR_MODE_64_ARGB_AX;
if (pI830->gammaEnabled[pI830->pipe])
temp |= MCURSOR_GAMMA_ENABLE;
} else
temp |= CURSOR_MODE_64_4C_AX;
temp |= (pI830->pipe << 28); /* Connect to correct pipe */
/* Need to set mode, then address. */
OUTREG(CURSOR_A_CONTROL, temp);
if (pI830->CursorIsARGB)
OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
else
OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical);
if (pI830->Clone) {
temp &= ~MCURSOR_PIPE_SELECT;
temp |= (!pI830->pipe << 28);
OUTREG(CURSOR_B_CONTROL, temp);
if (pI830->CursorIsARGB)
OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical);
else
OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical);
}
} else {
temp = INREG(CURSOR_CONTROL);
temp &= ~(CURSOR_FORMAT_MASK);
temp |= CURSOR_ENABLE;
if (pI830->CursorIsARGB) {
temp |= CURSOR_FORMAT_ARGB;
if (pI830->gammaEnabled[pI830->pipe])
temp |= CURSOR_GAMMA_ENABLE;
} else
temp |= CURSOR_FORMAT_3C;
OUTREG(CURSOR_CONTROL, temp);
if (pI830->CursorIsARGB)
OUTREG(CURSOR_BASEADDR, pI830->CursorMemARGB->Start);
else
OUTREG(CURSOR_BASEADDR, pI830->CursorMem->Start);
}
pI830->cursorOn = TRUE;
for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++)
I830SetPipeCursor (pScrn, pipe);
}
static void
I830HideCursor(ScrnInfoPtr pScrn)
{
CARD32 temp;
I830Ptr pI830 = I830PTR(pScrn);
int pipe;
DPRINTF(PFX, "I830HideCursor\n");
pI830->cursorOn = FALSE;
if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
temp = INREG(CURSOR_A_CONTROL);
temp &= ~(CURSOR_MODE|MCURSOR_GAMMA_ENABLE);
temp |= CURSOR_MODE_DISABLE;
OUTREG(CURSOR_A_CONTROL, temp);
/* This is needed to flush the above change. */
if (pI830->CursorIsARGB)
OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical);
else
OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical);
if (pI830->Clone) {
OUTREG(CURSOR_B_CONTROL, temp);
if (pI830->CursorIsARGB)
OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical);
else
OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical);
}
} else {
temp = INREG(CURSOR_CONTROL);
temp &= ~(CURSOR_ENABLE|CURSOR_GAMMA_ENABLE);
OUTREG(CURSOR_CONTROL, temp);
}
for (pipe = 0; pipe < MAX_DISPLAY_PIPES; pipe++)
I830SetPipeCursor (pScrn, pipe);
}
static void

View File

@ -245,13 +245,15 @@ i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y)
OUTREG(DSPABASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
else
OUTREG(DSPBBASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
pI830->pipeX[pipe] = x;
pI830->pipeY[pipe] = y;
}
/**
* Sets the given video mode on the given pipe. Assumes that plane A feeds
* pipe A, and plane B feeds pipe B. Should not affect the other planes/pipes.
*/
static Bool
Bool
i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe)
{
I830Ptr pI830 = I830PTR(pScrn);
@ -608,7 +610,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe)
OUTREG(DSPASTRIDE, pScrn->displayWidth * pI830->cpp);
OUTREG(DSPASIZE, dspsize);
OUTREG(DSPAPOS, 0);
i830PipeSetBase(pScrn, pipe, pScrn->frameX0, pScrn->frameY0);
i830PipeSetBase(pScrn, pipe, pI830->pipeX[pipe], pI830->pipeX[pipe]);
OUTREG(PIPEASRC, pipesrc);
/* Then, turn the pipe on first */
@ -656,7 +658,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe)
OUTREG(DSPBSTRIDE, pScrn->displayWidth * pI830->cpp);
OUTREG(DSPBSIZE, dspsize);
OUTREG(DSPBPOS, 0);
i830PipeSetBase(pScrn, pipe, pScrn->frameX0, pScrn->frameY0);
i830PipeSetBase(pScrn, pipe, pI830->pipeX[pipe], pI830->pipeY[pipe]);
OUTREG(PIPEBSRC, pipesrc);
if (outputs & PIPE_LCD_ACTIVE) {

View File

@ -26,6 +26,7 @@
*/
/* i830_display.c */
Bool i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe);
Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
Bool i830DetectCRT(ScrnInfoPtr pScrn, Bool allow_disturb);
void i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on);

View File

@ -273,7 +273,7 @@ static OptionInfoRec I830BIOSOptions[] = {
};
/* *INDENT-ON* */
static const char *output_type_names[] = {
const char *i830_output_type_names[] = {
"Unused",
"Analog",
"DVO",
@ -1133,7 +1133,7 @@ I830DetectMonitors(ScrnInfoPtr pScrn)
pI830->output[i].pDDCBus);
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC %s %d, %08lX\n",
output_type_names[pI830->output[i].type], i,
i830_output_type_names[pI830->output[i].type], i,
pI830->output[i].pDDCBus->DriverPrivate.uval);
xf86PrintEDID(pI830->output[i].MonInfo);
break;
@ -3164,22 +3164,8 @@ I830CreateScreenResources (ScreenPtr pScreen)
if (!(*pScreen->CreateScreenResources)(pScreen))
return FALSE;
if (pI830->rotation != RR_Rotate_0) {
RRScreenSize p;
Rotation requestedRotation = pI830->rotation;
pI830->rotation = RR_Rotate_0;
/* Just setup enough for an initial rotate */
p.width = pScreen->width;
p.height = pScreen->height;
p.mmWidth = pScreen->mmWidth;
p.mmHeight = pScreen->mmHeight;
pI830->starting = TRUE; /* abuse this for dual head & rotation */
I830RandRSetConfig (pScreen, requestedRotation, 0, &p);
pI830->starting = FALSE;
}
if (!I830RandRCreateScreenResources (pScreen))
return FALSE;
return TRUE;
}
@ -3507,6 +3493,9 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
if (!I830BIOSEnterVT(scrnIndex, 0))
return FALSE;
if (pScrn->virtualX > pScrn->displayWidth)
pScrn->displayWidth = pScrn->virtualX;
DPRINTF(PFX, "assert( if(!fbScreenInit(pScreen, ...) )\n");
if (!fbScreenInit(pScreen, pI830->FbBase + pScrn->fbOffset,
pScrn->virtualX, pScrn->virtualY,

View File

@ -954,6 +954,11 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time)
maxY = mode->VDisplay;
}
}
/* let the user specify a bigger virtual size if they like */
if (pScrn->display->virtualX > maxX)
maxX = pScrn->display->virtualX;
if (pScrn->display->virtualY > maxY)
maxY = pScrn->display->virtualY;
pScrn->virtualX = maxX;
pScrn->virtualY = maxY;
pScrn->displayWidth = (maxX + 63) & ~63;

View File

@ -23,6 +23,10 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "xf86.h"
#include "os.h"
#include "mibank.h"
@ -33,9 +37,11 @@
#include "mipointer.h"
#include "windowstr.h"
#include <randrstr.h>
#include <X11/extensions/render.h>
#include "i830.h"
#include "i830_xf86Modes.h"
#include "i830_display.h"
typedef struct _i830RandRInfo {
int virtualX;
@ -46,8 +52,18 @@ typedef struct _i830RandRInfo {
int maxY;
Rotation rotation; /* current mode */
Rotation supported_rotations; /* driver supported */
#ifdef RANDR_12_INTERFACE
RRCrtcPtr crtcs[MAX_DISPLAY_PIPES];
RROutputPtr outputs[MAX_OUTPUTS];
DisplayModePtr modes[MAX_DISPLAY_PIPES];
#endif
} XF86RandRInfoRec, *XF86RandRInfoPtr;
#ifdef RANDR_12_INTERFACE
static Bool I830RandRInit12 (ScreenPtr pScreen);
static Bool I830RandRCreateScreenResources12 (ScreenPtr pScreen);
#endif
static int i830RandRIndex;
static int i830RandRGeneration;
@ -316,6 +332,40 @@ I830GetRotation(ScreenPtr pScreen)
return randrp->rotation;
}
Bool
I830RandRCreateScreenResources (ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
#ifdef PANORAMIX
/* XXX disable RandR when using Xinerama */
if (!noPanoramiXExtension)
return TRUE;
#endif
#if RANDR_12_INTERFACE
if (I830RandRCreateScreenResources12 (pScreen))
return TRUE;
#endif
if (pI830->rotation != RR_Rotate_0) {
RRScreenSize p;
Rotation requestedRotation = pI830->rotation;
pI830->rotation = RR_Rotate_0;
/* Just setup enough for an initial rotate */
p.width = pScreen->width;
p.height = pScreen->height;
p.mmWidth = pScreen->mmWidth;
p.mmHeight = pScreen->mmHeight;
pI830->starting = TRUE; /* abuse this for dual head & rotation */
I830RandRSetConfig (pScreen, requestedRotation, 0, &p);
pI830->starting = FALSE;
}
return TRUE;
}
Bool
I830RandRInit (ScreenPtr pScreen, int rotation)
{
@ -359,6 +409,10 @@ I830RandRInit (ScreenPtr pScreen, int rotation)
pScreen->devPrivates[i830RandRIndex].ptr = randrp;
#if RANDR_12_INTERFACE
if (!I830RandRInit12 (pScreen))
return FALSE;
#endif
return TRUE;
}
@ -379,3 +433,399 @@ I830GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y)
*y = randrp->virtualY;
}
}
#if RANDR_12_INTERFACE
static Bool
I830RandRScreenSetSize (ScreenPtr pScreen,
CARD16 width,
CARD16 height,
CARD32 mmWidth,
CARD32 mmHeight)
{
XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen);
WindowPtr pRoot = WindowTable[pScreen->myNum];
Bool ret = TRUE;
if (randrp->virtualX == -1 || randrp->virtualY == -1)
{
randrp->virtualX = pScrn->virtualX;
randrp->virtualY = pScrn->virtualY;
}
if (pRoot)
(*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE);
pScrn->virtualX = width;
pScrn->virtualY = height;
pScreen->width = pScrn->virtualX;
pScreen->height = pScrn->virtualY;
pScreen->mmWidth = mmWidth;
pScreen->mmHeight = mmHeight;
xf86SetViewport (pScreen, pScreen->width, pScreen->height);
xf86SetViewport (pScreen, 0, 0);
if (pRoot)
(*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE);
if (WindowTable[pScreen->myNum])
RRScreenSizeNotify (pScreen);
return ret;
}
static Bool
I830RandRCrtcNotify (RRCrtcPtr crtc)
{
ScreenPtr pScreen = crtc->pScreen;
XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
RRModePtr mode = NULL;
int x;
int y;
Rotation rotation;
int numOutputs;
RROutputPtr outputs[MAX_OUTPUTS];
struct _I830OutputRec *output;
RROutputPtr rrout;
int pipe = (int) crtc->devPrivate;
int i, j;
DisplayModePtr pipeMode = &pI830->pipeCurMode[pipe];
int pipe_type;
x = pI830->pipeX[pipe];
y = pI830->pipeY[pipe];
rotation = RR_Rotate_0;
numOutputs = 0;
for (i = 0; i < pI830->num_outputs; i++)
{
output = &pI830->output[i];
/*
* Valid crtcs
*/
switch (output->type) {
case I830_OUTPUT_DVO:
case I830_OUTPUT_SDVO:
pipe_type = PIPE_DFP;
break;
case I830_OUTPUT_ANALOG:
pipe_type = PIPE_CRT;
break;
case I830_OUTPUT_LVDS:
pipe_type = PIPE_LFP;
break;
case I830_OUTPUT_TVOUT:
pipe_type = PIPE_TV;
break;
default:
pipe_type = PIPE_NONE;
break;
}
if (pI830->operatingDevices & (pipe_type << (pipe << 3)))
{
rrout = randrp->outputs[i];
outputs[numOutputs++] = rrout;
for (j = 0; j < rrout->numModes; j++)
{
DisplayModePtr outMode = rrout->modes[j]->devPrivate;
if (I830ModesEqual(pipeMode, outMode))
mode = rrout->modes[j];
}
}
}
return RRCrtcNotify (crtc, mode, x, y, rotation, numOutputs, outputs);
}
static Bool
I830RandRCrtcSet (ScreenPtr pScreen,
RRCrtcPtr crtc,
RRModePtr mode,
int x,
int y,
Rotation rotation,
int numOutputs,
RROutputPtr *outputs)
{
XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
int pipe = (int) (crtc->devPrivate);
DisplayModePtr display_mode = mode->devPrivate;
/* Sync the engine before adjust mode */
if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
(*pI830->AccelInfoRec->Sync)(pScrn);
pI830->AccelInfoRec->NeedToSync = FALSE;
}
if (display_mode != randrp->modes[pipe])
{
if (!i830PipeSetMode (pScrn, display_mode, pipe))
return FALSE;
randrp->modes[pipe] = display_mode;
}
i830PipeSetBase(pScrn, pipe, x, y);
return I830RandRCrtcNotify (crtc);
}
static Bool
I830RandRCrtcSetGamma (ScreenPtr pScreen,
RRCrtcPtr crtc)
{
return FALSE;
}
/*
* Mirror the current mode configuration to RandR
*/
static Bool
I830RandRSetInfo12 (ScreenPtr pScreen)
{
XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
RROutputPtr clones[MAX_OUTPUTS];
RRCrtcPtr crtc;
int nclone;
RRCrtcPtr crtcs[MAX_DISPLAY_PIPES];
int ncrtc;
RRModePtr *modes;
int nmode;
struct _I830OutputRec *output;
int i;
int j;
int clone_types;
int crtc_types;
int connection;
int pipe_type;
int pipe;
int subpixel;
if (randrp->virtualX == -1 || randrp->virtualY == -1)
{
randrp->virtualX = pScrn->virtualX;
randrp->virtualY = pScrn->virtualY;
}
RRScreenSetSizeRange (pScreen, 320, 240,
randrp->virtualX, randrp->virtualY);
for (i = 0; i < pI830->num_outputs; i++)
{
output = &pI830->output[i];
/*
* Valid crtcs
*/
switch (output->type) {
case I830_OUTPUT_DVO:
case I830_OUTPUT_SDVO:
crtc_types = ((1 << 0)|
(1 << 1));
clone_types = ((1 << I830_OUTPUT_ANALOG) |
(1 << I830_OUTPUT_DVO) |
(1 << I830_OUTPUT_SDVO));
pipe_type = PIPE_DFP;
subpixel = SubPixelHorizontalRGB;
break;
case I830_OUTPUT_ANALOG:
crtc_types = (1 << 0);
clone_types = ((1 << I830_OUTPUT_ANALOG) |
(1 << I830_OUTPUT_DVO) |
(1 << I830_OUTPUT_SDVO));
pipe_type = PIPE_CRT;
subpixel = SubPixelNone;
break;
case I830_OUTPUT_LVDS:
crtc_types = (1 << 1);
clone_types = (1 << I830_OUTPUT_LVDS);
pipe_type = PIPE_LFP;
subpixel = SubPixelHorizontalRGB;
break;
case I830_OUTPUT_TVOUT:
crtc_types = ((1 << 0) |
(1 << 1));
clone_types = (1 << I830_OUTPUT_TVOUT);
pipe_type = PIPE_TV;
subpixel = SubPixelNone;
break;
default:
crtc_types = 0;
clone_types = 0;
pipe_type = PIPE_NONE;
subpixel = SubPixelUnknown;
break;
}
ncrtc = 0;
pipe = -1;
crtc = NULL;
for (j = 0; j < MAX_DISPLAY_PIPES; j++)
{
#if 0
/* Can't flip outputs among crtcs yet */
if (crtc_types & (1 << j))
crtcs[ncrtc++] = randrp->crtcs[j];
#endif
if (pI830->operatingDevices & (pipe_type << (j << 3)))
{
pipe = j;
crtc = randrp->crtcs[j];
crtcs[ncrtc++] = crtc;
}
}
if (!RROutputSetCrtcs (randrp->outputs[i], crtcs, ncrtc))
return FALSE;
RROutputSetCrtc (randrp->outputs[i], crtc);
if (pipe >= 0)
{
MonPtr mon = pI830->pipeMon[pipe];
DisplayModePtr mode;
xRRModeInfo modeInfo;
RRModePtr rrmode;
nmode = 0;
for (mode = mon->Modes; mode; mode = mode->next)
nmode++;
if (nmode)
{
modes = xalloc (nmode * sizeof (RRModePtr));
if (!modes)
return FALSE;
nmode = 0;
for (mode = mon->Modes; mode; mode = mode->next)
{
modeInfo.nameLength = strlen (mode->name);
modeInfo.mmWidth = mon->widthmm;
modeInfo.mmHeight = mon->heightmm;
modeInfo.width = mode->HDisplay;
modeInfo.dotClock = mode->Clock * 1000;
modeInfo.hSyncStart = mode->HSyncStart;
modeInfo.hSyncEnd = mode->HSyncEnd;
modeInfo.hTotal = mode->HTotal;
modeInfo.hSkew = mode->HSkew;
modeInfo.height = mode->VDisplay;
modeInfo.vSyncStart = mode->VSyncStart;
modeInfo.vSyncEnd = mode->VSyncEnd;
modeInfo.vTotal = mode->VTotal;
modeInfo.modeFlags = mode->Flags;
rrmode = RRModeGet (pScreen, &modeInfo, mode->name);
rrmode->devPrivate = mode;
if (rrmode)
modes[nmode++] = rrmode;
}
if (!RROutputSetModes (randrp->outputs[i], modes, nmode))
{
xfree (modes);
return FALSE;
}
xfree (modes);
}
}
connection = RR_Disconnected;
if (pipe >= 0)
connection = RR_Connected;
RROutputSetConnection (randrp->outputs[i], connection);
RROutputSetSubpixelOrder (randrp->outputs[i], subpixel);
/*
* Valid clones
*/
nclone = 0;
for (j = 0; j < pI830->num_outputs; j++)
{
if (i != j && ((1 << pI830->output[j].type) & clone_types))
clones[nclone++] = randrp->outputs[j];
}
if (!RROutputSetClones (randrp->outputs[i], clones, nclone))
return FALSE;
}
for (i = 0; i < MAX_DISPLAY_PIPES; i++)
I830RandRCrtcNotify (randrp->crtcs[i]);
return TRUE;
}
/*
* Query the hardware for the current state, then mirror
* that to RandR
*/
static Bool
I830RandRGetInfo12 (ScreenPtr pScreen, Rotation *rotations)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
/* Re-probe the outputs for new monitors or modes */
I830ValidateXF86ModeList(pScrn, FALSE);
return I830RandRSetInfo12 (pScreen);
}
static Bool
I830RandRCreateScreenResources12 (ScreenPtr pScreen)
{
XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
I830Ptr pI830 = I830PTR(pScrn);
struct _I830OutputRec *output;
const char *name;
int i;
DisplayModePtr mode;
/*
* Create RandR resources, then probe them
*/
for (i = 0; i < MAX_DISPLAY_PIPES; i++)
{
randrp->crtcs[i] = RRCrtcCreate (pScreen, (void *) i);
RRCrtcGammaSetSize (randrp->crtcs[i], 256);
}
for (i = 0; i < pI830->num_outputs; i++)
{
output = &pI830->output[i];
name = i830_output_type_names[output->type];
randrp->outputs[i] = RROutputCreate (pScreen,
name, strlen (name),
(void *) i);
}
mode = pScrn->currentMode;
if (mode)
{
I830RandRScreenSetSize (pScreen,
mode->HDisplay,
mode->VDisplay,
pScreen->mmWidth,
pScreen->mmHeight);
}
for (i = 0; i < MAX_DISPLAY_PIPES; i++)
i830PipeSetBase(pScrn, i, 0, 0);
return I830RandRSetInfo12 (pScreen);
}
static void
I830RandRPointerMoved (int scrnIndex, int x, int y)
{
}
static Bool
I830RandRInit12 (ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
rrScrPrivPtr rp = rrGetScrPriv(pScreen);
rp->rrGetInfo = I830RandRGetInfo12;
rp->rrScreenSetSize = I830RandRScreenSetSize;
rp->rrCrtcSet = I830RandRCrtcSet;
rp->rrCrtcSetGamma = I830RandRCrtcSetGamma;
rp->rrSetConfig = NULL;
memset (rp->modes, '\0', sizeof (rp->modes));
pScrn->PointerMoved = I830RandRPointerMoved;
return TRUE;
}
#endif