diff options
-rw-r--r-- | include/avivo.h | 18 | ||||
-rw-r--r-- | xorg/Makefile.am | 1 | ||||
-rw-r--r-- | xorg/avivo_bios.c | 87 | ||||
-rw-r--r-- | xorg/avivo_output.c | 34 | ||||
-rw-r--r-- | xorg/avivo_output_lfp.c | 76 |
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; +} |