diff options
author | Mario Kleiner <mario.kleiner@tuebingen.mpg.de> | 2010-10-22 22:42:17 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-11-21 20:48:26 -0500 |
commit | f5a8020903932624cf020dc72455a10a3e005087 (patch) | |
tree | fed9a5a2acadf001d5866d42dad8b308f864ac75 /drivers/gpu/drm/radeon/radeon_display.c | |
parent | 27641c3f003e7f3b6585c01d8a788883603eb262 (diff) |
drm/kms/radeon: Add support for precise vblank timestamping.
This patch adds new functions for use by the drm core:
.get_vblank_timestamp() provides a precise timestamp
for the end of the most recent (or current) vblank
interval of a given crtc, as needed for the DRI2
implementation of the OML_sync_control extension.
It is a thin wrapper around the drm function
drm_calc_vbltimestamp_from_scanoutpos() which does
almost all the work and is shared across drivers.
.get_scanout_position() provides the current horizontal
and vertical video scanout position and "in vblank"
status of a given crtc, as needed by the drm for use by
drm_calc_vbltimestamp_from_scanoutpos().
The function is also used by the dynamic gpu reclocking
code to determine when it is safe to reclock inside vblank.
For that purpose radeon_pm_in_vbl() is modified to
accomodate a small change in the function prototype of
the radeon_get_crtc_scanoutpos() which is hooked up to
.get_scanout_position().
This code has been tested on AVIVO hardware, a RV530
(ATI Mobility Radeon X1600) in a Intel Core-2 Duo MacBookPro
and some R600 variant (FireGL V7600) in a single cpu
AMD Athlon 64 PC.
Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
Reviewed-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_display.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_display.c | 40 |
1 files changed, 21 insertions, 19 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 1df4dc6c063c..eeea7cbb9517 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
@@ -1019,7 +1019,7 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, | |||
1019 | /* | 1019 | /* |
1020 | * Retrieve current video scanout position of crtc on a given gpu. | 1020 | * Retrieve current video scanout position of crtc on a given gpu. |
1021 | * | 1021 | * |
1022 | * \param rdev Device to query. | 1022 | * \param dev Device to query. |
1023 | * \param crtc Crtc to query. | 1023 | * \param crtc Crtc to query. |
1024 | * \param *vpos Location where vertical scanout position should be stored. | 1024 | * \param *vpos Location where vertical scanout position should be stored. |
1025 | * \param *hpos Location where horizontal scanout position should go. | 1025 | * \param *hpos Location where horizontal scanout position should go. |
@@ -1031,72 +1031,74 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, | |||
1031 | * | 1031 | * |
1032 | * \return Flags, or'ed together as follows: | 1032 | * \return Flags, or'ed together as follows: |
1033 | * | 1033 | * |
1034 | * RADEON_SCANOUTPOS_VALID = Query successfull. | 1034 | * DRM_SCANOUTPOS_VALID = Query successfull. |
1035 | * RADEON_SCANOUTPOS_INVBL = Inside vblank. | 1035 | * DRM_SCANOUTPOS_INVBL = Inside vblank. |
1036 | * RADEON_SCANOUTPOS_ACCURATE = Returned position is accurate. A lack of | 1036 | * DRM_SCANOUTPOS_ACCURATE = Returned position is accurate. A lack of |
1037 | * this flag means that returned position may be offset by a constant but | 1037 | * this flag means that returned position may be offset by a constant but |
1038 | * unknown small number of scanlines wrt. real scanout position. | 1038 | * unknown small number of scanlines wrt. real scanout position. |
1039 | * | 1039 | * |
1040 | */ | 1040 | */ |
1041 | int radeon_get_crtc_scanoutpos(struct radeon_device *rdev, int crtc, int *vpos, int *hpos) | 1041 | int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, int *vpos, int *hpos) |
1042 | { | 1042 | { |
1043 | u32 stat_crtc = 0, vbl = 0, position = 0; | 1043 | u32 stat_crtc = 0, vbl = 0, position = 0; |
1044 | int vbl_start, vbl_end, vtotal, ret = 0; | 1044 | int vbl_start, vbl_end, vtotal, ret = 0; |
1045 | bool in_vbl = true; | 1045 | bool in_vbl = true; |
1046 | 1046 | ||
1047 | struct radeon_device *rdev = dev->dev_private; | ||
1048 | |||
1047 | if (ASIC_IS_DCE4(rdev)) { | 1049 | if (ASIC_IS_DCE4(rdev)) { |
1048 | if (crtc == 0) { | 1050 | if (crtc == 0) { |
1049 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + | 1051 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + |
1050 | EVERGREEN_CRTC0_REGISTER_OFFSET); | 1052 | EVERGREEN_CRTC0_REGISTER_OFFSET); |
1051 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + | 1053 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + |
1052 | EVERGREEN_CRTC0_REGISTER_OFFSET); | 1054 | EVERGREEN_CRTC0_REGISTER_OFFSET); |
1053 | ret |= RADEON_SCANOUTPOS_VALID; | 1055 | ret |= DRM_SCANOUTPOS_VALID; |
1054 | } | 1056 | } |
1055 | if (crtc == 1) { | 1057 | if (crtc == 1) { |
1056 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + | 1058 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + |
1057 | EVERGREEN_CRTC1_REGISTER_OFFSET); | 1059 | EVERGREEN_CRTC1_REGISTER_OFFSET); |
1058 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + | 1060 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + |
1059 | EVERGREEN_CRTC1_REGISTER_OFFSET); | 1061 | EVERGREEN_CRTC1_REGISTER_OFFSET); |
1060 | ret |= RADEON_SCANOUTPOS_VALID; | 1062 | ret |= DRM_SCANOUTPOS_VALID; |
1061 | } | 1063 | } |
1062 | if (crtc == 2) { | 1064 | if (crtc == 2) { |
1063 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + | 1065 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + |
1064 | EVERGREEN_CRTC2_REGISTER_OFFSET); | 1066 | EVERGREEN_CRTC2_REGISTER_OFFSET); |
1065 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + | 1067 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + |
1066 | EVERGREEN_CRTC2_REGISTER_OFFSET); | 1068 | EVERGREEN_CRTC2_REGISTER_OFFSET); |
1067 | ret |= RADEON_SCANOUTPOS_VALID; | 1069 | ret |= DRM_SCANOUTPOS_VALID; |
1068 | } | 1070 | } |
1069 | if (crtc == 3) { | 1071 | if (crtc == 3) { |
1070 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + | 1072 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + |
1071 | EVERGREEN_CRTC3_REGISTER_OFFSET); | 1073 | EVERGREEN_CRTC3_REGISTER_OFFSET); |
1072 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + | 1074 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + |
1073 | EVERGREEN_CRTC3_REGISTER_OFFSET); | 1075 | EVERGREEN_CRTC3_REGISTER_OFFSET); |
1074 | ret |= RADEON_SCANOUTPOS_VALID; | 1076 | ret |= DRM_SCANOUTPOS_VALID; |
1075 | } | 1077 | } |
1076 | if (crtc == 4) { | 1078 | if (crtc == 4) { |
1077 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + | 1079 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + |
1078 | EVERGREEN_CRTC4_REGISTER_OFFSET); | 1080 | EVERGREEN_CRTC4_REGISTER_OFFSET); |
1079 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + | 1081 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + |
1080 | EVERGREEN_CRTC4_REGISTER_OFFSET); | 1082 | EVERGREEN_CRTC4_REGISTER_OFFSET); |
1081 | ret |= RADEON_SCANOUTPOS_VALID; | 1083 | ret |= DRM_SCANOUTPOS_VALID; |
1082 | } | 1084 | } |
1083 | if (crtc == 5) { | 1085 | if (crtc == 5) { |
1084 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + | 1086 | vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + |
1085 | EVERGREEN_CRTC5_REGISTER_OFFSET); | 1087 | EVERGREEN_CRTC5_REGISTER_OFFSET); |
1086 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + | 1088 | position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + |
1087 | EVERGREEN_CRTC5_REGISTER_OFFSET); | 1089 | EVERGREEN_CRTC5_REGISTER_OFFSET); |
1088 | ret |= RADEON_SCANOUTPOS_VALID; | 1090 | ret |= DRM_SCANOUTPOS_VALID; |
1089 | } | 1091 | } |
1090 | } else if (ASIC_IS_AVIVO(rdev)) { | 1092 | } else if (ASIC_IS_AVIVO(rdev)) { |
1091 | if (crtc == 0) { | 1093 | if (crtc == 0) { |
1092 | vbl = RREG32(AVIVO_D1CRTC_V_BLANK_START_END); | 1094 | vbl = RREG32(AVIVO_D1CRTC_V_BLANK_START_END); |
1093 | position = RREG32(AVIVO_D1CRTC_STATUS_POSITION); | 1095 | position = RREG32(AVIVO_D1CRTC_STATUS_POSITION); |
1094 | ret |= RADEON_SCANOUTPOS_VALID; | 1096 | ret |= DRM_SCANOUTPOS_VALID; |
1095 | } | 1097 | } |
1096 | if (crtc == 1) { | 1098 | if (crtc == 1) { |
1097 | vbl = RREG32(AVIVO_D2CRTC_V_BLANK_START_END); | 1099 | vbl = RREG32(AVIVO_D2CRTC_V_BLANK_START_END); |
1098 | position = RREG32(AVIVO_D2CRTC_STATUS_POSITION); | 1100 | position = RREG32(AVIVO_D2CRTC_STATUS_POSITION); |
1099 | ret |= RADEON_SCANOUTPOS_VALID; | 1101 | ret |= DRM_SCANOUTPOS_VALID; |
1100 | } | 1102 | } |
1101 | } else { | 1103 | } else { |
1102 | /* Pre-AVIVO: Different encoding of scanout pos and vblank interval. */ | 1104 | /* Pre-AVIVO: Different encoding of scanout pos and vblank interval. */ |
@@ -1112,7 +1114,7 @@ int radeon_get_crtc_scanoutpos(struct radeon_device *rdev, int crtc, int *vpos, | |||
1112 | if (!(stat_crtc & 1)) | 1114 | if (!(stat_crtc & 1)) |
1113 | in_vbl = false; | 1115 | in_vbl = false; |
1114 | 1116 | ||
1115 | ret |= RADEON_SCANOUTPOS_VALID; | 1117 | ret |= DRM_SCANOUTPOS_VALID; |
1116 | } | 1118 | } |
1117 | if (crtc == 1) { | 1119 | if (crtc == 1) { |
1118 | vbl = (RREG32(RADEON_CRTC2_V_TOTAL_DISP) & | 1120 | vbl = (RREG32(RADEON_CRTC2_V_TOTAL_DISP) & |
@@ -1122,7 +1124,7 @@ int radeon_get_crtc_scanoutpos(struct radeon_device *rdev, int crtc, int *vpos, | |||
1122 | if (!(stat_crtc & 1)) | 1124 | if (!(stat_crtc & 1)) |
1123 | in_vbl = false; | 1125 | in_vbl = false; |
1124 | 1126 | ||
1125 | ret |= RADEON_SCANOUTPOS_VALID; | 1127 | ret |= DRM_SCANOUTPOS_VALID; |
1126 | } | 1128 | } |
1127 | } | 1129 | } |
1128 | 1130 | ||
@@ -1133,13 +1135,13 @@ int radeon_get_crtc_scanoutpos(struct radeon_device *rdev, int crtc, int *vpos, | |||
1133 | /* Valid vblank area boundaries from gpu retrieved? */ | 1135 | /* Valid vblank area boundaries from gpu retrieved? */ |
1134 | if (vbl > 0) { | 1136 | if (vbl > 0) { |
1135 | /* Yes: Decode. */ | 1137 | /* Yes: Decode. */ |
1136 | ret |= RADEON_SCANOUTPOS_ACCURATE; | 1138 | ret |= DRM_SCANOUTPOS_ACCURATE; |
1137 | vbl_start = vbl & 0x1fff; | 1139 | vbl_start = vbl & 0x1fff; |
1138 | vbl_end = (vbl >> 16) & 0x1fff; | 1140 | vbl_end = (vbl >> 16) & 0x1fff; |
1139 | } | 1141 | } |
1140 | else { | 1142 | else { |
1141 | /* No: Fake something reasonable which gives at least ok results. */ | 1143 | /* No: Fake something reasonable which gives at least ok results. */ |
1142 | vbl_start = rdev->mode_info.crtcs[crtc]->base.mode.crtc_vdisplay; | 1144 | vbl_start = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay; |
1143 | vbl_end = 0; | 1145 | vbl_end = 0; |
1144 | } | 1146 | } |
1145 | 1147 | ||
@@ -1155,7 +1157,7 @@ int radeon_get_crtc_scanoutpos(struct radeon_device *rdev, int crtc, int *vpos, | |||
1155 | 1157 | ||
1156 | /* Inside "upper part" of vblank area? Apply corrective offset if so: */ | 1158 | /* Inside "upper part" of vblank area? Apply corrective offset if so: */ |
1157 | if (in_vbl && (*vpos >= vbl_start)) { | 1159 | if (in_vbl && (*vpos >= vbl_start)) { |
1158 | vtotal = rdev->mode_info.crtcs[crtc]->base.mode.crtc_vtotal; | 1160 | vtotal = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vtotal; |
1159 | *vpos = *vpos - vtotal; | 1161 | *vpos = *vpos - vtotal; |
1160 | } | 1162 | } |
1161 | 1163 | ||
@@ -1164,7 +1166,7 @@ int radeon_get_crtc_scanoutpos(struct radeon_device *rdev, int crtc, int *vpos, | |||
1164 | 1166 | ||
1165 | /* In vblank? */ | 1167 | /* In vblank? */ |
1166 | if (in_vbl) | 1168 | if (in_vbl) |
1167 | ret |= RADEON_SCANOUTPOS_INVBL; | 1169 | ret |= DRM_SCANOUTPOS_INVBL; |
1168 | 1170 | ||
1169 | return ret; | 1171 | return ret; |
1170 | } | 1172 | } |