From 3ce0a23d2d253185df24e22e3d5f89800bb3dd1c Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Tue, 8 Sep 2009 10:10:24 +1000 Subject: drm/radeon/kms: add r600 KMS support This adds the r600 KMS + CS support to the Linux kernel. The r600 TTM support is quite basic and still needs more work esp around using interrupts, but the polled fencing should work okay for now. Also currently TTM is using memcpy to do VRAM moves, the code is here to use a 3D blit to do this, but isn't fully debugged yet. Authors: Alex Deucher Dave Airlie Jerome Glisse Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_device.c | 340 ++++++++++++++++++--------------- 1 file changed, 191 insertions(+), 149 deletions(-) (limited to 'drivers/gpu/drm/radeon/radeon_device.c') diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 7693f7c67bd3..f2469c511789 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -37,7 +37,7 @@ /* * Clear GPU surface registers. */ -static void radeon_surface_init(struct radeon_device *rdev) +void radeon_surface_init(struct radeon_device *rdev) { /* FIXME: check this out */ if (rdev->family < CHIP_R600) { @@ -56,7 +56,7 @@ static void radeon_surface_init(struct radeon_device *rdev) /* * GPU scratch registers helpers function. */ -static void radeon_scratch_init(struct radeon_device *rdev) +void radeon_scratch_init(struct radeon_device *rdev) { int i; @@ -156,16 +156,14 @@ int radeon_mc_setup(struct radeon_device *rdev) tmp = (tmp + rdev->mc.gtt_size - 1) & ~(rdev->mc.gtt_size - 1); rdev->mc.gtt_location = tmp; } - DRM_INFO("radeon: VRAM %uM\n", rdev->mc.real_vram_size >> 20); + DRM_INFO("radeon: VRAM %uM\n", (unsigned)(rdev->mc.mc_vram_size >> 20)); DRM_INFO("radeon: VRAM from 0x%08X to 0x%08X\n", - rdev->mc.vram_location, - rdev->mc.vram_location + rdev->mc.mc_vram_size - 1); - if (rdev->mc.real_vram_size != rdev->mc.mc_vram_size) - DRM_INFO("radeon: VRAM less than aperture workaround enabled\n"); - DRM_INFO("radeon: GTT %uM\n", rdev->mc.gtt_size >> 20); + (unsigned)rdev->mc.vram_location, + (unsigned)(rdev->mc.vram_location + rdev->mc.mc_vram_size - 1)); + DRM_INFO("radeon: GTT %uM\n", (unsigned)(rdev->mc.gtt_size >> 20)); DRM_INFO("radeon: GTT from 0x%08X to 0x%08X\n", - rdev->mc.gtt_location, - rdev->mc.gtt_location + rdev->mc.gtt_size - 1); + (unsigned)rdev->mc.gtt_location, + (unsigned)(rdev->mc.gtt_location + rdev->mc.gtt_size - 1)); return 0; } @@ -205,6 +203,31 @@ static bool radeon_card_posted(struct radeon_device *rdev) } +int radeon_dummy_page_init(struct radeon_device *rdev) +{ + rdev->dummy_page.page = alloc_page(GFP_DMA32 | GFP_KERNEL | __GFP_ZERO); + if (rdev->dummy_page.page == NULL) + return -ENOMEM; + rdev->dummy_page.addr = pci_map_page(rdev->pdev, rdev->dummy_page.page, + 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + if (!rdev->dummy_page.addr) { + __free_page(rdev->dummy_page.page); + rdev->dummy_page.page = NULL; + return -ENOMEM; + } + return 0; +} + +void radeon_dummy_page_fini(struct radeon_device *rdev) +{ + if (rdev->dummy_page.page == NULL) + return; + pci_unmap_page(rdev->pdev, rdev->dummy_page.addr, + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + __free_page(rdev->dummy_page.page); + rdev->dummy_page.page = NULL; +} + /* * Registers accessors functions. @@ -323,9 +346,15 @@ int radeon_asic_init(struct radeon_device *rdev) case CHIP_RV635: case CHIP_RV670: case CHIP_RS780: + case CHIP_RS880: + rdev->asic = &r600_asic; + break; case CHIP_RV770: case CHIP_RV730: case CHIP_RV710: + case CHIP_RV740: + rdev->asic = &rv770_asic; + break; default: /* FIXME: not supported yet */ return -EINVAL; @@ -448,7 +477,7 @@ int radeon_device_init(struct radeon_device *rdev, struct pci_dev *pdev, uint32_t flags) { - int r, ret; + int r, ret = 0; int dma_bits; DRM_INFO("radeon: Initializing kernel modesetting.\n"); @@ -487,10 +516,6 @@ int radeon_device_init(struct radeon_device *rdev, if (r) { return r; } - r = radeon_init(rdev); - if (r) { - return r; - } /* set DMA mask + need_dma32 flags. * PCIE - can handle 40-bits. @@ -521,111 +546,118 @@ int radeon_device_init(struct radeon_device *rdev, DRM_INFO("register mmio base: 0x%08X\n", (uint32_t)rdev->rmmio_base); DRM_INFO("register mmio size: %u\n", (unsigned)rdev->rmmio_size); - /* Setup errata flags */ - radeon_errata(rdev); - /* Initialize scratch registers */ - radeon_scratch_init(rdev); - /* Initialize surface registers */ - radeon_surface_init(rdev); - - /* TODO: disable VGA need to use VGA request */ - /* BIOS*/ - if (!radeon_get_bios(rdev)) { - if (ASIC_IS_AVIVO(rdev)) - return -EINVAL; - } - if (rdev->is_atom_bios) { - r = radeon_atombios_init(rdev); + rdev->new_init_path = false; + r = radeon_init(rdev); + if (r) { + return r; + } + if (!rdev->new_init_path) { + /* Setup errata flags */ + radeon_errata(rdev); + /* Initialize scratch registers */ + radeon_scratch_init(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); + + /* TODO: disable VGA need to use VGA request */ + /* BIOS*/ + if (!radeon_get_bios(rdev)) { + if (ASIC_IS_AVIVO(rdev)) + return -EINVAL; + } + if (rdev->is_atom_bios) { + r = radeon_atombios_init(rdev); + if (r) { + return r; + } + } else { + r = radeon_combios_init(rdev); + if (r) { + return r; + } + } + /* Reset gpu before posting otherwise ATOM will enter infinite loop */ + if (radeon_gpu_reset(rdev)) { + /* FIXME: what do we want to do here ? */ + } + /* check if cards are posted or not */ + if (!radeon_card_posted(rdev) && rdev->bios) { + DRM_INFO("GPU not posted. posting now...\n"); + if (rdev->is_atom_bios) { + atom_asic_init(rdev->mode_info.atom_context); + } else { + radeon_combios_asic_init(rdev->ddev); + } + } + /* Initialize clocks */ + r = radeon_clocks_init(rdev); if (r) { return r; } - } else { - r = radeon_combios_init(rdev); + /* Get vram informations */ + radeon_vram_info(rdev); + + /* Add an MTRR for the VRAM */ + rdev->mc.vram_mtrr = mtrr_add(rdev->mc.aper_base, rdev->mc.aper_size, + MTRR_TYPE_WRCOMB, 1); + DRM_INFO("Detected VRAM RAM=%uM, BAR=%uM\n", + (unsigned)(rdev->mc.mc_vram_size >> 20), + (unsigned)(rdev->mc.aper_size >> 20)); + DRM_INFO("RAM width %dbits %cDR\n", + rdev->mc.vram_width, rdev->mc.vram_is_ddr ? 'D' : 'S'); + /* Initialize memory controller (also test AGP) */ + r = radeon_mc_init(rdev); if (r) { return r; } - } - /* Reset gpu before posting otherwise ATOM will enter infinite loop */ - if (radeon_gpu_reset(rdev)) { - /* FIXME: what do we want to do here ? */ - } - /* check if cards are posted or not */ - if (!radeon_card_posted(rdev) && rdev->bios) { - DRM_INFO("GPU not posted. posting now...\n"); - if (rdev->is_atom_bios) { - atom_asic_init(rdev->mode_info.atom_context); - } else { - radeon_combios_asic_init(rdev->ddev); - } - } - /* Initialize clocks */ - r = radeon_clocks_init(rdev); - if (r) { - return r; - } - /* Get vram informations */ - radeon_vram_info(rdev); - - /* Add an MTRR for the VRAM */ - rdev->mc.vram_mtrr = mtrr_add(rdev->mc.aper_base, rdev->mc.aper_size, - MTRR_TYPE_WRCOMB, 1); - DRM_INFO("Detected VRAM RAM=%uM, BAR=%uM\n", - rdev->mc.real_vram_size >> 20, - (unsigned)rdev->mc.aper_size >> 20); - DRM_INFO("RAM width %dbits %cDR\n", - rdev->mc.vram_width, rdev->mc.vram_is_ddr ? 'D' : 'S'); - /* Initialize memory controller (also test AGP) */ - r = radeon_mc_init(rdev); - if (r) { - return r; - } - /* Fence driver */ - r = radeon_fence_driver_init(rdev); - if (r) { - return r; - } - r = radeon_irq_kms_init(rdev); - if (r) { - return r; - } - /* Memory manager */ - r = radeon_object_init(rdev); - if (r) { - return r; - } - /* Initialize GART (initialize after TTM so we can allocate - * memory through TTM but finalize after TTM) */ - r = radeon_gart_enable(rdev); - if (!r) { - r = radeon_gem_init(rdev); - } - - /* 1M ring buffer */ - if (!r) { - r = radeon_cp_init(rdev, 1024 * 1024); - } - if (!r) { - r = radeon_wb_init(rdev); + /* Fence driver */ + r = radeon_fence_driver_init(rdev); if (r) { - DRM_ERROR("radeon: failled initializing WB (%d).\n", r); return r; } - } - if (!r) { - r = radeon_ib_pool_init(rdev); + r = radeon_irq_kms_init(rdev); if (r) { - DRM_ERROR("radeon: failled initializing IB pool (%d).\n", r); return r; } - } - if (!r) { - r = radeon_ib_test(rdev); + /* Memory manager */ + r = radeon_object_init(rdev); if (r) { - DRM_ERROR("radeon: failled testing IB (%d).\n", r); return r; } + /* Initialize GART (initialize after TTM so we can allocate + * memory through TTM but finalize after TTM) */ + r = radeon_gart_enable(rdev); + if (!r) { + r = radeon_gem_init(rdev); + } + + /* 1M ring buffer */ + if (!r) { + r = radeon_cp_init(rdev, 1024 * 1024); + } + if (!r) { + r = radeon_wb_init(rdev); + if (r) { + DRM_ERROR("radeon: failled initializing WB (%d).\n", r); + return r; + } + } + if (!r) { + r = radeon_ib_pool_init(rdev); + if (r) { + DRM_ERROR("radeon: failled initializing IB pool (%d).\n", r); + return r; + } + } + if (!r) { + r = radeon_ib_test(rdev); + if (r) { + DRM_ERROR("radeon: failled testing IB (%d).\n", r); + return r; + } + } + ret = r; } - ret = r; r = radeon_modeset_init(rdev); if (r) { return r; @@ -651,26 +683,29 @@ void radeon_device_fini(struct radeon_device *rdev) rdev->shutdown = true; /* Order matter so becarefull if you rearrange anythings */ radeon_modeset_fini(rdev); - radeon_ib_pool_fini(rdev); - radeon_cp_fini(rdev); - radeon_wb_fini(rdev); - radeon_gem_fini(rdev); - radeon_object_fini(rdev); - /* mc_fini must be after object_fini */ - radeon_mc_fini(rdev); + if (!rdev->new_init_path) { + radeon_ib_pool_fini(rdev); + radeon_cp_fini(rdev); + radeon_wb_fini(rdev); + radeon_gem_fini(rdev); + radeon_mc_fini(rdev); #if __OS_HAS_AGP - radeon_agp_fini(rdev); + radeon_agp_fini(rdev); #endif - radeon_irq_kms_fini(rdev); - radeon_fence_driver_fini(rdev); - radeon_clocks_fini(rdev); - if (rdev->is_atom_bios) { - radeon_atombios_fini(rdev); + radeon_irq_kms_fini(rdev); + radeon_fence_driver_fini(rdev); + radeon_clocks_fini(rdev); + radeon_object_fini(rdev); + if (rdev->is_atom_bios) { + radeon_atombios_fini(rdev); + } else { + radeon_combios_fini(rdev); + } + kfree(rdev->bios); + rdev->bios = NULL; } else { - radeon_combios_fini(rdev); + radeon_fini(rdev); } - kfree(rdev->bios); - rdev->bios = NULL; iounmap(rdev->rmmio); rdev->rmmio = NULL; } @@ -708,9 +743,12 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) /* wait for gpu to finish processing current batch */ radeon_fence_wait_last(rdev); - radeon_cp_disable(rdev); - radeon_gart_disable(rdev); - + if (!rdev->new_init_path) { + radeon_cp_disable(rdev); + radeon_gart_disable(rdev); + } else { + radeon_suspend(rdev); + } /* evict remaining vram memory */ radeon_object_evict_vram(rdev); @@ -746,33 +784,37 @@ int radeon_resume_kms(struct drm_device *dev) if (radeon_gpu_reset(rdev)) { /* FIXME: what do we want to do here ? */ } - /* post card */ - if (rdev->is_atom_bios) { - atom_asic_init(rdev->mode_info.atom_context); + if (!rdev->new_init_path) { + /* post card */ + if (rdev->is_atom_bios) { + atom_asic_init(rdev->mode_info.atom_context); + } else { + radeon_combios_asic_init(rdev->ddev); + } + /* Initialize clocks */ + r = radeon_clocks_init(rdev); + if (r) { + release_console_sem(); + return r; + } + /* Enable IRQ */ + rdev->irq.sw_int = true; + radeon_irq_set(rdev); + /* Initialize GPU Memory Controller */ + r = radeon_mc_init(rdev); + if (r) { + goto out; + } + r = radeon_gart_enable(rdev); + if (r) { + goto out; + } + r = radeon_cp_init(rdev, rdev->cp.ring_size); + if (r) { + goto out; + } } else { - radeon_combios_asic_init(rdev->ddev); - } - /* Initialize clocks */ - r = radeon_clocks_init(rdev); - if (r) { - release_console_sem(); - return r; - } - /* Enable IRQ */ - rdev->irq.sw_int = true; - radeon_irq_set(rdev); - /* Initialize GPU Memory Controller */ - r = radeon_mc_init(rdev); - if (r) { - goto out; - } - r = radeon_gart_enable(rdev); - if (r) { - goto out; - } - r = radeon_cp_init(rdev, rdev->cp.ring_size); - if (r) { - goto out; + radeon_resume(rdev); } out: fb_set_suspend(rdev->fbdev_info, 0); -- cgit v1.2.3 From 905b68223be18937159a29b354e6a332952ff952 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Wed, 9 Sep 2009 22:24:20 +0200 Subject: drm/radeon/kms: add R4XX mc register access helper. Atombios will use the mc register access helper and R4XX hw have a bigger mc range than R3XX so add R4XX specific mc register access helper. Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r420.c | 17 ++++++++++++++ drivers/gpu/drm/radeon/r420d.h | 43 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/radeon.h | 4 ++++ drivers/gpu/drm/radeon/radeon_device.c | 4 ++++ 4 files changed, 68 insertions(+) create mode 100644 drivers/gpu/drm/radeon/r420d.h (limited to 'drivers/gpu/drm/radeon/radeon_device.c') diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index 97426a6f370f..96303f064db7 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c @@ -29,6 +29,7 @@ #include "drmP.h" #include "radeon_reg.h" #include "radeon.h" +#include "r420d.h" /* r420,r423,rv410 depends on : */ void r100_pci_gart_disable(struct radeon_device *rdev); @@ -232,3 +233,19 @@ int r420_debugfs_pipes_info_init(struct radeon_device *rdev) return 0; #endif } + +u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg) +{ + u32 r; + + WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg)); + r = RREG32(R_0001FC_MC_IND_DATA); + return r; +} + +void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v) +{ + WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg) | + S_0001F8_MC_IND_WR_EN(1)); + WREG32(R_0001FC_MC_IND_DATA, v); +} diff --git a/drivers/gpu/drm/radeon/r420d.h b/drivers/gpu/drm/radeon/r420d.h new file mode 100644 index 000000000000..8b946c1883ba --- /dev/null +++ b/drivers/gpu/drm/radeon/r420d.h @@ -0,0 +1,43 @@ +/* + * Copyright 2008 Advanced Micro Devices, Inc. + * Copyright 2008 Red Hat Inc. + * Copyright 2009 Jerome Glisse. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + * Alex Deucher + * Jerome Glisse + */ +#ifndef R420D_H +#define R420D_H + +#define R_0001F8_MC_IND_INDEX 0x0001F8 +#define S_0001F8_MC_IND_ADDR(x) (((x) & 0x7F) << 0) +#define G_0001F8_MC_IND_ADDR(x) (((x) >> 0) & 0x7F) +#define C_0001F8_MC_IND_ADDR 0xFFFFFF80 +#define S_0001F8_MC_IND_WR_EN(x) (((x) & 0x1) << 8) +#define G_0001F8_MC_IND_WR_EN(x) (((x) >> 8) & 0x1) +#define C_0001F8_MC_IND_WR_EN 0xFFFFFEFF +#define R_0001FC_MC_IND_DATA 0x0001FC +#define S_0001FC_MC_IND_DATA(x) (((x) & 0xFFFFFFFF) << 0) +#define G_0001FC_MC_IND_DATA(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_0001FC_MC_IND_DATA 0x00000000 + +#endif diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 24574bc0f2af..fa84c77577ab 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -936,4 +936,8 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v) /* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */ void r100_cp_disable(struct radeon_device *rdev); +/* r420,r423,rv410 */ +u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg); +void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v); + #endif diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index f2469c511789..05e1af0156c8 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -266,6 +266,10 @@ void radeon_register_accessor_init(struct radeon_device *rdev) rdev->pll_rreg = &r100_pll_rreg; rdev->pll_wreg = &r100_pll_wreg; } + if (rdev->family >= CHIP_R420) { + rdev->mc_rreg = &r420_mc_rreg; + rdev->mc_wreg = &r420_mc_wreg; + } if (rdev->family >= CHIP_RV515) { rdev->mc_rreg = &rv515_mc_rreg; rdev->mc_wreg = &rv515_mc_wreg; -- cgit v1.2.3 From c000273ebc830c27b8c9e03d5f4c147d3e310f48 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Thu, 10 Sep 2009 13:47:09 +0200 Subject: drm/radeon/kms: R3XX/R4XX AGP asic use PCI GART not PCIE GART R3XX/R4XX AGP asic use the old PCI GART block, not the new PCIE GART. Make sure we pick the right GART when disabling AGP. Signed-off-by: Jerome Glisse Acked-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r300.c | 6 ++++++ drivers/gpu/drm/radeon/r420.c | 9 +++++++-- drivers/gpu/drm/radeon/radeon.h | 4 ++++ drivers/gpu/drm/radeon/radeon_device.c | 2 +- 4 files changed, 18 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/radeon/radeon_device.c') diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index a5f82f7beed6..9c17b786982a 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -181,6 +181,12 @@ int r300_gart_enable(struct radeon_device *rdev) rdev->asic->gart_set_page = &rv370_pcie_gart_set_page; return rv370_pcie_gart_enable(rdev); } + if (rdev->flags & RADEON_IS_PCI) { + rdev->asic->gart_disable = &r100_pci_gart_disable; + rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush; + rdev->asic->gart_set_page = &r100_pci_gart_set_page; + return r100_pci_gart_enable(rdev); + } return r100_pci_gart_enable(rdev); } diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index 96303f064db7..551d6996d3f2 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c @@ -101,8 +101,13 @@ int r420_mc_init(struct radeon_device *rdev) void r420_mc_fini(struct radeon_device *rdev) { - rv370_pcie_gart_disable(rdev); - radeon_gart_table_vram_free(rdev); + if (rdev->flags & RADEON_IS_PCIE) { + rv370_pcie_gart_disable(rdev); + radeon_gart_table_vram_free(rdev); + } else { + r100_pci_gart_disable(rdev); + radeon_gart_table_ram_free(rdev); + } radeon_gart_fini(rdev); } diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index fa84c77577ab..d6ff4e012063 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -935,6 +935,10 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v) /* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */ void r100_cp_disable(struct radeon_device *rdev); +void r100_pci_gart_tlb_flush(struct radeon_device *rdev); +int r100_pci_gart_enable(struct radeon_device *rdev); +void r100_pci_gart_disable(struct radeon_device *rdev); +int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); /* r420,r423,rv410 */ u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg); diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 05e1af0156c8..bf6939497e15 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -503,7 +503,7 @@ int radeon_device_init(struct radeon_device *rdev, if (radeon_agpmode == -1) { rdev->flags &= ~RADEON_IS_AGP; - if (rdev->family > CHIP_RV515 || + if (rdev->family >= CHIP_RV515 || rdev->family == CHIP_RV380 || rdev->family == CHIP_RV410 || rdev->family == CHIP_R423) { -- cgit v1.2.3 From 6cf8a3f58806f12b975a89cfd7edf01566ff80a0 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Thu, 10 Sep 2009 21:46:48 +0200 Subject: drm/radeon/kms: move modeset init outside of GPU init We are splitting GPU & modeset init so that it's easier to abord only remaining GPU init when somethings fails. We want to always provide enough funcionalities to get fbcon and a shadowfb X working. Only acceptable error during initialization are memory allocation failure or io mapping failure. Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon.h | 4 ++++ drivers/gpu/drm/radeon/radeon_device.c | 20 +++----------------- drivers/gpu/drm/radeon/radeon_kms.c | 22 ++++++++++++++++++---- 3 files changed, 25 insertions(+), 21 deletions(-) (limited to 'drivers/gpu/drm/radeon/radeon_device.c') diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index d6ff4e012063..23ede0e4783e 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -933,6 +933,10 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v) #define radeon_clear_surface_reg(rdev, r) ((rdev)->asic->clear_surface_reg((rdev), (r))) #define radeon_bandwidth_update(rdev) (rdev)->asic->bandwidth_update((rdev)) +/* Common functions */ +int radeon_modeset_init(struct radeon_device *rdev); +void radeon_modeset_fini(struct radeon_device *rdev); + /* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */ void r100_cp_disable(struct radeon_device *rdev); void r100_pci_gart_tlb_flush(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index bf6939497e15..72f6262ea73b 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -469,9 +469,6 @@ void radeon_combios_fini(struct radeon_device *rdev) { } -int radeon_modeset_init(struct radeon_device *rdev); -void radeon_modeset_fini(struct radeon_device *rdev); - /* * Radeon device. @@ -481,7 +478,7 @@ int radeon_device_init(struct radeon_device *rdev, struct pci_dev *pdev, uint32_t flags) { - int r, ret = 0; + int r; int dma_bits; DRM_INFO("radeon: Initializing kernel modesetting.\n"); @@ -660,33 +657,22 @@ int radeon_device_init(struct radeon_device *rdev, return r; } } - ret = r; - } - r = radeon_modeset_init(rdev); - if (r) { - return r; - } - if (!ret) { - DRM_INFO("radeon: kernel modesetting successfully initialized.\n"); } + DRM_INFO("radeon: kernel modesetting successfully initialized.\n"); if (radeon_testing) { radeon_test_moves(rdev); } if (radeon_benchmarking) { radeon_benchmark(rdev); } - return ret; + return 0; } void radeon_device_fini(struct radeon_device *rdev) { - if (rdev == NULL || rdev->rmmio == NULL) { - return; - } DRM_INFO("radeon: finishing device.\n"); rdev->shutdown = true; /* Order matter so becarefull if you rearrange anythings */ - radeon_modeset_fini(rdev); if (!rdev->new_init_path) { radeon_ib_pool_fini(rdev); radeon_cp_fini(rdev); diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index dce09ada32bc..ac8505fe2ca7 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -54,12 +54,23 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) flags |= RADEON_IS_PCI; } + /* radeon_device_init should report only fatal error + * like memory allocation failure or iomapping failure, + * or memory manager initialization failure, it must + * properly initialize the GPU MC controller and permit + * VRAM allocation + */ r = radeon_device_init(rdev, dev, dev->pdev, flags); if (r) { - DRM_ERROR("Failed to initialize radeon, disabling IOCTL\n"); - radeon_device_fini(rdev); - kfree(rdev); - dev->dev_private = NULL; + DRM_ERROR("Fatal error while trying to initialize radeon.\n"); + return r; + } + /* Again modeset_init should fail only on fatal error + * otherwise it should provide enough functionalities + * for shadowfb to run + */ + r = radeon_modeset_init(rdev); + if (r) { return r; } return 0; @@ -69,6 +80,9 @@ int radeon_driver_unload_kms(struct drm_device *dev) { struct radeon_device *rdev = dev->dev_private; + if (rdev == NULL) + return 0; + radeon_modeset_fini(rdev); radeon_device_fini(rdev); kfree(rdev); dev->dev_private = NULL; -- cgit v1.2.3 From 9f022ddfb23793b475ff7e57ac08a766dd5d31bd Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Fri, 11 Sep 2009 15:35:22 +0200 Subject: drm/radeon/kms: convert r4xx to new init path This convert r4xx to new init path it also fix few bugs. Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100.c | 114 +++++++- drivers/gpu/drm/radeon/r100d.h | 471 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/r300.c | 50 +++- drivers/gpu/drm/radeon/r300d.h | 25 ++ drivers/gpu/drm/radeon/r420.c | 293 +++++++++++++------- drivers/gpu/drm/radeon/r420d.h | 206 ++++++++++++++ drivers/gpu/drm/radeon/radeon.h | 32 ++- drivers/gpu/drm/radeon/radeon_asic.h | 33 +-- drivers/gpu/drm/radeon/radeon_device.c | 19 +- drivers/gpu/drm/radeon/radeon_ring.c | 2 + 10 files changed, 1121 insertions(+), 124 deletions(-) (limited to 'drivers/gpu/drm/radeon/radeon_device.c') diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 4dd5ca50c0c5..47263d3ede98 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -299,6 +299,17 @@ int r100_irq_set(struct radeon_device *rdev) return 0; } +void r100_irq_disable(struct radeon_device *rdev) +{ + u32 tmp; + + WREG32(R_000040_GEN_INT_CNTL, 0); + /* Wait and acknowledge irq */ + mdelay(1); + tmp = RREG32(R_000044_GEN_INT_STATUS); + WREG32(R_000044_GEN_INT_STATUS, tmp); +} + static inline uint32_t r100_irq_ack(struct radeon_device *rdev) { uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS); @@ -396,14 +407,21 @@ int r100_wb_init(struct radeon_device *rdev) return r; } } - WREG32(RADEON_SCRATCH_ADDR, rdev->wb.gpu_addr); - WREG32(RADEON_CP_RB_RPTR_ADDR, rdev->wb.gpu_addr + 1024); - WREG32(RADEON_SCRATCH_UMSK, 0xff); + WREG32(R_000774_SCRATCH_ADDR, rdev->wb.gpu_addr); + WREG32(R_00070C_CP_RB_RPTR_ADDR, + S_00070C_RB_RPTR_ADDR((rdev->wb.gpu_addr + 1024) >> 2)); + WREG32(R_000770_SCRATCH_UMSK, 0xff); return 0; } +void r100_wb_disable(struct radeon_device *rdev) +{ + WREG32(R_000770_SCRATCH_UMSK, 0); +} + void r100_wb_fini(struct radeon_device *rdev) { + r100_wb_disable(rdev); if (rdev->wb.wb_obj) { radeon_object_kunmap(rdev->wb.wb_obj); radeon_object_unpin(rdev->wb.wb_obj); @@ -1581,11 +1599,12 @@ static int r100_packet3_check(struct radeon_cs_parser *p, int r100_cs_parse(struct radeon_cs_parser *p) { struct radeon_cs_packet pkt; - struct r100_cs_track track; + struct r100_cs_track *track; int r; - r100_cs_track_clear(p->rdev, &track); - p->track = &track; + track = kzalloc(sizeof(*track), GFP_KERNEL); + r100_cs_track_clear(p->rdev, track); + p->track = track; do { r = r100_cs_packet_parse(p, &pkt, p->idx); if (r) { @@ -3085,3 +3104,86 @@ int r100_ib_test(struct radeon_device *rdev) radeon_ib_free(rdev, &ib); return r; } + +void r100_ib_fini(struct radeon_device *rdev) +{ + radeon_ib_pool_fini(rdev); +} + +int r100_ib_init(struct radeon_device *rdev) +{ + int r; + + r = radeon_ib_pool_init(rdev); + if (r) { + dev_err(rdev->dev, "failled initializing IB pool (%d).\n", r); + r100_ib_fini(rdev); + return r; + } + r = r100_ib_test(rdev); + if (r) { + dev_err(rdev->dev, "failled testing IB (%d).\n", r); + r100_ib_fini(rdev); + return r; + } + return 0; +} + +void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save) +{ + /* Shutdown CP we shouldn't need to do that but better be safe than + * sorry + */ + rdev->cp.ready = false; + WREG32(R_000740_CP_CSQ_CNTL, 0); + + /* Save few CRTC registers */ + save->GENMO_WT = RREG32(R_0003C0_GENMO_WT); + save->CRTC_EXT_CNTL = RREG32(R_000054_CRTC_EXT_CNTL); + save->CRTC_GEN_CNTL = RREG32(R_000050_CRTC_GEN_CNTL); + save->CUR_OFFSET = RREG32(R_000260_CUR_OFFSET); + if (!(rdev->flags & RADEON_SINGLE_CRTC)) { + save->CRTC2_GEN_CNTL = RREG32(R_0003F8_CRTC2_GEN_CNTL); + save->CUR2_OFFSET = RREG32(R_000360_CUR2_OFFSET); + } + + /* Disable VGA aperture access */ + WREG32(R_0003C0_GENMO_WT, C_0003C0_VGA_RAM_EN & save->GENMO_WT); + /* Disable cursor, overlay, crtc */ + WREG32(R_000260_CUR_OFFSET, save->CUR_OFFSET | S_000260_CUR_LOCK(1)); + WREG32(R_000054_CRTC_EXT_CNTL, save->CRTC_EXT_CNTL | + S_000054_CRTC_DISPLAY_DIS(1)); + WREG32(R_000050_CRTC_GEN_CNTL, + (C_000050_CRTC_CUR_EN & save->CRTC_GEN_CNTL) | + S_000050_CRTC_DISP_REQ_EN_B(1)); + WREG32(R_000420_OV0_SCALE_CNTL, + C_000420_OV0_OVERLAY_EN & RREG32(R_000420_OV0_SCALE_CNTL)); + WREG32(R_000260_CUR_OFFSET, C_000260_CUR_LOCK & save->CUR_OFFSET); + if (!(rdev->flags & RADEON_SINGLE_CRTC)) { + WREG32(R_000360_CUR2_OFFSET, save->CUR2_OFFSET | + S_000360_CUR2_LOCK(1)); + WREG32(R_0003F8_CRTC2_GEN_CNTL, + (C_0003F8_CRTC2_CUR_EN & save->CRTC2_GEN_CNTL) | + S_0003F8_CRTC2_DISPLAY_DIS(1) | + S_0003F8_CRTC2_DISP_REQ_EN_B(1)); + WREG32(R_000360_CUR2_OFFSET, + C_000360_CUR2_LOCK & save->CUR2_OFFSET); + } +} + +void r100_mc_resume(struct radeon_device *rdev, struct r100_mc_save *save) +{ + /* Update base address for crtc */ + WREG32(R_00023C_DISPLAY_BASE_ADDR, rdev->mc.vram_location); + if (!(rdev->flags & RADEON_SINGLE_CRTC)) { + WREG32(R_00033C_CRTC2_DISPLAY_BASE_ADDR, + rdev->mc.vram_location); + } + /* Restore CRTC registers */ + WREG32(R_0003C0_GENMO_WT, save->GENMO_WT); + WREG32(R_000054_CRTC_EXT_CNTL, save->CRTC_EXT_CNTL); + WREG32(R_000050_CRTC_GEN_CNTL, save->CRTC_GEN_CNTL); + if (!(rdev->flags & RADEON_SINGLE_CRTC)) { + WREG32(R_0003F8_CRTC2_GEN_CNTL, save->CRTC2_GEN_CNTL); + } +} diff --git a/drivers/gpu/drm/radeon/r100d.h b/drivers/gpu/drm/radeon/r100d.h index 1d951ab77dce..c4b257ec920e 100644 --- a/drivers/gpu/drm/radeon/r100d.h +++ b/drivers/gpu/drm/radeon/r100d.h @@ -74,6 +74,477 @@ #define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF) /* Registers */ +#define R_000040_GEN_INT_CNTL 0x000040 +#define S_000040_CRTC_VBLANK(x) (((x) & 0x1) << 0) +#define G_000040_CRTC_VBLANK(x) (((x) >> 0) & 0x1) +#define C_000040_CRTC_VBLANK 0xFFFFFFFE +#define S_000040_CRTC_VLINE(x) (((x) & 0x1) << 1) +#define G_000040_CRTC_VLINE(x) (((x) >> 1) & 0x1) +#define C_000040_CRTC_VLINE 0xFFFFFFFD +#define S_000040_CRTC_VSYNC(x) (((x) & 0x1) << 2) +#define G_000040_CRTC_VSYNC(x) (((x) >> 2) & 0x1) +#define C_000040_CRTC_VSYNC 0xFFFFFFFB +#define S_000040_SNAPSHOT(x) (((x) & 0x1) << 3) +#define G_000040_SNAPSHOT(x) (((x) >> 3) & 0x1) +#define C_000040_SNAPSHOT 0xFFFFFFF7 +#define S_000040_FP_DETECT(x) (((x) & 0x1) << 4) +#define G_000040_FP_DETECT(x) (((x) >> 4) & 0x1) +#define C_000040_FP_DETECT 0xFFFFFFEF +#define S_000040_CRTC2_VLINE(x) (((x) & 0x1) << 5) +#define G_000040_CRTC2_VLINE(x) (((x) >> 5) & 0x1) +#define C_000040_CRTC2_VLINE 0xFFFFFFDF +#define S_000040_DMA_VIPH0_INT_EN(x) (((x) & 0x1) << 12) +#define G_000040_DMA_VIPH0_INT_EN(x) (((x) >> 12) & 0x1) +#define C_000040_DMA_VIPH0_INT_EN 0xFFFFEFFF +#define S_000040_CRTC2_VSYNC(x) (((x) & 0x1) << 6) +#define G_000040_CRTC2_VSYNC(x) (((x) >> 6) & 0x1) +#define C_000040_CRTC2_VSYNC 0xFFFFFFBF +#define S_000040_SNAPSHOT2(x) (((x) & 0x1) << 7) +#define G_000040_SNAPSHOT2(x) (((x) >> 7) & 0x1) +#define C_000040_SNAPSHOT2 0xFFFFFF7F +#define S_000040_CRTC2_VBLANK(x) (((x) & 0x1) << 9) +#define G_000040_CRTC2_VBLANK(x) (((x) >> 9) & 0x1) +#define C_000040_CRTC2_VBLANK 0xFFFFFDFF +#define S_000040_FP2_DETECT(x) (((x) & 0x1) << 10) +#define G_000040_FP2_DETECT(x) (((x) >> 10) & 0x1) +#define C_000040_FP2_DETECT 0xFFFFFBFF +#define S_000040_VSYNC_DIFF_OVER_LIMIT(x) (((x) & 0x1) << 11) +#define G_000040_VSYNC_DIFF_OVER_LIMIT(x) (((x) >> 11) & 0x1) +#define C_000040_VSYNC_DIFF_OVER_LIMIT 0xFFFFF7FF +#define S_000040_DMA_VIPH1_INT_EN(x) (((x) & 0x1) << 13) +#define G_000040_DMA_VIPH1_INT_EN(x) (((x) >> 13) & 0x1) +#define C_000040_DMA_VIPH1_INT_EN 0xFFFFDFFF +#define S_000040_DMA_VIPH2_INT_EN(x) (((x) & 0x1) << 14) +#define G_000040_DMA_VIPH2_INT_EN(x) (((x) >> 14) & 0x1) +#define C_000040_DMA_VIPH2_INT_EN 0xFFFFBFFF +#define S_000040_DMA_VIPH3_INT_EN(x) (((x) & 0x1) << 15) +#define G_000040_DMA_VIPH3_INT_EN(x) (((x) >> 15) & 0x1) +#define C_000040_DMA_VIPH3_INT_EN 0xFFFF7FFF +#define S_000040_I2C_INT_EN(x) (((x) & 0x1) << 17) +#define G_000040_I2C_INT_EN(x) (((x) >> 17) & 0x1) +#define C_000040_I2C_INT_EN 0xFFFDFFFF +#define S_000040_GUI_IDLE(x) (((x) & 0x1) << 19) +#define G_000040_GUI_IDLE(x) (((x) >> 19) & 0x1) +#define C_000040_GUI_IDLE 0xFFF7FFFF +#define S_000040_VIPH_INT_EN(x) (((x) & 0x1) << 24) +#define G_000040_VIPH_INT_EN(x) (((x) >> 24) & 0x1) +#define C_000040_VIPH_INT_EN 0xFEFFFFFF +#define S_000040_SW_INT_EN(x) (((x) & 0x1) << 25) +#define G_000040_SW_INT_EN(x) (((x) >> 25) & 0x1) +#define C_000040_SW_INT_EN 0xFDFFFFFF +#define S_000040_GEYSERVILLE(x) (((x) & 0x1) << 27) +#define G_000040_GEYSERVILLE(x) (((x) >> 27) & 0x1) +#define C_000040_GEYSERVILLE 0xF7FFFFFF +#define S_000040_HDCP_AUTHORIZED_INT(x) (((x) & 0x1) << 28) +#define G_000040_HDCP_AUTHORIZED_INT(x) (((x) >> 28) & 0x1) +#define C_000040_HDCP_AUTHORIZED_INT 0xEFFFFFFF +#define S_000040_DVI_I2C_INT(x) (((x) & 0x1) << 29) +#define G_000040_DVI_I2C_INT(x) (((x) >> 29) & 0x1) +#define C_000040_DVI_I2C_INT 0xDFFFFFFF +#define S_000040_GUIDMA(x) (((x) & 0x1) << 30) +#define G_000040_GUIDMA(x) (((x) >> 30) & 0x1) +#define C_000040_GUIDMA 0xBFFFFFFF +#define S_000040_VIDDMA(x) (((x) & 0x1) << 31) +#define G_000040_VIDDMA(x) (((x) >> 31) & 0x1) +#define C_000040_VIDDMA 0x7FFFFFFF +#define R_000044_GEN_INT_STATUS 0x000044 +#define S_000044_CRTC_VBLANK_STAT(x) (((x) & 0x1) << 0) +#define G_000044_CRTC_VBLANK_STAT(x) (((x) >> 0) & 0x1) +#define C_000044_CRTC_VBLANK_STAT 0xFFFFFFFE +#define S_000044_CRTC_VBLANK_STAT_AK(x) (((x) & 0x1) << 0) +#define G_000044_CRTC_VBLANK_STAT_AK(x) (((x) >> 0) & 0x1) +#define C_000044_CRTC_VBLANK_STAT_AK 0xFFFFFFFE +#define S_000044_CRTC_VLINE_STAT(x) (((x) & 0x1) << 1) +#define G_000044_CRTC_VLINE_STAT(x) (((x) >> 1) & 0x1) +#define C_000044_CRTC_VLINE_STAT 0xFFFFFFFD +#define S_000044_CRTC_VLINE_STAT_AK(x) (((x) & 0x1) << 1) +#define G_000044_CRTC_VLINE_STAT_AK(x) (((x) >> 1) & 0x1) +#define C_000044_CRTC_VLINE_STAT_AK 0xFFFFFFFD +#define S_000044_CRTC_VSYNC_STAT(x) (((x) & 0x1) << 2) +#define G_000044_CRTC_VSYNC_STAT(x) (((x) >> 2) & 0x1) +#define C_000044_CRTC_VSYNC_STAT 0xFFFFFFFB +#define S_000044_CRTC_VSYNC_STAT_AK(x) (((x) & 0x1) << 2) +#define G_000044_CRTC_VSYNC_STAT_AK(x) (((x) >> 2) & 0x1) +#define C_000044_CRTC_VSYNC_STAT_AK 0xFFFFFFFB +#define S_000044_SNAPSHOT_STAT(x) (((x) & 0x1) << 3) +#define G_000044_SNAPSHOT_STAT(x) (((x) >> 3) & 0x1) +#define C_000044_SNAPSHOT_STAT 0xFFFFFFF7 +#define S_000044_SNAPSHOT_STAT_AK(x) (((x) & 0x1) << 3) +#define G_000044_SNAPSHOT_STAT_AK(x) (((x) >> 3) & 0x1) +#define C_000044_SNAPSHOT_STAT_AK 0xFFFFFFF7 +#define S_000044_FP_DETECT_STAT(x) (((x) & 0x1) << 4) +#define G_000044_FP_DETECT_STAT(x) (((x) >> 4) & 0x1) +#define C_000044_FP_DETECT_STAT 0xFFFFFFEF +#define S_000044_FP_DETECT_STAT_AK(x) (((x) & 0x1) << 4) +#define G_000044_FP_DETECT_STAT_AK(x) (((x) >> 4) & 0x1) +#define C_000044_FP_DETECT_STAT_AK 0xFFFFFFEF +#define S_000044_CRTC2_VLINE_STAT(x) (((x) & 0x1) << 5) +#define G_000044_CRTC2_VLINE_STAT(x) (((x) >> 5) & 0x1) +#define C_000044_CRTC2_VLINE_STAT 0xFFFFFFDF +#define S_000044_CRTC2_VLINE_STAT_AK(x) (((x) & 0x1) << 5) +#define G_000044_CRTC2_VLINE_STAT_AK(x) (((x) >> 5) & 0x1) +#define C_000044_CRTC2_VLINE_STAT_AK 0xFFFFFFDF +#define S_000044_CRTC2_VSYNC_STAT(x) (((x) & 0x1) << 6) +#define G_000044_CRTC2_VSYNC_STAT(x) (((x) >> 6) & 0x1) +#define C_000044_CRTC2_VSYNC_STAT 0xFFFFFFBF +#define S_000044_CRTC2_VSYNC_STAT_AK(x) (((x) & 0x1) << 6) +#define G_000044_CRTC2_VSYNC_STAT_AK(x) (((x) >> 6) & 0x1) +#define C_000044_CRTC2_VSYNC_STAT_AK 0xFFFFFFBF +#define S_000044_SNAPSHOT2_STAT(x) (((x) & 0x1) << 7) +#define G_000044_SNAPSHOT2_STAT(x) (((x) >> 7) & 0x1) +#define C_000044_SNAPSHOT2_STAT 0xFFFFFF7F +#define S_000044_SNAPSHOT2_STAT_AK(x) (((x) & 0x1) << 7) +#define G_000044_SNAPSHOT2_STAT_AK(x) (((x) >> 7) & 0x1) +#define C_000044_SNAPSHOT2_STAT_AK 0xFFFFFF7F +#define S_000044_CAP0_INT_ACTIVE(x) (((x) & 0x1) << 8) +#define G_000044_CAP0_INT_ACTIVE(x) (((x) >> 8) & 0x1) +#define C_000044_CAP0_INT_ACTIVE 0xFFFFFEFF +#define S_000044_CRTC2_VBLANK_STAT(x) (((x) & 0x1) << 9) +#define G_000044_CRTC2_VBLANK_STAT(x) (((x) >> 9) & 0x1) +#define C_000044_CRTC2_VBLANK_STAT 0xFFFFFDFF +#define S_000044_CRTC2_VBLANK_STAT_AK(x) (((x) & 0x1) << 9) +#define G_000044_CRTC2_VBLANK_STAT_AK(x) (((x) >> 9) & 0x1) +#define C_000044_CRTC2_VBLANK_STAT_AK 0xFFFFFDFF +#define S_000044_FP2_DETECT_STAT(x) (((x) & 0x1) << 10) +#define G_000044_FP2_DETECT_STAT(x) (((x) >> 10) & 0x1) +#define C_000044_FP2_DETECT_STAT 0xFFFFFBFF +#define S_000044_FP2_DETECT_STAT_AK(x) (((x) & 0x1) << 10) +#define G_000044_FP2_DETECT_STAT_AK(x) (((x) >> 10) & 0x1) +#define C_000044_FP2_DETECT_STAT_AK 0xFFFFFBFF +#define S_000044_VSYNC_DIFF_OVER_LIMIT_STAT(x) (((x) & 0x1) << 11) +#define G_000044_VSYNC_DIFF_OVER_LIMIT_STAT(x) (((x) >> 11) & 0x1) +#define C_000044_VSYNC_DIFF_OVER_LIMIT_STAT 0xFFFFF7FF +#define S_000044_VSYNC_DIFF_OVER_LIMIT_STAT_AK(x) (((x) & 0x1) << 11) +#define G_000044_VSYNC_DIFF_OVER_LIMIT_STAT_AK(x) (((x) >> 11) & 0x1) +#define C_000044_VSYNC_DIFF_OVER_LIMIT_STAT_AK 0xFFFFF7FF +#define S_000044_DMA_VIPH0_INT(x) (((x) & 0x1) << 12) +#define G_000044_DMA_VIPH0_INT(x) (((x) >> 12) & 0x1) +#define C_000044_DMA_VIPH0_INT 0xFFFFEFFF +#define S_000044_DMA_VIPH0_INT_AK(x) (((x) & 0x1) << 12) +#define G_000044_DMA_VIPH0_INT_AK(x) (((x) >> 12) & 0x1) +#define C_000044_DMA_VIPH0_INT_AK 0xFFFFEFFF +#define S_000044_DMA_VIPH1_INT(x) (((x) & 0x1) << 13) +#define G_000044_DMA_VIPH1_INT(x) (((x) >> 13) & 0x1) +#define C_000044_DMA_VIPH1_INT 0xFFFFDFFF +#define S_000044_DMA_VIPH1_INT_AK(x) (((x) & 0x1) << 13) +#define G_000044_DMA_VIPH1_INT_AK(x) (((x) >> 13) & 0x1) +#define C_000044_DMA_VIPH1_INT_AK 0xFFFFDFFF +#define S_000044_DMA_VIPH2_INT(x) (((x) & 0x1) << 14) +#define G_000044_DMA_VIPH2_INT(x) (((x) >> 14) & 0x1) +#define C_000044_DMA_VIPH2_INT 0xFFFFBFFF +#define S_000044_DMA_VIPH2_INT_AK(x) (((x) & 0x1) << 14) +#define G_000044_DMA_VIPH2_INT_AK(x) (((x) >> 14) & 0x1) +#define C_000044_DMA_VIPH2_INT_AK 0xFFFFBFFF +#define S_000044_DMA_VIPH3_INT(x) (((x) & 0x1) << 15) +#define G_000044_DMA_VIPH3_INT(x) (((x) >> 15) & 0x1) +#define C_000044_DMA_VIPH3_INT 0xFFFF7FFF +#define S_000044_DMA_VIPH3_INT_AK(x) (((x) & 0x1) << 15) +#define G_000044_DMA_VIPH3_INT_AK(x) (((x) >> 15) & 0x1) +#define C_000044_DMA_VIPH3_INT_AK 0xFFFF7FFF +#define S_000044_I2C_INT(x) (((x) & 0x1) << 17) +#define G_000044_I2C_INT(x) (((x) >> 17) & 0x1) +#define C_000044_I2C_INT 0xFFFDFFFF +#define S_000044_I2C_INT_AK(x) (((x) & 0x1) << 17) +#define G_000044_I2C_INT_AK(x) (((x) >> 17) & 0x1) +#define C_000044_I2C_INT_AK 0xFFFDFFFF +#define S_000044_GUI_IDLE_STAT(x) (((x) & 0x1) << 19) +#define G_000044_GUI_IDLE_STAT(x) (((x) >> 19) & 0x1) +#define C_000044_GUI_IDLE_STAT 0xFFF7FFFF +#define S_000044_GUI_IDLE_STAT_AK(x) (((x) & 0x1) << 19) +#define G_000044_GUI_IDLE_STAT_AK(x) (((x) >> 19) & 0x1) +#define C_000044_GUI_IDLE_STAT_AK 0xFFF7FFFF +#define S_000044_VIPH_INT(x) (((x) & 0x1) << 24) +#define G_000044_VIPH_INT(x) (((x) >> 24) & 0x1) +#define C_000044_VIPH_INT 0xFEFFFFFF +#define S_000044_SW_INT(x) (((x) & 0x1) << 25) +#define G_000044_SW_INT(x) (((x) >> 25) & 0x1) +#define C_000044_SW_INT 0xFDFFFFFF +#define S_000044_SW_INT_AK(x) (((x) & 0x1) << 25) +#define G_000044_SW_INT_AK(x) (((x) >> 25) & 0x1) +#define C_000044_SW_INT_AK 0xFDFFFFFF +#define S_000044_SW_INT_SET(x) (((x) & 0x1) << 26) +#define G_000044_SW_INT_SET(x) (((x) >> 26) & 0x1) +#define C_000044_SW_INT_SET 0xFBFFFFFF +#define S_000044_GEYSERVILLE_STAT(x) (((x) & 0x1) << 27) +#define G_000044_GEYSERVILLE_STAT(x) (((x) >> 27) & 0x1) +#define C_000044_GEYSERVILLE_STAT 0xF7FFFFFF +#define S_000044_GEYSERVILLE_STAT_AK(x) (((x) & 0x1) << 27) +#define G_000044_GEYSERVILLE_STAT_AK(x) (((x) >> 27) & 0x1) +#define C_000044_GEYSERVILLE_STAT_AK 0xF7FFFFFF +#define S_000044_HDCP_AUTHORIZED_INT_STAT(x) (((x) & 0x1) << 28) +#define G_000044_HDCP_AUTHORIZED_INT_STAT(x) (((x) >> 28) & 0x1) +#define C_000044_HDCP_AUTHORIZED_INT_STAT 0xEFFFFFFF +#define S_000044_HDCP_AUTHORIZED_INT_AK(x) (((x) & 0x1) << 28) +#define G_000044_HDCP_AUTHORIZED_INT_AK(x) (((x) >> 28) & 0x1) +#define C_000044_HDCP_AUTHORIZED_INT_AK 0xEFFFFFFF +#define S_000044_DVI_I2C_INT_STAT(x) (((x) & 0x1) << 29) +#define G_000044_DVI_I2C_INT_STAT(x) (((x) >> 29) & 0x1) +#define C_000044_DVI_I2C_INT_STAT 0xDFFFFFFF +#define S_000044_DVI_I2C_INT_AK(x) (((x) & 0x1) << 29) +#define G_000044_DVI_I2C_INT_AK(x) (((x) >> 29) & 0x1) +#define C_000044_DVI_I2C_INT_AK 0xDFFFFFFF +#define S_000044_GUIDMA_STAT(x) (((x) & 0x1) << 30) +#define G_000044_GUIDMA_STAT(x) (((x) >> 30) & 0x1) +#define C_000044_GUIDMA_STAT 0xBFFFFFFF +#define S_000044_GUIDMA_AK(x) (((x) & 0x1) << 30) +#define G_000044_GUIDMA_AK(x) (((x) >> 30) & 0x1) +#define C_000044_GUIDMA_AK 0xBFFFFFFF +#define S_000044_VIDDMA_STAT(x) (((x) & 0x1) << 31) +#define G_000044_VIDDMA_STAT(x) (((x) >> 31) & 0x1) +#define C_000044_VIDDMA_STAT 0x7FFFFFFF +#define S_000044_VIDDMA_AK(x) (((x) & 0x1) << 31) +#define G_000044_VIDDMA_AK(x) (((x) >> 31) & 0x1) +#define C_000044_VIDDMA_AK 0x7FFFFFFF +#define R_000050_CRTC_GEN_CNTL 0x000050 +#define S_000050_CRTC_DBL_SCAN_EN(x) (((x) & 0x1) << 0) +#define G_000050_CRTC_DBL_SCAN_EN(x) (((x) >> 0) & 0x1) +#define C_000050_CRTC_DBL_SCAN_EN 0xFFFFFFFE +#define S_000050_CRTC_INTERLACE_EN(x) (((x) & 0x1) << 1) +#define G_000050_CRTC_INTERLACE_EN(x) (((x) >> 1) & 0x1) +#define C_000050_CRTC_INTERLACE_EN 0xFFFFFFFD +#define S_000050_CRTC_C_SYNC_EN(x) (((x) & 0x1) << 4) +#define G_000050_CRTC_C_SYNC_EN(x) (((x) >> 4) & 0x1) +#define C_000050_CRTC_C_SYNC_EN 0xFFFFFFEF +#define S_000050_CRTC_PIX_WIDTH(x) (((x) & 0xF) << 8) +#define G_000050_CRTC_PIX_WIDTH(x) (((x) >> 8) & 0xF) +#define C_000050_CRTC_PIX_WIDTH 0xFFFFF0FF +#define S_000050_CRTC_ICON_EN(x) (((x) & 0x1) << 15) +#define G_000050_CRTC_ICON_EN(x) (((x) >> 15) & 0x1) +#define C_000050_CRTC_ICON_EN 0xFFFF7FFF +#define S_000050_CRTC_CUR_EN(x) (((x) & 0x1) << 16) +#define G_000050_CRTC_CUR_EN(x) (((x) >> 16) & 0x1) +#define C_000050_CRTC_CUR_EN 0xFFFEFFFF +#define S_000050_CRTC_VSTAT_MODE(x) (((x) & 0x3) << 17) +#define G_000050_CRTC_VSTAT_MODE(x) (((x) >> 17) & 0x3) +#define C_000050_CRTC_VSTAT_MODE 0xFFF9FFFF +#define S_000050_CRTC_CUR_MODE(x) (((x) & 0x7) << 20) +#define G_000050_CRTC_CUR_MODE(x) (((x) >> 20) & 0x7) +#define C_000050_CRTC_CUR_MODE 0xFF8FFFFF +#define S_000050_CRTC_EXT_DISP_EN(x) (((x) & 0x1) << 24) +#define G_000050_CRTC_EXT_DISP_EN(x) (((x) >> 24) & 0x1) +#define C_000050_CRTC_EXT_DISP_EN 0xFEFFFFFF +#define S_000050_CRTC_EN(x) (((x) & 0x1) << 25) +#define G_000050_CRTC_EN(x) (((x) >> 25) & 0x1) +#define C_000050_CRTC_EN 0xFDFFFFFF +#define S_000050_CRTC_DISP_REQ_EN_B(x) (((x) & 0x1) << 26) +#define G_000050_CRTC_DISP_REQ_EN_B(x) (((x) >> 26) & 0x1) +#define C_000050_CRTC_DISP_REQ_EN_B 0xFBFFFFFF +#define R_000054_CRTC_EXT_CNTL 0x000054 +#define S_000054_CRTC_VGA_XOVERSCAN(x) (((x) & 0x1) << 0) +#define G_000054_CRTC_VGA_XOVERSCAN(x) (((x) >> 0) & 0x1) +#define C_000054_CRTC_VGA_XOVERSCAN 0xFFFFFFFE +#define S_000054_VGA_BLINK_RATE(x) (((x) & 0x3) << 1) +#define G_000054_VGA_BLINK_RATE(x) (((x) >> 1) & 0x3) +#define C_000054_VGA_BLINK_RATE 0xFFFFFFF9 +#define S_000054_VGA_ATI_LINEAR(x) (((x) & 0x1) << 3) +#define G_000054_VGA_ATI_LINEAR(x) (((x) >> 3) & 0x1) +#define C_000054_VGA_ATI_LINEAR 0xFFFFFFF7 +#define S_000054_VGA_128KAP_PAGING(x) (((x) & 0x1) << 4) +#define G_000054_VGA_128KAP_PAGING(x) (((x) >> 4) & 0x1) +#define C_000054_VGA_128KAP_PAGING 0xFFFFFFEF +#define S_000054_VGA_TEXT_132(x) (((x) & 0x1) << 5) +#define G_000054_VGA_TEXT_132(x) (((x) >> 5) & 0x1) +#define C_000054_VGA_TEXT_132 0xFFFFFFDF +#define S_000054_VGA_XCRT_CNT_EN(x) (((x) & 0x1) << 6) +#define G_000054_VGA_XCRT_CNT_EN(x) (((x) >> 6) & 0x1) +#define C_000054_VGA_XCRT_CNT_EN 0xFFFFFFBF +#define S_000054_CRTC_HSYNC_DIS(x) (((x) & 0x1) << 8) +#define G_000054_CRTC_HSYNC_DIS(x) (((x) >> 8) & 0x1) +#define C_000054_CRTC_HSYNC_DIS 0xFFFFFEFF +#define S_000054_CRTC_VSYNC_DIS(x) (((x) & 0x1) << 9) +#define G_000054_CRTC_VSYNC_DIS(x) (((x) >> 9) & 0x1) +#define C_000054_CRTC_VSYNC_DIS 0xFFFFFDFF +#define S_000054_CRTC_DISPLAY_DIS(x) (((x) & 0x1) << 10) +#define G_000054_CRTC_DISPLAY_DIS(x) (((x) >> 10) & 0x1) +#define C_000054_CRTC_DISPLAY_DIS 0xFFFFFBFF +#define S_000054_CRTC_SYNC_TRISTATE(x) (((x) & 0x1) << 11) +#define G_000054_CRTC_SYNC_TRISTATE(x) (((x) >> 11) & 0x1) +#define C_000054_CRTC_SYNC_TRISTATE 0xFFFFF7FF +#define S_000054_CRTC_HSYNC_TRISTATE(x) (((x) & 0x1) << 12) +#define G_000054_CRTC_HSYNC_TRISTATE(x) (((x) >> 12) & 0x1) +#define C_000054_CRTC_HSYNC_TRISTATE 0xFFFFEFFF +#define S_000054_CRTC_VSYNC_TRISTATE(x) (((x) & 0x1) << 13) +#define G_000054_CRTC_VSYNC_TRISTATE(x) (((x) >> 13) & 0x1) +#define C_000054_CRTC_VSYNC_TRISTATE 0xFFFFDFFF +#define S_000054_CRT_ON(x) (((x) & 0x1) << 15) +#define G_000054_CRT_ON(x) (((x) >> 15) & 0x1) +#define C_000054_CRT_ON 0xFFFF7FFF +#define S_000054_VGA_CUR_B_TEST(x) (((x) & 0x1) << 17) +#define G_000054_VGA_CUR_B_TEST(x) (((x) >> 17) & 0x1) +#define C_000054_VGA_CUR_B_TEST 0xFFFDFFFF +#define S_000054_VGA_PACK_DIS(x) (((x) & 0x1) << 18) +#define G_000054_VGA_PACK_DIS(x) (((x) >> 18) & 0x1) +#define C_000054_VGA_PACK_DIS 0xFFFBFFFF +#define S_000054_VGA_MEM_PS_EN(x) (((x) & 0x1) << 19) +#define G_000054_VGA_MEM_PS_EN(x) (((x) >> 19) & 0x1) +#define C_000054_VGA_MEM_PS_EN 0xFFF7FFFF +#define S_000054_VCRTC_IDX_MASTER(x) (((x) & 0x7F) << 24) +#define G_000054_VCRTC_IDX_MASTER(x) (((x) >> 24) & 0x7F) +#define C_000054_VCRTC_IDX_MASTER 0x80FFFFFF +#define R_00023C_DISPLAY_BASE_ADDR 0x00023C +#define S_00023C_DISPLAY_BASE_ADDR(x) (((x) & 0xFFFFFFFF) << 0) +#define G_00023C_DISPLAY_BASE_ADDR(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_00023C_DISPLAY_BASE_ADDR 0x00000000 +#define R_000260_CUR_OFFSET 0x000260 +#define S_000260_CUR_OFFSET(x) (((x) & 0x7FFFFFF) << 0) +#define G_000260_CUR_OFFSET(x) (((x) >> 0) & 0x7FFFFFF) +#define C_000260_CUR_OFFSET 0xF8000000 +#define S_000260_CUR_LOCK(x) (((x) & 0x1) << 31) +#define G_000260_CUR_LOCK(x) (((x) >> 31) & 0x1) +#define C_000260_CUR_LOCK 0x7FFFFFFF +#define R_00033C_CRTC2_DISPLAY_BASE_ADDR 0x00033C +#define S_00033C_CRTC2_DISPLAY_BASE_ADDR(x) (((x) & 0xFFFFFFFF) << 0) +#define G_00033C_CRTC2_DISPLAY_BASE_ADDR(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_00033C_CRTC2_DISPLAY_BASE_ADDR 0x00000000 +#define R_000360_CUR2_OFFSET 0x000360 +#define S_000360_CUR2_OFFSET(x) (((x) & 0x7FFFFFF) << 0) +#define G_000360_CUR2_OFFSET(x) (((x) >> 0) & 0x7FFFFFF) +#define C_000360_CUR2_OFFSET 0xF8000000 +#define S_000360_CUR2_LOCK(x) (((x) & 0x1) << 31) +#define G_000360_CUR2_LOCK(x) (((x) >> 31) & 0x1) +#define C_000360_CUR2_LOCK 0x7FFFFFFF +#define R_0003C0_GENMO_WT 0x0003C0 +#define S_0003C0_GENMO_MONO_ADDRESS_B(x) (((x) & 0x1) << 0) +#define G_0003C0_GENMO_MONO_ADDRESS_B(x) (((x) >> 0) & 0x1) +#define C_0003C0_GENMO_MONO_ADDRESS_B 0xFFFFFFFE +#define S_0003C0_VGA_RAM_EN(x) (((x) & 0x1) << 1) +#define G_0003C0_VGA_RAM_EN(x) (((x) >> 1) & 0x1) +#define C_0003C0_VGA_RAM_EN 0xFFFFFFFD +#define S_0003C0_VGA_CKSEL(x) (((x) & 0x3) << 2) +#define G_0003C0_VGA_CKSEL(x) (((x) >> 2) & 0x3) +#define C_0003C0_VGA_CKSEL 0xFFFFFFF3 +#define S_0003C0_ODD_EVEN_MD_PGSEL(x) (((x) & 0x1) << 5) +#define G_0003C0_ODD_EVEN_MD_PGSEL(x) (((x) >> 5) & 0x1) +#define C_0003C0_ODD_EVEN_MD_PGSEL 0xFFFFFFDF +#define S_0003C0_VGA_HSYNC_POL(x) (((x) & 0x1) << 6) +#define G_0003C0_VGA_HSYNC_POL(x) (((x) >> 6) & 0x1) +#define C_0003C0_VGA_HSYNC_POL 0xFFFFFFBF +#define S_0003C0_VGA_VSYNC_POL(x) (((x) & 0x1) << 7) +#define G_0003C0_VGA_VSYNC_POL(x) (((x) >> 7) & 0x1) +#define C_0003C0_VGA_VSYNC_POL 0xFFFFFF7F +#define R_0003F8_CRTC2_GEN_CNTL 0x0003F8 +#define S_0003F8_CRTC2_DBL_SCAN_EN(x) (((x) & 0x1) << 0) +#define G_0003F8_CRTC2_DBL_SCAN_EN(x) (((x) >> 0) & 0x1) +#define C_0003F8_CRTC2_DBL_SCAN_EN 0xFFFFFFFE +#define S_0003F8_CRTC2_INTERLACE_EN(x) (((x) & 0x1) << 1) +#define G_0003F8_CRTC2_INTERLACE_EN(x) (((x) >> 1) & 0x1) +#define C_0003F8_CRTC2_INTERLACE_EN 0xFFFFFFFD +#define S_0003F8_CRTC2_SYNC_TRISTATE(x) (((x) & 0x1) << 4) +#define G_0003F8_CRTC2_SYNC_TRISTATE(x) (((x) >> 4) & 0x1) +#define C_0003F8_CRTC2_SYNC_TRISTATE 0xFFFFFFEF +#define S_0003F8_CRTC2_HSYNC_TRISTATE(x) (((x) & 0x1) << 5) +#define G_0003F8_CRTC2_HSYNC_TRISTATE(x) (((x) >> 5) & 0x1) +#define C_0003F8_CRTC2_HSYNC_TRISTATE 0xFFFFFFDF +#define S_0003F8_CRTC2_VSYNC_TRISTATE(x) (((x) & 0x1) << 6) +#define G_0003F8_CRTC2_VSYNC_TRISTATE(x) (((x) >> 6) & 0x1) +#define C_0003F8_CRTC2_VSYNC_TRISTATE 0xFFFFFFBF +#define S_0003F8_CRT2_ON(x) (((x) & 0x1) << 7) +#define G_0003F8_CRT2_ON(x) (((x) >> 7) & 0x1) +#define C_0003F8_CRT2_ON 0xFFFFFF7F +#define S_0003F8_CRTC2_PIX_WIDTH(x) (((x) & 0xF) << 8) +#define G_0003F8_CRTC2_PIX_WIDTH(x) (((x) >> 8) & 0xF) +#define C_0003F8_CRTC2_PIX_WIDTH 0xFFFFF0FF +#define S_0003F8_CRTC2_ICON_EN(x) (((x) & 0x1) << 15) +#define G_0003F8_CRTC2_ICON_EN(x) (((x) >> 15) & 0x1) +#define C_0003F8_CRTC2_ICON_EN 0xFFFF7FFF +#define S_0003F8_CRTC2_CUR_EN(x) (((x) & 0x1) << 16) +#define G_0003F8_CRTC2_CUR_EN(x) (((x) >> 16) & 0x1) +#define C_0003F8_CRTC2_CUR_EN 0xFFFEFFFF +#define S_0003F8_CRTC2_CUR_MODE(x) (((x) & 0x7) << 20) +#define G_0003F8_CRTC2_CUR_MODE(x) (((x) >> 20) & 0x7) +#define C_0003F8_CRTC2_CUR_MODE 0xFF8FFFFF +#define S_0003F8_CRTC2_DISPLAY_DIS(x) (((x) & 0x1) << 23) +#define G_0003F8_CRTC2_DISPLAY_DIS(x) (((x) >> 23) & 0x1) +#define C_0003F8_CRTC2_DISPLAY_DIS 0xFF7FFFFF +#define S_0003F8_CRTC2_EN(x) (((x) & 0x1) << 25) +#define G_0003F8_CRTC2_EN(x) (((x) >> 25) & 0x1) +#define C_0003F8_CRTC2_EN 0xFDFFFFFF +#define S_0003F8_CRTC2_DISP_REQ_EN_B(x) (((x) & 0x1) << 26) +#define G_0003F8_CRTC2_DISP_REQ_EN_B(x) (((x) >> 26) & 0x1) +#define C_0003F8_CRTC2_DISP_REQ_EN_B 0xFBFFFFFF +#define S_0003F8_CRTC2_C_SYNC_EN(x) (((x) & 0x1) << 27) +#define G_0003F8_CRTC2_C_SYNC_EN(x) (((x) >> 27) & 0x1) +#define C_0003F8_CRTC2_C_SYNC_EN 0xF7FFFFFF +#define S_0003F8_CRTC2_HSYNC_DIS(x) (((x) & 0x1) << 28) +#define G_0003F8_CRTC2_HSYNC_DIS(x) (((x) >> 28) & 0x1) +#define C_0003F8_CRTC2_HSYNC_DIS 0xEFFFFFFF +#define S_0003F8_CRTC2_VSYNC_DIS(x) (((x) & 0x1) << 29) +#define G_0003F8_CRTC2_VSYNC_DIS(x) (((x) >> 29) & 0x1) +#define C_0003F8_CRTC2_VSYNC_DIS 0xDFFFFFFF +#define R_000420_OV0_SCALE_CNTL 0x000420 +#define S_000420_OV0_NO_READ_BEHIND_SCAN(x) (((x) & 0x1) << 1) +#define G_000420_OV0_NO_READ_BEHIND_SCAN(x) (((x) >> 1) & 0x1) +#define C_000420_OV0_NO_READ_BEHIND_SCAN 0xFFFFFFFD +#define S_000420_OV0_HORZ_PICK_NEAREST(x) (((x) & 0x1) << 2) +#define G_000420_OV0_HORZ_PICK_NEAREST(x) (((x) >> 2) & 0x1) +#define C_000420_OV0_HORZ_PICK_NEAREST 0xFFFFFFFB +#define S_000420_OV0_VERT_PICK_NEAREST(x) (((x) & 0x1) << 3) +#define G_000420_OV0_VERT_PICK_NEAREST(x) (((x) >> 3) & 0x1) +#define C_000420_OV0_VERT_PICK_NEAREST 0xFFFFFFF7 +#define S_000420_OV0_SIGNED_UV(x) (((x) & 0x1) << 4) +#define G_000420_OV0_SIGNED_UV(x) (((x) >> 4) & 0x1) +#define C_000420_OV0_SIGNED_UV 0xFFFFFFEF +#define S_000420_OV0_GAMMA_SEL(x) (((x) & 0x7) << 5) +#define G_000420_OV0_GAMMA_SEL(x) (((x) >> 5) & 0x7) +#define C_000420_OV0_GAMMA_SEL 0xFFFFFF1F +#define S_000420_OV0_SURFACE_FORMAT(x) (((x) & 0xF) << 8) +#define G_000420_OV0_SURFACE_FORMAT(x) (((x) >> 8) & 0xF) +#define C_000420_OV0_SURFACE_FORMAT 0xFFFFF0FF +#define S_000420_OV0_ADAPTIVE_DEINT(x) (((x) & 0x1) << 12) +#define G_000420_OV0_ADAPTIVE_DEINT(x) (((x) >> 12) & 0x1) +#define C_000420_OV0_ADAPTIVE_DEINT 0xFFFFEFFF +#define S_000420_OV0_CRTC_SEL(x) (((x) & 0x1) << 14) +#define G_000420_OV0_CRTC_SEL(x) (((x) >> 14) & 0x1) +#define C_000420_OV0_CRTC_SEL 0xFFFFBFFF +#define S_000420_OV0_BURST_PER_PLANE(x) (((x) & 0x7F) << 16) +#define G_000420_OV0_BURST_PER_PLANE(x) (((x) >> 16) & 0x7F) +#define C_000420_OV0_BURST_PER_PLANE 0xFF80FFFF +#define S_000420_OV0_DOUBLE_BUFFER_REGS(x) (((x) & 0x1) << 24) +#define G_000420_OV0_DOUBLE_BUFFER_REGS(x) (((x) >> 24) & 0x1) +#define C_000420_OV0_DOUBLE_BUFFER_REGS 0xFEFFFFFF +#define S_000420_OV0_BANDWIDTH(x) (((x) & 0x1) << 26) +#define G_000420_OV0_BANDWIDTH(x) (((x) >> 26) & 0x1) +#define C_000420_OV0_BANDWIDTH 0xFBFFFFFF +#define S_000420_OV0_LIN_TRANS_BYPASS(x) (((x) & 0x1) << 28) +#define G_000420_OV0_LIN_TRANS_BYPASS(x) (((x) >> 28) & 0x1) +#define C_000420_OV0_LIN_TRANS_BYPASS 0xEFFFFFFF +#define S_000420_OV0_INT_EMU(x) (((x) & 0x1) << 29) +#define G_000420_OV0_INT_EMU(x) (((x) >> 29) & 0x1) +#define C_000420_OV0_INT_EMU 0xDFFFFFFF +#define S_000420_OV0_OVERLAY_EN(x) (((x) & 0x1) << 30) +#define G_000420_OV0_OVERLAY_EN(x) (((x) >> 30) & 0x1) +#define C_000420_OV0_OVERLAY_EN 0xBFFFFFFF +#define S_000420_OV0_SOFT_RESET(x) (((x) & 0x1) << 31) +#define G_000420_OV0_SOFT_RESET(x) (((x) >> 31) & 0x1) +#define C_000420_OV0_SOFT_RESET 0x7FFFFFFF +#define R_00070C_CP_RB_RPTR_ADDR 0x00070C +#define S_00070C_RB_RPTR_SWAP(x) (((x) & 0x3) << 0) +#define G_00070C_RB_RPTR_SWAP(x) (((x) >> 0) & 0x3) +#define C_00070C_RB_RPTR_SWAP 0xFFFFFFFC +#define S_00070C_RB_RPTR_ADDR(x) (((x) & 0x3FFFFFFF) << 2) +#define G_00070C_RB_RPTR_ADDR(x) (((x) >> 2) & 0x3FFFFFFF) +#define C_00070C_RB_RPTR_ADDR 0x00000003 +#define R_000740_CP_CSQ_CNTL 0x000740 +#define S_000740_CSQ_CNT_PRIMARY(x) (((x) & 0xFF) << 0) +#define G_000740_CSQ_CNT_PRIMARY(x) (((x) >> 0) & 0xFF) +#define C_000740_CSQ_CNT_PRIMARY 0xFFFFFF00 +#define S_000740_CSQ_CNT_INDIRECT(x) (((x) & 0xFF) << 8) +#define G_000740_CSQ_CNT_INDIRECT(x) (((x) >> 8) & 0xFF) +#define C_000740_CSQ_CNT_INDIRECT 0xFFFF00FF +#define S_000740_CSQ_MODE(x) (((x) & 0xF) << 28) +#define G_000740_CSQ_MODE(x) (((x) >> 28) & 0xF) +#define C_000740_CSQ_MODE 0x0FFFFFFF +#define R_000770_SCRATCH_UMSK 0x000770 +#define S_000770_SCRATCH_UMSK(x) (((x) & 0x3F) << 0) +#define G_000770_SCRATCH_UMSK(x) (((x) >> 0) & 0x3F) +#define C_000770_SCRATCH_UMSK 0xFFFFFFC0 +#define S_000770_SCRATCH_SWAP(x) (((x) & 0x3) << 16) +#define G_000770_SCRATCH_SWAP(x) (((x) >> 16) & 0x3) +#define C_000770_SCRATCH_SWAP 0xFFFCFFFF +#define R_000774_SCRATCH_ADDR 0x000774 +#define S_000774_SCRATCH_ADDR(x) (((x) & 0x7FFFFFF) << 5) +#define G_000774_SCRATCH_ADDR(x) (((x) >> 5) & 0x7FFFFFF) +#define C_000774_SCRATCH_ADDR 0x0000001F #define R_000E40_RBBM_STATUS 0x000E40 #define S_000E40_CMDFIFO_AVAIL(x) (((x) & 0x7F) << 0) #define G_000E40_CMDFIFO_AVAIL(x) (((x) >> 0) & 0x7F) diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 9c17b786982a..92f9cb74a7d2 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -1241,11 +1241,12 @@ static int r300_packet3_check(struct radeon_cs_parser *p, int r300_cs_parse(struct radeon_cs_parser *p) { struct radeon_cs_packet pkt; - struct r100_cs_track track; + struct r100_cs_track *track; int r; - r100_cs_track_clear(p->rdev, &track); - p->track = &track; + track = kzalloc(sizeof(*track), GFP_KERNEL); + r100_cs_track_clear(p->rdev, track); + p->track = track; do { r = r100_cs_packet_parse(p, &pkt, p->idx); if (r) { @@ -1275,9 +1276,50 @@ int r300_cs_parse(struct radeon_cs_parser *p) return 0; } -int r300_init(struct radeon_device *rdev) +void r300_set_reg_safe(struct radeon_device *rdev) { rdev->config.r300.reg_safe_bm = r300_reg_safe_bm; rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r300_reg_safe_bm); +} + +int r300_init(struct radeon_device *rdev) +{ + r300_set_reg_safe(rdev); return 0; } + +void r300_mc_program(struct radeon_device *rdev) +{ + struct r100_mc_save save; + int r; + + r = r100_debugfs_mc_info_init(rdev); + if (r) { + dev_err(rdev->dev, "Failed to create r100_mc debugfs file.\n"); + } + + /* Stops all mc clients */ + r100_mc_stop(rdev, &save); + /* Shutdown PCI/PCIE GART */ + radeon_gart_disable(rdev); + if (rdev->flags & RADEON_IS_AGP) { + WREG32(R_00014C_MC_AGP_LOCATION, + S_00014C_MC_AGP_START(rdev->mc.gtt_start >> 16) | + S_00014C_MC_AGP_TOP(rdev->mc.gtt_end >> 16)); + WREG32(R_000170_AGP_BASE, lower_32_bits(rdev->mc.agp_base)); + WREG32(R_00015C_AGP_BASE_2, + upper_32_bits(rdev->mc.agp_base) & 0xff); + } else { + WREG32(R_00014C_MC_AGP_LOCATION, 0x0FFFFFFF); + WREG32(R_000170_AGP_BASE, 0); + WREG32(R_00015C_AGP_BASE_2, 0); + } + /* Wait for mc idle */ + if (r300_mc_wait_for_idle(rdev)) + DRM_INFO("Failed to wait MC idle before programming MC.\n"); + /* Program MC, should be a 32bits limited address space */ + WREG32(R_000148_MC_FB_LOCATION, + S_000148_MC_FB_START(rdev->mc.vram_start >> 16) | + S_000148_MC_FB_TOP(rdev->mc.vram_end >> 16)); + r100_mc_resume(rdev, &save); +} diff --git a/drivers/gpu/drm/radeon/r300d.h b/drivers/gpu/drm/radeon/r300d.h index 63ec076f2cd4..d4fa3eb1074f 100644 --- a/drivers/gpu/drm/radeon/r300d.h +++ b/drivers/gpu/drm/radeon/r300d.h @@ -73,4 +73,29 @@ #define CP_PACKET0_GET_ONE_REG_WR(h) (((h) >> 15) & 1) #define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF) +/* Registers */ +#define R_000148_MC_FB_LOCATION 0x000148 +#define S_000148_MC_FB_START(x) (((x) & 0xFFFF) << 0) +#define G_000148_MC_FB_START(x) (((x) >> 0) & 0xFFFF) +#define C_000148_MC_FB_START 0xFFFF0000 +#define S_000148_MC_FB_TOP(x) (((x) & 0xFFFF) << 16) +#define G_000148_MC_FB_TOP(x) (((x) >> 16) & 0xFFFF) +#define C_000148_MC_FB_TOP 0x0000FFFF +#define R_00014C_MC_AGP_LOCATION 0x00014C +#define S_00014C_MC_AGP_START(x) (((x) & 0xFFFF) << 0) +#define G_00014C_MC_AGP_START(x) (((x) >> 0) & 0xFFFF) +#define C_00014C_MC_AGP_START 0xFFFF0000 +#define S_00014C_MC_AGP_TOP(x) (((x) & 0xFFFF) << 16) +#define G_00014C_MC_AGP_TOP(x) (((x) >> 16) & 0xFFFF) +#define C_00014C_MC_AGP_TOP 0x0000FFFF +#define R_00015C_AGP_BASE_2 0x00015C +#define S_00015C_AGP_BASE_ADDR_2(x) (((x) & 0xF) << 0) +#define G_00015C_AGP_BASE_ADDR_2(x) (((x) >> 0) & 0xF) +#define C_00015C_AGP_BASE_ADDR_2 0xFFFFFFF0 +#define R_000170_AGP_BASE 0x000170 +#define S_000170_AGP_BASE_ADDR(x) (((x) & 0xFFFFFFFF) << 0) +#define G_000170_AGP_BASE_ADDR(x) (((x) >> 0) & 0xFFFFFFFF) +#define C_000170_AGP_BASE_ADDR 0x00000000 + + #endif diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index 551d6996d3f2..e57b9ba4aaf3 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c @@ -29,48 +29,13 @@ #include "drmP.h" #include "radeon_reg.h" #include "radeon.h" +#include "atom.h" #include "r420d.h" -/* r420,r423,rv410 depends on : */ -void r100_pci_gart_disable(struct radeon_device *rdev); -void r100_hdp_reset(struct radeon_device *rdev); -void r100_mc_setup(struct radeon_device *rdev); -int r100_gui_wait_for_idle(struct radeon_device *rdev); -void r100_mc_disable_clients(struct radeon_device *rdev); -void r300_vram_info(struct radeon_device *rdev); -int r300_mc_wait_for_idle(struct radeon_device *rdev); -int rv370_pcie_gart_enable(struct radeon_device *rdev); -void rv370_pcie_gart_disable(struct radeon_device *rdev); - -/* This files gather functions specifics to : - * r420,r423,rv410 - * - * Some of these functions might be used by newer ASICs. - */ -void r420_gpu_init(struct radeon_device *rdev); -int r420_debugfs_pipes_info_init(struct radeon_device *rdev); - - -/* - * MC - */ int r420_mc_init(struct radeon_device *rdev) { int r; - if (r100_debugfs_rbbm_init(rdev)) { - DRM_ERROR("Failed to register debugfs file for RBBM !\n"); - } - if (r420_debugfs_pipes_info_init(rdev)) { - DRM_ERROR("Failed to register debugfs file for pipes !\n"); - } - - r420_gpu_init(rdev); - r100_pci_gart_disable(rdev); - if (rdev->flags & RADEON_IS_PCIE) { - rv370_pcie_gart_disable(rdev); - } - /* Setup GPU memory space */ rdev->mc.vram_location = 0xFFFFFFFFUL; rdev->mc.gtt_location = 0xFFFFFFFFUL; @@ -88,38 +53,9 @@ int r420_mc_init(struct radeon_device *rdev) if (r) { return r; } - - /* Program GPU memory space */ - r100_mc_disable_clients(rdev); - if (r300_mc_wait_for_idle(rdev)) { - printk(KERN_WARNING "Failed to wait MC idle while " - "programming pipes. Bad things might happen.\n"); - } - r100_mc_setup(rdev); return 0; } -void r420_mc_fini(struct radeon_device *rdev) -{ - if (rdev->flags & RADEON_IS_PCIE) { - rv370_pcie_gart_disable(rdev); - radeon_gart_table_vram_free(rdev); - } else { - r100_pci_gart_disable(rdev); - radeon_gart_table_ram_free(rdev); - } - radeon_gart_fini(rdev); -} - - -/* - * Global GPU functions - */ -void r420_errata(struct radeon_device *rdev) -{ - rdev->pll_errata = 0; -} - void r420_pipes_init(struct radeon_device *rdev) { unsigned tmp; @@ -185,25 +121,216 @@ void r420_pipes_init(struct radeon_device *rdev) rdev->num_gb_pipes, rdev->num_z_pipes); } -void r420_gpu_init(struct radeon_device *rdev) +u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg) { - r100_hdp_reset(rdev); + u32 r; + + WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg)); + r = RREG32(R_0001FC_MC_IND_DATA); + return r; +} + +void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v) +{ + WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg) | + S_0001F8_MC_IND_WR_EN(1)); + WREG32(R_0001FC_MC_IND_DATA, v); +} + +static void r420_debugfs(struct radeon_device *rdev) +{ + if (r100_debugfs_rbbm_init(rdev)) { + DRM_ERROR("Failed to register debugfs file for RBBM !\n"); + } + if (r420_debugfs_pipes_info_init(rdev)) { + DRM_ERROR("Failed to register debugfs file for pipes !\n"); + } +} + +static void r420_clock_resume(struct radeon_device *rdev) +{ + u32 sclk_cntl; + sclk_cntl = RREG32_PLL(R_00000D_SCLK_CNTL); + sclk_cntl |= S_00000D_FORCE_CP(1) | S_00000D_FORCE_VIP(1); + if (rdev->family == CHIP_R420) + sclk_cntl |= S_00000D_FORCE_PX(1) | S_00000D_FORCE_TX(1); + WREG32_PLL(R_00000D_SCLK_CNTL, sclk_cntl); +} + +int r420_resume(struct radeon_device *rdev) +{ + int r; + + /* Resume clock before doing reset */ + r420_clock_resume(rdev); + /* Reset gpu before posting otherwise ATOM will enter infinite loop */ + if (radeon_gpu_reset(rdev)) { + dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", + RREG32(R_000E40_RBBM_STATUS), + RREG32(R_0007C0_CP_STAT)); + } + /* check if cards are posted or not */ + if (rdev->is_atom_bios) { + atom_asic_init(rdev->mode_info.atom_context); + } else { + radeon_combios_asic_init(rdev->ddev); + } + /* Resume clock after posting */ + r420_clock_resume(rdev); + r300_mc_program(rdev); + /* Initialize GART (initialize after TTM so we can allocate + * memory through TTM but finalize after TTM) */ + r = radeon_gart_enable(rdev); + if (r) { + dev_err(rdev->dev, "failled initializing GART (%d).\n", r); + return r; + } r420_pipes_init(rdev); - if (r300_mc_wait_for_idle(rdev)) { - printk(KERN_WARNING "Failed to wait MC idle while " - "programming pipes. Bad things might happen.\n"); + /* Enable IRQ */ + rdev->irq.sw_int = true; + r100_irq_set(rdev); + /* 1M ring buffer */ + r = r100_cp_init(rdev, 1024 * 1024); + if (r) { + dev_err(rdev->dev, "failled initializing CP (%d).\n", r); + return r; + } + r = r100_wb_init(rdev); + if (r) { + dev_err(rdev->dev, "failled initializing WB (%d).\n", r); } + r = r100_ib_init(rdev); + if (r) { + dev_err(rdev->dev, "failled initializing IB (%d).\n", r); + return r; + } + return 0; } +int r420_suspend(struct radeon_device *rdev) +{ + r100_cp_disable(rdev); + r100_wb_disable(rdev); + r100_irq_disable(rdev); + radeon_gart_disable(rdev); + return 0; +} -/* - * r420,r423,rv410 VRAM info - */ -void r420_vram_info(struct radeon_device *rdev) +void r420_fini(struct radeon_device *rdev) { - r300_vram_info(rdev); + r100_cp_fini(rdev); + r100_wb_fini(rdev); + r100_ib_fini(rdev); + radeon_gem_fini(rdev); + if (rdev->flags & RADEON_IS_PCIE) { + rv370_pcie_gart_disable(rdev); + radeon_gart_table_vram_free(rdev); + } else { + r100_pci_gart_disable(rdev); + radeon_gart_table_ram_free(rdev); + } + radeon_gart_fini(rdev); + radeon_agp_fini(rdev); + radeon_irq_kms_fini(rdev); + radeon_fence_driver_fini(rdev); + radeon_object_fini(rdev); + if (rdev->is_atom_bios) { + radeon_atombios_fini(rdev); + } else { + radeon_combios_fini(rdev); + } + kfree(rdev->bios); + rdev->bios = NULL; } +int r420_init(struct radeon_device *rdev) +{ + int r; + + rdev->new_init_path = true; + /* Initialize scratch registers */ + radeon_scratch_init(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); + /* TODO: disable VGA need to use VGA request */ + /* BIOS*/ + if (!radeon_get_bios(rdev)) { + if (ASIC_IS_AVIVO(rdev)) + return -EINVAL; + } + if (rdev->is_atom_bios) { + r = radeon_atombios_init(rdev); + if (r) { + return r; + } + } else { + r = radeon_combios_init(rdev); + if (r) { + return r; + } + } + /* Reset gpu before posting otherwise ATOM will enter infinite loop */ + if (radeon_gpu_reset(rdev)) { + dev_warn(rdev->dev, + "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", + RREG32(R_000E40_RBBM_STATUS), + RREG32(R_0007C0_CP_STAT)); + } + /* check if cards are posted or not */ + if (!radeon_card_posted(rdev) && rdev->bios) { + DRM_INFO("GPU not posted. posting now...\n"); + if (rdev->is_atom_bios) { + atom_asic_init(rdev->mode_info.atom_context); + } else { + radeon_combios_asic_init(rdev->ddev); + } + } + /* Initialize clocks */ + radeon_get_clock_info(rdev->ddev); + /* Get vram informations */ + r300_vram_info(rdev); + /* Initialize memory controller (also test AGP) */ + r = r420_mc_init(rdev); + if (r) { + return r; + } + r420_debugfs(rdev); + /* Fence driver */ + r = radeon_fence_driver_init(rdev); + if (r) { + return r; + } + r = radeon_irq_kms_init(rdev); + if (r) { + return r; + } + /* Memory manager */ + r = radeon_object_init(rdev); + if (r) { + return r; + } + r300_set_reg_safe(rdev); + r = r420_resume(rdev); + if (r) { + /* Somethings want wront with the accel init stop accel */ + dev_err(rdev->dev, "Disabling GPU acceleration\n"); + r420_suspend(rdev); + r100_cp_fini(rdev); + r100_wb_fini(rdev); + r100_ib_fini(rdev); + if (rdev->flags & RADEON_IS_PCIE) { + rv370_pcie_gart_disable(rdev); + radeon_gart_table_vram_free(rdev); + } else { + r100_pci_gart_disable(rdev); + radeon_gart_table_ram_free(rdev); + } + radeon_gart_fini(rdev); + radeon_agp_fini(rdev); + radeon_irq_kms_fini(rdev); + } + return 0; +} /* * Debugfs info @@ -238,19 +365,3 @@ int r420_debugfs_pipes_info_init(struct radeon_device *rdev) return 0; #endif } - -u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg) -{ - u32 r; - - WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg)); - r = RREG32(R_0001FC_MC_IND_DATA); - return r; -} - -void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v) -{ - WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg) | - S_0001F8_MC_IND_WR_EN(1)); - WREG32(R_0001FC_MC_IND_DATA, v); -} diff --git a/drivers/gpu/drm/radeon/r420d.h b/drivers/gpu/drm/radeon/r420d.h index 8b946c1883ba..a48a7db1e2aa 100644 --- a/drivers/gpu/drm/radeon/r420d.h +++ b/drivers/gpu/drm/radeon/r420d.h @@ -39,5 +39,211 @@ #define S_0001FC_MC_IND_DATA(x) (((x) & 0xFFFFFFFF) << 0) #define G_0001FC_MC_IND_DATA(x) (((x) >> 0) & 0xFFFFFFFF) #define C_0001FC_MC_IND_DATA 0x00000000 +#define R_0007C0_CP_STAT 0x0007C0 +#define S_0007C0_MRU_BUSY(x) (((x) & 0x1) << 0) +#define G_0007C0_MRU_BUSY(x) (((x) >> 0) & 0x1) +#define C_0007C0_MRU_BUSY 0xFFFFFFFE +#define S_0007C0_MWU_BUSY(x) (((x) & 0x1) << 1) +#define G_0007C0_MWU_BUSY(x) (((x) >> 1) & 0x1) +#define C_0007C0_MWU_BUSY 0xFFFFFFFD +#define S_0007C0_RSIU_BUSY(x) (((x) & 0x1) << 2) +#define G_0007C0_RSIU_BUSY(x) (((x) >> 2) & 0x1) +#define C_0007C0_RSIU_BUSY 0xFFFFFFFB +#define S_0007C0_RCIU_BUSY(x) (((x) & 0x1) << 3) +#define G_0007C0_RCIU_BUSY(x) (((x) >> 3) & 0x1) +#define C_0007C0_RCIU_BUSY 0xFFFFFFF7 +#define S_0007C0_CSF_PRIMARY_BUSY(x) (((x) & 0x1) << 9) +#define G_0007C0_CSF_PRIMARY_BUSY(x) (((x) >> 9) & 0x1) +#define C_0007C0_CSF_PRIMARY_BUSY 0xFFFFFDFF +#define S_0007C0_CSF_INDIRECT_BUSY(x) (((x) & 0x1) << 10) +#define G_0007C0_CSF_INDIRECT_BUSY(x) (((x) >> 10) & 0x1) +#define C_0007C0_CSF_INDIRECT_BUSY 0xFFFFFBFF +#define S_0007C0_CSQ_PRIMARY_BUSY(x) (((x) & 0x1) << 11) +#define G_0007C0_CSQ_PRIMARY_BUSY(x) (((x) >> 11) & 0x1) +#define C_0007C0_CSQ_PRIMARY_BUSY 0xFFFFF7FF +#define S_0007C0_CSQ_INDIRECT_BUSY(x) (((x) & 0x1) << 12) +#define G_0007C0_CSQ_INDIRECT_BUSY(x) (((x) >> 12) & 0x1) +#define C_0007C0_CSQ_INDIRECT_BUSY 0xFFFFEFFF +#define S_0007C0_CSI_BUSY(x) (((x) & 0x1) << 13) +#define G_0007C0_CSI_BUSY(x) (((x) >> 13) & 0x1) +#define C_0007C0_CSI_BUSY 0xFFFFDFFF +#define S_0007C0_CSF_INDIRECT2_BUSY(x) (((x) & 0x1) << 14) +#define G_0007C0_CSF_INDIRECT2_BUSY(x) (((x) >> 14) & 0x1) +#define C_0007C0_CSF_INDIRECT2_BUSY 0xFFFFBFFF +#define S_0007C0_CSQ_INDIRECT2_BUSY(x) (((x) & 0x1) << 15) +#define G_0007C0_CSQ_INDIRECT2_BUSY(x) (((x) >> 15) & 0x1) +#define C_0007C0_CSQ_INDIRECT2_BUSY 0xFFFF7FFF +#define S_0007C0_GUIDMA_BUSY(x) (((x) & 0x1) << 28) +#define G_0007C0_GUIDMA_BUSY(x) (((x) >> 28) & 0x1) +#define C_0007C0_GUIDMA_BUSY 0xEFFFFFFF +#define S_0007C0_VIDDMA_BUSY(x) (((x) & 0x1) << 29) +#define G_0007C0_VIDDMA_BUSY(x) (((x) >> 29) & 0x1) +#define C_0007C0_VIDDMA_BUSY 0xDFFFFFFF +#define S_0007C0_CMDSTRM_BUSY(x) (((x) & 0x1) << 30) +#define G_0007C0_CMDSTRM_BUSY(x) (((x) >> 30) & 0x1) +#define C_0007C0_CMDSTRM_BUSY 0xBFFFFFFF +#define S_0007C0_CP_BUSY(x) (((x) & 0x1) << 31) +#define G_0007C0_CP_BUSY(x) (((x) >> 31) & 0x1) +#define C_0007C0_CP_BUSY 0x7FFFFFFF +#define R_000E40_RBBM_STATUS 0x000E40 +#define S_000E40_CMDFIFO_AVAIL(x) (((x) & 0x7F) << 0) +#define G_000E40_CMDFIFO_AVAIL(x) (((x) >> 0) & 0x7F) +#define C_000E40_CMDFIFO_AVAIL 0xFFFFFF80 +#define S_000E40_HIRQ_ON_RBB(x) (((x) & 0x1) << 8) +#define G_000E40_HIRQ_ON_RBB(x) (((x) >> 8) & 0x1) +#define C_000E40_HIRQ_ON_RBB 0xFFFFFEFF +#define S_000E40_CPRQ_ON_RBB(x) (((x) & 0x1) << 9) +#define G_000E40_CPRQ_ON_RBB(x) (((x) >> 9) & 0x1) +#define C_000E40_CPRQ_ON_RBB 0xFFFFFDFF +#define S_000E40_CFRQ_ON_RBB(x) (((x) & 0x1) << 10) +#define G_000E40_CFRQ_ON_RBB(x) (((x) >> 10) & 0x1) +#define C_000E40_CFRQ_ON_RBB 0xFFFFFBFF +#define S_000E40_HIRQ_IN_RTBUF(x) (((x) & 0x1) << 11) +#define G_000E40_HIRQ_IN_RTBUF(x) (((x) >> 11) & 0x1) +#define C_000E40_HIRQ_IN_RTBUF 0xFFFFF7FF +#define S_000E40_CPRQ_IN_RTBUF(x) (((x) & 0x1) << 12) +#define G_000E40_CPRQ_IN_RTBUF(x) (((x) >> 12) & 0x1) +#define C_000E40_CPRQ_IN_RTBUF 0xFFFFEFFF +#define S_000E40_CFRQ_IN_RTBUF(x) (((x) & 0x1) << 13) +#define G_000E40_CFRQ_IN_RTBUF(x) (((x) >> 13) & 0x1) +#define C_000E40_CFRQ_IN_RTBUF 0xFFFFDFFF +#define S_000E40_CF_PIPE_BUSY(x) (((x) & 0x1) << 14) +#define G_000E40_CF_PIPE_BUSY(x) (((x) >> 14) & 0x1) +#define C_000E40_CF_PIPE_BUSY 0xFFFFBFFF +#define S_000E40_ENG_EV_BUSY(x) (((x) & 0x1) << 15) +#define G_000E40_ENG_EV_BUSY(x) (((x) >> 15) & 0x1) +#define C_000E40_ENG_EV_BUSY 0xFFFF7FFF +#define S_000E40_CP_CMDSTRM_BUSY(x) (((x) & 0x1) << 16) +#define G_000E40_CP_CMDSTRM_BUSY(x) (((x) >> 16) & 0x1) +#define C_000E40_CP_CMDSTRM_BUSY 0xFFFEFFFF +#define S_000E40_E2_BUSY(x) (((x) & 0x1) << 17) +#define G_000E40_E2_BUSY(x) (((x) >> 17) & 0x1) +#define C_000E40_E2_BUSY 0xFFFDFFFF +#define S_000E40_RB2D_BUSY(x) (((x) & 0x1) << 18) +#define G_000E40_RB2D_BUSY(x) (((x) >> 18) & 0x1) +#define C_000E40_RB2D_BUSY 0xFFFBFFFF +#define S_000E40_RB3D_BUSY(x) (((x) & 0x1) << 19) +#define G_000E40_RB3D_BUSY(x) (((x) >> 19) & 0x1) +#define C_000E40_RB3D_BUSY 0xFFF7FFFF +#define S_000E40_VAP_BUSY(x) (((x) & 0x1) << 20) +#define G_000E40_VAP_BUSY(x) (((x) >> 20) & 0x1) +#define C_000E40_VAP_BUSY 0xFFEFFFFF +#define S_000E40_RE_BUSY(x) (((x) & 0x1) << 21) +#define G_000E40_RE_BUSY(x) (((x) >> 21) & 0x1) +#define C_000E40_RE_BUSY 0xFFDFFFFF +#define S_000E40_TAM_BUSY(x) (((x) & 0x1) << 22) +#define G_000E40_TAM_BUSY(x) (((x) >> 22) & 0x1) +#define C_000E40_TAM_BUSY 0xFFBFFFFF +#define S_000E40_TDM_BUSY(x) (((x) & 0x1) << 23) +#define G_000E40_TDM_BUSY(x) (((x) >> 23) & 0x1) +#define C_000E40_TDM_BUSY 0xFF7FFFFF +#define S_000E40_PB_BUSY(x) (((x) & 0x1) << 24) +#define G_000E40_PB_BUSY(x) (((x) >> 24) & 0x1) +#define C_000E40_PB_BUSY 0xFEFFFFFF +#define S_000E40_TIM_BUSY(x) (((x) & 0x1) << 25) +#define G_000E40_TIM_BUSY(x) (((x) >> 25) & 0x1) +#define C_000E40_TIM_BUSY 0xFDFFFFFF +#define S_000E40_GA_BUSY(x) (((x) & 0x1) << 26) +#define G_000E40_GA_BUSY(x) (((x) >> 26) & 0x1) +#define C_000E40_GA_BUSY 0xFBFFFFFF +#define S_000E40_CBA2D_BUSY(x) (((x) & 0x1) << 27) +#define G_000E40_CBA2D_BUSY(x) (((x) >> 27) & 0x1) +#define C_000E40_CBA2D_BUSY 0xF7FFFFFF +#define S_000E40_GUI_ACTIVE(x) (((x) & 0x1) << 31) +#define G_000E40_GUI_ACTIVE(x) (((x) >> 31) & 0x1) +#define C_000E40_GUI_ACTIVE 0x7FFFFFFF + +/* CLK registers */ +#define R_00000D_SCLK_CNTL 0x00000D +#define S_00000D_SCLK_SRC_SEL(x) (((x) & 0x7) << 0) +#define G_00000D_SCLK_SRC_SEL(x) (((x) >> 0) & 0x7) +#define C_00000D_SCLK_SRC_SEL 0xFFFFFFF8 +#define S_00000D_CP_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 3) +#define G_00000D_CP_MAX_DYN_STOP_LAT(x) (((x) >> 3) & 0x1) +#define C_00000D_CP_MAX_DYN_STOP_LAT 0xFFFFFFF7 +#define S_00000D_HDP_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 4) +#define G_00000D_HDP_MAX_DYN_STOP_LAT(x) (((x) >> 4) & 0x1) +#define C_00000D_HDP_MAX_DYN_STOP_LAT 0xFFFFFFEF +#define S_00000D_TV_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 5) +#define G_00000D_TV_MAX_DYN_STOP_LAT(x) (((x) >> 5) & 0x1) +#define C_00000D_TV_MAX_DYN_STOP_LAT 0xFFFFFFDF +#define S_00000D_E2_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 6) +#define G_00000D_E2_MAX_DYN_STOP_LAT(x) (((x) >> 6) & 0x1) +#define C_00000D_E2_MAX_DYN_STOP_LAT 0xFFFFFFBF +#define S_00000D_SE_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 7) +#define G_00000D_SE_MAX_DYN_STOP_LAT(x) (((x) >> 7) & 0x1) +#define C_00000D_SE_MAX_DYN_STOP_LAT 0xFFFFFF7F +#define S_00000D_IDCT_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 8) +#define G_00000D_IDCT_MAX_DYN_STOP_LAT(x) (((x) >> 8) & 0x1) +#define C_00000D_IDCT_MAX_DYN_STOP_LAT 0xFFFFFEFF +#define S_00000D_VIP_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 9) +#define G_00000D_VIP_MAX_DYN_STOP_LAT(x) (((x) >> 9) & 0x1) +#define C_00000D_VIP_MAX_DYN_STOP_LAT 0xFFFFFDFF +#define S_00000D_RE_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 10) +#define G_00000D_RE_MAX_DYN_STOP_LAT(x) (((x) >> 10) & 0x1) +#define C_00000D_RE_MAX_DYN_STOP_LAT 0xFFFFFBFF +#define S_00000D_PB_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 11) +#define G_00000D_PB_MAX_DYN_STOP_LAT(x) (((x) >> 11) & 0x1) +#define C_00000D_PB_MAX_DYN_STOP_LAT 0xFFFFF7FF +#define S_00000D_TAM_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 12) +#define G_00000D_TAM_MAX_DYN_STOP_LAT(x) (((x) >> 12) & 0x1) +#define C_00000D_TAM_MAX_DYN_STOP_LAT 0xFFFFEFFF +#define S_00000D_TDM_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 13) +#define G_00000D_TDM_MAX_DYN_STOP_LAT(x) (((x) >> 13) & 0x1) +#define C_00000D_TDM_MAX_DYN_STOP_LAT 0xFFFFDFFF +#define S_00000D_RB_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 14) +#define G_00000D_RB_MAX_DYN_STOP_LAT(x) (((x) >> 14) & 0x1) +#define C_00000D_RB_MAX_DYN_STOP_LAT 0xFFFFBFFF +#define S_00000D_FORCE_DISP2(x) (((x) & 0x1) << 15) +#define G_00000D_FORCE_DISP2(x) (((x) >> 15) & 0x1) +#define C_00000D_FORCE_DISP2 0xFFFF7FFF +#define S_00000D_FORCE_CP(x) (((x) & 0x1) << 16) +#define G_00000D_FORCE_CP(x) (((x) >> 16) & 0x1) +#define C_00000D_FORCE_CP 0xFFFEFFFF +#define S_00000D_FORCE_HDP(x) (((x) & 0x1) << 17) +#define G_00000D_FORCE_HDP(x) (((x) >> 17) & 0x1) +#define C_00000D_FORCE_HDP 0xFFFDFFFF +#define S_00000D_FORCE_DISP1(x) (((x) & 0x1) << 18) +#define G_00000D_FORCE_DISP1(x) (((x) >> 18) & 0x1) +#define C_00000D_FORCE_DISP1 0xFFFBFFFF +#define S_00000D_FORCE_TOP(x) (((x) & 0x1) << 19) +#define G_00000D_FORCE_TOP(x) (((x) >> 19) & 0x1) +#define C_00000D_FORCE_TOP 0xFFF7FFFF +#define S_00000D_FORCE_E2(x) (((x) & 0x1) << 20) +#define G_00000D_FORCE_E2(x) (((x) >> 20) & 0x1) +#define C_00000D_FORCE_E2 0xFFEFFFFF +#define S_00000D_FORCE_SE(x) (((x) & 0x1) << 21) +#define G_00000D_FORCE_SE(x) (((x) >> 21) & 0x1) +#define C_00000D_FORCE_SE 0xFFDFFFFF +#define S_00000D_FORCE_IDCT(x) (((x) & 0x1) << 22) +#define G_00000D_FORCE_IDCT(x) (((x) >> 22) & 0x1) +#define C_00000D_FORCE_IDCT 0xFFBFFFFF +#define S_00000D_FORCE_VIP(x) (((x) & 0x1) << 23) +#define G_00000D_FORCE_VIP(x) (((x) >> 23) & 0x1) +#define C_00000D_FORCE_VIP 0xFF7FFFFF +#define S_00000D_FORCE_RE(x) (((x) & 0x1) << 24) +#define G_00000D_FORCE_RE(x) (((x) >> 24) & 0x1) +#define C_00000D_FORCE_RE 0xFEFFFFFF +#define S_00000D_FORCE_PB(x) (((x) & 0x1) << 25) +#define G_00000D_FORCE_PB(x) (((x) >> 25) & 0x1) +#define C_00000D_FORCE_PB 0xFDFFFFFF +#define S_00000D_FORCE_PX(x) (((x) & 0x1) << 26) +#define G_00000D_FORCE_PX(x) (((x) >> 26) & 0x1) +#define C_00000D_FORCE_PX 0xFBFFFFFF +#define S_00000D_FORCE_TX(x) (((x) & 0x1) << 27) +#define G_00000D_FORCE_TX(x) (((x) >> 27) & 0x1) +#define C_00000D_FORCE_TX 0xF7FFFFFF +#define S_00000D_FORCE_RB(x) (((x) & 0x1) << 28) +#define G_00000D_FORCE_RB(x) (((x) >> 28) & 0x1) +#define C_00000D_FORCE_RB 0xEFFFFFFF +#define S_00000D_FORCE_TV_SCLK(x) (((x) & 0x1) << 29) +#define G_00000D_FORCE_TV_SCLK(x) (((x) >> 29) & 0x1) +#define C_00000D_FORCE_TV_SCLK 0xDFFFFFFF +#define S_00000D_FORCE_SUBPIC(x) (((x) & 0x1) << 30) +#define G_00000D_FORCE_SUBPIC(x) (((x) >> 30) & 0x1) +#define C_00000D_FORCE_SUBPIC 0xBFFFFFFF +#define S_00000D_FORCE_OV0(x) (((x) & 0x1) << 31) +#define G_00000D_FORCE_OV0(x) (((x) >> 31) & 0x1) +#define C_00000D_FORCE_OV0 0x7FFFFFFF #endif diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 23ede0e4783e..e314756dacc3 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -690,6 +690,7 @@ typedef uint32_t (*radeon_rreg_t)(struct radeon_device*, uint32_t); typedef void (*radeon_wreg_t)(struct radeon_device*, uint32_t, uint32_t); struct radeon_device { + struct device *dev; struct drm_device *ddev; struct pci_dev *pdev; /* ASIC */ @@ -936,16 +937,45 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v) /* Common functions */ int radeon_modeset_init(struct radeon_device *rdev); void radeon_modeset_fini(struct radeon_device *rdev); +extern bool radeon_card_posted(struct radeon_device *rdev); /* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */ -void r100_cp_disable(struct radeon_device *rdev); +struct r100_mc_save { + u32 GENMO_WT; + u32 CRTC_EXT_CNTL; + u32 CRTC_GEN_CNTL; + u32 CRTC2_GEN_CNTL; + u32 CUR_OFFSET; + u32 CUR2_OFFSET; +}; +extern void r100_cp_disable(struct radeon_device *rdev); +extern int r100_cp_init(struct radeon_device *rdev, unsigned ring_size); +extern void r100_cp_fini(struct radeon_device *rdev); void r100_pci_gart_tlb_flush(struct radeon_device *rdev); int r100_pci_gart_enable(struct radeon_device *rdev); void r100_pci_gart_disable(struct radeon_device *rdev); int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); +extern int r100_debugfs_mc_info_init(struct radeon_device *rdev); +extern int r100_gui_wait_for_idle(struct radeon_device *rdev); +extern void r100_ib_fini(struct radeon_device *rdev); +extern int r100_ib_init(struct radeon_device *rdev); +extern void r100_irq_disable(struct radeon_device *rdev); +extern int r100_irq_set(struct radeon_device *rdev); +extern void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save); +extern void r100_mc_resume(struct radeon_device *rdev, struct r100_mc_save *save); +extern void r100_wb_disable(struct radeon_device *rdev); +extern void r100_wb_fini(struct radeon_device *rdev); +extern int r100_wb_init(struct radeon_device *rdev); + +/* r300,r350,rv350,rv370,rv380 */ +extern void r300_set_reg_safe(struct radeon_device *rdev); +extern void r300_mc_program(struct radeon_device *rdev); +extern void r300_vram_info(struct radeon_device *rdev); +extern void rv370_pcie_gart_disable(struct radeon_device *rdev); /* r420,r423,rv410 */ u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg); void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v); +extern int r420_debugfs_pipes_info_init(struct radeon_device *rdev); #endif diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index f9c8f9a041db..8f27be31e094 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -189,31 +189,34 @@ static struct radeon_asic r300_asic = { /* * r420,r423,rv410 */ -void r420_errata(struct radeon_device *rdev); -void r420_vram_info(struct radeon_device *rdev); -int r420_mc_init(struct radeon_device *rdev); -void r420_mc_fini(struct radeon_device *rdev); +extern int r420_init(struct radeon_device *rdev); +extern void r420_fini(struct radeon_device *rdev); +extern int r420_suspend(struct radeon_device *rdev); +extern int r420_resume(struct radeon_device *rdev); static struct radeon_asic r420_asic = { - .init = &r300_init, - .errata = &r420_errata, - .vram_info = &r420_vram_info, + .init = &r420_init, + .fini = &r420_fini, + .suspend = &r420_suspend, + .resume = &r420_resume, + .errata = NULL, + .vram_info = NULL, .gpu_reset = &r300_gpu_reset, - .mc_init = &r420_mc_init, - .mc_fini = &r420_mc_fini, - .wb_init = &r100_wb_init, - .wb_fini = &r100_wb_fini, + .mc_init = NULL, + .mc_fini = NULL, + .wb_init = NULL, + .wb_fini = NULL, .gart_enable = &r300_gart_enable, .gart_disable = &rv370_pcie_gart_disable, .gart_tlb_flush = &rv370_pcie_gart_tlb_flush, .gart_set_page = &rv370_pcie_gart_set_page, - .cp_init = &r100_cp_init, - .cp_fini = &r100_cp_fini, - .cp_disable = &r100_cp_disable, + .cp_init = NULL, + .cp_fini = NULL, + .cp_disable = NULL, .cp_commit = &r100_cp_commit, .ring_start = &r300_ring_start, .ring_test = &r100_ring_test, .ring_ib_execute = &r100_ring_ib_execute, - .ib_test = &r100_ib_test, + .ib_test = NULL, .irq_set = &r100_irq_set, .irq_process = &r100_irq_process, .get_vblank_counter = &r100_get_vblank_counter, diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 72f6262ea73b..633acf71400b 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -156,6 +156,10 @@ int radeon_mc_setup(struct radeon_device *rdev) tmp = (tmp + rdev->mc.gtt_size - 1) & ~(rdev->mc.gtt_size - 1); rdev->mc.gtt_location = tmp; } + rdev->mc.vram_start = rdev->mc.vram_location; + rdev->mc.vram_end = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; + rdev->mc.gtt_start = rdev->mc.gtt_location; + rdev->mc.gtt_end = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; DRM_INFO("radeon: VRAM %uM\n", (unsigned)(rdev->mc.mc_vram_size >> 20)); DRM_INFO("radeon: VRAM from 0x%08X to 0x%08X\n", (unsigned)rdev->mc.vram_location, @@ -171,7 +175,7 @@ int radeon_mc_setup(struct radeon_device *rdev) /* * GPU helpers function. */ -static bool radeon_card_posted(struct radeon_device *rdev) +bool radeon_card_posted(struct radeon_device *rdev) { uint32_t reg; @@ -483,6 +487,7 @@ int radeon_device_init(struct radeon_device *rdev, DRM_INFO("radeon: Initializing kernel modesetting.\n"); rdev->shutdown = false; + rdev->dev = &pdev->dev; rdev->ddev = ddev; rdev->pdev = pdev; rdev->flags = flags; @@ -497,6 +502,7 @@ int radeon_device_init(struct radeon_device *rdev, mutex_init(&rdev->ib_pool.mutex); mutex_init(&rdev->cp.mutex); rwlock_init(&rdev->fence_drv.lock); + INIT_LIST_HEAD(&rdev->gem.objects); if (radeon_agpmode == -1) { rdev->flags &= ~RADEON_IS_AGP; @@ -736,15 +742,14 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) if (!rdev->new_init_path) { radeon_cp_disable(rdev); radeon_gart_disable(rdev); + rdev->irq.sw_int = false; + radeon_irq_set(rdev); } else { radeon_suspend(rdev); } /* evict remaining vram memory */ radeon_object_evict_vram(rdev); - rdev->irq.sw_int = false; - radeon_irq_set(rdev); - pci_save_state(dev->pdev); if (state.event == PM_EVENT_SUSPEND) { /* Shut down the device */ @@ -771,10 +776,10 @@ int radeon_resume_kms(struct drm_device *dev) } pci_set_master(dev->pdev); /* Reset gpu before posting otherwise ATOM will enter infinite loop */ - if (radeon_gpu_reset(rdev)) { - /* FIXME: what do we want to do here ? */ - } if (!rdev->new_init_path) { + if (radeon_gpu_reset(rdev)) { + /* FIXME: what do we want to do here ? */ + } /* post card */ if (rdev->is_atom_bios) { atom_asic_init(rdev->mode_info.atom_context); diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index aa9837a6aa75..168a555d6fba 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c @@ -151,6 +151,8 @@ int radeon_ib_pool_init(struct radeon_device *rdev) int i; int r = 0; + if (rdev->ib_pool.robj) + return 0; /* Allocate 1M object buffer */ INIT_LIST_HEAD(&rdev->ib_pool.scheduled_ibs); r = radeon_object_create(rdev, NULL, RADEON_IB_POOL_SIZE*64*1024, -- cgit v1.2.3 From a4d68279b44522a2b2374a6bd4861756bfad40fe Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Fri, 11 Sep 2009 13:00:43 +0200 Subject: drm/radeon/kms: move mtrr range add and memory information Move mtrr range and memory information printing to radeon_object_init, this are memory information and initialization common to all GPU and they better fit in this function. Will also prevent code duplication with upcoming init path changes. airlied: fixed warning introduced Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_device.c | 8 -------- drivers/gpu/drm/radeon/radeon_object.c | 8 ++++++++ 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/radeon/radeon_device.c') diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 633acf71400b..ece097c3e079 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -604,14 +604,6 @@ int radeon_device_init(struct radeon_device *rdev, /* Get vram informations */ radeon_vram_info(rdev); - /* Add an MTRR for the VRAM */ - rdev->mc.vram_mtrr = mtrr_add(rdev->mc.aper_base, rdev->mc.aper_size, - MTRR_TYPE_WRCOMB, 1); - DRM_INFO("Detected VRAM RAM=%uM, BAR=%uM\n", - (unsigned)(rdev->mc.mc_vram_size >> 20), - (unsigned)(rdev->mc.aper_size >> 20)); - DRM_INFO("RAM width %dbits %cDR\n", - rdev->mc.vram_width, rdev->mc.vram_is_ddr ? 'D' : 'S'); /* Initialize memory controller (also test AGP) */ r = radeon_mc_init(rdev); if (r) { diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index b85fb83d7ae8..1500d5bc7af5 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -369,6 +369,14 @@ void radeon_object_force_delete(struct radeon_device *rdev) int radeon_object_init(struct radeon_device *rdev) { + /* Add an MTRR for the VRAM */ + rdev->mc.vram_mtrr = mtrr_add(rdev->mc.aper_base, rdev->mc.aper_size, + MTRR_TYPE_WRCOMB, 1); + DRM_INFO("Detected VRAM RAM=%lluM, BAR=%lluM\n", + rdev->mc.mc_vram_size >> 20, + (unsigned long long)rdev->mc.aper_size >> 20); + DRM_INFO("RAM width %dbits %cDR\n", + rdev->mc.vram_width, rdev->mc.vram_is_ddr ? 'D' : 'S'); return radeon_ttm_init(rdev); } -- cgit v1.2.3 From 4aac047323e3082d0866b8ad3784236632105af4 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Mon, 14 Sep 2009 18:29:49 +0200 Subject: drm/radeon/kms: clear confusion in GART init/deinit path GART static one time initialization was mixed up with GART enabling/disabling which could happen several time for instance during suspend/resume cycles. This patch splits all GART handling into 4 differents function. gart_init is for one time initialization, gart_deinit is called upon module unload to free resources allocated by gart_init, gart_enable enable the GART and is intented to be call after first initialization and at each resume cycle or reset cycle. Finaly gart_disable stop the GART and is intended to be call at suspend time or when unloading the module. Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100.c | 40 ++++++------ drivers/gpu/drm/radeon/r300.c | 108 ++++++++++++++------------------- drivers/gpu/drm/radeon/r420.c | 57 ++++++++++------- drivers/gpu/drm/radeon/r520.c | 5 -- drivers/gpu/drm/radeon/r600.c | 53 +++++++++++----- drivers/gpu/drm/radeon/radeon.h | 11 ++++ drivers/gpu/drm/radeon/radeon_asic.h | 38 +++++++++--- drivers/gpu/drm/radeon/radeon_device.c | 36 +++++++++-- drivers/gpu/drm/radeon/radeon_gart.c | 9 ++- drivers/gpu/drm/radeon/rs400.c | 53 ++++++++++------ drivers/gpu/drm/radeon/rs600.c | 41 +++++++++---- drivers/gpu/drm/radeon/rs690.c | 3 - drivers/gpu/drm/radeon/rv515.c | 5 -- drivers/gpu/drm/radeon/rv770.c | 37 ++++++----- 14 files changed, 306 insertions(+), 190 deletions(-) (limited to 'drivers/gpu/drm/radeon/radeon_device.c') diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 47263d3ede98..fa0fdc1e3457 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -84,23 +84,28 @@ void r100_pci_gart_tlb_flush(struct radeon_device *rdev) * could end up in wrong address. */ } -int r100_pci_gart_enable(struct radeon_device *rdev) +int r100_pci_gart_init(struct radeon_device *rdev) { - uint32_t tmp; int r; + if (rdev->gart.table.ram.ptr) { + WARN(1, "R100 PCI GART already initialized.\n"); + return 0; + } /* Initialize common gart structure */ r = radeon_gart_init(rdev); - if (r) { + if (r) return r; - } - if (rdev->gart.table.ram.ptr == NULL) { - rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; - r = radeon_gart_table_ram_alloc(rdev); - if (r) { - return r; - } - } + rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; + rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush; + rdev->asic->gart_set_page = &r100_pci_gart_set_page; + return radeon_gart_table_ram_alloc(rdev); +} + +int r100_pci_gart_enable(struct radeon_device *rdev) +{ + uint32_t tmp; + /* discard memory request outside of configured range */ tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS; WREG32(RADEON_AIC_CNTL, tmp); @@ -140,13 +145,11 @@ int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) return 0; } -int r100_gart_enable(struct radeon_device *rdev) +void r100_pci_gart_fini(struct radeon_device *rdev) { - if (rdev->flags & RADEON_IS_AGP) { - r100_pci_gart_disable(rdev); - return 0; - } - return r100_pci_gart_enable(rdev); + r100_pci_gart_disable(rdev); + radeon_gart_table_ram_free(rdev); + radeon_gart_fini(rdev); } @@ -273,9 +276,6 @@ int r100_mc_init(struct radeon_device *rdev) void r100_mc_fini(struct radeon_device *rdev) { - r100_pci_gart_disable(rdev); - radeon_gart_table_ram_free(rdev); - radeon_gart_fini(rdev); } diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index ced3322bd5fb..bb151ecdf8fc 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -42,7 +42,6 @@ int r100_cp_reset(struct radeon_device *rdev); int r100_rb2d_reset(struct radeon_device *rdev); int r100_cp_init(struct radeon_device *rdev, unsigned ring_size); int r100_pci_gart_enable(struct radeon_device *rdev); -void r100_pci_gart_disable(struct radeon_device *rdev); void r100_mc_setup(struct radeon_device *rdev); void r100_mc_disable_clients(struct radeon_device *rdev); int r100_gui_wait_for_idle(struct radeon_device *rdev); @@ -86,26 +85,57 @@ void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev) mb(); } -int rv370_pcie_gart_enable(struct radeon_device *rdev) +int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) +{ + void __iomem *ptr = (void *)rdev->gart.table.vram.ptr; + + if (i < 0 || i > rdev->gart.num_gpu_pages) { + return -EINVAL; + } + addr = (lower_32_bits(addr) >> 8) | + ((upper_32_bits(addr) & 0xff) << 24) | + 0xc; + /* on x86 we want this to be CPU endian, on powerpc + * on powerpc without HW swappers, it'll get swapped on way + * into VRAM - so no need for cpu_to_le32 on VRAM tables */ + writel(addr, ((void __iomem *)ptr) + (i * 4)); + return 0; +} + +int rv370_pcie_gart_init(struct radeon_device *rdev) { - uint32_t table_addr; - uint32_t tmp; int r; + if (rdev->gart.table.vram.robj) { + WARN(1, "RV370 PCIE GART already initialized.\n"); + return 0; + } /* Initialize common gart structure */ r = radeon_gart_init(rdev); - if (r) { + if (r) return r; - } r = rv370_debugfs_pcie_gart_info_init(rdev); - if (r) { + if (r) DRM_ERROR("Failed to register debugfs file for PCIE gart !\n"); - } rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; - r = radeon_gart_table_vram_alloc(rdev); - if (r) { - return r; + rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush; + rdev->asic->gart_set_page = &rv370_pcie_gart_set_page; + return radeon_gart_table_vram_alloc(rdev); +} + +int rv370_pcie_gart_enable(struct radeon_device *rdev) +{ + uint32_t table_addr; + uint32_t tmp; + int r; + + if (rdev->gart.table.vram.robj == NULL) { + dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); + return -EINVAL; } + r = radeon_gart_table_vram_pin(rdev); + if (r) + return r; /* discard memory request outside of configured range */ tmp = RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD; WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp); @@ -145,51 +175,13 @@ void rv370_pcie_gart_disable(struct radeon_device *rdev) } } -int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) -{ - void __iomem *ptr = (void *)rdev->gart.table.vram.ptr; - - if (i < 0 || i > rdev->gart.num_gpu_pages) { - return -EINVAL; - } - addr = (lower_32_bits(addr) >> 8) | - ((upper_32_bits(addr) & 0xff) << 24) | - 0xc; - /* on x86 we want this to be CPU endian, on powerpc - * on powerpc without HW swappers, it'll get swapped on way - * into VRAM - so no need for cpu_to_le32 on VRAM tables */ - writel(addr, ((void __iomem *)ptr) + (i * 4)); - return 0; -} - -int r300_gart_enable(struct radeon_device *rdev) +void rv370_pcie_gart_fini(struct radeon_device *rdev) { -#if __OS_HAS_AGP - if (rdev->flags & RADEON_IS_AGP) { - if (rdev->family > CHIP_RV350) { - rv370_pcie_gart_disable(rdev); - } else { - r100_pci_gart_disable(rdev); - } - return 0; - } -#endif - if (rdev->flags & RADEON_IS_PCIE) { - rdev->asic->gart_disable = &rv370_pcie_gart_disable; - rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush; - rdev->asic->gart_set_page = &rv370_pcie_gart_set_page; - return rv370_pcie_gart_enable(rdev); - } - if (rdev->flags & RADEON_IS_PCI) { - rdev->asic->gart_disable = &r100_pci_gart_disable; - rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush; - rdev->asic->gart_set_page = &r100_pci_gart_set_page; - return r100_pci_gart_enable(rdev); - } - return r100_pci_gart_enable(rdev); + rv370_pcie_gart_disable(rdev); + radeon_gart_table_vram_free(rdev); + radeon_gart_fini(rdev); } - /* * MC */ @@ -237,14 +229,6 @@ int r300_mc_init(struct radeon_device *rdev) void r300_mc_fini(struct radeon_device *rdev) { - if (rdev->flags & RADEON_IS_PCIE) { - rv370_pcie_gart_disable(rdev); - radeon_gart_table_vram_free(rdev); - } else { - r100_pci_gart_disable(rdev); - radeon_gart_table_ram_free(rdev); - } - radeon_gart_fini(rdev); } @@ -1299,8 +1283,6 @@ void r300_mc_program(struct radeon_device *rdev) /* Stops all mc clients */ r100_mc_stop(rdev, &save); - /* Shutdown PCI/PCIE GART */ - radeon_gart_disable(rdev); if (rdev->flags & RADEON_IS_AGP) { WREG32(R_00014C_MC_AGP_LOCATION, S_00014C_MC_AGP_START(rdev->mc.gtt_start >> 16) | diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index e57b9ba4aaf3..33a25a4377b8 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c @@ -161,6 +161,11 @@ int r420_resume(struct radeon_device *rdev) { int r; + /* Make sur GART are not working */ + if (rdev->flags & RADEON_IS_PCIE) + rv370_pcie_gart_disable(rdev); + if (rdev->flags & RADEON_IS_PCI) + r100_pci_gart_disable(rdev); /* Resume clock before doing reset */ r420_clock_resume(rdev); /* Reset gpu before posting otherwise ATOM will enter infinite loop */ @@ -180,10 +185,15 @@ int r420_resume(struct radeon_device *rdev) r300_mc_program(rdev); /* Initialize GART (initialize after TTM so we can allocate * memory through TTM but finalize after TTM) */ - r = radeon_gart_enable(rdev); - if (r) { - dev_err(rdev->dev, "failled initializing GART (%d).\n", r); - return r; + if (rdev->flags & RADEON_IS_PCIE) { + r = rv370_pcie_gart_enable(rdev); + if (r) + return r; + } + if (rdev->flags & RADEON_IS_PCI) { + r = r100_pci_gart_enable(rdev); + if (r) + return r; } r420_pipes_init(rdev); /* Enable IRQ */ @@ -212,7 +222,10 @@ int r420_suspend(struct radeon_device *rdev) r100_cp_disable(rdev); r100_wb_disable(rdev); r100_irq_disable(rdev); - radeon_gart_disable(rdev); + if (rdev->flags & RADEON_IS_PCIE) + rv370_pcie_gart_disable(rdev); + if (rdev->flags & RADEON_IS_PCI) + r100_pci_gart_disable(rdev); return 0; } @@ -222,14 +235,10 @@ void r420_fini(struct radeon_device *rdev) r100_wb_fini(rdev); r100_ib_fini(rdev); radeon_gem_fini(rdev); - if (rdev->flags & RADEON_IS_PCIE) { - rv370_pcie_gart_disable(rdev); - radeon_gart_table_vram_free(rdev); - } else { - r100_pci_gart_disable(rdev); - radeon_gart_table_ram_free(rdev); - } - radeon_gart_fini(rdev); + if (rdev->flags & RADEON_IS_PCIE) + rv370_pcie_gart_fini(rdev); + if (rdev->flags & RADEON_IS_PCI) + r100_pci_gart_fini(rdev); radeon_agp_fini(rdev); radeon_irq_kms_fini(rdev); radeon_fence_driver_fini(rdev); @@ -309,6 +318,16 @@ int r420_init(struct radeon_device *rdev) if (r) { return r; } + if (rdev->flags & RADEON_IS_PCIE) { + r = rv370_pcie_gart_init(rdev); + if (r) + return r; + } + if (rdev->flags & RADEON_IS_PCI) { + r = r100_pci_gart_init(rdev); + if (r) + return r; + } r300_set_reg_safe(rdev); r = r420_resume(rdev); if (r) { @@ -318,14 +337,10 @@ int r420_init(struct radeon_device *rdev) r100_cp_fini(rdev); r100_wb_fini(rdev); r100_ib_fini(rdev); - if (rdev->flags & RADEON_IS_PCIE) { - rv370_pcie_gart_disable(rdev); - radeon_gart_table_vram_free(rdev); - } else { - r100_pci_gart_disable(rdev); - radeon_gart_table_ram_free(rdev); - } - radeon_gart_fini(rdev); + if (rdev->flags & RADEON_IS_PCIE) + rv370_pcie_gart_fini(rdev); + if (rdev->flags & RADEON_IS_PCI) + r100_pci_gart_fini(rdev); radeon_agp_fini(rdev); radeon_irq_kms_fini(rdev); } diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c index 0e1686d1c873..d4b0b9d2e39b 100644 --- a/drivers/gpu/drm/radeon/r520.c +++ b/drivers/gpu/drm/radeon/r520.c @@ -31,8 +31,6 @@ /* r520,rv530,rv560,rv570,r580 depends on : */ void r100_hdp_reset(struct radeon_device *rdev); -int rv370_pcie_gart_enable(struct radeon_device *rdev); -void rv370_pcie_gart_disable(struct radeon_device *rdev); void r420_pipes_init(struct radeon_device *rdev); void rs600_mc_disable_clients(struct radeon_device *rdev); void rs600_disable_vga(struct radeon_device *rdev); @@ -118,9 +116,6 @@ int r520_mc_init(struct radeon_device *rdev) void r520_mc_fini(struct radeon_device *rdev) { - rv370_pcie_gart_disable(rdev); - radeon_gart_table_vram_free(rdev); - radeon_gart_fini(rdev); } diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 1bc25678986b..65699e9f2025 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -113,21 +113,34 @@ void r600_pcie_gart_tlb_flush(struct radeon_device *rdev) } } -int r600_pcie_gart_enable(struct radeon_device *rdev) +int r600_pcie_gart_init(struct radeon_device *rdev) { - u32 tmp; - int r, i; + int r; + if (rdev->gart.table.vram.robj) { + WARN(1, "R600 PCIE GART already initialized.\n"); + return 0; + } /* Initialize common gart structure */ r = radeon_gart_init(rdev); - if (r) { + if (r) return r; - } rdev->gart.table_size = rdev->gart.num_gpu_pages * 8; - r = radeon_gart_table_vram_alloc(rdev); - if (r) { - return r; + return radeon_gart_table_vram_alloc(rdev); +} + +int r600_pcie_gart_enable(struct radeon_device *rdev) +{ + u32 tmp; + int r, i; + + if (rdev->gart.table.vram.robj == NULL) { + dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); + return -EINVAL; } + r = radeon_gart_table_vram_pin(rdev); + if (r) + return r; for (i = 0; i < rdev->gart.num_gpu_pages; i++) r600_gart_clear_page(rdev, i); /* Setup L2 cache */ @@ -175,10 +188,6 @@ void r600_pcie_gart_disable(struct radeon_device *rdev) u32 tmp; int i; - /* Clear ptes*/ - for (i = 0; i < rdev->gart.num_gpu_pages; i++) - r600_gart_clear_page(rdev, i); - r600_pcie_gart_tlb_flush(rdev); /* Disable all tables */ for (i = 0; i < 7; i++) WREG32(VM_CONTEXT0_CNTL + (i * 4), 0); @@ -204,6 +213,17 @@ void r600_pcie_gart_disable(struct radeon_device *rdev) WREG32(MC_VM_L1_TLB_MCB_WR_SYS_CNTL, tmp); WREG32(MC_VM_L1_TLB_MCB_RD_HDP_CNTL, tmp); WREG32(MC_VM_L1_TLB_MCB_WR_HDP_CNTL, tmp); + if (rdev->gart.table.vram.robj) { + radeon_object_kunmap(rdev->gart.table.vram.robj); + radeon_object_unpin(rdev->gart.table.vram.robj); + } +} + +void r600_pcie_gart_fini(struct radeon_device *rdev) +{ + r600_pcie_gart_disable(rdev); + radeon_gart_table_vram_free(rdev); + radeon_gart_fini(rdev); } int r600_mc_wait_for_idle(struct radeon_device *rdev) @@ -1472,6 +1492,7 @@ int r600_suspend(struct radeon_device *rdev) { /* FIXME: we should wait for ring to be empty */ r600_cp_stop(rdev); + r600_pcie_gart_disable(rdev); return 0; } @@ -1548,6 +1569,10 @@ int r600_init(struct radeon_device *rdev) } } + r = r600_pcie_gart_init(rdev); + if (r) + return r; + r = r600_resume(rdev); if (r) { if (rdev->flags & RADEON_IS_AGP) { @@ -1583,9 +1608,7 @@ void r600_fini(struct radeon_device *rdev) r600_blit_fini(rdev); radeon_ring_fini(rdev); - r600_pcie_gart_disable(rdev); - radeon_gart_table_vram_free(rdev); - radeon_gart_fini(rdev); + r600_pcie_gart_fini(rdev); radeon_gem_fini(rdev); radeon_fence_driver_fini(rdev); radeon_clocks_fini(rdev); diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 8cec5bf2922b..99292be8bc99 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -596,6 +596,8 @@ struct radeon_asic { void (*mc_fini)(struct radeon_device *rdev); int (*wb_init)(struct radeon_device *rdev); void (*wb_fini)(struct radeon_device *rdev); + int (*gart_init)(struct radeon_device *rdev); + void (*gart_fini)(struct radeon_device *rdev); int (*gart_enable)(struct radeon_device *rdev); void (*gart_disable)(struct radeon_device *rdev); void (*gart_tlb_flush)(struct radeon_device *rdev); @@ -950,6 +952,8 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v) #define radeon_mc_fini(rdev) (rdev)->asic->mc_fini((rdev)) #define radeon_wb_init(rdev) (rdev)->asic->wb_init((rdev)) #define radeon_wb_fini(rdev) (rdev)->asic->wb_fini((rdev)) +#define radeon_gpu_gart_init(rdev) (rdev)->asic->gart_init((rdev)) +#define radeon_gpu_gart_fini(rdev) (rdev)->asic->gart_fini((rdev)) #define radeon_gart_enable(rdev) (rdev)->asic->gart_enable((rdev)) #define radeon_gart_disable(rdev) (rdev)->asic->gart_disable((rdev)) #define radeon_gart_tlb_flush(rdev) (rdev)->asic->gart_tlb_flush((rdev)) @@ -978,6 +982,7 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v) #define radeon_bandwidth_update(rdev) (rdev)->asic->bandwidth_update((rdev)) /* Common functions */ +extern int radeon_gart_table_vram_pin(struct radeon_device *rdev); extern int radeon_modeset_init(struct radeon_device *rdev); extern void radeon_modeset_fini(struct radeon_device *rdev); extern bool radeon_card_posted(struct radeon_device *rdev); @@ -1000,6 +1005,8 @@ extern void r100_cp_disable(struct radeon_device *rdev); extern int r100_cp_init(struct radeon_device *rdev, unsigned ring_size); extern void r100_cp_fini(struct radeon_device *rdev); extern void r100_pci_gart_tlb_flush(struct radeon_device *rdev); +extern int r100_pci_gart_init(struct radeon_device *rdev); +extern void r100_pci_gart_fini(struct radeon_device *rdev); extern int r100_pci_gart_enable(struct radeon_device *rdev); extern void r100_pci_gart_disable(struct radeon_device *rdev); extern int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); @@ -1020,6 +1027,9 @@ extern int r100_wb_init(struct radeon_device *rdev); extern void r300_set_reg_safe(struct radeon_device *rdev); extern void r300_mc_program(struct radeon_device *rdev); extern void r300_vram_info(struct radeon_device *rdev); +extern int rv370_pcie_gart_init(struct radeon_device *rdev); +extern void rv370_pcie_gart_fini(struct radeon_device *rdev); +extern int rv370_pcie_gart_enable(struct radeon_device *rdev); extern void rv370_pcie_gart_disable(struct radeon_device *rdev); /* r420,r423,rv410 */ @@ -1043,6 +1053,7 @@ extern int r600_cp_resume(struct radeon_device *rdev); extern int r600_count_pipe_bits(uint32_t val); extern int r600_gart_clear_page(struct radeon_device *rdev, int i); extern int r600_mc_wait_for_idle(struct radeon_device *rdev); +extern int r600_pcie_gart_init(struct radeon_device *rdev); extern void r600_pcie_gart_tlb_flush(struct radeon_device *rdev); extern int r600_ib_test(struct radeon_device *rdev); extern int r600_ring_test(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 8f27be31e094..5f2a9e6f12c5 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -53,7 +53,9 @@ void r100_mc_fini(struct radeon_device *rdev); u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc); int r100_wb_init(struct radeon_device *rdev); void r100_wb_fini(struct radeon_device *rdev); -int r100_gart_enable(struct radeon_device *rdev); +int r100_pci_gart_init(struct radeon_device *rdev); +void r100_pci_gart_fini(struct radeon_device *rdev); +int r100_pci_gart_enable(struct radeon_device *rdev); void r100_pci_gart_disable(struct radeon_device *rdev); void r100_pci_gart_tlb_flush(struct radeon_device *rdev); int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); @@ -92,7 +94,9 @@ static struct radeon_asic r100_asic = { .mc_fini = &r100_mc_fini, .wb_init = &r100_wb_init, .wb_fini = &r100_wb_fini, - .gart_enable = &r100_gart_enable, + .gart_init = &r100_pci_gart_init, + .gart_fini = &r100_pci_gart_fini, + .gart_enable = &r100_pci_gart_enable, .gart_disable = &r100_pci_gart_disable, .gart_tlb_flush = &r100_pci_gart_tlb_flush, .gart_set_page = &r100_pci_gart_set_page, @@ -135,7 +139,9 @@ void r300_ring_start(struct radeon_device *rdev); void r300_fence_ring_emit(struct radeon_device *rdev, struct radeon_fence *fence); int r300_cs_parse(struct radeon_cs_parser *p); -int r300_gart_enable(struct radeon_device *rdev); +int rv370_pcie_gart_init(struct radeon_device *rdev); +void rv370_pcie_gart_fini(struct radeon_device *rdev); +int rv370_pcie_gart_enable(struct radeon_device *rdev); void rv370_pcie_gart_disable(struct radeon_device *rdev); void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev); int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); @@ -157,7 +163,9 @@ static struct radeon_asic r300_asic = { .mc_fini = &r300_mc_fini, .wb_init = &r100_wb_init, .wb_fini = &r100_wb_fini, - .gart_enable = &r300_gart_enable, + .gart_init = &r100_pci_gart_init, + .gart_fini = &r100_pci_gart_fini, + .gart_enable = &r100_pci_gart_enable, .gart_disable = &r100_pci_gart_disable, .gart_tlb_flush = &r100_pci_gart_tlb_flush, .gart_set_page = &r100_pci_gart_set_page, @@ -205,8 +213,8 @@ static struct radeon_asic r420_asic = { .mc_fini = NULL, .wb_init = NULL, .wb_fini = NULL, - .gart_enable = &r300_gart_enable, - .gart_disable = &rv370_pcie_gart_disable, + .gart_enable = NULL, + .gart_disable = NULL, .gart_tlb_flush = &rv370_pcie_gart_tlb_flush, .gart_set_page = &rv370_pcie_gart_set_page, .cp_init = NULL, @@ -242,6 +250,8 @@ void rs400_errata(struct radeon_device *rdev); void rs400_vram_info(struct radeon_device *rdev); int rs400_mc_init(struct radeon_device *rdev); void rs400_mc_fini(struct radeon_device *rdev); +int rs400_gart_init(struct radeon_device *rdev); +void rs400_gart_fini(struct radeon_device *rdev); int rs400_gart_enable(struct radeon_device *rdev); void rs400_gart_disable(struct radeon_device *rdev); void rs400_gart_tlb_flush(struct radeon_device *rdev); @@ -257,6 +267,8 @@ static struct radeon_asic rs400_asic = { .mc_fini = &rs400_mc_fini, .wb_init = &r100_wb_init, .wb_fini = &r100_wb_fini, + .gart_init = &rs400_gart_init, + .gart_fini = &rs400_gart_fini, .gart_enable = &rs400_gart_enable, .gart_disable = &rs400_gart_disable, .gart_tlb_flush = &rs400_gart_tlb_flush, @@ -298,6 +310,8 @@ void rs600_mc_fini(struct radeon_device *rdev); int rs600_irq_set(struct radeon_device *rdev); int rs600_irq_process(struct radeon_device *rdev); u32 rs600_get_vblank_counter(struct radeon_device *rdev, int crtc); +int rs600_gart_init(struct radeon_device *rdev); +void rs600_gart_fini(struct radeon_device *rdev); int rs600_gart_enable(struct radeon_device *rdev); void rs600_gart_disable(struct radeon_device *rdev); void rs600_gart_tlb_flush(struct radeon_device *rdev); @@ -314,6 +328,8 @@ static struct radeon_asic rs600_asic = { .mc_fini = &rs600_mc_fini, .wb_init = &r100_wb_init, .wb_fini = &r100_wb_fini, + .gart_init = &rs600_gart_init, + .gart_fini = &rs600_gart_fini, .gart_enable = &rs600_gart_enable, .gart_disable = &rs600_gart_disable, .gart_tlb_flush = &rs600_gart_tlb_flush, @@ -361,6 +377,8 @@ static struct radeon_asic rs690_asic = { .mc_fini = &rs690_mc_fini, .wb_init = &r100_wb_init, .wb_fini = &r100_wb_fini, + .gart_init = &rs400_gart_init, + .gart_fini = &rs400_gart_fini, .gart_enable = &rs400_gart_enable, .gart_disable = &rs400_gart_disable, .gart_tlb_flush = &rs400_gart_tlb_flush, @@ -415,7 +433,9 @@ static struct radeon_asic rv515_asic = { .mc_fini = &rv515_mc_fini, .wb_init = &r100_wb_init, .wb_fini = &r100_wb_fini, - .gart_enable = &r300_gart_enable, + .gart_init = &rv370_pcie_gart_init, + .gart_fini = &rv370_pcie_gart_fini, + .gart_enable = &rv370_pcie_gart_enable, .gart_disable = &rv370_pcie_gart_disable, .gart_tlb_flush = &rv370_pcie_gart_tlb_flush, .gart_set_page = &rv370_pcie_gart_set_page, @@ -462,7 +482,9 @@ static struct radeon_asic r520_asic = { .mc_fini = &r520_mc_fini, .wb_init = &r100_wb_init, .wb_fini = &r100_wb_fini, - .gart_enable = &r300_gart_enable, + .gart_init = &rv370_pcie_gart_init, + .gart_fini = &rv370_pcie_gart_fini, + .gart_enable = &rv370_pcie_gart_enable, .gart_disable = &rv370_pcie_gart_disable, .gart_tlb_flush = &rv370_pcie_gart_tlb_flush, .gart_set_page = &rv370_pcie_gart_set_page, diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index ece097c3e079..7b6d0b1a5962 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -320,6 +320,14 @@ int radeon_asic_init(struct radeon_device *rdev) case CHIP_RV350: case CHIP_RV380: rdev->asic = &r300_asic; + if (rdev->flags & RADEON_IS_PCIE) { + rdev->asic->gart_init = &rv370_pcie_gart_init; + rdev->asic->gart_fini = &rv370_pcie_gart_fini; + rdev->asic->gart_enable = &rv370_pcie_gart_enable; + rdev->asic->gart_disable = &rv370_pcie_gart_disable; + rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush; + rdev->asic->gart_set_page = &rv370_pcie_gart_set_page; + } break; case CHIP_R420: case CHIP_R423: @@ -504,6 +512,12 @@ int radeon_device_init(struct radeon_device *rdev, rwlock_init(&rdev->fence_drv.lock); INIT_LIST_HEAD(&rdev->gem.objects); + /* Set asic functions */ + r = radeon_asic_init(rdev); + if (r) { + return r; + } + if (radeon_agpmode == -1) { rdev->flags &= ~RADEON_IS_AGP; if (rdev->family >= CHIP_RV515 || @@ -512,18 +526,24 @@ int radeon_device_init(struct radeon_device *rdev, rdev->family == CHIP_R423) { DRM_INFO("Forcing AGP to PCIE mode\n"); rdev->flags |= RADEON_IS_PCIE; + rdev->asic->gart_init = &rv370_pcie_gart_init; + rdev->asic->gart_fini = &rv370_pcie_gart_fini; + rdev->asic->gart_enable = &rv370_pcie_gart_enable; + rdev->asic->gart_disable = &rv370_pcie_gart_disable; + rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush; + rdev->asic->gart_set_page = &rv370_pcie_gart_set_page; } else { DRM_INFO("Forcing AGP to PCI mode\n"); rdev->flags |= RADEON_IS_PCI; + rdev->asic->gart_init = &r100_pci_gart_init; + rdev->asic->gart_fini = &r100_pci_gart_fini; + rdev->asic->gart_enable = &r100_pci_gart_enable; + rdev->asic->gart_disable = &r100_pci_gart_disable; + rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush; + rdev->asic->gart_set_page = &r100_pci_gart_set_page; } } - /* Set asic functions */ - r = radeon_asic_init(rdev); - if (r) { - return r; - } - /* set DMA mask + need_dma32 flags. * PCIE - can handle 40-bits. * IGP - can handle 40-bits (in theory) @@ -623,6 +643,9 @@ int radeon_device_init(struct radeon_device *rdev, if (r) { return r; } + r = radeon_gpu_gart_init(rdev); + if (r) + return r; /* Initialize GART (initialize after TTM so we can allocate * memory through TTM but finalize after TTM) */ r = radeon_gart_enable(rdev); @@ -675,6 +698,7 @@ void radeon_device_fini(struct radeon_device *rdev) radeon_ib_pool_fini(rdev); radeon_cp_fini(rdev); radeon_wb_fini(rdev); + radeon_gpu_gart_fini(rdev); radeon_gem_fini(rdev); radeon_mc_fini(rdev); #if __OS_HAS_AGP diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index 2977539880fb..a931af065dd4 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -75,7 +75,6 @@ void radeon_gart_table_ram_free(struct radeon_device *rdev) int radeon_gart_table_vram_alloc(struct radeon_device *rdev) { - uint64_t gpu_addr; int r; if (rdev->gart.table.vram.robj == NULL) { @@ -88,6 +87,14 @@ int radeon_gart_table_vram_alloc(struct radeon_device *rdev) return r; } } + return 0; +} + +int radeon_gart_table_vram_pin(struct radeon_device *rdev) +{ + uint64_t gpu_addr; + int r; + r = radeon_object_pin(rdev->gart.table.vram.robj, RADEON_GEM_DOMAIN_VRAM, &gpu_addr); if (r) { diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index e1e4ce427828..a3fbdad938c7 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -92,20 +92,41 @@ void rs400_gart_tlb_flush(struct radeon_device *rdev) WREG32_MC(RS480_GART_CACHE_CNTRL, 0); } -int rs400_gart_enable(struct radeon_device *rdev) +int rs400_gart_init(struct radeon_device *rdev) { - uint32_t size_reg; - uint32_t tmp; int r; + if (rdev->gart.table.ram.ptr) { + WARN(1, "RS400 GART already initialized.\n"); + return 0; + } + /* Check gart size */ + switch(rdev->mc.gtt_size / (1024 * 1024)) { + case 32: + case 64: + case 128: + case 256: + case 512: + case 1024: + case 2048: + break; + default: + return -EINVAL; + } /* Initialize common gart structure */ r = radeon_gart_init(rdev); - if (r) { + if (r) return r; - } - if (rs400_debugfs_pcie_gart_info_init(rdev)) { + if (rs400_debugfs_pcie_gart_info_init(rdev)) DRM_ERROR("Failed to register debugfs file for RS400 GART !\n"); - } + rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; + return radeon_gart_table_ram_alloc(rdev); +} + +int rs400_gart_enable(struct radeon_device *rdev) +{ + uint32_t size_reg; + uint32_t tmp; tmp = RREG32_MC(RS690_AIC_CTRL_SCRATCH); tmp |= RS690_DIS_OUT_OF_PCI_GART_ACCESS; @@ -136,13 +157,6 @@ int rs400_gart_enable(struct radeon_device *rdev) default: return -EINVAL; } - if (rdev->gart.table.ram.ptr == NULL) { - rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; - r = radeon_gart_table_ram_alloc(rdev); - if (r) { - return r; - } - } /* It should be fine to program it to max value */ if (rdev->family == CHIP_RS690 || (rdev->family == CHIP_RS740)) { WREG32_MC(RS690_MCCFG_AGP_BASE, 0xFFFFFFFF); @@ -201,6 +215,13 @@ void rs400_gart_disable(struct radeon_device *rdev) WREG32_MC(RS480_AGP_ADDRESS_SPACE_SIZE, 0); } +void rs400_gart_fini(struct radeon_device *rdev) +{ + rs400_gart_disable(rdev); + radeon_gart_table_ram_free(rdev); + radeon_gart_fini(rdev); +} + int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) { uint32_t entry; @@ -255,14 +276,12 @@ int rs400_mc_init(struct radeon_device *rdev) (void)RREG32(RADEON_HOST_PATH_CNTL); WREG32(RADEON_HOST_PATH_CNTL, tmp); (void)RREG32(RADEON_HOST_PATH_CNTL); + return 0; } void rs400_mc_fini(struct radeon_device *rdev) { - rs400_gart_disable(rdev); - radeon_gart_table_ram_free(rdev); - radeon_gart_fini(rdev); } diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 1b8d62f5e73c..c31bd8439259 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -68,22 +68,35 @@ void rs600_gart_tlb_flush(struct radeon_device *rdev) tmp = RREG32_MC(RS600_MC_PT0_CNTL); } -int rs600_gart_enable(struct radeon_device *rdev) +int rs600_gart_init(struct radeon_device *rdev) { - uint32_t tmp; - int i; int r; + if (rdev->gart.table.vram.robj) { + WARN(1, "RS600 GART already initialized.\n"); + return 0; + } /* Initialize common gart structure */ r = radeon_gart_init(rdev); if (r) { return r; } rdev->gart.table_size = rdev->gart.num_gpu_pages * 8; - r = radeon_gart_table_vram_alloc(rdev); - if (r) { - return r; + return radeon_gart_table_vram_alloc(rdev); +} + +int rs600_gart_enable(struct radeon_device *rdev) +{ + uint32_t tmp; + int r, i; + + if (rdev->gart.table.vram.robj == NULL) { + dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); + return -EINVAL; } + r = radeon_gart_table_vram_pin(rdev); + if (r) + return r; /* FIXME: setup default page */ WREG32_MC(RS600_MC_PT0_CNTL, (RS600_EFFECTIVE_L2_CACHE_SIZE(6) | @@ -138,8 +151,17 @@ void rs600_gart_disable(struct radeon_device *rdev) tmp = RREG32_MC(RS600_MC_CNTL1); tmp &= ~RS600_ENABLE_PAGE_TABLES; WREG32_MC(RS600_MC_CNTL1, tmp); - radeon_object_kunmap(rdev->gart.table.vram.robj); - radeon_object_unpin(rdev->gart.table.vram.robj); + if (rdev->gart.table.vram.robj) { + radeon_object_kunmap(rdev->gart.table.vram.robj); + radeon_object_unpin(rdev->gart.table.vram.robj); + } +} + +void rs600_gart_fini(struct radeon_device *rdev) +{ + rs600_gart_disable(rdev); + radeon_gart_table_vram_free(rdev); + radeon_gart_fini(rdev); } #define R600_PTE_VALID (1 << 0) @@ -235,9 +257,6 @@ int rs600_mc_init(struct radeon_device *rdev) void rs600_mc_fini(struct radeon_device *rdev) { - rs600_gart_disable(rdev); - radeon_gart_table_vram_free(rdev); - radeon_gart_fini(rdev); } diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 839595b00728..0f585ca8276d 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -94,9 +94,6 @@ int rs690_mc_init(struct radeon_device *rdev) void rs690_mc_fini(struct radeon_device *rdev) { - rs400_gart_disable(rdev); - radeon_gart_table_ram_free(rdev); - radeon_gart_fini(rdev); } diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 03d490269ed0..fd799748e7d8 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -37,8 +37,6 @@ int r100_cp_reset(struct radeon_device *rdev); int r100_rb2d_reset(struct radeon_device *rdev); int r100_gui_wait_for_idle(struct radeon_device *rdev); int r100_cp_init(struct radeon_device *rdev, unsigned ring_size); -int rv370_pcie_gart_enable(struct radeon_device *rdev); -void rv370_pcie_gart_disable(struct radeon_device *rdev); void r420_pipes_init(struct radeon_device *rdev); void rs600_mc_disable_clients(struct radeon_device *rdev); void rs600_disable_vga(struct radeon_device *rdev); @@ -126,9 +124,6 @@ int rv515_mc_init(struct radeon_device *rdev) void rv515_mc_fini(struct radeon_device *rdev) { - rv370_pcie_gart_disable(rdev); - radeon_gart_table_vram_free(rdev); - radeon_gart_fini(rdev); } diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 5ba5204091ec..4f2098bc7974 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -48,16 +48,13 @@ int rv770_pcie_gart_enable(struct radeon_device *rdev) u32 tmp; int r, i; - /* Initialize common gart structure */ - r = radeon_gart_init(rdev); - if (r) { - return r; + if (rdev->gart.table.vram.robj == NULL) { + dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); + return -EINVAL; } - rdev->gart.table_size = rdev->gart.num_gpu_pages * 8; - r = radeon_gart_table_vram_alloc(rdev); - if (r) { + r = radeon_gart_table_vram_pin(rdev); + if (r) return r; - } for (i = 0; i < rdev->gart.num_gpu_pages; i++) r600_gart_clear_page(rdev, i); /* Setup L2 cache */ @@ -98,10 +95,6 @@ void rv770_pcie_gart_disable(struct radeon_device *rdev) u32 tmp; int i; - /* Clear ptes*/ - for (i = 0; i < rdev->gart.num_gpu_pages; i++) - r600_gart_clear_page(rdev, i); - r600_pcie_gart_tlb_flush(rdev); /* Disable all tables */ for (i = 0; i < 7; i++) WREG32(VM_CONTEXT0_CNTL + (i * 4), 0); @@ -120,6 +113,17 @@ void rv770_pcie_gart_disable(struct radeon_device *rdev) WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp); WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp); + if (rdev->gart.table.vram.robj) { + radeon_object_kunmap(rdev->gart.table.vram.robj); + radeon_object_unpin(rdev->gart.table.vram.robj); + } +} + +void rv770_pcie_gart_fini(struct radeon_device *rdev) +{ + rv770_pcie_gart_disable(rdev); + radeon_gart_table_vram_free(rdev); + radeon_gart_fini(rdev); } @@ -871,6 +875,7 @@ int rv770_suspend(struct radeon_device *rdev) { /* FIXME: we should wait for ring to be empty */ r700_cp_stop(rdev); + rv770_pcie_gart_disable(rdev); return 0; } @@ -944,6 +949,10 @@ int rv770_init(struct radeon_device *rdev) } } + r = r600_pcie_gart_init(rdev); + if (r) + return r; + r = rv770_resume(rdev); if (r) { if (rdev->flags & RADEON_IS_AGP) { @@ -976,9 +985,7 @@ void rv770_fini(struct radeon_device *rdev) { r600_blit_fini(rdev); radeon_ring_fini(rdev); - rv770_pcie_gart_disable(rdev); - radeon_gart_table_vram_free(rdev); - radeon_gart_fini(rdev); + rv770_pcie_gart_fini(rdev); radeon_gem_fini(rdev); radeon_fence_driver_fini(rdev); radeon_clocks_fini(rdev); -- cgit v1.2.3 From 95a8f1bf4f48b434c9f839ab5a0773f66b39d7c6 Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Tue, 15 Sep 2009 17:09:26 +0200 Subject: drm/radeon/kms: Move radeon_clocks_init() call back after getting VRAM info. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It may indirectly call radeon_set_clock_gating() which relies on the VRAM info. Signed-off-by: Michel Dänzer Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/radeon/radeon_device.c') diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 7b6d0b1a5962..cc8e005c1b30 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -616,13 +616,13 @@ int radeon_device_init(struct radeon_device *rdev, radeon_combios_asic_init(rdev->ddev); } } + /* Get vram informations */ + radeon_vram_info(rdev); /* Initialize clocks */ r = radeon_clocks_init(rdev); if (r) { return r; } - /* Get vram informations */ - radeon_vram_info(rdev); /* Initialize memory controller (also test AGP) */ r = radeon_mc_init(rdev); -- cgit v1.2.3 From f657c2a7310ad56e2b67f35f4c5c6106a7146b9c Mon Sep 17 00:00:00 2001 From: Yang Zhao Date: Tue, 15 Sep 2009 12:21:01 +1000 Subject: drm/radeon: Save and restore bios scratch regs during S/R [airlied:- adapted slightly in naming] Signed-off-by: Yang Zhao Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon.h | 2 ++ drivers/gpu/drm/radeon/radeon_atombios.c | 28 ++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/radeon_device.c | 3 +++ drivers/gpu/drm/radeon/radeon_mode.h | 2 ++ 4 files changed, 35 insertions(+) (limited to 'drivers/gpu/drm/radeon/radeon_device.c') diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index ff9e4171559a..5bfc05612ac2 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -75,6 +75,7 @@ extern int radeon_tv; #define RADEON_IB_POOL_SIZE 16 #define RADEON_DEBUGFS_MAX_NUM_FILES 32 #define RADEONFB_CONN_LIMIT 4 +#define RADEON_BIOS_NUM_SCRATCH 8 enum radeon_family { CHIP_R100, @@ -783,6 +784,7 @@ struct radeon_device { struct radeon_asic *asic; struct radeon_gem gem; struct radeon_pm pm; + uint32_t bios_scratch[RADEON_BIOS_NUM_SCRATCH]; struct mutex cs_mutex; struct radeon_wb wb; struct radeon_dummy_page dummy_page; diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index aa756dec8959..cb5efcaf2bab 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -1045,6 +1045,34 @@ void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev) } +void radeon_save_bios_scratch_regs(struct radeon_device *rdev) +{ + uint32_t scratch_reg; + int i; + + if (rdev->family >= CHIP_R600) + scratch_reg = R600_BIOS_0_SCRATCH; + else + scratch_reg = RADEON_BIOS_0_SCRATCH; + + for (i = 0; i < RADEON_BIOS_NUM_SCRATCH; i++) + rdev->bios_scratch[i] = RREG32(scratch_reg + (i * 4)); +} + +void radeon_restore_bios_scratch_regs(struct radeon_device *rdev) +{ + uint32_t scratch_reg; + int i; + + if (rdev->family >= CHIP_R600) + scratch_reg = R600_BIOS_0_SCRATCH; + else + scratch_reg = RADEON_BIOS_0_SCRATCH; + + for (i = 0; i < RADEON_BIOS_NUM_SCRATCH; i++) + WREG32(scratch_reg + (i * 4), rdev->bios_scratch[i]); +} + void radeon_atom_output_lock(struct drm_encoder *encoder, bool lock) { struct drm_device *dev = encoder->dev; diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index cc8e005c1b30..db5ae73d6289 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -755,6 +755,8 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) /* wait for gpu to finish processing current batch */ radeon_fence_wait_last(rdev); + radeon_save_bios_scratch_regs(rdev); + if (!rdev->new_init_path) { radeon_cp_disable(rdev); radeon_gart_disable(rdev); @@ -828,6 +830,7 @@ int radeon_resume_kms(struct drm_device *dev) radeon_resume(rdev); } out: + radeon_restore_bios_scratch_regs(rdev); fb_set_suspend(rdev->fbdev_info, 0); release_console_sem(); diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 523d6cbd4f08..dde13817dee0 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -383,6 +383,8 @@ extern void radeon_combios_output_lock(struct drm_encoder *encoder, bool lock); extern void radeon_combios_initialize_bios_scratch_regs(struct drm_device *dev); extern void radeon_atom_output_lock(struct drm_encoder *encoder, bool lock); extern void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev); +extern void radeon_save_bios_scratch_regs(struct radeon_device *rdev); +extern void radeon_restore_bios_scratch_regs(struct radeon_device *rdev); extern void radeon_atombios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc); extern void -- cgit v1.2.3 From 733289c2656c556d5cf36eafa1c8ec77222c359f Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Wed, 16 Sep 2009 15:24:21 +0200 Subject: drm/radeon/kms: don't fail if we fail to init GPU acceleration Userspace can query if acceleration is working or not true get info ioctl and could fallback to software if for some reason kernel failed to initialize KMS. This should allow to give a working KMS setup in all case (even with non functionning accel). Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r420.c | 2 ++ drivers/gpu/drm/radeon/r600.c | 33 +++++++++++++------------ drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_device.c | 44 ++++++++++++++-------------------- drivers/gpu/drm/radeon/radeon_kms.c | 3 +++ drivers/gpu/drm/radeon/rv770.c | 33 +++++++++++++------------ include/drm/radeon_drm.h | 1 + 7 files changed, 61 insertions(+), 56 deletions(-) (limited to 'drivers/gpu/drm/radeon/radeon_device.c') diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index 33a25a4377b8..2142a4781970 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c @@ -329,6 +329,7 @@ int r420_init(struct radeon_device *rdev) return r; } r300_set_reg_safe(rdev); + rdev->accel_working = true; r = r420_resume(rdev); if (r) { /* Somethings want wront with the accel init stop accel */ @@ -343,6 +344,7 @@ int r420_init(struct radeon_device *rdev) r100_pci_gart_fini(rdev); radeon_agp_fini(rdev); radeon_irq_kms_fini(rdev); + rdev->accel_working = false; } return 0; } diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 65699e9f2025..af430d719e7f 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1573,6 +1573,7 @@ int r600_init(struct radeon_device *rdev) if (r) return r; + rdev->accel_working = true; r = r600_resume(rdev); if (r) { if (rdev->flags & RADEON_IS_AGP) { @@ -1581,22 +1582,24 @@ int r600_init(struct radeon_device *rdev) rdev->flags &= ~RADEON_IS_AGP; return r600_init(rdev); } - return r; - } - r = radeon_ib_pool_init(rdev); - if (r) { - DRM_ERROR("radeon: failled initializing IB pool (%d).\n", r); - return r; + rdev->accel_working = false; } - r = r600_blit_init(rdev); - if (r) { - DRM_ERROR("radeon: failled blitter (%d).\n", r); - return r; - } - r = radeon_ib_test(rdev); - if (r) { - DRM_ERROR("radeon: failled testing IB (%d).\n", r); - return r; + if (rdev->accel_working) { + r = radeon_ib_pool_init(rdev); + if (r) { + DRM_ERROR("radeon: failled initializing IB pool (%d).\n", r); + rdev->accel_working = false; + } + r = r600_blit_init(rdev); + if (r) { + DRM_ERROR("radeon: failled blitter (%d).\n", r); + rdev->accel_working = false; + } + r = radeon_ib_test(rdev); + if (r) { + DRM_ERROR("radeon: failled testing IB (%d).\n", r); + rdev->accel_working = false; + } } return 0; } diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 5bfc05612ac2..d7c4efd08928 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -793,6 +793,7 @@ struct radeon_device { bool suspend; bool need_dma32; bool new_init_path; + bool accel_working; struct radeon_surface_reg surface_regs[RADEON_GEM_MAX_SURFACES]; const struct firmware *me_fw; /* all family ME firmware */ const struct firmware *pfp_fw; /* r6/700 PFP firmware */ diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index db5ae73d6289..0b5014c2ae7f 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -504,6 +504,7 @@ int radeon_device_init(struct radeon_device *rdev, rdev->usec_timeout = RADEON_MAX_USEC_TIMEOUT; rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; rdev->gpu_lockup = false; + rdev->accel_working = false; /* mutex initialization are all done here so we * can recall function without having locking issues */ mutex_init(&rdev->cs_mutex); @@ -649,35 +650,26 @@ int radeon_device_init(struct radeon_device *rdev, /* Initialize GART (initialize after TTM so we can allocate * memory through TTM but finalize after TTM) */ r = radeon_gart_enable(rdev); - if (!r) { + if (r) + return 0; r = radeon_gem_init(rdev); - } + if (r) + return 0; /* 1M ring buffer */ - if (!r) { - r = radeon_cp_init(rdev, 1024 * 1024); - } - if (!r) { - r = radeon_wb_init(rdev); - if (r) { - DRM_ERROR("radeon: failled initializing WB (%d).\n", r); - return r; - } - } - if (!r) { - r = radeon_ib_pool_init(rdev); - if (r) { - DRM_ERROR("radeon: failled initializing IB pool (%d).\n", r); - return r; - } - } - if (!r) { - r = radeon_ib_test(rdev); - if (r) { - DRM_ERROR("radeon: failled testing IB (%d).\n", r); - return r; - } - } + r = radeon_cp_init(rdev, 1024 * 1024); + if (r) + return 0; + r = radeon_wb_init(rdev); + if (r) + DRM_ERROR("radeon: failled initializing WB (%d).\n", r); + r = radeon_ib_pool_init(rdev); + if (r) + return 0; + r = radeon_ib_test(rdev); + if (r) + return 0; + rdev->accel_working = true; } DRM_INFO("radeon: kernel modesetting successfully initialized.\n"); if (radeon_testing) { diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index ac8505fe2ca7..709bd892b3a9 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -112,6 +112,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) case RADEON_INFO_NUM_Z_PIPES: value = rdev->num_z_pipes; break; + case RADEON_INFO_ACCEL_WORKING: + value = rdev->accel_working; + break; default: DRM_DEBUG("Invalid request %d\n", info->request); return -EINVAL; diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 4f2098bc7974..be2f86539ebc 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -953,6 +953,7 @@ int rv770_init(struct radeon_device *rdev) if (r) return r; + rdev->accel_working = true; r = rv770_resume(rdev); if (r) { if (rdev->flags & RADEON_IS_AGP) { @@ -961,22 +962,24 @@ int rv770_init(struct radeon_device *rdev) rdev->flags &= ~RADEON_IS_AGP; return rv770_init(rdev); } - return r; - } - r = r600_blit_init(rdev); - if (r) { - DRM_ERROR("radeon: failled blitter (%d).\n", r); - return r; + rdev->accel_working = false; } - r = radeon_ib_pool_init(rdev); - if (r) { - DRM_ERROR("radeon: failled initializing IB pool (%d).\n", r); - return r; - } - r = radeon_ib_test(rdev); - if (r) { - DRM_ERROR("radeon: failled testing IB (%d).\n", r); - return r; + if (rdev->accel_working) { + r = r600_blit_init(rdev); + if (r) { + DRM_ERROR("radeon: failled blitter (%d).\n", r); + rdev->accel_working = false; + } + r = radeon_ib_pool_init(rdev); + if (r) { + DRM_ERROR("radeon: failled initializing IB pool (%d).\n", r); + rdev->accel_working = false; + } + r = radeon_ib_test(rdev); + if (r) { + DRM_ERROR("radeon: failled testing IB (%d).\n", r); + rdev->accel_working = false; + } } return 0; } diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h index 2ba61e18fc8b..b67bbd75bd20 100644 --- a/include/drm/radeon_drm.h +++ b/include/drm/radeon_drm.h @@ -899,6 +899,7 @@ struct drm_radeon_cs { #define RADEON_INFO_DEVICE_ID 0x00 #define RADEON_INFO_NUM_GB_PIPES 0x01 #define RADEON_INFO_NUM_Z_PIPES 0x02 +#define RADEON_INFO_ACCEL_WORKING 0x03 struct drm_radeon_info { uint32_t request; -- cgit v1.2.3 From 5e6dde7ec2e72f49ff749204efc03a59478d7d34 Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Thu, 17 Sep 2009 09:42:28 +0200 Subject: drm/radeon/kms: Move radeon_get_clock_info() call out of radeon_clocks_init(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Someone on IRC reported problems after commit 95a8f1bf4f48b434c9f839ab5a0773f66b39d7c6 ('drm/radeon/kms: Move radeon_clocks_init() call back after getting VRAM info.'). And indeed, at least some ASIC vram_info hooks use the clock info obtained by radeon_get_clock_info(). So, move that call out of radeon_clocks_init(), ahead of the radeon_vram_info() call. [airlied - fixup missing r600/rv770 calls] Signed-off-by: Michel Dänzer Signed-off-by: Dave Airlie drm/radeon/kms: fix get clock info calls for r600/rv770 init path. These were missed when it got split out. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r600.c | 1 + drivers/gpu/drm/radeon/radeon_device.c | 4 ++-- drivers/gpu/drm/radeon/rv770.c | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/radeon/radeon_device.c') diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index af430d719e7f..1e1cab5ef1e4 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1537,6 +1537,7 @@ int r600_init(struct radeon_device *rdev) r600_scratch_init(rdev); /* Initialize surface registers */ radeon_surface_init(rdev); + radeon_get_clock_info(rdev->ddev); r = radeon_clocks_init(rdev); if (r) return r; diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 0b5014c2ae7f..8a40c616b534 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -386,7 +386,6 @@ int radeon_clocks_init(struct radeon_device *rdev) { int r; - radeon_get_clock_info(rdev->ddev); r = radeon_static_clocks_init(rdev->ddev); if (r) { return r; @@ -617,7 +616,8 @@ int radeon_device_init(struct radeon_device *rdev, radeon_combios_asic_init(rdev->ddev); } } - /* Get vram informations */ + /* Get clock & vram information */ + radeon_get_clock_info(rdev->ddev); radeon_vram_info(rdev); /* Initialize clocks */ r = radeon_clocks_init(rdev); diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index be2f86539ebc..8bab6b4f05d1 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -917,6 +917,7 @@ int rv770_init(struct radeon_device *rdev) r600_scratch_init(rdev); /* Initialize surface registers */ radeon_surface_init(rdev); + radeon_get_clock_info(rdev->ddev); r = radeon_clocks_init(rdev); if (r) return r; -- cgit v1.2.3 From 28d520433b6375740990ab99d69b0d0067fd656b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 21 Sep 2009 14:33:58 +1000 Subject: drm/vgaarb: add VGA arbitration support to the drm and kms. VGA arb requires DRM support for non-kms drivers, to turn on/off irqs when disabling the mem/io regions. VGA arb requires KMS support for GPUs where we can turn off VGA decoding. Currently we know how to do this for intel and radeon kms drivers, which allows them to be removed from the arbiter. This patch comes from Fedora rawhide kernel. Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_irq.c | 27 +++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_dma.c | 20 ++++++++++++++++++++ drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_display.c | 17 +++++++++++++++++ drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/radeon/r100.c | 14 ++++++++++++++ drivers/gpu/drm/radeon/r600.c | 14 ++++++++++++++ drivers/gpu/drm/radeon/r600d.h | 1 + drivers/gpu/drm/radeon/radeon.h | 2 ++ drivers/gpu/drm/radeon/radeon_asic.h | 12 ++++++++++++ drivers/gpu/drm/radeon/radeon_device.c | 21 ++++++++++++++++++++- include/drm/drmP.h | 3 +++ 13 files changed, 133 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/radeon/radeon_device.c') diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index f85aaf21e783..0a6f0b3bdc78 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -37,6 +37,7 @@ #include /* For task queue support */ +#include /** * Get interrupt from bus id. * @@ -171,6 +172,26 @@ err: } EXPORT_SYMBOL(drm_vblank_init); +static void drm_irq_vgaarb_nokms(void *cookie, bool state) +{ + struct drm_device *dev = cookie; + + if (dev->driver->vgaarb_irq) { + dev->driver->vgaarb_irq(dev, state); + return; + } + + if (!dev->irq_enabled) + return; + + if (state) + dev->driver->irq_uninstall(dev); + else { + dev->driver->irq_preinstall(dev); + dev->driver->irq_postinstall(dev); + } +} + /** * Install IRQ handler. * @@ -231,6 +252,9 @@ int drm_irq_install(struct drm_device *dev) return ret; } + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + vga_client_register(dev->pdev, (void *)dev, drm_irq_vgaarb_nokms, NULL); + /* After installing handler */ ret = dev->driver->irq_postinstall(dev); if (ret < 0) { @@ -279,6 +303,9 @@ int drm_irq_uninstall(struct drm_device * dev) DRM_DEBUG("irq=%d\n", dev->pdev->irq); + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + vga_client_register(dev->pdev, NULL, NULL, NULL); + dev->driver->irq_uninstall(dev); free_irq(dev->pdev->irq, dev); diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 9909505d070a..5a49a1867b35 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -33,6 +33,7 @@ #include "intel_drv.h" #include "i915_drm.h" #include "i915_drv.h" +#include /* Really want an OS-independent resettable timer. Would like to have * this loop run for (eg) 3 sec, but have the timer reset every time @@ -1012,6 +1013,19 @@ static int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size, return 0; } +/* true = enable decode, false = disable decoder */ +static unsigned int i915_vga_set_decode(void *cookie, bool state) +{ + struct drm_device *dev = cookie; + + intel_modeset_vga_set_state(dev, state); + if (state) + return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | + VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; + else + return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; +} + static int i915_load_modeset_init(struct drm_device *dev, unsigned long prealloc_size, unsigned long agp_size) @@ -1057,6 +1071,11 @@ static int i915_load_modeset_init(struct drm_device *dev, if (ret) DRM_INFO("failed to find VBIOS tables\n"); + /* if we have > 1 VGA cards, then disable the radeon VGA resources */ + ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode); + if (ret) + goto destroy_ringbuffer; + ret = drm_irq_install(dev); if (ret) goto destroy_ringbuffer; @@ -1324,6 +1343,7 @@ int i915_driver_unload(struct drm_device *dev) if (drm_core_check_feature(dev, DRIVER_MODESET)) { drm_irq_uninstall(dev); + vga_client_register(dev->pdev, NULL, NULL, NULL); } if (dev->pdev->msi_enabled) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 77ed060b4292..a0632f8e76ac 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -766,6 +766,7 @@ static inline void opregion_enable_asle(struct drm_device *dev) { return; } /* modesetting */ extern void intel_modeset_init(struct drm_device *dev); extern void intel_modeset_cleanup(struct drm_device *dev); +extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state); /** * Lock test for when it's just for synchronization of ring access. diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e38cd21161c8..3f7963553464 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -30,6 +30,7 @@ * fb aperture size and the amount of pre-reserved memory. */ #define INTEL_GMCH_CTRL 0x52 +#define INTEL_GMCH_VGA_DISABLE (1 << 1) #define INTEL_GMCH_ENABLED 0x4 #define INTEL_GMCH_MEM_MASK 0x1 #define INTEL_GMCH_MEM_64M 0x1 diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 155719ff99d1..0227b1652906 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3917,3 +3917,20 @@ struct drm_encoder *intel_best_encoder(struct drm_connector *connector) return &intel_output->enc; } + +/* + * set vga decode state - true == enable VGA decode + */ +int intel_modeset_vga_set_state(struct drm_device *dev, bool state) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u16 gmch_ctrl; + + pci_read_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, &gmch_ctrl); + if (state) + gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE; + else + gmch_ctrl |= INTEL_GMCH_VGA_DISABLE; + pci_write_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, gmch_ctrl); + return 0; +} diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index b9e47f1e1cc0..3a0004f755d0 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -178,4 +178,5 @@ extern int intel_framebuffer_create(struct drm_device *dev, struct drm_mode_fb_cmd *mode_cmd, struct drm_framebuffer **fb, struct drm_gem_object *obj); + #endif /* __INTEL_DRV_H__ */ diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 737970b43aef..be51c5f7d0f6 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -1955,6 +1955,20 @@ void r100_vram_init_sizes(struct radeon_device *rdev) rdev->mc.real_vram_size = rdev->mc.aper_size; } +void r100_vga_set_state(struct radeon_device *rdev, bool state) +{ + uint32_t temp; + + temp = RREG32(RADEON_CONFIG_CNTL); + if (state == false) { + temp &= ~(1<<8); + temp |= (1<<9); + } else { + temp &= ~(1<<9); + } + WREG32(RADEON_CONFIG_CNTL, temp); +} + void r100_vram_info(struct radeon_device *rdev) { r100_vram_get_type(rdev); diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 5f42fad19190..eab31c1d6df1 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1499,6 +1499,20 @@ int r600_startup(struct radeon_device *rdev) return 0; } +void r600_vga_set_state(struct radeon_device *rdev, bool state) +{ + uint32_t temp; + + temp = RREG32(CONFIG_CNTL); + if (state == false) { + temp &= ~(1<<0); + temp |= (1<<1); + } else { + temp &= ~(1<<1); + } + WREG32(CONFIG_CNTL, temp); +} + int r600_resume(struct radeon_device *rdev) { int r; diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 723295f59281..4a9028a85c9b 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -78,6 +78,7 @@ #define CB_COLOR0_MASK 0x28100 #define CONFIG_MEMSIZE 0x5428 +#define CONFIG_CNTL 0x5424 #define CP_STAT 0x8680 #define CP_COHER_BASE 0x85F8 #define CP_DEBUG 0xC1FC diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 817af8ecff10..c839b608970f 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -596,6 +596,7 @@ struct radeon_asic { int (*suspend)(struct radeon_device *rdev); void (*errata)(struct radeon_device *rdev); void (*vram_info)(struct radeon_device *rdev); + void (*vga_set_state)(struct radeon_device *rdev, bool state); int (*gpu_reset)(struct radeon_device *rdev); int (*mc_init)(struct radeon_device *rdev); void (*mc_fini)(struct radeon_device *rdev); @@ -954,6 +955,7 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v) #define radeon_cs_parse(p) rdev->asic->cs_parse((p)) #define radeon_errata(rdev) (rdev)->asic->errata((rdev)) #define radeon_vram_info(rdev) (rdev)->asic->vram_info((rdev)) +#define radeon_vga_set_state(rdev, state) (rdev)->asic->vga_set_state((rdev), (state)) #define radeon_gpu_reset(rdev) (rdev)->asic->gpu_reset((rdev)) #define radeon_mc_init(rdev) (rdev)->asic->mc_init((rdev)) #define radeon_mc_fini(rdev) (rdev)->asic->mc_fini((rdev)) diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 5f2a9e6f12c5..8968f78fa1e3 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -47,6 +47,7 @@ uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg); void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); void r100_errata(struct radeon_device *rdev); void r100_vram_info(struct radeon_device *rdev); +void r100_vga_set_state(struct radeon_device *rdev, bool state); int r100_gpu_reset(struct radeon_device *rdev); int r100_mc_init(struct radeon_device *rdev); void r100_mc_fini(struct radeon_device *rdev); @@ -89,6 +90,7 @@ static struct radeon_asic r100_asic = { .init = &r100_init, .errata = &r100_errata, .vram_info = &r100_vram_info, + .vga_set_state = &r100_vga_set_state, .gpu_reset = &r100_gpu_reset, .mc_init = &r100_mc_init, .mc_fini = &r100_mc_fini, @@ -158,6 +160,7 @@ static struct radeon_asic r300_asic = { .init = &r300_init, .errata = &r300_errata, .vram_info = &r300_vram_info, + .vga_set_state = &r100_vga_set_state, .gpu_reset = &r300_gpu_reset, .mc_init = &r300_mc_init, .mc_fini = &r300_mc_fini, @@ -208,6 +211,7 @@ static struct radeon_asic r420_asic = { .resume = &r420_resume, .errata = NULL, .vram_info = NULL, + .vga_set_state = &r100_vga_set_state, .gpu_reset = &r300_gpu_reset, .mc_init = NULL, .mc_fini = NULL, @@ -262,6 +266,7 @@ static struct radeon_asic rs400_asic = { .init = &r300_init, .errata = &rs400_errata, .vram_info = &rs400_vram_info, + .vga_set_state = &r100_vga_set_state, .gpu_reset = &r300_gpu_reset, .mc_init = &rs400_mc_init, .mc_fini = &rs400_mc_fini, @@ -323,6 +328,7 @@ static struct radeon_asic rs600_asic = { .init = &rs600_init, .errata = &rs600_errata, .vram_info = &rs600_vram_info, + .vga_set_state = &r100_vga_set_state, .gpu_reset = &r300_gpu_reset, .mc_init = &rs600_mc_init, .mc_fini = &rs600_mc_fini, @@ -372,6 +378,7 @@ static struct radeon_asic rs690_asic = { .init = &rs600_init, .errata = &rs690_errata, .vram_info = &rs690_vram_info, + .vga_set_state = &r100_vga_set_state, .gpu_reset = &r300_gpu_reset, .mc_init = &rs690_mc_init, .mc_fini = &rs690_mc_fini, @@ -428,6 +435,7 @@ static struct radeon_asic rv515_asic = { .init = &rv515_init, .errata = &rv515_errata, .vram_info = &rv515_vram_info, + .vga_set_state = &r100_vga_set_state, .gpu_reset = &rv515_gpu_reset, .mc_init = &rv515_mc_init, .mc_fini = &rv515_mc_fini, @@ -477,6 +485,7 @@ static struct radeon_asic r520_asic = { .init = &rv515_init, .errata = &r520_errata, .vram_info = &r520_vram_info, + .vga_set_state = &r100_vga_set_state, .gpu_reset = &rv515_gpu_reset, .mc_init = &r520_mc_init, .mc_fini = &r520_mc_fini, @@ -520,6 +529,7 @@ int r600_init(struct radeon_device *rdev); void r600_fini(struct radeon_device *rdev); int r600_suspend(struct radeon_device *rdev); int r600_resume(struct radeon_device *rdev); +void r600_vga_set_state(struct radeon_device *rdev, bool state); int r600_wb_init(struct radeon_device *rdev); void r600_wb_fini(struct radeon_device *rdev); void r600_cp_commit(struct radeon_device *rdev); @@ -556,6 +566,7 @@ static struct radeon_asic r600_asic = { .resume = &r600_resume, .cp_commit = &r600_cp_commit, .vram_info = NULL, + .vga_set_state = &r600_vga_set_state, .gpu_reset = &r600_gpu_reset, .mc_init = NULL, .mc_fini = NULL, @@ -606,6 +617,7 @@ static struct radeon_asic rv770_asic = { .cp_commit = &r600_cp_commit, .vram_info = NULL, .gpu_reset = &rv770_gpu_reset, + .vga_set_state = &r600_vga_set_state, .mc_init = NULL, .mc_fini = NULL, .wb_init = &r600_wb_init, diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 8a40c616b534..daf5db780956 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "radeon_reg.h" #include "radeon.h" #include "radeon_asic.h" @@ -480,7 +481,18 @@ void radeon_combios_fini(struct radeon_device *rdev) { } +/* if we get transitioned to only one device, tak VGA back */ +static unsigned int radeon_vga_set_decode(void *cookie, bool state) +{ + struct radeon_device *rdev = cookie; + radeon_vga_set_state(rdev, state); + if (state) + return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | + VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; + else + return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; +} /* * Radeon device. */ @@ -578,6 +590,13 @@ int radeon_device_init(struct radeon_device *rdev, if (r) { return r; } + + /* if we have > 1 VGA cards, then disable the radeon VGA resources */ + r = vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode); + if (r) { + return -EINVAL; + } + if (!rdev->new_init_path) { /* Setup errata flags */ radeon_errata(rdev); @@ -586,7 +605,6 @@ int radeon_device_init(struct radeon_device *rdev, /* Initialize surface registers */ radeon_surface_init(rdev); - /* TODO: disable VGA need to use VGA request */ /* BIOS*/ if (!radeon_get_bios(rdev)) { if (ASIC_IS_AVIVO(rdev)) @@ -697,6 +715,7 @@ void radeon_device_fini(struct radeon_device *rdev) radeon_agp_fini(rdev); #endif radeon_irq_kms_fini(rdev); + vga_client_register(rdev->pdev, NULL, NULL, NULL); radeon_fence_driver_fini(rdev); radeon_clocks_fini(rdev); radeon_object_fini(rdev); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index eeefb6369e19..c8e64bbadbcf 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -810,6 +810,9 @@ struct drm_driver { int (*gem_init_object) (struct drm_gem_object *obj); void (*gem_free_object) (struct drm_gem_object *obj); + /* vga arb irq handler */ + void (*vgaarb_irq)(struct drm_device *dev, bool state); + /* Driver private ops for this object */ struct vm_operations_struct *gem_vm_ops; -- cgit v1.2.3