summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/atombios_crtc.c4
-rw-r--r--src/legacy_crtc.c19
-rw-r--r--src/radeon.h2
-rw-r--r--src/radeon_commonfuncs.c33
-rw-r--r--src/radeon_exa.c27
-rw-r--r--src/radeon_exa_funcs.c9
-rw-r--r--src/radeon_exa_render.c6
-rw-r--r--src/radeon_probe.h2
-rw-r--r--src/radeon_reg.h7
-rw-r--r--src/radeon_textured_videofuncs.c8
-rw-r--r--src/radeon_video.c32
-rw-r--r--src/radeon_video.h5
12 files changed, 150 insertions, 4 deletions
diff --git a/src/atombios_crtc.c b/src/atombios_crtc.c
index 4e2395f8..620bc8dc 100644
--- a/src/atombios_crtc.c
+++ b/src/atombios_crtc.c
@@ -511,6 +511,10 @@ atombios_crtc_mode_set(xf86CrtcPtr crtc,
else
OUTREG(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
0);
+
+ OUTREG(AVIVO_D1MODE_VLINE_START_END + radeon_crtc->crtc_offset,
+ ((0 << AVIVO_D1MODE_VLINE_START_SHIFT) |
+ (mode->VDisplay << AVIVO_D1MODE_VLINE_END_SHIFT)));
}
atombios_crtc_set_pll(crtc, adjusted_mode, pll_flags);
diff --git a/src/legacy_crtc.c b/src/legacy_crtc.c
index 75ab6c8a..2e7063c1 100644
--- a/src/legacy_crtc.c
+++ b/src/legacy_crtc.c
@@ -133,8 +133,10 @@ RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn,
OUTREG(RADEON_CRTC_V_TOTAL_DISP, restore->crtc_v_total_disp);
OUTREG(RADEON_CRTC_V_SYNC_STRT_WID, restore->crtc_v_sync_strt_wid);
+ OUTREG(RADEON_CRTC_GUI_TRIG_VLINE, restore->crtc_gui_trig_vline);
+
if (IS_R300_VARIANT)
- OUTREG(R300_CRTC_TILE_X0_Y0, restore->crtc_tile_x0_y0);
+ OUTREG(R300_CRTC_TILE_X0_Y0, restore->crtc_tile_x0_y0);
OUTREG(RADEON_CRTC_OFFSET_CNTL, restore->crtc_offset_cntl);
OUTREG(RADEON_CRTC_OFFSET, restore->crtc_offset);
@@ -177,11 +179,13 @@ RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn,
OUTREG(RADEON_CRTC2_V_TOTAL_DISP, restore->crtc2_v_total_disp);
OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, restore->crtc2_v_sync_strt_wid);
+ OUTREG(RADEON_CRTC2_GUI_TRIG_VLINE, restore->crtc2_gui_trig_vline);
+
OUTREG(RADEON_FP_H2_SYNC_STRT_WID, restore->fp_h2_sync_strt_wid);
OUTREG(RADEON_FP_V2_SYNC_STRT_WID, restore->fp_v2_sync_strt_wid);
if (IS_R300_VARIANT)
- OUTREG(R300_CRTC2_TILE_X0_Y0, restore->crtc2_tile_x0_y0);
+ OUTREG(R300_CRTC2_TILE_X0_Y0, restore->crtc2_tile_x0_y0);
OUTREG(RADEON_CRTC2_OFFSET_CNTL, restore->crtc2_offset_cntl);
OUTREG(RADEON_CRTC2_OFFSET, restore->crtc2_offset);
@@ -518,6 +522,8 @@ RADEONSaveCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
save->crtc_v_total_disp = INREG(RADEON_CRTC_V_TOTAL_DISP);
save->crtc_v_sync_strt_wid = INREG(RADEON_CRTC_V_SYNC_STRT_WID);
+ save->crtc_gui_trig_vline = INREG(RADEON_CRTC_GUI_TRIG_VLINE);
+
save->crtc_offset = INREG(RADEON_CRTC_OFFSET);
save->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL);
save->crtc_pitch = INREG(RADEON_CRTC_PITCH);
@@ -553,6 +559,9 @@ RADEONSaveCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save)
save->crtc2_h_sync_strt_wid = INREG(RADEON_CRTC2_H_SYNC_STRT_WID);
save->crtc2_v_total_disp = INREG(RADEON_CRTC2_V_TOTAL_DISP);
save->crtc2_v_sync_strt_wid = INREG(RADEON_CRTC2_V_SYNC_STRT_WID);
+
+ save->crtc2_gui_trig_vline = INREG(RADEON_CRTC2_GUI_TRIG_VLINE);
+
save->crtc2_offset = INREG(RADEON_CRTC2_OFFSET);
save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL);
save->crtc2_pitch = INREG(RADEON_CRTC2_PITCH);
@@ -946,6 +955,9 @@ RADEONInitCrtcRegisters(xf86CrtcPtr crtc, RADEONSavePtr save,
(pScrn->bitsPerPixel * 8));
save->crtc_pitch |= save->crtc_pitch << 16;
+ save->crtc_gui_trig_vline = ((0 << RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT) |
+ (mode->CrtcVDisplay << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT));
+
if (info->IsDellServer) {
save->dac2_cntl = info->SavedReg->dac2_cntl;
save->tv_dac_cntl = info->SavedReg->tv_dac_cntl;
@@ -1137,6 +1149,9 @@ RADEONInitCrtc2Registers(xf86CrtcPtr crtc, RADEONSavePtr save,
((pScrn->bitsPerPixel * 8) -1)) / (pScrn->bitsPerPixel * 8);
save->crtc2_pitch |= save->crtc2_pitch << 16;
+ save->crtc2_gui_trig_vline = ((0 << RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT) |
+ (mode->CrtcVDisplay << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT));
+
/* check to see if TV DAC is enabled for another crtc and keep it enabled */
if (save->crtc2_gen_cntl & RADEON_CRTC2_CRT2_ON)
save->crtc2_gen_cntl = RADEON_CRTC2_CRT2_ON;
diff --git a/src/radeon.h b/src/radeon.h
index 86cee4b4..826ffe38 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -941,8 +941,10 @@ extern Bool radeon_card_posted(ScrnInfoPtr pScrn);
/* radeon_commonfuncs.c */
#ifdef XF86DRI
extern void RADEONWaitForIdleCP(ScrnInfoPtr pScrn);
+extern void RADEONWaitForVLineCP(ScrnInfoPtr pScrn, PixmapPtr pPix, int crtc);
#endif
extern void RADEONWaitForIdleMMIO(ScrnInfoPtr pScrn);
+extern void RADEONWaitForVLineMMIO(ScrnInfoPtr pScrn, PixmapPtr pPix, int crtc);
/* radeon_crtc.c */
extern void radeon_crtc_dpms(xf86CrtcPtr crtc, int mode);
diff --git a/src/radeon_commonfuncs.c b/src/radeon_commonfuncs.c
index c7d42bce..556dba3f 100644
--- a/src/radeon_commonfuncs.c
+++ b/src/radeon_commonfuncs.c
@@ -632,6 +632,39 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
}
+/* inserts a wait for vline in the command stream */
+void FUNC_NAME(RADEONWaitForVLine)(ScrnInfoPtr pScrn, PixmapPtr pPix, int crtc)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ uint32_t offset;
+ ACCEL_PREAMBLE();
+
+ if ((crtc < 0) || (crtc > 1))
+ return;
+
+ if (!xf86_config->crtc[crtc]->enabled)
+ return;
+
+#ifdef USE_EXA
+ if (info->useEXA)
+ offset = exaGetPixmapOffset(pPix);
+ else
+#endif
+ offset = pPix->devPrivate.ptr - info->FB;
+
+ /* if drawing to front buffer */
+ if (offset == 0) {
+ BEGIN_ACCEL(1);
+ if (crtc == 0)
+ OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_FE_CRTC_VLINE |
+ RADEON_ENG_DISPLAY_SELECT_CRTC0));
+ else
+ OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_FE_CRTC_VLINE |
+ RADEON_ENG_DISPLAY_SELECT_CRTC1));
+ FINISH_ACCEL();
+ }
+}
/* MMIO:
*
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index 04c097b2..c4bc1bb1 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -192,6 +192,33 @@ Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset)
return RADEONGetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch);
}
+/*
+ * Used for vblank render stalling.
+ * Ideally we'd have one pixmap per crtc.
+ * syncing per-blit is unrealistic so,
+ * we sync to whichever crtc has a larger area.
+ */
+int RADEONBiggerCrtcArea(PixmapPtr pPix)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int c, crtc_num = -1, area = 0;
+
+ for (c = 0; c < xf86_config->num_crtc; c++) {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+ if (!crtc->enabled)
+ continue;
+
+ if ((crtc->mode.HDisplay * crtc->mode.VDisplay) > area) {
+ area = crtc->mode.HDisplay * crtc->mode.VDisplay;
+ crtc_num = c;
+ }
+ }
+
+ return crtc_num;
+}
+
#if X_BYTE_ORDER == X_BIG_ENDIAN
static unsigned long swapper_surfaces[3];
diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c
index 62224d01..76d6c413 100644
--- a/src/radeon_exa_funcs.c
+++ b/src/radeon_exa_funcs.c
@@ -117,6 +117,8 @@ FUNC_NAME(RADEONPrepareSolid)(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset);
FINISH_ACCEL();
+ FUNC_NAME(RADEONWaitForVLine)(pScrn, pPix, RADEONBiggerCrtcArea(pPix));
+
return TRUE;
}
@@ -205,6 +207,8 @@ FUNC_NAME(RADEONPrepareCopy)(PixmapPtr pSrc, PixmapPtr pDst,
FUNC_NAME(RADEONDoPrepareCopy)(pScrn, src_pitch_offset, dst_pitch_offset,
datatype, rop, planemask);
+ FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst));
+
return TRUE;
}
@@ -264,7 +268,7 @@ FUNC_NAME(RADEONUploadToScreen)(PixmapPtr pDst, int x, int y, int w, int h,
unsigned int hpass;
uint32_t buf_pitch, dst_pitch_off;
#endif
-#if X_BYTE_ORDER == X_BIG_ENDIAN
+#if X_BYTE_ORDER == X_BIG_ENDIAN
unsigned char *RADEONMMIO = info->MMIO;
unsigned int swapper = info->ModeReg->surface_cntl &
~(RADEON_NONSURF_AP0_SWP_32BPP | RADEON_NONSURF_AP1_SWP_32BPP |
@@ -284,6 +288,9 @@ FUNC_NAME(RADEONUploadToScreen)(PixmapPtr pDst, int x, int y, int w, int h,
ACCEL_PREAMBLE();
RADEON_SWITCH_TO_2D();
+
+ FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst));
+
while ((buf = RADEONHostDataBlit(pScrn,
cpp, w, dst_pitch_off, &buf_pitch,
x, &y, (unsigned int*)&h, &hpass)) != 0) {
diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
index a74abb63..895958cc 100644
--- a/src/radeon_exa_render.c
+++ b/src/radeon_exa_render.c
@@ -624,6 +624,8 @@ static Bool FUNC_NAME(R100PrepareComposite)(int op,
OUT_ACCEL_REG(RADEON_RB3D_BLENDCNTL, blendcntl);
FINISH_ACCEL();
+ FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst));
+
return TRUE;
}
@@ -930,6 +932,8 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture,
OUT_ACCEL_REG(RADEON_RB3D_BLENDCNTL, blendcntl);
FINISH_ACCEL();
+ FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst));
+
return TRUE;
}
@@ -1877,6 +1881,8 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
OUT_ACCEL_REG(R300_VAP_VTX_SIZE, 4);
FINISH_ACCEL();
+ FUNC_NAME(RADEONWaitForVLine)(pScrn, pDst, RADEONBiggerCrtcArea(pDst));
+
return TRUE;
}
diff --git a/src/radeon_probe.h b/src/radeon_probe.h
index 8c6845f7..313daa6b 100644
--- a/src/radeon_probe.h
+++ b/src/radeon_probe.h
@@ -442,6 +442,7 @@ typedef struct {
uint32_t crtc_h_sync_strt_wid;
uint32_t crtc_v_total_disp;
uint32_t crtc_v_sync_strt_wid;
+ uint32_t crtc_gui_trig_vline;
uint32_t crtc_offset;
uint32_t crtc_offset_cntl;
uint32_t crtc_pitch;
@@ -463,6 +464,7 @@ typedef struct {
uint32_t crtc2_h_sync_strt_wid;
uint32_t crtc2_v_total_disp;
uint32_t crtc2_v_sync_strt_wid;
+ uint32_t crtc2_gui_trig_vline;
uint32_t crtc2_offset;
uint32_t crtc2_offset_cntl;
uint32_t crtc2_pitch;
diff --git a/src/radeon_reg.h b/src/radeon_reg.h
index 672d1b59..bcb83ea4 100644
--- a/src/radeon_reg.h
+++ b/src/radeon_reg.h
@@ -401,6 +401,9 @@
# define RADEON_CRTC_H_CUTOFF_ACTIVE_EN (1<<4)
# define RADEON_CRTC_V_CUTOFF_ACTIVE_EN (1<<5)
#define RADEON_CRTC_GUI_TRIG_VLINE 0x0218
+# define RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT 0
+# define RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT 16
+# define RADEON_CRTC_GUI_TRIG_VLINE_INV (1 << 15)
#define RADEON_CRTC_H_SYNC_STRT_WID 0x0204
# define RADEON_CRTC_H_SYNC_STRT_PIX (0x07 << 0)
# define RADEON_CRTC_H_SYNC_STRT_CHAR (0x3ff << 3)
@@ -3619,6 +3622,10 @@
#define AVIVO_D1MODE_DATA_FORMAT 0x6528
# define AVIVO_D1MODE_INTERLEAVE_EN (1 << 0)
#define AVIVO_D1MODE_DESKTOP_HEIGHT 0x652c
+#define AVIVO_D1MODE_VLINE_START_END 0x6538
+# define AVIVO_D1MODE_VLINE_START_SHIFT 0
+# define AVIVO_D1MODE_VLINE_END_SHIFT 16
+# define AVIVO_D1MODE_VLINE_INV (1 << 31)
#define AVIVO_D1MODE_VIEWPORT_START 0x6580
#define AVIVO_D1MODE_VIEWPORT_SIZE 0x6584
#define AVIVO_D1MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6588
diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c
index 86532b53..edd322b3 100644
--- a/src/radeon_textured_videofuncs.c
+++ b/src/radeon_textured_videofuncs.c
@@ -1475,6 +1475,14 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv
}
}
+ FUNC_NAME(RADEONWaitForVLine)(pScrn, pPixmap,
+ radeon_covering_crtc_num(pScrn,
+ pPriv->drw_x,
+ pPriv->drw_x + pPriv->dst_w,
+ pPriv->drw_y,
+ pPriv->drw_y + pPriv->dst_h,
+ pPriv->desired_crtc));
+
while (nBox--) {
int srcX, srcY, srcw, srch;
int dstX, dstY, dstw, dsth;
diff --git a/src/radeon_video.c b/src/radeon_video.c
index 6249ceac..423ea28b 100644
--- a/src/radeon_video.c
+++ b/src/radeon_video.c
@@ -105,7 +105,6 @@ static Atom xvOvAlpha, xvGrAlpha, xvAlphaMode;
#define GET_PORT_PRIVATE(pScrn) \
(RADEONPortPrivPtr)((RADEONPTR(pScrn))->adaptor->pPortPrivates[0].ptr)
-#ifndef HAVE_XF86CRTCCLIPVIDEOHELPER
static void
radeon_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b)
{
@@ -136,6 +135,37 @@ radeon_box_area(BoxPtr box)
return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1);
}
+int
+radeon_covering_crtc_num(ScrnInfoPtr pScrn,
+ int x1, int x2, int y1, int y2,
+ xf86CrtcPtr desired)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int coverage, best_coverage;
+ int c, best_crtc = 0;
+ BoxRec box, crtc_box, cover_box;
+
+ box.x1 = x1;
+ box.x2 = x2;
+ box.y1 = y1;
+ box.y2 = y2;
+ best_coverage = 0;
+ for (c = 0; c < xf86_config->num_crtc; c++) {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+ radeon_crtc_box(crtc, &crtc_box);
+ radeon_box_intersect(&cover_box, &crtc_box, &box);
+ coverage = radeon_box_area(&cover_box);
+ if (coverage && crtc == desired) {
+ return c;
+ } else if (coverage > best_coverage) {
+ best_crtc = c;
+ best_coverage = coverage;
+ }
+ }
+ return best_crtc;
+}
+
+#ifndef HAVE_XF86CRTCCLIPVIDEOHELPER
static xf86CrtcPtr
radeon_covering_crtc(ScrnInfoPtr pScrn,
BoxPtr box,
diff --git a/src/radeon_video.h b/src/radeon_video.h
index 448377be..7c4151f0 100644
--- a/src/radeon_video.h
+++ b/src/radeon_video.h
@@ -117,6 +117,11 @@ typedef struct {
int drw_x, drw_y;
} RADEONPortPrivRec, *RADEONPortPrivPtr;
+int
+radeon_covering_crtc_num(ScrnInfoPtr pScrn,
+ int x1, int x2, int y1, int y2,
+ xf86CrtcPtr desired);
+
void RADEONInitI2C(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv);
void RADEONResetI2C(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv);