diff options
| author | Alex Deucher <alexander.deucher@amd.com> | 2012-03-20 17:18:23 -0400 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2012-03-21 02:55:54 -0400 |
| commit | 9b136d514e3537a41e506f5306cd92d6d142f8bb (patch) | |
| tree | 32ba495f210170d03822a97b61e4f016d6a999e3 | |
| parent | 25a857fbe973bdcc7df0df2e0c8f9c6e1ab0e475 (diff) | |
drm/radeon/kms: fill in startup/shutdown callbacks for SI
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
| -rw-r--r-- | drivers/gpu/drm/radeon/si.c | 329 |
1 files changed, 329 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 6aecbf54cd5d..4c0d8d251dd0 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
| @@ -3468,6 +3468,12 @@ static void si_irq_suspend(struct radeon_device *rdev) | |||
| 3468 | si_rlc_stop(rdev); | 3468 | si_rlc_stop(rdev); |
| 3469 | } | 3469 | } |
| 3470 | 3470 | ||
| 3471 | static void si_irq_fini(struct radeon_device *rdev) | ||
| 3472 | { | ||
| 3473 | si_irq_suspend(rdev); | ||
| 3474 | r600_ih_ring_fini(rdev); | ||
| 3475 | } | ||
| 3476 | |||
| 3471 | static inline u32 si_get_ih_wptr(struct radeon_device *rdev) | 3477 | static inline u32 si_get_ih_wptr(struct radeon_device *rdev) |
| 3472 | { | 3478 | { |
| 3473 | u32 wptr, tmp; | 3479 | u32 wptr, tmp; |
| @@ -3793,3 +3799,326 @@ restart_ih: | |||
| 3793 | return IRQ_HANDLED; | 3799 | return IRQ_HANDLED; |
| 3794 | } | 3800 | } |
| 3795 | 3801 | ||
| 3802 | /* | ||
| 3803 | * startup/shutdown callbacks | ||
| 3804 | */ | ||
| 3805 | static int si_startup(struct radeon_device *rdev) | ||
| 3806 | { | ||
| 3807 | struct radeon_ring *ring; | ||
| 3808 | int r; | ||
| 3809 | |||
| 3810 | if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw || | ||
| 3811 | !rdev->rlc_fw || !rdev->mc_fw) { | ||
| 3812 | r = si_init_microcode(rdev); | ||
| 3813 | if (r) { | ||
| 3814 | DRM_ERROR("Failed to load firmware!\n"); | ||
| 3815 | return r; | ||
| 3816 | } | ||
| 3817 | } | ||
| 3818 | |||
| 3819 | r = si_mc_load_microcode(rdev); | ||
| 3820 | if (r) { | ||
| 3821 | DRM_ERROR("Failed to load MC firmware!\n"); | ||
| 3822 | return r; | ||
| 3823 | } | ||
| 3824 | |||
| 3825 | r = r600_vram_scratch_init(rdev); | ||
| 3826 | if (r) | ||
| 3827 | return r; | ||
| 3828 | |||
| 3829 | si_mc_program(rdev); | ||
| 3830 | r = si_pcie_gart_enable(rdev); | ||
| 3831 | if (r) | ||
| 3832 | return r; | ||
| 3833 | si_gpu_init(rdev); | ||
| 3834 | |||
| 3835 | #if 0 | ||
| 3836 | r = evergreen_blit_init(rdev); | ||
| 3837 | if (r) { | ||
| 3838 | r600_blit_fini(rdev); | ||
| 3839 | rdev->asic->copy = NULL; | ||
| 3840 | dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); | ||
| 3841 | } | ||
| 3842 | #endif | ||
| 3843 | /* allocate rlc buffers */ | ||
| 3844 | r = si_rlc_init(rdev); | ||
| 3845 | if (r) { | ||
| 3846 | DRM_ERROR("Failed to init rlc BOs!\n"); | ||
| 3847 | return r; | ||
| 3848 | } | ||
| 3849 | |||
| 3850 | /* allocate wb buffer */ | ||
| 3851 | r = radeon_wb_init(rdev); | ||
| 3852 | if (r) | ||
| 3853 | return r; | ||
| 3854 | |||
| 3855 | r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); | ||
| 3856 | if (r) { | ||
| 3857 | dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); | ||
| 3858 | return r; | ||
| 3859 | } | ||
| 3860 | |||
| 3861 | r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP1_INDEX); | ||
| 3862 | if (r) { | ||
| 3863 | dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); | ||
| 3864 | return r; | ||
| 3865 | } | ||
| 3866 | |||
| 3867 | r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP2_INDEX); | ||
| 3868 | if (r) { | ||
| 3869 | dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); | ||
| 3870 | return r; | ||
| 3871 | } | ||
| 3872 | |||
| 3873 | /* Enable IRQ */ | ||
| 3874 | r = si_irq_init(rdev); | ||
| 3875 | if (r) { | ||
| 3876 | DRM_ERROR("radeon: IH init failed (%d).\n", r); | ||
| 3877 | radeon_irq_kms_fini(rdev); | ||
| 3878 | return r; | ||
| 3879 | } | ||
| 3880 | si_irq_set(rdev); | ||
| 3881 | |||
| 3882 | ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | ||
| 3883 | r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, | ||
| 3884 | CP_RB0_RPTR, CP_RB0_WPTR, | ||
| 3885 | 0, 0xfffff, RADEON_CP_PACKET2); | ||
| 3886 | if (r) | ||
| 3887 | return r; | ||
| 3888 | |||
| 3889 | ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; | ||
| 3890 | r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP1_RPTR_OFFSET, | ||
| 3891 | CP_RB1_RPTR, CP_RB1_WPTR, | ||
| 3892 | 0, 0xfffff, RADEON_CP_PACKET2); | ||
| 3893 | if (r) | ||
| 3894 | return r; | ||
| 3895 | |||
| 3896 | ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; | ||
| 3897 | r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP2_RPTR_OFFSET, | ||
| 3898 | CP_RB2_RPTR, CP_RB2_WPTR, | ||
| 3899 | 0, 0xfffff, RADEON_CP_PACKET2); | ||
| 3900 | if (r) | ||
| 3901 | return r; | ||
| 3902 | |||
| 3903 | r = si_cp_load_microcode(rdev); | ||
| 3904 | if (r) | ||
| 3905 | return r; | ||
| 3906 | r = si_cp_resume(rdev); | ||
| 3907 | if (r) | ||
| 3908 | return r; | ||
| 3909 | |||
| 3910 | r = radeon_ib_pool_start(rdev); | ||
| 3911 | if (r) | ||
| 3912 | return r; | ||
| 3913 | |||
| 3914 | r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); | ||
| 3915 | if (r) { | ||
| 3916 | DRM_ERROR("radeon: failed testing IB (%d) on CP ring 0\n", r); | ||
| 3917 | rdev->accel_working = false; | ||
| 3918 | return r; | ||
| 3919 | } | ||
| 3920 | |||
| 3921 | r = radeon_ib_test(rdev, CAYMAN_RING_TYPE_CP1_INDEX, &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]); | ||
| 3922 | if (r) { | ||
| 3923 | DRM_ERROR("radeon: failed testing IB (%d) on CP ring 1\n", r); | ||
| 3924 | rdev->accel_working = false; | ||
| 3925 | return r; | ||
| 3926 | } | ||
| 3927 | |||
| 3928 | r = radeon_ib_test(rdev, CAYMAN_RING_TYPE_CP2_INDEX, &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]); | ||
| 3929 | if (r) { | ||
| 3930 | DRM_ERROR("radeon: failed testing IB (%d) on CP ring 2\n", r); | ||
| 3931 | rdev->accel_working = false; | ||
| 3932 | return r; | ||
| 3933 | } | ||
| 3934 | |||
| 3935 | r = radeon_vm_manager_start(rdev); | ||
| 3936 | if (r) | ||
| 3937 | return r; | ||
| 3938 | |||
| 3939 | return 0; | ||
| 3940 | } | ||
| 3941 | |||
| 3942 | int si_resume(struct radeon_device *rdev) | ||
| 3943 | { | ||
| 3944 | int r; | ||
| 3945 | |||
| 3946 | /* Do not reset GPU before posting, on rv770 hw unlike on r500 hw, | ||
| 3947 | * posting will perform necessary task to bring back GPU into good | ||
| 3948 | * shape. | ||
| 3949 | */ | ||
| 3950 | /* post card */ | ||
| 3951 | atom_asic_init(rdev->mode_info.atom_context); | ||
| 3952 | |||
| 3953 | rdev->accel_working = true; | ||
| 3954 | r = si_startup(rdev); | ||
| 3955 | if (r) { | ||
| 3956 | DRM_ERROR("si startup failed on resume\n"); | ||
| 3957 | rdev->accel_working = false; | ||
| 3958 | return r; | ||
| 3959 | } | ||
| 3960 | |||
| 3961 | return r; | ||
| 3962 | |||
| 3963 | } | ||
| 3964 | |||
| 3965 | int si_suspend(struct radeon_device *rdev) | ||
| 3966 | { | ||
| 3967 | /* FIXME: we should wait for ring to be empty */ | ||
| 3968 | radeon_ib_pool_suspend(rdev); | ||
| 3969 | radeon_vm_manager_suspend(rdev); | ||
| 3970 | #if 0 | ||
| 3971 | r600_blit_suspend(rdev); | ||
| 3972 | #endif | ||
| 3973 | si_cp_enable(rdev, false); | ||
| 3974 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; | ||
| 3975 | rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false; | ||
| 3976 | rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false; | ||
| 3977 | si_irq_suspend(rdev); | ||
| 3978 | radeon_wb_disable(rdev); | ||
| 3979 | si_pcie_gart_disable(rdev); | ||
