diff options
author | Ilija Hadzic <ihadzic@research.bell-labs.com> | 2013-01-02 18:27:43 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-01-31 16:24:43 -0500 |
commit | 40592a17b8747903be95338f461573916a71d739 (patch) | |
tree | 0255123d601f1be2c11322ecabdcc368b81a1b16 /drivers/gpu | |
parent | 9ffb7a6dca4fd260db91c808efd4d5c56057600c (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.c | 120 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r600_cs.c | 61 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_reg.h | 2 |
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 | */ |
1071 | static int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p) | 1066 | static 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 | ||
1163 | static int evergreen_packet0_check(struct radeon_cs_parser *p, | 1089 | static 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 | */ | ||
888 | static 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 | */ |
893 | static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p) | 919 | int 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); |
1978 | bool radeon_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p); | 1978 | bool radeon_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p); |
1979 | 1979 | int 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 |