33,6 → 33,7 |
#include <drm/radeon_drm.h> |
#include "radeon.h" |
#include "radeon_asic.h" |
#include "radeon_audio.h" |
#include "radeon_mode.h" |
#include "r600d.h" |
#include "atom.h" |
107,7 → 108,80 |
extern int evergreen_rlc_resume(struct radeon_device *rdev); |
extern void rv770_set_clk_bypass_mode(struct radeon_device *rdev); |
|
/* |
* Indirect registers accessor |
*/ |
u32 r600_rcu_rreg(struct radeon_device *rdev, u32 reg) |
{ |
unsigned long flags; |
u32 r; |
|
spin_lock_irqsave(&rdev->rcu_idx_lock, flags); |
WREG32(R600_RCU_INDEX, ((reg) & 0x1fff)); |
r = RREG32(R600_RCU_DATA); |
spin_unlock_irqrestore(&rdev->rcu_idx_lock, flags); |
return r; |
} |
|
void r600_rcu_wreg(struct radeon_device *rdev, u32 reg, u32 v) |
{ |
unsigned long flags; |
|
spin_lock_irqsave(&rdev->rcu_idx_lock, flags); |
WREG32(R600_RCU_INDEX, ((reg) & 0x1fff)); |
WREG32(R600_RCU_DATA, (v)); |
spin_unlock_irqrestore(&rdev->rcu_idx_lock, flags); |
} |
|
u32 r600_uvd_ctx_rreg(struct radeon_device *rdev, u32 reg) |
{ |
unsigned long flags; |
u32 r; |
|
spin_lock_irqsave(&rdev->uvd_idx_lock, flags); |
WREG32(R600_UVD_CTX_INDEX, ((reg) & 0x1ff)); |
r = RREG32(R600_UVD_CTX_DATA); |
spin_unlock_irqrestore(&rdev->uvd_idx_lock, flags); |
return r; |
} |
|
void r600_uvd_ctx_wreg(struct radeon_device *rdev, u32 reg, u32 v) |
{ |
unsigned long flags; |
|
spin_lock_irqsave(&rdev->uvd_idx_lock, flags); |
WREG32(R600_UVD_CTX_INDEX, ((reg) & 0x1ff)); |
WREG32(R600_UVD_CTX_DATA, (v)); |
spin_unlock_irqrestore(&rdev->uvd_idx_lock, flags); |
} |
|
/** |
* r600_get_allowed_info_register - fetch the register for the info ioctl |
* |
* @rdev: radeon_device pointer |
* @reg: register offset in bytes |
* @val: register value |
* |
* Returns 0 for success or -EINVAL for an invalid register |
* |
*/ |
int r600_get_allowed_info_register(struct radeon_device *rdev, |
u32 reg, u32 *val) |
{ |
switch (reg) { |
case GRBM_STATUS: |
case GRBM_STATUS2: |
case R_000E50_SRBM_STATUS: |
case DMA_STATUS_REG: |
case UVD_STATUS: |
*val = RREG32(reg); |
return 0; |
default: |
return -EINVAL; |
} |
} |
|
/** |
* r600_get_xclk - get the xclk |
* |
* @rdev: radeon_device pointer |
2996,6 → 3070,18 |
return r; |
} |
|
if (rdev->has_uvd) { |
r = uvd_v1_0_resume(rdev); |
if (!r) { |
r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX); |
if (r) { |
dev_err(rdev->dev, "failed initializing UVD fences (%d).\n", r); |
} |
} |
if (r) |
rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0; |
} |
|
/* Enable IRQ */ |
if (!rdev->irq.installed) { |
r = radeon_irq_kms_init(rdev); |
3006,7 → 3092,7 |
r = r600_irq_init(rdev); |
if (r) { |
DRM_ERROR("radeon: IH init failed (%d).\n", r); |
// radeon_irq_kms_fini(rdev); |
radeon_irq_kms_fini(rdev); |
return r; |
} |
r600_irq_set(rdev); |
3024,6 → 3110,18 |
if (r) |
return r; |
|
if (rdev->has_uvd) { |
ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; |
if (ring->ring_size) { |
r = radeon_ring_init(rdev, ring, ring->ring_size, 0, |
RADEON_CP_PACKET2); |
if (!r) |
r = uvd_v1_0_init(rdev); |
if (r) |
DRM_ERROR("radeon: failed initializing UVD (%d).\n", r); |
} |
} |
|
r = radeon_ib_pool_init(rdev); |
if (r) { |
dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
3124,6 → 3222,14 |
rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL; |
r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024); |
|
if (rdev->has_uvd) { |
r = radeon_uvd_init(rdev); |
if (!r) { |
rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL; |
r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX], 4096); |
} |
} |
|
rdev->ih.ring_obj = NULL; |
r600_ih_ring_init(rdev, 64 * 1024); |
|
3135,6 → 3241,11 |
r = r600_startup(rdev); |
if (r) { |
dev_err(rdev->dev, "disabling GPU acceleration\n"); |
r600_cp_fini(rdev); |
r600_irq_fini(rdev); |
radeon_wb_fini(rdev); |
radeon_ib_pool_fini(rdev); |
radeon_irq_kms_fini(rdev); |
r600_pcie_gart_fini(rdev); |
rdev->accel_working = false; |
} |
3142,6 → 3253,31 |
return 0; |
} |
|
void r600_fini(struct radeon_device *rdev) |
{ |
radeon_pm_fini(rdev); |
radeon_audio_fini(rdev); |
r600_cp_fini(rdev); |
r600_irq_fini(rdev); |
if (rdev->has_uvd) { |
uvd_v1_0_fini(rdev); |
radeon_uvd_fini(rdev); |
} |
radeon_wb_fini(rdev); |
radeon_ib_pool_fini(rdev); |
radeon_irq_kms_fini(rdev); |
r600_pcie_gart_fini(rdev); |
r600_vram_scratch_fini(rdev); |
radeon_agp_fini(rdev); |
radeon_gem_fini(rdev); |
radeon_fence_driver_fini(rdev); |
radeon_bo_fini(rdev); |
radeon_atombios_fini(rdev); |
kfree(rdev->bios); |
rdev->bios = NULL; |
} |
|
|
/* |
* CS stuff |
*/ |
3521,6 → 3657,19 |
|
return ret; |
} |
|
void r600_irq_suspend(struct radeon_device *rdev) |
{ |
r600_irq_disable(rdev); |
r600_rlc_stop(rdev); |
} |
|
void r600_irq_fini(struct radeon_device *rdev) |
{ |
r600_irq_suspend(rdev); |
r600_ih_ring_fini(rdev); |
} |
|
int r600_irq_set(struct radeon_device *rdev) |
{ |
u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE; |
3666,6 → 3815,9 |
WREG32(RV770_CG_THERMAL_INT, thermal_int); |
} |
|
/* posting read */ |
RREG32(R_000E50_SRBM_STATUS); |
|
return 0; |
} |
|
3848,8 → 4000,6 |
* Note, these are based on r600 and may need to be |
* adjusted or added to on newer asics |
*/ |
#undef DRM_DEBUG |
#define DRM_DEBUG(...) |
|
int r600_irq_process(struct radeon_device *rdev) |
{ |
3894,23 → 4044,27 |
case 1: /* D1 vblank/vline */ |
switch (src_data) { |
case 0: /* D1 vblank */ |
if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT) { |
if (!(rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT)) |
DRM_DEBUG("IH: D1 vblank - IH event w/o asserted irq bit?\n"); |
|
if (rdev->irq.crtc_vblank_int[0]) { |
// drm_handle_vblank(rdev->ddev, 0); |
drm_handle_vblank(rdev->ddev, 0); |
rdev->pm.vblank_sync = true; |
// wake_up(&rdev->irq.vblank_queue); |
wake_up(&rdev->irq.vblank_queue); |
} |
// if (rdev->irq.pflip[0]) |
// radeon_crtc_handle_flip(rdev, 0); |
if (atomic_read(&rdev->irq.pflip[0])) |
radeon_crtc_handle_vblank(rdev, 0); |
rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT; |
DRM_DEBUG("IH: D1 vblank\n"); |
} |
|
break; |
case 1: /* D1 vline */ |
if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT) { |
if (!(rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT)) |
DRM_DEBUG("IH: D1 vline - IH event w/o asserted irq bit?\n"); |
|
rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VLINE_INTERRUPT; |
DRM_DEBUG("IH: D1 vline\n"); |
} |
|
break; |
default: |
DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
3920,23 → 4074,27 |
case 5: /* D2 vblank/vline */ |
switch (src_data) { |
case 0: /* D2 vblank */ |
if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VBLANK_INTERRUPT) { |
if (!(rdev->irq.stat_regs.r600.disp_int & LB_D2_VBLANK_INTERRUPT)) |
DRM_DEBUG("IH: D2 vblank - IH event w/o asserted irq bit?\n"); |
|
if (rdev->irq.crtc_vblank_int[1]) { |
// drm_handle_vblank(rdev->ddev, 1); |
drm_handle_vblank(rdev->ddev, 1); |
rdev->pm.vblank_sync = true; |
// wake_up(&rdev->irq.vblank_queue); |
wake_up(&rdev->irq.vblank_queue); |
} |
// if (rdev->irq.pflip[1]) |
// radeon_crtc_handle_flip(rdev, 1); |
if (atomic_read(&rdev->irq.pflip[1])) |
radeon_crtc_handle_vblank(rdev, 1); |
rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT; |
DRM_DEBUG("IH: D2 vblank\n"); |
} |
|
break; |
case 1: /* D1 vline */ |
if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VLINE_INTERRUPT) { |
if (!(rdev->irq.stat_regs.r600.disp_int & LB_D2_VLINE_INTERRUPT)) |
DRM_DEBUG("IH: D2 vline - IH event w/o asserted irq bit?\n"); |
|
rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VLINE_INTERRUPT; |
DRM_DEBUG("IH: D2 vline\n"); |
} |
|
break; |
default: |
DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
3943,49 → 4101,62 |
break; |
} |
break; |
case 9: /* D1 pflip */ |
DRM_DEBUG("IH: D1 flip\n"); |
break; |
case 11: /* D2 pflip */ |
DRM_DEBUG("IH: D2 flip\n"); |
break; |
case 19: /* HPD/DAC hotplug */ |
switch (src_data) { |
case 0: |
if (rdev->irq.stat_regs.r600.disp_int & DC_HPD1_INTERRUPT) { |
if (!(rdev->irq.stat_regs.r600.disp_int & DC_HPD1_INTERRUPT)) |
DRM_DEBUG("IH: HPD1 - IH event w/o asserted irq bit?\n"); |
|
rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD1_INTERRUPT; |
queue_hotplug = true; |
DRM_DEBUG("IH: HPD1\n"); |
} |
break; |
case 1: |
if (rdev->irq.stat_regs.r600.disp_int & DC_HPD2_INTERRUPT) { |
if (!(rdev->irq.stat_regs.r600.disp_int & DC_HPD2_INTERRUPT)) |
DRM_DEBUG("IH: HPD2 - IH event w/o asserted irq bit?\n"); |
|
rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD2_INTERRUPT; |
queue_hotplug = true; |
DRM_DEBUG("IH: HPD2\n"); |
} |
break; |
case 4: |
if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD3_INTERRUPT) { |
if (!(rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD3_INTERRUPT)) |
DRM_DEBUG("IH: HPD3 - IH event w/o asserted irq bit?\n"); |
|
rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD3_INTERRUPT; |
queue_hotplug = true; |
DRM_DEBUG("IH: HPD3\n"); |
} |
break; |
case 5: |
if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD4_INTERRUPT) { |
if (!(rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD4_INTERRUPT)) |
DRM_DEBUG("IH: HPD4 - IH event w/o asserted irq bit?\n"); |
|
rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD4_INTERRUPT; |
queue_hotplug = true; |
DRM_DEBUG("IH: HPD4\n"); |
} |
break; |
case 10: |
if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD5_INTERRUPT) { |
if (!(rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD5_INTERRUPT)) |
DRM_DEBUG("IH: HPD5 - IH event w/o asserted irq bit?\n"); |
|
rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD5_INTERRUPT; |
queue_hotplug = true; |
DRM_DEBUG("IH: HPD5\n"); |
} |
break; |
case 12: |
if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT) { |
if (!(rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT)) |
DRM_DEBUG("IH: HPD6 - IH event w/o asserted irq bit?\n"); |
|
rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD6_INTERRUPT; |
queue_hotplug = true; |
DRM_DEBUG("IH: HPD6\n"); |
} |
|
break; |
default: |
DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
3995,18 → 4166,22 |
case 21: /* hdmi */ |
switch (src_data) { |
case 4: |
if (rdev->irq.stat_regs.r600.hdmi0_status & HDMI0_AZ_FORMAT_WTRIG) { |
if (!(rdev->irq.stat_regs.r600.hdmi0_status & HDMI0_AZ_FORMAT_WTRIG)) |
DRM_DEBUG("IH: HDMI0 - IH event w/o asserted irq bit?\n"); |
|
rdev->irq.stat_regs.r600.hdmi0_status &= ~HDMI0_AZ_FORMAT_WTRIG; |
queue_hdmi = true; |
DRM_DEBUG("IH: HDMI0\n"); |
} |
|
break; |
case 5: |
if (rdev->irq.stat_regs.r600.hdmi1_status & HDMI0_AZ_FORMAT_WTRIG) { |
if (!(rdev->irq.stat_regs.r600.hdmi1_status & HDMI0_AZ_FORMAT_WTRIG)) |
DRM_DEBUG("IH: HDMI1 - IH event w/o asserted irq bit?\n"); |
|
rdev->irq.stat_regs.r600.hdmi1_status &= ~HDMI0_AZ_FORMAT_WTRIG; |
queue_hdmi = true; |
DRM_DEBUG("IH: HDMI1\n"); |
} |
|
break; |
default: |
DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); |