Skip to content

Commit 42c7448

Browse files
committed
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 <[email protected]>
1 parent 1715772 commit 42c7448

File tree

1 file changed

+73
-58
lines changed

1 file changed

+73
-58
lines changed

drivers/gpu/drm/vc4/vc4_plane.c

Lines changed: 73 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,21 @@ 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+
/* Compute column stride from buffer size and
1482+
* padded width
1483+
*/
1484+
pitch[i] = drm_format_info_plane_height(fb->format,
1485+
fb->height,
1486+
i);
1487+
break;
1488+
default:
1489+
pitch[i] = VC4_SET_FIELD(param, SCALER_TILE_HEIGHT);
1490+
break;
1491+
}
14731492

14741493
if (fb->format->format == DRM_FORMAT_P030) {
14751494
/*
@@ -1485,36 +1504,20 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
14851504
u32 last_bits = remaining_pixels % 12;
14861505

14871506
x_off = aligned * 16 + last_bits;
1488-
tile_w = 128;
14891507
pix_per_tile = 96;
14901508
} 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];
1509+
pix_per_tile = tile_width / fb->format->cpp[0];
15051510
x_off = (src_x % pix_per_tile) /
15061511
(i ? h_subsample : 1) *
15071512
fb->format->cpp[i];
15081513
}
15091514

15101515
tile = src_x / pix_per_tile;
15111516

1512-
offsets[i] += param * tile_w * tile;
1513-
offsets[i] += src_y / (i ? v_subsample : 1) * tile_w;
1517+
offsets[i] += pitch[i] * tile;
1518+
offsets[i] += src_y / (i ? v_subsample : 1) * tile_width;
15141519
offsets[i] += x_off & ~(i ? 1 : 0);
15151520
}
1516-
1517-
pitch0 = VC4_SET_FIELD(param, SCALER_TILE_HEIGHT);
15181521
break;
15191522
}
15201523

@@ -1669,7 +1672,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
16691672
vc4_dlist_write(vc4_state, 0xc0c0c0c0);
16701673

16711674
/* Pitch word 0 */
1672-
vc4_dlist_write(vc4_state, pitch0);
1675+
vc4_dlist_write(vc4_state, pitch[0]);
16731676

16741677
/* Pitch word 1/2 */
16751678
for (i = 1; i < num_planes; i++) {
@@ -1679,7 +1682,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
16791682
VC4_SET_FIELD(fb->pitches[i],
16801683
SCALER_SRC_PITCH));
16811684
} else {
1682-
vc4_dlist_write(vc4_state, pitch0);
1685+
vc4_dlist_write(vc4_state, pitch[1]);
16831686
}
16841687
}
16851688

