drm/radeon: refactor vline packet parsing function
authorIlija Hadzic <ihadzic@research.bell-labs.com>
Wed, 2 Jan 2013 23:27:43 +0000 (18:27 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 31 Jan 2013 21:24:43 +0000 (16:24 -0500)
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>
drivers/gpu/drm/radeon/evergreen_cs.c
drivers/gpu/drm/radeon/r600_cs.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_reg.h

index 883b9f7..2690532 100644 (file)
@@ -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.
  *
- * Userspace sends a special sequence for VLINE waits.
- * PACKET0 - VLINE_START_END + value
- * PACKET3 - WAIT_REG_MEM poll vline status reg
- * RELOC (P3) - crtc_id in reloc.
- *
- * 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.
+ * This is an Evergreen(+)-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 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;
-
-       /* parse the WAIT_REG_MEM */
-       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 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
+       };
+
+       return r600_cs_common_vline_parse(p, vline_start_end, vline_status);
 }
 
 static int evergreen_packet0_check(struct radeon_cs_parser *p,
index 6e6fa97..e61a013 100644 (file)
@@ -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.
  *
+ * 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.
  * PACKET0 - VLINE_START_END + value
  * 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
  * and WAIT_REG_MEM packets to the correct crtc.
  * 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_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);
        /* 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");
+               DRM_ERROR("vline WAIT_REG_MEM waiting on MEM instead of REG\n");
                return -EINVAL;
        }
        /* 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");
                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");
                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");
                return -EINVAL;
        }
@@ -959,7 +987,7 @@ static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
        crtc_id = radeon_crtc->crtc_id;
 
        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 + 3] = 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 + 7] = PACKET2(0);
                ib[h_idx + 8] = PACKET2(0);
-       } else if (crtc_id == 1) {
-               switch (reg) {
-               case AVIVO_D1MODE_VLINE_START_END:
-                       header &= ~R600_CP_PACKET0_REG_MASK;
-                       header |= AVIVO_D2MODE_VLINE_START_END >> 2;
-                       break;
-               default:
-                       DRM_ERROR("unknown crtc reloc\n");
-                       return -EINVAL;
-               }
+       } else if (reg == vline_start_end[0]) {
+               header &= ~R600_CP_PACKET0_REG_MASK;
+               header |= vline_start_end[crtc_id] >> 2;
                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;
 }
 
index 72c4836..5caeca3 100644 (file)
@@ -1976,7 +1976,9 @@ int radeon_cs_packet_parse(struct radeon_cs_parser *p,
                           struct radeon_cs_packet *pkt,
                           unsigned idx);
 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"
 
index ce7e9f2..7e2c2b7 100644 (file)
 
 #define RADEON_PACKET3_NOP 0x10
 
+#define RADEON_VLINE_STAT (1 << 12)
+
 #endif