lede/target/linux/bcm27xx/patches-6.12/950-0843-drm-vc4-Add-algorithmic-handling-for-SAND.patch
=?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= d81c03f05e bcm27xx: add 6.12 patches from RPi repo
These patches were generated from:
https://github.com/raspberrypi/linux/commits/rpi-6.12.y
With the following command:
git format-patch -N v6.12.27..HEAD
(HEAD -> 8d3206ee456a5ecdf9ddbfd8e5e231e4f0cd716e)

Exceptions:
- (def)configs patches
- github workflows patches
- applied & reverted patches
- readme patches
- wireless patches

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
2025-06-20 17:01:06 +08:00

323 lines
10 KiB
Diff

From 954433902f69eb2d7560dcaff9d1fc987923b661 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Wed, 13 Nov 2024 12:50:56 +0000
Subject: [PATCH] drm/vc4: Add algorithmic handling for SAND
The SAND handling had been using what was believed to be a runtime
parameter in the modifier, however that has been clarified that
all permitted variants of the modifier must be advertised, so
making it variable wasn't practical.
With a rationalisation of how the producers of this format are
configured, we can switch to a variant that doesn't have as much
variation, and can be configured such that only 2 options are
required.
Add a modifier with value 0 to denote that the height of the luma
column matches the buffer height, and chroma column will be half
that due to YUV420.
A modifier of 1 denotes that the height of the luma column still
matches the buffer height, but the chroma column height is the same.
This can be used to replicate the previous behaviour.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_plane.c | 121 +++++++++++++++++---------------
1 file changed, 63 insertions(+), 58 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -1293,7 +1293,7 @@ static int vc4_plane_mode_set(struct drm
u32 v_subsample = fb->format->vsub;
bool mix_plane_alpha;
bool covers_screen;
- u32 scl0, scl1, pitch0;
+ u32 scl0, scl1, pitch[2];
u32 tiling, src_x, src_y;
u32 width, height;
u32 hvs_format = format->hvs;
@@ -1347,7 +1347,7 @@ static int vc4_plane_mode_set(struct drm
switch (base_format_mod) {
case DRM_FORMAT_MOD_LINEAR:
tiling = SCALER_CTL0_TILING_LINEAR;
- pitch0 = VC4_SET_FIELD(fb->pitches[0], SCALER_SRC_PITCH);
+ pitch[0] = VC4_SET_FIELD(fb->pitches[0], SCALER_SRC_PITCH);
/* Adjust the base pointer to the first pixel to be scanned
* out.
@@ -1399,23 +1399,23 @@ static int vc4_plane_mode_set(struct drm
*/
if (rotation & DRM_MODE_REFLECT_Y) {
y_off = tile_h_mask - y_off;
- pitch0 = SCALER_PITCH0_TILE_LINE_DIR;
+ pitch[0] = SCALER_PITCH0_TILE_LINE_DIR;
} else {
- pitch0 = 0;
+ pitch[0] = 0;
}
tiling = SCALER_CTL0_TILING_256B_OR_T;
- pitch0 |= (VC4_SET_FIELD(x_off, SCALER_PITCH0_SINK_PIX) |
- VC4_SET_FIELD(y_off, SCALER_PITCH0_TILE_Y_OFFSET) |
- VC4_SET_FIELD(tiles_l, SCALER_PITCH0_TILE_WIDTH_L) |
- VC4_SET_FIELD(tiles_r, SCALER_PITCH0_TILE_WIDTH_R));
+ pitch[0] |= (VC4_SET_FIELD(x_off, SCALER_PITCH0_SINK_PIX) |
+ VC4_SET_FIELD(y_off, SCALER_PITCH0_TILE_Y_OFFSET) |
+ VC4_SET_FIELD(tiles_l, SCALER_PITCH0_TILE_WIDTH_L) |
+ VC4_SET_FIELD(tiles_r, SCALER_PITCH0_TILE_WIDTH_R));
offsets[0] += tiles_t * (tiles_w << tile_size_shift);
offsets[0] += subtile_y << 8;
offsets[0] += utile_y << 4;
/* Rows of tiles alternate left-to-right and right-to-left. */
if (tiles_t & 1) {
- pitch0 |= SCALER_PITCH0_TILE_INITIAL_LINE_DIR;
+ pitch[0] |= SCALER_PITCH0_TILE_INITIAL_LINE_DIR;
offsets[0] += (tiles_w - tiles_l) << tile_size_shift;
offsets[0] -= (1 + !tile_y) << 10;
} else {
@@ -1430,6 +1430,7 @@ static int vc4_plane_mode_set(struct drm
case DRM_FORMAT_MOD_BROADCOM_SAND128:
case DRM_FORMAT_MOD_BROADCOM_SAND256: {
uint32_t param = fourcc_mod_broadcom_param(fb->modifier);
+ unsigned int tile_width = 0;
if (param > SCALER_TILE_HEIGHT_MASK) {
DRM_DEBUG_KMS("SAND height too large (%d)\n",
@@ -1440,18 +1441,22 @@ static int vc4_plane_mode_set(struct drm
if (fb->format->format == DRM_FORMAT_P030) {
hvs_format = HVS_PIXEL_FORMAT_YCBCR_10BIT;
tiling = SCALER_CTL0_TILING_128B;
+ tile_width = 128;
} else {
hvs_format = HVS_PIXEL_FORMAT_H264;
switch (base_format_mod) {
case DRM_FORMAT_MOD_BROADCOM_SAND64:
tiling = SCALER_CTL0_TILING_64B;
+ tile_width = 64;
break;
case DRM_FORMAT_MOD_BROADCOM_SAND128:
tiling = SCALER_CTL0_TILING_128B;
+ tile_width = 128;
break;
case DRM_FORMAT_MOD_BROADCOM_SAND256:
tiling = SCALER_CTL0_TILING_256B_OR_T;
+ tile_width = 256;
break;
default:
return -EINVAL;
@@ -1469,7 +1474,16 @@ static int vc4_plane_mode_set(struct drm
* should be 6.
*/
for (i = 0; i < num_planes; i++) {
- u32 tile_w, tile, x_off, pix_per_tile;
+ u32 tile, x_off, pix_per_tile;
+
+ switch (param) {
+ case 0:
+ pitch[i] = fb->pitches[i];
+ break;
+ default:
+ pitch[i] = VC4_SET_FIELD(param, SCALER_TILE_HEIGHT);
+ break;
+ }
if (fb->format->format == DRM_FORMAT_P030) {
/*
@@ -1485,23 +1499,9 @@ static int vc4_plane_mode_set(struct drm
u32 last_bits = remaining_pixels % 12;
x_off = aligned * 16 + last_bits;
- tile_w = 128;
pix_per_tile = 96;
} else {
- switch (base_format_mod) {
- case DRM_FORMAT_MOD_BROADCOM_SAND64:
- tile_w = 64;
- break;
- case DRM_FORMAT_MOD_BROADCOM_SAND128:
- tile_w = 128;
- break;
- case DRM_FORMAT_MOD_BROADCOM_SAND256:
- tile_w = 256;
- break;
- default:
- return -EINVAL;
- }
- pix_per_tile = tile_w / fb->format->cpp[0];
+ pix_per_tile = tile_width / fb->format->cpp[0];
x_off = (src_x % pix_per_tile) /
(i ? h_subsample : 1) *
fb->format->cpp[i];
@@ -1509,12 +1509,10 @@ static int vc4_plane_mode_set(struct drm
tile = src_x / pix_per_tile;
- offsets[i] += param * tile_w * tile;
- offsets[i] += src_y / (i ? v_subsample : 1) * tile_w;
+ offsets[i] += pitch[i] * tile;
+ offsets[i] += src_y / (i ? v_subsample : 1) * tile_width;
offsets[i] += x_off & ~(i ? 1 : 0);
}
-
- pitch0 = VC4_SET_FIELD(param, SCALER_TILE_HEIGHT);
break;
}
@@ -1669,7 +1667,7 @@ static int vc4_plane_mode_set(struct drm
vc4_dlist_write(vc4_state, 0xc0c0c0c0);
/* Pitch word 0 */
- vc4_dlist_write(vc4_state, pitch0);
+ vc4_dlist_write(vc4_state, pitch[0]);
/* Pitch word 1/2 */
for (i = 1; i < num_planes; i++) {
@@ -1679,7 +1677,7 @@ static int vc4_plane_mode_set(struct drm
VC4_SET_FIELD(fb->pitches[i],
SCALER_SRC_PITCH));
} else {
- vc4_dlist_write(vc4_state, pitch0);
+ vc4_dlist_write(vc4_state, pitch[1]);
}
}
@@ -1834,7 +1832,7 @@ static int vc6_plane_mode_set(struct drm
u32 v_subsample = fb->format->vsub;
bool mix_plane_alpha;
bool covers_screen;
- u32 scl0, scl1, pitch0;
+ u32 scl0, scl1, pitch[2];
u32 tiling, src_x, src_y;
u32 width, height;
u32 hvs_format = format->hvs;
@@ -1904,6 +1902,7 @@ static int vc6_plane_mode_set(struct drm
case DRM_FORMAT_MOD_BROADCOM_SAND128:
case DRM_FORMAT_MOD_BROADCOM_SAND256: {
uint32_t param = fourcc_mod_broadcom_param(fb->modifier);
+ unsigned int tile_width = 0;
u32 components_per_word;
u32 starting_offset;
u32 fetch_count;
@@ -1917,21 +1916,29 @@ static int vc6_plane_mode_set(struct drm
if (fb->format->format == DRM_FORMAT_P030) {
hvs_format = HVS_PIXEL_FORMAT_YCBCR_10BIT;
tiling = SCALER6_CTL0_ADDR_MODE_128B;
+ tile_width = 128;
} else {
hvs_format = HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE;
switch (base_format_mod) {
case DRM_FORMAT_MOD_BROADCOM_SAND128:
tiling = SCALER6_CTL0_ADDR_MODE_128B;
+ tile_width = 128;
break;
case DRM_FORMAT_MOD_BROADCOM_SAND256:
tiling = SCALER6_CTL0_ADDR_MODE_256B;
+ tile_width = 256;
break;
default:
return -EINVAL;
}
}
+ components_per_word = fb->format->format == DRM_FORMAT_P030 ? 24 : 32;
+ starting_offset = src_x % components_per_word;
+ fetch_count = (width + starting_offset + components_per_word - 1) /
+ components_per_word;
+
/* Adjust the base pointer to the first pixel to be scanned
* out.
*
@@ -1943,7 +1950,16 @@ static int vc6_plane_mode_set(struct drm
* should be 6.
*/
for (i = 0; i < num_planes; i++) {
- u32 tile_w, tile, x_off, pix_per_tile;
+ u32 tile, x_off, pix_per_tile;
+
+ switch (param) {
+ case 0:
+ pitch[i] = fb->pitches[i];
+ break;
+ default:
+ pitch[i] = VC4_SET_FIELD(param, SCALER_TILE_HEIGHT);
+ break;
+ }
if (fb->format->format == DRM_FORMAT_P030) {
/*
@@ -1959,20 +1975,9 @@ static int vc6_plane_mode_set(struct drm
u32 last_bits = remaining_pixels % 12;
x_off = aligned * 16 + last_bits;
- tile_w = 128;
pix_per_tile = 96;
} else {
- switch (base_format_mod) {
- case DRM_FORMAT_MOD_BROADCOM_SAND128:
- tile_w = 128;
- break;
- case DRM_FORMAT_MOD_BROADCOM_SAND256:
- tile_w = 256;
- break;
- default:
- return -EINVAL;
- }
- pix_per_tile = tile_w / fb->format->cpp[0];
+ pix_per_tile = tile_width / fb->format->cpp[0];
x_off = (src_x % pix_per_tile) /
(i ? h_subsample : 1) *
fb->format->cpp[i];
@@ -1980,18 +1985,18 @@ static int vc6_plane_mode_set(struct drm
tile = src_x / pix_per_tile;
- offsets[i] += param * tile_w * tile;
- offsets[i] += src_y / (i ? v_subsample : 1) * tile_w;
+ offsets[i] += pitch[i] * tile;
+ offsets[i] += src_y / (i ? v_subsample : 1) * tile_width;
offsets[i] += x_off & ~(i ? 1 : 0);
- }
- components_per_word = fb->format->format == DRM_FORMAT_P030 ? 24 : 32;
- starting_offset = src_x % components_per_word;
- fetch_count = (width + starting_offset + components_per_word - 1) /
- components_per_word;
+ /*
+ * Finished using the pitch as a pitch, so pack it as the
+ * register value.
+ */
+ pitch[i] = VC4_SET_FIELD(pitch[i], SCALER6_PTR2_PITCH) |
+ VC4_SET_FIELD(fetch_count - 1, SCALER6_PTR2_FETCH_COUNT);
+ }
- pitch0 = VC4_SET_FIELD(param, SCALER6_PTR2_PITCH) |
- VC4_SET_FIELD(fetch_count - 1, SCALER6_PTR2_FETCH_COUNT);
break;
}
@@ -2104,7 +2109,7 @@ static int vc6_plane_mode_set(struct drm
VC4_SET_FIELD(fb->pitches[i],
SCALER6_PTR2_PITCH));
} else {
- vc4_dlist_write(vc4_state, pitch0);
+ vc4_dlist_write(vc4_state, pitch[i]);
}
}
@@ -2613,9 +2618,9 @@ struct drm_plane *vc4_plane_init(struct
unsigned i;
static const uint64_t modifiers[] = {
DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED,
- DRM_FORMAT_MOD_BROADCOM_SAND128,
- DRM_FORMAT_MOD_BROADCOM_SAND64,
- DRM_FORMAT_MOD_BROADCOM_SAND256,
+ DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(0),
+ DRM_FORMAT_MOD_BROADCOM_SAND64_COL_HEIGHT(0),
+ DRM_FORMAT_MOD_BROADCOM_SAND256_COL_HEIGHT(0),
DRM_FORMAT_MOD_LINEAR,
DRM_FORMAT_MOD_INVALID
};