summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--src/radeon.h5
-rw-r--r--src/radeon_driver.c61
-rw-r--r--src/radeon_mergedfb.c262
-rw-r--r--src/radeon_mergedfb.h2
5 files changed, 233 insertions, 109 deletions
diff --git a/ChangeLog b/ChangeLog
index ff2f6e48..cb824ccb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2006-04-01 Alex Deucher <agd5f@yahoo.com>
+
+ * src/radeon.h:
+ * src/radeon_driver.c: (RADEONPreInitModes), (RADEONPreInit),
+ (RADEONResetDPI), (RADEONSwitchMode):
+ * src/radeon_mergedfb.c: (RADEONMergedFBCalcDPI),
+ (RADEONMergedFBSetDpi), (RADEONMergedFBResetDpi):
+ * src/radeon_mergedfb.h:
+ - Fix dpi when switching from clone to dualhead with MergedFB.
+ - Add ConstantDPI option to force a particlar dpi across mode changes
+ Both based on Thomas Winischhofer's sis code.
+
2006-03-27 Benjamin Herrenschmidt <benh@kernel.crashing.org>
* src/radeon_driver.c: (RADEONRestoreMemMapRegisters),
diff --git a/src/radeon.h b/src/radeon.h
index ab82081f..acf253c7 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -708,6 +708,11 @@ typedef struct {
Bool NonRect, HaveNonRect, HaveOffsRegions, MouseRestrictions;
region NonRectDead, OffDead1, OffDead2;
+ int constantDPI; /* -1 = auto, 0 = off, 1 = on */
+ int RADEONDPIVX, RADEONDPIVY;
+ RADEONScrn2Rel MergedDPISRel;
+ int RADEONMergedDPIVX, RADEONMergedDPIVY, RADEONMergedDPIRot;
+
/* special handlings for DELL triple-head server */
Bool IsDellServer;
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index eca048e0..95b16644 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -1,5 +1,5 @@
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c,v 1.117 2004/02/19 22:38:12 tsi Exp $ */
-/* $XdotOrg: driver/xf86-video-ati/src/radeon_driver.c,v 1.108 2006/03/23 01:37:15 benh Exp $ */
+/* $XdotOrg: driver/xf86-video-ati/src/radeon_driver.c,v 1.109 2006-03-27 06:12:57 benh Exp $ */
/*
* Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
* VA Linux Systems Inc., Fremont, California.
@@ -200,7 +200,8 @@ typedef enum {
OPTION_VGA_ACCESS,
OPTION_REVERSE_DDC,
OPTION_LVDS_PROBE_PLL,
- OPTION_ACCELMETHOD
+ OPTION_ACCELMETHOD,
+ OPTION_CONSTANTDPI
} RADEONOpts;
static const OptionInfoRec RADEONOptions[] = {
@@ -264,6 +265,7 @@ static const OptionInfoRec RADEONOptions[] = {
{ OPTION_REVERSE_DDC, "ReverseDDC", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_LVDS_PROBE_PLL, "LVDSProbePLL", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_ACCELMETHOD, "AccelMethod", OPTV_STRING, {0}, FALSE },
+ { OPTION_CONSTANTDPI, "ConstantDPI", OPTV_BOOLEAN, {0}, FALSE },
{ -1, NULL, OPTV_NONE, {0}, FALSE }
};
@@ -4359,10 +4361,13 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
/* Set DPI */
/* xf86SetDpi(pScrn, 0, 0); */
- if(info->MergedFB)
+ if (info->MergedFB) {
RADEONMergedFBSetDpi(pScrn, info->CRT2pScrn, info->CRT2Position);
- else
+ } else {
xf86SetDpi(pScrn, 0, 0);
+ info->RADEONDPIVX = pScrn->virtualX;
+ info->RADEONDPIVY = pScrn->virtualY;
+ }
/* Get ScreenInit function */
if (!xf86LoadSubModule(pScrn, "fb")) return FALSE;
@@ -4822,7 +4827,7 @@ _X_EXPORT Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags)
const char *s;
char* microc_path = NULL;
char* microc_type = NULL;
-
+ MessageType from;
RADEONTRACE(("RADEONPreInit\n"));
if (pScrn->numEntities != 1) return FALSE;
@@ -5062,6 +5067,25 @@ _X_EXPORT Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags)
info->DispPriority = 1;
}
+ info->constantDPI = -1;
+ from = X_DEFAULT;
+ if (xf86GetOptValBool(info->Options, OPTION_CONSTANTDPI, &info->constantDPI)) {
+ from = X_CONFIG;
+ } else {
+ if (monitorResolution > 0) {
+ info->constantDPI = TRUE;
+ from = X_CMDLINE;
+ xf86DrvMsg(pScrn->scrnIndex, from,
+ "\"-dpi %d\" given in command line, assuming \"ConstantDPI\" set\n",
+ monitorResolution);
+ } else {
+ info->constantDPI = FALSE;
+ }
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from,
+ "X server will %skeep DPI constant for all screen sizes\n",
+ info->constantDPI ? "" : "not ");
+
if (xf86ReturnOptValBool(info->Options, OPTION_FBDEV, FALSE)) {
/* check for Linux framebuffer device */
@@ -8656,6 +8680,26 @@ static Bool RADEONSaveScreen(ScreenPtr pScreen, int mode)
return TRUE;
}
+static void
+RADEONResetDPI(ScrnInfoPtr pScrn, Bool force)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+
+ if(force ||
+ (info->RADEONDPIVX != pScrn->virtualX) ||
+ (info->RADEONDPIVY != pScrn->virtualY)
+ ) {
+
+ pScreen->mmWidth = (pScrn->virtualX * 254 + pScrn->xDpi * 5) / (pScrn->xDpi * 10);
+ pScreen->mmHeight = (pScrn->virtualY * 254 + pScrn->yDpi * 5) / (pScrn->yDpi * 10);
+
+ info->RADEONDPIVX = pScrn->virtualX;
+ info->RADEONDPIVY = pScrn->virtualY;
+
+ }
+}
+
_X_EXPORT Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
@@ -8740,8 +8784,11 @@ _X_EXPORT Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
/* Since RandR (indirectly) uses SwitchMode(), we need to
* update our Xinerama info here, too, in case of resizing
*/
- if(info->MergedFB) {
- RADEONUpdateXineramaScreenInfo(pScrn);
+ if (info->MergedFB) {
+ RADEONMergedFBResetDpi(pScrn, FALSE);
+ RADEONUpdateXineramaScreenInfo(pScrn);
+ } else if(info->constantDPI) {
+ RADEONResetDPI(pScrn, FALSE);
}
return ret;
diff --git a/src/radeon_mergedfb.c b/src/radeon_mergedfb.c
index 0510bb67..70846d90 100644
--- a/src/radeon_mergedfb.c
+++ b/src/radeon_mergedfb.c
@@ -1741,119 +1741,125 @@ RADEONAdjustFrameMerged(int scrnIndex, int x, int y, int flags)
RADEONDoAdjustFrame(pScrn1, pScrn2->frameX0, pScrn2->frameY0, TRUE);
}
-void
-RADEONMergedFBSetDpi(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, RADEONScrn2Rel srel)
+static void
+RADEONMergedFBCalcDPI(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, RADEONScrn2Rel srel, Bool quiet)
{
- RADEONInfoPtr info = RADEONPTR(pScrn1);
- MessageType from = X_DEFAULT;
- xf86MonPtr DDC1 = (xf86MonPtr)(pScrn1->monitor->DDC);
- xf86MonPtr DDC2 = (xf86MonPtr)(pScrn2->monitor->DDC);
- int ddcWidthmm = 0, ddcHeightmm = 0;
- const char *dsstr = "MergedFB: Display dimensions: (%d, %d) mm\n";
-
- /* This sets the DPI for MergedFB mode. The problem is that
- * this can never be exact, because the output devices may
- * have different dimensions. This function tries to compromise
- * through a few assumptions, and it just calculates an average DPI
- * value for both monitors.
- */
-
- /* Given DisplaySize should regard BOTH monitors */
- pScrn1->widthmm = pScrn1->monitor->widthmm;
- pScrn1->heightmm = pScrn1->monitor->heightmm;
-
- /* Get DDC display size; if only either CRT1 or CRT2 provided these,
- * assume equal dimensions for both, otherwise add dimensions
- */
- if( (DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) &&
- (DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0)) ) {
- ddcWidthmm = max(DDC1->features.hsize, DDC2->features.hsize) * 10;
- ddcHeightmm = max(DDC1->features.vsize, DDC2->features.vsize) * 10;
- switch(srel) {
- case radeonLeftOf:
- case radeonRightOf:
- ddcWidthmm = (DDC1->features.hsize + DDC2->features.hsize) * 10;
- break;
- case radeonAbove:
- case radeonBelow:
- ddcHeightmm = (DDC1->features.vsize + DDC2->features.vsize) * 10;
- default:
- break;
- }
-
- } else if(DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) {
- ddcWidthmm = DDC1->features.hsize * 10;
- ddcHeightmm = DDC1->features.vsize * 10;
- switch(srel) {
- case radeonLeftOf:
- case radeonRightOf:
- ddcWidthmm *= 2;
- break;
- case radeonAbove:
- case radeonBelow:
- ddcHeightmm *= 2;
- default:
- break;
- }
- } else if(DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0) ) {
- ddcWidthmm = DDC2->features.hsize * 10;
- ddcHeightmm = DDC2->features.vsize * 10;
- switch(srel) {
- case radeonLeftOf:
- case radeonRightOf:
- ddcWidthmm *= 2;
- break;
- case radeonAbove:
- case radeonBelow:
- ddcHeightmm *= 2;
- default:
- break;
- }
- }
+ RADEONInfoPtr info = RADEONPTR(pScrn1);
+ MessageType from = X_DEFAULT;
+ xf86MonPtr DDC1 = (xf86MonPtr)(pScrn1->monitor->DDC);
+ xf86MonPtr DDC2 = (xf86MonPtr)(pScrn2->monitor->DDC);
+ int ddcWidthmm = 0, ddcHeightmm = 0;
+ const char *dsstr = "MergedFB: Display dimensions: %dx%d mm\n";
+
+ /* This sets the DPI for MergedFB mode. The problem is that
+ * this can never be exact, because the output devices may
+ * have different dimensions. This function tries to compromise
+ * through a few assumptions, and it just calculates an average
+ * DPI value for both monitors.
+ */
- if(monitorResolution > 0) {
+ /* Copy user-given DisplaySize (which should regard BOTH monitors!) */
+ pScrn1->widthmm = pScrn1->monitor->widthmm;
+ pScrn1->heightmm = pScrn1->monitor->heightmm;
- /* Set command line given values (overrules given options) */
- pScrn1->xDpi = monitorResolution;
- pScrn1->yDpi = monitorResolution;
- from = X_CMDLINE;
+ if(monitorResolution > 0) {
- } else if(info->MergedFBXDPI) {
+ /* Set command line given values (overrules given options) */
+ pScrn1->xDpi = monitorResolution;
+ pScrn1->yDpi = monitorResolution;
+ from = X_CMDLINE;
- /* Set option-wise given values (overrule DisplaySize) */
- pScrn1->xDpi = info->MergedFBXDPI;
- pScrn1->yDpi = info->MergedFBYDPI;
- from = X_CONFIG;
+ } else if(info->MergedFBXDPI) {
- } else if(pScrn1->widthmm > 0 || pScrn1->heightmm > 0) {
+ /* Set option-wise given values (overrules DisplaySize config option) */
+ pScrn1->xDpi = info->MergedFBXDPI;
+ pScrn1->yDpi = info->MergedFBYDPI;
+ from = X_CONFIG;
- /* Set values calculated from given DisplaySize */
- from = X_CONFIG;
- if(pScrn1->widthmm > 0) {
- pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm);
- }
- if(pScrn1->heightmm > 0) {
- pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm);
- }
- xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, pScrn1->widthmm, pScrn1->heightmm);
+ } else if(pScrn1->widthmm > 0 || pScrn1->heightmm > 0) {
+
+ /* Set values calculated from given DisplaySize */
+ from = X_CONFIG;
+ if(pScrn1->widthmm > 0) {
+ pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm);
+ }
+ if(pScrn1->heightmm > 0) {
+ pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm);
+ }
+ if(!quiet) {
+ xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, pScrn1->widthmm, pScrn1->heightmm);
+ }
} else if(ddcWidthmm && ddcHeightmm) {
- /* Set values from DDC-provided display size */
- from = X_PROBED;
- xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, ddcWidthmm, ddcHeightmm );
- pScrn1->widthmm = ddcWidthmm;
- pScrn1->heightmm = ddcHeightmm;
- if(pScrn1->widthmm > 0) {
- pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm);
- }
- if(pScrn1->heightmm > 0) {
- pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm);
- }
+ /* Set values from DDC-provided display size */
+
+ /* Get DDC display size; if only either CRT1 or CRT2 provided these,
+ * assume equal dimensions for both, otherwise add dimensions
+ */
+ if( (DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) &&
+ (DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0)) ) {
+ ddcWidthmm = max(DDC1->features.hsize, DDC2->features.hsize) * 10;
+ ddcHeightmm = max(DDC1->features.vsize, DDC2->features.vsize) * 10;
+ switch(srel) {
+ case radeonLeftOf:
+ case radeonRightOf:
+ ddcWidthmm = (DDC1->features.hsize + DDC2->features.hsize) * 10;
+ break;
+ case radeonAbove:
+ case radeonBelow:
+ ddcHeightmm = (DDC1->features.vsize + DDC2->features.vsize) * 10;
+ default:
+ break;
+ }
+ } else if(DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) {
+ ddcWidthmm = DDC1->features.hsize * 10;
+ ddcHeightmm = DDC1->features.vsize * 10;
+ switch(srel) {
+ case radeonLeftOf:
+ case radeonRightOf:
+ ddcWidthmm *= 2;
+ break;
+ case radeonAbove:
+ case radeonBelow:
+ ddcHeightmm *= 2;
+ default:
+ break;
+ }
+ } else if(DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0) ) {
+ ddcWidthmm = DDC2->features.hsize * 10;
+ ddcHeightmm = DDC2->features.vsize * 10;
+ switch(srel) {
+ case radeonLeftOf:
+ case radeonRightOf:
+ ddcWidthmm *= 2;
+ break;
+ case radeonAbove:
+ case radeonBelow:
+ ddcHeightmm *= 2;
+ default:
+ break;
+ }
+ }
+
+ from = X_PROBED;
+
+ if(!quiet) {
+ xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, ddcWidthmm, ddcHeightmm);
+ }
+
+ pScrn1->widthmm = ddcWidthmm;
+ pScrn1->heightmm = ddcHeightmm;
+ if(pScrn1->widthmm > 0) {
+ pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm);
+ }
+ if(pScrn1->heightmm > 0) {
+ pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm);
+ }
} else {
- pScrn1->xDpi = pScrn1->yDpi = DEFAULT_DPI;
+ pScrn1->xDpi = pScrn1->yDpi = DEFAULT_DPI;
}
@@ -1866,8 +1872,60 @@ RADEONMergedFBSetDpi(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, RADEONScrn2Rel srel
pScrn2->xDpi = pScrn1->xDpi;
pScrn2->yDpi = pScrn1->yDpi;
- xf86DrvMsg(pScrn1->scrnIndex, from, "MergedFB: DPI set to (%d, %d)\n",
- pScrn1->xDpi, pScrn1->yDpi);
+ if(!quiet) {
+ xf86DrvMsg(pScrn1->scrnIndex, from, "MergedFB: DPI set to (%d, %d)\n",
+ pScrn1->xDpi, pScrn1->yDpi);
+ }
+}
+
+
+void
+RADEONMergedFBSetDpi(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, RADEONScrn2Rel srel)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn1);
+
+ RADEONMergedFBCalcDPI(pScrn1, pScrn2, srel, FALSE);
+
+ info->MergedDPISRel = srel;
+ info->RADEONMergedDPIVX = pScrn1->virtualX;
+ info->RADEONMergedDPIVY = pScrn1->virtualY;
+
+}
+
+void
+RADEONMergedFBResetDpi(ScrnInfoPtr pScrn, Bool force)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+ RADEONScrn2Rel srel = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2Position;
+
+ /* This does the same calculation for the DPI as
+ * the initial run. This means that an eventually
+ * given -dpi command line switch will lead to
+ * constant dpi values, regardless of the virtual
+ * screen size.
+ * I consider this consequent. If this is undesired,
+ * one should use the DisplaySize parameter in the
+ * config file instead of the command line switch.
+ * The DPI will be calculated then.
+ */
+
+ if(force ||
+ (info->MergedDPISRel != srel) ||
+ (info->RADEONMergedDPIVX != pScrn->virtualX) ||
+ (info->RADEONMergedDPIVY != pScrn->virtualY)
+ ) {
+
+ RADEONMergedFBCalcDPI(pScrn, info->CRT2pScrn, srel, TRUE);
+
+ pScreen->mmWidth = (pScrn->virtualX * 254 + pScrn->xDpi * 5) / (pScrn->xDpi * 10);
+ pScreen->mmHeight = (pScrn->virtualY * 254 + pScrn->yDpi * 5) / (pScrn->yDpi * 10);
+
+ info->MergedDPISRel = srel;
+ info->RADEONMergedDPIVX = pScrn->virtualX;
+ info->RADEONMergedDPIVY = pScrn->virtualY;
+
+ }
}
/* radeon cursor helpers */
diff --git a/src/radeon_mergedfb.h b/src/radeon_mergedfb.h
index a2c792c5..f8274281 100644
--- a/src/radeon_mergedfb.h
+++ b/src/radeon_mergedfb.h
@@ -107,6 +107,8 @@ RADEONUpdateXineramaScreenInfo(ScrnInfoPtr pScrn1);
extern void
RADEONMergedFBSetDpi(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, RADEONScrn2Rel srel);
extern void
+RADEONMergedFBResetDpi(ScrnInfoPtr pScrn, Bool force);
+extern void
RADEONRecalcDefaultVirtualSize(ScrnInfoPtr pScrn);
/* needed by radeon_cursor.c */