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

Commit c530174b authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch 'for-upstream/mali-dp' of git://linux-arm.org/linux-ld into drm-next



misc mali-dp updates.

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Liviu Dudau <Liviu.Dudau@arm.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20181003105009.GD1156@e110455-lin.cambridge.arm.com
parents 41050757 3dae1c09
Loading
Loading
Loading
Loading
+16 −12
Original line number Diff line number Diff line
@@ -348,19 +348,20 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc,

	/*
	 * check if there is enough rotation memory available for planes
	 * that need 90° and 270° rotation. Each plane has set its required
	 * memory size in the ->plane_check() callback, here we only make
	 * sure that the sums are less that the total usable memory.
	 * that need 90° and 270° rotion or planes that are compressed.
	 * Each plane has set its required memory size in the ->plane_check()
	 * callback, here we only make sure that the sums are less that the
	 * total usable memory.
	 *
	 * The rotation memory allocation algorithm (for each plane):
	 *  a. If no more rotated planes exist, all remaining rotate
	 *     memory in the bank is available for use by the plane.
	 *  b. If other rotated planes exist, and plane's layer ID is
	 *     DE_VIDEO1, it can use all the memory from first bank if
	 *     secondary rotation memory bank is available, otherwise it can
	 *  a. If no more rotated or compressed planes exist, all remaining
	 *     rotate memory in the bank is available for use by the plane.
	 *  b. If other rotated or compressed planes exist, and plane's
	 *     layer ID is DE_VIDEO1, it can use all the memory from first bank
	 *     if secondary rotation memory bank is available, otherwise it can
	 *     use up to half the bank's memory.
	 *  c. If other rotated planes exist, and plane's layer ID is not
	 *     DE_VIDEO1, it can use half of the available memory
	 *  c. If other rotated or compressed planes exist, and plane's layer ID
	 *     is not DE_VIDEO1, it can use half of the available memory.
	 *
	 * Note: this algorithm assumes that the order in which the planes are
	 * checked always has DE_VIDEO1 plane first in the list if it is
@@ -372,7 +373,9 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc,

	/* first count the number of rotated planes */
	drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) {
		if (pstate->rotation & MALIDP_ROTATED_MASK)
		struct drm_framebuffer *fb = pstate->fb;

		if ((pstate->rotation & MALIDP_ROTATED_MASK) || fb->modifier)
			rotated_planes++;
	}

@@ -388,8 +391,9 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc,
	drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) {
		struct malidp_plane *mp = to_malidp_plane(plane);
		struct malidp_plane_state *ms = to_malidp_plane_state(pstate);
		struct drm_framebuffer *fb = pstate->fb;

		if (pstate->rotation & MALIDP_ROTATED_MASK) {
		if ((pstate->rotation & MALIDP_ROTATED_MASK) || fb->modifier) {
			/* process current plane */
			rotated_planes--;

+127 −1
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#include "malidp_hw.h"

#define MALIDP_CONF_VALID_TIMEOUT	250
#define AFBC_HEADER_SIZE		16

static void malidp_write_gamma_table(struct malidp_hw_device *hwdev,
				     u32 data[MALIDP_COEFFTAB_NUM_COEFFS])
@@ -258,8 +259,133 @@ static const struct drm_mode_config_helper_funcs malidp_mode_config_helpers = {
	.atomic_commit_tail = malidp_atomic_commit_tail,
};

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");
		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:
		if ((mode_cmd->width % 16) || (mode_cmd->height % 16)) {
			DRM_DEBUG_KMS("AFBC buffers must be aligned to 16 pixels\n");
			return false;
		}
		break;
	default:
		DRM_DEBUG_KMS("Unsupported AFBC block size\n");
		return false;
	}

	return true;
}

static bool
malidp_verify_afbc_framebuffer_size(struct drm_device *dev,
				    struct drm_file *file,
				    const struct drm_mode_fb_cmd2 *mode_cmd)
{
	int n_superblocks = 0;
	const struct drm_format_info *info;
	struct drm_gem_object *objs = NULL;
	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:
		afbc_superblock_height = 16;
		afbc_superblock_width = 16;
		break;
	default:
		DRM_DEBUG_KMS("AFBC superblock size is not supported\n");
		return false;
	}

	info = drm_get_format_info(dev, mode_cmd);

	n_superblocks = (mode_cmd->width / afbc_superblock_width) *
		(mode_cmd->height / afbc_superblock_height);

	afbc_superblock_size = info->cpp[0] * afbc_superblock_width *
		afbc_superblock_height;

	afbc_size = ALIGN(n_superblocks * AFBC_HEADER_SIZE, 128);

	if (mode_cmd->width * info->cpp[0] != mode_cmd->pitches[0]) {
		DRM_DEBUG_KMS("Invalid value of pitch (=%u) should be same as width (=%u) * cpp (=%u)\n",
			      mode_cmd->pitches[0], mode_cmd->width, info->cpp[0]);
		return false;
	}

	objs = drm_gem_object_lookup(file, mode_cmd->handles[0]);
	if (!objs) {
		DRM_DEBUG_KMS("Failed to lookup GEM object\n");
		return false;
	}

	if (objs->size < afbc_size) {
		DRM_DEBUG_KMS("buffer size (%zu) too small for AFBC buffer size = %u\n",
			      objs->size, afbc_size);
		drm_gem_object_put_unlocked(objs);
		return false;
	}

	drm_gem_object_put_unlocked(objs);

	return true;
}

