Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5e290226 authored by Ayan Kumar Halder's avatar Ayan Kumar Halder Committed by Ayan kumar halder
Browse files

drm/arm/malidp:- Define a common list of AFBC format modifiers supported for DP500, DP550 and DP650

We need to define a common list of format modifiers supported by each of
the Mali display processors.

The following are the constraints with AFBC:-

1. AFBC is not supported for the formats defined in
malidp_hw_format_is_linear_only()

2. Some of the formats are supported only with AFBC modifiers. Thus we have
introduced a new function 'malidp_hw_format_is_afbc_only()' which verifies
the same.

3. AFBC_FORMAT_MOD_YTR needs to be provided for any RGB format.

4. Formats <= 16bpp cannot support AFBC_FORMAT_MOD_SPLIT.

5. CBR should not be set for non-subsampled formats.

6. SMART layer does not support framebuffer with AFBC modifiers.
Return -EINVAL for such a scenario.

7. AFBC_FORMAT_MOD_YTR is not supported for any YUV formats.

8. Formats which are subsampled cannot support AFBC_FORMAT_MOD_SPLIT.
However in DP550, YUV_420_10BIT is supported with AFBC_FORMAT_MOD_SPLIT.
This feature has been identified with
MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT.

9. In DP550 and DP650, for YUYV, the hardware supports different
format-ids to be used with and without AFBC modifier. We have used the
feature 'MALIDP_DEVICE_AFBC_YUYV_USE_422_P2' to identify this
characteristic.

10. DP500 does not support split mode (ie AFBC_FORMAT_MOD_SPLIT). We have
used the feature 'MALIDP_DEVICE_AFBC_SUPPORT_SPLIT' to identify the DPs
which support SPLIT mode.

11. DP550 supports YUV420 with split mode. We have defined the feature
'AFBC_SUPPORT_SPLIT_WITH_YUV_420_10' to identify this characteristic.

Changes since v1:-
- Merged https://patchwork.freedesktop.org/patch/265215/

 into this patch
- As Liviu pointed out in the last patch, we can pull the checks outside
of the 'while (*modifiers != DRM_FORMAT_MOD_INVALID)' loop
- Rebased

Changes since v3 (series):
- Added the ack
- Rebased on the latest drm-misc-next

