Setup MTRRs for frame buffer and aperture manually on Savage3D and
Savage4-based cards. Automatic setup in drm_initmap doesn't work due to the weird alignment and size of the aperture.main
parent
6c8a3194f4
commit
ffc51f1f32
|
@ -76,6 +76,7 @@ static struct drm_driver driver = {
|
||||||
.dev_priv_size = sizeof(drm_savage_buf_priv_t),
|
.dev_priv_size = sizeof(drm_savage_buf_priv_t),
|
||||||
.preinit = savage_preinit,
|
.preinit = savage_preinit,
|
||||||
.postinit = postinit,
|
.postinit = postinit,
|
||||||
|
.postcleanup = savage_postcleanup,
|
||||||
.reclaim_buffers = savage_reclaim_buffers,
|
.reclaim_buffers = savage_reclaim_buffers,
|
||||||
.get_map_ofs = drm_core_get_map_ofs,
|
.get_map_ofs = drm_core_get_map_ofs,
|
||||||
.get_reg_ofs = drm_core_get_reg_ofs,
|
.get_reg_ofs = drm_core_get_reg_ofs,
|
||||||
|
|
|
@ -283,10 +283,19 @@ void savage_freelist_put(drm_device_t *dev, drm_buf_t *buf)
|
||||||
entry->next = next;
|
entry->next = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initalize permanent mappings. On Savage4 and SavageIX the alignment
|
||||||
|
* and size of the aperture is not suitable for automatic MTRR setup
|
||||||
|
* in drm_initmap. Therefore we do it manually before the maps are
|
||||||
|
* initialized. We also need to take care of deleting the MTRRs in
|
||||||
|
* postcleanup.
|
||||||
|
*
|
||||||
|
* FIXME: this is linux-specific
|
||||||
|
*/
|
||||||
int savage_preinit(drm_device_t *dev, unsigned long chipset)
|
int savage_preinit(drm_device_t *dev, unsigned long chipset)
|
||||||
{
|
{
|
||||||
drm_savage_private_t *dev_priv;
|
drm_savage_private_t *dev_priv;
|
||||||
unsigned int mmio_base, fb_base, fb_size, aperture_base;
|
unsigned long mmio_base, fb_base, fb_size, aperture_base;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
dev_priv = drm_alloc(sizeof(drm_savage_private_t), DRM_MEM_DRIVER);
|
dev_priv = drm_alloc(sizeof(drm_savage_private_t), DRM_MEM_DRIVER);
|
||||||
|
@ -297,21 +306,61 @@ int savage_preinit(drm_device_t *dev, unsigned long chipset)
|
||||||
dev->dev_private = (void *)dev_priv;
|
dev->dev_private = (void *)dev_priv;
|
||||||
dev_priv->chipset = (enum savage_family)chipset;
|
dev_priv->chipset = (enum savage_family)chipset;
|
||||||
|
|
||||||
|
dev_priv->mtrr[0].handle = -1;
|
||||||
|
dev_priv->mtrr[1].handle = -1;
|
||||||
|
dev_priv->mtrr[2].handle = -1;
|
||||||
if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
|
if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
|
||||||
fb_base = pci_resource_start(dev->pdev, 0);
|
fb_base = pci_resource_start(dev->pdev, 0);
|
||||||
fb_size = SAVAGE_FB_SIZE_S3;
|
fb_size = SAVAGE_FB_SIZE_S3;
|
||||||
mmio_base = fb_base + SAVAGE_FB_SIZE_S3;
|
mmio_base = fb_base + SAVAGE_FB_SIZE_S3;
|
||||||
aperture_base = fb_base + SAVAGE_APERTURE_OFFSET;
|
aperture_base = fb_base + SAVAGE_APERTURE_OFFSET;
|
||||||
|
/* this should always be true */
|
||||||
|
if (pci_resource_len(dev->pdev, 0) == 0x08000000) {
|
||||||
|
/* Don't make MMIO write-cobining! We need 3
|
||||||
|
* MTRRs. */
|
||||||
|
dev_priv->mtrr[0].base = fb_base;
|
||||||
|
dev_priv->mtrr[0].size = 0x01000000;
|
||||||
|
dev_priv->mtrr[0].handle = mtrr_add(
|
||||||
|
dev_priv->mtrr[0].base, dev_priv->mtrr[0].size,
|
||||||
|
MTRR_TYPE_WRCOMB, 1);
|
||||||
|
dev_priv->mtrr[1].base = fb_base+0x02000000;
|
||||||
|
dev_priv->mtrr[1].size = 0x02000000;
|
||||||
|
dev_priv->mtrr[1].handle = mtrr_add(
|
||||||
|
dev_priv->mtrr[1].base, dev_priv->mtrr[1].size,
|
||||||
|
MTRR_TYPE_WRCOMB, 1);
|
||||||
|
dev_priv->mtrr[2].base = fb_base+0x04000000;
|
||||||
|
dev_priv->mtrr[2].size = 0x04000000;
|
||||||
|
dev_priv->mtrr[2].handle = mtrr_add(
|
||||||
|
dev_priv->mtrr[2].base, dev_priv->mtrr[2].size,
|
||||||
|
MTRR_TYPE_WRCOMB, 1);
|
||||||
|
} else {
|
||||||
|
DRM_ERROR("strange pci_resource_len %08lx\n",
|
||||||
|
pci_resource_len(dev->pdev, 0));
|
||||||
|
}
|
||||||
} else if (chipset != S3_SUPERSAVAGE && chipset != S3_SAVAGE2000) {
|
} else if (chipset != S3_SUPERSAVAGE && chipset != S3_SAVAGE2000) {
|
||||||
mmio_base = pci_resource_start(dev->pdev, 0);
|
mmio_base = pci_resource_start(dev->pdev, 0);
|
||||||
fb_base = pci_resource_start(dev->pdev, 1);
|
fb_base = pci_resource_start(dev->pdev, 1);
|
||||||
fb_size = SAVAGE_FB_SIZE_S4;
|
fb_size = SAVAGE_FB_SIZE_S4;
|
||||||
aperture_base = fb_base + SAVAGE_APERTURE_OFFSET;
|
aperture_base = fb_base + SAVAGE_APERTURE_OFFSET;
|
||||||
|
/* this should always be true */
|
||||||
|
if (pci_resource_len(dev->pdev, 1) == 0x08000000) {
|
||||||
|
/* Can use one MTRR to cover both fb and
|
||||||
|
* aperture. */
|
||||||
|
dev_priv->mtrr[0].base = fb_base;
|
||||||
|
dev_priv->mtrr[0].size = 0x08000000;
|
||||||
|
dev_priv->mtrr[0].handle = mtrr_add(
|
||||||
|
dev_priv->mtrr[0].base, dev_priv->mtrr[0].size,
|
||||||
|
MTRR_TYPE_WRCOMB, 1);
|
||||||
|
} else {
|
||||||
|
DRM_ERROR("strange pci_resource_len %08lx\n",
|
||||||
|
pci_resource_len(dev->pdev, 1));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
mmio_base = pci_resource_start(dev->pdev, 0);
|
mmio_base = pci_resource_start(dev->pdev, 0);
|
||||||
fb_base = pci_resource_start(dev->pdev, 1);
|
fb_base = pci_resource_start(dev->pdev, 1);
|
||||||
fb_size = pci_resource_len(dev->pdev, 1);
|
fb_size = pci_resource_len(dev->pdev, 1);
|
||||||
aperture_base = pci_resource_start(dev->pdev, 2);
|
aperture_base = pci_resource_start(dev->pdev, 2);
|
||||||
|
/* Automatic MTRR setup will do the right thing. */
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = drm_initmap(dev, mmio_base, SAVAGE_MMIO_SIZE,
|
if ((ret = drm_initmap(dev, mmio_base, SAVAGE_MMIO_SIZE,
|
||||||
|
@ -335,6 +384,25 @@ int savage_preinit(drm_device_t *dev, unsigned long chipset)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Delete MTRRs and free device-private data.
|
||||||
|
*/
|
||||||
|
int savage_postcleanup(drm_device_t *dev)
|
||||||
|
{
|
||||||
|
drm_savage_private_t *dev_priv = dev->dev_private;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 3; ++i)
|
||||||
|
if (dev_priv->mtrr[i].handle >= 0)
|
||||||
|
mtrr_del(dev_priv->mtrr[i].handle,
|
||||||
|
dev_priv->mtrr[i].base,
|
||||||
|
dev_priv->mtrr[i].size);
|
||||||
|
|
||||||
|
drm_free(dev_priv, sizeof(drm_savage_private_t), DRM_MEM_DRIVER);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int savage_do_init_bci(drm_device_t *dev, drm_savage_init_t *init)
|
static int savage_do_init_bci(drm_device_t *dev, drm_savage_init_t *init)
|
||||||
{
|
{
|
||||||
drm_savage_private_t *dev_priv = dev->dev_private;
|
drm_savage_private_t *dev_priv = dev->dev_private;
|
||||||
|
|
|
@ -140,6 +140,11 @@ typedef struct drm_savage_private {
|
||||||
drm_local_map_t *agp_textures;
|
drm_local_map_t *agp_textures;
|
||||||
drm_local_map_t *cmd_dma;
|
drm_local_map_t *cmd_dma;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
int handle;
|
||||||
|
unsigned long base, size;
|
||||||
|
} mtrr[3];
|
||||||
|
|
||||||
/* BCI and status-related stuff */
|
/* BCI and status-related stuff */
|
||||||
volatile uint32_t *status_ptr, *bci_ptr;
|
volatile uint32_t *status_ptr, *bci_ptr;
|
||||||
uint32_t status_used_mask;
|
uint32_t status_used_mask;
|
||||||
|
@ -177,6 +182,7 @@ extern uint16_t savage_bci_emit_event(drm_savage_private_t *dev_priv,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
extern void savage_freelist_put(drm_device_t *dev, drm_buf_t *buf);
|
extern void savage_freelist_put(drm_device_t *dev, drm_buf_t *buf);
|
||||||
extern int savage_preinit(drm_device_t *dev, unsigned long chipset);
|
extern int savage_preinit(drm_device_t *dev, unsigned long chipset);
|
||||||
|
extern int savage_postcleanup(drm_device_t *dev);
|
||||||
extern int savage_do_cleanup_bci(drm_device_t *dev);
|
extern int savage_do_cleanup_bci(drm_device_t *dev);
|
||||||
extern void savage_reclaim_buffers(drm_device_t *dev, DRMFILE filp);
|
extern void savage_reclaim_buffers(drm_device_t *dev, DRMFILE filp);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue