diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_device.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_device.c | 161 |
1 files changed, 136 insertions, 25 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index dd279da90546..8adfedfe547f 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -117,9 +117,10 @@ void radeon_scratch_init(struct radeon_device *rdev) } else { rdev->scratch.num_reg = 7; } + rdev->scratch.reg_base = RADEON_SCRATCH_REG0; for (i = 0; i < rdev->scratch.num_reg; i++) { rdev->scratch.free[i] = true; - rdev->scratch.reg[i] = RADEON_SCRATCH_REG0 + (i * 4); + rdev->scratch.reg[i] = rdev->scratch.reg_base + (i * 4); } } @@ -149,6 +150,86 @@ void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg) } } +void radeon_wb_disable(struct radeon_device *rdev) +{ + int r; + + if (rdev->wb.wb_obj) { + r = radeon_bo_reserve(rdev->wb.wb_obj, false); + if (unlikely(r != 0)) + return; + radeon_bo_kunmap(rdev->wb.wb_obj); + radeon_bo_unpin(rdev->wb.wb_obj); + radeon_bo_unreserve(rdev->wb.wb_obj); + } + rdev->wb.enabled = false; +} + +void radeon_wb_fini(struct radeon_device *rdev) +{ + radeon_wb_disable(rdev); + if (rdev->wb.wb_obj) { + radeon_bo_unref(&rdev->wb.wb_obj); + rdev->wb.wb = NULL; + rdev->wb.wb_obj = NULL; + } +} + +int radeon_wb_init(struct radeon_device *rdev) +{ + int r; + + if (rdev->wb.wb_obj == NULL) { + r = radeon_bo_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, true, + RADEON_GEM_DOMAIN_GTT, &rdev->wb.wb_obj); + if (r) { + dev_warn(rdev->dev, "(%d) create WB bo failed\n", r); + return r; + } + } + r = radeon_bo_reserve(rdev->wb.wb_obj, false); + if (unlikely(r != 0)) { + radeon_wb_fini(rdev); + return r; + } + r = radeon_bo_pin(rdev->wb.wb_obj, RADEON_GEM_DOMAIN_GTT, + &rdev->wb.gpu_addr); + if (r) { + radeon_bo_unreserve(rdev->wb.wb_obj); + dev_warn(rdev->dev, "(%d) pin WB bo failed\n", r); + radeon_wb_fini(rdev); + return r; + } + r = radeon_bo_kmap(rdev->wb.wb_obj, (void **)&rdev->wb.wb); + radeon_bo_unreserve(rdev->wb.wb_obj); + if (r) { + dev_warn(rdev->dev, "(%d) map WB bo failed\n", r); + radeon_wb_fini(rdev); + return r; + } + + /* disable event_write fences */ + rdev->wb.use_event = false; + /* disabled via module param */ + if (radeon_no_wb == 1) + rdev->wb.enabled = false; + else { + /* often unreliable on AGP */ + if (rdev->flags & RADEON_IS_AGP) { + rdev->wb.enabled = false; + } else { + rdev->wb.enabled = true; + /* event_write fences are only available on r600+ */ + if (rdev->family >= CHIP_R600) + rdev->wb.use_event = true; + } + } + + dev_info(rdev->dev, "WB %sabled\n", rdev->wb.enabled ? "en" : "dis"); + + return 0; +} + /** * radeon_vram_location - try to find VRAM location * @rdev: radeon device structure holding all necessary informations @@ -199,7 +280,7 @@ void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 mc->mc_vram_size = mc->aper_size; } mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; - if (rdev->flags & RADEON_IS_AGP && mc->vram_end > mc->gtt_start && mc->vram_end <= mc->gtt_end) { + if (rdev->flags & RADEON_IS_AGP && mc->vram_end > mc->gtt_start && mc->vram_start <= mc->gtt_end) { dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n"); mc->real_vram_size = mc->aper_size; mc->mc_vram_size = mc->aper_size; @@ -293,30 +374,20 @@ bool radeon_card_posted(struct radeon_device *rdev) void radeon_update_bandwidth_info(struct radeon_device *rdev) { fixed20_12 a; - u32 sclk, mclk; - - if (rdev->flags & RADEON_IS_IGP) { - sclk = radeon_get_engine_clock(rdev); - mclk = rdev->clock.default_mclk; + u32 sclk = rdev->pm.current_sclk; + u32 mclk = rdev->pm.current_mclk; - a.full = dfixed_const(100); - rdev->pm.sclk.full = dfixed_const(sclk); - rdev->pm.sclk.full = dfixed_div(rdev->pm.sclk, a); - rdev->pm.mclk.full = dfixed_const(mclk); - rdev->pm.mclk.full = dfixed_div(rdev->pm.mclk, a); + /* sclk/mclk in Mhz */ + a.full = dfixed_const(100); + rdev->pm.sclk.full = dfixed_const(sclk); + rdev->pm.sclk.full = dfixed_div(rdev->pm.sclk, a); + rdev->pm.mclk.full = dfixed_const(mclk); + rdev->pm.mclk.full = dfixed_div(rdev->pm.mclk, a); + if (rdev->flags & RADEON_IS_IGP) { a.full = dfixed_const(16); /* core_bandwidth = sclk(Mhz) * 16 */ rdev->pm.core_bandwidth.full = dfixed_div(rdev->pm.sclk, a); - } else { - sclk = radeon_get_engine_clock(rdev); - mclk = radeon_get_memory_clock(rdev); - - a.full = dfixed_const(100); - rdev->pm.sclk.full = dfixed_const(sclk); - rdev->pm.sclk.full = dfixed_div(rdev->pm.sclk, a); - rdev->pm.mclk.full = dfixed_const(mclk); - rdev->pm.mclk.full = dfixed_div(rdev->pm.mclk, a); } } @@ -347,7 +418,8 @@ int radeon_dummy_page_init(struct radeon_device *rdev) 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) { + if (pci_dma_mapping_error(rdev->pdev, rdev->dummy_page.addr)) { + dev_err(&rdev->pdev->dev, "Failed to DMA MAP the dummy page\n"); __free_page(rdev->dummy_page.page); rdev->dummy_page.page = NULL; return -ENOMEM; @@ -415,6 +487,22 @@ static uint32_t cail_reg_read(struct card_info *info, uint32_t reg) return r; } +static void cail_ioreg_write(struct card_info *info, uint32_t reg, uint32_t val) +{ + struct radeon_device *rdev = info->dev->dev_private; + + WREG32_IO(reg*4, val); +} + +static uint32_t cail_ioreg_read(struct card_info *info, uint32_t reg) +{ + struct radeon_device *rdev = info->dev->dev_private; + uint32_t r; + + r = RREG32_IO(reg*4); + return r; +} + int radeon_atombios_init(struct radeon_device *rdev) { struct card_info *atom_card_info = @@ -427,6 +515,15 @@ int radeon_atombios_init(struct radeon_device *rdev) atom_card_info->dev = rdev->ddev; atom_card_info->reg_read = cail_reg_read; atom_card_info->reg_write = cail_reg_write; + /* needed for iio ops */ + if (rdev->rio_mem) { + atom_card_info->ioreg_read = cail_ioreg_read; + atom_card_info->ioreg_write = cail_ioreg_write; + } else { + DRM_ERROR("Unable to find PCI I/O BAR; using MMIO for ATOM IIO\n"); + atom_card_info->ioreg_read = cail_reg_read; + atom_card_info->ioreg_write = cail_reg_write; + } atom_card_info->mc_read = cail_mc_read; atom_card_info->mc_write = cail_mc_write; atom_card_info->pll_read = cail_pll_read; @@ -573,7 +670,7 @@ int radeon_device_init(struct radeon_device *rdev, struct pci_dev *pdev, uint32_t flags) { - int r; + int r, i; int dma_bits; rdev->shutdown = false; @@ -650,8 +747,8 @@ int radeon_device_init(struct radeon_device *rdev, /* Registers mapping */ /* TODO: block userspace mapping of io register */ - rdev->rmmio_base = drm_get_resource_start(rdev->ddev, 2); - rdev->rmmio_size = drm_get_resource_len(rdev->ddev, 2); + rdev->rmmio_base = pci_resource_start(rdev->pdev, 2); + rdev->rmmio_size = pci_resource_len(rdev->pdev, 2); rdev->rmmio = ioremap(rdev->rmmio_base, rdev->rmmio_size); if (rdev->rmmio == NULL) { return -ENOMEM; @@ -659,6 +756,17 @@ 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); + /* io port mapping */ + for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { + if (pci_resource_flags(rdev->pdev, i) & IORESOURCE_IO) { + rdev->rio_mem_size = pci_resource_len(rdev->pdev, i); + rdev->rio_mem = pci_iomap(rdev->pdev, i, rdev->rio_mem_size); + break; + } + } + if (rdev->rio_mem == NULL) + DRM_ERROR("Unable to find PCI I/O BAR\n"); + /* if we have > 1 VGA cards, then disable the radeon VGA resources */ /* this will fail for cards that aren't VGA class devices, just * ignore it */ @@ -701,6 +809,9 @@ void radeon_device_fini(struct radeon_device *rdev) destroy_workqueue(rdev->wq); vga_switcheroo_unregister_client(rdev->pdev); vga_client_register(rdev->pdev, NULL, NULL, NULL); + if (rdev->rio_mem) + pci_iounmap(rdev->pdev, rdev->rio_mem); + rdev->rio_mem = NULL; iounmap(rdev->rmmio); rdev->rmmio = NULL; } |