24,10 → 24,10 |
#include <linux/firmware.h> |
//#include <linux/platform_device.h> |
#include <linux/slab.h> |
#include "drmP.h" |
#include <drm/drmP.h> |
#include "radeon.h" |
#include "radeon_asic.h" |
#include "radeon_drm.h" |
#include <drm/radeon_drm.h> |
#include "evergreend.h" |
#include "atom.h" |
#include "avivod.h" |
37,16 → 37,122 |
#define EVERGREEN_PFP_UCODE_SIZE 1120 |
#define EVERGREEN_PM4_UCODE_SIZE 1376 |
|
static const u32 crtc_offsets[6] = |
{ |
EVERGREEN_CRTC0_REGISTER_OFFSET, |
EVERGREEN_CRTC1_REGISTER_OFFSET, |
EVERGREEN_CRTC2_REGISTER_OFFSET, |
EVERGREEN_CRTC3_REGISTER_OFFSET, |
EVERGREEN_CRTC4_REGISTER_OFFSET, |
EVERGREEN_CRTC5_REGISTER_OFFSET |
}; |
|
static void evergreen_gpu_init(struct radeon_device *rdev); |
void evergreen_fini(struct radeon_device *rdev); |
static void evergreen_pcie_gen2_enable(struct radeon_device *rdev); |
void evergreen_pcie_gen2_enable(struct radeon_device *rdev); |
extern void cayman_cp_int_cntl_setup(struct radeon_device *rdev, |
int ring, u32 cp_int_cntl); |
|
void evergreen_tiling_fields(unsigned tiling_flags, unsigned *bankw, |
unsigned *bankh, unsigned *mtaspect, |
unsigned *tile_split) |
{ |
*bankw = (tiling_flags >> RADEON_TILING_EG_BANKW_SHIFT) & RADEON_TILING_EG_BANKW_MASK; |
*bankh = (tiling_flags >> RADEON_TILING_EG_BANKH_SHIFT) & RADEON_TILING_EG_BANKH_MASK; |
*mtaspect = (tiling_flags >> RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT) & RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK; |
*tile_split = (tiling_flags >> RADEON_TILING_EG_TILE_SPLIT_SHIFT) & RADEON_TILING_EG_TILE_SPLIT_MASK; |
switch (*bankw) { |
default: |
case 1: *bankw = EVERGREEN_ADDR_SURF_BANK_WIDTH_1; break; |
case 2: *bankw = EVERGREEN_ADDR_SURF_BANK_WIDTH_2; break; |
case 4: *bankw = EVERGREEN_ADDR_SURF_BANK_WIDTH_4; break; |
case 8: *bankw = EVERGREEN_ADDR_SURF_BANK_WIDTH_8; break; |
} |
switch (*bankh) { |
default: |
case 1: *bankh = EVERGREEN_ADDR_SURF_BANK_HEIGHT_1; break; |
case 2: *bankh = EVERGREEN_ADDR_SURF_BANK_HEIGHT_2; break; |
case 4: *bankh = EVERGREEN_ADDR_SURF_BANK_HEIGHT_4; break; |
case 8: *bankh = EVERGREEN_ADDR_SURF_BANK_HEIGHT_8; break; |
} |
switch (*mtaspect) { |
default: |
case 1: *mtaspect = EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_1; break; |
case 2: *mtaspect = EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_2; break; |
case 4: *mtaspect = EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_4; break; |
case 8: *mtaspect = EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_8; break; |
} |
} |
|
void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev) |
{ |
u16 ctl, v; |
int err; |
|
err = pcie_capability_read_word(rdev->pdev, PCI_EXP_DEVCTL, &ctl); |
if (err) |
return; |
|
v = (ctl & PCI_EXP_DEVCTL_READRQ) >> 12; |
|
/* if bios or OS sets MAX_READ_REQUEST_SIZE to an invalid value, fix it |
* to avoid hangs or perfomance issues |
*/ |
if ((v == 0) || (v == 6) || (v == 7)) { |
ctl &= ~PCI_EXP_DEVCTL_READRQ; |
ctl |= (2 << 12); |
pcie_capability_write_word(rdev->pdev, PCI_EXP_DEVCTL, ctl); |
} |
} |
|
/** |
* dce4_wait_for_vblank - vblank wait asic callback. |
* |
* @rdev: radeon_device pointer |
* @crtc: crtc to wait for vblank on |
* |
* Wait for vblank on the requested crtc (evergreen+). |
*/ |
void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc) |
{ |
int i; |
|
if (crtc >= rdev->num_crtc) |
return; |
|
if (RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[crtc]) & EVERGREEN_CRTC_MASTER_EN) { |
for (i = 0; i < rdev->usec_timeout; i++) { |
if (!(RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK)) |
break; |
udelay(1); |
} |
for (i = 0; i < rdev->usec_timeout; i++) { |
if (RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK) |
break; |
udelay(1); |
} |
} |
} |
|
|
/** |
* evergreen_page_flip - pageflip callback. |
* |
* @rdev: radeon_device pointer |
* @crtc_id: crtc to cleanup pageflip on |
* @crtc_base: new address of the crtc (GPU MC address) |
* |
* Does the actual pageflip (evergreen+). |
* During vblank we take the crtc lock and wait for the update_pending |
* bit to go high, when it does, we release the lock, and allow the |
* double buffered update to take place. |
* Returns the current update pending status. |
*/ |
u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) |
{ |
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; |
u32 tmp = RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset); |
int i; |
|
/* Lock the graphics update lock */ |
tmp |= EVERGREEN_GRPH_UPDATE_LOCK; |
64,7 → 170,11 |
(u32)crtc_base); |
|
/* Wait for update_pending to go high. */ |
while (!(RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING)); |
for (i = 0; i < rdev->usec_timeout; i++) { |
if (RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING) |
break; |
udelay(1); |
} |
DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); |
|
/* Unlock the lock, so double-buffering can take place inside vblank */ |
122,6 → 232,74 |
return actual_temp * 1000; |
} |
|
/** |
* sumo_pm_init_profile - Initialize power profiles callback. |
* |
* @rdev: radeon_device pointer |
* |
* Initialize the power states used in profile mode |
* (sumo, trinity, SI). |
* Used for profile mode only. |
*/ |
void sumo_pm_init_profile(struct radeon_device *rdev) |
{ |
int idx; |
|
/* default */ |
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; |
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; |
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; |
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0; |
|
/* low,mid sh/mh */ |
if (rdev->flags & RADEON_IS_MOBILITY) |
idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0); |
else |
idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); |
|
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = idx; |
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = idx; |
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; |
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; |
|
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = idx; |
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = idx; |
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; |
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; |
|
rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = idx; |
rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = idx; |
rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; |
rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0; |
|
rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = idx; |
rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = idx; |
rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; |
rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0; |
|
/* high sh/mh */ |
idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); |
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = idx; |
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = idx; |
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; |
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = |
rdev->pm.power_state[idx].num_clock_modes - 1; |
|
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = idx; |
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = idx; |
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; |
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = |
rdev->pm.power_state[idx].num_clock_modes - 1; |
} |
|
/** |
* evergreen_pm_misc - set additional pm hw parameters callback. |
* |
* @rdev: radeon_device pointer |
* |
* Set non-clock parameters associated with a power state |
* (voltage, etc.) (evergreen+). |
*/ |
void evergreen_pm_misc(struct radeon_device *rdev) |
{ |
int req_ps_idx = rdev->pm.requested_power_state_index; |
149,6 → 327,13 |
} |
} |
|
/** |
* evergreen_pm_prepare - pre-power state change callback. |
* |
* @rdev: radeon_device pointer |
* |
* Prepare for a power state change (evergreen+). |
*/ |
void evergreen_pm_prepare(struct radeon_device *rdev) |
{ |
struct drm_device *ddev = rdev->ddev; |
167,6 → 352,13 |
} |
} |
|
/** |
* evergreen_pm_finish - post-power state change callback. |
* |
* @rdev: radeon_device pointer |
* |
* Clean up after a power state change (evergreen+). |
*/ |
void evergreen_pm_finish(struct radeon_device *rdev) |
{ |
struct drm_device *ddev = rdev->ddev; |
185,6 → 377,15 |
} |
} |
|
/** |
* evergreen_hpd_sense - hpd sense callback. |
* |
* @rdev: radeon_device pointer |
* @hpd: hpd (hotplug detect) pin |
* |
* Checks if a digital monitor is connected (evergreen+). |
* Returns true if connected, false if not connected. |
*/ |
bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) |
{ |
bool connected = false; |
221,6 → 422,14 |
return connected; |
} |
|
/** |
* evergreen_hpd_set_polarity - hpd set polarity callback. |
* |
* @rdev: radeon_device pointer |
* @hpd: hpd (hotplug detect) pin |
* |
* Set the polarity of the hpd pin (evergreen+). |
*/ |
void evergreen_hpd_set_polarity(struct radeon_device *rdev, |
enum radeon_hpd_id hpd) |
{ |
281,10 → 490,19 |
} |
} |
|
/** |
* evergreen_hpd_init - hpd setup callback. |
* |
* @rdev: radeon_device pointer |
* |
* Setup the hpd pins used by the card (evergreen+). |
* Enable the pin, set the polarity, and enable the hpd interrupts. |
*/ |
void evergreen_hpd_init(struct radeon_device *rdev) |
{ |
struct drm_device *dev = rdev->ddev; |
struct drm_connector *connector; |
unsigned enabled = 0; |
u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | |
DC_HPDx_RX_INT_TIMER(0xfa) | DC_HPDx_EN; |
|
293,40 → 511,44 |
switch (radeon_connector->hpd.hpd) { |
case RADEON_HPD_1: |
WREG32(DC_HPD1_CONTROL, tmp); |
rdev->irq.hpd[0] = true; |
break; |
case RADEON_HPD_2: |
WREG32(DC_HPD2_CONTROL, tmp); |
rdev->irq.hpd[1] = true; |
break; |
case RADEON_HPD_3: |
WREG32(DC_HPD3_CONTROL, tmp); |
rdev->irq.hpd[2] = true; |
break; |
case RADEON_HPD_4: |
WREG32(DC_HPD4_CONTROL, tmp); |
rdev->irq.hpd[3] = true; |
break; |
case RADEON_HPD_5: |
WREG32(DC_HPD5_CONTROL, tmp); |
rdev->irq.hpd[4] = true; |
break; |
case RADEON_HPD_6: |
WREG32(DC_HPD6_CONTROL, tmp); |
rdev->irq.hpd[5] = true; |
break; |
default: |
break; |
} |
radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); |
enabled |= 1 << radeon_connector->hpd.hpd; |
} |
if (rdev->irq.installed) |
evergreen_irq_set(rdev); |
// radeon_irq_kms_enable_hpd(rdev, enabled); |
} |
|
/** |
* evergreen_hpd_fini - hpd tear down callback. |
* |
* @rdev: radeon_device pointer |
* |
* Tear down the hpd pins used by the card (evergreen+). |
* Disable the hpd interrupts. |
*/ |
void evergreen_hpd_fini(struct radeon_device *rdev) |
{ |
struct drm_device *dev = rdev->ddev; |
struct drm_connector *connector; |
unsigned disabled = 0; |
|
list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
333,32 → 555,28 |
switch (radeon_connector->hpd.hpd) { |
case RADEON_HPD_1: |
WREG32(DC_HPD1_CONTROL, 0); |
rdev->irq.hpd[0] = false; |
break; |
case RADEON_HPD_2: |
WREG32(DC_HPD2_CONTROL, 0); |
rdev->irq.hpd[1] = false; |
break; |
case RADEON_HPD_3: |
WREG32(DC_HPD3_CONTROL, 0); |
rdev->irq.hpd[2] = false; |
break; |
case RADEON_HPD_4: |
WREG32(DC_HPD4_CONTROL, 0); |
rdev->irq.hpd[3] = false; |
break; |
case RADEON_HPD_5: |
WREG32(DC_HPD5_CONTROL, 0); |
rdev->irq.hpd[4] = false; |
break; |
case RADEON_HPD_6: |
WREG32(DC_HPD6_CONTROL, 0); |
rdev->irq.hpd[5] = false; |
break; |
default: |
break; |
} |
disabled |= 1 << radeon_connector->hpd.hpd; |
} |
// radeon_irq_kms_disable_hpd(rdev, disabled); |
} |
|
/* watermark setup */ |
437,7 → 655,7 |
return 0; |
} |
|
static u32 evergreen_get_number_of_dram_channels(struct radeon_device *rdev) |
u32 evergreen_get_number_of_dram_channels(struct radeon_device *rdev) |
{ |
u32 tmp = RREG32(MC_SHARED_CHMAP); |
|
789,6 → 1007,14 |
|
} |
|
/** |
* evergreen_bandwidth_update - update display watermarks callback. |
* |
* @rdev: radeon_device pointer |
* |
* Update the display watermarks based on the requested mode(s) |
* (evergreen+). |
*/ |
void evergreen_bandwidth_update(struct radeon_device *rdev) |
{ |
struct drm_display_mode *mode0 = NULL; |
812,6 → 1038,15 |
} |
} |
|
/** |
* evergreen_mc_wait_for_idle - wait for MC idle callback. |
* |
* @rdev: radeon_device pointer |
* |
* Wait for the MC (memory controller) to be idle. |
* (evergreen+). |
* Returns 0 if the MC is idle, -1 if not. |
*/ |
int evergreen_mc_wait_for_idle(struct radeon_device *rdev) |
{ |
unsigned i; |
853,12 → 1088,12 |
} |
} |
|
int evergreen_pcie_gart_enable(struct radeon_device *rdev) |
static int evergreen_pcie_gart_enable(struct radeon_device *rdev) |
{ |
u32 tmp; |
int r; |
|
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; |
} |
885,6 → 1120,11 |
WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp); |
WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp); |
WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp); |
if ((rdev->family == CHIP_JUNIPER) || |
(rdev->family == CHIP_CYPRESS) || |
(rdev->family == CHIP_HEMLOCK) || |
(rdev->family == CHIP_BARTS)) |
WREG32(MC_VM_MD_L1_TLB3_CNTL, tmp); |
} |
WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp); |
WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp); |
900,14 → 1140,16 |
WREG32(VM_CONTEXT1_CNTL, 0); |
|
evergreen_pcie_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 evergreen_pcie_gart_disable(struct radeon_device *rdev) |
static void evergreen_pcie_gart_disable(struct radeon_device *rdev) |
{ |
u32 tmp; |
int r; |
|
/* Disable all tables */ |
WREG32(VM_CONTEXT0_CNTL, 0); |
927,17 → 1169,10 |
WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp); |
WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); |
WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp); |
if (rdev->gart.table.vram.robj) { |
r = radeon_bo_reserve(rdev->gart.table.vram.robj, false); |
if (likely(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 evergreen_pcie_gart_fini(struct radeon_device *rdev) |
static void evergreen_pcie_gart_fini(struct radeon_device *rdev) |
{ |
evergreen_pcie_gart_disable(rdev); |
radeon_gart_table_vram_free(rdev); |
945,7 → 1180,7 |
} |
|
|
void evergreen_agp_enable(struct radeon_device *rdev) |
static void evergreen_agp_enable(struct radeon_device *rdev) |
{ |
u32 tmp; |
|
973,175 → 1208,105 |
|
void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save) |
{ |
save->vga_control[0] = RREG32(D1VGA_CONTROL); |
save->vga_control[1] = RREG32(D2VGA_CONTROL); |
u32 crtc_enabled, tmp, frame_count, blackout; |
int i, j; |
|
save->vga_render_control = RREG32(VGA_RENDER_CONTROL); |
save->vga_hdp_control = RREG32(VGA_HDP_CONTROL); |
save->crtc_control[0] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET); |
save->crtc_control[1] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); |
if (rdev->num_crtc >= 4) { |
save->vga_control[2] = RREG32(EVERGREEN_D3VGA_CONTROL); |
save->vga_control[3] = RREG32(EVERGREEN_D4VGA_CONTROL); |
save->crtc_control[2] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET); |
save->crtc_control[3] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET); |
} |
if (rdev->num_crtc >= 6) { |
save->vga_control[4] = RREG32(EVERGREEN_D5VGA_CONTROL); |
save->vga_control[5] = RREG32(EVERGREEN_D6VGA_CONTROL); |
save->crtc_control[4] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET); |
save->crtc_control[5] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); |
} |
|
/* Stop all video */ |
/* disable VGA render */ |
WREG32(VGA_RENDER_CONTROL, 0); |
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); |
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); |
if (rdev->num_crtc >= 4) { |
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); |
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); |
/* blank the display controllers */ |
for (i = 0; i < rdev->num_crtc; i++) { |
crtc_enabled = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]) & EVERGREEN_CRTC_MASTER_EN; |
if (crtc_enabled) { |
save->crtc_enabled[i] = true; |
if (ASIC_IS_DCE6(rdev)) { |
tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); |
if (!(tmp & EVERGREEN_CRTC_BLANK_DATA_EN)) { |
radeon_wait_for_vblank(rdev, i); |
tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; |
WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); |
} |
if (rdev->num_crtc >= 6) { |
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); |
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); |
} else { |
tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); |
if (!(tmp & EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE)) { |
radeon_wait_for_vblank(rdev, i); |
tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; |
WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); |
} |
WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); |
WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); |
if (rdev->num_crtc >= 4) { |
WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); |
WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); |
} |
if (rdev->num_crtc >= 6) { |
WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); |
WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); |
/* wait for the next frame */ |
frame_count = radeon_get_vblank_counter(rdev, i); |
for (j = 0; j < rdev->usec_timeout; j++) { |
if (radeon_get_vblank_counter(rdev, i) != frame_count) |
break; |
udelay(1); |
} |
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); |
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); |
if (rdev->num_crtc >= 4) { |
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); |
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); |
} |
if (rdev->num_crtc >= 6) { |
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); |
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); |
} |
|
WREG32(D1VGA_CONTROL, 0); |
WREG32(D2VGA_CONTROL, 0); |
if (rdev->num_crtc >= 4) { |
WREG32(EVERGREEN_D3VGA_CONTROL, 0); |
WREG32(EVERGREEN_D4VGA_CONTROL, 0); |
radeon_mc_wait_for_idle(rdev); |
|
blackout = RREG32(MC_SHARED_BLACKOUT_CNTL); |
if ((blackout & BLACKOUT_MODE_MASK) != 1) { |
/* Block CPU access */ |
WREG32(BIF_FB_EN, 0); |
/* blackout the MC */ |
blackout &= ~BLACKOUT_MODE_MASK; |
WREG32(MC_SHARED_BLACKOUT_CNTL, blackout | 1); |
} |
if (rdev->num_crtc >= 6) { |
WREG32(EVERGREEN_D5VGA_CONTROL, 0); |
WREG32(EVERGREEN_D6VGA_CONTROL, 0); |
} |
} |
|
void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) |
{ |
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET, |
upper_32_bits(rdev->mc.vram_start)); |
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET, |
upper_32_bits(rdev->mc.vram_start)); |
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC0_REGISTER_OFFSET, |
(u32)rdev->mc.vram_start); |
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC0_REGISTER_OFFSET, |
(u32)rdev->mc.vram_start); |
u32 tmp, frame_count; |
int i, j; |
|
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC1_REGISTER_OFFSET, |
/* update crtc base addresses */ |
for (i = 0; i < rdev->num_crtc; i++) { |
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], |
upper_32_bits(rdev->mc.vram_start)); |
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC1_REGISTER_OFFSET, |
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], |
upper_32_bits(rdev->mc.vram_start)); |
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET, |
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i], |
(u32)rdev->mc.vram_start); |
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET, |
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i], |
(u32)rdev->mc.vram_start); |
|
if (rdev->num_crtc >= 4) { |
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, |
upper_32_bits(rdev->mc.vram_start)); |
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, |
upper_32_bits(rdev->mc.vram_start)); |
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET, |
(u32)rdev->mc.vram_start); |
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET, |
(u32)rdev->mc.vram_start); |
|
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET, |
upper_32_bits(rdev->mc.vram_start)); |
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET, |
upper_32_bits(rdev->mc.vram_start)); |
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET, |
(u32)rdev->mc.vram_start); |
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET, |
(u32)rdev->mc.vram_start); |
} |
if (rdev->num_crtc >= 6) { |
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, |
upper_32_bits(rdev->mc.vram_start)); |
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, |
upper_32_bits(rdev->mc.vram_start)); |
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET, |
(u32)rdev->mc.vram_start); |
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET, |
(u32)rdev->mc.vram_start); |
WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vram_start)); |
WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start); |
|
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET, |
upper_32_bits(rdev->mc.vram_start)); |
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET, |
upper_32_bits(rdev->mc.vram_start)); |
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET, |
(u32)rdev->mc.vram_start); |
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET, |
(u32)rdev->mc.vram_start); |
} |
/* unblackout the MC */ |
tmp = RREG32(MC_SHARED_BLACKOUT_CNTL); |
tmp &= ~BLACKOUT_MODE_MASK; |
WREG32(MC_SHARED_BLACKOUT_CNTL, tmp); |
/* allow CPU access */ |
WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN); |
|
WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vram_start)); |
WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start); |
/* Unlock host access */ |
WREG32(VGA_HDP_CONTROL, save->vga_hdp_control); |
mdelay(1); |
/* Restore video state */ |
WREG32(D1VGA_CONTROL, save->vga_control[0]); |
WREG32(D2VGA_CONTROL, save->vga_control[1]); |
if (rdev->num_crtc >= 4) { |
WREG32(EVERGREEN_D3VGA_CONTROL, save->vga_control[2]); |
WREG32(EVERGREEN_D4VGA_CONTROL, save->vga_control[3]); |
for (i = 0; i < rdev->num_crtc; i++) { |
if (save->crtc_enabled) { |
if (ASIC_IS_DCE6(rdev)) { |
tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); |
tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; |
WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); |
} else { |
tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); |
tmp &= ~EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; |
WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); |
} |
if (rdev->num_crtc >= 6) { |
WREG32(EVERGREEN_D5VGA_CONTROL, save->vga_control[4]); |
WREG32(EVERGREEN_D6VGA_CONTROL, save->vga_control[5]); |
/* wait for the next frame */ |
frame_count = radeon_get_vblank_counter(rdev, i); |
for (j = 0; j < rdev->usec_timeout; j++) { |
if (radeon_get_vblank_counter(rdev, i) != frame_count) |
break; |
udelay(1); |
} |
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); |
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); |
if (rdev->num_crtc >= 4) { |
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); |
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); |
} |
if (rdev->num_crtc >= 6) { |
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); |
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); |
} |
WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, save->crtc_control[0]); |
WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, save->crtc_control[1]); |
if (rdev->num_crtc >= 4) { |
WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, save->crtc_control[2]); |
WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, save->crtc_control[3]); |
} |
if (rdev->num_crtc >= 6) { |
WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, save->crtc_control[4]); |
WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, save->crtc_control[5]); |
} |
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); |
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); |
if (rdev->num_crtc >= 4) { |
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); |
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); |
} |
if (rdev->num_crtc >= 6) { |
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); |
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); |
} |
/* Unlock vga access */ |
WREG32(VGA_HDP_CONTROL, save->vga_hdp_control); |
mdelay(1); |
WREG32(VGA_RENDER_CONTROL, save->vga_render_control); |
} |
|
1188,8 → 1353,11 |
WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, |
rdev->mc.vram_end >> 12); |
} |
WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0); |
if (rdev->flags & RADEON_IS_IGP) { |
WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12); |
/* llano/ontario only */ |
if ((rdev->family == CHIP_PALM) || |
(rdev->family == CHIP_SUMO) || |
(rdev->family == CHIP_SUMO2)) { |
tmp = RREG32(MC_FUS_VM_FB_OFFSET) & 0x000FFFFF; |
tmp |= ((rdev->mc.vram_end >> 20) & 0xF) << 24; |
tmp |= ((rdev->mc.vram_start >> 20) & 0xF) << 20; |
1224,18 → 1392,36 |
*/ |
void evergreen_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) |
{ |
struct radeon_ring *ring = &rdev->ring[ib->ring]; |
u32 next_rptr; |
|
/* set to DX10/11 mode */ |
radeon_ring_write(rdev, PACKET3(PACKET3_MODE_CONTROL, 0)); |
radeon_ring_write(rdev, 1); |
/* FIXME: implement */ |
radeon_ring_write(rdev, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); |
radeon_ring_write(rdev, |
radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0)); |
radeon_ring_write(ring, 1); |
|
if (ring->rptr_save_reg) { |
next_rptr = ring->wptr + 3 + 4; |
radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); |
radeon_ring_write(ring, ((ring->rptr_save_reg - |
PACKET3_SET_CONFIG_REG_START) >> 2)); |
radeon_ring_write(ring, next_rptr); |
} else if (rdev->wb.enabled) { |
next_rptr = ring->wptr + 5 + 4; |
radeon_ring_write(ring, PACKET3(PACKET3_MEM_WRITE, 3)); |
radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); |
radeon_ring_write(ring, (upper_32_bits(ring->next_rptr_gpu_addr) & 0xff) | (1 << 18)); |
radeon_ring_write(ring, next_rptr); |
radeon_ring_write(ring, 0); |
} |
|
radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); |
radeon_ring_write(ring, |
#ifdef __BIG_ENDIAN |
(2 << 0) | |
#endif |
(ib->gpu_addr & 0xFFFFFFFC)); |
radeon_ring_write(rdev, upper_32_bits(ib->gpu_addr) & 0xFF); |
radeon_ring_write(rdev, ib->length_dw); |
radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFF); |
radeon_ring_write(ring, ib->length_dw); |
} |
|
|
1273,27 → 1459,28 |
|
static int evergreen_cp_start(struct radeon_device *rdev) |
{ |
struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; |
int r, i; |
uint32_t cp_me; |
|
r = radeon_ring_lock(rdev, 7); |
r = radeon_ring_lock(rdev, ring, 7); |
if (r) { |
DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); |
return r; |
} |
radeon_ring_write(rdev, PACKET3(PACKET3_ME_INITIALIZE, 5)); |
radeon_ring_write(rdev, 0x1); |
radeon_ring_write(rdev, 0x0); |
radeon_ring_write(rdev, rdev->config.evergreen.max_hw_contexts - 1); |
radeon_ring_write(rdev, PACKET3_ME_INITIALIZE_DEVICE_ID(1)); |
radeon_ring_write(rdev, 0); |
radeon_ring_write(rdev, 0); |
radeon_ring_unlock_commit(rdev); |
radeon_ring_write(ring, PACKET3(PACKET3_ME_INITIALIZE, 5)); |
radeon_ring_write(ring, 0x1); |
radeon_ring_write(ring, 0x0); |
radeon_ring_write(ring, rdev->config.evergreen.max_hw_contexts - 1); |
radeon_ring_write(ring, PACKET3_ME_INITIALIZE_DEVICE_ID(1)); |
radeon_ring_write(ring, 0); |
radeon_ring_write(ring, 0); |
radeon_ring_unlock_commit(rdev, ring); |
|
cp_me = 0xff; |
WREG32(CP_ME_CNTL, cp_me); |
|
r = radeon_ring_lock(rdev, evergreen_default_size + 19); |
r = radeon_ring_lock(rdev, ring, evergreen_default_size + 19); |
if (r) { |
DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); |
return r; |
1300,44 → 1487,45 |
} |
|
/* setup clear context state */ |
radeon_ring_write(rdev, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); |
radeon_ring_write(rdev, PACKET3_PREAMBLE_BEGIN_CLEAR_STATE); |
radeon_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); |
radeon_ring_write(ring, PACKET3_PREAMBLE_BEGIN_CLEAR_STATE); |
|
for (i = 0; i < evergreen_default_size; i++) |
radeon_ring_write(rdev, evergreen_default_state[i]); |
radeon_ring_write(ring, evergreen_default_state[i]); |
|
radeon_ring_write(rdev, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); |
radeon_ring_write(rdev, PACKET3_PREAMBLE_END_CLEAR_STATE); |
radeon_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); |
radeon_ring_write(ring, PACKET3_PREAMBLE_END_CLEAR_STATE); |
|
/* set clear context state */ |
radeon_ring_write(rdev, PACKET3(PACKET3_CLEAR_STATE, 0)); |
radeon_ring_write(rdev, 0); |
radeon_ring_write(ring, PACKET3(PACKET3_CLEAR_STATE, 0)); |
radeon_ring_write(ring, 0); |
|
/* SQ_VTX_BASE_VTX_LOC */ |
radeon_ring_write(rdev, 0xc0026f00); |
radeon_ring_write(rdev, 0x00000000); |
radeon_ring_write(rdev, 0x00000000); |
radeon_ring_write(rdev, 0x00000000); |
radeon_ring_write(ring, 0xc0026f00); |
radeon_ring_write(ring, 0x00000000); |
radeon_ring_write(ring, 0x00000000); |
radeon_ring_write(ring, 0x00000000); |
|
/* Clear consts */ |
radeon_ring_write(rdev, 0xc0036f00); |
radeon_ring_write(rdev, 0x00000bc4); |
radeon_ring_write(rdev, 0xffffffff); |
radeon_ring_write(rdev, 0xffffffff); |
radeon_ring_write(rdev, 0xffffffff); |
radeon_ring_write(ring, 0xc0036f00); |
radeon_ring_write(ring, 0x00000bc4); |
radeon_ring_write(ring, 0xffffffff); |
radeon_ring_write(ring, 0xffffffff); |
radeon_ring_write(ring, 0xffffffff); |
|
radeon_ring_write(rdev, 0xc0026900); |
radeon_ring_write(rdev, 0x00000316); |
radeon_ring_write(rdev, 0x0000000e); /* VGT_VERTEX_REUSE_BLOCK_CNTL */ |
radeon_ring_write(rdev, 0x00000010); /* */ |
radeon_ring_write(ring, 0xc0026900); |
radeon_ring_write(ring, 0x00000316); |
radeon_ring_write(ring, 0x0000000e); /* VGT_VERTEX_REUSE_BLOCK_CNTL */ |
radeon_ring_write(ring, 0x00000010); /* */ |
|
radeon_ring_unlock_commit(rdev); |
radeon_ring_unlock_commit(rdev, ring); |
|
return 0; |
} |
|
int evergreen_cp_resume(struct radeon_device *rdev) |
static int evergreen_cp_resume(struct radeon_device *rdev) |
{ |
struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; |
u32 tmp; |
u32 rb_bufsz; |
int r; |
1355,13 → 1543,14 |
RREG32(GRBM_SOFT_RESET); |
|
/* Set ring buffer size */ |
rb_bufsz = drm_order(rdev->cp.ring_size / 8); |
rb_bufsz = drm_order(ring->ring_size / 8); |
tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; |
#ifdef __BIG_ENDIAN |
tmp |= BUF_SWAP_32BIT; |
#endif |
WREG32(CP_RB_CNTL, tmp); |
WREG32(CP_SEM_WAIT_TIMER, 0x4); |
WREG32(CP_SEM_WAIT_TIMER, 0x0); |
WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0); |
|
/* Set the write pointer delay */ |
WREG32(CP_RB_WPTR_DELAY, 0); |
1369,7 → 1558,8 |
/* Initialize the ring buffer's read and write pointers */ |
WREG32(CP_RB_CNTL, tmp | RB_RPTR_WR_ENA); |
WREG32(CP_RB_RPTR_WR, 0); |
WREG32(CP_RB_WPTR, 0); |
ring->wptr = 0; |
WREG32(CP_RB_WPTR, ring->wptr); |
|
/* set the wb address wether it's enabled or not */ |
WREG32(CP_RB_RPTR_ADDR, |
1387,17 → 1577,16 |
mdelay(1); |
WREG32(CP_RB_CNTL, tmp); |
|
WREG32(CP_RB_BASE, rdev->cp.gpu_addr >> 8); |
WREG32(CP_RB_BASE, ring->gpu_addr >> 8); |
WREG32(CP_DEBUG, (1 << 27) | (1 << 28)); |
|
rdev->cp.rptr = RREG32(CP_RB_RPTR); |
rdev->cp.wptr = RREG32(CP_RB_WPTR); |
ring->rptr = RREG32(CP_RB_RPTR); |
|
evergreen_cp_start(rdev); |
rdev->cp.ready = true; |
r = radeon_ring_test(rdev); |
ring->ready = true; |
r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, ring); |
if (r) { |
rdev->cp.ready = false; |
ring->ready = false; |
return r; |
} |
return 0; |
1406,205 → 1595,10 |
/* |
* Core functions |
*/ |
static u32 evergreen_get_tile_pipe_to_backend_map(struct radeon_device *rdev, |
u32 num_tile_pipes, |
u32 num_backends, |
u32 backend_disable_mask) |
{ |
u32 backend_map = 0; |
u32 enabled_backends_mask = 0; |
u32 enabled_backends_count = 0; |
u32 cur_pipe; |
u32 swizzle_pipe[EVERGREEN_MAX_PIPES]; |
u32 cur_backend = 0; |
u32 i; |
bool force_no_swizzle; |
|
if (num_tile_pipes > EVERGREEN_MAX_PIPES) |
num_tile_pipes = EVERGREEN_MAX_PIPES; |
if (num_tile_pipes < 1) |
num_tile_pipes = 1; |
if (num_backends > EVERGREEN_MAX_BACKENDS) |
num_backends = EVERGREEN_MAX_BACKENDS; |
if (num_backends < 1) |
num_backends = 1; |
|
for (i = 0; i < EVERGREEN_MAX_BACKENDS; ++i) { |
if (((backend_disable_mask >> i) & 1) == 0) { |
enabled_backends_mask |= (1 << i); |
++enabled_backends_count; |
} |
if (enabled_backends_count == num_backends) |
break; |
} |
|
if (enabled_backends_count == 0) { |
enabled_backends_mask = 1; |
enabled_backends_count = 1; |
} |
|
if (enabled_backends_count != num_backends) |
num_backends = enabled_backends_count; |
|
memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * EVERGREEN_MAX_PIPES); |
switch (rdev->family) { |
case CHIP_CEDAR: |
case CHIP_REDWOOD: |
case CHIP_PALM: |
case CHIP_SUMO: |
case CHIP_SUMO2: |
case CHIP_TURKS: |
case CHIP_CAICOS: |
force_no_swizzle = false; |
break; |
case CHIP_CYPRESS: |
case CHIP_HEMLOCK: |
case CHIP_JUNIPER: |
case CHIP_BARTS: |
default: |
force_no_swizzle = true; |
break; |
} |
if (force_no_swizzle) { |
bool last_backend_enabled = false; |
|
force_no_swizzle = false; |
for (i = 0; i < EVERGREEN_MAX_BACKENDS; ++i) { |
if (((enabled_backends_mask >> i) & 1) == 1) { |
if (last_backend_enabled) |
force_no_swizzle = true; |
last_backend_enabled = true; |
} else |
last_backend_enabled = false; |
} |
} |
|
switch (num_tile_pipes) { |
case 1: |
case 3: |
case 5: |
case 7: |
DRM_ERROR("odd number of pipes!\n"); |
break; |
case 2: |
swizzle_pipe[0] = 0; |
swizzle_pipe[1] = 1; |
break; |
case 4: |
if (force_no_swizzle) { |
swizzle_pipe[0] = 0; |
swizzle_pipe[1] = 1; |
swizzle_pipe[2] = 2; |
swizzle_pipe[3] = 3; |
} else { |
swizzle_pipe[0] = 0; |
swizzle_pipe[1] = 2; |
swizzle_pipe[2] = 1; |
swizzle_pipe[3] = 3; |
} |
break; |
case 6: |
if (force_no_swizzle) { |
swizzle_pipe[0] = 0; |
swizzle_pipe[1] = 1; |
swizzle_pipe[2] = 2; |
swizzle_pipe[3] = 3; |
swizzle_pipe[4] = 4; |
swizzle_pipe[5] = 5; |
} else { |
swizzle_pipe[0] = 0; |
swizzle_pipe[1] = 2; |
swizzle_pipe[2] = 4; |
swizzle_pipe[3] = 1; |
swizzle_pipe[4] = 3; |
swizzle_pipe[5] = 5; |
} |
break; |
case 8: |
if (force_no_swizzle) { |
swizzle_pipe[0] = 0; |
swizzle_pipe[1] = 1; |
swizzle_pipe[2] = 2; |
swizzle_pipe[3] = 3; |
swizzle_pipe[4] = 4; |
swizzle_pipe[5] = 5; |
swizzle_pipe[6] = 6; |
swizzle_pipe[7] = 7; |
} else { |
swizzle_pipe[0] = 0; |
swizzle_pipe[1] = 2; |
swizzle_pipe[2] = 4; |
swizzle_pipe[3] = 6; |
swizzle_pipe[4] = 1; |
swizzle_pipe[5] = 3; |
swizzle_pipe[6] = 5; |
swizzle_pipe[7] = 7; |
} |
break; |
} |
|
for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) { |
while (((1 << cur_backend) & enabled_backends_mask) == 0) |
cur_backend = (cur_backend + 1) % EVERGREEN_MAX_BACKENDS; |
|
backend_map |= (((cur_backend & 0xf) << (swizzle_pipe[cur_pipe] * 4))); |
|
cur_backend = (cur_backend + 1) % EVERGREEN_MAX_BACKENDS; |
} |
|
return backend_map; |
} |
|
static void evergreen_program_channel_remap(struct radeon_device *rdev) |
{ |
u32 tcp_chan_steer_lo, tcp_chan_steer_hi, mc_shared_chremap, tmp; |
|
tmp = RREG32(MC_SHARED_CHMAP); |
switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) { |
case 0: |
case 1: |
case 2: |
case 3: |
default: |
/* default mapping */ |
mc_shared_chremap = 0x00fac688; |
break; |
} |
|
switch (rdev->family) { |
case CHIP_HEMLOCK: |
case CHIP_CYPRESS: |
case CHIP_BARTS: |
tcp_chan_steer_lo = 0x54763210; |
tcp_chan_steer_hi = 0x0000ba98; |
break; |
case CHIP_JUNIPER: |
case CHIP_REDWOOD: |
case CHIP_CEDAR: |
case CHIP_PALM: |
case CHIP_SUMO: |
case CHIP_SUMO2: |
case CHIP_TURKS: |
case CHIP_CAICOS: |
default: |
tcp_chan_steer_lo = 0x76543210; |
tcp_chan_steer_hi = 0x0000ba98; |
break; |
} |
|
WREG32(TCP_CHAN_STEER_LO, tcp_chan_steer_lo); |
WREG32(TCP_CHAN_STEER_HI, tcp_chan_steer_hi); |
WREG32(MC_SHARED_CHREMAP, mc_shared_chremap); |
} |
|
static void evergreen_gpu_init(struct radeon_device *rdev) |
{ |
u32 cc_rb_backend_disable = 0; |
u32 cc_gc_shader_pipe_config; |
u32 gb_addr_config = 0; |
u32 gb_addr_config; |
u32 mc_shared_chmap, mc_arb_ramcfg; |
u32 gb_backend_map; |
u32 grbm_gfx_index; |
u32 sx_debug_1; |
u32 smx_dc_ctl0; |
u32 sq_config; |
1619,6 → 1613,7 |
u32 sq_stack_resource_mgmt_3; |
u32 vgt_cache_invalidation; |
u32 hdp_host_path_cntl, tmp; |
u32 disabled_rb_mask; |
int i, j, num_shader_engines, ps_thread_count; |
|
switch (rdev->family) { |
1643,6 → 1638,7 |
rdev->config.evergreen.sc_prim_fifo_size = 0x100; |
rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; |
rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; |
gb_addr_config = CYPRESS_GB_ADDR_CONFIG_GOLDEN; |
break; |
case CHIP_JUNIPER: |
rdev->config.evergreen.num_ses = 1; |
1664,6 → 1660,7 |
rdev->config.evergreen.sc_prim_fifo_size = 0x100; |
rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; |
rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; |
gb_addr_config = JUNIPER_GB_ADDR_CONFIG_GOLDEN; |
break; |
case CHIP_REDWOOD: |
rdev->config.evergreen.num_ses = 1; |
1685,6 → 1682,7 |
rdev->config.evergreen.sc_prim_fifo_size = 0x100; |
rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; |
rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; |
gb_addr_config = REDWOOD_GB_ADDR_CONFIG_GOLDEN; |
break; |
case CHIP_CEDAR: |
default: |
1707,6 → 1705,7 |
rdev->config.evergreen.sc_prim_fifo_size = 0x40; |
rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; |
rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; |
gb_addr_config = CEDAR_GB_ADDR_CONFIG_GOLDEN; |
break; |
case CHIP_PALM: |
rdev->config.evergreen.num_ses = 1; |
1728,6 → 1727,7 |
rdev->config.evergreen.sc_prim_fifo_size = 0x40; |
rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; |
rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; |
gb_addr_config = CEDAR_GB_ADDR_CONFIG_GOLDEN; |
break; |
case CHIP_SUMO: |
rdev->config.evergreen.num_ses = 1; |
1755,6 → 1755,7 |
rdev->config.evergreen.sc_prim_fifo_size = 0x40; |
rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; |
rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; |
gb_addr_config = REDWOOD_GB_ADDR_CONFIG_GOLDEN; |
break; |
case CHIP_SUMO2: |
rdev->config.evergreen.num_ses = 1; |
1776,6 → 1777,7 |
rdev->config.evergreen.sc_prim_fifo_size = 0x40; |
rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; |
rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; |
gb_addr_config = REDWOOD_GB_ADDR_CONFIG_GOLDEN; |
break; |
case CHIP_BARTS: |
rdev->config.evergreen.num_ses = 2; |
1797,6 → 1799,7 |
rdev->config.evergreen.sc_prim_fifo_size = 0x100; |
rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; |
rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; |
gb_addr_config = BARTS_GB_ADDR_CONFIG_GOLDEN; |
break; |
case CHIP_TURKS: |
rdev->config.evergreen.num_ses = 1; |
1818,6 → 1821,7 |
rdev->config.evergreen.sc_prim_fifo_size = 0x100; |
rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; |
rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; |
gb_addr_config = TURKS_GB_ADDR_CONFIG_GOLDEN; |
break; |
case CHIP_CAICOS: |
rdev->config.evergreen.num_ses = 1; |
1839,6 → 1843,7 |
rdev->config.evergreen.sc_prim_fifo_size = 0x40; |
rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; |
rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; |
gb_addr_config = CAICOS_GB_ADDR_CONFIG_GOLDEN; |
break; |
} |
|
1853,154 → 1858,16 |
|
WREG32(GRBM_CNTL, GRBM_READ_TIMEOUT(0xff)); |
|
cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & ~2; |
evergreen_fix_pci_max_read_req_size(rdev); |
|
cc_gc_shader_pipe_config |= |
INACTIVE_QD_PIPES((EVERGREEN_MAX_PIPES_MASK << rdev->config.evergreen.max_pipes) |
& EVERGREEN_MAX_PIPES_MASK); |
cc_gc_shader_pipe_config |= |
INACTIVE_SIMDS((EVERGREEN_MAX_SIMDS_MASK << rdev->config.evergreen.max_simds) |
& EVERGREEN_MAX_SIMDS_MASK); |
|
cc_rb_backend_disable = |
BACKEND_DISABLE((EVERGREEN_MAX_BACKENDS_MASK << rdev->config.evergreen.max_backends) |
& EVERGREEN_MAX_BACKENDS_MASK); |
|
|
mc_shared_chmap = RREG32(MC_SHARED_CHMAP); |
if (rdev->flags & RADEON_IS_IGP) |
if ((rdev->family == CHIP_PALM) || |
(rdev->family == CHIP_SUMO) || |
(rdev->family == CHIP_SUMO2)) |
mc_arb_ramcfg = RREG32(FUS_MC_ARB_RAMCFG); |
else |
mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); |
|
switch (rdev->config.evergreen.max_tile_pipes) { |
case 1: |
default: |
gb_addr_config |= NUM_PIPES(0); |
break; |
case 2: |
gb_addr_config |= NUM_PIPES(1); |
break; |
case 4: |
gb_addr_config |= NUM_PIPES(2); |
break; |
case 8: |
gb_addr_config |= NUM_PIPES(3); |
break; |
} |
|
gb_addr_config |= PIPE_INTERLEAVE_SIZE((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT); |
gb_addr_config |= BANK_INTERLEAVE_SIZE(0); |
gb_addr_config |= NUM_SHADER_ENGINES(rdev->config.evergreen.num_ses - 1); |
gb_addr_config |= SHADER_ENGINE_TILE_SIZE(1); |
gb_addr_config |= NUM_GPUS(0); /* Hemlock? */ |
gb_addr_config |= MULTI_GPU_TILE_SIZE(2); |
|
if (((mc_arb_ramcfg & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT) > 2) |
gb_addr_config |= ROW_SIZE(2); |
else |
gb_addr_config |= ROW_SIZE((mc_arb_ramcfg & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT); |
|
if (rdev->ddev->pdev->device == 0x689e) { |
u32 efuse_straps_4; |
u32 efuse_straps_3; |
u8 efuse_box_bit_131_124; |
|
WREG32(RCU_IND_INDEX, 0x204); |
efuse_straps_4 = RREG32(RCU_IND_DATA); |
WREG32(RCU_IND_INDEX, 0x203); |
efuse_straps_3 = RREG32(RCU_IND_DATA); |
efuse_box_bit_131_124 = (u8)(((efuse_straps_4 & 0xf) << 4) | ((efuse_straps_3 & 0xf0000000) >> 28)); |
|
switch(efuse_box_bit_131_124) { |
case 0x00: |
gb_backend_map = 0x76543210; |
break; |
case 0x55: |
gb_backend_map = 0x77553311; |
break; |
case 0x56: |
gb_backend_map = 0x77553300; |
break; |
case 0x59: |
gb_backend_map = 0x77552211; |
break; |
case 0x66: |
gb_backend_map = 0x77443300; |
break; |
case 0x99: |
gb_backend_map = 0x66552211; |
break; |
case 0x5a: |
gb_backend_map = 0x77552200; |
break; |
case 0xaa: |
gb_backend_map = 0x66442200; |
break; |
case 0x95: |
gb_backend_map = 0x66553311; |
break; |
default: |
DRM_ERROR("bad backend map, using default\n"); |
gb_backend_map = |
evergreen_get_tile_pipe_to_backend_map(rdev, |
rdev->config.evergreen.max_tile_pipes, |
rdev->config.evergreen.max_backends, |
((EVERGREEN_MAX_BACKENDS_MASK << |
rdev->config.evergreen.max_backends) & |
EVERGREEN_MAX_BACKENDS_MASK)); |
break; |
} |
} else if (rdev->ddev->pdev->device == 0x68b9) { |
u32 efuse_straps_3; |
u8 efuse_box_bit_127_124; |
|
WREG32(RCU_IND_INDEX, 0x203); |
efuse_straps_3 = RREG32(RCU_IND_DATA); |
efuse_box_bit_127_124 = (u8)((efuse_straps_3 & 0xF0000000) >> 28); |
|
switch(efuse_box_bit_127_124) { |
case 0x0: |
gb_backend_map = 0x00003210; |
break; |
case 0x5: |
case 0x6: |
case 0x9: |
case 0xa: |
gb_backend_map = 0x00003311; |
break; |
default: |
DRM_ERROR("bad backend map, using default\n"); |
gb_backend_map = |
evergreen_get_tile_pipe_to_backend_map(rdev, |
rdev->config.evergreen.max_tile_pipes, |
rdev->config.evergreen.max_backends, |
((EVERGREEN_MAX_BACKENDS_MASK << |
rdev->config.evergreen.max_backends) & |
EVERGREEN_MAX_BACKENDS_MASK)); |
break; |
} |
} else { |
switch (rdev->family) { |
case CHIP_CYPRESS: |
case CHIP_HEMLOCK: |
case CHIP_BARTS: |
gb_backend_map = 0x66442200; |
break; |
case CHIP_JUNIPER: |
gb_backend_map = 0x00002200; |
break; |
default: |
gb_backend_map = |
evergreen_get_tile_pipe_to_backend_map(rdev, |
rdev->config.evergreen.max_tile_pipes, |
rdev->config.evergreen.max_backends, |
((EVERGREEN_MAX_BACKENDS_MASK << |
rdev->config.evergreen.max_backends) & |
EVERGREEN_MAX_BACKENDS_MASK)); |
} |
} |
|
/* setup tiling info dword. gb_addr_config is not adequate since it does |
* not have bank info, so create a custom tiling dword. |
* bits 3:0 num_pipes |
2027,47 → 1894,62 |
/* num banks is 8 on all fusion asics. 0 = 4, 1 = 8, 2 = 16 */ |
if (rdev->flags & RADEON_IS_IGP) |
rdev->config.evergreen.tile_config |= 1 << 4; |
else |
else { |
switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { |
case 0: /* four banks */ |
rdev->config.evergreen.tile_config |= 0 << 4; |
break; |
case 1: /* eight banks */ |
rdev->config.evergreen.tile_config |= 1 << 4; |
break; |
case 2: /* sixteen banks */ |
default: |
rdev->config.evergreen.tile_config |= 2 << 4; |
break; |
} |
} |
rdev->config.evergreen.tile_config |= 0 << 8; |
rdev->config.evergreen.tile_config |= |
((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4; |
rdev->config.evergreen.tile_config |= |
((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT) << 8; |
rdev->config.evergreen.tile_config |= |
((gb_addr_config & 0x30000000) >> 28) << 12; |
|
rdev->config.evergreen.backend_map = gb_backend_map; |
WREG32(GB_BACKEND_MAP, gb_backend_map); |
WREG32(GB_ADDR_CONFIG, gb_addr_config); |
WREG32(DMIF_ADDR_CONFIG, gb_addr_config); |
WREG32(HDP_ADDR_CONFIG, gb_addr_config); |
num_shader_engines = (gb_addr_config & NUM_SHADER_ENGINES(3) >> 12) + 1; |
|
evergreen_program_channel_remap(rdev); |
if ((rdev->family >= CHIP_CEDAR) && (rdev->family <= CHIP_HEMLOCK)) { |
u32 efuse_straps_4; |
u32 efuse_straps_3; |
|
num_shader_engines = ((RREG32(GB_ADDR_CONFIG) & NUM_SHADER_ENGINES(3)) >> 12) + 1; |
grbm_gfx_index = INSTANCE_BROADCAST_WRITES; |
WREG32(RCU_IND_INDEX, 0x204); |
efuse_straps_4 = RREG32(RCU_IND_DATA); |
WREG32(RCU_IND_INDEX, 0x203); |
efuse_straps_3 = RREG32(RCU_IND_DATA); |
tmp = (((efuse_straps_4 & 0xf) << 4) | |
((efuse_straps_3 & 0xf0000000) >> 28)); |
} else { |
tmp = 0; |
for (i = (rdev->config.evergreen.num_ses - 1); i >= 0; i--) { |
u32 rb_disable_bitmap; |
|
for (i = 0; i < rdev->config.evergreen.num_ses; i++) { |
u32 rb = cc_rb_backend_disable | (0xf0 << 16); |
u32 sp = cc_gc_shader_pipe_config; |
u32 gfx = grbm_gfx_index | SE_INDEX(i); |
|
if (i == num_shader_engines) { |
rb |= BACKEND_DISABLE(EVERGREEN_MAX_BACKENDS_MASK); |
sp |= INACTIVE_SIMDS(EVERGREEN_MAX_SIMDS_MASK); |
WREG32(GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_INDEX(i)); |
WREG32(RLC_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_INDEX(i)); |
rb_disable_bitmap = (RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000) >> 16; |
tmp <<= 4; |
tmp |= rb_disable_bitmap; |
} |
} |
/* enabled rb are just the one not disabled :) */ |
disabled_rb_mask = tmp; |
|
WREG32(GRBM_GFX_INDEX, gfx); |
WREG32(RLC_GFX_INDEX, gfx); |
WREG32(GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES); |
WREG32(RLC_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES); |
|
WREG32(CC_RB_BACKEND_DISABLE, rb); |
WREG32(CC_SYS_RB_BACKEND_DISABLE, rb); |
WREG32(GC_USER_RB_BACKEND_DISABLE, rb); |
WREG32(CC_GC_SHADER_PIPE_CONFIG, sp); |
} |
WREG32(GB_ADDR_CONFIG, gb_addr_config); |
WREG32(DMIF_ADDR_CONFIG, gb_addr_config); |
WREG32(HDP_ADDR_CONFIG, gb_addr_config); |
|
grbm_gfx_index |= SE_BROADCAST_WRITES; |
WREG32(GRBM_GFX_INDEX, grbm_gfx_index); |
WREG32(RLC_GFX_INDEX, grbm_gfx_index); |
tmp = gb_addr_config & NUM_PIPES_MASK; |
tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.evergreen.max_backends, |
EVERGREEN_MAX_BACKENDS, disabled_rb_mask); |
WREG32(GB_BACKEND_MAP, tmp); |
|
WREG32(CGTS_SYS_TCC_DISABLE, 0); |
WREG32(CGTS_TCC_DISABLE, 0); |
2095,6 → 1977,9 |
smx_dc_ctl0 |= NUMBER_OF_SETS(rdev->config.evergreen.sx_num_of_sets); |
WREG32(SMX_DC_CTL0, smx_dc_ctl0); |
|
if (rdev->family <= CHIP_SUMO2) |
WREG32(SMX_SAR_CTL0, 0x00010000); |
|
WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_size / 4) - 1) | |
POSITION_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_pos_size / 4) - 1) | |
SMX_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_smx_size / 4) - 1))); |
2260,7 → 2145,9 |
|
/* Get VRAM informations */ |
rdev->mc.vram_is_ddr = true; |
if (rdev->flags & RADEON_IS_IGP) |
if ((rdev->family == CHIP_PALM) || |
(rdev->family == CHIP_SUMO) || |
(rdev->family == CHIP_SUMO2)) |
tmp = RREG32(FUS_MC_ARB_RAMCFG); |
else |
tmp = RREG32(MC_ARB_RAMCFG); |
2292,12 → 2179,14 |
rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0); |
rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0); |
/* Setup GPU memory space */ |
if (rdev->flags & RADEON_IS_IGP) { |
if ((rdev->family == CHIP_PALM) || |
(rdev->family == CHIP_SUMO) || |
(rdev->family == CHIP_SUMO2)) { |
/* size in bytes on fusion */ |
rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); |
rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); |
} else { |
/* size in MB on evergreen */ |
/* size in MB on evergreen/cayman/tn */ |
rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; |
rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; |
} |
2308,13 → 2197,11 |
return 0; |
} |
|
bool evergreen_gpu_is_lockup(struct radeon_device *rdev) |
bool evergreen_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) |
{ |
u32 srbm_status; |
u32 grbm_status; |
u32 grbm_status_se0, grbm_status_se1; |
struct r100_gpu_lockup *lockup = &rdev->config.evergreen.lockup; |
int r; |
|
srbm_status = RREG32(SRBM_STATUS); |
grbm_status = RREG32(GRBM_STATUS); |
2321,20 → 2208,13 |
grbm_status_se0 = RREG32(GRBM_STATUS_SE0); |
grbm_status_se1 = RREG32(GRBM_STATUS_SE1); |
if (!(grbm_status & GUI_ACTIVE)) { |
r100_gpu_lockup_update(lockup, &rdev->cp); |
radeon_ring_lockup_update(ring); |
return false; |
} |
/* force CP activities */ |
r = radeon_ring_lock(rdev, 2); |
if (!r) { |
/* PACKET2 NOP */ |
radeon_ring_write(rdev, 0x80000000); |
radeon_ring_write(rdev, 0x80000000); |
radeon_ring_unlock_commit(rdev); |
radeon_ring_force_activity(rdev, ring); |
return radeon_ring_test_lockup(rdev, ring); |
} |
rdev->cp.rptr = RREG32(CP_RB_RPTR); |
return r100_gpu_cp_is_lockup(rdev, lockup, &rdev->cp); |
} |
|
static int evergreen_gpu_soft_reset(struct radeon_device *rdev) |
{ |
2353,6 → 2233,14 |
RREG32(GRBM_STATUS_SE1)); |
dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", |
RREG32(SRBM_STATUS)); |
dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", |
RREG32(CP_STALLED_STAT1)); |
dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", |
RREG32(CP_STALLED_STAT2)); |
dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", |
RREG32(CP_BUSY_STAT)); |
dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", |
RREG32(CP_STAT)); |
evergreen_mc_stop(rdev, &save); |
if (evergreen_mc_wait_for_idle(rdev)) { |
dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); |
2390,6 → 2278,14 |
RREG32(GRBM_STATUS_SE1)); |
dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", |
RREG32(SRBM_STATUS)); |
dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", |
RREG32(CP_STALLED_STAT1)); |
dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", |
RREG32(CP_STALLED_STAT2)); |
dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", |
RREG32(CP_BUSY_STAT)); |
dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", |
RREG32(CP_STAT)); |
evergreen_mc_resume(rdev, &save); |
return 0; |
} |
2403,28 → 2299,22 |
|
u32 evergreen_get_vblank_counter(struct radeon_device *rdev, int crtc) |
{ |
switch (crtc) { |
case 0: |
return RREG32(CRTC_STATUS_FRAME_COUNT + EVERGREEN_CRTC0_REGISTER_OFFSET); |
case 1: |
return RREG32(CRTC_STATUS_FRAME_COUNT + EVERGREEN_CRTC1_REGISTER_OFFSET); |
case 2: |
return RREG32(CRTC_STATUS_FRAME_COUNT + EVERGREEN_CRTC2_REGISTER_OFFSET); |
case 3: |
return RREG32(CRTC_STATUS_FRAME_COUNT + EVERGREEN_CRTC3_REGISTER_OFFSET); |
case 4: |
return RREG32(CRTC_STATUS_FRAME_COUNT + EVERGREEN_CRTC4_REGISTER_OFFSET); |
case 5: |
return RREG32(CRTC_STATUS_FRAME_COUNT + EVERGREEN_CRTC5_REGISTER_OFFSET); |
default: |
if (crtc >= rdev->num_crtc) |
return 0; |
else |
return RREG32(CRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]); |
} |
} |
|
void evergreen_disable_interrupt_state(struct radeon_device *rdev) |
{ |
u32 tmp; |
|
if (rdev->family >= CHIP_CAYMAN) { |
cayman_cp_int_cntl_setup(rdev, 0, |
CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); |
cayman_cp_int_cntl_setup(rdev, 1, 0); |
cayman_cp_int_cntl_setup(rdev, 2, 0); |
} else |
WREG32(CP_INT_CNTL, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); |
WREG32(GRBM_INT_CNTL, 0); |
WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); |
2449,6 → 2339,8 |
WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); |
} |
|
/* only one DAC on DCE6 */ |
if (!ASIC_IS_DCE6(rdev)) |
WREG32(DACA_AUTODETECT_INT_CONTROL, 0); |
WREG32(DACB_AUTODETECT_INT_CONTROL, 0); |
|
2470,10 → 2362,12 |
int evergreen_irq_set(struct radeon_device *rdev) |
{ |
u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE; |
u32 cp_int_cntl1 = 0, cp_int_cntl2 = 0; |
u32 crtc1 = 0, crtc2 = 0, crtc3 = 0, crtc4 = 0, crtc5 = 0, crtc6 = 0; |
u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6; |
u32 grbm_int_cntl = 0; |
u32 grph1 = 0, grph2 = 0, grph3 = 0, grph4 = 0, grph5 = 0, grph6 = 0; |
u32 afmt1 = 0, afmt2 = 0, afmt3 = 0, afmt4 = 0, afmt5 = 0, afmt6 = 0; |
|
if (!rdev->irq.installed) { |
WARN(1, "Can't enable IRQ/MSI because no handler is installed\n"); |
2494,38 → 2388,62 |
hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN; |
hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN; |
|
if (rdev->irq.sw_int) { |
DRM_DEBUG("evergreen_irq_set: sw int\n"); |
afmt1 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK; |
afmt2 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK; |
afmt3 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK; |
afmt4 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK; |
afmt5 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK; |
afmt6 = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET) & ~AFMT_AZ_FORMAT_WTRIG_MASK; |
|
if (rdev->family >= CHIP_CAYMAN) { |
/* enable CP interrupts on all rings */ |
if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { |
DRM_DEBUG("evergreen_irq_set: sw int gfx\n"); |
cp_int_cntl |= TIME_STAMP_INT_ENABLE; |
} |
if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_CP1_INDEX])) { |
DRM_DEBUG("evergreen_irq_set: sw int cp1\n"); |
cp_int_cntl1 |= TIME_STAMP_INT_ENABLE; |
} |
if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_CP2_INDEX])) { |
DRM_DEBUG("evergreen_irq_set: sw int cp2\n"); |
cp_int_cntl2 |= TIME_STAMP_INT_ENABLE; |
} |
} else { |
if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { |
DRM_DEBUG("evergreen_irq_set: sw int gfx\n"); |
cp_int_cntl |= RB_INT_ENABLE; |
cp_int_cntl |= TIME_STAMP_INT_ENABLE; |
} |
} |
|
if (rdev->irq.crtc_vblank_int[0] || |
rdev->irq.pflip[0]) { |
atomic_read(&rdev->irq.pflip[0])) { |
DRM_DEBUG("evergreen_irq_set: vblank 0\n"); |
crtc1 |= VBLANK_INT_MASK; |
} |
if (rdev->irq.crtc_vblank_int[1] || |
rdev->irq.pflip[1]) { |
atomic_read(&rdev->irq.pflip[1])) { |
DRM_DEBUG("evergreen_irq_set: vblank 1\n"); |
crtc2 |= VBLANK_INT_MASK; |
} |
if (rdev->irq.crtc_vblank_int[2] || |
rdev->irq.pflip[2]) { |
atomic_read(&rdev->irq.pflip[2])) { |
DRM_DEBUG("evergreen_irq_set: vblank 2\n"); |
crtc3 |= VBLANK_INT_MASK; |
} |
if (rdev->irq.crtc_vblank_int[3] || |
rdev->irq.pflip[3]) { |
atomic_read(&rdev->irq.pflip[3])) { |
DRM_DEBUG("evergreen_irq_set: vblank 3\n"); |
crtc4 |= VBLANK_INT_MASK; |
} |
if (rdev->irq.crtc_vblank_int[4] || |
rdev->irq.pflip[4]) { |
atomic_read(&rdev->irq.pflip[4])) { |
DRM_DEBUG("evergreen_irq_set: vblank 4\n"); |
crtc5 |= VBLANK_INT_MASK; |
} |
if (rdev->irq.crtc_vblank_int[5] || |
rdev->irq.pflip[5]) { |
atomic_read(&rdev->irq.pflip[5])) { |
DRM_DEBUG("evergreen_irq_set: vblank 5\n"); |
crtc6 |= VBLANK_INT_MASK; |
} |
2553,11 → 2471,36 |
DRM_DEBUG("evergreen_irq_set: hpd 6\n"); |
hpd6 |= DC_HPDx_INT_EN; |
} |
if (rdev->irq.gui_idle) { |
DRM_DEBUG("gui idle\n"); |
grbm_int_cntl |= GUI_IDLE_INT_ENABLE; |
if (rdev->irq.afmt[0]) { |
DRM_DEBUG("evergreen_irq_set: hdmi 0\n"); |
afmt1 |= AFMT_AZ_FORMAT_WTRIG_MASK; |
} |
if (rdev->irq.afmt[1]) { |
DRM_DEBUG("evergreen_irq_set: hdmi 1\n"); |
afmt2 |= AFMT_AZ_FORMAT_WTRIG_MASK; |
} |
if (rdev->irq.afmt[2]) { |
DRM_DEBUG("evergreen_irq_set: hdmi 2\n"); |
afmt3 |= AFMT_AZ_FORMAT_WTRIG_MASK; |
} |
if (rdev->irq.afmt[3]) { |
DRM_DEBUG("evergreen_irq_set: hdmi 3\n"); |
afmt4 |= AFMT_AZ_FORMAT_WTRIG_MASK; |
} |
if (rdev->irq.afmt[4]) { |
DRM_DEBUG("evergreen_irq_set: hdmi 4\n"); |
afmt5 |= AFMT_AZ_FORMAT_WTRIG_MASK; |
} |
if (rdev->irq.afmt[5]) { |
DRM_DEBUG("evergreen_irq_set: hdmi 5\n"); |
afmt6 |= AFMT_AZ_FORMAT_WTRIG_MASK; |
} |
|
if (rdev->family >= CHIP_CAYMAN) { |
cayman_cp_int_cntl_setup(rdev, 0, cp_int_cntl); |
cayman_cp_int_cntl_setup(rdev, 1, cp_int_cntl1); |
cayman_cp_int_cntl_setup(rdev, 2, cp_int_cntl2); |
} else |
WREG32(CP_INT_CNTL, cp_int_cntl); |
WREG32(GRBM_INT_CNTL, grbm_int_cntl); |
|
2590,10 → 2533,17 |
WREG32(DC_HPD5_INT_CONTROL, hpd5); |
WREG32(DC_HPD6_INT_CONTROL, hpd6); |
|
WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, afmt1); |
WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, afmt2); |
WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, afmt3); |
WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, afmt4); |
WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, afmt5); |
WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, afmt6); |
|
return 0; |
} |
|
static inline void evergreen_irq_ack(struct radeon_device *rdev) |
static void evergreen_irq_ack(struct radeon_device *rdev) |
{ |
u32 tmp; |
|
2614,6 → 2564,13 |
rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET); |
} |
|
rdev->irq.stat_regs.evergreen.afmt_status1 = RREG32(AFMT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET); |
rdev->irq.stat_regs.evergreen.afmt_status2 = RREG32(AFMT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET); |
rdev->irq.stat_regs.evergreen.afmt_status3 = RREG32(AFMT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET); |
rdev->irq.stat_regs.evergreen.afmt_status4 = RREG32(AFMT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET); |
rdev->irq.stat_regs.evergreen.afmt_status5 = RREG32(AFMT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET); |
rdev->irq.stat_regs.evergreen.afmt_status6 = RREG32(AFMT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET); |
|
if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED) |
WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); |
if (rdev->irq.stat_regs.evergreen.d2grph_int & GRPH_PFLIP_INT_OCCURRED) |
2687,9 → 2644,55 |
tmp |= DC_HPDx_INT_ACK; |
WREG32(DC_HPD6_INT_CONTROL, tmp); |
} |
if (rdev->irq.stat_regs.evergreen.afmt_status1 & AFMT_AZ_FORMAT_WTRIG) { |
tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET); |
tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; |
WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, tmp); |
} |
static inline u32 evergreen_get_ih_wptr(struct radeon_device *rdev) |
if (rdev->irq.stat_regs.evergreen.afmt_status2 & AFMT_AZ_FORMAT_WTRIG) { |
tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); |
tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; |
WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, tmp); |
} |
if (rdev->irq.stat_regs.evergreen.afmt_status3 & AFMT_AZ_FORMAT_WTRIG) { |
tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET); |
tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; |
WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, tmp); |
} |
if (rdev->irq.stat_regs.evergreen.afmt_status4 & AFMT_AZ_FORMAT_WTRIG) { |
tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET); |
tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; |
WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, tmp); |
} |
if (rdev->irq.stat_regs.evergreen.afmt_status5 & AFMT_AZ_FORMAT_WTRIG) { |
tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET); |
tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; |
WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, tmp); |
} |
if (rdev->irq.stat_regs.evergreen.afmt_status6 & AFMT_AZ_FORMAT_WTRIG) { |
tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); |
tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; |
WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, tmp); |
} |
} |
|
static void evergreen_irq_disable(struct radeon_device *rdev) |
{ |
r600_disable_interrupts(rdev); |
/* Wait and acknowledge irq */ |
mdelay(1); |
evergreen_irq_ack(rdev); |
evergreen_disable_interrupt_state(rdev); |
} |
|
void evergreen_irq_suspend(struct radeon_device *rdev) |
{ |
evergreen_irq_disable(rdev); |
r600_rlc_stop(rdev); |
} |
|
static u32 evergreen_get_ih_wptr(struct radeon_device *rdev) |
{ |
u32 wptr, tmp; |
|
if (rdev->wb.enabled) |
2718,22 → 2721,22 |
u32 rptr; |
u32 src_id, src_data; |
u32 ring_index; |
unsigned long flags; |
bool queue_hotplug = false; |
bool queue_hdmi = false; |
|
if (!rdev->ih.enabled || rdev->shutdown) |
return IRQ_NONE; |
|
wptr = evergreen_get_ih_wptr(rdev); |
|
restart_ih: |
/* is somebody else already processing irqs? */ |
if (atomic_xchg(&rdev->ih.lock, 1)) |
return IRQ_NONE; |
|
rptr = rdev->ih.rptr; |
DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); |
|
spin_lock_irqsave(&rdev->ih.lock, flags); |
if (rptr == wptr) { |
spin_unlock_irqrestore(&rdev->ih.lock, flags); |
return IRQ_NONE; |
} |
restart_ih: |
/* Order reading of wptr vs. reading of IH ring data */ |
rmb(); |
|
2740,7 → 2743,6 |
/* display interrupts */ |
evergreen_irq_ack(rdev); |
|
rdev->ih.wptr = wptr; |
while (rptr != wptr) { |
/* wptr/rptr are in bytes! */ |
ring_index = rptr / 4; |
2953,20 → 2955,80 |
break; |
} |
break; |
case 44: /* hdmi */ |
switch (src_data) { |
case 0: |
if (rdev->irq.stat_regs.evergreen.afmt_status1 & AFMT_AZ_FORMAT_WTRIG) { |
rdev->irq.stat_regs.evergreen.afmt_status1 &= ~AFMT_AZ_FORMAT_WTRIG; |
queue_hdmi = true; |
DRM_DEBUG("IH: HDMI0\n"); |
} |
break; |
case 1: |
if (rdev->irq.stat_regs.evergreen.afmt_status2 & AFMT_AZ_FORMAT_WTRIG) { |
rdev->irq.stat_regs.evergreen.afmt_status2 &= ~AFMT_AZ_FORMAT_WTRIG; |
queue_hdmi = true; |
DRM_DEBUG("IH: HDMI1\n"); |
} |
break; |
case 2: |
if (rdev->irq.stat_regs.evergreen.afmt_status3 & AFMT_AZ_FORMAT_WTRIG) { |
rdev->irq.stat_regs.evergreen.afmt_status3 &= ~AFMT_AZ_FORMAT_WTRIG; |
queue_hdmi = true; |
DRM_DEBUG("IH: HDMI2\n"); |
} |
break; |
case 3: |
if (rdev->irq.stat_regs.evergreen.afmt_status4 & AFMT_AZ_FORMAT_WTRIG) { |
rdev->irq.stat_regs.evergreen.afmt_status4 &= ~AFMT_AZ_FORMAT_WTRIG; |
queue_hdmi = true; |
DRM_DEBUG("IH: HDMI3\n"); |
} |
break; |
case 4: |
if (rdev->irq.stat_regs.evergreen.afmt_status5 & AFMT_AZ_FORMAT_WTRIG) { |
rdev->irq.stat_regs.evergreen.afmt_status5 &= ~AFMT_AZ_FORMAT_WTRIG; |
queue_hdmi = true; |
DRM_DEBUG("IH: HDMI4\n"); |
} |
break; |
case 5: |
if (rdev->irq.stat_regs.evergreen.afmt_status6 & AFMT_AZ_FORMAT_WTRIG) { |
rdev->irq.stat_regs.evergreen.afmt_status6 &= ~AFMT_AZ_FORMAT_WTRIG; |
queue_hdmi = true; |
DRM_DEBUG("IH: HDMI5\n"); |
} |
break; |
default: |
DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); |
break; |
} |
break; |
case 176: /* CP_INT in ring buffer */ |
case 177: /* CP_INT in IB1 */ |
case 178: /* CP_INT in IB2 */ |
DRM_DEBUG("IH: CP int: 0x%08x\n", src_data); |
radeon_fence_process(rdev); |
radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); |
break; |
case 181: /* CP EOP event */ |
DRM_DEBUG("IH: CP EOP\n"); |
radeon_fence_process(rdev); |
if (rdev->family >= CHIP_CAYMAN) { |
switch (src_data) { |
case 0: |
radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); |
break; |
case 1: |
radeon_fence_process(rdev, CAYMAN_RING_TYPE_CP1_INDEX); |
break; |
case 2: |
radeon_fence_process(rdev, CAYMAN_RING_TYPE_CP2_INDEX); |
break; |
} |
} else |
radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); |
break; |
case 233: /* GUI IDLE */ |
DRM_DEBUG("IH: GUI idle\n"); |
rdev->pm.gui_idle = true; |
// wake_up(&rdev->irq.idle_queue); |
break; |
default: |
DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
2977,24 → 3039,24 |
rptr += 16; |
rptr &= rdev->ih.ptr_mask; |
} |
rdev->ih.rptr = rptr; |
WREG32(IH_RB_RPTR, rdev->ih.rptr); |
atomic_set(&rdev->ih.lock, 0); |
|
/* make sure wptr hasn't changed while processing */ |
wptr = evergreen_get_ih_wptr(rdev); |
if (wptr != rdev->ih.wptr) |
if (wptr != rptr) |
goto restart_ih; |
// if (queue_hotplug) |
// schedule_work(&rdev->hotplug_work); |
rdev->ih.rptr = rptr; |
WREG32(IH_RB_RPTR, rdev->ih.rptr); |
spin_unlock_irqrestore(&rdev->ih.lock, flags); |
|
return IRQ_HANDLED; |
} |
|
static int evergreen_startup(struct radeon_device *rdev) |
{ |
struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; |
int r; |
|
/* enable pcie gen2 link */ |
if (!ASIC_IS_DCE5(rdev)) |
evergreen_pcie_gen2_enable(rdev); |
|
if (ASIC_IS_DCE5(rdev)) { |
3020,6 → 3082,10 |
} |
} |
|
r = r600_vram_scratch_init(rdev); |
if (r) |
return r; |
|
evergreen_mc_program(rdev); |
if (rdev->flags & RADEON_IS_AGP) { |
evergreen_agp_enable(rdev); |
3032,8 → 3098,8 |
|
r = evergreen_blit_init(rdev); |
if (r) { |
evergreen_blit_fini(rdev); |
rdev->asic->copy = NULL; |
// r600_blit_fini(rdev); |
rdev->asic->copy.copy = NULL; |
dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); |
} |
|
3051,7 → 3117,9 |
} |
evergreen_irq_set(rdev); |
|
r = radeon_ring_init(rdev, rdev->cp.ring_size); |
r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, |
R600_CP_RB_RPTR, R600_CP_RB_WPTR, |
0, 0xfffff, RADEON_CP_PACKET2); |
if (r) |
return r; |
r = evergreen_cp_load_microcode(rdev); |
3066,8 → 3134,8 |
|
|
|
#if 0 |
|
|
int evergreen_copy_blit(struct radeon_device *rdev, |
uint64_t src_offset, uint64_t dst_offset, |
unsigned num_pages, struct radeon_fence *fence) |
3088,6 → 3156,7 |
mutex_unlock(&rdev->r600_blit.mutex); |
return 0; |
} |
#endif |
|
/* Plan is to move initialization in that function and use |
* helper function so that radeon_device_init pretty much |
3099,10 → 3168,6 |
{ |
int r; |
|
/* This don't do much */ |
r = radeon_gem_init(rdev); |
if (r) |
return r; |
/* Read BIOS */ |
if (!radeon_get_bios(rdev)) { |
if (ASIC_IS_AVIVO(rdev)) |
3159,8 → 3224,8 |
if (r) |
return r; |
|
rdev->cp.ring_obj = NULL; |
r600_ring_init(rdev, 1024 * 1024); |
rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL; |
r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024); |
|
rdev->ih.ring_obj = NULL; |
r600_ih_ring_init(rdev, 64 * 1024); |
3175,25 → 3240,26 |
dev_err(rdev->dev, "disabling GPU acceleration\n"); |
rdev->accel_working = false; |
} |
if (rdev->accel_working) { |
r = radeon_ib_pool_init(rdev); |
if (r) { |
DRM_ERROR("radeon: failed initializing IB pool (%d).\n", r); |
rdev->accel_working = false; |
|
/* Don't start up if the MC ucode is missing on BTC parts. |
* The default clocks and voltages before the MC ucode |
* is loaded are not suffient for advanced operations. |
*/ |
if (ASIC_IS_DCE5(rdev)) { |
if (!rdev->mc_fw && !(rdev->flags & RADEON_IS_IGP)) { |
DRM_ERROR("radeon: MC ucode required for NI+.\n"); |
return -EINVAL; |
} |
r = r600_ib_test(rdev); |
if (r) { |
DRM_ERROR("radeon: failed testing IB (%d).\n", r); |
rdev->accel_working = false; |
} |
} |
|
return 0; |
} |
|
|
static void evergreen_pcie_gen2_enable(struct radeon_device *rdev) |
void evergreen_pcie_gen2_enable(struct radeon_device *rdev) |
{ |
u32 link_width_cntl, speed_cntl; |
u32 link_width_cntl, speed_cntl, mask; |
int ret; |
|
if (radeon_pcie_gen2 == 0) |
return; |
3208,7 → 3274,21 |
if (ASIC_IS_X2(rdev)) |
return; |
|
ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask); |
if (ret != 0) |
return; |
|
if (!(mask & DRM_PCIE_SPEED_50)) |
return; |
|
speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); |
if (speed_cntl & LC_CURRENT_DATA_RATE) { |
DRM_INFO("PCIE gen 2 link speeds already enabled\n"); |
return; |
} |
|
DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n"); |
|
if ((speed_cntl & LC_OTHER_SIDE_EVER_SENT_GEN2) || |
(speed_cntl & LC_OTHER_SIDE_SUPPORTS_GEN2)) { |
|