diff mbox series

drm/armada: add mmp2 support

Message ID 20190121060349.549797-1-lkundrak@v3.sk (mailing list archive)
State New, archived
Headers show
Series drm/armada: add mmp2 support | expand

Commit Message

Lubomir Rintel Jan. 21, 2019, 6:03 a.m. UTC
Heavily based on the Armada 510 (Dove) support. Like with 510 support, this
also just supports a single source clock -- the "Display 1" clock as
generated by the APMU. This one was chosen because the OLPC XO 1.75 laptop
uses it for its internal panel.

If anyone uses this to drive a MIPI or HDMI encoder, they may want to
extend this to choose a different source for the pixel clock -- it should
be a reasonably straightforward thing to do.

The data sheet is not available, but James Cameron of OLPC kindly
provided some details about the LCD_SCLK_DIV register.

Link: https://lists.freedesktop.org/archives/dri-devel/2018-December/201021.html
Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
---
 drivers/gpu/drm/armada/Makefile      |  1 +
 drivers/gpu/drm/armada/armada_610.c  | 93 ++++++++++++++++++++++++++++
 drivers/gpu/drm/armada/armada_crtc.c |  4 ++
 drivers/gpu/drm/armada/armada_drm.h  |  1 +
 drivers/gpu/drm/armada/armada_hw.h   | 10 +++
 5 files changed, 109 insertions(+)
 create mode 100644 drivers/gpu/drm/armada/armada_610.c

Comments

Russell King (Oracle) Jan. 22, 2019, 7:10 p.m. UTC | #1
On Mon, Jan 21, 2019 at 07:03:49AM +0100, Lubomir Rintel wrote:
> Heavily based on the Armada 510 (Dove) support. Like with 510 support, this
> also just supports a single source clock -- the "Display 1" clock as
> generated by the APMU. This one was chosen because the OLPC XO 1.75 laptop
> uses it for its internal panel.
> 
> If anyone uses this to drive a MIPI or HDMI encoder, they may want to
> extend this to choose a different source for the pixel clock -- it should
> be a reasonably straightforward thing to do.
> 
> The data sheet is not available, but James Cameron of OLPC kindly
> provided some details about the LCD_SCLK_DIV register.
> 
> Link: https://lists.freedesktop.org/archives/dri-devel/2018-December/201021.html
> Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
> ---
>  drivers/gpu/drm/armada/Makefile      |  1 +
>  drivers/gpu/drm/armada/armada_610.c  | 93 ++++++++++++++++++++++++++++
>  drivers/gpu/drm/armada/armada_crtc.c |  4 ++
>  drivers/gpu/drm/armada/armada_drm.h  |  1 +
>  drivers/gpu/drm/armada/armada_hw.h   | 10 +++
>  5 files changed, 109 insertions(+)
>  create mode 100644 drivers/gpu/drm/armada/armada_610.c
> 
> diff --git a/drivers/gpu/drm/armada/Makefile b/drivers/gpu/drm/armada/Makefile
> index 9bc3c3213724..5bbf86324cda 100644
> --- a/drivers/gpu/drm/armada/Makefile
> +++ b/drivers/gpu/drm/armada/Makefile
> @@ -2,6 +2,7 @@
>  armada-y	:= armada_crtc.o armada_drv.o armada_fb.o armada_fbdev.o \
>  		   armada_gem.o armada_overlay.o armada_plane.o armada_trace.o
>  armada-y	+= armada_510.o
> +armada-y	+= armada_610.o
>  armada-$(CONFIG_DEBUG_FS) += armada_debugfs.o
>  
>  obj-$(CONFIG_DRM_ARMADA) := armada.o
> diff --git a/drivers/gpu/drm/armada/armada_610.c b/drivers/gpu/drm/armada/armada_610.c
> new file mode 100644
> index 000000000000..278b204038ea
> --- /dev/null
> +++ b/drivers/gpu/drm/armada/armada_610.c
> @@ -0,0 +1,93 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2012 Russell King
> + * Copyright (C) 2018,2019 Lubomir Rintel
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Armada MMP2 variant support
> + */
> +#include <linux/clk.h>
> +#include <drm/drm_modes.h>
> +#include <drm/drm_crtc.h>
> +#include "armada_crtc.h"
> +#include "armada_drm.h"
> +#include "armada_hw.h"
> +
> +static int armada610_crtc_init(struct armada_crtc *dcrtc, struct device *dev)
> +{
> +	struct clk *clk;
> +
> +	clk = devm_clk_get(dev, "disp0");
> +	if (IS_ERR(clk))
> +		return PTR_ERR(clk) == -ENOENT ? -EPROBE_DEFER : PTR_ERR(clk);
> +
> +	dcrtc->extclk[0] = clk;

I've been reworking the clocking support for Armada, you can find the
current code in my git tree's drm-armada-devel branch (as mentioned
in MAINTAINERS).  You'll need to update to that before I can apply
this.

