aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2012-03-20 17:18:22 -0400
committerDave Airlie <airlied@redhat.com>2012-03-21 02:55:54 -0400
commit25a857fbe973bdcc7df0df2e0c8f9c6e1ab0e475 (patch)
tree48299c76543e234ef10ad746dc9d4e0904f472ad
parent347e7592beb0abd56a11ec16ca8aba9f60681f13 (diff)
drm/radeon/kms: add support for interrupts on SI
This is mostly identical to evergreen/ni, however there are some additional fields in the IV vector for RINGID and VMID. Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/radeon/r600.c4
-rw-r--r--drivers/gpu/drm/radeon/si.c721
-rw-r--r--drivers/gpu/drm/radeon/sid.h158
3 files changed, 881 insertions, 2 deletions
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 5eb23829353f..924b68718b82 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -2778,7 +2778,7 @@ void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size)
2778 rdev->ih.rptr = 0; 2778 rdev->ih.rptr = 0;
2779} 2779}
2780 2780
2781static int r600_ih_ring_alloc(struct radeon_device *rdev) 2781int r600_ih_ring_alloc(struct radeon_device *rdev)
2782{ 2782{
2783 int r; 2783 int r;
2784 2784
@@ -2814,7 +2814,7 @@ static int r600_ih_ring_alloc(struct radeon_device *rdev)
2814 return 0; 2814 return 0;
2815} 2815}
2816 2816
2817static void r600_ih_ring_fini(struct radeon_device *rdev) 2817void r600_ih_ring_fini(struct radeon_device *rdev)
2818{ 2818{
2819 int r; 2819 int r;
2820 if (rdev->ih.ring_obj) { 2820 if (rdev->ih.ring_obj) {
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index 4252cd0ab64b..6aecbf54cd5d 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -55,6 +55,8 @@ MODULE_FIRMWARE("radeon/VERDE_ce.bin");
55MODULE_FIRMWARE("radeon/VERDE_mc.bin"); 55MODULE_FIRMWARE("radeon/VERDE_mc.bin");
56MODULE_FIRMWARE("radeon/VERDE_rlc.bin"); 56MODULE_FIRMWARE("radeon/VERDE_rlc.bin");
57 57
58extern int r600_ih_ring_alloc(struct radeon_device *rdev);
59extern void r600_ih_ring_fini(struct radeon_device *rdev);
58extern void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev); 60extern void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev);
59extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save); 61extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save);
60extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save); 62extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save);
@@ -3072,3 +3074,722 @@ static int si_rlc_resume(struct radeon_device *rdev)
3072 return 0; 3074 return 0;
3073} 3075}
3074 3076
3077static void si_enable_interrupts(struct radeon_device *rdev)
3078{
3079 u32 ih_cntl = RREG32(IH_CNTL);
3080 u32 ih_rb_cntl = RREG32(IH_RB_CNTL);
3081
3082 ih_cntl |= ENABLE_INTR;
3083 ih_rb_cntl |= IH_RB_ENABLE;
3084 WREG32(IH_CNTL, ih_cntl);
3085 WREG32(IH_RB_CNTL, ih_rb_cntl);
3086 rdev->ih.enabled = true;
3087}
3088
3089static void si_disable_interrupts(struct radeon_device *rdev)
3090{
3091 u32 ih_rb_cntl = RREG32(IH_RB_CNTL);
3092 u32 ih_cntl = RREG32(IH_CNTL);
3093
3094 ih_rb_cntl &= ~IH_RB_ENABLE;
3095 ih_cntl &= ~ENABLE_INTR;
3096 WREG32(IH_RB_CNTL, ih_rb_cntl);
3097 WREG32(IH_CNTL, ih_cntl);
3098 /* set rptr, wptr to 0 */
3099 WREG32(IH_RB_RPTR, 0);
3100 WREG32(IH_RB_WPTR, 0);
3101 rdev->ih.enabled = false;
3102 rdev->ih.wptr = 0;
3103 rdev->ih.rptr = 0;
3104}
3105
3106static void si_disable_interrupt_state(struct radeon_device *rdev)
3107{
3108 u32 tmp;
3109
3110 WREG32(CP_INT_CNTL_RING0, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
3111 WREG32(CP_INT_CNTL_RING1, 0);
3112 WREG32(CP_INT_CNTL_RING2, 0);
3113 WREG32(GRBM_INT_CNTL, 0);
3114 WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
3115 WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
3116 if (rdev->num_crtc >= 4) {
3117 WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
3118 WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
3119 }
3120 if (rdev->num_crtc >= 6) {
3121 WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
3122 WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
3123 }
3124
3125 WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
3126 WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
3127 if (rdev->num_crtc >= 4) {
3128 WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
3129 WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
3130 }
3131 if (rdev->num_crtc >= 6) {
3132 WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
3133 WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
3134 }
3135
3136 WREG32(DACA_AUTODETECT_INT_CONTROL, 0);
3137
3138 tmp = RREG32(DC_HPD1_INT_CONTROL) & DC_HPDx_INT_POLARITY;
3139 WREG32(DC_HPD1_INT_CONTROL, tmp);
3140 tmp = RREG32(DC_HPD2_INT_CONTROL) & DC_HPDx_INT_POLARITY;
3141 WREG32(DC_HPD2_INT_CONTROL, tmp);
3142 tmp = RREG32(DC_HPD3_INT_CONTROL) & DC_HPDx_INT_POLARITY;
3143 WREG32(DC_HPD3_INT_CONTROL, tmp);
3144 tmp = RREG32(DC_HPD4_INT_CONTROL) & DC_HPDx_INT_POLARITY;
3145 WREG32(DC_HPD4_INT_CONTROL, tmp);
3146 tmp = RREG32(DC_HPD5_INT_CONTROL) & DC_HPDx_INT_POLARITY;
3147 WREG32(DC_HPD5_INT_CONTROL, tmp);
3148 tmp = RREG32(DC_HPD6_INT_CONTROL) & DC_HPDx_INT_POLARITY;
3149 WREG32(DC_HPD6_INT_CONTROL, tmp);
3150
3151}
3152
3153static int si_irq_init(struct radeon_device *rdev)
3154{
3155 int ret = 0;
3156 int rb_bufsz;
3157 u32 interrupt_cntl, ih_cntl, ih_rb_cntl;
3158
3159 /* allocate ring */
3160 ret = r600_ih_ring_alloc(rdev);
3161 if (ret)
3162 return ret;
3163
3164 /* disable irqs */
3165 si_disable_interrupts(rdev);
3166
3167 /* init rlc */
3168 ret = si_rlc_resume(rdev);
3169 if (ret) {
3170 r600_ih_ring_fini(rdev);
3171 return ret;
3172 }
3173
3174 /* setup interrupt control */
3175 /* set dummy read address to ring address */
3176 WREG32(INTERRUPT_CNTL2, rdev->ih.gpu_addr >> 8);
3177 interrupt_cntl = RREG32(INTERRUPT_CNTL);
3178 /* IH_DUMMY_RD_OVERRIDE=0 - dummy read disabled with msi, enabled without msi
3179 * IH_DUMMY_RD_OVERRIDE=1 - dummy read controlled by IH_DUMMY_RD_EN
3180 */
3181 interrupt_cntl &= ~IH_DUMMY_RD_OVERRIDE;
3182 /* IH_REQ_NONSNOOP_EN=1 if ring is in non-cacheable memory, e.g., vram */
3183 interrupt_cntl &= ~IH_REQ_NONSNOOP_EN;
3184 WREG32(INTERRUPT_CNTL, interrupt_cntl);
3185
3186 WREG32(IH_RB_BASE, rdev->ih.gpu_addr >> 8);
3187 rb_bufsz = drm_order(rdev->ih.ring_size / 4);
3188
3189 ih_rb_cntl = (IH_WPTR_OVERFLOW_ENABLE |
3190 IH_WPTR_OVERFLOW_CLEAR |
3191 (rb_bufsz << 1));
3192
3193 if (rdev->wb.enabled)
3194 ih_rb_cntl |= IH_WPTR_WRITEBACK_ENABLE;
3195
3196 /* set the writeback address whether it's enabled or not */
3197 WREG32(IH_RB_WPTR_ADDR_LO, (rdev->wb.gpu_addr + R600_WB_IH_WPTR_OFFSET) & 0xFFFFFFFC);
3198 WREG32(IH_RB_WPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + R600_WB_IH_WPTR_OFFSET) & 0xFF);
3199
3200 WREG32(IH_RB_CNTL, ih_rb_cntl);
3201
3202 /* set rptr, wptr to 0 */
3203 WREG32(IH_RB_RPTR, 0);
3204 WREG32(IH_RB_WPTR, 0);
3205
3206 /* Default settings for IH_CNTL (disabled at first) */
3207 ih_cntl = MC_WRREQ_CREDIT(0x10) | MC_WR_CLEAN_CNT(0x10) | MC_VMID(0);
3208 /* RPTR_REARM only works if msi's are enabled */
3209 if (rdev->msi_enabled)
3210 ih_cntl |= RPTR_REARM;
3211 WREG32(IH_CNTL, ih_cntl);
3212
3213 /* force the active interrupt state to all disabled */
3214 si_disable_interrupt_state(rdev);
3215
3216 /* enable irqs */
3217 si_enable_interrupts(rdev);
3218
3219 return ret;
3220}
3221
3222int si_irq_set(struct radeon_device *rdev)
3223{
3224 u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE;
3225 u32 cp_int_cntl1 = 0, cp_int_cntl2 = 0;