[PATCH 4/7] drm/pl111: Enable PL110 variant

Emil Velikov emil.l.velikov at gmail.com
Fri Sep 1 01:23:10 PDT 2017


On 31 August 2017 at 11:19, Eric Engestrom <eric.engestrom at imgtec.com> wrote:
> On Wednesday, 2017-08-30 20:07:08 +0200, Linus Walleij wrote:
>> We detect and enable the use of the PL110 variant, an earlier
>> incarnation of PL111. The only real difference is that the
>> control and interrupt enable registers have swapped place.
>> The Versatile AB and Versatile PB have a variant inbetween
>> PL110 and PL111, it is PL110 but they have already swapped the
>> two registers so those two need a bit of special handling.
>>
>> Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
>> ---
>>  drivers/gpu/drm/pl111/pl111_display.c | 27 +++--------
>>  drivers/gpu/drm/pl111/pl111_drm.h     | 17 +++++++
>>  drivers/gpu/drm/pl111/pl111_drv.c     | 84 ++++++++++++++++++++++++++++++++++-
>>  3 files changed, 105 insertions(+), 23 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/pl111/pl111_display.c b/drivers/gpu/drm/pl111/pl111_display.c
>> index ef86ef60aed1..6447f36c243a 100644
>> --- a/drivers/gpu/drm/pl111/pl111_display.c
>> +++ b/drivers/gpu/drm/pl111/pl111_display.c
>> @@ -201,7 +201,7 @@ static void pl111_display_enable(struct drm_simple_display_pipe *pipe,
>>               break;
>>       }
>>
>> -     writel(cntl, priv->regs + CLCD_PL111_CNTL);
>> +     writel(cntl, priv->regs + priv->ctrl);
>>
>>       drm_panel_enable(priv->panel);
>>
>> @@ -219,7 +219,7 @@ void pl111_display_disable(struct drm_simple_display_pipe *pipe)
>>       drm_panel_disable(priv->panel);
>>
>>       /* Disable and Power Down */
>> -     writel(0, priv->regs + CLCD_PL111_CNTL);
>> +     writel(0, priv->regs + priv->ctrl);
>>
>>       drm_panel_unprepare(priv->panel);
>>
>> @@ -259,7 +259,7 @@ int pl111_enable_vblank(struct drm_device *drm, unsigned int crtc)
>>  {
>>       struct pl111_drm_dev_private *priv = drm->dev_private;
>>
>> -     writel(CLCD_IRQ_NEXTBASE_UPDATE, priv->regs + CLCD_PL111_IENB);
>> +     writel(CLCD_IRQ_NEXTBASE_UPDATE, priv->regs + priv->ienb);
>>
>>       return 0;
>>  }
>> @@ -268,7 +268,7 @@ void pl111_disable_vblank(struct drm_device *drm, unsigned int crtc)
>>  {
>>       struct pl111_drm_dev_private *priv = drm->dev_private;
>>
>> -     writel(0, priv->regs + CLCD_PL111_IENB);
>> +     writel(0, priv->regs + priv->ienb);
>>  }
>>
>>  static int pl111_display_prepare_fb(struct drm_simple_display_pipe *pipe,
>> @@ -412,22 +412,6 @@ int pl111_display_init(struct drm_device *drm)
>>       struct device_node *endpoint;
>>       u32 tft_r0b0g0[3];
>>       int ret;
>> -     static const u32 formats[] = {
>> -             DRM_FORMAT_ABGR8888,
>> -             DRM_FORMAT_XBGR8888,
>> -             DRM_FORMAT_ARGB8888,
>> -             DRM_FORMAT_XRGB8888,
>> -             DRM_FORMAT_BGR565,
>> -             DRM_FORMAT_RGB565,
>> -             DRM_FORMAT_ABGR1555,
>> -             DRM_FORMAT_XBGR1555,
>> -             DRM_FORMAT_ARGB1555,
>> -             DRM_FORMAT_XRGB1555,
>> -             DRM_FORMAT_ABGR4444,
>> -             DRM_FORMAT_XBGR4444,
>> -             DRM_FORMAT_ARGB4444,
>> -             DRM_FORMAT_XRGB4444,
>> -     };
>>
>>       endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
>>       if (!endpoint)
>> @@ -456,7 +440,8 @@ int pl111_display_init(struct drm_device *drm)
>>
>>       ret = drm_simple_display_pipe_init(drm, &priv->pipe,
>>                                          &pl111_display_funcs,
>> -                                        formats, ARRAY_SIZE(formats),
>> +                                        priv->variant->formats,
>> +                                        priv->variant->nformats,
>>                                          priv->connector);
>>       if (ret)
>>               return ret;
>> diff --git a/drivers/gpu/drm/pl111/pl111_drm.h b/drivers/gpu/drm/pl111/pl111_drm.h
>> index 8804af0f8997..b316a8a0fbc0 100644
>> --- a/drivers/gpu/drm/pl111/pl111_drm.h
>> +++ b/drivers/gpu/drm/pl111/pl111_drm.h
>> @@ -31,6 +31,20 @@
>>
>>  struct drm_minor;
>>
>> +/**
>> + * struct pl111_variant_data - encodes IP differences
>> + * @name: the name of this variant
>> + * @is_pl110: this is the early PL110 variant
>> + * @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;
>> +     const u32 *formats;
>> +     unsigned int nformats;
>> +};
>> +
>>  struct pl111_drm_dev_private {
>>       struct drm_device *drm;
>>
>> @@ -42,6 +56,8 @@ struct pl111_drm_dev_private {
>>       struct drm_fbdev_cma *fbdev;
>>
>>       void *regs;
>> +     u32 ienb;
>> +     u32 ctrl;
>>       /* The pixel clock (a reference to our clock divider off of CLCDCLK). */
>>       struct clk *clk;
>>       /* pl111's internal clock divider. */
>> @@ -50,6 +66,7 @@ struct pl111_drm_dev_private {
>>        * subsystem and pl111_display_enable().
>>        */
>>       spinlock_t tim2_lock;
>> +     struct pl111_variant_data *variant;
>>  };
>>
>>  int pl111_display_init(struct drm_device *dev);
>> diff --git a/drivers/gpu/drm/pl111/pl111_drv.c b/drivers/gpu/drm/pl111/pl111_drv.c
>> index e66cbf202e17..f6863c0fb809 100644
>> --- a/drivers/gpu/drm/pl111/pl111_drv.c
>> +++ b/drivers/gpu/drm/pl111/pl111_drv.c
>> @@ -206,6 +206,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;
>>       struct drm_device *drm;
>>       int ret;
>>
>> @@ -219,6 +220,33 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
>>       amba_set_drvdata(amba_dev, drm);
>>       priv->drm = drm;
>>       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.
>> +      */
>> +     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;
>> +             }
>> +     } else {
>> +             priv->ienb = CLCD_PL111_IENB;
>> +             priv->ctrl = CLCD_PL111_CNTL;
>> +     }
>>
>>       priv->regs = devm_ioremap_resource(dev, &amba_dev->res);
>>       if (IS_ERR(priv->regs)) {
>> @@ -227,10 +255,10 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
>>       }
>>
>>       /* turn off interrupts before requesting the irq */
>> -     writel(0, priv->regs + CLCD_PL111_IENB);
>> +     writel(0, priv->regs + priv->ienb);
>>
>>       ret = devm_request_irq(dev, amba_dev->irq[0], pl111_irq, 0,
>> -                            "pl111", priv);
>> +                            variant->name, priv);
>>       if (ret != 0) {
>>               dev_err(dev, "%s failed irq %d\n", __func__, ret);
>>               return ret;
>> @@ -269,10 +297,62 @@ static int pl111_amba_remove(struct amba_device *amba_dev)
>>       return 0;
>>  }
>>
>> +/*
>> + * This variant exist in early versions like the ARM Integrator
>> + * and this version lacks the 565 and 444 pixel formats.
>> + */
>> +static const u32 pl110_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,
>> +};
>> +
>> +struct pl111_variant_data pl110_variant = {
>
> I think this (and `pl111_variant` below) can be `static const`, right?
>
Static - yes, const - I don't think so.
Struct amba_id::data lacks the constness, so the const qualifier will
get discarded.

In practise everyone considers/uses ::data as const, so that could be
tweaked with separate patch.

-Emil



More information about the linux-arm-kernel mailing list