/* * 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
*/
/* RV410 and R420 can lock up if CP DMA to host memory happens * while the 2D engine is busy. * * The proper workaround is to queue a RESYNC at the beginning * of the CP init, apparently.
*/
radeon_scratch_get(rdev, &rdev->config.r300.resync_scratch);
r = radeon_ring_lock(rdev, ring, 8);
WARN_ON(r);
radeon_ring_write(ring, PACKET0(R300_CP_RESYNC_ADDR, 1));
radeon_ring_write(ring, rdev->config.r300.resync_scratch);
radeon_ring_write(ring, 0xDEADBEEF);
radeon_ring_unlock_commit(rdev, ring, false);
}
/* Catch the RESYNC we dispatched all the way back, * at the very beginning of the CP init.
*/
r = radeon_ring_lock(rdev, ring, 8);
WARN_ON(r);
radeon_ring_write(ring, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
radeon_ring_write(ring, R300_RB3D_DC_FINISH);
radeon_ring_unlock_commit(rdev, ring, false);
radeon_scratch_free(rdev, rdev->config.r300.resync_scratch);
}
staticint r420_startup(struct radeon_device *rdev)
{ int r;
/* set common regs */
r100_set_common_regs(rdev); /* program mc */
r300_mc_program(rdev); /* Resume clock */
r420_clock_resume(rdev); /* Initialize GART (initialize after TTM so we can allocate
* memory through TTM but finalize after TTM) */ 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);
/* allocate wb buffer */
r = radeon_wb_init(rdev); if (r) return r;
r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); if (r) {
dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); return r;
}
/* Enable IRQ */ if (!rdev->irq.installed) {
r = radeon_irq_kms_init(rdev); if (r) return r;
}
r100_irq_set(rdev);
rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); /* 1M ring buffer */
r = r100_cp_init(rdev, 1024 * 1024); if (r) {
dev_err(rdev->dev, "failed initializing CP (%d).\n", r); return r;
}
r420_cp_errata_init(rdev);
r = radeon_ib_pool_init(rdev); if (r) {
dev_err(rdev->dev, "IB initialization failed (%d).\n", r); return r;
}
return 0;
}
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 */ if (radeon_asic_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_to_drm(rdev));
} /* Resume clock after posting */
r420_clock_resume(rdev); /* Initialize surface registers */
radeon_surface_init(rdev);
rdev->accel_working = true;
r = r420_startup(rdev); if (r) {
rdev->accel_working = false;
} return r;
}
int r420_suspend(struct radeon_device *rdev)
{
radeon_pm_suspend(rdev);
r420_cp_errata_fini(rdev);
r100_cp_disable(rdev);
radeon_wb_disable(rdev);
r100_irq_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;
}
int r420_init(struct radeon_device *rdev)
{ int r;
/* Initialize scratch registers */
radeon_scratch_init(rdev); /* Initialize surface registers */
radeon_surface_init(rdev); /* TODO: disable VGA need to use VGA request */ /* restore some register to sane defaults */
r100_restore_sanity(rdev); /* 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_asic_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_boot_test_post_card(rdev) == false) return -EINVAL;
/* Initialize clocks */
radeon_get_clock_info(rdev_to_drm(rdev)); /* initialize AGP */ if (rdev->flags & RADEON_IS_AGP) {
r = radeon_agp_init(rdev); if (r) {
radeon_agp_disable(rdev);
}
} /* initialize memory controller */
r300_mc_init(rdev);
r420_debugfs(rdev); /* Fence driver */
radeon_fence_driver_init(rdev); /* Memory manager */
r = radeon_bo_init(rdev); if (r) { return r;
} if (rdev->family == CHIP_R420)
r100_enable_bm(rdev);
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;
}
r420_set_reg_safe(rdev);
/* Initialize power management */
radeon_pm_init(rdev);
rdev->accel_working = true;
r = r420_startup(rdev); if (r) { /* Somethings want wront with the accel init stop accel */
dev_err(rdev->dev, "Disabling GPU acceleration\n");
r100_cp_fini(rdev);
radeon_wb_fini(rdev);
radeon_ib_pool_fini(rdev);
radeon_irq_kms_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);
rdev->accel_working = false;
} return 0;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.