@@ -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 ]);
0 commit comments