static bool
malidp_verify_afbc_framebuffer(struct drm_device *dev, struct drm_file *file,
			       const struct drm_mode_fb_cmd2 *mode_cmd)
{
	if (malidp_verify_afbc_framebuffer_caps(dev, mode_cmd))
		return malidp_verify_afbc_framebuffer_size(dev, file, mode_cmd);

	return false;
}

struct drm_framebuffer *
malidp_fb_create(struct drm_device *dev, struct drm_file *file,
		 const struct drm_mode_fb_cmd2 *mode_cmd)
{
	if (mode_cmd->modifier[0]) {
		if (!malidp_verify_afbc_framebuffer(dev, file, mode_cmd))
			return ERR_PTR(-EINVAL);
	}

	return drm_gem_fb_create(dev, file, mode_cmd);
}

static const struct drm_mode_config_funcs malidp_mode_config_funcs = {
	.fb_create = drm_gem_fb_create,
	.fb_create = malidp_fb_create,
	.atomic_check = drm_atomic_helper_check,
	.atomic_commit = drm_atomic_helper_commit,
};
+8 −0
Original line number Diff line number Diff line
@@ -55,6 +55,12 @@ struct malidp_plane {
	const struct malidp_layer *layer;
};

enum mmu_prefetch_mode {
	MALIDP_PREFETCH_MODE_NONE,
	MALIDP_PREFETCH_MODE_PARTIAL,
	MALIDP_PREFETCH_MODE_FULL,
};

