From 87c4b03b9d1180c2f878b19363ec0609b5f24c75 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Fri, 24 Jan 2020 14:25:41 +0000 Subject: [PATCH] drm/vc4: Add support for DRM_FORMAT_P030 to vc4 planes This currently doesn't handle non-zero source rectangles correctly, but add support for DRM_FORMAT_P030 with DRM_FORMAT_MOD_BROADCOM_SAND128 modifier to planes when running on HVS5. WIP still for source cropping SAND/P030 formats Signed-off-by: Dave Stevenson --- drivers/gpu/drm/vc4/vc4_plane.c | 83 +++++++++++++++++++++++---------- 1 file changed, 59 insertions(+), 24 deletions(-) --- 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) @@ -809,27 +816,33 @@ static int vc4_plane_mode_set(struct drm 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: + if (fb->format->format == DRM_FORMAT_P030) { + hvs_format = HVS_PIXEL_FORMAT_YCBCR_10BIT; 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; - } + tile_w = 96; + } else { + 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); return -EINVAL; } @@ -839,6 +852,13 @@ static int vc4_plane_mode_set(struct drm /* 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++) { vc4_state->offsets[i] += param * tile_w * tile; @@ -951,8 +971,8 @@ static int vc4_plane_mode_set(struct drm vc4_dlist_write(vc4_state, VC4_SET_FIELD(state->alpha >> 4, SCALER5_CTL2_ALPHA) | - fb->format->has_alpha ? - SCALER5_CTL2_ALPHA_PREMULT : 0 | + (fb->format->has_alpha ? + SCALER5_CTL2_ALPHA_PREMULT : 0) | (mix_plane_alpha ? SCALER5_CTL2_ALPHA_MIX : 0) | VC4_SET_FIELD(fb->format->has_alpha ? @@ -1000,7 +1020,8 @@ static int vc4_plane_mode_set(struct drm /* 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) { vc4_dlist_write(vc4_state, VC4_SET_FIELD(fb->pitches[i], SCALER_SRC_PITCH)); @@ -1371,6 +1392,13 @@ static bool vc4_format_mod_supported(str 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: @@ -1403,8 +1431,11 @@ struct drm_plane *vc4_plane_init(struct 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"); static const uint64_t modifiers[] = { DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED, DRM_FORMAT_MOD_BROADCOM_SAND128, @@ -1419,13 +1450,17 @@ struct drm_plane *vc4_plane_init(struct 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++; + } + } plane = &vc4_plane->base; ret = drm_universal_plane_init(dev, plane, 0, &vc4_plane_funcs, - formats, ARRAY_SIZE(formats), + formats, num_formats, modifiers, type, NULL); drm_plane_helper_add(plane, &vc4_plane_helper_funcs);