Skip to content

Commit ee7a86b

Browse files
6by9popcornmix
authored andcommitted
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>
1 parent 4a9f8e8 commit ee7a86b

File tree

1 file changed

+63
-58
lines changed

1 file changed

+63
-58
lines changed

drivers/gpu/drm/vc4/vc4_plane.c

Lines changed: 63 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1293,7 +1293,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
12931293
u32 v_subsample = fb->format->vsub;
12941294
bool mix_plane_alpha;
12951295
bool covers_screen;
1296-
u32 scl0, scl1, pitch0;
1296+
u32 scl0, scl1, pitch[2];
12971297
u32 tiling, src_x, src_y;
12981298
u32 width, height;
12991299
u32 hvs_format = format->hvs;
@@ -1347,7 +1347,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
13471347
switch (base_format_mod) {
13481348
case DRM_FORMAT_MOD_LINEAR:
13491349
tiling = SCALER_CTL0_TILING_LINEAR;
1350-
pitch0 = VC4_SET_FIELD(fb->pitches[0], SCALER_SRC_PITCH);
1350+
pitch[0] = VC4_SET_FIELD(fb->pitches[0], SCALER_SRC_PITCH);
13511351

13521352
/* Adjust the base pointer to the first pixel to be scanned
13531353
* out.
@@ -1399,23 +1399,23 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
13991399
*/
14001400
if (rotation & DRM_MODE_REFLECT_Y) {
14011401
y_off = tile_h_mask - y_off;
1402-
pitch0 = SCALER_PITCH0_TILE_LINE_DIR;
1402+
pitch[0] = SCALER_PITCH0_TILE_LINE_DIR;
14031403
} else {
1404-
pitch0 = 0;
1404+
pitch[0] = 0;
14051405
}
14061406

14071407
tiling = SCALER_CTL0_TILING_256B_OR_T;
1408-
pitch0 |= (VC4_SET_FIELD(x_off, SCALER_PITCH0_SINK_PIX) |
1409-
VC4_SET_FIELD(y_off, SCALER_PITCH0_TILE_Y_OFFSET) |
1410-
VC4_SET_FIELD(tiles_l, SCALER_PITCH0_TILE_WIDTH_L) |
1411-
VC4_SET_FIELD(tiles_r, SCALER_PITCH0_TILE_WIDTH_R));
1408+
pitch[0] |= (VC4_SET_FIELD(x_off, SCALER_PITCH0_SINK_PIX) |
1409+
VC4_SET_FIELD(y_off, SCALER_PITCH0_TILE_Y_OFFSET) |
1410+
VC4_SET_FIELD(tiles_l, SCALER_PITCH0_TILE_WIDTH_L) |
1411+
VC4_SET_FIELD(tiles_r, SCALER_PITCH0_TILE_WIDTH_R));
14121412
offsets[0] += tiles_t * (tiles_w << tile_size_shift);
14131413
offsets[0] += subtile_y << 8;
14141414
offsets[0] += utile_y << 4;
14151415

14161416
/* Rows of tiles alternate left-to-right and right-to-left. */
14171417
if (tiles_t & 1) {
1418-
pitch0 |= SCALER_PITCH0_TILE_INITIAL_LINE_DIR;
1418+
pitch[0] |= SCALER_PITCH0_TILE_INITIAL_LINE_DIR;
14191419
offsets[0] += (tiles_w - tiles_l) << tile_size_shift;
14201420
offsets[0] -= (1 + !tile_y) << 10;
14211421
} else {
@@ -1430,6 +1430,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
14301430
case DRM_FORMAT_MOD_BROADCOM_SAND128:
14311431
case DRM_FORMAT_MOD_BROADCOM_SAND256: {
14321432
uint32_t param = fourcc_mod_broadcom_param(fb->modifier);
1433+
unsigned int tile_width = 0;
14331434

14341435
if (param > SCALER_TILE_HEIGHT_MASK) {
14351436
DRM_DEBUG_KMS("SAND height too large (%d)\n",
@@ -1440,18 +1441,22 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
14401441
if (fb->format->format == DRM_FORMAT_P030) {
14411442
hvs_format = HVS_PIXEL_FORMAT_YCBCR_10BIT;
14421443
tiling = SCALER_CTL0_TILING_128B;
1444+
tile_width = 128;
14431445
} else {
14441446
hvs_format = HVS_PIXEL_FORMAT_H264;
14451447

14461448
switch (base_format_mod) {
14471449
case DRM_FORMAT_MOD_BROADCOM_SAND64:
14481450
tiling = SCALER_CTL0_TILING_64B;
1451+
tile_width = 64;
14491452
break;
14501453
case DRM_FORMAT_MOD_BROADCOM_SAND128:
14511454
tiling = SCALER_CTL0_TILING_128B;
1455+
tile_width = 128;
14521456
break;
14531457
case DRM_FORMAT_MOD_BROADCOM_SAND256:
14541458
tiling = SCALER_CTL0_TILING_256B_OR_T;
1459+
tile_width = 256;
14551460
break;
14561461
default:
14571462
return -EINVAL;
@@ -1469,7 +1474,16 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
14691474
* should be 6.
14701475
*/
14711476
for (i = 0; i < num_planes; i++) {
1472-
u32 tile_w, tile, x_off, pix_per_tile;
1477+
u32 tile, x_off, pix_per_tile;
1478+
1479+
switch (param) {
1480+
case 0:
1481+
pitch[i] = fb->pitches[i];
1482+
break;
1483+
default:
1484+
pitch[i] = VC4_SET_FIELD(param, SCALER_TILE_HEIGHT);
1485+
break;
1486+
}
14731487

14741488
if (fb->format->format == DRM_FORMAT_P030) {
14751489
/*
@@ -1485,36 +1499,20 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
14851499
u32 last_bits = remaining_pixels % 12;
14861500

14871501
x_off = aligned * 16 + last_bits;
1488-
tile_w = 128;
14891502
pix_per_tile = 96;
14901503
} else {
1491-
switch (base_format_mod) {
1492-
case DRM_FORMAT_MOD_BROADCOM_SAND64:
1493-
tile_w = 64;
1494-
break;
1495-
case DRM_FORMAT_MOD_BROADCOM_SAND128:
1496-
tile_w = 128;
1497-
break;
1498-
case DRM_FORMAT_MOD_BROADCOM_SAND256:
1499-
tile_w = 256;
1500-
break;
1501-
default:
1502-
return -EINVAL;
1503-
}
1504-
pix_per_tile = tile_w / fb->format->cpp[0];
1504+
pix_per_tile = tile_width / fb->format->cpp[0];
15051505
x_off = (src_x % pix_per_tile) /
15061506
(i ? h_subsample : 1) *
15071507
fb->format->cpp[i];
15081508
}
15091509

15101510
tile = src_x / pix_per_tile;
15111511

1512-
offsets[i] += param * tile_w * tile;
1513-
offsets[i] += src_y / (i ? v_subsample : 1) * tile_w;
1512+
offsets[i] += pitch[i] * tile;
1513+
offsets[i] += src_y / (i ? v_subsample : 1) * tile_width;
15141514
offsets[i] += x_off & ~(i ? 1 : 0);
15151515
}
1516-
1517-
pitch0 = VC4_SET_FIELD(param, SCALER_TILE_HEIGHT);
15181516
break;
15191517
}
15201518

@@ -1669,7 +1667,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
16691667
vc4_dlist_write(vc4_state, 0xc0c0c0c0);
16701668

16711669
/* Pitch word 0 */
1672-
vc4_dlist_write(vc4_state, pitch0);
1670+
vc4_dlist_write(vc4_state, pitch[0]);
16731671

16741672
/* Pitch word 1/2 */
16751673
for (i = 1; i < num_planes; i++) {
@@ -1679,7 +1677,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
16791677
VC4_SET_FIELD(fb->pitches[i],
16801678
SCALER_SRC_PITCH));
16811679
} else {
1682-
vc4_dlist_write(vc4_state, pitch0);
1680+
vc4_dlist_write(vc4_state, pitch[1]);
16831681
}
16841682
}
16851683

@@ -1834,7 +1832,7 @@ static int vc6_plane_mode_set(struct drm_plane *plane,
18341832
u32 v_subsample = fb->format->vsub;
18351833
bool mix_plane_alpha;
18361834
bool covers_screen;
1837-
u32 scl0, scl1, pitch0;
1835+
u32 scl0, scl1, pitch[2];
18381836
u32 tiling, src_x, src_y;
18391837
u32 width, height;
18401838
u32 hvs_format = format->hvs;
@@ -1904,6 +1902,7 @@ static int vc6_plane_mode_set(struct drm_plane *plane,
19041902
case DRM_FORMAT_MOD_BROADCOM_SAND128:
19051903
case DRM_FORMAT_MOD_BROADCOM_SAND256: {
19061904
uint32_t param = fourcc_mod_broadcom_param(fb->modifier);
1905+
unsigned int tile_width = 0;
19071906
u32 components_per_word;
19081907
u32 starting_offset;
19091908
u32 fetch_count;
@@ -1917,21 +1916,29 @@ static int vc6_plane_mode_set(struct drm_plane *plane,
19171916
if (fb->format->format == DRM_FORMAT_P030) {
19181917
hvs_format = HVS_PIXEL_FORMAT_YCBCR_10BIT;
19191918
tiling = SCALER6_CTL0_ADDR_MODE_128B;
1919+
tile_width = 128;
19201920
} else {
19211921
hvs_format = HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE;
19221922

19231923
switch (base_format_mod) {
19241924
case DRM_FORMAT_MOD_BROADCOM_SAND128:
19251925
tiling = SCALER6_CTL0_ADDR_MODE_128B;
1926+
tile_width = 128;
19261927
break;
19271928
case DRM_FORMAT_MOD_BROADCOM_SAND256:
19281929
tiling = SCALER6_CTL0_ADDR_MODE_256B;
1930+
tile_width = 256;
19291931
break;
19301932
default:
19311933
return -EINVAL;
19321934
}
19331935
}
19341936

1937+
components_per_word = fb->format->format == DRM_FORMAT_P030 ? 24 : 32;
1938+
starting_offset = src_x % components_per_word;
1939+
fetch_count = (width + starting_offset + components_per_word - 1) /
1940+
components_per_word;
1941+
19351942
/* Adjust the base pointer to the first pixel to be scanned
19361943
* out.
19371944
*
@@ -1943,7 +1950,16 @@ static int vc6_plane_mode_set(struct drm_plane *plane,
19431950
* should be 6.
19441951
*/
19451952
for (i = 0; i < num_planes; i++) {
1946-
u32 tile_w, tile, x_off, pix_per_tile;
1953+
u32 tile, x_off, pix_per_tile;
1954+
1955+
switch (param) {
1956+
case 0:
1957+
pitch[i] = fb->pitches[i];
1958+
break;
1959+
default:
1960+
pitch[i] = VC4_SET_FIELD(param, SCALER_TILE_HEIGHT);
1961+
break;
1962+
}
19471963

19481964
if (fb->format->format == DRM_FORMAT_P030) {
19491965
/*
@@ -1959,39 +1975,28 @@ static int vc6_plane_mode_set(struct drm_plane *plane,
19591975
u32 last_bits = remaining_pixels % 12;
19601976

19611977
x_off = aligned * 16 + last_bits;
1962-
tile_w = 128;
19631978
pix_per_tile = 96;
19641979
} else {
1965-
switch (base_format_mod) {
1966-
case DRM_FORMAT_MOD_BROADCOM_SAND128:
1967-
tile_w = 128;
1968-
break;
1969-
case DRM_FORMAT_MOD_BROADCOM_SAND256:
1970-
tile_w = 256;
1971-
break;
1972-
default:
1973-
return -EINVAL;
1974-
}
1975-
pix_per_tile = tile_w / fb->format->cpp[0];
1980+
pix_per_tile = tile_width / fb->format->cpp[0];
19761981
x_off = (src_x % pix_per_tile) /
19771982
(i ? h_subsample : 1) *
19781983
fb->format->cpp[i];
19791984
}
19801985

19811986
tile = src_x / pix_per_tile;
19821987

1983-
offsets[i] += param * tile_w * tile;
1984-
offsets[i] += src_y / (i ? v_subsample : 1) * tile_w;
1988+
offsets[i] += pitch[i] * tile;
1989+
offsets[i] += src_y / (i ? v_subsample : 1) * tile_width;
19851990
offsets[i] += x_off & ~(i ? 1 : 0);
1986-
}
19871991

1988-
components_per_word = fb->format->format == DRM_FORMAT_P030 ? 24 : 32;
1989-
starting_offset = src_x % components_per_word;
1990-
fetch_count = (width + starting_offset + components_per_word - 1) /
1991-
components_per_word;
1992+
/*
1993+
* Finished using the pitch as a pitch, so pack it as the
1994+
* register value.
1995+
*/
1996+
pitch[i] = VC4_SET_FIELD(pitch[i], SCALER6_PTR2_PITCH) |
1997+
VC4_SET_FIELD(fetch_count - 1, SCALER6_PTR2_FETCH_COUNT);
1998+
}
19921999

1993-
pitch0 = VC4_SET_FIELD(param, SCALER6_PTR2_PITCH) |
1994-
VC4_SET_FIELD(fetch_count - 1, SCALER6_PTR2_FETCH_COUNT);
19952000
break;
19962001
}
19972002

@@ -2104,7 +2109,7 @@ static int vc6_plane_mode_set(struct drm_plane *plane,
21042109
VC4_SET_FIELD(fb->pitches[i],
21052110
SCALER6_PTR2_PITCH));
21062111
} else {
2107-
vc4_dlist_write(vc4_state, pitch0);
2112+
vc4_dlist_write(vc4_state, pitch[i]);
21082113
}
21092114
}
21102115

@@ -2613,9 +2618,9 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
26132618
unsigned i;
26142619
static const uint64_t modifiers[] = {
26152620
DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED,
2616-
DRM_FORMAT_MOD_BROADCOM_SAND128,
2617-
DRM_FORMAT_MOD_BROADCOM_SAND64,
2618-
DRM_FORMAT_MOD_BROADCOM_SAND256,
2621+
DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(0),
2622+
DRM_FORMAT_MOD_BROADCOM_SAND64_COL_HEIGHT(0),
2623+
DRM_FORMAT_MOD_BROADCOM_SAND256_COL_HEIGHT(0),
26192624
DRM_FORMAT_MOD_LINEAR,
26202625
DRM_FORMAT_MOD_INVALID
26212626
};

0 commit comments

Comments
 (0)