Signed-off-by: default avatarAyan Kumar halder <ayan.halder@arm.com>
Reviewed-by: default avatarLiviu Dudau <liviu.dudau@arm.com>
Acked-by: default avatarAlyssa Rosenzweig <alyssa@rosenzweig.io>
Link: https://patchwork.freedesktop.org/patch/291762/?series=57895&rev=1
parent ed893860
Loading
Loading
Loading
Loading
+6 −26
Original line number Diff line number Diff line
@@ -264,37 +264,17 @@ static bool
malidp_verify_afbc_framebuffer_caps(struct drm_device *dev,
				    const struct drm_mode_fb_cmd2 *mode_cmd)
{
	const struct drm_format_info *info;

	if ((mode_cmd->modifier[0] >> 56) != DRM_FORMAT_MOD_VENDOR_ARM) {
		DRM_DEBUG_KMS("Unknown modifier (not Arm)\n");
	if (malidp_format_mod_supported(dev, mode_cmd->pixel_format,
					mode_cmd->modifier[0]) == false)
		return false;
	}

	if (mode_cmd->modifier[0] &
	    ~DRM_FORMAT_MOD_ARM_AFBC(AFBC_MOD_VALID_BITS)) {
		DRM_DEBUG_KMS("Unsupported modifiers\n");
		return false;
	}

	info = drm_get_format_info(dev, mode_cmd);
	if (!info) {
		DRM_DEBUG_KMS("Unable to get the format information\n");
		return false;
	}

	if (info->num_planes != 1) {
		DRM_DEBUG_KMS("AFBC buffers expect one plane\n");
		return false;
	}

	if (mode_cmd->offsets[0] != 0) {
		DRM_DEBUG_KMS("AFBC buffers' plane offset should be 0\n");
		return false;
	}

	switch (mode_cmd->modifier[0] & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) {
	case AFBC_FORMAT_MOD_BLOCK_SIZE_16x16:
	switch (mode_cmd->modifier[0] & AFBC_SIZE_MASK) {
	case AFBC_SIZE_16X16:
		if ((mode_cmd->width % 16) || (mode_cmd->height % 16)) {
			DRM_DEBUG_KMS("AFBC buffers must be aligned to 16 pixels\n");
			return false;
@@ -319,8 +299,8 @@ malidp_verify_afbc_framebuffer_size(struct drm_device *dev,
	u32 afbc_superblock_size = 0, afbc_superblock_height = 0;
	u32 afbc_superblock_width = 0, afbc_size = 0;

	switch (mode_cmd->modifier[0] & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) {
	case AFBC_FORMAT_MOD_BLOCK_SIZE_16x16:
	switch (mode_cmd->modifier[0] & AFBC_SIZE_MASK) {
	case AFBC_SIZE_16X16:
		afbc_superblock_height = 16;
		afbc_superblock_width = 16;
		break;
+6 −0
Original line number Diff line number Diff line
@@ -90,6 +90,12 @@ struct malidp_crtc_state {
int malidp_de_planes_init(struct drm_device *drm);
int malidp_crtc_init(struct drm_device *drm);

bool malidp_hw_format_is_linear_only(u32 format);
bool malidp_hw_format_is_afbc_only(u32 format);

bool malidp_format_mod_supported(struct drm_device *drm,
				 u32 format, u64 modifier);

#ifdef CONFIG_DEBUG_FS
void malidp_error(struct malidp_drm *malidp,
		  struct malidp_error_stats *error_stats, u32 status,
+91 −5
Original line number Diff line number Diff line
@@ -60,6 +60,8 @@ static const struct malidp_format_id malidp500_de_formats[] = {
#define MALIDP_ID(__group, __format) \
	((((__group) & 0x7) << 3) | ((__format) & 0x7))

#define AFBC_YUV_422_FORMAT_ID	MALIDP_ID(5, 1)

#define MALIDP_COMMON_FORMATS \
	/*    fourcc,   layers supporting the format,      internal id   */ \
	{ DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_VIDEO2 | SE_MEMWRITE, MALIDP_ID(0, 0) }, \
@@ -162,6 +164,32 @@ static const struct malidp_layer malidp650_layers[] = {
		ROTATE_NONE, 0 },
};

const u64 malidp_format_modifiers[] = {
	/* All RGB formats (except XRGB, RGBX, XBGR, BGRX) */
	DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR | AFBC_SPARSE),
	DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR),

	/* All RGB formats > 16bpp (except XRGB, RGBX, XBGR, BGRX) */
	DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_YTR | AFBC_SPARSE | AFBC_SPLIT),

	/* All 8 or 10 bit YUV 444 formats. */
	/* In DP550, 10 bit YUV 420 format also supported */
	DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_SPARSE | AFBC_SPLIT),

	/* YUV 420, 422 P1 8 bit and YUV 444 8 bit/10 bit formats */
	DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_SPARSE),
	DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16),

	/* YUV 420, 422 P1 8, 10 bit formats */
	DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_CBR | AFBC_SPARSE),
	DRM_FORMAT_MOD_ARM_AFBC(AFBC_SIZE_16X16 | AFBC_CBR),

	/* All formats */
	DRM_FORMAT_MOD_LINEAR,

	DRM_FORMAT_MOD_INVALID
};

#define SE_N_SCALING_COEFFS	96
static const u16 dp500_se_scaling_coeffs[][SE_N_SCALING_COEFFS] = {
	[MALIDP_UPSCALING_COEFFS - 1] = {
@@ -866,7 +894,10 @@ const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
			.se_base = MALIDP550_SE_BASE,
			.dc_base = MALIDP550_DC_BASE,
			.out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
			.features = MALIDP_REGMAP_HAS_CLEARIRQ,
			.features = MALIDP_REGMAP_HAS_CLEARIRQ |
				    MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
				    MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT |
				    MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
			.n_layers = ARRAY_SIZE(malidp550_layers),
			.layers = malidp550_layers,
			.de_irq_map = {
@@ -912,7 +943,9 @@ const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
			.se_base = MALIDP550_SE_BASE,
			.dc_base = MALIDP550_DC_BASE,
			.out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
			.features = MALIDP_REGMAP_HAS_CLEARIRQ,
			.features = MALIDP_REGMAP_HAS_CLEARIRQ |
				    MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
				    MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
			.n_layers = ARRAY_SIZE(malidp650_layers),
			.layers = malidp650_layers,
			.de_irq_map = {
@@ -961,19 +994,72 @@ const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
};

u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
			   u8 layer_id, u32 format)
			   u8 layer_id, u32 format, bool has_modifier)
{
	unsigned int i;

	for (i = 0; i < map->n_pixel_formats; i++) {
		if (((map->pixel_formats[i].layer & layer_id) == layer_id) &&
		    (map->pixel_formats[i].format == format))
		    (map->pixel_formats[i].format == format)) {
			/*
			 * In some DP550 and DP650, DRM_FORMAT_YUYV + AFBC modifier
			 * is supported by a different h/w format id than
			 * DRM_FORMAT_YUYV (only).
			 */
			if (format == DRM_FORMAT_YUYV &&
			    (has_modifier) &&
			    (map->features & MALIDP_DEVICE_AFBC_YUYV_USE_422_P2))
				return AFBC_YUV_422_FORMAT_ID;
			else
				return map->pixel_formats[i].id;
		}
	}

	return MALIDP_INVALID_FORMAT_ID;
}

bool malidp_hw_format_is_linear_only(u32 format)
{
	switch (format) {
	case DRM_FORMAT_ARGB2101010:
	case DRM_FORMAT_RGBA1010102:
	case DRM_FORMAT_BGRA1010102:
	case DRM_FORMAT_ARGB8888:
	case DRM_FORMAT_RGBA8888:
	case DRM_FORMAT_BGRA8888:
	case DRM_FORMAT_XBGR8888:
	case DRM_FORMAT_XRGB8888:
	case DRM_FORMAT_RGBX8888:
	case DRM_FORMAT_BGRX8888:
	case DRM_FORMAT_RGB888:
	case DRM_FORMAT_RGB565:
	case DRM_FORMAT_ARGB1555:
	case DRM_FORMAT_RGBA5551:
	case DRM_FORMAT_BGRA5551:
	case DRM_FORMAT_UYVY:
	case DRM_FORMAT_XYUV8888:
	case DRM_FORMAT_XVYU2101010:
	case DRM_FORMAT_X0L2:
	case DRM_FORMAT_X0L0:
		return true;
	default:
		return false;
	}
}

bool malidp_hw_format_is_afbc_only(u32 format)
{
	switch (format) {
	case DRM_FORMAT_VUY888:
	case DRM_FORMAT_VUY101010:
	case DRM_FORMAT_YUV420_8BIT:
	case DRM_FORMAT_YUV420_10BIT:
		return true;
	default:
		return false;
	}
}

static void malidp_hw_clear_irq(struct malidp_hw_device *hwdev, u8 block, u32 irq)
{
	u32 base = malidp_get_block_base(hwdev, block);
+18 −6
Original line number Diff line number Diff line
@@ -95,7 +95,10 @@ struct malidp_se_config {
};

/* regmap features */
#define MALIDP_REGMAP_HAS_CLEARIRQ	(1 << 0)
#define MALIDP_REGMAP_HAS_CLEARIRQ				BIT(0)
#define MALIDP_DEVICE_AFBC_SUPPORT_SPLIT			BIT(1)
#define MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT		BIT(2)
#define MALIDP_DEVICE_AFBC_YUYV_USE_422_P2			BIT(3)

struct malidp_hw_regmap {
	/* address offset of the DE register bank */
@@ -321,7 +324,7 @@ int malidp_se_irq_init(struct drm_device *drm, int irq);
void malidp_se_irq_fini(struct malidp_hw_device *hwdev);

u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
			   u8 layer_id, u32 format);
			   u8 layer_id, u32 format, bool has_modifier);

static inline u8 malidp_hw_get_pitch_align(struct malidp_hw_device *hwdev, bool rotated)
{
@@ -390,9 +393,18 @@ static inline void malidp_se_set_enh_coeffs(struct malidp_hw_device *hwdev)

#define MALIDP_GAMMA_LUT_SIZE		4096

#define AFBC_MOD_VALID_BITS (AFBC_FORMAT_MOD_BLOCK_SIZE_MASK | \
			AFBC_FORMAT_MOD_YTR | AFBC_FORMAT_MOD_SPLIT | \
			AFBC_FORMAT_MOD_SPARSE | AFBC_FORMAT_MOD_CBR | \
			AFBC_FORMAT_MOD_TILED | AFBC_FORMAT_MOD_SC)
#define AFBC_SIZE_MASK		AFBC_FORMAT_MOD_BLOCK_SIZE_MASK
#define AFBC_SIZE_16X16		AFBC_FORMAT_MOD_BLOCK_SIZE_16x16
#define AFBC_YTR		AFBC_FORMAT_MOD_YTR
#define AFBC_SPARSE		AFBC_FORMAT_MOD_SPARSE
#define AFBC_CBR		AFBC_FORMAT_MOD_CBR
#define AFBC_SPLIT		AFBC_FORMAT_MOD_SPLIT
#define AFBC_TILED		AFBC_FORMAT_MOD_TILED
#define AFBC_SC			AFBC_FORMAT_MOD_SC

#define AFBC_MOD_VALID_BITS	(AFBC_SIZE_MASK | AFBC_YTR | AFBC_SPLIT | \
				 AFBC_SPARSE | AFBC_CBR | AFBC_TILED | AFBC_SC)

extern const u64 malidp_format_modifiers[];

#endif  /* __MALIDP_HW_H__ */
+1 −1
Original line number Diff line number Diff line
@@ -143,7 +143,7 @@ malidp_mw_encoder_atomic_check(struct drm_encoder *encoder,

	mw_state->format =
		malidp_hw_get_format_id(&malidp->dev->hw->map, SE_MEMWRITE,
					fb->format->format);
					fb->format->format, !!fb->modifier);
	if (mw_state->format == MALIDP_INVALID_FORMAT_ID) {
		struct drm_format_name_buf format_name;

Loading