@@ -1834,7 +1837,7 @@ static int vc6_plane_mode_set(struct drm_plane *plane,
18341837
u32 v_subsample = fb->format->vsub;
18351838
bool mix_plane_alpha;
18361839
bool covers_screen;
1837-
u32 scl0, scl1, pitch0;
1840+
u32 scl0, scl1, pitch[2];
18381841
u32 tiling, src_x, src_y;
18391842
u32 width, height;
18401843
u32 hvs_format = format->hvs;
@@ -1904,6 +1907,7 @@ static int vc6_plane_mode_set(struct drm_plane *plane,
19041907
case DRM_FORMAT_MOD_BROADCOM_SAND128:
19051908
case DRM_FORMAT_MOD_BROADCOM_SAND256: {
19061909
uint32_t param = fourcc_mod_broadcom_param(fb->modifier);
1910+
unsigned int tile_width = 0;
19071911
u32 components_per_word;
19081912
u32 starting_offset;
19091913
u32 fetch_count;
@@ -1917,21 +1921,29 @@ static int vc6_plane_mode_set(struct drm_plane *plane,
19171921
if (fb->format->format == DRM_FORMAT_P030) {
19181922
hvs_format = HVS_PIXEL_FORMAT_YCBCR_10BIT;
19191923
tiling = SCALER6_CTL0_ADDR_MODE_128B;
1924+
tile_width = 128;
19201925
} else {
19211926
hvs_format = HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE;
19221927

19231928
switch (base_format_mod) {
19241929
case DRM_FORMAT_MOD_BROADCOM_SAND128:
19251930
tiling = SCALER6_CTL0_ADDR_MODE_128B;
1931+
tile_width = 128;
19261932
break;
19271933
case DRM_FORMAT_MOD_BROADCOM_SAND256:
19281934
tiling = SCALER6_CTL0_ADDR_MODE_256B;
1935+
tile_width = 256;
19291936
break;
19301937
default:
19311938
return -EINVAL;
19321939
}
19331940
}
19341941

1942+
components_per_word = fb->format->format == DRM_FORMAT_P030 ? 24 : 32;
1943+
starting_offset = src_x % components_per_word;
1944+
fetch_count = (width + starting_offset + components_per_word - 1) /
1945+
components_per_word;
1946+
19351947
/* Adjust the base pointer to the first pixel to be scanned
19361948
* out.
19371949
*
@@ -1943,7 +1955,21 @@ static int vc6_plane_mode_set(struct drm_plane *plane,
19431955
* should be 6.
19441956
*/
19451957
for (i = 0; i < num_planes; i++) {
1946-
u32 tile_w, tile, x_off, pix_per_tile;
1958+
u32 tile, x_off, pix_per_tile;
1959+
1960+
switch (param) {
1961+
case 0:
1962+
/* Compute column stride from buffer size and
1963+
* padded width
1964+
*/
1965+
pitch[i] = drm_format_info_plane_height(fb->format,
1966+
fb->height,
1967+
i);
1968+
break;
1969+
default:
1970+
pitch[i] = VC4_SET_FIELD(param, SCALER_TILE_HEIGHT);
1971+
break;
1972+
}
19471973

19481974
if (fb->format->format == DRM_FORMAT_P030) {
19491975
/*
@@ -1959,39 +1985,28 @@ static int vc6_plane_mode_set(struct drm_plane *plane,
19591985
u32 last_bits = remaining_pixels % 12;
19601986

19611987
x_off = aligned * 16 + last_bits;
1962-
tile_w = 128;
19631988
pix_per_tile = 96;
19641989
} 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];
1990+
pix_per_tile = tile_width / fb->format->cpp[0];
19761991
x_off = (src_x % pix_per_tile) /
19771992
(i ? h_subsample : 1) *
19781993
fb->format->cpp[i];
19791994
}
19801995

19811996
tile = src_x / pix_per_tile;
19821997

1983-
offsets[i] += param * tile_w * tile;
1984-
offsets[i] += src_y / (i ? v_subsample : 1) * tile_w;
1998+
offsets[i] += pitch[i] * tile;
1999+
offsets[i] += src_y / (i ? v_subsample : 1) * tile_width;
19852000
offsets[i] += x_off & ~(i ? 1 : 0);
1986-
}
19872001

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;
2002+
/*
2003+
* Finished using the pitch as a pitch, so pack it as the
2004+
* register value.
2005+
*/
2006+
pitch[i] = VC4_SET_FIELD(pitch[i], SCALER6_PTR2_PITCH) |
2007+
VC4_SET_FIELD(fetch_count - 1, SCALER6_PTR2_FETCH_COUNT);
2008+
}
19922009

1993-
pitch0 = VC4_SET_FIELD(param, SCALER6_PTR2_PITCH) |
1994-
VC4_SET_FIELD(fetch_count - 1, SCALER6_PTR2_FETCH_COUNT);
19952010
break;
19962011
}
19972012

@@ -2104,7 +2119,7 @@ static int vc6_plane_mode_set(struct drm_plane *plane,
21042119
VC4_SET_FIELD(fb->pitches[i],
21052120
SCALER6_PTR2_PITCH));
21062121
} else {
2107-
vc4_dlist_write(vc4_state, pitch0);
2122+
vc4_dlist_write(vc4_state, pitch[i]);
21082123
}
21092124
}
21102125

@@ -2613,9 +2628,9 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
26132628
unsigned i;
26142629
static const uint64_t modifiers[] = {
26152630
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,
2631+
DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(0),
2632+
DRM_FORMAT_MOD_BROADCOM_SAND64_COL_HEIGHT(0),
2633+
DRM_FORMAT_MOD_BROADCOM_SAND256_COL_HEIGHT(0),
26192634
DRM_FORMAT_MOD_LINEAR,
26202635
DRM_FORMAT_MOD_INVALID
26212636
};

0 commit comments

Comments
 (0)