diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 107a081..0160a3b 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -71,6 +71,7 @@ enum radeon_combios_table_offset /* relative offset tables */ COMBIOS_ASIC_INIT_3_TABLE, /* offset from misc info */ COMBIOS_ASIC_INIT_4_TABLE, /* offset from misc info */ + COMBIOS_DETECTED_MEM_TABLE, /* offset from misc info */ COMBIOS_ASIC_INIT_5_TABLE, /* offset from misc info */ COMBIOS_RAM_RESET_TABLE, /* offset from mem config */ COMBIOS_POWERPLAY_INFO_TABLE, /* offset from mobile info */ @@ -305,6 +306,17 @@ static uint16_t combios_get_table_offset(struct drm_device *dev, enum radeon_com } } break; + case COMBIOS_DETECTED_MEM_TABLE: /* offset from misc info */ + check_offset = combios_get_table_offset(dev, COMBIOS_MISC_INFO_TABLE); + if (check_offset) { + rev = radeon_bios8(dev_priv, check_offset); + if (rev > 0) { + check_offset = radeon_bios16(dev_priv, check_offset + 0x7); + if (check_offset) + offset = check_offset; + } + } + break; case COMBIOS_ASIC_INIT_5_TABLE: /* offset from misc info */ check_offset = combios_get_table_offset(dev, COMBIOS_MISC_INFO_TABLE); if (check_offset) { @@ -1308,6 +1320,97 @@ static void combios_parse_ram_reset_table(struct drm_device *dev, uint16_t offse } } +static uint32_t combios_detect_ram(struct drm_device *dev, int ram, int mem_addr_mapping) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + uint32_t mem_cntl; + uint32_t mem_size; + uint32_t addr = 0; + + mem_cntl = RADEON_READ(RADEON_MEM_CNTL); + if (mem_cntl & RV100_HALF_MODE) + ram /= 2; + mem_size = ram; + mem_cntl &= ~(0xff << 8); + mem_cntl |= (mem_addr_mapping & 0xff) << 8; + RADEON_WRITE(RADEON_MEM_CNTL, mem_cntl); + RADEON_READ(RADEON_MEM_CNTL); + + /* sdram reset ? */ + + /* something like this???? */ + while (ram--) { + addr = ram * 1024 * 1024; + /* write to each page */ + RADEON_WRITE(RADEON_MM_INDEX, (addr) | RADEON_MM_APER); + RADEON_WRITE(RADEON_MM_DATA, 0xdeadbeef); + /* read back and verify */ + RADEON_WRITE(RADEON_MM_INDEX, (addr) | RADEON_MM_APER); + if (RADEON_READ(RADEON_MM_DATA) != 0xdeadbeef) + return 0; + } + + return mem_size; +} + +static void combios_write_ram_size(struct drm_device *dev) +{ + struct drm_radeon_private *dev_priv = dev->dev_private; + uint8_t rev; + uint16_t offset; + uint32_t mem_size = 0; + uint32_t mem_cntl = 0; + + /* should do something smarter here I guess... */ + if (dev_priv->flags & RADEON_IS_IGP) + return; + + /* first check detected mem table */ + offset = combios_get_table_offset(dev, COMBIOS_DETECTED_MEM_TABLE); + if (offset) { + rev = radeon_bios8(dev_priv, offset); + if (rev < 3) { + mem_cntl = radeon_bios32(dev_priv, offset + 1); + mem_size = radeon_bios16(dev_priv, offset + 5); + if (((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_R200) && + ((dev->pdev->device != 0x515e) && (dev->pdev->device != 0x5969))) + RADEON_WRITE(RADEON_MEM_CNTL, mem_cntl); + } + } + + if (!mem_size) { + offset = combios_get_table_offset(dev, COMBIOS_MEM_CONFIG_TABLE); + if (offset) { + rev = radeon_bios8(dev_priv, offset - 1); + if (rev < 1) { + if (((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_R200) && + ((dev->pdev->device != 0x515e) && (dev->pdev->device != 0x5969))) { + int ram = 0; + int mem_addr_mapping = 0; + + while (radeon_bios8(dev_priv, offset)) { + ram = radeon_bios8(dev_priv, offset); + mem_addr_mapping = radeon_bios8(dev_priv, offset + 1); + if (mem_addr_mapping != 0x25) + ram *= 2; + mem_size = combios_detect_ram(dev, ram, mem_addr_mapping); + if (mem_size) + break; + offset +=2; + } + } else + mem_size = radeon_bios8(dev_priv, offset); + } else { + mem_size = radeon_bios8(dev_priv, offset); + mem_size *= 2; /* convert to MB */ + } + } + } + + mem_size *= (1024 * 1024); /* convert to bytes */ + RADEON_WRITE(RADEON_CONFIG_MEMSIZE, mem_size); +} + void radeon_combios_dyn_clk_setup(struct drm_device *dev, int enable) { uint16_t dyn_clk_info = combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE); @@ -1318,6 +1421,7 @@ void radeon_combios_dyn_clk_setup(struct drm_device *dev, int enable) void radeon_combios_asic_init(struct drm_device *dev) { + struct drm_radeon_private *dev_priv = dev->dev_private; uint16_t table; /* ASIC INIT 1 */ @@ -1335,31 +1439,31 @@ void radeon_combios_asic_init(struct drm_device *dev) if (table) combios_parse_mmio_table(dev, table); - /* ASIC INIT 4 */ - table = combios_get_table_offset(dev, COMBIOS_ASIC_INIT_4_TABLE); - if (table) - combios_parse_mmio_table(dev, table); + if (!(dev_priv->flags & RADEON_IS_IGP)) { + /* ASIC INIT 4 */ + table = combios_get_table_offset(dev, COMBIOS_ASIC_INIT_4_TABLE); + if (table) + combios_parse_mmio_table(dev, table); - /* RAM RESET */ - table = combios_get_table_offset(dev, COMBIOS_RAM_RESET_TABLE); - if (table) - combios_parse_ram_reset_table(dev, table); + /* RAM RESET */ + table = combios_get_table_offset(dev, COMBIOS_RAM_RESET_TABLE); + if (table) + combios_parse_ram_reset_table(dev, table); - /* ASIC INIT 3 */ - table = combios_get_table_offset(dev, COMBIOS_ASIC_INIT_3_TABLE); - if (table) - combios_parse_mmio_table(dev, table); + /* ASIC INIT 3 */ + table = combios_get_table_offset(dev, COMBIOS_ASIC_INIT_3_TABLE); + if (table) + combios_parse_mmio_table(dev, table); + + /* write CONFIG_MEMSIZE */ + combios_write_ram_size(dev); + } /* DYN CLK 1 */ table = combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE); if (table) combios_parse_pll_table(dev, table); - /* ASIC INIT 5 */ - table = combios_get_table_offset(dev, COMBIOS_ASIC_INIT_5_TABLE); - if (table) - combios_parse_mmio_table(dev, table); - } void radeon_combios_initialize_bios_scratch_regs(struct drm_device *dev) diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h index 0fa8a06..1df6e4c 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.h +++ b/drivers/gpu/drm/radeon/radeon_drv.h @@ -627,6 +627,7 @@ int radeon_resume(struct drm_device *dev); * for Radeon kernel driver. */ #define RADEON_MM_INDEX 0x0000 +# define RADEON_MM_APER (1 << 31) #define RADEON_MM_DATA 0x0004 #include "radeon_reg.h"