diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/si.c')
-rw-r--r-- | drivers/gpu/drm/radeon/si.c | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 408119a810c..4252cd0ab64 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
@@ -2940,3 +2940,135 @@ void si_vm_tlb_flush(struct radeon_device *rdev, struct radeon_vm *vm) | |||
2940 | WREG32(VM_INVALIDATE_REQUEST, 1 << vm->id); | 2940 | WREG32(VM_INVALIDATE_REQUEST, 1 << vm->id); |
2941 | } | 2941 | } |
2942 | 2942 | ||
2943 | /* | ||
2944 | * RLC | ||
2945 | */ | ||
2946 | static void si_rlc_fini(struct radeon_device *rdev) | ||
2947 | { | ||
2948 | int r; | ||
2949 | |||
2950 | /* save restore block */ | ||
2951 | if (rdev->rlc.save_restore_obj) { | ||
2952 | r = radeon_bo_reserve(rdev->rlc.save_restore_obj, false); | ||
2953 | if (unlikely(r != 0)) | ||
2954 | dev_warn(rdev->dev, "(%d) reserve RLC sr bo failed\n", r); | ||
2955 | radeon_bo_unpin(rdev->rlc.save_restore_obj); | ||
2956 | radeon_bo_unreserve(rdev->rlc.save_restore_obj); | ||
2957 | |||
2958 | radeon_bo_unref(&rdev->rlc.save_restore_obj); | ||
2959 | rdev->rlc.save_restore_obj = NULL; | ||
2960 | } | ||
2961 | |||
2962 | /* clear state block */ | ||
2963 | if (rdev->rlc.clear_state_obj) { | ||
2964 | r = radeon_bo_reserve(rdev->rlc.clear_state_obj, false); | ||
2965 | if (unlikely(r != 0)) | ||
2966 | dev_warn(rdev->dev, "(%d) reserve RLC c bo failed\n", r); | ||
2967 | radeon_bo_unpin(rdev->rlc.clear_state_obj); | ||
2968 | radeon_bo_unreserve(rdev->rlc.clear_state_obj); | ||
2969 | |||
2970 | radeon_bo_unref(&rdev->rlc.clear_state_obj); | ||
2971 | rdev->rlc.clear_state_obj = NULL; | ||
2972 | } | ||
2973 | } | ||
2974 | |||
2975 | static int si_rlc_init(struct radeon_device *rdev) | ||
2976 | { | ||
2977 | int r; | ||
2978 | |||
2979 | /* save restore block */ | ||
2980 | if (rdev->rlc.save_restore_obj == NULL) { | ||
2981 | r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE, PAGE_SIZE, true, | ||
2982 | RADEON_GEM_DOMAIN_VRAM, &rdev->rlc.save_restore_obj); | ||
2983 | if (r) { | ||
2984 | dev_warn(rdev->dev, "(%d) create RLC sr bo failed\n", r); | ||
2985 | return r; | ||
2986 | } | ||
2987 | } | ||
2988 | |||
2989 | r = radeon_bo_reserve(rdev->rlc.save_restore_obj, false); | ||
2990 | if (unlikely(r != 0)) { | ||
2991 | si_rlc_fini(rdev); | ||
2992 | return r; | ||
2993 | } | ||
2994 | r = radeon_bo_pin(rdev->rlc.save_restore_obj, RADEON_GEM_DOMAIN_VRAM, | ||
2995 | &rdev->rlc.save_restore_gpu_addr); | ||
2996 | if (r) { | ||
2997 | radeon_bo_unreserve(rdev->rlc.save_restore_obj); | ||
2998 | dev_warn(rdev->dev, "(%d) pin RLC sr bo failed\n", r); | ||
2999 | si_rlc_fini(rdev); | ||
3000 | return r; | ||
3001 | } | ||
3002 | |||
3003 | /* clear state block */ | ||
3004 | if (rdev->rlc.clear_state_obj == NULL) { | ||
3005 | r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE, PAGE_SIZE, true, | ||
3006 | RADEON_GEM_DOMAIN_VRAM, &rdev->rlc.clear_state_obj); | ||
3007 | if (r) { | ||
3008 | dev_warn(rdev->dev, "(%d) create RLC c bo failed\n", r); | ||
3009 | si_rlc_fini(rdev); | ||
3010 | return r; | ||
3011 | } | ||
3012 | } | ||
3013 | r = radeon_bo_reserve(rdev->rlc.clear_state_obj, false); | ||
3014 | if (unlikely(r != 0)) { | ||
3015 | si_rlc_fini(rdev); | ||
3016 | return r; | ||
3017 | } | ||
3018 | r = radeon_bo_pin(rdev->rlc.clear_state_obj, RADEON_GEM_DOMAIN_VRAM, | ||
3019 | &rdev->rlc.clear_state_gpu_addr); | ||
3020 | if (r) { | ||
3021 | |||
3022 | radeon_bo_unreserve(rdev->rlc.clear_state_obj); | ||
3023 | dev_warn(rdev->dev, "(%d) pin RLC c bo failed\n", r); | ||
3024 | si_rlc_fini(rdev); | ||
3025 | return r; | ||
3026 | } | ||
3027 | |||
3028 | return 0; | ||
3029 | } | ||
3030 | |||
3031 | static void si_rlc_stop(struct radeon_device *rdev) | ||
3032 | { | ||
3033 | WREG32(RLC_CNTL, 0); | ||
3034 | } | ||
3035 | |||
3036 | static void si_rlc_start(struct radeon_device *rdev) | ||
3037 | { | ||
3038 | WREG32(RLC_CNTL, RLC_ENABLE); | ||
3039 | } | ||
3040 | |||
3041 | static int si_rlc_resume(struct radeon_device *rdev) | ||
3042 | { | ||
3043 | u32 i; | ||
3044 | const __be32 *fw_data; | ||
3045 | |||
3046 | if (!rdev->rlc_fw) | ||
3047 | return -EINVAL; | ||
3048 | |||
3049 | si_rlc_stop(rdev); | ||
3050 | |||
3051 | WREG32(RLC_RL_BASE, 0); | ||
3052 | WREG32(RLC_RL_SIZE, 0); | ||
3053 | WREG32(RLC_LB_CNTL, 0); | ||
3054 | WREG32(RLC_LB_CNTR_MAX, 0xffffffff); | ||
3055 | WREG32(RLC_LB_CNTR_INIT, 0); | ||
3056 | |||
3057 | WREG32(RLC_SAVE_AND_RESTORE_BASE, rdev->rlc.save_restore_gpu_addr >> 8); | ||
3058 | WREG32(RLC_CLEAR_STATE_RESTORE_BASE, rdev->rlc.clear_state_gpu_addr >> 8); | ||
3059 | |||
3060 | WREG32(RLC_MC_CNTL, 0); | ||
3061 | WREG32(RLC_UCODE_CNTL, 0); | ||
3062 | |||
3063 | fw_data = (const __be32 *)rdev->rlc_fw->data; | ||
3064 | for (i = 0; i < SI_RLC_UCODE_SIZE; i++) { | ||
3065 | WREG32(RLC_UCODE_ADDR, i); | ||
3066 | WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); | ||
3067 | } | ||
3068 | WREG32(RLC_UCODE_ADDR, 0); | ||
3069 | |||
3070 | si_rlc_start(rdev); | ||
3071 | |||
3072 | return 0; | ||
3073 | } | ||
3074 | |||