summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJerome Glisse <glisse@freedesktop.org>2007-07-18 01:05:53 +0200
committerJerome Glisse <glisse@freedesktop.org>2007-07-18 01:05:53 +0200
commit7da689181f473877d27cf9b9bb5fac0713b089b6 (patch)
tree753eca874985e884659c38a338d2de3b4ce78fe2
parentd075f407cdedc7eda490d4a24dab36aa6ef5ccc9 (diff)
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.
-rw-r--r--include/avivo.h18
-rw-r--r--xorg/Makefile.am1
-rw-r--r--xorg/avivo_bios.c87
-rw-r--r--xorg/avivo_output.c34
-rw-r--r--xorg/avivo_output_lfp.c76
5 files changed, 159 insertions, 57 deletions
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);
+ mode->HTotal = mode->HDisplay + BIOS16(offset + ATOM_LFP_HBLANK);
+ mode->HSyncStart = mode->HDisplay + BIOS16(offset + ATOM_LFP_HOVER_PLUS);
+ mode->HSyncEnd = mode->HSyncStart + BIOS16(offset + ATOM_LFP_HSYNC_WIDTH);
+ mode->VTotal = mode->VDisplay + BIOS16(offset + ATOM_LFP_VBLANK);
+ mode->VSyncStart = mode->VDisplay + BIOS16(offset + ATOM_LFP_VOVER_PLUS);
+ mode->VSyncEnd = mode->VSyncStart + BIOS16(offset + ATOM_LFP_VSYNC_WIDTH);
+ mode->Clock = BIOS16(offset + ATOM_LFP_DOT_CLOCK) * 10;
+ mode->Flags = 0;
+ mode->type = M_T_USERDEF | M_T_PREFERRED;
+ mode->next = NULL;
+ mode->prev = NULL;
+ return mode;
+}
diff --git a/xorg/avivo_output.c b/xorg/avivo_output.c
index c2bf024..4e2a5d5 100644
--- a/xorg/avivo_output.c
+++ b/xorg/avivo_output.c
@@ -192,28 +192,6 @@ avivo_output_mode_fixup(xf86OutputPtr output,
return TRUE;
}
-static Bool
-avivo_output_lfp_mode_fixup(xf86OutputPtr output,
- DisplayModePtr mode,
- DisplayModePtr adjusted_mode)
-{
- struct avivo_info *avivo = avivo_get_info(output->scrn);
-
- if (avivo->lfp_fixed_mode) {
- adjusted_mode->HDisplay = avivo->lfp_fixed_mode->HDisplay;
- adjusted_mode->HSyncStart = avivo->lfp_fixed_mode->HSyncStart;
- adjusted_mode->HSyncEnd = avivo->lfp_fixed_mode->HSyncEnd;
- adjusted_mode->HTotal = avivo->lfp_fixed_mode->HTotal;
- adjusted_mode->VDisplay = avivo->lfp_fixed_mode->VDisplay;
- adjusted_mode->VSyncStart = avivo->lfp_fixed_mode->VSyncStart;
- adjusted_mode->VSyncEnd = avivo->lfp_fixed_mode->VSyncEnd;
- adjusted_mode->VTotal = avivo->lfp_fixed_mode->VTotal;
- adjusted_mode->Clock = avivo->lfp_fixed_mode->Clock;
- xf86SetModeCrtc(adjusted_mode, 0);
- }
- return TRUE;
-}
-
static void
avivo_output_prepare(xf86OutputPtr output)
{
@@ -262,18 +240,6 @@ avivo_output_get_modes(xf86OutputPtr output)
return modes;
}
-DisplayModePtr
-avivo_output_lfp_get_modes(xf86OutputPtr output)
-{
- struct avivo_info *avivo = avivo_get_info(output->scrn);
- DisplayModePtr modes;
-
- modes = avivo_output_get_modes(output);
- xf86DeleteMode(&avivo->lfp_fixed_mode, avivo->lfp_fixed_mode);
- avivo->lfp_fixed_mode = xf86DuplicateMode(modes);
- return modes;
-}
-
static void
avivo_output_destroy(xf86OutputPtr output)
{
diff --git a/xorg/avivo_output_lfp.c b/xorg/avivo_output_lfp.c
new file mode 100644
index 0000000..fbddf4a
--- /dev/null
+++ b/xorg/avivo_output_lfp.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright © 2007 Daniel Stone
+ * Copyright © 2007 Matthew Garrett
+ * Copyright © 2007 Jerome Glisse
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * A copy of the General Public License is included with the source
+ * distribution of this driver, as COPYING.
+ *
+ * Authors: Daniel Stone <daniel@fooishbar.org>
+ * Matthew Garrett <mjg59@srcf.ucam.org>
+ * Jerome Glisse <glisse@freedesktop.org>
+ */
+/*
+ * avivo output handling functions.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+/* DPMS */
+#define DPMS_SERVER
+#include <X11/extensions/dpms.h>
+
+#include "avivo.h"
+#include "radeon_reg.h"
+
+Bool
+avivo_output_lfp_mode_fixup(xf86OutputPtr output,
+ DisplayModePtr mode,
+ DisplayModePtr adjusted_mode)
+{
+ struct avivo_info *avivo = avivo_get_info(output->scrn);
+
+ if (avivo->lfp_fixed_mode) {
+ adjusted_mode->HDisplay = avivo->lfp_fixed_mode->HDisplay;
+ adjusted_mode->HSyncStart = avivo->lfp_fixed_mode->HSyncStart;
+ adjusted_mode->HSyncEnd = avivo->lfp_fixed_mode->HSyncEnd;
+ adjusted_mode->HTotal = avivo->lfp_fixed_mode->HTotal;
+ adjusted_mode->VDisplay = avivo->lfp_fixed_mode->VDisplay;
+ adjusted_mode->VSyncStart = avivo->lfp_fixed_mode->VSyncStart;
+ adjusted_mode->VSyncEnd = avivo->lfp_fixed_mode->VSyncEnd;
+ adjusted_mode->VTotal = avivo->lfp_fixed_mode->VTotal;
+ adjusted_mode->Clock = avivo->lfp_fixed_mode->Clock;
+ xf86SetModeCrtc(adjusted_mode, 0);
+ }
+ return TRUE;
+}
+
+DisplayModePtr
+avivo_output_lfp_get_modes(xf86OutputPtr output)
+{
+ ScrnInfoPtr screen_info = output->scrn;
+ struct avivo_info *avivo = avivo_get_info(output->scrn);
+ DisplayModePtr modes = NULL;
+
+ modes = avivo_output_get_modes(output);
+ if (modes == NULL) {
+ /* DDC EDID failed try to get timing from BIOS */
+ xf86DrvMsg(screen_info->scrnIndex, X_WARNING,
+ "Failed to get EDID over i2c for LFP try BIOS timings.\n");
+ modes = avivo_bios_get_lfp_timing(screen_info);
+ }
+ if (modes) {
+ xf86DeleteMode(&avivo->lfp_fixed_mode, avivo->lfp_fixed_mode);
+ avivo->lfp_fixed_mode = xf86DuplicateMode(modes);
+ }
+ return modes;
+}