mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-07-22 01:07:44 +08:00

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>
323 lines
10 KiB
Diff
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
|
|
};
|