From 1d5cfc649aeba62066af20336ca69566566500c3 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Wed, 3 Aug 2011 03:02:57 +0000 Subject: [PATCH] * move bios functions into bios.cpp * implement various methods to pull AtomBIOS from card * add some missing registers to headers from linux drm driver git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42553 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/graphics/radeon_hd/r600_reg.h | 25 ++ .../accelerants/radeon_hd/accelerant.cpp | 61 +---- .../accelerants/radeon_hd/accelerant.h | 3 +- src/add-ons/accelerants/radeon_hd/bios.cpp | 220 +++++++++++++++++- src/add-ons/accelerants/radeon_hd/bios.h | 2 +- 5 files changed, 250 insertions(+), 61 deletions(-) diff --git a/headers/private/graphics/radeon_hd/r600_reg.h b/headers/private/graphics/radeon_hd/r600_reg.h index 51629338dc..92c1f59211 100644 --- a/headers/private/graphics/radeon_hd/r600_reg.h +++ b/headers/private/graphics/radeon_hd/r600_reg.h @@ -34,14 +34,39 @@ #include "r600_reg_r7xx.h" +/* From Linux DRM Radeon driver for AtomBIOS */ +#define RADEON_SEPROM_CNTL1 0x01c0 +#define RADEON_SCK_PRESCALE_SHIFT 24 +#define RADEON_SCK_PRESCALE_MASK (0xff << 24) + +#define RADEON_VIPH_CONTROL 0x0c40 +#define RADEON_VIPH_EN (1 << 21) + +#define RADEON_GPIOPAD_MASK 0x0198 +#define RADEON_GPIOPAD_A 0x019c +#define RADEON_GPIOPAD_EN 0x01a0 +#define RADEON_GPIOPAD_Y 0x01a4 +#define RADEON_MDGPIO_MASK 0x01a8 +#define RADEON_MDGPIO_A 0x01ac +#define RADEON_MDGPIO_EN 0x01b0 +#define RADEON_MDGPIO_Y 0x01b4 + +#define RV370_BUS_CNTL 0x004c + +#define R600_CG_SPLL_FUNC_CNTL 0x600 +#define R600_CG_SPLL_STATUS 0x60c #define R600_ROM_CNTL 0x1600 #define R600_BUS_CNTL 0x5420 + #define R600_BIOS_ROM_DIS (1 << 1) #define R600_SCK_OVERWRITE (1 << 1) +#define R600_SPLL_CHG_STATUS (1 << 1) +#define R600_SPLL_BYPASS_EN (1 << 3) #define DVGA_CONTROL_MODE_ENABLE (1 << 0) #define DVGA_CONTROL_TIMING_SELECT (1 << 8) #define VGA_VSTATUS_CNTL_MASK (3 << 16) + /* SET_*_REG offsets + ends */ enum { SET_CONFIG_REG_offset = 0x00008000, diff --git a/src/add-ons/accelerants/radeon_hd/accelerant.cpp b/src/add-ons/accelerants/radeon_hd/accelerant.cpp index 93e5cf1241..db0be6034c 100644 --- a/src/add-ons/accelerants/radeon_hd/accelerant.cpp +++ b/src/add-ons/accelerants/radeon_hd/accelerant.cpp @@ -41,6 +41,7 @@ struct accelerant_info *gInfo; display_info *gDisplay[MAX_DISPLAY]; +void *gAtomBIOS; class AreaCloner { @@ -162,15 +163,21 @@ init_common(int device, bool isClone) gInfo->shared_info->rom_area); status = romCloner.InitCheck(); if (status < B_OK) { - //free(gInfo); + free(gInfo); TRACE("%s, failed to create rom area\n", __func__); - //return status; + return status; } sharedCloner.Keep(); regsCloner.Keep(); romCloner.Keep(); + gAtomBIOS = (void*)malloc(gInfo->shared_info->rom_size); + + if (gAtomBIOS == NULL) { + TRACE("%s, failed to malloc AtomBIOS pointer of holding\n", __func__); + } + // Define Radeon PLL default ranges gInfo->shared_info->pll_info.reference_frequency = RHD_PLL_REFERENCE_DEFAULT; @@ -199,6 +206,8 @@ uninit_common(void) free(gInfo); } + free(gAtomBIOS); + for (uint32 id = 0; id < MAX_DISPLAY; id++) { if (gDisplay[id] != NULL) { free(gDisplay[id]->regs); @@ -208,52 +217,6 @@ uninit_common(void) } -status_t -radeon_init_bios() -{ - radeon_shared_info &info = *gInfo->shared_info; - - uint32 bus_cntl = Read32(OUT, R600_BUS_CNTL); - uint32 d1vga_control = Read32(OUT, D1VGA_CONTROL); - uint32 d2vga_control = Read32(OUT, D2VGA_CONTROL); - uint32 vga_render_control = Read32(OUT, VGA_RENDER_CONTROL); - uint32 rom_cntl = Read32(OUT, R600_ROM_CNTL); - - // Enable rom access - Write32(OUT, R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); - /* Disable VGA mode */ - Write32(OUT, D1VGA_CONTROL, (d1vga_control - & ~(DVGA_CONTROL_MODE_ENABLE - | DVGA_CONTROL_TIMING_SELECT))); - Write32(OUT, D2VGA_CONTROL, (d2vga_control - & ~(DVGA_CONTROL_MODE_ENABLE - | DVGA_CONTROL_TIMING_SELECT))); - Write32(OUT, VGA_RENDER_CONTROL, (vga_render_control - & ~VGA_VSTATUS_CNTL_MASK)); - Write32(OUT, R600_ROM_CNTL, rom_cntl | R600_SCK_OVERWRITE); - - void* atomBIOS = (void*)malloc(info.rom_size); - if (atomBIOS == NULL) - return B_NO_MEMORY; - - snooze(2); - - memcpy(atomBIOS, gInfo->rom, info.rom_size); - - /* restore regs */ - Write32(OUT, R600_BUS_CNTL, bus_cntl); - Write32(OUT, D1VGA_CONTROL, d1vga_control); - Write32(OUT, D2VGA_CONTROL, d2vga_control); - Write32(OUT, VGA_RENDER_CONTROL, vga_render_control); - Write32(OUT, R600_ROM_CNTL, rom_cntl); - - // Init AtomBIOS - bios_init(atomBIOS); - - return B_OK; -} - - // #pragma mark - public accelerant functions @@ -272,7 +235,7 @@ radeon_init_accelerant(int device) init_lock(&info.accelerant_lock, "radeon hd accelerant"); init_lock(&info.engine_lock, "radeon hd engine"); - radeon_init_bios(); + radeon_init_bios(gAtomBIOS); status = detect_displays(); //if (status != B_OK) diff --git a/src/add-ons/accelerants/radeon_hd/accelerant.h b/src/add-ons/accelerants/radeon_hd/accelerant.h index 282868b668..0c8ffaf25e 100644 --- a/src/add-ons/accelerants/radeon_hd/accelerant.h +++ b/src/add-ons/accelerants/radeon_hd/accelerant.h @@ -116,7 +116,8 @@ typedef struct { extern accelerant_info *gInfo; -extern atom_context *gAtomBIOS; +extern void *gAtomBIOS; +extern atom_context *gAtomContext; extern display_info *gDisplay[MAX_DISPLAY]; diff --git a/src/add-ons/accelerants/radeon_hd/bios.cpp b/src/add-ons/accelerants/radeon_hd/bios.cpp index 6118792c5d..591fd10498 100644 --- a/src/add-ons/accelerants/radeon_hd/bios.cpp +++ b/src/add-ons/accelerants/radeon_hd/bios.cpp @@ -25,18 +25,218 @@ #endif -atom_context *gAtomBIOS; +atom_context *gAtomContext; status_t -bios_init(void* bios) +bios_read_enabled(void* bios, size_t size) { - if (gInfo->rom == NULL) { - // just incase, this prevents a crash - TRACE("%s: called even though VGA rom hasn't been mapped!\n", - __func__); - return B_ERROR; + status_t result = B_ERROR; + if (gInfo->rom[0] == 0x55 && gInfo->rom[1] == 0xaa) { + TRACE("%s: found AtomBIOS signature!\n", __func__); + bios = gInfo->rom; + result = B_OK; + } else + TRACE("%s: didn't find valid AtomBIOS\n", __func__); + + return result; +} + + +status_t +bios_read_disabled_northern(void* bios, size_t size) +{ + uint32 bus_cntl = Read32(OUT, R600_BUS_CNTL); + uint32 d1vga_control = Read32(OUT, D1VGA_CONTROL); + uint32 d2vga_control = Read32(OUT, D2VGA_CONTROL); + uint32 vga_render_control = Read32(OUT, VGA_RENDER_CONTROL); + uint32 rom_cntl = Read32(OUT, R600_ROM_CNTL); + + // Enable rom access + Write32(OUT, R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); + // Disable VGA mode + Write32(OUT, D1VGA_CONTROL, (d1vga_control + & ~(DVGA_CONTROL_MODE_ENABLE + | DVGA_CONTROL_TIMING_SELECT))); + Write32(OUT, D2VGA_CONTROL, (d2vga_control + & ~(DVGA_CONTROL_MODE_ENABLE + | DVGA_CONTROL_TIMING_SELECT))); + Write32(OUT, VGA_RENDER_CONTROL, (vga_render_control + & ~VGA_VSTATUS_CNTL_MASK)); + Write32(OUT, R600_ROM_CNTL, rom_cntl | R600_SCK_OVERWRITE); + + snooze(2); + + status_t result = B_ERROR; + if (gInfo->rom[0] == 0x55 && gInfo->rom[1] == 0xaa) { + TRACE("%s: found AtomBIOS signature!\n", __func__); + memcpy(&bios, gInfo->rom, size); + // grab it while we can + result = B_OK; + } else + TRACE("%s: didn't find valid AtomBIOS\n", __func__); + + // restore regs + Write32(OUT, R600_BUS_CNTL, bus_cntl); + Write32(OUT, D1VGA_CONTROL, d1vga_control); + Write32(OUT, D2VGA_CONTROL, d2vga_control); + Write32(OUT, VGA_RENDER_CONTROL, vga_render_control); + Write32(OUT, R600_ROM_CNTL, rom_cntl); + + return result; +} + + +status_t +bios_read_disabled_avivo(void* bios, size_t size) +{ + uint32 seprom_cntl1 = Read32(OUT, RADEON_SEPROM_CNTL1); + uint32 viph_control = Read32(OUT, RADEON_VIPH_CONTROL); + uint32 bus_cntl = Read32(OUT, RV370_BUS_CNTL); + uint32 d1vga_control = Read32(OUT, D1VGA_CONTROL); + uint32 d2vga_control = Read32(OUT, D2VGA_CONTROL); + uint32 vga_render_control = Read32(OUT, VGA_RENDER_CONTROL); + uint32 gpiopad_a = Read32(OUT, RADEON_GPIOPAD_A); + uint32 gpiopad_en = Read32(OUT, RADEON_GPIOPAD_EN); + uint32 gpiopad_mask = Read32(OUT, RADEON_GPIOPAD_MASK); + + Write32(OUT, RADEON_SEPROM_CNTL1, ((seprom_cntl1 & + ~RADEON_SCK_PRESCALE_MASK) | (0xc << RADEON_SCK_PRESCALE_SHIFT))); + Write32(OUT, RADEON_GPIOPAD_A, 0); + Write32(OUT, RADEON_GPIOPAD_EN, 0); + Write32(OUT, RADEON_GPIOPAD_MASK, 0); + + // Disable VIP + Write32(OUT, RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); + // Disable VGA mode + Write32(OUT, D1VGA_CONTROL, (d1vga_control + & ~(DVGA_CONTROL_MODE_ENABLE + | DVGA_CONTROL_TIMING_SELECT))); + Write32(OUT, D2VGA_CONTROL, (d2vga_control + & ~(DVGA_CONTROL_MODE_ENABLE + | DVGA_CONTROL_TIMING_SELECT))); + Write32(OUT, VGA_RENDER_CONTROL, (vga_render_control + & ~VGA_VSTATUS_CNTL_MASK)); + + snooze(2); + + status_t result = B_ERROR; + if (gInfo->rom[0] == 0x55 && gInfo->rom[1] == 0xaa) { + TRACE("%s: found AtomBIOS signature!\n", __func__); + memcpy(&bios, gInfo->rom, size); + // grab it while we can + result = B_OK; + } else + TRACE("%s: didn't find valid AtomBIOS\n", __func__); + + /* restore regs */ + Write32(OUT, RADEON_SEPROM_CNTL1, seprom_cntl1); + Write32(OUT, RADEON_VIPH_CONTROL, viph_control); + Write32(OUT, RV370_BUS_CNTL, bus_cntl); + Write32(OUT, D1VGA_CONTROL, d1vga_control); + Write32(OUT, D2VGA_CONTROL, d2vga_control); + Write32(OUT, VGA_RENDER_CONTROL, vga_render_control); + Write32(OUT, RADEON_GPIOPAD_A, gpiopad_a); + Write32(OUT, RADEON_GPIOPAD_EN, gpiopad_en); + Write32(OUT, RADEON_GPIOPAD_MASK, gpiopad_mask); + + + return result; +} + + +status_t +bios_read_disabled_r700(void* bios, size_t size) +{ + uint32 viph_control = Read32(OUT, RADEON_VIPH_CONTROL); + uint32 bus_cntl = Read32(OUT, R600_BUS_CNTL); + uint32 d1vga_control = Read32(OUT, D1VGA_CONTROL); + uint32 d2vga_control = Read32(OUT, D2VGA_CONTROL); + uint32 vga_render_control = Read32(OUT, VGA_RENDER_CONTROL); + uint32 rom_cntl = Read32(OUT, R600_ROM_CNTL); + + // Disable VIP + Write32(OUT, RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); + // Enable rom access + Write32(OUT, R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS)); + // Disable VGA mode + Write32(OUT, D1VGA_CONTROL, (d1vga_control + & ~(DVGA_CONTROL_MODE_ENABLE + | DVGA_CONTROL_TIMING_SELECT))); + Write32(OUT, D2VGA_CONTROL, (d2vga_control + & ~(DVGA_CONTROL_MODE_ENABLE + | DVGA_CONTROL_TIMING_SELECT))); + Write32(OUT, VGA_RENDER_CONTROL, (vga_render_control + & ~VGA_VSTATUS_CNTL_MASK)); + + uint32 cg_spll_func_cntl = 0; + radeon_shared_info &info = *gInfo->shared_info; + if (info.device_chipset == (RADEON_R700 | 0x30)) { + cg_spll_func_cntl = Read32(OUT, R600_CG_SPLL_FUNC_CNTL); + + // Enable bypass mode + Write32(OUT, R600_CG_SPLL_FUNC_CNTL, cg_spll_func_cntl + | R600_SPLL_BYPASS_EN); + + // wait for SPLL_CHG_STATUS to change to 1 + uint32 cg_spll_status = 0; + while (!(cg_spll_status & R600_SPLL_CHG_STATUS)) + cg_spll_status = Read32(OUT, R600_CG_SPLL_STATUS); + + Write32(OUT, R600_ROM_CNTL, (rom_cntl & ~R600_SCK_OVERWRITE)); + } else + Write32(OUT, R600_ROM_CNTL, rom_cntl | R600_SCK_OVERWRITE); + + snooze(2); + + status_t result = B_ERROR; + if (gInfo->rom[0] == 0x55 && gInfo->rom[1] == 0xaa) { + TRACE("%s: found AtomBIOS signature!\n", __func__); + memcpy(&bios, gInfo->rom, size); + // grab it while we can + result = B_OK; + } else + TRACE("%s: didn't find valid AtomBIOS\n", __func__); + + // restore regs + if (info.device_chipset == (RADEON_R700 | 0x30)) { + Write32(OUT, R600_CG_SPLL_FUNC_CNTL, cg_spll_func_cntl); + + // wait for SPLL_CHG_STATUS to change to 1 + uint32 cg_spll_status = 0; + while (!(cg_spll_status & R600_SPLL_CHG_STATUS)) + cg_spll_status = Read32(OUT, R600_CG_SPLL_STATUS); } + Write32(OUT, RADEON_VIPH_CONTROL, viph_control); + Write32(OUT, R600_BUS_CNTL, bus_cntl); + Write32(OUT, D1VGA_CONTROL, d1vga_control); + Write32(OUT, D2VGA_CONTROL, d2vga_control); + Write32(OUT, VGA_RENDER_CONTROL, vga_render_control); + Write32(OUT, R600_ROM_CNTL, rom_cntl); + + return result; +} + + +status_t +radeon_init_bios(void* bios) +{ + radeon_shared_info &info = *gInfo->shared_info; + + status_t bios_status; + if (bios_read_enabled(bios, info.rom_size) != B_OK) { + if (info.device_chipset > RADEON_R800) // TODO : >= BARTS + bios_status = bios_read_disabled_northern(bios, info.rom_size); + else if (info.device_chipset >= (RADEON_R700 | 0x70)) + bios_status = bios_read_disabled_r700(bios, info.rom_size); + else if (info.device_chipset >= RADEON_R600) + bios_status = bios_read_disabled_avivo(bios, info.rom_size); + else + bios_status = B_ERROR; + } + + if (bios_status != B_OK) + return bios_status; struct card_info *atom_card_info = (card_info*)malloc(sizeof(card_info)); @@ -61,10 +261,10 @@ bios_init(void* bios) atom_card_info->pll_read = _read32; atom_card_info->pll_write = _write32; - // Point AtomBIOS parser to card bios and malloc gAtomBIOS - gAtomBIOS = atom_parse(atom_card_info, bios); + // Point AtomBIOS parser to card bios and malloc gAtomContext + gAtomContext = atom_parse(atom_card_info, bios); - if (gAtomBIOS == NULL) { + if (gAtomContext == NULL) { TRACE("%s: couldn't parse system AtomBIOS\n", __func__); return B_ERROR; } diff --git a/src/add-ons/accelerants/radeon_hd/bios.h b/src/add-ons/accelerants/radeon_hd/bios.h index 97faed79cb..e29d462eaf 100644 --- a/src/add-ons/accelerants/radeon_hd/bios.h +++ b/src/add-ons/accelerants/radeon_hd/bios.h @@ -14,7 +14,7 @@ #include "atom.h" -status_t bios_init(void* bios); +status_t radeon_init_bios(void* bios); #endif /* RADEON_HD_BIOS_H */