aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c24
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
1031static 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
1031static int vlv_compute_fifo(struct intel_crtc_state *crtc_state) 1037static 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);