From 2a0f8918fc34713ecaeb900ffb9afa61df4cb08e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sat, 11 Jul 2009 04:44:47 +1000 Subject: [PATCH] drm/radeon/kms: fix VRAM sizing like DDX does it. Doing this like the DDX seems like the most sure fire way to avoid having to reinvent it slowly and painfully. At the moment we keep getting things wrong with aper vs vram, so we know the DDX does it right. booted on PCI r100, PCIE rv370, IGP rs400. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100.c | 65 +++++++++++++++++++++++++- drivers/gpu/drm/radeon/r300.c | 4 +- drivers/gpu/drm/radeon/r520.c | 4 +- drivers/gpu/drm/radeon/radeon.h | 2 + drivers/gpu/drm/radeon/radeon_device.c | 7 +-- drivers/gpu/drm/radeon/rs400.c | 14 +----- drivers/gpu/drm/radeon/rv515.c | 6 +-- 7 files changed, 71 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 154648a2c027..97c9229b9299 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -1360,9 +1360,50 @@ static void r100_vram_get_type(struct radeon_device *rdev) } } -void r100_vram_info(struct radeon_device *rdev) +static u32 r100_get_accessible_vram(struct radeon_device *rdev) { - r100_vram_get_type(rdev); + u32 aper_size; + u8 byte; + + aper_size = RREG32(RADEON_CONFIG_APER_SIZE); + + /* Set HDP_APER_CNTL only on cards that are known not to be broken, + * that is has the 2nd generation multifunction PCI interface + */ + if (rdev->family == CHIP_RV280 || + rdev->family >= CHIP_RV350) { + WREG32_P(RADEON_HOST_PATH_CNTL, RADEON_HDP_APER_CNTL, + ~RADEON_HDP_APER_CNTL); + DRM_INFO("Generation 2 PCI interface, using max accessible memory\n"); + return aper_size * 2; + } + + /* Older cards have all sorts of funny issues to deal with. First + * check if it's a multifunction card by reading the PCI config + * header type... Limit those to one aperture size + */ + pci_read_config_byte(rdev->pdev, 0xe, &byte); + if (byte & 0x80) { + DRM_INFO("Generation 1 PCI interface in multifunction mode\n"); + DRM_INFO("Limiting VRAM to one aperture\n"); + return aper_size; + } + + /* Single function older card. We read HDP_APER_CNTL to see how the BIOS + * have set it up. We don't write this as it's broken on some ASICs but + * we expect the BIOS to have done the right thing (might be too optimistic...) + */ + if (RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL) + return aper_size * 2; + return aper_size; +} + +void r100_vram_init_sizes(struct radeon_device *rdev) +{ + u64 config_aper_size; + u32 accessible; + + config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE); if (rdev->flags & RADEON_IS_IGP) { uint32_t tom; @@ -1383,10 +1424,30 @@ void r100_vram_info(struct radeon_device *rdev) } /* let driver place VRAM */ rdev->mc.vram_location = 0xFFFFFFFFUL; + /* Fix for RN50, M6, M7 with 8/16/32(??) MBs of VRAM - + * Novell bug 204882 + along with lots of ubuntu ones */ + if (config_aper_size > rdev->mc.vram_size) + rdev->mc.vram_size = config_aper_size; } + /* work out accessible VRAM */ + accessible = r100_get_accessible_vram(rdev); + rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + + if (accessible > rdev->mc.aper_size) + accessible = rdev->mc.aper_size; + + if (rdev->mc.vram_size > rdev->mc.aper_size) + rdev->mc.vram_size = rdev->mc.aper_size; +} + +void r100_vram_info(struct radeon_device *rdev) +{ + r100_vram_get_type(rdev); + + r100_vram_init_sizes(rdev); } diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 6435d659cbd1..0e0e094da503 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -585,10 +585,8 @@ void r300_vram_info(struct radeon_device *rdev) } else { rdev->mc.vram_width = 64; } - rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE); - rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); - rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + r100_vram_init_sizes(rdev); } diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c index 570a244bd88b..b6bd3758db6b 100644 --- a/drivers/gpu/drm/radeon/r520.c +++ b/drivers/gpu/drm/radeon/r520.c @@ -227,8 +227,6 @@ static void r520_vram_get_type(struct radeon_device *rdev) void r520_vram_info(struct radeon_device *rdev) { r520_vram_get_type(rdev); - rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE); - rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); - rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + r100_vram_init_sizes(rdev); } diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 3060ce14071e..248e3341a984 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -541,6 +541,8 @@ union radeon_asic_config { struct r300_asic r300; }; +/* r100 */ +void r100_vram_init_sizes(struct radeon_device *rdev); /* * IOCTL. diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 27a5ac969953..cdef6eb01baf 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -561,12 +561,7 @@ int radeon_device_init(struct radeon_device *rdev, } /* Get vram informations */ radeon_vram_info(rdev); - /* Device is severly broken if aper size > vram size. - * for RN50/M6/M7 - Novell bug 204882 ? - */ - if (rdev->mc.vram_size < rdev->mc.aper_size) { - rdev->mc.vram_size = rdev->mc.aper_size; - } + /* Add an MTRR for the VRAM */ rdev->mc.vram_mtrr = mtrr_add(rdev->mc.aper_base, rdev->mc.aper_size, MTRR_TYPE_WRCOMB, 1); diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index a18d053065c0..daf24e85cba3 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -292,24 +292,12 @@ void rs400_gpu_init(struct radeon_device *rdev) */ void rs400_vram_info(struct radeon_device *rdev) { - uint32_t tom; - rs400_gart_adjust_size(rdev); /* DDR for all card after R300 & IGP */ rdev->mc.vram_is_ddr = true; rdev->mc.vram_width = 128; - /* read NB_TOM to get the amount of ram stolen for the GPU */ - tom = RREG32(RADEON_NB_TOM); - rdev->mc.vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16); - WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); - - /* RS480 IGPs don't seem to translate to main RAM, they - * just reserve and scan out of it. So setting VRAM location - * to say 0, will actually trash the OS. */ - rdev->mc.vram_location = (tom & 0xffff) << 16; - rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); - rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + r100_vram_init_sizes(rdev); } diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index d1384d3991ad..677929ed8ed3 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -395,10 +395,8 @@ static void rv515_vram_get_type(struct radeon_device *rdev) void rv515_vram_info(struct radeon_device *rdev) { rv515_vram_get_type(rdev); - rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE); - - rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); - rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); + + r100_vram_init_sizes(rdev); } -- 2.39.5