[RFC 15/16] drm/armada: add mmp2 support

Lubomir Rintel lkundrak at v3.sk
Tue Dec 18 15:37:41 UTC 2018


This pretty much boils down to setting the LCD_CFG_SCLK_DIV register, and
is tailored to the OLPC XO-1.75. I have no idea what are the meanings of
most bits there, so I'm just making sure it ends up being 0x40001102.

This means that the selection of the source clock is hardwired. Apparently
the bit 30 selects the AXI bus clock as base clock for the pixel clock.
It is not known to me what other options are there.

Signed-off-by: Lubomir Rintel <lkundrak at v3.sk>

---
Notes; perhaps James or someone else with a datasheet could help me with
this.

I'm somewhat confused about the clock selection. The firmware contains
this line:

  h# 00000700 value pmua-disp-clk-sel  \ PLL1 / 7 -> 113.86 MHz

However, the Linux clock driver seems to consider the value of 7 to
configure the divisor to 8, so the resulting clock would end up being
100 MHz. Also, the clk-of-mmp2 driver suggests PLL1 outputs 800 MHz,
dividing that by 7 would end up being 114.29 MHz, not 113.86 MHz.

If the same logic was used here as Armada 510 driver uses, we'll end up
with the divisor of 1 in LCD_CFG_SCLK_DIV and disp0_div divisor of 16.
Would that be good also? (Do perhaps any of the bits in LCD_CFG_SCLK_DIV
allow for a fractional divisor, allowing us to get the clock we need
more precisely?)

The pxa168fb driver as used on the stock OLPC software just avoids
touching the register, preserving the value set from the firmware.
---
 drivers/gpu/drm/armada/Makefile      |  1 +
 drivers/gpu/drm/armada/armada_610.c  | 50 ++++++++++++++++++++++++++++
 drivers/gpu/drm/armada/armada_crtc.c |  4 +++
 drivers/gpu/drm/armada/armada_drm.h  |  1 +
 drivers/gpu/drm/armada/armada_drv.c  |  1 +
 drivers/gpu/drm/armada/armada_rmem.c |  4 ++-
 6 files changed, 60 insertions(+), 1 deletion(-)
 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 d34843e121c7..ac299fe35173 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..e86b9fed9d2f
--- /dev/null
+++ b/drivers/gpu/drm/armada/armada_610.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 Russell King
+ * Copyright (C) 2018 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"
+
+/*
+ * 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->axiclk;
+	uint32_t rate, ref, div;
+
+	if (!clk)
+		return -EINVAL;
+
+	rate = mode->clock * 1000;
+	ref = clk_get_rate(clk);
+	div = DIV_ROUND_UP(ref, rate);
+
+	if (div < 2)
+		return -EINVAL;
+
+	if (sclk) {
+		*sclk = 0x00001100; /* No idea */
+		*sclk |= (0x1 << 30); /* SCLK_SOURCE_SELECT = AXI bus clk */
+		*sclk |= div;
+	}
+
+	return 0;
+}
+
+const struct armada_variant armada610_ops = {
+	.compute_clock = armada610_crtc_compute_clock,
+};
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index 973c377975a1..9d450669faea 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -915,6 +915,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_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index deef34153c56..fed590e0916f 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -302,6 +302,7 @@ MODULE_DEVICE_TABLE(platform, armada_drm_platform_ids);
 
 static const struct of_device_id armada_drm_dt_ids[] = {
 	{ .compatible = "marvell,dove-display-subsystem", },
+	{ .compatible = "marvell,mmp2-display-subsystem", },
 	{ /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, armada_drm_dt_ids);
diff --git a/drivers/gpu/drm/armada/armada_rmem.c b/drivers/gpu/drm/armada/armada_rmem.c
index 36bb20e426b6..45f8b2eff822 100644
--- a/drivers/gpu/drm/armada/armada_rmem.c
+++ b/drivers/gpu/drm/armada/armada_rmem.c
@@ -45,5 +45,7 @@ static int __init armada_rmem_init(struct reserved_mem *rmem)
 	return 0;
 }
 
-RESERVEDMEM_OF_DECLARE(armada_rmem, "marvell,dove-framebuffer",
+RESERVEDMEM_OF_DECLARE(armada_dove_rmem, "marvell,dove-framebuffer",
+			armada_rmem_init);
+RESERVEDMEM_OF_DECLARE(armada_mmp2_rmem, "marvell,mmp2-framebuffer",
 			armada_rmem_init);
-- 
2.19.1



More information about the dri-devel mailing list