29,28 → 29,40 |
#include "drmP.h" |
#include "drm.h" |
#include "radeon_drm.h" |
#include "radeon_microcode.h" |
#include "radeon_reg.h" |
#include "radeon.h" |
#include "r100d.h" |
#include "rs100d.h" |
#include "rv200d.h" |
#include "rv250d.h" |
|
#include <linux/firmware.h> |
|
#include "r100_reg_safe.h" |
#include "rn50_reg_safe.h" |
|
/* Firmware Names */ |
#define FIRMWARE_R100 "radeon/R100_cp.bin" |
#define FIRMWARE_R200 "radeon/R200_cp.bin" |
#define FIRMWARE_R300 "radeon/R300_cp.bin" |
#define FIRMWARE_R420 "radeon/R420_cp.bin" |
#define FIRMWARE_RS690 "radeon/RS690_cp.bin" |
#define FIRMWARE_RS600 "radeon/RS600_cp.bin" |
#define FIRMWARE_R520 "radeon/R520_cp.bin" |
|
MODULE_FIRMWARE(FIRMWARE_R100); |
MODULE_FIRMWARE(FIRMWARE_R200); |
MODULE_FIRMWARE(FIRMWARE_R300); |
MODULE_FIRMWARE(FIRMWARE_R420); |
MODULE_FIRMWARE(FIRMWARE_RS690); |
MODULE_FIRMWARE(FIRMWARE_RS600); |
MODULE_FIRMWARE(FIRMWARE_R520); |
|
|
/* This files gather functions specifics to: |
* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 |
* |
* Some of these functions might be used by newer ASICs. |
*/ |
int r200_init(struct radeon_device *rdev); |
void r100_hdp_reset(struct radeon_device *rdev); |
void r100_gpu_init(struct radeon_device *rdev); |
int r100_gui_wait_for_idle(struct radeon_device *rdev); |
int r100_mc_wait_for_idle(struct radeon_device *rdev); |
void r100_gpu_wait_for_vsync(struct radeon_device *rdev); |
void r100_gpu_wait_for_vsync2(struct radeon_device *rdev); |
int r100_debugfs_mc_info_init(struct radeon_device *rdev); |
|
|
/* |
* PCI GART |
*/ |
131,133 → 143,31 |
} |
|
|
/* |
* MC |
*/ |
void r100_mc_disable_clients(struct radeon_device *rdev) |
void r100_irq_disable(struct radeon_device *rdev) |
{ |
uint32_t ov0_scale_cntl, crtc_ext_cntl, crtc_gen_cntl, crtc2_gen_cntl; |
u32 tmp; |
|
/* FIXME: is this function correct for rs100,rs200,rs300 ? */ |
if (r100_gui_wait_for_idle(rdev)) { |
printk(KERN_WARNING "Failed to wait GUI idle while " |
"programming pipes. Bad things might happen.\n"); |
WREG32(R_000040_GEN_INT_CNTL, 0); |
/* Wait and acknowledge irq */ |
mdelay(1); |
tmp = RREG32(R_000044_GEN_INT_STATUS); |
WREG32(R_000044_GEN_INT_STATUS, tmp); |
} |
|
/* stop display and memory access */ |
ov0_scale_cntl = RREG32(RADEON_OV0_SCALE_CNTL); |
WREG32(RADEON_OV0_SCALE_CNTL, ov0_scale_cntl & ~RADEON_SCALER_ENABLE); |
crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); |
WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl | RADEON_CRTC_DISPLAY_DIS); |
crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL); |
|
r100_gpu_wait_for_vsync(rdev); |
|
WREG32(RADEON_CRTC_GEN_CNTL, |
(crtc_gen_cntl & ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_ICON_EN)) | |
RADEON_CRTC_DISP_REQ_EN_B | RADEON_CRTC_EXT_DISP_EN); |
|
if (!(rdev->flags & RADEON_SINGLE_CRTC)) { |
crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); |
|
r100_gpu_wait_for_vsync2(rdev); |
WREG32(RADEON_CRTC2_GEN_CNTL, |
(crtc2_gen_cntl & |
~(RADEON_CRTC2_CUR_EN | RADEON_CRTC2_ICON_EN)) | |
RADEON_CRTC2_DISP_REQ_EN_B); |
} |
|
udelay(500); |
} |
|
void r100_mc_setup(struct radeon_device *rdev) |
static inline uint32_t r100_irq_ack(struct radeon_device *rdev) |
{ |
uint32_t tmp; |
int r; |
uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS); |
uint32_t irq_mask = RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT | |
RADEON_CRTC2_VBLANK_STAT; |
|
r = r100_debugfs_mc_info_init(rdev); |
if (r) { |
DRM_ERROR("Failed to register debugfs file for R100 MC !\n"); |
if (irqs) { |
WREG32(RADEON_GEN_INT_STATUS, irqs); |
} |
/* Write VRAM size in case we are limiting it */ |
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); |
/* Novell bug 204882 for RN50/M6/M7 with 8/16/32MB VRAM, |
* if the aperture is 64MB but we have 32MB VRAM |
* we report only 32MB VRAM but we have to set MC_FB_LOCATION |
* to 64MB, otherwise the gpu accidentially dies */ |
tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; |
tmp = REG_SET(RADEON_MC_FB_TOP, tmp >> 16); |
tmp |= REG_SET(RADEON_MC_FB_START, rdev->mc.vram_location >> 16); |
WREG32(RADEON_MC_FB_LOCATION, tmp); |
|
/* Enable bus mastering */ |
tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; |
WREG32(RADEON_BUS_CNTL, tmp); |
|
if (rdev->flags & RADEON_IS_AGP) { |
tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; |
tmp = REG_SET(RADEON_MC_AGP_TOP, tmp >> 16); |
tmp |= REG_SET(RADEON_MC_AGP_START, rdev->mc.gtt_location >> 16); |
WREG32(RADEON_MC_AGP_LOCATION, tmp); |
WREG32(RADEON_AGP_BASE, rdev->mc.agp_base); |
} else { |
WREG32(RADEON_MC_AGP_LOCATION, 0x0FFFFFFF); |
WREG32(RADEON_AGP_BASE, 0); |
return irqs & irq_mask; |
} |
|
tmp = RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL; |
tmp |= (7 << 28); |
WREG32(RADEON_HOST_PATH_CNTL, tmp | RADEON_HDP_SOFT_RESET | RADEON_HDP_READ_BUFFER_INVALIDATE); |
(void)RREG32(RADEON_HOST_PATH_CNTL); |
WREG32(RADEON_HOST_PATH_CNTL, tmp); |
(void)RREG32(RADEON_HOST_PATH_CNTL); |
} |
|
int r100_mc_init(struct radeon_device *rdev) |
{ |
int r; |
|
if (r100_debugfs_rbbm_init(rdev)) { |
DRM_ERROR("Failed to register debugfs file for RBBM !\n"); |
} |
|
r100_gpu_init(rdev); |
/* Disable gart which also disable out of gart access */ |
r100_pci_gart_disable(rdev); |
|
/* Setup GPU memory space */ |
rdev->mc.gtt_location = 0xFFFFFFFFUL; |
r = radeon_mc_setup(rdev); |
if (r) { |
return r; |
} |
|
r100_mc_disable_clients(rdev); |
if (r100_mc_wait_for_idle(rdev)) { |
printk(KERN_WARNING "Failed to wait MC idle while " |
"programming pipes. Bad things might happen.\n"); |
} |
|
r100_mc_setup(rdev); |
return 0; |
} |
|
void r100_mc_fini(struct radeon_device *rdev) |
{ |
} |
|
u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc) |
{ |
if (crtc == 0) |
return RREG32(RADEON_CRTC_CRNT_FRAME); |
else |
return RREG32(RADEON_CRTC2_CRNT_FRAME); |
} |
|
|
/* |
* Fence emission |
*/ |
void r100_fence_ring_emit(struct radeon_device *rdev, |
struct radeon_fence *fence) |
{ |
402,9 → 312,7 |
|
#endif |
|
/* |
* CP |
*/ |
|
static int r100_cp_wait_for_idle(struct radeon_device *rdev) |
{ |
unsigned i; |
437,33 → 345,33 |
radeon_ring_unlock_commit(rdev); |
} |
|
static void r100_cp_load_microcode(struct radeon_device *rdev) |
|
/* Load the microcode for the CP */ |
static int r100_cp_init_microcode(struct radeon_device *rdev) |
{ |
int i; |
struct platform_device *pdev; |
const char *fw_name = NULL; |
int err; |
|
if (r100_gui_wait_for_idle(rdev)) { |
printk(KERN_WARNING "Failed to wait GUI idle while " |
"programming pipes. Bad things might happen.\n"); |
} |
DRM_DEBUG("\n"); |
|
WREG32(RADEON_CP_ME_RAM_ADDR, 0); |
// pdev = platform_device_register_simple("radeon_cp", 0, NULL, 0); |
// err = IS_ERR(pdev); |
// if (err) { |
// printk(KERN_ERR "radeon_cp: Failed to register firmware\n"); |
// return -EINVAL; |
// } |
if ((rdev->family == CHIP_R100) || (rdev->family == CHIP_RV100) || |
(rdev->family == CHIP_RV200) || (rdev->family == CHIP_RS100) || |
(rdev->family == CHIP_RS200)) { |
DRM_INFO("Loading R100 Microcode\n"); |
for (i = 0; i < 256; i++) { |
WREG32(RADEON_CP_ME_RAM_DATAH, R100_cp_microcode[i][1]); |
WREG32(RADEON_CP_ME_RAM_DATAL, R100_cp_microcode[i][0]); |
} |
fw_name = FIRMWARE_R100; |
} else if ((rdev->family == CHIP_R200) || |
(rdev->family == CHIP_RV250) || |
(rdev->family == CHIP_RV280) || |
(rdev->family == CHIP_RS300)) { |
DRM_INFO("Loading R200 Microcode\n"); |
for (i = 0; i < 256; i++) { |
WREG32(RADEON_CP_ME_RAM_DATAH, R200_cp_microcode[i][1]); |
WREG32(RADEON_CP_ME_RAM_DATAL, R200_cp_microcode[i][0]); |
} |
fw_name = FIRMWARE_R200; |
} else if ((rdev->family == CHIP_R300) || |
(rdev->family == CHIP_R350) || |
(rdev->family == CHIP_RV350) || |
471,31 → 379,19 |
(rdev->family == CHIP_RS400) || |
(rdev->family == CHIP_RS480)) { |
DRM_INFO("Loading R300 Microcode\n"); |
for (i = 0; i < 256; i++) { |
WREG32(RADEON_CP_ME_RAM_DATAH, R300_cp_microcode[i][1]); |
WREG32(RADEON_CP_ME_RAM_DATAL, R300_cp_microcode[i][0]); |
} |
fw_name = FIRMWARE_R300; |
} else if ((rdev->family == CHIP_R420) || |
(rdev->family == CHIP_R423) || |
(rdev->family == CHIP_RV410)) { |
DRM_INFO("Loading R400 Microcode\n"); |
for (i = 0; i < 256; i++) { |
WREG32(RADEON_CP_ME_RAM_DATAH, R420_cp_microcode[i][1]); |
WREG32(RADEON_CP_ME_RAM_DATAL, R420_cp_microcode[i][0]); |
} |
fw_name = FIRMWARE_R420; |
} else if ((rdev->family == CHIP_RS690) || |
(rdev->family == CHIP_RS740)) { |
DRM_INFO("Loading RS690/RS740 Microcode\n"); |
for (i = 0; i < 256; i++) { |
WREG32(RADEON_CP_ME_RAM_DATAH, RS690_cp_microcode[i][1]); |
WREG32(RADEON_CP_ME_RAM_DATAL, RS690_cp_microcode[i][0]); |
} |
fw_name = FIRMWARE_RS690; |
} else if (rdev->family == CHIP_RS600) { |
DRM_INFO("Loading RS600 Microcode\n"); |
for (i = 0; i < 256; i++) { |
WREG32(RADEON_CP_ME_RAM_DATAH, RS600_cp_microcode[i][1]); |
WREG32(RADEON_CP_ME_RAM_DATAL, RS600_cp_microcode[i][0]); |
} |
fw_name = FIRMWARE_RS600; |
} else if ((rdev->family == CHIP_RV515) || |
(rdev->family == CHIP_R520) || |
(rdev->family == CHIP_RV530) || |
503,19 → 399,62 |
(rdev->family == CHIP_RV560) || |
(rdev->family == CHIP_RV570)) { |
DRM_INFO("Loading R500 Microcode\n"); |
for (i = 0; i < 256; i++) { |
WREG32(RADEON_CP_ME_RAM_DATAH, R520_cp_microcode[i][1]); |
WREG32(RADEON_CP_ME_RAM_DATAL, R520_cp_microcode[i][0]); |
fw_name = FIRMWARE_R520; |
} |
|
// err = request_firmware(&rdev->me_fw, fw_name, &pdev->dev); |
// platform_device_unregister(pdev); |
if (err) { |
printk(KERN_ERR "radeon_cp: Failed to load firmware \"%s\"\n", |
fw_name); |
} else if (rdev->me_fw->size % 8) { |
printk(KERN_ERR |
"radeon_cp: Bogus length %zu in firmware \"%s\"\n", |
rdev->me_fw->size, fw_name); |
err = -EINVAL; |
release_firmware(rdev->me_fw); |
rdev->me_fw = NULL; |
} |
return err; |
} |
|
static int r100_cp_init_microcode(struct radeon_device *rdev) |
static inline __u32 __swab32(__u32 x) |
{ |
return 0; |
asm("bswapl %0" : |
"=&r" (x) |
:"r" (x)); |
return x; |
} |
|
static inline __u32 be32_to_cpup(const __be32 *p) |
{ |
return __swab32(*(__u32 *)p); |
} |
|
|
static void r100_cp_load_microcode(struct radeon_device *rdev) |
{ |
const __be32 *fw_data; |
int i, size; |
|
if (r100_gui_wait_for_idle(rdev)) { |
printk(KERN_WARNING "Failed to wait GUI idle while " |
"programming pipes. Bad things might happen.\n"); |
} |
|
if (rdev->me_fw) { |
size = rdev->me_fw->size / 4; |
fw_data = (const __be32 *)&rdev->me_fw->data[0]; |
WREG32(RADEON_CP_ME_RAM_ADDR, 0); |
for (i = 0; i < size; i += 2) { |
WREG32(RADEON_CP_ME_RAM_DATAH, |
be32_to_cpup(&fw_data[i])); |
WREG32(RADEON_CP_ME_RAM_DATAL, |
be32_to_cpup(&fw_data[i + 1])); |
} |
} |
} |
|
int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) |
{ |
unsigned rb_bufsz; |
747,13 → 686,11 |
void r100_cs_dump_packet(struct radeon_cs_parser *p, |
struct radeon_cs_packet *pkt) |
{ |
struct radeon_cs_chunk *ib_chunk; |
volatile uint32_t *ib; |
unsigned i; |
unsigned idx; |
|
ib = p->ib->ptr; |
ib_chunk = &p->chunks[p->chunk_ib_idx]; |
idx = pkt->idx; |
for (i = 0; i <= (pkt->count + 1); i++, idx++) { |
DRM_INFO("ib[%d]=0x%08X\n", idx, ib[idx]); |
780,7 → 717,7 |
idx, ib_chunk->length_dw); |
return -EINVAL; |
} |
header = ib_chunk->kdata[idx]; |
header = radeon_get_ib_value(p, idx); |
pkt->idx = idx; |
pkt->type = CP_PACKET_GET_TYPE(header); |
pkt->count = CP_PACKET_GET_COUNT(header); |
823,7 → 760,6 |
*/ |
int r100_cs_packet_parse_vline(struct radeon_cs_parser *p) |
{ |
struct radeon_cs_chunk *ib_chunk; |
struct drm_mode_object *obj; |
struct drm_crtc *crtc; |
struct radeon_crtc *radeon_crtc; |
831,8 → 767,9 |
int crtc_id; |
int r; |
uint32_t header, h_idx, reg; |
volatile uint32_t *ib; |
|
ib_chunk = &p->chunks[p->chunk_ib_idx]; |
ib = p->ib->ptr; |
|
/* parse the wait until */ |
r = r100_cs_packet_parse(p, &waitreloc, p->idx); |
847,7 → 784,7 |
return r; |
} |
|
if (ib_chunk->kdata[waitreloc.idx + 1] != RADEON_WAIT_CRTC_VLINE) { |
if (radeon_get_ib_value(p, waitreloc.idx + 1) != RADEON_WAIT_CRTC_VLINE) { |
DRM_ERROR("vline wait had illegal wait until\n"); |
r = -EINVAL; |
return r; |
854,17 → 791,17 |
} |
|
/* jump over the NOP */ |
r = r100_cs_packet_parse(p, &p3reloc, p->idx); |
r = r100_cs_packet_parse(p, &p3reloc, p->idx + waitreloc.count + 2); |
if (r) |
return r; |
|
h_idx = p->idx - 2; |
p->idx += waitreloc.count; |
p->idx += p3reloc.count; |
p->idx += waitreloc.count + 2; |
p->idx += p3reloc.count + 2; |
|
header = ib_chunk->kdata[h_idx]; |
crtc_id = ib_chunk->kdata[h_idx + 5]; |
reg = ib_chunk->kdata[h_idx] >> 2; |
header = radeon_get_ib_value(p, h_idx); |
crtc_id = radeon_get_ib_value(p, h_idx + 5); |
reg = CP_PACKET0_GET_REG(header); |
mutex_lock(&p->rdev->ddev->mode_config.mutex); |
obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC); |
if (!obj) { |
878,16 → 815,16 |
|
if (!crtc->enabled) { |
/* if the CRTC isn't enabled - we need to nop out the wait until */ |
ib_chunk->kdata[h_idx + 2] = PACKET2(0); |
ib_chunk->kdata[h_idx + 3] = PACKET2(0); |
ib[h_idx + 2] = PACKET2(0); |
ib[h_idx + 3] = PACKET2(0); |
} else if (crtc_id == 1) { |
switch (reg) { |
case AVIVO_D1MODE_VLINE_START_END: |
header &= R300_CP_PACKET0_REG_MASK; |
header &= ~R300_CP_PACKET0_REG_MASK; |
header |= AVIVO_D2MODE_VLINE_START_END >> 2; |
break; |
case RADEON_CRTC_GUI_TRIG_VLINE: |
header &= R300_CP_PACKET0_REG_MASK; |
header &= ~R300_CP_PACKET0_REG_MASK; |
header |= RADEON_CRTC2_GUI_TRIG_VLINE >> 2; |
break; |
default: |
895,8 → 832,8 |
r = -EINVAL; |
goto out; |
} |
ib_chunk->kdata[h_idx] = header; |
ib_chunk->kdata[h_idx + 3] |= RADEON_ENG_DISPLAY_SELECT_CRTC1; |
ib[h_idx] = header; |
ib[h_idx + 3] |= RADEON_ENG_DISPLAY_SELECT_CRTC1; |
} |
out: |
mutex_unlock(&p->rdev->ddev->mode_config.mutex); |
917,7 → 854,6 |
int r100_cs_packet_next_reloc(struct radeon_cs_parser *p, |
struct radeon_cs_reloc **cs_reloc) |
{ |
struct radeon_cs_chunk *ib_chunk; |
struct radeon_cs_chunk *relocs_chunk; |
struct radeon_cs_packet p3reloc; |
unsigned idx; |
928,7 → 864,6 |
return -EINVAL; |
} |
*cs_reloc = NULL; |
ib_chunk = &p->chunks[p->chunk_ib_idx]; |
relocs_chunk = &p->chunks[p->chunk_relocs_idx]; |
r = r100_cs_packet_parse(p, &p3reloc, p->idx); |
if (r) { |
941,7 → 876,7 |
r100_cs_dump_packet(p, &p3reloc); |
return -EINVAL; |
} |
idx = ib_chunk->kdata[p3reloc.idx + 1]; |
idx = radeon_get_ib_value(p, p3reloc.idx + 1); |
if (idx >= relocs_chunk->length_dw) { |
DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", |
idx, relocs_chunk->length_dw); |
1010,7 → 945,6 |
struct radeon_cs_packet *pkt, |
unsigned idx, unsigned reg) |
{ |
struct radeon_cs_chunk *ib_chunk; |
struct radeon_cs_reloc *reloc; |
struct r100_cs_track *track; |
volatile uint32_t *ib; |
1018,11 → 952,13 |
int r; |
int i, face; |
u32 tile_flags = 0; |
u32 idx_value; |
|
ib = p->ib->ptr; |
ib_chunk = &p->chunks[p->chunk_ib_idx]; |
track = (struct r100_cs_track *)p->track; |
|
idx_value = radeon_get_ib_value(p, idx); |
|
switch (reg) { |
case RADEON_CRTC_GUI_TRIG_VLINE: |
r = r100_cs_packet_parse_vline(p); |
1050,8 → 986,8 |
return r; |
} |
track->zb.robj = reloc->robj; |
track->zb.offset = ib_chunk->kdata[idx]; |
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); |
track->zb.offset = idx_value; |
ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); |
break; |
case RADEON_RB3D_COLOROFFSET: |
r = r100_cs_packet_next_reloc(p, &reloc); |
1062,8 → 998,8 |
return r; |
} |
track->cb[0].robj = reloc->robj; |
track->cb[0].offset = ib_chunk->kdata[idx]; |
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); |
track->cb[0].offset = idx_value; |
ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); |
break; |
case RADEON_PP_TXOFFSET_0: |
case RADEON_PP_TXOFFSET_1: |
1076,7 → 1012,7 |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); |
ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); |
track->textures[i].robj = reloc->robj; |
break; |
case RADEON_PP_CUBIC_OFFSET_T0_0: |
1092,8 → 1028,8 |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
track->textures[0].cube_info[i].offset = ib_chunk->kdata[idx]; |
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); |
track->textures[0].cube_info[i].offset = idx_value; |
ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); |
track->textures[0].cube_info[i].robj = reloc->robj; |
break; |
case RADEON_PP_CUBIC_OFFSET_T1_0: |
1109,8 → 1045,8 |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
track->textures[1].cube_info[i].offset = ib_chunk->kdata[idx]; |
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); |
track->textures[1].cube_info[i].offset = idx_value; |
ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); |
track->textures[1].cube_info[i].robj = reloc->robj; |
break; |
case RADEON_PP_CUBIC_OFFSET_T2_0: |
1126,12 → 1062,12 |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
track->textures[2].cube_info[i].offset = ib_chunk->kdata[idx]; |
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); |
track->textures[2].cube_info[i].offset = idx_value; |
ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); |
track->textures[2].cube_info[i].robj = reloc->robj; |
break; |
case RADEON_RE_WIDTH_HEIGHT: |
track->maxy = ((ib_chunk->kdata[idx] >> 16) & 0x7FF); |
track->maxy = ((idx_value >> 16) & 0x7FF); |
break; |
case RADEON_RB3D_COLORPITCH: |
r = r100_cs_packet_next_reloc(p, &reloc); |
1147,17 → 1083,17 |
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) |
tile_flags |= RADEON_COLOR_MICROTILE_ENABLE; |
|
tmp = ib_chunk->kdata[idx] & ~(0x7 << 16); |
tmp = idx_value & ~(0x7 << 16); |
tmp |= tile_flags; |
ib[idx] = tmp; |
|
track->cb[0].pitch = ib_chunk->kdata[idx] & RADEON_COLORPITCH_MASK; |
track->cb[0].pitch = idx_value & RADEON_COLORPITCH_MASK; |
break; |
case RADEON_RB3D_DEPTHPITCH: |
track->zb.pitch = ib_chunk->kdata[idx] & RADEON_DEPTHPITCH_MASK; |
track->zb.pitch = idx_value & RADEON_DEPTHPITCH_MASK; |
break; |
case RADEON_RB3D_CNTL: |
switch ((ib_chunk->kdata[idx] >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) { |
switch ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) { |
case 7: |
case 8: |
case 9: |
1175,13 → 1111,13 |
break; |
default: |
DRM_ERROR("Invalid color buffer format (%d) !\n", |
((ib_chunk->kdata[idx] >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f)); |
((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f)); |
return -EINVAL; |
} |
track->z_enabled = !!(ib_chunk->kdata[idx] & RADEON_Z_ENABLE); |
track->z_enabled = !!(idx_value & RADEON_Z_ENABLE); |
break; |
case RADEON_RB3D_ZSTENCILCNTL: |
switch (ib_chunk->kdata[idx] & 0xf) { |
switch (idx_value & 0xf) { |
case 0: |
track->zb.cpp = 2; |
break; |
1205,44 → 1141,44 |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); |
ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); |
break; |
case RADEON_PP_CNTL: |
{ |
uint32_t temp = ib_chunk->kdata[idx] >> 4; |
uint32_t temp = idx_value >> 4; |
for (i = 0; i < track->num_texture; i++) |
track->textures[i].enabled = !!(temp & (1 << i)); |
} |
break; |
case RADEON_SE_VF_CNTL: |
track->vap_vf_cntl = ib_chunk->kdata[idx]; |
track->vap_vf_cntl = idx_value; |
break; |
case RADEON_SE_VTX_FMT: |
track->vtx_size = r100_get_vtx_size(ib_chunk->kdata[idx]); |
track->vtx_size = r100_get_vtx_size(idx_value); |
break; |
case RADEON_PP_TEX_SIZE_0: |
case RADEON_PP_TEX_SIZE_1: |
case RADEON_PP_TEX_SIZE_2: |
i = (reg - RADEON_PP_TEX_SIZE_0) / 8; |
track->textures[i].width = (ib_chunk->kdata[idx] & RADEON_TEX_USIZE_MASK) + 1; |
track->textures[i].height = ((ib_chunk->kdata[idx] & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1; |
track->textures[i].width = (idx_value & RADEON_TEX_USIZE_MASK) + 1; |
track->textures[i].height = ((idx_value & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1; |
break; |
case RADEON_PP_TEX_PITCH_0: |
case RADEON_PP_TEX_PITCH_1: |
case RADEON_PP_TEX_PITCH_2: |
i = (reg - RADEON_PP_TEX_PITCH_0) / 8; |
track->textures[i].pitch = ib_chunk->kdata[idx] + 32; |
track->textures[i].pitch = idx_value + 32; |
break; |
case RADEON_PP_TXFILTER_0: |
case RADEON_PP_TXFILTER_1: |
case RADEON_PP_TXFILTER_2: |
i = (reg - RADEON_PP_TXFILTER_0) / 24; |
track->textures[i].num_levels = ((ib_chunk->kdata[idx] & RADEON_MAX_MIP_LEVEL_MASK) |
track->textures[i].num_levels = ((idx_value & RADEON_MAX_MIP_LEVEL_MASK) |
>> RADEON_MAX_MIP_LEVEL_SHIFT); |
tmp = (ib_chunk->kdata[idx] >> 23) & 0x7; |
tmp = (idx_value >> 23) & 0x7; |
if (tmp == 2 || tmp == 6) |
track->textures[i].roundup_w = false; |
tmp = (ib_chunk->kdata[idx] >> 27) & 0x7; |
tmp = (idx_value >> 27) & 0x7; |
if (tmp == 2 || tmp == 6) |
track->textures[i].roundup_h = false; |
break; |
1250,16 → 1186,16 |
case RADEON_PP_TXFORMAT_1: |
case RADEON_PP_TXFORMAT_2: |
i = (reg - RADEON_PP_TXFORMAT_0) / 24; |
if (ib_chunk->kdata[idx] & RADEON_TXFORMAT_NON_POWER2) { |
if (idx_value & RADEON_TXFORMAT_NON_POWER2) { |
track->textures[i].use_pitch = 1; |
} else { |
track->textures[i].use_pitch = 0; |
track->textures[i].width = 1 << ((ib_chunk->kdata[idx] >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK); |
track->textures[i].height = 1 << ((ib_chunk->kdata[idx] >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK); |
track->textures[i].width = 1 << ((idx_value >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK); |
track->textures[i].height = 1 << ((idx_value >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK); |
} |
if (ib_chunk->kdata[idx] & RADEON_TXFORMAT_CUBIC_MAP_ENABLE) |
if (idx_value & RADEON_TXFORMAT_CUBIC_MAP_ENABLE) |
track->textures[i].tex_coord_type = 2; |
switch ((ib_chunk->kdata[idx] & RADEON_TXFORMAT_FORMAT_MASK)) { |
switch ((idx_value & RADEON_TXFORMAT_FORMAT_MASK)) { |
case RADEON_TXFORMAT_I8: |
case RADEON_TXFORMAT_RGB332: |
case RADEON_TXFORMAT_Y8: |
1286,13 → 1222,13 |
track->textures[i].cpp = 4; |
break; |
} |
track->textures[i].cube_info[4].width = 1 << ((ib_chunk->kdata[idx] >> 16) & 0xf); |
track->textures[i].cube_info[4].height = 1 << ((ib_chunk->kdata[idx] >> 20) & 0xf); |
track->textures[i].cube_info[4].width = 1 << ((idx_value >> 16) & 0xf); |
track->textures[i].cube_info[4].height = 1 << ((idx_value >> 20) & 0xf); |
break; |
case RADEON_PP_CUBIC_FACES_0: |
case RADEON_PP_CUBIC_FACES_1: |
case RADEON_PP_CUBIC_FACES_2: |
tmp = ib_chunk->kdata[idx]; |
tmp = idx_value; |
i = (reg - RADEON_PP_CUBIC_FACES_0) / 4; |
for (face = 0; face < 4; face++) { |
track->textures[i].cube_info[face].width = 1 << ((tmp >> (face * 8)) & 0xf); |
1311,15 → 1247,14 |
struct radeon_cs_packet *pkt, |
struct radeon_object *robj) |
{ |
struct radeon_cs_chunk *ib_chunk; |
unsigned idx; |
|
ib_chunk = &p->chunks[p->chunk_ib_idx]; |
u32 value; |
idx = pkt->idx + 1; |
if ((ib_chunk->kdata[idx+2] + 1) > radeon_object_size(robj)) { |
value = radeon_get_ib_value(p, idx + 2); |
if ((value + 1) > radeon_object_size(robj)) { |
DRM_ERROR("[drm] Buffer too small for PACKET3 INDX_BUFFER " |
"(need %u have %lu) !\n", |
ib_chunk->kdata[idx+2] + 1, |
value + 1, |
radeon_object_size(robj)); |
return -EINVAL; |
} |
1329,59 → 1264,20 |
static int r100_packet3_check(struct radeon_cs_parser *p, |
struct radeon_cs_packet *pkt) |
{ |
struct radeon_cs_chunk *ib_chunk; |
struct radeon_cs_reloc *reloc; |
struct r100_cs_track *track; |
unsigned idx; |
unsigned i, c; |
volatile uint32_t *ib; |
int r; |
|
ib = p->ib->ptr; |
ib_chunk = &p->chunks[p->chunk_ib_idx]; |
idx = pkt->idx + 1; |
track = (struct r100_cs_track *)p->track; |
switch (pkt->opcode) { |
case PACKET3_3D_LOAD_VBPNTR: |
c = ib_chunk->kdata[idx++]; |
track->num_arrays = c; |
for (i = 0; i < (c - 1); i += 2, idx += 3) { |
r = r100_cs_packet_next_reloc(p, &reloc); |
if (r) { |
DRM_ERROR("No reloc for packet3 %d\n", |
pkt->opcode); |
r100_cs_dump_packet(p, pkt); |
r = r100_packet3_load_vbpntr(p, pkt, idx); |
if (r) |
return r; |
} |
ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); |
track->arrays[i + 0].robj = reloc->robj; |
track->arrays[i + 0].esize = ib_chunk->kdata[idx] >> 8; |
track->arrays[i + 0].esize &= 0x7F; |
r = r100_cs_packet_next_reloc(p, &reloc); |
if (r) { |
DRM_ERROR("No reloc for packet3 %d\n", |
pkt->opcode); |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
ib[idx+2] = ib_chunk->kdata[idx+2] + ((u32)reloc->lobj.gpu_offset); |
track->arrays[i + 1].robj = reloc->robj; |
track->arrays[i + 1].esize = ib_chunk->kdata[idx] >> 24; |
track->arrays[i + 1].esize &= 0x7F; |
} |
if (c & 1) { |
r = r100_cs_packet_next_reloc(p, &reloc); |
if (r) { |
DRM_ERROR("No reloc for packet3 %d\n", |
pkt->opcode); |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); |
track->arrays[i + 0].robj = reloc->robj; |
track->arrays[i + 0].esize = ib_chunk->kdata[idx] >> 8; |
track->arrays[i + 0].esize &= 0x7F; |
} |
break; |
case PACKET3_INDX_BUFFER: |
r = r100_cs_packet_next_reloc(p, &reloc); |
1390,7 → 1286,7 |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); |
ib[idx+1] = radeon_get_ib_value(p, idx+1) + ((u32)reloc->lobj.gpu_offset); |
r = r100_cs_track_check_pkt3_indx_buffer(p, pkt, reloc->robj); |
if (r) { |
return r; |
1404,16 → 1300,16 |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); |
ib[idx] = radeon_get_ib_value(p, idx) + ((u32)reloc->lobj.gpu_offset); |
track->num_arrays = 1; |
track->vtx_size = r100_get_vtx_size(ib_chunk->kdata[idx+2]); |
track->vtx_size = r100_get_vtx_size(radeon_get_ib_value(p, idx + 2)); |
|
track->arrays[0].robj = reloc->robj; |
track->arrays[0].esize = track->vtx_size; |
|
track->max_indx = ib_chunk->kdata[idx+1]; |
track->max_indx = radeon_get_ib_value(p, idx+1); |
|
track->vap_vf_cntl = ib_chunk->kdata[idx+3]; |
track->vap_vf_cntl = radeon_get_ib_value(p, idx+3); |
track->immd_dwords = pkt->count - 1; |
r = r100_cs_track_check(p->rdev, track); |
if (r) |
1420,11 → 1316,11 |
return r; |
break; |
case PACKET3_3D_DRAW_IMMD: |
if (((ib_chunk->kdata[idx+1] >> 4) & 0x3) != 3) { |
if (((radeon_get_ib_value(p, idx + 1) >> 4) & 0x3) != 3) { |
DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n"); |
return -EINVAL; |
} |
track->vap_vf_cntl = ib_chunk->kdata[idx+1]; |
track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1); |
track->immd_dwords = pkt->count - 1; |
r = r100_cs_track_check(p->rdev, track); |
if (r) |
1432,11 → 1328,11 |
break; |
/* triggers drawing using in-packet vertex data */ |
case PACKET3_3D_DRAW_IMMD_2: |
if (((ib_chunk->kdata[idx] >> 4) & 0x3) != 3) { |
if (((radeon_get_ib_value(p, idx) >> 4) & 0x3) != 3) { |
DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n"); |
return -EINVAL; |
} |
track->vap_vf_cntl = ib_chunk->kdata[idx]; |
track->vap_vf_cntl = radeon_get_ib_value(p, idx); |
track->immd_dwords = pkt->count; |
r = r100_cs_track_check(p->rdev, track); |
if (r) |
1444,7 → 1340,7 |
break; |
/* triggers drawing using in-packet vertex data */ |
case PACKET3_3D_DRAW_VBUF_2: |
track->vap_vf_cntl = ib_chunk->kdata[idx]; |
track->vap_vf_cntl = radeon_get_ib_value(p, idx); |
r = r100_cs_track_check(p->rdev, track); |
if (r) |
return r; |
1451,7 → 1347,7 |
break; |
/* triggers drawing of vertex buffers setup elsewhere */ |
case PACKET3_3D_DRAW_INDX_2: |
track->vap_vf_cntl = ib_chunk->kdata[idx]; |
track->vap_vf_cntl = radeon_get_ib_value(p, idx); |
r = r100_cs_track_check(p->rdev, track); |
if (r) |
return r; |
1458,7 → 1354,7 |
break; |
/* triggers drawing using indices to vertex buffer */ |
case PACKET3_3D_DRAW_VBUF: |
track->vap_vf_cntl = ib_chunk->kdata[idx + 1]; |
track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1); |
r = r100_cs_track_check(p->rdev, track); |
if (r) |
return r; |
1465,7 → 1361,7 |
break; |
/* triggers drawing of vertex buffers setup elsewhere */ |
case PACKET3_3D_DRAW_INDX: |
track->vap_vf_cntl = ib_chunk->kdata[idx + 1]; |
track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1); |
r = r100_cs_track_check(p->rdev, track); |
if (r) |
return r; |
1922,7 → 1818,7 |
r100_pll_errata_after_data(rdev); |
} |
|
int r100_init(struct radeon_device *rdev) |
void r100_set_safe_registers(struct radeon_device *rdev) |
{ |
if (ASIC_IS_RN50(rdev)) { |
rdev->config.r100.reg_safe_bm = rn50_reg_safe_bm; |
1931,9 → 1827,8 |
rdev->config.r100.reg_safe_bm = r100_reg_safe_bm; |
rdev->config.r100.reg_safe_bm_size = ARRAY_SIZE(r100_reg_safe_bm); |
} else { |
return r200_init(rdev); |
r200_set_safe_registers(rdev); |
} |
return 0; |
} |
|
/* |
2231,10 → 2126,12 |
mode1 = &rdev->mode_info.crtcs[0]->base.mode; |
pixel_bytes1 = rdev->mode_info.crtcs[0]->base.fb->bits_per_pixel / 8; |
} |
if (!(rdev->flags & RADEON_SINGLE_CRTC)) { |
if (rdev->mode_info.crtcs[1]->base.enabled) { |
mode2 = &rdev->mode_info.crtcs[1]->base.mode; |
pixel_bytes2 = rdev->mode_info.crtcs[1]->base.fb->bits_per_pixel / 8; |
} |
} |
|
min_mem_eff.full = rfixed_const_8(0); |
/* get modes */ |
2651,7 → 2548,7 |
WREG32(R_000740_CP_CSQ_CNTL, 0); |
|
/* Save few CRTC registers */ |
save->GENMO_WT = RREG32(R_0003C0_GENMO_WT); |
save->GENMO_WT = RREG8(R_0003C2_GENMO_WT); |
save->CRTC_EXT_CNTL = RREG32(R_000054_CRTC_EXT_CNTL); |
save->CRTC_GEN_CNTL = RREG32(R_000050_CRTC_GEN_CNTL); |
save->CUR_OFFSET = RREG32(R_000260_CUR_OFFSET); |
2661,7 → 2558,7 |
} |
|
/* Disable VGA aperture access */ |
WREG32(R_0003C0_GENMO_WT, C_0003C0_VGA_RAM_EN & save->GENMO_WT); |
WREG8(R_0003C2_GENMO_WT, C_0003C2_VGA_RAM_EN & save->GENMO_WT); |
/* Disable cursor, overlay, crtc */ |
WREG32(R_000260_CUR_OFFSET, save->CUR_OFFSET | S_000260_CUR_LOCK(1)); |
WREG32(R_000054_CRTC_EXT_CNTL, save->CRTC_EXT_CNTL | |
2693,7 → 2590,7 |
rdev->mc.vram_location); |
} |
/* Restore CRTC registers */ |
WREG32(R_0003C0_GENMO_WT, save->GENMO_WT); |
WREG8(R_0003C2_GENMO_WT, save->GENMO_WT); |
WREG32(R_000054_CRTC_EXT_CNTL, save->CRTC_EXT_CNTL); |
WREG32(R_000050_CRTC_GEN_CNTL, save->CRTC_GEN_CNTL); |
if (!(rdev->flags & RADEON_SINGLE_CRTC)) { |
2701,6 → 2598,24 |
} |
} |
|
void r100_vga_render_disable(struct radeon_device *rdev) |
{ |
u32 tmp; |
|
tmp = RREG8(R_0003C2_GENMO_WT); |
WREG8(R_0003C2_GENMO_WT, C_0003C2_VGA_RAM_EN & tmp); |
} |
|
static void r100_debugfs(struct radeon_device *rdev) |
{ |
int r; |
|
r = r100_debugfs_mc_info_init(rdev); |
if (r) |
dev_warn(rdev->dev, "Failed to create r100_mc debugfs file.\n"); |
} |
|
|
int drm_order(unsigned long size) |
{ |
int order; |
2714,3 → 2629,193 |
return order; |
} |
|
static void r100_mc_program(struct radeon_device *rdev) |
{ |
struct r100_mc_save save; |
|
/* Stops all mc clients */ |
r100_mc_stop(rdev, &save); |
if (rdev->flags & RADEON_IS_AGP) { |
WREG32(R_00014C_MC_AGP_LOCATION, |
S_00014C_MC_AGP_START(rdev->mc.gtt_start >> 16) | |
S_00014C_MC_AGP_TOP(rdev->mc.gtt_end >> 16)); |
WREG32(R_000170_AGP_BASE, lower_32_bits(rdev->mc.agp_base)); |
if (rdev->family > CHIP_RV200) |
WREG32(R_00015C_AGP_BASE_2, |
upper_32_bits(rdev->mc.agp_base) & 0xff); |
} else { |
WREG32(R_00014C_MC_AGP_LOCATION, 0x0FFFFFFF); |
WREG32(R_000170_AGP_BASE, 0); |
if (rdev->family > CHIP_RV200) |
WREG32(R_00015C_AGP_BASE_2, 0); |
} |
/* Wait for mc idle */ |
if (r100_mc_wait_for_idle(rdev)) |
dev_warn(rdev->dev, "Wait for MC idle timeout.\n"); |
/* Program MC, should be a 32bits limited address space */ |
WREG32(R_000148_MC_FB_LOCATION, |
S_000148_MC_FB_START(rdev->mc.vram_start >> 16) | |
S_000148_MC_FB_TOP(rdev->mc.vram_end >> 16)); |
r100_mc_resume(rdev, &save); |
} |
|
void r100_clock_startup(struct radeon_device *rdev) |
{ |
u32 tmp; |
|
if (radeon_dynclks != -1 && radeon_dynclks) |
radeon_legacy_set_clock_gating(rdev, 1); |
/* We need to force on some of the block */ |
tmp = RREG32_PLL(R_00000D_SCLK_CNTL); |
tmp |= S_00000D_FORCE_CP(1) | S_00000D_FORCE_VIP(1); |
if ((rdev->family == CHIP_RV250) || (rdev->family == CHIP_RV280)) |
tmp |= S_00000D_FORCE_DISP1(1) | S_00000D_FORCE_DISP2(1); |
WREG32_PLL(R_00000D_SCLK_CNTL, tmp); |
} |
|
static int r100_startup(struct radeon_device *rdev) |
{ |
int r; |
|
r100_mc_program(rdev); |
/* Resume clock */ |
r100_clock_startup(rdev); |
/* Initialize GPU configuration (# pipes, ...) */ |
r100_gpu_init(rdev); |
/* Initialize GART (initialize after TTM so we can allocate |
* memory through TTM but finalize after TTM) */ |
if (rdev->flags & RADEON_IS_PCI) { |
r = r100_pci_gart_enable(rdev); |
if (r) |
return r; |
} |
/* Enable IRQ */ |
// rdev->irq.sw_int = true; |
// r100_irq_set(rdev); |
/* 1M ring buffer */ |
// r = r100_cp_init(rdev, 1024 * 1024); |
// if (r) { |
// dev_err(rdev->dev, "failled initializing CP (%d).\n", r); |
// return r; |
// } |
// r = r100_wb_init(rdev); |
// if (r) |
// dev_err(rdev->dev, "failled initializing WB (%d).\n", r); |
// r = r100_ib_init(rdev); |
// if (r) { |
// dev_err(rdev->dev, "failled initializing IB (%d).\n", r); |
// return r; |
// } |
return 0; |
} |
|
|
int r100_mc_init(struct radeon_device *rdev) |
{ |
int r; |
u32 tmp; |
|
/* Setup GPU memory space */ |
rdev->mc.vram_location = 0xFFFFFFFFUL; |
rdev->mc.gtt_location = 0xFFFFFFFFUL; |
if (rdev->flags & RADEON_IS_IGP) { |
tmp = G_00015C_MC_FB_START(RREG32(R_00015C_NB_TOM)); |
rdev->mc.vram_location = tmp << 16; |
} |
if (rdev->flags & RADEON_IS_AGP) { |
r = radeon_agp_init(rdev); |
if (r) { |
printk(KERN_WARNING "[drm] Disabling AGP\n"); |
rdev->flags &= ~RADEON_IS_AGP; |
rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; |
} else { |
rdev->mc.gtt_location = rdev->mc.agp_base; |
} |
} |
r = radeon_mc_setup(rdev); |
if (r) |
return r; |
return 0; |
} |
|
int r100_init(struct radeon_device *rdev) |
{ |
int r; |
|
/* Register debugfs file specific to this group of asics */ |
r100_debugfs(rdev); |
/* Disable VGA */ |
r100_vga_render_disable(rdev); |
/* Initialize scratch registers */ |
radeon_scratch_init(rdev); |
/* Initialize surface registers */ |
radeon_surface_init(rdev); |
/* TODO: disable VGA need to use VGA request */ |
/* BIOS*/ |
if (!radeon_get_bios(rdev)) { |
if (ASIC_IS_AVIVO(rdev)) |
return -EINVAL; |
} |
if (rdev->is_atom_bios) { |
dev_err(rdev->dev, "Expecting combios for RS400/RS480 GPU\n"); |
return -EINVAL; |
} else { |
r = radeon_combios_init(rdev); |
if (r) |
return r; |
} |
/* Reset gpu before posting otherwise ATOM will enter infinite loop */ |
if (radeon_gpu_reset(rdev)) { |
dev_warn(rdev->dev, |
"GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", |
RREG32(R_000E40_RBBM_STATUS), |
RREG32(R_0007C0_CP_STAT)); |
} |
/* check if cards are posted or not */ |
if (!radeon_card_posted(rdev) && rdev->bios) { |
DRM_INFO("GPU not posted. posting now...\n"); |
radeon_combios_asic_init(rdev->ddev); |
} |
/* Set asic errata */ |
r100_errata(rdev); |
/* Initialize clocks */ |
radeon_get_clock_info(rdev->ddev); |
/* Get vram informations */ |
r100_vram_info(rdev); |
/* Initialize memory controller (also test AGP) */ |
r = r100_mc_init(rdev); |
if (r) |
return r; |
/* Fence driver */ |
// r = radeon_fence_driver_init(rdev); |
// if (r) |
// return r; |
// r = radeon_irq_kms_init(rdev); |
// if (r) |
// return r; |
/* Memory manager */ |
r = radeon_object_init(rdev); |
if (r) |
return r; |
if (rdev->flags & RADEON_IS_PCI) { |
r = r100_pci_gart_init(rdev); |
if (r) |
return r; |
} |
r100_set_safe_registers(rdev); |
rdev->accel_working = true; |
r = r100_startup(rdev); |
if (r) { |
/* Somethings want wront with the accel init stop accel */ |
dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
// r100_suspend(rdev); |
// r100_cp_fini(rdev); |
// r100_wb_fini(rdev); |
// r100_ib_fini(rdev); |
if (rdev->flags & RADEON_IS_PCI) |
r100_pci_gart_fini(rdev); |
// radeon_irq_kms_fini(rdev); |
rdev->accel_working = false; |
} |
return 0; |
} |