Skip to content

Commit c03bc9e

Browse files
committed
drm/vc4: Skip input lines when doing a large downscale
The TPZ filter wants ideally 3 lines of image to give good quality downscaling. More than that leads to excessive SDRAM bandwidth for no gain. If the downsample factor allows for it, reduce the programmed image height and increase the pitch to compensate. This currently does not handle T-format images where we need to configure it slightly differently. Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
1 parent 01f7332 commit c03bc9e

3 files changed

Lines changed: 59 additions & 13 deletions

File tree

drivers/gpu/drm/vc4/vc4_drv.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,11 @@ struct vc4_plane_state {
459459
*/
460460
bool is_yuv444_unity;
461461

462+
/* Skip lines on large downscales to avoid consuming too much SDRAM
463+
* bandwidth
464+
*/
465+
unsigned int vdownsample;
466+
462467
/* Our allocation in LBM for temporary storage during scaling. */
463468
unsigned int lbm_handle;
464469

drivers/gpu/drm/vc4/vc4_plane.c

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -962,7 +962,7 @@ static void vc4_write_scaling_parameters(struct drm_plane_state *state,
962962

963963
/* Ch0 V-TPZ Words 0-2: Scaling Parameters, Recip, Context */
964964
if (vc4_state->y_scaling[channel] == VC4_SCALING_TPZ) {
965-
vc4_write_tpz(vc4_state, vc4_state->src_h[channel],
965+
vc4_write_tpz(vc4_state, vc4_state->src_h[channel] / vc4_state->vdownsample,
966966
vc4_state->crtc_h);
967967
vc4_dlist_write(vc4_state, 0xc0c0c0c0);
968968
}
@@ -1388,6 +1388,17 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
13881388
return 0;
13891389
}
13901390

1391+
if (vc4_state->y_scaling[0] == VC4_SCALING_TPZ &&
1392+
vc4_state->src_h[0] / vc4_state->crtc_h > (3 << 16)) {
1393+
/* Downscaling by more than x3. Reduce the number of lines read
1394+
* to avoid exceeding SDRAM bandwidth.
1395+
*/
1396+
vc4_state->vdownsample = ((vc4_state->src_h[0] /
1397+
(vc4_state->crtc_h * 3)) >> 16) + 1;
1398+
} else {
1399+
vc4_state->vdownsample = 1;
1400+
}
1401+
13911402
width = vc4_state->src_w[0] >> 16;
13921403
height = vc4_state->src_h[0] >> 16;
13931404

@@ -1433,6 +1444,9 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
14331444
break;
14341445

14351446
case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: {
1447+
/* Line skipping decimation currently not supported for T-format */
1448+
vc4_state->vdownsample = 1;
1449+
14361450
u32 tile_size_shift = 12; /* T tiles are 4kb */
14371451
/* Whole-tile offsets, mostly for setting the pitch. */
14381452
u32 tile_w_shift = fb->format->cpp[0] == 2 ? 6 : 5;
@@ -1585,6 +1599,9 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
15851599
offsets[i] += pitch[i] * tile * tile_width;
15861600
offsets[i] += src_y / (i ? v_subsample : 1) * tile_width;
15871601
offsets[i] += x_off & ~(i ? 1 : 0);
1602+
1603+
pitch[i] |= VC4_SET_FIELD(vc4_state->vdownsample - 1,
1604+
SCALER_TILE_SKIP_0);
15881605
}
15891606
break;
15901607
}
@@ -1662,7 +1679,8 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
16621679
(mix_plane_alpha ? SCALER_POS2_ALPHA_MIX : 0) |
16631680
vc4_hvs4_get_alpha_blend_mode(state) |
16641681
VC4_SET_FIELD(width, SCALER_POS2_WIDTH) |
1665-
VC4_SET_FIELD(height, SCALER_POS2_HEIGHT));
1682+
VC4_SET_FIELD(height / vc4_state->vdownsample,
1683+
SCALER_POS2_HEIGHT));
16661684

16671685
/* Position Word 3: Context. Written by the HVS. */
16681686
vc4_dlist_write(vc4_state, 0xc0c0c0c0);
@@ -1716,7 +1734,8 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
17161734
vc4_state->pos2_offset = vc4_state->dlist_count;
17171735
vc4_dlist_write(vc4_state,
17181736
VC4_SET_FIELD(width, SCALER5_POS2_WIDTH) |
1719-
VC4_SET_FIELD(height, SCALER5_POS2_HEIGHT));
1737+
VC4_SET_FIELD(height / vc4_state->vdownsample,
1738+
SCALER5_POS2_HEIGHT));
17201739

17211740
/* Position Word 3: Context. Written by the HVS. */
17221741
vc4_dlist_write(vc4_state, 0xc0c0c0c0);
@@ -1740,18 +1759,22 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
17401759
vc4_dlist_write(vc4_state, 0xc0c0c0c0);
17411760

17421761
/* Pitch word 0 */
1743-
vc4_dlist_write(vc4_state, pitch[0]);
1762+
if (hvs_format != HVS_PIXEL_FORMAT_H264 &&
1763+
hvs_format != HVS_PIXEL_FORMAT_YCBCR_10BIT)
1764+
vc4_dlist_write(vc4_state, pitch[0] * vc4_state->vdownsample);
1765+
else
1766+
vc4_dlist_write(vc4_state, pitch[0]);
17441767

