* 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
This commit is contained in:
Alexander von Gluck IV 2011-08-03 03:02:57 +00:00
parent 1c1415732d
commit 1d5cfc649a
5 changed files with 250 additions and 61 deletions

View File

@ -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,

View File

@ -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)

View File

@ -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];

View File

@ -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;
}

View File

@ -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 */