From b2d70917e4b9fc5bddfbd025bfb1f15185e74971 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Sat, 27 Jul 2013 17:53:25 -0400 Subject: drm/radeon: properly handle cg on asics without UVD Don't try and enable clockgating if the asic doesn't have UVD. Use rdev->has_uvd rather than using local checks. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/si.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/radeon/si.c') diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index d325280e2f9..1d656f7b13f 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -5215,14 +5215,12 @@ static void si_enable_mc_ls(struct radeon_device *rdev, static void si_init_cg(struct radeon_device *rdev) { - bool has_uvd = true; - si_enable_mgcg(rdev, true); si_enable_cgcg(rdev, true); /* disable MC LS on Tahiti */ if (rdev->family == CHIP_TAHITI) si_enable_mc_ls(rdev, false); - if (has_uvd) { + if (rdev->has_uvd) { si_enable_uvd_mgcg(rdev, true); si_init_uvd_internal_cg(rdev); } @@ -5230,9 +5228,7 @@ static void si_init_cg(struct radeon_device *rdev) static void si_fini_cg(struct radeon_device *rdev) { - bool has_uvd = true; - - if (has_uvd) + if (rdev->has_uvd) si_enable_uvd_mgcg(rdev, false); si_enable_cgcg(rdev, false); si_enable_mgcg(rdev, false); -- cgit v1.2.3-18-g5258 From 3652f00591982b15f0702dd90e4e5f0ddcfe7f8b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 29 Jul 2013 11:51:25 -0400 Subject: drm/radeon/si: disable cgcg and pg for now Coarse grain clockgating causes problems with reclocking on some cards and powergating (verde only) causes problems with ring initialization. The proper fix (restructuring the init sequences) is too invasive for 3.11 so just disable them for now. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/si.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/radeon/si.c') diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 1d656f7b13f..6ca904673a4 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -5216,7 +5216,7 @@ static void si_enable_mc_ls(struct radeon_device *rdev, static void si_init_cg(struct radeon_device *rdev) { si_enable_mgcg(rdev, true); - si_enable_cgcg(rdev, true); + si_enable_cgcg(rdev, false); /* disable MC LS on Tahiti */ if (rdev->family == CHIP_TAHITI) si_enable_mc_ls(rdev, false); @@ -5237,11 +5237,11 @@ static void si_fini_cg(struct radeon_device *rdev) static void si_init_pg(struct radeon_device *rdev) { bool has_pg = false; - +#if 0 /* only cape verde supports PG */ if (rdev->family == CHIP_VERDE) has_pg = true; - +#endif if (has_pg) { si_init_ao_cu_mask(rdev); si_init_dma_pg(rdev); -- cgit v1.2.3-18-g5258 From 2858c00d2823c83acce2a1175dbabb2cebee8678 Mon Sep 17 00:00:00 2001 From: Christian König Date: Thu, 1 Aug 2013 17:34:07 +0200 Subject: drm/radeon: fix halting UVD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removing the clock/power or resetting the VCPU can cause hangs if that happens in the middle of a register write. Stall the memory and register bus before putting the VCPU into reset. Keep it in reset when unloading the module or suspending. Signed-off-by: Christian König Cc: stable@vger.kernel.org Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/si.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/radeon/si.c') diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 6ca904673a4..242c1ac83e2 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -6621,7 +6621,7 @@ int si_suspend(struct radeon_device *rdev) si_cp_enable(rdev, false); cayman_dma_stop(rdev); if (rdev->has_uvd) { - r600_uvd_rbc_stop(rdev); + r600_uvd_stop(rdev); radeon_uvd_suspend(rdev); } si_irq_suspend(rdev); @@ -6763,8 +6763,10 @@ void si_fini(struct radeon_device *rdev) radeon_vm_manager_fini(rdev); radeon_ib_pool_fini(rdev); radeon_irq_kms_fini(rdev); - if (rdev->has_uvd) + if (rdev->has_uvd) { + r600_uvd_stop(rdev); radeon_uvd_fini(rdev); + } si_pcie_gart_fini(rdev); r600_vram_scratch_fini(rdev); radeon_gem_fini(rdev); -- cgit v1.2.3-18-g5258 From 6fab3febf6d949b0a12b1e4e73db38e4a177a79e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Sun, 4 Aug 2013 12:13:17 -0400 Subject: drm/radeon: always program the MC on startup For r6xx+ asics. This mirrors the behavior of pre-r6xx asics. We need to program the MC even if something else in startup() fails. Failure to do so results in an unusable GPU. Based on a fix from: Mark Kettenis Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/si.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/radeon/si.c') diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 242c1ac83e2..6a2dca4acfc 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -6418,6 +6418,8 @@ static int si_startup(struct radeon_device *rdev) /* enable aspm */ si_program_aspm(rdev); + si_mc_program(rdev); + if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw || !rdev->rlc_fw || !rdev->mc_fw) { r = si_init_microcode(rdev); @@ -6437,7 +6439,6 @@ static int si_startup(struct radeon_device *rdev) if (r) return r; - si_mc_program(rdev); r = si_pcie_gart_enable(rdev); if (r) return r; -- cgit v1.2.3-18-g5258 From 8a53fa23fd3e7c22d93f28e6aaae8358c53326ba Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 7 Aug 2013 16:09:08 -0400 Subject: drm/radeon: make missing smc ucode non-fatal The smc ucode is required for dpm (dynamic power management), but if it's missing just skip dpm setup and don't disable acceleration. Should fix: https://bugs.freedesktop.org/show_bug.cgi?id=67876 Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/si.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/radeon/si.c') diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 6a2dca4acfc..daa8d2df8ec 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -1663,9 +1663,13 @@ static int si_init_microcode(struct radeon_device *rdev) snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name); err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev); - if (err) - goto out; - if (rdev->smc_fw->size != smc_req_size) { + if (err) { + printk(KERN_ERR + "smc: error loading firmware \"%s\"\n", + fw_name); + release_firmware(rdev->smc_fw); + rdev->smc_fw = NULL; + } else if (rdev->smc_fw->size != smc_req_size) { printk(KERN_ERR "si_smc: Bogus length %zu in firmware \"%s\"\n", rdev->smc_fw->size, fw_name); -- cgit v1.2.3-18-g5258 From 866d83de0c9cc36a598252282bdedc158f50dcc2 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 15 Apr 2013 17:13:29 -0400 Subject: drm/radeon/cik: restructure rlc setup Restructure rlc setup to handle clock and power gating. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/si.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/radeon/si.c') diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index daa8d2df8ec..610adfc86be 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -5435,7 +5435,7 @@ int si_rlc_init(struct radeon_device *rdev) return 0; } -static void si_rlc_reset(struct radeon_device *rdev) +void si_rlc_reset(struct radeon_device *rdev) { u32 tmp = RREG32(GRBM_SOFT_RESET); -- cgit v1.2.3-18-g5258 From 1fd11777c2f0e6b6b37432b984bf40e3c6072f23 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 17 Apr 2013 17:53:50 -0400 Subject: drm/radeon: convert SI,CIK to use sumo_rlc functions and remove duplicate si_rlc functions. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/si.c | 174 +++----------------------------------------- 1 file changed, 11 insertions(+), 163 deletions(-) (limited to 'drivers/gpu/drm/radeon/si.c') diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 610adfc86be..8b8963d4a73 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -68,6 +68,8 @@ MODULE_FIRMWARE("radeon/HAINAN_smc.bin"); static void si_pcie_gen3_enable(struct radeon_device *rdev); static void si_program_aspm(struct radeon_device *rdev); +extern void sumo_rlc_fini(struct radeon_device *rdev); +extern int sumo_rlc_init(struct radeon_device *rdev); extern int r600_ih_ring_alloc(struct radeon_device *rdev); extern void r600_ih_ring_fini(struct radeon_device *rdev); extern void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev); @@ -5275,166 +5277,6 @@ static void si_fini_pg(struct radeon_device *rdev) /* * RLC */ -void si_rlc_fini(struct radeon_device *rdev) -{ - int r; - - /* save restore block */ - if (rdev->rlc.save_restore_obj) { - r = radeon_bo_reserve(rdev->rlc.save_restore_obj, false); - if (unlikely(r != 0)) - dev_warn(rdev->dev, "(%d) reserve RLC sr bo failed\n", r); - radeon_bo_unpin(rdev->rlc.save_restore_obj); - radeon_bo_unreserve(rdev->rlc.save_restore_obj); - - radeon_bo_unref(&rdev->rlc.save_restore_obj); - rdev->rlc.save_restore_obj = NULL; - } - - /* clear state block */ - if (rdev->rlc.clear_state_obj) { - r = radeon_bo_reserve(rdev->rlc.clear_state_obj, false); - if (unlikely(r != 0)) - dev_warn(rdev->dev, "(%d) reserve RLC c bo failed\n", r); - radeon_bo_unpin(rdev->rlc.clear_state_obj); - radeon_bo_unreserve(rdev->rlc.clear_state_obj); - - radeon_bo_unref(&rdev->rlc.clear_state_obj); - rdev->rlc.clear_state_obj = NULL; - } -} - -#define RLC_CLEAR_STATE_END_MARKER 0x00000001 - -int si_rlc_init(struct radeon_device *rdev) -{ - volatile u32 *dst_ptr; - u32 dws, data, i, j, k, reg_num; - u32 reg_list_num, reg_list_hdr_blk_index, reg_list_blk_index; - u64 reg_list_mc_addr; - const struct cs_section_def *cs_data = si_cs_data; - int r; - - /* save restore block */ - if (rdev->rlc.save_restore_obj == NULL) { - r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE, PAGE_SIZE, true, - RADEON_GEM_DOMAIN_VRAM, NULL, - &rdev->rlc.save_restore_obj); - if (r) { - dev_warn(rdev->dev, "(%d) create RLC sr bo failed\n", r); - return r; - } - } - - r = radeon_bo_reserve(rdev->rlc.save_restore_obj, false); - if (unlikely(r != 0)) { - si_rlc_fini(rdev); - return r; - } - r = radeon_bo_pin(rdev->rlc.save_restore_obj, RADEON_GEM_DOMAIN_VRAM, - &rdev->rlc.save_restore_gpu_addr); - if (r) { - radeon_bo_unreserve(rdev->rlc.save_restore_obj); - dev_warn(rdev->dev, "(%d) pin RLC sr bo failed\n", r); - si_rlc_fini(rdev); - return r; - } - - if (rdev->family == CHIP_VERDE) { - r = radeon_bo_kmap(rdev->rlc.save_restore_obj, (void **)&rdev->rlc.sr_ptr); - if (r) { - dev_warn(rdev->dev, "(%d) map RLC sr bo failed\n", r); - si_rlc_fini(rdev); - return r; - } - /* write the sr buffer */ - dst_ptr = rdev->rlc.sr_ptr; - for (i = 0; i < ARRAY_SIZE(verde_rlc_save_restore_register_list); i++) { - dst_ptr[i] = verde_rlc_save_restore_register_list[i]; - } - radeon_bo_kunmap(rdev->rlc.save_restore_obj); - } - radeon_bo_unreserve(rdev->rlc.save_restore_obj); - - /* clear state block */ - reg_list_num = 0; - dws = 0; - for (i = 0; cs_data[i].section != NULL; i++) { - for (j = 0; cs_data[i].section[j].extent != NULL; j++) { - reg_list_num++; - dws += cs_data[i].section[j].reg_count; - } - } - reg_list_blk_index = (3 * reg_list_num + 2); - dws += reg_list_blk_index; - - if (rdev->rlc.clear_state_obj == NULL) { - r = radeon_bo_create(rdev, dws * 4, PAGE_SIZE, true, - RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->rlc.clear_state_obj); - if (r) { - dev_warn(rdev->dev, "(%d) create RLC c bo failed\n", r); - si_rlc_fini(rdev); - return r; - } - } - r = radeon_bo_reserve(rdev->rlc.clear_state_obj, false); - if (unlikely(r != 0)) { - si_rlc_fini(rdev); - return r; - } - r = radeon_bo_pin(rdev->rlc.clear_state_obj, RADEON_GEM_DOMAIN_VRAM, - &rdev->rlc.clear_state_gpu_addr); - if (r) { - - radeon_bo_unreserve(rdev->rlc.clear_state_obj); - dev_warn(rdev->dev, "(%d) pin RLC c bo failed\n", r); - si_rlc_fini(rdev); - return r; - } - r = radeon_bo_kmap(rdev->rlc.clear_state_obj, (void **)&rdev->rlc.cs_ptr); - if (r) { - dev_warn(rdev->dev, "(%d) map RLC c bo failed\n", r); - si_rlc_fini(rdev); - return r; - } - /* set up the cs buffer */ - dst_ptr = rdev->rlc.cs_ptr; - reg_list_hdr_blk_index = 0; - reg_list_mc_addr = rdev->rlc.clear_state_gpu_addr + (reg_list_blk_index * 4); - data = upper_32_bits(reg_list_mc_addr); - dst_ptr[reg_list_hdr_blk_index] = data; - reg_list_hdr_blk_index++; - for (i = 0; cs_data[i].section != NULL; i++) { - for (j = 0; cs_data[i].section[j].extent != NULL; j++) { - reg_num = cs_data[i].section[j].reg_count; - data = reg_list_mc_addr & 0xffffffff; - dst_ptr[reg_list_hdr_blk_index] = data; - reg_list_hdr_blk_index++; - - data = (cs_data[i].section[j].reg_index * 4) & 0xffffffff; - dst_ptr[reg_list_hdr_blk_index] = data; - reg_list_hdr_blk_index++; - - data = 0x08000000 | (reg_num * 4); - dst_ptr[reg_list_hdr_blk_index] = data; - reg_list_hdr_blk_index++; - - for (k = 0; k < reg_num; k++) { - data = cs_data[i].section[j].extent[k]; - dst_ptr[reg_list_blk_index + k] = data; - } - reg_list_mc_addr += reg_num * 4; - reg_list_blk_index += reg_num; - } - } - dst_ptr[reg_list_hdr_blk_index] = RLC_CLEAR_STATE_END_MARKER; - - radeon_bo_kunmap(rdev->rlc.clear_state_obj); - radeon_bo_unreserve(rdev->rlc.clear_state_obj); - - return 0; -} - void si_rlc_reset(struct radeon_device *rdev) { u32 tmp = RREG32(GRBM_SOFT_RESET); @@ -6449,7 +6291,13 @@ static int si_startup(struct radeon_device *rdev) si_gpu_init(rdev); /* allocate rlc buffers */ - r = si_rlc_init(rdev); + if (rdev->family == CHIP_VERDE) { + rdev->rlc.reg_list = verde_rlc_save_restore_register_list; + rdev->rlc.reg_list_size = + (u32)ARRAY_SIZE(verde_rlc_save_restore_register_list); + } + rdev->rlc.cs_data = si_cs_data; + r = sumo_rlc_init(rdev); if (r) { DRM_ERROR("Failed to init rlc BOs!\n"); return r; @@ -6735,7 +6583,7 @@ int si_init(struct radeon_device *rdev) si_cp_fini(rdev); cayman_dma_fini(rdev); si_irq_fini(rdev); - si_rlc_fini(rdev); + sumo_rlc_fini(rdev); radeon_wb_fini(rdev); radeon_ib_pool_fini(rdev); radeon_vm_manager_fini(rdev); @@ -6761,7 +6609,7 @@ void si_fini(struct radeon_device *rdev) si_cp_fini(rdev); cayman_dma_fini(rdev); si_irq_fini(rdev); - si_rlc_fini(rdev); + sumo_rlc_fini(rdev); si_fini_cg(rdev); si_fini_pg(rdev); radeon_wb_fini(rdev); -- cgit v1.2.3-18-g5258 From 22c775ce80ed921fe9490f3cc2ca66dcda44f572 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 23 Jul 2013 09:41:05 -0400 Subject: drm/radeon: implement clock and power gating for CIK (v3) Only the APUs support power gating. v2: disable cgcg for now v3: workaround hw issue in mgcg Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/si.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/radeon/si.c') diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 8b8963d4a73..4f91e1f4d81 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -4901,7 +4901,7 @@ static void si_set_uvd_dcm(struct radeon_device *rdev, WREG32_UVD_CTX(UVD_CGC_CTRL2, tmp2); } -static void si_init_uvd_internal_cg(struct radeon_device *rdev) +void si_init_uvd_internal_cg(struct radeon_device *rdev) { bool hw_mode = true; -- cgit v1.2.3-18-g5258 From 5e884f606cdba9c599c9c9373808f272ae794088 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 6 Aug 2013 11:39:38 -0400 Subject: drm/radeon: restructure UVD code to handle UVD PG (v2) When we PG (powergate) UVD, we need to re-initialize it before we can use it again. v2: rebase on UVD stop fixes Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/si.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/radeon/si.c') diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 4f91e1f4d81..da23ce8f438 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -6421,7 +6421,7 @@ static int si_startup(struct radeon_device *rdev) UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR, 0, 0xfffff, RADEON_CP_PACKET2); if (!r) - r = r600_uvd_init(rdev); + r = r600_uvd_init(rdev, true); if (r) DRM_ERROR("radeon: failed initializing UVD (%d).\n", r); } -- cgit v1.2.3-18-g5258 From 02c9f7fa4e7230fc4ae8bf26f64e45aa76011f9c Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 13 Aug 2013 11:56:51 +0200 Subject: drm/radeon: rework UVD writeback & [rw]ptr handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hardware just doesn't support this correctly. Disable it before we accidentally write anywhere we shouldn't. Signed-off-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/si.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu/drm/radeon/si.c') diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index da23ce8f438..4ff59c8f508 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -6416,8 +6416,7 @@ static int si_startup(struct radeon_device *rdev) if (rdev->has_uvd) { ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; if (ring->ring_size) { - r = radeon_ring_init(rdev, ring, ring->ring_size, - R600_WB_UVD_RPTR_OFFSET, + r = radeon_ring_init(rdev, ring, ring->ring_size, 0, UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR, 0, 0xfffff, RADEON_CP_PACKET2); if (!r) -- cgit v1.2.3-18-g5258 From 2e1e6dad6a6d437e4c40611fdcc4e6cd9e2f969e Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 13 Aug 2013 11:56:52 +0200 Subject: drm/radeon: remove special handling for the DMA ring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we have callbacks for [rw]ptr handling we can remove the special handling for the DMA rings and use the callbacks instead. Signed-off-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/si.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/radeon/si.c') diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 4ff59c8f508..ae232be6292 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -6368,21 +6368,21 @@ static int si_startup(struct radeon_device *rdev) ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, CP_RB0_RPTR, CP_RB0_WPTR, - 0, 0xfffff, RADEON_CP_PACKET2); + RADEON_CP_PACKET2); if (r) return r; ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP1_RPTR_OFFSET, CP_RB1_RPTR, CP_RB1_WPTR, - 0, 0xfffff, RADEON_CP_PACKET2); + RADEON_CP_PACKET2); if (r) return r; ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP2_RPTR_OFFSET, CP_RB2_RPTR, CP_RB2_WPTR, - 0, 0xfffff, RADEON_CP_PACKET2); + RADEON_CP_PACKET2); if (r) return r; @@ -6390,7 +6390,7 @@ static int si_startup(struct radeon_device *rdev) r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET, DMA_RB_RPTR + DMA0_REGISTER_OFFSET, DMA_RB_WPTR + DMA0_REGISTER_OFFSET, - 2, 0x3fffc, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0)); + DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0)); if (r) return r; @@ -6398,7 +6398,7 @@ static int si_startup(struct radeon_device *rdev) r = radeon_ring_init(rdev, ring, ring->ring_size, CAYMAN_WB_DMA1_RPTR_OFFSET, DMA_RB_RPTR + DMA1_REGISTER_OFFSET, DMA_RB_WPTR + DMA1_REGISTER_OFFSET, - 2, 0x3fffc, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0)); + DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0)); if (r) return r; @@ -6418,7 +6418,7 @@ static int si_startup(struct radeon_device *rdev) if (ring->ring_size) { r = radeon_ring_init(rdev, ring, ring->ring_size, 0, UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR, - 0, 0xfffff, RADEON_CP_PACKET2); + RADEON_CP_PACKET2); if (!r) r = r600_uvd_init(rdev, true); if (r) -- cgit v1.2.3-18-g5258 From e409b128625732926c112cc9b709fb7bb1aa387f Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 13 Aug 2013 11:56:53 +0200 Subject: drm/radeon: separate UVD code v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Our different hardware blocks are actually completely separated, so it doesn't make much sense any more to structure the code by pure chipset generations. Start restructuring the code by separating our the UVD block. v2: updated commit message v3: rebased and restructurized start/stop functions for kv dpm. Signed-off-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/si.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/radeon/si.c') diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index ae232be6292..f3f79089405 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -6339,7 +6339,7 @@ static int si_startup(struct radeon_device *rdev) } if (rdev->has_uvd) { - r = rv770_uvd_resume(rdev); + r = uvd_v2_2_resume(rdev); if (!r) { r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX); @@ -6420,7 +6420,7 @@ static int si_startup(struct radeon_device *rdev) UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR, RADEON_CP_PACKET2); if (!r) - r = r600_uvd_init(rdev, true); + r = uvd_v1_0_init(rdev); if (r) DRM_ERROR("radeon: failed initializing UVD (%d).\n", r); } @@ -6473,7 +6473,7 @@ int si_suspend(struct radeon_device *rdev) si_cp_enable(rdev, false); cayman_dma_stop(rdev); if (rdev->has_uvd) { - r600_uvd_stop(rdev); + uvd_v1_0_fini(rdev); radeon_uvd_suspend(rdev); } si_irq_suspend(rdev); @@ -6616,7 +6616,7 @@ void si_fini(struct radeon_device *rdev) radeon_ib_pool_fini(rdev); radeon_irq_kms_fini(rdev); if (rdev->has_uvd) { - r600_uvd_stop(rdev); + uvd_v1_0_fini(rdev); radeon_uvd_fini(rdev); } si_pcie_gart_fini(rdev); -- cgit v1.2.3-18-g5258 From 2483b4ea982efe8a544697d3f9642932e9af4dc1 Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 13 Aug 2013 11:56:54 +0200 Subject: drm/radeon: separate DMA code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Similar to separating the UVD code, just put the DMA functions into separate files. Signed-off-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/si.c | 188 ++------------------------------------------ 1 file changed, 7 insertions(+), 181 deletions(-) (limited to 'drivers/gpu/drm/radeon/si.c') diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index f3f79089405..f5307e6bb92 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -78,6 +78,11 @@ extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_ extern u32 evergreen_get_number_of_dram_channels(struct radeon_device *rdev); extern void evergreen_print_gpu_status_regs(struct radeon_device *rdev); extern bool evergreen_is_display_hung(struct radeon_device *rdev); +extern void si_dma_vm_set_page(struct radeon_device *rdev, + struct radeon_ib *ib, + uint64_t pe, + uint64_t addr, unsigned count, + uint32_t incr, uint32_t flags); static const u32 verde_rlc_save_restore_register_list[] = { @@ -3495,7 +3500,7 @@ static int si_cp_resume(struct radeon_device *rdev) return 0; } -static u32 si_gpu_check_soft_reset(struct radeon_device *rdev) +u32 si_gpu_check_soft_reset(struct radeon_device *rdev) { u32 reset_mask = 0; u32 tmp; @@ -3744,34 +3749,6 @@ bool si_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) return radeon_ring_test_lockup(rdev, ring); } -/** - * si_dma_is_lockup - Check if the DMA engine is locked up - * - * @rdev: radeon_device pointer - * @ring: radeon_ring structure holding ring information - * - * Check if the async DMA engine is locked up. - * Returns true if the engine appears to be locked up, false if not. - */ -bool si_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) -{ - u32 reset_mask = si_gpu_check_soft_reset(rdev); - u32 mask; - - if (ring->idx == R600_RING_TYPE_DMA_INDEX) - mask = RADEON_RESET_DMA; - else - mask = RADEON_RESET_DMA1; - - if (!(reset_mask & mask)) { - radeon_ring_lockup_update(ring); - return false; - } - /* force ring activities */ - radeon_ring_force_activity(rdev, ring); - return radeon_ring_test_lockup(rdev, ring); -} - /* MC */ static void si_mc_program(struct radeon_device *rdev) { @@ -4710,58 +4687,7 @@ void si_vm_set_page(struct radeon_device *rdev, } } else { /* DMA */ - if (flags & RADEON_VM_PAGE_SYSTEM) { - while (count) { - ndw = count * 2; - if (ndw > 0xFFFFE) - ndw = 0xFFFFE; - - /* for non-physically contiguous pages (system) */ - ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_WRITE, 0, 0, 0, ndw); - ib->ptr[ib->length_dw++] = pe; - ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff; - for (; ndw > 0; ndw -= 2, --count, pe += 8) { - if (flags & RADEON_VM_PAGE_SYSTEM) { - value = radeon_vm_map_gart(rdev, addr); - value &= 0xFFFFFFFFFFFFF000ULL; - } else if (flags & RADEON_VM_PAGE_VALID) { - value = addr; - } else { - value = 0; - } - addr += incr; - value |= r600_flags; - ib->ptr[ib->length_dw++] = value; - ib->ptr[ib->length_dw++] = upper_32_bits(value); - } - } - } else { - while (count) { - ndw = count * 2; - if (ndw > 0xFFFFE) - ndw = 0xFFFFE; - - if (flags & RADEON_VM_PAGE_VALID) - value = addr; - else - value = 0; - /* for physically contiguous pages (vram) */ - ib->ptr[ib->length_dw++] = DMA_PTE_PDE_PACKET(ndw); - ib->ptr[ib->length_dw++] = pe; /* dst addr */ - ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff; - ib->ptr[ib->length_dw++] = r600_flags; /* mask */ - ib->ptr[ib->length_dw++] = 0; - ib->ptr[ib->length_dw++] = value; /* value */ - ib->ptr[ib->length_dw++] = upper_32_bits(value); - ib->ptr[ib->length_dw++] = incr; /* increment size */ - ib->ptr[ib->length_dw++] = 0; - pe += ndw * 4; - addr += (ndw / 2) * incr; - count -= ndw / 2; - } - } - while (ib->length_dw & 0x7) - ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0); + si_dma_vm_set_page(rdev, ib, pe, addr, count, incr, flags); } } @@ -4808,32 +4734,6 @@ void si_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm) radeon_ring_write(ring, 0x0); } -void si_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm) -{ - struct radeon_ring *ring = &rdev->ring[ridx]; - - if (vm == NULL) - return; - - radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0, 0)); - if (vm->id < 8) { - radeon_ring_write(ring, (0xf << 16) | ((VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm->id << 2)) >> 2)); - } else { - radeon_ring_write(ring, (0xf << 16) | ((VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((vm->id - 8) << 2)) >> 2)); - } - radeon_ring_write(ring, vm->pd_gpu_addr >> 12); - - /* flush hdp cache */ - radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0, 0)); - radeon_ring_write(ring, (0xf << 16) | (HDP_MEM_COHERENCY_FLUSH_CNTL >> 2)); - radeon_ring_write(ring, 1); - - /* bits 0-7 are the VM contexts0-7 */ - radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0, 0)); - radeon_ring_write(ring, (0xf << 16) | (VM_INVALIDATE_REQUEST >> 2)); - radeon_ring_write(ring, 1 << vm->id); -} - /* * Power and clock gating */ @@ -6177,80 +6077,6 @@ restart_ih: return IRQ_HANDLED; } -/** - * si_copy_dma - copy pages using the DMA engine - * - * @rdev: radeon_device pointer - * @src_offset: src GPU address - * @dst_offset: dst GPU address - * @num_gpu_pages: number of GPU pages to xfer - * @fence: radeon fence object - * - * Copy GPU paging using the DMA engine (SI). - * Used by the radeon ttm implementation to move pages if - * registered as the asic copy callback. - */ -int si_copy_dma(struct radeon_device *rdev, - uint64_t src_offset, uint64_t dst_offset, - unsigned num_gpu_pages, - struct radeon_fence **fence) -{ - struct radeon_semaphore *sem = NULL; - int ring_index = rdev->asic->copy.dma_ring_index; - struct radeon_ring *ring = &rdev->ring[ring_index]; - u32 size_in_bytes, cur_size_in_bytes; - int i, num_loops; - int r = 0; - - r = radeon_semaphore_create(rdev, &sem); - if (r) { - DRM_ERROR("radeon: moving bo (%d).\n", r); - return r; - } - - size_in_bytes = (num_gpu_pages << RADEON_GPU_PAGE_SHIFT); - num_loops = DIV_ROUND_UP(size_in_bytes, 0xfffff); - r = radeon_ring_lock(rdev, ring, num_loops * 5 + 11); - if (r) { - DRM_ERROR("radeon: moving bo (%d).\n", r); - radeon_semaphore_free(rdev, &sem, NULL); - return r; - } - - if (radeon_fence_need_sync(*fence, ring->idx)) { - radeon_semaphore_sync_rings(rdev, sem, (*fence)->ring, - ring->idx); - radeon_fence_note_sync(*fence, ring->idx); - } else { - radeon_semaphore_free(rdev, &sem, NULL); - } - - for (i = 0; i < num_loops; i++) { - cur_size_in_bytes = size_in_bytes; - if (cur_size_in_bytes > 0xFFFFF) - cur_size_in_bytes = 0xFFFFF; - size_in_bytes -= cur_size_in_bytes; - radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_COPY, 1, 0, 0, cur_size_in_bytes)); - radeon_ring_write(ring, dst_offset & 0xffffffff); - radeon_ring_write(ring, src_offset & 0xffffffff); - radeon_ring_write(ring, upper_32_bits(dst_offset) & 0xff); - radeon_ring_write(ring, upper_32_bits(src_offset) & 0xff); - src_offset += cur_size_in_bytes; - dst_offset += cur_size_in_bytes; - } - - r = radeon_fence_emit(rdev, fence, ring->idx); - if (r) { - radeon_ring_unlock_undo(rdev, ring); - return r; - } - - radeon_ring_unlock_commit(rdev, ring); - radeon_semaphore_free(rdev, &sem, *fence); - - return r; -} - /* * startup/shutdown callbacks */ -- cgit v1.2.3-18-g5258 From b530602fd4625f763344e455902981b22f85f609 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 31 Jul 2013 16:51:33 -0400 Subject: drm/radeon: add audio support for DCE6/8 GPUs (v12) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Similar to DCE4/5, but supports multiple audio pins which can be assigned per afmt block. v2: rework the driver to handle more than one audio pin. v3: try different dto reg v4: properly program dto v5 (ck): change dto programming order v6: program speaker allocation block v7: rebase v8: rebase on Rafał's changes v9: integrated Rafał's comments, update to latest drm_edid_to_speaker_allocation API v10: add missing line break in error message v11: add back audio enabled messages v12: fix copy paste typo in r600_audio_enable Signed-off-by: Alex Deucher Signed-off-by: Christian König Acked-by: Rafał Miłecki --- drivers/gpu/drm/radeon/si.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/gpu/drm/radeon/si.c') diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index f5307e6bb92..fb2058c9670 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -6264,6 +6264,10 @@ static int si_startup(struct radeon_device *rdev) return r; } + r = dce6_audio_init(rdev); + if (r) + return r; + return 0; } @@ -6295,6 +6299,7 @@ int si_resume(struct radeon_device *rdev) int si_suspend(struct radeon_device *rdev) { + dce6_audio_fini(rdev); radeon_vm_manager_fini(rdev); si_cp_enable(rdev, false); cayman_dma_stop(rdev); -- cgit v1.2.3-18-g5258 From 0116e1efafe09a2d99042943a850deaa1d9b069c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 8 Aug 2013 18:00:10 -0400 Subject: drm/radeon: use new cg/pg flags for SI Allows us finer grained control over clock and powergating on SI. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/si.c | 59 +++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 29 deletions(-) (limited to 'drivers/gpu/drm/radeon/si.c') diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index fb2058c9670..e116128f3d8 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -5121,39 +5121,44 @@ static void si_enable_mc_ls(struct radeon_device *rdev, static void si_init_cg(struct radeon_device *rdev) { - si_enable_mgcg(rdev, true); - si_enable_cgcg(rdev, false); - /* disable MC LS on Tahiti */ - if (rdev->family == CHIP_TAHITI) + if (rdev->cg_flags & RADEON_CG_SUPPORT_GFX_MGCG) + si_enable_mgcg(rdev, true); + if (rdev->cg_flags & RADEON_CG_SUPPORT_GFX_CGCG) + si_enable_cgcg(rdev, false/*true*/); + /* Disable MC LS on tahiti */ + if (!(rdev->cg_flags & RADEON_CG_SUPPORT_MC_LS)) si_enable_mc_ls(rdev, false); if (rdev->has_uvd) { - si_enable_uvd_mgcg(rdev, true); + if (rdev->cg_flags & RADEON_CG_SUPPORT_UVD_MGCG) + si_enable_uvd_mgcg(rdev, true); si_init_uvd_internal_cg(rdev); } } static void si_fini_cg(struct radeon_device *rdev) { - if (rdev->has_uvd) - si_enable_uvd_mgcg(rdev, false); - si_enable_cgcg(rdev, false); - si_enable_mgcg(rdev, false); + if (rdev->has_uvd) { + if (rdev->cg_flags & RADEON_CG_SUPPORT_UVD_MGCG) + si_enable_uvd_mgcg(rdev, false); + } + if (rdev->cg_flags & RADEON_CG_SUPPORT_GFX_CGCG) + si_enable_cgcg(rdev, false); + if (rdev->cg_flags & RADEON_CG_SUPPORT_GFX_MGCG) + si_enable_mgcg(rdev, false); } static void si_init_pg(struct radeon_device *rdev) { - bool has_pg = false; -#if 0 - /* only cape verde supports PG */ - if (rdev->family == CHIP_VERDE) - has_pg = true; -#endif - if (has_pg) { + if (rdev->pg_flags) { + if (rdev->pg_flags & RADEON_PG_SUPPORT_SDMA) { + si_init_dma_pg(rdev); + si_enable_dma_pg(rdev, true); + } si_init_ao_cu_mask(rdev); - si_init_dma_pg(rdev); - si_enable_dma_pg(rdev, true); - si_init_gfx_cgpg(rdev); - si_enable_gfx_cgpg(rdev, true); + if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_CG) { + si_init_gfx_cgpg(rdev); + si_enable_gfx_cgpg(rdev, true); + } } else { WREG32(RLC_SAVE_AND_RESTORE_BASE, rdev->rlc.save_restore_gpu_addr >> 8); WREG32(RLC_CLEAR_STATE_RESTORE_BASE, rdev->rlc.clear_state_gpu_addr >> 8); @@ -5162,15 +5167,11 @@ static void si_init_pg(struct radeon_device *rdev) static void si_fini_pg(struct radeon_device *rdev) { - bool has_pg = false; - - /* only cape verde supports PG */ - if (rdev->family == CHIP_VERDE) - has_pg = true; - - if (has_pg) { - si_enable_dma_pg(rdev, false); - si_enable_gfx_cgpg(rdev, false); + if (rdev->pg_flags) { + if (rdev->pg_flags & RADEON_PG_SUPPORT_SDMA) + si_enable_dma_pg(rdev, false); + if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_CG) + si_enable_gfx_cgpg(rdev, false); } } -- cgit v1.2.3-18-g5258 From e16866ecfbfabc546fe8f02fdf4359707f81e81e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 8 Aug 2013 19:34:07 -0400 Subject: drm/radeon/si: restructure cg code (v3) Resturcture clockgating code so that it can be enabled/disabled from other components such as dpm. v2: make function static v3: add fine grained cg controls Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/si.c | 207 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 178 insertions(+), 29 deletions(-) (limited to 'drivers/gpu/drm/radeon/si.c') diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index e116128f3d8..b1d22c704c5 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -4844,7 +4844,7 @@ static void si_enable_dma_pg(struct radeon_device *rdev, bool enable) u32 data, orig; orig = data = RREG32(DMA_PG); - if (enable) + if (enable && (rdev->pg_flags & RADEON_PG_SUPPORT_SDMA)) data |= PG_CNTL_ENABLE; else data &= ~PG_CNTL_ENABLE; @@ -4868,7 +4868,7 @@ static void si_enable_gfx_cgpg(struct radeon_device *rdev, { u32 tmp; - if (enable) { + if (enable && (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_CG)) { tmp = RLC_PUD(0x10) | RLC_PDD(0x10) | RLC_TTPD(0x10) | RLC_MSD(0x10); WREG32(RLC_TTOP_D, tmp); @@ -4973,7 +4973,7 @@ static void si_enable_cgcg(struct radeon_device *rdev, si_enable_gui_idle_interrupt(rdev, enable); - if (enable) { + if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_GFX_CGCG)) { WREG32(RLC_GCPM_GENERAL_3, 0x00000080); tmp = si_halt_rlc(rdev); @@ -5007,16 +5007,18 @@ static void si_enable_mgcg(struct radeon_device *rdev, { u32 data, orig, tmp = 0; - if (enable) { + if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_GFX_MGCG)) { orig = data = RREG32(CGTS_SM_CTRL_REG); data = 0x96940200; if (orig != data) WREG32(CGTS_SM_CTRL_REG, data); - orig = data = RREG32(CP_MEM_SLP_CNTL); - data |= CP_MEM_LS_EN; - if (orig != data) - WREG32(CP_MEM_SLP_CNTL, data); + if (rdev->cg_flags & RADEON_CG_SUPPORT_GFX_CP_LS) { + orig = data = RREG32(CP_MEM_SLP_CNTL); + data |= CP_MEM_LS_EN; + if (orig != data) + WREG32(CP_MEM_SLP_CNTL, data); + } orig = data = RREG32(RLC_CGTT_MGCG_OVERRIDE); data &= 0xffffffc0; @@ -5061,7 +5063,7 @@ static void si_enable_uvd_mgcg(struct radeon_device *rdev, { u32 orig, data, tmp; - if (enable) { + if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_UVD_MGCG)) { tmp = RREG32_UVD_CTX(UVD_CGC_MEM_CTRL); tmp |= 0x3fff; WREG32_UVD_CTX(UVD_CGC_MEM_CTRL, tmp); @@ -5109,7 +5111,7 @@ static void si_enable_mc_ls(struct radeon_device *rdev, for (i = 0; i < ARRAY_SIZE(mc_cg_registers); i++) { orig = data = RREG32(mc_cg_registers[i]); - if (enable) + if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_MC_LS)) data |= MC_LS_ENABLE; else data &= ~MC_LS_ENABLE; @@ -5118,19 +5120,158 @@ static void si_enable_mc_ls(struct radeon_device *rdev, } } +static void si_enable_mc_mgcg(struct radeon_device *rdev, + bool enable) +{ + int i; + u32 orig, data; + + for (i = 0; i < ARRAY_SIZE(mc_cg_registers); i++) { + orig = data = RREG32(mc_cg_registers[i]); + if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_MC_MGCG)) + data |= MC_CG_ENABLE; + else + data &= ~MC_CG_ENABLE; + if (data != orig) + WREG32(mc_cg_registers[i], data); + } +} + +static void si_enable_dma_mgcg(struct radeon_device *rdev, + bool enable) +{ + u32 orig, data, offset; + int i; + + if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_SDMA_MGCG)) { + for (i = 0; i < 2; i++) { + if (i == 0) + offset = DMA0_REGISTER_OFFSET; + else + offset = DMA1_REGISTER_OFFSET; + orig = data = RREG32(DMA_POWER_CNTL + offset); + data &= ~MEM_POWER_OVERRIDE; + if (data != orig) + WREG32(DMA_POWER_CNTL + offset, data); + WREG32(DMA_CLK_CTRL + offset, 0x00000100); + } + } else { + for (i = 0; i < 2; i++) { + if (i == 0) + offset = DMA0_REGISTER_OFFSET; + else + offset = DMA1_REGISTER_OFFSET; + orig = data = RREG32(DMA_POWER_CNTL + offset); + data |= MEM_POWER_OVERRIDE; + if (data != orig) + WREG32(DMA_POWER_CNTL + offset, data); + + orig = data = RREG32(DMA_CLK_CTRL + offset); + data = 0xff000000; + if (data != orig) + WREG32(DMA_CLK_CTRL + offset, data); + } + } +} + +static void si_enable_bif_mgls(struct radeon_device *rdev, + bool enable) +{ + u32 orig, data; + + orig = data = RREG32_PCIE(PCIE_CNTL2); + + if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_BIF_LS)) + data |= SLV_MEM_LS_EN | MST_MEM_LS_EN | + REPLAY_MEM_LS_EN | SLV_MEM_AGGRESSIVE_LS_EN; + else + data &= ~(SLV_MEM_LS_EN | MST_MEM_LS_EN | + REPLAY_MEM_LS_EN | SLV_MEM_AGGRESSIVE_LS_EN); + + if (orig != data) + WREG32_PCIE(PCIE_CNTL2, data); +} + +static void si_enable_hdp_mgcg(struct radeon_device *rdev, + bool enable) +{ + u32 orig, data; + + orig = data = RREG32(HDP_HOST_PATH_CNTL); + + if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_HDP_MGCG)) + data &= ~CLOCK_GATING_DIS; + else + data |= CLOCK_GATING_DIS; + + if (orig != data) + WREG32(HDP_HOST_PATH_CNTL, data); +} + +static void si_enable_hdp_ls(struct radeon_device *rdev, + bool enable) +{ + u32 orig, data; + + orig = data = RREG32(HDP_MEM_POWER_LS); + + if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_HDP_LS)) + data |= HDP_LS_ENABLE; + else + data &= ~HDP_LS_ENABLE; + + if (orig != data) + WREG32(HDP_MEM_POWER_LS, data); +} + +void si_update_cg(struct radeon_device *rdev, + u32 block, bool enable) +{ + if (block & RADEON_CG_BLOCK_GFX) { + /* order matters! */ + if (enable) { + si_enable_mgcg(rdev, true); + si_enable_cgcg(rdev, true); + } else { + si_enable_cgcg(rdev, false); + si_enable_mgcg(rdev, false); + } + } + + if (block & RADEON_CG_BLOCK_MC) { + si_enable_mc_mgcg(rdev, enable); + si_enable_mc_ls(rdev, enable); + } + + if (block & RADEON_CG_BLOCK_SDMA) { + si_enable_dma_mgcg(rdev, enable); + } + + if (block & RADEON_CG_BLOCK_BIF) { + si_enable_bif_mgls(rdev, enable); + } + + if (block & RADEON_CG_BLOCK_UVD) { + if (rdev->has_uvd) { + si_enable_uvd_mgcg(rdev, enable); + } + } + + if (block & RADEON_CG_BLOCK_HDP) { + si_enable_hdp_mgcg(rdev, enable); + si_enable_hdp_ls(rdev, enable); + } +} static void si_init_cg(struct radeon_device *rdev) { - if (rdev->cg_flags & RADEON_CG_SUPPORT_GFX_MGCG) - si_enable_mgcg(rdev, true); - if (rdev->cg_flags & RADEON_CG_SUPPORT_GFX_CGCG) - si_enable_cgcg(rdev, false/*true*/); - /* Disable MC LS on tahiti */ - if (!(rdev->cg_flags & RADEON_CG_SUPPORT_MC_LS)) - si_enable_mc_ls(rdev, false); + si_update_cg(rdev, (RADEON_CG_BLOCK_GFX | + RADEON_CG_BLOCK_MC | + RADEON_CG_BLOCK_SDMA | + RADEON_CG_BLOCK_BIF | + RADEON_CG_BLOCK_HDP), true); if (rdev->has_uvd) { - if (rdev->cg_flags & RADEON_CG_SUPPORT_UVD_MGCG) - si_enable_uvd_mgcg(rdev, true); + si_update_cg(rdev, RADEON_CG_BLOCK_UVD, true); si_init_uvd_internal_cg(rdev); } } @@ -5138,13 +5279,20 @@ static void si_init_cg(struct radeon_device *rdev) static void si_fini_cg(struct radeon_device *rdev) { if (rdev->has_uvd) { - if (rdev->cg_flags & RADEON_CG_SUPPORT_UVD_MGCG) - si_enable_uvd_mgcg(rdev, false); + si_update_cg(rdev, RADEON_CG_BLOCK_UVD, false); } - if (rdev->cg_flags & RADEON_CG_SUPPORT_GFX_CGCG) - si_enable_cgcg(rdev, false); - if (rdev->cg_flags & RADEON_CG_SUPPORT_GFX_MGCG) - si_enable_mgcg(rdev, false); + si_update_cg(rdev, (RADEON_CG_BLOCK_GFX | + RADEON_CG_BLOCK_MC | + RADEON_CG_BLOCK_SDMA | + RADEON_CG_BLOCK_BIF | + RADEON_CG_BLOCK_HDP), false); +} + +void si_update_pg(struct radeon_device *rdev, + bool enable) +{ + si_enable_dma_pg(rdev, enable); + si_enable_gfx_cgpg(rdev, enable); } static void si_init_pg(struct radeon_device *rdev) @@ -5152,13 +5300,12 @@ static void si_init_pg(struct radeon_device *rdev) if (rdev->pg_flags) { if (rdev->pg_flags & RADEON_PG_SUPPORT_SDMA) { si_init_dma_pg(rdev); - si_enable_dma_pg(rdev, true); } si_init_ao_cu_mask(rdev); if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_CG) { si_init_gfx_cgpg(rdev); - si_enable_gfx_cgpg(rdev, true); } + si_update_pg(rdev, false); } else { WREG32(RLC_SAVE_AND_RESTORE_BASE, rdev->rlc.save_restore_gpu_addr >> 8); WREG32(RLC_CLEAR_STATE_RESTORE_BASE, rdev->rlc.clear_state_gpu_addr >> 8); @@ -6308,6 +6455,8 @@ int si_suspend(struct radeon_device *rdev) uvd_v1_0_fini(rdev); radeon_uvd_suspend(rdev); } + si_fini_pg(rdev); + si_fini_cg(rdev); si_irq_suspend(rdev); radeon_wb_disable(rdev); si_pcie_gart_disable(rdev); @@ -6439,10 +6588,10 @@ void si_fini(struct radeon_device *rdev) { si_cp_fini(rdev); cayman_dma_fini(rdev); + si_fini_pg(rdev); + si_fini_cg(rdev); si_irq_fini(rdev); sumo_rlc_fini(rdev); - si_fini_cg(rdev); - si_fini_pg(rdev); radeon_wb_fini(rdev); radeon_vm_manager_fini(rdev); radeon_ib_pool_fini(rdev); -- cgit v1.2.3-18-g5258 From 5594a558faca933f64277c2033bd724968cd3d89 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 15 Aug 2013 16:20:26 -0400 Subject: drm/radeon: fixes for gfx clockgating on SI Clockgating requires signalling between the CP and the RLC to work properly. Resetting the CP block in the CP resume code messed up the internal coordination between the blocks. Removing the reset allows gfx clockgating to work properly. However, when gfx clock gating is enabled, there is a strange interaction with dpm which causes the chip to stay in the high performance level all the time, so leave gfx clockgating disabled for now. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/si.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) (limited to 'drivers/gpu/drm/radeon/si.c') diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index b1d22c704c5..ff48c88c913 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -3371,17 +3371,6 @@ static int si_cp_resume(struct radeon_device *rdev) u32 rb_bufsz; int r; - /* Reset cp; if cp is reset, then PA, SH, VGT also need to be reset */ - WREG32(GRBM_SOFT_RESET, (SOFT_RESET_CP | - SOFT_RESET_PA | - SOFT_RESET_VGT | - SOFT_RESET_SPI | - SOFT_RESET_SX)); - RREG32(GRBM_SOFT_RESET); - mdelay(15); - WREG32(GRBM_SOFT_RESET, 0); - RREG32(GRBM_SOFT_RESET); - WREG32(CP_SEM_WAIT_TIMER, 0x0); WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0); @@ -4971,9 +4960,9 @@ static void si_enable_cgcg(struct radeon_device *rdev, orig = data = RREG32(RLC_CGCG_CGLS_CTRL); - si_enable_gui_idle_interrupt(rdev, enable); - if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_GFX_CGCG)) { + si_enable_gui_idle_interrupt(rdev, true); + WREG32(RLC_GCPM_GENERAL_3, 0x00000080); tmp = si_halt_rlc(rdev); @@ -4990,6 +4979,8 @@ static void si_enable_cgcg(struct radeon_device *rdev, data |= CGCG_EN | CGLS_EN; } else { + si_enable_gui_idle_interrupt(rdev, false); + RREG32(CB_CGTT_SCLK_CTRL); RREG32(CB_CGTT_SCLK_CTRL); RREG32(CB_CGTT_SCLK_CTRL); -- cgit v1.2.3-18-g5258 From 59a82d0e65539812652dffea160ef483c1d310f5 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 13 Aug 2013 12:48:06 -0400 Subject: drm/radeon/si: properly set up the clearstate buffer for pg (v2) The format of the clearstate buffer used for pg (powergating) changed between NI and SI. This formats it properly for what the hardware expects on SI. v2: fix addresses Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/si.c | 91 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) (limited to 'drivers/gpu/drm/radeon/si.c') diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index ff48c88c913..ebe04e45e5c 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -5286,6 +5286,97 @@ void si_update_pg(struct radeon_device *rdev, si_enable_gfx_cgpg(rdev, enable); } +u32 si_get_csb_size(struct radeon_device *rdev) +{ + u32 count = 0; + const struct cs_section_def *sect = NULL; + const struct cs_extent_def *ext = NULL; + + if (rdev->rlc.cs_data == NULL) + return 0; + + /* begin clear state */ + count += 2; + /* context control state */ + count += 3; + + for (sect = rdev->rlc.cs_data; sect->section != NULL; ++sect) { + for (ext = sect->section; ext->extent != NULL; ++ext) { + if (sect->id == SECT_CONTEXT) + count += 2 + ext->reg_count; + else + return 0; + } + } + /* pa_sc_raster_config */ + count += 3; + /* end clear state */ + count += 2; + /* clear state */ + count += 2; + + return count; +} + +void si_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer) +{ + u32 count = 0, i; + const struct cs_section_def *sect = NULL; + const struct cs_extent_def *ext = NULL; + + if (rdev->rlc.cs_data == NULL) + return; + if (buffer == NULL) + return; + + buffer[count++] = PACKET3(PACKET3_PREAMBLE_CNTL, 0); + buffer[count++] = PACKET3_PREAMBLE_BEGIN_CLEAR_STATE; + + buffer[count++] = PACKET3(PACKET3_CONTEXT_CONTROL, 1); + buffer[count++] = 0x80000000; + buffer[count++] = 0x80000000; + + for (sect = rdev->rlc.cs_data; sect->section != NULL; ++sect) { + for (ext = sect->section; ext->extent != NULL; ++ext) { + if (sect->id == SECT_CONTEXT) { + buffer[count++] = PACKET3(PACKET3_SET_CONTEXT_REG, ext->reg_count); + buffer[count++] = ext->reg_index - 0xa000; + for (i = 0; i < ext->reg_count; i++) + buffer[count++] = ext->extent[i]; + } else { + return; + } + } + } + + buffer[count++] = PACKET3(PACKET3_SET_CONTEXT_REG, 1); + buffer[count++] = PA_SC_RASTER_CONFIG - PACKET3_SET_CONTEXT_REG_START; + switch (rdev->family) { + case CHIP_TAHITI: + case CHIP_PITCAIRN: + buffer[count++] = 0x2a00126a; + break; + case CHIP_VERDE: + buffer[count++] = 0x0000124a; + break; + case CHIP_OLAND: + buffer[count++] = 0x00000082; + break; + case CHIP_HAINAN: + buffer[count++] = 0x00000000; + break; + default: + buffer[count++] = 0x00000000; + break; + } + + buffer[count++] = PACKET3(PACKET3_PREAMBLE_CNTL, 0); + buffer[count++] = PACKET3_PREAMBLE_END_CLEAR_STATE; + + buffer[count++] = PACKET3(PACKET3_CLEAR_STATE, 0); + buffer[count++] = 0; +} + static void si_init_pg(struct radeon_device *rdev) { if (rdev->pg_flags) { -- cgit v1.2.3-18-g5258 From ca6ebb39df2be99f08fcf30335b4d52319ab9208 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 13 Aug 2013 13:18:37 -0400 Subject: drm/radeon/si: enable DMA pg by default Enable DMA powergating by default. The DMA engines will be powergated when not in use. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/si.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'drivers/gpu/drm/radeon/si.c') diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index ebe04e45e5c..d5f77eb2344 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -5279,13 +5279,6 @@ static void si_fini_cg(struct radeon_device *rdev) RADEON_CG_BLOCK_HDP), false); } -void si_update_pg(struct radeon_device *rdev, - bool enable) -{ - si_enable_dma_pg(rdev, enable); - si_enable_gfx_cgpg(rdev, enable); -} - u32 si_get_csb_size(struct radeon_device *rdev) { u32 count = 0; @@ -5387,7 +5380,8 @@ static void si_init_pg(struct radeon_device *rdev) if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_CG) { si_init_gfx_cgpg(rdev); } - si_update_pg(rdev, false); + si_enable_dma_pg(rdev, true); + si_enable_gfx_cgpg(rdev, true); } else { WREG32(RLC_SAVE_AND_RESTORE_BASE, rdev->rlc.save_restore_gpu_addr >> 8); WREG32(RLC_CLEAR_STATE_RESTORE_BASE, rdev->rlc.clear_state_gpu_addr >> 8); @@ -5397,10 +5391,8 @@ static void si_init_pg(struct radeon_device *rdev) static void si_fini_pg(struct radeon_device *rdev) { if (rdev->pg_flags) { - if (rdev->pg_flags & RADEON_PG_SUPPORT_SDMA) - si_enable_dma_pg(rdev, false); - if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_CG) - si_enable_gfx_cgpg(rdev, false); + si_enable_dma_pg(rdev, false); + si_enable_gfx_cgpg(rdev, false); } } -- cgit v1.2.3-18-g5258 From e5b9e7503eb1f4884efa3b321d3cc47806779202 Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Fri, 16 Aug 2013 17:47:39 -0400 Subject: drm/radeon/si: Add support for CP DMA to CS checker for compute v2 Also add a new RADEON_INFO query to check that CP DMA packets are supported on the compute ring. CP DMA has been supported since the 3.8 kernel, but due to an oversight we forgot to teach the CS checker that the CP DMA packet was legal for the compute ring on Southern Islands GPUs. This patch fixes a bug where the radeon driver will incorrectly reject a legal CP DMA packet from user space. I would like to have the patch backported to stable so that we don't have to require Mesa users to use a bleeding edge kernel in order to take advantage of this feature which is already present in the stable kernels (3.8 and newer). v2: - Don't bump kms version, so this patch can be backported to stable kernels. Cc: stable@vger.kernel.org Signed-off-by: Tom Stellard Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/si.c | 106 +++++++++++++++++++++++++------------------- 1 file changed, 61 insertions(+), 45 deletions(-) (limited to 'drivers/gpu/drm/radeon/si.c') diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index d5f77eb2344..0b4e979b2cb 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -4051,13 +4051,64 @@ static int si_vm_packet3_ce_check(struct radeon_device *rdev, return 0; } +static int si_vm_packet3_cp_dma_check(u32 *ib, u32 idx) +{ + u32 start_reg, reg, i; + u32 command = ib[idx + 4]; + u32 info = ib[idx + 1]; + u32 idx_value = ib[idx]; + if (command & PACKET3_CP_DMA_CMD_SAS) { + /* src address space is register */ + if (((info & 0x60000000) >> 29) == 0) { + start_reg = idx_value << 2; + if (command & PACKET3_CP_DMA_CMD_SAIC) { + reg = start_reg; + if (!si_vm_reg_valid(reg)) { + DRM_ERROR("CP DMA Bad SRC register\n"); + return -EINVAL; + } + } else { + for (i = 0; i < (command & 0x1fffff); i++) { + reg = start_reg + (4 * i); + if (!si_vm_reg_valid(reg)) { + DRM_ERROR("CP DMA Bad SRC register\n"); + return -EINVAL; + } + } + } + } + } + if (command & PACKET3_CP_DMA_CMD_DAS) { + /* dst address space is register */ + if (((info & 0x00300000) >> 20) == 0) { + start_reg = ib[idx + 2]; + if (command & PACKET3_CP_DMA_CMD_DAIC) { + reg = start_reg; + if (!si_vm_reg_valid(reg)) { + DRM_ERROR("CP DMA Bad DST register\n"); + return -EINVAL; + } + } else { + for (i = 0; i < (command & 0x1fffff); i++) { + reg = start_reg + (4 * i); + if (!si_vm_reg_valid(reg)) { + DRM_ERROR("CP DMA Bad DST register\n"); + return -EINVAL; + } + } + } + } + } + return 0; +} + static int si_vm_packet3_gfx_check(struct radeon_device *rdev, u32 *ib, struct radeon_cs_packet *pkt) { + int r; u32 idx = pkt->idx + 1; u32 idx_value = ib[idx]; u32 start_reg, end_reg, reg, i; - u32 command, info; switch (pkt->opcode) { case PACKET3_NOP: @@ -4158,50 +4209,9 @@ static int si_vm_packet3_gfx_check(struct radeon_device *rdev, } break; case PACKET3_CP_DMA: - command = ib[idx + 4]; - info = ib[idx + 1]; - if (command & PACKET3_CP_DMA_CMD_SAS) { - /* src address space is register */ - if (((info & 0x60000000) >> 29) == 0) { - start_reg = idx_value << 2; - if (command & PACKET3_CP_DMA_CMD_SAIC) { - reg = start_reg; - if (!si_vm_reg_valid(reg)) { - DRM_ERROR("CP DMA Bad SRC register\n"); - return -EINVAL; - } - } else { - for (i = 0; i < (command & 0x1fffff); i++) { - reg = start_reg + (4 * i); - if (!si_vm_reg_valid(reg)) { - DRM_ERROR("CP DMA Bad SRC register\n"); - return -EINVAL; - } - } - } - } - } - if (command & PACKET3_CP_DMA_CMD_DAS) { - /* dst address space is register */ - if (((info & 0x00300000) >> 20) == 0) { - start_reg = ib[idx + 2]; - if (command & PACKET3_CP_DMA_CMD_DAIC) { - reg = start_reg; - if (!si_vm_reg_valid(reg)) { - DRM_ERROR("CP DMA Bad DST register\n"); - return -EINVAL; - } - } else { - for (i = 0; i < (command & 0x1fffff); i++) { - reg = start_reg + (4 * i); - if (!si_vm_reg_valid(reg)) { - DRM_ERROR("CP DMA Bad DST register\n"); - return -EINVAL; - } - } - } - } - } + r = si_vm_packet3_cp_dma_check(ib, idx); + if (r) + return r; break; default: DRM_ERROR("Invalid GFX packet3: 0x%x\n", pkt->opcode); @@ -4213,6 +4223,7 @@ static int si_vm_packet3_gfx_check(struct radeon_device *rdev, static int si_vm_packet3_compute_check(struct radeon_device *rdev, u32 *ib, struct radeon_cs_packet *pkt) { + int r; u32 idx = pkt->idx + 1; u32 idx_value = ib[idx]; u32 start_reg, reg, i; @@ -4285,6 +4296,11 @@ static int si_vm_packet3_compute_check(struct radeon_device *rdev, return -EINVAL; } break; + case PACKET3_CP_DMA: + r = si_vm_packet3_cp_dma_check(ib, idx); + if (r) + return r; + break; default: DRM_ERROR("Invalid Compute packet3: 0x%x\n", pkt->opcode); return -EINVAL; -- cgit v1.2.3-18-g5258 From 290d24576ccf1aa0373d2185cedfe262d0d4952a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 19 Aug 2013 11:15:43 -0400 Subject: drm/radeon: update line buffer allocation for dce6 We need to allocate line buffer to each display when setting up the watermarks. Failure to do so can lead to a blank screen. This fixes blank screen problems on dce6 asics. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=64850 Based on an initial fix from: Jay Cornwall Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/si.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/radeon/si.c') diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 0b4e979b2cb..89393ed593f 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -1711,7 +1711,8 @@ static u32 dce6_line_buffer_adjust(struct radeon_device *rdev, struct drm_display_mode *mode, struct drm_display_mode *other_mode) { - u32 tmp; + u32 tmp, buffer_alloc, i; + u32 pipe_offset = radeon_crtc->crtc_id * 0x20; /* * Line Buffer Setup * There are 3 line buffers, each one shared by 2 display controllers. @@ -1726,16 +1727,30 @@ static u32 dce6_line_buffer_adjust(struct radeon_device *rdev, * non-linked crtcs for maximum line buffer allocation. */ if (radeon_crtc->base.enabled && mode) { - if (other_mode) + if (other_mode) { tmp = 0; /* 1/2 */ - else + buffer_alloc = 1; + } else { tmp = 2; /* whole */ - } else + buffer_alloc = 2; + } + } else { tmp = 0; + buffer_alloc = 0; + } WREG32(DC_LB_MEMORY_SPLIT + radeon_crtc->crtc_offset, DC_LB_MEMORY_CONFIG(tmp)); + WREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset, + DMIF_BUFFERS_ALLOCATED(buffer_alloc)); + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset) & + DMIF_BUFFERS_ALLOCATED_COMPLETED) + break; + udelay(1); + } + if (radeon_crtc->base.enabled && mode) { switch (tmp) { case 0: -- cgit v1.2.3-18-g5258 From e5903d399a7b0e5c14673c1206f4aeec2859c730 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 30 Aug 2013 08:58:20 -0400 Subject: drm/radeon: fix init ordering for r600+ The vram scratch buffer needs to be initialized before the mc is programmed otherwise we program 0 as the GPU address of the default GPU fault page. In most cases we put vram at zero anyway and reserve a page for the legacy vga buffer so in practice this shouldn't cause any problems, but better to make it correct. Was changed in: 6fab3febf6d949b0a12b1e4e73db38e4a177a79e Reported-by: FrankR Huang Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/si.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/radeon/si.c') diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 89393ed593f..fe8bca68690 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -6343,6 +6343,11 @@ static int si_startup(struct radeon_device *rdev) /* enable aspm */ si_program_aspm(rdev); + /* scratch needs to be initialized before MC */ + r = r600_vram_scratch_init(rdev); + if (r) + return r; + si_mc_program(rdev); if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw || @@ -6360,10 +6365,6 @@ static int si_startup(struct radeon_device *rdev) return r; } - r = r600_vram_scratch_init(rdev); - if (r) - return r; - r = si_pcie_gart_enable(rdev); if (r) return r; -- cgit v1.2.3-18-g5258