drm/radeon: refactor vline packet parsing function
vline packet parsing function for R600 and Evergreen+ are the same, except that they use different registers. Factor out the algorithm into a common function that uses register table passed from ASIC-specific caller. This reduces ASIC-specific function to (trivial) setup of register table and call into the common function. Signed-off-by: Ilija Hadzic <ihadzic@research.bell-labs.com> Reviewed-by: Marek Olšák <maraeo@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
9ffb7a6dca
commit
40592a17b8
4 changed files with 69 additions and 116 deletions
|
@ -1055,109 +1055,35 @@ static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* evergreen_cs_packet_next_vline() - parse userspace VLINE packet
|
* evergreen_cs_packet_parse_vline() - parse userspace VLINE packet
|
||||||
* @parser: parser structure holding parsing context.
|
* @parser: parser structure holding parsing context.
|
||||||
*
|
*
|
||||||
* Userspace sends a special sequence for VLINE waits.
|
* This is an Evergreen(+)-specific function for parsing VLINE packets.
|
||||||
* PACKET0 - VLINE_START_END + value
|
* Real work is done by r600_cs_common_vline_parse function.
|
||||||
* PACKET3 - WAIT_REG_MEM poll vline status reg
|
* Here we just set up ASIC-specific register table and call
|
||||||
* RELOC (P3) - crtc_id in reloc.
|
* the common implementation function.
|
||||||
*
|
|
||||||
* This function parses this and relocates the VLINE START END
|
|
||||||
* and WAIT_REG_MEM packets to the correct crtc.
|
|
||||||
* It also detects a switched off crtc and nulls out the
|
|
||||||
* wait in that case.
|
|
||||||
*/
|
*/
|
||||||
static int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p)
|
static int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p)
|
||||||
{
|
{
|
||||||
struct drm_mode_object *obj;
|
|
||||||
struct drm_crtc *crtc;
|
|
||||||
struct radeon_crtc *radeon_crtc;
|
|
||||||
struct radeon_cs_packet p3reloc, wait_reg_mem;
|
|
||||||
int crtc_id;
|
|
||||||
int r;
|
|
||||||
uint32_t header, h_idx, reg, wait_reg_mem_info;
|
|
||||||
volatile uint32_t *ib;
|
|
||||||
|
|
||||||
ib = p->ib.ptr;
|
static uint32_t vline_start_end[6] = {
|
||||||
|
EVERGREEN_VLINE_START_END + EVERGREEN_CRTC0_REGISTER_OFFSET,
|
||||||
|
EVERGREEN_VLINE_START_END + EVERGREEN_CRTC1_REGISTER_OFFSET,
|
||||||
|
EVERGREEN_VLINE_START_END + EVERGREEN_CRTC2_REGISTER_OFFSET,
|
||||||
|
EVERGREEN_VLINE_START_END + EVERGREEN_CRTC3_REGISTER_OFFSET,
|
||||||
|
EVERGREEN_VLINE_START_END + EVERGREEN_CRTC4_REGISTER_OFFSET,
|
||||||
|
EVERGREEN_VLINE_START_END + EVERGREEN_CRTC5_REGISTER_OFFSET
|
||||||
|
};
|
||||||
|
static uint32_t vline_status[6] = {
|
||||||
|
EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET,
|
||||||
|
EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET,
|
||||||
|
EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET,
|
||||||
|
EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET,
|
||||||
|
EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET,
|
||||||
|
EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET
|
||||||
|
};
|
||||||
|
|
||||||
/* parse the WAIT_REG_MEM */
|
return r600_cs_common_vline_parse(p, vline_start_end, vline_status);
|
||||||
r = radeon_cs_packet_parse(p, &wait_reg_mem, p->idx);
|
|
||||||
if (r)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
/* check its a WAIT_REG_MEM */
|
|
||||||
if (wait_reg_mem.type != PACKET_TYPE3 ||
|
|
||||||
wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {
|
|
||||||
DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
|
|
||||||
/* bit 4 is reg (0) or mem (1) */
|
|
||||||
if (wait_reg_mem_info & 0x10) {
|
|
||||||
DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
/* waiting for value to be equal */
|
|
||||||
if ((wait_reg_mem_info & 0x7) != 0x3) {
|
|
||||||
DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != EVERGREEN_VLINE_STATUS) {
|
|
||||||
DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != EVERGREEN_VLINE_STAT) {
|
|
||||||
DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* jump over the NOP */
|
|
||||||
r = radeon_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2);
|
|
||||||
if (r)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
h_idx = p->idx - 2;
|
|
||||||
p->idx += wait_reg_mem.count + 2;
|
|
||||||
p->idx += p3reloc.count + 2;
|
|
||||||
|
|
||||||
header = radeon_get_ib_value(p, h_idx);
|
|
||||||
crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
|
|
||||||
reg = 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);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
crtc = obj_to_crtc(obj);
|
|
||||||
radeon_crtc = to_radeon_crtc(crtc);
|
|
||||||
crtc_id = radeon_crtc->crtc_id;
|
|
||||||
|
|
||||||
if (!crtc->enabled) {
|
|
||||||
/* if the CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */
|
|
||||||
ib[h_idx + 2] = PACKET2(0);
|
|
||||||
ib[h_idx + 3] = PACKET2(0);
|
|
||||||
ib[h_idx + 4] = PACKET2(0);
|
|
||||||
ib[h_idx + 5] = PACKET2(0);
|
|
||||||
ib[h_idx + 6] = PACKET2(0);
|
|
||||||
ib[h_idx + 7] = PACKET2(0);
|
|
||||||
ib[h_idx + 8] = PACKET2(0);
|
|
||||||
} else {
|
|
||||||
switch (reg) {
|
|
||||||
case EVERGREEN_VLINE_START_END:
|
|
||||||
header &= ~R600_CP_PACKET0_REG_MASK;
|
|
||||||
header |= (EVERGREEN_VLINE_START_END + radeon_crtc->crtc_offset) >> 2;
|
|
||||||
ib[h_idx] = header;
|
|
||||||
ib[h_idx + 4] = (EVERGREEN_VLINE_STATUS + radeon_crtc->crtc_offset) >> 2;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
DRM_ERROR("unknown crtc reloc\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int evergreen_packet0_check(struct radeon_cs_parser *p,
|
static int evergreen_packet0_check(struct radeon_cs_parser *p,
|
||||||
|
|
|
@ -877,9 +877,30 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* r600_cs_packet_next_vline() - parse userspace VLINE packet
|
* r600_cs_packet_parse_vline() - parse userspace VLINE packet
|
||||||
* @parser: parser structure holding parsing context.
|
* @parser: parser structure holding parsing context.
|
||||||
*
|
*
|
||||||
|
* This is an R600-specific function for parsing VLINE packets.
|
||||||
|
* Real work is done by r600_cs_common_vline_parse function.
|
||||||
|
* Here we just set up ASIC-specific register table and call
|
||||||
|
* the common implementation function.
|
||||||
|
*/
|
||||||
|
static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
|
||||||
|
{
|
||||||
|
static uint32_t vline_start_end[2] = {AVIVO_D1MODE_VLINE_START_END,
|
||||||
|
AVIVO_D2MODE_VLINE_START_END};
|
||||||
|
static uint32_t vline_status[2] = {AVIVO_D1MODE_VLINE_STATUS,
|
||||||
|
AVIVO_D2MODE_VLINE_STATUS};
|
||||||
|
|
||||||
|
return r600_cs_common_vline_parse(p, vline_start_end, vline_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* r600_cs_common_vline_parse() - common vline parser
|
||||||
|
* @parser: parser structure holding parsing context.
|
||||||
|
* @vline_start_end: table of vline_start_end registers
|
||||||
|
* @vline_status: table of vline_status registers
|
||||||
|
*
|
||||||
* Userspace sends a special sequence for VLINE waits.
|
* Userspace sends a special sequence for VLINE waits.
|
||||||
* PACKET0 - VLINE_START_END + value
|
* PACKET0 - VLINE_START_END + value
|
||||||
* PACKET3 - WAIT_REG_MEM poll vline status reg
|
* PACKET3 - WAIT_REG_MEM poll vline status reg
|
||||||
|
@ -888,9 +909,16 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
|
||||||
* This function parses this and relocates the VLINE START END
|
* This function parses this and relocates the VLINE START END
|
||||||
* and WAIT_REG_MEM packets to the correct crtc.
|
* and WAIT_REG_MEM packets to the correct crtc.
|
||||||
* It also detects a switched off crtc and nulls out the
|
* It also detects a switched off crtc and nulls out the
|
||||||
* wait in that case.
|
* wait in that case. This function is common for all ASICs that
|
||||||
|
* are R600 and newer. The parsing algorithm is the same, and only
|
||||||
|
* differs in which registers are used.
|
||||||
|
*
|
||||||
|
* Caller is the ASIC-specific function which passes the parser
|
||||||
|
* context and ASIC-specific register table
|
||||||
*/
|
*/
|
||||||
static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
|
int r600_cs_common_vline_parse(struct radeon_cs_parser *p,
|
||||||
|
uint32_t *vline_start_end,
|
||||||
|
uint32_t *vline_status)
|
||||||
{
|
{
|
||||||
struct drm_mode_object *obj;
|
struct drm_mode_object *obj;
|
||||||
struct drm_crtc *crtc;
|
struct drm_crtc *crtc;
|
||||||
|
@ -918,7 +946,7 @@ static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
|
||||||
wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
|
wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
|
||||||
/* bit 4 is reg (0) or mem (1) */
|
/* bit 4 is reg (0) or mem (1) */
|
||||||
if (wait_reg_mem_info & 0x10) {
|
if (wait_reg_mem_info & 0x10) {
|
||||||
DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n");
|
DRM_ERROR("vline WAIT_REG_MEM waiting on MEM instead of REG\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
/* waiting for value to be equal */
|
/* waiting for value to be equal */
|
||||||
|
@ -926,12 +954,12 @@ static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
|
||||||
DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
|
DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != AVIVO_D1MODE_VLINE_STATUS) {
|
if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != vline_status[0]) {
|
||||||
DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
|
DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != AVIVO_D1MODE_VLINE_STAT) {
|
if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != RADEON_VLINE_STAT) {
|
||||||
DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");
|
DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -959,7 +987,7 @@ static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
|
||||||
crtc_id = radeon_crtc->crtc_id;
|
crtc_id = radeon_crtc->crtc_id;
|
||||||
|
|
||||||
if (!crtc->enabled) {
|
if (!crtc->enabled) {
|
||||||
/* if the CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */
|
/* CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */
|
||||||
ib[h_idx + 2] = PACKET2(0);
|
ib[h_idx + 2] = PACKET2(0);
|
||||||
ib[h_idx + 3] = PACKET2(0);
|
ib[h_idx + 3] = PACKET2(0);
|
||||||
ib[h_idx + 4] = PACKET2(0);
|
ib[h_idx + 4] = PACKET2(0);
|
||||||
|
@ -967,20 +995,15 @@ static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
|
||||||
ib[h_idx + 6] = PACKET2(0);
|
ib[h_idx + 6] = PACKET2(0);
|
||||||
ib[h_idx + 7] = PACKET2(0);
|
ib[h_idx + 7] = PACKET2(0);
|
||||||
ib[h_idx + 8] = PACKET2(0);
|
ib[h_idx + 8] = PACKET2(0);
|
||||||
} else if (crtc_id == 1) {
|
} else if (reg == vline_start_end[0]) {
|
||||||
switch (reg) {
|
header &= ~R600_CP_PACKET0_REG_MASK;
|
||||||
case AVIVO_D1MODE_VLINE_START_END:
|
header |= vline_start_end[crtc_id] >> 2;
|
||||||
header &= ~R600_CP_PACKET0_REG_MASK;
|
|
||||||
header |= AVIVO_D2MODE_VLINE_START_END >> 2;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
DRM_ERROR("unknown crtc reloc\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
ib[h_idx] = header;
|
ib[h_idx] = header;
|
||||||
ib[h_idx + 4] = AVIVO_D2MODE_VLINE_STATUS >> 2;
|
ib[h_idx + 4] = vline_status[crtc_id] >> 2;
|
||||||
|
} else {
|
||||||
|
DRM_ERROR("unknown crtc reloc\n");
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1976,7 +1976,9 @@ int radeon_cs_packet_parse(struct radeon_cs_parser *p,
|
||||||
struct radeon_cs_packet *pkt,
|
struct radeon_cs_packet *pkt,
|
||||||
unsigned idx);
|
unsigned idx);
|
||||||
bool radeon_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p);
|
bool radeon_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p);
|
||||||
|
int r600_cs_common_vline_parse(struct radeon_cs_parser *p,
|
||||||
|
uint32_t *vline_start_end,
|
||||||
|
uint32_t *vline_status);
|
||||||
|
|
||||||
#include "radeon_object.h"
|
#include "radeon_object.h"
|
||||||
|
|
||||||
|
|
|
@ -3719,4 +3719,6 @@
|
||||||
|
|
||||||
#define RADEON_PACKET3_NOP 0x10
|
#define RADEON_PACKET3_NOP 0x10
|
||||||
|
|
||||||
|
#define RADEON_VLINE_STAT (1 << 12)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue