aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorIlija Hadzic <ihadzic@research.bell-labs.com>2013-01-02 18:27:43 -0500
committerAlex Deucher <alexander.deucher@amd.com>2013-01-31 16:24:43 -0500
commit40592a17b8747903be95338f461573916a71d739 (patch)
tree0255123d601f1be2c11322ecabdcc368b81a1b16 /drivers/gpu
parent9ffb7a6dca4fd260db91c808efd4d5c56057600c (diff)
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>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/radeon/evergreen_cs.c120
-rw-r--r--drivers/gpu/drm/radeon/r600_cs.c61
-rw-r--r--drivers/gpu/drm/radeon/radeon.h4
-rw-r--r--drivers/gpu/drm/radeon/radeon_reg.h2
4 files changed, 70 insertions, 117 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c
index 883b9f76a495..26905322d8e7 100644
--- a/drivers/gpu/drm/radeon/evergreen_cs.c
+++ b/drivers/gpu/drm/radeon/evergreen_cs.c
@@ -1055,109 +1055,35 @@ static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
1055} 1055}
1056 1056
1057/** 1057/**
1058 * evergreen_cs_packet_next_vline() - parse userspace VLINE packet 1058 * evergreen_cs_packet_parse_vline() - parse userspace VLINE packet
1059 * @parser: parser structure holding parsing context. 1059 * @parser: parser structure holding parsing context.
1060 * 1060 *
1061 * Userspace sends a special sequence for VLINE waits. 1061 * This is an Evergreen(+)-specific function for parsing VLINE packets.
1062 * PACKET0 - VLINE_START_END + value 1062 * Real work is done by r600_cs_common_vline_parse function.
1063 * PACKET3 - WAIT_REG_MEM poll vline status reg 1063 * Here we just set up ASIC-specific register table and call
1064 * RELOC (P3) - crtc_id in reloc. 1064 * the common implementation function.
1065 *
1066 * This function parses this and relocates the VLINE START END
1067 * and WAIT_REG_MEM packets to the correct crtc.
1068 * It also detects a switched off crtc and nulls out the
1069 * wait in that case.
1070 */ 1065 */
1071static int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p) 1066static int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p)
1072{ 1067{
1073 struct drm_mode_object *obj;
1074 struct drm_crtc *crtc;
1075 struct radeon_crtc *radeon_crtc;
1076 struct radeon_cs_packet p3reloc, wait_reg_mem;
1077 int crtc_id;
1078 int r;
1079 uint32_t header, h_idx, reg, wait_reg_mem_info;
1080 volatile uint32_t *ib;
1081
1082 ib = p->ib.ptr;
1083
1084 /* parse the WAIT_REG_MEM */
1085 r = radeon_cs_packet_parse(p, &wait_reg_mem, p->idx);
1086 if (r)
1087 return r;
1088
1089 /* check its a WAIT_REG_MEM */
1090 if (wait_reg_mem.type != PACKET_TYPE3 ||
1091 wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {
1092 DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n");
1093 return -EINVAL;
1094 }
1095
1096 wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
1097 /* bit 4 is reg (0) or mem (1) */
1098 if (wait_reg_mem_info & 0x10) {
1099 DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n");
1100 return -EINVAL;
1101 }
1102 /* waiting for value to be equal */
1103 if ((wait_reg_mem_info & 0x7) != 0x3) {
1104 DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
1105 return -EINVAL;
1106 }
1107 if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != EVERGREEN_VLINE_STATUS) {
1108 DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
1109 return -EINVAL;
1110 }
1111 1068
1112 if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != EVERGREEN_VLINE_STAT) { 1069 static uint32_t vline_start_end[6] = {
1113 DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n"); 1070 EVERGREEN_VLINE_START_END + EVERGREEN_CRTC0_REGISTER_OFFSET,
1114 return -EINVAL; 1071 EVERGREEN_VLINE_START_END + EVERGREEN_CRTC1_REGISTER_OFFSET,
1115 } 1072 EVERGREEN_VLINE_START_END + EVERGREEN_CRTC2_REGISTER_OFFSET,
1116 1073 EVERGREEN_VLINE_START_END + EVERGREEN_CRTC3_REGISTER_OFFSET,
1117 /* jump over the NOP */ 1074 EVERGREEN_VLINE_START_END + EVERGREEN_CRTC4_REGISTER_OFFSET,
1118 r = radeon_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2); 1075 EVERGREEN_VLINE_START_END + EVERGREEN_CRTC5_REGISTER_OFFSET
1119 if (r) 1076 };
1120 return r; 1077 static uint32_t vline_status[6] = {
1121 1078 EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET,
1122 h_idx = p->idx - 2; 1079 EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET,
1123 p->idx += wait_reg_mem.count + 2; 1080 EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET,
1124 p->idx += p3reloc.count + 2; 1081 EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET,
1125 1082 EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET,
1126 header = radeon_get_ib_value(p, h_idx); 1083 EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET
1127 crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1); 1084 };
1128 reg = CP_PACKET0_GET_REG(header); 1085
1129 obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC); 1086 return r600_cs_common_vline_parse(p, vline_start_end, vline_status);
1130 if (!obj) {
1131 DRM_ERROR("cannot find crtc %d\n", crtc_id);
1132 return -EINVAL;
1133 }
1134 crtc = obj_to_crtc(obj);
1135 radeon_crtc = to_radeon_crtc(crtc);
1136 crtc_id = radeon_crtc->crtc_id;
1137
1138 if (!crtc->enabled) {
1139 /* if the CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */
1140 ib[h_idx + 2] = PACKET2(0);
1141 ib[h_idx + 3] = PACKET2(0);
1142 ib[h_idx + 4] = PACKET2(0);
1143 ib[h_idx + 5] = PACKET2(0);
1144 ib[h_idx + 6] = PACKET2(0);
1145 ib[h_idx + 7] = PACKET2(0);
1146 ib[h_idx + 8] = PACKET2(0);
1147 } else {
1148 switch (reg) {
1149 case EVERGREEN_VLINE_START_END:
1150 header &= ~R600_CP_PACKET0_REG_MASK;
1151 header |= (EVERGREEN_VLINE_START_END + radeon_crtc->crtc_offset) >> 2;
1152 ib[h_idx] = header;
1153 ib[h_idx + 4] = (EVERGREEN_VLINE_STATUS + radeon_crtc->crtc_offset) >> 2;
1154 break;
1155 default:
1156 DRM_ERROR("unknown crtc reloc\n");
1157 return -EINVAL;
1158 }
1159 }
1160 return 0;
1161} 1087}
1162 1088
1163static int evergreen_packet0_check(struct radeon_cs_parser *p, 1089static int evergreen_packet0_check(struct radeon_cs_parser *p,
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c
index 6e6fa97043d0..e61a013e63fc 100644
--- a/drivers/gpu/drm/radeon/r600_cs.c
+++ b/drivers/gpu/drm/radeon/r600_cs.c
@@ -877,9 +877,30 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
877} 877}
878 878
879/** 879/**
880 * r600_cs_packet_next_vline() - parse userspace VLINE packet 880 * r600_cs_packet_parse_vline() - parse userspace VLINE packet
881 * @parser: parser structure holding parsing context. 881 * @parser: parser structure holding parsing context.
882 * 882 *
883 * This is an R600-specific function for parsing VLINE packets.
884 * Real work is done by r600_cs_common_vline_parse function.
885 * Here we just set up ASIC-specific register table and call
886 * the common implementation function.
887 */
888static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
889{
890 static uint32_t vline_start_end[2] = {AVIVO_D1MODE_VLINE_START_END,
891 AVIVO_D2MODE_VLINE_START_END};
892 static uint32_t vline_status[2] = {AVIVO_D1MODE_VLINE_STATUS,
893 AVIVO_D2MODE_VLINE_STATUS};
894
895 return r600_cs_common_vline_parse(p, vline_start_end, vline_status);
896}
897
898/**
899 * r600_cs_common_vline_parse() - common vline parser
900 * @parser: parser structure holding parsing context.
901 * @vline_start_end: table of vline_start_end registers
902 * @vline_status: table of vline_status registers
903 *
883 * Userspace sends a special sequence for VLINE waits. 904 * Userspace sends a special sequence for VLINE waits.
884 * PACKET0 - VLINE_START_END + value 905 * PACKET0 - VLINE_START_END + value
885 * PACKET3 - WAIT_REG_MEM poll vline status reg 906 * 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,
888 * This function parses this and relocates the VLINE START END 909 * This function parses this and relocates the VLINE START END
889 * and WAIT_REG_MEM packets to the correct crtc. 910 * and WAIT_REG_MEM packets to the correct crtc.
890 * It also detects a switched off crtc and nulls out the 911 * It also detects a switched off crtc and nulls out the
891 * wait in that case. 912 * wait in that case. This function is common for all ASICs that
913 * are R600 and newer. The parsing algorithm is the same, and only
914 * differs in which registers are used.
915 *
916 * Caller is the ASIC-specific function which passes the parser
917 * context and ASIC-specific register table
892 */ 918 */
893static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p) 919int r600_cs_common_vline_parse(struct radeon_cs_parser *p,
920 uint32_t *vline_start_end,
921 uint32_t *vline_status)
894{ 922{
895 struct drm_mode_object *obj; 923 struct drm_mode_object *obj;
896 struct drm_crtc *crtc; 924 struct drm_crtc *crtc;
@@ -918,7 +946,7 @@ static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
918 wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1); 946 wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
919 /* bit 4 is reg (0) or mem (1) */ 947 /* bit 4 is reg (0) or mem (1) */
920 if (wait_reg_mem_info & 0x10) { 948 if (wait_reg_mem_info & 0x10) {
921 DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n"); 949 DRM_ERROR("vline WAIT_REG_MEM waiting on MEM instead of REG\n");
922 return -EINVAL; 950 return -EINVAL;
923 } 951 }
924 /* waiting for value to be equal */ 952 /* waiting for value to be equal */
@@ -926,12 +954,12 @@ static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
926 DRM_ERROR("vline WAIT_REG_MEM function not equal\n"); 954 DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
927 return -EINVAL; 955 return -EINVAL;
928 } 956 }
929 if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != AVIVO_D1MODE_VLINE_STATUS) { 957 if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != vline_status[0]) {
930 DRM_ERROR("vline WAIT_REG_MEM bad reg\n"); 958 DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
931 return -EINVAL; 959 return -EINVAL;
932 } 960 }
933 961
934 if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != AVIVO_D1MODE_VLINE_STAT) { 962 if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != RADEON_VLINE_STAT) {
935 DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n"); 963 DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");
936 return -EINVAL; 964 return -EINVAL;
937 } 965 }
@@ -959,7 +987,7 @@ static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
959 crtc_id = radeon_crtc->crtc_id; 987 crtc_id = radeon_crtc->crtc_id;
960 988
961 if (!crtc->enabled) { 989 if (!crtc->enabled) {
962 /* if the CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */ 990 /* CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */
963 ib[h_idx + 2] = PACKET2(0); 991 ib[h_idx + 2] = PACKET2(0);
964 ib[h_idx + 3] = PACKET2(0); 992 ib[h_idx + 3] = PACKET2(0);
965 ib[h_idx + 4] = PACKET2(0); 993 ib[h_idx + 4] = PACKET2(0);
@@ -967,20 +995,15 @@ static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
967 ib[h_idx + 6] = PACKET2(0); 995 ib[h_idx + 6] = PACKET2(0);
968 ib[h_idx + 7] = PACKET2(0); 996 ib[h_idx + 7] = PACKET2(0);
969 ib[h_idx + 8] = PACKET2(0); 997 ib[h_idx + 8] = PACKET2(0);
970 } else if (crtc_id == 1) { 998 } else if (reg == vline_start_end[0]) {
971 switch (reg) { 999 header &= ~R600_CP_PACKET0_REG_MASK;
972 case AVIVO_D1MODE_VLINE_START_END: 1000 header |= vline_start_end[crtc_id] >> 2;
973 header &= ~R600_CP_PACKET0_REG_MASK;
974 header |= AVIVO_D2MODE_VLINE_START_END >> 2;
975 break;
976 default:
977 DRM_ERROR("unknown crtc reloc\n");
978 return -EINVAL;
979 }
980 ib[h_idx] = header; 1001 ib[h_idx] = header;
981 ib[h_idx + 4] = AVIVO_D2MODE_VLINE_STATUS >> 2; 1002 ib[h_idx + 4] = vline_status[crtc_id] >> 2;
1003 } else {
1004 DRM_ERROR("unknown crtc reloc\n");
1005 return -EINVAL;
982 } 1006 }
983
984 return 0; 1007 return 0;
985} 1008}
986 1009
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 72c4836162ec..5caeca38383d 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1976,7 +1976,9 @@ int radeon_cs_packet_parse(struct radeon_cs_parser *p,
1976 struct radeon_cs_packet *pkt, 1976 struct radeon_cs_packet *pkt,
1977 unsigned idx); 1977 unsigned idx);
1978bool radeon_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p); 1978bool radeon_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p);
1979 1979int r600_cs_common_vline_parse(struct radeon_cs_parser *p,
1980 uint32_t *vline_start_end,
1981 uint32_t *vline_status);
1980 1982
1981#include "radeon_object.h" 1983#include "radeon_object.h"
1982 1984
diff --git a/drivers/gpu/drm/radeon/radeon_reg.h b/drivers/gpu/drm/radeon/radeon_reg.h
index ce7e9f29cc89..7e2c2b7cf188 100644
--- a/drivers/gpu/drm/radeon/radeon_reg.h
+++ b/drivers/gpu/drm/radeon/radeon_reg.h
@@ -3719,4 +3719,6 @@
3719 3719
3720#define RADEON_PACKET3_NOP 0x10 3720#define RADEON_PACKET3_NOP 0x10
3721 3721
3722#define RADEON_VLINE_STAT (1 << 12)
3723
3722#endif 3724#endif