diff options
| -rw-r--r-- | drivers/gpu/drm/i915/intel_pm.c | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 7caed0006ee7..6e2acfd687a1 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
| @@ -1028,6 +1028,12 @@ static uint16_t vlv_compute_wm_level(const struct intel_crtc_state *crtc_state, | |||
| 1028 | return min_t(int, wm, USHRT_MAX); | 1028 | return min_t(int, wm, USHRT_MAX); |
| 1029 | } | 1029 | } |
| 1030 | 1030 | ||
| 1031 | static bool vlv_need_sprite0_fifo_workaround(unsigned int active_planes) | ||
| 1032 | { | ||
| 1033 | return (active_planes & (BIT(PLANE_SPRITE0) | | ||
| 1034 | BIT(PLANE_SPRITE1))) == BIT(PLANE_SPRITE1); | ||
| 1035 | } | ||
| 1036 | |||
| 1031 | static int vlv_compute_fifo(struct intel_crtc_state *crtc_state) | 1037 | static int vlv_compute_fifo(struct intel_crtc_state *crtc_state) |
| 1032 | { | 1038 | { |
| 1033 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); | 1039 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); |
| @@ -1038,12 +1044,25 @@ static int vlv_compute_fifo(struct intel_crtc_state *crtc_state) | |||
| 1038 | int num_active_planes = hweight32(active_planes); | 1044 | int num_active_planes = hweight32(active_planes); |
| 1039 | const int fifo_size = 511; | 1045 | const int fifo_size = 511; |
| 1040 | int fifo_extra, fifo_left = fifo_size; | 1046 | int fifo_extra, fifo_left = fifo_size; |
| 1047 | int sprite0_fifo_extra = 0; | ||
| 1041 | unsigned int total_rate; | 1048 | unsigned int total_rate; |
| 1042 | enum plane_id plane_id; | 1049 | enum plane_id plane_id; |
| 1043 | 1050 | ||
| 1051 | /* | ||
| 1052 | * When enabling sprite0 after sprite1 has already been enabled | ||
| 1053 | * we tend to get an underrun unless sprite0 already has some | ||
| 1054 | * FIFO space allcoated. Hence we always allocate at least one | ||
| 1055 | * cacheline for sprite0 whenever sprite1 is enabled. | ||
| 1056 | * | ||
| 1057 | * All other plane enable sequences appear immune to this problem. | ||
| 1058 | */ | ||
| 1059 | if (vlv_need_sprite0_fifo_workaround(active_planes)) | ||
| 1060 | sprite0_fifo_extra = 1; | ||
| 1061 | |||
| 1044 | total_rate = raw->plane[PLANE_PRIMARY] + | 1062 | total_rate = raw->plane[PLANE_PRIMARY] + |
| 1045 | raw->plane[PLANE_SPRITE0] + | 1063 | raw->plane[PLANE_SPRITE0] + |
| 1046 | raw->plane[PLANE_SPRITE1]; | 1064 | raw->plane[PLANE_SPRITE1] + |
| 1065 | sprite0_fifo_extra; | ||
| 1047 | 1066 | ||
| 1048 | if (total_rate > fifo_size) | 1067 | if (total_rate > fifo_size) |
| 1049 | return -EINVAL; | 1068 | return -EINVAL; |
| @@ -1064,6 +1083,9 @@ static int vlv_compute_fifo(struct intel_crtc_state *crtc_state) | |||
| 1064 | fifo_left -= fifo_state->plane[plane_id]; | 1083 | fifo_left -= fifo_state->plane[plane_id]; |
| 1065 | } | 1084 | } |
| 1066 | 1085 | ||
| 1086 | fifo_state->plane[PLANE_SPRITE0] += sprite0_fifo_extra; | ||
| 1087 | fifo_left -= sprite0_fifo_extra; | ||
| 1088 | |||
| 1067 | fifo_state->plane[PLANE_CURSOR] = 63; | 1089 | fifo_state->plane[PLANE_CURSOR] = 63; |
| 1068 | 1090 | ||
| 1069 | fifo_extra = DIV_ROUND_UP(fifo_left, num_active_planes ?: 1); | 1091 | fifo_extra = DIV_ROUND_UP(fifo_left, num_active_planes ?: 1); |
