35,7 → 35,7 |
* close to the one of the R600 family (R600 likely being an evolution |
* of the RS600 GART block). |
*/ |
#include "drmP.h" |
#include <drm/drmP.h> |
#include "radeon.h" |
#include "radeon_asic.h" |
#include "atom.h" |
43,9 → 43,35 |
|
#include "rs600_reg_safe.h" |
|
void rs600_gpu_init(struct radeon_device *rdev); |
static void rs600_gpu_init(struct radeon_device *rdev); |
int rs600_mc_wait_for_idle(struct radeon_device *rdev); |
|
static const u32 crtc_offsets[2] = |
{ |
0, |
AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL |
}; |
|
void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc) |
{ |
int i; |
|
if (crtc >= rdev->num_crtc) |
return; |
|
if (RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[crtc]) & AVIVO_CRTC_EN) { |
for (i = 0; i < rdev->usec_timeout; i++) { |
if (!(RREG32(AVIVO_D1CRTC_STATUS + crtc_offsets[crtc]) & AVIVO_D1CRTC_V_BLANK)) |
break; |
udelay(1); |
} |
for (i = 0; i < rdev->usec_timeout; i++) { |
if (RREG32(AVIVO_D1CRTC_STATUS + crtc_offsets[crtc]) & AVIVO_D1CRTC_V_BLANK) |
break; |
udelay(1); |
} |
} |
} |
/* hpd for digital panel detect/disconnect */ |
bool rs600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) |
{ |
101,6 → 127,7 |
{ |
struct drm_device *dev = rdev->ddev; |
struct drm_connector *connector; |
unsigned enable = 0; |
|
list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
108,19 → 135,18 |
case RADEON_HPD_1: |
WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL, |
S_007D00_DC_HOT_PLUG_DETECT1_EN(1)); |
rdev->irq.hpd[0] = true; |
break; |
case RADEON_HPD_2: |
WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL, |
S_007D10_DC_HOT_PLUG_DETECT2_EN(1)); |
rdev->irq.hpd[1] = true; |
break; |
default: |
break; |
} |
enable |= 1 << radeon_connector->hpd.hpd; |
radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); |
} |
if (rdev->irq.installed) |
rs600_irq_set(rdev); |
// radeon_irq_kms_enable_hpd(rdev, enable); |
} |
|
void rs600_hpd_fini(struct radeon_device *rdev) |
127,6 → 153,7 |
{ |
struct drm_device *dev = rdev->ddev; |
struct drm_connector *connector; |
unsigned disable = 0; |
|
list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
134,29 → 161,19 |
case RADEON_HPD_1: |
WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL, |
S_007D00_DC_HOT_PLUG_DETECT1_EN(0)); |
rdev->irq.hpd[0] = false; |
break; |
case RADEON_HPD_2: |
WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL, |
S_007D10_DC_HOT_PLUG_DETECT2_EN(0)); |
rdev->irq.hpd[1] = false; |
break; |
default: |
break; |
} |
disable |= 1 << radeon_connector->hpd.hpd; |
} |
// radeon_irq_kms_disable_hpd(rdev, disable); |
} |
|
void rs600_bm_disable(struct radeon_device *rdev) |
{ |
u32 tmp; |
|
/* disable bus mastering */ |
tmp = PciRead16(rdev->pdev->bus, rdev->pdev->devfn, 0x4); |
PciWrite16(rdev->pdev->bus, rdev->pdev->devfn, 0x4, tmp & 0xFFFB); |
mdelay(1); |
} |
|
int rs600_asic_reset(struct radeon_device *rdev) |
{ |
struct rv515_mc_save save; |
180,7 → 197,8 |
WREG32(RADEON_CP_RB_CNTL, tmp); |
// pci_save_state(rdev->pdev); |
/* disable bus mastering */ |
rs600_bm_disable(rdev); |
// pci_clear_master(rdev->pdev); |
mdelay(1); |
/* reset GA+VAP */ |
WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_VAP(1) | |
S_0000F0_SOFT_RESET_GA(1)); |
211,7 → 229,6 |
/* Check if GPU is idle */ |
if (G_000E40_GA_BUSY(status) || G_000E40_VAP_BUSY(status)) { |
dev_err(rdev->dev, "failed to reset GPU\n"); |
rdev->gpu_lockup = true; |
ret = -1; |
} else |
dev_info(rdev->dev, "GPU reset succeed\n"); |
240,11 → 257,11 |
tmp = RREG32_MC(R_000100_MC_PT0_CNTL); |
} |
|
int rs600_gart_init(struct radeon_device *rdev) |
static int rs600_gart_init(struct radeon_device *rdev) |
{ |
int r; |
|
if (rdev->gart.table.vram.robj) { |
if (rdev->gart.robj) { |
WARN(1, "RS600 GART already initialized\n"); |
return 0; |
} |
262,7 → 279,7 |
u32 tmp; |
int r, i; |
|
if (rdev->gart.table.vram.robj == NULL) { |
if (rdev->gart.robj == NULL) { |
dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); |
return -EINVAL; |
} |
315,30 → 332,25 |
tmp = RREG32_MC(R_000009_MC_CNTL1); |
WREG32_MC(R_000009_MC_CNTL1, (tmp | S_000009_ENABLE_PAGE_TABLES(1))); |
rs600_gart_tlb_flush(rdev); |
DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", |
(unsigned)(rdev->mc.gtt_size >> 20), |
(unsigned long long)rdev->gart.table_addr); |
rdev->gart.ready = true; |
return 0; |
} |
|
void rs600_gart_disable(struct radeon_device *rdev) |
static void rs600_gart_disable(struct radeon_device *rdev) |
{ |
u32 tmp; |
int r; |
|
/* FIXME: disable out of gart access */ |
WREG32_MC(R_000100_MC_PT0_CNTL, 0); |
tmp = RREG32_MC(R_000009_MC_CNTL1); |
WREG32_MC(R_000009_MC_CNTL1, tmp & C_000009_ENABLE_PAGE_TABLES); |
if (rdev->gart.table.vram.robj) { |
r = radeon_bo_reserve(rdev->gart.table.vram.robj, false); |
if (r == 0) { |
radeon_bo_kunmap(rdev->gart.table.vram.robj); |
radeon_bo_unpin(rdev->gart.table.vram.robj); |
radeon_bo_unreserve(rdev->gart.table.vram.robj); |
radeon_gart_table_vram_unpin(rdev); |
} |
} |
} |
|
void rs600_gart_fini(struct radeon_device *rdev) |
static void rs600_gart_fini(struct radeon_device *rdev) |
{ |
radeon_gart_fini(rdev); |
rs600_gart_disable(rdev); |
353,7 → 365,7 |
|
int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) |
{ |
void __iomem *ptr = (void *)rdev->gart.table.vram.ptr; |
void __iomem *ptr = (void *)rdev->gart.ptr; |
|
if (i < 0 || i > rdev->gart.num_gpu_pages) { |
return -EINVAL; |
373,6 → 385,12 |
~S_007D08_DC_HOT_PLUG_DETECT1_INT_EN(1); |
u32 hpd2 = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL) & |
~S_007D18_DC_HOT_PLUG_DETECT2_INT_EN(1); |
u32 hdmi0; |
if (ASIC_IS_DCE2(rdev)) |
hdmi0 = RREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL) & |
~S_007408_HDMI0_AZ_FORMAT_WTRIG_MASK(1); |
else |
hdmi0 = 0; |
|
if (!rdev->irq.installed) { |
WARN(1, "Can't enable IRQ/MSI because no handler is installed\n"); |
379,18 → 397,15 |
WREG32(R_000040_GEN_INT_CNTL, 0); |
return -EINVAL; |
} |
if (rdev->irq.sw_int) { |
if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { |
tmp |= S_000040_SW_INT_EN(1); |
} |
if (rdev->irq.gui_idle) { |
tmp |= S_000040_GUI_IDLE(1); |
} |
if (rdev->irq.crtc_vblank_int[0] || |
rdev->irq.pflip[0]) { |
atomic_read(&rdev->irq.pflip[0])) { |
mode_int |= S_006540_D1MODE_VBLANK_INT_MASK(1); |
} |
if (rdev->irq.crtc_vblank_int[1] || |
rdev->irq.pflip[1]) { |
atomic_read(&rdev->irq.pflip[1])) { |
mode_int |= S_006540_D2MODE_VBLANK_INT_MASK(1); |
} |
if (rdev->irq.hpd[0]) { |
399,10 → 414,15 |
if (rdev->irq.hpd[1]) { |
hpd2 |= S_007D18_DC_HOT_PLUG_DETECT2_INT_EN(1); |
} |
if (rdev->irq.afmt[0]) { |
hdmi0 |= S_007408_HDMI0_AZ_FORMAT_WTRIG_MASK(1); |
} |
WREG32(R_000040_GEN_INT_CNTL, tmp); |
WREG32(R_006540_DxMODE_INT_MASK, mode_int); |
WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, hpd1); |
WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2); |
if (ASIC_IS_DCE2(rdev)) |
WREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL, hdmi0); |
return 0; |
} |
|
412,12 → 432,6 |
uint32_t irq_mask = S_000044_SW_INT(1); |
u32 tmp; |
|
/* the interrupt works, but the status bit is permanently asserted */ |
if (rdev->irq.gui_idle && radeon_gui_idle(rdev)) { |
if (!rdev->irq.gui_idle_acked) |
irq_mask |= S_000044_GUI_IDLE_STAT(1); |
} |
|
if (G_000044_DISPLAY_INT_STAT(irqs)) { |
rdev->irq.stat_regs.r500.disp_int = RREG32(R_007EDC_DISP_INTERRUPT_STATUS); |
if (G_007EDC_LB_D1_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { |
442,6 → 456,17 |
rdev->irq.stat_regs.r500.disp_int = 0; |
} |
|
if (ASIC_IS_DCE2(rdev)) { |
rdev->irq.stat_regs.r500.hdmi0_status = RREG32(R_007404_HDMI0_STATUS) & |
S_007404_HDMI0_AZ_FORMAT_WTRIG(1); |
if (G_007404_HDMI0_AZ_FORMAT_WTRIG(rdev->irq.stat_regs.r500.hdmi0_status)) { |
tmp = RREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL); |
tmp |= S_007408_HDMI0_AZ_FORMAT_WTRIG_ACK(1); |
WREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL, tmp); |
} |
} else |
rdev->irq.stat_regs.r500.hdmi0_status = 0; |
|
if (irqs) { |
WREG32(R_000044_GEN_INT_STATUS, irqs); |
} |
450,6 → 475,9 |
|
void rs600_irq_disable(struct radeon_device *rdev) |
{ |
u32 hdmi0 = RREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL) & |
~S_007408_HDMI0_AZ_FORMAT_WTRIG_MASK(1); |
WREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL, hdmi0); |
WREG32(R_000040_GEN_INT_CNTL, 0); |
WREG32(R_006540_DxMODE_INT_MASK, 0); |
/* Wait and acknowledge irq */ |
461,25 → 489,21 |
{ |
u32 status, msi_rearm; |
bool queue_hotplug = false; |
bool queue_hdmi = false; |
|
/* reset gui idle ack. the status bit is broken */ |
rdev->irq.gui_idle_acked = false; |
|
status = rs600_irq_ack(rdev); |
if (!status && !rdev->irq.stat_regs.r500.disp_int) { |
if (!status && |
!rdev->irq.stat_regs.r500.disp_int && |
!rdev->irq.stat_regs.r500.hdmi0_status) { |
return IRQ_NONE; |
} |
while (status || rdev->irq.stat_regs.r500.disp_int) { |
while (status || |
rdev->irq.stat_regs.r500.disp_int || |
rdev->irq.stat_regs.r500.hdmi0_status) { |
/* SW interrupt */ |
if (G_000044_SW_INT(status)) { |
radeon_fence_process(rdev); |
radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); |
} |
/* GUI idle */ |
if (G_000040_GUI_IDLE(status)) { |
rdev->irq.gui_idle_acked = true; |
rdev->pm.gui_idle = true; |
// wake_up(&rdev->irq.idle_queue); |
} |
/* Vertical blank interrupts */ |
if (G_007EDC_LB_D1_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { |
if (rdev->irq.crtc_vblank_int[0]) { |
507,12 → 531,16 |
queue_hotplug = true; |
DRM_DEBUG("HPD2\n"); |
} |
if (G_007404_HDMI0_AZ_FORMAT_WTRIG(rdev->irq.stat_regs.r500.hdmi0_status)) { |
queue_hdmi = true; |
DRM_DEBUG("HDMI0\n"); |
} |
status = rs600_irq_ack(rdev); |
} |
/* reset gui idle ack. the status bit is broken */ |
rdev->irq.gui_idle_acked = false; |
// if (queue_hotplug) |
// schedule_work(&rdev->hotplug_work); |
// if (queue_hdmi) |
// schedule_work(&rdev->audio_work); |
if (rdev->msi_enabled) { |
switch (rdev->family) { |
case CHIP_RS600: |
523,9 → 551,7 |
WREG32(RADEON_BUS_CNTL, msi_rearm | RS600_MSI_REARM); |
break; |
default: |
msi_rearm = RREG32(RADEON_MSI_REARM_EN) & ~RV370_MSI_REARM_EN; |
WREG32(RADEON_MSI_REARM_EN, msi_rearm); |
WREG32(RADEON_MSI_REARM_EN, msi_rearm | RV370_MSI_REARM_EN); |
WREG32(RADEON_MSI_REARM_EN, RV370_MSI_REARM_EN); |
break; |
} |
} |
552,7 → 578,7 |
return -1; |
} |
|
void rs600_gpu_init(struct radeon_device *rdev) |
static void rs600_gpu_init(struct radeon_device *rdev) |
{ |
r420_pipes_init(rdev); |
/* Wait for mc idle */ |
560,7 → 586,7 |
dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n"); |
} |
|
void rs600_mc_init(struct radeon_device *rdev) |
static void rs600_mc_init(struct radeon_device *rdev) |
{ |
u64 base; |
|
622,7 → 648,7 |
WREG32(R_000074_MC_IND_DATA, v); |
} |
|
void rs600_debugfs(struct radeon_device *rdev) |
static void rs600_debugfs(struct radeon_device *rdev) |
{ |
if (r100_debugfs_rbbm_init(rdev)) |
DRM_ERROR("Failed to register debugfs file for RBBM !\n"); |
688,11 → 714,14 |
dev_err(rdev->dev, "failed initializing CP (%d).\n", r); |
return r; |
} |
r = r100_ib_init(rdev); |
|
r = radeon_ib_pool_init(rdev); |
if (r) { |
dev_err(rdev->dev, "failed initializing IB (%d).\n", r); |
dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
return r; |
} |
|
|
return 0; |
} |
|
754,6 → 783,7 |
if (r) |
return r; |
rs600_set_safe_registers(rdev); |
|
rdev->accel_working = true; |
r = rs600_startup(rdev); |
if (r) { |