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

Commit 3d95f76a authored by Linus Walleij's avatar Linus Walleij
Browse files

drm/pl111: Properly detect the ARM PL110 variants



With a bit of refactoring we can contain the variant data for
the strange PL110 versions that is feature-incomplete PL110 for
the ARM Integrator/CP and somewhere inbetween PL110 and PL111
for the ARM Versatile AB and Versatile PB.

We also accomodate for the custom duct-taped RGB565/BGR565 support
in the Versatile variant.

Reviewed-by: default avatarEric Anholt <eric@anholt.net>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20180206093540.8147-1-linus.walleij@linaro.org
parent f40f5b87
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -36,12 +36,15 @@ struct drm_minor;
 * struct pl111_variant_data - encodes IP differences
 * struct pl111_variant_data - encodes IP differences
 * @name: the name of this variant
 * @name: the name of this variant
 * @is_pl110: this is the early PL110 variant
 * @is_pl110: this is the early PL110 variant
 * @external_bgr: this is the Versatile Pl110 variant with external
 *	BGR/RGB routing
 * @formats: array of supported pixel formats on this variant
 * @formats: array of supported pixel formats on this variant
 * @nformats: the length of the array of supported pixel formats
 * @nformats: the length of the array of supported pixel formats
 */
 */
struct pl111_variant_data {
struct pl111_variant_data {
	const char *name;
	const char *name;
	bool is_pl110;
	bool is_pl110;
	bool external_bgr;
	const u32 *formats;
	const u32 *formats;
	unsigned int nformats;
	unsigned int nformats;
};
};
+10 −27
Original line number Original line Diff line number Diff line
@@ -193,7 +193,7 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
{
{
	struct device *dev = &amba_dev->dev;
	struct device *dev = &amba_dev->dev;
	struct pl111_drm_dev_private *priv;
	struct pl111_drm_dev_private *priv;
	struct pl111_variant_data *variant = id->data;
	const struct pl111_variant_data *variant = id->data;
	struct drm_device *drm;
	struct drm_device *drm;
	int ret;
	int ret;


@@ -209,27 +209,10 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
	drm->dev_private = priv;
	drm->dev_private = priv;
	priv->variant = variant;
	priv->variant = variant;


	/*
	/* The two variants swap this register */
	 * The PL110 and PL111 variants have two registers
	 * swapped: interrupt enable and control. For this reason
	 * we use offsets that we can change per variant.
	 */
	if (variant->is_pl110) {
	if (variant->is_pl110) {
		/*
		 * The ARM Versatile boards are even more special:
		 * their PrimeCell ID say they are PL110 but the
		 * control and interrupt enable registers are anyway
		 * swapped to the PL111 order so they are not following
		 * the PL110 datasheet.
		 */
		if (of_machine_is_compatible("arm,versatile-ab") ||
		    of_machine_is_compatible("arm,versatile-pb")) {
			priv->ienb = CLCD_PL111_IENB;
			priv->ctrl = CLCD_PL111_CNTL;
		} else {
		priv->ienb = CLCD_PL110_IENB;
		priv->ienb = CLCD_PL110_IENB;
		priv->ctrl = CLCD_PL110_CNTL;
		priv->ctrl = CLCD_PL110_CNTL;
		}
	} else {
	} else {
		priv->ienb = CLCD_PL111_IENB;
		priv->ienb = CLCD_PL111_IENB;
		priv->ctrl = CLCD_PL111_CNTL;
		priv->ctrl = CLCD_PL111_CNTL;
@@ -241,6 +224,11 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
		return PTR_ERR(priv->regs);
		return PTR_ERR(priv->regs);
	}
	}


	/* This may override some variant settings */
	ret = pl111_versatile_init(dev, priv);
	if (ret)
		goto dev_unref;

	/* turn off interrupts before requesting the irq */
	/* turn off interrupts before requesting the irq */
	writel(0, priv->regs + priv->ienb);
	writel(0, priv->regs + priv->ienb);


@@ -251,10 +239,6 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
		return ret;
		return ret;
	}
	}


	ret = pl111_versatile_init(dev, priv);
	if (ret)
		goto dev_unref;

	ret = pl111_modeset_init(drm);
	ret = pl111_modeset_init(drm);
	if (ret != 0)
	if (ret != 0)
		goto dev_unref;
		goto dev_unref;
@@ -286,8 +270,7 @@ static int pl111_amba_remove(struct amba_device *amba_dev)
}
}


/*
/*
 * This variant exist in early versions like the ARM Integrator
 * This early variant lacks the 565 and 444 pixel formats.
 * and this version lacks the 565 and 444 pixel formats.
 */
 */
static const u32 pl110_pixel_formats[] = {
static const u32 pl110_pixel_formats[] = {
	DRM_FORMAT_ABGR8888,
	DRM_FORMAT_ABGR8888,
+65 −19
Original line number Original line Diff line number Diff line
#include <linux/amba/clcd-regs.h>
#include <linux/device.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/regmap.h>
@@ -64,10 +65,8 @@ static const struct of_device_id versatile_clcd_of_match[] = {
#define INTEGRATOR_CLCD_LCDBIASEN	BIT(8)
#define INTEGRATOR_CLCD_LCDBIASEN	BIT(8)
#define INTEGRATOR_CLCD_LCDBIASUP	BIT(9)
#define INTEGRATOR_CLCD_LCDBIASUP	BIT(9)
#define INTEGRATOR_CLCD_LCDBIASDN	BIT(10)
#define INTEGRATOR_CLCD_LCDBIASDN	BIT(10)
/* Bits 11,12,13 controls the LCD type */
/* Bits 11,12,13 controls the LCD or VGA bridge type */
#define INTEGRATOR_CLCD_LCDMUX_MASK	(BIT(11)|BIT(12)|BIT(13))
#define INTEGRATOR_CLCD_LCDMUX_LCD24	BIT(11)
#define INTEGRATOR_CLCD_LCDMUX_LCD24	BIT(11)
#define INTEGRATOR_CLCD_LCDMUX_VGA565	BIT(12)
#define INTEGRATOR_CLCD_LCDMUX_SHARP	(BIT(11)|BIT(12))
#define INTEGRATOR_CLCD_LCDMUX_SHARP	(BIT(11)|BIT(12))
#define INTEGRATOR_CLCD_LCDMUX_VGA555	BIT(13)
#define INTEGRATOR_CLCD_LCDMUX_VGA555	BIT(13)
#define INTEGRATOR_CLCD_LCDMUX_VGA24	(BIT(11)|BIT(12)|BIT(13))
#define INTEGRATOR_CLCD_LCDMUX_VGA24	(BIT(11)|BIT(12)|BIT(13))
@@ -82,16 +81,7 @@ static const struct of_device_id versatile_clcd_of_match[] = {
/* 0 = 24bit VGA, 1 = 18bit VGA */
/* 0 = 24bit VGA, 1 = 18bit VGA */
#define INTEGRATOR_CLCD_LCD_N24BITEN	BIT(19)
#define INTEGRATOR_CLCD_LCD_N24BITEN	BIT(19)


#define INTEGRATOR_CLCD_MASK		(INTEGRATOR_CLCD_LCDBIASEN | \
#define INTEGRATOR_CLCD_MASK		GENMASK(19, 8)
					 INTEGRATOR_CLCD_LCDBIASUP | \
					 INTEGRATOR_CLCD_LCDBIASDN | \
					 INTEGRATOR_CLCD_LCDMUX_MASK | \
					 INTEGRATOR_CLCD_LCD0_EN | \
					 INTEGRATOR_CLCD_LCD1_EN | \
					 INTEGRATOR_CLCD_LCD_STATIC1 | \
					 INTEGRATOR_CLCD_LCD_STATIC2 | \
					 INTEGRATOR_CLCD_LCD_STATIC | \
					 INTEGRATOR_CLCD_LCD_N24BITEN)


static void pl111_integrator_enable(struct drm_device *drm, u32 format)
static void pl111_integrator_enable(struct drm_device *drm, u32 format)
{
{
@@ -106,11 +96,8 @@ static void pl111_integrator_enable(struct drm_device *drm, u32 format)
	switch (format) {
	switch (format) {
	case DRM_FORMAT_XBGR8888:
	case DRM_FORMAT_XBGR8888:
	case DRM_FORMAT_XRGB8888:
	case DRM_FORMAT_XRGB8888:
		break;
		/* 24bit formats */
	case DRM_FORMAT_BGR565:
		val |= INTEGRATOR_CLCD_LCDMUX_VGA24;
	case DRM_FORMAT_RGB565:
		/* truecolor RGB565 */
		val |= INTEGRATOR_CLCD_LCDMUX_VGA565;
		break;
		break;
	case DRM_FORMAT_XBGR1555:
	case DRM_FORMAT_XBGR1555:
	case DRM_FORMAT_XRGB1555:
	case DRM_FORMAT_XRGB1555:
@@ -217,6 +204,55 @@ static void pl111_realview_clcd_enable(struct drm_device *drm, u32 format)
			   SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH);
			   SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH);
}
}


/* PL110 pixel formats for Integrator, vanilla PL110 */
static const u32 pl110_integrator_pixel_formats[] = {
	DRM_FORMAT_ABGR8888,
	DRM_FORMAT_XBGR8888,
	DRM_FORMAT_ARGB8888,
	DRM_FORMAT_XRGB8888,
	DRM_FORMAT_ABGR1555,
	DRM_FORMAT_XBGR1555,
	DRM_FORMAT_ARGB1555,
	DRM_FORMAT_XRGB1555,
};

/* Extended PL110 pixel formats for Integrator and Versatile */
static const u32 pl110_versatile_pixel_formats[] = {
	DRM_FORMAT_ABGR8888,
	DRM_FORMAT_XBGR8888,
	DRM_FORMAT_ARGB8888,
	DRM_FORMAT_XRGB8888,
	DRM_FORMAT_BGR565, /* Uses external PLD */
	DRM_FORMAT_RGB565, /* Uses external PLD */
	DRM_FORMAT_ABGR1555,
	DRM_FORMAT_XBGR1555,
	DRM_FORMAT_ARGB1555,
	DRM_FORMAT_XRGB1555,
};

/*
 * The Integrator variant is a PL110 with a bunch of broken, or not
 * yet implemented features
 */
static const struct pl111_variant_data pl110_integrator = {
	.name = "PL110 Integrator",
	.is_pl110 = true,
	.formats = pl110_integrator_pixel_formats,
	.nformats = ARRAY_SIZE(pl110_integrator_pixel_formats),
};

/*
 * This is the in-between PL110 variant found in the ARM Versatile,
 * supporting RGB565/BGR565
 */
static const struct pl111_variant_data pl110_versatile = {
	.name = "PL110 Versatile",
	.is_pl110 = true,
	.external_bgr = true,
	.formats = pl110_versatile_pixel_formats,
	.nformats = ARRAY_SIZE(pl110_versatile_pixel_formats),
};

int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv)
int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv)
{
{
	const struct of_device_id *clcd_id;
	const struct of_device_id *clcd_id;
@@ -241,14 +277,24 @@ int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv)
	switch (versatile_clcd_type) {
	switch (versatile_clcd_type) {
	case INTEGRATOR_CLCD_CM:
	case INTEGRATOR_CLCD_CM:
		versatile_syscon_map = map;
		versatile_syscon_map = map;
		priv->variant = &pl110_integrator;
		priv->variant_display_enable = pl111_integrator_enable;
		priv->variant_display_enable = pl111_integrator_enable;
		dev_info(dev, "set up callbacks for Integrator PL110\n");
		dev_info(dev, "set up callbacks for Integrator PL110\n");
		break;
		break;
	case VERSATILE_CLCD:
	case VERSATILE_CLCD:
		versatile_syscon_map = map;
		versatile_syscon_map = map;
		/* This can do RGB565 with external PLD */
		priv->variant = &pl110_versatile;
		priv->variant_display_enable = pl111_versatile_enable;
		priv->variant_display_enable = pl111_versatile_enable;
		priv->variant_display_disable = pl111_versatile_disable;
		priv->variant_display_disable = pl111_versatile_disable;
		dev_info(dev, "set up callbacks for Versatile PL110+\n");
		/*
		 * The Versatile has a variant halfway between PL110
		 * and PL111 where these two registers have already been
		 * swapped.
		 */
		priv->ienb = CLCD_PL111_IENB;
		priv->ctrl = CLCD_PL111_CNTL;
		dev_info(dev, "set up callbacks for Versatile PL110\n");
		break;
		break;
	case REALVIEW_CLCD_EB:
	case REALVIEW_CLCD_EB:
	case REALVIEW_CLCD_PB1176:
	case REALVIEW_CLCD_PB1176: