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 { |
