diff options
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_plane.c | 84 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_regs.h | 6 |
2 files changed, 83 insertions, 7 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 6efd55bae8db..2575bd81a010 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -467,12 +467,14 @@ static int vc4_plane_mode_set(struct drm_plane *plane, struct drm_framebuffer *fb = state->fb; u32 ctl0_offset = vc4_state->dlist_count; const struct hvs_format *format = vc4_get_hvs_format(fb->format->format); + u64 base_format_mod = fourcc_mod_broadcom_mod(fb->modifier); int num_planes = drm_format_num_planes(format->drm); bool mix_plane_alpha; bool covers_screen; u32 scl0, scl1, pitch0; u32 lbm_size, tiling; unsigned long irqflags; + u32 hvs_format = format->hvs; int ret, i; ret = vc4_plane_setup_clipping_and_scaling(state); @@ -512,7 +514,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane, scl1 = vc4_get_scl_field(state, 0); } - switch (fb->modifier) { + switch (base_format_mod) { case DRM_FORMAT_MOD_LINEAR: tiling = SCALER_CTL0_TILING_LINEAR; pitch0 = VC4_SET_FIELD(fb->pitches[0], SCALER_SRC_PITCH); @@ -535,6 +537,49 @@ static int vc4_plane_mode_set(struct drm_plane *plane, break; } + case DRM_FORMAT_MOD_BROADCOM_SAND64: + case DRM_FORMAT_MOD_BROADCOM_SAND128: + case DRM_FORMAT_MOD_BROADCOM_SAND256: { + uint32_t param = fourcc_mod_broadcom_param(fb->modifier); + + /* Column-based NV12 or RGBA. + */ + if (fb->format->num_planes > 1) { + if (hvs_format != HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE) { + DRM_DEBUG_KMS("SAND format only valid for NV12/21"); + return -EINVAL; + } + hvs_format = HVS_PIXEL_FORMAT_H264; + } else { + if (base_format_mod == DRM_FORMAT_MOD_BROADCOM_SAND256) { + DRM_DEBUG_KMS("SAND256 format only valid for H.264"); + return -EINVAL; + } + } + + 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: + break; + } + + if (param > SCALER_TILE_HEIGHT_MASK) { + DRM_DEBUG_KMS("SAND height too large (%d)\n", param); + return -EINVAL; + } + + pitch0 = VC4_SET_FIELD(param, SCALER_TILE_HEIGHT); + break; + } + default: DRM_DEBUG_KMS("Unsupported FB tiling flag 0x%16llx", (long long)fb->modifier); @@ -546,7 +591,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane, SCALER_CTL0_VALID | VC4_SET_FIELD(SCALER_CTL0_RGBA_EXPAND_ROUND, SCALER_CTL0_RGBA_EXPAND) | (format->pixel_order << SCALER_CTL0_ORDER_SHIFT) | - (format->hvs << SCALER_CTL0_PIXEL_FORMAT_SHIFT) | + (hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) | VC4_SET_FIELD(tiling, SCALER_CTL0_TILING) | (vc4_state->is_unity ? SCALER_CTL0_UNITY : 0) | VC4_SET_FIELD(scl0, SCALER_CTL0_SCL0) | @@ -608,8 +653,13 @@ static int vc4_plane_mode_set(struct drm_plane *plane, /* Pitch word 1/2 */ for (i = 1; i < num_planes; i++) { - vc4_dlist_write(vc4_state, - VC4_SET_FIELD(fb->pitches[i], SCALER_SRC_PITCH)); + if (hvs_format != HVS_PIXEL_FORMAT_H264) { + vc4_dlist_write(vc4_state, + VC4_SET_FIELD(fb->pitches[i], + SCALER_SRC_PITCH)); + } else { + vc4_dlist_write(vc4_state, pitch0); + } } /* Colorspace conversion words */ @@ -867,13 +917,30 @@ static bool vc4_format_mod_supported(struct drm_plane *plane, case DRM_FORMAT_BGR565: case DRM_FORMAT_ARGB1555: case DRM_FORMAT_XRGB1555: - return true; + switch (fourcc_mod_broadcom_mod(modifier)) { + case DRM_FORMAT_MOD_LINEAR: + case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: + case DRM_FORMAT_MOD_BROADCOM_SAND64: + case DRM_FORMAT_MOD_BROADCOM_SAND128: + return true; + default: + return false; + } + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV21: + switch (fourcc_mod_broadcom_mod(modifier)) { + case DRM_FORMAT_MOD_LINEAR: + case DRM_FORMAT_MOD_BROADCOM_SAND64: + case DRM_FORMAT_MOD_BROADCOM_SAND128: + case DRM_FORMAT_MOD_BROADCOM_SAND256: + return true; + default: + return false; + } case DRM_FORMAT_YUV422: case DRM_FORMAT_YVU422: case DRM_FORMAT_YUV420: case DRM_FORMAT_YVU420: - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV21: case DRM_FORMAT_NV16: case DRM_FORMAT_NV61: default: @@ -903,6 +970,9 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, 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_LINEAR, DRM_FORMAT_MOD_INVALID }; diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h index d1fb6fec46eb..d6864fa4bd14 100644 --- a/drivers/gpu/drm/vc4/vc4_regs.h +++ b/drivers/gpu/drm/vc4/vc4_regs.h @@ -1031,6 +1031,12 @@ enum hvs_pixel_format { #define SCALER_SRC_PITCH_MASK VC4_MASK(15, 0) #define SCALER_SRC_PITCH_SHIFT 0 +/* PITCH0/1/2 fields for tiled (SAND). */ +#define SCALER_TILE_SKIP_0_MASK VC4_MASK(18, 16) +#define SCALER_TILE_SKIP_0_SHIFT 16 +#define SCALER_TILE_HEIGHT_MASK VC4_MASK(15, 0) +#define SCALER_TILE_HEIGHT_SHIFT 0 + /* PITCH0 fields for T-tiled. */ #define SCALER_PITCH0_TILE_WIDTH_L_MASK VC4_MASK(22, 16) #define SCALER_PITCH0_TILE_WIDTH_L_SHIFT 16 |