From 3e6c7accdc2f89908389df126f3fb7294eb9be45 Mon Sep 17 00:00:00 2001
From: Joel Bodenmann <joel@seriouslyembedded.com>
Date: Sun, 12 Jul 2015 02:54:17 +0200
Subject: Adding DMA2D to STM32F429i-Discovery

---
 .../gdisp_lld_STM32F429iDiscovery.c                | 95 ++++++++++++++++++++++
 .../gdisp/STM32F429iDiscovery/gdisp_lld_config.h   | 14 ++++
 drivers/gdisp/STM32F429iDiscovery/stm32_dma2d.h    | 18 ++++
 3 files changed, 127 insertions(+)
 create mode 100644 drivers/gdisp/STM32F429iDiscovery/stm32_dma2d.h

diff --git a/drivers/gdisp/STM32F429iDiscovery/gdisp_lld_STM32F429iDiscovery.c b/drivers/gdisp/STM32F429iDiscovery/gdisp_lld_STM32F429iDiscovery.c
index a42fe990..204097d3 100644
--- a/drivers/gdisp/STM32F429iDiscovery/gdisp_lld_STM32F429iDiscovery.c
+++ b/drivers/gdisp/STM32F429iDiscovery/gdisp_lld_STM32F429iDiscovery.c
@@ -18,12 +18,20 @@
 	#undef GDISP_SCREEN_WIDTH
 #endif
 
+#ifndef LTDC_USE_DMA2D
+ 	#define LTDC_USE_DMA2D FALSE
+#endif
+
 #define GDISP_DRIVER_VMT			GDISPVMT_STM32F429iDiscovery
 #include "drivers/gdisp/STM32F429iDiscovery/gdisp_lld_config.h"
 #include "src/gdisp/gdisp_driver.h"
 
 #include "stm32_ltdc.h"
 
