67,6 → 67,38 |
* and others in some cases. |
*/ |
|
static bool r100_is_in_vblank(struct radeon_device *rdev, int crtc) |
{ |
if (crtc == 0) { |
if (RREG32(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_CUR) |
return true; |
else |
return false; |
} else { |
if (RREG32(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_CUR) |
return true; |
else |
return false; |
} |
} |
|
static bool r100_is_counter_moving(struct radeon_device *rdev, int crtc) |
{ |
u32 vline1, vline2; |
|
if (crtc == 0) { |
vline1 = (RREG32(RADEON_CRTC_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL; |
vline2 = (RREG32(RADEON_CRTC_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL; |
} else { |
vline1 = (RREG32(RADEON_CRTC2_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL; |
vline2 = (RREG32(RADEON_CRTC2_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL; |
} |
if (vline1 != vline2) |
return true; |
else |
return false; |
} |
|
/** |
* r100_wait_for_vblank - vblank wait asic callback. |
* |
77,39 → 109,36 |
*/ |
void r100_wait_for_vblank(struct radeon_device *rdev, int crtc) |
{ |
int i; |
unsigned i = 0; |
|
if (crtc >= rdev->num_crtc) |
return; |
|
if (crtc == 0) { |
if (RREG32(RADEON_CRTC_GEN_CNTL) & RADEON_CRTC_EN) { |
for (i = 0; i < rdev->usec_timeout; i++) { |
if (!(RREG32(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_CUR)) |
break; |
udelay(1); |
if (!(RREG32(RADEON_CRTC_GEN_CNTL) & RADEON_CRTC_EN)) |
return; |
} else { |
if (!(RREG32(RADEON_CRTC2_GEN_CNTL) & RADEON_CRTC2_EN)) |
return; |
} |
for (i = 0; i < rdev->usec_timeout; i++) { |
if (RREG32(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_CUR) |
|
/* depending on when we hit vblank, we may be close to active; if so, |
* wait for another frame. |
*/ |
while (r100_is_in_vblank(rdev, crtc)) { |
if (i++ % 100 == 0) { |
if (!r100_is_counter_moving(rdev, crtc)) |
break; |
udelay(1); |
} |
} |
} else { |
if (RREG32(RADEON_CRTC2_GEN_CNTL) & RADEON_CRTC2_EN) { |
for (i = 0; i < rdev->usec_timeout; i++) { |
if (!(RREG32(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_CUR)) |
|
while (!r100_is_in_vblank(rdev, crtc)) { |
if (i++ % 100 == 0) { |
if (!r100_is_counter_moving(rdev, crtc)) |
break; |
udelay(1); |
} |
for (i = 0; i < rdev->usec_timeout; i++) { |
if (RREG32(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_CUR) |
break; |
udelay(1); |
} |
} |
} |
} |
u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) |
{ |
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; |
857,11 → 886,11 |
struct radeon_cs_reloc *reloc; |
u32 value; |
|
r = r100_cs_packet_next_reloc(p, &reloc); |
r = radeon_cs_packet_next_reloc(p, &reloc, 0); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
radeon_cs_dump_packet(p, pkt); |
return r; |
} |
|
875,7 → 904,7 |
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { |
if (reg == RADEON_SRC_PITCH_OFFSET) { |
DRM_ERROR("Cannot src blit from microtiled surface\n"); |
r100_cs_dump_packet(p, pkt); |
radeon_cs_dump_packet(p, pkt); |
return -EINVAL; |
} |
tile_flags |= RADEON_DST_TILE_MICRO; |
905,16 → 934,16 |
if (c > 16) { |
DRM_ERROR("Only 16 vertex buffers are allowed %d\n", |
pkt->opcode); |
r100_cs_dump_packet(p, pkt); |
radeon_cs_dump_packet(p, pkt); |
return -EINVAL; |
} |
track->num_arrays = c; |
for (i = 0; i < (c - 1); i+=2, idx+=3) { |
r = r100_cs_packet_next_reloc(p, &reloc); |
r = radeon_cs_packet_next_reloc(p, &reloc, 0); |
if (r) { |
DRM_ERROR("No reloc for packet3 %d\n", |
pkt->opcode); |
r100_cs_dump_packet(p, pkt); |
radeon_cs_dump_packet(p, pkt); |
return r; |
} |
idx_value = radeon_get_ib_value(p, idx); |
923,11 → 952,11 |
track->arrays[i + 0].esize = idx_value >> 8; |
track->arrays[i + 0].robj = reloc->robj; |
track->arrays[i + 0].esize &= 0x7F; |
r = r100_cs_packet_next_reloc(p, &reloc); |
r = radeon_cs_packet_next_reloc(p, &reloc, 0); |
if (r) { |
DRM_ERROR("No reloc for packet3 %d\n", |
pkt->opcode); |
r100_cs_dump_packet(p, pkt); |
radeon_cs_dump_packet(p, pkt); |
return r; |
} |
ib[idx+2] = radeon_get_ib_value(p, idx + 2) + ((u32)reloc->lobj.gpu_offset); |
936,11 → 965,11 |
track->arrays[i + 1].esize &= 0x7F; |
} |
if (c & 1) { |
r = r100_cs_packet_next_reloc(p, &reloc); |
r = radeon_cs_packet_next_reloc(p, &reloc, 0); |
if (r) { |
DRM_ERROR("No reloc for packet3 %d\n", |
pkt->opcode); |
r100_cs_dump_packet(p, pkt); |
radeon_cs_dump_packet(p, pkt); |
return r; |
} |
idx_value = radeon_get_ib_value(p, idx); |
1086,7 → 1115,7 |
ib = p->ib.ptr; |
|
/* parse the wait until */ |
r = r100_cs_packet_parse(p, &waitreloc, p->idx); |
r = radeon_cs_packet_parse(p, &waitreloc, p->idx); |
if (r) |
return r; |
|
1103,7 → 1132,7 |
} |
|
/* jump over the NOP */ |
r = r100_cs_packet_parse(p, &p3reloc, p->idx + waitreloc.count + 2); |
r = radeon_cs_packet_parse(p, &p3reloc, p->idx + waitreloc.count + 2); |
if (r) |
return r; |
|
1113,7 → 1142,7 |
|
header = radeon_get_ib_value(p, h_idx); |
crtc_id = radeon_get_ib_value(p, h_idx + 5); |
reg = CP_PACKET0_GET_REG(header); |
reg = R100_CP_PACKET0_GET_REG(header); |
obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC); |
if (!obj) { |
DRM_ERROR("cannot find crtc %d\n", crtc_id); |
1148,54 → 1177,6 |
return 0; |
} |
|
/** |
* r100_cs_packet_next_reloc() - parse next packet which should be reloc packet3 |
* @parser: parser structure holding parsing context. |
* @data: pointer to relocation data |
* @offset_start: starting offset |
* @offset_mask: offset mask (to align start offset on) |
* @reloc: reloc informations |
* |
* Check next packet is relocation packet3, do bo validation and compute |
* GPU offset using the provided start. |
**/ |
int r100_cs_packet_next_reloc(struct radeon_cs_parser *p, |
struct radeon_cs_reloc **cs_reloc) |
{ |
struct radeon_cs_chunk *relocs_chunk; |
struct radeon_cs_packet p3reloc; |
unsigned idx; |
int r; |
|
if (p->chunk_relocs_idx == -1) { |
DRM_ERROR("No relocation chunk !\n"); |
return -EINVAL; |
} |
*cs_reloc = NULL; |
relocs_chunk = &p->chunks[p->chunk_relocs_idx]; |
r = r100_cs_packet_parse(p, &p3reloc, p->idx); |
if (r) { |
return r; |
} |
p->idx += p3reloc.count + 2; |
if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) { |
DRM_ERROR("No packet3 for relocation for packet at %d.\n", |
p3reloc.idx); |
r100_cs_dump_packet(p, &p3reloc); |
return -EINVAL; |
} |
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); |
r100_cs_dump_packet(p, &p3reloc); |
return -EINVAL; |
} |
/* FIXME: we assume reloc size is 4 dwords */ |
*cs_reloc = p->relocs_ptr[(idx / 4)]; |
return 0; |
} |
|
static int r100_get_vtx_size(uint32_t vtx_fmt) |
{ |
int vtx_size; |
1273,7 → 1254,7 |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
radeon_cs_dump_packet(p, pkt); |
return r; |
} |
break; |
1286,11 → 1267,11 |
return r; |
break; |
case RADEON_RB3D_DEPTHOFFSET: |
r = r100_cs_packet_next_reloc(p, &reloc); |
r = radeon_cs_packet_next_reloc(p, &reloc, 0); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
radeon_cs_dump_packet(p, pkt); |
return r; |
} |
track->zb.robj = reloc->robj; |
1299,11 → 1280,11 |
ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); |
break; |
case RADEON_RB3D_COLOROFFSET: |
r = r100_cs_packet_next_reloc(p, &reloc); |
r = radeon_cs_packet_next_reloc(p, &reloc, 0); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
radeon_cs_dump_packet(p, pkt); |
return r; |
} |
track->cb[0].robj = reloc->robj; |
1315,11 → 1296,11 |
case RADEON_PP_TXOFFSET_1: |
case RADEON_PP_TXOFFSET_2: |
i = (reg - RADEON_PP_TXOFFSET_0) / 24; |
r = r100_cs_packet_next_reloc(p, &reloc); |
r = radeon_cs_packet_next_reloc(p, &reloc, 0); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
radeon_cs_dump_packet(p, pkt); |
return r; |
} |
if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { |
1342,11 → 1323,11 |
case RADEON_PP_CUBIC_OFFSET_T0_3: |
case RADEON_PP_CUBIC_OFFSET_T0_4: |
i = (reg - RADEON_PP_CUBIC_OFFSET_T0_0) / 4; |
r = r100_cs_packet_next_reloc(p, &reloc); |
r = radeon_cs_packet_next_reloc(p, &reloc, 0); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
radeon_cs_dump_packet(p, pkt); |
return r; |
} |
track->textures[0].cube_info[i].offset = idx_value; |
1360,11 → 1341,11 |
case RADEON_PP_CUBIC_OFFSET_T1_3: |
case RADEON_PP_CUBIC_OFFSET_T1_4: |
i = (reg - RADEON_PP_CUBIC_OFFSET_T1_0) / 4; |
r = r100_cs_packet_next_reloc(p, &reloc); |
r = radeon_cs_packet_next_reloc(p, &reloc, 0); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
radeon_cs_dump_packet(p, pkt); |
return r; |
} |
track->textures[1].cube_info[i].offset = idx_value; |
1378,11 → 1359,11 |
case RADEON_PP_CUBIC_OFFSET_T2_3: |
case RADEON_PP_CUBIC_OFFSET_T2_4: |
i = (reg - RADEON_PP_CUBIC_OFFSET_T2_0) / 4; |
r = r100_cs_packet_next_reloc(p, &reloc); |
r = radeon_cs_packet_next_reloc(p, &reloc, 0); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
radeon_cs_dump_packet(p, pkt); |
return r; |
} |
track->textures[2].cube_info[i].offset = idx_value; |
1396,11 → 1377,11 |
track->zb_dirty = true; |
break; |
case RADEON_RB3D_COLORPITCH: |
r = r100_cs_packet_next_reloc(p, &reloc); |
r = radeon_cs_packet_next_reloc(p, &reloc, 0); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
radeon_cs_dump_packet(p, pkt); |
return r; |
} |
if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { |
1467,11 → 1448,11 |
track->zb_dirty = true; |
break; |
case RADEON_RB3D_ZPASS_ADDR: |
r = r100_cs_packet_next_reloc(p, &reloc); |
r = radeon_cs_packet_next_reloc(p, &reloc, 0); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
radeon_cs_dump_packet(p, pkt); |
return r; |
} |
ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); |
1628,10 → 1609,10 |
return r; |
break; |
case PACKET3_INDX_BUFFER: |
r = r100_cs_packet_next_reloc(p, &reloc); |
r = radeon_cs_packet_next_reloc(p, &reloc, 0); |
if (r) { |
DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode); |
r100_cs_dump_packet(p, pkt); |
radeon_cs_dump_packet(p, pkt); |
return r; |
} |
ib[idx+1] = radeon_get_ib_value(p, idx+1) + ((u32)reloc->lobj.gpu_offset); |
1642,10 → 1623,10 |
break; |
case 0x23: |
/* 3D_RNDR_GEN_INDX_PRIM on r100/r200 */ |
r = r100_cs_packet_next_reloc(p, &reloc); |
r = radeon_cs_packet_next_reloc(p, &reloc, 0); |
if (r) { |
DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode); |
r100_cs_dump_packet(p, pkt); |
radeon_cs_dump_packet(p, pkt); |
return r; |
} |
ib[idx] = radeon_get_ib_value(p, idx) + ((u32)reloc->lobj.gpu_offset); |
1742,13 → 1723,13 |
r100_cs_track_clear(p->rdev, track); |
p->track = track; |
do { |
r = r100_cs_packet_parse(p, &pkt, p->idx); |
r = radeon_cs_packet_parse(p, &pkt, p->idx); |
if (r) { |
return r; |
} |
p->idx += pkt.count + 2; |
switch (pkt.type) { |
case PACKET_TYPE0: |
case RADEON_PACKET_TYPE0: |
if (p->rdev->family >= CHIP_R200) |
r = r100_cs_parse_packet0(p, &pkt, |
p->rdev->config.r100.reg_safe_bm, |
1760,9 → 1741,9 |
p->rdev->config.r100.reg_safe_bm_size, |
&r100_packet0_check); |
break; |
case PACKET_TYPE2: |
case RADEON_PACKET_TYPE2: |
break; |
case PACKET_TYPE3: |
case RADEON_PACKET_TYPE3: |
r = r100_packet3_check(p, &pkt); |
break; |
default: |
1770,9 → 1751,8 |
pkt.type); |
return -EINVAL; |
} |
if (r) { |
if (r) |
return r; |
} |
} while (p->idx < p->chunks[p->chunk_ib_idx].length_dw); |
return 0; |
} |
3593,6 → 3573,12 |
} |
|
/* Enable IRQ */ |
if (!rdev->irq.installed) { |
r = radeon_irq_kms_init(rdev); |
if (r) |
return r; |
} |
|
r100_irq_set(rdev); |
rdev->config.r100.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); |
/* 1M ring buffer */ |
3691,9 → 3677,6 |
r = radeon_fence_driver_init(rdev); |
if (r) |
return r; |
r = radeon_irq_kms_init(rdev); |
if (r) |
return r; |
/* Memory manager */ |
r = radeon_bo_init(rdev); |
if (r) |