The clocks are named in Dove's TRM as:

   0 = AXIbus: Select AXI bus clock as pixel clock source.
   1 = EXT_REF_CLK0: LCD_EXT_REF_CLK[0]
   2 = PLLDivider: Select PLL divider input clock as pixel clock source.
   3 = EXT_REF_CLK1: LCD_EXT_REF_CLK[1]

So I chose to use these neumonics in the Armada 510.  Please can we
keep to naming the clock inputs as per documented names please?

Also, have a look at how Armada 510 gets its clocks from DT - note
that the array they're placed in is ordered by priority (iow, if we
have an external clock, we use that in preference to the more
restricted axibus and plldivider clocks.)

Thanks.
Lubomir Rintel Jan. 25, 2019, 4:41 p.m. UTC | #2
On Tue, 2019-01-22 at 19:10 +0000, Russell King - ARM Linux admin
wrote:
> On Mon, Jan 21, 2019 at 07:03:49AM +0100, Lubomir Rintel wrote:
> > Heavily based on the Armada 510 (Dove) support. Like with 510 support, this
> > also just supports a single source clock -- the "Display 1" clock as
> > generated by the APMU. This one was chosen because the OLPC XO 1.75 laptop
> > uses it for its internal panel.
> > 
> > If anyone uses this to drive a MIPI or HDMI encoder, they may want to
> > extend this to choose a different source for the pixel clock -- it should
> > be a reasonably straightforward thing to do.
> > 
> > The data sheet is not available, but James Cameron of OLPC kindly
> > provided some details about the LCD_SCLK_DIV register.
> > 
> > Link: https://lists.freedesktop.org/archives/dri-devel/2018-December/201021.html
> > Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
> > ---
> >  drivers/gpu/drm/armada/Makefile      |  1 +
> >  drivers/gpu/drm/armada/armada_610.c  | 93 ++++++++++++++++++++++++++++
> >  drivers/gpu/drm/armada/armada_crtc.c |  4 ++
> >  drivers/gpu/drm/armada/armada_drm.h  |  1 +
> >  drivers/gpu/drm/armada/armada_hw.h   | 10 +++
> >  5 files changed, 109 insertions(+)
> >  create mode 100644 drivers/gpu/drm/armada/armada_610.c
> > 
> > diff --git a/drivers/gpu/drm/armada/Makefile b/drivers/gpu/drm/armada/Makefile
> > index 9bc3c3213724..5bbf86324cda 100644
> > --- a/drivers/gpu/drm/armada/Makefile
> > +++ b/drivers/gpu/drm/armada/Makefile
> > @@ -2,6 +2,7 @@
> >  armada-y	:= armada_crtc.o armada_drv.o armada_fb.o armada_fbdev.o \
> >  		   armada_gem.o armada_overlay.o armada_plane.o armada_trace.o
> >  armada-y	+= armada_510.o
> > +armada-y	+= armada_610.o
> >  armada-$(CONFIG_DEBUG_FS) += armada_debugfs.o
> >  
> >  obj-$(CONFIG_DRM_ARMADA) := armada.o
> > diff --git a/drivers/gpu/drm/armada/armada_610.c b/drivers/gpu/drm/armada/armada_610.c
> > new file mode 100644
> > index 000000000000..278b204038ea
> > --- /dev/null
> > +++ b/drivers/gpu/drm/armada/armada_610.c
> > @@ -0,0 +1,93 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2012 Russell King
> > + * Copyright (C) 2018,2019 Lubomir Rintel
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + *
> > + * Armada MMP2 variant support
> > + */
> > +#include <linux/clk.h>
> > +#include <drm/drm_modes.h>
> > +#include <drm/drm_crtc.h>
> > +#include "armada_crtc.h"
> > +#include "armada_drm.h"
> > +#include "armada_hw.h"
> > +
> > +static int armada610_crtc_init(struct armada_crtc *dcrtc, struct device *dev)
> > +{
> > +	struct clk *clk;
> > +
> > +	clk = devm_clk_get(dev, "disp0");
> > +	if (IS_ERR(clk))
> > +		return PTR_ERR(clk) == -ENOENT ? -EPROBE_DEFER : PTR_ERR(clk);
> > +
> > +	dcrtc->extclk[0] = clk;
> 
> I've been reworking the clocking support for Armada, you can find the
> current code in my git tree's drm-armada-devel branch (as mentioned
> in MAINTAINERS).  You'll need to update to that before I can apply
> this.
> 
> The clocks are named in Dove's TRM as:
> 
>    0 = AXIbus: Select AXI bus clock as pixel clock source.
>    1 = EXT_REF_CLK0: LCD_EXT_REF_CLK[0]
>    2 = PLLDivider: Select PLL divider input clock as pixel clock source.
>    3 = EXT_REF_CLK1: LCD_EXT_REF_CLK[1]