17451768
/* Pitch word 1/2 */
17461769
for (i = 1; i < num_planes; i++) {
17471770
if (hvs_format != HVS_PIXEL_FORMAT_H264 &&
1748-
hvs_format != HVS_PIXEL_FORMAT_YCBCR_10BIT) {
1771+
hvs_format != HVS_PIXEL_FORMAT_YCBCR_10BIT)
17491772
vc4_dlist_write(vc4_state,
1750-
VC4_SET_FIELD(fb->pitches[i],
1773+
VC4_SET_FIELD(fb->pitches[i] /
1774+
vc4_state->vdownsample,
17511775
SCALER_SRC_PITCH));
1752-
} else {
1753-
vc4_dlist_write(vc4_state, pitch[1]);
1754-
}
1776+
else
1777+
vc4_dlist_write(vc4_state, pitch[i]);
17551778
}
17561779

17571780
/* Colorspace conversion words */
@@ -1965,6 +1988,17 @@ static int vc6_plane_mode_set(struct drm_plane *plane,
19651988
width = vc4_state->src_w[0] >> 16;
19661989
height = vc4_state->src_h[0] >> 16;
19671990

1991+
if (vc4_state->y_scaling[0] == VC4_SCALING_TPZ &&
1992+
vc4_state->src_h[0] / vc4_state->crtc_h > (3 << 16)) {
1993+
/* Downscaling by more than x3. Reduce the number of lines read
1994+
* to avoid exceeding SDRAM bandwidth.
1995+
*/
1996+
vc4_state->vdownsample = ((vc4_state->src_h[0] /
1997+
(vc4_state->crtc_h * 3)) >> 16) + 1;
1998+
} else {
1999+
vc4_state->vdownsample = 1;
2000+
}
2001+
19682002
/* SCL1 is used for Cb/Cr scaling of planar formats. For RGB
19692003
* and 4:4:4, scl1 should be set to scl0 so both channels of
19702004
* the scaler do the same thing. For YUV, the Y plane needs
@@ -2117,8 +2151,11 @@ static int vc6_plane_mode_set(struct drm_plane *plane,
21172151
* Finished using the pitch as a pitch, so pack it as the
21182152
* register value.
21192153
*/
2120-
pitch[i] = VC4_SET_FIELD(pitch[i], SCALER6_PTR2_PITCH) |
2121-
VC4_SET_FIELD(fetch_count - 1, SCALER6_PTR2_FETCH_COUNT);
2154+
pitch[i] = VC4_SET_FIELD(pitch[i], SCALER6_PTR2_TILE_HEIGHT) |
2155+
VC4_SET_FIELD(fetch_count - 1,
2156+
SCALER6_PTR2_TILE_FETCH_COUNT) |
2157+
VC4_SET_FIELD(vc4_state->vdownsample - 1,
2158+
SCALER6_PTR2_TILE_LSKIP);
21222159
}
21232160

21242161
break;
@@ -2179,7 +2216,7 @@ static int vc6_plane_mode_set(struct drm_plane *plane,
21792216
/* Position Word 2: Source Image Size */
21802217
vc4_state->pos2_offset = vc4_state->dlist_count;
21812218
vc4_dlist_write(vc4_state,
2182-
VC4_SET_FIELD(height - 1,
2219+
VC4_SET_FIELD((height / vc4_state->vdownsample) - 1,
21832220
SCALER6_POS2_SRC_LINES) |
21842221
VC4_SET_FIELD(width - 1,
21852222
SCALER6_POS2_SRC_WIDTH));
@@ -2214,7 +2251,7 @@ static int vc6_plane_mode_set(struct drm_plane *plane,
22142251
if (base_format_mod != DRM_FORMAT_MOD_BROADCOM_SAND128 &&
22152252
base_format_mod != DRM_FORMAT_MOD_BROADCOM_SAND256) {
22162253
vc4_dlist_write(vc4_state,
2217-
VC4_SET_FIELD(fb->pitches[i],
2254+
VC4_SET_FIELD((fb->pitches[i] * vc4_state->vdownsample),
22182255
SCALER6_PTR2_PITCH));
22192256
} else {
22202257
vc4_dlist_write(vc4_state, pitch[i]);

drivers/gpu/drm/vc4/vc4_regs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,4 +1437,8 @@ enum hvs_pixel_format {
14371437
#define SCALER6_PTR2_PITCH_MASK VC4_MASK(16, 0)
14381438
#define SCALER6_PTR2_FETCH_COUNT_MASK VC4_MASK(26, 16)
14391439

1440+
#define SCALER6_PTR2_TILE_LSKIP_MASK VC4_MASK(31, 29)
1441+
#define SCALER6_PTR2_TILE_FETCH_COUNT_MASK VC4_MASK(26, 16)
1442+
#define SCALER6_PTR2_TILE_HEIGHT_MASK VC4_MASK(16, 0)
1443+
14401444
#endif /* VC4_REGS_H */

0 commit comments

Comments
 (0)