+#if LTDC_USE_DMA2D
+ 	#include "stm32_dma2d.h"
+#endif
+
 typedef struct ltdcLayerConfig {
 	// frame
 	LLDCOLOR_TYPE	*frame;			// Frame buffer address
@@ -287,6 +295,11 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	// Initialise the LTDC controller
 	LTDC_Init();
 
+	// Initialise DMA2D
+	#if LTDC_USE_DMA2D
+		dma2d_init();
+	#endif
+
 	// Initialise DMA2D
 	//dma2dStart(&DMA2DD1, &dma2d_cfg);
 	//dma2d_test();
@@ -422,4 +435,86 @@ LLDSPEC	color_t gdisp_lld_get_pixel_color(GDisplay *g) {
 	}
 #endif
 
+#if LTDC_USE_DMA2D
+	static void dma2d_init(void)
+	{
+		// Enable DMA2D clock (DMA2DEN = 1)
+		RCC->AHB1ENR |= RCC_AHB1ENR_DMA2DEN;
+	
+		// Output color format
+		#if GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB565
+			DMA2D->OPFCCR = OPFCCR_RGB565;
+		#elif GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB888
+			DMA2D->OPFCCR = OPFCCR_OPFCCR_RGB888;
+		#endif
+	
+		// Foreground color format
+		#if GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB565
+			DMA2D->FGPFCCR = FGPFCCR_CM_RGB565;
+		#elif GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB888
+			DMA2D->FGPFCCR = FGPFCCR_CM_RGB888;
+		#endif
+	}
+
+	// Uses p.x,p.y  p.cx,p.cy  p.color
+	LLDSPEC void gdisp_lld_fill_area(GDisplay* g)
+	{
+		LLDCOLOR_TYPE c;
+	
+		// Wait until DMA2D is ready
+		while (1) {
+			if (!(DMA2D->CR & DMA2D_CR_START)) {
+				break;
+			}
+		}
+	
+		c = gdispColor2Native(g->p.color);
+	
+		// Output color register
+		DMA2D->OCOLR = (uint32_t)c;
+	
+		// Output memory address register
+		DMA2D->OMAR = g->p.y * g->g.Width * LTDC_PIXELBYTES + g->p.x * LTDC_PIXELBYTES + (uint32_t)driverCfg.bglayer.frame;
+
+		// Output offset register (in pixels)
+		DMA2D->OOR = g->g.Width - g->p.cx;
+	
+		// PL (pixel per lines to be transferred); NL (number of lines)
+		DMA2D->NLR = (g->p.cx << 16) | (g->p.cy);
+
+		// Set MODE to R2M and Start the process
+		DMA2D->CR = DMA2D_CR_MODE_R2M | DMA2D_CR_START;
+	}
+
+	// Uses p.x,p.y  p.cx,p.cy  p.x1,p.y1 (=srcx,srcy)  p.x2 (=srccx), p.ptr (=buffer)
+	LLDSPEC void gdisp_lld_blit_area(GDisplay* g)
+	{
+		// Wait until DMA2D is ready
+		while (1) {
+			if (!(DMA2D->CR & DMA2D_CR_START)) {
+				break;
+			}
+		}
+
+		// Foreground memory address register
+		DMA2D->FGMAR = g->p.y1 * g->p.x2 * LTDC_PIXELBYTES + g->p.x1 * LTDC_PIXELBYTES + (uint32_t)g->p.ptr;
+
+		// Foreground offset register (expressed in pixels)
+		DMA2D->FGOR = g->p.x2 - g->p.cx;
+	
+		// Output memory address register
+		DMA2D->OMAR = g->p.y * g->g.Width * LTDC_PIXELBYTES + g->p.x * LTDC_PIXELBYTES + (uint32_t)driverCfg.bglayer.frame;
+
+		// Output offset register (expressed in pixels)
+		DMA2D->OOR = g->g.Width - g->p.cx;
+	
+		// PL (pixel per lines to be transferred); NL (number of lines)
+		DMA2D->NLR = (g->p.cx << 16) | (g->p.cy);
+
+		// Set MODE to M2M and Start the process
+		DMA2D->CR = DMA2D_CR_MODE_M2M | DMA2D_CR_START;
+	}
+
+#endif /* LTDC_USE_DMA2D */
+
 #endif /* GFX_USE_GDISP */
diff --git a/drivers/gdisp/STM32F429iDiscovery/gdisp_lld_config.h b/drivers/gdisp/STM32F429iDiscovery/gdisp_lld_config.h
index 29e016ce..c661f67c 100644
--- a/drivers/gdisp/STM32F429iDiscovery/gdisp_lld_config.h
+++ b/drivers/gdisp/STM32F429iDiscovery/gdisp_lld_config.h
@@ -14,11 +14,25 @@
 /* Driver hardware support.                                                  */
 /*===========================================================================*/
 
+#define	LTDC_USE_DMA2D					TRUE
 #define GDISP_HARDWARE_DRAWPIXEL		TRUE
 #define GDISP_HARDWARE_PIXELREAD		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
 #define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_RGB565
 
+
+/*===========================================================================*/
+/* Don't change stuff below this line. Please.                               */
+/*===========================================================================*/
+
+#if LTDC_USE_DMA2D
+ 	#define GDISP_HARDWARE_FILLS		TRUE
+ 	#define GDISP_HARDWARE_BITFILLS		TRUE
+#else
+ 	#define GDISP_HARDWARE_FILLS		FALSE
+ 	#define GDISP_HARDWARE_BITFILLS		FALSE
+#endif /* GDISP_USE_DMA2D */
+
 #endif	/* GFX_USE_GDISP */
 
 #endif	/* _GDISP_LLD_CONFIG_H */
diff --git a/drivers/gdisp/STM32F429iDiscovery/stm32_dma2d.h b/drivers/gdisp/STM32F429iDiscovery/stm32_dma2d.h
new file mode 100644
index 00000000..d3374d05
--- /dev/null
+++ b/drivers/gdisp/STM32F429iDiscovery/stm32_dma2d.h
@@ -0,0 +1,18 @@
+#ifndef _STM32_DMA2D_H
+#define _STM32_DMA2D_H
+
+#define OPFCCR_ARGB8888		0x00
+#define OPFCCR_RGB888		0x01
+#define OPFCCR_RGB565		0x02
+#define OPFCCR_ARGB1555		0x03
+#define OPFCCR_ARGB4444		0x04
+
+#define FGPFCCR_CM_RGB888	0x01
+#define FGPFCCR_CM_RGB565	0x02
+
+#define DMA2D_CR_MODE_R2M	((uint32_t)0x00030000)	/* Register-to-memory mode */
+#define DMA2D_CR_MODE_M2M	((uint32_t)0x00000000)	/* Register-to-memory mode */
+
+static void dma2d_init(void);
+
+#endif /* _STM32_DMA2D_H */
-- 
cgit v1.2.3