ba27bbc6d5dd8027dbd50d644194e37ba7afa0c9
[openwrt/openwrt.git] / target / linux / bcm27xx / patches-5.15 / 950-0787-vc4-drm-vc4_plane-Keep-fractional-source-coords-insi.patch
1 From 7c0802428580f42e538dc8dcff8e5fbed80a5202 Mon Sep 17 00:00:00 2001
2 From: Dom Cobley <popcornmix@gmail.com>
3 Date: Mon, 14 Mar 2022 17:56:10 +0000
4 Subject: [PATCH] vc4/drm: vc4_plane: Keep fractional source coords
5 inside state
6
7 Signed-off-by: Dom Cobley <popcornmix@gmail.com>
8 ---
9 drivers/gpu/drm/vc4/vc4_drv.h | 2 +-
10 drivers/gpu/drm/vc4/vc4_plane.c | 67 ++++++++++++++++-----------------
11 2 files changed, 34 insertions(+), 35 deletions(-)
12
13 --- a/drivers/gpu/drm/vc4/vc4_drv.h
14 +++ b/drivers/gpu/drm/vc4/vc4_drv.h
15 @@ -386,7 +386,7 @@ struct vc4_plane_state {
16
17 /* Clipped coordinates of the plane on the display. */
18 int crtc_x, crtc_y, crtc_w, crtc_h;
19 - /* Clipped area being scanned from in the FB. */
20 + /* Clipped area being scanned from in the FB in u16.16 format */
21 u32 src_x, src_y;
22
23 u32 src_w[2], src_h[2];
24 --- a/drivers/gpu/drm/vc4/vc4_plane.c
25 +++ b/drivers/gpu/drm/vc4/vc4_plane.c
26 @@ -181,9 +181,9 @@ static const struct hvs_format *vc4_get_
27
28 static enum vc4_scaling_mode vc4_get_scaling_mode(u32 src, u32 dst)
29 {
30 - if (dst == src)
31 + if (dst == src >> 16)
32 return VC4_SCALING_NONE;
33 - if (3 * dst >= 2 * src)
34 + if (3 * dst >= 2 * (src >> 16))
35 return VC4_SCALING_PPF;
36 else
37 return VC4_SCALING_TPZ;
38 @@ -390,15 +390,10 @@ static int vc4_plane_setup_clipping_and_
39 for (i = 0; i < num_planes; i++)
40 vc4_state->offsets[i] = bo->paddr + fb->offsets[i];
41
42 - /*
43 - * We don't support subpixel source positioning for scaling,
44 - * but fractional coordinates can be generated by clipping
45 - * so just round for now
46 - */
47 - vc4_state->src_x = DIV_ROUND_CLOSEST(state->src.x1, 1 << 16);
48 - vc4_state->src_y = DIV_ROUND_CLOSEST(state->src.y1, 1 << 16);
49 - vc4_state->src_w[0] = DIV_ROUND_CLOSEST(state->src.x2, 1 << 16) - vc4_state->src_x;
50 - vc4_state->src_h[0] = DIV_ROUND_CLOSEST(state->src.y2, 1 << 16) - vc4_state->src_y;
51 + vc4_state->src_x = state->src.x1;
52 + vc4_state->src_y = state->src.y1;
53 + vc4_state->src_w[0] = state->src.x2 - vc4_state->src_x;
54 + vc4_state->src_h[0] = state->src.y2 - vc4_state->src_y;
55
56 vc4_state->crtc_x = state->dst.x1;
57 vc4_state->crtc_y = state->dst.y1;
58 @@ -451,7 +446,7 @@ static void vc4_write_tpz(struct vc4_pla
59 {
60 u32 scale, recip;
61
62 - scale = (1 << 16) * src / dst;
63 + scale = src / dst;
64
65 /* The specs note that while the reciprocal would be defined
66 * as (1<<32)/scale, ~0 is close enough.
67 @@ -497,7 +492,7 @@ static u32 vc4_lbm_size(struct drm_plane
68 if (vc4_state->x_scaling[0] == VC4_SCALING_TPZ)
69 pix_per_line = vc4_state->crtc_w;
70 else
71 - pix_per_line = vc4_state->src_w[0];
72 + pix_per_line = vc4_state->src_w[0] >> 16;
73
74 if (!vc4_state->is_yuv) {
75 if (vc4_state->y_scaling[0] == VC4_SCALING_TPZ)
76 @@ -588,7 +583,8 @@ static void vc4_plane_calc_load(struct d
77 for (i = 0; i < fb->format->num_planes; i++) {
78 /* Even if the bandwidth/plane required for a single frame is
79 *
80 - * vc4_state->src_w[i] * vc4_state->src_h[i] * cpp * vrefresh
81 + * (vc4_state->src_w[i] >> 16) * (vc4_state->src_h[i] >> 16) *
82 + * cpp * vrefresh
83 *
84 * when downscaling, we have to read more pixels per line in
85 * the time frame reserved for a single line, so the bandwidth
86 @@ -597,11 +593,11 @@ static void vc4_plane_calc_load(struct d
87 * load by this number. We're likely over-estimating the read
88 * demand, but that's better than under-estimating it.
89 */
90 - vscale_factor = DIV_ROUND_UP(vc4_state->src_h[i],
91 + vscale_factor = DIV_ROUND_UP(vc4_state->src_h[i] >> 16,
92 vc4_state->crtc_h);
93 - vc4_state->membus_load += vc4_state->src_w[i] *
94 - vc4_state->src_h[i] * vscale_factor *
95 - fb->format->cpp[i];
96 + vc4_state->membus_load += (vc4_state->src_w[i] >> 16) *
97 + (vc4_state->src_h[i] >> 16) *
98 + vscale_factor * fb->format->cpp[i];
99 vc4_state->hvs_load += vc4_state->crtc_h * vc4_state->crtc_w;
100 }
101
102 @@ -754,7 +750,8 @@ static int vc4_plane_mode_set(struct drm
103 bool mix_plane_alpha;
104 bool covers_screen;
105 u32 scl0, scl1, pitch0;
106 - u32 tiling, src_y;
107 + u32 tiling, src_x, src_y;
108 + u32 width, height;
109 u32 hvs_format = format->hvs;
110 unsigned int rotation;
111 int ret, i;
112 @@ -766,6 +763,9 @@ static int vc4_plane_mode_set(struct drm
113 if (ret)
114 return ret;
115
116 + width = vc4_state->src_w[0] >> 16;
117 + height = vc4_state->src_h[0] >> 16;
118 +
119 /* SCL1 is used for Cb/Cr scaling of planar formats. For RGB
120 * and 4:4:4, scl1 should be set to scl0 so both channels of
121 * the scaler do the same thing. For YUV, the Y plane needs
122 @@ -786,9 +786,11 @@ static int vc4_plane_mode_set(struct drm
123 DRM_MODE_REFLECT_Y);
124
125 /* We must point to the last line when Y reflection is enabled. */
126 - src_y = vc4_state->src_y;
127 + src_y = vc4_state->src_y >> 16;
128 if (rotation & DRM_MODE_REFLECT_Y)
129 - src_y += vc4_state->src_h[0] - 1;
130 + src_y += height - 1;
131 +
132 + src_x = vc4_state->src_x >> 16;
133
134 switch (base_format_mod) {
135 case DRM_FORMAT_MOD_LINEAR:
136 @@ -803,7 +805,7 @@ static int vc4_plane_mode_set(struct drm
137 (i ? v_subsample : 1) *
138 fb->pitches[i];
139
140 - vc4_state->offsets[i] += vc4_state->src_x /
141 + vc4_state->offsets[i] += src_x /
142 (i ? h_subsample : 1) *
143 fb->format->cpp[i];
144 }
145 @@ -826,7 +828,7 @@ static int vc4_plane_mode_set(struct drm
146 * pitch * tile_h == tile_size * tiles_per_row
147 */
148 u32 tiles_w = fb->pitches[0] >> (tile_size_shift - tile_h_shift);
149 - u32 tiles_l = vc4_state->src_x >> tile_w_shift;
150 + u32 tiles_l = src_x >> tile_w_shift;
151 u32 tiles_r = tiles_w - tiles_l;
152 u32 tiles_t = src_y >> tile_h_shift;
153 /* Intra-tile offsets, which modify the base address (the
154 @@ -836,7 +838,7 @@ static int vc4_plane_mode_set(struct drm
155 u32 tile_y = (src_y >> 4) & 1;
156 u32 subtile_y = (src_y >> 2) & 3;
157 u32 utile_y = src_y & 3;
158 - u32 x_off = vc4_state->src_x & tile_w_mask;
159 + u32 x_off = src_x & tile_w_mask;
160 u32 y_off = src_y & tile_h_mask;
161
162 /* When Y reflection is requested we must set the
163 @@ -932,7 +934,7 @@ static int vc4_plane_mode_set(struct drm
164 * of the 12-pixels in that 128-bit word is the
165 * first pixel to be used
166 */
167 - u32 remaining_pixels = vc4_state->src_x % 96;
168 + u32 remaining_pixels = src_x % 96;
169 u32 aligned = remaining_pixels / 12;
170 u32 last_bits = remaining_pixels % 12;
171
172 @@ -954,12 +956,12 @@ static int vc4_plane_mode_set(struct drm
173 return -EINVAL;
174 }
175 pix_per_tile = tile_w / fb->format->cpp[0];
176 - x_off = (vc4_state->src_x % pix_per_tile) /
177 + x_off = (src_x % pix_per_tile) /
178 (i ? h_subsample : 1) *
179 fb->format->cpp[i];
180 }
181
182 - tile = vc4_state->src_x / pix_per_tile;
183 + tile = src_x / pix_per_tile;
184
185 vc4_state->offsets[i] += param * tile_w * tile;
186 vc4_state->offsets[i] += src_y /
187 @@ -1020,10 +1022,8 @@ static int vc4_plane_mode_set(struct drm
188 vc4_dlist_write(vc4_state,
189 (mix_plane_alpha ? SCALER_POS2_ALPHA_MIX : 0) |
190 vc4_hvs4_get_alpha_blend_mode(state) |
191 - VC4_SET_FIELD(vc4_state->src_w[0],
192 - SCALER_POS2_WIDTH) |
193 - VC4_SET_FIELD(vc4_state->src_h[0],
194 - SCALER_POS2_HEIGHT));
195 + VC4_SET_FIELD(width, SCALER_POS2_WIDTH) |
196 + VC4_SET_FIELD(height, SCALER_POS2_HEIGHT));
197
198 /* Position Word 3: Context. Written by the HVS. */
199 vc4_dlist_write(vc4_state, 0xc0c0c0c0);
200 @@ -1081,10 +1081,8 @@ static int vc4_plane_mode_set(struct drm
201 /* Position Word 2: Source Image Size */
202 vc4_state->pos2_offset = vc4_state->dlist_count;
203 vc4_dlist_write(vc4_state,
204 - VC4_SET_FIELD(vc4_state->src_w[0],
205 - SCALER5_POS2_WIDTH) |
206 - VC4_SET_FIELD(vc4_state->src_h[0],
207 - SCALER5_POS2_HEIGHT));
208 + VC4_SET_FIELD(width, SCALER5_POS2_WIDTH) |
209 + VC4_SET_FIELD(height, SCALER5_POS2_HEIGHT));
210
211 /* Position Word 3: Context. Written by the HVS. */
212 vc4_dlist_write(vc4_state, 0xc0c0c0c0);