xserver-xorg-video-avivo: Changes to 'upstream-experimental'
avivotool/avivotool.c | 144 +++++++++++--
include/avivo.h | 52 ++++
include/avivo_chipset.h | 93 ++++++++
include/radeon_reg.h | 21 +
xorg/Makefile.am | 20 +
xorg/avivo.c | 268 +++++++++++++++++--------
xorg/avivo_bios.c | 87 ++++++--
xorg/avivo_chipset.c | 511 ++++++++++++++++++++++++++++++++++++++++++++----
xorg/avivo_common.c | 4
xorg/avivo_crtc.c | 194 ++++++++++++------
xorg/avivo_i2c.c | 56 +++++
xorg/avivo_memory.c | 74 ++++++
xorg/avivo_output.c | 316 ++++++++++++++++++++++++++---
xorg/avivo_output_lfp.c | 76 +++++++
xorg/avivo_state.c | 6
15 files changed, 1637 insertions(+), 285 deletions(-)
New commits:
commit 7800016506da80b09a94279d17c0675b40791db0
Author: Jerome Glisse <glisse@freedesktop.org>
Date: Tue Jul 24 15:38:03 2007 +0200
avivo: rework output dpms handling.
This should have better behavior when dpms status change
is triggered.
diff --git a/include/avivo.h b/include/avivo.h
index 4b39b2e..5e644ed 100644
--- a/include/avivo.h
+++ b/include/avivo.h
@@ -73,6 +73,8 @@ struct avivo_output_private {
unsigned long output_offset;
int number;
char *name;
+ void (*setup)(xf86OutputPtr output);
+ void (*dpms)(xf86OutputPtr output, int mode);
};
struct avivo_state
diff --git a/include/radeon_reg.h b/include/radeon_reg.h
index 5dc370e..6ef9fd2 100644
--- a/include/radeon_reg.h
+++ b/include/radeon_reg.h
@@ -3383,7 +3383,8 @@
#define AVIVO_TMDS2_MYSTERY3 0x7b10
#define AVIVO_LVDS_CNTL 0x7af0
-# define AVIVO_LVDS_EN ((1 << 0) | (1 << 4))
+# define AVIVO_LVDS_EN ((1 << 4))
+# define AVIVO_LVDS_MYSTERY ((1 << 0) | (1 << 2) | (1 << 3))
#define AVIVO_LVDS_BACKLIGHT_CNTL 0x7af8
# define AVIVO_LVDS_BACKLIGHT_CNTL_EN (1 << 0)
# define AVIVO_LVDS_BACKLIGHT_LEVEL_MASK 0x0000ff00
diff --git a/xorg/avivo_crtc.c b/xorg/avivo_crtc.c
index 7dfae82..f48790e 100644
--- a/xorg/avivo_crtc.c
+++ b/xorg/avivo_crtc.c
@@ -172,6 +172,7 @@ avivo_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
}
OUTREG(AVIVO_CRTC_PLL_SOURCE, (0 << AVIVO_CRTC1_PLL_SOURCE_SHIFT)
| (1 << AVIVO_CRTC2_PLL_SOURCE_SHIFT));
+ OUTREG(0x454, INREG(0x454) | 0x2);
avivo_wait_idle(avivo);
}
diff --git a/xorg/avivo_output.c b/xorg/avivo_output.c
index 3406805..84b7489 100644
--- a/xorg/avivo_output.c
+++ b/xorg/avivo_output.c
@@ -28,11 +28,233 @@
/* DPMS */
#define DPMS_SERVER
#include <X11/extensions/dpms.h>
+#include <unistd.h>
#include "avivo.h"
#include "radeon_reg.h"
+static void
+avivo_output_dac1_setup(xf86OutputPtr output)
+{
+ struct avivo_output_private *avivo_output = output->driver_private;
+ struct avivo_info *avivo = avivo_get_info(output->scrn);
+
+ if (output->crtc) {
+ struct avivo_crtc_private *avivo_crtc = output->crtc->driver_private;
+
+ xf86DrvMsg(output->scrn->scrnIndex, X_INFO,
+ "(DAC1) %s connector associated to crtc(%d)\n",
+ xf86ConnectorGetName(avivo_output->type),
+ avivo_crtc->crtc_number);
+ OUTREG(AVIVO_DAC1_CRTC_SOURCE, avivo_crtc->crtc_number);
+ }
+ OUTREG(AVIVO_DAC1_MYSTERY1, 0);
+ OUTREG(AVIVO_DAC1_MYSTERY2, 0);
+ OUTREG(AVIVO_DAC1_CNTL, AVIVO_DAC_EN);
+}
+
+static void
+avivo_output_dac2_setup(xf86OutputPtr output)
+{
+ struct avivo_output_private *avivo_output = output->driver_private;
+ struct avivo_info *avivo = avivo_get_info(output->scrn);
+
+ if (output->crtc) {
+ struct avivo_crtc_private *avivo_crtc = output->crtc->driver_private;
+
+ xf86DrvMsg(output->scrn->scrnIndex, X_INFO,
+ "(DAC2) %s connector associated to crtc(%d)\n",
+ xf86ConnectorGetName(avivo_output->type),
+ avivo_crtc->crtc_number);
+ OUTREG(AVIVO_DAC2_CRTC_SOURCE, avivo_crtc->crtc_number);
+ }
+ OUTREG(AVIVO_DAC2_MYSTERY1, 0);
+ OUTREG(AVIVO_DAC2_MYSTERY2, 0);
+ OUTREG(AVIVO_DAC2_CNTL, AVIVO_DAC_EN);
+}
+
+static void
+avivo_output_tmds1_setup(xf86OutputPtr output)
+{
+ struct avivo_output_private *avivo_output = output->driver_private;
+ struct avivo_info *avivo = avivo_get_info(output->scrn);
+
+ if (output->crtc) {
+ struct avivo_crtc_private *avivo_crtc = output->crtc->driver_private;
+
+ xf86DrvMsg(output->scrn->scrnIndex, X_INFO,
+ "(TMDS1) %s connector associated to crtc(%d)\n",
+ xf86ConnectorGetName(avivo_output->type),
+ avivo_crtc->crtc_number);
+ OUTREG(AVIVO_TMDS1_CRTC_SOURCE, avivo_crtc->crtc_number);
+ }
+ OUTREG(AVIVO_TMDS1_MYSTERY1, AVIVO_TMDS_MYSTERY1_EN);
+ OUTREG(AVIVO_TMDS1_MYSTERY2, AVIVO_TMDS_MYSTERY2_EN);
+ OUTREG(AVIVO_TMDS1_MYSTERY3, 0x30630011);
+ OUTREG(AVIVO_TMDS1_CLOCK_CNTL, 0x1f1f);
+ OUTREG(AVIVO_TMDS1_CNTL, AVIVO_TMDS_EN);
+}
+
+static void
+avivo_output_tmds2_setup(xf86OutputPtr output)
+{
+ struct avivo_output_private *avivo_output = output->driver_private;
+ struct avivo_info *avivo = avivo_get_info(output->scrn);
+
+ xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "SETUP TMDS2\n");
+ if (output->crtc) {
+ struct avivo_crtc_private *avivo_crtc = output->crtc->driver_private;
+
+ xf86DrvMsg(output->scrn->scrnIndex, X_INFO,
+ "(TMDS2) %s connector associated to crtc(%d)\n",
+ xf86ConnectorGetName(avivo_output->type),
+ avivo_crtc->crtc_number);
+ OUTREG(AVIVO_TMDS2_CRTC_SOURCE, avivo_crtc->crtc_number);
+ }
+ OUTREG(AVIVO_TMDS2_CLOCK_CNTL, 0x1f3f);
+ OUTREG(AVIVO_TMDS2_MYSTERY1, AVIVO_TMDS_MYSTERY1_EN);
+ OUTREG(AVIVO_TMDS2_MYSTERY2, AVIVO_TMDS_MYSTERY2_EN);
+ if (avivo_output->type == XF86ConnectorLFP) {
+ OUTREG(AVIVO_TMDS2_MYSTERY3, 0x00630011);
+ OUTREG(AVIVO_TMDS2_CNTL, AVIVO_TMDS_EN | (1 << 24));
+ } else {
+ OUTREG(AVIVO_TMDS2_MYSTERY3, 0x30630011);
+ OUTREG(AVIVO_TMDS2_CNTL, AVIVO_TMDS_EN);
+ }
+}
+
+static void
+avivo_output_dac1_dpms(xf86OutputPtr output, int mode)
+{
+ struct avivo_info *avivo = avivo_get_info(output->scrn);
+
+ switch(mode) {
+ case DPMSModeOn:
+ OUTREG(AVIVO_DAC1_CNTL, AVIVO_DAC_EN);
+ break;
+ case DPMSModeStandby:
+ case DPMSModeSuspend:
+ case DPMSModeOff:
+ OUTREG(AVIVO_DAC1_CNTL, 0);
+ break;
+ }
+}
+
+static void
+avivo_output_dac2_dpms(xf86OutputPtr output, int mode)
+{
+ struct avivo_info *avivo = avivo_get_info(output->scrn);
+
+ switch(mode) {
+ case DPMSModeOn:
+ OUTREG(AVIVO_DAC2_CNTL, AVIVO_DAC_EN);
+ break;
+ case DPMSModeStandby:
+ case DPMSModeSuspend:
+ case DPMSModeOff:
+ OUTREG(AVIVO_DAC2_CNTL, 0);
+ break;
+ }
+}
+
+static void
+avivo_output_tmds1_dpms(xf86OutputPtr output, int mode)
+{
+ struct avivo_info *avivo = avivo_get_info(output->scrn);
+
+ switch(mode) {
+ case DPMSModeOn:
+ OUTREG(AVIVO_TMDS1_CLOCK_ENABLE, 1);
+ OUTREG(AVIVO_TMDS1_CLOCK_CNTL, 0x3E);
+ break;
+ case DPMSModeStandby:
+ case DPMSModeSuspend:
+ case DPMSModeOff:
+ OUTREG(AVIVO_TMDS1_CLOCK_CNTL, 0);
+ OUTREG(AVIVO_TMDS1_CLOCK_ENABLE, 0);
+ break;
+ }
+}
+
+static void
+avivo_output_tmds2_dpms(xf86OutputPtr output, int mode)
+{
+ struct avivo_info *avivo = avivo_get_info(output->scrn);
+
+ switch(mode) {
+ case DPMSModeOn:
+ OUTREG(AVIVO_TMDS2_CLOCK_ENABLE, 1);
+ OUTREG(AVIVO_TMDS2_CLOCK_CNTL, 0x3E);
+ break;
+ case DPMSModeStandby:
+ case DPMSModeSuspend:
+ case DPMSModeOff:
+ OUTREG(AVIVO_TMDS2_CLOCK_CNTL, 0);
+ OUTREG(AVIVO_TMDS2_CLOCK_ENABLE, 0);
+ break;
+ }
+}
+
+static void
+avivo_output_lvds_dpms(xf86OutputPtr output, int mode)
+{
+ struct avivo_info *avivo = avivo_get_info(output->scrn);
+ int tmp;
+
+ switch(mode) {
+ case DPMSModeOn:
+ xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "ENABLE TMDS2\n");
+ OUTREG(AVIVO_LVDS_CNTL, AVIVO_LVDS_EN | AVIVO_LVDS_MYSTERY);
+ OUTREG(AVIVO_TMDS2_CLOCK_CNTL, 0x1E1E);
+ break;
+ case DPMSModeStandby:
+ case DPMSModeSuspend:
+ case DPMSModeOff:
+ xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "DISABLE TMDS2\n");
+ OUTREG(AVIVO_LVDS_CNTL, AVIVO_LVDS_MYSTERY);
+ do {
+ tmp = INREG(0x7AF4);
+ usleep(100);
+ } while (tmp != 0x800);
+ OUTREG(AVIVO_TMDS2_CLOCK_CNTL, 0);
+ OUTREG(AVIVO_TMDS2_CLOCK_ENABLE, 0);
+ break;
+ }
+}
+#if 1
+static void
+avivo_output_dpms(xf86OutputPtr output, int mode)
+{
+ struct avivo_output_private *avivo_output = output->driver_private;
+ struct avivo_info *avivo = avivo_get_info(output->scrn);
+ int tmp, count;
+
+ /* try to grab card lock or at least somethings that looks like a lock
+ * if it fails more than 5 times with 1000ms wait btw each try than we
+ * assume we can process.
+ */
+ count = 0;
+ tmp = INREG(0x0028);
+ while((tmp & 0x100) && (count < 5)) {
+ tmp = INREG(0x0028);
+ count++;
+ usleep(1000);
+ }
+ if (count >= 5) {
+ xf86DrvMsg(output->scrn->scrnIndex, X_INFO,
+ "%s (WARNING) failed to grab card lock process anyway.\n",
+ __func__);
+ }
+ OUTREG(0x0028, tmp | 0x100);
+
+ if (avivo_output->dpms)
+ avivo_output->dpms(output, mode);
+ /* release card lock */
+ tmp = INREG(0x0028);
+ OUTREG(0x0028, tmp & (~0x100));
+}
+#else
static void
avivo_output_dpms(xf86OutputPtr output, int mode)
{
@@ -144,7 +366,7 @@ avivo_output_dpms(xf86OutputPtr output, int mode)
break;
}
}
-
+#endif
static int
avivo_output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
{
@@ -181,6 +403,10 @@ avivo_output_mode_set(xf86OutputPtr output,
static void
avivo_output_commit(xf86OutputPtr output)
{
+ struct avivo_output_private *avivo_output = output->driver_private;
+
+ if (avivo_output->setup)
+ avivo_output->setup(output);
output->funcs->dpms(output, DPMSModeOn);
}
@@ -344,6 +570,35 @@ avivo_output_init(ScrnInfoPtr screen_info, xf86ConnectorType type,
break;
}
}
+ switch (avivo_output->type) {
+ case XF86ConnectorVGA:
+ if (!number) {
+ avivo_output->setup = avivo_output_dac1_setup;
+ avivo_output->dpms = avivo_output_dac1_dpms;
+ } else {
+ avivo_output->setup = avivo_output_dac2_setup;
+ avivo_output->dpms = avivo_output_dac2_dpms;
+ }
+ break;
+ case XF86ConnectorLFP:
+ avivo_output->setup = avivo_output_tmds2_setup;
+ avivo_output->dpms = avivo_output_lvds_dpms;
+ break;
+ case XF86ConnectorDVI_I:
+ case XF86ConnectorDVI_D:
+ case XF86ConnectorDVI_A:
+ if (!number) {
+ avivo_output->setup = avivo_output_tmds1_setup;
+ avivo_output->dpms = avivo_output_tmds1_dpms;
+ } else {
+ avivo_output->setup = avivo_output_tmds2_setup;
+ avivo_output->dpms = avivo_output_tmds2_dpms;
+ }
+ break;
+ default:
+ avivo_output->setup = NULL;
+ break;
+ }
if (avivo_output->type == XF86ConnectorLFP) {
avivo_output->output_offset = AVIVO_TMDS2_CNTL - AVIVO_TMDS1_CNTL;
/* allocate & initialize xf86Output */
commit e03a0c86190f74962a6ff59602f274e27353d6ae
Author: Jerome Glisse <glisse@localhost.localdomain>
Date: Thu Jul 19 19:25:20 2007 +0200
avivo: fix previous commit on PLL (usual cut & paste bug introduction).
diff --git a/xorg/avivo_crtc.c b/xorg/avivo_crtc.c
index 45fffcd..7dfae82 100644
--- a/xorg/avivo_crtc.c
+++ b/xorg/avivo_crtc.c
@@ -121,7 +121,7 @@ avivo_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
double c;
int div1, div2, clock;
int sdiv1, sdiv2, smul, sclock;
- int tdiv1, tdiv2, tmul, tclock;
+ int mul;
c = (((double)mode->Clock) * 40.0) / 1080000.0;
clock = mode->Clock;
@@ -130,17 +130,15 @@ avivo_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
smul = 0;
for (div1 = 2; div1 <= 6; div1++) {
for (div2 = div1 + 1; div2 < (div1 + 14); div2++) {
- tmul = ceil(c * div1 * div2);
- tdiv1 = div1;
- tdiv2 = div2;
- tclock = (tmul * 1080000) / (40 * tdiv1 * tdiv2);
- if ((tclock - clock) >= 0 &&
- fabsl(sclock - clock) > fabsl(tclock - clock) &&
- tmul < 256 && (tdiv1 * tdiv2) > (sdiv1 * sdiv2)) {
- sdiv1 = tdiv1;
- sdiv2 = tdiv2;
- smul = tmul;
- sclock = tclock;
+ mul = ceil(c * div1 * div2);
+ clock = (mul * 1080000) / (40 * div1 * div2);
+ if ((div1 * div2) > 20 && (clock - mode->Clock) >= 0 &&
+ fabsl(sclock - mode->Clock) >= fabsl(clock - mode->Clock) &&
+ mul < 256 && (div1 * div2) > (sdiv1 * sdiv2)) {
+ sdiv1 = div1;
+ sdiv2 = div2;
+ smul = mul;
+ sclock = clock;
}
}
}
commit 830e10b7fe41c58e2fb61c6778fe59be0febdfbd
Author: Jerome Glisse <glisse@freedesktop.org>
Date: Thu Jul 19 18:43:45 2007 +0200
avivo: change pll values computation algorithm.
No more infinite loop, simply goes over all values.
The constraint i put are based on several dump with
several different modes clock and barely resume to:
1 < div1 < 7
div1 < div2 < div1 + 14
1 < mul < 256
div1 * div2 should be as big as possible
diff --git a/xorg/avivo_crtc.c b/xorg/avivo_crtc.c
index 9d70e52..45fffcd 100644
--- a/xorg/avivo_crtc.c
+++ b/xorg/avivo_crtc.c
@@ -118,70 +118,58 @@ avivo_crtc_set_pll(xf86CrtcPtr crtc, DisplayModePtr mode)
{
struct avivo_crtc_private *avivo_crtc = crtc->driver_private;
struct avivo_info *avivo = avivo_get_info(crtc->scrn);
- int adjusted_clock;
- int div, pdiv, pmul;
- int n_pdiv, n_pmul, n_div;
- int clock;
- int diff, n_diff;
-
- adjusted_clock = mode->Clock;
- div = 8;
- pdiv = 6;
- pmul = floor(((40.0 * adjusted_clock * pdiv * div)
- / 1080000.0) + 0.5);
- clock = (pmul * 1080000) / (40 * pdiv * div);
- diff = clock - adjusted_clock;
- while (1) {
- if (pmul > 255) {
- if (pdiv > 2) {
- n_pdiv = pdiv - 1;
- n_div = div;
- } else {
- n_pdiv = pdiv;
- n_div = div - 1;
+ double c;
+ int div1, div2, clock;
+ int sdiv1, sdiv2, smul, sclock;
+ int tdiv1, tdiv2, tmul, tclock;
+
+ c = (((double)mode->Clock) * 40.0) / 1080000.0;
+ clock = mode->Clock;
+ sdiv1 = 0;
+ sdiv2 = 0;
+ smul = 0;
+ for (div1 = 2; div1 <= 6; div1++) {
+ for (div2 = div1 + 1; div2 < (div1 + 14); div2++) {
+ tmul = ceil(c * div1 * div2);
+ tdiv1 = div1;
+ tdiv2 = div2;
+ tclock = (tmul * 1080000) / (40 * tdiv1 * tdiv2);
+ if ((tclock - clock) >= 0 &&
+ fabsl(sclock - clock) > fabsl(tclock - clock) &&
+ tmul < 256 && (tdiv1 * tdiv2) > (sdiv1 * sdiv2)) {
+ sdiv1 = tdiv1;
+ sdiv2 = tdiv2;
+ smul = tmul;
+ sclock = tclock;
}
- } else {
- n_pdiv = pdiv;
- n_div = div + 1;
}
- n_pmul = floor(((40.0 * adjusted_clock * n_pdiv * n_div) / 1080000.0)
- + 0.5);
- clock = (n_pmul * 1080000) / (40 * n_pdiv * n_div);
- n_diff = clock - adjusted_clock;
- if (diff >= 0 && fabsl(n_diff) >= diff && pmul <= 255)
- break;
- div = n_div;
- pdiv = n_pdiv;
- pmul = n_pmul;
- diff = n_diff;
}
- clock = (pmul * 1080000) / (40 * pdiv * div);
xf86DrvMsg(crtc->scrn->scrnIndex, X_INFO,
"crtc(%d) Clock: mode %d, PLL %d\n",
- avivo_crtc->crtc_number, mode->Clock, clock);
+ avivo_crtc->crtc_number, mode->Clock, sclock);
xf86DrvMsg(crtc->scrn->scrnIndex, X_INFO,
"crtc(%d) PLL : div %d, pmul 0x%X(%d), pdiv %d\n",
- avivo_crtc->crtc_number, div, pmul, pmul, pdiv);
+ avivo_crtc->crtc_number, sdiv1, smul, smul, sdiv2);
switch (avivo_crtc->crtc_number) {
case 0:
OUTREG(AVIVO_PLL1_POST_DIV_CNTL, AVIVO_PLL_POST_DIV_EN);
- OUTREG(AVIVO_PLL1_POST_DIV_MYSTERY, AVIVO_PLL_POST_DIV_MYSTERY_VALUE);
- OUTREG(AVIVO_PLL1_POST_DIV, pdiv);
- OUTREG(AVIVO_PLL1_POST_MUL, (pmul << AVIVO_PLL_POST_MUL_SHIFT));
- OUTREG(AVIVO_PLL1_DIVIDER_CNTL, AVIVO_PLL_DIVIDER_EN);
- OUTREG(AVIVO_PLL1_DIVIDER, div);
- OUTREG(AVIVO_PLL1_MYSTERY0, AVIVO_PLL_MYSTERY0_VALUE);
- OUTREG(AVIVO_PLL1_MYSTERY1, AVIVO_PLL_MYSTERY1_VALUE);
+ OUTREG(AVIVO_PLL1_POST_DIV_MYSTERY, AVIVO_PLL_POST_DIV_MYSTERY_VALUE);
+ OUTREG(AVIVO_PLL1_POST_DIV, sdiv1);
+ OUTREG(AVIVO_PLL1_POST_MUL, (smul << AVIVO_PLL_POST_MUL_SHIFT));
+ OUTREG(AVIVO_PLL1_DIVIDER_CNTL, AVIVO_PLL_DIVIDER_EN);
+ OUTREG(AVIVO_PLL1_DIVIDER, sdiv2);
+ OUTREG(AVIVO_PLL1_MYSTERY0, AVIVO_PLL_MYSTERY0_VALUE);
+ OUTREG(AVIVO_PLL1_MYSTERY1, AVIVO_PLL_MYSTERY1_VALUE);
break;
case 1:
OUTREG(AVIVO_PLL2_POST_DIV_CNTL, AVIVO_PLL_POST_DIV_EN);
- OUTREG(AVIVO_PLL2_POST_DIV_MYSTERY, AVIVO_PLL_POST_DIV_MYSTERY_VALUE);
- OUTREG(AVIVO_PLL2_POST_DIV, pdiv);
- OUTREG(AVIVO_PLL2_POST_MUL, (pmul << AVIVO_PLL_POST_MUL_SHIFT));
- OUTREG(AVIVO_PLL2_DIVIDER_CNTL, AVIVO_PLL_DIVIDER_EN);
- OUTREG(AVIVO_PLL2_DIVIDER, div);
- OUTREG(AVIVO_PLL2_MYSTERY0, AVIVO_PLL_MYSTERY0_VALUE);
- OUTREG(AVIVO_PLL2_MYSTERY1, AVIVO_PLL_MYSTERY1_VALUE);
+ OUTREG(AVIVO_PLL2_POST_DIV_MYSTERY, AVIVO_PLL_POST_DIV_MYSTERY_VALUE);
+ OUTREG(AVIVO_PLL2_POST_DIV, sdiv1);
+ OUTREG(AVIVO_PLL2_POST_MUL, (smul << AVIVO_PLL_POST_MUL_SHIFT));
+ OUTREG(AVIVO_PLL2_DIVIDER_CNTL, AVIVO_PLL_DIVIDER_EN);
+ OUTREG(AVIVO_PLL2_DIVIDER, sdiv2);
+ OUTREG(AVIVO_PLL2_MYSTERY0, AVIVO_PLL_MYSTERY0_VALUE);
+ OUTREG(AVIVO_PLL2_MYSTERY1, AVIVO_PLL_MYSTERY1_VALUE);
break;
}
OUTREG(AVIVO_CRTC_PLL_SOURCE, (0 << AVIVO_CRTC1_PLL_SOURCE_SHIFT)
commit 559b7019a736c6fff19b63e4c4f3e646f00b5717
Author: Jerome Glisse <glisse@freedesktop.org>
Date: Wed Jul 18 19:07:34 2007 +0200
avivo: push missing bits from last commit.
diff --git a/xorg/avivo_i2c.c b/xorg/avivo_i2c.c
index 12979b0..8bc696f 100644
--- a/xorg/avivo_i2c.c
+++ b/xorg/avivo_i2c.c
@@ -28,3 +28,59 @@
#include "avivo.h"
#include "radeon_reg.h"
#include <stdint.h>
+
+void
+avivo_i2c_gpio0_get_bits(I2CBusPtr b, int *Clock, int *data)
+{
+ ScrnInfoPtr screen_info = xf86Screens[b->scrnIndex];
+ struct avivo_info *avivo = avivo_get_info(screen_info);
+ unsigned long val;
+
+ /* Get the result */
+ val = INREG(b->DriverPrivate.uval + 0xC);
+ *Clock = (val & (1<<19)) != 0;
+ *data = (val & (1<<18)) != 0;
+}
+
+void
+avivo_i2c_gpio0_put_bits(I2CBusPtr b, int Clock, int data)
+{
+ ScrnInfoPtr screen_info = xf86Screens[b->scrnIndex];
+ struct avivo_info *avivo = avivo_get_info(screen_info);
+ unsigned long val;
+
+ val = 0;
+ val |= (Clock ? 0:(1<<19));
+ val |= (data ? 0:(1<<18));
+ OUTREG(b->DriverPrivate.uval + 0x8, val);
+ /* read back to improve reliability on some cards. */
+ val = INREG(b->DriverPrivate.uval + 0x8);
+}
+
+void
+avivo_i2c_gpio123_get_bits(I2CBusPtr b, int *Clock, int *data)
+{
+ ScrnInfoPtr screen_info = xf86Screens[b->scrnIndex];
+ struct avivo_info *avivo = avivo_get_info(screen_info);
+ unsigned long val;
+
+ /* Get the result */
+ val = INREG(b->DriverPrivate.uval + 0xC);
+ *Clock = (val & (1<<0)) != 0;
+ *data = (val & (1<<8)) != 0;
+}
+
+void
+avivo_i2c_gpio123_put_bits(I2CBusPtr b, int Clock, int data)
+{
+ ScrnInfoPtr screen_info = xf86Screens[b->scrnIndex];
+ struct avivo_info *avivo = avivo_get_info(screen_info);
+ unsigned long val;
+
+ val = 0;
+ val |= (Clock ? 0:(1<<0));
+ val |= (data ? 0:(1<<8));
+ OUTREG(b->DriverPrivate.uval + 0x8, val);
+ /* read back to improve reliability on some cards. */
+ val = INREG(b->DriverPrivate.uval + 0x8);
+}
commit d779065b5ad8d3b30e4c91c8a3ad8935292e05c1
Author: Jerome Glisse <glisse@freedesktop.org>
Date: Wed Jul 18 18:53:51 2007 +0200
avivo: properly handle GPIO 0 (0x7E30) for i2c.
diff --git a/avivotool/avivotool.c b/avivotool/avivotool.c
index 0f0dba8..bb06c72 100644
--- a/avivotool/avivotool.c
+++ b/avivotool/avivotool.c
@@ -1588,6 +1588,7 @@ static void radeon_rom_atom_connectors(unsigned char *bios, int master)
for (i = 0; i < 8; i++) {
if (tmp & (1 << i)) {
+ int gpio;
int portinfo = BIOS16(offset + 6 + i * 2);
crtc = (portinfo >> 8) & 0xf;
@@ -1596,16 +1597,17 @@ static void radeon_rom_atom_connectors(unsigned char *bios, int master)
tmp0 = BIOS16(master + 24);
if (1 /* crtc */) {
- int gpio = BIOS16(tmp0 + 4 + 27 * crtc) * 4;
+ gpio = BIOS16(tmp0 + 4 + 27 * crtc) * 4;
switch(gpio)
{
case RADEON_GPIO_MONID: ddc = 1; break;
case RADEON_GPIO_DVI_DDC: ddc = 2; break;
case RADEON_GPIO_VGA_DDC: ddc = 3; break;
case RADEON_GPIO_CRT2_DDC: ddc = 4; break;
- case AVIVO_GPIO_CONNECTOR_0: ddc = 5; break;
- case AVIVO_GPIO_CONNECTOR_1: ddc = 6; break;
- case AVIVO_GPIO_LVDS: ddc = 7; break;
+ case AVIVO_GPIO_0: ddc = 7; break;
+ case AVIVO_GPIO_1: ddc = 5; break;
+ case AVIVO_GPIO_2: ddc = 6; break;
+ case AVIVO_GPIO_3: ddc = 7; break;
default: ddc = 0; break;
}
}
@@ -1619,6 +1621,7 @@ static void radeon_rom_atom_connectors(unsigned char *bios, int master)
/* On AVIVO cards, the DAC is unset for TMDS */
if (dac >= 0 || (i != 3 && i != 7))
printf(", DAC: %s", radeon_valname(ldac_type_name, dac));
+ printf(", GPIO: 0x%04X", gpio);
if (i == 3)
printf(" TMDS: Internal\n");
else if (i == 7)
diff --git a/include/avivo.h b/include/avivo.h
index 083b572..4b39b2e 100644
--- a/include/avivo.h
+++ b/include/avivo.h
@@ -69,6 +69,7 @@ struct avivo_crtc_private {
struct avivo_output_private {
xf86ConnectorType type;
I2CBusPtr i2c;
+ unsigned long gpio;
unsigned long output_offset;
int number;
char *name;
@@ -283,4 +284,12 @@ FBLinearPtr avivo_xf86AllocateOffscreenLinear(ScreenPtr screen, int length,
RemoveLinearCallbackProcPtr removeCB,
pointer priv_data);
+/*
+ * avivo i2c
+ */
+void avivo_i2c_gpio0_get_bits(I2CBusPtr b, int *Clock, int *data);
+void avivo_i2c_gpio0_put_bits(I2CBusPtr b, int Clock, int data);
+void avivo_i2c_gpio123_get_bits(I2CBusPtr b, int *Clock, int *data);
+void avivo_i2c_gpio123_put_bits(I2CBusPtr b, int Clock, int data);
+
#endif /* _AVIVO_H_ */
diff --git a/include/radeon_reg.h b/include/radeon_reg.h
index 936e5a3..5dc370e 100644
--- a/include/radeon_reg.h
+++ b/include/radeon_reg.h
@@ -3390,9 +3390,10 @@
# define AVIVO_LVDS_BACKLIGHT_LEVEL_SHIFT 8
/* The BIOS says so, anyway ... */
-#define AVIVO_GPIO_CONNECTOR_0 0x7e40
-#define AVIVO_GPIO_CONNECTOR_1 0x7e50
-#define AVIVO_GPIO_LVDS 0x7e60
+#define AVIVO_GPIO_0 0x7e30
+#define AVIVO_GPIO_1 0x7e40
+#define AVIVO_GPIO_2 0x7e50
+#define AVIVO_GPIO_3 0x7e60
#define AVIVO_TMDS_STATUS 0x7e9c
# define AVIVO_TMDS1_CONNECTED (1 << 0)
diff --git a/xorg/avivo_output.c b/xorg/avivo_output.c
index 4e2a5d5..3406805 100644
--- a/xorg/avivo_output.c
+++ b/xorg/avivo_output.c
@@ -32,33 +32,6 @@
#include "avivo.h"
#include "radeon_reg.h"
-static void
-avivo_i2c_get_bits(I2CBusPtr b, int *Clock, int *data)
-{
- ScrnInfoPtr screen_info = xf86Screens[b->scrnIndex];
- struct avivo_info *avivo = avivo_get_info(screen_info);
- unsigned long val;
-
- /* Get the result */
- val = INREG(b->DriverPrivate.uval + 0xC);
- *Clock = (val & (1<<0)) != 0;
- *data = (val & (1<<8)) != 0;
-}
-
-static void
-avivo_i2c_put_bits(I2CBusPtr b, int Clock, int data)
-{
- ScrnInfoPtr screen_info = xf86Screens[b->scrnIndex];
- struct avivo_info *avivo = avivo_get_info(screen_info);
- unsigned long val;
-
- val = 0;
- val |= (Clock ? 0:(1<<0));
- val |= (data ? 0:(1<<8));
- OUTREG(b->DriverPrivate.uval + 0x8, val);
- /* read back to improve reliability on some cards. */
- val = INREG(b->DriverPrivate.uval + 0x8);
-}
static void
avivo_output_dpms(xf86OutputPtr output, int mode)
@@ -337,8 +310,13 @@ avivo_output_init(ScrnInfoPtr screen_info, xf86ConnectorType type,
}
avivo_output->i2c->BusName = avivo_output->name;
avivo_output->i2c->scrnIndex = screen_info->scrnIndex;
- avivo_output->i2c->I2CPutBits = avivo_i2c_put_bits;
- avivo_output->i2c->I2CGetBits = avivo_i2c_get_bits;
+ if (ddc_reg == AVIVO_GPIO_0) {
+ avivo_output->i2c->I2CPutBits = avivo_i2c_gpio0_put_bits;
+ avivo_output->i2c->I2CGetBits = avivo_i2c_gpio0_get_bits;
+ } else {
+ avivo_output->i2c->I2CPutBits = avivo_i2c_gpio123_put_bits;
+ avivo_output->i2c->I2CGetBits = avivo_i2c_gpio123_get_bits;
+ }
avivo_output->i2c->AcknTimeout = 5;
avivo_output->i2c->DriverPrivate.uval = ddc_reg;
if (!xf86I2CBusInit(avivo_output->i2c)) {
@@ -347,6 +325,7 @@ avivo_output_init(ScrnInfoPtr screen_info, xf86ConnectorType type,
xf86ConnectorGetName(type), number);
return FALSE;
}
+ avivo_output->gpio = ddc_reg;
avivo_output->type = type;
avivo_output->number = number;
avivo_output->output_offset = 0;
commit d3564fe5f01a924018f206b9b911348ab6b0a3bb
Author: Jerome Glisse <glisse@freedesktop.org>
Date: Wed Jul 18 18:29:37 2007 +0200
avivotool: fix handling of gpio 0x7e30.
diff --git a/avivotool/avivotool.c b/avivotool/avivotool.c
index 0fcf69d..0f0dba8 100644
--- a/avivotool/avivotool.c
+++ b/avivotool/avivotool.c
@@ -324,8 +324,8 @@ static void AVIVOI2CGetBits(I2CBusPtr b, int *Clock, int *data)
*Clock = (val & (1<<0)) != 0;
*data = (val & (1<<8)) != 0;
} else {
- *Clock = (val & (1<<18)) != 0;
- *data = (val & (1<<19)) != 0;
+ *Clock = (val & (1<<19)) != 0;
+ *data = (val & (1<<18)) != 0;
}
if (debug_i2c)
printf("IN 0x%08lX -> clock = %d, data = %d\n", val, *Clock, *data);
@@ -340,8 +340,8 @@ static void AVIVOI2CPutBits(I2CBusPtr b, int Clock, int data)
val |= (Clock ? 0:(1<<0));
val |= (data ? 0:(1<<8));
} else {
- val |= (Clock ? 0:(1<<18));
- val |= (data ? 0:(1<<19));
+ val |= (Clock ? 0:(1<<19));
+ val |= (data ? 0:(1<<18));
}
if (debug_i2c)
printf("OUT 0x%08lX (Clock = %d, data = %d)\n", val, Clock, data);
commit 7da689181f473877d27cf9b9bb5fac0713b089b6
Author: Jerome Glisse <glisse@freedesktop.org>
Date: Wed Jul 18 01:05:53 2007 +0200
avivo: If EDID fails for LFP use timings from bios.
In case EDID fails we use bios timings if they are
present, if they are not present we should add a
function to extract timings from currently set mode.
diff --git a/include/avivo.h b/include/avivo.h
index 53eb949..083b572 100644
--- a/include/avivo.h
+++ b/include/avivo.h
@@ -184,7 +184,7 @@ struct avivo_info
#endif
unsigned char *vbios;
int rom_header;
- int master_data;
+ int master_offset;
int is_atom_bios;
int bpp;
@@ -231,6 +231,11 @@ void avivo_set_mc(ScrnInfoPtr screen_info,
struct avivo_info *avivo_get_info(ScrnInfoPtr screen_info);
/*
+ * avivo bios functions
+ */
+DisplayModePtr avivo_bios_get_lfp_timing(ScrnInfoPtr screen_info);
+
+/*
* avivo state handling
*/
void avivo_wait_idle(struct avivo_info *avivo);
@@ -249,11 +254,18 @@ Bool avivo_crtc_create(ScrnInfoPtr screen_info);
*/
Bool avivo_output_exist(ScrnInfoPtr screen_info, xf86ConnectorType type,
int number, unsigned long ddc_reg);
-
Bool avivo_output_init(ScrnInfoPtr screen_info, xf86ConnectorType type,
int number, unsigned long ddc_reg);
-
Bool avivo_output_setup(ScrnInfoPtr screen_info);
+DisplayModePtr avivo_output_get_modes(xf86OutputPtr output);
+
+/*
+ * avivo lfp output handling
+ */
+Bool avivo_output_lfp_mode_fixup(xf86OutputPtr output,
+ DisplayModePtr mode,
+ DisplayModePtr adjusted_mode);
+DisplayModePtr avivo_output_lfp_get_modes(xf86OutputPtr output);
/*
* avivo cursor handling
diff --git a/xorg/Makefile.am b/xorg/Makefile.am
index 771d05d..1b211f7 100644
--- a/xorg/Makefile.am
+++ b/xorg/Makefile.am
@@ -37,5 +37,6 @@ avivo_drv_la_SOURCES = \
avivo_cursor.c \
avivo_crtc.c \
avivo_output.c \
+ avivo_output_lfp.c \
avivo_i2c.c \
avivo.c
diff --git a/xorg/avivo_bios.c b/xorg/avivo_bios.c
index 3eaadf3..3ec8422 100644
--- a/xorg/avivo_bios.c
+++ b/xorg/avivo_bios.c
@@ -28,10 +28,24 @@
#include "avivo.h"
#include "radeon_reg.h"
-#define RADEON_BIOS8(v) (avivo->vbios[v])
-#define RADEON_BIOS16(v) (avivo->vbios[v] | \
+#define ATOM_OFFSET_ROM_HEADER_OFFSET 72
+#define ATOM_ROM_HEADER_MASTER_OFFSET 32
+#define ATOM_MASTER_LFP_OFFSET 16
+#define ATOM_LFP_XRES 6
+#define ATOM_LFP_YRES 10
+#define ATOM_LFP_DOT_CLOCK 4
+#define ATOM_LFP_HBLANK 8
+#define ATOM_LFP_HOVER_PLUS 14
+#define ATOM_LFP_HSYNC_WIDTH 16
+#define ATOM_LFP_VBLANK 12
+#define ATOM_LFP_VOVER_PLUS 18
+#define ATOM_LFP_VSYNC_WIDTH 20
+#define ATOM_LFP_POWER_ON_DELAY 40
+
+#define BIOS8(v) (avivo->vbios[v])
+#define BIOS16(v) (avivo->vbios[v] | \
(avivo->vbios[(v) + 1] << 8))
-#define RADEON_BIOS32(v) (avivo->vbios[v] | \
+#define BIOS32(v) (avivo->vbios[v] | \
(avivo->vbios[(v) + 1] << 8) | \
(avivo->vbios[(v) + 2] << 16) | \
(avivo->vbios[(v) + 3] << 24))
@@ -75,9 +89,9 @@ RADEONGetBIOSInfo(ScrnInfoPtr screen_info)
}
/* Verify it's an x86 BIOS not OF firmware, copied from radeonfb */
- dptr = RADEON_BIOS16(0x18);
+ dptr = BIOS16(0x18);
/* If PCI data signature is wrong assume x86 video BIOS anyway */
- if (RADEON_BIOS32(dptr) != (('R' << 24) | ('I' << 16) | ('C' << 8) | 'P')) {
+ if (BIOS32(dptr) != (('R' << 24) | ('I' << 16) | ('C' << 8) | 'P')) {
xf86DrvMsg(screen_info->scrnIndex, X_WARNING,
"ROM PCI data signature incorrect, ignoring\n");
}
@@ -90,7 +104,7 @@ RADEONGetBIOSInfo(ScrnInfoPtr screen_info)
}
if (avivo->vbios)
- avivo->rom_header = RADEON_BIOS16(0x48);
+ avivo->rom_header = BIOS16(0x48);
if(!avivo->rom_header) {
xf86DrvMsg(screen_info->scrnIndex, X_WARNING,
@@ -101,20 +115,20 @@ RADEONGetBIOSInfo(ScrnInfoPtr screen_info)
}
tmp = avivo->rom_header + 4;
- if ((RADEON_BIOS8(tmp) == 'A' &&
- RADEON_BIOS8(tmp+1) == 'T' &&
- RADEON_BIOS8(tmp+2) == 'O' &&
- RADEON_BIOS8(tmp+3) == 'M') ||
- (RADEON_BIOS8(tmp) == 'M' &&
- RADEON_BIOS8(tmp+1) == 'O' &&
- RADEON_BIOS8(tmp+2) == 'T' &&
- RADEON_BIOS8(tmp+3) == 'A'))
+ if ((BIOS8(tmp) == 'A' &&
+ BIOS8(tmp+1) == 'T' &&
+ BIOS8(tmp+2) == 'O' &&
+ BIOS8(tmp+3) == 'M') ||
+ (BIOS8(tmp) == 'M' &&
+ BIOS8(tmp+1) == 'O' &&
+ BIOS8(tmp+2) == 'T' &&
+ BIOS8(tmp+3) == 'A'))
avivo->is_atom_bios = 1;
else
avivo->is_atom_bios = 0;
if (avivo->is_atom_bios)
- avivo->master_data = RADEON_BIOS16(avivo->rom_header + 32);
+ avivo->master_offset = BIOS16(avivo->rom_header + 32);
xf86DrvMsg(screen_info->scrnIndex, X_INFO, "%s BIOS detected\n",
avivo->is_atom_bios ? "ATOM":"Legacy");
@@ -145,25 +159,25 @@ avivo_output_setup(ScrnInfoPtr screen_info)
if (RADEONGetBIOSInfo(screen_info))
return FALSE;
- offset = RADEON_BIOS16(avivo->master_data + 22);
+ offset = BIOS16(avivo->master_offset + 22);
if (offset == 0) {
xf86DrvMsg(screen_info->scrnIndex, X_INFO,
"No connector table in BIOS");
return 1;
}
- tmp = RADEON_BIOS16(offset + 4);
+ tmp = BIOS16(offset + 4);
for (i = 0; i < 8; i++) {
if (tmp & (1 << i)) {
int portinfo, number, connector_type, tmp0;
unsigned int ddc_reg;
xf86ConnectorType type;
- portinfo = RADEON_BIOS16(offset + 6 + i * 2);
+ portinfo = BIOS16(offset + 6 + i * 2);
number = (portinfo >> 8) & 0xf;
connector_type = (portinfo >> 4) & 0xf;
- tmp0 = RADEON_BIOS16(avivo->master_data + 24);
- ddc_reg = RADEON_BIOS16(tmp0 + 4 + 27 * number) * 4;
+ tmp0 = BIOS16(avivo->master_offset + 24);
+ ddc_reg = BIOS16(tmp0 + 4 + 27 * number) * 4;
switch (connector_type) {
case 0: type = XF86ConnectorNone; break;
case 1: type = XF86ConnectorVGA; break;
@@ -237,3 +251,36 @@ avivo_output_setup(ScrnInfoPtr screen_info)
return TRUE;
}
+
+DisplayModePtr
+avivo_bios_get_lfp_timing(ScrnInfoPtr screen_info)
+{
+ DisplayModePtr mode;
+ struct avivo_info *avivo = avivo_get_info(screen_info);
+ int offset;
+
+ if (!avivo->is_atom_bios || avivo->vbios == NULL)
+ return NULL;
+ offset = BIOS16(avivo->master_offset + ATOM_MASTER_LFP_OFFSET);
+ if (!offset)
+ return NULL;
+ mode = xnfcalloc(1, sizeof(DisplayModeRec));
+ mode->name = xnfalloc(32);
+ snprintf(mode->name, 32, "%dx%d",
+ BIOS16(offset + ATOM_LFP_XRES),
+ BIOS16(offset + ATOM_LFP_YRES));
+ mode->HDisplay = BIOS16(offset + ATOM_LFP_XRES);
+ mode->VDisplay = BIOS16(offset + ATOM_LFP_YRES);
Reply to: