drm/pl111: Properly detect the ARM PL110 variants
authorLinus Walleij <linus.walleij@linaro.org>
Tue, 6 Feb 2018 09:35:36 +0000 (10:35 +0100)
committerLinus Walleij <linus.walleij@linaro.org>
Wed, 7 Feb 2018 08:08:23 +0000 (09:08 +0100)
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: Eric Anholt <eric@anholt.net>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20180206093540.8147-1-linus.walleij@linaro.org
drivers/gpu/drm/pl111/pl111_drm.h
drivers/gpu/drm/pl111/pl111_drv.c
drivers/gpu/drm/pl111/pl111_versatile.c

index 07fa2cdb364aff68b0fae1444c98a9a5fd439751..bc04b54014a7cc58755feeb933f935a7a54c5054 100644 (file)
@@ -36,12 +36,15 @@ struct drm_minor;
  * struct pl111_variant_data - encodes IP differences
  * @name: the name of this 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
  * @nformats: the length of the array of supported pixel formats
  */
 struct pl111_variant_data {
        const char *name;
        bool is_pl110;
+       bool external_bgr;
        const u32 *formats;
        unsigned int nformats;
 };
index 19e1725c3ef687ae2fa12a8c9ab00a03644fd1f0..ad8dfead2d008408093f044f4d7e3c6b76a643ea 100644 (file)
@@ -193,7 +193,7 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
 {
        struct device *dev = &amba_dev->dev;
        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;
        int ret;
 
@@ -209,27 +209,10 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
        drm->dev_private = priv;
        priv->variant = variant;
 
-       /*
-        * 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.
-        */
+       /* The two variants swap this register */
        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->ctrl = CLCD_PL110_CNTL;
-               }
+               priv->ienb = CLCD_PL110_IENB;
+               priv->ctrl = CLCD_PL110_CNTL;
        } else {
                priv->ienb = CLCD_PL111_IENB;
                priv->ctrl = CLCD_PL111_CNTL;
@@ -241,6 +224,11 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
                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 */
        writel(0, priv->regs + priv->ienb);
 
@@ -251,10 +239,6 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
                return ret;
        }
 
-       ret = pl111_versatile_init(dev, priv);
-       if (ret)
-               goto dev_unref;
-
        ret = pl111_modeset_init(drm);
        if (ret != 0)
                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
- * and this version lacks the 565 and 444 pixel formats.
+ * This early variant lacks the 565 and 444 pixel formats.
  */
 static const u32 pl110_pixel_formats[] = {
        DRM_FORMAT_ABGR8888,
index 97d4af6925a3a3ece50a842339c171b38c9779e5..1fe825139d9b8e25b007ba3ac58db365769a9303 100644 (file)
@@ -1,3 +1,4 @@
+#include <linux/amba/clcd-regs.h>
 #include <linux/device.h>
 #include <linux/of.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_LCDBIASUP      BIT(9)
 #define INTEGRATOR_CLCD_LCDBIASDN      BIT(10)
-/* Bits 11,12,13 controls the LCD type */
-#define INTEGRATOR_CLCD_LCDMUX_MASK    (BIT(11)|BIT(12)|BIT(13))
+/* Bits 11,12,13 controls the LCD or VGA bridge type */
 #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_VGA555  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 */
 #define INTEGRATOR_CLCD_LCD_N24BITEN   BIT(19)
 
-#define INTEGRATOR_CLCD_MASK           (INTEGRATOR_CLCD_LCDBIASEN | \
-                                        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)
+#define INTEGRATOR_CLCD_MASK           GENMASK(19, 8)
 
 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) {
        case DRM_FORMAT_XBGR8888:
        case DRM_FORMAT_XRGB8888:
-               break;
-       case DRM_FORMAT_BGR565:
-       case DRM_FORMAT_RGB565:
-               /* truecolor RGB565 */
-               val |= INTEGRATOR_CLCD_LCDMUX_VGA565;
+               /* 24bit formats */
+               val |= INTEGRATOR_CLCD_LCDMUX_VGA24;
                break;
        case DRM_FORMAT_XBGR1555:
        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);
 }
 
+/* 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)
 {
        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) {
        case INTEGRATOR_CLCD_CM:
                versatile_syscon_map = map;
+               priv->variant = &pl110_integrator;
                priv->variant_display_enable = pl111_integrator_enable;
                dev_info(dev, "set up callbacks for Integrator PL110\n");
                break;
        case VERSATILE_CLCD:
                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_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;
        case REALVIEW_CLCD_EB:
        case REALVIEW_CLCD_PB1176: