diff options
author | Dave Airlie <airlied@redhat.com> | 2014-02-26 23:39:30 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2014-02-26 23:39:30 -0500 |
commit | 4d538b79197901fecc42e746d515d07fd1089b62 (patch) | |
tree | 0551acabf260fcd7c0189a4e06bb608e31d1206e | |
parent | c48cdd23ea5006c377b670bc3056fa7b63f92574 (diff) | |
parent | 82dc62a31ce3ed7b4eeea9c65a3b69e81e2ea688 (diff) |
Merge branch 'drm-next-3.15' of git://people.freedesktop.org/~deathsimple/linux into drm-next
So this is the initial pull request for radeon drm-next 3.15. Highlights:
- VCE bringup including DPM support
- Few cleanups for the ring handling code
* 'drm-next-3.15' of git://people.freedesktop.org/~deathsimple/linux:
drm/radeon: cleanup false positive lockup handling
drm/radeon: drop radeon_ring_force_activity
drm/radeon: drop drivers copy of the rptr
drm/radeon/cik: enable/disable vce cg when encoding v2
drm/radeon: add support for vce 2.0 clock gating
drm/radeon/dpm: properly enable/disable vce when vce pg is enabled
drm/radeon/dpm: enable dynamic vce state switching v2
drm/radeon: add vce dpm support for KV/KB
drm/radeon: enable vce dpm on CI
drm/radeon: add vce dpm support for CI
drm/radeon: fill in set_vce_clocks for CIK asics
drm/radeon/dpm: fetch vce states from the vbios
drm/radeon/dpm: fill in some initial vce infrastructure
drm/radeon/dpm: move platform caps fetching to a separate function
drm/radeon: add callback for setting vce clocks
drm/radeon: add VCE version parsing and checking
drm/radeon: add VCE ring query
drm/radeon: initial VCE support v4
drm/radeon: fix CP semaphores on CIK
40 files changed, 1691 insertions, 175 deletions
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile index 306364a1ecda..ed60caa32518 100644 --- a/drivers/gpu/drm/radeon/Makefile +++ b/drivers/gpu/drm/radeon/Makefile | |||
@@ -99,6 +99,12 @@ radeon-y += \ | |||
99 | uvd_v3_1.o \ | 99 | uvd_v3_1.o \ |
100 | uvd_v4_2.o | 100 | uvd_v4_2.o |
101 | 101 | ||
102 | # add VCE block | ||
103 | radeon-y += \ | ||
104 | radeon_vce.o \ | ||
105 | vce_v1_0.o \ | ||
106 | vce_v2_0.o \ | ||
107 | |||
102 | radeon-$(CONFIG_COMPAT) += radeon_ioc32.o | 108 | radeon-$(CONFIG_COMPAT) += radeon_ioc32.o |
103 | radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o | 109 | radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o |
104 | radeon-$(CONFIG_ACPI) += radeon_acpi.o | 110 | radeon-$(CONFIG_ACPI) += radeon_acpi.o |
diff --git a/drivers/gpu/drm/radeon/btc_dpm.c b/drivers/gpu/drm/radeon/btc_dpm.c index ea103ccdf4bd..f81d7ca134db 100644 --- a/drivers/gpu/drm/radeon/btc_dpm.c +++ b/drivers/gpu/drm/radeon/btc_dpm.c | |||
@@ -2601,6 +2601,10 @@ int btc_dpm_init(struct radeon_device *rdev) | |||
2601 | pi->min_vddc_in_table = 0; | 2601 | pi->min_vddc_in_table = 0; |
2602 | pi->max_vddc_in_table = 0; | 2602 | pi->max_vddc_in_table = 0; |
2603 | 2603 | ||
2604 | ret = r600_get_platform_caps(rdev); | ||
2605 | if (ret) | ||
2606 | return ret; | ||
2607 | |||
2604 | ret = rv7xx_parse_power_table(rdev); | 2608 | ret = rv7xx_parse_power_table(rdev); |
2605 | if (ret) | 2609 | if (ret) |
2606 | return ret; | 2610 | return ret; |
diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index 8d49104ca6c2..cad89a977527 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c | |||
@@ -172,6 +172,8 @@ extern void si_trim_voltage_table_to_fit_state_table(struct radeon_device *rdev, | |||
172 | extern void cik_enter_rlc_safe_mode(struct radeon_device *rdev); | 172 | extern void cik_enter_rlc_safe_mode(struct radeon_device *rdev); |
173 | extern void cik_exit_rlc_safe_mode(struct radeon_device *rdev); | 173 | extern void cik_exit_rlc_safe_mode(struct radeon_device *rdev); |
174 | extern int ci_mc_load_microcode(struct radeon_device *rdev); | 174 | extern int ci_mc_load_microcode(struct radeon_device *rdev); |
175 | extern void cik_update_cg(struct radeon_device *rdev, | ||
176 | u32 block, bool enable); | ||
175 | 177 | ||
176 | static int ci_get_std_voltage_value_sidd(struct radeon_device *rdev, | 178 | static int ci_get_std_voltage_value_sidd(struct radeon_device *rdev, |
177 | struct atom_voltage_table_entry *voltage_table, | 179 | struct atom_voltage_table_entry *voltage_table, |
@@ -746,6 +748,14 @@ static void ci_apply_state_adjust_rules(struct radeon_device *rdev, | |||
746 | u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc; | 748 | u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc; |
747 | int i; | 749 | int i; |
748 | 750 | ||
751 | if (rps->vce_active) { | ||
752 | rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk; | ||
753 | rps->ecclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].ecclk; | ||
754 | } else { | ||
755 | rps->evclk = 0; | ||
756 | rps->ecclk = 0; | ||
757 | } | ||
758 | |||
749 | if ((rdev->pm.dpm.new_active_crtc_count > 1) || | 759 | if ((rdev->pm.dpm.new_active_crtc_count > 1) || |
750 | ci_dpm_vblank_too_short(rdev)) | 760 | ci_dpm_vblank_too_short(rdev)) |
751 | disable_mclk_switching = true; | 761 | disable_mclk_switching = true; |
@@ -804,6 +814,13 @@ static void ci_apply_state_adjust_rules(struct radeon_device *rdev, | |||
804 | sclk = ps->performance_levels[0].sclk; | 814 | sclk = ps->performance_levels[0].sclk; |
805 | } | 815 | } |
806 | 816 | ||
817 | if (rps->vce_active) { | ||
818 | if (sclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk) | ||
819 | sclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk; | ||
820 | if (mclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].mclk) | ||
821 | mclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].mclk; | ||
822 | } | ||
823 | |||
807 | ps->performance_levels[0].sclk = sclk; | 824 | ps->performance_levels[0].sclk = sclk; |
808 | ps->performance_levels[0].mclk = mclk; | 825 | ps->performance_levels[0].mclk = mclk; |
809 | 826 | ||
@@ -3468,7 +3485,6 @@ static int ci_enable_uvd_dpm(struct radeon_device *rdev, bool enable) | |||
3468 | 0 : -EINVAL; | 3485 | 0 : -EINVAL; |
3469 | } | 3486 | } |
3470 | 3487 | ||
3471 | #if 0 | ||
3472 | static int ci_enable_vce_dpm(struct radeon_device *rdev, bool enable) | 3488 | static int ci_enable_vce_dpm(struct radeon_device *rdev, bool enable) |
3473 | { | 3489 | { |
3474 | struct ci_power_info *pi = ci_get_pi(rdev); | 3490 | struct ci_power_info *pi = ci_get_pi(rdev); |
@@ -3501,6 +3517,7 @@ static int ci_enable_vce_dpm(struct radeon_device *rdev, bool enable) | |||
3501 | 0 : -EINVAL; | 3517 | 0 : -EINVAL; |
3502 | } | 3518 | } |
3503 | 3519 | ||
3520 | #if 0 | ||
3504 | static int ci_enable_samu_dpm(struct radeon_device *rdev, bool enable) | 3521 | static int ci_enable_samu_dpm(struct radeon_device *rdev, bool enable) |
3505 | { | 3522 | { |
3506 | struct ci_power_info *pi = ci_get_pi(rdev); | 3523 | struct ci_power_info *pi = ci_get_pi(rdev); |
@@ -3587,7 +3604,6 @@ static int ci_update_uvd_dpm(struct radeon_device *rdev, bool gate) | |||
3587 | return ci_enable_uvd_dpm(rdev, !gate); | 3604 | return ci_enable_uvd_dpm(rdev, !gate); |
3588 | } | 3605 | } |
3589 | 3606 | ||
3590 | #if 0 | ||
3591 | static u8 ci_get_vce_boot_level(struct radeon_device *rdev) | 3607 | static u8 ci_get_vce_boot_level(struct radeon_device *rdev) |
3592 | { | 3608 | { |
3593 | u8 i; | 3609 | u8 i; |
@@ -3608,15 +3624,15 @@ static int ci_update_vce_dpm(struct radeon_device *rdev, | |||
3608 | struct radeon_ps *radeon_current_state) | 3624 | struct radeon_ps *radeon_current_state) |
3609 | { | 3625 | { |
3610 | struct ci_power_info *pi = ci_get_pi(rdev); | 3626 | struct ci_power_info *pi = ci_get_pi(rdev); |
3611 | bool new_vce_clock_non_zero = (radeon_new_state->evclk != 0); | ||
3612 | bool old_vce_clock_non_zero = (radeon_current_state->evclk != 0); | ||
3613 | int ret = 0; | 3627 | int ret = 0; |
3614 | u32 tmp; | 3628 | u32 tmp; |
3615 | 3629 | ||
3616 | if (new_vce_clock_non_zero != old_vce_clock_non_zero) { | 3630 | if (radeon_current_state->evclk != radeon_new_state->evclk) { |
3617 | if (new_vce_clock_non_zero) { | 3631 | if (radeon_new_state->evclk) { |
3618 | pi->smc_state_table.VceBootLevel = ci_get_vce_boot_level(rdev); | 3632 | /* turn the clocks on when encoding */ |
3633 | cik_update_cg(rdev, RADEON_CG_BLOCK_VCE, false); | ||
3619 | 3634 | ||
3635 | pi->smc_state_table.VceBootLevel = ci_get_vce_boot_level(rdev); | ||
3620 | tmp = RREG32_SMC(DPM_TABLE_475); | 3636 | tmp = RREG32_SMC(DPM_TABLE_475); |
3621 | tmp &= ~VceBootLevel_MASK; | 3637 | tmp &= ~VceBootLevel_MASK; |
3622 | tmp |= VceBootLevel(pi->smc_state_table.VceBootLevel); | 3638 | tmp |= VceBootLevel(pi->smc_state_table.VceBootLevel); |
@@ -3624,12 +3640,16 @@ static int ci_update_vce_dpm(struct radeon_device *rdev, | |||
3624 | 3640 | ||
3625 | ret = ci_enable_vce_dpm(rdev, true); | 3641 | ret = ci_enable_vce_dpm(rdev, true); |
3626 | } else { | 3642 | } else { |
3643 | /* turn the clocks off when not encoding */ | ||
3644 | cik_update_cg(rdev, RADEON_CG_BLOCK_VCE, true); | ||
3645 | |||
3627 | ret = ci_enable_vce_dpm(rdev, false); | 3646 | ret = ci_enable_vce_dpm(rdev, false); |
3628 | } | 3647 | } |
3629 | } | 3648 | } |
3630 | return ret; | 3649 | return ret; |
3631 | } | 3650 | } |
3632 | 3651 | ||
3652 | #if 0 | ||
3633 | static int ci_update_samu_dpm(struct radeon_device *rdev, bool gate) | 3653 | static int ci_update_samu_dpm(struct radeon_device *rdev, bool gate) |
3634 | { | 3654 | { |
3635 | return ci_enable_samu_dpm(rdev, gate); | 3655 | return ci_enable_samu_dpm(rdev, gate); |
@@ -4752,13 +4772,13 @@ int ci_dpm_set_power_state(struct radeon_device *rdev) | |||
4752 | DRM_ERROR("ci_generate_dpm_level_enable_mask failed\n"); | 4772 | DRM_ERROR("ci_generate_dpm_level_enable_mask failed\n"); |
4753 | return ret; | 4773 | return ret; |
4754 | } | 4774 | } |
4755 | #if 0 | 4775 | |
4756 | ret = ci_update_vce_dpm(rdev, new_ps, old_ps); | 4776 | ret = ci_update_vce_dpm(rdev, new_ps, old_ps); |
4757 | if (ret) { | 4777 | if (ret) { |
4758 | DRM_ERROR("ci_update_vce_dpm failed\n"); | 4778 | DRM_ERROR("ci_update_vce_dpm failed\n"); |
4759 | return ret; | 4779 | return ret; |
4760 | } | 4780 | } |
4761 | #endif | 4781 | |
4762 | ret = ci_update_sclk_t(rdev); | 4782 | ret = ci_update_sclk_t(rdev); |
4763 | if (ret) { | 4783 | if (ret) { |
4764 | DRM_ERROR("ci_update_sclk_t failed\n"); | 4784 | DRM_ERROR("ci_update_sclk_t failed\n"); |
@@ -4959,9 +4979,6 @@ static int ci_parse_power_table(struct radeon_device *rdev) | |||
4959 | if (!rdev->pm.dpm.ps) | 4979 | if (!rdev->pm.dpm.ps) |
4960 | return -ENOMEM; | 4980 | return -ENOMEM; |
4961 | power_state_offset = (u8 *)state_array->states; | 4981 | power_state_offset = (u8 *)state_array->states; |
4962 | rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps); | ||
4963 | rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime); | ||
4964 | rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime); | ||
4965 | for (i = 0; i < state_array->ucNumEntries; i++) { | 4982 | for (i = 0; i < state_array->ucNumEntries; i++) { |
4966 | u8 *idx; | 4983 | u8 *idx; |
4967 | power_state = (union pplib_power_state *)power_state_offset; | 4984 | power_state = (union pplib_power_state *)power_state_offset; |
@@ -4998,6 +5015,21 @@ static int ci_parse_power_table(struct radeon_device *rdev) | |||
4998 | power_state_offset += 2 + power_state->v2.ucNumDPMLevels; | 5015 | power_state_offset += 2 + power_state->v2.ucNumDPMLevels; |
4999 | } | 5016 | } |
5000 | rdev->pm.dpm.num_ps = state_array->ucNumEntries; | 5017 | rdev->pm.dpm.num_ps = state_array->ucNumEntries; |
5018 | |||
5019 | /* fill in the vce power states */ | ||
5020 | for (i = 0; i < RADEON_MAX_VCE_LEVELS; i++) { | ||
5021 | u32 sclk, mclk; | ||
5022 | clock_array_index = rdev->pm.dpm.vce_states[i].clk_idx; | ||
5023 | clock_info = (union pplib_clock_info *) | ||
5024 | &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize]; | ||
5025 | sclk = le16_to_cpu(clock_info->ci.usEngineClockLow); | ||
5026 | sclk |= clock_info->ci.ucEngineClockHigh << 16; | ||
5027 | mclk = le16_to_cpu(clock_info->ci.usMemoryClockLow); | ||
5028 | mclk |= clock_info->ci.ucMemoryClockHigh << 16; | ||
5029 | rdev->pm.dpm.vce_states[i].sclk = sclk; | ||
5030 | rdev->pm.dpm.vce_states[i].mclk = mclk; | ||
5031 | } | ||
5032 | |||
5001 | return 0; | 5033 | return 0; |
5002 | } | 5034 | } |
5003 | 5035 | ||
@@ -5077,17 +5109,25 @@ int ci_dpm_init(struct radeon_device *rdev) | |||
5077 | ci_dpm_fini(rdev); | 5109 | ci_dpm_fini(rdev); |
5078 | return ret; | 5110 | return ret; |
5079 | } | 5111 | } |
5080 | ret = ci_parse_power_table(rdev); | 5112 | |
5113 | ret = r600_get_platform_caps(rdev); | ||
5081 | if (ret) { | 5114 | if (ret) { |
5082 | ci_dpm_fini(rdev); | 5115 | ci_dpm_fini(rdev); |
5083 | return ret; | 5116 | return ret; |
5084 | } | 5117 | } |
5118 | |||
5085 | ret = r600_parse_extended_power_table(rdev); | 5119 | ret = r600_parse_extended_power_table(rdev); |
5086 | if (ret) { | 5120 | if (ret) { |
5087 | ci_dpm_fini(rdev); | 5121 | ci_dpm_fini(rdev); |
5088 | return ret; | 5122 | return ret; |
5089 | } | 5123 | } |
5090 | 5124 | ||
5125 | ret = ci_parse_power_table(rdev); | ||
5126 | if (ret) { | ||
5127 | ci_dpm_fini(rdev); | ||
5128 | return ret; | ||
5129 | } | ||
5130 | |||
5091 | pi->dll_default_on = false; | 5131 | pi->dll_default_on = false; |
5092 | pi->sram_end = SMC_RAM_END; | 5132 | pi->sram_end = SMC_RAM_END; |
5093 | 5133 | ||
@@ -5120,6 +5160,7 @@ int ci_dpm_init(struct radeon_device *rdev) | |||
5120 | pi->caps_sclk_throttle_low_notification = false; | 5160 | pi->caps_sclk_throttle_low_notification = false; |
5121 | 5161 | ||
5122 | pi->caps_uvd_dpm = true; | 5162 | pi->caps_uvd_dpm = true; |
5163 | pi->caps_vce_dpm = true; | ||
5123 | 5164 | ||
5124 | ci_get_leakage_voltages(rdev); | 5165 | ci_get_leakage_voltages(rdev); |
5125 | ci_patch_dependency_tables_with_leakage(rdev); | 5166 | ci_patch_dependency_tables_with_leakage(rdev); |
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index e6419ca7cd37..92e38b54efb9 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c | |||
@@ -75,6 +75,7 @@ extern void si_init_uvd_internal_cg(struct radeon_device *rdev); | |||
75 | extern int cik_sdma_resume(struct radeon_device *rdev); | 75 | extern int cik_sdma_resume(struct radeon_device *rdev); |
76 | extern void cik_sdma_enable(struct radeon_device *rdev, bool enable); | 76 | extern void cik_sdma_enable(struct radeon_device *rdev, bool enable); |
77 | extern void cik_sdma_fini(struct radeon_device *rdev); | 77 | extern void cik_sdma_fini(struct radeon_device *rdev); |
78 | extern void vce_v2_0_enable_mgcg(struct radeon_device *rdev, bool enable); | ||
78 | static void cik_rlc_stop(struct radeon_device *rdev); | 79 | static void cik_rlc_stop(struct radeon_device *rdev); |
79 | static void cik_pcie_gen3_enable(struct radeon_device *rdev); | 80 | static void cik_pcie_gen3_enable(struct radeon_device *rdev); |
80 | static void cik_program_aspm(struct radeon_device *rdev); | 81 | static void cik_program_aspm(struct radeon_device *rdev); |
@@ -4030,8 +4031,6 @@ static int cik_cp_gfx_resume(struct radeon_device *rdev) | |||
4030 | WREG32(CP_RB0_BASE, rb_addr); | 4031 | WREG32(CP_RB0_BASE, rb_addr); |
4031 | WREG32(CP_RB0_BASE_HI, upper_32_bits(rb_addr)); | 4032 | WREG32(CP_RB0_BASE_HI, upper_32_bits(rb_addr)); |
4032 | 4033 | ||
4033 | ring->rptr = RREG32(CP_RB0_RPTR); | ||
4034 | |||
4035 | /* start the ring */ | 4034 | /* start the ring */ |
4036 | cik_cp_gfx_start(rdev); | 4035 | cik_cp_gfx_start(rdev); |
4037 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = true; | 4036 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = true; |
@@ -4586,8 +4585,7 @@ static int cik_cp_compute_resume(struct radeon_device *rdev) | |||
4586 | rdev->ring[idx].wptr = 0; | 4585 | rdev->ring[idx].wptr = 0; |
4587 | mqd->queue_state.cp_hqd_pq_wptr = rdev->ring[idx].wptr; | 4586 | mqd->queue_state.cp_hqd_pq_wptr = rdev->ring[idx].wptr; |
4588 | WREG32(CP_HQD_PQ_WPTR, mqd->queue_state.cp_hqd_pq_wptr); | 4587 | WREG32(CP_HQD_PQ_WPTR, mqd->queue_state.cp_hqd_pq_wptr); |
4589 | rdev->ring[idx].rptr = RREG32(CP_HQD_PQ_RPTR); | 4588 | mqd->queue_state.cp_hqd_pq_rptr = RREG32(CP_HQD_PQ_RPTR); |
4590 | mqd->queue_state.cp_hqd_pq_rptr = rdev->ring[idx].rptr; | ||
4591 | 4589 | ||
4592 | /* set the vmid for the queue */ | 4590 | /* set the vmid for the queue */ |
4593 | mqd->queue_state.cp_hqd_vmid = 0; | 4591 | mqd->queue_state.cp_hqd_vmid = 0; |
@@ -5117,11 +5115,9 @@ bool cik_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) | |||
5117 | if (!(reset_mask & (RADEON_RESET_GFX | | 5115 | if (!(reset_mask & (RADEON_RESET_GFX | |
5118 | RADEON_RESET_COMPUTE | | 5116 | RADEON_RESET_COMPUTE | |
5119 | RADEON_RESET_CP))) { | 5117 | RADEON_RESET_CP))) { |
5120 | radeon_ring_lockup_update(ring); | 5118 | radeon_ring_lockup_update(rdev, ring); |
5121 | return false; | 5119 | return false; |
5122 | } | 5120 | } |
5123 | /* force CP activities */ | ||
5124 | radeon_ring_force_activity(rdev, ring); | ||
5125 | return radeon_ring_test_lockup(rdev, ring); | 5121 | return radeon_ring_test_lockup(rdev, ring); |
5126 | } | 5122 | } |
5127 | 5123 | ||
@@ -6141,6 +6137,10 @@ void cik_update_cg(struct radeon_device *rdev, | |||
6141 | cik_enable_hdp_mgcg(rdev, enable); | 6137 | cik_enable_hdp_mgcg(rdev, enable); |
6142 | cik_enable_hdp_ls(rdev, enable); | 6138 | cik_enable_hdp_ls(rdev, enable); |
6143 | } | 6139 | } |
6140 | |||
6141 | if (block & RADEON_CG_BLOCK_VCE) { | ||
6142 | vce_v2_0_enable_mgcg(rdev, enable); | ||
6143 | } | ||
6144 | } | 6144 | } |
6145 | 6145 | ||
6146 | static void cik_init_cg(struct radeon_device *rdev) | 6146 | static void cik_init_cg(struct radeon_device *rdev) |
@@ -7490,6 +7490,20 @@ restart_ih: | |||
7490 | /* reset addr and status */ | 7490 | /* reset addr and status */ |
7491 | WREG32_P(VM_CONTEXT1_CNTL2, 1, ~1); | 7491 | WREG32_P(VM_CONTEXT1_CNTL2, 1, ~1); |
7492 | break; | 7492 | break; |
7493 | case 167: /* VCE */ | ||
7494 | DRM_DEBUG("IH: VCE int: 0x%08x\n", src_data); | ||
7495 | switch (src_data) { | ||
7496 | case 0: | ||
7497 | radeon_fence_process(rdev, TN_RING_TYPE_VCE1_INDEX); | ||
7498 | break; | ||
7499 | case 1: | ||
7500 | radeon_fence_process(rdev, TN_RING_TYPE_VCE2_INDEX); | ||
7501 | break; | ||
7502 | default: | ||
7503 | DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); | ||
7504 | break; | ||
7505 | } | ||
7506 | break; | ||
7493 | case 176: /* GFX RB CP_INT */ | 7507 | case 176: /* GFX RB CP_INT */ |
7494 | case 177: /* GFX IB CP_INT */ | 7508 | case 177: /* GFX IB CP_INT */ |
7495 | radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); | 7509 | radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); |
@@ -7789,6 +7803,22 @@ static int cik_startup(struct radeon_device *rdev) | |||
7789 | if (r) | 7803 | if (r) |
7790 | rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0; | 7804 | rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0; |
7791 | 7805 | ||
7806 | r = radeon_vce_resume(rdev); | ||
7807 | if (!r) { | ||
7808 | r = vce_v2_0_resume(rdev); | ||
7809 | if (!r) | ||
7810 | r = radeon_fence_driver_start_ring(rdev, | ||
7811 | TN_RING_TYPE_VCE1_INDEX); | ||
7812 | if (!r) | ||
7813 | r = radeon_fence_driver_start_ring(rdev, | ||
7814 | TN_RING_TYPE_VCE2_INDEX); | ||
7815 | } | ||
7816 | if (r) { | ||
7817 | dev_err(rdev->dev, "VCE init error (%d).\n", r); | ||
7818 | rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0; | ||
7819 | rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0; | ||
7820 | } | ||
7821 | |||
7792 | /* Enable IRQ */ | 7822 | /* Enable IRQ */ |
7793 | if (!rdev->irq.installed) { | 7823 | if (!rdev->irq.installed) { |
7794 | r = radeon_irq_kms_init(rdev); | 7824 | r = radeon_irq_kms_init(rdev); |
@@ -7864,6 +7894,23 @@ static int cik_startup(struct radeon_device *rdev) | |||
7864 | DRM_ERROR("radeon: failed initializing UVD (%d).\n", r); | 7894 | DRM_ERROR("radeon: failed initializing UVD (%d).\n", r); |
7865 | } | 7895 | } |
7866 | 7896 | ||
7897 | r = -ENOENT; | ||
7898 | |||
7899 | ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX]; | ||
7900 | if (ring->ring_size) | ||
7901 | r = radeon_ring_init(rdev, ring, ring->ring_size, 0, | ||
7902 | VCE_CMD_NO_OP); | ||
7903 | |||
7904 | ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX]; | ||
7905 | if (ring->ring_size) | ||
7906 | r = radeon_ring_init(rdev, ring, ring->ring_size, 0, | ||
7907 | VCE_CMD_NO_OP); | ||
7908 | |||
7909 | if (!r) | ||
7910 | r = vce_v1_0_init(rdev); | ||
7911 | else if (r != -ENOENT) | ||
7912 | DRM_ERROR("radeon: failed initializing VCE (%d).\n", r); | ||
7913 | |||
7867 | r = radeon_ib_pool_init(rdev); | 7914 | r = radeon_ib_pool_init(rdev); |
7868 | if (r) { | 7915 | if (r) { |
7869 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | 7916 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
@@ -7934,6 +7981,7 @@ int cik_suspend(struct radeon_device *rdev) | |||
7934 | cik_sdma_enable(rdev, false); | 7981 | cik_sdma_enable(rdev, false); |
7935 | uvd_v1_0_fini(rdev); | 7982 | uvd_v1_0_fini(rdev); |
7936 | radeon_uvd_suspend(rdev); | 7983 | radeon_uvd_suspend(rdev); |
7984 | radeon_vce_suspend(rdev); | ||
7937 | cik_fini_pg(rdev); | 7985 | cik_fini_pg(rdev); |
7938 | cik_fini_cg(rdev); | 7986 | cik_fini_cg(rdev); |
7939 | cik_irq_suspend(rdev); | 7987 | cik_irq_suspend(rdev); |
@@ -8066,6 +8114,17 @@ int cik_init(struct radeon_device *rdev) | |||
8066 | r600_ring_init(rdev, ring, 4096); | 8114 | r600_ring_init(rdev, ring, 4096); |
8067 | } | 8115 | } |
8068 | 8116 | ||
8117 | r = radeon_vce_init(rdev); | ||
8118 | if (!r) { | ||
8119 | ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX]; | ||
8120 | ring->ring_obj = NULL; | ||
8121 | r600_ring_init(rdev, ring, 4096); | ||
8122 | |||
8123 | ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX]; | ||
8124 | ring->ring_obj = NULL; | ||
8125 | r600_ring_init(rdev, ring, 4096); | ||
8126 | } | ||
8127 | |||
8069 | rdev->ih.ring_obj = NULL; | 8128 | rdev->ih.ring_obj = NULL; |
8070 | r600_ih_ring_init(rdev, 64 * 1024); | 8129 | r600_ih_ring_init(rdev, 64 * 1024); |
8071 | 8130 | ||
@@ -8127,6 +8186,7 @@ void cik_fini(struct radeon_device *rdev) | |||
8127 | radeon_irq_kms_fini(rdev); | 8186 | radeon_irq_kms_fini(rdev); |
8128 | uvd_v1_0_fini(rdev); | 8187 | uvd_v1_0_fini(rdev); |
8129 | radeon_uvd_fini(rdev); | 8188 | radeon_uvd_fini(rdev); |
8189 | radeon_vce_fini(rdev); | ||
8130 | cik_pcie_gart_fini(rdev); | 8190 | cik_pcie_gart_fini(rdev); |
8131 | r600_vram_scratch_fini(rdev); | 8191 | r600_vram_scratch_fini(rdev); |
8132 | radeon_gem_fini(rdev); | 8192 | radeon_gem_fini(rdev); |
@@ -8865,6 +8925,41 @@ int cik_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) | |||
8865 | return r; | 8925 | return r; |
8866 | } | 8926 | } |
8867 | 8927 | ||
8928 | int cik_set_vce_clocks(struct radeon_device *rdev, u32 evclk, u32 ecclk) | ||
8929 | { | ||
8930 | int r, i; | ||
8931 | struct atom_clock_dividers dividers; | ||
8932 | u32 tmp; | ||
8933 | |||
8934 | r = radeon_atom_get_clock_dividers(rdev, COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK, | ||
8935 | ecclk, false, ÷rs); | ||
8936 | if (r) | ||
8937 | return r; | ||
8938 | |||
8939 | for (i = 0; i < 100; i++) { | ||
8940 | if (RREG32_SMC(CG_ECLK_STATUS) & ECLK_STATUS) | ||
8941 | break; | ||
8942 | mdelay(10); | ||
8943 | } | ||
8944 | if (i == 100) | ||
8945 | return -ETIMEDOUT; | ||
8946 | |||
8947 | tmp = RREG32_SMC(CG_ECLK_CNTL); | ||
8948 | tmp &= ~(ECLK_DIR_CNTL_EN|ECLK_DIVIDER_MASK); | ||
8949 | tmp |= dividers.post_divider; | ||
8950 | WREG32_SMC(CG_ECLK_CNTL, tmp); | ||
8951 | |||
8952 | for (i = 0; i < 100; i++) { | ||
8953 | if (RREG32_SMC(CG_ECLK_STATUS) & ECLK_STATUS) | ||
8954 | break; | ||
8955 | mdelay(10); | ||
8956 | } | ||
8957 | if (i == 100) | ||
8958 | return -ETIMEDOUT; | ||
8959 | |||
8960 | return 0; | ||
8961 | } | ||
8962 | |||
8868 | static void cik_pcie_gen3_enable(struct radeon_device *rdev) | 8963 | static void cik_pcie_gen3_enable(struct radeon_device *rdev) |
8869 | { | 8964 | { |
8870 | struct pci_dev *root = rdev->pdev->bus->self; | 8965 | struct pci_dev *root = rdev->pdev->bus->self; |
diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c index 1ecb3f1070e3..00150ac49cd2 100644 --- a/drivers/gpu/drm/radeon/cik_sdma.c +++ b/drivers/gpu/drm/radeon/cik_sdma.c | |||
@@ -362,8 +362,6 @@ static int cik_sdma_gfx_resume(struct radeon_device *rdev) | |||
362 | ring->wptr = 0; | 362 | ring->wptr = 0; |
363 | WREG32(SDMA0_GFX_RB_WPTR + reg_offset, ring->wptr << 2); | 363 | WREG32(SDMA0_GFX_RB_WPTR + reg_offset, ring->wptr << 2); |
364 | 364 | ||
365 | ring->rptr = RREG32(SDMA0_GFX_RB_RPTR + reg_offset) >> 2; | ||
366 | |||
367 | /* enable DMA RB */ | 365 | /* enable DMA RB */ |
368 | WREG32(SDMA0_GFX_RB_CNTL + reg_offset, rb_cntl | SDMA_RB_ENABLE); | 366 | WREG32(SDMA0_GFX_RB_CNTL + reg_offset, rb_cntl | SDMA_RB_ENABLE); |
369 | 367 | ||
@@ -713,11 +711,9 @@ bool cik_sdma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) | |||
713 | mask = RADEON_RESET_DMA1; | 711 | mask = RADEON_RESET_DMA1; |
714 | 712 | ||
715 | if (!(reset_mask & mask)) { | 713 | if (!(reset_mask & mask)) { |
716 | radeon_ring_lockup_update(ring); | 714 | radeon_ring_lockup_update(rdev, ring); |
717 | return false; | 715 | return false; |
718 | } | 716 | } |
719 | /* force ring activities */ | ||
720 | radeon_ring_force_activity(rdev, ring); | ||
721 | return radeon_ring_test_lockup(rdev, ring); | 717 | return radeon_ring_test_lockup(rdev, ring); |
722 | } | 718 | } |
723 | 719 | ||
diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h index 98bae9d7b74d..213873270d5f 100644 --- a/drivers/gpu/drm/radeon/cikd.h +++ b/drivers/gpu/drm/radeon/cikd.h | |||
@@ -203,6 +203,12 @@ | |||
203 | #define CTF_TEMP_MASK 0x0003fe00 | 203 | #define CTF_TEMP_MASK 0x0003fe00 |
204 | #define CTF_TEMP_SHIFT 9 | 204 | #define CTF_TEMP_SHIFT 9 |
205 | 205 | ||
206 | #define CG_ECLK_CNTL 0xC05000AC | ||
207 | # define ECLK_DIVIDER_MASK 0x7f | ||
208 | # define ECLK_DIR_CNTL_EN (1 << 8) | ||
209 | #define CG_ECLK_STATUS 0xC05000B0 | ||
210 | # define ECLK_STATUS (1 << 0) | ||
211 | |||
206 | #define CG_SPLL_FUNC_CNTL 0xC0500140 | 212 | #define CG_SPLL_FUNC_CNTL 0xC0500140 |
207 | #define SPLL_RESET (1 << 0) | 213 | #define SPLL_RESET (1 << 0) |
208 | #define SPLL_PWRON (1 << 1) | 214 | #define SPLL_PWRON (1 << 1) |
@@ -2010,4 +2016,47 @@ | |||
2010 | /* UVD CTX indirect */ | 2016 | /* UVD CTX indirect */ |
2011 | #define UVD_CGC_MEM_CTRL 0xC0 | 2017 | #define UVD_CGC_MEM_CTRL 0xC0 |
2012 | 2018 | ||
2019 | /* VCE */ | ||
2020 | |||
2021 | #define VCE_VCPU_CACHE_OFFSET0 0x20024 | ||
2022 | #define VCE_VCPU_CACHE_SIZE0 0x20028 | ||
2023 | #define VCE_VCPU_CACHE_OFFSET1 0x2002c | ||
2024 | #define VCE_VCPU_CACHE_SIZE1 0x20030 | ||
2025 | #define VCE_VCPU_CACHE_OFFSET2 0x20034 | ||
2026 | #define VCE_VCPU_CACHE_SIZE2 0x20038 | ||
2027 | #define VCE_RB_RPTR2 0x20178 | ||
2028 | #define VCE_RB_WPTR2 0x2017c | ||
2029 | #define VCE_RB_RPTR 0x2018c | ||
2030 | #define VCE_RB_WPTR 0x20190 | ||
2031 | #define VCE_CLOCK_GATING_A 0x202f8 | ||
2032 | # define CGC_CLK_GATE_DLY_TIMER_MASK (0xf << 0) | ||
2033 | # define CGC_CLK_GATE_DLY_TIMER(x) ((x) << 0) | ||
2034 | # define CGC_CLK_GATER_OFF_DLY_TIMER_MASK (0xff << 4) | ||
2035 | # define CGC_CLK_GATER_OFF_DLY_TIMER(x) ((x) << 4) | ||
2036 | # define CGC_UENC_WAIT_AWAKE (1 << 18) | ||
2037 | #define VCE_CLOCK_GATING_B 0x202fc | ||
2038 | #define VCE_CGTT_CLK_OVERRIDE 0x207a0 | ||
2039 | #define VCE_UENC_CLOCK_GATING 0x207bc | ||
2040 | # define CLOCK_ON_DELAY_MASK (0xf << 0) | ||
2041 | # define CLOCK_ON_DELAY(x) ((x) << 0) | ||
2042 | # define CLOCK_OFF_DELAY_MASK (0xff << 4) | ||
2043 | # define CLOCK_OFF_DELAY(x) ((x) << 4) | ||
2044 | #define VCE_UENC_REG_CLOCK_GATING 0x207c0 | ||
2045 | #define VCE_SYS_INT_EN 0x21300 | ||
2046 | # define VCE_SYS_INT_TRAP_INTERRUPT_EN (1 << 3) | ||
2047 | #define VCE_LMI_CTRL2 0x21474 | ||
2048 | #define VCE_LMI_CTRL 0x21498 | ||
2049 | #define VCE_LMI_VM_CTRL 0x214a0 | ||
2050 | #define VCE_LMI_SWAP_CNTL 0x214b4 | ||
2051 | #define VCE_LMI_SWAP_CNTL1 0x214b8 | ||
2052 | #define VCE_LMI_CACHE_CTRL 0x214f4 | ||
2053 | |||
2054 | #define VCE_CMD_NO_OP 0x00000000 | ||
2055 | #define VCE_CMD_END 0x00000001 | ||
2056 | #define VCE_CMD_IB 0x00000002 | ||
2057 | #define VCE_CMD_FENCE 0x00000003 | ||
2058 | #define VCE_CMD_TRAP 0x00000004 | ||
2059 | #define VCE_CMD_IB_AUTO 0x00000005 | ||
2060 | #define VCE_CMD_SEMAPHORE 0x00000006 | ||
2061 | |||
2013 | #endif | 2062 | #endif |
diff --git a/drivers/gpu/drm/radeon/cypress_dpm.c b/drivers/gpu/drm/radeon/cypress_dpm.c index cf783fc0ef21..5a9a5f4d7888 100644 --- a/drivers/gpu/drm/radeon/cypress_dpm.c +++ b/drivers/gpu/drm/radeon/cypress_dpm.c | |||
@@ -2036,6 +2036,10 @@ int cypress_dpm_init(struct radeon_device *rdev) | |||
2036 | pi->min_vddc_in_table = 0; | 2036 | pi->min_vddc_in_table = 0; |
2037 | pi->max_vddc_in_table = 0; | 2037 | pi->max_vddc_in_table = 0; |
2038 | 2038 | ||
2039 | ret = r600_get_platform_caps(rdev); | ||
2040 | if (ret) | ||
2041 | return ret; | ||
2042 | |||
2039 | ret = rv7xx_parse_power_table(rdev); | 2043 | ret = rv7xx_parse_power_table(rdev); |
2040 | if (ret) | 2044 | if (ret) |
2041 | return ret; | 2045 | return ret; |
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 5623e7542d99..b1f1253e2ced 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
@@ -2990,8 +2990,6 @@ static int evergreen_cp_resume(struct radeon_device *rdev) | |||
2990 | WREG32(CP_RB_BASE, ring->gpu_addr >> 8); | 2990 | WREG32(CP_RB_BASE, ring->gpu_addr >> 8); |
2991 | WREG32(CP_DEBUG, (1 << 27) | (1 << 28)); | 2991 | WREG32(CP_DEBUG, (1 << 27) | (1 << 28)); |
2992 | 2992 | ||
2993 | ring->rptr = RREG32(CP_RB_RPTR); | ||
2994 | |||
2995 | evergreen_cp_start(rdev); | 2993 | evergreen_cp_start(rdev); |
2996 | ring->ready = true; | 2994 | ring->ready = true; |
2997 | r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, ring); | 2995 | r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, ring); |
@@ -3952,11 +3950,9 @@ bool evergreen_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *rin | |||
3952 | if (!(reset_mask & (RADEON_RESET_GFX | | 3950 | if (!(reset_mask & (RADEON_RESET_GFX | |
3953 | RADEON_RESET_COMPUTE | | 3951 | RADEON_RESET_COMPUTE | |
3954 | RADEON_RESET_CP))) { | 3952 | RADEON_RESET_CP))) { |
3955 | radeon_ring_lockup_update(ring); | 3953 | radeon_ring_lockup_update(rdev, ring); |
3956 | return false; | 3954 | return false; |
3957 | } | 3955 | } |
3958 | /* force CP activities */ | ||
3959 | radeon_ring_force_activity(rdev, ring); | ||
3960 | return radeon_ring_test_lockup(rdev, ring); | 3956 | return radeon_ring_test_lockup(rdev, ring); |
3961 | } | 3957 | } |
3962 | 3958 | ||
diff --git a/drivers/gpu/drm/radeon/evergreen_dma.c b/drivers/gpu/drm/radeon/evergreen_dma.c index a37b54436382..287fe966d7de 100644 --- a/drivers/gpu/drm/radeon/evergreen_dma.c +++ b/drivers/gpu/drm/radeon/evergreen_dma.c | |||
@@ -174,11 +174,9 @@ bool evergreen_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *rin | |||
174 | u32 reset_mask = evergreen_gpu_check_soft_reset(rdev); | 174 | u32 reset_mask = evergreen_gpu_check_soft_reset(rdev); |
175 | 175 | ||
176 | if (!(reset_mask & RADEON_RESET_DMA)) { | 176 | if (!(reset_mask & RADEON_RESET_DMA)) { |
177 | radeon_ring_lockup_update(ring); | 177 | radeon_ring_lockup_update(rdev, ring); |
178 | return false; | 178 | return false; |
179 | } | 179 | } |
180 | /* force ring activities */ | ||
181 | radeon_ring_force_activity(rdev, ring); | ||
182 | return radeon_ring_test_lockup(rdev, ring); | 180 | return radeon_ring_test_lockup(rdev, ring); |
183 | } | 181 | } |
184 | 182 | ||
diff --git a/drivers/gpu/drm/radeon/kv_dpm.c b/drivers/gpu/drm/radeon/kv_dpm.c index 351db361239d..16ec9d56a234 100644 --- a/drivers/gpu/drm/radeon/kv_dpm.c +++ b/drivers/gpu/drm/radeon/kv_dpm.c | |||
@@ -1338,13 +1338,11 @@ static int kv_enable_uvd_dpm(struct radeon_device *rdev, bool enable) | |||
1338 | PPSMC_MSG_UVDDPM_Enable : PPSMC_MSG_UVDDPM_Disable); | 1338 | PPSMC_MSG_UVDDPM_Enable : PPSMC_MSG_UVDDPM_Disable); |
1339 | } | 1339 | } |
1340 | 1340 | ||
1341 | #if 0 | ||
1342 | static int kv_enable_vce_dpm(struct radeon_device *rdev, bool enable) | 1341 | static int kv_enable_vce_dpm(struct radeon_device *rdev, bool enable) |
1343 | { | 1342 | { |
1344 | return kv_notify_message_to_smu(rdev, enable ? | 1343 | return kv_notify_message_to_smu(rdev, enable ? |
1345 | PPSMC_MSG_VCEDPM_Enable : PPSMC_MSG_VCEDPM_Disable); | 1344 | PPSMC_MSG_VCEDPM_Enable : PPSMC_MSG_VCEDPM_Disable); |
1346 | } | 1345 | } |
1347 | #endif | ||
1348 | 1346 | ||
1349 | static int kv_enable_samu_dpm(struct radeon_device *rdev, bool enable) | 1347 | static int kv_enable_samu_dpm(struct radeon_device *rdev, bool enable) |
1350 | { | 1348 | { |
@@ -1389,7 +1387,6 @@ static int kv_update_uvd_dpm(struct radeon_device *rdev, bool gate) | |||
1389 | return kv_enable_uvd_dpm(rdev, !gate); | 1387 | return kv_enable_uvd_dpm(rdev, !gate); |
1390 | } | 1388 | } |
1391 | 1389 | ||
1392 | #if 0 | ||
1393 | static u8 kv_get_vce_boot_level(struct radeon_device *rdev) | 1390 | static u8 kv_get_vce_boot_level(struct radeon_device *rdev) |
1394 | { | 1391 | { |
1395 | u8 i; | 1392 | u8 i; |
@@ -1414,6 +1411,9 @@ static int kv_update_vce_dpm(struct radeon_device *rdev, | |||
1414 | int ret; | 1411 | int ret; |
1415 | 1412 | ||
1416 | if (radeon_new_state->evclk > 0 && radeon_current_state->evclk == 0) { | 1413 | if (radeon_new_state->evclk > 0 && radeon_current_state->evclk == 0) { |
1414 | kv_dpm_powergate_vce(rdev, false); | ||
1415 | /* turn the clocks on when encoding */ | ||
1416 | cik_update_cg(rdev, RADEON_CG_BLOCK_VCE, false); | ||
1417 | if (pi->caps_stable_p_state) | 1417 | if (pi->caps_stable_p_state) |
1418 | pi->vce_boot_level = table->count - 1; | 1418 | pi->vce_boot_level = table->count - 1; |
1419 | else | 1419 | else |
@@ -1436,11 +1436,13 @@ static int kv_update_vce_dpm(struct radeon_device *rdev, | |||
1436 | kv_enable_vce_dpm(rdev, true); | 1436 | kv_enable_vce_dpm(rdev, true); |
1437 | } else if (radeon_new_state->evclk == 0 && radeon_current_state->evclk > 0) { | 1437 | } else if (radeon_new_state->evclk == 0 && radeon_current_state->evclk > 0) { |
1438 | kv_enable_vce_dpm(rdev, false); | 1438 | kv_enable_vce_dpm(rdev, false); |
1439 | /* turn the clocks off when not encoding */ | ||
1440 | cik_update_cg(rdev, RADEON_CG_BLOCK_VCE, true); | ||
1441 | kv_dpm_powergate_vce(rdev, true); | ||
1439 | } | 1442 | } |
1440 | 1443 | ||
1441 | return 0; | 1444 | return 0; |
1442 | } | 1445 | } |
1443 | #endif | ||
1444 | 1446 | ||
1445 | static int kv_update_samu_dpm(struct radeon_device *rdev, bool gate) | 1447 | static int kv_update_samu_dpm(struct radeon_device *rdev, bool gate) |
1446 | { | 1448 | { |
@@ -1575,11 +1577,16 @@ static void kv_dpm_powergate_vce(struct radeon_device *rdev, bool gate) | |||
1575 | pi->vce_power_gated = gate; | 1577 | pi->vce_power_gated = gate; |
1576 | 1578 | ||
1577 | if (gate) { | 1579 | if (gate) { |
1578 | if (pi->caps_vce_pg) | 1580 | if (pi->caps_vce_pg) { |
1581 | /* XXX do we need a vce_v1_0_stop() ? */ | ||
1579 | kv_notify_message_to_smu(rdev, PPSMC_MSG_VCEPowerOFF); | 1582 | kv_notify_message_to_smu(rdev, PPSMC_MSG_VCEPowerOFF); |
1583 | } | ||
1580 | } else { | 1584 | } else { |
1581 | if (pi->caps_vce_pg) | 1585 | if (pi->caps_vce_pg) { |
1582 | kv_notify_message_to_smu(rdev, PPSMC_MSG_VCEPowerON); | 1586 | kv_notify_message_to_smu(rdev, PPSMC_MSG_VCEPowerON); |
1587 | vce_v2_0_resume(rdev); | ||
1588 | vce_v1_0_start(rdev); | ||
1589 | } | ||
1583 | } | 1590 | } |
1584 | } | 1591 | } |
1585 | 1592 | ||
@@ -1768,7 +1775,7 @@ int kv_dpm_set_power_state(struct radeon_device *rdev) | |||
1768 | { | 1775 | { |
1769 | struct kv_power_info *pi = kv_get_pi(rdev); | 1776 | struct kv_power_info *pi = kv_get_pi(rdev); |
1770 | struct radeon_ps *new_ps = &pi->requested_rps; | 1777 | struct radeon_ps *new_ps = &pi->requested_rps; |
1771 | /*struct radeon_ps *old_ps = &pi->current_rps;*/ | 1778 | struct radeon_ps *old_ps = &pi->current_rps; |
1772 | int ret; | 1779 | int ret; |
1773 | 1780 | ||
1774 | if (pi->bapm_enable) { | 1781 | if (pi->bapm_enable) { |
@@ -1798,13 +1805,12 @@ int kv_dpm_set_power_state(struct radeon_device *rdev) | |||
1798 | kv_set_enabled_levels(rdev); | 1805 | kv_set_enabled_levels(rdev); |
1799 | kv_force_lowest_valid(rdev); | 1806 | kv_force_lowest_valid(rdev); |
1800 | kv_unforce_levels(rdev); | 1807 | kv_unforce_levels(rdev); |
1801 | #if 0 | 1808 | |
1802 | ret = kv_update_vce_dpm(rdev, new_ps, old_ps); | 1809 | ret = kv_update_vce_dpm(rdev, new_ps, old_ps); |
1803 | if (ret) { | 1810 | if (ret) { |
1804 | DRM_ERROR("kv_update_vce_dpm failed\n"); | 1811 | DRM_ERROR("kv_update_vce_dpm failed\n"); |
1805 | return ret; | 1812 | return ret; |
1806 | } | 1813 | } |
1807 | #endif | ||
1808 | kv_update_sclk_t(rdev); | 1814 | kv_update_sclk_t(rdev); |
1809 | } | 1815 | } |
1810 | } else { | 1816 | } else { |
@@ -1823,13 +1829,11 @@ int kv_dpm_set_power_state(struct radeon_device *rdev) | |||
1823 | kv_program_nbps_index_settings(rdev, new_ps); | 1829 | kv_program_nbps_index_settings(rdev, new_ps); |
1824 | kv_freeze_sclk_dpm(rdev, false); | 1830 | kv_freeze_sclk_dpm(rdev, false); |
1825 | kv_set_enabled_levels(rdev); | 1831 | kv_set_enabled_levels(rdev); |
1826 | #if 0 | ||
1827 | ret = kv_update_vce_dpm(rdev, new_ps, old_ps); | 1832 | ret = kv_update_vce_dpm(rdev, new_ps, old_ps); |
1828 | if (ret) { | 1833 | if (ret) { |
1829 | DRM_ERROR("kv_update_vce_dpm failed\n"); | 1834 | DRM_ERROR("kv_update_vce_dpm failed\n"); |
1830 | return ret; | 1835 | return ret; |
1831 | } | 1836 | } |
1832 | #endif | ||
1833 | kv_update_acp_boot_level(rdev); | 1837 | kv_update_acp_boot_level(rdev); |
1834 | kv_update_sclk_t(rdev); | 1838 | kv_update_sclk_t(rdev); |
1835 | kv_enable_nb_dpm(rdev); | 1839 | kv_enable_nb_dpm(rdev); |
@@ -2037,6 +2041,14 @@ static void kv_apply_state_adjust_rules(struct radeon_device *rdev, | |||
2037 | struct radeon_clock_and_voltage_limits *max_limits = | 2041 | struct radeon_clock_and_voltage_limits *max_limits = |
2038 | &rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac; | 2042 | &rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac; |
2039 | 2043 | ||
2044 | if (new_rps->vce_active) { | ||
2045 | new_rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk; | ||
2046 | new_rps->ecclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].ecclk; | ||
2047 | } else { | ||
2048 | new_rps->evclk = 0; | ||
2049 | new_rps->ecclk = 0; | ||
2050 | } | ||
2051 | |||
2040 | mclk = max_limits->mclk; | 2052 | mclk = max_limits->mclk; |
2041 | sclk = min_sclk; | 2053 | sclk = min_sclk; |
2042 | 2054 | ||
@@ -2056,6 +2068,11 @@ static void kv_apply_state_adjust_rules(struct radeon_device *rdev, | |||
2056 | sclk = stable_p_state_sclk; | 2068 | sclk = stable_p_state_sclk; |
2057 | } | 2069 | } |
2058 | 2070 | ||
2071 | if (new_rps->vce_active) { | ||
2072 | if (sclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk) | ||
2073 | sclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk; | ||
2074 | } | ||
2075 | |||
2059 | ps->need_dfs_bypass = true; | 2076 | ps->need_dfs_bypass = true; |
2060 | 2077 | ||
2061 | for (i = 0; i < ps->num_levels; i++) { | 2078 | for (i = 0; i < ps->num_levels; i++) { |
@@ -2092,7 +2109,8 @@ static void kv_apply_state_adjust_rules(struct radeon_device *rdev, | |||
2092 | } | 2109 | } |
2093 | } | 2110 | } |
2094 | 2111 | ||
2095 | pi->video_start = new_rps->dclk || new_rps->vclk; | 2112 | pi->video_start = new_rps->dclk || new_rps->vclk || |
2113 | new_rps->evclk || new_rps->ecclk; | ||
2096 | 2114 | ||
2097 | if ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == | 2115 | if ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == |
2098 | ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) | 2116 | ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) |
@@ -2538,9 +2556,6 @@ static int kv_parse_power_table(struct radeon_device *rdev) | |||
2538 | if (!rdev->pm.dpm.ps) | 2556 | if (!rdev->pm.dpm.ps) |
2539 | return -ENOMEM; | 2557 | return -ENOMEM; |
2540 | power_state_offset = (u8 *)state_array->states; | 2558 | power_state_offset = (u8 *)state_array->states; |
2541 | rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps); | ||
2542 | rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime); | ||
2543 | rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime); | ||
2544 | for (i = 0; i < state_array->ucNumEntries; i++) { | 2559 | for (i = 0; i < state_array->ucNumEntries; i++) { |
2545 | u8 *idx; | 2560 | u8 *idx; |
2546 | power_state = (union pplib_power_state *)power_state_offset; | 2561 | power_state = (union pplib_power_state *)power_state_offset; |
@@ -2577,6 +2592,19 @@ static int kv_parse_power_table(struct radeon_device *rdev) | |||
2577 | power_state_offset += 2 + power_state->v2.ucNumDPMLevels; | 2592 | power_state_offset += 2 + power_state->v2.ucNumDPMLevels; |
2578 | } | 2593 | } |
2579 | rdev->pm.dpm.num_ps = state_array->ucNumEntries; | 2594 | rdev->pm.dpm.num_ps = state_array->ucNumEntries; |
2595 | |||
2596 | /* fill in the vce power states */ | ||
2597 | for (i = 0; i < RADEON_MAX_VCE_LEVELS; i++) { | ||
2598 | u32 sclk; | ||
2599 | clock_array_index = rdev->pm.dpm.vce_states[i].clk_idx; | ||
2600 | clock_info = (union pplib_clock_info *) | ||
2601 | &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize]; | ||
2602 | sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow); | ||
2603 | sclk |= clock_info->sumo.ucEngineClockHigh << 16; | ||
2604 | rdev->pm.dpm.vce_states[i].sclk = sclk; | ||
2605 | rdev->pm.dpm.vce_states[i].mclk = 0; | ||
2606 | } | ||
2607 | |||
2580 | return 0; | 2608 | return 0; |
2581 | } | 2609 | } |
2582 | 2610 | ||
@@ -2590,6 +2618,10 @@ int kv_dpm_init(struct radeon_device *rdev) | |||
2590 | return -ENOMEM; | 2618 | return -ENOMEM; |
2591 | rdev->pm.dpm.priv = pi; | 2619 | rdev->pm.dpm.priv = pi; |
2592 | 2620 | ||
2621 | ret = r600_get_platform_caps(rdev); | ||
2622 | if (ret) | ||
2623 | return ret; | ||
2624 | |||
2593 | ret = r600_parse_extended_power_table(rdev); | 2625 | ret = r600_parse_extended_power_table(rdev); |
2594 | if (ret) | 2626 | if (ret) |
2595 | return ret; | 2627 | return ret; |
@@ -2623,7 +2655,7 @@ int kv_dpm_init(struct radeon_device *rdev) | |||
2623 | pi->caps_fps = false; /* true? */ | 2655 | pi->caps_fps = false; /* true? */ |
2624 | pi->caps_uvd_pg = true; | 2656 | pi->caps_uvd_pg = true; |
2625 | pi->caps_uvd_dpm = true; | 2657 | pi->caps_uvd_dpm = true; |
2626 | pi->caps_vce_pg = false; | 2658 | pi->caps_vce_pg = false; /* XXX true */ |
2627 | pi->caps_samu_pg = false; | 2659 | pi->caps_samu_pg = false; |
2628 | pi->caps_acp_pg = false; | 2660 | pi->caps_acp_pg = false; |
2629 | pi->caps_stable_p_state = false; | 2661 | pi->caps_stable_p_state = false; |
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index ea932ac66fc6..85168ecd216b 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c | |||
@@ -1642,8 +1642,8 @@ static int cayman_cp_resume(struct radeon_device *rdev) | |||
1642 | ring = &rdev->ring[ridx[i]]; | 1642 | ring = &rdev->ring[ridx[i]]; |
1643 | WREG32_P(cp_rb_cntl[i], RB_RPTR_WR_ENA, ~RB_RPTR_WR_ENA); | 1643 | WREG32_P(cp_rb_cntl[i], RB_RPTR_WR_ENA, ~RB_RPTR_WR_ENA); |
1644 | 1644 | ||
1645 | ring->rptr = ring->wptr = 0; | 1645 | ring->wptr = 0; |
1646 | WREG32(cp_rb_rptr[i], ring->rptr); | 1646 | WREG32(cp_rb_rptr[i], 0); |
1647 | WREG32(cp_rb_wptr[i], ring->wptr); | 1647 | WREG32(cp_rb_wptr[i], ring->wptr); |
1648 | 1648 | ||
1649 | mdelay(1); | 1649 | mdelay(1); |
@@ -1917,11 +1917,9 @@ bool cayman_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) | |||
1917 | if (!(reset_mask & (RADEON_RESET_GFX | | 1917 | if (!(reset_mask & (RADEON_RESET_GFX | |
1918 | RADEON_RESET_COMPUTE | | 1918 | RADEON_RESET_COMPUTE | |
1919 | RADEON_RESET_CP))) { | 1919 | RADEON_RESET_CP))) { |
1920 | radeon_ring_lockup_update(ring); | 1920 | radeon_ring_lockup_update(rdev, ring); |
1921 | return false; | 1921 | return false; |
1922 | } | 1922 | } |
1923 | /* force CP activities */ | ||
1924 | radeon_ring_force_activity(rdev, ring); | ||
1925 | return radeon_ring_test_lockup(rdev, ring); | 1923 | return radeon_ring_test_lockup(rdev, ring); |
1926 | } | 1924 | } |
1927 | 1925 | ||
diff --git a/drivers/gpu/drm/radeon/ni_dma.c b/drivers/gpu/drm/radeon/ni_dma.c index 7cf96b15377f..6378e0276691 100644 --- a/drivers/gpu/drm/radeon/ni_dma.c +++ b/drivers/gpu/drm/radeon/ni_dma.c | |||
@@ -248,8 +248,6 @@ int cayman_dma_resume(struct radeon_device *rdev) | |||
248 | ring->wptr = 0; | 248 | ring->wptr = 0; |
249 | WREG32(DMA_RB_WPTR + reg_offset, ring->wptr << 2); | 249 | WREG32(DMA_RB_WPTR + reg_offset, ring->wptr << 2); |
250 | 250 | ||
251 | ring->rptr = RREG32(DMA_RB_RPTR + reg_offset) >> 2; | ||
252 | |||
253 | WREG32(DMA_RB_CNTL + reg_offset, rb_cntl | DMA_RB_ENABLE); | 251 | WREG32(DMA_RB_CNTL + reg_offset, rb_cntl | DMA_RB_ENABLE); |
254 | 252 | ||
255 | ring->ready = true; | 253 | ring->ready = true; |
@@ -302,11 +300,9 @@ bool cayman_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) | |||
302 | mask = RADEON_RESET_DMA1; | 300 | mask = RADEON_RESET_DMA1; |
303 | 301 | ||
304 | if (!(reset_mask & mask)) { | 302 | if (!(reset_mask & mask)) { |
305 | radeon_ring_lockup_update(ring); | 303 | radeon_ring_lockup_update(rdev, ring); |
306 | return false; | 304 | return false; |
307 | } | 305 | } |
308 | /* force ring activities */ | ||
309 | radeon_ring_force_activity(rdev, ring); | ||
310 | return radeon_ring_test_lockup(rdev, ring); | 306 | return radeon_ring_test_lockup(rdev, ring); |
311 | } | 307 | } |
312 | 308 | ||
diff --git a/drivers/gpu/drm/radeon/ni_dpm.c b/drivers/gpu/drm/radeon/ni_dpm.c index ca814276b075..004c931606c4 100644 --- a/drivers/gpu/drm/radeon/ni_dpm.c +++ b/drivers/gpu/drm/radeon/ni_dpm.c | |||
@@ -4025,9 +4025,6 @@ static int ni_parse_power_table(struct radeon_device *rdev) | |||
4025 | power_info->pplib.ucNumStates, GFP_KERNEL); | 4025 | power_info->pplib.ucNumStates, GFP_KERNEL); |
4026 | if (!rdev->pm.dpm.ps) | 4026 | if (!rdev->pm.dpm.ps) |
4027 | return -ENOMEM; | 4027 | return -ENOMEM; |
4028 | rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps); | ||
4029 | rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime); | ||
4030 | rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime); | ||
4031 | 4028 | ||
4032 | for (i = 0; i < power_info->pplib.ucNumStates; i++) { | 4029 | for (i = 0; i < power_info->pplib.ucNumStates; i++) { |
4033 | power_state = (union pplib_power_state *) | 4030 | power_state = (union pplib_power_state *) |
@@ -4089,6 +4086,10 @@ int ni_dpm_init(struct radeon_device *rdev) | |||
4089 | pi->min_vddc_in_table = 0; | 4086 | pi->min_vddc_in_table = 0; |
4090 | pi->max_vddc_in_table = 0; | 4087 | pi->max_vddc_in_table = 0; |
4091 | 4088 | ||
4089 | ret = r600_get_platform_caps(rdev); | ||
4090 | if (ret) | ||
4091 | return ret; | ||
4092 | |||
4092 | ret = ni_parse_power_table(rdev); | 4093 | ret = ni_parse_power_table(rdev); |
4093 | if (ret) | 4094 | if (ret) |
4094 | return ret; | 4095 | return ret; |
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index ef024ce3f7cc..1690a2dc0721 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c | |||
@@ -1193,7 +1193,6 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) | |||
1193 | 1193 | ||
1194 | WREG32(RADEON_CP_RB_CNTL, tmp); | 1194 | WREG32(RADEON_CP_RB_CNTL, tmp); |
1195 | udelay(10); | 1195 | udelay(10); |
1196 | ring->rptr = RREG32(RADEON_CP_RB_RPTR); | ||
1197 | /* Set cp mode to bus mastering & enable cp*/ | 1196 | /* Set cp mode to bus mastering & enable cp*/ |
1198 | WREG32(RADEON_CP_CSQ_MODE, | 1197 | WREG32(RADEON_CP_CSQ_MODE, |
1199 | REG_SET(RADEON_INDIRECT2_START, indirect2_start) | | 1198 | REG_SET(RADEON_INDIRECT2_START, indirect2_start) | |
@@ -2523,11 +2522,9 @@ bool r100_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) | |||
2523 | 2522 | ||
2524 | rbbm_status = RREG32(R_000E40_RBBM_STATUS); | 2523 | rbbm_status = RREG32(R_000E40_RBBM_STATUS); |
2525 | if (!G_000E40_GUI_ACTIVE(rbbm_status)) { | 2524 | if (!G_000E40_GUI_ACTIVE(rbbm_status)) { |
2526 | radeon_ring_lockup_update(ring); | 2525 | radeon_ring_lockup_update(rdev, ring); |
2527 | return false; | 2526 | return false; |
2528 | } | 2527 | } |
2529 | /* force CP activities */ | ||
2530 | radeon_ring_force_activity(rdev, ring); | ||
2531 | return radeon_ring_test_lockup(rdev, ring); | 2528 | return radeon_ring_test_lockup(rdev, ring); |
2532 | } | 2529 | } |
2533 | 2530 | ||
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index cdbc4171fe73..0f4ab928a15a 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
@@ -1748,11 +1748,9 @@ bool r600_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) | |||
1748 | if (!(reset_mask & (RADEON_RESET_GFX | | 1748 | if (!(reset_mask & (RADEON_RESET_GFX | |
1749 | RADEON_RESET_COMPUTE | | 1749 | RADEON_RESET_COMPUTE | |
1750 | RADEON_RESET_CP))) { | 1750 | RADEON_RESET_CP))) { |
1751 | radeon_ring_lockup_update(ring); | 1751 | radeon_ring_lockup_update(rdev, ring); |
1752 | return false; | 1752 | return false; |
1753 | } | 1753 | } |
1754 | /* force CP activities */ | ||
1755 | radeon_ring_force_activity(rdev, ring); | ||
1756 | return radeon_ring_test_lockup(rdev, ring); | 1754 | return radeon_ring_test_lockup(rdev, ring); |
1757 | } | 1755 | } |
1758 | 1756 | ||
@@ -2604,8 +2602,6 @@ int r600_cp_resume(struct radeon_device *rdev) | |||
2604 | WREG32(CP_RB_BASE, ring->gpu_addr >> 8); | 2602 | WREG32(CP_RB_BASE, ring->gpu_addr >> 8); |
2605 | WREG32(CP_DEBUG, (1 << 27) | (1 << 28)); | 2603 | WREG32(CP_DEBUG, (1 << 27) | (1 << 28)); |
2606 | 2604 | ||
2607 | ring->rptr = RREG32(CP_RB_RPTR); | ||
2608 | |||
2609 | r600_cp_start(rdev); | 2605 | r600_cp_start(rdev); |
2610 | ring->ready = true; | 2606 | ring->ready = true; |
2611 | r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, ring); | 2607 | r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, ring); |
diff --git a/drivers/gpu/drm/radeon/r600_dma.c b/drivers/gpu/drm/radeon/r600_dma.c index b2d4c91e6272..53fcb28f5578 100644 --- a/drivers/gpu/drm/radeon/r600_dma.c +++ b/drivers/gpu/drm/radeon/r600_dma.c | |||
@@ -176,8 +176,6 @@ int r600_dma_resume(struct radeon_device *rdev) | |||
176 | ring->wptr = 0; | 176 | ring->wptr = 0; |
177 | WREG32(DMA_RB_WPTR, ring->wptr << 2); | 177 | WREG32(DMA_RB_WPTR, ring->wptr << 2); |
178 | 178 | ||
179 | ring->rptr = RREG32(DMA_RB_RPTR) >> 2; | ||
180 | |||
181 | WREG32(DMA_RB_CNTL, rb_cntl | DMA_RB_ENABLE); | 179 | WREG32(DMA_RB_CNTL, rb_cntl | DMA_RB_ENABLE); |
182 | 180 | ||
183 | ring->ready = true; | 181 | ring->ready = true; |
@@ -221,11 +219,9 @@ bool r600_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) | |||
221 | u32 reset_mask = r600_gpu_check_soft_reset(rdev); | 219 | u32 reset_mask = r600_gpu_check_soft_reset(rdev); |
222 | 220 | ||
223 | if (!(reset_mask & RADEON_RESET_DMA)) { | 221 | if (!(reset_mask & RADEON_RESET_DMA)) { |
224 | radeon_ring_lockup_update(ring); | 222 | radeon_ring_lockup_update(rdev, ring); |
225 | return false; | 223 | return false; |
226 | } | 224 | } |
227 | /* force ring activities */ | ||
228 | radeon_ring_force_activity(rdev, ring); | ||
229 | return radeon_ring_test_lockup(rdev, ring); | 225 | return radeon_ring_test_lockup(rdev, ring); |
230 | } | 226 | } |
231 | 227 | ||
diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c index e4cc9b314ce9..cbf7e3269f84 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.c +++ b/drivers/gpu/drm/radeon/r600_dpm.c | |||
@@ -834,6 +834,26 @@ static int r600_parse_clk_voltage_dep_table(struct radeon_clock_voltage_dependen | |||
834 | return 0; | 834 | return 0; |
835 | } | 835 | } |
836 | 836 | ||
837 | int r600_get_platform_caps(struct radeon_device *rdev) | ||
838 | { | ||
839 | struct radeon_mode_info *mode_info = &rdev->mode_info; | ||
840 | union power_info *power_info; | ||
841 | int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); | ||
842 | u16 data_offset; | ||
843 | u8 frev, crev; | ||
844 | |||
845 | if (!atom_parse_data_header(mode_info->atom_context, index, NULL, | ||
846 | &frev, &crev, &data_offset)) | ||
847 | return -EINVAL; | ||
848 | power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); | ||
849 | |||
850 | rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps); | ||
851 | rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime); | ||
852 | rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime); | ||
853 | |||
854 | return 0; | ||
855 | } | ||
856 | |||
837 | /* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */ | 857 | /* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */ |
838 | #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12 | 858 | #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12 |
839 | #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14 | 859 | #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14 |
@@ -1043,7 +1063,15 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) | |||
1043 | (mode_info->atom_context->bios + data_offset + | 1063 | (mode_info->atom_context->bios + data_offset + |
1044 | le16_to_cpu(ext_hdr->usVCETableOffset) + 1 + | 1064 | le16_to_cpu(ext_hdr->usVCETableOffset) + 1 + |
1045 | 1 + array->ucNumEntries * sizeof(VCEClockInfo)); | 1065 | 1 + array->ucNumEntries * sizeof(VCEClockInfo)); |
1066 | ATOM_PPLIB_VCE_State_Table *states = | ||
1067 | (ATOM_PPLIB_VCE_State_Table *) | ||
1068 | (mode_info->atom_context->bios + data_offset + | ||
1069 | le16_to_cpu(ext_hdr->usVCETableOffset) + 1 + | ||
1070 | 1 + (array->ucNumEntries * sizeof (VCEClockInfo)) + | ||
1071 | 1 + (limits->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record))); | ||
1046 | ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *entry; | 1072 | ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *entry; |
1073 | ATOM_PPLIB_VCE_State_Record *state_entry; | ||
1074 | VCEClockInfo *vce_clk; | ||
1047 | u32 size = limits->numEntries * | 1075 | u32 size = limits->numEntries * |
1048 | sizeof(struct radeon_vce_clock_voltage_dependency_entry); | 1076 | sizeof(struct radeon_vce_clock_voltage_dependency_entry); |
1049 | rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries = | 1077 | rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries = |
@@ -1055,8 +1083,9 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) | |||
1055 | rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count = | 1083 | rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count = |
1056 | limits->numEntries; | 1084 | limits->numEntries; |
1057 | entry = &limits->entries[0]; | 1085 | entry = &limits->entries[0]; |
1086 | state_entry = &states->entries[0]; | ||
1058 | for (i = 0; i < limits->numEntries; i++) { | 1087 | for (i = 0; i < limits->numEntries; i++) { |
1059 | VCEClockInfo *vce_clk = (VCEClockInfo *) | 1088 | vce_clk = (VCEClockInfo *) |
1060 | ((u8 *)&array->entries[0] + | 1089 | ((u8 *)&array->entries[0] + |
1061 | (entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo))); | 1090 | (entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo))); |
1062 | rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].evclk = | 1091 | rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].evclk = |
@@ -1068,6 +1097,23 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) | |||
1068 | entry = (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *) | 1097 | entry = (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *) |
1069 | ((u8 *)entry + sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record)); | 1098 | ((u8 *)entry + sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record)); |
1070 | } | 1099 | } |
1100 | for (i = 0; i < states->numEntries; i++) { | ||
1101 | if (i >= RADEON_MAX_VCE_LEVELS) | ||
1102 | break; | ||
1103 | vce_clk = (VCEClockInfo *) | ||
1104 | ((u8 *)&array->entries[0] + | ||
1105 | (state_entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo))); | ||
1106 | rdev->pm.dpm.vce_states[i].evclk = | ||
1107 | le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16); | ||
1108 | rdev->pm.dpm.vce_states[i].ecclk = | ||
1109 | le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16); | ||
1110 | rdev->pm.dpm.vce_states[i].clk_idx = | ||
1111 | state_entry->ucClockInfoIndex & 0x3f; | ||
1112 | rdev->pm.dpm.vce_states[i].pstate = | ||
1113 | (state_entry->ucClockInfoIndex & 0xc0) >> 6; | ||
1114 | state_entry = (ATOM_PPLIB_VCE_State_Record *) | ||
1115 | ((u8 *)state_entry + sizeof(ATOM_PPLIB_VCE_State_Record)); | ||
1116 | } | ||
1071 | } | 1117 | } |
1072 | if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) && | 1118 | if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) && |
1073 | ext_hdr->usUVDTableOffset) { | 1119 | ext_hdr->usUVDTableOffset) { |
diff --git a/drivers/gpu/drm/radeon/r600_dpm.h b/drivers/gpu/drm/radeon/r600_dpm.h index 07eab2b04e81..46b9d2a03018 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.h +++ b/drivers/gpu/drm/radeon/r600_dpm.h | |||
@@ -215,6 +215,8 @@ void r600_stop_dpm(struct radeon_device *rdev); | |||
215 | 215 | ||
216 | bool r600_is_internal_thermal_sensor(enum radeon_int_thermal_type sensor); | 216 | bool r600_is_internal_thermal_sensor(enum radeon_int_thermal_type sensor); |
217 | 217 | ||
218 | int r600_get_platform_caps(struct radeon_device *rdev); | ||
219 | |||
218 | int r600_parse_extended_power_table(struct radeon_device *rdev); | 220 | int r600_parse_extended_power_table(struct radeon_device *rdev); |
219 | void r600_free_extended_power_table(struct radeon_device *rdev); | 221 | void r600_free_extended_power_table(struct radeon_device *rdev); |
220 | 222 | ||
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 024db37b1832..4581df193932 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -113,19 +113,16 @@ extern int radeon_hard_reset; | |||
113 | #define RADEONFB_CONN_LIMIT 4 | 113 | #define RADEONFB_CONN_LIMIT 4 |
114 | #define RADEON_BIOS_NUM_SCRATCH 8 | 114 | #define RADEON_BIOS_NUM_SCRATCH 8 |
115 | 115 | ||
116 | /* max number of rings */ | ||
117 | #define RADEON_NUM_RINGS 6 | ||
118 | |||
119 | /* fence seq are set to this number when signaled */ | 116 | /* fence seq are set to this number when signaled */ |
120 | #define RADEON_FENCE_SIGNALED_SEQ 0LL | 117 | #define RADEON_FENCE_SIGNALED_SEQ 0LL |
121 | 118 | ||
122 | /* internal ring indices */ | 119 | /* internal ring indices */ |
123 | /* r1xx+ has gfx CP ring */ | 120 | /* r1xx+ has gfx CP ring */ |
124 | #define RADEON_RING_TYPE_GFX_INDEX 0 | 121 | #define RADEON_RING_TYPE_GFX_INDEX 0 |
125 | 122 | ||
126 | /* cayman has 2 compute CP rings */ | 123 | /* cayman has 2 compute CP rings */ |
127 | #define CAYMAN_RING_TYPE_CP1_INDEX 1 | 124 | #define CAYMAN_RING_TYPE_CP1_INDEX 1 |
128 | #define CAYMAN_RING_TYPE_CP2_INDEX 2 | 125 | #define CAYMAN_RING_TYPE_CP2_INDEX 2 |
129 | 126 | ||
130 | /* R600+ has an async dma ring */ | 127 | /* R600+ has an async dma ring */ |
131 | #define R600_RING_TYPE_DMA_INDEX 3 | 128 | #define R600_RING_TYPE_DMA_INDEX 3 |
@@ -133,7 +130,17 @@ extern int radeon_hard_reset; | |||
133 | #define CAYMAN_RING_TYPE_DMA1_INDEX 4 | 130 | #define CAYMAN_RING_TYPE_DMA1_INDEX 4 |
134 | 131 | ||
135 | /* R600+ */ | 132 | /* R600+ */ |
136 | #define R600_RING_TYPE_UVD_INDEX 5 | 133 | #define R600_RING_TYPE_UVD_INDEX 5 |
134 | |||
135 | /* TN+ */ | ||
136 | #define TN_RING_TYPE_VCE1_INDEX 6 | ||
137 | #define TN_RING_TYPE_VCE2_INDEX 7 | ||
138 | |||
139 | /* max number of rings */ | ||
140 | #define RADEON_NUM_RINGS 8 | ||
141 | |||
142 | /* number of hw syncs before falling back on blocking */ | ||
143 | #define RADEON_NUM_SYNCS 4 | ||
137 | 144 | ||
138 | /* number of hw syncs before falling back on blocking */ | 145 | /* number of hw syncs before falling back on blocking */ |
139 | #define RADEON_NUM_SYNCS 4 | 146 | #define RADEON_NUM_SYNCS 4 |
@@ -789,7 +796,6 @@ struct radeon_ib { | |||
789 | struct radeon_ring { | 796 | struct radeon_ring { |
790 | struct radeon_bo *ring_obj; | 797 | struct radeon_bo *ring_obj; |
791 | volatile uint32_t *ring; | 798 | volatile uint32_t *ring; |
792 | unsigned rptr; | ||
793 | unsigned rptr_offs; | 799 | unsigned rptr_offs; |
794 | unsigned rptr_save_reg; | 800 | unsigned rptr_save_reg; |
795 | u64 next_rptr_gpu_addr; | 801 | u64 next_rptr_gpu_addr; |
@@ -953,8 +959,8 @@ void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *c | |||
953 | void radeon_ring_undo(struct radeon_ring *ring); | 959 | void radeon_ring_undo(struct radeon_ring *ring); |
954 | void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *cp); | 960 | void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *cp); |
955 | int radeon_ring_test(struct radeon_device *rdev, struct radeon_ring *cp); | 961 | int radeon_ring_test(struct radeon_device *rdev, struct radeon_ring *cp); |
956 | void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring); | 962 | void radeon_ring_lockup_update(struct radeon_device *rdev, |
957 | void radeon_ring_lockup_update(struct radeon_ring *ring); | 963 | struct radeon_ring *ring); |
958 | bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *ring); | 964 | bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *ring); |
959 | unsigned radeon_ring_backup(struct radeon_device *rdev, struct radeon_ring *ring, | 965 | unsigned radeon_ring_backup(struct radeon_device *rdev, struct radeon_ring *ring, |
960 | uint32_t **data); | 966 | uint32_t **data); |
@@ -1255,6 +1261,17 @@ enum radeon_dpm_event_src { | |||
1255 | RADEON_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL = 4 | 1261 | RADEON_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL = 4 |
1256 | }; | 1262 | }; |
1257 | 1263 | ||
1264 | #define RADEON_MAX_VCE_LEVELS 6 | ||
1265 | |||
1266 | enum radeon_vce_level { | ||
1267 | RADEON_VCE_LEVEL_AC_ALL = 0, /* AC, All cases */ | ||
1268 | RADEON_VCE_LEVEL_DC_EE = 1, /* DC, entropy encoding */ | ||
1269 | RADEON_VCE_LEVEL_DC_LL_LOW = 2, /* DC, low latency queue, res <= 720 */ | ||
1270 | RADEON_VCE_LEVEL_DC_LL_HIGH = 3, /* DC, low latency queue, 1080 >= res > 720 */ | ||
1271 | RADEON_VCE_LEVEL_DC_GP_LOW = 4, /* DC, general purpose queue, res <= 720 */ | ||
1272 | RADEON_VCE_LEVEL_DC_GP_HIGH = 5, /* DC, general purpose queue, 1080 >= res > 720 */ | ||
1273 | }; | ||
1274 | |||
1258 | struct radeon_ps { | 1275 | struct radeon_ps { |
1259 | u32 caps; /* vbios flags */ | 1276 | u32 caps; /* vbios flags */ |
1260 | u32 class; /* vbios flags */ | 1277 | u32 class; /* vbios flags */ |
@@ -1265,6 +1282,8 @@ struct radeon_ps { | |||
1265 | /* VCE clocks */ | 1282 | /* VCE clocks */ |
1266 | u32 evclk; | 1283 | u32 evclk; |
1267 | u32 ecclk; | 1284 | u32 ecclk; |
1285 | bool vce_active; | ||
1286 | enum radeon_vce_level vce_level; | ||
1268 | /* asic priv */ | 1287 | /* asic priv */ |
1269 | void *ps_priv; | 1288 | void *ps_priv; |
1270 | }; | 1289 | }; |
@@ -1439,6 +1458,17 @@ enum radeon_dpm_forced_level { | |||
1439 | RADEON_DPM_FORCED_LEVEL_HIGH = 2, | 1458 | RADEON_DPM_FORCED_LEVEL_HIGH = 2, |
1440 | }; | 1459 | }; |
1441 | 1460 | ||
1461 | struct radeon_vce_state { | ||
1462 | /* vce clocks */ | ||
1463 | u32 evclk; | ||
1464 | u32 ecclk; | ||
1465 | /* gpu clocks */ | ||
1466 | u32 sclk; | ||
1467 | u32 mclk; | ||
1468 | u8 clk_idx; | ||
1469 | u8 pstate; | ||
1470 | }; | ||
1471 | |||
1442 | struct radeon_dpm { | 1472 | struct radeon_dpm { |
1443 | struct radeon_ps *ps; | 1473 | struct radeon_ps *ps; |
1444 | /* number of valid power states */ | 1474 | /* number of valid power states */ |
@@ -1451,6 +1481,9 @@ struct radeon_dpm { | |||
1451 | struct radeon_ps *boot_ps; | 1481 | struct radeon_ps *boot_ps; |
1452 | /* default uvd power state */ | 1482 | /* default uvd power state */ |
1453 | struct radeon_ps *uvd_ps; | 1483 | struct radeon_ps *uvd_ps; |
1484 | /* vce requirements */ | ||
1485 | struct radeon_vce_state vce_states[RADEON_MAX_VCE_LEVELS]; | ||
1486 | enum radeon_vce_level vce_level; | ||
1454 | enum radeon_pm_state_type state; | 1487 | enum radeon_pm_state_type state; |
1455 | enum radeon_pm_state_type user_state; | 1488 | enum radeon_pm_state_type user_state; |
1456 | u32 platform_caps; | 1489 | u32 platform_caps; |
@@ -1476,6 +1509,7 @@ struct radeon_dpm { | |||
1476 | /* special states active */ | 1509 | /* special states active */ |
1477 | bool thermal_active; | 1510 | bool thermal_active; |
1478 | bool uvd_active; | 1511 | bool uvd_active; |
1512 | bool vce_active; | ||
1479 | /* thermal handling */ | 1513 | /* thermal handling */ |
1480 | struct radeon_dpm_thermal thermal; | 1514 | struct radeon_dpm_thermal thermal; |
1481 | /* forced levels */ | 1515 | /* forced levels */ |
@@ -1486,6 +1520,7 @@ struct radeon_dpm { | |||
1486 | }; | 1520 | }; |
1487 | 1521 | ||
1488 | void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable); | 1522 | void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable); |
1523 | void radeon_dpm_enable_vce(struct radeon_device *rdev, bool enable); | ||
1489 | 1524 | ||
1490 | struct radeon_pm { | 1525 | struct radeon_pm { |
1491 | struct mutex mutex; | 1526 | struct mutex mutex; |
@@ -1591,6 +1626,46 @@ int radeon_uvd_calc_upll_dividers(struct radeon_device *rdev, | |||
1591 | int radeon_uvd_send_upll_ctlreq(struct radeon_device *rdev, | 1626 | int radeon_uvd_send_upll_ctlreq(struct radeon_device *rdev, |
1592 | unsigned cg_upll_func_cntl); | 1627 | unsigned cg_upll_func_cntl); |
1593 | 1628 | ||
1629 | /* | ||
1630 | * VCE | ||
1631 | */ | ||
1632 | #define RADEON_MAX_VCE_HANDLES 16 | ||
1633 | #define RADEON_VCE_STACK_SIZE (1024*1024) | ||
1634 | #define RADEON_VCE_HEAP_SIZE (4*1024*1024) | ||
1635 | |||
1636 | struct radeon_vce { | ||
1637 | struct radeon_bo *vcpu_bo; | ||
1638 | void *cpu_addr; | ||
1639 | uint64_t gpu_addr; | ||
1640 | unsigned fw_version; | ||
1641 | unsigned fb_version; | ||
1642 | atomic_t handles[RADEON_MAX_VCE_HANDLES]; | ||
1643 | struct drm_file *filp[RADEON_MAX_VCE_HANDLES]; | ||
1644 | struct delayed_work idle_work; | ||
1645 | }; | ||
1646 | |||
1647 | int radeon_vce_init(struct radeon_device *rdev); | ||
1648 | void radeon_vce_fini(struct radeon_device *rdev); | ||
1649 | int radeon_vce_suspend(struct radeon_device *rdev); | ||
1650 | int radeon_vce_resume(struct radeon_device *rdev); | ||
1651 | int radeon_vce_get_create_msg(struct radeon_device *rdev, int ring, | ||
1652 | uint32_t handle, struct radeon_fence **fence); | ||
1653 | int radeon_vce_get_destroy_msg(struct radeon_device *rdev, int ring, | ||
1654 | uint32_t handle, struct radeon_fence **fence); | ||
1655 | void radeon_vce_free_handles(struct radeon_device *rdev, struct drm_file *filp); | ||
1656 | void radeon_vce_note_usage(struct radeon_device *rdev); | ||
1657 | int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi); | ||
1658 | int radeon_vce_cs_parse(struct radeon_cs_parser *p); | ||
1659 | bool radeon_vce_semaphore_emit(struct radeon_device *rdev, | ||
1660 | struct radeon_ring *ring, | ||
1661 | struct radeon_semaphore *semaphore, | ||
1662 | bool emit_wait); | ||
1663 | void radeon_vce_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); | ||
1664 | void radeon_vce_fence_emit(struct radeon_device *rdev, | ||
1665 | struct radeon_fence *fence); | ||
1666 | int radeon_vce_ring_test(struct radeon_device *rdev, struct radeon_ring *ring); | ||
1667 | int radeon_vce_ib_test(struct radeon_device *rdev, struct radeon_ring *ring); | ||
1668 | |||
1594 | struct r600_audio_pin { | 1669 | struct r600_audio_pin { |
1595 | int channels; | 1670 | int channels; |
1596 | int rate; | 1671 | int rate; |
@@ -1780,6 +1855,7 @@ struct radeon_asic { | |||
1780 | void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes); | 1855 | void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes); |
1781 | void (*set_clock_gating)(struct radeon_device *rdev, int enable); | 1856 | void (*set_clock_gating)(struct radeon_device *rdev, int enable); |
1782 | int (*set_uvd_clocks)(struct radeon_device *rdev, u32 vclk, u32 dclk); | 1857 | int (*set_uvd_clocks)(struct radeon_device *rdev, u32 vclk, u32 dclk); |
1858 | int (*set_vce_clocks)(struct radeon_device *rdev, u32 evclk, u32 ecclk); | ||
1783 | int (*get_temperature)(struct radeon_device *rdev); | 1859 | int (*get_temperature)(struct radeon_device *rdev); |
1784 | } pm; | 1860 | } pm; |
1785 | /* dynamic power management */ | 1861 | /* dynamic power management */ |
@@ -2186,6 +2262,7 @@ struct radeon_device { | |||
2186 | struct radeon_gem gem; | 2262 | struct radeon_gem gem; |
2187 | struct radeon_pm pm; | 2263 | struct radeon_pm pm; |
2188 | struct radeon_uvd uvd; | 2264 | struct radeon_uvd uvd; |
2265 | struct radeon_vce vce; | ||
2189 | uint32_t bios_scratch[RADEON_BIOS_NUM_SCRATCH]; | 2266 | uint32_t bios_scratch[RADEON_BIOS_NUM_SCRATCH]; |
2190 | struct radeon_wb wb; | 2267 | struct radeon_wb wb; |
2191 | struct radeon_dummy_page dummy_page; | 2268 | struct radeon_dummy_page dummy_page; |
@@ -2205,6 +2282,7 @@ struct radeon_device { | |||
2205 | const struct firmware *sdma_fw; /* CIK SDMA firmware */ | 2282 | const struct firmware *sdma_fw; /* CIK SDMA firmware */ |
2206 | const struct firmware *smc_fw; /* SMC firmware */ | 2283 | const struct firmware *smc_fw; /* SMC firmware */ |
2207 | const struct firmware *uvd_fw; /* UVD firmware */ | 2284 | const struct firmware *uvd_fw; /* UVD firmware */ |
2285 | const struct firmware *vce_fw; /* VCE firmware */ | ||
2208 | struct r600_vram_scratch vram_scratch; | 2286 | struct r600_vram_scratch vram_scratch; |
2209 | int msi_enabled; /* msi enabled */ | 2287 | int msi_enabled; /* msi enabled */ |
2210 | struct r600_ih ih; /* r6/700 interrupt ring */ | 2288 | struct r600_ih ih; /* r6/700 interrupt ring */ |
@@ -2639,6 +2717,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v); | |||
2639 | #define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->pm.set_pcie_lanes((rdev), (l)) | 2717 | #define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->pm.set_pcie_lanes((rdev), (l)) |
2640 | #define radeon_set_clock_gating(rdev, e) (rdev)->asic->pm.set_clock_gating((rdev), (e)) | 2718 | #define radeon_set_clock_gating(rdev, e) (rdev)->asic->pm.set_clock_gating((rdev), (e)) |
2641 | #define radeon_set_uvd_clocks(rdev, v, d) (rdev)->asic->pm.set_uvd_clocks((rdev), (v), (d)) | 2719 | #define radeon_set_uvd_clocks(rdev, v, d) (rdev)->asic->pm.set_uvd_clocks((rdev), (v), (d)) |
2720 | #define radeon_set_vce_clocks(rdev, ev, ec) (rdev)->asic->pm.set_vce_clocks((rdev), (ev), (ec)) | ||
2642 | #define radeon_get_temperature(rdev) (rdev)->asic->pm.get_temperature((rdev)) | 2721 | #define radeon_get_temperature(rdev) (rdev)->asic->pm.get_temperature((rdev)) |
2643 | #define radeon_set_surface_reg(rdev, r, f, p, o, s) ((rdev)->asic->surface.set_reg((rdev), (r), (f), (p), (o), (s))) | 2722 | #define radeon_set_surface_reg(rdev, r, f, p, o, s) ((rdev)->asic->surface.set_reg((rdev), (r), (f), (p), (o), (s))) |
2644 | #define radeon_clear_surface_reg(rdev, r) ((rdev)->asic->surface.clear_reg((rdev), (r))) | 2723 | #define radeon_clear_surface_reg(rdev, r) ((rdev)->asic->surface.clear_reg((rdev), (r))) |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index dda02bfc10a4..b8a24a75d4ff 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c | |||
@@ -1987,6 +1987,19 @@ static struct radeon_asic_ring ci_dma_ring = { | |||
1987 | .set_wptr = &cik_sdma_set_wptr, | 1987 | .set_wptr = &cik_sdma_set_wptr, |
1988 | }; | 1988 | }; |
1989 | 1989 | ||
1990 | static struct radeon_asic_ring ci_vce_ring = { | ||
1991 | .ib_execute = &radeon_vce_ib_execute, | ||
1992 | .emit_fence = &radeon_vce_fence_emit, | ||
1993 | .emit_semaphore = &radeon_vce_semaphore_emit, | ||
1994 | .cs_parse = &radeon_vce_cs_parse, | ||
1995 | .ring_test = &radeon_vce_ring_test, | ||
1996 | .ib_test = &radeon_vce_ib_test, | ||
1997 | .is_lockup = &radeon_ring_test_lockup, | ||
1998 | .get_rptr = &vce_v1_0_get_rptr, | ||
1999 | .get_wptr = &vce_v1_0_get_wptr, | ||
2000 | .set_wptr = &vce_v1_0_set_wptr, | ||
2001 | }; | ||
2002 | |||
1990 | static struct radeon_asic ci_asic = { | 2003 | static struct radeon_asic ci_asic = { |
1991 | .init = &cik_init, | 2004 | .init = &cik_init, |
1992 | .fini = &cik_fini, | 2005 | .fini = &cik_fini, |
@@ -2015,6 +2028,8 @@ static struct radeon_asic ci_asic = { | |||
2015 | [R600_RING_TYPE_DMA_INDEX] = &ci_dma_ring, | 2028 | [R600_RING_TYPE_DMA_INDEX] = &ci_dma_ring, |
2016 | [CAYMAN_RING_TYPE_DMA1_INDEX] = &ci_dma_ring, | 2029 | [CAYMAN_RING_TYPE_DMA1_INDEX] = &ci_dma_ring, |
2017 | [R600_RING_TYPE_UVD_INDEX] = &cayman_uvd_ring, | 2030 | [R600_RING_TYPE_UVD_INDEX] = &cayman_uvd_ring, |
2031 | [TN_RING_TYPE_VCE1_INDEX] = &ci_vce_ring, | ||
2032 | [TN_RING_TYPE_VCE2_INDEX] = &ci_vce_ring, | ||
2018 | }, | 2033 | }, |
2019 | .irq = { | 2034 | .irq = { |
2020 | .set = &cik_irq_set, | 2035 | .set = &cik_irq_set, |
@@ -2061,6 +2076,7 @@ static struct radeon_asic ci_asic = { | |||
2061 | .set_pcie_lanes = NULL, | 2076 | .set_pcie_lanes = NULL, |
2062 | .set_clock_gating = NULL, | 2077 | .set_clock_gating = NULL, |
2063 | .set_uvd_clocks = &cik_set_uvd_clocks, | 2078 | .set_uvd_clocks = &cik_set_uvd_clocks, |
2079 | .set_vce_clocks = &cik_set_vce_clocks, | ||
2064 | .get_temperature = &ci_get_temp, | 2080 | .get_temperature = &ci_get_temp, |
2065 | }, | 2081 | }, |
2066 | .dpm = { | 2082 | .dpm = { |
@@ -2117,6 +2133,8 @@ static struct radeon_asic kv_asic = { | |||
2117 | [R600_RING_TYPE_DMA_INDEX] = &ci_dma_ring, | 2133 | [R600_RING_TYPE_DMA_INDEX] = &ci_dma_ring, |
2118 | [CAYMAN_RING_TYPE_DMA1_INDEX] = &ci_dma_ring, | 2134 | [CAYMAN_RING_TYPE_DMA1_INDEX] = &ci_dma_ring, |
2119 | [R600_RING_TYPE_UVD_INDEX] = &cayman_uvd_ring, | 2135 | [R600_RING_TYPE_UVD_INDEX] = &cayman_uvd_ring, |
2136 | [TN_RING_TYPE_VCE1_INDEX] = &ci_vce_ring, | ||
2137 | [TN_RING_TYPE_VCE2_INDEX] = &ci_vce_ring, | ||
2120 | }, | 2138 | }, |
2121 | .irq = { | 2139 | .irq = { |
2122 | .set = &cik_irq_set, | 2140 | .set = &cik_irq_set, |
@@ -2163,6 +2181,7 @@ static struct radeon_asic kv_asic = { | |||
2163 | .set_pcie_lanes = NULL, | 2181 | .set_pcie_lanes = NULL, |
2164 | .set_clock_gating = NULL, | 2182 | .set_clock_gating = NULL, |
2165 | .set_uvd_clocks = &cik_set_uvd_clocks, | 2183 | .set_uvd_clocks = &cik_set_uvd_clocks, |
2184 | .set_vce_clocks = &cik_set_vce_clocks, | ||
2166 | .get_temperature = &kv_get_temp, | 2185 | .get_temperature = &kv_get_temp, |
2167 | }, | 2186 | }, |
2168 | .dpm = { | 2187 | .dpm = { |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index ae637cfda783..3d55a3a39e82 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h | |||
@@ -717,6 +717,7 @@ u32 cik_get_xclk(struct radeon_device *rdev); | |||
717 | uint32_t cik_pciep_rreg(struct radeon_device *rdev, uint32_t reg); | 717 | uint32_t cik_pciep_rreg(struct radeon_device *rdev, uint32_t reg); |
718 | void cik_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); | 718 | void cik_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); |
719 | int cik_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk); | 719 | int cik_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk); |
720 | int cik_set_vce_clocks(struct radeon_device *rdev, u32 evclk, u32 ecclk); | ||
720 | void cik_sdma_fence_ring_emit(struct radeon_device *rdev, | 721 | void cik_sdma_fence_ring_emit(struct radeon_device *rdev, |
721 | struct radeon_fence *fence); | 722 | struct radeon_fence *fence); |
722 | bool cik_sdma_semaphore_ring_emit(struct radeon_device *rdev, | 723 | bool cik_sdma_semaphore_ring_emit(struct radeon_device *rdev, |
@@ -863,4 +864,17 @@ bool uvd_v3_1_semaphore_emit(struct radeon_device *rdev, | |||
863 | /* uvd v4.2 */ | 864 | /* uvd v4.2 */ |
864 | int uvd_v4_2_resume(struct radeon_device *rdev); | 865 | int uvd_v4_2_resume(struct radeon_device *rdev); |
865 | 866 | ||
867 | /* vce v1.0 */ | ||
868 | uint32_t vce_v1_0_get_rptr(struct radeon_device *rdev, | ||
869 | struct radeon_ring *ring); | ||
870 | uint32_t vce_v1_0_get_wptr(struct radeon_device *rdev, | ||
871 | struct radeon_ring *ring); | ||
872 | void vce_v1_0_set_wptr(struct radeon_device *rdev, | ||
873 | struct radeon_ring *ring); | ||
874 | int vce_v1_0_init(struct radeon_device *rdev); | ||
875 | int vce_v1_0_start(struct radeon_device *rdev); | ||
876 | |||
877 | /* vce v2.0 */ | ||
878 | int vce_v2_0_resume(struct radeon_device *rdev); | ||
879 | |||
866 | #endif | 880 | #endif |
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index dfb5a1db87d4..f28a8d82fa19 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c | |||
@@ -147,6 +147,10 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority | |||
147 | case RADEON_CS_RING_UVD: | 147 | case RADEON_CS_RING_UVD: |
148 | p->ring = R600_RING_TYPE_UVD_INDEX; | 148 | p->ring = R600_RING_TYPE_UVD_INDEX; |
149 | break; | 149 | break; |
150 | case RADEON_CS_RING_VCE: | ||
151 | /* TODO: only use the low priority ring for now */ | ||
152 | p->ring = TN_RING_TYPE_VCE1_INDEX; | ||
153 | break; | ||
150 | } | 154 | } |
151 | return 0; | 155 | return 0; |
152 | } | 156 | } |
@@ -343,6 +347,9 @@ static int radeon_cs_ib_chunk(struct radeon_device *rdev, | |||
343 | 347 | ||
344 | if (parser->ring == R600_RING_TYPE_UVD_INDEX) | 348 | if (parser->ring == R600_RING_TYPE_UVD_INDEX) |
345 | radeon_uvd_note_usage(rdev); | 349 | radeon_uvd_note_usage(rdev); |
350 | else if ((parser->ring == TN_RING_TYPE_VCE1_INDEX) || | ||
351 | (parser->ring == TN_RING_TYPE_VCE2_INDEX)) | ||
352 | radeon_vce_note_usage(rdev); | ||
346 | 353 | ||
347 | radeon_cs_sync_rings(parser); | 354 | radeon_cs_sync_rings(parser); |
348 | r = radeon_ib_schedule(rdev, &parser->ib, NULL); | 355 | r = radeon_ib_schedule(rdev, &parser->ib, NULL); |
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 114d1672d616..baff98be65b1 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c | |||
@@ -433,6 +433,9 @@ static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file | |||
433 | case RADEON_CS_RING_UVD: | 433 | case RADEON_CS_RING_UVD: |
434 | *value = rdev->ring[R600_RING_TYPE_UVD_INDEX].ready; | 434 | *value = rdev->ring[R600_RING_TYPE_UVD_INDEX].ready; |
435 | break; | 435 | break; |
436 | case RADEON_CS_RING_VCE: | ||
437 | *value = rdev->ring[TN_RING_TYPE_VCE1_INDEX].ready; | ||
438 | break; | ||
436 | default: | 439 | default: |
437 | return -EINVAL; | 440 | return -EINVAL; |
438 | } | 441 | } |
@@ -477,6 +480,12 @@ static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file | |||
477 | else | 480 | else |
478 | *value = rdev->pm.default_sclk * 10; | 481 | *value = rdev->pm.default_sclk * 10; |
479 | break; | 482 | break; |
483 | case RADEON_INFO_VCE_FW_VERSION: | ||
484 | *value = rdev->vce.fw_version; | ||
485 | break; | ||
486 | case RADEON_INFO_VCE_FB_VERSION: | ||
487 | *value = rdev->vce.fb_version; | ||
488 | break; | ||
480 | default: | 489 | default: |
481 | DRM_DEBUG_KMS("Invalid request %d\n", info->request); | 490 | DRM_DEBUG_KMS("Invalid request %d\n", info->request); |
482 | return -EINVAL; | 491 | return -EINVAL; |
@@ -610,6 +619,7 @@ void radeon_driver_preclose_kms(struct drm_device *dev, | |||
610 | if (rdev->cmask_filp == file_priv) | 619 | if (rdev->cmask_filp == file_priv) |
611 | rdev->cmask_filp = NULL; | 620 | rdev->cmask_filp = NULL; |
612 | radeon_uvd_free_handles(rdev, file_priv); | 621 | radeon_uvd_free_handles(rdev, file_priv); |
622 | radeon_vce_free_handles(rdev, file_priv); | ||
613 | } | 623 | } |
614 | 624 | ||
615 | /* | 625 | /* |
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 8e8153e471c2..4ad9af9fc517 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
@@ -826,6 +826,9 @@ static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev) | |||
826 | 826 | ||
827 | /* no need to reprogram if nothing changed unless we are on BTC+ */ | 827 | /* no need to reprogram if nothing changed unless we are on BTC+ */ |
828 | if (rdev->pm.dpm.current_ps == rdev->pm.dpm.requested_ps) { | 828 | if (rdev->pm.dpm.current_ps == rdev->pm.dpm.requested_ps) { |
829 | /* vce just modifies an existing state so force a change */ | ||
830 | if (ps->vce_active != rdev->pm.dpm.vce_active) | ||
831 | goto force; | ||
829 | if ((rdev->family < CHIP_BARTS) || (rdev->flags & RADEON_IS_IGP)) { | 832 | if ((rdev->family < CHIP_BARTS) || (rdev->flags & RADEON_IS_IGP)) { |
830 | /* for pre-BTC and APUs if the num crtcs changed but state is the same, | 833 | /* for pre-BTC and APUs if the num crtcs changed but state is the same, |
831 | * all we need to do is update the display configuration. | 834 | * all we need to do is update the display configuration. |
@@ -862,16 +865,21 @@ static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev) | |||
862 | } | 865 | } |
863 | } | 866 | } |
864 | 867 | ||
868 | force: | ||
865 | if (radeon_dpm == 1) { | 869 | if (radeon_dpm == 1) { |
866 | printk("switching from power state:\n"); | 870 | printk("switching from power state:\n"); |
867 | radeon_dpm_print_power_state(rdev, rdev->pm.dpm.current_ps); | 871 | radeon_dpm_print_power_state(rdev, rdev->pm.dpm.current_ps); |
868 | printk("switching to power state:\n"); | 872 | printk("switching to power state:\n"); |
869 | radeon_dpm_print_power_state(rdev, rdev->pm.dpm.requested_ps); | 873 | radeon_dpm_print_power_state(rdev, rdev->pm.dpm.requested_ps); |
870 | } | 874 | } |
875 | |||
871 | mutex_lock(&rdev->ddev->struct_mutex); | 876 | mutex_lock(&rdev->ddev->struct_mutex); |
872 | down_write(&rdev->pm.mclk_lock); | 877 | down_write(&rdev->pm.mclk_lock); |
873 | mutex_lock(&rdev->ring_lock); | 878 | mutex_lock(&rdev->ring_lock); |
874 | 879 | ||
880 | /* update whether vce is active */ | ||
881 | ps->vce_active = rdev->pm.dpm.vce_active; | ||
882 | |||
875 | ret = radeon_dpm_pre_set_power_state(rdev); | 883 | ret = radeon_dpm_pre_set_power_state(rdev); |
876 | if (ret) | 884 | if (ret) |
877 | goto done; | 885 | goto done; |
@@ -960,6 +968,23 @@ void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable) | |||
960 | } | 968 | } |
961 | } | 969 | } |
962 | 970 | ||
971 | void radeon_dpm_enable_vce(struct radeon_device *rdev, bool enable) | ||
972 | { | ||
973 | if (enable) { | ||
974 | mutex_lock(&rdev->pm.mutex); | ||
975 | rdev->pm.dpm.vce_active = true; | ||
976 | /* XXX select vce level based on ring/task */ | ||
977 | rdev->pm.dpm.vce_level = RADEON_VCE_LEVEL_AC_ALL; | ||
978 | mutex_unlock(&rdev->pm.mutex); | ||
979 | } else { | ||
980 | mutex_lock(&rdev->pm.mutex); | ||
981 | rdev->pm.dpm.vce_active = false; | ||
982 | mutex_unlock(&rdev->pm.mutex); | ||
983 | } | ||
984 | |||
985 | radeon_pm_compute_clocks(rdev); | ||
986 | } | ||
987 | |||
963 | static void radeon_pm_suspend_old(struct radeon_device *rdev) | 988 | static void radeon_pm_suspend_old(struct radeon_device *rdev) |
964 | { | 989 | { |
965 | mutex_lock(&rdev->pm.mutex); | 990 | mutex_lock(&rdev->pm.mutex); |
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index 15e44a7281ab..b14c86d57607 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c | |||
@@ -342,13 +342,17 @@ bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev, | |||
342 | */ | 342 | */ |
343 | void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring) | 343 | void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring) |
344 | { | 344 | { |
345 | ring->rptr = radeon_ring_get_rptr(rdev, ring); | 345 | uint32_t rptr = radeon_ring_get_rptr(rdev, ring); |
346 | |||
346 | /* This works because ring_size is a power of 2 */ | 347 | /* This works because ring_size is a power of 2 */ |
347 | ring->ring_free_dw = (ring->rptr + (ring->ring_size / 4)); | 348 | ring->ring_free_dw = rptr + (ring->ring_size / 4); |
348 | ring->ring_free_dw -= ring->wptr; | 349 | ring->ring_free_dw -= ring->wptr; |
349 | ring->ring_free_dw &= ring->ptr_mask; | 350 | ring->ring_free_dw &= ring->ptr_mask; |
350 | if (!ring->ring_free_dw) { | 351 | if (!ring->ring_free_dw) { |
352 | /* this is an empty ring */ | ||
351 | ring->ring_free_dw = ring->ring_size / 4; | 353 | ring->ring_free_dw = ring->ring_size / 4; |
354 | /* update lockup info to avoid false positive */ | ||
355 | radeon_ring_lockup_update(rdev, ring); | ||
352 | } | 356 | } |
353 | } | 357 | } |
354 | 358 | ||
@@ -372,12 +376,6 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsi | |||
372 | /* Align requested size with padding so unlock_commit can | 376 | /* Align requested size with padding so unlock_commit can |
373 | * pad safely */ | 377 | * pad safely */ |
374 | radeon_ring_free_size(rdev, ring); | 378 | radeon_ring_free_size(rdev, ring); |
375 | if (ring->ring_free_dw == (ring->ring_size / 4)) { | ||
376 | /* This is an empty ring update lockup info to avoid | ||
377 | * false positive. | ||
378 | */ | ||
379 | radeon_ring_lockup_update(ring); | ||
380 | } | ||
381 | ndw = (ndw + ring->align_mask) & ~ring->align_mask; | 379 | ndw = (ndw + ring->align_mask) & ~ring->align_mask; |
382 | while (ndw > (ring->ring_free_dw - 1)) { | 380 | while (ndw > (ring->ring_free_dw - 1)) { |
383 | radeon_ring_free_size(rdev, ring); | 381 | radeon_ring_free_size(rdev, ring); |
@@ -478,38 +476,16 @@ void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *rin | |||
478 | } | 476 | } |
479 | 477 | ||
480 | /** | 478 | /** |
481 | * radeon_ring_force_activity - add some nop packets to the ring | ||
482 | * | ||
483 | * @rdev: radeon_device pointer | ||
484 | * @ring: radeon_ring structure holding ring information | ||
485 | * | ||
486 | * Add some nop packets to the ring to force activity (all asics). | ||
487 | * Used for lockup detection to see if the rptr is advancing. | ||
488 | */ | ||
489 | void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring) | ||
490 | { | ||
491 | int r; | ||
492 | |||
493 | radeon_ring_free_size(rdev, ring); | ||
494 | if (ring->rptr == ring->wptr) { | ||
495 | r = radeon_ring_alloc(rdev, ring, 1); | ||
496 | if (!r) { | ||
497 | radeon_ring_write(ring, ring->nop); | ||
498 | radeon_ring_commit(rdev, ring); | ||
499 | } | ||
500 | } | ||
501 | } | ||
502 | |||
503 | /** | ||
504 | * radeon_ring_lockup_update - update lockup variables | 479 | * radeon_ring_lockup_update - update lockup variables |
505 | * | 480 | * |
506 | * @ring: radeon_ring structure holding ring information | 481 | * @ring: radeon_ring structure holding ring information |
507 | * | 482 | * |
508 | * Update the last rptr value and timestamp (all asics). | 483 | * Update the last rptr value and timestamp (all asics). |
509 | */ | 484 | */ |
510 | void radeon_ring_lockup_update(struct radeon_ring *ring) | 485 | void radeon_ring_lockup_update(struct radeon_device *rdev, |
486 | struct radeon_ring *ring) | ||
511 | { | 487 | { |
512 | ring->last_rptr = ring->rptr; | 488 | ring->last_rptr = radeon_ring_get_rptr(rdev, ring); |
513 | ring->last_activity = jiffies; | 489 | ring->last_activity = jiffies; |
514 | } | 490 | } |
515 | 491 | ||
@@ -518,35 +494,21 @@ void radeon_ring_lockup_update(struct radeon_ring *ring) | |||
518 | * @rdev: radeon device structure | 494 | * @rdev: radeon device structure |
519 | * @ring: radeon_ring structure holding ring information | 495 | * @ring: radeon_ring structure holding ring information |
520 | * | 496 | * |
521 | * We don't need to initialize the lockup tracking information as we will either | 497 | */ |
522 | * have CP rptr to a different value of jiffies wrap around which will force | ||
523 | * initialization of the lockup tracking informations. | ||
524 | * | ||
525 | * A possible false positivie is if we get call after while and last_cp_rptr == | ||
526 | * the current CP rptr, even if it's unlikely it might happen. To avoid this | ||
527 | * if the elapsed time since last call is bigger than 2 second than we return | ||
528 | * false and update the tracking information. Due to this the caller must call | ||
529 | * radeon_ring_test_lockup several time in less than 2sec for lockup to be reported | ||
530 | * the fencing code should be cautious about that. | ||
531 | * | ||
532 | * Caller should write to the ring to force CP to do something so we don't get | ||
533 | * false positive when CP is just gived nothing to do. | ||
534 | * | ||
535 | **/ | ||
536 | bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *ring) | 498 | bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *ring) |
537 | { | 499 | { |
500 | uint32_t rptr = radeon_ring_get_rptr(rdev, ring); | ||
538 | unsigned long cjiffies, elapsed; | 501 | unsigned long cjiffies, elapsed; |
539 | 502 | ||
540 | cjiffies = jiffies; | 503 | cjiffies = jiffies; |
541 | if (!time_after(cjiffies, ring->last_activity)) { | 504 | if (!time_after(cjiffies, ring->last_activity)) { |
542 | /* likely a wrap around */ | 505 | /* likely a wrap around */ |
543 | radeon_ring_lockup_update(ring); | 506 | radeon_ring_lockup_update(rdev, ring); |
544 | return false; | 507 | return false; |
545 | } | 508 | } |
546 | ring->rptr = radeon_ring_get_rptr(rdev, ring); | 509 | if (rptr != ring->last_rptr) { |
547 | if (ring->rptr != ring->last_rptr) { | ||
548 | /* CP is still working no lockup */ | 510 | /* CP is still working no lockup */ |
549 | radeon_ring_lockup_update(ring); | 511 | radeon_ring_lockup_update(rdev, ring); |
550 | return false; | 512 | return false; |
551 | } | 513 | } |
552 | elapsed = jiffies_to_msecs(cjiffies - ring->last_activity); | 514 | elapsed = jiffies_to_msecs(cjiffies - ring->last_activity); |
@@ -709,7 +671,7 @@ int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsig | |||
709 | if (radeon_debugfs_ring_init(rdev, ring)) { | 671 | if (radeon_debugfs_ring_init(rdev, ring)) { |
710 | DRM_ERROR("Failed to register debugfs file for rings !\n"); | 672 | DRM_ERROR("Failed to register debugfs file for rings !\n"); |
711 | } | 673 | } |
712 | radeon_ring_lockup_update(ring); | 674 | radeon_ring_lockup_update(rdev, ring); |
713 | return 0; | 675 | return 0; |
714 | } | 676 | } |
715 | 677 | ||
@@ -780,8 +742,6 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data) | |||
780 | 742 | ||
781 | seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n", | 743 | seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n", |
782 | ring->wptr, ring->wptr); | 744 | ring->wptr, ring->wptr); |
783 | seq_printf(m, "driver's copy of the rptr: 0x%08x [%5d]\n", | ||
784 | ring->rptr, ring->rptr); | ||
785 | seq_printf(m, "last semaphore signal addr : 0x%016llx\n", | 745 | seq_printf(m, "last semaphore signal addr : 0x%016llx\n", |
786 | ring->last_semaphore_signal_addr); | 746 | ring->last_semaphore_signal_addr); |
787 | seq_printf(m, "last semaphore wait addr : 0x%016llx\n", | 747 | seq_printf(m, "last semaphore wait addr : 0x%016llx\n", |
@@ -814,6 +774,8 @@ static int cayman_cp2_index = CAYMAN_RING_TYPE_CP2_INDEX; | |||
814 | static int radeon_dma1_index = R600_RING_TYPE_DMA_INDEX; | 774 | static int radeon_dma1_index = R600_RING_TYPE_DMA_INDEX; |
815 | static int radeon_dma2_index = CAYMAN_RING_TYPE_DMA1_INDEX; | 775 | static int radeon_dma2_index = CAYMAN_RING_TYPE_DMA1_INDEX; |
816 | static int r600_uvd_index = R600_RING_TYPE_UVD_INDEX; | 776 | static int r600_uvd_index = R600_RING_TYPE_UVD_INDEX; |
777 | static int si_vce1_index = TN_RING_TYPE_VCE1_INDEX; | ||
778 | static int si_vce2_index = TN_RING_TYPE_VCE2_INDEX; | ||
817 | 779 | ||
818 | static struct drm_info_list radeon_debugfs_ring_info_list[] = { | 780 | static struct drm_info_list radeon_debugfs_ring_info_list[] = { |
819 | {"radeon_ring_gfx", radeon_debugfs_ring_info, 0, &radeon_gfx_index}, | 781 | {"radeon_ring_gfx", radeon_debugfs_ring_info, 0, &radeon_gfx_index}, |
@@ -822,6 +784,8 @@ static struct drm_info_list radeon_debugfs_ring_info_list[] = { | |||
822 | {"radeon_ring_dma1", radeon_debugfs_ring_info, 0, &radeon_dma1_index}, | 784 | {"radeon_ring_dma1", radeon_debugfs_ring_info, 0, &radeon_dma1_index}, |
823 | {"radeon_ring_dma2", radeon_debugfs_ring_info, 0, &radeon_dma2_index}, | 785 | {"radeon_ring_dma2", radeon_debugfs_ring_info, 0, &radeon_dma2_index}, |
824 | {"radeon_ring_uvd", radeon_debugfs_ring_info, 0, &r600_uvd_index}, | 786 | {"radeon_ring_uvd", radeon_debugfs_ring_info, 0, &r600_uvd_index}, |
787 | {"radeon_ring_vce1", radeon_debugfs_ring_info, 0, &si_vce1_index}, | ||
788 | {"radeon_ring_vce2", radeon_debugfs_ring_info, 0, &si_vce2_index}, | ||
825 | }; | 789 | }; |
826 | 790 | ||
827 | static int radeon_debugfs_sa_info(struct seq_file *m, void *data) | 791 | static int radeon_debugfs_sa_info(struct seq_file *m, void *data) |
diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c index 12e8099a0823..3a13e0d1055c 100644 --- a/drivers/gpu/drm/radeon/radeon_test.c +++ b/drivers/gpu/drm/radeon/radeon_test.c | |||
@@ -257,20 +257,36 @@ static int radeon_test_create_and_emit_fence(struct radeon_device *rdev, | |||
257 | struct radeon_ring *ring, | 257 | struct radeon_ring *ring, |
258 | struct radeon_fence **fence) | 258 | struct radeon_fence **fence) |
259 | { | 259 | { |
260 | uint32_t handle = ring->idx ^ 0xdeafbeef; | ||
260 | int r; | 261 | int r; |
261 | 262 | ||
262 | if (ring->idx == R600_RING_TYPE_UVD_INDEX) { | 263 | if (ring->idx == R600_RING_TYPE_UVD_INDEX) { |
263 | r = radeon_uvd_get_create_msg(rdev, ring->idx, 1, NULL); | 264 | r = radeon_uvd_get_create_msg(rdev, ring->idx, handle, NULL); |
264 | if (r) { | 265 | if (r) { |
265 | DRM_ERROR("Failed to get dummy create msg\n"); | 266 | DRM_ERROR("Failed to get dummy create msg\n"); |
266 | return r; | 267 | return r; |
267 | } | 268 | } |
268 | 269 | ||
269 | r = radeon_uvd_get_destroy_msg(rdev, ring->idx, 1, fence); | 270 | r = radeon_uvd_get_destroy_msg(rdev, ring->idx, handle, fence); |
270 | if (r) { | 271 | if (r) { |
271 | DRM_ERROR("Failed to get dummy destroy msg\n"); | 272 | DRM_ERROR("Failed to get dummy destroy msg\n"); |
272 | return r; | 273 | return r; |
273 | } | 274 | } |
275 | |||
276 | } else if (ring->idx == TN_RING_TYPE_VCE1_INDEX || | ||
277 | ring->idx == TN_RING_TYPE_VCE2_INDEX) { | ||
278 | r = radeon_vce_get_create_msg(rdev, ring->idx, handle, NULL); | ||
279 | if (r) { | ||
280 | DRM_ERROR("Failed to get dummy create msg\n"); | ||
281 | return r; | ||
282 | } | ||
283 | |||
284 | r = radeon_vce_get_destroy_msg(rdev, ring->idx, handle, fence); | ||
285 | if (r) { | ||
286 | DRM_ERROR("Failed to get dummy destroy msg\n"); | ||
287 | return r; | ||
288 | } | ||
289 | |||
274 | } else { | 290 | } else { |
275 | r = radeon_ring_lock(rdev, ring, 64); | 291 | r = radeon_ring_lock(rdev, ring, 64); |
276 | if (r) { | 292 | if (r) { |
@@ -486,6 +502,16 @@ out_cleanup: | |||
486 | printk(KERN_WARNING "Error while testing ring sync (%d).\n", r); | 502 | printk(KERN_WARNING "Error while testing ring sync (%d).\n", r); |
487 | } | 503 | } |
488 | 504 | ||
505 | static bool radeon_test_sync_possible(struct radeon_ring *ringA, | ||
506 | struct radeon_ring *ringB) | ||
507 | { | ||
508 | if (ringA->idx == TN_RING_TYPE_VCE2_INDEX && | ||
509 | ringB->idx == TN_RING_TYPE_VCE1_INDEX) | ||
510 | return false; | ||
511 | |||
512 | return true; | ||
513 | } | ||
514 | |||
489 | void radeon_test_syncing(struct radeon_device *rdev) | 515 | void radeon_test_syncing(struct radeon_device *rdev) |
490 | { | 516 | { |
491 | int i, j, k; | 517 | int i, j, k; |
@@ -500,6 +526,9 @@ void radeon_test_syncing(struct radeon_device *rdev) | |||
500 | if (!ringB->ready) | 526 | if (!ringB->ready) |
501 | continue; | 527 | continue; |
502 | 528 | ||
529 | if (!radeon_test_sync_possible(ringA, ringB)) | ||
530 | continue; | ||
531 | |||
503 | DRM_INFO("Testing syncing between rings %d and %d...\n", i, j); | 532 | DRM_INFO("Testing syncing between rings %d and %d...\n", i, j); |
504 | radeon_test_ring_sync(rdev, ringA, ringB); | 533 | radeon_test_ring_sync(rdev, ringA, ringB); |
505 | 534 | ||
@@ -511,6 +540,12 @@ void radeon_test_syncing(struct radeon_device *rdev) | |||
511 | if (!ringC->ready) | 540 | if (!ringC->ready) |
512 | continue; | 541 | continue; |
513 | 542 | ||
543 | if (!radeon_test_sync_possible(ringA, ringC)) | ||
544 | continue; | ||
545 | |||
546 | if (!radeon_test_sync_possible(ringB, ringC)) | ||
547 | continue; | ||
548 | |||
514 | DRM_INFO("Testing syncing between rings %d, %d and %d...\n", i, j, k); | 549 | DRM_INFO("Testing syncing between rings %d, %d and %d...\n", i, j, k); |
515 | radeon_test_ring_sync2(rdev, ringA, ringB, ringC); | 550 | radeon_test_ring_sync2(rdev, ringA, ringB, ringC); |
516 | 551 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_vce.c b/drivers/gpu/drm/radeon/radeon_vce.c new file mode 100644 index 000000000000..d130432e313a --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_vce.c | |||
@@ -0,0 +1,694 @@ | |||
1 | /* | ||
2 | * Copyright 2013 Advanced Micro Devices, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
6 | * copy of this software and associated documentation files (the | ||
7 | * "Software"), to deal in the Software without restriction, including | ||
8 | * without limitation the rights to use, copy, modify, merge, publish, | ||
9 | * distribute, sub license, and/or sell copies of the Software, and to | ||
10 | * permit persons to whom the Software is furnished to do so, subject to | ||
11 | * the following conditions: | ||
12 | * | ||
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
16 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
17 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
18 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
19 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
20 | * | ||
21 | * The above copyright notice and this permission notice (including the | ||
22 | * next paragraph) shall be included in all copies or substantial portions | ||
23 | * of the Software. | ||
24 | * | ||
25 | * Authors: Christian König <christian.koenig@amd.com> | ||
26 | */ | ||
27 | |||
28 | #include <linux/firmware.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <drm/drmP.h> | ||
31 | #include <drm/drm.h> | ||
32 | |||
33 | #include "radeon.h" | ||
34 | #include "radeon_asic.h" | ||
35 | #include "sid.h" | ||
36 | |||
37 | /* 1 second timeout */ | ||
38 | #define VCE_IDLE_TIMEOUT_MS 1000 | ||
39 | |||
40 | /* Firmware Names */ | ||
41 | #define FIRMWARE_BONAIRE "radeon/BONAIRE_vce.bin" | ||
42 | |||
43 | MODULE_FIRMWARE(FIRMWARE_BONAIRE); | ||
44 | |||
45 | static void radeon_vce_idle_work_handler(struct work_struct *work); | ||
46 | |||
47 | /** | ||
48 | * radeon_vce_init - allocate memory, load vce firmware | ||
49 | * | ||
50 | * @rdev: radeon_device pointer | ||
51 | * | ||
52 | * First step to get VCE online, allocate memory and load the firmware | ||
53 | */ | ||
54 | int radeon_vce_init(struct radeon_device *rdev) | ||
55 | { | ||
56 | static const char *fw_version = "[ATI LIB=VCEFW,"; | ||
57 | static const char *fb_version = "[ATI LIB=VCEFWSTATS,"; | ||
58 | unsigned long size; | ||
59 | const char *fw_name, *c; | ||
60 | uint8_t start, mid, end; | ||
61 | int i, r; | ||
62 | |||
63 | INIT_DELAYED_WORK(&rdev->vce.idle_work, radeon_vce_idle_work_handler); | ||
64 | |||
65 | switch (rdev->family) { | ||
66 | case CHIP_BONAIRE: | ||
67 | case CHIP_KAVERI: | ||
68 | case CHIP_KABINI: | ||
69 | fw_name = FIRMWARE_BONAIRE; | ||
70 | break; | ||
71 | |||
72 | default: | ||
73 | return -EINVAL; | ||
74 | } | ||
75 | |||
76 | r = request_firmware(&rdev->vce_fw, fw_name, rdev->dev); | ||
77 | if (r) { | ||
78 | dev_err(rdev->dev, "radeon_vce: Can't load firmware \"%s\"\n", | ||
79 | fw_name); | ||
80 | return r; | ||
81 | } | ||
82 | |||
83 | /* search for firmware version */ | ||
84 | |||
85 | size = rdev->vce_fw->size - strlen(fw_version) - 9; | ||
86 | c = rdev->vce_fw->data; | ||
87 | for (;size > 0; --size, ++c) | ||
88 | if (strncmp(c, fw_version, strlen(fw_version)) == 0) | ||
89 | break; | ||
90 | |||
91 | if (size == 0) | ||
92 | return -EINVAL; | ||
93 | |||
94 | c += strlen(fw_version); | ||
95 | if (sscanf(c, "%2hhd.%2hhd.%2hhd]", &start, &mid, &end) != 3) | ||
96 | return -EINVAL; | ||
97 | |||
98 | /* search for feedback version */ | ||
99 | |||
100 | size = rdev->vce_fw->size - strlen(fb_version) - 3; | ||
101 | c = rdev->vce_fw->data; | ||
102 | for (;size > 0; --size, ++c) | ||
103 | if (strncmp(c, fb_version, strlen(fb_version)) == 0) | ||
104 | break; | ||
105 | |||
106 | if (size == 0) | ||
107 | return -EINVAL; | ||
108 | |||
109 | c += strlen(fb_version); | ||
110 | if (sscanf(c, "%2u]", &rdev->vce.fb_version) != 1) | ||
111 | return -EINVAL; | ||
112 | |||
113 | DRM_INFO("Found VCE firmware/feedback version %hhd.%hhd.%hhd / %d!\n", | ||
114 | start, mid, end, rdev->vce.fb_version); | ||
115 | |||
116 | rdev->vce.fw_version = (start << 24) | (mid << 16) | (end << 8); | ||
117 | |||
118 | /* we can only work with this fw version for now */ | ||
119 | if (rdev->vce.fw_version != ((40 << 24) | (2 << 16) | (2 << 8))) | ||
120 | return -EINVAL; | ||
121 | |||
122 | /* load firmware into VRAM */ | ||
123 | |||
124 | size = RADEON_GPU_PAGE_ALIGN(rdev->vce_fw->size) + | ||
125 | RADEON_VCE_STACK_SIZE + RADEON_VCE_HEAP_SIZE; | ||
126 | r = radeon_bo_create(rdev, size, PAGE_SIZE, true, | ||
127 | RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->vce.vcpu_bo); | ||
128 | if (r) { | ||
129 | dev_err(rdev->dev, "(%d) failed to allocate VCE bo\n", r); | ||
130 | return r; | ||
131 | } | ||
132 | |||
133 | r = radeon_vce_resume(rdev); | ||
134 | if (r) | ||
135 | return r; | ||
136 | |||
137 | memset(rdev->vce.cpu_addr, 0, size); | ||
138 | memcpy(rdev->vce.cpu_addr, rdev->vce_fw->data, rdev->vce_fw->size); | ||
139 | |||
140 | r = radeon_vce_suspend(rdev); | ||
141 | if (r) | ||
142 | return r; | ||
143 | |||
144 | for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) { | ||
145 | atomic_set(&rdev->vce.handles[i], 0); | ||
146 | rdev->vce.filp[i] = NULL; | ||
147 | } | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | /** | ||
153 | * radeon_vce_fini - free memory | ||
154 | * | ||
155 | * @rdev: radeon_device pointer | ||
156 | * | ||
157 | * Last step on VCE teardown, free firmware memory | ||
158 | */ | ||
159 | void radeon_vce_fini(struct radeon_device *rdev) | ||
160 | { | ||
161 | radeon_vce_suspend(rdev); | ||
162 | radeon_bo_unref(&rdev->vce.vcpu_bo); | ||
163 | } | ||
164 | |||
165 | /** | ||
166 | * radeon_vce_suspend - unpin VCE fw memory | ||
167 | * | ||
168 | * @rdev: radeon_device pointer | ||
169 | * | ||
170 | * TODO: Test VCE suspend/resume | ||
171 | */ | ||
172 | int radeon_vce_suspend(struct radeon_device *rdev) | ||
173 | { | ||
174 | int r; | ||
175 | |||
176 | if (rdev->vce.vcpu_bo == NULL) | ||
177 | return 0; | ||
178 | |||
179 | r = radeon_bo_reserve(rdev->vce.vcpu_bo, false); | ||
180 | if (!r) { | ||
181 | radeon_bo_kunmap(rdev->vce.vcpu_bo); | ||
182 | radeon_bo_unpin(rdev->vce.vcpu_bo); | ||
183 | radeon_bo_unreserve(rdev->vce.vcpu_bo); | ||
184 | } | ||
185 | return r; | ||
186 | } | ||
187 | |||
188 | /** | ||
189 | * radeon_vce_resume - pin VCE fw memory | ||
190 | * | ||
191 | * @rdev: radeon_device pointer | ||
192 | * | ||
193 | * TODO: Test VCE suspend/resume | ||
194 | */ | ||
195 | int radeon_vce_resume(struct radeon_device *rdev) | ||
196 | { | ||
197 | int r; | ||
198 | |||
199 | if (rdev->vce.vcpu_bo == NULL) | ||
200 | return -EINVAL; | ||
201 | |||
202 | r = radeon_bo_reserve(rdev->vce.vcpu_bo, false); | ||
203 | if (r) { | ||
204 | radeon_bo_unref(&rdev->vce.vcpu_bo); | ||
205 | dev_err(rdev->dev, "(%d) failed to reserve VCE bo\n", r); | ||
206 | return r; | ||
207 | } | ||
208 | |||
209 | r = radeon_bo_pin(rdev->vce.vcpu_bo, RADEON_GEM_DOMAIN_VRAM, | ||
210 | &rdev->vce.gpu_addr); | ||
211 | if (r) { | ||
212 | radeon_bo_unreserve(rdev->vce.vcpu_bo); | ||
213 | radeon_bo_unref(&rdev->vce.vcpu_bo); | ||
214 | dev_err(rdev->dev, "(%d) VCE bo pin failed\n", r); | ||
215 | return r; | ||
216 | } | ||
217 | |||
218 | r = radeon_bo_kmap(rdev->vce.vcpu_bo, &rdev->vce.cpu_addr); | ||
219 | if (r) { | ||
220 | dev_err(rdev->dev, "(%d) VCE map failed\n", r); | ||
221 | return r; | ||
222 | } | ||
223 | |||
224 | radeon_bo_unreserve(rdev->vce.vcpu_bo); | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | /** | ||
230 | * radeon_vce_idle_work_handler - power off VCE | ||
231 | * | ||
232 | * @work: pointer to work structure | ||
233 | * | ||
234 | * power of VCE when it's not used any more | ||
235 | */ | ||
236 | static void radeon_vce_idle_work_handler(struct work_struct *work) | ||
237 | { | ||
238 | struct radeon_device *rdev = | ||
239 | container_of(work, struct radeon_device, vce.idle_work.work); | ||
240 | |||
241 | if ((radeon_fence_count_emitted(rdev, TN_RING_TYPE_VCE1_INDEX) == 0) && | ||
242 | (radeon_fence_count_emitted(rdev, TN_RING_TYPE_VCE2_INDEX) == 0)) { | ||
243 | if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) { | ||
244 | radeon_dpm_enable_vce(rdev, false); | ||
245 | } else { | ||
246 | radeon_set_vce_clocks(rdev, 0, 0); | ||
247 | } | ||
248 | } else { | ||
249 | schedule_delayed_work(&rdev->vce.idle_work, | ||
250 | msecs_to_jiffies(VCE_IDLE_TIMEOUT_MS)); | ||
251 | } | ||
252 | } | ||
253 | |||
254 | /** | ||
255 | * radeon_vce_note_usage - power up VCE | ||
256 | * | ||
257 | * @rdev: radeon_device pointer | ||
258 | * | ||
259 | * Make sure VCE is powerd up when we want to use it | ||
260 | */ | ||
261 | void radeon_vce_note_usage(struct radeon_device *rdev) | ||
262 | { | ||
263 | bool streams_changed = false; | ||
264 | bool set_clocks = !cancel_delayed_work_sync(&rdev->vce.idle_work); | ||
265 | set_clocks &= schedule_delayed_work(&rdev->vce.idle_work, | ||
266 | msecs_to_jiffies(VCE_IDLE_TIMEOUT_MS)); | ||
267 | |||
268 | if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) { | ||
269 | /* XXX figure out if the streams changed */ | ||
270 | streams_changed = false; | ||
271 | } | ||
272 | |||
273 | if (set_clocks || streams_changed) { | ||
274 | if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) { | ||
275 | radeon_dpm_enable_vce(rdev, true); | ||
276 | } else { | ||
277 | radeon_set_vce_clocks(rdev, 53300, 40000); | ||
278 | } | ||
279 | } | ||
280 | } | ||
281 | |||
282 | /** | ||
283 | * radeon_vce_free_handles - free still open VCE handles | ||
284 | * | ||
285 | * @rdev: radeon_device pointer | ||
286 | * @filp: drm file pointer | ||
287 | * | ||
288 | * Close all VCE handles still open by this file pointer | ||
289 | */ | ||
290 | void radeon_vce_free_handles(struct radeon_device *rdev, struct drm_file *filp) | ||
291 | { | ||
292 | int i, r; | ||
293 | for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) { | ||
294 | uint32_t handle = atomic_read(&rdev->vce.handles[i]); | ||
295 | if (!handle || rdev->vce.filp[i] != filp) | ||
296 | continue; | ||
297 | |||
298 | radeon_vce_note_usage(rdev); | ||
299 | |||
300 | r = radeon_vce_get_destroy_msg(rdev, TN_RING_TYPE_VCE1_INDEX, | ||
301 | handle, NULL); | ||
302 | if (r) | ||
303 | DRM_ERROR("Error destroying VCE handle (%d)!\n", r); | ||
304 | |||
305 | rdev->vce.filp[i] = NULL; | ||
306 | atomic_set(&rdev->vce.handles[i], 0); | ||
307 | } | ||
308 | } | ||
309 | |||
310 | /** | ||
311 | * radeon_vce_get_create_msg - generate a VCE create msg | ||
312 | * | ||
313 | * @rdev: radeon_device pointer | ||
314 | * @ring: ring we should submit the msg to | ||
315 | * @handle: VCE session handle to use | ||
316 | * @fence: optional fence to return | ||
317 | * | ||
318 | * Open up a stream for HW test | ||
319 | */ | ||
320 | int radeon_vce_get_create_msg(struct radeon_device *rdev, int ring, | ||
321 | uint32_t handle, struct radeon_fence **fence) | ||
322 | { | ||
323 | const unsigned ib_size_dw = 1024; | ||
324 | struct radeon_ib ib; | ||
325 | uint64_t dummy; | ||
326 | int i, r; | ||
327 | |||
328 | r = radeon_ib_get(rdev, ring, &ib, NULL, ib_size_dw * 4); | ||
329 | if (r) { | ||
330 | DRM_ERROR("radeon: failed to get ib (%d).\n", r); | ||
331 | return r; | ||
332 | } | ||
333 | |||
334 | dummy = ib.gpu_addr + 1024; | ||
335 | |||
336 | /* stitch together an VCE create msg */ | ||
337 | ib.length_dw = 0; | ||
338 | ib.ptr[ib.length_dw++] = 0x0000000c; /* len */ | ||
339 | ib.ptr[ib.length_dw++] = 0x00000001; /* session cmd */ | ||
340 | ib.ptr[ib.length_dw++] = handle; | ||
341 | |||
342 | ib.ptr[ib.length_dw++] = 0x00000030; /* len */ | ||
343 | ib.ptr[ib.length_dw++] = 0x01000001; /* create cmd */ | ||
344 | ib.ptr[ib.length_dw++] = 0x00000000; | ||
345 | ib.ptr[ib.length_dw++] = 0x00000042; | ||
346 | ib.ptr[ib.length_dw++] = 0x0000000a; | ||
347 | ib.ptr[ib.length_dw++] = 0x00000001; | ||
348 | ib.ptr[ib.length_dw++] = 0x00000080; | ||
349 | ib.ptr[ib.length_dw++] = 0x00000060; | ||
350 | ib.ptr[ib.length_dw++] = 0x00000100; | ||
351 | ib.ptr[ib.length_dw++] = 0x00000100; | ||
352 | ib.ptr[ib.length_dw++] = 0x0000000c; | ||
353 | ib.ptr[ib.length_dw++] = 0x00000000; | ||
354 | |||
355 | ib.ptr[ib.length_dw++] = 0x00000014; /* len */ | ||
356 | ib.ptr[ib.length_dw++] = 0x05000005; /* feedback buffer */ | ||
357 | ib.ptr[ib.length_dw++] = upper_32_bits(dummy); | ||
358 | ib.ptr[ib.length_dw++] = dummy; | ||
359 | ib.ptr[ib.length_dw++] = 0x00000001; | ||
360 | |||
361 | for (i = ib.length_dw; i < ib_size_dw; ++i) | ||
362 | ib.ptr[i] = 0x0; | ||
363 | |||
364 | r = radeon_ib_schedule(rdev, &ib, NULL); | ||
365 | if (r) { | ||
366 | DRM_ERROR("radeon: failed to schedule ib (%d).\n", r); | ||
367 | } | ||
368 | |||
369 | if (fence) | ||
370 | *fence = radeon_fence_ref(ib.fence); | ||
371 | |||
372 | radeon_ib_free(rdev, &ib); | ||
373 | |||
374 | return r; | ||
375 | } | ||
376 | |||
377 | /** | ||
378 | * radeon_vce_get_destroy_msg - generate a VCE destroy msg | ||
379 | * | ||
380 | * @rdev: radeon_device pointer | ||
381 | * @ring: ring we should submit the msg to | ||
382 | * @handle: VCE session handle to use | ||
383 | * @fence: optional fence to return | ||
384 | * | ||
385 | * Close up a stream for HW test or if userspace failed to do so | ||
386 | */ | ||
387 | int radeon_vce_get_destroy_msg(struct radeon_device *rdev, int ring, | ||
388 | uint32_t handle, struct radeon_fence **fence) | ||
389 | { | ||
390 | const unsigned ib_size_dw = 1024; | ||
391 | struct radeon_ib ib; | ||
392 | uint64_t dummy; | ||
393 | int i, r; | ||
394 | |||
395 | r = radeon_ib_get(rdev, ring, &ib, NULL, ib_size_dw * 4); | ||
396 | if (r) { | ||
397 | DRM_ERROR("radeon: failed to get ib (%d).\n", r); | ||
398 | return r; | ||
399 | } | ||
400 | |||
401 | dummy = ib.gpu_addr + 1024; | ||
402 | |||
403 | /* stitch together an VCE destroy msg */ | ||
404 | ib.length_dw = 0; | ||
405 | ib.ptr[ib.length_dw++] = 0x0000000c; /* len */ | ||
406 | ib.ptr[ib.length_dw++] = 0x00000001; /* session cmd */ | ||
407 | ib.ptr[ib.length_dw++] = handle; | ||
408 | |||
409 | ib.ptr[ib.length_dw++] = 0x00000014; /* len */ | ||
410 | ib.ptr[ib.length_dw++] = 0x05000005; /* feedback buffer */ | ||
411 | ib.ptr[ib.length_dw++] = upper_32_bits(dummy); | ||
412 | ib.ptr[ib.length_dw++] = dummy; | ||
413 | ib.ptr[ib.length_dw++] = 0x00000001; | ||
414 | |||
415 | ib.ptr[ib.length_dw++] = 0x00000008; /* len */ | ||
416 | ib.ptr[ib.length_dw++] = 0x02000001; /* destroy cmd */ | ||
417 | |||
418 | for (i = ib.length_dw; i < ib_size_dw; ++i) | ||
419 | ib.ptr[i] = 0x0; | ||
420 | |||
421 | r = radeon_ib_schedule(rdev, &ib, NULL); | ||
422 | if (r) { | ||
423 | DRM_ERROR("radeon: failed to schedule ib (%d).\n", r); | ||
424 | } | ||
425 | |||
426 | if (fence) | ||
427 | *fence = radeon_fence_ref(ib.fence); | ||
428 | |||
429 | radeon_ib_free(rdev, &ib); | ||
430 | |||
431 | return r; | ||
432 | } | ||
433 | |||
434 | /** | ||
435 | * radeon_vce_cs_reloc - command submission relocation | ||
436 | * | ||
437 | * @p: parser context | ||
438 | * @lo: address of lower dword | ||
439 | * @hi: address of higher dword | ||
440 | * | ||
441 | * Patch relocation inside command stream with real buffer address | ||
442 | */ | ||
443 | int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi) | ||
444 | { | ||
445 | struct radeon_cs_chunk *relocs_chunk; | ||
446 | uint64_t offset; | ||
447 | unsigned idx; | ||
448 | |||
449 | relocs_chunk = &p->chunks[p->chunk_relocs_idx]; | ||
450 | offset = radeon_get_ib_value(p, lo); | ||
451 | idx = radeon_get_ib_value(p, hi); | ||
452 | |||
453 | if (idx >= relocs_chunk->length_dw) { | ||
454 | DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", | ||
455 | idx, relocs_chunk->length_dw); | ||
456 | return -EINVAL; | ||
457 | } | ||
458 | |||
459 | offset += p->relocs_ptr[(idx / 4)]->lobj.gpu_offset; | ||
460 | |||
461 | p->ib.ptr[lo] = offset & 0xFFFFFFFF; | ||
462 | p->ib.ptr[hi] = offset >> 32; | ||
463 | |||
464 | return 0; | ||
465 | } | ||
466 | |||
467 | /** | ||
468 | * radeon_vce_cs_parse - parse and validate the command stream | ||
469 | * | ||
470 | * @p: parser context | ||
471 | * | ||
472 | */ | ||
473 | int radeon_vce_cs_parse(struct radeon_cs_parser *p) | ||
474 | { | ||
475 | uint32_t handle = 0; | ||
476 | bool destroy = false; | ||
477 | int i, r; | ||
478 | |||
479 | while (p->idx < p->chunks[p->chunk_ib_idx].length_dw) { | ||
480 | uint32_t len = radeon_get_ib_value(p, p->idx); | ||
481 | uint32_t cmd = radeon_get_ib_value(p, p->idx + 1); | ||
482 | |||
483 | if ((len < 8) || (len & 3)) { | ||
484 | DRM_ERROR("invalid VCE command length (%d)!\n", len); | ||
485 | return -EINVAL; | ||
486 | } | ||
487 | |||
488 | switch (cmd) { | ||
489 | case 0x00000001: // session | ||
490 | handle = radeon_get_ib_value(p, p->idx + 2); | ||
491 | break; | ||
492 | |||
493 | case 0x00000002: // task info | ||
494 | case 0x01000001: // create | ||
495 | case 0x04000001: // config extension | ||
496 | case 0x04000002: // pic control | ||
497 | case 0x04000005: // rate control | ||
498 | case 0x04000007: // motion estimation | ||
499 | case 0x04000008: // rdo | ||
500 | break; | ||
501 | |||
502 | case 0x03000001: // encode | ||
503 | r = radeon_vce_cs_reloc(p, p->idx + 10, p->idx + 9); | ||
504 | if (r) | ||
505 | return r; | ||
506 | |||
507 | r = radeon_vce_cs_reloc(p, p->idx + 12, p->idx + 11); | ||
508 | if (r) | ||
509 | return r; | ||
510 | break; | ||
511 | |||
512 | case 0x02000001: // destroy | ||
513 | destroy = true; | ||
514 | break; | ||
515 | |||
516 | case 0x05000001: // context buffer | ||
517 | case 0x05000004: // video bitstream buffer | ||
518 | case 0x05000005: // feedback buffer | ||
519 | r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2); | ||
520 | if (r) | ||
521 | return r; | ||
522 | break; | ||
523 | |||
524 | default: | ||
525 | DRM_ERROR("invalid VCE command (0x%x)!\n", cmd); | ||
526 | return -EINVAL; | ||
527 | } | ||
528 | |||
529 | p->idx += len / 4; | ||
530 | } | ||
531 | |||
532 | if (destroy) { | ||
533 | /* IB contains a destroy msg, free the handle */ | ||
534 | for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) | ||
535 | atomic_cmpxchg(&p->rdev->vce.handles[i], handle, 0); | ||
536 | |||
537 | return 0; | ||
538 | } | ||
539 | |||
540 | /* create or encode, validate the handle */ | ||
541 | for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) { | ||
542 | if (atomic_read(&p->rdev->vce.handles[i]) == handle) | ||
543 | return 0; | ||
544 | } | ||
545 | |||
546 | /* handle not found try to alloc a new one */ | ||
547 | for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) { | ||
548 | if (!atomic_cmpxchg(&p->rdev->vce.handles[i], 0, handle)) { | ||
549 | p->rdev->vce.filp[i] = p->filp; | ||
550 | return 0; | ||
551 | } | ||
552 | } | ||
553 | |||
554 | DRM_ERROR("No more free VCE handles!\n"); | ||
555 | return -EINVAL; | ||
556 | } | ||
557 | |||
558 | /** | ||
559 | * radeon_vce_semaphore_emit - emit a semaphore command | ||
560 | * | ||
561 | * @rdev: radeon_device pointer | ||
562 | * @ring: engine to use | ||
563 | * @semaphore: address of semaphore | ||
564 | * @emit_wait: true=emit wait, false=emit signal | ||
565 | * | ||
566 | */ | ||
567 | bool radeon_vce_semaphore_emit(struct radeon_device *rdev, | ||
568 | struct radeon_ring *ring, | ||
569 | struct radeon_semaphore *semaphore, | ||
570 | bool emit_wait) | ||
571 | { | ||
572 | uint64_t addr = semaphore->gpu_addr; | ||
573 | |||
574 | radeon_ring_write(ring, VCE_CMD_SEMAPHORE); | ||
575 | radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF); | ||
576 | radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF); | ||
577 | radeon_ring_write(ring, 0x01003000 | (emit_wait ? 1 : 0)); | ||
578 | if (!emit_wait) | ||
579 | radeon_ring_write(ring, VCE_CMD_END); | ||
580 | |||
581 | return true; | ||
582 | } | ||
583 | |||
584 | /** | ||
585 | * radeon_vce_ib_execute - execute indirect buffer | ||
586 | * | ||
587 | * @rdev: radeon_device pointer | ||
588 | * @ib: the IB to execute | ||
589 | * | ||
590 | */ | ||
591 | void radeon_vce_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) | ||
592 | { | ||
593 | struct radeon_ring *ring = &rdev->ring[ib->ring]; | ||
594 | radeon_ring_write(ring, VCE_CMD_IB); | ||
595 | radeon_ring_write(ring, ib->gpu_addr); | ||
596 | radeon_ring_write(ring, upper_32_bits(ib->gpu_addr)); | ||
597 | radeon_ring_write(ring, ib->length_dw); | ||
598 | } | ||
599 | |||
600 | /** | ||
601 | * radeon_vce_fence_emit - add a fence command to the ring | ||
602 | * | ||
603 | * @rdev: radeon_device pointer | ||
604 | * @fence: the fence | ||
605 | * | ||
606 | */ | ||
607 | void radeon_vce_fence_emit(struct radeon_device *rdev, | ||
608 | struct radeon_fence *fence) | ||
609 | { | ||
610 | struct radeon_ring *ring = &rdev->ring[fence->ring]; | ||
611 | uint32_t addr = rdev->fence_drv[fence->ring].gpu_addr; | ||
612 | |||
613 | radeon_ring_write(ring, VCE_CMD_FENCE); | ||
614 | radeon_ring_write(ring, addr); | ||
615 | radeon_ring_write(ring, upper_32_bits(addr)); | ||
616 | radeon_ring_write(ring, fence->seq); | ||
617 | radeon_ring_write(ring, VCE_CMD_TRAP); | ||
618 | radeon_ring_write(ring, VCE_CMD_END); | ||
619 | } | ||
620 | |||
621 | /** | ||
622 | * radeon_vce_ring_test - test if VCE ring is working | ||
623 | * | ||
624 | * @rdev: radeon_device pointer | ||
625 | * @ring: the engine to test on | ||
626 | * | ||
627 | */ | ||
628 | int radeon_vce_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) | ||
629 | { | ||
630 | uint32_t rptr = vce_v1_0_get_rptr(rdev, ring); | ||
631 | unsigned i; | ||
632 | int r; | ||
633 | |||
634 | r = radeon_ring_lock(rdev, ring, 16); | ||
635 | if (r) { | ||
636 | DRM_ERROR("radeon: vce failed to lock ring %d (%d).\n", | ||
637 | ring->idx, r); | ||
638 | return r; | ||
639 | } | ||
640 | radeon_ring_write(ring, VCE_CMD_END); | ||
641 | radeon_ring_unlock_commit(rdev, ring); | ||
642 | |||
643 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
644 | if (vce_v1_0_get_rptr(rdev, ring) != rptr) | ||
645 | break; | ||
646 | DRM_UDELAY(1); | ||
647 | } | ||
648 | |||
649 | if (i < rdev->usec_timeout) { | ||
650 | DRM_INFO("ring test on %d succeeded in %d usecs\n", | ||
651 | ring->idx, i); | ||
652 | } else { | ||
653 | DRM_ERROR("radeon: ring %d test failed\n", | ||
654 | ring->idx); | ||
655 | r = -ETIMEDOUT; | ||
656 | } | ||
657 | |||
658 | return r; | ||
659 | } | ||
660 | |||
661 | /** | ||
662 | * radeon_vce_ib_test - test if VCE IBs are working | ||
663 | * | ||
664 | * @rdev: radeon_device pointer | ||
665 | * @ring: the engine to test on | ||
666 | * | ||
667 | */ | ||
668 | int radeon_vce_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) | ||
669 | { | ||
670 | struct radeon_fence *fence = NULL; | ||
671 | int r; | ||
672 | |||
673 | r = radeon_vce_get_create_msg(rdev, ring->idx, 1, NULL); | ||
674 | if (r) { | ||
675 | DRM_ERROR("radeon: failed to get create msg (%d).\n", r); | ||
676 | goto error; | ||
677 | } | ||
678 | |||
679 | r = radeon_vce_get_destroy_msg(rdev, ring->idx, 1, &fence); | ||
680 | if (r) { | ||
681 | DRM_ERROR("radeon: failed to get destroy ib (%d).\n", r); | ||
682 | goto error; | ||
683 | } | ||
684 | |||
685 | r = radeon_fence_wait(fence, false); | ||
686 | if (r) { | ||
687 | DRM_ERROR("radeon: fence wait failed (%d).\n", r); | ||
688 | } else { | ||
689 | DRM_INFO("ib test on ring %d succeeded\n", ring->idx); | ||
690 | } | ||
691 | error: | ||
692 | radeon_fence_unref(&fence); | ||
693 | return r; | ||
694 | } | ||
diff --git a/drivers/gpu/drm/radeon/rs780_dpm.c b/drivers/gpu/drm/radeon/rs780_dpm.c index 8512085b0aef..02f7710de470 100644 --- a/drivers/gpu/drm/radeon/rs780_dpm.c +++ b/drivers/gpu/drm/radeon/rs780_dpm.c | |||
@@ -807,9 +807,6 @@ static int rs780_parse_power_table(struct radeon_device *rdev) | |||
807 | power_info->pplib.ucNumStates, GFP_KERNEL); | 807 | power_info->pplib.ucNumStates, GFP_KERNEL); |
808 | if (!rdev->pm.dpm.ps) | 808 | if (!rdev->pm.dpm.ps) |
809 | return -ENOMEM; | 809 | return -ENOMEM; |
810 | rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps); | ||
811 | rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime); | ||
812 | rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime); | ||
813 | 810 | ||
814 | for (i = 0; i < power_info->pplib.ucNumStates; i++) { | 811 | for (i = 0; i < power_info->pplib.ucNumStates; i++) { |
815 | power_state = (union pplib_power_state *) | 812 | power_state = (union pplib_power_state *) |
@@ -859,6 +856,10 @@ int rs780_dpm_init(struct radeon_device *rdev) | |||
859 | return -ENOMEM; | 856 | return -ENOMEM; |
860 | rdev->pm.dpm.priv = pi; | 857 | rdev->pm.dpm.priv = pi; |
861 | 858 | ||
859 | ret = r600_get_platform_caps(rdev); | ||
860 | if (ret) | ||
861 | return ret; | ||
862 | |||
862 | ret = rs780_parse_power_table(rdev); | 863 | ret = rs780_parse_power_table(rdev); |
863 | if (ret) | 864 | if (ret) |
864 | return ret; | 865 | return ret; |
diff --git a/drivers/gpu/drm/radeon/rv6xx_dpm.c b/drivers/gpu/drm/radeon/rv6xx_dpm.c index bebf31c4d841..e7045b085715 100644 --- a/drivers/gpu/drm/radeon/rv6xx_dpm.c +++ b/drivers/gpu/drm/radeon/rv6xx_dpm.c | |||
@@ -1891,9 +1891,6 @@ static int rv6xx_parse_power_table(struct radeon_device *rdev) | |||
1891 | power_info->pplib.ucNumStates, GFP_KERNEL); | 1891 | power_info->pplib.ucNumStates, GFP_KERNEL); |
1892 | if (!rdev->pm.dpm.ps) | 1892 | if (!rdev->pm.dpm.ps) |
1893 | return -ENOMEM; | 1893 | return -ENOMEM; |
1894 | rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps); | ||
1895 | rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime); | ||
1896 | rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime); | ||
1897 | 1894 | ||
1898 | for (i = 0; i < power_info->pplib.ucNumStates; i++) { | 1895 | for (i = 0; i < power_info->pplib.ucNumStates; i++) { |
1899 | power_state = (union pplib_power_state *) | 1896 | power_state = (union pplib_power_state *) |
@@ -1943,6 +1940,10 @@ int rv6xx_dpm_init(struct radeon_device *rdev) | |||
1943 | return -ENOMEM; | 1940 | return -ENOMEM; |
1944 | rdev->pm.dpm.priv = pi; | 1941 | rdev->pm.dpm.priv = pi; |
1945 | 1942 | ||
1943 | ret = r600_get_platform_caps(rdev); | ||
1944 | if (ret) | ||
1945 | return ret; | ||
1946 | |||
1946 | ret = rv6xx_parse_power_table(rdev); | 1947 | ret = rv6xx_parse_power_table(rdev); |
1947 | if (ret) | 1948 | if (ret) |
1948 | return ret; | 1949 | return ret; |
diff --git a/drivers/gpu/drm/radeon/rv770_dpm.c b/drivers/gpu/drm/radeon/rv770_dpm.c index b5f63f5e22a3..da041a43d82e 100644 --- a/drivers/gpu/drm/radeon/rv770_dpm.c +++ b/drivers/gpu/drm/radeon/rv770_dpm.c | |||
@@ -2281,9 +2281,6 @@ int rv7xx_parse_power_table(struct radeon_device *rdev) | |||
2281 | power_info->pplib.ucNumStates, GFP_KERNEL); | 2281 | power_info->pplib.ucNumStates, GFP_KERNEL); |
2282 | if (!rdev->pm.dpm.ps) | 2282 | if (!rdev->pm.dpm.ps) |
2283 | return -ENOMEM; | 2283 | return -ENOMEM; |
2284 | rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps); | ||
2285 | rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime); | ||
2286 | rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime); | ||
2287 | 2284 | ||
2288 | for (i = 0; i < power_info->pplib.ucNumStates; i++) { | 2285 | for (i = 0; i < power_info->pplib.ucNumStates; i++) { |
2289 | power_state = (union pplib_power_state *) | 2286 | power_state = (union pplib_power_state *) |
@@ -2361,6 +2358,10 @@ int rv770_dpm_init(struct radeon_device *rdev) | |||
2361 | pi->min_vddc_in_table = 0; | 2358 | pi->min_vddc_in_table = 0; |
2362 | pi->max_vddc_in_table = 0; | 2359 | pi->max_vddc_in_table = 0; |
2363 | 2360 | ||
2361 | ret = r600_get_platform_caps(rdev); | ||
2362 | if (ret) | ||
2363 | return ret; | ||
2364 | |||
2364 | ret = rv7xx_parse_power_table(rdev); | 2365 | ret = rv7xx_parse_power_table(rdev); |
2365 | if (ret) | 2366 | if (ret) |
2366 | return ret; | 2367 | return ret; |
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 83578324e5d1..8008cb8d5324 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
@@ -3434,8 +3434,6 @@ static int si_cp_resume(struct radeon_device *rdev) | |||
3434 | 3434 | ||
3435 | WREG32(CP_RB0_BASE, ring->gpu_addr >> 8); | 3435 | WREG32(CP_RB0_BASE, ring->gpu_addr >> 8); |
3436 | 3436 | ||
3437 | ring->rptr = RREG32(CP_RB0_RPTR); | ||
3438 | |||
3439 | /* ring1 - compute only */ | 3437 | /* ring1 - compute only */ |
3440 | /* Set ring buffer size */ | 3438 | /* Set ring buffer size */ |
3441 | ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; | 3439 | ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; |
@@ -3460,8 +3458,6 @@ static int si_cp_resume(struct radeon_device *rdev) | |||
3460 | 3458 | ||
3461 | WREG32(CP_RB1_BASE, ring->gpu_addr >> 8); | 3459 | WREG32(CP_RB1_BASE, ring->gpu_addr >> 8); |
3462 | 3460 | ||
3463 | ring->rptr = RREG32(CP_RB1_RPTR); | ||
3464 | |||
3465 | /* ring2 - compute only */ | 3461 | /* ring2 - compute only */ |
3466 | /* Set ring buffer size */ | 3462 | /* Set ring buffer size */ |
3467 | ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; | 3463 | ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; |
@@ -3486,8 +3482,6 @@ static int si_cp_resume(struct radeon_device *rdev) | |||
3486 | 3482 | ||
3487 | WREG32(CP_RB2_BASE, ring->gpu_addr >> 8); | 3483 | WREG32(CP_RB2_BASE, ring->gpu_addr >> 8); |
3488 | 3484 | ||
3489 | ring->rptr = RREG32(CP_RB2_RPTR); | ||
3490 | |||
3491 | /* start the rings */ | 3485 | /* start the rings */ |
3492 | si_cp_start(rdev); | 3486 | si_cp_start(rdev); |
3493 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = true; | 3487 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = true; |
@@ -3872,11 +3866,9 @@ bool si_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) | |||
3872 | if (!(reset_mask & (RADEON_RESET_GFX | | 3866 | if (!(reset_mask & (RADEON_RESET_GFX | |
3873 | RADEON_RESET_COMPUTE | | 3867 | RADEON_RESET_COMPUTE | |
3874 | RADEON_RESET_CP))) { | 3868 | RADEON_RESET_CP))) { |
3875 | radeon_ring_lockup_update(ring); | 3869 | radeon_ring_lockup_update(rdev, ring); |
3876 | return false; | 3870 | return false; |
3877 | } | 3871 | } |
3878 | /* force CP activities */ | ||
3879 | radeon_ring_force_activity(rdev, ring); | ||
3880 | return radeon_ring_test_lockup(rdev, ring); | 3872 | return radeon_ring_test_lockup(rdev, ring); |
3881 | } | 3873 | } |
3882 | 3874 | ||
diff --git a/drivers/gpu/drm/radeon/si_dma.c b/drivers/gpu/drm/radeon/si_dma.c index 59be2cfcbb47..cf0fdad8c278 100644 --- a/drivers/gpu/drm/radeon/si_dma.c +++ b/drivers/gpu/drm/radeon/si_dma.c | |||
@@ -49,11 +49,9 @@ bool si_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) | |||
49 | mask = RADEON_RESET_DMA1; | 49 | mask = RADEON_RESET_DMA1; |
50 | 50 | ||
51 | if (!(reset_mask & mask)) { | 51 | if (!(reset_mask & mask)) { |
52 | radeon_ring_lockup_update(ring); | 52 | radeon_ring_lockup_update(rdev, ring); |
53 | return false; | 53 | return false; |
54 | } | 54 | } |
55 | /* force ring activities */ | ||
56 | radeon_ring_force_activity(rdev, ring); | ||
57 | return radeon_ring_test_lockup(rdev, ring); | 55 | return radeon_ring_test_lockup(rdev, ring); |
58 | } | 56 | } |
59 | 57 | ||
diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index 0a2f5b4bca43..9a3567bedaae 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c | |||
@@ -6271,9 +6271,6 @@ static int si_parse_power_table(struct radeon_device *rdev) | |||
6271 | if (!rdev->pm.dpm.ps) | 6271 | if (!rdev->pm.dpm.ps) |
6272 | return -ENOMEM; | 6272 | return -ENOMEM; |
6273 | power_state_offset = (u8 *)state_array->states; | 6273 | power_state_offset = (u8 *)state_array->states; |
6274 | rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps); | ||
6275 | rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime); | ||
6276 | rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime); | ||
6277 | for (i = 0; i < state_array->ucNumEntries; i++) { | 6274 | for (i = 0; i < state_array->ucNumEntries; i++) { |
6278 | u8 *idx; | 6275 | u8 *idx; |
6279 | power_state = (union pplib_power_state *)power_state_offset; | 6276 | power_state = (union pplib_power_state *)power_state_offset; |
@@ -6350,6 +6347,10 @@ int si_dpm_init(struct radeon_device *rdev) | |||
6350 | pi->min_vddc_in_table = 0; | 6347 | pi->min_vddc_in_table = 0; |
6351 | pi->max_vddc_in_table = 0; | 6348 | pi->max_vddc_in_table = 0; |
6352 | 6349 | ||
6350 | ret = r600_get_platform_caps(rdev); | ||
6351 | if (ret) | ||
6352 | return ret; | ||
6353 | |||
6353 | ret = si_parse_power_table(rdev); | 6354 | ret = si_parse_power_table(rdev); |
6354 | if (ret) | 6355 | if (ret) |
6355 | return ret; | 6356 | return ret; |
diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 9239a6d29128..683532f84931 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h | |||
@@ -1798,4 +1798,51 @@ | |||
1798 | #define DMA_PACKET_CONSTANT_FILL 0xd | 1798 | #define DMA_PACKET_CONSTANT_FILL 0xd |
1799 | #define DMA_PACKET_NOP 0xf | 1799 | #define DMA_PACKET_NOP 0xf |
1800 | 1800 | ||
1801 | #define VCE_STATUS 0x20004 | ||
1802 | #define VCE_VCPU_CNTL 0x20014 | ||
1803 | #define VCE_CLK_EN (1 << 0) | ||
1804 | #define VCE_VCPU_CACHE_OFFSET0 0x20024 | ||
1805 | #define VCE_VCPU_CACHE_SIZE0 0x20028 | ||
1806 | #define VCE_VCPU_CACHE_OFFSET1 0x2002c | ||
1807 | #define VCE_VCPU_CACHE_SIZE1 0x20030 | ||
1808 | #define VCE_VCPU_CACHE_OFFSET2 0x20034 | ||
1809 | #define VCE_VCPU_CACHE_SIZE2 0x20038 | ||
1810 | #define VCE_SOFT_RESET 0x20120 | ||
1811 | #define VCE_ECPU_SOFT_RESET (1 << 0) | ||
1812 | #define VCE_FME_SOFT_RESET (1 << 2) | ||
1813 | #define VCE_RB_BASE_LO2 0x2016c | ||
1814 | #define VCE_RB_BASE_HI2 0x20170 | ||
1815 | #define VCE_RB_SIZE2 0x20174 | ||
1816 | #define VCE_RB_RPTR2 0x20178 | ||
1817 | #define VCE_RB_WPTR2 0x2017c | ||
1818 | #define VCE_RB_BASE_LO 0x20180 | ||
1819 | #define VCE_RB_BASE_HI 0x20184 | ||
1820 | #define VCE_RB_SIZE 0x20188 | ||
1821 | #define VCE_RB_RPTR 0x2018c | ||
1822 | #define VCE_RB_WPTR 0x20190 | ||
1823 | #define VCE_CLOCK_GATING_A 0x202f8 | ||
1824 | #define VCE_CLOCK_GATING_B 0x202fc | ||
1825 | #define VCE_UENC_CLOCK_GATING 0x205bc | ||
1826 | #define VCE_UENC_REG_CLOCK_GATING 0x205c0 | ||
1827 | #define VCE_FW_REG_STATUS 0x20e10 | ||
1828 | # define VCE_FW_REG_STATUS_BUSY (1 << 0) | ||
1829 | # define VCE_FW_REG_STATUS_PASS (1 << 3) | ||
1830 | # define VCE_FW_REG_STATUS_DONE (1 << 11) | ||
1831 | #define VCE_LMI_FW_START_KEYSEL 0x20e18 | ||
1832 | #define VCE_LMI_FW_PERIODIC_CTRL 0x20e20 | ||
1833 | #define VCE_LMI_CTRL2 0x20e74 | ||
1834 | #define VCE_LMI_CTRL 0x20e98 | ||
1835 | #define VCE_LMI_VM_CTRL 0x20ea0 | ||
1836 | #define VCE_LMI_SWAP_CNTL 0x20eb4 | ||
1837 | #define VCE_LMI_SWAP_CNTL1 0x20eb8 | ||
1838 | #define VCE_LMI_CACHE_CTRL 0x20ef4 | ||
1839 | |||
1840 | #define VCE_CMD_NO_OP 0x00000000 | ||
1841 | #define VCE_CMD_END 0x00000001 | ||
1842 | #define VCE_CMD_IB 0x00000002 | ||
1843 | #define VCE_CMD_FENCE 0x00000003 | ||
1844 | #define VCE_CMD_TRAP 0x00000004 | ||
1845 | #define VCE_CMD_IB_AUTO 0x00000005 | ||
1846 | #define VCE_CMD_SEMAPHORE 0x00000006 | ||
1847 | |||
1801 | #endif | 1848 | #endif |
diff --git a/drivers/gpu/drm/radeon/sumo_dpm.c b/drivers/gpu/drm/radeon/sumo_dpm.c index 8b47b3cd0357..3f0e8d7b8dbe 100644 --- a/drivers/gpu/drm/radeon/sumo_dpm.c +++ b/drivers/gpu/drm/radeon/sumo_dpm.c | |||
@@ -1484,9 +1484,6 @@ static int sumo_parse_power_table(struct radeon_device *rdev) | |||
1484 | if (!rdev->pm.dpm.ps) | 1484 | if (!rdev->pm.dpm.ps) |
1485 | return -ENOMEM; | 1485 | return -ENOMEM; |
1486 | power_state_offset = (u8 *)state_array->states; | 1486 | power_state_offset = (u8 *)state_array->states; |
1487 | rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps); | ||
1488 | rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime); | ||
1489 | rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime); | ||
1490 | for (i = 0; i < state_array->ucNumEntries; i++) { | 1487 | for (i = 0; i < state_array->ucNumEntries; i++) { |
1491 | u8 *idx; | 1488 | u8 *idx; |
1492 | power_state = (union pplib_power_state *)power_state_offset; | 1489 | power_state = (union pplib_power_state *)power_state_offset; |
@@ -1772,6 +1769,10 @@ int sumo_dpm_init(struct radeon_device *rdev) | |||
1772 | 1769 | ||
1773 | sumo_construct_boot_and_acpi_state(rdev); | 1770 | sumo_construct_boot_and_acpi_state(rdev); |
1774 | 1771 | ||
1772 | ret = r600_get_platform_caps(rdev); | ||
1773 | if (ret) | ||
1774 | return ret; | ||
1775 | |||
1775 | ret = sumo_parse_power_table(rdev); | 1776 | ret = sumo_parse_power_table(rdev); |
1776 | if (ret) | 1777 | if (ret) |
1777 | return ret; | 1778 | return ret; |
diff --git a/drivers/gpu/drm/radeon/trinity_dpm.c b/drivers/gpu/drm/radeon/trinity_dpm.c index 2da0e17eb960..2a2822c03329 100644 --- a/drivers/gpu/drm/radeon/trinity_dpm.c +++ b/drivers/gpu/drm/radeon/trinity_dpm.c | |||
@@ -1694,9 +1694,6 @@ static int trinity_parse_power_table(struct radeon_device *rdev) | |||
1694 | if (!rdev->pm.dpm.ps) | 1694 | if (!rdev->pm.dpm.ps) |
1695 | return -ENOMEM; | 1695 | return -ENOMEM; |
1696 | power_state_offset = (u8 *)state_array->states; | 1696 | power_state_offset = (u8 *)state_array->states; |
1697 | rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps); | ||
1698 | rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime); | ||
1699 | rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime); | ||
1700 | for (i = 0; i < state_array->ucNumEntries; i++) { | 1697 | for (i = 0; i < state_array->ucNumEntries; i++) { |
1701 | u8 *idx; | 1698 | u8 *idx; |
1702 | power_state = (union pplib_power_state *)power_state_offset; | 1699 | power_state = (union pplib_power_state *)power_state_offset; |
@@ -1895,6 +1892,10 @@ int trinity_dpm_init(struct radeon_device *rdev) | |||
1895 | 1892 | ||
1896 | trinity_construct_boot_state(rdev); | 1893 | trinity_construct_boot_state(rdev); |
1897 | 1894 | ||
1895 | ret = r600_get_platform_caps(rdev); | ||
1896 | if (ret) | ||
1897 | return ret; | ||
1898 | |||
1898 | ret = trinity_parse_power_table(rdev); | 1899 | ret = trinity_parse_power_table(rdev); |
1899 | if (ret) | 1900 | if (ret) |
1900 | return ret; | 1901 | return ret; |
diff --git a/drivers/gpu/drm/radeon/uvd_v1_0.c b/drivers/gpu/drm/radeon/uvd_v1_0.c index d4a68af1a279..0a243f0e5d68 100644 --- a/drivers/gpu/drm/radeon/uvd_v1_0.c +++ b/drivers/gpu/drm/radeon/uvd_v1_0.c | |||
@@ -262,7 +262,7 @@ int uvd_v1_0_start(struct radeon_device *rdev) | |||
262 | /* Initialize the ring buffer's read and write pointers */ | 262 | /* Initialize the ring buffer's read and write pointers */ |
263 | WREG32(UVD_RBC_RB_RPTR, 0x0); | 263 | WREG32(UVD_RBC_RB_RPTR, 0x0); |
264 | 264 | ||
265 | ring->wptr = ring->rptr = RREG32(UVD_RBC_RB_RPTR); | 265 | ring->wptr = RREG32(UVD_RBC_RB_RPTR); |
266 | WREG32(UVD_RBC_RB_WPTR, ring->wptr); | 266 | WREG32(UVD_RBC_RB_WPTR, ring->wptr); |
267 | 267 | ||
268 | /* set the ring address */ | 268 | /* set the ring address */ |
diff --git a/drivers/gpu/drm/radeon/vce_v1_0.c b/drivers/gpu/drm/radeon/vce_v1_0.c new file mode 100644 index 000000000000..b44d9c842f7b --- /dev/null +++ b/drivers/gpu/drm/radeon/vce_v1_0.c | |||
@@ -0,0 +1,187 @@ | |||
1 | /* | ||
2 | * Copyright 2013 Advanced Micro Devices, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
6 | * copy of this software and associated documentation files (the | ||
7 | * "Software"), to deal in the Software without restriction, including | ||
8 | * without limitation the rights to use, copy, modify, merge, publish, | ||
9 | * distribute, sub license, and/or sell copies of the Software, and to | ||
10 | * permit persons to whom the Software is furnished to do so, subject to | ||
11 | * the following conditions: | ||
12 | * | ||
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
16 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
17 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
18 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
19 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
20 | * | ||
21 | * The above copyright notice and this permission notice (including the | ||
22 | * next paragraph) shall be included in all copies or substantial portions | ||
23 | * of the Software. | ||
24 | * | ||
25 | * Authors: Christian König <christian.koenig@amd.com> | ||
26 | */ | ||
27 | |||
28 | #include <linux/firmware.h> | ||
29 | #include <drm/drmP.h> | ||
30 | #include "radeon.h" | ||
31 | #include "radeon_asic.h" | ||
32 | #include "sid.h" | ||
33 | |||
34 | /** | ||
35 | * vce_v1_0_get_rptr - get read pointer | ||
36 | * | ||
37 | * @rdev: radeon_device pointer | ||
38 | * @ring: radeon_ring pointer | ||
39 | * | ||
40 | * Returns the current hardware read pointer | ||
41 | */ | ||
42 | uint32_t vce_v1_0_get_rptr(struct radeon_device *rdev, | ||
43 | struct radeon_ring *ring) | ||
44 | { | ||
45 | if (ring->idx == TN_RING_TYPE_VCE1_INDEX) | ||
46 | return RREG32(VCE_RB_RPTR); | ||
47 | else | ||
48 | return RREG32(VCE_RB_RPTR2); | ||
49 | } | ||
50 | |||
51 | /** | ||
52 | * vce_v1_0_get_wptr - get write pointer | ||
53 | * | ||
54 | * @rdev: radeon_device pointer | ||
55 | * @ring: radeon_ring pointer | ||
56 | * | ||
57 | * Returns the current hardware write pointer | ||
58 | */ | ||
59 | uint32_t vce_v1_0_get_wptr(struct radeon_device *rdev, | ||
60 | struct radeon_ring *ring) | ||
61 | { | ||
62 | if (ring->idx == TN_RING_TYPE_VCE1_INDEX) | ||
63 | return RREG32(VCE_RB_WPTR); | ||
64 | else | ||
65 | return RREG32(VCE_RB_WPTR2); | ||
66 | } | ||
67 | |||
68 | /** | ||
69 | * vce_v1_0_set_wptr - set write pointer | ||
70 | * | ||
71 | * @rdev: radeon_device pointer | ||
72 | * @ring: radeon_ring pointer | ||
73 | * | ||
74 | * Commits the write pointer to the hardware | ||
75 | */ | ||
76 | void vce_v1_0_set_wptr(struct radeon_device *rdev, | ||
77 | struct radeon_ring *ring) | ||
78 | { | ||
79 | if (ring->idx == TN_RING_TYPE_VCE1_INDEX) | ||
80 | WREG32(VCE_RB_WPTR, ring->wptr); | ||
81 | else | ||
82 | WREG32(VCE_RB_WPTR2, ring->wptr); | ||
83 | } | ||
84 | |||
85 | /** | ||
86 | * vce_v1_0_start - start VCE block | ||
87 | * | ||
88 | * @rdev: radeon_device pointer | ||
89 | * | ||
90 | * Setup and start the VCE block | ||
91 | */ | ||
92 | int vce_v1_0_start(struct radeon_device *rdev) | ||
93 | { | ||
94 | struct radeon_ring *ring; | ||
95 | int i, j, r; | ||
96 | |||
97 | /* set BUSY flag */ | ||
98 | WREG32_P(VCE_STATUS, 1, ~1); | ||
99 | |||
100 | ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX]; | ||
101 | WREG32(VCE_RB_RPTR, ring->wptr); | ||
102 | WREG32(VCE_RB_WPTR, ring->wptr); | ||
103 | WREG32(VCE_RB_BASE_LO, ring->gpu_addr); | ||
104 | WREG32(VCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); | ||
105 | WREG32(VCE_RB_SIZE, ring->ring_size / 4); | ||
106 | |||
107 | ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX]; | ||
108 | WREG32(VCE_RB_RPTR2, ring->wptr); | ||
109 | WREG32(VCE_RB_WPTR2, ring->wptr); | ||
110 | WREG32(VCE_RB_BASE_LO2, ring->gpu_addr); | ||
111 | WREG32(VCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr)); | ||
112 | WREG32(VCE_RB_SIZE2, ring->ring_size / 4); | ||
113 | |||
114 | WREG32_P(VCE_VCPU_CNTL, VCE_CLK_EN, ~VCE_CLK_EN); | ||
115 | |||
116 | WREG32_P(VCE_SOFT_RESET, | ||
117 | VCE_ECPU_SOFT_RESET | | ||
118 | VCE_FME_SOFT_RESET, ~( | ||
119 | VCE_ECPU_SOFT_RESET | | ||
120 | VCE_FME_SOFT_RESET)); | ||
121 | |||
122 | mdelay(100); | ||
123 | |||
124 | WREG32_P(VCE_SOFT_RESET, 0, ~( | ||
125 | VCE_ECPU_SOFT_RESET | | ||
126 | VCE_FME_SOFT_RESET)); | ||
127 | |||
128 | for (i = 0; i < 10; ++i) { | ||
129 | uint32_t status; | ||
130 | for (j = 0; j < 100; ++j) { | ||
131 | status = RREG32(VCE_STATUS); | ||
132 | if (status & 2) | ||
133 | break; | ||
134 | mdelay(10); | ||
135 | } | ||
136 | r = 0; | ||
137 | if (status & 2) | ||
138 | break; | ||
139 | |||
140 | DRM_ERROR("VCE not responding, trying to reset the ECPU!!!\n"); | ||
141 | WREG32_P(VCE_SOFT_RESET, VCE_ECPU_SOFT_RESET, ~VCE_ECPU_SOFT_RESET); | ||
142 | mdelay(10); | ||
143 | WREG32_P(VCE_SOFT_RESET, 0, ~VCE_ECPU_SOFT_RESET); | ||
144 | mdelay(10); | ||
145 | r = -1; | ||
146 | } | ||
147 | |||
148 | /* clear BUSY flag */ | ||
149 | WREG32_P(VCE_STATUS, 0, ~1); | ||
150 | |||
151 | if (r) { | ||
152 | DRM_ERROR("VCE not responding, giving up!!!\n"); | ||
153 | return r; | ||
154 | } | ||
155 | |||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | int vce_v1_0_init(struct radeon_device *rdev) | ||
160 | { | ||
161 | struct radeon_ring *ring; | ||
162 | int r; | ||
163 | |||
164 | r = vce_v1_0_start(rdev); | ||
165 | if (r) | ||
166 | return r; | ||
167 | |||
168 | ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX]; | ||
169 | ring->ready = true; | ||
170 | r = radeon_ring_test(rdev, TN_RING_TYPE_VCE1_INDEX, ring); | ||
171 | if (r) { | ||
172 | ring->ready = false; | ||
173 | return r; | ||
174 | } | ||
175 | |||
176 | ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX]; | ||
177 | ring->ready = true; | ||
178 | r = radeon_ring_test(rdev, TN_RING_TYPE_VCE2_INDEX, ring); | ||
179 | if (r) { | ||
180 | ring->ready = false; | ||
181 | return r; | ||
182 | } | ||
183 | |||
184 | DRM_INFO("VCE initialized successfully.\n"); | ||
185 | |||
186 | return 0; | ||
187 | } | ||
diff --git a/drivers/gpu/drm/radeon/vce_v2_0.c b/drivers/gpu/drm/radeon/vce_v2_0.c new file mode 100644 index 000000000000..1ac7bb825a1b --- /dev/null +++ b/drivers/gpu/drm/radeon/vce_v2_0.c | |||
@@ -0,0 +1,181 @@ | |||
1 | /* | ||
2 | * Copyright 2013 Advanced Micro Devices, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
6 | * copy of this software and associated documentation files (the | ||
7 | * "Software"), to deal in the Software without restriction, including | ||
8 | * without limitation the rights to use, copy, modify, merge, publish, | ||
9 | * distribute, sub license, and/or sell copies of the Software, and to | ||
10 | * permit persons to whom the Software is furnished to do so, subject to | ||
11 | * the following conditions: | ||
12 | * | ||
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
16 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
17 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
18 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
19 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
20 | * | ||
21 | * The above copyright notice and this permission notice (including the | ||
22 | * next paragraph) shall be included in all copies or substantial portions | ||
23 | * of the Software. | ||
24 | * | ||
25 | * Authors: Christian König <christian.koenig@amd.com> | ||
26 | */ | ||
27 | |||
28 | #include <linux/firmware.h> | ||
29 | #include <drm/drmP.h> | ||
30 | #include "radeon.h" | ||
31 | #include "radeon_asic.h" | ||
32 | #include "cikd.h" | ||
33 | |||
34 | static void vce_v2_0_set_sw_cg(struct radeon_device *rdev, bool gated) | ||
35 | { | ||
36 | u32 tmp; | ||
37 | |||
38 | if (gated) { | ||
39 | tmp = RREG32(VCE_CLOCK_GATING_B); | ||
40 | tmp |= 0xe70000; | ||
41 | WREG32(VCE_CLOCK_GATING_B, tmp); | ||
42 | |||
43 | tmp = RREG32(VCE_UENC_CLOCK_GATING); | ||
44 | tmp |= 0xff000000; | ||
45 | WREG32(VCE_UENC_CLOCK_GATING, tmp); | ||
46 | |||
47 | tmp = RREG32(VCE_UENC_REG_CLOCK_GATING); | ||
48 | tmp &= ~0x3fc; | ||
49 | WREG32(VCE_UENC_REG_CLOCK_GATING, tmp); | ||
50 | |||
51 | WREG32(VCE_CGTT_CLK_OVERRIDE, 0); | ||
52 | } else { | ||
53 | tmp = RREG32(VCE_CLOCK_GATING_B); | ||
54 | tmp |= 0xe7; | ||
55 | tmp &= ~0xe70000; | ||
56 | WREG32(VCE_CLOCK_GATING_B, tmp); | ||
57 | |||
58 | tmp = RREG32(VCE_UENC_CLOCK_GATING); | ||
59 | tmp |= 0x1fe000; | ||
60 | tmp &= ~0xff000000; | ||
61 | WREG32(VCE_UENC_CLOCK_GATING, tmp); | ||
62 | |||
63 | tmp = RREG32(VCE_UENC_REG_CLOCK_GATING); | ||
64 | tmp |= 0x3fc; | ||
65 | WREG32(VCE_UENC_REG_CLOCK_GATING, tmp); | ||
66 | } | ||
67 | } | ||
68 | |||
69 | static void vce_v2_0_set_dyn_cg(struct radeon_device *rdev, bool gated) | ||
70 | { | ||
71 | u32 orig, tmp; | ||
72 | |||
73 | tmp = RREG32(VCE_CLOCK_GATING_B); | ||
74 | tmp &= ~0x00060006; | ||
75 | if (gated) { | ||
76 | tmp |= 0xe10000; | ||
77 | } else { | ||
78 | tmp |= 0xe1; | ||
79 | tmp &= ~0xe10000; | ||
80 | } | ||
81 | WREG32(VCE_CLOCK_GATING_B, tmp); | ||
82 | |||
83 | orig = tmp = RREG32(VCE_UENC_CLOCK_GATING); | ||
84 | tmp &= ~0x1fe000; | ||
85 | tmp &= ~0xff000000; | ||
86 | if (tmp != orig) | ||
87 | WREG32(VCE_UENC_CLOCK_GATING, tmp); | ||
88 | |||
89 | orig = tmp = RREG32(VCE_UENC_REG_CLOCK_GATING); | ||
90 | tmp &= ~0x3fc; | ||
91 | if (tmp != orig) | ||
92 | WREG32(VCE_UENC_REG_CLOCK_GATING, tmp); | ||
93 | |||
94 | if (gated) | ||
95 | WREG32(VCE_CGTT_CLK_OVERRIDE, 0); | ||
96 | } | ||
97 | |||
98 | static void vce_v2_0_disable_cg(struct radeon_device *rdev) | ||
99 | { | ||
100 | WREG32(VCE_CGTT_CLK_OVERRIDE, 7); | ||
101 | } | ||
102 | |||
103 | void vce_v2_0_enable_mgcg(struct radeon_device *rdev, bool enable) | ||
104 | { | ||
105 | bool sw_cg = false; | ||
106 | |||
107 | if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_VCE_MGCG)) { | ||
108 | if (sw_cg) | ||
109 | vce_v2_0_set_sw_cg(rdev, true); | ||
110 | else | ||
111 | vce_v2_0_set_dyn_cg(rdev, true); | ||
112 | } else { | ||
113 | vce_v2_0_disable_cg(rdev); | ||
114 | |||
115 | if (sw_cg) | ||
116 | vce_v2_0_set_sw_cg(rdev, false); | ||
117 | else | ||
118 | vce_v2_0_set_dyn_cg(rdev, false); | ||
119 | } | ||
120 | } | ||
121 | |||
122 | static void vce_v2_0_init_cg(struct radeon_device *rdev) | ||
123 | { | ||
124 | u32 tmp; | ||
125 | |||
126 | tmp = RREG32(VCE_CLOCK_GATING_A); | ||
127 | tmp &= ~(CGC_CLK_GATE_DLY_TIMER_MASK | CGC_CLK_GATER_OFF_DLY_TIMER_MASK); | ||
128 | tmp |= (CGC_CLK_GATE_DLY_TIMER(0) | CGC_CLK_GATER_OFF_DLY_TIMER(4)); | ||
129 | tmp |= CGC_UENC_WAIT_AWAKE; | ||
130 | WREG32(VCE_CLOCK_GATING_A, tmp); | ||
131 | |||
132 | tmp = RREG32(VCE_UENC_CLOCK_GATING); | ||
133 | tmp &= ~(CLOCK_ON_DELAY_MASK | CLOCK_OFF_DELAY_MASK); | ||
134 | tmp |= (CLOCK_ON_DELAY(0) | CLOCK_OFF_DELAY(4)); | ||
135 | WREG32(VCE_UENC_CLOCK_GATING, tmp); | ||
136 | |||
137 | tmp = RREG32(VCE_CLOCK_GATING_B); | ||
138 | tmp |= 0x10; | ||
139 | tmp &= ~0x100000; | ||
140 | WREG32(VCE_CLOCK_GATING_B, tmp); | ||
141 | } | ||
142 | |||
143 | int vce_v2_0_resume(struct radeon_device *rdev) | ||
144 | { | ||
145 | uint64_t addr = rdev->vce.gpu_addr; | ||
146 | uint32_t size; | ||
147 | |||
148 | WREG32_P(VCE_CLOCK_GATING_A, 0, ~(1 << 16)); | ||
149 | WREG32_P(VCE_UENC_CLOCK_GATING, 0x1FF000, ~0xFF9FF000); | ||
150 | WREG32_P(VCE_UENC_REG_CLOCK_GATING, 0x3F, ~0x3F); | ||
151 | WREG32(VCE_CLOCK_GATING_B, 0xf7); | ||
152 | |||
153 | WREG32(VCE_LMI_CTRL, 0x00398000); | ||
154 | WREG32_P(VCE_LMI_CACHE_CTRL, 0x0, ~0x1); | ||
155 | WREG32(VCE_LMI_SWAP_CNTL, 0); | ||
156 | WREG32(VCE_LMI_SWAP_CNTL1, 0); | ||
157 | WREG32(VCE_LMI_VM_CTRL, 0); | ||
158 | |||
159 | size = RADEON_GPU_PAGE_ALIGN(rdev->vce_fw->size); | ||
160 | WREG32(VCE_VCPU_CACHE_OFFSET0, addr & 0x7fffffff); | ||
161 | WREG32(VCE_VCPU_CACHE_SIZE0, size); | ||
162 | |||
163 | addr += size; | ||
164 | size = RADEON_VCE_STACK_SIZE; | ||
165 | WREG32(VCE_VCPU_CACHE_OFFSET1, addr & 0x7fffffff); | ||
166 | WREG32(VCE_VCPU_CACHE_SIZE1, size); | ||
167 | |||
168 | addr += size; | ||
169 | size = RADEON_VCE_HEAP_SIZE; | ||
170 | WREG32(VCE_VCPU_CACHE_OFFSET2, addr & 0x7fffffff); | ||
171 | WREG32(VCE_VCPU_CACHE_SIZE2, size); | ||
172 | |||
173 | WREG32_P(VCE_LMI_CTRL2, 0x0, ~0x100); | ||
174 | |||
175 | WREG32_P(VCE_SYS_INT_EN, VCE_SYS_INT_TRAP_INTERRUPT_EN, | ||
176 | ~VCE_SYS_INT_TRAP_INTERRUPT_EN); | ||
177 | |||
178 | vce_v2_0_init_cg(rdev); | ||
179 | |||
180 | return 0; | ||
181 | } | ||
diff --git a/include/uapi/drm/radeon_drm.h b/include/uapi/drm/radeon_drm.h index d9ea3a73afe2..1cf18b4a39ec 100644 --- a/include/uapi/drm/radeon_drm.h +++ b/include/uapi/drm/radeon_drm.h | |||
@@ -919,6 +919,7 @@ struct drm_radeon_gem_va { | |||
919 | #define RADEON_CS_RING_COMPUTE 1 | 919 | #define RADEON_CS_RING_COMPUTE 1 |
920 | #define RADEON_CS_RING_DMA 2 | 920 | #define RADEON_CS_RING_DMA 2 |
921 | #define RADEON_CS_RING_UVD 3 | 921 | #define RADEON_CS_RING_UVD 3 |
922 | #define RADEON_CS_RING_VCE 4 | ||
922 | /* The third dword of RADEON_CHUNK_ID_FLAGS is a sint32 that sets the priority */ | 923 | /* The third dword of RADEON_CHUNK_ID_FLAGS is a sint32 that sets the priority */ |
923 | /* 0 = normal, + = higher priority, - = lower priority */ | 924 | /* 0 = normal, + = higher priority, - = lower priority */ |
924 | 925 | ||
@@ -987,6 +988,10 @@ struct drm_radeon_cs { | |||
987 | #define RADEON_INFO_SI_BACKEND_ENABLED_MASK 0x19 | 988 | #define RADEON_INFO_SI_BACKEND_ENABLED_MASK 0x19 |
988 | /* max engine clock - needed for OpenCL */ | 989 | /* max engine clock - needed for OpenCL */ |
989 | #define RADEON_INFO_MAX_SCLK 0x1a | 990 | #define RADEON_INFO_MAX_SCLK 0x1a |
991 | /* version of VCE firmware */ | ||
992 | #define RADEON_INFO_VCE_FW_VERSION 0x1b | ||
993 | /* version of VCE feedback */ | ||
994 | #define RADEON_INFO_VCE_FB_VERSION 0x1c | ||
990 | 995 | ||
991 | 996 | ||
992 | struct drm_radeon_info { | 997 | struct drm_radeon_info { |