What we know (from [1]) about MMP2 clock sources is:

0 AXI
1 LCD Display 1
2 LCD Display 2
3 HDMI PLL

[1] 
https://lists.freedesktop.org/archives/dri-devel/2018-December/201021.html

> So I chose to use these neumonics in the Armada 510.  Please can we
> keep to naming the clock inputs as per documented names please?

Are you suggesting that clocks that are available on MMP2 are
essentially the same as on 510? Like this?

0 AXI -- axiclk
1 LCD Display 1 -- ext_ref_clk0
2 LCD Display 2 --
ext_ref_clk1
3 HDMI PLL -- plldivider

If that is the case, then I'm happy to take your word on it. I had to
guess.

Why I guessed differently was because the clock numbers in
the LCD_SCLK_DIV register don't seem to match and I thought the
"external" clock sources on 510 are external to the SoC (while they two
"LCD Display" clocks on MMP2 are generated by the PMU).

> Also, have a look at how Armada 510 gets its clocks from DT - note
> that the array they're placed in is ordered by priority (iow, if we
> have an external clock, we use that in preference to the more
> restricted axibus and plldivider clocks.)

Okay. I'll follow up with an updated patch over the course of the next
week.

> 
> Thanks.

Thank you
Lubo
diff mbox series

Patch

diff --git a/drivers/gpu/drm/armada/Makefile b/drivers/gpu/drm/armada/Makefile
index 9bc3c3213724..5bbf86324cda 100644
--- a/drivers/gpu/drm/armada/Makefile
+++ b/drivers/gpu/drm/armada/Makefile
@@ -2,6 +2,7 @@ 
 armada-y	:= armada_crtc.o armada_drv.o armada_fb.o armada_fbdev.o \
 		   armada_gem.o armada_overlay.o armada_plane.o armada_trace.o
 armada-y	+= armada_510.o
+armada-y	+= armada_610.o
 armada-$(CONFIG_DEBUG_FS) += armada_debugfs.o
 
 obj-$(CONFIG_DRM_ARMADA) := armada.o
