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 /drivers/gpu/drm/radeon | |
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>
Diffstat (limited to 'drivers/gpu/drm/radeon')
-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); | ||
3980 | return 0; | ||
3981 | } | ||
3982 | |||
3983 | /* Plan is to move initialization in that function and use | ||
3984 | * helper function so that radeon_device_init pretty much | ||
3985 | * do nothing more than calling asic specific function. This | ||
3986 | * should also allow to remove a bunch of callback function | ||
3987 | * like vram_info. | ||
3988 | */ | ||
3989 | int si_init(struct radeon_device *rdev) | ||
3990 | { | ||
3991 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | ||
3992 | int r; | ||
3993 | |||
3994 | /* This don't do much */ | ||
3995 | r = radeon_gem_init(rdev); | ||
3996 | if (r) | ||
3997 | return r; | ||
3998 | /* Read BIOS */ | ||
3999 | if (!radeon_get_bios(rdev)) { | ||
4000 | if (ASIC_IS_AVIVO(rdev)) | ||
4001 | return -EINVAL; | ||
4002 | } | ||
4003 | /* Must be an ATOMBIOS */ | ||
4004 | if (!rdev->is_atom_bios) { | ||
4005 | dev_err(rdev->dev, "Expecting atombios for cayman GPU\n"); | ||
4006 | return -EINVAL; | ||
4007 | } | ||
4008 | r = radeon_atombios_init(rdev); | ||
4009 | if (r) | ||
4010 | return r; | ||
4011 | |||
4012 | /* Post card if necessary */ | ||
4013 | if (!radeon_card_posted(rdev)) { | ||
4014 | if (!rdev->bios) { | ||
4015 | dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n"); | ||
4016 | return -EINVAL; | ||
4017 | } | ||
4018 | DRM_INFO("GPU not posted. posting now...\n"); | ||
4019 | atom_asic_init(rdev->mode_info.atom_context); | ||
4020 | } | ||
4021 | /* Initialize scratch registers */ | ||
4022 | si_scratch_init(rdev); | ||
4023 | /* Initialize surface registers */ | ||
4024 | radeon_surface_init(rdev); | ||
4025 | /* Initialize clocks */ | ||
4026 | radeon_get_clock_info(rdev->ddev); | ||
4027 | |||
4028 | /* Fence driver */ | ||
4029 | r = radeon_fence_driver_init(rdev); | ||
4030 | if (r) | ||
4031 | return r; | ||
4032 | |||
4033 | /* initialize memory controller */ | ||
4034 | r = si_mc_init(rdev); | ||
4035 | if (r) | ||
4036 | return r; | ||
4037 | /* Memory manager */ | ||
4038 | r = radeon_bo_init(rdev); | ||
4039 | if (r) | ||
4040 | return r; | ||
4041 | |||
4042 | r = radeon_irq_kms_init(rdev); | ||
4043 | if (r) | ||
4044 | return r; | ||
4045 | |||
4046 | ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | ||
4047 | ring->ring_obj = NULL; | ||
4048 | r600_ring_init(rdev, ring, 1024 * 1024); | ||
4049 | |||
4050 | ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; | ||
4051 | ring->ring_obj = NULL; | ||
4052 | r600_ring_init(rdev, ring, 1024 * 1024); | ||
4053 | |||
4054 | ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; | ||
4055 | ring->ring_obj = NULL; | ||
4056 | r600_ring_init(rdev, ring, 1024 * 1024); | ||
4057 | |||
4058 | rdev->ih.ring_obj = NULL; | ||
4059 | r600_ih_ring_init(rdev, 64 * 1024); | ||
4060 | |||
4061 | r = r600_pcie_gart_init(rdev); | ||
4062 | if (r) | ||
4063 | return r; | ||
4064 | |||
4065 | r = radeon_ib_pool_init(rdev); | ||
4066 | rdev->accel_working = true; | ||
4067 | if (r) { | ||
4068 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
4069 | rdev->accel_working = false; | ||
4070 | } | ||
4071 | r = radeon_vm_manager_init(rdev); | ||
4072 | if (r) { | ||
4073 | dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r); | ||
4074 | } | ||
4075 | |||
4076 | r = si_startup(rdev); | ||
4077 | if (r) { | ||
4078 | dev_err(rdev->dev, "disabling GPU acceleration\n"); | ||
4079 | si_cp_fini(rdev); | ||
4080 | si_irq_fini(rdev); | ||
4081 | si_rlc_fini(rdev); | ||
4082 | radeon_wb_fini(rdev); | ||
4083 | r100_ib_fini(rdev); | ||
4084 | radeon_vm_manager_fini(rdev); | ||
4085 | radeon_irq_kms_fini(rdev); | ||
4086 | si_pcie_gart_fini(rdev); | ||
4087 | rdev->accel_working = false; | ||
4088 | } | ||
4089 | |||
4090 | /* Don't start up if the MC ucode is missing. | ||
4091 | * The default clocks and voltages before the MC ucode | ||
4092 | * is loaded are not suffient for advanced operations. | ||
4093 | */ | ||
4094 | if (!rdev->mc_fw) { | ||
4095 | DRM_ERROR("radeon: MC ucode required for NI+.\n"); | ||
4096 | return -EINVAL; | ||
4097 | } | ||
4098 | |||
4099 | return 0; | ||
4100 | } | ||
4101 | |||
4102 | void si_fini(struct radeon_device *rdev) | ||
4103 | { | ||
4104 | #if 0 | ||
4105 | r600_blit_fini(rdev); | ||
4106 | #endif | ||
4107 | si_cp_fini(rdev); | ||
4108 | si_irq_fini(rdev); | ||
4109 | si_rlc_fini(rdev); | ||
4110 | radeon_wb_fini(rdev); | ||
4111 | radeon_vm_manager_fini(rdev); | ||
4112 | r100_ib_fini(rdev); | ||
4113 | radeon_irq_kms_fini(rdev); | ||
4114 | si_pcie_gart_fini(rdev); | ||
4115 | r600_vram_scratch_fini(rdev); | ||
4116 | radeon_gem_fini(rdev); | ||
4117 | radeon_semaphore_driver_fini(rdev); | ||
4118 | radeon_fence_driver_fini(rdev); | ||
4119 | radeon_bo_fini(rdev); | ||
4120 | radeon_atombios_fini(rdev); | ||
4121 | kfree(rdev->bios); | ||
4122 | rdev->bios = NULL; | ||
4123 | } | ||
4124 | |||