struct malidp_plane_state {
	struct drm_plane_state base;

@@ -63,6 +69,8 @@ struct malidp_plane_state {
	/* internal format ID */
	u8 format;
	u8 n_planes;
	enum mmu_prefetch_mode mmu_prefetch_mode;
	u32 mmu_prefetch_pgsize;
};

#define to_malidp_plane(x) container_of(x, struct malidp_plane, base)
+41 −17
Original line number Diff line number Diff line
@@ -84,16 +84,48 @@ static const struct malidp_format_id malidp550_de_formats[] = {
};

static const struct malidp_layer malidp500_layers[] = {
	{ DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE, MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB },
	{ DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE, MALIDP_DE_LG_STRIDE, 0 },
	{ DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE, MALIDP_DE_LG_STRIDE, 0 },
	/* id, base address, fb pointer address base, stride offset,
	 *	yuv2rgb matrix offset, mmu control register offset, rotation_features
	 */
	{ DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE,
		MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB, 0, ROTATE_ANY },
	{ DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE,
		MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY },
	{ DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE,
		MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY },
};

static const struct malidp_layer malidp550_layers[] = {
	{ DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE, MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB },
	{ DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE, MALIDP_DE_LG_STRIDE, 0 },
	{ DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE, MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB },
	{ DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE, MALIDP550_DE_LS_R1_STRIDE, 0 },
	/* id, base address, fb pointer address base, stride offset,
	 *	yuv2rgb matrix offset, mmu control register offset, rotation_features
	 */
	{ DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
		MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY },
	{ DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
		MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY },
	{ DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
		MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY },
	{ DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
		MALIDP550_DE_LS_R1_STRIDE, 0, 0, ROTATE_NONE },
};

static const struct malidp_layer malidp650_layers[] = {
	/* id, base address, fb pointer address base, stride offset,
	 *	yuv2rgb matrix offset, mmu control register offset,
	 *	rotation_features
	 */
	{ DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
		MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
		MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY },
	{ DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
		MALIDP_DE_LG_STRIDE, 0, MALIDP650_DE_LG_MMU_CTRL,
		ROTATE_COMPRESSED },
	{ DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
		MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
		MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY },
	{ DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
		MALIDP550_DE_LS_R1_STRIDE, 0, MALIDP650_DE_LS_MMU_CTRL,
		ROTATE_NONE },
};

#define SE_N_SCALING_COEFFS	96
@@ -288,10 +320,6 @@ static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode *

static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt)
{
	/* RGB888 or BGR888 can't be rotated */
	if ((fmt == DRM_FORMAT_RGB888) || (fmt == DRM_FORMAT_BGR888))
		return -EINVAL;

	/*
	 * Each layer needs enough rotation memory to fit 8 lines
	 * worth of pixel data. Required size is then:
@@ -579,10 +607,6 @@ static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16
{
	u32 bytes_per_col;

	/* raw RGB888 or BGR888 can't be rotated */
	if ((fmt == DRM_FORMAT_RGB888) || (fmt == DRM_FORMAT_BGR888))
		return -EINVAL;

	switch (fmt) {
	/* 8 lines at 4 bytes per pixel */
	case DRM_FORMAT_ARGB2101010:
@@ -853,8 +877,8 @@ const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
			.dc_base = MALIDP550_DC_BASE,
			.out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
			.features = MALIDP_REGMAP_HAS_CLEARIRQ,
			.n_layers = ARRAY_SIZE(malidp550_layers),
			.layers = malidp550_layers,
			.n_layers = ARRAY_SIZE(malidp650_layers),
			.layers = malidp650_layers,
			.de_irq_map = {
				.irq_mask = MALIDP_DE_IRQ_UNDERRUN |
					    MALIDP650_DE_IRQ_DRIFT |
+13 −0
Original line number Diff line number Diff line
@@ -36,6 +36,12 @@ enum {
	SE_MEMWRITE = BIT(5),
};

enum rotation_features {
	ROTATE_NONE,		/* does not support rotation at all */
	ROTATE_ANY,		/* supports rotation on any buffers */
	ROTATE_COMPRESSED,	/* supports rotation only on compressed buffers */
};

struct malidp_format_id {
	u32 format;		/* DRM fourcc */
	u8 layer;		/* bitmask of layers supporting it */
@@ -62,6 +68,8 @@ struct malidp_layer {
	u16 ptr;		/* address offset for the pointer register */
	u16 stride_offset;	/* offset to the first stride register. */
	s16 yuv2rgb_offset;	/* offset to the YUV->RGB matrix entries */
	u16 mmu_ctrl_offset;    /* offset to the MMU control register */
	enum rotation_features rot;	/* type of rotation supported */
};

enum malidp_scaling_coeff_set {
@@ -380,4 +388,9 @@ 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)

#endif  /* __MALIDP_HW_H__ */
Loading