diff --git a/drivers/gpu/drm/armada/armada_610.c b/drivers/gpu/drm/armada/armada_610.c
new file mode 100644
index 000000000000..278b204038ea
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_610.c
@@ -0,0 +1,93 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2012 Russell King
+ * Copyright (C) 2018,2019 Lubomir Rintel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Armada MMP2 variant support
+ */
+#include <linux/clk.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_crtc.h>
+#include "armada_crtc.h"
+#include "armada_drm.h"
+#include "armada_hw.h"
+
+static int armada610_crtc_init(struct armada_crtc *dcrtc, struct device *dev)
+{
+	struct clk *clk;
+
+	clk = devm_clk_get(dev, "disp0");
+	if (IS_ERR(clk))
+		return PTR_ERR(clk) == -ENOENT ? -EPROBE_DEFER : PTR_ERR(clk);
+
+	dcrtc->extclk[0] = clk;
+
+	return 0;
+}
+
+/*
+ * This gets called with sclk = NULL to test whether the mode is
+ * supportable, and again with sclk != NULL to set the clocks up for
+ * that.  The former can return an error, but the latter is expected
+ * not to.
+ */
+static int armada610_crtc_compute_clock(struct armada_crtc *dcrtc,
+	const struct drm_display_mode *mode, uint32_t *sclk)
+{
+	struct clk *clk = dcrtc->extclk[0];
+	uint32_t ret, rate, ref, div;
+
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	rate = mode->clock * 1000;
+	ref = clk_get_rate(clk);
+	div = DIV_ROUND_UP(ref, rate);
+
+	if (div < 2)
+		return -EINVAL;
+
+	if (dcrtc->clk != clk) {
+		ret = clk_prepare_enable(clk);
+		if (ret)
+			return ret;
+		dcrtc->clk = clk;
+	}
+
+	if (sclk) {
+		*sclk = 0x00001000; /* No idea */
+		*sclk |= 1 << 8; /* MIPI clock bypass */
+		*sclk |= SCLK_610_DISP0;
+		*sclk |= div;
+	}
+
+	return 0;
+}
+
+static void armada610_crtc_disable(struct armada_crtc *dcrtc)
+{
+	if (!IS_ERR(dcrtc->clk)) {
+		clk_disable_unprepare(dcrtc->clk);
+		dcrtc->clk = ERR_PTR(-EINVAL);
+	}
+}
+
+static void armada610_crtc_enable(struct armada_crtc *dcrtc,
+	const struct drm_display_mode *mode)
+{
+	if (IS_ERR(dcrtc->clk)) {
+		dcrtc->clk = dcrtc->extclk[0];
+		WARN_ON(clk_prepare_enable(dcrtc->clk));
+	}
+}
+
+const struct armada_variant armada610_ops = {
+	.init = armada610_crtc_init,
+	.compute_clock = armada610_crtc_compute_clock,
+	.disable = armada610_crtc_disable,
+	.enable = armada610_crtc_enable,
+};
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index da9360688b55..927be8898eb7 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -884,6 +884,10 @@  static const struct of_device_id armada_lcd_of_match[] = {
 		.compatible	= "marvell,dove-lcd",
 		.data		= &armada510_ops,
 	},
+	{
+		.compatible	= "marvell,mmp2-lcd",
+		.data		= &armada610_ops,
+	},
 	{}
 };
 MODULE_DEVICE_TABLE(of, armada_lcd_of_match);
diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h
index f09083ff15d3..7cbcf33d0304 100644
--- a/drivers/gpu/drm/armada/armada_drm.h
+++ b/drivers/gpu/drm/armada/armada_drm.h
@@ -52,6 +52,7 @@  struct armada_variant {
 
 /* Variant ops */
 extern const struct armada_variant armada510_ops;
+extern const struct armada_variant armada610_ops;
 
 struct armada_private {
 	struct drm_device	drm;
diff --git a/drivers/gpu/drm/armada/armada_hw.h b/drivers/gpu/drm/armada/armada_hw.h
index 277580b36758..df2ff77b9c07 100644
--- a/drivers/gpu/drm/armada/armada_hw.h
+++ b/drivers/gpu/drm/armada/armada_hw.h
@@ -205,6 +205,16 @@  enum {
 	SCLK_510_FRAC_DIV_MASK	= 0xfff << 16,
 	SCLK_510_INT_DIV_MASK	= 0xffff << 0,
 
+	/* Armada 610 */
+	SCLK_610_AXI		= 0x0 << 30,
+	SCLK_610_DISP0		= 0x1 << 30,	/* LCD Display 1 */
+	SCLK_610_DISP1		= 0x2 << 30,	/* LCD Display 2 */
+	SCLK_610_PLL		= 0x3 << 30,	/* HDMI PLL clock */
+	SCLK_610_PANEL_CLK_DIS	= 0x1 << 28,	/* 1 = panel clock disabled */
+	SCLK_610_FRAC_DIV_MASK	= 0xfff << 16,
+	SCLK_610_MIPI_DIV_MASK	= 0xf << 8,	/* 0 = off, 1 = bypass, ... */
+	SCLK_610_INT_DIV_MASK	= 0xff << 0,
+
 	/* Armada 16x */
 	SCLK_16X_AHB		= 0x0 << 28,
 	SCLK_16X_PCLK		= 0x1 << 28,