[PATCH v4 2/3] drm/vc4: plane: Add support for DRM_FORMAT_P030
Maxime Ripard
maxime at cerno.tech
Thu Dec 16 08:34:24 UTC 2021
Hi Thomas,
Thanks for your review
On Wed, Dec 15, 2021 at 04:11:50PM +0100, Thomas Zimmermann wrote:
> Hi,
>
> I have a number of comments below. But if you want, you can add
>
> Acked-by: Thomas Zimmermann <tzimmermann at suse.de>
Thanks :)
> Am 15.12.21 um 10:17 schrieb Maxime Ripard:
> > From: Dave Stevenson <dave.stevenson at raspberrypi.com>
> >
> > The P030 format, used with the DRM_FORMAT_MOD_BROADCOM_SAND128 modifier,
> > is a format output by the video decoder on the BCM2711.
> >
> > Add native support to the KMS planes for that format.
> >
> > Signed-off-by: Dave Stevenson <dave.stevenson at raspberrypi.com>
> > Signed-off-by: Maxime Ripard <maxime at cerno.tech>
> > ---
> > drivers/gpu/drm/vc4/vc4_plane.c | 127 ++++++++++++++++++++++++--------
> > 1 file changed, 96 insertions(+), 31 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
> > index ac761c683663..022cd12f561e 100644
> > --- a/drivers/gpu/drm/vc4/vc4_plane.c
> > +++ b/drivers/gpu/drm/vc4/vc4_plane.c
> > @@ -33,6 +33,7 @@ static const struct hvs_format {
> > u32 hvs; /* HVS_FORMAT_* */
> > u32 pixel_order;
> > u32 pixel_order_hvs5;
> > + bool hvs5_only;
> > } hvs_formats[] = {
> > {
> > .drm = DRM_FORMAT_XRGB8888,
> > @@ -128,6 +129,12 @@ static const struct hvs_format {
> > .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE,
> > .pixel_order = HVS_PIXEL_ORDER_XYCRCB,
> > },
> > + {
> > + .drm = DRM_FORMAT_P030,
> > + .hvs = HVS_PIXEL_FORMAT_YCBCR_10BIT,
> > + .pixel_order = HVS_PIXEL_ORDER_XYCBCR,
> > + .hvs5_only = true,
> > + },
> > };
> > static const struct hvs_format *vc4_get_hvs_format(u32 drm_format)
> > @@ -762,47 +769,90 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
> > case DRM_FORMAT_MOD_BROADCOM_SAND128:
> > case DRM_FORMAT_MOD_BROADCOM_SAND256: {
> > uint32_t param = fourcc_mod_broadcom_param(fb->modifier);
> > - u32 tile_w, tile, x_off, pix_per_tile;
> > -
> > - hvs_format = HVS_PIXEL_FORMAT_H264;
> > -
> > - switch (base_format_mod) {
> > - case DRM_FORMAT_MOD_BROADCOM_SAND64:
> > - tiling = SCALER_CTL0_TILING_64B;
> > - tile_w = 64;
> > - break;
> > - case DRM_FORMAT_MOD_BROADCOM_SAND128:
> > - tiling = SCALER_CTL0_TILING_128B;
> > - tile_w = 128;
> > - break;
> > - case DRM_FORMAT_MOD_BROADCOM_SAND256:
> > - tiling = SCALER_CTL0_TILING_256B_OR_T;
> > - tile_w = 256;
> > - break;
> > - default:
> > - break;
> > - }
> > if (param > SCALER_TILE_HEIGHT_MASK) {
> > - DRM_DEBUG_KMS("SAND height too large (%d)\n", param);
> > + DRM_DEBUG_KMS("SAND height too large (%d)\n",
> > + param);
>
> Should be good for the 100-character limit.
>
> > return -EINVAL;
> > }
> > - pix_per_tile = tile_w / fb->format->cpp[0];
> > - tile = vc4_state->src_x / pix_per_tile;
> > - x_off = vc4_state->src_x % pix_per_tile;
> > + if (fb->format->format == DRM_FORMAT_P030) {
> > + hvs_format = HVS_PIXEL_FORMAT_YCBCR_10BIT;
> > + tiling = SCALER_CTL0_TILING_128B;
> > + } else {
> > + hvs_format = HVS_PIXEL_FORMAT_H264;
> > +
> > + switch (base_format_mod) {
> > + case DRM_FORMAT_MOD_BROADCOM_SAND64:
> > + tiling = SCALER_CTL0_TILING_64B;
> > + break;
> > + case DRM_FORMAT_MOD_BROADCOM_SAND128:
> > + tiling = SCALER_CTL0_TILING_128B;
> > + break;
> > + case DRM_FORMAT_MOD_BROADCOM_SAND256:
> > + tiling = SCALER_CTL0_TILING_256B_OR_T;
> > + break;
> > + default:
> > + return -EINVAL;
>
> It's not atomic modesetting? I'm asking because the code returns errno codes
> in several places.
This is atomic modesetting, but we're allowed to return an error at this
point :)
The function name is a bit confusing but it's mostly due to how the
hardware operates. We don't have the usual register set for the
composition but instead we have a list of hardware descriptors that will
describe the next frame.
The driver builds it here, at atomic_check time, and then copy it to the
hardware at atomic_commit time. So even though it's called
vc4_plane_mode_set, and does the operations needed to setup the
composition properly, we're still in atomic_check at this point.
> > + }
> > + }
> > /* Adjust the base pointer to the first pixel to be scanned
> > * out.
> > + *
> > + * For P030, y_ptr [31:4] is the 128bit word for the start pixel
> > + * y_ptr [3:0] is the pixel (0-11) contained within that 128bit
> > + * word that should be taken as the first pixel.
> > + * Ditto uv_ptr [31:4] vs [3:0], however [3:0] contains the
> > + * element within the 128bit word, eg for pixel 3 the value
> > + * should be 6.
> > */
> > for (i = 0; i < num_planes; i++) {
> > + u32 tile_w, tile, x_off, pix_per_tile;
> > +
> > + if (fb->format->format == DRM_FORMAT_P030) {
> > + /*
> > + * Spec says: bits [31:4] of the given address
> > + * should point to the 128-bit word containing
> > + * the desired starting pixel, and bits[3:0]
> > + * should be between 0 and 11, indicating which
> > + * of the 12-pixels in that 128-bit word is the
> > + * first pixel to be used
> > + */
> > + u32 remaining_pixels = vc4_state->src_x % 96;
> > + u32 aligned = remaining_pixels / 12;
> > + 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];
> > + x_off = (vc4_state->src_x % pix_per_tile) /
> > + (i ? h_subsample : 1) *
> > + fb->format->cpp[i];
> > + }
> > +
> > + tile = vc4_state->src_x / pix_per_tile;
> > +
>
> It's hard to read. If you can put some of these switches into helpers, it
> might be worth it.
Indeed. The whole function would need some though, is it ok if I send a
subsequent patch to fix it after merging this one?
> > vc4_state->offsets[i] += param * tile_w * tile;
> > vc4_state->offsets[i] += src_y /
> > (i ? v_subsample : 1) *
> > tile_w;
> > - vc4_state->offsets[i] += x_off /
> > - (i ? h_subsample : 1) *
> > - fb->format->cpp[i];
> > + vc4_state->offsets[i] += x_off & ~(i ? 1 : 0);
> > }
> > pitch0 = VC4_SET_FIELD(param, SCALER_TILE_HEIGHT);
> > @@ -955,7 +1005,8 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
> > /* Pitch word 1/2 */
> > for (i = 1; i < num_planes; i++) {
> > - if (hvs_format != HVS_PIXEL_FORMAT_H264) {
> > + if (hvs_format != HVS_PIXEL_FORMAT_H264 &&
> > + hvs_format != HVS_PIXEL_FORMAT_YCBCR_10BIT) {
>
> This branch's condition looks like is could be a little helper.
>
> > vc4_dlist_write(vc4_state,
> > VC4_SET_FIELD(fb->pitches[i],
> > SCALER_SRC_PITCH));
> > @@ -1315,6 +1366,13 @@ static bool vc4_format_mod_supported(struct drm_plane *plane,
> > default:
> > return false;
> > }
> > + case DRM_FORMAT_P030:
> > + switch (fourcc_mod_broadcom_mod(modifier)) {
> > + case DRM_FORMAT_MOD_BROADCOM_SAND128:
> > + return true;
> > + default:
> > + return false;
> > + }
> > case DRM_FORMAT_RGBX1010102:
> > case DRM_FORMAT_BGRX1010102:
> > case DRM_FORMAT_RGBA1010102:
> > @@ -1347,8 +1405,11 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
> > struct drm_plane *plane = NULL;
> > struct vc4_plane *vc4_plane;
> > u32 formats[ARRAY_SIZE(hvs_formats)];
> > + int num_formats = 0;
> > int ret = 0;
> > unsigned i;
> > + bool hvs5 = of_device_is_compatible(dev->dev->of_node,
> > + "brcm,bcm2711-vc5");
>
> Maybe also a little helper function?
>
> > static const uint64_t modifiers[] = {
> > DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED,
> > DRM_FORMAT_MOD_BROADCOM_SAND128,
> > @@ -1363,13 +1424,17 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
> > if (!vc4_plane)
> > return ERR_PTR(-ENOMEM);
> > - for (i = 0; i < ARRAY_SIZE(hvs_formats); i++)
> > - formats[i] = hvs_formats[i].drm;
> > + for (i = 0; i < ARRAY_SIZE(hvs_formats); i++) {
> > + if (!hvs_formats[i].hvs5_only || hvs5) {
> > + formats[num_formats] = hvs_formats[i].drm;
> > + num_formats++;
> > + }
> > + }
>
> With this loop, could num_formats ever be 0?
It shouldn't no, unless the older generation didn't define any format,
which is highly unlikely.
Maxime
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <https://lists.freedesktop.org/archives/dri-devel/attachments/20211216/d9221490/attachment.sig>
More information about the dri-devel
mailing list