summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKeith Packard <keithp@guitar.keithp.com>2006-09-20 22:38:55 -0700
committerKeith Packard <keithp@guitar.keithp.com>2006-09-20 22:38:55 -0700
commitf6500e94fec0d6db8c1f1350bee1d137bf06a09e (patch)
treea26330810dec0fe897bf09dd28ed0b1f8fa2e291 /src
parentcbaf3cf74bd420533d299c4113761ec536097e33 (diff)
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.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/i830.h22
-rw-r--r--src/i830_cursor.c371
-rw-r--r--src/i830_display.c8
-rw-r--r--src/i830_display.h1
-rw-r--r--src/i830_driver.c25
-rw-r--r--src/i830_modes.c5
-rw-r--r--src/i830_randr.c450
8 files changed, 686 insertions, 198 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 50d0ad1a..03b5fe67 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -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
diff --git a/src/i830.h b/src/i830.h
index 3a939312..fcd03efb 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -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);
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index 2cb069cc..1e7beef2 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -80,12 +80,106 @@ 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
-
- 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;
- }
-
- x -= hotspotx;
- y -= hotspoty;
-
- /* Now, readjust */
- x -= pScrn->frameX0;
- y -= pScrn->frameY0;
-
- /* 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 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
-
- 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);
-
- OUTREG(CURSOR_A_POSITION, temp);
- if (pI830->Clone)
- OUTREG(CURSOR_B_POSITION, temp);
-
- if (pI830->cursorOn) {
- if (hide)
- pI830->CursorInfoRec->HideCursor(pScrn);
- else if (show)
- pI830->CursorInfoRec->ShowCursor(pScrn);
- pI830->cursorOn = TRUE;
- }
-
- /* 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);
- }
- }
+ 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;
+
+ 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;
+
+ 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];
+
+ if (!pI830->planeEnabled[pipe])
+ 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 <= -I810_CURSOR_X || thisy <= -I810_CURSOR_Y)
+ {
+ inrange = FALSE;
+ thisx = 0;
+ thisy = 0;
+ }
+
+ 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);
+
+ if (pipe == 0)
+ OUTREG(CURSOR_A_POSITION, temp);
+ if (pipe == 1)
+ OUTREG(CURSOR_B_POSITION, temp);
+
+ 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);
+ }
+ }
}
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
diff --git a/src/i830_display.c b/src/i830_display.c
index 6eb2a330..52d488a4 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -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) {
diff --git a/src/i830_display.h b/src/i830_display.h
index 2e61afce..e5bca1c8 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -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);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 8464b39f..dc136a3a 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -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,
diff --git a/src/i830_modes.c b/src/i830_modes.c
index 6bff1d0a..3b70d5d4 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -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;
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 4c7c087e..4132eb2e 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -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;
@@ -317,6 +333,40 @@ I830GetRotation(ScreenPtr pScreen)
}
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)
{
rrScrPrivPtr rp;
@@ -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