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

Commit 83d642ee authored by Mihail Atanassov's avatar Mihail Atanassov Committed by Liviu Dudau
Browse files

drm: mali-dp: fix stride setting for multi-plane formats



Hardware has multiple (2 or 3, depending on model) stride
registers per layer; add a function that correctly takes that
into account. On hardware that only has 2 stride registers,
ensure that 3-plane (YUV) content has identical strides
for both chroma planes.

Signed-off-by: default avatarMihail Atanassov <mihail.atanassov@arm.com>
[Removed smart layer stride setup, comment and commit message clarifications]
Signed-off-by: default avatarLiviu Dudau <Liviu.Dudau@arm.com>
parent b70b332f
Loading
Loading
Loading
Loading
+10 −7
Original line number Diff line number Diff line
@@ -74,16 +74,16 @@ 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 },
	{ DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE },
	{ DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE },
	{ DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE, MALIDP_DE_LV_STRIDE0 },
	{ DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE, MALIDP_DE_LG_STRIDE },
	{ DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE, MALIDP_DE_LG_STRIDE },
};

static const struct malidp_layer malidp550_layers[] = {
	{ DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE },
	{ DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE },
	{ DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE },
	{ DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE },
	{ DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE, MALIDP_DE_LV_STRIDE0 },
	{ DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE, MALIDP_DE_LG_STRIDE },
	{ DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE, MALIDP_DE_LV_STRIDE0 },
	{ DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE, 0 },
};

#define MALIDP_DE_DEFAULT_PREFETCH_START	5
@@ -447,6 +447,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = {
		.set_config_valid = malidp500_set_config_valid,
		.modeset = malidp500_modeset,
		.rotmem_required = malidp500_rotmem_required,
		.features = MALIDP_DEVICE_LV_HAS_3_STRIDES,
	},
	[MALIDP_550] = {
		.map = {
@@ -480,6 +481,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = {
		.set_config_valid = malidp550_set_config_valid,
		.modeset = malidp550_modeset,
		.rotmem_required = malidp550_rotmem_required,
		.features = 0,
	},
	[MALIDP_650] = {
		.map = {
@@ -514,6 +516,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = {
		.set_config_valid = malidp550_set_config_valid,
		.modeset = malidp550_modeset,
		.rotmem_required = malidp550_rotmem_required,
		.features = 0,
	},
};

+5 −0
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ struct malidp_layer {
	u16 id;			/* layer ID */
	u16 base;		/* address offset for the register bank */
	u16 ptr;		/* address offset for the pointer register */
	u16 stride_offset;	/* Offset to the first stride register. */
};

/* regmap features */
@@ -93,6 +94,10 @@ struct malidp_hw_regmap {
	const u8 bus_align_bytes;
};

/* device features */
/* Unlike DP550/650, DP500 has 3 stride registers in its video layer. */
#define MALIDP_DEVICE_LV_HAS_3_STRIDES	BIT(0)

struct malidp_hw_device {
	const struct malidp_hw_regmap map;
	void __iomem *regs;
+31 −3
Original line number Diff line number Diff line
@@ -37,7 +37,6 @@
#define   LAYER_V_VAL(x)		(((x) & 0x1fff) << 16)
#define MALIDP_LAYER_COMP_SIZE		0x010
#define MALIDP_LAYER_OFFSET		0x014
#define MALIDP_LAYER_STRIDE		0x018

/*
 * This 4-entry look-up-table is used to determine the full 8-bit alpha value
@@ -138,6 +137,16 @@ static int malidp_de_plane_check(struct drm_plane *plane,
	    (state->crtc_h < mp->hwdev->min_line_size))
		return -EINVAL;

	/*
	 * DP550/650 video layers can accept 3 plane formats only if
	 * fb->pitches[1] == fb->pitches[2] since they don't have a
	 * third plane stride register.
	 */
	if (ms->n_planes == 3 &&
	    !(mp->hwdev->features & MALIDP_DEVICE_LV_HAS_3_STRIDES) &&
	    (state->fb->pitches[1] != state->fb->pitches[2]))
		return -EINVAL;

	/* packed RGB888 / BGR888 can't be rotated or flipped */
	if (state->rotation != DRM_ROTATE_0 &&
	    (fb->format->format == DRM_FORMAT_RGB888 ||
@@ -170,6 +179,25 @@ static int malidp_de_plane_check(struct drm_plane *plane,
	return 0;
}

static void malidp_de_set_plane_pitches(struct malidp_plane *mp,
					int num_planes, unsigned int pitches[3])
{
	int i;
	int num_strides = num_planes;

	if (!mp->layer->stride_offset)
		return;

	if (num_planes == 3)
		num_strides = (mp->hwdev->features &
			       MALIDP_DEVICE_LV_HAS_3_STRIDES) ? 3 : 2;

	for (i = 0; i < num_strides; ++i)
		malidp_hw_write(mp->hwdev, pitches[i],
				mp->layer->base +
				mp->layer->stride_offset + i * 4);
}

static void malidp_de_plane_update(struct drm_plane *plane,
				   struct drm_plane_state *old_state)
{
@@ -200,9 +228,9 @@ static void malidp_de_plane_update(struct drm_plane *plane,
		obj->paddr += plane->state->fb->offsets[i];
		malidp_hw_write(mp->hwdev, lower_32_bits(obj->paddr), ptr);
		malidp_hw_write(mp->hwdev, upper_32_bits(obj->paddr), ptr + 4);
		malidp_hw_write(mp->hwdev, plane->state->fb->pitches[i],
				mp->layer->base + MALIDP_LAYER_STRIDE);
	}
	malidp_de_set_plane_pitches(mp, ms->n_planes,
				    plane->state->fb->pitches);

	malidp_hw_write(mp->hwdev, LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h),
			mp->layer->base + MALIDP_LAYER_SIZE);
+4 −0
Original line number Diff line number Diff line
@@ -81,6 +81,10 @@
#define MALIDP_DE_SYNC_WIDTH		0x8
#define MALIDP_DE_HV_ACTIVE		0xc

/* Stride register offsets relative to Lx_BASE */
#define MALIDP_DE_LG_STRIDE		0x18
#define MALIDP_DE_LV_STRIDE0		0x18

/* macros to set values into registers */
#define MALIDP_DE_H_FRONTPORCH(x)	(((x) & 0xfff) << 0)
#define MALIDP_DE_H_BACKPORCH(x)	(((x) & 0x3ff) << 16)